summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /dom/canvas/test/webgl-conf/checkout
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/00_test_list.txt7
-rw-r--r--dom/canvas/test/webgl-conf/checkout/CONFORMANCE_RULES.txt127
-rw-r--r--dom/canvas/test/webgl-conf/checkout/README.md94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/AUTHORS19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/CONTRIBUTING48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/LICENSE176
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/README-Khronos.txt20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/README.md9
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/closurebuilder.py287
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depstree.py189
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depswriter.py204
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/jscompiler.py135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/source.py127
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/treescan.py78
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/calcdeps.py590
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/scopify.py221
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/base.js2496
-rw-r--r--dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/deps.js1465
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/00_test_list.txt19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html191
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html131
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html190
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html171
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-bind-test.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-and-buffer-sub-data.html203
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-array-buffer-delete.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-uninitialized.html104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/element-array-buffer-delete-recreate.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-copies-indices.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-crash-with-buffer-sub-data.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-large-buffer.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-verifies-too-many-indices.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-with-resized-buffer.html107
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation.html119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/buffers/vertex-buffer-updated-after-draw.html94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/00_test_list.txt19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-offscreen-test.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-preserve-test.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-test.html195
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-zero-size.html43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-static-webgl-to-multiple-canvas-test.html75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-webgl-to-canvas-test.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-hd-dpi-test.html204
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-static-canvas-test.html116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-test.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-affected-by-to-data-url.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-unaffected-on-resize.html85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/rapid-resizing.html171
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/render-after-resize-test.html142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/texture-bindings-unaffected-on-resize.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-after-composite.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-test.html142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/viewport-unchanged-upon-resize.html92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/canvas/webgl-to-2d-canvas.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/00_test_list.txt21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/constants-and-properties.html546
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer-antialias.html143
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-attributes-alpha-depth-stencil-antialias.html281
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation-and-destruction.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-eviction-with-garbage-collection.html57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-hidden-alpha.html166
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html287
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost.html379
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-no-alpha-fbo-with-alpha.html77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-upon-reload.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-with-workers.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-size-change.html92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/context-type-test.html53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/deleted-object-behavior.html237
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/incorrect-context-object-behaviour.html165
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/methods.html178
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/premultiplyalpha-test.html251
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-child-with-worker.html55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-upon-reload-child.html54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-worker.js4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/user-defined-properties-on-context.html49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/context/zero-sized-canvas.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/00_test_list.txt46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays-out-of-bounds.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays.html723
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-blend-minmax.html225
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-color-buffer-half-float.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-disjoint-timer-query.html312
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-float-blend.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-frag-depth.html289
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-sRGB.html468
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-shader-texture-lod.html341
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-bptc.html159
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-rgtc.html162
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-filter-anisotropic.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/get-extension.html99
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/khr-parallel-shader-compile.html220
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-element-index-uint.html428
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-fbo-render-mipmap.html92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-standard-derivatives.html444
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-linear.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-canvas.html34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image-data.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image.html34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-video.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float.html426
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-linear.html46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-canvas.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image-data.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-video.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float.html474
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object-bufferData.html194
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object.html780
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/s3tc-and-rgtc.html1066
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-astc.html2524
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc.html126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc1.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-pvrtc.html371
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-s3tc-srgb.html912
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-size-limit.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-renderer-info.html104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-shaders.html144
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-depth-texture.html377
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-broadcast-return.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-framebuffer-unsupported.html126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-max-draw-buffers.html118
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers.html812
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-multi-draw.html1064
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-webcodecs-video-frame.html211
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/00_test_list.txt12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/00_test_list.txt52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/README.md18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-ambiguous-function-call.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-constructor-invalid-parameters.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-d3d11-compiler-error.html96
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-dx-variable-bug.html96
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/array-of-struct-with-int-first-position.html141
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/bool-type-cast-bug-int-float.html312
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/character-set.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compare-loop-index-to-uniform.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/complex-glsl-does-not-crash.html191
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compound-assignment-type-combination.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-in-loop.html142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-optimization.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-texture-fetch.html130
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/constant-precision-qualifier.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/essl3-shaders-with-webgl1.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floor-div-cos-should-not-truncate.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floored-division-accuracy.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/fragcoord-linking-bug.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/gl-fragcoord-multisampling-bug.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/global-invariant-does-not-leak-across-shaders.html77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/if-return-and-elseif.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/init-array-with-loop.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/invariant-does-not-leak-across-shaders.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/logic-inside-block-without-braces.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/long-expressions-should-not-crash.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/loop-if-loop-gradient.html75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/modulo-arithmetic-accuracy.html68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/multiplication-assignment.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-functions-should-not-crash.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-loops-with-break-and-continue.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-sequence-operator.html47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-of-small-constant-in-user-defined-function.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-with-constant-exponent-should-not-crash.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-crash.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-loop-with-continue-crash.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-struct-function-arg.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-using-loop-index.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-struct-function-arg.html113
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sequence-operator-evaluation-order.html116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sketchfab-lighting-shader-crash.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-constructor-highp-bug.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-with-single-member-constructor.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/temp-expressions-should-not-crash.html100
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/unary-minus-operator-float-bug.html49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/undefined-index-should-not-crash.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/uniforms-should-not-lose-values.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/varying-arrays-should-not-be-reversed.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-matrix-constructor-scalarization.html181
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html99
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/00_test_list.txt14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec2.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec3.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec2.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec3.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat2.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat3.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-corner-cases.html195
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-index.html53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec2.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec3.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/00_test_list.txt36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-abs.html45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-acos.html95
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-asin.html95
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan-xy.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan.html95
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-ceil.html53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-float.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-gentype.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cos.html99
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cross.html53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-distance.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-dot.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-faceforward.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-floor.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-fract.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-length.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-lessThan.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-float.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-gentype.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-float.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-gentype.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-float.html54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-gentype.html54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-float.html53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-gentype.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-normalize.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-reflect.html61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-refract.html70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sign.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sin.html96
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-float.html97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-gentype.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-float.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-gentype.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/00_test_list.txt65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_int_to_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/construct_struct.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_int_float.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec2_vec2.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec3_vec3.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec4_vec4.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than_equal.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than_equal.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_int_float.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec2_vec2.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec3_vec3.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec4_vec4.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/00_test_list.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/float_literal.vert.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/literal_precision.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/overflow_leak.vert.html61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/00_test_list.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat3-construction.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat4-to-mat3.html70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/matrix-compound-multiply.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/00_test_list.txt126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/attrib-location-length-limits.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/boolean_precision.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/const-variable-initialization.html244
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/embedded-struct-definitions-forbidden.html41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty-declaration.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty_main.vert.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/expression-list-in-declarator-initializer.html68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/fragcolor-fragdata-invariant.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/gl_position_unset.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/global-variable-init.html323
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html132
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-function-nodes.html134
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-vertex-branch.html128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/include.vs4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/large-loop-compile.html172
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/local-variable-shadowing-outer-function.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii-comments.vert.html54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii.vert.html54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/re-compile-re-link.html150
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sampler-operand.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sequence-operator-returns-constant.html60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-precision-format-obeyed.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-struct-scope.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-uniform-packing-restrictions.html251
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-varying-packing-restrictions.html188
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-define.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-identifier.frag.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-define.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-identifier.frag.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-_webgl-identifier.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-containing-arrays.html133
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-uniform.html145
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-array.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-struct.vert.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-clipvertex.vert.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-assignment.html41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-conditional-assignment.html192
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-separated-variable-declarations.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping-negative.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping.html45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.frag.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.vert.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx.frag.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-do-loop.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-error-directive.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-explicit-int-cast.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-float-return-value.frag.html46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-loop.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-scoping.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-frag-depth.frag.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-recursion.frag.html45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-scoped-struct.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-functional-scoping.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glcolor.vert.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-1.frag.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-symbol.frag.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-global-variable-precision-mismatch.html128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-hex-int-constant-macro.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.frag.html238
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.vert.html224
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-include.vert.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-int-return-value.frag.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-invalid-identifier.frag.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec2-return-value.frag.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec3-return-value.frag.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec4-return-value.frag.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-limited-indexing.frag.html54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-long-line.html67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-ascii-error.frag.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-1-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-2-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-3-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-4-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-5-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-6-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-7-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-8-of-8.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-precision.frag.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-preprocessor-whitespace.html62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-quoted-error.frag.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-reserved-words.html263
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-short-circuiting-operators.html156
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-similar-uniform-array-names.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-too-many-uniforms.html123
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-two-initializer-types.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec2-return-value.frag.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec3-return-value.frag.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-return-value.frag.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.frag.html41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-120.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-130.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-webgl-identifier.vert.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-while-loop.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-without-precision.frag.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-constant-expression-loop-conditions.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-invariance.html332
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-uniforms.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-varyings.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-missing-varyings.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-name-conflicts.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-uniform-structs.html289
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-varyings.html103
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shared.html151
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-inout-parameter.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-out-parameter.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-assign.html214
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-equals.html217
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-mixed-array-declarators.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-exceeds-maximum.html55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-of-variable-names.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-under-maximum.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-specifiers-in-uniforms.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-unary-operators.html70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operator-on-arrays.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-global-initializers.html67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-initializers.html124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uniform-location-length-limits.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uninitialized-local-global-variables.html274
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/00_test_list.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/comments.html204
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/macro-expansion-tricky.html46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_field.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_function.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_struct.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_variable.vert.html34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_field.vert.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_function.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_struct.vert.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_variable.vert.html34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/00_test_list.txt4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2d-bias.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dlod.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dproj.html116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dprojlod.html162
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/00_test_list.txt6
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord-xy-values.html185
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragdata-and-fragcolor.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-frontfacing.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-pointcoord.html141
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/glsl-built-ins.html106
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/limits/00_test_list.txt6
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-line-width.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-max-texture-dimensions.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-attribs.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-textures.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-uniforms.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/manual/angle-instanced-arrays-state-leakage.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-clear-on-zero-count-draw.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-readpixels.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-unsuccessful-draw.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/manual/framebuffers-keep-contents-exiting-fullscreen-mode.html134
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/00_test_list.txt17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/bad-arguments-test.html100
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/boolean-argument-conversion.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/delayed-drawing.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/error-reporting.html75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/expando-loss.html223
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/functions-returning-strings.html104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/hint.html124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/instanceof-test.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/invalid-passed-params.html170
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/is-object.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/null-object-behaviour.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/object-deletion-behaviour.html443
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html340
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/type-conversion-test.html151
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/uninitialized-test.html262
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html299
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/00_test_list.txt54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/README.md53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests.html378
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_linkonly.html378
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_sequential.html378
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-A.js69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B1.js61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B2.js154
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B3.js68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B4.js71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-C.js119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-D_G.js235
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-G_I.js124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-L_S.js122
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-S_V.js212
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/badArgsArityLessThanArgc.html576
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/constants.html350
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/fuzzTheAPI.html116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/getContext.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/methods.html180
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-A.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B1.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B2.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B3.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B4.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-C.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-D_G.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-G_I.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-L_S.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-S_V.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI.js414
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPIBadArgs.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/webGLArrays.html165
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBuffer.html48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBufferBadArgs.html73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindFramebufferLeaveNonZero.html29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferData.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferDataBadArgs.html58
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubData.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubDataBadArgs.html79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2D.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2DBadArgs.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2D.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2DBadArgs.html96
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/deleteBufferBadArgs.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawArrays.html110
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawElements.html122
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTests.html61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTestsBadArgs.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixels.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixelsBadArgs.html113
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2D.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DBadArgs.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTML.html149
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTMLBadArgs.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2D.html70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DBadArgs.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTML.html160
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTMLBadArgs.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrix.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrixBadArgs.html143
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformf.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfArrayLen1.html100
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfBadArgs.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformi.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformiBadArgs.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttrib.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribBadArgs.html97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointer.html85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointerBadArgs.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/arrayOutOfBounds.html258
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/uniformOutOfBounds.html196
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/index.html75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/unit.css66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/unit.js970
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/more/util.js1287
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/00_test_list.txt12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-attribute-preserve-drawing-buffer.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.js13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.html43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.js51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.html43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.js35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.js13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-resize.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-timer-query.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-transfer-image-bitmap.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/00_test_list.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary_ref.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary_ref.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary_ref.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary_ref.frag94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary_ref.vert41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary_ref.frag130
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary_ref.vert56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary_ref.frag166
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary_ref.vert72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_001_to_004.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag_ref.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert_ref.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_001_to_004.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag_ref.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert_ref.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/array_001_to_006.html201
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_frag.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_vert.vert27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_frag.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_frag.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_vert.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary_ref.frag93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary_ref.vert40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary_ref.frag129
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary_ref.vert54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary_ref.frag165
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary_ref.vert69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary_ref.frag55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary_ref.frag71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary_ref.vert56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary_ref.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary_ref.frag115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary_ref.frag133
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary_ref.vert116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary_ref.vert133
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary_ref.frag161
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary.frag37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary_ref.frag186
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary_ref.vert161
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary.vert39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary_ref.vert185
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_009_to_016.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Data_Types_frag.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Standard_Library_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectBuiltInOveride_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectComma_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding1_vert.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding2_vert.vert421
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstruct_vert.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension10_V100_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension1_V100_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension4_V100_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFull_vert.vert654
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_frag.frag27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_vert.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFunction1_vert.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectModule_frag.frag64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse1_frag.frag51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_frag.frag136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_vert.vert149
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest1_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess5_frag.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess8_frag.frag115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess9_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_vert.vert17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_frag.frag39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_vert.vert17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle3_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectVersion_V100_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/DuplicateVersion1_V100_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/FunctionParam_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Include_Preprocessor_Directive_frag.frag12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Low_Level_Assembly_Reserved_Words_frag.frag27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Main_Parameters_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest4_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Constant_Conversions_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Scalar_Vector_Expressions_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/TernaryOp_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Texture_Rectangle_Samplers_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array10_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array11_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array1_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array2_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array3_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array4_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array5_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array6_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array7_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array8_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array9_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute1_vert.vert14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute2_vert.vert14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/break_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_001_to_008.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_009_to_016.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_017_to_024.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_025_to_032.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_033_to_040.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_041_to_048.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_049_to_056.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_057_to_064.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_065_to_072.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_073_to_080.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_081_to_088.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_089_to_096.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_097_to_104.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_105_to_112.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_113_to_120.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_121_to_128.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_129_to_136.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_137_to_144.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_145_to_152.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_153_to_160.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_161_to_168.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_169_to_176.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_177_to_178.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma1_vert.vert16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_vert.vert16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma3_vert.vert17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comment_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional1_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional2_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional3_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constFunc_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor1_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor2_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor3_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/continue_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType10_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType11_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType12_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType13_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType19_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType1_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType2_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType3_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType4_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType5_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType6_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType7_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType8_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType9_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.vert15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dowhile_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec2_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec3_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec4_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension2_V100_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension3_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension5_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension6_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension7_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension8_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension9_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float2_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float3_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float4_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly1_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly2_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly3_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly4_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function10_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function1_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function2_V100_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function3_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function4_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function6_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function7_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function8_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function9_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec2_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec3_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec4_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier1_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier2_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier3_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if1_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if2_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment1_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment2_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment3_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment4_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment6_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/input.run.txt24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main1_vert.vert11
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main2_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main3_vert.vert12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/matrix_V100_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/normal_vert.vert13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser10_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser1_vert.vert13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser3_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser4_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser5_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser6_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser7_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser8_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser9_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess0_frag.frag63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess10_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess1_frag.frag64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess2_frag.frag60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess3_frag.frag43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess4_frag.frag60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess6_frag.frag37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess7_frag.frag51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping1_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct10_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct11_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct1_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct2_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct3_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct4_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct5_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct6_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct7_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct8_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct9_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle1_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle2_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle3_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/typecast_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform1_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying1_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying2_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying3_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vector_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version2_V100_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version3_V100_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly2_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertex_vert.vert13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while1_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while2_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/built_in_varying_array_out_of_bounds_001_to_001.html41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/gl_Color_array_index_out_of_bounds_frag.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary_ref.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary_ref.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary_ref.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary_ref.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary_ref.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary_ref.vert27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter_ref.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter_ref.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter_ref.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter_ref.frag27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter_ref.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_009_to_010.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_frag.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_frag.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_vert.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_frag.frag35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_vert.vert35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_frag.frag44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_vert.vert44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_frag.frag40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_vert.vert40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary_ref.frag53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary_ref.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary_ref.frag57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary_ref.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary_ref.frag57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary_ref.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_001_to_002.html57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst_ref.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst_ref.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_001_to_001.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/expected.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_001_to_002.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag_ref.frag27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary_ref.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary_ref.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary_ref.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary_ref.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary_ref.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary_ref.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst_ref.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst_ref.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst_ref.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst_ref.vert31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary_ref.frag27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary_ref.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary_ref.frag35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary_ref.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_frag.frag85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_vert.vert86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_frag.frag68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_vert.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_frag.frag42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_vert.vert42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_frag.frag112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_vert.vert112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_frag.frag85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_vert.vert85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_frag.frag68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_vert.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_frag.frag68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_vert.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_frag.frag42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_vert.vert42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_009_to_016.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_017_to_024.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_025_to_032.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_033_to_040.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_041_to_048.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_049_to_056.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_057_to_064.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_065_to_072.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_073_to_080.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_081_to_088.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_089_to_096.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_097_to_104.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_105_to_112.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_113_to_120.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_121_to_126.html181
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/input.run.txt17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_frag.frag68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_vert.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_frag.frag42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_vert.vert42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_frag.frag112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_vert.vert112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_frag.frag85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_vert.vert85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_frag.frag68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_vert.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_frag.frag124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_vert.vert124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_frag.frag128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_vert.vert128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_frag.frag124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_vert.vert124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_frag.frag128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_vert.vert128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_frag.frag124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_vert.vert124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_frag.frag128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_vert.vert128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_frag.frag118
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_vert.vert118
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_frag.frag119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_vert.vert119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_frag.frag42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_vert.vert42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_vert.vert70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_frag.frag91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_vert.vert91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_frag.frag112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_vert.vert112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_frag.frag74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_frag.frag85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_vert.vert85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_frag.frag68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_vert.vert68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_vert.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_w_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag_ref.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag.frag15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_001_to_001.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary_ref.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary_ref.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary_ref.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01_ref.frag39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01_ref.vert40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary_ref.vert35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01_ref.frag39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01_ref.vert40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01_ref.frag39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01_ref.vert40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_frag.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_vert.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_frag.frag37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_vert.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_frag.frag39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_vert.vert39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_frag.frag56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_vert.vert55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_frag.frag53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_vert.vert52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_vert.vert66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_frag.frag63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_vert.vert62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_frag.frag78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_vert.vert77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_frag.frag75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/input.run.txt7
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_frag.frag56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_vert.vert55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_frag.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_frag.frag53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_vert.vert52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_frag.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_vert.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_frag.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_vert.vert33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_vert.vert65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_frag.frag42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_vert.vert42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_frag.frag63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_vert.vert62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_frag.frag57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_vert.vert54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_frag.frag59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_vert.vert56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_frag.frag78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_vert.vert77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_frag.frag75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_vert.vert74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_009_to_016.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_017_to_024.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_025_to_032.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_033_to_040.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_041_to_046.html181
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3_001_to_006.html343
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_frag.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_vert.vert35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_frag.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_vert.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_vert.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixCompMult_001_to_004.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag_ref.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert_ref.vert27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag_ref.frag42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert_ref.vert47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf_ref.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf_ref.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf_ref.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf_ref.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf_ref.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_001_to_008.html159
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_vert.vert17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_001_to_004.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag_ref.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert_ref.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag_ref.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert_ref.vert31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/input.run.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_009_to_012.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag_ref.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag_ref.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_vert.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_frag.frag61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_vert.vert61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_vert.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/input.run.txt5
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_frag.frag94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_vert.vert94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_vert.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_009_to_016.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_017_to_024.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_025_to_026.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_frag.frag27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_frag.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_vert.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_vert.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/input.run.txt4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_009_to_016.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_017_to_024.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary_ref.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst_ref.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst_ref.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst_ref.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst_ref.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst_ref.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst_ref.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst_ref.frag37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst.vert29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst_ref.frag38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst_ref.vert38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary_ref.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary_ref.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary_ref.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary_ref.vert27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary_ref.frag84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary_ref.vert38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary_ref.frag120
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary_ref.vert62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary_ref.frag156
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary_ref.vert62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter_ref.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter_ref.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter_ref.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter_ref.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary_ref.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf_ref.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf_ref.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf_ref.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf_ref.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf_ref.frag44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf_ref.vert45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/input.run.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_frag.frag99
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_vert.vert102
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_009_to_016.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_017_to_024.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_025_to_032.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_033_to_040.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_041_to_048.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_049_to_056.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_vert.vert35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_frag.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_frag.frag36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_vert.vert37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_vert.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_vert.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_frag.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_vert.vert38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_frag.frag31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_vert.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_frag.frag28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_vert.vert32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_vert.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_frag.frag38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_vert.vert39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_frag.frag51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_vert.vert53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_frag.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_frag.frag26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_frag.frag38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_vert.vert41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_frag.frag54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_vert.vert57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_vert.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_frag.frag34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_vert.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_frag.frag62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_vert.vert57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_frag.frag83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_vert.vert72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_frag.frag33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_vert.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_vert.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_vert.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/input.run.txt16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_001_to_008.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_017_to_024.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_025_to_032.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_033_to_040.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_041_to_048.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_049_to_056.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_057_to_064.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_065_to_072.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_073_to_080.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_081_to_088.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_089_to_096.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_097_to_104.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_105_to_112.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_113_to_120.html135
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_frag.frag21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_vert.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_vert.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_vert.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_frag.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_vert.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_vert.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_vert.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_001_to_006.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary_ref.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary_ref.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary_ref.frag30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary.vert31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary_ref.vert31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary.frag35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary_ref.frag35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary_ref.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/input.run.txt4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_vert.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_frag.frag23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_vert.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_001_to_008.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_009_to_016.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_017_to_018.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/input.run.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3_001_to_008.html313
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_frag.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_vert.vert30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_frag.frag38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_vert.vert34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_frag.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_vert.vert28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.frag51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.frag44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.frag51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.frag47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.frag48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.frag47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.frag47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.vert144
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/copy_texture/copy_texture.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.vert132
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.frag14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.vert17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.vert27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_vert.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.frag47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/brick.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/texture.frag35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.frag29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.vert23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat2.vert45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat3.vert45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat4.vert45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_vec.vert48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.frag45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.vert71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.frag18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.frag24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.frag25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests2.vert24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/vec_tests.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.frag16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21f_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21i_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22f_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22i_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23f_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23i_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24f_frag.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24i_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2m_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3m_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_frag.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.vert18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4m_frag.frag20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/default.vert16
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.vert22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_vert.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.frag14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.vert20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_vert.vert44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/three_uniforms/4f_frag.frag22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_vert.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_frag.frag46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_vert.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_frag.frag66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_vert.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/vertex_program_point_size/point_size.vert19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/README.md20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/mustpass.run.txt64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js791
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/process-ogles2-tests.py568
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/00_test_list.txt12
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/get-active-test.html119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-long-names-test.html153
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-test.html139
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-attribute.html85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-uniform.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-getshadersource.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-shader-test.html94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/invalid-UTF-16.html48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/program-handling.html142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/program-infolog.html62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/program-test.html406
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/programs/use-program-crash-with-discard-in-fragment-shader.html77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html251
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html428
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/depth-renderbuffer-initialization.html132
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/feedback-loop.html104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-object-attachment.html678
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-state-restoration.html112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-test.html176
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/renderbuffer-initialization.html99
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/stencil-renderbuffer-initialization.html132
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html146
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html266
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html127
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html95
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html229
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html123
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html129
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html166
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html173
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html183
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/00_test_list.txt9
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/fb-attach-implicit-target-assignment.html94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enable-enum-test.html171
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enum-tests.html29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-get-calls.html198
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-geterror.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-getstring.html60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-initial-state.html58
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/gl-object-get-calls.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/state/state-uneffected-after-compositing.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/00_test_list.txt14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-alpha-alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-alpha-alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance-luminance-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-alpha-alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance-luminance-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-alpha-alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance-luminance-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/00_test_list.txt58
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/canvas-teximage-after-multiple-drawimages.html100
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/compressed-tex-image.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-2d-formats.html173
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-and-sub-image-2d.html137
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-crash.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-large-partial-copy-corruption.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-subrects.html170
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-incomplete-fbo.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-map-uploads-out-of-order.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/default-texture.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/exif-orientation.html167
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/format-filterable-renderable.html378
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-get-tex-parameter.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-pixelstorei.html96
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-teximage.html406
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/mipmap-fbo.html109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance-offscreencanvas.html125
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance.html137
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/png-image-types.html164
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html304
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-uniform-binding-bugs.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-canvas-corruption.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-webgl.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-format-and-type.html722
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-invalid-data.html158
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-input-validation.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d-bad-args.html133
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-video-using-tex-unit-non-zero.html191
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texparameter-test.html129
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind-2.html210
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind.html179
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-attachment-formats.html176
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-clear.html43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-complete.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-and-deletion.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-feedback-loops.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-corner-case-videos.html47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-cube-as-fbo-attachment.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-draw-with-2d-and-cube.html103
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-fakeblack.html94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-formats-test.html274
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-hd-dpi.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-mips.html297
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot-video.html160
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot.html305
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-cube-maps.html331
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-limit.html167
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size.html217
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-srgb-upload.html253
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-sub-image-cube-maps.html316
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-transparent-pixels-initialized.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-cube-maps.html52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-size.html151
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-video-transparent.html164
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-with-flip-y-and-premultiply-alpha.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/upload-from-srcset-with-empty-data.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/video-rotation.html167
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-alpha-alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance-luminance-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-alpha-alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-alpha-alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/00_test_list.txt7
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-crash.html40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-view-crash.html41
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-large-array-tests.html102
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html1103
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-crash.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-test.html421
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/typed-arrays-in-workers.html257
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/00_test_list.txt31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-get-uniform-non-current-program.html79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-arrays.html738
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-bool.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-struct-unused.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-unused-array-elements-get-truncated.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniformmatrix4fv.html149
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-unknown-uniform.html67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-00.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-01.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-02.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-03.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-04.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-05.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-06.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-07.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-08.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-09.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-10.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-11.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-12.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-13.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-14.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-15.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-16.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-17.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/null-uniform-location.html81
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/out-of-bounds-uniform-array-access.html168
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-default-values.html339
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-location.html96
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-samplers-test.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-values-per-program.html179
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/00_test_list.txt20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-i-render.html108
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-normalized-int.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib.html28
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer-offsets.html154
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer.html126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/invalid-vertex-attribs.html73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/attribs/render-no-enabled-attrib-arrays.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-contents.html176
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html102
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html183
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html110
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/delete-buffer.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data-validity.html250
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html223
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html195
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-second-compile.html104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-state-restoration.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers.html576
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/canvas/00_test_list.txt1
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/canvas/compositing.html92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/canvas/to-data-url-with-pack-params.html73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/00_test_list.txt10
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/constants-and-properties-2.html835
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/context-attributes-depth-stencil-antialias-obeyed.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/context-mode.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/context-resize-changes-buffer-binding-bug.html49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/context-sharing-texture2darray-texture3d-data-bug.html150
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/context-type-test-2.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/incorrect-context-object-behaviour.html230
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/methods-2.html268
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/context/no-experimental-webgl2.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/00_test_list.txt19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html508
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-half-float.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-disjoint-timer-query-webgl2.html316
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-filter-anisotropic.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-norm16.html253
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/oes-draw-buffers-indexed.html573
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html524
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_depth.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_draw_buffers.html158
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_flat_varying.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_instanced_draw.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_non_multiview_shaders.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_single_view_operations.html253
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_timer_query.html142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_transform_feedback.html125
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions-in-shaders.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/required-extensions.html58
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-multi-draw-instanced-base-vertex-base-instance.html1021
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-as-return-value.html150
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign-constructor.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-complex-indexing.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-element-increment.html131
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-equality.html240
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-in-complex-expression.html144
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-initialize-with-same-name-array.html48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-length-side-effects.html100
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/bool-type-cast-bug-uint-ivec-uvec.html368
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compare-structs-containing-arrays.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compound-assignment-type-combination.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-array-init.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-struct-from-array-as-function-parameter.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/float-parsing.html167
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forbidden-operators.html124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forward-declaration.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/frag-depth.html157
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/fragment-shader-loop-crash.html72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/gradient-in-discontinuous-loop.html75
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/input-with-interpotaion-as-lvalue.html83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-default-precision.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-invariant.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/loops-with-side-effects.html211
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major-dynamic-indexing.html118
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/misplaced-version-directive.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/no-attribute-vertex-shader.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/precision-side-effects-bug.html125
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/reciprocal-sqrt-of-sum-of-squares-crash.html66
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-array-indexing.html94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-no-precision.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sequence-operator-returns-non-constant.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-linking.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-invalid-characters.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-mis-matching-uniform-block.html59
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/short-circuiting-in-loop-condition.html180
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html351
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html170
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-out-of-range.html106
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-uniform-texture-coordinate.html170
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/tricky-loop-conditions.html327
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uint-int-shift-bug.html106
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/unary-minus-operator-in-dynamic-loop.html248
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layout-match.html57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layouts.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-struct-with-non-square-matrix.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uninitialized-local-global-variables.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/valid-invariant.html95
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/varying-struct-inline-definition.html62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing.html369
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html176
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html285
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html583
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html320
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.js13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.js13
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-query.html79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-sync.html77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-timer-query.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-transfer-image-bitmap.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/programs/00_test_list.txt4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/programs/active-built-in-attribs.html86
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/programs/get-uniform-indices.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/programs/gl-get-frag-data-location.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/programs/sampler-uniforms.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/query/00_test_list.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/query/occlusion-query.html137
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/query/query.html167
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/reading/00_test_list.txt5
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/reading/format-r11f-g11f-b10f.html266
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-fbo-test.html642
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-rgb8-into-pbo-bug.html85
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-into-pixel-pack-buffer.html152
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-pack-parameters.html353
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt10
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html508
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html288
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html144
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html230
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-draws-between-blits.html207
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html180
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html149
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-stencil-renderbuffer-initialization.html167
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html174
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/00_test_list.txt51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/attrib-type-match.html561
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-outofbounds.html172
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-srgb.html161
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-multisampled-readbuffer.html112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-outside-readbuffer.html267
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-r11f-g11f-b10f.html113
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-resolve-to-back-buffer.html245
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-scissor-enabled.html160
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-size-overflow.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-srgb-and-linear-drawbuffers.html207
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-stencil-only.html170
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-test.html361
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-unaffected-by-colormask.html102
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/builtin-vert-attribs.html408
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/canvas-resizing-with-pbo-bound.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-func-buffer-type-match.html145
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-srgb-color-buffer.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html216
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-sub-source.html110
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbufferfv-with-alpha-false.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clipping-wide-points.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/depth-stencil-feedback-loop.html165
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-dirty-state-bug.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-driver-hang.html187
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-sparse-output-locations.html108
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers.html598
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-with-integer-texture-base-level.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/element-index-uint.html432
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-draw-framebuffer.html74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-unaffected.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-mismatched-attachment-targets.html162
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer-angle-issue.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer.html440
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-changing-base-level.html107
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-level1.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html201
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-unsupported.html134
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/fs-color-type-mismatch-color-buffer-type.html169
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-arrays.html271
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-bug.html254
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-large-divisor.html145
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/line-rendering-quality.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-depth-resolve.html179
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-fragment-evaluation.html143
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/out-of-bounds-index-buffers-after-copying.html187
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rasterizer-discard-and-implicit-clear.html149
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/read-draw-when-missing-image.html288
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rgb-format-support.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/texture-switch-performance.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/uniform-block-buffer-size.html228
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id-large-count.html127
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id.html219
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/samplers/00_test_list.txt3
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/samplers/multi-context-sampler-test.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/samplers/sampler-drawing-test.html124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/samplers/samplers.html230
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/state/00_test_list.txt4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-enum-tests.html29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-get-calls.html177
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-getstring.html60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-object-get-calls.html23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/sync/00_test_list.txt1
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html156
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/00_test_list.txt14
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r32f-red-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8-red-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8ui-red_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg32f-rg-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8-rg-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb32f-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-half_float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba32f-rgba-float.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8-rgb-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html39
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html124
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/angle-stuck-depth-textures.html197
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/canvas-remains-unchanged-after-used-in-webgl-texture.html73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-from-pbo-crash.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-image.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-AMD-bug.html104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-bug.html49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html165
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-same-texture.html144
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-webgl-specific.html303
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html249
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/generate-mipmap-with-large-base-level.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html221
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html216
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-texture-sampling.html169
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/mipmap-fbo.html50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/npot-video-sizing.html181
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/origin-clean-conformance-offscreencanvas.html146
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-mipmap-levels-intel-bug.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html189
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-base-level-bug.html76
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html197
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html128
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html51
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html225
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html565
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-srgb-mipmap.html220
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html290
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-and-subimage-3d.html242
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-compressed-formats.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-canvas-bug.html56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-pixel-buffer-bug.html90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-imagedata.html126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-with-flip-y-and-premultiply-alpha.html499
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params.html591
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texel-fetch-undefined.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html160
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/00_test_list.txt68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r32f-red-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8-red-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg32f-rg-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8-rg-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb32f-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-half_float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba32f-rgba-float.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8-rgb-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/00_test_list.txt9
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/default_transform_feedback.html117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/non-existent-varying.html70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/same-buffer-two-binding-points.html176
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/simultaneous_binding.html330
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/switching-objects.html231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/too-small-buffers.html242
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html645
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/two-unreferenced-varyings.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/unwritten-output-defaults-to-zero.html133
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt9
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html120
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html404
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html335
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html122
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/00_test_list.txt2
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object-and-disabled-attributes.html132
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object.html671
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/00_test_list.txt7
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/LICENSE202
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/README.md21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/build.py264
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/compiler_additional_extern.js94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/00_test_list.txt31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.test333
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.test288
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.test662
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.template36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.test5930
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.test553
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.test206
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.test206
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.test206
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.test602
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.test1844
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.test548
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.test602
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.test1196
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.test140
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.test76
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.test3475
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.test90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.test1613
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.test1715
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.test4287
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.test785
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.test250
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.test823
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/shader-lib-test.html462
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-conversions.js33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-swizzles.js47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.template36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.test6811
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.test469
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.test865
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.test1063
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.test469
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.test865
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.test1063
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.test469
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.test865
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.test1063
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/template.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/00_test_list.txt33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.test1962
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.test381
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.test483
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.test1153
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.template25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.test14246
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.test1887
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.test1952
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.test872
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.test392
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.test1160
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.test3480
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.test1064
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.test1160
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.test2312
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.test591
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.test76
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.test4345
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.test1143
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.test3219
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.test3833
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.test100
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.test5256
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.test2714
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.test901
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-conversions.js33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-swizzles.js47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.test633
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.template36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.test7459
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.test511
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.test943
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.test1159
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.test511
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.test943
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.test1159
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.test511
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.test943
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.html42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.test1159
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/template.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuBilinearImageCompare.js272
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuCompressedTexture.js967
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloat.js862
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js349
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFuzzyImageCompare.js338
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js757
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuInterval.js609
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuLogImage.js163
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrix.js354
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrixUtil.js70
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuPixelFormat.js79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuRGBA.js279
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSkipList.js245
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuStringTemplate.js42
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSurface.js184
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTestCase.js491
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexCompareVerifier.js1356
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexLookupVerifier.js2225
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexVerifierUtil.js265
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexture.js3636
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTextureUtil.js725
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js1143
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js260
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluDrawUtil.js510
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluObjectWrapper.js117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluPixelTransfer.js55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderProgram.js488
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderUtil.js795
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluStrUtil.js166
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTexture.js380
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTextureUtil.js1025
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarType.js814
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarTypeUtil.js693
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/00_test_list.txt1
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/referencecontext.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrGLContext.js231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContext.js4986
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContextTest.js834
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceUtils.js317
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrShaderProgram.js336
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js190
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js323
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js1274
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js123
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js113
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js641
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/00_test_list.txt80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/attriblocation.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/booleanstatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/buffercopy.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/bufferobjectquery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/00_test_list.txt55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/abs.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acos.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acosh.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/add.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asin.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asinh.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan2.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atanh.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/builtinprecision_test_generator.py143
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/ceil.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/clamp.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cos.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cosh.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cross.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/degrees.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/determinant.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/distance.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/div.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/dot.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp2.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/faceforward.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/floor.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/fract.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inverse.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inversesqrt.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/length.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log2.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/matrixcompmult.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/max.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/min.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mix.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mod.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/modf.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mul.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/normalize.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/outerproduct.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/pow.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/radians.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/reflect.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/refract.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/round.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/roundeven.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sign.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sin.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sinh.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/smoothstep.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sqrt.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/step.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sub.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tan.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tanh.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/transpose.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/trunc.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/clipping.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/defaultvertexattribute.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/00_test_list.txt7
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays_instanced.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements_instanced.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_range_elements.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_test_generator.py89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/instancing.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/random.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fApiCase.js161
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fAttribLocationTests.js267
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBooleanStateQuery.js372
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferCopyTests.js355
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferObjectQueryTests.js177
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBuiltinPrecisionTests.js87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fClippingTests.js406
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fDrawTests.js1155
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboColorbufferTests.js1049
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboCompletenessTests.js567
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboDepthbufferTests.js385
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboInvalidateTests.js1471
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboMultisampleTests.js377
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js2389
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStateQueryTests.js796
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStencilbufferTests.js325
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestCase.js483
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestUtil.js1324
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFloatStateQueryTests.js431
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragDepthTests.js593
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragmentOutputTests.js1398
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFramebufferBlitTests.js1261
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIndexedStateQueryTests.js409
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInstancedRenderingTests.js711
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIntegerStateQueryTests.js2049
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInternalFormatQueryTests.js173
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fLifetimeTests.js471
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fMultisampleTests.js1744
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeBufferApiTests.js1104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeFragmentApiTests.js339
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeShaderApiTests.js1195
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeStateApiTests.js927
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeTextureApiTests.js3002
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeVertexArrayApiTests.js906
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fOcclusionQueryTests.js511
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPixelBufferObjectTest.js585
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPrimitiveRestartTests.js709
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRasterizerDiscardTests.js485
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRboStateQueryTests.js308
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fReadPixelTests.js517
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerObjectTests.js313
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerStateQueryTests.js205
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderApiTests.js650
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderBuiltinVarTests.js1109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderCommonFunctionTests.js1973
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderDerivateTests.js1696
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderIndexingTests.js1278
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js1251
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderMatrixTest.js1852
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderOperatorTests.js3252
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js791
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPrecisionTests.js947
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStateQueryTests.js2205
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStructTests.js1957
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderSwitchTests.js492
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderTextureFunctionTests.js2709
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fStringQueryTests.js111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSyncTests.js330
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js2282
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFormatTests.js1185
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureShadowTests.js898
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureSpecificationTests.js7456
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureStateQuery.js376
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureWrapTests.js434
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTransformFeedbackTests.js1914
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformApiTests.js3203
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformBlockTests.js748
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayObjectTests.js875
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayTests.js1103
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/00_test_list.txt26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/blend.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/clear.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/fbocolorbuffer_test_generator.py116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_00.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_01.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_02.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_03.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_04.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_05.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_00.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_01.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_02.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_03.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_04.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_05.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_00.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_01.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_02.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_03.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_04.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_05.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_00.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_01.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_02.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_03.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_04.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_05.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocompleteness.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbodepthbuffer.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/00_test_list.txt7
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/default.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/fboinvalidate_test_generator.py114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_00.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_01.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_02.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/sub.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/target.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/whole.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.2_samples.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.4_samples.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.8_samples.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/00_test_list.txt18
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/fborender_test_generator.py117
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_depth_stencil.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_clear.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_depth_stencil.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/stencil_clear.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostencilbuffer.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/floatstatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragdepth.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/00_test_list.txt11
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.fixed.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.float.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.int.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.uint.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.fixed.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.float.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.int.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.uint.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/fragmentoutput_test_generator.py93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/00_test_list.txt50
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_08.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_09.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_10.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_11.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_12.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_13.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_14.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_15.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_16.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_17.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_18.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_19.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_20.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_21.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_22.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_23.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_24.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_25.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_26.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_27.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_28.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_29.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_30.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_31.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_32.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_33.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_34.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/depth_stencil.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/frambufferblit_test_generator.py111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/indexedstatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/instancedrendering.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/integerstatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/internalformatquery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/lifetime.html34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/00_test_list.txt6
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/default_fbo.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_4_samples.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_8_samples.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_max_samples.html31
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/multisample_test_generator.py98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativebufferapi.html30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativefragmentapi.html23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativeshaderapi.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativestateapi.html23
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativetextureapi.html30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativevertexarrayapi.html30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_conservative.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_strict.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/pixelbufferobject.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00_test_list.txt8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/primitiverestart_test_generator.py84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rasterizerdiscard.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rbostatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/readpixel.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerobject.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerstatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderapi.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderbuiltinvar.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadercommonfunction.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdx.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdy.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_fwidth.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/00_test_list.txt9
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/shaderindexing_test_generator.py97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/tmp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/uniform.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/varying.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec2.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec3.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec4.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_do_while.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_for.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_while.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/00_test_list.txt33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_assign.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_const.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_dynamic.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_uniform.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/determinant.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_assign.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_const.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_dynamic.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_uniform.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/inverse.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/matrixcompmult.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_assign.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_highp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_lowp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_mediump.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_highp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_lowp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_mediump.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_highp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_lowp.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_mediump.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/negation.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/outerproduct.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_decrement.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_increment.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_decrement.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_increment.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/shadermatrix_test_generator.py121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_assign.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_const.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_dynamic.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_uniform.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/transpose.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/unary_addition.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/00_test_list.txt37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_00.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_01.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_02.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_03.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_00.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_01.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_02.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_03.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_04.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_05.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_06.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_07.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_08.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_09.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_10.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_11.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_12.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_13.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_14.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_15.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/bool_compare.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_00.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_01.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_02.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_03.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_04.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_05.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_06.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/exponential.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/float_compare.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/geometric.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/int_compare.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/selection.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/sequence.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/shaderoperator_test_generator.py127
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_00.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_01.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_02.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderpackingfunction.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_float.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_int.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_uint.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstatequery.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstruct.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderswitch.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/00_test_list.txt15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/shadertexturefunction_test_generator.py103
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetch.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetchoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texture.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegrad.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegradoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelod.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelodoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureproj.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgrad.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgradoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlod.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlodoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojoffset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturesize.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/stringquery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/sync.html32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/00_test_list.txt116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_08.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_09.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_08.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_09.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_08.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_09.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_10.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_11.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_12.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_13.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_14.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_15.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_16.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_17.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_18.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_19.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_20.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_21.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_22.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_23.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_24.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_25.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_26.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_27.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_28.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_29.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_30.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_31.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_32.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_33.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_34.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_35.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_08.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_09.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_05.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_06.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_07.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_08.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_09.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_no_edges_visible.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/texturefiltering_test_generator.py138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/00_test_list.txt38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_2d.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_cube.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_depth_stencil.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/textureformat_test_generator.py126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d_array.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_3d.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/00_test_list.txt144
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_always.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less_or_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_never.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_not_equal.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/textureshadow_test_generator.py116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/00_test_list.txt90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copyteximage2d.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copytexsubimage2d.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_2d.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_cube.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_align.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth_pbo.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_unpack_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth_pbo.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_unpack_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_depth_stencil.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_size.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_depth_stencil.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_size.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_align.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_depth.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_empty_tex.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_02.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_03.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_04.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_unpack_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_depth.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_unpack_params.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texturespecification_test_generator.py178
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturestatequery.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/00_test_list.txt22
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_npot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_pot.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/texturewrap_test_generator.py110
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/00_test_list.txt29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_centroid.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_flat.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_smooth.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/point_size.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/position.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_lines.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_points.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_triangles.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/transformfeedback_test_generator.py118
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/00_test_list.txt4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/info_query.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/random.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/uniformapi_test_generator.py92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_assigned.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_initial.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/00_test_list.txt10
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/instance_array_basic_type.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_basic_types.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_nested_struct.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/random.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_array.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_type.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct_array.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct_array.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/uniformbuffers_test_generator.py98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrayobject.html24
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/00_test_list.txt27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.count.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.output.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.storage.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.stride.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.first.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.normalize.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.offset.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.byte.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.float.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.half.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int_2_10_10_10.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.short.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_byte.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int_2_10_10_10.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_short.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.stride.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_copy.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_draw.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_read.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_copy.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_draw.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_read.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_copy.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_draw.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_read.html31
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/vertexarrays_test_generator.py110
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/genHTMLfromTest.py43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsAttributeLocationTests.js1477
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBufferTestUtil.js1068
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js5415
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTestsUnitTests.js2819
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsDrawTests.js3452
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboCompletenessTests.js961
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboUtil.js1413
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsLifetimeTests.js1118
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsRandomUniformBlockCase.js282
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsSamplerObjectTest.js1148
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderExecUtil.js731
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibrary.js1114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibraryCase.js1132
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderRenderCase.js1200
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsStateQuery.js367
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsTextureTestUtil.js2642
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsUniformBlockCase.js2451
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsVertexArrayTests.js2534
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/deqp/run-closure.sh26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/chrome.js156
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/deprecated.js46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es3.js2236
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es5.js269
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6.js856
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6_collections.js253
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/fileapi.js961
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/flash.js210
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_css.js126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_dom.js1120
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_event.js62
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_xml.js73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/google.js30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/html5.js3231
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_css.js267
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_dom.js1395
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_event.js309
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_vml.js77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/intl.js163
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/iphone.js362
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/mediasource.js142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/page_visibility.js32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/v8.js125
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_anim_timing.js191
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css.js2505
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css3d.js199
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_device_sensor_event.js101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom1.js874
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom2.js2619
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom3.js854
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_elementtraversal.js56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_encoding.js54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event.js372
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event3.js63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_geolocation.js101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_indexeddb.js914
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_navigation_timing.js161
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_range.js248
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_rtc.js1002
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_selectors.js94
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_xml.js417
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_css.js456
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_dom.js281
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_event.js48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_notifications.js201
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webstorage.js148
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/window.js191
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.js4
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.sh60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/webgl2.js5520
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/50x50pixel-black-with-red-triangle.pngbin0 -> 3032 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/big-fbos-example.html256
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/buffer-gc-stress.html155
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/buffer-sizes.html268
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.html88
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.pngbin0 -> 212531 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/constant-index-out-of-range.html219
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/context-creation-and-destruction-stress.html35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/cube-map-uploads-out-of-order.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/fbo-lost-context.html202
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/getbuffersubdata-nonblocking-benchmark.html223
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/logo-256x256.pngbin0 -> 4155 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-example.html89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-shader-example.html155
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/multisample-corruption-stress.html37
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/offscreen-issue.html43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/out-of-bounds-uniform-array-access.html105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/out-of-memory.html84
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/out-of-resources.html120
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/out-of-vram.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/point-no-attributes-stress.html61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/program-test-1.html80
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/readpixels-after-alert.html65
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/sample-100.pngbin0 -> 960 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/sample-200.pngbin0 -> 2364 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/sample-400.pngbin0 -> 5181 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/sample.svg4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/simulated-attrib-0-bug-test.html36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/slow-shader-example.html112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.js158
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/texture-allocation-stress-test.html47
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/texture-from-camera-stress.html79
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/texture-sizing.html229
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/webgl-compressed-texture-size-limit-stress.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/webgl-drawelements-validation.html142
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/webgl-info.html275
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/webgl-translate-shader.html153
-rw-r--r--dom/canvas/test/webgl-conf/checkout/extra/workload-simulator.html851
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/desktop-gl-constants.js2639
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js424
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-constructor-tests-generator.js919
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-generator.js1234
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/js-test-post.js38
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/js-test-pre.js801
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/pnglib.js207
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/test-eval.js15
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js825
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/compositing-test.js136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js133
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/compressed-tex-image.js138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/compressed-texture-utils.js258
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/context-methods.js52
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/ext-color-buffer-half-float.js473
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/ext-float-blend.js237
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/ext-texture-filter-anisotropic.js169
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js123
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js183
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js1090
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js263
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js105
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/invalid-vertex-attrib-test.js129
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js183
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/line-rendering-quality.js163
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/no-over-optimizations-on-uniform-array.js247
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js151
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/offscreencanvas-transfer-image-bitmap.js57
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js321
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/ovr_multiview2_util.js263
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/shader-with-non-reserved-words.js664
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js292
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js468
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js46
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js240
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js257
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js140
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js291
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js298
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js287
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js226
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js48
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js74
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js56
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js49
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js45
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js83
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js259
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js260
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js104
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js244
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js212
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js865
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js435
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js563
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/texture-corner-case-videos.js299
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/webgl-compressed-texture-size-limit.js226
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/webgl-draw-buffers-utils.js69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/webgl-test-harness.js642
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js3677
-rw-r--r--dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/index.html401
-rw-r--r--dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/README35
-rw-r--r--dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/shader-cache.txt2747
-rw-r--r--dom/canvas/test/webgl-conf/checkout/performance/webgl_webcodecs_video_frame/index.html186
-rw-r--r--dom/canvas/test/webgl-conf/checkout/py/lint/LICENSE30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/py/lint/README.md115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/py/lint/lint.allowlist57
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/py/lint/lint.py225
-rwxr-xr-xdom/canvas/test/webgl-conf/checkout/py/tex_image_test_generator.py182
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/1-channel.jpgbin0 -> 16799 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/3x3.pngbin0 -> 2806 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/blue-1x1.jpgbin0 -> 319 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/boolUniformShader.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/bug-32888-texture.pngbin0 -> 10050 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-2-mirror-horizontal.jpgbin0 -> 4785 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-3-rotate-180.jpgbin0 -> 4792 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-4-mirror-vertical.jpgbin0 -> 4793 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-5-mirror-horizontal-90-ccw.jpgbin0 -> 4844 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-6-90-ccw.jpgbin0 -> 4841 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-7-mirror-horizontal-90-cw.jpgbin0 -> 4837 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-8-90-cw.jpgbin0 -> 4840 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test.psdbin0 -> 85975 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-1-normal.jpgbin0 -> 4789 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-2-mirror-horizontal.jpgbin0 -> 4845 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-3-rotate-180.jpgbin0 -> 4852 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-4-mirror-vertical.jpgbin0 -> 4853 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-5-mirror-horizontal-90-ccw.jpgbin0 -> 4904 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-6-90-ccw.jpgbin0 -> 4901 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-7-mirror-horizontal-90-cw.jpgbin0 -> 4897 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-8-90-cw.jpgbin0 -> 4900 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/floatUniformShader.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/fragmentShader.frag32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/glsl-feature-tests.css29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/glsl-generator.js1234
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-1024x1024.jpgbin0 -> 10314 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256-with-128-alpha.pngbin0 -> 81 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256.pngbin0 -> 78 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-default-gamma.pngbin0 -> 123 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma0.1.pngbin0 -> 133 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma1.0.pngbin0 -> 133 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma2.0.pngbin0 -> 133 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma4.0.pngbin0 -> 133 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma9.0.pngbin0 -> 133 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/gray-ramp.pngbin0 -> 123 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/green-2x2-16bit.pngbin0 -> 134 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/intArrayUniformShader.vert8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/intUniformShader.vert43
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/js-test-style.css20
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/matForWebGL2UniformShader.vert25
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/matUniformShader.vert40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.frag34
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.vert4
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.frag40
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.vert6
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/npot-video-1920x1080.mp4bin0 -> 78665 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/npot-video.mp4bin0 -> 41430 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/npot-video.theora.ogvbin0 -> 24630 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/npot-video.webmvp8.webmbin0 -> 51240 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/ogles-tests.css30
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/opengl_logo.jpgbin0 -> 5827 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.jpgbin0 -> 1089 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.psdbin0 -> 21098 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272-sar-136x135-dar-16x9.mp4bin0 -> 1585 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272.pngbin0 -> 507 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.pngbin0 -> 469 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.psdbin0 -> 20380 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.hdrbin0 -> 303 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.pngbin0 -> 1166 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green-semi-transparent.pngbin0 -> 101 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green.bt601.vp9.webmbin0 -> 4015 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green.mp4bin0 -> 93506 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green.pngbin0 -> 144 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green.svg6
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green.theora.ogvbin0 -> 10292 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-green.webmvp8.webmbin0 -> 10979 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/red-indexed.pngbin0 -> 168 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/samplerForWebGL2UniformShader.frag17
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/samplerUniformShader.frag8
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-cie-rgb-profile.pngbin0 -> 868 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colormatch-profile.pngbin0 -> 871 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.jpgbin0 -> 9145 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.pngbin0 -> 841 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-e-srgb-profile.pngbin0 -> 1985 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-smpte-c-profile.pngbin0 -> 871 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/small-square-with-srgb-iec61966-2.1-profile.pngbin0 -> 3201 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/structUniformShader.vert53
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/thunderbird-logo-64x64.pngbin0 -> 63843 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.mp4bin0 -> 2124 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.webmbin0 -> 960 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/transparent-on-left-indexed.pngbin0 -> 972 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/uintUniformShader.vert21
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.frag19
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.vert26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/vertexShader.vert36
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.mp4bin0 -> 2085 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.vp9.mp4bin0 -> 2471 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.mp4bin0 -> 2082 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.vp9.mp4bin0 -> 2461 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.mp4bin0 -> 2126 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.vp9.mp4bin0 -> 2504 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.mp4bin0 -> 2092 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.vp9.mp4bin0 -> 2480 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/webgl-logo.pngbin0 -> 9077 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/resources/zero-alpha.pngbin0 -> 89 bytes
-rw-r--r--dom/canvas/test/webgl-conf/checkout/test-guidelines.md165
-rw-r--r--dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html1305
5161 files changed, 590024 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/00_test_list.txt
new file mode 100644
index 0000000000..3fde5ef8de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/00_test_list.txt
@@ -0,0 +1,7 @@
+// files that end in .txt list other tests
+// other lines are assumed to be .html files
+
+conformance/00_test_list.txt
+conformance/more/00_test_list.txt
+deqp/00_test_list.txt
+--min-version 2.0.0 conformance2/00_test_list.txt
diff --git a/dom/canvas/test/webgl-conf/checkout/CONFORMANCE_RULES.txt b/dom/canvas/test/webgl-conf/checkout/CONFORMANCE_RULES.txt
new file mode 100644
index 0000000000..c267d34b08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/CONFORMANCE_RULES.txt
@@ -0,0 +1,127 @@
+Rules for Claiming a Conformant WebGL Implementation
+====================================================
+
+The WebGL API is a web standard, and many web browser implementers
+deliver their browser on multiple operating systems (OSs). WebGL
+implementations also typically rely on the presence of an OpenGL or
+OpenGL ES implementation on the OS. It can be appreciated that a WebGL
+implementation therefore has many dependencies. This document attempts
+to clarify to potential implementers the rules the Khronos Group uses
+to judge whether a particular WebGL implementation is conformant.
+
+There are two primary reasons to submit conformance results:
+
+ A) A web browser implementer desires to certify their WebGL
+ implementation as conformant.
+
+ B) A GPU manufacturer delivering an embedded system including web
+ browser with WebGL support desires to certify their WebGL
+ implementation as conformant.
+
+Each of these situations carries different constraints, so the
+conformance rules are phrased differently for each. Typically, a web
+browser implementer aims to certify that the WebGL "layer" is correct.
+A GPU vendor typically aims to certify that a given device is
+physically capable of passing the tests.
+
+A newly-developed WebGL implementation should not support the "webgl"
+HTML Canvas context type by default in a shipping version of the
+product until reaching conformance. It is acceptable to give end users
+an option to turn on WebGL support in a non-conformant implementation
+as long as the documentation for that option clearly indicates that
+the implementation is not yet conformant and may have compatibility
+issues. It is suggested that the Canvas context type
+"experimental-webgl" may be supported by default in such
+implementations.
+
+A WebGL implementation might reach conformance, but a subsequent
+graphics driver release on a particular OS might introduce a
+regression causing failures of one or more of the WebGL conformance
+tests. In this situation it is not required to revoke support for the
+"webgl" HTML Canvas context type. The WebGL implementer should work
+with the GPU vendor to ensure the driver regression is fixed. A
+situation like this would, however, prevent the WebGL implementer from
+conforming to a subsequent version of the test suite.
+
+(A) Conformance Rules for a Web Browser Implementer
+===================================================
+
+1. Conformance on a particular operating system
+
+On a given OS, a WebGL implementation will be considered to conform to
+a particular version of the conformance suite if the suite passes with
+no test failures on at least two GPUs, each from a different
+vendor. If the OS only supports a GPU from one vendor, the two-GPU
+requirement is dropped.
+
+2. Conformance across multiple operating systems
+
+A WebGL implementation will be considered to conform to a particular
+version of the conformance suite if it passes rule (1) on all of the
+OSs on which the WebGL implementation is intended to be supported.
+
+3. Conformance as the web browser is upgraded
+
+WebGL conformance results submitted for an earlier version of the
+browser carry forward to later versions of the browser that do not
+cause any previously passing test to fail.
+
+4. Conformance as the operating system is upgraded
+
+If a new version is released of one of the OSs on which a WebGL
+implementation is intended to run, then WebGL conformance results
+submitted for earlier versions of that OS carry forward. Future
+conformance results must be submitted against the new version of the
+OS. If it is anticipated that the older OS version will be supported
+for some time, then future conformance results must be submitted
+separately for both the old and new versions of the OS.
+
+(B) Conformance Rules for a GPU Vendor
+======================================
+
+A GPU vendor submitting conformance results for a WebGL implementation
+typically does so because the device containing the GPU includes a
+built-in web browser. In this case the following rules apply:
+
+1. Conformance results must be submitted for each GPU and operating
+system combination to be certified. It is not required to submit
+results for different devices containing the same GPU and running the
+same operating system that do not cause any previously passing test to
+fail.
+
+2. Conformance results carry forward for a given GPU as the operating
+system and graphics driver are upgraded but do not cause any previously
+passing test to fail.
+
+Discussion
+==========
+
+A WebGL implementation intended to ship on three OSs may reach
+conformance on two of them, but due to graphics driver bugs, may be
+unable to reach conformance on the third. In this situation the
+implementation is not yet considered to be conformant.
+
+An existing WebGL implementation which conformed to an earlier version
+of the test suite is not required to remove support for the "webgl"
+HTML Canvas context type while in the process of conforming to a later
+version of the test suite. However, the implementer must not advertise
+conformance to the later version until it has been reached. It is
+acceptable for the implementer to advertise details of their
+conformance, for example number or percentage of passing or failing
+tests, or names of passing or failing tests.
+
+A GPU vendor might submit conformance results in order to use the
+WebGL logo in a marketing campaign. In this situation, results may be
+submitted in advance of the product becoming available through sales
+channels, per the rules above.
+
+The WebGL API has strict security requirements. Even one failing test
+may indicate a serious security issue in the WebGL implementation. For
+this reason, no exceptions for failing conformance tests will be
+granted.
+
+The Khronos Group determines whether a particular WebGL implementation
+is conformant based on the implementer's conformance suite
+submissions, on multiple OSs and on multiple GPUs as necessary, using
+the rules above. An implementer shall not judge their own
+implementation conformant simply by applying the above rules.
diff --git a/dom/canvas/test/webgl-conf/checkout/README.md b/dom/canvas/test/webgl-conf/checkout/README.md
new file mode 100644
index 0000000000..72e58db893
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/README.md
@@ -0,0 +1,94 @@
+Welcome to the WebGL Conformance Test Suite
+===========================================
+
+Note: Before adding a new test or editing an existing test
+[please read these guidelines](test-guidelines.md).
+
+This is the WebGL conformance test suite. You can find a the current "live"
+version at [https://www.khronos.org/registry/webgl/sdk/tests/webgl-conformance-tests.html](https://www.khronos.org/registry/webgl/sdk/tests/webgl-conformance-tests.html)
+
+NOTE TO USERS: Unless you are a WebGL implementor, there is no need to submit
+a conformance result using this process. Should you discover bugs in your
+browser's WebGL implementation, either via this test suite or otherwise,
+please report them through your browser vendor's bug tracking system.
+
+FOR WEBGL IMPLEMENTORS: Please follow the instructions below to create
+a formal conformance submission:
+
+1. Open webgl-conformance-tests.html in your target browser
+
+2. Press the "run tests" button
+
+3. At the end of the run, press "display text summary"
+
+4. Verify that the User Agent and WebGL renderer strings identify your browser and target correctly.
+
+5. Submit a PR with the results to [https://github.com/KhronosGroup/WebGLConformanceSubmissions].
+
+Please see CONFORMANCE_RULES.txt in this directory for guidelines
+about what constitutes a conformant WebGL implementation.
+
+Usage Notes:
+------------
+
+There are various URL options you can pass in:
+
+ run: Set to 1 to start the tests automatically
+
+ Example: webgl-conformance-tests.html?run=1
+
+ version: Set to the version of the harness you wish to run. Tests
+ at this version or below will be run
+
+ Example: webgl-conformance-tests.html?version=1.3.2
+
+ minVersion: Set to the minimum version of each test to include. Only tests
+ at this version or above will be included.
+
+ Example: webgl-conformance-tests.html?minVersion=1.3.2
+
+ fast: Only run tests not marked with --slow
+
+ Example: webgl-conformance-tests.html?fast=true
+
+ skip: Comma separated list of regular expressions of which tests to skip.
+
+ Example: webgl-conformance-tests.html?skip=glsl,.*destruction\.html
+
+ include: Comma separated list of regular expressions of which tests to include.
+
+ Example: webgl-conformance-tests.html?include=glsl,.*destruction\.html
+
+ frames: The number of iframes to use to run tests in parallel.
+
+ Example: webgl-conformance-tests.html?frames=8
+
+ Note the tests are not required to run with anything other than frames = 1.
+
+To individual tests you can pass:
+
+ showRenderer: 1 to show the renderer or unmasked renderer if `WEBGL_debug_renderer_info`
+ is available
+
+ runUntilFail: 1 to re-run the test until it fails
+
+ Also, all of [the context creation attributes](https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.2
+
+ Example: some-test.html?powerPreference=high-performance&antialias=false&depth=false
+
+The tests at https://www.khronos.org/registry/webgl/sdk/tests/ are kept up-to-date with a GitHub webhook. If you suspect these tests are not in sync with GitHub, please verify the webhook log file here:
+
+ https://www.khronos.org/webgl/pull-github/logs/github.log
+
+History
+-------
+
+The dates below are when work on the conformance suite version was started.
+
+- 2011/02/24: Version 1.0.0
+- 2012/02/23: Version 1.0.1
+- 2012/03/20: Version 1.0.2
+- 2013/02/14: Version 1.0.3
+- 2013/10/11: Version 2.0.0
+- 2014/11/14: Version 1.0.4
+- 2016/11/21: Version 2.0.1
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/AUTHORS b/dom/canvas/test/webgl-conf/checkout/closure-library/AUTHORS
new file mode 100644
index 0000000000..d5fa71f80e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/AUTHORS
@@ -0,0 +1,19 @@
+# This is a list of contributors to the Closure Library.
+
+# Names should be added to this file like so:
+# Name or Organization <email address>
+
+Google Inc.
+Stellar Science Ltd.
+Mohamed Mansour <hello@mohamedmansour.com>
+Bjorn Tipling <bjorn.tipling@gmail.com>
+SameGoal LLC <help@samegoal.com>
+Guido Tapia <guido.tapia@gmail.com>
+Andrew Mattie <amattie@gmail.com>
+Ilia Mirkin <ibmirkin@gmail.com>
+Ivan Kozik <ivan.kozik@gmail.com>
+Rich Dougherty <rich@rd.gen.nz>
+Chad Killingsworth <chadkillingsworth@missouristate.edu>
+Dan Pupius <dan.pupius@gmail.com>
+Mike Dunn <dunn74@gmail.com>
+Kengo Toda <skypencil@gmail.com>
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/CONTRIBUTING b/dom/canvas/test/webgl-conf/checkout/closure-library/CONTRIBUTING
new file mode 100644
index 0000000000..bab94181df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/CONTRIBUTING
@@ -0,0 +1,48 @@
+Closure Library welcomes patches/pulls for features and bugfixes.
+
+For contributors inside Google, follow the instructions given here:
+http://go/closure-contributors
+
+For contributors external to Google, follow the instructions given here:
+
+Notes on Contributions to Closure Library
+
+Google Individual Contributor License
+
+In all cases, contributors must sign a contributor license agreement,
+either for an individual or corporation, before a patch can be
+accepted. Please fill out the agreement for an individual or a
+corporation, as appropriate.
+
+https://developers.google.com/open-source/cla/individual
+https://developers.google.com/open-source/cla/corporate
+
+If you or your organization is not listed there already, you should
+add an entry to the AUTHORS file as part of your patch.
+
+If you plan to add a significant component or large chunk of code, it
+is recommended to bring it up on the discussion list for a design
+discussion before writing code.
+
+If appropriate, write a unit test that demonstrates your patch. Tests are the
+best way to ensure that future contributors do not break your code
+accidentally.
+
+To change the Closure Library source, you must submit a pull request
+in GitHub. See the GitHub documentation here:
+
+https://help.github.com/categories/63/articles
+
+Closure Library developers monitor outstanding pull requests. They may
+request changes on the pull request before accepting. They will also
+verify that the CLA has been signed.
+
+Oftentimes, the pull request will not be directly merged, but patched to
+the internal Google codebase to verify that unit and integration tests
+will Closure pass before submitting (and optionally make changes to
+the patch to match style, fix text, or to make the code or comments
+clearer). In this case, the issue associated with the pull request
+will be closed when the patch pushed to the repository via the MOE
+(Make Open Easy) system.
+
+https://code.google.com/p/moe-java/
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/LICENSE b/dom/canvas/test/webgl-conf/checkout/closure-library/LICENSE
new file mode 100644
index 0000000000..d9a10c0d8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/LICENSE
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/README-Khronos.txt b/dom/canvas/test/webgl-conf/checkout/closure-library/README-Khronos.txt
new file mode 100644
index 0000000000..64d81e51cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/README-Khronos.txt
@@ -0,0 +1,20 @@
+This is a partial snapshot of the Closure library workspace from:
+
+ https://github.com/google/closure-library
+
+It contains only the portions needed to type check the ported dEQP
+tests, namely:
+
+ closure/goog/base.js
+ closure/goog/deps.js
+
+and supporting scripts in closure/bin/ .
+
+The current version snapshotted here is:
+
+-----
+commit 57bdfe0093cc158fb3a58d2c5f7d75ece8c4b45b
+Author: Nathan Naze <nanaze@gmail.com>
+Date: Fri Apr 24 18:38:26 2015 -0400
+
+ fix bad merge
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/README.md b/dom/canvas/test/webgl-conf/checkout/closure-library/README.md
new file mode 100644
index 0000000000..d794d1b9b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/README.md
@@ -0,0 +1,9 @@
+# Closure Library
+
+Closure Library is a powerful, low-level JavaScript library designed
+for building complex and scalable web applications. It is used by many
+Google web applications, such as Gmail and Google Docs.
+
+For more information, visit the
+[Google Developers](https://developers.google.com/closure/library) or
+[GitHub](https://github.com/google/closure-library) sites.
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/closurebuilder.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/closurebuilder.py
new file mode 100755
index 0000000000..9e4e2eb339
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/closurebuilder.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Utility for Closure Library dependency calculation.
+
+ClosureBuilder scans source files to build dependency info. From the
+dependencies, the script can produce a manifest in dependency order,
+a concatenated script, or compiled output from the Closure Compiler.
+
+Paths to files can be expressed as individual arguments to the tool (intended
+for use with find and xargs). As a convenience, --root can be used to specify
+all JS files below a directory.
+
+usage: %prog [options] [file1.js file2.js ...]
+"""
+
+__author__ = 'nnaze@google.com (Nathan Naze)'
+
+
+import logging
+import optparse
+import os
+import sys
+
+import depstree
+import jscompiler
+import source
+import treescan
+
+
+def _GetOptionsParser():
+ """Get the options parser."""
+
+ parser = optparse.OptionParser(__doc__)
+ parser.add_option('-i',
+ '--input',
+ dest='inputs',
+ action='append',
+ default=[],
+ help='One or more input files to calculate dependencies '
+ 'for. The namespaces in this file will be combined with '
+ 'those given with the -n flag to form the set of '
+ 'namespaces to find dependencies for.')
+ parser.add_option('-n',
+ '--namespace',
+ dest='namespaces',
+ action='append',
+ default=[],
+ help='One or more namespaces to calculate dependencies '
+ 'for. These namespaces will be combined with those given '
+ 'with the -i flag to form the set of namespaces to find '
+ 'dependencies for. A Closure namespace is a '
+ 'dot-delimited path expression declared with a call to '
+ 'goog.provide() (e.g. "goog.array" or "foo.bar").')
+ parser.add_option('--root',
+ dest='roots',
+ action='append',
+ default=[],
+ help='The paths that should be traversed to build the '
+ 'dependencies.')
+ parser.add_option('-o',
+ '--output_mode',
+ dest='output_mode',
+ type='choice',
+ action='store',
+ choices=['list', 'script', 'compiled'],
+ default='list',
+ help='The type of output to generate from this script. '
+ 'Options are "list" for a list of filenames, "script" '
+ 'for a single script containing the contents of all the '
+ 'files, or "compiled" to produce compiled output with '
+ 'the Closure Compiler. Default is "list".')
+ parser.add_option('-c',
+ '--compiler_jar',
+ dest='compiler_jar',
+ action='store',
+ help='The location of the Closure compiler .jar file.')
+ parser.add_option('-f',
+ '--compiler_flags',
+ dest='compiler_flags',
+ default=[],
+ action='append',
+ help='Additional flags to pass to the Closure compiler. '
+ 'To pass multiple flags, --compiler_flags has to be '
+ 'specified multiple times.')
+ parser.add_option('-j',
+ '--jvm_flags',
+ dest='jvm_flags',
+ default=[],
+ action='append',
+ help='Additional flags to pass to the JVM compiler. '
+ 'To pass multiple flags, --jvm_flags has to be '
+ 'specified multiple times.')
+ parser.add_option('--output_file',
+ dest='output_file',
+ action='store',
+ help=('If specified, write output to this path instead of '
+ 'writing to standard output.'))
+
+ return parser
+
+
+def _GetInputByPath(path, sources):
+ """Get the source identified by a path.
+
+ Args:
+ path: str, A path to a file that identifies a source.
+ sources: An iterable collection of source objects.
+
+ Returns:
+ The source from sources identified by path, if found. Converts to
+ real paths for comparison.
+ """
+ for js_source in sources:
+ # Convert both to real paths for comparison.
+ if os.path.realpath(path) == os.path.realpath(js_source.GetPath()):
+ return js_source
+
+
+def _GetClosureBaseFile(sources):
+ """Given a set of sources, returns the one base.js file.
+
+ Note that if zero or two or more base.js files are found, an error message
+ will be written and the program will be exited.
+
+ Args:
+ sources: An iterable of _PathSource objects.
+
+ Returns:
+ The _PathSource representing the base Closure file.
+ """
+ base_files = [
+ js_source for js_source in sources if _IsClosureBaseFile(js_source)]
+
+ if not base_files:
+ logging.error('No Closure base.js file found.')
+ sys.exit(1)
+ if len(base_files) > 1:
+ logging.error('More than one Closure base.js files found at these paths:')
+ for base_file in base_files:
+ logging.error(base_file.GetPath())
+ sys.exit(1)
+ return base_files[0]
+
+
+def _IsClosureBaseFile(js_source):
+ """Returns true if the given _PathSource is the Closure base.js source."""
+ return (os.path.basename(js_source.GetPath()) == 'base.js' and
+ js_source.provides == set(['goog']))
+
+
+class _PathSource(source.Source):
+ """Source file subclass that remembers its file path."""
+
+ def __init__(self, path):
+ """Initialize a source.
+
+ Args:
+ path: str, Path to a JavaScript file. The source string will be read
+ from this file.
+ """
+ super(_PathSource, self).__init__(source.GetFileContents(path))
+
+ self._path = path
+
+ def __str__(self):
+ return 'PathSource %s' % self._path
+
+ def GetPath(self):
+ """Returns the path."""
+ return self._path
+
+
+def _WrapGoogModuleSource(src):
+ return ('goog.loadModule(function(exports) {{'
+ '"use strict";'
+ '{0}'
+ '\n' # terminate any trailing single line comment.
+ ';return exports'
+ '}});\n').format(src)
+
+
+def main():
+ logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
+ level=logging.INFO)
+ options, args = _GetOptionsParser().parse_args()
+
+ # Make our output pipe.
+ if options.output_file:
+ out = open(options.output_file, 'w')
+ else:
+ out = sys.stdout
+
+ sources = set()
+
+ logging.info('Scanning paths...')
+ for path in options.roots:
+ for js_path in treescan.ScanTreeForJsFiles(path):
+ sources.add(_PathSource(js_path))
+
+ # Add scripts specified on the command line.
+ for js_path in args:
+ sources.add(_PathSource(js_path))
+
+ logging.info('%s sources scanned.', len(sources))
+
+ # Though deps output doesn't need to query the tree, we still build it
+ # to validate dependencies.
+ logging.info('Building dependency tree..')
+ tree = depstree.DepsTree(sources)
+
+ input_namespaces = set()
+ inputs = options.inputs or []
+ for input_path in inputs:
+ js_input = _GetInputByPath(input_path, sources)
+ if not js_input:
+ logging.error('No source matched input %s', input_path)
+ sys.exit(1)
+ input_namespaces.update(js_input.provides)
+
+ input_namespaces.update(options.namespaces)
+
+ if not input_namespaces:
+ logging.error('No namespaces found. At least one namespace must be '
+ 'specified with the --namespace or --input flags.')
+ sys.exit(2)
+
+ # The Closure Library base file must go first.
+ base = _GetClosureBaseFile(sources)
+ deps = [base] + tree.GetDependencies(input_namespaces)
+
+ output_mode = options.output_mode
+ if output_mode == 'list':
+ out.writelines([js_source.GetPath() + '\n' for js_source in deps])
+ elif output_mode == 'script':
+ for js_source in deps:
+ src = js_source.GetSource()
+ if js_source.is_goog_module:
+ src = _WrapGoogModuleSource(src)
+ out.write(src + '\n')
+ elif output_mode == 'compiled':
+ logging.warning("""\
+Closure Compiler now natively understands and orders Closure dependencies and
+is prefererred over using this script for performing JavaScript compilation.
+
+Please migrate your codebase.
+
+See:
+https://github.com/google/closure-compiler/wiki/Manage-Closure-Dependencies
+""")
+
+ # Make sure a .jar is specified.
+ if not options.compiler_jar:
+ logging.error('--compiler_jar flag must be specified if --output is '
+ '"compiled"')
+ sys.exit(2)
+
+ # Will throw an error if the compilation fails.
+ compiled_source = jscompiler.Compile(
+ options.compiler_jar,
+ [js_source.GetPath() for js_source in deps],
+ jvm_flags=options.jvm_flags,
+ compiler_flags=options.compiler_flags)
+
+ logging.info('JavaScript compilation succeeded.')
+ out.write(compiled_source)
+
+ else:
+ logging.error('Invalid value for --output flag.')
+ sys.exit(2)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depstree.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depstree.py
new file mode 100755
index 0000000000..f288dd3aa6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depstree.py
@@ -0,0 +1,189 @@
+# Copyright 2009 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Class to represent a full Closure Library dependency tree.
+
+Offers a queryable tree of dependencies of a given set of sources. The tree
+will also do logical validation to prevent duplicate provides and circular
+dependencies.
+"""
+
+__author__ = 'nnaze@google.com (Nathan Naze)'
+
+
+class DepsTree(object):
+ """Represents the set of dependencies between source files."""
+
+ def __init__(self, sources):
+ """Initializes the tree with a set of sources.
+
+ Args:
+ sources: A set of JavaScript sources.
+
+ Raises:
+ MultipleProvideError: A namespace is provided by muplitple sources.
+ NamespaceNotFoundError: A namespace is required but never provided.
+ """
+
+ self._sources = sources
+ self._provides_map = dict()
+
+ # Ensure nothing was provided twice.
+ for source in sources:
+ for provide in source.provides:
+ if provide in self._provides_map:
+ raise MultipleProvideError(
+ provide, [self._provides_map[provide], source])
+
+ self._provides_map[provide] = source
+
+ # Check that all required namespaces are provided.
+ for source in sources:
+ for require in source.requires:
+ if require not in self._provides_map:
+ raise NamespaceNotFoundError(require, source)
+
+ def GetDependencies(self, required_namespaces):
+ """Get source dependencies, in order, for the given namespaces.
+
+ Args:
+ required_namespaces: A string (for one) or list (for one or more) of
+ namespaces.
+
+ Returns:
+ A list of source objects that provide those namespaces and all
+ requirements, in dependency order.
+
+ Raises:
+ NamespaceNotFoundError: A namespace is requested but doesn't exist.
+ CircularDependencyError: A cycle is detected in the dependency tree.
+ """
+ if isinstance(required_namespaces, str):
+ required_namespaces = [required_namespaces]
+
+ deps_sources = []
+
+ for namespace in required_namespaces:
+ for source in DepsTree._ResolveDependencies(
+ namespace, [], self._provides_map, []):
+ if source not in deps_sources:
+ deps_sources.append(source)
+
+ return deps_sources
+
+ @staticmethod
+ def _ResolveDependencies(required_namespace, deps_list, provides_map,
+ traversal_path):
+ """Resolve dependencies for Closure source files.
+
+ Follows the dependency tree down and builds a list of sources in dependency
+ order. This function will recursively call itself to fill all dependencies
+ below the requested namespaces, and then append its sources at the end of
+ the list.
+
+ Args:
+ required_namespace: String of required namespace.
+ deps_list: List of sources in dependency order. This function will append
+ the required source once all of its dependencies are satisfied.
+ provides_map: Map from namespace to source that provides it.
+ traversal_path: List of namespaces of our path from the root down the
+ dependency/recursion tree. Used to identify cyclical dependencies.
+ This is a list used as a stack -- when the function is entered, the
+ current namespace is pushed and popped right before returning.
+ Each recursive call will check that the current namespace does not
+ appear in the list, throwing a CircularDependencyError if it does.
+
+ Returns:
+ The given deps_list object filled with sources in dependency order.
+
+ Raises:
+ NamespaceNotFoundError: A namespace is requested but doesn't exist.
+ CircularDependencyError: A cycle is detected in the dependency tree.
+ """
+
+ source = provides_map.get(required_namespace)
+ if not source:
+ raise NamespaceNotFoundError(required_namespace)
+
+ if required_namespace in traversal_path:
+ traversal_path.append(required_namespace) # do this *after* the test
+
+ # This must be a cycle.
+ raise CircularDependencyError(traversal_path)
+
+ # If we don't have the source yet, we'll have to visit this namespace and
+ # add the required dependencies to deps_list.
+ if source not in deps_list:
+ traversal_path.append(required_namespace)
+
+ for require in source.requires:
+
+ # Append all other dependencies before we append our own.
+ DepsTree._ResolveDependencies(require, deps_list, provides_map,
+ traversal_path)
+ deps_list.append(source)
+
+ traversal_path.pop()
+
+ return deps_list
+
+
+class BaseDepsTreeError(Exception):
+ """Base DepsTree error."""
+
+ def __init__(self):
+ Exception.__init__(self)
+
+
+class CircularDependencyError(BaseDepsTreeError):
+ """Raised when a dependency cycle is encountered."""
+
+ def __init__(self, dependency_list):
+ BaseDepsTreeError.__init__(self)
+ self._dependency_list = dependency_list
+
+ def __str__(self):
+ return ('Encountered circular dependency:\n%s\n' %
+ '\n'.join(self._dependency_list))
+
+
+class MultipleProvideError(BaseDepsTreeError):
+ """Raised when a namespace is provided more than once."""
+
+ def __init__(self, namespace, sources):
+ BaseDepsTreeError.__init__(self)
+ self._namespace = namespace
+ self._sources = sources
+
+ def __str__(self):
+ source_strs = map(str, self._sources)
+
+ return ('Namespace "%s" provided more than once in sources:\n%s\n' %
+ (self._namespace, '\n'.join(source_strs)))
+
+
+class NamespaceNotFoundError(BaseDepsTreeError):
+ """Raised when a namespace is requested but not provided."""
+
+ def __init__(self, namespace, source=None):
+ BaseDepsTreeError.__init__(self)
+ self._namespace = namespace
+ self._source = source
+
+ def __str__(self):
+ msg = 'Namespace "%s" never provided.' % self._namespace
+ if self._source:
+ msg += ' Required in %s' % self._source
+ return msg
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depswriter.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depswriter.py
new file mode 100755
index 0000000000..bc3be88a35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/depswriter.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Generates out a Closure deps.js file given a list of JavaScript sources.
+
+Paths can be specified as arguments or (more commonly) specifying trees
+with the flags (call with --help for descriptions).
+
+Usage: depswriter.py [path/to/js1.js [path/to/js2.js] ...]
+"""
+
+import logging
+import optparse
+import os
+import posixpath
+import shlex
+import sys
+
+import source
+import treescan
+
+
+__author__ = 'nnaze@google.com (Nathan Naze)'
+
+
+def MakeDepsFile(source_map):
+ """Make a generated deps file.
+
+ Args:
+ source_map: A dict map of the source path to source.Source object.
+
+ Returns:
+ str, A generated deps file source.
+ """
+
+ # Write in path alphabetical order
+ paths = sorted(source_map.keys())
+
+ lines = []
+
+ for path in paths:
+ js_source = source_map[path]
+
+ # We don't need to add entries that don't provide anything.
+ if js_source.provides:
+ lines.append(_GetDepsLine(path, js_source))
+
+ return ''.join(lines)
+
+
+def _GetDepsLine(path, js_source):
+ """Get a deps.js file string for a source."""
+
+ provides = sorted(js_source.provides)
+ requires = sorted(js_source.requires)
+ module = 'true' if js_source.is_goog_module else 'false'
+
+ return 'goog.addDependency(\'%s\', %s, %s, %s);\n' % (
+ path, provides, requires, module)
+
+
+def _GetOptionsParser():
+ """Get the options parser."""
+
+ parser = optparse.OptionParser(__doc__)
+
+ parser.add_option('--output_file',
+ dest='output_file',
+ action='store',
+ help=('If specified, write output to this path instead of '
+ 'writing to standard output.'))
+ parser.add_option('--root',
+ dest='roots',
+ default=[],
+ action='append',
+ help='A root directory to scan for JS source files. '
+ 'Paths of JS files in generated deps file will be '
+ 'relative to this path. This flag may be specified '
+ 'multiple times.')
+ parser.add_option('--root_with_prefix',
+ dest='roots_with_prefix',
+ default=[],
+ action='append',
+ help='A root directory to scan for JS source files, plus '
+ 'a prefix (if either contains a space, surround with '
+ 'quotes). Paths in generated deps file will be relative '
+ 'to the root, but preceded by the prefix. This flag '
+ 'may be specified multiple times.')
+ parser.add_option('--path_with_depspath',
+ dest='paths_with_depspath',
+ default=[],
+ action='append',
+ help='A path to a source file and an alternate path to '
+ 'the file in the generated deps file (if either contains '
+ 'a space, surround with whitespace). This flag may be '
+ 'specified multiple times.')
+ return parser
+
+
+def _NormalizePathSeparators(path):
+ """Replaces OS-specific path separators with POSIX-style slashes.
+
+ Args:
+ path: str, A file path.
+
+ Returns:
+ str, The path with any OS-specific path separators (such as backslash on
+ Windows) replaced with URL-compatible forward slashes. A no-op on systems
+ that use POSIX paths.
+ """
+ return path.replace(os.sep, posixpath.sep)
+
+
+def _GetRelativePathToSourceDict(root, prefix=''):
+ """Scans a top root directory for .js sources.
+
+ Args:
+ root: str, Root directory.
+ prefix: str, Prefix for returned paths.
+
+ Returns:
+ dict, A map of relative paths (with prefix, if given), to source.Source
+ objects.
+ """
+ # Remember and restore the cwd when we're done. We work from the root so
+ # that paths are relative from the root.
+ start_wd = os.getcwd()
+ os.chdir(root)
+
+ path_to_source = {}
+ for path in treescan.ScanTreeForJsFiles('.'):
+ prefixed_path = _NormalizePathSeparators(os.path.join(prefix, path))
+ path_to_source[prefixed_path] = source.Source(source.GetFileContents(path))
+
+ os.chdir(start_wd)
+
+ return path_to_source
+
+
+def _GetPair(s):
+ """Return a string as a shell-parsed tuple. Two values expected."""
+ try:
+ # shlex uses '\' as an escape character, so they must be escaped.
+ s = s.replace('\\', '\\\\')
+ first, second = shlex.split(s)
+ return (first, second)
+ except:
+ raise Exception('Unable to parse input line as a pair: %s' % s)
+
+
+def main():
+ """CLI frontend to MakeDepsFile."""
+ logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
+ level=logging.INFO)
+ options, args = _GetOptionsParser().parse_args()
+
+ path_to_source = {}
+
+ # Roots without prefixes
+ for root in options.roots:
+ path_to_source.update(_GetRelativePathToSourceDict(root))
+
+ # Roots with prefixes
+ for root_and_prefix in options.roots_with_prefix:
+ root, prefix = _GetPair(root_and_prefix)
+ path_to_source.update(_GetRelativePathToSourceDict(root, prefix=prefix))
+
+ # Source paths
+ for path in args:
+ path_to_source[path] = source.Source(source.GetFileContents(path))
+
+ # Source paths with alternate deps paths
+ for path_with_depspath in options.paths_with_depspath:
+ srcpath, depspath = _GetPair(path_with_depspath)
+ path_to_source[depspath] = source.Source(source.GetFileContents(srcpath))
+
+ # Make our output pipe.
+ if options.output_file:
+ out = open(options.output_file, 'w')
+ else:
+ out = sys.stdout
+
+ out.write('// This file was autogenerated by %s.\n' % sys.argv[0])
+ out.write('// Please do not edit.\n')
+
+ out.write(MakeDepsFile(path_to_source))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/jscompiler.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/jscompiler.py
new file mode 100644
index 0000000000..cc6eb55f9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/jscompiler.py
@@ -0,0 +1,135 @@
+# Copyright 2010 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Utility to use the Closure Compiler CLI from Python."""
+
+
+import logging
+import os
+import re
+import subprocess
+
+
+# Pulls just the major and minor version numbers from the first line of
+# 'java -version'. Versions are in the format of [0-9]+\.[0-9]+\..* See:
+# http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
+_VERSION_REGEX = re.compile(r'"([0-9]+)\.([0-9]+)')
+
+
+class JsCompilerError(Exception):
+ """Raised if there's an error in calling the compiler."""
+ pass
+
+
+def _GetJavaVersionString():
+ """Get the version string from the Java VM."""
+ return subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT)
+
+
+def _ParseJavaVersion(version_string):
+ """Returns a 2-tuple for the current version of Java installed.
+
+ Args:
+ version_string: String of the Java version (e.g. '1.7.2-ea').
+
+ Returns:
+ The major and minor versions, as a 2-tuple (e.g. (1, 7)).
+ """
+ match = _VERSION_REGEX.search(version_string)
+ if match:
+ version = tuple(int(x, 10) for x in match.groups())
+ assert len(version) == 2
+ return version
+
+
+def _JavaSupports32BitMode():
+ """Determines whether the JVM supports 32-bit mode on the platform."""
+ # Suppresses process output to stderr and stdout from showing up in the
+ # console as we're only trying to determine 32-bit JVM support.
+ supported = False
+ try:
+ devnull = open(os.devnull, 'wb')
+ return subprocess.call(
+ ['java', '-d32', '-version'], stdout=devnull, stderr=devnull) == 0
+ except IOError:
+ pass
+ else:
+ devnull.close()
+ return supported
+
+
+def _GetJsCompilerArgs(compiler_jar_path, java_version, source_paths,
+ jvm_flags, compiler_flags):
+ """Assembles arguments for call to JsCompiler."""
+
+ if java_version < (1, 7):
+ raise JsCompilerError('Closure Compiler requires Java 1.7 or higher. '
+ 'Please visit http://www.java.com/getjava')
+
+ args = ['java']
+
+ # Add JVM flags we believe will produce the best performance. See
+ # https://groups.google.com/forum/#!topic/closure-library-discuss/7w_O9-vzlj4
+
+ # Attempt 32-bit mode if available (Java 7 on Mac OS X does not support 32-bit
+ # mode, for example).
+ if _JavaSupports32BitMode():
+ args += ['-d32']
+
+ # Prefer the "client" VM.
+ args += ['-client']
+
+ # Add JVM flags, if any
+ if jvm_flags:
+ args += jvm_flags
+
+ # Add the application JAR.
+ args += ['-jar', compiler_jar_path]
+
+ for path in source_paths:
+ args += ['--js', path]
+
+ # Add compiler flags, if any.
+ if compiler_flags:
+ args += compiler_flags
+
+ return args
+
+
+def Compile(compiler_jar_path, source_paths,
+ jvm_flags=None,
+ compiler_flags=None):
+ """Prepares command-line call to Closure Compiler.
+
+ Args:
+ compiler_jar_path: Path to the Closure compiler .jar file.
+ source_paths: Source paths to build, in order.
+ jvm_flags: A list of additional flags to pass on to JVM.
+ compiler_flags: A list of additional flags to pass on to Closure Compiler.
+
+ Returns:
+ The compiled source, as a string, or None if compilation failed.
+ """
+
+ java_version = _ParseJavaVersion(_GetJavaVersionString())
+
+ args = _GetJsCompilerArgs(
+ compiler_jar_path, java_version, source_paths, jvm_flags, compiler_flags)
+
+ logging.info('Compiling with the following command: %s', ' '.join(args))
+
+ try:
+ return subprocess.check_output(args)
+ except subprocess.CalledProcessError:
+ raise JsCompilerError('JavaScript compilation failed.')
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/source.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/source.py
new file mode 100644
index 0000000000..be5e0d8ad6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/source.py
@@ -0,0 +1,127 @@
+# Copyright 2009 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Scans a source JS file for its provided and required namespaces.
+
+Simple class to scan a JavaScript file and express its dependencies.
+"""
+
+__author__ = 'nnaze@google.com'
+
+
+import re
+
+_BASE_REGEX_STRING = r'^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
+_MODULE_REGEX = re.compile(_BASE_REGEX_STRING % 'module')
+_PROVIDE_REGEX = re.compile(_BASE_REGEX_STRING % 'provide')
+
+_REQUIRE_REGEX_STRING = (r'^\s*(?:(?:var|let|const)\s+[a-zA-Z_$][a-zA-Z0-9$_]*'
+ r'\s*=\s*)?goog\.require\(\s*[\'"](.+)[\'"]\s*\)')
+_REQUIRES_REGEX = re.compile(_REQUIRE_REGEX_STRING)
+
+
+class Source(object):
+ """Scans a JavaScript source for its provided and required namespaces."""
+
+ # Matches a "/* ... */" comment.
+ # Note: We can't definitively distinguish a "/*" in a string literal without a
+ # state machine tokenizer. We'll assume that a line starting with whitespace
+ # and "/*" is a comment.
+ _COMMENT_REGEX = re.compile(
+ r"""
+ ^\s* # Start of a new line and whitespace
+ /\* # Opening "/*"
+ .*? # Non greedy match of any characters (including newlines)
+ \*/ # Closing "*/""",
+ re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+ def __init__(self, source):
+ """Initialize a source.
+
+ Args:
+ source: str, The JavaScript source.
+ """
+
+ self.provides = set()
+ self.requires = set()
+ self.is_goog_module = False
+
+ self._source = source
+ self._ScanSource()
+
+ def GetSource(self):
+ """Get the source as a string."""
+ return self._source
+
+ @classmethod
+ def _StripComments(cls, source):
+ return cls._COMMENT_REGEX.sub('', source)
+
+ @classmethod
+ def _HasProvideGoogFlag(cls, source):
+ """Determines whether the @provideGoog flag is in a comment."""
+ for comment_content in cls._COMMENT_REGEX.findall(source):
+ if '@provideGoog' in comment_content:
+ return True
+
+ return False
+
+ def _ScanSource(self):
+ """Fill in provides and requires by scanning the source."""
+
+ stripped_source = self._StripComments(self.GetSource())
+
+ source_lines = stripped_source.splitlines()
+ for line in source_lines:
+ match = _PROVIDE_REGEX.match(line)
+ if match:
+ self.provides.add(match.group(1))
+ match = _MODULE_REGEX.match(line)
+ if match:
+ self.provides.add(match.group(1))
+ self.is_goog_module = True
+ match = _REQUIRES_REGEX.match(line)
+ if match:
+ self.requires.add(match.group(1))
+
+ # Closure's base file implicitly provides 'goog'.
+ # This is indicated with the @provideGoog flag.
+ if self._HasProvideGoogFlag(self.GetSource()):
+
+ if len(self.provides) or len(self.requires):
+ raise Exception(
+ 'Base file should not provide or require namespaces.')
+
+ self.provides.add('goog')
+
+
+def GetFileContents(path):
+ """Get a file's contents as a string.
+
+ Args:
+ path: str, Path to file.
+
+ Returns:
+ str, Contents of file.
+
+ Raises:
+ IOError: An error occurred opening or reading the file.
+
+ """
+ fileobj = open(path)
+ try:
+ return fileobj.read()
+ finally:
+ fileobj.close()
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/treescan.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/treescan.py
new file mode 100644
index 0000000000..6694593aab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/build/treescan.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Shared utility functions for scanning directory trees."""
+
+import os
+import re
+
+
+__author__ = 'nnaze@google.com (Nathan Naze)'
+
+
+# Matches a .js file path.
+_JS_FILE_REGEX = re.compile(r'^.+\.js$')
+
+
+def ScanTreeForJsFiles(root):
+ """Scans a directory tree for JavaScript files.
+
+ Args:
+ root: str, Path to a root directory.
+
+ Returns:
+ An iterable of paths to JS files, relative to cwd.
+ """
+ return ScanTree(root, path_filter=_JS_FILE_REGEX)
+
+
+def ScanTree(root, path_filter=None, ignore_hidden=True):
+ """Scans a directory tree for files.
+
+ Args:
+ root: str, Path to a root directory.
+ path_filter: A regular expression filter. If set, only paths matching
+ the path_filter are returned.
+ ignore_hidden: If True, do not follow or return hidden directories or files
+ (those starting with a '.' character).
+
+ Yields:
+ A string path to files, relative to cwd.
+ """
+
+ def OnError(os_error):
+ raise os_error
+
+ for dirpath, dirnames, filenames in os.walk(root, onerror=OnError):
+ # os.walk allows us to modify dirnames to prevent decent into particular
+ # directories. Avoid hidden directories.
+ for dirname in dirnames:
+ if ignore_hidden and dirname.startswith('.'):
+ dirnames.remove(dirname)
+
+ for filename in filenames:
+
+ # nothing that starts with '.'
+ if ignore_hidden and filename.startswith('.'):
+ continue
+
+ fullpath = os.path.join(dirpath, filename)
+
+ if path_filter and not path_filter.match(fullpath):
+ continue
+
+ yield os.path.normpath(fullpath)
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/calcdeps.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/calcdeps.py
new file mode 100755
index 0000000000..9cb1a6db06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/calcdeps.py
@@ -0,0 +1,590 @@
+#!/usr/bin/env python
+#
+# Copyright 2006 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Calculates JavaScript dependencies without requiring Google's build system.
+
+This tool is deprecated and is provided for legacy users.
+See build/closurebuilder.py and build/depswriter.py for the current tools.
+
+It iterates over a number of search paths and builds a dependency tree. With
+the inputs provided, it walks the dependency tree and outputs all the files
+required for compilation.
+"""
+
+
+
+
+
+try:
+ import distutils.version
+except ImportError:
+ # distutils is not available in all environments
+ distutils = None
+
+import logging
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+
+_BASE_REGEX_STRING = '^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
+req_regex = re.compile(_BASE_REGEX_STRING % 'require')
+prov_regex = re.compile(_BASE_REGEX_STRING % 'provide')
+ns_regex = re.compile('^ns:((\w+\.)*(\w+))$')
+version_regex = re.compile('[\.0-9]+')
+
+
+def IsValidFile(ref):
+ """Returns true if the provided reference is a file and exists."""
+ return os.path.isfile(ref)
+
+
+def IsJsFile(ref):
+ """Returns true if the provided reference is a Javascript file."""
+ return ref.endswith('.js')
+
+
+def IsNamespace(ref):
+ """Returns true if the provided reference is a namespace."""
+ return re.match(ns_regex, ref) is not None
+
+
+def IsDirectory(ref):
+ """Returns true if the provided reference is a directory."""
+ return os.path.isdir(ref)
+
+
+def ExpandDirectories(refs):
+ """Expands any directory references into inputs.
+
+ Description:
+ Looks for any directories in the provided references. Found directories
+ are recursively searched for .js files, which are then added to the result
+ list.
+
+ Args:
+ refs: a list of references such as files, directories, and namespaces
+
+ Returns:
+ A list of references with directories removed and replaced by any
+ .js files that are found in them. Also, the paths will be normalized.
+ """
+ result = []
+ for ref in refs:
+ if IsDirectory(ref):
+ # Disable 'Unused variable' for subdirs
+ # pylint: disable=unused-variable
+ for (directory, subdirs, filenames) in os.walk(ref):
+ for filename in filenames:
+ if IsJsFile(filename):
+ result.append(os.path.join(directory, filename))
+ else:
+ result.append(ref)
+ return map(os.path.normpath, result)
+
+
+class DependencyInfo(object):
+ """Represents a dependency that is used to build and walk a tree."""
+
+ def __init__(self, filename):
+ self.filename = filename
+ self.provides = []
+ self.requires = []
+
+ def __str__(self):
+ return '%s Provides: %s Requires: %s' % (self.filename,
+ repr(self.provides),
+ repr(self.requires))
+
+
+def BuildDependenciesFromFiles(files):
+ """Build a list of dependencies from a list of files.
+
+ Description:
+ Takes a list of files, extracts their provides and requires, and builds
+ out a list of dependency objects.
+
+ Args:
+ files: a list of files to be parsed for goog.provides and goog.requires.
+
+ Returns:
+ A list of dependency objects, one for each file in the files argument.
+ """
+ result = []
+ filenames = set()
+ for filename in files:
+ if filename in filenames:
+ continue
+
+ # Python 3 requires the file encoding to be specified
+ if (sys.version_info[0] < 3):
+ file_handle = open(filename, 'r')
+ else:
+ file_handle = open(filename, 'r', encoding='utf8')
+
+ try:
+ dep = CreateDependencyInfo(filename, file_handle)
+ result.append(dep)
+ finally:
+ file_handle.close()
+
+ filenames.add(filename)
+
+ return result
+
+
+def CreateDependencyInfo(filename, source):
+ """Create dependency info.
+
+ Args:
+ filename: Filename for source.
+ source: File-like object containing source.
+
+ Returns:
+ A DependencyInfo object with provides and requires filled.
+ """
+ dep = DependencyInfo(filename)
+ for line in source:
+ if re.match(req_regex, line):
+ dep.requires.append(re.search(req_regex, line).group(1))
+ if re.match(prov_regex, line):
+ dep.provides.append(re.search(prov_regex, line).group(1))
+ return dep
+
+
+def BuildDependencyHashFromDependencies(deps):
+ """Builds a hash for searching dependencies by the namespaces they provide.
+
+ Description:
+ Dependency objects can provide multiple namespaces. This method enumerates
+ the provides of each dependency and adds them to a hash that can be used
+ to easily resolve a given dependency by a namespace it provides.
+
+ Args:
+ deps: a list of dependency objects used to build the hash.
+
+ Raises:
+ Exception: If a multiple files try to provide the same namepace.
+
+ Returns:
+ A hash table { namespace: dependency } that can be used to resolve a
+ dependency by a namespace it provides.
+ """
+ dep_hash = {}
+ for dep in deps:
+ for provide in dep.provides:
+ if provide in dep_hash:
+ raise Exception('Duplicate provide (%s) in (%s, %s)' % (
+ provide,
+ dep_hash[provide].filename,
+ dep.filename))
+ dep_hash[provide] = dep
+ return dep_hash
+
+
+def CalculateDependencies(paths, inputs):
+ """Calculates the dependencies for given inputs.
+
+ Description:
+ This method takes a list of paths (files, directories) and builds a
+ searchable data structure based on the namespaces that each .js file
+ provides. It then parses through each input, resolving dependencies
+ against this data structure. The final output is a list of files,
+ including the inputs, that represent all of the code that is needed to
+ compile the given inputs.
+
+ Args:
+ paths: the references (files, directories) that are used to build the
+ dependency hash.
+ inputs: the inputs (files, directories, namespaces) that have dependencies
+ that need to be calculated.
+
+ Raises:
+ Exception: if a provided input is invalid.
+
+ Returns:
+ A list of all files, including inputs, that are needed to compile the given
+ inputs.
+ """
+ deps = BuildDependenciesFromFiles(paths + inputs)
+ search_hash = BuildDependencyHashFromDependencies(deps)
+ result_list = []
+ seen_list = []
+ for input_file in inputs:
+ if IsNamespace(input_file):
+ namespace = re.search(ns_regex, input_file).group(1)
+ if namespace not in search_hash:
+ raise Exception('Invalid namespace (%s)' % namespace)
+ input_file = search_hash[namespace].filename
+ if not IsValidFile(input_file) or not IsJsFile(input_file):
+ raise Exception('Invalid file (%s)' % input_file)
+ seen_list.append(input_file)
+ file_handle = open(input_file, 'r')
+ try:
+ for line in file_handle:
+ if re.match(req_regex, line):
+ require = re.search(req_regex, line).group(1)
+ ResolveDependencies(require, search_hash, result_list, seen_list)
+ finally:
+ file_handle.close()
+ result_list.append(input_file)
+
+ # All files depend on base.js, so put it first.
+ base_js_path = FindClosureBasePath(paths)
+ if base_js_path:
+ result_list.insert(0, base_js_path)
+ else:
+ logging.warning('Closure Library base.js not found.')
+
+ return result_list
+
+
+def FindClosureBasePath(paths):
+ """Given a list of file paths, return Closure base.js path, if any.
+
+ Args:
+ paths: A list of paths.
+
+ Returns:
+ The path to Closure's base.js file including filename, if found.
+ """
+
+ for path in paths:
+ pathname, filename = os.path.split(path)
+
+ if filename == 'base.js':
+ f = open(path)
+
+ is_base = False
+
+ # Sanity check that this is the Closure base file. Check that this
+ # is where goog is defined. This is determined by the @provideGoog
+ # flag.
+ for line in f:
+ if '@provideGoog' in line:
+ is_base = True
+ break
+
+ f.close()
+
+ if is_base:
+ return path
+
+def ResolveDependencies(require, search_hash, result_list, seen_list):
+ """Takes a given requirement and resolves all of the dependencies for it.
+
+ Description:
+ A given requirement may require other dependencies. This method
+ recursively resolves all dependencies for the given requirement.
+
+ Raises:
+ Exception: when require does not exist in the search_hash.
+
+ Args:
+ require: the namespace to resolve dependencies for.
+ search_hash: the data structure used for resolving dependencies.
+ result_list: a list of filenames that have been calculated as dependencies.
+ This variable is the output for this function.
+ seen_list: a list of filenames that have been 'seen'. This is required
+ for the dependency->dependant ordering.
+ """
+ if require not in search_hash:
+ raise Exception('Missing provider for (%s)' % require)
+
+ dep = search_hash[require]
+ if not dep.filename in seen_list:
+ seen_list.append(dep.filename)
+ for sub_require in dep.requires:
+ ResolveDependencies(sub_require, search_hash, result_list, seen_list)
+ result_list.append(dep.filename)
+
+
+def GetDepsLine(dep, base_path):
+ """Returns a JS string for a dependency statement in the deps.js file.
+
+ Args:
+ dep: The dependency that we're printing.
+ base_path: The path to Closure's base.js including filename.
+ """
+ return 'goog.addDependency("%s", %s, %s);' % (
+ GetRelpath(dep.filename, base_path), dep.provides, dep.requires)
+
+
+def GetRelpath(path, start):
+ """Return a relative path to |path| from |start|."""
+ # NOTE: Python 2.6 provides os.path.relpath, which has almost the same
+ # functionality as this function. Since we want to support 2.4, we have
+ # to implement it manually. :(
+ path_list = os.path.abspath(os.path.normpath(path)).split(os.sep)
+ start_list = os.path.abspath(
+ os.path.normpath(os.path.dirname(start))).split(os.sep)
+
+ common_prefix_count = 0
+ for i in range(0, min(len(path_list), len(start_list))):
+ if path_list[i] != start_list[i]:
+ break
+ common_prefix_count += 1
+
+ # Always use forward slashes, because this will get expanded to a url,
+ # not a file path.
+ return '/'.join(['..'] * (len(start_list) - common_prefix_count) +
+ path_list[common_prefix_count:])
+
+
+def PrintLine(msg, out):
+ out.write(msg)
+ out.write('\n')
+
+
+def PrintDeps(source_paths, deps, out):
+ """Print out a deps.js file from a list of source paths.
+
+ Args:
+ source_paths: Paths that we should generate dependency info for.
+ deps: Paths that provide dependency info. Their dependency info should
+ not appear in the deps file.
+ out: The output file.
+
+ Returns:
+ True on success, false if it was unable to find the base path
+ to generate deps relative to.
+ """
+ base_path = FindClosureBasePath(source_paths + deps)
+ if not base_path:
+ return False
+
+ PrintLine('// This file was autogenerated by calcdeps.py', out)
+ excludesSet = set(deps)
+
+ for dep in BuildDependenciesFromFiles(source_paths + deps):
+ if not dep.filename in excludesSet:
+ PrintLine(GetDepsLine(dep, base_path), out)
+
+ return True
+
+
+def PrintScript(source_paths, out):
+ for index, dep in enumerate(source_paths):
+ PrintLine('// Input %d' % index, out)
+ f = open(dep, 'r')
+ PrintLine(f.read(), out)
+ f.close()
+
+
+def GetJavaVersion():
+ """Returns the string for the current version of Java installed."""
+ proc = subprocess.Popen(['java', '-version'], stderr=subprocess.PIPE)
+ proc.wait()
+ version_line = proc.stderr.read().splitlines()[0]
+ return version_regex.search(version_line).group()
+
+
+def FilterByExcludes(options, files):
+ """Filters the given files by the exlusions specified at the command line.
+
+ Args:
+ options: The flags to calcdeps.
+ files: The files to filter.
+ Returns:
+ A list of files.
+ """
+ excludes = []
+ if options.excludes:
+ excludes = ExpandDirectories(options.excludes)
+
+ excludesSet = set(excludes)
+ return [i for i in files if not i in excludesSet]
+
+
+def GetPathsFromOptions(options):
+ """Generates the path files from flag options.
+
+ Args:
+ options: The flags to calcdeps.
+ Returns:
+ A list of files in the specified paths. (strings).
+ """
+
+ search_paths = options.paths
+ if not search_paths:
+ search_paths = ['.'] # Add default folder if no path is specified.
+
+ search_paths = ExpandDirectories(search_paths)
+ return FilterByExcludes(options, search_paths)
+
+
+def GetInputsFromOptions(options):
+ """Generates the inputs from flag options.
+
+ Args:
+ options: The flags to calcdeps.
+ Returns:
+ A list of inputs (strings).
+ """
+ inputs = options.inputs
+ if not inputs: # Parse stdin
+ logging.info('No inputs specified. Reading from stdin...')
+ inputs = filter(None, [line.strip('\n') for line in sys.stdin.readlines()])
+
+ logging.info('Scanning files...')
+ inputs = ExpandDirectories(inputs)
+
+ return FilterByExcludes(options, inputs)
+
+
+def Compile(compiler_jar_path, source_paths, out, flags=None):
+ """Prepares command-line call to Closure compiler.
+
+ Args:
+ compiler_jar_path: Path to the Closure compiler .jar file.
+ source_paths: Source paths to build, in order.
+ flags: A list of additional flags to pass on to Closure compiler.
+ """
+ args = ['java', '-jar', compiler_jar_path]
+ for path in source_paths:
+ args += ['--js', path]
+
+ if flags:
+ args += flags
+
+ logging.info('Compiling with the following command: %s', ' '.join(args))
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+ (stdoutdata, stderrdata) = proc.communicate()
+ if proc.returncode != 0:
+ logging.error('JavaScript compilation failed.')
+ sys.exit(1)
+ else:
+ out.write(stdoutdata)
+
+
+def main():
+ """The entrypoint for this script."""
+
+ logging.basicConfig(format='calcdeps.py: %(message)s', level=logging.INFO)
+
+ usage = 'usage: %prog [options] arg'
+ parser = optparse.OptionParser(usage)
+ parser.add_option('-i',
+ '--input',
+ dest='inputs',
+ action='append',
+ help='The inputs to calculate dependencies for. Valid '
+ 'values can be files, directories, or namespaces '
+ '(ns:goog.net.XhrIo). Only relevant to "list" and '
+ '"script" output.')
+ parser.add_option('-p',
+ '--path',
+ dest='paths',
+ action='append',
+ help='The paths that should be traversed to build the '
+ 'dependencies.')
+ parser.add_option('-d',
+ '--dep',
+ dest='deps',
+ action='append',
+ help='Directories or files that should be traversed to '
+ 'find required dependencies for the deps file. '
+ 'Does not generate dependency information for names '
+ 'provided by these files. Only useful in "deps" mode.')
+ parser.add_option('-e',
+ '--exclude',
+ dest='excludes',
+ action='append',
+ help='Files or directories to exclude from the --path '
+ 'and --input flags')
+ parser.add_option('-o',
+ '--output_mode',
+ dest='output_mode',
+ action='store',
+ default='list',
+ help='The type of output to generate from this script. '
+ 'Options are "list" for a list of filenames, "script" '
+ 'for a single script containing the contents of all the '
+ 'file, "deps" to generate a deps.js file for all '
+ 'paths, or "compiled" to produce compiled output with '
+ 'the Closure compiler.')
+ parser.add_option('-c',
+ '--compiler_jar',
+ dest='compiler_jar',
+ action='store',
+ help='The location of the Closure compiler .jar file.')
+ parser.add_option('-f',
+ '--compiler_flag',
+ '--compiler_flags', # for backwards compatability
+ dest='compiler_flags',
+ action='append',
+ help='Additional flag to pass to the Closure compiler. '
+ 'May be specified multiple times to pass multiple flags.')
+ parser.add_option('--output_file',
+ dest='output_file',
+ action='store',
+ help=('If specified, write output to this path instead of '
+ 'writing to standard output.'))
+
+ (options, args) = parser.parse_args()
+
+ search_paths = GetPathsFromOptions(options)
+
+ if options.output_file:
+ out = open(options.output_file, 'w')
+ else:
+ out = sys.stdout
+
+ if options.output_mode == 'deps':
+ result = PrintDeps(search_paths, ExpandDirectories(options.deps or []), out)
+ if not result:
+ logging.error('Could not find Closure Library in the specified paths')
+ sys.exit(1)
+
+ return
+
+ inputs = GetInputsFromOptions(options)
+
+ logging.info('Finding Closure dependencies...')
+ deps = CalculateDependencies(search_paths, inputs)
+ output_mode = options.output_mode
+
+ if output_mode == 'script':
+ PrintScript(deps, out)
+ elif output_mode == 'list':
+ # Just print out a dep per line
+ for dep in deps:
+ PrintLine(dep, out)
+ elif output_mode == 'compiled':
+ # Make sure a .jar is specified.
+ if not options.compiler_jar:
+ logging.error('--compiler_jar flag must be specified if --output is '
+ '"compiled"')
+ sys.exit(1)
+
+ # User friendly version check.
+ if distutils and not (distutils.version.LooseVersion(GetJavaVersion()) >
+ distutils.version.LooseVersion('1.6')):
+ logging.error('Closure Compiler requires Java 1.6 or higher.')
+ logging.error('Please visit http://www.java.com/getjava')
+ sys.exit(1)
+
+ Compile(options.compiler_jar, deps, out, options.compiler_flags)
+
+ else:
+ logging.error('Invalid value for --output flag.')
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/scopify.py b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/scopify.py
new file mode 100755
index 0000000000..d8057efbc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/bin/scopify.py
@@ -0,0 +1,221 @@
+#!/usr/bin/python
+#
+# Copyright 2010 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Automatically converts codebases over to goog.scope.
+
+Usage:
+cd path/to/my/dir;
+../../../../javascript/closure/bin/scopify.py
+
+Scans every file in this directory, recursively. Looks for existing
+goog.scope calls, and goog.require'd symbols. If it makes sense to
+generate a goog.scope call for the file, then we will do so, and
+try to auto-generate some aliases based on the goog.require'd symbols.
+
+Known Issues:
+
+ When a file is goog.scope'd, the file contents will be indented +2.
+ This may put some lines over 80 chars. These will need to be fixed manually.
+
+ We will only try to create aliases for capitalized names. We do not check
+ to see if those names will conflict with any existing locals.
+
+ This creates merge conflicts for every line of every outstanding change.
+ If you intend to run this on your codebase, make sure your team members
+ know. Better yet, send them this script so that they can scopify their
+ outstanding changes and "accept theirs".
+
+ When an alias is "captured", it can no longer be stubbed out for testing.
+ Run your tests.
+
+"""
+
+__author__ = 'nicksantos@google.com (Nick Santos)'
+
+import os.path
+import re
+import sys
+
+REQUIRES_RE = re.compile(r"goog.require\('([^']*)'\)")
+
+# Edit this manually if you want something to "always" be aliased.
+# TODO(nicksantos): Add a flag for this.
+DEFAULT_ALIASES = {}
+
+def Transform(lines):
+ """Converts the contents of a file into javascript that uses goog.scope.
+
+ Arguments:
+ lines: A list of strings, corresponding to each line of the file.
+ Returns:
+ A new list of strings, or None if the file was not modified.
+ """
+ requires = []
+
+ # Do an initial scan to be sure that this file can be processed.
+ for line in lines:
+ # Skip this file if it has already been scopified.
+ if line.find('goog.scope') != -1:
+ return None
+
+ # If there are any global vars or functions, then we also have
+ # to skip the whole file. We might be able to deal with this
+ # more elegantly.
+ if line.find('var ') == 0 or line.find('function ') == 0:
+ return None
+
+ for match in REQUIRES_RE.finditer(line):
+ requires.append(match.group(1))
+
+ if len(requires) == 0:
+ return None
+
+ # Backwards-sort the requires, so that when one is a substring of another,
+ # we match the longer one first.
+ for val in DEFAULT_ALIASES.values():
+ if requires.count(val) == 0:
+ requires.append(val)
+
+ requires.sort()
+ requires.reverse()
+
+ # Generate a map of requires to their aliases
+ aliases_to_globals = DEFAULT_ALIASES.copy()
+ for req in requires:
+ index = req.rfind('.')
+ if index == -1:
+ alias = req
+ else:
+ alias = req[(index + 1):]
+
+ # Don't scopify lowercase namespaces, because they may conflict with
+ # local variables.
+ if alias[0].isupper():
+ aliases_to_globals[alias] = req
+
+ aliases_to_matchers = {}
+ globals_to_aliases = {}
+ for alias, symbol in aliases_to_globals.items():
+ globals_to_aliases[symbol] = alias
+ aliases_to_matchers[alias] = re.compile('\\b%s\\b' % symbol)
+
+ # Insert a goog.scope that aliases all required symbols.
+ result = []
+
+ START = 0
+ SEEN_REQUIRES = 1
+ IN_SCOPE = 2
+
+ mode = START
+ aliases_used = set()
+ insertion_index = None
+ num_blank_lines = 0
+ for line in lines:
+ if mode == START:
+ result.append(line)
+
+ if re.search(REQUIRES_RE, line):
+ mode = SEEN_REQUIRES
+
+ elif mode == SEEN_REQUIRES:
+ if (line and
+ not re.search(REQUIRES_RE, line) and
+ not line.isspace()):
+ # There should be two blank lines before goog.scope
+ result += ['\n'] * 2
+ result.append('goog.scope(function() {\n')
+ insertion_index = len(result)
+ result += ['\n'] * num_blank_lines
+ mode = IN_SCOPE
+ elif line.isspace():
+ # Keep track of the number of blank lines before each block of code so
+ # that we can move them after the goog.scope line if necessary.
+ num_blank_lines += 1
+ else:
+ # Print the blank lines we saw before this code block
+ result += ['\n'] * num_blank_lines
+ num_blank_lines = 0
+ result.append(line)
+
+ if mode == IN_SCOPE:
+ for symbol in requires:
+ if not symbol in globals_to_aliases:
+ continue
+
+ alias = globals_to_aliases[symbol]
+ matcher = aliases_to_matchers[alias]
+ for match in matcher.finditer(line):
+ # Check to make sure we're not in a string.
+ # We do this by being as conservative as possible:
+ # if there are any quote or double quote characters
+ # before the symbol on this line, then bail out.
+ before_symbol = line[:match.start(0)]
+ if before_symbol.count('"') > 0 or before_symbol.count("'") > 0:
+ continue
+
+ line = line.replace(match.group(0), alias)
+ aliases_used.add(alias)
+
+ if line.isspace():
+ # Truncate all-whitespace lines
+ result.append('\n')
+ else:
+ result.append(line)
+
+ if len(aliases_used):
+ aliases_used = [alias for alias in aliases_used]
+ aliases_used.sort()
+ aliases_used.reverse()
+ for alias in aliases_used:
+ symbol = aliases_to_globals[alias]
+ result.insert(insertion_index,
+ 'var %s = %s;\n' % (alias, symbol))
+ result.append('}); // goog.scope\n')
+ return result
+ else:
+ return None
+
+def TransformFileAt(path):
+ """Converts a file into javascript that uses goog.scope.
+
+ Arguments:
+ path: A path to a file.
+ """
+ f = open(path)
+ lines = Transform(f.readlines())
+ if lines:
+ f = open(path, 'w')
+ for l in lines:
+ f.write(l)
+ f.close()
+
+if __name__ == '__main__':
+ args = sys.argv[1:]
+ if not len(args):
+ args = '.'
+
+ for file_name in args:
+ if os.path.isdir(file_name):
+ for root, dirs, files in os.walk(file_name):
+ for name in files:
+ if name.endswith('.js') and \
+ not os.path.islink(os.path.join(root, name)):
+ TransformFileAt(os.path.join(root, name))
+ else:
+ if file_name.endswith('.js') and \
+ not os.path.islink(file_name):
+ TransformFileAt(file_name)
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/base.js b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/base.js
new file mode 100644
index 0000000000..a96333017c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/base.js
@@ -0,0 +1,2496 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Bootstrap for the Google JS Library (Closure).
+ *
+ * In uncompiled mode base.js will write out Closure's deps file, unless the
+ * global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects to
+ * include their own deps file(s) from different locations.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * @provideGoog
+ */
+
+
+/**
+ * @define {boolean} Overridden to true by the compiler when --closure_pass
+ * or --mark_as_compiled is specified.
+ */
+var COMPILED = false;
+
+
+/**
+ * Base namespace for the Closure library. Checks to see goog is already
+ * defined in the current scope before assigning to prevent clobbering if
+ * base.js is loaded more than once.
+ *
+ * @const
+ */
+var goog = goog || {};
+
+
+/**
+ * Reference to the global context. In most cases this will be 'window'.
+ */
+goog.global = this;
+
+
+/**
+ * A hook for overriding the define values in uncompiled mode.
+ *
+ * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before
+ * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES},
+ * {@code goog.define} will use the value instead of the default value. This
+ * allows flags to be overwritten without compilation (this is normally
+ * accomplished with the compiler's "define" flag).
+ *
+ * Example:
+ * <pre>
+ * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
+ * </pre>
+ *
+ * @type {Object<string, (string|number|boolean)>|undefined}
+ */
+goog.global.CLOSURE_UNCOMPILED_DEFINES;
+
+
+/**
+ * A hook for overriding the define values in uncompiled or compiled mode,
+ * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In
+ * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.
+ *
+ * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or
+ * string literals or the compiler will emit an error.
+ *
+ * While any @define value may be set, only those set with goog.define will be
+ * effective for uncompiled code.
+ *
+ * Example:
+ * <pre>
+ * var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
+ * </pre>
+ *
+ * @type {Object<string, (string|number|boolean)>|undefined}
+ */
+goog.global.CLOSURE_DEFINES;
+
+
+/**
+ * Returns true if the specified value is not undefined.
+ * WARNING: Do not use this to test if an object has a property. Use the in
+ * operator instead.
+ *
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is defined.
+ */
+goog.isDef = function(val) {
+ // void 0 always evaluates to undefined and hence we do not need to depend on
+ // the definition of the global variable named 'undefined'.
+ return val !== void 0;
+};
+
+
+/**
+ * Builds an object structure for the provided namespace path, ensuring that
+ * names that already exist are not overwritten. For example:
+ * "a.b.c" -> a = {};a.b={};a.b.c={};
+ * Used by goog.provide and goog.exportSymbol.
+ * @param {string} name name of the object that this file defines.
+ * @param {*=} opt_object the object to expose at the end of the path.
+ * @param {Object=} opt_objectToExportTo The object to add the path to; default
+ * is |goog.global|.
+ * @private
+ */
+goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
+ var parts = name.split('.');
+ var cur = opt_objectToExportTo || goog.global;
+
+ // Internet Explorer exhibits strange behavior when throwing errors from
+ // methods externed in this manner. See the testExportSymbolExceptions in
+ // base_test.html for an example.
+ if (!(parts[0] in cur) && cur.execScript) {
+ cur.execScript('var ' + parts[0]);
+ }
+
+ // Certain browsers cannot parse code in the form for((a in b); c;);
+ // This pattern is produced by the JSCompiler when it collapses the
+ // statement above into the conditional loop below. To prevent this from
+ // happening, use a for-loop and reserve the init logic as below.
+
+ // Parentheses added to eliminate strict JS warning in Firefox.
+ for (var part; parts.length && (part = parts.shift());) {
+ if (!parts.length && goog.isDef(opt_object)) {
+ // last part and we have an object; use it
+ cur[part] = opt_object;
+ } else if (cur[part]) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+};
+
+
+/**
+ * Defines a named value. In uncompiled mode, the value is retrieved from
+ * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and
+ * has the property specified, and otherwise used the defined defaultValue.
+ * When compiled the default can be overridden using the compiler
+ * options or the value set in the CLOSURE_DEFINES object.
+ *
+ * @param {string} name The distinguished name to provide.
+ * @param {string|number|boolean} defaultValue
+ */
+goog.define = function(name, defaultValue) {
+ var value = defaultValue;
+ if (!COMPILED) {
+ if (goog.global.CLOSURE_UNCOMPILED_DEFINES &&
+ Object.prototype.hasOwnProperty.call(
+ goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
+ value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
+ } else if (goog.global.CLOSURE_DEFINES &&
+ Object.prototype.hasOwnProperty.call(
+ goog.global.CLOSURE_DEFINES, name)) {
+ value = goog.global.CLOSURE_DEFINES[name];
+ }
+ }
+ goog.exportPath_(name, value);
+};
+
+
+/**
+ * @define {boolean} DEBUG is provided as a convenience so that debugging code
+ * that should not be included in a production js_binary can be easily stripped
+ * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
+ * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
+ * because they are generally used for debugging purposes and it is difficult
+ * for the JSCompiler to statically determine whether they are used.
+ */
+goog.define('goog.DEBUG', true);
+
+
+/**
+ * @define {string} LOCALE defines the locale being used for compilation. It is
+ * used to select locale specific data to be compiled in js binary. BUILD rule
+ * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
+ * option.
+ *
+ * Take into account that the locale code format is important. You should use
+ * the canonical Unicode format with hyphen as a delimiter. Language must be
+ * lowercase, Language Script - Capitalized, Region - UPPERCASE.
+ * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
+ *
+ * See more info about locale codes here:
+ * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
+ *
+ * For language codes you should use values defined by ISO 693-1. See it here
+ * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
+ * this rule: the Hebrew language. For legacy reasons the old code (iw) should
+ * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
+ */
+goog.define('goog.LOCALE', 'en'); // default to en
+
+
+/**
+ * @define {boolean} Whether this code is running on trusted sites.
+ *
+ * On untrusted sites, several native functions can be defined or overridden by
+ * external libraries like Prototype, Datejs, and JQuery and setting this flag
+ * to false forces closure to use its own implementations when possible.
+ *
+ * If your JavaScript can be loaded by a third party site and you are wary about
+ * relying on non-standard implementations, specify
+ * "--define goog.TRUSTED_SITE=false" to the JSCompiler.
+ */
+goog.define('goog.TRUSTED_SITE', true);
+
+
+/**
+ * @define {boolean} Whether a project is expected to be running in strict mode.
+ *
+ * This define can be used to trigger alternate implementations compatible with
+ * running in EcmaScript Strict mode or warn about unavailable functionality.
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
+ *
+ */
+goog.define('goog.STRICT_MODE_COMPATIBLE', false);
+
+
+/**
+ * @define {boolean} Whether code that calls {@link goog.setTestOnly} should
+ * be disallowed in the compilation unit.
+ */
+goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG);
+
+
+/**
+ * Defines a namespace in Closure.
+ *
+ * A namespace may only be defined once in a codebase. It may be defined using
+ * goog.provide() or goog.module().
+ *
+ * The presence of one or more goog.provide() calls in a file indicates
+ * that the file defines the given objects/namespaces.
+ * Provided symbols must not be null or undefined.
+ *
+ * In addition, goog.provide() creates the object stubs for a namespace
+ * (for example, goog.provide("goog.foo.bar") will create the object
+ * goog.foo.bar if it does not already exist).
+ *
+ * Build tools also scan for provide/require/module statements
+ * to discern dependencies, build dependency files (see deps.js), etc.
+ *
+ * @see goog.require
+ * @see goog.module
+ * @param {string} name Namespace provided by this file in the form
+ * "goog.package.part".
+ */
+goog.provide = function(name) {
+ if (!COMPILED) {
+ // Ensure that the same namespace isn't provided twice.
+ // A goog.module/goog.provide maps a goog.require to a specific file
+ if (goog.isProvided_(name)) {
+ throw Error('Namespace "' + name + '" already declared.');
+ }
+ }
+
+ goog.constructNamespace_(name);
+};
+
+
+/**
+ * @param {string} name Namespace provided by this file in the form
+ * "goog.package.part".
+ * @param {Object=} opt_obj The object to embed in the namespace.
+ * @private
+ */
+goog.constructNamespace_ = function(name, opt_obj) {
+ if (!COMPILED) {
+ delete goog.implicitNamespaces_[name];
+
+ var namespace = name;
+ while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
+ if (goog.getObjectByName(namespace)) {
+ break;
+ }
+ goog.implicitNamespaces_[namespace] = true;
+ }
+ }
+
+ goog.exportPath_(name, opt_obj);
+};
+
+
+/**
+ * Module identifier validation regexp.
+ * Note: This is a conservative check, it is very possible to be more lenient,
+ * the primary exclusion here is "/" and "\" and a leading ".", these
+ * restrictions are intended to leave the door open for using goog.require
+ * with relative file paths rather than module identifiers.
+ * @private
+ */
+goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
+
+
+/**
+ * Defines a module in Closure.
+ *
+ * Marks that this file must be loaded as a module and claims the namespace.
+ *
+ * A namespace may only be defined once in a codebase. It may be defined using
+ * goog.provide() or goog.module().
+ *
+ * goog.module() has three requirements:
+ * - goog.module may not be used in the same file as goog.provide.
+ * - goog.module must be the first statement in the file.
+ * - only one goog.module is allowed per file.
+ *
+ * When a goog.module annotated file is loaded, it is enclosed in
+ * a strict function closure. This means that:
+ * - any variables declared in a goog.module file are private to the file
+ * (not global), though the compiler is expected to inline the module.
+ * - The code must obey all the rules of "strict" JavaScript.
+ * - the file will be marked as "use strict"
+ *
+ * NOTE: unlike goog.provide, goog.module does not declare any symbols by
+ * itself. If declared symbols are desired, use
+ * goog.module.declareLegacyNamespace().
+ *
+ *
+ * See the public goog.module proposal: http://goo.gl/Va1hin
+ *
+ * @param {string} name Namespace provided by this file in the form
+ * "goog.package.part", is expected but not required.
+ */
+goog.module = function(name) {
+ if (!goog.isString(name) ||
+ !name ||
+ name.search(goog.VALID_MODULE_RE_) == -1) {
+ throw Error('Invalid module identifier');
+ }
+ if (!goog.isInModuleLoader_()) {
+ throw Error('Module ' + name + ' has been loaded incorrectly.');
+ }
+ if (goog.moduleLoaderState_.moduleName) {
+ throw Error('goog.module may only be called once per module.');
+ }
+
+ // Store the module name for the loader.
+ goog.moduleLoaderState_.moduleName = name;
+ if (!COMPILED) {
+ // Ensure that the same namespace isn't provided twice.
+ // A goog.module/goog.provide maps a goog.require to a specific file
+ if (goog.isProvided_(name)) {
+ throw Error('Namespace "' + name + '" already declared.');
+ }
+ delete goog.implicitNamespaces_[name];
+ }
+};
+
+
+/**
+ * @param {string} name The module identifier.
+ * @return {?} The module exports for an already loaded module or null.
+ *
+ * Note: This is not an alternative to goog.require, it does not
+ * indicate a hard dependency, instead it is used to indicate
+ * an optional dependency or to access the exports of a module
+ * that has already been loaded.
+ * @suppress {missingProvide}
+ */
+goog.module.get = function(name) {
+ return goog.module.getInternal_(name);
+};
+
+
+/**
+ * @param {string} name The module identifier.
+ * @return {?} The module exports for an already loaded module or null.
+ * @private
+ */
+goog.module.getInternal_ = function(name) {
+ if (!COMPILED) {
+ if (goog.isProvided_(name)) {
+ // goog.require only return a value with-in goog.module files.
+ return name in goog.loadedModules_ ?
+ goog.loadedModules_[name] :
+ goog.getObjectByName(name);
+ } else {
+ return null;
+ }
+ }
+};
+
+
+/**
+ * @private {?{
+ * moduleName: (string|undefined),
+ * declareTestMethods: boolean
+ * }}
+ */
+goog.moduleLoaderState_ = null;
+
+
+/**
+ * @private
+ * @return {boolean} Whether a goog.module is currently being initialized.
+ */
+goog.isInModuleLoader_ = function() {
+ return goog.moduleLoaderState_ != null;
+};
+
+
+/**
+ * Indicate that a module's exports that are known test methods should
+ * be copied to the global object. This makes the test methods visible to
+ * test runners that inspect the global object.
+ *
+ * TODO(johnlenz): Make the test framework aware of goog.module so
+ * that this isn't necessary. Alternately combine this with goog.setTestOnly
+ * to minimize boiler plate.
+ * @suppress {missingProvide}
+ */
+goog.module.declareTestMethods = function() {
+ if (!goog.isInModuleLoader_()) {
+ throw new Error('goog.module.declareTestMethods must be called from ' +
+ 'within a goog.module');
+ }
+ goog.moduleLoaderState_.declareTestMethods = true;
+};
+
+
+/**
+ * Provide the module's exports as a globally accessible object under the
+ * module's declared name. This is intended to ease migration to goog.module
+ * for files that have existing usages.
+ * @suppress {missingProvide}
+ */
+goog.module.declareLegacyNamespace = function() {
+ if (!COMPILED && !goog.isInModuleLoader_()) {
+ throw new Error('goog.module.declareLegacyNamespace must be called from ' +
+ 'within a goog.module');
+ }
+ if (!COMPILED && !goog.moduleLoaderState_.moduleName) {
+ throw Error('goog.module must be called prior to ' +
+ 'goog.module.declareLegacyNamespace.');
+ }
+ goog.moduleLoaderState_.declareLegacyNamespace = true;
+};
+
+
+/**
+ * Marks that the current file should only be used for testing, and never for
+ * live code in production.
+ *
+ * In the case of unit tests, the message may optionally be an exact namespace
+ * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra
+ * provide (if not explicitly defined in the code).
+ *
+ * @param {string=} opt_message Optional message to add to the error that's
+ * raised when used in production code.
+ */
+goog.setTestOnly = function(opt_message) {
+ if (goog.DISALLOW_TEST_ONLY_CODE) {
+ opt_message = opt_message || '';
+ throw Error('Importing test-only code into non-debug environment' +
+ (opt_message ? ': ' + opt_message : '.'));
+ }
+};
+
+
+/**
+ * Forward declares a symbol. This is an indication to the compiler that the
+ * symbol may be used in the source yet is not required and may not be provided
+ * in compilation.
+ *
+ * The most common usage of forward declaration is code that takes a type as a
+ * function parameter but does not need to require it. By forward declaring
+ * instead of requiring, no hard dependency is made, and (if not required
+ * elsewhere) the namespace may never be required and thus, not be pulled
+ * into the JavaScript binary. If it is required elsewhere, it will be type
+ * checked as normal.
+ *
+ *
+ * @param {string} name The namespace to forward declare in the form of
+ * "goog.package.part".
+ */
+goog.forwardDeclare = function(name) {};
+
+
+if (!COMPILED) {
+
+ /**
+ * Check if the given name has been goog.provided. This will return false for
+ * names that are available only as implicit namespaces.
+ * @param {string} name name of the object to look for.
+ * @return {boolean} Whether the name has been provided.
+ * @private
+ */
+ goog.isProvided_ = function(name) {
+ return (name in goog.loadedModules_) ||
+ (!goog.implicitNamespaces_[name] &&
+ goog.isDefAndNotNull(goog.getObjectByName(name)));
+ };
+
+ /**
+ * Namespaces implicitly defined by goog.provide. For example,
+ * goog.provide('goog.events.Event') implicitly declares that 'goog' and
+ * 'goog.events' must be namespaces.
+ *
+ * @type {!Object<string, (boolean|undefined)>}
+ * @private
+ */
+ goog.implicitNamespaces_ = {'goog.module': true};
+
+ // NOTE: We add goog.module as an implicit namespace as goog.module is defined
+ // here and because the existing module package has not been moved yet out of
+ // the goog.module namespace. This satisifies both the debug loader and
+ // ahead-of-time dependency management.
+}
+
+
+/**
+ * Returns an object based on its fully qualified external name. The object
+ * is not found if null or undefined. If you are using a compilation pass that
+ * renames property names beware that using this function will not find renamed
+ * properties.
+ *
+ * @param {string} name The fully qualified name.
+ * @param {Object=} opt_obj The object within which to look; default is
+ * |goog.global|.
+ * @return {?} The value (object or primitive) or, if not found, null.
+ */
+goog.getObjectByName = function(name, opt_obj) {
+ var parts = name.split('.');
+ var cur = opt_obj || goog.global;
+ for (var part; part = parts.shift(); ) {
+ if (goog.isDefAndNotNull(cur[part])) {
+ cur = cur[part];
+ } else {
+ return null;
+ }
+ }
+ return cur;
+};
+
+
+/**
+ * Globalizes a whole namespace, such as goog or goog.lang.
+ *
+ * @param {!Object} obj The namespace to globalize.
+ * @param {Object=} opt_global The object to add the properties to.
+ * @deprecated Properties may be explicitly exported to the global scope, but
+ * this should no longer be done in bulk.
+ */
+goog.globalize = function(obj, opt_global) {
+ var global = opt_global || goog.global;
+ for (var x in obj) {
+ global[x] = obj[x];
+ }
+};
+
+
+/**
+ * Adds a dependency from a file to the files it requires.
+ * @param {string} relPath The path to the js file.
+ * @param {!Array<string>} provides An array of strings with
+ * the names of the objects this file provides.
+ * @param {!Array<string>} requires An array of strings with
+ * the names of the objects this file requires.
+ * @param {boolean=} opt_isModule Whether this dependency must be loaded as
+ * a module as declared by goog.module.
+ */
+goog.addDependency = function(relPath, provides, requires, opt_isModule) {
+ if (goog.DEPENDENCIES_ENABLED) {
+ var provide, require;
+ var path = relPath.replace(/\\/g, '/');
+ var deps = goog.dependencies_;
+ for (var i = 0; provide = provides[i]; i++) {
+ deps.nameToPath[provide] = path;
+ deps.pathIsModule[path] = !!opt_isModule;
+ }
+ for (var j = 0; require = requires[j]; j++) {
+ if (!(path in deps.requires)) {
+ deps.requires[path] = {};
+ }
+ deps.requires[path][require] = true;
+ }
+ }
+};
+
+
+
+
+// NOTE(nnaze): The debug DOM loader was included in base.js as an original way
+// to do "debug-mode" development. The dependency system can sometimes be
+// confusing, as can the debug DOM loader's asynchronous nature.
+//
+// With the DOM loader, a call to goog.require() is not blocking -- the script
+// will not load until some point after the current script. If a namespace is
+// needed at runtime, it needs to be defined in a previous script, or loaded via
+// require() with its registered dependencies.
+// User-defined namespaces may need their own deps file. See http://go/js_deps,
+// http://go/genjsdeps, or, externally, DepsWriter.
+// https://developers.google.com/closure/library/docs/depswriter
+//
+// Because of legacy clients, the DOM loader can't be easily removed from
+// base.js. Work is being done to make it disableable or replaceable for
+// different environments (DOM-less JavaScript interpreters like Rhino or V8,
+// for example). See bootstrap/ for more information.
+
+
+/**
+ * @define {boolean} Whether to enable the debug loader.
+ *
+ * If enabled, a call to goog.require() will attempt to load the namespace by
+ * appending a script tag to the DOM (if the namespace has been registered).
+ *
+ * If disabled, goog.require() will simply assert that the namespace has been
+ * provided (and depend on the fact that some outside tool correctly ordered
+ * the script).
+ */
+goog.define('goog.ENABLE_DEBUG_LOADER', true);
+
+
+/**
+ * @param {string} msg
+ * @private
+ */
+goog.logToConsole_ = function(msg) {
+ if (goog.global.console) {
+ goog.global.console['error'](msg);
+ }
+};
+
+
+/**
+ * Implements a system for the dynamic resolution of dependencies that works in
+ * parallel with the BUILD system. Note that all calls to goog.require will be
+ * stripped by the JSCompiler when the --closure_pass option is used.
+ * @see goog.provide
+ * @param {string} name Namespace to include (as was given in goog.provide()) in
+ * the form "goog.package.part".
+ * @return {?} If called within a goog.module file, the associated namespace or
+ * module otherwise null.
+ */
+goog.require = function(name) {
+
+ // If the object already exists we do not need do do anything.
+ if (!COMPILED) {
+ if (goog.ENABLE_DEBUG_LOADER && goog.IS_OLD_IE_) {
+ goog.maybeProcessDeferredDep_(name);
+ }
+
+ if (goog.isProvided_(name)) {
+ if (goog.isInModuleLoader_()) {
+ return goog.module.getInternal_(name);
+ } else {
+ return null;
+ }
+ }
+
+ if (goog.ENABLE_DEBUG_LOADER) {
+ var path = goog.getPathFromDeps_(name);
+ if (path) {
+ goog.included_[path] = true;
+ goog.writeScripts_();
+ return null;
+ }
+ }
+
+ var errorMessage = 'goog.require could not find: ' + name;
+ goog.logToConsole_(errorMessage);
+
+ throw Error(errorMessage);
+ }
+};
+
+
+/**
+ * Path for included scripts.
+ * @type {string}
+ */
+goog.basePath = '';
+
+
+/**
+ * A hook for overriding the base path.
+ * @type {string|undefined}
+ */
+goog.global.CLOSURE_BASE_PATH;
+
+
+/**
+ * Whether to write out Closure's deps file. By default, the deps are written.
+ * @type {boolean|undefined}
+ */
+goog.global.CLOSURE_NO_DEPS;
+
+
+/**
+ * A function to import a single script. This is meant to be overridden when
+ * Closure is being run in non-HTML contexts, such as web workers. It's defined
+ * in the global scope so that it can be set before base.js is loaded, which
+ * allows deps.js to be imported properly.
+ *
+ * The function is passed the script source, which is a relative URI. It should
+ * return true if the script was imported, false otherwise.
+ * @type {(function(string): boolean)|undefined}
+ */
+goog.global.CLOSURE_IMPORT_SCRIPT;
+
+
+/**
+ * Null function used for default values of callbacks, etc.
+ * @return {void} Nothing.
+ */
+goog.nullFunction = function() {};
+
+
+/**
+ * The identity function. Returns its first argument.
+ *
+ * @param {*=} opt_returnValue The single value that will be returned.
+ * @param {...*} var_args Optional trailing arguments. These are ignored.
+ * @return {?} The first argument. We can't know the type -- just pass it along
+ * without type.
+ * @deprecated Use goog.functions.identity instead.
+ */
+goog.identityFunction = function(opt_returnValue, var_args) {
+ return opt_returnValue;
+};
+
+
+/**
+ * When defining a class Foo with an abstract method bar(), you can do:
+ * Foo.prototype.bar = goog.abstractMethod
+ *
+ * Now if a subclass of Foo fails to override bar(), an error will be thrown
+ * when bar() is invoked.
+ *
+ * Note: This does not take the name of the function to override as an argument
+ * because that would make it more difficult to obfuscate our JavaScript code.
+ *
+ * @type {!Function}
+ * @throws {Error} when invoked to indicate the method should be overridden.
+ */
+goog.abstractMethod = function() {
+ throw Error('unimplemented abstract method');
+};
+
+
+/**
+ * Adds a {@code getInstance} static method that always returns the same
+ * instance object.
+ * @param {!Function} ctor The constructor for the class to add the static
+ * method to.
+ */
+goog.addSingletonGetter = function(ctor) {
+ ctor.getInstance = function() {
+ if (ctor.instance_) {
+ return ctor.instance_;
+ }
+ if (goog.DEBUG) {
+ // NOTE: JSCompiler can't optimize away Array#push.
+ goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
+ }
+ return ctor.instance_ = new ctor;
+ };
+};
+
+
+/**
+ * All singleton classes that have been instantiated, for testing. Don't read
+ * it directly, use the {@code goog.testing.singleton} module. The compiler
+ * removes this variable if unused.
+ * @type {!Array<!Function>}
+ * @private
+ */
+goog.instantiatedSingletons_ = [];
+
+
+/**
+ * @define {boolean} Whether to load goog.modules using {@code eval} when using
+ * the debug loader. This provides a better debugging experience as the
+ * source is unmodified and can be edited using Chrome Workspaces or similar.
+ * However in some environments the use of {@code eval} is banned
+ * so we provide an alternative.
+ */
+goog.define('goog.LOAD_MODULE_USING_EVAL', true);
+
+
+/**
+ * @define {boolean} Whether the exports of goog.modules should be sealed when
+ * possible.
+ */
+goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);
+
+
+/**
+ * The registry of initialized modules:
+ * the module identifier to module exports map.
+ * @private @const {!Object<string, ?>}
+ */
+goog.loadedModules_ = {};
+
+
+/**
+ * True if goog.dependencies_ is available.
+ * @const {boolean}
+ */
+goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
+
+
+if (goog.DEPENDENCIES_ENABLED) {
+ /**
+ * Object used to keep track of urls that have already been added. This record
+ * allows the prevention of circular dependencies.
+ * @private {!Object<string, boolean>}
+ */
+ goog.included_ = {};
+
+
+ /**
+ * This object is used to keep track of dependencies and other data that is
+ * used for loading scripts.
+ * @private
+ * @type {{
+ * pathIsModule: !Object<string, boolean>,
+ * nameToPath: !Object<string, string>,
+ * requires: !Object<string, !Object<string, boolean>>,
+ * visited: !Object<string, boolean>,
+ * written: !Object<string, boolean>,
+ * deferred: !Object<string, string>
+ * }}
+ */
+ goog.dependencies_ = {
+ pathIsModule: {}, // 1 to 1
+
+ nameToPath: {}, // 1 to 1
+
+ requires: {}, // 1 to many
+
+ // Used when resolving dependencies to prevent us from visiting file twice.
+ visited: {},
+
+ written: {}, // Used to keep track of script files we have written.
+
+ deferred: {} // Used to track deferred module evaluations in old IEs
+ };
+
+
+ /**
+ * Tries to detect whether is in the context of an HTML document.
+ * @return {boolean} True if it looks like HTML document.
+ * @private
+ */
+ goog.inHtmlDocument_ = function() {
+ var doc = goog.global.document;
+ return typeof doc != 'undefined' &&
+ 'write' in doc; // XULDocument misses write.
+ };
+
+
+ /**
+ * Tries to detect the base path of base.js script that bootstraps Closure.
+ * @private
+ */
+ goog.findBasePath_ = function() {
+ if (goog.isDef(goog.global.CLOSURE_BASE_PATH)) {
+ goog.basePath = goog.global.CLOSURE_BASE_PATH;
+ return;
+ } else if (!goog.inHtmlDocument_()) {
+ return;
+ }
+ var doc = goog.global.document;
+ var scripts = doc.getElementsByTagName('SCRIPT');
+ // Search backwards since the current script is in almost all cases the one
+ // that has base.js.
+ for (var i = scripts.length - 1; i >= 0; --i) {
+ var script = /** @type {!HTMLScriptElement} */ (scripts[i]);
+ var src = script.src;
+ var qmark = src.lastIndexOf('?');
+ var l = qmark == -1 ? src.length : qmark;
+ if (src.substr(l - 7, 7) == 'base.js') {
+ goog.basePath = src.substr(0, l - 7);
+ return;
+ }
+ }
+ };
+
+
+ /**
+ * Imports a script if, and only if, that script hasn't already been imported.
+ * (Must be called at execution time)
+ * @param {string} src Script source.
+ * @param {string=} opt_sourceText The optionally source text to evaluate
+ * @private
+ */
+ goog.importScript_ = function(src, opt_sourceText) {
+ var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
+ goog.writeScriptTag_;
+ if (importScript(src, opt_sourceText)) {
+ goog.dependencies_.written[src] = true;
+ }
+ };
+
+
+ /** @const @private {boolean} */
+ goog.IS_OLD_IE_ = !!(!goog.global.atob && goog.global.document &&
+ goog.global.document.all);
+
+
+ /**
+ * Given a URL initiate retrieval and execution of the module.
+ * @param {string} src Script source URL.
+ * @private
+ */
+ goog.importModule_ = function(src) {
+ // In an attempt to keep browsers from timing out loading scripts using
+ // synchronous XHRs, put each load in its own script block.
+ var bootstrap = 'goog.retrieveAndExecModule_("' + src + '");';
+
+ if (goog.importScript_('', bootstrap)) {
+ goog.dependencies_.written[src] = true;
+ }
+ };
+
+
+ /** @private {!Array<string>} */
+ goog.queuedModules_ = [];
+
+
+ /**
+ * Return an appropriate module text. Suitable to insert into
+ * a script tag (that is unescaped).
+ * @param {string} srcUrl
+ * @param {string} scriptText
+ * @return {string}
+ * @private
+ */
+ goog.wrapModule_ = function(srcUrl, scriptText) {
+ if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) {
+ return '' +
+ 'goog.loadModule(function(exports) {' +
+ '"use strict";' +
+ scriptText +
+ '\n' + // terminate any trailing single line comment.
+ ';return exports' +
+ '});' +
+ '\n//# sourceURL=' + srcUrl + '\n';
+ } else {
+ return '' +
+ 'goog.loadModule(' +
+ goog.global.JSON.stringify(
+ scriptText + '\n//# sourceURL=' + srcUrl + '\n') +
+ ');';
+ }
+ };
+
+ // On IE9 and earlier, it is necessary to handle
+ // deferred module loads. In later browsers, the
+ // code to be evaluated is simply inserted as a script
+ // block in the correct order. To eval deferred
+ // code at the right time, we piggy back on goog.require to call
+ // goog.maybeProcessDeferredDep_.
+ //
+ // The goog.requires are used both to bootstrap
+ // the loading process (when no deps are available) and
+ // declare that they should be available.
+ //
+ // Here we eval the sources, if all the deps are available
+ // either already eval'd or goog.require'd. This will
+ // be the case when all the dependencies have already
+ // been loaded, and the dependent module is loaded.
+ //
+ // But this alone isn't sufficient because it is also
+ // necessary to handle the case where there is no root
+ // that is not deferred. For that there we register for an event
+ // and trigger goog.loadQueuedModules_ handle any remaining deferred
+ // evaluations.
+
+ /**
+ * Handle any remaining deferred goog.module evals.
+ * @private
+ */
+ goog.loadQueuedModules_ = function() {
+ var count = goog.queuedModules_.length;
+ if (count > 0) {
+ var queue = goog.queuedModules_;
+ goog.queuedModules_ = [];
+ for (var i = 0; i < count; i++) {
+ var path = queue[i];
+ goog.maybeProcessDeferredPath_(path);
+ }
+ }
+ };
+
+
+ /**
+ * Eval the named module if its dependencies are
+ * available.
+ * @param {string} name The module to load.
+ * @private
+ */
+ goog.maybeProcessDeferredDep_ = function(name) {
+ if (goog.isDeferredModule_(name) &&
+ goog.allDepsAreAvailable_(name)) {
+ var path = goog.getPathFromDeps_(name);
+ goog.maybeProcessDeferredPath_(goog.basePath + path);
+ }
+ };
+
+ /**
+ * @param {string} name The module to check.
+ * @return {boolean} Whether the name represents a
+ * module whose evaluation has been deferred.
+ * @private
+ */
+ goog.isDeferredModule_ = function(name) {
+ var path = goog.getPathFromDeps_(name);
+ if (path && goog.dependencies_.pathIsModule[path]) {
+ var abspath = goog.basePath + path;
+ return (abspath) in goog.dependencies_.deferred;
+ }
+ return false;
+ };
+
+ /**
+ * @param {string} name The module to check.
+ * @return {boolean} Whether the name represents a
+ * module whose declared dependencies have all been loaded
+ * (eval'd or a deferred module load)
+ * @private
+ */
+ goog.allDepsAreAvailable_ = function(name) {
+ var path = goog.getPathFromDeps_(name);
+ if (path && (path in goog.dependencies_.requires)) {
+ for (var requireName in goog.dependencies_.requires[path]) {
+ if (!goog.isProvided_(requireName) &&
+ !goog.isDeferredModule_(requireName)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+
+ /**
+ * @param {string} abspath
+ * @private
+ */
+ goog.maybeProcessDeferredPath_ = function(abspath) {
+ if (abspath in goog.dependencies_.deferred) {
+ var src = goog.dependencies_.deferred[abspath];
+ delete goog.dependencies_.deferred[abspath];
+ goog.globalEval(src);
+ }
+ };
+
+
+ /**
+ * @param {function(?):?|string} moduleDef The module definition.
+ */
+ goog.loadModule = function(moduleDef) {
+ // NOTE: we allow function definitions to be either in the from
+ // of a string to eval (which keeps the original source intact) or
+ // in a eval forbidden environment (CSP) we allow a function definition
+ // which in its body must call {@code goog.module}, and return the exports
+ // of the module.
+ var previousState = goog.moduleLoaderState_;
+ try {
+ goog.moduleLoaderState_ = {
+ moduleName: undefined, declareTestMethods: false};
+ var exports;
+ if (goog.isFunction(moduleDef)) {
+ exports = moduleDef.call(goog.global, {});
+ } else if (goog.isString(moduleDef)) {
+ exports = goog.loadModuleFromSource_.call(goog.global, moduleDef);
+ } else {
+ throw Error('Invalid module definition');
+ }
+
+ var moduleName = goog.moduleLoaderState_.moduleName;
+ if (!goog.isString(moduleName) || !moduleName) {
+ throw Error('Invalid module name \"' + moduleName + '\"');
+ }
+
+ // Don't seal legacy namespaces as they may be uses as a parent of
+ // another namespace
+ if (goog.moduleLoaderState_.declareLegacyNamespace) {
+ goog.constructNamespace_(moduleName, exports);
+ } else if (goog.SEAL_MODULE_EXPORTS && Object.seal) {
+ Object.seal(exports);
+ }
+
+ goog.loadedModules_[moduleName] = exports;
+ if (goog.moduleLoaderState_.declareTestMethods) {
+ for (var entry in exports) {
+ if (entry.indexOf('test', 0) === 0 ||
+ entry == 'tearDown' ||
+ entry == 'setUp' ||
+ entry == 'setUpPage' ||
+ entry == 'tearDownPage') {
+ goog.global[entry] = exports[entry];
+ }
+ }
+ }
+ } finally {
+ goog.moduleLoaderState_ = previousState;
+ }
+ };
+
+
+ /**
+ * @param {string} source
+ * @return {!Object}
+ * @private
+ */
+ goog.loadModuleFromSource_ = function(source) {
+ // NOTE: we avoid declaring parameters or local variables here to avoid
+ // masking globals or leaking values into the module definition.
+ 'use strict';
+ var exports = {};
+ eval(arguments[0]);
+ return exports;
+ };
+
+
+ /**
+ * The default implementation of the import function. Writes a script tag to
+ * import the script.
+ *
+ * @param {string} src The script url.
+ * @param {string=} opt_sourceText The optionally source text to evaluate
+ * @return {boolean} True if the script was imported, false otherwise.
+ * @private
+ */
+ goog.writeScriptTag_ = function(src, opt_sourceText) {
+ if (goog.inHtmlDocument_()) {
+ var doc = goog.global.document;
+
+ // If the user tries to require a new symbol after document load,
+ // something has gone terribly wrong. Doing a document.write would
+ // wipe out the page.
+ if (doc.readyState == 'complete') {
+ // Certain test frameworks load base.js multiple times, which tries
+ // to write deps.js each time. If that happens, just fail silently.
+ // These frameworks wipe the page between each load of base.js, so this
+ // is OK.
+ var isDeps = /\bdeps.js$/.test(src);
+ if (isDeps) {
+ return false;
+ } else {
+ throw Error('Cannot write "' + src + '" after document load');
+ }
+ }
+
+ var isOldIE = goog.IS_OLD_IE_;
+
+ if (opt_sourceText === undefined) {
+ if (!isOldIE) {
+ doc.write(
+ '<script type="application/javascript" src="' +
+ src + '"></' + 'script>');
+ } else {
+ var state = " onreadystatechange='goog.onScriptLoad_(this, " +
+ ++goog.lastNonModuleScriptIndex_ + ")' ";
+ doc.write(
+ '<script type="application/javascript" src="' +
+ src + '"' + state + '></' + 'script>');
+ }
+ } else {
+ doc.write(
+ '<script type="application/javascript">' +
+ opt_sourceText +
+ '</' + 'script>');
+ }
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+
+ /** @private {number} */
+ goog.lastNonModuleScriptIndex_ = 0;
+
+
+ /**
+ * A readystatechange handler for legacy IE
+ * @param {!HTMLScriptElement} script
+ * @param {number} scriptIndex
+ * @return {boolean}
+ * @private
+ */
+ goog.onScriptLoad_ = function(script, scriptIndex) {
+ // for now load the modules when we reach the last script,
+ // later allow more inter-mingling.
+ if (script.readyState == 'complete' &&
+ goog.lastNonModuleScriptIndex_ == scriptIndex) {
+ goog.loadQueuedModules_();
+ }
+ return true;
+ };
+
+ /**
+ * Resolves dependencies based on the dependencies added using addDependency
+ * and calls importScript_ in the correct order.
+ * @private
+ */
+ goog.writeScripts_ = function() {
+ /** @type {!Array<string>} The scripts we need to write this time. */
+ var scripts = [];
+ var seenScript = {};
+ var deps = goog.dependencies_;
+
+ /** @param {string} path */
+ function visitNode(path) {
+ if (path in deps.written) {
+ return;
+ }
+
+ // We have already visited this one. We can get here if we have cyclic
+ // dependencies.
+ if (path in deps.visited) {
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ return;
+ }
+
+ deps.visited[path] = true;
+
+ if (path in deps.requires) {
+ for (var requireName in deps.requires[path]) {
+ // If the required name is defined, we assume that it was already
+ // bootstrapped by other means.
+ if (!goog.isProvided_(requireName)) {
+ if (requireName in deps.nameToPath) {
+ visitNode(deps.nameToPath[requireName]);
+ } else {
+ throw Error('Undefined nameToPath for ' + requireName);
+ }
+ }
+ }
+ }
+
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ }
+
+ for (var path in goog.included_) {
+ if (!deps.written[path]) {
+ visitNode(path);
+ }
+ }
+
+ // record that we are going to load all these scripts.
+ for (var i = 0; i < scripts.length; i++) {
+ var path = scripts[i];
+ goog.dependencies_.written[path] = true;
+ }
+
+ // If a module is loaded synchronously then we need to
+ // clear the current inModuleLoader value, and restore it when we are
+ // done loading the current "requires".
+ var moduleState = goog.moduleLoaderState_;
+ goog.moduleLoaderState_ = null;
+
+ var loadingModule = false;
+ for (var i = 0; i < scripts.length; i++) {
+ var path = scripts[i];
+ if (path) {
+ if (!deps.pathIsModule[path]) {
+ goog.importScript_(goog.basePath + path);
+ } else {
+ loadingModule = true;
+ goog.importModule_(goog.basePath + path);
+ }
+ } else {
+ goog.moduleLoaderState_ = moduleState;
+ throw Error('Undefined script input');
+ }
+ }
+
+ // restore the current "module loading state"
+ goog.moduleLoaderState_ = moduleState;
+ };
+
+
+ /**
+ * Looks at the dependency rules and tries to determine the script file that
+ * fulfills a particular rule.
+ * @param {string} rule In the form goog.namespace.Class or project.script.
+ * @return {?string} Url corresponding to the rule, or null.
+ * @private
+ */
+ goog.getPathFromDeps_ = function(rule) {
+ if (rule in goog.dependencies_.nameToPath) {
+ return goog.dependencies_.nameToPath[rule];
+ } else {
+ return null;
+ }
+ };
+
+ goog.findBasePath_();
+
+ // Allow projects to manage the deps files themselves.
+ if (!goog.global.CLOSURE_NO_DEPS) {
+ goog.importScript_(goog.basePath + 'deps.js');
+ }
+}
+
+
+/**
+ * Normalize a file path by removing redundant ".." and extraneous "." file
+ * path components.
+ * @param {string} path
+ * @return {string}
+ * @private
+ */
+goog.normalizePath_ = function(path) {
+ var components = path.split('/');
+ var i = 0;
+ while (i < components.length) {
+ if (components[i] == '.') {
+ components.splice(i, 1);
+ } else if (i && components[i] == '..' &&
+ components[i - 1] && components[i - 1] != '..') {
+ components.splice(--i, 2);
+ } else {
+ i++;
+ }
+ }
+ return components.join('/');
+};
+
+
+/**
+ * Retrieve and execute a module.
+ * @param {string} src Script source URL.
+ * @private
+ */
+goog.retrieveAndExecModule_ = function(src) {
+ if (!COMPILED) {
+ // The full but non-canonicalized URL for later use.
+ var originalPath = src;
+ // Canonicalize the path, removing any /./ or /../ since Chrome's debugging
+ // console doesn't auto-canonicalize XHR loads as it does <script> srcs.
+ src = goog.normalizePath_(src);
+
+ var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
+ goog.writeScriptTag_;
+
+ var scriptText = null;
+
+ var xhr = new goog.global['XMLHttpRequest']();
+
+ /** @this {Object} */
+ xhr.onload = function() {
+ scriptText = this.responseText;
+ };
+ xhr.open('get', src, false);
+ xhr.send();
+
+ scriptText = xhr.responseText;
+
+ if (scriptText != null) {
+ var execModuleScript = goog.wrapModule_(src, scriptText);
+ var isOldIE = goog.IS_OLD_IE_;
+ if (isOldIE) {
+ goog.dependencies_.deferred[originalPath] = execModuleScript;
+ goog.queuedModules_.push(originalPath);
+ } else {
+ importScript(src, execModuleScript);
+ }
+ } else {
+ throw new Error('load of ' + src + 'failed');
+ }
+ }
+};
+
+
+//==============================================================================
+// Language Enhancements
+//==============================================================================
+
+
+/**
+ * This is a "fixed" version of the typeof operator. It differs from the typeof
+ * operator in such a way that null returns 'null' and arrays return 'array'.
+ * @param {*} value The value to get the type of.
+ * @return {string} The name of the type.
+ */
+goog.typeOf = function(value) {
+ var s = typeof value;
+ if (s == 'object') {
+ if (value) {
+ // Check these first, so we can avoid calling Object.prototype.toString if
+ // possible.
+ //
+ // IE improperly marshals tyepof across execution contexts, but a
+ // cross-context object will still return false for "instanceof Object".
+ if (value instanceof Array) {
+ return 'array';
+ } else if (value instanceof Object) {
+ return s;
+ }
+
+ // HACK: In order to use an Object prototype method on the arbitrary
+ // value, the compiler requires the value be cast to type Object,
+ // even though the ECMA spec explicitly allows it.
+ var className = Object.prototype.toString.call(
+ /** @type {Object} */ (value));
+ // In Firefox 3.6, attempting to access iframe window objects' length
+ // property throws an NS_ERROR_FAILURE, so we need to special-case it
+ // here.
+ if (className == '[object Window]') {
+ return 'object';
+ }
+
+ // We cannot always use constructor == Array or instanceof Array because
+ // different frames have different Array objects. In IE6, if the iframe
+ // where the array was created is destroyed, the array loses its
+ // prototype. Then dereferencing val.splice here throws an exception, so
+ // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
+ // so that will work. In this case, this function will return false and
+ // most array functions will still work because the array is still
+ // array-like (supports length and []) even though it has lost its
+ // prototype.
+ // Mark Miller noticed that Object.prototype.toString
+ // allows access to the unforgeable [[Class]] property.
+ // 15.2.4.2 Object.prototype.toString ( )
+ // When the toString method is called, the following steps are taken:
+ // 1. Get the [[Class]] property of this object.
+ // 2. Compute a string value by concatenating the three strings
+ // "[object ", Result(1), and "]".
+ // 3. Return Result(2).
+ // and this behavior survives the destruction of the execution context.
+ if ((className == '[object Array]' ||
+ // In IE all non value types are wrapped as objects across window
+ // boundaries (not iframe though) so we have to do object detection
+ // for this edge case.
+ typeof value.length == 'number' &&
+ typeof value.splice != 'undefined' &&
+ typeof value.propertyIsEnumerable != 'undefined' &&
+ !value.propertyIsEnumerable('splice')
+
+ )) {
+ return 'array';
+ }
+ // HACK: There is still an array case that fails.
+ // function ArrayImpostor() {}
+ // ArrayImpostor.prototype = [];
+ // var impostor = new ArrayImpostor;
+ // this can be fixed by getting rid of the fast path
+ // (value instanceof Array) and solely relying on
+ // (value && Object.prototype.toString.vall(value) === '[object Array]')
+ // but that would require many more function calls and is not warranted
+ // unless closure code is receiving objects from untrusted sources.
+
+ // IE in cross-window calls does not correctly marshal the function type
+ // (it appears just as an object) so we cannot use just typeof val ==
+ // 'function'. However, if the object has a call property, it is a
+ // function.
+ if ((className == '[object Function]' ||
+ typeof value.call != 'undefined' &&
+ typeof value.propertyIsEnumerable != 'undefined' &&
+ !value.propertyIsEnumerable('call'))) {
+ return 'function';
+ }
+
+ } else {
+ return 'null';
+ }
+
+ } else if (s == 'function' && typeof value.call == 'undefined') {
+ // In Safari typeof nodeList returns 'function', and on Firefox typeof
+ // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We
+ // would like to return object for those and we can detect an invalid
+ // function by making sure that the function object has a call method.
+ return 'object';
+ }
+ return s;
+};
+
+
+/**
+ * Returns true if the specified value is null.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is null.
+ */
+goog.isNull = function(val) {
+ return val === null;
+};
+
+
+/**
+ * Returns true if the specified value is defined and not null.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is defined and not null.
+ */
+goog.isDefAndNotNull = function(val) {
+ // Note that undefined == null.
+ return val != null;
+};
+
+
+/**
+ * Returns true if the specified value is an array.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArray = function(val) {
+ return goog.typeOf(val) == 'array';
+};
+
+
+/**
+ * Returns true if the object looks like an array. To qualify as array like
+ * the value needs to be either a NodeList or an object with a Number length
+ * property. As a special case, a function value is not array like, because its
+ * length property is fixed to correspond to the number of expected arguments.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArrayLike = function(val) {
+ var type = goog.typeOf(val);
+ // We do not use goog.isObject here in order to exclude function values.
+ return type == 'array' || type == 'object' && typeof val.length == 'number';
+};
+
+
+/**
+ * Returns true if the object looks like a Date. To qualify as Date-like the
+ * value needs to be an object and have a getFullYear() function.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a like a Date.
+ */
+goog.isDateLike = function(val) {
+ return goog.isObject(val) && typeof val.getFullYear == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is a string.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a string.
+ */
+goog.isString = function(val) {
+ return typeof val == 'string';
+};
+
+
+/**
+ * Returns true if the specified value is a boolean.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is boolean.
+ */
+goog.isBoolean = function(val) {
+ return typeof val == 'boolean';
+};
+
+
+/**
+ * Returns true if the specified value is a number.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a number.
+ */
+goog.isNumber = function(val) {
+ return typeof val == 'number';
+};
+
+
+/**
+ * Returns true if the specified value is a function.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a function.
+ */
+goog.isFunction = function(val) {
+ return goog.typeOf(val) == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is an object. This includes arrays and
+ * functions.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is an object.
+ */
+goog.isObject = function(val) {
+ var type = typeof val;
+ return type == 'object' && val != null || type == 'function';
+ // return Object(val) === val also works, but is slower, especially if val is
+ // not an object.
+};
+
+
+/**
+ * Gets a unique ID for an object. This mutates the object so that further calls
+ * with the same object as a parameter returns the same value. The unique ID is
+ * guaranteed to be unique across the current session amongst objects that are
+ * passed into {@code getUid}. There is no guarantee that the ID is unique or
+ * consistent across sessions. It is unsafe to generate unique ID for function
+ * prototypes.
+ *
+ * @param {Object} obj The object to get the unique ID for.
+ * @return {number} The unique ID for the object.
+ */
+goog.getUid = function(obj) {
+ // TODO(arv): Make the type stricter, do not accept null.
+
+ // In Opera window.hasOwnProperty exists but always returns false so we avoid
+ // using it. As a consequence the unique ID generated for BaseClass.prototype
+ // and SubClass.prototype will be the same.
+ return obj[goog.UID_PROPERTY_] ||
+ (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
+};
+
+
+/**
+ * Whether the given object is already assigned a unique ID.
+ *
+ * This does not modify the object.
+ *
+ * @param {!Object} obj The object to check.
+ * @return {boolean} Whether there is an assigned unique id for the object.
+ */
+goog.hasUid = function(obj) {
+ return !!obj[goog.UID_PROPERTY_];
+};
+
+
+/**
+ * Removes the unique ID from an object. This is useful if the object was
+ * previously mutated using {@code goog.getUid} in which case the mutation is
+ * undone.
+ * @param {Object} obj The object to remove the unique ID field from.
+ */
+goog.removeUid = function(obj) {
+ // TODO(arv): Make the type stricter, do not accept null.
+
+ // In IE, DOM nodes are not instances of Object and throw an exception if we
+ // try to delete. Instead we try to use removeAttribute.
+ if ('removeAttribute' in obj) {
+ obj.removeAttribute(goog.UID_PROPERTY_);
+ }
+ /** @preserveTry */
+ try {
+ delete obj[goog.UID_PROPERTY_];
+ } catch (ex) {
+ }
+};
+
+
+/**
+ * Name for unique ID property. Initialized in a way to help avoid collisions
+ * with other closure JavaScript on the same page.
+ * @type {string}
+ * @private
+ */
+goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);
+
+
+/**
+ * Counter for UID.
+ * @type {number}
+ * @private
+ */
+goog.uidCounter_ = 0;
+
+
+/**
+ * Adds a hash code field to an object. The hash code is unique for the
+ * given object.
+ * @param {Object} obj The object to get the hash code for.
+ * @return {number} The hash code for the object.
+ * @deprecated Use goog.getUid instead.
+ */
+goog.getHashCode = goog.getUid;
+
+
+/**
+ * Removes the hash code field from an object.
+ * @param {Object} obj The object to remove the field from.
+ * @deprecated Use goog.removeUid instead.
+ */
+goog.removeHashCode = goog.removeUid;
+
+
+/**
+ * Clones a value. The input may be an Object, Array, or basic type. Objects and
+ * arrays will be cloned recursively.
+ *
+ * WARNINGS:
+ * <code>goog.cloneObject</code> does not detect reference loops. Objects that
+ * refer to themselves will cause infinite recursion.
+ *
+ * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
+ * UIDs created by <code>getUid</code> into cloned results.
+ *
+ * @param {*} obj The value to clone.
+ * @return {*} A clone of the input value.
+ * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
+ */
+goog.cloneObject = function(obj) {
+ var type = goog.typeOf(obj);
+ if (type == 'object' || type == 'array') {
+ if (obj.clone) {
+ return obj.clone();
+ }
+ var clone = type == 'array' ? [] : {};
+ for (var key in obj) {
+ clone[key] = goog.cloneObject(obj[key]);
+ }
+ return clone;
+ }
+
+ return obj;
+};
+
+
+/**
+ * A native implementation of goog.bind.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which this should
+ * point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially applied to the
+ * function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ * @private
+ * @suppress {deprecated} The compiler thinks that Function.prototype.bind is
+ * deprecated because some people have declared a pure-JS version.
+ * Only the pure-JS version is truly deprecated.
+ */
+goog.bindNative_ = function(fn, selfObj, var_args) {
+ return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
+};
+
+
+/**
+ * A pure-JS implementation of goog.bind.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which this should
+ * point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially applied to the
+ * function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ * @private
+ */
+goog.bindJs_ = function(fn, selfObj, var_args) {
+ if (!fn) {
+ throw new Error();
+ }
+
+ if (arguments.length > 2) {
+ var boundArgs = Array.prototype.slice.call(arguments, 2);
+ return function() {
+ // Prepend the bound arguments to the current arguments.
+ var newArgs = Array.prototype.slice.call(arguments);
+ Array.prototype.unshift.apply(newArgs, boundArgs);
+ return fn.apply(selfObj, newArgs);
+ };
+
+ } else {
+ return function() {
+ return fn.apply(selfObj, arguments);
+ };
+ }
+};
+
+
+/**
+ * Partially applies this function to a particular 'this object' and zero or
+ * more arguments. The result is a new function with some arguments of the first
+ * function pre-filled and the value of this 'pre-specified'.
+ *
+ * Remaining arguments specified at call-time are appended to the pre-specified
+ * ones.
+ *
+ * Also see: {@link #partial}.
+ *
+ * Usage:
+ * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
+ * barMethBound('arg3', 'arg4');</pre>
+ *
+ * @param {?function(this:T, ...)} fn A function to partially apply.
+ * @param {T} selfObj Specifies the object which this should point to when the
+ * function is run.
+ * @param {...*} var_args Additional arguments that are partially applied to the
+ * function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ * @template T
+ * @suppress {deprecated} See above.
+ */
+goog.bind = function(fn, selfObj, var_args) {
+ // TODO(nicksantos): narrow the type signature.
+ if (Function.prototype.bind &&
+ // NOTE(nicksantos): Somebody pulled base.js into the default Chrome
+ // extension environment. This means that for Chrome extensions, they get
+ // the implementation of Function.prototype.bind that calls goog.bind
+ // instead of the native one. Even worse, we don't want to introduce a
+ // circular dependency between goog.bind and Function.prototype.bind, so
+ // we have to hack this to make sure it works correctly.
+ Function.prototype.bind.toString().indexOf('native code') != -1) {
+ goog.bind = goog.bindNative_;
+ } else {
+ goog.bind = goog.bindJs_;
+ }
+ return goog.bind.apply(null, arguments);
+};
+
+
+/**
+ * Like bind(), except that a 'this object' is not required. Useful when the
+ * target function is already bound.
+ *
+ * Usage:
+ * var g = partial(f, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {...*} var_args Additional arguments that are partially applied to fn.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.partial = function(fn, var_args) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() {
+ // Clone the array (with slice()) and append additional arguments
+ // to the existing arguments.
+ var newArgs = args.slice();
+ newArgs.push.apply(newArgs, arguments);
+ return fn.apply(this, newArgs);
+ };
+};
+
+
+/**
+ * Copies all the members of a source object to a target object. This method
+ * does not work on all browsers for all objects that contain keys such as
+ * toString or hasOwnProperty. Use goog.object.extend for this purpose.
+ * @param {Object} target Target.
+ * @param {Object} source Source.
+ */
+goog.mixin = function(target, source) {
+ for (var x in source) {
+ target[x] = source[x];
+ }
+
+ // For IE7 or lower, the for-in-loop does not contain any properties that are
+ // not enumerable on the prototype object (for example, isPrototypeOf from
+ // Object.prototype) but also it will not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+};
+
+
+/**
+ * @return {number} An integer value representing the number of milliseconds
+ * between midnight, January 1, 1970 and the current time.
+ */
+goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {
+ // Unary plus operator converts its operand to a number which in the case of
+ // a date is done by calling getTime().
+ return +new Date();
+});
+
+
+/**
+ * Evals JavaScript in the global scope. In IE this uses execScript, other
+ * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
+ * global scope (for example, in Safari), appends a script tag instead.
+ * Throws an exception if neither execScript or eval is defined.
+ * @param {string} script JavaScript string.
+ */
+goog.globalEval = function(script) {
+ if (goog.global.execScript) {
+ goog.global.execScript(script, 'JavaScript');
+ } else if (goog.global.eval) {
+ // Test to see if eval works
+ if (goog.evalWorksForGlobals_ == null) {
+ goog.global.eval('var _et_ = 1;');
+ if (typeof goog.global['_et_'] != 'undefined') {
+ delete goog.global['_et_'];
+ goog.evalWorksForGlobals_ = true;
+ } else {
+ goog.evalWorksForGlobals_ = false;
+ }
+ }
+
+ if (goog.evalWorksForGlobals_) {
+ goog.global.eval(script);
+ } else {
+ var doc = goog.global.document;
+ var scriptElt = doc.createElement('SCRIPT');
+ scriptElt.type = 'application/javascript';
+ scriptElt.defer = false;
+ // Note(user): can't use .innerHTML since "t('<test>')" will fail and
+ // .text doesn't work in Safari 2. Therefore we append a text node.
+ scriptElt.appendChild(doc.createTextNode(script));
+ doc.body.appendChild(scriptElt);
+ doc.body.removeChild(scriptElt);
+ }
+ } else {
+ throw Error('goog.globalEval not available');
+ }
+};
+
+
+/**
+ * Indicates whether or not we can call 'eval' directly to eval code in the
+ * global scope. Set to a Boolean by the first call to goog.globalEval (which
+ * empirically tests whether eval works for globals). @see goog.globalEval
+ * @type {?boolean}
+ * @private
+ */
+goog.evalWorksForGlobals_ = null;
+
+
+/**
+ * Optional map of CSS class names to obfuscated names used with
+ * goog.getCssName().
+ * @private {!Object<string, string>|undefined}
+ * @see goog.setCssNameMapping
+ */
+goog.cssNameMapping_;
+
+
+/**
+ * Optional obfuscation style for CSS class names. Should be set to either
+ * 'BY_WHOLE' or 'BY_PART' if defined.
+ * @type {string|undefined}
+ * @private
+ * @see goog.setCssNameMapping
+ */
+goog.cssNameMappingStyle_;
+
+
+/**
+ * Handles strings that are intended to be used as CSS class names.
+ *
+ * This function works in tandem with @see goog.setCssNameMapping.
+ *
+ * Without any mapping set, the arguments are simple joined with a hyphen and
+ * passed through unaltered.
+ *
+ * When there is a mapping, there are two possible styles in which these
+ * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)
+ * of the passed in css name is rewritten according to the map. In the BY_WHOLE
+ * style, the full css name is looked up in the map directly. If a rewrite is
+ * not specified by the map, the compiler will output a warning.
+ *
+ * When the mapping is passed to the compiler, it will replace calls to
+ * goog.getCssName with the strings from the mapping, e.g.
+ * var x = goog.getCssName('foo');
+ * var y = goog.getCssName(this.baseClass, 'active');
+ * becomes:
+ * var x= 'foo';
+ * var y = this.baseClass + '-active';
+ *
+ * If one argument is passed it will be processed, if two are passed only the
+ * modifier will be processed, as it is assumed the first argument was generated
+ * as a result of calling goog.getCssName.
+ *
+ * @param {string} className The class name.
+ * @param {string=} opt_modifier A modifier to be appended to the class name.
+ * @return {string} The class name or the concatenation of the class name and
+ * the modifier.
+ */
+goog.getCssName = function(className, opt_modifier) {
+ var getMapping = function(cssName) {
+ return goog.cssNameMapping_[cssName] || cssName;
+ };
+
+ var renameByParts = function(cssName) {
+ // Remap all the parts individually.
+ var parts = cssName.split('-');
+ var mapped = [];
+ for (var i = 0; i < parts.length; i++) {
+ mapped.push(getMapping(parts[i]));
+ }
+ return mapped.join('-');
+ };
+
+ var rename;
+ if (goog.cssNameMapping_) {
+ rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
+ getMapping : renameByParts;
+ } else {
+ rename = function(a) {
+ return a;
+ };
+ }
+
+ if (opt_modifier) {
+ return className + '-' + rename(opt_modifier);
+ } else {
+ return rename(className);
+ }
+};
+
+
+/**
+ * Sets the map to check when returning a value from goog.getCssName(). Example:
+ * <pre>
+ * goog.setCssNameMapping({
+ * "goog": "a",
+ * "disabled": "b",
+ * });
+ *
+ * var x = goog.getCssName('goog');
+ * // The following evaluates to: "a a-b".
+ * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
+ * </pre>
+ * When declared as a map of string literals to string literals, the JSCompiler
+ * will replace all calls to goog.getCssName() using the supplied map if the
+ * --closure_pass flag is set.
+ *
+ * @param {!Object} mapping A map of strings to strings where keys are possible
+ * arguments to goog.getCssName() and values are the corresponding values
+ * that should be returned.
+ * @param {string=} opt_style The style of css name mapping. There are two valid
+ * options: 'BY_PART', and 'BY_WHOLE'.
+ * @see goog.getCssName for a description.
+ */
+goog.setCssNameMapping = function(mapping, opt_style) {
+ goog.cssNameMapping_ = mapping;
+ goog.cssNameMappingStyle_ = opt_style;
+};
+
+
+/**
+ * To use CSS renaming in compiled mode, one of the input files should have a
+ * call to goog.setCssNameMapping() with an object literal that the JSCompiler
+ * can extract and use to replace all calls to goog.getCssName(). In uncompiled
+ * mode, JavaScript code should be loaded before this base.js file that declares
+ * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
+ * to ensure that the mapping is loaded before any calls to goog.getCssName()
+ * are made in uncompiled mode.
+ *
+ * A hook for overriding the CSS name mapping.
+ * @type {!Object<string, string>|undefined}
+ */
+goog.global.CLOSURE_CSS_NAME_MAPPING;
+
+
+if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
+ // This does not call goog.setCssNameMapping() because the JSCompiler
+ // requires that goog.setCssNameMapping() be called with an object literal.
+ goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
+}
+
+
+/**
+ * Gets a localized message.
+ *
+ * This function is a compiler primitive. If you give the compiler a localized
+ * message bundle, it will replace the string at compile-time with a localized
+ * version, and expand goog.getMsg call to a concatenated string.
+ *
+ * Messages must be initialized in the form:
+ * <code>
+ * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
+ * </code>
+ *
+ * @param {string} str Translatable string, places holders in the form {$foo}.
+ * @param {Object<string, string>=} opt_values Maps place holder name to value.
+ * @return {string} message with placeholders filled.
+ */
+goog.getMsg = function(str, opt_values) {
+ if (opt_values) {
+ str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
+ return key in opt_values ? opt_values[key] : match;
+ });
+ }
+ return str;
+};
+
+
+/**
+ * Gets a localized message. If the message does not have a translation, gives a
+ * fallback message.
+ *
+ * This is useful when introducing a new message that has not yet been
+ * translated into all languages.
+ *
+ * This function is a compiler primitive. Must be used in the form:
+ * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>
+ * where MSG_A and MSG_B were initialized with goog.getMsg.
+ *
+ * @param {string} a The preferred message.
+ * @param {string} b The fallback message.
+ * @return {string} The best translated message.
+ */
+goog.getMsgWithFallback = function(a, b) {
+ return a;
+};
+
+
+/**
+ * Exposes an unobfuscated global namespace path for the given object.
+ * Note that fields of the exported object *will* be obfuscated, unless they are
+ * exported in turn via this function or goog.exportProperty.
+ *
+ * Also handy for making public items that are defined in anonymous closures.
+ *
+ * ex. goog.exportSymbol('public.path.Foo', Foo);
+ *
+ * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);
+ * public.path.Foo.staticFunction();
+ *
+ * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
+ * Foo.prototype.myMethod);
+ * new public.path.Foo().myMethod();
+ *
+ * @param {string} publicPath Unobfuscated name to export.
+ * @param {*} object Object the name should point to.
+ * @param {Object=} opt_objectToExportTo The object to add the path to; default
+ * is goog.global.
+ */
+goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
+ goog.exportPath_(publicPath, object, opt_objectToExportTo);
+};
+
+
+/**
+ * Exports a property unobfuscated into the object's namespace.
+ * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
+ * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
+ * @param {Object} object Object whose static property is being exported.
+ * @param {string} publicName Unobfuscated name to export.
+ * @param {*} symbol Object the name should point to.
+ */
+goog.exportProperty = function(object, publicName, symbol) {
+ object[publicName] = symbol;
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * Usage:
+ * <pre>
+ * function ParentClass(a, b) { }
+ * ParentClass.prototype.foo = function(a) { };
+ *
+ * function ChildClass(a, b, c) {
+ * ChildClass.base(this, 'constructor', a, b);
+ * }
+ * goog.inherits(ChildClass, ParentClass);
+ *
+ * var child = new ChildClass('a', 'b', 'see');
+ * child.foo(); // This works.
+ * </pre>
+ *
+ * @param {Function} childCtor Child class.
+ * @param {Function} parentCtor Parent class.
+ */
+goog.inherits = function(childCtor, parentCtor) {
+ /** @constructor */
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ /** @override */
+ childCtor.prototype.constructor = childCtor;
+
+ /**
+ * Calls superclass constructor/method.
+ *
+ * This function is only available if you use goog.inherits to
+ * express inheritance relationships between classes.
+ *
+ * NOTE: This is a replacement for goog.base and for superClass_
+ * property defined in childCtor.
+ *
+ * @param {!Object} me Should always be "this".
+ * @param {string} methodName The method name to call. Calling
+ * superclass constructor can be done with the special string
+ * 'constructor'.
+ * @param {...*} var_args The arguments to pass to superclass
+ * method/constructor.
+ * @return {*} The return value of the superclass method/constructor.
+ */
+ childCtor.base = function(me, methodName, var_args) {
+ // Copying using loop to avoid deop due to passing arguments object to
+ // function. This is faster in many JS engines as of late 2014.
+ var args = new Array(arguments.length - 2);
+ for (var i = 2; i < arguments.length; i++) {
+ args[i - 2] = arguments[i];
+ }
+ return parentCtor.prototype[methodName].apply(me, args);
+ };
+};
+
+
+/**
+ * Call up to the superclass.
+ *
+ * If this is called from a constructor, then this calls the superclass
+ * constructor with arguments 1-N.
+ *
+ * If this is called from a prototype method, then you must pass the name of the
+ * method as the second argument to this function. If you do not, you will get a
+ * runtime error. This calls the superclass' method with arguments 2-N.
+ *
+ * This function only works if you use goog.inherits to express inheritance
+ * relationships between your classes.
+ *
+ * This function is a compiler primitive. At compile-time, the compiler will do
+ * macro expansion to remove a lot of the extra overhead that this function
+ * introduces. The compiler will also enforce a lot of the assumptions that this
+ * function makes, and treat it as a compiler error if you break them.
+ *
+ * @param {!Object} me Should always be "this".
+ * @param {*=} opt_methodName The method name if calling a super method.
+ * @param {...*} var_args The rest of the arguments.
+ * @return {*} The return value of the superclass method.
+ * @suppress {es5Strict} This method can not be used in strict mode, but
+ * all Closure Library consumers must depend on this file.
+ */
+goog.base = function(me, opt_methodName, var_args) {
+ var caller = arguments.callee.caller;
+
+ if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {
+ throw Error('arguments.caller not defined. goog.base() cannot be used ' +
+ 'with strict mode code. See ' +
+ 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
+ }
+
+ if (caller.superClass_) {
+ // Copying using loop to avoid deop due to passing arguments object to
+ // function. This is faster in many JS engines as of late 2014.
+ var ctorArgs = new Array(arguments.length - 1);
+ for (var i = 1; i < arguments.length; i++) {
+ ctorArgs[i - 1] = arguments[i];
+ }
+ // This is a constructor. Call the superclass constructor.
+ return caller.superClass_.constructor.apply(me, ctorArgs);
+ }
+
+ // Copying using loop to avoid deop due to passing arguments object to
+ // function. This is faster in many JS engines as of late 2014.
+ var args = new Array(arguments.length - 2);
+ for (var i = 2; i < arguments.length; i++) {
+ args[i - 2] = arguments[i];
+ }
+ var foundCaller = false;
+ for (var ctor = me.constructor;
+ ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
+ if (ctor.prototype[opt_methodName] === caller) {
+ foundCaller = true;
+ } else if (foundCaller) {
+ return ctor.prototype[opt_methodName].apply(me, args);
+ }
+ }
+
+ // If we did not find the caller in the prototype chain, then one of two
+ // things happened:
+ // 1) The caller is an instance method.
+ // 2) This method was not called by the right caller.
+ if (me[opt_methodName] === caller) {
+ return me.constructor.prototype[opt_methodName].apply(me, args);
+ } else {
+ throw Error(
+ 'goog.base called from a method of one name ' +
+ 'to a method of a different name');
+ }
+};
+
+
+/**
+ * Allow for aliasing within scope functions. This function exists for
+ * uncompiled code - in compiled code the calls will be inlined and the aliases
+ * applied. In uncompiled code the function is simply run since the aliases as
+ * written are valid JavaScript.
+ *
+ *
+ * @param {function()} fn Function to call. This function can contain aliases
+ * to namespaces (e.g. "var dom = goog.dom") or classes
+ * (e.g. "var Timer = goog.Timer").
+ */
+goog.scope = function(fn) {
+ fn.call(goog.global);
+};
+
+
+/*
+ * To support uncompiled, strict mode bundles that use eval to divide source
+ * like so:
+ * eval('someSource;//# sourceUrl sourcefile.js');
+ * We need to export the globally defined symbols "goog" and "COMPILED".
+ * Exporting "goog" breaks the compiler optimizations, so we required that
+ * be defined externally.
+ * NOTE: We don't use goog.exportSymbol here because we don't want to trigger
+ * extern generation when that compiler option is enabled.
+ */
+if (!COMPILED) {
+ goog.global['COMPILED'] = COMPILED;
+}
+
+
+
+//==============================================================================
+// goog.defineClass implementation
+//==============================================================================
+
+
+/**
+ * Creates a restricted form of a Closure "class":
+ * - from the compiler's perspective, the instance returned from the
+ * constructor is sealed (no new properties may be added). This enables
+ * better checks.
+ * - the compiler will rewrite this definition to a form that is optimal
+ * for type checking and optimization (initially this will be a more
+ * traditional form).
+ *
+ * @param {Function} superClass The superclass, Object or null.
+ * @param {goog.defineClass.ClassDescriptor} def
+ * An object literal describing
+ * the class. It may have the following properties:
+ * "constructor": the constructor function
+ * "statics": an object literal containing methods to add to the constructor
+ * as "static" methods or a function that will receive the constructor
+ * function as its only parameter to which static properties can
+ * be added.
+ * all other properties are added to the prototype.
+ * @return {!Function} The class constructor.
+ */
+goog.defineClass = function(superClass, def) {
+ // TODO(johnlenz): consider making the superClass an optional parameter.
+ var constructor = def.constructor;
+ var statics = def.statics;
+ // Wrap the constructor prior to setting up the prototype and static methods.
+ if (!constructor || constructor == Object.prototype.constructor) {
+ constructor = function() {
+ throw Error('cannot instantiate an interface (no constructor defined).');
+ };
+ }
+
+ var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);
+ if (superClass) {
+ goog.inherits(cls, superClass);
+ }
+
+ // Remove all the properties that should not be copied to the prototype.
+ delete def.constructor;
+ delete def.statics;
+
+ goog.defineClass.applyProperties_(cls.prototype, def);
+ if (statics != null) {
+ if (statics instanceof Function) {
+ statics(cls);
+ } else {
+ goog.defineClass.applyProperties_(cls, statics);
+ }
+ }
+
+ return cls;
+};
+
+
+/**
+ * @typedef {
+ * !Object|
+ * {constructor:!Function}|
+ * {constructor:!Function, statics:(Object|function(Function):void)}}
+ * @suppress {missingProvide}
+ */
+goog.defineClass.ClassDescriptor;
+
+
+/**
+ * @define {boolean} Whether the instances returned by
+ * goog.defineClass should be sealed when possible.
+ */
+goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);
+
+
+/**
+ * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is
+ * defined, this function will wrap the constructor in a function that seals the
+ * results of the provided constructor function.
+ *
+ * @param {!Function} ctr The constructor whose results maybe be sealed.
+ * @param {Function} superClass The superclass constructor.
+ * @return {!Function} The replacement constructor.
+ * @private
+ */
+goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
+ if (goog.defineClass.SEAL_CLASS_INSTANCES &&
+ Object.seal instanceof Function) {
+ // Don't seal subclasses of unsealable-tagged legacy classes.
+ if (superClass && superClass.prototype &&
+ superClass.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]) {
+ return ctr;
+ }
+ /**
+ * @this {Object}
+ * @return {?}
+ */
+ var wrappedCtr = function() {
+ // Don't seal an instance of a subclass when it calls the constructor of
+ // its super class as there is most likely still setup to do.
+ var instance = ctr.apply(this, arguments) || this;
+ instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];
+ if (this.constructor === wrappedCtr) {
+ Object.seal(instance);
+ }
+ return instance;
+ };
+ return wrappedCtr;
+ }
+ return ctr;
+};
+
+
+// TODO(johnlenz): share these values with the goog.object
+/**
+ * The names of the fields that are defined on Object.prototype.
+ * @type {!Array<string>}
+ * @private
+ * @const
+ */
+goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [
+ 'constructor',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'toLocaleString',
+ 'toString',
+ 'valueOf'
+];
+
+
+// TODO(johnlenz): share this function with the goog.object
+/**
+ * @param {!Object} target The object to add properties to.
+ * @param {!Object} source The object to copy properties from.
+ * @private
+ */
+goog.defineClass.applyProperties_ = function(target, source) {
+ // TODO(johnlenz): update this to support ES5 getters/setters
+
+ var key;
+ for (key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+
+ // For IE the for-in-loop does not contain any properties that are not
+ // enumerable on the prototype object (for example isPrototypeOf from
+ // Object.prototype) and it will also not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+ for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {
+ key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+};
+
+
+/**
+ * Sealing classes breaks the older idiom of assigning properties on the
+ * prototype rather than in the constructor. As such, goog.defineClass
+ * must not seal subclasses of these old-style classes until they are fixed.
+ * Until then, this marks a class as "broken", instructing defineClass
+ * not to seal subclasses.
+ * @param {!Function} ctr The legacy constructor to tag as unsealable.
+ */
+goog.tagUnsealableClass = function(ctr) {
+ if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) {
+ ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true;
+ }
+};
+
+
+/**
+ * Name for unsealable tag property.
+ * @const @private {string}
+ */
+goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable';
diff --git a/dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/deps.js b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/deps.js
new file mode 100644
index 0000000000..c64782643c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/closure-library/closure/goog/deps.js
@@ -0,0 +1,1465 @@
+// Copyright 2015 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file has been auto-generated by GenJsDeps, please do not edit.
+
+goog.addDependency('../../third_party/closure/goog/caja/string/html/htmlparser.js', ['goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlParser.Entities', 'goog.string.html.HtmlSaxHandler'], [], false);
+goog.addDependency('../../third_party/closure/goog/caja/string/html/htmlsanitizer.js', ['goog.string.html.HtmlSanitizer', 'goog.string.html.HtmlSanitizer.AttributeType', 'goog.string.html.HtmlSanitizer.Attributes', 'goog.string.html.htmlSanitize'], ['goog.string.StringBuffer', 'goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlSaxHandler'], false);
+goog.addDependency('../../third_party/closure/goog/dojo/dom/query.js', ['goog.dom.query'], ['goog.array', 'goog.dom', 'goog.functions', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('../../third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js', ['goog.crypt.JpegEncoder'], ['goog.crypt.base64'], false);
+goog.addDependency('../../third_party/closure/goog/loremipsum/text/loremipsum.js', ['goog.text.LoremIpsum'], ['goog.array', 'goog.math', 'goog.string', 'goog.structs.Map', 'goog.structs.Set'], false);
+goog.addDependency('../../third_party/closure/goog/mochikit/async/deferred.js', ['goog.async.Deferred', 'goog.async.Deferred.AlreadyCalledError', 'goog.async.Deferred.CanceledError'], ['goog.Promise', 'goog.Thenable', 'goog.array', 'goog.asserts', 'goog.debug.Error'], false);
+goog.addDependency('../../third_party/closure/goog/mochikit/async/deferredlist.js', ['goog.async.DeferredList'], ['goog.async.Deferred'], false);
+goog.addDependency('../../third_party/closure/goog/osapi/osapi.js', ['goog.osapi'], [], false);
+goog.addDependency('../../third_party/closure/goog/svgpan/svgpan.js', ['svgpan.SvgPan'], ['goog.Disposable', 'goog.events', 'goog.events.EventType', 'goog.events.MouseWheelHandler'], false);
+goog.addDependency('a11y/aria/announcer.js', ['goog.a11y.aria.Announcer'], ['goog.Disposable', 'goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.object'], false);
+goog.addDependency('a11y/aria/announcer_test.js', ['goog.a11y.aria.AnnouncerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Announcer', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.iframe', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('a11y/aria/aria.js', ['goog.a11y.aria'], ['goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.a11y.aria.datatables', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.object', 'goog.string'], false);
+goog.addDependency('a11y/aria/aria_test.js', ['goog.a11y.ariaTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit'], false);
+goog.addDependency('a11y/aria/attributes.js', ['goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.CheckedValues', 'goog.a11y.aria.DropEffectValues', 'goog.a11y.aria.ExpandedValues', 'goog.a11y.aria.GrabbedValues', 'goog.a11y.aria.InvalidValues', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.OrientationValues', 'goog.a11y.aria.PressedValues', 'goog.a11y.aria.RelevantValues', 'goog.a11y.aria.SelectedValues', 'goog.a11y.aria.SortValues', 'goog.a11y.aria.State'], [], false);
+goog.addDependency('a11y/aria/datatables.js', ['goog.a11y.aria.datatables'], ['goog.a11y.aria.State', 'goog.object'], false);
+goog.addDependency('a11y/aria/roles.js', ['goog.a11y.aria.Role'], [], false);
+goog.addDependency('array/array.js', ['goog.array', 'goog.array.ArrayLike'], ['goog.asserts'], false);
+goog.addDependency('array/array_test.js', ['goog.arrayTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('asserts/asserts.js', ['goog.asserts', 'goog.asserts.AssertionError'], ['goog.debug.Error', 'goog.dom.NodeType', 'goog.string'], false);
+goog.addDependency('asserts/asserts_test.js', ['goog.assertsTest'], ['goog.asserts', 'goog.asserts.AssertionError', 'goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('async/animationdelay.js', ['goog.async.AnimationDelay'], ['goog.Disposable', 'goog.events', 'goog.functions'], false);
+goog.addDependency('async/animationdelay_test.js', ['goog.async.AnimationDelayTest'], ['goog.async.AnimationDelay', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('async/conditionaldelay.js', ['goog.async.ConditionalDelay'], ['goog.Disposable', 'goog.async.Delay'], false);
+goog.addDependency('async/conditionaldelay_test.js', ['goog.async.ConditionalDelayTest'], ['goog.async.ConditionalDelay', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('async/delay.js', ['goog.Delay', 'goog.async.Delay'], ['goog.Disposable', 'goog.Timer'], false);
+goog.addDependency('async/delay_test.js', ['goog.async.DelayTest'], ['goog.async.Delay', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('async/freelist.js', ['goog.async.FreeList'], [], false);
+goog.addDependency('async/freelist_test.js', ['goog.async.FreeListTest'], ['goog.async.FreeList', 'goog.testing.jsunit'], false);
+goog.addDependency('async/nexttick.js', ['goog.async.nextTick', 'goog.async.throwException'], ['goog.debug.entryPointRegistry', 'goog.dom.TagName', 'goog.functions', 'goog.labs.userAgent.browser', 'goog.labs.userAgent.engine'], false);
+goog.addDependency('async/nexttick_test.js', ['goog.async.nextTickTest'], ['goog.async.nextTick', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.dom', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('async/run.js', ['goog.async.run'], ['goog.async.WorkQueue', 'goog.async.nextTick', 'goog.async.throwException', 'goog.testing.watchers'], false);
+goog.addDependency('async/run_test.js', ['goog.async.runTest'], ['goog.async.run', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('async/throttle.js', ['goog.Throttle', 'goog.async.Throttle'], ['goog.Disposable', 'goog.Timer'], false);
+goog.addDependency('async/throttle_test.js', ['goog.async.ThrottleTest'], ['goog.async.Throttle', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('async/workqueue.js', ['goog.async.WorkItem', 'goog.async.WorkQueue'], ['goog.asserts', 'goog.async.FreeList'], false);
+goog.addDependency('async/workqueue_test.js', ['goog.async.WorkQueueTest'], ['goog.async.WorkQueue', 'goog.testing.jsunit'], false);
+goog.addDependency('base.js', ['goog'], [], false);
+goog.addDependency('base_module_test.js', ['goog.baseModuleTest'], ['goog.Timer', 'goog.test_module', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], true);
+goog.addDependency('base_test.js', ['an.existing.path', 'dup.base', 'far.out', 'goog.baseTest', 'goog.explicit', 'goog.implicit.explicit', 'goog.test', 'goog.test.name', 'goog.test.name.space', 'goog.xy', 'goog.xy.z', 'ns', 'testDep.bar'], ['goog.Timer', 'goog.dom.TagName', 'goog.functions', 'goog.test_module', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('color/alpha.js', ['goog.color.alpha'], ['goog.color'], false);
+goog.addDependency('color/alpha_test.js', ['goog.color.alphaTest'], ['goog.array', 'goog.color', 'goog.color.alpha', 'goog.testing.jsunit'], false);
+goog.addDependency('color/color.js', ['goog.color', 'goog.color.Hsl', 'goog.color.Hsv', 'goog.color.Rgb'], ['goog.color.names', 'goog.math'], false);
+goog.addDependency('color/color_test.js', ['goog.colorTest'], ['goog.array', 'goog.color', 'goog.color.names', 'goog.testing.jsunit'], false);
+goog.addDependency('color/names.js', ['goog.color.names'], [], false);
+goog.addDependency('crypt/aes.js', ['goog.crypt.Aes'], ['goog.asserts', 'goog.crypt.BlockCipher'], false);
+goog.addDependency('crypt/aes_test.js', ['goog.crypt.AesTest'], ['goog.crypt', 'goog.crypt.Aes', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/arc4.js', ['goog.crypt.Arc4'], ['goog.asserts'], false);
+goog.addDependency('crypt/arc4_test.js', ['goog.crypt.Arc4Test'], ['goog.array', 'goog.crypt.Arc4', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/base64.js', ['goog.crypt.base64'], ['goog.crypt', 'goog.userAgent'], false);
+goog.addDependency('crypt/base64_test.js', ['goog.crypt.base64Test'], ['goog.crypt', 'goog.crypt.base64', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/basen.js', ['goog.crypt.baseN'], [], false);
+goog.addDependency('crypt/basen_test.js', ['goog.crypt.baseNTest'], ['goog.crypt.baseN', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/blobhasher.js', ['goog.crypt.BlobHasher', 'goog.crypt.BlobHasher.EventType'], ['goog.asserts', 'goog.events.EventTarget', 'goog.fs', 'goog.log'], false);
+goog.addDependency('crypt/blobhasher_test.js', ['goog.crypt.BlobHasherTest'], ['goog.crypt', 'goog.crypt.BlobHasher', 'goog.crypt.Md5', 'goog.events', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/blockcipher.js', ['goog.crypt.BlockCipher'], [], false);
+goog.addDependency('crypt/bytestring_perf.js', ['goog.crypt.byteArrayToStringPerf'], ['goog.array', 'goog.dom', 'goog.testing.PerformanceTable'], false);
+goog.addDependency('crypt/cbc.js', ['goog.crypt.Cbc'], ['goog.array', 'goog.asserts', 'goog.crypt'], false);
+goog.addDependency('crypt/cbc_test.js', ['goog.crypt.CbcTest'], ['goog.crypt', 'goog.crypt.Aes', 'goog.crypt.Cbc', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/crypt.js', ['goog.crypt'], ['goog.array', 'goog.asserts'], false);
+goog.addDependency('crypt/crypt_test.js', ['goog.cryptTest'], ['goog.crypt', 'goog.string', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/hash.js', ['goog.crypt.Hash'], [], false);
+goog.addDependency('crypt/hash32.js', ['goog.crypt.hash32'], ['goog.crypt'], false);
+goog.addDependency('crypt/hash32_test.js', ['goog.crypt.hash32Test'], ['goog.crypt.hash32', 'goog.testing.TestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/hashtester.js', ['goog.crypt.hashTester'], ['goog.array', 'goog.crypt', 'goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTable', 'goog.testing.PseudoRandom', 'goog.testing.asserts'], false);
+goog.addDependency('crypt/hmac.js', ['goog.crypt.Hmac'], ['goog.crypt.Hash'], false);
+goog.addDependency('crypt/hmac_test.js', ['goog.crypt.HmacTest'], ['goog.crypt.Hmac', 'goog.crypt.Sha1', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/md5.js', ['goog.crypt.Md5'], ['goog.crypt.Hash'], false);
+goog.addDependency('crypt/md5_test.js', ['goog.crypt.Md5Test'], ['goog.crypt', 'goog.crypt.Md5', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/pbkdf2.js', ['goog.crypt.pbkdf2'], ['goog.array', 'goog.asserts', 'goog.crypt', 'goog.crypt.Hmac', 'goog.crypt.Sha1'], false);
+goog.addDependency('crypt/pbkdf2_test.js', ['goog.crypt.pbkdf2Test'], ['goog.crypt', 'goog.crypt.pbkdf2', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('crypt/sha1.js', ['goog.crypt.Sha1'], ['goog.crypt.Hash'], false);
+goog.addDependency('crypt/sha1_test.js', ['goog.crypt.Sha1Test'], ['goog.crypt', 'goog.crypt.Sha1', 'goog.crypt.hashTester', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('crypt/sha2.js', ['goog.crypt.Sha2'], ['goog.array', 'goog.asserts', 'goog.crypt.Hash'], false);
+goog.addDependency('crypt/sha224.js', ['goog.crypt.Sha224'], ['goog.crypt.Sha2'], false);
+goog.addDependency('crypt/sha224_test.js', ['goog.crypt.Sha224Test'], ['goog.crypt', 'goog.crypt.Sha224', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/sha256.js', ['goog.crypt.Sha256'], ['goog.crypt.Sha2'], false);
+goog.addDependency('crypt/sha256_test.js', ['goog.crypt.Sha256Test'], ['goog.crypt', 'goog.crypt.Sha256', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false);
+goog.addDependency('crypt/sha2_64bit.js', ['goog.crypt.Sha2_64bit'], ['goog.array', 'goog.asserts', 'goog.crypt.Hash', 'goog.math.Long'], false);
+goog.addDependency('crypt/sha2_64bit_test.js', ['goog.crypt.Sha2_64bit_test'], ['goog.array', 'goog.crypt', 'goog.crypt.Sha384', 'goog.crypt.Sha512', 'goog.crypt.Sha512_256', 'goog.crypt.hashTester', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('crypt/sha384.js', ['goog.crypt.Sha384'], ['goog.crypt.Sha2_64bit'], false);
+goog.addDependency('crypt/sha512.js', ['goog.crypt.Sha512'], ['goog.crypt.Sha2_64bit'], false);
+goog.addDependency('crypt/sha512_256.js', ['goog.crypt.Sha512_256'], ['goog.crypt.Sha2_64bit'], false);
+goog.addDependency('cssom/cssom.js', ['goog.cssom', 'goog.cssom.CssRuleType'], ['goog.array', 'goog.dom', 'goog.dom.TagName'], false);
+goog.addDependency('cssom/cssom_test.js', ['goog.cssomTest'], ['goog.array', 'goog.cssom', 'goog.cssom.CssRuleType', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('cssom/iframe/style.js', ['goog.cssom.iframe.style'], ['goog.asserts', 'goog.cssom', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('cssom/iframe/style_test.js', ['goog.cssom.iframe.styleTest'], ['goog.cssom', 'goog.cssom.iframe.style', 'goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('datasource/datamanager.js', ['goog.ds.DataManager'], ['goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.Expr', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.Map'], false);
+goog.addDependency('datasource/datasource.js', ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState', 'goog.ds.SortedNodeList', 'goog.ds.Util', 'goog.ds.logger'], ['goog.array', 'goog.log'], false);
+goog.addDependency('datasource/datasource_test.js', ['goog.ds.JsDataSourceTest'], ['goog.dom.xml', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.SortedNodeList', 'goog.ds.XmlDataSource', 'goog.testing.jsunit'], false);
+goog.addDependency('datasource/expr.js', ['goog.ds.Expr'], ['goog.ds.BasicNodeList', 'goog.ds.EmptyNodeList', 'goog.string'], false);
+goog.addDependency('datasource/expr_test.js', ['goog.ds.ExprTest'], ['goog.ds.DataManager', 'goog.ds.Expr', 'goog.ds.JsDataSource', 'goog.testing.jsunit'], false);
+goog.addDependency('datasource/fastdatanode.js', ['goog.ds.AbstractFastDataNode', 'goog.ds.FastDataNode', 'goog.ds.FastListNode', 'goog.ds.PrimitiveFastDataNode'], ['goog.ds.DataManager', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.string'], false);
+goog.addDependency('datasource/fastdatanode_test.js', ['goog.ds.FastDataNodeTest'], ['goog.array', 'goog.ds.DataManager', 'goog.ds.Expr', 'goog.ds.FastDataNode', 'goog.testing.jsunit'], false);
+goog.addDependency('datasource/jsdatasource.js', ['goog.ds.JsDataSource', 'goog.ds.JsPropertyDataSource'], ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.DataNode', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState'], false);
+goog.addDependency('datasource/jsondatasource.js', ['goog.ds.JsonDataSource'], ['goog.Uri', 'goog.dom', 'goog.dom.TagName', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.log'], false);
+goog.addDependency('datasource/jsxmlhttpdatasource.js', ['goog.ds.JsXmlHttpDataSource'], ['goog.Uri', 'goog.ds.DataManager', 'goog.ds.FastDataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.events', 'goog.log', 'goog.net.EventType', 'goog.net.XhrIo'], false);
+goog.addDependency('datasource/jsxmlhttpdatasource_test.js', ['goog.ds.JsXmlHttpDataSourceTest'], ['goog.ds.JsXmlHttpDataSource', 'goog.testing.TestQueue', 'goog.testing.jsunit', 'goog.testing.net.XhrIo'], false);
+goog.addDependency('datasource/xmldatasource.js', ['goog.ds.XmlDataSource', 'goog.ds.XmlHttpDataSource'], ['goog.Uri', 'goog.dom.NodeType', 'goog.dom.xml', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.DataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.net.XhrIo', 'goog.string'], false);
+goog.addDependency('date/date.js', ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay'], ['goog.asserts', 'goog.date.DateLike', 'goog.i18n.DateTimeSymbols', 'goog.string'], false);
+goog.addDependency('date/date_test.js', ['goog.dateTest'], ['goog.array', 'goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay', 'goog.i18n.DateTimeSymbols', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.platform', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('date/datelike.js', ['goog.date.DateLike'], [], false);
+goog.addDependency('date/daterange.js', ['goog.date.DateRange', 'goog.date.DateRange.Iterator', 'goog.date.DateRange.StandardDateRangeKeys'], ['goog.date.Date', 'goog.date.Interval', 'goog.iter.Iterator', 'goog.iter.StopIteration'], false);
+goog.addDependency('date/daterange_test.js', ['goog.date.DateRangeTest'], ['goog.date.Date', 'goog.date.DateRange', 'goog.date.Interval', 'goog.i18n.DateTimeSymbols', 'goog.testing.jsunit'], false);
+goog.addDependency('date/duration.js', ['goog.date.duration'], ['goog.i18n.DateTimeFormat', 'goog.i18n.MessageFormat'], false);
+goog.addDependency('date/duration_test.js', ['goog.date.durationTest'], ['goog.date.duration', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.testing.jsunit'], false);
+goog.addDependency('date/relative.js', ['goog.date.relative', 'goog.date.relative.TimeDeltaFormatter', 'goog.date.relative.Unit'], ['goog.i18n.DateTimeFormat'], false);
+goog.addDependency('date/relative_test.js', ['goog.date.relativeTest'], ['goog.date.DateTime', 'goog.date.relative', 'goog.i18n.DateTimeFormat', 'goog.testing.jsunit'], false);
+goog.addDependency('date/relativewithplurals.js', ['goog.date.relativeWithPlurals'], ['goog.date.relative', 'goog.date.relative.Unit', 'goog.i18n.MessageFormat'], false);
+goog.addDependency('date/relativewithplurals_test.js', ['goog.date.relativeWithPluralsTest'], ['goog.date.relative', 'goog.date.relativeTest', 'goog.date.relativeWithPlurals', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_fa'], false);
+goog.addDependency('date/utcdatetime.js', ['goog.date.UtcDateTime'], ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval'], false);
+goog.addDependency('date/utcdatetime_test.js', ['goog.date.UtcDateTimeTest'], ['goog.date.Interval', 'goog.date.UtcDateTime', 'goog.date.month', 'goog.date.weekDay', 'goog.testing.jsunit'], false);
+goog.addDependency('db/cursor.js', ['goog.db.Cursor'], ['goog.async.Deferred', 'goog.db.Error', 'goog.debug', 'goog.events.EventTarget'], false);
+goog.addDependency('db/db.js', ['goog.db', 'goog.db.BlockedCallback', 'goog.db.UpgradeNeededCallback'], ['goog.asserts', 'goog.async.Deferred', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.Transaction'], false);
+goog.addDependency('db/db_test.js', ['goog.dbTest'], ['goog.Disposable', 'goog.array', 'goog.async.Deferred', 'goog.async.DeferredList', 'goog.db', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.KeyRange', 'goog.db.Transaction', 'goog.events', 'goog.object', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('db/error.js', ['goog.db.Error', 'goog.db.Error.ErrorCode', 'goog.db.Error.ErrorName', 'goog.db.Error.VersionChangeBlockedError'], ['goog.debug.Error'], false);
+goog.addDependency('db/index.js', ['goog.db.Index'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.debug'], false);
+goog.addDependency('db/indexeddb.js', ['goog.db.IndexedDb'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.ObjectStore', 'goog.db.Transaction', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget'], false);
+goog.addDependency('db/keyrange.js', ['goog.db.KeyRange'], [], false);
+goog.addDependency('db/objectstore.js', ['goog.db.ObjectStore'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.Index', 'goog.debug', 'goog.events'], false);
+goog.addDependency('db/old_db_test.js', ['goog.oldDbTest'], ['goog.async.Deferred', 'goog.db', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.KeyRange', 'goog.db.Transaction', 'goog.events', 'goog.testing.AsyncTestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('db/transaction.js', ['goog.db.Transaction', 'goog.db.Transaction.TransactionMode'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.ObjectStore', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget'], false);
+goog.addDependency('debug/console.js', ['goog.debug.Console'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.debug.TextFormatter'], false);
+goog.addDependency('debug/console_test.js', ['goog.debug.ConsoleTest'], ['goog.debug.Console', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('debug/debug.js', ['goog.debug'], ['goog.array', 'goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.uncheckedconversions', 'goog.string.Const', 'goog.structs.Set', 'goog.userAgent'], false);
+goog.addDependency('debug/debug_test.js', ['goog.debugTest'], ['goog.debug', 'goog.html.SafeHtml', 'goog.structs.Set', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/debugwindow.js', ['goog.debug.DebugWindow'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyleSheet', 'goog.string.Const', 'goog.structs.CircularBuffer', 'goog.userAgent'], false);
+goog.addDependency('debug/debugwindow_test.js', ['goog.debug.DebugWindowTest'], ['goog.debug.DebugWindow', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/devcss/devcss.js', ['goog.debug.DevCss', 'goog.debug.DevCss.UserAgent'], ['goog.asserts', 'goog.cssom', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('debug/devcss/devcss_test.js', ['goog.debug.DevCssTest'], ['goog.debug.DevCss', 'goog.style', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/devcss/devcssrunner.js', ['goog.debug.devCssRunner'], ['goog.debug.DevCss'], false);
+goog.addDependency('debug/divconsole.js', ['goog.debug.DivConsole'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.style'], false);
+goog.addDependency('debug/enhanceerror_test.js', ['goog.debugEnhanceErrorTest'], ['goog.debug', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/entrypointregistry.js', ['goog.debug.EntryPointMonitor', 'goog.debug.entryPointRegistry'], ['goog.asserts'], false);
+goog.addDependency('debug/entrypointregistry_test.js', ['goog.debug.entryPointRegistryTest'], ['goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/error.js', ['goog.debug.Error'], [], false);
+goog.addDependency('debug/error_test.js', ['goog.debug.ErrorTest'], ['goog.debug.Error', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('debug/errorhandler.js', ['goog.debug.ErrorHandler', 'goog.debug.ErrorHandler.ProtectedFunctionError'], ['goog.Disposable', 'goog.asserts', 'goog.debug', 'goog.debug.EntryPointMonitor', 'goog.debug.Error', 'goog.debug.Trace'], false);
+goog.addDependency('debug/errorhandler_async_test.js', ['goog.debug.ErrorHandlerAsyncTest'], ['goog.debug.ErrorHandler', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('debug/errorhandler_test.js', ['goog.debug.ErrorHandlerTest'], ['goog.debug.ErrorHandler', 'goog.testing.MockControl', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/errorhandlerweakdep.js', ['goog.debug.errorHandlerWeakDep'], [], false);
+goog.addDependency('debug/errorreporter.js', ['goog.debug.ErrorReporter', 'goog.debug.ErrorReporter.ExceptionEvent'], ['goog.asserts', 'goog.debug', 'goog.debug.Error', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.log', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.uri.utils', 'goog.userAgent'], false);
+goog.addDependency('debug/errorreporter_test.js', ['goog.debug.ErrorReporterTest'], ['goog.debug.Error', 'goog.debug.ErrorReporter', 'goog.events', 'goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('debug/fancywindow.js', ['goog.debug.FancyWindow'], ['goog.array', 'goog.debug.DebugWindow', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyleSheet', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.userAgent'], false);
+goog.addDependency('debug/formatter.js', ['goog.debug.Formatter', 'goog.debug.HtmlFormatter', 'goog.debug.TextFormatter'], ['goog.debug', 'goog.debug.Logger', 'goog.debug.RelativeTimeProvider', 'goog.html.SafeHtml'], false);
+goog.addDependency('debug/formatter_test.js', ['goog.debug.FormatterTest'], ['goog.debug.HtmlFormatter', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.html.SafeHtml', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/fpsdisplay.js', ['goog.debug.FpsDisplay'], ['goog.asserts', 'goog.async.AnimationDelay', 'goog.dom', 'goog.dom.TagName', 'goog.ui.Component'], false);
+goog.addDependency('debug/fpsdisplay_test.js', ['goog.debug.FpsDisplayTest'], ['goog.debug.FpsDisplay', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/gcdiagnostics.js', ['goog.debug.GcDiagnostics'], ['goog.debug.Trace', 'goog.log', 'goog.userAgent'], false);
+goog.addDependency('debug/logbuffer.js', ['goog.debug.LogBuffer'], ['goog.asserts', 'goog.debug.LogRecord'], false);
+goog.addDependency('debug/logbuffer_test.js', ['goog.debug.LogBufferTest'], ['goog.debug.LogBuffer', 'goog.debug.Logger', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/logger.js', ['goog.debug.LogManager', 'goog.debug.Loggable', 'goog.debug.Logger', 'goog.debug.Logger.Level'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.LogBuffer', 'goog.debug.LogRecord'], false);
+goog.addDependency('debug/logger_test.js', ['goog.debug.LoggerTest'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/logrecord.js', ['goog.debug.LogRecord'], [], false);
+goog.addDependency('debug/logrecordserializer.js', ['goog.debug.logRecordSerializer'], ['goog.debug.LogRecord', 'goog.debug.Logger', 'goog.json', 'goog.object'], false);
+goog.addDependency('debug/logrecordserializer_test.js', ['goog.debug.logRecordSerializerTest'], ['goog.debug.LogRecord', 'goog.debug.Logger', 'goog.debug.logRecordSerializer', 'goog.testing.jsunit'], false);
+goog.addDependency('debug/relativetimeprovider.js', ['goog.debug.RelativeTimeProvider'], [], false);
+goog.addDependency('debug/tracer.js', ['goog.debug.Trace'], ['goog.array', 'goog.debug.Logger', 'goog.iter', 'goog.log', 'goog.structs.Map', 'goog.structs.SimplePool'], false);
+goog.addDependency('debug/tracer_test.js', ['goog.debug.TraceTest'], ['goog.debug.Trace', 'goog.testing.jsunit'], false);
+goog.addDependency('defineclass_test.js', ['goog.defineClassTest'], ['goog.testing.jsunit'], false);
+goog.addDependency('disposable/disposable.js', ['goog.Disposable', 'goog.dispose', 'goog.disposeAll'], ['goog.disposable.IDisposable'], false);
+goog.addDependency('disposable/disposable_test.js', ['goog.DisposableTest'], ['goog.Disposable', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('disposable/idisposable.js', ['goog.disposable.IDisposable'], [], false);
+goog.addDependency('dom/abstractmultirange.js', ['goog.dom.AbstractMultiRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange'], false);
+goog.addDependency('dom/abstractrange.js', ['goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.SavedCaretRange', 'goog.dom.TagIterator', 'goog.userAgent'], false);
+goog.addDependency('dom/abstractrange_test.js', ['goog.dom.AbstractRangeTest'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.Range', 'goog.dom.TagName', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/animationframe/animationframe.js', ['goog.dom.animationFrame', 'goog.dom.animationFrame.Spec', 'goog.dom.animationFrame.State'], ['goog.dom.animationFrame.polyfill'], false);
+goog.addDependency('dom/animationframe/polyfill.js', ['goog.dom.animationFrame.polyfill'], [], false);
+goog.addDependency('dom/annotate.js', ['goog.dom.annotate', 'goog.dom.annotate.AnnotateFn'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml'], false);
+goog.addDependency('dom/annotate_test.js', ['goog.dom.annotateTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.annotate', 'goog.html.SafeHtml', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/browserfeature.js', ['goog.dom.BrowserFeature'], ['goog.userAgent'], false);
+goog.addDependency('dom/browserrange/abstractrange.js', ['goog.dom.browserrange.AbstractRange'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter', 'goog.math.Coordinate', 'goog.string', 'goog.string.StringBuffer', 'goog.userAgent'], false);
+goog.addDependency('dom/browserrange/browserrange.js', ['goog.dom.browserrange', 'goog.dom.browserrange.Error'], ['goog.dom', 'goog.dom.BrowserFeature', 'goog.dom.NodeType', 'goog.dom.browserrange.GeckoRange', 'goog.dom.browserrange.IeRange', 'goog.dom.browserrange.OperaRange', 'goog.dom.browserrange.W3cRange', 'goog.dom.browserrange.WebKitRange', 'goog.userAgent'], false);
+goog.addDependency('dom/browserrange/browserrange_test.js', ['goog.dom.browserrangeTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/browserrange/geckorange.js', ['goog.dom.browserrange.GeckoRange'], ['goog.dom.browserrange.W3cRange'], false);
+goog.addDependency('dom/browserrange/ierange.js', ['goog.dom.browserrange.IeRange'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange.AbstractRange', 'goog.log', 'goog.string'], false);
+goog.addDependency('dom/browserrange/operarange.js', ['goog.dom.browserrange.OperaRange'], ['goog.dom.browserrange.W3cRange'], false);
+goog.addDependency('dom/browserrange/w3crange.js', ['goog.dom.browserrange.W3cRange'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange.AbstractRange', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('dom/browserrange/webkitrange.js', ['goog.dom.browserrange.WebKitRange'], ['goog.dom.RangeEndpoint', 'goog.dom.browserrange.W3cRange', 'goog.userAgent'], false);
+goog.addDependency('dom/bufferedviewportsizemonitor.js', ['goog.dom.BufferedViewportSizeMonitor'], ['goog.asserts', 'goog.async.Delay', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType'], false);
+goog.addDependency('dom/bufferedviewportsizemonitor_test.js', ['goog.dom.BufferedViewportSizeMonitorTest'], ['goog.dom.BufferedViewportSizeMonitor', 'goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.EventType', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/classes.js', ['goog.dom.classes'], ['goog.array'], false);
+goog.addDependency('dom/classes_test.js', ['goog.dom.classes_test'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/classlist.js', ['goog.dom.classlist'], ['goog.array'], false);
+goog.addDependency('dom/classlist_test.js', ['goog.dom.classlist_test'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/controlrange.js', ['goog.dom.ControlRange', 'goog.dom.ControlRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagWalkType', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.userAgent'], false);
+goog.addDependency('dom/controlrange_test.js', ['goog.dom.ControlRangeTest'], ['goog.dom', 'goog.dom.ControlRange', 'goog.dom.RangeType', 'goog.dom.TagName', 'goog.dom.TextRange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/dataset.js', ['goog.dom.dataset'], ['goog.string', 'goog.userAgent.product'], false);
+goog.addDependency('dom/dataset_test.js', ['goog.dom.datasetTest'], ['goog.dom', 'goog.dom.dataset', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/dom.js', ['goog.dom', 'goog.dom.Appendable', 'goog.dom.DomHelper'], ['goog.array', 'goog.asserts', 'goog.dom.BrowserFeature', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.math.Coordinate', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.userAgent'], false);
+goog.addDependency('dom/dom_test.js', ['goog.dom.dom_test'], ['goog.dom', 'goog.dom.BrowserFeature', 'goog.dom.DomHelper', 'goog.dom.InputType', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.functions', 'goog.html.testing', 'goog.object', 'goog.string.Unicode', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('dom/fontsizemonitor.js', ['goog.dom.FontSizeMonitor', 'goog.dom.FontSizeMonitor.EventType'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent'], false);
+goog.addDependency('dom/fontsizemonitor_test.js', ['goog.dom.FontSizeMonitorTest'], ['goog.dom', 'goog.dom.FontSizeMonitor', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/forms.js', ['goog.dom.forms'], ['goog.dom.InputType', 'goog.dom.TagName', 'goog.structs.Map'], false);
+goog.addDependency('dom/forms_test.js', ['goog.dom.formsTest'], ['goog.dom', 'goog.dom.forms', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/fullscreen.js', ['goog.dom.fullscreen', 'goog.dom.fullscreen.EventType'], ['goog.dom', 'goog.userAgent'], false);
+goog.addDependency('dom/iframe.js', ['goog.dom.iframe'], ['goog.dom', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.legacyconversions', 'goog.userAgent'], false);
+goog.addDependency('dom/iframe_test.js', ['goog.dom.iframeTest'], ['goog.dom', 'goog.dom.iframe', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/inputtype.js', ['goog.dom.InputType'], [], false);
+goog.addDependency('dom/inputtype_test.js', ['goog.dom.InputTypeTest'], ['goog.dom.InputType', 'goog.object'], false);
+goog.addDependency('dom/iter.js', ['goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator'], ['goog.iter.Iterator', 'goog.iter.StopIteration'], false);
+goog.addDependency('dom/iter_test.js', ['goog.dom.iterTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.testing.dom', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/multirange.js', ['goog.dom.MultiRange', 'goog.dom.MultiRangeIterator'], ['goog.array', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.log'], false);
+goog.addDependency('dom/multirange_test.js', ['goog.dom.MultiRangeTest'], ['goog.dom', 'goog.dom.MultiRange', 'goog.dom.Range', 'goog.iter', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/nodeiterator.js', ['goog.dom.NodeIterator'], ['goog.dom.TagIterator'], false);
+goog.addDependency('dom/nodeiterator_test.js', ['goog.dom.NodeIteratorTest'], ['goog.dom', 'goog.dom.NodeIterator', 'goog.testing.dom', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/nodeoffset.js', ['goog.dom.NodeOffset'], ['goog.Disposable', 'goog.dom.TagName'], false);
+goog.addDependency('dom/nodeoffset_test.js', ['goog.dom.NodeOffsetTest'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/nodetype.js', ['goog.dom.NodeType'], [], false);
+goog.addDependency('dom/pattern/abstractpattern.js', ['goog.dom.pattern.AbstractPattern'], ['goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/pattern/allchildren.js', ['goog.dom.pattern.AllChildren'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/pattern/callback/callback.js', ['goog.dom.pattern.callback'], ['goog.dom', 'goog.dom.TagWalkType', 'goog.iter'], false);
+goog.addDependency('dom/pattern/callback/counter.js', ['goog.dom.pattern.callback.Counter'], [], false);
+goog.addDependency('dom/pattern/callback/test.js', ['goog.dom.pattern.callback.Test'], ['goog.iter.StopIteration'], false);
+goog.addDependency('dom/pattern/childmatches.js', ['goog.dom.pattern.ChildMatches'], ['goog.dom.pattern.AllChildren', 'goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/pattern/endtag.js', ['goog.dom.pattern.EndTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag'], false);
+goog.addDependency('dom/pattern/fulltag.js', ['goog.dom.pattern.FullTag'], ['goog.dom.pattern.MatchType', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Tag'], false);
+goog.addDependency('dom/pattern/matcher.js', ['goog.dom.pattern.Matcher'], ['goog.dom.TagIterator', 'goog.dom.pattern.MatchType', 'goog.iter'], false);
+goog.addDependency('dom/pattern/matcher_test.js', ['goog.dom.pattern.matcherTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.pattern.EndTag', 'goog.dom.pattern.FullTag', 'goog.dom.pattern.Matcher', 'goog.dom.pattern.Repeat', 'goog.dom.pattern.Sequence', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.callback.Counter', 'goog.dom.pattern.callback.Test', 'goog.iter.StopIteration', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/pattern/nodetype.js', ['goog.dom.pattern.NodeType'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/pattern/pattern.js', ['goog.dom.pattern', 'goog.dom.pattern.MatchType'], [], false);
+goog.addDependency('dom/pattern/pattern_test.js', ['goog.dom.patternTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagWalkType', 'goog.dom.pattern.AllChildren', 'goog.dom.pattern.ChildMatches', 'goog.dom.pattern.EndTag', 'goog.dom.pattern.FullTag', 'goog.dom.pattern.MatchType', 'goog.dom.pattern.NodeType', 'goog.dom.pattern.Repeat', 'goog.dom.pattern.Sequence', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Text', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/pattern/repeat.js', ['goog.dom.pattern.Repeat'], ['goog.dom.NodeType', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/pattern/sequence.js', ['goog.dom.pattern.Sequence'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/pattern/starttag.js', ['goog.dom.pattern.StartTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag'], false);
+goog.addDependency('dom/pattern/tag.js', ['goog.dom.pattern.Tag'], ['goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType', 'goog.object'], false);
+goog.addDependency('dom/pattern/text.js', ['goog.dom.pattern.Text'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false);
+goog.addDependency('dom/range.js', ['goog.dom.Range'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.BrowserFeature', 'goog.dom.ControlRange', 'goog.dom.MultiRange', 'goog.dom.NodeType', 'goog.dom.TextRange', 'goog.userAgent'], false);
+goog.addDependency('dom/range_test.js', ['goog.dom.RangeTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeType', 'goog.dom.TagName', 'goog.dom.TextRange', 'goog.dom.browserrange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/rangeendpoint.js', ['goog.dom.RangeEndpoint'], [], false);
+goog.addDependency('dom/safe.js', ['goog.dom.safe'], ['goog.html.SafeHtml', 'goog.html.SafeUrl'], false);
+goog.addDependency('dom/safe_test.js', ['goog.dom.safeTest'], ['goog.dom.safe', 'goog.html.SafeUrl', 'goog.html.testing', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/savedcaretrange.js', ['goog.dom.SavedCaretRange'], ['goog.array', 'goog.dom', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.string'], false);
+goog.addDependency('dom/savedcaretrange_test.js', ['goog.dom.SavedCaretRangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.SavedCaretRange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/savedrange.js', ['goog.dom.SavedRange'], ['goog.Disposable', 'goog.log'], false);
+goog.addDependency('dom/savedrange_test.js', ['goog.dom.SavedRangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/selection.js', ['goog.dom.selection'], ['goog.dom.InputType', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('dom/selection_test.js', ['goog.dom.selectionTest'], ['goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.selection', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/tagiterator.js', ['goog.dom.TagIterator', 'goog.dom.TagWalkType'], ['goog.dom', 'goog.dom.NodeType', 'goog.iter.Iterator', 'goog.iter.StopIteration'], false);
+goog.addDependency('dom/tagiterator_test.js', ['goog.dom.TagIteratorTest'], ['goog.dom', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.dom.TagWalkType', 'goog.iter', 'goog.iter.StopIteration', 'goog.testing.dom', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/tagname.js', ['goog.dom.TagName'], [], false);
+goog.addDependency('dom/tagname_test.js', ['goog.dom.TagNameTest'], ['goog.dom.TagName', 'goog.object', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/tags.js', ['goog.dom.tags'], ['goog.object'], false);
+goog.addDependency('dom/tags_test.js', ['goog.dom.tagsTest'], ['goog.dom.tags', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/textrange.js', ['goog.dom.TextRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.dom.browserrange', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('dom/textrange_test.js', ['goog.dom.TextRangeTest'], ['goog.dom', 'goog.dom.ControlRange', 'goog.dom.Range', 'goog.dom.TextRange', 'goog.math.Coordinate', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('dom/textrangeiterator.js', ['goog.dom.TextRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeIterator', 'goog.dom.TagName', 'goog.iter.StopIteration'], false);
+goog.addDependency('dom/textrangeiterator_test.js', ['goog.dom.TextRangeIteratorTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter.StopIteration', 'goog.testing.dom', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/vendor.js', ['goog.dom.vendor'], ['goog.string', 'goog.userAgent'], false);
+goog.addDependency('dom/vendor_test.js', ['goog.dom.vendorTest'], ['goog.array', 'goog.dom.vendor', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil'], false);
+goog.addDependency('dom/viewportsizemonitor.js', ['goog.dom.ViewportSizeMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size'], false);
+goog.addDependency('dom/viewportsizemonitor_test.js', ['goog.dom.ViewportSizeMonitorTest'], ['goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('dom/xml.js', ['goog.dom.xml'], ['goog.dom', 'goog.dom.NodeType'], false);
+goog.addDependency('dom/xml_test.js', ['goog.dom.xmlTest'], ['goog.dom.TagName', 'goog.dom.xml', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/browserfeature.js', ['goog.editor.BrowserFeature'], ['goog.editor.defines', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('editor/browserfeature_test.js', ['goog.editor.BrowserFeatureTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/clicktoeditwrapper.js', ['goog.editor.ClickToEditWrapper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.range', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.log'], false);
+goog.addDependency('editor/clicktoeditwrapper_test.js', ['goog.editor.ClickToEditWrapperTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.ClickToEditWrapper', 'goog.editor.SeamlessField', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('editor/command.js', ['goog.editor.Command'], [], false);
+goog.addDependency('editor/contenteditablefield.js', ['goog.editor.ContentEditableField'], ['goog.asserts', 'goog.editor.Field', 'goog.log'], false);
+goog.addDependency('editor/contenteditablefield_test.js', ['goog.editor.ContentEditableFieldTest'], ['goog.dom', 'goog.editor.ContentEditableField', 'goog.editor.field_test', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/defines.js', ['goog.editor.defines'], [], false);
+goog.addDependency('editor/field.js', ['goog.editor.Field', 'goog.editor.Field.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.array', 'goog.asserts', 'goog.async.Delay', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.editor.range', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.log', 'goog.log.Level', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('editor/field_test.js', ['goog.editor.field_test'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.LooseMock', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('editor/focus.js', ['goog.editor.focus'], ['goog.dom.selection'], false);
+goog.addDependency('editor/focus_test.js', ['goog.editor.focusTest'], ['goog.dom.selection', 'goog.editor.BrowserFeature', 'goog.editor.focus', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/icontent.js', ['goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo'], ['goog.dom', 'goog.editor.BrowserFeature', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('editor/icontent_test.js', ['goog.editor.icontentTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/link.js', ['goog.editor.Link'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.string.Unicode', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex'], false);
+goog.addDependency('editor/link_test.js', ['goog.editor.LinkTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Link', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/node.js', ['goog.editor.node'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.iter', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.userAgent'], false);
+goog.addDependency('editor/node_test.js', ['goog.editor.nodeTest'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.node', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugin.js', ['goog.editor.Plugin'], ['goog.events.EventTarget', 'goog.functions', 'goog.log', 'goog.object', 'goog.reflect', 'goog.userAgent'], false);
+goog.addDependency('editor/plugin_test.js', ['goog.editor.PluginTest'], ['goog.editor.Field', 'goog.editor.Plugin', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/abstractbubbleplugin.js', ['goog.editor.plugins.AbstractBubblePlugin'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.Plugin', 'goog.editor.style', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.actionEventWrapper', 'goog.functions', 'goog.string.Unicode', 'goog.ui.Component', 'goog.ui.editor.Bubble', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/abstractbubbleplugin_test.js', ['goog.editor.plugins.AbstractBubblePluginTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.style', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.editor.Bubble', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/abstractdialogplugin.js', ['goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.plugins.AbstractDialogPlugin.EventType'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.ui.editor.AbstractDialog'], false);
+goog.addDependency('editor/plugins/abstractdialogplugin_test.js', ['goog.editor.plugins.AbstractDialogPluginTest'], ['goog.dom.SavedRange', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.Event', 'goog.events.EventHandler', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/abstracttabhandler.js', ['goog.editor.plugins.AbstractTabHandler'], ['goog.editor.Plugin', 'goog.events.KeyCodes', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/abstracttabhandler_test.js', ['goog.editor.plugins.AbstractTabHandlerTest'], ['goog.editor.Field', 'goog.editor.plugins.AbstractTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/basictextformatter.js', ['goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.BasicTextFormatter.COMMAND'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.editor.style', 'goog.iter', 'goog.iter.StopIteration', 'goog.log', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.editor.messages', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/basictextformatter_test.js', ['goog.editor.plugins.BasicTextFormatterTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.BasicTextFormatter', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.LooseMock', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/blockquote.js', ['goog.editor.plugins.Blockquote'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions', 'goog.log'], false);
+goog.addDependency('editor/plugins/blockquote_test.js', ['goog.editor.plugins.BlockquoteTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.plugins.Blockquote', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/plugins/emoticons.js', ['goog.editor.plugins.Emoticons'], ['goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.range', 'goog.functions', 'goog.ui.emoji.Emoji', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/emoticons_test.js', ['goog.editor.plugins.EmoticonsTest'], ['goog.Uri', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.Emoticons', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/enterhandler.js', ['goog.editor.plugins.EnterHandler'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.Blockquote', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.functions', 'goog.object', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/enterhandler_test.js', ['goog.editor.plugins.EnterHandlerTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.Blockquote', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.events', 'goog.events.KeyCodes', 'goog.testing.ExpectedFailures', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/firststrong.js', ['goog.editor.plugins.FirstStrong'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.i18n.bidi', 'goog.i18n.uChar', 'goog.iter', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/firststrong_test.js', ['goog.editor.plugins.FirstStrongTest'], ['goog.dom.Range', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.plugins.FirstStrong', 'goog.editor.range', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/headerformatter.js', ['goog.editor.plugins.HeaderFormatter'], ['goog.editor.Command', 'goog.editor.Plugin', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/headerformatter_test.js', ['goog.editor.plugins.HeaderFormatterTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.HeaderFormatter', 'goog.events.BrowserEvent', 'goog.testing.LooseMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/linkbubble.js', ['goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkBubble.Action'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.editor.range', 'goog.functions', 'goog.string', 'goog.style', 'goog.ui.editor.messages', 'goog.uri.utils', 'goog.window'], false);
+goog.addDependency('editor/plugins/linkbubble_test.js', ['goog.editor.plugins.LinkBubbleTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.LinkBubble', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.string', 'goog.style', 'goog.testing.FunctionMock', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/linkdialogplugin.js', ['goog.editor.plugins.LinkDialogPlugin'], ['goog.array', 'goog.dom', 'goog.editor.Command', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.EventHandler', 'goog.functions', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.uri.utils'], false);
+goog.addDependency('editor/plugins/linkdialogplugin_test.js', ['goog.ui.editor.plugins.LinkDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Link', 'goog.editor.plugins.LinkDialogPlugin', 'goog.string', 'goog.string.Unicode', 'goog.testing.MockControl', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.editor.dom', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/linkshortcutplugin.js', ['goog.editor.plugins.LinkShortcutPlugin'], ['goog.editor.Command', 'goog.editor.Plugin'], false);
+goog.addDependency('editor/plugins/linkshortcutplugin_test.js', ['goog.editor.plugins.LinkShortcutPluginTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkShortcutPlugin', 'goog.events.KeyCodes', 'goog.testing.PropertyReplacer', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/plugins/listtabhandler.js', ['goog.editor.plugins.ListTabHandler'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.plugins.AbstractTabHandler', 'goog.iter'], false);
+goog.addDependency('editor/plugins/listtabhandler_test.js', ['goog.editor.plugins.ListTabHandlerTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.plugins.ListTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/plugins/loremipsum.js', ['goog.editor.plugins.LoremIpsum'], ['goog.asserts', 'goog.dom', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/loremipsum_test.js', ['goog.editor.plugins.LoremIpsumTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.plugins.LoremIpsum', 'goog.string.Unicode', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/removeformatting.js', ['goog.editor.plugins.RemoveFormatting'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/removeformatting_test.js', ['goog.editor.plugins.RemoveFormattingTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.plugins.RemoveFormatting', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.dom', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/spacestabhandler.js', ['goog.editor.plugins.SpacesTabHandler'], ['goog.dom.TagName', 'goog.editor.plugins.AbstractTabHandler', 'goog.editor.range'], false);
+goog.addDependency('editor/plugins/spacestabhandler_test.js', ['goog.editor.plugins.SpacesTabHandlerTest'], ['goog.dom', 'goog.dom.Range', 'goog.editor.plugins.SpacesTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/plugins/tableeditor.js', ['goog.editor.plugins.TableEditor'], ['goog.array', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.Table', 'goog.editor.node', 'goog.editor.range', 'goog.object', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/tableeditor_test.js', ['goog.editor.plugins.TableEditorTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.plugins.TableEditor', 'goog.object', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/tagonenterhandler.js', ['goog.editor.plugins.TagOnEnterHandler'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.functions', 'goog.string.Unicode', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/tagonenterhandler_test.js', ['goog.editor.plugins.TagOnEnterHandlerTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.TagOnEnterHandler', 'goog.events.KeyCodes', 'goog.string.Unicode', 'goog.testing.dom', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/plugins/undoredo.js', ['goog.editor.plugins.UndoRedo'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventHandler', 'goog.log', 'goog.object'], false);
+goog.addDependency('editor/plugins/undoredo_test.js', ['goog.editor.plugins.UndoRedoTest'], ['goog.array', 'goog.dom', 'goog.dom.browserrange', 'goog.editor.Field', 'goog.editor.plugins.LoremIpsum', 'goog.editor.plugins.UndoRedo', 'goog.events', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/plugins/undoredomanager.js', ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoManager.EventType'], ['goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventTarget'], false);
+goog.addDependency('editor/plugins/undoredomanager_test.js', ['goog.editor.plugins.UndoRedoManagerTest'], ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.testing.StrictMock', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/plugins/undoredostate.js', ['goog.editor.plugins.UndoRedoState'], ['goog.events.EventTarget'], false);
+goog.addDependency('editor/plugins/undoredostate_test.js', ['goog.editor.plugins.UndoRedoStateTest'], ['goog.editor.plugins.UndoRedoState', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/range.js', ['goog.editor.range', 'goog.editor.range.Point'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.SavedCaretRange', 'goog.editor.node', 'goog.editor.style', 'goog.iter', 'goog.userAgent'], false);
+goog.addDependency('editor/range_test.js', ['goog.editor.rangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.range', 'goog.editor.range.Point', 'goog.string', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('editor/seamlessfield.js', ['goog.editor.SeamlessField'], ['goog.cssom.iframe.style', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.safe', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.events', 'goog.events.EventType', 'goog.html.uncheckedconversions', 'goog.log', 'goog.string.Const', 'goog.style'], false);
+goog.addDependency('editor/seamlessfield_test.js', ['goog.editor.seamlessfield_test'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.SeamlessField', 'goog.events', 'goog.functions', 'goog.style', 'goog.testing.MockClock', 'goog.testing.MockRange', 'goog.testing.jsunit'], false);
+goog.addDependency('editor/style.js', ['goog.editor.style'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.events.EventType', 'goog.object', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('editor/style_test.js', ['goog.editor.styleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.style', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.style', 'goog.testing.LooseMock', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false);
+goog.addDependency('editor/table.js', ['goog.editor.Table', 'goog.editor.TableCell', 'goog.editor.TableRow'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.log', 'goog.string.Unicode', 'goog.style'], false);
+goog.addDependency('editor/table_test.js', ['goog.editor.TableTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Table', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/actioneventwrapper.js', ['goog.events.actionEventWrapper'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.EventWrapper', 'goog.events.KeyCodes', 'goog.userAgent'], false);
+goog.addDependency('events/actioneventwrapper_test.js', ['goog.events.actionEventWrapperTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.events', 'goog.events.EventHandler', 'goog.events.KeyCodes', 'goog.events.actionEventWrapper', 'goog.testing.events', 'goog.testing.jsunit'], false);
+goog.addDependency('events/actionhandler.js', ['goog.events.ActionEvent', 'goog.events.ActionHandler', 'goog.events.ActionHandler.EventType', 'goog.events.BeforeActionEvent'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent'], false);
+goog.addDependency('events/actionhandler_test.js', ['goog.events.ActionHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.ActionHandler', 'goog.testing.events', 'goog.testing.jsunit'], false);
+goog.addDependency('events/browserevent.js', ['goog.events.BrowserEvent', 'goog.events.BrowserEvent.MouseButton'], ['goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.reflect', 'goog.userAgent'], false);
+goog.addDependency('events/browserevent_test.js', ['goog.events.BrowserEventTest'], ['goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/browserfeature.js', ['goog.events.BrowserFeature'], ['goog.userAgent'], false);
+goog.addDependency('events/event.js', ['goog.events.Event', 'goog.events.EventLike'], ['goog.Disposable', 'goog.events.EventId'], false);
+goog.addDependency('events/event_test.js', ['goog.events.EventTest'], ['goog.events.Event', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.testing.jsunit'], false);
+goog.addDependency('events/eventhandler.js', ['goog.events.EventHandler'], ['goog.Disposable', 'goog.events', 'goog.object'], false);
+goog.addDependency('events/eventhandler_test.js', ['goog.events.EventHandlerTest'], ['goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('events/eventid.js', ['goog.events.EventId'], [], false);
+goog.addDependency('events/events.js', ['goog.events', 'goog.events.CaptureSimulationMode', 'goog.events.Key', 'goog.events.ListenableType'], ['goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Listenable', 'goog.events.ListenerMap'], false);
+goog.addDependency('events/events_test.js', ['goog.eventsTest'], ['goog.asserts.AssertionError', 'goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.BrowserFeature', 'goog.events.CaptureSimulationMode', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.Listener', 'goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('events/eventtarget.js', ['goog.events.EventTarget'], ['goog.Disposable', 'goog.asserts', 'goog.events', 'goog.events.Event', 'goog.events.Listenable', 'goog.events.ListenerMap', 'goog.object'], false);
+goog.addDependency('events/eventtarget_test.js', ['goog.events.EventTargetTest'], ['goog.events.EventTarget', 'goog.events.Listenable', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing.jsunit'], false);
+goog.addDependency('events/eventtarget_via_googevents_test.js', ['goog.events.EventTargetGoogEventsTest'], ['goog.events', 'goog.events.EventTarget', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing', 'goog.testing.jsunit'], false);
+goog.addDependency('events/eventtarget_via_w3cinterface_test.js', ['goog.events.EventTargetW3CTest'], ['goog.events.EventTarget', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing.jsunit'], false);
+goog.addDependency('events/eventtargettester.js', ['goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType'], ['goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.testing.asserts', 'goog.testing.recordFunction'], false);
+goog.addDependency('events/eventtype.js', ['goog.events.EventType'], ['goog.userAgent'], false);
+goog.addDependency('events/eventwrapper.js', ['goog.events.EventWrapper'], [], false);
+goog.addDependency('events/filedrophandler.js', ['goog.events.FileDropHandler', 'goog.events.FileDropHandler.EventType'], ['goog.array', 'goog.dom', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.log', 'goog.log.Level'], false);
+goog.addDependency('events/filedrophandler_test.js', ['goog.events.FileDropHandlerTest'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.FileDropHandler', 'goog.testing.jsunit'], false);
+goog.addDependency('events/focushandler.js', ['goog.events.FocusHandler', 'goog.events.FocusHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.userAgent'], false);
+goog.addDependency('events/imehandler.js', ['goog.events.ImeHandler', 'goog.events.ImeHandler.Event', 'goog.events.ImeHandler.EventType'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent'], false);
+goog.addDependency('events/imehandler_test.js', ['goog.events.ImeHandlerTest'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.ImeHandler', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/inputhandler.js', ['goog.events.InputHandler', 'goog.events.InputHandler.EventType'], ['goog.Timer', 'goog.dom', 'goog.dom.TagName', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.userAgent'], false);
+goog.addDependency('events/inputhandler_test.js', ['goog.events.InputHandlerTest'], ['goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('events/keycodes.js', ['goog.events.KeyCodes'], ['goog.userAgent'], false);
+goog.addDependency('events/keycodes_test.js', ['goog.events.KeyCodesTest'], ['goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/keyhandler.js', ['goog.events.KeyEvent', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent'], false);
+goog.addDependency('events/keyhandler_test.js', ['goog.events.KeyEventTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/keynames.js', ['goog.events.KeyNames'], [], false);
+goog.addDependency('events/listenable.js', ['goog.events.Listenable', 'goog.events.ListenableKey'], ['goog.events.EventId'], false);
+goog.addDependency('events/listenable_test.js', ['goog.events.ListenableTest'], ['goog.events.Listenable', 'goog.testing.jsunit'], false);
+goog.addDependency('events/listener.js', ['goog.events.Listener'], ['goog.events.ListenableKey'], false);
+goog.addDependency('events/listenermap.js', ['goog.events.ListenerMap'], ['goog.array', 'goog.events.Listener', 'goog.object'], false);
+goog.addDependency('events/listenermap_test.js', ['goog.events.ListenerMapTest'], ['goog.dispose', 'goog.events', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.events.ListenerMap', 'goog.testing.jsunit'], false);
+goog.addDependency('events/mousewheelhandler.js', ['goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.events.MouseWheelHandler.EventType'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.math', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('events/mousewheelhandler_test.js', ['goog.events.MouseWheelHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.functions', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/onlinehandler.js', ['goog.events.OnlineHandler', 'goog.events.OnlineHandler.EventType'], ['goog.Timer', 'goog.events.BrowserFeature', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.NetworkStatusMonitor'], false);
+goog.addDependency('events/onlinelistener_test.js', ['goog.events.OnlineHandlerTest'], ['goog.events', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.OnlineHandler', 'goog.net.NetworkStatusMonitor', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('events/pastehandler.js', ['goog.events.PasteHandler', 'goog.events.PasteHandler.EventType', 'goog.events.PasteHandler.State'], ['goog.Timer', 'goog.async.ConditionalDelay', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.log', 'goog.userAgent'], false);
+goog.addDependency('events/pastehandler_test.js', ['goog.events.PasteHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.PasteHandler', 'goog.testing.MockClock', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('events/wheelevent.js', ['goog.events.WheelEvent'], ['goog.asserts', 'goog.events.BrowserEvent'], false);
+goog.addDependency('events/wheelhandler.js', ['goog.events.WheelHandler'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.WheelEvent', 'goog.style', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('events/wheelhandler_test.js', ['goog.events.WheelHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.WheelEvent', 'goog.events.WheelHandler', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('format/emailaddress.js', ['goog.format.EmailAddress'], ['goog.string'], false);
+goog.addDependency('format/emailaddress_test.js', ['goog.format.EmailAddressTest'], ['goog.array', 'goog.format.EmailAddress', 'goog.testing.jsunit'], false);
+goog.addDependency('format/format.js', ['goog.format'], ['goog.i18n.GraphemeBreak', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('format/format_test.js', ['goog.formatTest'], ['goog.dom', 'goog.dom.TagName', 'goog.format', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('format/htmlprettyprinter.js', ['goog.format.HtmlPrettyPrinter', 'goog.format.HtmlPrettyPrinter.Buffer'], ['goog.dom.TagName', 'goog.object', 'goog.string.StringBuffer'], false);
+goog.addDependency('format/htmlprettyprinter_test.js', ['goog.format.HtmlPrettyPrinterTest'], ['goog.format.HtmlPrettyPrinter', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('format/internationalizedemailaddress.js', ['goog.format.InternationalizedEmailAddress'], ['goog.format.EmailAddress', 'goog.string'], false);
+goog.addDependency('format/internationalizedemailaddress_test.js', ['goog.format.InternationalizedEmailAddressTest'], ['goog.array', 'goog.format.InternationalizedEmailAddress', 'goog.testing.jsunit'], false);
+goog.addDependency('format/jsonprettyprinter.js', ['goog.format.JsonPrettyPrinter', 'goog.format.JsonPrettyPrinter.HtmlDelimiters', 'goog.format.JsonPrettyPrinter.TextDelimiters'], ['goog.json', 'goog.json.Serializer', 'goog.string', 'goog.string.StringBuffer', 'goog.string.format'], false);
+goog.addDependency('format/jsonprettyprinter_test.js', ['goog.format.JsonPrettyPrinterTest'], ['goog.format.JsonPrettyPrinter', 'goog.testing.jsunit'], false);
+goog.addDependency('fs/entry.js', ['goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntry.Behavior', 'goog.fs.Entry', 'goog.fs.FileEntry'], [], false);
+goog.addDependency('fs/entryimpl.js', ['goog.fs.DirectoryEntryImpl', 'goog.fs.EntryImpl', 'goog.fs.FileEntryImpl'], ['goog.array', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.Entry', 'goog.fs.Error', 'goog.fs.FileEntry', 'goog.fs.FileWriter', 'goog.functions', 'goog.string'], false);
+goog.addDependency('fs/error.js', ['goog.fs.Error', 'goog.fs.Error.ErrorCode'], ['goog.debug.Error', 'goog.object', 'goog.string'], false);
+goog.addDependency('fs/filereader.js', ['goog.fs.FileReader', 'goog.fs.FileReader.EventType', 'goog.fs.FileReader.ReadyState'], ['goog.async.Deferred', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent'], false);
+goog.addDependency('fs/filesaver.js', ['goog.fs.FileSaver', 'goog.fs.FileSaver.EventType', 'goog.fs.FileSaver.ReadyState'], ['goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent'], false);
+goog.addDependency('fs/filesystem.js', ['goog.fs.FileSystem'], [], false);
+goog.addDependency('fs/filesystemimpl.js', ['goog.fs.FileSystemImpl'], ['goog.fs.DirectoryEntryImpl', 'goog.fs.FileSystem'], false);
+goog.addDependency('fs/filewriter.js', ['goog.fs.FileWriter'], ['goog.fs.Error', 'goog.fs.FileSaver'], false);
+goog.addDependency('fs/fs.js', ['goog.fs'], ['goog.array', 'goog.async.Deferred', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSystemImpl', 'goog.fs.url', 'goog.userAgent'], false);
+goog.addDependency('fs/fs_test.js', ['goog.fsTest'], ['goog.Promise', 'goog.array', 'goog.dom', 'goog.events', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSaver', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('fs/progressevent.js', ['goog.fs.ProgressEvent'], ['goog.events.Event'], false);
+goog.addDependency('fs/url.js', ['goog.fs.url'], [], false);
+goog.addDependency('fs/url_test.js', ['goog.urlTest'], ['goog.fs.url', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('functions/functions.js', ['goog.functions'], [], false);
+goog.addDependency('functions/functions_test.js', ['goog.functionsTest'], ['goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('fx/abstractdragdrop.js', ['goog.fx.AbstractDragDrop', 'goog.fx.AbstractDragDrop.EventType', 'goog.fx.DragDropEvent', 'goog.fx.DragDropItem'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style'], false);
+goog.addDependency('fx/abstractdragdrop_test.js', ['goog.fx.AbstractDragDropTest'], ['goog.array', 'goog.dom.TagName', 'goog.events.EventType', 'goog.functions', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/anim/anim.js', ['goog.fx.anim', 'goog.fx.anim.Animated'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.object'], false);
+goog.addDependency('fx/anim/anim_test.js', ['goog.fx.animTest'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.events', 'goog.functions', 'goog.fx.Animation', 'goog.fx.anim', 'goog.object', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('fx/animation.js', ['goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent'], ['goog.array', 'goog.events.Event', 'goog.fx.Transition', 'goog.fx.TransitionBase', 'goog.fx.anim', 'goog.fx.anim.Animated'], false);
+goog.addDependency('fx/animation_test.js', ['goog.fx.AnimationTest'], ['goog.events', 'goog.fx.Animation', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/animationqueue.js', ['goog.fx.AnimationParallelQueue', 'goog.fx.AnimationQueue', 'goog.fx.AnimationSerialQueue'], ['goog.array', 'goog.asserts', 'goog.events', 'goog.fx.Transition', 'goog.fx.TransitionBase'], false);
+goog.addDependency('fx/animationqueue_test.js', ['goog.fx.AnimationQueueTest'], ['goog.events', 'goog.fx.Animation', 'goog.fx.AnimationParallelQueue', 'goog.fx.AnimationSerialQueue', 'goog.fx.Transition', 'goog.fx.anim', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/css3/fx.js', ['goog.fx.css3'], ['goog.fx.css3.Transition'], false);
+goog.addDependency('fx/css3/transition.js', ['goog.fx.css3.Transition'], ['goog.Timer', 'goog.asserts', 'goog.fx.TransitionBase', 'goog.style', 'goog.style.transition'], false);
+goog.addDependency('fx/css3/transition_test.js', ['goog.fx.css3.TransitionTest'], ['goog.dispose', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.fx.Transition', 'goog.fx.css3.Transition', 'goog.style.transition', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('fx/cssspriteanimation.js', ['goog.fx.CssSpriteAnimation'], ['goog.fx.Animation'], false);
+goog.addDependency('fx/cssspriteanimation_test.js', ['goog.fx.CssSpriteAnimationTest'], ['goog.fx.CssSpriteAnimation', 'goog.math.Box', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/dom.js', ['goog.fx.dom', 'goog.fx.dom.BgColorTransform', 'goog.fx.dom.ColorTransform', 'goog.fx.dom.Fade', 'goog.fx.dom.FadeIn', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOut', 'goog.fx.dom.FadeOutAndHide', 'goog.fx.dom.PredefinedEffect', 'goog.fx.dom.Resize', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Scroll', 'goog.fx.dom.Slide', 'goog.fx.dom.SlideFrom', 'goog.fx.dom.Swipe'], ['goog.color', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.style', 'goog.style.bidi'], false);
+goog.addDependency('fx/dragdrop.js', ['goog.fx.DragDrop'], ['goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem'], false);
+goog.addDependency('fx/dragdropgroup.js', ['goog.fx.DragDropGroup'], ['goog.dom', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem'], false);
+goog.addDependency('fx/dragdropgroup_test.js', ['goog.fx.DragDropGroupTest'], ['goog.events', 'goog.fx.DragDropGroup', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/dragger.js', ['goog.fx.DragEvent', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.style', 'goog.style.bidi', 'goog.userAgent'], false);
+goog.addDependency('fx/dragger_test.js', ['goog.fx.DraggerTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.style.bidi', 'goog.testing.StrictMock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('fx/draglistgroup.js', ['goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.DragListGroup.EventType', 'goog.fx.DragListGroupEvent'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Coordinate', 'goog.string', 'goog.style'], false);
+goog.addDependency('fx/draglistgroup_test.js', ['goog.fx.DragListGroupTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.fx.DragEvent', 'goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.Dragger', 'goog.math.Coordinate', 'goog.object', 'goog.testing.events', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/dragscrollsupport.js', ['goog.fx.DragScrollSupport'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.style'], false);
+goog.addDependency('fx/dragscrollsupport_test.js', ['goog.fx.DragScrollSupportTest'], ['goog.fx.DragScrollSupport', 'goog.math.Coordinate', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/easing.js', ['goog.fx.easing'], [], false);
+goog.addDependency('fx/easing_test.js', ['goog.fx.easingTest'], ['goog.fx.easing', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/fx.js', ['goog.fx'], ['goog.asserts', 'goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent', 'goog.fx.Transition.EventType', 'goog.fx.easing'], false);
+goog.addDependency('fx/fx_test.js', ['goog.fxTest'], ['goog.fx.Animation', 'goog.object', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('fx/transition.js', ['goog.fx.Transition', 'goog.fx.Transition.EventType'], [], false);
+goog.addDependency('fx/transitionbase.js', ['goog.fx.TransitionBase', 'goog.fx.TransitionBase.State'], ['goog.events.EventTarget', 'goog.fx.Transition'], false);
+goog.addDependency('graphics/abstractgraphics.js', ['goog.graphics.AbstractGraphics'], ['goog.dom', 'goog.graphics.Path', 'goog.math.Coordinate', 'goog.math.Size', 'goog.style', 'goog.ui.Component'], false);
+goog.addDependency('graphics/affinetransform.js', ['goog.graphics.AffineTransform'], ['goog.math'], false);
+goog.addDependency('graphics/canvaselement.js', ['goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.Path', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement', 'goog.html.SafeHtml', 'goog.html.uncheckedconversions', 'goog.math', 'goog.string', 'goog.string.Const'], false);
+goog.addDependency('graphics/canvasgraphics.js', ['goog.graphics.CanvasGraphics'], ['goog.dom.TagName', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement', 'goog.graphics.SolidFill', 'goog.math.Size', 'goog.style'], false);
+goog.addDependency('graphics/element.js', ['goog.graphics.Element'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.Listenable', 'goog.graphics.AffineTransform', 'goog.math'], false);
+goog.addDependency('graphics/ellipseelement.js', ['goog.graphics.EllipseElement'], ['goog.graphics.StrokeAndFillElement'], false);
+goog.addDependency('graphics/ext/coordinates.js', ['goog.graphics.ext.coordinates'], ['goog.string'], false);
+goog.addDependency('graphics/ext/element.js', ['goog.graphics.ext.Element'], ['goog.events.EventTarget', 'goog.functions', 'goog.graphics.ext.coordinates'], false);
+goog.addDependency('graphics/ext/ellipse.js', ['goog.graphics.ext.Ellipse'], ['goog.graphics.ext.StrokeAndFillElement'], false);
+goog.addDependency('graphics/ext/ext.js', ['goog.graphics.ext'], ['goog.graphics.ext.Ellipse', 'goog.graphics.ext.Graphics', 'goog.graphics.ext.Group', 'goog.graphics.ext.Image', 'goog.graphics.ext.Rectangle', 'goog.graphics.ext.Shape', 'goog.graphics.ext.coordinates'], false);
+goog.addDependency('graphics/ext/graphics.js', ['goog.graphics.ext.Graphics'], ['goog.events', 'goog.events.EventType', 'goog.graphics', 'goog.graphics.ext.Group'], false);
+goog.addDependency('graphics/ext/group.js', ['goog.graphics.ext.Group'], ['goog.array', 'goog.graphics.ext.Element'], false);
+goog.addDependency('graphics/ext/image.js', ['goog.graphics.ext.Image'], ['goog.graphics.ext.Element'], false);
+goog.addDependency('graphics/ext/path.js', ['goog.graphics.ext.Path'], ['goog.graphics.AffineTransform', 'goog.graphics.Path', 'goog.math.Rect'], false);
+goog.addDependency('graphics/ext/rectangle.js', ['goog.graphics.ext.Rectangle'], ['goog.graphics.ext.StrokeAndFillElement'], false);
+goog.addDependency('graphics/ext/shape.js', ['goog.graphics.ext.Shape'], ['goog.graphics.ext.StrokeAndFillElement'], false);
+goog.addDependency('graphics/ext/strokeandfillelement.js', ['goog.graphics.ext.StrokeAndFillElement'], ['goog.graphics.ext.Element'], false);
+goog.addDependency('graphics/fill.js', ['goog.graphics.Fill'], [], false);
+goog.addDependency('graphics/font.js', ['goog.graphics.Font'], [], false);
+goog.addDependency('graphics/graphics.js', ['goog.graphics'], ['goog.dom', 'goog.graphics.CanvasGraphics', 'goog.graphics.SvgGraphics', 'goog.graphics.VmlGraphics', 'goog.userAgent'], false);
+goog.addDependency('graphics/groupelement.js', ['goog.graphics.GroupElement'], ['goog.graphics.Element'], false);
+goog.addDependency('graphics/imageelement.js', ['goog.graphics.ImageElement'], ['goog.graphics.Element'], false);
+goog.addDependency('graphics/lineargradient.js', ['goog.graphics.LinearGradient'], ['goog.asserts', 'goog.graphics.Fill'], false);
+goog.addDependency('graphics/path.js', ['goog.graphics.Path', 'goog.graphics.Path.Segment'], ['goog.array', 'goog.math'], false);
+goog.addDependency('graphics/pathelement.js', ['goog.graphics.PathElement'], ['goog.graphics.StrokeAndFillElement'], false);
+goog.addDependency('graphics/paths.js', ['goog.graphics.paths'], ['goog.graphics.Path', 'goog.math.Coordinate'], false);
+goog.addDependency('graphics/rectelement.js', ['goog.graphics.RectElement'], ['goog.graphics.StrokeAndFillElement'], false);
+goog.addDependency('graphics/solidfill.js', ['goog.graphics.SolidFill'], ['goog.graphics.Fill'], false);
+goog.addDependency('graphics/stroke.js', ['goog.graphics.Stroke'], [], false);
+goog.addDependency('graphics/strokeandfillelement.js', ['goog.graphics.StrokeAndFillElement'], ['goog.graphics.Element'], false);
+goog.addDependency('graphics/svgelement.js', ['goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement'], false);
+goog.addDependency('graphics/svggraphics.js', ['goog.graphics.SvgGraphics'], ['goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.LinearGradient', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement', 'goog.math', 'goog.math.Size', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('graphics/textelement.js', ['goog.graphics.TextElement'], ['goog.graphics.StrokeAndFillElement'], false);
+goog.addDependency('graphics/vmlelement.js', ['goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement'], false);
+goog.addDependency('graphics/vmlgraphics.js', ['goog.graphics.VmlGraphics'], ['goog.array', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.LinearGradient', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement', 'goog.html.uncheckedconversions', 'goog.math', 'goog.math.Size', 'goog.string', 'goog.string.Const', 'goog.style'], false);
+goog.addDependency('history/event.js', ['goog.history.Event'], ['goog.events.Event', 'goog.history.EventType'], false);
+goog.addDependency('history/eventtype.js', ['goog.history.EventType'], [], false);
+goog.addDependency('history/history.js', ['goog.History', 'goog.History.Event', 'goog.History.EventType'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.safe', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event', 'goog.history.EventType', 'goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions', 'goog.labs.userAgent.device', 'goog.memoize', 'goog.string', 'goog.string.Const', 'goog.userAgent'], false);
+goog.addDependency('history/history_test.js', ['goog.HistoryTest'], ['goog.History', 'goog.dispose', 'goog.dom', 'goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('history/html5history.js', ['goog.history.Html5History', 'goog.history.Html5History.TokenTransformer'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event'], false);
+goog.addDependency('history/html5history_test.js', ['goog.history.Html5HistoryTest'], ['goog.history.Html5History', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false);
+goog.addDependency('html/flash.js', ['goog.html.flash'], ['goog.asserts', 'goog.html.SafeHtml'], false);
+goog.addDependency('html/flash_test.js', ['goog.html.flashTest'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/legacyconversions.js', ['goog.html.legacyconversions'], ['goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl'], false);
+goog.addDependency('html/legacyconversions_test.js', ['goog.html.legacyconversionsTest'], ['goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('html/safehtml.js', ['goog.html.SafeHtml'], ['goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.tags', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.string.TypedString'], false);
+goog.addDependency('html/safehtml_test.js', ['goog.html.safeHtmlTest'], ['goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.testing', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/safescript.js', ['goog.html.SafeScript'], ['goog.asserts', 'goog.string.Const', 'goog.string.TypedString'], false);
+goog.addDependency('html/safescript_test.js', ['goog.html.safeScriptTest'], ['goog.html.SafeScript', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/safestyle.js', ['goog.html.SafeStyle'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.string.Const', 'goog.string.TypedString'], false);
+goog.addDependency('html/safestyle_test.js', ['goog.html.safeStyleTest'], ['goog.html.SafeStyle', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/safestylesheet.js', ['goog.html.SafeStyleSheet'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.string.Const', 'goog.string.TypedString'], false);
+goog.addDependency('html/safestylesheet_test.js', ['goog.html.safeStyleSheetTest'], ['goog.html.SafeStyleSheet', 'goog.string', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/safeurl.js', ['goog.html.SafeUrl'], ['goog.asserts', 'goog.fs.url', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.string.Const', 'goog.string.TypedString'], false);
+goog.addDependency('html/safeurl_test.js', ['goog.html.safeUrlTest'], ['goog.html.SafeUrl', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('html/silverlight.js', ['goog.html.silverlight'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.string.Const'], false);
+goog.addDependency('html/silverlight_test.js', ['goog.html.silverlightTest'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.silverlight', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/testing.js', ['goog.html.testing'], ['goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl'], false);
+goog.addDependency('html/trustedresourceurl.js', ['goog.html.TrustedResourceUrl'], ['goog.asserts', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.string.Const', 'goog.string.TypedString'], false);
+goog.addDependency('html/trustedresourceurl_test.js', ['goog.html.trustedResourceUrlTest'], ['goog.html.TrustedResourceUrl', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/uncheckedconversions.js', ['goog.html.uncheckedconversions'], ['goog.asserts', 'goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.string', 'goog.string.Const'], false);
+goog.addDependency('html/uncheckedconversions_test.js', ['goog.html.uncheckedconversionsTest'], ['goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.uncheckedconversions', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('html/utils.js', ['goog.html.utils'], ['goog.string'], false);
+goog.addDependency('html/utils_test.js', ['goog.html.UtilsTest'], ['goog.array', 'goog.dom.TagName', 'goog.html.utils', 'goog.object', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/bidi.js', ['goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.i18n.bidi.Format'], [], false);
+goog.addDependency('i18n/bidi_test.js', ['goog.i18n.bidiTest'], ['goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/bidiformatter.js', ['goog.i18n.BidiFormatter'], ['goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.Format'], false);
+goog.addDependency('i18n/bidiformatter_test.js', ['goog.i18n.BidiFormatterTest'], ['goog.html.SafeHtml', 'goog.i18n.BidiFormatter', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.Format', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/charlistdecompressor.js', ['goog.i18n.CharListDecompressor'], ['goog.array', 'goog.i18n.uChar'], false);
+goog.addDependency('i18n/charlistdecompressor_test.js', ['goog.i18n.CharListDecompressorTest'], ['goog.i18n.CharListDecompressor', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/charpickerdata.js', ['goog.i18n.CharPickerData'], [], false);
+goog.addDependency('i18n/collation.js', ['goog.i18n.collation'], [], false);
+goog.addDependency('i18n/collation_test.js', ['goog.i18n.collationTest'], ['goog.i18n.collation', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('i18n/compactnumberformatsymbols.js', ['goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.CompactNumberFormatSymbols_af', 'goog.i18n.CompactNumberFormatSymbols_af_ZA', 'goog.i18n.CompactNumberFormatSymbols_am', 'goog.i18n.CompactNumberFormatSymbols_am_ET', 'goog.i18n.CompactNumberFormatSymbols_ar', 'goog.i18n.CompactNumberFormatSymbols_ar_001', 'goog.i18n.CompactNumberFormatSymbols_az', 'goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ', 'goog.i18n.CompactNumberFormatSymbols_bg', 'goog.i18n.CompactNumberFormatSymbols_bg_BG', 'goog.i18n.CompactNumberFormatSymbols_bn', 'goog.i18n.CompactNumberFormatSymbols_bn_BD', 'goog.i18n.CompactNumberFormatSymbols_br', 'goog.i18n.CompactNumberFormatSymbols_br_FR', 'goog.i18n.CompactNumberFormatSymbols_ca', 'goog.i18n.CompactNumberFormatSymbols_ca_AD', 'goog.i18n.CompactNumberFormatSymbols_ca_ES', 'goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA', 'goog.i18n.CompactNumberFormatSymbols_ca_FR', 'goog.i18n.CompactNumberFormatSymbols_ca_IT', 'goog.i18n.CompactNumberFormatSymbols_chr', 'goog.i18n.CompactNumberFormatSymbols_chr_US', 'goog.i18n.CompactNumberFormatSymbols_cs', 'goog.i18n.CompactNumberFormatSymbols_cs_CZ', 'goog.i18n.CompactNumberFormatSymbols_cy', 'goog.i18n.CompactNumberFormatSymbols_cy_GB', 'goog.i18n.CompactNumberFormatSymbols_da', 'goog.i18n.CompactNumberFormatSymbols_da_DK', 'goog.i18n.CompactNumberFormatSymbols_da_GL', 'goog.i18n.CompactNumberFormatSymbols_de', 'goog.i18n.CompactNumberFormatSymbols_de_AT', 'goog.i18n.CompactNumberFormatSymbols_de_BE', 'goog.i18n.CompactNumberFormatSymbols_de_CH', 'goog.i18n.CompactNumberFormatSymbols_de_DE', 'goog.i18n.CompactNumberFormatSymbols_de_LU', 'goog.i18n.CompactNumberFormatSymbols_el', 'goog.i18n.CompactNumberFormatSymbols_el_GR', 'goog.i18n.CompactNumberFormatSymbols_en', 'goog.i18n.CompactNumberFormatSymbols_en_001', 'goog.i18n.CompactNumberFormatSymbols_en_AS', 'goog.i18n.CompactNumberFormatSymbols_en_AU', 'goog.i18n.CompactNumberFormatSymbols_en_DG', 'goog.i18n.CompactNumberFormatSymbols_en_FM', 'goog.i18n.CompactNumberFormatSymbols_en_GB', 'goog.i18n.CompactNumberFormatSymbols_en_GU', 'goog.i18n.CompactNumberFormatSymbols_en_IE', 'goog.i18n.CompactNumberFormatSymbols_en_IN', 'goog.i18n.CompactNumberFormatSymbols_en_IO', 'goog.i18n.CompactNumberFormatSymbols_en_MH', 'goog.i18n.CompactNumberFormatSymbols_en_MP', 'goog.i18n.CompactNumberFormatSymbols_en_PR', 'goog.i18n.CompactNumberFormatSymbols_en_PW', 'goog.i18n.CompactNumberFormatSymbols_en_SG', 'goog.i18n.CompactNumberFormatSymbols_en_TC', 'goog.i18n.CompactNumberFormatSymbols_en_UM', 'goog.i18n.CompactNumberFormatSymbols_en_US', 'goog.i18n.CompactNumberFormatSymbols_en_VG', 'goog.i18n.CompactNumberFormatSymbols_en_VI', 'goog.i18n.CompactNumberFormatSymbols_en_ZA', 'goog.i18n.CompactNumberFormatSymbols_en_ZW', 'goog.i18n.CompactNumberFormatSymbols_es', 'goog.i18n.CompactNumberFormatSymbols_es_419', 'goog.i18n.CompactNumberFormatSymbols_es_EA', 'goog.i18n.CompactNumberFormatSymbols_es_ES', 'goog.i18n.CompactNumberFormatSymbols_es_IC', 'goog.i18n.CompactNumberFormatSymbols_et', 'goog.i18n.CompactNumberFormatSymbols_et_EE', 'goog.i18n.CompactNumberFormatSymbols_eu', 'goog.i18n.CompactNumberFormatSymbols_eu_ES', 'goog.i18n.CompactNumberFormatSymbols_fa', 'goog.i18n.CompactNumberFormatSymbols_fa_IR', 'goog.i18n.CompactNumberFormatSymbols_fi', 'goog.i18n.CompactNumberFormatSymbols_fi_FI', 'goog.i18n.CompactNumberFormatSymbols_fil', 'goog.i18n.CompactNumberFormatSymbols_fil_PH', 'goog.i18n.CompactNumberFormatSymbols_fr', 'goog.i18n.CompactNumberFormatSymbols_fr_BL', 'goog.i18n.CompactNumberFormatSymbols_fr_CA', 'goog.i18n.CompactNumberFormatSymbols_fr_FR', 'goog.i18n.CompactNumberFormatSymbols_fr_GF', 'goog.i18n.CompactNumberFormatSymbols_fr_GP', 'goog.i18n.CompactNumberFormatSymbols_fr_MC', 'goog.i18n.CompactNumberFormatSymbols_fr_MF', 'goog.i18n.CompactNumberFormatSymbols_fr_MQ', 'goog.i18n.CompactNumberFormatSymbols_fr_PM', 'goog.i18n.CompactNumberFormatSymbols_fr_RE', 'goog.i18n.CompactNumberFormatSymbols_fr_YT', 'goog.i18n.CompactNumberFormatSymbols_ga', 'goog.i18n.CompactNumberFormatSymbols_ga_IE', 'goog.i18n.CompactNumberFormatSymbols_gl', 'goog.i18n.CompactNumberFormatSymbols_gl_ES', 'goog.i18n.CompactNumberFormatSymbols_gsw', 'goog.i18n.CompactNumberFormatSymbols_gsw_CH', 'goog.i18n.CompactNumberFormatSymbols_gsw_LI', 'goog.i18n.CompactNumberFormatSymbols_gu', 'goog.i18n.CompactNumberFormatSymbols_gu_IN', 'goog.i18n.CompactNumberFormatSymbols_haw', 'goog.i18n.CompactNumberFormatSymbols_haw_US', 'goog.i18n.CompactNumberFormatSymbols_he', 'goog.i18n.CompactNumberFormatSymbols_he_IL', 'goog.i18n.CompactNumberFormatSymbols_hi', 'goog.i18n.CompactNumberFormatSymbols_hi_IN', 'goog.i18n.CompactNumberFormatSymbols_hr', 'goog.i18n.CompactNumberFormatSymbols_hr_HR', 'goog.i18n.CompactNumberFormatSymbols_hu', 'goog.i18n.CompactNumberFormatSymbols_hu_HU', 'goog.i18n.CompactNumberFormatSymbols_hy', 'goog.i18n.CompactNumberFormatSymbols_hy_AM', 'goog.i18n.CompactNumberFormatSymbols_id', 'goog.i18n.CompactNumberFormatSymbols_id_ID', 'goog.i18n.CompactNumberFormatSymbols_in', 'goog.i18n.CompactNumberFormatSymbols_is', 'goog.i18n.CompactNumberFormatSymbols_is_IS', 'goog.i18n.CompactNumberFormatSymbols_it', 'goog.i18n.CompactNumberFormatSymbols_it_IT', 'goog.i18n.CompactNumberFormatSymbols_it_SM', 'goog.i18n.CompactNumberFormatSymbols_iw', 'goog.i18n.CompactNumberFormatSymbols_ja', 'goog.i18n.CompactNumberFormatSymbols_ja_JP', 'goog.i18n.CompactNumberFormatSymbols_ka', 'goog.i18n.CompactNumberFormatSymbols_ka_GE', 'goog.i18n.CompactNumberFormatSymbols_kk', 'goog.i18n.CompactNumberFormatSymbols_kk_Cyrl_KZ', 'goog.i18n.CompactNumberFormatSymbols_km', 'goog.i18n.CompactNumberFormatSymbols_km_KH', 'goog.i18n.CompactNumberFormatSymbols_kn', 'goog.i18n.CompactNumberFormatSymbols_kn_IN', 'goog.i18n.CompactNumberFormatSymbols_ko', 'goog.i18n.CompactNumberFormatSymbols_ko_KR', 'goog.i18n.CompactNumberFormatSymbols_ky', 'goog.i18n.CompactNumberFormatSymbols_ky_Cyrl_KG', 'goog.i18n.CompactNumberFormatSymbols_ln', 'goog.i18n.CompactNumberFormatSymbols_ln_CD', 'goog.i18n.CompactNumberFormatSymbols_lo', 'goog.i18n.CompactNumberFormatSymbols_lo_LA', 'goog.i18n.CompactNumberFormatSymbols_lt', 'goog.i18n.CompactNumberFormatSymbols_lt_LT', 'goog.i18n.CompactNumberFormatSymbols_lv', 'goog.i18n.CompactNumberFormatSymbols_lv_LV', 'goog.i18n.CompactNumberFormatSymbols_mk', 'goog.i18n.CompactNumberFormatSymbols_mk_MK', 'goog.i18n.CompactNumberFormatSymbols_ml', 'goog.i18n.CompactNumberFormatSymbols_ml_IN', 'goog.i18n.CompactNumberFormatSymbols_mn', 'goog.i18n.CompactNumberFormatSymbols_mn_Cyrl_MN', 'goog.i18n.CompactNumberFormatSymbols_mr', 'goog.i18n.CompactNumberFormatSymbols_mr_IN', 'goog.i18n.CompactNumberFormatSymbols_ms', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn_MY', 'goog.i18n.CompactNumberFormatSymbols_mt', 'goog.i18n.CompactNumberFormatSymbols_mt_MT', 'goog.i18n.CompactNumberFormatSymbols_my', 'goog.i18n.CompactNumberFormatSymbols_my_MM', 'goog.i18n.CompactNumberFormatSymbols_nb', 'goog.i18n.CompactNumberFormatSymbols_nb_NO', 'goog.i18n.CompactNumberFormatSymbols_nb_SJ', 'goog.i18n.CompactNumberFormatSymbols_ne', 'goog.i18n.CompactNumberFormatSymbols_ne_NP', 'goog.i18n.CompactNumberFormatSymbols_nl', 'goog.i18n.CompactNumberFormatSymbols_nl_NL', 'goog.i18n.CompactNumberFormatSymbols_no', 'goog.i18n.CompactNumberFormatSymbols_no_NO', 'goog.i18n.CompactNumberFormatSymbols_or', 'goog.i18n.CompactNumberFormatSymbols_or_IN', 'goog.i18n.CompactNumberFormatSymbols_pa', 'goog.i18n.CompactNumberFormatSymbols_pa_Guru_IN', 'goog.i18n.CompactNumberFormatSymbols_pl', 'goog.i18n.CompactNumberFormatSymbols_pl_PL', 'goog.i18n.CompactNumberFormatSymbols_pt', 'goog.i18n.CompactNumberFormatSymbols_pt_BR', 'goog.i18n.CompactNumberFormatSymbols_pt_PT', 'goog.i18n.CompactNumberFormatSymbols_ro', 'goog.i18n.CompactNumberFormatSymbols_ro_RO', 'goog.i18n.CompactNumberFormatSymbols_ru', 'goog.i18n.CompactNumberFormatSymbols_ru_RU', 'goog.i18n.CompactNumberFormatSymbols_si', 'goog.i18n.CompactNumberFormatSymbols_si_LK', 'goog.i18n.CompactNumberFormatSymbols_sk', 'goog.i18n.CompactNumberFormatSymbols_sk_SK', 'goog.i18n.CompactNumberFormatSymbols_sl', 'goog.i18n.CompactNumberFormatSymbols_sl_SI', 'goog.i18n.CompactNumberFormatSymbols_sq', 'goog.i18n.CompactNumberFormatSymbols_sq_AL', 'goog.i18n.CompactNumberFormatSymbols_sr', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.CompactNumberFormatSymbols_sv', 'goog.i18n.CompactNumberFormatSymbols_sv_SE', 'goog.i18n.CompactNumberFormatSymbols_sw', 'goog.i18n.CompactNumberFormatSymbols_sw_TZ', 'goog.i18n.CompactNumberFormatSymbols_ta', 'goog.i18n.CompactNumberFormatSymbols_ta_IN', 'goog.i18n.CompactNumberFormatSymbols_te', 'goog.i18n.CompactNumberFormatSymbols_te_IN', 'goog.i18n.CompactNumberFormatSymbols_th', 'goog.i18n.CompactNumberFormatSymbols_th_TH', 'goog.i18n.CompactNumberFormatSymbols_tl', 'goog.i18n.CompactNumberFormatSymbols_tr', 'goog.i18n.CompactNumberFormatSymbols_tr_TR', 'goog.i18n.CompactNumberFormatSymbols_uk', 'goog.i18n.CompactNumberFormatSymbols_uk_UA', 'goog.i18n.CompactNumberFormatSymbols_ur', 'goog.i18n.CompactNumberFormatSymbols_ur_PK', 'goog.i18n.CompactNumberFormatSymbols_uz', 'goog.i18n.CompactNumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.CompactNumberFormatSymbols_vi', 'goog.i18n.CompactNumberFormatSymbols_vi_VN', 'goog.i18n.CompactNumberFormatSymbols_zh', 'goog.i18n.CompactNumberFormatSymbols_zh_CN', 'goog.i18n.CompactNumberFormatSymbols_zh_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_CN', 'goog.i18n.CompactNumberFormatSymbols_zh_TW', 'goog.i18n.CompactNumberFormatSymbols_zu', 'goog.i18n.CompactNumberFormatSymbols_zu_ZA'], [], false);
+goog.addDependency('i18n/compactnumberformatsymbols_ext.js', ['goog.i18n.CompactNumberFormatSymbolsExt', 'goog.i18n.CompactNumberFormatSymbols_aa', 'goog.i18n.CompactNumberFormatSymbols_aa_DJ', 'goog.i18n.CompactNumberFormatSymbols_aa_ER', 'goog.i18n.CompactNumberFormatSymbols_aa_ET', 'goog.i18n.CompactNumberFormatSymbols_af_NA', 'goog.i18n.CompactNumberFormatSymbols_agq', 'goog.i18n.CompactNumberFormatSymbols_agq_CM', 'goog.i18n.CompactNumberFormatSymbols_ak', 'goog.i18n.CompactNumberFormatSymbols_ak_GH', 'goog.i18n.CompactNumberFormatSymbols_ar_AE', 'goog.i18n.CompactNumberFormatSymbols_ar_BH', 'goog.i18n.CompactNumberFormatSymbols_ar_DJ', 'goog.i18n.CompactNumberFormatSymbols_ar_DZ', 'goog.i18n.CompactNumberFormatSymbols_ar_EG', 'goog.i18n.CompactNumberFormatSymbols_ar_EH', 'goog.i18n.CompactNumberFormatSymbols_ar_ER', 'goog.i18n.CompactNumberFormatSymbols_ar_IL', 'goog.i18n.CompactNumberFormatSymbols_ar_IQ', 'goog.i18n.CompactNumberFormatSymbols_ar_JO', 'goog.i18n.CompactNumberFormatSymbols_ar_KM', 'goog.i18n.CompactNumberFormatSymbols_ar_KW', 'goog.i18n.CompactNumberFormatSymbols_ar_LB', 'goog.i18n.CompactNumberFormatSymbols_ar_LY', 'goog.i18n.CompactNumberFormatSymbols_ar_MA', 'goog.i18n.CompactNumberFormatSymbols_ar_MR', 'goog.i18n.CompactNumberFormatSymbols_ar_OM', 'goog.i18n.CompactNumberFormatSymbols_ar_PS', 'goog.i18n.CompactNumberFormatSymbols_ar_QA', 'goog.i18n.CompactNumberFormatSymbols_ar_SA', 'goog.i18n.CompactNumberFormatSymbols_ar_SD', 'goog.i18n.CompactNumberFormatSymbols_ar_SO', 'goog.i18n.CompactNumberFormatSymbols_ar_SS', 'goog.i18n.CompactNumberFormatSymbols_ar_SY', 'goog.i18n.CompactNumberFormatSymbols_ar_TD', 'goog.i18n.CompactNumberFormatSymbols_ar_TN', 'goog.i18n.CompactNumberFormatSymbols_ar_YE', 'goog.i18n.CompactNumberFormatSymbols_as', 'goog.i18n.CompactNumberFormatSymbols_as_IN', 'goog.i18n.CompactNumberFormatSymbols_asa', 'goog.i18n.CompactNumberFormatSymbols_asa_TZ', 'goog.i18n.CompactNumberFormatSymbols_ast', 'goog.i18n.CompactNumberFormatSymbols_ast_ES', 'goog.i18n.CompactNumberFormatSymbols_az_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.CompactNumberFormatSymbols_az_Latn', 'goog.i18n.CompactNumberFormatSymbols_bas', 'goog.i18n.CompactNumberFormatSymbols_bas_CM', 'goog.i18n.CompactNumberFormatSymbols_be', 'goog.i18n.CompactNumberFormatSymbols_be_BY', 'goog.i18n.CompactNumberFormatSymbols_bem', 'goog.i18n.CompactNumberFormatSymbols_bem_ZM', 'goog.i18n.CompactNumberFormatSymbols_bez', 'goog.i18n.CompactNumberFormatSymbols_bez_TZ', 'goog.i18n.CompactNumberFormatSymbols_bm', 'goog.i18n.CompactNumberFormatSymbols_bm_Latn', 'goog.i18n.CompactNumberFormatSymbols_bm_Latn_ML', 'goog.i18n.CompactNumberFormatSymbols_bn_IN', 'goog.i18n.CompactNumberFormatSymbols_bo', 'goog.i18n.CompactNumberFormatSymbols_bo_CN', 'goog.i18n.CompactNumberFormatSymbols_bo_IN', 'goog.i18n.CompactNumberFormatSymbols_brx', 'goog.i18n.CompactNumberFormatSymbols_brx_IN', 'goog.i18n.CompactNumberFormatSymbols_bs', 'goog.i18n.CompactNumberFormatSymbols_bs_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA', 'goog.i18n.CompactNumberFormatSymbols_bs_Latn', 'goog.i18n.CompactNumberFormatSymbols_bs_Latn_BA', 'goog.i18n.CompactNumberFormatSymbols_cgg', 'goog.i18n.CompactNumberFormatSymbols_cgg_UG', 'goog.i18n.CompactNumberFormatSymbols_ckb', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.CompactNumberFormatSymbols_ckb_IQ', 'goog.i18n.CompactNumberFormatSymbols_ckb_IR', 'goog.i18n.CompactNumberFormatSymbols_ckb_Latn', 'goog.i18n.CompactNumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.CompactNumberFormatSymbols_dav', 'goog.i18n.CompactNumberFormatSymbols_dav_KE', 'goog.i18n.CompactNumberFormatSymbols_de_LI', 'goog.i18n.CompactNumberFormatSymbols_dje', 'goog.i18n.CompactNumberFormatSymbols_dje_NE', 'goog.i18n.CompactNumberFormatSymbols_dsb', 'goog.i18n.CompactNumberFormatSymbols_dsb_DE', 'goog.i18n.CompactNumberFormatSymbols_dua', 'goog.i18n.CompactNumberFormatSymbols_dua_CM', 'goog.i18n.CompactNumberFormatSymbols_dyo', 'goog.i18n.CompactNumberFormatSymbols_dyo_SN', 'goog.i18n.CompactNumberFormatSymbols_dz', 'goog.i18n.CompactNumberFormatSymbols_dz_BT', 'goog.i18n.CompactNumberFormatSymbols_ebu', 'goog.i18n.CompactNumberFormatSymbols_ebu_KE', 'goog.i18n.CompactNumberFormatSymbols_ee', 'goog.i18n.CompactNumberFormatSymbols_ee_GH', 'goog.i18n.CompactNumberFormatSymbols_ee_TG', 'goog.i18n.CompactNumberFormatSymbols_el_CY', 'goog.i18n.CompactNumberFormatSymbols_en_150', 'goog.i18n.CompactNumberFormatSymbols_en_AG', 'goog.i18n.CompactNumberFormatSymbols_en_AI', 'goog.i18n.CompactNumberFormatSymbols_en_BB', 'goog.i18n.CompactNumberFormatSymbols_en_BE', 'goog.i18n.CompactNumberFormatSymbols_en_BM', 'goog.i18n.CompactNumberFormatSymbols_en_BS', 'goog.i18n.CompactNumberFormatSymbols_en_BW', 'goog.i18n.CompactNumberFormatSymbols_en_BZ', 'goog.i18n.CompactNumberFormatSymbols_en_CA', 'goog.i18n.CompactNumberFormatSymbols_en_CC', 'goog.i18n.CompactNumberFormatSymbols_en_CK', 'goog.i18n.CompactNumberFormatSymbols_en_CM', 'goog.i18n.CompactNumberFormatSymbols_en_CX', 'goog.i18n.CompactNumberFormatSymbols_en_DM', 'goog.i18n.CompactNumberFormatSymbols_en_ER', 'goog.i18n.CompactNumberFormatSymbols_en_FJ', 'goog.i18n.CompactNumberFormatSymbols_en_FK', 'goog.i18n.CompactNumberFormatSymbols_en_GD', 'goog.i18n.CompactNumberFormatSymbols_en_GG', 'goog.i18n.CompactNumberFormatSymbols_en_GH', 'goog.i18n.CompactNumberFormatSymbols_en_GI', 'goog.i18n.CompactNumberFormatSymbols_en_GM', 'goog.i18n.CompactNumberFormatSymbols_en_GY', 'goog.i18n.CompactNumberFormatSymbols_en_HK', 'goog.i18n.CompactNumberFormatSymbols_en_IM', 'goog.i18n.CompactNumberFormatSymbols_en_JE', 'goog.i18n.CompactNumberFormatSymbols_en_JM', 'goog.i18n.CompactNumberFormatSymbols_en_KE', 'goog.i18n.CompactNumberFormatSymbols_en_KI', 'goog.i18n.CompactNumberFormatSymbols_en_KN', 'goog.i18n.CompactNumberFormatSymbols_en_KY', 'goog.i18n.CompactNumberFormatSymbols_en_LC', 'goog.i18n.CompactNumberFormatSymbols_en_LR', 'goog.i18n.CompactNumberFormatSymbols_en_LS', 'goog.i18n.CompactNumberFormatSymbols_en_MG', 'goog.i18n.CompactNumberFormatSymbols_en_MO', 'goog.i18n.CompactNumberFormatSymbols_en_MS', 'goog.i18n.CompactNumberFormatSymbols_en_MT', 'goog.i18n.CompactNumberFormatSymbols_en_MU', 'goog.i18n.CompactNumberFormatSymbols_en_MW', 'goog.i18n.CompactNumberFormatSymbols_en_MY', 'goog.i18n.CompactNumberFormatSymbols_en_NA', 'goog.i18n.CompactNumberFormatSymbols_en_NF', 'goog.i18n.CompactNumberFormatSymbols_en_NG', 'goog.i18n.CompactNumberFormatSymbols_en_NR', 'goog.i18n.CompactNumberFormatSymbols_en_NU', 'goog.i18n.CompactNumberFormatSymbols_en_NZ', 'goog.i18n.CompactNumberFormatSymbols_en_PG', 'goog.i18n.CompactNumberFormatSymbols_en_PH', 'goog.i18n.CompactNumberFormatSymbols_en_PK', 'goog.i18n.CompactNumberFormatSymbols_en_PN', 'goog.i18n.CompactNumberFormatSymbols_en_RW', 'goog.i18n.CompactNumberFormatSymbols_en_SB', 'goog.i18n.CompactNumberFormatSymbols_en_SC', 'goog.i18n.CompactNumberFormatSymbols_en_SD', 'goog.i18n.CompactNumberFormatSymbols_en_SH', 'goog.i18n.CompactNumberFormatSymbols_en_SL', 'goog.i18n.CompactNumberFormatSymbols_en_SS', 'goog.i18n.CompactNumberFormatSymbols_en_SX', 'goog.i18n.CompactNumberFormatSymbols_en_SZ', 'goog.i18n.CompactNumberFormatSymbols_en_TK', 'goog.i18n.CompactNumberFormatSymbols_en_TO', 'goog.i18n.CompactNumberFormatSymbols_en_TT', 'goog.i18n.CompactNumberFormatSymbols_en_TV', 'goog.i18n.CompactNumberFormatSymbols_en_TZ', 'goog.i18n.CompactNumberFormatSymbols_en_UG', 'goog.i18n.CompactNumberFormatSymbols_en_VC', 'goog.i18n.CompactNumberFormatSymbols_en_VU', 'goog.i18n.CompactNumberFormatSymbols_en_WS', 'goog.i18n.CompactNumberFormatSymbols_en_ZM', 'goog.i18n.CompactNumberFormatSymbols_eo', 'goog.i18n.CompactNumberFormatSymbols_eo_001', 'goog.i18n.CompactNumberFormatSymbols_es_AR', 'goog.i18n.CompactNumberFormatSymbols_es_BO', 'goog.i18n.CompactNumberFormatSymbols_es_CL', 'goog.i18n.CompactNumberFormatSymbols_es_CO', 'goog.i18n.CompactNumberFormatSymbols_es_CR', 'goog.i18n.CompactNumberFormatSymbols_es_CU', 'goog.i18n.CompactNumberFormatSymbols_es_DO', 'goog.i18n.CompactNumberFormatSymbols_es_EC', 'goog.i18n.CompactNumberFormatSymbols_es_GQ', 'goog.i18n.CompactNumberFormatSymbols_es_GT', 'goog.i18n.CompactNumberFormatSymbols_es_HN', 'goog.i18n.CompactNumberFormatSymbols_es_MX', 'goog.i18n.CompactNumberFormatSymbols_es_NI', 'goog.i18n.CompactNumberFormatSymbols_es_PA', 'goog.i18n.CompactNumberFormatSymbols_es_PE', 'goog.i18n.CompactNumberFormatSymbols_es_PH', 'goog.i18n.CompactNumberFormatSymbols_es_PR', 'goog.i18n.CompactNumberFormatSymbols_es_PY', 'goog.i18n.CompactNumberFormatSymbols_es_SV', 'goog.i18n.CompactNumberFormatSymbols_es_US', 'goog.i18n.CompactNumberFormatSymbols_es_UY', 'goog.i18n.CompactNumberFormatSymbols_es_VE', 'goog.i18n.CompactNumberFormatSymbols_ewo', 'goog.i18n.CompactNumberFormatSymbols_ewo_CM', 'goog.i18n.CompactNumberFormatSymbols_fa_AF', 'goog.i18n.CompactNumberFormatSymbols_ff', 'goog.i18n.CompactNumberFormatSymbols_ff_CM', 'goog.i18n.CompactNumberFormatSymbols_ff_GN', 'goog.i18n.CompactNumberFormatSymbols_ff_MR', 'goog.i18n.CompactNumberFormatSymbols_ff_SN', 'goog.i18n.CompactNumberFormatSymbols_fo', 'goog.i18n.CompactNumberFormatSymbols_fo_FO', 'goog.i18n.CompactNumberFormatSymbols_fr_BE', 'goog.i18n.CompactNumberFormatSymbols_fr_BF', 'goog.i18n.CompactNumberFormatSymbols_fr_BI', 'goog.i18n.CompactNumberFormatSymbols_fr_BJ', 'goog.i18n.CompactNumberFormatSymbols_fr_CD', 'goog.i18n.CompactNumberFormatSymbols_fr_CF', 'goog.i18n.CompactNumberFormatSymbols_fr_CG', 'goog.i18n.CompactNumberFormatSymbols_fr_CH', 'goog.i18n.CompactNumberFormatSymbols_fr_CI', 'goog.i18n.CompactNumberFormatSymbols_fr_CM', 'goog.i18n.CompactNumberFormatSymbols_fr_DJ', 'goog.i18n.CompactNumberFormatSymbols_fr_DZ', 'goog.i18n.CompactNumberFormatSymbols_fr_GA', 'goog.i18n.CompactNumberFormatSymbols_fr_GN', 'goog.i18n.CompactNumberFormatSymbols_fr_GQ', 'goog.i18n.CompactNumberFormatSymbols_fr_HT', 'goog.i18n.CompactNumberFormatSymbols_fr_KM', 'goog.i18n.CompactNumberFormatSymbols_fr_LU', 'goog.i18n.CompactNumberFormatSymbols_fr_MA', 'goog.i18n.CompactNumberFormatSymbols_fr_MG', 'goog.i18n.CompactNumberFormatSymbols_fr_ML', 'goog.i18n.CompactNumberFormatSymbols_fr_MR', 'goog.i18n.CompactNumberFormatSymbols_fr_MU', 'goog.i18n.CompactNumberFormatSymbols_fr_NC', 'goog.i18n.CompactNumberFormatSymbols_fr_NE', 'goog.i18n.CompactNumberFormatSymbols_fr_PF', 'goog.i18n.CompactNumberFormatSymbols_fr_RW', 'goog.i18n.CompactNumberFormatSymbols_fr_SC', 'goog.i18n.CompactNumberFormatSymbols_fr_SN', 'goog.i18n.CompactNumberFormatSymbols_fr_SY', 'goog.i18n.CompactNumberFormatSymbols_fr_TD', 'goog.i18n.CompactNumberFormatSymbols_fr_TG', 'goog.i18n.CompactNumberFormatSymbols_fr_TN', 'goog.i18n.CompactNumberFormatSymbols_fr_VU', 'goog.i18n.CompactNumberFormatSymbols_fr_WF', 'goog.i18n.CompactNumberFormatSymbols_fur', 'goog.i18n.CompactNumberFormatSymbols_fur_IT', 'goog.i18n.CompactNumberFormatSymbols_fy', 'goog.i18n.CompactNumberFormatSymbols_fy_NL', 'goog.i18n.CompactNumberFormatSymbols_gd', 'goog.i18n.CompactNumberFormatSymbols_gd_GB', 'goog.i18n.CompactNumberFormatSymbols_gsw_FR', 'goog.i18n.CompactNumberFormatSymbols_guz', 'goog.i18n.CompactNumberFormatSymbols_guz_KE', 'goog.i18n.CompactNumberFormatSymbols_gv', 'goog.i18n.CompactNumberFormatSymbols_gv_IM', 'goog.i18n.CompactNumberFormatSymbols_ha', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn_GH', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn_NE', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn_NG', 'goog.i18n.CompactNumberFormatSymbols_hr_BA', 'goog.i18n.CompactNumberFormatSymbols_hsb', 'goog.i18n.CompactNumberFormatSymbols_hsb_DE', 'goog.i18n.CompactNumberFormatSymbols_ia', 'goog.i18n.CompactNumberFormatSymbols_ia_FR', 'goog.i18n.CompactNumberFormatSymbols_ig', 'goog.i18n.CompactNumberFormatSymbols_ig_NG', 'goog.i18n.CompactNumberFormatSymbols_ii', 'goog.i18n.CompactNumberFormatSymbols_ii_CN', 'goog.i18n.CompactNumberFormatSymbols_it_CH', 'goog.i18n.CompactNumberFormatSymbols_jgo', 'goog.i18n.CompactNumberFormatSymbols_jgo_CM', 'goog.i18n.CompactNumberFormatSymbols_jmc', 'goog.i18n.CompactNumberFormatSymbols_jmc_TZ', 'goog.i18n.CompactNumberFormatSymbols_kab', 'goog.i18n.CompactNumberFormatSymbols_kab_DZ', 'goog.i18n.CompactNumberFormatSymbols_kam', 'goog.i18n.CompactNumberFormatSymbols_kam_KE', 'goog.i18n.CompactNumberFormatSymbols_kde', 'goog.i18n.CompactNumberFormatSymbols_kde_TZ', 'goog.i18n.CompactNumberFormatSymbols_kea', 'goog.i18n.CompactNumberFormatSymbols_kea_CV', 'goog.i18n.CompactNumberFormatSymbols_khq', 'goog.i18n.CompactNumberFormatSymbols_khq_ML', 'goog.i18n.CompactNumberFormatSymbols_ki', 'goog.i18n.CompactNumberFormatSymbols_ki_KE', 'goog.i18n.CompactNumberFormatSymbols_kk_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_kkj', 'goog.i18n.CompactNumberFormatSymbols_kkj_CM', 'goog.i18n.CompactNumberFormatSymbols_kl', 'goog.i18n.CompactNumberFormatSymbols_kl_GL', 'goog.i18n.CompactNumberFormatSymbols_kln', 'goog.i18n.CompactNumberFormatSymbols_kln_KE', 'goog.i18n.CompactNumberFormatSymbols_ko_KP', 'goog.i18n.CompactNumberFormatSymbols_kok', 'goog.i18n.CompactNumberFormatSymbols_kok_IN', 'goog.i18n.CompactNumberFormatSymbols_ks', 'goog.i18n.CompactNumberFormatSymbols_ks_Arab', 'goog.i18n.CompactNumberFormatSymbols_ks_Arab_IN', 'goog.i18n.CompactNumberFormatSymbols_ksb', 'goog.i18n.CompactNumberFormatSymbols_ksb_TZ', 'goog.i18n.CompactNumberFormatSymbols_ksf', 'goog.i18n.CompactNumberFormatSymbols_ksf_CM', 'goog.i18n.CompactNumberFormatSymbols_ksh', 'goog.i18n.CompactNumberFormatSymbols_ksh_DE', 'goog.i18n.CompactNumberFormatSymbols_kw', 'goog.i18n.CompactNumberFormatSymbols_kw_GB', 'goog.i18n.CompactNumberFormatSymbols_ky_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_lag', 'goog.i18n.CompactNumberFormatSymbols_lag_TZ', 'goog.i18n.CompactNumberFormatSymbols_lb', 'goog.i18n.CompactNumberFormatSymbols_lb_LU', 'goog.i18n.CompactNumberFormatSymbols_lg', 'goog.i18n.CompactNumberFormatSymbols_lg_UG', 'goog.i18n.CompactNumberFormatSymbols_lkt', 'goog.i18n.CompactNumberFormatSymbols_lkt_US', 'goog.i18n.CompactNumberFormatSymbols_ln_AO', 'goog.i18n.CompactNumberFormatSymbols_ln_CF', 'goog.i18n.CompactNumberFormatSymbols_ln_CG', 'goog.i18n.CompactNumberFormatSymbols_lu', 'goog.i18n.CompactNumberFormatSymbols_lu_CD', 'goog.i18n.CompactNumberFormatSymbols_luo', 'goog.i18n.CompactNumberFormatSymbols_luo_KE', 'goog.i18n.CompactNumberFormatSymbols_luy', 'goog.i18n.CompactNumberFormatSymbols_luy_KE', 'goog.i18n.CompactNumberFormatSymbols_mas', 'goog.i18n.CompactNumberFormatSymbols_mas_KE', 'goog.i18n.CompactNumberFormatSymbols_mas_TZ', 'goog.i18n.CompactNumberFormatSymbols_mer', 'goog.i18n.CompactNumberFormatSymbols_mer_KE', 'goog.i18n.CompactNumberFormatSymbols_mfe', 'goog.i18n.CompactNumberFormatSymbols_mfe_MU', 'goog.i18n.CompactNumberFormatSymbols_mg', 'goog.i18n.CompactNumberFormatSymbols_mg_MG', 'goog.i18n.CompactNumberFormatSymbols_mgh', 'goog.i18n.CompactNumberFormatSymbols_mgh_MZ', 'goog.i18n.CompactNumberFormatSymbols_mgo', 'goog.i18n.CompactNumberFormatSymbols_mgo_CM', 'goog.i18n.CompactNumberFormatSymbols_mn_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn_BN', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn_SG', 'goog.i18n.CompactNumberFormatSymbols_mua', 'goog.i18n.CompactNumberFormatSymbols_mua_CM', 'goog.i18n.CompactNumberFormatSymbols_naq', 'goog.i18n.CompactNumberFormatSymbols_naq_NA', 'goog.i18n.CompactNumberFormatSymbols_nd', 'goog.i18n.CompactNumberFormatSymbols_nd_ZW', 'goog.i18n.CompactNumberFormatSymbols_ne_IN', 'goog.i18n.CompactNumberFormatSymbols_nl_AW', 'goog.i18n.CompactNumberFormatSymbols_nl_BE', 'goog.i18n.CompactNumberFormatSymbols_nl_BQ', 'goog.i18n.CompactNumberFormatSymbols_nl_CW', 'goog.i18n.CompactNumberFormatSymbols_nl_SR', 'goog.i18n.CompactNumberFormatSymbols_nl_SX', 'goog.i18n.CompactNumberFormatSymbols_nmg', 'goog.i18n.CompactNumberFormatSymbols_nmg_CM', 'goog.i18n.CompactNumberFormatSymbols_nn', 'goog.i18n.CompactNumberFormatSymbols_nn_NO', 'goog.i18n.CompactNumberFormatSymbols_nnh', 'goog.i18n.CompactNumberFormatSymbols_nnh_CM', 'goog.i18n.CompactNumberFormatSymbols_nr', 'goog.i18n.CompactNumberFormatSymbols_nr_ZA', 'goog.i18n.CompactNumberFormatSymbols_nso', 'goog.i18n.CompactNumberFormatSymbols_nso_ZA', 'goog.i18n.CompactNumberFormatSymbols_nus', 'goog.i18n.CompactNumberFormatSymbols_nus_SD', 'goog.i18n.CompactNumberFormatSymbols_nyn', 'goog.i18n.CompactNumberFormatSymbols_nyn_UG', 'goog.i18n.CompactNumberFormatSymbols_om', 'goog.i18n.CompactNumberFormatSymbols_om_ET', 'goog.i18n.CompactNumberFormatSymbols_om_KE', 'goog.i18n.CompactNumberFormatSymbols_os', 'goog.i18n.CompactNumberFormatSymbols_os_GE', 'goog.i18n.CompactNumberFormatSymbols_os_RU', 'goog.i18n.CompactNumberFormatSymbols_pa_Arab', 'goog.i18n.CompactNumberFormatSymbols_pa_Arab_PK', 'goog.i18n.CompactNumberFormatSymbols_pa_Guru', 'goog.i18n.CompactNumberFormatSymbols_ps', 'goog.i18n.CompactNumberFormatSymbols_ps_AF', 'goog.i18n.CompactNumberFormatSymbols_pt_AO', 'goog.i18n.CompactNumberFormatSymbols_pt_CV', 'goog.i18n.CompactNumberFormatSymbols_pt_GW', 'goog.i18n.CompactNumberFormatSymbols_pt_MO', 'goog.i18n.CompactNumberFormatSymbols_pt_MZ', 'goog.i18n.CompactNumberFormatSymbols_pt_ST', 'goog.i18n.CompactNumberFormatSymbols_pt_TL', 'goog.i18n.CompactNumberFormatSymbols_qu', 'goog.i18n.CompactNumberFormatSymbols_qu_BO', 'goog.i18n.CompactNumberFormatSymbols_qu_EC', 'goog.i18n.CompactNumberFormatSymbols_qu_PE', 'goog.i18n.CompactNumberFormatSymbols_rm', 'goog.i18n.CompactNumberFormatSymbols_rm_CH', 'goog.i18n.CompactNumberFormatSymbols_rn', 'goog.i18n.CompactNumberFormatSymbols_rn_BI', 'goog.i18n.CompactNumberFormatSymbols_ro_MD', 'goog.i18n.CompactNumberFormatSymbols_rof', 'goog.i18n.CompactNumberFormatSymbols_rof_TZ', 'goog.i18n.CompactNumberFormatSymbols_ru_BY', 'goog.i18n.CompactNumberFormatSymbols_ru_KG', 'goog.i18n.CompactNumberFormatSymbols_ru_KZ', 'goog.i18n.CompactNumberFormatSymbols_ru_MD', 'goog.i18n.CompactNumberFormatSymbols_ru_UA', 'goog.i18n.CompactNumberFormatSymbols_rw', 'goog.i18n.CompactNumberFormatSymbols_rw_RW', 'goog.i18n.CompactNumberFormatSymbols_rwk', 'goog.i18n.CompactNumberFormatSymbols_rwk_TZ', 'goog.i18n.CompactNumberFormatSymbols_sah', 'goog.i18n.CompactNumberFormatSymbols_sah_RU', 'goog.i18n.CompactNumberFormatSymbols_saq', 'goog.i18n.CompactNumberFormatSymbols_saq_KE', 'goog.i18n.CompactNumberFormatSymbols_sbp', 'goog.i18n.CompactNumberFormatSymbols_sbp_TZ', 'goog.i18n.CompactNumberFormatSymbols_se', 'goog.i18n.CompactNumberFormatSymbols_se_FI', 'goog.i18n.CompactNumberFormatSymbols_se_NO', 'goog.i18n.CompactNumberFormatSymbols_se_SE', 'goog.i18n.CompactNumberFormatSymbols_seh', 'goog.i18n.CompactNumberFormatSymbols_seh_MZ', 'goog.i18n.CompactNumberFormatSymbols_ses', 'goog.i18n.CompactNumberFormatSymbols_ses_ML', 'goog.i18n.CompactNumberFormatSymbols_sg', 'goog.i18n.CompactNumberFormatSymbols_sg_CF', 'goog.i18n.CompactNumberFormatSymbols_shi', 'goog.i18n.CompactNumberFormatSymbols_shi_Latn', 'goog.i18n.CompactNumberFormatSymbols_shi_Latn_MA', 'goog.i18n.CompactNumberFormatSymbols_shi_Tfng', 'goog.i18n.CompactNumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.CompactNumberFormatSymbols_smn', 'goog.i18n.CompactNumberFormatSymbols_smn_FI', 'goog.i18n.CompactNumberFormatSymbols_sn', 'goog.i18n.CompactNumberFormatSymbols_sn_ZW', 'goog.i18n.CompactNumberFormatSymbols_so', 'goog.i18n.CompactNumberFormatSymbols_so_DJ', 'goog.i18n.CompactNumberFormatSymbols_so_ET', 'goog.i18n.CompactNumberFormatSymbols_so_KE', 'goog.i18n.CompactNumberFormatSymbols_so_SO', 'goog.i18n.CompactNumberFormatSymbols_sq_MK', 'goog.i18n.CompactNumberFormatSymbols_sq_XK', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_XK', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_RS', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK', 'goog.i18n.CompactNumberFormatSymbols_ss', 'goog.i18n.CompactNumberFormatSymbols_ss_SZ', 'goog.i18n.CompactNumberFormatSymbols_ss_ZA', 'goog.i18n.CompactNumberFormatSymbols_ssy', 'goog.i18n.CompactNumberFormatSymbols_ssy_ER', 'goog.i18n.CompactNumberFormatSymbols_sv_AX', 'goog.i18n.CompactNumberFormatSymbols_sv_FI', 'goog.i18n.CompactNumberFormatSymbols_sw_KE', 'goog.i18n.CompactNumberFormatSymbols_sw_UG', 'goog.i18n.CompactNumberFormatSymbols_swc', 'goog.i18n.CompactNumberFormatSymbols_swc_CD', 'goog.i18n.CompactNumberFormatSymbols_ta_LK', 'goog.i18n.CompactNumberFormatSymbols_ta_MY', 'goog.i18n.CompactNumberFormatSymbols_ta_SG', 'goog.i18n.CompactNumberFormatSymbols_teo', 'goog.i18n.CompactNumberFormatSymbols_teo_KE', 'goog.i18n.CompactNumberFormatSymbols_teo_UG', 'goog.i18n.CompactNumberFormatSymbols_ti', 'goog.i18n.CompactNumberFormatSymbols_ti_ER', 'goog.i18n.CompactNumberFormatSymbols_ti_ET', 'goog.i18n.CompactNumberFormatSymbols_tn', 'goog.i18n.CompactNumberFormatSymbols_tn_BW', 'goog.i18n.CompactNumberFormatSymbols_tn_ZA', 'goog.i18n.CompactNumberFormatSymbols_to', 'goog.i18n.CompactNumberFormatSymbols_to_TO', 'goog.i18n.CompactNumberFormatSymbols_tr_CY', 'goog.i18n.CompactNumberFormatSymbols_ts', 'goog.i18n.CompactNumberFormatSymbols_ts_ZA', 'goog.i18n.CompactNumberFormatSymbols_twq', 'goog.i18n.CompactNumberFormatSymbols_twq_NE', 'goog.i18n.CompactNumberFormatSymbols_tzm', 'goog.i18n.CompactNumberFormatSymbols_tzm_Latn', 'goog.i18n.CompactNumberFormatSymbols_tzm_Latn_MA', 'goog.i18n.CompactNumberFormatSymbols_ug', 'goog.i18n.CompactNumberFormatSymbols_ug_Arab', 'goog.i18n.CompactNumberFormatSymbols_ug_Arab_CN', 'goog.i18n.CompactNumberFormatSymbols_ur_IN', 'goog.i18n.CompactNumberFormatSymbols_uz_Arab', 'goog.i18n.CompactNumberFormatSymbols_uz_Arab_AF', 'goog.i18n.CompactNumberFormatSymbols_uz_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.CompactNumberFormatSymbols_uz_Latn', 'goog.i18n.CompactNumberFormatSymbols_vai', 'goog.i18n.CompactNumberFormatSymbols_vai_Latn', 'goog.i18n.CompactNumberFormatSymbols_vai_Latn_LR', 'goog.i18n.CompactNumberFormatSymbols_vai_Vaii', 'goog.i18n.CompactNumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.CompactNumberFormatSymbols_ve', 'goog.i18n.CompactNumberFormatSymbols_ve_ZA', 'goog.i18n.CompactNumberFormatSymbols_vo', 'goog.i18n.CompactNumberFormatSymbols_vo_001', 'goog.i18n.CompactNumberFormatSymbols_vun', 'goog.i18n.CompactNumberFormatSymbols_vun_TZ', 'goog.i18n.CompactNumberFormatSymbols_wae', 'goog.i18n.CompactNumberFormatSymbols_wae_CH', 'goog.i18n.CompactNumberFormatSymbols_xog', 'goog.i18n.CompactNumberFormatSymbols_xog_UG', 'goog.i18n.CompactNumberFormatSymbols_yav', 'goog.i18n.CompactNumberFormatSymbols_yav_CM', 'goog.i18n.CompactNumberFormatSymbols_yi', 'goog.i18n.CompactNumberFormatSymbols_yi_001', 'goog.i18n.CompactNumberFormatSymbols_yo', 'goog.i18n.CompactNumberFormatSymbols_yo_BJ', 'goog.i18n.CompactNumberFormatSymbols_yo_NG', 'goog.i18n.CompactNumberFormatSymbols_zgh', 'goog.i18n.CompactNumberFormatSymbols_zgh_MA', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_TW'], [], false);
+goog.addDependency('i18n/currency.js', ['goog.i18n.currency', 'goog.i18n.currency.CurrencyInfo', 'goog.i18n.currency.CurrencyInfoTier2'], [], false);
+goog.addDependency('i18n/currency_test.js', ['goog.i18n.currencyTest'], ['goog.i18n.NumberFormat', 'goog.i18n.currency', 'goog.i18n.currency.CurrencyInfo', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/currencycodemap.js', ['goog.i18n.currencyCodeMap', 'goog.i18n.currencyCodeMapTier2'], [], false);
+goog.addDependency('i18n/datetimeformat.js', ['goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeFormat.Format'], ['goog.asserts', 'goog.date', 'goog.i18n.DateTimeSymbols', 'goog.i18n.TimeZone', 'goog.string'], false);
+goog.addDependency('i18n/datetimeformat_test.js', ['goog.i18n.DateTimeFormatTest'], ['goog.date.Date', 'goog.date.DateTime', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.TimeZone', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/datetimeparse.js', ['goog.i18n.DateTimeParse'], ['goog.date', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols'], false);
+goog.addDependency('i18n/datetimeparse_test.js', ['goog.i18n.DateTimeParseTest'], ['goog.date.Date', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeParse', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_zh', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('i18n/datetimepatterns.js', ['goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_af', 'goog.i18n.DateTimePatterns_am', 'goog.i18n.DateTimePatterns_ar', 'goog.i18n.DateTimePatterns_az', 'goog.i18n.DateTimePatterns_bg', 'goog.i18n.DateTimePatterns_bn', 'goog.i18n.DateTimePatterns_br', 'goog.i18n.DateTimePatterns_ca', 'goog.i18n.DateTimePatterns_chr', 'goog.i18n.DateTimePatterns_cs', 'goog.i18n.DateTimePatterns_cy', 'goog.i18n.DateTimePatterns_da', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_de_AT', 'goog.i18n.DateTimePatterns_de_CH', 'goog.i18n.DateTimePatterns_el', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_en_AU', 'goog.i18n.DateTimePatterns_en_GB', 'goog.i18n.DateTimePatterns_en_IE', 'goog.i18n.DateTimePatterns_en_IN', 'goog.i18n.DateTimePatterns_en_SG', 'goog.i18n.DateTimePatterns_en_US', 'goog.i18n.DateTimePatterns_en_ZA', 'goog.i18n.DateTimePatterns_es', 'goog.i18n.DateTimePatterns_es_419', 'goog.i18n.DateTimePatterns_es_ES', 'goog.i18n.DateTimePatterns_et', 'goog.i18n.DateTimePatterns_eu', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fi', 'goog.i18n.DateTimePatterns_fil', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_fr_CA', 'goog.i18n.DateTimePatterns_ga', 'goog.i18n.DateTimePatterns_gl', 'goog.i18n.DateTimePatterns_gsw', 'goog.i18n.DateTimePatterns_gu', 'goog.i18n.DateTimePatterns_haw', 'goog.i18n.DateTimePatterns_he', 'goog.i18n.DateTimePatterns_hi', 'goog.i18n.DateTimePatterns_hr', 'goog.i18n.DateTimePatterns_hu', 'goog.i18n.DateTimePatterns_hy', 'goog.i18n.DateTimePatterns_id', 'goog.i18n.DateTimePatterns_in', 'goog.i18n.DateTimePatterns_is', 'goog.i18n.DateTimePatterns_it', 'goog.i18n.DateTimePatterns_iw', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_ka', 'goog.i18n.DateTimePatterns_kk', 'goog.i18n.DateTimePatterns_km', 'goog.i18n.DateTimePatterns_kn', 'goog.i18n.DateTimePatterns_ko', 'goog.i18n.DateTimePatterns_ky', 'goog.i18n.DateTimePatterns_ln', 'goog.i18n.DateTimePatterns_lo', 'goog.i18n.DateTimePatterns_lt', 'goog.i18n.DateTimePatterns_lv', 'goog.i18n.DateTimePatterns_mk', 'goog.i18n.DateTimePatterns_ml', 'goog.i18n.DateTimePatterns_mn', 'goog.i18n.DateTimePatterns_mo', 'goog.i18n.DateTimePatterns_mr', 'goog.i18n.DateTimePatterns_ms', 'goog.i18n.DateTimePatterns_mt', 'goog.i18n.DateTimePatterns_my', 'goog.i18n.DateTimePatterns_nb', 'goog.i18n.DateTimePatterns_ne', 'goog.i18n.DateTimePatterns_nl', 'goog.i18n.DateTimePatterns_no', 'goog.i18n.DateTimePatterns_no_NO', 'goog.i18n.DateTimePatterns_or', 'goog.i18n.DateTimePatterns_pa', 'goog.i18n.DateTimePatterns_pl', 'goog.i18n.DateTimePatterns_pt', 'goog.i18n.DateTimePatterns_pt_BR', 'goog.i18n.DateTimePatterns_pt_PT', 'goog.i18n.DateTimePatterns_ro', 'goog.i18n.DateTimePatterns_ru', 'goog.i18n.DateTimePatterns_sh', 'goog.i18n.DateTimePatterns_si', 'goog.i18n.DateTimePatterns_sk', 'goog.i18n.DateTimePatterns_sl', 'goog.i18n.DateTimePatterns_sq', 'goog.i18n.DateTimePatterns_sr', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimePatterns_sw', 'goog.i18n.DateTimePatterns_ta', 'goog.i18n.DateTimePatterns_te', 'goog.i18n.DateTimePatterns_th', 'goog.i18n.DateTimePatterns_tl', 'goog.i18n.DateTimePatterns_tr', 'goog.i18n.DateTimePatterns_uk', 'goog.i18n.DateTimePatterns_ur', 'goog.i18n.DateTimePatterns_uz', 'goog.i18n.DateTimePatterns_vi', 'goog.i18n.DateTimePatterns_zh', 'goog.i18n.DateTimePatterns_zh_CN', 'goog.i18n.DateTimePatterns_zh_HK', 'goog.i18n.DateTimePatterns_zh_TW', 'goog.i18n.DateTimePatterns_zu'], [], false);
+goog.addDependency('i18n/datetimepatternsext.js', ['goog.i18n.DateTimePatternsExt', 'goog.i18n.DateTimePatterns_af_NA', 'goog.i18n.DateTimePatterns_af_ZA', 'goog.i18n.DateTimePatterns_agq', 'goog.i18n.DateTimePatterns_agq_CM', 'goog.i18n.DateTimePatterns_ak', 'goog.i18n.DateTimePatterns_ak_GH', 'goog.i18n.DateTimePatterns_am_ET', 'goog.i18n.DateTimePatterns_ar_001', 'goog.i18n.DateTimePatterns_ar_AE', 'goog.i18n.DateTimePatterns_ar_BH', 'goog.i18n.DateTimePatterns_ar_DJ', 'goog.i18n.DateTimePatterns_ar_DZ', 'goog.i18n.DateTimePatterns_ar_EG', 'goog.i18n.DateTimePatterns_ar_EH', 'goog.i18n.DateTimePatterns_ar_ER', 'goog.i18n.DateTimePatterns_ar_IL', 'goog.i18n.DateTimePatterns_ar_IQ', 'goog.i18n.DateTimePatterns_ar_JO', 'goog.i18n.DateTimePatterns_ar_KM', 'goog.i18n.DateTimePatterns_ar_KW', 'goog.i18n.DateTimePatterns_ar_LB', 'goog.i18n.DateTimePatterns_ar_LY', 'goog.i18n.DateTimePatterns_ar_MA', 'goog.i18n.DateTimePatterns_ar_MR', 'goog.i18n.DateTimePatterns_ar_OM', 'goog.i18n.DateTimePatterns_ar_PS', 'goog.i18n.DateTimePatterns_ar_QA', 'goog.i18n.DateTimePatterns_ar_SA', 'goog.i18n.DateTimePatterns_ar_SD', 'goog.i18n.DateTimePatterns_ar_SO', 'goog.i18n.DateTimePatterns_ar_SS', 'goog.i18n.DateTimePatterns_ar_SY', 'goog.i18n.DateTimePatterns_ar_TD', 'goog.i18n.DateTimePatterns_ar_TN', 'goog.i18n.DateTimePatterns_ar_YE', 'goog.i18n.DateTimePatterns_as', 'goog.i18n.DateTimePatterns_as_IN', 'goog.i18n.DateTimePatterns_asa', 'goog.i18n.DateTimePatterns_asa_TZ', 'goog.i18n.DateTimePatterns_az_Cyrl', 'goog.i18n.DateTimePatterns_az_Cyrl_AZ', 'goog.i18n.DateTimePatterns_az_Latn', 'goog.i18n.DateTimePatterns_az_Latn_AZ', 'goog.i18n.DateTimePatterns_bas', 'goog.i18n.DateTimePatterns_bas_CM', 'goog.i18n.DateTimePatterns_be', 'goog.i18n.DateTimePatterns_be_BY', 'goog.i18n.DateTimePatterns_bem', 'goog.i18n.DateTimePatterns_bem_ZM', 'goog.i18n.DateTimePatterns_bez', 'goog.i18n.DateTimePatterns_bez_TZ', 'goog.i18n.DateTimePatterns_bg_BG', 'goog.i18n.DateTimePatterns_bm', 'goog.i18n.DateTimePatterns_bm_Latn', 'goog.i18n.DateTimePatterns_bm_Latn_ML', 'goog.i18n.DateTimePatterns_bn_BD', 'goog.i18n.DateTimePatterns_bn_IN', 'goog.i18n.DateTimePatterns_bo', 'goog.i18n.DateTimePatterns_bo_CN', 'goog.i18n.DateTimePatterns_bo_IN', 'goog.i18n.DateTimePatterns_br_FR', 'goog.i18n.DateTimePatterns_brx', 'goog.i18n.DateTimePatterns_brx_IN', 'goog.i18n.DateTimePatterns_bs', 'goog.i18n.DateTimePatterns_bs_Cyrl', 'goog.i18n.DateTimePatterns_bs_Cyrl_BA', 'goog.i18n.DateTimePatterns_bs_Latn', 'goog.i18n.DateTimePatterns_bs_Latn_BA', 'goog.i18n.DateTimePatterns_ca_AD', 'goog.i18n.DateTimePatterns_ca_ES', 'goog.i18n.DateTimePatterns_ca_FR', 'goog.i18n.DateTimePatterns_ca_IT', 'goog.i18n.DateTimePatterns_cgg', 'goog.i18n.DateTimePatterns_cgg_UG', 'goog.i18n.DateTimePatterns_chr_US', 'goog.i18n.DateTimePatterns_cs_CZ', 'goog.i18n.DateTimePatterns_cy_GB', 'goog.i18n.DateTimePatterns_da_DK', 'goog.i18n.DateTimePatterns_da_GL', 'goog.i18n.DateTimePatterns_dav', 'goog.i18n.DateTimePatterns_dav_KE', 'goog.i18n.DateTimePatterns_de_BE', 'goog.i18n.DateTimePatterns_de_DE', 'goog.i18n.DateTimePatterns_de_LI', 'goog.i18n.DateTimePatterns_de_LU', 'goog.i18n.DateTimePatterns_dje', 'goog.i18n.DateTimePatterns_dje_NE', 'goog.i18n.DateTimePatterns_dsb', 'goog.i18n.DateTimePatterns_dsb_DE', 'goog.i18n.DateTimePatterns_dua', 'goog.i18n.DateTimePatterns_dua_CM', 'goog.i18n.DateTimePatterns_dyo', 'goog.i18n.DateTimePatterns_dyo_SN', 'goog.i18n.DateTimePatterns_dz', 'goog.i18n.DateTimePatterns_dz_BT', 'goog.i18n.DateTimePatterns_ebu', 'goog.i18n.DateTimePatterns_ebu_KE', 'goog.i18n.DateTimePatterns_ee', 'goog.i18n.DateTimePatterns_ee_GH', 'goog.i18n.DateTimePatterns_ee_TG', 'goog.i18n.DateTimePatterns_el_CY', 'goog.i18n.DateTimePatterns_el_GR', 'goog.i18n.DateTimePatterns_en_001', 'goog.i18n.DateTimePatterns_en_150', 'goog.i18n.DateTimePatterns_en_AG', 'goog.i18n.DateTimePatterns_en_AI', 'goog.i18n.DateTimePatterns_en_AS', 'goog.i18n.DateTimePatterns_en_BB', 'goog.i18n.DateTimePatterns_en_BE', 'goog.i18n.DateTimePatterns_en_BM', 'goog.i18n.DateTimePatterns_en_BS', 'goog.i18n.DateTimePatterns_en_BW', 'goog.i18n.DateTimePatterns_en_BZ', 'goog.i18n.DateTimePatterns_en_CA', 'goog.i18n.DateTimePatterns_en_CC', 'goog.i18n.DateTimePatterns_en_CK', 'goog.i18n.DateTimePatterns_en_CM', 'goog.i18n.DateTimePatterns_en_CX', 'goog.i18n.DateTimePatterns_en_DG', 'goog.i18n.DateTimePatterns_en_DM', 'goog.i18n.DateTimePatterns_en_ER', 'goog.i18n.DateTimePatterns_en_FJ', 'goog.i18n.DateTimePatterns_en_FK', 'goog.i18n.DateTimePatterns_en_FM', 'goog.i18n.DateTimePatterns_en_GD', 'goog.i18n.DateTimePatterns_en_GG', 'goog.i18n.DateTimePatterns_en_GH', 'goog.i18n.DateTimePatterns_en_GI', 'goog.i18n.DateTimePatterns_en_GM', 'goog.i18n.DateTimePatterns_en_GU', 'goog.i18n.DateTimePatterns_en_GY', 'goog.i18n.DateTimePatterns_en_HK', 'goog.i18n.DateTimePatterns_en_IM', 'goog.i18n.DateTimePatterns_en_IO', 'goog.i18n.DateTimePatterns_en_JE', 'goog.i18n.DateTimePatterns_en_JM', 'goog.i18n.DateTimePatterns_en_KE', 'goog.i18n.DateTimePatterns_en_KI', 'goog.i18n.DateTimePatterns_en_KN', 'goog.i18n.DateTimePatterns_en_KY', 'goog.i18n.DateTimePatterns_en_LC', 'goog.i18n.DateTimePatterns_en_LR', 'goog.i18n.DateTimePatterns_en_LS', 'goog.i18n.DateTimePatterns_en_MG', 'goog.i18n.DateTimePatterns_en_MH', 'goog.i18n.DateTimePatterns_en_MO', 'goog.i18n.DateTimePatterns_en_MP', 'goog.i18n.DateTimePatterns_en_MS', 'goog.i18n.DateTimePatterns_en_MT', 'goog.i18n.DateTimePatterns_en_MU', 'goog.i18n.DateTimePatterns_en_MW', 'goog.i18n.DateTimePatterns_en_MY', 'goog.i18n.DateTimePatterns_en_NA', 'goog.i18n.DateTimePatterns_en_NF', 'goog.i18n.DateTimePatterns_en_NG', 'goog.i18n.DateTimePatterns_en_NR', 'goog.i18n.DateTimePatterns_en_NU', 'goog.i18n.DateTimePatterns_en_NZ', 'goog.i18n.DateTimePatterns_en_PG', 'goog.i18n.DateTimePatterns_en_PH', 'goog.i18n.DateTimePatterns_en_PK', 'goog.i18n.DateTimePatterns_en_PN', 'goog.i18n.DateTimePatterns_en_PR', 'goog.i18n.DateTimePatterns_en_PW', 'goog.i18n.DateTimePatterns_en_RW', 'goog.i18n.DateTimePatterns_en_SB', 'goog.i18n.DateTimePatterns_en_SC', 'goog.i18n.DateTimePatterns_en_SD', 'goog.i18n.DateTimePatterns_en_SH', 'goog.i18n.DateTimePatterns_en_SL', 'goog.i18n.DateTimePatterns_en_SS', 'goog.i18n.DateTimePatterns_en_SX', 'goog.i18n.DateTimePatterns_en_SZ', 'goog.i18n.DateTimePatterns_en_TC', 'goog.i18n.DateTimePatterns_en_TK', 'goog.i18n.DateTimePatterns_en_TO', 'goog.i18n.DateTimePatterns_en_TT', 'goog.i18n.DateTimePatterns_en_TV', 'goog.i18n.DateTimePatterns_en_TZ', 'goog.i18n.DateTimePatterns_en_UG', 'goog.i18n.DateTimePatterns_en_UM', 'goog.i18n.DateTimePatterns_en_US_POSIX', 'goog.i18n.DateTimePatterns_en_VC', 'goog.i18n.DateTimePatterns_en_VG', 'goog.i18n.DateTimePatterns_en_VI', 'goog.i18n.DateTimePatterns_en_VU', 'goog.i18n.DateTimePatterns_en_WS', 'goog.i18n.DateTimePatterns_en_ZM', 'goog.i18n.DateTimePatterns_en_ZW', 'goog.i18n.DateTimePatterns_eo', 'goog.i18n.DateTimePatterns_es_AR', 'goog.i18n.DateTimePatterns_es_BO', 'goog.i18n.DateTimePatterns_es_CL', 'goog.i18n.DateTimePatterns_es_CO', 'goog.i18n.DateTimePatterns_es_CR', 'goog.i18n.DateTimePatterns_es_CU', 'goog.i18n.DateTimePatterns_es_DO', 'goog.i18n.DateTimePatterns_es_EA', 'goog.i18n.DateTimePatterns_es_EC', 'goog.i18n.DateTimePatterns_es_GQ', 'goog.i18n.DateTimePatterns_es_GT', 'goog.i18n.DateTimePatterns_es_HN', 'goog.i18n.DateTimePatterns_es_IC', 'goog.i18n.DateTimePatterns_es_MX', 'goog.i18n.DateTimePatterns_es_NI', 'goog.i18n.DateTimePatterns_es_PA', 'goog.i18n.DateTimePatterns_es_PE', 'goog.i18n.DateTimePatterns_es_PH', 'goog.i18n.DateTimePatterns_es_PR', 'goog.i18n.DateTimePatterns_es_PY', 'goog.i18n.DateTimePatterns_es_SV', 'goog.i18n.DateTimePatterns_es_US', 'goog.i18n.DateTimePatterns_es_UY', 'goog.i18n.DateTimePatterns_es_VE', 'goog.i18n.DateTimePatterns_et_EE', 'goog.i18n.DateTimePatterns_eu_ES', 'goog.i18n.DateTimePatterns_ewo', 'goog.i18n.DateTimePatterns_ewo_CM', 'goog.i18n.DateTimePatterns_fa_AF', 'goog.i18n.DateTimePatterns_fa_IR', 'goog.i18n.DateTimePatterns_ff', 'goog.i18n.DateTimePatterns_ff_CM', 'goog.i18n.DateTimePatterns_ff_GN', 'goog.i18n.DateTimePatterns_ff_MR', 'goog.i18n.DateTimePatterns_ff_SN', 'goog.i18n.DateTimePatterns_fi_FI', 'goog.i18n.DateTimePatterns_fil_PH', 'goog.i18n.DateTimePatterns_fo', 'goog.i18n.DateTimePatterns_fo_FO', 'goog.i18n.DateTimePatterns_fr_BE', 'goog.i18n.DateTimePatterns_fr_BF', 'goog.i18n.DateTimePatterns_fr_BI', 'goog.i18n.DateTimePatterns_fr_BJ', 'goog.i18n.DateTimePatterns_fr_BL', 'goog.i18n.DateTimePatterns_fr_CD', 'goog.i18n.DateTimePatterns_fr_CF', 'goog.i18n.DateTimePatterns_fr_CG', 'goog.i18n.DateTimePatterns_fr_CH', 'goog.i18n.DateTimePatterns_fr_CI', 'goog.i18n.DateTimePatterns_fr_CM', 'goog.i18n.DateTimePatterns_fr_DJ', 'goog.i18n.DateTimePatterns_fr_DZ', 'goog.i18n.DateTimePatterns_fr_FR', 'goog.i18n.DateTimePatterns_fr_GA', 'goog.i18n.DateTimePatterns_fr_GF', 'goog.i18n.DateTimePatterns_fr_GN', 'goog.i18n.DateTimePatterns_fr_GP', 'goog.i18n.DateTimePatterns_fr_GQ', 'goog.i18n.DateTimePatterns_fr_HT', 'goog.i18n.DateTimePatterns_fr_KM', 'goog.i18n.DateTimePatterns_fr_LU', 'goog.i18n.DateTimePatterns_fr_MA', 'goog.i18n.DateTimePatterns_fr_MC', 'goog.i18n.DateTimePatterns_fr_MF', 'goog.i18n.DateTimePatterns_fr_MG', 'goog.i18n.DateTimePatterns_fr_ML', 'goog.i18n.DateTimePatterns_fr_MQ', 'goog.i18n.DateTimePatterns_fr_MR', 'goog.i18n.DateTimePatterns_fr_MU', 'goog.i18n.DateTimePatterns_fr_NC', 'goog.i18n.DateTimePatterns_fr_NE', 'goog.i18n.DateTimePatterns_fr_PF', 'goog.i18n.DateTimePatterns_fr_PM', 'goog.i18n.DateTimePatterns_fr_RE', 'goog.i18n.DateTimePatterns_fr_RW', 'goog.i18n.DateTimePatterns_fr_SC', 'goog.i18n.DateTimePatterns_fr_SN', 'goog.i18n.DateTimePatterns_fr_SY', 'goog.i18n.DateTimePatterns_fr_TD', 'goog.i18n.DateTimePatterns_fr_TG', 'goog.i18n.DateTimePatterns_fr_TN', 'goog.i18n.DateTimePatterns_fr_VU', 'goog.i18n.DateTimePatterns_fr_WF', 'goog.i18n.DateTimePatterns_fr_YT', 'goog.i18n.DateTimePatterns_fur', 'goog.i18n.DateTimePatterns_fur_IT', 'goog.i18n.DateTimePatterns_fy', 'goog.i18n.DateTimePatterns_fy_NL', 'goog.i18n.DateTimePatterns_ga_IE', 'goog.i18n.DateTimePatterns_gd', 'goog.i18n.DateTimePatterns_gd_GB', 'goog.i18n.DateTimePatterns_gl_ES', 'goog.i18n.DateTimePatterns_gsw_CH', 'goog.i18n.DateTimePatterns_gsw_FR', 'goog.i18n.DateTimePatterns_gsw_LI', 'goog.i18n.DateTimePatterns_gu_IN', 'goog.i18n.DateTimePatterns_guz', 'goog.i18n.DateTimePatterns_guz_KE', 'goog.i18n.DateTimePatterns_gv', 'goog.i18n.DateTimePatterns_gv_IM', 'goog.i18n.DateTimePatterns_ha', 'goog.i18n.DateTimePatterns_ha_Latn', 'goog.i18n.DateTimePatterns_ha_Latn_GH', 'goog.i18n.DateTimePatterns_ha_Latn_NE', 'goog.i18n.DateTimePatterns_ha_Latn_NG', 'goog.i18n.DateTimePatterns_haw_US', 'goog.i18n.DateTimePatterns_he_IL', 'goog.i18n.DateTimePatterns_hi_IN', 'goog.i18n.DateTimePatterns_hr_BA', 'goog.i18n.DateTimePatterns_hr_HR', 'goog.i18n.DateTimePatterns_hsb', 'goog.i18n.DateTimePatterns_hsb_DE', 'goog.i18n.DateTimePatterns_hu_HU', 'goog.i18n.DateTimePatterns_hy_AM', 'goog.i18n.DateTimePatterns_id_ID', 'goog.i18n.DateTimePatterns_ig', 'goog.i18n.DateTimePatterns_ig_NG', 'goog.i18n.DateTimePatterns_ii', 'goog.i18n.DateTimePatterns_ii_CN', 'goog.i18n.DateTimePatterns_is_IS', 'goog.i18n.DateTimePatterns_it_CH', 'goog.i18n.DateTimePatterns_it_IT', 'goog.i18n.DateTimePatterns_it_SM', 'goog.i18n.DateTimePatterns_ja_JP', 'goog.i18n.DateTimePatterns_jgo', 'goog.i18n.DateTimePatterns_jgo_CM', 'goog.i18n.DateTimePatterns_jmc', 'goog.i18n.DateTimePatterns_jmc_TZ', 'goog.i18n.DateTimePatterns_ka_GE', 'goog.i18n.DateTimePatterns_kab', 'goog.i18n.DateTimePatterns_kab_DZ', 'goog.i18n.DateTimePatterns_kam', 'goog.i18n.DateTimePatterns_kam_KE', 'goog.i18n.DateTimePatterns_kde', 'goog.i18n.DateTimePatterns_kde_TZ', 'goog.i18n.DateTimePatterns_kea', 'goog.i18n.DateTimePatterns_kea_CV', 'goog.i18n.DateTimePatterns_khq', 'goog.i18n.DateTimePatterns_khq_ML', 'goog.i18n.DateTimePatterns_ki', 'goog.i18n.DateTimePatterns_ki_KE', 'goog.i18n.DateTimePatterns_kk_Cyrl', 'goog.i18n.DateTimePatterns_kk_Cyrl_KZ', 'goog.i18n.DateTimePatterns_kkj', 'goog.i18n.DateTimePatterns_kkj_CM', 'goog.i18n.DateTimePatterns_kl', 'goog.i18n.DateTimePatterns_kl_GL', 'goog.i18n.DateTimePatterns_kln', 'goog.i18n.DateTimePatterns_kln_KE', 'goog.i18n.DateTimePatterns_km_KH', 'goog.i18n.DateTimePatterns_kn_IN', 'goog.i18n.DateTimePatterns_ko_KP', 'goog.i18n.DateTimePatterns_ko_KR', 'goog.i18n.DateTimePatterns_kok', 'goog.i18n.DateTimePatterns_kok_IN', 'goog.i18n.DateTimePatterns_ks', 'goog.i18n.DateTimePatterns_ks_Arab', 'goog.i18n.DateTimePatterns_ks_Arab_IN', 'goog.i18n.DateTimePatterns_ksb', 'goog.i18n.DateTimePatterns_ksb_TZ', 'goog.i18n.DateTimePatterns_ksf', 'goog.i18n.DateTimePatterns_ksf_CM', 'goog.i18n.DateTimePatterns_ksh', 'goog.i18n.DateTimePatterns_ksh_DE', 'goog.i18n.DateTimePatterns_kw', 'goog.i18n.DateTimePatterns_kw_GB', 'goog.i18n.DateTimePatterns_ky_Cyrl', 'goog.i18n.DateTimePatterns_ky_Cyrl_KG', 'goog.i18n.DateTimePatterns_lag', 'goog.i18n.DateTimePatterns_lag_TZ', 'goog.i18n.DateTimePatterns_lb', 'goog.i18n.DateTimePatterns_lb_LU', 'goog.i18n.DateTimePatterns_lg', 'goog.i18n.DateTimePatterns_lg_UG', 'goog.i18n.DateTimePatterns_lkt', 'goog.i18n.DateTimePatterns_lkt_US', 'goog.i18n.DateTimePatterns_ln_AO', 'goog.i18n.DateTimePatterns_ln_CD', 'goog.i18n.DateTimePatterns_ln_CF', 'goog.i18n.DateTimePatterns_ln_CG', 'goog.i18n.DateTimePatterns_lo_LA', 'goog.i18n.DateTimePatterns_lt_LT', 'goog.i18n.DateTimePatterns_lu', 'goog.i18n.DateTimePatterns_lu_CD', 'goog.i18n.DateTimePatterns_luo', 'goog.i18n.DateTimePatterns_luo_KE', 'goog.i18n.DateTimePatterns_luy', 'goog.i18n.DateTimePatterns_luy_KE', 'goog.i18n.DateTimePatterns_lv_LV', 'goog.i18n.DateTimePatterns_mas', 'goog.i18n.DateTimePatterns_mas_KE', 'goog.i18n.DateTimePatterns_mas_TZ', 'goog.i18n.DateTimePatterns_mer', 'goog.i18n.DateTimePatterns_mer_KE', 'goog.i18n.DateTimePatterns_mfe', 'goog.i18n.DateTimePatterns_mfe_MU', 'goog.i18n.DateTimePatterns_mg', 'goog.i18n.DateTimePatterns_mg_MG', 'goog.i18n.DateTimePatterns_mgh', 'goog.i18n.DateTimePatterns_mgh_MZ', 'goog.i18n.DateTimePatterns_mgo', 'goog.i18n.DateTimePatterns_mgo_CM', 'goog.i18n.DateTimePatterns_mk_MK', 'goog.i18n.DateTimePatterns_ml_IN', 'goog.i18n.DateTimePatterns_mn_Cyrl', 'goog.i18n.DateTimePatterns_mn_Cyrl_MN', 'goog.i18n.DateTimePatterns_mr_IN', 'goog.i18n.DateTimePatterns_ms_Latn', 'goog.i18n.DateTimePatterns_ms_Latn_BN', 'goog.i18n.DateTimePatterns_ms_Latn_MY', 'goog.i18n.DateTimePatterns_ms_Latn_SG', 'goog.i18n.DateTimePatterns_mt_MT', 'goog.i18n.DateTimePatterns_mua', 'goog.i18n.DateTimePatterns_mua_CM', 'goog.i18n.DateTimePatterns_my_MM', 'goog.i18n.DateTimePatterns_naq', 'goog.i18n.DateTimePatterns_naq_NA', 'goog.i18n.DateTimePatterns_nb_NO', 'goog.i18n.DateTimePatterns_nb_SJ', 'goog.i18n.DateTimePatterns_nd', 'goog.i18n.DateTimePatterns_nd_ZW', 'goog.i18n.DateTimePatterns_ne_IN', 'goog.i18n.DateTimePatterns_ne_NP', 'goog.i18n.DateTimePatterns_nl_AW', 'goog.i18n.DateTimePatterns_nl_BE', 'goog.i18n.DateTimePatterns_nl_BQ', 'goog.i18n.DateTimePatterns_nl_CW', 'goog.i18n.DateTimePatterns_nl_NL', 'goog.i18n.DateTimePatterns_nl_SR', 'goog.i18n.DateTimePatterns_nl_SX', 'goog.i18n.DateTimePatterns_nmg', 'goog.i18n.DateTimePatterns_nmg_CM', 'goog.i18n.DateTimePatterns_nn', 'goog.i18n.DateTimePatterns_nn_NO', 'goog.i18n.DateTimePatterns_nnh', 'goog.i18n.DateTimePatterns_nnh_CM', 'goog.i18n.DateTimePatterns_nus', 'goog.i18n.DateTimePatterns_nus_SD', 'goog.i18n.DateTimePatterns_nyn', 'goog.i18n.DateTimePatterns_nyn_UG', 'goog.i18n.DateTimePatterns_om', 'goog.i18n.DateTimePatterns_om_ET', 'goog.i18n.DateTimePatterns_om_KE', 'goog.i18n.DateTimePatterns_or_IN', 'goog.i18n.DateTimePatterns_os', 'goog.i18n.DateTimePatterns_os_GE', 'goog.i18n.DateTimePatterns_os_RU', 'goog.i18n.DateTimePatterns_pa_Arab', 'goog.i18n.DateTimePatterns_pa_Arab_PK', 'goog.i18n.DateTimePatterns_pa_Guru', 'goog.i18n.DateTimePatterns_pa_Guru_IN', 'goog.i18n.DateTimePatterns_pl_PL', 'goog.i18n.DateTimePatterns_ps', 'goog.i18n.DateTimePatterns_ps_AF', 'goog.i18n.DateTimePatterns_pt_AO', 'goog.i18n.DateTimePatterns_pt_CV', 'goog.i18n.DateTimePatterns_pt_GW', 'goog.i18n.DateTimePatterns_pt_MO', 'goog.i18n.DateTimePatterns_pt_MZ', 'goog.i18n.DateTimePatterns_pt_ST', 'goog.i18n.DateTimePatterns_pt_TL', 'goog.i18n.DateTimePatterns_qu', 'goog.i18n.DateTimePatterns_qu_BO', 'goog.i18n.DateTimePatterns_qu_EC', 'goog.i18n.DateTimePatterns_qu_PE', 'goog.i18n.DateTimePatterns_rm', 'goog.i18n.DateTimePatterns_rm_CH', 'goog.i18n.DateTimePatterns_rn', 'goog.i18n.DateTimePatterns_rn_BI', 'goog.i18n.DateTimePatterns_ro_MD', 'goog.i18n.DateTimePatterns_ro_RO', 'goog.i18n.DateTimePatterns_rof', 'goog.i18n.DateTimePatterns_rof_TZ', 'goog.i18n.DateTimePatterns_ru_BY', 'goog.i18n.DateTimePatterns_ru_KG', 'goog.i18n.DateTimePatterns_ru_KZ', 'goog.i18n.DateTimePatterns_ru_MD', 'goog.i18n.DateTimePatterns_ru_RU', 'goog.i18n.DateTimePatterns_ru_UA', 'goog.i18n.DateTimePatterns_rw', 'goog.i18n.DateTimePatterns_rw_RW', 'goog.i18n.DateTimePatterns_rwk', 'goog.i18n.DateTimePatterns_rwk_TZ', 'goog.i18n.DateTimePatterns_sah', 'goog.i18n.DateTimePatterns_sah_RU', 'goog.i18n.DateTimePatterns_saq', 'goog.i18n.DateTimePatterns_saq_KE', 'goog.i18n.DateTimePatterns_sbp', 'goog.i18n.DateTimePatterns_sbp_TZ', 'goog.i18n.DateTimePatterns_se', 'goog.i18n.DateTimePatterns_se_FI', 'goog.i18n.DateTimePatterns_se_NO', 'goog.i18n.DateTimePatterns_se_SE', 'goog.i18n.DateTimePatterns_seh', 'goog.i18n.DateTimePatterns_seh_MZ', 'goog.i18n.DateTimePatterns_ses', 'goog.i18n.DateTimePatterns_ses_ML', 'goog.i18n.DateTimePatterns_sg', 'goog.i18n.DateTimePatterns_sg_CF', 'goog.i18n.DateTimePatterns_shi', 'goog.i18n.DateTimePatterns_shi_Latn', 'goog.i18n.DateTimePatterns_shi_Latn_MA', 'goog.i18n.DateTimePatterns_shi_Tfng', 'goog.i18n.DateTimePatterns_shi_Tfng_MA', 'goog.i18n.DateTimePatterns_si_LK', 'goog.i18n.DateTimePatterns_sk_SK', 'goog.i18n.DateTimePatterns_sl_SI', 'goog.i18n.DateTimePatterns_smn', 'goog.i18n.DateTimePatterns_smn_FI', 'goog.i18n.DateTimePatterns_sn', 'goog.i18n.DateTimePatterns_sn_ZW', 'goog.i18n.DateTimePatterns_so', 'goog.i18n.DateTimePatterns_so_DJ', 'goog.i18n.DateTimePatterns_so_ET', 'goog.i18n.DateTimePatterns_so_KE', 'goog.i18n.DateTimePatterns_so_SO', 'goog.i18n.DateTimePatterns_sq_AL', 'goog.i18n.DateTimePatterns_sq_MK', 'goog.i18n.DateTimePatterns_sq_XK', 'goog.i18n.DateTimePatterns_sr_Cyrl', 'goog.i18n.DateTimePatterns_sr_Cyrl_BA', 'goog.i18n.DateTimePatterns_sr_Cyrl_ME', 'goog.i18n.DateTimePatterns_sr_Cyrl_RS', 'goog.i18n.DateTimePatterns_sr_Cyrl_XK', 'goog.i18n.DateTimePatterns_sr_Latn', 'goog.i18n.DateTimePatterns_sr_Latn_BA', 'goog.i18n.DateTimePatterns_sr_Latn_ME', 'goog.i18n.DateTimePatterns_sr_Latn_RS', 'goog.i18n.DateTimePatterns_sr_Latn_XK', 'goog.i18n.DateTimePatterns_sv_AX', 'goog.i18n.DateTimePatterns_sv_FI', 'goog.i18n.DateTimePatterns_sv_SE', 'goog.i18n.DateTimePatterns_sw_KE', 'goog.i18n.DateTimePatterns_sw_TZ', 'goog.i18n.DateTimePatterns_sw_UG', 'goog.i18n.DateTimePatterns_swc', 'goog.i18n.DateTimePatterns_swc_CD', 'goog.i18n.DateTimePatterns_ta_IN', 'goog.i18n.DateTimePatterns_ta_LK', 'goog.i18n.DateTimePatterns_ta_MY', 'goog.i18n.DateTimePatterns_ta_SG', 'goog.i18n.DateTimePatterns_te_IN', 'goog.i18n.DateTimePatterns_teo', 'goog.i18n.DateTimePatterns_teo_KE', 'goog.i18n.DateTimePatterns_teo_UG', 'goog.i18n.DateTimePatterns_th_TH', 'goog.i18n.DateTimePatterns_ti', 'goog.i18n.DateTimePatterns_ti_ER', 'goog.i18n.DateTimePatterns_ti_ET', 'goog.i18n.DateTimePatterns_to', 'goog.i18n.DateTimePatterns_to_TO', 'goog.i18n.DateTimePatterns_tr_CY', 'goog.i18n.DateTimePatterns_tr_TR', 'goog.i18n.DateTimePatterns_twq', 'goog.i18n.DateTimePatterns_twq_NE', 'goog.i18n.DateTimePatterns_tzm', 'goog.i18n.DateTimePatterns_tzm_Latn', 'goog.i18n.DateTimePatterns_tzm_Latn_MA', 'goog.i18n.DateTimePatterns_ug', 'goog.i18n.DateTimePatterns_ug_Arab', 'goog.i18n.DateTimePatterns_ug_Arab_CN', 'goog.i18n.DateTimePatterns_uk_UA', 'goog.i18n.DateTimePatterns_ur_IN', 'goog.i18n.DateTimePatterns_ur_PK', 'goog.i18n.DateTimePatterns_uz_Arab', 'goog.i18n.DateTimePatterns_uz_Arab_AF', 'goog.i18n.DateTimePatterns_uz_Cyrl', 'goog.i18n.DateTimePatterns_uz_Cyrl_UZ', 'goog.i18n.DateTimePatterns_uz_Latn', 'goog.i18n.DateTimePatterns_uz_Latn_UZ', 'goog.i18n.DateTimePatterns_vai', 'goog.i18n.DateTimePatterns_vai_Latn', 'goog.i18n.DateTimePatterns_vai_Latn_LR', 'goog.i18n.DateTimePatterns_vai_Vaii', 'goog.i18n.DateTimePatterns_vai_Vaii_LR', 'goog.i18n.DateTimePatterns_vi_VN', 'goog.i18n.DateTimePatterns_vun', 'goog.i18n.DateTimePatterns_vun_TZ', 'goog.i18n.DateTimePatterns_wae', 'goog.i18n.DateTimePatterns_wae_CH', 'goog.i18n.DateTimePatterns_xog', 'goog.i18n.DateTimePatterns_xog_UG', 'goog.i18n.DateTimePatterns_yav', 'goog.i18n.DateTimePatterns_yav_CM', 'goog.i18n.DateTimePatterns_yi', 'goog.i18n.DateTimePatterns_yi_001', 'goog.i18n.DateTimePatterns_yo', 'goog.i18n.DateTimePatterns_yo_BJ', 'goog.i18n.DateTimePatterns_yo_NG', 'goog.i18n.DateTimePatterns_zgh', 'goog.i18n.DateTimePatterns_zgh_MA', 'goog.i18n.DateTimePatterns_zh_Hans', 'goog.i18n.DateTimePatterns_zh_Hans_CN', 'goog.i18n.DateTimePatterns_zh_Hans_HK', 'goog.i18n.DateTimePatterns_zh_Hans_MO', 'goog.i18n.DateTimePatterns_zh_Hans_SG', 'goog.i18n.DateTimePatterns_zh_Hant', 'goog.i18n.DateTimePatterns_zh_Hant_HK', 'goog.i18n.DateTimePatterns_zh_Hant_MO', 'goog.i18n.DateTimePatterns_zh_Hant_TW', 'goog.i18n.DateTimePatterns_zu_ZA'], ['goog.i18n.DateTimePatterns'], false);
+goog.addDependency('i18n/datetimesymbols.js', ['goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_af', 'goog.i18n.DateTimeSymbols_am', 'goog.i18n.DateTimeSymbols_ar', 'goog.i18n.DateTimeSymbols_az', 'goog.i18n.DateTimeSymbols_bg', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_br', 'goog.i18n.DateTimeSymbols_ca', 'goog.i18n.DateTimeSymbols_chr', 'goog.i18n.DateTimeSymbols_cs', 'goog.i18n.DateTimeSymbols_cy', 'goog.i18n.DateTimeSymbols_da', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_de_AT', 'goog.i18n.DateTimeSymbols_de_CH', 'goog.i18n.DateTimeSymbols_el', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_AU', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_ISO', 'goog.i18n.DateTimeSymbols_en_SG', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_en_ZA', 'goog.i18n.DateTimeSymbols_es', 'goog.i18n.DateTimeSymbols_es_419', 'goog.i18n.DateTimeSymbols_es_ES', 'goog.i18n.DateTimeSymbols_et', 'goog.i18n.DateTimeSymbols_eu', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fi', 'goog.i18n.DateTimeSymbols_fil', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_CA', 'goog.i18n.DateTimeSymbols_ga', 'goog.i18n.DateTimeSymbols_gl', 'goog.i18n.DateTimeSymbols_gsw', 'goog.i18n.DateTimeSymbols_gu', 'goog.i18n.DateTimeSymbols_haw', 'goog.i18n.DateTimeSymbols_he', 'goog.i18n.DateTimeSymbols_hi', 'goog.i18n.DateTimeSymbols_hr', 'goog.i18n.DateTimeSymbols_hu', 'goog.i18n.DateTimeSymbols_hy', 'goog.i18n.DateTimeSymbols_id', 'goog.i18n.DateTimeSymbols_in', 'goog.i18n.DateTimeSymbols_is', 'goog.i18n.DateTimeSymbols_it', 'goog.i18n.DateTimeSymbols_iw', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_ka', 'goog.i18n.DateTimeSymbols_kk', 'goog.i18n.DateTimeSymbols_km', 'goog.i18n.DateTimeSymbols_kn', 'goog.i18n.DateTimeSymbols_ko', 'goog.i18n.DateTimeSymbols_ky', 'goog.i18n.DateTimeSymbols_ln', 'goog.i18n.DateTimeSymbols_lo', 'goog.i18n.DateTimeSymbols_lt', 'goog.i18n.DateTimeSymbols_lv', 'goog.i18n.DateTimeSymbols_mk', 'goog.i18n.DateTimeSymbols_ml', 'goog.i18n.DateTimeSymbols_mn', 'goog.i18n.DateTimeSymbols_mr', 'goog.i18n.DateTimeSymbols_ms', 'goog.i18n.DateTimeSymbols_mt', 'goog.i18n.DateTimeSymbols_my', 'goog.i18n.DateTimeSymbols_nb', 'goog.i18n.DateTimeSymbols_ne', 'goog.i18n.DateTimeSymbols_nl', 'goog.i18n.DateTimeSymbols_no', 'goog.i18n.DateTimeSymbols_no_NO', 'goog.i18n.DateTimeSymbols_or', 'goog.i18n.DateTimeSymbols_pa', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_pt', 'goog.i18n.DateTimeSymbols_pt_BR', 'goog.i18n.DateTimeSymbols_pt_PT', 'goog.i18n.DateTimeSymbols_ro', 'goog.i18n.DateTimeSymbols_ru', 'goog.i18n.DateTimeSymbols_si', 'goog.i18n.DateTimeSymbols_sk', 'goog.i18n.DateTimeSymbols_sl', 'goog.i18n.DateTimeSymbols_sq', 'goog.i18n.DateTimeSymbols_sr', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.DateTimeSymbols_sw', 'goog.i18n.DateTimeSymbols_ta', 'goog.i18n.DateTimeSymbols_te', 'goog.i18n.DateTimeSymbols_th', 'goog.i18n.DateTimeSymbols_tl', 'goog.i18n.DateTimeSymbols_tr', 'goog.i18n.DateTimeSymbols_uk', 'goog.i18n.DateTimeSymbols_ur', 'goog.i18n.DateTimeSymbols_uz', 'goog.i18n.DateTimeSymbols_vi', 'goog.i18n.DateTimeSymbols_zh', 'goog.i18n.DateTimeSymbols_zh_CN', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.i18n.DateTimeSymbols_zh_TW', 'goog.i18n.DateTimeSymbols_zu'], [], false);
+goog.addDependency('i18n/datetimesymbolsext.js', ['goog.i18n.DateTimeSymbolsExt', 'goog.i18n.DateTimeSymbols_aa', 'goog.i18n.DateTimeSymbols_aa_DJ', 'goog.i18n.DateTimeSymbols_aa_ER', 'goog.i18n.DateTimeSymbols_aa_ET', 'goog.i18n.DateTimeSymbols_af_NA', 'goog.i18n.DateTimeSymbols_af_ZA', 'goog.i18n.DateTimeSymbols_agq', 'goog.i18n.DateTimeSymbols_agq_CM', 'goog.i18n.DateTimeSymbols_ak', 'goog.i18n.DateTimeSymbols_ak_GH', 'goog.i18n.DateTimeSymbols_am_ET', 'goog.i18n.DateTimeSymbols_ar_001', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_BH', 'goog.i18n.DateTimeSymbols_ar_DJ', 'goog.i18n.DateTimeSymbols_ar_DZ', 'goog.i18n.DateTimeSymbols_ar_EG', 'goog.i18n.DateTimeSymbols_ar_EH', 'goog.i18n.DateTimeSymbols_ar_ER', 'goog.i18n.DateTimeSymbols_ar_IL', 'goog.i18n.DateTimeSymbols_ar_IQ', 'goog.i18n.DateTimeSymbols_ar_JO', 'goog.i18n.DateTimeSymbols_ar_KM', 'goog.i18n.DateTimeSymbols_ar_KW', 'goog.i18n.DateTimeSymbols_ar_LB', 'goog.i18n.DateTimeSymbols_ar_LY', 'goog.i18n.DateTimeSymbols_ar_MA', 'goog.i18n.DateTimeSymbols_ar_MR', 'goog.i18n.DateTimeSymbols_ar_OM', 'goog.i18n.DateTimeSymbols_ar_PS', 'goog.i18n.DateTimeSymbols_ar_QA', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_ar_SD', 'goog.i18n.DateTimeSymbols_ar_SO', 'goog.i18n.DateTimeSymbols_ar_SS', 'goog.i18n.DateTimeSymbols_ar_SY', 'goog.i18n.DateTimeSymbols_ar_TD', 'goog.i18n.DateTimeSymbols_ar_TN', 'goog.i18n.DateTimeSymbols_ar_YE', 'goog.i18n.DateTimeSymbols_as', 'goog.i18n.DateTimeSymbols_as_IN', 'goog.i18n.DateTimeSymbols_asa', 'goog.i18n.DateTimeSymbols_asa_TZ', 'goog.i18n.DateTimeSymbols_ast', 'goog.i18n.DateTimeSymbols_ast_ES', 'goog.i18n.DateTimeSymbols_az_Cyrl', 'goog.i18n.DateTimeSymbols_az_Cyrl_AZ', 'goog.i18n.DateTimeSymbols_az_Latn', 'goog.i18n.DateTimeSymbols_az_Latn_AZ', 'goog.i18n.DateTimeSymbols_bas', 'goog.i18n.DateTimeSymbols_bas_CM', 'goog.i18n.DateTimeSymbols_be', 'goog.i18n.DateTimeSymbols_be_BY', 'goog.i18n.DateTimeSymbols_bem', 'goog.i18n.DateTimeSymbols_bem_ZM', 'goog.i18n.DateTimeSymbols_bez', 'goog.i18n.DateTimeSymbols_bez_TZ', 'goog.i18n.DateTimeSymbols_bg_BG', 'goog.i18n.DateTimeSymbols_bm', 'goog.i18n.DateTimeSymbols_bm_Latn', 'goog.i18n.DateTimeSymbols_bm_Latn_ML', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_bn_IN', 'goog.i18n.DateTimeSymbols_bo', 'goog.i18n.DateTimeSymbols_bo_CN', 'goog.i18n.DateTimeSymbols_bo_IN', 'goog.i18n.DateTimeSymbols_br_FR', 'goog.i18n.DateTimeSymbols_brx', 'goog.i18n.DateTimeSymbols_brx_IN', 'goog.i18n.DateTimeSymbols_bs', 'goog.i18n.DateTimeSymbols_bs_Cyrl', 'goog.i18n.DateTimeSymbols_bs_Cyrl_BA', 'goog.i18n.DateTimeSymbols_bs_Latn', 'goog.i18n.DateTimeSymbols_bs_Latn_BA', 'goog.i18n.DateTimeSymbols_ca_AD', 'goog.i18n.DateTimeSymbols_ca_ES', 'goog.i18n.DateTimeSymbols_ca_ES_VALENCIA', 'goog.i18n.DateTimeSymbols_ca_FR', 'goog.i18n.DateTimeSymbols_ca_IT', 'goog.i18n.DateTimeSymbols_cgg', 'goog.i18n.DateTimeSymbols_cgg_UG', 'goog.i18n.DateTimeSymbols_chr_US', 'goog.i18n.DateTimeSymbols_ckb', 'goog.i18n.DateTimeSymbols_ckb_Arab', 'goog.i18n.DateTimeSymbols_ckb_Arab_IQ', 'goog.i18n.DateTimeSymbols_ckb_Arab_IR', 'goog.i18n.DateTimeSymbols_ckb_IQ', 'goog.i18n.DateTimeSymbols_ckb_IR', 'goog.i18n.DateTimeSymbols_ckb_Latn', 'goog.i18n.DateTimeSymbols_ckb_Latn_IQ', 'goog.i18n.DateTimeSymbols_cs_CZ', 'goog.i18n.DateTimeSymbols_cy_GB', 'goog.i18n.DateTimeSymbols_da_DK', 'goog.i18n.DateTimeSymbols_da_GL', 'goog.i18n.DateTimeSymbols_dav', 'goog.i18n.DateTimeSymbols_dav_KE', 'goog.i18n.DateTimeSymbols_de_BE', 'goog.i18n.DateTimeSymbols_de_DE', 'goog.i18n.DateTimeSymbols_de_LI', 'goog.i18n.DateTimeSymbols_de_LU', 'goog.i18n.DateTimeSymbols_dje', 'goog.i18n.DateTimeSymbols_dje_NE', 'goog.i18n.DateTimeSymbols_dsb', 'goog.i18n.DateTimeSymbols_dsb_DE', 'goog.i18n.DateTimeSymbols_dua', 'goog.i18n.DateTimeSymbols_dua_CM', 'goog.i18n.DateTimeSymbols_dyo', 'goog.i18n.DateTimeSymbols_dyo_SN', 'goog.i18n.DateTimeSymbols_dz', 'goog.i18n.DateTimeSymbols_dz_BT', 'goog.i18n.DateTimeSymbols_ebu', 'goog.i18n.DateTimeSymbols_ebu_KE', 'goog.i18n.DateTimeSymbols_ee', 'goog.i18n.DateTimeSymbols_ee_GH', 'goog.i18n.DateTimeSymbols_ee_TG', 'goog.i18n.DateTimeSymbols_el_CY', 'goog.i18n.DateTimeSymbols_el_GR', 'goog.i18n.DateTimeSymbols_en_001', 'goog.i18n.DateTimeSymbols_en_150', 'goog.i18n.DateTimeSymbols_en_AG', 'goog.i18n.DateTimeSymbols_en_AI', 'goog.i18n.DateTimeSymbols_en_AS', 'goog.i18n.DateTimeSymbols_en_BB', 'goog.i18n.DateTimeSymbols_en_BE', 'goog.i18n.DateTimeSymbols_en_BM', 'goog.i18n.DateTimeSymbols_en_BS', 'goog.i18n.DateTimeSymbols_en_BW', 'goog.i18n.DateTimeSymbols_en_BZ', 'goog.i18n.DateTimeSymbols_en_CA', 'goog.i18n.DateTimeSymbols_en_CC', 'goog.i18n.DateTimeSymbols_en_CK', 'goog.i18n.DateTimeSymbols_en_CM', 'goog.i18n.DateTimeSymbols_en_CX', 'goog.i18n.DateTimeSymbols_en_DG', 'goog.i18n.DateTimeSymbols_en_DM', 'goog.i18n.DateTimeSymbols_en_ER', 'goog.i18n.DateTimeSymbols_en_FJ', 'goog.i18n.DateTimeSymbols_en_FK', 'goog.i18n.DateTimeSymbols_en_FM', 'goog.i18n.DateTimeSymbols_en_GD', 'goog.i18n.DateTimeSymbols_en_GG', 'goog.i18n.DateTimeSymbols_en_GH', 'goog.i18n.DateTimeSymbols_en_GI', 'goog.i18n.DateTimeSymbols_en_GM', 'goog.i18n.DateTimeSymbols_en_GU', 'goog.i18n.DateTimeSymbols_en_GY', 'goog.i18n.DateTimeSymbols_en_HK', 'goog.i18n.DateTimeSymbols_en_IM', 'goog.i18n.DateTimeSymbols_en_IO', 'goog.i18n.DateTimeSymbols_en_JE', 'goog.i18n.DateTimeSymbols_en_JM', 'goog.i18n.DateTimeSymbols_en_KE', 'goog.i18n.DateTimeSymbols_en_KI', 'goog.i18n.DateTimeSymbols_en_KN', 'goog.i18n.DateTimeSymbols_en_KY', 'goog.i18n.DateTimeSymbols_en_LC', 'goog.i18n.DateTimeSymbols_en_LR', 'goog.i18n.DateTimeSymbols_en_LS', 'goog.i18n.DateTimeSymbols_en_MG', 'goog.i18n.DateTimeSymbols_en_MH', 'goog.i18n.DateTimeSymbols_en_MO', 'goog.i18n.DateTimeSymbols_en_MP', 'goog.i18n.DateTimeSymbols_en_MS', 'goog.i18n.DateTimeSymbols_en_MT', 'goog.i18n.DateTimeSymbols_en_MU', 'goog.i18n.DateTimeSymbols_en_MW', 'goog.i18n.DateTimeSymbols_en_MY', 'goog.i18n.DateTimeSymbols_en_NA', 'goog.i18n.DateTimeSymbols_en_NF', 'goog.i18n.DateTimeSymbols_en_NG', 'goog.i18n.DateTimeSymbols_en_NR', 'goog.i18n.DateTimeSymbols_en_NU', 'goog.i18n.DateTimeSymbols_en_NZ', 'goog.i18n.DateTimeSymbols_en_PG', 'goog.i18n.DateTimeSymbols_en_PH', 'goog.i18n.DateTimeSymbols_en_PK', 'goog.i18n.DateTimeSymbols_en_PN', 'goog.i18n.DateTimeSymbols_en_PR', 'goog.i18n.DateTimeSymbols_en_PW', 'goog.i18n.DateTimeSymbols_en_RW', 'goog.i18n.DateTimeSymbols_en_SB', 'goog.i18n.DateTimeSymbols_en_SC', 'goog.i18n.DateTimeSymbols_en_SD', 'goog.i18n.DateTimeSymbols_en_SH', 'goog.i18n.DateTimeSymbols_en_SL', 'goog.i18n.DateTimeSymbols_en_SS', 'goog.i18n.DateTimeSymbols_en_SX', 'goog.i18n.DateTimeSymbols_en_SZ', 'goog.i18n.DateTimeSymbols_en_TC', 'goog.i18n.DateTimeSymbols_en_TK', 'goog.i18n.DateTimeSymbols_en_TO', 'goog.i18n.DateTimeSymbols_en_TT', 'goog.i18n.DateTimeSymbols_en_TV', 'goog.i18n.DateTimeSymbols_en_TZ', 'goog.i18n.DateTimeSymbols_en_UG', 'goog.i18n.DateTimeSymbols_en_UM', 'goog.i18n.DateTimeSymbols_en_VC', 'goog.i18n.DateTimeSymbols_en_VG', 'goog.i18n.DateTimeSymbols_en_VI', 'goog.i18n.DateTimeSymbols_en_VU', 'goog.i18n.DateTimeSymbols_en_WS', 'goog.i18n.DateTimeSymbols_en_ZM', 'goog.i18n.DateTimeSymbols_en_ZW', 'goog.i18n.DateTimeSymbols_eo', 'goog.i18n.DateTimeSymbols_eo_001', 'goog.i18n.DateTimeSymbols_es_AR', 'goog.i18n.DateTimeSymbols_es_BO', 'goog.i18n.DateTimeSymbols_es_CL', 'goog.i18n.DateTimeSymbols_es_CO', 'goog.i18n.DateTimeSymbols_es_CR', 'goog.i18n.DateTimeSymbols_es_CU', 'goog.i18n.DateTimeSymbols_es_DO', 'goog.i18n.DateTimeSymbols_es_EA', 'goog.i18n.DateTimeSymbols_es_EC', 'goog.i18n.DateTimeSymbols_es_GQ', 'goog.i18n.DateTimeSymbols_es_GT', 'goog.i18n.DateTimeSymbols_es_HN', 'goog.i18n.DateTimeSymbols_es_IC', 'goog.i18n.DateTimeSymbols_es_MX', 'goog.i18n.DateTimeSymbols_es_NI', 'goog.i18n.DateTimeSymbols_es_PA', 'goog.i18n.DateTimeSymbols_es_PE', 'goog.i18n.DateTimeSymbols_es_PH', 'goog.i18n.DateTimeSymbols_es_PR', 'goog.i18n.DateTimeSymbols_es_PY', 'goog.i18n.DateTimeSymbols_es_SV', 'goog.i18n.DateTimeSymbols_es_US', 'goog.i18n.DateTimeSymbols_es_UY', 'goog.i18n.DateTimeSymbols_es_VE', 'goog.i18n.DateTimeSymbols_et_EE', 'goog.i18n.DateTimeSymbols_eu_ES', 'goog.i18n.DateTimeSymbols_ewo', 'goog.i18n.DateTimeSymbols_ewo_CM', 'goog.i18n.DateTimeSymbols_fa_AF', 'goog.i18n.DateTimeSymbols_fa_IR', 'goog.i18n.DateTimeSymbols_ff', 'goog.i18n.DateTimeSymbols_ff_CM', 'goog.i18n.DateTimeSymbols_ff_GN', 'goog.i18n.DateTimeSymbols_ff_MR', 'goog.i18n.DateTimeSymbols_ff_SN', 'goog.i18n.DateTimeSymbols_fi_FI', 'goog.i18n.DateTimeSymbols_fil_PH', 'goog.i18n.DateTimeSymbols_fo', 'goog.i18n.DateTimeSymbols_fo_FO', 'goog.i18n.DateTimeSymbols_fr_BE', 'goog.i18n.DateTimeSymbols_fr_BF', 'goog.i18n.DateTimeSymbols_fr_BI', 'goog.i18n.DateTimeSymbols_fr_BJ', 'goog.i18n.DateTimeSymbols_fr_BL', 'goog.i18n.DateTimeSymbols_fr_CD', 'goog.i18n.DateTimeSymbols_fr_CF', 'goog.i18n.DateTimeSymbols_fr_CG', 'goog.i18n.DateTimeSymbols_fr_CH', 'goog.i18n.DateTimeSymbols_fr_CI', 'goog.i18n.DateTimeSymbols_fr_CM', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_fr_DZ', 'goog.i18n.DateTimeSymbols_fr_FR', 'goog.i18n.DateTimeSymbols_fr_GA', 'goog.i18n.DateTimeSymbols_fr_GF', 'goog.i18n.DateTimeSymbols_fr_GN', 'goog.i18n.DateTimeSymbols_fr_GP', 'goog.i18n.DateTimeSymbols_fr_GQ', 'goog.i18n.DateTimeSymbols_fr_HT', 'goog.i18n.DateTimeSymbols_fr_KM', 'goog.i18n.DateTimeSymbols_fr_LU', 'goog.i18n.DateTimeSymbols_fr_MA', 'goog.i18n.DateTimeSymbols_fr_MC', 'goog.i18n.DateTimeSymbols_fr_MF', 'goog.i18n.DateTimeSymbols_fr_MG', 'goog.i18n.DateTimeSymbols_fr_ML', 'goog.i18n.DateTimeSymbols_fr_MQ', 'goog.i18n.DateTimeSymbols_fr_MR', 'goog.i18n.DateTimeSymbols_fr_MU', 'goog.i18n.DateTimeSymbols_fr_NC', 'goog.i18n.DateTimeSymbols_fr_NE', 'goog.i18n.DateTimeSymbols_fr_PF', 'goog.i18n.DateTimeSymbols_fr_PM', 'goog.i18n.DateTimeSymbols_fr_RE', 'goog.i18n.DateTimeSymbols_fr_RW', 'goog.i18n.DateTimeSymbols_fr_SC', 'goog.i18n.DateTimeSymbols_fr_SN', 'goog.i18n.DateTimeSymbols_fr_SY', 'goog.i18n.DateTimeSymbols_fr_TD', 'goog.i18n.DateTimeSymbols_fr_TG', 'goog.i18n.DateTimeSymbols_fr_TN', 'goog.i18n.DateTimeSymbols_fr_VU', 'goog.i18n.DateTimeSymbols_fr_WF', 'goog.i18n.DateTimeSymbols_fr_YT', 'goog.i18n.DateTimeSymbols_fur', 'goog.i18n.DateTimeSymbols_fur_IT', 'goog.i18n.DateTimeSymbols_fy', 'goog.i18n.DateTimeSymbols_fy_NL', 'goog.i18n.DateTimeSymbols_ga_IE', 'goog.i18n.DateTimeSymbols_gd', 'goog.i18n.DateTimeSymbols_gd_GB', 'goog.i18n.DateTimeSymbols_gl_ES', 'goog.i18n.DateTimeSymbols_gsw_CH', 'goog.i18n.DateTimeSymbols_gsw_FR', 'goog.i18n.DateTimeSymbols_gsw_LI', 'goog.i18n.DateTimeSymbols_gu_IN', 'goog.i18n.DateTimeSymbols_guz', 'goog.i18n.DateTimeSymbols_guz_KE', 'goog.i18n.DateTimeSymbols_gv', 'goog.i18n.DateTimeSymbols_gv_IM', 'goog.i18n.DateTimeSymbols_ha', 'goog.i18n.DateTimeSymbols_ha_Latn', 'goog.i18n.DateTimeSymbols_ha_Latn_GH', 'goog.i18n.DateTimeSymbols_ha_Latn_NE', 'goog.i18n.DateTimeSymbols_ha_Latn_NG', 'goog.i18n.DateTimeSymbols_haw_US', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_hi_IN', 'goog.i18n.DateTimeSymbols_hr_BA', 'goog.i18n.DateTimeSymbols_hr_HR', 'goog.i18n.DateTimeSymbols_hsb', 'goog.i18n.DateTimeSymbols_hsb_DE', 'goog.i18n.DateTimeSymbols_hu_HU', 'goog.i18n.DateTimeSymbols_hy_AM', 'goog.i18n.DateTimeSymbols_ia', 'goog.i18n.DateTimeSymbols_ia_FR', 'goog.i18n.DateTimeSymbols_id_ID', 'goog.i18n.DateTimeSymbols_ig', 'goog.i18n.DateTimeSymbols_ig_NG', 'goog.i18n.DateTimeSymbols_ii', 'goog.i18n.DateTimeSymbols_ii_CN', 'goog.i18n.DateTimeSymbols_is_IS', 'goog.i18n.DateTimeSymbols_it_CH', 'goog.i18n.DateTimeSymbols_it_IT', 'goog.i18n.DateTimeSymbols_it_SM', 'goog.i18n.DateTimeSymbols_ja_JP', 'goog.i18n.DateTimeSymbols_jgo', 'goog.i18n.DateTimeSymbols_jgo_CM', 'goog.i18n.DateTimeSymbols_jmc', 'goog.i18n.DateTimeSymbols_jmc_TZ', 'goog.i18n.DateTimeSymbols_ka_GE', 'goog.i18n.DateTimeSymbols_kab', 'goog.i18n.DateTimeSymbols_kab_DZ', 'goog.i18n.DateTimeSymbols_kam', 'goog.i18n.DateTimeSymbols_kam_KE', 'goog.i18n.DateTimeSymbols_kde', 'goog.i18n.DateTimeSymbols_kde_TZ', 'goog.i18n.DateTimeSymbols_kea', 'goog.i18n.DateTimeSymbols_kea_CV', 'goog.i18n.DateTimeSymbols_khq', 'goog.i18n.DateTimeSymbols_khq_ML', 'goog.i18n.DateTimeSymbols_ki', 'goog.i18n.DateTimeSymbols_ki_KE', 'goog.i18n.DateTimeSymbols_kk_Cyrl', 'goog.i18n.DateTimeSymbols_kk_Cyrl_KZ', 'goog.i18n.DateTimeSymbols_kkj', 'goog.i18n.DateTimeSymbols_kkj_CM', 'goog.i18n.DateTimeSymbols_kl', 'goog.i18n.DateTimeSymbols_kl_GL', 'goog.i18n.DateTimeSymbols_kln', 'goog.i18n.DateTimeSymbols_kln_KE', 'goog.i18n.DateTimeSymbols_km_KH', 'goog.i18n.DateTimeSymbols_kn_IN', 'goog.i18n.DateTimeSymbols_ko_KP', 'goog.i18n.DateTimeSymbols_ko_KR', 'goog.i18n.DateTimeSymbols_kok', 'goog.i18n.DateTimeSymbols_kok_IN', 'goog.i18n.DateTimeSymbols_ks', 'goog.i18n.DateTimeSymbols_ks_Arab', 'goog.i18n.DateTimeSymbols_ks_Arab_IN', 'goog.i18n.DateTimeSymbols_ksb', 'goog.i18n.DateTimeSymbols_ksb_TZ', 'goog.i18n.DateTimeSymbols_ksf', 'goog.i18n.DateTimeSymbols_ksf_CM', 'goog.i18n.DateTimeSymbols_ksh', 'goog.i18n.DateTimeSymbols_ksh_DE', 'goog.i18n.DateTimeSymbols_kw', 'goog.i18n.DateTimeSymbols_kw_GB', 'goog.i18n.DateTimeSymbols_ky_Cyrl', 'goog.i18n.DateTimeSymbols_ky_Cyrl_KG', 'goog.i18n.DateTimeSymbols_lag', 'goog.i18n.DateTimeSymbols_lag_TZ', 'goog.i18n.DateTimeSymbols_lb', 'goog.i18n.DateTimeSymbols_lb_LU', 'goog.i18n.DateTimeSymbols_lg', 'goog.i18n.DateTimeSymbols_lg_UG', 'goog.i18n.DateTimeSymbols_lkt', 'goog.i18n.DateTimeSymbols_lkt_US', 'goog.i18n.DateTimeSymbols_ln_AO', 'goog.i18n.DateTimeSymbols_ln_CD', 'goog.i18n.DateTimeSymbols_ln_CF', 'goog.i18n.DateTimeSymbols_ln_CG', 'goog.i18n.DateTimeSymbols_lo_LA', 'goog.i18n.DateTimeSymbols_lt_LT', 'goog.i18n.DateTimeSymbols_lu', 'goog.i18n.DateTimeSymbols_lu_CD', 'goog.i18n.DateTimeSymbols_luo', 'goog.i18n.DateTimeSymbols_luo_KE', 'goog.i18n.DateTimeSymbols_luy', 'goog.i18n.DateTimeSymbols_luy_KE', 'goog.i18n.DateTimeSymbols_lv_LV', 'goog.i18n.DateTimeSymbols_mas', 'goog.i18n.DateTimeSymbols_mas_KE', 'goog.i18n.DateTimeSymbols_mas_TZ', 'goog.i18n.DateTimeSymbols_mer', 'goog.i18n.DateTimeSymbols_mer_KE', 'goog.i18n.DateTimeSymbols_mfe', 'goog.i18n.DateTimeSymbols_mfe_MU', 'goog.i18n.DateTimeSymbols_mg', 'goog.i18n.DateTimeSymbols_mg_MG', 'goog.i18n.DateTimeSymbols_mgh', 'goog.i18n.DateTimeSymbols_mgh_MZ', 'goog.i18n.DateTimeSymbols_mgo', 'goog.i18n.DateTimeSymbols_mgo_CM', 'goog.i18n.DateTimeSymbols_mk_MK', 'goog.i18n.DateTimeSymbols_ml_IN', 'goog.i18n.DateTimeSymbols_mn_Cyrl', 'goog.i18n.DateTimeSymbols_mn_Cyrl_MN', 'goog.i18n.DateTimeSymbols_mr_IN', 'goog.i18n.DateTimeSymbols_ms_Latn', 'goog.i18n.DateTimeSymbols_ms_Latn_BN', 'goog.i18n.DateTimeSymbols_ms_Latn_MY', 'goog.i18n.DateTimeSymbols_ms_Latn_SG', 'goog.i18n.DateTimeSymbols_mt_MT', 'goog.i18n.DateTimeSymbols_mua', 'goog.i18n.DateTimeSymbols_mua_CM', 'goog.i18n.DateTimeSymbols_my_MM', 'goog.i18n.DateTimeSymbols_naq', 'goog.i18n.DateTimeSymbols_naq_NA', 'goog.i18n.DateTimeSymbols_nb_NO', 'goog.i18n.DateTimeSymbols_nb_SJ', 'goog.i18n.DateTimeSymbols_nd', 'goog.i18n.DateTimeSymbols_nd_ZW', 'goog.i18n.DateTimeSymbols_ne_IN', 'goog.i18n.DateTimeSymbols_ne_NP', 'goog.i18n.DateTimeSymbols_nl_AW', 'goog.i18n.DateTimeSymbols_nl_BE', 'goog.i18n.DateTimeSymbols_nl_BQ', 'goog.i18n.DateTimeSymbols_nl_CW', 'goog.i18n.DateTimeSymbols_nl_NL', 'goog.i18n.DateTimeSymbols_nl_SR', 'goog.i18n.DateTimeSymbols_nl_SX', 'goog.i18n.DateTimeSymbols_nmg', 'goog.i18n.DateTimeSymbols_nmg_CM', 'goog.i18n.DateTimeSymbols_nn', 'goog.i18n.DateTimeSymbols_nn_NO', 'goog.i18n.DateTimeSymbols_nnh', 'goog.i18n.DateTimeSymbols_nnh_CM', 'goog.i18n.DateTimeSymbols_nr', 'goog.i18n.DateTimeSymbols_nr_ZA', 'goog.i18n.DateTimeSymbols_nso', 'goog.i18n.DateTimeSymbols_nso_ZA', 'goog.i18n.DateTimeSymbols_nus', 'goog.i18n.DateTimeSymbols_nus_SD', 'goog.i18n.DateTimeSymbols_nyn', 'goog.i18n.DateTimeSymbols_nyn_UG', 'goog.i18n.DateTimeSymbols_om', 'goog.i18n.DateTimeSymbols_om_ET', 'goog.i18n.DateTimeSymbols_om_KE', 'goog.i18n.DateTimeSymbols_or_IN', 'goog.i18n.DateTimeSymbols_os', 'goog.i18n.DateTimeSymbols_os_GE', 'goog.i18n.DateTimeSymbols_os_RU', 'goog.i18n.DateTimeSymbols_pa_Arab', 'goog.i18n.DateTimeSymbols_pa_Arab_PK', 'goog.i18n.DateTimeSymbols_pa_Guru', 'goog.i18n.DateTimeSymbols_pa_Guru_IN', 'goog.i18n.DateTimeSymbols_pl_PL', 'goog.i18n.DateTimeSymbols_ps', 'goog.i18n.DateTimeSymbols_ps_AF', 'goog.i18n.DateTimeSymbols_pt_AO', 'goog.i18n.DateTimeSymbols_pt_CV', 'goog.i18n.DateTimeSymbols_pt_GW', 'goog.i18n.DateTimeSymbols_pt_MO', 'goog.i18n.DateTimeSymbols_pt_MZ', 'goog.i18n.DateTimeSymbols_pt_ST', 'goog.i18n.DateTimeSymbols_pt_TL', 'goog.i18n.DateTimeSymbols_qu', 'goog.i18n.DateTimeSymbols_qu_BO', 'goog.i18n.DateTimeSymbols_qu_EC', 'goog.i18n.DateTimeSymbols_qu_PE', 'goog.i18n.DateTimeSymbols_rm', 'goog.i18n.DateTimeSymbols_rm_CH', 'goog.i18n.DateTimeSymbols_rn', 'goog.i18n.DateTimeSymbols_rn_BI', 'goog.i18n.DateTimeSymbols_ro_MD', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_rof', 'goog.i18n.DateTimeSymbols_rof_TZ', 'goog.i18n.DateTimeSymbols_ru_BY', 'goog.i18n.DateTimeSymbols_ru_KG', 'goog.i18n.DateTimeSymbols_ru_KZ', 'goog.i18n.DateTimeSymbols_ru_MD', 'goog.i18n.DateTimeSymbols_ru_RU', 'goog.i18n.DateTimeSymbols_ru_UA', 'goog.i18n.DateTimeSymbols_rw', 'goog.i18n.DateTimeSymbols_rw_RW', 'goog.i18n.DateTimeSymbols_rwk', 'goog.i18n.DateTimeSymbols_rwk_TZ', 'goog.i18n.DateTimeSymbols_sah', 'goog.i18n.DateTimeSymbols_sah_RU', 'goog.i18n.DateTimeSymbols_saq', 'goog.i18n.DateTimeSymbols_saq_KE', 'goog.i18n.DateTimeSymbols_sbp', 'goog.i18n.DateTimeSymbols_sbp_TZ', 'goog.i18n.DateTimeSymbols_se', 'goog.i18n.DateTimeSymbols_se_FI', 'goog.i18n.DateTimeSymbols_se_NO', 'goog.i18n.DateTimeSymbols_se_SE', 'goog.i18n.DateTimeSymbols_seh', 'goog.i18n.DateTimeSymbols_seh_MZ', 'goog.i18n.DateTimeSymbols_ses', 'goog.i18n.DateTimeSymbols_ses_ML', 'goog.i18n.DateTimeSymbols_sg', 'goog.i18n.DateTimeSymbols_sg_CF', 'goog.i18n.DateTimeSymbols_shi', 'goog.i18n.DateTimeSymbols_shi_Latn', 'goog.i18n.DateTimeSymbols_shi_Latn_MA', 'goog.i18n.DateTimeSymbols_shi_Tfng', 'goog.i18n.DateTimeSymbols_shi_Tfng_MA', 'goog.i18n.DateTimeSymbols_si_LK', 'goog.i18n.DateTimeSymbols_sk_SK', 'goog.i18n.DateTimeSymbols_sl_SI', 'goog.i18n.DateTimeSymbols_smn', 'goog.i18n.DateTimeSymbols_smn_FI', 'goog.i18n.DateTimeSymbols_sn', 'goog.i18n.DateTimeSymbols_sn_ZW', 'goog.i18n.DateTimeSymbols_so', 'goog.i18n.DateTimeSymbols_so_DJ', 'goog.i18n.DateTimeSymbols_so_ET', 'goog.i18n.DateTimeSymbols_so_KE', 'goog.i18n.DateTimeSymbols_so_SO', 'goog.i18n.DateTimeSymbols_sq_AL', 'goog.i18n.DateTimeSymbols_sq_MK', 'goog.i18n.DateTimeSymbols_sq_XK', 'goog.i18n.DateTimeSymbols_sr_Cyrl', 'goog.i18n.DateTimeSymbols_sr_Cyrl_BA', 'goog.i18n.DateTimeSymbols_sr_Cyrl_ME', 'goog.i18n.DateTimeSymbols_sr_Cyrl_RS', 'goog.i18n.DateTimeSymbols_sr_Cyrl_XK', 'goog.i18n.DateTimeSymbols_sr_Latn', 'goog.i18n.DateTimeSymbols_sr_Latn_BA', 'goog.i18n.DateTimeSymbols_sr_Latn_ME', 'goog.i18n.DateTimeSymbols_sr_Latn_RS', 'goog.i18n.DateTimeSymbols_sr_Latn_XK', 'goog.i18n.DateTimeSymbols_ss', 'goog.i18n.DateTimeSymbols_ss_SZ', 'goog.i18n.DateTimeSymbols_ss_ZA', 'goog.i18n.DateTimeSymbols_ssy', 'goog.i18n.DateTimeSymbols_ssy_ER', 'goog.i18n.DateTimeSymbols_sv_AX', 'goog.i18n.DateTimeSymbols_sv_FI', 'goog.i18n.DateTimeSymbols_sv_SE', 'goog.i18n.DateTimeSymbols_sw_KE', 'goog.i18n.DateTimeSymbols_sw_TZ', 'goog.i18n.DateTimeSymbols_sw_UG', 'goog.i18n.DateTimeSymbols_swc', 'goog.i18n.DateTimeSymbols_swc_CD', 'goog.i18n.DateTimeSymbols_ta_IN', 'goog.i18n.DateTimeSymbols_ta_LK', 'goog.i18n.DateTimeSymbols_ta_MY', 'goog.i18n.DateTimeSymbols_ta_SG', 'goog.i18n.DateTimeSymbols_te_IN', 'goog.i18n.DateTimeSymbols_teo', 'goog.i18n.DateTimeSymbols_teo_KE', 'goog.i18n.DateTimeSymbols_teo_UG', 'goog.i18n.DateTimeSymbols_th_TH', 'goog.i18n.DateTimeSymbols_ti', 'goog.i18n.DateTimeSymbols_ti_ER', 'goog.i18n.DateTimeSymbols_ti_ET', 'goog.i18n.DateTimeSymbols_tn', 'goog.i18n.DateTimeSymbols_tn_BW', 'goog.i18n.DateTimeSymbols_tn_ZA', 'goog.i18n.DateTimeSymbols_to', 'goog.i18n.DateTimeSymbols_to_TO', 'goog.i18n.DateTimeSymbols_tr_CY', 'goog.i18n.DateTimeSymbols_tr_TR', 'goog.i18n.DateTimeSymbols_ts', 'goog.i18n.DateTimeSymbols_ts_ZA', 'goog.i18n.DateTimeSymbols_twq', 'goog.i18n.DateTimeSymbols_twq_NE', 'goog.i18n.DateTimeSymbols_tzm', 'goog.i18n.DateTimeSymbols_tzm_Latn', 'goog.i18n.DateTimeSymbols_tzm_Latn_MA', 'goog.i18n.DateTimeSymbols_ug', 'goog.i18n.DateTimeSymbols_ug_Arab', 'goog.i18n.DateTimeSymbols_ug_Arab_CN', 'goog.i18n.DateTimeSymbols_uk_UA', 'goog.i18n.DateTimeSymbols_ur_IN', 'goog.i18n.DateTimeSymbols_ur_PK', 'goog.i18n.DateTimeSymbols_uz_Arab', 'goog.i18n.DateTimeSymbols_uz_Arab_AF', 'goog.i18n.DateTimeSymbols_uz_Cyrl', 'goog.i18n.DateTimeSymbols_uz_Cyrl_UZ', 'goog.i18n.DateTimeSymbols_uz_Latn', 'goog.i18n.DateTimeSymbols_uz_Latn_UZ', 'goog.i18n.DateTimeSymbols_vai', 'goog.i18n.DateTimeSymbols_vai_Latn', 'goog.i18n.DateTimeSymbols_vai_Latn_LR', 'goog.i18n.DateTimeSymbols_vai_Vaii', 'goog.i18n.DateTimeSymbols_vai_Vaii_LR', 'goog.i18n.DateTimeSymbols_ve', 'goog.i18n.DateTimeSymbols_ve_ZA', 'goog.i18n.DateTimeSymbols_vi_VN', 'goog.i18n.DateTimeSymbols_vo', 'goog.i18n.DateTimeSymbols_vo_001', 'goog.i18n.DateTimeSymbols_vun', 'goog.i18n.DateTimeSymbols_vun_TZ', 'goog.i18n.DateTimeSymbols_wae', 'goog.i18n.DateTimeSymbols_wae_CH', 'goog.i18n.DateTimeSymbols_xog', 'goog.i18n.DateTimeSymbols_xog_UG', 'goog.i18n.DateTimeSymbols_yav', 'goog.i18n.DateTimeSymbols_yav_CM', 'goog.i18n.DateTimeSymbols_yi', 'goog.i18n.DateTimeSymbols_yi_001', 'goog.i18n.DateTimeSymbols_yo', 'goog.i18n.DateTimeSymbols_yo_BJ', 'goog.i18n.DateTimeSymbols_yo_NG', 'goog.i18n.DateTimeSymbols_zgh', 'goog.i18n.DateTimeSymbols_zgh_MA', 'goog.i18n.DateTimeSymbols_zh_Hans', 'goog.i18n.DateTimeSymbols_zh_Hans_CN', 'goog.i18n.DateTimeSymbols_zh_Hans_HK', 'goog.i18n.DateTimeSymbols_zh_Hans_MO', 'goog.i18n.DateTimeSymbols_zh_Hans_SG', 'goog.i18n.DateTimeSymbols_zh_Hant', 'goog.i18n.DateTimeSymbols_zh_Hant_HK', 'goog.i18n.DateTimeSymbols_zh_Hant_MO', 'goog.i18n.DateTimeSymbols_zh_Hant_TW', 'goog.i18n.DateTimeSymbols_zu_ZA'], ['goog.i18n.DateTimeSymbols'], false);
+goog.addDependency('i18n/graphemebreak.js', ['goog.i18n.GraphemeBreak'], ['goog.structs.InversionMap'], false);
+goog.addDependency('i18n/graphemebreak_test.js', ['goog.i18n.GraphemeBreakTest'], ['goog.i18n.GraphemeBreak', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/messageformat.js', ['goog.i18n.MessageFormat'], ['goog.asserts', 'goog.i18n.NumberFormat', 'goog.i18n.ordinalRules', 'goog.i18n.pluralRules'], false);
+goog.addDependency('i18n/messageformat_test.js', ['goog.i18n.MessageFormatTest'], ['goog.i18n.MessageFormat', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.pluralRules', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/mime.js', ['goog.i18n.mime', 'goog.i18n.mime.encode'], ['goog.array'], false);
+goog.addDependency('i18n/mime_test.js', ['goog.i18n.mime.encodeTest'], ['goog.i18n.mime.encode', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/numberformat.js', ['goog.i18n.NumberFormat', 'goog.i18n.NumberFormat.CurrencyStyle', 'goog.i18n.NumberFormat.Format'], ['goog.asserts', 'goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.currency', 'goog.math'], false);
+goog.addDependency('i18n/numberformat_test.js', ['goog.i18n.NumberFormatTest'], ['goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.CompactNumberFormatSymbols_de', 'goog.i18n.CompactNumberFormatSymbols_en', 'goog.i18n.CompactNumberFormatSymbols_fr', 'goog.i18n.NumberFormat', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_ro', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('i18n/numberformatsymbols.js', ['goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_af', 'goog.i18n.NumberFormatSymbols_af_ZA', 'goog.i18n.NumberFormatSymbols_am', 'goog.i18n.NumberFormatSymbols_am_ET', 'goog.i18n.NumberFormatSymbols_ar', 'goog.i18n.NumberFormatSymbols_ar_001', 'goog.i18n.NumberFormatSymbols_az', 'goog.i18n.NumberFormatSymbols_az_Latn_AZ', 'goog.i18n.NumberFormatSymbols_bg', 'goog.i18n.NumberFormatSymbols_bg_BG', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_bn_BD', 'goog.i18n.NumberFormatSymbols_br', 'goog.i18n.NumberFormatSymbols_br_FR', 'goog.i18n.NumberFormatSymbols_ca', 'goog.i18n.NumberFormatSymbols_ca_AD', 'goog.i18n.NumberFormatSymbols_ca_ES', 'goog.i18n.NumberFormatSymbols_ca_ES_VALENCIA', 'goog.i18n.NumberFormatSymbols_ca_FR', 'goog.i18n.NumberFormatSymbols_ca_IT', 'goog.i18n.NumberFormatSymbols_chr', 'goog.i18n.NumberFormatSymbols_chr_US', 'goog.i18n.NumberFormatSymbols_cs', 'goog.i18n.NumberFormatSymbols_cs_CZ', 'goog.i18n.NumberFormatSymbols_cy', 'goog.i18n.NumberFormatSymbols_cy_GB', 'goog.i18n.NumberFormatSymbols_da', 'goog.i18n.NumberFormatSymbols_da_DK', 'goog.i18n.NumberFormatSymbols_da_GL', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_de_AT', 'goog.i18n.NumberFormatSymbols_de_BE', 'goog.i18n.NumberFormatSymbols_de_CH', 'goog.i18n.NumberFormatSymbols_de_DE', 'goog.i18n.NumberFormatSymbols_de_LU', 'goog.i18n.NumberFormatSymbols_el', 'goog.i18n.NumberFormatSymbols_el_GR', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_en_001', 'goog.i18n.NumberFormatSymbols_en_AS', 'goog.i18n.NumberFormatSymbols_en_AU', 'goog.i18n.NumberFormatSymbols_en_DG', 'goog.i18n.NumberFormatSymbols_en_FM', 'goog.i18n.NumberFormatSymbols_en_GB', 'goog.i18n.NumberFormatSymbols_en_GU', 'goog.i18n.NumberFormatSymbols_en_IE', 'goog.i18n.NumberFormatSymbols_en_IN', 'goog.i18n.NumberFormatSymbols_en_IO', 'goog.i18n.NumberFormatSymbols_en_MH', 'goog.i18n.NumberFormatSymbols_en_MP', 'goog.i18n.NumberFormatSymbols_en_PR', 'goog.i18n.NumberFormatSymbols_en_PW', 'goog.i18n.NumberFormatSymbols_en_SG', 'goog.i18n.NumberFormatSymbols_en_TC', 'goog.i18n.NumberFormatSymbols_en_UM', 'goog.i18n.NumberFormatSymbols_en_US', 'goog.i18n.NumberFormatSymbols_en_VG', 'goog.i18n.NumberFormatSymbols_en_VI', 'goog.i18n.NumberFormatSymbols_en_ZA', 'goog.i18n.NumberFormatSymbols_en_ZW', 'goog.i18n.NumberFormatSymbols_es', 'goog.i18n.NumberFormatSymbols_es_419', 'goog.i18n.NumberFormatSymbols_es_EA', 'goog.i18n.NumberFormatSymbols_es_ES', 'goog.i18n.NumberFormatSymbols_es_IC', 'goog.i18n.NumberFormatSymbols_et', 'goog.i18n.NumberFormatSymbols_et_EE', 'goog.i18n.NumberFormatSymbols_eu', 'goog.i18n.NumberFormatSymbols_eu_ES', 'goog.i18n.NumberFormatSymbols_fa', 'goog.i18n.NumberFormatSymbols_fa_IR', 'goog.i18n.NumberFormatSymbols_fi', 'goog.i18n.NumberFormatSymbols_fi_FI', 'goog.i18n.NumberFormatSymbols_fil', 'goog.i18n.NumberFormatSymbols_fil_PH', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_fr_BL', 'goog.i18n.NumberFormatSymbols_fr_CA', 'goog.i18n.NumberFormatSymbols_fr_FR', 'goog.i18n.NumberFormatSymbols_fr_GF', 'goog.i18n.NumberFormatSymbols_fr_GP', 'goog.i18n.NumberFormatSymbols_fr_MC', 'goog.i18n.NumberFormatSymbols_fr_MF', 'goog.i18n.NumberFormatSymbols_fr_MQ', 'goog.i18n.NumberFormatSymbols_fr_PM', 'goog.i18n.NumberFormatSymbols_fr_RE', 'goog.i18n.NumberFormatSymbols_fr_YT', 'goog.i18n.NumberFormatSymbols_ga', 'goog.i18n.NumberFormatSymbols_ga_IE', 'goog.i18n.NumberFormatSymbols_gl', 'goog.i18n.NumberFormatSymbols_gl_ES', 'goog.i18n.NumberFormatSymbols_gsw', 'goog.i18n.NumberFormatSymbols_gsw_CH', 'goog.i18n.NumberFormatSymbols_gsw_LI', 'goog.i18n.NumberFormatSymbols_gu', 'goog.i18n.NumberFormatSymbols_gu_IN', 'goog.i18n.NumberFormatSymbols_haw', 'goog.i18n.NumberFormatSymbols_haw_US', 'goog.i18n.NumberFormatSymbols_he', 'goog.i18n.NumberFormatSymbols_he_IL', 'goog.i18n.NumberFormatSymbols_hi', 'goog.i18n.NumberFormatSymbols_hi_IN', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.NumberFormatSymbols_hr_HR', 'goog.i18n.NumberFormatSymbols_hu', 'goog.i18n.NumberFormatSymbols_hu_HU', 'goog.i18n.NumberFormatSymbols_hy', 'goog.i18n.NumberFormatSymbols_hy_AM', 'goog.i18n.NumberFormatSymbols_id', 'goog.i18n.NumberFormatSymbols_id_ID', 'goog.i18n.NumberFormatSymbols_in', 'goog.i18n.NumberFormatSymbols_is', 'goog.i18n.NumberFormatSymbols_is_IS', 'goog.i18n.NumberFormatSymbols_it', 'goog.i18n.NumberFormatSymbols_it_IT', 'goog.i18n.NumberFormatSymbols_it_SM', 'goog.i18n.NumberFormatSymbols_iw', 'goog.i18n.NumberFormatSymbols_ja', 'goog.i18n.NumberFormatSymbols_ja_JP', 'goog.i18n.NumberFormatSymbols_ka', 'goog.i18n.NumberFormatSymbols_ka_GE', 'goog.i18n.NumberFormatSymbols_kk', 'goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ', 'goog.i18n.NumberFormatSymbols_km', 'goog.i18n.NumberFormatSymbols_km_KH', 'goog.i18n.NumberFormatSymbols_kn', 'goog.i18n.NumberFormatSymbols_kn_IN', 'goog.i18n.NumberFormatSymbols_ko', 'goog.i18n.NumberFormatSymbols_ko_KR', 'goog.i18n.NumberFormatSymbols_ky', 'goog.i18n.NumberFormatSymbols_ky_Cyrl_KG', 'goog.i18n.NumberFormatSymbols_ln', 'goog.i18n.NumberFormatSymbols_ln_CD', 'goog.i18n.NumberFormatSymbols_lo', 'goog.i18n.NumberFormatSymbols_lo_LA', 'goog.i18n.NumberFormatSymbols_lt', 'goog.i18n.NumberFormatSymbols_lt_LT', 'goog.i18n.NumberFormatSymbols_lv', 'goog.i18n.NumberFormatSymbols_lv_LV', 'goog.i18n.NumberFormatSymbols_mk', 'goog.i18n.NumberFormatSymbols_mk_MK', 'goog.i18n.NumberFormatSymbols_ml', 'goog.i18n.NumberFormatSymbols_ml_IN', 'goog.i18n.NumberFormatSymbols_mn', 'goog.i18n.NumberFormatSymbols_mn_Cyrl_MN', 'goog.i18n.NumberFormatSymbols_mr', 'goog.i18n.NumberFormatSymbols_mr_IN', 'goog.i18n.NumberFormatSymbols_ms', 'goog.i18n.NumberFormatSymbols_ms_Latn_MY', 'goog.i18n.NumberFormatSymbols_mt', 'goog.i18n.NumberFormatSymbols_mt_MT', 'goog.i18n.NumberFormatSymbols_my', 'goog.i18n.NumberFormatSymbols_my_MM', 'goog.i18n.NumberFormatSymbols_nb', 'goog.i18n.NumberFormatSymbols_nb_NO', 'goog.i18n.NumberFormatSymbols_nb_SJ', 'goog.i18n.NumberFormatSymbols_ne', 'goog.i18n.NumberFormatSymbols_ne_NP', 'goog.i18n.NumberFormatSymbols_nl', 'goog.i18n.NumberFormatSymbols_nl_NL', 'goog.i18n.NumberFormatSymbols_no', 'goog.i18n.NumberFormatSymbols_no_NO', 'goog.i18n.NumberFormatSymbols_or', 'goog.i18n.NumberFormatSymbols_or_IN', 'goog.i18n.NumberFormatSymbols_pa', 'goog.i18n.NumberFormatSymbols_pa_Guru_IN', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_pl_PL', 'goog.i18n.NumberFormatSymbols_pt', 'goog.i18n.NumberFormatSymbols_pt_BR', 'goog.i18n.NumberFormatSymbols_pt_PT', 'goog.i18n.NumberFormatSymbols_ro', 'goog.i18n.NumberFormatSymbols_ro_RO', 'goog.i18n.NumberFormatSymbols_ru', 'goog.i18n.NumberFormatSymbols_ru_RU', 'goog.i18n.NumberFormatSymbols_si', 'goog.i18n.NumberFormatSymbols_si_LK', 'goog.i18n.NumberFormatSymbols_sk', 'goog.i18n.NumberFormatSymbols_sk_SK', 'goog.i18n.NumberFormatSymbols_sl', 'goog.i18n.NumberFormatSymbols_sl_SI', 'goog.i18n.NumberFormatSymbols_sq', 'goog.i18n.NumberFormatSymbols_sq_AL', 'goog.i18n.NumberFormatSymbols_sr', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.NumberFormatSymbols_sv', 'goog.i18n.NumberFormatSymbols_sv_SE', 'goog.i18n.NumberFormatSymbols_sw', 'goog.i18n.NumberFormatSymbols_sw_TZ', 'goog.i18n.NumberFormatSymbols_ta', 'goog.i18n.NumberFormatSymbols_ta_IN', 'goog.i18n.NumberFormatSymbols_te', 'goog.i18n.NumberFormatSymbols_te_IN', 'goog.i18n.NumberFormatSymbols_th', 'goog.i18n.NumberFormatSymbols_th_TH', 'goog.i18n.NumberFormatSymbols_tl', 'goog.i18n.NumberFormatSymbols_tr', 'goog.i18n.NumberFormatSymbols_tr_TR', 'goog.i18n.NumberFormatSymbols_uk', 'goog.i18n.NumberFormatSymbols_uk_UA', 'goog.i18n.NumberFormatSymbols_ur', 'goog.i18n.NumberFormatSymbols_ur_PK', 'goog.i18n.NumberFormatSymbols_uz', 'goog.i18n.NumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.NumberFormatSymbols_vi', 'goog.i18n.NumberFormatSymbols_vi_VN', 'goog.i18n.NumberFormatSymbols_zh', 'goog.i18n.NumberFormatSymbols_zh_CN', 'goog.i18n.NumberFormatSymbols_zh_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans_CN', 'goog.i18n.NumberFormatSymbols_zh_TW', 'goog.i18n.NumberFormatSymbols_zu', 'goog.i18n.NumberFormatSymbols_zu_ZA'], [], false);
+goog.addDependency('i18n/numberformatsymbolsext.js', ['goog.i18n.NumberFormatSymbolsExt', 'goog.i18n.NumberFormatSymbols_aa', 'goog.i18n.NumberFormatSymbols_aa_DJ', 'goog.i18n.NumberFormatSymbols_aa_ER', 'goog.i18n.NumberFormatSymbols_aa_ET', 'goog.i18n.NumberFormatSymbols_af_NA', 'goog.i18n.NumberFormatSymbols_agq', 'goog.i18n.NumberFormatSymbols_agq_CM', 'goog.i18n.NumberFormatSymbols_ak', 'goog.i18n.NumberFormatSymbols_ak_GH', 'goog.i18n.NumberFormatSymbols_ar_AE', 'goog.i18n.NumberFormatSymbols_ar_BH', 'goog.i18n.NumberFormatSymbols_ar_DJ', 'goog.i18n.NumberFormatSymbols_ar_DZ', 'goog.i18n.NumberFormatSymbols_ar_EG', 'goog.i18n.NumberFormatSymbols_ar_EH', 'goog.i18n.NumberFormatSymbols_ar_ER', 'goog.i18n.NumberFormatSymbols_ar_IL', 'goog.i18n.NumberFormatSymbols_ar_IQ', 'goog.i18n.NumberFormatSymbols_ar_JO', 'goog.i18n.NumberFormatSymbols_ar_KM', 'goog.i18n.NumberFormatSymbols_ar_KW', 'goog.i18n.NumberFormatSymbols_ar_LB', 'goog.i18n.NumberFormatSymbols_ar_LY', 'goog.i18n.NumberFormatSymbols_ar_MA', 'goog.i18n.NumberFormatSymbols_ar_MR', 'goog.i18n.NumberFormatSymbols_ar_OM', 'goog.i18n.NumberFormatSymbols_ar_PS', 'goog.i18n.NumberFormatSymbols_ar_QA', 'goog.i18n.NumberFormatSymbols_ar_SA', 'goog.i18n.NumberFormatSymbols_ar_SD', 'goog.i18n.NumberFormatSymbols_ar_SO', 'goog.i18n.NumberFormatSymbols_ar_SS', 'goog.i18n.NumberFormatSymbols_ar_SY', 'goog.i18n.NumberFormatSymbols_ar_TD', 'goog.i18n.NumberFormatSymbols_ar_TN', 'goog.i18n.NumberFormatSymbols_ar_YE', 'goog.i18n.NumberFormatSymbols_as', 'goog.i18n.NumberFormatSymbols_as_IN', 'goog.i18n.NumberFormatSymbols_asa', 'goog.i18n.NumberFormatSymbols_asa_TZ', 'goog.i18n.NumberFormatSymbols_ast', 'goog.i18n.NumberFormatSymbols_ast_ES', 'goog.i18n.NumberFormatSymbols_az_Cyrl', 'goog.i18n.NumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.NumberFormatSymbols_az_Latn', 'goog.i18n.NumberFormatSymbols_bas', 'goog.i18n.NumberFormatSymbols_bas_CM', 'goog.i18n.NumberFormatSymbols_be', 'goog.i18n.NumberFormatSymbols_be_BY', 'goog.i18n.NumberFormatSymbols_bem', 'goog.i18n.NumberFormatSymbols_bem_ZM', 'goog.i18n.NumberFormatSymbols_bez', 'goog.i18n.NumberFormatSymbols_bez_TZ', 'goog.i18n.NumberFormatSymbols_bm', 'goog.i18n.NumberFormatSymbols_bm_Latn', 'goog.i18n.NumberFormatSymbols_bm_Latn_ML', 'goog.i18n.NumberFormatSymbols_bn_IN', 'goog.i18n.NumberFormatSymbols_bo', 'goog.i18n.NumberFormatSymbols_bo_CN', 'goog.i18n.NumberFormatSymbols_bo_IN', 'goog.i18n.NumberFormatSymbols_brx', 'goog.i18n.NumberFormatSymbols_brx_IN', 'goog.i18n.NumberFormatSymbols_bs', 'goog.i18n.NumberFormatSymbols_bs_Cyrl', 'goog.i18n.NumberFormatSymbols_bs_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_bs_Latn', 'goog.i18n.NumberFormatSymbols_bs_Latn_BA', 'goog.i18n.NumberFormatSymbols_cgg', 'goog.i18n.NumberFormatSymbols_cgg_UG', 'goog.i18n.NumberFormatSymbols_ckb', 'goog.i18n.NumberFormatSymbols_ckb_Arab', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.NumberFormatSymbols_ckb_IQ', 'goog.i18n.NumberFormatSymbols_ckb_IR', 'goog.i18n.NumberFormatSymbols_ckb_Latn', 'goog.i18n.NumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.NumberFormatSymbols_dav', 'goog.i18n.NumberFormatSymbols_dav_KE', 'goog.i18n.NumberFormatSymbols_de_LI', 'goog.i18n.NumberFormatSymbols_dje', 'goog.i18n.NumberFormatSymbols_dje_NE', 'goog.i18n.NumberFormatSymbols_dsb', 'goog.i18n.NumberFormatSymbols_dsb_DE', 'goog.i18n.NumberFormatSymbols_dua', 'goog.i18n.NumberFormatSymbols_dua_CM', 'goog.i18n.NumberFormatSymbols_dyo', 'goog.i18n.NumberFormatSymbols_dyo_SN', 'goog.i18n.NumberFormatSymbols_dz', 'goog.i18n.NumberFormatSymbols_dz_BT', 'goog.i18n.NumberFormatSymbols_ebu', 'goog.i18n.NumberFormatSymbols_ebu_KE', 'goog.i18n.NumberFormatSymbols_ee', 'goog.i18n.NumberFormatSymbols_ee_GH', 'goog.i18n.NumberFormatSymbols_ee_TG', 'goog.i18n.NumberFormatSymbols_el_CY', 'goog.i18n.NumberFormatSymbols_en_150', 'goog.i18n.NumberFormatSymbols_en_AG', 'goog.i18n.NumberFormatSymbols_en_AI', 'goog.i18n.NumberFormatSymbols_en_BB', 'goog.i18n.NumberFormatSymbols_en_BE', 'goog.i18n.NumberFormatSymbols_en_BM', 'goog.i18n.NumberFormatSymbols_en_BS', 'goog.i18n.NumberFormatSymbols_en_BW', 'goog.i18n.NumberFormatSymbols_en_BZ', 'goog.i18n.NumberFormatSymbols_en_CA', 'goog.i18n.NumberFormatSymbols_en_CC', 'goog.i18n.NumberFormatSymbols_en_CK', 'goog.i18n.NumberFormatSymbols_en_CM', 'goog.i18n.NumberFormatSymbols_en_CX', 'goog.i18n.NumberFormatSymbols_en_DM', 'goog.i18n.NumberFormatSymbols_en_ER', 'goog.i18n.NumberFormatSymbols_en_FJ', 'goog.i18n.NumberFormatSymbols_en_FK', 'goog.i18n.NumberFormatSymbols_en_GD', 'goog.i18n.NumberFormatSymbols_en_GG', 'goog.i18n.NumberFormatSymbols_en_GH', 'goog.i18n.NumberFormatSymbols_en_GI', 'goog.i18n.NumberFormatSymbols_en_GM', 'goog.i18n.NumberFormatSymbols_en_GY', 'goog.i18n.NumberFormatSymbols_en_HK', 'goog.i18n.NumberFormatSymbols_en_IM', 'goog.i18n.NumberFormatSymbols_en_JE', 'goog.i18n.NumberFormatSymbols_en_JM', 'goog.i18n.NumberFormatSymbols_en_KE', 'goog.i18n.NumberFormatSymbols_en_KI', 'goog.i18n.NumberFormatSymbols_en_KN', 'goog.i18n.NumberFormatSymbols_en_KY', 'goog.i18n.NumberFormatSymbols_en_LC', 'goog.i18n.NumberFormatSymbols_en_LR', 'goog.i18n.NumberFormatSymbols_en_LS', 'goog.i18n.NumberFormatSymbols_en_MG', 'goog.i18n.NumberFormatSymbols_en_MO', 'goog.i18n.NumberFormatSymbols_en_MS', 'goog.i18n.NumberFormatSymbols_en_MT', 'goog.i18n.NumberFormatSymbols_en_MU', 'goog.i18n.NumberFormatSymbols_en_MW', 'goog.i18n.NumberFormatSymbols_en_MY', 'goog.i18n.NumberFormatSymbols_en_NA', 'goog.i18n.NumberFormatSymbols_en_NF', 'goog.i18n.NumberFormatSymbols_en_NG', 'goog.i18n.NumberFormatSymbols_en_NR', 'goog.i18n.NumberFormatSymbols_en_NU', 'goog.i18n.NumberFormatSymbols_en_NZ', 'goog.i18n.NumberFormatSymbols_en_PG', 'goog.i18n.NumberFormatSymbols_en_PH', 'goog.i18n.NumberFormatSymbols_en_PK', 'goog.i18n.NumberFormatSymbols_en_PN', 'goog.i18n.NumberFormatSymbols_en_RW', 'goog.i18n.NumberFormatSymbols_en_SB', 'goog.i18n.NumberFormatSymbols_en_SC', 'goog.i18n.NumberFormatSymbols_en_SD', 'goog.i18n.NumberFormatSymbols_en_SH', 'goog.i18n.NumberFormatSymbols_en_SL', 'goog.i18n.NumberFormatSymbols_en_SS', 'goog.i18n.NumberFormatSymbols_en_SX', 'goog.i18n.NumberFormatSymbols_en_SZ', 'goog.i18n.NumberFormatSymbols_en_TK', 'goog.i18n.NumberFormatSymbols_en_TO', 'goog.i18n.NumberFormatSymbols_en_TT', 'goog.i18n.NumberFormatSymbols_en_TV', 'goog.i18n.NumberFormatSymbols_en_TZ', 'goog.i18n.NumberFormatSymbols_en_UG', 'goog.i18n.NumberFormatSymbols_en_VC', 'goog.i18n.NumberFormatSymbols_en_VU', 'goog.i18n.NumberFormatSymbols_en_WS', 'goog.i18n.NumberFormatSymbols_en_ZM', 'goog.i18n.NumberFormatSymbols_eo', 'goog.i18n.NumberFormatSymbols_eo_001', 'goog.i18n.NumberFormatSymbols_es_AR', 'goog.i18n.NumberFormatSymbols_es_BO', 'goog.i18n.NumberFormatSymbols_es_CL', 'goog.i18n.NumberFormatSymbols_es_CO', 'goog.i18n.NumberFormatSymbols_es_CR', 'goog.i18n.NumberFormatSymbols_es_CU', 'goog.i18n.NumberFormatSymbols_es_DO', 'goog.i18n.NumberFormatSymbols_es_EC', 'goog.i18n.NumberFormatSymbols_es_GQ', 'goog.i18n.NumberFormatSymbols_es_GT', 'goog.i18n.NumberFormatSymbols_es_HN', 'goog.i18n.NumberFormatSymbols_es_MX', 'goog.i18n.NumberFormatSymbols_es_NI', 'goog.i18n.NumberFormatSymbols_es_PA', 'goog.i18n.NumberFormatSymbols_es_PE', 'goog.i18n.NumberFormatSymbols_es_PH', 'goog.i18n.NumberFormatSymbols_es_PR', 'goog.i18n.NumberFormatSymbols_es_PY', 'goog.i18n.NumberFormatSymbols_es_SV', 'goog.i18n.NumberFormatSymbols_es_US', 'goog.i18n.NumberFormatSymbols_es_UY', 'goog.i18n.NumberFormatSymbols_es_VE', 'goog.i18n.NumberFormatSymbols_ewo', 'goog.i18n.NumberFormatSymbols_ewo_CM', 'goog.i18n.NumberFormatSymbols_fa_AF', 'goog.i18n.NumberFormatSymbols_ff', 'goog.i18n.NumberFormatSymbols_ff_CM', 'goog.i18n.NumberFormatSymbols_ff_GN', 'goog.i18n.NumberFormatSymbols_ff_MR', 'goog.i18n.NumberFormatSymbols_ff_SN', 'goog.i18n.NumberFormatSymbols_fo', 'goog.i18n.NumberFormatSymbols_fo_FO', 'goog.i18n.NumberFormatSymbols_fr_BE', 'goog.i18n.NumberFormatSymbols_fr_BF', 'goog.i18n.NumberFormatSymbols_fr_BI', 'goog.i18n.NumberFormatSymbols_fr_BJ', 'goog.i18n.NumberFormatSymbols_fr_CD', 'goog.i18n.NumberFormatSymbols_fr_CF', 'goog.i18n.NumberFormatSymbols_fr_CG', 'goog.i18n.NumberFormatSymbols_fr_CH', 'goog.i18n.NumberFormatSymbols_fr_CI', 'goog.i18n.NumberFormatSymbols_fr_CM', 'goog.i18n.NumberFormatSymbols_fr_DJ', 'goog.i18n.NumberFormatSymbols_fr_DZ', 'goog.i18n.NumberFormatSymbols_fr_GA', 'goog.i18n.NumberFormatSymbols_fr_GN', 'goog.i18n.NumberFormatSymbols_fr_GQ', 'goog.i18n.NumberFormatSymbols_fr_HT', 'goog.i18n.NumberFormatSymbols_fr_KM', 'goog.i18n.NumberFormatSymbols_fr_LU', 'goog.i18n.NumberFormatSymbols_fr_MA', 'goog.i18n.NumberFormatSymbols_fr_MG', 'goog.i18n.NumberFormatSymbols_fr_ML', 'goog.i18n.NumberFormatSymbols_fr_MR', 'goog.i18n.NumberFormatSymbols_fr_MU', 'goog.i18n.NumberFormatSymbols_fr_NC', 'goog.i18n.NumberFormatSymbols_fr_NE', 'goog.i18n.NumberFormatSymbols_fr_PF', 'goog.i18n.NumberFormatSymbols_fr_RW', 'goog.i18n.NumberFormatSymbols_fr_SC', 'goog.i18n.NumberFormatSymbols_fr_SN', 'goog.i18n.NumberFormatSymbols_fr_SY', 'goog.i18n.NumberFormatSymbols_fr_TD', 'goog.i18n.NumberFormatSymbols_fr_TG', 'goog.i18n.NumberFormatSymbols_fr_TN', 'goog.i18n.NumberFormatSymbols_fr_VU', 'goog.i18n.NumberFormatSymbols_fr_WF', 'goog.i18n.NumberFormatSymbols_fur', 'goog.i18n.NumberFormatSymbols_fur_IT', 'goog.i18n.NumberFormatSymbols_fy', 'goog.i18n.NumberFormatSymbols_fy_NL', 'goog.i18n.NumberFormatSymbols_gd', 'goog.i18n.NumberFormatSymbols_gd_GB', 'goog.i18n.NumberFormatSymbols_gsw_FR', 'goog.i18n.NumberFormatSymbols_guz', 'goog.i18n.NumberFormatSymbols_guz_KE', 'goog.i18n.NumberFormatSymbols_gv', 'goog.i18n.NumberFormatSymbols_gv_IM', 'goog.i18n.NumberFormatSymbols_ha', 'goog.i18n.NumberFormatSymbols_ha_Latn', 'goog.i18n.NumberFormatSymbols_ha_Latn_GH', 'goog.i18n.NumberFormatSymbols_ha_Latn_NE', 'goog.i18n.NumberFormatSymbols_ha_Latn_NG', 'goog.i18n.NumberFormatSymbols_hr_BA', 'goog.i18n.NumberFormatSymbols_hsb', 'goog.i18n.NumberFormatSymbols_hsb_DE', 'goog.i18n.NumberFormatSymbols_ia', 'goog.i18n.NumberFormatSymbols_ia_FR', 'goog.i18n.NumberFormatSymbols_ig', 'goog.i18n.NumberFormatSymbols_ig_NG', 'goog.i18n.NumberFormatSymbols_ii', 'goog.i18n.NumberFormatSymbols_ii_CN', 'goog.i18n.NumberFormatSymbols_it_CH', 'goog.i18n.NumberFormatSymbols_jgo', 'goog.i18n.NumberFormatSymbols_jgo_CM', 'goog.i18n.NumberFormatSymbols_jmc', 'goog.i18n.NumberFormatSymbols_jmc_TZ', 'goog.i18n.NumberFormatSymbols_kab', 'goog.i18n.NumberFormatSymbols_kab_DZ', 'goog.i18n.NumberFormatSymbols_kam', 'goog.i18n.NumberFormatSymbols_kam_KE', 'goog.i18n.NumberFormatSymbols_kde', 'goog.i18n.NumberFormatSymbols_kde_TZ', 'goog.i18n.NumberFormatSymbols_kea', 'goog.i18n.NumberFormatSymbols_kea_CV', 'goog.i18n.NumberFormatSymbols_khq', 'goog.i18n.NumberFormatSymbols_khq_ML', 'goog.i18n.NumberFormatSymbols_ki', 'goog.i18n.NumberFormatSymbols_ki_KE', 'goog.i18n.NumberFormatSymbols_kk_Cyrl', 'goog.i18n.NumberFormatSymbols_kkj', 'goog.i18n.NumberFormatSymbols_kkj_CM', 'goog.i18n.NumberFormatSymbols_kl', 'goog.i18n.NumberFormatSymbols_kl_GL', 'goog.i18n.NumberFormatSymbols_kln', 'goog.i18n.NumberFormatSymbols_kln_KE', 'goog.i18n.NumberFormatSymbols_ko_KP', 'goog.i18n.NumberFormatSymbols_kok', 'goog.i18n.NumberFormatSymbols_kok_IN', 'goog.i18n.NumberFormatSymbols_ks', 'goog.i18n.NumberFormatSymbols_ks_Arab', 'goog.i18n.NumberFormatSymbols_ks_Arab_IN', 'goog.i18n.NumberFormatSymbols_ksb', 'goog.i18n.NumberFormatSymbols_ksb_TZ', 'goog.i18n.NumberFormatSymbols_ksf', 'goog.i18n.NumberFormatSymbols_ksf_CM', 'goog.i18n.NumberFormatSymbols_ksh', 'goog.i18n.NumberFormatSymbols_ksh_DE', 'goog.i18n.NumberFormatSymbols_kw', 'goog.i18n.NumberFormatSymbols_kw_GB', 'goog.i18n.NumberFormatSymbols_ky_Cyrl', 'goog.i18n.NumberFormatSymbols_lag', 'goog.i18n.NumberFormatSymbols_lag_TZ', 'goog.i18n.NumberFormatSymbols_lb', 'goog.i18n.NumberFormatSymbols_lb_LU', 'goog.i18n.NumberFormatSymbols_lg', 'goog.i18n.NumberFormatSymbols_lg_UG', 'goog.i18n.NumberFormatSymbols_lkt', 'goog.i18n.NumberFormatSymbols_lkt_US', 'goog.i18n.NumberFormatSymbols_ln_AO', 'goog.i18n.NumberFormatSymbols_ln_CF', 'goog.i18n.NumberFormatSymbols_ln_CG', 'goog.i18n.NumberFormatSymbols_lu', 'goog.i18n.NumberFormatSymbols_lu_CD', 'goog.i18n.NumberFormatSymbols_luo', 'goog.i18n.NumberFormatSymbols_luo_KE', 'goog.i18n.NumberFormatSymbols_luy', 'goog.i18n.NumberFormatSymbols_luy_KE', 'goog.i18n.NumberFormatSymbols_mas', 'goog.i18n.NumberFormatSymbols_mas_KE', 'goog.i18n.NumberFormatSymbols_mas_TZ', 'goog.i18n.NumberFormatSymbols_mer', 'goog.i18n.NumberFormatSymbols_mer_KE', 'goog.i18n.NumberFormatSymbols_mfe', 'goog.i18n.NumberFormatSymbols_mfe_MU', 'goog.i18n.NumberFormatSymbols_mg', 'goog.i18n.NumberFormatSymbols_mg_MG', 'goog.i18n.NumberFormatSymbols_mgh', 'goog.i18n.NumberFormatSymbols_mgh_MZ', 'goog.i18n.NumberFormatSymbols_mgo', 'goog.i18n.NumberFormatSymbols_mgo_CM', 'goog.i18n.NumberFormatSymbols_mn_Cyrl', 'goog.i18n.NumberFormatSymbols_ms_Latn', 'goog.i18n.NumberFormatSymbols_ms_Latn_BN', 'goog.i18n.NumberFormatSymbols_ms_Latn_SG', 'goog.i18n.NumberFormatSymbols_mua', 'goog.i18n.NumberFormatSymbols_mua_CM', 'goog.i18n.NumberFormatSymbols_naq', 'goog.i18n.NumberFormatSymbols_naq_NA', 'goog.i18n.NumberFormatSymbols_nd', 'goog.i18n.NumberFormatSymbols_nd_ZW', 'goog.i18n.NumberFormatSymbols_ne_IN', 'goog.i18n.NumberFormatSymbols_nl_AW', 'goog.i18n.NumberFormatSymbols_nl_BE', 'goog.i18n.NumberFormatSymbols_nl_BQ', 'goog.i18n.NumberFormatSymbols_nl_CW', 'goog.i18n.NumberFormatSymbols_nl_SR', 'goog.i18n.NumberFormatSymbols_nl_SX', 'goog.i18n.NumberFormatSymbols_nmg', 'goog.i18n.NumberFormatSymbols_nmg_CM', 'goog.i18n.NumberFormatSymbols_nn', 'goog.i18n.NumberFormatSymbols_nn_NO', 'goog.i18n.NumberFormatSymbols_nnh', 'goog.i18n.NumberFormatSymbols_nnh_CM', 'goog.i18n.NumberFormatSymbols_nr', 'goog.i18n.NumberFormatSymbols_nr_ZA', 'goog.i18n.NumberFormatSymbols_nso', 'goog.i18n.NumberFormatSymbols_nso_ZA', 'goog.i18n.NumberFormatSymbols_nus', 'goog.i18n.NumberFormatSymbols_nus_SD', 'goog.i18n.NumberFormatSymbols_nyn', 'goog.i18n.NumberFormatSymbols_nyn_UG', 'goog.i18n.NumberFormatSymbols_om', 'goog.i18n.NumberFormatSymbols_om_ET', 'goog.i18n.NumberFormatSymbols_om_KE', 'goog.i18n.NumberFormatSymbols_os', 'goog.i18n.NumberFormatSymbols_os_GE', 'goog.i18n.NumberFormatSymbols_os_RU', 'goog.i18n.NumberFormatSymbols_pa_Arab', 'goog.i18n.NumberFormatSymbols_pa_Arab_PK', 'goog.i18n.NumberFormatSymbols_pa_Guru', 'goog.i18n.NumberFormatSymbols_ps', 'goog.i18n.NumberFormatSymbols_ps_AF', 'goog.i18n.NumberFormatSymbols_pt_AO', 'goog.i18n.NumberFormatSymbols_pt_CV', 'goog.i18n.NumberFormatSymbols_pt_GW', 'goog.i18n.NumberFormatSymbols_pt_MO', 'goog.i18n.NumberFormatSymbols_pt_MZ', 'goog.i18n.NumberFormatSymbols_pt_ST', 'goog.i18n.NumberFormatSymbols_pt_TL', 'goog.i18n.NumberFormatSymbols_qu', 'goog.i18n.NumberFormatSymbols_qu_BO', 'goog.i18n.NumberFormatSymbols_qu_EC', 'goog.i18n.NumberFormatSymbols_qu_PE', 'goog.i18n.NumberFormatSymbols_rm', 'goog.i18n.NumberFormatSymbols_rm_CH', 'goog.i18n.NumberFormatSymbols_rn', 'goog.i18n.NumberFormatSymbols_rn_BI', 'goog.i18n.NumberFormatSymbols_ro_MD', 'goog.i18n.NumberFormatSymbols_rof', 'goog.i18n.NumberFormatSymbols_rof_TZ', 'goog.i18n.NumberFormatSymbols_ru_BY', 'goog.i18n.NumberFormatSymbols_ru_KG', 'goog.i18n.NumberFormatSymbols_ru_KZ', 'goog.i18n.NumberFormatSymbols_ru_MD', 'goog.i18n.NumberFormatSymbols_ru_UA', 'goog.i18n.NumberFormatSymbols_rw', 'goog.i18n.NumberFormatSymbols_rw_RW', 'goog.i18n.NumberFormatSymbols_rwk', 'goog.i18n.NumberFormatSymbols_rwk_TZ', 'goog.i18n.NumberFormatSymbols_sah', 'goog.i18n.NumberFormatSymbols_sah_RU', 'goog.i18n.NumberFormatSymbols_saq', 'goog.i18n.NumberFormatSymbols_saq_KE', 'goog.i18n.NumberFormatSymbols_sbp', 'goog.i18n.NumberFormatSymbols_sbp_TZ', 'goog.i18n.NumberFormatSymbols_se', 'goog.i18n.NumberFormatSymbols_se_FI', 'goog.i18n.NumberFormatSymbols_se_NO', 'goog.i18n.NumberFormatSymbols_se_SE', 'goog.i18n.NumberFormatSymbols_seh', 'goog.i18n.NumberFormatSymbols_seh_MZ', 'goog.i18n.NumberFormatSymbols_ses', 'goog.i18n.NumberFormatSymbols_ses_ML', 'goog.i18n.NumberFormatSymbols_sg', 'goog.i18n.NumberFormatSymbols_sg_CF', 'goog.i18n.NumberFormatSymbols_shi', 'goog.i18n.NumberFormatSymbols_shi_Latn', 'goog.i18n.NumberFormatSymbols_shi_Latn_MA', 'goog.i18n.NumberFormatSymbols_shi_Tfng', 'goog.i18n.NumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.NumberFormatSymbols_smn', 'goog.i18n.NumberFormatSymbols_smn_FI', 'goog.i18n.NumberFormatSymbols_sn', 'goog.i18n.NumberFormatSymbols_sn_ZW', 'goog.i18n.NumberFormatSymbols_so', 'goog.i18n.NumberFormatSymbols_so_DJ', 'goog.i18n.NumberFormatSymbols_so_ET', 'goog.i18n.NumberFormatSymbols_so_KE', 'goog.i18n.NumberFormatSymbols_so_SO', 'goog.i18n.NumberFormatSymbols_sq_MK', 'goog.i18n.NumberFormatSymbols_sq_XK', 'goog.i18n.NumberFormatSymbols_sr_Cyrl', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_XK', 'goog.i18n.NumberFormatSymbols_sr_Latn', 'goog.i18n.NumberFormatSymbols_sr_Latn_BA', 'goog.i18n.NumberFormatSymbols_sr_Latn_ME', 'goog.i18n.NumberFormatSymbols_sr_Latn_RS', 'goog.i18n.NumberFormatSymbols_sr_Latn_XK', 'goog.i18n.NumberFormatSymbols_ss', 'goog.i18n.NumberFormatSymbols_ss_SZ', 'goog.i18n.NumberFormatSymbols_ss_ZA', 'goog.i18n.NumberFormatSymbols_ssy', 'goog.i18n.NumberFormatSymbols_ssy_ER', 'goog.i18n.NumberFormatSymbols_sv_AX', 'goog.i18n.NumberFormatSymbols_sv_FI', 'goog.i18n.NumberFormatSymbols_sw_KE', 'goog.i18n.NumberFormatSymbols_sw_UG', 'goog.i18n.NumberFormatSymbols_swc', 'goog.i18n.NumberFormatSymbols_swc_CD', 'goog.i18n.NumberFormatSymbols_ta_LK', 'goog.i18n.NumberFormatSymbols_ta_MY', 'goog.i18n.NumberFormatSymbols_ta_SG', 'goog.i18n.NumberFormatSymbols_teo', 'goog.i18n.NumberFormatSymbols_teo_KE', 'goog.i18n.NumberFormatSymbols_teo_UG', 'goog.i18n.NumberFormatSymbols_ti', 'goog.i18n.NumberFormatSymbols_ti_ER', 'goog.i18n.NumberFormatSymbols_ti_ET', 'goog.i18n.NumberFormatSymbols_tn', 'goog.i18n.NumberFormatSymbols_tn_BW', 'goog.i18n.NumberFormatSymbols_tn_ZA', 'goog.i18n.NumberFormatSymbols_to', 'goog.i18n.NumberFormatSymbols_to_TO', 'goog.i18n.NumberFormatSymbols_tr_CY', 'goog.i18n.NumberFormatSymbols_ts', 'goog.i18n.NumberFormatSymbols_ts_ZA', 'goog.i18n.NumberFormatSymbols_twq', 'goog.i18n.NumberFormatSymbols_twq_NE', 'goog.i18n.NumberFormatSymbols_tzm', 'goog.i18n.NumberFormatSymbols_tzm_Latn', 'goog.i18n.NumberFormatSymbols_tzm_Latn_MA', 'goog.i18n.NumberFormatSymbols_ug', 'goog.i18n.NumberFormatSymbols_ug_Arab', 'goog.i18n.NumberFormatSymbols_ug_Arab_CN', 'goog.i18n.NumberFormatSymbols_ur_IN', 'goog.i18n.NumberFormatSymbols_uz_Arab', 'goog.i18n.NumberFormatSymbols_uz_Arab_AF', 'goog.i18n.NumberFormatSymbols_uz_Cyrl', 'goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.NumberFormatSymbols_uz_Latn', 'goog.i18n.NumberFormatSymbols_vai', 'goog.i18n.NumberFormatSymbols_vai_Latn', 'goog.i18n.NumberFormatSymbols_vai_Latn_LR', 'goog.i18n.NumberFormatSymbols_vai_Vaii', 'goog.i18n.NumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.NumberFormatSymbols_ve', 'goog.i18n.NumberFormatSymbols_ve_ZA', 'goog.i18n.NumberFormatSymbols_vo', 'goog.i18n.NumberFormatSymbols_vo_001', 'goog.i18n.NumberFormatSymbols_vun', 'goog.i18n.NumberFormatSymbols_vun_TZ', 'goog.i18n.NumberFormatSymbols_wae', 'goog.i18n.NumberFormatSymbols_wae_CH', 'goog.i18n.NumberFormatSymbols_xog', 'goog.i18n.NumberFormatSymbols_xog_UG', 'goog.i18n.NumberFormatSymbols_yav', 'goog.i18n.NumberFormatSymbols_yav_CM', 'goog.i18n.NumberFormatSymbols_yi', 'goog.i18n.NumberFormatSymbols_yi_001', 'goog.i18n.NumberFormatSymbols_yo', 'goog.i18n.NumberFormatSymbols_yo_BJ', 'goog.i18n.NumberFormatSymbols_yo_NG', 'goog.i18n.NumberFormatSymbols_zgh', 'goog.i18n.NumberFormatSymbols_zgh_MA', 'goog.i18n.NumberFormatSymbols_zh_Hans', 'goog.i18n.NumberFormatSymbols_zh_Hans_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans_MO', 'goog.i18n.NumberFormatSymbols_zh_Hans_SG', 'goog.i18n.NumberFormatSymbols_zh_Hant', 'goog.i18n.NumberFormatSymbols_zh_Hant_HK', 'goog.i18n.NumberFormatSymbols_zh_Hant_MO', 'goog.i18n.NumberFormatSymbols_zh_Hant_TW'], ['goog.i18n.NumberFormatSymbols'], false);
+goog.addDependency('i18n/ordinalrules.js', ['goog.i18n.ordinalRules'], [], false);
+goog.addDependency('i18n/pluralrules.js', ['goog.i18n.pluralRules'], [], false);
+goog.addDependency('i18n/pluralrules_test.js', ['goog.i18n.pluralRulesTest'], ['goog.i18n.pluralRules', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/timezone.js', ['goog.i18n.TimeZone'], ['goog.array', 'goog.date.DateLike', 'goog.string'], false);
+goog.addDependency('i18n/timezone_test.js', ['goog.i18n.TimeZoneTest'], ['goog.i18n.TimeZone', 'goog.testing.jsunit'], false);
+goog.addDependency('i18n/uchar.js', ['goog.i18n.uChar'], [], false);
+goog.addDependency('i18n/uchar/localnamefetcher.js', ['goog.i18n.uChar.LocalNameFetcher'], ['goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.log'], false);
+goog.addDependency('i18n/uchar/localnamefetcher_test.js', ['goog.i18n.uChar.LocalNameFetcherTest'], ['goog.i18n.uChar.LocalNameFetcher', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('i18n/uchar/namefetcher.js', ['goog.i18n.uChar.NameFetcher'], [], false);
+goog.addDependency('i18n/uchar/remotenamefetcher.js', ['goog.i18n.uChar.RemoteNameFetcher'], ['goog.Disposable', 'goog.Uri', 'goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.log', 'goog.net.XhrIo', 'goog.structs.Map'], false);
+goog.addDependency('i18n/uchar/remotenamefetcher_test.js', ['goog.i18n.uChar.RemoteNameFetcherTest'], ['goog.i18n.uChar.RemoteNameFetcher', 'goog.net.XhrIo', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false);
+goog.addDependency('i18n/uchar_test.js', ['goog.i18n.uCharTest'], ['goog.i18n.uChar', 'goog.testing.jsunit'], false);
+goog.addDependency('iter/iter.js', ['goog.iter', 'goog.iter.Iterable', 'goog.iter.Iterator', 'goog.iter.StopIteration'], ['goog.array', 'goog.asserts', 'goog.functions', 'goog.math'], false);
+goog.addDependency('iter/iter_test.js', ['goog.iterTest'], ['goog.iter', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.testing.jsunit'], false);
+goog.addDependency('json/evaljsonprocessor.js', ['goog.json.EvalJsonProcessor'], ['goog.json', 'goog.json.Processor', 'goog.json.Serializer'], false);
+goog.addDependency('json/hybrid.js', ['goog.json.hybrid'], ['goog.asserts', 'goog.json'], false);
+goog.addDependency('json/hybrid_test.js', ['goog.json.hybridTest'], ['goog.json', 'goog.json.hybrid', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('json/hybridjsonprocessor.js', ['goog.json.HybridJsonProcessor'], ['goog.json.Processor', 'goog.json.hybrid'], false);
+goog.addDependency('json/hybridjsonprocessor_test.js', ['goog.json.HybridJsonProcessorTest'], ['goog.json.HybridJsonProcessor', 'goog.json.hybrid', 'goog.testing.jsunit'], false);
+goog.addDependency('json/json.js', ['goog.json', 'goog.json.Replacer', 'goog.json.Reviver', 'goog.json.Serializer'], [], false);
+goog.addDependency('json/json_perf.js', ['goog.jsonPerf'], ['goog.dom', 'goog.json', 'goog.math', 'goog.string', 'goog.testing.PerformanceTable', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('json/json_test.js', ['goog.jsonTest'], ['goog.functions', 'goog.json', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('json/nativejsonprocessor.js', ['goog.json.NativeJsonProcessor'], ['goog.asserts', 'goog.json.Processor'], false);
+goog.addDependency('json/processor.js', ['goog.json.Processor'], ['goog.string.Parser', 'goog.string.Stringifier'], false);
+goog.addDependency('json/processor_test.js', ['goog.json.processorTest'], ['goog.json.EvalJsonProcessor', 'goog.json.NativeJsonProcessor', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('labs/dom/pagevisibilitymonitor.js', ['goog.labs.dom.PageVisibilityEvent', 'goog.labs.dom.PageVisibilityMonitor', 'goog.labs.dom.PageVisibilityState'], ['goog.dom', 'goog.dom.vendor', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.memoize'], false);
+goog.addDependency('labs/dom/pagevisibilitymonitor_test.js', ['goog.labs.dom.PageVisibilityMonitorTest'], ['goog.events', 'goog.functions', 'goog.labs.dom.PageVisibilityMonitor', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('labs/events/nondisposableeventtarget.js', ['goog.labs.events.NonDisposableEventTarget'], ['goog.array', 'goog.asserts', 'goog.events.Event', 'goog.events.Listenable', 'goog.events.ListenerMap', 'goog.object'], false);
+goog.addDependency('labs/events/nondisposableeventtarget_test.js', ['goog.labs.events.NonDisposableEventTargetTest'], ['goog.events.Listenable', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.labs.events.NonDisposableEventTarget', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/events/nondisposableeventtarget_via_googevents_test.js', ['goog.labs.events.NonDisposableEventTargetGoogEventsTest'], ['goog.events', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.labs.events.NonDisposableEventTarget', 'goog.testing', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/events/touch.js', ['goog.labs.events.touch', 'goog.labs.events.touch.TouchData'], ['goog.array', 'goog.asserts', 'goog.events.EventType', 'goog.string'], false);
+goog.addDependency('labs/events/touch_test.js', ['goog.labs.events.touchTest'], ['goog.labs.events.touch', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/format/csv.js', ['goog.labs.format.csv', 'goog.labs.format.csv.ParseError', 'goog.labs.format.csv.Token'], ['goog.array', 'goog.asserts', 'goog.debug.Error', 'goog.object', 'goog.string', 'goog.string.newlines'], false);
+goog.addDependency('labs/format/csv_test.js', ['goog.labs.format.csvTest'], ['goog.labs.format.csv', 'goog.labs.format.csv.ParseError', 'goog.object', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/html/attribute_rewriter.js', ['goog.labs.html.AttributeRewriter', 'goog.labs.html.AttributeValue', 'goog.labs.html.attributeRewriterPresubmitWorkaround'], [], false);
+goog.addDependency('labs/html/sanitizer.js', ['goog.labs.html.Sanitizer'], ['goog.asserts', 'goog.html.SafeUrl', 'goog.labs.html.attributeRewriterPresubmitWorkaround', 'goog.labs.html.scrubber', 'goog.object', 'goog.string'], false);
+goog.addDependency('labs/html/sanitizer_test.js', ['goog.labs.html.SanitizerTest'], ['goog.html.SafeUrl', 'goog.labs.html.Sanitizer', 'goog.string', 'goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/html/scrubber.js', ['goog.labs.html.scrubber'], ['goog.array', 'goog.dom.tags', 'goog.labs.html.attributeRewriterPresubmitWorkaround', 'goog.string'], false);
+goog.addDependency('labs/html/scrubber_test.js', ['goog.html.ScrubberTest'], ['goog.labs.html.scrubber', 'goog.object', 'goog.string', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/i18n/listformat.js', ['goog.labs.i18n.GenderInfo', 'goog.labs.i18n.GenderInfo.Gender', 'goog.labs.i18n.ListFormat'], ['goog.asserts', 'goog.labs.i18n.ListFormatSymbols'], false);
+goog.addDependency('labs/i18n/listformat_test.js', ['goog.labs.i18n.ListFormatTest'], ['goog.labs.i18n.GenderInfo', 'goog.labs.i18n.ListFormat', 'goog.labs.i18n.ListFormatSymbols', 'goog.labs.i18n.ListFormatSymbols_el', 'goog.labs.i18n.ListFormatSymbols_en', 'goog.labs.i18n.ListFormatSymbols_fr', 'goog.labs.i18n.ListFormatSymbols_ml', 'goog.labs.i18n.ListFormatSymbols_zu', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/i18n/listsymbols.js', ['goog.labs.i18n.ListFormatSymbols', 'goog.labs.i18n.ListFormatSymbols_af', 'goog.labs.i18n.ListFormatSymbols_am', 'goog.labs.i18n.ListFormatSymbols_ar', 'goog.labs.i18n.ListFormatSymbols_az', 'goog.labs.i18n.ListFormatSymbols_bg', 'goog.labs.i18n.ListFormatSymbols_bn', 'goog.labs.i18n.ListFormatSymbols_br', 'goog.labs.i18n.ListFormatSymbols_ca', 'goog.labs.i18n.ListFormatSymbols_chr', 'goog.labs.i18n.ListFormatSymbols_cs', 'goog.labs.i18n.ListFormatSymbols_cy', 'goog.labs.i18n.ListFormatSymbols_da', 'goog.labs.i18n.ListFormatSymbols_de', 'goog.labs.i18n.ListFormatSymbols_de_AT', 'goog.labs.i18n.ListFormatSymbols_de_CH', 'goog.labs.i18n.ListFormatSymbols_el', 'goog.labs.i18n.ListFormatSymbols_en', 'goog.labs.i18n.ListFormatSymbols_en_AU', 'goog.labs.i18n.ListFormatSymbols_en_GB', 'goog.labs.i18n.ListFormatSymbols_en_IE', 'goog.labs.i18n.ListFormatSymbols_en_IN', 'goog.labs.i18n.ListFormatSymbols_en_SG', 'goog.labs.i18n.ListFormatSymbols_en_US', 'goog.labs.i18n.ListFormatSymbols_en_ZA', 'goog.labs.i18n.ListFormatSymbols_es', 'goog.labs.i18n.ListFormatSymbols_es_419', 'goog.labs.i18n.ListFormatSymbols_es_ES', 'goog.labs.i18n.ListFormatSymbols_et', 'goog.labs.i18n.ListFormatSymbols_eu', 'goog.labs.i18n.ListFormatSymbols_fa', 'goog.labs.i18n.ListFormatSymbols_fi', 'goog.labs.i18n.ListFormatSymbols_fil', 'goog.labs.i18n.ListFormatSymbols_fr', 'goog.labs.i18n.ListFormatSymbols_fr_CA', 'goog.labs.i18n.ListFormatSymbols_ga', 'goog.labs.i18n.ListFormatSymbols_gl', 'goog.labs.i18n.ListFormatSymbols_gsw', 'goog.labs.i18n.ListFormatSymbols_gu', 'goog.labs.i18n.ListFormatSymbols_haw', 'goog.labs.i18n.ListFormatSymbols_he', 'goog.labs.i18n.ListFormatSymbols_hi', 'goog.labs.i18n.ListFormatSymbols_hr', 'goog.labs.i18n.ListFormatSymbols_hu', 'goog.labs.i18n.ListFormatSymbols_hy', 'goog.labs.i18n.ListFormatSymbols_id', 'goog.labs.i18n.ListFormatSymbols_in', 'goog.labs.i18n.ListFormatSymbols_is', 'goog.labs.i18n.ListFormatSymbols_it', 'goog.labs.i18n.ListFormatSymbols_iw', 'goog.labs.i18n.ListFormatSymbols_ja', 'goog.labs.i18n.ListFormatSymbols_ka', 'goog.labs.i18n.ListFormatSymbols_kk', 'goog.labs.i18n.ListFormatSymbols_km', 'goog.labs.i18n.ListFormatSymbols_kn', 'goog.labs.i18n.ListFormatSymbols_ko', 'goog.labs.i18n.ListFormatSymbols_ky', 'goog.labs.i18n.ListFormatSymbols_ln', 'goog.labs.i18n.ListFormatSymbols_lo', 'goog.labs.i18n.ListFormatSymbols_lt', 'goog.labs.i18n.ListFormatSymbols_lv', 'goog.labs.i18n.ListFormatSymbols_mk', 'goog.labs.i18n.ListFormatSymbols_ml', 'goog.labs.i18n.ListFormatSymbols_mn', 'goog.labs.i18n.ListFormatSymbols_mo', 'goog.labs.i18n.ListFormatSymbols_mr', 'goog.labs.i18n.ListFormatSymbols_ms', 'goog.labs.i18n.ListFormatSymbols_mt', 'goog.labs.i18n.ListFormatSymbols_my', 'goog.labs.i18n.ListFormatSymbols_nb', 'goog.labs.i18n.ListFormatSymbols_ne', 'goog.labs.i18n.ListFormatSymbols_nl', 'goog.labs.i18n.ListFormatSymbols_no', 'goog.labs.i18n.ListFormatSymbols_no_NO', 'goog.labs.i18n.ListFormatSymbols_or', 'goog.labs.i18n.ListFormatSymbols_pa', 'goog.labs.i18n.ListFormatSymbols_pl', 'goog.labs.i18n.ListFormatSymbols_pt', 'goog.labs.i18n.ListFormatSymbols_pt_BR', 'goog.labs.i18n.ListFormatSymbols_pt_PT', 'goog.labs.i18n.ListFormatSymbols_ro', 'goog.labs.i18n.ListFormatSymbols_ru', 'goog.labs.i18n.ListFormatSymbols_sh', 'goog.labs.i18n.ListFormatSymbols_si', 'goog.labs.i18n.ListFormatSymbols_sk', 'goog.labs.i18n.ListFormatSymbols_sl', 'goog.labs.i18n.ListFormatSymbols_sq', 'goog.labs.i18n.ListFormatSymbols_sr', 'goog.labs.i18n.ListFormatSymbols_sv', 'goog.labs.i18n.ListFormatSymbols_sw', 'goog.labs.i18n.ListFormatSymbols_ta', 'goog.labs.i18n.ListFormatSymbols_te', 'goog.labs.i18n.ListFormatSymbols_th', 'goog.labs.i18n.ListFormatSymbols_tl', 'goog.labs.i18n.ListFormatSymbols_tr', 'goog.labs.i18n.ListFormatSymbols_uk', 'goog.labs.i18n.ListFormatSymbols_ur', 'goog.labs.i18n.ListFormatSymbols_uz', 'goog.labs.i18n.ListFormatSymbols_vi', 'goog.labs.i18n.ListFormatSymbols_zh', 'goog.labs.i18n.ListFormatSymbols_zh_CN', 'goog.labs.i18n.ListFormatSymbols_zh_HK', 'goog.labs.i18n.ListFormatSymbols_zh_TW', 'goog.labs.i18n.ListFormatSymbols_zu'], [], false);
+goog.addDependency('labs/i18n/listsymbolsext.js', ['goog.labs.i18n.ListFormatSymbolsExt', 'goog.labs.i18n.ListFormatSymbols_af_NA', 'goog.labs.i18n.ListFormatSymbols_af_ZA', 'goog.labs.i18n.ListFormatSymbols_agq', 'goog.labs.i18n.ListFormatSymbols_agq_CM', 'goog.labs.i18n.ListFormatSymbols_ak', 'goog.labs.i18n.ListFormatSymbols_ak_GH', 'goog.labs.i18n.ListFormatSymbols_am_ET', 'goog.labs.i18n.ListFormatSymbols_ar_001', 'goog.labs.i18n.ListFormatSymbols_ar_AE', 'goog.labs.i18n.ListFormatSymbols_ar_BH', 'goog.labs.i18n.ListFormatSymbols_ar_DJ', 'goog.labs.i18n.ListFormatSymbols_ar_DZ', 'goog.labs.i18n.ListFormatSymbols_ar_EG', 'goog.labs.i18n.ListFormatSymbols_ar_EH', 'goog.labs.i18n.ListFormatSymbols_ar_ER', 'goog.labs.i18n.ListFormatSymbols_ar_IL', 'goog.labs.i18n.ListFormatSymbols_ar_IQ', 'goog.labs.i18n.ListFormatSymbols_ar_JO', 'goog.labs.i18n.ListFormatSymbols_ar_KM', 'goog.labs.i18n.ListFormatSymbols_ar_KW', 'goog.labs.i18n.ListFormatSymbols_ar_LB', 'goog.labs.i18n.ListFormatSymbols_ar_LY', 'goog.labs.i18n.ListFormatSymbols_ar_MA', 'goog.labs.i18n.ListFormatSymbols_ar_MR', 'goog.labs.i18n.ListFormatSymbols_ar_OM', 'goog.labs.i18n.ListFormatSymbols_ar_PS', 'goog.labs.i18n.ListFormatSymbols_ar_QA', 'goog.labs.i18n.ListFormatSymbols_ar_SA', 'goog.labs.i18n.ListFormatSymbols_ar_SD', 'goog.labs.i18n.ListFormatSymbols_ar_SO', 'goog.labs.i18n.ListFormatSymbols_ar_SS', 'goog.labs.i18n.ListFormatSymbols_ar_SY', 'goog.labs.i18n.ListFormatSymbols_ar_TD', 'goog.labs.i18n.ListFormatSymbols_ar_TN', 'goog.labs.i18n.ListFormatSymbols_ar_YE', 'goog.labs.i18n.ListFormatSymbols_as', 'goog.labs.i18n.ListFormatSymbols_as_IN', 'goog.labs.i18n.ListFormatSymbols_asa', 'goog.labs.i18n.ListFormatSymbols_asa_TZ', 'goog.labs.i18n.ListFormatSymbols_az_Cyrl', 'goog.labs.i18n.ListFormatSymbols_az_Cyrl_AZ', 'goog.labs.i18n.ListFormatSymbols_az_Latn', 'goog.labs.i18n.ListFormatSymbols_az_Latn_AZ', 'goog.labs.i18n.ListFormatSymbols_bas', 'goog.labs.i18n.ListFormatSymbols_bas_CM', 'goog.labs.i18n.ListFormatSymbols_be', 'goog.labs.i18n.ListFormatSymbols_be_BY', 'goog.labs.i18n.ListFormatSymbols_bem', 'goog.labs.i18n.ListFormatSymbols_bem_ZM', 'goog.labs.i18n.ListFormatSymbols_bez', 'goog.labs.i18n.ListFormatSymbols_bez_TZ', 'goog.labs.i18n.ListFormatSymbols_bg_BG', 'goog.labs.i18n.ListFormatSymbols_bm', 'goog.labs.i18n.ListFormatSymbols_bm_Latn', 'goog.labs.i18n.ListFormatSymbols_bm_Latn_ML', 'goog.labs.i18n.ListFormatSymbols_bn_BD', 'goog.labs.i18n.ListFormatSymbols_bn_IN', 'goog.labs.i18n.ListFormatSymbols_bo', 'goog.labs.i18n.ListFormatSymbols_bo_CN', 'goog.labs.i18n.ListFormatSymbols_bo_IN', 'goog.labs.i18n.ListFormatSymbols_br_FR', 'goog.labs.i18n.ListFormatSymbols_brx', 'goog.labs.i18n.ListFormatSymbols_brx_IN', 'goog.labs.i18n.ListFormatSymbols_bs', 'goog.labs.i18n.ListFormatSymbols_bs_Cyrl', 'goog.labs.i18n.ListFormatSymbols_bs_Cyrl_BA', 'goog.labs.i18n.ListFormatSymbols_bs_Latn', 'goog.labs.i18n.ListFormatSymbols_bs_Latn_BA', 'goog.labs.i18n.ListFormatSymbols_ca_AD', 'goog.labs.i18n.ListFormatSymbols_ca_ES', 'goog.labs.i18n.ListFormatSymbols_ca_FR', 'goog.labs.i18n.ListFormatSymbols_ca_IT', 'goog.labs.i18n.ListFormatSymbols_cgg', 'goog.labs.i18n.ListFormatSymbols_cgg_UG', 'goog.labs.i18n.ListFormatSymbols_chr_US', 'goog.labs.i18n.ListFormatSymbols_cs_CZ', 'goog.labs.i18n.ListFormatSymbols_cy_GB', 'goog.labs.i18n.ListFormatSymbols_da_DK', 'goog.labs.i18n.ListFormatSymbols_da_GL', 'goog.labs.i18n.ListFormatSymbols_dav', 'goog.labs.i18n.ListFormatSymbols_dav_KE', 'goog.labs.i18n.ListFormatSymbols_de_BE', 'goog.labs.i18n.ListFormatSymbols_de_DE', 'goog.labs.i18n.ListFormatSymbols_de_LI', 'goog.labs.i18n.ListFormatSymbols_de_LU', 'goog.labs.i18n.ListFormatSymbols_dje', 'goog.labs.i18n.ListFormatSymbols_dje_NE', 'goog.labs.i18n.ListFormatSymbols_dsb', 'goog.labs.i18n.ListFormatSymbols_dsb_DE', 'goog.labs.i18n.ListFormatSymbols_dua', 'goog.labs.i18n.ListFormatSymbols_dua_CM', 'goog.labs.i18n.ListFormatSymbols_dyo', 'goog.labs.i18n.ListFormatSymbols_dyo_SN', 'goog.labs.i18n.ListFormatSymbols_dz', 'goog.labs.i18n.ListFormatSymbols_dz_BT', 'goog.labs.i18n.ListFormatSymbols_ebu', 'goog.labs.i18n.ListFormatSymbols_ebu_KE', 'goog.labs.i18n.ListFormatSymbols_ee', 'goog.labs.i18n.ListFormatSymbols_ee_GH', 'goog.labs.i18n.ListFormatSymbols_ee_TG', 'goog.labs.i18n.ListFormatSymbols_el_CY', 'goog.labs.i18n.ListFormatSymbols_el_GR', 'goog.labs.i18n.ListFormatSymbols_en_001', 'goog.labs.i18n.ListFormatSymbols_en_150', 'goog.labs.i18n.ListFormatSymbols_en_AG', 'goog.labs.i18n.ListFormatSymbols_en_AI', 'goog.labs.i18n.ListFormatSymbols_en_AS', 'goog.labs.i18n.ListFormatSymbols_en_BB', 'goog.labs.i18n.ListFormatSymbols_en_BE', 'goog.labs.i18n.ListFormatSymbols_en_BM', 'goog.labs.i18n.ListFormatSymbols_en_BS', 'goog.labs.i18n.ListFormatSymbols_en_BW', 'goog.labs.i18n.ListFormatSymbols_en_BZ', 'goog.labs.i18n.ListFormatSymbols_en_CA', 'goog.labs.i18n.ListFormatSymbols_en_CC', 'goog.labs.i18n.ListFormatSymbols_en_CK', 'goog.labs.i18n.ListFormatSymbols_en_CM', 'goog.labs.i18n.ListFormatSymbols_en_CX', 'goog.labs.i18n.ListFormatSymbols_en_DG', 'goog.labs.i18n.ListFormatSymbols_en_DM', 'goog.labs.i18n.ListFormatSymbols_en_ER', 'goog.labs.i18n.ListFormatSymbols_en_FJ', 'goog.labs.i18n.ListFormatSymbols_en_FK', 'goog.labs.i18n.ListFormatSymbols_en_FM', 'goog.labs.i18n.ListFormatSymbols_en_GD', 'goog.labs.i18n.ListFormatSymbols_en_GG', 'goog.labs.i18n.ListFormatSymbols_en_GH', 'goog.labs.i18n.ListFormatSymbols_en_GI', 'goog.labs.i18n.ListFormatSymbols_en_GM', 'goog.labs.i18n.ListFormatSymbols_en_GU', 'goog.labs.i18n.ListFormatSymbols_en_GY', 'goog.labs.i18n.ListFormatSymbols_en_HK', 'goog.labs.i18n.ListFormatSymbols_en_IM', 'goog.labs.i18n.ListFormatSymbols_en_IO', 'goog.labs.i18n.ListFormatSymbols_en_JE', 'goog.labs.i18n.ListFormatSymbols_en_JM', 'goog.labs.i18n.ListFormatSymbols_en_KE', 'goog.labs.i18n.ListFormatSymbols_en_KI', 'goog.labs.i18n.ListFormatSymbols_en_KN', 'goog.labs.i18n.ListFormatSymbols_en_KY', 'goog.labs.i18n.ListFormatSymbols_en_LC', 'goog.labs.i18n.ListFormatSymbols_en_LR', 'goog.labs.i18n.ListFormatSymbols_en_LS', 'goog.labs.i18n.ListFormatSymbols_en_MG', 'goog.labs.i18n.ListFormatSymbols_en_MH', 'goog.labs.i18n.ListFormatSymbols_en_MO', 'goog.labs.i18n.ListFormatSymbols_en_MP', 'goog.labs.i18n.ListFormatSymbols_en_MS', 'goog.labs.i18n.ListFormatSymbols_en_MT', 'goog.labs.i18n.ListFormatSymbols_en_MU', 'goog.labs.i18n.ListFormatSymbols_en_MW', 'goog.labs.i18n.ListFormatSymbols_en_MY', 'goog.labs.i18n.ListFormatSymbols_en_NA', 'goog.labs.i18n.ListFormatSymbols_en_NF', 'goog.labs.i18n.ListFormatSymbols_en_NG', 'goog.labs.i18n.ListFormatSymbols_en_NR', 'goog.labs.i18n.ListFormatSymbols_en_NU', 'goog.labs.i18n.ListFormatSymbols_en_NZ', 'goog.labs.i18n.ListFormatSymbols_en_PG', 'goog.labs.i18n.ListFormatSymbols_en_PH', 'goog.labs.i18n.ListFormatSymbols_en_PK', 'goog.labs.i18n.ListFormatSymbols_en_PN', 'goog.labs.i18n.ListFormatSymbols_en_PR', 'goog.labs.i18n.ListFormatSymbols_en_PW', 'goog.labs.i18n.ListFormatSymbols_en_RW', 'goog.labs.i18n.ListFormatSymbols_en_SB', 'goog.labs.i18n.ListFormatSymbols_en_SC', 'goog.labs.i18n.ListFormatSymbols_en_SD', 'goog.labs.i18n.ListFormatSymbols_en_SH', 'goog.labs.i18n.ListFormatSymbols_en_SL', 'goog.labs.i18n.ListFormatSymbols_en_SS', 'goog.labs.i18n.ListFormatSymbols_en_SX', 'goog.labs.i18n.ListFormatSymbols_en_SZ', 'goog.labs.i18n.ListFormatSymbols_en_TC', 'goog.labs.i18n.ListFormatSymbols_en_TK', 'goog.labs.i18n.ListFormatSymbols_en_TO', 'goog.labs.i18n.ListFormatSymbols_en_TT', 'goog.labs.i18n.ListFormatSymbols_en_TV', 'goog.labs.i18n.ListFormatSymbols_en_TZ', 'goog.labs.i18n.ListFormatSymbols_en_UG', 'goog.labs.i18n.ListFormatSymbols_en_UM', 'goog.labs.i18n.ListFormatSymbols_en_US_POSIX', 'goog.labs.i18n.ListFormatSymbols_en_VC', 'goog.labs.i18n.ListFormatSymbols_en_VG', 'goog.labs.i18n.ListFormatSymbols_en_VI', 'goog.labs.i18n.ListFormatSymbols_en_VU', 'goog.labs.i18n.ListFormatSymbols_en_WS', 'goog.labs.i18n.ListFormatSymbols_en_ZM', 'goog.labs.i18n.ListFormatSymbols_en_ZW', 'goog.labs.i18n.ListFormatSymbols_eo', 'goog.labs.i18n.ListFormatSymbols_es_AR', 'goog.labs.i18n.ListFormatSymbols_es_BO', 'goog.labs.i18n.ListFormatSymbols_es_CL', 'goog.labs.i18n.ListFormatSymbols_es_CO', 'goog.labs.i18n.ListFormatSymbols_es_CR', 'goog.labs.i18n.ListFormatSymbols_es_CU', 'goog.labs.i18n.ListFormatSymbols_es_DO', 'goog.labs.i18n.ListFormatSymbols_es_EA', 'goog.labs.i18n.ListFormatSymbols_es_EC', 'goog.labs.i18n.ListFormatSymbols_es_GQ', 'goog.labs.i18n.ListFormatSymbols_es_GT', 'goog.labs.i18n.ListFormatSymbols_es_HN', 'goog.labs.i18n.ListFormatSymbols_es_IC', 'goog.labs.i18n.ListFormatSymbols_es_MX', 'goog.labs.i18n.ListFormatSymbols_es_NI', 'goog.labs.i18n.ListFormatSymbols_es_PA', 'goog.labs.i18n.ListFormatSymbols_es_PE', 'goog.labs.i18n.ListFormatSymbols_es_PH', 'goog.labs.i18n.ListFormatSymbols_es_PR', 'goog.labs.i18n.ListFormatSymbols_es_PY', 'goog.labs.i18n.ListFormatSymbols_es_SV', 'goog.labs.i18n.ListFormatSymbols_es_US', 'goog.labs.i18n.ListFormatSymbols_es_UY', 'goog.labs.i18n.ListFormatSymbols_es_VE', 'goog.labs.i18n.ListFormatSymbols_et_EE', 'goog.labs.i18n.ListFormatSymbols_eu_ES', 'goog.labs.i18n.ListFormatSymbols_ewo', 'goog.labs.i18n.ListFormatSymbols_ewo_CM', 'goog.labs.i18n.ListFormatSymbols_fa_AF', 'goog.labs.i18n.ListFormatSymbols_fa_IR', 'goog.labs.i18n.ListFormatSymbols_ff', 'goog.labs.i18n.ListFormatSymbols_ff_CM', 'goog.labs.i18n.ListFormatSymbols_ff_GN', 'goog.labs.i18n.ListFormatSymbols_ff_MR', 'goog.labs.i18n.ListFormatSymbols_ff_SN', 'goog.labs.i18n.ListFormatSymbols_fi_FI', 'goog.labs.i18n.ListFormatSymbols_fil_PH', 'goog.labs.i18n.ListFormatSymbols_fo', 'goog.labs.i18n.ListFormatSymbols_fo_FO', 'goog.labs.i18n.ListFormatSymbols_fr_BE', 'goog.labs.i18n.ListFormatSymbols_fr_BF', 'goog.labs.i18n.ListFormatSymbols_fr_BI', 'goog.labs.i18n.ListFormatSymbols_fr_BJ', 'goog.labs.i18n.ListFormatSymbols_fr_BL', 'goog.labs.i18n.ListFormatSymbols_fr_CD', 'goog.labs.i18n.ListFormatSymbols_fr_CF', 'goog.labs.i18n.ListFormatSymbols_fr_CG', 'goog.labs.i18n.ListFormatSymbols_fr_CH', 'goog.labs.i18n.ListFormatSymbols_fr_CI', 'goog.labs.i18n.ListFormatSymbols_fr_CM', 'goog.labs.i18n.ListFormatSymbols_fr_DJ', 'goog.labs.i18n.ListFormatSymbols_fr_DZ', 'goog.labs.i18n.ListFormatSymbols_fr_FR', 'goog.labs.i18n.ListFormatSymbols_fr_GA', 'goog.labs.i18n.ListFormatSymbols_fr_GF', 'goog.labs.i18n.ListFormatSymbols_fr_GN', 'goog.labs.i18n.ListFormatSymbols_fr_GP', 'goog.labs.i18n.ListFormatSymbols_fr_GQ', 'goog.labs.i18n.ListFormatSymbols_fr_HT', 'goog.labs.i18n.ListFormatSymbols_fr_KM', 'goog.labs.i18n.ListFormatSymbols_fr_LU', 'goog.labs.i18n.ListFormatSymbols_fr_MA', 'goog.labs.i18n.ListFormatSymbols_fr_MC', 'goog.labs.i18n.ListFormatSymbols_fr_MF', 'goog.labs.i18n.ListFormatSymbols_fr_MG', 'goog.labs.i18n.ListFormatSymbols_fr_ML', 'goog.labs.i18n.ListFormatSymbols_fr_MQ', 'goog.labs.i18n.ListFormatSymbols_fr_MR', 'goog.labs.i18n.ListFormatSymbols_fr_MU', 'goog.labs.i18n.ListFormatSymbols_fr_NC', 'goog.labs.i18n.ListFormatSymbols_fr_NE', 'goog.labs.i18n.ListFormatSymbols_fr_PF', 'goog.labs.i18n.ListFormatSymbols_fr_PM', 'goog.labs.i18n.ListFormatSymbols_fr_RE', 'goog.labs.i18n.ListFormatSymbols_fr_RW', 'goog.labs.i18n.ListFormatSymbols_fr_SC', 'goog.labs.i18n.ListFormatSymbols_fr_SN', 'goog.labs.i18n.ListFormatSymbols_fr_SY', 'goog.labs.i18n.ListFormatSymbols_fr_TD', 'goog.labs.i18n.ListFormatSymbols_fr_TG', 'goog.labs.i18n.ListFormatSymbols_fr_TN', 'goog.labs.i18n.ListFormatSymbols_fr_VU', 'goog.labs.i18n.ListFormatSymbols_fr_WF', 'goog.labs.i18n.ListFormatSymbols_fr_YT', 'goog.labs.i18n.ListFormatSymbols_fur', 'goog.labs.i18n.ListFormatSymbols_fur_IT', 'goog.labs.i18n.ListFormatSymbols_fy', 'goog.labs.i18n.ListFormatSymbols_fy_NL', 'goog.labs.i18n.ListFormatSymbols_ga_IE', 'goog.labs.i18n.ListFormatSymbols_gd', 'goog.labs.i18n.ListFormatSymbols_gd_GB', 'goog.labs.i18n.ListFormatSymbols_gl_ES', 'goog.labs.i18n.ListFormatSymbols_gsw_CH', 'goog.labs.i18n.ListFormatSymbols_gsw_FR', 'goog.labs.i18n.ListFormatSymbols_gsw_LI', 'goog.labs.i18n.ListFormatSymbols_gu_IN', 'goog.labs.i18n.ListFormatSymbols_guz', 'goog.labs.i18n.ListFormatSymbols_guz_KE', 'goog.labs.i18n.ListFormatSymbols_gv', 'goog.labs.i18n.ListFormatSymbols_gv_IM', 'goog.labs.i18n.ListFormatSymbols_ha', 'goog.labs.i18n.ListFormatSymbols_ha_Latn', 'goog.labs.i18n.ListFormatSymbols_ha_Latn_GH', 'goog.labs.i18n.ListFormatSymbols_ha_Latn_NE', 'goog.labs.i18n.ListFormatSymbols_ha_Latn_NG', 'goog.labs.i18n.ListFormatSymbols_haw_US', 'goog.labs.i18n.ListFormatSymbols_he_IL', 'goog.labs.i18n.ListFormatSymbols_hi_IN', 'goog.labs.i18n.ListFormatSymbols_hr_BA', 'goog.labs.i18n.ListFormatSymbols_hr_HR', 'goog.labs.i18n.ListFormatSymbols_hsb', 'goog.labs.i18n.ListFormatSymbols_hsb_DE', 'goog.labs.i18n.ListFormatSymbols_hu_HU', 'goog.labs.i18n.ListFormatSymbols_hy_AM', 'goog.labs.i18n.ListFormatSymbols_id_ID', 'goog.labs.i18n.ListFormatSymbols_ig', 'goog.labs.i18n.ListFormatSymbols_ig_NG', 'goog.labs.i18n.ListFormatSymbols_ii', 'goog.labs.i18n.ListFormatSymbols_ii_CN', 'goog.labs.i18n.ListFormatSymbols_is_IS', 'goog.labs.i18n.ListFormatSymbols_it_CH', 'goog.labs.i18n.ListFormatSymbols_it_IT', 'goog.labs.i18n.ListFormatSymbols_it_SM', 'goog.labs.i18n.ListFormatSymbols_ja_JP', 'goog.labs.i18n.ListFormatSymbols_jgo', 'goog.labs.i18n.ListFormatSymbols_jgo_CM', 'goog.labs.i18n.ListFormatSymbols_jmc', 'goog.labs.i18n.ListFormatSymbols_jmc_TZ', 'goog.labs.i18n.ListFormatSymbols_ka_GE', 'goog.labs.i18n.ListFormatSymbols_kab', 'goog.labs.i18n.ListFormatSymbols_kab_DZ', 'goog.labs.i18n.ListFormatSymbols_kam', 'goog.labs.i18n.ListFormatSymbols_kam_KE', 'goog.labs.i18n.ListFormatSymbols_kde', 'goog.labs.i18n.ListFormatSymbols_kde_TZ', 'goog.labs.i18n.ListFormatSymbols_kea', 'goog.labs.i18n.ListFormatSymbols_kea_CV', 'goog.labs.i18n.ListFormatSymbols_khq', 'goog.labs.i18n.ListFormatSymbols_khq_ML', 'goog.labs.i18n.ListFormatSymbols_ki', 'goog.labs.i18n.ListFormatSymbols_ki_KE', 'goog.labs.i18n.ListFormatSymbols_kk_Cyrl', 'goog.labs.i18n.ListFormatSymbols_kk_Cyrl_KZ', 'goog.labs.i18n.ListFormatSymbols_kkj', 'goog.labs.i18n.ListFormatSymbols_kkj_CM', 'goog.labs.i18n.ListFormatSymbols_kl', 'goog.labs.i18n.ListFormatSymbols_kl_GL', 'goog.labs.i18n.ListFormatSymbols_kln', 'goog.labs.i18n.ListFormatSymbols_kln_KE', 'goog.labs.i18n.ListFormatSymbols_km_KH', 'goog.labs.i18n.ListFormatSymbols_kn_IN', 'goog.labs.i18n.ListFormatSymbols_ko_KP', 'goog.labs.i18n.ListFormatSymbols_ko_KR', 'goog.labs.i18n.ListFormatSymbols_kok', 'goog.labs.i18n.ListFormatSymbols_kok_IN', 'goog.labs.i18n.ListFormatSymbols_ks', 'goog.labs.i18n.ListFormatSymbols_ks_Arab', 'goog.labs.i18n.ListFormatSymbols_ks_Arab_IN', 'goog.labs.i18n.ListFormatSymbols_ksb', 'goog.labs.i18n.ListFormatSymbols_ksb_TZ', 'goog.labs.i18n.ListFormatSymbols_ksf', 'goog.labs.i18n.ListFormatSymbols_ksf_CM', 'goog.labs.i18n.ListFormatSymbols_ksh', 'goog.labs.i18n.ListFormatSymbols_ksh_DE', 'goog.labs.i18n.ListFormatSymbols_kw', 'goog.labs.i18n.ListFormatSymbols_kw_GB', 'goog.labs.i18n.ListFormatSymbols_ky_Cyrl', 'goog.labs.i18n.ListFormatSymbols_ky_Cyrl_KG', 'goog.labs.i18n.ListFormatSymbols_lag', 'goog.labs.i18n.ListFormatSymbols_lag_TZ', 'goog.labs.i18n.ListFormatSymbols_lb', 'goog.labs.i18n.ListFormatSymbols_lb_LU', 'goog.labs.i18n.ListFormatSymbols_lg', 'goog.labs.i18n.ListFormatSymbols_lg_UG', 'goog.labs.i18n.ListFormatSymbols_lkt', 'goog.labs.i18n.ListFormatSymbols_lkt_US', 'goog.labs.i18n.ListFormatSymbols_ln_AO', 'goog.labs.i18n.ListFormatSymbols_ln_CD', 'goog.labs.i18n.ListFormatSymbols_ln_CF', 'goog.labs.i18n.ListFormatSymbols_ln_CG', 'goog.labs.i18n.ListFormatSymbols_lo_LA', 'goog.labs.i18n.ListFormatSymbols_lt_LT', 'goog.labs.i18n.ListFormatSymbols_lu', 'goog.labs.i18n.ListFormatSymbols_lu_CD', 'goog.labs.i18n.ListFormatSymbols_luo', 'goog.labs.i18n.ListFormatSymbols_luo_KE', 'goog.labs.i18n.ListFormatSymbols_luy', 'goog.labs.i18n.ListFormatSymbols_luy_KE', 'goog.labs.i18n.ListFormatSymbols_lv_LV', 'goog.labs.i18n.ListFormatSymbols_mas', 'goog.labs.i18n.ListFormatSymbols_mas_KE', 'goog.labs.i18n.ListFormatSymbols_mas_TZ', 'goog.labs.i18n.ListFormatSymbols_mer', 'goog.labs.i18n.ListFormatSymbols_mer_KE', 'goog.labs.i18n.ListFormatSymbols_mfe', 'goog.labs.i18n.ListFormatSymbols_mfe_MU', 'goog.labs.i18n.ListFormatSymbols_mg', 'goog.labs.i18n.ListFormatSymbols_mg_MG', 'goog.labs.i18n.ListFormatSymbols_mgh', 'goog.labs.i18n.ListFormatSymbols_mgh_MZ', 'goog.labs.i18n.ListFormatSymbols_mgo', 'goog.labs.i18n.ListFormatSymbols_mgo_CM', 'goog.labs.i18n.ListFormatSymbols_mk_MK', 'goog.labs.i18n.ListFormatSymbols_ml_IN', 'goog.labs.i18n.ListFormatSymbols_mn_Cyrl', 'goog.labs.i18n.ListFormatSymbols_mn_Cyrl_MN', 'goog.labs.i18n.ListFormatSymbols_mr_IN', 'goog.labs.i18n.ListFormatSymbols_ms_Latn', 'goog.labs.i18n.ListFormatSymbols_ms_Latn_BN', 'goog.labs.i18n.ListFormatSymbols_ms_Latn_MY', 'goog.labs.i18n.ListFormatSymbols_ms_Latn_SG', 'goog.labs.i18n.ListFormatSymbols_mt_MT', 'goog.labs.i18n.ListFormatSymbols_mua', 'goog.labs.i18n.ListFormatSymbols_mua_CM', 'goog.labs.i18n.ListFormatSymbols_my_MM', 'goog.labs.i18n.ListFormatSymbols_naq', 'goog.labs.i18n.ListFormatSymbols_naq_NA', 'goog.labs.i18n.ListFormatSymbols_nb_NO', 'goog.labs.i18n.ListFormatSymbols_nb_SJ', 'goog.labs.i18n.ListFormatSymbols_nd', 'goog.labs.i18n.ListFormatSymbols_nd_ZW', 'goog.labs.i18n.ListFormatSymbols_ne_IN', 'goog.labs.i18n.ListFormatSymbols_ne_NP', 'goog.labs.i18n.ListFormatSymbols_nl_AW', 'goog.labs.i18n.ListFormatSymbols_nl_BE', 'goog.labs.i18n.ListFormatSymbols_nl_BQ', 'goog.labs.i18n.ListFormatSymbols_nl_CW', 'goog.labs.i18n.ListFormatSymbols_nl_NL', 'goog.labs.i18n.ListFormatSymbols_nl_SR', 'goog.labs.i18n.ListFormatSymbols_nl_SX', 'goog.labs.i18n.ListFormatSymbols_nmg', 'goog.labs.i18n.ListFormatSymbols_nmg_CM', 'goog.labs.i18n.ListFormatSymbols_nn', 'goog.labs.i18n.ListFormatSymbols_nn_NO', 'goog.labs.i18n.ListFormatSymbols_nnh', 'goog.labs.i18n.ListFormatSymbols_nnh_CM', 'goog.labs.i18n.ListFormatSymbols_nus', 'goog.labs.i18n.ListFormatSymbols_nus_SD', 'goog.labs.i18n.ListFormatSymbols_nyn', 'goog.labs.i18n.ListFormatSymbols_nyn_UG', 'goog.labs.i18n.ListFormatSymbols_om', 'goog.labs.i18n.ListFormatSymbols_om_ET', 'goog.labs.i18n.ListFormatSymbols_om_KE', 'goog.labs.i18n.ListFormatSymbols_or_IN', 'goog.labs.i18n.ListFormatSymbols_os', 'goog.labs.i18n.ListFormatSymbols_os_GE', 'goog.labs.i18n.ListFormatSymbols_os_RU', 'goog.labs.i18n.ListFormatSymbols_pa_Arab', 'goog.labs.i18n.ListFormatSymbols_pa_Arab_PK', 'goog.labs.i18n.ListFormatSymbols_pa_Guru', 'goog.labs.i18n.ListFormatSymbols_pa_Guru_IN', 'goog.labs.i18n.ListFormatSymbols_pl_PL', 'goog.labs.i18n.ListFormatSymbols_ps', 'goog.labs.i18n.ListFormatSymbols_ps_AF', 'goog.labs.i18n.ListFormatSymbols_pt_AO', 'goog.labs.i18n.ListFormatSymbols_pt_CV', 'goog.labs.i18n.ListFormatSymbols_pt_GW', 'goog.labs.i18n.ListFormatSymbols_pt_MO', 'goog.labs.i18n.ListFormatSymbols_pt_MZ', 'goog.labs.i18n.ListFormatSymbols_pt_ST', 'goog.labs.i18n.ListFormatSymbols_pt_TL', 'goog.labs.i18n.ListFormatSymbols_qu', 'goog.labs.i18n.ListFormatSymbols_qu_BO', 'goog.labs.i18n.ListFormatSymbols_qu_EC', 'goog.labs.i18n.ListFormatSymbols_qu_PE', 'goog.labs.i18n.ListFormatSymbols_rm', 'goog.labs.i18n.ListFormatSymbols_rm_CH', 'goog.labs.i18n.ListFormatSymbols_rn', 'goog.labs.i18n.ListFormatSymbols_rn_BI', 'goog.labs.i18n.ListFormatSymbols_ro_MD', 'goog.labs.i18n.ListFormatSymbols_ro_RO', 'goog.labs.i18n.ListFormatSymbols_rof', 'goog.labs.i18n.ListFormatSymbols_rof_TZ', 'goog.labs.i18n.ListFormatSymbols_ru_BY', 'goog.labs.i18n.ListFormatSymbols_ru_KG', 'goog.labs.i18n.ListFormatSymbols_ru_KZ', 'goog.labs.i18n.ListFormatSymbols_ru_MD', 'goog.labs.i18n.ListFormatSymbols_ru_RU', 'goog.labs.i18n.ListFormatSymbols_ru_UA', 'goog.labs.i18n.ListFormatSymbols_rw', 'goog.labs.i18n.ListFormatSymbols_rw_RW', 'goog.labs.i18n.ListFormatSymbols_rwk', 'goog.labs.i18n.ListFormatSymbols_rwk_TZ', 'goog.labs.i18n.ListFormatSymbols_sah', 'goog.labs.i18n.ListFormatSymbols_sah_RU', 'goog.labs.i18n.ListFormatSymbols_saq', 'goog.labs.i18n.ListFormatSymbols_saq_KE', 'goog.labs.i18n.ListFormatSymbols_sbp', 'goog.labs.i18n.ListFormatSymbols_sbp_TZ', 'goog.labs.i18n.ListFormatSymbols_se', 'goog.labs.i18n.ListFormatSymbols_se_FI', 'goog.labs.i18n.ListFormatSymbols_se_NO', 'goog.labs.i18n.ListFormatSymbols_se_SE', 'goog.labs.i18n.ListFormatSymbols_seh', 'goog.labs.i18n.ListFormatSymbols_seh_MZ', 'goog.labs.i18n.ListFormatSymbols_ses', 'goog.labs.i18n.ListFormatSymbols_ses_ML', 'goog.labs.i18n.ListFormatSymbols_sg', 'goog.labs.i18n.ListFormatSymbols_sg_CF', 'goog.labs.i18n.ListFormatSymbols_shi', 'goog.labs.i18n.ListFormatSymbols_shi_Latn', 'goog.labs.i18n.ListFormatSymbols_shi_Latn_MA', 'goog.labs.i18n.ListFormatSymbols_shi_Tfng', 'goog.labs.i18n.ListFormatSymbols_shi_Tfng_MA', 'goog.labs.i18n.ListFormatSymbols_si_LK', 'goog.labs.i18n.ListFormatSymbols_sk_SK', 'goog.labs.i18n.ListFormatSymbols_sl_SI', 'goog.labs.i18n.ListFormatSymbols_smn', 'goog.labs.i18n.ListFormatSymbols_smn_FI', 'goog.labs.i18n.ListFormatSymbols_sn', 'goog.labs.i18n.ListFormatSymbols_sn_ZW', 'goog.labs.i18n.ListFormatSymbols_so', 'goog.labs.i18n.ListFormatSymbols_so_DJ', 'goog.labs.i18n.ListFormatSymbols_so_ET', 'goog.labs.i18n.ListFormatSymbols_so_KE', 'goog.labs.i18n.ListFormatSymbols_so_SO', 'goog.labs.i18n.ListFormatSymbols_sq_AL', 'goog.labs.i18n.ListFormatSymbols_sq_MK', 'goog.labs.i18n.ListFormatSymbols_sq_XK', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_BA', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_ME', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_RS', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_XK', 'goog.labs.i18n.ListFormatSymbols_sr_Latn', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_BA', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_ME', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_RS', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_XK', 'goog.labs.i18n.ListFormatSymbols_sv_AX', 'goog.labs.i18n.ListFormatSymbols_sv_FI', 'goog.labs.i18n.ListFormatSymbols_sv_SE', 'goog.labs.i18n.ListFormatSymbols_sw_KE', 'goog.labs.i18n.ListFormatSymbols_sw_TZ', 'goog.labs.i18n.ListFormatSymbols_sw_UG', 'goog.labs.i18n.ListFormatSymbols_swc', 'goog.labs.i18n.ListFormatSymbols_swc_CD', 'goog.labs.i18n.ListFormatSymbols_ta_IN', 'goog.labs.i18n.ListFormatSymbols_ta_LK', 'goog.labs.i18n.ListFormatSymbols_ta_MY', 'goog.labs.i18n.ListFormatSymbols_ta_SG', 'goog.labs.i18n.ListFormatSymbols_te_IN', 'goog.labs.i18n.ListFormatSymbols_teo', 'goog.labs.i18n.ListFormatSymbols_teo_KE', 'goog.labs.i18n.ListFormatSymbols_teo_UG', 'goog.labs.i18n.ListFormatSymbols_th_TH', 'goog.labs.i18n.ListFormatSymbols_ti', 'goog.labs.i18n.ListFormatSymbols_ti_ER', 'goog.labs.i18n.ListFormatSymbols_ti_ET', 'goog.labs.i18n.ListFormatSymbols_to', 'goog.labs.i18n.ListFormatSymbols_to_TO', 'goog.labs.i18n.ListFormatSymbols_tr_CY', 'goog.labs.i18n.ListFormatSymbols_tr_TR', 'goog.labs.i18n.ListFormatSymbols_twq', 'goog.labs.i18n.ListFormatSymbols_twq_NE', 'goog.labs.i18n.ListFormatSymbols_tzm', 'goog.labs.i18n.ListFormatSymbols_tzm_Latn', 'goog.labs.i18n.ListFormatSymbols_tzm_Latn_MA', 'goog.labs.i18n.ListFormatSymbols_ug', 'goog.labs.i18n.ListFormatSymbols_ug_Arab', 'goog.labs.i18n.ListFormatSymbols_ug_Arab_CN', 'goog.labs.i18n.ListFormatSymbols_uk_UA', 'goog.labs.i18n.ListFormatSymbols_ur_IN', 'goog.labs.i18n.ListFormatSymbols_ur_PK', 'goog.labs.i18n.ListFormatSymbols_uz_Arab', 'goog.labs.i18n.ListFormatSymbols_uz_Arab_AF', 'goog.labs.i18n.ListFormatSymbols_uz_Cyrl', 'goog.labs.i18n.ListFormatSymbols_uz_Cyrl_UZ', 'goog.labs.i18n.ListFormatSymbols_uz_Latn', 'goog.labs.i18n.ListFormatSymbols_uz_Latn_UZ', 'goog.labs.i18n.ListFormatSymbols_vai', 'goog.labs.i18n.ListFormatSymbols_vai_Latn', 'goog.labs.i18n.ListFormatSymbols_vai_Latn_LR', 'goog.labs.i18n.ListFormatSymbols_vai_Vaii', 'goog.labs.i18n.ListFormatSymbols_vai_Vaii_LR', 'goog.labs.i18n.ListFormatSymbols_vi_VN', 'goog.labs.i18n.ListFormatSymbols_vun', 'goog.labs.i18n.ListFormatSymbols_vun_TZ', 'goog.labs.i18n.ListFormatSymbols_wae', 'goog.labs.i18n.ListFormatSymbols_wae_CH', 'goog.labs.i18n.ListFormatSymbols_xog', 'goog.labs.i18n.ListFormatSymbols_xog_UG', 'goog.labs.i18n.ListFormatSymbols_yav', 'goog.labs.i18n.ListFormatSymbols_yav_CM', 'goog.labs.i18n.ListFormatSymbols_yi', 'goog.labs.i18n.ListFormatSymbols_yi_001', 'goog.labs.i18n.ListFormatSymbols_yo', 'goog.labs.i18n.ListFormatSymbols_yo_BJ', 'goog.labs.i18n.ListFormatSymbols_yo_NG', 'goog.labs.i18n.ListFormatSymbols_zgh', 'goog.labs.i18n.ListFormatSymbols_zgh_MA', 'goog.labs.i18n.ListFormatSymbols_zh_Hans', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_CN', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_HK', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_MO', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_SG', 'goog.labs.i18n.ListFormatSymbols_zh_Hant', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_HK', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_MO', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_TW', 'goog.labs.i18n.ListFormatSymbols_zu_ZA'], ['goog.labs.i18n.ListFormatSymbols'], false);
+goog.addDependency('labs/iterable/iterable.js', ['goog.labs.iterable'], [], true);
+goog.addDependency('labs/iterable/iterable_test.js', ['goog.labs.iterableTest'], ['goog.labs.iterable', 'goog.testing.jsunit', 'goog.testing.recordFunction'], true);
+goog.addDependency('labs/mock/mock.js', ['goog.labs.mock', 'goog.labs.mock.VerificationError'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.Error', 'goog.functions', 'goog.object'], false);
+goog.addDependency('labs/mock/mock_test.js', ['goog.labs.mockTest'], ['goog.array', 'goog.labs.mock', 'goog.labs.mock.VerificationError', 'goog.labs.testing.AnythingMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.string', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/net/image.js', ['goog.labs.net.image'], ['goog.Promise', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.net.EventType', 'goog.userAgent'], false);
+goog.addDependency('labs/net/image_test.js', ['goog.labs.net.imageTest'], ['goog.labs.net.image', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('labs/net/webchannel.js', ['goog.net.WebChannel'], ['goog.events', 'goog.events.Event'], false);
+goog.addDependency('labs/net/webchannel/basetestchannel.js', ['goog.labs.net.webChannel.BaseTestChannel'], ['goog.labs.net.webChannel.Channel', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat'], false);
+goog.addDependency('labs/net/webchannel/channel.js', ['goog.labs.net.webChannel.Channel'], [], false);
+goog.addDependency('labs/net/webchannel/channelrequest.js', ['goog.labs.net.webChannel.ChannelRequest'], ['goog.Timer', 'goog.async.Throttle', 'goog.events.EventHandler', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.uri.utils.StandardQueryParam', 'goog.userAgent'], false);
+goog.addDependency('labs/net/webchannel/channelrequest_test.js', ['goog.labs.net.webChannel.channelRequestTest'], ['goog.Uri', 'goog.functions', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false);
+goog.addDependency('labs/net/webchannel/connectionstate.js', ['goog.labs.net.webChannel.ConnectionState'], [], false);
+goog.addDependency('labs/net/webchannel/forwardchannelrequestpool.js', ['goog.labs.net.webChannel.ForwardChannelRequestPool'], ['goog.array', 'goog.string', 'goog.structs.Set'], false);
+goog.addDependency('labs/net/webchannel/forwardchannelrequestpool_test.js', ['goog.labs.net.webChannel.forwardChannelRequestPoolTest'], ['goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/net/webchannel/netutils.js', ['goog.labs.net.webChannel.netUtils'], ['goog.Uri', 'goog.labs.net.webChannel.WebChannelDebug'], false);
+goog.addDependency('labs/net/webchannel/requeststats.js', ['goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Event', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.labs.net.webChannel.requestStats.ServerReachabilityEvent', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.labs.net.webChannel.requestStats.StatEvent', 'goog.labs.net.webChannel.requestStats.TimingEvent'], ['goog.events.Event', 'goog.events.EventTarget'], false);
+goog.addDependency('labs/net/webchannel/webchannelbase.js', ['goog.labs.net.webChannel.WebChannelBase'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.TextFormatter', 'goog.json', 'goog.labs.net.webChannel.BaseTestChannel', 'goog.labs.net.webChannel.Channel', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ConnectionState', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.Wire', 'goog.labs.net.webChannel.WireV8', 'goog.labs.net.webChannel.netUtils', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.log', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer'], false);
+goog.addDependency('labs/net/webchannel/webchannelbase_test.js', ['goog.labs.net.webChannel.webChannelBaseTest'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.functions', 'goog.json', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.labs.net.webChannel.WebChannelBase', 'goog.labs.net.webChannel.WebChannelBaseTransport', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.Wire', 'goog.labs.net.webChannel.netUtils', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/net/webchannel/webchannelbasetransport.js', ['goog.labs.net.webChannel.WebChannelBaseTransport'], ['goog.asserts', 'goog.events.EventTarget', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelBase', 'goog.log', 'goog.net.WebChannel', 'goog.net.WebChannelTransport', 'goog.object', 'goog.string.path'], false);
+goog.addDependency('labs/net/webchannel/webchannelbasetransport_test.js', ['goog.labs.net.webChannel.webChannelBaseTransportTest'], ['goog.events', 'goog.functions', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelBaseTransport', 'goog.net.WebChannel', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/net/webchannel/webchanneldebug.js', ['goog.labs.net.webChannel.WebChannelDebug'], ['goog.json', 'goog.log'], false);
+goog.addDependency('labs/net/webchannel/wire.js', ['goog.labs.net.webChannel.Wire'], [], false);
+goog.addDependency('labs/net/webchannel/wirev8.js', ['goog.labs.net.webChannel.WireV8'], ['goog.asserts', 'goog.json', 'goog.json.NativeJsonProcessor', 'goog.structs'], false);
+goog.addDependency('labs/net/webchannel/wirev8_test.js', ['goog.labs.net.webChannel.WireV8Test'], ['goog.labs.net.webChannel.WireV8', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/net/webchanneltransport.js', ['goog.net.WebChannelTransport'], [], false);
+goog.addDependency('labs/net/webchanneltransportfactory.js', ['goog.net.createWebChannelTransport'], ['goog.functions', 'goog.labs.net.webChannel.WebChannelBaseTransport'], false);
+goog.addDependency('labs/net/xhr.js', ['goog.labs.net.xhr', 'goog.labs.net.xhr.Error', 'goog.labs.net.xhr.HttpError', 'goog.labs.net.xhr.Options', 'goog.labs.net.xhr.PostData', 'goog.labs.net.xhr.ResponseType', 'goog.labs.net.xhr.TimeoutError'], ['goog.Promise', 'goog.debug.Error', 'goog.json', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.string', 'goog.uri.utils', 'goog.userAgent'], false);
+goog.addDependency('labs/net/xhr_test.js', ['goog.labs.net.xhrTest'], ['goog.Promise', 'goog.labs.net.xhr', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttp', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('labs/object/object.js', ['goog.labs.object'], [], false);
+goog.addDependency('labs/object/object_test.js', ['goog.labs.objectTest'], ['goog.labs.object', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/pubsub/broadcastpubsub.js', ['goog.labs.pubsub.BroadcastPubSub'], ['goog.Disposable', 'goog.Timer', 'goog.array', 'goog.async.run', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.math', 'goog.pubsub.PubSub', 'goog.storage.Storage', 'goog.storage.mechanism.HTML5LocalStorage', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('labs/pubsub/broadcastpubsub_test.js', ['goog.labs.pubsub.BroadcastPubSubTest'], ['goog.array', 'goog.debug.Logger', 'goog.json', 'goog.labs.pubsub.BroadcastPubSub', 'goog.storage.Storage', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('labs/storage/boundedcollectablestorage.js', ['goog.labs.storage.BoundedCollectableStorage'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage'], false);
+goog.addDependency('labs/storage/boundedcollectablestorage_test.js', ['goog.labs.storage.BoundedCollectableStorageTest'], ['goog.labs.storage.BoundedCollectableStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false);
+goog.addDependency('labs/structs/map.js', ['goog.labs.structs.Map'], ['goog.array', 'goog.asserts', 'goog.labs.object', 'goog.object'], false);
+goog.addDependency('labs/structs/map_perf.js', ['goog.labs.structs.MapPerf'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.labs.structs.Map', 'goog.structs.Map', 'goog.testing.PerformanceTable', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/structs/map_test.js', ['goog.labs.structs.MapTest'], ['goog.labs.structs.Map', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/structs/multimap.js', ['goog.labs.structs.Multimap'], ['goog.array', 'goog.labs.object', 'goog.labs.structs.Map'], false);
+goog.addDependency('labs/structs/multimap_test.js', ['goog.labs.structs.MultimapTest'], ['goog.labs.structs.Map', 'goog.labs.structs.Multimap', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/style/pixeldensitymonitor.js', ['goog.labs.style.PixelDensityMonitor', 'goog.labs.style.PixelDensityMonitor.Density', 'goog.labs.style.PixelDensityMonitor.EventType'], ['goog.events', 'goog.events.EventTarget'], false);
+goog.addDependency('labs/style/pixeldensitymonitor_test.js', ['goog.labs.style.PixelDensityMonitorTest'], ['goog.array', 'goog.dom.DomHelper', 'goog.events', 'goog.labs.style.PixelDensityMonitor', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('labs/testing/assertthat.js', ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat'], ['goog.debug.Error'], false);
+goog.addDependency('labs/testing/assertthat_test.js', ['goog.labs.testing.assertThatTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('labs/testing/decoratormatcher.js', ['goog.labs.testing.AnythingMatcher'], ['goog.labs.testing.Matcher'], false);
+goog.addDependency('labs/testing/decoratormatcher_test.js', ['goog.labs.testing.decoratorMatcherTest'], ['goog.labs.testing.AnythingMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/dictionarymatcher.js', ['goog.labs.testing.HasEntriesMatcher', 'goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.HasKeyMatcher', 'goog.labs.testing.HasValueMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.object'], false);
+goog.addDependency('labs/testing/dictionarymatcher_test.js', ['goog.labs.testing.dictionaryMatcherTest'], ['goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/environment.js', ['goog.labs.testing.Environment'], ['goog.array', 'goog.debug.Console', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/environment_test.js', ['goog.labs.testing.environmentTest'], ['goog.labs.testing.Environment', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/environment_usage_test.js', ['goog.labs.testing.environmentUsageTest'], ['goog.labs.testing.Environment'], false);
+goog.addDependency('labs/testing/logicmatcher.js', ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.AnyOfMatcher', 'goog.labs.testing.IsNotMatcher'], ['goog.array', 'goog.labs.testing.Matcher'], false);
+goog.addDependency('labs/testing/logicmatcher_test.js', ['goog.labs.testing.logicMatcherTest'], ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/matcher.js', ['goog.labs.testing.Matcher'], [], false);
+goog.addDependency('labs/testing/numbermatcher.js', ['goog.labs.testing.CloseToMatcher', 'goog.labs.testing.EqualToMatcher', 'goog.labs.testing.GreaterThanEqualToMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.LessThanEqualToMatcher', 'goog.labs.testing.LessThanMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher'], false);
+goog.addDependency('labs/testing/numbermatcher_test.js', ['goog.labs.testing.numberMatcherTest'], ['goog.labs.testing.LessThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/objectmatcher.js', ['goog.labs.testing.HasPropertyMatcher', 'goog.labs.testing.InstanceOfMatcher', 'goog.labs.testing.IsNullMatcher', 'goog.labs.testing.IsNullOrUndefinedMatcher', 'goog.labs.testing.IsUndefinedMatcher', 'goog.labs.testing.ObjectEqualsMatcher'], ['goog.labs.testing.Matcher'], false);
+goog.addDependency('labs/testing/objectmatcher_test.js', ['goog.labs.testing.objectMatcherTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.ObjectEqualsMatcher', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/testing/stringmatcher.js', ['goog.labs.testing.ContainsStringMatcher', 'goog.labs.testing.EndsWithMatcher', 'goog.labs.testing.EqualToIgnoringWhitespaceMatcher', 'goog.labs.testing.EqualsMatcher', 'goog.labs.testing.RegexMatcher', 'goog.labs.testing.StartsWithMatcher', 'goog.labs.testing.StringContainsInOrderMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.string'], false);
+goog.addDependency('labs/testing/stringmatcher_test.js', ['goog.labs.testing.stringMatcherTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.StringContainsInOrderMatcher', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/useragent/browser.js', ['goog.labs.userAgent.browser'], ['goog.array', 'goog.labs.userAgent.util', 'goog.object', 'goog.string'], false);
+goog.addDependency('labs/useragent/browser_test.js', ['goog.labs.userAgent.browserTest'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.object', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/useragent/device.js', ['goog.labs.userAgent.device'], ['goog.labs.userAgent.util'], false);
+goog.addDependency('labs/useragent/device_test.js', ['goog.labs.userAgent.deviceTest'], ['goog.labs.userAgent.device', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/useragent/engine.js', ['goog.labs.userAgent.engine'], ['goog.array', 'goog.labs.userAgent.util', 'goog.string'], false);
+goog.addDependency('labs/useragent/engine_test.js', ['goog.labs.userAgent.engineTest'], ['goog.labs.userAgent.engine', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/useragent/platform.js', ['goog.labs.userAgent.platform'], ['goog.labs.userAgent.util', 'goog.string'], false);
+goog.addDependency('labs/useragent/platform_test.js', ['goog.labs.userAgent.platformTest'], ['goog.labs.userAgent.platform', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit'], false);
+goog.addDependency('labs/useragent/test_agents.js', ['goog.labs.userAgent.testAgents'], [], false);
+goog.addDependency('labs/useragent/util.js', ['goog.labs.userAgent.util'], ['goog.string'], false);
+goog.addDependency('labs/useragent/util_test.js', ['goog.labs.userAgent.utilTest'], ['goog.functions', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('locale/countries.js', ['goog.locale.countries'], [], false);
+goog.addDependency('locale/countrylanguagenames_test.js', ['goog.locale.countryLanguageNamesTest'], ['goog.locale', 'goog.testing.jsunit'], false);
+goog.addDependency('locale/defaultlocalenameconstants.js', ['goog.locale.defaultLocaleNameConstants'], [], false);
+goog.addDependency('locale/genericfontnames.js', ['goog.locale.genericFontNames'], [], false);
+goog.addDependency('locale/genericfontnames_test.js', ['goog.locale.genericFontNamesTest'], ['goog.locale.genericFontNames', 'goog.testing.jsunit'], false);
+goog.addDependency('locale/genericfontnamesdata.js', ['goog.locale.genericFontNamesData'], [], false);
+goog.addDependency('locale/locale.js', ['goog.locale'], ['goog.locale.nativeNameConstants'], false);
+goog.addDependency('locale/nativenameconstants.js', ['goog.locale.nativeNameConstants'], [], false);
+goog.addDependency('locale/scriptToLanguages.js', ['goog.locale.scriptToLanguages'], ['goog.locale'], false);
+goog.addDependency('locale/timezonedetection.js', ['goog.locale.timeZoneDetection'], ['goog.locale.TimeZoneFingerprint'], false);
+goog.addDependency('locale/timezonedetection_test.js', ['goog.locale.timeZoneDetectionTest'], ['goog.locale.timeZoneDetection', 'goog.testing.jsunit'], false);
+goog.addDependency('locale/timezonefingerprint.js', ['goog.locale.TimeZoneFingerprint'], [], false);
+goog.addDependency('locale/timezonelist.js', ['goog.locale.TimeZoneList'], ['goog.locale'], false);
+goog.addDependency('locale/timezonelist_test.js', ['goog.locale.TimeZoneListTest'], ['goog.locale', 'goog.locale.TimeZoneList', 'goog.testing.jsunit'], false);
+goog.addDependency('log/log.js', ['goog.log', 'goog.log.Level', 'goog.log.LogRecord', 'goog.log.Logger'], ['goog.debug', 'goog.debug.LogManager', 'goog.debug.LogRecord', 'goog.debug.Logger'], false);
+goog.addDependency('log/log_test.js', ['goog.logTest'], ['goog.debug.LogManager', 'goog.log', 'goog.log.Level', 'goog.testing.jsunit'], false);
+goog.addDependency('math/affinetransform.js', ['goog.math.AffineTransform'], ['goog.math'], false);
+goog.addDependency('math/affinetransform_test.js', ['goog.math.AffineTransformTest'], ['goog.array', 'goog.math', 'goog.math.AffineTransform', 'goog.testing.jsunit'], false);
+goog.addDependency('math/bezier.js', ['goog.math.Bezier'], ['goog.math', 'goog.math.Coordinate'], false);
+goog.addDependency('math/bezier_test.js', ['goog.math.BezierTest'], ['goog.math', 'goog.math.Bezier', 'goog.math.Coordinate', 'goog.testing.jsunit'], false);
+goog.addDependency('math/box.js', ['goog.math.Box'], ['goog.math.Coordinate'], false);
+goog.addDependency('math/box_test.js', ['goog.math.BoxTest'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.testing.jsunit'], false);
+goog.addDependency('math/coordinate.js', ['goog.math.Coordinate'], ['goog.math'], false);
+goog.addDependency('math/coordinate3.js', ['goog.math.Coordinate3'], [], false);
+goog.addDependency('math/coordinate3_test.js', ['goog.math.Coordinate3Test'], ['goog.math.Coordinate3', 'goog.testing.jsunit'], false);
+goog.addDependency('math/coordinate_test.js', ['goog.math.CoordinateTest'], ['goog.math.Coordinate', 'goog.testing.jsunit'], false);
+goog.addDependency('math/exponentialbackoff.js', ['goog.math.ExponentialBackoff'], ['goog.asserts'], false);
+goog.addDependency('math/exponentialbackoff_test.js', ['goog.math.ExponentialBackoffTest'], ['goog.math.ExponentialBackoff', 'goog.testing.jsunit'], false);
+goog.addDependency('math/integer.js', ['goog.math.Integer'], [], false);
+goog.addDependency('math/integer_test.js', ['goog.math.IntegerTest'], ['goog.math.Integer', 'goog.testing.jsunit'], false);
+goog.addDependency('math/interpolator/interpolator1.js', ['goog.math.interpolator.Interpolator1'], [], false);
+goog.addDependency('math/interpolator/linear1.js', ['goog.math.interpolator.Linear1'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.interpolator.Interpolator1'], false);
+goog.addDependency('math/interpolator/linear1_test.js', ['goog.math.interpolator.Linear1Test'], ['goog.math.interpolator.Linear1', 'goog.testing.jsunit'], false);
+goog.addDependency('math/interpolator/pchip1.js', ['goog.math.interpolator.Pchip1'], ['goog.math', 'goog.math.interpolator.Spline1'], false);
+goog.addDependency('math/interpolator/pchip1_test.js', ['goog.math.interpolator.Pchip1Test'], ['goog.math.interpolator.Pchip1', 'goog.testing.jsunit'], false);
+goog.addDependency('math/interpolator/spline1.js', ['goog.math.interpolator.Spline1'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.interpolator.Interpolator1', 'goog.math.tdma'], false);
+goog.addDependency('math/interpolator/spline1_test.js', ['goog.math.interpolator.Spline1Test'], ['goog.math.interpolator.Spline1', 'goog.testing.jsunit'], false);
+goog.addDependency('math/line.js', ['goog.math.Line'], ['goog.math', 'goog.math.Coordinate'], false);
+goog.addDependency('math/line_test.js', ['goog.math.LineTest'], ['goog.math.Coordinate', 'goog.math.Line', 'goog.testing.jsunit'], false);
+goog.addDependency('math/long.js', ['goog.math.Long'], [], false);
+goog.addDependency('math/long_test.js', ['goog.math.LongTest'], ['goog.math.Long', 'goog.testing.jsunit'], false);
+goog.addDependency('math/math.js', ['goog.math'], ['goog.array', 'goog.asserts'], false);
+goog.addDependency('math/math_test.js', ['goog.mathTest'], ['goog.math', 'goog.testing.jsunit'], false);
+goog.addDependency('math/matrix.js', ['goog.math.Matrix'], ['goog.array', 'goog.math', 'goog.math.Size', 'goog.string'], false);
+goog.addDependency('math/matrix_test.js', ['goog.math.MatrixTest'], ['goog.math.Matrix', 'goog.testing.jsunit'], false);
+goog.addDependency('math/path.js', ['goog.math.Path', 'goog.math.Path.Segment'], ['goog.array', 'goog.math'], false);
+goog.addDependency('math/path_test.js', ['goog.math.PathTest'], ['goog.array', 'goog.math.AffineTransform', 'goog.math.Path', 'goog.testing.jsunit'], false);
+goog.addDependency('math/paths.js', ['goog.math.paths'], ['goog.math.Coordinate', 'goog.math.Path'], false);
+goog.addDependency('math/paths_test.js', ['goog.math.pathsTest'], ['goog.math.Coordinate', 'goog.math.paths', 'goog.testing.jsunit'], false);
+goog.addDependency('math/range.js', ['goog.math.Range'], ['goog.asserts'], false);
+goog.addDependency('math/range_test.js', ['goog.math.RangeTest'], ['goog.math.Range', 'goog.testing.jsunit'], false);
+goog.addDependency('math/rangeset.js', ['goog.math.RangeSet'], ['goog.array', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.math.Range'], false);
+goog.addDependency('math/rangeset_test.js', ['goog.math.RangeSetTest'], ['goog.iter', 'goog.math.Range', 'goog.math.RangeSet', 'goog.testing.jsunit'], false);
+goog.addDependency('math/rect.js', ['goog.math.Rect'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size'], false);
+goog.addDependency('math/rect_test.js', ['goog.math.RectTest'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.testing.jsunit'], false);
+goog.addDependency('math/size.js', ['goog.math.Size'], [], false);
+goog.addDependency('math/size_test.js', ['goog.math.SizeTest'], ['goog.math.Size', 'goog.testing.jsunit'], false);
+goog.addDependency('math/tdma.js', ['goog.math.tdma'], [], false);
+goog.addDependency('math/tdma_test.js', ['goog.math.tdmaTest'], ['goog.math.tdma', 'goog.testing.jsunit'], false);
+goog.addDependency('math/vec2.js', ['goog.math.Vec2'], ['goog.math', 'goog.math.Coordinate'], false);
+goog.addDependency('math/vec2_test.js', ['goog.math.Vec2Test'], ['goog.math.Vec2', 'goog.testing.jsunit'], false);
+goog.addDependency('math/vec3.js', ['goog.math.Vec3'], ['goog.math', 'goog.math.Coordinate3'], false);
+goog.addDependency('math/vec3_test.js', ['goog.math.Vec3Test'], ['goog.math.Coordinate3', 'goog.math.Vec3', 'goog.testing.jsunit'], false);
+goog.addDependency('memoize/memoize.js', ['goog.memoize'], [], false);
+goog.addDependency('memoize/memoize_test.js', ['goog.memoizeTest'], ['goog.memoize', 'goog.testing.jsunit'], false);
+goog.addDependency('messaging/abstractchannel.js', ['goog.messaging.AbstractChannel'], ['goog.Disposable', 'goog.json', 'goog.log', 'goog.messaging.MessageChannel'], false);
+goog.addDependency('messaging/abstractchannel_test.js', ['goog.messaging.AbstractChannelTest'], ['goog.messaging.AbstractChannel', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit'], false);
+goog.addDependency('messaging/bufferedchannel.js', ['goog.messaging.BufferedChannel'], ['goog.Disposable', 'goog.Timer', 'goog.events', 'goog.log', 'goog.messaging.MessageChannel', 'goog.messaging.MultiChannel'], false);
+goog.addDependency('messaging/bufferedchannel_test.js', ['goog.messaging.BufferedChannelTest'], ['goog.debug.Console', 'goog.dom', 'goog.dom.TagName', 'goog.log', 'goog.log.Level', 'goog.messaging.BufferedChannel', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/deferredchannel.js', ['goog.messaging.DeferredChannel'], ['goog.Disposable', 'goog.messaging.MessageChannel'], false);
+goog.addDependency('messaging/deferredchannel_test.js', ['goog.messaging.DeferredChannelTest'], ['goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/loggerclient.js', ['goog.messaging.LoggerClient'], ['goog.Disposable', 'goog.debug', 'goog.debug.LogManager', 'goog.debug.Logger'], false);
+goog.addDependency('messaging/loggerclient_test.js', ['goog.messaging.LoggerClientTest'], ['goog.debug', 'goog.debug.Logger', 'goog.messaging.LoggerClient', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/loggerserver.js', ['goog.messaging.LoggerServer'], ['goog.Disposable', 'goog.log', 'goog.log.Level'], false);
+goog.addDependency('messaging/loggerserver_test.js', ['goog.messaging.LoggerServerTest'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.log', 'goog.log.Level', 'goog.messaging.LoggerServer', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/messagechannel.js', ['goog.messaging.MessageChannel'], [], false);
+goog.addDependency('messaging/messaging.js', ['goog.messaging'], [], false);
+goog.addDependency('messaging/messaging_test.js', ['goog.testing.messaging.MockMessageChannelTest'], ['goog.messaging', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/multichannel.js', ['goog.messaging.MultiChannel', 'goog.messaging.MultiChannel.VirtualChannel'], ['goog.Disposable', 'goog.log', 'goog.messaging.MessageChannel', 'goog.object'], false);
+goog.addDependency('messaging/multichannel_test.js', ['goog.messaging.MultiChannelTest'], ['goog.messaging.MultiChannel', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel', 'goog.testing.mockmatchers.IgnoreArgument'], false);
+goog.addDependency('messaging/portcaller.js', ['goog.messaging.PortCaller'], ['goog.Disposable', 'goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object'], false);
+goog.addDependency('messaging/portcaller_test.js', ['goog.messaging.PortCallerTest'], ['goog.events.EventTarget', 'goog.messaging.PortCaller', 'goog.messaging.PortNetwork', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/portchannel.js', ['goog.messaging.PortChannel'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.debug', 'goog.events', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.messaging.AbstractChannel', 'goog.messaging.DeferredChannel', 'goog.object', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('messaging/portnetwork.js', ['goog.messaging.PortNetwork'], [], false);
+goog.addDependency('messaging/portoperator.js', ['goog.messaging.PortOperator'], ['goog.Disposable', 'goog.asserts', 'goog.log', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object'], false);
+goog.addDependency('messaging/portoperator_test.js', ['goog.messaging.PortOperatorTest'], ['goog.messaging.PortNetwork', 'goog.messaging.PortOperator', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel', 'goog.testing.messaging.MockMessagePort'], false);
+goog.addDependency('messaging/respondingchannel.js', ['goog.messaging.RespondingChannel'], ['goog.Disposable', 'goog.log', 'goog.messaging.MultiChannel'], false);
+goog.addDependency('messaging/respondingchannel_test.js', ['goog.messaging.RespondingChannelTest'], ['goog.messaging.RespondingChannel', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('messaging/testdata/portchannel_worker.js', ['goog.messaging.testdata.portchannel_worker'], ['goog.messaging.PortChannel'], false);
+goog.addDependency('messaging/testdata/portnetwork_worker1.js', ['goog.messaging.testdata.portnetwork_worker1'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel'], false);
+goog.addDependency('messaging/testdata/portnetwork_worker2.js', ['goog.messaging.testdata.portnetwork_worker2'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel'], false);
+goog.addDependency('module/abstractmoduleloader.js', ['goog.module.AbstractModuleLoader'], ['goog.module'], false);
+goog.addDependency('module/basemodule.js', ['goog.module.BaseModule'], ['goog.Disposable', 'goog.module'], false);
+goog.addDependency('module/loader.js', ['goog.module.Loader'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.module', 'goog.object'], false);
+goog.addDependency('module/module.js', ['goog.module'], [], false);
+goog.addDependency('module/moduleinfo.js', ['goog.module.ModuleInfo'], ['goog.Disposable', 'goog.async.throwException', 'goog.functions', 'goog.module', 'goog.module.BaseModule', 'goog.module.ModuleLoadCallback'], false);
+goog.addDependency('module/moduleinfo_test.js', ['goog.module.ModuleInfoTest'], ['goog.module.BaseModule', 'goog.module.ModuleInfo', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('module/moduleloadcallback.js', ['goog.module.ModuleLoadCallback'], ['goog.debug.entryPointRegistry', 'goog.debug.errorHandlerWeakDep', 'goog.module'], false);
+goog.addDependency('module/moduleloadcallback_test.js', ['goog.module.ModuleLoadCallbackTest'], ['goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.functions', 'goog.module.ModuleLoadCallback', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('module/moduleloader.js', ['goog.module.ModuleLoader'], ['goog.Timer', 'goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.labs.userAgent.browser', 'goog.log', 'goog.module.AbstractModuleLoader', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.net.jsloader', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('module/moduleloader_test.js', ['goog.module.ModuleLoaderTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.functions', 'goog.module.ModuleLoader', 'goog.module.ModuleManager', 'goog.net.BulkLoader', 'goog.net.XmlHttp', 'goog.object', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.events.EventObserver', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('module/modulemanager.js', ['goog.module.ModuleManager', 'goog.module.ModuleManager.CallbackType', 'goog.module.ModuleManager.FailureType'], ['goog.Disposable', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.debug.Trace', 'goog.dispose', 'goog.log', 'goog.module', 'goog.module.ModuleInfo', 'goog.module.ModuleLoadCallback', 'goog.object'], false);
+goog.addDependency('module/modulemanager_test.js', ['goog.module.ModuleManagerTest'], ['goog.array', 'goog.functions', 'goog.module.BaseModule', 'goog.module.ModuleManager', 'goog.testing', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('module/testdata/modA_1.js', ['goog.module.testdata.modA_1'], [], false);
+goog.addDependency('module/testdata/modA_2.js', ['goog.module.testdata.modA_2'], ['goog.module.ModuleManager'], false);
+goog.addDependency('module/testdata/modB_1.js', ['goog.module.testdata.modB_1'], ['goog.module.ModuleManager'], false);
+goog.addDependency('net/browserchannel.js', ['goog.net.BrowserChannel', 'goog.net.BrowserChannel.Error', 'goog.net.BrowserChannel.Event', 'goog.net.BrowserChannel.Handler', 'goog.net.BrowserChannel.LogSaver', 'goog.net.BrowserChannel.QueuedMap', 'goog.net.BrowserChannel.ServerReachability', 'goog.net.BrowserChannel.ServerReachabilityEvent', 'goog.net.BrowserChannel.Stat', 'goog.net.BrowserChannel.StatEvent', 'goog.net.BrowserChannel.State', 'goog.net.BrowserChannel.TimingEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.TextFormatter', 'goog.events.Event', 'goog.events.EventTarget', 'goog.json', 'goog.json.EvalJsonProcessor', 'goog.log', 'goog.net.BrowserTestChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.XhrIo', 'goog.net.tmpnetwork', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer'], false);
+goog.addDependency('net/browserchannel_test.js', ['goog.net.BrowserChannelTest'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.functions', 'goog.json', 'goog.net.BrowserChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.tmpnetwork', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/browsertestchannel.js', ['goog.net.BrowserTestChannel'], ['goog.json.EvalJsonProcessor', 'goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error', 'goog.net.tmpnetwork', 'goog.string.Parser', 'goog.userAgent'], false);
+goog.addDependency('net/bulkloader.js', ['goog.net.BulkLoader'], ['goog.events.EventHandler', 'goog.events.EventTarget', 'goog.log', 'goog.net.BulkLoaderHelper', 'goog.net.EventType', 'goog.net.XhrIo'], false);
+goog.addDependency('net/bulkloader_test.js', ['goog.net.BulkLoaderTest'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('net/bulkloaderhelper.js', ['goog.net.BulkLoaderHelper'], ['goog.Disposable', 'goog.log'], false);
+goog.addDependency('net/channeldebug.js', ['goog.net.ChannelDebug'], ['goog.json', 'goog.log'], false);
+goog.addDependency('net/channelrequest.js', ['goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error'], ['goog.Timer', 'goog.async.Throttle', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.userAgent'], false);
+goog.addDependency('net/channelrequest_test.js', ['goog.net.ChannelRequestTest'], ['goog.Uri', 'goog.functions', 'goog.net.BrowserChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/cookies.js', ['goog.net.Cookies', 'goog.net.cookies'], [], false);
+goog.addDependency('net/cookies_test.js', ['goog.net.cookiesTest'], ['goog.array', 'goog.net.cookies', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('net/corsxmlhttpfactory.js', ['goog.net.CorsXmlHttpFactory', 'goog.net.IeCorsXhrAdapter'], ['goog.net.HttpStatus', 'goog.net.XhrLike', 'goog.net.XmlHttp', 'goog.net.XmlHttpFactory'], false);
+goog.addDependency('net/corsxmlhttpfactory_test.js', ['goog.net.CorsXmlHttpFactoryTest'], ['goog.net.CorsXmlHttpFactory', 'goog.net.IeCorsXhrAdapter', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('net/crossdomainrpc.js', ['goog.net.CrossDomainRpc'], ['goog.Uri', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.html.legacyconversions', 'goog.json', 'goog.log', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('net/crossdomainrpc_test.js', ['goog.net.CrossDomainRpcTest'], ['goog.log', 'goog.log.Level', 'goog.net.CrossDomainRpc', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('net/errorcode.js', ['goog.net.ErrorCode'], [], false);
+goog.addDependency('net/eventtype.js', ['goog.net.EventType'], [], false);
+goog.addDependency('net/filedownloader.js', ['goog.net.FileDownloader', 'goog.net.FileDownloader.Error'], ['goog.Disposable', 'goog.asserts', 'goog.async.Deferred', 'goog.crypt.hash32', 'goog.debug.Error', 'goog.events', 'goog.events.EventHandler', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.object'], false);
+goog.addDependency('net/filedownloader_test.js', ['goog.net.FileDownloaderTest'], ['goog.fs.Error', 'goog.net.ErrorCode', 'goog.net.FileDownloader', 'goog.net.XhrIo', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.fs', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit', 'goog.testing.net.XhrIoPool'], false);
+goog.addDependency('net/httpstatus.js', ['goog.net.HttpStatus'], [], false);
+goog.addDependency('net/iframe_xhr_test.js', ['goog.net.iframeXhrTest'], ['goog.Timer', 'goog.debug.Console', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.TagName', 'goog.events', 'goog.net.IframeIo', 'goog.net.XhrIo', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('net/iframeio.js', ['goog.net.IframeIo', 'goog.net.IframeIo.IncrementalDataEvent'], ['goog.Timer', 'goog.Uri', 'goog.asserts', 'goog.debug', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.html.uncheckedconversions', 'goog.json', 'goog.log', 'goog.log.Level', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.reflect', 'goog.string', 'goog.string.Const', 'goog.structs', 'goog.userAgent'], false);
+goog.addDependency('net/iframeio_different_base_test.js', ['goog.net.iframeIoDifferentBaseTest'], ['goog.events', 'goog.net.EventType', 'goog.net.IframeIo', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('net/iframeio_test.js', ['goog.net.IframeIoTest'], ['goog.debug', 'goog.debug.DivConsole', 'goog.debug.LogManager', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.log', 'goog.log.Level', 'goog.net.IframeIo', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('net/iframeloadmonitor.js', ['goog.net.IframeLoadMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent'], false);
+goog.addDependency('net/iframeloadmonitor_test.js', ['goog.net.IframeLoadMonitorTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.net.IframeLoadMonitor', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('net/imageloader.js', ['goog.net.ImageLoader'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.EventType', 'goog.object', 'goog.userAgent'], false);
+goog.addDependency('net/imageloader_test.js', ['goog.net.ImageLoaderTest'], ['goog.Timer', 'goog.array', 'goog.dispose', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.net.EventType', 'goog.net.ImageLoader', 'goog.object', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/ipaddress.js', ['goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address'], ['goog.array', 'goog.math.Integer', 'goog.object', 'goog.string'], false);
+goog.addDependency('net/ipaddress_test.js', ['goog.net.IpAddressTest'], ['goog.math.Integer', 'goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address', 'goog.testing.jsunit'], false);
+goog.addDependency('net/jsloader.js', ['goog.net.jsloader', 'goog.net.jsloader.Error', 'goog.net.jsloader.ErrorCode', 'goog.net.jsloader.Options'], ['goog.array', 'goog.async.Deferred', 'goog.debug.Error', 'goog.dom', 'goog.dom.TagName'], false);
+goog.addDependency('net/jsloader_test.js', ['goog.net.jsloaderTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.net.jsloader', 'goog.net.jsloader.ErrorCode', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('net/jsonp.js', ['goog.net.Jsonp'], ['goog.Uri', 'goog.net.jsloader'], false);
+goog.addDependency('net/jsonp_test.js', ['goog.net.JsonpTest'], ['goog.net.Jsonp', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('net/mockiframeio.js', ['goog.net.MockIFrameIo'], ['goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.IframeIo'], false);
+goog.addDependency('net/multiiframeloadmonitor.js', ['goog.net.MultiIframeLoadMonitor'], ['goog.events', 'goog.net.IframeLoadMonitor'], false);
+goog.addDependency('net/multiiframeloadmonitor_test.js', ['goog.net.MultiIframeLoadMonitorTest'], ['goog.dom', 'goog.dom.TagName', 'goog.net.IframeLoadMonitor', 'goog.net.MultiIframeLoadMonitor', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('net/networkstatusmonitor.js', ['goog.net.NetworkStatusMonitor'], ['goog.events.Listenable'], false);
+goog.addDependency('net/networktester.js', ['goog.net.NetworkTester'], ['goog.Timer', 'goog.Uri', 'goog.log'], false);
+goog.addDependency('net/networktester_test.js', ['goog.net.NetworkTesterTest'], ['goog.Uri', 'goog.net.NetworkTester', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('net/testdata/jsloader_test1.js', ['goog.net.testdata.jsloader_test1'], [], false);
+goog.addDependency('net/testdata/jsloader_test2.js', ['goog.net.testdata.jsloader_test2'], [], false);
+goog.addDependency('net/testdata/jsloader_test3.js', ['goog.net.testdata.jsloader_test3'], [], false);
+goog.addDependency('net/testdata/jsloader_test4.js', ['goog.net.testdata.jsloader_test4'], [], false);
+goog.addDependency('net/tmpnetwork.js', ['goog.net.tmpnetwork'], ['goog.Uri', 'goog.net.ChannelDebug'], false);
+goog.addDependency('net/websocket.js', ['goog.net.WebSocket', 'goog.net.WebSocket.ErrorEvent', 'goog.net.WebSocket.EventType', 'goog.net.WebSocket.MessageEvent'], ['goog.Timer', 'goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.log'], false);
+goog.addDependency('net/websocket_test.js', ['goog.net.WebSocketTest'], ['goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.functions', 'goog.net.WebSocket', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/wrapperxmlhttpfactory.js', ['goog.net.WrapperXmlHttpFactory'], ['goog.net.XhrLike', 'goog.net.XmlHttpFactory'], false);
+goog.addDependency('net/xhrio.js', ['goog.net.XhrIo', 'goog.net.XhrIo.ResponseType'], ['goog.Timer', 'goog.array', 'goog.debug.entryPointRegistry', 'goog.events.EventTarget', 'goog.json', 'goog.log', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.userAgent'], false);
+goog.addDependency('net/xhrio_test.js', ['goog.net.XhrIoTest'], ['goog.Uri', 'goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.functions', 'goog.net.EventType', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/xhriopool.js', ['goog.net.XhrIoPool'], ['goog.net.XhrIo', 'goog.structs.PriorityPool'], false);
+goog.addDependency('net/xhrlike.js', ['goog.net.XhrLike'], [], false);
+goog.addDependency('net/xhrmanager.js', ['goog.net.XhrManager', 'goog.net.XhrManager.Event', 'goog.net.XhrManager.Request'], ['goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.structs.Map'], false);
+goog.addDependency('net/xhrmanager_test.js', ['goog.net.XhrManagerTest'], ['goog.events', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrManager', 'goog.testing.jsunit', 'goog.testing.net.XhrIoPool', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/xmlhttp.js', ['goog.net.DefaultXmlHttpFactory', 'goog.net.XmlHttp', 'goog.net.XmlHttp.OptionType', 'goog.net.XmlHttp.ReadyState', 'goog.net.XmlHttpDefines'], ['goog.asserts', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttpFactory'], false);
+goog.addDependency('net/xmlhttpfactory.js', ['goog.net.XmlHttpFactory'], ['goog.net.XhrLike'], false);
+goog.addDependency('net/xpc/crosspagechannel.js', ['goog.net.xpc.CrossPageChannel'], ['goog.Uri', 'goog.async.Deferred', 'goog.async.Delay', 'goog.dispose', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.messaging.AbstractChannel', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.DirectTransport', 'goog.net.xpc.FrameElementMethodTransport', 'goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframeRelayTransport', 'goog.net.xpc.NativeMessagingTransport', 'goog.net.xpc.NixTransport', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields', 'goog.string', 'goog.uri.utils', 'goog.userAgent'], false);
+goog.addDependency('net/xpc/crosspagechannel_test.js', ['goog.net.xpc.CrossPageChannelTest'], ['goog.Disposable', 'goog.Uri', 'goog.async.Deferred', 'goog.dom', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.object', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('net/xpc/crosspagechannelrole.js', ['goog.net.xpc.CrossPageChannelRole'], [], false);
+goog.addDependency('net/xpc/directtransport.js', ['goog.net.xpc.DirectTransport'], ['goog.Timer', 'goog.async.Deferred', 'goog.events.EventHandler', 'goog.log', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.object'], false);
+goog.addDependency('net/xpc/directtransport_test.js', ['goog.net.xpc.DirectTransportTest'], ['goog.dom', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('net/xpc/frameelementmethodtransport.js', ['goog.net.xpc.FrameElementMethodTransport'], ['goog.log', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes'], false);
+goog.addDependency('net/xpc/iframepollingtransport.js', ['goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframePollingTransport.Receiver', 'goog.net.xpc.IframePollingTransport.Sender'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.userAgent'], false);
+goog.addDependency('net/xpc/iframepollingtransport_test.js', ['goog.net.xpc.IframePollingTransportTest'], ['goog.Timer', 'goog.dom', 'goog.dom.TagName', 'goog.functions', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.object', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('net/xpc/iframerelaytransport.js', ['goog.net.xpc.IframeRelayTransport'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.html.SafeHtml', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.string', 'goog.string.Const', 'goog.userAgent'], false);
+goog.addDependency('net/xpc/nativemessagingtransport.js', ['goog.net.xpc.NativeMessagingTransport'], ['goog.Timer', 'goog.asserts', 'goog.async.Deferred', 'goog.events', 'goog.events.EventHandler', 'goog.log', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes'], false);
+goog.addDependency('net/xpc/nativemessagingtransport_test.js', ['goog.net.xpc.NativeMessagingTransportTest'], ['goog.dom', 'goog.events', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.NativeMessagingTransport', 'goog.testing.jsunit'], false);
+goog.addDependency('net/xpc/nixtransport.js', ['goog.net.xpc.NixTransport'], ['goog.log', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.reflect'], false);
+goog.addDependency('net/xpc/relay.js', ['goog.net.xpc.relay'], [], false);
+goog.addDependency('net/xpc/transport.js', ['goog.net.xpc.Transport'], ['goog.Disposable', 'goog.dom', 'goog.net.xpc.TransportNames'], false);
+goog.addDependency('net/xpc/xpc.js', ['goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.TransportNames', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields'], ['goog.log'], false);
+goog.addDependency('object/object.js', ['goog.object'], [], false);
+goog.addDependency('object/object_test.js', ['goog.objectTest'], ['goog.functions', 'goog.object', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('positioning/absoluteposition.js', ['goog.positioning.AbsolutePosition'], ['goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition'], false);
+goog.addDependency('positioning/abstractposition.js', ['goog.positioning.AbstractPosition'], [], false);
+goog.addDependency('positioning/anchoredposition.js', ['goog.positioning.AnchoredPosition'], ['goog.positioning', 'goog.positioning.AbstractPosition'], false);
+goog.addDependency('positioning/anchoredposition_test.js', ['goog.positioning.AnchoredPositionTest'], ['goog.dom', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.jsunit'], false);
+goog.addDependency('positioning/anchoredviewportposition.js', ['goog.positioning.AnchoredViewportPosition'], ['goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus'], false);
+goog.addDependency('positioning/anchoredviewportposition_test.js', ['goog.positioning.AnchoredViewportPositionTest'], ['goog.dom', 'goog.math.Box', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.OverflowStatus', 'goog.style', 'goog.testing.jsunit'], false);
+goog.addDependency('positioning/clientposition.js', ['goog.positioning.ClientPosition'], ['goog.asserts', 'goog.dom', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.style'], false);
+goog.addDependency('positioning/clientposition_test.js', ['goog.positioning.clientPositionTest'], ['goog.dom', 'goog.dom.TagName', 'goog.positioning.ClientPosition', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit'], false);
+goog.addDependency('positioning/menuanchoredposition.js', ['goog.positioning.MenuAnchoredPosition'], ['goog.positioning.AnchoredViewportPosition', 'goog.positioning.Overflow'], false);
+goog.addDependency('positioning/menuanchoredposition_test.js', ['goog.positioning.MenuAnchoredPositionTest'], ['goog.dom', 'goog.dom.TagName', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.testing.jsunit'], false);
+goog.addDependency('positioning/positioning.js', ['goog.positioning', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.style.bidi'], false);
+goog.addDependency('positioning/positioning_test.js', ['goog.positioningTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('positioning/viewportclientposition.js', ['goog.positioning.ViewportClientPosition'], ['goog.dom', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.ClientPosition', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.style'], false);
+goog.addDependency('positioning/viewportclientposition_test.js', ['goog.positioning.ViewportClientPositionTest'], ['goog.dom', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.style', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('positioning/viewportposition.js', ['goog.positioning.ViewportPosition'], ['goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.positioning.Corner', 'goog.style'], false);
+goog.addDependency('promise/promise.js', ['goog.Promise'], ['goog.Thenable', 'goog.asserts', 'goog.async.FreeList', 'goog.async.run', 'goog.async.throwException', 'goog.debug.Error', 'goog.promise.Resolver'], false);
+goog.addDependency('promise/promise_test.js', ['goog.PromiseTest'], ['goog.Promise', 'goog.Thenable', 'goog.functions', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('promise/resolver.js', ['goog.promise.Resolver'], [], false);
+goog.addDependency('promise/testsuiteadapter.js', ['goog.promise.testSuiteAdapter'], ['goog.Promise'], false);
+goog.addDependency('promise/thenable.js', ['goog.Thenable'], [], false);
+goog.addDependency('proto/proto.js', ['goog.proto'], ['goog.proto.Serializer'], false);
+goog.addDependency('proto/serializer.js', ['goog.proto.Serializer'], ['goog.json.Serializer', 'goog.string'], false);
+goog.addDependency('proto/serializer_test.js', ['goog.protoTest'], ['goog.proto', 'goog.testing.jsunit'], false);
+goog.addDependency('proto2/descriptor.js', ['goog.proto2.Descriptor', 'goog.proto2.Metadata'], ['goog.array', 'goog.asserts', 'goog.object', 'goog.string'], false);
+goog.addDependency('proto2/descriptor_test.js', ['goog.proto2.DescriptorTest'], ['goog.proto2.Descriptor', 'goog.proto2.Message', 'goog.testing.jsunit'], false);
+goog.addDependency('proto2/fielddescriptor.js', ['goog.proto2.FieldDescriptor'], ['goog.asserts', 'goog.string'], false);
+goog.addDependency('proto2/fielddescriptor_test.js', ['goog.proto2.FieldDescriptorTest'], ['goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.testing.jsunit'], false);
+goog.addDependency('proto2/lazydeserializer.js', ['goog.proto2.LazyDeserializer'], ['goog.asserts', 'goog.proto2.Message', 'goog.proto2.Serializer'], false);
+goog.addDependency('proto2/message.js', ['goog.proto2.Message'], ['goog.asserts', 'goog.proto2.Descriptor', 'goog.proto2.FieldDescriptor'], false);
+goog.addDependency('proto2/message_test.js', ['goog.proto2.MessageTest'], ['goog.testing.jsunit', 'proto2.TestAllTypes', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup'], false);
+goog.addDependency('proto2/objectserializer.js', ['goog.proto2.ObjectSerializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.Serializer', 'goog.string'], false);
+goog.addDependency('proto2/objectserializer_test.js', ['goog.proto2.ObjectSerializerTest'], ['goog.proto2.ObjectSerializer', 'goog.proto2.Serializer', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'proto2.TestAllTypes'], false);
+goog.addDependency('proto2/package_test.pb.js', ['someprotopackage.TestPackageTypes'], ['goog.proto2.Message', 'proto2.TestAllTypes'], false);
+goog.addDependency('proto2/pbliteserializer.js', ['goog.proto2.PbLiteSerializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.LazyDeserializer', 'goog.proto2.Serializer'], false);
+goog.addDependency('proto2/pbliteserializer_test.js', ['goog.proto2.PbLiteSerializerTest'], ['goog.proto2.PbLiteSerializer', 'goog.testing.jsunit', 'proto2.TestAllTypes'], false);
+goog.addDependency('proto2/proto_test.js', ['goog.proto2.messageTest'], ['goog.proto2.FieldDescriptor', 'goog.testing.jsunit', 'proto2.TestAllTypes', 'someprotopackage.TestPackageTypes'], false);
+goog.addDependency('proto2/serializer.js', ['goog.proto2.Serializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message'], false);
+goog.addDependency('proto2/test.pb.js', ['proto2.TestAllTypes', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup', 'proto2.TestDefaultChild', 'proto2.TestDefaultParent'], ['goog.proto2.Message'], false);
+goog.addDependency('proto2/textformatserializer.js', ['goog.proto2.TextFormatSerializer'], ['goog.array', 'goog.asserts', 'goog.json', 'goog.math', 'goog.object', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.proto2.Serializer', 'goog.string'], false);
+goog.addDependency('proto2/textformatserializer_test.js', ['goog.proto2.TextFormatSerializerTest'], ['goog.proto2.ObjectSerializer', 'goog.proto2.TextFormatSerializer', 'goog.testing.jsunit', 'proto2.TestAllTypes'], false);
+goog.addDependency('proto2/util.js', ['goog.proto2.Util'], ['goog.asserts'], false);
+goog.addDependency('pubsub/pubsub.js', ['goog.pubsub.PubSub'], ['goog.Disposable', 'goog.array'], false);
+goog.addDependency('pubsub/pubsub_test.js', ['goog.pubsub.PubSubTest'], ['goog.array', 'goog.pubsub.PubSub', 'goog.testing.jsunit'], false);
+goog.addDependency('pubsub/topicid.js', ['goog.pubsub.TopicId'], [], false);
+goog.addDependency('pubsub/typedpubsub.js', ['goog.pubsub.TypedPubSub'], ['goog.Disposable', 'goog.pubsub.PubSub'], false);
+goog.addDependency('pubsub/typedpubsub_test.js', ['goog.pubsub.TypedPubSubTest'], ['goog.array', 'goog.pubsub.TopicId', 'goog.pubsub.TypedPubSub', 'goog.testing.jsunit'], false);
+goog.addDependency('reflect/reflect.js', ['goog.reflect'], [], false);
+goog.addDependency('result/deferredadaptor.js', ['goog.result.DeferredAdaptor'], ['goog.async.Deferred', 'goog.result', 'goog.result.Result'], false);
+goog.addDependency('result/dependentresult.js', ['goog.result.DependentResult'], ['goog.result.Result'], false);
+goog.addDependency('result/result_interface.js', ['goog.result.Result'], ['goog.Thenable'], false);
+goog.addDependency('result/resultutil.js', ['goog.result'], ['goog.array', 'goog.result.DependentResult', 'goog.result.Result', 'goog.result.SimpleResult'], false);
+goog.addDependency('result/simpleresult.js', ['goog.result.SimpleResult', 'goog.result.SimpleResult.StateError'], ['goog.Promise', 'goog.Thenable', 'goog.debug.Error', 'goog.result.Result'], false);
+goog.addDependency('soy/data.js', ['goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind'], ['goog.html.SafeHtml', 'goog.html.uncheckedconversions', 'goog.string.Const'], false);
+goog.addDependency('soy/data_test.js', ['goog.soy.dataTest'], ['goog.html.SafeHtml', 'goog.soy.testHelper', 'goog.testing.jsunit'], false);
+goog.addDependency('soy/renderer.js', ['goog.soy.InjectedDataSupplier', 'goog.soy.Renderer'], ['goog.asserts', 'goog.dom', 'goog.soy', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind'], false);
+goog.addDependency('soy/renderer_test.js', ['goog.soy.RendererTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.html.SafeHtml', 'goog.i18n.bidi.Dir', 'goog.soy.Renderer', 'goog.soy.data.SanitizedContentKind', 'goog.soy.testHelper', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('soy/soy.js', ['goog.soy'], ['goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.string'], false);
+goog.addDependency('soy/soy_test.js', ['goog.soyTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.functions', 'goog.soy', 'goog.soy.testHelper', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('soy/soy_testhelper.js', ['goog.soy.testHelper'], ['goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi.Dir', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('spell/spellcheck.js', ['goog.spell.SpellCheck', 'goog.spell.SpellCheck.WordChangedEvent'], ['goog.Timer', 'goog.events.Event', 'goog.events.EventTarget', 'goog.structs.Set'], false);
+goog.addDependency('spell/spellcheck_test.js', ['goog.spell.SpellCheckTest'], ['goog.spell.SpellCheck', 'goog.testing.jsunit'], false);
+goog.addDependency('stats/basicstat.js', ['goog.stats.BasicStat'], ['goog.asserts', 'goog.log', 'goog.string.format', 'goog.structs.CircularBuffer'], false);
+goog.addDependency('stats/basicstat_test.js', ['goog.stats.BasicStatTest'], ['goog.array', 'goog.stats.BasicStat', 'goog.string.format', 'goog.testing.PseudoRandom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('storage/collectablestorage.js', ['goog.storage.CollectableStorage'], ['goog.array', 'goog.iter', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage', 'goog.storage.RichStorage'], false);
+goog.addDependency('storage/collectablestorage_test.js', ['goog.storage.CollectableStorageTest'], ['goog.storage.CollectableStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false);
+goog.addDependency('storage/collectablestoragetester.js', ['goog.storage.collectableStorageTester'], ['goog.testing.asserts'], false);
+goog.addDependency('storage/encryptedstorage.js', ['goog.storage.EncryptedStorage'], ['goog.crypt', 'goog.crypt.Arc4', 'goog.crypt.Sha1', 'goog.crypt.base64', 'goog.json', 'goog.json.Serializer', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage'], false);
+goog.addDependency('storage/encryptedstorage_test.js', ['goog.storage.EncryptedStorageTest'], ['goog.json', 'goog.storage.EncryptedStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.PseudoRandom', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false);
+goog.addDependency('storage/errorcode.js', ['goog.storage.ErrorCode'], [], false);
+goog.addDependency('storage/expiringstorage.js', ['goog.storage.ExpiringStorage'], ['goog.storage.RichStorage'], false);
+goog.addDependency('storage/expiringstorage_test.js', ['goog.storage.ExpiringStorageTest'], ['goog.storage.ExpiringStorage', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false);
+goog.addDependency('storage/mechanism/errorcode.js', ['goog.storage.mechanism.ErrorCode'], [], false);
+goog.addDependency('storage/mechanism/errorhandlingmechanism.js', ['goog.storage.mechanism.ErrorHandlingMechanism'], ['goog.storage.mechanism.Mechanism'], false);
+goog.addDependency('storage/mechanism/errorhandlingmechanism_test.js', ['goog.storage.mechanism.ErrorHandlingMechanismTest'], ['goog.storage.mechanism.ErrorHandlingMechanism', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('storage/mechanism/html5localstorage.js', ['goog.storage.mechanism.HTML5LocalStorage'], ['goog.storage.mechanism.HTML5WebStorage'], false);
+goog.addDependency('storage/mechanism/html5localstorage_test.js', ['goog.storage.mechanism.HTML5LocalStorageTest'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('storage/mechanism/html5sessionstorage.js', ['goog.storage.mechanism.HTML5SessionStorage'], ['goog.storage.mechanism.HTML5WebStorage'], false);
+goog.addDependency('storage/mechanism/html5sessionstorage_test.js', ['goog.storage.mechanism.HTML5SessionStorageTest'], ['goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('storage/mechanism/html5webstorage.js', ['goog.storage.mechanism.HTML5WebStorage'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism'], false);
+goog.addDependency('storage/mechanism/html5webstorage_test.js', ['goog.storage.mechanism.HTML5MockStorage', 'goog.storage.mechanism.HTML5WebStorageTest', 'goog.storage.mechanism.MockThrowableStorage'], ['goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.HTML5WebStorage', 'goog.testing.jsunit'], false);
+goog.addDependency('storage/mechanism/ieuserdata.js', ['goog.storage.mechanism.IEUserData'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism', 'goog.structs.Map', 'goog.userAgent'], false);
+goog.addDependency('storage/mechanism/ieuserdata_test.js', ['goog.storage.mechanism.IEUserDataTest'], ['goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('storage/mechanism/iterablemechanism.js', ['goog.storage.mechanism.IterableMechanism'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.mechanism.Mechanism'], false);
+goog.addDependency('storage/mechanism/iterablemechanismtester.js', ['goog.storage.mechanism.iterableMechanismTester'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism', 'goog.testing.asserts'], false);
+goog.addDependency('storage/mechanism/mechanism.js', ['goog.storage.mechanism.Mechanism'], [], false);
+goog.addDependency('storage/mechanism/mechanismfactory.js', ['goog.storage.mechanism.mechanismfactory'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.PrefixedMechanism'], false);
+goog.addDependency('storage/mechanism/mechanismfactory_test.js', ['goog.storage.mechanism.mechanismfactoryTest'], ['goog.storage.mechanism.mechanismfactory', 'goog.testing.jsunit'], false);
+goog.addDependency('storage/mechanism/mechanismseparationtester.js', ['goog.storage.mechanism.mechanismSeparationTester'], ['goog.iter.StopIteration', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.asserts'], false);
+goog.addDependency('storage/mechanism/mechanismsharingtester.js', ['goog.storage.mechanism.mechanismSharingTester'], ['goog.iter.StopIteration', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.asserts'], false);
+goog.addDependency('storage/mechanism/mechanismtestdefinition.js', ['goog.storage.mechanism.mechanismTestDefinition'], [], false);
+goog.addDependency('storage/mechanism/mechanismtester.js', ['goog.storage.mechanism.mechanismTester'], ['goog.storage.mechanism.ErrorCode', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('storage/mechanism/prefixedmechanism.js', ['goog.storage.mechanism.PrefixedMechanism'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism'], false);
+goog.addDependency('storage/mechanism/prefixedmechanism_test.js', ['goog.storage.mechanism.PrefixedMechanismTest'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.PrefixedMechanism', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.testing.jsunit'], false);
+goog.addDependency('storage/richstorage.js', ['goog.storage.RichStorage', 'goog.storage.RichStorage.Wrapper'], ['goog.storage.ErrorCode', 'goog.storage.Storage'], false);
+goog.addDependency('storage/richstorage_test.js', ['goog.storage.RichStorageTest'], ['goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.storage_test', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false);
+goog.addDependency('storage/storage.js', ['goog.storage.Storage'], ['goog.json', 'goog.storage.ErrorCode'], false);
+goog.addDependency('storage/storage_test.js', ['goog.storage.storage_test'], ['goog.structs.Map', 'goog.testing.asserts'], false);
+goog.addDependency('string/const.js', ['goog.string.Const'], ['goog.asserts', 'goog.string.TypedString'], false);
+goog.addDependency('string/const_test.js', ['goog.string.constTest'], ['goog.string.Const', 'goog.testing.jsunit'], false);
+goog.addDependency('string/linkify.js', ['goog.string.linkify'], ['goog.string'], false);
+goog.addDependency('string/linkify_test.js', ['goog.string.linkifyTest'], ['goog.dom.TagName', 'goog.string', 'goog.string.linkify', 'goog.testing.dom', 'goog.testing.jsunit'], false);
+goog.addDependency('string/newlines.js', ['goog.string.newlines', 'goog.string.newlines.Line'], ['goog.array'], false);
+goog.addDependency('string/newlines_test.js', ['goog.string.newlinesTest'], ['goog.string.newlines', 'goog.testing.jsunit'], false);
+goog.addDependency('string/parser.js', ['goog.string.Parser'], [], false);
+goog.addDependency('string/path.js', ['goog.string.path'], ['goog.array', 'goog.string'], false);
+goog.addDependency('string/path_test.js', ['goog.string.pathTest'], ['goog.string.path', 'goog.testing.jsunit'], false);
+goog.addDependency('string/string.js', ['goog.string', 'goog.string.Unicode'], [], false);
+goog.addDependency('string/string_test.js', ['goog.stringTest'], ['goog.dom.TagName', 'goog.functions', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false);
+goog.addDependency('string/stringbuffer.js', ['goog.string.StringBuffer'], [], false);
+goog.addDependency('string/stringbuffer_test.js', ['goog.string.StringBufferTest'], ['goog.string.StringBuffer', 'goog.testing.jsunit'], false);
+goog.addDependency('string/stringformat.js', ['goog.string.format'], ['goog.string'], false);
+goog.addDependency('string/stringformat_test.js', ['goog.string.formatTest'], ['goog.string.format', 'goog.testing.jsunit'], false);
+goog.addDependency('string/stringifier.js', ['goog.string.Stringifier'], [], false);
+goog.addDependency('string/typedstring.js', ['goog.string.TypedString'], [], false);
+goog.addDependency('structs/avltree.js', ['goog.structs.AvlTree', 'goog.structs.AvlTree.Node'], ['goog.structs.Collection'], false);
+goog.addDependency('structs/avltree_test.js', ['goog.structs.AvlTreeTest'], ['goog.array', 'goog.structs.AvlTree', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/circularbuffer.js', ['goog.structs.CircularBuffer'], [], false);
+goog.addDependency('structs/circularbuffer_test.js', ['goog.structs.CircularBufferTest'], ['goog.structs.CircularBuffer', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/collection.js', ['goog.structs.Collection'], [], false);
+goog.addDependency('structs/collection_test.js', ['goog.structs.CollectionTest'], ['goog.structs.AvlTree', 'goog.structs.Set', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/heap.js', ['goog.structs.Heap'], ['goog.array', 'goog.object', 'goog.structs.Node'], false);
+goog.addDependency('structs/heap_test.js', ['goog.structs.HeapTest'], ['goog.structs', 'goog.structs.Heap', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/inversionmap.js', ['goog.structs.InversionMap'], ['goog.array'], false);
+goog.addDependency('structs/inversionmap_test.js', ['goog.structs.InversionMapTest'], ['goog.structs.InversionMap', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/linkedmap.js', ['goog.structs.LinkedMap'], ['goog.structs.Map'], false);
+goog.addDependency('structs/linkedmap_test.js', ['goog.structs.LinkedMapTest'], ['goog.structs.LinkedMap', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('structs/map.js', ['goog.structs.Map'], ['goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.object'], false);
+goog.addDependency('structs/map_test.js', ['goog.structs.MapTest'], ['goog.iter', 'goog.structs', 'goog.structs.Map', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/node.js', ['goog.structs.Node'], [], false);
+goog.addDependency('structs/pool.js', ['goog.structs.Pool'], ['goog.Disposable', 'goog.structs.Queue', 'goog.structs.Set'], false);
+goog.addDependency('structs/pool_test.js', ['goog.structs.PoolTest'], ['goog.structs.Pool', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/prioritypool.js', ['goog.structs.PriorityPool'], ['goog.structs.Pool', 'goog.structs.PriorityQueue'], false);
+goog.addDependency('structs/prioritypool_test.js', ['goog.structs.PriorityPoolTest'], ['goog.structs.PriorityPool', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/priorityqueue.js', ['goog.structs.PriorityQueue'], ['goog.structs.Heap'], false);
+goog.addDependency('structs/priorityqueue_test.js', ['goog.structs.PriorityQueueTest'], ['goog.structs', 'goog.structs.PriorityQueue', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/quadtree.js', ['goog.structs.QuadTree', 'goog.structs.QuadTree.Node', 'goog.structs.QuadTree.Point'], ['goog.math.Coordinate'], false);
+goog.addDependency('structs/quadtree_test.js', ['goog.structs.QuadTreeTest'], ['goog.structs', 'goog.structs.QuadTree', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/queue.js', ['goog.structs.Queue'], ['goog.array'], false);
+goog.addDependency('structs/queue_test.js', ['goog.structs.QueueTest'], ['goog.structs.Queue', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/set.js', ['goog.structs.Set'], ['goog.structs', 'goog.structs.Collection', 'goog.structs.Map'], false);
+goog.addDependency('structs/set_test.js', ['goog.structs.SetTest'], ['goog.iter', 'goog.structs', 'goog.structs.Set', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/simplepool.js', ['goog.structs.SimplePool'], ['goog.Disposable'], false);
+goog.addDependency('structs/stringset.js', ['goog.structs.StringSet'], ['goog.asserts', 'goog.iter'], false);
+goog.addDependency('structs/stringset_test.js', ['goog.structs.StringSetTest'], ['goog.array', 'goog.iter', 'goog.structs.StringSet', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/structs.js', ['goog.structs'], ['goog.array', 'goog.object'], false);
+goog.addDependency('structs/structs_test.js', ['goog.structsTest'], ['goog.array', 'goog.dom.TagName', 'goog.structs', 'goog.structs.Map', 'goog.structs.Set', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/treenode.js', ['goog.structs.TreeNode'], ['goog.array', 'goog.asserts', 'goog.structs.Node'], false);
+goog.addDependency('structs/treenode_test.js', ['goog.structs.TreeNodeTest'], ['goog.structs.TreeNode', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/trie.js', ['goog.structs.Trie'], ['goog.object', 'goog.structs'], false);
+goog.addDependency('structs/trie_test.js', ['goog.structs.TrieTest'], ['goog.object', 'goog.structs', 'goog.structs.Trie', 'goog.testing.jsunit'], false);
+goog.addDependency('structs/weak/weak.js', ['goog.structs.weak'], ['goog.userAgent'], false);
+goog.addDependency('structs/weak/weak_test.js', ['goog.structs.weakTest'], ['goog.array', 'goog.structs.weak', 'goog.testing.jsunit'], false);
+goog.addDependency('style/bidi.js', ['goog.style.bidi'], ['goog.dom', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('style/bidi_test.js', ['goog.style.bidiTest'], ['goog.dom', 'goog.style', 'goog.style.bidi', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('style/cursor.js', ['goog.style.cursor'], ['goog.userAgent'], false);
+goog.addDependency('style/cursor_test.js', ['goog.style.cursorTest'], ['goog.style.cursor', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('style/style.js', ['goog.style'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.vendor', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('style/style_document_scroll_test.js', ['goog.style.style_document_scroll_test'], ['goog.dom', 'goog.style', 'goog.testing.jsunit'], false);
+goog.addDependency('style/style_test.js', ['goog.style_test'], ['goog.array', 'goog.color', 'goog.dom', 'goog.dom.TagName', 'goog.events.BrowserEvent', 'goog.labs.userAgent.util', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.MockUserAgent', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgentTestUtil', 'goog.userAgentTestUtil.UserAgents'], false);
+goog.addDependency('style/style_webkit_scrollbars_test.js', ['goog.style.webkitScrollbarsTest'], ['goog.asserts', 'goog.style', 'goog.styleScrollbarTester', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('style/stylescrollbartester.js', ['goog.styleScrollbarTester'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.asserts'], false);
+goog.addDependency('style/transform.js', ['goog.style.transform'], ['goog.functions', 'goog.math.Coordinate', 'goog.math.Coordinate3', 'goog.style', 'goog.userAgent', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('style/transform_test.js', ['goog.style.transformTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style.transform', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('style/transition.js', ['goog.style.transition', 'goog.style.transition.Css3Property'], ['goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.safe', 'goog.dom.vendor', 'goog.functions', 'goog.html.SafeHtml', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('style/transition_test.js', ['goog.style.transitionTest'], ['goog.style', 'goog.style.transition', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('test_module.js', ['goog.test_module'], ['goog.test_module_dep'], true);
+goog.addDependency('test_module_dep.js', ['goog.test_module_dep'], [], true);
+goog.addDependency('testing/asserts.js', ['goog.testing.JsUnitException', 'goog.testing.asserts', 'goog.testing.asserts.ArrayLike'], ['goog.testing.stacktrace'], false);
+goog.addDependency('testing/asserts_test.js', ['goog.testing.assertsTest'], ['goog.array', 'goog.dom', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.labs.userAgent.browser', 'goog.string', 'goog.structs.Map', 'goog.structs.Set', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('testing/async/mockcontrol.js', ['goog.testing.async.MockControl'], ['goog.asserts', 'goog.async.Deferred', 'goog.debug', 'goog.testing.asserts', 'goog.testing.mockmatchers.IgnoreArgument'], false);
+goog.addDependency('testing/async/mockcontrol_test.js', ['goog.testing.async.MockControlTest'], ['goog.async.Deferred', 'goog.testing.MockControl', 'goog.testing.asserts', 'goog.testing.async.MockControl', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/asynctestcase.js', ['goog.testing.AsyncTestCase', 'goog.testing.AsyncTestCase.ControlBreakingException'], ['goog.testing.TestCase', 'goog.testing.asserts'], false);
+goog.addDependency('testing/asynctestcase_async_test.js', ['goog.testing.AsyncTestCaseAsyncTest'], ['goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/asynctestcase_noasync_test.js', ['goog.testing.AsyncTestCaseSyncTest'], ['goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/asynctestcase_test.js', ['goog.testing.AsyncTestCaseTest'], ['goog.debug.Error', 'goog.testing.AsyncTestCase', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/benchmark.js', ['goog.testing.benchmark'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTable', 'goog.testing.PerformanceTimer', 'goog.testing.TestCase'], false);
+goog.addDependency('testing/continuationtestcase.js', ['goog.testing.ContinuationTestCase', 'goog.testing.ContinuationTestCase.Step', 'goog.testing.ContinuationTestCase.Test'], ['goog.array', 'goog.events.EventHandler', 'goog.testing.TestCase', 'goog.testing.asserts'], false);
+goog.addDependency('testing/continuationtestcase_test.js', ['goog.testing.ContinuationTestCaseTest'], ['goog.events', 'goog.events.EventTarget', 'goog.testing.ContinuationTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/deferredtestcase.js', ['goog.testing.DeferredTestCase'], ['goog.testing.AsyncTestCase', 'goog.testing.TestCase'], false);
+goog.addDependency('testing/deferredtestcase_test.js', ['goog.testing.DeferredTestCaseTest'], ['goog.async.Deferred', 'goog.testing.DeferredTestCase', 'goog.testing.TestCase', 'goog.testing.TestRunner', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('testing/dom.js', ['goog.testing.dom'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.iter', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.asserts', 'goog.userAgent'], false);
+goog.addDependency('testing/dom_test.js', ['goog.testing.domTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('testing/editor/dom.js', ['goog.testing.editor.dom'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagWalkType', 'goog.iter', 'goog.string', 'goog.testing.asserts'], false);
+goog.addDependency('testing/editor/dom_test.js', ['goog.testing.editor.domTest'], ['goog.dom', 'goog.dom.TagName', 'goog.functions', 'goog.testing.editor.dom', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/editor/fieldmock.js', ['goog.testing.editor.FieldMock'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.testing.LooseMock', 'goog.testing.mockmatchers'], false);
+goog.addDependency('testing/editor/testhelper.js', ['goog.testing.editor.TestHelper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.node', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.testing.dom'], false);
+goog.addDependency('testing/editor/testhelper_test.js', ['goog.testing.editor.TestHelperTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.node', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('testing/events/eventobserver.js', ['goog.testing.events.EventObserver'], ['goog.array'], false);
+goog.addDependency('testing/events/eventobserver_test.js', ['goog.testing.events.EventObserverTest'], ['goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.testing.events.EventObserver', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/events/events.js', ['goog.testing.events', 'goog.testing.events.Event'], ['goog.Disposable', 'goog.asserts', 'goog.dom.NodeType', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.object', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('testing/events/events_test.js', ['goog.testing.eventsTest'], ['goog.array', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false);
+goog.addDependency('testing/events/matchers.js', ['goog.testing.events.EventMatcher'], ['goog.events.Event', 'goog.testing.mockmatchers.ArgumentMatcher'], false);
+goog.addDependency('testing/events/matchers_test.js', ['goog.testing.events.EventMatcherTest'], ['goog.events.Event', 'goog.testing.events.EventMatcher', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/events/onlinehandler.js', ['goog.testing.events.OnlineHandler'], ['goog.events.EventTarget', 'goog.net.NetworkStatusMonitor'], false);
+goog.addDependency('testing/events/onlinehandler_test.js', ['goog.testing.events.OnlineHandlerTest'], ['goog.events', 'goog.net.NetworkStatusMonitor', 'goog.testing.events.EventObserver', 'goog.testing.events.OnlineHandler', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/expectedfailures.js', ['goog.testing.ExpectedFailures'], ['goog.debug.DivConsole', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.log', 'goog.style', 'goog.testing.JsUnitException', 'goog.testing.TestCase', 'goog.testing.asserts'], false);
+goog.addDependency('testing/expectedfailures_test.js', ['goog.testing.ExpectedFailuresTest'], ['goog.debug.Logger', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/blob.js', ['goog.testing.fs.Blob'], ['goog.crypt.base64'], false);
+goog.addDependency('testing/fs/blob_test.js', ['goog.testing.fs.BlobTest'], ['goog.testing.fs.Blob', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/directoryentry_test.js', ['goog.testing.fs.DirectoryEntryTest'], ['goog.array', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/entry.js', ['goog.testing.fs.DirectoryEntry', 'goog.testing.fs.Entry', 'goog.testing.fs.FileEntry'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntryImpl', 'goog.fs.Entry', 'goog.fs.Error', 'goog.fs.FileEntry', 'goog.functions', 'goog.object', 'goog.string', 'goog.testing.fs.File', 'goog.testing.fs.FileWriter'], false);
+goog.addDependency('testing/fs/entry_test.js', ['goog.testing.fs.EntryTest'], ['goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/file.js', ['goog.testing.fs.File'], ['goog.testing.fs.Blob'], false);
+goog.addDependency('testing/fs/fileentry_test.js', ['goog.testing.fs.FileEntryTest'], ['goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.FileEntry', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/filereader.js', ['goog.testing.fs.FileReader'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.testing.fs.ProgressEvent'], false);
+goog.addDependency('testing/fs/filereader_test.js', ['goog.testing.fs.FileReaderTest'], ['goog.Timer', 'goog.async.Deferred', 'goog.events', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSaver', 'goog.testing.AsyncTestCase', 'goog.testing.fs.FileReader', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/filesystem.js', ['goog.testing.fs.FileSystem'], ['goog.fs.FileSystem', 'goog.testing.fs.DirectoryEntry'], false);
+goog.addDependency('testing/fs/filewriter.js', ['goog.testing.fs.FileWriter'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.string', 'goog.testing.fs.ProgressEvent'], false);
+goog.addDependency('testing/fs/filewriter_test.js', ['goog.testing.fs.FileWriterTest'], ['goog.async.Deferred', 'goog.events', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/fs.js', ['goog.testing.fs'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.fs', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem'], false);
+goog.addDependency('testing/fs/fs_test.js', ['goog.testing.fsTest'], ['goog.testing.AsyncTestCase', 'goog.testing.fs', 'goog.testing.fs.Blob', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/integration_test.js', ['goog.testing.fs.integrationTest'], ['goog.async.Deferred', 'goog.async.DeferredList', 'goog.events', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.fs', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/fs/progressevent.js', ['goog.testing.fs.ProgressEvent'], ['goog.events.Event'], false);
+goog.addDependency('testing/functionmock.js', ['goog.testing', 'goog.testing.FunctionMock', 'goog.testing.GlobalFunctionMock', 'goog.testing.MethodMock'], ['goog.object', 'goog.testing.LooseMock', 'goog.testing.Mock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock'], false);
+goog.addDependency('testing/functionmock_test.js', ['goog.testing.FunctionMockTest'], ['goog.array', 'goog.string', 'goog.testing', 'goog.testing.FunctionMock', 'goog.testing.Mock', 'goog.testing.StrictMock', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false);
+goog.addDependency('testing/graphics.js', ['goog.testing.graphics'], ['goog.graphics.Path', 'goog.testing.asserts'], false);
+goog.addDependency('testing/i18n/asserts.js', ['goog.testing.i18n.asserts'], ['goog.testing.jsunit'], false);
+goog.addDependency('testing/i18n/asserts_test.js', ['goog.testing.i18n.assertsTest'], ['goog.testing.ExpectedFailures', 'goog.testing.i18n.asserts'], false);
+goog.addDependency('testing/jsunit.js', ['goog.testing.jsunit'], ['goog.dom.TagName', 'goog.testing.TestCase', 'goog.testing.TestRunner'], false);
+goog.addDependency('testing/loosemock.js', ['goog.testing.LooseExpectationCollection', 'goog.testing.LooseMock'], ['goog.array', 'goog.structs.Map', 'goog.testing.Mock'], false);
+goog.addDependency('testing/loosemock_test.js', ['goog.testing.LooseMockTest'], ['goog.testing.LooseMock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false);
+goog.addDependency('testing/messaging/mockmessagechannel.js', ['goog.testing.messaging.MockMessageChannel'], ['goog.messaging.AbstractChannel', 'goog.testing.asserts'], false);
+goog.addDependency('testing/messaging/mockmessageevent.js', ['goog.testing.messaging.MockMessageEvent'], ['goog.events.BrowserEvent', 'goog.events.EventType', 'goog.testing.events.Event'], false);
+goog.addDependency('testing/messaging/mockmessageport.js', ['goog.testing.messaging.MockMessagePort'], ['goog.events.EventTarget'], false);
+goog.addDependency('testing/messaging/mockportnetwork.js', ['goog.testing.messaging.MockPortNetwork'], ['goog.messaging.PortNetwork', 'goog.testing.messaging.MockMessageChannel'], false);
+goog.addDependency('testing/mock.js', ['goog.testing.Mock', 'goog.testing.MockExpectation'], ['goog.array', 'goog.object', 'goog.testing.JsUnitException', 'goog.testing.MockInterface', 'goog.testing.mockmatchers'], false);
+goog.addDependency('testing/mock_test.js', ['goog.testing.MockTest'], ['goog.array', 'goog.testing', 'goog.testing.Mock', 'goog.testing.MockControl', 'goog.testing.MockExpectation', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/mockclassfactory.js', ['goog.testing.MockClassFactory', 'goog.testing.MockClassRecord'], ['goog.array', 'goog.object', 'goog.testing.LooseMock', 'goog.testing.StrictMock', 'goog.testing.TestCase', 'goog.testing.mockmatchers'], false);
+goog.addDependency('testing/mockclassfactory_test.js', ['fake.BaseClass', 'fake.ChildClass', 'goog.testing.MockClassFactoryTest'], ['goog.testing', 'goog.testing.MockClassFactory', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/mockclock.js', ['goog.testing.MockClock'], ['goog.Disposable', 'goog.async.run', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.watchers'], false);
+goog.addDependency('testing/mockclock_test.js', ['goog.testing.MockClockTest'], ['goog.Promise', 'goog.Timer', 'goog.events', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false);
+goog.addDependency('testing/mockcontrol.js', ['goog.testing.MockControl'], ['goog.array', 'goog.testing', 'goog.testing.LooseMock', 'goog.testing.StrictMock'], false);
+goog.addDependency('testing/mockcontrol_test.js', ['goog.testing.MockControlTest'], ['goog.testing.Mock', 'goog.testing.MockControl', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/mockinterface.js', ['goog.testing.MockInterface'], [], false);
+goog.addDependency('testing/mockmatchers.js', ['goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.mockmatchers.IgnoreArgument', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.mockmatchers.ObjectEquals', 'goog.testing.mockmatchers.RegexpMatch', 'goog.testing.mockmatchers.SaveArgument', 'goog.testing.mockmatchers.TypeOf'], ['goog.array', 'goog.dom', 'goog.testing.asserts'], false);
+goog.addDependency('testing/mockmatchers_test.js', ['goog.testing.mockmatchersTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher'], false);
+goog.addDependency('testing/mockrandom.js', ['goog.testing.MockRandom'], ['goog.Disposable'], false);
+goog.addDependency('testing/mockrandom_test.js', ['goog.testing.MockRandomTest'], ['goog.testing.MockRandom', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/mockrange.js', ['goog.testing.MockRange'], ['goog.dom.AbstractRange', 'goog.testing.LooseMock'], false);
+goog.addDependency('testing/mockrange_test.js', ['goog.testing.MockRangeTest'], ['goog.testing.MockRange', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/mockstorage.js', ['goog.testing.MockStorage'], ['goog.structs.Map'], false);
+goog.addDependency('testing/mockstorage_test.js', ['goog.testing.MockStorageTest'], ['goog.testing.MockStorage', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/mockuseragent.js', ['goog.testing.MockUserAgent'], ['goog.Disposable', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.userAgent'], false);
+goog.addDependency('testing/mockuseragent_test.js', ['goog.testing.MockUserAgentTest'], ['goog.dispose', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('testing/multitestrunner.js', ['goog.testing.MultiTestRunner', 'goog.testing.MultiTestRunner.TestFrame'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.functions', 'goog.string', 'goog.ui.Component', 'goog.ui.ServerChart', 'goog.ui.TableSorter'], false);
+goog.addDependency('testing/net/xhrio.js', ['goog.testing.net.XhrIo'], ['goog.array', 'goog.dom.xml', 'goog.events', 'goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.object', 'goog.structs.Map'], false);
+goog.addDependency('testing/net/xhrio_test.js', ['goog.testing.net.XhrIoTest'], ['goog.dom.xml', 'goog.events', 'goog.events.Event', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.testing.MockControl', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.net.XhrIo'], false);
+goog.addDependency('testing/net/xhriopool.js', ['goog.testing.net.XhrIoPool'], ['goog.net.XhrIoPool', 'goog.testing.net.XhrIo'], false);
+goog.addDependency('testing/objectpropertystring.js', ['goog.testing.ObjectPropertyString'], [], false);
+goog.addDependency('testing/performancetable.js', ['goog.testing.PerformanceTable'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTimer'], false);
+goog.addDependency('testing/performancetimer.js', ['goog.testing.PerformanceTimer', 'goog.testing.PerformanceTimer.Task'], ['goog.array', 'goog.async.Deferred', 'goog.math'], false);
+goog.addDependency('testing/performancetimer_test.js', ['goog.testing.PerformanceTimerTest'], ['goog.async.Deferred', 'goog.dom', 'goog.math', 'goog.testing.MockClock', 'goog.testing.PerformanceTimer', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/propertyreplacer.js', ['goog.testing.PropertyReplacer'], ['goog.testing.ObjectPropertyString', 'goog.userAgent'], false);
+goog.addDependency('testing/propertyreplacer_test.js', ['goog.testing.PropertyReplacerTest'], ['goog.dom.TagName', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/proto2/proto2.js', ['goog.testing.proto2'], ['goog.proto2.Message', 'goog.proto2.ObjectSerializer', 'goog.testing.asserts'], false);
+goog.addDependency('testing/proto2/proto2_test.js', ['goog.testing.proto2Test'], ['goog.testing.jsunit', 'goog.testing.proto2', 'proto2.TestAllTypes'], false);
+goog.addDependency('testing/pseudorandom.js', ['goog.testing.PseudoRandom'], ['goog.Disposable'], false);
+goog.addDependency('testing/pseudorandom_test.js', ['goog.testing.PseudoRandomTest'], ['goog.testing.PseudoRandom', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/recordfunction.js', ['goog.testing.FunctionCall', 'goog.testing.recordConstructor', 'goog.testing.recordFunction'], ['goog.testing.asserts'], false);
+goog.addDependency('testing/recordfunction_test.js', ['goog.testing.recordFunctionTest'], ['goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordConstructor', 'goog.testing.recordFunction'], false);
+goog.addDependency('testing/shardingtestcase.js', ['goog.testing.ShardingTestCase'], ['goog.asserts', 'goog.testing.TestCase'], false);
+goog.addDependency('testing/shardingtestcase_test.js', ['goog.testing.ShardingTestCaseTest'], ['goog.testing.ShardingTestCase', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/singleton.js', ['goog.testing.singleton'], [], false);
+goog.addDependency('testing/singleton_test.js', ['goog.testing.singletonTest'], ['goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.singleton'], false);
+goog.addDependency('testing/stacktrace.js', ['goog.testing.stacktrace', 'goog.testing.stacktrace.Frame'], [], false);
+goog.addDependency('testing/stacktrace_test.js', ['goog.testing.stacktraceTest'], ['goog.functions', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.stacktrace', 'goog.testing.stacktrace.Frame', 'goog.userAgent'], false);
+goog.addDependency('testing/storage/fakemechanism.js', ['goog.testing.storage.FakeMechanism'], ['goog.storage.mechanism.IterableMechanism', 'goog.structs.Map'], false);
+goog.addDependency('testing/strictmock.js', ['goog.testing.StrictMock'], ['goog.array', 'goog.testing.Mock'], false);
+goog.addDependency('testing/strictmock_test.js', ['goog.testing.StrictMockTest'], ['goog.testing.StrictMock', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/style/layoutasserts.js', ['goog.testing.style.layoutasserts'], ['goog.style', 'goog.testing.asserts', 'goog.testing.style'], false);
+goog.addDependency('testing/style/layoutasserts_test.js', ['goog.testing.style.layoutassertsTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.jsunit', 'goog.testing.style.layoutasserts'], false);
+goog.addDependency('testing/style/style.js', ['goog.testing.style'], ['goog.dom', 'goog.math.Rect', 'goog.style'], false);
+goog.addDependency('testing/style/style_test.js', ['goog.testing.styleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.jsunit', 'goog.testing.style'], false);
+goog.addDependency('testing/testcase.js', ['goog.testing.TestCase', 'goog.testing.TestCase.Error', 'goog.testing.TestCase.Order', 'goog.testing.TestCase.Result', 'goog.testing.TestCase.Test'], ['goog.Promise', 'goog.Thenable', 'goog.dom.TagName', 'goog.object', 'goog.testing.asserts', 'goog.testing.stacktrace'], false);
+goog.addDependency('testing/testcase_test.js', ['goog.testing.TestCaseTest'], ['goog.Promise', 'goog.testing.MockRandom', 'goog.testing.TestCase', 'goog.testing.jsunit'], false);
+goog.addDependency('testing/testqueue.js', ['goog.testing.TestQueue'], [], false);
+goog.addDependency('testing/testrunner.js', ['goog.testing.TestRunner'], ['goog.dom.TagName', 'goog.testing.TestCase'], false);
+goog.addDependency('testing/testsuite.js', ['goog.testing.testSuite'], ['goog.testing.TestCase'], false);
+goog.addDependency('testing/ui/rendererasserts.js', ['goog.testing.ui.rendererasserts'], ['goog.testing.asserts', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('testing/ui/rendererasserts_test.js', ['goog.testing.ui.rendererassertsTest'], ['goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('testing/ui/rendererharness.js', ['goog.testing.ui.RendererHarness'], ['goog.Disposable', 'goog.dom.NodeType', 'goog.testing.asserts', 'goog.testing.dom'], false);
+goog.addDependency('testing/ui/style.js', ['goog.testing.ui.style'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.testing.asserts'], false);
+goog.addDependency('testing/ui/style_test.js', ['goog.testing.ui.styleTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style'], false);
+goog.addDependency('testing/watchers.js', ['goog.testing.watchers'], [], false);
+goog.addDependency('timer/timer.js', ['goog.Timer'], ['goog.Promise', 'goog.events.EventTarget'], false);
+goog.addDependency('timer/timer_test.js', ['goog.TimerTest'], ['goog.Promise', 'goog.Timer', 'goog.events', 'goog.testing.MockClock', 'goog.testing.jsunit'], false);
+goog.addDependency('tweak/entries.js', ['goog.tweak.BaseEntry', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting'], ['goog.array', 'goog.asserts', 'goog.log', 'goog.object'], false);
+goog.addDependency('tweak/entries_test.js', ['goog.tweak.BaseEntryTest'], ['goog.testing.MockControl', 'goog.testing.jsunit', 'goog.tweak.testhelpers'], false);
+goog.addDependency('tweak/registry.js', ['goog.tweak.Registry'], ['goog.array', 'goog.asserts', 'goog.log', 'goog.string', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting', 'goog.uri.utils'], false);
+goog.addDependency('tweak/registry_test.js', ['goog.tweak.RegistryTest'], ['goog.asserts.AssertionError', 'goog.testing.jsunit', 'goog.tweak', 'goog.tweak.testhelpers'], false);
+goog.addDependency('tweak/testhelpers.js', ['goog.tweak.testhelpers'], ['goog.tweak', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting'], false);
+goog.addDependency('tweak/tweak.js', ['goog.tweak', 'goog.tweak.ConfigParams'], ['goog.asserts', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting'], false);
+goog.addDependency('tweak/tweakui.js', ['goog.tweak.EntriesPanel', 'goog.tweak.TweakUi'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.object', 'goog.string.Const', 'goog.style', 'goog.tweak', 'goog.tweak.BaseEntry', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting', 'goog.ui.Zippy', 'goog.userAgent'], false);
+goog.addDependency('tweak/tweakui_test.js', ['goog.tweak.TweakUiTest'], ['goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.testing.jsunit', 'goog.tweak', 'goog.tweak.TweakUi', 'goog.tweak.testhelpers'], false);
+goog.addDependency('ui/abstractspellchecker.js', ['goog.ui.AbstractSpellChecker', 'goog.ui.AbstractSpellChecker.AsyncResult'], ['goog.a11y.aria', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.selection', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.structs.Set', 'goog.style', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.PopupMenu'], false);
+goog.addDependency('ui/ac/ac.js', ['goog.ui.ac'], ['goog.ui.ac.ArrayMatcher', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.Renderer'], false);
+goog.addDependency('ui/ac/ac_test.js', ['goog.ui.acTest'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.dom.selection', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ac', 'goog.userAgent'], false);
+goog.addDependency('ui/ac/arraymatcher.js', ['goog.ui.ac.ArrayMatcher'], ['goog.string'], false);
+goog.addDependency('ui/ac/arraymatcher_test.js', ['goog.ui.ac.ArrayMatcherTest'], ['goog.testing.jsunit', 'goog.ui.ac.ArrayMatcher'], false);
+goog.addDependency('ui/ac/autocomplete.js', ['goog.ui.ac.AutoComplete', 'goog.ui.ac.AutoComplete.EventType'], ['goog.array', 'goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.object'], false);
+goog.addDependency('ui/ac/autocomplete_test.js', ['goog.ui.ac.AutoCompleteTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.string', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RenderOptions', 'goog.ui.ac.Renderer'], false);
+goog.addDependency('ui/ac/cachingmatcher.js', ['goog.ui.ac.CachingMatcher'], ['goog.array', 'goog.async.Throttle', 'goog.ui.ac.ArrayMatcher', 'goog.ui.ac.RenderOptions'], false);
+goog.addDependency('ui/ac/cachingmatcher_test.js', ['goog.ui.ac.CachingMatcherTest'], ['goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.ac.CachingMatcher'], false);
+goog.addDependency('ui/ac/inputhandler.js', ['goog.ui.ac.InputHandler'], ['goog.Disposable', 'goog.Timer', 'goog.a11y.aria', 'goog.dom', 'goog.dom.selection', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.string', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('ui/ac/inputhandler_test.js', ['goog.ui.ac.InputHandlerTest'], ['goog.dom.selection', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.functions', 'goog.object', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ac.InputHandler', 'goog.userAgent'], false);
+goog.addDependency('ui/ac/remote.js', ['goog.ui.ac.Remote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RemoteArrayMatcher', 'goog.ui.ac.Renderer'], false);
+goog.addDependency('ui/ac/remotearraymatcher.js', ['goog.ui.ac.RemoteArrayMatcher'], ['goog.Disposable', 'goog.Uri', 'goog.events', 'goog.json', 'goog.net.EventType', 'goog.net.XhrIo'], false);
+goog.addDependency('ui/ac/remotearraymatcher_test.js', ['goog.ui.ac.RemoteArrayMatcherTest'], ['goog.json', 'goog.net.XhrIo', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.ui.ac.RemoteArrayMatcher'], false);
+goog.addDependency('ui/ac/renderer.js', ['goog.ui.ac.Renderer', 'goog.ui.ac.Renderer.CustomRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dispose', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.string', 'goog.style', 'goog.ui.IdGenerator', 'goog.ui.ac.AutoComplete'], false);
+goog.addDependency('ui/ac/renderer_test.js', ['goog.ui.ac.RendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.string', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.Renderer'], false);
+goog.addDependency('ui/ac/renderoptions.js', ['goog.ui.ac.RenderOptions'], [], false);
+goog.addDependency('ui/ac/richinputhandler.js', ['goog.ui.ac.RichInputHandler'], ['goog.ui.ac.InputHandler'], false);
+goog.addDependency('ui/ac/richremote.js', ['goog.ui.ac.RichRemote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.Remote', 'goog.ui.ac.Renderer', 'goog.ui.ac.RichInputHandler', 'goog.ui.ac.RichRemoteArrayMatcher'], false);
+goog.addDependency('ui/ac/richremotearraymatcher.js', ['goog.ui.ac.RichRemoteArrayMatcher'], ['goog.dom.safe', 'goog.html.legacyconversions', 'goog.json', 'goog.ui.ac.RemoteArrayMatcher'], false);
+goog.addDependency('ui/activitymonitor.js', ['goog.ui.ActivityMonitor'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType'], false);
+goog.addDependency('ui/activitymonitor_test.js', ['goog.ui.ActivityMonitorTest'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.ActivityMonitor'], false);
+goog.addDependency('ui/advancedtooltip.js', ['goog.ui.AdvancedTooltip'], ['goog.events', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Tooltip', 'goog.userAgent'], false);
+goog.addDependency('ui/advancedtooltip_test.js', ['goog.ui.AdvancedTooltipTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.AdvancedTooltip', 'goog.ui.Tooltip', 'goog.userAgent'], false);
+goog.addDependency('ui/animatedzippy.js', ['goog.ui.AnimatedZippy'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.fx.easing', 'goog.ui.Zippy', 'goog.ui.ZippyEvent'], false);
+goog.addDependency('ui/animatedzippy_test.js', ['goog.ui.AnimatedZippyTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events', 'goog.functions', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.ui.AnimatedZippy', 'goog.ui.Zippy'], false);
+goog.addDependency('ui/attachablemenu.js', ['goog.ui.AttachableMenu'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.string', 'goog.style', 'goog.ui.ItemEvent', 'goog.ui.MenuBase', 'goog.ui.PopupBase', 'goog.userAgent'], false);
+goog.addDependency('ui/bidiinput.js', ['goog.ui.BidiInput'], ['goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.InputHandler', 'goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.ui.Component'], false);
+goog.addDependency('ui/bidiinput_test.js', ['goog.ui.BidiInputTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.BidiInput'], false);
+goog.addDependency('ui/bubble.js', ['goog.ui.Bubble'], ['goog.Timer', 'goog.dom.safe', 'goog.events', 'goog.events.EventType', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.math.Box', 'goog.positioning', 'goog.positioning.AbsolutePosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.string.Const', 'goog.style', 'goog.ui.Component', 'goog.ui.Popup'], false);
+goog.addDependency('ui/button.js', ['goog.ui.Button', 'goog.ui.Button.Side'], ['goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.NativeButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/button_test.js', ['goog.ui.ButtonTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.NativeButtonRenderer'], false);
+goog.addDependency('ui/buttonrenderer.js', ['goog.ui.ButtonRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/buttonrenderer_test.js', ['goog.ui.ButtonRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component'], false);
+goog.addDependency('ui/buttonside.js', ['goog.ui.ButtonSide'], [], false);
+goog.addDependency('ui/charcounter.js', ['goog.ui.CharCounter', 'goog.ui.CharCounter.Display'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.InputHandler'], false);
+goog.addDependency('ui/charcounter_test.js', ['goog.ui.CharCounterTest'], ['goog.dom', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.ui.CharCounter', 'goog.userAgent'], false);
+goog.addDependency('ui/charpicker.js', ['goog.ui.CharPicker'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.i18n.CharListDecompressor', 'goog.i18n.uChar', 'goog.structs.Set', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.ContainerScroller', 'goog.ui.FlatButtonRenderer', 'goog.ui.HoverCard', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.Tooltip'], false);
+goog.addDependency('ui/charpicker_test.js', ['goog.ui.CharPickerTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dispose', 'goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.i18n.CharPickerData', 'goog.i18n.uChar.NameFetcher', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.CharPicker', 'goog.ui.FlatButtonRenderer'], false);
+goog.addDependency('ui/checkbox.js', ['goog.ui.Checkbox', 'goog.ui.Checkbox.State'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.string', 'goog.ui.CheckboxRenderer', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.registry'], false);
+goog.addDependency('ui/checkbox_test.js', ['goog.ui.CheckboxTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.KeyCodes', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Checkbox', 'goog.ui.CheckboxRenderer', 'goog.ui.Component', 'goog.ui.ControlRenderer', 'goog.ui.decorate'], false);
+goog.addDependency('ui/checkboxmenuitem.js', ['goog.ui.CheckBoxMenuItem'], ['goog.ui.MenuItem', 'goog.ui.registry'], false);
+goog.addDependency('ui/checkboxrenderer.js', ['goog.ui.CheckboxRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.object', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/colorbutton.js', ['goog.ui.ColorButton'], ['goog.ui.Button', 'goog.ui.ColorButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/colorbutton_test.js', ['goog.ui.ColorButtonTest'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.ColorButton', 'goog.ui.decorate'], false);
+goog.addDependency('ui/colorbuttonrenderer.js', ['goog.ui.ColorButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.functions', 'goog.ui.ColorMenuButtonRenderer'], false);
+goog.addDependency('ui/colormenubutton.js', ['goog.ui.ColorMenuButton'], ['goog.array', 'goog.object', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.ColorPalette', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.registry'], false);
+goog.addDependency('ui/colormenubuttonrenderer.js', ['goog.ui.ColorMenuButtonRenderer'], ['goog.asserts', 'goog.color', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.MenuButtonRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/colormenubuttonrenderer_test.js', ['goog.ui.ColorMenuButtonTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.testing.ui.RendererHarness', 'goog.testing.ui.rendererasserts', 'goog.ui.ColorMenuButton', 'goog.ui.ColorMenuButtonRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/colorpalette.js', ['goog.ui.ColorPalette'], ['goog.array', 'goog.color', 'goog.dom.TagName', 'goog.style', 'goog.ui.Palette', 'goog.ui.PaletteRenderer'], false);
+goog.addDependency('ui/colorpalette_test.js', ['goog.ui.ColorPaletteTest'], ['goog.color', 'goog.testing.jsunit', 'goog.ui.ColorPalette'], false);
+goog.addDependency('ui/colorpicker.js', ['goog.ui.ColorPicker', 'goog.ui.ColorPicker.EventType'], ['goog.ui.ColorPalette', 'goog.ui.Component'], false);
+goog.addDependency('ui/colorsplitbehavior.js', ['goog.ui.ColorSplitBehavior'], ['goog.ui.ColorMenuButton', 'goog.ui.SplitBehavior'], false);
+goog.addDependency('ui/combobox.js', ['goog.ui.ComboBox', 'goog.ui.ComboBoxItem'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.log', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.ItemEvent', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.registry', 'goog.userAgent'], false);
+goog.addDependency('ui/combobox_test.js', ['goog.ui.ComboBoxTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.ComboBox', 'goog.ui.ComboBoxItem', 'goog.ui.Component', 'goog.ui.ControlRenderer', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem'], false);
+goog.addDependency('ui/component.js', ['goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Component.State'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.object', 'goog.style', 'goog.ui.IdGenerator'], false);
+goog.addDependency('ui/component_test.js', ['goog.ui.ComponentTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.events.EventTarget', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component'], false);
+goog.addDependency('ui/container.js', ['goog.ui.Container', 'goog.ui.Container.EventType', 'goog.ui.Container.Orientation'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.object', 'goog.style', 'goog.ui.Component', 'goog.ui.ContainerRenderer', 'goog.ui.Control'], false);
+goog.addDependency('ui/container_test.js', ['goog.ui.ContainerTest'], ['goog.a11y.aria', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.events.KeyEvent', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Control'], false);
+goog.addDependency('ui/containerrenderer.js', ['goog.ui.ContainerRenderer'], ['goog.a11y.aria', 'goog.array', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.style', 'goog.ui.registry', 'goog.userAgent'], false);
+goog.addDependency('ui/containerrenderer_test.js', ['goog.ui.ContainerRendererTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Container', 'goog.ui.ContainerRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/containerscroller.js', ['goog.ui.ContainerScroller'], ['goog.Disposable', 'goog.Timer', 'goog.events.EventHandler', 'goog.style', 'goog.ui.Component', 'goog.ui.Container'], false);
+goog.addDependency('ui/containerscroller_test.js', ['goog.ui.ContainerScrollerTest'], ['goog.dom', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Container', 'goog.ui.ContainerScroller'], false);
+goog.addDependency('ui/control.js', ['goog.ui.Control'], ['goog.Disposable', 'goog.array', 'goog.dom', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.string', 'goog.ui.Component', 'goog.ui.ControlContent', 'goog.ui.ControlRenderer', 'goog.ui.decorate', 'goog.ui.registry', 'goog.userAgent'], false);
+goog.addDependency('ui/control_test.js', ['goog.ui.ControlTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer', 'goog.ui.registry', 'goog.userAgent'], false);
+goog.addDependency('ui/controlcontent.js', ['goog.ui.ControlContent'], [], false);
+goog.addDependency('ui/controlrenderer.js', ['goog.ui.ControlRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.object', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/controlrenderer_test.js', ['goog.ui.ControlRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/cookieeditor.js', ['goog.ui.CookieEditor'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventType', 'goog.net.cookies', 'goog.string', 'goog.style', 'goog.ui.Component'], false);
+goog.addDependency('ui/cookieeditor_test.js', ['goog.ui.CookieEditorTest'], ['goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.net.cookies', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.CookieEditor'], false);
+goog.addDependency('ui/css3buttonrenderer.js', ['goog.ui.Css3ButtonRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.Component', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false);
+goog.addDependency('ui/css3menubuttonrenderer.js', ['goog.ui.Css3MenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/cssnames.js', ['goog.ui.INLINE_BLOCK_CLASSNAME'], [], false);
+goog.addDependency('ui/custombutton.js', ['goog.ui.CustomButton'], ['goog.ui.Button', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/custombuttonrenderer.js', ['goog.ui.CustomButtonRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME'], false);
+goog.addDependency('ui/customcolorpalette.js', ['goog.ui.CustomColorPalette'], ['goog.color', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.ColorPalette', 'goog.ui.Component'], false);
+goog.addDependency('ui/customcolorpalette_test.js', ['goog.ui.CustomColorPaletteTest'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.CustomColorPalette'], false);
+goog.addDependency('ui/datepicker.js', ['goog.ui.DatePicker', 'goog.ui.DatePicker.Events', 'goog.ui.DatePickerEvent'], ['goog.a11y.aria', 'goog.asserts', 'goog.date.Date', 'goog.date.DateRange', 'goog.date.Interval', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns', 'goog.i18n.DateTimeSymbols', 'goog.style', 'goog.ui.Component', 'goog.ui.DefaultDatePickerRenderer', 'goog.ui.IdGenerator'], false);
+goog.addDependency('ui/datepicker_test.js', ['goog.ui.DatePickerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.date.Date', 'goog.date.DateRange', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.style', 'goog.testing.jsunit', 'goog.ui.DatePicker'], false);
+goog.addDependency('ui/datepickerrenderer.js', ['goog.ui.DatePickerRenderer'], [], false);
+goog.addDependency('ui/decorate.js', ['goog.ui.decorate'], ['goog.ui.registry'], false);
+goog.addDependency('ui/decorate_test.js', ['goog.ui.decorateTest'], ['goog.testing.jsunit', 'goog.ui.decorate', 'goog.ui.registry'], false);
+goog.addDependency('ui/defaultdatepickerrenderer.js', ['goog.ui.DefaultDatePickerRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.DatePickerRenderer'], false);
+goog.addDependency('ui/dialog.js', ['goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.ButtonSet.DefaultButtons', 'goog.ui.Dialog.DefaultButtonCaptions', 'goog.ui.Dialog.DefaultButtonKeys', 'goog.ui.Dialog.Event', 'goog.ui.Dialog.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.safe', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Dragger', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.math.Rect', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.ModalPopup'], false);
+goog.addDependency('ui/dialog_test.js', ['goog.ui.DialogTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.css3', 'goog.html.SafeHtml', 'goog.html.testing', 'goog.style', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Dialog', 'goog.userAgent'], false);
+goog.addDependency('ui/dimensionpicker.js', ['goog.ui.DimensionPicker'], ['goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.DimensionPickerRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/dimensionpicker_test.js', ['goog.ui.DimensionPickerTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.DimensionPicker', 'goog.ui.DimensionPickerRenderer'], false);
+goog.addDependency('ui/dimensionpickerrenderer.js', ['goog.ui.DimensionPickerRenderer'], ['goog.a11y.aria.Announcer', 'goog.a11y.aria.LivePriority', 'goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/dimensionpickerrenderer_test.js', ['goog.ui.DimensionPickerRendererTest'], ['goog.a11y.aria.LivePriority', 'goog.array', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.DimensionPicker', 'goog.ui.DimensionPickerRenderer'], false);
+goog.addDependency('ui/dragdropdetector.js', ['goog.ui.DragDropDetector', 'goog.ui.DragDropDetector.EventType', 'goog.ui.DragDropDetector.ImageDropEvent', 'goog.ui.DragDropDetector.LinkDropEvent'], ['goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('ui/drilldownrow.js', ['goog.ui.DrilldownRow'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.ui.Component'], false);
+goog.addDependency('ui/drilldownrow_test.js', ['goog.ui.DrilldownRowTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.DrilldownRow'], false);
+goog.addDependency('ui/editor/abstractdialog.js', ['goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventTarget', 'goog.string', 'goog.ui.Dialog', 'goog.ui.PopupBase'], false);
+goog.addDependency('ui/editor/abstractdialog_test.js', ['goog.ui.editor.AbstractDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.KeyCodes', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.userAgent'], false);
+goog.addDependency('ui/editor/bubble.js', ['goog.ui.editor.Bubble'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.ViewportSizeMonitor', 'goog.dom.classlist', 'goog.editor.style', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.functions', 'goog.log', 'goog.math.Box', 'goog.object', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.PopupBase', 'goog.userAgent'], false);
+goog.addDependency('ui/editor/bubble_test.js', ['goog.ui.editor.BubbleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.positioning.Corner', 'goog.positioning.OverflowStatus', 'goog.string', 'goog.style', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.editor.Bubble'], false);
+goog.addDependency('ui/editor/defaulttoolbar.js', ['goog.ui.editor.ButtonDescriptor', 'goog.ui.editor.DefaultToolbar'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.Command', 'goog.style', 'goog.ui.editor.ToolbarFactory', 'goog.ui.editor.messages', 'goog.userAgent'], false);
+goog.addDependency('ui/editor/linkdialog.js', ['goog.ui.editor.LinkDialog', 'goog.ui.editor.LinkDialog.BeforeTestLinkEvent', 'goog.ui.editor.LinkDialog.EventType', 'goog.ui.editor.LinkDialog.OkEvent'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.editor.focus', 'goog.editor.node', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.InputHandler', 'goog.html.SafeHtml', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.LinkButtonRenderer', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.TabPane', 'goog.ui.editor.messages', 'goog.userAgent', 'goog.window'], false);
+goog.addDependency('ui/editor/linkdialog_test.js', ['goog.ui.editor.LinkDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.ui.editor.messages', 'goog.userAgent'], false);
+goog.addDependency('ui/editor/messages.js', ['goog.ui.editor.messages'], ['goog.html.uncheckedconversions', 'goog.string.Const'], false);
+goog.addDependency('ui/editor/tabpane.js', ['goog.ui.editor.TabPane'], ['goog.asserts', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.Tab', 'goog.ui.TabBar'], false);
+goog.addDependency('ui/editor/toolbarcontroller.js', ['goog.ui.editor.ToolbarController'], ['goog.editor.Field', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.ui.Component'], false);
+goog.addDependency('ui/editor/toolbarfactory.js', ['goog.ui.editor.ToolbarFactory'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Option', 'goog.ui.Toolbar', 'goog.ui.ToolbarButton', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarMenuButton', 'goog.ui.ToolbarRenderer', 'goog.ui.ToolbarSelect', 'goog.userAgent'], false);
+goog.addDependency('ui/editor/toolbarfactory_test.js', ['goog.ui.editor.ToolbarFactoryTest'], ['goog.dom', 'goog.testing.ExpectedFailures', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.ui.editor.ToolbarFactory', 'goog.userAgent'], false);
+goog.addDependency('ui/emoji/emoji.js', ['goog.ui.emoji.Emoji'], [], false);
+goog.addDependency('ui/emoji/emojipalette.js', ['goog.ui.emoji.EmojiPalette'], ['goog.events.EventType', 'goog.net.ImageLoader', 'goog.ui.Palette', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPaletteRenderer'], false);
+goog.addDependency('ui/emoji/emojipaletterenderer.js', ['goog.ui.emoji.EmojiPaletteRenderer'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.style', 'goog.ui.PaletteRenderer', 'goog.ui.emoji.Emoji'], false);
+goog.addDependency('ui/emoji/emojipicker.js', ['goog.ui.emoji.EmojiPicker'], ['goog.dom.TagName', 'goog.style', 'goog.ui.Component', 'goog.ui.TabPane', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPalette', 'goog.ui.emoji.EmojiPaletteRenderer', 'goog.ui.emoji.ProgressiveEmojiPaletteRenderer'], false);
+goog.addDependency('ui/emoji/emojipicker_test.js', ['goog.ui.emoji.EmojiPickerTest'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo'], false);
+goog.addDependency('ui/emoji/fast_nonprogressive_emojipicker_test.js', ['goog.ui.emoji.FastNonProgressiveEmojiPickerTest'], ['goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.net.EventType', 'goog.style', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo', 'goog.userAgent'], false);
+goog.addDependency('ui/emoji/fast_progressive_emojipicker_test.js', ['goog.ui.emoji.FastProgressiveEmojiPickerTest'], ['goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.net.EventType', 'goog.style', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo'], false);
+goog.addDependency('ui/emoji/popupemojipicker.js', ['goog.ui.emoji.PopupEmojiPicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.Component', 'goog.ui.Popup', 'goog.ui.emoji.EmojiPicker'], false);
+goog.addDependency('ui/emoji/popupemojipicker_test.js', ['goog.ui.emoji.PopupEmojiPickerTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.emoji.PopupEmojiPicker'], false);
+goog.addDependency('ui/emoji/progressiveemojipaletterenderer.js', ['goog.ui.emoji.ProgressiveEmojiPaletteRenderer'], ['goog.dom.TagName', 'goog.style', 'goog.ui.emoji.EmojiPaletteRenderer'], false);
+goog.addDependency('ui/emoji/spriteinfo.js', ['goog.ui.emoji.SpriteInfo'], [], false);
+goog.addDependency('ui/emoji/spriteinfo_test.js', ['goog.ui.emoji.SpriteInfoTest'], ['goog.testing.jsunit', 'goog.ui.emoji.SpriteInfo'], false);
+goog.addDependency('ui/filteredmenu.js', ['goog.ui.FilteredMenu'], ['goog.a11y.aria', 'goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.FilterObservingMenuItem', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.userAgent'], false);
+goog.addDependency('ui/filteredmenu_test.js', ['goog.ui.FilteredMenuTest'], ['goog.a11y.aria', 'goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Rect', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.FilteredMenu', 'goog.ui.MenuItem'], false);
+goog.addDependency('ui/filterobservingmenuitem.js', ['goog.ui.FilterObservingMenuItem'], ['goog.ui.FilterObservingMenuItemRenderer', 'goog.ui.MenuItem', 'goog.ui.registry'], false);
+goog.addDependency('ui/filterobservingmenuitemrenderer.js', ['goog.ui.FilterObservingMenuItemRenderer'], ['goog.ui.MenuItemRenderer'], false);
+goog.addDependency('ui/flatbuttonrenderer.js', ['goog.ui.FlatButtonRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false);
+goog.addDependency('ui/flatmenubuttonrenderer.js', ['goog.ui.FlatMenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.ui.FlatButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/formpost.js', ['goog.ui.FormPost'], ['goog.array', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.ui.Component'], false);
+goog.addDependency('ui/formpost_test.js', ['goog.ui.FormPostTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.object', 'goog.testing.jsunit', 'goog.ui.FormPost', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('ui/gauge.js', ['goog.ui.Gauge', 'goog.ui.GaugeColoredRange'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.TagName', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.fx.easing', 'goog.graphics', 'goog.graphics.Font', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.math', 'goog.ui.Component', 'goog.ui.GaugeTheme'], false);
+goog.addDependency('ui/gaugetheme.js', ['goog.ui.GaugeTheme'], ['goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke'], false);
+goog.addDependency('ui/hovercard.js', ['goog.ui.HoverCard', 'goog.ui.HoverCard.EventType', 'goog.ui.HoverCard.TriggerEvent'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.ui.AdvancedTooltip', 'goog.ui.PopupBase', 'goog.ui.Tooltip'], false);
+goog.addDependency('ui/hovercard_test.js', ['goog.ui.HoverCardTest'], ['goog.dom', 'goog.events', 'goog.math.Coordinate', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.HoverCard'], false);
+goog.addDependency('ui/hsvapalette.js', ['goog.ui.HsvaPalette'], ['goog.array', 'goog.color.alpha', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.HsvPalette'], false);
+goog.addDependency('ui/hsvapalette_test.js', ['goog.ui.HsvaPaletteTest'], ['goog.color.alpha', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.math.Coordinate', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.HsvaPalette', 'goog.userAgent'], false);
+goog.addDependency('ui/hsvpalette.js', ['goog.ui.HsvPalette'], ['goog.color', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/hsvpalette_test.js', ['goog.ui.HsvPaletteTest'], ['goog.color', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.math.Coordinate', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.HsvPalette', 'goog.userAgent'], false);
+goog.addDependency('ui/idgenerator.js', ['goog.ui.IdGenerator'], [], false);
+goog.addDependency('ui/idletimer.js', ['goog.ui.IdleTimer'], ['goog.Timer', 'goog.events', 'goog.events.EventTarget', 'goog.structs.Set', 'goog.ui.ActivityMonitor'], false);
+goog.addDependency('ui/idletimer_test.js', ['goog.ui.IdleTimerTest'], ['goog.events', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.IdleTimer', 'goog.ui.MockActivityMonitor'], false);
+goog.addDependency('ui/iframemask.js', ['goog.ui.IframeMask'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.dom.iframe', 'goog.events.EventHandler', 'goog.style'], false);
+goog.addDependency('ui/iframemask_test.js', ['goog.ui.IframeMaskTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.iframe', 'goog.structs.Pool', 'goog.style', 'goog.testing.MockClock', 'goog.testing.StrictMock', 'goog.testing.jsunit', 'goog.ui.IframeMask', 'goog.ui.Popup', 'goog.ui.PopupBase', 'goog.userAgent'], false);
+goog.addDependency('ui/imagelessbuttonrenderer.js', ['goog.ui.ImagelessButtonRenderer'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false);
+goog.addDependency('ui/imagelessmenubuttonrenderer.js', ['goog.ui.ImagelessMenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/inputdatepicker.js', ['goog.ui.InputDatePicker'], ['goog.date.DateTime', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.string', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker'], false);
+goog.addDependency('ui/inputdatepicker_test.js', ['goog.ui.InputDatePickerTest'], ['goog.dom', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeParse', 'goog.testing.jsunit', 'goog.ui.InputDatePicker'], false);
+goog.addDependency('ui/itemevent.js', ['goog.ui.ItemEvent'], ['goog.events.Event'], false);
+goog.addDependency('ui/keyboardshortcuthandler.js', ['goog.ui.KeyboardShortcutEvent', 'goog.ui.KeyboardShortcutHandler', 'goog.ui.KeyboardShortcutHandler.EventType'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyNames', 'goog.object', 'goog.userAgent'], false);
+goog.addDependency('ui/keyboardshortcuthandler_test.js', ['goog.ui.KeyboardShortcutHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.KeyboardShortcutHandler', 'goog.userAgent'], false);
+goog.addDependency('ui/labelinput.js', ['goog.ui.LabelInput'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/labelinput_test.js', ['goog.ui.LabelInputTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.LabelInput', 'goog.userAgent'], false);
+goog.addDependency('ui/linkbuttonrenderer.js', ['goog.ui.LinkButtonRenderer'], ['goog.ui.Button', 'goog.ui.FlatButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/media/flashobject.js', ['goog.ui.media.FlashObject', 'goog.ui.media.FlashObject.ScriptAccessLevel', 'goog.ui.media.FlashObject.Wmodes'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.html.legacyconversions', 'goog.log', 'goog.object', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.userAgent', 'goog.userAgent.flash'], false);
+goog.addDependency('ui/media/flashobject_test.js', ['goog.ui.media.FlashObjectTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.html.SafeUrl', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.userAgent'], false);
+goog.addDependency('ui/media/flickr.js', ['goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel'], ['goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/flickr_test.js', ['goog.ui.media.FlickrSetTest'], ['goog.dom', 'goog.dom.TagName', 'goog.html.testing', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel', 'goog.ui.media.Media'], false);
+goog.addDependency('ui/media/googlevideo.js', ['goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/googlevideo_test.js', ['goog.ui.media.GoogleVideoTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel', 'goog.ui.media.Media'], false);
+goog.addDependency('ui/media/media.js', ['goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.style', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/media/media_test.js', ['goog.ui.media.MediaTest'], ['goog.dom', 'goog.dom.TagName', 'goog.math.Size', 'goog.testing.jsunit', 'goog.ui.ControlRenderer', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/mediamodel.js', ['goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Category', 'goog.ui.media.MediaModel.Credit', 'goog.ui.media.MediaModel.Credit.Role', 'goog.ui.media.MediaModel.Credit.Scheme', 'goog.ui.media.MediaModel.Medium', 'goog.ui.media.MediaModel.MimeType', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaModel.SubTitle', 'goog.ui.media.MediaModel.Thumbnail'], ['goog.array', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions'], false);
+goog.addDependency('ui/media/mediamodel_test.js', ['goog.ui.media.MediaModelTest'], ['goog.testing.jsunit', 'goog.ui.media.MediaModel'], false);
+goog.addDependency('ui/media/mp3.js', ['goog.ui.media.Mp3'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/mp3_test.js', ['goog.ui.media.Mp3Test'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.Mp3'], false);
+goog.addDependency('ui/media/photo.js', ['goog.ui.media.Photo'], ['goog.dom.TagName', 'goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/photo_test.js', ['goog.ui.media.PhotoTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.MediaModel', 'goog.ui.media.Photo'], false);
+goog.addDependency('ui/media/picasa.js', ['goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel'], ['goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/picasa_test.js', ['goog.ui.media.PicasaTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel'], false);
+goog.addDependency('ui/media/vimeo.js', ['goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/vimeo_test.js', ['goog.ui.media.VimeoTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel'], false);
+goog.addDependency('ui/media/youtube.js', ['goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel'], ['goog.dom.TagName', 'goog.string', 'goog.ui.Component', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false);
+goog.addDependency('ui/media/youtube_test.js', ['goog.ui.media.YoutubeTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel'], false);
+goog.addDependency('ui/menu.js', ['goog.ui.Menu', 'goog.ui.Menu.EventType'], ['goog.dom.TagName', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.MenuHeader', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.MenuSeparator'], false);
+goog.addDependency('ui/menu_test.js', ['goog.ui.MenuTest'], ['goog.dom', 'goog.events', 'goog.math.Coordinate', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Menu'], false);
+goog.addDependency('ui/menubar.js', ['goog.ui.menuBar'], ['goog.ui.Container', 'goog.ui.MenuBarRenderer'], false);
+goog.addDependency('ui/menubardecorator.js', ['goog.ui.menuBarDecorator'], ['goog.ui.MenuBarRenderer', 'goog.ui.menuBar', 'goog.ui.registry'], false);
+goog.addDependency('ui/menubarrenderer.js', ['goog.ui.MenuBarRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Container', 'goog.ui.ContainerRenderer'], false);
+goog.addDependency('ui/menubase.js', ['goog.ui.MenuBase'], ['goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.ui.Popup'], false);
+goog.addDependency('ui/menubutton.js', ['goog.ui.MenuButton'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.math.Box', 'goog.math.Rect', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.IdGenerator', 'goog.ui.Menu', 'goog.ui.MenuButtonRenderer', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.registry', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('ui/menubutton_test.js', ['goog.ui.MenuButtonTest'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.SubMenu', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('ui/menubuttonrenderer.js', ['goog.ui.MenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuRenderer'], false);
+goog.addDependency('ui/menubuttonrenderer_test.js', ['goog.ui.MenuButtonRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/menuheader.js', ['goog.ui.MenuHeader'], ['goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuHeaderRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/menuheaderrenderer.js', ['goog.ui.MenuHeaderRenderer'], ['goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/menuitem.js', ['goog.ui.MenuItem'], ['goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.classlist', 'goog.math.Coordinate', 'goog.string', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuItemRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/menuitem_test.js', ['goog.ui.MenuItemTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuItemRenderer'], false);
+goog.addDependency('ui/menuitemrenderer.js', ['goog.ui.MenuItemRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/menuitemrenderer_test.js', ['goog.ui.MenuItemRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuItemRenderer'], false);
+goog.addDependency('ui/menurenderer.js', ['goog.ui.MenuRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.ui.ContainerRenderer', 'goog.ui.Separator'], false);
+goog.addDependency('ui/menuseparator.js', ['goog.ui.MenuSeparator'], ['goog.ui.MenuSeparatorRenderer', 'goog.ui.Separator', 'goog.ui.registry'], false);
+goog.addDependency('ui/menuseparatorrenderer.js', ['goog.ui.MenuSeparatorRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/menuseparatorrenderer_test.js', ['goog.ui.MenuSeparatorRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.MenuSeparator', 'goog.ui.MenuSeparatorRenderer'], false);
+goog.addDependency('ui/mockactivitymonitor.js', ['goog.ui.MockActivityMonitor'], ['goog.events.EventType', 'goog.ui.ActivityMonitor'], false);
+goog.addDependency('ui/mockactivitymonitor_test.js', ['goog.ui.MockActivityMonitorTest'], ['goog.events', 'goog.functions', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.ActivityMonitor', 'goog.ui.MockActivityMonitor'], false);
+goog.addDependency('ui/modalpopup.js', ['goog.ui.ModalPopup'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.iframe', 'goog.events', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.fx.Transition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.PopupBase', 'goog.userAgent'], false);
+goog.addDependency('ui/modalpopup_test.js', ['goog.ui.ModalPopupTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dispose', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventTarget', 'goog.fx.Transition', 'goog.fx.css3', 'goog.string', 'goog.style', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ModalPopup', 'goog.ui.PopupBase'], false);
+goog.addDependency('ui/nativebuttonrenderer.js', ['goog.ui.NativeButtonRenderer'], ['goog.asserts', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.ui.ButtonRenderer', 'goog.ui.Component'], false);
+goog.addDependency('ui/nativebuttonrenderer_test.js', ['goog.ui.NativeButtonRendererTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.testing.ExpectedFailures', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.NativeButtonRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/option.js', ['goog.ui.Option'], ['goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.registry'], false);
+goog.addDependency('ui/palette.js', ['goog.ui.Palette'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.PaletteRenderer', 'goog.ui.SelectionModel'], false);
+goog.addDependency('ui/palette_test.js', ['goog.ui.PaletteTest'], ['goog.a11y.aria', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyEvent', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Palette'], false);
+goog.addDependency('ui/paletterenderer.js', ['goog.ui.PaletteRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.iter', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/paletterenderer_test.js', ['goog.ui.PaletteRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.Palette', 'goog.ui.PaletteRenderer'], false);
+goog.addDependency('ui/plaintextspellchecker.js', ['goog.ui.PlainTextSpellChecker'], ['goog.Timer', 'goog.a11y.aria', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.spell.SpellCheck', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/plaintextspellchecker_test.js', ['goog.ui.PlainTextSpellCheckerTest'], ['goog.Timer', 'goog.dom', 'goog.events.KeyCodes', 'goog.spell.SpellCheck', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.PlainTextSpellChecker'], false);
+goog.addDependency('ui/popup.js', ['goog.ui.Popup', 'goog.ui.Popup.AbsolutePosition', 'goog.ui.Popup.AnchoredPosition', 'goog.ui.Popup.AnchoredViewPortPosition', 'goog.ui.Popup.ClientPosition', 'goog.ui.Popup.Overflow', 'goog.ui.Popup.ViewPortClientPosition', 'goog.ui.Popup.ViewPortPosition'], ['goog.math.Box', 'goog.positioning.AbsolutePosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.ClientPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.positioning.ViewportPosition', 'goog.style', 'goog.ui.PopupBase'], false);
+goog.addDependency('ui/popup_test.js', ['goog.ui.PopupTest'], ['goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit', 'goog.ui.Popup', 'goog.userAgent'], false);
+goog.addDependency('ui/popupbase.js', ['goog.ui.PopupBase', 'goog.ui.PopupBase.EventType', 'goog.ui.PopupBase.Type'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.style', 'goog.userAgent'], false);
+goog.addDependency('ui/popupbase_test.js', ['goog.ui.PopupBaseTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.fx.css3', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.PopupBase'], false);
+goog.addDependency('ui/popupcolorpicker.js', ['goog.ui.PopupColorPicker'], ['goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.ColorPicker', 'goog.ui.Component', 'goog.ui.Popup'], false);
+goog.addDependency('ui/popupcolorpicker_test.js', ['goog.ui.PopupColorPickerTest'], ['goog.dom', 'goog.events', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.ColorPicker', 'goog.ui.PopupColorPicker'], false);
+goog.addDependency('ui/popupdatepicker.js', ['goog.ui.PopupDatePicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.style', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.Popup', 'goog.ui.PopupBase'], false);
+goog.addDependency('ui/popupdatepicker_test.js', ['goog.ui.PopupDatePickerTest'], ['goog.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker'], false);
+goog.addDependency('ui/popupmenu.js', ['goog.ui.PopupMenu'], ['goog.events.EventType', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.PopupBase', 'goog.userAgent'], false);
+goog.addDependency('ui/popupmenu_test.js', ['goog.ui.PopupMenuTest'], ['goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.PopupMenu'], false);
+goog.addDependency('ui/progressbar.js', ['goog.ui.ProgressBar', 'goog.ui.ProgressBar.Orientation'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.RangeModel', 'goog.userAgent'], false);
+goog.addDependency('ui/prompt.js', ['goog.ui.Prompt'], ['goog.Timer', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.functions', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.ui.Component', 'goog.ui.Dialog', 'goog.userAgent'], false);
+goog.addDependency('ui/prompt_test.js', ['goog.ui.PromptTest'], ['goog.dom.selection', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.functions', 'goog.string', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.BidiInput', 'goog.ui.Dialog', 'goog.ui.Prompt', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('ui/rangemodel.js', ['goog.ui.RangeModel'], ['goog.events.EventTarget', 'goog.ui.Component'], false);
+goog.addDependency('ui/rangemodel_test.js', ['goog.ui.RangeModelTest'], ['goog.testing.jsunit', 'goog.ui.RangeModel'], false);
+goog.addDependency('ui/ratings.js', ['goog.ui.Ratings', 'goog.ui.Ratings.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.ui.Component'], false);
+goog.addDependency('ui/registry.js', ['goog.ui.registry'], ['goog.asserts', 'goog.dom.classlist'], false);
+goog.addDependency('ui/registry_test.js', ['goog.ui.registryTest'], ['goog.object', 'goog.testing.jsunit', 'goog.ui.registry'], false);
+goog.addDependency('ui/richtextspellchecker.js', ['goog.ui.RichTextSpellChecker'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.Component', 'goog.ui.PopupMenu'], false);
+goog.addDependency('ui/richtextspellchecker_test.js', ['goog.ui.RichTextSpellCheckerTest'], ['goog.dom.Range', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.object', 'goog.spell.SpellCheck', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.RichTextSpellChecker'], false);
+goog.addDependency('ui/roundedpanel.js', ['goog.ui.BaseRoundedPanel', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.ui.RoundedPanel.Corner'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.graphics', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/roundedpanel_test.js', ['goog.ui.RoundedPanelTest'], ['goog.testing.jsunit', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.userAgent'], false);
+goog.addDependency('ui/roundedtabrenderer.js', ['goog.ui.RoundedTabRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.TabRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/scrollfloater.js', ['goog.ui.ScrollFloater', 'goog.ui.ScrollFloater.EventType'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/scrollfloater_test.js', ['goog.ui.ScrollFloaterTest'], ['goog.dom', 'goog.events', 'goog.style', 'goog.testing.jsunit', 'goog.ui.ScrollFloater'], false);
+goog.addDependency('ui/select.js', ['goog.ui.Select'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.IdGenerator', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.SelectionModel', 'goog.ui.registry'], false);
+goog.addDependency('ui/select_test.js', ['goog.ui.SelectTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.Select', 'goog.ui.Separator'], false);
+goog.addDependency('ui/selectionmenubutton.js', ['goog.ui.SelectionMenuButton', 'goog.ui.SelectionMenuButton.SelectionState'], ['goog.dom.InputType', 'goog.dom.TagName', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.registry'], false);
+goog.addDependency('ui/selectionmenubutton_test.js', ['goog.ui.SelectionMenuButtonTest'], ['goog.dom', 'goog.events', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.SelectionMenuButton'], false);
+goog.addDependency('ui/selectionmodel.js', ['goog.ui.SelectionModel'], ['goog.array', 'goog.events.EventTarget', 'goog.events.EventType'], false);
+goog.addDependency('ui/selectionmodel_test.js', ['goog.ui.SelectionModelTest'], ['goog.array', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.SelectionModel'], false);
+goog.addDependency('ui/separator.js', ['goog.ui.Separator'], ['goog.a11y.aria', 'goog.asserts', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuSeparatorRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/serverchart.js', ['goog.ui.ServerChart', 'goog.ui.ServerChart.AxisDisplayType', 'goog.ui.ServerChart.ChartType', 'goog.ui.ServerChart.EncodingType', 'goog.ui.ServerChart.Event', 'goog.ui.ServerChart.LegendPosition', 'goog.ui.ServerChart.MaximumValue', 'goog.ui.ServerChart.MultiAxisAlignment', 'goog.ui.ServerChart.MultiAxisType', 'goog.ui.ServerChart.UriParam', 'goog.ui.ServerChart.UriTooLongEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.Component'], false);
+goog.addDependency('ui/serverchart_test.js', ['goog.ui.ServerChartTest'], ['goog.Uri', 'goog.events', 'goog.testing.jsunit', 'goog.ui.ServerChart'], false);
+goog.addDependency('ui/slider.js', ['goog.ui.Slider', 'goog.ui.Slider.Orientation'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.dom.TagName', 'goog.ui.SliderBase'], false);
+goog.addDependency('ui/sliderbase.js', ['goog.ui.SliderBase', 'goog.ui.SliderBase.AnimationFactory', 'goog.ui.SliderBase.Orientation'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.MouseWheelHandler', 'goog.functions', 'goog.fx.AnimationParallelQueue', 'goog.fx.Dragger', 'goog.fx.Transition', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Slide', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.ui.RangeModel'], false);
+goog.addDependency('ui/sliderbase_test.js', ['goog.ui.SliderBaseTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Animation', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.SliderBase', 'goog.userAgent'], false);
+goog.addDependency('ui/splitbehavior.js', ['goog.ui.SplitBehavior', 'goog.ui.SplitBehavior.DefaultHandlers'], ['goog.Disposable', 'goog.asserts', 'goog.dispose', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.decorate', 'goog.ui.registry'], false);
+goog.addDependency('ui/splitbehavior_test.js', ['goog.ui.SplitBehaviorTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.CustomButton', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.SplitBehavior', 'goog.ui.decorate'], false);
+goog.addDependency('ui/splitpane.js', ['goog.ui.SplitPane', 'goog.ui.SplitPane.Orientation'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false);
+goog.addDependency('ui/splitpane_test.js', ['goog.ui.SplitPaneTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.math.Size', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.SplitPane'], false);
+goog.addDependency('ui/style/app/buttonrenderer.js', ['goog.ui.style.app.ButtonRenderer'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false);
+goog.addDependency('ui/style/app/buttonrenderer_test.js', ['goog.ui.style.app.ButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.style.app.ButtonRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/style/app/menubuttonrenderer.js', ['goog.ui.style.app.MenuButtonRenderer'], ['goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuRenderer', 'goog.ui.style.app.ButtonRenderer'], false);
+goog.addDependency('ui/style/app/menubuttonrenderer_test.js', ['goog.ui.style.app.MenuButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Component', 'goog.ui.MenuButton', 'goog.ui.style.app.MenuButtonRenderer'], false);
+goog.addDependency('ui/style/app/primaryactionbuttonrenderer.js', ['goog.ui.style.app.PrimaryActionButtonRenderer'], ['goog.ui.Button', 'goog.ui.registry', 'goog.ui.style.app.ButtonRenderer'], false);
+goog.addDependency('ui/style/app/primaryactionbuttonrenderer_test.js', ['goog.ui.style.app.PrimaryActionButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.style.app.PrimaryActionButtonRenderer'], false);
+goog.addDependency('ui/submenu.js', ['goog.ui.SubMenu'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.style', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenuRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/submenu_test.js', ['goog.ui.SubMenuTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.functions', 'goog.positioning', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenu', 'goog.ui.SubMenuRenderer'], false);
+goog.addDependency('ui/submenurenderer.js', ['goog.ui.SubMenuRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuItemRenderer'], false);
+goog.addDependency('ui/tab.js', ['goog.ui.Tab'], ['goog.ui.Component', 'goog.ui.Control', 'goog.ui.TabRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/tab_test.js', ['goog.ui.TabTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Tab', 'goog.ui.TabRenderer'], false);
+goog.addDependency('ui/tabbar.js', ['goog.ui.TabBar', 'goog.ui.TabBar.Location'], ['goog.ui.Component.EventType', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.Tab', 'goog.ui.TabBarRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/tabbar_test.js', ['goog.ui.TabBarTest'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.TabBarRenderer'], false);
+goog.addDependency('ui/tabbarrenderer.js', ['goog.ui.TabBarRenderer'], ['goog.a11y.aria.Role', 'goog.object', 'goog.ui.ContainerRenderer'], false);
+goog.addDependency('ui/tabbarrenderer_test.js', ['goog.ui.TabBarRendererTest'], ['goog.a11y.aria.Role', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Container', 'goog.ui.TabBar', 'goog.ui.TabBarRenderer'], false);
+goog.addDependency('ui/tablesorter.js', ['goog.ui.TableSorter', 'goog.ui.TableSorter.EventType'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.functions', 'goog.ui.Component'], false);
+goog.addDependency('ui/tablesorter_test.js', ['goog.ui.TableSorterTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.TableSorter'], false);
+goog.addDependency('ui/tabpane.js', ['goog.ui.TabPane', 'goog.ui.TabPane.Events', 'goog.ui.TabPane.TabLocation', 'goog.ui.TabPane.TabPage', 'goog.ui.TabPaneEvent'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style'], false);
+goog.addDependency('ui/tabpane_test.js', ['goog.ui.TabPaneTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.TabPane'], false);
+goog.addDependency('ui/tabrenderer.js', ['goog.ui.TabRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/tabrenderer_test.js', ['goog.ui.TabRendererTest'], ['goog.a11y.aria.Role', 'goog.dom', 'goog.dom.classlist', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Tab', 'goog.ui.TabRenderer'], false);
+goog.addDependency('ui/textarea.js', ['goog.ui.Textarea', 'goog.ui.Textarea.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.style', 'goog.ui.Control', 'goog.ui.TextareaRenderer', 'goog.userAgent'], false);
+goog.addDependency('ui/textarea_test.js', ['goog.ui.TextareaTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.events.EventObserver', 'goog.testing.jsunit', 'goog.ui.Textarea', 'goog.ui.TextareaRenderer', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('ui/textarearenderer.js', ['goog.ui.TextareaRenderer'], ['goog.dom.TagName', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false);
+goog.addDependency('ui/togglebutton.js', ['goog.ui.ToggleButton'], ['goog.ui.Button', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/toolbar.js', ['goog.ui.Toolbar'], ['goog.ui.Container', 'goog.ui.ToolbarRenderer'], false);
+goog.addDependency('ui/toolbar_test.js', ['goog.ui.ToolbarTest'], ['goog.a11y.aria', 'goog.dom', 'goog.events.EventType', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.Toolbar', 'goog.ui.ToolbarMenuButton'], false);
+goog.addDependency('ui/toolbarbutton.js', ['goog.ui.ToolbarButton'], ['goog.ui.Button', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/toolbarbuttonrenderer.js', ['goog.ui.ToolbarButtonRenderer'], ['goog.ui.CustomButtonRenderer'], false);
+goog.addDependency('ui/toolbarcolormenubutton.js', ['goog.ui.ToolbarColorMenuButton'], ['goog.ui.ColorMenuButton', 'goog.ui.ToolbarColorMenuButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/toolbarcolormenubuttonrenderer.js', ['goog.ui.ToolbarColorMenuButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.MenuButtonRenderer', 'goog.ui.ToolbarMenuButtonRenderer'], false);
+goog.addDependency('ui/toolbarcolormenubuttonrenderer_test.js', ['goog.ui.ToolbarColorMenuButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.RendererHarness', 'goog.testing.ui.rendererasserts', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarColorMenuButtonRenderer'], false);
+goog.addDependency('ui/toolbarmenubutton.js', ['goog.ui.ToolbarMenuButton'], ['goog.ui.MenuButton', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/toolbarmenubuttonrenderer.js', ['goog.ui.ToolbarMenuButtonRenderer'], ['goog.ui.MenuButtonRenderer'], false);
+goog.addDependency('ui/toolbarrenderer.js', ['goog.ui.ToolbarRenderer'], ['goog.a11y.aria.Role', 'goog.dom.TagName', 'goog.ui.Container', 'goog.ui.ContainerRenderer', 'goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer'], false);
+goog.addDependency('ui/toolbarselect.js', ['goog.ui.ToolbarSelect'], ['goog.ui.Select', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/toolbarseparator.js', ['goog.ui.ToolbarSeparator'], ['goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/toolbarseparatorrenderer.js', ['goog.ui.ToolbarSeparatorRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuSeparatorRenderer'], false);
+goog.addDependency('ui/toolbarseparatorrenderer_test.js', ['goog.ui.ToolbarSeparatorRendererTest'], ['goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.ToolbarSeparator', 'goog.ui.ToolbarSeparatorRenderer'], false);
+goog.addDependency('ui/toolbartogglebutton.js', ['goog.ui.ToolbarToggleButton'], ['goog.ui.ToggleButton', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/tooltip.js', ['goog.ui.Tooltip', 'goog.ui.Tooltip.CursorTooltipPosition', 'goog.ui.Tooltip.ElementTooltipPosition', 'goog.ui.Tooltip.State'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.EventType', 'goog.html.legacyconversions', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.positioning.ViewportPosition', 'goog.structs.Set', 'goog.style', 'goog.ui.Popup', 'goog.ui.PopupBase'], false);
+goog.addDependency('ui/tooltip_test.js', ['goog.ui.TooltipTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.html.testing', 'goog.math.Coordinate', 'goog.positioning.AbsolutePosition', 'goog.style', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestQueue', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.PopupBase', 'goog.ui.Tooltip', 'goog.userAgent'], false);
+goog.addDependency('ui/tree/basenode.js', ['goog.ui.tree.BaseNode', 'goog.ui.tree.BaseNode.EventType'], ['goog.Timer', 'goog.a11y.aria', 'goog.asserts', 'goog.dom.safe', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.legacyconversions', 'goog.string', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.Component'], false);
+goog.addDependency('ui/tree/basenode_test.js', ['goog.ui.tree.BaseNodeTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.html.legacyconversions', 'goog.html.testing', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TreeNode'], false);
+goog.addDependency('ui/tree/treecontrol.js', ['goog.ui.tree.TreeControl'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.events.KeyHandler', 'goog.html.SafeHtml', 'goog.log', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeNode', 'goog.ui.tree.TypeAhead', 'goog.userAgent'], false);
+goog.addDependency('ui/tree/treecontrol_test.js', ['goog.ui.tree.TreeControlTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.tree.TreeControl'], false);
+goog.addDependency('ui/tree/treenode.js', ['goog.ui.tree.TreeNode'], ['goog.ui.tree.BaseNode'], false);
+goog.addDependency('ui/tree/typeahead.js', ['goog.ui.tree.TypeAhead', 'goog.ui.tree.TypeAhead.Offset'], ['goog.array', 'goog.events.KeyCodes', 'goog.string', 'goog.structs.Trie'], false);
+goog.addDependency('ui/tree/typeahead_test.js', ['goog.ui.tree.TypeAheadTest'], ['goog.dom', 'goog.events.KeyCodes', 'goog.testing.jsunit', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TypeAhead'], false);
+goog.addDependency('ui/tristatemenuitem.js', ['goog.ui.TriStateMenuItem', 'goog.ui.TriStateMenuItem.State'], ['goog.dom.classlist', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.TriStateMenuItemRenderer', 'goog.ui.registry'], false);
+goog.addDependency('ui/tristatemenuitemrenderer.js', ['goog.ui.TriStateMenuItemRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.MenuItemRenderer'], false);
+goog.addDependency('ui/twothumbslider.js', ['goog.ui.TwoThumbSlider'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.dom.TagName', 'goog.ui.SliderBase'], false);
+goog.addDependency('ui/twothumbslider_test.js', ['goog.ui.TwoThumbSliderTest'], ['goog.testing.jsunit', 'goog.ui.SliderBase', 'goog.ui.TwoThumbSlider'], false);
+goog.addDependency('ui/zippy.js', ['goog.ui.Zippy', 'goog.ui.Zippy.Events', 'goog.ui.ZippyEvent'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style'], false);
+goog.addDependency('ui/zippy_test.js', ['goog.ui.ZippyTest'], ['goog.a11y.aria', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.object', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Zippy'], false);
+goog.addDependency('uri/uri.js', ['goog.Uri', 'goog.Uri.QueryData'], ['goog.array', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.StandardQueryParam'], false);
+goog.addDependency('uri/uri_test.js', ['goog.UriTest'], ['goog.Uri', 'goog.testing.jsunit'], false);
+goog.addDependency('uri/utils.js', ['goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.QueryArray', 'goog.uri.utils.QueryValue', 'goog.uri.utils.StandardQueryParam'], ['goog.asserts', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('uri/utils_test.js', ['goog.uri.utilsTest'], ['goog.functions', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.uri.utils'], false);
+goog.addDependency('useragent/adobereader.js', ['goog.userAgent.adobeReader'], ['goog.string', 'goog.userAgent'], false);
+goog.addDependency('useragent/adobereader_test.js', ['goog.userAgent.adobeReaderTest'], ['goog.testing.jsunit', 'goog.userAgent.adobeReader'], false);
+goog.addDependency('useragent/flash.js', ['goog.userAgent.flash'], ['goog.string'], false);
+goog.addDependency('useragent/flash_test.js', ['goog.userAgent.flashTest'], ['goog.testing.jsunit', 'goog.userAgent.flash'], false);
+goog.addDependency('useragent/iphoto.js', ['goog.userAgent.iphoto'], ['goog.string', 'goog.userAgent'], false);
+goog.addDependency('useragent/jscript.js', ['goog.userAgent.jscript'], ['goog.string'], false);
+goog.addDependency('useragent/jscript_test.js', ['goog.userAgent.jscriptTest'], ['goog.testing.jsunit', 'goog.userAgent.jscript'], false);
+goog.addDependency('useragent/keyboard.js', ['goog.userAgent.keyboard'], ['goog.labs.userAgent.platform'], false);
+goog.addDependency('useragent/keyboard_test.js', ['goog.userAgent.keyboardTest'], ['goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent.keyboard', 'goog.userAgentTestUtil'], false);
+goog.addDependency('useragent/platform.js', ['goog.userAgent.platform'], ['goog.string', 'goog.userAgent'], false);
+goog.addDependency('useragent/platform_test.js', ['goog.userAgent.platformTest'], ['goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.platform', 'goog.userAgentTestUtil'], false);
+goog.addDependency('useragent/product.js', ['goog.userAgent.product'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.platform', 'goog.userAgent'], false);
+goog.addDependency('useragent/product_isversion.js', ['goog.userAgent.product.isVersion'], ['goog.labs.userAgent.platform', 'goog.string', 'goog.userAgent', 'goog.userAgent.product'], false);
+goog.addDependency('useragent/product_test.js', ['goog.userAgent.productTest'], ['goog.array', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion', 'goog.userAgentTestUtil'], false);
+goog.addDependency('useragent/useragent.js', ['goog.userAgent'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.labs.userAgent.util', 'goog.string'], false);
+goog.addDependency('useragent/useragent_quirks_test.js', ['goog.userAgentQuirksTest'], ['goog.testing.jsunit', 'goog.userAgent'], false);
+goog.addDependency('useragent/useragent_test.js', ['goog.userAgentTest'], ['goog.array', 'goog.labs.userAgent.platform', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil'], false);
+goog.addDependency('useragent/useragenttestutil.js', ['goog.userAgentTestUtil', 'goog.userAgentTestUtil.UserAgents'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.userAgent', 'goog.userAgent.keyboard', 'goog.userAgent.platform', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false);
+goog.addDependency('vec/float32array.js', ['goog.vec.Float32Array'], [], false);
+goog.addDependency('vec/float64array.js', ['goog.vec.Float64Array'], [], false);
+goog.addDependency('vec/mat3.js', ['goog.vec.Mat3'], ['goog.vec'], false);
+goog.addDependency('vec/mat3d.js', ['goog.vec.mat3d', 'goog.vec.mat3d.Type'], ['goog.vec'], false);
+goog.addDependency('vec/mat3f.js', ['goog.vec.mat3f', 'goog.vec.mat3f.Type'], ['goog.vec'], false);
+goog.addDependency('vec/mat4.js', ['goog.vec.Mat4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4'], false);
+goog.addDependency('vec/mat4d.js', ['goog.vec.mat4d', 'goog.vec.mat4d.Type'], ['goog.vec', 'goog.vec.vec3d', 'goog.vec.vec4d'], false);
+goog.addDependency('vec/mat4f.js', ['goog.vec.mat4f', 'goog.vec.mat4f.Type'], ['goog.vec', 'goog.vec.vec3f', 'goog.vec.vec4f'], false);
+goog.addDependency('vec/matrix3.js', ['goog.vec.Matrix3'], [], false);
+goog.addDependency('vec/matrix4.js', ['goog.vec.Matrix4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4'], false);
+goog.addDependency('vec/quaternion.js', ['goog.vec.Quaternion'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4'], false);
+goog.addDependency('vec/ray.js', ['goog.vec.Ray'], ['goog.vec.Vec3'], false);
+goog.addDependency('vec/vec.js', ['goog.vec', 'goog.vec.AnyType', 'goog.vec.ArrayType', 'goog.vec.Float32', 'goog.vec.Float64', 'goog.vec.Number'], ['goog.vec.Float32Array', 'goog.vec.Float64Array'], false);
+goog.addDependency('vec/vec2.js', ['goog.vec.Vec2'], ['goog.vec'], false);
+goog.addDependency('vec/vec2d.js', ['goog.vec.vec2d', 'goog.vec.vec2d.Type'], ['goog.vec'], false);
+goog.addDependency('vec/vec2f.js', ['goog.vec.vec2f', 'goog.vec.vec2f.Type'], ['goog.vec'], false);
+goog.addDependency('vec/vec3.js', ['goog.vec.Vec3'], ['goog.vec'], false);
+goog.addDependency('vec/vec3d.js', ['goog.vec.vec3d', 'goog.vec.vec3d.Type'], ['goog.vec'], false);
+goog.addDependency('vec/vec3f.js', ['goog.vec.vec3f', 'goog.vec.vec3f.Type'], ['goog.vec'], false);
+goog.addDependency('vec/vec4.js', ['goog.vec.Vec4'], ['goog.vec'], false);
+goog.addDependency('vec/vec4d.js', ['goog.vec.vec4d', 'goog.vec.vec4d.Type'], ['goog.vec'], false);
+goog.addDependency('vec/vec4f.js', ['goog.vec.vec4f', 'goog.vec.vec4f.Type'], ['goog.vec'], false);
+goog.addDependency('webgl/webgl.js', ['goog.webgl'], [], false);
+goog.addDependency('window/window.js', ['goog.window'], ['goog.dom.TagName', 'goog.labs.userAgent.platform', 'goog.string', 'goog.userAgent'], false);
+goog.addDependency('window/window_test.js', ['goog.windowTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.functions', 'goog.labs.userAgent.platform', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.window'], false);
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/00_test_list.txt
new file mode 100644
index 0000000000..96a88cac2a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/00_test_list.txt
@@ -0,0 +1,19 @@
+attribs/00_test_list.txt
+buffers/00_test_list.txt
+canvas/00_test_list.txt
+context/00_test_list.txt
+extensions/00_test_list.txt
+glsl/00_test_list.txt
+limits/00_test_list.txt
+misc/00_test_list.txt
+--min-version 1.0.2 ogles/00_test_list.txt
+--min-version 1.0.4 offscreencanvas/00_test_list.txt
+programs/00_test_list.txt
+reading/00_test_list.txt
+renderbuffers/00_test_list.txt
+rendering/00_test_list.txt
+state/00_test_list.txt
+textures/00_test_list.txt
+typedarrays/00_test_list.txt
+uniforms/00_test_list.txt
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt
new file mode 100644
index 0000000000..317fe70233
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt
@@ -0,0 +1,15 @@
+--min-version 1.0.3 gl-bindAttribLocation-aliasing.html
+--min-version 1.0.3 gl-bindAttribLocation-matrix.html
+--min-version 1.0.4 gl-bindAttribLocation-nonexistent-attribute.html
+--min-version 1.0.4 gl-bindAttribLocation-repeated.html
+--min-version 1.0.2 gl-disabled-vertex-attrib.html
+--min-version 1.0.4 gl-disabled-vertex-attrib-update.html
+gl-enable-vertex-attrib.html
+--min-version 1.0.3 gl-matrix-attributes.html
+--max-version 1.9.9 gl-vertex-attrib.html
+gl-vertexattribpointer.html
+gl-vertexattribpointer-offsets.html
+--min-version 1.0.2 gl-vertex-attrib-render.html
+gl-vertex-attrib-zero-issues.html
+--min-version 1.0.4 gl-vertex-attrib-unconsumed-out-of-bounds.html
+--min-version 1.0.4 gl-vertex-attrib-context-switch.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html
new file mode 100644
index 0000000000..aae54715dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/gl-bindattriblocation-aliasing.js"></script>
+<title>bindAttribLocation with aliasing</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script id="vertexShader" type="text/something-not-javascript">
+precision mediump float;
+attribute $(type_1) a_1;
+attribute $(type_2) a_2;
+void main() {
+ gl_Position = $(gl_Position_1) + $(gl_Position_2);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies combinations of valid, active attribute types cannot be bound to the same location with bindAttribLocation.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);
+
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShader'));
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html
new file mode 100644
index 0000000000..ef5fd25b19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL bindAttribLocation with Matrix Attributes Conformance Test</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script>
+"use strict";
+description("This test verifies that vectors placed via bindAttribLocation right after matricies will fail if there is insufficient room for the matrix.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+// Make sure we have room for at least a mat4.
+var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes);
+shouldBeGreaterThanOrEqual('maxAttributes', '4');
+
+var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);
+
+// Given a matrix dimension, load a vertex shader with a matrix of that dimension
+// and a vector. Ensure that both the vector and matrix are active attributes.
+// Return the compiled vertex shader.
+function loadVertexShader(numMatrixDimensions) {
+ var strVertexShader =
+ 'attribute mat' + numMatrixDimensions + ' matrix;\n' +
+ 'attribute vec' + numMatrixDimensions + ' vector;\n' +
+ 'void main(void) { gl_Position = vec4(vector*matrix';
+ // Ensure the vec4 has the correct number of dimensions in order to be assignable
+ // to gl_Position.
+ for (var ii = numMatrixDimensions; ii < 4; ++ii) {
+ strVertexShader += ",0.0";
+ }
+ strVertexShader += ");}\n";
+ return wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
+}
+
+// Given a vertex shader, matrix location and vector location, create and link
+// a program with glFragmentShader and a vertex shader returned by loadVertexShader
+// attached. Bind the matrix to matrixLocation and the vector to vectorLocation.
+// Return whether the link was successful.
+function createAndLinkProgram(glVertexShader, matrixLocation, vectorLocation) {
+ var glProgram = gl.createProgram();
+ gl.bindAttribLocation(glProgram, matrixLocation, 'matrix');
+ gl.bindAttribLocation(glProgram, vectorLocation, 'vector');
+ gl.attachShader(glProgram, glVertexShader);
+ gl.attachShader(glProgram, glFragmentShader);
+ gl.linkProgram(glProgram);
+ return gl.getProgramParameter(glProgram, gl.LINK_STATUS);
+}
+
+// For each matrix dimension (mat2, mat3 and mat4)
+for (var mm = 2; mm <= 4; ++mm) {
+ debug('Testing ' + mm + ' dimensional matrices');
+ var glVertexShader = loadVertexShader(mm);
+ // Per the WebGL spec: "LinkProgram will fail if the attribute bindings assigned
+ // by bindAttribLocation do not leave enough space to assign a location for an
+ // active matrix attribute which requires multiple contiguous generic attributes."
+ // We will test this by placing the vector after the matrix attribute such that there
+ // is not enough room for the matrix. Vertify the link operation fails.
+
+ // Run the test for each available attribute slot. Go to maxAttributes-mm to leave enough room
+ // for the matrix itself. Leave another slot open for the vector following the matrix.
+ for (var pp = 0; pp <= maxAttributes - mm - 1; ++pp) {
+ // For each matrix dimension, bind the vector right after the matrix such that we leave
+ // insufficient room for the matrix. Verify doing this will fail the link operation.
+ for (var ll = 0; ll < mm; ++ll) {
+ var vectorLocation = pp + ll;
+ assertMsg(!createAndLinkProgram(glVertexShader, /*matrixLocation*/pp, vectorLocation),
+ "Matrix with location " + pp + " and vector with location " + vectorLocation + " should not link.");
+ }
+ // Ensure that once we have left enough room for the matrix, the program links successfully.
+ var vectorLocation = pp + ll;
+ assertMsg(createAndLinkProgram(glVertexShader, /*matrixLocation*/pp, vectorLocation),
+ "Matrix with location " + pp + " and vector with location " + vectorLocation + " should link.");
+ debug('');
+ }
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html
new file mode 100644
index 0000000000..d6968b5ea4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html
@@ -0,0 +1,82 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>bindAttribLocation with nonexistent attribute name</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8"></canvas>
+<script id="vertexShader" type="text/something-not-javascript">
+precision highp float;
+attribute vec4 attr;
+void main() {
+ gl_Position = vec4(attr);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies that calling bindAttribLocation with a non-existent attribute location is fine.");
+
+// OpenGL ES 2.0.25 section 2.10 page 34.
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var fragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);
+var vertexShader = wtu.loadShaderFromScript(gl, 'vertexShader', gl.VERTEX_SHADER);
+assertMsg(vertexShader != null, "Vertex shader compiled successfully.");
+
+var checkAttribLocation = function(program, expectedLocation) {
+ var location = gl.getAttribLocation(program, 'attr');
+ if (location != expectedLocation) {
+ testFailed('Unexpected location for attr: ' + location);
+ } else {
+ testPassed('Location of attr is: ' + location);
+ }
+}
+
+var testProgramNonExistentAttributeBound = function() {
+ var program = gl.createProgram();
+ gl.bindAttribLocation(program, 0, 'attr');
+ gl.bindAttribLocation(program, 1, 'bogus_attr');
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+ var linkStatus = gl.getProgramParameter(program, gl.LINK_STATUS);
+ expectTrue(linkStatus, "Link should succeed even if a non-existent attribute is bound.");
+ if (linkStatus) {
+ checkAttribLocation(program, 0);
+ }
+};
+var testProgramNonExistentAttributeOverlap = function() {
+ var program = gl.createProgram();
+ gl.bindAttribLocation(program, 1, 'attr');
+ gl.bindAttribLocation(program, 1, 'bogus_attr');
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+ var linkStatus = gl.getProgramParameter(program, gl.LINK_STATUS);
+ expectTrue(linkStatus, "Link should succeed even if a non-existent attribute is bound to the same location as an attribute that's present in the shader text.");
+ if (linkStatus) {
+ checkAttribLocation(program, 1);
+ }
+};
+
+testProgramNonExistentAttributeBound();
+testProgramNonExistentAttributeOverlap();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html
new file mode 100644
index 0000000000..cfbea4fb63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html
@@ -0,0 +1,68 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Repeated BindAttribLocation Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+ void main()
+ {
+ gl_FragColor = vec4(0.0,1.0,0.0,1.0);
+ }
+</script>
+
+<script>
+"use strict";
+description("Test repeated loading of programs involving bindAttribLocation calls");
+debug("Regression test for <a href='https://code.google.com/p/chromium/issues/detail?id=510637'>crbug.com/510637</a>");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var g_program;
+var g_attribLocation;
+function setup(attribIndex) {
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition'], [attribIndex]);
+ g_program = program;
+ g_attribLocation = attribIndex;
+ shouldBe("gl.getAttribLocation(g_program, 'vPosition')", "g_attribLocation");
+ return program;
+}
+
+var p0 = setup(0);
+var p3 = setup(3);
+var p1 = setup(1);
+// This call fails the getAttribLocation check on some drivers when
+// Chrome's program binary cache is enabled. On the affected drivers,
+// it returns the bound attribute location from the first binary
+// created. Swapping 0 and 1 above will cause it to return 1 rather
+// than 0.
+p3 = setup(3);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html
new file mode 100644
index 0000000000..3ef12fb9aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html
@@ -0,0 +1,79 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Disabled Vertex Attrib Update Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+attribute float a_actualValue;
+uniform float u_expectedValue;
+varying float v_result;
+void main() {
+ gl_Position = a_position;
+ v_result = a_actualValue == u_expectedValue ? 1.0 : 0.0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying float v_result;
+void main() {
+ gl_FragColor = v_result > 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script>
+// Tests that repeatedly updating a disabled vertex attribute works as expected.
+// This covers an ANGLE bug where dirty bits for current values were ignoring repeated updates.
+// Based on ANGLE test (VertexAttributeTest, DisabledAttribUpdates) from https://github.com/google/angle/blob/f7f0b8c3ab21c52cc2915048959361cf628d95f0/src/tests/gl_tests/VertexAttributeTest.cpp
+"use strict";
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example");
+
+var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+gl.useProgram(program);
+
+var positionLocation = gl.getAttribLocation(program, "a_position");
+var attribLoc = gl.getAttribLocation(program, "a_actualValue");
+gl.vertexAttribPointer(attribLoc, 1, gl.FLOAT, gl.FALSE, 0, 0);
+
+var uniLoc = gl.getUniformLocation(program, "u_expectedValue");
+
+var gridRes = 1;
+wtu.setupIndexedQuad(gl, gridRes, positionLocation);
+
+var testValues = [1, 2, 3, 4];
+for (var i = 0; i < testValues.length; ++i) {
+ var testValue = testValues[i];
+ gl.uniform1f(uniLoc, testValue);
+ gl.vertexAttrib1f(attribLoc, testValue);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html
new file mode 100644
index 0000000000..f4f8997449
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html
@@ -0,0 +1,79 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Disabled Vertex Attrib Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+attribute vec4 a_color;
+varying vec4 v_color;
+bool isCorrectColor(vec4 v) {
+ return v.x == 0.0 && v.y == 0.0 && v.z == 0.0 && v.w == 1.0;
+}
+void main() {
+ gl_Position = a_position;
+ v_color = isCorrectColor(a_color) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main() {
+ gl_FragColor = v_color;
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example");
+
+var numVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+for (var ii = 0; ii < numVertexAttribs; ++ii) {
+ var colorLocation = (ii + 1) % numVertexAttribs;
+ var positionLocation = colorLocation ? 0 : 1;
+
+ if (positionLocation != 0) {
+ // We need to create a new 3d context for testing attrib 0
+ // since we've already effected attrib 0 on other tests.
+ gl = wtu.create3DContext();
+ }
+
+ debug("testing attrib: " + colorLocation);
+ var program = wtu.setupProgram(
+ gl,
+ ['vshader', 'fshader'],
+ ['a_position', 'a_color'],
+ [positionLocation, colorLocation]);
+ var gridRes = 1;
+ wtu.setupIndexedQuad(gl, gridRes, positionLocation);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html
new file mode 100644
index 0000000000..6425a33a7a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+<meta charset="utf-8">
+ <title>WebGL Enable Vertex Attrib Test</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+ <script src="../../js/tests/invalid-vertex-attrib-test.js"></script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("tests that turning on attribs that have no buffer bound fails to draw");
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext("example");
+
+async function runInvalidAttribTests() {
+ const invalidAttribTestFn = createInvalidAttribTestFn(gl);
+
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ await invalidAttribTestFn(drawArrays);
+ await invalidAttribTestFn(drawElements);
+ finishTest();
+}
+runInvalidAttribTests();
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html
new file mode 100644
index 0000000000..fc7ab56b0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL Matrix Attribute Conformance Test</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script>
+"use strict";
+description("This tests ensures that matrix attribute locations do not clash with other shader attributes.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+// Make sure we have room for at least a mat4.
+var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes);
+shouldBeGreaterThanOrEqual('maxAttributes', '4');
+
+var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);
+
+// prepareMatrixProgram creates a program with glFragmentShader as the fragment shader.
+// The vertex shader has numVector number of vectors and a matrix with numMatrixDimensions
+// dimensions at location numMatrixPosition in the list of attributes.
+// Ensures that every vector and matrix is used by the program.
+// Returns a valid program on successfull link; null on link failure.
+function prepareMatrixProgram(numVectors, numMatrixDimensions, numMatrixPosition) {
+ // Add the matrix and vector attribute declarations. Declare the vectors
+ // to have the same number of components as the matrix so we can perform
+ // operations on them when we assign to gl_Position later on.
+ var strVertexShader = "";
+ for (var ii = 1; ii <= numVectors; ++ii) {
+ if (numMatrixPosition === ii) {
+ strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n";
+ }
+ strVertexShader += "attribute vec" + numMatrixDimensions + " vec_" + ii + ";\n";
+ }
+ // numMatrixPosition will be one past numVectors if the caller wants it to be
+ // last. Hence, we need this check outside the loop as well as inside.
+ if (numMatrixPosition === ii) {
+ strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n";
+ }
+ // Add the body of the shader. Add up all of the vectors and multiply by the matrix.
+ // The operations we perform do not matter. We just need to ensure that all the vector and
+ // matrix attributes are used.
+ strVertexShader += "void main(void) { \ngl_Position = vec4((";
+ for (var ii = 1; ii <= numVectors; ++ii) {
+ if (ii > 1) {
+ strVertexShader += "+"
+ }
+ strVertexShader += "vec_" + ii;
+ }
+ strVertexShader += ")*matrix";
+ // Ensure the vec4 has the correct number of dimensions in order to be assignable
+ // to gl_Position.
+ for (var ii = numMatrixDimensions; ii < 4; ++ii) {
+ strVertexShader += ",0.0";
+ }
+ strVertexShader += ");}\n";
+ // Load the shader, attach it to a program, and return the link results
+ var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
+ var strTest = 'Load shader with ' + numVectors + ' vectors and 1 matrix';
+ if (glVertexShader !== null) {
+ testPassed(strTest);
+
+ var glProgram = gl.createProgram();
+ gl.attachShader(glProgram, glVertexShader);
+ gl.attachShader(glProgram, glFragmentShader);
+ gl.linkProgram(glProgram);
+ if (gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'linkProgram');
+ return glProgram;
+ }
+ } else {
+ testFailed(strTest);
+ }
+ return null;
+}
+
+debug('');
+
+// Test mat2, mat3 and mat4.
+for (var mm = 2; mm <= 4; ++mm) {
+ // Add maxAttribute number of attributes by saving enough room in the attribute
+ // list for a matrix of mm dimensions. All of the other attribute slots will be
+ // filled with vectors.
+ var numVectors = maxAttributes - mm;
+ for (var pp = 1; pp <= numVectors + 1; ++pp) {
+ debug('Test ' + mm + ' dimensional matrix at position ' + pp);
+ var glProgram = prepareMatrixProgram(numVectors, /*numMatrixDimensions*/mm, /*numMatrixPosition*/pp);
+ shouldBeNonNull('glProgram');
+ var attribMatrix = gl.getAttribLocation(glProgram, 'matrix');
+ debug('Matrix is at attribute location ' + attribMatrix);
+ shouldBeTrue('attribMatrix > -1');
+ // Per the spec, when an attribute is a matrix attribute, getAttribLocation
+ // returns the index of the first component of the matrix. The implementation must
+ // leave sufficient room for all the components. Here we ensure none of the vectors
+ // in the shader are assigned attribute locations that belong to the matrix.
+ for (var vv = 1; vv <= numVectors; ++vv) {
+ var strVector = 'vec_' + vv
+ var attribVector = gl.getAttribLocation(glProgram, strVector);
+ debug(strVector + ' is at attribute location ' + attribVector);
+ // Begin with the first attribute location where the matrix begins and ensure
+ // the vector's attribute location is not assigned to the matrix. Loop until
+ // we've checked all of the attribute locations that belong to the matrix.
+ for (var ii = attribMatrix; ii < attribMatrix + mm; ++ii) {
+ var testStr = strVector + ' attribute location: ' + attribVector + '. Should not be ' + ii;
+ if (attribVector !== ii) {
+ testPassed(testStr);
+ } else {
+ testFailed(testStr);
+ }
+ }
+ }
+ debug('');
+ }
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html
new file mode 100644
index 0000000000..1db1c9a321
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html
@@ -0,0 +1,60 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+<meta charset="utf-8">
+ <title>WebGL Vertex Attrib Context Switch Test</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="one" width="50" height="50">
+</canvas>
+<canvas id="two" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("tests that vertex attrib value is preserved across context switches");
+var wtu = WebGLTestUtils;
+var positionLocation = 0;
+var colorLocation = 1;
+var gridRes = 1;
+
+var canvas1 = document.getElementById("one");
+var gl1 = wtu.create3DContext(canvas1);
+var program1 = wtu.setupSimpleVertexColorProgram(gl1, positionLocation, colorLocation);
+gl1.vertexAttrib4f(colorLocation, 0.0, 1.0, 0.0, 1.0);
+wtu.setupIndexedQuad(gl1, gridRes, positionLocation);
+wtu.clearAndDrawIndexedQuad(gl1, gridRes);
+wtu.checkCanvas(gl1, [0, 255, 0, 255], "should be green 1");
+
+var canvas2 = document.getElementById("two");
+var gl2 = wtu.create3DContext(canvas2);
+var program2 = wtu.setupSimpleVertexColorProgram(gl2, positionLocation, colorLocation);
+wtu.setupIndexedQuad(gl2, gridRes, positionLocation);
+wtu.clearAndDrawIndexedQuad(gl2, gridRes);
+wtu.checkCanvas(gl2, [0, 0, 0, 255], "should be black 1");
+
+wtu.checkCanvas(gl1, [0, 255, 0, 255], "should be green 2");
+
+wtu.clearAndDrawIndexedQuad(gl2, gridRes);
+wtu.checkCanvas(gl2, [0, 0, 0, 255], "should be black 2");
+
+wtu.clearAndDrawIndexedQuad(gl1, gridRes);
+wtu.checkCanvas(gl1, [0, 255, 0, 255], "should be green 3");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html
new file mode 100644
index 0000000000..b10ebfe688
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader'>
+attribute vec4 a;
+attribute vec2 p;
+void main() {
+ gl_Position = vec4(p.x + a.x + a.y + a.z + a.w, p.y, 0.0, 1.0);
+}
+</script>
+<script id='fshader' type='x-shader'>
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+function checkRedPortion(gl, w, low, high) {
+ var buf = new Uint8Array(w * w * 4);
+ gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var i = 0;
+ for (; i < w; ++i) {
+ if (buf[i * 4 + 0] == 255 && buf[i * 4 + 1] == 0 && buf[i * 4 + 2] == 0 && buf[i * 4 + 3] == 255) {
+ break;
+ }
+ }
+ return low <= i && i <= high;
+}
+
+function runTest() {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('testbed', { preserveDrawingBuffer : true });
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['p', 'a'])
+
+ gl.enableVertexAttribArray(gl.p);
+ var pos = gl.createBuffer();
+ pos.type = gl.FLOAT;
+ pos.size = 2;
+ pos.num = 4;
+ gl.bindBuffer(gl.ARRAY_BUFFER, pos);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(0, pos.size, pos.type, false, 0, 0);
+
+ debug('Test vertexAttrib[1..4]fv by setting different combinations that add up to 1.5 and use that when rendering.');
+ var vals = [[0.5], [0.1,0.4], [0.2,-0.2,0.5], [-1.0,0.3,0.2,2.0]];
+
+ for (var j = 0; j < 4; ++j) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl['vertexAttrib' + (j+1) + 'fv'](1, vals[j]);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, pos.num);
+
+ if (checkRedPortion(gl, 50, 50 * 0.7, 50 * 0.8)) {
+ testPassed('Attribute of size ' + (j+1) + ' was set correctly');
+ } else {
+ testFailed('Attribute of size ' + (j+1) + ' was not set correctly');
+ }
+ }
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that using constant attributes works.');
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html
new file mode 100644
index 0000000000..f704dd643b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html
@@ -0,0 +1,191 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Unconsumed Vertex Attributes Out of Bounds Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+ void main() { }
+</script>
+
+<script id="vshader_attrib" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main() {
+ gl_Position = vPosition;
+ }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+ void main() {
+ gl_FragColor = vec4(1);
+ }
+</script>
+
+<script>
+"use strict";
+description("Test that unconsumed vertex attributes are not read out of bounds");
+// Tests for http://crbug.com/756293 (driver crash on macOS)
+// and a class of similar bugs that could exist on other systems.
+
+var wtu = WebGLTestUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var gl = wtu.create3DContext("example");
+var g_program;
+var g_attribLocation;
+
+var numAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+var allocatedBuffer;
+var indexBuffer;
+
+function setupBuffers(numVerts) {
+ var vertices = new Float32Array(numVerts * 3);
+ allocatedBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, allocatedBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+
+ var indices = new Uint16Array(numVerts);
+ for (var ii = 0; ii < numVerts; ++ii) {
+ indices[ii] = ii;
+ }
+
+ indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+}
+
+var progNoAttribs = wtu.setupProgram(gl, ['vshader', 'fshader'], [], []);
+var progAttrib1 = wtu.setupProgram(gl, ['vshader_attrib', 'fshader'], ['vPosition'], [1]);
+var progAttrib2 = wtu.setupProgram(gl, ['vshader_attrib', 'fshader'], ['vPosition'], [2]);
+setupBuffers(60000);
+
+var unallocatedBuffer = gl.createBuffer();
+var tests = [];
+
+debug("");
+debug("<u>Tests with one unconsumed attribute<u>");
+
+tests.push({
+ name: "drawArrays",
+ errors: gl.NO_ERROR,
+ draw: function() { gl.drawArrays(gl.TRIANGLES, 0, 3); }
+});
+tests.push({
+ name: "drawElements",
+ errors: gl.NO_ERROR,
+ draw: function() { gl.drawElements(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0); }
+});
+
+if (contextVersion >= 2) {
+ tests.push({
+ name: "drawArraysInstanced",
+ errors: gl.NO_ERROR,
+ draw: function() { gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 1); }
+ });
+ tests.push({
+ name: "drawElementsInstanced",
+ errors: gl.NO_ERROR,
+ draw: function() { gl.drawElementsInstanced(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0, 1); }
+ });
+ tests.push({
+ name: "drawRangeElements",
+ errors: gl.NO_ERROR,
+ draw: function() { gl.drawRangeElements(gl.TRIANGLES, 0, 60000, 60000, gl.UNSIGNED_SHORT, 0, 1); }
+ });
+}
+
+// Run tests
+
+// Bound forever
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+
+for (var attrib = 0; attrib < numAttribs; ++attrib) {
+ debug("Attrib " + attrib + " unconsumed");
+ for (var i = 0; i < tests.length; ++i) {
+ var test = tests[i];
+ gl.useProgram(progNoAttribs);
+
+ gl.enableVertexAttribArray(attrib);
+ gl.bindBuffer(gl.ARRAY_BUFFER, unallocatedBuffer);
+ gl.vertexAttribPointer(attrib, 3, gl.FLOAT, false, 0, 0);
+
+ test.draw();
+
+ gl.disableVertexAttribArray(attrib);
+ wtu.glErrorShouldBe(gl, test.errors, test.name);
+ }
+}
+
+debug("");
+debug("<u>Tests with one consumed attribute and one unconsumed attribute<u>");
+
+var ext = gl.getExtension("ANGLE_instanced_arrays");
+if (!ext) {
+ debug("ANGLE_instanced_arrays not available - skipped");
+} else {
+ tests.push({
+ name: "drawArraysInstancedANGLE",
+ errors: gl.NO_ERROR,
+ draw: function() {
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 3, 1);
+ }
+ });
+ tests.push({
+ name: "drawElementsInstancedANGLE",
+ errors: gl.NO_ERROR,
+ draw: function() {
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0, 1);
+ }
+ });
+}
+
+// Note these don't trigger the macOS driver crash (http://crbug.com/756293)
+// but they still add potentially useful coverage.
+for (var attrib = 0; attrib < numAttribs; ++attrib) {
+ var consumedAttrib = attrib == 1 ? 2 : 1;
+ var prog = consumedAttrib == 1 ? progAttrib1 : progAttrib2;
+ debug("Attrib " + attrib +
+ " unconsumed (attrib " + consumedAttrib + " consumed)");
+
+ for (var i = 0; i < tests.length; ++i) {
+ var test = tests[i];
+ gl.useProgram(prog);
+
+ gl.enableVertexAttribArray(attrib);
+ gl.bindBuffer(gl.ARRAY_BUFFER, unallocatedBuffer);
+ gl.vertexAttribPointer(attrib, 3, gl.FLOAT, false, 0, 0);
+
+ // Needed because ANGLE_instanced_arrays requires at least one consumed
+ // attribute to have divisor=0 (which is the default, so we don't need to
+ // call vertexAttribDivisorANGLE here).
+ gl.enableVertexAttribArray(consumedAttrib);
+ gl.bindBuffer(gl.ARRAY_BUFFER, allocatedBuffer);
+ gl.vertexAttribPointer(consumedAttrib, 3, gl.FLOAT, false, 0, 0);
+
+ test.draw();
+
+ gl.disableVertexAttribArray(attrib);
+ gl.disableVertexAttribArray(consumedAttrib);
+ wtu.glErrorShouldBe(gl, test.errors, test.name);
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html
new file mode 100644
index 0000000000..9de9439911
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html
@@ -0,0 +1,131 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Enable Vertex Attrib Zero Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+ void main()
+ {
+ gl_FragColor = vec4(0.0,1.0,0.0,1.0);
+ }
+</script>
+
+<script>
+"use strict";
+description("Test some of the issues of the difference between attrib 0 on OpenGL vs WebGL");
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var g_program;
+var g_attribLocation;
+function setup(attribIndex) {
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition'], [attribIndex]);
+ g_program = program;
+ g_attribLocation = attribIndex;
+ shouldBe("g_attribLocation", "gl.getAttribLocation(g_program, 'vPosition')");
+ return program;
+}
+
+function setupVerts(numVerts) {
+ var verts = [
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, -1.0, 0.0
+ ];
+ var positions = new Float32Array(numVerts * 3);
+ var indices = new Uint16Array(numVerts);
+ for (var ii = 0; ii < numVerts; ++ii) {
+ var ndx = ii % 6;
+ var dst = ii * 3;
+ var src = ndx * 3;
+ for (var jj = 0; jj < 3; ++jj) {
+ positions[dst + jj] = verts[src + jj];
+ }
+ indices[ii] = ii;
+ }
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+}
+
+var p0 = setup(0);
+var p3 = setup(3);
+setupVerts(60000);
+
+for (var ii = 0; ii < 5; ++ii) {
+ // test drawing with attrib 0
+ gl.useProgram(p0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR,
+ "drawing using attrib 0 with 6 verts");
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "canvas should be green");
+ gl.disableVertexAttribArray(0);
+
+ // test drawing without attrib 0
+ gl.useProgram(p3);
+ gl.enableVertexAttribArray(3);
+ gl.vertexAttribPointer(3, 3, gl.FLOAT, false, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 60000);
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR,
+ "drawing using attrib 3 with 60000 verts");
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "canvas should be green");
+ gl.disableVertexAttribArray(3);
+
+ // This second test of drawing without attrib0 uncovered a bug in chrome
+ // where after the draw without attrib0 the attrib 0 emulation code disabled
+ // attrib 0 and it was never re-enabled so this next draw failed.
+ gl.useProgram(p3);
+ gl.enableVertexAttribArray(3);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR,
+ "drawing using attrib 3 with 60000 verts");
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "canvas should be green");
+ gl.disableVertexAttribArray(3);
+}
+
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html
new file mode 100644
index 0000000000..aa69c5e7bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html
@@ -0,0 +1,28 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL vertexAttrib Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/gl-vertex-attrib.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html
new file mode 100644
index 0000000000..3cb8bd84a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html
@@ -0,0 +1,190 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+<meta charset="utf-8">
+ <title>vertexattribpointer offsets test</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+There is supposed to be an example drawing here, but it's not important.
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+ <script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ </script>
+
+ <script id="fshader" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform vec4 color;
+ void main()
+ {
+ gl_FragColor = color;
+ }
+ </script>
+
+ <script>
+ "use strict";
+ function init()
+ {
+ description("test vertexattribpointer offsets work");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var tests = [
+ { data: new Float32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.FLOAT,
+ componentSize: 4,
+ normalize: false,
+ },
+ { data: new Uint16Array([ 0, 32767, 0, 32767, 0, 0, 0, 0, 0]),
+ type: gl.SHORT,
+ componentSize: 2,
+ normalize: true,
+ },
+ { data: new Uint16Array([ 0, 65535, 0, 65535, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_SHORT,
+ componentSize: 2,
+ normalize: true,
+ },
+ { data: new Uint16Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_SHORT,
+ componentSize: 2,
+ normalize: false,
+ },
+ { data: new Uint16Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.SHORT,
+ componentSize: 2,
+ normalize: false,
+ },
+ { data: new Uint8Array([ 0, 127, 0, 127, 0, 0, 0, 0, 0 ]),
+ type: gl.BYTE,
+ componentSize: 1,
+ normalize: true,
+ },
+ { data: new Uint8Array([ 0, 255, 0, 255, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_BYTE,
+ componentSize: 1,
+ normalize: true,
+ },
+ { data: new Uint8Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.BYTE,
+ componentSize: 1,
+ normalize: false,
+ },
+ { data: new Uint8Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_BYTE,
+ componentSize: 1,
+ normalize: false,
+ }
+ ];
+
+ if (wtu.getDefault3DContextVersion() >= 2) {
+ tests.push(...[
+ { data: new Int32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0]),
+ type: gl.INT,
+ componentSize: 4,
+ normalize: false,
+ },
+ { data: new Int32Array([ 0, 2147483647, 0, 2147483647, 0, 0, 0, 0, 0]),
+ type: gl.INT,
+ componentSize: 4,
+ normalize: true,
+ },
+ { data: new Uint32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0]),
+ type: gl.UNSIGNED_INT,
+ componentSize: 4,
+ normalize: false,
+ },
+ { data: new Uint32Array([ 0, 4294967295, 0, 4294967295, 0, 0, 0, 0, 0]),
+ type: gl.UNSIGNED_INT,
+ componentSize: 4,
+ normalize: true,
+ },
+ { data: new Uint16Array([ 0, 0b11110000000000, 0, 0b11110000000000, 0, 0, 0, 0, 0]),
+ type: gl.HALF_FLOAT,
+ componentSize: 2,
+ normalize: false,
+ },
+ { data: new Uint16Array([ 0, 0b11110000000000, 0, 0b11110000000000, 0, 0, 0, 0, 0]),
+ type: gl.HALF_FLOAT,
+ componentSize: 2,
+ normalize: false,
+ }
+ ]);
+ }
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+
+ var colorLoc = gl.getUniformLocation(program, "color");
+ var kNumVerts = 3;
+ var kNumComponents = 3;
+
+ var count = 0;
+ for (var tt = 0; tt < tests.length; ++tt) {
+ var test = tests[tt];
+ for (var oo = 0; oo < 3; ++oo) {
+ for (var ss = 0; ss < 3; ++ss) {
+ var offset = (oo + 1) * test.componentSize;
+ var color = (count % 2) ? [1, 0, 0, 1] : [0, 1, 0, 1];
+ var stride = test.componentSize * kNumComponents + test.componentSize * ss;
+ debug("");
+ debug("check with " + wtu.glEnumToString(gl, test.type) + " at offset: " + offset + " with stride:" + stride + " normalize: " + test.normalize);
+ gl.uniform4fv(colorLoc, color);
+ var data = new Uint8Array(test.componentSize * kNumVerts * kNumComponents + stride * (kNumVerts - 1));
+ var view = new Uint8Array(test.data.buffer);
+ var size = test.componentSize * kNumComponents;
+ for (var jj = 0; jj < kNumVerts; ++jj) {
+ var off1 = jj * size;
+ var off2 = jj * stride;
+ for (var zz = 0; zz < size; ++zz) {
+ data[off2 + zz] = view[off1 + zz];
+ }
+ }
+ gl.bufferSubData(gl.ARRAY_BUFFER, offset, data);
+ gl.vertexAttribPointer(0, 3, test.type, test.normalize, stride, offset);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ var buf = new Uint8Array(50 * 50 * 4);
+ gl.readPixels(0, 0, 50, 50, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+ var black = [0, 0, 0, 0];
+ var other = [color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255];
+ var otherMsg = "should be " + ((count % 2) ? "red" : "green")
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, black, "should be black", 0);
+ wtu.checkCanvasRect(gl, 0, 49, 1, 1, black, "should be black", 0);
+ wtu.checkCanvasRect(gl, 26, 40, 1, 1, other, otherMsg, 0);
+ wtu.checkCanvasRect(gl, 26, 27, 1, 1, other, otherMsg, 0);
+ wtu.checkCanvasRect(gl, 40, 27, 1, 1, other, otherMsg, 0);
+ ++count;
+ }
+ }
+ }
+ }
+
+ init();
+ var successfullyParsed = true;
+ </script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html
new file mode 100644
index 0000000000..1276cec7c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html
@@ -0,0 +1,171 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL vertexAttribPointer Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks vertexAttribPointer behaviors in WebGL.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking gl.vertexAttribPointer.");
+
+ if (!gl.FIXED) {
+ gl.FIXED = 0x140C;
+ }
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(0), gl.STATIC_DRAW);
+
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "vertexAttribPointer should fail if no buffer is bound and `offset` is non-zero.");
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "vertexAttribPointer should succeed if no buffer is bound and `offset` is zero.");
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+
+
+ if (wtu.getDefault3DContextVersion() < 2) {
+ gl.vertexAttribPointer(0, 1, gl.INT, 0, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "vertexAttribPointer should not support INT");
+ gl.vertexAttribPointer(0, 1, gl.UNSIGNED_INT, 0, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "vertexAttribPointer should not support UNSIGNED_INT");
+ }
+ gl.vertexAttribPointer(0, 1, gl.FIXED, 0, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "vertexAttribPointer should not support FIXED");
+
+ var checkVertexAttribPointer = function(
+ gl, err, reason, size, type, normalize, stride, offset) {
+ gl.vertexAttribPointer(0, size, type, normalize, stride, offset);
+ var succeeded = (err == gl.NO_ERROR);
+ wtu.glErrorShouldBe(gl, err,
+ "gl.vertexAttribPointer(0, " + size +
+ ", gl." + wtu.glEnumToString(gl, type) +
+ ", " + normalize +
+ ", " + stride +
+ ", " + offset +
+ ") should " + (succeeded ? "succeed " : "fail ") + reason);
+ if (succeeded) {
+ shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE)', size.toString());
+ shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE)', 'gl.' + wtu.glEnumToString(gl, type));
+ shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED)', normalize.toString());
+ shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE)', stride.toString());
+ shouldBe('gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)', offset.toString());
+ }
+ }
+
+ var types = [
+ { type:gl.BYTE, bytesPerComponent: 1 },
+ { type:gl.UNSIGNED_BYTE, bytesPerComponent: 1 },
+ { type:gl.SHORT, bytesPerComponent: 2 },
+ { type:gl.UNSIGNED_SHORT, bytesPerComponent: 2 },
+ { type:gl.FLOAT, bytesPerComponent: 4 },
+ ];
+
+ if (wtu.getDefault3DContextVersion() >= 2) {
+ types.push(...[
+ { type:gl.INT, bytesPerComponent: 4 },
+ { type:gl.UNSIGNED_INT, bytesPerComponent: 4 },
+ { type:gl.HALF_FLOAT, bytesPerComponent: 2 },
+ { type:gl.INT_2_10_10_10_REV, bytesPerComponent: 4, minSize: 4 },
+ { type:gl.UNSIGNED_INT_2_10_10_10_REV, bytesPerComponent: 4, minSize: 4 },
+ ]);
+ }
+
+ for (var ii = 0; ii < types.length; ++ii) {
+ var info = types[ii];
+ debug("");
+ for (var size = 1; size <= 4; ++size) {
+ debug("");
+ debug("checking: " + wtu.glEnumToString(gl, info.type) + " with size " + size);
+ var bytesPerElement = size * info.bytesPerComponent;
+ var offsetSet = [
+ 0,
+ 1,
+ info.bytesPerComponent - 1,
+ info.bytesPerComponent,
+ info.bytesPerComponent + 1,
+ info.bytesPerComponent * 2];
+ for (var jj = 0; jj < offsetSet.length; ++jj) {
+ var offset = offsetSet[jj];
+ for (var kk = 0; kk < offsetSet.length; ++kk) {
+ var stride = offsetSet[kk];
+ var err = gl.NO_ERROR;
+ var reason = ""
+ if (offset % info.bytesPerComponent != 0) {
+ reason = "because offset is bad";
+ err = gl.INVALID_OPERATION;
+ }
+ if (stride % info.bytesPerComponent != 0) {
+ reason = "because stride is bad";
+ err = gl.INVALID_OPERATION;
+ }
+ if (size < info.minSize) {
+ reason = "because size < minSize";
+ err = gl.INVALID_OPERATION;
+ }
+ checkVertexAttribPointer(
+ gl, err, reason, size, info.type, false, stride, offset);
+ }
+ var stride = Math.floor(255 / info.bytesPerComponent) * info.bytesPerComponent;
+
+ if (offset == 0) {
+ checkVertexAttribPointer(
+ gl, size < info.minSize ? gl.INVALID_OPERATION : gl.NO_ERROR, "at stride limit",
+ size, info.type, false, stride, offset);
+ checkVertexAttribPointer(
+ gl, size < info.minSize ? [gl.INVALID_OPERATION, gl.INVALID_VALUE] : gl.INVALID_VALUE, "over stride limit",
+ size, info.type, false,
+ stride + info.bytesPerComponent, offset);
+ }
+ }
+ }
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
new file mode 100644
index 0000000000..d6f6af332f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
@@ -0,0 +1,14 @@
+buffer-bind-test.html
+buffer-data-and-buffer-sub-data.html
+--min-version 1.0.3 buffer-data-array-buffer-delete.html
+--min-version 1.0.4 buffer-data-dynamic-delay.html
+--min-version 1.0.4 buffer-uninitialized.html
+--min-version 1.0.2 element-array-buffer-delete-recreate.html
+index-validation-copies-indices.html
+index-validation-crash-with-buffer-sub-data.html
+--min-version 1.0.2 index-validation-large-buffer.html
+index-validation-verifies-too-many-indices.html
+index-validation-with-resized-buffer.html
+index-validation.html
+--min-version 1.0.4 vertex-buffer-updated-after-draw.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-bind-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-bind-test.html
new file mode 100644
index 0000000000..b0f1fd7a38
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-bind-test.html
@@ -0,0 +1,66 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+<meta charset="utf-8">
+ <title>WebGL BindBuffer conformance test.</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Checks a buffer can only be bound to 1 target.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be able to bind array buffer.");
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be able to unbind array buffer.");
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "should get INVALID_OPERATION if attempting to bind array buffer to different target");
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be able to bind element array buffer.");
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be able to unbind element array buffer.");
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "should get INVALID_OPERATION if attempting to bind element array buffer to different target");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-and-buffer-sub-data.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-and-buffer-sub-data.html
new file mode 100644
index 0000000000..f3c2658a22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-and-buffer-sub-data.html
@@ -0,0 +1,203 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test bufferData/bufferSubData with or without ArrayBuffer input");
+
+debug('Regression test for <a href="https://bugs.webkit.org/show_bug.cgi?id=41884">https://bugs.webkit.org/show_bug.cgi?id=41884</a> : <code>Implement bufferData and bufferSubData with ArrayBuffer as input</code>');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ bufferDataTest();
+ bufferDataSizesTest();
+
+ bufferSubDataTest();
+}
+
+function bufferDataTest() {
+ debug("");
+ debug("Test bufferData without ArrayBuffer input");
+
+ var buf = gl.createBuffer();
+ shouldBeNonNull(buf);
+
+ gl.bufferData(gl.ARRAY_BUFFER, 4, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "no buffer bound");
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.bufferData(gl.ARRAY_BUFFER, -4, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferData when buffer size is negative should generate INVALID_VALUE");
+
+ gl.bufferData(gl.ARRAY_BUFFER, null, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferData when BufferDataSource is null should generate INVALID_VALUE");
+
+ gl.bufferData(gl.ARRAY_BUFFER, undefined, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferData when BufferDataSource is undefined should generate INVALID_VALUE");
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+}
+
+function bufferDataSizesTest() {
+ debug("");
+ debug("Test bufferData overloads");
+
+ // bufferData has an integer overload and an ArrayBuffer overload.
+ // Per the WebIDL spec, the overload resolution algorithm should resolve types as follows:
+ // - If the argument is null or undefined, pick the nullable type, which is ArrayBuffer.
+ // Per the WebGL spec, null should flag INVALID_VALUE.
+ // - If the argument is an ArrayBuffer, then pick the ArrayBuffer overload
+ // - Everything else should pick the numeric overload. This means things like objects, strings,
+ // floating point numbers, arrays of numbers and strings, etc should convert themselves to a number.
+ var bufferDataParams = [
+ { parameter: 0, expectedBufferSize: 0 },
+ { parameter: 4, expectedBufferSize: 4 },
+ { parameter: 5.1, expectedBufferSize: 5 },
+ { parameter: 5.8, expectedBufferSize: 5 },
+ { parameter: 5.5, expectedBufferSize: 5 },
+
+ { parameter: "4", expectedBufferSize: 4 },
+ { parameter: "5.1", expectedBufferSize: 5 },
+ { parameter: "5.8", expectedBufferSize: 5 },
+ { parameter: "5.5", expectedBufferSize: 5 },
+ { parameter: "0", expectedBufferSize: 0 },
+
+ { parameter: [42, 64], expectedBufferSize: 0 },
+ { parameter: [42], expectedBufferSize: 42 },
+ { parameter: ["42"], expectedBufferSize: 42 },
+ { parameter: ["42", "64"], expectedBufferSize: 0 },
+
+ { parameter: new ArrayBuffer(0), expectedBufferSize: 0 },
+ { parameter: new ArrayBuffer(4), expectedBufferSize: 4 },
+ { parameter: new Uint8Array(new ArrayBuffer(5)), expectedBufferSize: 5 },
+ { parameter: new DataView(new ArrayBuffer(7)), expectedBufferSize: 7 },
+
+ { parameter: "WebGL Rocks!", expectedBufferSize: 0 },
+ { parameter: { mystring: "WebGL Rocks!" }, expectedBufferSize: 0 },
+ ];
+
+ if (window.SharedArrayBuffer) {
+ bufferDataParams.push(
+ { parameter: new SharedArrayBuffer(3), expectedBufferSize: 3 },
+ { parameter: new Uint8Array(new SharedArrayBuffer(6)), expectedBufferSize: 6 },
+ { parameter: new DataView(new SharedArrayBuffer(8)), expectedBufferSize: 8 }
+ );
+ }
+
+ bufferDataParams.forEach(function (bufferDataParam) {
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferDataParam.parameter, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Passing " + bufferDataParam.parameter + " to bufferData");
+
+ shouldEvaluateTo("gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)", bufferDataParam.expectedBufferSize);
+ });
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+}
+
+function bufferSubDataTest() {
+ debug("");
+ debug("Test bufferSubData");
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new ArrayBuffer(1));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Calling bufferSubData before bufferData should fail");
+
+ gl.bufferData(gl.ARRAY_BUFFER, 128, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var array = new ArrayBuffer(64);
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, -10, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferSubData with ArrayBuffer when offset is negative should INVALID_VALUE");
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, 65, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "buffer overflow");
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, -10, new Float32Array(8));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferSubData with ArrayBufferView when offset is negative should generate INVALID_VALUE");
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, 10, array);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferSubData with ArrayBuffer should succeed");
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, 10, new Float32Array(0));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferSubData with zero-sized ArrayBufferView should succeed");
+
+ // Arguments that are not ArrayBuffers, null or undefined should throw a TypeError exception
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 0, 42);");
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 0, 5.5);");
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 0, \"5.5\");");
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 0, [4]);");
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 0, { mynumber: 42});");
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 10, null)");
+ shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 10, undefined)");
+
+ if (window.SharedArrayBuffer) {
+ const validDatas = [
+ 'new SharedArrayBuffer(3)',
+ 'new Uint8Array(new SharedArrayBuffer(3))',
+ 'new DataView(new SharedArrayBuffer(3))',
+ ];
+ for (const x of validDatas) {
+ shouldNotThrow(`gl.bufferSubData(gl.ARRAY_BUFFER, 0, ${x})`);
+ }
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should generate no GL error");
+
+ // -
+ // Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1611837
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new ArrayBuffer(0));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "Calling bufferSubData with empty ArrayBuffer and null WebGLBuffer should fail");
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new ArrayBuffer(0));
+ wtu.glErrorShouldBe(gl, 0,
+ "Calling bufferSubData with empty ArrayBuffer and non-null WebGLBuffer should succeed");
+
+ // -
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-array-buffer-delete.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-array-buffer-delete.html
new file mode 100644
index 0000000000..4a25426f0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-array-buffer-delete.html
@@ -0,0 +1,63 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test ARRAY_BUFFER deletion when a vertex attrib array with location != 0 is pointing to it and preserveDrawingBuffer is true.");
+
+var canvas = document.createElement('canvas');
+document.body.appendChild(canvas);
+
+canvas.addEventListener(
+ "webglcontextlost",
+ function(event) {
+ testFailed("Context lost");
+ event.preventDefault();
+ },
+ false);
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(canvas, {preserveDrawingBuffer: true});
+
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var array = new Float32Array([0]);
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var attribLocation = 1;
+ gl.enableVertexAttribArray(attribLocation);
+ gl.vertexAttribPointer(attribLocation, 1, gl.FLOAT, false, 0, 0);
+
+ gl.deleteBuffer(buf);
+
+ setTimeout(function() {
+ // Wait for possible context loss
+ finishTest();
+ }, 2000);
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html
new file mode 100644
index 0000000000..8e41a687bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html
@@ -0,0 +1,114 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>bufferData with DYNAMIC_DRAW and delay between updating data</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec2 a_position;
+ attribute vec2 a_color;
+ varying vec2 v_color;
+ void main()
+ {
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ v_color = a_color;
+ }
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+ precision mediump float;
+ varying vec2 v_color;
+ void main()
+ {
+ gl_FragColor = vec4(v_color, 0.0, 1.0);
+ }
+</script>
+
+<script>
+"use strict";
+description("Verifies that bufferData with DYNAMIC_DRAW updates the vertex attribute when there is a significant delay between updating the buffer.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+
+// Initialize position vertex attribute to draw a square covering the entire canvas.
+var positionBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1.0, 1.0,
+ 1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0
+ ]), gl.DYNAMIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+// Initialize color vertex attribute to red.
+var colorBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 0.0,
+ ]), gl.DYNAMIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after setup");
+
+// Fill the canvas with red
+gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after first drawArrays");
+
+wtu.checkCanvasRect(gl, 0, 0, 50, 50, [255, 0, 0, 255], "Canvas should be red after the first drawArrays");
+
+// With the buffer set to DYNAMIC_DRAW, Angle internally changes the storage type of the vertex attribute from DYNAMIC to DIRECT
+// if the buffer has not been updated after ~4-5 draw calls. When the buffer is eventually updated, the vertex attribute
+// is updated back to DYNAMIC, but there was a bug in Angle where the data is not marked as dirty. The result is that the
+// vertex data is not updated with the new buffer data. This test verifies that the vertex data is updated.
+var iteration = 0;
+function draw() {
+ // Draw 10 times to ensure that the vertex attribute storage type is changed.
+ if (iteration < 10) {
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 2);
+ requestAnimationFrame(draw);
+ }
+ else {
+ // Update the buffer bound to the color vertex attribute to green and draw.
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 1.0,
+ ]), gl.DYNAMIC_DRAW);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after last drawArrays");
+
+ wtu.checkCanvasRect(gl, 0, 0, 50, 50, [0, 255, 0, 255], "Canvas should be green after 10 frames");
+
+ finishTest();
+ }
+
+ iteration++;
+}
+
+requestAnimationFrame(draw);
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-uninitialized.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-uninitialized.html
new file mode 100644
index 0000000000..75282f3674
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-uninitialized.html
@@ -0,0 +1,104 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<canvas id="canvas" width="1" height="1"></canvas>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute float a_vertex;
+void main()
+{
+ gl_Position = a_vertex == 0.0 ? vec4(9, 9, 9, 1) : vec4(0.5, 0.5, 0.5, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+description("Tests that uninitialized WebGLBuffers are zeroed out");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(document.getElementById("canvas"));
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_vertex"]);
+shouldBeTrue("program != null");
+
+var TEST_LENGTH = 1024;
+var TEST_BUFSIZE = TEST_LENGTH * 4;
+var data = new Float32Array(TEST_LENGTH / 4); // this array is zeroed
+
+var indices = new Uint16Array(TEST_LENGTH);
+for (var i = 0; i < TEST_LENGTH; i++) {
+ indices[i] = i;
+}
+
+gl.clearColor(0, 1, 0, 1);
+
+function test(initFunction) {
+ var uninitializedBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer);
+ initFunction();
+
+ var elements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ gl.useProgram(program);
+ var vertexLoc = gl.getAttribLocation(program, "a_vertex");
+ gl.vertexAttribPointer(vertexLoc, 1, gl.FLOAT, gl.FALSE, 0, 0);
+ gl.enableVertexAttribArray(vertexLoc);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error should result from setup");
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.POINTS, TEST_LENGTH, gl.UNSIGNED_SHORT, 0);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255], "buffer should be initialized to zero");
+
+ gl.deleteBuffer(uninitializedBuffer);
+}
+
+var REPETITIONS = 50;
+
+var j;
+debug("");
+debug("testing bufferData(..., size, ...)");
+for (j = 0; j < REPETITIONS; j++) {
+ test(function() {
+ gl.bufferData(gl.ARRAY_BUFFER, TEST_BUFSIZE, gl.STATIC_DRAW);
+ });
+}
+
+debug("");
+debug("testing bufferSubData(..., offset, data) of uninitialized buffer");
+for (j = 0; j < REPETITIONS; j++) {
+ test(function() {
+ gl.bufferData(gl.ARRAY_BUFFER, TEST_BUFSIZE, gl.STATIC_DRAW);
+ // bufferSubData the second quarter of the buffer
+ gl.bufferSubData(gl.ARRAY_BUFFER, TEST_BUFSIZE / 4, data);
+ });
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/element-array-buffer-delete-recreate.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/element-array-buffer-delete-recreate.html
new file mode 100644
index 0000000000..d4fb81af9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/element-array-buffer-delete-recreate.html
@@ -0,0 +1,69 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+ <title>Element Array Buffer Deletion and Recreation Test</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+function init()
+{
+ description();
+
+ // Clear the background with red.
+ var gl = wtu.create3DContext("example");
+ wtu.setupSimpleColorProgram(gl);
+ var color = [0, 255, 0, 255];
+ wtu.setUByteDrawColor(gl, color);
+
+ var vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, 1
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ // Create an element array buffer.
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3]), gl.STATIC_DRAW);
+
+ // Delete the element array buffer.
+ gl.deleteBuffer(indexBuffer);
+
+ // Create a new element array buffer.
+ indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3]), gl.STATIC_DRAW);
+
+ // Draw with the new element array buffer.
+ // If the geometry is drawn successfully, the fragment shader will color it green.
+ gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_BYTE, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+ wtu.checkCanvas(gl, color, "should be green")
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-copies-indices.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-copies-indices.html
new file mode 100644
index 0000000000..e823f95f69
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-copies-indices.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description('Test that client data is always copied during bufferData and bufferSubData calls, because otherwise the data the GL uses to draw may differ from that checked by the index validation code.')
+
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+
+context.useProgram(program);
+var vertexObject = context.createBuffer();
+context.enableVertexAttribArray(0);
+context.bindBuffer(context.ARRAY_BUFFER, vertexObject);
+// 4 vertices -> 2 triangles
+context.bufferData(context.ARRAY_BUFFER, new Float32Array([ 0,0,0, 0,1,0, 1,0,0, 1,1,0 ]), context.STATIC_DRAW);
+context.vertexAttribPointer(0, 3, context.FLOAT, false, 0, 0);
+
+var indexObject = context.createBuffer();
+
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indexObject);
+var indices = new Uint16Array([ 10000, 0, 1, 2, 3, 10000 ]);
+context.bufferData(context.ELEMENT_ARRAY_BUFFER, indices, context.STATIC_DRAW);
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
+var indexValidationError = wtu.shouldGenerateGLError(context,
+ [context.INVALID_OPERATION, context.NO_ERROR],
+ "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(context, indexValidationError, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
+indices[0] = 2;
+indices[5] = 1;
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
+wtu.shouldGenerateGLError(context, indexValidationError, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(context, indexValidationError, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-crash-with-buffer-sub-data.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-crash-with-buffer-sub-data.html
new file mode 100644
index 0000000000..91873f740f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-crash-with-buffer-sub-data.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description('Verifies that the index validation code which is within bufferSubData does not crash.')
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+var elementBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, gl.STATIC_DRAW);
+var data = new Uint8Array(127);
+gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 63, data);
+testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-large-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-large-buffer.html
new file mode 100644
index 0000000000..a0427039a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-large-buffer.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description('Tests that index validation for drawElements works with large attribute buffers');
+
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+
+context.useProgram(program);
+
+// Create a small index buffer.
+var indexObject = context.createBuffer();
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indexObject);
+var indexArray = new Uint16Array([0, 1, 2]);
+context.bufferData(context.ELEMENT_ARRAY_BUFFER, indexArray, context.STATIC_DRAW);
+
+// Create a large attribute buffer.
+var vertexObject = context.createBuffer();
+context.enableVertexAttribArray(0);
+context.bindBuffer(context.ARRAY_BUFFER, vertexObject);
+context.bufferData(context.ARRAY_BUFFER, new Float32Array(3 * 65536), context.STATIC_DRAW);
+context.vertexAttribPointer(0, 3, context.FLOAT, false, 0, 0);
+
+debug("Test large attribute buffer")
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 3, context.UNSIGNED_SHORT, 0)");
+
+// Enlarge the attribute buffer slightly.
+debug("Test even larger attribute buffer")
+context.bufferData(context.ARRAY_BUFFER, new Float32Array(3 * 65536 + 3), context.STATIC_DRAW);
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 3, context.UNSIGNED_SHORT, 0)");
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-verifies-too-many-indices.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-verifies-too-many-indices.html
new file mode 100644
index 0000000000..8ebbf4f32d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-verifies-too-many-indices.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description('Tests that index validation for drawElements does not examine too many indices');
+
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+
+context.useProgram(program);
+var vertexObject = context.createBuffer();
+context.enableVertexAttribArray(0);
+context.bindBuffer(context.ARRAY_BUFFER, vertexObject);
+// 4 vertices -> 2 triangles
+context.bufferData(context.ARRAY_BUFFER, new Float32Array([ 0,0,0, 0,1,0, 1,0,0, 1,1,0 ]), context.STATIC_DRAW);
+context.vertexAttribPointer(0, 3, context.FLOAT, false, 0, 0);
+
+var indexObject = context.createBuffer();
+
+debug("Test out of range indices")
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indexObject);
+context.bufferData(context.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 10000, 0, 1, 2, 3, 10000 ]), context.STATIC_DRAW);
+var indexValidationError = wtu.shouldGenerateGLError(context, [context.INVALID_OPERATION, context.NO_ERROR], "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
+wtu.shouldGenerateGLError(context, indexValidationError, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-with-resized-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-with-resized-buffer.html
new file mode 100644
index 0000000000..182768085f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation-with-resized-buffer.html
@@ -0,0 +1,107 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="1" height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vs" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main() {
+ gl_Position = vPosition;
+ color = vColor;
+}
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description('Test that updating the size of a vertex buffer is properly noticed by the WebGL implementation.')
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initialization");
+
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [-1,1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex setup");
+
+var texCoordObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coord setup");
+
+// Now resize these buffers because we want to change what we're drawing.
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0,
+ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0]), gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex redefinition");
+gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
+gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coordinate / color redefinition");
+
+var numQuads = 2;
+var indices = new Uint8Array(numQuads * 6);
+for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ var quad = (ii == (numQuads - 1)) ? 4 : 0;
+ indices[offset + 0] = quad + 0;
+ indices[offset + 1] = quad + 1;
+ indices[offset + 2] = quad + 2;
+ indices[offset + 3] = quad + 2;
+ indices[offset + 4] = quad + 1;
+ indices[offset + 5] = quad + 3;
+}
+var indexObject = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
+gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation.html
new file mode 100644
index 0000000000..0aa7e78781
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/index-validation.html
@@ -0,0 +1,119 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests that index validation verifies the correct number of indices");
+
+function sizeInBytes(type) {
+ switch (type) {
+ case gl.BYTE:
+ case gl.UNSIGNED_BYTE:
+ return 1;
+ case gl.SHORT:
+ case gl.UNSIGNED_SHORT:
+ return 2;
+ case gl.INT:
+ case gl.UNSIGNED_INT:
+ case gl.FLOAT:
+ return 4;
+ default:
+ throw "unknown type";
+ }
+}
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var program = wtu.loadStandardProgram(gl);
+
+// 3 vertices => 1 triangle, interleaved data
+var dataComplete = new Float32Array([0, 0, 0, 1,
+ 0, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 1,
+ 1, 1, 1, 1,
+ 0, 0, 1]);
+var dataIncomplete = new Float32Array([0, 0, 0, 1,
+ 0, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 1,
+ 1, 1, 1, 1]);
+var indices = new Uint16Array([0, 1, 2]);
+
+debug("Testing with valid indices");
+
+var bufferComplete = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, bufferComplete);
+gl.bufferData(gl.ARRAY_BUFFER, dataComplete, gl.STATIC_DRAW);
+var elements = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+gl.useProgram(program);
+var vertexLoc = gl.getAttribLocation(program, "a_vertex");
+var normalLoc = gl.getAttribLocation(program, "a_normal");
+gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
+gl.enableVertexAttribArray(vertexLoc);
+gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+gl.enableVertexAttribArray(normalLoc);
+shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("Testing with out-of-range indices");
+
+var bufferIncomplete = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
+gl.bufferData(gl.ARRAY_BUFFER, dataIncomplete, gl.STATIC_DRAW);
+gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
+gl.enableVertexAttribArray(vertexLoc);
+gl.disableVertexAttribArray(normalLoc);
+debug("Enable vertices, valid");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+debug("Enable normals, out-of-range");
+gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+gl.enableVertexAttribArray(normalLoc);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.NO_ERROR]);
+
+debug("Test with enabled attribute that does not belong to current program");
+
+gl.disableVertexAttribArray(normalLoc);
+var extraLoc = Math.max(vertexLoc, normalLoc) + 1;
+gl.enableVertexAttribArray(extraLoc);
+debug("Enable an extra attribute with null");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+debug("Enable an extra attribute with insufficient data buffer");
+gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+debug("Pass large negative index to vertexAttribPointer");
+gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/vertex-buffer-updated-after-draw.html b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/vertex-buffer-updated-after-draw.html
new file mode 100644
index 0000000000..90436b64ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/vertex-buffer-updated-after-draw.html
@@ -0,0 +1,94 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Vertex Buffer Updated After Draw Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 a_position;
+attribute vec4 a_color;
+varying vec4 v_outcolor;
+void main() {
+ gl_Position = vec4(a_position, 0, 1);
+ v_outcolor = a_color;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+varying mediump vec4 v_outcolor;
+void main() {
+ gl_FragColor = v_outcolor;
+}
+</script>
+
+<script>
+// Tests that D3D11 dirty bit updates don't forget about BufferSubData attrib updates.
+// Based on ANGLE test (StateChangeTest, VertexBufferUpdatedAfterDraw) from https://github.com/google/angle/blob/f7f0b8c3ab21c52cc2915048959361cf628d95f0/src/tests/gl_tests/StateChangeTest.cpp
+"use strict";
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example");
+
+var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+
+var colorLoc = gl.getAttribLocation(program, "a_color");
+var green = new Uint8Array(4 * 6);
+var red = new Uint8Array(4 * 6);
+
+for (var i = 0; i < 6; ++i) {
+ var ci = i * 4;
+
+ green[ci] = 0;
+ red[ci] = 255;
+
+ green[ci + 1] = 255;
+ red[ci + 1] = 0;
+
+ green[ci + 2] = red[ci + 2] = 0;
+
+ green[ci + 3] = red[ci + 3] = 255;
+}
+
+var positionLoc = gl.getAttribLocation(program, "a_position");
+
+var gridRes = 1;
+wtu.setupIndexedQuad(gl, gridRes, positionLoc);
+
+var colorBuf = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colorBuf);
+gl.bufferData(gl.ARRAY_BUFFER, green, gl.STATIC_DRAW);
+gl.vertexAttribPointer(colorLoc, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+gl.enableVertexAttribArray(colorLoc);
+
+wtu.clearAndDrawIndexedQuad(gl, gridRes);
+wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+
+gl.bufferSubData(gl.ARRAY_BUFFER, 0, red);
+
+wtu.clearAndDrawIndexedQuad(gl, gridRes);
+wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/00_test_list.txt
new file mode 100644
index 0000000000..558163de17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/00_test_list.txt
@@ -0,0 +1,19 @@
+buffer-offscreen-test.html
+buffer-preserve-test.html
+canvas-test.html
+canvas-zero-size.html
+drawingbuffer-static-canvas-test.html
+--min-version 1.0.2 drawingbuffer-hd-dpi-test.html
+drawingbuffer-test.html
+--min-version 1.0.3 draw-webgl-to-canvas-test.html
+--min-version 1.0.3 draw-static-webgl-to-multiple-canvas-test.html
+--min-version 1.0.2 framebuffer-bindings-unaffected-on-resize.html
+--min-version 1.0.4 framebuffer-bindings-affected-by-to-data-url.html
+--min-version 1.0.3 rapid-resizing.html
+--min-version 1.0.4 render-after-resize-test.html
+--min-version 1.0.2 texture-bindings-unaffected-on-resize.html
+--min-version 1.0.2 to-data-url-test.html
+--min-version 1.0.4 to-data-url-after-composite.html
+viewport-unchanged-upon-resize.html
+--min-version 1.0.4 webgl-to-2d-canvas.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-offscreen-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-offscreen-test.html
new file mode 100644
index 0000000000..c0bf2d35fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-offscreen-test.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL required buffer clear behaviour test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<style type="text/css">
+body {
+ height: 3000px;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
+<div id="console"></div>
+<script>
+description("This test ensures WebGL implementations correctly clear " +
+ "the drawing buffer on composite if preserveDrawingBuffer is false.");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl1 = wtu.create3DContext("c");
+var gl2 = wtu.create3DContext();
+shouldBeNonNull("gl1");
+shouldBeNonNull("gl2");
+
+shouldBeFalse('gl1.getContextAttributes().preserveDrawingBuffer');
+shouldBeFalse('gl2.getContextAttributes().preserveDrawingBuffer');
+
+function init(gl) {
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // enable scissor here, before compositing, to make sure it's correctly
+ // ignored and restored
+ gl.scissor(0, 10, 10, 10);
+ gl.enable(gl.SCISSOR_TEST);
+}
+
+init(gl1);
+init(gl2);
+
+wtu.waitForComposite(function() {
+ function clear(gl) {
+ // scissor was set earlier
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+ clear(gl1);
+ clear(gl2);
+
+ debug("check on screen canvas");
+ wtu.checkCanvasRect(gl1, 0, 10, 10, 10, [0, 0, 255, 255],
+ "cleared corner should be blue, stencil should be preserved");
+ wtu.checkCanvasRect(gl1, 0, 0, 10, 10, [0, 0, 0, 0],
+ "remainder of buffer should be cleared");
+ debug("check off screen canvas");
+ wtu.checkCanvasRect(gl2, 0, 10, 10, 10, [0, 0, 255, 255],
+ "cleared corner should be blue, stencil should be preserved");
+ wtu.checkCanvasRect(gl2, 0, 0, 10, 10, [255, 0, 0, 255],
+ "remainder of buffer should be un-cleared red");
+
+ finishTest();
+});
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-preserve-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-preserve-test.html
new file mode 100644
index 0000000000..38c07f5211
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/buffer-preserve-test.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL required buffer clear behaviour test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/compositing-test.js"></script>
+<style type="text/css">
+body {
+ height: 3000px;
+}
+</style>
+</head>
+<body>
+<!-- Important to put the canvas at the top so that it's always visible even in the test suite runner.
+ Otherwise it just doesn't get composited in Firefox. -->
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+"use strict";
+
+description("This test ensures WebGL implementations correctly clear the drawing buffer " +
+ "on composite if preserveDrawingBuffer is false.");
+debug("");
+
+const wtu = WebGLTestUtils;
+
+async function runCompositingTests() {
+ const compositingTestFn = createCompositingTestFn({
+ webglVersion: 1,
+ shadersFn(gl) {
+ const vs = `\
+ attribute vec4 position;
+ void main() {
+ gl_Position = position;
+ }
+ `;
+ const fs = `\
+ precision mediump float;
+ void main() {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+ `;
+ return [vs, fs];
+ },
+ });
+
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ await compositingTestFn(drawArrays);
+ await compositingTestFn(drawElements);
+ finishTest();
+}
+runCompositingTests();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-test.html
new file mode 100644
index 0000000000..02164692c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-test.html
@@ -0,0 +1,195 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<canvas id="canvas2d" width="40" height="40"> </canvas>
+<script>
+"use strict";
+
+description("This test ensures WebGL implementations interact correctly with the canvas tag.");
+
+debug("");
+debug("Canvas.getContext");
+
+var err;
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var canvas2d = document.getElementById("canvas2d");
+var ctx2d = canvas2d.getContext("2d");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking canvas and WebGL interaction");
+
+ // Check that a canvas with no width or height is 300x150 pixels
+ shouldBe('canvas.width', '300');
+ shouldBe('canvas.height', '150');
+
+ // Check get a 4 value gl parameter as a csv string.
+ var getValue4v = function(name) {
+ var v = gl.getParameter(name);
+ var result = '' +
+ v[0] + ',' +
+ v[1] + ',' +
+ v[2] + ',' +
+ v[3];
+ return result;
+ }
+
+ var getViewport = function() {
+ return getValue4v(gl.VIEWPORT);
+ }
+
+ var getClearColor = function() {
+ return getValue4v(gl.COLOR_CLEAR_VALUE);
+ }
+
+ var isAboutEqual = function(a, b) {
+ return Math.abs(a - b) < 0.01;
+ }
+
+ var isAboutEqualInt = function(a, b) {
+ return Math.abs(a - b) < 3;
+ }
+
+ var checkCanvasContentIs = function(r3d,g3d,b3d,a3d) {
+ var r2d;
+ var g2d;
+ var b2d;
+ var a2d;
+
+ var checkPixel = function(x, y, r3d,g3d,b3d,a3d) {
+ var offset = (y * 40 + x) * 4;
+ r2d = imgData.data[offset];
+ g2d = imgData.data[offset + 1];
+ b2d = imgData.data[offset + 2];
+ a2d = imgData.data[offset + 3];
+ var res = isAboutEqualInt(r2d, r3d) &&
+ isAboutEqualInt(g2d, g3d) &&
+ isAboutEqualInt(b2d, b3d) &&
+ isAboutEqualInt(a2d, a3d);
+ if (!res) {
+ bufferedLogToConsole('at ' + x + ', ' + y + " (offset " + offset + ") = " + r2d + ", " + g2d + ", " + b2d + ", " + a2d);
+ }
+ return res;
+ }
+
+ var checkPixels = function(r3d,g3d,b3d,a3d) {
+ return checkPixel(0, 0, r3d, g3d, b3d, a3d) &&
+ checkPixel(0, 39, r3d, g3d, b3d, a3d) &&
+ checkPixel(39, 0, r3d, g3d, b3d, a3d) &&
+ checkPixel(39, 39, r3d, g3d, b3d, a3d) &&
+ checkPixel(0, 0, r3d, g3d, b3d, a3d);
+ };
+
+ // Set to just take the color from the 3d canvas
+ ctx2d.globalCompositeOperation = 'copy';
+
+ // fill 2d canvas with orange
+ ctx2d.fillStyle = "rgb(255,192,128)";
+ ctx2d.fillRect (0, 0, 40, 40);
+
+ // get the image data
+ var imgData = ctx2d.getImageData(0, 0, 40, 40);
+
+ // check it got cleared.
+ if (!checkPixels(255, 192, 128, 255)) {
+ testFailed("unable to fill 2d context.");
+ return;
+ }
+
+ // draw 3d canvas on top.
+ ctx2d.drawImage(canvas, 0,0, 40, 40);
+
+ // get the image data
+ var imgData = ctx2d.getImageData(0, 0, 40, 40);
+
+ // Check it's the expected color.
+ if (!checkPixels(r3d, g3d, b3d, a3d)) {
+ testFailed("pixels are " + r2d + "," + g2d + "," + b2d + "," + a2d +
+ " expected " + r3d + "," + g3d + "," + b3d + "," + a3d);
+ } else {
+ testPassed("pixels are " + r3d + "," + g3d + "," + b3d + "," + a3d);
+ }
+ }
+
+ checkCanvasContentIs(0, 0, 0, 0);
+ shouldBe('getViewport()', '"0,0,300,150"');
+
+ // Change the display size of the canvas and check
+ // the viewport size does not change.
+ debug("");
+ debug("change display size of canvas and see that viewport does not change");
+ canvas.style.width = "100px";
+ canvas.style.height = "25px";
+ var intervalId;
+ intervalId = window.setInterval(function() {
+ if (canvas.clientWidth == 100 &&
+ canvas.clientHeight == 25) {
+ window.clearInterval(intervalId);
+ shouldBe('getViewport()', '"0,0,300,150"');
+ shouldBe('canvas.width', '300');
+ shouldBe('canvas.height', '150');
+
+ // Change the actual size of the canvas
+ // Check that the viewport does not change.
+ // Check that the clear color does not change.
+ // Check that the color mask does not change.
+ debug("");
+ debug("change the actual size of the canvas and see that the viewport does not change");
+ gl.clearColor(0.25, 0.5, 0.75, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ checkCanvasContentIs(64, 128, 192, 255);
+ gl.colorMask(0,0,0,0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL errors before resizing the canvas");
+ canvas.width = 400;
+ canvas.height = 10;
+ err = gl.getError();
+ // Some implementations might lost the context when resizing
+ if (err != gl.CONTEXT_LOST_WEBGL) {
+ shouldBe("err", "gl.NO_ERROR");
+ var v = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ assertMsg(isAboutEqual(v[0], 0.25) &&
+ isAboutEqual(v[1], 0.5) &&
+ isAboutEqual(v[2], 0.75) &&
+ isAboutEqual(v[3], 1),
+ "gl.clearColor should not change after canvas resize");
+ v = gl.getParameter(gl.COLOR_WRITEMASK);
+ assertMsg(isAboutEqual(v[0], 0) &&
+ isAboutEqual(v[1], 0) &&
+ isAboutEqual(v[2], 0) &&
+ isAboutEqual(v[3], 0),
+ "gl.colorMask should not change after canvas resize");
+ shouldBe('getViewport()', '"0,0,300,150"');
+ checkCanvasContentIs(0, 0, 0, 0);
+ }
+
+ debug("");
+ finishTest();
+ }
+ }, 1000/30);
+}
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-zero-size.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-zero-size.html
new file mode 100644
index 0000000000..c85a73d342
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/canvas-zero-size.html
@@ -0,0 +1,43 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Zero Size Canvas Test</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Tests that a zero size canvas does not fail.");
+var wtu = WebGLTestUtils;
+var canvas = document.createElement('canvas');
+var gl = wtu.create3DContext(canvas);
+canvas.width = 0;
+canvas.height = 0;
+gl.viewport(0, 0, 0, 0);
+var program = wtu.setupTexturedQuad(gl);
+shouldBeTrue("program != null");
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+var pixel = new Uint8Array([0, 255, 0, 255]);
+gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+wtu.clearAndDrawUnitQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-static-webgl-to-multiple-canvas-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-static-webgl-to-multiple-canvas-test.html
new file mode 100644
index 0000000000..be7a2e6f54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-static-webgl-to-multiple-canvas-test.html
@@ -0,0 +1,75 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas2d_0" width="128" height="128"> </canvas>
+<canvas id="canvas2d_1" width="400" height="400"> </canvas>
+<canvas id="canvas2d_2" width="128" height="128"> </canvas>
+<canvas id="webgl" width="400" height="400"> </canvas>
+<script>
+"use strict";
+
+description("This test ensures WebGL implementations interact correctly with the canvas 2D drawImage call when drawing the same content.");
+
+var err;
+var wtu = WebGLTestUtils;
+
+var canvas2d = [];
+var ctx2d = [];
+for (var i = 0; i < 3; i ++) {
+ canvas2d[i] = document.getElementById("canvas2d_" + i);
+ ctx2d[i] = canvas2d[i].getContext("2d");
+}
+
+var canvas = document.getElementById("webgl");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("Checking drawing the same WebGL content to HW accelerated canvas and SW Canvases");
+ debug("");
+ var color = [[0.25, 0.5, 0.75, 1], [1, 0, 0, 1], [1, 0, 1, 1]];
+ var colorValue = [[64, 128, 192, 255], [255, 0, 0, 255], [255, 0, 255, 255]];
+ for (var count = 0; count < 10; count ++) {
+ for (var i = 0; i < 3; i++) {
+ gl.clearColor(color[i][0], color[i][1], color[i][2], color[i][3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ ctx2d[0].drawImage(canvas, 0, 0, canvas2d[0].width, canvas2d[0].height);
+ ctx2d[1].drawImage(canvas, 0, 0, canvas2d[1].width, canvas2d[1].height);
+ ctx2d[2].drawImage(canvas, 0, 0, canvas2d[2].width, canvas2d[2].height);
+ wtu.checkCanvasRect(ctx2d[0], 0, 0, canvas2d[0].width, canvas2d[0].height, colorValue[i],
+ "drawImage: Should be (" + colorValue[i][0] + "," + colorValue[i][1] +
+ "," + colorValue[i][2] + "," + colorValue[i][3] + ").", 2);
+ wtu.checkCanvasRect(ctx2d[1], 0, 0, canvas2d[1].width, canvas2d[1].height, colorValue[i],
+ "drawImage: Should be (" + colorValue[i][0] + "," + colorValue[i][1] +
+ "," + colorValue[i][2] + "," + colorValue[i][3] + ").", 2);
+ wtu.checkCanvasRect(ctx2d[2], 0, 0, canvas2d[2].width, canvas2d[2].height, colorValue[i],
+ "drawImage: Should be (" + colorValue[i][0] + "," + colorValue[i][1] +
+ "," + colorValue[i][2] + "," + colorValue[i][3] + ").", 2);
+ }
+ }
+
+ err = gl.getError();
+ debug("");
+}
+finishTest();
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-webgl-to-canvas-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-webgl-to-canvas-test.html
new file mode 100644
index 0000000000..16007cfe50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/draw-webgl-to-canvas-test.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas2d_0" width="400" height="400"> </canvas>
+<canvas id="canvas2d_1" width="400" height="400"> </canvas>
+<canvas id="canvas2d_2" width="400" height="400"> </canvas>
+<canvas id="webgl" width="400" height="400"> </canvas>
+<script>
+"use strict";
+
+description("This test ensures WebGL implementations interact correctly with the canvas 2D drawImage call.");
+
+var err;
+var wtu = WebGLTestUtils;
+
+var canvas2d = [];
+var ctx2d = [];
+for (var i = 0; i < 3; i ++) {
+ canvas2d[i] = document.getElementById("canvas2d_" + i);
+ ctx2d[i] = canvas2d[i].getContext("2d");
+}
+
+var canvas = document.getElementById("webgl");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking canvas and WebGL drawImage interaction");
+ for (var count = 0; count < 10; count ++) {
+ gl.clearColor(0.25, 0.5, 0.75, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ ctx2d[0].drawImage(canvas, 0, 0, canvas2d[0].width, canvas2d[0].height);
+
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ ctx2d[1].drawImage(canvas, 0, 0, canvas2d[1].width, canvas2d[1].height);
+
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ ctx2d[2].drawImage(canvas, 0, 0, canvas2d[2].width, canvas2d[2].height);
+
+ gl.clearColor(1, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ wtu.checkCanvasRect(ctx2d[0], 0, 0, canvas2d[0].width, canvas2d[0].height, [64, 128, 192, 255],
+ "drawImage: Should be [64, 128, 192, 255]", 2);
+ wtu.checkCanvasRect(ctx2d[1], 0, 0, canvas2d[1].width, canvas2d[1].height, [255, 0, 0, 255],
+ "drawImage: Should be [255, 0, 0, 255]", 2);
+ wtu.checkCanvasRect(ctx2d[2], 0, 0, canvas2d[2].width, canvas2d[2].height, [255, 0, 255, 255],
+ "drawImage: Should be [255, 0, 255, 255]", 2);
+ }
+
+ err = gl.getError();
+ debug("");
+}
+finishTest();
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-hd-dpi-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-hd-dpi-test.html
new file mode 100644
index 0000000000..93edeacc0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-hd-dpi-test.html
@@ -0,0 +1,204 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL DrawingBuffer dimensions on HD-DPI machines test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshaderGrid" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+}
+</script>
+
+<script id="fshaderGrid" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ float r = mod(gl_FragCoord.x, 2.0) < 1.0 ? 0.0 : 1.0;
+ float g = mod(gl_FragCoord.y, 2.0) < 1.0 ? 0.0 : 1.0;
+ gl_FragColor = vec4(r, g, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description();
+debug("");
+
+var gl;
+var canvas;
+
+function checkDimensions() {
+ // We expect that for the sizes being testing drawingBufferWidth and drawingBufferHeight
+ // will match canvas.width and canvas.height.
+
+ // We need to test that devicePixelRatio does not effect the backbuffer size of a canvas.
+ shouldBe('gl.drawingBufferWidth', 'canvas.width');
+ shouldBe('gl.drawingBufferHeight', 'canvas.height');
+}
+
+// This uses gl_FragCoord to draw a device pixel relavent pattern.
+// If drawBufferWidth or drawBufferHeight are not in device pixels
+// this test should fail.
+function checkGrid(gl, width, height) {
+ var program = wtu.setupProgram(gl, ["vshaderGrid", "fshaderGrid"], ["a_position"]);
+ wtu.setupUnitQuad(gl);
+ gl.useProgram(program);
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ wtu.clearAndDrawUnitQuad(gl);
+
+ var pixels = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+
+ var colors = [
+ [ { color: [0, 0, 0, 255], name: "black" }, { color: [255, 0, 0, 255], name: "red" } ],
+ [ { color: [0, 255, 0, 255], name: "green" }, { color: [255, 255, 0, 255], name: "yellow" } ],
+ ];
+
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var info = colors[yy % 2][xx % 2];
+ var color = info.color;
+ var offset = (yy * width + xx) * 4;
+ for (var jj = 0; jj < 4; ++jj) {
+ if (pixels[offset + jj] != color[jj]) {
+ var actual = [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+ testFailed("at " + xx + ", " + yy + " expected " + color + "(" + info.name + ") was " + actual);
+ return;
+ }
+ }
+ }
+ }
+ testPassed("grid rendered correctly");
+}
+
+// This passes device coordinate vertices in to make sure gl.viewport is not being mucked with.
+function checkQuad(gl, width, height) {
+ var deviceToClipSpace = function(value, range) {
+ return value / range * 2 - 1;
+ }
+
+ var program = wtu.setupColorQuad(gl);
+
+ // draw a small green square in the top right corner.
+ var deviceX1 = width - 4;
+ var deviceX2 = width;
+ var deviceY1 = height - 4;
+ var deviceY2 = height;
+
+ var clipX1 = deviceToClipSpace(deviceX1, width);
+ var clipX2 = deviceToClipSpace(deviceX2, width);
+ var clipY1 = deviceToClipSpace(deviceY1, height);
+ var clipY2 = deviceToClipSpace(deviceY2, height);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [ clipX2, clipY2,
+ clipX1, clipY2,
+ clipX1, clipY1,
+ clipX2, clipY2,
+ clipX1, clipY1,
+ clipX2, clipY1]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var green = [0, 255, 0, 255];
+ var black = [0, 0, 0, 0];
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.drawUByteColorQuad(gl, [0, 255, 0, 255]);
+
+ var squareWidth = deviceX2 - deviceX1;
+ var squareHeight = deviceY2 - deviceY1;
+
+ // check the square.
+ wtu.checkCanvasRect(gl, deviceX1, deviceY1, squareWidth, squareHeight, green, "should be green");
+ // check outside the square.
+ wtu.checkCanvasRect(gl, 0, 0, width, height - squareHeight, black, "should be black");
+ wtu.checkCanvasRect(gl, 0, height - squareHeight, width - squareWidth, squareHeight, black, "should be black");
+}
+
+
+function test(desiredWidth, desiredHeight) {
+ debug("");
+ debug("testing canvas width = " + desiredWidth + ", height = " + desiredHeight);
+
+ // Make a fresh canvas.
+ canvas = document.createElement("canvas");
+ canvas.width = desiredWidth;
+ canvas.height = desiredHeight;
+
+ // This 'gl' must be global for shouldBe to work.
+ gl = wtu.create3DContext(canvas, {antialias: false});
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ // Check the dimensions are correct.
+ checkDimensions();
+
+ // Draw a pixel grid using a shader that draws in device coordinates
+ checkGrid(gl, desiredWidth, desiredHeight);
+
+ // Draw a quad in the top right corner.
+ checkQuad(gl, desiredWidth, desiredHeight);
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ debug("");
+ debug("testing resizing canvas to width = " + desiredWidth + ", height = " + desiredHeight);
+
+ var oldViewport = gl.getParameter(gl.VIEWPORT);
+
+ // flip width and height
+ canvas.width = desiredHeight;
+ canvas.height = desiredWidth;
+
+ // fix the viewport
+ gl.viewport(0, 0, desiredHeight, desiredWidth);
+
+ // Check the dimensions are correct.
+ checkDimensions();
+
+ // Draw a pixel grid using a shader that draws in device coordinates
+ checkGrid(gl, desiredHeight, desiredWidth);
+
+ // Draw a quad in the top right corner.
+ checkQuad(gl, desiredHeight, desiredWidth);
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ }
+}
+
+var wtu = WebGLTestUtils;
+
+// test a few sizes
+test(32, 16);
+test(128, 64);
+test(256, 512);
+
+debug("")
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-static-canvas-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-static-canvas-test.html
new file mode 100644
index 0000000000..66ffb32194
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-static-canvas-test.html
@@ -0,0 +1,116 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="50" height="50"> </canvas>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+
+function drawTriangleTest(gl)
+{
+ var width = 50;
+ var height = 50;
+ gl.viewport(0, 0, width, height);
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ 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.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ // Test several locations
+ wtu.checkCanvasRect(gl, 0, 0, width, 1, [0, 0, 0, 255],
+ 'First line should be all black');
+ wtu.checkCanvasRect(gl, 20, 15, 10, 1, [255, 0, 0, 255],
+ 'Line 15 should be red for at least 10 red pixels starting 20 pixels in');
+ wtu.checkCanvasRect(gl, 0, height - 1, width, 1, [0, 0, 0, 255],
+ 'Last line should be all black');
+}
+
+description("This test ensures WebGL implementations correctly implement drawingbufferWidth/Height with compositing.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var err;
+var maxSize;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+ shouldBeNonNull("program");
+ gl.enable(gl.DEPTH_TEST);
+ gl.clearColor(0, 0, 0, 1);
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ debug("");
+ debug("Checking drawingBufferWidth/drawingBufferHeight");
+
+ shouldBe('gl.drawingBufferWidth', 'gl.canvas.width');
+ shouldBe('gl.drawingBufferHeight', 'gl.canvas.height');
+
+ // Check that changing the canvas size to something too large falls back to reasonable values.
+ maxSize = gl.getParameter(gl.MAX_VIEWPORT_DIMS);
+ shouldBeTrue('maxSize[0] > 0');
+ shouldBeTrue('maxSize[1] > 0');
+
+ // debug("MAX_VIEWPORT_DIMS = " + maxSize[0] + "x" + maxSize[1]);
+ gl.canvas.width = maxSize[0] * 4;
+ gl.canvas.height = maxSize[1] * 4;
+ shouldBeTrue('gl.drawingBufferWidth > 0');
+ shouldBeTrue('gl.drawingBufferHeight > 0');
+ shouldBeTrue('gl.drawingBufferWidth <= maxSize[0]');
+ shouldBeTrue('gl.drawingBufferHeight <= maxSize[1]');
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ debug("");
+ debug("Checking scaling up then back down to 50/50, drawing still works.");
+ gl.canvas.width = 50;
+ gl.canvas.height = 50;
+ shouldBeTrue('gl.drawingBufferWidth == 50');
+ shouldBeTrue('gl.drawingBufferHeight == 50');
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ drawTriangleTest(gl);
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+}
+debug("")
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-test.html
new file mode 100644
index 0000000000..e1f458e59a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/drawingbuffer-test.html
@@ -0,0 +1,117 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Canvas.drawingBufferWidth,drawingBufferHeight Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+debug("");
+
+var gl;
+var oldViewport;
+
+function getMaxViewportDimensions() {
+ // create a fresh canvas. This canvas will be discarded
+ // after exiting this function.
+ var canvas = document.createElement("canvas");
+ gl = wtu.create3DContext(canvas, {antialias: false});
+ if (!gl) {
+ testFailed("context does not exist");
+ return [0, 0];
+ } else {
+ testPassed("context exists");
+
+ // For a default size canvas these should be equal.
+ // WebGL contexts are not allowed to change the size of the drawingBuffer
+ // for things like hi-res displays.
+ shouldBe('gl.drawingBufferWidth', 'gl.canvas.width');
+ shouldBe('gl.drawingBufferHeight', 'gl.canvas.height');
+ return gl.getParameter(gl.MAX_VIEWPORT_DIMS);
+ }
+}
+
+function test(desiredWidth, desiredHeight) {
+ debug("");
+ debug("testing canvas width = " + desiredWidth + ", height = " + desiredHeight);
+
+ // Make a fresh canvas.
+ var canvas = document.createElement("canvas");
+ canvas.width = desiredWidth;
+ canvas.height = desiredHeight;
+
+ // This 'gl' must be global for shouldBe to work.
+ gl = wtu.create3DContext(canvas, {antialias: false});
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ // Verify these stats didn't change since they come from a different
+ // context.
+ shouldBe('gl.getParameter(gl.MAX_VIEWPORT_DIMS)[0]', 'maxSize[0]');
+ shouldBe('gl.getParameter(gl.MAX_VIEWPORT_DIMS)[1]', 'maxSize[1]');
+
+ // check the initial viewport matches the drawingBufferWidth and drawingBufferHeight
+ shouldBe('gl.getParameter(gl.VIEWPORT)[0]', '0');
+ shouldBe('gl.getParameter(gl.VIEWPORT)[1]', '0');
+ shouldBe('gl.getParameter(gl.VIEWPORT)[2]', 'gl.drawingBufferWidth');
+ shouldBe('gl.getParameter(gl.VIEWPORT)[3]', 'gl.drawingBufferHeight');
+
+ debug("");
+ debug("testing resizing canvas to width = " + desiredWidth + ", height = " + desiredHeight);
+
+ oldViewport = gl.getParameter(gl.VIEWPORT);
+
+ // flip width and height
+ canvas.width = desiredHeight;
+ canvas.height = desiredWidth;
+
+ // Verify the viewport didn't change.
+ shouldBe('gl.getParameter(gl.VIEWPORT)[0]', 'oldViewport[0]');
+ shouldBe('gl.getParameter(gl.VIEWPORT)[1]', 'oldViewport[1]');
+ shouldBe('gl.getParameter(gl.VIEWPORT)[2]', 'oldViewport[2]');
+ shouldBe('gl.getParameter(gl.VIEWPORT)[3]', 'oldViewport[3]');
+
+ // fix the viewport
+// gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ }
+}
+
+var wtu = WebGLTestUtils;
+var maxSize = getMaxViewportDimensions();
+debug("MAX_VIEWPORT_DIMS: " + maxSize[0] + ", " + maxSize[1]);
+
+shouldBeTrue('maxSize[0] > 0');
+shouldBeTrue('maxSize[1] > 0');
+
+// test a small size to make sure it works at all.
+test(16, 32);
+
+// Make a canvas slightly larger than the max size WebGL can handle.
+// From section 2.2 of the spec the WebGL implementation should allow this to work.
+
+// test a size larger than MAX_VIEWPORT_DIMS in both dimensions
+test(maxSize[0] + 32, 8);
+
+debug("")
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-affected-by-to-data-url.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-affected-by-to-data-url.html
new file mode 100644
index 0000000000..bc21aca2ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-affected-by-to-data-url.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verifies than GL framebuffer bindings do not change by toDataURL()</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Verifies than GL framebuffer bindings do not change by toDataURL()");
+
+var wtu = WebGLTestUtils;
+function test() {
+ var glCanvas = document.getElementById("example");
+ var gl = wtu.create3DContext(glCanvas, {preserveDrawingBuffer: true, premultipliedAlpha: true});
+
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+
+ var program = wtu.setupColorQuad(gl);
+
+ // Clear backbuffer in red.
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+ var fbo = gl.createFramebuffer();
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 50, 50, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ return;
+ }
+
+ // Clear the FBO in green.
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // backbuffer is still in red.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ // toDataURL() calls must not bind backbuffer.
+ glCanvas.toDataURL();
+ // Calling twice caused a bug due to wrong cache impl; crbug.com/445848
+ glCanvas.toDataURL();
+ // It must applies to the FBO, not backbuffer.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // backbuffer must be in red, not green.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+}
+test();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-unaffected-on-resize.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-unaffected-on-resize.html
new file mode 100644
index 0000000000..e342841fe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/framebuffer-bindings-unaffected-on-resize.html
@@ -0,0 +1,85 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verifies that GL framebuffer bindings do not change when canvas is resized</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Verifies that GL framebuffer bindings do not change when canvas is resized");
+
+var err;
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var green = [0, 255, 0, 255];
+var blue = [0, 0, 255, 255];
+var fboSize = 2;
+shouldBeTrue("fboSize < canvas.width");
+var fbo = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+var fboTex = gl.createTexture();
+gl.activeTexture(gl.TEXTURE1);
+gl.bindTexture(gl.TEXTURE_2D, fboTex);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fboTex, 0);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fboSize, fboSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+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);
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+function checkFBO(color, msg) {
+ wtu.checkCanvasRect(gl, 0, 0, fboSize, fboSize, color, msg);
+ wtu.checkCanvasRect(gl, fboSize, fboSize, fboSize, fboSize, [0, 0, 0, 0], "area outside fbo should be transparent black");
+}
+
+// The FBO is 2x2 and it's bound so clearing should clear a 2x2 area
+// and calling read pixels should read the clear color in that 2x2 area
+// and 0,0,0,0 outside that area.
+//
+// If the FBO is no longer bound because of a WebGL implementation error
+// then likely the clear will clear the backbuffer and reading outside
+// the 2x2 area will not be 0,0,0,0
+
+function test() {
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ checkFBO(blue, "should be blue");
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ checkFBO(green, "should be green");
+}
+
+debug("test before resizing canvas");
+test();
+debug("test after resizing canvas");
+canvas.width = 8;
+test();
+debug("test after resizing canvas and waiting for compositing");
+canvas.width = 16;
+wtu.waitForComposite(function() {
+ test();
+ finishTest();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+});
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/rapid-resizing.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/rapid-resizing.html
new file mode 100644
index 0000000000..ed42083030
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/rapid-resizing.html
@@ -0,0 +1,171 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Rapid Resizing Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas1" style="width: 256px; height: 256px;"> </canvas>
+<canvas id="canvas2" style="width: 256px; height: 256px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 position;
+void main()
+{
+ gl_Position = vec4(position, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(0.0,1.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+
+description("Verifies that rapidly resizing the canvas works correctly.");
+
+debug("");
+debug("Regression test for Chromium <a href='http://crbug.com/299371'>Issue 299371</a> and <a href='http://crbug.com/557848'>Issue 557848</a>");
+debug("");
+
+var err;
+var wtu = WebGLTestUtils;
+var canvas;
+var largeSize = 256;
+var smallSize = 128;
+var currentSize;
+var gl;
+var program;
+var numFrames = 0;
+var testNumber = 0;
+
+function nextTest() {
+ ++testNumber;
+ numFrames = 0;
+ currentSize = largeSize;
+ if (testNumber > 2) {
+ finishTest();
+ return;
+ }
+
+ canvas = document.getElementById("canvas" + testNumber);
+ canvas.width = currentSize;
+ canvas.height = currentSize;
+ var usePreserveDrawingBuffer = (testNumber == 1) ? true : false;
+ debug("Testing preserveDrawingBuffer = " + usePreserveDrawingBuffer);
+ gl = wtu.create3DContext(canvas, { preserveDrawingBuffer: usePreserveDrawingBuffer });
+
+ if (!gl) {
+ testFailed("context does not exist");
+
+ wtu.requestAnimFrame(nextTest);
+ } else {
+ testPassed("context exists");
+
+ gl.clearColor(0, 0, 0, 1);
+
+ program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position"]);
+ shouldBeNonNull("program");
+
+ // Prepare to draw quads
+ var quadSize = 0.1;
+
+ var vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ // Lower left
+ -1, -1 + quadSize,
+ -1, -1,
+ -1 + quadSize, -1,
+ -1 + quadSize, -1 + quadSize,
+
+ // Lower right
+ 1 - quadSize, -1 + quadSize,
+ 1 - quadSize, -1,
+ 1, -1,
+ 1, -1 + quadSize,
+
+ // Upper right
+ 1 - quadSize, 1,
+ 1 - quadSize, 1 - quadSize,
+ 1, 1 - quadSize,
+ 1, 1,
+
+ // Upper left
+ -1, 1,
+ -1, 1 - quadSize,
+ -1 + quadSize, 1 - quadSize,
+ -1 + quadSize, 1
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([
+ 0, 1, 2,
+ 0, 2, 3,
+
+ 4, 5, 6,
+ 4, 6, 7,
+
+ 8, 9, 10,
+ 8, 10, 11,
+
+ 12, 13, 14,
+ 12, 14, 15
+ ]), gl.STATIC_DRAW);
+
+ wtu.requestAnimFrame(render);
+ }
+}
+
+function render() {
+ if (++numFrames < 30) {
+ if (currentSize == largeSize) {
+ canvas.height = smallSize;
+ currentSize = smallSize;
+ } else {
+ canvas.height = largeSize;
+ currentSize = largeSize;
+ }
+ }
+
+ gl.viewport(0, 0, largeSize, currentSize);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 24, gl.UNSIGNED_SHORT, 0);
+
+ // Check the four corners
+ var green = [ 0, 255, 0, 255 ];
+ var inset = 3;
+ wtu.checkCanvasRect(gl, inset, inset, 1, 1, green, "lower left should be green", 1);
+ wtu.checkCanvasRect(gl, largeSize - inset, inset, 1, 1, green, "lower right should be green", 1);
+ wtu.checkCanvasRect(gl, inset, currentSize - inset, 1, 1, green, "upper left should be green", 1);
+ wtu.checkCanvasRect(gl, largeSize - inset, currentSize - inset, 1, 1, green, "upper right should be green", 1);
+
+ if (numFrames < 60) {
+ wtu.requestAnimFrame(render);
+ } else {
+ wtu.requestAnimFrame(nextTest);
+ }
+}
+
+wtu.requestAnimFrame(nextTest);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/render-after-resize-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/render-after-resize-test.html
new file mode 100644
index 0000000000..f973d4d618
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/render-after-resize-test.html
@@ -0,0 +1,142 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL render after resize test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<canvas style="width: 100px; height: 100px; border: 1px solid black;" id="c"></canvas>
+<div id="console"></div>
+<script>
+description("This test ensures WebGL implementations can render correctly after resizing the canvas.");
+debug("");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext("c", {depth: true, stencil: true});
+shouldBeTrue("gl != null");
+
+gl.clearColor(1,0,0,1);
+
+const positionLocation = 0;
+const program = wtu.setupColorQuad(gl, positionLocation);
+const colorLocation = gl.getUniformLocation(program, 'u_color');
+gl.useProgram(program);
+
+const SMALL = 2;
+// Changing this size to something smaller produces
+// different results. Sometimes wrong, sometimes correct.
+const LARGE = 1200;
+
+gl.uniform4fv(colorLocation, [0.0, 1.0, 0.0, 1.0]);
+
+// -
+
+debug('\nResize then render.');
+gl.canvas.width = gl.canvas.height = SMALL;
+gl.viewport(0, 0, SMALL, SMALL);
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.drawUnitQuad(gl);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
+
+// -
+
+debug('\nResize twice then render.');
+gl.canvas.width = gl.canvas.height = LARGE;
+gl.canvas.width = gl.canvas.height = SMALL;
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.drawUnitQuad(gl);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
+
+debug('\nCause a GL error, then resize and render.');
+gl.depthFunc(0); // Causes INVALID_ENUM
+gl.canvas.width = gl.canvas.height = LARGE;
+gl.clear(gl.COLOR_BUFFER_BIT);
+gl.canvas.width = gl.canvas.height = SMALL;
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.drawUnitQuad(gl);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
+wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+// -
+
+debug('\nRender, no-op resize, then depth-fail render.');
+
+gl.enable(gl.DEPTH_TEST);
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+gl.uniform4fv(colorLocation, [0.0, 1.0, 0.0, 1.0]);
+wtu.drawUnitQuad(gl);
+
+gl.canvas.width = gl.canvas.width;
+gl.uniform4fv(colorLocation, [0.0, 0.0, 1.0, 1.0]);
+wtu.drawUnitQuad(gl);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
+
+// Reset
+gl.disable(gl.DEPTH_TEST);
+
+// -
+
+debug('\nRender, no-op resize, then stencil-fail render.');
+
+gl.enable(gl.STENCIL_TEST);
+gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
+gl.stencilFunc(gl.EQUAL, 0, 0xff);
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+gl.uniform4fv(colorLocation, [0.0, 1.0, 0.0, 1.0]);
+wtu.drawUnitQuad(gl);
+
+gl.canvas.width = gl.canvas.width;
+gl.uniform4fv(colorLocation, [0.0, 0.0, 1.0, 1.0]);
+wtu.drawUnitQuad(gl);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
+
+// Reset
+gl.disable(gl.STENCIL_TEST);
+gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+gl.stencilFunc(gl.ALWAYS, 0, 0xff);
+
+// -
+
+debug('\nRender, no-op resize, then scissor render.');
+
+gl.enable(gl.SCISSOR_TEST);
+gl.clear(gl.COLOR_BUFFER_BIT);
+gl.uniform4fv(colorLocation, [0.0, 1.0, 0.0, 1.0]);
+wtu.drawUnitQuad(gl);
+
+gl.canvas.width = gl.canvas.width;
+gl.enable(gl.SCISSOR_TEST);
+gl.scissor(0, 0, 1, 1);
+gl.uniform4fv(colorLocation, [0.0, 0.0, 1.0, 1.0]);
+wtu.drawUnitQuad(gl);
+gl.disable(gl.SCISSOR_TEST);
+
+wtu.checkCanvasRect(gl, 1, 0, 1, 1, [ 0, 255, 0, 255 ]);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 0, 255, 255 ]);
+
+// -
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/texture-bindings-unaffected-on-resize.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/texture-bindings-unaffected-on-resize.html
new file mode 100644
index 0000000000..ac05a734ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/texture-bindings-unaffected-on-resize.html
@@ -0,0 +1,66 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verifies that GL texture bindings do not change when canvas is resized');
+
+var err;
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+var green = [0, 255, 0, 255];
+var blue = [0, 0, 255, 255];
+var tex0 = gl.createTexture();
+wtu.fillTexture(gl, tex0, 1, 1, blue, 0);
+gl.activeTexture(gl.TEXTURE1)
+var tex1 = gl.createTexture();
+wtu.fillTexture(gl, tex1, 1, 1, green, 0);
+
+var loc = gl.getUniformLocation(program, "tex");
+
+function test() {
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.uniform1i(loc, 0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, blue, "should be blue");
+ gl.uniform1i(loc, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, green, "should be green");
+}
+
+debug("test before resizing canvas");
+test();
+debug("test after resizing canvas");
+canvas.width = 8;
+test();
+debug("test after resizing canvas and waiting for compositing");
+canvas.width = 16;
+wtu.waitForComposite(function() {
+ test();
+ finishTest();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+});
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-after-composite.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-after-composite.html
new file mode 100644
index 0000000000..668b9c7154
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-after-composite.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL toDataURL after composite test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas width="20" height="20" style="border: 1px solid black; width: 128px; height: 128px" id="c3d"></canvas>
+<canvas width="20" height="20" style="border: 1px solid black; width: 128px; height: 128px" id="c2d"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+const wtu = WebGLTestUtils;
+let gl;
+let ctx;
+
+function main() {
+ description();
+ const c2d = document.getElementById("c2d");
+ ctx = c2d.getContext("2d");
+ gl = wtu.create3DContext("c3d", { preserveDrawingBuffer: true });
+
+ // Clear to green
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.waitForComposite(() => {
+ // Performs gl.canvas.toDataURL() internally
+ let img = wtu.makeImageFromCanvas(gl.canvas, function() {
+ ctx.drawImage(img, 0, 0);
+ wtu.checkCanvas(ctx, [0, 255, 0], "toDataURL loaded into image, drawn into 2D context, should be green", 5);
+ finishTest();
+ });
+ });
+
+};
+
+main();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-test.html
new file mode 100644
index 0000000000..60e882c61f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/to-data-url-test.html
@@ -0,0 +1,142 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL toDataURL test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas width="20" height="20" style="border: 1px solid black; width: 16px; height: 16px" id="c3d"></canvas>
+<canvas width="20" height="20" style="border: 1px solid black; width: 16px; height: 16px" id="c2d"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+var wtu = WebGLTestUtils;
+var numTests = 10;
+var gl;
+var ctx;
+
+var main = function() {
+ description();
+ ctx = document.getElementById("c2d").getContext("2d");
+
+ var updateCanvas = function(width, height, attributes) {
+ var canvas = document.getElementById("c3d");
+
+ if (gl && (gl.attributes !== attributes)) {
+ // Attributes changed, recreate the canvas
+ var newCanvas = canvas.cloneNode();
+ canvas.parentNode.replaceChild(newCanvas, canvas);
+ canvas = newCanvas;
+ gl = undefined;
+ }
+
+ canvas.width = width;
+ canvas.height = height;
+
+ if (!gl) {
+ gl = wtu.create3DContext(canvas, attributes);
+
+ if (!gl) {
+ testFailed("can't create 3d context");
+ return;
+ }
+
+ gl.attributes = attributes;
+ }
+
+ return gl;
+ };
+
+ var clearRect = function(gl, x, y, width, height, color) {
+ gl.clearColor(color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
+ gl.scissor(x, y, width, height);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ };
+
+ var testSize = function(width, height, attributes, callback) {
+ let attributesDebugMessage = "";
+ if (attributes) {
+ attributesDebugMessage = " attributes: " + JSON.stringify(attributes);
+ }
+ debug("testing " + width + " by " + height + attributesDebugMessage);
+ var gl = updateCanvas(width, height, attributes);
+ if (!gl) {
+ callback();
+ return;
+ }
+
+ gl.viewport(0, 0, width, height);
+ gl.enable(gl.SCISSOR_TEST);
+
+ var bottomColor = [255, 0, 0, 255];
+ var topColor = [0, 255, 0, 255];
+ var rightColor = [0, 0, 255, 255];
+ var halfHeight = Math.floor(height / 2);
+ var topHeight = height - halfHeight;
+ var canvasTopHeight = height - topHeight;
+ clearRect(gl, 0, 0, width, halfHeight, bottomColor);
+ clearRect(gl, 0, halfHeight, width, topHeight, topColor);
+ clearRect(gl, width - 1, 0, 1, height, rightColor);
+
+ // Performs gl.canvas.toDataURL() internally
+ var img = wtu.makeImageFromCanvas(gl.canvas, function() {
+ ctx.canvas.width = width;
+ ctx.canvas.height = height;
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(img, 0, 0);
+ wtu.checkCanvasRect(ctx, 0, 0, width - 1, topHeight, topColor);
+ wtu.checkCanvasRect(ctx, 0, topHeight, width - 1, halfHeight, bottomColor);
+ wtu.checkCanvasRect(ctx, width - 1, 0, 1, height, rightColor);
+ debug("");
+ callback();
+ });
+ };
+
+ const premultipliedAlphaAttributes = {
+ premultipliedAlpha: false,
+ };
+ var tests = [
+ { width: 16 , height: 16 , },
+ { width: 16 - 1, height: 16 , },
+ { width: 16 - 1, height: 16 - 1, },
+ { width: 16 + 1, height: 16 - 1, },
+ { width: 16 - 1, height: 16 + 1, },
+ { width: 256 , height: 256 , },
+ { width: 256 - 1, height: 256 , },
+ { width: 256 - 1, height: 256 - 1, },
+ { width: 256 + 1, height: 256 - 1, },
+ { width: 256 - 1, height: 256 + 1, },
+ { width: 512 , height: 512 , },
+ { width: 512 - 1, height: 512 , },
+ { width: 512 - 1, height: 512 - 1, },
+ { width: 512 + 1, height: 512 - 1, },
+ { width: 512 - 1, height: 512 + 1, },
+ { width: 16 , height: 16 , attributes: premultipliedAlphaAttributes},
+ ];
+ var testIndex = 0;
+ var runNextTest = function() {
+ if (testIndex == tests.length) {
+ finishTest();
+ return;
+ }
+ var test = tests[testIndex++];
+ testSize(test.width, test.height, test.attributes, function() {
+ setTimeout(runNextTest, 0);
+ })
+ };
+ runNextTest();
+};
+main();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/viewport-unchanged-upon-resize.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/viewport-unchanged-upon-resize.html
new file mode 100644
index 0000000000..70414fc1a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/viewport-unchanged-upon-resize.html
@@ -0,0 +1,92 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 g_Position;
+
+void main()
+{
+ gl_Position = vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verifies that GL viewport does not change when canvas is resized');
+
+var err;
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["g_Position"]);
+
+var vertices = new Float32Array([
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, -1.0, 0.0]);
+var vbo = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+// Clear and set up
+gl.clearColor(0, 0, 1, 1);
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+gl.useProgram(program);
+// Draw the triangle pair to the frame buffer
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+// Ensure that the frame buffer is red at the sampled pixel
+wtu.checkCanvasRect(gl, 2, 2, 1, 1, [255, 0, 0, 255]);
+
+// Now resize the canvas
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL errors before resizing the canvas");
+var canvas = gl.canvas;
+canvas.width = 8;
+canvas.height = 8;
+err = gl.getError();
+// Some implementations might lost the context when resizing
+if (err == gl.CONTEXT_LOST_WEBGL) {
+ testPassed("canvas lost context on resize");
+} else {
+ shouldBe("err", "gl.NO_ERROR");
+ // Do another render
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ // This time, because we did not change the viewport, it should
+ // still be (0, 0, 4, 4), so only the lower-left quadrant should
+ // have been filled.
+ wtu.checkCanvasRect(gl, 6, 6, 1, 1, [0, 0, 255, 255]);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/canvas/webgl-to-2d-canvas.html b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/webgl-to-2d-canvas.html
new file mode 100644
index 0000000000..bed9c89718
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/canvas/webgl-to-2d-canvas.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL canvas to 2D canvas test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<style>
+canvas {
+ border: 1px solid black;
+ margin: 3px;
+ display: block;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+var wtu = WebGLTestUtils;
+var diff;
+var consoleElem = document.querySelector('#console');
+
+var main = function() {
+ description();
+
+ test({ premultipliedAlpha: true, }, [171, 234, 172, 191], [128, 255, 177, 128]);
+ test({ premultipliedAlpha: false, }, [170, 234, 171, 191], [128, 255, 177, 128]);
+ test({ alpha: false, }, [127, 255, 178, 255], [128, 255, 178, 255]);
+ test({ premultipliedAlpha: false, alpha: false, }, [127, 255, 178, 255], [128, 255, 178, 255]);
+
+ function test(attrs, expected, expected2) {
+ debug(`test: ${JSON.stringify(attrs)}`);
+
+ const canvas = document.createElement('canvas');
+ canvas.width = 64;
+ canvas.height = 64;
+
+ const gl = wtu.create3DContext(canvas, attrs);
+ if (!gl) {
+ testFailed("can't create 3d context");
+ return;
+ }
+ const alpha = 0.5;
+ const effectiveAlpha = attrs.premultipliedAlpha ? alpha : 1.0;
+ const color = [0.5, 1.0, 0.7].map(v => v * effectiveAlpha);
+ color.push(0.5);
+ debug(`clearColor: ${color.join(', ')}`);
+ gl.clearColor(...color);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ consoleElem.appendChild(canvas);
+
+ const ctx = document.createElement('canvas').getContext('2d');
+ ctx.canvas.width = 128;
+ ctx.canvas.height = 128;
+ ctx.fillStyle = 'rgba(255, 190, 160, 0.5)';
+ ctx.fillRect(0, 0, 64, 64);
+ ctx.drawImage(canvas, 32, 32);
+ consoleElem.appendChild(ctx.canvas);
+
+ wtu.checkCanvasRect(ctx, 33, 33, 1, 1, expected, 'canvas 2d is correct color', 3);
+ wtu.checkCanvasRect(ctx, 65, 65, 1, 1, expected2, 'canvas 2d is correct color', 3);
+ debug('----------------------------------');
+ }
+ finishTest();
+};
+main();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/context/00_test_list.txt
new file mode 100644
index 0000000000..f1acae5dfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/00_test_list.txt
@@ -0,0 +1,21 @@
+--max-version 1.9.9 constants-and-properties.html
+--min-version 1.0.2 context-attribute-preserve-drawing-buffer.html
+--min-version 1.0.4 context-attribute-preserve-drawing-buffer-antialias.html
+context-attributes-alpha-depth-stencil-antialias.html
+--min-version 1.0.4 context-size-change.html
+--min-version 1.0.4 context-no-alpha-fbo-with-alpha.html
+--min-version 1.0.2 --slow context-creation-and-destruction.html
+--min-version 1.0.3 --slow context-creation.html
+--min-version 1.0.3 --slow context-eviction-with-garbage-collection.html
+--min-version 1.0.3 context-hidden-alpha.html
+--min-version 1.0.2 context-release-upon-reload.html
+--min-version 1.0.2 context-release-with-workers.html
+context-lost-restored.html
+context-lost.html
+--max-version 1.9.9 context-type-test.html
+--min-version 1.0.4 deleted-object-behavior.html
+incorrect-context-object-behaviour.html
+--max-version 1.9.9 methods.html
+premultiplyalpha-test.html
+--min-version 1.0.4 user-defined-properties-on-context.html
+--min-version 1.0.4 zero-sized-canvas.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/constants-and-properties.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/constants-and-properties.html
new file mode 100644
index 0000000000..ccf128e11b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/constants-and-properties.html
@@ -0,0 +1,546 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Constants and Properties Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<script>
+"use strict";
+description("This test ensures that the WebGL context has all the constants and (non-function) properties in the specification.");
+
+var constants = {
+ /* ClearBufferMask */
+DEPTH_BUFFER_BIT : 0x00000100,
+STENCIL_BUFFER_BIT : 0x00000400,
+COLOR_BUFFER_BIT : 0x00004000,
+
+ /* BeginMode */
+POINTS : 0x0000,
+LINES : 0x0001,
+LINE_LOOP : 0x0002,
+LINE_STRIP : 0x0003,
+TRIANGLES : 0x0004,
+TRIANGLE_STRIP : 0x0005,
+TRIANGLE_FAN : 0x0006,
+
+ /* AlphaFunction (not supported in ES20) */
+ /* NEVER */
+ /* LESS */
+ /* EQUAL */
+ /* LEQUAL */
+ /* GREATER */
+ /* NOTEQUAL */
+ /* GEQUAL */
+ /* ALWAYS */
+
+ /* BlendingFactorDest */
+ZERO : 0,
+ONE : 1,
+SRC_COLOR : 0x0300,
+ONE_MINUS_SRC_COLOR : 0x0301,
+SRC_ALPHA : 0x0302,
+ONE_MINUS_SRC_ALPHA : 0x0303,
+DST_ALPHA : 0x0304,
+ONE_MINUS_DST_ALPHA : 0x0305,
+
+ /* BlendingFactorSrc */
+ /* ZERO */
+ /* ONE */
+DST_COLOR : 0x0306,
+ONE_MINUS_DST_COLOR : 0x0307,
+SRC_ALPHA_SATURATE : 0x0308,
+ /* SRC_ALPHA */
+ /* ONE_MINUS_SRC_ALPHA */
+ /* DST_ALPHA */
+ /* ONE_MINUS_DST_ALPHA */
+
+ /* BlendEquationSeparate */
+FUNC_ADD : 0x8006,
+BLEND_EQUATION : 0x8009,
+BLEND_EQUATION_RGB : 0x8009, /* same as BLEND_EQUATION */
+BLEND_EQUATION_ALPHA : 0x883D,
+
+ /* BlendSubtract */
+FUNC_SUBTRACT : 0x800A,
+FUNC_REVERSE_SUBTRACT : 0x800B,
+
+ /* Separate Blend Functions */
+BLEND_DST_RGB : 0x80C8,
+BLEND_SRC_RGB : 0x80C9,
+BLEND_DST_ALPHA : 0x80CA,
+BLEND_SRC_ALPHA : 0x80CB,
+CONSTANT_COLOR : 0x8001,
+ONE_MINUS_CONSTANT_COLOR : 0x8002,
+CONSTANT_ALPHA : 0x8003,
+ONE_MINUS_CONSTANT_ALPHA : 0x8004,
+BLEND_COLOR : 0x8005,
+
+ /* Buffer Objects */
+ARRAY_BUFFER : 0x8892,
+ELEMENT_ARRAY_BUFFER : 0x8893,
+ARRAY_BUFFER_BINDING : 0x8894,
+ELEMENT_ARRAY_BUFFER_BINDING : 0x8895,
+
+STREAM_DRAW : 0x88E0,
+STATIC_DRAW : 0x88E4,
+DYNAMIC_DRAW : 0x88E8,
+
+BUFFER_SIZE : 0x8764,
+BUFFER_USAGE : 0x8765,
+
+CURRENT_VERTEX_ATTRIB : 0x8626,
+
+ /* CullFaceMode */
+FRONT : 0x0404,
+BACK : 0x0405,
+FRONT_AND_BACK : 0x0408,
+
+ /* DepthFunction */
+ /* NEVER */
+ /* LESS */
+ /* EQUAL */
+ /* LEQUAL */
+ /* GREATER */
+ /* NOTEQUAL */
+ /* GEQUAL */
+ /* ALWAYS */
+
+ /* EnableCap */
+ /* TEXTURE_2D */
+CULL_FACE : 0x0B44,
+BLEND : 0x0BE2,
+DITHER : 0x0BD0,
+STENCIL_TEST : 0x0B90,
+DEPTH_TEST : 0x0B71,
+SCISSOR_TEST : 0x0C11,
+POLYGON_OFFSET_FILL : 0x8037,
+SAMPLE_ALPHA_TO_COVERAGE : 0x809E,
+SAMPLE_COVERAGE : 0x80A0,
+
+ /* ErrorCode */
+NO_ERROR : 0,
+INVALID_ENUM : 0x0500,
+INVALID_VALUE : 0x0501,
+INVALID_OPERATION : 0x0502,
+OUT_OF_MEMORY : 0x0505,
+
+ /* FrontFaceDirection */
+CW : 0x0900,
+CCW : 0x0901,
+
+ /* GetPName */
+LINE_WIDTH : 0x0B21,
+ALIASED_POINT_SIZE_RANGE : 0x846D,
+ALIASED_LINE_WIDTH_RANGE : 0x846E,
+CULL_FACE_MODE : 0x0B45,
+FRONT_FACE : 0x0B46,
+DEPTH_RANGE : 0x0B70,
+DEPTH_WRITEMASK : 0x0B72,
+DEPTH_CLEAR_VALUE : 0x0B73,
+DEPTH_FUNC : 0x0B74,
+STENCIL_CLEAR_VALUE : 0x0B91,
+STENCIL_FUNC : 0x0B92,
+STENCIL_FAIL : 0x0B94,
+STENCIL_PASS_DEPTH_FAIL : 0x0B95,
+STENCIL_PASS_DEPTH_PASS : 0x0B96,
+STENCIL_REF : 0x0B97,
+STENCIL_VALUE_MASK : 0x0B93,
+STENCIL_WRITEMASK : 0x0B98,
+STENCIL_BACK_FUNC : 0x8800,
+STENCIL_BACK_FAIL : 0x8801,
+STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802,
+STENCIL_BACK_PASS_DEPTH_PASS : 0x8803,
+STENCIL_BACK_REF : 0x8CA3,
+STENCIL_BACK_VALUE_MASK : 0x8CA4,
+STENCIL_BACK_WRITEMASK : 0x8CA5,
+VIEWPORT : 0x0BA2,
+SCISSOR_BOX : 0x0C10,
+ /* SCISSOR_TEST */
+COLOR_CLEAR_VALUE : 0x0C22,
+COLOR_WRITEMASK : 0x0C23,
+UNPACK_ALIGNMENT : 0x0CF5,
+PACK_ALIGNMENT : 0x0D05,
+MAX_TEXTURE_SIZE : 0x0D33,
+MAX_VIEWPORT_DIMS : 0x0D3A,
+SUBPIXEL_BITS : 0x0D50,
+RED_BITS : 0x0D52,
+GREEN_BITS : 0x0D53,
+BLUE_BITS : 0x0D54,
+ALPHA_BITS : 0x0D55,
+DEPTH_BITS : 0x0D56,
+STENCIL_BITS : 0x0D57,
+POLYGON_OFFSET_UNITS : 0x2A00,
+ /* POLYGON_OFFSET_FILL */
+POLYGON_OFFSET_FACTOR : 0x8038,
+TEXTURE_BINDING_2D : 0x8069,
+SAMPLE_BUFFERS : 0x80A8,
+SAMPLES : 0x80A9,
+SAMPLE_COVERAGE_VALUE : 0x80AA,
+SAMPLE_COVERAGE_INVERT : 0x80AB,
+
+ /* GetTextureParameter */
+ /* TEXTURE_MAG_FILTER */
+ /* TEXTURE_MIN_FILTER */
+ /* TEXTURE_WRAP_S */
+ /* TEXTURE_WRAP_T */
+
+COMPRESSED_TEXTURE_FORMATS : 0x86A3,
+
+ /* HintMode */
+DONT_CARE : 0x1100,
+FASTEST : 0x1101,
+NICEST : 0x1102,
+
+ /* HintTarget */
+GENERATE_MIPMAP_HINT : 0x8192,
+
+ /* DataType */
+BYTE : 0x1400,
+UNSIGNED_BYTE : 0x1401,
+SHORT : 0x1402,
+UNSIGNED_SHORT : 0x1403,
+INT : 0x1404,
+UNSIGNED_INT : 0x1405,
+FLOAT : 0x1406,
+
+ /* PixelFormat */
+DEPTH_COMPONENT : 0x1902,
+ALPHA : 0x1906,
+RGB : 0x1907,
+RGBA : 0x1908,
+LUMINANCE : 0x1909,
+LUMINANCE_ALPHA : 0x190A,
+
+ /* PixelType */
+ /* UNSIGNED_BYTE */
+UNSIGNED_SHORT_4_4_4_4 : 0x8033,
+UNSIGNED_SHORT_5_5_5_1 : 0x8034,
+UNSIGNED_SHORT_5_6_5 : 0x8363,
+
+ /* Shaders */
+FRAGMENT_SHADER : 0x8B30,
+VERTEX_SHADER : 0x8B31,
+MAX_VERTEX_ATTRIBS : 0x8869,
+MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB,
+MAX_VARYING_VECTORS : 0x8DFC,
+MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D,
+MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C,
+MAX_TEXTURE_IMAGE_UNITS : 0x8872,
+MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD,
+SHADER_TYPE : 0x8B4F,
+DELETE_STATUS : 0x8B80,
+LINK_STATUS : 0x8B82,
+VALIDATE_STATUS : 0x8B83,
+ATTACHED_SHADERS : 0x8B85,
+ACTIVE_UNIFORMS : 0x8B86,
+ACTIVE_ATTRIBUTES : 0x8B89,
+SHADING_LANGUAGE_VERSION : 0x8B8C,
+CURRENT_PROGRAM : 0x8B8D,
+
+ /* StencilFunction */
+NEVER : 0x0200,
+LESS : 0x0201,
+EQUAL : 0x0202,
+LEQUAL : 0x0203,
+GREATER : 0x0204,
+NOTEQUAL : 0x0205,
+GEQUAL : 0x0206,
+ALWAYS : 0x0207,
+
+ /* StencilOp */
+ /* ZERO */
+KEEP : 0x1E00,
+REPLACE : 0x1E01,
+INCR : 0x1E02,
+DECR : 0x1E03,
+INVERT : 0x150A,
+INCR_WRAP : 0x8507,
+DECR_WRAP : 0x8508,
+
+ /* StringName */
+VENDOR : 0x1F00,
+RENDERER : 0x1F01,
+VERSION : 0x1F02,
+
+ /* TextureMagFilter */
+NEAREST : 0x2600,
+LINEAR : 0x2601,
+
+ /* TextureMinFilter */
+ /* NEAREST */
+ /* LINEAR */
+NEAREST_MIPMAP_NEAREST : 0x2700,
+LINEAR_MIPMAP_NEAREST : 0x2701,
+NEAREST_MIPMAP_LINEAR : 0x2702,
+LINEAR_MIPMAP_LINEAR : 0x2703,
+
+ /* TextureParameterName */
+TEXTURE_MAG_FILTER : 0x2800,
+TEXTURE_MIN_FILTER : 0x2801,
+TEXTURE_WRAP_S : 0x2802,
+TEXTURE_WRAP_T : 0x2803,
+
+ /* TextureTarget */
+TEXTURE_2D : 0x0DE1,
+TEXTURE : 0x1702,
+
+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,
+MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C,
+
+ /* TextureUnit */
+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,
+
+ /* TextureWrapMode */
+REPEAT : 0x2901,
+CLAMP_TO_EDGE : 0x812F,
+MIRRORED_REPEAT : 0x8370,
+
+ /* Uniform Types */
+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_2D : 0x8B5E,
+SAMPLER_CUBE : 0x8B60,
+
+ /* Vertex Arrays */
+VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622,
+VERTEX_ATTRIB_ARRAY_SIZE : 0x8623,
+VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624,
+VERTEX_ATTRIB_ARRAY_TYPE : 0x8625,
+VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A,
+VERTEX_ATTRIB_ARRAY_POINTER : 0x8645,
+VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
+
+ /* Read Format */
+IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A,
+IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B,
+
+ /* Shader Source */
+COMPILE_STATUS : 0x8B81,
+
+ /* Shader Precision-Specified Types */
+LOW_FLOAT : 0x8DF0,
+MEDIUM_FLOAT : 0x8DF1,
+HIGH_FLOAT : 0x8DF2,
+LOW_INT : 0x8DF3,
+MEDIUM_INT : 0x8DF4,
+HIGH_INT : 0x8DF5,
+
+ /* Framebuffer Object. */
+FRAMEBUFFER : 0x8D40,
+RENDERBUFFER : 0x8D41,
+
+RGBA4 : 0x8056,
+RGB5_A1 : 0x8057,
+RGB565 : 0x8D62,
+DEPTH_COMPONENT16 : 0x81A5,
+STENCIL_INDEX8 : 0x8D48,
+DEPTH_STENCIL : 0x84F9,
+
+RENDERBUFFER_WIDTH : 0x8D42,
+RENDERBUFFER_HEIGHT : 0x8D43,
+RENDERBUFFER_INTERNAL_FORMAT : 0x8D44,
+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_ATTACHMENT_OBJECT_TYPE : 0x8CD0,
+FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3,
+
+COLOR_ATTACHMENT0 : 0x8CE0,
+DEPTH_ATTACHMENT : 0x8D00,
+STENCIL_ATTACHMENT : 0x8D20,
+DEPTH_STENCIL_ATTACHMENT : 0x821A,
+
+NONE : 0,
+
+FRAMEBUFFER_COMPLETE : 0x8CD5,
+FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6,
+FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7,
+FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9,
+FRAMEBUFFER_UNSUPPORTED : 0x8CDD,
+
+FRAMEBUFFER_BINDING : 0x8CA6,
+RENDERBUFFER_BINDING : 0x8CA7,
+MAX_RENDERBUFFER_SIZE : 0x84E8,
+
+INVALID_FRAMEBUFFER_OPERATION : 0x0506,
+
+/* WebGL-specific enums */
+UNPACK_FLIP_Y_WEBGL : 0x9240,
+UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241,
+CONTEXT_LOST_WEBGL : 0x9242,
+UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243,
+BROWSER_DEFAULT_WEBGL : 0x9244
+};
+
+// Other non-function properties on the WebGL object
+var otherProperties = {
+drawingBufferWidth : "number",
+drawingBufferHeight : "number",
+drawingBufferColorSpace : "string",
+unpackColorSpace : "string",
+canvas : "implementation-dependent"
+};
+
+// Properties to be ignored (as a list of strings) because they were
+// added in versions of the spec that are backward-compatible with
+// this version
+var ignoredProperties = [
+];
+
+// Constants removed from the WebGL spec compared to ES 2.0
+var removedConstants = {
+NUM_COMPRESSED_TEXTURE_FORMATS : 0x86A2,
+FIXED : 0x140C,
+ACTIVE_UNIFORM_MAX_LENGTH : 0x8B87,
+ACTIVE_ATTRIBUTE_MAX_LENGTH : 0x8B8A,
+EXTENSIONS : 0x1F03,
+INFO_LOG_LENGTH : 0x8B84,
+SHADER_SOURCE_LENGTH : 0x8B88,
+SHADER_COMPILER : 0x8DFA,
+SHADER_BINARY_FORMATS : 0x8DF8,
+NUM_SHADER_BINARY_FORMATS : 0x8DF9,
+};
+
+function assertProperty(v, p) {
+ if (p in v) {
+ return true;
+ } else {
+ testFailed("Property does not exist: " + p)
+ return false;
+ }
+}
+
+function assertNoProperty(v, p) {
+ if (p in v) {
+ testFailed("Property is defined and should not be: " + p)
+ return false;
+ } else {
+ return true;
+ }
+}
+
+function assertMsg_(bool, msg) {
+ if (!bool) // show only failures to avoid spamming result list
+ assertMsg(bool, msg);
+ return bool;
+}
+
+debug("");
+debug("Canvas.getContext");
+
+var canvas = document.getElementById("canvas");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(canvas);
+var passed = true;
+for (var i in constants) {
+ var r = assertProperty(gl, i) && assertMsg_(gl[i] == constants[i], "Property "+i+" value test "+gl[i]+" == "+constants[i]);
+ passed = passed && r;
+}
+if (passed) {
+ testPassed("All WebGL constants found to have correct values.");
+}
+passed = true;
+for (var i in removedConstants) {
+ var r = assertNoProperty(gl, i);
+ passed = passed && r;
+}
+if (passed) {
+ testPassed("All constants removed from WebGL spec were absent from WebGL context.");
+}
+var extended = false;
+for (var i in gl) {
+ if (constants[i] !== undefined) {
+ // OK; known constant
+ } else if (ignoredProperties.indexOf(i) != -1) {
+ // OK; constant that should be ignored because it was added in a later version of the spec
+ } else if (otherProperties[i] !== undefined &&
+ (otherProperties[i] == "implementation-dependent" || typeof gl[i] == otherProperties[i])) {
+ // OK; known property of known type
+ } else if (typeof gl[i] != "function" && removedConstants[i] === undefined) {
+ if (!extended) {
+ extended = true;
+ testFailed("Also found the following extra properties:");
+ }
+ testFailed(i);
+ }
+}
+
+if (!extended) {
+ testPassed("No extra properties found on WebGL context.");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer-antialias.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer-antialias.html
new file mode 100644
index 0000000000..fa8d9937db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer-antialias.html
@@ -0,0 +1,143 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="128" height="64" style="width: 32px; height: 32px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description(' Test drawingbuffer is preserved when drawing');
+
+const waitForComposite = () => new Promise(resolve => wtu.waitForComposite(resolve));
+const gl = wtu.create3DContext("canvas", {
+ preserveDrawingBuffer: true,
+ antialias: true,
+});
+console.log(gl.getContextAttributes());
+const w = 128;
+const h = 64;
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ gl.viewport(0, 0, w, h);
+ runTest(gl, 4);
+}
+
+async function runTest(gl, sampleCount) {
+ const vs = `
+ attribute vec4 position;
+ uniform mat4 mat;
+
+ void main() {
+ gl_Position = mat * position;
+ }
+ `;
+
+ const fs = `
+ precision mediump float;
+ uniform vec4 color;
+ void main() {
+ gl_FragColor = color;
+ }
+ `;
+
+ const positionLoc = 0; // hard coded in shaders so they match
+ const buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0, 0,
+ 1, 0,
+ 0, 1,
+ 0, 1,
+ 1, 0,
+ 1, 1,
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ const program = wtu.setupProgram(gl, [vs, fs]);
+
+ const colorLoc = gl.getUniformLocation(program, 'color');
+ const matLoc = gl.getUniformLocation(program, 'mat');
+
+ gl.useProgram(program);
+
+ const draw = (color, mat) => {
+ gl.uniform4fv(colorLoc, color);
+ gl.uniformMatrix4fv(matLoc, false, mat);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ };
+
+ const f32Red = [1, 0, 0, 1];
+ const f32Green = [0, 1, 0, 1];
+ const f32Gray = [0.5, 0.5, 0.5, 1];
+
+ const u8Red = [255, 0, 0, 255];
+ const u8Green = [ 0, 255, 0, 255];
+ const u8LightRed = [255, 128, 128, 255];
+ const u8LightGreen = [128, 255, 128, 255];
+
+ draw(f32Red, [
+ 2, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ -1, -1, 0, 1,
+ ]);
+ await waitForComposite();
+
+ draw(f32Green, [
+ 1, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ 0, -1, 0, 1,
+ ]);
+ await waitForComposite();
+
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ONE);
+ draw(f32Gray, [
+ 1, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ -0.5, -1, 0, 1,
+ ]);
+ gl.disable(gl.BLEND);
+ await waitForComposite();
+
+ /*
+ expected
+ +-----+-------+---------+--------+
+ | red | ltRed | ltGreen | green |
+ +-----+-------+---------+--------+
+ 0,0
+ */
+
+ const tolerance = 2; // For multisampling resolution differences between GPUs
+ wtu.checkCanvasRect(gl, 0, 0, w / 4, h , u8Red, 'left edge', tolerance)
+ wtu.checkCanvasRect(gl, w * 3 / 4, 0, w / 4, h, u8Green, 'right edge', tolerance);
+ wtu.checkCanvasRect(gl, w / 4, 0, w / 4, h, u8LightRed, 'left of center', tolerance);
+ wtu.checkCanvasRect(gl, w / 2, 0, w / 4, h, u8LightGreen, 'right of center', tolerance);
+
+ finishTest();
+}
+
+var successfullyParsed = true;
+shouldBeTrue("successfullyParsed");
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer.html
new file mode 100644
index 0000000000..7a023996fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attribute-preserve-drawing-buffer.html
@@ -0,0 +1,117 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+.pattern {
+ white-space: nowrap;
+ display: inline-block;
+}
+canvas {
+ width:10px;
+ height:10px;
+}
+.square {
+ display:inline-block;
+ width:10px;
+ height:10px;
+ background-color:red;
+}
+</style>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+function checkResult(ctx1, ctx2, preserve) {
+ var imgData1 = ctx1.getImageData(0,0,1,1);
+ var imgData2 = ctx2.getImageData(0,0,1,1);
+ var correct1 = [255,0,0,255];
+ var correct2 = preserve ? [255,0,0,255] : [0,0,0,255];
+ var ok1 = true;
+ var ok2 = true;
+ for (var p = 0; p < 4; ++p) {
+ if (imgData1.data[p] != correct1[p])
+ ok1 = false;
+ if (imgData2.data[p] != correct2[p])
+ ok2 = false;
+ }
+ if (ok1 && ok2)
+ testPassed('Rendered ok with preserveDrawingBuffer ' + preserve +'.');
+ else
+ testFailed('Did not render ok with preserveDrawingBuffer ' + preserve + '.');
+ if (preserve) {
+ finishTest()
+ } else {
+ runTest(true);
+ }
+}
+
+function runTest(preserve) {
+ var c1 = document.getElementById('c' + (preserve * 3 + 1));
+ var c2 = document.getElementById('c' + (preserve * 3 + 2));
+ var c3 = document.getElementById('c' + (preserve * 3 + 3));
+ var ctx1 = c1.getContext('2d');
+ var ctx2 = c2.getContext('2d');
+ var gl = wtu.create3DContext(c3, { alpha:false, preserveDrawingBuffer:preserve });
+ if (!gl) {
+ testFailed("context does not exist");
+ if (preserve) {
+ finishTest()
+ } else {
+ runTest(true);
+ }
+ return;
+ }
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ctx1.drawImage(c3, 0, 0);
+ wtu.waitForComposite(function() {
+ ctx2.drawImage(c3, 0, 0);
+ checkResult(ctx1, ctx2, preserve);
+ });
+}
+</script>
+</head>
+<body>
+<div class="pattern">
+ <canvas id='c1'></canvas>
+ <canvas id='c2'></canvas>
+ <canvas id='c3'></canvas>
+</div>
+<span>should look like</span>
+<div class="pattern">
+ <div class='square'></div>
+ <div class='square' style='background-color:black'></div>
+ <div class='square'></div>
+</div>
+<hr />
+<div class="pattern">
+ <canvas id='c4'></canvas>
+ <canvas id='c5'></canvas>
+ <canvas id='c6'></canvas>
+</div>
+<span>should look like</span>
+<div class="pattern">
+ <div class='square'></div>
+ <div class='square'></div>
+ <div class='square'></div>
+</div>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that preserveDrawingBuffer attribute is honored.');
+runTest(false);
+var successfullyParsed = true;
+shouldBeTrue("successfullyParsed");
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attributes-alpha-depth-stencil-antialias.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attributes-alpha-depth-stencil-antialias.html
new file mode 100644
index 0000000000..40f46a744a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-attributes-alpha-depth-stencil-antialias.html
@@ -0,0 +1,281 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 pos;
+attribute vec4 colorIn;
+varying vec4 color;
+
+void main()
+{
+ color = colorIn;
+ gl_Position = vec4(pos.xyz, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+"use strict";
+
+// These four declarations need to be global for "shouldBe" to see them
+var wtu = WebGLTestUtils;
+var gl;
+var contextAttribs = null;
+var redChannels = [0, 0, 0];
+var correctColor = null;
+var framebuffer;
+var fbHasColor;
+var fbHasDepth;
+var fbHasStencil;
+var contextVersion = wtu.getDefault3DContextVersion();
+
+function init()
+{
+ description('Verify WebGLContextAttributes are working as specified, including alpha, depth, stencil, antialias, but not premultipliedAlpha');
+
+ runTest();
+}
+
+var vertices = new Float32Array([
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, -1.0, 0.0]);
+
+var colors = new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255]);
+
+
+function getWebGL(canvasWidth, canvasHeight, contextAttribs, clearColor, clearDepth, clearStencil)
+{
+ var canvas = document.createElement("canvas");
+ if (!canvas)
+ return null;
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
+
+ gl = wtu.create3DContext(canvas, contextAttribs, contextVersion);
+ if (!gl)
+ return null;
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["pos", "colorIn"]);
+ if (!program)
+ return null;
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.enable(gl.STENCIL_TEST);
+
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clearDepth(clearDepth);
+ gl.clearStencil(clearStencil);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.canvas.width, gl.canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ fbHasStencil = false;
+ fbHasDepth = false;
+ fbHasColor = gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE;
+ if (fbHasColor) {
+ var depthStencil = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencil);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, gl.canvas.width, gl.canvas.height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencil);
+ fbHasDepth = gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE;
+ if (!fbHasDepth) {
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ } else {
+ fbHasStencil = true;
+ }
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ var colorOffset = vertices.byteLength;
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, colorOffset + colors.byteLength, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
+ gl.bufferSubData(gl.ARRAY_BUFFER, colorOffset, colors);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, colorOffset);
+ gl.enableVertexAttribArray(1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ return gl;
+}
+
+function draw(gl, verticesCount)
+{
+ verticesCount = verticesCount || vertices.length / 3;
+ gl.drawArrays(gl.TRIANGLES, 0, verticesCount);
+}
+
+function checkDraw(hasAlpha, hasStencil, hasDepth, hasAntialias)
+{
+ let red = [255, 0, 0, 255 ];
+ let black = [0, 0, 0, hasAlpha ? 0 : 255 ];
+ debug(`Testing that stencil ${ hasStencil ? 'affects': 'does not affect'} the rendering.`);
+ gl.stencilFunc(gl.NEVER, 1, 1);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ draw(gl);
+ correctColor = hasStencil ? black : red;
+ wtu.checkCanvas(gl, correctColor)
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ wtu.checkCanvas(gl, black);
+ gl.stencilFunc(gl.ALWAYS, 1, 1);
+
+ debug(`Testing that depth ${ hasDepth ? 'affects': 'does not affect'} the rendering.`);
+ gl.depthFunc(gl.NEVER);
+ draw(gl);
+ correctColor = hasDepth ? black : red;
+ wtu.checkCanvas(gl, correctColor);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ wtu.checkCanvas(gl, black);
+ gl.depthFunc(gl.ALWAYS);
+
+ debug(`Testing that rendering is ${hasAntialias ? 'antialiased' : 'aliased'}.`);
+ draw(gl, 3);
+ let N = 2;
+ let buf = new Uint8Array(N * N * 4);
+ gl.readPixels(0, 0, N, N, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ redChannels[0] = buf[4 * (N + 1)]; // (1, 1)
+ redChannels[1] = buf[4 * N * (N - 1)]; // left top
+ redChannels[2] = buf[4 * (N - 1)]; // right bottom
+ shouldBe("redChannels[1]", "255");
+ shouldBe("redChannels[2]", "0");
+ if (hasAntialias) {
+ shouldNotBe("redChannels[0]", "255");
+ shouldNotBe("redChannels[0]", "0");
+ } else {
+ shouldBeTrue("redChannels[0] == 255 || redChannels[0] == 0");
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ wtu.checkCanvas(gl, black);
+
+ debug("Testing that rendering works.");
+ draw(gl);
+ wtu.checkCanvas(gl, red);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ wtu.checkCanvas(gl, black);
+}
+
+function testDefault()
+{
+ debug("Testing default attributes: { stencil:false }");
+ shouldBeNonNull("gl = getWebGL(1, 1, null, [ 0, 0, 0, 0 ], 1, 0)");
+ shouldBeFalse("gl.getContextAttributes().stencil");
+ shouldBe("gl.getParameter(gl.STENCIL_BITS)", "0");
+}
+
+function testAttributesAffectContext(alpha, stencil, depth, antialias)
+{
+ shouldBeNonNull(`gl = getWebGL(2, 2, { depth: ${depth}, stencil: ${stencil}, antialias: ${antialias}, alpha: ${alpha} }, [ 0, 0, 0, 0 ], 1, 0)`);
+ shouldBeNonNull("contextAttribs = gl.getContextAttributes()");
+
+ shouldBeGreaterThanOrEqual("gl.getParameter(gl.RED_BITS)", "8");
+ shouldBeGreaterThanOrEqual("gl.getParameter(gl.GREEN_BITS)", "8");
+ shouldBeGreaterThanOrEqual("gl.getParameter(gl.BLUE_BITS)", "8");
+
+ shouldBe("contextAttribs.alpha", "" + alpha);
+ if (contextVersion < 2) {
+ if (!stencil)
+ shouldBeFalse("contextAttribs.stencil");
+ else
+ stencil = contextAttribs.stencil;
+ if (!depth)
+ shouldBeFalse("contextAttribs.depth");
+ else
+ depth = contextAttribs.depth;
+ if (!antialias)
+ shouldBeFalse("contextAttribs.antialias");
+ else
+ antialias = contextAttribs.antialias;
+ } else {
+ shouldBe("contextAttribs.stencil", "" + stencil);
+ shouldBe("contextAttribs.depth", "" + depth);
+ shouldBe("contextAttribs.antialias", "" + antialias);
+ }
+
+ if (alpha)
+ shouldBeGreaterThanOrEqual("gl.getParameter(gl.ALPHA_BITS)", "8");
+ else
+ shouldBe("gl.getParameter(gl.ALPHA_BITS)", "0");
+ if (stencil)
+ shouldBeGreaterThanOrEqual("gl.getParameter(gl.STENCIL_BITS)", "8");
+ else
+ shouldBe("gl.getParameter(gl.STENCIL_BITS)", "0");
+ if (depth)
+ shouldBeGreaterThanOrEqual("gl.getParameter(gl.DEPTH_BITS)", "16");
+ else
+ shouldBe("gl.getParameter(gl.DEPTH_BITS)", "0");
+
+ var correctColor = alpha ? [0, 0, 0, 0] : [0, 0, 0, 255];
+ wtu.checkCanvas(gl, correctColor);
+
+ debug("Testing default framebuffer.");
+ checkDraw(alpha, stencil, depth, antialias);
+
+ if (fbHasColor) {
+ debug("Testing bound framebuffer object.");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ checkDraw(true, fbHasStencil, fbHasDepth, false);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ }
+}
+
+function runTest()
+{
+ testDefault();
+ let cases = [false, true];
+ for (let alpha of cases) {
+ for (let stencil of cases) {
+ for (let depth of cases) {
+ for (let antialias of cases) {
+ testAttributesAffectContext(alpha, stencil, depth, antialias);
+ }
+ }
+ }
+ }
+ finishTest();
+}
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation-and-destruction.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation-and-destruction.html
new file mode 100644
index 0000000000..72324b5f17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation-and-destruction.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test that contexts are freed and garbage collected reasonably</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/iterable-test.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+
+var test = IterableTest.createContextCreationAndDestructionTest();
+var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 50;
+IterableTest.run(test, iterations);
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation.html
new file mode 100644
index 0000000000..ceeb5b092b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-creation.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test that you can create large numbers of WebGL contexts.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/iterable-test.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+
+var test = IterableTest.createContextCreationTest();
+var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 50;
+IterableTest.run(test, iterations);
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-eviction-with-garbage-collection.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-eviction-with-garbage-collection.html
new file mode 100644
index 0000000000..1898e73520
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-eviction-with-garbage-collection.html
@@ -0,0 +1,57 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test that context eviction and garbage collection do not interfere with each other</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+// See http://crbug.com/374086 for original failing case.
+description("Test that context eviction and garbage collection do not interfere with each other.");
+var wtu = WebGLTestUtils;
+
+var total_iteration = 50;
+var array_count = 10;
+
+var bank = [];
+for (var i = 0; i < array_count; i++)
+ bank[i] = [];
+
+for (var iter = 0; iter < total_iteration; ++iter) {
+ for (var i = 0; i < array_count; i++)
+ bank[i][iter * i] = iter;
+
+ var canvas = document.createElement('canvas');
+ var gl = wtu.create3DContext(canvas);
+ canvas.width = 50;
+ canvas.height = 50;
+ var program = wtu.setupTexturedQuad(gl);
+ shouldBeTrue("program != null");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var pixel = new Uint8Array([0, 255, 0, 255]);
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from iteration " + iter);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-hidden-alpha.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-hidden-alpha.html
new file mode 100644
index 0000000000..ed67fc0093
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-hidden-alpha.html
@@ -0,0 +1,166 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vs' type='x-shader/x-vertex'>
+ attribute vec2 aPosCoord;
+
+ void main(void) {
+ gl_Position = vec4(aPosCoord, 0.0, 1.0);
+ }
+</script>
+
+<script id='fs' type='x-shader/x-fragment'>
+ precision mediump float;
+
+ void main(void) {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+</script>
+<script>
+"use strict";
+
+var posCoords_arr = new Float32Array(2 * 4);
+var posCoords_buff = null;
+function DrawQuad(gl, prog, x0, y0, x1, y1) {
+ gl.useProgram(prog);
+
+ if (!posCoords_buff) {
+ posCoords_buff = gl.createBuffer();
+ }
+ gl.bindBuffer(gl.ARRAY_BUFFER, posCoords_buff);
+ posCoords_arr[0] = x0;
+ posCoords_arr[1] = y0;
+
+ posCoords_arr[2] = x1;
+ posCoords_arr[3] = y0;
+
+ posCoords_arr[4] = x0;
+ posCoords_arr[5] = y1;
+
+ posCoords_arr[6] = x1;
+ posCoords_arr[7] = y1;
+ gl.bufferData(gl.ARRAY_BUFFER, posCoords_arr, gl.STREAM_DRAW);
+
+ gl.enableVertexAttribArray(prog.aPosCoord);
+ gl.vertexAttribPointer(prog.aPosCoord, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+}
+
+function DrawSquare(gl, prog, size) {
+ DrawQuad(gl, prog, -size, -size, size, size);
+}
+
+function Reset(gl) {
+ gl.canvas.width += 1;
+ gl.canvas.width -= 1;
+}
+
+var iColor;
+var pixel;
+var dataURL_pre;
+var dataURL_post;
+
+function Test(gl, prog, shouldFinish) {
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.ZERO, gl.DST_ALPHA);
+
+ iColor = 64;
+ var fColor = iColor / 255.0;
+
+ //////////////////
+
+ debug('clear(R,G,B,0)');
+
+ Reset(gl);
+
+ gl.clearColor(fColor, fColor, fColor, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ dataURL_pre = gl.canvas.toDataURL();
+ //console.log('Before blending: ' + dataURL_pre);
+
+ DrawSquare(gl, prog, 0.7);
+
+ WebGLTestUtils.checkCanvasRect(gl, gl.drawingBufferWidth/2,
+ gl.drawingBufferHeight/2, 1, 1,
+ [iColor, iColor, iColor, 255],
+ 'Should blend as if alpha is 1.0.');
+
+ dataURL_post = gl.canvas.toDataURL();
+ //console.log('After blending: ' + dataURL_post);
+ shouldBe("dataURL_post", "dataURL_pre");
+
+ //////////////////
+
+ debug('mask(R,G,B,0), clear(R,G,B,1)');
+
+ Reset(gl);
+
+ gl.colorMask(true, true, true, false);
+ gl.clearColor(fColor, fColor, fColor, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.colorMask(true, true, true, true);
+
+ dataURL_pre = gl.canvas.toDataURL();
+ //console.log('Before blending: ' + dataURL_pre);
+
+ DrawSquare(gl, prog, 0.7);
+
+ WebGLTestUtils.checkCanvasRect(gl, gl.drawingBufferWidth/2,
+ gl.drawingBufferHeight/2, 1, 1,
+ [iColor, iColor, iColor, 255],
+ 'Should blend as if alpha is 1.0.');
+
+ dataURL_post = gl.canvas.toDataURL();
+ //console.log('After blending: ' + dataURL_post);
+ shouldBe("dataURL_post", "dataURL_pre");
+
+ ////////////////
+
+ WebGLTestUtils.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ if (shouldFinish)
+ finishTest();
+}
+
+var gl;
+function init() {
+ var canvas = document.getElementById('canvas');
+ var attribs = {
+ alpha: false,
+ antialias: false,
+ premultipliedAlpha: false,
+ };
+ gl = canvas.getContext('experimental-webgl', attribs);
+ shouldBeNonNull(gl);
+ shouldBe("gl.getParameter(gl.ALPHA_BITS)", "0");
+
+ var prog = WebGLTestUtils.setupProgram(gl, ['vs', 'fs']);
+ shouldBeNonNull(prog);
+ prog.aPosCoord = gl.getAttribLocation(prog, 'aPosCoord');
+
+ Test(gl, prog, false);
+
+ requestAnimationFrame(function(){ Test(gl, prog, true); });
+}
+
+</script>
+</head>
+<body onload="init()">
+<canvas id='canvas'></canvas>
+<br/>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
new file mode 100644
index 0000000000..6942e3d1ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
@@ -0,0 +1,287 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+var WEBGL_lose_context;
+var new_WEBGL_lose_context;
+var bufferObjects;
+var program;
+var texture;
+var texColor = [255, 10, 20, 255];
+var allowRestore;
+var contextLostEventFired;
+var contextRestoredEventFired;
+var OES_vertex_array_object;
+var old_OES_vertex_array_object;
+var vertexArrayObject;
+var OES_texture_float;
+var newExtension;
+
+function init()
+{
+ enableJSTestPreVerboseLogging();
+ description("Tests behavior under a restored context.");
+
+ shouldGenerateGLError = wtu.shouldGenerateGLError;
+ testLosingContext();
+}
+
+function setupTest()
+{
+ canvas = document.createElement("canvas");
+ canvas.width = 1;
+ canvas.height = 1;
+ gl = wtu.create3DContext(canvas);
+ WEBGL_lose_context = getExtensionAndAddProperty(gl, "WEBGL_lose_context");
+ if (!WEBGL_lose_context) {
+ debug("Could not find WEBGL_lose_context extension");
+ return false;
+ }
+
+ // Try to get a few extensions
+ OES_vertex_array_object = getExtensionAndAddProperty(gl, "OES_vertex_array_object");
+ OES_texture_float = getExtensionAndAddProperty(gl, "OES_texture_float");
+
+ return true;
+}
+
+function getExtensionAndAddProperty(gl, name) {
+ var ext = wtu.getExtensionWithKnownPrefixes(gl, name);
+ if (ext) {
+ ext.webglTestProperty = true;
+ }
+ return ext;
+}
+
+function reGetExtensionAndTestForProperty(gl, name, expectProperty) {
+ newExtension = wtu.getExtensionWithKnownPrefixes(gl, name);
+ // NOTE: while getting a extension after context lost/restored is allowed to fail
+ // for the purpose the conformance tests it is not.
+ //
+ // Hypothetically the user can switch GPUs live. For example on Windows, install 2 GPUs,
+ // then in the control panen enable 1, disable the others and visa versa. Since the GPUs
+ // have different capabilities one or the other may not support a particlar extension.
+ //
+ // But, for the purpose of the conformance tests the context is expected to restore
+ // on the same GPU and therefore the extensions that succeeded previously should
+ // succeed on restore.
+ shouldBeTrue("newExtension != null");
+ if (expectProperty) {
+ shouldBeTrue("newExtension.webglTestProperty === true");
+ } else {
+ shouldBeTrue("newExtension.webglTestProperty === undefined");
+ }
+ return newExtension;
+}
+
+function testLosingContext()
+{
+ if (!setupTest()) {
+ finishTest();
+ return;
+ }
+
+ debug("Test losing a context and inability to restore it.");
+
+ canvas.addEventListener("webglcontextlost", function(e) {
+ testLostContext(e);
+ // restore the context after this event has exited.
+ setTimeout(function() {
+ // we didn't call prevent default so we should not be able to restore the context
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "WEBGL_lose_context.restoreContext()");
+ testLosingAndRestoringContext();
+ }, 0);
+ });
+ canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext);
+ allowRestore = false;
+ contextLostEventFired = false;
+ contextRestoredEventFired = false;
+
+ testOriginalContext();
+ WEBGL_lose_context.loseContext();
+ // The context should be lost immediately.
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ // gl methods should be no-ops
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
+ // but the event should not have been fired.
+ shouldBeFalse("contextLostEventFired");
+}
+
+function testLosingAndRestoringContext()
+{
+ if (!setupTest())
+ finishTest();
+
+ debug("");
+ debug("Test losing and restoring a context.");
+
+ canvas.addEventListener("webglcontextlost", function(e) {
+ testLostContext(e);
+ // restore the context after this event has exited.
+ setTimeout(function() {
+ shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()");
+ // Calling restoreContext() twice should not cause error or crash
+ shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()");
+ // The context should still be lost. It will not get restored until the
+ // webglrestorecontext event is fired.
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ // gl methods should still be no-ops
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
+ }, 0);
+ });
+ canvas.addEventListener("webglcontextrestored", function() {
+ testRestoredContext();
+ finishTest();
+ });
+ allowRestore = true;
+ contextLostEventFired = false;
+ contextRestoredEventFired = false;
+
+ testOriginalContext();
+ WEBGL_lose_context.loseContext();
+ // The context should be lost immediately.
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ // gl methods should be no-ops
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
+ // but the event should not have been fired.
+ shouldBeFalse("contextLostEventFired");
+}
+
+function testRendering()
+{
+ gl.clearColor(0, 0, 0, 255);
+ gl.colorMask(1, 1, 1, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ program = wtu.setupSimpleTextureProgram(gl);
+ bufferObjects = wtu.setupUnitQuad(gl);
+ texture = wtu.createColoredTexture(gl, canvas.width, canvas.height, texColor);
+
+ gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ var compare = texColor.slice(0, 3);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, compare, "shouldBe " + compare);
+
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function testOriginalContext()
+{
+ debug("Test valid context");
+ shouldBeFalse("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ testRendering();
+ debug("");
+}
+
+function testLostContext(e)
+{
+ debug("Test lost context");
+ shouldBeFalse("contextLostEventFired");
+ contextLostEventFired = true;
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ debug("");
+ if (allowRestore)
+ e.preventDefault();
+}
+
+function testShouldNotRestoreContext(e)
+{
+ testFailed("Should not restore the context unless preventDefault is called on the context lost event");
+ debug("");
+}
+
+function testResources(expected)
+{
+ var tests = [
+ "gl.bindTexture(gl.TEXTURE_2D, texture)",
+ "gl.useProgram(program)",
+ "gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[0])",
+ ];
+
+ for (var i = 0; i < tests.length; ++i)
+ shouldGenerateGLError(gl, expected, tests[i]);
+}
+
+function testOESTextureFloat() {
+ if (OES_texture_float) {
+ // Extension must still be lost.
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)");
+ // Try re-enabling extension
+ OES_texture_float = reGetExtensionAndTestForProperty(gl, "OES_texture_float", false);
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)");
+ }
+}
+
+function testOESVertexArrayObject() {
+ if (OES_vertex_array_object) {
+ // Extension must still be lost.
+ shouldBeNull("OES_vertex_array_object.createVertexArrayOES()");
+ // Try re-enabling extension
+
+ old_OES_vertex_array_object = OES_vertex_array_object;
+ OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false);
+ shouldBeTrue("OES_vertex_array_object.createVertexArrayOES() != null");
+ shouldBeTrue("old_OES_vertex_array_object.createVertexArrayOES() == null");
+ }
+}
+
+function testExtensions() {
+ testOESTextureFloat();
+ testOESVertexArrayObject();
+ // Only the WEBGL_lose_context extension should be the same object after context lost.
+ new_WEBGL_lose_context = reGetExtensionAndTestForProperty(gl, "WEBGL_lose_context", true);
+}
+
+function testRestoredContext()
+{
+ debug("Test restored context");
+ shouldBeFalse("contextRestoredEventFired");
+ contextRestoredEventFired = true;
+ shouldBeFalse("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+
+ // Validate that using old resources fails.
+ testResources(gl.INVALID_OPERATION);
+
+ testRendering();
+
+ // Validate new resources created in testRendering().
+ testResources(gl.NO_ERROR);
+
+ testExtensions();
+
+ debug("");
+}
+
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost.html
new file mode 100644
index 0000000000..31d07a94a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost.html
@@ -0,0 +1,379 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+var wtu;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+var extensionName;
+var extension;
+
+var buffer;
+var framebuffer;
+var program;
+var renderbuffer;
+var shader;
+var texture;
+var uniformLocation;
+var arrayBuffer;
+var arrayBufferView
+var image;
+var video;
+var canvas2d;
+var ctx2d;
+var imageData;
+var float32array;
+var int32array;
+var OES_vertex_array_object;
+var vertexArrayObject;
+
+var secondCanvas;
+var secondGL;
+
+function init()
+{
+ wtu = WebGLTestUtils;
+ canvas = document.getElementById("canvas");
+ gl = wtu.create3DContext(canvas);
+ secondCanvas = document.getElementById("canvas2");
+ secondGL = wtu.create3DContext(secondCanvas);
+ shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+ description("Tests behavior under a lost context");
+
+ // call testValidContext() before checking for the extension, because this is where we check
+ // for the isContextLost() method, which we want to do regardless of the extension's presence.
+ testValidContext();
+
+ extensionName = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_lose_context");
+ if (!extensionName) {
+ debug("Could not find WEBGL_lose_context extension");
+ finishTest();
+ return false;
+ }
+ extension = gl.getExtension(extensionName);
+
+ // need an extension that exposes new API methods.
+ OES_vertex_array_object = wtu.getExtensionWithKnownPrefixes(gl, "OES_vertex_array_object");
+
+ canvas.addEventListener("webglcontextlost", testLostContext, false);
+
+ // We need to initialize |uniformLocation| before losing context.
+ // Otherwise gl.getUniform() when context is lost will throw.
+ uniformLocation = gl.getUniformLocation(program, "tex");
+ loseContext();
+}
+
+function loseContext()
+{
+ debug("");
+ debug("Lose context");
+
+ // Note: this will cause the context to be lost, but the
+ // webglcontextlost event listener to be queued.
+ extension.loseContext();
+ debug("");
+}
+
+function testValidContext()
+{
+ debug("Test valid context");
+
+ shouldBeFalse("gl.isContextLost()");
+
+ arrayBuffer = new ArrayBuffer(4);
+ arrayBufferView = new Int8Array(arrayBuffer);
+
+ // Generate resources for testing.
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ program = wtu.setupSimpleTextureProgram(gl);
+ renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ shader = gl.createShader(gl.VERTEX_SHADER);
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+
+ // Test is queries that will later be false
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enable(gl.BLEND)");
+ shouldBeTrue("gl.isBuffer(buffer)");
+ shouldBeTrue("gl.isEnabled(gl.BLEND)");
+ shouldBeTrue("gl.isFramebuffer(framebuffer)");
+ shouldBeTrue("gl.isProgram(program)");
+ shouldBeTrue("gl.isRenderbuffer(renderbuffer)");
+ shouldBeTrue("gl.isShader(shader)");
+ shouldBeTrue("gl.isTexture(texture)");
+
+ if (OES_vertex_array_object) {
+ vertexArrayObject = OES_vertex_array_object.createVertexArrayOES();
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ shouldBeTrue("OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)");
+ }
+}
+
+function testGLNOErrorFunctions(tests) {
+ tests.forEach(function(test) {
+ shouldGenerateGLError(gl, gl.NO_ERROR, test);
+ });
+}
+
+function testFunctionsThatReturnNULL(tests) {
+ tests.forEach(function(test) {
+ shouldBeNull(test);
+ });
+}
+
+function testUploadingLostContextToTexture() {
+ debug("Testing uploading a canvas with a lost WebGL context to a texture");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at beginning");
+ let texture = secondGL.createTexture();
+ secondGL.bindTexture(secondGL.TEXTURE_2D, texture);
+ secondGL.texImage2D(secondGL.TEXTURE_2D, 0, secondGL.RGBA, secondGL.RGBA, secondGL.UNSIGNED_BYTE, canvas);
+ wtu.glErrorShouldBe(secondGL, [secondGL.INVALID_OPERATION, secondGL.NO_ERROR], "Should not crash when uploading canvas with lost WebGL context to a texture");
+}
+
+function testLostContext()
+{
+ debug("Test lost context");
+
+ // Functions with special return values.
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
+ shouldBe("gl.getAttribLocation(program, 'u_modelViewProjMatrix')", "-1");
+ shouldBe("gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)", "0");
+
+ // Attempt resize of lost context should succeed, still lost.
+ gl.canvas.width = gl.canvas.width; // Try to hit any same-size resize path.
+ shouldBeTrue("gl.isContextLost()");
+
+ const newSize = gl.canvas.width + 1;
+ gl.canvas.width = newSize;
+ shouldBe("gl.canvas.width", newSize);
+ shouldBeTrue("gl.isContextLost()");
+
+ // Test the extension itself.
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.loseContext()");
+
+ image = document.createElement("img");
+ video = document.createElement("video");
+ canvas2d = document.createElement("canvas");
+ ctx2d = canvas2d.getContext("2d");
+ imageData = ctx2d.createImageData(1, 1);
+ float32array = new Float32Array(1);
+ int32array = new Int32Array(1);
+
+ // Functions returning void should return immediately.
+ // This is untestable, but we can at least be sure they cause no errors
+ // and the codepaths are exercised.
+ var voidTests = [
+ "gl.activeTexture(gl.TEXTURE0)",
+ "gl.attachShader(program, shader)",
+ "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)",
+ "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)",
+ "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)",
+ "gl.bindTexture(gl.TEXTURE_2D, texture)",
+ "gl.blendColor(1.0, 1.0, 1.0, 1.0)",
+ "gl.blendEquation(gl.FUNC_ADD)",
+ "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)",
+ "gl.blendFunc(gl.ONE, gl.ONE)",
+ "gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE)",
+ "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)",
+ "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)",
+ "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)",
+ "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)",
+ "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)",
+ "gl.clear(gl.COLOR_BUFFER_BIT)",
+ "gl.clearColor(1, 1, 1, 1)",
+ "gl.clearDepth(1)",
+ "gl.clearStencil(0)",
+ "gl.colorMask(1, 1, 1, 1)",
+ "gl.compileShader(shader)",
+ "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)",
+ "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)",
+ "gl.cullFace(gl.FRONT)",
+ "gl.deleteBuffer(buffer)",
+ "gl.deleteFramebuffer(framebuffer)",
+ "gl.deleteProgram(program)",
+ "gl.deleteRenderbuffer(renderbuffer)",
+ "gl.deleteShader(shader)",
+ "gl.deleteTexture(texture)",
+ "gl.depthFunc(gl.NEVER)",
+ "gl.depthMask(0)",
+ "gl.depthRange(0, 1)",
+ "gl.detachShader(program, shader)",
+ "gl.disable(gl.BLEND)",
+ "gl.disableVertexAttribArray(0)",
+ "gl.drawArrays(gl.POINTS, 0, 0)",
+ "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)",
+ "gl.enable(gl.BLEND)",
+ "gl.enableVertexAttribArray(0)",
+ "gl.finish()",
+ "gl.flush()",
+ "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)",
+ "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)",
+ "gl.frontFace(gl.CW)",
+ "gl.generateMipmap(gl.TEXTURE_2D)",
+ "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)",
+ "gl.lineWidth(0)",
+ "gl.linkProgram(program)",
+ "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)",
+ "gl.polygonOffset(0, 0)",
+ "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+ "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)",
+ "gl.sampleCoverage(0, 0)",
+ "gl.scissor(0, 0, 0, 0)",
+ "gl.shaderSource(shader, '')",
+ "gl.stencilFunc(gl.NEVER, 0, 0)",
+ "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)",
+ "gl.stencilMask(0)",
+ "gl.stencilMaskSeparate(gl.FRONT, 0)",
+ "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)",
+ "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)",
+ "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+ "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
+ "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)",
+ "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d)",
+ "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video)",
+ "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
+ "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
+ "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+ "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
+ "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image)",
+ "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d)",
+ "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video)",
+ "gl.uniform1f(uniformLocation, 0)",
+ "gl.uniform1fv(uniformLocation, float32array)",
+ "gl.uniform1fv(uniformLocation, [0])",
+ "gl.uniform1i(uniformLocation, 0)",
+ "gl.uniform1iv(uniformLocation, int32array)",
+ "gl.uniform1iv(uniformLocation, [0])",
+ "gl.uniform2f(uniformLocation, 0, 0)",
+ "gl.uniform2fv(uniformLocation, float32array)",
+ "gl.uniform2fv(uniformLocation, [0, 0])",
+ "gl.uniform2i(uniformLocation, 0, 0)",
+ "gl.uniform2iv(uniformLocation, int32array)",
+ "gl.uniform2iv(uniformLocation, [0, 0])",
+ "gl.uniform3f(uniformLocation, 0, 0, 0)",
+ "gl.uniform3fv(uniformLocation, float32array)",
+ "gl.uniform3fv(uniformLocation, [0, 0, 0])",
+ "gl.uniform3i(uniformLocation, 0, 0, 0)",
+ "gl.uniform3iv(uniformLocation, int32array)",
+ "gl.uniform3iv(uniformLocation, [0, 0, 0])",
+ "gl.uniform4f(uniformLocation, 0, 0, 0, 0)",
+ "gl.uniform4fv(uniformLocation, float32array)",
+ "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])",
+ "gl.uniform4i(uniformLocation, 0, 0, 0, 0)",
+ "gl.uniform4iv(uniformLocation, int32array)",
+ "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])",
+ "gl.uniformMatrix2fv(uniformLocation, false, float32array)",
+ "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])",
+ "gl.uniformMatrix3fv(uniformLocation, false, float32array)",
+ "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])",
+ "gl.uniformMatrix4fv(uniformLocation, false, float32array)",
+ "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])",
+ "gl.useProgram(program)",
+ "gl.validateProgram(program)",
+ "gl.vertexAttrib1f(0, 0)",
+ "gl.vertexAttrib1fv(0, float32array)",
+ "gl.vertexAttrib1fv(0, [0])",
+ "gl.vertexAttrib2f(0, 0, 0)",
+ "gl.vertexAttrib2fv(0, float32array)",
+ "gl.vertexAttrib2fv(0, [0, 0])",
+ "gl.vertexAttrib3f(0, 0, 0, 0)",
+ "gl.vertexAttrib3fv(0, float32array)",
+ "gl.vertexAttrib3fv(0, [0, 0, 0])",
+ "gl.vertexAttrib4f(0, 0, 0, 0, 0)",
+ "gl.vertexAttrib4fv(0, float32array)",
+ "gl.vertexAttrib4fv(0, [0, 0, 0, 0])",
+ "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)",
+ "gl.viewport(0, 0, 0, 0)",
+ ];
+ testGLNOErrorFunctions(voidTests);
+
+ // Functions return nullable values should all return null.
+ var nullTests = [
+ "gl.createBuffer()",
+ "gl.createFramebuffer()",
+ "gl.createProgram()",
+ "gl.createRenderbuffer()",
+ "gl.createShader(gl.GL_VERTEX_SHADER)",
+ "gl.createTexture()",
+ "gl.getActiveAttrib(program, 0)",
+ "gl.getActiveUniform(program, 0)",
+ "gl.getAttachedShaders(program)",
+ "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)",
+ "gl.getContextAttributes()",
+ "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)",
+ "gl.getParameter(gl.CURRENT_PROGRAM)",
+ "gl.getProgramInfoLog(program)",
+ "gl.getProgramParameter(program, gl.LINK_STATUS)",
+ "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)",
+ "gl.getShaderInfoLog(shader)",
+ "gl.getShaderParameter(shader, gl.SHADER_TYPE)",
+ "gl.getShaderSource(shader)",
+ "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)",
+ "gl.getUniform(program, uniformLocation)",
+ "gl.getUniformLocation(program, 'vPosition')",
+ "gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)",
+ "gl.getSupportedExtensions()",
+ "gl.getExtension('" + extensionName + "')",
+ ];
+ testFunctionsThatReturnNULL(nullTests);
+
+ // "Is" queries should all return false.
+ shouldBeFalse("gl.isBuffer(buffer)");
+ shouldBeFalse("gl.isEnabled(gl.BLEND)");
+ shouldBeFalse("gl.isFramebuffer(framebuffer)");
+ shouldBeFalse("gl.isProgram(program)");
+ shouldBeFalse("gl.isRenderbuffer(renderbuffer)");
+ shouldBeFalse("gl.isShader(shader)");
+ shouldBeFalse("gl.isTexture(texture)");
+
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+
+ // test extensions
+ if (OES_vertex_array_object) {
+ testGLNOErrorFunctions(
+ [
+ "OES_vertex_array_object.bindVertexArrayOES(vertexArrayObject)",
+ "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)",
+ "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)",
+ ]);
+ testFunctionsThatReturnNULL(
+ [
+ "OES_vertex_array_object.createVertexArrayOES()",
+ ]);
+ }
+
+ testUploadingLostContextToTexture();
+
+ debug("");
+
+ finishTest();
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas">
+<canvas id="canvas2">
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-no-alpha-fbo-with-alpha.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-no-alpha-fbo-with-alpha.html
new file mode 100644
index 0000000000..81fc80ee5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-no-alpha-fbo-with-alpha.html
@@ -0,0 +1,77 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+
+// This declaration needs to be global for "shouldBe" to see it
+var gl;
+
+function init()
+{
+ description('Verify that a WebGL context with alpha:false still works correctly after handling textures with an alpha channel.');
+
+ runTest();
+}
+
+function getWebGL(contextAttribs)
+{
+ return wtu.create3DContext("c", contextAttribs);
+}
+
+function runTest()
+{
+ var buf = new Uint8Array(1 * 1 * 4);
+ shouldBeNonNull("gl = getWebGL({ alpha: false, antialias: false })");
+
+ // Clear to black. Alpha channel of clearColor() is ignored.
+ gl.clearColor(0.0, 0.0, 0.0, 0.7);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 255],
+ "Alpha channel of clearColor should be ignored");
+
+ wtu.waitForComposite(function() {
+ // Make a new framebuffer and attach a texture with an alpha channel.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ // Clear texture. Note that alpha channel is not 1.0.
+ gl.clearColor(1.0, 0.0, 0.0, 0.5);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 0, 128],
+ "Alpha channel of clearColor should be obeyed for FBO with alpha channel",
+ 1);
+
+ // Bind back buffer and check that its alpha channel is still 1.0.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 255],
+ "Alpha channel of back buffer should still be 255");
+ finishTest();
+ });
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-upon-reload.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-upon-reload.html
new file mode 100644
index 0000000000..fbd3a61741
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-upon-reload.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Context Release Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<iframe id="host" style="width: 256px; height: 256px; border: 0;"></iframe>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test ensures that WebGL contexts are released properly upon page reload");
+
+var wtu = WebGLTestUtils;
+
+var host = document.getElementById("host");
+var testIterations = 25;
+var currentIteration = 0;
+
+function refreshFrame() {
+ if(currentIteration < testIterations) {
+ currentIteration++;
+ debug("");
+ debug("Test " + currentIteration + " of " + testIterations);
+ host.src = "resources/context-release-upon-reload-child.html";
+ } else {
+ finishTest();
+ }
+}
+
+function testContext() {
+ var gl = host.contentWindow.glContext;
+ assertMsg(gl != null, "context was created properly");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ if(gl.canvas.width != gl.drawingBufferWidth ||
+ gl.canvas.height != gl.drawingBufferHeight) {
+ testFailed("Buffer was the wrong size: " +
+ gl.drawingBufferWidth + "x" + gl.drawingBufferHeight);
+ } else {
+ testPassed("Buffer was the correct size: " +
+ gl.drawingBufferWidth + "x" + gl.drawingBufferHeight);
+ refreshFrame();
+ }
+
+ gl = null;
+}
+
+window.addEventListener("message", function(event) {
+ if(event.data == "Ready") {
+ testContext();
+ }
+});
+
+refreshFrame();
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-with-workers.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-with-workers.html
new file mode 100644
index 0000000000..23037fd3c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-release-with-workers.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Context Release Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<iframe id="host" style="width: 256px; height: 256px; border: 0;"></iframe>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test ensures that WebGL contexts are released properly when a worker is used");
+
+var wtu = WebGLTestUtils;
+
+var host = document.getElementById("host");
+var testIterations = 25;
+var currentIteration = 0;
+
+function refreshFrame() {
+ if(currentIteration < testIterations) {
+ currentIteration++;
+ debug("");
+ debug("Test " + currentIteration + " of " + testIterations);
+ host.src = "resources/context-release-child-with-worker.html";
+ } else {
+ finishTest();
+ }
+}
+
+function testContext() {
+ var gl = host.contentWindow.glContext;
+ assertMsg(gl != null, "context was created properly");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ if(gl.canvas.width != gl.drawingBufferWidth ||
+ gl.canvas.height != gl.drawingBufferHeight) {
+ testFailed("Buffer was the wrong size: " +
+ gl.drawingBufferWidth + "x" + gl.drawingBufferHeight);
+ } else {
+ testPassed("Buffer was the correct size: " +
+ gl.drawingBufferWidth + "x" + gl.drawingBufferHeight);
+ refreshFrame();
+ }
+
+ gl = null;
+}
+
+window.addEventListener("message", function(event) {
+ if(event.data == "Ready") {
+ testContext();
+ }
+});
+
+refreshFrame();
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-size-change.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-size-change.html
new file mode 100644
index 0000000000..638d7a7099
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-size-change.html
@@ -0,0 +1,92 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script>
+"use strict";
+
+// These declarations need to be global for "shouldBe" to see them
+var gl;
+var pixel = [0, 0, 0, 1];
+var canvas;
+
+function init()
+{
+ description('Verify that changing the size of an antialiased WebGL context does not cause it to stop working.');
+
+ runTest();
+}
+
+function getWebGL(canvasWidth, canvasHeight, contextAttribs)
+{
+ canvas = document.createElement("canvas");
+ if (!canvas)
+ return null;
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
+
+ gl = WebGLTestUtils.create3DContext(canvas, contextAttribs);
+ if (!gl)
+ return null;
+
+ return gl;
+}
+
+function runTest()
+{
+ shouldBeNonNull("gl = getWebGL(1, 1, { alpha: false, antialias: true })");
+
+ // Clear to black.
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Check that the pixel's R channel is 0.
+ var buf = new Uint8Array(1 * 1 * 4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ pixel[0] = buf[0];
+ shouldBeTrue("pixel[0] == 0");
+
+ // Change the size of the canvas.
+ canvas.width = 3;
+ canvas.height = 3;
+
+ // Clear to black.
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Clear the top-left pixel to white.
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(0, 0, 1, 1);
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Check that the top-left pixel has R channel 255.
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ pixel[0] = buf[0];
+ shouldBeTrue("pixel[0] == 255");
+
+ // Check that the bottom-right pixel has R channel 0.
+ gl.readPixels(2, 2, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ pixel[0] = buf[0];
+ shouldBeTrue("pixel[0] == 0");
+
+ finishTest();
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-type-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-type-test.html
new file mode 100644
index 0000000000..1aa315219a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-type-test.html
@@ -0,0 +1,53 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<canvas id="canvas2d" width="40" height="40"> </canvas>
+<script>
+"use strict";
+description("This test ensures WebGL implementations interact correctly with the canvas tag.");
+
+debug("");
+debug("Canvas.getContext");
+
+assertMsg(window.WebGLRenderingContext,
+ "WebGLRenderingContext should be a member of window");
+assertMsg('WebGLRenderingContext' in window,
+ "WebGLRenderingContext should be 'in' window");
+assertMsg(Object.getPrototypeOf(WebGLRenderingContext.prototype) === Object.prototype,
+ "WebGLRenderingContext should only have Object in it's prototype chain");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("Checking context type");
+ assertMsg(gl instanceof WebGLRenderingContext,
+ "context type should be WebGLRenderingContext");
+}
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/deleted-object-behavior.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/deleted-object-behavior.html
new file mode 100644
index 0000000000..525f399678
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/deleted-object-behavior.html
@@ -0,0 +1,237 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Deleted Object Behavior</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="canvases">
+<canvas id="canvas1">
+</div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Verifies behavior of deleted objects");
+
+const wtu = WebGLTestUtils;
+const canvas1 = document.getElementById("canvas1");
+const sz = 64;
+canvas1.width = sz;
+canvas1.height = sz;
+const gl = wtu.create3DContext("canvas1");
+let tex, rb; // for shouldBe
+
+function testBoundFBOTexture() {
+ debug("Verifies that a texture attached to a bound framebuffer and then deleted is automatically detached");
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sz, sz, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during framebuffer setup");
+ // The WebGL 1.0 spec guarantees that this combination of attachments results
+ // in a complete framebuffer.
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE",
+ "Framebuffer should be complete after setup");
+ debug("Texture should still be bound to the context");
+ shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "tex");
+ // Delete the texture.
+ gl.deleteTexture(tex);
+ debug("Texture should have been unbound from the context");
+ shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+ debug("Framebuffer should report that the texture was detached");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ debug("Framebuffer should be incomplete after texture was deleted");
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ debug("Texture should not report that it's still a texture after deletion");
+ shouldBe("gl.isTexture(tex)", "false");
+ // Framebuffer should not function.
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "Framebuffer should not work after deleting its only attachment");
+ // Default framebuffer shouldn't have been touched.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, [0, 0, 0, 0], "default framebuffer should be transparent black");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after verifying default framebuffer's contents");
+ // Attempt to bind deleted texture should fail.
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "from binding deleted texture");
+ debug("");
+ gl.deleteFramebuffer(fb);
+}
+
+function testUnboundFBOTexture() {
+ debug("Verifies that a texture attached to an unbound framebuffer and then deleted remains usable until detached");
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sz, sz, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during framebuffer setup");
+ // The WebGL 1.0 spec guarantees that this combination of attachments results
+ // in a complete framebuffer.
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE",
+ "Framebuffer should be complete after setup");
+ // Unbind the framebuffer from the context so that deleting the texture
+ // doesn't automatically unbind it from the framebuffer.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ debug("Texture should still be bound to the context");
+ shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "tex");
+ // Delete the texture.
+ gl.deleteTexture(tex);
+ debug("Texture should have been unbound from the context");
+ shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+ // Framebuffer should still be complete.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ debug("Framebuffer should still be complete after texture was deleted");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ debug("Framebuffer should report that the texture is still attached");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
+ debug("Texture should not report that it's still a texture after deletion");
+ shouldBe("gl.isTexture(tex)", "false");
+ // Framebuffer should still function.
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, [0, 255, 0, 255], "framebuffer should be green");
+ // Deleting texture a second time should not unbind it from the framebuffer.
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "deleting an object twice is not an error");
+ debug("Framebuffer should still report that the texture is attached");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
+ // Default framebuffer shouldn't have been touched.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, [0, 0, 0, 0], "default framebuffer should be transparent black");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after verifying framebuffers' contents");
+ // Attempt to bind deleted texture should fail.
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "from binding deleted texture");
+ debug("");
+ gl.deleteFramebuffer(fb);
+}
+
+function testBoundFBORenderbuffer() {
+ debug("Verifies that a renderbuffer attached to a bound framebuffer and then deleted is automatically detached");
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, sz, sz)
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during framebuffer setup");
+ // The WebGL 1.0 spec doesn't guarantee that this framebuffer configuration
+ // will be complete.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Framebuffer with GL_RGBA4 renderbuffer was incomplete; skipping test");
+ return;
+ }
+ debug("Renderbuffer should still be bound to the context");
+ shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rb");
+ // Delete the renderbuffer.
+ gl.deleteRenderbuffer(rb);
+ debug("Renderbuffer should have been unbound from the context");
+ shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
+ debug("Framebuffer should report that the texture was detached");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ debug("Framebuffer should be incomplete after renderbuffer was deleted");
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ debug("Renderbuffer should not report that it's still a renderbuffer after deletion");
+ shouldBe("gl.isRenderbuffer(rb)", "false");
+ // Framebuffer should not function.
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "Framebuffer should not work after deleting its only attachment");
+ // Default framebuffer shouldn't have been touched.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, [0, 0, 0, 0], "default framebuffer should be transparent black");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after verifying framebuffers' contents");
+ // Attempt to bind deleted renderbuffer should fail.
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "from binding deleted renderbuffer");
+ debug("");
+ gl.deleteFramebuffer(fb);
+}
+
+function testUnboundFBORenderbuffer() {
+ debug("Verifies that a renderbuffer attached to an unbound framebuffer and then deleted remains usable until detached");
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, sz, sz)
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during framebuffer setup");
+ // The WebGL 1.0 spec doesn't guarantee that this framebuffer configuration
+ // will be complete.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Framebuffer with GL_RGBA4 renderbuffer was incomplete; skipping test");
+ return;
+ }
+ // Unbind the framebuffer from the context so that deleting the renderbuffer
+ // doesn't automatically unbind it from the framebuffer.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ debug("Renderbuffer should still be bound to the context");
+ shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rb");
+ // Delete the renderbuffer.
+ gl.deleteRenderbuffer(rb);
+ debug("Renderbuffer should have been unbound from the context");
+ shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
+ // Framebuffer should still be complete.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ debug("Framebuffer should still be complete after renderbuffer was deleted");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ debug("Framebuffer should report that the renderbuffer is still attached");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rb");
+ debug("Renderbuffer should not report that it's still a renderbuffer after deletion");
+ shouldBe("gl.isRenderbuffer(rb)", "false");
+ // Framebuffer should still function.
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Use a high tolerance to accommodate low bit depth precision.
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, [0, 255, 0, 255], "framebuffer should be green", 20);
+ // Deleting renderbuffer a second time should not unbind it from the framebuffer.
+ gl.deleteRenderbuffer(rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "deleting an object twice is not an error");
+ debug("Framebuffer should still report that the renderbuffer is attached");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rb");
+ // Default framebuffer shouldn't have been touched.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, [0, 0, 0, 0], "default framebuffer should be transparent black");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after verifying framebuffers' contents");
+ // Attempt to bind deleted renderbuffer should fail.
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "from binding deleted renderbuffer");
+ debug("");
+ gl.deleteFramebuffer(fb);
+}
+
+function runTests() {
+ testBoundFBOTexture();
+ testUnboundFBOTexture();
+ testBoundFBORenderbuffer();
+ testUnboundFBORenderbuffer();
+ finishTest();
+}
+
+requestAnimationFrame(runTests);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/incorrect-context-object-behaviour.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/incorrect-context-object-behaviour.html
new file mode 100644
index 0000000000..30d9b04708
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/incorrect-context-object-behaviour.html
@@ -0,0 +1,165 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests calling WebGL APIs with objects from other contexts");
+
+var wtu = WebGLTestUtils;
+var contextA = wtu.create3DContext();
+var contextB = wtu.create3DContext();
+var bufferA = contextA.createBuffer();
+var bufferB = contextB.createBuffer();
+var frameBufferA = contextA.createFramebuffer();
+var frameBufferB = contextB.createFramebuffer();
+var programA = wtu.loadStandardProgram(contextA);
+var programB = wtu.loadStandardProgram(contextB);
+var renderBufferA = contextA.createRenderbuffer();
+var renderBufferB = contextB.createRenderbuffer();
+var shaderA = wtu.loadStandardVertexShader(contextA);
+var shaderB = wtu.loadStandardVertexShader(contextB);
+var textureA = contextA.createTexture();
+var textureB = contextB.createTexture();
+var locationA = contextA.getUniformLocation(programA, 'u_modelViewProjMatrix');
+var locationB = contextB.getUniformLocation(programB, 'u_modelViewProjMatrix');
+var uniformData = [];
+
+function generateFloat32Array(length) {
+ uniformData = new Float32Array(length);
+}
+
+function generateFloatArray(length) {
+ uniformData = new Array(length);
+ for (var i = 0; i < length; i++) {
+ uniformData[i] = 0.0;
+ }
+}
+
+function generateInt32Array(length) {
+ uniformData = new Int32Array(length);
+}
+
+function generateIntArray(length) {
+ uniformData = new Array(length);
+ for (var i = 0; i < length; i++) {
+ uniformData[i] = 0;
+ }
+}
+
+// Make the bindable objects valid in both contexts first.
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, bufferA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, bufferB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, null)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindFramebuffer(contextB.FRAMEBUFFER, frameBufferB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindFramebuffer(contextB.FRAMEBUFFER, null)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindRenderbuffer(contextB.RENDERBUFFER, renderBufferB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindRenderbuffer(contextB.RENDERBUFFER, null)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTexture(contextA.TEXTURE_2D, textureA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTexture(contextA.TEXTURE_2D, null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTexture(contextB.TEXTURE_2D, textureB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTexture(contextB.TEXTURE_2D, null)");
+
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programA, shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programB, shaderA)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programB, shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindAttribLocation(programB, 0, 'foo')");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindBuffer(contextA.ARRAY_BUFFER, bufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindTexture(contextA.TEXTURE_2D, textureB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.compileShader(shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteBuffer(bufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteFramebuffer(frameBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteProgram(programB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteRenderbuffer(renderBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteShader(shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteShader(shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteTexture(textureB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programA, shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderA)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferRenderbuffer(contextA.FRAMEBUFFER, contextA.DEPTH_ATTACHMENT, contextA.RENDERBUFFER, renderBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferTexture2D(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, contextA.TEXTURE_2D, textureB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveAttrib(programB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniform(programB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getAttachedShaders(programB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getAttribLocation(programB, 'a_vertex')");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getProgramParameter(programB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getProgramInfoLog(programB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderParameter(shaderB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderInfoLog(shaderB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderSource(shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programB, locationA)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programA, locationB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformLocation(programB, 'u_modelViewProjMatrix')");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isBuffer(bufferB)");
+shouldBeFalse("contextA.isBuffer(bufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isFramebuffer(frameBufferB)");
+shouldBeFalse("contextA.isFramebuffer(frameBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isProgram(programB)");
+shouldBeFalse("contextA.isProgram(programB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isRenderbuffer(renderBufferB)");
+shouldBeFalse("contextA.isRenderbuffer(renderBufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isShader(shaderB)");
+shouldBeFalse("contextA.isShader(shaderB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isTexture(textureB)");
+shouldBeFalse("contextA.isTexture(textureB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.linkProgram(programB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.shaderSource(shaderB, 'foo')");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1f(locationB, 0.0)");
+generateFloat32Array(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData)");
+generateFloatArray(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1i(locationB, 0)");
+generateInt32Array(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData)");
+generateIntArray(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2f(locationB, 0.0, 0.0)");
+generateFloat32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData)");
+generateFloatArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2i(locationB, 0, 0)");
+generateInt32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData)");
+generateIntArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3f(locationB, 0.0, 0.0, 0.0)");
+generateFloat32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData)");
+generateFloatArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3i(locationB, 0, 0, 0)");
+generateInt32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData)");
+generateIntArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4f(locationB, 0.0, 0.0, 0.0, 0.0)");
+generateFloat32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData)");
+generateFloatArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4i(locationB, 0, 0, 0, 0)");
+generateInt32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData)");
+generateIntArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData)");
+generateFloat32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData)");
+generateFloatArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData)");
+generateFloat32Array(9); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData)");
+generateFloatArray(9); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData)");
+generateFloat32Array(16); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData)");
+generateFloatArray(16); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData)");
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/methods.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/methods.html
new file mode 100644
index 0000000000..d1e47f32a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/methods.html
@@ -0,0 +1,178 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Methods Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/context-methods.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<script>
+"use strict";
+description("This test ensures that the WebGL context has all the methods in the specification.");
+
+const methods = [
+ "getContextAttributes",
+ "activeTexture",
+ "attachShader",
+ "bindAttribLocation",
+ "bindBuffer",
+ "bindFramebuffer",
+ "bindRenderbuffer",
+ "bindTexture",
+ "blendColor",
+ "blendEquation",
+ "blendEquationSeparate",
+ "blendFunc",
+ "blendFuncSeparate",
+ "bufferData",
+ "bufferSubData",
+ "checkFramebufferStatus",
+ "clear",
+ "clearColor",
+ "clearDepth",
+ "clearStencil",
+ "colorMask",
+ "compileShader",
+ "compressedTexImage2D",
+ "compressedTexSubImage2D",
+ "copyTexImage2D",
+ "copyTexSubImage2D",
+ "createBuffer",
+ "createFramebuffer",
+ "createProgram",
+ "createRenderbuffer",
+ "createShader",
+ "createTexture",
+ "cullFace",
+ "deleteBuffer",
+ "deleteFramebuffer",
+ "deleteProgram",
+ "deleteRenderbuffer",
+ "deleteShader",
+ "deleteTexture",
+ "depthFunc",
+ "depthMask",
+ "depthRange",
+ "detachShader",
+ "disable",
+ "disableVertexAttribArray",
+ "drawArrays",
+ "drawElements",
+ "enable",
+ "enableVertexAttribArray",
+ "finish",
+ "flush",
+ "framebufferRenderbuffer",
+ "framebufferTexture2D",
+ "frontFace",
+ "generateMipmap",
+ "getActiveAttrib",
+ "getActiveUniform",
+ "getAttachedShaders",
+ "getAttribLocation",
+ "getParameter",
+ "getBufferParameter",
+ "getError",
+ "getExtension",
+ "getFramebufferAttachmentParameter",
+ "getProgramParameter",
+ "getProgramInfoLog",
+ "getRenderbufferParameter",
+ "getShaderParameter",
+ "getShaderInfoLog",
+ "getShaderPrecisionFormat",
+ "getShaderSource",
+ "getSupportedExtensions",
+ "getTexParameter",
+ "getUniform",
+ "getUniformLocation",
+ "getVertexAttrib",
+ "getVertexAttribOffset",
+ "hint",
+ "isBuffer",
+ "isContextLost",
+ "isEnabled",
+ "isFramebuffer",
+ "isProgram",
+ "isRenderbuffer",
+ "isShader",
+ "isTexture",
+ "lineWidth",
+ "linkProgram",
+ "pixelStorei",
+ "polygonOffset",
+ "readPixels",
+ "renderbufferStorage",
+ "sampleCoverage",
+ "scissor",
+ "shaderSource",
+ "stencilFunc",
+ "stencilFuncSeparate",
+ "stencilMask",
+ "stencilMaskSeparate",
+ "stencilOp",
+ "stencilOpSeparate",
+ "texImage2D",
+ "texParameterf",
+ "texParameteri",
+ "texSubImage2D",
+ "uniform1f",
+ "uniform1fv",
+ "uniform1i",
+ "uniform1iv",
+ "uniform2f",
+ "uniform2fv",
+ "uniform2i",
+ "uniform2iv",
+ "uniform3f",
+ "uniform3fv",
+ "uniform3i",
+ "uniform3iv",
+ "uniform4f",
+ "uniform4fv",
+ "uniform4i",
+ "uniform4iv",
+ "uniformMatrix2fv",
+ "uniformMatrix3fv",
+ "uniformMatrix4fv",
+ "useProgram",
+ "validateProgram",
+ "vertexAttrib1f",
+ "vertexAttrib1fv",
+ "vertexAttrib2f",
+ "vertexAttrib2fv",
+ "vertexAttrib3f",
+ "vertexAttrib3fv",
+ "vertexAttrib4f",
+ "vertexAttrib4fv",
+ "vertexAttribPointer",
+ "viewport"
+];
+
+debug("");
+debug("Canvas.getContext");
+
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("canvas");
+const gl = wtu.create3DContext(canvas);
+
+testContextMethods(gl, methods);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/premultiplyalpha-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/premultiplyalpha-test.html
new file mode 100644
index 0000000000..ecbe251611
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/premultiplyalpha-test.html
@@ -0,0 +1,251 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test the WebGL premultipliedAlpha context creation flag.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div><div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+// wtu.create3DContext(...) will set antialias to false by default
+// if the antialias property is not set to true explicitly.
+// To cover the antialias case, it needs to set antialias to true
+// explicitly.
+var tests = [
+ // If premultipliedAlpha is true and antialias is false then
+ // [texture] [canvas] [dataURL]
+ // 32, 64, 128, 128 -> 64, 128, 255, 128 -> 64, 128, 255, 128
+ { creationAttributes: {},
+ sentColor: [32, 64, 128, 128],
+ expectedColor: [64, 128, 255, 128],
+ errorRange: 2,
+ imageFormat: "image/png"
+ },
+ // If premultipliedAlpha is true and antialias is true then
+ // [texture] [canvas] [dataURL]
+ // 32, 64, 128, 128 -> 64, 128, 255, 128 -> 64, 128, 255, 128
+ { creationAttributes: {antialias: true},
+ sentColor: [32, 64, 128, 128],
+ expectedColor: [64, 128, 255, 128],
+ errorRange: 2,
+ imageFormat: "image/png"
+ },
+ // If premultipliedAlpha is true and antialias is false then
+ // [texture] [canvas] [texture]
+ // 32, 64, 128, 128 -> 64, 128, 255, 128 -> 64, 128, 255, 128
+ { creationAttributes: {},
+ sentColor: [32, 64, 128, 128],
+ expectedColor: [64, 128, 255, 128],
+ errorRange: 2,
+ },
+ // If premultipliedAlpha is true and antialias is true then
+ // [texture] [canvas] [texture]
+ // 32, 64, 128, 128 -> 64, 128, 255, 128 -> 64, 128, 255, 128
+ { creationAttributes: {antialias: true},
+ sentColor: [32, 64, 128, 128],
+ expectedColor: [64, 128, 255, 128],
+ errorRange: 2,
+ },
+ // If premultipliedAlpha is false and antialias is false then
+ // [texture] [canvas] [dataURL]
+ // 255, 192, 128, 1 -> 255, 192, 128, 1 -> 255, 192, 128, 1
+ { creationAttributes: {premultipliedAlpha: false},
+ sentColor: [255, 192, 128, 1],
+ expectedColor: [255, 192, 128, 1],
+ errorRange: 0,
+ imageFormat: "image/png"
+ },
+ // If premultipliedAlpha is false and antialias is true then
+ // [texture] [canvas] [dataURL]
+ // 255, 192, 128, 1 -> 255, 192, 128, 1 -> 255, 192, 128, 1
+ { creationAttributes: {premultipliedAlpha: false, antialias: true},
+ sentColor: [255, 192, 128, 1],
+ expectedColor: [255, 192, 128, 1],
+ errorRange: 0,
+ imageFormat: "image/png"
+ },
+ // If premultipliedAlpha is false and antialias is false then
+ // [texture] [canvas] [texture]
+ // 255, 192, 128, 1 -> 255, 192, 128, 1 -> 255, 192, 128, 1
+ { creationAttributes: {premultipliedAlpha: false},
+ sentColor: [255, 192, 128, 1],
+ expectedColor: [255, 192, 128, 1],
+ errorRange: 0,
+ },
+ // If premultipliedAlpha is false and antialias is true then
+ // [texture] [canvas] [texture]
+ // 255, 192, 128, 1 -> 255, 192, 128, 1 -> 255, 192, 128, 1
+ { creationAttributes: {premultipliedAlpha: false, antialias: true},
+ sentColor: [255, 192, 128, 1],
+ expectedColor: [255, 192, 128, 1],
+ errorRange: 0,
+ },
+ // If premultipliedAlpha is false and antialias is false then
+ // [texture] [canvas] [dataURL]
+ // 255, 255, 255, 128 -> 255, 255, 255, 128 -> 128, 128, 128, 255
+ { creationAttributes: {premultipliedAlpha: false},
+ sentColor: [255, 255, 255, 128],
+ expectedColor: [128, 128, 128, 255],
+ errorRange: 2,
+ imageFormat: "image/jpeg"
+ },
+ // If premultipliedAlpha is false and antialias is true then
+ // [texture] [canvas] [dataURL]
+ // 255, 255, 255, 128 -> 255, 255, 255, 128 -> 128, 128, 128, 255
+ { creationAttributes: {premultipliedAlpha: false, antialias: true},
+ sentColor: [255, 255, 255, 128],
+ expectedColor: [128, 128, 128, 255],
+ errorRange: 2,
+ imageFormat: "image/jpeg"
+ },
+ // If premultipliedAlpha is true and antialias is false then
+ // [texture] [canvas] [dataURL]
+ // 128, 128, 128, 128 -> 255, 255, 255, 128 -> 128, 128, 128, 255
+ { creationAttributes: {},
+ sentColor: [128, 128, 128, 128],
+ expectedColor: [128, 128, 128, 255],
+ errorRange: 2,
+ imageFormat: "image/jpeg"
+ },
+ // If premultipliedAlpha is true and antialias is true then
+ // [texture] [canvas] [dataURL]
+ // 128, 128, 128, 128 -> 255, 255, 255, 128 -> 128, 128, 128, 255
+ { creationAttributes: {antialias: true},
+ sentColor: [128, 128, 128, 128],
+ expectedColor: [128, 128, 128, 255],
+ errorRange: 2,
+ imageFormat: "image/jpeg"
+ }
+];
+
+var g_count = 0;
+var gl;
+var canvas;
+var premultipliedAlpha;
+
+enableJSTestPreVerboseLogging();
+description("Test the WebGL premultipliedAlpha context creation flag.");
+doNextTest();
+function doNextTest() {
+ if (g_count < tests.length) {
+ var test = tests[g_count++];
+ canvas = document.createElement("canvas");
+ // Need to preserve drawing buffer to load it in a callback
+ test.creationAttributes.preserveDrawingBuffer = true;
+ gl = wtu.create3DContext(canvas, test.creationAttributes);
+ var premultipliedAlpha = test.creationAttributes.premultipliedAlpha != false;
+ var antialias = test.creationAttributes.antialias == true;
+ debug("")
+ debug("testing: premultipliedAlpha: " + premultipliedAlpha
+ + ", antialias: " + antialias
+ + ", imageFormat: " + test.imageFormat);
+
+ if (!gl) {
+ testFailed("context does not exist");
+ doNextTest();
+ return;
+ }
+
+ shouldBe('gl.getContextAttributes().premultipliedAlpha', premultipliedAlpha.toString());
+ shouldBeTrue('gl.getContextAttributes().preserveDrawingBuffer');
+
+ wtu.log(gl.getContextAttributes());
+ var program = wtu.setupTexturedQuad(gl);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+ var tex = gl.createTexture();
+ wtu.fillTexture(gl, tex, 2, 2, test.sentColor, 0);
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+ 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);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from drawing.");
+
+ var loadTexture = function() {
+ debug("loadTexture called");
+ var pngTex = gl.createTexture();
+ // not needed as it's the default
+ // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ gl.bindTexture(gl.TEXTURE_2D, pngTex);
+ if (test.imageFormat) {
+ // create texture from image
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this);
+ } else {
+ // create texture from canvas
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+ }
+ 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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from creating copy.");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from 2nd drawing.");
+ wtu.checkCanvas(
+ gl, test.expectedColor,
+ "should draw with " + test.expectedColor, test.errorRange);
+
+ doNextTest();
+ }
+
+ var loadTextureError = function() {
+ testFailed("Creating image from canvas failed. Image src: " + this.src);
+ finishTest();
+ }
+
+ var shrinkString = function(string) {
+ if (string.length < 63) {
+ return string;
+ }
+ return string.substr(0, 30) + "..." + string.substr(string.length - 30);
+ }
+
+ if (test.imageFormat) {
+ // Load canvas into string using toDataURL
+ debug("Calling canvas.toDataURL('" + test.imageFormat + "')");
+ var imageUrl = canvas.toDataURL(test.imageFormat);
+ debug("imageUrl = '" + shrinkString(imageUrl) + "'");
+ if (test.imageFormat != "image/png" &&
+ (imageUrl.indexOf("data:image/png,") == 0 ||
+ imageUrl.indexOf("data:image/png;") == 0)) {
+ debug("Image format " + test.imageFormat + " not supported; skipping");
+ setTimeout(doNextTest, 0);
+ } else {
+ // Load string into the texture
+ debug("Waiting for image.onload");
+ var input = wtu.makeImage(imageUrl, loadTexture, loadTextureError);
+ }
+ } else {
+ // Load canvas into the texture asynchronously (to prevent unbounded stack consumption)
+ debug("Waiting for setTimeout");
+ setTimeout(loadTexture, 0);
+ }
+ } else {
+ var successfullyParsed = true;
+ finishTest();
+ }
+}
+
+</script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-child-with-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-child-with-worker.html
new file mode 100644
index 0000000000..66408c0ef2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-child-with-worker.html
@@ -0,0 +1,55 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html style="margin: 0; padding: 0;">
+<head>
+<meta charset="utf-8">
+<title>Simple WebGL context with Worker</title>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body style="margin: 0; padding: 0; overflow: hidden;">
+<canvas id="c" width="1680" height="1050" style="width: 256px; height: 256px;"> <!-- scaled to fit page better -->
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var myWorker = new Worker("context-release-worker.js");
+
+var gl = wtu.create3DContext("c", { antialias: false });
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.75,0, -0.75,-0.75,0, 0.75,-0.75,0 ]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+gl.clearColor(0.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+if (parent) {
+ window.glContext = gl;
+ parent.postMessage("Ready", "*");
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-upon-reload-child.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-upon-reload-child.html
new file mode 100644
index 0000000000..9f06c41d4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-upon-reload-child.html
@@ -0,0 +1,54 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html style="margin: 0; padding: 0;">
+<head>
+<meta charset="utf-8">
+<title>Simple WebGL context</title>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body style="margin: 0; padding: 0; overflow: hidden;">
+<canvas id="c" width="1680" height="1050" style="width: 256px; height: 256px;"> <!-- scaled to fit page better -->
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext("c", { antialias: false });
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.75,0, -0.75,-0.75,0, 0.75,-0.75,0 ]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+gl.clearColor(0.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+if (parent) {
+ window.glContext = gl;
+ parent.postMessage("Ready", "*");
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-worker.js
new file mode 100644
index 0000000000..3680117c25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/resources/context-release-worker.js
@@ -0,0 +1,4 @@
+// Simple worker used to provoke WebGL context release bugs on Chrome
+
+postMessage("Hello World");
+close(); \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/user-defined-properties-on-context.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/user-defined-properties-on-context.html
new file mode 100644
index 0000000000..4029087c1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/user-defined-properties-on-context.html
@@ -0,0 +1,49 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL User-Defined Properties Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body onload="initialize()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<script>
+"use strict";
+description("This test ensures that if user-defined properties are set on the WebGL context object, that they don't disappear after garbage collection.");
+
+var gl2 = null;
+
+function initialize() {
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("canvas");
+ var gl1 = wtu.create3DContext(canvas);
+ if (!gl1) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+ } else {
+ testPassed("WebGL context exists");
+ gl1.myProperty = 2;
+ wtu.requestAnimFrame(runTest);
+ }
+}
+
+function runTest() {
+ webglHarnessCollectGarbage();
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("canvas");
+ gl2 = wtu.create3DContext(canvas);
+ shouldBe('gl2.myProperty', '2');
+ finishTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/context/zero-sized-canvas.html b/dom/canvas/test/webgl-conf/checkout/conformance/context/zero-sized-canvas.html
new file mode 100644
index 0000000000..13e1338865
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/zero-sized-canvas.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+// Global declarations so that "shouldBe" can eval with them:
+let gl;
+
+(function() {
+ description('Check that zero-sized canvases work with WebGL.');
+
+ testZero();
+
+ finishTest();
+})();
+
+function testZero() {
+ const canvas = document.createElement('canvas');
+ canvas.width = 0;
+ canvas.height = 0;
+ gl = WebGLTestUtils.create3DContext(canvas);
+
+ expectTrue(gl, `Context creation with ${canvas.width}x${canvas.height} canvas should succeed.`);
+ shouldBe('gl.drawingBufferWidth', '1');
+ shouldBe('gl.drawingBufferHeight', '1');
+ shouldBeFalse('gl.isContextLost()');
+
+ const version = gl.getParameter(gl.VERSION);
+ expectTrue(version && version.length, `getParameter() should return something.`);
+
+ debug('canvas.width = 2');
+ canvas.width = 2;
+ shouldBe('gl.drawingBufferWidth', '2');
+ shouldBeFalse('gl.isContextLost()');
+
+ debug('canvas.width = 0');
+ canvas.width = 0;
+ shouldBe('gl.drawingBufferWidth', '1');
+ shouldBeFalse('gl.isContextLost()');
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/00_test_list.txt
new file mode 100644
index 0000000000..9a72b67ef0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/00_test_list.txt
@@ -0,0 +1,46 @@
+--min-version 1.0.3 --max-version 1.9.9 angle-instanced-arrays.html
+--min-version 1.0.3 --max-version 1.9.9 angle-instanced-arrays-out-of-bounds.html
+--min-version 1.0.3 --max-version 1.9.9 ext-blend-minmax.html
+--min-version 1.0.4 ext-color-buffer-half-float.html
+--min-version 1.0.4 ext-float-blend.html
+--min-version 1.0.4 ext-texture-compression-bptc.html
+--min-version 1.0.4 ext-texture-compression-rgtc.html
+--min-version 1.0.4 ext-disjoint-timer-query.html
+--min-version 1.0.3 --max-version 1.9.9 ext-frag-depth.html
+--min-version 1.0.3 --max-version 1.9.9 ext-shader-texture-lod.html
+--min-version 1.0.3 --max-version 1.9.9 ext-sRGB.html
+--min-version 1.0.2 ext-texture-filter-anisotropic.html
+--min-version 1.0.2 get-extension.html
+--min-version 1.0.4 khr-parallel-shader-compile.html
+--max-version 1.9.9 oes-standard-derivatives.html
+--max-version 1.9.9 oes-texture-float-with-canvas.html
+--max-version 1.9.9 oes-texture-float-with-image-data.html
+--max-version 1.9.9 oes-texture-float-with-image.html
+--max-version 1.9.9 oes-texture-float-with-video.html
+--max-version 1.9.9 oes-texture-float.html
+--max-version 1.9.9 oes-vertex-array-object.html
+--min-version 1.0.3 --max-version 1.9.9 oes-vertex-array-object-bufferData.html
+--min-version 1.0.3 --max-version 1.9.9 oes-texture-half-float.html
+--min-version 1.0.3 oes-texture-float-linear.html
+--min-version 1.0.3 --max-version 1.9.9 oes-texture-half-float-linear.html
+--min-version 1.0.3 --max-version 1.9.9 oes-texture-half-float-with-canvas.html
+--min-version 1.0.3 --max-version 1.9.9 oes-texture-half-float-with-image-data.html
+--min-version 1.0.3 --max-version 1.9.9 oes-texture-half-float-with-image.html
+--min-version 1.0.3 --max-version 1.9.9 oes-texture-half-float-with-video.html
+--min-version 1.0.2 --max-version 1.9.9 oes-element-index-uint.html
+--min-version 1.0.4 --max-version 1.9.9 oes-fbo-render-mipmap.html
+webgl-debug-renderer-info.html
+webgl-debug-shaders.html
+--min-version 1.0.4 webgl-compressed-texture-astc.html
+--min-version 1.0.4 webgl-compressed-texture-etc.html
+--min-version 1.0.4 webgl-compressed-texture-etc1.html
+--min-version 1.0.3 webgl-compressed-texture-pvrtc.html
+--min-version 1.0.4 s3tc-and-rgtc.html
+--min-version 1.0.4 webgl-compressed-texture-s3tc-srgb.html
+--min-version 1.0.3 webgl-compressed-texture-size-limit.html
+--min-version 1.0.2 --max-version 1.9.9 webgl-depth-texture.html
+--min-version 1.0.3 --max-version 1.9.9 webgl-draw-buffers.html
+--min-version 1.0.4 --max-version 1.9.9 webgl-draw-buffers-broadcast-return.html
+--min-version 1.0.4 --max-version 1.9.9 webgl-draw-buffers-framebuffer-unsupported.html
+--min-version 1.0.4 --max-version 1.9.9 webgl-draw-buffers-max-draw-buffers.html
+--min-version 1.0.4 webgl-multi-draw.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays-out-of-bounds.html
new file mode 100644
index 0000000000..64a063854e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays-out-of-bounds.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/out-of-bounds-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test of drawArraysInstancedANGLE and drawElementsInstancedANGLE with out-of-bounds parameters");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext();
+var ext = wtu.getExtensionWithKnownPrefixes(gl, "ANGLE_instanced_arrays");
+if (!ext) {
+ testPassed("No ANGLE_instanced_arrays support -- this is legal");
+} else {
+ testPassed("Successfully enabled ANGLE_instanced_arrays extension");
+ debug("");
+ debug("Test with 1 instance without instanced attributes");
+ debug("");
+ OutOfBoundsTest.runDrawArraysTest("ext.drawArraysInstancedANGLE(gl.TRIANGLES, $(offset), $(count), 1)", gl, wtu, ext);
+ debug("");
+ OutOfBoundsTest.runDrawElementsTest("ext.drawElementsInstancedANGLE(gl.TRIANGLES, $(count), $(type), $(offset), 1)", gl, wtu, ext);
+ debug("");
+ debug("Test with 2 instances without instanced attributes");
+ debug("");
+ OutOfBoundsTest.runDrawArraysTest("ext.drawArraysInstancedANGLE(gl.TRIANGLES, $(offset), $(count), 2)", gl, wtu, ext);
+ debug("");
+ OutOfBoundsTest.runDrawElementsTest("ext.drawElementsInstancedANGLE(gl.TRIANGLES, $(count), $(type), $(offset), 2)", gl, wtu, ext);
+ debug("");
+ OutOfBoundsTest.runDrawArraysInstancedTest("ext.drawArraysInstancedANGLE(gl.TRIANGLES, $(offset), $(count), $(primcount))", gl, wtu, ext);
+ debug("");
+ OutOfBoundsTest.runDrawElementsInstancedTest("ext.drawElementsInstancedANGLE(gl.TRIANGLES, $(count), $(type), $(offset), $(primcount))", gl, wtu, ext);
+ debug("");
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays.html
new file mode 100644
index 0000000000..f96c732bb2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/angle-instanced-arrays.html
@@ -0,0 +1,723 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ANGLE_instanced_arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compositing-test.js"></script>
+<script src="../../js/tests/invalid-vertex-attrib-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing instanced draws -->
+<script id="outputVertexShader" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+attribute vec2 aOffset;
+attribute vec4 aColor;
+varying vec4 vColor;
+void main() {
+ vColor = aColor;
+ gl_Position = aPosition + vec4(aOffset, 0.0, 0.0);
+}
+</script>
+
+<script id="outputFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 vColor;
+void main() {
+ gl_FragColor = vColor;
+}
+</script>
+
+<script id="drawArraysTestVertexShader" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+attribute vec3 aInstancePos;
+uniform vec3 uOffset;
+void main() {
+ gl_Position = vec4(aPosition.xyz + aInstancePos.xyz + uOffset, 1.0);
+}
+</script>
+
+<script id="drawArraysTestFragmentShader" type="x-shader/x-fragment">
+void main() {
+ gl_FragColor = vec4(1.0, 0, 0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the ANGLE_instanced_arrays extension, if it is available.");
+
+debug("");
+
+const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var vaoext = null;
+
+var positionLoc = 0;
+var offsetLoc = 2;
+var colorLoc = 3;
+var program;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+} else {
+ testPassed("WebGL context exists");
+
+ runDivisorTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "ANGLE_instanced_arrays");
+ if (!ext) {
+ testPassed("No ANGLE_instanced_arrays support -- this is legal");
+
+ runSupportedTest(false);
+ finishTest();
+ } else {
+ testPassed("Successfully enabled ANGLE_instanced_arrays extension");
+
+ (async function() {
+ runSupportedTest(true);
+
+ runDivisorTestEnabled();
+ runUniqueObjectTest();
+
+ setupCanvas();
+ runOutputTests();
+ runDrawArraysWithOffsetTest();
+ runVAOInstancingInteractionTest();
+ await runANGLECorruptionTest();
+ await runInvalidAttribTests(gl);
+ await runCompositingTests();
+ finishTest();
+ }());
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("ANGLE_instanced_arrays") >= 0) {
+ if (extensionEnabled) {
+ testPassed("ANGLE_instanced_arrays listed as supported and getExtension succeeded");
+ } else {
+ testFailed("ANGLE_instanced_arrays listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("ANGLE_instanced_arrays not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("ANGLE_instanced_arrays not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runDivisorTestDisabled() {
+ debug("Testing VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE with extension disabled");
+
+ var VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
+
+ gl.getVertexAttrib(0, VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE should not be queryable if extension is disabled");
+}
+
+function runDivisorTestEnabled() {
+ debug("Testing VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE with extension enabled");
+
+ shouldBe("ext.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE", "0x88FE");
+
+ var max_vertex_attribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+
+ for (var i = 0; i < max_vertex_attribs; ++i) {
+ var queried_value = gl.getVertexAttrib(i, ext.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
+ if(queried_value == 0){
+ testPassed("Vertex attribute " + i + " must has a default divisor of 0");
+ }
+ else{
+ testFailed("Default divisor of vertex attribute " + i + " should be: 0, returned value was: " + queried_value);
+ }
+ }
+
+ ext.vertexAttribDivisorANGLE(max_vertex_attribs, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "vertexAttribDivisorANGLE index set greater than or equal to MAX_VERTEX_ATTRIBS should be an invalid value");
+
+ ext.vertexAttribDivisorANGLE(max_vertex_attribs-1, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "vertexAttribDivisorANGLE index set less than MAX_VERTEX_ATTRIBS should succeed");
+
+ var queried_value = gl.getVertexAttrib(max_vertex_attribs-1, ext.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
+ if(queried_value == 2){
+ testPassed("Set value of VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE matches expecation");
+ }
+ else{
+ testFailed("Set value of VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE should be: 2, returned value was: " + queried_value);
+ }
+
+ // Reset vertex attrib divisors so they cannot affect following subtests.
+ ext.vertexAttribDivisorANGLE(max_vertex_attribs-1, 0);
+}
+
+function setupCanvas() {
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.clearColor(0, 0, 0, 0);
+
+ program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['aPosition', 'aOffset', 'aColor'], [positionLoc, offsetLoc, colorLoc]);
+ ext = gl.getExtension("ANGLE_instanced_arrays");
+}
+
+function runOutputTests() {
+ var instanceCount = 4;
+
+ debug("Testing various draws for valid built-in function behavior");
+
+ var offsets = new Float32Array([
+ -1.0, 1.0,
+ 1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0,
+ ]);
+ var offsetBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(offsetLoc);
+ gl.vertexAttribPointer(offsetLoc, 2, gl.FLOAT, false, 0, 0);
+ ext.vertexAttribDivisorANGLE(offsetLoc, 1);
+
+ var colors = new Float32Array([
+ 1.0, 0.0, 0.0, 1.0, // Red
+ 0.0, 1.0, 0.0, 1.0, // Green
+ 0.0, 0.0, 1.0, 1.0, // Blue
+ 1.0, 1.0, 0.0, 1.0, // Yellow
+ // extra data when colorLoc divisor is set back to 0
+ 1.0, 1.0, 0.0, 1.0, // Yellow
+ 1.0, 1.0, 0.0, 1.0, // Yellow
+ ]);
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+ ext.vertexAttribDivisorANGLE(colorLoc, 1);
+
+ wtu.setupUnitQuad(gl, 0);
+
+ // Draw 1: Regular drawArrays
+ debug("");
+ debug("Testing drawArrays with non-zero divisor");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "vertex attrib divisor should affect regular drawArrays when the extension is enabled");
+ wtu.checkCanvasRect(gl, 0, canvas.height/2, canvas.width/2, canvas.height/2, [255, 0, 0, 255]);
+
+ // Draw 2: Draw Non-indexed instances
+ debug("");
+ debug("Testing drawArraysInstancedANGLE");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Test drawArraysInstancedANGLE error conditions
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.checkCanvasRect(gl, 0, canvas.height/2, canvas.width/2, canvas.height/2, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, canvas.height/2, canvas.width/2, canvas.height/2, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width/2, canvas.height/2, [0, 0, 255, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, 0, canvas.width/2, canvas.height/2, [255, 255, 0, 255]);
+
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, -1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawArraysInstancedANGLE cannot have a primcount less than 0");
+
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, -1, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawArraysInstancedANGLE cannot have a count less than 0");
+
+ ext.vertexAttribDivisorANGLE(positionLoc, 1);
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "There must be at least one vertex attribute with a divisor of zero when calling drawArraysInstancedANGLE");
+ ext.vertexAttribDivisorANGLE(positionLoc, 0);
+
+ ext.drawArraysInstancedANGLE(gl.POINTS, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstancedANGLE with POINTS should succeed");
+ ext.drawArraysInstancedANGLE(gl.LINES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstancedANGLE with LINES should succeed");
+ ext.drawArraysInstancedANGLE(gl.LINE_LIST, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstancedANGLE with LINE_LIST should return succeed");
+ ext.drawArraysInstancedANGLE(gl.TRIANGLE_LIST, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstancedANGLE with TRIANGLE_LIST should succeed");
+
+ ext.drawArraysInstancedANGLE(desktopGL['QUAD_STRIP'], 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstancedANGLE with QUAD_STRIP should return INVALID_ENUM");
+ ext.drawArraysInstancedANGLE(desktopGL['QUADS'], 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstancedANGLE with QUADS should return INVALID_ENUM");
+ ext.drawArraysInstancedANGLE(desktopGL['POLYGON'], 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstancedANGLE with POLYGON should return INVALID_ENUM");
+
+ debug("");
+ debug("Testing drawArraysInstancedANGLE with param 'first' > 0");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.setupQuad(gl, {
+ positionLocation: 0,
+ scale: 0.5
+ });
+ var offsetsHalf = new Float32Array([
+ -0.5, 0.5,
+ 0.5, 0.5,
+ -0.5, -0.5,
+ 0.5, -0.5
+ ]);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsetsHalf, gl.STATIC_DRAW);
+
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 3, 3, instanceCount);
+ var w = Math.floor(0.25*canvas.width),
+ h = Math.floor(0.25*canvas.height);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [0, 0, 255, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
+
+ debug("");
+ debug("Testing drawArraysInstancedANGLE with attributes 'divisor' reset to 0");
+ debug("Correct rendering output: 4 yellow triangles");
+ debug("Possible incorrect rendering output: missing triangles, or triangles with different color at each vertex");
+ ext.vertexAttribDivisorANGLE(colorLoc, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 3, 3, instanceCount);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [255, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
+ ext.vertexAttribDivisorANGLE(colorLoc, 1);
+
+ wtu.setupUnitQuad(gl, 0);
+ wtu.setupIndexedQuad(gl, 1, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+
+ // Draw 3: Regular drawElements
+ debug("");
+ debug("Testing drawElements with non-zero divisor");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Point to another location in the buffer so that the draw would overflow without the divisor
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 48);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "vertex attrib divisor should affect regular drawElements when the extension is enabled");
+ wtu.checkCanvasRect(gl, 0, canvas.height/2, canvas.width/2, canvas.height/2, [255, 255, 0, 255]);
+ // Restore the vertex attrib pointer
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+
+ // Draw 4: Draw indexed instances
+ debug("");
+ debug("Testing drawElementsInstancedANGLE");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.checkCanvasRect(gl, 0, canvas.height/2, canvas.width/2, canvas.height/2, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, canvas.height/2, canvas.width/2, canvas.height/2, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width/2, canvas.height/2, [0, 0, 255, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, 0, canvas.width/2, canvas.height/2, [255, 255, 0, 255]);
+
+ // Test drawElementsInstancedANGLE error conditions
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, -1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawElementsInstancedANGLE cannot have a primcount less than 0");
+
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, -1, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawElementsInstancedANGLE cannot have a count less than 0");
+
+ ext.vertexAttribDivisorANGLE(positionLoc, 1);
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "There must be at least one vertex attribute with a divisor of zero when calling drawElementsInstancedANGLE");
+ ext.vertexAttribDivisorANGLE(positionLoc, 0);
+
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstancedANGLE with UNSIGNED_BYTE should succeed");
+
+ ext.drawElementsInstancedANGLE(gl.POINTS, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstancedANGLE with POINTS should succeed");
+ ext.drawElementsInstancedANGLE(gl.LINES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstancedANGLE with LINES should succeed");
+ ext.drawElementsInstancedANGLE(gl.LINE_LIST, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstancedANGLE with LINE_LIST should return succeed");
+ ext.drawElementsInstancedANGLE(gl.TRIANGLE_LIST, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstancedANGLE with TRIANGLE_LIST should succeed");
+
+ ext.drawElementsInstancedANGLE(desktopGL['QUAD_STRIP'], 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawElementsInstancedANGLE with QUAD_STRIP should return INVALID_ENUM");
+ ext.drawElementsInstancedANGLE(desktopGL['QUADS'], 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawElementsInstancedANGLE with QUADS should return INVALID_ENUM");
+ ext.drawElementsInstancedANGLE(desktopGL['POLYGON'], 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawElementsInstancedANGLE with POLYGON should return INVALID_ENUM");
+
+ // Reset vertex attrib divisors so they cannot affect following subtests.
+ ext.vertexAttribDivisorANGLE(colorLoc, 0);
+ ext.vertexAttribDivisorANGLE(offsetLoc, 0);
+}
+
+function runDrawArraysTest(program, first, count, instanceCount, offset)
+{
+ // Get the attribute and uniform locations
+ var positionLoc = gl.getAttribLocation(program, "aPosition");
+ var instancePosLoc = gl.getAttribLocation(program, "aInstancePos");
+ var uniformLoc = gl.getUniformLocation(program, "uOffset");
+
+ // Load the vertex positions
+ var positions = new Float32Array([
+ -1, -1,
+ -1, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, -1,
+ -1, -1,
+
+ 1, -1,
+ 1, 0,
+ 0, 0,
+
+ 0, 0,
+ 0, -1,
+ 1, -1,
+ ]);
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ // Load the instance positions
+ var instancePositions = new Float32Array([
+ 0, 0,
+ 1, 0
+ ]);
+ var instancePositionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, instancePositionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, instancePositions, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(instancePosLoc);
+ gl.vertexAttribPointer(instancePosLoc, 2, gl.FLOAT, false, 0, 0);
+
+ // Enable instancing
+ ext.vertexAttribDivisorANGLE(instancePosLoc, 1);
+
+ // Offset
+ gl.uniform3fv(uniformLoc, offset);
+
+ // Do the instanced draw
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, first, count, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstancedANGLE should succeed");
+
+ // Reset vertex attrib divisors so they cannot affect following subtests.
+ ext.vertexAttribDivisorANGLE(instancePosLoc, 0);
+}
+
+function runDrawArraysWithOffsetTest()
+{
+ debug("");
+ debug("Testing that the 'first' parameter to drawArraysInstancedANGLE is only an offset into the non-instanced vertex attributes.");
+ // See: http://crbug.com/457269 and http://crbug.com/447140
+
+ var drawArraysProgram = wtu.setupProgram(gl, ["drawArraysTestVertexShader", "drawArraysTestFragmentShader"]);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ runDrawArraysTest(drawArraysProgram, 0, 6, 2, [0, 0, 0]);
+
+ runDrawArraysTest(drawArraysProgram, 6, 6, 2, [-1, 1, 0]);
+
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ ext = null;
+ gl.getExtension("ANGLE_instanced_arrays").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("ANGLE_instanced_arrays").myProperty', '2');
+}
+
+function runVAOInstancingInteractionTest()
+{
+ debug("")
+ debug("Testing that ANGLE_instanced_arrays interacts correctly with OES_vertex_array_object if present");
+ // See: https://github.com/KhronosGroup/WebGL/issues/1228
+
+ // Query the extension and store globally so shouldBe can access it
+ vaoext = gl.getExtension("OES_vertex_array_object");
+ if (!vaoext) {
+ testPassed("No OES_vertex_array_object support -- this is legal");
+ return;
+ }
+
+ testPassed("Successfully enabled OES_vertex_array_object extension");
+
+ gl.useProgram(program);
+
+ var positions = new Float32Array([
+ 0.0, 1.0, // Left quad
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 0.0, 1.0,
+ -1.0, -1.0,
+ 0.0, -1.0,
+
+ 1.0, 1.0, // Right quad
+ 0.0, 1.0,
+ 0.0, -1.0,
+ 1.0, 1.0,
+ 0.0, -1.0,
+ 1.0, -1.0
+ ]);
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+
+ var colors = new Float32Array([
+ 1.0, 0.0, 0.0, 1.0, // Red
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 0.0, 0.0, 1.0,
+
+ 0.0, 0.0, 1.0, 1.0, // Blue
+ 0.0, 0.0, 1.0, 1.0,
+ 0.0, 0.0, 1.0, 1.0,
+ 0.0, 0.0, 1.0, 1.0,
+ 0.0, 0.0, 1.0, 1.0,
+ 0.0, 0.0, 1.0, 1.0,
+ ]);
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+
+ // Reset the divisor of the default VAO to 0
+ ext.vertexAttribDivisorANGLE(colorLoc, 0);
+
+ // Set up VAO with an attrib divisor
+ var vao1 = vaoext.createVertexArrayOES();
+ vaoext.bindVertexArrayOES(vao1);
+ {
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+ ext.vertexAttribDivisorANGLE(colorLoc, 1);
+
+ gl.vertexAttrib2fv(offsetLoc, [0.0, 0.0]);
+ }
+ vaoext.bindVertexArrayOES(null);
+
+ // Set up VAO with no attrib divisor
+ var vao2 = vaoext.createVertexArrayOES();
+ vaoext.bindVertexArrayOES(vao2);
+ {
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+ // Note that no divisor is set here, which implies that it's 0
+
+ gl.vertexAttrib2fv(offsetLoc, [0.0, 0.0]);
+ }
+ vaoext.bindVertexArrayOES(null);
+
+ debug("");
+ debug("Ensure that Vertex Array Objects retain attrib divisors");
+
+ vaoext.bindVertexArrayOES(vao1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 12);
+ // If the divisor is properly managed by the VAO a single red quad will be drawn
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "entire canvas should be red");
+
+ vaoext.bindVertexArrayOES(vao2);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 12);
+ // If the divisor is properly managed by the VAO a red and blue quad will be drawn.
+ wtu.checkCanvasRects(gl, [
+ wtu.makeCheckRect(0, 0, canvas.width * 0.5, canvas.height, [255, 0, 0, 255], "left half of canvas should be red", 1),
+ wtu.makeCheckRect(canvas.width * 0.5, 0, canvas.width * 0.5, canvas.height, [0, 0, 255, 255], "right half of canvas should be blue", 1)
+ ]);
+
+ vaoext.bindVertexArrayOES(null);
+}
+
+async function runANGLECorruptionTest()
+{
+ debug("")
+ debug("Testing to ensure that rendering isn't corrupt due to an ANGLE bug");
+ // See: https://code.google.com/p/angleproject/issues/detail?id=467
+
+ setupCanvas();
+
+ var tolerance = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
+ var instanceCount = 10; // Must be higher than 6
+
+ var offsets = new Float32Array([
+ 0.0, 0.0,
+ 0.2, 0.0,
+ 0.4, 0.0,
+ 0.6, 0.0,
+ 0.8, 0.0,
+ 1.0, 0.0,
+ 1.2, 0.0,
+ 1.4, 0.0,
+ 1.6, 0.0,
+ 1.8, 0.0,
+ ]);
+ var offsetBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets.byteLength * 2, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, offsets);
+ gl.enableVertexAttribArray(offsetLoc);
+ gl.vertexAttribPointer(offsetLoc, 2, gl.FLOAT, false, 0, 0);
+ ext.vertexAttribDivisorANGLE(offsetLoc, 1);
+
+ var colors = new Float32Array([
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 1.0, 1.0,
+ 0.0, 0.0, 1.0, 1.0,
+ 1.0, 0.0, 1.0, 1.0,
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 1.0, 1.0,
+ ]);
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors.byteLength * 2, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, colors);
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+ ext.vertexAttribDivisorANGLE(colorLoc, 1);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.setupUnitQuad(gl, 0);
+
+ const totalIterations = 10;
+ for (let iteration = 0; iteration < totalIterations; ++iteration)
+ {
+ // Update the instanced data buffers outside the accessed range.
+ // This, plus rendering more instances than vertices, triggers the bug.
+ var nullData = new Float32Array(offsets.length);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferSubData(gl.ARRAY_BUFFER, offsets.byteLength, nullData);
+
+ nullData = new Float32Array(colors.length);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferSubData(gl.ARRAY_BUFFER, colors.byteLength, nullData);
+
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, instanceCount);
+
+ // Make sure each color was drawn correctly
+ var i;
+ var passed = true;
+ for (i = 0; i < instanceCount; ++i) {
+ var w = canvas.width / instanceCount;
+ var x = w * i;
+ var color = [colors[(i*4)] * 255, colors[(i*4)+1] * 255, colors[(i*4)+2] * 255, 255]
+
+ wtu.checkCanvasRectColor(
+ gl, x, 0, w, canvas.height, color, tolerance,
+ function() {},
+ function() {
+ passed = false;
+ }, debug);
+ }
+
+ if (passed) {
+ testPassed("Passed test " + iteration + " of " + totalIterations);
+ } else {
+ testFailed("Failed test " + iteration + " of " + totalIterations);
+ break;
+ }
+ await wait();
+ }
+ ext.vertexAttribDivisorANGLE(offsetLoc, 0);
+ ext.vertexAttribDivisorANGLE(colorLoc, 0);
+}
+
+async function runDrawTests(testFn) {
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ function drawArraysInstancedANGLE(gl) {
+ const ext = gl.getExtension('ANGLE_instanced_arrays');
+ if (!ext) {
+ return true;
+ }
+
+ ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, 1);
+ }
+
+ function drawElementsInstancedANGLE(gl) {
+ const ext = gl.getExtension('ANGLE_instanced_arrays');
+ if (!ext) {
+ return true;
+ }
+
+ ext.drawElementsInstancedANGLE(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1);
+ }
+
+ await testFn(drawArrays); // sanity check
+ await testFn(drawElements); // sanity check
+
+ await testFn(drawArraysInstancedANGLE);
+ await testFn(drawElementsInstancedANGLE);
+}
+
+async function runCompositingTests() {
+ const compositingTestFn = createCompositingTestFn({
+ webglVersion: 1,
+ shadersFn(gl) {
+ const vs = `\
+ attribute vec4 position;
+ void main() {
+ gl_Position = position;
+ }
+ `;
+ const fs = `\
+ precision mediump float;
+ void main() {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+ `;
+ return [vs, fs];
+ },
+ });
+ await runDrawTests(compositingTestFn);
+}
+
+async function runInvalidAttribTests(gl) {
+ const invalidAttribTestFn = createInvalidAttribTestFn(gl);
+ await runDrawTests(invalidAttribTestFn);
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-blend-minmax.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-blend-minmax.html
new file mode 100644
index 0000000000..445dcb92d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-blend-minmax.html
@@ -0,0 +1,225 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_blend_minmax Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders to test output -->
+<script id="outputVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+<script id="outputFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 uColor;
+void main() {
+ gl_FragColor = uColor;
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_blend_minmax extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+
+// Use the constant directly when we don't have the extension
+var MIN_EXT = 0x8007;
+var MAX_EXT = 0x8008;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runBlendTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_blend_minmax");
+ if (!ext) {
+ testPassed("No EXT_blend_minmax support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ debug("");
+ testPassed("Successfully enabled EXT_blend_minmax extension");
+
+ runSupportedTest(true);
+
+ runBlendTestEnabled();
+ runOutputTests();
+ runUniqueObjectTest();
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("EXT_blend_minmax") >= 0) {
+ if (extensionEnabled) {
+ testPassed("EXT_blend_minmax listed as supported and getExtension succeeded");
+ } else {
+ testFailed("EXT_blend_minmax listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("EXT_blend_minmax not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("EXT_blend_minmax not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runBlendTestDisabled() {
+ debug("");
+ debug("Testing blending enums with extension disabled");
+
+ // Set the blend equation to a known-good enum first
+ gl.blendEquation(gl.FUNC_ADD);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquation(MIN_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquation(MAX_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(MIN_EXT, gl.FUNC_ADD)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(gl.FUNC_ADD, MIN_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(MAX_EXT, gl.FUNC_ADD)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(gl.FUNC_ADD, MAX_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");
+}
+
+function runBlendTestEnabled() {
+ debug("");
+ debug("Testing blending enums with extension enabled");
+
+ shouldBe("ext.MIN_EXT", "0x8007");
+ shouldBe("ext.MAX_EXT", "0x8008");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquation(ext.MIN_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "ext.MIN_EXT");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquation(ext.MAX_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "ext.MAX_EXT");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(ext.MIN_EXT, gl.FUNC_ADD)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "ext.MIN_EXT");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, ext.MIN_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "ext.MIN_EXT");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(ext.MAX_EXT, gl.FUNC_ADD)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "ext.MAX_EXT");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, ext.MAX_EXT)");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");
+ shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "ext.MAX_EXT");
+}
+
+function runOutputTests() {
+ var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
+
+ debug("");
+ debug("Testing various draws for valid blending behavior");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ONE);
+
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition'], [0]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+ var colorUniform = gl.getUniformLocation(program, "uColor");
+
+
+ // Draw 1
+ gl.blendEquation(ext.MIN_EXT);
+
+ gl.clearColor(0.2, 0.4, 0.6, 0.8);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
+ wtu.drawUnitQuad(gl);
+
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [51, 102, 102, 51]);
+
+ // Draw 2:
+ gl.blendEquation(ext.MAX_EXT);
+
+ gl.clearColor(0.2, 0.4, 0.6, 0.8);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
+ wtu.drawUnitQuad(gl);
+
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [204, 153, 153, 204]);
+
+ // Draw 3
+ gl.blendEquationSeparate(ext.MIN_EXT, ext.MAX_EXT);
+
+ gl.clearColor(0.2, 0.4, 0.6, 0.8);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
+ wtu.drawUnitQuad(gl);
+
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [51, 102, 102, 204]);
+
+ // Draw 4
+ gl.blendEquationSeparate(ext.MAX_EXT, ext.MIN_EXT);
+
+ gl.clearColor(0.2, 0.4, 0.6, 0.8);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
+ wtu.drawUnitQuad(gl);
+
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [204, 153, 153, 51]);
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ ext = null;
+ gl.getExtension("EXT_blend_minmax").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("EXT_blend_minmax").myProperty', '2');
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-color-buffer-half-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-color-buffer-half-float.html
new file mode 100644
index 0000000000..752fe98e45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-color-buffer-half-float.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_color_buffer_half_float Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head> 
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+var version = 1;
+</script>
+<script src="../../js/tests/ext-color-buffer-half-float.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-disjoint-timer-query.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-disjoint-timer-query.html
new file mode 100644
index 0000000000..1fc29cc445
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-disjoint-timer-query.html
@@ -0,0 +1,312 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_disjoint_timer_query Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_disjoint_timer_query extension, if it is available.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var query = null;
+var query2 = null;
+var elapsed_query = null;
+var timestamp_query1 = null;
+var timestamp_query2 = null;
+var availability_retry = 500;
+var timestamp_counter_bits = 0;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+} else {
+ testPassed("WebGL context exists");
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_disjoint_timer_query");
+ if (!ext) {
+ testPassed("No EXT_disjoint_timer_query support -- this is legal");
+ finishTest();
+ } else {
+ if (wtu.getDefault3DContextVersion() > 1) {
+ testFailed("EXT_disjoint_timer_query must not be advertised on WebGL 2.0 contexts");
+ finishTest();
+ } else {
+ runSanityTests();
+
+ // Clear disjoint value.
+ gl.getParameter(ext.GPU_DISJOINT_EXT);
+
+ runElapsedTimeTest();
+ timestamp_counter_bits = ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT);
+ if (timestamp_counter_bits > 0) {
+ runTimeStampTest();
+ }
+ verifyQueryResultsNotAvailable();
+
+ window.requestAnimationFrame(checkQueryResults);
+ }
+ }
+}
+
+function runSanityTests() {
+ debug("");
+ debug("Testing timer query expectations");
+
+ shouldBe("ext.QUERY_COUNTER_BITS_EXT", "0x8864");
+ shouldBe("ext.CURRENT_QUERY_EXT", "0x8865");
+ shouldBe("ext.QUERY_RESULT_EXT", "0x8866");
+ shouldBe("ext.QUERY_RESULT_AVAILABLE_EXT", "0x8867");
+ shouldBe("ext.TIME_ELAPSED_EXT", "0x88BF");
+ shouldBe("ext.TIMESTAMP_EXT", "0x8E28");
+ shouldBe("ext.GPU_DISJOINT_EXT", "0x8FBB");
+
+ shouldBe("ext.isQueryEXT(null)", "false");
+
+ shouldBeTrue("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT) === null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeTrue("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ shouldBeTrue("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.CURRENT_QUERY_EXT) === null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // Certain drivers set timestamp counter bits to 0 as they don't support timestamps
+ shouldBeTrue("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30 || " +
+ "ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) === 0");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing time elapsed query lifecycle");
+ query = ext.createQueryEXT();
+ shouldBe("ext.isQueryEXT(query)", "false");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query creation must succeed.");
+ shouldThrow("ext.beginQueryEXT(ext.TIMESTAMP_EXT, null)");
+ ext.beginQueryEXT(ext.TIMESTAMP_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Beginning a timestamp query should fail.");
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
+ shouldBe("ext.isQueryEXT(query)", "true");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Beginning an inactive time elapsed query should succeed.");
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to begin an active query should fail.");
+ ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability of an active query should fail.");
+ ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result of an active query should fail.");
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
+ ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Ending an active time elapsed query should succeed.");
+ shouldThrow("ext.getQueryObjectEXT(null, ext.QUERY_RESULT_AVAILABLE_EXT)");
+ ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Fetching query result availability after query end should succeed.");
+ ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to end an inactive query should fail.");
+ ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should not be able to use time elapsed query to store a timestamp.");
+ ext.deleteQueryEXT(query);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query deletion must succeed.");
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning a deleted query must fail.");
+ ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability after query deletion should fail.");
+ shouldBe("ext.isQueryEXT(query)", "false");
+
+ debug("");
+ debug("Testing timestamp counter");
+ query = ext.createQueryEXT();
+ shouldThrow("ext.queryCounterEXT(null, ext.TIMESTAMP_EXT)");
+ ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp counter queries should work.");
+ ext.deleteQueryEXT(query);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Performing parameter sanity checks");
+ gl.getParameter(ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter timestamp calls should work.");
+ gl.getParameter(ext.GPU_DISJOINT_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter disjoint calls should work.");
+
+ debug("");
+ debug("Testing current query conditions");
+ query = ext.createQueryEXT();
+ query2 = ext.createQueryEXT();
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing failed begin query should not change the current query.");
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning an elapsed query without ending should fail.");
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing beginning a timestamp query is invalid and should not change the elapsed query.");
+ ext.beginQueryEXT(ext.TIMESTAMP_EXT, query2)
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing timestamp queries end immediately so are never current.");
+ ext.queryCounterEXT(query2, ext.TIMESTAMP_EXT);
+ shouldBe("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.CURRENT_QUERY_EXT)", "null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing ending the query should clear the current query.");
+ ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing beginning a elapsed query using a timestamp query should fail and not affect current query.")
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching query targets should fail.");
+ shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ ext.deleteQueryEXT(query);
+ ext.deleteQueryEXT(query2);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at end of sanity tests");
+}
+
+function runElapsedTimeTest() {
+ debug("");
+ debug("Testing elapsed time query");
+
+ elapsed_query = ext.createQueryEXT();
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, elapsed_query);
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Time elapsed query should have no errors");
+}
+
+function runTimeStampTest() {
+ debug("");
+ debug("Testing timestamp query");
+
+ timestamp_query1 = ext.createQueryEXT();
+ timestamp_query2 = ext.createQueryEXT();
+ ext.queryCounterEXT(timestamp_query1, ext.TIMESTAMP_EXT);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.queryCounterEXT(timestamp_query2, ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp queries should have no errors");
+}
+
+function verifyQueryResultsNotAvailable() {
+ debug("");
+ debug("Verifying queries' results don't become available too early");
+
+ // Verify as best as possible that the implementation doesn't
+ // allow a query's result to become available the same frame, by
+ // spin-looping for some time and ensuring that none of the
+ // queries' results become available.
+ var startTime = Date.now();
+ while (Date.now() - startTime < 2000) {
+ gl.finish();
+ if (ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT)) {
+ testFailed("One of the queries' results became available too early");
+ return;
+ }
+ if (timestamp_counter_bits > 0) {
+ if (ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_AVAILABLE_EXT) ||
+ ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT)) {
+ testFailed("One of the queries' results became available too early");
+ return;
+ }
+ }
+ }
+
+ testPassed("Queries' results didn't become available in a spin loop");
+}
+
+function checkQueryResults() {
+ if (availability_retry > 0) {
+ // Make a reasonable attempt to wait for the queries' results to become available.
+ if (!ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT) ||
+ (timestamp_counter_bits > 0 && !ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT))) {
+ var error = gl.getError();
+ if (error != gl.NO_ERROR) {
+ testFailed("getQueryObjectEXT should have no errors: " + wtu.glEnumToString(gl, error));
+ debug("");
+ finishTest();
+ return;
+ }
+ availability_retry--;
+ window.requestAnimationFrame(checkQueryResults);
+ return;
+ }
+ }
+
+ debug("");
+ debug("Testing query results");
+
+ // Make sure queries are available.
+ shouldBe("ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
+ if (timestamp_counter_bits > 0) {
+ shouldBe("ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
+ shouldBe("ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
+ }
+
+ var disjoint_value = gl.getParameter(ext.GPU_DISJOINT_EXT);
+ if (disjoint_value) {
+ // Cannot validate results make sense, but this is okay.
+ testPassed("Disjoint triggered.");
+ } else {
+ var elapsed_result = ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_EXT);
+ if (timestamp_counter_bits > 0) {
+ var timestamp_result1 = ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_EXT);
+ var timestamp_result2 = ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_EXT);
+ }
+ // Do some basic validity checking of the elapsed time query. There's no way it should
+ // take more than about half a second for a no-op query.
+ var halfSecondInNanos = 0.5 * 1000 * 1000 * 1000;
+ if (elapsed_result < 0 || elapsed_result > halfSecondInNanos) {
+ testFailed("Time elapsed query returned invalid data: " + elapsed_result);
+ } else {
+ testPassed("Time elapsed query results were valid.");
+ }
+
+ if (timestamp_counter_bits > 0) {
+ if (timestamp_result1 <= 0 ||
+ timestamp_result2 <= 0 ||
+ timestamp_result2 <= timestamp_result1) {
+ testFailed("Timestamp queries returned invalid data: timestamp_result1 = " +
+ timestamp_result1 + ", timestamp_result2 = " + timestamp_result2);
+ } else {
+ testPassed("Timestamp query results were valid.");
+ }
+ }
+ }
+
+ debug("");
+ finishTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-float-blend.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-float-blend.html
new file mode 100644
index 0000000000..a825d78bef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-float-blend.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_float_blend Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ext-float-blend.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_float_blend extension, if it is available.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+
+function extFloatBlendTests(version, config) {
+ debug("");
+ debug("Testing float32 blending without EXT_float_blend");
+ testExtFloatBlend(config.internalFormat);
+ testExtFloatBlendMRT(version, config.drawBuffers);
+ testExtFloatBlendNonFloat32Type(version, config.oesTextureHalfFloat);
+
+ const floatBlend = gl.getExtension("EXT_float_blend");
+ if (!floatBlend) {
+ testPassed("EXT_float_blend is allowed to be missing.");
+ return;
+ }
+
+ debug("");
+ debug("Testing that float32 blending is allowed with EXT_float_blend");
+ testExtFloatBlend(config.internalFormat);
+ testExtFloatBlendMRT(version, config.drawBuffers);
+ testExtFloatBlendNonFloat32Type(version, config.oesTextureHalfFloat);
+}
+
+(function(){
+ if (wtu.getDefault3DContextVersion() < 2) {
+ const oesTextureFloat = gl.getExtension("OES_texture_float");
+ if (!oesTextureFloat) {
+ testPassed("OES_texture_float is allowed to be missing.");
+ return;
+ }
+
+ const colorBufferFloat = gl.getExtension("WEBGL_color_buffer_float");
+ if (!colorBufferFloat) {
+ testPassed("WEBGL_color_buffer_float is allowed to be missing.");
+ return;
+ }
+
+ const drawBuffers = gl.getExtension("WEBGL_draw_buffers");
+ if (!drawBuffers) {
+ debug("WEBGL_draw_buffers is allowed to be missing. MRT tests will be skipped.");
+ }
+
+ const oesTextureHalfFloat = gl.getExtension("OES_texture_half_float");
+ const extColorBufferHalfFloat = gl.getExtension("EXT_color_buffer_half_float");
+ const testHalfFloat = !(!oesTextureHalfFloat || !extColorBufferHalfFloat);
+ if (!testHalfFloat) {
+ debug("OES_texture_half_float or EXT_color_buffer_half_float is allowed to be missing. NonFloat32Type tests will be skipped.");
+ }
+
+ const internalFormat = gl.RGBA;
+ extFloatBlendTests(1, {
+ internalFormat, drawBuffers, oesTextureHalfFloat
+ });
+ } else {
+ const colorBufferFloat = gl.getExtension("EXT_color_buffer_float");
+ if (!colorBufferFloat) {
+ testPassed("EXT_color_buffer_float is allowed to be missing.");
+ return;
+ }
+
+ const internalFormat = gl.RGBA32F;
+ extFloatBlendTests(2, {
+ internalFormat
+ });
+ }
+})();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-frag-depth.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-frag-depth.html
new file mode 100644
index 0000000000..ee2a6df0cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-frag-depth.html
@@ -0,0 +1,289 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_frag_depth Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing fragment depth writing -->
+
+<!-- Shader omitting the required #extension pragma -->
+<script id="missingPragmaFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepthEXT = 1.0;
+}
+</script>
+
+<!-- Shader to test macro definition -->
+<script id="macroFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+#ifdef GL_EXT_frag_depth
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+#else
+ // Error expected
+ #error no GL_EXT_frag_depth;
+#endif
+}
+</script>
+
+<!-- Shader with required #extension pragma -->
+<script id="testFragmentShader" type="x-shader/x-fragment">
+#extension GL_EXT_frag_depth : enable
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepthEXT = 1.0;
+}
+</script>
+<!-- Shaders to link with test fragment shaders -->
+<script id="goodVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+<!-- Shaders to test output -->
+<script id="outputVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+<script id="outputFragmentShader" type="x-shader/x-fragment">
+#extension GL_EXT_frag_depth : enable
+precision mediump float;
+uniform float uDepth;
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepthEXT = uDepth;
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_frag_depth extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+
+// Run all tests once.
+runAllTests();
+
+// Run all tests against with a new context to test for any cache issues.
+debug("");
+debug("Testing new context to catch cache errors");
+gl = wtu.create3DContext();
+ext = null;
+runAllTests();
+
+function runAllTests() {
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ } else {
+ testPassed("WebGL context exists");
+
+ runShaderTests(false);
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_frag_depth");
+ if (!ext) {
+ testPassed("No EXT_frag_depth support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled EXT_frag_depth extension");
+
+ runSupportedTest(true);
+
+ runShaderTests(true);
+ runOutputTests();
+ runUniqueObjectTest();
+
+ // Run deferred link tests.
+ runDeferredLinkTests();
+ }
+ }
+
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("EXT_frag_depth") >= 0) {
+ if (extensionEnabled) {
+ testPassed("EXT_frag_depth listed as supported and getExtension succeeded");
+ } else {
+ testFailed("EXT_frag_depth listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("EXT_frag_depth not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("EXT_frag_depth not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runShaderTests(extensionEnabled) {
+ debug("");
+ debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
+
+ // Expect the macro shader to succeed ONLY if enabled
+ var macroFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "macroFragmentShader");
+ if (extensionEnabled) {
+ if (macroFragmentProgram) {
+ // Expected result
+ testPassed("GL_EXT_frag_depth defined in shaders when extension is enabled");
+ } else {
+ testFailed("GL_EXT_frag_depth not defined in shaders when extension is enabled");
+ }
+ } else {
+ if (macroFragmentProgram) {
+ testFailed("GL_EXT_frag_depth defined in shaders when extension is disabled");
+ } else {
+ testPassed("GL_EXT_frag_depth not defined in shaders when extension disabled");
+ }
+ }
+
+ // Always expect the shader missing the #pragma to fail (whether enabled or not)
+ var missingPragmaFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "missingPragmaFragmentShader");
+ if (missingPragmaFragmentProgram) {
+ testFailed("Shader built-ins allowed without #extension pragma");
+ } else {
+ testPassed("Shader built-ins disallowed without #extension pragma");
+ }
+
+ // Try to compile a shader using the built-ins that should only succeed if enabled
+ var testFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "testFragmentShader");
+ if (extensionEnabled) {
+ if (testFragmentProgram) {
+ testPassed("Shader built-ins compiled successfully when extension enabled");
+ } else {
+ testFailed("Shader built-ins failed to compile when extension enabled");
+ }
+ } else {
+ if (testFragmentProgram) {
+ testFailed("Shader built-ins compiled successfully when extension disabled");
+ } else {
+ testPassed("Shader built-ins failed to compile when extension disabled");
+ }
+ }
+}
+
+function runOutputTests() {
+ var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
+
+ debug("Testing various draws for valid built-in function behavior");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ // Enable depth testing with a clearDepth of 0.5
+ // This makes it so that fragments are only rendered when
+ // gl_fragDepthEXT is < 0.5
+ gl.clearDepth(0.5);
+ gl.enable(gl.DEPTH_TEST);
+
+ var positionLoc = 0;
+ var texcoordLoc = 1;
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition'], [0]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+ var depthUniform = gl.getUniformLocation(program, "uDepth");
+
+ // Draw 1: Greater than clear depth
+ gl.uniform1f(depthUniform, 1.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 255, 255, 255]);
+
+ // Draw 2: Less than clear depth
+ gl.uniform1f(depthUniform, 0.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+}
+
+function runUniqueObjectTest()
+{
+ debug("Testing that getExtension() returns the same object each time");
+ ext = null;
+ gl.getExtension("EXT_frag_depth").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("EXT_frag_depth").myProperty', '2');
+}
+
+function runDeferredLinkTests() {
+ debug("");
+ debug("Testing deferred shader compilation tests.");
+
+ // Test for compilation failures that are caused by missing extensions
+ // do not succeed if extensions are enabled during linking. This would
+ // only happen for deferred shader compilations.
+
+ // First test if link succeeds with extension enabled.
+ var glEnabled = wtu.create3DContext();
+ var extEnabled = glEnabled.getExtension("EXT_frag_depth");
+ if (!extEnabled) {
+ testFailed("Deferred link test expects the extension to be supported");
+ }
+
+ var vertexShader = wtu.loadShaderFromScript(glEnabled, "goodVertexShader");
+ var fragmentShader = wtu.loadShaderFromScript(glEnabled, "macroFragmentShader");
+
+ if (!vertexShader || !fragmentShader) {
+ testFailed("Could not create good shaders.");
+ return;
+ }
+
+ var program = wtu.setupProgram(glEnabled, [vertexShader, fragmentShader]);
+
+ if (!program) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ // Create new context to test link failure without extension enabled.
+ var glDeferred = wtu.create3DContext();
+
+ var vertexShader = wtu.loadShaderFromScript(glDeferred, "goodVertexShader", glDeferred.VERTEX_SHADER, undefined, undefined, true);
+ var fragmentShader = wtu.loadShaderFromScript(glDeferred, "macroFragmentShader", glDeferred.FRAGMENT_SHADER, undefined, undefined, true);
+
+ if (vertexShader == null || fragmentShader == null) {
+ testFailed("Could not create shaders.");
+ return;
+ }
+
+ // Shader compilations should have failed due to extensions not enabled.
+ glDeferred.getExtension("EXT_frag_depth");
+ var program = wtu.setupProgram(glDeferred, [vertexShader, fragmentShader]);
+ if (program) {
+ testFailed("Compilation with extension disabled then linking with extension enabled should have failed.");
+ return;
+ }
+
+ testPassed("Compilation with extension disabled then linking with extension enabled.");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-sRGB.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-sRGB.html
new file mode 100644
index 0000000000..7e8353f7f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-sRGB.html
@@ -0,0 +1,468 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="16" height="16" style="width: 50px; height: 50px; border: 1px solid black;"></canvas>
+
+<!-- Shaders to test output -->
+<script id="vertexShader" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+
+<script id="fragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+uniform float uColor;
+void main() {
+ gl_FragColor = vec4(uColor, uColor, uColor, 1);
+}
+</script>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+var canvas;
+var gl;
+var ext = null;
+
+var extConstants = {
+ "SRGB_EXT": 0x8C40,
+ "SRGB_ALPHA_EXT": 0x8C42,
+ "SRGB8_ALPHA8_EXT": 0x8C43,
+ "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT": 0x8210
+};
+
+function getExtension() {
+ ext = gl.getExtension("EXT_sRGB");
+}
+
+function listsExtension() {
+ var supported = gl.getSupportedExtensions();
+ return (supported.indexOf("EXT_sRGB") >= 0);
+}
+
+function toVec3String(val) {
+ if (typeof(val) == 'number') {
+ return toVec3String([val, val, val]);
+ }
+ return '[' + val[0] + ', ' + val[1] + ', ' + val[2] + ']';
+}
+
+var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
+
+function expectResult(target) {
+ wtu.checkCanvasRect(gl,
+ Math.floor(gl.drawingBufferWidth / 2),
+ Math.floor(gl.drawingBufferHeight / 2),
+ 1,
+ 1,
+ [target, target, target, 255],
+ undefined,
+ e);
+}
+
+function createGreysRGBTexture(gl, color, format) {
+ var numPixels = gl.drawingBufferWidth * gl.drawingBufferHeight;
+ var elements;
+ switch (format) {
+ case ext.SRGB_EXT: elements = 3; break;
+ case ext.SRGB_ALPHA_EXT: elements = 4; break;
+ default: return null;
+ }
+
+ var size = numPixels * elements;
+ var buf = new Uint8Array(size);
+ for (var ii = 0; ii < numPixels; ++ii) {
+ var off = ii * elements;
+ buf[off + 0] = color;
+ buf[off + 1] = color;
+ buf[off + 2] = color;
+ if (format == ext.SRGB_ALPHA_EXT) {
+ buf[off + 3] = 255;
+ }
+ }
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0,
+ format,
+ gl.drawingBufferWidth,
+ gl.drawingBufferHeight,
+ 0,
+ format,
+ gl.UNSIGNED_BYTE,
+ buf);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ 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);
+ return tex;
+}
+
+function testValidFormat(fn, internalFormat, formatName, enabled) {
+ if (enabled) {
+ fn(internalFormat);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "was able to create type " + formatName);
+ } else {
+ testInvalidFormat(fn, internalFormat, formatName, enabled);
+ }
+}
+
+function testInvalidFormat(fn, internalFormat, formatName, enabled) {
+ fn(internalFormat);
+ var err = gl.getError();
+ if (err == gl.NO_ERROR) {
+ testFailed("should NOT be able to create type " + formatName);
+ } else if (err == gl.INVALID_ENUM || err == gl.INVALID_VALUE) {
+ testPassed("not able to create invalid format: " + formatName);
+ }
+}
+
+var textureFormatFixture = {
+ desc: "Checking texture formats",
+ create: function(format) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ format, // internalFormat
+ gl.drawingBufferWidth, // width
+ gl.drawingBufferHeight, // height
+ 0, // border
+ format, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ },
+ tests: [
+ {
+ desc: "Checking valid formats",
+ fn: testValidFormat,
+ formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ]
+ },
+ {
+ desc: "Checking invalid formats",
+ fn: testInvalidFormat,
+ formats: [ 'SRGB8_ALPHA8_EXT' ]
+ }
+ ]
+};
+
+var renderbufferFormatFixture = {
+ desc: "Checking renderbuffer formats",
+ create: function(format) {
+ var rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER,
+ format,
+ gl.drawingBufferWidth,
+ gl.drawingBufferHeight);
+ },
+ tests: [
+ {
+ desc: "Checking valid formats",
+ fn: testValidFormat,
+ formats: [ 'SRGB8_ALPHA8_EXT' ]
+ },
+ {
+ desc: "Checking invalid formats",
+ fn: testInvalidFormat,
+ formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ]
+ }
+ ]
+};
+
+
+description("Test sRGB texture support");
+
+debug("");
+debug("Canvas.getContext");
+
+canvas = document.getElementById("canvas");
+gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking sRGB texture support with extension disabled");
+
+ runFormatTest(textureFormatFixture, false);
+ runFormatTest(renderbufferFormatFixture, false);
+
+ debug("");
+ debug("Checking sRGB texture support");
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("EXT_sRGB");
+
+ if (!ext) {
+ testPassed("No EXT_sRGB support -- this is legal");
+
+ runSupportedTest(false);
+ finishTest();
+ } else {
+ testPassed("Successfully enabled EXT_sRGB extension");
+
+ runSupportedTest(true);
+
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+
+ runConstantsTest();
+ runFormatTest(textureFormatFixture, true);
+ runFormatTest(renderbufferFormatFixture, true);
+ runTextureReadConversionTest();
+ runFramebufferTextureConversionTest(ext.SRGB_EXT);
+ runFramebufferTextureConversionTest(ext.SRGB_ALPHA_EXT);
+ runFramebufferRenderbufferConversionTest();
+ runGenerateMipmapTest();
+ runLoadFromImageTest(function() {
+ finishTest();
+ });
+ }
+}
+
+function runConstantsTest() {
+ debug("");
+ debug("Checking extension constants values");
+
+ for (var constant in extConstants) {
+ if (constant in ext) {
+ if (extConstants[constant] != ext[constant]) {
+ testFailed("Value of " + constant + " should be: " + extConstants[constant] + ", was: " + ext[constant]);
+ } else {
+ testPassed("Value of " + constant + " was expected value: " + extConstants[constant]);
+ }
+ } else {
+ testFailed(constant + " not found in extension object");
+ }
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ if (listsExtension()) {
+ if (extensionEnabled) {
+ testPassed("EXT_sRGB listed as supported and getExtension succeeded");
+ } else {
+ testFailed("EXT_sRGB listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("EXT_sRGB not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("EXT_sRGB not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runFormatTest(fixture, enabled) {
+ debug("");
+ debug(fixture.desc);
+
+ for (var tt = 0; tt < fixture.tests.length; ++tt) {
+ var test = fixture.tests[tt];
+ debug(test.desc);
+
+ for (var ii = 0; ii < test.formats.length; ++ii) {
+ var formatName = test.formats[ii];
+ test.fn(fixture.create, extConstants[formatName], "ext." + formatName, enabled);
+ }
+
+ if (tt != fixture.tests.length - 1)
+ debug("");
+ }
+}
+
+function runTextureReadConversionTest() {
+ debug("");
+ debug("Test the conversion of colors from sRGB to linear on texture read");
+
+ // Draw
+ var conversions = [
+ [ 0, 0 ],
+ [ 63, 13 ],
+ [ 127, 54 ],
+ [ 191, 133 ],
+ [ 255, 255 ]
+ ];
+
+ var program = wtu.setupTexturedQuad(gl);
+ gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+
+ for (var ii = 0; ii < conversions.length; ii++) {
+ var tex = createGreysRGBTexture(gl, conversions[ii][0], ext.SRGB_EXT);
+ wtu.drawUnitQuad(gl);
+ expectResult(conversions[ii][1]);
+ }
+}
+
+function runFramebufferTextureConversionTest(format) {
+ var formatString;
+ var validFormat;
+ switch (format) {
+ case ext.SRGB_EXT: formatString = "sRGB"; validFormat = false; break;
+ case ext.SRGB_ALPHA_EXT: formatString = "sRGB_ALPHA"; validFormat = true; break;
+ default: return null;
+ }
+ debug("");
+ debug("Test " + formatString + " framebuffer attachments." + (validFormat ? "" : " (Invalid)"));
+
+ var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]);
+ var tex = createGreysRGBTexture(gl, 0, format);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
+
+ if (validFormat) {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ debug("");
+ debug("Test the conversion of colors from linear to " + formatString + " on framebuffer (texture) write");
+
+ // Draw
+ var conversions = [
+ [ 0, 0 ],
+ [ 13, 63 ],
+ [ 54, 127 ],
+ [ 133, 191 ],
+ [ 255, 255 ]
+ ];
+
+ wtu.setupUnitQuad(gl, 0);
+
+ for (var ii = 0; ii < conversions.length; ii++) {
+ gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0);
+ wtu.drawUnitQuad(gl, [0, 0, 0, 0]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ expectResult(conversions[ii][1]);
+ }
+ } else {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+
+ wtu.setupUnitQuad(gl, 0);
+ gl.uniform1f(gl.getUniformLocation(program, "uColor"), 0.5);
+ wtu.drawUnitQuad(gl, [0, 0, 0, 0]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+}
+
+function runFramebufferRenderbufferConversionTest() {
+ debug("");
+ debug("Test the conversion of colors from linear to sRGB on framebuffer (renderbuffer) write");
+
+ function createsRGBFramebuffer(gl, width, height) {
+ var rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, ext.SRGB8_ALPHA8_EXT, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.RENDERBUFFER, rbo);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ return fbo;
+ }
+
+ // Draw
+ var conversions = [
+ [ 0, 0 ],
+ [ 13, 63 ],
+ [ 54, 127 ],
+ [ 133, 191 ],
+ [ 255, 255 ]
+ ];
+
+ var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]);
+ wtu.setupUnitQuad(gl, 0);
+ var fbo = createsRGBFramebuffer(gl, gl.drawingBufferWidth, gl.drawingBufferHeight);
+
+ for (var ii = 0; ii < conversions.length; ii++) {
+ gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0);
+ wtu.drawUnitQuad(gl, [0, 0, 0, 0]);
+ expectResult(conversions[ii][1]);
+ }
+}
+
+function runLoadFromImageTest(callback) {
+ debug("");
+ debug("Tests to ensure that SRGB textures can successfully use image elements as their source");
+
+ var img = wtu.makeImage("../../resources/gray-1024x1024.jpg", function() {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.SRGB_EXT, ext.SRGB_EXT, gl.UNSIGNED_BYTE, img);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.SRGB_ALPHA_EXT, ext.SRGB_ALPHA_EXT, gl.UNSIGNED_BYTE, img);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ callback();
+ }, function() {
+ testFailed("Image could not be loaded");
+ callback();
+ });
+}
+
+function runGenerateMipmapTest()
+{
+ debug("");
+ debug("GenerateMipmaps for sRGB textures is forbidden");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.SRGB_ALPHA_EXT, 2, 2, 0, ext.SRGB_ALPHA_EXT,
+ gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+
+ gl.deleteTexture(tex);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-shader-texture-lod.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-shader-texture-lod.html
new file mode 100644
index 0000000000..30176bd590
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-shader-texture-lod.html
@@ -0,0 +1,341 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_shader_texture_lod Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 256px; height: 256px;"> </canvas>
+<canvas id="canvas2" style="width: 256px; height: 256px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing texture LOD functions -->
+
+<!-- Shader omitting the required #extension pragma -->
+<script id="missingPragmaFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 texCoord0v;
+uniform float lod;
+uniform sampler2D tex;
+void main() {
+ vec4 color = texture2DLodEXT(tex, texCoord0v, lod);
+ gl_FragColor = color;
+}
+</script>
+
+<!-- Shader to test macro definition -->
+<script id="macroFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+#ifdef GL_EXT_shader_texture_lod
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+#else
+ // Error expected
+ #error no GL_EXT_shader_texture_lod;
+#endif
+}
+</script>
+
+<!-- Shader with required #extension pragma -->
+<script id="testFragmentShader" type="x-shader/x-fragment">
+#extension GL_EXT_shader_texture_lod : enable
+precision mediump float;
+varying vec2 texCoord0v;
+uniform float lod;
+uniform sampler2D tex;
+void main() {
+ vec4 color = texture2DLodEXT(tex, texCoord0v, lod);
+ gl_FragColor = color;
+}
+</script>
+
+<!-- Shaders to link with test fragment shaders -->
+<script id="goodVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord0v;
+void main() {
+ texCoord0v = texCoord0;
+ gl_Position = vPosition;
+}
+</script>
+
+<!-- Shaders to test output -->
+<script id="outputVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord0v;
+void main() {
+ texCoord0v = texCoord0;
+ gl_Position = vPosition;
+}
+</script>
+<script id="outputFragmentShader" type="x-shader/x-fragment">
+#extension GL_EXT_shader_texture_lod : require
+precision mediump float;
+varying vec2 texCoord0v;
+uniform float lod;
+uniform sampler2D tex;
+void main() {
+ vec4 color = texture2DLodEXT(tex, texCoord0v, lod);
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+description("This test verifies the functionality of the EXT_shader_texture_lod extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+
+// Run all tests once.
+runAllTests();
+
+// Run all tests against with a new context to test for any cache issues.
+debug("");
+debug("Testing new context to catch cache errors");
+var canvas2 = document.getElementById("canvas2");
+gl = wtu.create3DContext(canvas2);
+ext = null;
+runAllTests();
+
+function runAllTests() {
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ } else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runShaderTests(false);
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("EXT_shader_texture_lod");
+ if (!ext) {
+ testPassed("No EXT_shader_texture_lod support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled EXT_shader_texture_lod extension");
+
+ runSupportedTest(true);
+
+ runShaderTests(true);
+ runOutputTests();
+ runUniqueObjectTest();
+ runReferenceCycleTest();
+
+ // Run deferred link tests.
+ runDeferredLinkTests();
+ }
+ }
+
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("EXT_shader_texture_lod") >= 0) {
+ if (extensionEnabled) {
+ testPassed("EXT_shader_texture_lod listed as supported and getExtension succeeded");
+ } else {
+ testFailed("EXT_shader_texture_lod listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("EXT_shader_texture_lod not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("EXT_shader_texture_lod not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runShaderTests(extensionEnabled) {
+ debug("");
+ debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
+
+ // Expect the macro shader to succeed ONLY if enabled
+ var macroFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "macroFragmentShader");
+ if (extensionEnabled) {
+ if (macroFragmentProgram) {
+ // Expected result
+ testPassed("GL_EXT_shader_texture_lod defined in shaders when extension is enabled");
+ } else {
+ testFailed("GL_EXT_shader_texture_lod not defined in shaders when extension is enabled");
+ }
+ } else {
+ if (macroFragmentProgram) {
+ testFailed("GL_EXT_shader_texture_lod defined in shaders when extension is disabled");
+ } else {
+ testPassed("GL_EXT_shader_texture_lod not defined in shaders when extension disabled");
+ }
+ }
+
+ // Always expect the shader missing the #pragma to fail (whether enabled or not)
+ var missingPragmaFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "missingPragmaFragmentShader");
+ if (missingPragmaFragmentProgram) {
+ testFailed("Shader built-ins allowed without #extension pragma");
+ } else {
+ testPassed("Shader built-ins disallowed without #extension pragma");
+ }
+
+ // Try to compile a shader using the built-ins that should only succeed if enabled
+ var testFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "testFragmentShader");
+ if (extensionEnabled) {
+ if (testFragmentProgram) {
+ testPassed("Shader built-ins compiled successfully when extension enabled");
+ } else {
+ testFailed("Shader built-ins failed to compile when extension enabled");
+ }
+ } else {
+ if (testFragmentProgram) {
+ testFailed("Shader built-ins compiled successfully when extension disabled");
+ } else {
+ testPassed("Shader built-ins failed to compile when extension disabled");
+ }
+ }
+}
+
+function runOutputTests() {
+ debug("");
+ debug("Testing various draws for valid built-in function behavior");
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition', 'texCoord0'], [0, 1]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+
+ var colors = [
+ {name: 'red', color:[255, 0, 0, 255]},
+ {name: 'green', color:[0, 255, 0, 255]},
+ {name: 'blue', color:[0, 0, 255, 255]},
+ {name: 'yellow', color:[255, 255, 0, 255]},
+ {name: 'magenta', color:[255, 0, 255, 255]},
+ {name: 'cyan', color:[0, 255, 255, 255]},
+ {name: 'pink', color:[255, 128, 128, 255]},
+ {name: 'gray', color:[128, 128, 128, 255]},
+ {name: 'light green', color:[128, 255, 128, 255]},
+ ];
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var color = colors[ii];
+ var size = Math.pow(2, colors.length - ii - 1);
+ wtu.fillTexture(gl, tex, size, size, color.color, ii);
+ }
+
+ var loc = gl.getUniformLocation(program, "lod");
+
+ for (var ii = 0; ii < colors.length; ++ii) {
+ gl.uniform1f(loc, ii);
+ var color = colors[ii];
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, color.color,
+ "256x256 texture drawn to 256x256 dest with lod = " + ii +
+ " should be " + color.name);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ ext = null;
+ gl.getExtension("EXT_shader_texture_lod").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("EXT_shader_texture_lod").myProperty', '2');
+}
+
+function runReferenceCycleTest()
+{
+ // create some reference cycles. The goal is to see if they cause leaks. The point is that
+ // some browser test runners have instrumentation to detect leaked refcounted objects.
+ debug("");
+ debug("Testing reference cycles between context and extension objects");
+ var ext = gl.getExtension("EXT_shader_texture_lod");
+
+ // create cycle between extension and context, since the context has to hold a reference to the extension
+ ext.context = gl;
+
+ // create a self-cycle on the extension object
+ ext.ext = ext;
+}
+
+function runDeferredLinkTests() {
+ debug("");
+ debug("Testing deferred shader compilation tests.");
+
+ // Test for compilation failures that are caused by missing extensions
+ // do not succeed if extensions are enabled during linking. This would
+ // only happen for deferred shader compilations.
+
+ // First test if link succeeds with extension enabled.
+ var glEnabled = wtu.create3DContext();
+ var extEnabled = glEnabled.getExtension("EXT_shader_texture_lod");
+ if (!extEnabled) {
+ testFailed("Deferred link test expects the extension to be supported");
+ }
+
+ var vertexShader = wtu.loadShaderFromScript(glEnabled, "goodVertexShader");
+ var fragmentShader = wtu.loadShaderFromScript(glEnabled, "macroFragmentShader");
+
+ if (!vertexShader || !fragmentShader) {
+ testFailed("Could not create good shaders.");
+ return;
+ }
+
+ var program = wtu.setupProgram(glEnabled, [vertexShader, fragmentShader]);
+
+ if (!program) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ // Create new context to test link failure without extension enabled.
+ var glDeferred = wtu.create3DContext();
+
+ var vertexShader = wtu.loadShaderFromScript(glDeferred, "goodVertexShader", glDeferred.VERTEX_SHADER, undefined, undefined, true);
+ var fragmentShader = wtu.loadShaderFromScript(glDeferred, "macroFragmentShader", glDeferred.FRAGMENT_SHADER, undefined, undefined, true);
+
+ if (vertexShader == null || fragmentShader == null) {
+ testFailed("Could not create shaders.");
+ return;
+ }
+
+ // Shader compilations should have failed due to extensions not enabled.
+ glDeferred.getExtension("EXT_shader_texture_lod");
+ var program = wtu.setupProgram(glDeferred, [vertexShader, fragmentShader]);
+ if (program) {
+ testFailed("Compilation with extension disabled then linking with extension enabled should have failed.");
+ return;
+ }
+
+ testPassed("Compilation with extension disabled then linking with extension enabled.");
+}
+
+debug("");
+successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-bptc.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-bptc.html
new file mode 100644
index 0000000000..5b6c10f044
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-bptc.html
@@ -0,0 +1,159 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_texture_compression_bptc Conformance Tests</title>
+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_texture_compression_bptc extension, if it is available.");
+
+debug("");
+
+var validFormats = {
+ COMPRESSED_RGBA_BPTC_UNORM_EXT: 0x8E8C,
+ COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 0x8E8D,
+ COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 0x8E8E,
+ COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 0x8E8F
+};
+
+function expectedByteLength(width, height, format) {
+ return Math.ceil(width / 4) * Math.ceil(height / 4) * 16;
+}
+
+function getBlockDimensions(format) {
+ return {width: 4, height: 4};
+}
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var gl = wtu.create3DContext();
+var ext;
+
+var formats = null;
+
+function runTestExtension() {
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(ext, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+ // Test TexSubImage validation on dimensions
+ // CompressedTexSubImage* will result in an
+ // INVALID_OPERATION error only if one of the following conditions occurs:
+ // * <width> is not a multiple of four, and <width> plus <xoffset> is not
+ // equal to TEXTURE_WIDTH;
+ // * <height> is not a multiple of four, and <height> plus <yoffset> is
+ // not equal to TEXTURE_HEIGHT; or
+ // * <xoffset> or <yoffset> is not a multiple of four.
+ ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ 16, 16, [
+ { xoffset: 0, yoffset: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
+ { xoffset: 0, yoffset: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
+ { xoffset: 1, yoffset: 0, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
+ { xoffset: 0, yoffset: 1, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
+ { xoffset: 12, yoffset: 12, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ ]);
+
+ // Test TexImage validation on level dimensions combinations.
+ // When level equals 0, width and height must be a multiple of 4.
+ // When level is larger than 0, this constraint doesn't apply.
+
+ let npotExpectation, npotMessage;
+ if (contextVersion >= 2) {
+ npotExpectation = gl.NO_ERROR;
+ npotMessage = "valid";
+ } else {
+ npotExpectation = gl.INVALID_VALUE;
+ npotMessage = "invalid";
+ }
+
+ ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { level: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "level is 0, height is not a multiple of 4" },
+ { level: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
+ { level: 0, width: 2, height: 2,
+ expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
+ { level: 0, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ { level: 1, width: 1, height: 1,
+ expectation: gl.INVALID_OPERATION, message: "implied base mip 2x2 is invalid" },
+ { level: 1, width: 1, height: 2,
+ expectation: gl.INVALID_OPERATION, message: "implied base mip 2x4 is invalid" },
+ { level: 1, width: 2, height: 1,
+ expectation: gl.INVALID_OPERATION, message: "implied base mip 4x2 is invalid" },
+ { level: 1, width: 2, height: 2,
+ expectation: gl.NO_ERROR, message: "implied base mip 4x4 is valid" },
+ { level: 2, width: 1, height: 3,
+ expectation: npotExpectation, message: "implied base mip 4x12 is " + npotMessage },
+ ]);
+
+ // Test that BPTC enums are not accepted by texImage2D
+ {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_OPERATION], "COMPRESSED_RGBA_BPTC_UNORM_EXT fails with texImage2D");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_OPERATION], "COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT fails with texImage2D");
+
+ if (contextVersion >= 2) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 0, gl.RGB, gl.FLOAT, null);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_OPERATION], "COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT fails with texImage2D");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 0, gl.RGB, gl.FLOAT, null);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_OPERATION], "COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT fails with texImage2D");
+ }
+
+ gl.deleteTexture(tex);
+ }
+};
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
+
+ ext = gl.getExtension("EXT_texture_compression_bptc");
+
+ wtu.runExtensionSupportedTest(gl, "EXT_texture_compression_bptc", ext !== null);
+
+ if (ext !== null) {
+ runTestExtension();
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-rgtc.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-rgtc.html
new file mode 100644
index 0000000000..70dcf9ba7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-compression-rgtc.html
@@ -0,0 +1,162 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_texture_compression_rgtc Conformance Tests</title>
+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_texture_compression_rgtc extension, if it is available.");
+
+debug("");
+
+var validFormats = {
+ COMPRESSED_RED_RGTC1_EXT: 0x8DBB,
+ COMPRESSED_SIGNED_RED_RGTC1_EXT: 0x8DBC,
+ COMPRESSED_RED_GREEN_RGTC2_EXT: 0x8DBD,
+ COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 0x8DBE
+};
+
+function expectedByteLength(width, height, format) {
+ if (format == validFormats.COMPRESSED_RED_RGTC1_EXT || format == validFormats.COMPRESSED_SIGNED_RED_RGTC1_EXT) {
+ return Math.ceil(width / 4) * Math.ceil(height / 4) * 8;
+ }
+ else {
+ return Math.ceil(width / 4) * Math.ceil(height / 4) * 16;
+ }
+}
+
+function getBlockDimensions(format) {
+ return {width: 4, height: 4};
+}
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var gl = wtu.create3DContext();
+var ext;
+
+var formats = null;
+
+function runTestExtension() {
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(ext, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+ // Test TexSubImage validation on dimensions
+ // CompressedTexSubImage* will result in an
+ // INVALID_OPERATION error only if one of the following conditions occurs:
+ // * <width> is not a multiple of four, and <width> plus <xoffset> is not
+ // equal to TEXTURE_WIDTH;
+ // * <height> is not a multiple of four, and <height> plus <yoffset> is
+ // not equal to TEXTURE_HEIGHT; or
+ // * <xoffset> or <yoffset> is not a multiple of four.
+ ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ 16, 16, [
+ { xoffset: 0, yoffset: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
+ { xoffset: 0, yoffset: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
+ { xoffset: 1, yoffset: 0, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
+ { xoffset: 0, yoffset: 1, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
+ { xoffset: 12, yoffset: 12, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ ]);
+
+ // Test TexImage validation on level dimensions combinations.
+ // When level equals 0, width and height must be a multiple of 4.
+ // When level is larger than 0, this constraint doesn't apply.
+
+ let npotExpectation, npotMessage;
+ if (contextVersion >= 2) {
+ npotExpectation = gl.NO_ERROR;
+ npotMessage = "valid";
+ } else {
+ npotExpectation = gl.INVALID_VALUE;
+ npotMessage = "invalid";
+ }
+
+ ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { level: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "level is 0, height is not a multiple of 4" },
+ { level: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
+ { level: 0, width: 2, height: 2,
+ expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
+ { level: 0, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ { level: 1, width: 1, height: 1,
+ expectation: gl.INVALID_OPERATION, message: "implied base mip 2x2 is invalid" },
+ { level: 1, width: 1, height: 2,
+ expectation: gl.INVALID_OPERATION, message: "implied base mip 2x4 is invalid" },
+ { level: 1, width: 2, height: 1,
+ expectation: gl.INVALID_OPERATION, message: "implied base mip 4x2 is invalid" },
+ { level: 1, width: 2, height: 2,
+ expectation: gl.NO_ERROR, message: "implied base mip 4x4 is valid" },
+ { level: 2, width: 1, height: 3,
+ expectation: npotExpectation, message: "implied base mip 4x12 is " + npotMessage },
+ ]);
+
+ // Test that RGTC enums are not accepted by texImage2D
+ if (contextVersion >= 2) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RED_RGTC1_EXT, 4, 4, 0, gl.RED, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RED_RGTC1_EXT fails with texImage2D");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 0, gl.RED, gl.BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SIGNED_RED_RGTC1_EXT fails with texImage2D");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 0, gl.RG, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RED_GREEN_RGTC2_EXT fails with texImage2D");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 0, gl.RG, gl.BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT fails with texImage2D");
+
+ gl.deleteTexture(tex);
+ }
+};
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
+
+ ext = gl.getExtension("EXT_texture_compression_rgtc");
+
+ wtu.runExtensionSupportedTest(gl, "EXT_texture_compression_rgtc", ext !== null);
+
+ if (ext !== null) {
+ runTestExtension();
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-filter-anisotropic.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-filter-anisotropic.html
new file mode 100644
index 0000000000..1376d3e402
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/ext-texture-filter-anisotropic.html
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/ext-texture-filter-anisotropic.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/get-extension.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/get-extension.html
new file mode 100644
index 0000000000..8d9a9bc6de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/get-extension.html
@@ -0,0 +1,99 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Extension Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+
+var pseudoRandom = (function() {
+ var seed = 3;
+ return function() {
+ seed = (seed * 11 + 17) % 25;
+ return seed / 25;
+ };
+})();
+
+var randomizeCase = function(str) {
+ var newChars = [];
+ for (var ii = 0; ii < str.length; ++ii) {
+ var c = str.substr(ii, 1);
+ var m = (pseudoRandom() > 0.5) ? c.toLowerCase() : c.toUpperCase();
+ newChars.push(m);
+ }
+ return newChars.join("");
+};
+
+description();
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+
+var ii;
+
+debug("check every extension advertised can be enabled");
+debug("");
+var extensionNames = gl.getSupportedExtensions();
+var extensionNamesLower = [];
+for (ii = 0; ii < extensionNames.length; ++ii) {
+ extensionNamesLower.push(extensionNames[ii].toLowerCase());
+}
+
+for (ii = 0; ii < extensionNames.length; ++ii) {
+ var originalName = extensionNames[ii];
+ var mixedName = randomizeCase(originalName);
+ var extension = gl.getExtension(mixedName);
+ assertMsg(extension, "able to get " + originalName + " as " + mixedName);
+ if (extension) {
+ var kTestString = "this is a test";
+ var kTestNumber = 123;
+ var kTestFunction = function() { };
+ var kTestObject = { };
+ extension.testStringProperty = kTestString;
+ extension.testNumberProperty = kTestNumber;
+ extension.testFunctionProperty = kTestFunction;
+ extension.testObjectProperty = kTestObject;
+ webglHarnessCollectGarbage();
+ var extension2 = gl.getExtension(originalName);
+ assertMsg(
+ extension === extension2,
+ "calling getExtension twice for the same extension returns the same object");
+ assertMsg(
+ extension2.testStringProperty === kTestString &&
+ extension2.testFunctionProperty === kTestFunction &&
+ extension2.testObjectProperty === kTestObject &&
+ extension2.testNumberProperty === kTestNumber,
+ "object returned by 2nd call to getExtension has same properties");
+
+ var prefixedVariants = wtu.getExtensionPrefixedNames(originalName);
+ for (var jj = 0; jj < prefixedVariants.length; ++jj) {
+ assertMsg(
+ gl.getExtension(prefixedVariants[jj]) === null ||
+ extensionNamesLower.indexOf(prefixedVariants[jj].toLowerCase()) !== -1,
+ "getExtension('" + prefixedVariants[jj] + "') returns an object only if the name is returned by getSupportedExtensions");
+ }
+ }
+ debug("");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/khr-parallel-shader-compile.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/khr-parallel-shader-compile.html
new file mode 100644
index 0000000000..2915a2d2de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/khr-parallel-shader-compile.html
@@ -0,0 +1,220 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+.spinner {
+ width: 100px;
+ height: 100px;
+ border: 20px solid transparent;
+ border-top: 20px solid black;
+ border-radius: 100%;
+ text-align: center;
+ padding: 10px;
+}
+@keyframes rotation {
+ from { transorm: rotate(0); }
+ to { transform: rotate(360deg); }
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<button onclick='compileShaders()'>The spinners below should not stutter when you click this button.</button>
+<div class="spinner" style="animation: rotation 2s infinite linear;">CSS</div>
+<div class="spinner" id=spinner>JS</div>
+<div id="console"></div>
+<canvas id=canvas></canvas>
+<script>
+"use strict";
+description("Test KHR_parallel_shader_compile");
+
+function spinSpinner() {
+ let degrees = (performance.now() / 1000 / 2 % 1.) * 360;
+ spinner.style.transform = `rotate(${degrees}deg)`;
+ requestAnimationFrame(spinSpinner);
+}
+spinSpinner();
+
+const wtu = WebGLTestUtils;
+
+const gl = wtu.create3DContext();
+const loseContext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_lose_context");
+
+let counter = 0;
+const vertexSource = (extra) => `
+void main() {
+ vec4 result = vec4(0.${counter++});
+${extra || ''}
+ gl_Position = result;
+}`;
+const fragmentSource = (extra) => `
+precision highp float;
+void main() {
+ vec4 result = vec4(0.${counter++});
+${extra || ''}
+ gl_FragColor = result;
+}`;
+
+let vs = gl.createShader(gl.VERTEX_SHADER);
+let fs = gl.createShader(gl.FRAGMENT_SHADER);
+let program = gl.createProgram();
+gl.attachShader(program, vs);
+gl.attachShader(program, fs);
+
+const COMPLETION_STATUS_KHR = 0x91B1;
+
+gl.shaderSource(vs, vertexSource());
+gl.compileShader(vs);
+let status = gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
+if (status !== null) testFailed('Extension disabled, status should be null');
+wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "extension disabled");
+
+gl.shaderSource(fs, fragmentSource());
+gl.compileShader(fs);
+
+gl.linkProgram(program);
+status = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
+if (status !== null) testFailed('Extension disabled, status should be null');
+wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "extension disabled");
+
+const ext = wtu.getExtensionWithKnownPrefixes(gl, "KHR_parallel_shader_compile");
+
+let successfullyParsed = false;
+
+let extraCode = '';
+
+(async () => {
+
+ if (!ext) {
+ testPassed("No KHR_parallel_shader_compile support -- this is legal");
+ } else {
+ testPassed("Successfully enabled KHR_parallel_shader_compile extension");
+
+ shouldBe("ext.COMPLETION_STATUS_KHR", "0x91B1");
+
+ debug("Checking that status is a boolean.");
+ gl.shaderSource(vs, vertexSource());
+ gl.compileShader(vs);
+ let status = gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
+ if (status !== true && status !== false) testFailed("status should be a boolean");
+
+ gl.linkProgram(program);
+ status = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
+ if (status !== true && status !== false) testFailed("status should be a boolean");
+
+ const minimumShaderCompileDurationMs = 500;
+ debug(`Constructing shader that takes > ${minimumShaderCompileDurationMs} ms to compile.`);
+ let measuredCompileDuration = 0;
+ extraCode = '\n if (true) { result += vec4(0.0000001); }';
+ for (let i = 0; measuredCompileDuration < minimumShaderCompileDurationMs; i++) {
+ extraCode += extraCode;
+ extraCode += extraCode;
+ if (i < 4) continue;
+ gl.shaderSource(vs, vertexSource(extraCode));
+ gl.shaderSource(fs, fragmentSource(extraCode));
+ gl.compileShader(vs);
+ gl.compileShader(fs);
+ gl.linkProgram(program);
+ const start = performance.now();
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ testFailed(`Shaders failed to compile.
+ program: ${gl.getProgramInfoLog(program)}
+ vs: ${gl.getShaderInfoLog(vs)}
+ fs: ${gl.getShaderInfoLog(fs)}`);
+ break;
+ }
+ measuredCompileDuration = performance.now() - start;
+ }
+
+ debug('');
+ gl.shaderSource(vs, vertexSource(extraCode));
+ gl.shaderSource(fs, fragmentSource(extraCode));
+ gl.compileShader(vs);
+ gl.compileShader(fs);
+ gl.linkProgram(program);
+
+ let start = performance.now();
+ gl.getShaderParameter(fs, COMPLETION_STATUS_KHR);
+ gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
+ let duration = performance.now() - start;
+ if (duration > 100)
+ testFailed(`Querying shader status should not wait for compilation. Took ${duration} ms`);
+
+ let frames = 0;
+ const maximumTimeToWait = measuredCompileDuration * 4;
+ while (!gl.getProgramParameter(program, COMPLETION_STATUS_KHR)
+ && performance.now() - start < maximumTimeToWait) {
+ frames++;
+ await new Promise(requestAnimationFrame);
+ }
+ duration = performance.now() - start;
+ if (!gl.getProgramParameter(program, COMPLETION_STATUS_KHR)) {
+ testFailed(`Program took longer than ${maximumTimeToWait} ms to compile. Expected: ${measuredCompileDuration} ms, actual: ${duration} ms`);
+ } else if (!gl.getShaderParameter(vs, COMPLETION_STATUS_KHR) || !gl.getShaderParameter(fs, COMPLETION_STATUS_KHR)) {
+ testFailed('Program linked before shaders finished compiling.');
+ } else if (frames <= 6) {
+ testFailed(`Program should have taken many more than 6 frames to compile. Actual value: ${frames} frames, duration ${performance.now() - start} ms.`);
+ } else {
+ console.log(`COMPLETION_STATUS_KHR sucessfully transitioned from false to true in ${frames} frames and ${duration} ms.`);
+ testPassed(`COMPLETION_STATUS_KHR sucessfully transitioned from false to true`);
+ }
+
+
+ debug("Checking that status is true when context is lost.");
+ if (loseContext) {
+ gl.shaderSource(vs, vertexSource(extraCode));
+ gl.shaderSource(fs, fragmentSource(extraCode));
+ gl.compileShader(vs);
+ gl.compileShader(fs);
+ gl.linkProgram(program);
+ loseContext.loseContext();
+ status = gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
+ if (status !== true) testFailed("shader status should be true when context is lost");
+ status = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
+ if (status !== true) testFailed("program status should be true when context is lost");
+ loseContext.restoreContext();
+ vs = gl.createShader(gl.VERTEX_SHADER);
+ fs = gl.createShader(gl.FRAGMENT_SHADER);
+ program = gl.createProgram();
+ }
+ }
+ finishTest();
+})();
+
+async function compileShaders() {
+ console.log('Compiling shaders');
+ const gl = canvas.getContext('webgl');
+ const vs = gl.createShader(gl.VERTEX_SHADER);
+ const fs = gl.createShader(gl.FRAGMENT_SHADER);
+ const program = gl.createProgram();
+ gl.getExtension(wtu.getExtensionWithKnownPrefixes(gl, "KHR_parallel_shader_compile"));
+ gl.attachShader(program, vs);
+ gl.attachShader(program, fs);
+ gl.shaderSource(vs, vertexSource(extraCode));
+ gl.shaderSource(fs, fragmentSource(extraCode));
+ gl.compileShader(vs);
+ gl.compileShader(fs);
+ gl.linkProgram(program);
+ while (!gl.getProgramParameter(program, COMPLETION_STATUS_KHR)) {
+ gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
+ gl.getShaderParameter(fs, COMPLETION_STATUS_KHR);
+ await new Promise(requestAnimationFrame);
+ }
+ gl.getProgramParameter(program, gl.LINK_STATUS);
+ console.log('Compilation finished.');
+}
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-element-index-uint.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-element-index-uint.html
new file mode 100644
index 0000000000..f30acaba28
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-element-index-uint.html
@@ -0,0 +1,428 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_element_index_uint Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="vs" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main() {
+ gl_Position = vPosition;
+ color = vColor;
+}
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the OES_element_index_uint extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = null;
+var ext = null;
+var canvas = null;
+
+// Test both STATIC_DRAW and DYNAMIC_DRAW as a regression test
+// for a bug in ANGLE which has since been fixed.
+for (var ii = 0; ii < 2; ++ii) {
+ canvas = document.createElement("canvas");
+ canvas.width = 50;
+ canvas.height = 50;
+
+ gl = wtu.create3DContext(canvas);
+
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ } else {
+ testPassed("WebGL context exists");
+
+ var drawType = (ii == 0) ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
+ debug("Testing " + ((ii == 0) ? "STATIC_DRAW" : "DYNAMIC_DRAW"));
+
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("OES_element_index_uint");
+ if (!ext) {
+ testPassed("No OES_element_index_uint support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled OES_element_index_uint extension");
+
+ runSupportedTest(true);
+
+ runDrawTests(drawType);
+
+ // These tests are tweaked duplicates of the buffers/index-validation* tests
+ // using unsigned int indices to ensure that behavior remains consistent
+ runIndexValidationTests(drawType);
+ runCopiesIndicesTests(drawType);
+ runResizedBufferTests(drawType);
+ runVerifiesTooManyIndicesTests(drawType);
+ runCrashWithBufferSubDataTests(drawType);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("OES_element_index_uint") >= 0) {
+ if (extensionEnabled) {
+ testPassed("OES_element_index_uint listed as supported and getExtension succeeded");
+ } else {
+ testFailed("OES_element_index_uint listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("OES_element_index_uint not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("OES_element_index_uint not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runDrawTests(drawType) {
+ debug("Test that draws with unsigned integer indices produce the expected results");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var program = wtu.setupSimpleColorProgram(gl);
+
+ function setupDraw(s) {
+ // Create a vertex buffer that cannot be fully indexed via shorts
+ var quadArrayLen = 65537 * 3;
+ var quadArray = new Float32Array(quadArrayLen);
+
+ // Leave all but the last 4 values zero-ed out
+ var idx = quadArrayLen - 12;
+
+ // Initialized the last 4 values to a quad
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, quadArray, drawType);
+
+ // Create an unsigned int index buffer that indexes the last 4 vertices
+ var baseIndex = (quadArrayLen / 3) - 4;
+
+ var indexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([
+ baseIndex + 0,
+ baseIndex + 1,
+ baseIndex + 2,
+ baseIndex + 2,
+ baseIndex + 3,
+ baseIndex + 0]), drawType);
+
+ var opt_positionLocation = 0;
+ gl.enableVertexAttribArray(opt_positionLocation);
+ gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0);
+ };
+ function testPixel(blockList, allowList) {
+ function testList(list, expected) {
+ for (var n = 0; n < list.length; n++) {
+ var l = list[n];
+ var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2;
+ var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2;
+ wtu.checkCanvasRect(gl, x, y, 1, 1, [expected, expected, expected],
+ "Draw should pass", 2);
+ }
+ }
+ testList(blockList, 0);
+ testList(allowList, 255);
+ };
+ function verifyDraw(s) {
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.setFloatDrawColor(gl, [0.0, 0.0, 0.0, 1.0]);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
+
+ var blockList = [];
+ var allowList = [];
+ var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
+ for (var n = 0; n < points.length; n++) {
+ if (points[n] <= s) {
+ blockList.push(points[n]);
+ } else {
+ allowList.push(points[n]);
+ }
+ }
+ testPixel(blockList, allowList);
+ };
+
+ setupDraw(0.5);
+ verifyDraw(0.5);
+}
+
+function runIndexValidationTests(drawType) {
+ description("Tests that index validation verifies the correct number of indices");
+
+ function sizeInBytes(type) {
+ switch (type) {
+ case gl.BYTE:
+ case gl.UNSIGNED_BYTE:
+ return 1;
+ case gl.SHORT:
+ case gl.UNSIGNED_SHORT:
+ return 2;
+ case gl.INT:
+ case gl.UNSIGNED_INT:
+ case gl.FLOAT:
+ return 4;
+ default:
+ throw "unknown type";
+ }
+ }
+
+ var program = wtu.loadStandardProgram(gl);
+
+ // 3 vertices => 1 triangle, interleaved data
+ var dataComplete = new Float32Array([0, 0, 0, 1,
+ 0, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 1,
+ 1, 1, 1, 1,
+ 0, 0, 1]);
+ var dataIncomplete = new Float32Array([0, 0, 0, 1,
+ 0, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 1,
+ 1, 1, 1, 1]);
+ var indices = new Uint32Array([0, 1, 2]);
+
+ debug("Testing with valid indices");
+
+ var bufferComplete = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferComplete);
+ gl.bufferData(gl.ARRAY_BUFFER, dataComplete, drawType);
+ var elements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
+ gl.useProgram(program);
+ var vertexLoc = gl.getAttribLocation(program, "a_vertex");
+ var normalLoc = gl.getAttribLocation(program, "a_normal");
+ gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
+ gl.enableVertexAttribArray(vertexLoc);
+ gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+ gl.enableVertexAttribArray(normalLoc);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("Testing with out-of-range indices");
+
+ var bufferIncomplete = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
+ gl.bufferData(gl.ARRAY_BUFFER, dataIncomplete, drawType);
+ gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
+ gl.enableVertexAttribArray(vertexLoc);
+ gl.disableVertexAttribArray(normalLoc);
+ debug("Enable vertices, valid");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ debug("Enable normals, out-of-range");
+ gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+ gl.enableVertexAttribArray(normalLoc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
+ 'gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+
+ debug("Test with enabled attribute that does not belong to current program");
+
+ gl.disableVertexAttribArray(normalLoc);
+ var extraLoc = Math.max(vertexLoc, normalLoc) + 1;
+ gl.enableVertexAttribArray(extraLoc);
+ debug("Enable an extra attribute with null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ debug("Enable an extra attribute with insufficient data buffer");
+ gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ debug("Pass large negative index to vertexAttribPointer");
+ gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+}
+
+function runCopiesIndicesTests(drawType) {
+ debug("Test that client data is always copied during bufferData and bufferSubData calls");
+
+ var program = wtu.loadStandardProgram(gl);
+
+ gl.useProgram(program);
+ var vertexObject = gl.createBuffer();
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ // 4 vertices -> 2 triangles
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0,0, 0,1,0, 1,0,0, 1,1,0 ]), drawType);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexObject = gl.createBuffer();
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ var indices = new Uint32Array([ 10000, 0, 1, 2, 3, 10000 ]);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 4)");
+ var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
+ "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 0)");
+ wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 8)");
+ indices[0] = 2;
+ indices[5] = 1;
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 4)");
+ wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 0)");
+ wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 8)");
+}
+
+function runResizedBufferTests(drawType) {
+ debug("Test that updating the size of a vertex buffer is properly noticed by the WebGL implementation.");
+
+ var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initialization");
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [-1,1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0]), drawType);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex setup");
+
+ var texCoordObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1]), drawType);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coord setup");
+
+ // Now resize these buffers because we want to change what we're drawing.
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0,
+ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0]), drawType);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex redefinition");
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]), drawType);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coordinate / color redefinition");
+
+ var numQuads = 2;
+ var indices = new Uint32Array(numQuads * 6);
+ for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ var quad = (ii == (numQuads - 1)) ? 4 : 0;
+ indices[offset + 0] = quad + 0;
+ indices[offset + 1] = quad + 1;
+ indices[offset + 2] = quad + 2;
+ indices[offset + 3] = quad + 2;
+ indices[offset + 4] = quad + 1;
+ indices[offset + 5] = quad + 3;
+ }
+ var indexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
+ gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_INT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+}
+
+function runVerifiesTooManyIndicesTests(drawType) {
+ description("Tests that index validation for drawElements does not examine too many indices");
+
+ var program = wtu.loadStandardProgram(gl);
+
+ gl.useProgram(program);
+ var vertexObject = gl.createBuffer();
+ gl.enableVertexAttribArray(0);
+ gl.disableVertexAttribArray(1);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ // 4 vertices -> 2 triangles
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0,0, 0,1,0, 1,0,0, 1,1,0 ]), drawType);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexObject = gl.createBuffer();
+
+ debug("Test out of range indices")
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([ 10000, 0, 1, 2, 3, 10000 ]), drawType);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 4)");
+ var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
+ "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 0)");
+ wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 8)");
+}
+
+function runCrashWithBufferSubDataTests(drawType) {
+ debug('Verifies that the index validation code which is within bufferSubData does not crash.')
+
+ var elementBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, drawType);
+ var data = new Uint32Array(127);
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 64, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "after attempting to update a buffer outside of the allocated bounds");
+ testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-fbo-render-mipmap.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-fbo-render-mipmap.html
new file mode 100644
index 0000000000..b560a4c89a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-fbo-render-mipmap.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_fbo_render_mipmap Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="128" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the OES_fbo_render_mipmap extension, if it is available.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+
+(function(){
+
+ const oesFboRenderMipmap = gl.getExtension("OES_fbo_render_mipmap");
+ if (!oesFboRenderMipmap) {
+ testPassed("OES_fbo_render_mipmap is allowed to be missing.");
+ return;
+ }
+
+ let texture = gl.createTexture();
+ 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_MIPMAP_NEAREST);
+
+ let colors = [
+ [255, 0, 0, 255],
+ [255, 127, 0, 255],
+ [255, 255, 0, 255],
+ [0, 255, 0, 255],
+ [0, 255, 255, 255],
+ [0, 127, 255, 255],
+ [0, 0, 255, 255],
+ [255, 0, 255, 255],
+ ];
+
+ let fbos = [];
+ let maxLevel = 7;
+ for (let level = 0; level <= maxLevel; level++) {
+ let size = Math.pow(2, maxLevel - level);
+ gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ let fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, level);
+ fbos.push(fbo);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Any level of a texture can be attached to a framebuffer object.");
+ }
+
+ for (let level = 0; level <= maxLevel; level++) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbos[level]);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.clearColor(colors[level][0] / 255, colors[level][1] / 255, colors[level][2] / 255, colors[level][3] / 255);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ let program = wtu.setupTexturedQuad(gl);
+
+ for (let level = 0; level <= maxLevel; level++) {
+ let size = Math.pow(2, maxLevel - level);
+ // We use differrent viewport sizes to affect which miplevel is fetched from the texture.
+ gl.viewport(0, 0, size, size);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, colors[level]);
+ }
+
+})();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-standard-derivatives.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-standard-derivatives.html
new file mode 100644
index 0000000000..f6f4de0243
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-standard-derivatives.html
@@ -0,0 +1,444 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_standard_derivatives Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing standard derivatives -->
+
+<!-- Shader omitting the required #extension pragma -->
+<script id="missingPragmaFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 texCoord;
+void main() {
+ float dx = dFdx(texCoord.x);
+ float dy = dFdy(texCoord.y);
+ float w = fwidth(texCoord.x);
+ gl_FragColor = vec4(dx, dy, w, 1.0);
+}
+</script>
+
+<!-- Shader to test macro definition -->
+<script id="macroFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+#ifdef GL_OES_standard_derivatives
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+#else
+ // Error expected
+ #error no GL_OES_standard_derivatives;
+#endif
+}
+</script>
+
+<!-- Shader with required #extension pragma -->
+<script id="testFragmentShader" type="x-shader/x-fragment">
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+varying vec2 texCoord;
+void main() {
+ float dx = dFdx(texCoord.x);
+ float dy = dFdy(texCoord.y);
+ float w = fwidth(texCoord.x);
+ gl_FragColor = vec4(dx, dy, w, 1.0);
+}
+</script>
+<!-- Shader with #extension after other code -->
+<script id="testFragmentShaderWithExtensionNotAtTop" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 texCoord;
+void main() {
+#extension GL_OES_standard_derivatives : enable
+ float dx = dFdx(texCoord.x);
+ float dy = dFdy(texCoord.y);
+ float w = fwidth(texCoord.x);
+ gl_FragColor = vec4(dx, dy, w, 1.0);
+}
+</script>
+<!-- Shaders to link with test fragment shaders -->
+<script id="goodVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec2 texCoord;
+void main() {
+ texCoord = vPosition.xy;
+ gl_Position = vPosition;
+}
+</script>
+<!-- Shaders to test output -->
+<script id="outputVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 position;
+void main() {
+ position = vPosition;
+ gl_Position = vPosition;
+}
+</script>
+<script id="outputFragmentShader" type="x-shader/x-fragment">
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+varying vec4 position;
+void main() {
+ float dzdx = dFdx(position.z);
+ float dzdy = dFdy(position.z);
+ float fw = fwidth(position.z);
+ gl_FragColor = vec4(abs(dzdx) * 40.0, abs(dzdy) * 40.0, fw * 40.0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the OES_standard_derivatives extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+
+// Run all tests once.
+runAllTests();
+
+// Run all tests against with a new context to test for any cache issues.
+debug("");
+debug("Testing new context to catch cache errors");
+gl = wtu.create3DContext();
+ext = null;
+runAllTests();
+
+function runAllTests() {
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ } else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runHintTestDisabled();
+ runShaderTests(false);
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("OES_standard_derivatives");
+ if (!ext) {
+ testPassed("No OES_standard_derivatives support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled OES_standard_derivatives extension");
+
+ runSupportedTest(true);
+
+ runHintTestEnabled();
+ runShaderTests(true);
+ runOutputTests();
+ runUniqueObjectTest();
+
+ // Run deferred link tests.
+ runDeferredLinkTests();
+ }
+ }
+
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("OES_standard_derivatives") >= 0) {
+ if (extensionEnabled) {
+ testPassed("OES_standard_derivatives listed as supported and getExtension succeeded");
+ } else {
+ testFailed("OES_standard_derivatives listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("OES_standard_derivatives not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("OES_standard_derivatives not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runHintTestDisabled() {
+ debug("Testing FRAGMENT_SHADER_DERIVATIVE_HINT_OES with extension disabled");
+
+ // Use the constant directly as we don't have the extension
+ var FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
+
+ gl.getParameter(FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAGMENT_SHADER_DERIVATIVE_HINT_OES should not be queryable if extension is disabled");
+
+ gl.hint(FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.DONT_CARE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "hint should not accept FRAGMENT_SHADER_DERIVATIVE_HINT_OES if extension is disabled");
+}
+
+function runHintTestEnabled() {
+ debug("Testing FRAGMENT_SHADER_DERIVATIVE_HINT_OES with extension enabled");
+
+ shouldBe("ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES", "0x8B8B");
+
+ gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "FRAGMENT_SHADER_DERIVATIVE_HINT_OES query should succeed if extension is enabled");
+
+ // Default value is DONT_CARE
+ if (gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES) == gl.DONT_CARE) {
+ testPassed("Default value of FRAGMENT_SHADER_DERIVATIVE_HINT_OES is DONT_CARE");
+ } else {
+ testFailed("Default value of FRAGMENT_SHADER_DERIVATIVE_HINT_OES is not DONT_CARE");
+ }
+
+ // Ensure that we can set the target
+ gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.DONT_CARE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "hint should accept FRAGMENT_SHADER_DERIVATIVE_HINT_OES");
+
+ // Test all the hint modes
+ var validModes = ["FASTEST", "NICEST", "DONT_CARE"];
+ var anyFailed = false;
+ for (var n = 0; n < validModes.length; n++) {
+ var mode = validModes[n];
+ gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl[mode]);
+ if (gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES) != gl[mode]) {
+ testFailed("Round-trip of hint()/getParameter() failed on mode " + mode);
+ anyFailed = true;
+ }
+ }
+ if (!anyFailed) {
+ testPassed("Round-trip of hint()/getParameter() with all supported modes");
+ }
+}
+
+function runShaderTests(extensionEnabled) {
+ debug("");
+ debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
+
+ // Expect the macro shader to succeed ONLY if enabled
+ {
+ const macroFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "macroFragmentShader");
+ if (extensionEnabled) {
+ if (macroFragmentProgram) {
+ // Expected result
+ testPassed("GL_OES_standard_derivatives defined in shaders when extension is enabled");
+ } else {
+ testFailed("GL_OES_standard_derivatives not defined in shaders when extension is enabled");
+ }
+ } else {
+ if (macroFragmentProgram) {
+ testFailed("GL_OES_standard_derivatives defined in shaders when extension is disabled");
+ } else {
+ testPassed("GL_OES_standard_derivatives not defined in shaders when extension disabled");
+ }
+ }
+ }
+
+ // Always expect the shader missing the #pragma to fail (whether enabled or not)
+ {
+ const missingPragmaFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "missingPragmaFragmentShader");
+ if (missingPragmaFragmentProgram) {
+ testFailed("Shader built-ins allowed without #extension pragma");
+ } else {
+ testPassed("Shader built-ins disallowed without #extension pragma");
+ }
+ }
+
+ // Try to compile a shader using the built-ins that should only succeed if enabled
+ {
+ const testFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "testFragmentShader");
+ if (extensionEnabled) {
+ if (testFragmentProgram) {
+ testPassed("Shader built-ins compiled successfully when extension enabled");
+ } else {
+ testFailed("Shader built-ins failed to compile when extension enabled");
+ }
+ } else {
+ if (testFragmentProgram) {
+ testFailed("Shader built-ins compiled successfully when extension disabled");
+ } else {
+ testPassed("Shader built-ins failed to compile when extension disabled");
+ }
+ }
+ }
+
+ // This tests specifically that #extension directives after other code are
+ // valid, per spec (6.35 GLSL ES #extension directive location).
+ //
+ // This test actually has nothing to do with OES_standard_derivatives, but
+ // is inserted here because this extension is ubiquitous.
+ //
+ // This test is not as strict as the spec - it doesn't require that "the
+ // scope ... is always the whole shader", because implementations (ANGLE
+ // shader translator) do not actually implement this correctly. The test
+ // coverage is intentionally left incomplete - in practice, all WebGL
+ // shaders already work with the current implementation, so there's no
+ // practical reason to update them to match the spec. Conversely, the
+ // currently implemented rules are too complex to formalize in spec.
+ //
+ // Regression test for https://crbug.com/971660 .
+ {
+ const testFragmentProgramWithExtensionNotAtTop = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "testFragmentShaderWithExtensionNotAtTop");
+ if (extensionEnabled) {
+ if (testFragmentProgramWithExtensionNotAtTop) {
+ testPassed("Shader with #extension after non-preprocessor code: compiled successfully when extension enabled");
+ } else {
+ testFailed("Shader with #extension after non-preprocessor code: failed to compile when extension enabled");
+ }
+ }
+ }
+}
+
+function runOutputTests() {
+ // This tests does several draws with various values of z.
+ // The output of the fragment shader is:
+ // [dFdx(z), dFdy(z), fwidth(z), 1.0]
+ // The expected math: (note the conversion to uint8)
+ // canvas.width = canvas.height = 50
+ // dFdx = totalChange.x / canvas.width = 0.5 / 50.0 = 0.01
+ // dFdy = totalChange.y / canvas.height = 0.5 / 50.0 = 0.01
+ // fw = abs(dFdx + dFdy) = 0.01 + 0.01 = 0.02
+ // r = floor(dFdx * 40.0 * 255) = 102
+ // g = floor(dFdy * 40.0 * 255) = 102
+ // b = floor(fw * 40.0 * 255) = 204
+
+ var e = 5; // Amount of variance to allow in result pixels - may need to be tweaked higher
+
+ debug("Testing various draws for valid built-in function behavior");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.NICEST);
+
+ var positionLoc = 0;
+ var texcoordLoc = 1;
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition', 'texCoord0'], [0, 1]);
+ var quadParameters = wtu.setupUnitQuad(gl, positionLoc, texcoordLoc);
+
+ function expectResult(target, message) {
+ var locations = [
+ [ 0.1, 0.1 ],
+ [ 0.9, 0.1 ],
+ [ 0.1, 0.9 ],
+ [ 0.9, 0.9 ],
+ [ 0.5, 0.5 ]
+ ];
+ for (var n = 0; n < locations.length; n++) {
+ var loc = locations[n];
+ var px = Math.floor(loc[0] * canvas.width);
+ var py = Math.floor(loc[1] * canvas.height);
+ wtu.checkCanvasRect(gl, px, py, 1, 1, target, message, 4);
+ }
+ };
+
+ function setupBuffers(tl, tr, bl, br) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadParameters[0]);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0, 1.0, tr,
+ -1.0, 1.0, tl,
+ -1.0, -1.0, bl,
+ 1.0, 1.0, tr,
+ -1.0, -1.0, bl,
+ 1.0, -1.0, br]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
+ };
+
+ // Draw 1: (no variation)
+ setupBuffers(0.0, 0.0, 0.0, 0.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ expectResult([0, 0, 0, 255],
+ "Draw 1 (no variation) should pass");
+
+ // Draw 2: (variation in x)
+ setupBuffers(1.0, 0.0, 1.0, 0.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ expectResult([204, 0, 204, 255],
+ "Draw 2 (variation in x) should pass");
+
+ // Draw 3: (variation in y)
+ setupBuffers(1.0, 1.0, 0.0, 0.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ expectResult([0, 204, 204, 255],
+ "Draw 3 (variation in y) should pass");
+
+ // Draw 4: (variation in x & y)
+ setupBuffers(1.0, 0.5, 0.5, 0.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ expectResult([102, 102, 204, 255],
+ "Draw 4 (variation in x & y) should pass");
+}
+
+function runUniqueObjectTest()
+{
+ debug("Testing that getExtension() returns the same object each time");
+ ext = null;
+ gl.getExtension("OES_standard_derivatives").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("OES_standard_derivatives").myProperty', '2');
+}
+
+function runDeferredLinkTests() {
+ debug("");
+ debug("Testing deferred shader compilation tests.");
+
+ // Test for compilation failures that are caused by missing extensions
+ // do not succeed if extensions are enabled during linking. This would
+ // only happen for deferred shader compilations.
+
+ // First test if link succeeds with extension enabled.
+ var glEnabled = wtu.create3DContext();
+ var extEnabled = glEnabled.getExtension("OES_standard_derivatives");
+ if (!extEnabled) {
+ testFailed("Deferred link test expects the extension to be supported");
+ }
+
+ var vertexShader = wtu.loadShaderFromScript(glEnabled, "goodVertexShader");
+ var fragmentShader = wtu.loadShaderFromScript(glEnabled, "macroFragmentShader");
+
+ if (!vertexShader || !fragmentShader) {
+ testFailed("Could not create good shaders.");
+ return;
+ }
+
+ var program = wtu.setupProgram(glEnabled, [vertexShader, fragmentShader]);
+
+ if (!program) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ // Create new context to test link failure without extension enabled.
+ var glDeferred = wtu.create3DContext();
+
+ var vertexShader = wtu.loadShaderFromScript(glDeferred, "goodVertexShader", glDeferred.VERTEX_SHADER, undefined, undefined, true);
+ var fragmentShader = wtu.loadShaderFromScript(glDeferred, "macroFragmentShader", glDeferred.FRAGMENT_SHADER, undefined, undefined, true);
+
+ if (vertexShader == null || fragmentShader == null) {
+ testFailed("Could not create shaders.");
+ return;
+ }
+
+ // Shader compilations should have failed due to extensions not enabled.
+ glDeferred.getExtension("OES_standard_derivatives");
+ var program = wtu.setupProgram(glDeferred, [vertexShader, fragmentShader]);
+ if (program) {
+ testFailed("Compilation with extension disabled then linking with extension enabled should have failed.");
+ return;
+ }
+
+ testPassed("Compilation with extension disabled then linking with extension enabled.");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-linear.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-linear.html
new file mode 100644
index 0000000000..2c8f194e82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-linear.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/oes-texture-float-and-half-float-linear.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description("Test OES_texture_float_linear, if available.");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext();
+
+(function() {
+ if (!wtu.isWebGL2(gl)) {
+ if (!gl.getExtension("OES_texture_float")) {
+ testPassed("No OES_texture_float support -- this is legal");
+ return;
+ }
+ }
+ testTexLinear(gl, "OES_texture_float_linear", "RGBA32F", "FLOAT");
+})();
+
+debug("");
+const successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-canvas.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-canvas.html
new file mode 100644
index 0000000000..b681083899
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-canvas.html
@@ -0,0 +1,34 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ if (!gl.getExtension("OES_texture_float")) {
+ testPassed("No OES_texture_float support -- this is legal");
+ return false;
+ }
+
+ testPassed("Successfully enabled OES_texture_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "FLOAT", testPrologue, "../../resources/")()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image-data.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image-data.html
new file mode 100644
index 0000000000..74ad8d27db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image-data.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ if (!gl.getExtension("OES_texture_float")) {
+ testPassed("No OES_texture_float support -- this is legal");
+ return false;
+ }
+
+ testPassed("Successfully enabled OES_texture_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "FLOAT", testPrologue, "../../resources/")()'>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image.html
new file mode 100644
index 0000000000..cff19e5d51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-image.html
@@ -0,0 +1,34 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ if (!gl.getExtension("OES_texture_float")) {
+ testPassed("No OES_texture_float support -- this is legal");
+ return false;
+ }
+
+ testPassed("Successfully enabled OES_texture_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "FLOAT", testPrologue, "../../resources/")()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-video.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-video.html
new file mode 100644
index 0000000000..3ccbd50f15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float-with-video.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ if (!gl.getExtension("OES_texture_float")) {
+ testPassed("No OES_texture_float support -- this is legal");
+ return false;
+ }
+
+ testPassed("Successfully enabled OES_texture_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "FLOAT", testPrologue, "../../resources/")()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<video width="640" height="228" id="vid" controls muted>
+ <source src="../../resources/red-green.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
+ <source src="../../resources/red-green.webmvp8.webm" type='video/webm; codecs="vp8, vorbis"' />
+ <source src="../../resources/red-green.theora.ogv" type='video/ogg; codecs="theora, vorbis"' />
+</video>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float.html
new file mode 100644
index 0000000000..a757cb22ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-float.html
@@ -0,0 +1,426 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>OES_texture_float/WEBGL_color_buffer_float</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ext-float-blend.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing floating-point textures -->
+<script id="testFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+uniform vec4 subtractor;
+varying vec2 texCoord;
+void main()
+{
+ vec4 color = texture2D(tex, texCoord);
+ if (abs(color.r - subtractor.r) +
+ abs(color.g - subtractor.g) +
+ abs(color.b - subtractor.b) +
+ abs(color.a - subtractor.a) < 8.0) {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ } else {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+}
+</script>
+<!-- Shaders for testing floating-point render targets -->
+<script id="positionVertexShader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="floatingPointFragmentShader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(10000.0, 10000.0, 10000.0, 10000.0);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of the OES_texture_float and WEBGL_color_buffer_float extensions, if available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ var texturedShaders = [
+ wtu.simpleTextureVertexShader,
+ "testFragmentShader"
+ ];
+ var testProgram =
+ wtu.setupProgram(gl,
+ texturedShaders,
+ ['vPosition', 'texCoord0'],
+ [0, 1]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+
+ // First verify that allocation of floating-point textures fails if
+ // the extension has not been enabled yet.
+ runTextureCreationTest(testProgram, false);
+
+ if (!gl.getExtension("OES_texture_float")) {
+ testPassed("No OES_texture_float support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OES_texture_float extension");
+ // If alpha value is missing from a texture it gets filled to 1 when sampling according to GLES2.0 table 3.12
+ runTextureCreationTest(testProgram, true, gl.RGBA, 4, [10000, 10000, 10000, 10000]);
+ runTextureCreationTest(testProgram, true, gl.RGB, 3, [10000, 10000, 10000, 1]);
+ runTextureCreationTest(testProgram, true, gl.LUMINANCE, 1, [10000, 10000, 10000, 1]);
+ runTextureCreationTest(testProgram, true, gl.ALPHA, 1, [0, 0, 0, 10000]);
+ runTextureCreationTest(testProgram, true, gl.LUMINANCE_ALPHA, 2, [10000, 10000, 10000, 10000]);
+
+ (function() {
+ debug("");
+ var renderable = isRenderable(gl);
+ var renderableExtName = "WEBGL_color_buffer_float";
+ var supported = gl.getSupportedExtensions().includes(renderableExtName);
+ if (renderable && !supported) {
+ testFailed("RGBA/FLOAT is color renderable but " + renderableExtName + " not exposed");
+ } else if (supported && !renderable) {
+ testFailed(renderableExtName + " is exposed but RGBA/FLOAT is not color renderable");
+ }
+ if (supported) {
+ runRenderTargetAndReadbackTest(testProgram, gl.RGBA, 4, [10000, 10000, 10000, 10000], 0, true);
+ runRenderTargetAndReadbackTest(testProgram, gl.RGB, 3, [10000, 10000, 10000, 1], 0, false);
+ runRenderTargetAndReadbackTest(testProgram, gl.RGBA, 4, [10000, 10000, 10000, 10000], 1, true);
+ runRenderTargetAndReadbackTest(testProgram, gl.RGBA, 4, [10000, 10000, 10000, 10000], 0.5, true);
+ runFramebufferTest();
+
+ debug("");
+ debug("Test float32 blending without EXT_float_blend.");
+ testExtFloatBlend(gl.RGBA);
+
+ debug("");
+ debug("Testing that float32 blending succeeds with EXT_float_blend.");
+ if (!gl.getExtension("EXT_float_blend")) {
+ testPassed("No EXT_float_blend support -- this is legal");
+ return;
+ }
+ testExtFloatBlend(gl.RGBA);
+ }
+ })();
+
+ runUniqueObjectTest();
+ }
+}
+
+function isRenderable(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+
+ return status == gl.FRAMEBUFFER_COMPLETE;
+}
+
+function allocateTexture()
+{
+ 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);
+ 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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
+ return texture;
+}
+
+function checkRenderingResults()
+{
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function runTextureCreationTest(testProgram, extensionEnabled, opt_format, opt_numChannels, opt_subtractor)
+{
+ var format = opt_format || gl.RGBA;
+ var numberOfChannels = opt_numChannels || 4;
+ var expectFailure = !extensionEnabled;
+ var subtractor = opt_subtractor || [10000, 10000, 10000, 10000];
+
+ debug("");
+ debug("testing format: " + wtu.glEnumToString(gl, format) +
+ " expect:" + (extensionEnabled ? "success" : "failure"));
+
+ var texture = allocateTexture();
+ // Generate data.
+ var width = 2;
+ var height = 2;
+ var data = new Float32Array(width * height * numberOfChannels);
+ for (var ii = 0; ii < data.length; ++ii) {
+ data[ii] = 10000;
+ }
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, gl.FLOAT, data);
+ if (expectFailure) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point texture allocation must be disallowed if OES_texture_float isn't enabled");
+ return;
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled");
+ }
+ // Verify that the texture actually works for sampling and contains the expected data.
+ gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
+ wtu.clearAndDrawUnitQuad(gl);
+ checkRenderingResults();
+
+ // Check that linear fails.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+}
+
+function arrayToString(arr, size) {
+ var mySize;
+ if (!size)
+ mySize = arr.length;
+ else
+ mySize = size;
+ var out = "[";
+ for (var ii = 0; ii < mySize; ++ii) {
+ if (ii > 0) {
+ out += ", ";
+ }
+ out += arr[ii];
+ }
+ return out + "]";
+}
+
+function runRenderTargetAndReadbackTest(testProgram, format, numberOfChannels, subtractor, texSubImageCover, requireRenderable)
+{
+ var formatString = wtu.glEnumToString(gl, format);
+ debug("");
+ debug("testing floating-point " + formatString + " render target" + (texSubImageCover > 0 ? " after calling texSubImage" : ""));
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, gl.FLOAT, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled");
+
+ // Try to use this texture as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ // It is legal for a WebGL implementation exposing the OES_texture_float extension to
+ // support floating-point textures but not as attachments to framebuffer objects.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ if (requireRenderable)
+ testFailed("floating-point " + formatString + " render target not supported");
+ else
+ debug("floating-point " + formatString + " render target not supported -- this is legal");
+ return;
+ }
+
+ if (texSubImageCover > 0) {
+ // Ensure that replacing the whole texture or a part of it with texSubImage2D doesn't affect renderability
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ var data = new Float32Array(width * height * numberOfChannels * texSubImageCover);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height * texSubImageCover, format, gl.FLOAT, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed if OES_texture_float is enabled");
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("render target support changed after calling texSubImage2D");
+ return;
+ }
+ }
+
+ var renderProgram =
+ wtu.setupProgram(gl,
+ ["positionVertexShader", "floatingPointFragmentShader"],
+ ['vPosition'],
+ [0]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed");
+
+ // Now sample from the floating-point texture and verify we got the correct values.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.useProgram(testProgram);
+ gl.uniform1i(gl.getUniformLocation(testProgram, "tex"), 0);
+ gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from floating-point texture should succeed");
+ checkRenderingResults();
+
+ // Finally, if the implementation supports floating-point readback, verify it.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
+ var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter of IMPLEMENTATION_COLOR_READ_{FORMAT|TYPE} should succeed");
+ if ((implFormat == gl.RGBA || implFormat == gl.RGB) && implType == gl.FLOAT) {
+ debug("Checking readback of floating-point values");
+ var arraySize = (implFormat == gl.RGBA) ? 4 : 3
+ var buf = new Float32Array(arraySize);
+ gl.readPixels(0, 0, 1, 1, implFormat, implType , buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels from floating-point renderbuffer should succeed");
+ var ok = true;
+ var tolerance = 8.0; // TODO: factor this out from both this test and the subtractor shader above.
+ for (var ii = 0; ii < buf.length; ++ii) {
+ if (Math.abs(buf[ii] - subtractor[ii]) > tolerance) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ testPassed("readPixels of float-type data from floating-point renderbuffer succeeded");
+ } else {
+ testFailed("readPixels of float-type data from floating-point renderbuffer failed: expected "
+ + arrayToString(subtractor, arraySize) + ", got " + arrayToString(buf));
+ }
+ }
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ gl.getExtension("OES_texture_float").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("OES_texture_float").myProperty', '2');
+}
+
+// Make sure we can call readPixels with the passed in arrayBufferConstructor and that the color
+// channels are the ones we expect. If there is a mismatch between the glType and arrayBuffer type,
+// fail the test.
+function verifyReadPixelsColors(red, green, blue, alpha, alphaRGB, glFormat, glType, arrayBufferConstructor) {
+ var typeName = wtu.glEnumToString(gl, glType);
+
+ debug(wtu.glEnumToString(gl, glFormat) + " framebuffer with " + typeName + " readback.");
+
+ var arrayBuffer = new arrayBufferConstructor(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should return NO_ERROR when reading " + typeName + " data.");
+
+ assertMsg(arrayBuffer[0] === red, "Red channel should be " + red + " for " + typeName + " readPixels. Received: " + arrayBuffer[0]);
+ assertMsg(arrayBuffer[1] === green, "Green channel should be " + green + " for " + typeName + " readPixels. Received: " + arrayBuffer[1]);
+ assertMsg(arrayBuffer[2] === blue, "Blue channel should be " + blue + " for " + typeName + " readPixels. Received: " + arrayBuffer[2]);
+ if (glFormat === gl.RGBA) {
+ assertMsg(arrayBuffer[3] === alpha, "Alpha channel should be " + alpha + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]);
+ } else if (glFormat === gl.RGB) {
+ assertMsg(arrayBuffer[3] === alphaRGB, "Alpha channel should be " + alphaRGB + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]);
+ }
+
+ // Make sure any arrayBuffer types that are not equal to arrayBufferConstructor fail readPixels.
+ if (arrayBufferConstructor !== Uint8Array) {
+ arrayBuffer = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint8Array.toString());
+ }
+ if (arrayBufferConstructor !== Float32Array) {
+ arrayBuffer = new Float32Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Float32Array.toString());
+ }
+ if (arrayBufferConstructor !== Uint16Array) {
+ arrayBuffer = new Uint16Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint16Array.toString());
+ }
+}
+
+// Verify that float textures attached to frame buffers function correctly with regard to framebuffer
+// completness, IMPLEMENTATION_COLOR_READ_FORMAT/TYPE and readPixels
+function runFramebufferTest() {
+ debug("");
+ debug("Framebuffer Tests");
+
+ var texture = allocateTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ debug("Ensure non-color-renderable formats [LUMINANCE, LUMINANCE_ALPHA, ALPHA] fail.");
+ var arrayBufferFloatOutput = new Float32Array(4); // 4 color channels
+ [gl.LUMINANCE, gl.LUMINANCE_ALPHA, gl.ALPHA].forEach(function(badFormat) {
+ debug(wtu.glEnumToString(gl, badFormat) + " framebuffer");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, badFormat, 1, 1, 0, badFormat, gl.FLOAT, null);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+
+ shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_FORMAT should fail for incomplete framebuffers.");
+
+ shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_TYPE should fail for incomplete framebuffers.");
+
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, arrayBufferFloatOutput);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION , "readPixels should fail on incomplete framebuffers.");
+ debug("");
+ });
+
+ debug("Ensure color renderable formats [RGBA, RGB] succeed.");
+ var arrayBufferFloatInput = new Float32Array(4); // 4 color channels
+ arrayBufferFloatInput[0] = 0;
+ arrayBufferFloatInput[1] = .25;
+ arrayBufferFloatInput[2] = .50;
+ arrayBufferFloatInput[3] = .75;
+
+ [gl.RGBA, gl.RGB].forEach(function(goodFormat) {
+ debug("");
+ debug(wtu.glEnumToString(gl, goodFormat) + " framebuffer tests");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, goodFormat, 1, 1, 0, goodFormat, gl.FLOAT, arrayBufferFloatInput);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testPassed("Format is not renderable. This is allowed.");
+ return;
+ }
+ verifyReadPixelsColors(
+ 0.00, // red
+ 0.25, // green
+ 0.50, // blue
+ 0.75, // alpha
+ 1.0, // alphaRGB
+ goodFormat,
+ gl.FLOAT,
+ Float32Array);
+
+ var implementationColorReadFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
+ assertMsg(implementationColorReadFormat === gl.RGBA || implementationColorReadFormat === gl.RGB,
+ "IMPLEMENTATION_COLOR_READ_FORMAT should be color renderable: RGBA or RGB. Received: " + wtu.glEnumToString(gl, implementationColorReadFormat));
+
+ var implementationColorReadType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
+ assertMsg(implementationColorReadType === gl.UNSIGNED_BYTE ||
+ implementationColorReadType === gl.FLOAT ||
+ "IMPLEMENTATION_COLOR_READ_TYPE must be one of UNSIGNED_BYTE or FLOAT " +
+ "Received: " + wtu.glEnumToString(gl, implementationColorReadType));
+ });
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-linear.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-linear.html
new file mode 100644
index 0000000000..459346857e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-linear.html
@@ -0,0 +1,46 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/oes-texture-float-and-half-float-linear.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description("Test OES_texture_half_float_linear, if available.");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext();
+
+(function() {
+ if (wtu.isWebGL2(gl))
+ throw new Error("OES_texture_half_float_linear is core in WebGL 2.");
+
+ const ext = gl.getExtension("OES_texture_half_float");
+ if (!ext) {
+ testPassed("No OES_texture_half_float support -- this is legal");
+ return;
+ }
+ // Required by the test harness.
+ gl.HALF_FLOAT_OES = ext.HALF_FLOAT_OES;
+ testTexLinear(gl, "OES_texture_half_float_linear", undefined, "HALF_FLOAT_OES");
+})();
+
+debug("");
+const successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-canvas.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-canvas.html
new file mode 100644
index 0000000000..b991c58b19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-canvas.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ var ext = null;
+
+ if (!(ext = gl.getExtension("OES_texture_half_float"))) {
+ testPassed("No OES_texture_half_float support -- this is legal");
+ return false;
+ }
+
+ // Required by the test harness.
+ gl.HALF_FLOAT_OES = ext.HALF_FLOAT_OES;
+
+ testPassed("Successfully enabled OES_texture_half_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "HALF_FLOAT_OES", testPrologue, "../../resources/")()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image-data.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image-data.html
new file mode 100644
index 0000000000..91f3f97b08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image-data.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ var ext = null;
+
+ if (!(ext = gl.getExtension("OES_texture_half_float"))) {
+ testPassed("No OES_texture_half_float support -- this is legal");
+ return false;
+ }
+
+ // Required by the test harness.
+ gl.HALF_FLOAT_OES = ext.HALF_FLOAT_OES;
+
+ testPassed("Successfully enabled OES_texture_half_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "HALF_FLOAT_OES", testPrologue, "../../resources/")()'>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image.html
new file mode 100644
index 0000000000..3f486eac0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-image.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ var ext = null;
+
+ if (!(ext = gl.getExtension("OES_texture_half_float"))) {
+ testPassed("No OES_texture_half_float support -- this is legal");
+ return false;
+ }
+
+ // Required by the test harness.
+ gl.HALF_FLOAT_OES = ext.HALF_FLOAT_OES;
+
+ testPassed("Successfully enabled OES_texture_half_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "HALF_FLOAT_OES", testPrologue, "../../resources/")()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-video.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-video.html
new file mode 100644
index 0000000000..719b332113
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float-with-video.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ var ext = null;
+
+ if (!(ext = gl.getExtension("OES_texture_half_float"))) {
+ testPassed("No OES_texture_half_float support -- this is legal");
+ return false;
+ }
+
+ // Required by the test harness.
+ gl.HALF_FLOAT_OES = ext.HALF_FLOAT_OES;
+
+ testPassed("Successfully enabled OES_texture_half_float extension");
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "RGBA", "HALF_FLOAT_OES", testPrologue, "../../resources/")()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<video width="640" height="228" id="vid" controls muted>
+ <source src="../../resources/red-green.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
+ <source src="../../resources/red-green.webmvp8.webm" type='video/webm; codecs="vp8, vorbis"' />
+ <source src="../../resources/red-green.theora.ogv" type='video/ogg; codecs="theora, vorbis"' />
+</video>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float.html
new file mode 100644
index 0000000000..4d5d81608a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-texture-half-float.html
@@ -0,0 +1,474 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_texture_half_float Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<canvas id="canvas2d" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="testFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+uniform vec4 subtractor;
+varying vec2 texCoord;
+void main()
+{
+ vec4 color = texture2D(tex, texCoord);
+ if (abs(color.r - subtractor.r) +
+ abs(color.g - subtractor.g) +
+ abs(color.b - subtractor.b) +
+ abs(color.a - subtractor.a) < 8.0) {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ } else {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+}
+</script>
+<!-- Shaders for testing half-floating-point render targets -->
+<script id="floatingPointFragmentShader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(10000.0, 10000.0, 10000.0, 10000.0);
+}
+</script>
+<script>
+"use strict"
+description("This test verifies the functionality of OES_texture_half_float with null/non-null ArrayBufferView");
+
+debug("");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var colorCanvas = document.getElementById("canvas2d");
+colorCanvas.width = 2;
+colorCanvas.height = 2;
+var ctx = colorCanvas.getContext("2d");
+ctx.fillStyle = "rgb(255,0,0)";
+ctx.fillRect(0, 0, 2, 2);
+var gl = wtu.create3DContext(canvas);
+// This constant must be defined in order to run the texture creation test without the extension enabled.
+var halfFloatOESEnum = 0x8D61;
+var ext = null;
+
+
+if (!gl) {
+ testFailed("WebGL context does not exists");
+} else {
+ testPassed("WebGL context exists");
+
+ // Verify that allocation of texture fails if extension is not enabled
+ runTextureCreationTest(false);
+ ext = gl.getExtension("OES_texture_half_float")
+ if (!ext) {
+ testPassed("No OES_texture_half_float support. This is legal");
+ } else {
+ testPassed("Successfully enabled OES_texture_half_float extension");
+
+ var program = wtu.setupTexturedQuad(gl);
+
+ // Check if creation of texture succeed's with various formats and null ArrayBufferView
+ var formats = [
+ { format: gl.RGBA, expected: [255, 0, 0, 255], },
+ { format: gl.RGB, expected: [255, 0, 0, 255], },
+ { format: gl.LUMINANCE, expected: [255, 255, 255, 255], },
+ { format: gl.ALPHA, expected: [ 0, 0, 0, 255], },
+ { format: gl.LUMINANCE_ALPHA, expected: [255, 255, 255, 255], },
+ ];
+ formats.forEach(function(f) {
+ runTextureCreationTest(true, f.format, null, f.expected);
+ });
+
+ // Texture creation should fail when passed with non-null, non-Uint16 ArrayBufferView
+ formats.forEach(function(f) {
+ var width = 2;
+ var height = 2;
+ var format = f.format;
+
+ // Float32Array
+ var float32Data = new Float32Array(width * height * getNumberOfChannels(format));
+ for (var ii = 0; ii < float32Data.length; ii++) {
+ float32Data[ii] = 1000;
+ }
+ runTextureCreationTest(true, format, float32Data, null);
+
+ // Int16Array
+ var int16Data = new Int16Array(width * height * getNumberOfChannels(format));
+ for (var ii = 0; ii < int16Data.length; ii++) {
+ int16Data[ii] = 1000;
+ }
+ runTextureCreationTest(true, format, int16Data, null);
+ });
+
+ // Test that Uint16 encoded half float values can be used as texture data.
+
+ // First test that values in the 0-1 range can be written and read.
+ var halfFloatOneThird = 0x3555; // Half float 1/3
+ var uint16Formats = [
+ { format: gl.RGBA, expected: [85, 85, 85, 85], },
+ { format: gl.RGB, expected: [85, 85, 85, 255], },
+ { format: gl.LUMINANCE, expected: [85, 85, 85, 255], },
+ { format: gl.ALPHA, expected: [ 0, 0, 0, 85], },
+ { format: gl.LUMINANCE_ALPHA, expected: [85, 85, 85, 85], },
+ ];
+
+ uint16Formats.forEach(function(f) {
+ var width = 2;
+ var height = 2;
+ var format = f.format;
+
+ var uint16Data = new Uint16Array(width * height * getNumberOfChannels(format));
+ for (var ii = 0; ii < uint16Data.length; ii++) {
+ uint16Data[ii] = halfFloatOneThird;
+ }
+ runTextureCreationTest(true, format, uint16Data, f.expected);
+ });
+
+ // Next check that values outside the 0-1 range can be written.
+ var halfFloatTenK = 0x70E2; // Half float 10000
+ var uint16Formats2 = [
+ { format: gl.RGBA, subtractor: [10000, 10000, 10000, 10000], requireRenderable: true},
+ { format: gl.RGB, subtractor: [10000, 10000, 10000, 1], requireRenderable: false},
+ ];
+
+ uint16Formats2.forEach(function(f) {
+ var width = 2;
+ var height = 2;
+ var format = f.format;
+
+ var uint16Data = new Uint16Array(width * height * getNumberOfChannels(format));
+ for (var ii = 0; ii < uint16Data.length; ii++) {
+ uint16Data[ii] = halfFloatTenK;
+ }
+ runRenderTest(format, f.subtractor, uint16Data, f.requireRenderable);
+ });
+
+ (function() {
+ debug("");
+ var renderable = isRenderable(gl, ext);
+ var renderableExtName = "EXT_color_buffer_half_float";
+ var supported = gl.getSupportedExtensions().includes(renderableExtName);
+ if (renderable && !supported) {
+ testFailed("RGBA/HALF_FLOAT_OES is color renderable but " + renderableExtName + " not exposed");
+ } else if (supported && !renderable) {
+ testFailed(renderableExtName + " is exposed but RGBA/HALF_FLOAT_OES is not color renderable");
+ }
+ if (supported) {
+ runRenderTest(gl.RGBA, [10000, 10000, 10000, 10000], null, true);
+ runRenderTest(gl.RGB, [10000, 10000, 10000, 1], null, false);
+ runFramebufferTest();
+ }
+ })();
+
+ // Check of getExtension() returns same object
+ runUniqueObjectTest();
+ }
+}
+
+function isRenderable(gl, ext) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, ext.HALF_FLOAT_OES, null);
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+
+ return status == gl.FRAMEBUFFER_COMPLETE;
+}
+
+function getNumberOfChannels(format)
+{
+ if (format == gl.RGBA)
+ return 4;
+ else if (format == gl.RGB)
+ return 3;
+ else if (format == gl.LUMINANCE || format == gl.ALPHA)
+ return 1;
+ else if (format == gl.LUMINANCE_ALPHA)
+ return 2;
+}
+
+function allocateTexture()
+{
+ 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);
+ 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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
+ return texture;
+}
+
+function runTextureCreationTest(extensionEnabled, opt_format, opt_data, opt_expected)
+{
+ var format = opt_format || gl.RGBA;
+ var data = opt_data || null;
+ var expectSuccess = true;
+
+ if (!extensionEnabled || !opt_expected)
+ expectSuccess = false;
+ debug("Testing texture creation with extension " + (extensionEnabled ? "enabled" : "disabled") +
+ ", format " + wtu.glEnumToString(gl, format) + ", and data " + (data ? "non-null" : "null") +
+ ". Expect " + (expectSuccess ? "Success" : "Failure"));
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, halfFloatOESEnum, data);
+ if(!extensionEnabled) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Half floating point texture must be disallowed if OES_texture_half_float isn't enabled");
+ return;
+ } else if (!opt_expected) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Half floating point texture allocation must be disallowed when ArrayBufferView is not-null and not-Uint16");
+ return;
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Half floating point texture allocation should succeed if OES_texture_half_float is enabled");
+
+ if (!data) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, format, halfFloatOESEnum, colorCanvas);
+ }
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, opt_expected);
+ // Check that linear fails.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 0, 255], "should be black");
+ }
+
+}
+
+function checkRenderingResults()
+{
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function runRenderTest(format, subtractor, data, requireRenderable)
+{
+ var formatString = wtu.glEnumToString(gl, format);
+
+ debug("");
+
+ if (!data) {
+ debug("Testing half floating point " + formatString + " render target");
+ } else {
+ debug("Testing half floating point " + formatString + " from a Uint16Array");
+ }
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, ext.HALF_FLOAT_OES, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Half floating point texture allocation should succeed if OES_texture_half_float is enabled");
+
+ if (!data) {
+ // Try to use this texture as render target
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ // It is legal for a WebGL implementation exposing the OES_texture_half_float extension to
+ // support half floating point textures but not as attachments to framebuffer objects.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ if (requireRenderable) {
+ testFailed(formatString + " render targets not supported.");
+ } else {
+ debug(formatString + " render targets not supported -- this is legal");
+ }
+ return;
+ }
+
+ var renderProgram =
+ wtu.setupProgram(gl,
+ [wtu.simpleVertexShader, "floatingPointFragmentShader"],
+ ['vPosition'],
+ [0]);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Rendering to half floating point texture should succeed");
+ }
+
+ // Now sample from the half floating-point texture and verify we got the correct values.
+ var texturedShaders = [
+ wtu.simpleTextureVertexShader,
+ "testFragmentShader"
+ ];
+ var testProgram =
+ wtu.setupProgram(gl,
+ [wtu.simpleTextureVertexShader, "testFragmentShader"],
+ ['vPosition', 'texCoord0'],
+ [0, 1]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.useProgram(testProgram);
+ gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from half floating point texture should succeed");
+ checkRenderingResults();
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ ext = null;
+ gl.getExtension("OES_texture_half_float").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("OES_texture_half_float").myProperty', '2');
+}
+
+// Make sure we can call readPixels with the passed in arrayBufferConstructor and that the color
+// channels are the ones we expect. If there is a mismatch between the glType and arrayBuffer type,
+// fail the test.
+function verifyReadPixelsColors(red, green, blue, alpha, alphaRGB, glFormat, glType, arrayBufferConstructor) {
+ var typeName = wtu.glEnumToString(gl, glType);
+
+ debug(wtu.glEnumToString(gl, glFormat) + " framebuffer with " + typeName + " readback.");
+
+ var arrayBuffer = new arrayBufferConstructor(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should return NO_ERROR when reading " + typeName + " data.");
+
+ assertMsg(arrayBuffer[0] === red, "Red channel should be " + red + " for " + typeName + " readPixels. Received: " + arrayBuffer[0]);
+ assertMsg(arrayBuffer[1] === green, "Green channel should be " + green + " for " + typeName + " readPixels. Received: " + arrayBuffer[1]);
+ assertMsg(arrayBuffer[2] === blue, "Blue channel should be " + blue + " for " + typeName + " readPixels. Received: " + arrayBuffer[2]);
+ if (glFormat === gl.RGBA) {
+ assertMsg(arrayBuffer[3] === alpha, "Alpha channel should be " + alpha + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]);
+ } else if (glFormat === gl.RGB) {
+ assertMsg(arrayBuffer[3] === alphaRGB, "Alpha channel should be " + alphaRGB + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]);
+ }
+
+ // Make sure any arrayBuffer types that are not equal to arrayBufferConstructor fail readPixels.
+ if (arrayBufferConstructor !== Uint8Array) {
+ arrayBuffer = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint8Array.toString());
+ }
+ if (arrayBufferConstructor !== Float32Array) {
+ arrayBuffer = new Float32Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Float32Array.toString());
+ }
+ if (arrayBufferConstructor !== Uint16Array) {
+ arrayBuffer = new Uint16Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint16Array.toString());
+ }
+}
+
+// Verify that half float textures attached to frame buffers function correctly with regard to framebuffer
+// completness, IMPLEMENTATION_COLOR_READ_FORMAT/TYPE and readPixels
+function runFramebufferTest() {
+ debug("");
+ debug("Framebuffer Tests");
+
+ var texture = allocateTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ debug("Ensure non-color-renderable formats [LUMINANCE, LUMINANCE_ALPHA, ALPHA] fail.");
+ var arrayBufferFloatOutput = new Float32Array(4); // 4 color channels
+ [gl.LUMINANCE, gl.LUMINANCE_ALPHA, gl.ALPHA].forEach(function(badFormat) {
+ debug(wtu.glEnumToString(gl, badFormat) + " framebuffer");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, badFormat, 1, 1, 0, badFormat, ext.HALF_FLOAT_OES, null);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+
+ shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_FORMAT should fail for incomplete framebuffers.");
+
+ shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_TYPE should fail for incomplete framebuffers.");
+
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, arrayBufferFloatOutput);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION , "readPixels should fail on incomplete framebuffers.");
+ debug("");
+ });
+
+ debug("Ensure color renderable formats [RGBA, RGB] succeed.");
+ var arrayBufferHalfFloatInput = new Uint16Array(4); // 4 color channels
+ arrayBufferHalfFloatInput[0] = 0; // 0 in half float
+ arrayBufferHalfFloatInput[1] = 0x3400; // 0.25 in half float
+ arrayBufferHalfFloatInput[2] = 0x3800; // 0.50 in half float
+ arrayBufferHalfFloatInput[3] = 0x3A00; // 0.75 in half float
+
+ [gl.RGBA, gl.RGB].forEach(function(goodFormat) {
+ debug(wtu.glEnumToString(gl, goodFormat) + " framebuffer tests");
+ debug("");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, goodFormat, 1, 1, 0, goodFormat, ext.HALF_FLOAT_OES, arrayBufferHalfFloatInput);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // Per the OES_color_buffer_half_float, RGBA/FLOAT should always succeed for readPixels
+ verifyReadPixelsColors(
+ 0.00, // red
+ 0.25, // green
+ 0.50, // blue
+ 0.75, // alpha
+ 1.0, // alphaRGB
+ goodFormat,
+ gl.FLOAT,
+ Float32Array);
+
+ var implementationColorReadFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
+ assertMsg(implementationColorReadFormat === gl.RGBA || implementationColorReadFormat === gl.RGB,
+ "IMPLEMENTATION_COLOR_READ_FORMAT should be color renderable: RGBA or RGB. Received: " + wtu.glEnumToString(gl, implementationColorReadFormat));
+
+ var implementationColorReadType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
+
+ // There is nothing in the specifications that keeps the
+ // implementation color read format and type from being the
+ // same as the implicitly supported one. For this reason, keep
+ // gl.FLOAT as one of the valid options.
+ assertMsg(implementationColorReadType === gl.UNSIGNED_BYTE ||
+ implementationColorReadType === gl.FLOAT ||
+ implementationColorReadType === ext.HALF_FLOAT_OES ||
+ implementationColorReadType === gl.UNSIGNED_SHORT_4_4_4_4 ||
+ implementationColorReadType === gl.UNSIGNED_SHORT_5_5_5_1 ||
+ implementationColorReadType === gl.UNSIGNED_SHORT_5_6_5,
+ "IMPLEMENTATION_COLOR_READ_TYPE must be one of UNSIGNED_BYTE, UNSIGNED_SHORT_4_4_4_4, UNSIGNED_SHORT_5_5_5_1, UNSIGNED_SHORT_5_6_5, FLOAT, or HALF_FLOAT_OES. " +
+ "Received: " + wtu.glEnumToString(gl, implementationColorReadType));
+
+ // Test the RGBA/HALF_FLOAT_OES combination
+ if (implementationColorReadFormat === gl.RGBA && implementationColorReadType === ext.HALF_FLOAT_OES) {
+ verifyReadPixelsColors(
+ 0, // red
+ 0x3400, // green
+ 0x3800, // blue
+ 0x3A00, // alpha
+ 0x3C00, // alphaRGB
+ goodFormat,
+ ext.HALF_FLOAT_OES,
+ Uint16Array);
+ }
+ }
+ debug("");
+ });
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object-bufferData.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object-bufferData.html
new file mode 100644
index 0000000000..d89e9bcc1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object-bufferData.html
@@ -0,0 +1,194 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_vertex_array_object_bufferData Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<!-- comment in the script tag below to test through JS emualation of the extension. -->
+<!--
+<script src="../../../demos/google/resources/OESVertexArrayObject.js"></script>
+-->
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+attribute vec4 a_color;
+varying vec4 v_color;
+void main(void) {
+ gl_Position = a_position;
+ v_color = a_color;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main(void) {
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+description("This test verifies drawing results when using gl.bufferData with the OES_vertex_array_object extension.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var vao = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Setup emulated OESVertexArrayObject if it has been included.
+ if (window.setupVertexArrayObject) {
+ debug("using emuated OES_vertex_array_object");
+ setupVertexArrayObject(gl);
+ }
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("OES_vertex_array_object");
+ if (!ext) {
+ testPassed("No OES_vertex_array_object support -- this is legal");
+
+ } else {
+ testPassed("Successfully enabled OES_vertex_array_object extension");
+
+ runBufferDataTest();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+/**
+ * The OES_vertex_array_object extension seems to work incorrectly on some handheld devices,
+ * namely the Nexus 5, and Nexus 7 (in 2014/01) when using bufferData before binding the VAO.
+ * The tested OS was Android KitKat 4.4.2, the effects were the same in all tested browsers
+ * (Chrome, Chrome Beta, Firefox, Firefox Beta), so it is likely a driver bug.
+ * These devices have the similar Adreno 320 and Adreno 330 GPUs respectively.
+ *
+ * The issuse resulted from this sequence of actions in a requestAnimationFrame loop:
+ * 1. upload some vertex buffers with gl.bufferData (eg. colors)
+ * 2. bind the VAO
+ * 3. clear the canvas
+ * 4. draw (some triangles) to the canvas
+ * 5. unbind the VAO
+ *
+ * This caused the drawn triangles to be drawn with black (0) for most of the frames, with some
+ * rare frames presenting the correct render results. Interestingly on both devices exactly every
+ * 64th frame passed (starting with the very first one), the others failed.
+ * (Because of this, we test multiple frames.)
+ * When positions were uploaded, seemingly nothing was drawn, that's likely because the
+ * position buffer was also all 0s.
+ *
+ * The issue did not occur:
+ * - if step 1. and 2. were swapped
+ * - or if step5 was ommited (probably because that makes step 2 a no-op since the VAO is bound)
+ */
+function runBufferDataTest() {
+ debug("Testing draws with bufferData");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var testColor = [0, 255, 0, 255];
+ var clearColor = [255, 0, 0, 255];
+
+ // Where the issue occures, this is the sequence of success/failure every time:
+ // result: success fail fail fail fail ... success fail fail ...
+ // currentTestCount: 0 1 2 3 4 ... 64 65 66 ...
+ // So with just 1 test it passes, but 2 tests are enough. Here we use 3.
+ var numberOfTests = 3;
+ var currentTestCount = 0;
+
+ var positionLoc = 0;
+ var colorLoc = 1;
+ var gridRes = 1;
+
+ var program = wtu.setupSimpleVertexColorProgram(gl, positionLoc, colorLoc);
+
+ var vao0 = ext.createVertexArrayOES();
+ ext.bindVertexArrayOES(vao0);
+
+ var buffers = wtu.setupIndexedQuadWithOptions(gl,
+ { gridRes: gridRes,
+ positionLocation: positionLoc
+ });
+
+ var colorTypedArray = createColorTypedArray();
+
+ var colorBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+
+ ext.bindVertexArrayOES(null);
+
+ testDrawing();
+
+ function testDrawing() {
+ // this order works fine:
+ // ext.bindVertexArrayOES(vao0);
+ // uploadColor();
+
+ // this order doesn't:
+ uploadColor();
+ ext.bindVertexArrayOES(vao0);
+
+ wtu.clearAndDrawIndexedQuad(gl, 1, clearColor);
+
+ ext.bindVertexArrayOES(null);
+
+ //debug("<span>"+currentTestCount+"</span");
+ wtu.checkCanvas(gl, testColor, "should be green")
+
+ if (++currentTestCount < numberOfTests) {
+ testDrawing();
+ // wtu.requestAnimFrame(testDrawing);
+ } else {
+ // clean up
+ ext.deleteVertexArrayOES(vao0);
+ }
+ }
+
+ function uploadColor() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colorTypedArray, gl.STREAM_DRAW);
+ }
+
+ function createColorTypedArray() {
+ var colors = [];
+ var pOffset = 0;
+ for (var yy = 0; yy <= gridRes; ++yy) {
+ for (var xx = 0; xx <= gridRes; ++xx) {
+ colors[pOffset + 0] = testColor[0];
+ colors[pOffset + 1] = testColor[1];
+ colors[pOffset + 2] = testColor[2];
+ colors[pOffset + 3] = testColor[3];
+ pOffset += 4;
+ }
+ }
+ return new Float32Array(colors);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object.html
new file mode 100644
index 0000000000..4d544aeade
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object.html
@@ -0,0 +1,780 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_vertex_array_object Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<!-- comment in the script tag below to test through JS emulation of the extension. -->
+<!--
+<script src="../../../demos/google/resources/OESVertexArrayObject.js"></script>
+-->
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+attribute vec4 a_color;
+varying vec4 v_color;
+void main(void) {
+ gl_Position = a_position;
+ v_color = a_color;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main(void) {
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of the OES_vertex_array_object extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var vao = null;
+
+var contextA;
+var contextB;
+var extA;
+var extB;
+var vertexArrayA;
+var vertexArrayB;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Setup emulated OESVertexArrayObject if it has been included.
+ if (window.setupVertexArrayObject) {
+ debug("using emulated OES_vertex_array_object");
+ setupVertexArrayObject(gl);
+ }
+
+ // Run tests with extension disabled
+ runBindingTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("OES_vertex_array_object");
+ if (!ext) {
+ testPassed("No OES_vertex_array_object support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled OES_vertex_array_object extension");
+
+ runSupportedTest(true);
+ runBindingTestEnabled();
+ runObjectTest();
+ runAttributeTests();
+ runAttributeValueTests();
+ runDrawTests();
+ runUnboundDeleteTests();
+ runBoundDeleteTests();
+ runArrayBufferBindTests();
+ runInvalidContextTests();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("OES_vertex_array_object") >= 0) {
+ if (extensionEnabled) {
+ testPassed("OES_vertex_array_object listed as supported and getExtension succeeded");
+ } else {
+ testFailed("OES_vertex_array_object listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("OES_vertex_array_object not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("OES_vertex_array_object not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runBindingTestDisabled() {
+ debug("");
+ debug("Testing binding enum with extension disabled");
+
+ // Use the constant directly as we don't have the extension
+ var VERTEX_ARRAY_BINDING_OES = 0x85B5;
+
+ gl.getParameter(VERTEX_ARRAY_BINDING_OES);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "VERTEX_ARRAY_BINDING_OES should not be queryable if extension is disabled");
+}
+
+function runBindingTestEnabled() {
+ debug("");
+ debug("Testing binding enum with extension enabled");
+
+ shouldBe("ext.VERTEX_ARRAY_BINDING_OES", "0x85B5");
+
+ gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "VERTEX_ARRAY_BINDING_OES query should succeed if extension is enabled");
+
+ // Default value is null
+ if (gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) === null) {
+ testPassed("Default value of VERTEX_ARRAY_BINDING_OES is null");
+ } else {
+ testFailed("Default value of VERTEX_ARRAY_BINDING_OES is not null");
+ }
+
+ debug("");
+ debug("Testing binding a VAO");
+ var vao0 = ext.createVertexArrayOES();
+ var vao1 = ext.createVertexArrayOES();
+ shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
+ ext.bindVertexArrayOES(vao0);
+ if (gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) == vao0) {
+ testPassed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is expected VAO");
+ } else {
+ testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO")
+ }
+ ext.bindVertexArrayOES(vao1);
+ if (gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) == vao1) {
+ testPassed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is expected VAO");
+ } else {
+ testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO")
+ }
+ ext.deleteVertexArrayOES(vao1);
+ shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
+ ext.bindVertexArrayOES(vao1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted vertex array object");
+ ext.bindVertexArrayOES(null);
+ shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
+ ext.deleteVertexArrayOES(vao1);
+}
+
+function runObjectTest() {
+ debug("");
+ debug("Testing object creation");
+
+ vao = ext.createVertexArrayOES();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createVertexArrayOES should not set an error");
+ shouldBeNonNull("vao");
+
+ // Expect false if never bound
+ shouldBeFalse("ext.isVertexArrayOES(vao)");
+ ext.bindVertexArrayOES(vao);
+ shouldBeTrue("ext.isVertexArrayOES(vao)");
+ ext.bindVertexArrayOES(null);
+ shouldBeTrue("ext.isVertexArrayOES(vao)");
+
+ shouldBeFalse("ext.isVertexArrayOES(null)");
+
+ ext.deleteVertexArrayOES(vao);
+ vao = null;
+}
+
+function runAttributeTests() {
+ debug("");
+ debug("Testing attributes work across bindings");
+
+ var states = [];
+
+ var attrCount = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+ for (var n = 0; n < attrCount; n++) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+
+ var state = {};
+ states.push(state);
+
+ var vao = state.vao = ext.createVertexArrayOES();
+ ext.bindVertexArrayOES(vao);
+
+ var enableArray = (n % 2 == 0);
+ if (enableArray) {
+ gl.enableVertexAttribArray(n);
+ } else {
+ gl.disableVertexAttribArray(n);
+ }
+
+ if (enableArray) {
+ var buffer = state.buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(n, 1 + n % 4, gl.FLOAT, true, n * 4, n * 4);
+ }
+
+ if (enableArray) {
+ var elbuffer = state.elbuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elbuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
+ }
+
+ ext.bindVertexArrayOES(null);
+ }
+
+ var anyMismatch = false;
+ for (var n = 0; n < attrCount; n++) {
+ var state = states[n];
+
+ ext.bindVertexArrayOES(state.vao);
+
+ var shouldBeEnabled = (n % 2 == 0);
+ var isEnabled = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
+ if (shouldBeEnabled != isEnabled) {
+ testFailed("VERTEX_ATTRIB_ARRAY_ENABLED not preserved");
+ anyMismatch = true;
+ }
+
+ var buffer = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ if (shouldBeEnabled) {
+ if (buffer == state.buffer) {
+ // Matched
+ if ((gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_SIZE) == 1 + n % 4) &&
+ (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_TYPE) == gl.FLOAT) &&
+ (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED) == true) &&
+ (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_STRIDE) == n * 4) &&
+ (gl.getVertexAttribOffset(n, gl.VERTEX_ATTRIB_ARRAY_POINTER) == n * 4)) {
+ // Matched
+ } else {
+ testFailed("VERTEX_ATTRIB_ARRAY_* not preserved");
+ anyMismatch = true;
+ }
+ } else {
+ testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ } else {
+ // GL_CURRENT_VERTEX_ATTRIB is not preserved
+ if (buffer) {
+ testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ }
+
+ var elbuffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
+ if (shouldBeEnabled) {
+ if (elbuffer == state.elbuffer) {
+ // Matched
+ } else {
+ testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ } else {
+ if (elbuffer == null) {
+ // Matched
+ } else {
+ testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ }
+ }
+ ext.bindVertexArrayOES(null);
+ if (!anyMismatch) {
+ testPassed("All attributes preserved across bindings");
+ }
+
+ for (var n = 0; n < attrCount; n++) {
+ var state = states[n];
+ ext.deleteVertexArrayOES(state.vao);
+ }
+}
+
+function runAttributeValueTests() {
+ debug("");
+ debug("Testing that attribute values are not attached to bindings");
+
+ var v;
+ var vao0 = ext.createVertexArrayOES();
+ var anyFailed = false;
+
+ ext.bindVertexArrayOES(null);
+ gl.vertexAttrib4f(0, 0, 1, 2, 3);
+
+ v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
+ if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) {
+ testFailed("Vertex attrib value not round-tripped?");
+ anyFailed = true;
+ }
+
+ ext.bindVertexArrayOES(vao0);
+
+ v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
+ if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) {
+ testFailed("Vertex attrib value reset across bindings");
+ anyFailed = true;
+ }
+
+ gl.vertexAttrib4f(0, 4, 5, 6, 7);
+ ext.bindVertexArrayOES(null);
+
+ v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
+ if (!(v[0] == 4 && v[1] == 5 && v[2] == 6 && v[3] == 7)) {
+ testFailed("Vertex attrib value bound to buffer");
+ anyFailed = true;
+ }
+
+ if (!anyFailed) {
+ testPassed("Vertex attribute values are not attached to bindings")
+ }
+
+ ext.bindVertexArrayOES(null);
+ ext.deleteVertexArrayOES(vao0);
+}
+
+function runDrawTests() {
+ debug("");
+ debug("Testing draws with various VAO bindings");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var vao0 = ext.createVertexArrayOES();
+ var vao1 = ext.createVertexArrayOES();
+ var vao2 = ext.createVertexArrayOES();
+
+ var positionLocation = 0;
+ var colorLocation = 1;
+
+ var program = wtu.setupSimpleVertexColorProgram(gl, positionLocation, colorLocation);
+
+ function setupQuad(s, colorsInArray) {
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0 * s, 1.0 * s, 0.0,
+ -1.0 * s, 1.0 * s, 0.0,
+ -1.0 * s, -1.0 * s, 0.0,
+ 1.0 * s, 1.0 * s, 0.0,
+ -1.0 * s, -1.0 * s, 0.0,
+ 1.0 * s, -1.0 * s, 0.0]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(positionLocation);
+ gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+
+ // Test switching between VAOs that have different number of enabled arrays
+ if (colorsInArray) {
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0, 1.0]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(colorLocation);
+ gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
+ } else {
+ gl.disableVertexAttribArray(colorLocation);
+ }
+ };
+
+ function verifyDiagonalPixels(s, expectedInside, drawDescription) {
+ // Tests pixels along a diagonal running from the center of the canvas to the (0, 0) corner.
+ // Values on the points list indicate relative position along this diagonal.
+ var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
+ for (var n = 0; n < points.length; n++) {
+ var expected = points[n] <= s ? expectedInside : 255;
+ var x = Math.round((1 - points[n]) * canvas.width / 2);
+ var y = Math.round((1 - points[n]) * canvas.height / 2);
+ wtu.checkCanvasRect(gl, x, y, 1, 1, [expected, expected, expected, 255],
+ "Drawing " + drawDescription + " should pass", 2);
+ }
+ };
+ function verifyDraw(drawDescription, s, colorsInArray) {
+ wtu.clearAndDrawUnitQuad(gl);
+ var expectedInside = colorsInArray ? 0 : 128;
+ verifyDiagonalPixels(s, expectedInside, drawDescription);
+ };
+
+ // Setup all bindings
+ setupQuad(1, true);
+ ext.bindVertexArrayOES(vao0);
+ setupQuad(0.5, true);
+ ext.bindVertexArrayOES(vao1);
+ setupQuad(0.25, true);
+ ext.bindVertexArrayOES(vao2);
+ setupQuad(0.75, false);
+
+ gl.vertexAttrib4f(colorLocation, 0.5, 0.5, 0.5, 1);
+
+ // Verify drawing
+ ext.bindVertexArrayOES(null);
+ verifyDraw("with the default VAO", 1, true);
+ ext.bindVertexArrayOES(vao0);
+ verifyDraw("with VAO #0", 0.5, true);
+ ext.bindVertexArrayOES(vao1);
+ verifyDraw("with VAO #1", 0.25, true);
+ ext.bindVertexArrayOES(vao2);
+ verifyDraw("with VAO that has the color array disabled", 0.75, false);
+
+ // Verify bound VAO after delete
+ ext.bindVertexArrayOES(vao1);
+ ext.deleteVertexArrayOES(vao0);
+ verifyDraw("after deleting another VAO", 0.25, true);
+ ext.deleteVertexArrayOES(vao1);
+ verifyDraw("after deleting the VAO that was bound", 1, true);
+
+ // Disable global vertex attrib array
+ gl.disableVertexAttribArray(positionLocation);
+ gl.disableVertexAttribArray(colorLocation);
+
+ // Check that constant values are treated correctly as not being part of VAO state.
+ var positionLoc = 0;
+ var colorLoc = 1;
+ var gridRes = 1;
+ wtu.setupIndexedQuad(gl, gridRes, positionLoc);
+ // Set the vertex color to red.
+ gl.vertexAttrib4f(colorLoc, 1, 0, 0, 1);
+
+ var vao0 = ext.createVertexArrayOES();
+ ext.bindVertexArrayOES(vao0);
+ var program = wtu.setupSimpleVertexColorProgram(gl, positionLoc, colorLoc);
+ wtu.setupIndexedQuad(gl, gridRes, positionLoc);
+ // Set the vertex color to green.
+ gl.vertexAttrib4f(colorLoc, 0, 1, 0, 1);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ ext.deleteVertexArrayOES(vao0);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function runUnboundDeleteTests() {
+ debug("");
+ debug("Testing using buffers that are deleted when attached to unbound VAOs");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+ gl.useProgram(program);
+
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]),
+ gl.STATIC_DRAW);
+
+ var colors = [
+ [255, 0, 0, 255],
+ [ 0, 255, 0, 255],
+ [ 0, 0, 255, 255],
+ [ 0, 255, 255, 255]
+ ];
+ var colorBuffers = [];
+ var elementBuffers = [];
+ var vaos = [];
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var vao = ext.createVertexArrayOES();
+ vaos.push(vao);
+ ext.bindVertexArrayOES(vao);
+ // Set the position buffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var elementBuffer = gl.createBuffer();
+ elementBuffers.push(elementBuffer);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 0, 2, 3]),
+ gl.STATIC_DRAW);
+
+ // Setup the color attrib
+ var color = colors[ii];
+ if (ii < 3) {
+ var colorBuffer = gl.createBuffer();
+ colorBuffers.push(colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3]
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ } else {
+ gl.vertexAttrib4f(1, color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
+ }
+ }
+
+ // delete the color buffers AND the position buffer.
+ ext.bindVertexArrayOES(null);
+ for (var ii = 0; ii < colorBuffers.length; ++ii) {
+ gl.deleteBuffer(colorBuffers[ii]);
+ gl.deleteBuffer(elementBuffers[ii]);
+ ext.bindVertexArrayOES(vaos[ii]);
+ var boundBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ // The buffers should still be valid at this point, since it was attached to the VAO
+ if(boundBuffer != colorBuffers[ii]) {
+ testFailed("buffer removed even though it is still attached to a VAO");
+ }
+ }
+
+ ext.bindVertexArrayOES(null);
+ gl.deleteBuffer(positionBuffer);
+
+ // Render with the deleted buffers. As they are referenced by VAOs they
+ // must still be around.
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var color = colors[ii];
+ ext.bindVertexArrayOES(vaos[ii]);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, color, "should be " + color);
+ }
+
+ // Clean up.
+ for (var ii = 0; ii < colorBuffers.length; ++ii) {
+ ext.deleteVertexArrayOES(vaos[ii]);
+ }
+
+ for (var ii = 0; ii < colorBuffers.length; ++ii) {
+ // The buffers should no longer be valid now that the VAOs are deleted
+ if(gl.isBuffer(colorBuffers[ii])) {
+ testFailed("buffer not properly cleaned up after VAO deletion");
+ }
+ }
+}
+
+function runBoundDeleteTests() {
+ debug("Testing using buffers that are deleted when attached to bound VAOs");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+ gl.useProgram(program);
+
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]),
+ gl.STATIC_DRAW);
+
+ // Setup the color attrib
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 0, 255, 255,
+ 0, 255, 255, 255
+ ]), gl.STATIC_DRAW);
+
+ var vaos = [];
+ var elementBuffers = [];
+ for (var ii = 0; ii < 4; ++ii) {
+ var vao = ext.createVertexArrayOES();
+ vaos.push(vao);
+ ext.bindVertexArrayOES(vao);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var elementBuffer = gl.createBuffer();
+ elementBuffers.push(elementBuffer);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 0, 2, 3]),
+ gl.STATIC_DRAW);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ }
+
+ // delete the color buffers AND the position buffer, that are bound to the current VAO
+ for (var ii = 0; ii < vaos.length; ++ii) {
+ ext.bindVertexArrayOES(vaos[ii]);
+
+ gl.deleteBuffer(colorBuffer);
+ gl.deleteBuffer(positionBuffer);
+
+ // After the first iteration, deleteBuffer will be a no-op, and will not unbind its matching
+ // bind points on the now-bound VAO like it did on the first iteration.
+ var expectRetained = (ii != 0);
+ var shouldBeStr = (expectRetained ? "retained" : "cleared");
+
+ var boundPositionBuffer = gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ if (expectRetained != (boundPositionBuffer == positionBuffer)) {
+ testFailed("Position attrib stored buffer should be " + shouldBeStr + ".");
+ }
+
+ var boundColorBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ if (expectRetained != (boundColorBuffer == colorBuffer)) {
+ testFailed("Color attrib stored buffer should be " + shouldBeStr + ".");
+ }
+
+ // If retained, everything should still work. If cleared, drawing should now fail.
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ var expectedError = (expectRetained ? gl.NO_ERROR : gl.INVALID_OPERATION);
+ wtu.glErrorShouldBe(gl, expectedError,
+ "Draw call should " + (expectRetained ? "not " : "") + "fail.");
+
+ if (gl.isBuffer(positionBuffer)) {
+ testFailed("References from unbound VAOs don't keep Position buffer alive.");
+ }
+ if (gl.isBuffer(colorBuffer)) {
+ testFailed("References from unbound VAOs don't keep Color buffer alive");
+ }
+ }
+}
+
+function runArrayBufferBindTests() {
+ debug("");
+ debug("Testing that buffer bindings on VAOs don't affect default VAO ARRAY_BUFFER binding.");
+
+ ext.bindVertexArrayOES(null);
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_color", "a_position"]);
+ gl.useProgram(program);
+
+ // create shared element buffer
+ var elementBuffer = gl.createBuffer();
+ // bind to default
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 0, 2, 3]),
+ gl.STATIC_DRAW);
+
+ // first create the buffers for no VAO draw.
+ var nonVAOColorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ ]), gl.STATIC_DRAW);
+
+ // shared position buffer.
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]),
+ gl.STATIC_DRAW);
+
+ // attach position buffer to default
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ // now create VAO
+ var vao = ext.createVertexArrayOES();
+ ext.bindVertexArrayOES(vao);
+
+ // attach the position buffer VAO
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ var vaoColorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vaoColorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+
+ // now set the buffer back to the nonVAOColorBuffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer);
+
+ // bind to VAO
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+ // unbind VAO
+ ext.bindVertexArrayOES(null);
+
+ // At this point the nonVAOColorBuffer should be still be bound.
+ // If the WebGL impl is emulating VAOs it must make sure
+ // it correctly restores this binding.
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function runInvalidContextTests() {
+ contextA = wtu.create3DContext(undefined, undefined, 1);
+ contextB = wtu.create3DContext(undefined, undefined, 1);
+ extA = contextA.getExtension("OES_vertex_array_object");
+ extB = contextB.getExtension("OES_vertex_array_object");
+ vertexArrayA = extA.createVertexArrayOES();
+ vertexArrayB = extB.createVertexArrayOES();
+
+ wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "extA.bindVertexArrayOES(vertexArrayA)");
+ wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "extA.bindVertexArrayOES(null)");
+ wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "extB.bindVertexArrayOES(vertexArrayB)");
+ wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "extB.bindVertexArrayOES(null)");
+
+ debug("")
+ debug("State queries validate context");
+ shouldBeFalse("extA.isVertexArrayOES(vertexArrayB)");
+ wtu.glErrorShouldBe(contextA, gl.NO_ERROR, "there should be no errors from invalid request");
+ shouldBeFalse("extB.isVertexArrayOES(vertexArrayA)");
+ wtu.glErrorShouldBe(contextB, gl.NO_ERROR, "there should be no errors from invalid request");
+ shouldBeTrue("extA.isVertexArrayOES(vertexArrayA)");
+ wtu.glErrorShouldBe(contextA, gl.NO_ERROR, "there should be no errors from valid request");
+ shouldBeTrue("extB.isVertexArrayOES(vertexArrayB)");
+ wtu.glErrorShouldBe(contextB, gl.NO_ERROR, "there should be no errors from valid request");
+
+ debug("")
+ debug("Deleting an object from another context generates an error");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "extA.deleteVertexArrayOES(vertexArrayB)");
+ wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "extB.deleteVertexArrayOES(vertexArrayA)");
+
+ debug("")
+ debug("Invalid delete operations do not delete");
+ shouldBeTrue("extA.isVertexArrayOES(vertexArrayA)");
+ shouldBeTrue("extB.isVertexArrayOES(vertexArrayB)");
+
+ debug("")
+ debug("Cannot bind VAOs from other contexts");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "extA.bindVertexArrayOES(vertexArrayB)");
+ wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "extB.bindVertexArrayOES(vertexArrayA)");
+
+ debug("")
+ debug("Context checks happen even for deleted objects");
+ wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "extA.deleteVertexArrayOES(vertexArrayA)");
+ wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "extB.deleteVertexArrayOES(vertexArrayB)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "extA.deleteVertexArrayOES(vertexArrayB)");
+ wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "extB.deleteVertexArrayOES(vertexArrayA)");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/s3tc-and-rgtc.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/s3tc-and-rgtc.html
new file mode 100644
index 0000000000..3b725ffe22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/s3tc-and-rgtc.html
@@ -0,0 +1,1066 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+<title>WebGL WEBGL_compressed_texture_s3tc and EXT_texture_compression_rgtc Conformance Tests</title>
+<style>
+img {
+ border: 1px solid black;
+ margin-right: 1em;
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available. It also tests the related formats from the EXT_texture_compression_rgtc extension.");
+
+debug("");
+
+// Acceptable interpolation error depends on endpoints:
+// 1.0 / 255.0 + 0.03 * max(abs(endpoint0 - endpoint1), abs(endpoint0_p - endpoint1_p))
+// For simplicity, assume the worst case (e0 is 0.0, e1 is 1.0). After conversion to unorm8, it is 9.
+const DEFAULT_COLOR_ERROR = 9;
+
+/*
+BC1 (DXT1) block
+e0 = [ 0, 255, 0]
+e1 = [255, 0, 0]
+e0 < e1, so it uses 3-color mode
+
+local palette
+ 0: [ 0, 255, 0, 255]
+ 1: [255, 0, 0, 255]
+ 2: [128, 128, 0, 255]
+ 3: [ 0, 0, 0, 255] // for BC1 RGB
+ 3: [ 0, 0, 0, 0] // for BC1 RGBA
+selectors
+ 3 2 1 0
+ 2 2 1 0
+ 1 1 1 0
+ 0 0 0 0
+
+Extending this block with opaque alpha and uploading as BC2 or BC3
+will generate wrong colors because BC2 and BC3 do not have 3-color mode.
+*/
+var img_4x4_rgba_dxt1 = new Uint8Array([
+ 0xE0, 0x07, 0x00, 0xF8, 0x1B, 0x1A, 0x15, 0x00
+]);
+
+/*
+BC2 (DXT3) block
+
+Quantized alpha values
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 A B
+ C D E F
+
+RGB block
+e0 = [255, 0, 0]
+e1 = [ 0, 255, 0]
+BC2 has only 4-color mode
+
+local palette
+ 0: [255, 0, 0]
+ 1: [ 0, 255, 0]
+ 2: [170, 85, 0]
+ 3: [ 85, 170, 0]
+selectors
+ 0 1 2 3
+ 1 1 2 3
+ 2 2 2 3
+ 3 3 3 3
+*/
+var img_4x4_rgba_dxt3 = new Uint8Array([
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ 0x00, 0xF8, 0xE0, 0x07, 0xE4, 0xE5, 0xEA, 0xFF
+]);
+
+/*
+BC3 (DXT5) block
+
+Alpha block (aka DXT5A)
+e0 = 255
+e1 = 0
+e0 > e1, so using 6 intermediate points
+local palette
+ 255, 0, 219, 182, 146, 109, 73, 36
+selectors
+ 0 1 2 3
+ 1 2 3 4
+ 2 3 4 5
+ 3 4 5 6
+
+RGB block
+e0 = [255, 0, 0]
+e1 = [ 0, 255, 0]
+BC3 has only 4-color mode
+
+local palette
+ 0: [255, 0, 0]
+ 1: [ 0, 255, 0]
+ 2: [170, 85, 0]
+ 3: [ 85, 170, 0]
+selectors
+ 3 2 1 0
+ 3 2 1 1
+ 3 2 2 2
+ 3 3 3 3
+*/
+var img_4x4_rgba_dxt5 = new Uint8Array([
+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x00, 0xF8, 0xE0, 0x07, 0x1B, 0x5B, 0xAB, 0xFF
+]);
+
+// BC4 - just the alpha block from BC3 above, interpreted as the red channel.
+// See http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/#bc4
+// for format details.
+var img_4x4_r_bc4 = new Uint8Array([
+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+]);
+
+// BC5 - Two BC3 alpha blocks, interpreted as the red and green channels.
+var img_4x4_rg_bc5 = new Uint8Array([
+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x00, 0xFF, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+]);
+
+// Signed BC4 - change endpoints to use full -1 to 1 range.
+var img_4x4_signed_r_bc4 = new Uint8Array([
+ 0x7F, 0x80, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+]);
+
+// Signed BC5 - Two BC3 alpha blocks, interpreted as the red and green channels.
+var img_4x4_signed_rg_bc5 = new Uint8Array([
+ 0x7F, 0x80, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x80, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+]);
+
+
+/*
+8x8 block endpoints use half-intensity values (appear darker than 4x4)
+*/
+var img_8x8_rgba_dxt1 = new Uint8Array([
+ 0xe0,0x03,0x00,0x78,0x13,0x10,0x15,0x00,
+ 0x0f,0x00,0xe0,0x7b,0x11,0x10,0x15,0x00,
+ 0xe0,0x03,0x0f,0x78,0x44,0x45,0x40,0x55,
+ 0x0f,0x00,0xef,0x03,0x44,0x45,0x40,0x55
+]);
+var img_8x8_rgba_dxt3 = new Uint8Array([
+ 0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0x78,0xe0,0x03,0x44,0x45,0x40,0x55,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x7b,0x0f,0x00,0x44,0x45,0x40,0x55,
+ 0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x03,0x0f,0x00,0x11,0x10,0x15,0x00
+]);
+var img_8x8_rgba_dxt5 = new Uint8Array([
+ 0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x78,0xe0,0x03,0x44,0x45,0x40,0x55,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x7b,0x0f,0x00,0x44,0x45,0x40,0x55,
+ 0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x03,0xef,0x00,0x11,0x10,0x15,0x00
+]);
+var img_8x8_r_bc4 = new Uint8Array([
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+]);
+var img_8x8_rg_bc5 = new Uint8Array([
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+]);
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var program = wtu.setupTexturedQuad(gl);
+var ext = null;
+var ext_rgtc = {};
+var vao = null;
+var validFormats = {
+ COMPRESSED_RGB_S3TC_DXT1_EXT : 0x83F0,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT : 0x83F1,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT : 0x83F2,
+ COMPRESSED_RGBA_S3TC_DXT5_EXT : 0x83F3,
+};
+var name;
+var supportedFormats;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc");
+ if (!ext) {
+ testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal");
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", false);
+ } else {
+ testPassed("Successfully enabled WEBGL_compressed_texture_s3tc extension");
+
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", true);
+ runTestExtension();
+ }
+ ext_rgtc = wtu.getExtensionWithKnownPrefixes(gl, "EXT_texture_compression_rgtc");
+ if (ext_rgtc) {
+ ext = ext || {};
+ // Make ctu.formatToString work for rgtc enums.
+ for (const name in ext_rgtc)
+ ext[name] = ext_rgtc[name];
+ runTestRGTC();
+ }
+}
+
+function expectedByteLength(width, height, format) {
+ if (format == validFormats.COMPRESSED_RGBA_S3TC_DXT3_EXT || format == validFormats.COMPRESSED_RGBA_S3TC_DXT5_EXT) {
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
+ }
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
+}
+
+function getBlockDimensions(format) {
+ return {width: 4, height: 4};
+}
+
+function runTestExtension() {
+ debug("");
+ debug("Testing WEBGL_compressed_texture_s3tc");
+
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(ext, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+
+ // Test each format
+ testDXT1_RGB();
+ testDXT1_RGBA();
+ testDXT3_RGBA();
+ testDXT5_RGBA();
+
+ // Test compressed PBOs with a single format
+ if (contextVersion >= 2) {
+ testDXT5_RGBA_PBO();
+ }
+
+ // Test TexImage validation on level dimensions combinations.
+ debug("");
+ debug("When level equals 0, width and height must be a multiple of 4.");
+ debug("When level is larger than 0, this constraint doesn't apply.");
+ ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { level: 0, width: 4, height: 3, expectation: gl.INVALID_OPERATION, message: "0: 4x3" },
+ { level: 0, width: 3, height: 4, expectation: gl.INVALID_OPERATION, message: "0: 3x4" },
+ { level: 0, width: 2, height: 2, expectation: gl.INVALID_OPERATION, message: "0: 2x2" },
+ { level: 0, width: 4, height: 4, expectation: gl.NO_ERROR, message: "0: 4x4" },
+ { level: 1, width: 2, height: 2, expectation: gl.NO_ERROR, message: "1: 2x2" },
+ { level: 2, width: 1, height: 1, expectation: gl.NO_ERROR, message: "2: 1x1" },
+ ]);
+
+ ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 16, 16,
+ [
+ { xoffset: 0, yoffset: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
+ { xoffset: 0, yoffset: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
+ { xoffset: 1, yoffset: 0, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
+ { xoffset: 0, yoffset: 1, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
+ { xoffset: 12, yoffset: 12, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ ]);
+
+ if (contextVersion >= 2) {
+ debug("");
+ debug("Testing NPOT textures");
+ ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { level: 0, width: 0, height: 0, expectation: gl.NO_ERROR, message: "0: 0x0 is valid" },
+ { level: 0, width: 1, height: 1, expectation: gl.INVALID_OPERATION, message: "0: 1x1 is invalid" },
+ { level: 0, width: 2, height: 2, expectation: gl.INVALID_OPERATION, message: "0: 2x2 is invalid" },
+ { level: 0, width: 3, height: 3, expectation: gl.INVALID_OPERATION, message: "0: 3x3 is invalid" },
+ { level: 0, width: 10, height: 10, expectation: gl.INVALID_OPERATION, message: "0: 10x10 is invalid" },
+ { level: 0, width: 11, height: 11, expectation: gl.INVALID_OPERATION, message: "0: 11x11 is invalid" },
+ { level: 0, width: 11, height: 12, expectation: gl.INVALID_OPERATION, message: "0: 11x12 is invalid" },
+ { level: 0, width: 12, height: 11, expectation: gl.INVALID_OPERATION, message: "0: 12x11 is invalid" },
+ { level: 0, width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
+ { level: 1, width: 0, height: 0, expectation: gl.NO_ERROR, message: "1: 0x0, is valid" },
+ { level: 1, width: 3, height: 3, expectation: gl.INVALID_OPERATION, message: "1: 3x3, is invalid" },
+ { level: 1, width: 5, height: 5, expectation: gl.INVALID_OPERATION, message: "1: 5x5, is invalid" },
+ { level: 1, width: 5, height: 6, expectation: gl.INVALID_OPERATION, message: "1: 5x6, is invalid" },
+ { level: 1, width: 6, height: 5, expectation: gl.INVALID_OPERATION, message: "1: 6x5, is invalid" },
+ { level: 1, width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
+ { level: 2, width: 0, height: 0, expectation: gl.NO_ERROR, message: "2: 0x0, is valid" },
+ { level: 2, width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
+ { level: 3, width: 1, height: 3, expectation: gl.NO_ERROR, message: "3: 1x3, is valid" },
+ { level: 3, width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
+ ]);
+
+ debug("");
+ debug("Testing partial updates");
+ ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 12, 12,
+ [
+ { xoffset: 0, yoffset: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
+ { xoffset: 0, yoffset: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
+ { xoffset: 1, yoffset: 0, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
+ { xoffset: 0, yoffset: 1, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
+ { xoffset: 8, yoffset: 8, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ ]);
+
+ debug("");
+ debug("Testing immutable NPOT textures");
+ ctu.testTexStorageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
+ { width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
+ { width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
+ { width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
+ ]);
+ }
+}
+
+function runTestRGTC() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 1,
+ data: img_4x4_r_bc4,
+ format: ext_rgtc.COMPRESSED_RED_RGTC1_EXT,
+ hasAlpha: false,
+ },
+ { width: 4,
+ height: 4,
+ channels: 1,
+ data: img_4x4_signed_r_bc4,
+ format: ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT,
+ hasAlpha: false,
+ },
+ { width: 4,
+ height: 4,
+ channels: 2,
+ data: img_4x4_rg_bc5,
+ format: ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT,
+ hasAlpha: false,
+ },
+ { width: 4,
+ height: 4,
+ channels: 2,
+ data: img_4x4_signed_rg_bc5,
+ format: ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT,
+ hasAlpha: false,
+ error: 18, // Signed, so twice the normal error.
+ // Experimentally needed by e.g. RTX 3070.
+ },
+ { width: 8,
+ height: 8,
+ channels: 2,
+ data: img_8x8_r_bc4,
+ format: ext_rgtc.COMPRESSED_RED_RGTC1_EXT,
+ hasAlpha: false,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_r_bc4,
+ },
+ { width: 8,
+ height: 8,
+ channels: 2,
+ data: img_8x8_rg_bc5,
+ format: ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT,
+ hasAlpha: false,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rg_bc5,
+ },
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT1_RGB() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 3,
+ data: img_4x4_rgba_dxt1,
+ format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT,
+ hasAlpha: false,
+ },
+ { width: 8,
+ height: 8,
+ channels: 3,
+ data: img_8x8_rgba_dxt1,
+ format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT,
+ hasAlpha: false,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rgba_dxt1
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT1_RGBA() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_dxt1,
+ format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ // This is a special case -- the texture is still opaque
+ // though it's RGBA.
+ hasAlpha: false,
+ },
+ { width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_dxt1,
+ format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ // This is a special case -- the texture is still opaque
+ // though it's RGBA.
+ hasAlpha: false,
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT3_RGBA() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_dxt3,
+ format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ hasAlpha: true,
+ },
+ { width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_dxt3,
+ format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ hasAlpha: true,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rgba_dxt3
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT5_RGBA() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_dxt5,
+ format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ hasAlpha: true,
+ },
+ { width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_dxt5,
+ format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ hasAlpha: true,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rgba_dxt5
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXTTextures(tests) {
+ debug("<hr/>");
+ for (var ii = 0; ii < tests.length; ++ii) {
+ testDXTTexture(tests[ii], false);
+ if (contextVersion >= 2) {
+ debug("<br/>");
+ testDXTTexture(tests[ii], true);
+ }
+ }
+}
+
+function uncompressDXTBlock(
+ destBuffer, destX, destY, destWidth, src, srcOffset, format) {
+ // Decoding routines follow D3D11 functional spec wrt
+ // endpoints unquantization and interpolation.
+ // Some hardware may produce slightly different values - it's normal.
+
+ function make565(src, offset) {
+ return src[offset + 0] + (src[offset + 1] << 8);
+ }
+ function make8888From565(c) {
+ // These values exactly match hw decoder when selectors are 0 or 1.
+ function replicateBits(v, w) {
+ return (v << (8 - w)) | (v >> (w + w - 8));
+ }
+ return [
+ replicateBits((c >> 11) & 0x1F, 5),
+ replicateBits((c >> 5) & 0x3F, 6),
+ replicateBits((c >> 0) & 0x1F, 5),
+ 255
+ ];
+ }
+ function mix(mult, c0, c1, div) {
+ var r = [];
+ for (var ii = 0; ii < c0.length; ++ii) {
+ // For green channel (6 bits), this interpolation exactly matches hw decoders
+
+ // For red and blue channels (5 bits), this interpolation exactly
+ // matches only some hw decoders and stays within acceptable range for others.
+ r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div + 0.5);
+ }
+ return r;
+ }
+ var isBC45 = ext_rgtc &&
+ (format == ext_rgtc.COMPRESSED_RED_RGTC1_EXT ||
+ format == ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT ||
+ format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT ||
+ format == ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
+ let colorOffset = srcOffset;
+ if (!isBC45) {
+ var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ if (!isDXT1) {
+ colorOffset += 8;
+ }
+ var color0 = make565(src, colorOffset + 0);
+ var color1 = make565(src, colorOffset + 2);
+ var c0gtc1 = color0 > color1 || !isDXT1;
+ var rgba0 = make8888From565(color0);
+ var rgba1 = make8888From565(color1);
+ var colors = [
+ rgba0,
+ rgba1,
+ c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
+ c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
+ ];
+ }
+ const isSigned = ext_rgtc && (format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT || format == ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
+ const signedSrc = new Int8Array(src);
+
+ // yea I know there is a lot of math in this inner loop.
+ // so sue me.
+ for (var yy = 0; yy < 4; ++yy) {
+ var pixels = src[colorOffset + 4 + yy];
+ for (var xx = 0; xx < 4; ++xx) {
+ var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
+ if (!isBC45) {
+ var code = (pixels >> (xx * 2)) & 0x3;
+ var srcColor = colors[code];
+ }
+ var alpha;
+ var rgChannel2 = 0;
+ let decodeAlpha = (offset) => {
+ let alpha;
+ var alpha0 = (isSigned ? signedSrc : src)[offset + 0];
+ var alpha1 = (isSigned ? signedSrc : src)[offset + 1];
+ var alphaOff = (yy >> 1) * 3 + 2;
+ var alphaBits =
+ src[offset + alphaOff + 0] +
+ src[offset + alphaOff + 1] * 256 +
+ src[offset + alphaOff + 2] * 65536;
+ var alphaShift = (yy % 2) * 12 + xx * 3;
+ var alphaCode = (alphaBits >> alphaShift) & 0x7;
+ if (alpha0 > alpha1) {
+ switch (alphaCode) {
+ case 0:
+ alpha = alpha0;
+ break;
+ case 1:
+ alpha = alpha1;
+ break;
+ default:
+ alpha = Math.floor(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7.0 + 0.5);
+ break;
+ }
+ } else {
+ switch (alphaCode) {
+ case 0:
+ alpha = alpha0;
+ break;
+ case 1:
+ alpha = alpha1;
+ break;
+ case 6:
+ alpha = 0;
+ break;
+ case 7:
+ alpha = 255;
+ break;
+ default:
+ alpha = Math.floor(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5.0 + 0.5);
+ break;
+ }
+ }
+ return alpha;
+ }
+
+ switch (format) {
+ case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
+ alpha = 255;
+ break;
+ case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ alpha = (code == 3 && !c0gtc1) ? 0 : 255;
+ break;
+ case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ {
+ var alpha0 = src[srcOffset + yy * 2 + (xx >> 1)];
+ var alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF;
+ alpha = alpha1 | (alpha1 << 4);
+ }
+ break;
+ case ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ rgChannel2 = decodeAlpha(srcOffset + 8);
+ // FALLTHROUGH
+ case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case ext_rgtc.COMPRESSED_RED_RGTC1_EXT:
+ case ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ alpha = decodeAlpha(srcOffset);
+ break;
+ default:
+ throw "bad format";
+ }
+ if (isBC45) {
+ destBuffer[dstOff + 0] = alpha;
+ destBuffer[dstOff + 1] = rgChannel2;
+ destBuffer[dstOff + 2] = 0;
+ destBuffer[dstOff + 3] = 255;
+ if (isSigned) {
+ destBuffer[dstOff + 0] = Math.max(0, alpha) * 2;
+ destBuffer[dstOff + 1] = Math.max(0, rgChannel2) * 2;
+ }
+ } else {
+ destBuffer[dstOff + 0] = srcColor[0];
+ destBuffer[dstOff + 1] = srcColor[1];
+ destBuffer[dstOff + 2] = srcColor[2];
+ destBuffer[dstOff + 3] = alpha;
+ }
+ }
+ }
+}
+
+function getBlockSize(format) {
+ var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ var isBC4 = ext_rgtc && (format == ext_rgtc.COMPRESSED_RED_RGTC1_EXT || format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT);
+ return isDXT1 || isBC4 ? 8 : 16;
+}
+
+function uncompressDXT(width, height, data, format) {
+ if (width % 4 || height % 4) throw "bad width or height";
+
+ var dest = new Uint8Array(width * height * 4);
+ var blocksAcross = width / 4;
+ var blocksDown = height / 4;
+ var blockSize = getBlockSize(format);
+ for (var yy = 0; yy < blocksDown; ++yy) {
+ for (var xx = 0; xx < blocksAcross; ++xx) {
+ uncompressDXTBlock(
+ dest, xx * 4, yy * 4, width, data,
+ (yy * blocksAcross + xx) * blockSize, format);
+ }
+ }
+ return dest;
+}
+
+function uncompressDXTIntoSubRegion(width, height, subX0, subY0, subWidth, subHeight, data, format)
+{
+ if (width % 4 || height % 4 || subX0 % 4 || subY0 % 4 || subWidth % 4 || subHeight % 4)
+ throw "bad dimension";
+
+ var dest = new Uint8Array(width * height * 4);
+ // Zero-filled DXT1 or BC4/5 texture represents [0, 0, 0, 255]
+ if (format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT || format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT ||
+ format == ext.COMPRESSED_RED_RGTC1_EXT || format == ext.COMPRESSED_SIGNED_RED_RGTC1_EXT ||
+ format == ext.COMPRESSED_RED_GREEN_RGTC2_EXT || format == ext.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) {
+ for (var i = 3; i < dest.length; i += 4) dest[i] = 255;
+ }
+ var blocksAcross = subWidth / 4;
+ var blocksDown = subHeight / 4;
+ var blockSize = getBlockSize(format);
+ for (var yy = 0; yy < blocksDown; ++yy) {
+ for (var xx = 0; xx < blocksAcross; ++xx) {
+ uncompressDXTBlock(
+ dest, subX0 + xx * 4, subY0 + yy * 4, width, data,
+ (yy * blocksAcross + xx) * blockSize, format);
+ }
+ }
+ return dest;
+}
+
+function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) {
+ var bytesPerLine = width * 4;
+ var srcOffset = srcX * 4 + srcY * stride;
+ var dstOffset = dstX * 4 + dstY * stride;
+ for (; height > 0; --height) {
+ for (var ii = 0; ii < bytesPerLine; ++ii) {
+ data[dstOffset + ii] = data[srcOffset + ii];
+ }
+ srcOffset += stride;
+ dstOffset += stride;
+ }
+}
+
+function testDXTTexture(test, useTexStorage) {
+ test.error = test.error || DEFAULT_COLOR_ERROR;
+
+ var data = new Uint8Array(test.data);
+ var width = test.width;
+ var height = test.height;
+ var format = test.format;
+
+ var uncompressedData = uncompressDXT(width, height, data, format);
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+ debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height +
+ (useTexStorage ? " via texStorage2D" : " via compressedTexImage2D"));
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ if (useTexStorage) {
+ if (test.subData) {
+ var uncompressedDataSub = uncompressDXTIntoSubRegion(
+ width, height, test.subX0, test.subY0, test.subWidth, test.subHeight, test.subData, format);
+ var tex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D");
+ gl.compressedTexSubImage2D(
+ gl.TEXTURE_2D, 0, test.subX0, test.subY0, test.subWidth, test.subHeight, format, test.subData);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture data via compressedTexSubImage2D");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 1");
+ compareRect(width, height, test.channels, uncompressedDataSub, "NEAREST", test.error);
+
+ // Clean up and recover
+ gl.deleteTexture(tex1);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ }
+
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ var clearColor = (test.hasAlpha ? [0, 0, 0, 0] : [0, 0, 0, 255]);
+ wtu.checkCanvas(gl, clearColor, "texture should be initialized to black");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture data via compressedTexSubImage2D");
+ } else {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ }
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after clearing generateMipmap error");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 1");
+ compareRect(width, height, test.channels, uncompressedData, "NEAREST", test.error);
+ // Test again with linear filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 2");
+ compareRect(width, height, test.channels, uncompressedData, "LINEAR", test.error);
+
+ if (!useTexStorage) {
+ // It's not allowed to redefine textures defined via texStorage2D.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+ if (width == 4) {
+ // The width/height of the implied base level must be a multiple of the block size.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ }
+ if (height == 4) {
+ // The width/height of the implied base level must be a multiple of the block size.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ }
+ }
+
+ // pick a wrong format that uses the same amount of data.
+ var wrongFormat;
+ switch (format) {
+ case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
+ wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ break;
+ case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ wrongFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;
+ break;
+ case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+ case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ break;
+ case ext_rgtc.COMPRESSED_RED_RGTC1_EXT:
+ case ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ wrongFormat = ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT;
+ break;
+ case ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ wrongFormat = ext_rgtc.COMPRESSED_RED_RGTC1_EXT;
+ break;
+ }
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 4, 0, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "dimension out of range");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 4, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "dimension out of range");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+ var subData = new Uint8Array(data.buffer, 0, getBlockSize(format));
+
+ if (width == 8 && height == 8) {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+ }
+
+ var stride = width * 4;
+ for (var yoff = 0; yoff < height; yoff += 4) {
+ for (var xoff = 0; xoff < width; xoff += 4) {
+ copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ // First test NEAREST filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ wtu.clearAndDrawUnitQuad(gl);
+ compareRect(width, height, test.channels, uncompressedData, "NEAREST", test.error);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ // Next test LINEAR filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ compareRect(width, height, test.channels, uncompressedData, "LINEAR", test.error);
+ }
+ }
+}
+
+function testDXT5_RGBA_PBO() {
+ debug("");
+ debug("testing PBO uploads");
+ var width = 8;
+ var height = 8;
+ var channels = 4;
+ var data = img_8x8_rgba_dxt5;
+ var format = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ var uncompressedData = uncompressDXT(width, height, data, format);
+
+ var tex = gl.createTexture();
+
+ // First, PBO size = image size
+ var pbo1 = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo1);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a PBO");
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data.length, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a texture from a PBO");
+
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ compareRect(width, height, channels, uncompressedData, "NEAREST", DEFAULT_COLOR_ERROR);
+
+ // Clear the texture before the next test
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, new Uint8Array(data.length));
+
+ // Second, image is just a subrange of the PBO
+ var pbo2 = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo2);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data.length*3, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.PIXEL_UNPACK_BUFFER, data.length, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a PBO subrange");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data.length, data.length);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a texture from a PBO subrange");
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ compareRect(width, height, channels, uncompressedData, "NEAREST", DEFAULT_COLOR_ERROR);
+}
+
+function compareRect(width, height, channels, expectedData, filteringMode, colorError) {
+ var actual = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "reading back pixels");
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(width, height, width, expectedData, true));
+ ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(width, height, width, actual, true));
+ div.appendChild(document.createElement('br'));
+ document.getElementById("console").appendChild(div);
+
+ var failed = false;
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ var expected = expectedData.slice(offset, offset + 4);
+ const was = actual.slice(offset, offset + 4);
+
+ // Compare RGB values
+ for (var jj = 0; jj < 3; ++jj) {
+ if (Math.abs(was[jj] - expected[jj]) > colorError) {
+ failed = true;
+ testFailed(`RGB at (${xx}, ${yy}) expected: ${expected}` +
+ ` +/- ${colorError}, was ${was}`);
+ break;
+ }
+ }
+
+ if (channels == 3) {
+ // BC1 RGB is allowed to be mapped to BC1 RGBA.
+ // In such a case, 3-color mode black value can be transparent:
+ // [0, 0, 0, 0] instead of [0, 0, 0, 255].
+
+ if (actual[offset + 3] != expected[3]) {
+ // Got non-opaque value for opaque format
+
+ // Check RGB values. Notice, that the condition here
+ // is more permissive than needed since we don't have
+ // compressed data at this point.
+ if (was[0] == 0 &&
+ was[1] == 0 &&
+ was[2] == 0 &&
+ was[3] == 0) {
+ debug("<b>DXT1 RGB is mapped to DXT1 RGBA</b>");
+ } else {
+ failed = true;
+ testFailed('Alpha at (' + xx + ', ' + yy +
+ ') expected: ' + expected[3] + ' was ' + was);
+ }
+ }
+ } else {
+ // Compare Alpha values
+ // Acceptable interpolation error depends on endpoints:
+ // 1.0 / 65535.0 + 0.03 * max(abs(endpoint0 - endpoint1), abs(endpoint0_p - endpoint1_p))
+ // For simplicity, assume the worst case (e0 is 0.0, e1 is 1.0). After conversion to unorm8, it is 8.
+ if (Math.abs(was[3] - expected[3]) > 8) {
+ failed = true;
+ testFailed('Alpha at (' + xx + ', ' + yy +
+ ') expected: ' + expected + ' +/- 8 was ' + was);
+ }
+ }
+ }
+ }
+ if (!failed) {
+ testPassed("texture rendered correctly with " + filteringMode + " filtering");
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-astc.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-astc.html
new file mode 100644
index 0000000000..d737c3f2a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-astc.html
@@ -0,0 +1,2524 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+<title>WebGL WEBGL_compressed_texture_astc Conformance Tests</title>
+<style>
+img {
+ border: 1px solid black;
+ margin-right: 1em;
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_compressed_texture_astc extension, if it is available.");
+
+debug("");
+
+// Compressed textures generated with ARM's ASTC encoder
+// https://github.com/ARM-software/astc-encoder
+
+// The data below is printed directly from the astc file,
+// and the header has been left for clarity reasons.
+
+// LDR encoded with the following command line:
+// 'astcenc -c source.png result.astc {blockSize} -medium'
+
+// The image used for LDR compression can be found
+// at sdk/tests/resources/red-green-hard.png
+
+var astc_4x4_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x4, 0x4, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x42, 0x2, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x42, 0x2, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x42, 0x2, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x42, 0x2, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x42, 0x2, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x42, 0x2, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+]);
+var astc_5x4_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x5, 0x4, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xc1, 0x2, 0x1, 0x2, 0x1, 0x0, 0x0, 0x80, 0x48, 0x22, 0x89, 0x24, 0x92, 0x48, 0x22, 0x9,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xc1, 0x2, 0x1, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x20, 0x89, 0x24, 0x92, 0x48, 0x22, 0x89,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xc1, 0x2, 0x1, 0x2, 0x1, 0x0, 0x0, 0x80, 0x48, 0x22, 0x89, 0x24, 0x0, 0x40, 0x0, 0x80,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xc1, 0x2, 0x1, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x89, 0x24, 0x92, 0x48, 0x22, 0x89,
+]);
+var astc_5x5_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x5, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xf3, 0x0, 0x81, 0xff, 0x7, 0x0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xf3, 0x0, 0x7f, 0x0, 0xf8, 0x1, 0xe0, 0xff, 0xf1, 0xff, 0xf8, 0x7f, 0x0, 0x0, 0x0, 0x0,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff,
+]);
+var astc_6x5_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x6, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x63, 0x1, 0x81, 0x10, 0x0, 0x0, 0x48, 0x49, 0x29, 0x29, 0x25, 0xa5, 0xa4, 0x94, 0x94, 0x12,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x63, 0x1, 0x81, 0x10, 0x0, 0x0, 0x48, 0x0, 0x28, 0x0, 0x24, 0x0, 0xa4, 0x94, 0x94, 0x92,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x63, 0x1, 0x81, 0x10, 0x0, 0x0, 0x0, 0x48, 0x1, 0x28, 0x1, 0xa4, 0x0, 0x94, 0x0, 0x92,
+]);
+var astc_6x6_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x6, 0x6, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x4, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x4, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xc3, 0x30, 0xfc,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x4, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xe3, 0xf8, 0xff, 0xff,
+]);
+var astc_8x5_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x8, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xf0, 0xff, 0xf0, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xff, 0xf, 0xff, 0xf, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x66, 0x0, 0x3f, 0x0, 0x1f, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0,
+]);
+var astc_8x6_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x8, 0x6, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x70, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x70, 0x7f, 0x7f, 0xf8, 0x7f, 0x56, 0x3f, 0x72, 0x7f, 0x7f,
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x70, 0x7f, 0x7f, 0x7f, 0x3f, 0x72, 0x78, 0x7f, 0x70, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x50, 0x7f, 0x72, 0xfe, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+]);
+var astc_8x8_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x8, 0x8, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x44, 0x5, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0x44, 0x5, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x44, 0x5, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc,
+ 0x44, 0x5, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f,
+]);
+var astc_10x5_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x65, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0x0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x65, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0x0, 0x0, 0xfc, 0xf0, 0xc3, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x65, 0x1, 0xff, 0x1, 0x0, 0xfe, 0x1, 0x0, 0x0, 0xc0, 0x7, 0x1f, 0x7c, 0xf0, 0xc1, 0x7,
+]);
+var astc_10x6_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0x6, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xa4, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xa4, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xf0, 0xc3, 0xf, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xa4, 0x1, 0x1, 0xfe, 0xff, 0x1, 0x0, 0x0, 0x0, 0x3e, 0xf8, 0xe0, 0xff, 0xff, 0xff, 0xff,
+]);
+var astc_10x8_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0x8, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x65, 0x9, 0x69, 0x35, 0x0, 0x8, 0x10, 0x2, 0x0, 0x0, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x6, 0x11, 0x69, 0x2d, 0x80, 0x40, 0x2, 0x80, 0x4, 0x0, 0x8, 0x0, 0xff, 0xf, 0xf0, 0xff,
+ 0x44, 0x5, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+]);
+var astc_10x10_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0xa, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xa4, 0xc9, 0xc, 0x3, 0x22, 0x0, 0x8, 0x40, 0x8, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x45, 0x89, 0x7, 0x35, 0x0, 0x40, 0x10, 0x0, 0x20, 0x0, 0x0, 0x1f, 0x7c, 0xf0, 0xc1, 0xff,
+]);
+var astc_12x10_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xc, 0xa, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x64, 0x8, 0x11, 0x3, 0x22, 0x0, 0x8, 0x40, 0x38, 0xfc, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xe5, 0x10, 0x4a, 0x4d, 0x46, 0x7f, 0x0, 0xc0, 0xf, 0x40, 0xf8, 0x1, 0x39, 0xf1, 0x7, 0x0,
+]);
+var astc_12x12_argb_ldr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xc, 0xc, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x64, 0xa8, 0x21, 0x3, 0x22, 0x0, 0x8, 0x40, 0x38, 0xfc, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x84, 0xd8, 0xe9, 0x2e, 0x0, 0x0, 0x1, 0x0, 0x80, 0xc0, 0x80, 0x28, 0x2a, 0xab, 0x2a, 0xff,
+]);
+
+// HDR encoded with the following command line:
+// 'astcenc -c source.hdr result.astc {blockSize} -medium'
+
+// The image used for HDR compression can be found
+// at sdk/tests/resources/red-green-hard.hdr
+
+var astc_4x4_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x4, 0x4, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x42, 0x2, 0x1, 0x82, 0x82, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x42, 0x2, 0x81, 0x3, 0x82, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x42, 0x2, 0x81, 0x3, 0x82, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x42, 0x2, 0x83, 0x0, 0x0, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0,
+ 0x42, 0x2, 0x83, 0x0, 0x0, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x42, 0x2, 0x1, 0x82, 0x82, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+]);
+var astc_5x4_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x5, 0x4, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xc1, 0x2, 0x1, 0x42, 0x21, 0x0, 0x0, 0x80, 0x48, 0x22, 0x89, 0x24, 0x92, 0x48, 0x22, 0x9,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xc1, 0x2, 0x1, 0x42, 0x21, 0x0, 0x0, 0x0, 0x0, 0x20, 0x89, 0x24, 0x92, 0x48, 0x22, 0x89,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xc1, 0x2, 0x1, 0x42, 0x21, 0x0, 0x0, 0x80, 0x48, 0x22, 0x89, 0x24, 0x0, 0x40, 0x0, 0x80,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xc1, 0x2, 0x1, 0x42, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x89, 0x24, 0x92, 0x48, 0x22, 0x89,
+]);
+var astc_5x5_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x5, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xf3, 0x0, 0x81, 0xff, 0x7, 0x0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xf3, 0x0, 0x81, 0xff, 0x7, 0x0, 0x0, 0x0, 0xe, 0x0, 0x7, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff,
+]);
+var astc_6x5_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x6, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x63, 0x1, 0x81, 0x10, 0x0, 0x0, 0x48, 0x49, 0x29, 0x29, 0x25, 0xa5, 0xa4, 0x94, 0x94, 0x12,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x63, 0x1, 0x81, 0x10, 0x0, 0x0, 0x48, 0x0, 0x28, 0x0, 0x24, 0x0, 0xa4, 0x94, 0x94, 0x92,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x63, 0x1, 0x81, 0x10, 0x0, 0x0, 0x0, 0x48, 0x1, 0x28, 0x1, 0xa4, 0x0, 0x94, 0x0, 0x92,
+]);
+var astc_6x6_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x6, 0x6, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x4, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x4, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xc3, 0x30, 0xfc,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x4, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xe3, 0xf8, 0xff, 0xff,
+]);
+var astc_8x5_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x8, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xf0, 0xff, 0xf0, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xff, 0xf, 0xff, 0xf, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x66, 0x0, 0xc1, 0xff, 0x0, 0x0, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff,
+]);
+var astc_8x6_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x8, 0x6, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x70, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x70, 0x7f, 0x7f, 0xf8, 0x7f, 0x56, 0x3f, 0x72, 0x7f, 0x7f,
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x70, 0x7f, 0x7f, 0x7f, 0x3f, 0x72, 0x78, 0x7f, 0x70, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x54, 0x1, 0x81, 0x20, 0x0, 0x0, 0x50, 0x7f, 0x72, 0xfe, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+]);
+var astc_8x8_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0x8, 0x8, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x44, 0x5, 0x81, 0x3, 0x82, 0x0, 0x0, 0x0, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0x44, 0x5, 0x81, 0x3, 0x82, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x44, 0x5, 0x1, 0x82, 0x82, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc,
+ 0x44, 0x5, 0x1, 0x82, 0x82, 0x0, 0x0, 0x0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f,
+]);
+var astc_10x5_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0x5, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x65, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x65, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0x0, 0xfc, 0xf0, 0xc3, 0xff, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x65, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0x0, 0xf8, 0xe0, 0x83, 0xf, 0x3e, 0xf8,
+]);
+var astc_10x6_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0x6, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xa4, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xa4, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xf0, 0xc3, 0xf, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xa4, 0x1, 0x1, 0xfc, 0xfd, 0x1, 0x0, 0x0, 0x0, 0x3e, 0xf8, 0xe0, 0xff, 0xff, 0xff, 0xff,
+]);
+var astc_10x8_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0x8, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x65, 0x9, 0x69, 0x35, 0x0, 0x8, 0x10, 0x2, 0x0, 0x0, 0xfc, 0xe0, 0x3, 0x0, 0x0, 0x0,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x15, 0x11, 0x69, 0x25, 0x0, 0x84, 0x0, 0x10, 0x0, 0x2, 0x40, 0x88, 0x3f, 0x0, 0x3f, 0x0,
+ 0x44, 0x5, 0x1, 0x2, 0x2, 0x0, 0x0, 0x0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+]);
+var astc_10x10_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xa, 0xa, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0xa4, 0xc9, 0xc, 0x3, 0x22, 0x0, 0x8, 0x40, 0x8, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x45, 0x89, 0x7, 0x35, 0x0, 0x40, 0x0, 0x82, 0x0, 0x0, 0x0, 0xe0, 0x83, 0xf, 0x3e, 0x0,
+]);
+var astc_12x10_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xc, 0xa, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x64, 0x8, 0x11, 0x3, 0x22, 0x0, 0x8, 0x40, 0x38, 0xfc, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x44, 0x10, 0x4a, 0x49, 0x46, 0xf, 0x1c, 0x3f, 0x0, 0x28, 0xff, 0x1, 0xc0, 0x3f, 0xc, 0x0,
+]);
+var astc_12x12_argb_hdr = new Uint8Array([
+ //0x13, 0xab, 0xa1, 0x5c, 0xc, 0xc, 0x1, 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x1, 0x0, 0x0, HEADER
+ 0x64, 0xa8, 0x21, 0x3, 0x22, 0x0, 0x8, 0x40, 0x38, 0xfc, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x4, 0xd8, 0xe9, 0x2e, 0x0, 0x8, 0x1, 0x40, 0x80, 0xc0, 0x81, 0x28, 0x2a, 0x0, 0x0, 0x0,
+]);
+
+// Decoded ASTC textures generated with ARM's ASTC encoder
+// https://github.com/ARM-software/astc-encoder
+
+// As the original image is quite simple to compress,
+// several decoded images share the same data
+
+// LDR decoded with the following command line:
+// 'astcenc -d source.astc result.tga'
+var decoded_4x4To10x6_argb_ldr = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_10x8_argb_ldr = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xdf, 0x20, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_10x10_argb_ldr = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff,
+ 0x20, 0xdf, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x8f, 0x70, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_12x10_argb_ldr = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xdf, 0x20, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x70, 0x8f, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_12x12_argb_ldr = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x10, 0xef, 0x0, 0xff, 0x10, 0xef, 0x0, 0xff,
+ 0x10, 0xef, 0x0, 0xff, 0x10, 0xef, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x70, 0x8f, 0x0, 0xff, 0x70, 0x8f, 0x0, 0xff,
+ 0x70, 0x8f, 0x0, 0xff, 0x70, 0x8f, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xcf, 0x30, 0x0, 0xff, 0xcf, 0x30, 0x0, 0xff,
+ 0xcf, 0x30, 0x0, 0xff, 0xcf, 0x30, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xbf, 0x40, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x60, 0x9f, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+
+var decoded_10x8_argb_ldr_srgb = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xbc, 0x4, 0x0, 0xff, 0x4, 0xbc, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_10x10_argb_ldr_srgb = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x4, 0xbc, 0x0, 0xff, 0x4, 0xbc, 0x0, 0xff,
+ 0x4, 0xbc, 0x0, 0xff, 0x4, 0xbc, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x46, 0x29, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_12x10_argb_ldr_srgb = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xbc, 0x4, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x29, 0x46, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+var decoded_12x12_argb_ldr_srgb = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x1, 0xdc, 0x0, 0xff, 0x1, 0xdc, 0x0, 0xff,
+ 0x1, 0xdc, 0x0, 0xff, 0x1, 0xdc, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x29, 0x46, 0x0, 0xff, 0x29, 0x46, 0x0, 0xff,
+ 0x29, 0x46, 0x0, 0xff, 0x29, 0x46, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x9f, 0x8, 0x0, 0xff, 0x9f, 0x8, 0x0, 0xff,
+ 0x9f, 0x8, 0x0, 0xff, 0x9f, 0x8, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x85, 0xd, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x1e, 0x58, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+]);
+
+// HDR decoded with the following command line:
+// 'astcenc -d source.astc result.tga'
+
+var decoded_4x4_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfd, 0x0, 0xff, 0x0, 0xfd, 0x0, 0xff,
+ 0x0, 0xfd, 0x0, 0xff, 0x0, 0xfd, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_5x4_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_5x5_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_6x5_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_6x6_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_8x5_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_8x6_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_8x8_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfd, 0x0, 0xff, 0x0, 0xfd, 0x0, 0xff,
+ 0x0, 0xfd, 0x0, 0xff, 0x0, 0xfd, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xfd, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+
+var decoded_10x5To10x6_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xfe, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+
+var decoded_10x8_argb_hdr = new Uint8Array([
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xdf, 0x20, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_10x10_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff,
+ 0x20, 0xdf, 0x0, 0xff, 0x20, 0xdf, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x8f, 0x70, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_12x10_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xdf, 0x20, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x70, 0x8f, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+var decoded_12x12_argb_hdr = new Uint8Array([
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0x0, 0xfe, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x10, 0xef, 0x0, 0xff, 0x10, 0xef, 0x0, 0xff,
+ 0x10, 0xef, 0x0, 0xff, 0x10, 0xef, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0x70, 0x8f, 0x0, 0xff, 0x70, 0x8f, 0x0, 0xff,
+ 0x70, 0x8f, 0x0, 0xff, 0x70, 0x8f, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xcf, 0x30, 0x0, 0xff, 0xcf, 0x30, 0x0, 0xff,
+ 0xcf, 0x30, 0x0, 0xff, 0xcf, 0x30, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0xbf, 0x40, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x60, 0x9f, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xff,
+]);
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var program = wtu.setupTexturedQuad(gl);
+var nanToMagentaProgram2D, nanToMagentaProgram2DArray, nanToMagentaProgram3D;
+var program2DArray, program3D;
+
+gl.useProgram(program);
+
+var extFlag = "WEBGL_compressed_texture_astc";
+var ext = null;
+var vao = null;
+var validFormats = {
+
+ COMPRESSED_RGBA_ASTC_4x4_KHR : 0x93B0,
+ COMPRESSED_RGBA_ASTC_5x4_KHR : 0x93B1,
+ COMPRESSED_RGBA_ASTC_5x5_KHR : 0x93B2,
+ COMPRESSED_RGBA_ASTC_6x5_KHR : 0x93B3,
+ COMPRESSED_RGBA_ASTC_6x6_KHR : 0x93B4,
+ COMPRESSED_RGBA_ASTC_8x5_KHR : 0x93B5,
+ COMPRESSED_RGBA_ASTC_8x6_KHR : 0x93B6,
+ COMPRESSED_RGBA_ASTC_8x8_KHR : 0x93B7,
+ COMPRESSED_RGBA_ASTC_10x5_KHR : 0x93B8,
+ COMPRESSED_RGBA_ASTC_10x6_KHR : 0x93B9,
+ COMPRESSED_RGBA_ASTC_10x8_KHR : 0x93BA,
+ COMPRESSED_RGBA_ASTC_10x10_KHR : 0x93BB,
+ COMPRESSED_RGBA_ASTC_12x10_KHR : 0x93BC,
+ COMPRESSED_RGBA_ASTC_12x12_KHR : 0x93BD,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : 0x93D0,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : 0x93D1,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : 0x93D2,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : 0x93D3,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : 0x93D4,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : 0x93D5,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : 0x93D6,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : 0x93D7,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : 0x93D8,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : 0x93D9,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : 0x93DA,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : 0x93DB,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : 0x93DC,
+ COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : 0x93DD
+
+};
+var name;
+
+const errorColor = [255, 0, 255, 255];
+let hasHdr = false;
+
+var check2DTarget = 1;
+var check2DArrayTarget = 1;
+var check3DTarget = 1;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // The texture size 3 * 5 * 8 below is divisible by all the different block sizes supported by the extension.
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 3 * 5 * 8);
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, extFlag);
+ if (!ext) {
+ testPassed("No WEBGL_compressed_texture_astc support -- this is legal");
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_astc", false);
+ } else {
+ testPassed("Successfully enabled WEBGL_compressed_texture_astc extension");
+
+ debug("");
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_astc", true);
+ runTestExtension();
+ }
+}
+
+function runTestExtension() {
+ debug("");
+ debug("Testing " + extFlag);
+
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(ext, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+
+ if (contextVersion >= 2) {
+ // For LDR and non-sRGB formats, the error color is magenta *or* all NaNs. To
+ // make sure we accept this we create a program that transforms an all NaN
+ // sampling result to magenta.
+
+ nanToMagentaProgram2D = wtu.setupSimpleTextureProgramESSL300(gl, undefined, undefined,
+ `#version 300 es
+ precision mediump float;
+ uniform sampler2D tex;
+ in vec2 texCoord;
+ out vec4 out_color;
+ void main() {
+ vec4 c = texture(tex, texCoord);
+ if (all(isnan(c))) {
+ out_color = vec4(1, 0, 1, 1);
+ } else {
+ out_color = c;
+ }
+ }`
+ );
+
+ nanToMagentaProgram2DArray = wtu.setupSimpleTextureProgramESSL300(gl, undefined, undefined,
+ `#version 300 es
+ precision mediump float;
+ uniform mediump sampler2DArray tex;
+ in vec2 texCoord;
+ out vec4 out_color;
+ void main() {
+ vec4 c = texture(tex, vec3(texCoord, 0));
+ if (all(isnan(c))) {
+ out_color = vec4(1, 0, 1, 1);
+ } else {
+ out_color = c;
+ }
+ }`
+ );
+
+ nanToMagentaProgram3D = wtu.setupSimpleTextureProgramESSL300(gl, undefined, undefined,
+ `#version 300 es
+ precision mediump float;
+ uniform mediump sampler3D tex;
+ in vec2 texCoord;
+ out vec4 out_color;
+ void main() {
+ vec4 c = texture(tex, vec3(texCoord, 0));
+ if (all(isnan(c))) {
+ out_color = vec4(1, 0, 1, 1);
+ } else {
+ out_color = c;
+ }
+ }`
+ );
+
+ program2DArray = wtu.setupSimpleTextureProgramESSL300(gl, undefined, undefined,
+ `#version 300 es
+ precision mediump float;
+ uniform mediump sampler2DArray tex;
+ in vec2 texCoord;
+ out vec4 out_color;
+ void main() {
+ out_color = texture(tex, vec3(texCoord, 0));
+ }`
+ );
+
+ program3D = wtu.setupSimpleTextureProgramESSL300(gl, undefined, undefined,
+ `#version 300 es
+ precision mediump float;
+ uniform mediump sampler3D tex;
+ in vec2 texCoord;
+ out vec4 out_color;
+ void main() {
+ out_color = texture(tex, vec3(texCoord, 0));
+ }`
+ );
+ }
+
+ // Query supported profiles and test ASTC texture with appropriate formats
+ var profiles = ext.getSupportedProfiles();
+ // Check for HDR support first, since it affects sliced 3D support for LDR
+ if (profiles.indexOf("hdr") != -1) {
+ hasHdr = true;
+ testHDRTextures();
+ } else {
+ testPassed("HDR profile is not supported.");
+ }
+
+ if (profiles.indexOf("ldr") != -1) {
+ testLDRTextures();
+ } else {
+ testFailed('LDR profile must be supported.');
+ }
+}
+
+function testLDRTextures() {
+ debug("");
+ debug("Testing every LDR texture format compression");
+
+ var data = [];
+ var formats = [];
+ var sRGBformats = [];
+ var raws = [];
+ var sRGBraws = [];
+
+ data.push(astc_4x4_argb_ldr, astc_5x4_argb_ldr, astc_5x5_argb_ldr,
+ astc_6x5_argb_ldr, astc_6x6_argb_ldr, astc_8x5_argb_ldr,
+ astc_8x6_argb_ldr, astc_8x8_argb_ldr, astc_10x5_argb_ldr,
+ astc_10x6_argb_ldr, astc_10x8_argb_ldr, astc_10x10_argb_ldr,
+ astc_12x10_argb_ldr, astc_12x12_argb_ldr);
+
+ formats.push(ext.COMPRESSED_RGBA_ASTC_4x4_KHR, ext.COMPRESSED_RGBA_ASTC_5x4_KHR,
+ ext.COMPRESSED_RGBA_ASTC_5x5_KHR, ext.COMPRESSED_RGBA_ASTC_6x5_KHR,
+ ext.COMPRESSED_RGBA_ASTC_6x6_KHR, ext.COMPRESSED_RGBA_ASTC_8x5_KHR,
+ ext.COMPRESSED_RGBA_ASTC_8x6_KHR, ext.COMPRESSED_RGBA_ASTC_8x8_KHR,
+ ext.COMPRESSED_RGBA_ASTC_10x5_KHR, ext.COMPRESSED_RGBA_ASTC_10x6_KHR,
+ ext.COMPRESSED_RGBA_ASTC_10x8_KHR, ext.COMPRESSED_RGBA_ASTC_10x10_KHR,
+ ext.COMPRESSED_RGBA_ASTC_12x10_KHR, ext.COMPRESSED_RGBA_ASTC_12x12_KHR);
+
+ sRGBformats.push(ext.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+ ext.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+ ext.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+ ext.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+ ext.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+ ext.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+ ext.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, ext.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
+
+ // adds decoded image to use in the compare function
+ // certain block size share the same decoded data
+ // due to the fact that the test image is quite simple
+ for (var i = 0; i < 10; ++i)
+ raws.push(decoded_4x4To10x6_argb_ldr);
+ raws.push(decoded_10x8_argb_ldr, decoded_10x10_argb_ldr, decoded_12x10_argb_ldr, decoded_12x12_argb_ldr);
+
+ // Given that test images mostly use 0 and 255, sRGB decoding is the same as linear for 4x4 - 10x6 images
+ for (var i = 0; i < 10; ++i)
+ sRGBraws.push(decoded_4x4To10x6_argb_ldr);
+ sRGBraws.push(decoded_10x8_argb_ldr_srgb, decoded_10x10_argb_ldr_srgb, decoded_12x10_argb_ldr_srgb, decoded_12x12_argb_ldr_srgb);
+
+ testASTCTextures(buildTests(data, formats, raws, 'LDR'));
+ testASTCTextures(buildTests(data, sRGBformats, sRGBraws, 'LDR-sRGB'));
+}
+
+function testHDRTextures() {
+ debug("");
+ debug("Testing every HDR texture format compression");
+
+
+ var data = [];
+ var formats = [];
+ var raws = [];
+
+ data.push(astc_4x4_argb_hdr, astc_5x4_argb_hdr, astc_5x5_argb_hdr,
+ astc_6x5_argb_hdr, astc_6x6_argb_hdr, astc_8x5_argb_hdr,
+ astc_8x6_argb_hdr, astc_8x8_argb_hdr, astc_10x5_argb_hdr,
+ astc_10x6_argb_hdr, astc_10x8_argb_hdr, astc_10x10_argb_hdr,
+ astc_12x10_argb_hdr, astc_12x12_argb_hdr);
+
+ formats.push(ext.COMPRESSED_RGBA_ASTC_4x4_KHR, ext.COMPRESSED_RGBA_ASTC_5x4_KHR,
+ ext.COMPRESSED_RGBA_ASTC_5x5_KHR, ext.COMPRESSED_RGBA_ASTC_6x5_KHR,
+ ext.COMPRESSED_RGBA_ASTC_6x6_KHR, ext.COMPRESSED_RGBA_ASTC_8x5_KHR,
+ ext.COMPRESSED_RGBA_ASTC_8x6_KHR, ext.COMPRESSED_RGBA_ASTC_8x8_KHR,
+ ext.COMPRESSED_RGBA_ASTC_10x5_KHR, ext.COMPRESSED_RGBA_ASTC_10x6_KHR,
+ ext.COMPRESSED_RGBA_ASTC_10x8_KHR, ext.COMPRESSED_RGBA_ASTC_10x10_KHR,
+ ext.COMPRESSED_RGBA_ASTC_12x10_KHR, ext.COMPRESSED_RGBA_ASTC_12x12_KHR);
+
+ // adds decoded image to use in the compare function
+ // certain block size share the same decoded data
+ // due to the fact that the test image is quite simple
+ raws.push(decoded_4x4_argb_hdr, decoded_5x4_argb_hdr, decoded_5x5_argb_hdr, decoded_6x5_argb_hdr,
+ decoded_6x6_argb_hdr, decoded_8x5_argb_hdr, decoded_8x6_argb_hdr, decoded_8x8_argb_hdr,
+ decoded_10x5To10x6_argb_hdr, decoded_10x5To10x6_argb_hdr, decoded_10x8_argb_hdr,
+ decoded_10x10_argb_hdr, decoded_12x10_argb_hdr, decoded_12x12_argb_hdr);
+
+ testASTCTextures(buildTests(data, formats, raws, 'HDR'));
+}
+
+function testASTCTextures(tests) {
+ debug("<hr/>");
+ for (var i = 0; i < tests.length; ++i) {
+ testASTCTexture(tests[i], contextVersion >= 2);
+ }
+}
+
+function testASTCTexture(test, useES3) {
+ var data = test.data;
+ var width = test.width;
+ var height = test.height;
+ var format = test.format;
+ var raw = test.raw;
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+ debug("");
+ debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height + " (" + test.mode + ")" +
+ (useES3 ? " via ES 3.0 entrypoints" : " via compressedTexImage2D"));
+ debug("");
+
+ function errorColorMaybeNaN() {
+ return format >= ext.COMPRESSED_RGBA_ASTC_4x4_KHR && format <= ext.COMPRESSED_RGBA_ASTC_12x12_KHR;
+ }
+
+ function ensureParameters(target) {
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ }
+
+ function setupEmptyTexture(target, useStorage) {
+ var tex = gl.createTexture();
+ gl.bindTexture(target, tex);
+ ensureParameters(target);
+
+ if (target == gl.TEXTURE_2D) {
+ if (useStorage) {
+ gl.texStorage2D(target, 1, format, width, height);
+ } else {
+ gl.compressedTexImage2D(target, 0, format, width, height, 0, new Uint8Array(data.length));
+ }
+ } else if (target == gl.TEXTURE_2D_ARRAY || target == gl.TEXTURE_3D) {
+ if (useStorage) {
+ gl.texStorage3D(target, 1, format, width, height, 1);
+ } else {
+ gl.compressedTexImage3D(target, 0, format, width, height, 1, 0, new Uint8Array(data.length));
+ }
+ }
+
+ return tex; // Keep reference to the texture so it could be deleted
+ }
+
+ function uploadSubData(target) {
+ function checkResult(target, expectations, dim) {
+ switch (target) {
+ case gl.TEXTURE_2D:
+ wtu.glErrorShouldBe(gl, expectations[0], "uploading compressed 2D texture data via compressedTexSubImage" + dim);
+ break;
+ case gl.TEXTURE_2D_ARRAY:
+ wtu.glErrorShouldBe(gl, expectations[1], "uploading compressed 2D array texture data via compressedTexSubImage" + dim);
+ break;
+ case gl.TEXTURE_3D:
+ wtu.glErrorShouldBe(gl, expectations[2], "uploading compressed 3D texture data via compressedTexSubImage" + dim);
+ break;
+ }
+ }
+
+ gl.compressedTexSubImage2D(target, 0, 0, 0, width, height, format, data);
+ checkResult(target, [gl.NO_ERROR, gl.INVALID_ENUM, gl.INVALID_ENUM ], "2D");
+
+ if (useES3) {
+ gl.compressedTexSubImage3D(target, 0, 0, 0, 0, width, height, 1, format, data);
+ checkResult(target, [gl.INVALID_ENUM, gl.NO_ERROR, gl.NO_ERROR], "3D");
+ }
+ }
+
+ function setupFilledTexture(target) {
+ var tex = gl.createTexture();
+ gl.bindTexture(target, tex);
+ ensureParameters(target);
+
+ if (target == gl.TEXTURE_2D) {
+ gl.compressedTexImage2D(target, 0, format, width, height, 1, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
+
+ gl.compressedTexImage2D(target, 0, format, width, height, 0, data);
+ } else if (target == gl.TEXTURE_2D_ARRAY || target == gl.TEXTURE_3D) {
+ gl.compressedTexImage3D(target, 0, format, width, height, 1, 0, data);
+ }
+
+ return tex; // Keep reference to the texture so it could be deleted
+ }
+
+ function switchProgram(target) {
+ // For LDR non-sRGB and HDR formats, we accept all NaNs as a valid result.
+ // This program transforms all NaNs to the normal error color, magenta.
+
+ // There's no 100% reliable way to check NaN values on ESSL 1.0,
+ // so error color is verified only on ESSL 3.0.
+
+ if (errorColorMaybeNaN()) {
+ if (target == gl.TEXTURE_2D) {
+ gl.useProgram(nanToMagentaProgram2D);
+ } else if (target == gl.TEXTURE_2D_ARRAY) {
+ gl.useProgram(nanToMagentaProgram2DArray);
+ } else if (target == gl.TEXTURE_3D) {
+ gl.useProgram(nanToMagentaProgram3D);
+ }
+ } else {
+ if (target == gl.TEXTURE_2D) {
+ gl.useProgram(program);
+ } else if (target == gl.TEXTURE_2D_ARRAY) {
+ gl.useProgram(program2DArray);
+ } else if (target == gl.TEXTURE_3D) {
+ gl.useProgram(program3D);
+ }
+ }
+ }
+
+ function checkErrorColor() {
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad from empty texture");
+ wtu.checkCanvas(gl, errorColor, "texture should be initialized to error color");
+ }
+
+ function checkSampling(target) {
+ // Check that the decoded image is consistent with NEAREST filtering
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing quad with NEAREST filtering");
+ compareRect(width, height, test.channels, width, height, raw, data, format, undefined, "NEAREST");
+
+ // Check that the decoded image is consistent with LINEAR filtering
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing quad with LINEAR filtering");
+ compareRect(width, height, test.channels, width, height, raw, data, format, undefined, "LINEAR");
+
+ debug("");
+ // Mipmaps handling
+ gl.generateMipmap(target);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
+ }
+
+ var tex;
+
+ if (useES3) {
+ // 2D texture
+ if (check2DTarget) {
+ switchProgram(gl.TEXTURE_2D);
+
+ // immutable
+ tex = setupEmptyTexture(gl.TEXTURE_2D, true);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D");
+ checkErrorColor();
+ uploadSubData(gl.TEXTURE_2D);
+ checkSampling(gl.TEXTURE_2D)
+ gl.deleteTexture(tex);
+
+ // mutable empty
+ tex = setupEmptyTexture(gl.TEXTURE_2D, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating empty compressed texture via compressedTexImage2D");
+ checkErrorColor();
+ uploadSubData(gl.TEXTURE_2D);
+ checkSampling(gl.TEXTURE_2D)
+ gl.deleteTexture(tex);
+
+ // mutable filled
+ tex = setupFilledTexture(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating filled compressed texture via compressedTexImage2D");
+ checkSampling(gl.TEXTURE_2D)
+ gl.deleteTexture(tex);
+ }
+
+ // 2D array
+ if (check2DArrayTarget) {
+ switchProgram(gl.TEXTURE_2D_ARRAY);
+
+ // immutable
+ tex = setupEmptyTexture(gl.TEXTURE_2D_ARRAY, true);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture array via texStorage3D");
+ checkErrorColor();
+ uploadSubData(gl.TEXTURE_2D_ARRAY);
+ checkSampling(gl.TEXTURE_2D_ARRAY)
+ gl.deleteTexture(tex);
+
+ // mutable empty
+ tex = setupEmptyTexture(gl.TEXTURE_2D_ARRAY, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating empty compressed texture array via compressedTexImage3D");
+ checkErrorColor();
+ uploadSubData(gl.TEXTURE_2D_ARRAY);
+ checkSampling(gl.TEXTURE_2D_ARRAY)
+ gl.deleteTexture(tex);
+
+ // mutable filled
+ tex = setupFilledTexture(gl.TEXTURE_2D_ARRAY);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating filled compressed texture array via compressedTexImage3D");
+ checkSampling(gl.TEXTURE_2D_ARRAY)
+ gl.deleteTexture(tex);
+ }
+
+ // 3D texture
+ if (check3DTarget) {
+ switchProgram(gl.TEXTURE_3D);
+ // immutable
+ tex = setupEmptyTexture(gl.TEXTURE_3D, true);
+ if (hasHdr) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed sliced 3D texture via texStorage3D");
+ checkErrorColor();
+ uploadSubData(gl.TEXTURE_3D);
+ checkSampling(gl.TEXTURE_3D)
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "allocating compressed sliced 3D texture via texStorage3D");
+ }
+ gl.deleteTexture(tex);
+
+ // mutable empty
+ tex = setupEmptyTexture(gl.TEXTURE_3D, false);
+ if (hasHdr) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating empty compressed sliced 3D texture via compressedTexImage3D");
+ checkErrorColor();
+ uploadSubData(gl.TEXTURE_3D);
+ checkSampling(gl.TEXTURE_3D)
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "allocating empty compressed sliced 3D texture via compressedTexImage3D");
+ }
+ gl.deleteTexture(tex);
+
+ // mutable filled
+ tex = setupFilledTexture(gl.TEXTURE_3D);
+ if (hasHdr) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating filled compressed sliced 3D texture via compressedTexImage3D");
+ checkSampling(gl.TEXTURE_3D)
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "allocating filled compressed sliced 3D texture via compressedTexImage3D");
+ }
+ gl.deleteTexture(tex);
+ }
+ } else {
+ // 2D texture
+ if (check2DTarget) {
+ // mutable empty
+ tex = setupEmptyTexture(gl.TEXTURE_2D, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating empty compressed texture via compressedTexImage2D");
+
+ // Skip error color check on HDR and non-sRGB formats on WebGL 1.0
+ if (!errorColorMaybeNaN()) checkErrorColor();
+ uploadSubData(gl.TEXTURE_2D);
+ checkSampling(gl.TEXTURE_2D)
+ gl.deleteTexture(tex);
+
+ // mutable filled
+ tex = setupFilledTexture(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating filled compressed texture via compressedTexImage2D");
+ checkSampling(gl.TEXTURE_2D)
+ gl.deleteTexture(tex);
+ }
+ }
+}
+
+function compareRect(
+ actualWidth, actualHeight, actualChannels,
+ dataWidth, dataHeight, expectedData,
+ testData, testFormat, tolerance, filteringMode) {
+
+ if(typeof(tolerance) == 'undefined') { tolerance = 5; }
+ var actual = new Uint8Array(actualWidth * actualHeight * 4);
+ gl.readPixels(0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+ flipImage(actual, actualWidth, actualHeight);
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(
+ actualWidth, actualHeight, dataWidth, expectedData,
+ actualChannels == 4));
+ ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(
+ actualWidth, actualHeight, actualWidth, actual,
+ actualChannels == 4));
+ div.appendChild(document.createElement('br'));
+ document.getElementById("console").appendChild(div);
+
+ var failed = false;
+ for (var yy = 0; yy < actualHeight; ++yy) {
+ for (var xx = 0; xx < actualWidth; ++xx) {
+ var actualOffset = (yy * actualWidth + xx) * 4;
+ var expectedOffset = (yy * dataWidth + xx) * 4;
+ var expected = [
+ expectedData[expectedOffset + 0],
+ expectedData[expectedOffset + 1],
+ expectedData[expectedOffset + 2],
+ (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
+ ];
+ for (var jj = 0; jj < 4; ++jj) {
+ if (Math.abs(actual[actualOffset + jj] - expected[jj]) > tolerance) {
+ failed = true;
+ var was = actual[actualOffset + 0].toString();
+ for (var j = 1; j < 4; ++j) {
+ was += "," + actual[actualOffset + j];
+ }
+ testFailed('at (' + xx + ', ' + yy +
+ ') expected: ' + expected + ' was ' + was);
+ }
+ }
+ }
+ }
+ if (!failed) {
+ testPassed("texture rendered correctly with " + filteringMode + " filtering");
+ }
+}
+
+// Builds several tests from two arrays
+// data gives each Uint8Array encoded data to use
+// formats the associate format to decode the data
+// raws gives each decoded Uint8Array data for texture comparison
+// mode 'LDR', 'LDR-sRGB', or 'HDR'
+function buildTests(data, formats, raws, mode) {
+
+ var tests = [];
+ for (var i = 0; i < data.length; ++i) {
+ var test = {
+ width: 16,
+ height: 16,
+ channels: 4,
+ data: data[i],
+ format: formats[i],
+ raw: raws[i],
+ mode: mode
+ };
+ tests.push(test);
+ }
+
+ return tests;
+}
+
+function expectedByteLength(w, h, format) {
+
+ if (format == validFormats.COMPRESSED_RGBA_ASTC_4x4_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)
+ return Math.floor((w + 3) / 4) * Math.floor((h + 3) / 4) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_5x4_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR)
+ return Math.floor((w + 4) / 5) * Math.floor((h + 3) / 4) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_5x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR)
+ return Math.floor((w + 4) / 5) * Math.floor((h + 4) / 5) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_6x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR)
+ return Math.floor((w + 5) / 6) * Math.floor((h + 4) / 5) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_6x6_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR)
+ return Math.floor((w + 5) / 6) * Math.floor((h + 5) / 6) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_8x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR)
+ return Math.floor((w + 7) / 8) * Math.floor((h + 4) / 5) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_8x6_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR)
+ return Math.floor((w + 7) / 8) * Math.floor((h + 5) / 6) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_8x8_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR)
+ return Math.floor((w + 7) / 8) * Math.floor((h + 7) / 8) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR)
+ return Math.floor((w + 9) / 10) * Math.floor((h + 4) / 5) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x6_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR)
+ return Math.floor((w + 9) / 10) * Math.floor((h + 5) / 6) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x8_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR)
+ return Math.floor((w + 9) / 10) * Math.floor((h + 7) / 8) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x10_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR)
+ return Math.floor((w + 9) / 10) * Math.floor((h + 9) / 10) * 16;
+ else if (format == validFormats.COMPRESSED_RGBA_ASTC_12x10_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR)
+ return Math.floor((w + 11) / 12) * Math.floor((h + 9) / 10) * 16;
+
+ return Math.floor((w + 11) / 12) * Math.floor((h + 11) / 12) * 16;
+}
+
+function getBlockDimensions(format) {
+ var re = /.*_(\d+)x(\d+)_KHR/;
+ for (name in validFormats) {
+ if (validFormats[name] === format) {
+ var match = name.match(re);
+ return {
+ width: parseInt(match[1], 10),
+ height: parseInt(match[2], 10)
+ };
+ }
+ }
+ testFailed('Could not find block dimensions for format ' + ctu.formatToString(ext, format));
+ return {width: 4, height: 4};
+}
+
+// Swaps two cells in an arraybuffer.
+// this function is used in the image flipping function
+function swapCell(array, i, j) {
+ var a = array[i];
+ array[i] = array[j];
+ array[j] = a;
+}
+
+function flipImage(imgBuffer, w, h) {
+ var halfHeight = h / 2;
+
+ for (var j = 0; j < halfHeight; j++) {
+ for (var i = 0; i < w; i++) {
+ var beginByte = (j * w + i) * 4;
+ var endByte = ((h - j - 1) * w + i) * 4;
+
+ swapCell(imgBuffer, beginByte, endByte);
+ swapCell(imgBuffer, beginByte + 1, endByte + 1);
+ swapCell(imgBuffer, beginByte + 2, endByte + 2);
+ swapCell(imgBuffer, beginByte + 3, endByte + 3);
+ }
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc.html
new file mode 100644
index 0000000000..8a85239ff9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_compressed_texture_etc Conformance Tests</title>
+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_compressed_texture_etc extension, if it is available.");
+
+debug("");
+
+var validFormats = {
+ COMPRESSED_R11_EAC : 0x9270,
+ COMPRESSED_SIGNED_R11_EAC : 0x9271,
+ COMPRESSED_RG11_EAC : 0x9272,
+ COMPRESSED_SIGNED_RG11_EAC : 0x9273,
+ COMPRESSED_RGB8_ETC2 : 0x9274,
+ COMPRESSED_SRGB8_ETC2 : 0x9275,
+ COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9276,
+ COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9277,
+ COMPRESSED_RGBA8_ETC2_EAC : 0x9278,
+ COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : 0x9279
+};
+
+function expectedByteLength(width, height, format) {
+ var blockSizeInBytes = 8;
+
+ var largerBlockFormats = [
+ validFormats.COMPRESSED_RG11_EAC,
+ validFormats.COMPRESSED_SIGNED_RG11_EAC,
+ validFormats.COMPRESSED_RGBA8_ETC2_EAC,
+ validFormats.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC];
+
+ if (largerBlockFormats.indexOf(format) >= 0) {
+ blockSizeInBytes = 16;
+ }
+
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * blockSizeInBytes;
+}
+
+function getBlockDimensions(format) {
+ return {width: 4, height: 4};
+}
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var gl = wtu.create3DContext();
+var WEBGL_compressed_texture_etc;
+
+var formats = null;
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
+
+ WEBGL_compressed_texture_etc = gl.getExtension("WEBGL_compressed_texture_etc");
+
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_etc", WEBGL_compressed_texture_etc !== null);
+
+ var isPositive = WEBGL_compressed_texture_etc !== null;
+
+ if (isPositive) {
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(WEBGL_compressed_texture_etc, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ for (var name in validFormats) {
+ if (validFormats.hasOwnProperty(name)) {
+ var format = validFormats[name];
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, " + format + ", 4, 4, 0, new Uint8Array(" + expectedByteLength(4, 4, format) + "))");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, " + format + ", new Uint8Array(" + expectedByteLength(4, 4, format) + "))");
+ }
+ }
+ }
+
+ var tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+
+ debug("");
+ if (contextVersion >= 2) {
+ var expectedError = isPositive ? gl.INVALID_OPERATION: [gl.INVALID_ENUM, gl.INVALID_OPERATION];
+ // `null` coerces into `0` for the PBO entrypoint, yielding INVALID_OP due to no PBO bound.
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 0, 0, null)");
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, 0, null)");
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 4, 0, 0, null)");
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, 0, null)");
+ } else {
+ shouldThrow("gl.compressedTexImage2D(gl.TEXTURE_2D, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 0, null)");
+ shouldThrow("gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, null)");
+ shouldThrow("gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 4, 0, null)");
+ shouldThrow("gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, null)");
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc1.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc1.html
new file mode 100644
index 0000000000..09a6ed0642
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-etc1.html
@@ -0,0 +1,74 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_compressed_texture_etc1 Conformance Tests</title>
+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_compressed_texture_etc1 extension, if it is available.");
+
+debug("");
+
+var validFormats = {
+ COMPRESSED_RGB_ETC1_WEBGL: 0x8D64,
+};
+
+function expectedByteLength(width, height, format) {
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
+}
+
+function getBlockDimensions(format) {
+ return {width: 4, height: 4};
+}
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var gl = wtu.create3DContext();
+var WEBGL_compressed_texture_etc1;
+
+var formats = null;
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
+
+ WEBGL_compressed_texture_etc1 = gl.getExtension("WEBGL_compressed_texture_etc1");
+
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_etc1", WEBGL_compressed_texture_etc1 !== null);
+
+ if (WEBGL_compressed_texture_etc1 !== null) {
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(WEBGL_compressed_texture_etc1, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-pvrtc.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-pvrtc.html
new file mode 100644
index 0000000000..465f44a9cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-pvrtc.html
@@ -0,0 +1,371 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL WEBGL_compressed_texture_pvrtc Conformance Tests</title>
+<style>
+img {
+ border: 1px solid black;
+ margin-right: 1em;
+}
+.testimages {
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_compressed_texture_pvrtc extension, if it is available.");
+
+debug("");
+
+var pvrtc_4x4_2bpp = new Uint8Array([
+ 0x77, 0x22, 0x77, 0x22, 0xbb, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+]);
+
+var pvrtc_4x4_4bpp = new Uint8Array([
+ 0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80, 0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+]);
+
+var pvrtc_4x4_rgba_decoded = new Uint8Array([
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xba, 0x44,
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb7, 0x44,
+]);
+
+var pvrtc_4x4_rgb_decoded = new Uint8Array([
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xba, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb7, 0xff,
+]);
+
+var wtu = WebGLTestUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var program = wtu.setupTexturedQuad(gl);
+var ext = null;
+var vao = null;
+var validFormats = {
+ COMPRESSED_RGB_PVRTC_4BPPV1_IMG : 0x8C00,
+ COMPRESSED_RGB_PVRTC_2BPPV1_IMG : 0x8C01,
+ COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : 0x8C02,
+ COMPRESSED_RGBA_PVRTC_2BPPV1_IMG : 0x8C03,
+};
+var name;
+var supportedFormats;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
+ if (!ext) {
+ testPassed("No WEBGL_compressed_texture_pvrtc support -- this is legal");
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled WEBGL_compressed_texture_pvrtc extension");
+
+ runSupportedTest(true);
+ runTestExtension();
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
+ if (name !== undefined) {
+ if (extensionEnabled) {
+ testPassed("WEBGL_compressed_texture_pvrtc listed as supported and getExtension succeeded");
+ } else {
+ testFailed("WEBGL_compressed_texture_pvrtc listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("WEBGL_compressed_texture_pvrtc not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("WEBGL_compressed_texture_pvrtc not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+
+function runTestDisabled() {
+ debug("Testing binding enum with extension disabled");
+
+ supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
+ shouldBe("supportedFormats", "[]");
+}
+
+function formatExists(format, supportedFormats) {
+ for (var ii = 0; ii < supportedFormats.length; ++ii) {
+ if (format == supportedFormats[ii]) {
+ testPassed("supported format " + formatToString(format) + " is exists");
+ return;
+ }
+ }
+ testFailed("supported format " + formatToString(format) + " does not exist");
+}
+
+function formatToString(format) {
+ for (var p in ext) {
+ if (ext[p] == format) {
+ return p;
+ }
+ }
+ return "0x" + format.toString(16);
+}
+
+function runTestExtension() {
+ debug("Testing WEBGL_compressed_texture_pvrtc");
+
+ // check that all format enums exist.
+ for (name in validFormats) {
+ var expected = "0x" + validFormats[name].toString(16);
+ var actual = "ext['" + name + "']";
+ shouldBe(actual, expected);
+ }
+
+ supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
+ // There should be exactly 4 formats for both WebGL 1.0 and WebGL 2.0.
+ shouldBe("supportedFormats.length", "4");
+
+ // check that all 4 formats exist
+ for (var name in validFormats.length) {
+ formatExists(validFormats[name], supportedFormats);
+ }
+
+ // Test each format
+ testPVRTC_RGBA_2BPP();
+ testPVRTC_RGB_2BPP();
+ testPVRTC_RGBA_4BPP();
+ testPVRTC_RGB_4BPP();
+}
+
+function testPVRTC_RGBA_2BPP() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: pvrtc_4x4_2bpp,
+ raw: pvrtc_4x4_rgba_decoded,
+ format: ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
+ }
+ ];
+ testPVRTCTextures(tests);
+}
+
+function testPVRTC_RGB_2BPP() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: pvrtc_4x4_2bpp,
+ raw: pvrtc_4x4_rgb_decoded,
+ format: ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
+ }
+ ];
+ testPVRTCTextures(tests);
+}
+
+function testPVRTC_RGBA_4BPP() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: pvrtc_4x4_4bpp,
+ raw: pvrtc_4x4_rgba_decoded,
+ format: ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
+ }
+ ];
+ testPVRTCTextures(tests);
+}
+
+function testPVRTC_RGB_4BPP() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: pvrtc_4x4_4bpp,
+ raw: pvrtc_4x4_rgb_decoded,
+ format: ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
+ }
+ ];
+ testPVRTCTextures(tests);
+}
+
+function testPVRTCTextures(tests) {
+ debug("<hr/>");
+ for (var ii = 0; ii < tests.length; ++ii) {
+ testPVRTCTexture(tests[ii]);
+ }
+}
+
+function testPVRTCTexture(test) {
+ var data = new Uint8Array(test.data);
+ var width = test.width;
+ var height = test.height;
+ var format = test.format;
+ var uncompressedData = test.raw;
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+ debug("testing " + formatToString(format) + " " + width + "x" + height);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
+ wtu.clearAndDrawUnitQuad(gl);
+ compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "NEAREST");
+ // Test again with linear filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "LINEAR");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "compressedTexSubImage2D allowed for reloading of complete textures");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 2, 0, width - 2, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 2, width, height - 2, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
+}
+
+function insertImg(element, caption, img) {
+ var div = document.createElement("div");
+ div.appendChild(img);
+ var label = document.createElement("div");
+ label.appendChild(document.createTextNode(caption));
+ div.appendChild(label);
+ element.appendChild(div);
+}
+
+function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
+ var scale = 8;
+ var c = document.createElement("canvas");
+ c.width = imageWidth * scale;
+ c.height = imageHeight * scale;
+ var ctx = c.getContext("2d");
+ for (var yy = 0; yy < imageHeight; ++yy) {
+ for (var xx = 0; xx < imageWidth; ++xx) {
+ var offset = (yy * dataWidth + xx) * 4;
+ ctx.fillStyle = "rgba(" +
+ data[offset + 0] + "," +
+ data[offset + 1] + "," +
+ data[offset + 2] + "," +
+ (alpha ? data[offset + 3] / 255 : 1) + ")";
+ ctx.fillRect(xx * scale, yy * scale, scale, scale);
+ }
+ }
+ return wtu.makeImageFromCanvas(c);
+}
+function compareRect(
+ actualWidth, actualHeight, actualChannels,
+ dataWidth, dataHeight, expectedData,
+ testData, testFormat, tolerance, filteringMode) {
+ if(typeof(tolerance) == 'undefined') { tolerance = 5; }
+ var actual = new Uint8Array(actualWidth * actualHeight * 4);
+ gl.readPixels(
+ 0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ insertImg(div, "expected", makeImage(
+ actualWidth, actualHeight, dataWidth, expectedData,
+ actualChannels == 4));
+ insertImg(div, "actual", makeImage(
+ actualWidth, actualHeight, actualWidth, actual,
+ actualChannels == 4));
+ div.appendChild(document.createElement('br'));
+ document.getElementById("console").appendChild(div);
+
+ var failed = false;
+ for (var yy = 0; yy < actualHeight; ++yy) {
+ for (var xx = 0; xx < actualWidth; ++xx) {
+ var actualOffset = (yy * actualWidth + xx) * 4;
+ var expectedOffset = (yy * dataWidth + xx) * 4;
+ var expected = [
+ expectedData[expectedOffset + 0],
+ expectedData[expectedOffset + 1],
+ expectedData[expectedOffset + 2],
+ (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
+ ];
+ for (var jj = 0; jj < 4; ++jj) {
+ if (Math.abs(actual[actualOffset + jj] - expected[jj]) > tolerance) {
+ failed = true;
+ var was = actual[actualOffset + 0].toString();
+ for (var j = 1; j < 4; ++j) {
+ was += "," + actual[actualOffset + j];
+ }
+ testFailed('at (' + xx + ', ' + yy +
+ ') expected: ' + expected + ' was ' + was);
+ }
+ }
+ }
+ }
+ if (!failed) {
+ testPassed("texture rendered correctly with " + filteringMode + " filtering");
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-s3tc-srgb.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-s3tc-srgb.html
new file mode 100644
index 0000000000..91fc3f0b1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-s3tc-srgb.html
@@ -0,0 +1,912 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compressed-texture-utils.js"></script>
+<title>WebGL WEBGL_compressed_texture_s3tc_srgb Conformance Tests</title>
+<style>
+img {
+ border: 1px solid black;
+ margin-right: 1em;
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc_srgb extension, if it is available.");
+
+debug("");
+
+/*
+These tests use the same payloads as a non-sRGB version. When running side-by-side,
+images from these tests must appear much darker than linear counterparts.
+*/
+
+/*
+BC1 (DXT1) block
+e0 = [ 0, 255, 0]
+e1 = [255, 0, 0]
+e0 < e1, so it uses 3-color mode
+
+local palette
+ 0: [ 0, 255, 0, 255]
+ 1: [255, 0, 0, 255]
+ 2: [128, 128, 0, 255]
+ 3: [ 0, 0, 0, 255] // for BC1 RGB
+ 3: [ 0, 0, 0, 0] // for BC1 RGBA
+selectors
+ 3 2 1 0
+ 2 2 1 0
+ 1 1 1 0
+ 0 0 0 0
+
+Extending this block with opaque alpha and uploading as BC2 or BC3
+will generate wrong colors because BC2 and BC3 do not have 3-color mode.
+*/
+var img_4x4_rgba_dxt1 = new Uint8Array([
+ 0xE0, 0x07, 0x00, 0xF8, 0x1B, 0x1A, 0x15, 0x00
+]);
+
+/*
+BC2 (DXT3) block
+
+Quantized alpha values
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 A B
+ C D E F
+
+RGB block
+e0 = [255, 0, 0]
+e1 = [ 0, 255, 0]
+BC2 has only 4-color mode
+
+local palette
+ 0: [255, 0, 0]
+ 1: [ 0, 255, 0]
+ 2: [170, 85, 0]
+ 3: [ 85, 170, 0]
+selectors
+ 0 1 2 3
+ 1 1 2 3
+ 2 2 2 3
+ 3 3 3 3
+*/
+var img_4x4_rgba_dxt3 = new Uint8Array([
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ 0x00, 0xF8, 0xE0, 0x07, 0xE4, 0xE5, 0xEA, 0xFF
+]);
+
+/*
+BC3 (DXT5) block
+
+Alpha block (aka DXT5A)
+e0 = 255
+e1 = 0
+e0 > e1, so using 6 intermediate points
+local palette
+ 255, 0, 219, 182, 146, 109, 73, 36
+selectors
+ 0 1 2 3
+ 1 2 3 4
+ 2 3 4 5
+ 3 4 5 6
+
+RGB block
+e0 = [255, 0, 0]
+e1 = [ 0, 255, 0]
+BC3 has only 4-color mode
+
+local palette
+ 0: [255, 0, 0]
+ 1: [ 0, 255, 0]
+ 2: [170, 85, 0]
+ 3: [ 85, 170, 0]
+selectors
+ 3 2 1 0
+ 3 2 1 1
+ 3 2 2 2
+ 3 3 3 3
+*/
+var img_4x4_rgba_dxt5 = new Uint8Array([
+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
+ 0x00, 0xF8, 0xE0, 0x07, 0x1B, 0x5B, 0xAB, 0xFF
+]);
+
+/*
+8x8 block endpoints use half-intensity values (appear darker than 4x4)
+*/
+var img_8x8_rgba_dxt1 = new Uint8Array([
+ 0xe0,0x03,0x00,0x78,0x13,0x10,0x15,0x00,
+ 0x0f,0x00,0xe0,0x7b,0x11,0x10,0x15,0x00,
+ 0xe0,0x03,0x0f,0x78,0x44,0x45,0x40,0x55,
+ 0x0f,0x00,0xef,0x03,0x44,0x45,0x40,0x55
+]);
+var img_8x8_rgba_dxt3 = new Uint8Array([
+ 0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0x78,0xe0,0x03,0x44,0x45,0x40,0x55,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x7b,0x0f,0x00,0x44,0x45,0x40,0x55,
+ 0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x03,0x0f,0x00,0x11,0x10,0x15,0x00
+]);
+var img_8x8_rgba_dxt5 = new Uint8Array([
+0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x78,0xe0,0x03,0x44,0x45,0x40,0x55,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x7b,0x0f,0x00,0x44,0x45,0x40,0x55,
+ 0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x03,0xef,0x00,0x11,0x10,0x15,0x00
+]);
+
+var wtu = WebGLTestUtils;
+var ctu = CompressedTextureUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var program = wtu.setupTexturedQuad(gl);
+var ext = null;
+var vao = null;
+var validFormats = {
+ 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,
+};
+var name;
+var supportedFormats;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc_srgb");
+ if (!ext) {
+ testPassed("No WEBGL_compressed_texture_s3tc_srgb support -- this is legal");
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc_srgb", false);
+ } else {
+ testPassed("Successfully enabled WEBGL_compressed_texture_s3tc_srgb extension");
+
+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc_srgb", true);
+ runTestExtension();
+ }
+}
+
+function expectedByteLength(width, height, format) {
+ if (format == validFormats.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || format == validFormats.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
+ }
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
+}
+
+function getBlockDimensions(format) {
+ return {width: 4, height: 4};
+}
+
+function runTestExtension() {
+ debug("");
+ debug("Testing WEBGL_compressed_texture_s3tc_srgb");
+
+ // Test that enum values are listed correctly in supported formats and in the extension object.
+ ctu.testCompressedFormatsListed(gl, validFormats);
+ ctu.testCorrectEnumValuesInExt(ext, validFormats);
+ // Test that texture upload buffer size is validated correctly.
+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
+
+ // Test each format
+ testDXT1_SRGB();
+ testDXT1_SRGB_ALPHA();
+ testDXT3_SRGB_ALPHA();
+ testDXT5_SRGB_ALPHA();
+
+ // Test compressed PBOs with a single format
+ if (contextVersion >= 2) {
+ testDXT5_SRGB_ALPHA_PBO();
+ }
+
+ // Test TexImage validation on level dimensions combinations.
+ debug("");
+ debug("When level equals 0, width and height must be a multiple of 4.");
+ debug("When level is larger than 0, this constraint doesn't apply.");
+ ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { level: 0, width: 4, height: 3, expectation: gl.INVALID_OPERATION, message: "0: 4x3" },
+ { level: 0, width: 3, height: 4, expectation: gl.INVALID_OPERATION, message: "0: 3x4" },
+ { level: 0, width: 2, height: 2, expectation: gl.INVALID_OPERATION, message: "0: 2x2" },
+ { level: 0, width: 4, height: 4, expectation: gl.NO_ERROR, message: "0: 4x4" },
+ { level: 1, width: 2, height: 2, expectation: gl.NO_ERROR, message: "1: 2x2" },
+ { level: 2, width: 1, height: 1, expectation: gl.NO_ERROR, message: "2: 1x1" },
+ ]);
+
+ ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 16, 16,
+ [
+ { xoffset: 0, yoffset: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
+ { xoffset: 0, yoffset: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
+ { xoffset: 1, yoffset: 0, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
+ { xoffset: 0, yoffset: 1, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
+ { xoffset: 12, yoffset: 12, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ ]);
+
+ if (contextVersion >= 2) {
+ debug("");
+ debug("Testing NPOT textures");
+ ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { level: 0, width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
+ { level: 1, width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
+ { level: 2, width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
+ { level: 3, width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
+ ]);
+
+ debug("");
+ debug("Testing partial updates");
+ ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 12, 12,
+ [
+ { xoffset: 0, yoffset: 0, width: 4, height: 3,
+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
+ { xoffset: 0, yoffset: 0, width: 3, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
+ { xoffset: 1, yoffset: 0, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
+ { xoffset: 0, yoffset: 1, width: 4, height: 4,
+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
+ { xoffset: 8, yoffset: 8, width: 4, height: 4,
+ expectation: gl.NO_ERROR, message: "is valid" },
+ ]);
+
+ debug("");
+ debug("Testing immutable NPOT textures");
+ ctu.testTexStorageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
+ [
+ { width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
+ { width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
+ { width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
+ { width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
+ ]);
+ }
+}
+
+function testDXT1_SRGB() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 3,
+ data: img_4x4_rgba_dxt1,
+ format: ext.COMPRESSED_SRGB_S3TC_DXT1_EXT,
+ hasAlpha: false,
+ },
+ { width: 8,
+ height: 8,
+ channels: 3,
+ data: img_8x8_rgba_dxt1,
+ format: ext.COMPRESSED_SRGB_S3TC_DXT1_EXT,
+ hasAlpha: false,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rgba_dxt1
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT1_SRGB_ALPHA() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_dxt1,
+ format: ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+ // This is a special case -- the texture is still opaque
+ // though it's RGBA.
+ hasAlpha: false,
+ },
+ { width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_dxt1,
+ format: ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+ // This is a special case -- the texture is still opaque
+ // though it's RGBA.
+ hasAlpha: false,
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT3_SRGB_ALPHA() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_dxt3,
+ format: ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+ hasAlpha: true,
+ },
+ { width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_dxt3,
+ format: ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+ hasAlpha: true,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rgba_dxt3
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXT5_SRGB_ALPHA() {
+ var tests = [
+ { width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_dxt5,
+ format: ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+ hasAlpha: true,
+ },
+ { width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_dxt5,
+ format: ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+ hasAlpha: true,
+ subX0: 0,
+ subY0: 0,
+ subWidth: 4,
+ subHeight: 4,
+ subData: img_4x4_rgba_dxt5
+ }
+ ];
+ testDXTTextures(tests);
+}
+
+function testDXTTextures(tests) {
+ debug("<hr/>");
+ for (var ii = 0; ii < tests.length; ++ii) {
+ testDXTTexture(tests[ii], false);
+ if (contextVersion >= 2) {
+ debug("<br/>");
+ testDXTTexture(tests[ii], true);
+ }
+ }
+}
+
+function uncompressDXTBlockSRGB(
+ destBuffer, destX, destY, destWidth, src, srcOffset, format) {
+ // Decoding routines follow D3D11 functional spec wrt
+ // endpoints unquantization and interpolation.
+ // Some hardware may produce slightly different values - it's normal.
+
+ function make565(src, offset) {
+ return src[offset + 0] + (src[offset + 1] << 8);
+ }
+ function make8888From565(c) {
+ // These values exactly match hw decoder when selectors are 0 or 1.
+ function replicateBits(v, w) {
+ return (v << (8 - w)) | (v >> (w + w - 8));
+ }
+ return [
+ replicateBits((c >> 11) & 0x1F, 5),
+ replicateBits((c >> 5) & 0x3F, 6),
+ replicateBits((c >> 0) & 0x1F, 5),
+ 255
+ ];
+ }
+ function mix(mult, c0, c1, div) {
+ var r = [];
+ for (var ii = 0; ii < c0.length; ++ii) {
+ // For green channel (6 bits), this interpolation exactly matches hw decoders
+
+ // For red and blue channels (5 bits), this interpolation exactly
+ // matches only some hw decoders and stays within acceptable range for others.
+ r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div + 0.5);
+ }
+ return r;
+ }
+ var isDXT1 = format == ext.COMPRESSED_SRGB_S3TC_DXT1_EXT ||
+ format == ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ var colorOffset = srcOffset + (isDXT1 ? 0 : 8);
+ var color0 = make565(src, colorOffset + 0);
+ var color1 = make565(src, colorOffset + 2);
+ var c0gtc1 = color0 > color1 || !isDXT1;
+ var rgba0 = make8888From565(color0);
+ var rgba1 = make8888From565(color1);
+ var colors = [
+ rgba0,
+ rgba1,
+ c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
+ c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
+ ];
+
+ // yea I know there is a lot of math in this inner loop.
+ // so sue me.
+ for (var yy = 0; yy < 4; ++yy) {
+ var pixels = src[colorOffset + 4 + yy];
+ for (var xx = 0; xx < 4; ++xx) {
+ var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
+ var code = (pixels >> (xx * 2)) & 0x3;
+ var srcColor = colors[code];
+ var alpha;
+ switch (format) {
+ case ext.COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ alpha = 255;
+ break;
+ case ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ alpha = (code == 3 && !c0gtc1) ? 0 : 255;
+ break;
+ case ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ {
+ var alpha0 = src[srcOffset + yy * 2 + (xx >> 1)];
+ var alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF;
+ alpha = alpha1 | (alpha1 << 4);
+ }
+ break;
+ case ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ {
+ var alpha0 = src[srcOffset + 0];
+ var alpha1 = src[srcOffset + 1];
+ var alphaOff = (yy >> 1) * 3 + 2;
+ var alphaBits =
+ src[srcOffset + alphaOff + 0] +
+ src[srcOffset + alphaOff + 1] * 256 +
+ src[srcOffset + alphaOff + 2] * 65536;
+ var alphaShift = (yy % 2) * 12 + xx * 3;
+ var alphaCode = (alphaBits >> alphaShift) & 0x7;
+ if (alpha0 > alpha1) {
+ switch (alphaCode) {
+ case 0:
+ alpha = alpha0;
+ break;
+ case 1:
+ alpha = alpha1;
+ break;
+ default:
+ alpha = Math.floor(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7.0 + 0.5);
+ break;
+ }
+ } else {
+ switch (alphaCode) {
+ case 0:
+ alpha = alpha0;
+ break;
+ case 1:
+ alpha = alpha1;
+ break;
+ case 6:
+ alpha = 0;
+ break;
+ case 7:
+ alpha = 255;
+ break;
+ default:
+ alpha = Math.floor(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5.0 + 0.5);
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ throw "bad format";
+ }
+ destBuffer[dstOff + 0] = sRGBChannelToLinear(srcColor[0]);
+ destBuffer[dstOff + 1] = sRGBChannelToLinear(srcColor[1]);
+ destBuffer[dstOff + 2] = sRGBChannelToLinear(srcColor[2]);
+ destBuffer[dstOff + 3] = alpha;
+ }
+ }
+}
+
+function getBlockSize(format) {
+ var isDXT1 = format == ext.COMPRESSED_SRGB_S3TC_DXT1_EXT ||
+ format == ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ return isDXT1 ? 8 : 16;
+}
+
+function uncompressDXTSRGB(width, height, data, format) {
+ if (width % 4 || height % 4) throw "bad width or height";
+
+ var dest = new Uint8Array(width * height * 4);
+ var blocksAcross = width / 4;
+ var blocksDown = height / 4;
+ var blockSize = getBlockSize(format);
+ for (var yy = 0; yy < blocksDown; ++yy) {
+ for (var xx = 0; xx < blocksAcross; ++xx) {
+ uncompressDXTBlockSRGB(
+ dest, xx * 4, yy * 4, width, data,
+ (yy * blocksAcross + xx) * blockSize, format);
+ }
+ }
+ return dest;
+}
+
+function uncompressDXTIntoSubRegionSRGB(width, height, subX0, subY0, subWidth, subHeight, data, format)
+{
+ if (width % 4 || height % 4 || subX0 % 4 || subY0 % 4 || subWidth % 4 || subHeight % 4)
+ throw "bad dimension";
+
+ var dest = new Uint8Array(width * height * 4);
+ // Zero-filled DXT1 texture represents [0, 0, 0, 255]
+ if (format == ext.COMPRESSED_SRGB_S3TC_DXT1_EXT || format == ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) {
+ for (var i = 3; i < dest.length; i += 4) dest[i] = 255;
+ }
+ var blocksAcross = subWidth / 4;
+ var blocksDown = subHeight / 4;
+ var blockSize = getBlockSize(format);
+ for (var yy = 0; yy < blocksDown; ++yy) {
+ for (var xx = 0; xx < blocksAcross; ++xx) {
+ uncompressDXTBlockSRGB(
+ dest, subX0 + xx * 4, subY0 + yy * 4, width, data,
+ (yy * blocksAcross + xx) * blockSize, format);
+ }
+ }
+ return dest;
+}
+
+function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) {
+ var bytesPerLine = width * 4;
+ var srcOffset = srcX * 4 + srcY * stride;
+ var dstOffset = dstX * 4 + dstY * stride;
+ for (; height > 0; --height) {
+ for (var ii = 0; ii < bytesPerLine; ++ii) {
+ data[dstOffset + ii] = data[srcOffset + ii];
+ }
+ srcOffset += stride;
+ dstOffset += stride;
+ }
+}
+
+function testDXTTexture(test, useTexStorage) {
+ var data = new Uint8Array(test.data);
+ var width = test.width;
+ var height = test.height;
+ var format = test.format;
+
+ var uncompressedData = uncompressDXTSRGB(width, height, data, format);
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+ debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height +
+ (useTexStorage ? " via texStorage2D" : " via compressedTexImage2D"));
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ if (useTexStorage) {
+ if (test.subData) {
+ var uncompressedDataSub = uncompressDXTIntoSubRegionSRGB(
+ width, height, test.subX0, test.subY0, test.subWidth, test.subHeight, test.subData, format);
+ var tex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D");
+ gl.compressedTexSubImage2D(
+ gl.TEXTURE_2D, 0, test.subX0, test.subY0, test.subWidth, test.subHeight, format, test.subData);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture data via compressedTexSubImage2D");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 1");
+ compareRect(width, height, test.channels, uncompressedDataSub, "NEAREST");
+
+ // Clean up and recover
+ gl.deleteTexture(tex1);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ }
+
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ var clearColor = (test.hasAlpha ? [0, 0, 0, 0] : [0, 0, 0, 255]);
+ wtu.checkCanvas(gl, clearColor, "texture should be initialized to black");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture data via compressedTexSubImage2D");
+ } else {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ }
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after clearing generateMipmap error");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 1");
+ compareRect(width, height, test.channels, uncompressedData, "NEAREST");
+ // Test again with linear filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 2");
+ compareRect(width, height, test.channels, uncompressedData, "LINEAR");
+
+ if (!useTexStorage) {
+ // It's not allowed to redefine textures defined via texStorage2D.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+ if (width == 4) {
+ // The width/height of the implied base level must be a multiple of the block size.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ }
+ if (height == 4) {
+ // The width/height of the implied base level must be a multiple of the block size.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ }
+ }
+
+ // pick a wrong format that uses the same amount of data.
+ var wrongFormat;
+ switch (format) {
+ case ext.COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ wrongFormat = ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ break;
+ case ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ wrongFormat = ext.COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ break;
+ case ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ wrongFormat = ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ break;
+ case ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ wrongFormat = ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ break;
+ }
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 4, 0, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "dimension out of range");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 4, width, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "dimension out of range");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+ var subData = new Uint8Array(data.buffer, 0, getBlockSize(format));
+
+ if (width == 8 && height == 8) {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+ }
+
+ var stride = width * 4;
+ for (var yoff = 0; yoff < height; yoff += 4) {
+ for (var xoff = 0; xoff < width; xoff += 4) {
+ copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ // First test NEAREST filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ wtu.clearAndDrawUnitQuad(gl);
+ compareRect(width, height, test.channels, uncompressedData, "NEAREST");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ // Next test LINEAR filtering.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ compareRect(width, height, test.channels, uncompressedData, "LINEAR");
+ }
+ }
+}
+
+function testDXT5_SRGB_ALPHA_PBO() {
+ debug("");
+ debug("testing PBO uploads");
+ var width = 8;
+ var height = 8;
+ var channels = 4;
+ var data = img_8x8_rgba_dxt5;
+ var format = ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ var uncompressedData = uncompressDXTSRGB(width, height, data, format);
+
+ var tex = gl.createTexture();
+
+ // First, PBO size = image size
+ var pbo1 = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo1);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a PBO");
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data.length, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a texture from a PBO");
+
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ compareRect(width, height, channels, uncompressedData, "NEAREST");
+
+ // Clear the texture before the next test
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, new Uint8Array(data.length));
+
+ // Second, image is just a subrange of the PBO
+ var pbo2 = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo2);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data.length*3, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.PIXEL_UNPACK_BUFFER, data.length, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a PBO subrange");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data.length, data.length);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a texture from a PBO subrange");
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad");
+ compareRect(width, height, channels, uncompressedData, "NEAREST");
+}
+
+// See EXT_texture_sRGB, Section 3.8.x, sRGB Texture Color Conversion.
+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 compareRect(width, height, channels, expectedData, filteringMode) {
+ var actual = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "reading back pixels");
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(width, height, width, expectedData, true));
+ ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(width, height, width, actual, true));
+ div.appendChild(document.createElement('br'));
+ document.getElementById("console").appendChild(div);
+
+ var failed = false;
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ var expected = expectedData.slice(offset, offset + 4);
+ // Compare RGB values
+ for (var jj = 0; jj < 3; ++jj) {
+ // Acceptable interpolation error depends on endpoints:
+ // 1.0 / 255.0 + 0.03 * max(abs(endpoint0 - endpoint1), abs(endpoint0_p - endpoint1_p))
+ // For simplicity, assume the worst case (e0 is 0.0, e1 is 1.0). After conversion to unorm8, it is 9.
+ if (Math.abs(actual[offset + jj] - expected[jj]) > 9) {
+ var was = actual[offset + 0].toString();
+ for (var j = 1; j < 3; ++j) {
+ was += "," + actual[offset + j];
+ }
+ failed = true;
+ testFailed('RGB at (' + xx + ', ' + yy +
+ ') expected: ' + expected + ' ± 9 was ' + was);
+ }
+ }
+
+ if (channels == 3) {
+ // BC1 RGB is allowed to be mapped to BC1 RGBA.
+ // In such a case, 3-color mode black value can be transparent:
+ // [0, 0, 0, 0] instead of [0, 0, 0, 255].
+
+ if (actual[offset + 3] != expected[3]) {
+ // Got non-opaque value for opaque format
+
+ // Check RGB values. Notice, that the condition here
+ // is more permissive than needed since we don't have
+ // compressed data at this point.
+ if (actual[offset] == 0 &&
+ actual[offset + 1] == 0 &&
+ actual[offset + 2] == 0 &&
+ actual[offset + 3] == 0) {
+ debug("<b>DXT1 SRGB is mapped to DXT1 SRGB ALPHA</b>");
+ } else {
+ failed = true;
+ testFailed('Alpha at (' + xx + ', ' + yy +
+ ') expected: ' + expected[3] + ' was ' + actual[offset + 3]);
+ }
+ }
+ } else {
+ // Compare Alpha values
+ // Acceptable interpolation error depends on endpoints:
+ // 1.0 / 65535.0 + 0.03 * max(abs(endpoint0 - endpoint1), abs(endpoint0_p - endpoint1_p))
+ // For simplicity, assume the worst case (e0 is 0.0, e1 is 1.0). After conversion to unorm8, it is 8.
+ if (Math.abs(actual[offset + 3] - expected[3]) > 8) {
+ var was = actual[offset + 3].toString();
+ failed = true;
+ testFailed('Alpha at (' + xx + ', ' + yy +
+ ') expected: ' + expected + ' ± 8 was ' + was);
+ }
+ }
+ }
+ }
+ if (!failed) {
+ testPassed("texture rendered correctly with " + filteringMode + " filtering");
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-size-limit.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-size-limit.html
new file mode 100644
index 0000000000..ab50e64d07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-compressed-texture-size-limit.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL compressed texture size limit conformance test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/webgl-compressed-texture-size-limit.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Checks size limit of the webgl compressed textures")
+
+// ArrayBuffers can be at most 4GB (minus 1 byte), but any allocations larger than 1 GB are unreliable in practice. So limit allocations to 1 GB.
+// Textures that are wide in just one dimension can still be used to test max TEXTURE_2D size limit even if we can't allocate space for huge square textures.
+// Use a fairly conservative limit for positive test cube map size so OOM is avoided.
+runCompressedTextureSizeLimitTest(Math.pow(2, 30), 2048);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-renderer-info.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-renderer-info.html
new file mode 100644
index 0000000000..7901225db7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-renderer-info.html
@@ -0,0 +1,104 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WebGL_debug_renderer_info Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 1px; height: 1px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing standard derivatives -->
+
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_debug_renderer_info extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+var ext = null;
+var vao = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("WEBGL_debug_renderer_info");
+ if (!ext) {
+ testPassed("No WEBGL_debug_renderer_info support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled WEBGL_debug_renderer_info extension");
+
+ runSupportedTest(true);
+ runTestEnabled();
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("WEBGL_debug_renderer_info") >= 0) {
+ if (extensionEnabled) {
+ testPassed("WEBGL_debug_renderer_info listed as supported and getExtension succeeded");
+ } else {
+ testFailed("WEBGL_debug_renderer_info listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("WEBGL_debug_renderer_info not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("WEBGL_debug_renderer_info not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runTestDisabled() {
+ debug("Testing enums with extension disabled");
+
+ // Use the constants directly as we don't have the extension
+
+ var UNMASKED_VENDOR_WEBGL = 0x9245;
+ gl.getParameter(UNMASKED_VENDOR_WEBGL);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "UNMASKED_VENDOR_WEBGL should not be queryable if extension is disabled");
+
+ var UNMASKED_RENDERER_WEBGL = 0x9246;
+ gl.getParameter(UNMASKED_RENDERER_WEBGL);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "UNMASKED_RENDERER_WEBGL should not be queryable if extension is disabled");
+}
+
+function runTestEnabled() {
+ debug("Testing enums with extension enabled");
+
+ shouldBe("ext.UNMASKED_VENDOR_WEBGL", "0x9245");
+ gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "UNMASKED_VENDOR_WEBGL query should succeed if extension is enable");
+
+ shouldBe("ext.UNMASKED_RENDERER_WEBGL", "0x9246");
+ gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "UNMASKED_RENDERER_WEBGL query should succeed if extension is enable");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-shaders.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-shaders.html
new file mode 100644
index 0000000000..9a95736a86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-debug-shaders.html
@@ -0,0 +1,144 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WebGL_debug_shaders Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 1px; height: 1px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing standard derivatives -->
+
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_debug_shaders extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+var ext = null;
+var shader = null;
+var program = null;
+var info = null;
+var translatedSource;
+var newTranslatedSource;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("WEBGL_debug_shaders");
+ if (!ext) {
+ testPassed("No WEBGL_debug_shaders support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled WEBGL_debug_shaders extension");
+
+ runSupportedTest(true);
+ runTestEnabled();
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("WEBGL_debug_shaders") >= 0) {
+ if (extensionEnabled) {
+ testPassed("WEBGL_debug_shaders listed as supported and getExtension succeeded");
+ } else {
+ testFailed("WEBGL_debug_shaders listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("WEBGL_debug_shaders not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("WEBGL_debug_shaders not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runTestEnabled() {
+ debug("Testing function with extension enabled");
+
+ var shaderInfos = [
+ {
+ source: "void main() { gl_Position = vec4(1.0, 0.0, 0.0, 1.0); }",
+ type: gl.VERTEX_SHADER
+ },
+ {
+ source: "void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }",
+ type: gl.FRAGMENT_SHADER
+ }
+ ];
+
+ // Do this twice to test for caching issues.
+ for (var jj = 0; jj < 2; ++jj) {
+ debug("pass:" + (jj + 1));
+ program = gl.createProgram();
+ for (var ii = 0; ii < shaderInfos.length; ++ii) {
+ info = shaderInfos[ii];
+
+ shader = gl.createShader(info.type);
+
+ // if no source has been defined or compileShader() has not been called,
+ // getTranslatedShaderSource() should return an empty string.
+ shouldBe("ext.getTranslatedShaderSource(shader)", '""');
+ gl.shaderSource(shader, info.source);
+ shouldBe("ext.getTranslatedShaderSource(shader)", '""');
+ gl.compileShader(shader);
+ shouldBeTrue("gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
+ translatedSource = ext.getTranslatedShaderSource(shader);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No gl error should occur");
+ if (translatedSource && translatedSource.length > 0) {
+ testPassed("Successfully called getTranslatedShaderSource()");
+ } else {
+ testFailed("Calling getTranslatedShaderSource() failed");
+ }
+ gl.attachShader(program, shader);
+ }
+ gl.linkProgram(program);
+ shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)");
+ }
+
+ // Test changing the source. Make sure we get the correct source each time.
+ debug("test changing source");
+ shader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(shader, "void main() { gl_FragColor = vec4(gl_FragCoord.x, 0.0, 0.0, 1.0); }");
+ gl.compileShader(shader);
+ shouldBeTrue("gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
+ shouldThrow("ext.getTranslatedShaderSource(null)");
+ translatedSource = ext.getTranslatedShaderSource(shader);
+ shouldBeTrue('translatedSource && translatedSource.indexOf("gl_FragCoord") >= 0');
+ // change the source but don't compile.
+ gl.shaderSource(shader, "void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }");
+ // the source should NOT change. It should be the same as the old source.
+ newTranslatedSource = ext.getTranslatedShaderSource(shader);
+ shouldBe('newTranslatedSource', 'translatedSource');
+ // now compile.
+ gl.compileShader(shader);
+ shouldBeTrue("gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
+ // the source should have change.
+ newTranslatedSource = ext.getTranslatedShaderSource(shader);
+ shouldNotBe('newTranslatedSource', 'translatedSource');
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-depth-texture.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-depth-texture.html
new file mode 100644
index 0000000000..f2318cc1d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-depth-texture.html
@@ -0,0 +1,377 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL WEBGL_depth_texture Conformance Tests</title>
+</head>
+<body>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D u_texture;
+uniform vec2 u_resolution;
+void main()
+{
+ vec2 texcoord = (gl_FragCoord.xy - vec2(0.5)) / (u_resolution - vec2(1.0));
+ gl_FragColor = texture2D(u_texture, texcoord);
+}
+</script>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_depth_texture extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var program = wtu.setupTexturedQuad(gl);
+var ext = null;
+var vao = null;
+var tex;
+var name;
+var supportedFormats;
+var canvas2;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture");
+ if (!ext) {
+ testPassed("No WEBGL_depth_texture support -- this is legal");
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled WEBGL_depth_texture extension");
+
+ runSupportedTest(true);
+ runTestExtension(true);
+ runTestExtension(false);
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture");
+ if (name !== undefined) {
+ if (extensionEnabled) {
+ testPassed("WEBGL_depth_texture listed as supported and getExtension succeeded");
+ } else {
+ testFailed("WEBGL_depth_texture listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("WEBGL_depth_texture not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("WEBGL_depth_texture not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+
+function runTestDisabled() {
+ debug("Testing binding enum with extension disabled");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE],
+ 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null)');
+ wtu.shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE],
+ 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null)');
+}
+
+
+function dumpIt(gl, res, msg) {
+ return; // comment out to debug
+ debug(msg);
+ var actualPixels = new Uint8Array(res * res * 4);
+ gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
+
+ for (var yy = 0; yy < res; ++yy) {
+ var strs = [];
+ for (var xx = 0; xx < res; ++xx) {
+ var actual = (yy * res + xx) * 4;
+ strs.push("(" + actualPixels[actual] + "," + actualPixels[actual+1] + "," + actualPixels[actual + 2] + "," + actualPixels[actual + 3] + ")");
+ }
+ debug(strs.join(" "));
+ }
+}
+function runTestExtension(unpackFlipY) {
+ debug("Testing WEBGL_depth_texture. UNPACK_FLIP_Y_WEBGL: " + unpackFlipY);
+
+ const res = 2;
+ const destRes = 4;
+
+ // make canvas for testing.
+ canvas2 = document.createElement("canvas");
+ canvas2.width = res;
+ canvas2.height = res;
+ var ctx = canvas2.getContext("2d");
+ ctx.fillStyle = "blue";
+ ctx.fillRect(0, 0, canvas2.width, canvas2.height);
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position']);
+ gl.useProgram(program);
+ gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), destRes, destRes);
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [ 1, 1, 1,
+ -1, 1, 0,
+ -1, -1, -1,
+ 1, 1, 1,
+ -1, -1, -1,
+ 1, -1, 0,
+ ]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, unpackFlipY);
+
+ var types = [
+ {obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_SHORT', data: 'new Uint16Array(1)', depthBits: "16"},
+ {obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_INT', data: 'new Uint32Array(1)', depthBits: "16"},
+ {obj: 'ext', attachment: 'DEPTH_STENCIL_ATTACHMENT', format: 'DEPTH_STENCIL', type: 'UNSIGNED_INT_24_8_WEBGL', data: 'new Uint32Array(1)', depthBits: "24", stencilBits: "8"}
+ ];
+
+ for (var ii = 0; ii < types.length; ++ii) {
+ var typeInfo = types[ii];
+ var type = typeInfo.type;
+ var typeStr = typeInfo.obj + '.' + type;
+
+ debug("");
+ debug("testing: " + type);
+
+ // check that cubemaps are not allowed.
+ var cubeTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeTex);
+ var targets = [
+ 'TEXTURE_CUBE_MAP_POSITIVE_X',
+ 'TEXTURE_CUBE_MAP_NEGATIVE_X',
+ 'TEXTURE_CUBE_MAP_POSITIVE_Y',
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Y',
+ 'TEXTURE_CUBE_MAP_POSITIVE_Z',
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Z'
+ ];
+ for (var tt = 0; tt < targets.length; ++tt) {
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.' + targets[ii] + ', 0, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
+ }
+
+ // The WebGL_depth_texture extension supports both NEAREST and
+ // LINEAR filtering for depth textures, even though LINEAR
+ // doesn't have much meaning, and isn't supported in WebGL
+ // 2.0. Still, test both.
+ var filterModes = [
+ 'LINEAR',
+ 'NEAREST'
+ ];
+
+ for (var jj = 0; jj < filterModes.length; ++jj) {
+ debug('');
+ debug('testing ' + filterModes[jj] + ' filtering');
+ var filterMode = gl[filterModes[jj]];
+
+ // check 2d textures.
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterMode);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterMode);
+
+ // test level > 0
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
+
+ // test with data
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')');
+
+ // test with canvas
+ wtu.shouldGenerateGLError(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', gl.' + typeInfo.format + ', ' + typeStr + ', canvas2)');
+
+ // test copyTexImage2D
+ wtu.shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 0, 0, 1, 1, 0)');
+
+ // test real thing
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', ' + res + ', ' + res + ', 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
+
+ // test texSubImage2D
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')');
+
+ // test copyTexSubImage2D
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)');
+
+ // test generateMipmap
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.generateMipmap(gl.TEXTURE_2D)');
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, tex, 0);
+
+ // Ensure DEPTH_BITS returns >= 16 bits for UNSIGNED_SHORT and UNSIGNED_INT, >= 24 UNSIGNED_INT_24_8_WEBGL.
+ // If there is stencil, ensure STENCIL_BITS reports >= 8 for UNSIGNED_INT_24_8_WEBGL.
+ shouldBeGreaterThanOrEqual('gl.getParameter(gl.DEPTH_BITS)', typeInfo.depthBits);
+ if (typeInfo.stencilBits === undefined) {
+ shouldBe('gl.getParameter(gl.STENCIL_BITS)', '0');
+ } else {
+ shouldBeGreaterThanOrEqual('gl.getParameter(gl.STENCIL_BITS)', typeInfo.stencilBits);
+ }
+
+ // TODO: remove this check if the spec is updated to require these combinations to work.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
+ {
+ // try adding a color buffer.
+ var colorTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, colorTex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, res, res, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
+ }
+
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ // use the default texture to render with while we return to the depth texture.
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ /* Setup 2x2 depth texture:
+ * 1 0.6 0.8
+ * |
+ * 0 0.2 0.4
+ * 0---1
+ */
+ const d00 = 0.2;
+ const d01 = 0.4;
+ const d10 = 0.6;
+ const d11 = 0.8;
+
+ gl.enable(gl.SCISSOR_TEST);
+
+ gl.scissor(0, 0, 1, 1);
+ gl.clearDepth(d00);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ gl.scissor(1, 0, 1, 1);
+ gl.clearDepth(d10);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ gl.scissor(0, 1, 1, 1);
+ gl.clearDepth(d01);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ gl.scissor(1, 1, 1, 1);
+ gl.clearDepth(d11);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ gl.disable(gl.SCISSOR_TEST);
+
+ // render the depth texture.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.canvas.width = destRes;
+ gl.canvas.height = destRes;
+ gl.viewport(0, 0, destRes, destRes);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ gl.disable(gl.DITHER);
+ gl.enable(gl.DEPTH_TEST);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clearDepth(1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ dumpIt(gl, res, "--depth--");
+
+ var actualPixels = new Uint8Array(destRes * destRes * 4);
+ gl.readPixels(0, 0, destRes, destRes, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
+
+ const eps = 0.002;
+
+ let expectedMin;
+ let expectedMax;
+ if (filterMode == gl.NEAREST) {
+ expectedMin = [
+ d00, d00, d10, d10,
+ d00, d00, d10, d10,
+ d01, d01, d11, d11,
+ d01, d01, d11, d11
+ ];
+ expectedMax = expectedMin.slice();
+
+ expectedMin = expectedMin.map(x => x - eps);
+ expectedMax = expectedMax.map(x => x + eps);
+ } else {
+ expectedMin = [
+ d00-eps, d00, d00, d10-eps,
+ d00, d00, d00, d10,
+ d00, d00, d00, d10,
+ d01-eps, d01, d01, d11-eps,
+ ];
+ expectedMax = [
+ d00+eps, d10, d10, d10+eps,
+ d01, d11, d11, d11,
+ d01, d11, d11, d11,
+ d01+eps, d11, d11, d11+eps,
+ ];
+ }
+
+ for (var yy = 0; yy < destRes; ++yy) {
+ for (var xx = 0; xx < destRes; ++xx) {
+ const t = xx + destRes*yy;
+ const was = actualPixels[4*t] / 255.0; // 4bpp
+ const eMin = expectedMin[t];
+ const eMax = expectedMax[t];
+ let func = testPassed;
+ const text = `At ${xx},${yy}, expected within [${eMin},${eMax}], was ${was.toFixed(3)}`
+ if (was <= eMin || was >= eMax) {
+ func = testFailed;
+ }
+ func(text);
+ }
+ }
+
+ // check limitations
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, null, 0);
+ var badAttachment = typeInfo.attachment == 'DEPTH_ATTACHMENT' ? 'DEPTH_STENCIL_ATTACHMENT' : 'DEPTH_ATTACHMENT';
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.' + badAttachment + ', gl.TEXTURE_2D, tex, 0)');
+ shouldNotBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, 'gl.clear(gl.DEPTH_BUFFER_BIT)');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ }
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-broadcast-return.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-broadcast-return.html
new file mode 100644
index 0000000000..d773ae8621
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-broadcast-return.html
@@ -0,0 +1,138 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_draw_buffers Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/webgl-draw-buffers-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="fshaderRedWithReturn" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+uniform float u_zero;
+void main() {
+ gl_FragColor = vec4(1,0,0,1);
+ if (u_zero < 1.0) {
+ return;
+ }
+ gl_FragColor = vec4(0,0,1,1);
+}
+</script>
+<script id="fshaderWithDiscard" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+uniform float u_zero;
+void main() {
+ gl_FragColor = vec4(1,0,0,1);
+ if (u_zero < 1.0) {
+ discard;
+ }
+ gl_FragColor = vec4(0,0,1,1);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies gl_FragColor being broadcasted when using WEBGL_draw_buffers extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var drawBuffersUtils;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("WEBGL_draw_buffers");
+ if (!ext) {
+ testPassed("No WEBGL_draw_buffers support -- this is legal");
+ } else {
+ testPassed("Successfully enabled WEBGL_draw_buffers extension");
+ drawBuffersUtils = WebGLDrawBuffersUtils(gl, ext);
+ runDrawTests();
+ }
+}
+
+function runDrawTests() {
+ debug("");
+ var fb = gl.createFramebuffer();
+
+ var maxUsable = drawBuffersUtils.getMaxUsableColorAttachments();
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+
+ var width = 64;
+ var height = 64;
+ var attachments = [];
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ attachments.push({
+ texture: tex
+ });
+ }
+
+ debug("test that gl_FragColor broadcasts if extension is enabled in fragment shader and fragment shader main returns in the middle");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ var redProgramWithReturn = wtu.setupProgram(gl, [wtu.simpleVertexShader, "fshaderRedWithReturn"], ["vPosition"], undefined, true);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.useProgram(redProgramWithReturn);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after draw");
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ debug("test that none of the attachments are written in case the fragment shader discards");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ var programWithDiscard = wtu.setupProgram(gl, [wtu.simpleVertexShader, "fshaderWithDiscard"], ["vPosition"], undefined, true);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.useProgram(programWithDiscard);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after draw");
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 0, 0, 0]);
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fb);
+ attachments.forEach(function(attachment) {
+ gl.deleteTexture(attachment.texture);
+ });
+ gl.deleteProgram(redProgramWithReturn);
+ gl.deleteProgram(programWithDiscard);
+}
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-framebuffer-unsupported.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-framebuffer-unsupported.html
new file mode 100644
index 0000000000..5866a3c38b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-framebuffer-unsupported.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_draw_buffers FRAMEBUFFER_UNSUPPORTED Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+var canvas = document.getElementById("canvas");
+var fb1 = null;
+var fb2 = null;
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (expected.indexOf(actual) < 0) {
+ var msg = "checkFramebufferStatus expects [";
+ for (var index = 0; index < expected.length; ++index) {
+ msg += wtu.glEnumToString(gl, expected[index]);
+ if (index + 1 < expected.length)
+ msg += ", ";
+ }
+ msg += "], was " + wtu.glEnumToString(gl, actual);
+ testFailed(msg);
+ } else {
+ var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
+ " as expected";
+ testPassed(msg);
+ }
+}
+
+function testImageAttachedTwoPoints() {
+ debug("");
+ debug("Checking an image is attached to more than one color attachment in a framebuffer.");
+
+ var tex1 = gl.createTexture();
+ var tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ 1, // width
+ 1, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ new Uint8Array(4)); // data
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture creation should succeed.");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, tex1, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, tex2, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT2_WEBGL, gl.TEXTURE_2D, tex1, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ var texCube = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ for (var target = gl.TEXTURE_CUBE_MAP_POSITIVE_X; target < gl.TEXTURE_CUBE_MAP_POSITIVE_X + 6; target++) {
+ gl.texImage2D(target, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ }
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, texCube, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT2_WEBGL, gl.TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
+
+ // Clean up
+ gl.deleteTexture(tex1);
+ gl.deleteTexture(tex2);
+ gl.deleteTexture(texCube);
+}
+
+description("This tests FRAMEBUFFER_UNSUPPORTED.");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 1)");
+fb1 = gl.createFramebuffer();
+fb2 = gl.createFramebuffer();
+
+var ext = gl.getExtension("WEBGL_draw_buffers");
+if (!ext) {
+ testPassed("No WEBGL_draw_buffers support -- this is legal");
+} else {
+ var bufs = [ext.COLOR_ATTACHMENT0_WEBGL, ext.COLOR_ATTACHMENT1_WEBGL, ext.COLOR_ATTACHMENT2_WEBGL];
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ ext.drawBuffersWEBGL(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL successfully");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ ext.drawBuffersWEBGL(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL successfully");
+
+ testPassed("Successfully enabled WEBGL_draw_buffers extension");
+ testImageAttachedTwoPoints();
+
+ gl.deleteFramebuffer(fb1);
+ gl.deleteFramebuffer(fb2);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-max-draw-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-max-draw-buffers.html
new file mode 100644
index 0000000000..8181a6a587
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers-max-draw-buffers.html
@@ -0,0 +1,118 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_draw_buffers gl_FragData[gl_MaxDrawBuffers] Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+void main() {
+ gl_FragData[gl_MaxDrawBuffers] = vec4(0.0);
+}
+</script>
+<script id="fshaderConstantIndex" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+void main() {
+ gl_FragData[$(gl_MaxDrawBuffers)] = vec4(0.0);
+}
+</script>
+<script id="fshaderTestMaxDrawBuffersValue" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+void main() {
+ gl_FragColor = ($(gl_MaxDrawBuffers) == gl_MaxDrawBuffers) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies that compiling the same shader using GL_EXT_draw_buffers twice will have similar results on both rounds.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var maxDrawBuffers;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ ext = gl.getExtension("WEBGL_draw_buffers");
+ if (!ext) {
+ testPassed("No WEBGL_draw_buffers support -- this is legal");
+ finishTest();
+ } else {
+ testPassed("Successfully enabled WEBGL_draw_buffers extension");
+ maxDrawBuffers = gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL);
+ runShadersTest();
+ finishTest();
+ }
+}
+
+function testValueOfMaxDrawBuffers() {
+ debug("Test the value of gl_MaxDrawBuffers in a shader");
+ var fshader = wtu.replaceParams(wtu.getScript("fshaderTestMaxDrawBuffersValue"), {"gl_MaxDrawBuffers": maxDrawBuffers});
+ var program = wtu.setupProgram(gl, ["vshader", fshader], ["a_position"], undefined, true);
+ expectTrue(program != null, "Test program should compile");
+ wtu.setupUnitQuad(gl);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green to indicate that gl_MaxDrawBuffers had the right value");
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runSingleTest(shaders, indexMsg) {
+ var program = wtu.setupProgram(gl, shaders, ["a_position"], undefined, true);
+ var programLinkedSuccessfully = (program != null);
+ expectTrue(!programLinkedSuccessfully, "Program where gl_FragData is indexed by " + indexMsg + " should fail compilation.");
+ gl.deleteProgram(program);
+}
+
+function runShadersTest() {
+ debug("MAX_DRAW_BUFFERS_WEBGL is: " + maxDrawBuffers);
+
+ // For reference, use a constant out-of-range parameter to test:
+ debug("Test indexing gl_FragData with value of MAX_DRAW_BUFFERS_WEBGL");
+ var fshader = wtu.replaceParams(wtu.getScript("fshaderConstantIndex"), {"gl_MaxDrawBuffers": maxDrawBuffers});
+ runSingleTest(["vshader", fshader], maxDrawBuffers + " (value of MAX_DRAW_BUFFERS_WEBGL)");
+
+ debug("");
+
+ debug("Test indexing gl_FragData with gl_MaxDrawBuffers");
+ debug("Repeat this test twice as that has revealed a bug.");
+ for (var i = 0; i < 2; ++i) {
+ runSingleTest(["vshader", "fshader"], "gl_MaxDrawBuffers");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("");
+
+ testValueOfMaxDrawBuffers();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers.html
new file mode 100644
index 0000000000..a33844f6b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-draw-buffers.html
@@ -0,0 +1,812 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_draw_buffers Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/webgl-draw-buffers-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+uniform vec4 u_colors[$(numDrawingBuffers)];
+void main() {
+ for (int i = 0; i < $(numDrawingBuffers); ++i) {
+ gl_FragData[i] = u_colors[i];
+ }
+}
+</script>
+<script id="fshaderNoWrite" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+void main() {
+}
+</script>
+<script id="fshaderRed" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1,0,0,1);
+}
+</script>
+<script id="fshaderRedWithExtension" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1,0,0,1);
+}
+</script>
+<script id="fshaderMacroDisabled" type="x-shader/x-fragment">
+#ifdef GL_EXT_draw_buffers
+ bad code here
+#endif
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fshaderMacroEnabled" type="x-shader/x-fragment">
+#ifdef GL_EXT_draw_buffers
+ #if GL_EXT_draw_buffers == 1
+ #define CODE
+ #else
+ #define CODE this_code_is_bad_it_should_have_compiled
+ #endif
+#else
+ #define CODE this_code_is_bad_it_should_have_compiled
+#endif
+CODE
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fshaderBuiltInConstEnabled" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = (gl_MaxDrawBuffers == $(numDrawingBuffers)) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_draw_buffers extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+var ext = null;
+var programWithMaxDrawBuffersEqualOne = null;
+var drawBuffersUtils;
+let fb;
+
+var extensionConstants = [
+ { name: "MAX_COLOR_ATTACHMENTS_WEBGL", enum: 0x8CDF, expectedFn: function(v) { return v >= 4; }, passMsg: " should be >= 4"},
+ { name: "MAX_DRAW_BUFFERS_WEBGL", enum: 0x8824, expectedFn: function(v) { return v > 0; }, passMsg: " should be > 0"},
+
+ { name: "COLOR_ATTACHMENT0_WEBGL", enum: 0x8CE0, },
+ { name: "COLOR_ATTACHMENT1_WEBGL", enum: 0x8CE1, },
+ { name: "COLOR_ATTACHMENT2_WEBGL", enum: 0x8CE2, },
+ { name: "COLOR_ATTACHMENT3_WEBGL", enum: 0x8CE3, },
+ { name: "COLOR_ATTACHMENT4_WEBGL", enum: 0x8CE4, },
+ { name: "COLOR_ATTACHMENT5_WEBGL", enum: 0x8CE5, },
+ { name: "COLOR_ATTACHMENT6_WEBGL", enum: 0x8CE6, },
+ { name: "COLOR_ATTACHMENT7_WEBGL", enum: 0x8CE7, },
+ { name: "COLOR_ATTACHMENT8_WEBGL", enum: 0x8CE8, },
+ { name: "COLOR_ATTACHMENT9_WEBGL", enum: 0x8CE9, },
+ { name: "COLOR_ATTACHMENT10_WEBGL", enum: 0x8CEA, },
+ { name: "COLOR_ATTACHMENT11_WEBGL", enum: 0x8CEB, },
+ { name: "COLOR_ATTACHMENT12_WEBGL", enum: 0x8CEC, },
+ { name: "COLOR_ATTACHMENT13_WEBGL", enum: 0x8CED, },
+ { name: "COLOR_ATTACHMENT14_WEBGL", enum: 0x8CEE, },
+ { name: "COLOR_ATTACHMENT15_WEBGL", enum: 0x8CEF, },
+
+ { name: "DRAW_BUFFER0_WEBGL", enum: 0x8825, },
+ { name: "DRAW_BUFFER1_WEBGL", enum: 0x8826, },
+ { name: "DRAW_BUFFER2_WEBGL", enum: 0x8827, },
+ { name: "DRAW_BUFFER3_WEBGL", enum: 0x8828, },
+ { name: "DRAW_BUFFER4_WEBGL", enum: 0x8829, },
+ { name: "DRAW_BUFFER5_WEBGL", enum: 0x882A, },
+ { name: "DRAW_BUFFER6_WEBGL", enum: 0x882B, },
+ { name: "DRAW_BUFFER7_WEBGL", enum: 0x882C, },
+ { name: "DRAW_BUFFER8_WEBGL", enum: 0x882D, },
+ { name: "DRAW_BUFFER9_WEBGL", enum: 0x882E, },
+ { name: "DRAW_BUFFER10_WEBGL", enum: 0x882F, },
+ { name: "DRAW_BUFFER11_WEBGL", enum: 0x8830, },
+ { name: "DRAW_BUFFER12_WEBGL", enum: 0x8831, },
+ { name: "DRAW_BUFFER13_WEBGL", enum: 0x8832, },
+ { name: "DRAW_BUFFER14_WEBGL", enum: 0x8833, },
+ { name: "DRAW_BUFFER15_WEBGL", enum: 0x8834, },
+];
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runEnumTestDisabled();
+ runShadersTestDisabled();
+ runAttachmentTestDisabled();
+
+ debug("");
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("WEBGL_draw_buffers");
+ if (!ext) {
+ testPassed("No WEBGL_draw_buffers support -- this is legal");
+
+ runSupportedTest(false);
+ finishTest();
+ } else {
+ testPassed("Successfully enabled WEBGL_draw_buffers extension");
+
+ drawBuffersUtils = WebGLDrawBuffersUtils(gl, ext);
+ runSupportedTest(true);
+ runEnumTestEnabled();
+ runShadersTestEnabled();
+ runAttachmentTestEnabled();
+ runDrawTests();
+ runPreserveTests();
+ }
+}
+
+function createExtDrawBuffersProgram(scriptId, sub) {
+ var fsource = wtu.getScript(scriptId);
+ fsource = wtu.replaceParams(fsource, sub);
+ return wtu.setupProgram(gl, [wtu.simpleVertexShader, fsource], ["vPosition"], undefined, true);
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("WEBGL_draw_buffers") >= 0) {
+ if (extensionEnabled) {
+ testPassed("WEBGL_draw_buffers listed as supported and getExtension succeeded");
+ } else {
+ testFailed("WEBGL_draw_buffers listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("WEBGL_draw_buffers not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("WEBGL_draw_buffers not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runEnumTestDisabled() {
+ debug("");
+ debug("Testing binding enum with extension disabled");
+
+ // Use the constant directly as we don't have the extension
+ extensionConstants.forEach(function(c) {
+ if (c.expectedFn) {
+ shouldBeNull(`gl.getParameter(${c.enum})`);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, c.name + " should not be queryable if extension is disabled");
+ }
+ });
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runEnumTestEnabled() {
+ debug("");
+ debug("Testing enums with extension enabled");
+
+ extensionConstants.forEach(function(c) {
+ shouldBe("ext." + c.name, "0x" + c.enum.toString(16));
+ if (c.expectedFn) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "before getParameter");
+ debug(c.name + ": 0x" + ext[c.name].toString(16));
+ expectTrue(c.expectedFn(gl.getParameter(ext[c.name])), "gl.getParameter(ext." + c.name + ")" + c.passMsg);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, c.name + " query should succeed if extension is enabled");
+ }
+ });
+
+ shouldBeTrue("gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL) >= gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL)");
+
+ debug("Testing drawBuffersWEBGL with default drawing buffer");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.drawBuffersWEBGL([])");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.drawBuffersWEBGL([gl.NONE, gl.NONE])");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT0_WEBGL])");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.NONE])");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.NONE");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.BACK])");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("Testing drawBuffers and getParameter with bindFramebuffer, without drawing.");
+ fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.COLOR_ATTACHMENT0");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL+1)", "gl.NONE");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.NONE])");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.NONE");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.NONE,gl.COLOR_ATTACHMENT0+1])");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.NONE");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL+1)", "gl.COLOR_ATTACHMENT0+1");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.COLOR_ATTACHMENT0,gl.COLOR_ATTACHMENT0+1])");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.COLOR_ATTACHMENT0");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL+1)", "gl.COLOR_ATTACHMENT0+1");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fb)");
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK");
+}
+
+function testShaders(tests, sub) {
+ tests.forEach(function(test) {
+ var shaders = [wtu.simpleVertexShader, wtu.replaceParams(wtu.getScript(test.fragmentShaderTemplate), sub)];
+ var program = wtu.setupProgram(gl, shaders, ["vPosition"], undefined, true);
+ var programLinkedSuccessfully = (program != null);
+ var expectedProgramToLinkSuccessfully = (test.expectFailure == true);
+ expectTrue(programLinkedSuccessfully != expectedProgramToLinkSuccessfully, test.msg);
+ gl.deleteProgram(program);
+ });
+}
+
+function runShadersTestDisabled() {
+ debug("");
+ debug("test shaders disabled");
+
+ var sub = {numDrawingBuffers: 1};
+ testShaders([
+ { fragmentShaderTemplate: "fshaderMacroDisabled",
+ msg: "GL_EXT_draw_buffers should not be defined in GLSL",
+ },
+ { fragmentShaderTemplate: "fshader",
+ msg: "#extension GL_EXT_draw_buffers should not be allowed in GLSL",
+ expectFailure: true,
+ },
+ ], sub);
+
+ programWithMaxDrawBuffersEqualOne = createExtDrawBuffersProgram("fshaderBuiltInConstEnabled", sub);
+ wtu.setupUnitQuad(gl);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runShadersTestEnabled() {
+ debug("");
+ debug("test shaders enabled");
+
+ var sub = {numDrawingBuffers: gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL)};
+ testShaders([
+ { fragmentShaderTemplate: "fshaderMacroEnabled",
+ msg: "GL_EXT_draw_buffers should be defined as 1 in GLSL",
+ },
+ { fragmentShaderTemplate: "fshader",
+ msg: "fragment shader containing the #extension directive should compile",
+ },
+ ], sub);
+
+ var program = createExtDrawBuffersProgram("fshaderBuiltInConstEnabled", sub);
+ wtu.setupUnitQuad(gl);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("");
+ debug("test that gl_MaxDrawBuffers is frozen at link time and enabling the extension won't change it.");
+ gl.useProgram(programWithMaxDrawBuffersEqualOne);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ gl.deleteProgram(programWithMaxDrawBuffersEqualOne);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runAttachmentTestDisabled() {
+ debug("");
+ debug("test attachment disabled");
+ var tex = gl.createTexture();
+ var fb = gl.createFramebuffer();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + 1, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "should not be able to attach to gl.COLOR_ATTACHMENT1");
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function makeArray(size, value) {
+ var array = []
+ for (var ii = 0; ii < size; ++ii) {
+ array.push(value);
+ }
+ return array;
+}
+
+function runAttachmentTestEnabled() {
+ debug("");
+ debug("test attachment enabled");
+
+ var maxDrawingBuffers = gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL);
+ var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL);
+
+ var tex = gl.createTexture();
+ var fb = gl.createFramebuffer();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachments, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "should not be able to attach pass the max attachment point: gl.COLOR_ATTACHMENT0 + " + maxColorAttachments);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachments - 1, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to attach to the max attachment point: gl.COLOR_ATTACHMENT0 + " + (maxColorAttachments - 1));
+ ext.drawBuffersWEBGL(makeArray(maxDrawingBuffers, gl.NONE));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with array NONE of size " + maxColorAttachments);
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(maxDrawingBuffers);
+ ext.drawBuffersWEBGL(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with array attachments of size " + maxColorAttachments);
+ bufs[0] = gl.NONE;
+ ext.drawBuffersWEBGL(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with mixed array attachments of size " + maxColorAttachments);
+ if (maxDrawingBuffers > 1) {
+ bufs[0] = ext.COLOR_ATTACHMENT1_WEBGL;
+ bufs[1] = ext.COLOR_ATTACHMENT0_WEBGL;
+ ext.drawBuffersWEBGL(bufs);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be able to call drawBuffersWEBGL with out of order attachments of size " + maxColorAttachments);
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(Math.floor(maxDrawingBuffers / 2));
+ ext.drawBuffersWEBGL(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with short array of attachments of size " + bufs.length);
+ }
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function makeColorByIndex(index) {
+ var low = (index - 1) % 15 + 1;
+ var high = (index - 1) / 15;
+
+ var zeroOrOne = function(v) {
+ return v ? 1 : 0;
+ };
+
+ var oneOrTwo = function(v) {
+ return v ? 2 : 1;
+ }
+
+ var makeComponent = function(b0, b1, b2) {
+ return Math.floor(255 * zeroOrOne(b0) / oneOrTwo(b1) / oneOrTwo(b2));
+ };
+ return [
+ makeComponent(low & (1 << 0), high & (1 << 0), high & (1 << 4)),
+ makeComponent(low & (1 << 1), high & (1 << 1), high & (1 << 5)),
+ makeComponent(low & (1 << 2), high & (1 << 2), high & (1 << 6)),
+ makeComponent(low & (1 << 3), high & (1 << 3), high & (1 << 7)),
+ ];
+}
+
+function runDrawTests() {
+ debug("");
+ debug("--------- draw tests -----------");
+ var fb = gl.createFramebuffer();
+ var fb2 = gl.createFramebuffer();
+ var halfFB1 = gl.createFramebuffer();
+ var halfFB2 = gl.createFramebuffer();
+ var endsFB = gl.createFramebuffer();
+ var middleFB = gl.createFramebuffer();
+
+ var maxDrawingBuffers = gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL);
+ var maxUsable = drawBuffersUtils.getMaxUsableColorAttachments();
+ var half = Math.floor(maxUsable / 2);
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ var nones = makeArray(maxUsable, gl.NONE);
+
+ [fb, fb2, halfFB1, halfFB2, endsFB, middleFB].forEach(function(fbo) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ });
+
+ var checkProgram = wtu.setupTexturedQuad(gl);
+ var redProgram = wtu.setupProgram(gl, [wtu.simpleVertexShader, "fshaderRed"], ["vPosition"]);
+ var redProgramWithExtension = wtu.setupProgram(gl, [wtu.simpleVertexShader, "fshaderRedWithExtension"], ["vPosition"]);
+ var drawProgram = createExtDrawBuffersProgram("fshader", {numDrawingBuffers: maxDrawingBuffers});
+ var width = 64;
+ var height = 64;
+ var attachments = [];
+ // Makes 6 framebuffers.
+ // fb and fb2 have all the attachments.
+ // halfFB1 has the first half of the attachments
+ // halfFB2 has the second half of the attachments
+ // endsFB has the first and last attachments
+ // middleFB has all but the first and last attachments
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, ii < half ? halfFB1 : halfFB2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, (ii == 0 || ii == (maxUsable - 1)) ? endsFB : middleFB);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ var location = gl.getUniformLocation(drawProgram, "u_colors[" + ii + "]");
+ var color = makeColorByIndex(ii + 1);
+ var floatColor = [color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255];
+ gl.uniform4fv(location, floatColor);
+ attachments.push({
+ texture: tex,
+ color: color
+ });
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ var drawAndCheckAttachments = function(testFB, msg, testFn) {
+ debug("test clearing " + msg);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
+
+ attachments.forEach(function(attachment, index) {
+ debug("attachment: " + index + " = " + wtu.glEnumToString(gl, gl.getParameter(ext.DRAW_BUFFER0_WEBGL + index)) +
+ ", " + wtu.glEnumToString(gl, gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + index, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)));
+ });
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("framebuffer not complete");
+ debug("");
+ return;
+ }
+
+ // Clear all the attachments
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ //drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ // return [0, 0, 0, 0];
+ //});
+ //debug("--");
+
+ // Clear some attachments using testFB
+ gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
+
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return testFn(attachment, index) ? [0, 255, 0, 255] : [0, 0, 0, 0];
+ });
+
+ debug("test drawing to " + msg);
+
+ // Draw to some attachments using testFB
+ gl.useProgram(drawProgram);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return testFn(attachment, index) ? attachment.color : [0, 0, 0, 0];
+ });
+ };
+
+ gl.useProgram(drawProgram);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ ext.drawBuffersWEBGL(bufs);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+
+ wtu.drawUnitQuad(gl);
+
+ debug("test that each texture got the correct color.");
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments);
+
+ debug("test clearing clears all the textures");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
+
+ debug("test a fragment shader writing to neither gl_FragColor nor gl_FragData does not touch attachments");
+ var noWriteProgram = wtu.setupProgram(gl, [wtu.simpleVertexShader, "fshaderNoWrite"], ["vPosition"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no GL error setting up the program");
+ if (!noWriteProgram) {
+ testFailed("Setup a program where fragment shader writes nothing failed");
+ } else {
+ gl.useProgram(noWriteProgram);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Active draw buffers with missing frag outputs.");
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
+ gl.deleteProgram(noWriteProgram);
+ }
+
+ debug("test that NONE draws nothing");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(nones);
+ gl.useProgram(redProgram);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
+
+ debug("test that gl_FragColor does not broadcast unless extension is enabled in fragment shader");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ gl.useProgram(redProgram);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Active draw buffers with missing frag outputs.");
+ gl.colorMask(false, false, false, false);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors when all 4 channels of color mask are disabled.");
+ gl.colorMask(false, true, false, false);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "partially diabled color mask shall have no impact.");
+ gl.colorMask(true, true, true, true);
+
+ debug("test that gl_FragColor broadcasts if extension is enabled in fragment shader");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ gl.useProgram(redProgramWithExtension);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ if (maxUsable > 1) {
+ // First half of color buffers disable.
+ var bufs1 = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ // Second half of color buffers disable.
+ var bufs2 = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ // Color buffers with even indices disabled.
+ var bufs3 = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ // Color buffers with odd indices disabled.
+ var bufs4 = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ if (ii < half) {
+ bufs1[ii] = gl.NONE;
+ } else {
+ bufs2[ii] = gl.NONE;
+ }
+ if (ii % 2) {
+ bufs3[ii] = gl.NONE;
+ } else {
+ bufs4[ii] = gl.NONE;
+ }
+ }
+
+ debug("test setting first half to NONE and clearing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ // We should clear all buffers rather than depending on the previous
+ // gl_FragColor broadcasts test to succeed and setting the colors.
+ ext.drawBuffersWEBGL(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ ext.drawBuffersWEBGL(bufs1);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? [255, 0, 0, 255] : [0, 255, 0, 255];
+ });
+
+ debug("test setting first half to NONE and drawing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? [255, 0, 0, 255] : attachment.color;
+ });
+
+ debug("test setting second half to NONE and clearing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ ext.drawBuffersWEBGL(bufs2);
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? [0, 0, 255, 255] : [255, 0, 0, 255];
+ });
+
+ debug("test setting second half to NONE and drawing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? attachment.color : [255, 0, 0, 255];
+ });
+
+ debug("test setting buffers with even indices to NONE and clearing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.drawBuffersWEBGL(bufs3);
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return (index % 2) ? [255, 0, 0, 255] : [255, 0, 255, 255];
+ });
+
+ debug("test setting buffers with odd indices to NONE and drawing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.useProgram(drawProgram);
+ ext.drawBuffersWEBGL(bufs4);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return (index % 2 == 0) ? [0, 0, 0, 255] : attachment.color;
+ });
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB1);
+ ext.drawBuffersWEBGL(bufs);
+ drawAndCheckAttachments(
+ halfFB1, "framebuffer that only has first half of attachments",
+ function(attachment, index) {
+ return index < half;
+ });
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB2);
+ ext.drawBuffersWEBGL(bufs);
+ drawAndCheckAttachments(
+ halfFB2, "framebuffer that only has second half of attachments",
+ function(attachment, index) {
+ return index >= half;
+ });
+
+ if (maxUsable > 2) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, endsFB);
+ ext.drawBuffersWEBGL(bufs);
+ drawAndCheckAttachments(
+ endsFB, "framebuffer that only has first and last attachments",
+ function(attachment, index) {
+ return index == 0 || index == (maxUsable - 1);
+ });
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, middleFB);
+ ext.drawBuffersWEBGL(bufs);
+ drawAndCheckAttachments(
+ middleFB,
+ "framebuffer that has all but the first and last attachments",
+ function(attachment, index) {
+ return index != 0 && index != (maxUsable - 1);
+ });
+ }
+ }
+
+ debug("test switching between fbos does not affect any color attachment contents");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ ext.drawBuffersWEBGL(nones);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.drawBuffersWEBGL(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ // fb2 still has the NONE draw buffers from before, so this draw should be a no-op.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+ drawBuffersUtils.checkAttachmentsForColor(attachments);
+
+ debug("test queries");
+ debug("check framebuffer with all attachments on");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL + " + ii + ")", "gl.COLOR_ATTACHMENT0 + " + ii);
+ }
+
+ debug("check framebuffer with all attachments off");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL + " + ii + ")", "gl.NONE");
+ }
+
+ debug("test attachment size mis-match");
+ gl.bindTexture(gl.TEXTURE_2D, attachments[0].texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * 2, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteFramebuffer(fb2);
+ gl.deleteFramebuffer(halfFB1);
+ gl.deleteFramebuffer(halfFB2);
+ attachments.forEach(function(attachment) {
+ gl.deleteTexture(attachment.texture);
+ });
+ gl.deleteProgram(checkProgram);
+ gl.deleteProgram(redProgram);
+ gl.deleteProgram(redProgramWithExtension);
+ gl.deleteProgram(drawProgram);
+}
+
+function runPreserveTests() {
+ debug("");
+ debug("--------- preserve tests -----------");
+
+ debug("Testing that frame buffer is cleared after compositing");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ gl.clearColor(1, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [255, 255, 0, 255], "should be yellow");
+
+ // set the draw buffer to NONE
+ ext.drawBuffersWEBGL([gl.NONE]);
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // make sure the canvas is still clear
+ wtu.checkCanvas(gl, [255, 255, 0, 255], "should be yellow");
+
+ wtu.waitForComposite(function() {
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "should be clear");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ runEndTests();
+ });
+}
+
+function runEndTests() {
+ // Create new context and verify shader tests with no extension still succeeds.
+ debug("");
+ debug("Testing new context with no extension");
+ gl = wtu.create3DContext();
+ if (!gl) {
+ testFailed("New WebGL context does not exist");
+ } else {
+ testPassed("New WebGL context exists");
+ runEnumTestDisabled();
+ runShadersTestDisabled();
+ runAttachmentTestDisabled();
+ }
+
+ finishTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-multi-draw.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-multi-draw.html
new file mode 100644
index 0000000000..ae4bbc1af0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-multi-draw.html
@@ -0,0 +1,1064 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ANGLE_multi_draw Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compositing-test.js"></script>
+<script src="../../js/tests/invalid-vertex-attrib-test.js"></script>
+</head>
+<body>
+<script id="vshaderIllegalDrawID" type="x-shader/x-vertex">
+attribute vec2 vPosition;
+varying vec4 color;
+void main()
+{
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_Position = vec4(vPosition * 2.0 - 1.0, gl_DrawID, 1);
+}
+</script>
+<script id="vshaderDrawIDZero" type="x-shader/x-vertex">
+#extension GL_ANGLE_multi_draw : require
+attribute vec2 vPosition;
+varying vec4 color;
+void main()
+{
+ if (gl_DrawID == 0) {
+ color = vec4(0, 1, 0, 1);
+ } else {
+ color = vec4(1, 0, 0, 1);
+ }
+ gl_Position = vec4(vPosition * 2.0 - 1.0, 0, 1);
+}
+</script>
+<!-- The behavior of the shaders below is described in runPixelTests() -->
+<script id="vshaderWithDrawID" type="x-shader/x-vertex">
+#extension GL_ANGLE_multi_draw : require
+attribute vec2 vPosition;
+attribute float vInstance;
+varying vec4 color;
+void main()
+{
+ // color_id = (gl_DrawID / 2) % 3
+ float quad_id = float(gl_DrawID / 2);
+ float color_id = quad_id - (3.0 * floor(quad_id / 3.0));
+ if (color_id < 0.5) {
+ color = vec4(1, 0, 0, 1);
+ } else if (color_id < 1.5) {
+ color = vec4(0, 1, 0, 1);
+ } else {
+ color = vec4(0, 0, 1, 1);
+ }
+ mat3 transform = mat3(1.0);
+ // vInstance starts at 1.0 on instanced calls
+ if (vInstance >= 1.0) {
+ transform[0][0] = 0.5;
+ transform[1][1] = 0.5;
+ }
+ if (vInstance == 1.0) {
+ } else if (vInstance == 2.0) {
+ transform[2][0] = 0.5;
+ } else if (vInstance == 3.0) {
+ transform[2][1] = 0.5;
+ } else if (vInstance == 4.0) {
+ transform[2][0] = 0.5;
+ transform[2][1] = 0.5;
+ }
+ gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
+}
+</script>
+<script id="vshaderEmulatedDrawID" type="x-shader/x-vertex">
+uniform int drawID;
+attribute vec2 vPosition;
+attribute float vInstance;
+varying vec4 color;
+void main()
+{
+ float quad_id = float(drawID / 2);
+ float color_id = quad_id - (3.0 * floor(quad_id / 3.0));
+ if (color_id == 0.0) {
+ color = vec4(1, 0, 0, 1);
+ } else if (color_id == 1.0) {
+ color = vec4(0, 1, 0, 1);
+ } else {
+ color = vec4(0, 0, 1, 1);
+ }
+ mat3 transform = mat3(1.0);
+ // vInstance starts at 1.0 on instanced calls
+ if (vInstance >= 1.0) {
+ transform[0][0] = 0.5;
+ transform[1][1] = 0.5;
+ }
+ if (vInstance == 1.0) {
+ } else if (vInstance == 2.0) {
+ transform[2][0] = 0.5;
+ } else if (vInstance == 3.0) {
+ transform[2][1] = 0.5;
+ } else if (vInstance == 4.0) {
+ transform[2][0] = 0.5;
+ transform[2][1] = 0.5;
+ }
+ gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
+}
+</script>
+<script id="vshaderNoDrawID" type="x-shader/x-vertex">
+attribute vec2 vPosition;
+attribute float vInstance;
+varying vec4 color;
+void main()
+{
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+ mat3 transform = mat3(1.0);
+ // vInstance starts at 1.0 on instanced calls
+ if (vInstance >= 1.0) {
+ transform[0][0] = 0.5;
+ transform[1][1] = 0.5;
+ }
+ if (vInstance == 1.0) {
+ } else if (vInstance == 2.0) {
+ transform[2][0] = 0.5;
+ } else if (vInstance == 3.0) {
+ transform[2][1] = 0.5;
+ } else if (vInstance == 4.0) {
+ transform[2][0] = 0.5;
+ transform[2][1] = 0.5;
+ }
+ gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<div id="description"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the ANGLE_multi_draw extension, if it is available.");
+
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("canvas");
+const gl = wtu.create3DContext(canvas);
+const instancedExt = gl && gl.getExtension('ANGLE_instanced_arrays');
+const bufferUsageSet = [ gl.STATIC_DRAW, gl.DYNAMIC_DRAW ];
+
+// Check if the extension is either both enabled and supported or
+// not enabled and not supported.
+function runSupportedTest(extensionName, extensionEnabled) {
+ const supported = gl.getSupportedExtensions();
+ if (supported.indexOf(extensionName) >= 0) {
+ if (extensionEnabled) {
+ testPassed(extensionName + ' listed as supported and getExtension succeeded');
+ return true;
+ } else {
+ testFailed(extensionName + ' listed as supported but getExtension failed');
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed(extensionName + ' not listed as supported but getExtension succeeded');
+ } else {
+ testPassed(extensionName + ' not listed as supported and getExtension failed -- this is legal');
+ }
+ }
+ return false;
+}
+
+function runTest() {
+ if (!gl) {
+ return function() {
+ testFailed('WebGL context does not exist');
+ }
+ }
+
+ const extensionName = 'WEBGL_multi_draw';
+ const ext = gl.getExtension(extensionName);
+ if (!runSupportedTest(extensionName, ext)) {
+ return;
+ }
+
+ doTest(ext, false);
+ doTest(ext, true);
+}
+
+function doTest(ext, instanced) {
+
+ function runValidationTests(bufferUsage) {
+ const vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.2,0.2, 0.8,0.2, 0.5,0.8 ]), bufferUsage);
+
+ const indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2, 0]), bufferUsage);
+
+ const instanceBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2, 3 ]), bufferUsage);
+
+ const program = wtu.setupProgram(gl, ["vshaderNoDrawID", "fshader"], ["vPosition", "vInstance"], [0, 1]);
+ expectTrue(program != null, "can compile simple program");
+
+ function setupDrawArrays() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ }
+
+ function setupDrawElements() {
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ }
+
+ function setupInstanced() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+ if (wtu.getDefault3DContextVersion() < 2) {
+ instancedExt.vertexAttribDivisorANGLE(1, 1);
+ } else {
+ gl.vertexAttribDivisor(1, 1);
+ }
+ }
+
+ function setupDrawArraysInstanced() {
+ setupDrawArrays();
+ setupInstanced();
+ }
+
+ function setupDrawElementsInstanced() {
+ setupDrawElements();
+ setupInstanced();
+ }
+
+ // Wrap a draw call in a function to setup the draw call, execute,
+ // and check errors.
+ // The `drawFunc` is one of the extension entrypoints being tested. It may
+ // be undefined if that entrypoint is not supported on the context
+ function makeDrawCheck(drawFunc, setup) {
+ if (!drawFunc) {
+ return function() {};
+ }
+ return function(f_args, expect, msg) {
+ setup();
+ drawFunc.apply(ext, f_args);
+ wtu.glErrorShouldBe(gl, expect, drawFunc.name + " " + msg);
+ gl.disableVertexAttribArray(0);
+ gl.disableVertexAttribArray(1);
+ }
+ }
+
+ const checkMultiDrawArrays = makeDrawCheck(
+ ext.multiDrawArraysWEBGL, setupDrawArrays);
+ const checkMultiDrawElements = makeDrawCheck(
+ ext.multiDrawElementsWEBGL, setupDrawElements);
+ const checkMultiDrawArraysInstanced = makeDrawCheck(
+ ext.multiDrawArraysInstancedWEBGL, setupDrawArraysInstanced);
+ const checkMultiDrawElementsInstanced = makeDrawCheck(
+ ext.multiDrawElementsInstancedWEBGL, setupDrawElementsInstanced);
+
+ gl.useProgram(program);
+
+ // Check that drawing a single triangle works
+ if (!instanced) {
+ checkMultiDrawArrays(
+ [gl.TRIANGLES, [0], 0, [3], 0, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES");
+ checkMultiDrawElements(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES");
+ } else {
+ checkMultiDrawElementsInstanced(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES");
+ checkMultiDrawArraysInstanced(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES");
+ }
+
+ // Zero drawcount permitted
+ if (!instanced) {
+ checkMultiDrawArrays(
+ [gl.TRIANGLES, [0], 0, [3], 0, 0],
+ gl.NO_ERROR, "with drawcount == 0");
+ checkMultiDrawElements(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, 0],
+ gl.NO_ERROR, "with drawcount == 0");
+ } else {
+ checkMultiDrawElementsInstanced(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, 0],
+ gl.NO_ERROR, "with drawcount == 0");
+ checkMultiDrawArraysInstanced(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, 0],
+ gl.NO_ERROR, "with drawcount == 0");
+ }
+
+ // Check negative drawcount
+ if (!instanced) {
+ checkMultiDrawArrays(
+ [gl.TRIANGLES, [0], 0, [3], 0, -1],
+ gl.INVALID_VALUE, "with drawcount < 0");
+ checkMultiDrawElements(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, -1],
+ gl.INVALID_VALUE, "with drawcount < 0");
+ } else {
+ checkMultiDrawElementsInstanced(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, -1],
+ gl.INVALID_VALUE, "with drawcount < 0");
+ checkMultiDrawArraysInstanced(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, -1],
+ gl.INVALID_VALUE, "with drawcount < 0");
+ }
+
+ // Check offsets greater than array length
+ if (!instanced) {
+ checkMultiDrawArrays(
+ [gl.TRIANGLES, [0], 1, [3], 0, 1],
+ gl.INVALID_OPERATION, "with firstsStart >= firstsList.length");
+ checkMultiDrawArrays(
+ [gl.TRIANGLES, [0], 0, [3], 1, 1],
+ gl.INVALID_OPERATION, "with countsStart >= countsList.length");
+
+ checkMultiDrawElements(
+ [gl.TRIANGLES, [3], 1, gl.UNSIGNED_BYTE, [0], 0, 1],
+ gl.INVALID_OPERATION, "with countsStart >= countsList.length");
+ checkMultiDrawElements(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 1, 1],
+ gl.INVALID_OPERATION, "with offsetsStart >= offsetsList.length");
+ } else {
+ checkMultiDrawArraysInstanced(
+ [gl.TRIANGLES, [0], 1, [3], 0, [1], 0, 1],
+ gl.INVALID_OPERATION, "with firstsStart >= firstsList.length");
+ checkMultiDrawArraysInstanced(
+ [gl.TRIANGLES, [0], 0, [3], 1, [1], 0, 1],
+ gl.INVALID_OPERATION, "with countsStart >= countsList.length");
+ checkMultiDrawArraysInstanced(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 1, 1],
+ gl.INVALID_OPERATION, "with instanceCountsStart >= instanceCountsList.length");
+
+ checkMultiDrawElementsInstanced(
+ [gl.TRIANGLES, [3], 1, gl.UNSIGNED_BYTE, [0], 0, [1], 0, 1],
+ gl.INVALID_OPERATION, "with countsStart >= countsList.length");
+ checkMultiDrawElementsInstanced(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 1, [1], 0, 1],
+ gl.INVALID_OPERATION, "with offsetsStart >= offsetsList.length");
+ checkMultiDrawElementsInstanced(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 1, 1],
+ gl.INVALID_OPERATION, "with instanceCountsStart >= instanceCountsList.length");
+ }
+ }
+
+ function runShaderTests(bufferUsage) {
+ const illegalProgram = wtu.setupProgram(gl, ["vshaderIllegalDrawID", "fshader"], ["vPosition"], [0]);
+ expectTrue(illegalProgram == null, "cannot compile program with gl_DrawID but no extension directive");
+
+ const drawIDProgram = wtu.setupProgram(gl, ["vshaderDrawIDZero", "fshader"], ["vPosition"], [0]);
+ wtu.setupProgram(gl, ["vshaderDrawIDZero", "fshader"], ["vPosition"], [0]);
+ expectTrue(drawIDProgram !== null, "can compile program with gl_DrawID");
+ gl.useProgram(drawIDProgram);
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0,1, 0,1, 1,0, 1,1 ]), bufferUsage);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "gl_DrawID is 0 for non-Multi* draw calls", 0);
+ }
+
+ function runPixelTests(bufferUsage, useSharedArrayBuffer) {
+ // An array of quads is tiled across the screen.
+ // gl_DrawID is checked by using it to select the color of the draw.
+ // Instanced entrypoints are tested here scaling and then instancing the
+ // array of quads over four quadrants on the screen.
+
+ // These tests also include "manyDraw" tests which emulate a multiDraw with
+ // a Javascript for-loop and gl_DrawID with a uniform constiable. They are
+ // included to ensure the test is written correctly.
+
+ const width = gl.canvas.width;
+ const height = gl.canvas.height;
+ const x_count = 8;
+ const y_count = 8;
+ const quad_count = x_count * y_count;
+ const tri_count = quad_count * 2;
+ const tileSize = [ 1/x_count, 1/y_count ];
+ const tilePixelSize = [ Math.floor(width / x_count), Math.floor(height / y_count) ];
+ const quadRadius = [ 0.25 * tileSize[0], 0.25 * tileSize[1] ];
+ const pixelCheckSize = [ Math.floor(quadRadius[0] * width), Math.floor(quadRadius[1] * height) ];
+
+ function getTileCenter(x, y) {
+ return [ tileSize[0] * (0.5 + x), tileSize[1] * (0.5 + y) ];
+ }
+
+ function getQuadVertices(x, y) {
+ const center = getTileCenter(x, y);
+ return [
+ [center[0] - quadRadius[0], center[1] - quadRadius[1], 0],
+ [center[0] + quadRadius[0], center[1] - quadRadius[1], 0],
+ [center[0] + quadRadius[0], center[1] + quadRadius[1], 0],
+ [center[0] - quadRadius[0], center[1] + quadRadius[1], 0],
+ ]
+ }
+
+ const indicesData = [];
+ const verticesData = [];
+ const nonIndexedVerticesData = [];
+ {
+ const is = new Uint16Array([0, 1, 2, 0, 2, 3]);
+ for (let y = 0; y < y_count; ++y) {
+ for (let x = 0; x < x_count; ++x) {
+ const quadIndex = y * x_count + x;
+ const starting_index = 4 * quadIndex;
+ const vs = getQuadVertices(x, y);
+ for (let i = 0; i < is.length; ++i) {
+ indicesData.push(starting_index + is[i]);
+ }
+ for (let i = 0; i < vs.length; ++i) {
+ for (let v = 0; v < vs[i].length; ++v) verticesData.push(vs[i][v]);
+ }
+ for (let i = 0; i < is.length; ++i) {
+ for (let v = 0; v < vs[is[i]].length; ++v) nonIndexedVerticesData.push(vs[is[i]][v]);
+ }
+ }
+ }
+ }
+
+ const indices = new Uint16Array(indicesData);
+ const vertices = new Float32Array(verticesData);
+ const nonIndexedVertices = new Float32Array(nonIndexedVerticesData);
+
+ const indexBuffer = gl.createBuffer();
+ const vertexBuffer = gl.createBuffer();
+ const nonIndexedVertexBuffer = gl.createBuffer();
+ const instanceBuffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonIndexedVertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, nonIndexedVertices, bufferUsage);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, bufferUsage);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, bufferUsage);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), bufferUsage);
+
+ function checkResult(config, msg) {
+ const rects = [];
+ const expected = [
+ [255, 0, 0, 255],
+ [0, 255, 0, 255],
+ [0, 0, 255, 255],
+ ];
+ for (let y = 0; y < y_count; ++y) {
+ for (let x = 0; x < x_count; ++x) {
+ const center_x = x * tilePixelSize[0] + Math.floor(tilePixelSize[0] / 2);
+ const center_y = y * tilePixelSize[1] + Math.floor(tilePixelSize[1] / 2);
+ const quadID = y * x_count + x;
+ const colorID = config.drawID ? quadID % 3 : 0;
+ if (config.instanced) {
+ rects.push(wtu.makeCheckRect(
+ center_x / 2 - Math.floor(pixelCheckSize[0] / 4),
+ center_y / 2 - Math.floor(pixelCheckSize[1] / 4),
+ pixelCheckSize[0] / 2,
+ pixelCheckSize[1] / 2,
+ expected[colorID],
+ msg + " (" + x + "," + y + ")", 0));
+ rects.push(wtu.makeCheckRect(
+ center_x / 2 - Math.floor(pixelCheckSize[0] / 4) + width / 2,
+ center_y / 2 - Math.floor(pixelCheckSize[1] / 4),
+ pixelCheckSize[0] / 2,
+ pixelCheckSize[1] / 2,
+ expected[colorID],
+ msg + " (" + x + "," + y + ")", 0));
+ rects.push(wtu.makeCheckRect(
+ center_x / 2 - Math.floor(pixelCheckSize[0] / 4),
+ center_y / 2 - Math.floor(pixelCheckSize[1] / 4) + height / 2,
+ pixelCheckSize[0] / 2,
+ pixelCheckSize[1] / 2,
+ expected[colorID],
+ msg + " (" + x + "," + y + ")", 0));
+ rects.push(wtu.makeCheckRect(
+ center_x / 2 - Math.floor(pixelCheckSize[0] / 4) + width / 2,
+ center_y / 2 - Math.floor(pixelCheckSize[1] / 4) + height / 2,
+ pixelCheckSize[0] / 2,
+ pixelCheckSize[1] / 2,
+ expected[colorID],
+ msg + " (" + x + "," + y + ")", 0));
+ } else {
+ rects.push(wtu.makeCheckRect(
+ center_x - Math.floor(pixelCheckSize[0] / 2),
+ center_y - Math.floor(pixelCheckSize[1] / 2),
+ pixelCheckSize[0],
+ pixelCheckSize[1],
+ expected[colorID],
+ msg + " (" + x + "," + y + ")", 0));
+ }
+ }
+ }
+ wtu.checkCanvasRects(gl, rects);
+ }
+
+ function newIntArray(count) {
+ if (!useSharedArrayBuffer) {
+ return new Int32Array(count);
+ }
+ let sab = new SharedArrayBuffer(count * Int32Array.BYTES_PER_ELEMENT);
+ return new Int32Array(sab);
+ }
+
+ const firsts = newIntArray(tri_count);
+ const counts = newIntArray(tri_count);
+ const offsets = newIntArray(tri_count);
+ const instances = newIntArray(tri_count);
+
+ for (let i = 0; i < firsts.length; ++i) firsts[i] = i * 3;
+ counts.fill(3);
+ for (let i = 0; i < offsets.length; ++i) offsets[i] = i * 3 * 2;
+ instances.fill(4);
+
+ const firstsOffset = 47;
+ const countsOffset = firstsOffset + firsts.length;
+ const offsetsOffset = countsOffset + counts.length;
+ const instancesOffset = offsetsOffset + instances.length;
+
+ const buffer = newIntArray(firstsOffset + firsts.length + counts.length + offsets.length + instances.length);
+ buffer.set(firsts, firstsOffset);
+ buffer.set(counts, countsOffset);
+ buffer.set(offsets, offsetsOffset);
+ buffer.set(instances, instancesOffset);
+
+ let drawIDLocation;
+
+ const multiDrawArrays = function() {
+ ext.multiDrawArraysWEBGL(gl.TRIANGLES, firsts, 0, counts, 0, tri_count);
+ }
+
+ const multiDrawArraysWithNonzeroOffsets = function() {
+ ext.multiDrawArraysWEBGL(gl.TRIANGLES, buffer, firstsOffset, buffer, countsOffset, tri_count);
+ }
+
+ const multiDrawElements = function() {
+ ext.multiDrawElementsWEBGL(gl.TRIANGLES, counts, 0, gl.UNSIGNED_SHORT, offsets, 0, tri_count);
+ }
+
+ const multiDrawElementsWithNonzeroOffsets = function() {
+ ext.multiDrawElementsWEBGL(gl.TRIANGLES, buffer, countsOffset, gl.UNSIGNED_SHORT, buffer, offsetsOffset, tri_count);
+ }
+
+ const multiDrawArraysInstanced = function() {
+ ext.multiDrawArraysInstancedWEBGL(gl.TRIANGLES, firsts, 0, counts, 0, instances, 0, tri_count);
+ }
+
+ const multiDrawArraysInstancedWithNonzeroOffsets = function() {
+ ext.multiDrawArraysInstancedWEBGL(gl.TRIANGLES, buffer, firstsOffset, buffer, countsOffset, buffer, instancesOffset, tri_count);
+ }
+
+ const multiDrawElementsInstanced = function() {
+ ext.multiDrawElementsInstancedWEBGL(gl.TRIANGLES, counts, 0, gl.UNSIGNED_SHORT, offsets, 0, instances, 0, tri_count);
+ }
+
+ const multiDrawElementsInstancedWithNonzeroOffsets = function() {
+ ext.multiDrawElementsInstancedWEBGL(gl.TRIANGLES, buffer, countsOffset, gl.UNSIGNED_SHORT, buffer, offsetsOffset, buffer, instancesOffset, tri_count);
+ }
+
+ const manyDrawArrays = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ gl.drawArrays(gl.TRIANGLES, firsts[i], counts[i]);
+ }
+ }
+
+ const manyDrawElements = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ gl.drawElements(gl.TRIANGLES, counts[i], gl.UNSIGNED_SHORT, offsets[i]);
+ }
+ }
+
+ const manyDrawArraysEmulateDrawID = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ gl.uniform1i(drawIDLocation, i);
+ gl.drawArrays(gl.TRIANGLES, firsts[i], counts[i]);
+ }
+ }
+
+ const manyDrawElementsEmulateDrawID = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ gl.uniform1i(drawIDLocation, i);
+ gl.drawElements(gl.TRIANGLES, counts[i], gl.UNSIGNED_SHORT, offsets[i]);
+ }
+ }
+
+ function drawArraysInstanced() {
+ if (wtu.getDefault3DContextVersion() < 2) {
+ instancedExt.drawArraysInstancedANGLE.apply(instancedExt, arguments);
+ } else {
+ gl.drawArraysInstanced.apply(gl, arguments);
+ }
+ }
+
+ function drawElementsInstanced() {
+ if (wtu.getDefault3DContextVersion() < 2) {
+ instancedExt.drawElementsInstancedANGLE.apply(instancedExt, arguments);
+ } else {
+ gl.drawElementsInstanced.apply(gl, arguments);
+ }
+ }
+
+ function vertexAttribDivisor(attrib, divisor) {
+ if (wtu.getDefault3DContextVersion() < 2) {
+ instancedExt.vertexAttribDivisorANGLE(attrib, divisor);
+ } else {
+ gl.vertexAttribDivisor(attrib, divisor);
+ }
+ }
+
+ const manyDrawArraysInstanced = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ drawArraysInstanced(gl.TRIANGLES, firsts[i], counts[i], 4);
+ }
+ }
+
+ const manyDrawElementsInstanced = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ drawElementsInstanced(gl.TRIANGLES, counts[i], gl.UNSIGNED_SHORT, offsets[i], 4);
+ }
+ }
+
+ const manyDrawArraysInstancedEmulateDrawID = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ gl.uniform1i(drawIDLocation, i);
+ drawArraysInstanced(gl.TRIANGLES, firsts[i], counts[i], 4);
+ }
+ }
+
+ const manyDrawElementsInstancedEmulateDrawID = function() {
+ for (let i = 0; i < tri_count; ++i) {
+ gl.uniform1i(drawIDLocation, i);
+ drawElementsInstanced(gl.TRIANGLES, counts[i], gl.UNSIGNED_SHORT, offsets[i], 4);
+ }
+ }
+
+ function checkDraw(config) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ if (config.indexed) {
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ } else {
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonIndexedVertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ }
+
+ if (config.instanced) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+ vertexAttribDivisor(1, 1);
+ }
+
+ config.drawFunc();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ checkResult(config, config.drawFunc.name + (
+ config.instanced ? ' instanced' : ''
+ ) + (
+ config.drawID ? ' with gl_DrawID' : ''
+ ) + (
+ useSharedArrayBuffer ? ' and SharedArrayBuffer' : ''
+ ));
+
+ gl.disableVertexAttribArray(0);
+ gl.disableVertexAttribArray(1);
+ }
+
+ const noDrawIDProgram = wtu.setupProgram(gl, ["vshaderNoDrawID", "fshader"], ["vPosition", "vInstance"], [0, 1]);
+ expectTrue(noDrawIDProgram != null, "can compile simple program");
+ if (noDrawIDProgram) {
+ gl.useProgram(noDrawIDProgram);
+
+ if (!instanced) {
+ checkDraw({
+ drawFunc: multiDrawArrays,
+ drawID: false,
+ });
+ checkDraw({
+ drawFunc: multiDrawArraysWithNonzeroOffsets,
+ drawID: false,
+ });
+ checkDraw({
+ drawFunc: multiDrawElements,
+ indexed: true,
+ drawID: false,
+ });
+ checkDraw({
+ drawFunc: multiDrawElementsWithNonzeroOffsets,
+ indexed: true,
+ drawID: false,
+ });
+ checkDraw({
+ drawFunc: manyDrawArrays,
+ drawID: false,
+ });
+ checkDraw({
+ drawFunc: manyDrawElements,
+ indexed: true,
+ drawID: false,
+ });
+ } else {
+ checkDraw({
+ drawFunc: multiDrawArraysInstanced,
+ drawID: false,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawArraysInstancedWithNonzeroOffsets,
+ drawID: false,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawElementsInstanced,
+ indexed: true,
+ drawID: false,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawElementsInstancedWithNonzeroOffsets,
+ indexed: true,
+ drawID: false,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: manyDrawArraysInstanced,
+ drawID: false,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: manyDrawElementsInstanced,
+ indexed: true,
+ drawID: false,
+ instanced: true,
+ });
+ }
+ }
+
+ const withDrawIDProgram = wtu.setupProgram(gl, ["vshaderWithDrawID", "fshader"], ["vPosition", "vInstance"], [0, 1]);
+ expectTrue(withDrawIDProgram != null, "can compile program with ANGLE_multi_draw");
+ if (withDrawIDProgram) {
+ gl.useProgram(withDrawIDProgram);
+
+ if (!instanced) {
+ checkDraw({
+ drawFunc: multiDrawArrays,
+ drawID: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawArraysWithNonzeroOffsets,
+ drawID: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawElements,
+ indexed: true,
+ drawID: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawElementsWithNonzeroOffsets,
+ indexed: true,
+ drawID: true,
+ });
+ } else {
+ checkDraw({
+ drawFunc: multiDrawArraysInstanced,
+ drawID: true,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawArraysInstancedWithNonzeroOffsets,
+ drawID: true,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawElementsInstanced,
+ indexed: true,
+ drawID: true,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: multiDrawElementsInstancedWithNonzeroOffsets,
+ indexed: true,
+ drawID: true,
+ instanced: true,
+ });
+ }
+ }
+
+ const emulatedDrawIDProgram = wtu.setupProgram(gl, ["vshaderEmulatedDrawID", "fshader"], ["vPosition", "vInstance"], [0, 1]);
+ expectTrue(emulatedDrawIDProgram != null, "can compile program to emulate gl_DrawID");
+ drawIDLocation = gl.getUniformLocation(emulatedDrawIDProgram, "drawID");
+ if (emulatedDrawIDProgram) {
+ gl.useProgram(emulatedDrawIDProgram);
+
+ if (!instanced) {
+ checkDraw({
+ drawFunc: manyDrawArraysEmulateDrawID,
+ drawID: true,
+ });
+ checkDraw({
+ drawFunc: manyDrawElementsEmulateDrawID,
+ indexed: true,
+ drawID: true,
+ });
+ } else {
+ checkDraw({
+ drawFunc: manyDrawArraysInstancedEmulateDrawID,
+ drawID: true,
+ instanced: true,
+ });
+ checkDraw({
+ drawFunc: manyDrawElementsInstancedEmulateDrawID,
+ indexed: true,
+ drawID: true,
+ instanced: true,
+ });
+ }
+ }
+ }
+
+ for (let i = 0; i < bufferUsageSet.length; i++) {
+ let bufferUsage = bufferUsageSet[i];
+ debug("Testing with BufferUsage = " + bufferUsage);
+ runValidationTests(bufferUsage);
+ runShaderTests(bufferUsage);
+ runPixelTests(bufferUsage, false);
+ }
+
+ // Run a subset of the pixel tests with SharedArrayBuffer if supported.
+ if (window.SharedArrayBuffer) {
+ runPixelTests(bufferUsageSet[0], true);
+ }
+}
+
+function waitForComposite() {
+ debug('wait for composite');
+ return new Promise(resolve => wtu.waitForComposite(resolve));
+}
+
+async function testPreserveDrawingBufferFalse(gl, drawFn) {
+ debug('');
+ debug('test preserveDrawingBuffer: false');
+
+ if (drawFn(gl)) {
+ debug('skipped: extension does not exist');
+ return;
+ }
+
+ wtu.checkCanvasRect(gl, 0, 0, 20, 20, [255, 0, 0, 255],
+ "canvas should be red");
+
+ // enable scissor here, before compositing, to make sure it's correctly
+ // ignored and restored
+ gl.scissor(0, 10, 10, 10);
+ gl.enable(gl.SCISSOR_TEST);
+
+ await waitForComposite();
+
+ // scissor was set earlier
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.checkCanvasRect(gl, 0, 10, 10, 10, [0, 0, 255, 255],
+ "cleared corner should be blue, stencil should be preserved");
+ wtu.checkCanvasRect(gl, 0, 0, 10, 10, [0, 0, 0, 0],
+ "remainder of buffer should be cleared");
+
+ gl.disable(gl.SCISSOR_TEST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+async function testPreserveDrawingBufferTrue(gl, drawFn) {
+ debug('');
+ debug('test preserveDrawingBuffer: true');
+ if (drawFn(gl)) {
+ debug('skipped: extension does not exist');
+ return;
+ }
+
+ wtu.checkCanvasRect(gl, 0, 0, 20, 20, [255, 0, 0, 255],
+ "canvas should be red");
+
+ await waitForComposite();
+
+ wtu.checkCanvasRect(gl, 0, 0, 20, 20, [255, 0, 0, 255],
+ "canvas should be red");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+async function doCompositingTests([glPreserveDrawingBufferFalse, glPreserveDrawingBufferTrue], drawFn) {
+ debug('');
+ debug(drawFn.name);
+
+ await testPreserveDrawingBufferFalse(glPreserveDrawingBufferFalse, drawFn);
+ await testPreserveDrawingBufferTrue(glPreserveDrawingBufferTrue, drawFn);
+}
+
+async function runDrawTests(testFn) {
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ function drawArraysInstanced(gl) {
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, 1);
+ }
+
+ function drawElementsInstanced(gl) {
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1);
+ }
+
+ function multiDrawArraysWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_multi_draw');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_multi_draw';
+ }
+
+ ext.multiDrawArraysWEBGL(
+ gl.TRIANGLES,
+ [0], 0, // firsts
+ [6], 0, // counts
+ 1, // drawCount
+ );
+ }
+
+ function multiDrawElementsWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_multi_draw');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_multi_draw';
+ }
+
+ ext.multiDrawElementsWEBGL(
+ gl.TRIANGLES,
+ [6], 0, // counts
+ gl.UNSIGNED_BYTE,
+ [0], 0, // offsets
+ 1, // drawCount
+ );
+ }
+
+ function multiDrawArraysInstancedWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_multi_draw');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_multi_draw';
+ }
+ ext.multiDrawArraysInstancedWEBGL(
+ gl.TRIANGLES,
+ [0], 0, // firsts
+ [6], 0, // counts
+ [1], 0, // instances
+ 1, // drawCount
+ );
+ }
+
+ function multiDrawElementsInstancedWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_multi_draw');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_multi_draw';
+ }
+ ext.multiDrawElementsInstancedWEBGL(
+ gl.TRIANGLES,
+ [6], 0, // counts
+ gl.UNSIGNED_BYTE,
+ [0], 0, // offsets
+ [1], 0, // instances
+ 1, // drawCount
+ );
+ }
+
+ await testFn(drawArrays); // sanity check
+ await testFn(drawElements); // sanity check
+
+ // It's only legal to call testFn if the extension is supported,
+ // since the invalid vertex attrib tests, in particular, expect the
+ // draw function to have an effect.
+ if (gl.getExtension('WEBGL_multi_draw')) {
+ await testFn(multiDrawArraysWEBGL);
+ await testFn(multiDrawElementsWEBGL);
+ await testFn(multiDrawArraysInstancedWEBGL);
+ await testFn(multiDrawElementsInstancedWEBGL);
+ }
+}
+
+async function runCompositingTests() {
+ const compositingTestFn = createCompositingTestFn({
+ webglVersion: 1,
+ shadersFn(gl) {
+ const vs = `\
+ //#extension GL_ANGLE_multi_draw : enable
+ attribute vec4 position;
+ void main() {
+ gl_Position = position;
+ }
+ `;
+ const fs = `\
+ precision mediump float;
+ void main() {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+ `;
+ return [vs, fs];
+ },
+ });
+ await runDrawTests(compositingTestFn);
+}
+
+async function runInvalidAttribTests(gl) {
+ const invalidAttribTestFn = createInvalidAttribTestFn(gl);
+ await runDrawTests(invalidAttribTestFn);
+}
+
+function testSideEffects() {
+ debug("")
+ debug("Testing that ANGLE_instanced_arrays is implicitly enabled")
+ const canvas = document.createElement("canvas");
+ const gl = wtu.create3DContext(canvas, undefined, 1);
+ if (!gl) {
+ testFailed('WebGL context creation failed');
+ return;
+ }
+ gl.enableVertexAttribArray(0);
+ const VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
+ gl.getVertexAttrib(0, VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "divisor enum unknown");
+ const ext = gl.getExtension("WEBGL_multi_draw");
+ if (ext) {
+ debug("WEBGL_multi_draw enabled");
+ gl.getVertexAttrib(0, VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "divisor enum known");
+ }
+}
+
+async function main() {
+ runTest();
+ testSideEffects();
+ await runInvalidAttribTests(gl);
+ await runCompositingTests();
+ finishTest();
+}
+main();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-webcodecs-video-frame.html b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-webcodecs-video-frame.html
new file mode 100644
index 0000000000..f0e413e2f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/webgl-webcodecs-video-frame.html
@@ -0,0 +1,211 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="UTF-8">
+ <link rel="stylesheet" href="../../resources/js-test-style.css" />
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"></script>
+ <script src="../../js/tests/out-of-bounds-test.js"></script>
+ <script src="../../../../extensions/proposals/WEBGL_webcodecs_video_frame/webgl_webcodecs_video_frame.js"></script>
+ <style>
+ canvas {
+ padding: 10px;
+ background: gold;
+ }
+
+ button {
+ background-color: #555555;
+ border: none;
+ color: white;
+ padding: 15px 32px;
+ width: 150px;
+ text-align: center;
+ display: block;
+ font-size: 16px;
+ }
+ </style>
+</head>
+
+<body>
+ <canvas id="src" width="640" height="480"></canvas>
+ <canvas id="dst" width="640" height="480"></canvas>
+ <p id="info"></p>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script>
+ "use strict";
+ description("Test of importing Videoframe from Webcodecs to Webgl");
+
+ const kIsRunningTest = true;
+ const kMaxFrame = 10;
+ const kTestPixel = [255, 128, 0, 255];
+ // Sum of pixel difference of R/G/B channel. Use to decide whether a
+ // pixel is matched with another.
+ const codec_string = "vp09.00.51.08.00";
+
+ let wtu = WebGLTestUtils;
+ let cnv = document.getElementById("src");
+ let src_width = cnv.width;
+ let src_height = cnv.height;
+ let src_color = "rgba(" + kTestPixel[0].toString() + "," + kTestPixel[1].toString() + ","
+ + kTestPixel[2].toString() + "," + kTestPixel[3].toString() + ")";
+ let frame_counter = 0;
+ let pixelCompareTolerance = 5;
+
+ function getQueryVariable(variable) {
+ var query = window.location.search.substring(1);
+ var vars = query.split("&");
+ for (var i = 0; i < vars.length; i++) {
+ var pair = vars[i].split("=");
+ if (pair[0] == variable) { return pair[1]; }
+ }
+ return false;
+ }
+
+ let th = parseInt(getQueryVariable('threshold'));
+ if (!isNaN(th))
+ pixelCompareTolerance = th;
+
+ async function startDrawing() {
+ let cnv = document.getElementById("src");
+ var ctx = cnv.getContext('2d', { alpha: false });
+
+ ctx.fillStyle = src_color;
+ let drawOneFrame = function (time) {
+ ctx.fillStyle = src_color;
+ ctx.fillRect(0, 0, src_width, src_height);
+ window.requestAnimationFrame(drawOneFrame);
+ }
+ window.requestAnimationFrame(drawOneFrame);
+ }
+
+ function captureAndEncode(processChunk) {
+ let cnv = document.getElementById("src");
+ let fps = 60;
+ let pending_outputs = 0;
+ let stream = cnv.captureStream(fps);
+ let processor = new MediaStreamTrackProcessor(stream.getVideoTracks()[0]);
+
+ const init = {
+ output: (chunk) => {
+ testPassed("Encode frame successfully.");
+ pending_outputs--;
+ processChunk(chunk);
+ },
+ error: (e) => {
+ testFailed("Failed to encode frame.");
+ finishTest();
+ vtr.stop();
+ }
+ };
+
+ const config = {
+ codec: codec_string,
+ width: cnv.width,
+ height: cnv.height,
+ bitrate: 10e6,
+ framerate: fps,
+ };
+
+ let encoder = new VideoEncoder(init);
+ encoder.configure(config);
+
+ const frame_reader = processor.readable.getReader();
+ frame_reader.read().then(function processFrame({done, value}) {
+ if (done)
+ return;
+
+ if (pending_outputs > 30) {
+ console.log("drop this frame");
+ // Too many frames in flight, encoder is overwhelmed
+ // let's drop this frame.
+ value.close();
+ frame_reader.read().then(processFrame);
+ return;
+ }
+
+ if(frame_counter == kMaxFrame) {
+ frame_reader.releaseLock();
+ processor.readable.cancel();
+ value.close();
+ return;
+ }
+
+ frame_counter++;
+ pending_outputs++;
+ const insert_keyframe = (frame_counter % 150) == 0;
+ encoder.encode(value, { keyFrame: insert_keyframe });
+
+ frame_reader.read().then(processFrame);
+ });
+ }
+
+ function startDecodingAndRendering(cnv, handleFrame) {
+ const init = {
+ output: handleFrame,
+ error: (e) => {
+ testFailed("Failed to decode frame.");
+ finishTest();
+ }
+ };
+
+ const config = {
+ codec: codec_string,
+ codedWidth: cnv.width,
+ codedHeight: cnv.height,
+ acceleration: "deny",
+
+ };
+
+ let decoder = new VideoDecoder(init);
+ decoder.configure(config);
+ return decoder;
+ }
+
+ function isFramePixelMatched(gl, th_per_pixel = pixelCompareTolerance) {
+ WebGLTestUtils.checkCanvasRect(gl, 0, 0, src_width, src_width, kTestPixel, "should be orange", pixelCompareTolerance)
+ }
+
+ function main() {
+ if (!("VideoEncoder" in window)) {
+ testPassed("WebCodecs API is not supported.");
+ finishTest();
+ return;
+ }
+ let cnv = document.getElementById("dst");
+
+ let webgl_webcodecs_test_context = {
+ maxFrameTested: kMaxFrame,
+ displayed_frame: 0,
+ isFramePixelMatched: isFramePixelMatched,
+ testFailed: testFailed,
+ testPassed: testPassed,
+ finishTest: finishTest
+ };
+ setTestMode(webgl_webcodecs_test_context);
+ let handleFrame = requestWebGLVideoFrameHandler(cnv);
+ if (handleFrame === null) {
+ finishTest();
+ return;
+ }
+
+ startDrawing();
+ let decoder = startDecodingAndRendering(cnv, handleFrame);
+ captureAndEncode((chunk) => {
+ decoder.decode(chunk);
+ });
+ }
+
+ document.body.onload = main;
+ </script>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/00_test_list.txt
new file mode 100644
index 0000000000..8ab2039cc6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/00_test_list.txt
@@ -0,0 +1,12 @@
+bugs/00_test_list.txt
+--min-version 1.0.3 constructors/00_test_list.txt
+functions/00_test_list.txt
+implicit/00_test_list.txt
+--min-version 1.0.2 literals/00_test_list.txt
+--min-version 1.0.2 matrices/00_test_list.txt
+misc/00_test_list.txt
+--min-version 1.0.4 preprocessor/00_test_list.txt
+reserved/00_test_list.txt
+--min-version 1.0.2 samplers/00_test_list.txt
+variables/00_test_list.txt
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/00_test_list.txt
new file mode 100644
index 0000000000..c84e94bbd0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/00_test_list.txt
@@ -0,0 +1,52 @@
+--min-version 1.0.4 angle-ambiguous-function-call.html
+--min-version 1.0.4 angle-constructor-invalid-parameters.html
+--min-version 1.0.3 angle-d3d11-compiler-error.html
+--min-version 1.0.3 angle-dx-variable-bug.html
+--min-version 1.0.3 array-of-struct-with-int-first-position.html
+--min-version 1.0.4 assign-to-swizzled-twice-in-function.html
+--min-version 1.0.4 bool-type-cast-bug-int-float.html
+--min-version 1.0.4 character-set.html
+--min-version 1.0.3 compare-loop-index-to-uniform.html
+--min-version 1.0.3 complex-glsl-does-not-crash.html
+--min-version 1.0.4 compound-assignment-type-combination.html
+--min-version 1.0.3 conditional-discard-in-loop.html
+--min-version 1.0.3 conditional-discard-optimization.html
+--min-version 1.0.4 conditional-texture-fetch.html
+--min-version 1.0.3 constant-precision-qualifier.html
+--min-version 1.0.3 --max-version 1.99 essl3-shaders-with-webgl1.html
+--min-version 1.0.4 floor-div-cos-should-not-truncate.html
+--min-version 1.0.3 floored-division-accuracy.html
+--min-version 1.0.3 fragcoord-linking-bug.html
+--min-version 1.0.4 gl-fragcoord-multisampling-bug.html
+--min-version 1.0.4 global-invariant-does-not-leak-across-shaders.html
+--min-version 1.0.4 if-return-and-elseif.html
+--min-version 1.0.4 init-array-with-loop.html
+--min-version 1.0.4 invariant-does-not-leak-across-shaders.html
+--min-version 1.0.4 in-parameter-passed-as-inout-argument-and-global.html
+--min-version 1.0.4 logic-inside-block-without-braces.html
+--min-version 1.0.3 long-expressions-should-not-crash.html
+--min-version 1.0.4 loop-if-loop-gradient.html
+--min-version 1.0.3 modulo-arithmetic-accuracy.html
+--min-version 1.0.3 multiplication-assignment.html
+--min-version 1.0.3 nested-functions-should-not-crash.html
+--min-version 1.0.4 nested-loops-with-break-and-continue.html
+--min-version 1.0.4 nested-sequence-operator.html
+--min-version 1.0.4 pow-of-small-constant-in-user-defined-function.html
+--min-version 1.0.4 pow-with-constant-exponent-should-not-crash.html
+--min-version 1.0.4 qualcomm-crash.html
+--min-version 1.0.4 qualcomm-loop-with-continue-crash.html
+--min-version 1.0.4 sampler-array-struct-function-arg.html
+--min-version 1.0.3 sampler-array-using-loop-index.html
+--min-version 1.0.4 sampler-struct-function-arg.html
+--min-version 1.0.4 sequence-operator-evaluation-order.html
+--min-version 1.0.4 sketchfab-lighting-shader-crash.html
+--min-version 1.0.4 struct-constructor-highp-bug.html
+--min-version 1.0.4 struct-with-single-member-constructor.html
+--min-version 1.0.3 temp-expressions-should-not-crash.html
+--min-version 1.0.4 unary-minus-operator-float-bug.html
+--min-version 1.0.4 undefined-index-should-not-crash.html
+--min-version 1.0.3 uniforms-should-not-lose-values.html
+--min-version 1.0.4 varying-arrays-should-not-be-reversed.html
+--min-version 1.0.4 vector-matrix-constructor-scalarization.html
+--min-version 1.0.4 vector-scalar-arithmetic-inside-loop.html
+--min-version 1.0.4 vector-scalar-arithmetic-inside-loop-complex.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/README.md b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/README.md
new file mode 100644
index 0000000000..d917f6d741
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/README.md
@@ -0,0 +1,18 @@
+BUGS
+====
+
+This folder is for GLSL tests that test driver specific bugs.
+
+Most tests in other folders are fairly generic. While they might
+only fail on specific drivers the tests themselves are designed
+to test something in a generic way.
+
+Tests in this folder on the otherhand are very targeted. They may
+have very specific shaders that only fail under specific circumstances
+on specific drivers.
+
+An example might be if there was a driver that failed only when
+and identifier was named "ABC". It makes no sense to have a generic
+test that says "must allow ABC". A generic test would test some
+subset of all possible identifiers not just one.
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-ambiguous-function-call.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-ambiguous-function-call.html
new file mode 100644
index 0000000000..c7f10a05f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-ambiguous-function-call.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ANGLE ambiguous function call test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderAmbiguousHLSLFunctionCall" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 uv;
+uniform mat2 um;
+vec4 foo(vec4 v) {
+ return v;
+}
+vec4 foo(mat2 m) {
+ return vec4(m);
+}
+void main()
+{
+ gl_FragColor = foo(uv) + foo(um);
+}
+</script>
+<script id="fshaderAmbiguousHLSLStructFunctionCall" type="x-shader/x-fragment">
+precision mediump float;
+uniform float u_zero;
+struct S { float foo; };
+struct S2 { float foo; };
+float get(S s) { return s.foo + u_zero; }
+float get(S2 s2) { return 0.25 + s2.foo + u_zero; }
+void main()
+{
+ S s;
+ s.foo = 0.5;
+ S2 s2;
+ s2.foo = 0.25;
+ gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("Test overloaded functions with vec4 and mat2 parameters that have had issues in ANGLE. Issues were due to HLSL compiler treating float4 and float2x2 as the same type when resolving which overloaded function to call.");
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshaderAmbiguousHLSLFunctionCall',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Disambiguate correctly between overloaded function calls with 4-component float parameters"
+},
+{
+ fShaderId: 'fshaderAmbiguousHLSLStructFunctionCall',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Disambiguate correctly between overloaded function calls with struct parameters",
+ render: true
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-constructor-invalid-parameters.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-constructor-invalid-parameters.html
new file mode 100644
index 0000000000..6c663811f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-constructor-invalid-parameters.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ANGLE constructor bugs test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderSamplerInConstructorArguments" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D s;
+void main()
+{
+ gl_FragColor = vec4(0.0, s, 0.0, 0.0);
+}
+</script>
+<script id="fshaderVoidInConstructorArguments" type="x-shader/x-fragment">
+precision mediump float;
+void foo() {}
+void main()
+{
+ gl_FragColor = vec4(0.0, foo(), 0.0, 0.0);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("Test constructors that have had issues in ANGLE");
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshaderSamplerInConstructorArguments',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Sampler in constructor arguments should not compile"
+},
+{
+ fShaderId: 'fshaderVoidInConstructorArguments',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Void in constructor arguments should not compile"
+},
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-d3d11-compiler-error.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-d3d11-compiler-error.html
new file mode 100644
index 0000000000..158ddad08f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-d3d11-compiler-error.html
@@ -0,0 +1,96 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ANGLE D3D11 Bug - Shader compilation error</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+
+<script id="vs" type="x-shader/x-fragment">
+precision mediump float;
+uniform float A;
+void main() {
+ bool B = bool(A);
+ float x = B ? -A : 1.+A;
+ float y = B ? 1.+A : -A;
+ gl_Position = vec4(x, y, 0, 0);
+}
+
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1, 0, 0, 1);
+}
+</script>
+
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+// See http://crbug.com/371868 for original failing case.
+description("This test checks an ANGLE D3D11 shader compiler error.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking shader compilation and linking.");
+
+ checkCompilation();
+}
+
+function checkCompilation() {
+ var vs = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vs, document.getElementById("vs").text);
+ gl.compileShader(vs);
+ if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
+ testFailed("Vertex Shader failed to compile: " + gl.getShaderInfoLog(vs));
+ return;
+ }
+
+ var fs = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs, document.getElementById("fs").text);
+ gl.compileShader(fs);
+ if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
+ testFailed("Fragment Shader failed to compile: " + gl.getShaderInfoLog(fs));
+ return;
+ }
+
+ var p = gl.createProgram();
+ gl.attachShader(p, vs);
+ gl.attachShader(p, fs);
+ gl.linkProgram(p);
+ if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
+ testFailed("Program failed to link: " + gl.getProgramInfoLog(p));
+ return;
+ }
+
+ testPassed("Linked Successfully");
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-dx-variable-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-dx-variable-bug.html
new file mode 100644
index 0000000000..c094beff66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/angle-dx-variable-bug.html
@@ -0,0 +1,96 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ANGLE D3D11 Bug - Variables beginning with "dx_"</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+
+<script id="vs" type="x-shader/x-fragment">
+precision mediump float;
+attribute vec4 position;
+varying float dx_var;
+void main() {
+ gl_Position = position;
+ dx_var = position.x;
+}
+
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+varying float dx_var;
+void main() {
+ gl_FragColor = vec4(dx_var, 0, 0, 1);
+}
+</script>
+
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+// See http://crbug.com/371868 for original failing case.
+description("This test checks an ANGLE D3D11 shader compiler error.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking shader compilation and linking.");
+
+ checkCompilation()
+}
+
+function checkCompilation() {
+ var vs = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vs, document.getElementById("vs").text);
+ gl.compileShader(vs);
+ if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
+ testFailed("Vertex Shader failed to compile: " + gl.getShaderInfoLog(vs));
+ return;
+ }
+
+ var fs = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs, document.getElementById("fs").text);
+ gl.compileShader(fs);
+ if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
+ testFailed("Fragment Shader failed to compile: " + gl.getShaderInfoLog(fs));
+ return;
+ }
+
+ var p = gl.createProgram();
+ gl.attachShader(p, vs);
+ gl.attachShader(p, fs);
+ gl.linkProgram(p);
+ if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
+ testFailed("Program failed to link: " + gl.getProgramInfoLog(p));
+ return;
+ }
+
+ testPassed("Linked Successfully");
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/array-of-struct-with-int-first-position.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/array-of-struct-with-int-first-position.html
new file mode 100644
index 0000000000..e7dd805566
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/array-of-struct-with-int-first-position.html
@@ -0,0 +1,141 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver Bug - Array of structs with int or bool in first position</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+
+<body>
+<canvas id="example" style="border: none;" width="788" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+attribute vec2 pos;
+void main(void) {
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
+</script>
+
+<script id="shader-fs-int" type="x-shader/x-fragment">
+precision mediump float;
+struct Light {
+ int unused;
+ vec3 color;
+};
+const int numLights = 1;
+void main() {
+ Light lights[numLights];
+ lights[0].color = vec3(0.0, 0.5, 0.0);
+
+ vec3 result = vec3(0.0, 0.0, 0.0);
+ for (int i=0; i<numLights; i++) {
+ result += lights[i].color;
+ }
+ gl_FragColor = vec4(result.rgb, 1.0);
+}
+</script>
+
+<script id="shader-fs-bool" type="x-shader/x-fragment">
+precision mediump float;
+struct Light {
+ bool unused;
+ vec3 color;
+};
+const int numLights = 1;
+void main() {
+ Light lights[numLights];
+ lights[0].color = vec3(0.0, 0.5, 0.0);
+
+ vec3 result = vec3(0.0, 0.0, 0.0);
+ for (int i=0; i<numLights; i++) {
+ result += lights[i].color;
+ }
+ gl_FragColor = vec4(result.rgb, 1.0);
+}
+</script>
+
+<script id="shader-fs-bool-read" type="x-shader/x-fragment">
+precision mediump float;
+struct Light {
+ bool useLight;
+ vec3 color;
+};
+const int numLights = 1;
+void main() {
+ Light lights[numLights];
+ lights[0].color = vec3(0.0, 0.5, 0.0);
+ lights[0].useLight = true;
+
+ vec3 result = vec3(0.0, 0.0, 0.0);
+ for (int i=0; i<numLights; i++) {
+ Light light = lights[i];
+ if (light.useLight) {
+ result += light.color;
+ }
+ }
+ gl_FragColor = vec4(result.rgb, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+
+function test() {
+ description();
+ debug(
+ "This test checks accessing an array of structs, where the struct " +
+ "definition has an int or bool in the first position. " +
+ "This test has has failed in OS X on some NVIDIA cards, " +
+ "such as the NVIDIA GeForce GT 650M. If things are working " +
+ "correctly, then there will be a series of 50% green squares.")
+ debug("");
+
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("example");
+ var gl = wtu.create3DContext(canvas);
+
+ var testNum = 0;
+ var border = 10; // border between test squares for visibility
+ var squareSize = 256;
+ var expectedColor = [0, 127, 0, 255]; // 50% green
+
+ function subTest(message, fragmentShader) {
+ debug(message);
+ var startX = (squareSize + border) * testNum;
+ var program = wtu.setupProgram(
+ gl, ["shader-vs", fragmentShader], ["pos"], null, true);
+ gl.viewport(startX, 0, squareSize, squareSize);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(
+ gl, startX, 0, squareSize, squareSize,
+ expectedColor, "square should be 50% green", 1);
+ debug("");
+ testNum++;
+ }
+
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ wtu.setupUnitQuad(gl);
+ subTest("Test unused int in first struct position.", "shader-fs-int");
+ subTest("Test unused bool in first struct position.", "shader-fs-bool");
+ subTest("Test used bool in first struct position.", "shader-fs-bool-read");
+ }
+}
+
+test();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html
new file mode 100644
index 0000000000..847127a408
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Assigning an assignment to a swizzled value inside function</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+vec2 f()
+{
+ vec2 r = vec2(0);
+ r.x = r.y = 1.0;
+ return r;
+}
+
+void main()
+{
+ gl_FragColor.ga = f();
+}
+
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+// Minimal test case based on report at http://crbug.com/798117
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Assigning an assignment to a swizzled value inside a user-defined function"
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/bool-type-cast-bug-int-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/bool-type-cast-bug-int-float.html
new file mode 100644
index 0000000000..984c4e0289
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/bool-type-cast-bug-int-float.html
@@ -0,0 +1,312 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify int(bool) and float(bool) work correctly (Mac AMD driver bug)</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader-int1" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+varying mediump float fvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ int ivalue = int(bvalue);
+ if (ivalue == 0) {
+ fvalue = 0.0;
+ } else if (ivalue == 1) {
+ fvalue = 1.0;
+ } else {
+ fvalue = -1.0;
+ }
+}
+</script>
+<script id="fshader-int1" type="x-shader/x-fragment">
+varying mediump float fvalue;
+
+void main() {
+ if (fvalue == 1.0)
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == 0.0)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-int2" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-int2" type="x-shader/x-fragment">
+uniform bool bvalue;
+
+void main() {
+ int ivalue = int(bvalue);
+
+ if (ivalue == 1)
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == 0)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-float1" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+varying mediump float fvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ fvalue = float(bvalue);
+}
+</script>
+<script id="fshader-float1" type="x-shader/x-fragment">
+varying mediump float fvalue;
+
+void main() {
+ if (fvalue == 1.0)
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == 0.0)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-float2" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-float2" type="x-shader/x-fragment">
+uniform bool bvalue;
+
+void main() {
+ mediump float fvalue = float(bvalue);
+
+ if (fvalue == 1.0)
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == 0.0)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-vec2-1" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+varying mediump vec2 fvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ fvalue = vec2(bvalue);
+}
+</script>
+<script id="fshader-vec2-1" type="x-shader/x-fragment">
+varying mediump vec2 fvalue;
+
+void main() {
+ if (fvalue == vec2(1.0, 1.0))
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == vec2(0.0, 0.0))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-vec2-2" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-vec2-2" type="x-shader/x-fragment">
+precision mediump float;
+uniform bool bvalue;
+
+void main() {
+ vec2 fvalue = vec2(bvalue);
+
+ if (fvalue == vec2(1.0, 1.0))
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == vec2(0.0, 0.0))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-vec3-1" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+varying mediump vec3 fvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ fvalue = vec3(bvalue);
+}
+</script>
+<script id="fshader-vec3-1" type="x-shader/x-fragment">
+varying mediump vec3 fvalue;
+
+void main() {
+ if (fvalue == vec3(1.0, 1.0, 1.0))
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == vec3(0.0, 0.0, 0.0))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-vec3-2" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-vec3-2" type="x-shader/x-fragment">
+precision mediump float;
+uniform bool bvalue;
+
+void main() {
+ vec3 fvalue = vec3(bvalue);
+
+ if (fvalue == vec3(1.0, 1.0, 1.0))
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == vec3(0.0, 0.0, 0.0))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-vec4-1" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+varying mediump vec4 fvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ fvalue = vec4(bvalue);
+}
+</script>
+<script id="fshader-vec4-1" type="x-shader/x-fragment">
+varying mediump vec4 fvalue;
+
+void main() {
+ if (fvalue == vec4(1.0, 1.0, 1.0, 1.0))
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == vec4(0.0, 0.0, 0.0, 0.0))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-vec4-2" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-vec4-2" type="x-shader/x-fragment">
+precision mediump float;
+uniform bool bvalue;
+
+void main() {
+ vec4 fvalue = vec4(bvalue);
+
+ if (fvalue == vec4(1.0, 1.0, 1.0, 1.0))
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (fvalue == vec4(0.0, 0.0, 0.0, 0.0))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+ <script type="application/javascript">
+"use strict";
+description("Verify int(bool) and float(bool) work correctly");
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ wtu.setupUnitQuad(gl);
+
+ var testCases = [
+ { vshader: "vshader-int1", fshader: "fshader-int1", desc: "vertex shader int" },
+ { vshader: "vshader-int2", fshader: "fshader-int2", desc: "fragment shader int" },
+ { vshader: "vshader-float1", fshader: "fshader-float1", desc: "vertex shader float" },
+ { vshader: "vshader-float2", fshader: "fshader-float2", desc: "fragment shader float" },
+ { vshader: "vshader-vec2-1", fshader: "fshader-vec2-1", desc: "vertex shader vec2" },
+ { vshader: "vshader-vec2-2", fshader: "fshader-vec2-2", desc: "fragment shader vec2" },
+ { vshader: "vshader-vec3-1", fshader: "fshader-vec3-1", desc: "vertex shader vec3" },
+ { vshader: "vshader-vec3-2", fshader: "fshader-vec3-2", desc: "fragment shader vec3" },
+ { vshader: "vshader-vec4-1", fshader: "fshader-vec4-1", desc: "vertex shader vec4" },
+ { vshader: "vshader-vec4-2", fshader: "fshader-vec4-2", desc: "fragment shader vec4" },
+ ];
+
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ var test = testCases[idx];
+
+ debug("");
+ var program = wtu.setupProgram(gl, [test.vshader, test.fshader], ["aPosition"]);
+ if (!program) {
+ testFailed("Fail to set up program");
+ } else {
+ var uniformLoc = gl.getUniformLocation(program, 'bvalue');
+ debug("Testing " + test.desc + " with false");
+ gl.uniform1i(uniformLoc, 0);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ debug("Testing " + test.desc + " with true");
+ gl.uniform1i(uniformLoc, 1);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255]);
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from testing");
+ }
+ }
+};
+
+test();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/character-set.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/character-set.html
new file mode 100644
index 0000000000..6d6fca5f89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/character-set.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Character Set</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+// See http://crbug.com/1108588 for original failing case.
+// Check "OpenGL Registry The OpenGL ES Shading Language"
+// Section 3.2 Character Sets For more info
+description("This test checks character set validation for glsl.");
+
+debug("");
+debug("Canvas.getContext");
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext("canvas");
+let consoleDiv = document.getElementById("console");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking shader character set validation and compilation");
+
+ runTest();
+}
+
+function testShaderSource(shaderSource, msg) {
+ if (!quietMode()) {
+ wtu.addShaderSource(consoleDiv, "test fragment shader", shaderSource);
+ }
+
+ let shader = gl.createShader(gl.FRAGMENT_SHADER);
+ if (shader == null) {
+ testFailed("*** Error: unable to create shader '" + shaderSource + "'");
+ return;
+ }
+
+ gl.shaderSource(shader, shaderSource);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, msg);
+}
+
+function MUST(ifTruthy) {
+ return ifTruthy ? 'MUST' : 'MUST NOT';
+}
+
+function runTest() {
+
+ const BAD_STRINGS = [
+ '$',
+ '"',
+ '一些注释',
+ '#line 42 "foo.glsl"',
+ ];
+ const TESTS = [
+ ['in identifier', s => s, false],
+ ['in comment', s => `// ${s}`, true, true],
+ ['in ifdef-out', s => `#if 0 \n${s} \n#endif`, true],
+ ['in ifdef-out #preproc', s => `#if 0 \n#${s} \n#endif`, true],
+ ['in #preproc', s => `#${s}`, false],
+ ['in comment after #define', s => `#define TEST // ${s}`, true], // Regression test for crbug.com/940865
+ ];
+
+ const glsl_tests = [];
+
+ for (const s of BAD_STRINGS) {
+ for (const [where, template, validCompile] of TESTS) {
+ const st = template(s);
+ const src = `
+precision mediump float;
+${st}
+void main() {
+ gl_FragColor = vec4(1, 0, 0, 1);
+}`.trim();
+
+ testShaderSource(src, `shaderSource allows Out-of-charset string '${s}' ${where} until compilation.`);
+
+ glsl_tests.push(
+ {
+ fShaderSource: src,
+ fShaderSuccess: validCompile,
+ linkSuccess: validCompile,
+ passMsg: `Out-of-charset string '${s}' ${where} ${MUST(validCompile)} compile.`
+ }
+ );
+ }
+ }
+
+ GLSLConformanceTester.runTests(glsl_tests);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compare-loop-index-to-uniform.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compare-loop-index-to-uniform.html
new file mode 100644
index 0000000000..a96da7fea9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compare-loop-index-to-uniform.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver bug - Comparing loop index against uniform in a fragment shader should work</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform int uCount;
+
+void main() {
+ float a = 0.0;
+ for (int i = 0; i < 5; ++i) {
+ if (i < uCount) {
+ a += 0.2;
+ }
+ }
+ gl_FragColor = vec4(1.0 - a, a, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Comparing loop index to an uniform in a fragment shader should work.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Compare a loop index to an uniform',
+ uniforms: [{name: "uCount", functionName: "uniform1i", value: 5}]
+}
+]);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/complex-glsl-does-not-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/complex-glsl-does-not-crash.html
new file mode 100644
index 0000000000..7b324def84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/complex-glsl-does-not-crash.html
@@ -0,0 +1,191 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver Bug - complex glsl should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-vertex">
+precision mediump float;
+varying vec4 v_varying;
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="vshaderArrayTest" type="x-shader/x-vertex">
+attribute vec4 a_position;
+varying vec4 v_varying;
+uniform $(type) u_uniform[$(numTestType)];
+void main()
+{
+ v_varying = $(code);
+ gl_Position = a_position;
+}
+</script>
+<script id="fshaderArrayTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform $(type) u_uniform[$(numTestType)];
+void main()
+{
+ gl_FragColor = $(code);
+}
+</script>
+<script id="vshaderUniformTest" type="x-shader/x-fragment">
+attribute vec4 a_position;
+varying vec4 v_varying;
+$(uniforms)
+void main()
+{
+ v_varying = $(code);
+ gl_Position = a_position;
+}
+</script>
+<script id="fshaderUniformTest" type="x-shader/x-fragment">
+precision mediump float;
+$(uniforms)
+void main()
+{
+ gl_FragColor = $(code);
+}
+</script>
+<script>
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var uniformTypes = [
+ { type: "bool", componentsPerRow: 1, rows: 1, code: "vec4(u_uniform$(id)$(index), 0, 0, 0)", },
+ { type: "float", componentsPerRow: 1, rows: 1, code: "vec4(u_uniform$(id)$(index), 0, 0, 0)", },
+ { type: "int", componentsPerRow: 1, rows: 1, code: "vec4(u_uniform$(id)$(index), 0, 0, 0)", },
+ { type: "vec2", componentsPerRow: 2, rows: 1, code: "vec4(u_uniform$(id)$(index), 0, 0)", },
+ { type: "ivec2", componentsPerRow: 2, rows: 1, code: "vec4(u_uniform$(id)$(index), 0, 0)", },
+ { type: "bvec2", componentsPerRow: 2, rows: 1, code: "vec4(u_uniform$(id)$(index), 0, 0)", },
+ { type: "vec3", componentsPerRow: 3, rows: 1, code: "vec4(u_uniform$(id)$(index), 0)", },
+ { type: "ivec3", componentsPerRow: 3, rows: 1, code: "vec4(u_uniform$(id)$(index), 0)", },
+ { type: "bvec3", componentsPerRow: 3, rows: 1, code: "vec4(u_uniform$(id)$(index), 0)", },
+ { type: "vec4", componentsPerRow: 4, rows: 1, code: "vec4(u_uniform$(id)$(index))", },
+ { type: "ivec4", componentsPerRow: 4, rows: 1, code: "vec4(u_uniform$(id)$(index))", },
+ { type: "bvec4", componentsPerRow: 4, rows: 1, code: "vec4(u_uniform$(id)$(index))", },
+// Yes, the spec says mat2 takes 4 columns, 2 rows.
+ { type: "mat2", componentsPerRow: 4, rows: 2, code: "vec4(u_uniform$(id)$(index)[0], 0, 0)", },
+ { type: "mat3", componentsPerRow: 3, rows: 3, code: "vec4(u_uniform$(id)$(index)[0], 0)", },
+ { type: "mat4", componentsPerRow: 4, rows: 4, code: "vec4(u_uniform$(id)$(index)[0])", },
+// Samplers generally have more restictive limits.
+// { type: "sampler2D", componentsPerRow: 1, rows: 1, code: "vec4(texture2D(u_uniform[$(index)], vec2(0, 0)))", },
+// { type: "samplerCube", componentsPerRow: 1, rows: 1, code: "vec4(textureCube(u_uniform[$(index)], vec3(0, 0, 0)))", },
+];
+
+var vBaseSource = wtu.getScript("vshader");
+var fBaseSource = wtu.getScript("fshader");
+var vArrayTestSource = wtu.getScript("vshaderArrayTest");
+var fArrayTestSource = wtu.getScript("fshaderArrayTest");
+var vUniformTestSource = wtu.getScript("vshaderUniformTest");
+var fUniformTestSource = wtu.getScript("fshaderUniformTest");
+
+var tests = [];
+var shaderTypes = [
+ { type: "vertex",
+ // For tests that expect failure which shader might fail.
+ vertExpectation: false,
+ fragExpectation: true,
+ vertArrayTest: vArrayTestSource,
+ fragArrayTest: fBaseSource,
+ vertUniformTest: vUniformTestSource,
+ fragUniformTest: fBaseSource,
+ maxVectors: gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS),
+ minVectors: 128, // GLSL ES 1.0.17 Appendix A.7,
+ },
+ { type: "fragment",
+ // For tests that expect failure which shader might fail.
+ vertExpectation: true,
+ fragExpectation: false,
+ vertArrayTest: vBaseSource,
+ fragArrayTest: fArrayTestSource,
+ vertUniformTest: vBaseSource,
+ fragUniformTest: fUniformTestSource,
+ maxVectors: gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS),
+ minVectors: 16, // GLSL ES 1.0.17 Appendix A.7,
+ },
+];
+for (var ss = 0; ss < shaderTypes.length; ++ss) {
+ var shaderType = shaderTypes[ss];
+ debug("max " + shaderType.type + ": " + shaderType.maxVectors);
+ for (var ii = 0; ii < uniformTypes.length; ++ii) {
+ var info = uniformTypes[ii];
+ wtu.log("checking: " + info.type);
+ // Compute the maximum amount of this type allowed in a single array.
+ var numVars = Math.floor(shaderType.maxVectors / info.rows);
+ // Compute the minimum required to work in a single array.
+ var minVars = Math.floor(shaderType.minVectors / info.rows);
+ // Compute the maximum allowed as single elements
+ var numPerRow = Math.floor(4 / info.componentsPerRow);
+ var numMax = Math.floor(shaderType.maxVectors * numPerRow / info.rows);
+
+ // Test array[max] of the type
+ // Note: We can't test for success or failer as actual GL drivers are only required to be able to
+ // do the minimum number. After that it can fail for any reason.
+ var code = wtu.replaceParams(info.code, {id: "", index: "[" + (numVars - 1) + "]"});
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: numVars, code: code}, info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: numVars, code: code}, info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: true,
+ passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + numVars + " elements (the maximum)",
+ });
+
+ var generateCode = function(numVars) {
+ var uniforms = [];
+ var codes = [];
+ for (var uu = 0; uu < numVars; ++uu) {
+ uniforms.push(" uniform " + info.type + " u_uniform" + uu + ";");
+ codes.push(wtu.replaceParams(info.code, {id: uu, index: ""}));
+ }
+ return {
+ uniforms: uniforms.join("\n"),
+ code: codes.join(" + \n "),
+ };
+ };
+
+ // Test max uniforms of type.
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(numMax), info),
+ vShaderSuccess: shaderType.vertExpectation,
+ fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(numMax), info),
+ fShaderSuccess: shaderType.fragExpectation,
+ linkSuccess: true,
+ ignoreResults: true,
+ passMsg: shaderType.type + " shader with " + (numMax) + " uniforms of " + info.type,
+ });
+ }
+}
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compound-assignment-type-combination.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compound-assignment-type-combination.html
new file mode 100644
index 0000000000..7b61946b35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/compound-assignment-type-combination.html
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Result type should match the l-value type in compound assignment</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/tests/compound-assignment-type-combination.js"></script>
+</head>
+<body onload="runTest(1)">
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+description();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-in-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-in-loop.html
new file mode 100644
index 0000000000..1c4709dd10
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-in-loop.html
@@ -0,0 +1,142 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Conditional discard in loop issue</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+
+<body>
+<canvas id="output" style="border: none;" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+// Inputs
+attribute vec4 a_position;
+attribute vec2 a_tex_coords;
+
+// Output
+varying vec2 v_tex_coords;
+
+void main(void) {
+ v_tex_coords = a_tex_coords;
+ gl_Position = a_position;
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+// Constants
+const float TEXEL_COUNT_V = 256.0;
+const float TEXEL_HEIGHT = 1.0 / TEXEL_COUNT_V;
+const float SEP_IX = TEXEL_COUNT_V / 2.0;
+
+const vec4 GREEN = vec4(0.0, 1.0, 0.0, 1.0);
+const vec4 BLUE = vec4(0.0, 0.0, 1.0, 1.0);
+
+// Input
+varying vec2 v_tex_coords;
+
+uniform sampler2D u_data;
+
+// Without this function or directly returning the data, the issue does not occur
+mediump vec4 UnpackData(in vec4 inData) {
+ float s = inData.x;
+ // Note s is always 0
+ // mod(0, 1) = 0
+ // So return value = (0, 0, -1, 0)
+ return vec4(0.0, 0.0, mod(s, 1.0) - 1.0, 0.0);
+
+ // Comment out the line above and uncomment the line below and the test succeeds on angle-dx11
+ // return vec4(0.0, 0.0, -1.0, 0.0);
+}
+
+void main(void) {
+ // Set initial color
+ gl_FragColor = BLUE;
+
+ if (gl_FragCoord.y <= SEP_IX) {
+ mediump vec2 addr = vec2(v_tex_coords.x, TEXEL_HEIGHT);
+
+ for (float e_ix = 0.0; e_ix < TEXEL_COUNT_V; ++e_ix) {
+ vec4 entry = texture2D(u_data, addr);
+ mediump vec4 unpack = UnpackData(entry);
+
+ // Buffer is filled with 0, unpack is always (0, 0, -1, 0)
+ // So discard is always triggered
+ if (unpack.z == -1.0) {
+ discard;
+ }
+
+ addr.y += unpack.z * TEXEL_HEIGHT;
+ }
+ // If discard is not triggered the output color is blue
+ }
+ else {
+ gl_FragColor = GREEN;
+ }
+}
+</script>
+
+
+<script>
+"use strict";
+
+description();
+debug("");
+debug("If the code is executed correctly, the upper half of the viewport will be green, the lower half will be red.");
+debug("This is a conformance suite test for the issue reported here : https://code.google.com/p/angleproject/issues/detail?id=706");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("output");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+
+ // Create texture filled with zero's
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ wtu.fillTexture(gl, tex, 256, 256, [0, 0, 0, 0]);
+
+ // Clear complete viewport to red
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var attribBuffers = wtu.setupUnitQuad(gl, 0, 1);
+ var program = wtu.setupProgram(gl, ["shader-vs", "shader-fs"], ["a_position", "a_tex_coords"], [0, 1], true);
+
+ // Bind texture
+ var uniformMap = wtu.getUniformMap(gl, program);
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.uniform1i(uniformMap.u_data.location, 0);
+
+ // Draw
+ wtu.drawUnitQuad(gl);
+
+ // Verify output
+ wtu.checkCanvasRect(gl, 0, 0, 256, 128, [ 255, 0, 0, 255 ], "should be red", 1);
+ wtu.checkCanvasRect(gl, 0, 128, 256, 128, [ 0, 255, 0, 255 ], "should be green", 1);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-optimization.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-optimization.html
new file mode 100644
index 0000000000..1c3b1bb6fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-discard-optimization.html
@@ -0,0 +1,117 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!-- author: Bill Baxter (wbaxter at google.com) -->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ANGLE WebGL Shader Conditionals Repro</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+
+<body>
+<canvas id="repro" style="border: none;" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+attribute vec2 pos;
+varying mediump float varA;
+void main(void) {
+ varA = 0.;
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+precision mediump float;
+varying float varA;
+void main(void) {
+ if (varA < -1. || (varA < -1. && varA > 1.)) {
+ discard;
+ }
+ gl_FragColor = vec4(0, 1, 0, 1) + 2. * varA * 2.;
+}
+</script>
+
+<script id="shader-fs-mutable" type="x-shader/x-fragment">
+precision mediump float;
+varying float varA;
+void main(void) {
+ float b = varA;
+ if (varA < (b -= 1.) || (varA < b && varA > (b += 2.))) {
+ discard;
+ }
+ gl_FragColor = vec4(0, 1, 0, 1) + 2. * varA * 2.;
+}
+</script>
+<script id="shader-fs-unfolded" type="x-shader/x-fragment">
+precision mediump float;
+varying float varA;
+void main(void) {
+ bool s1 = varA < -1.;
+ if (!s1) {
+ bool s2 = varA < -1.;
+ if (s2) {
+ s2 = varA > 1.;
+ }
+ s1 = s2;
+ }
+ if (s1) {
+ discard;
+ }
+ gl_FragColor = vec4(0, 1, 0, 1) + 2. * varA * 2.;
+}
+</script>
+<script>
+"use strict";
+
+description();
+debug("");
+debug("If things are working correctly, then there will be a green square.");
+debug("Otherwise it will be a black void.");
+debug("This is a repro for an issue seen on the D3D9 ANGLE implementation of WebGL on Chrome in a shader with a conditional discard, where the conditional is of the form (a || (b && c)).");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("repro");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ wtu.setupUnitQuad(gl);
+
+ debug("");
+ debug("Testing shader with conditional discard");
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ var program = wtu.setupProgram(gl, ["shader-vs", "shader-fs"], ["pos"], undefined, true);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 128, 128, 128, 128, [ 0, 255, 0, 255 ], "should be green", 1);
+
+ debug("");
+ debug("Testing conditional discard with side-effects in conditions");
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ var programMutable = wtu.setupProgram(gl, ["shader-vs", "shader-fs-mutable"], ["pos"], undefined, true);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 128, 128, 128, 128, [ 0, 255, 0, 255 ], "should be green", 1);
+
+ debug("");
+ debug("Testing conditional discard with unfolded condition logic");
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ var programMutable = wtu.setupProgram(gl, ["shader-vs", "shader-fs-unfolded"], ["pos"], undefined, true);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 128, 128, 128, 128, [ 0, 255, 0, 255 ], "should be green", 1);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-texture-fetch.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-texture-fetch.html
new file mode 100644
index 0000000000..f382b8c800
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/conditional-texture-fetch.html
@@ -0,0 +1,130 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Conditional texture fetch test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<canvas id="output" style="border: none;" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshaderConditionalTextureFetch" type="x-shader/x-vertex">
+attribute vec2 a_position;
+attribute vec4 a_canvasTileColor;
+attribute vec2 a_texCoord;
+varying vec2 texCoord;
+varying vec4 canvasTileColor;
+void main()
+{
+ canvasTileColor = a_canvasTileColor;
+ texCoord = a_texCoord;
+ gl_Position = vec4(a_position, 0.0, 1.0);
+}
+</script>
+<script id="fshaderConditionalTextureFetch" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 canvasTileColor;
+uniform bool hasTexture;
+uniform sampler2D canvasTileTexture;
+varying vec2 texCoord;
+uniform vec4 uvRect;
+void main()
+{
+ vec4 finalColor = canvasTileColor;
+ if (hasTexture) {
+ vec2 clampedUV = clamp(texCoord.xy, uvRect.xy, uvRect.zw);
+ finalColor = texture2D(canvasTileTexture, clampedUV);
+ }
+ gl_FragColor = finalColor;
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+debug("If the test passes correctly the viewport will be green.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("output");
+var gl = wtu.create3DContext(canvas);
+
+var createGreenTexture = function() {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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);
+ wtu.fillTexture(gl, texture, 1, 1, [0, 255, 0, 255]);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ return texture;
+};
+
+var test = function(greenTexture) {
+ // This is a reduced test case for a problem reported by Figma.
+ // Program compilation produces the following warning/error on ANGLE's
+ // D3D9 backend:
+ // [WARNING:angle_platform_impl.cc(51)] : rx::HLSLCompiler::compileToBinary(228): C:\fakepath(26,12): error X6077: texld/texldb/texldp/dsx/dsy instructions with r# as source cannot be used inside dynamic conditional 'if' blocks, dynamic conditional subroutine calls, or loop/rep with break*.
+ //
+ // All of the operations in the shader -- including the clamping of the
+ // texture coordinates -- seem to be needed in order to provoke this
+ // error.
+ //
+ // However, this doesn't seem to produce incorrect rendering results.
+ var program = wtu.setupProgram(
+ gl,
+ ["vshaderConditionalTextureFetch",
+ "fshaderConditionalTextureFetch"],
+ ["a_position", "a_canvasTileColor", "a_texCoord"],
+ [0, 1, 2],
+ true);
+ if (!program) {
+ testFailed("Shader compilation/link failed");
+ } else {
+ // Set up buffers
+ wtu.setupUnitQuad(gl, 0, 2);
+
+ // Set up constant color (red)
+ gl.vertexAttrib4f(1, 1, 0, 0, 1);
+
+ var uniformMap = wtu.getUniformMap(gl, program);
+
+ // Use texturing
+ gl.uniform1i(uniformMap["hasTexture"].location, 1);
+
+ // Bind texture
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, greenTexture);
+ gl.uniform1i(uniformMap["canvasTileTexture"].location, 0);
+
+ // Set up (essentially no-op) clamp rectangle
+ gl.uniform4f(uniformMap["uvRect"].location, 0, 0, 0.25, 0.25);
+
+ // Draw
+ wtu.clearAndDrawUnitQuad(gl);
+
+ // Verify output
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 1);
+ }
+};
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ var tex = createGreenTexture();
+ test(tex);
+}
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/constant-precision-qualifier.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/constant-precision-qualifier.html
new file mode 100644
index 0000000000..d3628862bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/constant-precision-qualifier.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Bug - the precision qualifier of a constant variable should affect the precision of a consuming operation</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+// It is assumed that uTest is set to 0. It's here to make the expression not constant.
+uniform mediump float uTest;
+
+void main() {
+ // exact representation of 4096.5 requires 13 bits of relative precision.
+ const highp float c = 4096.5;
+ mediump float a = 0.0;
+ // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
+ // Thus fract should also be evaluated at highp.
+ // See OpenGL ES Shading Language spec section 4.5.2.
+ // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
+ // (exceptions for operation precision are allowed for a small number of computationally
+ // intensive built-in functions, but it is reasonable to think that fract is not one of those).
+ // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
+ // or at IEEE half float precision, the result is 0.0.
+ a = fract(c + uTest);
+
+ // Multiply by 2.0 to make the color green.
+ gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
+}
+</script>
+<script id="fshaderNoConstants" type="x-shader/x-fragment">
+// This shader has the same functionality as the one above, but it doesn't contain
+// operations that can be constant folded at compile-time.
+// It's here to provide a point of comparison.
+uniform mediump float uTest;
+uniform highp float uTestHigh;
+
+void main() {
+ highp float c = 4096.5 + uTestHigh;
+ mediump float a = 0.0;
+ a = fract(c + uTest);
+ gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
+}
+</script>
+<script id="fshaderAllHighp" type="x-shader/x-fragment">
+// This shader has the same functionality as the one above, but it only uses highp.
+// It's here to provide a point of comparison.
+uniform highp float uTest;
+
+void main() {
+ highp float c = 4096.5 + uTest;
+ highp float a = 0.0;
+ a = fract(c + uTest);
+ gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+function test() {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext();
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+ if (gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision == 0) {
+ testPassed("highp precision not supported");
+ finishTest();
+ } else {
+ GLSLConformanceTester.runRenderTests([
+ {
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'The precision qualifier of a constant affects built-in function results',
+ uniforms: [{name: "uTest", functionName: "uniform1f", value: 0}]
+ },
+ {
+ fShaderId: 'fshaderNoConstants',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'The precision qualifier of a variable affects built-in function results',
+ uniforms: [{name: "uTest", functionName: "uniform1f", value: 0},
+ {name: "uTestHigh", functionName: "uniform1f", value: 0}]
+ },
+ {
+ fShaderId: 'fshaderAllHighp',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'All variables are qualified as highp',
+ uniforms: [{name: "uTest", functionName: "uniform1f", value: 0}]
+ },
+ ]);
+ }
+};
+
+test();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/essl3-shaders-with-webgl1.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/essl3-shaders-with-webgl1.html
new file mode 100644
index 0000000000..47e58c5c92
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/essl3-shaders-with-webgl1.html
@@ -0,0 +1,138 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Browser bug - WebGL 1 context should not accept OpenGL ES 3 shading language shaders</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="ES1VertexShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="ES1FragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<!-- Note that the version directive should be on the very first line in ESSL 3, see ESSL 3 section 3.3 -->
+<script id="ES3VertexShader" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+in vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="ES3FragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+
+void main() {
+ my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="emptyES3FragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+void main() {
+}
+</script>
+<script id="vertexShaderWithInQualifier" type="x-shader/x-vertex">
+precision mediump float;
+in vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="fragmentShaderWithOutQualifier" type="x-shader/x-fragment">
+precision mediump float;
+out vec4 my_FragColor;
+
+void main() {
+ my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("OpenGL ES 3 shading language shaders should not be accepted by WebGL 1.");
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "ES3VertexShader",
+ vShaderSuccess: false,
+ fShaderId: "ES1FragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "OpenGL ES 3 shading language vertex shader with an in variable should not be accepted by WebGL 1."
+ },
+ {
+ vShaderId: "ES1VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "ES3FragmentShader",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "OpenGL ES 3 shading language fragment shader with an out variable should not be accepted by WebGL 1."
+ },
+ {
+ vShaderId: "ES1VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "emptyES3FragmentShader",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "OpenGL ES 3 shading language fragment shader with an empty body should not be accepted by WebGL 1."
+ },
+ {
+ vShaderId: "ES3VertexShader",
+ vShaderSuccess: false,
+ fShaderId: "ES3FragmentShader",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "OpenGL ES 3 shading language shaders should not be linked by WebGL 1."
+ },
+ {
+ vShaderId: "ES3VertexShader",
+ vShaderSuccess: false,
+ fShaderId: "emptyES3FragmentShader",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "OpenGL ES 3 shading language shaders including fragment shader with empty body should not be linked by WebGL 1."
+ },
+ {
+ vShaderId: "vertexShaderWithInQualifier",
+ vShaderSuccess: false,
+ fShaderId: "ES1FragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Vertex shader with an in qualifier on a global variable should not be accepted by WebGL 1."
+ },
+ {
+ vShaderId: "ES1VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderWithOutQualifier",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Fragment shader with an out qualifier on a global variable should not be accepted by WebGL 1."
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floor-div-cos-should-not-truncate.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floor-div-cos-should-not-truncate.html
new file mode 100644
index 0000000000..69a019aa1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floor-div-cos-should-not-truncate.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Floor + divide + cosine should not truncate intermediate results.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">
+precision highp float;
+
+attribute vec3 pos;
+
+// This divisor must be greater than the 32-bit floating point
+// representation of 1e6 / (2 * pi) to repro.
+const float magic = 159154.953125;
+
+void main(void) {
+ // This floor must be present to repro.
+ float x = floor(pos.x);
+
+ // This divide and cosine must be present to repro.
+ x = cos(x / magic);
+
+ // If the GPU truncated 'x / magic' to 0, then 'cos(x / magic)' will produce
+ // 1.0, the green square will be moved offscreen, and the red background
+ // will be visible.
+ gl_Position.x = pos.y + x * 2.0;
+ gl_Position.y = pos.z;
+ gl_Position.z = 0.0;
+ gl_Position.w = 1.0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision highp float;
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+
+<script type="application/javascript">
+"use strict";
+description("Flooring a number, then dividing by a large number, then computing the cosine of that should not truncate the intermediate values.");
+debug("Regression test for <a href='https://code.google.com/p/angleproject/issues/detail?id=1179'>https://code.google.com/p/angleproject/issues/detail?id=1179</a>");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos'], undefined, true);
+
+gl.clearColor(1, 0, 0, 1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+
+var magic = 159154.953125;
+var x = (Math.PI / 2.0) * magic;
+var data = [
+ x, -1, -1,
+ x, 1, -1,
+ x, 1, 1,
+ x, -1, -1,
+ x, 1, 1,
+ x, -1, 1
+];
+
+gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 12, 0);
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+wtu.checkCanvas(gl, [0,255,0,255], "should be 0,255,0,255");
+finishTest();
+</script>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floored-division-accuracy.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floored-division-accuracy.html
new file mode 100644
index 0000000000..6986344d3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/floored-division-accuracy.html
@@ -0,0 +1,69 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!-- author: Bill Baxter (wbaxter at google.com) -->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Floored Division Accuracy Bug</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+uniform float divisor;
+varying vec4 vColor;
+void main(void) {
+ gl_Position = vPosition;
+ float index = 9.0;
+ // Floating point operations don't have any guaranteed precision, but they
+ // should at least be accurate to 1 part in 10^5.
+ float value = floor((index / divisor) * 1.00001);
+ vColor = (value == 3.) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 vColor;
+void main(void) {
+ gl_FragColor = vColor;
+}
+</script>
+<script>
+"use strict";
+description();
+
+debug("");
+// Reproduces bug seen on Mac OS X with AMD Radeon HD 6490 GPU
+debug("If things are working correctly, then the square will be green.");
+debug("If your card thinks floor(9. / 3.) is not 3 to within 1 part in 10^5, ");
+debug("then the square will be red.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ vShaderId: 'shader-vs',
+ vShaderSuccess: true,
+ fShaderId: 'shader-fs',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test that floor(9. / 3.) is 3 to within 1 part in 10^5',
+ uniforms: [{name: "divisor", functionName: "uniform1f", value: 3}]
+}
+]);
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/fragcoord-linking-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/fragcoord-linking-bug.html
new file mode 100644
index 0000000000..f22632c0a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/fragcoord-linking-bug.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL compiler bug referencing gl_FragCoord</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<!-- These shaders were extracted from Skia's GPU accelerated backend "Ganesh". -->
+<script id="shader-vs" type="x-shader/x-vertex">
+uniform mat3 uViewM;
+uniform mat3 uStageMatrix_Stage1;
+uniform vec4 urtAdjustment;
+attribute vec2 aPosition;
+attribute vec4 aColor;
+varying vec4 vColor;
+varying vec2 vMatrixCoord_Stage1;
+void main() {
+ vec3 pos3 = uViewM * vec3(aPosition, 1);
+ vColor = aColor;
+ { // Stage 0: XferEffect
+ }
+ vMatrixCoord_Stage1 = (uStageMatrix_Stage1 * vec3(aPosition, 1)).xy;
+ { // Stage 1: Texture
+ }
+ gl_Position = vec4(dot(pos3.xz, urtAdjustment.xy), dot(pos3.yz, urtAdjustment.zw), 0, pos3.z);
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D uDstCopySampler;
+uniform vec2 uDstCopyUpperLeft;
+uniform vec2 uDstCopyCoordScale;
+uniform float uRTHeight;
+uniform sampler2D uSampler0_Stage1;
+varying vec4 vColor;
+varying vec2 vMatrixCoord_Stage1;
+void main() {
+ vec4 fragCoordYDown = vec4(gl_FragCoord.x, uRTHeight - gl_FragCoord.y, gl_FragCoord.zw);
+ // Read color from copy of the destination.
+ vec2 _dstTexCoord = (fragCoordYDown.xy - uDstCopyUpperLeft) * uDstCopyCoordScale;
+ _dstTexCoord.y = 1.0 - _dstTexCoord.y;
+ vec4 _dstColor = texture2D(uDstCopySampler, _dstTexCoord);
+
+ vec4 output_Stage0;
+ { // Stage 0: XferEffect
+ // SkXfermode::Mode: Multiply
+ output_Stage0.a = vColor.a + (1.0 - vColor.a) * _dstColor.a;
+ output_Stage0.rgb = (1.0 - vColor.a) * _dstColor.rgb + (1.0 - _dstColor.a) * vColor.rgb + vColor.rgb * _dstColor.rgb;
+ }
+ vec4 output_Stage1;
+ { // Stage 1: Texture
+ output_Stage1 = texture2D(uSampler0_Stage1, vMatrixCoord_Stage1);
+ }
+ gl_FragColor = ((output_Stage0 * output_Stage1) + ((vec4(1) - output_Stage1) * _dstColor));
+}
+</script>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description();
+debug("");
+debug('Verify shaders using gl_FragCoord z and w components compile and link correctly');
+debug('Regression test for Qualcomm bug ID CR649654');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ var program = wtu.setupProgram(gl, ["shader-vs", "shader-fs"], null, null, true);
+ if (program) {
+ testPassed("Program compiled and linked successfully");
+ } else {
+ testFailed("Program failed to compile and link");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/gl-fragcoord-multisampling-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/gl-fragcoord-multisampling-bug.html
new file mode 100644
index 0000000000..ef1184d49f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/gl-fragcoord-multisampling-bug.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>gl_FragCoord multisampling bug</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="canvasHolder"></div>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main() {
+ gl_Position = vec4(a_position.xy, 1.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ float depth = gl_FragCoord.z / gl_FragCoord.w;
+ gl_FragColor = vec4( 0.0, depth, 0.0, 1.0 );
+}
+</script>
+
+<script type="application/javascript">
+"use strict";
+description("gl_FragCoord multisampling bug");
+debug("Verifies gl_FragCoord z/w values are unaffected by multisampling.");
+debug('Regression test for <a href="https://github.com/mrdoob/three.js/issues/7769">Three.js Issue 7769</a>');
+var wtu = WebGLTestUtils;
+for (var ii = 0; ii < 2; ++ii) {
+ debug("Testing " + (ii > 0 ? "with" : "without") + " multisampling");
+ var canvas = document.createElement('canvas');
+ canvas.width = 256;
+ canvas.height = 256;
+ canvas.style.padding = "2px";
+ document.getElementById('canvasHolder').appendChild(canvas);
+ var options;
+ if (ii > 0) {
+ options = { antialias: true };
+ }
+ var gl = wtu.create3DContext(canvas, options);
+
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var attribBuffers = wtu.setupUnitQuad(gl, 0, 1);
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position'], [0], true);
+ if (!program) {
+ testFailed("Shader compilation/link failed");
+ } else {
+ // Draw
+ wtu.drawUnitQuad(gl);
+ // Verify output
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 3);
+ }
+}
+
+finishTest();
+</script>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/global-invariant-does-not-leak-across-shaders.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/global-invariant-does-not-leak-across-shaders.html
new file mode 100644
index 0000000000..b02622bb29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/global-invariant-does-not-leak-across-shaders.html
@@ -0,0 +1,77 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Global invariant does not leak across shaders</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="InvariantVertex" type="x-shader/x-vertex">
+#pragma STDGL invariant(all)
+
+void main()
+{
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="Fragment" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="VertexWithVarying" type="x-shader/x-vertex">
+varying vec2 testVarying;
+
+void main() {
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+ testVarying = vec2(0.0, 0.0);
+}
+</script>
+<script id="FragmentWithVarying" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 testVarying;
+
+void main()
+{
+ gl_FragColor = vec4(testVarying, 0.0, 1.0);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("The use of the global invariant pragma in one shader must not affect other shaders.");
+
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "InvariantVertex",
+ vShaderSuccess: true,
+ fShaderId: "Fragment",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Shaders using global invariant pragma should compile and link."
+ },
+ {
+ vShaderId: "VertexWithVarying",
+ vShaderSuccess: true,
+ fShaderId: "FragmentWithVarying",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Shaders not using global invariant pragma should compile and link."
+ },
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/if-return-and-elseif.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/if-return-and-elseif.html
new file mode 100644
index 0000000000..4e88ae83be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/if-return-and-elseif.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>If with return and else if in fragment shader</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 pos;
+varying vec2 vPos;
+void main()
+{
+ gl_Position = pos;
+ vPos = pos.xy;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec2 vPos;
+void main()
+{
+ if(vPos.x < 1.0) // This colors the whole canvas green
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ return;
+ }
+ else if(vPos.x < 1.1) // This should have no effect
+ {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+}
+
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+// Minimal test case based on report at http://anglebug.com/2325
+
+GLSLConformanceTester.runRenderTests([
+{
+ vShaderId: 'vshader',
+ vShaderSuccess: true,
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "If and else if in fragment shader"
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html
new file mode 100644
index 0000000000..77edd0ec3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Function in parameter passed as an inout argument and a global variable with the same name</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderParameters" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec3 u_zero;
+vec3 p;
+void G(inout vec3 q) {
+ p += q;
+}
+void F(in vec3 p) {
+ G(p);
+}
+void main(){
+ F(u_zero + vec3(0.0, 1.0, 0.0));
+ gl_FragColor = vec4(p, 1.0);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+// This is intended to test an issue seen on NVIDIA OpenGL drivers (at least up to version 388.59).
+// http://crbug.com/792210
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderParameters',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Function in parameter passed as an inout argument and a global variable with the same name"
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/init-array-with-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/init-array-with-loop.html
new file mode 100644
index 0000000000..2bd24765bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/init-array-with-loop.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Initializing an array with a loop test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderInitLoop" type="x-shader/x-fragment">
+precision mediump float;
+
+void initGlobals();
+
+uniform vec4 in0;
+vec4 out0;
+
+float func(float a[4]) {
+ a[0] = -1.0;
+ return a[0];
+}
+
+float arr[4];
+
+bool isOk(vec4 a) {
+ vec4 ref = -(in0 + 1.0);
+ if (abs(a.x - ref.x) < 0.05 && abs(a.y - ref.y) < 0.05 && abs(a.z - ref.z) < 0.05 && abs(a.w - ref.w) < 0.05)
+ {
+ return true;
+ }
+ return false;
+}
+
+void main() {
+ initGlobals();
+ arr[0] = in0.x + 1.0;
+ arr[1] = in0.y + 1.0;
+ arr[2] = in0.z + 1.0;
+ arr[3] = in0.w + 1.0;
+ mediump float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ if (isOk(out0))
+ {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ }
+ else
+ {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+}
+
+void initGlobals() {
+ out0 = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 4; ++i)
+ {
+ arr[i] = 0.0;
+ }
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderInitLoop',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Initialize a global array using a for loop"
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/invariant-does-not-leak-across-shaders.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/invariant-does-not-leak-across-shaders.html
new file mode 100644
index 0000000000..d203731012
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/invariant-does-not-leak-across-shaders.html
@@ -0,0 +1,74 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Invariant does not leak across shaders</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="InvariantVertex" type="x-shader/x-vertex">
+varying vec4 v_varying;
+invariant v_varying;
+
+void main()
+{
+ gl_Position = v_varying;
+}
+</script>
+<script id="InvariantFragment" type="x-shader/x-fragment">
+precision mediump float;
+invariant varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="VertexWithVarying" type="x-shader/x-vertex">
+varying vec4 v_varying;
+
+void main() {
+ gl_Position = v_varying;
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("The use of the invariant qualifier in one shader must not affect other shaders.");
+
+debug("");
+debug("This is a deliberate subset of conformance/glsl/misc/shaders-with-invariance.html.");
+debug("Compared with the original tests, order of the tests is different.");
+debug("This test covers an ANGLE bug. See crbug.com/634813.");
+
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "InvariantVertex",
+ vShaderSuccess: true,
+ fShaderId: "InvariantFragment",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Shaders using invariant qualifier should compile and link."
+ },
+ {
+ vShaderId: "VertexWithVarying",
+ vShaderSuccess: true,
+ fShaderId: "InvariantFragment",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with variant varying and fragment shader with invariant varying must fail"
+ },
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/logic-inside-block-without-braces.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/logic-inside-block-without-braces.html
new file mode 100644
index 0000000000..2bbac4dbd0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/logic-inside-block-without-braces.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Short-circuiting logic operator with side effects inside if statement without braces should work</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderIf" type="x-shader/x-fragment">
+precision mediump float;
+uniform bool uFalse;
+
+float wrong = 0.0;
+
+bool foo() {
+ wrong += 1.0;
+ return !uFalse;
+}
+
+bool bar() {
+ return !uFalse;
+}
+
+void main() {
+ // No braces here - that can affect whether the contents of the if get parsed as a block or a statement.
+ if (uFalse)
+ foo() && bar();
+ gl_FragColor = vec4(0.0, 1.0 - wrong, 0.0, 1.0);
+}
+</script>
+<script id="fshaderFor" type="x-shader/x-fragment">
+precision mediump float;
+
+float wrong = 0.0;
+
+bool foo() {
+ wrong += 1.0;
+ return false;
+}
+
+bool bar() {
+ return false;
+}
+
+void main() {
+ // No braces here - that can affect whether the contents of the for get parsed as a block or a statement.
+ for (int i = 0; i < 0; ++i)
+ foo() && bar();
+ gl_FragColor = vec4(0.0, 1.0 - wrong, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Short-circuiting logic operator with side effects inside if/for statement without braces should work.");
+debug("");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderIf',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Short-circuiting operator inside if statement without braces',
+ uniforms: [{name: "uFalse", functionName: "uniform1i", value: 0}]
+},
+{
+ fShaderId: 'fshaderFor',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Short-circuiting operator inside for statement without braces'
+}
+]);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/long-expressions-should-not-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/long-expressions-should-not-crash.html
new file mode 100644
index 0000000000..eaf0509b23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/long-expressions-should-not-crash.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver Bug - long experssions should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<canvas id="example" width="40" height="40"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+void main(){
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="vshaderUniformTest" type="x-shader/x-vertex">
+uniform vec4 u_uniform;
+void main(){
+ gl_Position =
+ $(code)
+ vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(0, 0, 0, 0);
+}
+</script>
+<script id="fshaderUniformTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_uniform;
+void main()
+{
+ gl_FragColor =
+ $(code)
+ vec4(0, 0, 0, 0);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+var vUniformTestSource = wtu.getScript("vshaderUniformTest");
+var fUniformTestSource = wtu.getScript("fshaderUniformTest");
+
+var tests = [
+];
+var counts = [
+ { count:10,
+ mustPass: true,
+ },
+ { count:100,
+ mustPass: true,
+ },
+ { count: 1000,
+ mustPass: false,
+ },
+ { count: 10000,
+ mustPass: false,
+ },
+];
+var operatorSets = [
+ ["+", "-", "/", "*"],
+ ["+"],
+ ["-"],
+];
+counts.forEach(function(info) {
+ operatorSets.forEach(function(operators) {
+ var generateCode = function(numVars) {
+ var codes = [];
+ for (var uu = 0; uu < numVars; ++uu) {
+ codes.push("u_uniform " + operators[uu % operators.length]);
+ }
+ return {
+ code: codes.join("\n "),
+ };
+ };
+
+ var subs = generateCode(info.count);
+ tests.push({
+ vShaderId: "vshader",
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fUniformTestSource, subs),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with " + info.count + " [" + operators + "] operators in expression in multiple lines",
+ });
+ tests.push({
+ vShaderSource: wtu.replaceParams(vUniformTestSource, subs),
+ vShaderSuccess: true,
+ fShaderId: "fshader",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with " + info.count + " [" + operators + "] operators in expression in multiple lines",
+ });
+ subs.code = subs.code.replace(/\n /g, "")
+ tests.push({
+ vShaderId: "vshader",
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fUniformTestSource, subs),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with " + info.count + " [" + operators + "] operators in expression in one line",
+ });
+ tests.push({
+ vShaderSource: wtu.replaceParams(vUniformTestSource, subs),
+ vShaderSuccess: true,
+ fShaderId: "fshader",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with " + info.count + " [" + operators + "] operators in expression in one line",
+ });
+ });
+});
+GLSLConformanceTester.runTests(tests);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/loop-if-loop-gradient.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/loop-if-loop-gradient.html
new file mode 100644
index 0000000000..914604ad07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/loop-if-loop-gradient.html
@@ -0,0 +1,75 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Gradient loop in if in loop crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>
+precision highp float;
+void main() {
+gl_Position = vec4( 1.0, 1.0, 1.0, 1.0 );
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>
+precision mediump float;
+uniform lowp sampler2D iChannel0;
+
+void main(){
+ highp float c;
+ for (mediump float i = 0.0; i <= 1.0; i++) {
+ if (gl_FragCoord.x < 0.0) {
+ for (mediump float l = 0.0; l < 2.0; l++) { // with 1 as a bound it works
+ c = texture2D(iChannel0, vec2(l), 0.0).x;
+ }
+ }
+ }
+ gl_FragColor = vec4(c, vec3(1.0));
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test checks an ANGLE regression that was caused by a complex ShaderToy shader. <a href='https://code.google.com/p/chromium/issues/detail?id=524297'>crbug.com/524297</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+gl.canvas.addEventListener("webglcontextlost", function(e) {
+ testFailed("WebGL context lost");
+});
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ debug("");
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ testFailed("Program failed to link");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+// Cycle through a rAF once to give any webglcontextlost events a chance to propagate
+window.requestAnimationFrame(function() { finishTest(); });
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/modulo-arithmetic-accuracy.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/modulo-arithmetic-accuracy.html
new file mode 100644
index 0000000000..6e39f69ab7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/modulo-arithmetic-accuracy.html
@@ -0,0 +1,68 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!-- author: Bill Baxter (wbaxter at google.com) -->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Modulo Arithmetic Accuracy Bug</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+uniform float divisor;
+varying vec4 vColor;
+void main(void) {
+ gl_Position = vPosition;
+ float index = 9.0;
+ // mod(x, y) is computed as x-y*floor(x/y). There are no guarantees on
+ // the precision of floating point operations in WebGL shaders, but division
+ // should be accurate to at least 1 part in 10^5.
+ float value = mod(index * 1.00001, divisor);
+ vColor = (value < 1.) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 vColor;
+void main(void) {
+ gl_FragColor = vColor;
+}
+</script>
+<script>
+"use strict";
+
+description();
+debug("");
+// Reproduces bug seen on Mac OS X with AMD Radeon HD 6490 GPU
+debug("If things are working correctly, then the square will be green.");
+debug("If your card thinks mod(9,3) is not 0, then the square will be red.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ vShaderId: 'shader-vs',
+ vShaderSuccess: true,
+ fShaderId: 'shader-fs',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test that mod(9/3) is 0',
+ uniforms: [{name: "divisor", functionName: "uniform1f", value: 3}]
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/multiplication-assignment.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/multiplication-assignment.html
new file mode 100644
index 0000000000..cb157cdec6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/multiplication-assignment.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Multiplication assignment operator compilation bug</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform mat3 rot;
+float foo(vec3 bar) {
+ bar *= rot;
+ return 0.0;
+}
+
+void main(void){
+ gl_FragColor = vec4(foo(vec3(0)));
+}
+</script>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description();
+debug("");
+debug('Verify multiplication assignment operator compiles correctly - regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=384847">Chromium bug 384847</a>');
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vec3 *= mat3 multiplication assignment operator",
+}
+]);
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-functions-should-not-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-functions-should-not-crash.html
new file mode 100644
index 0000000000..130f0a0e4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-functions-should-not-crash.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver Bug - nested functions should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<canvas id="example" width="40" height="40"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+void main(){
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fshaderUniformTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_uniform;
+
+$(code)
+
+void main()
+{
+ gl_FragColor = function0();
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+var fUniformTestSource = wtu.getScript("fshaderUniformTest");
+
+var tests = [
+];
+var counts = [
+ { count:10,
+ mustPass: true,
+ },
+ { count:100,
+ mustPass: false,
+ },
+ { count: 1000,
+ mustPass: false,
+ },
+ { count: 10000,
+ mustPass: false,
+ },
+];
+var operators = ["+", "-", "/", "*"];
+counts.forEach(function(info) {
+ var generateCode = function(numVars) {
+ var codes = [];
+ codes.push("vec4 function" + numVars + "() { return u_uniform; }");
+ for (var uu = 0; uu < numVars; ++uu) {
+ var id = numVars - uu - 1;
+ codes.push("vec4 function" + id + "() { return function" + (id + 1) + "(); }");
+ }
+ return {
+ code: codes.join("\n\n"),
+ };
+ };
+
+ var subs = generateCode(info.count);
+ tests.push({
+ vShaderId: "vshader",
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fUniformTestSource, subs),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with " + info.count + " nested functions",
+ });
+});
+GLSLConformanceTester.runTests(tests);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-loops-with-break-and-continue.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-loops-with-break-and-continue.html
new file mode 100644
index 0000000000..d6a744741a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-loops-with-break-and-continue.html
@@ -0,0 +1,83 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Using nested loops with break and/or continue statements in a fragment shader should work</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform int uCount;
+
+void main() {
+ int a = 0;
+ for (int i = 0; i < 10; ++i) {
+ if (i >= uCount) { break; }
+ for (int j = 0; j < 10; ++j) {
+ if (j >= uCount) { continue; }
+ a += 1;
+ }
+ for (int j = 0; j < 10; ++j) {
+ if (j >= uCount) { break; }
+ a += 1;
+ }
+ for (int j = 0; j < 10; ++j) {
+ if (j >= uCount) { continue; }
+ a += 1;
+ }
+ for (int j = 0; j < 10; ++j) {
+ if (j >= uCount) { break; }
+ a += 1;
+ }
+ for (int j = 0; j < 10; ++j) {
+ if (j >= uCount) { continue; }
+ a += 1;
+ }
+ }
+ float b = (float(a) / 125.0) * (64.0 / 255.0);
+ gl_FragColor = vec4(b, 1.0 - b, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Multiple loops using break and continue statements should work.");
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ wtu.setupUnitQuad(gl);
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["aPosition"], undefined, true);
+ var uniformLoc = gl.getUniformLocation(program, 'uCount');
+ gl.uniform1i(uniformLoc, 5);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [64, 191, 0, 255], "should be 64,191,0,255");
+};
+
+test();
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-sequence-operator.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-sequence-operator.html
new file mode 100644
index 0000000000..b202b854ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/nested-sequence-operator.html
@@ -0,0 +1,47 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Nested sequence operator</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderNestedSequenceOperator" type="x-shader/x-fragment">
+precision mediump float;
+// Note that keep_flop_positive is expected to keep its default value false.
+uniform bool keep_flop_positive;
+float flop;
+void main()
+{
+ flop = -1.0,
+ (flop *= -1.0,
+ keep_flop_positive ? 0.0 : flop *= -1.0),
+ gl_FragColor = vec4(0, -flop, 0, 1);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("Test a nested sequence operator with a ternary operator inside. The ternary operator needs to be converted into an if statement on a HLSL based WebGL backend, which makes this case tricky.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderNestedSequenceOperator',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Nested sequence operator is evaluated in the expected order."
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-of-small-constant-in-user-defined-function.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-of-small-constant-in-user-defined-function.html
new file mode 100644
index 0000000000..d5fa55b898
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-of-small-constant-in-user-defined-function.html
@@ -0,0 +1,74 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Bug - calculating powers of constants smaller than 1.0e-5 in user-defined functions should work</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision highp float;
+
+float fun(float arg) {
+ // These values are still easily within the highp range.
+ // The minimum range in terms of 10's exponent is around -19 to 19, and IEEE-754 single precision range is higher than that.
+ return 1.0e12 * pow(arg, 2.0);
+}
+
+void main() {
+ // Note that the bug did not reproduce if an uniform was passed to the function instead of a constant,
+ // or if the expression was moved outside the user-defined function.
+ const float a = 1.0e-6;
+ float b = fun(a);
+ if (abs(b - 1.0) < 0.01) {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // green
+ } else {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // red
+ }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ if (gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision == 0) {
+ testPassed("highp precision not supported");
+ } else {
+ wtu.setupUnitQuad(gl);
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["aPosition"], undefined, true);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, 256, 256, [0, 255, 0, 255]);
+ }
+};
+
+test();
+finishTest();
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-with-constant-exponent-should-not-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-with-constant-exponent-should-not-crash.html
new file mode 100644
index 0000000000..8e95842b12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/pow-with-constant-exponent-should-not-crash.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Bug - pow() with constant vector exponent should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderTest" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ // pow() with a constant vector exponent may cause a crash on NVIDIA 331 series OpenGL drivers
+ vec2 v = pow(gl_FragCoord.xy, vec2(2.0));
+ float y = pow(v, vec2(0.45, 0.5)).y;
+ gl_FragColor = vec4(0.0, 1.0 + y - gl_FragCoord.y, 0.0, 1.0);
+}
+</script>
+<script id="fshaderNestedTest" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ // pow() with a constant vector exponent may cause a crash on NVIDIA 331 series OpenGL drivers
+ // workarounds for this should work even if problematic pow() statements are nested within
+ // each other.
+ float y = pow(pow(gl_FragCoord.xy, vec2(2.0)), vec2(0.45, 0.5)).y;
+ gl_FragColor = vec4(0.0, 1.0 + y - gl_FragCoord.y, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+
+// This test has quite a lot of tolerance since pow() doesn't have explicit precision requirements
+// in ESSL1, and in ESSL3 the limits are very loose.
+GLSLConformanceTester.runRenderTests([
+ {
+ fShaderId: "fshaderTest",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ renderTolerance: 20,
+ passMsg: "shader with pow() with a constant vector exponent should not crash",
+ },
+ {
+ fShaderId: "fshaderNestedTest",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ renderTolerance: 20,
+ passMsg: "shader with nested pow() calls with constant vector exponents should not crash",
+ }
+]);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-crash.html
new file mode 100644
index 0000000000..f1ef1e47ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-crash.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Qualcomm program link crash Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script id='vshader1' type='x-shader/x-vertex'>
+precision highp float;
+void main() {
+gl_Position = vec4( 1.0, 1.0, 1.0, 1.0 );
+}
+</script>
+<script id='fshader1' type='x-shader/x-fragment'>
+precision highp float;
+uniform int renderType;
+uniform sampler2D texMap;
+void main() {
+ vec2 uv = vec2(0.0, 0.0);
+ if( renderType == 0 ) {
+ gl_FragColor = texture2D( texMap, uv );
+ } else {
+ vec4 texture = texture2D( texMap, uv );
+ gl_FragColor = texture;
+ }
+}
+</script>
+
+<script id='vshader2' type='x-shader/x-vertex'>
+attribute vec3 vertex_position;
+uniform mat4 matrix_model;
+uniform mat4 matrix_viewProjection;
+
+attribute vec4 vertex_boneWeights;
+attribute vec4 vertex_boneIndices;
+
+uniform sampler2D texture_poseMap;
+uniform vec2 texture_poseMapSize;
+
+mat4 getBoneMatrix(const in float i)
+{
+ float j = i * 4.0;
+ float x = mod(j, float(texture_poseMapSize.x));
+ float y = floor(j / float(texture_poseMapSize.x));
+
+ float dx = 1.0 / float(texture_poseMapSize.x);
+ float dy = 1.0 / float(texture_poseMapSize.y);
+
+ y = dy * (y + 0.5);
+
+ vec4 v1 = texture2D(texture_poseMap, vec2(dx * (x + 0.5), y));
+ vec4 v2 = texture2D(texture_poseMap, vec2(dx * (x + 1.5), y));
+ vec4 v3 = texture2D(texture_poseMap, vec2(dx * (x + 2.5), y));
+ vec4 v4 = texture2D(texture_poseMap, vec2(dx * (x + 3.5), y));
+
+ mat4 bone = mat4(v1, v2, v3, v4);
+
+ return bone;
+}
+
+void main(void)
+{
+ mat4 modelMatrix = vertex_boneWeights.x * getBoneMatrix(vertex_boneIndices.x) +
+ vertex_boneWeights.y * getBoneMatrix(vertex_boneIndices.y) +
+ vertex_boneWeights.z * getBoneMatrix(vertex_boneIndices.z) +
+ vertex_boneWeights.w * getBoneMatrix(vertex_boneIndices.w);
+
+ vec4 positionW = modelMatrix * vec4(vertex_position, 1.0);
+ gl_Position = matrix_viewProjection * positionW;
+
+}
+</script>
+<script id='fshader2' type='x-shader/x-fragment'>
+precision highp float;
+void main() {
+ gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test checks a known bug in some Qualcomm drivers which causes crashes when linking certain shaders. <a href='https://code.google.com/p/chromium/issues/detail?id=498947'>crbug.com/498947</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+gl.canvas.addEventListener("webglcontextlost", function(e) {
+ testFailed("WebGL context lost");
+});
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ debug("");
+
+ if (gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision == 0) {
+ testPassed("highp precision not supported");
+ } else {
+ var program1 = wtu.setupProgram(gl, ['vshader1', 'fshader1']);
+ if (!gl.getProgramParameter(program1, gl.LINK_STATUS)) {
+ testFailed("Program failed to link");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("");
+
+ var program2 = wtu.setupProgram(gl, ['vshader2', 'fshader2']);
+ if (!gl.getProgramParameter(program2, gl.LINK_STATUS)) {
+ testFailed("Program failed to link");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+// Cycle through a rAF once to give any webglcontextlost events a chance to propagate
+window.requestAnimationFrame(function() { finishTest(); });
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-loop-with-continue-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-loop-with-continue-crash.html
new file mode 100644
index 0000000000..ff94c52268
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/qualcomm-loop-with-continue-crash.html
@@ -0,0 +1,71 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Qualcomm loop with continue crash test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script id='vshader1' type='x-shader/x-vertex'>
+void main ()
+{
+}
+</script>
+<script id='fshader1' type='x-shader/x-fragment'>
+void main ()
+{
+ int count1 = 0, count2 = 0;
+ for(int i=0;i<4;i++)
+ {
+ if(count1 == 2)
+ continue;
+ }
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test exercises a crash on Adreno 300 series GPUs when compiling certain loop constructs. <a href='https://code.google.com/p/chromium/issues/detail?id=527761'>crbug.com/527761</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+gl.canvas.addEventListener("webglcontextlost", function(e) {
+ testFailed("WebGL context lost");
+});
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ debug("");
+
+ var program1 = wtu.setupProgram(gl, ['vshader1', 'fshader1']);
+ if (!gl.getProgramParameter(program1, gl.LINK_STATUS)) {
+ testFailed("Program failed to link");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("");
+}
+
+// Cycle through a rAF once to give any webglcontextlost events a chance to propagate
+window.requestAnimationFrame(function() { finishTest(); });
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-struct-function-arg.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-struct-function-arg.html
new file mode 100644
index 0000000000..b39179a186
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-struct-function-arg.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL struct containing an array of samplers passed into a user-defined function</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+
+<canvas id="output" style="border: none;" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderSampler" type="x-shader/x-fragment">
+precision mediump float;
+
+struct S {
+ sampler2D sam[2];
+};
+
+uniform S uni;
+
+vec4 useSampler(S arg)
+{
+ return texture2D(arg.sam[0], vec2(0.0, 0.0));
+}
+
+void main() {
+ gl_FragColor = vec4(useSampler(uni));
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("output");
+var gl = wtu.create3DContext(canvas);
+
+if (!gl) {
+ testFailed("Could not create a GL context.");
+} else {
+ debug("Drawing with a shader that uses a sampler array in a struct passed into a function.");
+ var program = wtu.setupProgram(
+ gl, [wtu.simpleVertexShader, 'fshaderSampler'], ['a_position'], [0], true);
+ wtu.setupUnitQuad(gl);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ wtu.fillTexture(gl, tex, 1, 1, [0, 255, 0, 255]);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-using-loop-index.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-using-loop-index.html
new file mode 100644
index 0000000000..c5707a1f89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-array-using-loop-index.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Sampler arrays using loop index should compile fine.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D uni[2];
+
+float zero(int x)
+{
+ return float(x) - float(x);
+}
+
+void main()
+{
+ vec4 c = vec4(0,0,0,0);
+ for (int ii = 1; ii < 3; ++ii) {
+ if (c.x > 255.0) {
+ c.x = 255.0 + zero(ii);
+ break;
+ }
+ c += texture2D(uni[ii - 1], vec2(0.5, 0.5));
+ }
+ gl_FragColor = c;
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition'], undefined, true);
+
+for (var ii = 0; ii < 2; ++ii) {
+ var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ var tex = gl.createTexture();
+ wtu.fillTexture(gl, tex, 1, 1, [32, 16, 8, ii * 9], 0);
+ gl.uniform1i(loc, ii);
+}
+
+wtu.clearAndDrawUnitQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [64, 32, 16, 9],
+ "Should render correctly", 1);
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-struct-function-arg.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-struct-function-arg.html
new file mode 100644
index 0000000000..f2bc755444
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sampler-struct-function-arg.html
@@ -0,0 +1,113 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Passing a struct containing a sampler to a function.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+
+<body>
+<canvas id="output" style="border: none;" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+ precision mediump float;
+
+ struct SomeStruct{
+ sampler2D source;
+ };
+
+ vec4 fun(SomeStruct s){
+ return texture2D(s.source, vec2(0.5));
+ }
+
+ uniform SomeStruct green;
+ void main(){
+ gl_FragColor = fun(green);
+ }
+</script>
+
+<script id="shader-fs-array" type="x-shader/x-fragment">
+ precision mediump float;
+
+ struct SomeStruct{
+ sampler2D source;
+ };
+
+ vec4 fun(SomeStruct s[2]){
+ return texture2D(s[0].source, vec2(0.5));
+ }
+
+ uniform SomeStruct green[2];
+ void main(){
+ gl_FragColor = fun(green);
+ }
+</script>
+
+<script>
+"use strict";
+
+description();
+debug("If the test passes correctly the viewport will be green.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("output");
+var gl = wtu.create3DContext(canvas);
+
+var textureGreen;
+
+var createGreenTexture = function() {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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);
+ wtu.fillTexture(gl, texture, 1, 1, [0, 255, 0, 255]);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ return texture;
+};
+
+var test = function(fragShaderId, texUniformName) {
+ var program = wtu.setupProgram(gl, [wtu.simpleVertexShader, fragShaderId], ["a_position"], [0], true);
+
+ if (!program) {
+ testFailed("Shader compilation/link failed");
+ } else {
+ // Bind texture
+ var uniformMap = wtu.getUniformMap(gl, program);
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, textureGreen);
+ gl.uniform1i(uniformMap[texUniformName].location, 0);
+
+ // Draw
+ wtu.clearAndDrawUnitQuad(gl);
+
+ // Verify output
+ wtu.checkCanvasRect(gl, 0, 128, 256, 128, [0, 255,0, 255], "should be green", 1);
+ }
+};
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ wtu.setupUnitQuad(gl, 0, 1);
+ textureGreen = createGreenTexture();
+ test("shader-fs", "green.source");
+ test("shader-fs-array", "green[0].source");
+}
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sequence-operator-evaluation-order.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sequence-operator-evaluation-order.html
new file mode 100644
index 0000000000..7e9af6f1aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sequence-operator-evaluation-order.html
@@ -0,0 +1,116 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL short-circuiting operators should be evaluated after previous operands in a sequence</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderSequenceSideEffectsAffectTernary" type="x-shader/x-fragment">
+precision mediump float;
+
+bool correct = true;
+
+uniform float u_zero;
+
+float wrong() {
+ correct = false;
+ return 0.0;
+}
+
+void main() {
+ // ESSL 1.00 section 5.9, about sequence operator:
+ // "All expressions are evaluated, in order, from left to right"
+ // Also use a ternary operator where the third operand has side effects to make sure
+ // only the second operand is evaluated.
+ float a = u_zero - 0.5; // Result should be -0.5.
+ float green = (a++, a > 0.0 ? 1.0 : wrong());
+ gl_FragColor = vec4(0.0, correct ? green : 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fshaderSequenceSideEffectsAffectAnd" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform bool u_false;
+
+bool sideEffectA = false;
+bool funcA() {
+ sideEffectA = true;
+ return true;
+}
+
+bool sideEffectB = false;
+bool funcB() {
+ sideEffectB = true;
+ return true;
+}
+
+void main() {
+ bool b = (funcA(), u_false == sideEffectA && funcB());
+ gl_FragColor = (!b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script id="fshaderSequenceSideEffectsAffectOr" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform bool u_false;
+
+bool sideEffectA = false;
+bool funcA() {
+ sideEffectA = true;
+ return false;
+}
+
+bool sideEffectB = false;
+bool funcB() {
+ sideEffectB = true;
+ return false;
+}
+
+void main() {
+ bool b = (funcA(), (u_false == !sideEffectA) || funcB());
+ gl_FragColor = (b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+debug("");
+debug("This test is targeted to stress syntax tree transformations that might need to be done in shader translation to unfold operators.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderSequenceSideEffectsAffectTernary',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where first operand of a sequence operator has side effects which affect the second operand that is a ternary operator'
+},
+{
+ fShaderId: 'fshaderSequenceSideEffectsAffectAnd',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where first operand of a sequence operator has side effects which affect the second operand that is an and operator'
+},
+{
+ fShaderId: 'fshaderSequenceSideEffectsAffectOr',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where first operand of a sequence operator has side effects which affect the second operand that is an or operator'
+}
+]);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sketchfab-lighting-shader-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sketchfab-lighting-shader-crash.html
new file mode 100644
index 0000000000..73416d17de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/sketchfab-lighting-shader-crash.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Sketchfab Lighting Shader Crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script id='vshader1' type='x-shader/x-vertex'>
+attribute float testValue; // Can be uniform as well.
+varying mediump float FragVarying; // Necessary to reproduce.
+
+void main() {
+ // Crashes with mat4 as well. Does not crash with vectors.
+ mat2 projectionMatrix = mat2(0.0, 0.0, 0.0, 0.0);
+ if (testValue == 1.0)
+ {
+ // Using the matrix variable appears necessary.
+ projectionMatrix[0][0] = 1.0;
+ }
+
+ FragVarying = 0.0;
+ // Referencing the matrix is necessary though clearly the compiler
+ // doesn't realize the assignment is useless.
+ gl_Position = vec4(projectionMatrix[1][0], 0.0, 0.0, 1.0);
+}
+</script>
+<script id='fshader1' type='x-shader/x-fragment'>
+precision mediump float;
+varying float FragVarying;
+
+void main() {
+ gl_FragColor = vec4(FragVarying, 0.0, 0.0, 1.0);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test demonstrates a crash on the Nexus 5 (Adreno 330) when compiling Sketchfab's lighting shader. <a href='https://code.google.com/p/chromium/issues/detail?id=551937'>crbug.com/551937</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+gl.canvas.addEventListener("webglcontextlost", function(e) {
+ testFailed("WebGL context lost");
+});
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ debug("");
+
+ var program1 = wtu.setupProgram(gl, ['vshader1', 'fshader1']);
+ if (!gl.getProgramParameter(program1, gl.LINK_STATUS)) {
+ testFailed("Program failed to link");
+ } else {
+ testPassed("Program linked successfully");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("");
+}
+
+// Cycle through rAF a few times to give any webglcontextlost events a chance to propagate.
+wtu.waitForComposite(function() { finishTest(); });
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-constructor-highp-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-constructor-highp-bug.html
new file mode 100644
index 0000000000..afb72e1916
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-constructor-highp-bug.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Struct constructor highp bug.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+
+struct Test {
+ vec3 color;
+};
+
+void main() {
+ vec3 color = vec3( 0.0, 1.0, 0.0 );
+ Test test = Test( color );
+ gl_FragColor = vec4( test.color, 1.0 );
+}
+</script>
+
+<script type="application/javascript">
+"use strict";
+description("Struct constructors should evaluate properly.");
+debug("Regression test for Three.js bug worked around in <a href='https://github.com/mrdoob/three.js/pull/7556'>https://github.com/mrdoob/three.js/pull/7556</a> that reproduced on Nexus 4 and 5 (Adreno 320 and 330).");
+debug("When high precision is used in the fragment shader on these devices, bugs occur in evaluation of structs' constructors. Thanks to Mr. doob for the reduced test case.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Struct contstructor evaluation"
+}
+]);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-with-single-member-constructor.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-with-single-member-constructor.html
new file mode 100644
index 0000000000..8d1008326f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/struct-with-single-member-constructor.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL struct with a single member constructor test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+#version 100
+
+precision mediump float;
+
+struct S {
+ mat2 rotation;
+};
+void main(void)
+{
+ float angle = 1.0;
+ S(mat2(1.0, angle, 1.0, 1.0));
+}
+</script>
+<script>
+"use strict";
+description();
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/swiftshader/issues/detail?id=56'>Swiftshader bug 56</a>.");
+debug("");
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Construct a struct with a single matrix member"
+}
+]);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/temp-expressions-should-not-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/temp-expressions-should-not-crash.html
new file mode 100644
index 0000000000..c28db1daad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/temp-expressions-should-not-crash.html
@@ -0,0 +1,100 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver Bug - temp experssions should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<canvas id="example" width="40" height="40"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+void main(){
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fshaderUniformTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_uniform;
+void main()
+{
+ vec4 temp = vec4(0, 0, 0, 0);
+$(code)
+ gl_FragColor = temp;
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+var fUniformTestSource = wtu.getScript("fshaderUniformTest");
+
+var tests = [
+];
+var counts = [
+ { count:100,
+ mustPass: true,
+ },
+ { count: 1000,
+ mustPass: false,
+ },
+ { count: 10000,
+ mustPass: false,
+ },
+];
+var operators = ["+", "-", "/", "*"];
+counts.forEach(function(info) {
+ var generateCode = function(numVars) {
+ var codes = [];
+ var count = 0;
+ var step = 10;
+ for (var uu = 0; uu < numVars; uu += step) {
+ var subCodes = [""];
+ for (var vv = 0; vv < step; ++vv) {
+ subCodes.push(operators[(count++) % operators.length]);
+ }
+ subCodes.push("");
+ codes.push(" temp += " + subCodes.join("\n u_uniform ") + ";");
+ }
+ return {
+ code: codes.join("\n"),
+ };
+ };
+
+ var subs = generateCode(info.count);
+ tests.push({
+ vShaderId: "vshader",
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fUniformTestSource, subs),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with uniform with " + info.count + " operators in temp expressions in multiple lines",
+ });
+ subs.code = subs.code.replace(/\n +/g, " ")
+ tests.push({
+ vShaderId: "vshader",
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fUniformTestSource, subs),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ ignoreResults: !info.mustPass,
+ passMsg: "shader with uniform with " + info.count + " operators in temp expressions in one line",
+ });
+});
+GLSLConformanceTester.runTests(tests);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/unary-minus-operator-float-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/unary-minus-operator-float-bug.html
new file mode 100644
index 0000000000..85f7231444
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/unary-minus-operator-float-bug.html
@@ -0,0 +1,49 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL unary minus operator with float bug Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main () {
+ float f = -1.0;
+ // atan(tan(0.5), -f) is in range [1.5707, 1.5708) on Mac OSX 10.11 with Intel GPU.
+ // But it should be 0.5.
+ gl_FragColor = vec4(atan(tan(0.5), -f), 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description("Test for unary minus operator with float bug on MacOSX 10.11 with Intel GPU");
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=308366'>Chromium Issue 308366</a>");
+debug("");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Evaluate unary minus operator and atan(x, y)",
+ renderTolerance: 3,
+ renderColor: [127, 0, 0, 255]
+}
+]);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/undefined-index-should-not-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/undefined-index-should-not-crash.html
new file mode 100644
index 0000000000..0c97c987f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/undefined-index-should-not-crash.html
@@ -0,0 +1,64 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Bug - indexing with 'int()' should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<canvas id="example" width="40" height="40"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+void main(){
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fshaderTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 uniformVec;
+uniform mat4 uniformMat;
+uniform float uniformArray[4];
+void main()
+{
+ vec4 tempVec = vec4(0.0);
+ mat4 tempMat = mat4(0.0);
+ float tempArray[4];
+ gl_FragColor = vec4($(indexed)[int()]);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+var fTestSource = wtu.getScript("fshaderTest");
+
+var tests = [];
+
+var indexedValues = ['tempVec', 'tempMat[0]', 'tempArray', 'uniformVec', 'uniformMat[0]', 'uniformArray'];
+
+for (var i = 0; i < indexedValues.length; ++i) {
+ var subs = {indexed: indexedValues[i]};
+ tests.push({
+ vShaderId: "vshader",
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fTestSource, subs),
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "shader with invalid index expression int() should not compile",
+ });
+}
+GLSLConformanceTester.runTests(tests);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/uniforms-should-not-lose-values.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/uniforms-should-not-lose-values.html
new file mode 100644
index 0000000000..fc99f0f87f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/uniforms-should-not-lose-values.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Driver Bug - Uniforms should no lose values</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="512" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+uniform float k,u;
+uniform mat4 l;
+attribute vec3 a;
+void main(){
+ gl_Position=l*vec4(a,1.+u+k);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform float w,x,y,z;
+void main() {
+ gl_FragColor=vec4(1.-y,y,w+x+z,1);
+}
+</script>
+<script>
+"use strict";
+// Certain drivers fail this test. Specifically Mac NVidia GT 330 on OSX 10.8.2
+description();
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+
+ wtu.setupUnitQuad(gl);
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a"], undefined, true);
+
+ var setUniformf = function(name, val) {
+ var loc = gl.getUniformLocation(program, name);
+ var func = 'uniform' + val.length + 'fv';
+ gl[func](loc, val);
+ };
+
+ var setUniformMat = function(name, val) {
+ var loc = gl.getUniformLocation(program, name);
+ var func = 'uniformMatrix' + Math.sqrt(val.length) + 'fv';
+ gl[func](loc, false, val);
+ };
+
+ setUniformMat('l', [1, 0 ,0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
+ gl.viewport(0, 0, 256, 256);
+ setUniformf('y', [0]);
+ wtu.drawUnitQuad(gl);
+ gl.viewport(256, 0, 256, 256);
+ setUniformf('y', [1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, 256, 256, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, 256, 0, 256, 256, [0, 255, 0, 255]);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+test();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/varying-arrays-should-not-be-reversed.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/varying-arrays-should-not-be-reversed.html
new file mode 100644
index 0000000000..14cdd9fe09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/varying-arrays-should-not-be-reversed.html
@@ -0,0 +1,82 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Varying arrays should not be reversed</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="512" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+varying float colors[3];
+uniform vec3 testData;
+attribute vec3 position;
+void main(){
+ gl_Position = vec4(position, 1.0);
+ colors[0] = testData.x;
+ colors[1] = testData.y;
+ colors[2] = testData.z;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying float colors[3];
+void main() {
+ gl_FragColor = vec4(colors[0], colors[1], colors[2], 1.0);
+}
+</script>
+<script>
+"use strict";
+description("Varying arrays should not be reversed.");
+debug("This issue has been seen in Chrome on Nexus 7 2013 (Adreno 320) and Moto G3 (Adreno 306).");
+debug("");
+debug("If things are working correctly, the vertical stripes should be: red, green, blue, light blue, orange");
+debug("");
+debug("If they are not, the red and blue channels will appear to be swapped and you will see: blue, green, red, orange, light blue");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+
+ wtu.setupUnitQuad(gl);
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position"], undefined, true);
+ var loc = gl.getUniformLocation(program, 'testData');
+
+ var triples = [
+ [255, 0, 0],
+ [0, 255, 0],
+ [0, 0, 255],
+ [0, 128, 255],
+ [255, 128, 0]
+ ];
+
+ for (var i = 0; i < triples.length; i++) {
+ var triple = triples[i];
+ var x = i * 64;
+ gl.viewport(x, 0, 64, 256);
+ gl.uniform3f(loc, triple[0] / 255, triple[1] / 255, triple[2] / 255);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, x, 0, 64, 256, [triple[0], triple[1], triple[2], 255]);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+test();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-matrix-constructor-scalarization.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-matrix-constructor-scalarization.html
new file mode 100644
index 0000000000..a6ad3483c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-matrix-constructor-scalarization.html
@@ -0,0 +1,181 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title></title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<!--
+
+Original Shadertoy:
+https://www.shadertoy.com/view/ttGyzh
+
+ float a = 0.; // bug
+ #define A 0. // ok
+//#define A min(0.,iTime) // bug
+
+
+ #define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) ) // bug
+//#define r(a) mat2( cos(a), -sin(a), sin(a), cos(a) ) // no bug
+//#define r(a) cos(a),sin(a)) // no bug ( vec instead of mat )
+//#define r(a) cos(a+vec2(0,-1.5708)) // no bug ( vec instead of mat )
+
+vec2 c;
+#define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
+
+void mainImage( out vec4 O, vec2 U )
+{
+ U /= iResolution.xy;
+
+ O = U.y > .5
+ ? vec4( f(U,a) , f(U*4.,a) , 0,0) // top
+ : vec4( f(U,A) , f(U*4.,A) , 0,0); // bottom
+}
+-->
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 aPosition;
+attribute vec2 aTexCoord;
+
+varying vec2 vTexCoord;
+
+void main(void) {
+ gl_Position = vec4(aPosition, 0.0, 1.0);
+ vTexCoord = aTexCoord;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec2 vTexCoord;
+
+float a = 0.;
+#define A 0.
+
+#define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
+vec2 c;
+#define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
+
+void main() {
+ vec2 U = vTexCoord;
+
+ gl_FragColor = U.y > .5
+ ? vec4( f(U,a) , f(U*4.,a) , 0,1.0) // top
+ : vec4( f(U,A) , f(U*4.,A) , 0,1.0); // bottom
+}
+</script>
+
+<script id="compileVShader" type="x-shader/x-vertex">
+varying vec2 v_texcoord;
+
+void main() {
+ v_texcoord = vec2(0.0, 0.0);
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="compileFShader" type="x-shader/x-fragment">
+// From http://crbug.com/398694
+precision mediump float;
+uniform sampler2D s_texture;
+uniform vec4 color_weights;
+varying vec2 v_texcoord;
+void main() {
+ gl_FragColor = color_weights * mat4(
+ vec4(texture2D(s_texture, v_texcoord).rgb, 1.0),
+ vec4(texture2D(s_texture, v_texcoord).rgb, 1.0),
+ vec4(texture2D(s_texture, v_texcoord).rgb, 1.0),
+ vec4(texture2D(s_texture, v_texcoord).rgb, 1.0));
+}
+</script>
+
+</head>
+<body>
+<canvas id="example"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Vector and matrix constructor scalarization workaround (SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) caused bugs");
+debug('Regression test for <a href="http://crbug.com/1165751">crbug.com/1165751</a>');
+
+// Note: Firefox reports that without this workaround, there are
+// failures on at least Windows / Intel GPU / OpenGL on:
+// conformance/glsl/constructors/glsl-construct-mat2.html
+// https://searchfox.org/mozilla-central/source/dom/canvas/WebGLShaderValidator.cpp#63
+
+// Chromium reported that
+// conformance/glsl/misc/shader-struct-scope.html failed on macOS and
+// on Linux AMD without this workaround enabled:
+// http://crbug.com/angleproject/701
+
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("example");
+const sz = canvas.width = canvas.height = 256;
+const gl = wtu.create3DContext(canvas, undefined);
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+ finishTest();
+} else {
+ testPassed("WebGL context creation succeeded");
+ runDrawTest();
+ runCompileTest();
+ finishTest();
+}
+
+function runDrawTest() {
+ debug("Ensure that shader translation isn't broken by the vector and matrix constructor scalarization workaround");
+ let positionLocation = 0;
+ let texCoordLocation = 1;
+ wtu.setupUnitQuad(gl, positionLocation, texCoordLocation);
+ let program = wtu.setupProgram(gl, ["vshader", "fshader"],
+ ["aPosition", "aTexCoord"],
+ [positionLocation, texCoordLocation], true);
+ if (!program) {
+ testFailed("Error compiling shaders");
+ return;
+ }
+ gl.useProgram(program);
+ // Buffers returned from setupQuad above, and ignored, are already bound.
+ wtu.drawUnitQuad(gl);
+
+ // Top and bottom halves should be roughly equal. Go through one
+ // horizontal scanline in the middle.
+ const compareHeight = sz / 4;
+ let pixelValue = new Uint8Array(4);
+ let allEqual = true;
+ // Empirically found that tolerance between the top and bottom
+ // needs to be up to roughly 8 on some platforms.
+ const tolerance = 8;
+ let tempBuf = new Uint8Array(4);
+ // Step over some pixels to spew slightly fewer comparison messages.
+ for (let x = 0; x < sz; x += 4) {
+ gl.readPixels(x, compareHeight, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixelValue);
+ wtu.checkCanvasRect(gl, x, sz - compareHeight, 1, 1, pixelValue, undefined, tolerance, tempBuf);
+ }
+}
+
+function runCompileTest() {
+ debug("Running compilation test");
+ let program = wtu.setupProgram(gl, ["compileVShader", "compileFShader"], [], [], true);
+ if (program) {
+ testPassed("Shader previously requiring SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS compiled successfully");
+ } else {
+ testFailed("Shader previously requiring SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS failed to compile");
+ }
+}
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html
new file mode 100644
index 0000000000..3b1277c1be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL vector/scalar arithmetic inside a for loop (complex cases)</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fShaderVectorCompoundMulAndAddInSeparateStatementsInsideForLoop" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ float x = gl_FragCoord.x;
+ float y = (x *= 2.0);
+ gl_FragColor = gl_FragColor + vec4(y, y, y, y);
+ }
+ if (gl_FragColor.g == gl_FragColor.r &&
+ gl_FragColor.b == gl_FragColor.r &&
+ gl_FragColor.a == gl_FragColor.r)
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+}
+</script>
+<script id="fShaderVectorCompoundMulAndAddInSeparateStatementsInsideForLoop2" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ float x = gl_FragCoord.x;
+ float y = (x *= 2.0);
+ gl_FragColor = gl_FragColor + vec4(x, y, x, y);
+ }
+ if (gl_FragColor.g == gl_FragColor.r &&
+ gl_FragColor.b == gl_FragColor.r &&
+ gl_FragColor.a == gl_FragColor.r)
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+// See http://crbug.com/772651
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fShaderVectorCompoundMulAndAddInSeparateStatementsInsideForLoop',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Adding a vector that's just 4 copies of a scalar to another vector inside for loop should work."
+},
+{
+ fShaderId: 'fShaderVectorCompoundMulAndAddInSeparateStatementsInsideForLoop2',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Adding a vector that's just 4 copies of a scalar stored in two different variables to another vector inside for loop should work."
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html
new file mode 100644
index 0000000000..622ea38129
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html
@@ -0,0 +1,99 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL vector/scalar arithmetic inside a for loop</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fShaderVectorMulAndAddInsideForLoop" type="x-shader/x-fragment">
+void main(){
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ gl_FragColor += (2.0 * gl_FragCoord.x);
+ }
+ if (gl_FragColor.g == gl_FragColor.r &&
+ gl_FragColor.b == gl_FragColor.r &&
+ gl_FragColor.a == gl_FragColor.r)
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+}
+</script>
+<script id="fShaderVectorCompoundMulAndAddInsideForLoop" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ float x = gl_FragCoord.x;
+ gl_FragColor = gl_FragColor + (x *= 2.0);
+ }
+ if (gl_FragColor.g == gl_FragColor.r &&
+ gl_FragColor.b == gl_FragColor.r &&
+ gl_FragColor.a == gl_FragColor.r)
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+}
+</script>
+<script id="fShaderVectorCompoundDivAndAddInsideForLoop" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ float x = gl_FragCoord.x;
+ gl_FragColor = gl_FragColor + (x /= 2.0);
+ }
+ if (gl_FragColor.g == gl_FragColor.r &&
+ gl_FragColor.b == gl_FragColor.r &&
+ gl_FragColor.a == gl_FragColor.r)
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+// See http://crbug.com/772651
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fShaderVectorMulAndAddInsideForLoop',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Adding a scalar to a vector inside for loop should work."
+},
+{
+ fShaderId: 'fShaderVectorCompoundMulAndAddInsideForLoop',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Adding a scalar (target of a compound assignment/multiplication operation) to a vector inside for loop should work."
+},
+{
+ fShaderId: 'fShaderVectorCompoundDivAndAddInsideForLoop',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Adding a scalar (target of a compound assignment/division operation) to a vector inside for loop should work."
+}
+]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/00_test_list.txt
new file mode 100644
index 0000000000..6758bea8e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/00_test_list.txt
@@ -0,0 +1,14 @@
+glsl-construct-vec2.html
+glsl-construct-vec3.html
+glsl-construct-vec4.html
+glsl-construct-ivec2.html
+glsl-construct-ivec3.html
+glsl-construct-ivec4.html
+glsl-construct-bvec2.html
+glsl-construct-bvec3.html
+glsl-construct-bvec4.html
+glsl-construct-mat2.html
+glsl-construct-mat3.html
+glsl-construct-mat4.html
+--min-version 1.0.3 glsl-construct-vec-mat-corner-cases.html
+--min-version 1.0.3 glsl-construct-vec-mat-index.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec2.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec2.html
new file mode 100644
index 0000000000..b1e72160d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec2.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "bvec2";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec3.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec3.html
new file mode 100644
index 0000000000..57f51d3902
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec3.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "bvec3";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec4.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec4.html
new file mode 100644
index 0000000000..a873c016d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-bvec4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "bvec4";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec2.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec2.html
new file mode 100644
index 0000000000..5524fe3abc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec2.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "ivec2";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec3.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec3.html
new file mode 100644
index 0000000000..594f6713f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec3.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "ivec3";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec4.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec4.html
new file mode 100644
index 0000000000..8bc59761e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-ivec4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "ivec4";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat2.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat2.html
new file mode 100644
index 0000000000..5a4afb817d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat2.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "mat2";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat3.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat3.html
new file mode 100644
index 0000000000..e4a2e9815d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat3.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "mat3";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat4.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat4.html
new file mode 100644
index 0000000000..81fd92b2ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-mat4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "mat4";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-corner-cases.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-corner-cases.html
new file mode 100644
index 0000000000..a2c8f306ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-corner-cases.html
@@ -0,0 +1,195 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vsVec4Mat2Add" type="text/something-not-javascript">
+void main()
+{
+ mat2 m1 = mat2(1.0, 2.0, 3.0, 4.0);
+ mat2 m2 = mat2(0);
+ vec4 v = vec4(m1 + m2);
+ gl_Position = v;
+}
+</script>
+<script id="fsVec4Mat3Add" type="text/something-not-javascript">
+precision mediump float;
+void main()
+{
+ mat3 m1 = mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
+ mat3 m2 = mat3(0);
+ vec4 v = vec4(m1 + m2);
+ gl_FragColor = v;
+}
+</script>
+
+<script id="vsMat2Vec4Sub" type="text/something-not-javascript">
+void main()
+{
+ vec4 v1 = vec4(1.0, 2.0, 3.0, 4.0);
+ vec4 v2 = vec4(0);
+ mat2 m = mat2(v1 - v2);
+ gl_Position = vec4(1.0, m);
+}
+</script>
+<script id="fsMat3Vec4AddSub" type="text/something-not-javascript">
+precision mediump float;
+void main()
+{
+ vec4 v1 = vec4(1.0, 2.0, 3.0, 4.0);
+ vec4 v2 = vec4(0);
+ mat3 m = mat3(v1 + v2, 5.0, v1 - v2);
+ gl_FragColor = vec4(m);
+}
+</script>
+
+<script id="vsVec4Mat2Func" type="text/something-not-javascript">
+mat2 f(mat2 a)
+{
+ return a;
+}
+void main()
+{
+ mat2 m = mat2(1.0, 2.0, 3.0, 4.0);
+ vec4 v = vec4(f(m));
+ gl_Position = vec4(1.0, v);
+}
+</script>
+<script id="fsVec4Mat3Func" type="text/something-not-javascript">
+precision mediump float;
+mat3 f(mat3 a)
+{
+ return a;
+}
+void main()
+{
+ mat3 m = mat3(0);
+ vec4 v = vec4(f(m));
+ gl_FragColor = v;
+}
+</script>
+
+<script id="vsMat2Vec4Func" type="text/something-not-javascript">
+vec4 f(vec4 a)
+{
+ return a;
+}
+void main()
+{
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ mat2 m = mat2(f(v));
+ gl_Position = vec4(1.0, m);
+}
+</script>
+<script id="fsMat3Vec4Func" type="text/something-not-javascript">
+precision mediump float;
+vec4 f(vec4 a)
+{
+ return a;
+}
+void main()
+{
+ vec4 v1 = vec4(1.0, 2.0, 3.0, 4.0);
+ vec4 v2 = vec4(0);
+ mat3 m = mat3(f(v1), 5.0, f(v2));
+ gl_FragColor = vec4(m);
+}
+</script>
+
+<script id="vsMat4VecMultiple" type="text/something-not-javascript">
+vec4 f(vec4 a)
+{
+ return a;
+}
+void main()
+{
+ vec2 v2 = vec2(1.0, 2.0);
+ vec3 v3 = vec3(1.0, 2.0, 3.0);
+ vec4 v4 = vec4(1.0, 2.0, 3.0, 4.0);
+ mat4 m = mat4(0.0, v2, 1.0, v3 + vec3(1), 2.0, vec4(0), f(v4));
+ gl_Position = vec4(1.0, m);
+}
+</script>
+<script id="fsMat4VecMultiple" type="text/something-not-javascript">
+precision mediump float;
+vec4 f(vec4 a)
+{
+ return a;
+}
+void main()
+{
+ vec2 v2 = vec2(1.0, 2.0);
+ vec3 v3 = vec3(1.0, 2.0, 3.0);
+ vec4 v4 = vec4(1.0, 2.0, 3.0, 4.0);
+ mat4 m = mat4(0.0, v2, 1.0, v3 + vec3(1), 2.0, vec4(0), f(v4));
+ gl_FragColor = vec4(m);
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var tests = [];
+
+tests.push({
+ vShaderSource: wtu.getScript("vsVec4Mat2Add"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fsVec4Mat3Add"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vec(mat +/- mat) works ok",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vsMat2Vec4Sub"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fsMat3Vec4AddSub"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "mat(vec +/- vec) works ok",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vsVec4Mat2Func"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fsVec4Mat3Func"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vec(func(mat)) works ok",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vsMat2Vec4Func"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fsMat3Vec4Func"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "mat(func(vec)) works ok",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vsMat4VecMultiple"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fsMat4VecMultiple"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "mat4(float, vec2, float, vec3+vec3, float, vec4, f(vec4)) works ok",
+});
+
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-index.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-index.html
new file mode 100644
index 0000000000..084d532f8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec-mat-index.html
@@ -0,0 +1,53 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// A matrix constructor with two writes and reads to the same variable inside it in different parameters must succeed "mat2(index++, vec4(index++))"
+// ESSL 1.00 spec section 5.4 Constructors: "Arguments are evaluated from left to right."
+precision mediump float;
+bool equal(mat2 m1, mat2 m2)
+{
+ float EPSILON = 0.00001;
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (abs(m1[i][j] - m2[i][j]) > EPSILON)
+ return false;
+ }
+ }
+ return true;
+}
+void main()
+{
+ int i = 0;
+ mat2 m = mat2(i++, vec4(i++));
+ if (equal(m, mat2(0, 1, 1, 1)))
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+GLSLConformanceTester.runRenderTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec2.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec2.html
new file mode 100644
index 0000000000..6fa0d2af52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec2.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "vec2";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec3.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec3.html
new file mode 100644
index 0000000000..b5e1a7cd4d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec3.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "vec3";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec4.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec4.html
new file mode 100644
index 0000000000..c66fa470a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/constructors/glsl-construct-vec4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script src="../../../js/glsl-constructor-tests-generator.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var targetType = "vec4";
+description("Test " + targetType + " constructor expressions.");
+
+var testSet = GLSLConstructorTestsGenerator.getDefaultTestSet(targetType);
+
+// Generate tests
+var testCases = GLSLConstructorTestsGenerator.getConstructorTests(targetType, testSet);
+
+// Run the tests
+GLSLConformanceTester.runTests(testCases);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/00_test_list.txt
new file mode 100644
index 0000000000..dd06ea0520
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/00_test_list.txt
@@ -0,0 +1,36 @@
+glsl-function.html
+glsl-function-abs.html
+glsl-function-acos.html
+glsl-function-asin.html
+glsl-function-atan.html
+glsl-function-atan-xy.html
+glsl-function-ceil.html
+glsl-function-clamp-float.html
+glsl-function-clamp-gentype.html
+glsl-function-cos.html
+glsl-function-cross.html
+glsl-function-distance.html
+glsl-function-dot.html
+glsl-function-faceforward.html
+glsl-function-floor.html
+glsl-function-fract.html
+glsl-function-length.html
+#glsl-function-lessThan.html
+glsl-function-max-float.html
+glsl-function-max-gentype.html
+glsl-function-min-float.html
+glsl-function-min-gentype.html
+glsl-function-mix-float.html
+glsl-function-mix-gentype.html
+glsl-function-mod-float.html
+glsl-function-mod-gentype.html
+glsl-function-normalize.html
+glsl-function-reflect.html
+#glsl-function-refract.html
+glsl-function-sign.html
+glsl-function-sin.html
+glsl-function-step-float.html
+glsl-function-step-gentype.html
+glsl-function-smoothstep-float.html
+glsl-function-smoothstep-gentype.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-abs.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-abs.html
new file mode 100644
index 0000000000..e7e3b19207
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-abs.html
@@ -0,0 +1,45 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL abs function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "abs",
+ testFunc: "$(func)($(arg0))",
+ emuFunc: ["float $(func)_base(float value) {",
+ " return value >= 0.0 ? value : -value;",
+ "}"].join("\n"),
+ gridRes: 4,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 2.0 - 1.0),",
+ " 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ "$(output) = vec4(0, $(func)($(input).xy * 2.0 - vec2(1, 1)), 1);",
+ "$(output) = vec4($(func)($(input).xyz * 2.0 - vec3(1, 1, 1)), 1);",
+ "$(output) = $(func)($(input) * 2.0 - vec4(1, 1, 1, 1));"
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-acos.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-acos.html
new file mode 100644
index 0000000000..ba6b9ab33f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-acos.html
@@ -0,0 +1,95 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL acos function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var piConstants = [
+ "const float kPI = 3.14159265358979323846;",
+ "const float kHalfPI = (kPI * 0.5);",
+ "const float k2PI = (kPI * 2.0);"
+].join("\n");
+
+var kPI = Math.PI;
+var kHalfPI = Math.PI * 0.5;
+var k2PI = Math.PI * 2.0;
+var acos = Math.acos; // shorthand
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "acos",
+ args: "$(type) value",
+ testFunc: "$(func)($(type))",
+ gridRes: 8,
+ tolerance: 2,
+ extra: piConstants,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).x * 0.8) / kPI,",
+ " $(func)($(input).y * 0.8) / kPI,",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ acos(x * 0.8) / kPI,
+ acos(y * 0.8) / kPI,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xy * 0.8) / kPI,",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ acos(x * 0.8) / kPI,
+ acos(y * 0.8) / kPI,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xyz * 0.8) / kPI,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ acos(x * 0.8) / kPI,
+ acos(y * 0.8) / kPI,
+ acos(z * 0.8) / kPI,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = ",
+ " $(func)($(input) * 0.8) / kPI;",
+ ].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ acos(x * 0.8) / kPI,
+ acos(y * 0.8) / kPI,
+ acos(z * 0.8) / kPI,
+ acos(w * 0.8) / kPI ];
+ },
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-asin.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-asin.html
new file mode 100644
index 0000000000..051c4f7d81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-asin.html
@@ -0,0 +1,95 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL asin function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var piConstants = [
+ "const float kPI = 3.14159265358979323846;",
+ "const float kHalfPI = (kPI * 0.5);",
+ "const float k2PI = (kPI * 2.0);"
+].join("\n");
+
+var kPI = Math.PI;
+var kHalfPI = Math.PI * 0.5;
+var k2PI = Math.PI * 2.0;
+var asin = Math.asin; // shorthand
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "asin",
+ args: "$(type) value",
+ testFunc: "$(func)($(type))",
+ gridRes: 8,
+ tolerance: 2,
+ extra: piConstants,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).x * 0.8) / kPI + 0.5,",
+ " $(func)($(input).y * 0.8) / kPI + 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ asin(x * 0.8) / kPI + 0.5,
+ asin(y * 0.8) / kPI + 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xy * 0.8) / kPI + 0.5,",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ asin(x * 0.8) / kPI + 0.5,
+ asin(y * 0.8) / kPI + 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xyz * 0.8) / kPI + 0.5,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ asin(x * 0.8) / kPI + 0.5,
+ asin(y * 0.8) / kPI + 0.5,
+ asin(z * 0.8) / kPI + 0.5,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = ",
+ " $(func)($(input) * 0.8) / kPI + 0.5;",
+ ].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ asin(x * 0.8) / kPI + 0.5,
+ asin(y * 0.8) / kPI + 0.5,
+ asin(z * 0.8) / kPI + 0.5,
+ asin(w * 0.8) / kPI + 0.5 ];
+ },
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan-xy.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan-xy.html
new file mode 100644
index 0000000000..e20d18d2c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan-xy.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL atan-xy function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var piConstants = [
+ "const float kPI = 3.14159265358979323846;",
+ "const float kHalfPI = (kPI * 0.5);",
+ "const float k2PI = (kPI * 2.0);"
+].join("\n");
+
+var kPI = Math.PI;
+var kHalfPI = Math.PI * 0.5;
+var k2PI = Math.PI * 2.0;
+var atan2 = Math.atan2; // shorthand
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "atan",
+ args: "$(type) y, $(type) x",
+ testFunc: "$(func)($(type), $(type))",
+ gridRes: 8,
+ tolerance: 5,
+ extra: piConstants,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).x + 0.1, $(input).y) / k2PI + 0.5,",
+ " 0,",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan2(x + 0.1, y) / k2PI + 0.5,
+ 0,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xy + vec2(0.1, 0.1), $(input).yx) / ",
+ " k2PI + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan2(x + 0.1, y) / k2PI + 0.5,
+ atan2(y + 0.1, x) / k2PI + 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xyz + vec3(0.1, 0.1, 0.1), $(input).yzx) / ",
+ " k2PI + vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan2(x + 0.1, y) / k2PI + 0.5,
+ atan2(y + 0.1, z) / k2PI + 0.5,
+ atan2(z + 0.1, x) / k2PI + 0.5,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = ",
+ " $(func)($(input) + vec4(0.1, 0.1, 0.1, 0.1), $(input).wzyx) / ",
+ " k2PI + vec4(0.5, 0.5, 0.5, 0.5);",
+ ].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan2(x + 0.1, w) / k2PI + 0.5,
+ atan2(y + 0.1, z) / k2PI + 0.5,
+ atan2(z + 0.1, y) / k2PI + 0.5,
+ atan2(w + 0.1, x) / k2PI + 0.5 ];
+ },
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan.html
new file mode 100644
index 0000000000..20d1366f70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-atan.html
@@ -0,0 +1,95 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL atan function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var piConstants = [
+ "const float kPI = 3.14159265358979323846;",
+ "const float kHalfPI = (kPI * 0.5);",
+ "const float k2PI = (kPI * 2.0);"
+].join("\n");
+
+var kPI = Math.PI;
+var kHalfPI = Math.PI * 0.5;
+var k2PI = Math.PI * 2.0;
+var atan = Math.atan; // shorthand
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "atan",
+ args: "$(type) value",
+ testFunc: "$(func)($(type))",
+ gridRes: 8,
+ tolerance: 4,
+ extra: piConstants,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).x * 8.0 - 4.0) / k2PI + 0.5,",
+ " 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan(x * 8.0 - 4.0) / k2PI + 0.5,
+ 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xy * 8.0 - vec2(4, 4)) / k2PI + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan(x * 8.0 - 4) / k2PI + 0.5,
+ atan(y * 8.0 - 4) / k2PI + 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xyz * 8.0 - vec3(4, 4, 4)) / k2PI + vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan(x * 8.0 - 4) / k2PI + 0.5,
+ atan(y * 8.0 - 4) / k2PI + 0.5,
+ atan(z * 8.0 - 4) / k2PI + 0.5,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = ",
+ " $(func)($(input) * 8.0 - vec4(4, 4, 4, 4)) / k2PI + vec4(0.5, 0.5, 0.5, 0.5);",
+ ].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ atan(x * 8.0 - 4) / k2PI + 0.5,
+ atan(y * 8.0 - 4) / k2PI + 0.5,
+ atan(z * 8.0 - 4) / k2PI + 0.5,
+ atan(w * 8.0 - 4) / k2PI + 0.5 ];
+ },
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-ceil.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-ceil.html
new file mode 100644
index 0000000000..a031b93fa3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-ceil.html
@@ -0,0 +1,53 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL ceil function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "ceil",
+ testFunc: "$(func)($(arg0))",
+ emuFunc: ["float $(func)_base(float value) {",
+ " float m = mod(value, 1.0);",
+ " return m != 0.0 ? (value + 1.0 - m) : value;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 8.0 - 4.0) / 8.0 + 0.5,",
+ " $(func)($(input).y * 8.0 - 4.0) / 8.0 + 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * 8.0 - vec2(4, 4)) / 8.0 + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 8.0 - vec3(4, 4, 4)) / 8.0 + ",
+ " vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * 8.0 - vec4(4, 4, 4, 4)) / 8.0 + ",
+ " vec4(0.5, 0.5, 0.5, 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-float.html
new file mode 100644
index 0000000000..bb74a30961
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-float.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL clamp-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "clamp",
+ args: "$(type) value, float minValue, float maxValue",
+ baseArgs: "value$(field), minValue, maxValue",
+ testFunc: "$(func)($(type), float, float)",
+ emuFunc: ["float $(func)_base(float value, float minValue, float maxValue) {",
+ " return min(max(value, minValue), maxValue);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 6.0 - 3.0, -1.5, 1.5) / 3.0 + 0.5,",
+ " $(func)($(input).y * 10.0 - 5.0, -2.5, 2.5) / 5.0 + 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * vec2(6, 10) - vec2(3, 5), -1.5, 2.0) / ",
+ " vec2(3.0, 5.0) + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * vec3(6, 10, 8) - vec3(3, 5, 4), -1.5, 2.0) / ",
+ " vec3(3, 5, 4) + vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * vec4(6, 10, 8, 4) - vec4(3, 5, 4, 2),",
+ " -1.5, 2.2) / vec4(3, 5, 4, 2) + ",
+ " vec4(0.5, 0.5, 0.5, 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-gentype.html
new file mode 100644
index 0000000000..2967bdc57d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-clamp-gentype.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL clamp-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "clamp",
+ args: "$(type) value, $(type) minValue, $(type) maxValue",
+ baseArgs: "value$(field), minValue$(field), maxValue$(field)",
+ testFunc: "$(func)($(type), $(type), $(type))",
+ emuFunc: ["float $(func)_base(float value, float minValue, float maxValue) {",
+ " return min(max(value, minValue), maxValue);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 6.0 - 3.0, -1.5, 1.5) / 3.0 + 0.5,",
+ " $(func)($(input).y * 10.0 - 5.0, -2.5, 2.5) / 5.0 + 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * vec2(6, 10) - vec2(3, 5), ",
+ " vec2(-1.5, -2.5), vec2(1.5, 2.5)) / ",
+ " vec2(3.0, 5.0) + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * vec3(6, 10, 8) - vec3(3, 5, 4), ",
+ " vec3(-1.5, -2.5, -2), vec3(1.5, 2.5, 2)) / vec3(3, 5, 4) + ",
+ " vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * vec4(6, 10, 8, 4) - vec4(3, 5, 4, 2),",
+ " vec4(-1.5, -2.5, -2, -1), vec4(1.5, 2.5, 2, 1)) / ",
+ " vec4(3, 5, 4, 2) + ",
+ " vec4(0.5, 0.5, 0.5, 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cos.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cos.html
new file mode 100644
index 0000000000..a62ffc76fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cos.html
@@ -0,0 +1,99 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL cos function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var piConstants = [
+ "const float kPI = 3.14159265358979323846;",
+ "const float kHalfPI = (kPI * 0.5);",
+ "const float k2PI = (kPI * 2.0);"
+].join("\n");
+
+var kPI = Math.PI;
+var kHalfPI = Math.PI * 0.5;
+var k2PI = Math.PI * 2.0;
+var cos = Math.cos; // shorthand
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "cos",
+ args: "$(type) value",
+ testFunc: "$(func)($(type))",
+ gridRes: 8,
+ tolerance: 3,
+ extra: piConstants,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).x * kHalfPI + kHalfPI),",
+ " $(func)($(input).y * kHalfPI),",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ cos(x * kHalfPI + kHalfPI),
+ cos(y * kHalfPI),
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xy * vec2(kPI, k2PI)) * 0.5 + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ cos(x * kPI) * 0.5 + 0.5,
+ cos(y * k2PI) * 0.5 + 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ // FIXME: for some reason, this test requires a higher tolerance when run in a vertex shader.
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xyz * vec3(kPI, k2PI, 4.0)) * ",
+ " 0.5 + vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ cos(x * kPI) * 0.5 + 0.5,
+ cos(y * k2PI) * 0.5 + 0.5,
+ cos(z * 4.0) * 0.5 + 0.5,
+ 1 ];
+ },
+ tolerance: 7,
+ },
+ {
+ source: ["$(output) = ",
+ " $(func)($(input) * vec4(k2PI, 4.0, kHalfPI, kPI)) *",
+ " 0.5 + vec4(0.5, 0.5, 0.5, 1);",
+ ].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ cos(x * k2PI) * 0.5 + 0.5,
+ cos(y * 4.0) * 0.5 + 0.5,
+ cos(z * kHalfPI) * 0.5 + 0.5,
+ cos(w * kPI) * 0.5 + 1.0 ];
+ },
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cross.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cross.html
new file mode 100644
index 0000000000..37d17a4eda
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-cross.html
@@ -0,0 +1,53 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL cross function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+GLSLGenerator.runFeatureTest({
+ feature: "cross",
+ args: "$(type) x, $(type) y",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type),$(type))",
+ emuFuncs: [
+ { type: "vec3",
+ code: [
+ "vec3 $(func)_emu($(args)) {",
+ " return vec3(",
+ " x[1] * y[2] - y[1] * x[2],",
+ " x[2] * y[0] - y[2] * x[0],",
+ " x[0] * y[1] - y[0] * x[1]);",
+ "}"].join("\n")
+ },
+ ],
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " normalize($(input).xyz - 0.5),",
+ " normalize($(input).yzw - 0.5)) * 0.5 + 0.5,",
+ " 1);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-distance.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-distance.html
new file mode 100644
index 0000000000..1efa4f7e4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-distance.html
@@ -0,0 +1,88 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL distance function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+GLSLGenerator.runFeatureTest({
+ feature: "distance",
+ args: "$(type) p1, $(type) p2",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type),$(type))",
+ emuFuncs: [
+ { type: "float",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return abs(p1 - p2);",
+ "}"].join("\n")
+ },
+ { type: "vec2",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return length(p1 - p2);",
+ "}"].join("\n")
+ },
+ { type: "vec3",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return length(p1 - p2);",
+ "}"].join("\n")
+ },
+ { type: "vec4",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return length(p1 - p2);",
+ "}"].join("\n")
+ }
+ ],
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).x * 8.0 - 4.0,",
+ " $(input).y * 8.0 - 4.0) / 8.0,",
+ " 0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " 0,",
+ " $(func)(",
+ " $(input).xy * 8.0 - 4.0,",
+ " $(input).wz * 8.0 - 4.0) / 8.0,",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " 0, 0,",
+ " $(func)(",
+ " $(input).xyz * 8.0 - 4.0,",
+ " $(input).yzw * 8.0 - 4.0) / 8.0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " vec4($(input).xyz, 0) * 8.0 - 4.0,",
+ " vec4(0, $(input).wzy) * 8.0 - 4.0) / 8.0,",
+ " 0, 0, 1);",
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-dot.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-dot.html
new file mode 100644
index 0000000000..c29e43e464
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-dot.html
@@ -0,0 +1,90 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL dot function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+GLSLGenerator.runFeatureTest({
+ feature: "dot",
+ args: "$(type) p1, $(type) p2",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type),$(type))",
+ fragmentTolerance: 1,
+ emuFuncs: [
+ { type: "float",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return p1 * p2;",
+ "}"].join("\n")
+ },
+ { type: "vec2",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return p1.x * p2.x + p1.y * p2.y;",
+ "}"].join("\n")
+ },
+ { type: "vec3",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;",
+ "}"].join("\n")
+ },
+ { type: "vec4",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z + p1.w * p2.w;",
+ "}"].join("\n")
+ }
+ ],
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).x * 8.0 - 4.0,",
+ " $(input).y * 8.0 - 4.0) / 8.0,",
+ " 0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " 0,",
+ " $(func)(",
+ " $(input).xy * 8.0 - 4.0,",
+ " $(input).wz * 8.0 - 4.0) / 8.0,",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " 0, 0,",
+ " $(func)(",
+ " $(input).xyz * 8.0 - 4.0,",
+ " $(input).yzw * 8.0 - 4.0) / 8.0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " vec4($(input).xyz, 0) * 8.0 - 4.0,",
+ " vec4(0, $(input).wzy) * 8.0 - 4.0) / 8.0,",
+ " 0, 0, 1);",
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-faceforward.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-faceforward.html
new file mode 100644
index 0000000000..16a4e72ef7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-faceforward.html
@@ -0,0 +1,66 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL faceforward function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+GLSLGenerator.runFeatureTest({
+ feature: "faceforward",
+ args: "$(type) N, $(type) I, $(type) Nref",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type),$(type),$(type))",
+ simpleEmu: [
+ "$(type) $(func)_emu($(args)) {",
+ " return dot(Nref, I) < 0.0 ? N : -N;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).x * 2.0 - 1.0,",
+ " $(input).y * 2.0 - 1.0,",
+ " $(input).z * 2.0 - 1.0),",
+ " 0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xy * 2.0 - 1.0,",
+ " $(input).yz * 2.0 - 1.0,",
+ " $(input).zw * 2.0 - 1.0),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xyz * 2.0 - 1.0,",
+ " $(input).yzw * 2.0 - 1.0,",
+ " $(input).zwx * 2.0 - 1.0),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(",
+ " $(input).xyzw * 2.0 - 1.0,",
+ " $(input).yzwx * 2.0 - 1.0,",
+ " $(input).zwxy * 2.0 - 1.0);"
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-floor.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-floor.html
new file mode 100644
index 0000000000..371ebd746b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-floor.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL floor function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "floor",
+ testFunc: "$(func)($(arg0))",
+ emuFunc: ["float $(func)_base(float value) {",
+ " return value - mod(value, 1.0);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 8.0 - 4.0) / 8.0 + 0.5,",
+ " $(func)($(input).y * 8.0 - 4.0) / 8.0 + 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * 8.0 - vec2(4, 4)) / 8.0 + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 8.0 - vec3(4, 4, 4)) / 8.0 + ",
+ " vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * 8.0 - vec4(4, 4, 4, 4)) / 8.0 + ",
+ " vec4(0.5, 0.5, 0.5, 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-fract.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-fract.html
new file mode 100644
index 0000000000..90e1c0bf13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-fract.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL fract function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "fract",
+ testFunc: "$(func)($(arg0))",
+ emuFunc: ["float $(func)_base(float value) {",
+ " return value - floor(value);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 4.0 - 2.0),",
+ " $(func)($(input).y * 4.0 - 2.0),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * 4.0 - vec2(2, 2)),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 4.0 - vec3(2, 2, 2)),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * 4.0 - vec4(2, 2, 2, 2));"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-length.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-length.html
new file mode 100644
index 0000000000..f3f04f4543
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-length.html
@@ -0,0 +1,87 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL length function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+GLSLGenerator.runFeatureTest({
+ feature: "length",
+ args: "$(type) value",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type))",
+ fragmentTolerance: 1,
+ emuFuncs: [
+ { type: "float",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return abs($(baseArgs));",
+ "}"].join("\n")
+ },
+ { type: "vec2",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return sqrt(",
+ " $(baseArgsX) * $(baseArgsX) + ",
+ " $(baseArgsY) * $(baseArgsY));",
+ "}"].join("\n")
+ },
+ { type: "vec3",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return sqrt(",
+ " $(baseArgsX) * $(baseArgsX) + ",
+ " $(baseArgsY) * $(baseArgsY) + ",
+ " $(baseArgsZ) * $(baseArgsZ));",
+ "}"].join("\n")
+ },
+ { type: "vec4",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return sqrt(",
+ " $(baseArgsX) * $(baseArgsX) + ",
+ " $(baseArgsY) * $(baseArgsY) + ",
+ " $(baseArgsZ) * $(baseArgsZ) + ",
+ " $(baseArgsW) * $(baseArgsW));",
+ "}"].join("\n")
+ }
+ ],
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 8.0 - 4.0) / 4.0,",
+ " $(func)($(input).y * 8.0 - 4.0) / 4.0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * 8.0 - 4.0) / 4.0,",
+ " 0, 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 8.0 - 4.0) / 4.0,",
+ " 0, 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input) * 8.0 - 4.0) / 4.0, 0, 0, 1);",
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-lessThan.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-lessThan.html
new file mode 100644
index 0000000000..d461c2ee16
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-lessThan.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL lessThan function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "lessThan",
+ args: "$(type) x, $(type) y",
+ bvecTest: true,
+ baseArgs: "x, y",
+ testFunc: "$(func)($(type), $(type))",
+ emuFunc: ["bool $(func) _base(float x, float y) {",
+ " return x < y;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["bvec2 r = bvec2($(func)($(input).xy, $(input).yw));",
+ "$(output) = vec4(",
+ " r.x ? 0.2: 0.8,",
+ " r.y ? 0.2: 0.8,",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 8.0 - vec3(4, 4, 4)) / 8.0 + ",
+ " vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * 8.0 - vec4(4, 4, 4, 4)) / 8.0 + ",
+ " vec4(0.5, 0.5, 0.5, 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-float.html
new file mode 100644
index 0000000000..880fa24b48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-float.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL max-float function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "max",
+ args: "$(type) value, float maxValue",
+ baseArgs: "value$(field), maxValue",
+ testFunc: "$(func)($(arg0), float)",
+ emuFunc: ["float $(func)_base(float value, float maxValue) {",
+ " return value > maxValue ? value : maxValue;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x, 0.5),",
+ " $(func)($(input).y, 0.5),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input), 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-gentype.html
new file mode 100644
index 0000000000..8d30dacdf9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-max-gentype.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL max-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "max",
+ args: "$(type) value, $(type) maxValue",
+ baseArgs: "value$(field), maxValue$(field)",
+ testFunc: "$(func)($(type), $(type))",
+ emuFunc: ["float $(func)_base(float value, float maxValue) {",
+ " return value > maxValue ? value : maxValue;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x, 0.5),",
+ " $(func)($(input).y, 0.5),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy, vec2(0.5, 0.5)),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz, vec3(0.5, 0.5, 0.5)),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input), vec4(0.5, 0.5, 0.5, 0.5));"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-float.html
new file mode 100644
index 0000000000..1cb140ce45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-float.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL min-float function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "min",
+ args: "$(type) value, float divisor",
+ baseArgs: "value$(field), divisor",
+ testFunc: "$(func)($(arg0), float)",
+ emuFunc: ["float $(func)_base(float value, float divisor) {",
+ " return value < divisor ? value : divisor;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x, 0.5),",
+ " $(func)($(input).y, 0.5),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input), 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-gentype.html
new file mode 100644
index 0000000000..4ff565112a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-min-gentype.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL min-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "min",
+ args: "$(type) value, $(type) minValue",
+ baseArgs: "value$(field), minValue$(field)",
+ testFunc: "$(func)($(type), $(type))",
+ emuFunc: ["float $(func)_base(float value, float minValue) {",
+ " return value < minValue ? value : minValue;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x, 0.5),",
+ " $(func)($(input).y, 0.5),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy, vec2(0.5, 0.5)),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz, vec3(0.5, 0.5, 0.5)),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input), vec4(0.5, 0.5, 0.5, 0.5));"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-float.html
new file mode 100644
index 0000000000..34e70068c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-float.html
@@ -0,0 +1,54 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mix-float function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "mix",
+ args: "$(type) startValue, $(type) endValue, float mixValue",
+ baseArgs: "startValue$(field), endValue$(field), mixValue",
+ testFunc: "$(func)($(type), $(type), float)",
+ emuFunc: [
+ "float $(func)_base(float startValue, float endValue, float mixValue) {",
+ " return startValue * (1.0 - mixValue) + endValue * mixValue;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(1.0, 0.0, $(input).x),",
+ " ($(func)(-2.0, 3.0, $(input).y) + 2.0) / 5.0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec2(1, -2), vec2(0, 2), $(input).z), ",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec3(1, -2, -1), vec3(0, 2, 3), $(input).y),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(vec4(1, -2, -1, 0.5), vec4(0, 2, 3, 1), $(input).w);"
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-gentype.html
new file mode 100644
index 0000000000..2fa3330e7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mix-gentype.html
@@ -0,0 +1,54 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mix-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "mix",
+ args: "$(type) startValue, $(type) endValue, $(type) mixValue",
+ baseArgs: "startValue$(field), endValue$(field), mixValue$(field)",
+ testFunc: "$(func)($(type), $(type), $(type))",
+ emuFunc: [
+ "float $(func)_base(float startValue, float endValue, float mixValue) {",
+ " return startValue * (1.0 - mixValue) + endValue * mixValue;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(1.0, 0.0, $(input).x),",
+ " ($(func)(-2.0, 3.0, $(input).y) + 2.0) / 5.0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec2(1, -2), vec2(0, 2), $(input).xy), ",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec3(1, -2, -1), vec3(0, 2, 3), $(input).xyz),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(vec4(1, -2, -1, 0.5), vec4(0, 2, 3, 1), $(input));"
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-float.html
new file mode 100644
index 0000000000..83bcf76715
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-float.html
@@ -0,0 +1,53 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mod-float function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "mod",
+ args: "$(type) value, float divisor",
+ baseArgs: "value$(field), divisor",
+ testFunc: "$(func)($(arg0), float)",
+ fragmentTolerance: 1,
+ emuFunc: ["float $(func)_base(float value, float divisor) {",
+ " return value - divisor * floor(value / divisor);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 6.0 - 3.0, 1.5) / 1.5,",
+ " $(func)($(input).y * 6.0 - 3.0, 1.5) / 1.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * 6.0 - vec2(3, 3), 1.5) / 1.5,",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 6.0 - vec3(3, 3, 3), 1.5) / 1.5,",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * 6.0 - vec4(3, 3, 3, 3), 1.5) / 1.5;"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-gentype.html
new file mode 100644
index 0000000000..9b562300b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-mod-gentype.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mod-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "mod",
+ args: "$(type) value, $(type) divisor",
+ baseArgs: "value$(field), divisor$(field)",
+ testFunc: "$(func)($(type), $(type))",
+ emuFunc: ["float $(func)_base(float value, float divisor) {",
+ " return value - divisor * floor(value / divisor);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tolerance: 1,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 6.0 - 3.0, 1.5) / 1.5,",
+ " $(func)($(input).y * 10.0 - 5.0, 2.1) / 2.1,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * vec2(6, 10) - vec2(3, 5), ",
+ " vec2(1.5, 2.1)) / vec2(1.5, 2.1),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * vec3(6, 10, 8) - vec3(3, 5, 4), ",
+ " vec3(1.5, 2.1, 3.2)) / vec3(1.5, 2.1, 3.2),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * vec4(6, 10, 8, 4) - vec4(3, 5, 4, 2),",
+ " vec4(1.5, 2.1, 3.2, 1.1)) / vec4(1.5, 2.1, 3.2, 1.1);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-normalize.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-normalize.html
new file mode 100644
index 0000000000..bd5f8844d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-normalize.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL normalize function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "normalize",
+ args: "$(type) value",
+ testFunc: "$(func)($(type))",
+ simpleEmu: [
+ "$(type) $(func)_emu($(args)) {",
+ " return value / length(value);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tolerance: 1,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).x * 8.0 - 4.1) * 0.5 + 0.5,",
+ " 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xy * 8.0 - 4.1) * 0.5 + 0.5,",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xyz * 8.0 - 4.1) * 0.5 + 0.5,",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(",
+ " vec4($(input).xyz, 0) * 8.0 - 4.1) * 0.5 + 0.5 + vec4(0,0,0,0.5);",
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-reflect.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-reflect.html
new file mode 100644
index 0000000000..70d9e557f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-reflect.html
@@ -0,0 +1,61 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL reflect function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "reflect",
+ args: "$(type) I, $(type) N",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type),$(type))",
+ simpleEmu: [
+ "$(type) $(func)_emu($(args)) {",
+ " return I - 2.0 * dot(N, I) * N;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).x * 2.0 - 1.0,",
+ " $(input).y * 2.0 - 1.0),",
+ " 0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xy * 2.0 - 1.0,",
+ " $(input).yz * 2.0 - 1.0),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xyz * 2.0 - 1.0,",
+ " $(input).yzw * 2.0 - 1.0),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(",
+ " $(input).xyzw * 2.0 - 1.0,",
+ " $(input).yzwx * 2.0 - 1.0);"
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-refract.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-refract.html
new file mode 100644
index 0000000000..1ee43b2f60
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-refract.html
@@ -0,0 +1,70 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL refract function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "refract",
+ args: "$(type) I, $(type) N, float eta",
+ baseArgs: "value$(field)",
+ testFunc: "$(func)($(type),$(type),float)",
+ simpleEmu: [
+ "$(type) $(func)_emu($(args)) {",
+ " float dotNI = dot(N, I);",
+ " float k = 1.0 - eta * eta * (1.0 - dotNI * dotNI);",
+ " if (k < 0.0) {",
+ " return $(type)(0.0);",
+ " }",
+ " return eta * I - (eta * dotNI * sqrt(k)) * N;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).x * 2.0 - 1.0,",
+ " $(input).y * 2.0 - 1.0,",
+ " $(input).w),",
+ " 0,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xy * 2.0 - 1.0,",
+ " $(input).yz * 2.0 - 1.0,",
+ " $(input).w),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(",
+ " $(input).xyz * 2.0 - 1.0,",
+ " $(input).yzw * 2.0 - 1.0,",
+ " $(input).w),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(",
+ " $(input).xyzw * 2.0 - 1.0,",
+ " $(input).yzwx * 2.0 - 1.0,",
+ " $(input).w);"
+ ].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sign.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sign.html
new file mode 100644
index 0000000000..3185c647ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sign.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL sign function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "sign",
+ testFunc: "$(func)($(arg0))",
+ emuFunc: ["float $(func)_base(float value) {",
+ " if (value == 0.0) return 0.0;",
+ " return value > 0.0 ? 1.0 : -1.0;",
+ "}"].join("\n"),
+ gridRes: 4,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)($(input).x * 2.0 - 1.0) * 0.5 + 0.5,",
+ " 0.5,",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xy * 2.0 - vec2(1, 1)) * 0.5 + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)($(input).xyz * 2.0 - vec3(1, 1, 1)) * 0.5 + ",
+ " vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)($(input) * 2.0 - vec4(1, 1, 1, 1)) * 0.5 + ",
+ " vec4(0.5, 0.5, 0.5, 0.5);"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sin.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sin.html
new file mode 100644
index 0000000000..b27e6ace1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-sin.html
@@ -0,0 +1,96 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL sin function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var piConstants = [
+ "const float kPI = 3.14159265358979323846;",
+ "const float kHalfPI = (kPI * 0.5);",
+ "const float k2PI = (kPI * 2.0);"
+].join("\n");
+
+var kPI = Math.PI;
+var kHalfPI = Math.PI * 0.5;
+var k2PI = Math.PI * 2.0;
+var sin = Math.sin; // shorthand
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "sin",
+ args: "$(type) value",
+ testFunc: "$(func)($(type))",
+ gridRes: 8,
+ tolerance: 4,
+ extra: piConstants,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).x * kHalfPI + kHalfPI),",
+ " $(func)($(input).y * kHalfPI),",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ sin(x * kHalfPI + kHalfPI),
+ sin(y * kHalfPI),
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xy * vec2(kPI, k2PI)) * 0.5 + vec2(0.5, 0.5),",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ sin(x * kPI) * 0.5 + 0.5,
+ sin(y * k2PI) * 0.5 + 0.5,
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = vec4(",
+ " $(func)($(input).xyz * vec3(kPI, k2PI, 4.0)) * ",
+ " 0.5 + vec3(0.5, 0.5, 0.5),",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ sin(x * kPI) * 0.5 + 0.5,
+ sin(y * k2PI) * 0.5 + 0.5,
+ sin(z * 4.0) * 0.5 + 0.5,
+ 1 ];
+ },
+ },
+ {
+ source: ["$(output) = ",
+ " $(func)($(input) * vec4(k2PI, 4.0, kHalfPI, kPI)) *",
+ " 0.5 + vec4(0.5, 0.5, 0.5, 1);",
+ ].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ sin(x * k2PI) * 0.5 + 0.5,
+ sin(y * 4.0) * 0.5 + 0.5,
+ sin(z * kHalfPI) * 0.5 + 0.5,
+ sin(w * kPI) * 0.5 + 1 ];
+ },
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-float.html
new file mode 100644
index 0000000000..a963ec0fb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-float.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL smoothstep-float function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+function clamp(value, min, max) {
+ return Math.max(min, Math.min(value, max));
+}
+
+function smoothstep(edge0, edge1, value) {
+ var t = clamp((value - edge0) / (edge1 - edge0), 0, 1);
+ return t * t * (3 - 2 * t);
+}
+
+GLSLGenerator.runReferenceImageTest({
+ feature: "smoothstep",
+ args: "float edge0, float edge1, $(type) value",
+ testFunc: "$(func)(float, float, $(type))",
+ gridRes: 8,
+ tolerance: 4,
+ tests: [
+ {
+ source: ["$(output) = vec4(",
+ " $(func)(0.3, 0.7, $(input).x),",
+ " $(func)(0.2, 0.8, $(input).y),",
+ " 0,",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ smoothstep(0.3, 0.7, x),
+ smoothstep(0.2, 0.8, y),
+ 0,
+ 1 ];
+ },
+ },
+ {
+ source: [ "$(output) = vec4(",
+ " $(func)(0.4, 0.8, $(input).xy),",
+ " 0, 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ smoothstep(0.4, 0.8, x),
+ smoothstep(0.4, 0.8, y),
+ 0,
+ 1 ];
+ },
+ },
+ {
+ // FIXME: this test seems to need a higher tolerance when run in a vertex shader.
+ source: [ "$(output) = vec4(",
+ " $(func)(0.3, 0.7, $(input).xyz),",
+ " 1);"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ smoothstep(0.3, 0.7, x),
+ smoothstep(0.3, 0.7, y),
+ smoothstep(0.3, 0.7, z),
+ 1 ];
+ },
+ tolerance: 12,
+ fragmentTolerance: 3,
+ },
+ {
+ // FIXME: this test seems to need a higher tolerance when run in a vertex shader.
+ source: ["$(output) = ",
+ " $(func)(0.3, 0.9, $(input));"].join("\n"),
+ generator: function(x, y, z, w) {
+ return [ smoothstep(0.3, 0.9, x),
+ smoothstep(0.3, 0.9, y),
+ smoothstep(0.3, 0.9, z),
+ smoothstep(0.3, 0.9, w) ];
+ },
+ tolerance: 7,
+ fragmentTolerance: 3,
+ },
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-gentype.html
new file mode 100644
index 0000000000..84c992ed64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-smoothstep-gentype.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL smoothstep-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+GLSLGenerator.runFeatureTest({
+ feature: "smoothstep",
+ args: "$(type) edge0, $(type) edge1, $(type) value",
+ baseArgs: "edge0$(field), edge1$(field), value$(field)",
+ testFunc: "$(func)($(type), $(type), $(type))",
+ emuFunc: ["float $(func)_base(float edge0, float edge1, float value) {",
+ " float t = clamp((value - edge0) / (edge1 - edge0), 0.0, 1.0);",
+ " return t * t * (3.0 - 2.0 * t);",
+ "}"].join("\n"),
+ gridRes: 8,
+ tolerance: 1,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(0.3, 0.7, $(input).x),",
+ " $(func)(0.2, 0.8, $(input).y),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec2(0.4, 0.6), vec2(0.8, 0.9), $(input).xy),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec3(0.3, 0.5, 0.7), vec3(0.7, 0.9, 1.0), $(input).xyz),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(vec4(0.3, 0.4, 0.5, 0.2), ",
+ " vec4(0.7, 0.6, 0.9, 0.8), ",
+ " $(input));"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-float.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-float.html
new file mode 100644
index 0000000000..09f6e38612
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-float.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL step-float function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "step",
+ args: "float edge, $(type) value",
+ baseArgs: "edge, value$(field)",
+ testFunc: "$(func)(float, $(type))",
+ emuFunc: ["float $(func)_base(float edge, float value) {",
+ " return value < edge ? 0.0 : 1.0;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(0.3, $(input).x),",
+ " $(func)(0.7, $(input).y),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(0.4, $(input).xy),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(0.4, $(input).xyz),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)(0.4, $(input));"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-gentype.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-gentype.html
new file mode 100644
index 0000000000..8b267265f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function-step-gentype.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL step-gentype function test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "step",
+ args: "$(type) edge, $(type) value",
+ baseArgs: "edge$(field), value$(field)",
+ testFunc: "$(func)($(type), $(type))",
+ emuFunc: ["float $(func)_base(float edge, float value) {",
+ " return value < edge ? 0.0 : 1.0;",
+ "}"].join("\n"),
+ gridRes: 8,
+ tests: [
+ ["$(output) = vec4(",
+ " $(func)(0.3, $(input).x),",
+ " $(func)(0.7, $(input).y),",
+ " 0,",
+ " 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec2(0.4, 0.6), $(input).xy),",
+ " 0, 1);"].join("\n"),
+ ["$(output) = vec4(",
+ " $(func)(vec3(0.3, 0.5, 0.7), $(input).xyz),",
+ " 1);"].join("\n"),
+ ["$(output) = ",
+ " $(func)( vec4(0.3, 0.4, 0.5, 0.2), $(input));"].join("\n")
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function.html
new file mode 100644
index 0000000000..51acf0dae2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/functions/glsl-function.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL function test test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+GLSLGenerator.runFeatureTest({
+ feature: "the_GLSL_test_harness",
+ testFunc: "pass through",
+ emuFunc: "float $(func)_base(float value) { return 0.0; }",
+ gridRes: 4,
+ tests: [
+ "$(output) = vec4($(input).x, 0, 0, 1);",
+ "$(output) = vec4(0, $(input).xy, 1);",
+ "$(output) = vec4($(input).xyz, 1);",
+ "$(output) = $(input);"
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/00_test_list.txt
new file mode 100644
index 0000000000..d700b29a56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/00_test_list.txt
@@ -0,0 +1,65 @@
+add_int_float.vert.html
+add_int_mat2.vert.html
+add_int_mat3.vert.html
+add_int_mat4.vert.html
+add_int_vec2.vert.html
+add_int_vec3.vert.html
+add_int_vec4.vert.html
+add_ivec2_vec2.vert.html
+add_ivec3_vec3.vert.html
+add_ivec4_vec4.vert.html
+assign_int_to_float.vert.html
+assign_ivec2_to_vec2.vert.html
+assign_ivec3_to_vec3.vert.html
+assign_ivec4_to_vec4.vert.html
+construct_struct.vert.html
+divide_int_float.vert.html
+divide_int_mat2.vert.html
+divide_int_mat3.vert.html
+divide_int_mat4.vert.html
+divide_int_vec2.vert.html
+divide_int_vec3.vert.html
+divide_int_vec4.vert.html
+divide_ivec2_vec2.vert.html
+divide_ivec3_vec3.vert.html
+divide_ivec4_vec4.vert.html
+equal_int_float.vert.html
+equal_ivec2_vec2.vert.html
+equal_ivec3_vec3.vert.html
+equal_ivec4_vec4.vert.html
+function_int_float.vert.html
+function_ivec2_vec2.vert.html
+function_ivec3_vec3.vert.html
+function_ivec4_vec4.vert.html
+greater_than.vert.html
+greater_than_equal.vert.html
+less_than.vert.html
+less_than_equal.vert.html
+multiply_int_float.vert.html
+multiply_int_mat2.vert.html
+multiply_int_mat3.vert.html
+multiply_int_mat4.vert.html
+multiply_int_vec2.vert.html
+multiply_int_vec3.vert.html
+multiply_int_vec4.vert.html
+multiply_ivec2_vec2.vert.html
+multiply_ivec3_vec3.vert.html
+multiply_ivec4_vec4.vert.html
+not_equal_int_float.vert.html
+not_equal_ivec2_vec2.vert.html
+not_equal_ivec3_vec3.vert.html
+not_equal_ivec4_vec4.vert.html
+subtract_int_float.vert.html
+subtract_int_mat2.vert.html
+subtract_int_mat3.vert.html
+subtract_int_mat4.vert.html
+subtract_int_vec2.vert.html
+subtract_int_vec3.vert.html
+subtract_int_vec4.vert.html
+subtract_ivec2_vec2.vert.html
+subtract_ivec3_vec3.vert.html
+subtract_ivec4_vec4.vert.html
+ternary_int_float.vert.html
+ternary_ivec2_vec2.vert.html
+ternary_ivec3_vec3.vert.html
+ternary_ivec4_vec4.vert.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_float.vert.html
new file mode 100644
index 0000000000..6805834dcd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to float should fail
+void main()
+{
+ float f = 1.0 + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat2.vert.html
new file mode 100644
index 0000000000..89eed34cc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to mat2 should fail
+void main()
+{
+ mat2 f = mat2(1.0) + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat3.vert.html
new file mode 100644
index 0000000000..6a921d4012
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to mat3 should fail
+void main()
+{
+ mat3 f = mat3(1.0) + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat4.vert.html
new file mode 100644
index 0000000000..17c134d096
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_mat4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to mat4 should fail
+void main()
+{
+ mat4 f = mat4(1.0) + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec2.vert.html
new file mode 100644
index 0000000000..d985b77e74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to vec2 should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec3.vert.html
new file mode 100644
index 0000000000..2db9028769
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to vec3 should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec4.vert.html
new file mode 100644
index 0000000000..6cca2d9887
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_int_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding integer to vec4 should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) + 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..86cd54eb5d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding ivec2 to vec2 should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) + ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..dfcbe64110
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding ivec3 to vec3 should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) + ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..54c55be4f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/add_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast adding ivec4 to vec4 should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) + ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_int_to_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_int_to_float.vert.html
new file mode 100644
index 0000000000..d3f835e218
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_int_to_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast assing int to float should fail
+void main()
+{
+ float f = -123;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html
new file mode 100644
index 0000000000..ccaed7e041
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast assigning ivec2 to vec2 should fail
+void main()
+{
+ vec2 f = ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html
new file mode 100644
index 0000000000..35f0ee4029
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast assigning ivec3 to vec3 should fail
+void main()
+{
+ vec3 f = ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html
new file mode 100644
index 0000000000..8745a50f50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast assigning ivec4 to vec4 should fail
+void main()
+{
+ vec4 f = ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/construct_struct.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/construct_struct.vert.html
new file mode 100644
index 0000000000..c62dc731f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/construct_struct.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast from int to float in struct initializer should fail
+struct Foo {
+ float bar;
+};
+
+void main() {
+ Foo foo = Foo(1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_float.vert.html
new file mode 100644
index 0000000000..902b2e9669
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of float divided by int should fail
+void main()
+{
+ float f = 1.0 / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat2.vert.html
new file mode 100644
index 0000000000..ac7a547249
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of mat2 divided by int should fail
+void main()
+{
+ mat2 f = mat2(1.0) / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat3.vert.html
new file mode 100644
index 0000000000..2ad85937a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of mat3 divided by int should fail
+void main()
+{
+ mat3 f = mat3(1.0) / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat4.vert.html
new file mode 100644
index 0000000000..df22909191
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_mat4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of mat4 divided by int should fail
+void main()
+{
+ mat4 f = mat4(1.0) / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec2.vert.html
new file mode 100644
index 0000000000..545ca3e341
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of vec2 divided by int should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec3.vert.html
new file mode 100644
index 0000000000..fa80b9836a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of vec3 divided by int should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec4.vert.html
new file mode 100644
index 0000000000..136de073c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_int_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of vec4 divided by int should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) / 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..de88cd680b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of vec2 divided by ivec2 should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) / ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..99e8a69a09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of vec3 divided by ivec3 should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) / ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..2039ba9e1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/divide_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of vec4 divided by ivec4 should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) / ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_int_float.vert.html
new file mode 100644
index 0000000000..ebfdb6ae54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float in comparision should fail
+void main()
+{
+ bool b = 1.0 == 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..8d16edde32
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec2 to vec2 in comparision should fail
+void main()
+{
+ bool b = vec2(1.0, 2.0) == ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..a6951cb77f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec3 to vec3 in comparision should fail
+void main()
+{
+ bool b = vec3(1.0, 2.0, 3.0) == ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..39bdbafee2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/equal_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec4 to vec4 in comparision should fail
+void main()
+{
+ bool b = vec4(1.0, 2.0, 3.0, 4.0) == ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_int_float.vert.html
new file mode 100644
index 0000000000..0a20eeab37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_int_float.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float in function argument should fail
+float foo(float f) {
+ return f;
+}
+
+void main() {
+ float f = foo(1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..d4401c25c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec2_vec2.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec2 to vec2 in function argument should fail
+vec2 foo(vec2 f) {
+ return f;
+}
+
+void main() {
+ vec2 f = foo(ivec2(1, 2));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..1658ac5de8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec3_vec3.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec3 to vec3 in function argument should fail
+vec3 foo(vec3 f) {
+ return f;
+}
+
+void main() {
+ vec3 f = foo(ivec3(1, 2, 3));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..87e49c503d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/function_ivec4_vec4.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec4 to vec4 in function argument should fail
+vec4 foo(vec4 f) {
+ return f;
+}
+
+void main() {
+ vec4 f = foo(ivec4(1, 2, 3, 4));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than.vert.html
new file mode 100644
index 0000000000..73c2164a08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float with greater than should fail
+void main()
+{
+ bool b = 1.0 > 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than_equal.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than_equal.vert.html
new file mode 100644
index 0000000000..58dfe5ed77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/greater_than_equal.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float with greater than or equal to should fail
+void main()
+{
+ bool b = 1.0 >= 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than.vert.html
new file mode 100644
index 0000000000..c1addc6316
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float with less than should fail
+void main()
+{
+ bool b = 1.0 < 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than_equal.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than_equal.vert.html
new file mode 100644
index 0000000000..a4a7573e40
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/less_than_equal.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float with less than or equal to should fail
+void main()
+{
+ bool b = 1.0 <= 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_float.vert.html
new file mode 100644
index 0000000000..5e14dba1af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float in multiply should fail
+void main()
+{
+ float f = 1.0 * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat2.vert.html
new file mode 100644
index 0000000000..36ec2ae995
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to mat2 in multiply should fail
+void main()
+{
+ mat2 f = mat2(1.0) * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat3.vert.html
new file mode 100644
index 0000000000..a44379ccd7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to mat3 in multiply should fail
+void main()
+{
+ mat3 f = mat3(1.0) * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat4.vert.html
new file mode 100644
index 0000000000..f33d147f36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_mat4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to mat4 in multiply should fail
+void main()
+{
+ mat4 f = mat4(1.0) * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec2.vert.html
new file mode 100644
index 0000000000..ff83c9a657
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to vec2 in multiply should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec3.vert.html
new file mode 100644
index 0000000000..a39872f21f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to vec3 in multiply should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec4.vert.html
new file mode 100644
index 0000000000..8543b6d410
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_int_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to vec4 in multiply should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) * 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..03d797a333
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec2 to vec2 in multiply should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) * ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..92951c42f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec3 to vec3 in multiply should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) * ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..c5b3ce4741
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/multiply_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec4 to vec4 in multiply should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) * ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_int_float.vert.html
new file mode 100644
index 0000000000..9a87af0ae4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float in not equal comparison should fail
+void main()
+{
+ bool b = 1.0 != 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..81984c9cca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec2 to vec2 in not equal comparison should fail
+void main()
+{
+ bool b = vec2(1.0, 2.0) != ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..3b1acc1527
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec3 to vec3 in not equal comparison should fail
+void main()
+{
+ bool b = vec3(1.0, 2.0, 3.0) != ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..a28210486c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec4 to vec4 in not equal comparison should fail
+void main()
+{
+ bool b = vec4(1.0, 2.0, 3.0, 4.0) != ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_float.vert.html
new file mode 100644
index 0000000000..0a9ee88498
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float in subtraction should fail
+void main()
+{
+ float f = 1.0 - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat2.vert.html
new file mode 100644
index 0000000000..c6ac5e3fc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to mat2 in subtraction should fail
+void main()
+{
+ mat2 f = mat2(1.0) - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat3.vert.html
new file mode 100644
index 0000000000..bb04a9094b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to mat3 in subtraction should fail
+void main()
+{
+ mat3 f = mat3(1.0) - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat4.vert.html
new file mode 100644
index 0000000000..e1dc2807b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_mat4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to mat4 in subtraction should fail
+void main()
+{
+ mat4 f = mat4(1.0) - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec2.vert.html
new file mode 100644
index 0000000000..0a89e5f4e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to vec2 in subtraction should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec3.vert.html
new file mode 100644
index 0000000000..ec0fdc673b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to vec3 in subtraction should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec4.vert.html
new file mode 100644
index 0000000000..fc53e4ae55
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_int_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to vec4 in subtraction should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) - 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..770384258a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec2 to vec2 in subtraction should fail
+void main()
+{
+ vec2 f = vec2(1.0, 2.0) - ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..1203b09a3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec3 to vec3 in subtraction should fail
+void main()
+{
+ vec3 f = vec3(1.0, 2.0, 3.0) - ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..e440bec91f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/subtract_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec4 to vec4 in subtraction should fail
+void main()
+{
+ vec4 f = vec4(1.0, 2.0, 3.0, 4.0) - ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_int_float.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_int_float.vert.html
new file mode 100644
index 0000000000..7898bb92e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_int_float.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of int to float in ternary expression should fail
+void main()
+{
+ float f = true ? 1.0 : 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec2_vec2.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec2_vec2.vert.html
new file mode 100644
index 0000000000..08dca0cc02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec2_vec2.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec2 to vec2 in ternary expression should fail
+void main()
+{
+ vec2 f = true ? vec2(1.0, 2.0) : ivec2(1, 2);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec3_vec3.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec3_vec3.vert.html
new file mode 100644
index 0000000000..a281e59296
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec3_vec3.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec3 to vec3 in ternary expression should fail
+void main()
+{
+ vec3 f = true ? vec3(1.0, 2.0, 3.0) : ivec3(1, 2, 3);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec4_vec4.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec4_vec4.vert.html
new file mode 100644
index 0000000000..ba2b669b8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/implicit/ternary_ivec4_vec4.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// implicit cast of ivec4 to vec4 in ternary expression should fail
+void main()
+{
+ vec4 f = true ? vec4(1.0, 2.0, 3.0, 4.0) : ivec4(1, 2, 3, 4);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/00_test_list.txt
new file mode 100644
index 0000000000..50802bf346
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/00_test_list.txt
@@ -0,0 +1,3 @@
+float_literal.vert.html
+--min-version 1.0.3 literal_precision.html
+overflow_leak.vert.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/float_literal.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/float_literal.vert.html
new file mode 100644
index 0000000000..86bbf8a883
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/float_literal.vert.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// parsing floating point literals should succeed
+void main() {
+ float zero = 0.0;
+ float fractionalConstant = 1.0;
+ float fractionalConstantExponent = 1.0e1;
+ float fractionalConstantPosExponent = 1.0e+1;
+ float fractionalConstantNegExponent = 1.0e-1;
+ float digitSequenceExponent = 1e1;
+ float digitSequencePosExponent = 1e+1;
+ float digitSequenceNegExponent = 1e-1;
+ float pointDigit = .1;
+ float digitPoint= 1.;
+ float upperCaseExponent = 1.0E1;
+ highp float posInRange = 4611686018427387903.; // 2^62 - 1
+ highp float posOutRange = 4611686018427387905.; // 2^62 + 1
+ highp float posHuge = 1E100;
+ highp float negInRange = -4611686018427387903.;
+ highp float negOutRange = -4611686018427387905.;
+ highp float negHuge = -1E100;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/literal_precision.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/literal_precision.html
new file mode 100644
index 0000000000..c2ccbbe1ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/literal_precision.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// parsing floating point literals with precision should fail
+void main() {
+ mediump float zero = mediump 0.0;
+ gl_Position = vec4(zero, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/overflow_leak.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/overflow_leak.vert.html
new file mode 100644
index 0000000000..b11960dd5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/literals/overflow_leak.vert.html
@@ -0,0 +1,61 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+// float literal overflow should not affect next literal parsing.
+precision mediump float;
+
+varying vec4 v_color;
+attribute vec4 a_position;
+void main() {
+ highp float floatOverflow = 1E100;
+ int i = 10;
+ if (i == 10)
+ v_color = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ v_color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 v_color;
+void main() {
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+wtu.setupUnitQuad(gl);
+var program = wtu.setupProgram(gl, ["vshader", "fshader"]);
+if (!program)
+ testFailed("Fail to setup program");
+wtu.clearAndDrawUnitQuad(gl);
+wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/00_test_list.txt
new file mode 100644
index 0000000000..74693de0ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/00_test_list.txt
@@ -0,0 +1,3 @@
+glsl-mat4-to-mat3.html
+--min-version 1.0.3 glsl-mat3-construction.html
+--min-version 1.0.4 matrix-compound-multiply.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat3-construction.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat3-construction.html
new file mode 100644
index 0000000000..bca1bdb706
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat3-construction.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mat3 construction test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="shader_emu" type="something-not-js">
+mat3 mat3_emu(vec3 v3_0, vec3 v3_1, vec3 v3_2) {
+ mat3 test;
+ test[0] = v3_0;
+ test[1] = v3_1;
+ test[2] = v3_2;
+ return test;
+}
+</script>
+<script id="shader_test" type="something-not-js">
+ vec3 v3 = vec3($(input).xyz);
+ mat3 m3 = $(conversion)(v3, v3, v3);
+ vec3 c;
+ if ($(input).y < 0.33) {
+ c = m3[0];
+ } else if ($(input).y > 0.66) {
+ c = m3[1];
+ } else {
+ c = m3[2];
+ }
+ $(output) = vec4(c, 1);
+</script>
+<script>
+"use strict";
+// See resources glsl-generator runBasicTest for how this works
+var wtu = WebGLTestUtils;
+GLSLGenerator.runBasicTest({
+ gridRes: 8,
+ tests: [
+ {
+ name: "vec3 to mat3",
+ reference: {
+ shader: wtu.getScript("shader_test"),
+ subs: {
+ emu: wtu.getScript("shader_emu"),
+ conversion: "mat3_emu"
+ }
+ },
+ test: {
+ shader: wtu.getScript("shader_test"),
+ subs: {
+ conversion: "mat3"
+ },
+ }
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat4-to-mat3.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat4-to-mat3.html
new file mode 100644
index 0000000000..4716c630cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/glsl-mat4-to-mat3.html
@@ -0,0 +1,70 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mat4 to mat3 test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-generator.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="shader_emu" type="something-not-js">
+mat3 mat3_emu(mat4 m4) {
+ return mat3(
+ m4[0][0], m4[0][1], m4[0][2],
+ m4[1][0], m4[1][1], m4[1][2],
+ m4[2][0], m4[2][1], m4[2][2]);
+}
+</script>
+<script id="shader_test" type="something-not-js">
+ mat4 m4 = mat4($(input), $(input).yzwx, $(input).zwxy, $(input).wxyz);
+ mat3 m3 = $(conversion)(m4);
+ vec3 c;
+ if ($(input).y < 0.33) {
+ c = m3[0];
+ } else if ($(input).y > 0.66) {
+ c = m3[1];
+ } else {
+ c = m3[2];
+ }
+ $(output) = vec4(c, 1);
+</script>
+<script>
+"use strict";
+// See resources glsl-generator runBasicTest for how this works
+var wtu = WebGLTestUtils;
+GLSLGenerator.runBasicTest({
+ gridRes: 8,
+ tests: [
+ {
+ name: "mat4 to mat3",
+ reference: {
+ shader: wtu.getScript("shader_test"),
+ subs: {
+ emu: wtu.getScript("shader_emu"),
+ conversion: "mat3_emu"
+ }
+ },
+ test: {
+ shader: wtu.getScript("shader_test"),
+ subs: {
+ conversion: "mat3"
+ },
+ }
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/matrix-compound-multiply.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/matrix-compound-multiply.html
new file mode 100644
index 0000000000..a485160c56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/matrices/matrix-compound-multiply.html
@@ -0,0 +1,71 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Matrix compound multiplication test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ $(type) a = $(type)(0.0);
+ $(type) b = $(type)(0.0);
+ a[1][1] = 3.0; // 2nd column, 2nd row
+ b[0][1] = 2.0; // 1st column, 2nd row
+ $(type) c = a * b;
+ a *= b;
+ $(type) diffMat = a - c;
+ float diff = length(diffMat[0]) + length(diffMat[1]);
+ gl_FragColor = vec4(0.0, diff < 0.01 ? 1.0 : 0.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Matrix compound multiplication test comparing against normal multiplication.");
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ wtu.setupUnitQuad(gl);
+ var fshaderTemplate = wtu.getScript('fshader');
+
+ var types = ['mat2', 'mat3', 'mat4'];
+ for (var i = 0; i < types.length; ++i) {
+ debug('');
+ debug('Testing type ' + types[i]);
+ var fshaderSource = wtu.replaceParams(fshaderTemplate, {type: types[i]});
+ var program = wtu.setupProgram(gl, ['vshader', fshaderSource], ["aPosition"], undefined, true);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], 'should be green');
+ }
+};
+
+test();
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/00_test_list.txt
new file mode 100644
index 0000000000..c60310df14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/00_test_list.txt
@@ -0,0 +1,126 @@
+--max-version 1.9.9 attrib-location-length-limits.html
+--min-version 1.0.3 boolean_precision.html
+--min-version 1.0.4 const-variable-initialization.html
+embedded-struct-definitions-forbidden.html
+--min-version 1.0.4 empty-declaration.html
+empty_main.vert.html
+--min-version 1.0.3 expression-list-in-declarator-initializer.html
+--min-version 1.0.4 fragcolor-fragdata-invariant.html
+gl_position_unset.vert.html
+--min-version 1.0.4 global-variable-init.html
+# this test is intentionally disabled as it is too strict and to hard to simulate
+# glsl-2types-of-textures-on-same-unit.html
+glsl-function-nodes.html
+--min-version 1.0.2 glsl-vertex-branch.html
+glsl-long-variable-names.html
+--min-version 1.0.4 local-variable-shadowing-outer-function.html
+non-ascii-comments.vert.html
+non-ascii.vert.html
+--min-version 1.0.2 re-compile-re-link.html
+--min-version 1.0.4 sequence-operator-returns-constant.html
+--min-version 1.0.3 shader-precision-format-obeyed.html
+--min-version 1.0.3 shader-struct-scope.html
+--min-version 1.0.2 shader-uniform-packing-restrictions.html
+--min-version 1.0.2 shader-varying-packing-restrictions.html
+--min-version 1.0.2 shader-with-256-character-define.html
+shader-with-256-character-identifier.frag.html
+--min-version 1.0.2 --max-version 1.9.9 shader-with-257-character-define.html
+--max-version 1.9.9 shader-with-257-character-identifier.frag.html
+shader-with-_webgl-identifier.vert.html
+shader-with-arbitrary-indexing.frag.html
+shader-with-arbitrary-indexing.vert.html
+--min-version 1.0.2 shader-with-array-of-structs-containing-arrays.html
+--min-version 1.0.2 shader-with-array-of-structs-uniform.html
+shader-with-attrib-array.vert.html
+shader-with-attrib-struct.vert.html
+shader-with-clipvertex.vert.html
+--min-version 1.0.2 shader-with-conditional-scoping.html
+--min-version 1.0.2 shader-with-conditional-scoping-negative.html
+shader-with-default-precision.frag.html
+shader-with-default-precision.vert.html
+shader-with-dfdx-no-ext.frag.html
+shader-with-dfdx.frag.html
+--min-version 1.0.2 shader-with-do-loop.html
+shader-with-error-directive.html
+shader-with-explicit-int-cast.vert.html
+shader-with-float-return-value.frag.html
+--min-version 1.0.2 shader-with-for-scoping.html
+--min-version 1.0.2 shader-with-for-loop.html
+shader-with-frag-depth.frag.html
+shader-with-function-recursion.frag.html
+--min-version 1.0.2 shader-with-function-scoped-struct.html
+--min-version 1.0.2 shader-with-functional-scoping.html
+--min-version 1.0.2 shader-with-comma-assignment.html
+--min-version 1.0.2 shader-with-comma-conditional-assignment.html
+--min-version 1.0.4 shader-with-comma-separated-variable-declarations.html
+shader-with-glcolor.vert.html
+shader-with-gles-1.frag.html
+shader-with-gles-symbol.frag.html
+shader-with-glprojectionmatrix.vert.html
+shader-with-implicit-vec3-to-vec4-cast.vert.html
+shader-with-include.vert.html
+shader-with-int-return-value.frag.html
+shader-with-invalid-identifier.frag.html
+shader-with-ivec2-return-value.frag.html
+shader-with-ivec3-return-value.frag.html
+shader-with-ivec4-return-value.frag.html
+shader-with-limited-indexing.frag.html
+--min-version 1.0.2 shader-with-hex-int-constant-macro.html
+shader-with-long-line.html
+shader-with-non-ascii-error.frag.html
+--min-version 1.0.2 shader-with-non-reserved-words-1-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-2-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-3-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-4-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-5-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-6-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-7-of-8.html
+--min-version 1.0.2 shader-with-non-reserved-words-8-of-8.html
+shader-with-precision.frag.html
+--min-version 1.0.3 shader-with-preprocessor-whitespace.html
+shader-with-quoted-error.frag.html
+--min-version 1.0.2 shader-with-reserved-words.html
+--min-version 1.0.2 shader-with-similar-uniform-array-names.html
+--min-version 1.0.2 shader-with-too-many-uniforms.html
+--min-version 1.0.4 shader-with-two-initializer-types.html
+shader-with-undefined-preprocessor-symbol.frag.html
+shader-with-uniform-in-loop-condition.vert.html
+shader-with-vec2-return-value.frag.html
+shader-with-vec3-return-value.frag.html
+shader-with-vec4-return-value.frag.html
+--min-version 1.0.2 shader-with-vec4-vec3-vec4-conditional.html
+shader-with-version-100.frag.html
+shader-with-version-100.vert.html
+shader-with-version-120.vert.html
+shader-with-version-130.vert.html
+shader-with-webgl-identifier.vert.html
+--min-version 1.0.2 shader-with-while-loop.html
+shader-without-precision.frag.html
+--min-version 1.0.3 shaders-with-constant-expression-loop-conditions.html
+--min-version 1.0.3 shaders-with-invariance.html
+--min-version 1.0.3 shaders-with-name-conflicts.html
+--min-version 1.0.2 shaders-with-mis-matching-uniforms.html
+--min-version 1.0.2 shaders-with-mis-matching-varyings.html
+--min-version 1.0.2 shaders-with-missing-varyings.html
+--min-version 1.0.3 shaders-with-uniform-structs.html
+--min-version 1.0.2 shaders-with-varyings.html
+shared.html
+--min-version 1.0.4 struct-as-inout-parameter.html
+--min-version 1.0.4 struct-as-out-parameter.html
+struct-nesting-exceeds-maximum.html
+struct-nesting-under-maximum.html
+--max-version 1.9.9 uniform-location-length-limits.html
+--min-version 1.0.2 shader-with-short-circuiting-operators.html
+--min-version 1.0.2 shader-with-global-variable-precision-mismatch.html
+--min-version 1.0.2 large-loop-compile.html
+--min-version 1.0.3 struct-equals.html
+--min-version 1.0.4 struct-assign.html
+--min-version 1.0.3 struct-mixed-array-declarators.html
+--min-version 1.0.3 struct-nesting-of-variable-names.html
+--min-version 1.0.3 struct-specifiers-in-uniforms.html
+--min-version 1.0.3 struct-unary-operators.html
+--min-version 1.0.4 ternary-operator-on-arrays.html
+--min-version 1.0.3 ternary-operators-in-global-initializers.html
+--min-version 1.0.3 ternary-operators-in-initializers.html
+--min-version 1.0.4 uninitialized-local-global-variables.html
+--min-version 1.0.4 sampler-operand.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/attrib-location-length-limits.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/attrib-location-length-limits.html
new file mode 100644
index 0000000000..1f18a2309b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/attrib-location-length-limits.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<title>WebGL attrib location length tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+There is supposed to be an example drawing here, but it's not important.
+</canvas>
+<div id="description">Verify limits on the lengths of attribute locations per WebGL spec, "Maximum Uniform and Attribute Location Lengths".</div>
+<div id="console"></div>
+<script id="goodVertexShader" type="x-shader/x-vertex">
+// A vertex shader where the needed attrib location is exactly 256 characters.
+attribute vec4 vPosition0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456;
+
+void main()
+{
+ gl_Position = vPosition0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456;
+}
+</script>
+<script id="badVertexShader" type="x-shader/x-vertex">
+// A vertex shader where the needed attrib location is 257 characters.
+attribute vec4 vPosition01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567;
+
+void main()
+{
+ gl_Position = vPosition01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567;
+}
+</script>
+<script id="fragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description("test attrib location length limit");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+debug("Test attrib location underneath the length limit");
+var program = wtu.loadProgramFromScript(gl, "goodVertexShader", "fragmentShader");
+shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+var attrib256Name = "vPosition0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456";
+gl.bindAttribLocation(program, 0, attrib256Name);
+wtu.glErrorShouldBe(gl, gl.NONE);
+var attribLoc = gl.getAttribLocation(program, attrib256Name);
+if (attribLoc == -1) {
+ testFailed("attrib location was -1, should not be");
+} else {
+ testPassed("attrib location should not be -1");
+}
+wtu.glErrorShouldBe(gl, gl.NONE);
+
+debug("Test attrib location over the length limit");
+var attrib257Name = attrib256Name + "7";
+
+debug("Shader compilation or link should fail");
+shouldBe('wtu.loadProgramFromScriptExpectError(gl, "badVertexShader", "fragmentShader")', 'null');
+wtu.glErrorShouldBe(gl, gl.NONE);
+
+debug("Attempt to bind too-long attrib location should produce error");
+program = gl.createProgram();
+gl.bindAttribLocation(program, 0, attrib257Name);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+debug("Attempt to fetch too-long attrib location should produce error");
+program = wtu.loadStandardProgram(gl);
+shouldBe('gl.getAttribLocation(program, attrib257Name)', '-1');
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/boolean_precision.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/boolean_precision.html
new file mode 100644
index 0000000000..da0c55a164
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/boolean_precision.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexTest" type="text/something-not-javascript">
+// parsing boolean variables with precision should fail
+void main() {
+ mediump $(type) fail = $(initializer);
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fragmentTest" type="text/something-not-javascript">
+// parsing boolean variables with precision should fail
+void main() {
+ mediump $(type) fail = $(initializer);
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+var types = ['bool', 'bvec2', 'bvec3', 'bvec4'];
+var tests = [];
+var vTestSource = wtu.getScript("vertexTest");
+var fTestSource = wtu.getScript("fragmentTest");
+
+for (var i = 0; i < types.length; ++i) {
+ var initializer = 'true';
+ if (types[i] !== 'bool') {
+ initializer = types[i] + "(true";
+ for (var j = 0; j < i; ++j) {
+ initializer += ", true";
+ }
+ initializer += ")";
+ }
+ var subs = {type: types[i], initializer: initializer};
+ tests.push({
+ vShaderSource: wtu.replaceParams(vTestSource, subs),
+ vShaderSuccess: false,
+ passMsg: "vertex shader with a " + types[i] + " variable with precision should fail."
+ });
+ tests.push({
+ fShaderSource: wtu.replaceParams(fTestSource, subs),
+ fShaderSuccess: false,
+ passMsg: "fragment shader with a " + types[i] + " variable with precision should fail."
+ });
+}
+GLSLConformanceTester.runTests(tests);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/const-variable-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/const-variable-initialization.html
new file mode 100644
index 0000000000..f9d8be7f70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/const-variable-initialization.html
@@ -0,0 +1,244 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>All valid constant expressions should be allowed in the initialization of const variables</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<script id="VertexTemplate" type="x-shader/x-vertex">
+precision mediump float;
+
+$(init)
+
+void main() {
+ const $(constType) c = $(constantExpression);
+ gl_Position = vec4(float(c$(constTypeToScalar)));
+}
+</script>
+<script id="FragmentTemplate" type="x-shader/x-fragment">
+precision mediump float;
+
+$(init)
+
+void main() {
+ const $(constType) c = $(constantExpression);
+ gl_FragColor = vec4(float(c$(constTypeToScalar)));
+}
+</script>
+</head>
+<body onload="runTest()">
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+
+// ESSL 1.00 spec section 4.3.2.
+// Initializers for const declarations must be a constant expression.
+
+// ESSL 1.00 spec section 5.10.
+// A constant expression is one of
+// * a literal value (e.g., 5 or true)
+// * a global or local variable qualified as const excluding function parameters
+// * an expression formed by an operator on operands that are constant expressions, including getting
+// an element of a constant vector or a constant matrix, or a field of a constant structure
+// * a constructor whose arguments are all constant expressions
+// * a built-in function call whose arguments are all constant expressions, with the exception of the
+// texture lookup functions.
+
+var binaryOpsGenTypeRValuesToGenType = [
+ '+',
+ '-',
+ '*',
+ '/'
+];
+
+var binaryOpsScalarsToBool = [
+ '<',
+ '>',
+ '<=',
+ '>='
+];
+
+var binaryOpsRValuesToBool = [
+ '==',
+ '!='
+];
+
+var binaryOpsBoolsToBool = [
+ '&&',
+ '^^',
+ '||'
+];
+
+var builtInsGenTypeToGenType = [
+ 'radians',
+ 'degrees',
+ 'sin',
+ 'cos',
+ 'tan',
+ 'asin',
+ 'acos',
+ 'atan',
+ 'exp',
+ 'log',
+ 'exp2',
+ 'log2',
+ 'sqrt',
+ 'inversesqrt',
+ 'abs',
+ 'sign',
+ 'floor',
+ 'ceil',
+ 'fract'
+];
+
+var builtIns2VecToBvec = [
+ 'lessThan',
+ 'lessThanEqual',
+ 'greaterThan',
+ 'greaterThanEqual',
+ 'equal',
+ 'notEqual'
+];
+
+var builtIns2GenTypeToGenType = [
+ 'atan',
+ 'pow',
+ 'mod',
+ 'min',
+ 'max',
+ 'step'
+];
+
+var runTest = function() {
+ var vsTemplate = document.getElementById('VertexTemplate').text;
+ var fsTemplate = document.getElementById('FragmentTemplate').text;
+
+ var tests = [];
+ var i;
+ var op;
+ var builtIn;
+
+ var pushTest = function(constType, constantExpression, expectSuccess, opt_init) {
+ if (opt_init === undefined) {
+ opt_init = '';
+ }
+ var constTypeToScalar = '';
+ if (constType.substring(0, 3) == 'vec' || constType.substring(1, 4) == 'vec') {
+ constTypeToScalar = '.x';
+ } else if (constType.substring(0, 3) == 'mat') {
+ constTypeToScalar = '[0].x';
+ } else if (constType == 'my_struct') {
+ constTypeToScalar = '.field';
+ }
+ var vs = wtu.replaceParams(vsTemplate, {constType: constType, constantExpression: constantExpression, constTypeToScalar: constTypeToScalar, init: opt_init});
+ var fs = wtu.replaceParams(fsTemplate, {constType: constType, constantExpression: constantExpression, constTypeToScalar: constTypeToScalar, init: opt_init});
+ tests.push({
+ vShaderSource: vs,
+ vShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Assigning " + constantExpression + " to a const in a vertex shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ tests.push({
+ fShaderSource: fs,
+ fShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Assigning " + constantExpression + " to a const in a fragment shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ }
+
+ // Handle some one of a kind cases first
+ pushTest('float', 'vec4(0.5).x', true);
+ pushTest('float', 'vec4(0.5)[0]', true);
+ pushTest('float', 'true ? 0.5 : 0.2', true);
+ pushTest('my_struct', 'my_struct(0.5, 0.2)', true, 'struct my_struct { float field; float field2; };');
+ pushTest('float', '(0.2, 0.5)', true);
+
+ pushTest('float', 'clamp(0.2, 0.3, 0.4)', true);
+ pushTest('float', 'mix(0.2, 0.3, 0.4)', true);
+ pushTest('float', 'smoothstep(0.2, 0.3, 0.4)', true);
+ pushTest('float', 'length(vec4(0.5))', true);
+ pushTest('float', 'distance(vec4(0.5), vec4(0.2))', true);
+ pushTest('float', 'dot(vec4(0.5), vec4(0.2))', true);
+ pushTest('vec3', 'cross(vec3(0.5), vec3(0.2))', true);
+ pushTest('vec4', 'normalize(vec4(0.5))', true);
+ pushTest('vec4', 'faceforward(vec4(0.2), vec4(0.3), vec4(0.4))', true);
+ pushTest('vec4', 'reflect(vec4(0.2), vec4(0.5))', true);
+ pushTest('vec4', 'refract(vec4(0.2), vec4(0.3), 0.4)', true);
+ pushTest('mat4', 'matrixCompMult(mat4(0.2), mat4(0.5))', true);
+
+ // Handle built-in constructors
+ for (i = 2; i <= 4; ++i) {
+ var vecType = 'vec' + i;
+ pushTest(vecType, vecType + '(0.5)', true);
+ pushTest('i' + vecType, 'i' + vecType + '(1)', true);
+ pushTest('b' + vecType, 'b' + vecType + '(true)', true);
+ pushTest('mat' + i, 'mat' + i + '(0.5)', true);
+ }
+
+ // Handle ops
+ for (i = 0; i < binaryOpsGenTypeRValuesToGenType.length; ++i) {
+ var op = binaryOpsGenTypeRValuesToGenType[i];
+ pushTest('float', '0.2 ' + op + ' 0.5', true);
+ pushTest('vec4', 'vec4(0.2) ' + op + ' vec4(0.5)', true);
+ pushTest('mat4', 'mat4(0.2) ' + op + ' mat4(0.5)', true);
+ }
+
+ for (i = 0; i < binaryOpsScalarsToBool.length; ++i) {
+ var op = binaryOpsScalarsToBool[i];
+ pushTest('bool', '0.2 ' + op + ' 0.5', true);
+ }
+
+ for (i = 0; i < binaryOpsRValuesToBool.length; ++i) {
+ var op = binaryOpsRValuesToBool[i];
+ pushTest('bool', '0.2 ' + op + ' 0.5', true);
+ pushTest('bool', 'vec4(0.2) ' + op + ' vec4(0.5)', true);
+ }
+
+ for (i = 0; i < binaryOpsBoolsToBool.length; ++i) {
+ var op = binaryOpsBoolsToBool[i];
+ pushTest('bool', 'false ' + op + ' true', true);
+ }
+
+ // Handle allowed built-ins
+ for (i = 0; i < builtInsGenTypeToGenType.length; ++i) {
+ builtIn = builtInsGenTypeToGenType[i];
+ pushTest('float', builtIn + '(0.5)', true);
+ pushTest('vec4', builtIn + '(vec4(0.5))', true);
+ }
+
+ for (i = 0; i < builtIns2VecToBvec.length; ++i) {
+ builtIn = builtIns2VecToBvec[i];
+ pushTest('bvec4', builtIn + '(vec4(0.2), vec4(0.5))', true);
+ }
+
+ for (i = 0; i < builtIns2GenTypeToGenType.length; ++i) {
+ builtIn = builtIns2GenTypeToGenType[i];
+ pushTest('float', builtIn + '(0.2, 0.5)', true);
+ pushTest('vec4', builtIn + '(vec4(0.2), vec4(0.5))', true);
+ }
+
+ // Include some expressions with a constant variable reference
+ pushTest('float', 'cc', true, 'const float cc = 0.5;');
+ pushTest('float', 'cc + cc2', true, 'const float cc = 0.5; const float cc2 = 0.2;');
+ pushTest('float', 'sqrt(cc)', true, 'const float cc = 0.5;');
+
+ GLSLConformanceTester.runTests(tests);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/embedded-struct-definitions-forbidden.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/embedded-struct-definitions-forbidden.html
new file mode 100644
index 0000000000..dc945fe2c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/embedded-struct-definitions-forbidden.html
@@ -0,0 +1,41 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// embedded structure definitions are forbidden per GLSL ES section 4.1.8, "Structures", and should fail
+struct nesting1 {
+ struct nesting2 {
+ vec4 vector;
+ } field2;
+};
+
+uniform nesting1 uniform1;
+void main()
+{
+ gl_Position = uniform1.field2.vector;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty-declaration.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty-declaration.html
new file mode 100644
index 0000000000..785180f7e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty-declaration.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - empty declarations</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexEmptyDeclaration" type="text/something-not-javascript">
+// Vertex shader with an empty declaration should succeed.
+// See shading language grammar rules init_declarator_list and single_declaration
+// in ESSL specs.
+// Empty declarations are a side effect of how grammar for structs is defined.
+void main() {
+ float;
+ gl_Position = vec4(0.0);
+}
+</script>
+<script id="vertexEmptyDeclarationPlus" type="text/something-not-javascript">
+// Vertex shader with an empty declaration followed by declarator should succeed.
+// See shading language grammar rules init_declarator_list and single_declaration
+// in ESSL specs.
+void main() {
+ float, a = 0.0;
+ gl_Position = vec4(a);
+}
+</script>
+<script id="vertexEmptyStructDeclarationPlus" type="text/something-not-javascript">
+// Vertex shader with an empty declaration followed by declarator should succeed.
+// See shading language grammar rules init_declarator_list and single_declaration
+// in ESSL specs.
+
+struct S {
+ float member;
+}, a;
+
+void main() {
+ a.member = 0.0;
+ gl_Position = vec4(a.member);
+}
+</script>
+<script id="vertexEmptyDeclarationInStruct" type="text/something-not-javascript">
+// Vertex shader with an empty declaration inside struct should fail.
+// In-struct declarations have different grammar from declarations outside structs.
+struct S {
+ float;
+ float a;
+};
+
+void main() {
+ gl_Position = vec4(0.0);
+}
+</script>
+<script id="vertexEmptyDeclarationPlusInStruct" type="text/something-not-javascript">
+// Vertex shader with an empty declaration inside struct should fail.
+// In-struct declarations have different grammar from declarations outside structs.
+struct S {
+ float, a;
+ float b;
+};
+
+void main() {
+ gl_Position = vec4(0.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ { vShaderId: 'vertexEmptyDeclaration',
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Vertex shader with an empty declaration should succeed'
+ },
+ { vShaderId: 'vertexEmptyDeclarationPlus',
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Vertex shader with an empty declaration followed by declarator should succeed'
+ },
+ { vShaderId: 'vertexEmptyStructDeclarationPlus',
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Vertex shader with an empty struct declaration followed by declarator should succeed'
+ },
+ { vShaderId: 'vertexEmptyDeclarationInStruct',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Vertex shader with an empty declaration in a struct should fail'
+ },
+ { vShaderId: 'vertexEmptyDeclarationPlusInStruct',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Vertex shader with an empty declaration followed by declarator in a struct should fail'
+ }
+]);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty_main.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty_main.vert.html
new file mode 100644
index 0000000000..b8c308d2d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/empty_main.vert.html
@@ -0,0 +1,33 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader with an empty main() should succeed
+void main() { }
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/expression-list-in-declarator-initializer.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/expression-list-in-declarator-initializer.html
new file mode 100644
index 0000000000..3db79d94e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/expression-list-in-declarator-initializer.html
@@ -0,0 +1,68 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title></title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+void main() {
+ $(type) a, b;
+ $(type) c = (b = $(initializer), a = b);
+ gl_FragColor = $(asVec4);
+}
+</script>
+<script>
+"use strict";
+description("Verifies expression lists in declarator initializers work correctly.");
+var tests = [];
+var wtu = WebGLTestUtils;
+var typeInfos = [
+ { type: 'float', initializer: '1.0', asVec4: 'vec4(0.0,$(var),0.0,1.0)' },
+ { type: 'vec2', initializer: 'vec2(0.0, 1.0)', asVec4: 'vec4($(var),0.0,1.0)' },
+ { type: 'vec3', initializer: 'vec3(0.0, 1.0, 0.0)', asVec4: 'vec4($(var),1.0)' },
+ { type: 'vec4', initializer: 'vec4(0.0, 1.0, 0.0, 1.0)', asVec4: '$(var)' },
+ { type: 'int', initializer: '1', asVec4: 'vec4(0.0,$(var),0.0,1.0)' },
+ { type: 'ivec2', initializer: 'ivec2(0, 1)', asVec4: 'vec4($(var),0.0,1.0)' },
+ { type: 'ivec3', initializer: 'ivec3(0, 1, 0)', asVec4: 'vec4($(var),1.0)' },
+ { type: 'ivec4', initializer: 'ivec4(0, 1, 0, 1)', asVec4: 'vec4($(var))' },
+ { type: 'bool', initializer: 'true', asVec4: 'vec4(0.0,$(var),0.0,1.0)' },
+ { type: 'bvec2', initializer: 'bvec2(false, true)', asVec4: 'vec4($(var),0.0,1.0)' },
+ { type: 'bvec3', initializer: 'bvec3(false, true, false)', asVec4: 'vec4($(var),1.0)' },
+ { type: 'bvec4', initializer: 'bvec4(false,true,false,true)',asVec4: 'vec4($(var))' },
+];
+// Ensure that each variable is properly initialized to green, not just c.
+['a', 'b', 'c'].forEach(function(varName) {
+ typeInfos.forEach(function (typeInfo) {
+ var replaceParams = {
+ type: typeInfo.type,
+ initializer: typeInfo.initializer,
+ asVec4: wtu.replaceParams(typeInfo.asVec4, {var: varName}),
+ };
+ tests.push({
+ fShaderSource: wtu.replaceParams(wtu.getScript('fragmentShader'), replaceParams),
+ passMsg: typeInfo.type + ' with contents of ' + varName + ' rendered',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render:true
+ });
+ });
+});
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/fragcolor-fragdata-invariant.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/fragcolor-fragdata-invariant.html
new file mode 100644
index 0000000000..d936872514
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/fragcolor-fragdata-invariant.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - gl_FragColor and gl_FragData both declared as invariant</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Declaring both gl_FragColor and gl_FragData invariant should succeed.
+precision mediump float;
+
+// Static write of both gl_FragColor and gl_FragData is disallowed. However, simply declaring a variable invariant is not really accessing the variable, so it should be ok.
+invariant gl_FragColor;
+invariant gl_FragData;
+
+void main()
+{
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/gl_position_unset.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/gl_position_unset.vert.html
new file mode 100644
index 0000000000..6e462c123a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/gl_position_unset.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader without gl_Position being written should succeed
+void main() {
+ vec4 a = vec4(0.0, 0.0, 0.0, 1.0);
+ float f = a.x;
+ a.y = f;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/global-variable-init.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/global-variable-init.html
new file mode 100644
index 0000000000..99e7417f69
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/global-variable-init.html
@@ -0,0 +1,323 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Global variable initializer restrictions</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="constGlobalShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+const float c = 1.0;
+float f = c;
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="globalShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+float c = 1.0;
+float f = c;
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="uniformShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+uniform float u;
+float f = u;
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="builtinFunctionShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+float c = 1.0;
+float f = sin(c);
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="builtinTextureFunctionShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+uniform sampler2D s;
+float f = texture2DLod(s, vec2(0.5, 0.5), 0.0).x;
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="attributeShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+float f = aPosition.x;
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="userDefinedFunctionShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+float foo() {
+ return 1.0;
+}
+float f = foo();
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="varyingShader" type="x-shader/x-fragment">
+precision mediump float;
+varying float v;
+float f = v;
+
+void main() {
+ gl_FragColor = vec4(f);
+}
+</script>
+<script id="globalLValueShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+float c = 1.0;
+float f = (c = 0.0);
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="globalLValueShader2" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+varying float v;
+
+float c = 1.0;
+float f = (c++);
+
+void main() {
+ v = f;
+ gl_Position = aPosition;
+}
+</script>
+<script id="globalNonConstTernary" type="x-shader/x-fragment">
+precision mediump float;
+float green = 1.0;
+float black = 0.0;
+float f = true ? green : black;
+
+void main() {
+ gl_FragColor = vec4(0.0, f, 0.0, 1.0);
+}
+</script>
+<script id="globalUniformTernary" type="x-shader/x-fragment">
+precision mediump float;
+uniform float u_zero;
+float green = 1.0 + u_zero;
+float f = true ? green : u_zero;
+
+void main() {
+ gl_FragColor = vec4(0.0, f, 0.0, 1.0);
+}
+</script>
+<script id="globalUniformTernary2" type="x-shader/x-fragment">
+precision mediump float;
+uniform float u_zero;
+float green = 1.0;
+float f = (u_zero < 0.1) ? green : 0.0;
+
+void main() {
+ gl_FragColor = vec4(0.0, f, 0.0, 1.0);
+}
+</script>
+<script id="globalUniformStruct" type="x-shader/x-fragment">
+precision mediump float;
+struct S {
+ float zero;
+ int one;
+};
+uniform S us;
+S s = us;
+
+void main() {
+ float green = (s.one == 1) ? 1.0 : 0.0;
+ gl_FragColor = vec4(0.0, green, 0.0, 1.0);
+}
+</script>
+<script id="builtInConstant" type="x-shader/x-fragment">
+precision mediump float;
+int i = gl_MaxFragmentUniformVectors;
+
+void main() {
+ float green = (i > 0) ? 1.0 : 0.0;
+ gl_FragColor = vec4(0.0, green, 0.0, 1.0);
+}
+</script>
+<script id="builtInNonConstant" type="x-shader/x-fragment">
+precision mediump float;
+vec4 v = gl_FragCoord;
+
+void main() {
+ gl_FragColor = v;
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "constGlobalShader",
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "A const global in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ vShaderId: "globalShader",
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Another global in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ vShaderId: "uniformShader",
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "A uniform in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ vShaderId: "builtinFunctionShader",
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "A built-in math function in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ vShaderId: "builtinTextureFunctionShader",
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "A texture lookup function in a global variable initializer should not be accepted by WebGL."
+ },
+ {
+ vShaderId: "attributeShader",
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "An attribute in a global variable initializer should not be accepted by WebGL."
+ },
+ {
+ vShaderId: "userDefinedFunctionShader",
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "A user-defined function call in a global variable initializer should not be accepted by WebGL."
+ },
+ {
+ vShaderId: "constGlobalShader",
+ vShaderSuccess: true,
+ fShaderId: "varyingShader",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "A varying in a global variable initializer should not be accepted by WebGL."
+ },
+ {
+ vShaderId: "globalLValueShader",
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Another global as an l-value in a global variable initializer should not be accepted by WebGL."
+ },
+ {
+ vShaderId: "globalLValueShader2",
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Another global as an l-value (parameter of ++) in a global variable initializer should not be accepted by WebGL."
+ },
+ {
+ fShaderId: "globalNonConstTernary",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Non-const global variables as operands for a ternary operator in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ fShaderId: "globalUniformTernary",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "A uniform as the second operand for a ternary operator in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ fShaderId: "globalUniformTernary2",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Referencing a uniform inside the first operand for a ternary operator in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ fShaderId: "globalUniformStruct",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ uniforms: [
+ { name: 'us.one', functionName: 'uniform1i', value: 1 }
+ ],
+ passMsg: "A global struct initialized with a uniform struct should be accepted by WebGL."
+ },
+ {
+ fShaderId: "builtInConstant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Referencing a built-in constant in a global variable initializer should be accepted by WebGL."
+ },
+ {
+ fShaderId: "builtInNonConstant",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Referencing a built-in non-constant in a global variable initializer should not be accepted by WebGL."
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
new file mode 100644
index 0000000000..1e8aebde39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
@@ -0,0 +1,132 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+<meta charset="utf-8">
+ <title>WebGL GLSL 2 types of textures on same unit conformance test.</title>
+ <link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+ <script src="../../../js/js-test-pre.js"></script>
+ <script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<canvas id="canvas2d" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D tex2d;
+uniform samplerCube texCube;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex2d, texCoord) +
+ textureCube(texCube, vec3(0,1,0));
+}
+</script>
+
+ <script>
+ "use strict";
+function init()
+{
+ description(
+ "Tests that using 2 types of textures on the same texture unit" +
+ "and referencing them both in the same program fails as per" +
+ "OpenGL ES 2.0.24 spec section 2.10.4, Samplers subsection.");
+
+ var canvas2d = document.getElementById("canvas2d");
+ var ctx2d = canvas2d.getContext("2d");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition", "texCoord0"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ -1, 1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ // Make texture unit 1 active.
+ gl.activeTexture(gl.TEXTURE1);
+
+ // Make a 2d texture
+ var tex2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+ ctx2d.fillStyle = "rgba(0, 0, 255, 255)";
+ ctx2d.fillRect(0, 0, 1, 1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+
+ // make a cube texture
+ var texCube = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ ctx2d.fillStyle = "rgba(0, 255, 0, 64)";
+ ctx2d.fillRect(0, 0, 1, 1);
+ 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 ii = 0; ii < targets.length; ++ii) {
+ gl.texImage2D(targets[ii], 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+ }
+
+ var tex2dLoc = gl.getUniformLocation(program, "tex2d");
+ var texCubeLoc = gl.getUniformLocation(program, "texCube");
+ gl.uniform1i(tex2dLoc, 1);
+ gl.uniform1i(texCubeLoc, 1);
+
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ for (var ii = 0; ii < 4; ++ii) {
+ var x = ii % 2;
+ var y = Math.floor(ii / 2);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "drawing with 2 different targets on the same texture unit should generate INVALID_VALUE");
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-function-nodes.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-function-nodes.html
new file mode 100644
index 0000000000..566356fc43
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-function-nodes.html
@@ -0,0 +1,134 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL function nodes Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+
+<script id="vshaderFunction" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+varying vec4 vColor;
+
+float sign_emu(float value) {
+ if (value == 0.0) return 0.0;
+ return value > 0.0 ? 1.0 : -1.0;
+}
+
+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);
+ vColor = vec4(
+ sign_emu(color.x * 2.0 - 1.0) * 0.5 + 0.5,
+ sign_emu(color.y * 2.0 - 1.0) * 0.5 + 0.5,
+ 0,
+ 1);
+}
+</script>
+
+<script id="vshaderMacro" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+varying vec4 vColor;
+
+#define sign_emu(value) ((value) == 0.0 ? 0.0 : ((value) > 0.0 ? 1.0 : -1.0))
+
+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);
+ vColor = vec4(
+ sign_emu(color.x * 2.0 - 1.0) * 0.5 + 0.5,
+ sign_emu(color.y * 2.0 - 1.0) * 0.5 + 0.5,
+ 0,
+ 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 vColor;
+void main()
+{
+ gl_FragColor = vColor;
+}
+</script>
+</head>
+<body>
+<canvas id="canvasFunction" width="50" height="50"></canvas>
+<canvas id="canvasMacro" width="50" height="50"></canvas>
+<div id="description">This tests against a Mac driver bug related to function calls.</div>
+<div id="console"></div>
+<script>
+"use strict";
+var width = 50;
+var height = 50;
+var wtu = WebGLTestUtils;
+
+function drawAndRead(canvasID, vshaderID, buffer)
+{
+ var gl = wtu.create3DContext(canvasID);
+ var program = wtu.setupProgram(gl, [vshaderID, "fshader"], ["aPosition"]);
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ 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.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ return true;
+}
+
+function compareRendering(buffer1, buffer2, tol)
+{
+ for (var i = 0; i < width * height * 4; ++i) {
+ if (Math.abs(buffer1[i] - buffer2[i]) > tol)
+ return false;
+ }
+ return true;
+}
+
+function init()
+{
+ description("tests function nodes");
+
+ var bufFunction = new Uint8Array(width * height * 4);
+ var bufMacro = new Uint8Array(width * height * 4);
+
+ if (drawAndRead("canvasFunction", "vshaderFunction", bufFunction) == false ||
+ drawAndRead("canvasMacro", "vshaderMacro", bufMacro) == false) {
+ testFailed("Setup failed");
+ } else {
+ if (compareRendering(bufFunction, bufMacro, 4) == false)
+ testFailed("Rendering results are different");
+ else
+ testPassed("Rendering results are the same");
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-vertex-branch.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-vertex-branch.html
new file mode 100644
index 0000000000..dee3597546
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/glsl-vertex-branch.html
@@ -0,0 +1,128 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL function nodes Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+
+<script id="vshaderNoBranch" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+uniform float redIntensity;
+
+varying vec4 vColor;
+
+float MADBug(float paramValue) {
+ float localVar = 1.0;
+ return 0.25 * ceil(localVar) + paramValue;
+}
+
+void main(void) {
+ gl_Position = vec4(aPosition, 1.0);
+ vColor = vec4(MADBug(redIntensity), 0., 0., 1.);
+}
+</script>
+
+<script id="vshaderBranch" type="x-shader/x-vertex">
+attribute vec3 aPosition;
+uniform float redIntensity;
+
+varying vec4 vColor;
+
+float MADBug(float paramValue) {
+ float localVar = 1.0;
+ return 0.25 * ceil(localVar) + paramValue;
+}
+
+void main(void) {
+ float condition = 42.;
+ if (condition == 0.) {}
+ gl_Position = vec4(aPosition, 1.0);
+ vColor = vec4(MADBug(redIntensity), 0., 0., 1.);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 vColor;
+void main()
+{
+ gl_FragColor = vColor;
+}
+</script>
+</head>
+<body>
+<canvas id="canvasNoBranch" width="50" height="50"></canvas>
+<canvas id="canvasBranch" width="50" height="50"></canvas>
+<div id="description">This tests against a Mac driver bug related to branches
+ inside of Vertex Shaders.</div>
+<div id="console"></div>
+<script>
+"use strict";
+var width = 50;
+var height = 50;
+var wtu = WebGLTestUtils;
+
+function drawAndRead(canvasID, vshaderID, buffer)
+{
+ var gl = wtu.create3DContext(canvasID);
+ var program = wtu.setupProgram(gl, [vshaderID, "fshader"], ["aPosition"]);
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -1,-1,0, 1,-1,0 ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var loc = gl.getUniformLocation(program, "redIntensity");
+ gl.uniform1f(loc, 0.75);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ return true;
+}
+
+function compareRendering(buffer1, buffer2, tol)
+{
+ for (var i = 0; i < width * height * 4; ++i) {
+ if (Math.abs(buffer1[i] - buffer2[i]) > tol)
+ return false;
+ }
+ return true;
+}
+
+function init()
+{
+ description("tests vertex shader with branch");
+
+ var bufBranch = new Uint8Array(width * height * 4);
+ var bufNoBranch = new Uint8Array(width * height * 4);
+
+ if (drawAndRead("canvasBranch", "vshaderBranch", bufBranch) == false ||
+ drawAndRead("canvasNoBranch", "vshaderNoBranch", bufNoBranch) == false) {
+ testFailed("Setup failed");
+ } else {
+ if (compareRendering(bufBranch, bufNoBranch, 4) == false)
+ testFailed("Rendering results are different");
+ else
+ testPassed("Rendering results are the same");
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/include.vs b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/include.vs
new file mode 100644
index 0000000000..50970e6ccf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/include.vs
@@ -0,0 +1,4 @@
+// Do not delete!
+// Needed to help glsl-conformance tests.
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/large-loop-compile.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/large-loop-compile.html
new file mode 100644
index 0000000000..1f096ec30f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/large-loop-compile.html
@@ -0,0 +1,172 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+attribute vec2 position;
+
+void main(){
+ gl_Position = vec4(position, 0.0, 1.0);
+}
+</script>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+uniform sampler2D source;
+
+mat3 front = mat3(
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0
+);
+
+mat3 back = mat3(
+ -1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, -1.0
+);
+
+mat3 left = mat3(
+ 0.0, 0.0, -1.0,
+ 0.0, 1.0, 0.0,
+ 1.0, 0.0, 0.0
+);
+
+mat3 right = mat3(
+ 0.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0,
+ -1.0, 0.0, 0.0
+);
+
+mat3 up = mat3(
+ 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0,
+ 0.0, -1.0, 0.0
+);
+
+mat3 down = mat3(
+ 1.0, 0.0, 0.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 1.0, 0.0
+);
+
+float coefficient(vec3 normal){
+ int index = int(gl_FragCoord.x);
+ float x = normal.x;
+ float y = normal.y;
+ float z = normal.z;
+
+ if(index==0){
+ return 1.0;
+ }
+ else if(index==1){
+ return y;
+ }
+ else if(index==2){
+ return z;
+ }
+ else if(index==3){
+ return x;
+ }
+ else if(index==4){
+ return x*y;
+ }
+ else if(index==5){
+ return y*z;
+ }
+ else if(index==6){
+ return 3.0*z*z - 1.0;
+ }
+ else if(index==7){
+ return x*z;
+ }
+ else{
+ return x*x - y*y;
+ }
+}
+
+vec3 sample(float cidx, mat3 side){
+ vec3 result = vec3(0.0);
+ float divider = 0.0;
+
+ for(int i=0; i<256; i++){
+ float x = mod(float(i), 16.0);
+ float y = float(i/16);
+ vec2 texcoord = (vec2(x+cidx*16.0, y+floor(gl_FragCoord.y)*16.0)+0.5)/6.0;
+ vec2 sidecoord = ((vec2(x,y)+vec2(0.5, 0.5))/vec2(16.0))*2.0-1.0;
+ vec3 normal = normalize(vec3(sidecoord, -1.0));
+ vec3 texel = texture2D(source, texcoord).rgb;
+ result += coefficient(side*normal) * texel * -normal.z;
+ divider += -normal.z;
+ }
+ return result/divider;
+}
+
+void main(){
+ vec3 result = (
+ //sample(0.0, front) +
+ //sample(1.0, back) +
+ sample(2.0, left) +
+ sample(3.0, right) +
+ sample(4.0, up) +
+ sample(5.0, down)
+ )/6.0;
+ gl_FragColor = vec4(result, 1.0);
+}
+</script>
+<script>
+"use strict";
+var receivedContextLost = false;
+description("Ensures that compilation of a large loop completes in a reasonable period of time and does not cause the WebGL context to be lost");
+var wtu = WebGLTestUtils;
+var canvas = document.createElement('canvas');
+canvas.width = 32;
+canvas.height = 32;
+canvas.addEventListener("webglcontextlost", function(e) {
+ testFailed("context was lost during shader compilation or linking");
+ receivedContextLost = true;
+});
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var startTime = Date.now();
+ wtu.setupProgram(gl, ["vertexShader", "fragmentShader"], undefined, undefined, true);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
+ var endTime = Date.now();
+
+ // Delay for some period to increase chances that context lost event will be delivered.
+ setTimeout(function() {
+ if (!receivedContextLost) {
+ testPassed("Large loop compiled and linked without terminating the WebGL context");
+ const timeString = `${endTime - startTime} ms`;
+ if (endTime - startTime < 7500) {
+ testPassed("Shader compilation completed in a reasonable amount of time: " + timeString);
+ } else {
+ testFailed("Shader compilation took an unreasonably long time: " + timeString);
+ }
+ }
+ finishTest();
+ }, 500);
+}
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/local-variable-shadowing-outer-function.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/local-variable-shadowing-outer-function.html
new file mode 100644
index 0000000000..4fb814c0d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/local-variable-shadowing-outer-function.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Test - Local Variable Shadowing Outer Function</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader must succeed
+attribute vec3 vertex;
+varying float interp;
+void main() {
+ interp = vertex.x;
+ gl_Position = vec4(vertex, 1.0);
+}
+</script>
+<script id="fragmentShader" type="text/something-not-javascript">
+// local variable shadowing outer function definition must succeed
+precision mediump float;
+
+varying float interp;
+
+float rsquared(float radius)
+{
+ return radius * radius;
+}
+
+void some_computation(float radius, out float bsdf) {
+ bsdf = 0.0;
+ float rsquared = rsquared(radius);
+ bsdf += rsquared;
+}
+
+void main() {
+ float comp;
+ some_computation(interp, comp);
+ gl_FragColor = vec4(comp, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii-comments.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii-comments.vert.html
new file mode 100644
index 0000000000..14d807ed71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii-comments.vert.html
@@ -0,0 +1,54 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/plain">
+Loading...
+</script>
+<script>
+"use strict";
+
+// Via `[].map.call(str, x => x.codePointAt(0));`
+let a = [12371,12428,12399,65313,65331,65315,65321,65321,12391,12399,12394,12356,12391,12377,12290];
+let b = [65332,65352,65353,65363,12288,65321,65363,12288,65326,65359,65364,12288,65313,65331,65315,65321,65321];
+a = String.fromCodePoint(...a);
+b = String.fromCodePoint(...b);
+
+// -
+
+vertexShader.textContent = `
+// Non ascii comments in source should succeed
+// ${a}
+// ${b}
+/*
+ * ${b}
+ */
+#define TEST 1 // ${b}
+void main() {
+ gl_Position = vec4(1,1,1,1); // ${b}
+} // ${b}
+`;
+
+// -
+
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii.vert.html
new file mode 100644
index 0000000000..7cc05b9354
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/non-ascii.vert.html
@@ -0,0 +1,54 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/plain">
+Loading...
+</script>
+<script>
+"use strict";
+
+// Via `[].map.call(str, x => x.codePointAt(0));`
+let a = [12371,12428,12399,65313,65331,65315,65321,65321,12391,12399,12394,12356,12391,12377,12290];
+let b = [65332,65352,65353,65363,12288,65321,65363,12288,65326,65359,65364,12288,65313,65331,65315,65321,65321];
+let c = [65326,65359,65364,65313,65331,65315,65321,65321];
+a = String.fromCodePoint(...a);
+b = String.fromCodePoint(...b);
+c = String.fromCodePoint(...c);
+
+// -
+
+vertexShader.textContent = `
+// Non ascii data in source should fail
+// See GLSL ES Spec 1.0.17 section 3.1 and 3.2
+// ${a}
+// ${b}
+uniform mat4 ${c};
+void main() {
+ gl_Position = vec4(1,1,1,1);
+}
+`;
+
+// -
+
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/re-compile-re-link.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/re-compile-re-link.html
new file mode 100644
index 0000000000..caed432120
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/re-compile-re-link.html
@@ -0,0 +1,150 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Re-Compile and Re-link Shader conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute float column;
+attribute float height;
+uniform float position;
+void main() {
+ gl_Position = vec4(mod(column - position, 1.0) * 2.0 - 1.0, height, 0, 1);
+}
+</script>
+
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1,0,0,1);
+}
+</script>
+<script id="fshader2" type="x-shader/x-fragment">
+precision mediump float;
+uniform float foobar;
+void main() {
+ gl_FragColor = vec4(1,0,foobar,1);
+}
+</script>
+<script id="vshaderB" type="not-js">
+attribute vec2 position;
+varying vec2 v_texCoord;
+void main() {
+ gl_Position = vec4(position, 0, 1);
+ v_texCoord = vec2(position * 0.5 + 0.5);
+}
+</script>
+<script id="fshaderB" type="not-js">
+precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D tex;
+void main() {
+ gl_FragColor = texture2D(tex, v_texCoord);
+}
+</script>
+
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var vsSource = document.getElementById("vshader").text;
+var fs1Source = document.getElementById("fshader1").text;
+var fs2Source = document.getElementById("fshader2").text;
+
+var vsSourceB = document.getElementById("vshaderB").text;
+var fsSourceB = document.getElementById("fshaderB").text;
+
+var vShader = gl.createShader(gl.VERTEX_SHADER);
+var fShader = gl.createShader(gl.FRAGMENT_SHADER);
+
+var vShaderB = gl.createShader(gl.VERTEX_SHADER);
+var fShaderB = gl.createShader(gl.FRAGMENT_SHADER);
+
+var program = gl.createProgram();
+var programB = gl.createProgram();
+
+gl.attachShader(program, vShader);
+gl.attachShader(program, fShader);
+
+gl.attachShader(programB, vShaderB);
+gl.attachShader(programB, fShaderB);
+
+var success;
+var shader;
+
+function checkShaderStatus(s) {
+ shader = s;
+ shouldBeTrue("success = gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
+ if (!success) {
+ debug("error: " + gl.getShaderInfoLog(shader));
+ }
+}
+
+var prg;
+function checkProgramStatus(p) {
+ prg = p;
+ shouldBeTrue("success = gl.getProgramParameter(prg, gl.LINK_STATUS)");
+ if (!success) {
+ debug("error: " + gl.getProgramInfoLog(prg));
+ }
+}
+
+for (var i = 0; i < 10; ++i) {
+ gl.shaderSource(vShader, vsSource);
+ gl.compileShader(vShader);
+ checkShaderStatus(vShader)
+ gl.shaderSource(fShader, fs1Source);
+ gl.compileShader(fShader);
+ checkShaderStatus(fShader)
+
+ gl.linkProgram(program);
+ checkProgramStatus(program)
+ gl.useProgram(program);
+
+ gl.shaderSource(vShaderB, vsSourceB);
+ gl.compileShader(vShaderB);
+ checkShaderStatus(vShaderB)
+ gl.shaderSource(fShaderB, fsSourceB);
+ gl.compileShader(fShaderB);
+ checkShaderStatus(fShaderB)
+
+ gl.linkProgram(programB);
+ checkProgramStatus(programB)
+
+ gl.useProgram(programB);
+}
+
+for (var i = 0; i < 10; ++i) {
+ // Now change the fragment shader
+ gl.shaderSource(fShader, fs2Source);
+ gl.compileShader(fShader);
+ checkShaderStatus(fShader)
+
+ // And re-link
+ gl.linkProgram(program);
+ checkProgramStatus(program)
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sampler-operand.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sampler-operand.html
new file mode 100644
index 0000000000..4b6d6c0bad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sampler-operand.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - sampler operands</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+// ESSL(1.00, 3.00, 3.10) section 4.1.7
+// Except for array indexing, structure field selection, and
+// parentheses, samplers are not allowed to be operands in expressions.
+</script>
+
+<script id="samplerAdding" type="x-shader/x-fragment">
+// This covers an ANGLE bug.
+// See https://bugs.chromium.org/p/angleproject/issues/detail?id=2028.
+uniform sampler2D s1;
+uniform sampler2D s2;
+void main() {
+ s1 + s2;
+}
+</script>
+
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ { fShaderId: 'samplerAdding',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Adding on samplers should fail'
+ },
+]);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sequence-operator-returns-constant.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sequence-operator-returns-constant.html
new file mode 100644
index 0000000000..8ea601f719
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/sequence-operator-returns-constant.html
@@ -0,0 +1,60 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Sequence operator returns constant test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader-const-expression" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ // RHS should be a constant expression (a compile-time constants) stated in section 4.3.2 from GLESSL 1.0.17
+ const float a = (0.0, 1.0);
+}
+</script>
+<script id="fshader-non-const-expression" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ float a[(2, 3)];
+}
+</script>
+<script>
+"use strict";
+description("Checks sequence operators returning constants and can be used as an array size.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+GLSLConformanceTester.runTests([
+{ fShaderId: 'fshader-const-expression',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Sequence operator can return a constant expression",
+},
+{ fShaderId: 'fshader-non-const-expression',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Sequence operator return value can be used as array size",
+},
+]);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-precision-format-obeyed.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-precision-format-obeyed.html
new file mode 100644
index 0000000000..4574846469
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-precision-format-obeyed.html
@@ -0,0 +1,83 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderWithHighPrecision" type="text/something-not-javascript">
+precision highp float;
+uniform vec4 constantColor;
+
+void main()
+{
+ gl_FragColor = constantColor;
+}
+</script>
+<script id="fshaderWhichCompilesWithHighp" type="text/something-not-javascript">
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+// Something which compiles
+#else
+somethingWhichDoesNotCompile();
+#endif
+
+void main()
+{
+ gl_FragColor = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fshaderWhichCompilesWithoutHighp" type="text/something-not-javascript">
+#ifndef GL_FRAGMENT_PRECISION_HIGH
+// Something which compiles
+#else
+somethingWhichDoesNotCompile();
+#endif
+
+void main()
+{
+ gl_FragColor = vec4(0, 0, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description("Checks that getShaderPrecisionFormat's return value matches whether highp is supported in fragment shaders.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var precision = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
+var highpSupported = (precision.rangeMin >= 62 && precision.rangeMax >= 62 && precision.precision >= 16);
+debug("highp is" + (highpSupported ? "" : " not") + " supported in fragment shaders");
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshaderWithHighPrecision',
+ fShaderSuccess: highpSupported,
+ linkSuccess: highpSupported,
+ passMsg: "getShaderPrecisionFormat's results agree with highp support in fragment shaders",
+},
+{
+ fShaderId: highpSupported ? 'fshaderWhichCompilesWithHighp' : 'fshaderWhichCompilesWithoutHighp',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "getShaderPrecisionFormat's results agree with definition of GL_FRAGMENT_PRECISION_HIGH",
+},
+]);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-struct-scope.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-struct-scope.html
new file mode 100644
index 0000000000..a04faf03b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-struct-scope.html
@@ -0,0 +1,231 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!-- author: Jamie Madill (jmadill at chromium) -->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Struct Scope Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs-1" type="x-shader/x-vertex">
+void main(void) {
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+
+ {
+ struct T {
+ int v1;
+ };
+
+ T x;
+ gl_Position.x += float(x.v1);
+ }
+
+ {
+ struct T {
+ float v2;
+ };
+
+ T x;
+ gl_Position.x += x.v2;
+ }
+
+}
+</script>
+
+<script id="shader-vs-2" type="x-shader/x-vertex">
+void main(void) {
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+
+ struct T {
+ int v1;
+ };
+
+ T x;
+ gl_Position.x += float(x.v1);
+
+ {
+ struct T {
+ float v2;
+ };
+
+ T x;
+ gl_Position.x += x.v2;
+ }
+
+}
+</script>
+
+<script id="shader-vs-3" type="x-shader/x-vertex">
+void main(void) {
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+
+ {
+ struct T {
+ int v1;
+ };
+
+ T x;
+ gl_Position.x += float(x.v1);
+ }
+
+ struct T {
+ float v2;
+ };
+
+ T x;
+ gl_Position.x += x.v2;
+}
+</script>
+
+<script id="shader-vs-bad" type="x-shader/x-vertex">
+void main(void) {
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+
+ struct T {
+ int v1;
+ };
+
+ T x;
+ gl_Position.x += float(x.v1);
+
+ struct T {
+ float v2;
+ };
+
+ T y;
+ gl_Position.x += y.v2;
+}
+</script>
+
+<script id="shader-vs-anglebug" type="x-shader/x-vertex">
+
+struct T_0 {
+ int v1;
+};
+
+void main(void) {
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+
+ struct T {
+ float v2;
+ };
+
+ T_0 x;
+ gl_Position.x += float(x.v1);
+
+ T y;
+ gl_Position.x += y.v2;
+}
+</script>
+
+<script id="shader-vs-masked-struct-variable" type="x-shader/x-vertex">
+
+struct T {
+ float f;
+};
+
+void main(void) {
+
+ T a;
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+
+ struct T {
+ float q;
+ };
+
+ gl_Position.x += a.f;
+
+ T b;
+ gl_Position.x += b.q;
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+precision mediump float;
+void main(void) {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+description("Testing struct definition scope");
+
+var wtu = WebGLTestUtils;
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "shader-vs-1",
+ vShaderSuccess: true,
+ fShaderId: "shader-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Two structs defined within non-overlapping scopes should be able to use the same name",
+ },
+ {
+ vShaderId: "shader-vs-2",
+ vShaderSuccess: true,
+ fShaderId: "shader-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "A struct defined inside a scope overrides a struct defined in a outer scope with the same name",
+ },
+ {
+ vShaderId: "shader-vs-3",
+ vShaderSuccess: true,
+ fShaderId: "shader-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "A struct can use the same name of another out-of-scope struct",
+ },
+ {
+ vShaderId: "shader-vs-bad",
+ vShaderSuccess: false,
+ fShaderId: "shader-fs",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "A struct can't be defined with the same name as another struct defined in the same scope",
+ },
+ {
+ vShaderId: "shader-vs-anglebug",
+ vShaderSuccess: true,
+ fShaderId: "shader-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Structs with appended underscored numbers don't cause link errors (ANGLE bug)",
+ },
+ {
+ vShaderId: "shader-vs-masked-struct-variable",
+ vShaderSuccess: true,
+ fShaderId: "shader-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Variables of masked outer scope struct work with inner scope struct",
+ },
+]);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-uniform-packing-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-uniform-packing-restrictions.html
new file mode 100644
index 0000000000..22a968470f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-uniform-packing-restrictions.html
@@ -0,0 +1,251 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform packing restrctions Conformance Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-vertex">
+precision mediump float;
+varying vec4 v_varying;
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="vshaderArrayTest" type="x-shader/x-vertex">
+attribute vec4 a_position;
+varying vec4 v_varying;
+uniform $(type) u_uniform[$(numTestType)];
+void main()
+{
+ v_varying = $(result);
+ gl_Position = a_position;
+}
+</script>
+<script id="fshaderArrayTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform $(type) u_uniform[$(numTestType)];
+void main()
+{
+ gl_FragColor = $(result);
+}
+</script>
+<script id="vshaderUniformTest" type="x-shader/x-fragment">
+attribute vec4 a_position;
+varying vec4 v_varying;
+$(uniforms)
+void main()
+{
+ $(code)
+ v_varying = $(result);
+ gl_Position = a_position;
+}
+</script>
+<script id="fshaderUniformTest" type="x-shader/x-fragment">
+precision mediump float;
+$(uniforms)
+void main()
+{
+ $(code)
+ gl_FragColor = $(result);
+}
+</script>
+<script>
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var uniformTypes = [
+ { type: "bool", componentsPerRow: 1, rows: 1, fType: "float", uniToF: "float(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0, 0)"},
+ { type: "float", componentsPerRow: 1, rows: 1, fType: "float", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0, 0, 0)"},
+ { type: "int", componentsPerRow: 1, rows: 1, fType: "float", uniToF: "float(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0, 0)"},
+ { type: "vec2", componentsPerRow: 2, rows: 1, fType: "vec2", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0, 0)"},
+ { type: "ivec2", componentsPerRow: 2, rows: 1, fType: "vec2", uniToF: "vec2(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0)"},
+ { type: "bvec2", componentsPerRow: 2, rows: 1, fType: "vec2", uniToF: "vec2(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0)"},
+ { type: "vec3", componentsPerRow: 3, rows: 1, fType: "vec3", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0)"},
+ { type: "ivec3", componentsPerRow: 3, rows: 1, fType: "vec3", uniToF: "vec3(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0)"},
+ { type: "bvec3", componentsPerRow: 3, rows: 1, fType: "vec3", uniToF: "vec3(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0)"},
+ { type: "vec4", componentsPerRow: 4, rows: 1, fType: "vec4", uniToF: "u_uniform$(id)$(index)", fToVec4: "$(f)"},
+ { type: "ivec4", componentsPerRow: 4, rows: 1, fType: "vec4", uniToF: "vec4(u_uniform$(id)$(index))", fToVec4: "$(f)"},
+ { type: "bvec4", componentsPerRow: 4, rows: 1, fType: "vec4", uniToF: "vec4(u_uniform$(id)$(index))", fToVec4: "$(f)"},
+// Yes, the spec says mat2 takes 4 columns, 2 rows.
+ { type: "mat2", componentsPerRow: 4, rows: 2, fType: "vec2", uniToF: "vec2(u_uniform$(id)$(index)[0])", fToVec4: "vec4($(f), 0, 0)"},
+ { type: "mat3", componentsPerRow: 3, rows: 3, fType: "vec3", uniToF: "vec3(u_uniform$(id)$(index)[0])", fToVec4: "vec4($(f), 0)"},
+ { type: "mat4", componentsPerRow: 4, rows: 4, fType: "vec4", uniToF: "vec4(u_uniform$(id)$(index)[0])", fToVec4: "$(f)"},
+// Samplers generally have more restrictive limits.
+// { type: "sampler2D", componentsPerRow: 1, rows: 1, code: "vec4(texture2D(u_uniform[$(index)], vec2(0, 0)))", },
+// { type: "samplerCube", componentsPerRow: 1, rows: 1, code: "vec4(textureCube(u_uniform[$(index)], vec3(0, 0, 0)))", },
+];
+
+var vBaseSource = wtu.getScript("vshader");
+var fBaseSource = wtu.getScript("fshader");
+var vArrayTestSource = wtu.getScript("vshaderArrayTest");
+var fArrayTestSource = wtu.getScript("fshaderArrayTest");
+var vUniformTestSource = wtu.getScript("vshaderUniformTest");
+var fUniformTestSource = wtu.getScript("fshaderUniformTest");
+
+var tests = [];
+var shaderTypes = [
+ { type: "vertex",
+ // For tests that expect failure which shader might fail.
+ vertExpectation: false,
+ fragExpectation: true,
+ vertArrayTest: vArrayTestSource,
+ fragArrayTest: fBaseSource,
+ vertUniformTest: vUniformTestSource,
+ fragUniformTest: fBaseSource,
+ maxVectors: gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS),
+ minVectors: 127, // GLSL ES 1.0.17 Appendix A.7 and A.8. Reserve one row for constants in the code, hence 128 - 1.
+ },
+ { type: "fragment",
+ // For tests that expect failure which shader might fail.
+ vertExpectation: true,
+ fragExpectation: false,
+ vertArrayTest: vBaseSource,
+ fragArrayTest: fArrayTestSource,
+ vertUniformTest: vBaseSource,
+ fragUniformTest: fUniformTestSource,
+ maxVectors: gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS),
+ minVectors: 15, // GLSL ES 1.0.17 Appendix A.8 - minimum value of gl_maxFragmentUniformVectors is 16. Again, reserve a row for constants.
+ },
+];
+for (var ss = 0; ss < shaderTypes.length; ++ss) {
+ var shaderType = shaderTypes[ss];
+ debug("max " + shaderType.type + ": " + shaderType.maxVectors);
+ for (var ii = 0; ii < uniformTypes.length; ++ii) {
+ var info = uniformTypes[ii];
+ wtu.log("checking: " + info.type);
+ // Compute the maximum amount of this type allowed in a single array.
+ var maxInArray = Math.floor(shaderType.maxVectors / info.rows);
+ // Compute the minimum required to work in a single array.
+ var minVars = Math.floor(shaderType.minVectors / info.rows);
+ // Compute the maximum allowed as single elements
+ var maxPerRow = Math.floor(4 / info.componentsPerRow);
+ var maxPacked = Math.floor(shaderType.maxVectors * maxPerRow / info.rows);
+
+ // Test array[1] of the type
+ var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[0]"});
+ var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: 1, result: vec4}, info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: 1, result: vec4}, info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: shaderType.type + " shader with uniform array of " + info.type + " with 1 element should succeed",
+ });
+
+ // Note: We can't test an array filling all uniform space as actual GL drivers are
+ // only required to be able to do the minimum number. After that it can fail for
+ // multiple reasons, including uniform registers being reserved for the implementation's
+ // own use. Constants also take up uniform registers.
+
+ // Test required number of uniforms
+ var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[" + (minVars - 1) + "]"});
+ var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: minVars, result: vec4}, info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: minVars, result: vec4}, info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + minVars + " elements (the minimum required) should succeed",
+ });
+
+ // Test array[max + 1] accessing last element. WebGL requires this to fail.
+ var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[" + maxInArray + "]"});
+ var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
+ vShaderSuccess: shaderType.vertExpectation,
+ fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
+ fShaderSuccess: shaderType.fragExpectation,
+ linkSuccess: false,
+ passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + (maxInArray + 1) + " elements (one past maximum) accessing last element should fail",
+ });
+
+ // Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
+ var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[0]"});
+ var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
+ vShaderSuccess: shaderType.vertExpectation,
+ fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
+ fShaderSuccess: shaderType.fragExpectation,
+ linkSuccess: false,
+ passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + (maxInArray + 1) + " elements (one past maximum) accessing first element should fail",
+ });
+
+ // Note: We can't test max uniforms as actual GL drivers are only required to be able
+ // to do the minimum number. After that it can fail for multiple reasons, including
+ // uniform registers being reserved for the implementation's own use or also instruction
+ // space limitations. Strictly speaking, guaranteed supported length of a shader
+ // executable is defined by the GLES2 conformance tests according to GLSL ES 1.0.17
+ // Appendix A.2. This does not give us an exact limit: this test only aims to fit within
+ // instruction space limits imposed by existing GLES2 compliant hardware.
+
+ var generateCode = function(numVars) {
+ var uniforms = [];
+ var sumTerms = [];
+ for (var uu = 0; uu < numVars; ++uu) {
+ uniforms.push(" uniform " + info.type + " u_uniform" + uu + ";");
+ sumTerms.push(wtu.replaceParams(info.uniToF, {id: uu, index: ""}));
+ }
+ return {
+ uniforms: uniforms.join("\n"),
+ code: info.fType + " sum = " + sumTerms.join(" + \n ") + ";",
+ result: wtu.replaceParams(info.fToVec4, {f: 'sum'})
+ };
+ };
+
+ // Test max+1 uniforms of type.
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(maxPacked + 1), info),
+ vShaderSuccess: shaderType.vertExpectation,
+ fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(maxPacked + 1), info),
+ fShaderSuccess: shaderType.fragExpectation,
+ linkSuccess: false,
+ passMsg: shaderType.type + " shader with " + (maxPacked + 1) + " uniforms of " + info.type + " (one past maximum) should fail",
+ });
+
+ // Test required uniforms of type.
+ tests.push({
+ vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(minVars), info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(minVars), info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: shaderType.type + " shader with " + minVars + " uniforms of " + info.type + " (the minimum required) should succeed",
+ });
+ }
+}
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-varying-packing-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-varying-packing-restrictions.html
new file mode 100644
index 0000000000..741ad7b63f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-varying-packing-restrictions.html
@@ -0,0 +1,188 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL varying packing restrictions Conformance Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshaderArrayTest" type="x-shader/x-vertex">
+attribute vec4 a_position;
+varying $(type) v_varying[$(numTestType)];
+void main()
+{
+ gl_Position = a_position;
+ $(vcode)
+}
+</script>
+<script id="fshaderArrayTest" type="x-shader/x-fragment">
+precision mediump float;
+varying $(type) v_varying[$(numTestType)];
+void main()
+{
+ gl_FragColor = $(fcode);
+}
+</script>
+<script id="vshaderVaryingTest" type="x-shader/x-fragment">
+attribute vec4 a_position;
+$(varyings)
+void main()
+{
+ gl_Position = a_position;
+ $(vcode)
+}
+</script>
+<script id="fshaderVaryingTest" type="x-shader/x-fragment">
+precision mediump float;
+$(varyings)
+void main()
+{
+ gl_FragColor = $(fcode);
+}
+</script>
+<script>
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var varyingTypes = [
+ { type: "float", componentsPerRow: 1, rows: 1, vcode: "v_varying$(id)$(index) = 1.0;", fcode: "vec4(v_varying$(id)$(index), 0, 0, 0)", },
+ { type: "vec2", componentsPerRow: 2, rows: 1, vcode: "v_varying$(id)$(index) = vec2(0, 0);", fcode: "vec4(v_varying$(id)$(index), 0, 0)", },
+ { type: "vec3", componentsPerRow: 3, rows: 1, vcode: "v_varying$(id)$(index) = vec3(0, 0, 0);", fcode: "vec4(v_varying$(id)$(index), 0)", },
+ { type: "vec4", componentsPerRow: 4, rows: 1, vcode: "v_varying$(id)$(index) = vec4(0, 0, 0, 0);", fcode: "vec4(v_varying$(id)$(index))", },
+// Yes, the spec says mat2 takes 4 columns, 2 rows.
+ { type: "mat2", componentsPerRow: 4, rows: 2, vcode: "v_varying$(id)$(index) = mat2(1.0);", fcode: "vec4(v_varying$(id)$(index)[0], 0, 0)", },
+ { type: "mat3", componentsPerRow: 3, rows: 3, vcode: "v_varying$(id)$(index) = mat3(1.0);", fcode: "vec4(v_varying$(id)$(index)[0], 0)", },
+ { type: "mat4", componentsPerRow: 4, rows: 4, vcode: "v_varying$(id)$(index) = mat4(1.0);", fcode: "vec4(v_varying$(id)$(index)[0])", },
+];
+
+var vArrayTestSource = wtu.getScript("vshaderArrayTest");
+var fArrayTestSource = wtu.getScript("fshaderArrayTest");
+var vVaryingTestSource = wtu.getScript("vshaderVaryingTest");
+var fVaryingTestSource = wtu.getScript("fshaderVaryingTest");
+
+var minVaryingVectors = 8;
+var maxVaryingVectors = gl.getParameter(gl.MAX_VARYING_VECTORS);
+var tests = [];
+
+for (var ii = 0; ii < varyingTypes.length; ++ii) {
+ var info = varyingTypes[ii];
+ wtu.log("checking: " + info.type);
+ // Compute the maximum amount of this type allowed in a single array.
+ var numVars = Math.floor(maxVaryingVectors / info.rows);
+ // Compute the minimum required to work in a single array.
+ var minVars = Math.floor(minVaryingVectors / info.rows);
+ // Compute the maximum allowed as single elements
+ var numPerRow = Math.floor(4 / info.componentsPerRow);
+ var numMax = Math.floor(maxVaryingVectors * numPerRow / info.rows);
+
+ // Test array[1] of the type
+ var vcode = wtu.replaceParams(info.vcode, {id: "", index: "[0]"});
+ var fcode = wtu.replaceParams(info.fcode, {id: "", index: "[0]"});
+ tests.push({
+ vShaderSource: wtu.replaceParams(vArrayTestSource, {numTestType: 1, vcode: vcode}, info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: 1, fcode: fcode}, info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "shaders with varying array of " + info.type + " with 1 element should succeed",
+ });
+
+ // Test required number of varyings
+ var vcode = wtu.replaceParams(info.vcode, {id: "", index: "[" + (minVars - 1) + "]"});
+ var fcode = wtu.replaceParams(info.fcode, {id: "", index: "[" + (minVars - 1) + "]"});
+ tests.push({
+ vShaderSource: wtu.replaceParams(vArrayTestSource, {numTestType: minVars, vcode: vcode}, info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: minVars, fcode: fcode}, info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "shaders with varying array of " + info.type + " with " + minVars + " elements (the minimum required) should succeed",
+ });
+
+ // Test array[max + 1] accessing last element. WebGL requires this to fail.
+ var vcode = wtu.replaceParams(info.vcode, {id: "", index: "[" + numVars + "]"});
+ var fcode = wtu.replaceParams(info.fcode, {id: "", index: "[" + numVars + "]"});
+ tests.push({
+ vShaderSource: wtu.replaceParams(vArrayTestSource, {numTestType: numVars + 1, vcode: vcode}, info),
+ vShaderSuccess: false,
+ fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "shaders with varying array of " + info.type + " with " + (numVars + 1) + " elements (one past maximum) accessing last element should fail",
+ });
+
+ // Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
+ var vcode = wtu.replaceParams(info.vcode, {id: "", index: "[0]"});
+ var fcode = wtu.replaceParams(info.fcode, {id: "", index: "[0]"});
+ tests.push({
+ vShaderSource: wtu.replaceParams(vArrayTestSource, {numTestType: numVars + 1, vcode: vcode}, info),
+ vShaderSuccess: false,
+ fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "shaders with varying array of " + info.type + " with " + (numVars + 1) + " elements (one past maximum) accessing first element should fail",
+ });
+
+ // Note: We can't test max varyings as actual GL drivers are only required to be able to
+ // do the minimum number. After that it can fail for any reason, for example running out of
+ // instruction space.
+
+ var generateCode = function(numVars) {
+ var varyings = [];
+ var vcodes = [];
+ var fcodes = [];
+ for (var uu = 0; uu < numVars; ++uu) {
+ varyings.push(" varying " + info.type + " v_varying" + uu + ";");
+ vcodes.push(wtu.replaceParams(info.vcode, {id: uu, index: ""}));
+ fcodes.push(wtu.replaceParams(info.fcode, {id: uu, index: ""}));
+ }
+ return {
+ varyings: varyings.join("\n"),
+ vcode: vcodes.join("\n "),
+ fcode: fcodes.join(" + \n "),
+ };
+ };
+
+ // Test max+1 varyings of type.
+ tests.push({
+ vShaderSource: wtu.replaceParams(vVaryingTestSource, generateCode(numMax + 1), info),
+ vShaderSuccess: false,
+ fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(numMax + 1), info),
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "shaders with " + (numMax + 1) + " varyings of " + info.type + " (one past maximum) should fail",
+ });
+
+ // Test required varyings of type.
+ tests.push({
+ vShaderSource: wtu.replaceParams(vVaryingTestSource, generateCode(minVars), info),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(minVars), info),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "shaders with " + minVars + " varyings of " + info.type + " (the minimum required) should succeed",
+ });
+}
+
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-define.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-define.html
new file mode 100644
index 0000000000..9ed15009b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-define.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses 256 character token in #define should succeed
+#define LEN_256_OK XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX
+
+void main()
+{
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-identifier.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-identifier.frag.html
new file mode 100644
index 0000000000..66112ded1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-256-character-identifier.frag.html
@@ -0,0 +1,105 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader256" type="text/something-not-javascript">
+// shader that uses 256 character identifier should succeed
+precision mediump float;
+uniform float a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345;
+void main()
+{
+ gl_FragColor = vec4(a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345,0.0,0.0,1.0);
+}
+</script>
+<script id="fragmentShader_before" type="text/something-not-javascript">
+// shader that uses 256 character identifier that starts with underscore should succeed
+precision mediump float;
+uniform float _a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234;
+void main()
+{
+ gl_FragColor = vec4(_a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234,0.0,0.0,1.0);
+}
+</script>
+<script id="fragmentShader_after" type="text/something-not-javascript">
+// shader that uses 256 character identifier that ends with underscore should succeed
+precision mediump float;
+uniform float a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234_;
+void main()
+{
+ gl_FragColor = vec4(a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234_,0.0,0.0,1.0);
+}
+</script>
+<script id="fragmentShader256_odd" type="text/something-not-javascript">
+// shader that uses 256 character identifier with odd characters as underscores should succeed
+precision mediump float;
+uniform float a_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_;
+void main()
+{
+ gl_FragColor = vec4(a_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_6_8_0_2_4_,0.0,0.0,1.0);
+}
+</script>
+<script id="fragmentShader256_even" type="text/something-not-javascript">
+// shader that uses 256 character identifier with even characters as underscores should succeed
+precision mediump float;
+uniform float a1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5;
+void main()
+{
+ gl_FragColor = vec4(a1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5_7_9_1_3_5,0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ {
+ fShaderId: 'fragmentShader256',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shader with 256 character identifier should succeed'
+ },
+ {
+ fShaderId: 'fragmentShader_before',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shader with 256 character identifier that starts with underscore should succeed'
+ },
+ {
+ fShaderId: 'fragmentShader_after',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shader with 256 character identifier that ends with underscore should succeed'
+ },
+ {
+ fShaderId: 'fragmentShader256_odd',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shader with 256 character identifier with odd characters as underscores should succeed'
+ },
+ {
+ fShaderId: 'fragmentShader256_even',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shader with 256 character identifier with even characters as underscores should succeed'
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-define.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-define.html
new file mode 100644
index 0000000000..0d43c280e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-define.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses 257 character token in #define should fail
+#define LEN_257_BAD XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX
+
+void main()
+{
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-identifier.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-identifier.frag.html
new file mode 100644
index 0000000000..e3b70e99e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-257-character-identifier.frag.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// shader that uses 257 character identifier should fail
+precision mediump float;
+uniform float a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456;
+void main()
+{
+ gl_FragColor = vec4(a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456,0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-_webgl-identifier.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-_webgl-identifier.vert.html
new file mode 100644
index 0000000000..cbd2191902
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-_webgl-identifier.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses _webgl identifier should fail
+attribute vec4 _webgl_vPosition;
+void main()
+{
+ gl_Position = _webgl_vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html
new file mode 100644
index 0000000000..778375dc01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html
@@ -0,0 +1,41 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with arbitrary indexing expression should fail
+// http://www.khronos.org/registry/webgl/specs/latest/#SUPPORTED_GLSL_CONSTRUCTS
+precision mediump float;
+
+uniform vec4 u_colors[8];
+varying float a_index;
+
+void main()
+{
+ int index = int(floor(a_index));
+ gl_FragColor = u_colors[index];
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html
new file mode 100644
index 0000000000..eedbf67244
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader with arbitrary indexing expression should succeed
+// http://www.khronos.org/registry/webgl/specs/latest/#SUPPORTED_GLSL_CONSTRUCTS
+uniform mat4 u_matrices[8];
+attribute vec4 a_vertex;
+attribute float a_index;
+
+void main()
+{
+ int index = int(floor(a_index));
+ gl_Position = u_matrices[index] * a_vertex;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-containing-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-containing-arrays.html
new file mode 100644
index 0000000000..e4acce11fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-containing-arrays.html
@@ -0,0 +1,133 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Array of Structs Containing Arrays</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader0" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color[2];
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = u_colors[0].color[0];
+}
+</script>
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color[2];
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = u_colors[0].color[1];
+}
+</script>
+<script id="fshader-with-one-element-arrays" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color[1];
+};
+uniform my_struct u_colors[1];
+void main(void) {
+ gl_FragColor = u_colors[0].color[0];
+}
+</script>
+<script id="fshader3" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color1[2];
+ vec4 color2[2];
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = u_colors[0].color1[0] + u_colors[0].color2[0] + u_colors[1].color1[1] +u_colors[1].color2[1];
+}
+</script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+wtu.setupUnitQuad(gl);
+
+for (var ii = 0; ii < 2; ++ii) {
+ var program = wtu.setupProgram(gl, ["vshader", "fshader" + ii], ["a_position"]);
+ var red_loc = gl.getUniformLocation(program, "u_colors[0].color[" + ii + "]");
+ var green_loc = gl.getUniformLocation(program, "u_colors[0].color[" + (1 - ii) + "]");
+ gl.uniform4fv(red_loc, [1, 0, 0, 1]);
+ gl.uniform4fv(green_loc, [0, 1, 0, 1]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red");
+}
+
+var program = wtu.setupProgram(gl, ["vshader", "fshader-with-one-element-arrays"], ["a_position"]);
+var green_loc = gl.getUniformLocation(program, "u_colors[0].color[0]");
+gl.uniform4fv(green_loc, [0, 1, 0, 1]);
+wtu.clearAndDrawUnitQuad(gl);
+wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green");
+
+var program = wtu.setupProgram(gl, ["vshader", "fshader3"], ["a_position"]);
+var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+shouldBe("numUniforms", "4");
+var uniforms = []
+for (var ii = 0; ii < numUniforms; ++ii) {
+ uniforms.push(gl.getActiveUniform(program, ii).name);
+}
+uniforms.sort();
+shouldBe("uniforms[0]", '"u_colors[0].color1[0]"');
+shouldBe("uniforms[1]", '"u_colors[0].color2[0]"');
+shouldBe("uniforms[2]", '"u_colors[1].color1[0]"');
+shouldBe("uniforms[3]", '"u_colors[1].color2[0]"');
+var loc00 = gl.getUniformLocation(program, "u_colors[0].color1");
+var loc01 = gl.getUniformLocation(program, "u_colors[0].color2");
+var loc10 = gl.getUniformLocation(program, "u_colors[1].color1");
+var loc11 = gl.getUniformLocation(program, "u_colors[1].color2");
+shouldBeTrue("loc00 != undefined");
+shouldBeTrue("loc01 != undefined");
+shouldBeTrue("loc10 != undefined");
+shouldBeTrue("loc11 != undefined");
+gl.uniform4fv(loc00, [1, 0, 0, 0]);
+gl.uniform4fv(loc01, [0, 1, 0, 0]);
+gl.uniform4fv(loc10, [0, 0, 0, 0, 0, 0, 1, 0]);
+gl.uniform4fv(loc11, [0, 0, 0, 0, 0, 0, 0, 1]);
+var loc101 = gl.getUniformLocation(program, "u_colors[1].color1[1]");
+var loc111 = gl.getUniformLocation(program, "u_colors[1].color2[1]");
+shouldBeTrue("loc101 != undefined");
+shouldBeTrue("loc111 != undefined");
+wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 0]);
+gl.uniform4fv(loc101, [0, 0, 0, 0]);
+gl.uniform4fv(loc111, [0, 0, 0, 0]);
+wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 0]);
+wtu.checkCanvas(gl, [255, 255, 0, 0], "Should be yellow");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-uniform.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-uniform.html
new file mode 100644
index 0000000000..87560e3e70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-array-of-structs-uniform.html
@@ -0,0 +1,145 @@
+
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Array of Structs Uniform</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader0" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color;
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = u_colors[0].color;
+}
+</script>
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color;
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = u_colors[1].color;
+}
+</script>
+<script id="fshader2" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec4 color1;
+ vec4 color2;
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = u_colors[0].color1 + u_colors[0].color2 + u_colors[1].color1 +u_colors[1].color2;
+}
+</script>
+<script id="fshader3" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ float r;
+ float g;
+ float b;
+ float a;
+};
+uniform my_struct u_colors[2];
+void main(void) {
+ gl_FragColor = vec4(u_colors[0].r, u_colors[0].g, u_colors[1].b, u_colors[1].a);
+}
+</script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+wtu.setupUnitQuad(gl);
+
+for (var ii = 0; ii < 2; ++ii) {
+ var program = wtu.setupProgram(gl, ["vshader", "fshader" + ii], ["a_position"]);
+ var red_loc = gl.getUniformLocation(program, "u_colors[" + ii + "].color");
+ var green_loc = gl.getUniformLocation(program, "u_colors[" + (1 - ii) + "].color");
+ gl.uniform4fv(red_loc, [1, 0, 0, 1]);
+ gl.uniform4fv(green_loc, [0, 1, 0, 1]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red");
+}
+
+var program = wtu.setupProgram(gl, ["vshader", "fshader2"], ["a_position"]);
+var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+shouldBe("numUniforms", "4");
+var uniforms = []
+for (var ii = 0; ii < numUniforms; ++ii) {
+ uniforms.push(gl.getActiveUniform(program, ii).name);
+}
+uniforms.sort();
+shouldBe("uniforms[0]", '"u_colors[0].color1"');
+shouldBe("uniforms[1]", '"u_colors[0].color2"');
+shouldBe("uniforms[2]", '"u_colors[1].color1"');
+shouldBe("uniforms[3]", '"u_colors[1].color2"');
+var loc00 = gl.getUniformLocation(program, "u_colors[0].color1");
+var loc01 = gl.getUniformLocation(program, "u_colors[0].color2");
+var loc10 = gl.getUniformLocation(program, "u_colors[1].color1");
+var loc11 = gl.getUniformLocation(program, "u_colors[1].color2");
+shouldBeTrue("loc00 != undefined");
+shouldBeTrue("loc01 != undefined");
+shouldBeTrue("loc10 != undefined");
+shouldBeTrue("loc11 != undefined");
+gl.uniform4fv(loc00, [1, 0, 0, 0]);
+gl.uniform4fv(loc01, [0, 1, 0, 0]);
+gl.uniform4fv(loc10, [0, 0, 1, 0]);
+gl.uniform4fv(loc11, [0, 0, 0, 1]);
+wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 0]);
+wtu.checkCanvas(gl, [255, 255, 255, 255], "Should be white");
+
+program = wtu.setupProgram(gl, ["vshader", "fshader3"], ["a_position"]);
+var loc0r = gl.getUniformLocation(program, "u_colors[0].r");
+var loc0g = gl.getUniformLocation(program, "u_colors[0].g");
+var loc0b = gl.getUniformLocation(program, "u_colors[0].b");
+var loc0a = gl.getUniformLocation(program, "u_colors[0].a");
+var loc1r = gl.getUniformLocation(program, "u_colors[1].r");
+var loc1g = gl.getUniformLocation(program, "u_colors[1].g");
+var loc1b = gl.getUniformLocation(program, "u_colors[1].b");
+var loc1a = gl.getUniformLocation(program, "u_colors[1].a");
+shouldBeTrue("loc0r != undefined");
+shouldBeTrue("loc0g != undefined");
+shouldBeTrue("loc1b != undefined");
+shouldBeTrue("loc1a != undefined");
+gl.uniform1f(loc0r, 1);
+gl.uniform1f(loc0g, 1);
+gl.uniform1f(loc1b, 1);
+gl.uniform1f(loc1a, 1);
+wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 0]);
+wtu.checkCanvas(gl, [255, 255, 255, 255], "Should be white");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-array.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-array.vert.html
new file mode 100644
index 0000000000..14b1ffb189
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-array.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses attribute array should fail as per GLSL page 110, appendix A, section 5
+attribute vec4 vPosition[2];
+void main()
+{
+ gl_Position = vPosition[0] + vPosition[1];
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-struct.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-struct.vert.html
new file mode 100644
index 0000000000..f8069d11b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-attrib-struct.vert.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses attribute struct should fail per GLSL ES section 4.4.3, "Attribute", p. 30
+struct UserType {
+ attribute vec4 position;
+};
+
+attribute UserType userAttr;
+void main()
+{
+ gl_Position = userAttr.position;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-clipvertex.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-clipvertex.vert.html
new file mode 100644
index 0000000000..3c9d302854
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-clipvertex.vert.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses gl_ClipVertex should fail
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+ gl_ClipVertex = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-assignment.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-assignment.html
new file mode 100644
index 0000000000..70816d4173
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-assignment.html
@@ -0,0 +1,41 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with comma assignment should succeed
+precision mediump float;
+void main() {
+ float a = 0.0;
+ float b = 0.0;
+ float c = 0.0;
+ float d = 0.0;
+ a = 1.1, b = 3.1;
+ c = 2.1, d = 4.1;
+ // Output green if successful, red if not.
+ gl_FragColor = ((a + b + c + d > 10.0) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runRenderTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-conditional-assignment.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-conditional-assignment.html
new file mode 100644
index 0000000000..ec672d569e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-conditional-assignment.html
@@ -0,0 +1,192 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShaderAGreaterThanBCheckR" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 3.0;
+ float b = 2.0;
+ float r = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (r = r0, a) : (r = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((r == r0) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderAGreaterThanBCheckAB" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 3.0;
+ float b = 2.0;
+ float r = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (r = r0, a) : (r = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((ab == a) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderAGreaterThanBCheckT0" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 3.0;
+ float b = 2.0;
+ float t0 = 0.0;
+ float t1 = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (t0 = r0, a) : (t1 = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((t0 == r0) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderAGreaterThanBCheckT1" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 3.0;
+ float b = 2.0;
+ float t0 = 0.0;
+ float t1 = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (t0 = r0, a) : (t1 = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((t1 == 0.0) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderBGreaterThanACheckR" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 2.0;
+ float b = 3.0;
+ float r = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (r = r0, a) : (r = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((r == r1) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderBGreaterThanACheckAB" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 2.0;
+ float b = 3.0;
+ float r = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (r = r0, a) : (r = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((ab == b) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderBGreaterThanACheckT0" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 2.0;
+ float b = 3.0;
+ float t0 = 0.0;
+ float t1 = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (t0 = r0, a) : (t1 = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((t0 == 0.0) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script id="fragmentShaderBGreaterThanACheckT1" type="text/something-not-javascript">
+// fragment shader with for scoping should succeed
+precision mediump float;
+void main() {
+ float a = 2.0;
+ float b = 3.0;
+ float t0 = 0.0;
+ float t1 = 0.0;
+ float r0 = 0.5;
+ float r1 = 1.0;
+ float ab = a > b ? (t0 = r0, a) : (t1 = r1, b);
+ // Output green if successful, red if not.
+ gl_FragColor = ((t1 == r1) ? vec4(0,1,0,1) : vec4(1,0,0,1));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fragmentShaderAGreaterThanBCheckR',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderAGreaterThanBCheckAB',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderAGreaterThanBCheckT0',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderAGreaterThanBCheckT1',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderBGreaterThanACheckR',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderBGreaterThanACheckAB',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderBGreaterThanACheckT0',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+},
+{
+ fShaderId: 'fragmentShaderBGreaterThanACheckT1',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "comma based conditional assignment works",
+}
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-separated-variable-declarations.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-separated-variable-declarations.html
new file mode 100644
index 0000000000..b63a10ae5d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-comma-separated-variable-declarations.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// shader with comma separated uniform variable declarations should succeed
+precision mediump float;
+
+uniform float x, y;
+
+void main() {
+ gl_FragColor = vec4(x, y, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping-negative.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping-negative.html
new file mode 100644
index 0000000000..7d5826cf9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping-negative.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with illegal references to conditionally scoped variables should fail
+precision mediump float;
+void main() {
+ int k = 3;
+
+ if (true) int g = k = 4;
+ else int q = k = 5;
+
+ g = 3; // should error
+ q = 4; // should error
+
+ gl_FragColor = vec4(1.);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping.html
new file mode 100644
index 0000000000..31b705dfea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-conditional-scoping.html
@@ -0,0 +1,45 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with conditional scoping should succeed
+precision mediump float;
+void main() {
+ int k = 3;
+
+ if (true) int g = k = 4;
+ else int q = k = 5;
+
+ if (true) int g = 4;
+ else int k = 10;
+
+ if (true) { int g = 10; }
+ else { int k = 20; }
+
+ gl_FragColor = vec4(1.);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.frag.html
new file mode 100644
index 0000000000..b03af46f4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.frag.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with default precision should succeed
+precision mediump float;
+precision mediump int;
+precision lowp sampler2D;
+precision lowp samplerCube;
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.vert.html
new file mode 100644
index 0000000000..a8f43ec6f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-default-precision.vert.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader with default precision should succeed
+precision mediump float;
+precision mediump int;
+precision lowp sampler2D;
+precision lowp samplerCube;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html
new file mode 100644
index 0000000000..50803c92ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that uses dFdx without #extension should fail
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx.frag.html
new file mode 100644
index 0000000000..0636867932
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-dfdx.frag.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that uses dFdx should fail
+#extension GL_OES_standard_derivatives:enable
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-do-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-do-loop.html
new file mode 100644
index 0000000000..76643dd3c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-do-loop.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with do loop should fail
+precision mediump float;
+void main() {
+ int k = 0;
+ do {
+ k++;
+ } while (k < 5);
+ gl_FragColor = vec4(float(k));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-error-directive.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-error-directive.html
new file mode 100644
index 0000000000..fec151fc81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-error-directive.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderWithErrorDirective" type="text/something-not-javascript">
+#error testing123 testing123
+void main()
+{
+ gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script>
+"use strict";
+description("Checks shader with error directive");
+
+var wtu = WebGLTestUtils;
+GLSLConformanceTester.runTests([
+{ vShaderId: undefined,
+ vShaderSuccess: true,
+ fShaderId: 'fshaderWithErrorDirective',
+ fShaderSuccess: false,
+ // We can't test for the actual error message as
+ // GLSL 1.0.17 11 says the messages are implementation dependant.
+ //fShaderTest: (function() {
+ // return wtu.getLastError().indexOf("testing123 testing123") >= 0; }),
+ linkSuccess: false,
+ passMsg: "error directive causes error",
+},
+]);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-explicit-int-cast.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-explicit-int-cast.vert.html
new file mode 100644
index 0000000000..908dc9fb03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-explicit-int-cast.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that explicit int to float cast should succeed
+attribute vec4 vPosition;
+void main()
+{
+ int k = 123;
+ gl_Position = vec4(vPosition.x, vPosition.y, vPosition.z, float(k));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-float-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-float-return-value.frag.html
new file mode 100644
index 0000000000..04362b86c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-float-return-value.frag.html
@@ -0,0 +1,46 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with float return value from function call should succeed
+precision mediump float;
+
+float functionResult();
+
+void main()
+{
+ float r = functionResult();
+ gl_FragColor = vec4(r, r, r, r);
+}
+
+float functionResult()
+{
+ return 1.0;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-loop.html
new file mode 100644
index 0000000000..cf11a88d9f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-loop.html
@@ -0,0 +1,83 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with for loop should succeed
+
+// TODO(gman): trim to min size to test bug.
+precision mediump float;
+uniform float time;
+uniform vec2 resolution;
+
+// Saw-tooth function that is synced with the demo music (128bpm)
+float gBeat;
+
+// Calculate the surface color
+vec3 surfColor(vec2 p)
+{
+ vec2 q=vec2(sin(.08*p.x),4.*p.y);
+ vec3 c=vec3(0);
+ for(float i=0.;i<15.;i++)
+ c+=(1.+sin(i*sin(time)+vec3(0.,1.3,2.2)))*.2/length(q-vec2(sin(i),12.*sin(.3*time+i)));
+ return c+vec3(mix(mod(floor(p.x*.2)+floor(p.y*2.2),2.),.2,gBeat));
+}
+
+// Ray trace (cylinder)
+vec3 trace(vec3 o,vec3 d)
+{
+ d.y*=.65+.1*sin(.5*time);
+ float D=1./(d.y*d.y+d.z*d.z),
+ a=(o.y*d.y+o.z*d.z)*D,
+ b=(o.y*o.y+o.z*o.z-36.)*D,
+ t=-a-sqrt(a*a-b);
+ o+=t*d;
+ return surfColor(vec2(o.x,atan(o.y,o.z)))*(1.+.01*t);
+}
+
+void main()
+{
+ gBeat=fract(time*3.2/3.);
+ // Screen setup
+ vec2 p=(2.*gl_FragCoord.xy-resolution)/resolution.y,
+ q=2.*gl_FragCoord.xy/resolution-1.;
+
+ // Camera setup
+ vec3 cp=vec3(-time*20.+1.,1.6*sin(time*1.2),2.+2.*cos(time*.3)),
+ ct=cp+vec3(1.,.3*cos(time),-.2),
+ cd=normalize(ct-cp),
+ cr=normalize(cross(cd,vec3(.5*cos(.3*time),0.,1.))),
+ cu=cross(cr,cd),
+ rd=normalize(2.*cd+cr*p.x+cu*p.y);
+
+ // Trace! (+some funky lens/raster effects)
+ vec3 c=trace(cp,rd)*
+ min(1.,1.8-dot(q,q))*
+ (.9+.1*sin(3.*sin(gBeat)*gl_FragCoord.y));
+
+ gl_FragColor=vec4(c,1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-scoping.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-scoping.html
new file mode 100644
index 0000000000..c4d9620fd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-for-scoping.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with illegal for scoping should fail
+precision mediump float;
+void main() {
+ int k = 0;
+ for (int i = 0; i < 10; i++) { int i = k+i; } // not a nested scope, in i's scope, nesting already happened
+ gl_FragColor = vec4(float(k));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-frag-depth.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-frag-depth.frag.html
new file mode 100644
index 0000000000..48454492c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-frag-depth.frag.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that uses gl_FragDepth should fail
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+ gl_FragDepth = 1.0;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-recursion.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-recursion.frag.html
new file mode 100644
index 0000000000..dfa12e471a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-recursion.frag.html
@@ -0,0 +1,45 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// shader with recursive function calls should fail
+void a();
+void b();
+void main()
+{
+ a();
+ gl_FragColor = vec4(0,0,0,0);
+}
+void a()
+{
+ b();
+}
+void b()
+{
+ a();
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-scoped-struct.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-scoped-struct.html
new file mode 100644
index 0000000000..be694ae5ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-function-scoped-struct.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with private function scoped struct should fail.
+precision mediump float;
+int fun2(struct s { int m; } g) { return g.m; }
+
+s a;
+
+void main() {
+ int e = fun2(s(3));
+
+ gl_FragColor = vec4(1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-functional-scoping.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-functional-scoping.html
new file mode 100644
index 0000000000..c18f3cc495
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-functional-scoping.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with invalid functional scoping should fail
+precision mediump float;
+int f(int k) {
+ int k = k + 3;
+ return k;
+}
+
+void main() {
+ gl_FragColor = vec4(f(100));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glcolor.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glcolor.vert.html
new file mode 100644
index 0000000000..52cd783902
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glcolor.vert.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses gl_Color should fail
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = gl_Color;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-1.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-1.frag.html
new file mode 100644
index 0000000000..bc8a7b3a8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-1.frag.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that expects GL_ES == 1 should succeed
+#if GL_ES == 1
+ precision mediump float;
+ void main()
+ {
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+ }
+#else
+ foo
+#endif
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-symbol.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-symbol.frag.html
new file mode 100644
index 0000000000..b569958f5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-gles-symbol.frag.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that uses GL_ES preprocessor symbol should succeed
+#if defined(GL_ES)
+ precision mediump float;
+ void main()
+ {
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+ }
+#else
+ foo
+#endif
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-global-variable-precision-mismatch.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-global-variable-precision-mismatch.html
new file mode 100644
index 0000000000..6303915f30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-global-variable-precision-mismatch.html
@@ -0,0 +1,128 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderWithMediumpGlobal" type="text/something-not-javascript">
+// There is no default float precision in fragment shaders, so specify mediump.
+precision mediump float;
+
+uniform vec4 foo;
+
+void main()
+{
+ gl_FragColor = foo;
+}
+</script>
+<script id="fshaderWithMediumpGlobalInt" type="text/something-not-javascript">
+// Default precision for int in fragment shaders is mediump.
+uniform int foo;
+
+void main()
+{
+ gl_FragColor = vec4(foo, 0, 0, 1);
+}
+</script>
+<script id="fshaderWithMediumpGlobalStruct" type="text/something-not-javascript">
+// There is no default float precision in fragment shaders, so specify mediump.
+precision mediump float;
+
+struct foo
+{
+ vec4 bar;
+};
+
+uniform foo baz;
+
+void main()
+{
+ gl_FragColor = baz.bar;
+}
+</script>
+<script id="vshaderWithHighpGlobal" type="x-shader/x-vertex">
+// Default precision for vertex shaders is highp.
+uniform vec4 foo;
+
+void main() {
+ gl_Position = foo;
+}
+</script>
+<script id="vshaderWithHighpGlobalInt" type="x-shader/x-vertex">
+// Default precision for int in vertex shaders is highp.
+uniform int foo;
+
+void main() {
+ gl_Position = vec4(foo, 0, 0, 1);
+}
+</script>
+<script id="vshaderWithHighpGlobalStruct" type="x-shader/x-vertex">
+// Default precision for vertex shaders is highp.
+struct foo
+{
+ vec4 bar;
+};
+
+uniform foo baz;
+
+void main()
+{
+ gl_Position = baz.bar;
+}
+</script>
+<script>
+"use strict";
+description("Checks shaders with global variables and precision qualifier mismatch.");
+
+var wtu = WebGLTestUtils;
+
+var glslTests = [];
+
+glslTests.push({
+ vShaderId: 'vshaderWithHighpGlobal',
+ vShaderSuccess: true,
+ fShaderId: 'fshaderWithMediumpGlobal',
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "mismatching precision for uniforms causes link error (as expected)",
+});
+
+glslTests.push({
+ vShaderId: 'vshaderWithHighpGlobalInt',
+ vShaderSuccess: true,
+ fShaderId: 'fshaderWithMediumpGlobalInt',
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "mismatching precision for int uniforms with default precision causes link error (as expected)",
+});
+
+glslTests.push({
+ vShaderId: 'vshaderWithHighpGlobalStruct',
+ vShaderSuccess: true,
+ fShaderId: 'fshaderWithMediumpGlobalStruct',
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "mismatching precision for structure uniforms causes link error (as expected)",
+});
+
+GLSLConformanceTester.runTests(glslTests);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html
new file mode 100644
index 0000000000..9387918f1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses gl_ProjectionMatrix should fail
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition * gl_ProjectionMatrix;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-hex-int-constant-macro.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-hex-int-constant-macro.html
new file mode 100644
index 0000000000..7a9ed875b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-hex-int-constant-macro.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader uses the long integer constant should succeed
+attribute vec4 vPosition;
+void main()
+{
+ #define TEST 0x1F
+ int a = TEST;
+
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.frag.html
new file mode 100644
index 0000000000..04902c50db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.frag.html
@@ -0,0 +1,238 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShaderVoid" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump void;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderBool" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump bool;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderVec2" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump vec2;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderVec3" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump vec3;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderVec4" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump vec4;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderBvec2" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump bvec2;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderBvec3" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump bvec3;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderBvec4" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump bvec4;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderIvec2" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump ivec2;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderIvec3" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump ivec3;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderIvec4" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump ivec4;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderMat2" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump mat2;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderMat3" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump mat3;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script id="fragmentShaderMat4" type="text/something-not-javascript">
+// fragment shader with default precision for illegal type should fail
+precision mediump mat4;
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ {
+ fShaderId: 'fragmentShaderVoid',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for void should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderBool',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bool should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderVec2',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for vec2 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderVec3',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for vec3 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderVec4',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for vec4 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderBvec2',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bvec2 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderBvec3',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bvec3 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderBvec4',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bvec4 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderIvec2',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for ivec2 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderIvec3',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for ivec3 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderIvec4',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for ivec4 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderMat2',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for mat2 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderMat3',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for mat3 should fail'
+ },
+ {
+ fShaderId: 'fragmentShaderMat4',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for mat4 should fail'
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.vert.html
new file mode 100644
index 0000000000..5710fddfd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-illegal-default-precision.vert.html
@@ -0,0 +1,224 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderVoid" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump void;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderBool" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump bool;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderVec2" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump vec2;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderVec3" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump vec3;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderVec4" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump vec4;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderBvec2" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump bvec2;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderBvec3" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump bvec3;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderBvec4" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump bvec4;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderIvec2" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump ivec2;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderIvec3" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump ivec3;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderIvec4" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump ivec4;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderMat2" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump mat2;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderMat3" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump mat3;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderMat4" type="text/something-not-javascript">
+// vertex shader with default precision for illegal type should fail
+precision mediump mat4;
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ { vShaderId: 'vertexShaderVoid',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for void should fail'
+ },
+ { vShaderId: 'vertexShaderBool',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bool should fail'
+ },
+ { vShaderId: 'vertexShaderVec2',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for vec2 should fail'
+ },
+ { vShaderId: 'vertexShaderVec3',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for vec3 should fail'
+ },
+ { vShaderId: 'vertexShaderVec4',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for vec4 should fail'
+ },
+ { vShaderId: 'vertexShaderBvec2',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bvec2 should fail'
+ },
+ { vShaderId: 'vertexShaderBvec3',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bvec3 should fail'
+ },
+ { vShaderId: 'vertexShaderBvec4',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for bvec4 should fail'
+ },
+ { vShaderId: 'vertexShaderIvec2',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for ivec2 should fail'
+ },
+ { vShaderId: 'vertexShaderIvec3',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for ivec3 should fail'
+ },
+ { vShaderId: 'vertexShaderIvec4',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for ivec4 should fail'
+ },
+ { vShaderId: 'vertexShaderMat2',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for mat2 should fail'
+ },
+ { vShaderId: 'vertexShaderMat3',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for mat3 should fail'
+ },
+ { vShaderId: 'vertexShaderMat4',
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'shader with default precision for mat4 should fail'
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html
new file mode 100644
index 0000000000..c77a3e1915
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that implicit vec3 to vec4 cast should fail
+attribute vec4 vPosition;
+void main()
+{
+ mediump vec3 k = vec3(1, 2, 3);
+ gl_Position = k;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-include.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-include.vert.html
new file mode 100644
index 0000000000..bc0cf93cc2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-include.vert.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader uses #include should fail
+
+// Sadly I can not force the current path so this could fail beacuse include.vs
+// does not exist, not because #include is disallowed.
+#include "include.vs"
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-int-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-int-return-value.frag.html
new file mode 100644
index 0000000000..7b4430c0f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-int-return-value.frag.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with int return value from function call should succeed
+int functionResult();
+
+void main()
+{
+ int r = functionResult();
+ gl_FragColor = vec4(r, r, r, r);
+}
+
+int functionResult()
+{
+ return 1;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-invalid-identifier.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-invalid-identifier.frag.html
new file mode 100644
index 0000000000..af918519c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-invalid-identifier.frag.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with gl_ identifier should fail
+precision mediump float;
+uniform float gl_foo;
+void main()
+{
+ gl_FragColor = vec4(gl_foo,0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec2-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec2-return-value.frag.html
new file mode 100644
index 0000000000..2445e7d3c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec2-return-value.frag.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with ivec2 return value from function call should succeed
+ivec2 functionResult();
+
+void main()
+{
+ ivec2 r = functionResult();
+ gl_FragColor = vec4(r.x, r.y, r.x, r.y);
+}
+
+ivec2 functionResult()
+{
+ return ivec2(1, 1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec3-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec3-return-value.frag.html
new file mode 100644
index 0000000000..c765ef9259
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec3-return-value.frag.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with ivec3 return value from function call should succeed
+ivec3 functionResult();
+
+void main()
+{
+ ivec3 r = functionResult();
+ gl_FragColor = vec4(r.x, r.y, r.z, r.x);
+}
+
+ivec3 functionResult()
+{
+ return ivec3(1, 1, 1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec4-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec4-return-value.frag.html
new file mode 100644
index 0000000000..77317d22e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-ivec4-return-value.frag.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with ivec4 return value from function call should succeed
+ivec4 functionResult();
+
+void main()
+{
+ ivec4 r = functionResult();
+ gl_FragColor = vec4(r.x, r.y, r.z, r.w);
+}
+
+ivec4 functionResult()
+{
+ return ivec4(1, 1, 1, 1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-limited-indexing.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-limited-indexing.frag.html
new file mode 100644
index 0000000000..df7401ef3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-limited-indexing.frag.html
@@ -0,0 +1,54 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader should succeed
+attribute vec4 a_weights;
+varying vec4 v_weights;
+
+void main() {
+ v_weights = a_weights;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with appropriately limited indexing expression should succeed
+// http://www.khronos.org/registry/webgl/specs/latest/#SUPPORTED_GLSL_CONSTRUCTS
+precision mediump float;
+
+uniform vec4 u_colors[8];
+varying vec4 v_weights;
+
+void main()
+{
+ vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < 4; i++) {
+ color += u_colors[i] * v_weights[i];
+ }
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-long-line.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-long-line.html
new file mode 100644
index 0000000000..4f22beb027
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-long-line.html
@@ -0,0 +1,67 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderWithLongLine" type="text/something-not-javascript">
+precision mediump float;
+uniform float fooo;
+#if defined(someSymbolNotDefined)
+#error long
+#endif
+void main()
+{
+ gl_FragColor = vec4(fooo+fooo+fooo+fooo, fooo+fooo+fooo+fooo, fooo+fooo+fooo+fooo, 1.0);
+}
+</script>
+<script>
+"use strict";
+description("checks shader with long line succeeds");
+
+var wtu = WebGLTestUtils;
+GLSLConformanceTester.runTests([
+ {
+ fShaderId: 'fshaderWithLongLine',
+ fShaderSuccess: true,
+ fShaderPrep: function(str) {
+ function expand(str, re, replacement, count) {
+ for (var ii = 0; ii < count; ++ii) {
+ str = str.replace(re, replacement);
+ }
+ return str;
+ }
+ str = expand(str, new RegExp(" ", 'g'), " ", 12);
+ var manyZeros = expand("0", new RegExp("0", 'g'), "00", 8).substring(2);
+ str = expand(str, new RegExp("0", 'g'), manyZeros, 1);
+ str = expand(str, new RegExp("fooo", 'g'), "fooofooo", 6);
+ str = expand(str, new RegExp("long", 'g'), "longlong", 6);
+ //debug("len:" + str.length);
+ //debug(str);
+ return str;
+ },
+ linkSuccess: true,
+ passMsg: 'shader that uses long lines should succeed',
+ }
+ ]);
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-ascii-error.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-ascii-error.frag.html
new file mode 100644
index 0000000000..b80cf3a995
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-ascii-error.frag.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// shader with error directive using characters outside of allowed set fails
+#error // will return INVALID_VALUE. See WebGL 6.18
+void main()
+{
+ gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-1-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-1-of-8.html
new file mode 100644
index 0000000000..f2f8bc674e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-1-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 1 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 1;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-2-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-2-of-8.html
new file mode 100644
index 0000000000..4be404a5d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-2-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 2 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 2;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-3-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-3-of-8.html
new file mode 100644
index 0000000000..58b8ab21d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-3-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 3 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 3;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-4-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-4-of-8.html
new file mode 100644
index 0000000000..4c2162970a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-4-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 4 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 4;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-5-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-5-of-8.html
new file mode 100644
index 0000000000..546cc04d84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-5-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 5 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 5;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-6-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-6-of-8.html
new file mode 100644
index 0000000000..7fad96cedc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-6-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 6 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 6;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-7-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-7-of-8.html
new file mode 100644
index 0000000000..b45abfe2bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-7-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 7 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 7;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-8-of-8.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-8-of-8.html
new file mode 100644
index 0000000000..f901cacc58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-non-reserved-words-8-of-8.html
@@ -0,0 +1,31 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Non Reserved Words 8 of 8</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/shader-with-non-reserved-words.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const numParts = 8;
+const part = 8;
+testNonReservedWords(part, numParts);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-precision.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-precision.frag.html
new file mode 100644
index 0000000000..536b66ec0b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-precision.frag.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with precision should succeed
+void main()
+{
+ mediump vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-preprocessor-whitespace.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-preprocessor-whitespace.html
new file mode 100644
index 0000000000..c8e31d5927
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-preprocessor-whitespace.html
@@ -0,0 +1,62 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexWhitespace" type="text/something-not-javascript">
+// GLSL ES spec section 3.4
+ # ifdef GL_ES
+attribute vec4 v_Position;
+void main()
+{
+ gl_Position = v_Position;
+}
+#endif
+</script>
+<script id="fragmentWhitespace" type="text/something-not-javascript">
+// GLSL ES spec section 3.4
+ # ifdef GL_ES
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+}
+#endif
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: 'vertexWhitespace',
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Vertex shader using space and tab characters around # should succeed'
+ },
+ {
+ fShaderId: 'fragmentWhitespace',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Fragment shader using space and tab characters around # should succeed'
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-quoted-error.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-quoted-error.frag.html
new file mode 100644
index 0000000000..c79315d3f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-quoted-error.frag.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// shader with error directive using quotes will fail
+#error "testing123 testing123" // will return INVALID_VALUE. See WebGL 6.18
+void main()
+{
+ gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-reserved-words.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-reserved-words.html
new file mode 100644
index 0000000000..fd6953e0fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-reserved-words.html
@@ -0,0 +1,263 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Reserved Words</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader0" type="text/something-not-javascript">
+struct $replaceMe {
+ vec4 $replaceMe;
+};
+struct Foo {
+ $replaceMe $replaceMe;
+};
+attribute vec4 position;
+void main()
+{
+ Foo f;
+ f.$replaceMe.$replaceMe = position;
+ gl_Position = f.$replaceMe.$replaceMe;
+}
+</script>
+<script id="fragmentShader0" type="text/something-not-javascript">
+precision mediump float;
+vec4 $replaceMe() {
+ return vec4(0,1,0,1);
+}
+void main()
+{
+ gl_FragColor = $replaceMe();
+}
+</script>
+<script id="vertexShader1" type="text/something-not-javascript">
+attribute vec4 $replaceMe;
+void main()
+{
+ gl_Position = $replaceMe;
+}
+</script>
+<script id="fragmentShader1" type="text/something-not-javascript">
+precision mediump float;
+vec4 foo(vec4 $replaceMe) {
+ return $replaceMe;
+}
+void main()
+{
+ gl_FragColor = foo(vec4(1,0,1,1));
+}
+</script>
+<script id="vertexShader2" type="text/something-not-javascript">
+varying vec4 $replaceMe;
+attribute vec4 position;
+void main()
+{
+ gl_Position = position;
+ $replaceMe = position;
+}
+</script>
+<script id="fragmentShader2" type="text/something-not-javascript">
+precision mediump float;
+varying vec4 $replaceMe;
+void main()
+{
+ gl_FragColor = $replaceMe;
+}
+</script>
+<script id="vertexShader3" type="text/something-not-javascript">
+attribute vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+</script>
+<script id="fragmentShader3" type="text/something-not-javascript">
+precision mediump float;
+uniform vec4 $replaceMe;
+void main()
+{
+ gl_FragColor = $replaceMe;
+}
+</script>
+<script>
+"use strict";
+var GLSL_1_0_17_words = [
+ "attribute",
+ "const",
+ "uniform",
+ "varying",
+ "break",
+ "continue",
+ "do",
+ "for",
+ "while",
+ "if",
+ "else",
+ "in",
+ "out",
+ "inout",
+ "float",
+ "int",
+ "void",
+ "bool",
+ "true",
+ "false",
+ "lowp",
+ "mediump",
+ "highp",
+ "precision",
+ "invariant",
+ "discard",
+ "return",
+ "mat2",
+ "mat3",
+ "mat4",
+ "vec2",
+ "vec3",
+ "vec4",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "sampler2D",
+ "samplerCube",
+ "struct"
+]
+
+var GLSL_1_0_17_FutureWords = [
+ "asm",
+ "class",
+ "union",
+ "enum",
+ "typedef",
+ "template",
+ "this",
+ "packed",
+ "goto",
+ "switch",
+ "default",
+ "inline",
+ "noinline",
+ "volatile",
+ "public",
+ "static",
+ "extern",
+ "external",
+ "interface",
+ "flat",
+ "long",
+ "short",
+ "double",
+ "half",
+ "fixed",
+ "unsigned",
+ "superp",
+ "input",
+ "output",
+ "hvec2",
+ "hvec3",
+ "hvec4",
+ "dvec2",
+ "dvec3",
+ "dvec4",
+ "fvec2",
+ "fvec3",
+ "fvec4",
+ "sampler1D",
+ "sampler3D",
+ "sampler1DShadow",
+ "sampler2DShadow",
+ "sampler2DRect",
+ "sampler3DRect",
+ "sampler2DRectShadow",
+ "sizeof",
+ "cast",
+ "namespace",
+ "using",
+ "__foo", // something that has 2 underscores
+ "foo__bar", // something that has 2 underscores
+ "gl_foo", // something that starts with gl_
+ "webgl_foo" // something that starts with webgl_
+];
+
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+var reservedWordsLists = [
+ GLSL_1_0_17_words,
+ GLSL_1_0_17_FutureWords
+];
+
+var reservedWords = [];
+for (var ii = 0; ii < reservedWordsLists.length; ++ii) {
+ var list = reservedWordsLists[ii];
+ for (var jj = 0; jj < list.length; ++jj) {
+ reservedWords.push(list[jj]);
+ }
+}
+
+var src = [];
+for (var ii = 0; ii < 4; ++ii) {
+ var vsrc = document.getElementById("vertexShader" + ii).text;
+ var fsrc = document.getElementById("fragmentShader" + ii).text;
+ src.push({vsrc: vsrc, fsrc: fsrc});
+}
+
+var wordNdx = 0;
+
+function testNextWord() {
+ if (wordNdx >= reservedWords.length) {
+ finishTest();
+ return;
+ }
+ testWord(reservedWords[wordNdx]);
+ ++wordNdx;
+ setTimeout(testNextWord, 0);
+}
+testNextWord();
+
+function testWord(word) {
+ debug("");
+ debug("testing: " + word);
+
+ for (var ii = 0; ii < src.length; ++ii) {
+ var vs = src[ii].vsrc.replace(/\$replaceMe/g, word);
+ var fs = src[ii].fsrc.replace(/\$replaceMe/g, word);
+
+ var success = true;
+ var program = wtu.loadProgram(gl, vs, fs, function(msg) {
+ //debug(msg);
+ success = false;
+ }, true);
+ if (success) {
+ testFailed("shader with: '" + word + "' compiled even though it should not");
+ } else {
+ testPassed("shader with: '" + word + "' correctly failed to compile");
+ }
+ if (program) {
+ gl.deleteProgram(program);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no GL errors");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-short-circuiting-operators.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-short-circuiting-operators.html
new file mode 100644
index 0000000000..c05649aa83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-short-circuiting-operators.html
@@ -0,0 +1,156 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL short-circuit evaluation</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+
+<!-------------------------------------
+ WebGL Shaders
+---------------------------------------->
+<!-- Pass through Shaders -->
+<script id="vshader0" type="x-shader/x-vertex">
+/* PASS-THROUGH VERTEX SHADER */
+attribute vec4 vPosition;
+
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader0" type="x-shader/x-fragment">
+/* PASS-THROUGH FRAGMENT SHADER */
+precision mediump float;
+varying vec4 vPassThrough;
+
+void main()
+{
+ gl_FragColor = vPassThrough;
+}
+</script>
+
+<!-- basic conditonal short circuit Shaders -->
+<script id="vshader1" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 vPassThrough;
+
+void main()
+{
+ int x = 1;
+ $(variables)
+
+ if ($(condition))
+ { /*do nothing*/ }
+
+ /* if x was unmodified return green, else return red */
+ vPassThrough = (x == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ int x = 1;
+ $(variables)
+
+ if ($(condition))
+ { /*do nothing*/ }
+
+ gl_FragColor = (x == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+
+<!-- Main body of the Webgl program -->
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+
+wtu.setupUnitQuad(gl, [0, 1]);
+
+var shaderTemplates = [
+ { vs: "vshader1", fs: "fshader0" }, // basic vertex short-circuit test
+ { vs: "vshader0", fs: "fshader1" }, // basic fragment short-circuit test
+];
+
+/* replace the names of the shaders in the tempate variables with
+ * the shaders themselves */
+for (var ii = 0; ii < shaderTemplates.length; ++ii) {
+ var template = shaderTemplates[ii];
+ template.vs = wtu.getScript(template.vs);
+ template.fs = wtu.getScript(template.fs);
+}
+
+/* define the conditon that will be used in the shaders. If additional
+ * variables are needed that are not present i the shader they my be
+ * defined in the variables variable */
+var tests = [
+ { condition: "true || (x = 0) == 1", variables: "" }, /* test basic 'or' short circuit */
+ { condition: "false && (x = 0) == 1", variables: "" }, /* test basic 'and' short circuit */
+ { condition: "(j == 3 && j == k) || (j > (x = 0))", variables: "int j = 3;\nint k = 3;" }, /* test basic 'or' short circuit with actual condition */
+ { condition: "(j == 3 && j == k) && (j > (x = 0))", variables: "int j = 3;\nint k = 4;" }, /* test basic 'and' short circuit with actual condition */
+ { condition: "(j + 3 > k && ((j < 10) || (x + 5 > j + (x = 0))) || ( x = 0 ) == 7)", variables: "int j = 5;\nint k = 3;" }, /* complex test */
+ { condition: "j + 1 == 6 ? x == 1 || j > (x = 0) : (x = 0) == 1 && (x = 0) <= 1", variables: "int j = 5;" }, /* nested with ternary operator */
+ { condition: "true && (true || (x = 0) == 1)", variables: "" }, /* test unfold short circuit update order correctness */
+];
+
+function testShortCircuit(test) {
+ debug("");
+ debug("testing short circuit condition: " + test.condition);
+
+ /* Setting clear color to blue */
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
+
+ for (var ii = 0; ii < shaderTemplates.length; ++ii) {
+
+ /* clear the screen so that subsequent tests don't conflict */
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var template = shaderTemplates[ii];
+
+ var vs = wtu.replaceParams(template.vs, test);
+ var fs = wtu.replaceParams(template.fs, test);
+
+ var program = wtu.setupProgram(gl, [vs, fs], ['vPosition'], undefined, true);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
+
+ gl.deleteProgram(program);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no GL errors");
+ }
+}
+
+var testNdx = 0;
+function runNextTest() {
+ testShortCircuit(tests[testNdx++]);
+ if (testNdx >= tests.length) {
+ finishTest();
+ } else {
+ setTimeout(runNextTest, 0);
+ }
+}
+
+runNextTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-similar-uniform-array-names.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-similar-uniform-array-names.html
new file mode 100644
index 0000000000..e96ab4055c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-similar-uniform-array-names.html
@@ -0,0 +1,109 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL similar names issue</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_nameCollision[2];
+uniform vec4 u_nameCollision2[2];
+uniform vec4 u_name[2];
+void main(void) {
+ gl_FragColor = u_nameCollision[0] + u_nameCollision2[0] + u_name[0];
+}
+</script>
+<script id="fshader2" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_nameCollision2[2];
+uniform vec4 u_nameCollision[2];
+uniform vec4 u_name[2];
+void main(void) {
+ gl_FragColor = u_nameCollision2[0] + u_nameCollision[0] + u_name[0];
+}
+</script>
+<script id="fshader3" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_nameCollision[2];
+uniform vec4 u_name[2];
+uniform vec4 u_nameCollision2[2];
+void main(void) {
+ gl_FragColor = u_nameCollision[0] + u_name[0] + u_nameCollision2[0];
+}
+</script>
+<script id="fshader4" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_nameCollision2[2];
+uniform vec4 u_name[2];
+uniform vec4 u_nameCollision[2];
+void main(void) {
+ gl_FragColor = u_nameCollision2[0] + u_name[0] + u_nameCollision[0];
+}
+</script>
+<script id="fshader5" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_name[2];
+uniform vec4 u_nameCollision[2];
+uniform vec4 u_nameCollision2[2];
+void main(void) {
+ gl_FragColor = u_name[0] + u_nameCollision[0] + u_nameCollision2[0];
+}
+</script>
+<script id="fshader6" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_name[2];
+uniform vec4 u_nameCollision2[2];
+uniform vec4 u_nameCollision[2];
+void main(void) {
+ gl_FragColor = u_name[0] + u_nameCollision2[0] + u_nameCollision[0];
+}
+</script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+wtu.setupUnitQuad(gl);
+
+for (var ii = 0; ii < 6; ++ii) {
+ var program = wtu.setupProgram(gl, ["vshader", "fshader" + (ii + 1)], ["a_position"]);
+ var loc1 = gl.getUniformLocation(program, "u_name[0]");
+ var loc2 = gl.getUniformLocation(program, "u_nameCollision[0]");
+ var loc3 = gl.getUniformLocation(program, "u_nameCollision2[0]");
+ gl.uniform4fv(loc1, [1, 0, 0, 0]);
+ gl.uniform4fv(loc2, [0, 1, 0, 0]);
+ gl.uniform4fv(loc3, [0, 0, 0, 1]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 255, 0, 255], "Should be yellow");
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-too-many-uniforms.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-too-many-uniforms.html
new file mode 100644
index 0000000000..b5e87f9c85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-too-many-uniforms.html
@@ -0,0 +1,123 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+}
+</script>
+<script id="vshader-max" type="x-shader/x-vertex">
+attribute vec4 a_position;
+uniform vec4 u_color[$(maxUniformVectors)];
+void main()
+{
+ vec4 v = vec4(0, 0, 0, 0);
+ for (int i = 0; i < $(maxUniformVectors); ++i) {
+ v = v + vec4(u_color[i]);
+ }
+ gl_Position = a_position + v;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fshader-max" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_color[$(maxUniformVectors)];
+void main()
+{
+ vec4 v = vec4(0, 0, 0, 0);
+ for (int i = 0; i < $(maxUniformVectors); ++i) {
+ v = v + vec4(u_color[i]);
+ }
+ gl_FragColor = v;
+}
+</script>
+<script>
+"use strict";
+description("checks shader with too many uniforms fails");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var maxFragmentUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
+var maxVertexUniformVectors = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
+
+// Up to 2 uniform vector registers may be spent for literal constants in
+// vshader-max or fshader-max code. One vector row is used for the vec4, and
+// another may be used for integer constants that are allowed to be treated
+// internally as floats and are packable to the space of one row. This is
+// according to the GLSL ES variable packing algorithm detailed in Section 7 of
+// Appendix A of the GLSL ES Specification 10.0.17.
+var maxVectorStorageUsedForLiterals = 2;
+
+var tests = [
+ { desc: "using all uniforms in vertex shader should succeed",
+ maxUniformVectors: maxVertexUniformVectors - maxVectorStorageUsedForLiterals,
+ vShader: "vshader-max",
+ fShader: "fshader",
+ success: true,
+ },
+ { desc: "using too many uniforms in vertex shader should fail",
+ maxUniformVectors: maxVertexUniformVectors + 1,
+ vShader: "vshader-max",
+ fShader: "fshader",
+ color: [0, 1, 0, 1],
+ success: false,
+ },
+ { desc: "using all uniforms in fragment shader should succeed",
+ maxUniformVectors: maxFragmentUniformVectors - maxVectorStorageUsedForLiterals,
+ vShader: "vshader",
+ fShader: "fshader-max",
+ success: true,
+ },
+ { desc: "using too many uniforms in fragment shader should fail",
+ maxUniformVectors: maxFragmentUniformVectors + 1,
+ vShader: "vshader",
+ fShader: "fshader-max",
+ color: [0, 1, 0, 1],
+ success: false,
+ },
+];
+
+var glslTests = [];
+
+for (var ii = 0; ii < tests.length; ++ii) {
+ var test = tests[ii];
+ var vSrc = wtu.replaceParams(wtu.getScript(test.vShader), test);
+ var fSrc = wtu.replaceParams(wtu.getScript(test.fShader), test);
+ glslTests.push({
+ vShaderSource: vSrc,
+ fShaderSource: fSrc,
+ linkSuccess: test.success,
+ passMsg: 'shader ' + test.desc,
+ });
+}
+
+GLSLConformanceTester.runTests(glslTests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-two-initializer-types.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-two-initializer-types.html
new file mode 100644
index 0000000000..fac53b08d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-two-initializer-types.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with different initializer types should succeed
+precision mediump float;
+
+void main() {
+ float test1[4], test2;
+ gl_FragColor = vec4(0.0,1.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html
new file mode 100644
index 0000000000..06783bcfd8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader (3.4) undefined preprocessor symbol should fail
+#if UNDEFINED_FOO
+ // according to ES GLSL spec 3.4 undefined symbols should fail.
+#else
+ precision mediump float;
+ void main()
+ {
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+ }
+#endif
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html
new file mode 100644
index 0000000000..be8d3067b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader with uniform variable in loop condition should fail
+// http://www.khronos.org/registry/webgl/specs/latest/#SUPPORTED_GLSL_CONSTRUCTS
+uniform int u_numIterations;
+attribute vec4 a_position;
+
+void main()
+{
+ float count = 0.0;
+ for (int i = 0; i < u_numIterations; i++) {
+ count += 1.0;
+ }
+ gl_Position = a_position + vec4(count, count, count, count);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec2-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec2-return-value.frag.html
new file mode 100644
index 0000000000..c5f5860707
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec2-return-value.frag.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with vec2 return value from function call should succeed
+precision mediump float;
+
+vec2 functionResult();
+
+void main()
+{
+ vec2 r = functionResult();
+ gl_FragColor = vec4(r.x, r.y, r.x, r.y);
+}
+
+vec2 functionResult()
+{
+ return vec2(1.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec3-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec3-return-value.frag.html
new file mode 100644
index 0000000000..fe5a60c6c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec3-return-value.frag.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with vec3 return value from function call should succeed
+precision mediump float;
+
+vec3 functionResult();
+
+void main()
+{
+ vec3 r = functionResult();
+ gl_FragColor = vec4(r.x, r.y, r.z, r.x);
+}
+
+vec3 functionResult()
+{
+ return vec3(1.0, 1.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-return-value.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-return-value.frag.html
new file mode 100644
index 0000000000..69001a0f83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-return-value.frag.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shader with vec4 return value from function call should succeed
+precision mediump float;
+
+vec4 functionResult();
+
+void main()
+{
+ vec4 r = functionResult();
+ gl_FragColor = vec4(r.x, r.y, r.z, r.w);
+}
+
+vec4 functionResult()
+{
+ return vec4(1.0, 1.0, 1.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html
new file mode 100644
index 0000000000..2cc0e8ea61
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that vec4->vec3->vec4 conditional should succeed
+precision mediump float;
+uniform float x;
+void main()
+{
+ gl_FragColor = vec4((x > 0.0 ? vec4(1.0, 1.0, 1.0, 0.0) : vec4(0.1, 0.1, 0.1, 0.0)).xyz, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.frag.html
new file mode 100644
index 0000000000..0d88a7f689
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.frag.html
@@ -0,0 +1,41 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader that uses __VERSION__==100 should succeed
+#if __VERSION__ == 100
+ precision mediump float;
+ void main()
+ {
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+ }
+#else
+ foo
+#endif
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.vert.html
new file mode 100644
index 0000000000..9a0357971f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-100.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader uses the #version 100 directive should succeed
+#version 100
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-120.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-120.vert.html
new file mode 100644
index 0000000000..c1bc6d7d07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-120.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader uses the #version not 100 directive should fail
+#version 120
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-130.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-130.vert.html
new file mode 100644
index 0000000000..6983c92f9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-version-130.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader uses the #version not 100 directive should fail
+#version 130
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-webgl-identifier.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-webgl-identifier.vert.html
new file mode 100644
index 0000000000..a1c0af9d9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-webgl-identifier.vert.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses webgl identifier should fail
+attribute vec4 webgl_vPosition;
+void main()
+{
+ gl_Position = webgl_vPosition;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-while-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-while-loop.html
new file mode 100644
index 0000000000..592f55541e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-with-while-loop.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with while loop should fail
+precision mediump float;
+void main() {
+ int k = 0;
+ while (k < 5) {
+ k++;
+ }
+ gl_FragColor = vec4(float(k));
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-without-precision.frag.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-without-precision.frag.html
new file mode 100644
index 0000000000..c5543e2119
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shader-without-precision.frag.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader without precision should fail
+uniform vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-constant-expression-loop-conditions.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-constant-expression-loop-conditions.html
new file mode 100644
index 0000000000..c06de87ef8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-constant-expression-loop-conditions.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderLiteralLoopCondition" type="text/something-not-javascript">
+attribute vec4 a_position;
+void main()
+{
+ for (int i = 0; i < 5 + 5; i++) { }
+ gl_Position = a_position;
+}
+</script>
+<script id="fragmentShaderLiteralLoopCondition" type="text/something-not-javascript">
+void main()
+{
+ for (int i = 0; i < 5 + 5; i++) { }
+ gl_FragColor = vec4(1.0);
+}
+</script>
+<script id="vertexShaderConstVarLoopCondition" type="text/something-not-javascript">
+attribute vec4 a_position;
+void main()
+{
+ // Explicitly constant variables can be part of a constant expression
+ const int constVar = 5;
+ for (int i = 0; i < 5 + constVar; i++) { }
+ gl_Position = a_position;
+}
+</script>
+<script id="fragmentShaderConstVarLoopCondition" type="text/something-not-javascript">
+void main()
+{
+ // Explicitly constant variables can be part of a constant expression
+ const int constVar = 5;
+ for (int i = 0; i < constVar + 5; i++) { }
+ gl_FragColor = vec4(1.0);
+}
+</script>
+<script id="vertexShaderNonConstVarLoopCondition" type="text/something-not-javascript">
+attribute vec4 a_position;
+void main()
+{
+ // Despite assigning a constant and not modifying it, nonConstVar is not semantically a constant expression
+ int nonConstVar = 10;
+ for (int i = 0; i < nonConstVar; i++) { }
+ gl_Position = a_position;
+}
+</script>
+<script id="fragmentShaderNonConstVarLoopCondition" type="text/something-not-javascript">
+void main()
+{
+ // Despite assigning a constant and not modifying it, nonConstVar is not semantically a constant expression
+ int nonConstVar = 10;
+ for (int i = 0; i < nonConstVar; i++) { }
+ gl_FragColor = vec4(1.0);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+var tests = [];
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderLiteralLoopCondition"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderLiteralLoopCondition"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Shaders with literals in the loop condition should compile and link.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderConstVarLoopCondition"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderConstVarLoopCondition"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Shaders with constant variables in the loop condition should compile and link.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderNonConstVarLoopCondition"),
+ vShaderSuccess: false,
+ fShaderSource: wtu.getScript("fragmentShaderLiteralLoopCondition"),
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Vertex shader with non-const variable in the loop condition should fail.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderLiteralLoopCondition"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderNonConstVarLoopCondition"),
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Fragment shader with non-const variable in the loop condition should fail.",
+});
+
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-invariance.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-invariance.html
new file mode 100644
index 0000000000..205d78cee4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-invariance.html
@@ -0,0 +1,332 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderVariant" type="text/something-not-javascript">
+varying vec4 v_varying;
+
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderInvariant" type="text/something-not-javascript">
+invariant varying vec4 v_varying;
+
+void main()
+{
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderSeparateInvariant" type="text/something-not-javascript">
+varying vec4 v_varying;
+invariant v_varying;
+
+void main()
+{
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderSeparateInvariantWrongOrder" type="text/something-not-javascript">
+invariant v_varying;
+varying vec4 v_varying;
+
+void main()
+{
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderGlobalInvariant" type="text/something-not-javascript">
+#pragma STDGL invariant(all)
+varying vec4 v_varying;
+
+void main()
+{
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderInvariantGlPosition" type="text/something-not-javascript">
+invariant gl_Position;
+
+void main()
+{
+ gl_Position = vec4(0, 0, 0, 0);
+}
+</script>
+<script id="vertexShaderInvariantGlPointSize" type="text/something-not-javascript">
+invariant gl_PointSize;
+
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0, 0, 0, 0);
+}
+</script>
+<script id="fragmentShaderVariant" type="text/something-not-javascript">
+precision mediump float;
+
+varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="fragmentShaderInvariant" type="text/something-not-javascript">
+precision mediump float;
+
+invariant varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="fragmentShaderSeparateInvariant" type="text/something-not-javascript">
+precision mediump float;
+
+varying vec4 v_varying;
+invariant v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="fragmentShaderSeparateInvariantWrongOrder" type="text/something-not-javascript">
+precision mediump float;
+
+invariant v_varying;
+varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="fragmentShaderGlobalInvariant" type="text/something-not-javascript">
+#pragma STDGL invariant(all)
+precision mediump float;
+
+varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script id="fragmentShaderInvariantGlFragCoord" type="text/something-not-javascript">
+invariant gl_FragCoord;
+
+void main()
+{
+ gl_FragColor = gl_FragCoord;
+}
+</script>
+<script id="fragmentShaderVariantGlFragCoord" type="text/something-not-javascript">
+void main()
+{
+ gl_FragColor = gl_FragCoord;
+}
+</script>
+<script id="fragmentShaderInvariantGlPointCoord" type="text/something-not-javascript">
+invariant gl_PointCoord;
+
+void main()
+{
+ gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);
+}
+</script>
+<script id="fragmentShaderVariantGlPointCoord" type="text/something-not-javascript">
+void main()
+{
+ gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);
+}
+</script>
+<script id="fragmentShaderInvariantGlFrontFacing" type="text/something-not-javascript">
+invariant gl_FrontFacing;
+
+void main()
+{
+ gl_FragColor = gl_FrontFacing ? vec4(1, 1, 1, 1) : vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fragmentShaderVariantGlFrontFacing" type="text/something-not-javascript">
+void main()
+{
+ gl_FragColor = gl_FrontFacing ? vec4(1, 1, 1, 1) : vec4(0, 0, 0, 1);
+}
+</script>
+<script>
+// GLSL 1.0.17 4.3.5
+"use strict";
+// See GLSL ES spec 1.0.17 section 4.6.4 "Invariance and linkage".
+var cases = [
+ {
+ vShaderId: "vertexShaderVariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariant",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with variant varying and fragment shader with invariant varying must fail",
+ },
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariant",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with invariant varying and fragment shader with variant varying must fail",
+ },
+ {
+ vShaderId: "vertexShaderGlobalInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariant",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with invariant (global setting) varying and fragment shader with variant varying must fail",
+ },
+ {
+ vShaderId: "vertexShaderGlobalInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant (global setting) varying and fragment shader with invariant varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderSeparateInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant (separately set) varying and fragment shader with invariant varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderSeparateInvariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant varying and fragment shader with invariant (separately set) varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderSeparateInvariantWrongOrder",
+ vShaderSuccess: false,
+ fShaderId: "fragmentShaderInvariant",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with invariant (separately set in wrong order) varying must fail",
+ },
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderSeparateInvariantWrongOrder",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "fragment shader with invariant (separately set in wrong order) varying must fail",
+ },
+ {
+ vShaderId: "vertexShaderInvariantGlPosition",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariantGlFragCoord",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant gl_Position and fragment shader with invariant gl_FragCoord must succeed",
+ },
+ {
+ vShaderId: "vertexShaderVariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariantGlFragCoord",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with variant gl_Position and fragment shader with invariant gl_FragCoord must fail",
+ },
+ {
+ vShaderId: "vertexShaderInvariantGlPosition",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariantGlFragCoord",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant gl_Position and fragment shader with variant gl_FragCoord must succeed",
+ },
+ {
+ vShaderId: "vertexShaderInvariantGlPointSize",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariantGlPointCoord",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant gl_PointSize and fragment shader with invariant gl_PointCoord must succeed",
+ },
+ {
+ vShaderId: "vertexShaderVariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariantGlPointCoord",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with variant gl_PointSize and fragment shader with invariant gl_PointCoord must fail",
+ },
+ {
+ vShaderId: "vertexShaderInvariantGlPointSize",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariantGlPointCoord",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant gl_PointSize and fragment shader with variant gl_PointCoord must succeed",
+ },
+ {
+ vShaderId: "vertexShaderVariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariantGlFrontFacing",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "fragment shader with variant gl_FrontFacing must succeed compilation",
+ },
+ {
+ vShaderId: "vertexShaderVariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInvariantGlFrontFacing",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "fragment shader with invariant gl_FrontFacing must fail compilation",
+ },
+ {
+ vShaderId: "vertexShaderVariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderGlobalInvariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with variant varying and fragment shader with invariant (global setting) varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderGlobalInvariant",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with invariant varying and fragment shader with invariant (global setting) varying must fail",
+ }
+];
+
+GLSLConformanceTester.runTests(cases);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-uniforms.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-uniforms.html
new file mode 100644
index 0000000000..73a032278f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-uniforms.html
@@ -0,0 +1,87 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// Shaders with mis-matching uniform types should fail
+// GLSL 1.017 4.3.4
+uniform $(type) u_uniform;
+
+void main()
+{
+ gl_Position = $(code);
+}
+</script>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shaders with mis-matching uniform types should fail
+// GLSL 1.017 4.3.4
+precision mediump float;
+
+uniform $(type) u_uniform;
+
+void main()
+{
+ gl_FragColor = $(code);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var uniformTypes = [
+ { type: "bool", code: "vec4(u_uniform, 0, 0, 0)", },
+ { type: "float", code: "vec4(u_uniform, 0, 0, 0)", },
+ { type: "int", code: "vec4(u_uniform, 0, 0, 0)", },
+ { type: "vec2", code: "vec4(u_uniform, 0, 0)", },
+ { type: "ivec2", code: "vec4(u_uniform, 0, 0)", },
+ { type: "bvec2", code: "vec4(u_uniform, 0, 0)", },
+ { type: "vec3", code: "vec4(u_uniform, 0)", },
+ { type: "ivec3", code: "vec4(u_uniform, 0)", },
+ { type: "bvec3", code: "vec4(u_uniform, 0)", },
+ { type: "vec4", code: "vec4(u_uniform)", },
+ { type: "ivec4", code: "vec4(u_uniform)", },
+ { type: "bvec4", code: "vec4(u_uniform)", },
+ { type: "mat2", code: "vec4(u_uniform[0][0], 0, 0, 0)", },
+ { type: "mat3", code: "vec4(u_uniform[0][0], 0, 0, 0)", },
+ { type: "mat4", code: "vec4(u_uniform[0][0], 0, 0, 0)", },
+];
+var vSource = wtu.getScript("vertexShader");
+var fSource = wtu.getScript("fragmentShader");
+var tests = [];
+for (var ii = 0; ii < uniformTypes.length; ++ii) {
+ var u1 = uniformTypes[ii];
+ var vs = wtu.replaceParams(vSource, u1);
+ for (var jj = ii + 1; jj < uniformTypes.length; ++jj) {
+ var u2 = uniformTypes[jj];
+ var fs = wtu.replaceParams(fSource, u2);
+ tests.push({
+ vShaderSource: vs,
+ vShaderSuccess: true,
+ fShaderSource: fs,
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with uniform " + u1.type + " and fragment shader with uniform " + u2.type + " with the same name should fail to link",
+ });
+ }
+}
+
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-varyings.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-varyings.html
new file mode 100644
index 0000000000..342bbc0199
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-mis-matching-varyings.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// Shaders with mis-matching varying types should fail
+// GLSL 1.0.17 4.3.5
+attribute $(type) a_attribute;
+varying $(type) v_varying;
+
+void main()
+{
+ v_varying = a_attribute;
+ gl_Position = vec4(0,0,0,0);
+}
+</script>
+<script id="fragmentShader" type="text/something-not-javascript">
+// Shaders with mis-matching varyings types should fail
+// GLSL 1.0.17 4.3.5
+precision mediump float;
+
+varying $(type) v_varying;
+
+void main()
+{
+ gl_FragColor = $(code);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var varyingTypes = [
+ { type: "float", code: "vec4(v_varying, 0, 0, 0)", },
+ { type: "vec2", code: "vec4(v_varying, 0, 0)", },
+ { type: "vec3", code: "vec4(v_varying, 0)", },
+ { type: "vec4", code: "vec4(v_varying)", },
+ { type: "mat2", code: "vec4(v_varying[0][0], 0, 0, 0)", },
+ { type: "mat3", code: "vec4(v_varying[0][0], 0, 0, 0)", },
+ { type: "mat4", code: "vec4(v_varying[0][0], 0, 0, 0)", },
+];
+var vSource = wtu.getScript("vertexShader");
+var fSource = wtu.getScript("fragmentShader");
+var tests = [];
+for (var ii = 0; ii < varyingTypes.length; ++ii) {
+ var u1 = varyingTypes[ii];
+ var vs = wtu.replaceParams(vSource, u1);
+ for (var jj = ii + 1; jj < varyingTypes.length; ++jj) {
+ var u2 = varyingTypes[jj];
+ var fs = wtu.replaceParams(fSource, u2);
+ tests.push({
+ vShaderSource: vs,
+ vShaderSuccess: true,
+ fShaderSource: fs,
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with varying " + u1.type + " and fragment shader with varying " + u2.type + " with the same name should fail to link",
+ });
+ }
+}
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-missing-varyings.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-missing-varyings.html
new file mode 100644
index 0000000000..4dab279f60
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-missing-varyings.html
@@ -0,0 +1,74 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// GLSL 1.0.17 4.3.5
+void main()
+{
+ gl_Position = vec4(0,0,0,0);
+}
+</script>
+<script id="fragmentShader" type="text/something-not-javascript">
+// GLSL 1.0.17 4.3.5
+precision mediump float;
+
+varying $(type) v_varying;
+
+void main()
+{
+ gl_FragColor = $(code);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var varyingTypes = [
+ { type: "float", code: "vec4(v_varying, 0, 0, 0)", },
+ { type: "vec2", code: "vec4(v_varying, 0, 0)", },
+ { type: "vec3", code: "vec4(v_varying, 0)", },
+ { type: "vec4", code: "vec4(v_varying)", },
+ { type: "mat2", code: "vec4(v_varying[0][0], 0, 0, 0)", },
+ { type: "mat3", code: "vec4(v_varying[0][0], 0, 0, 0)", },
+ { type: "mat4", code: "vec4(v_varying[0][0], 0, 0, 0)", },
+];
+var vSource = wtu.getScript("vertexShader");
+var fSource = wtu.getScript("fragmentShader");
+var tests = [];
+for (var ii = 0; ii < varyingTypes.length; ++ii) {
+ var u1 = varyingTypes[ii];
+ var vs = wtu.replaceParams(vSource, u1);
+ for (var jj = ii + 1; jj < varyingTypes.length; ++jj) {
+ var u2 = varyingTypes[jj];
+ var fs = wtu.replaceParams(fSource, u2);
+ tests.push({
+ vShaderSource: vs,
+ vShaderSuccess: true,
+ fShaderSource: fs,
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader no varyings and fragment shader with varying " + u2.type + " should fail to link",
+ });
+ }
+}
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-name-conflicts.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-name-conflicts.html
new file mode 100644
index 0000000000..e4c9af8b8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-name-conflicts.html
@@ -0,0 +1,88 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader should succeed
+precision mediump float;
+uniform vec4 foo;
+void main()
+{
+ gl_FragColor = foo;
+}
+</script>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader should succeed
+attribute vec4 foo;
+void main()
+{
+ gl_Position = foo;
+}
+</script>
+<script>
+"use strict";
+
+/*
+This test previously concluded that an attribute in a vertex shader
+would conflict across shaders with a uniform of the same name in the
+fragment shader, based on the following sections of the GLSL ES 1.0.17
+specification:
+
+---
+Section 4.2.6
+
+...
+
+With the exception of uniform declarations, vertex and fragment shaders
+have separate name spaces. Functions and global variables declared in a
+vertex shader cannot be referenced by a fragment shader and vice versa.
+Uniforms have a single name space. Uniforms declared with the same name
+must have matching types and precisions.
+
+Section 4.3.3
+
+Attribute variables are required to have global scope
+
+Section 4.3.4
+
+The uniform qualifier is used to declare global variables
+---
+
+GLSL ES 3.00 later confirmed that pipeline stages have distinct
+namespaces. The OpenGL ES working group confirmed in discussions
+https://github.com/KhronosGroup/WebGL/issues/3201 that this was the
+intended behavior for GLSL ES 1.00.
+
+For this reason, this test asserts that such usage does not generate a
+conflict.
+*/
+
+GLSLConformanceTester.runTests([
+ { vShaderId: 'vertexShader',
+ vShaderSuccess: true,
+ fShaderId: 'fragmentShader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'using the same name for a vertex shader attribute and fragment shader uniform should succeed'
+ },
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-uniform-structs.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-uniform-structs.html
new file mode 100644
index 0000000000..8713bd0cbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-uniform-structs.html
@@ -0,0 +1,289 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderStructSequence" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_Position = uni.pos;
+}
+</script>
+<script id="fragmentShaderStructSequence" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 color;
+ vec4 pos;
+};
+
+uniform info uni;
+void main()
+{
+ gl_FragColor = uni.color;
+}
+</script>
+<script id="vertexShaderStructName" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_Position = uni.pos;
+}
+</script>
+<script id="fragmentShaderStructNameFailure" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info1 {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info1 uni;
+void main()
+{
+ gl_FragColor = uni.color;
+}
+</script>
+<script id="fragmentShaderStructNameSuccess" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+
+// Add a struct before info to make sure the struct info here is assigned
+// a different internal unique ID from the struct info in vertex shader.
+struct extra {
+ vec4 p;
+};
+
+struct info {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ extra my;
+ my.p = uni.color;
+ gl_FragColor = my.p;
+}
+</script>
+<script id="vertexShaderStructFieldName" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_Position = uni.pos;
+}
+</script>
+<script id="fragmentShaderStructFieldName" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 pos1;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_FragColor = uni.color;
+}
+</script>
+<script id="vertexShaderStructFieldType" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_Position = uni.pos;
+}
+</script>
+<script id="fragmentShaderStructFieldType" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec3 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_FragColor = uni.color;
+}
+</script>
+<script id="vertexShaderStructFieldPrecision" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+struct info {
+ mediump vec4 pos;
+ highp vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_Position = uni.pos;
+}
+</script>
+<script id="fragmentShaderStructFieldPrecision" type="text/something-not-javascript">
+// Structures must have the same name, sequence of type names, and
+// type definitions, and field names to be considered the same type.
+// GLSL 1.017 4.2.4
+precision mediump float;
+struct info {
+ vec4 pos;
+ vec4 color;
+};
+
+uniform info uni;
+void main()
+{
+ gl_FragColor = uni.color;
+}
+</script>
+<script id="vertexShaderUnnamedStruct" type="text/something-not-javascript">
+// ANGLE regression on Windows, crbug.com/401296
+uniform struct {
+ float f;
+ vec4 v;
+} u_struct;
+
+void main()
+{
+ gl_Position = u_struct.f * u_struct.v;
+}
+</script>
+<script id="fragmentShaderSimple" type="text/something-not-javascript">
+void main()
+{
+ gl_FragColor = vec4(1.0);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+var tests = [];
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderStructName"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderStructNameSuccess"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Structures with the same defination must be considered the same type.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderStructName"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderStructNameFailure"),
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Structures must have the same name to be considered the same type.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderStructSequence"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderStructSequence"),
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Structures must have the same sequence of type names to be considered the same type.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderStructFieldName"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderStructFieldName"),
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Structures must have the same field names to be considered the same type.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderStructFieldType"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderStructFieldType"),
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Structures must have the same type definitions to be considered the same type.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderStructFieldPrecision"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderStructFieldPrecision"),
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Structures must have the same type definitions (including precision) to be considered the same type.",
+});
+tests.push({
+ vShaderSource: wtu.getScript("vertexShaderUnnamedStruct"),
+ vShaderSuccess: true,
+ fShaderSource: wtu.getScript("fragmentShaderSimple"),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Shaders with uniforms of unnamed struct type should compile and link successfully.",
+});
+
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-varyings.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-varyings.html
new file mode 100644
index 0000000000..87baaa2bdc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shaders-with-varyings.html
@@ -0,0 +1,103 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderNoVarying" type="text/something-not-javascript">
+void main()
+{
+ gl_Position = vec4(0,0,0,0);
+}
+</script>
+<script id="vertexShaderUnusedVarying" type="text/something-not-javascript">
+varying vec4 v_varying;
+
+void main()
+{
+ gl_Position = vec4(0,0,0,0);
+}
+</script>
+<script id="vertexShaderUsedVarying" type="text/something-not-javascript">
+varying vec4 v_varying;
+
+void main()
+{
+ gl_Position = v_varying;
+}
+</script>
+<script id="fragmentShaderUnusedVarying" type="text/something-not-javascript">
+precision mediump float;
+
+varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fragmentShaderUsedVarying" type="text/something-not-javascript">
+precision mediump float;
+
+varying vec4 v_varying;
+
+void main()
+{
+ gl_FragColor = v_varying;
+}
+</script>
+<script>
+// GLSL 1.0.17 4.3.5
+"use strict";
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "vertexShaderNoVarying",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderUnusedVarying",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with no varying and fragment shader with unused varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderNoVarying",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderUsedVarying",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "vertex shader with no varying and fragment shader with used varying must fail",
+ },
+ {
+ vShaderId: "vertexShaderUnusedVarying",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderUnusedVarying",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with unused varying and fragment shader with unused varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderUnusedVarying",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderUsedVarying",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with unused varying and fragment shader with used varying must succeed",
+ },
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shared.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shared.html
new file mode 100644
index 0000000000..77786bb385
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/shared.html
@@ -0,0 +1,151 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="sharedVertexShader" type="text/something-not-javascript">
+// shared vertex shader should succeed.
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec2 texCoord;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_surfaceToLight;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 world = orientMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_surfaceToLight = (world * position).xyz;
+ gl_Position = v_position;
+}
+</script>
+<script id="fragmentShaderA" type="text/something-not-javascript">
+// shared fragment shader should succeed.
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_surfaceToLight;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 halfVector = normalize(surfaceToLight);
+ vec4 litR = lit(1.0, 1.0, shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+}
+</script>
+<script id="fragmentShaderB" type="text/something-not-javascript">
+// shared fragment shader should succeed.
+precision mediump float;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_surfaceToLight;
+
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec4 reflection = vec4(0,0,0,0); // #noReflection
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec4 skyColor = vec4(0.5,0.5,1,1); // #noReflection
+
+ vec3 halfVector = normalize(surfaceToLight);
+ vec4 litR = lit(1.0, 1.0, 10.0);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ vec4(1,2,3,4) * (litR.y + litR.z * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ 1.0);
+ // #fogCode
+ gl_FragColor = outColor;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTests([
+ { vShaderSource: document.getElementById("sharedVertexShader").text,
+ vShaderSuccess: true,
+ fShaderSource: document.getElementById("fragmentShaderA").text,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shared fragment shader should succeed',
+ },
+ { vShaderSource: document.getElementById("sharedVertexShader").text,
+ vShaderSuccess: true,
+ fShaderSource: document.getElementById("fragmentShaderB").text,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'shared fragment shader should succeed',
+ }
+]);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-inout-parameter.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-inout-parameter.html
new file mode 100644
index 0000000000..e041661477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-inout-parameter.html
@@ -0,0 +1,117 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Structure as Inout Parameter Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+
+<script id="simple-vs" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="struct-inout-parameter-fs" type="x-shader/x-fragment">
+struct ColorData {
+ vec3 red;
+ vec3 blue;
+};
+
+void modify(inout ColorData colorData) {
+ colorData.red += vec3(0.5, 0.0, 0.0);
+ colorData.blue += vec3(0.0, 0.0, 0.5);
+}
+
+void main() {
+ ColorData colorData;
+ colorData.red = vec3(0.5, 0.0, 0.0);
+ colorData.blue = vec3(0.0, 0.0, 0.5);
+
+ vec3 red = vec3(1.0, 0.0, 0.0);
+ vec3 green = vec3(0.0, 1.0, 0.0);
+ vec3 blue = vec3(0.0, 0.0, 1.0);
+ vec3 finalColor;
+
+ modify(colorData);
+
+ if (colorData.red == red && colorData.blue == blue)
+ finalColor = green;
+ else
+ finalColor = red;
+
+ gl_FragColor = vec4(finalColor, 1.0);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Testing structs as inout parameter");
+
+debug('Regression test for <a href="http://crbug.com/851870">http://crbug.com/851870</a> / <a href="https://github.com/mrdoob/three.js/issues/14137">https://github.com/mrdoob/three.js/issues/14137</a>');
+
+function prepend(floatPrecision) {
+ let source = document.getElementById('struct-inout-parameter-fs').text;
+ return 'precision ' + floatPrecision + ' float;\n' + source;
+}
+
+let tests = [
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderSource: prepend('lowp'),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "lowp struct used as inout parameter",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderSource: prepend('mediump'),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "mediump struct used as inout parameter",
+ },
+];
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext();
+let precision = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
+let highpSupported = (precision.rangeMin >= 62 && precision.rangeMax >= 62 && precision.precision >= 16);
+debug("highp is" + (highpSupported ? "" : " not") + " supported in fragment shaders");
+
+if (highpSupported) {
+ tests.push(
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderSource: prepend('highp'),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "highp struct used as inout parameter",
+ }
+ );
+}
+
+GLSLConformanceTester.runTests(tests);
+debug("");
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-out-parameter.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-out-parameter.html
new file mode 100644
index 0000000000..4190c691e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-as-out-parameter.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Structure as Out Parameter Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+
+<script id="simple-vs" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="struct-out-parameter-fs" type="x-shader/x-fragment">
+struct ColorData {
+ vec3 red;
+ vec3 blue;
+};
+
+void modify(out ColorData colorData) {
+ colorData.red = vec3(1.0, 0.0, 0.0);
+ colorData.blue = vec3(0.0, 0.0, 1.0);
+}
+
+void main() {
+ ColorData colorData;
+
+ vec3 red = vec3(1.0, 0.0, 0.0);
+ vec3 green = vec3(0.0, 1.0, 0.0);
+ vec3 blue = vec3(0.0, 0.0, 1.0);
+ vec3 finalColor;
+
+ modify(colorData);
+
+ if (colorData.red == red && colorData.blue == blue)
+ finalColor = green;
+ else
+ finalColor = red;
+
+ gl_FragColor = vec4(finalColor, 1.0);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Testing structs as out parameter");
+
+debug('Regression test for <a href="http://crbug.com/851873">http://crbug.com/851873</a> / <a href="https://github.com/mrdoob/three.js/issues/14137">https://github.com/mrdoob/three.js/issues/14137</a>');
+
+function prepend(floatPrecision) {
+ let source = document.getElementById('struct-out-parameter-fs').text;
+ return 'precision ' + floatPrecision + ' float;\n' + source;
+}
+
+let tests = [
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderSource: prepend('lowp'),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "lowp struct used as out parameter",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderSource: prepend('mediump'),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "mediump struct used as out parameter",
+ },
+];
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext();
+let precision = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
+let highpSupported = (precision.rangeMin >= 62 && precision.rangeMax >= 62 && precision.precision >= 16);
+debug("highp is" + (highpSupported ? "" : " not") + " supported in fragment shaders");
+
+if (highpSupported) {
+ tests.push(
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderSource: prepend('highp'),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "highp struct used as out parameter",
+ }
+ );
+}
+
+GLSLConformanceTester.runTests(tests);
+debug("");
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-assign.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-assign.html
new file mode 100644
index 0000000000..9d1d77d068
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-assign.html
@@ -0,0 +1,214 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Structure Assignment Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+
+<script id="simple-vs" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="simple-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ float f;
+};
+
+my_struct a = my_struct(0.0);
+my_struct b = my_struct(1.0);
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ a = b;
+ if (a.f == 1.0) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="vec-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec3 v;
+};
+
+my_struct a = my_struct(vec3(0.0, 0.0, 0.0));
+my_struct b = my_struct(vec3(1.0, 2.0, 3.0));
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ a = b;
+ if (a.v.x == 1.0) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="nested-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct s1
+{
+ float f;
+};
+
+struct s2
+{
+ s1 s;
+};
+
+s2 a = s2(s1(0.0));
+s2 b = s2(s1(1.0));
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ a = b;
+ if (a.s.f == 1.0) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="nested-vec-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct s1
+{
+ vec3 v;
+};
+
+struct s2
+{
+ s1 s;
+};
+
+s2 a = s2(s1(vec3(0.0, 0.0, 0.0)));
+s2 b = s2(s1(vec3(1.0, 2.0, 3.0)));
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ a = b;
+ if (a.s.v.x == 1.0) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="array-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct my_struct
+{
+ float f[3];
+};
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ my_struct a;
+ my_struct b;
+ for (int i = 0; i < 3; ++i) {
+ a.f[i] = 0.0;
+ b.f[i] = float(i);
+ }
+
+ a = b;
+ if (a.f[1] == 1.0 && a.f[2] == 2.0) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="sampler-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct my_struct
+{
+ sampler2D s;
+};
+
+uniform my_struct a;
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ my_struct b;
+ b = a;
+}
+</script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Testing struct assignment");
+
+var wtu = WebGLTestUtils;
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "simple-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple struct with one float",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "vec-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple struct with a vector",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "nested-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Nested struct with a float",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "nested-vec-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Nested struct with a vector",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "array-struct-fs",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Assigning a struct containing an array should not compile",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "sampler-struct-fs",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Assigning a struct containing a sampler should not compile",
+ }
+]);
+debug("");
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-equals.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-equals.html
new file mode 100644
index 0000000000..50ac40e5c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-equals.html
@@ -0,0 +1,217 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Structure Equals Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+
+<script id="simple-vs" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main(void) {
+ gl_Position = a_position;
+}
+</script>
+<script id="simple-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ float f;
+};
+
+my_struct a = my_struct(1.0);
+my_struct b = my_struct(1.0);
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="vec-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+struct my_struct {
+ vec3 v;
+};
+
+my_struct a = my_struct(vec3(1.0, 2.0, 3.0));
+my_struct b = my_struct(vec3(1.0, 2.0, 3.0));
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="nested-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct s1
+{
+ float f;
+};
+
+struct s2
+{
+ s1 s;
+};
+
+s2 a = s2(s1(1.0));
+s2 b = s2(s1(1.0));
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="nested-vec-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct s1
+{
+ vec3 v;
+};
+
+struct s2
+{
+ s1 s;
+};
+
+s2 a = s2(s1(vec3(1.0, 2.0, 3.0)));
+s2 b = s2(s1(vec3(1.0, 2.0, 3.0)));
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ gl_FragColor.y = 1.0;
+ }
+}
+</script>
+<script id="array-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct my_struct
+{
+ float f[3];
+};
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ my_struct a;
+ my_struct b;
+ for (int i = 0; i < 3; ++i) {
+ a.f[i] = 0.0;
+ b.f[i] = 1.0;
+ }
+
+ if (a == b) {
+ gl_FragColor.x = 1.0;
+ }
+}
+</script>
+<script id="sampler-struct-fs" type="x-shader/x-fragment">
+precision mediump float;
+
+struct my_struct
+{
+ sampler2D s;
+};
+
+uniform my_struct a;
+uniform my_struct b;
+
+void main(void) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ gl_FragColor.x = 1.0;
+ }
+}
+</script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Testing struct equals");
+
+var wtu = WebGLTestUtils;
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "simple-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple struct with one float",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "vec-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple struct with a vector",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "nested-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Nested struct with a float",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "nested-vec-struct-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Nested struct with a vector",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "array-struct-fs",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Comparing a struct containing an array should not compile",
+ },
+ {
+ vShaderId: "simple-vs",
+ vShaderSuccess: true,
+ fShaderId: "sampler-struct-fs",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Comparing a struct containing a sampler should not compile",
+ }
+]);
+debug("");
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-mixed-array-declarators.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-mixed-array-declarators.html
new file mode 100644
index 0000000000..108cee9d0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-mixed-array-declarators.html
@@ -0,0 +1,71 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title></title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+void main() {
+ struct S {
+ $(type) field;
+ };
+ S s1[2], s2;
+ $(var).field = $(initializer);
+ gl_FragColor = $(asVec4);
+}
+</script>
+<script>
+"use strict";
+description("Verifies that mixed (array vs. not array) struct declarators work correctly.");
+var tests = [];
+var wtu = WebGLTestUtils;
+var typeInfos = [
+ { type: 'float', initializer: '1.0', asVec4: 'vec4(0.0,$(var).field,0.0,1.0)' },
+ { type: 'vec2', initializer: 'vec2(0.0, 1.0)', asVec4: 'vec4($(var).field,0.0,1.0)' },
+ { type: 'vec3', initializer: 'vec3(0.0, 1.0, 0.0)', asVec4: 'vec4($(var).field,1.0)' },
+ { type: 'vec4', initializer: 'vec4(0.0, 1.0, 0.0, 1.0)', asVec4: '$(var).field' },
+ { type: 'int', initializer: '1', asVec4: 'vec4(0.0,$(var).field,0.0,1.0)' },
+ { type: 'ivec2', initializer: 'ivec2(0, 1)', asVec4: 'vec4($(var).field,0.0,1.0)' },
+ { type: 'ivec3', initializer: 'ivec3(0, 1, 0)', asVec4: 'vec4($(var).field,1.0)' },
+ { type: 'ivec4', initializer: 'ivec4(0, 1, 0, 1)', asVec4: 'vec4($(var).field)' },
+ { type: 'bool', initializer: 'true', asVec4: 'vec4(0.0,$(var).field,0.0,1.0)' },
+ { type: 'bvec2', initializer: 'bvec2(false, true)', asVec4: 'vec4($(var).field,0.0,1.0)' },
+ { type: 'bvec3', initializer: 'bvec3(false, true, false)', asVec4: 'vec4($(var).field,1.0)' },
+ { type: 'bvec4', initializer: 'bvec4(false,true,false,true)',asVec4: 'vec4($(var).field)' },
+];
+['s1[0]', 's1[1]', 's2'].forEach(function(varName) {
+ typeInfos.forEach(function (typeInfo) {
+ var replaceParams = {
+ type: typeInfo.type,
+ initializer: typeInfo.initializer,
+ var: varName,
+ asVec4: wtu.replaceParams(typeInfo.asVec4, {var: varName})
+ };
+ tests.push({
+ fShaderSource: wtu.replaceParams(wtu.getScript('fragmentShader'), replaceParams),
+ passMsg: typeInfo.type,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render:true
+ });
+ });
+});
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-exceeds-maximum.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-exceeds-maximum.html
new file mode 100644
index 0000000000..772e47d70d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-exceeds-maximum.html
@@ -0,0 +1,55 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// shader with too-deep struct nesting should fail per WebGL spec
+struct nesting5 {
+ vec4 vecfield;
+};
+
+struct nesting4 {
+ nesting5 field5;
+};
+
+struct nesting3 {
+ nesting4 field4;
+};
+
+struct nesting2 {
+ nesting3 field3;
+};
+
+struct nesting1 {
+ nesting2 field2;
+};
+
+uniform nesting1 uniform1;
+void main()
+{
+ gl_Position = uniform1.field2.field3.field4.field5.vecfield;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-of-variable-names.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-of-variable-names.html
new file mode 100644
index 0000000000..0762628141
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-of-variable-names.html
@@ -0,0 +1,74 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title></title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+struct S { $(outer_type) u; };
+void main() {
+ S S; // This is legal, 'S' as a typename is defined in another scope.
+ {
+ struct S { $(inner_type) a; }; // This is legal as well, 'S' is now defined as a variable name in an ancestor scope
+ S newvar;
+ newvar.a = $(initializer);
+ gl_FragColor = $(fragColor);
+ }
+}
+</script>
+<script>
+"use strict";
+description("This test verifies that defining a typename in a new scope when the typename is the name of a variable that hides a typename declaration succeeds for all combinations of GLSL types.");
+var tests = [];
+var wtu = WebGLTestUtils;
+var typeInfo = [
+ { Type: 'float', initializer: '1.0', fragColor: 'vec4(0.0, newvar.a, 0.0, 1.0)' },
+ { Type: 'vec2', initializer: 'vec2(0.0, 1.0)', fragColor: 'vec4(newvar.a, 0.0, 1.0)' },
+ { Type: 'vec3', initializer: 'vec3(0.0, 1.0, 0.0)', fragColor: 'vec4(newvar.a, 1.0)' },
+ { Type: 'vec4', initializer: 'vec4(0.0, 1.0, 0.0, 1.0)', fragColor: 'newvar.a' },
+ { Type: 'int', initializer: '1', fragColor: 'vec4(0.0, newvar.a, 0.0, 1.0)' },
+ { Type: 'ivec2', initializer: 'ivec2(0, 1)', fragColor: 'vec4(newvar.a, 0.0, 1.0)' },
+ { Type: 'ivec3', initializer: 'ivec3(0, 1, 0)', fragColor: 'vec4(newvar.a, 1.0)' },
+ { Type: 'ivec4', initializer: 'ivec4(0, 1, 0, 1)', fragColor: 'vec4(newvar.a)' },
+ { Type: 'bool', initializer: 'true', fragColor: 'vec4(0.0, newvar.a, 0.0, 1.0)' },
+ { Type: 'bvec2', initializer: 'bvec2(false, true)', fragColor: 'vec4(newvar.a, 0.0, 1.0)' },
+ { Type: 'bvec3', initializer: 'bvec3(false, true, false)', fragColor: 'vec4(newvar.a, 1.0)' },
+ { Type: 'bvec4', initializer: 'bvec4(false,true,false,true)',fragColor: 'vec4(newvar.a)' },
+];
+typeInfo.forEach(function (outerType) {
+ typeInfo.forEach(function (innerType) {
+ var replaceParams = {
+ outer_type: outerType.Type,
+ inner_type: innerType.Type,
+ // use the initializer and fragColor for the inner type. Its definition should override the variable name in the outerscope.
+ initializer: innerType.initializer,
+ fragColor: innerType.fragColor
+ };
+ tests.push({
+ fShaderSource: wtu.replaceParams(wtu.getScript('fragmentShader'), replaceParams),
+ passMsg: 'Outer struct type: ' + outerType.Type + ' inner struct type: ' + innerType.Type,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true
+ });
+ })
+})
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-under-maximum.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-under-maximum.html
new file mode 100644
index 0000000000..1707e57007
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-nesting-under-maximum.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// shader with struct nesting less than maximum in WebGL spec should succeed
+struct nesting4 {
+ vec4 vecfield;
+};
+
+struct nesting3 {
+ nesting4 field4;
+};
+
+struct nesting2 {
+ nesting3 field3;
+};
+
+struct nesting1 {
+ nesting2 field2;
+};
+
+uniform nesting1 uniform1;
+void main()
+{
+ gl_Position = uniform1.field2.field3.field4.vecfield;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-specifiers-in-uniforms.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-specifiers-in-uniforms.html
new file mode 100644
index 0000000000..3c0c704a29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-specifiers-in-uniforms.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title></title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+uniform struct S { $(type) field;} s;
+void main() {
+ // All uniforms are required to be zero initialized. Add the color green
+ // to make the rendering test pass.
+ gl_FragColor = $(asVec4) + vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description("Verifies that structure specifiers work with uniforms.");
+var tests = [];
+var wtu = WebGLTestUtils;
+var typeInfos = [
+ { type: 'float', asVec4: 'vec4(0.0,s.field,0.0,0.0)' },
+ { type: 'vec2', asVec4: 'vec4(s.field,0.0,0.0)' },
+ { type: 'vec3', asVec4: 'vec4(s.field,0.0)' },
+ { type: 'vec4', asVec4: 's.field' },
+ { type: 'int', asVec4: 'vec4(0.0,s.field,0.0,0.0)' },
+ { type: 'ivec2', asVec4: 'vec4(s.field,0.0,0.0)' },
+ { type: 'ivec3', asVec4: 'vec4(s.field,0.0)' },
+ { type: 'ivec4', asVec4: 'vec4(s.field)' },
+ { type: 'bool', asVec4: 'vec4(0.0,s.field,0.0,0.0)' },
+ { type: 'bvec2', asVec4: 'vec4(s.field,0.0,0.0)' },
+ { type: 'bvec3', asVec4: 'vec4(s.field,0.0)' },
+ { type: 'bvec4', asVec4: 'vec4(s.field)' },
+];
+typeInfos.forEach(function (typeInfo) {
+ var replaceParams = {
+ type: typeInfo.type,
+ asVec4: typeInfo.asVec4
+ };
+ tests.push({
+ fShaderSource: wtu.replaceParams(wtu.getScript('fragmentShader'), replaceParams),
+ passMsg: typeInfo.type,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render:true
+ });
+});
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-unary-operators.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-unary-operators.html
new file mode 100644
index 0000000000..d14a860fd8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/struct-unary-operators.html
@@ -0,0 +1,70 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title></title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+struct S { $(type) t; };
+void main() {
+ S a;
+ a.t = $(initializer);
+ S b = $(operator)a; // Unary operators not allowed
+ gl_FragColor = $(fragColor);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies that unary operators +, ++, -, --, !, and ~ do not work on structures. Per the spec, field selectors, equality and assignment are the only operators allowed on structures.");
+var tests = [];
+var wtu = WebGLTestUtils;
+var operators = ['+', '++', '-', '--', '!', '~']
+var typeInfos = [
+ { type: 'float', initializer: '1.0', fragColor: 'vec4(0.0, b.t, 0.0, 1.0)' },
+ { type: 'vec2', initializer: 'vec2(0.0, 1.0)', fragColor: 'vec4(b.t, 0.0, 1.0)' },
+ { type: 'vec3', initializer: 'vec3(0.0, 1.0, 0.0)', fragColor: 'vec4(b.t, 1.0)' },
+ { type: 'vec4', initializer: 'vec4(0.0, 1.0, 0.0, 1.0)', fragColor: 'b.t' },
+ { type: 'int', initializer: '1', fragColor: 'vec4(0.0, b.t, 0.0, 1.0)' },
+ { type: 'ivec2', initializer: 'ivec2(0, 1)', fragColor: 'vec4(b.t, 0.0, 1.0)' },
+ { type: 'ivec3', initializer: 'ivec3(0, 1, 0)', fragColor: 'vec4(b.t, 1.0)' },
+ { type: 'ivec4', initializer: 'ivec4(0, 1, 0, 1)', fragColor: 'vec4(b.t)' },
+ { type: 'bool', initializer: 'true', fragColor: 'vec4(0.0, b.t, 0.0, 1.0)' },
+ { type: 'bvec2', initializer: 'bvec2(false, true)', fragColor: 'vec4(b.t, 0.0, 1.0)' },
+ { type: 'bvec3', initializer: 'bvec3(false, true, false)', fragColor: 'vec4(b.t, 1.0)' },
+ { type: 'bvec4', initializer: 'bvec4(false,true,false,true)',fragColor: 'vec4(b.t)' },
+];
+operators.forEach(function (operator) {
+ typeInfos.forEach(function (typeInfo) {
+ var replaceParams = {
+ initializer: typeInfo.initializer,
+ type: typeInfo.type,
+ fragColor: typeInfo.fragColor,
+ operator: operator,
+ };
+ tests.push({
+ fShaderSource: wtu.replaceParams(wtu.getScript('fragmentShader'), replaceParams),
+ passMsg: 'Unary operator ' + operator + ' cannot be used on a struct with a ' + typeInfo.type,
+ fShaderSuccess: false,
+ linkSuccess: false
+ });
+ });
+});
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operator-on-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operator-on-arrays.html
new file mode 100644
index 0000000000..adeddc5e33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operator-on-arrays.html
@@ -0,0 +1,64 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Ternary operator on arrays</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader-array-ternary-operator" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ float a[3];
+ float b[3];
+ float c[3] = true ? a : b;
+}
+</script>
+<script id="fshader-struct-array-ternary-operator" type="x-shader/x-fragment">
+precision mediump float;
+struct MyStruct {
+ bool a[3];
+};
+
+void main()
+{
+ MyStruct b;
+ MyStruct c;
+ MyStruct d = true ? b : c;
+}
+</script>
+<script>
+"use strict";
+description("Checks ternary operators for structs and arrays.");
+
+GLSLConformanceTester.runTests([
+{ fShaderId: 'fshader-array-ternary-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using ternary operators with arrays is not allowed",
+},
+{ fShaderId: 'fshader-struct-array-ternary-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "By implication, using ternary operators with structs containing arrays is not allowed",
+},
+]);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-global-initializers.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-global-initializers.html
new file mode 100644
index 0000000000..a8fe592ad0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-global-initializers.html
@@ -0,0 +1,67 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title>Ternary Operators in Global Initializers</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+precision mediump float;
+const $(type) green = $(green);
+const $(type) black = $(black);
+$(type) var = (true) ? green : black;
+void main() {
+ gl_FragColor = $(asVec4);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies that ternary operators can be used in global initializers.");
+var tests = [];
+var wtu = WebGLTestUtils;
+var typeInfos = [
+ { type: 'float', green: '1.0', black: '0.0', asVec4: 'vec4(0.0,var,0.0,1.0)' },
+ { type: 'vec2', green: 'vec2(0.0,1.0)', black: 'vec2(0.0,0.0)', asVec4: 'vec4(var,0.0,1.0)' },
+ { type: 'vec3', green: 'vec3(0.0,1.0,0.0)', black: 'vec3(0.0,0.0,0.0)', asVec4: 'vec4(var,1.0)' },
+ { type: 'vec4', green: 'vec4(0.0,1.0,0.0,1.0)', black: 'vec4(0.0,0.0,0.0,0.0)', asVec4: 'var' },
+ { type: 'int', green: '1', black: '0', asVec4: 'vec4(0.0,var,0.0,1.0)' },
+ { type: 'ivec2', green: 'ivec2(0,1)', black: 'ivec2(0,0)', asVec4: 'vec4(var,0.0,1.0)' },
+ { type: 'ivec3', green: 'ivec3(0,1,0)', black: 'ivec3(0,0,0)', asVec4: 'vec4(var,1.0)' },
+ { type: 'ivec4', green: 'ivec4(0,1,0,1)', black: 'ivec4(0,0,0,0)', asVec4: 'vec4(var)' },
+ { type: 'bool', green: 'true', black: 'false', asVec4: 'vec4(0.0,var,0.0,1.0)' },
+ { type: 'bvec2', green: 'bvec2(false,true)', black: 'bvec2(false,false)', asVec4: 'vec4(var,0.0,1.0)' },
+ { type: 'bvec3', green: 'bvec3(false,true,false)', black: 'bvec3(false,false,false)', asVec4: 'vec4(var,1.0)' },
+ { type: 'bvec4', green: 'bvec4(false,true,false,true)',black: 'bvec4(false,false,false,false)', asVec4: 'vec4(var)' },
+];
+typeInfos.forEach(function (typeInfo) {
+ var replaceParams = {
+ type: typeInfo.type,
+ green: typeInfo.green,
+ black: typeInfo.black,
+ asVec4: typeInfo.asVec4,
+ };
+ tests.push({
+ fShaderSource: wtu.replaceParams(wtu.getScript('fragmentShader'), replaceParams),
+ passMsg: typeInfo.type,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true
+ });
+});
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-initializers.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-initializers.html
new file mode 100644
index 0000000000..cdbc59a5c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/ternary-operators-in-initializers.html
@@ -0,0 +1,124 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css" />
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+<title></title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="intFragShader" type="text/something-not-javascript">
+void main() {
+ int i = 2, j = (i > 1) ? 1 : 0;
+ gl_FragColor = vec4(0.0, j, 0.0, 1.0);
+}
+</script>
+<script id="ivec2FragShader" type="text/something-not-javascript">
+void main() {
+ ivec2 i = ivec2(2, 0), j = (i.x > 1) ? ivec2(0, 1) : ivec2(0, 0);
+ gl_FragColor = vec4(j, 0.0, 1.0);
+}
+</script>
+<script id="ivec3FragShader" type="text/something-not-javascript">
+void main() {
+ ivec3 i = ivec3(0, 2, 0), j = (i.y > 1) ? ivec3(0, 1, 0) : ivec3(0, 0, 0);
+ gl_FragColor = vec4(j, 1.0);
+}
+</script>
+<script id="ivec4FragShader" type="text/something-not-javascript">
+void main() {
+ ivec4 i = ivec4(0.0, 0.0, 2.0, 0.0), j = (i.z > 1) ? ivec4(0, 1, 0, 1) : ivec4(0, 0, 0, 1);
+ gl_FragColor = vec4(j);
+}
+</script>
+<script id="floatFragShader" type="text/something-not-javascript">
+void main() {
+ precision mediump float;
+ float i = 2.0, j = (i > 1.0) ? 1.0 : 0.0;
+ gl_FragColor = vec4(0.0, j, 0.0, 1.0);
+}
+</script>
+<script id="vec2FragShader" type="text/something-not-javascript">
+void main() {
+ precision mediump float;
+ vec2 i = vec2(2.0, 0.0), j = (i.x > 1.0) ? vec2(0.0, 1.0) : vec2(0.0, 0.0);
+ gl_FragColor = vec4(j, 0.0, 1.0);
+}
+</script>
+<script id="vec3FragShader" type="text/something-not-javascript">
+void main() {
+ precision mediump float;
+ vec3 i = vec3(0.0, 2.0, 0.0), j = (i.y > 1.0) ? vec3(0.0, 1.0, 0.0) : vec3(0.0, 0.0, 0.0);
+ gl_FragColor = vec4(j, 1.0);
+}
+</script>
+<script id="vec4FragShader" type="text/something-not-javascript">
+void main() {
+ precision mediump float;
+ vec4 i = vec4(0.0, 0.0, 2.0, 0.0), j = (i.z > 1.0) ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0);
+ gl_FragColor = j;
+}
+</script>
+<script id="boolFragShader" type="text/something-not-javascript">
+void main() {
+ bool i = true, j = i ? true : false;
+ gl_FragColor = vec4(0.0, j, 0.0, 1.0);
+}
+</script>
+<script id="bvec2FragShader" type="text/something-not-javascript">
+void main() {
+ bvec2 i = bvec2(true, false), j = i.x ? bvec2(false, true) : bvec2(false, false);
+ gl_FragColor = vec4(j, 0.0, 1.0);
+}
+</script>
+<script id="bvec3FragShader" type="text/something-not-javascript">
+void main() {
+ bvec3 i = bvec3(false, true, false), j = i.y ? bvec3(false, true, false) : bvec3(false, false, false);
+ gl_FragColor = vec4(j, 1.0);
+}
+</script>
+<script id="bvec4FragShader" type="text/something-not-javascript">
+void main() {
+ bvec4 i = bvec4(false, false, true, true), j = i.z ? bvec4(false, true, false, true) : bvec4(false, false, false, true);
+ gl_FragColor = vec4(j);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies initializers with ternary operators correctly initialize all variables.");
+// Test fragment shaders are of the form
+// void main() {
+// {type} i = {initializer}, j = {ternary test using i that succeeds} ? : {green} : {black};
+// gl_FragColor = vec4(...); // Emit green so that test will pass
+// }
+// The fragment shader must compile and link with the default vertex shader. J must be able to use the values of I as well as have its own
+// values properly initialized.
+var tests = [
+ { fShaderId: 'intFragShader', passMsg: 'Ternary operator in integer initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'ivec2FragShader', passMsg: 'Ternary operator in ivec2 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'ivec3FragShader', passMsg: 'Ternary operator in ivec3 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'ivec4FragShader', passMsg: 'Ternary operator in ivec4 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'floatFragShader', passMsg: 'Ternary operator in float initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'vec2FragShader', passMsg: 'Ternary operator in vec2 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'vec3FragShader', passMsg: 'Ternary operator in vec3 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'vec4FragShader', passMsg: 'Ternary operator in vec4 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'boolFragShader', passMsg: 'Ternary operator in bool initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'bvec2FragShader', passMsg: 'Ternary operator in bvec2 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'bvec3FragShader', passMsg: 'Ternary operator in bvec3 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+ { fShaderId: 'bvec4FragShader', passMsg: 'Ternary operator in bvec4 initalization', fShaderSuccess: true, linkSuccess: true, render: true },
+];
+GLSLConformanceTester.runTests(tests);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uniform-location-length-limits.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uniform-location-length-limits.html
new file mode 100644
index 0000000000..8aeaeb1937
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uniform-location-length-limits.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<title>WebGL uniform location length tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+There is supposed to be an example drawing here, but it's not important.
+</canvas>
+<div id="description">Verify limits on the lengths of uniform locations per WebGL spec, "Maximum Uniform and Attribute Location Lengths".</div>
+<div id="console"></div>
+<script id="goodVertexShader" type="x-shader/x-vertex">
+// A vertex shader where the needed uniform location is exactly 256 characters.
+struct Nesting2 {
+ vec4 identifier62CharactersLong_01234567890123456789012345678901234;
+};
+
+struct Nesting1 {
+ Nesting2 identifier64CharactersLong_0123456789012345678901234567890123456;
+};
+
+uniform Nesting1 identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789;
+
+void main() {
+ gl_Position = identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.identifier64CharactersLong_0123456789012345678901234567890123456.identifier62CharactersLong_01234567890123456789012345678901234;
+}
+</script>
+<script id="badVertexShader" type="x-shader/x-vertex">
+// A vertex shader where the needed uniform location is 257 characters.
+struct Nesting2 {
+ vec4 identifier63CharactersLong_012345678901234567890123456789012345;
+};
+
+struct Nesting1 {
+ Nesting2 identifier64CharactersLong_0123456789012345678901234567890123456;
+};
+
+uniform Nesting1 identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789;
+
+void main() {
+ Nesting2 temp = identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.identifier64CharactersLong_0123456789012345678901234567890123456;
+ gl_Position = temp.identifier63CharactersLong_012345678901234567890123456789012345;
+}
+</script>
+<script id="fragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+debug("Test uniform location underneath the length limit");
+var program = wtu.loadProgramFromScript(gl, "goodVertexShader", "fragmentShader");
+shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+var uniformLoc = gl.getUniformLocation(program, "identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.identifier64CharactersLong_0123456789012345678901234567890123456.identifier62CharactersLong_01234567890123456789012345678901234");
+shouldBeNonNull('uniformLoc');
+wtu.glErrorShouldBe(gl, gl.NONE);
+
+debug("Test uniform location over the length limit");
+program = wtu.loadProgramFromScript(gl, "badVertexShader", "fragmentShader");
+wtu.glErrorShouldBe(gl, gl.NONE);
+shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+var uniformLoc = gl.getUniformLocation(program, "identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.identifier64CharactersLong_0123456789012345678901234567890123456.identifier63CharactersLong_012345678901234567890123456789012345");
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+shouldBeNull('uniformLoc');
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uninitialized-local-global-variables.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uninitialized-local-global-variables.html
new file mode 100644
index 0000000000..d0552af096
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/misc/uninitialized-local-global-variables.html
@@ -0,0 +1,274 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Uninitialized local/global variables should be initialized</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+
+<script id="vs_uninit_in_frag" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+
+<!-- Uninitialized local in vertex shader -->
+<script id="vs_uninit_local_in_vert" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 a_position;
+varying vec3 v_uninit;
+void main() {
+ vec3 uninit; // uninitialized
+ v_uninit = uninit;
+ gl_Position = a_position;
+}
+</script>
+<script id="fs_uninit_local_in_vert" type="x-shader/x-fragment">
+precision mediump float;
+varying vec3 v_uninit;
+void main() {
+ gl_FragColor = v_uninit.xyzz;
+}
+</script>
+
+<!-- Uninitialized local in fragment shader -->
+<script id="fs_uninit_local_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ vec2 uninit; // uninitialized
+ gl_FragColor = uninit.xyyy;
+}
+</script>
+
+<!-- Uninitialized global in vertex shader -->
+<script id="vs_uninit_global_in_vert" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 a_position;
+varying float v_uninit;
+float uninit; // uninitialized
+void main() {
+ v_uninit = uninit;
+ gl_Position = a_position;
+}
+</script>
+<script id="fs_uninit_global_in_vert" type="x-shader/x-fragment">
+precision mediump float;
+varying float v_uninit;
+void main() {
+ gl_FragColor = vec4(v_uninit);
+}
+</script>
+
+<!-- Uninitialized global in fragment shader -->
+<script id="fs_uninit_global_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+vec4 uninit; // uninitialized
+void main() {
+ gl_FragColor = uninit;
+}
+</script>
+
+<!-- Uninitialized local int in fragment shader -->
+<script id="fs_uninit_local_int_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ int uninit;
+ gl_FragColor = vec4(uninit);
+}
+</script>
+
+<!-- Uninitialized local variable and another variable in the same declaration using it as an initializer in fragment shader -->
+<script id="fs_uninit_two_local_variables_in_declaration_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ vec2 uninit, uninit2 = uninit;
+ gl_FragColor = uninit2.xyyy;
+}
+</script>
+
+<!-- Uninitialized local array and another variable in the same declaration using it in its initializer in fragment shader -->
+<script id="fs_uninit_array_and_another_in_declaration_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ vec2 uninit[2], uninit2 = uninit[0];
+ gl_FragColor = uninit2.xyyy;
+}
+</script>
+
+<!-- Uninitialized global int in fragment shader -->
+<script id="fs_uninit_global_int_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+int uninit; // uninitialized
+void main() {
+ gl_FragColor = vec4(uninit);
+}
+</script>
+
+<!-- Uninitialized local struct in fragment shader -->
+<script id="fs_uninit_local_struct_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+struct S { vec4 v; };
+void main() {
+ S uninit; // uninitialized
+ gl_FragColor = uninit.v;
+}
+</script>
+
+<!-- Uninitialized global struct in fragment shader -->
+<script id="fs_uninit_global_struct_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+struct S { vec4 v; };
+S uninit; // uninitialized
+void main() {
+ gl_FragColor = uninit.v;
+}
+</script>
+
+<!-- Uninitialized nameless local struct in fragment shader -->
+<script id="fs_uninit_nameless_local_struct_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ struct { vec4 v; } uninit; // uninitialized
+ gl_FragColor = uninit.v;
+}
+</script>
+
+<!-- Uninitialized nameless global struct in fragment shader -->
+<script id="fs_uninit_nameless_global_struct_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+struct { vec4 v; } uninit; // uninitialized
+void main() {
+ gl_FragColor = uninit.v;
+}
+</script>
+
+<!-- Uninitialized local bool in fragment shader -->
+<script id="fs_uninit_local_bool_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ bool uninit[16]; // uninitialized
+ bool result;
+ for (int i = 0; i < 16; i++) {
+ result = result || uninit[i];
+ }
+ gl_FragColor = result ? vec4(1, 0, 0, 1) : vec4(0);
+}
+</script>
+
+<!-- Uninitialized global bool in fragment shader -->
+<script id="fs_uninit_global_bool_in_frag" type="x-shader/x-fragment">
+precision mediump float;
+bool uninit[16]; // uninitialized
+void main() {
+ bool result = false;
+ for (int i = 0; i < 16; i++) {
+ result = result || uninit[i];
+ }
+ gl_FragColor = result ? vec4(1, 0, 0, 1) : vec4(0);
+}
+</script>
+
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Uninitialized local/global variables should be initialized: http://anglebug.com/1966');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+wtu.setupUnitQuad(gl);
+
+var cases = [
+ {
+ name: "Uninitialized local variable in vertex shader",
+ prog: ["vs_uninit_local_in_vert", "fs_uninit_local_in_vert"],
+ },
+ {
+ name: "Uninitialized local variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_local_in_frag"],
+ },
+ {
+ name: "Uninitialized global variable in vertex shader",
+ prog: ["vs_uninit_global_in_vert", "fs_uninit_global_in_vert"],
+ },
+ {
+ name: "Uninitialized global variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_global_in_frag"],
+ },
+ {
+ name: "Uninitialized local int variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_local_int_in_frag"],
+ },
+ {
+ name: "Uninitialized local variable and another variable in the same declaration using it as an initializer in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_two_local_variables_in_declaration_in_frag"],
+ },
+ {
+ name: "Uninitialized local array and another variable in the same declaration using it in its initializer in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_array_and_another_in_declaration_in_frag"],
+ },
+ {
+ name: "Uninitialized global int variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_global_int_in_frag"],
+ },
+ {
+ name: "Uninitialized local struct variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_local_struct_in_frag"],
+ },
+ {
+ name: "Uninitialized global struct variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_global_struct_in_frag"],
+ },
+ {
+ name: "Uninitialized nameless local struct variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_nameless_local_struct_in_frag"],
+ },
+ {
+ name: "Uninitialized nameless global struct variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_nameless_global_struct_in_frag"],
+ },
+ {
+ name: "Uninitialized local bool array variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_local_bool_in_frag"],
+ },
+ {
+ name: "Uninitialized global bool array variable in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_global_bool_in_frag"],
+ },
+];
+
+function runTest() {
+ for (var i = 0; i < cases.length; ++i) {
+ debug("");
+ debug(cases[i].name);
+ var program = wtu.setupProgram(gl, cases[i].prog, ["a_position"], undefined, true);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 0, 0]);
+ }
+
+ debug("");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/00_test_list.txt
new file mode 100644
index 0000000000..110657c1f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/00_test_list.txt
@@ -0,0 +1,2 @@
+--min-version 1.0.4 comments.html
+--min-version 1.0.4 macro-expansion-tricky.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/comments.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/comments.html
new file mode 100644
index 0000000000..0e3dfb3e32
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/comments.html
@@ -0,0 +1,204 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Comments</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+// Your syntax highlighter may hate this file.
+// Because this stuff is tricky, we collect all tests here, including duplicating from other tests.
+// That way, this test file is a one-stop-shop for validation testing.
+
+const nonAscii = [
+ 65533,
+ 65533,
+ 65533,
+ 65533,
+ 834,
+ 96,
+ 65533,
+ 114,
+ 65533,
+ 98,
+ 65533,
+ 104,
+ 65533,
+ 104,
+ 65533,
+ 322,
+ 834,
+ 514,
+ 65533,
+ 65533,
+ 322,
+ 65533,
+ 65533,
+ 66,
+].map(x => String.fromCodePoint(x)).join('');
+
+GLSLConformanceTester.runTests([{
+ vShaderSource: `void main() {}`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Normal minimal testcase'
+ }, {
+ vShaderSource: `void main() {}/*`,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Missing block-comment-end'
+ }, {
+ vShaderSource: `void main() {}/**`,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Partial block-comment-end'
+ }, {
+ vShaderSource: `void main() {}/**/`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Complete block-comment-end'
+ }, {
+ vShaderSource: `void main() {}/* **/`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Complete block-comment-end with **/'
+ }, {
+ vShaderSource: `void main() {}/`,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Partial line-comment-begin at EOF'
+ }, {
+ vShaderSource: `void main() {}//`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Complete line-comment-begin at EOF'
+ }, {
+ vShaderSource: `//
+void main() {}`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: `Minimal line comment: "//,\\n"`
+ }, {
+ vShaderSource: `//\
+
+void main() {}`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: `Minimal continued line comment: "//,\\,\\n,\\n"`
+ }, {
+ vShaderSource: `//\
+a
+void main() {}`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: `Line-comment continuation with content that must be skipped: "//,\\,\\n,a,\\n"`
+ }, {
+ vShaderSource: `void main() {} // The quick brown fox jumped\\over the lazy dog`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Backslash in comment'
+ }, {
+ vShaderSource: `void main() {} // The quick brown fox jumped\\over the lazy dog
+`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Backslash in comment with newline before EOF'
+ }, {
+ vShaderSource: `void main() {} // The quick brown fox jumped\\
+over the lazy dog`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Line-comment with backslash-line-continuation'
+ }, {
+ vShaderSource: `void main() {} // The quick brown fox jumped\\
+over the lazy dog
+`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Line-comment with backslash-line-continuation with newline before EOF'
+ }, {
+ vShaderSource: `void main() {}//${String.fromCodePoint(0x8f)}`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'upper-ascii in line-comment'
+ }, {
+ vShaderSource: `void main() {}/*${String.fromCodePoint(0x8f)}*/`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'upper-ascii in block-comment'
+
+ // -
+ // Like comment_frag.frag from conformance/ogles/GL/build/build_049_to_056.html
+ }, {
+ vShaderSource: `
+void main()
+{
+ /****** // comment not closed
+}`,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Unclosed block-comment containing line-comment'
+
+
+ // -
+ // Like conformance/glsl/misc/non-ascii-comments.vert.html
+ }, {
+ vShaderSource: `void main() {}/*${String.fromCodePoint(0x8f)}`,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'upper-ascii in unterminated block-comment'
+ }, {
+ vShaderSource: `void main() {}// ${nonAscii}`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'More non-ascii in line-comment'
+ }, {
+ vShaderSource: `void main() {}/*
+ * ${nonAscii}
+ */`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'More non-ascii in block-comment'
+ }, {
+ vShaderSource: `void main() {}/*
+ * ${nonAscii}
+ *`,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'More non-ascii in unterminated block-comment'
+
+
+ // -
+ // Like deqp/data/gles2/shaders/preprocessor.html | preprocessor.comments.comment_trick_2_*
+ }, {
+ vShaderSource: `void main() {
+ float out0;
+ /**/
+ out0 = 1.0;
+ /*/
+ out0 = 0.0;
+ /**/
+ }`,
+ vShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: '/**/ /*/ /**/'
+}]);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/macro-expansion-tricky.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/macro-expansion-tricky.html
new file mode 100644
index 0000000000..8c925f4d7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/preprocessor/macro-expansion-tricky.html
@@ -0,0 +1,46 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Tricky macro expansion</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderRecursiveMacroNameInsideIncompleteMacroInvocationInMacroExpansion" type="x-shader/x-fragment">
+#define m(a)
+#define a m((a)
+a)
+
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshaderRecursiveMacroNameInsideIncompleteMacroInvocationInMacroExpansion',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Recursive macro name inside incomplete macro invocation in macro expansion should not crash'
+}
+]);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/00_test_list.txt
new file mode 100644
index 0000000000..7c2da3e8f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/00_test_list.txt
@@ -0,0 +1,8 @@
+_webgl_field.vert.html
+_webgl_function.vert.html
+_webgl_struct.vert.html
+_webgl_variable.vert.html
+webgl_field.vert.html
+webgl_function.vert.html
+webgl_struct.vert.html
+webgl_variable.vert.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_field.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_field.vert.html
new file mode 100644
index 0000000000..b9bba36da7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_field.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved _webgl prefix as structure field should fail
+struct Foo {
+ int _webgl_bar;
+};
+
+void main() {
+ Foo foo = Foo(1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_function.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_function.vert.html
new file mode 100644
index 0000000000..ea9586fd53
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_function.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved _webgl prefix as function name should fail
+vec4 _webgl_foo() {
+ return vec4(1.0);
+}
+
+void main() {
+ gl_Position = _webgl_foo();
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_struct.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_struct.vert.html
new file mode 100644
index 0000000000..df61e9d7d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_struct.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved _webgl prefix as structure name should fail
+struct _webgl_Foo {
+ int bar;
+};
+
+void main() {
+ _webgl_Foo foo = _webgl_Foo(1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_variable.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_variable.vert.html
new file mode 100644
index 0000000000..bcae6ec7ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/_webgl_variable.vert.html
@@ -0,0 +1,34 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved _webgl prefix as structure field should fail
+void main() {
+ vec4 _webgl_foo;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_field.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_field.vert.html
new file mode 100644
index 0000000000..a41712661f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_field.vert.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved webgl_ prefix as structure field should fail
+struct Foo {
+ int webgl_bar;
+};
+
+void main() {
+ Foo foo = Foo(1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_function.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_function.vert.html
new file mode 100644
index 0000000000..4a9ac1698a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_function.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved webgl_ prefix as function name should fail
+vec4 webgl_foo() {
+ return vec4(1.0);
+}
+
+void main() {
+ gl_Position = webgl_foo();
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_struct.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_struct.vert.html
new file mode 100644
index 0000000000..a5a0294a3d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_struct.vert.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved webgl_ prefix as structure name should fail
+struct webgl_Foo {
+ int bar;
+};
+
+void main() {
+ webgl_Foo foo = webgl_Foo(1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_variable.vert.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_variable.vert.html
new file mode 100644
index 0000000000..f2b6708e9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/reserved/webgl_variable.vert.html
@@ -0,0 +1,34 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+
+// use of reserved webgl_ prefix as variable should fail
+void main() {
+ vec4 webgl_foo;
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/00_test_list.txt
new file mode 100644
index 0000000000..c0f612d81d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/00_test_list.txt
@@ -0,0 +1,4 @@
+glsl-function-texture2d-bias.html
+glsl-function-texture2dlod.html
+glsl-function-texture2dproj.html
+--min-version 1.0.3 glsl-function-texture2dprojlod.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2d-bias.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2d-bias.html
new file mode 100644
index 0000000000..073276615f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2d-bias.html
@@ -0,0 +1,101 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture2D GLSL conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="256" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader2d" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main() {
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+<script id="fshader2d" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+uniform float bias;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2D(tex, texCoord, bias);
+}
+</script>
+<script>
+"use strict";
+description("tests GLSL texture2D function with bias");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+
+shouldBe("canvas.width", "256");
+shouldBe("canvas.height", "256");
+
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupProgram(
+ gl, ['vshader2d', 'fshader2d'], ['vPosition', 'texCoord0'], [0, 1]);
+wtu.setupUnitQuad(gl, 0, 1);
+
+var colors = [
+ {name: 'red', color:[255, 0, 0, 255]},
+ {name: 'green', color:[0, 255, 0, 255]},
+ {name: 'blue', color:[0, 0, 255, 255]},
+ {name: 'yellow', color:[255, 255, 0, 255]},
+ {name: 'magenta', color:[255, 0, 255, 255]},
+ {name: 'cyan', color:[0, 255, 255, 255]},
+ {name: 'pink', color:[255, 128, 128, 255]},
+ {name: 'gray', color:[128, 128, 128, 255]},
+ {name: 'light green', color:[128, 255, 128, 255]},
+];
+
+shouldBe("colors.length", "9");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+for (var ii = 0; ii < colors.length; ++ii) {
+ var color = colors[ii];
+ var size = Math.pow(2, colors.length - ii - 1);
+ wtu.fillTexture(gl, tex, size, size, color.color, ii);
+}
+
+var loc = gl.getUniformLocation(program, "bias");
+
+for (var ii = 0; ii < colors.length; ++ii) {
+ gl.uniform1f(loc, ii);
+ var color = colors[ii];
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, color.color,
+ "256x256 texture drawn to 256x256 dest with bias = " + ii +
+ " should be " + color.name);
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dlod.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dlod.html
new file mode 100644
index 0000000000..41387bca15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dlod.html
@@ -0,0 +1,109 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture2D GLSL conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="256" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader2d" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec4 color;
+uniform sampler2D tex;
+uniform float lod;
+void main() {
+ gl_Position = vPosition;
+ color = texture2DLod(tex, texCoord0, lod);
+}
+</script>
+<script id="fshader2d" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragData[0] = color;
+}
+</script>
+<script>
+"use strict";
+description("tests GLSL texture2DLod function");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+
+shouldBe("canvas.width", "256");
+shouldBe("canvas.height", "256");
+
+var colors = [
+ {name: 'red', color:[255, 0, 0, 255]},
+ {name: 'green', color:[0, 255, 0, 255]},
+ {name: 'blue', color:[0, 0, 255, 255]},
+ {name: 'yellow', color:[255, 255, 0, 255]},
+ {name: 'magenta', color:[255, 0, 255, 255]},
+ {name: 'cyan', color:[0, 255, 255, 255]},
+ {name: 'pink', color:[255, 128, 128, 255]},
+ {name: 'gray', color:[128, 128, 128, 255]},
+ {name: 'light green', color:[128, 255, 128, 255]},
+];
+
+var gl = wtu.create3DContext(canvas);
+if (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) > 0) {
+ runTest();
+} else {
+ testPassed("MAX_VERTEX_TEXTURE_IMAGE_UNITS == 0, this is okay.");
+}
+
+function runTest() {
+ var program = wtu.setupProgram(
+ gl, ['vshader2d', 'fshader2d'], ['vPosition', 'texCoord0'], [0, 1]);
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ shouldBe("colors.length", "9");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var color = colors[ii];
+ var size = Math.pow(2, colors.length - ii - 1);
+ wtu.fillTexture(gl, tex, size, size, color.color, ii);
+ }
+
+ var loc = gl.getUniformLocation(program, "lod");
+
+ for (var ii = 0; ii < colors.length; ++ii) {
+ gl.uniform1f(loc, ii);
+ var color = colors[ii];
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, color.color,
+ "256x256 texture drawn to 256x256 dest with lod = " + ii +
+ " should be " + color.name);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+}
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dproj.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dproj.html
new file mode 100644
index 0000000000..c9e042f9a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dproj.html
@@ -0,0 +1,116 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture2D GLSL conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader0" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main() {
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+<script id="fshader0" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+uniform float divisor;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2DProj(tex, vec3(texCoord, divisor));
+}
+</script>
+<script id="vshader1" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main() {
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+uniform float divisor;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2DProj(tex, vec4(texCoord, 123.0, divisor));
+}
+</script>
+<script>
+"use strict";
+description("tests GLSL texture2DProj function with");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", {antialias: false});
+
+wtu.setupUnitQuad(gl, 0, 1);
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+var c = document.createElement("canvas");
+c.width = 16;
+c.height = 16;
+var ctx = c.getContext("2d");
+ctx.fillStyle = "rgb(0,255,0)";
+ctx.fillRect(0, 0, 16, 16);
+ctx.fillStyle = "rgb(0,0,255)";
+ctx.fillRect(0, 0, 8, 8);
+ctx.fillRect(8, 8, 8, 8);
+
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+
+for (var ss = 0; ss < 2; ++ss) {
+ debug("");
+ debug(ss ? "testing vec4 version" : "testing vec3 version");
+ var program = wtu.setupProgram(
+ gl, ['vshader' + ss, 'fshader' + ss],
+ ['vPosition', 'texCoord0'], [0, 1]);
+ gl.useProgram(program);
+ var loc = gl.getUniformLocation(program, "divisor");
+
+ for (var ii = 0; ii < 3; ++ii) {
+ var denominator = Math.pow(2, ii);
+ gl.uniform1f(loc, 1 / denominator);
+ wtu.clearAndDrawUnitQuad(gl);
+ var size = 16 / denominator;
+ for (var yy = 0; yy < 32; yy += size) {
+ for (var xx = 0; xx < 32; xx += size) {
+ var odd = (xx / size + yy / size) % 2;
+ var color = odd ? [0, 255, 0, 255] : [0, 0, 255, 255];
+ var msg = "" + xx + ", " + yy + ", " + size + ", " + size + " should be " + (odd ? "green" : "blue");
+ wtu.checkCanvasRect(gl, xx, yy, size, size, color, msg);
+ }
+ }
+ }
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dprojlod.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dprojlod.html
new file mode 100644
index 0000000000..c7c091ee8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/samplers/glsl-function-texture2dprojlod.html
@@ -0,0 +1,162 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture2D GLSL conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="256" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader2dvec3" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 color;
+uniform sampler2D tex;
+uniform float divisor;
+uniform float lod;
+void main() {
+ gl_Position = vPosition;
+ color = texture2DProjLod(tex, vec3(0.75 * divisor, 0.25 * divisor, divisor), lod);
+}
+</script>
+<script id="vshader2dvec4" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 color;
+uniform sampler2D tex;
+uniform float divisor;
+uniform float lod;
+void main() {
+ gl_Position = vPosition;
+ color = texture2DProjLod(tex, vec4(0.75 * divisor, 0.25 * divisor, 123.0, divisor), lod);
+}
+</script>
+<script id="fshader2d" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragData[0] = color;
+}
+</script>
+<script>
+"use strict";
+description("tests GLSL texture2DProjLod function");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+
+shouldBe("canvas.width", "256");
+shouldBe("canvas.height", "256");
+
+var colors = [
+ {name: 'red', color:[255, 0, 0, 255]},
+ {name: 'green', color:[0, 255, 0, 255]},
+ {name: 'blue', color:[0, 0, 255, 255]},
+ {name: 'yellow', color:[255, 255, 0, 255]},
+ {name: 'magenta', color:[255, 0, 255, 255]},
+ {name: 'cyan', color:[0, 255, 255, 255]},
+ {name: 'pink', color:[255, 128, 128, 255]},
+ {name: 'gray', color:[128, 128, 128, 255]},
+ {name: 'light green', color:[128, 255, 128, 255]},
+];
+var contextTypes = ["2d", "webgl"];
+var vectorTypes = ["vec3", "vec4"];
+
+var gl = wtu.create3DContext(canvas);
+if (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) > 0) {
+ runTest();
+} else {
+ testPassed("MAX_VERTEX_TEXTURE_IMAGE_UNITS == 0, this is okay.");
+}
+
+
+function runTest() {
+ // Avoid creating a WebGL context for every test, as it causes:
+ // Too many active WebGL contexts. Oldest context will be lost.
+ var canvasWebGL = document.createElement("canvas");
+ var ctxWebGL = canvasWebGL.getContext("webgl");
+
+ // Might as well do the same for canvas 2d
+ var canvas2d = document.createElement("canvas");
+ var ctx2d = canvas2d.getContext("2d");
+
+ shouldBe("colors.length", "9");
+ contextTypes.forEach((context) => {
+ vectorTypes.forEach((vectorType) => {
+ debug("");
+ debug(`testing ${context} context with ${vectorType} vertex shader`);
+ var program = wtu.setupProgram(
+ gl, ['vshader2d' + vectorType, 'fshader2d'], ['vPosition', 'texCoord0'], [0, 1]);
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ // Fill the top right quadrant of each texture level with one of the colors
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var color = colors[ii];
+ var size = Math.pow(2, colors.length - ii - 1);
+
+ if (context === "2d") {
+ canvas2d.width = size;
+ canvas2d.height = size;
+ ctx2d.fillStyle = "rgb(0,0,0)";
+ ctx2d.fillRect(0, 0, size, size);
+ ctx2d.fillStyle = "rgb(" + color.color[0] + "," + color.color[1] + "," + color.color[2] + ")";
+ ctx2d.fillRect(size / 2, 0, size / 2, size / 2);
+ gl.texImage2D(gl.TEXTURE_2D, ii, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+ } else if (context === "webgl") {
+ canvasWebGL.width = canvasWebGL.height = size;
+ ctxWebGL.clearColor(0, 0, 0, 1);
+ ctxWebGL.clear(gl.COLOR_BUFFER_BIT);
+ ctxWebGL.enable(gl.SCISSOR_TEST);
+ ctxWebGL.scissor(size/2, size/2, size/2, size/2)
+ ctxWebGL.clearColor(color.color[0]/255, color.color[1]/255, color.color[2]/255, 1)
+ ctxWebGL.clear(gl.COLOR_BUFFER_BIT);
+ gl.texImage2D(gl.TEXTURE_2D, ii, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvasWebGL);
+ }
+ }
+
+ var lodLoc = gl.getUniformLocation(program, "lod");
+ var divLoc = gl.getUniformLocation(program, "divisor");
+
+ for (var div = 1; div < 4; ++div) {
+ for (var ii = 0; ii < colors.length - 1; ++ii) {
+ gl.uniform1f(lodLoc, ii);
+ gl.uniform1f(divLoc, div);
+ var lodColor = colors[ii];
+ var size = Math.pow(2, colors.length - ii - 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, lodColor.color,
+ "sampling with lod = " + ii +
+ " divider = " + div +
+ " should be " + lodColor.name);
+ }
+ }
+ });
+ });
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+}
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/00_test_list.txt
new file mode 100644
index 0000000000..31fe0f8f20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/00_test_list.txt
@@ -0,0 +1,6 @@
+gl-fragcoord.html
+gl-frontfacing.html
+gl-pointcoord.html
+--min-version 1.0.2 glsl-built-ins.html
+--min-version 1.0.3 gl-fragcoord-xy-values.html
+--min-version 1.0.3 gl-fragdata-and-fragcolor.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord-xy-values.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord-xy-values.html
new file mode 100644
index 0000000000..161a58bfc6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord-xy-values.html
@@ -0,0 +1,185 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>gl-fragcoord Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="32" height="32">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+// Inputs
+attribute vec4 aPosInfo;
+
+// Outputs
+varying vec2 vTargetPixelCoord;
+
+void main()
+{
+ vTargetPixelCoord = aPosInfo.zw;
+
+ gl_PointSize = 1.0;
+ gl_Position = vec4(aPosInfo.xy, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+// Inputs
+varying vec2 vTargetPixelCoord;
+
+// Colors used to signal correctness
+const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
+const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);
+
+void main()
+{
+ // Check pixel index
+ bool pixelIxValid = (floor(gl_FragCoord.xy) == vTargetPixelCoord);
+
+ // Check fractional part of coordinates
+ bool fracCoordValid = all(lessThan(abs(fract(gl_FragCoord.xy) - vec2(0.5)), vec2(0.0001)));
+
+ gl_FragColor = (pixelIxValid && fracCoordValid) ? green : red;
+}
+</script>
+
+<script id="test_fshader" type="x-shader/x-fragment">
+// Shader to test if the frame buffer positions within the output pixel are different for the five render passes
+// Pass on frame buffer position in varying, change in vertex shader : vTargetPixelCoord = aPosInfo.xy;
+// Set test_fshader in setupProgram()
+
+precision mediump float;
+
+// Inputs
+varying vec2 vTargetPixelCoord;
+
+const vec2 pixSize = vec2(2.0/32.0, 2.0/32.0);
+
+void main()
+{
+ // Coordinates within a framebuffer pixel [0, 1>
+ vec2 inPixelCoord = fract(vTargetPixelCoord / pixSize);
+
+ // Create different color dependent on the position inside the framebuffer pixel
+ float r = (inPixelCoord.x < 0.4) ? 0.2 : (inPixelCoord.x > 0.6) ? 0.8 : 0.5;
+ float g = (inPixelCoord.y < 0.4) ? 0.2 : (inPixelCoord.y > 0.6) ? 0.8 : 0.5;
+
+ gl_FragColor = vec4(r, g, 0.0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+
+// Test if gl_FragCoord.xy values are always of the form :
+// (first framebuffer pixel index + 0.5, second framebuffer pixel index + 0.5)
+// (if no multisampling)
+
+// This is done by rendering a set of points which targets either the center of the
+// output pixel or the center of one of the quadrants
+
+// Constants
+var floatsPerAttribute = 4;
+
+// Globals
+var wtu;
+var gl;
+var program;
+var vxBuffer;
+
+// Set data for one attribute (framebuffer.xy, pixel_index.xy)
+function setPixelData(data, dIx, xx, yy, xSize, ySize, xOffset, yOffset)
+{
+ // Frame buffer first coordinate [-1, 1]
+ data[dIx++] = (xx + 0.5) * xSize + xOffset - 1;
+
+ // Frame buffer second coordinate [-1, 1]
+ data[dIx++] = (yy + 0.5) * ySize + yOffset - 1;
+
+ // Frame buffer pixel first index
+ data[dIx++] = xx;
+
+ // Frame buffer pixel second index
+ data[dIx++] = yy;
+
+ return dIx;
+}
+
+// Create attribute data
+function createAttributeData(xOffset, yOffset)
+{
+ // Retrieve realised dimensions of viewport
+ var widthPx = gl.drawingBufferWidth;
+ var heightPx = gl.drawingBufferHeight;
+ var pixelCount = widthPx * heightPx;
+
+ // Pixel size in framebuffer coordinates
+ var pWidth = 2 / widthPx;
+ var pHeight = 2 / heightPx;
+ var data = new Float32Array(pixelCount * floatsPerAttribute);
+ var dIx = 0;
+ for (var yy = 0; yy < heightPx; ++yy)
+ for (var xx = 0; xx < widthPx; ++xx)
+ dIx = setPixelData(data, dIx, xx, yy, pWidth, pHeight, xOffset * pWidth, yOffset * pHeight);
+
+ if (dIx !== data.length)
+ wtu.error("gl-fragcoord-xy-values.html, createAttributeData(), index not correct at end");
+
+ return data;
+}
+
+// Initialize test
+function init()
+{
+ description("tests gl_FragCoord.xy values");
+
+ wtu = WebGLTestUtils;
+ gl = wtu.create3DContext("canvas", { antialias: false });
+ program = wtu.setupProgram(gl, ["vshader", "fshader"], ["aPosInfo"]);
+ vxBuffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, vxBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, floatsPerAttribute, gl.FLOAT, false, 0, 0);
+}
+
+// Render data
+function render(xOffset, yOffset, passMsg)
+{
+ // Set attribute data
+ var data = createAttributeData(xOffset, yOffset);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.POINTS, 0, data.length / floatsPerAttribute);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+ var green = [0, 255, 0, 255];
+ wtu.checkCanvas(gl, green, passMsg);
+}
+
+// Run tests
+init();
+render(0, 0, "green : sampling at center of output pixel is correct");
+render(0.25, 0.25, "green : sampling in top right quadrant of output pixel is correct");
+render(-0.25, 0.25, "green : sampling in top left quadrant of output pixel is correct");
+render( 0.25, -0.25, "green : sampling in bottom right quadrant of output pixel is correct");
+render(-0.25, -0.25, "green : sampling in bottom left quadrant of output pixel is correct");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord.html
new file mode 100644
index 0000000000..e5f6e27537
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragcoord.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>gl-fragcoord Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="32" height="32">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(
+ floor(gl_FragCoord.x * 4.0 / 32.0) / 4.0,
+ floor(gl_FragCoord.y * 4.0 / 32.0) / 4.0,
+ floor(gl_FragCoord.z * 4.0) / 4.0,
+ 1);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description("tests gl_FragCoord");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [-1, -1, -1, 1, -1, 0, -1, 1, 0,
+ -1, 1, 0, 1, -1, 0, 1, 1, 1]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ for (var xx = 0; xx < 32; xx += 4) {
+ for (var yy = 0; yy < 32; yy += 4) {
+ var zz = (xx / 64) + (yy / 64);
+ var color = [
+ Math.floor(Math.floor(xx * 4.0 / 32.0) / 4 * 256),
+ Math.floor(Math.floor(yy * 4.0 / 32.0) / 4 * 256),
+ Math.floor(Math.floor(zz * 4.0) / 4 * 256)
+ ];
+ var msg = "should be " + color;
+ wtu.checkCanvasRect(gl, xx, yy, 1, 1, color, msg, 4);
+ }
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragdata-and-fragcolor.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragdata-and-fragcolor.html
new file mode 100644
index 0000000000..5f0e82e8af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-fragdata-and-fragcolor.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragmentShader" type="text/something-not-javascript">
+// fragment shader with static assignment to both gl_FragData[0] and gl_FragColor should fail.
+// GLES spec section 3.8.2 subsection Shader Outputs.
+precision mediump float;
+
+void main()
+{
+ gl_FragData[0] = vec4(1, 0, 0, 1);
+ gl_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-frontfacing.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-frontfacing.html
new file mode 100644
index 0000000000..1716161bcf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-frontfacing.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>gl-fragcoord Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="32" height="32">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(
+ gl_FrontFacing ? 1.0 : 0.0,
+ gl_FrontFacing ? 0.0 : 1.0,
+ 0,
+ 1);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description("tests gl_FrontFacing");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var gridRes = 4;
+ wtu.setupIndexedQuad(gl, gridRes, 0, true);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ var step = 32 / gridRes;
+ var halfStep = step / 2;
+ var quarterStep = halfStep / 2;
+ for (var xx = 0; xx < 32; xx += step) {
+ for (var yy = 0; yy < 32; yy += step) {
+ for (var ii = 0; ii < 2; ++ii) {
+ var color = [
+ ii == 0 ? 255 : 0,
+ ii == 0 ? 0 : 255,
+ 0
+ ];
+ var msg = "should be " + color;
+ wtu.checkCanvasRect(
+ gl,
+ xx + quarterStep + halfStep * ii,
+ yy + quarterStep + halfStep * ii,
+ 1, 1, color, msg, 4);
+ }
+ }
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-pointcoord.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-pointcoord.html
new file mode 100644
index 0000000000..f87078a6ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/gl-pointcoord.html
@@ -0,0 +1,141 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>gl-pointcoord Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="256">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+uniform float uPointSize;
+void main()
+{
+ gl_PointSize = uPointSize;
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(
+ gl_PointCoord.x,
+ gl_PointCoord.y,
+ 0,
+ 1);
+}
+</script>
+
+<script>
+"use strict";
+description("Checks gl_PointCoord and gl_PointSize");
+debug("");
+
+// NOTE: I'm not 100% confident in this test. I think it is correct.
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+shouldBeNonNull("gl");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var canvas = gl.canvas;
+var width = canvas.width;
+var height = canvas.height;
+shouldBe("width", "height");
+
+var maxPointSize = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE)[1];
+shouldBeTrue("maxPointSize >= 1");
+// The minimum and maximum point sizes may be floating-point numbers.
+shouldBeTrue("Math.floor(maxPointSize) >= 1");
+maxPointSize = Math.floor(maxPointSize);
+shouldBeTrue("maxPointSize % 1 == 0");
+
+maxPointSize = Math.min(maxPointSize, 64);
+var pointWidth = maxPointSize / width;
+var pointStep = Math.floor(maxPointSize / 4);
+var pointStep = Math.max(1, pointStep);
+
+var pointSizeLoc = gl.getUniformLocation(program, "uPointSize");
+gl.uniform1f(pointSizeLoc, maxPointSize);
+
+var pixelOffset = (maxPointSize % 2) ? (1 / width) : 0;
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [-0.5 + pixelOffset, -0.5 + pixelOffset,
+ 0.5 + pixelOffset, -0.5 + pixelOffset,
+ -0.5 + pixelOffset, 0.5 + pixelOffset,
+ 0.5 + pixelOffset, 0.5 + pixelOffset]),
+ gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+gl.drawArrays(gl.POINTS, 0, 4);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+function s2p(s) {
+ return (s + 1.0) * 0.5 * width;
+}
+
+//function print(x, y) {
+// var b = new Uint8Array(4);
+// gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, b);
+// debug("" + x + "," + y + ": " + b[0] + "," + b[1] + "," + b[2]);
+//}
+//
+//for (var ii = 0; ii < 100; ++ii) {
+// print(ii, ii);
+//}
+
+for (var py = 0; py < 2; ++py) {
+ for (var px = 0; px < 2; ++px) {
+ debug("");
+ var pointX = -0.5 + px + pixelOffset;
+ var pointY = -0.5 + py + pixelOffset;
+ for (var yy = 0; yy < maxPointSize; yy += pointStep) {
+ for (var xx = 0; xx < maxPointSize; xx += pointStep) {
+ // formula for s and t from OpenGL ES 2.0 spec section 3.3
+ var xw = s2p(pointX);
+ var yw = s2p(pointY);
+ //debug("xw: " + xw + " yw: " + yw);
+ var u = xx / maxPointSize * 2 - 1;
+ var v = yy / maxPointSize * 2 - 1;
+ var xf = Math.floor(s2p(pointX + u * pointWidth));
+ var yf = Math.floor(s2p(pointY + v * pointWidth));
+ //debug("xf: " + xf + " yf: " + yf);
+ var s = 0.5 + (xf + 0.5 - xw) / maxPointSize;
+ var t = 0.5 + (yf + 0.5 - yw) / maxPointSize;
+ //debug("s: " + s + " t: " + t);
+ var color = [Math.floor(s * 255), Math.floor((1 - t) * 255), 0];
+ var msg = "pixel " + xf + "," + yf + " should be " + color;
+ wtu.checkCanvasRect(gl, xf, yf, 1, 1, color, msg, 4);
+ }
+ }
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/glsl-built-ins.html b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/glsl-built-ins.html
new file mode 100644
index 0000000000..32c3f8f5e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/glsl/variables/glsl-built-ins.html
@@ -0,0 +1,106 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL built in variables Conformance Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+}
+</script>
+<script id="vshaderCheck" type="x-shader/x-vertex">
+attribute vec4 a_position;
+varying vec4 v_color;
+void main()
+{
+ gl_Position = a_position;
+ v_color = (gl_$(name) == $(max)) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main()
+{
+ gl_FragColor = v_color;
+}
+</script>
+<script id="fshaderCheck" type="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = (gl_$(name) == $(max)) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script>
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var contextVersion = wtu.getDefault3DContextVersion();
+
+var variables = [
+ { name: 'MaxVertexAttribs', min: 8, },
+ { name: 'MaxVertexUniformVectors', min: 128, },
+ { name: 'MaxVaryingVectors', min: 8, },
+ { name: 'MaxVertexTextureImageUnits', min: 0, },
+ { name: 'MaxCombinedTextureImageUnits', min: 8, },
+ { name: 'MaxTextureImageUnits', min: 8, },
+ { name: 'MaxFragmentUniformVectors', min: 16, },
+];
+
+if (contextVersion <= 1) {
+ variables.push({ name: 'MaxDrawBuffers', min: 1, max: 1});
+} else {
+ variables.push({ name: 'MaxDrawBuffers', min: 1, });
+}
+
+var toUnderscore = function(str) {
+ return str.replace(/([a-z])([A-Z])/g, function (g) { return g[0] + "_" + g[1].toUpperCase() }).toUpperCase();
+};
+
+var shaderPairs = [
+ [wtu.getScript("vshader"), wtu.getScript("fshaderCheck")],
+ [wtu.getScript("vshaderCheck"), wtu.getScript("fshader")],
+];
+
+wtu.setupUnitQuad(gl);
+
+variables.forEach(function(variable) {
+ debug("");
+ debug("Testing gl_" + variable.name);
+ if (!variable.max) {
+ variable.max = gl.getParameter(gl[toUnderscore(variable.name)]);
+ expectTrue(variable.max >= variable.min, "gl.getParameter(gl." + toUnderscore(variable.name) + ") >= " + variable.min);
+ }
+ shaderPairs.forEach(function(pair) {
+ var shaders = [wtu.replaceParams(pair[0], variable), wtu.replaceParams(pair[1], variable)];
+ var program = wtu.setupProgram(gl, shaders, ["a_position"], undefined, true);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ });
+});
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/limits/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/limits/00_test_list.txt
new file mode 100644
index 0000000000..79eb84a48e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/limits/00_test_list.txt
@@ -0,0 +1,6 @@
+--min-version 1.0.4 gl-line-width.html
+gl-min-attribs.html
+gl-max-texture-dimensions.html
+gl-min-textures.html
+gl-min-uniforms.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-line-width.html b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-line-width.html
new file mode 100644
index 0000000000..e446c62a94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-line-width.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify that line width limits are enforced.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+// Query the line width range
+var lineWidthRange = gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+if (lineWidthRange[0] > 1 || lineWidthRange[1] < 1)
+ testFailed("Line width range must include width 1");
+
+// Zero, negative, or NaN values should cause an error and leave the value unchanged.
+var curLineWidth = gl.getParameter(gl.LINE_WIDTH);
+gl.lineWidth(0);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Should not be able to set lineWidth to zero");
+shouldBe('gl.getParameter(gl.LINE_WIDTH)', 'curLineWidth'); // Previous value should be preserved
+
+gl.lineWidth(-1);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Should not be able to set lineWidth to a negative value");
+shouldBe('gl.getParameter(gl.LINE_WIDTH)', 'curLineWidth'); // Previous value should be preserved
+
+gl.lineWidth(NaN);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Should not be able to set lineWidth to NaN");
+shouldBe('gl.getParameter(gl.LINE_WIDTH)', 'curLineWidth'); // Previous value should be preserved
+
+// Check that the line width can be set to the valid range.
+gl.lineWidth(lineWidthRange[1]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be able to set lineWidth to the max supported value");
+shouldBe('gl.getParameter(gl.LINE_WIDTH)', 'lineWidthRange[1]');
+
+gl.lineWidth(lineWidthRange[0]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be able to set lineWidth to the min supported value");
+shouldBe('gl.getParameter(gl.LINE_WIDTH)', 'lineWidthRange[0]');
+
+// Checks that the line width can be set outside the supported range without error,
+// and the unclamped value can be queried back.
+// Yes, this is actually what the spec says should happen.
+// See: https://www.khronos.org/opengles/sdk/docs/man3/html/glLineWidth.xhtml
+gl.lineWidth(lineWidthRange[1]+1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be able to set lineWidth to the above max supported value");
+shouldBe('gl.getParameter(gl.LINE_WIDTH)', 'lineWidthRange[1]+1');
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-max-texture-dimensions.html b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-max-texture-dimensions.html
new file mode 100644
index 0000000000..a9c5850225
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-max-texture-dimensions.html
@@ -0,0 +1,109 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL the max advertized texture size is supported.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform samplerCube tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = textureCube(tex, normalize(vec3(texCoord, 1)));
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+function shouldBePowerOfTwo(n, name) {
+ var power = Math.round(Math.log(n) / Math.log(2));
+ if (Math.pow(2, power) == n) {
+ testPassed(name + ' is a power of two.');
+ } else {
+ testFailed(name + ' should be a power of two, but was ' + n);
+ }
+}
+
+// Note: It seems like a reasonable assuption that a 1xN texture size should
+// work. Even 1 by 128k is only 512k
+var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+debug("advertised max size: " + maxSize);
+debug("verifying max size is power-of-two (implied by GLES 2.0 section 3.7.1)");
+shouldBePowerOfTwo(maxSize, 'Max size');
+var testSize = Math.min(maxSize, 128 * 1024);
+var pixels = new Uint8Array(testSize * 4);
+for (var ii = 0; ii < testSize; ++ii) {
+ var off = ii * 4;
+ pixels[off + 0] = 0;
+ pixels[off + 1] = 255;
+ pixels[off + 2] = 128;
+ pixels[off + 3] = 255;
+}
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+debug("test " + testSize + "x1");
+gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, testSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ pixels);
+gl.generateMipmap(gl.TEXTURE_2D);
+
+wtu.clearAndDrawUnitQuad(gl);
+wtu.checkCanvas(gl, [0, 255, 128, 255],
+ "Should be 0, 255, 128, 255");
+debug("test 1x" + testSize);
+gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, 1, testSize, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ pixels);
+gl.generateMipmap(gl.TEXTURE_2D);
+
+wtu.clearAndDrawUnitQuad(gl);
+wtu.checkCanvas(gl, [0, 255, 128, 255],
+ "Should be 0, 255, 128, 255");
+
+var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+// NOTE: We can't easily test cube maps because they require width == height
+// and we might not have enough memory for maxSize by maxSize texture.
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-attribs.html b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-attribs.html
new file mode 100644
index 0000000000..368130306c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-attribs.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL the minimum number of attributes are supported.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec4 v0;
+attribute vec4 v1;
+attribute vec4 v2;
+attribute vec4 v3;
+attribute vec4 v4;
+attribute vec4 v5;
+attribute vec4 v6;
+varying vec4 color;
+void main()
+{
+ gl_Position = vPosition;
+ color = v0 + v1 + v2 + v3 + v4 + v5 + v6;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+var program = wtu.setupProgram(
+ gl,
+ ['vshader', 'fshader'],
+ ['vPosition', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5', 'v6'],
+ [0, 1, 2, 3, 4, 5, 6, 7]);
+
+for (var ii = 0; ii < 7; ++ii) {
+ var v = (ii + 1) / 28;
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ v, v/2, v/4, v/8,
+ v, v/2, v/4, v/8,
+ v, v/2, v/4, v/8,
+ v, v/2, v/4, v/8,
+ v, v/2, v/4, v/8,
+ v, v/2, v/4, v/8]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(ii + 1);
+ gl.vertexAttribPointer(ii + 1, 4, gl.FLOAT, false, 0, 0);
+}
+
+wtu.clearAndDrawUnitQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [255, 127, 64, 32], "Should render 255,127,64,32 (+/-1)", 1);
+
+var successfullyParsed = true;
+
+</script>
+</body>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-textures.html b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-textures.html
new file mode 100644
index 0000000000..33b9f1f94c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-textures.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#define NUM_TEXTURES 8 // See spec
+precision mediump float;
+uniform sampler2D uni[NUM_TEXTURES];
+void main()
+{
+ vec4 c = vec4(0,0,0,0);
+ // The loop was manually unrolled in order to verify that this works.
+ // A separate test sampler-array-using-loop-index.html checks that
+ // loops indexing sampler arrays still work.
+ c += texture2D(uni[0], vec2(0.5, 0.5));
+ c += texture2D(uni[1], vec2(0.5, 0.5));
+ c += texture2D(uni[2], vec2(0.5, 0.5));
+ c += texture2D(uni[3], vec2(0.5, 0.5));
+ c += texture2D(uni[4], vec2(0.5, 0.5));
+ c += texture2D(uni[5], vec2(0.5, 0.5));
+ c += texture2D(uni[6], vec2(0.5, 0.5));
+ c += texture2D(uni[7], vec2(0.5, 0.5));
+ gl_FragColor = c;
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition'], [0]);
+
+for (var ii = 0; ii < 8; ++ii) {
+ var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ var tex = gl.createTexture();
+ wtu.fillTexture(gl, tex, 1, 1, [32, 16, 8, ii * 9], 0);
+ gl.uniform1i(loc, ii);
+}
+
+wtu.clearAndDrawUnitQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [255, 128, 64, 252],
+ "Should render using all texture units", 1);
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-uniforms.html b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-uniforms.html
new file mode 100644
index 0000000000..e4a1bf7ea4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/limits/gl-min-uniforms.html
@@ -0,0 +1,105 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+#define NUM_UNIFORMS 128 // See spec
+attribute vec4 vPosition;
+uniform vec4 uni[NUM_UNIFORMS];
+varying vec4 color;
+void main()
+{
+ gl_Position = vPosition;
+ vec4 c = vec4(0,0,0,0);
+ for (int ii = 0; ii < NUM_UNIFORMS; ++ii) {
+ c += uni[ii];
+ }
+ color = c;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+<script id="vshader2" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader2" type="x-shader/x-fragment">
+precision mediump float;
+#define NUM_UNIFORMS 16 // See spec
+uniform vec4 uni[NUM_UNIFORMS];
+void main()
+{
+ vec4 c = vec4(0,0,0,0);
+ for (int ii = 0; ii < NUM_UNIFORMS; ++ii) {
+ c += uni[ii];
+ }
+ gl_FragColor = vec4(c.r, c.g, c.b, c.a / 120.0);
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['vPosition'], [0]);
+
+for (var ii = 0; ii < 128; ++ii) {
+ var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+ gl.uniform4f(loc, 2/256, 2/512, 2/1024, ii/8128);
+}
+
+wtu.clearAndDrawUnitQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [255, 127, 64, 255], "Should render 255,127,64,32 (+/-1)", 1);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(gl, ['vshader2', 'fshader2'], ['vPosition'], [0]);
+
+for (var ii = 0; ii < 16; ++ii) {
+ var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+ gl.uniform4f(loc, 16/2048, 16/1024, 16/512, ii);
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.clearAndDrawUnitQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [32, 64, 127, 255], "Should render 32,64,127,255 (+/-1)", 1);
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/manual/angle-instanced-arrays-state-leakage.html b/dom/canvas/test/webgl-conf/checkout/conformance/manual/angle-instanced-arrays-state-leakage.html
new file mode 100644
index 0000000000..d36e9877ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/manual/angle-instanced-arrays-state-leakage.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that ANGLE_instanced_arrays state does not leak to browser</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid black;
+}
+.correct {
+ border: 1px solid black;
+ background-color: #00ff00;
+}
+</style>
+</head>
+<body>
+<pre>
+This test must be run manually.
+
+This test tests that leaving state for ANGLE_instanced_arrays with non-default values at the
+end of rendering does not interfere with proper compositing of results.
+Failures seen on Linux and Mac with Chrome 32.
+See http://crbug.com/304927 for more info.
+
+You should see a <span class="correct">green rectangle</span>
+with black a outline on success. Briefly flashing red is normal.
+</pre>
+<canvas id='c'></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var c = document.getElementById("c");
+// The bug has only been seen with preserveDrawingBuffer=true.
+var gl = wtu.create3DContext(c, { preserveDrawingBuffer: true });
+var ext = wtu.getExtensionWithKnownPrefixes(gl, "ANGLE_instanced_arrays");
+var frame = 0;
+function render() {
+ var RED_FRAMES = 3;
+ if (frame < RED_FRAMES) {
+ // Draw N frames red, leaving the vertex divisor to 0 after each call.
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.requestAnimFrame(render);
+ } else {
+ // Draw 2 more times in green, setting the divisor to 1 afterward.
+ gl.clearColor(0,1,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ if (frame - RED_FRAMES < 2) {
+ wtu.requestAnimFrame(render);
+ } else {
+ finishTest();
+ }
+ // Leave attrib 0 set with a divisor of 1 before returning to browser.
+ if (ext) {
+ ext.vertexAttribDivisorANGLE(0, 1);
+ }
+ }
+ frame++;
+}
+
+if (!ext) {
+ testPassed("No ANGLE_instanced_arrays support -- this is legal");
+}
+wtu.requestAnimFrame(render);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-clear-on-zero-count-draw.html b/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-clear-on-zero-count-draw.html
new file mode 100644
index 0000000000..c18c8ab96e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-clear-on-zero-count-draw.html
@@ -0,0 +1,90 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that the canvas is NOT recomposited after unsucessful draw call</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid black;
+}
+.correct {
+ border: 1px solid black;
+ background-color: #ffffff;
+}
+</style>
+</head>
+<body>
+<pre>
+This test must be run manually.
+
+This test tests that a canvas is cleared
+even when a draw call has a zero count.
+
+You should see three <span class="correct">white rectangles</span>
+with black outlines on success.
+</pre>
+<canvas id='c1'></canvas>
+<canvas id='c2'></canvas>
+<canvas id='c3'></canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+void main() {
+ gl_Position = vec4(0,0,0,1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ discard;
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var c1 = document.getElementById("c1");
+var c2 = document.getElementById("c2");
+var c3 = document.getElementById("c2");
+var gl1 = wtu.create3DContext(c1);
+var gl2 = wtu.create3DContext(c2);
+var gl3 = wtu.create3DContext(c2);
+gl1.clearColor(0,1,0,1);
+gl1.clear(gl1.COLOR_BUFFER_BIT);
+gl2.clearColor(0,1,0,1);
+gl2.clear(gl2.COLOR_BUFFER_BIT);
+gl3.clearColor(0,1,0,1);
+gl3.clear(gl2.COLOR_BUFFER_BIT);
+
+wtu.waitForComposite(function() {
+ // test drawArrays
+ gl1.drawArrays(gl1.TRIANGLES, 0, 0);
+ wtu.glErrorShouldBe(gl1, gl1.NO_ERROR, "no errors");
+});
+
+wtu.waitForComposite(function() {
+ // test drawElements
+ var buf = gl2.createBuffer();
+ gl2.bindBuffer(gl2.ELEMENT_ARRAY_BUFFER, buf);
+ gl2.bufferData(gl2.ELEMENT_ARRAY_BUFFER, new Uint8Array(1), gl2.STATIC_DRAW);
+ gl2.drawElements(gl2.TRIANGLES, 0, gl2.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl2, gl2.NO_ERROR, "no errors");
+});
+
+wtu.waitForComposite(function() {
+ // test draw with program.
+ wtu.setupProgram(gl3, ["vshader", "fshader"]);
+ gl1.drawArrays(gl3.TRIANGLES, 0, 0);
+ wtu.glErrorShouldBe(gl3, gl2.NO_ERROR, "no errors");
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-readpixels.html b/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-readpixels.html
new file mode 100644
index 0000000000..3cab7821c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-readpixels.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that the canvas is NOT recomposited after calling readPixels</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid black;
+}
+.correct {
+ border: 1px solid black;
+ background-color: #00ff00;
+}
+</style>
+</head>
+<body>
+<pre>
+This test must be run manually.
+
+This test tests that a canvas is NOT cleared
+and recomposited after calling readPixels.
+
+You should see a <span class="correct">green rectangle</span>
+with black a outline on success.
+</pre>
+<canvas id='c'></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var c = document.getElementById("c");
+var gl = wtu.create3DContext(c);
+gl.clearColor(0,1,0,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.waitForComposite(function() {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors");
+});
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-unsuccessful-draw.html b/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-unsuccessful-draw.html
new file mode 100644
index 0000000000..ba104d0774
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/manual/canvas-no-clear-on-unsuccessful-draw.html
@@ -0,0 +1,63 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that the canvas is NOT recomposited after unsucessful draw call</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid black;
+}
+.correct {
+ border: 1px solid black;
+ background-color: #00ff00;
+}
+</style>
+</head>
+<body>
+<pre>
+This test must be run manually.
+
+This test tests that a canvas is NOT cleared
+when a draw call fails.
+
+You should see two <span class="correct">green rectangles</span>
+with black outlines on success.
+</pre>
+<canvas id='c1'></canvas>
+<canvas id='c2'></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var c1 = document.getElementById("c1");
+var c2 = document.getElementById("c2");
+var gl1 = wtu.create3DContext(c1);
+var gl2 = wtu.create3DContext(c2);
+gl1.clearColor(0,1,0,1);
+gl1.clear(gl1.COLOR_BUFFER_BIT);
+gl2.clearColor(0,1,0,1);
+gl2.clear(gl2.COLOR_BUFFER_BIT);
+wtu.waitForComposite(function() {
+ gl1.drawArrays(gl1.BLEND, 0, 0);
+ wtu.glErrorShouldBe(gl1, gl1.INVALID_ENUM, "no errors");
+});
+
+wtu.waitForComposite(function() {
+ var buf = gl2.createBuffer();
+ gl2.bindBuffer(gl2.ELEMENT_ARRAY_BUFFER, buf);
+ gl2.bufferData(gl2.ELEMENT_ARRAY_BUFFER, new Uint8Array(1), gl2.STATIC_DRAW);
+ gl2.drawElements(gl2.BLEND, 0, gl2.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl2, gl2.INVALID_ENUM, "no errors");
+});
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/manual/framebuffers-keep-contents-exiting-fullscreen-mode.html b/dom/canvas/test/webgl-conf/checkout/conformance/manual/framebuffers-keep-contents-exiting-fullscreen-mode.html
new file mode 100644
index 0000000000..f5b6fe8d19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/manual/framebuffers-keep-contents-exiting-fullscreen-mode.html
@@ -0,0 +1,134 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that framebuffers keep contents exiting fullscreen mode.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ width: 100%;
+ height: 50px;
+ border: 1px solid black;
+}
+#f {
+ left: 0px;
+ top: 0px;
+}
+#inner {
+}
+input.button {
+ font-size: 36pt;
+}
+.redbox {
+ border: 1px solid black;
+ background-color: red;
+}
+#canvasholder {
+ position: relative;
+}
+#clabel {
+ position: absolute;
+ width: 100%;
+ top: 0px;
+ left: 0px;
+ font-size: 40px;
+ z-index: 10;
+ text-align: center;
+}
+</style>
+</head>
+<body>
+<pre>
+This test must be run manually.
+
+Checks that framebuffers keep their contents going into and out of fullscreen mode.
+
+Through the entire test you should see a <span class="redbox">red rectangle</span>. If it is not <span class="redbox">red</span> in all cases the test has failed.
+</pre>
+<div id="f">
+ <div id="inner">
+ <div id="buttonHolder">
+ <div><input id="button" class="button" type="button" value="Click this button to continue the test"/></div>
+ <div id="canvasholder">
+ <canvas id='c'></canvas>
+ <div id='clabel'>
+ should be red
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var testedFullScreen = false;
+var c = document.getElementById("c");
+var button = document.getElementById("button");
+var buttonHolder = document.getElementById("buttonHolder");
+var gl = wtu.create3DContext(c);
+if (!gl) {
+ testFailed("can't init WebGL");
+}
+
+var checkState = function() {
+ debug("");
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255]);
+ shouldBeNonNull("gl.getParameter(gl.FRAMEBUFFER_BINDING)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+var checkFramebufferState = function(fullscreen) {
+ checkState();
+
+ debug("fullscreen:" + fullscreen);
+
+ if (fullscreen) {
+ // Not sure if this is needed but need to make sure
+ // we at least went fullscreen once.
+ testedFullScreen = true;
+ } else {
+ if (testedFullScreen) {
+ finishTest();
+ }
+ }
+};
+
+var test = function() {
+ if (!wtu.setupFullscreen("button", "f", checkFramebufferState)) {
+ testPassed("Browser does not support fullscreen mode. This is OK");
+ finishTest();
+ return;
+ }
+
+ var fb = gl.createFramebuffer();
+ var tex = gl.createTexture();
+
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ checkState();
+};
+test();
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/misc/00_test_list.txt
new file mode 100644
index 0000000000..3cbdf888f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/00_test_list.txt
@@ -0,0 +1,17 @@
+bad-arguments-test.html
+--min-version 1.0.2 boolean-argument-conversion.html
+--min-version 1.0.2 delayed-drawing.html
+error-reporting.html
+--min-version 1.0.4 expando-loss.html
+functions-returning-strings.html
+--min-version 1.0.4 hint.html
+--max-version 1.9.9 instanceof-test.html
+invalid-passed-params.html
+is-object.html
+null-object-behaviour.html
+object-deletion-behaviour.html
+shader-precision-format.html
+type-conversion-test.html
+uninitialized-test.html
+webgl-specific.html
+--min-version 1.0.4 webgl-specific-stencil-settings.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/bad-arguments-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/bad-arguments-test.html
new file mode 100644
index 0000000000..2ae7d91bf3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/bad-arguments-test.html
@@ -0,0 +1,100 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Tests calling WebGL APIs with wrong argument types");
+
+
+var testArguments = [
+ { value: "foo",
+ throwsForNullables: true },
+ { value: 0,
+ throwsForNullables: true },
+ { value: null,
+ throwsForNullables: false },
+ { value: undefined,
+ throwsForNullables: false }
+];
+
+var argument;
+
+var context = wtu.create3DContext();
+var program;
+var shader;
+var loc;
+wtu.loadStandardProgramAsync(context, function(success, prog) {
+ program = prog;
+ wtu.loadStandardVertexShaderAsync(context, function(success, s) {
+ shader = s;
+
+ assertMsg(program != null, "Program Compiled");
+ assertMsg(shader != null, "Shader Compiled");
+
+ loc = context.getUniformLocation(program, "u_modelViewProjMatrix");
+ assertMsg(loc != null, "getUniformLocation succeeded");
+
+ for (var i = 0; i < testArguments.length; ++i) {
+ argument = testArguments[i].value;
+
+ debug('Testing argument: ' + argument);
+
+ // These functions don't accept nullable arguments any more.
+ shouldThrow("context.compileShader(argument)");
+ shouldThrow("context.linkProgram(argument)");
+ shouldThrow("context.attachShader(program, argument)");
+ shouldThrow("context.attachShader(argument, shader)");
+ shouldThrow("context.detachShader(program, argument)");
+ shouldThrow("context.detachShader(argument, shader)");
+ shouldThrow("context.shaderSource(argument, 'foo')");
+ shouldThrow("context.bindAttribLocation(argument, 0, 'foo')");
+ shouldThrow("context.getProgramInfoLog(argument)");
+ shouldThrow("context.getProgramParameter(argument, 0)");
+ shouldThrow("context.getShaderInfoLog(argument)");
+ shouldThrow("context.getShaderParameter(argument, 0)");
+ shouldThrow("context.getShaderSource(argument)");
+ shouldThrow("context.getUniform(argument, loc)");
+ shouldThrow("context.getUniform(program, argument)");
+ shouldThrow("context.getUniformLocation(argument, 'u_modelViewProjMatrix')");
+
+ // The following entry points still accept nullable arguments.
+ var func;
+ if (testArguments[i].throwsForNullables) {
+ func = shouldThrow;
+ } else {
+ func = shouldBeUndefined;
+ }
+
+ func("context.bindBuffer(context.ARRAY_BUFFER, argument)");
+ func("context.bindFramebuffer(context.FRAMEBUFFER, argument)");
+ func("context.bindRenderbuffer(context.RENDERBUFFER, argument)");
+ func("context.bindTexture(context.TEXTURE_2D, argument)");
+ func("context.framebufferRenderbuffer(context.FRAMEBUFFER, context.DEPTH_ATTACHMENT, context.RENDERBUFFER, argument)");
+ func("context.framebufferTexture2D(context.FRAMEBUFFER, context.COLOR_ATTACHMENT0, context.TEXTURE_2D, argument, 0)");
+ func("context.uniform2fv(argument, new Float32Array([0.0, 0.0]))");
+ func("context.uniform2iv(argument, new Int32Array([0, 0]))");
+ func("context.uniformMatrix2fv(argument, false, new Float32Array([0.0, 0.0, 0.0, 0.0]))");
+ func("context.useProgram(argument)");
+ }
+ finishTest();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/boolean-argument-conversion.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/boolean-argument-conversion.html
new file mode 100644
index 0000000000..1423673bda
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/boolean-argument-conversion.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/test-eval.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Test that conversion of boolean arguments of WebGL functions follows EcmaScript 9.2. ToBoolean");
+debug("");
+debug("When an object is converted to a boolean, it should always evaluate as true. Any valueOf() method should not even get called. See Mozilla bug 727590 where Gecko incorrectly converted such an argument to a Number instead of a Boolean, giving the wrong behavior. See 9.2 and 9.3 in the EcmaScript specification.");
+debug("");
+var gl = wtu.create3DContext();
+var program = wtu.loadStandardProgram(gl);
+var shader = wtu.loadStandardVertexShader(gl);
+var shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+assertMsg(program != null, "Program Compiled");
+assertMsg(shader != null, "Shader Compiled");
+
+var uloc = gl.getUniformLocation(program, "u_modelViewProjMatrix");
+var aloc = gl.getAttribLocation(program, "a_vertex");
+
+gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from initialization.");
+assertMsg(uloc, "Uniform not found");
+assertMsg(aloc >= 0, "Attribute not found");
+
+var boolArg = { valueOf: function() { throw "Converting an Object to a Boolean should just give 'true' without further evaluation"; } }
+
+function shouldNotThrowWithBoolArgs(code) {
+ try {
+ TestEval(code);
+ } catch(e) {
+ testFailed(code + " threw exception: " + e);
+ return;
+ }
+ testPassed(code + " converted its boolean arguments correctly");
+}
+
+shouldNotThrowWithBoolArgs(
+ "gl.colorMask(boolArg, boolArg, boolArg, boolArg)"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.depthMask(boolArg)"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.sampleCoverage(1, boolArg)"
+);
+
+function zeroArray(length) {
+ var a = new Array(length);
+ for (var i = 0; i < length; i++)
+ a[i] = 0;
+ return a;
+}
+
+function zeroFloat32Array(length) {
+ var a = new Float32Array(length);
+ for (var i = 0; i < length; i++)
+ a[i] = 0;
+ return a;
+}
+
+shouldNotThrowWithBoolArgs(
+ "gl.uniformMatrix2fv(uloc, boolArg, zeroFloat32Array(4))"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.uniformMatrix2fv(uloc, boolArg, zeroArray(4))"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.uniformMatrix3fv(uloc, boolArg, zeroFloat32Array(9))"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.uniformMatrix3fv(uloc, boolArg, zeroArray(9))"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.uniformMatrix4fv(uloc, boolArg, zeroFloat32Array(16))"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.uniformMatrix4fv(uloc, boolArg, zeroArray(16))"
+);
+
+shouldNotThrowWithBoolArgs(
+ "gl.vertexAttribPointer(aloc, 4, gl.FLOAT, boolArg, 4, 0)"
+);
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/delayed-drawing.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/delayed-drawing.html
new file mode 100644
index 0000000000..4dc9ea8f3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/delayed-drawing.html
@@ -0,0 +1,64 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Delayed Drawing test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var tex = gl.createTexture();
+wtu.fillTexture(gl, tex, 5, 3, [0, 192, 128, 255]);
+
+var loc = gl.getUniformLocation(program, "tex");
+gl.uniform1i(loc, 0);
+
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+
+drawAndCheck();
+
+setTimeout(step2, 1000);
+
+function step2() {
+ drawAndCheck();
+ finishTest();
+}
+
+function drawAndCheck() {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors before drawing.");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from drawing.");
+ wtu.checkCanvas(
+ gl, [0, 192, 128, 255],
+ "draw should be 0, 192, 128, 255");
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/error-reporting.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/error-reporting.html
new file mode 100644
index 0000000000..bfba0abc86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/error-reporting.html
@@ -0,0 +1,75 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests generation of synthetic and real GL errors");
+
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+
+// Other tests like incorrect-context-object-behaviour already test the raising
+// of many synthetic GL errors. This test verifies the raising of certain
+// known real GL errors, and contains a few regression tests for bugs
+// discovered in the synthetic error generation and in the WebGL
+// implementation itself.
+
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+
+debug("Testing getActiveAttrib");
+shouldThrow("context.getActiveAttrib(null, 2)");
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+// Error state should be clear by this point
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+// Real OpenGL error
+shouldBeNull("context.getActiveAttrib(program, 2)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+// Error state should be clear by this point
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+
+debug("Testing getActiveUniform");
+shouldThrow("context.getActiveUniform(null, 0)");
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+// Error state should be clear by this point
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+// Real OpenGL error
+shouldBeNull("context.getActiveUniform(program, 50)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+// Error state should be clear by this point
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+
+debug("Testing attempts to manipulate the default framebuffer");
+shouldBeUndefined("context.bindFramebuffer(context.FRAMEBUFFER, null)");
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+shouldBeUndefined("context.framebufferRenderbuffer(context.FRAMEBUFFER, context.DEPTH_ATTACHMENT, context.RENDERBUFFER, null)");
+// Synthetic OpenGL error
+wtu.glErrorShouldBe(context, context.INVALID_OPERATION);
+// Error state should be clear by this point
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+shouldBeUndefined("context.framebufferTexture2D(context.FRAMEBUFFER, context.COLOR_ATTACHMENT0, context.TEXTURE_2D, null, 0)");
+// Synthetic OpenGL error
+wtu.glErrorShouldBe(context, context.INVALID_OPERATION);
+// Error state should be clear by this point
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/expando-loss.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/expando-loss.html
new file mode 100644
index 0000000000..9e1f041f02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/expando-loss.html
@@ -0,0 +1,223 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL Object Expandos Conformance Test</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script>
+"use strict";
+description("This test verifies that WebGL object expandos are preserved across garbage collections.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+// Helpers that set expandos and verify they are set to the correct value.
+var expandoValue = "WebGL is awesome!"
+function setTestExpandos(instance) {
+ instance.expando1 = expandoValue;
+ instance.expando2 = { subvalue : expandoValue };
+}
+function verifyTestExpandos(instance, msg) {
+ assertMsg(instance.expando1 === expandoValue, msg + ": Expect basic expando to survive despite GC.");
+ assertMsg(instance.expando2 && instance.expando2.subvalue === expandoValue, msg + ": Expect subobject expando to survive despite GC.");
+}
+
+// Tests that we don't get expando loss for bound resources where the
+// only remaining reference is internal to WebGL
+function testBasicBindings() {
+ debug('Basic Bindings');
+
+ // Test data that describes how to create, bind, and retrieve an object off of the context
+ var glProt = Object.getPrototypeOf(gl);
+ var simpleData = [
+ {
+ creationFn: glProt.createTexture,
+ bindFn: glProt.bindTexture,
+ bindConstant: glProt.TEXTURE_2D,
+ retrieveConstant: glProt.TEXTURE_BINDING_2D,
+ name: "TEXTURE_BINDING_2D",
+ },
+ {
+ creationFn: glProt.createFramebuffer,
+ bindFn: glProt.bindFramebuffer,
+ bindConstant: glProt.FRAMEBUFFER,
+ retrieveConstant: glProt.FRAMEBUFFER_BINDING,
+ name: "FRAMEBUFFER_BINDING",
+ },
+ {
+ creationFn: glProt.createRenderbuffer,
+ bindFn: glProt.bindRenderbuffer,
+ bindConstant: glProt.RENDERBUFFER,
+ retrieveConstant: glProt.RENDERBUFFER_BINDING,
+ name: "RENDERBUFFER_BINDING",
+ },
+ {
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.ELEMENT_ARRAY_BUFFER,
+ retrieveConstant: glProt.ELEMENT_ARRAY_BUFFER_BINDING,
+ name: "ELEMENT_ARRAY_BUFFER_BINDING",
+ },
+ {
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.ARRAY_BUFFER,
+ retrieveConstant: glProt.ARRAY_BUFFER_BINDING,
+ name: "ARRAY_BUFFER_BINDING",
+ },
+ {
+ creationFn: glProt.createTexture,
+ bindFn: glProt.bindTexture,
+ bindConstant: glProt.TEXTURE_CUBE_MAP,
+ retrieveConstant: glProt.TEXTURE_BINDING_CUBE_MAP,
+ name: "TEXTURE_BINDING_CUBE_MAP",
+ },
+ ];
+
+ simpleData.forEach(function(test) {
+ var instance = test.creationFn.apply(gl, []);
+ var msg = "getParameter(" + test.name + ")";
+ setTestExpandos(instance);
+
+ test.bindFn.apply(gl, [test.bindConstant, instance]);
+ assertMsg(instance === gl.getParameter(test.retrieveConstant), msg + " returns instance that was bound.");
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ instance = null;
+ webglHarnessCollectGarbage();
+
+ verifyTestExpandos(gl.getParameter(test.retrieveConstant), msg);
+ });
+
+ debug('');
+}
+
+// Attach a couple of shaders to a program and verify no expando loss when you call
+// getAttachedShaders and getParameter(CURRENT_PROGRAM).
+function testProgramsAndShaders() {
+ debug('Programs and Shaders');
+
+ var vs = wtu.loadShader(gl, wtu.simpleVertexShader, gl.VERTEX_SHADER);
+ setTestExpandos(vs);
+
+ var fs = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);
+ setTestExpandos(fs);
+
+ var program = wtu.setupProgram(gl, [vs, fs]);
+ setTestExpandos(program);
+ assertMsg(program === gl.getParameter(gl.CURRENT_PROGRAM), "getParameter(gl.CURRENT_PROGRAM) return instance set with useProgram");
+
+ var attachedShaders = gl.getAttachedShaders(program);
+ assertMsg(attachedShaders.indexOf(vs) !== -1, "Vertex shader instance found in getAttachedShaders");
+ assertMsg(attachedShaders.indexOf(fs) !== -1, "Fragment shader instance found in getAttachedShaders");
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ attachedShaders = null;
+ program = null;
+ vs = null;
+ fs = null;
+ webglHarnessCollectGarbage();
+
+ var currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
+ verifyTestExpandos(currentProgram, "Current program");
+ shouldBeType(currentProgram, 'WebGLProgram');
+
+ var retrievedShaders = gl.getAttachedShaders(currentProgram);
+ verifyTestExpandos(retrievedShaders[0], "Shader[0]");
+ shouldBeType(retrievedShaders[0], "WebGLShader");
+ verifyTestExpandos(retrievedShaders[1], "Shader[1]");
+ shouldBeType(retrievedShaders[1], "WebGLShader");
+
+ debug('');
+}
+
+// Attach a buffer via vertexAttribPointer and verify no expando loss when you call getVertexAttrib.
+function testVertexAttributeBuffers() {
+ debug('Vertex Attribute Buffers');
+
+ var program = wtu.setupSimpleColorProgram(gl);
+ var position = gl.getAttribLocation(program, "vPosition");
+
+ var buffer = gl.createBuffer();
+ setTestExpandos(buffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
+ assertMsg(buffer === gl.getVertexAttrib(position, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING),
+ "getVertexAttrib(VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) return instance set with vertexAttribPointer");
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ buffer = null;
+ program = null;
+ webglHarnessCollectGarbage();
+
+ var retrievedBuffer = gl.getVertexAttrib(position, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ verifyTestExpandos(retrievedBuffer, "Vertex Attribute Buffer");
+ shouldBeType(retrievedBuffer, 'WebGLBuffer');
+
+ debug('');
+}
+
+// Attach renderbuffers to framebuffers and verify no expando loss ocurrs when you call
+// getFramebufferAttachmentParameter
+function testFrameBufferAttachments() {
+ debug('FrameBuffer Attachments');
+
+ var framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ var attachments = [
+ { enum: gl.COLOR_ATTACHMENT0, name: "COLOR_ATTACHMENT0" },
+ { enum: gl.DEPTH_ATTACHMENT, name: "DEPTH_ATTACHMENT" },
+ { enum: gl.STENCIL_ATTACHMENT, name: "STENCIL_ATTACHMENT" },
+ { enum: gl.DEPTH_STENCIL_ATTACHMENT,name: "DEPTH_STENCIL_ATTACHMENT" },
+ ];
+
+ // Attach a renderbuffer to all attachment points.
+ attachments.forEach(function(attachment) {
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ setTestExpandos(renderbuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment.enum, gl.RENDERBUFFER, renderbuffer);
+ assertMsg(renderbuffer === gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment.enum, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME),
+ "getFramebufferAttachmentParameter(" + attachment.name + ") returns instance set with framebufferRenderbuffer");
+ renderbuffer = null;
+ });
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ webglHarnessCollectGarbage();
+
+ // Verify all attached renderbuffers have expandos.
+ attachments.forEach(function(attachment) {
+ var retrievedRenderbuffer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment.enum, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ verifyTestExpandos(retrievedRenderbuffer, attachment.name);
+ shouldBeType(retrievedRenderbuffer, 'WebGLRenderbuffer');
+ });
+
+ debug('');
+}
+
+// Run tests
+testBasicBindings();
+testProgramsAndShaders();
+testVertexAttributeBuffers();
+testFrameBufferAttachments();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/functions-returning-strings.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/functions-returning-strings.html
new file mode 100644
index 0000000000..15e89e46f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/functions-returning-strings.html
@@ -0,0 +1,104 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/test-eval.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("Test that functions returning strings really do return strings (and not e.g. null)");
+debug("");
+
+var validVertexShaderString =
+ "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }";
+var validFragmentShaderString =
+ "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }";
+
+function shouldReturnString(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = TestEval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + ' should return a string. Threw exception ' + exception);
+ else if (typeof _av == "string")
+ testPassed(_a + ' returns a string');
+ else
+ testFailed(_a + ' should return a string. Returns: "' + _av + '"');
+}
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ var vs = gl.createShader(gl.VERTEX_SHADER);
+ shouldReturnString("gl.getShaderSource(vs)");
+ shouldReturnString("gl.getShaderInfoLog(vs)");
+ gl.shaderSource(vs, validVertexShaderString);
+ gl.compileShader(vs);
+ shouldReturnString("gl.getShaderSource(vs)");
+ shouldReturnString("gl.getShaderInfoLog(vs)");
+
+ var fs = gl.createShader(gl.FRAGMENT_SHADER);
+ shouldReturnString("gl.getShaderSource(fs)");
+ shouldReturnString("gl.getShaderInfoLog(fs)");
+ gl.shaderSource(fs, validFragmentShaderString);
+ gl.compileShader(fs);
+ shouldReturnString("gl.getShaderSource(fs)");
+ shouldReturnString("gl.getShaderInfoLog(fs)");
+
+ var prog = gl.createProgram();
+ shouldReturnString("gl.getProgramInfoLog(prog)");
+ gl.attachShader(prog, vs);
+ gl.attachShader(prog, fs);
+ gl.linkProgram(prog);
+ shouldReturnString("gl.getProgramInfoLog(prog)");
+
+ // Make sure different numbers of extensions doesn't result in
+ // different test output.
+ var exts = gl.getSupportedExtensions();
+ var allPassed = true;
+ for (var ii = 0; ii < exts.length; ++ii) {
+ var s = exts[ii];
+ if (typeof s != "string") {
+ shouldReturnString("gl.getSupportedExtensions()[" + s + "]");
+ allPassed = false;
+ }
+ }
+ if (allPassed) {
+ testPassed('getSupportedExtensions() returns an array of strings');
+ }
+
+ shouldReturnString("gl.getParameter(gl.VENDOR)");
+ shouldReturnString("gl.getParameter(gl.RENDERER)");
+ shouldReturnString("gl.getParameter(gl.VERSION)");
+ shouldReturnString("gl.getParameter(gl.SHADING_LANGUAGE_VERSION)");
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/hint.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/hint.html
new file mode 100644
index 0000000000..f49f2248fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/hint.html
@@ -0,0 +1,124 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+description("Tests webgl.hint()");
+
+const gl = wtu.create3DContext();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup should succeed");
+
+// From https://kdashg.github.io/misc/gl/search-headers.html#str=_HINT
+const HINT_TARGETS = {
+ GL_GENERATE_MIPMAP_HINT: 0x8192,
+ GL_FRAGMENT_SHADER_DERIVATIVE_HINT: 0x8B8B,
+ GL_BINNING_CONTROL_HINT_QCOM: 0x8FB0,
+ GL_PROGRAM_BINARY_RETRIEVABLE_HINT: 0x8257,
+ GL_LINE_SMOOTH_HINT: 0x0C52,
+ GL_POLYGON_SMOOTH_HINT: 0x0C53,
+ EGL_PRODUCER_MAX_FRAME_HINT_NV: 0x3337,
+ EGL_CONSUMER_MAX_FRAME_HINT_NV: 0x3338,
+ EGL_YUV_COLOR_SPACE_HINT_EXT: 0x327B,
+ EGL_SAMPLE_RANGE_HINT_EXT: 0x327C,
+ EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT: 0x327D,
+ EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT: 0x327E,
+ EGL_LOCK_USAGE_HINT_KHR: 0x30C5,
+ GL_TEXTURE_COMPRESSION_HINT: 0x84EF,
+ GL_TEXTURE_STORAGE_HINT_APPLE: 0x85BC,
+ GL_TRANSFORM_HINT_APPLE: 0x85B1,
+ GL_VERTEX_ARRAY_STORAGE_HINT_APPLE: 0x851F,
+ GL_CLIP_VOLUME_CLIPPING_HINT_EXT: 0x80F0,
+ GL_PACK_CMYK_HINT_EXT: 0x800E,
+ GL_UNPACK_CMYK_HINT_EXT: 0x800F,
+ GL_MULTISAMPLE_FILTER_HINT_NV: 0x8534,
+ GL_PREFER_DOUBLEBUFFER_HINT_PGI: 0x1A1F8,
+ GL_CONSERVE_MEMORY_HINT_PGI: 0x1A1FD,
+ GL_RECLAIM_MEMORY_HINT_PGI: 0x1A1FE,
+ GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI: 0x1A203,
+ GL_NATIVE_GRAPHICS_END_HINT_PGI: 0x1A204,
+ GL_ALWAYS_FAST_HINT_PGI: 0x1A20C,
+ GL_ALWAYS_SOFT_HINT_PGI: 0x1A20D,
+ GL_ALLOW_DRAW_OBJ_HINT_PGI: 0x1A20E,
+ GL_ALLOW_DRAW_WIN_HINT_PGI: 0x1A20F,
+ GL_ALLOW_DRAW_FRG_HINT_PGI: 0x1A210,
+ GL_ALLOW_DRAW_MEM_HINT_PGI: 0x1A211,
+ GL_STRICT_DEPTHFUNC_HINT_PGI: 0x1A216,
+ GL_STRICT_LIGHTING_HINT_PGI: 0x1A217,
+ GL_STRICT_SCISSOR_HINT_PGI: 0x1A218,
+ GL_FULL_STIPPLE_HINT_PGI: 0x1A219,
+ GL_CLIP_NEAR_HINT_PGI: 0x1A220,
+ GL_CLIP_FAR_HINT_PGI: 0x1A221,
+ GL_WIDE_LINE_HINT_PGI: 0x1A222,
+ GL_BACK_NORMALS_HINT_PGI: 0x1A223,
+ GL_VERTEX_DATA_HINT_PGI: 0x1A22A,
+ GL_VERTEX_CONSISTENT_HINT_PGI: 0x1A22B,
+ GL_MATERIAL_SIDE_HINT_PGI: 0x1A22C,
+ GL_MAX_VERTEX_HINT_PGI: 0x1A22D,
+ GL_GENERATE_MIPMAP_HINT_SGIS: 0x8192,
+ GL_CONVOLUTION_HINT_SGIX: 0x8316,
+ GL_SCALEBIAS_HINT_SGIX: 0x8322,
+ GL_TEXTURE_MULTI_BUFFER_HINT_SGIX: 0x812E,
+ GL_VERTEX_PRECLIP_HINT_SGIX: 0x83EF,
+ GL_PHONG_HINT_WIN: 0x80EB,
+};
+
+async function testValidTargets(validTargets) {
+ Object.entries(HINT_TARGETS).forEach(kv => {
+ const [k,v] = kv;
+ let targetError = gl.INVALID_ENUM;
+ if (validTargets[v]) {
+ targetError = 0;
+ }
+ debug("");
+ debug(k);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, `gl.hint(HINT_TARGETS.${k}, gl.DONT_CARE-1)`);
+ wtu.shouldGenerateGLError(gl, targetError, `gl.hint(HINT_TARGETS.${k}, gl.DONT_CARE)`);
+ wtu.shouldGenerateGLError(gl, targetError, `gl.hint(HINT_TARGETS.${k}, gl.FASTEST)`);
+ wtu.shouldGenerateGLError(gl, targetError, `gl.hint(HINT_TARGETS.${k}, gl.NICEST)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, `gl.hint(HINT_TARGETS.${k}, gl.NICEST+1)`);
+ });
+}
+
+(async () => {
+ const validTargets = {};
+ validTargets[HINT_TARGETS.GL_GENERATE_MIPMAP_HINT] = true;
+
+ if (gl.FRAGMENT_SHADER_DERIVATIVE_HINT) { // webgl2
+ validTargets[gl.FRAGMENT_SHADER_DERIVATIVE_HINT] = true;
+ }
+ testValidTargets(validTargets);
+
+ const ext = gl.getExtension("OES_standard_derivatives");
+ if (ext) {
+ debug("");
+ debug("");
+ debug("-----------------------------------------");
+ debug("Test with OES_standard_derivatives enabled");
+ debug("");
+ validTargets[ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES] = true;
+ testValidTargets(validTargets);
+ }
+
+ finishTest();
+})();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/instanceof-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/instanceof-test.html
new file mode 100644
index 0000000000..aa2464e7a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/instanceof-test.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL instanceof test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/instanceof-test.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/invalid-passed-params.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/invalid-passed-params.html
new file mode 100644
index 0000000000..3f1ca805da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/invalid-passed-params.html
@@ -0,0 +1,170 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test for invalid passed parameters");
+
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var contextVersion = wtu.getDefault3DContextVersion();
+
+debug("");
+debug("Test createShader()");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.createShader(context.FRAGMENT_SHADER)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.createShader(context.VERTEX_SHADER)");
+wtu.shouldGenerateGLError(context, context.INVALID_ENUM, "context.createShader(0)");
+wtu.shouldGenerateGLError(context, context.INVALID_ENUM, "context.createShader(context.TRIANGLES)");
+
+debug("");
+debug("Test clear()");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'])");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'] | context.COLOR_BUFFER_BIT)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'] | context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT)");
+
+debug("");
+debug("Test {copy}Tex{Sub}Image2D with negative offset/width/height");
+var tex = context.createTexture();
+var pixels = new Uint8Array(2 * 2 * 4);
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.bindTexture(context.TEXTURE_2D, tex)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, -16, -16, 0, context.RGBA, context.UNSIGNED_BYTE, null)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 16, 16, 0, context.RGBA, context.UNSIGNED_BYTE, null)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.texSubImage2D(context.TEXTURE_2D, 0, -1, -1, 2, 2, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.texSubImage2D(context.TEXTURE_2D, 0, 0, 0, -1, -1, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.texSubImage2D(context.TEXTURE_2D, 0, 0, 0, 2, 2, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, -1, -1, 0)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, 16, 16, 0)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, -1, -1, 0, 0, 2, 2)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, -1, -1)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2)");
+
+debug("");
+debug("Test renderbufferStorage() with negative width/height");
+var renderbuffer = context.createRenderbuffer();
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.bindRenderbuffer(context.RENDERBUFFER, renderbuffer)");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.renderbufferStorage(context.RENDERBUFFER, context.RGBA4, -2, -2)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.renderbufferStorage(context.RENDERBUFFER, context.RGBA4, 16, 16)");
+
+debug("");
+debug("Test scissor() with negative width/height");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.scissor(0, 0, -2, -2)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.scissor(0, 0, 16, 16)");
+
+debug("");
+debug("Test viewport() with negative width/height");
+wtu.shouldGenerateGLError(context, context.INVALID_VALUE, "context.viewport(0, 0, -2, -2)");
+wtu.shouldGenerateGLError(context, context.NO_ERROR, "context.viewport(0, 0, 16, 16)");
+
+debug("");
+debug("Set up a program to test invalid characters");
+var invalidSet = ['"', '$', '`', '@', '\\', "'"];
+var validUniformName = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
+var validAttribName = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+function generateShaderSource(opt_invalidIdentifierChar, opt_invalidCommentChar) {
+ var invalidIdentifierString = "";
+ var invalidCommentString = "";
+ if (opt_invalidIdentifierChar != undefined) {
+ invalidIdentifierString += opt_invalidIdentifierChar;
+ }
+ if (opt_invalidCommentChar != undefined) {
+ invalidCommentString += opt_invalidCommentChar;
+ }
+ return "uniform float " + validUniformName + invalidIdentifierString + ";\n"
+ + "varying float " + validAttribName + ";\n"
+ + "void main() {\n"
+ + validAttribName + " = " + validUniformName + ";\n"
+ + "gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }\n"
+ + "//.+-/*%<>[](){}^|&~=!:;,?# " + invalidCommentString;
+}
+var vShader = context.createShader(context.VERTEX_SHADER);
+context.shaderSource(vShader, generateShaderSource());
+context.compileShader(vShader);
+shouldBe("context.getError()", "context.NO_ERROR");
+var fShader = context.createShader(context.FRAGMENT_SHADER);
+context.shaderSource(fShader, "precision mediump float;\n"
+ + "varying float " + validAttribName + ";\n"
+ + "void main() {\n"
+ + "gl_FragColor = vec4(" + validAttribName + ", 0.0, 0.0, 1.0); }");
+context.compileShader(fShader);
+shouldBe("context.getError()", "context.NO_ERROR");
+var program = context.createProgram();
+context.attachShader(program, vShader);
+context.attachShader(program, fShader);
+context.linkProgram(program);
+var linkStatus = context.getProgramParameter(program, context.LINK_STATUS);
+shouldBeTrue("linkStatus");
+if (!linkStatus)
+ debug(context.getProgramInfoLog(program));
+shouldBe("context.getError()", "context.NO_ERROR");
+context.bindAttribLocation(program, 1, validAttribName);
+shouldBe("context.getError()", "context.NO_ERROR");
+context.getAttribLocation(program, validAttribName);
+shouldBe("context.getError()", "context.NO_ERROR");
+context.getUniformLocation(program, validUniformName);
+shouldBe("context.getError()", "context.NO_ERROR");
+
+debug("");
+debug("Test shaderSource() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+ // Backslash as line-continuation is allowed in WebGL 2.0.
+ if (contextVersion > 1 && invalidSet[i] == '\\')
+ continue;
+ // With recent specification changes from
+ // https://github.com/KhronosGroup/WebGL/pull/3206 , shaderSource no
+ // longer generates INVALID_VALUE.
+ var validShaderSource = generateShaderSource(undefined, invalidSet[i]);
+ context.shaderSource(vShader, validShaderSource);
+ shouldBe("context.getError()", "context.NO_ERROR");
+ var invalidShaderSource = generateShaderSource(invalidSet[i], undefined);
+ context.shaderSource(vShader, invalidShaderSource);
+ shouldBe("context.getError()", "context.NO_ERROR");
+}
+
+debug("");
+debug("Test bindAttribLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+ var invalidName = validAttribName + invalidSet[i];
+ context.bindAttribLocation(program, 1, invalidName);
+ shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test getAttribLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+ var invalidName = validAttribName + invalidSet[i];
+ context.getAttribLocation(program, invalidName);
+ shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test getUniformLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+ var invalidName = validUniformName + invalidSet[i];
+ context.getUniformLocation(program, invalidName);
+ shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/is-object.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/is-object.html
new file mode 100644
index 0000000000..f6255ae573
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/is-object.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas">
+<script>
+"use strict";
+var wtu;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+
+var buffer;
+var framebuffer;
+var program;
+var renderbuffer;
+var shader;
+var texture;
+
+description("Tests 'is' calls against non-bound and deleted objects");
+
+wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "buffer = gl.createBuffer()");
+shouldBeFalse("gl.isBuffer(buffer)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
+shouldBeTrue("gl.isBuffer(buffer)");
+debug("");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "framebuffer = gl.createFramebuffer()");
+shouldBeFalse("gl.isFramebuffer(framebuffer)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)");
+shouldBeTrue("gl.isFramebuffer(framebuffer)");
+debug("");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "renderbuffer = gl.createRenderbuffer()");
+shouldBeFalse("gl.isRenderbuffer(renderbuffer)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)");
+shouldBeTrue("gl.isRenderbuffer(renderbuffer)");
+debug("");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "texture = gl.createTexture()");
+shouldBeFalse("gl.isTexture(texture)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, texture)");
+shouldBeTrue("gl.isTexture(texture)");
+debug("");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "program = gl.createProgram()");
+shouldBeTrue("gl.isProgram(program)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteProgram(program)");
+shouldBeFalse("gl.isProgram(program)");
+debug("");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "shader = gl.createShader(gl.VERTEX_SHADER)");
+shouldBeTrue("gl.isShader(shader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(shader)");
+shouldBeFalse("gl.isShader(shader)");
+debug("");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/null-object-behaviour.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/null-object-behaviour.html
new file mode 100644
index 0000000000..a08584cf05
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/null-object-behaviour.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Tests calling WebGL APIs without providing the necessary objects");
+
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+var shader = wtu.loadStandardVertexShader(context);
+var shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+assertMsg(program != null, "Program Compiled");
+assertMsg(shader != null, "Shader Compiled");
+shouldThrow("context.compileShader(undefined)");
+shouldThrow("context.linkProgram(undefined)");
+shouldThrow("context.attachShader(undefined, undefined)");
+shouldThrow("context.attachShader(program, undefined)");
+shouldThrow("context.attachShader(undefined, shader)");
+shouldThrow("context.detachShader(program, undefined)");
+shouldThrow("context.detachShader(undefined, shader)");
+shouldThrow("context.shaderSource(undefined, undefined)");
+shouldThrow("context.shaderSource(undefined, 'foo')");
+shouldThrow("context.bindAttribLocation(undefined, 0, 'foo')");
+shouldThrow("context.bindBuffer(context.ARRAY_BUFFER, 0)");
+shouldThrow("context.bindFramebuffer(context.FRAMEBUFFER, 0)");
+shouldThrow("context.bindRenderbuffer(context.RENDERBUFFER, 0)");
+shouldThrow("context.bindTexture(context.TEXTURE_2D, 0)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindBuffer(context.ARRAY_BUFFER, null)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindFramebuffer(context.FRAMEBUFFER, null)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindRenderbuffer(context.RENDERBUFFER, null)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindTexture(context.TEXTURE_2D, null)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindBuffer(context.ARRAY_BUFFER, undefined)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindFramebuffer(context.FRAMEBUFFER, undefined)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindRenderbuffer(context.RENDERBUFFER, undefined)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindTexture(context.TEXTURE_2D, undefined)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.framebufferRenderbuffer(context.FRAMEBUFFER, context.DEPTH_ATTACHMENT, context.RENDERBUFFER, null)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.framebufferTexture2D(context.FRAMEBUFFER, context.COLOR_ATTACHMENT0, context.TEXTURE_2D, null, 0)");
+shouldThrow("context.getProgramParameter(undefined, 0)");
+shouldThrow("context.getProgramInfoLog(undefined, 0)");
+shouldThrow("context.getShaderParameter(undefined, 0)");
+shouldThrow("context.getShaderInfoLog(undefined, 0)");
+shouldThrow("context.getShaderSource(undefined)");
+shouldThrow("context.getUniform(undefined, null)");
+shouldThrow("context.getUniformLocation(undefined, 'foo')");
+
+debug("");
+debug("check with bindings");
+context.bindBuffer(context.ARRAY_BUFFER, context.createBuffer());
+context.bindTexture(context.TEXTURE_2D, context.createTexture());
+shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 1, context.STATIC_DRAW)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.getBufferParameter(context.ARRAY_BUFFER, context.BUFFER_SIZE)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 1, 1, 0, context.RGBA, context.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]))");
+shouldGenerateGLError(context, context.NO_ERROR, "context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.getTexParameter(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER)");
+
+debug("");
+debug("check without bindings");
+context.bindBuffer(context.ARRAY_BUFFER, null);
+context.bindTexture(context.TEXTURE_2D, null);
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.bufferData(context.ARRAY_BUFFER, 1, context.STATIC_DRAW)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.getBufferParameter(context.ARRAY_BUFFER, context.BUFFER_SIZE)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 1, 1, 0, context.RGBA, context.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]))");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.getTexParameter(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER)");
+
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/object-deletion-behaviour.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/object-deletion-behaviour.html
new file mode 100644
index 0000000000..54730ec4eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/object-deletion-behaviour.html
@@ -0,0 +1,443 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests deletion behavior for buffer, texture, renderbuffer, shader, and program");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var shouldGenerateGLError = wtu.shouldGenerateGLError;
+var contextVersion = wtu.getDefault3DContextVersion();
+
+debug("");
+debug("shader and program deletion");
+
+var vertexShader = wtu.loadStandardVertexShader(gl);
+assertMsg(vertexShader, "vertex shader loaded");
+var fragmentShader = wtu.loadStandardFragmentShader(gl);
+assertMsg(fragmentShader, "fragment shader loaded");
+
+var program = gl.createProgram();
+shouldBeNonNull("program");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, vertexShader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, fragmentShader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.linkProgram(program)");
+shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.useProgram(program)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(vertexShader)");
+shouldBeTrue("gl.isShader(vertexShader)");
+shouldBeTrue("gl.getShaderParameter(vertexShader, gl.DELETE_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.detachShader(program, vertexShader)");
+shouldBeFalse("gl.isShader(vertexShader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(fragmentShader)");
+shouldBeTrue("gl.isShader(fragmentShader)");
+shouldBeTrue("gl.getShaderParameter(fragmentShader, gl.DELETE_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteProgram(program)");
+shouldBeTrue("gl.isProgram(program)");
+shouldBeTrue("gl.getProgramParameter(program, gl.DELETE_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.useProgram(null)");
+shouldBeFalse("gl.isProgram(program)");
+shouldBeFalse("gl.isShader(fragmentShader)");
+
+debug("");
+debug("texture deletion");
+
+var fbo = gl.createFramebuffer(), fbo2 = gl.createFramebuffer(), fbo3 = gl.createFramebuffer();
+shouldBeNonNull("fbo");
+shouldBeNonNull("fbo2");
+shouldBeNonNull("fbo3");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+
+var tex = gl.createTexture();
+shouldBeNonNull("tex");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "tex");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.TEXTURE");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
+// Deleting a texture bound to the currently-bound fbo is the same as
+// detaching the textue from fbo first, then delete the texture.
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+if (contextVersion > 1) {
+ shouldBeNull("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+} else {
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+}
+shouldBeFalse("gl.isTexture(tex)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+
+var texCubeMap = gl.createTexture();
+shouldBeNonNull("texCubeMap");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)", "texCubeMap");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(texCubeMap)");
+shouldBeFalse("gl.isTexture(texCubeMap)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)");
+
+var t = gl.createTexture();
+shouldBeNonNull("t");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindTexture(gl.TEXTURE_2D, t)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
+
+var t2 = gl.createTexture();
+shouldBeNonNull("t2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE1)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t2)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+
+debug("");
+debug("renderbuffer deletion");
+
+var rbo = gl.createRenderbuffer(), rbo2 = gl.createRenderbuffer(), rbo3 = gl.createRenderbuffer();
+shouldBeNonNull("rbo");
+shouldBeNonNull("rbo2");
+shouldBeNonNull("rbo3");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+// Deleting a renderbuffer bound to the currently-bound fbo is the same as
+// detaching the renderbuffer from fbo first, then delete the renderbuffer.
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+if (contextVersion > 1) {
+ shouldBeNull("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+} else {
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+}
+shouldBeFalse("gl.isRenderbuffer(rbo)");
+shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2)");
+shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo3)");
+shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo2");
+
+debug("");
+debug("using deleted renderbuffer");
+rbo = gl.createRenderbuffer();
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // make backbuffer red
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ // delete renderbuffer. It should still be attached to fbo though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+ // Use fbo that has deleted rbo.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("renderbuffer attached twice to same framebuffer");
+rbo = gl.createRenderbuffer();
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ rbo2 = gl.createRenderbuffer();
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+ // attach rbo2 at two attachment points incompatible with it
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo2");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo2");
+ // fbo can't be complete as rbo2 is attached at incompatible attachment points
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // now we delete rbo2, which detaches it from the two attachment points where it currently is attached
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo2)");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ // we should now be in the same state as before with only rbo attached, so fbo should be complete again
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
+}
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+
+
+
+debug("");
+debug("using deleted texture");
+tex = gl.createTexture();
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ // delete texture. It should still be attached to fbo though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255,0,0,255], "backbuffer should be red")');
+ // Use fbo that has deleted texture.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("using deleted renderbuffer");
+rbo = gl.createRenderbuffer();
+shouldBeNonNull("rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // make backbuffer red
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // delete renderbuffer. It should still be attached to fbo2 though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+ // fbo has no attachments
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Use fbo2 that has deleted rbo.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ if (contextVersion > 1) {
+ shouldBeNull("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+ } else {
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+ }
+ shouldGenerateGLError(gl, gl.NONE, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("using deleted texture");
+tex = gl.createTexture();
+shouldBeNonNull("tex");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // delete texture. It should still be attached to fbo2 though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
+ // fbo has no attachments
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Use fbo that has deleted texture.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ if (contextVersion > 1) {
+ shouldBeNull("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+ } else {
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+ }
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("buffer deletion");
+
+var buffer = gl.createBuffer();
+shouldBeNonNull("buffer");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
+shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer)");
+shouldBeFalse("gl.isBuffer(buffer)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+
+var buffer2 = gl.createBuffer();
+shouldBeNonNull("buffer2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
+shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, null)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer2)");
+shouldBeFalse("gl.isBuffer(buffer2)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+
+var bufferElement = gl.createBuffer();
+shouldBeNonNull("bufferElement");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement)");
+shouldBe("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)", "bufferElement");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferElement)");
+shouldBeFalse("gl.isBuffer(bufferElement)");
+shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement)");
+shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
+
+var b = gl.createBuffer();
+shouldBeNonNull("b");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
+
+var b1 = gl.createBuffer();
+shouldBeNonNull("b1");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b1);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(1);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);");
+var b2 = gl.createBuffer();
+shouldBeNonNull("b2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b2);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(2);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 0, 0);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(3);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(3, 4, gl.FLOAT, false, 0, 0);");
+shouldBe("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b1");
+shouldBe("gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b2");
+shouldBe("gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b2);");
+shouldBe("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b1");
+shouldBeNull("gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
+shouldBeNull("gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b1);");
+shouldBeNull("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
+
+debug("");
+debug("framebuffer deletion");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo)");
+shouldBeFalse("gl.isFramebuffer(fbo)");
+shouldBeNull("gl.getParameter(gl.FRAMEBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldBeNull("gl.getParameter(gl.FRAMEBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo3)");
+shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
+
+fbo = gl.createFramebuffer();
+rbo = gl.createRenderbuffer();
+shouldBeNonNull("fbo");
+shouldBeNonNull("rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // set backbuffer to red
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // set framebuffer to green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // check framebuffer
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 16, 16, 1, 1, [0,0,0,0], "outside fbo should be black")');
+ // delete framebuffer. because this was the bound fbo the backbuffer should be active now
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo)");
+ // check backbuffer
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [255,0,0,255], "backbuffer should be red")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 300, 0, 300, 300, [0,0,0,0], "outside backbuffer should be black")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 150, 300, 300, [0,0,0,0], "outside backbuffer should be black")');
+ // check drawing to backbuffer
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ // check again because many buggy implementations will have bound to the true backbuffer on deleteFramebuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html
new file mode 100644
index 0000000000..46be2a8145
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html
@@ -0,0 +1,340 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL shader precision format test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description(document.title);
+debug("Tests that WebGLShaderPrecisionFormat class and getShaderPrecisionFormat work.");
+debug("");
+var gl = wtu.create3DContext("canvas");
+
+function verifyShaderPrecisionFormat(shadertype, precisiontype) {
+ shouldBeTrue('gl.getShaderPrecisionFormat(' + shadertype + ', ' +
+ precisiontype + ') instanceof WebGLShaderPrecisionFormat');
+}
+
+debug("");
+debug("Test that getShaderPrecisionFormat returns a WebGLShaderPrecisionFormat object.");
+debug("");
+
+verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.LOW_FLOAT');
+verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.MEDIUM_FLOAT');
+verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.HIGH_FLOAT');
+verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.LOW_INT');
+verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.MEDIUM_INT');
+verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.HIGH_INT');
+verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.LOW_FLOAT');
+verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.MEDIUM_FLOAT');
+verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.HIGH_FLOAT');
+verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.LOW_INT');
+verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.MEDIUM_INT');
+verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.HIGH_INT');
+
+debug("");
+debug("Test that getShaderPrecisionFormat throws an error with invalid parameters.");
+debug("");
+
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.getShaderPrecisionFormat(gl.HIGH_INT, gl.VERTEX_SHADER)');
+
+debug("");
+debug("Test that WebGLShaderPrecisionFormat values are sensible.");
+debug("");
+
+// The minimum values are from OpenGL ES Shading Language spec, section 4.5.
+
+var shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 1');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 1');
+shouldBeTrue('shaderPrecisionFormat.precision >= 8');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 14');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 14');
+shouldBeTrue('shaderPrecisionFormat.precision >= 10');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 62');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 62');
+shouldBeTrue('shaderPrecisionFormat.precision >= 16');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_INT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 8');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 8');
+shouldBeTrue('shaderPrecisionFormat.precision == 0');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_INT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 10');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 10');
+shouldBeTrue('shaderPrecisionFormat.precision == 0');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_INT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 16');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 16');
+shouldBeTrue('shaderPrecisionFormat.precision == 0');
+
+var shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 1');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 1');
+shouldBeTrue('shaderPrecisionFormat.precision >= 8');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 14');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 14');
+shouldBeTrue('shaderPrecisionFormat.precision >= 10');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 8');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 8');
+shouldBeTrue('shaderPrecisionFormat.precision == 0');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin >= 10');
+shouldBeTrue('shaderPrecisionFormat.rangeMax >= 10');
+shouldBeTrue('shaderPrecisionFormat.precision == 0');
+
+debug("");
+debug("Test optional highp support in fragment shaders.");
+debug("");
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
+shouldBeTrue('(shaderPrecisionFormat.rangeMin == 0 && shaderPrecisionFormat.rangeMax == 0 && shaderPrecisionFormat.precision == 0) || (shaderPrecisionFormat.rangeMin >= 62 && shaderPrecisionFormat.rangeMax >= 62 && shaderPrecisionFormat.precision >= 16)');
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT);
+shouldBeTrue('(shaderPrecisionFormat.rangeMin == 0 && shaderPrecisionFormat.rangeMax == 0 && shaderPrecisionFormat.precision == 0) || (shaderPrecisionFormat.rangeMin >= 16 && shaderPrecisionFormat.rangeMax >= 16 && shaderPrecisionFormat.precision == 0)');
+
+debug("");
+debug("Test that getShaderPrecisionFormat returns the same thing every call.");
+debug("");
+
+shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
+var shaderPrecisionFormat2 = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
+shouldBeTrue('shaderPrecisionFormat.rangeMin == shaderPrecisionFormat2.rangeMin');
+shouldBeTrue('shaderPrecisionFormat.rangeMax == shaderPrecisionFormat2.rangeMax');
+shouldBeTrue('shaderPrecisionFormat.precision == shaderPrecisionFormat2.precision');
+
+debug("");
+debug("Test that specified precision matches rendering results");
+debug("");
+
+function testRenderPrecisionSetup(gl, shaderPair) {
+ const program = wtu.setupProgram(gl, shaderPair);
+
+ // Create a buffer and setup an attribute.
+ // We wouldn't need this except for a bug in Safari and arguably
+ // this should be removed from the test but we can't test the test itself
+ // without until the bug is fixed.
+ // see https://bugs.webkit.org/show_bug.cgi?id=197592
+ {
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+ gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
+ const loc = gl.getAttribLocation(program, 'position');
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribPointer(loc, 1, gl.UNSIGNED_BYTE, false, 0, 0);
+ }
+
+ gl.useProgram(program);
+
+ return program;
+}
+
+function testRenderPrecision(gl, shaderType, type, precision, expected, msg) {
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.POINTS, 0, 1);
+
+ const pixel = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, expected, msg, 5);
+}
+
+function testRenderPrecisionFloat(gl, precisionEnum, precision) {
+ function test(gl, shaderPair, shaderType) {
+ const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum);
+ const value = 2 ** format.precision - 1;
+
+ const length = v => Math.sqrt(v.reduce((sum, v) => sum + v * v, 0));
+ const normalize = (v) => {
+ const l = length(v);
+ return v.map(v => v / l);
+ };
+
+ const input = [Math.sqrt(value), Math.sqrt(value), Math.sqrt(value)];
+ const expected = [...normalize(input).map(v => (v * 0.5 + 0.5) * 255 | 0), 255];
+
+ const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} float precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`;
+ const program = testRenderPrecisionSetup(gl, shaderPair);
+ const vLocation = gl.getUniformLocation(program, 'v');
+ gl.uniform3fv(vLocation, input);
+ testRenderPrecision(gl, shaderType, 'float', precision, expected, msg);
+ }
+
+ {
+ const vs = `
+ attribute vec4 position;
+ uniform ${precision} vec3 v;
+ varying ${precision} vec4 v_result;
+ void main() {
+ gl_Position = position;
+ gl_PointSize = 1.0;
+ v_result = vec4(normalize(v) * 0.5 + 0.5, 1);
+ }
+ `;
+
+ const fs = `
+ precision ${precision} float;
+ varying ${precision} vec4 v_result;
+ void main() {
+ gl_FragColor = v_result;
+ }
+ `;
+
+ test(gl, [vs, fs], gl.VERTEX_SHADER);
+ }
+
+ {
+ const vs = `
+ attribute vec4 position;
+ void main() {
+ gl_Position = position;
+ gl_PointSize = 1.0;
+ }
+ `;
+
+ const fs = `
+ precision ${precision} float;
+ uniform ${precision} vec3 v;
+ void main() {
+ gl_FragColor = vec4(normalize(v) * 0.5 + 0.5, 1);
+ }
+ `;
+
+ test(gl, [vs, fs], gl.FRAGMENT_SHADER);
+ }
+}
+
+function testRenderPrecisionInt(gl, precisionEnum, precision) {
+ function test(gl, shaderPair, shaderType) {
+ const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum);
+ const value = 1 << (format.rangeMax - 1);
+
+ const input = [value, value, value, value];
+ const expected = [255, 255, 255, 255];
+
+ const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} int precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`;
+ const program = testRenderPrecisionSetup(gl, shaderPair);
+ gl.uniform1i(gl.getUniformLocation(program, 'v'), value);
+ gl.uniform1f(gl.getUniformLocation(program, 'f'), value);
+ testRenderPrecision(gl, shaderType, 'int', precision, expected, msg);
+ }
+
+ {
+ const vs = `
+ attribute vec4 position;
+ uniform ${precision} int v;
+ uniform highp float f;
+ varying vec4 v_result;
+
+ void main() {
+ gl_Position = position;
+ gl_PointSize = 1.0;
+ float diff = abs(float(v) - f);
+ bool pass = diff < 1.0;
+ v_result = vec4(pass);
+ }
+ `;
+
+ const fs = `
+ precision mediump float;
+ varying vec4 v_result;
+ void main() {
+ gl_FragColor = v_result;
+ }
+ `;
+ test(gl, [vs, fs], gl.VERTEX_SHADER);
+ }
+
+ {
+ const vs = `
+ attribute vec4 position;
+ void main() {
+ gl_Position = position;
+ gl_PointSize = 1.0;
+ }
+ `;
+
+ const fs = `
+ precision ${precision} float;
+ uniform ${precision} int v;
+ uniform mediump float f;
+
+ void main() {
+ mediump float diff = abs(float(v) - f);
+ bool pass = diff < 1.0;
+ gl_FragColor = vec4(pass);
+ }
+ `;
+
+ test(gl, [vs, fs], gl.FRAGMENT_SHADER);
+ }
+}
+
+// because the canvas can be 16 bit IIRC
+const fb = gl.createFramebuffer(gl.FRAMEBUFFER);
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+const tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+gl.framebufferTexture2D(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ tex,
+ 0);
+
+gl.viewport(0, 0, 1, 1);
+
+{
+ testRenderPrecisionFloat(gl, gl.LOW_FLOAT, 'lowp');
+ testRenderPrecisionFloat(gl, gl.MEDIUM_FLOAT, 'mediump');
+
+ const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
+ if (format.precision !== 0) {
+ testRenderPrecisionFloat(gl, gl.HIGH_FLOAT, 'highp');
+ }
+}
+
+{
+ testRenderPrecisionInt(gl, gl.LOW_INT, 'lowp');
+ testRenderPrecisionInt(gl, gl.MEDIUM_INT, 'mediump');
+
+ const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT);
+ if (format.rangeMax !== 0) {
+ testRenderPrecisionInt(gl, gl.HIGH_INT, 'highp');
+ }
+}
+
+finishTest();
+</script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/type-conversion-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/type-conversion-test.html
new file mode 100644
index 0000000000..bb04f3ba00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/type-conversion-test.html
@@ -0,0 +1,151 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Tests calling WebGL APIs with various types");
+
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+var shader = wtu.loadStandardVertexShader(context);
+
+assertMsg(program != null, "Program Compiled");
+assertMsg(shader != null, "Shader Compiled");
+
+var loc = context.getUniformLocation(program, "u_modelViewProjMatrix");
+assertMsg(loc != null, "getUniformLocation succeeded");
+
+var buffer = context.createBuffer();
+context.bindBuffer(context.ARRAY_BUFFER, buffer);
+var texture = context.createTexture();
+context.bindTexture(context.TEXTURE_2D, texture);
+context.useProgram(program);
+
+var args = [
+ { type: "number", value: 0 },
+ { type: "number", value: 2 },
+ { type: "string that is NaN", value: "foo", },
+ { type: "string that is number", value: "2", },
+ { type: "null", value: null },
+ { type: "Empty Array", value: [] },
+ { type: "Object", value: {} },
+ { type: "Array of Number", value: [2] },
+ { type: "Array of String", value: ["foo"] },
+ { type: "Array of String that is number", value: ["0"] },
+ { type: "Array of String that is number", value: ["2"] },
+ { type: "TypedArray", value: new Float32Array(1) }
+];
+
+var argument;
+
+for (var i = 0; i < args.length; ++i) {
+ argument = args[i].value;
+ var func1 = shouldBeUndefined;
+ var func2 = shouldBeNonNull;
+ if (argument == 2) {
+ func2 = shouldBeNull;
+ }
+ var func3 = shouldBeNull;
+ debug("");
+ debug("testing type of " + args[i].type + " : value = " + argument);
+ func1("context.bindAttribLocation(program, argument, 'foo')");
+ func1("context.blendColor(argument, argument, argument, argument)");
+ func1("context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW)");
+ func1("context.bufferData(context.ARRAY_BUFFER, new Float32Array(10), context.STATIC_DRAW)");
+ func1("context.bufferSubData(context.ARRAY_BUFFER, argument, new Float32Array(2))");
+ func1("context.clear(argument)")
+ func1("context.clearColor(argument, 0, 0, 0)");
+ func1("context.clearColor(0, argument, 0, 0)");
+ func1("context.clearColor(0, 0, argument, 0)");
+ func1("context.clearColor(0, 0, 0, argument)");
+ func1("context.clearDepth(argument)");
+ func1("context.clearStencil(argument)");
+ func1("context.copyTexImage2D(context.TEXTURE_2D, argument, context.RGBA, 0, 0, 1, 1, 0)");
+ func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, argument, 0, 1, 1, 0)");
+ func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, argument, 1, 1, 0)");
+ func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, argument, 1, 0)");
+ func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, 0, argument, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, argument, 0, 0, 0, 0, 0, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, argument, 0, 0, 0, 0, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, argument, 0, 0, 0, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, argument, 0, 0, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, argument, 0, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, argument, 0)");
+ func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, 0, argument)");
+ func1("context.depthMask(argument)");
+ func1("context.depthRange(argument, 1)");
+ func1("context.depthRange(0, argument)");
+ func1("context.drawArrays(context.POINTS, argument, 1)");
+ func1("context.drawArrays(context.POINTS, 0, argument)");
+ //func1("context.drawElements(...)");
+ func1("context.enableVertexAttribArray(argument)");
+ func1("context.disableVertexAttribArray(argument)");
+ func2("context.getActiveAttrib(program, argument)");
+ func2("context.getActiveUniform(program, argument)");
+ func3("context.getParameter(argument)");
+ func1("context.lineWidth(argument)");
+ func1("context.polygonOffset(argument, 0)");
+ func1("context.polygonOffset(0, argument)");
+ //func1("context.readPixels(...)");
+ //func1("context.renderbufferStorage(...)");
+ func1("context.sampleCoverage(argument, 0)");
+ func1("context.sampleCoverage(0, argument)");
+ func1("context.scissor(argument, 0, 10, 10)");
+ func1("context.scissor(0, argument, 10, 10)");
+ func1("context.scissor(0, 0, argument, 10)");
+ func1("context.scissor(0, 0, 10, argument)");
+ func1("context.shaderSource(shader, argument)");
+ func1("context.stencilFunc(context.NEVER, argument, 255)");
+ func1("context.stencilFunc(context.NEVER, 0, argument)");
+ //func1("context.stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)");
+ func1("context.stencilMask(argument)");
+ //func1("context.stencilMaskSeparate(context.FRONT, argument);
+ //func1("context.texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView pixels)");
+ //func1("context.texParameterf(GLenum target, GLenum pname, GLfloat param)");
+ //func1("context.texParameteri(GLenum target, GLenum pname, GLint param)");
+ //func1("context.texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,GLsizei width, GLsizei height,GLenum format, GLenum type, ArrayBufferView pixels)");
+ func1("context.uniform1i(loc, argument)");
+ func1("context.uniform2i(loc, argument, 0)");
+ func1("context.uniform2i(loc, 0, argument)");
+ func1("context.uniform3i(loc, argument, 0, 0)");
+ func1("context.uniform3i(loc, 0, argument, 0)");
+ func1("context.uniform3i(loc, 0, 0, argument)");
+ func1("context.uniform4i(loc, argument, 0, 0, 0)");
+ func1("context.uniform4i(loc, 0, argument, 0, 0)");
+ func1("context.uniform4i(loc, 0, 0, argument, 0)");
+ func1("context.uniform4i(loc, 0, 0, 0, argument)");
+ func1("context.uniform1f(loc, argument)");
+ func1("context.uniform2f(loc, argument, 0)");
+ func1("context.uniform2f(loc, 0, argument)");
+ func1("context.uniform3f(loc, argument, 0, 0)");
+ func1("context.uniform3f(loc, 0, argument, 0)");
+ func1("context.uniform3f(loc, 0, 0, argument)");
+ func1("context.uniform4f(loc, argument, 0, 0, 0)");
+ func1("context.uniform4f(loc, 0, argument, 0, 0)");
+ func1("context.uniform4f(loc, 0, 0, argument, 0)");
+ func1("context.uniform4f(loc, 0, 0, 0, argument)");
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/uninitialized-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/uninitialized-test.html
new file mode 100644
index 0000000000..c8f935dd1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/uninitialized-test.html
@@ -0,0 +1,262 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uninitialized GL Resources Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("Tests to check user code cannot access uninitialized data from GL resources.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl)
+ testFailed("Context created.");
+else
+ testPassed("Context created.");
+
+function setupTexture(texWidth, texHeight) {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
+ // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem)
+ // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time.
+
+ var badData = new Uint8Array(texWidth * texHeight * 4);
+ for (var i = 0; i < badData.length; ++i)
+ badData[i] = i % 255;
+
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ gl.finish(); // make sure it has been uploaded
+
+ gl.deleteTexture(texture);
+ gl.finish(); // make sure it has been deleted
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ return texture;
+}
+
+function checkNonZeroPixels(texture, texWidth, texHeight, skipX, skipY, skipWidth, skipHeight, skipR, skipG, skipB, skipA) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ var data = new Uint8Array(texWidth * texHeight * 4);
+ gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, data);
+
+ var k = 0;
+ for (var y = 0; y < texHeight; ++y) {
+ for (var x = 0; x < texWidth; ++x) {
+ var index = (y * texWidth + x) * 4;
+ if (x >= skipX && x < skipX + skipWidth && y >= skipY && y < skipY + skipHeight) {
+ if (data[index] != skipR || data[index + 1] != skipG || data[index + 2] != skipB || data[index + 3] != skipA) {
+ testFailed("non-zero pixel values are wrong");
+ return;
+ }
+ } else {
+ for (var i = 0; i < 4; ++i) {
+ if (data[index + i] != 0)
+ k++;
+ }
+ }
+ }
+ }
+ if (k) {
+ testFailed("Found " + k + " non-zero bytes");
+ } else {
+ testPassed("All data initialized");
+ }
+}
+
+var width = 512;
+var height = 512;
+
+debug("");
+debug("Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0.");
+
+var tex = setupTexture(width, height);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+checkNonZeroPixels(tex, width, height, 0, 0, 0, 0, 0, 0, 0, 0);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading a partially initialized texture (texImage2D) should succeed with all uninitialized bytes set to 0 and initialized bytes untouched.");
+
+var tex = setupTexture(width, height);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+var data = new Uint8Array(4);
+var r = 108;
+var g = 72;
+var b = 36;
+var a = 9;
+data[0] = r;
+data[1] = g;
+data[2] = b;
+data[3] = a;
+gl.texSubImage2D(gl.TEXTURE_2D, 0, width/2, height/2, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data);
+checkNonZeroPixels(tex, width, height, width/2, height/2, 1, 1, r, g, b, a);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading an uninitialized portion of a texture (copyTexImage2D) should succeed with all bytes set to 0.");
+
+var tex = setupTexture(width, height);
+var fbo = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+var rbo = gl.createRenderbuffer();
+gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+var fboWidth = 16;
+var fboHeight = 16;
+gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+gl.clearColor(1.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0);
+checkNonZeroPixels(tex, width, height, 0, 0, fboWidth, fboHeight, 255, 0, 0, 255);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should succeed with all bytes set to 0.");
+
+var tex = setupTexture(width, height);
+var fbo = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+var rbo = gl.createRenderbuffer();
+gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+var fboWidth = 16;
+var fboHeight = 16;
+gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+gl.clearColor(1.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+var x = -8;
+var y = -8;
+gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, x, y, width, height, 0);
+checkNonZeroPixels(tex, width, height, -x, -y, fboWidth, fboHeight, 255, 0, 0, 255);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading an uninitialized portion of a texture (copyTexImage2D from WebGL internal fbo) should succeed with all bytes set to 0.");
+
+var tex = setupTexture(width, height);
+gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+gl.clearColor(0.0, 1.0, 0.0, 0.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0);
+checkNonZeroPixels(tex, width, height, 0, 0, gl.canvas.width, gl.canvas.height, 0, 255, 0, 0);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading an uninitialized portion of a texture (copyTexSubImage2D) should succeed with all bytes set to 0.");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+var fbo = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+var rbo = gl.createRenderbuffer();
+gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+var fboWidth = 16;
+var fboHeight = 16;
+gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+gl.clearColor(1.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
+checkNonZeroPixels(tex, width, height, 0, 0, fboWidth, fboHeight, 255, 0, 0, 255);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading an uninitialized portion of a texture (copyTexSubImage2D with negative x and y) should succeed with all bytes set to 0.");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+var fbo = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+var rbo = gl.createRenderbuffer();
+gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+var fboWidth = 16;
+var fboHeight = 16;
+gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+gl.clearColor(1.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+var x = -8;
+var y = -8;
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, x, y, width, height);
+checkNonZeroPixels(tex, width, height, -x, -y, fboWidth, fboHeight, 255, 0, 0, 255);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Reading an uninitialized portion of a texture (copyTexSubImage2D from WebGL internal fbo) should succeed with all bytes set to 0.");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+gl.clearColor(0.0, 1.0, 0.0, 0.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
+checkNonZeroPixels(tex, width, height, 0, 0, canvas.width, canvas.height, 0, 255, 0, 0);
+gl.deleteTexture(tex);
+gl.finish();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+//TODO: uninitialized vertex array buffer
+//TODO: uninitialized vertex elements buffer
+//TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?)
+//TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?)
+//TODO: uninitialized uniform arrays?
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
new file mode 100644
index 0000000000..770a107dc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
@@ -0,0 +1,299 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL stencil mask/func front-state-back-state equality test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Tests that stencil mask/func are validated correctly when the front state and back state differ.");
+
+var gl;
+
+function checkDrawError(errIfMismatch) {
+ wtu.shouldGenerateGLError(gl, errIfMismatch, "wtu.dummySetProgramAndDrawNothing(gl)");
+}
+
+function setStencilMask(mask) {
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMaskSeparate(gl.FRONT, " + mask[0] + ")");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMaskSeparate(gl.BACK, " + mask[1] + ")");
+}
+
+function testStencilMaskCase(mask, error) {
+ setStencilMask(mask);
+ // If an error is generated, it should be at draw time.
+ checkDrawError(error);
+}
+
+function testStencilMask(errIfMismatch) {
+ testStencilMaskCase([0, 256], gl.NO_ERROR);
+ testStencilMaskCase([1, 256], errIfMismatch);
+ testStencilMaskCase([1, 257], gl.NO_ERROR);
+ testStencilMaskCase([1, 258], errIfMismatch);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMask(1023)", "resetting stencilMask");
+}
+
+function setStencilFunc(ref, mask) {
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFuncSeparate(gl.FRONT, gl.ALWAYS, " + ref[0] + ", " + mask[0] + ")");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFuncSeparate(gl.BACK, gl.ALWAYS, " + ref[1] + ", " + mask[1] + ")");
+}
+
+function testStencilFuncCase(ref, mask, error) {
+ setStencilFunc(ref, mask);
+ // If an error is generated, it should be at draw time.
+ checkDrawError(error);
+}
+
+function testStencilFunc(errIfMismatch) {
+ testStencilFuncCase([ 256, 257], [1023, 1023], gl.NO_ERROR);
+ testStencilFuncCase([ 256, 254], [1023, 1023], errIfMismatch);
+
+ testStencilFuncCase([ -1, 0], [1023, 1023], gl.NO_ERROR);
+ testStencilFuncCase([ -1, 254], [1023, 1023], errIfMismatch);
+
+ testStencilFuncCase([ 0, 0], [ 1, 257], gl.NO_ERROR);
+ testStencilFuncCase([ 0, 0], [ 1, 258], errIfMismatch);
+
+ testStencilFuncCase([ 1, 1], [1024, 2048], gl.NO_ERROR);
+ testStencilFuncCase([ 1, 1], [2048, 1024], gl.NO_ERROR);
+
+ testStencilFuncCase([ -1, -1], [1023, 1023], gl.NO_ERROR);
+ testStencilFuncCase([ -1, 0], [1023, 1023], gl.NO_ERROR);
+ testStencilFuncCase([ 0, -1], [1023, 1023], gl.NO_ERROR);
+ testStencilFuncCase([ 0, 0], [1023, 1023], gl.NO_ERROR);
+
+ testStencilFuncCase([ -1, 255], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([ 0, 256], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([ 0, 1024], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([ 1, 257], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([ 255, -1], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([ 256, 0], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([1024, 0], [1023, 1023], errIfMismatch);
+ testStencilFuncCase([ 257, 1], [1023, 1023], errIfMismatch);
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFunc(gl.ALWAYS, 0, 1023)", "resetting stencilFunc");
+}
+
+//
+// Tests of the default framebuffer
+//
+
+debug("");
+
+debug("Testing default framebuffer with { stencil: true }");
+gl = wtu.create3DContext(undefined, { stencil: true });
+{
+ gl.enable(gl.STENCIL_TEST);
+ testStencilMaskCase([1, 256], gl.INVALID_OPERATION);
+ testStencilFuncCase([256, 0], [1023, 1023], gl.INVALID_OPERATION);
+}
+
+debug("Testing default framebuffer with { stencil: false }");
+gl = wtu.create3DContext(undefined, { stencil: false });
+{
+ // with { stencil: false }
+ gl.enable(gl.STENCIL_TEST);
+ testStencilMaskCase([1, 256], gl.NO_ERROR);
+ testStencilFuncCase([256, 0], [1023, 1023], gl.NO_ERROR);
+}
+// (continue using this GL context for the other tests)
+
+//
+// Tests with a framebuffer object
+//
+
+const fb = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+const colorRB = gl.createRenderbuffer();
+gl.bindRenderbuffer(gl.RENDERBUFFER, colorRB);
+gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 1, 1);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRB);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "initial framebuffer setup")
+
+function runWithStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, fn) {
+ let rbo = null;
+ let attachment;
+ if (haveDepthBuffer || haveStencilBuffer) {
+ rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+
+ let internalformat;
+ if (haveDepthBuffer && haveStencilBuffer) {
+ internalformat = gl.DEPTH_STENCIL;
+ attachment = gl.DEPTH_STENCIL_ATTACHMENT;
+ } else if (haveDepthBuffer) {
+ internalformat = gl.DEPTH_COMPONENT16;
+ attachment = gl.DEPTH_ATTACHMENT;
+ } else if (haveStencilBuffer) {
+ internalformat = gl.STENCIL_INDEX8;
+ attachment = gl.STENCIL_ATTACHMENT;
+ }
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalformat, 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, rbo);
+ }
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "depth/stencil renderbuffer setup")
+
+ if (enableStencilTest) {
+ gl.enable(gl.STENCIL_TEST);
+ } else {
+ gl.disable(gl.STENCIL_TEST);
+ }
+
+ fn();
+
+ if (rbo) {
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(rbo);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "depth/stencil renderbuffer cleanup")
+}
+
+function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, errIfMismatch) {
+ debug("");
+ debug("With depthbuffer=" + haveDepthBuffer +
+ ", stencilbuffer=" + haveStencilBuffer +
+ ", stencilTest=" + enableStencilTest +
+ ", expecting error=" + wtu.glEnumToString(gl, errIfMismatch) +
+ " for mismatching mask or func settings.");
+
+ runWithStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, () => {
+ // Errors should be the same for both mask and func, because stencil test
+ // and stencil write are always enabled/disabled in tandem.
+ testStencilMask(errIfMismatch);
+ testStencilFunc(errIfMismatch);
+ });
+}
+
+debug("");
+debug("Base case checks:");
+testStencilMaskCase([0, 0], gl.NO_ERROR);
+testStencilFuncCase([0, 0], [1023, 1023], gl.NO_ERROR);
+
+// haveDepthBuffer
+// | haveStencilBuffer
+// | | enableStencilTest
+// | | | errIfMismatch
+testStencilSettings(false, false, false, gl.NO_ERROR);
+testStencilSettings( true, false, false, gl.NO_ERROR);
+testStencilSettings(false, true, false, gl.NO_ERROR);
+testStencilSettings( true, true, false, gl.NO_ERROR);
+
+testStencilSettings(false, false, true, gl.NO_ERROR);
+testStencilSettings( true, false, true, gl.NO_ERROR);
+testStencilSettings(false, true, true, gl.INVALID_OPERATION);
+testStencilSettings( true, true, true, gl.INVALID_OPERATION);
+
+//
+// Tests to make sure the stencil validation check, if cached, is invalidated correctly.
+//
+
+debug("");
+
+debug("Setup for stencil validation cache invalidation tests");
+setStencilMask([1, 258]);
+setStencilFunc([0, 256], [1023, 1023]);
+
+debug("Test with enabling/disabling stencil test");
+runWithStencilSettings(false, true, false, () => {
+ checkDrawError(gl.NO_ERROR);
+ gl.enable(gl.STENCIL_TEST);
+ checkDrawError(gl.INVALID_OPERATION);
+ gl.disable(gl.STENCIL_TEST);
+ checkDrawError(gl.NO_ERROR);
+});
+
+debug("Test with swapping in a new FBO");
+runWithStencilSettings(false, false, true, () => {
+ // no error with no stencil buffer
+ checkDrawError(gl.NO_ERROR);
+
+ // swap in a new FBO with a stencil buffer
+ const fb2 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorRB);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRB);
+ const rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // this draw sholud detect the new fbo state
+ checkDrawError(gl.INVALID_OPERATION);
+
+ gl.deleteFramebuffer(fb2);
+ gl.deleteRenderbuffer(rbo)
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+});
+
+debug("Test with adding a stencil attachment");
+runWithStencilSettings(false, false, true, () => {
+ // no error with no stencil buffer
+ checkDrawError(gl.NO_ERROR);
+
+ // add a stencil attachment
+ const rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // this draw sholud detect the new fbo state
+ checkDrawError(gl.INVALID_OPERATION);
+
+ gl.deleteRenderbuffer(rbo)
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+});
+
+debug("Test with reallocating the DEPTH_STENCIL attachment from depth to depth+stencil");
+runWithStencilSettings(false, false, true, () => {
+ // attach a depth buffer to the DEPTH_STENCIL attachment
+ const rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // this draw is invalid, but it still might trigger caching of the stencil validation
+ checkDrawError(gl.INVALID_FRAMEBUFFER_OPERATION);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, 1, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ // this draw sholud detect the new fbo state
+ checkDrawError(gl.INVALID_OPERATION);
+
+ gl.deleteRenderbuffer(rbo)
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+});
+
+gl.deleteFramebuffer(fb);
+gl.deleteRenderbuffer(colorRB);
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific.html
new file mode 100644
index 0000000000..a4cdc8c782
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLES2 difference test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Tests the few differences between WebGL and GLES2");
+
+var gl = wtu.create3DContext();
+var program = wtu.loadStandardProgram(gl);
+gl.useProgram(program);
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup should succeed");
+
+debug("");
+debug("Verify that constant color and constant alpha cannot be used together as source and destination factors in the blend function");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.CONSTANT_COLOR, gl.CONSTANT_ALPHA)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.ONE_MINUS_CONSTANT_COLOR, gl.CONSTANT_ALPHA)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.CONSTANT_ALPHA, gl.CONSTANT_COLOR)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.ONE_MINUS_CONSTANT_ALPHA, gl.CONSTANT_COLOR)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFunc(gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR)");
+
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.CONSTANT_COLOR, gl.CONSTANT_ALPHA, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_COLOR, gl.CONSTANT_ALPHA, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.CONSTANT_ALPHA, gl.CONSTANT_COLOR, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_ALPHA, gl.CONSTANT_COLOR, gl.ONE, gl.ZERO)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE, gl.ZERO)");
+
+debug("");
+debug("Verify that in depthRange zNear <= zFar");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.depthRange(20, 10)");
+
+debug("");
+debug("Verify that *LENGTH are undefined");
+shouldBeUndefined(gl.INFO_LOG_LENGTH);
+shouldBeUndefined(gl.SHADER_SOURCE_LENGTH);
+shouldBeUndefined(gl.ACTIVE_UNIFORM_MAX_LENGTH);
+shouldBeUndefined(gl.ACTIVE_ATTRIB_MAX_LENGTH);
+shouldBeUndefined(gl.ACTIVE_ATTRIBUTE_MAX_LENGTH);
+
+debug("");
+debug("Verify that UNPACK_COLORSPACE_CONVERSION_WEBGL is supported");
+shouldBe("gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL)", "gl.BROWSER_DEFAULT_WEBGL");
+gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
+shouldBe("gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL)", "gl.NONE");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "set/get UNPACK_COLORSPACE_CONVERSION_WEBGL should generate no error");
+
+debug("");
+debug("Verify that drawingBufferWidth and drawingBufferHeights are implemented");
+shouldBeTrue("gl.drawingBufferWidth >= 0 && gl.drawingBufferHeight >= 0");
+
+debug("");
+debug("Verify that bindAttribLocation rejects names start with webgl_ or _webgl_");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindAttribLocation(program, 0, 'webgl_a')");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindAttribLocation(program, 0, '_webgl_a')");
+
+debug("");
+debug("Verify that NaN line width is not accepted");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.lineWidth(NaN)");
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/more/00_test_list.txt
new file mode 100644
index 0000000000..f202776ac5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/00_test_list.txt
@@ -0,0 +1,54 @@
+conformance/constants.html
+conformance/getContext.html
+conformance/methods.html
+conformance/quickCheckAPI-A.html
+conformance/quickCheckAPI-B1.html
+conformance/quickCheckAPI-B2.html
+conformance/quickCheckAPI-B3.html
+conformance/quickCheckAPI-B4.html
+conformance/quickCheckAPI-C.html
+conformance/quickCheckAPI-D_G.html
+conformance/quickCheckAPI-G_I.html
+conformance/quickCheckAPI-L_S.html
+conformance/quickCheckAPI-S_V.html
+conformance/webGLArrays.html
+functions/bindBuffer.html
+functions/bindBufferBadArgs.html
+functions/bindFramebufferLeaveNonZero.html
+functions/bufferData.html
+functions/bufferDataBadArgs.html
+functions/bufferSubData.html
+functions/bufferSubDataBadArgs.html
+functions/copyTexImage2D.html
+functions/copyTexImage2DBadArgs.html
+functions/copyTexSubImage2D.html
+functions/copyTexSubImage2DBadArgs.html
+functions/deleteBufferBadArgs.html
+functions/drawArrays.html
+functions/drawElements.html
+functions/isTests.html
+--min-version 1.0.2 functions/isTestsBadArgs.html
+functions/readPixels.html
+functions/readPixelsBadArgs.html
+functions/texImage2D.html
+functions/texImage2DBadArgs.html
+functions/texImage2DHTML.html
+functions/texImage2DHTMLBadArgs.html
+functions/texSubImage2D.html
+functions/texSubImage2DBadArgs.html
+functions/texSubImage2DHTML.html
+functions/texSubImage2DHTMLBadArgs.html
+functions/uniformf.html
+functions/uniformfBadArgs.html
+functions/uniformfArrayLen1.html
+functions/uniformi.html
+functions/uniformiBadArgs.html
+functions/uniformMatrix.html
+functions/uniformMatrixBadArgs.html
+functions/vertexAttrib.html
+functions/vertexAttribBadArgs.html
+functions/vertexAttribPointer.html
+functions/vertexAttribPointerBadArgs.html
+glsl/arrayOutOfBounds.html
+glsl/uniformOutOfBounds.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/README.md b/dom/canvas/test/webgl-conf/checkout/conformance/more/README.md
new file mode 100644
index 0000000000..01937147f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/README.md
@@ -0,0 +1,53 @@
+Tests for the WebGL canvas context
+==================================
+
+These tests are intended to serve the following purposes:
+
+ * Assert spec conformance
+ * Check the safety of the GL binding (bounds checking, same origin policy)
+ * Provide performance numbers for developers
+
+
+Running the tests
+-----------------
+
+ 1. <a href="http://learningwebgl.com/blog/?p=11">Install a browser with WebGL support</a>
+ 2. Run <code>ruby gen_tests.rb</code> if you have modified the tests.
+ 3. Run <code>ruby test_server.rb</code> if you want to get test run output to test_server's stdout (especially useful for finding out which test crashed your browser.)
+ 4. Open all_tests.html in your browser.
+
+
+Want to contribute?
+-------------------
+
+ 1. Fork this repo
+ 2. Run <code>gen_tests.rb</code>
+ 3. Look into templates/ to see which functions lack tests (also see <a href="../raw/master/methods.txt">methods.txt</a> and <a href="http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl">nsICanvasRenderingContextWebGL.idl</a>):
+ 1. copy methodName.html to functions/methodName.html and write tests that test the results of valid inputs.
+ 2. copy methodNameBadArgs.html to functions/methodNameBadArgs.html and write tests to assert that invalid inputs throw exceptions.
+ 3. If your test causes a segfault, add the following to the top of the script tag: <code>Tests.autorun = false; Tests.message = "Caution: this may crash your browser";</code>
+ 4. For each performance test:
+ 1. Write a performance/myTestName.html and set <code>Tests.autorun = false;</code>
+ 5. If you have a test that you would like to run over the whole API or want to generate tests programmatically, add them to gen_tests.rb or write your own script.
+ 6. Create a commit for each file. (E.g. <code>for f in $(git status | grep -e "^#\\s*functions/\\S*$" | sed "s/^#\s*//"); do git add $f; git commit -m $f; done</code>)
+ 7. Send me a pull request.
+ 8. Congratulations, you're now a contributor!
+
+
+For more information on WebGL:
+
+ * <a href="http://planet-webgl.org">Planet WebGL</a>
+ * <a href="http://learningwebgl.com">Learning WebGL</a>
+ * <a href="http://www.khronos.org/message_boards/viewforum.php?f=34">WebGL on Khronos Message Boards</a>
+
+Developer links:
+
+ * <a href="https://bugzilla.mozilla.org/buglist.cgi?quicksearch=webgl">WebGL on Mozilla Bugzilla</a>
+ * <a href="https://bugzilla.webkit.org/buglist.cgi?quicksearch=webgl">WebGL on WebKit Bugzilla</a>
+ * <a href="http://code.google.com/p/chromium/issues/list?q=label:3D-WebGL">WebGL on Chromium Bugzilla</a>
+
+What's the stuff in apigen?
+
+ There are some Python scripts in the apigen/ directory that generate C++ based on the API definition files (gl2.h, api_modifications.txt, valid_args.txt.) The generated code is Mozilla XPCOM functions that check their args against the valid GLES 2.0 constants (as they were written on the man pages.) There's also some wackier stuff for checking copyTexImage2D and copyTexSubImage2D image dimensions against viewport dimensions.
+
+ If you can use it to generate code for your WebGL implementation, it might save you 1500 lines of typing and testing. The last time I used it was summer 2009 to generate a patch for Canvas 3D, so it's likely somewhat out of date.
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests.html
new file mode 100644
index 0000000000..d089c716f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+ <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+ <style type="text/css">
+ h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+ iframe { display: inline; border: 1px solid black; overflow: hidden;}
+ </style>
+ <script type="application/javascript">
+ function loadTest(id, url) {
+ document.getElementById(id).src = url;
+ }
+ function seqLoader() {
+ var iframes = document.getElementsByTagName('iframe');
+ for (var i=0; i<iframes.length; i++) {
+ iframes[i].addEventListener('load', (function(j) {
+ return function() {
+ var e = document.getElementById((j+1)+'_link');
+ if (e) loadTest(j+1, e.href);
+ }
+ })(i), false);
+ }
+ var e = document.getElementById('0_link');
+ if (e) loadTest(0, e.href);
+ }
+ </script>
+</head>
+<body onload="seqLoader()">
+
+ <div>
+ <iframe src="conformance/badArgsArityLessThanArgc.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/constants.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/constants.html">conformance/constants.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/fuzzTheAPI.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/getContext.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/getContext.html">conformance/getContext.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/methods.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/methods.html">conformance/methods.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/quickCheckAPI.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/quickCheckAPIBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="conformance/webGLArrays.html" width="110" height="42"></iframe>
+ <h2><a href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bindBuffer.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bindBufferBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bindFramebufferLeaveNonZero.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bufferData.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bufferData.html">functions/bufferData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bufferDataBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bufferSubData.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/bufferSubDataBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/copyTexImage2D.html" width="110" height="42"></iframe>
+ <h2><a href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/copyTexImage2DBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/copyTexSubImage2D.html" width="110" height="42"></iframe>
+ <h2><a href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/copyTexSubImage2DBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/deleteBufferBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/drawArrays.html" width="110" height="42"></iframe>
+ <h2><a href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/drawArraysOutOfBounds.html" width="110" height="42"></iframe>
+ <h2><a href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/drawElements.html" width="110" height="42"></iframe>
+ <h2><a href="functions/drawElements.html">functions/drawElements.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/drawElementsBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/getImageData.html" width="110" height="42"></iframe>
+ <h2><a href="functions/getImageData.html">functions/getImageData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/getImageDataBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/isTests.html" width="110" height="42"></iframe>
+ <h2><a href="functions/isTests.html">functions/isTests.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/linkProgramBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/readPixels.html" width="110" height="42"></iframe>
+ <h2><a href="functions/readPixels.html">functions/readPixels.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/readPixelsBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texImage2D.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texImage2DBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texImage2DHTML.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texImage2DHTMLBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texSubImage2D.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texSubImage2DBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texSubImage2DHTML.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/texSubImage2DHTMLBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/uniformMatrix.html" width="110" height="42"></iframe>
+ <h2><a href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/uniformMatrixBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/uniformf.html" width="110" height="42"></iframe>
+ <h2><a href="functions/uniformf.html">functions/uniformf.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/uniformfBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/uniformi.html" width="110" height="42"></iframe>
+ <h2><a href="functions/uniformi.html">functions/uniformi.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/uniformiBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/vertexAttrib.html" width="110" height="42"></iframe>
+ <h2><a href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/vertexAttribBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/vertexAttribPointer.html" width="110" height="42"></iframe>
+ <h2><a href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="functions/vertexAttribPointerBadArgs.html" width="110" height="42"></iframe>
+ <h2><a href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="performance/CPUvsGPU.html" width="110" height="42"></iframe>
+ <h2><a href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="performance/bandwidth.html" width="110" height="42"></iframe>
+ <h2><a href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="performance/jsGCPause.html" width="110" height="42"></iframe>
+ <h2><a href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="performance/jsMatrixMult.html" width="110" height="42"></iframe>
+ <h2><a href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="performance/jsToGLOverhead.html" width="110" height="42"></iframe>
+ <h2><a href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="glsl/arrayOutOfBounds.html" width="110" height="42"></iframe>
+ <h2><a href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="glsl/longLoops.html" width="110" height="42"></iframe>
+ <h2><a href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="glsl/uniformOutOfBounds.html" width="110" height="42"></iframe>
+ <h2><a href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe src="glsl/unusedAttribsUniforms.html" width="110" height="42"></iframe>
+ <h2><a href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+ </div>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_linkonly.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_linkonly.html
new file mode 100644
index 0000000000..0ec563b028
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_linkonly.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+ <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+ <style type="text/css">
+ h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+ iframe { display: inline; border: 1px solid black; overflow: hidden;}
+ </style>
+ <script type="application/javascript">
+ function loadTest(id, url) {
+ document.getElementById(id).src = url;
+ }
+ function seqLoader() {
+ var iframes = document.getElementsByTagName('iframe');
+ for (var i=0; i<iframes.length; i++) {
+ iframes[i].addEventListener('load', (function(j) {
+ return function() {
+ var e = document.getElementById((j+1)+'_link');
+ if (e) loadTest(j+1, e.href);
+ }
+ })(i), false);
+ }
+ var e = document.getElementById('0_link');
+ if (e) loadTest(0, e.href);
+ }
+ </script>
+</head>
+<body onload="seqLoader()">
+
+ <div>
+ <iframe id="0" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(0, 'conformance/badArgsArityLessThanArgc.html');return false" href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="1" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(1, 'conformance/constants.html');return false" href="conformance/constants.html">conformance/constants.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="2" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(2, 'conformance/fuzzTheAPI.html');return false" href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="3" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(3, 'conformance/getContext.html');return false" href="conformance/getContext.html">conformance/getContext.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="4" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(4, 'conformance/methods.html');return false" href="conformance/methods.html">conformance/methods.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="5" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(5, 'conformance/quickCheckAPI.html');return false" href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="6" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(6, 'conformance/quickCheckAPIBadArgs.html');return false" href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="7" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(7, 'conformance/webGLArrays.html');return false" href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="8" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(8, 'functions/bindBuffer.html');return false" href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="9" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(9, 'functions/bindBufferBadArgs.html');return false" href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="10" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(10, 'functions/bindFramebufferLeaveNonZero.html');return false" href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="11" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(11, 'functions/bufferData.html');return false" href="functions/bufferData.html">functions/bufferData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="12" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(12, 'functions/bufferDataBadArgs.html');return false" href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="13" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(13, 'functions/bufferSubData.html');return false" href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="14" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(14, 'functions/bufferSubDataBadArgs.html');return false" href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="15" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(15, 'functions/copyTexImage2D.html');return false" href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="16" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(16, 'functions/copyTexImage2DBadArgs.html');return false" href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="17" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(17, 'functions/copyTexSubImage2D.html');return false" href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="18" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(18, 'functions/copyTexSubImage2DBadArgs.html');return false" href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="19" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(19, 'functions/deleteBufferBadArgs.html');return false" href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="20" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(20, 'functions/drawArrays.html');return false" href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="21" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(21, 'functions/drawArraysOutOfBounds.html');return false" href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="22" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(22, 'functions/drawElements.html');return false" href="functions/drawElements.html">functions/drawElements.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="23" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(23, 'functions/drawElementsBadArgs.html');return false" href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="24" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(24, 'functions/getImageData.html');return false" href="functions/getImageData.html">functions/getImageData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="25" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(25, 'functions/getImageDataBadArgs.html');return false" href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="26" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(26, 'functions/isTests.html');return false" href="functions/isTests.html">functions/isTests.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="27" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(27, 'functions/linkProgramBadArgs.html');return false" href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="28" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(28, 'functions/readPixels.html');return false" href="functions/readPixels.html">functions/readPixels.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="29" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(29, 'functions/readPixelsBadArgs.html');return false" href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="30" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(30, 'functions/texImage2D.html');return false" href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="31" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(31, 'functions/texImage2DBadArgs.html');return false" href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="32" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(32, 'functions/texImage2DHTML.html');return false" href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="33" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(33, 'functions/texImage2DHTMLBadArgs.html');return false" href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="34" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(34, 'functions/texSubImage2D.html');return false" href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="35" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(35, 'functions/texSubImage2DBadArgs.html');return false" href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="36" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(36, 'functions/texSubImage2DHTML.html');return false" href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="37" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(37, 'functions/texSubImage2DHTMLBadArgs.html');return false" href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="38" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(38, 'functions/uniformMatrix.html');return false" href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="39" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(39, 'functions/uniformMatrixBadArgs.html');return false" href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="40" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(40, 'functions/uniformf.html');return false" href="functions/uniformf.html">functions/uniformf.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="41" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(41, 'functions/uniformfBadArgs.html');return false" href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="42" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(42, 'functions/uniformi.html');return false" href="functions/uniformi.html">functions/uniformi.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="43" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(43, 'functions/uniformiBadArgs.html');return false" href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="44" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(44, 'functions/vertexAttrib.html');return false" href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="45" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(45, 'functions/vertexAttribBadArgs.html');return false" href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="46" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(46, 'functions/vertexAttribPointer.html');return false" href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="47" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(47, 'functions/vertexAttribPointerBadArgs.html');return false" href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="48" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(48, 'performance/CPUvsGPU.html');return false" href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="49" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(49, 'performance/bandwidth.html');return false" href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="50" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(50, 'performance/jsGCPause.html');return false" href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="51" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(51, 'performance/jsMatrixMult.html');return false" href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="52" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(52, 'performance/jsToGLOverhead.html');return false" href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="53" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(53, 'glsl/arrayOutOfBounds.html');return false" href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="54" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(54, 'glsl/longLoops.html');return false" href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="55" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(55, 'glsl/uniformOutOfBounds.html');return false" href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="56" width="110" height="42"></iframe>
+ <h2><a onclick="loadTest(56, 'glsl/unusedAttribsUniforms.html');return false" href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+ </div>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_sequential.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_sequential.html
new file mode 100644
index 0000000000..5ebf8382ba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/all_tests_sequential.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+ <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+ <style type="text/css">
+ h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+ iframe { display: inline; border: 1px solid black; overflow: hidden;}
+ </style>
+ <script type="application/javascript">
+ function loadTest(id, url) {
+ document.getElementById(id).src = url;
+ }
+ function seqLoader() {
+ var iframes = document.getElementsByTagName('iframe');
+ for (var i=0; i<iframes.length; i++) {
+ iframes[i].addEventListener('load', (function(j) {
+ return function() {
+ var e = document.getElementById((j+1)+'_link');
+ if (e) loadTest(j+1, e.href);
+ }
+ })(i), false);
+ }
+ var e = document.getElementById('0_link');
+ if (e) loadTest(0, e.href);
+ }
+ </script>
+</head>
+<body onload="seqLoader()">
+
+ <div>
+ <iframe id="0" width="110" height="42"></iframe>
+ <h2><a id="0_link" href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="1" width="110" height="42"></iframe>
+ <h2><a id="1_link" href="conformance/constants.html">conformance/constants.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="2" width="110" height="42"></iframe>
+ <h2><a id="2_link" href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="3" width="110" height="42"></iframe>
+ <h2><a id="3_link" href="conformance/getContext.html">conformance/getContext.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="4" width="110" height="42"></iframe>
+ <h2><a id="4_link" href="conformance/methods.html">conformance/methods.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="5" width="110" height="42"></iframe>
+ <h2><a id="5_link" href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="6" width="110" height="42"></iframe>
+ <h2><a id="6_link" href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="7" width="110" height="42"></iframe>
+ <h2><a id="7_link" href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="8" width="110" height="42"></iframe>
+ <h2><a id="8_link" href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="9" width="110" height="42"></iframe>
+ <h2><a id="9_link" href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="10" width="110" height="42"></iframe>
+ <h2><a id="10_link" href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="11" width="110" height="42"></iframe>
+ <h2><a id="11_link" href="functions/bufferData.html">functions/bufferData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="12" width="110" height="42"></iframe>
+ <h2><a id="12_link" href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="13" width="110" height="42"></iframe>
+ <h2><a id="13_link" href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="14" width="110" height="42"></iframe>
+ <h2><a id="14_link" href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="15" width="110" height="42"></iframe>
+ <h2><a id="15_link" href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="16" width="110" height="42"></iframe>
+ <h2><a id="16_link" href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="17" width="110" height="42"></iframe>
+ <h2><a id="17_link" href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="18" width="110" height="42"></iframe>
+ <h2><a id="18_link" href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="19" width="110" height="42"></iframe>
+ <h2><a id="19_link" href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="20" width="110" height="42"></iframe>
+ <h2><a id="20_link" href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="21" width="110" height="42"></iframe>
+ <h2><a id="21_link" href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="22" width="110" height="42"></iframe>
+ <h2><a id="22_link" href="functions/drawElements.html">functions/drawElements.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="23" width="110" height="42"></iframe>
+ <h2><a id="23_link" href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="24" width="110" height="42"></iframe>
+ <h2><a id="24_link" href="functions/getImageData.html">functions/getImageData.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="25" width="110" height="42"></iframe>
+ <h2><a id="25_link" href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="26" width="110" height="42"></iframe>
+ <h2><a id="26_link" href="functions/isTests.html">functions/isTests.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="27" width="110" height="42"></iframe>
+ <h2><a id="27_link" href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="28" width="110" height="42"></iframe>
+ <h2><a id="28_link" href="functions/readPixels.html">functions/readPixels.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="29" width="110" height="42"></iframe>
+ <h2><a id="29_link" href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="30" width="110" height="42"></iframe>
+ <h2><a id="30_link" href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="31" width="110" height="42"></iframe>
+ <h2><a id="31_link" href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="32" width="110" height="42"></iframe>
+ <h2><a id="32_link" href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="33" width="110" height="42"></iframe>
+ <h2><a id="33_link" href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="34" width="110" height="42"></iframe>
+ <h2><a id="34_link" href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="35" width="110" height="42"></iframe>
+ <h2><a id="35_link" href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="36" width="110" height="42"></iframe>
+ <h2><a id="36_link" href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="37" width="110" height="42"></iframe>
+ <h2><a id="37_link" href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="38" width="110" height="42"></iframe>
+ <h2><a id="38_link" href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="39" width="110" height="42"></iframe>
+ <h2><a id="39_link" href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="40" width="110" height="42"></iframe>
+ <h2><a id="40_link" href="functions/uniformf.html">functions/uniformf.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="41" width="110" height="42"></iframe>
+ <h2><a id="41_link" href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="42" width="110" height="42"></iframe>
+ <h2><a id="42_link" href="functions/uniformi.html">functions/uniformi.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="43" width="110" height="42"></iframe>
+ <h2><a id="43_link" href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="44" width="110" height="42"></iframe>
+ <h2><a id="44_link" href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="45" width="110" height="42"></iframe>
+ <h2><a id="45_link" href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="46" width="110" height="42"></iframe>
+ <h2><a id="46_link" href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="47" width="110" height="42"></iframe>
+ <h2><a id="47_link" href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="48" width="110" height="42"></iframe>
+ <h2><a id="48_link" href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="49" width="110" height="42"></iframe>
+ <h2><a id="49_link" href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="50" width="110" height="42"></iframe>
+ <h2><a id="50_link" href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="51" width="110" height="42"></iframe>
+ <h2><a id="51_link" href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="52" width="110" height="42"></iframe>
+ <h2><a id="52_link" href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="53" width="110" height="42"></iframe>
+ <h2><a id="53_link" href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="54" width="110" height="42"></iframe>
+ <h2><a id="54_link" href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="55" width="110" height="42"></iframe>
+ <h2><a id="55_link" href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+ </div>
+
+
+ <div>
+ <iframe id="56" width="110" height="42"></iframe>
+ <h2><a id="56_link" href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+ </div>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-A.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-A.js
new file mode 100644
index 0000000000..c3e301ce14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-A.js
@@ -0,0 +1,69 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// A
+
+ activeTexture : {
+ generate : function() { return [textureUnit.random()]; },
+ checkArgValidity : function(t) { return textureUnit.has(t); },
+ teardown : function() { GL.activeTexture(GL.TEXTURE0); }
+ },
+ attachShader : {
+ generate : function() {
+ var p = GL.createProgram();
+ var sh = GL.createShader(shaderType.random());
+ return [p, sh];
+ },
+ checkArgValidity : function(p, sh) {
+ return GL.isProgram(p) && GL.isShader(sh) && !GL.getAttachedShaders(p).has(sh);
+ },
+ cleanup : function(p, sh) {
+ try {GL.detachShader(p,sh);} catch(e) {}
+ try {GL.deleteProgram(p);} catch(e) {}
+ try {GL.deleteShader(sh);} catch(e) {}
+ }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B1.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B1.js
new file mode 100644
index 0000000000..04f394be02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B1.js
@@ -0,0 +1,61 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// B-1
+
+ bindAttribLocation : {
+ generate : function() {
+ var program = GL.createProgram();
+ return [program, randomVertexAttribute(), randomName()];
+ },
+ checkArgValidity : function(program, index, name) {
+ return GL.isProgram(program) && isVertexAttribute(index) && isValidName(name);
+ },
+ cleanup : function(program, index, name) {
+ try { GL.deleteProgram(program); } catch(e) {}
+ }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B2.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B2.js
new file mode 100644
index 0000000000..f366c3d8f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B2.js
@@ -0,0 +1,154 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// B-2
+
+ bindBuffer : {
+ generate : function(buf) {
+ return [bufferTarget.random(), GL.createBuffer()];
+ },
+ checkArgValidity : function(target, buf) {
+ if (!bufferTarget.has(target))
+ return false;
+ GL.bindBuffer(target, buf);
+ return GL.isBuffer(buf);
+ },
+ cleanup : function(t, buf, m) {
+ GL.deleteBuffer(buf);
+ }
+ },
+ bindFramebuffer : {
+ generate : function() {
+ return [GL.FRAMEBUFFER, Math.random() > 0.5 ? null : GL.createFramebuffer()];
+ },
+ checkArgValidity : function(target, fbo) {
+ if (target != GL.FRAMEBUFFER)
+ return false;
+ if (fbo != null)
+ GL.bindFramebuffer(target, fbo);
+ return (fbo == null || GL.isFramebuffer(fbo));
+ },
+ cleanup : function(target, fbo) {
+ GL.bindFramebuffer(target, null);
+ if (fbo)
+ GL.deleteFramebuffer(fbo);
+ }
+ },
+ bindRenderbuffer : {
+ generate : function() {
+ return [GL.RENDERBUFFER, Math.random() > 0.5 ? null : GL.createRenderbuffer()];
+ },
+ checkArgValidity : function(target, rbo) {
+ if (target != GL.RENDERBUFFER)
+ return false;
+ if (rbo != null)
+ GL.bindRenderbuffer(target, rbo);
+ return (rbo == null || GL.isRenderbuffer(rbo));
+ },
+ cleanup : function(target, rbo) {
+ GL.bindRenderbuffer(target, null);
+ if (rbo)
+ GL.deleteRenderbuffer(rbo);
+ }
+ },
+ bindTexture : {
+ generate : function() {
+ return [bindTextureTarget.random(), Math.random() > 0.5 ? null : GL.createTexture()];
+ },
+ checkArgValidity : function(target, o) {
+ if (!bindTextureTarget.has(target))
+ return false;
+ if (o != null)
+ GL.bindTexture(target, o);
+ return (o == null || GL.isTexture(o));
+ },
+ cleanup : function(target, o) {
+ GL.bindTexture(target, null);
+ if (o)
+ GL.deleteTexture(o);
+ }
+ },
+ blendColor : {
+ generate : function() { return randomColor(); },
+ teardown : function() { GL.blendColor(0,0,0,0); }
+ },
+ blendEquation : {
+ generate : function() { return [blendEquationMode.random()]; },
+ checkArgValidity : function(o) { return blendEquationMode.has(o); },
+ teardown : function() { GL.blendEquation(GL.FUNC_ADD); }
+ },
+ blendEquationSeparate : {
+ generate : function() {
+ return [blendEquationMode.random(), blendEquationMode.random()];
+ },
+ checkArgValidity : function(o,p) {
+ return blendEquationMode.has(o) && blendEquationMode.has(p);
+ },
+ teardown : function() { GL.blendEquationSeparate(GL.FUNC_ADD, GL.FUNC_ADD); }
+ },
+ blendFunc : {
+ generate : function() {
+ return [blendFuncSfactor.random(), blendFuncDfactor.random()];
+ },
+ checkArgValidity : function(s,d) {
+ return blendFuncSfactor.has(s) && blendFuncDfactor.has(d);
+ },
+ teardown : function() { GL.blendFunc(GL.ONE, GL.ZERO); }
+ },
+ blendFuncSeparate : {
+ generate : function() {
+ return [blendFuncSfactor.random(), blendFuncDfactor.random(),
+ blendFuncSfactor.random(), blendFuncDfactor.random()];
+ },
+ checkArgValidity : function(s,d,as,ad) {
+ return blendFuncSfactor.has(s) && blendFuncDfactor.has(d) &&
+ blendFuncSfactor.has(as) && blendFuncDfactor.has(ad) ;
+ },
+ teardown : function() {
+ GL.blendFuncSeparate(GL.ONE, GL.ZERO, GL.ONE, GL.ZERO);
+ }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B3.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B3.js
new file mode 100644
index 0000000000..2a4796d914
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B3.js
@@ -0,0 +1,68 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// B-3
+
+ bufferData : {
+ setup : function() {
+ var buf = GL.createBuffer();
+ var ebuf = GL.createBuffer();
+ GL.bindBuffer(GL.ARRAY_BUFFER, buf);
+ GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ebuf);
+ return [buf, ebuf];
+ },
+ generate : function(buf, ebuf) {
+ return [bufferTarget.random(), randomBufferData(), bufferMode.random()];
+ },
+ checkArgValidity : function(target, bufData, mode) {
+ return bufferTarget.has(target) && isBufferData(bufData) && bufferMode.has(mode);
+ },
+ teardown : function(buf, ebuf) {
+ GL.deleteBuffer(buf);
+ GL.deleteBuffer(ebuf);
+ },
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B4.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B4.js
new file mode 100644
index 0000000000..4c1ca7d8b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-B4.js
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// B-4
+
+ bufferSubData : {
+ setup : function() {
+ var buf = GL.createBuffer();
+ var ebuf = GL.createBuffer();
+ GL.bindBuffer(GL.ARRAY_BUFFER, buf);
+ GL.bufferData(GL.ARRAY_BUFFER, 256, GL.STATIC_DRAW);
+ GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ebuf);
+ GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, 256, GL.STATIC_DRAW);
+ return [buf, ebuf];
+ },
+ generate : function(buf, ebuf) {
+ var d = randomBufferSubData(256);
+ return [bufferTarget.random(), d.offset, d.data];
+ },
+ checkArgValidity : function(target, offset, data) {
+ return bufferTarget.has(target) && offset >= 0 && data.byteLength >= 0 && offset + data.byteLength <= 256;
+ },
+ teardown : function(buf, ebuf) {
+ GL.deleteBuffer(buf);
+ GL.deleteBuffer(ebuf);
+ },
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-C.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-C.js
new file mode 100644
index 0000000000..fbe1c2a5c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-C.js
@@ -0,0 +1,119 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// C
+
+ checkFramebufferStatus : {
+ generate : function() {
+ return [Math.random() > 0.5 ? null : GL.createFramebuffer()];
+ },
+ checkArgValidity : function(fbo) {
+ if (fbo != null)
+ GL.bindFramebuffer(GL.FRAMEBUFFER, fbo);
+ return fbo == null || GL.isFramebuffer(fbo);
+ },
+ cleanup : function(fbo){
+ GL.bindFramebuffer(GL.FRAMEBUFFER, null);
+ if (fbo != null)
+ try{ GL.deleteFramebuffer(fbo); } catch(e) {}
+ }
+ },
+ clear : {
+ generate : function() { return [clearMask.random()]; },
+ checkArgValidity : function(mask) { return clearMask.has(mask); }
+ },
+ clearColor : {
+ generate : function() { return randomColor(); },
+ teardown : function() { GL.clearColor(0,0,0,0); }
+ },
+ clearDepth : {
+ generate : function() { return [Math.random()]; },
+ teardown : function() { GL.clearDepth(1); }
+ },
+ clearStencil : {
+ generate : function() { return [randomStencil()]; },
+ teardown : function() { GL.clearStencil(0); }
+ },
+ colorMask : {
+ generate : function() {
+ return [randomBool(), randomBool(), randomBool(), randomBool()];
+ },
+ teardown : function() { GL.colorMask(true, true, true, true); }
+ },
+ compileShader : {}, // FIXME
+ copyTexImage2D : {}, // FIXME
+ copyTexSubImage2D : {}, // FIXME
+ createBuffer : {
+ generate : function() { return []; },
+ returnValueCleanup : function(o) { GL.deleteBuffer(o); }
+ },
+ createFramebuffer : {
+ generate : function() { return []; },
+ returnValueCleanup : function(o) { GL.deleteFramebuffer(o); }
+ },
+ createProgram : {
+ generate : function() { return []; },
+ returnValueCleanup : function(o) { GL.deleteProgram(o); }
+ },
+ createRenderbuffer : {
+ generate : function() { return []; },
+ returnValueCleanup : function(o) { GL.deleteRenderbuffer(o); }
+ },
+ createShader : {
+ generate : function() { return [shaderType.random()]; },
+ checkArgValidity : function(t) { return shaderType.has(t); },
+ returnValueCleanup : function(o) { GL.deleteShader(o); }
+ },
+ createTexture : {
+ generate : function() { return []; },
+ returnValueCleanup : function(o) { GL.deleteTexture(o); }
+ },
+ cullFace : {
+ generate : function() { return [cullFace.random()]; },
+ checkArgValidity : function(f) { return cullFace.has(f); },
+ teardown : function() { GL.cullFace(GL.BACK); }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-D_G.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-D_G.js
new file mode 100644
index 0000000000..00e602002f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-D_G.js
@@ -0,0 +1,235 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// D
+
+ deleteBuffer : {
+ generate : function() { return [GL.createBuffer()]; },
+ checkArgValidity : function(o) {
+ GL.bindBuffer(GL.ARRAY_BUFFER, o);
+ return GL.isBuffer(o);
+ },
+ cleanup : function(o) {
+ GL.bindBuffer(GL.ARRAY_BUFFER, null);
+ try { GL.deleteBuffer(o); } catch(e) {}
+ }
+ },
+ deleteFramebuffer : {
+ generate : function() { return [GL.createFramebuffer()]; },
+ checkArgValidity : function(o) {
+ GL.bindFramebuffer(GL.FRAMEBUFFER, o);
+ return GL.isFramebuffer(o);
+ },
+ cleanup : function(o) {
+ GL.bindFramebuffer(GL.FRAMEBUFFER, null);
+ try { GL.deleteFramebuffer(o); } catch(e) {}
+ }
+ },
+ deleteProgram : {
+ generate : function() { return [GL.createProgram()]; },
+ checkArgValidity : function(o) { return GL.isProgram(o); },
+ cleanup : function(o) { try { GL.deleteProgram(o); } catch(e) {} }
+ },
+ deleteRenderbuffer : {
+ generate : function() { return [GL.createRenderbuffer()]; },
+ checkArgValidity : function(o) {
+ GL.bindRenderbuffer(GL.RENDERBUFFER, o);
+ return GL.isRenderbuffer(o);
+ },
+ cleanup : function(o) {
+ GL.bindRenderbuffer(GL.RENDERBUFFER, null);
+ try { GL.deleteRenderbuffer(o); } catch(e) {}
+ }
+ },
+ deleteShader : {
+ generate : function() { return [GL.createShader(shaderType.random())]; },
+ checkArgValidity : function(o) { return GL.isShader(o); },
+ cleanup : function(o) { try { GL.deleteShader(o); } catch(e) {} }
+ },
+ deleteTexture : {
+ generate : function() { return [GL.createTexture()]; },
+ checkArgValidity : function(o) {
+ GL.bindTexture(GL.TEXTURE_2D, o);
+ return GL.isTexture(o);
+ },
+ cleanup : function(o) {
+ GL.bindTexture(GL.TEXTURE_2D, null);
+ try { GL.deleteTexture(o); } catch(e) {}
+ }
+ },
+ depthFunc : {
+ generate : function() { return [depthFuncFunc.random()]; },
+ checkArgValidity : function(f) { return depthFuncFunc.has(f); },
+ teardown : function() { GL.depthFunc(GL.LESS); }
+ },
+ depthMask : {
+ generate : function() { return [randomBool()]; },
+ teardown : function() { GL.depthFunc(GL.TRUE); }
+ },
+ depthRange : {
+ generate : function() { return [Math.random(), Math.random()]; },
+ teardown : function() { GL.depthRange(0, 1); }
+ },
+ detachShader : {
+ generate : function() {
+ var p = GL.createProgram();
+ var sh = GL.createShader(shaderType.random());
+ GL.attachShader(p, sh);
+ return [p, sh];
+ },
+ checkArgValidity : function(p, sh) {
+ return GL.isProgram(p) && GL.isShader(sh) && GL.getAttachedShaders(p).has(sh);
+ },
+ cleanup : function(p, sh) {
+ try {GL.deleteProgram(p);} catch(e) {}
+ try {GL.deleteShader(sh);} catch(e) {}
+ }
+ },
+ disable : {
+ generate : function() { return [enableCap.random()]; },
+ checkArgValidity : function(c) { return enableCap.has(c); },
+ cleanup : function(c) { if (c == GL.DITHER) GL.enable(c); }
+ },
+ disableVertexAttribArray : {
+ generate : function() { return [randomVertexAttribute()]; },
+ checkArgValidity : function(v) { return isVertexAttribute(v); }
+ },
+ drawArrays : {}, // FIXME
+ drawElements : {}, // FIXME
+
+// E
+
+ enable : {
+ generate : function() { return [enableCap.random()]; },
+ checkArgValidity : function(c) { return enableCap.has(c); },
+ cleanup : function(c) { if (c != GL.DITHER) GL.disable(c); }
+ },
+ enableVertexAttribArray : {
+ generate : function() { return [randomVertexAttribute()]; },
+ checkArgValidity : function(v) { return isVertexAttribute(castToInt(v)); },
+ cleanup : function(v) { GL.disableVertexAttribArray(v); }
+ },
+
+// F
+
+ finish : {
+ generate : function() { return []; }
+ },
+ flush : {
+ generate : function() { return []; }
+ },
+ framebufferRenderbuffer : {}, // FIXME
+ framebufferTexture2D : {}, // FIXME
+ frontFace : {
+ generate : function() { return [frontFaceMode.random()]; },
+ checkArgValidity : function(c) { return frontFaceMode.has(c); },
+ cleanup : function(c) { GL.frontFace(GL.CCW); }
+ },
+
+// G-1
+
+ generateMipmap : {
+ setup : function() {
+ var tex = GL.createTexture();
+ var tex2 = GL.createTexture();
+ GL.bindTexture(GL.TEXTURE_2D, tex);
+ GL.bindTexture(GL.TEXTURE_CUBE_MAP, tex2);
+ var pix = new Uint8Array(16*16*4);
+ GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ GL.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ GL.texImage2D(GL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ GL.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ GL.texImage2D(GL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ GL.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ GL.texImage2D(GL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+ },
+ generate : function() { return [bindTextureTarget.random()]; },
+ checkArgValidity : function(t) { return bindTextureTarget.has(t); },
+ teardown : function(tex, tex2) {
+ GL.bindTexture(GL.TEXTURE_2D, null);
+ GL.bindTexture(GL.TEXTURE_CUBE_MAP, null);
+ GL.deleteTexture(tex);
+ GL.deleteTexture(tex2);
+ }
+ },
+ getActiveAttrib : {
+ /* FIXME the queried attrib needs to be an active one
+ generate : function() {
+ var program = GL.createProgram();
+ return [program, randomVertexAttribute()];
+ },
+ checkArgValidity : function(program, index) {
+ return GL.isProgram(program) && isVertexAttribute(index);
+ },
+ cleanup : function(program, index) {
+ GL.deleteProgram(program);
+ }
+ */
+ },
+ getActiveUniform : {}, // FIXME
+ getAttachedShaders : {
+ setup : function() {
+ var program = GL.createProgram();
+ var s1 = GL.createShader(GL.VERTEX_SHADER);
+ var s2 = GL.createShader(GL.FRAGMENT_SHADER);
+ GL.attachShader(program, s1);
+ GL.attachShader(program, s2);
+ return [program, s1, s2];
+ },
+ generate : function(program, s1, s2) {
+ return [program]
+ },
+ checkArgValidity : function(program) {
+ return GL.isProgram(program);
+ },
+ teardown : function(program, s1, s2) {
+ GL.deleteProgram(program);
+ GL.deleteShader(s1);
+ GL.deleteShader(s2);
+ }
+ }
+
+};
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-G_I.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-G_I.js
new file mode 100644
index 0000000000..6aa2474241
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-G_I.js
@@ -0,0 +1,124 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// G-2
+
+ getAttribLocation : {
+ generate : function() {
+ var program = GL.createProgram();
+ var name = randomName();
+ GL.bindAttribLocation(program, randomVertexAttribute(), name);
+ return [program, name];
+ },
+ checkArgValidity : function(program, name) {
+ return GL.isProgram(program) && isValidName(name);
+ },
+ cleanup : function(program, name) {
+ try { GL.deleteProgram(program); } catch(e) {}
+ }
+ },/*
+ getParameter : {
+ generate : function() { return [getParameterPname.random()]; },
+ checkArgValidity : function(p) { return getParameterPname.has(p); }
+ },
+ getBufferParameter : {}, // FIXME
+ getError : {
+ generate : function() { return []; }
+ },
+ getFramebufferAttachmentParameter : {}, // FIXME
+ getProgramParameter : {}, // FIXME
+ getProgramInfoLog : {}, // FIXME
+ getRenderbufferParameter : {}, // FIXME
+ getShaderParameter : {}, // FIXME
+ getShaderInfoLog : {}, // FIXME
+ getShaderSource : {}, // FIXME
+ getTexParameter : {}, // FIXME
+ getUniform : {}, // FIXME
+ getUniformLocation : {}, // FIXME
+ getVertexAttrib : {}, // FIXME
+ getVertexAttribOffset : {}, // FIXME
+
+// H
+
+ hint : {
+ generate : function() { return [GL.GENERATE_MIPMAP_HINT, mipmapHint.random()]; },
+ checkValidArgs : function(h, m) {
+ return h == GL.GENERATE_MIPMAP_HINT && mipmapHint.has(m);
+ },
+ teardown : function(){ GL.hint(GL.GENERATE_MIPMAP_HINT, GL.DONT_CARE); }
+ },
+
+// I
+
+ isBuffer : {
+ generate : function() { return [GL.createBuffer()]; },
+ cleanup : function(o) { try { GL.deleteBuffer(o); } catch(e) {} }
+ },
+ isEnabled : {
+ generate : function() { return [enableCap.random()]; },
+ checkArgValidity : function(c) { return enableCap.has(c); }
+ },
+ isFramebuffer : {
+ generate : function() { return [GL.createFramebuffer()]; },
+ cleanup : function(o) { try { GL.deleteFramebuffer(o); } catch(e) {} }
+ },
+ isProgram : {
+ generate : function() { return [GL.createProgram()]; },
+ cleanup : function(o) { try { GL.deleteProgram(o); } catch(e) {} }
+ },
+ isRenderbuffer : {
+ generate : function() { return [GL.createRenderbuffer()]; },
+ cleanup : function(o) { try { GL.deleteRenderbuffer(o); } catch(e) {} }
+ },
+ isShader : {
+ generate : function() { return [GL.createShader(shaderType.random())]; },
+ cleanup : function(o) { try { GL.deleteShader(o); } catch(e) {} }
+ },
+ isTexture : {
+ generate : function() { return [GL.createTexture()]; },
+ cleanup : function(o) { try { GL.deleteTexture(o); } catch(e) {} }
+ }*/
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-L_S.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-L_S.js
new file mode 100644
index 0000000000..d3cdb3e67a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-L_S.js
@@ -0,0 +1,122 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// L
+
+ lineWidth : {
+ generate : function() { return [randomLineWidth()]; },
+ teardown : function() { GL.lineWidth(1); }
+ },
+ linkProgram : {}, // FIXME
+
+// P
+ pixelStorei : {
+ generate : function() {
+ return [pixelStoreiPname.random(), pixelStoreiParam.random()];
+ },
+ checkArgValidity : function(pname, param) {
+ return pixelStoreiPname.has(pname) && pixelStoreiParam.has(param);
+ },
+ teardown : function() {
+ GL.pixelStorei(GL.PACK_ALIGNMENT, 4);
+ GL.pixelStorei(GL.UNPACK_ALIGNMENT, 4);
+ }
+ },
+ polygonOffset : {
+ generate : function() { return [randomFloat(), randomFloat()]; },
+ teardown : function() { GL.polygonOffset(0,0); }
+ },
+
+// R
+
+ readPixels : {}, // FIXME
+ renderbufferStorage : {}, // FIXME
+
+// S-1
+
+ sampleCoverage : {
+ generate : function() { return [randomFloatFromRange(0,1), randomBool()] },
+ teardown : function() { GL.sampleCoverage(1, false); }
+ },
+ scissor : {
+ generate : function() {
+ return [randomInt(3000)-1500, randomInt(3000)-1500, randomIntFromRange(0,3000), randomIntFromRange(0,3000)];
+ },
+ checkArgValidity : function(x,y,w,h) {
+ return castToInt(w) >= 0 && castToInt(h) >= 0;
+ },
+ teardown : function() {
+ GL.scissor(0,0,GL.canvas.width, GL.canvas.height);
+ }
+ },
+ shaderSource : {}, // FIXME
+ stencilFunc : {
+ generate : function(){
+ return [stencilFuncFunc.random(), randomInt(MaxStencilValue), randomInt(0xffffffff)];
+ },
+ checkArgValidity : function(func, ref, mask) {
+ return stencilFuncFunc.has(func) && castToInt(ref) >= 0 && castToInt(ref) < MaxStencilValue;
+ },
+ teardown : function() {
+ GL.stencilFunc(GL.ALWAYS, 0, 0xffffffff);
+ }
+ },
+ stencilFuncSeparate : {
+ generate : function(){
+ return [cullFace.random(), stencilFuncFunc.random(), randomInt(MaxStencilValue), randomInt(0xffffffff)];
+ },
+ checkArgValidity : function(face, func, ref, mask) {
+ return cullFace.has(face) && stencilFuncFunc.has(func) && castToInt(ref) >= 0 && castToInt(ref) < MaxStencilValue;
+ },
+ teardown : function() {
+ GL.stencilFunc(GL.ALWAYS, 0, 0xffffffff);
+ }
+ },
+ stencilMask : {
+ generate : function() { return [randomInt(0xffffffff)]; },
+ teardown : function() { GL.stencilMask(0xffffffff); }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-S_V.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-S_V.js
new file mode 100644
index 0000000000..d08310001c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/argGenerators-S_V.js
@@ -0,0 +1,212 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+// - setup -- set up state for testing the GL function, returns values
+// that need cleanup in teardown. Run once before entering a
+// test loop.
+// - teardown -- do cleanup on setup's return values after testing is complete
+// - generate -- generate a valid set of random arguments for the GL function
+// - returnValueCleanup -- do cleanup on value returned by the tested GL function
+// - cleanup -- do cleanup on generated arguments from generate
+// - checkArgValidity -- check if passed args are valid. Has a call signature
+// that matches generate's return value. Returns true
+// if args are valid, false if not.
+//
+// Example test loop that demonstrates how the function args and return
+// values flow together:
+//
+// var setupArgs = argGen.setup();
+// for (var i=0; i<numberOfTests; i++) {
+// var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+// var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+// var rv = call the GL function with generatedArgs;
+// argGen.returnValueCleanup(rv);
+// argGen.cleanup.apply(argGen, generatedArgs);
+// }
+// argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// S-2
+
+ stencilMaskSeparate : {
+ generate : function() { return [cullFace.random(), randomInt(0xffffffff)]; },
+ checkArgValidity : function(face, mask) {
+ return cullFace.has(face);
+ },
+ teardown : function() { GL.stencilMask(0xffffffff); }
+ },
+ stencilOp : {
+ generate : function() {
+ return [stencilOp.random(), stencilOp.random(), stencilOp.random()];
+ },
+ checkArgValidity : function(sfail, dpfail, dppass) {
+ return stencilOp.has(sfail) && stencilOp.has(dpfail) && stencilOp.has(dppass);
+ },
+ teardown : function() { GL.stencilOp(GL.KEEP, GL.KEEP, GL.KEEP); }
+ },
+ stencilOpSeparate : {
+ generate : function() {
+ return [cullFace.random(), stencilOp.random(), stencilOp.random(), stencilOp.random()];
+ },
+ checkArgValidity : function(face, sfail, dpfail, dppass) {
+ return cullFace.has(face) && stencilOp.has(sfail) &&
+ stencilOp.has(dpfail) && stencilOp.has(dppass);
+ },
+ teardown : function() { GL.stencilOp(GL.KEEP, GL.KEEP, GL.KEEP); }
+ },
+
+// T
+ texImage2D : {
+ noAlreadyTriedCheck : true, // Object.toSource is very slow here
+ setup : function() {
+ var tex = GL.createTexture();
+ var tex2 = GL.createTexture();
+ GL.bindTexture(GL.TEXTURE_2D, tex);
+ GL.bindTexture(GL.TEXTURE_CUBE_MAP, tex2);
+ return [tex, tex2];
+ },
+ generate : function() {
+ var format = texImageFormat.random();
+ if (Math.random() < 0.5) {
+ var img = randomImage(16,16);
+ var a = [ texImageTarget.random(), 0, format, format, GL.UNSIGNED_BYTE, img ];
+ return a;
+ } else {
+ var pix = null;
+ if (Math.random > 0.5) {
+ pix = new Uint8Array(16*16*4);
+ }
+ return [
+ texImageTarget.random(), 0,
+ format, 16, 16, 0,
+ format, GL.UNSIGNED_BYTE, pix
+ ];
+ }
+ },
+ checkArgValidity : function(target, level, internalformat, width, height, border, format, type, data) {
+ // or : function(target, level, internalformat, format, type, image)
+ if (!texImageTarget.has(target) || castToInt(level) < 0)
+ return false;
+ if (arguments.length <= 6) {
+ var xformat = width;
+ var xtype = height;
+ var ximage = border;
+ if ((ximage instanceof HTMLImageElement ||
+ ximage instanceof HTMLVideoElement ||
+ ximage instanceof HTMLCanvasElement ||
+ ximage instanceof ImageData) &&
+ texImageInternalFormat.has(internalformat) &&
+ texImageFormat.has(xformat) &&
+ texImageType.has(xtype) &&
+ internalformat == xformat)
+ return true;
+ return false;
+ }
+ var w = castToInt(width), h = castToInt(height), b = castToInt(border);
+ return texImageInternalFormat.has(internalformat) && w >= 0 && h >= 0 &&
+ b == 0 && (data == null || data.byteLength == w*h*4) &&
+ texImageFormat.has(format) && texImageType.has(type)
+ && internalformat == format;
+ },
+ teardown : function(tex, tex2) {
+ GL.bindTexture(GL.TEXTURE_2D, null);
+ GL.bindTexture(GL.TEXTURE_CUBE_MAP, null);
+ GL.deleteTexture(tex);
+ GL.deleteTexture(tex2);
+ }
+ },
+ texParameterf : {
+ generate : function() {
+ var pname = texParameterPname.random();
+ var param = texParameterParam[pname].random();
+ return [bindTextureTarget.random(), pname, param];
+ },
+ checkArgValidity : function(target, pname, param) {
+ if (!bindTextureTarget.has(target))
+ return false;
+ if (!texParameterPname.has(pname))
+ return false;
+ return texParameterParam[pname].has(param);
+ }
+ },
+ texParameteri : {
+ generate : function() {
+ var pname = texParameterPname.random();
+ var param = texParameterParam[pname].random();
+ return [bindTextureTarget.random(), pname, param];
+ },
+ checkArgValidity : function(target, pname, param) {
+ if (!bindTextureTarget.has(target))
+ return false;
+ if (!texParameterPname.has(pname))
+ return false;
+ return texParameterParam[pname].has(param);
+ }
+ },
+ texSubImage2D : {}, // FIXME
+
+// U
+
+ uniform1f : {}, // FIXME
+ uniform1fv : {}, // FIXME
+ uniform1i : {}, // FIXME
+ uniform1iv : {}, // FIXME
+ uniform2f : {}, // FIXME
+ uniform2fv : {}, // FIXME
+ uniform2i : {}, // FIXME
+ uniform2iv : {}, // FIXME
+ uniform3f : {}, // FIXME
+ uniform3fv : {}, // FIXME
+ uniform3i : {}, // FIXME
+ uniform3iv : {}, // FIXME
+ uniform4f : {}, // FIXME
+ uniform4fv : {}, // FIXME
+ uniform4i : {}, // FIXME
+ uniform4iv : {}, // FIXME
+ uniformMatrix2fv : {}, // FIXME
+ uniformMatrix3fv : {}, // FIXME
+ uniformMatrix4fv : {}, // FIXME
+ useProgram : {}, // FIXME
+
+// V
+
+ validateProgram : {}, // FIXME
+ vertexAttrib1f : {}, // FIXME
+ vertexAttrib1fv : {}, // FIXME
+ vertexAttrib2f : {}, // FIXME
+ vertexAttrib2fv : {}, // FIXME
+ vertexAttrib3f : {}, // FIXME
+ vertexAttrib3fv : {}, // FIXME
+ vertexAttrib4f : {}, // FIXME
+ vertexAttrib4fv : {}, // FIXME
+ vertexAttribPointer : {}, // FIXME
+ viewport : {
+ generate : function() {
+ return [randomInt(3000)-1500, randomInt(3000)-1500, randomIntFromRange(0,3000), randomIntFromRange(0,3000)];
+ },
+ checkArgValidity : function(x,y,w,h) {
+ return castToInt(w) >= 0 && castToInt(h) >= 0;
+ },
+ teardown : function() {
+ GL.viewport(0,0,GL.canvas.width, GL.canvas.height);
+ }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/badArgsArityLessThanArgc.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/badArgsArityLessThanArgc.html
new file mode 100644
index 0000000000..5ee9727a6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/badArgsArityLessThanArgc.html
@@ -0,0 +1,576 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+/*
+ The following tests are generated from
+ http://www.khronos.org/registry/gles/api/2.0/gl2.h
+ and api_modifications.txt
+*/
+Tests.test_activeTexture = function(gl) {
+ assertFail(function(){ gl.activeTexture(); });
+}
+Tests.test_attachShader = function(gl) {
+ assertFail(function(){ gl.attachShader(); });
+ assertFail(function(){ gl.attachShader(0); });
+}
+Tests.test_bindAttribLocation = function(gl) {
+ assertFail(function(){ gl.bindAttribLocation(); });
+ assertFail(function(){ gl.bindAttribLocation(0); });
+ assertFail(function(){ gl.bindAttribLocation(0,0); });
+}
+Tests.test_bindBuffer = function(gl) {
+ assertFail(function(){ gl.bindBuffer(); });
+ assertFail(function(){ gl.bindBuffer(0); });
+}
+Tests.test_bindFramebuffer = function(gl) {
+ assertFail(function(){ gl.bindFramebuffer(); });
+ assertFail(function(){ gl.bindFramebuffer(0); });
+}
+Tests.test_bindRenderbuffer = function(gl) {
+ assertFail(function(){ gl.bindRenderbuffer(); });
+ assertFail(function(){ gl.bindRenderbuffer(0); });
+}
+Tests.test_bindTexture = function(gl) {
+ assertFail(function(){ gl.bindTexture(); });
+ assertFail(function(){ gl.bindTexture(0); });
+}
+Tests.test_blendColor = function(gl) {
+ assertFail(function(){ gl.blendColor(); });
+ assertFail(function(){ gl.blendColor(0); });
+ assertFail(function(){ gl.blendColor(0,0); });
+ assertFail(function(){ gl.blendColor(0,0,0); });
+}
+Tests.test_blendEquation = function(gl) {
+ assertFail(function(){ gl.blendEquation(); });
+}
+Tests.test_blendEquationSeparate = function(gl) {
+ assertFail(function(){ gl.blendEquationSeparate(); });
+ assertFail(function(){ gl.blendEquationSeparate(0); });
+}
+Tests.test_blendFunc = function(gl) {
+ assertFail(function(){ gl.blendFunc(); });
+ assertFail(function(){ gl.blendFunc(0); });
+}
+Tests.test_blendFuncSeparate = function(gl) {
+ assertFail(function(){ gl.blendFuncSeparate(); });
+ assertFail(function(){ gl.blendFuncSeparate(0); });
+ assertFail(function(){ gl.blendFuncSeparate(0,0); });
+ assertFail(function(){ gl.blendFuncSeparate(0,0,0); });
+}
+Tests.test_bufferData = function(gl) {
+ assertFail(function(){ gl.bufferData(); });
+ assertFail(function(){ gl.bufferData(0); });
+ assertFail(function(){ gl.bufferData(0,0); });
+}
+Tests.test_bufferSubData = function(gl) {
+ assertFail(function(){ gl.bufferSubData(); });
+ assertFail(function(){ gl.bufferSubData(0); });
+ assertFail(function(){ gl.bufferSubData(0,0); });
+}
+Tests.test_checkFramebufferStatus = function(gl) {
+ assertFail(function(){ gl.checkFramebufferStatus(); });
+}
+Tests.test_clear = function(gl) {
+ assertFail(function(){ gl.clear(); });
+}
+Tests.test_clearColor = function(gl) {
+ assertFail(function(){ gl.clearColor(); });
+ assertFail(function(){ gl.clearColor(0); });
+ assertFail(function(){ gl.clearColor(0,0); });
+ assertFail(function(){ gl.clearColor(0,0,0); });
+}
+Tests.test_clearDepth = function(gl) {
+ assertFail(function(){ gl.clearDepth(); });
+}
+Tests.test_clearStencil = function(gl) {
+ assertFail(function(){ gl.clearStencil(); });
+}
+Tests.test_colorMask = function(gl) {
+ assertFail(function(){ gl.colorMask(); });
+ assertFail(function(){ gl.colorMask(0); });
+ assertFail(function(){ gl.colorMask(0,0); });
+ assertFail(function(){ gl.colorMask(0,0,0); });
+}
+Tests.test_compileShader = function(gl) {
+ assertFail(function(){ gl.compileShader(); });
+}
+Tests.test_copyTexImage2D = function(gl) {
+ assertFail(function(){ gl.copyTexImage2D(); });
+ assertFail(function(){ gl.copyTexImage2D(0); });
+ assertFail(function(){ gl.copyTexImage2D(0,0); });
+ assertFail(function(){ gl.copyTexImage2D(0,0,0); });
+ assertFail(function(){ gl.copyTexImage2D(0,0,0,0); });
+ assertFail(function(){ gl.copyTexImage2D(0,0,0,0,0); });
+ assertFail(function(){ gl.copyTexImage2D(0,0,0,0,0,0); });
+ assertFail(function(){ gl.copyTexImage2D(0,0,0,0,0,0,0); });
+}
+Tests.test_copyTexSubImage2D = function(gl) {
+ assertFail(function(){ gl.copyTexSubImage2D(); });
+ assertFail(function(){ gl.copyTexSubImage2D(0); });
+ assertFail(function(){ gl.copyTexSubImage2D(0,0); });
+ assertFail(function(){ gl.copyTexSubImage2D(0,0,0); });
+ assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0); });
+ assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0,0); });
+ assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0,0,0); });
+ assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0,0,0,0); });
+}
+Tests.test_createProgram = function(gl) {
+}
+Tests.test_createShader = function(gl) {
+ assertFail(function(){ gl.createShader(); });
+}
+Tests.test_cullFace = function(gl) {
+ assertFail(function(){ gl.cullFace(); });
+}
+Tests.test_deleteBuffer = function(gl) {
+ assertFail(function(){ gl.deleteBuffer(); });
+}
+Tests.test_deleteFramebuffer = function(gl) {
+ assertFail(function(){ gl.deleteFramebuffer(); });
+}
+Tests.test_deleteProgram = function(gl) {
+ assertFail(function(){ gl.deleteProgram(); });
+}
+Tests.test_deleteRenderbuffer = function(gl) {
+ assertFail(function(){ gl.deleteRenderbuffer(); });
+}
+Tests.test_deleteShader = function(gl) {
+ assertFail(function(){ gl.deleteShader(); });
+}
+Tests.test_deleteTexture = function(gl) {
+ assertFail(function(){ gl.deleteTexture(); });
+}
+Tests.test_depthFunc = function(gl) {
+ assertFail(function(){ gl.depthFunc(); });
+}
+Tests.test_depthMask = function(gl) {
+ assertFail(function(){ gl.depthMask(); });
+}
+Tests.test_depthRange = function(gl) {
+ assertFail(function(){ gl.depthRange(); });
+ assertFail(function(){ gl.depthRange(0); });
+}
+Tests.test_detachShader = function(gl) {
+ assertFail(function(){ gl.detachShader(); });
+ assertFail(function(){ gl.detachShader(0); });
+}
+Tests.test_disable = function(gl) {
+ assertFail(function(){ gl.disable(); });
+}
+Tests.test_disableVertexAttribArray = function(gl) {
+ assertFail(function(){ gl.disableVertexAttribArray(); });
+}
+Tests.test_drawArrays = function(gl) {
+ assertFail(function(){ gl.drawArrays(); });
+ assertFail(function(){ gl.drawArrays(0); });
+ assertFail(function(){ gl.drawArrays(0,0); });
+}
+Tests.test_drawElements = function(gl) {
+ assertFail(function(){ gl.drawElements(); });
+ assertFail(function(){ gl.drawElements(0); });
+ assertFail(function(){ gl.drawElements(0,0); });
+ assertFail(function(){ gl.drawElements(0,0,0); });
+}
+Tests.test_enable = function(gl) {
+ assertFail(function(){ gl.enable(); });
+}
+Tests.test_enableVertexAttribArray = function(gl) {
+ assertFail(function(){ gl.enableVertexAttribArray(); });
+}
+Tests.test_finish = function(gl) {
+}
+Tests.test_flush = function(gl) {
+}
+Tests.test_framebufferRenderbuffer = function(gl) {
+ assertFail(function(){ gl.framebufferRenderbuffer(); });
+ assertFail(function(){ gl.framebufferRenderbuffer(0); });
+ assertFail(function(){ gl.framebufferRenderbuffer(0,0); });
+ assertFail(function(){ gl.framebufferRenderbuffer(0,0,0); });
+}
+Tests.test_framebufferTexture2D = function(gl) {
+ assertFail(function(){ gl.framebufferTexture2D(); });
+ assertFail(function(){ gl.framebufferTexture2D(0); });
+ assertFail(function(){ gl.framebufferTexture2D(0,0); });
+ assertFail(function(){ gl.framebufferTexture2D(0,0,0); });
+ assertFail(function(){ gl.framebufferTexture2D(0,0,0,0); });
+}
+Tests.test_frontFace = function(gl) {
+ assertFail(function(){ gl.frontFace(); });
+}
+Tests.test_createBuffer = function(gl) {
+}
+Tests.test_generateMipmap = function(gl) {
+ assertFail(function(){ gl.generateMipmap(); });
+}
+Tests.test_createFramebuffer = function(gl) {
+}
+Tests.test_createRenderbuffer = function(gl) {
+}
+Tests.test_createTexture = function(gl) {
+}
+Tests.test_getActiveAttrib = function(gl) {
+ assertFail(function(){ gl.getActiveAttrib(); });
+ assertFail(function(){ gl.getActiveAttrib(0); });
+}
+Tests.test_getActiveUniform = function(gl) {
+ assertFail(function(){ gl.getActiveUniform(); });
+ assertFail(function(){ gl.getActiveUniform(0); });
+}
+Tests.test_getAttachedShaders = function(gl) {
+ assertFail(function(){ gl.getAttachedShaders(); });
+}
+Tests.test_getAttribLocation = function(gl) {
+ assertFail(function(){ gl.getAttribLocation(); });
+ assertFail(function(){ gl.getAttribLocation(0); });
+}
+Tests.test_getBufferParameteri = function(gl) {
+ assertFail(function(){ gl.getBufferParameteri(); });
+ assertFail(function(){ gl.getBufferParameteri(0); });
+}
+Tests.test_getError = function(gl) {
+}
+Tests.test_getFramebufferAttachmentParameteri = function(gl) {
+ assertFail(function(){ gl.getFramebufferAttachmentParameteri(); });
+ assertFail(function(){ gl.getFramebufferAttachmentParameteri(0); });
+ assertFail(function(){ gl.getFramebufferAttachmentParameteri(0,0); });
+}
+Tests.test_getProgramInfoLog = function(gl) {
+ assertFail(function(){ gl.getProgramInfoLog(); });
+}
+Tests.test_getRenderbufferParameteri = function(gl) {
+ assertFail(function(){ gl.getRenderbufferParameteri(); });
+ assertFail(function(){ gl.getRenderbufferParameteri(0); });
+}
+Tests.test_getShaderInfoLog = function(gl) {
+ assertFail(function(){ gl.getShaderInfoLog(); });
+}
+Tests.test_getShaderSource = function(gl) {
+ assertFail(function(){ gl.getShaderSource(); });
+}
+Tests.test_getUniformLocation = function(gl) {
+ assertFail(function(){ gl.getUniformLocation(); });
+ assertFail(function(){ gl.getUniformLocation(0); });
+}
+Tests.test_hint = function(gl) {
+ assertFail(function(){ gl.hint(); });
+ assertFail(function(){ gl.hint(0); });
+}
+Tests.test_isBuffer = function(gl) {
+ assertFail(function(){ gl.isBuffer(); });
+}
+Tests.test_isEnabled = function(gl) {
+ assertFail(function(){ gl.isEnabled(); });
+}
+Tests.test_isFramebuffer = function(gl) {
+ assertFail(function(){ gl.isFramebuffer(); });
+}
+Tests.test_isProgram = function(gl) {
+ assertFail(function(){ gl.isProgram(); });
+}
+Tests.test_isRenderbuffer = function(gl) {
+ assertFail(function(){ gl.isRenderbuffer(); });
+}
+Tests.test_isShader = function(gl) {
+ assertFail(function(){ gl.isShader(); });
+}
+Tests.test_isTexture = function(gl) {
+ assertFail(function(){ gl.isTexture(); });
+}
+Tests.test_lineWidth = function(gl) {
+ assertFail(function(){ gl.lineWidth(); });
+}
+Tests.test_linkProgram = function(gl) {
+ assertFail(function(){ gl.linkProgram(); });
+}
+Tests.test_polygonOffset = function(gl) {
+ assertFail(function(){ gl.polygonOffset(); });
+ assertFail(function(){ gl.polygonOffset(0); });
+}
+Tests.test_readPixels = function(gl) {
+ assertFail(function(){ gl.readPixels(); });
+ assertFail(function(){ gl.readPixels(0); });
+ assertFail(function(){ gl.readPixels(0,0); });
+ assertFail(function(){ gl.readPixels(0,0,0); });
+ assertFail(function(){ gl.readPixels(0,0,0,0); });
+ assertFail(function(){ gl.readPixels(0,0,0,0,0); });
+}
+Tests.test_renderbufferStorage = function(gl) {
+ assertFail(function(){ gl.renderbufferStorage(); });
+ assertFail(function(){ gl.renderbufferStorage(0); });
+ assertFail(function(){ gl.renderbufferStorage(0,0); });
+ assertFail(function(){ gl.renderbufferStorage(0,0,0); });
+}
+Tests.test_sampleCoverage = function(gl) {
+ assertFail(function(){ gl.sampleCoverage(); });
+ assertFail(function(){ gl.sampleCoverage(0); });
+}
+Tests.test_scissor = function(gl) {
+ assertFail(function(){ gl.scissor(); });
+ assertFail(function(){ gl.scissor(0); });
+ assertFail(function(){ gl.scissor(0,0); });
+ assertFail(function(){ gl.scissor(0,0,0); });
+}
+Tests.test_shaderSource = function(gl) {
+ assertFail(function(){ gl.shaderSource(); });
+ assertFail(function(){ gl.shaderSource(0); });
+}
+Tests.test_stencilFunc = function(gl) {
+ assertFail(function(){ gl.stencilFunc(); });
+ assertFail(function(){ gl.stencilFunc(0); });
+ assertFail(function(){ gl.stencilFunc(0,0); });
+}
+Tests.test_stencilFuncSeparate = function(gl) {
+ assertFail(function(){ gl.stencilFuncSeparate(); });
+ assertFail(function(){ gl.stencilFuncSeparate(0); });
+ assertFail(function(){ gl.stencilFuncSeparate(0,0); });
+ assertFail(function(){ gl.stencilFuncSeparate(0,0,0); });
+}
+Tests.test_stencilMask = function(gl) {
+ assertFail(function(){ gl.stencilMask(); });
+}
+Tests.test_stencilMaskSeparate = function(gl) {
+ assertFail(function(){ gl.stencilMaskSeparate(); });
+ assertFail(function(){ gl.stencilMaskSeparate(0); });
+}
+Tests.test_stencilOp = function(gl) {
+ assertFail(function(){ gl.stencilOp(); });
+ assertFail(function(){ gl.stencilOp(0); });
+ assertFail(function(){ gl.stencilOp(0,0); });
+}
+Tests.test_stencilOpSeparate = function(gl) {
+ assertFail(function(){ gl.stencilOpSeparate(); });
+ assertFail(function(){ gl.stencilOpSeparate(0); });
+ assertFail(function(){ gl.stencilOpSeparate(0,0); });
+ assertFail(function(){ gl.stencilOpSeparate(0,0,0); });
+}
+Tests.test_texImage2D = function(gl) {
+ assertFail(function(){ gl.texImage2D(); });
+ assertFail(function(){ gl.texImage2D(0); });
+ assertFail(function(){ gl.texImage2D(0,0); });
+}
+Tests.test_texParameteri = function(gl) {
+ assertFail(function(){ gl.texParameteri(); });
+ assertFail(function(){ gl.texParameteri(0); });
+ assertFail(function(){ gl.texParameteri(0,0); });
+}
+Tests.test_texSubImage2D = function(gl) {
+ assertFail(function(){ gl.texSubImage2D(); });
+ assertFail(function(){ gl.texSubImage2D(0); });
+ assertFail(function(){ gl.texSubImage2D(0,0); });
+ assertFail(function(){ gl.texSubImage2D(0,0,0); });
+ assertFail(function(){ gl.texSubImage2D(0,0,0,0); });
+ assertFail(function(){ gl.texSubImage2D(0,0,0,0,0); });
+ assertFail(function(){ gl.texSubImage2D(0,0,0,0,0,0); });
+ assertFail(function(){ gl.texSubImage2D(0,0,0,0,0,0,0); });
+ assertFail(function(){ gl.texSubImage2D(0,0,0,0,0,0,0,0); });
+}
+Tests.test_uniform1f = function(gl) {
+ assertFail(function(){ gl.uniform1f(); });
+ assertFail(function(){ gl.uniform1f(0); });
+}
+Tests.test_uniform1fv = function(gl) {
+ assertFail(function(){ gl.uniform1fv(); });
+ assertFail(function(){ gl.uniform1fv(0); });
+}
+Tests.test_uniform1i = function(gl) {
+ assertFail(function(){ gl.uniform1i(); });
+ assertFail(function(){ gl.uniform1i(0); });
+}
+Tests.test_uniform1iv = function(gl) {
+ assertFail(function(){ gl.uniform1iv(); });
+ assertFail(function(){ gl.uniform1iv(0); });
+}
+Tests.test_uniform2f = function(gl) {
+ assertFail(function(){ gl.uniform2f(); });
+ assertFail(function(){ gl.uniform2f(0); });
+ assertFail(function(){ gl.uniform2f(0,0); });
+}
+Tests.test_uniform2fv = function(gl) {
+ assertFail(function(){ gl.uniform2fv(); });
+ assertFail(function(){ gl.uniform2fv(0); });
+}
+Tests.test_uniform2i = function(gl) {
+ assertFail(function(){ gl.uniform2i(); });
+ assertFail(function(){ gl.uniform2i(0); });
+ assertFail(function(){ gl.uniform2i(0,0); });
+}
+Tests.test_uniform2iv = function(gl) {
+ assertFail(function(){ gl.uniform2iv(); });
+ assertFail(function(){ gl.uniform2iv(0); });
+}
+Tests.test_uniform3f = function(gl) {
+ assertFail(function(){ gl.uniform3f(); });
+ assertFail(function(){ gl.uniform3f(0); });
+ assertFail(function(){ gl.uniform3f(0,0); });
+ assertFail(function(){ gl.uniform3f(0,0,0); });
+}
+Tests.test_uniform3fv = function(gl) {
+ assertFail(function(){ gl.uniform3fv(); });
+ assertFail(function(){ gl.uniform3fv(0); });
+}
+Tests.test_uniform3i = function(gl) {
+ assertFail(function(){ gl.uniform3i(); });
+ assertFail(function(){ gl.uniform3i(0); });
+ assertFail(function(){ gl.uniform3i(0,0); });
+ assertFail(function(){ gl.uniform3i(0,0,0); });
+}
+Tests.test_uniform3iv = function(gl) {
+ assertFail(function(){ gl.uniform3iv(); });
+ assertFail(function(){ gl.uniform3iv(0); });
+}
+Tests.test_uniform4f = function(gl) {
+ assertFail(function(){ gl.uniform4f(); });
+ assertFail(function(){ gl.uniform4f(0); });
+ assertFail(function(){ gl.uniform4f(0,0); });
+ assertFail(function(){ gl.uniform4f(0,0,0); });
+ assertFail(function(){ gl.uniform4f(0,0,0,0); });
+}
+Tests.test_uniform4fv = function(gl) {
+ assertFail(function(){ gl.uniform4fv(); });
+ assertFail(function(){ gl.uniform4fv(0); });
+}
+Tests.test_uniform4i = function(gl) {
+ assertFail(function(){ gl.uniform4i(); });
+ assertFail(function(){ gl.uniform4i(0); });
+ assertFail(function(){ gl.uniform4i(0,0); });
+ assertFail(function(){ gl.uniform4i(0,0,0); });
+ assertFail(function(){ gl.uniform4i(0,0,0,0); });
+}
+Tests.test_uniform4iv = function(gl) {
+ assertFail(function(){ gl.uniform4iv(); });
+ assertFail(function(){ gl.uniform4iv(0); });
+}
+Tests.test_uniformMatrix2fv = function(gl) {
+ assertFail(function(){ gl.uniformMatrix2fv(); });
+ assertFail(function(){ gl.uniformMatrix2fv(0); });
+ assertFail(function(){ gl.uniformMatrix2fv(0,0); });
+}
+Tests.test_uniformMatrix3fv = function(gl) {
+ assertFail(function(){ gl.uniformMatrix3fv(); });
+ assertFail(function(){ gl.uniformMatrix3fv(0); });
+ assertFail(function(){ gl.uniformMatrix3fv(0,0); });
+}
+Tests.test_uniformMatrix4fv = function(gl) {
+ assertFail(function(){ gl.uniformMatrix4fv(); });
+ assertFail(function(){ gl.uniformMatrix4fv(0); });
+ assertFail(function(){ gl.uniformMatrix4fv(0,0); });
+}
+Tests.test_useProgram = function(gl) {
+ assertFail(function(){ gl.useProgram(); });
+}
+Tests.test_validateProgram = function(gl) {
+ assertFail(function(){ gl.validateProgram(); });
+}
+Tests.test_vertexAttrib1f = function(gl) {
+ assertFail(function(){ gl.vertexAttrib1f(); });
+ assertFail(function(){ gl.vertexAttrib1f(0); });
+}
+Tests.test_vertexAttrib1fv = function(gl) {
+ assertFail(function(){ gl.vertexAttrib1fv(); });
+ assertFail(function(){ gl.vertexAttrib1fv(0); });
+}
+Tests.test_vertexAttrib2f = function(gl) {
+ assertFail(function(){ gl.vertexAttrib2f(); });
+ assertFail(function(){ gl.vertexAttrib2f(0); });
+ assertFail(function(){ gl.vertexAttrib2f(0,0); });
+}
+Tests.test_vertexAttrib2fv = function(gl) {
+ assertFail(function(){ gl.vertexAttrib2fv(); });
+ assertFail(function(){ gl.vertexAttrib2fv(0); });
+}
+Tests.test_vertexAttrib3f = function(gl) {
+ assertFail(function(){ gl.vertexAttrib3f(); });
+ assertFail(function(){ gl.vertexAttrib3f(0); });
+ assertFail(function(){ gl.vertexAttrib3f(0,0); });
+ assertFail(function(){ gl.vertexAttrib3f(0,0,0); });
+}
+Tests.test_vertexAttrib3fv = function(gl) {
+ assertFail(function(){ gl.vertexAttrib3fv(); });
+ assertFail(function(){ gl.vertexAttrib3fv(0); });
+}
+Tests.test_vertexAttrib4f = function(gl) {
+ assertFail(function(){ gl.vertexAttrib4f(); });
+ assertFail(function(){ gl.vertexAttrib4f(0); });
+ assertFail(function(){ gl.vertexAttrib4f(0,0); });
+ assertFail(function(){ gl.vertexAttrib4f(0,0,0); });
+ assertFail(function(){ gl.vertexAttrib4f(0,0,0,0); });
+}
+Tests.test_vertexAttrib4fv = function(gl) {
+ assertFail(function(){ gl.vertexAttrib4fv(); });
+ assertFail(function(){ gl.vertexAttrib4fv(0); });
+}
+Tests.test_vertexAttribPointer = function(gl) {
+ assertFail(function(){ gl.vertexAttribPointer(); });
+ assertFail(function(){ gl.vertexAttribPointer(0); });
+ assertFail(function(){ gl.vertexAttribPointer(0,0); });
+ assertFail(function(){ gl.vertexAttribPointer(0,0,0); });
+ assertFail(function(){ gl.vertexAttribPointer(0,0,0,0); });
+ assertFail(function(){ gl.vertexAttribPointer(0,0,0,0,0); });
+}
+Tests.test_viewport = function(gl) {
+ assertFail(function(){ gl.viewport(); });
+ assertFail(function(){ gl.viewport(0); });
+ assertFail(function(){ gl.viewport(0,0); });
+ assertFail(function(){ gl.viewport(0,0,0); });
+}
+Tests.test_currentArrayBufferBinding = function(gl) {
+}
+Tests.test_currentElementArrayBufferBinding = function(gl) {
+}
+Tests.test_currentFramebufferBinding = function(gl) {
+}
+Tests.test_currentRenderbufferBinding = function(gl) {
+}
+Tests.test_currentTextureBinding2D = function(gl) {
+}
+Tests.test_currentTextureBindingCubeMap = function(gl) {
+}
+Tests.test_currentProgram = function(gl) {
+}
+Tests.test_getParameter = function(gl) {
+ assertFail(function(){ gl.getParameter(); });
+}
+Tests.test_getProgramParameter = function(gl) {
+ assertFail(function(){ gl.getProgramParameter(); });
+ assertFail(function(){ gl.getProgramParameter(0); });
+}
+Tests.test_getShaderParameter = function(gl) {
+ assertFail(function(){ gl.getShaderParameter(); });
+ assertFail(function(){ gl.getShaderParameter(0); });
+}
+Tests.test_getTexParameteri = function(gl) {
+ assertFail(function(){ gl.getTexParameteri(); });
+ assertFail(function(){ gl.getTexParameteri(0); });
+}
+Tests.test_getUniformi = function(gl) {
+ assertFail(function(){ gl.getUniformi(); });
+ assertFail(function(){ gl.getUniformi(0); });
+}
+Tests.test_getVertexAttribi = function(gl) {
+ assertFail(function(){ gl.getVertexAttribi(); });
+ assertFail(function(){ gl.getVertexAttribi(0); });
+}
+Tests.test_present = function(gl) {
+}
+Tests.startUnit = function() {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/constants.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/constants.html
new file mode 100644
index 0000000000..61997afae6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/constants.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+/*
+ The following tests are generated from
+ http://www.khronos.org/registry/gles/api/2.0/gl2.h
+ and api_modifications.txt
+*/
+var constants = {
+DEPTH_BUFFER_BIT : 0x00000100,
+STENCIL_BUFFER_BIT : 0x00000400,
+COLOR_BUFFER_BIT : 0x00004000,
+POINTS : 0x0000,
+LINES : 0x0001,
+LINE_LOOP : 0x0002,
+LINE_STRIP : 0x0003,
+TRIANGLES : 0x0004,
+TRIANGLE_STRIP : 0x0005,
+TRIANGLE_FAN : 0x0006,
+ZERO : 0,
+ONE : 1,
+SRC_COLOR : 0x0300,
+ONE_MINUS_SRC_COLOR : 0x0301,
+SRC_ALPHA : 0x0302,
+ONE_MINUS_SRC_ALPHA : 0x0303,
+DST_ALPHA : 0x0304,
+ONE_MINUS_DST_ALPHA : 0x0305,
+DST_COLOR : 0x0306,
+ONE_MINUS_DST_COLOR : 0x0307,
+SRC_ALPHA_SATURATE : 0x0308,
+FUNC_ADD : 0x8006,
+BLEND_EQUATION : 0x8009,
+BLEND_EQUATION_RGB : 0x8009,
+BLEND_EQUATION_ALPHA : 0x883D,
+FUNC_SUBTRACT : 0x800A,
+FUNC_REVERSE_SUBTRACT : 0x800B,
+BLEND_DST_RGB : 0x80C8,
+BLEND_SRC_RGB : 0x80C9,
+BLEND_DST_ALPHA : 0x80CA,
+BLEND_SRC_ALPHA : 0x80CB,
+CONSTANT_COLOR : 0x8001,
+ONE_MINUS_CONSTANT_COLOR : 0x8002,
+CONSTANT_ALPHA : 0x8003,
+ONE_MINUS_CONSTANT_ALPHA : 0x8004,
+BLEND_COLOR : 0x8005,
+ARRAY_BUFFER : 0x8892,
+ELEMENT_ARRAY_BUFFER : 0x8893,
+ARRAY_BUFFER_BINDING : 0x8894,
+ELEMENT_ARRAY_BUFFER_BINDING : 0x8895,
+STREAM_DRAW : 0x88E0,
+STATIC_DRAW : 0x88E4,
+DYNAMIC_DRAW : 0x88E8,
+BUFFER_SIZE : 0x8764,
+BUFFER_USAGE : 0x8765,
+CURRENT_VERTEX_ATTRIB : 0x8626,
+FRONT : 0x0404,
+BACK : 0x0405,
+FRONT_AND_BACK : 0x0408,
+TEXTURE_2D : 0x0DE1,
+CULL_FACE : 0x0B44,
+BLEND : 0x0BE2,
+DITHER : 0x0BD0,
+STENCIL_TEST : 0x0B90,
+DEPTH_TEST : 0x0B71,
+SCISSOR_TEST : 0x0C11,
+POLYGON_OFFSET_FILL : 0x8037,
+SAMPLE_ALPHA_TO_COVERAGE : 0x809E,
+SAMPLE_COVERAGE : 0x80A0,
+NO_ERROR : 0,
+INVALID_ENUM : 0x0500,
+INVALID_VALUE : 0x0501,
+INVALID_OPERATION : 0x0502,
+OUT_OF_MEMORY : 0x0505,
+CW : 0x0900,
+CCW : 0x0901,
+LINE_WIDTH : 0x0B21,
+ALIASED_POINT_SIZE_RANGE : 0x846D,
+ALIASED_LINE_WIDTH_RANGE : 0x846E,
+CULL_FACE_MODE : 0x0B45,
+FRONT_FACE : 0x0B46,
+DEPTH_RANGE : 0x0B70,
+DEPTH_WRITEMASK : 0x0B72,
+DEPTH_CLEAR_VALUE : 0x0B73,
+DEPTH_FUNC : 0x0B74,
+STENCIL_CLEAR_VALUE : 0x0B91,
+STENCIL_FUNC : 0x0B92,
+STENCIL_FAIL : 0x0B94,
+STENCIL_PASS_DEPTH_FAIL : 0x0B95,
+STENCIL_PASS_DEPTH_PASS : 0x0B96,
+STENCIL_REF : 0x0B97,
+STENCIL_VALUE_MASK : 0x0B93,
+STENCIL_WRITEMASK : 0x0B98,
+STENCIL_BACK_FUNC : 0x8800,
+STENCIL_BACK_FAIL : 0x8801,
+STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802,
+STENCIL_BACK_PASS_DEPTH_PASS : 0x8803,
+STENCIL_BACK_REF : 0x8CA3,
+STENCIL_BACK_VALUE_MASK : 0x8CA4,
+STENCIL_BACK_WRITEMASK : 0x8CA5,
+VIEWPORT : 0x0BA2,
+SCISSOR_BOX : 0x0C10,
+COLOR_CLEAR_VALUE : 0x0C22,
+COLOR_WRITEMASK : 0x0C23,
+UNPACK_ALIGNMENT : 0x0CF5,
+PACK_ALIGNMENT : 0x0D05,
+MAX_TEXTURE_SIZE : 0x0D33,
+MAX_VIEWPORT_DIMS : 0x0D3A,
+SUBPIXEL_BITS : 0x0D50,
+RED_BITS : 0x0D52,
+GREEN_BITS : 0x0D53,
+BLUE_BITS : 0x0D54,
+ALPHA_BITS : 0x0D55,
+DEPTH_BITS : 0x0D56,
+STENCIL_BITS : 0x0D57,
+POLYGON_OFFSET_UNITS : 0x2A00,
+POLYGON_OFFSET_FACTOR : 0x8038,
+TEXTURE_BINDING_2D : 0x8069,
+SAMPLE_BUFFERS : 0x80A8,
+SAMPLES : 0x80A9,
+SAMPLE_COVERAGE_VALUE : 0x80AA,
+SAMPLE_COVERAGE_INVERT : 0x80AB,
+COMPRESSED_TEXTURE_FORMATS : 0x86A3,
+DONT_CARE : 0x1100,
+FASTEST : 0x1101,
+NICEST : 0x1102,
+GENERATE_MIPMAP_HINT : 0x8192,
+BYTE : 0x1400,
+UNSIGNED_BYTE : 0x1401,
+SHORT : 0x1402,
+UNSIGNED_SHORT : 0x1403,
+INT : 0x1404,
+UNSIGNED_INT : 0x1405,
+FLOAT : 0x1406,
+//FIXED : 0x140C,
+DEPTH_COMPONENT : 0x1902,
+ALPHA : 0x1906,
+RGB : 0x1907,
+RGBA : 0x1908,
+LUMINANCE : 0x1909,
+LUMINANCE_ALPHA : 0x190A,
+UNSIGNED_SHORT_4_4_4_4 : 0x8033,
+UNSIGNED_SHORT_5_5_5_1 : 0x8034,
+UNSIGNED_SHORT_5_6_5 : 0x8363,
+FRAGMENT_SHADER : 0x8B30,
+VERTEX_SHADER : 0x8B31,
+MAX_VERTEX_ATTRIBS : 0x8869,
+MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB,
+MAX_VARYING_VECTORS : 0x8DFC,
+MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D,
+MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C,
+MAX_TEXTURE_IMAGE_UNITS : 0x8872,
+MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD,
+SHADER_TYPE : 0x8B4F,
+DELETE_STATUS : 0x8B80,
+LINK_STATUS : 0x8B82,
+VALIDATE_STATUS : 0x8B83,
+ATTACHED_SHADERS : 0x8B85,
+ACTIVE_UNIFORMS : 0x8B86,
+ACTIVE_ATTRIBUTES : 0x8B89,
+SHADING_LANGUAGE_VERSION : 0x8B8C,
+CURRENT_PROGRAM : 0x8B8D,
+NEVER : 0x0200,
+LESS : 0x0201,
+EQUAL : 0x0202,
+LEQUAL : 0x0203,
+GREATER : 0x0204,
+NOTEQUAL : 0x0205,
+GEQUAL : 0x0206,
+ALWAYS : 0x0207,
+KEEP : 0x1E00,
+REPLACE : 0x1E01,
+INCR : 0x1E02,
+DECR : 0x1E03,
+INVERT : 0x150A,
+INCR_WRAP : 0x8507,
+DECR_WRAP : 0x8508,
+VENDOR : 0x1F00,
+RENDERER : 0x1F01,
+VERSION : 0x1F02,
+//EXTENSIONS : 0x1F03,
+NEAREST : 0x2600,
+LINEAR : 0x2601,
+NEAREST_MIPMAP_NEAREST : 0x2700,
+LINEAR_MIPMAP_NEAREST : 0x2701,
+NEAREST_MIPMAP_LINEAR : 0x2702,
+LINEAR_MIPMAP_LINEAR : 0x2703,
+TEXTURE_MAG_FILTER : 0x2800,
+TEXTURE_MIN_FILTER : 0x2801,
+TEXTURE_WRAP_S : 0x2802,
+TEXTURE_WRAP_T : 0x2803,
+TEXTURE : 0x1702,
+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,
+MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C,
+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,
+REPEAT : 0x2901,
+CLAMP_TO_EDGE : 0x812F,
+MIRRORED_REPEAT : 0x8370,
+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_2D : 0x8B5E,
+SAMPLER_CUBE : 0x8B60,
+VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622,
+VERTEX_ATTRIB_ARRAY_SIZE : 0x8623,
+VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624,
+VERTEX_ATTRIB_ARRAY_TYPE : 0x8625,
+VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A,
+VERTEX_ATTRIB_ARRAY_POINTER : 0x8645,
+VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
+//IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A,
+//IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B,
+COMPILE_STATUS : 0x8B81,
+//SHADER_COMPILER : 0x8DFA,
+LOW_FLOAT : 0x8DF0,
+MEDIUM_FLOAT : 0x8DF1,
+HIGH_FLOAT : 0x8DF2,
+LOW_INT : 0x8DF3,
+MEDIUM_INT : 0x8DF4,
+HIGH_INT : 0x8DF5,
+FRAMEBUFFER : 0x8D40,
+RENDERBUFFER : 0x8D41,
+RGBA4 : 0x8056,
+RGB5_A1 : 0x8057,
+RGB565 : 0x8D62,
+DEPTH_COMPONENT16 : 0x81A5,
+STENCIL_INDEX8 : 0x8D48,
+DEPTH_STENCIL : 0x84F9,
+RENDERBUFFER_WIDTH : 0x8D42,
+RENDERBUFFER_HEIGHT : 0x8D43,
+RENDERBUFFER_INTERNAL_FORMAT : 0x8D44,
+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_ATTACHMENT_OBJECT_TYPE : 0x8CD0,
+FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3,
+COLOR_ATTACHMENT0 : 0x8CE0,
+DEPTH_ATTACHMENT : 0x8D00,
+STENCIL_ATTACHMENT : 0x8D20,
+DEPTH_STENCIL_ATTACHMENT : 0x821A,
+NONE : 0,
+FRAMEBUFFER_COMPLETE : 0x8CD5,
+FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6,
+FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7,
+FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9,
+FRAMEBUFFER_UNSUPPORTED : 0x8CDD,
+FRAMEBUFFER_BINDING : 0x8CA6,
+RENDERBUFFER_BINDING : 0x8CA7,
+MAX_RENDERBUFFER_SIZE : 0x84E8,
+INVALID_FRAMEBUFFER_OPERATION : 0x0506,
+//FALSE : 0,
+//TRUE : 1,
+UNPACK_FLIP_Y_WEBGL : 0x9240,
+UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241
+}
+
+Tests.testOES20Constants = function(gl) {
+ for (var i in constants) {
+ assertProperty(gl, i) &&
+ assertEquals(i, gl[i], constants[i]);
+ }
+ var extended = false;
+ for (var i in gl) {
+ if (i.match(/^[A-Z_]+$/) && constants[i] == null) {
+ if (!extended) {
+ extended = true;
+ var h = document.createElement('h3');
+ h.textContent = "Also found the following extra constants";
+ __testLog__.appendChild(h);
+ }
+ log(i);
+ }
+ }
+}
+
+Tests.startUnit = function() {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/fuzzTheAPI.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/fuzzTheAPI.html
new file mode 100644
index 0000000000..c1090aeb4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/fuzzTheAPI.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+
+<script type="application/javascript">
+
+Tests.autorun = false;
+Tests.message = "This will fuzz the API with random inputs for a [long] while."
+
+
+function randomCall(testProgress, gl, m, arities) {
+ doTestNotify(m);
+ var argcs = {};
+ var foundArity = false;
+ if (arities == null) {
+ testProgress.textContent += " 500 random arity calls on " + m + "\n";
+ for (var i=0; i<50; i++) {
+ for (var j=0; j<10; j++) {
+ var args = generateRandomArgs(j);
+// doTestNotify(m + ": " + args.toSource());
+ try {
+ gl[m].apply(gl, args);
+ argcs[j] = true;
+ foundArity = true;
+ } catch (e) {
+ }
+ }
+ }
+ for (var j in argcs) {
+ testProgress.textContent += "200 arity " + j + " calls on " + m + "\n";
+ for (var i=0; i<200; i++) {
+ var args = generateRandomArgs(j);
+// doTestNotify(m + ": " + args.toSource());
+ try {
+ gl[m].apply(gl, args);
+ argcs[j] = true;
+ } catch (e) {
+ }
+ }
+ }
+ } else {
+ for (var k=0; k<arities.length; k++) {
+ var j = arities[k];
+ testProgress.textContent += "500 arity " + j + " calls on " + m + "\n";
+ for (var i=0; i<500; i++) {
+ var args = generateRandomArgs(j);
+// doTestNotify(m + ": " + args.toSource());
+ try {
+ gl[m].apply(gl, args);
+ } catch (e) {
+ }
+ }
+ }
+ }
+// doTestNotify(m+"--OK");
+}
+
+Tests.testGetGLWeb20 = function() {
+ var testProgress = document.getElementById('testProgress');
+ var funcnames = document.getElementById('funcnames').value.split(",");
+ var canvas = document.getElementById('glweb20');
+ var gl;
+ assertOk(function(){gl = getGLContext(canvas);});
+ var funcs = [];
+ for (var i=0; i<funcnames.length; i++) {
+ var fn = funcnames[i];
+ fn = fn.replace(/^\s+|\s+$/g, '');
+ if (fn.length > 0)
+ funcs.push(fn);
+ }
+ if (funcs.length == 0) {
+ for (var m in gl)
+ try{if (typeof gl[m] == 'function')
+ funcs.push(m);}catch(e){}
+ }
+ var idx = 0;
+ var count = 0;
+ var limit = 1000;
+ var iv1;
+ var iv2;
+ iv1 = setInterval(function(){
+ if (idx >= funcs.length) {
+ iv2 = setInterval(function(){
+ if (count >= limit) {
+ clearInterval(iv2);
+ return false;
+ }
+ count++;
+ var f = Math.floor(Math.random() * funcs.length);
+ randomCall(testProgress, gl, funcs[f]);
+ }, 50);
+ clearInterval(iv1);
+ return false;
+ }
+ randomCall(testProgress, gl, funcs[idx]);
+ idx++;
+ }, 50);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="glweb20" width="16" height="16"></canvas>
+ <p>Optional: Enter a comma-separated list of functions to fuzz (leave blank for full API)</p>
+ <input type="text" size="40" id="funcnames" value="">
+ <pre id="testProgress"></pre>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/getContext.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/getContext.html
new file mode 100644
index 0000000000..14c0559123
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/getContext.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+
+<script type="application/javascript">
+
+Tests.testGetWebGL = function() {
+ var canvas = document.getElementById('webgl');
+ var gl;
+ assertOk(function(){gl = getGLContext(canvas)});
+ assertEquals("ctx.canvas === canvas", gl.canvas, canvas);
+ assertOk(function(){g2d = canvas.getContext('2d')});
+ assert("Should get a null 2d context after getting webgl context", g2d === null);
+}
+
+Tests.testGet2D = function() {
+ var canvas = document.getElementById('2d');
+ var g2d;
+ var gl;
+ assertOk(function(){g2d = canvas.getContext('2d')});
+ assertOk(function(){gl = getGLContext(canvas)});
+ assert("Should get a null WebGL context after getting 2D context", gl === null);
+}
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+ <canvas id="2d" width="1" height="1"></canvas>
+ <canvas id="webgl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/methods.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/methods.html
new file mode 100644
index 0000000000..d6d14bd827
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/methods.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+/*
+ The following tests are generated from
+ http://www.khronos.org/registry/gles/api/2.0/gl2.h
+ and api_modifications.txt
+*/
+var methods = ['canvas',
+"activeTexture",
+"attachShader",
+"bindAttribLocation",
+"bindBuffer",
+"bindFramebuffer",
+"bindRenderbuffer",
+"bindTexture",
+"blendColor",
+"blendEquation",
+"blendEquationSeparate",
+"blendFunc",
+"blendFuncSeparate",
+"bufferData",
+"bufferSubData",
+"checkFramebufferStatus",
+"clear",
+"clearColor",
+"clearDepth",
+"clearStencil",
+"colorMask",
+"compileShader",
+"copyTexImage2D",
+"copyTexSubImage2D",
+"createProgram",
+"createShader",
+"cullFace",
+"deleteBuffer",
+"deleteFramebuffer",
+"deleteProgram",
+"deleteRenderbuffer",
+"deleteShader",
+"deleteTexture",
+"depthFunc",
+"depthMask",
+"depthRange",
+"detachShader",
+"disable",
+"disableVertexAttribArray",
+"drawArrays",
+"drawElements",
+"enable",
+"enableVertexAttribArray",
+"finish",
+"flush",
+"framebufferRenderbuffer",
+"framebufferTexture2D",
+"frontFace",
+"createBuffer",
+"generateMipmap",
+"createFramebuffer",
+"createRenderbuffer",
+"createTexture",
+"getActiveAttrib",
+"getActiveUniform",
+"getAttachedShaders",
+"getAttribLocation",
+"getBufferParameter",
+"getError",
+"getExtension",
+"getSupportedExtensions",
+"getFramebufferAttachmentParameter",
+"getProgramInfoLog",
+"getRenderbufferParameter",
+"getShaderInfoLog",
+"getShaderSource",
+"getUniformLocation",
+"hint",
+"isBuffer",
+"isContextLost",
+"isEnabled",
+"isFramebuffer",
+"isProgram",
+"isRenderbuffer",
+"isShader",
+"isTexture",
+"lineWidth",
+"linkProgram",
+"polygonOffset",
+"readPixels",
+"renderbufferStorage",
+"sampleCoverage",
+"scissor",
+"shaderSource",
+"stencilFunc",
+"stencilFuncSeparate",
+"stencilMask",
+"stencilMaskSeparate",
+"stencilOp",
+"stencilOpSeparate",
+"texImage2D",
+"texParameteri",
+"texSubImage2D",
+"uniform1f",
+"uniform1fv",
+"uniform1i",
+"uniform1iv",
+"uniform2f",
+"uniform2fv",
+"uniform2i",
+"uniform2iv",
+"uniform3f",
+"uniform3fv",
+"uniform3i",
+"uniform3iv",
+"uniform4f",
+"uniform4fv",
+"uniform4i",
+"uniform4iv",
+"uniformMatrix2fv",
+"uniformMatrix3fv",
+"uniformMatrix4fv",
+"useProgram",
+"validateProgram",
+"vertexAttrib1f",
+"vertexAttrib1fv",
+"vertexAttrib2f",
+"vertexAttrib2fv",
+"vertexAttrib3f",
+"vertexAttrib3fv",
+"vertexAttrib4f",
+"vertexAttrib4fv",
+"vertexAttribPointer",
+"viewport",
+"getParameter",
+"getProgramParameter",
+"getShaderParameter",
+"getTexParameter",
+"getUniform",
+"getVertexAttrib"
+]
+
+Tests.testOES20Methods = function(gl) {
+ for (var i=0; i<methods.length; i++) {
+ assertProperty(gl, methods[i]);
+ }
+ var extended = false;
+ for (var i in gl) {
+ if (i.match(/^[a-z_]+$/) && methods.indexOf(i) == -1) {
+ if (!extended) {
+ extended = true;
+ var h = document.createElement('h3');
+ h.textContent = "Also found the following extra properties";
+ __testLog__.appendChild(h);
+ }
+ log(i);
+ }
+ }
+}
+
+Tests.startUnit = function() {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-A.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-A.html
new file mode 100644
index 0000000000..fe453457c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-A.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-A.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B1.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B1.html
new file mode 100644
index 0000000000..6d34f27795
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B1.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-B1.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B2.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B2.html
new file mode 100644
index 0000000000..2a1ddd9bd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B2.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-B2.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B3.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B3.html
new file mode 100644
index 0000000000..08e85dbc04
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B3.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-B3.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B4.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B4.html
new file mode 100644
index 0000000000..9ee5228e78
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-B4.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-B4.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-C.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-C.html
new file mode 100644
index 0000000000..3717e41e77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-C.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-C.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-D_G.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-D_G.html
new file mode 100644
index 0000000000..c692db331b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-D_G.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-D_G.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-G_I.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-G_I.html
new file mode 100644
index 0000000000..1f474892fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-G_I.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-G_I.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-L_S.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-L_S.html
new file mode 100644
index 0000000000..698e1c93d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-L_S.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-L_S.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-S_V.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-S_V.html
new file mode 100644
index 0000000000..84e60151e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI-S_V.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+<script type="application/javascript" src="argGenerators-S_V.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ if (!gen.noAlreadyTriedCheck) {
+ var src = Object.toSource(args);
+ if (alreadyTriedArgs[src])
+ return true;
+
+ alreadyTriedArgs[src] = true;
+ }
+ var ok = false;
+ // if we have an validity checker, assert that the generated args are valid
+ if (gen.checkArgValidity)
+ assert("Valid args: "+name+"("+argsToString(args)+")",
+ gen.checkArgValidity.apply(gen, args));
+ var rv;
+ // assert that GL function works when called with valid args
+ assertOk("This should work: "+name+"("+argsToString(args)+")",
+ function(){rv = GL[name].apply(GL, args); ok = true;});
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup)
+ assertOk("Cleaning up return value after "+name+"("+argsToString(args)+")",
+ function() { gen.returnValueCleanup(rv); });
+ return ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI.js
new file mode 100644
index 0000000000..50e74963e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPI.js
@@ -0,0 +1,414 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+/*
+ QuickCheck tests for WebGL:
+
+ 1. Write a valid arg generator for each function
+ 1.1. Write valid arg predicates to use with random generator:
+ if value passes generator, accept it as valid.
+ 1.2. Often needs initializing and cleanup:
+ setup - generate - cleanup
+ gl.createBuffer - test(bindBufferGenerator) - gl.deleteBuffer
+
+ 2. Write an invalid arg generator
+ 2.1. Take valid args, modify an arg until the args no longer pass
+ checkArgValidity.
+ 2.2. Repeat for all args.
+
+ 3. Test functions using the generators
+ 3.1. Args generated with the valid arg generator should pass
+ assertOk(f(args))
+ 3.2. Args generated with the invalid arg generator should pass
+ assertFail(f(args))
+*/
+var GLcanvas = document.createElement('canvas');
+var canvas2D = document.createElement('canvas');
+GLcanvas.width = GLcanvas.height = 256;
+GL = getGLContext(GLcanvas);
+Array.from = function(o) {
+ var a = [];
+ for (var i=0; i<o.length; i++)
+ a.push(o[i]);
+ return a;
+}
+Array.prototype.has = function(v) { return this.indexOf(v) != -1; }
+Array.prototype.random = function() { return this[randomInt(this.length)]; }
+
+castToInt = function(o) {
+ if (typeof o == 'number')
+ return isNaN(o) ? 0 : Math.floor(o);
+ if (o == true) return 1;
+ return 0;
+};
+
+// Creates a constant checker / generator from its arguments.
+//
+// E.g. if you want a constant checker for the constants 1, 2, and 3, you
+// would do the following:
+//
+// var cc = constCheck(1,2,3);
+// var randomConst = cc.random();
+// if (cc.has(randomConst))
+// console.log("randomConst is included in cc's constants");
+//
+constCheck = function() {
+ var a = Array.from(arguments);
+ a.has = function(v) { return this.indexOf(castToInt(v)) != -1; };
+ return a;
+}
+
+bindTextureTarget = constCheck(GL.TEXTURE_2D, GL.TEXTURE_CUBE_MAP);
+blendEquationMode = constCheck(GL.FUNC_ADD, GL.FUNC_SUBTRACT, GL.FUNC_REVERSE_SUBTRACT);
+blendFuncSfactor = constCheck(
+ GL.ZERO, GL.ONE, GL.SRC_COLOR, GL.ONE_MINUS_SRC_COLOR, GL.DST_COLOR,
+ GL.ONE_MINUS_DST_COLOR, GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.DST_ALPHA,
+ GL.ONE_MINUS_DST_ALPHA, GL.CONSTANT_COLOR, GL.ONE_MINUS_CONSTANT_COLOR,
+ GL.CONSTANT_ALPHA, GL.ONE_MINUS_CONSTANT_ALPHA, GL.SRC_ALPHA_SATURATE
+);
+blendFuncDfactor = constCheck(
+ GL.ZERO, GL.ONE, GL.SRC_COLOR, GL.ONE_MINUS_SRC_COLOR, GL.DST_COLOR,
+ GL.ONE_MINUS_DST_COLOR, GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.DST_ALPHA,
+ GL.ONE_MINUS_DST_ALPHA, GL.CONSTANT_COLOR, GL.ONE_MINUS_CONSTANT_COLOR,
+ GL.CONSTANT_ALPHA, GL.ONE_MINUS_CONSTANT_ALPHA
+);
+bufferTarget = constCheck(GL.ARRAY_BUFFER, GL.ELEMENT_ARRAY_BUFFER);
+bufferMode = constCheck(GL.STREAM_DRAW, GL.STATIC_DRAW, GL.DYNAMIC_DRAW);
+clearMask = constCheck(
+ GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT | GL.STENCIL_BUFFER_BIT,
+ GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT,
+ GL.COLOR_BUFFER_BIT | GL.STENCIL_BUFFER_BIT,
+ GL.DEPTH_BUFFER_BIT | GL.STENCIL_BUFFER_BIT,
+ GL.COLOR_BUFFER_BIT, GL.DEPTH_BUFFER_BIT, GL.STENCIL_BUFFER_BIT, 0
+);
+cullFace = constCheck(GL.FRONT, GL.BACK, GL.FRONT_AND_BACK);
+depthFuncFunc = constCheck(
+ GL.NEVER, GL.LESS, GL.EQUAL, GL.LEQUAL, GL.GREATER, GL.NOTEQUAL,
+ GL.GEQUAL, GL.ALWAYS
+);
+stencilFuncFunc = depthFuncFunc;
+enableCap = constCheck(
+ GL.BLEND, GL.CULL_FACE, GL.DEPTH_TEST, GL.DITHER, GL.POLYGON_OFFSET_FILL,
+ GL.SAMPLE_ALPHA_TO_COVERAGE, GL.SAMPLE_COVERAGE, GL.SCISSOR_TEST,
+ GL.STENCIL_TEST
+);
+frontFaceMode = constCheck(GL.CCW, GL.CW);
+getParameterPname = constCheck(
+ GL.ACTIVE_TEXTURE || "GL.ACTIVE_TEXTURE",
+ GL.ALIASED_LINE_WIDTH_RANGE || "GL.ALIASED_LINE_WIDTH_RANGE",
+ GL.ALIASED_POINT_SIZE_RANGE || "GL.ALIASED_POINT_SIZE_RANGE",
+ GL.ALPHA_BITS || "GL.ALPHA_BITS",
+ GL.ARRAY_BUFFER_BINDING || "GL.ARRAY_BUFFER_BINDING",
+ GL.BLEND || "GL.BLEND",
+ GL.BLEND_COLOR || "GL.BLEND_COLOR",
+ GL.BLEND_DST_ALPHA || "GL.BLEND_DST_ALPHA",
+ GL.BLEND_DST_RGB || "GL.BLEND_DST_RGB",
+ GL.BLEND_EQUATION_ALPHA || "GL.BLEND_EQUATION_ALPHA",
+ GL.BLEND_EQUATION_RGB || "GL.BLEND_EQUATION_RGB",
+ GL.BLEND_SRC_ALPHA || "GL.BLEND_SRC_ALPHA",
+ GL.BLEND_SRC_RGB || "GL.BLEND_SRC_RGB",
+ GL.BLUE_BITS || "GL.BLUE_BITS",
+ GL.COLOR_CLEAR_VALUE || "GL.COLOR_CLEAR_VALUE",
+ GL.COLOR_WRITEMASK || "GL.COLOR_WRITEMASK",
+ GL.COMPRESSED_TEXTURE_FORMATS || "GL.COMPRESSED_TEXTURE_FORMATS",
+ GL.CULL_FACE || "GL.CULL_FACE",
+ GL.CULL_FACE_MODE || "GL.CULL_FACE_MODE",
+ GL.CURRENT_PROGRAM || "GL.CURRENT_PROGRAM",
+ GL.DEPTH_BITS || "GL.DEPTH_BITS",
+ GL.DEPTH_CLEAR_VALUE || "GL.DEPTH_CLEAR_VALUE",
+ GL.DEPTH_FUNC || "GL.DEPTH_FUNC",
+ GL.DEPTH_RANGE || "GL.DEPTH_RANGE",
+ GL.DEPTH_TEST || "GL.DEPTH_TEST",
+ GL.DEPTH_WRITEMASK || "GL.DEPTH_WRITEMASK",
+ GL.DITHER || "GL.DITHER",
+ GL.ELEMENT_ARRAY_BUFFER_BINDING || "GL.ELEMENT_ARRAY_BUFFER_BINDING",
+ GL.FRAMEBUFFER_BINDING || "GL.FRAMEBUFFER_BINDING",
+ GL.FRONT_FACE || "GL.FRONT_FACE",
+ GL.GENERATE_MIPMAP_HINT || "GL.GENERATE_MIPMAP_HINT",
+ GL.GREEN_BITS || "GL.GREEN_BITS",
+ GL.LINE_WIDTH || "GL.LINE_WIDTH",
+ GL.MAX_COMBINED_TEXTURE_IMAGE_UNITS || "GL.MAX_COMBINED_TEXTURE_IMAGE_UNITS",
+ GL.MAX_CUBE_MAP_TEXTURE_SIZE || "GL.MAX_CUBE_MAP_TEXTURE_SIZE",
+ GL.MAX_FRAGMENT_UNIFORM_VECTORS || "GL.MAX_FRAGMENT_UNIFORM_VECTORS",
+ GL.MAX_RENDERBUFFER_SIZE || "GL.MAX_RENDERBUFFER_SIZE",
+ GL.MAX_TEXTURE_IMAGE_UNITS || "GL.MAX_TEXTURE_IMAGE_UNITS",
+ GL.MAX_TEXTURE_SIZE || "GL.MAX_TEXTURE_SIZE",
+ GL.MAX_VARYING_VECTORS || "GL.MAX_VARYING_VECTORS",
+ GL.MAX_VERTEX_ATTRIBS || "GL.MAX_VERTEX_ATTRIBS",
+ GL.MAX_VERTEX_TEXTURE_IMAGE_UNITS || "GL.MAX_VERTEX_TEXTURE_IMAGE_UNITS",
+ GL.MAX_VERTEX_UNIFORM_VECTORS || "GL.MAX_VERTEX_UNIFORM_VECTORS",
+ GL.MAX_VIEWPORT_DIMS || "GL.MAX_VIEWPORT_DIMS",
+ GL.PACK_ALIGNMENT || "GL.PACK_ALIGNMENT",
+ GL.POLYGON_OFFSET_FACTOR || "GL.POLYGON_OFFSET_FACTOR",
+ GL.POLYGON_OFFSET_FILL || "GL.POLYGON_OFFSET_FILL",
+ GL.POLYGON_OFFSET_UNITS || "GL.POLYGON_OFFSET_UNITS",
+ GL.RED_BITS || "GL.RED_BITS",
+ GL.RENDERBUFFER_BINDING || "GL.RENDERBUFFER_BINDING",
+ GL.SAMPLE_BUFFERS || "GL.SAMPLE_BUFFERS",
+ GL.SAMPLE_COVERAGE_INVERT || "GL.SAMPLE_COVERAGE_INVERT",
+ GL.SAMPLE_COVERAGE_VALUE || "GL.SAMPLE_COVERAGE_VALUE",
+ GL.SAMPLES || "GL.SAMPLES",
+ GL.SCISSOR_BOX || "GL.SCISSOR_BOX",
+ GL.SCISSOR_TEST || "GL.SCISSOR_TEST",
+ GL.STENCIL_BACK_FAIL || "GL.STENCIL_BACK_FAIL",
+ GL.STENCIL_BACK_FUNC || "GL.STENCIL_BACK_FUNC",
+ GL.STENCIL_BACK_PASS_DEPTH_FAIL || "GL.STENCIL_BACK_PASS_DEPTH_FAIL",
+ GL.STENCIL_BACK_PASS_DEPTH_PASS || "GL.STENCIL_BACK_PASS_DEPTH_PASS",
+ GL.STENCIL_BACK_REF || "GL.STENCIL_BACK_REF",
+ GL.STENCIL_BACK_VALUE_MASK || "GL.STENCIL_BACK_VALUE_MASK",
+ GL.STENCIL_BACK_WRITEMASK || "GL.STENCIL_BACK_WRITEMASK",
+ GL.STENCIL_BITS || "GL.STENCIL_BITS",
+ GL.STENCIL_CLEAR_VALUE || "GL.STENCIL_CLEAR_VALUE",
+ GL.STENCIL_FAIL || "GL.STENCIL_FAIL",
+ GL.STENCIL_FUNC || "GL.STENCIL_FUNC",
+ GL.STENCIL_PASS_DEPTH_FAIL || "GL.STENCIL_PASS_DEPTH_FAIL",
+ GL.STENCIL_PASS_DEPTH_PASS || "GL.STENCIL_PASS_DEPTH_PASS",
+ GL.STENCIL_REF || "GL.STENCIL_REF",
+ GL.STENCIL_TEST || "GL.STENCIL_TEST",
+ GL.STENCIL_VALUE_MASK || "GL.STENCIL_VALUE_MASK",
+ GL.STENCIL_WRITEMASK || "GL.STENCIL_WRITEMASK",
+ GL.SUBPIXEL_BITS || "GL.SUBPIXEL_BITS",
+ GL.TEXTURE_BINDING_2D || "GL.TEXTURE_BINDING_2D",
+ GL.TEXTURE_BINDING_CUBE_MAP || "GL.TEXTURE_BINDING_CUBE_MAP",
+ GL.UNPACK_ALIGNMENT || "GL.UNPACK_ALIGNMENT",
+ GL.VIEWPORT || "GL.VIEWPORT"
+);
+mipmapHint = constCheck(GL.FASTEST, GL.NICEST, GL.DONT_CARE);
+pixelStoreiPname = constCheck(GL.PACK_ALIGNMENT, GL.UNPACK_ALIGNMENT);
+pixelStoreiParam = constCheck(1,2,4,8);
+shaderType = constCheck(GL.VERTEX_SHADER, GL.FRAGMENT_SHADER);
+stencilOp = constCheck(GL.KEEP, GL.ZERO, GL.REPLACE, GL.INCR, GL.INCR_WRAP,
+ GL.DECR, GL.DECR_WRAP, GL.INVERT);
+texImageTarget = constCheck(
+ GL.TEXTURE_2D,
+ 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
+);
+texImageInternalFormat = constCheck(
+ GL.ALPHA,
+ GL.LUMINANCE,
+ GL.LUMINANCE_ALPHA,
+ GL.RGB,
+ GL.RGBA
+);
+texImageFormat = constCheck(
+ GL.ALPHA,
+ GL.LUMINANCE,
+ GL.LUMINANCE_ALPHA,
+ GL.RGB,
+ GL.RGBA
+);
+texImageType = constCheck(GL.UNSIGNED_BYTE);
+texParameterPname = constCheck(
+ GL.TEXTURE_MIN_FILTER, GL.TEXTURE_MAG_FILTER,
+ GL.TEXTURE_WRAP_S, GL.TEXTURE_WRAP_T);
+texParameterParam = {};
+texParameterParam[GL.TEXTURE_MIN_FILTER] = constCheck(
+ GL.NEAREST, GL.LINEAR, GL.NEAREST_MIPMAP_NEAREST, GL.LINEAR_MIPMAP_NEAREST,
+ GL.NEAREST_MIPMAP_LINEAR, GL.LINEAR_MIPMAP_LINEAR);
+texParameterParam[GL.TEXTURE_MAG_FILTER] = constCheck(GL.NEAREST, GL.LINEAR);
+texParameterParam[GL.TEXTURE_WRAP_S] = constCheck(
+ GL.CLAMP_TO_EDGE, GL.MIRRORED_REPEAT, GL.REPEAT);
+texParameterParam[GL.TEXTURE_WRAP_T] = texParameterParam[GL.TEXTURE_WRAP_S];
+textureUnit = constCheck.apply(this, (function(){
+ var textureUnits = [];
+ var texUnits = GL.getParameter(GL.MAX_TEXTURE_IMAGE_UNITS);
+ for (var i=0; i<texUnits; i++) textureUnits.push(GL['TEXTURE'+i]);
+ return textureUnits;
+})());
+
+var StencilBits = GL.getParameter(GL.STENCIL_BITS);
+var MaxStencilValue = 1 << StencilBits;
+
+var MaxVertexAttribs = GL.getParameter(GL.MAX_VERTEX_ATTRIBS);
+var LineWidthRange = GL.getParameter(GL.ALIASED_LINE_WIDTH_RANGE);
+
+// Returns true if bufData can be passed to GL.bufferData
+isBufferData = function(bufData) {
+ if (typeof bufData == 'number')
+ return bufData >= 0;
+ if (bufData instanceof ArrayBuffer)
+ return true;
+ return WebGLArrayTypes.some(function(t) {
+ return bufData instanceof t;
+ });
+};
+
+isVertexAttribute = function(idx) {
+ if (typeof idx != 'number') return false;
+ return idx >= 0 && idx < MaxVertexAttribs;
+};
+
+isValidName = function(name) {
+ if (typeof name != 'string') return false;
+ for (var i=0; i<name.length; i++) {
+ var c = name.charCodeAt(i);
+ if (c & 0x00FF == 0 || c & 0xFF00 == 0) {
+ return false;
+ }
+ }
+ return true;
+};
+
+WebGLArrayTypes = [
+ Float32Array,
+ Int32Array,
+ Int16Array,
+ Int8Array,
+ Uint32Array,
+ Uint16Array,
+ Uint8Array
+];
+webGLArrayContentGenerators = [randomLength, randomSmallIntArray];
+randomWebGLArray = function() {
+ var t = WebGLArrayTypes.random();
+ return new t(webGLArrayContentGenerators.random()());
+};
+
+randomArrayBuffer = function(buflen) {
+ if (buflen == null) buflen = 256;
+ var len = randomInt(buflen)+1;
+ var rv;
+ try {
+ rv = new ArrayBuffer(len);
+ } catch(e) {
+ log("Error creating ArrayBuffer with length " + len);
+ throw(e);
+ }
+ return rv;
+};
+
+bufferDataGenerators = [randomLength, randomWebGLArray, randomArrayBuffer];
+randomBufferData = function() {
+ return bufferDataGenerators.random()();
+};
+
+randomSmallWebGLArray = function(buflen) {
+ var t = WebGLArrayTypes.random();
+ return new t(randomInt(buflen/4)+1);
+};
+
+bufferSubDataGenerators = [randomSmallWebGLArray, randomArrayBuffer];
+randomBufferSubData = function(buflen) {
+ var data = bufferSubDataGenerators.random()(buflen);
+ var offset = randomInt(buflen - data.byteLength);
+ return {data:data, offset:offset};
+};
+
+randomColor = function() {
+ return [Math.random(), Math.random(), Math.random(), Math.random()];
+};
+
+randomName = function() {
+ var arr = [];
+ var len = randomLength()+1;
+ for (var i=0; i<len; i++) {
+ var l = randomInt(255)+1;
+ var h = randomInt(255)+1;
+ var c = (h << 8) | l;
+ arr.push(String.fromCharCode(c));
+ }
+ return arr.join('');
+};
+randomVertexAttribute = function() {
+ return randomInt(MaxVertexAttribs);
+};
+
+randomBool = function() { return Math.random() > 0.5; };
+
+randomStencil = function() {
+ return randomInt(MaxStencilValue);
+};
+
+randomLineWidth = function() {
+ var lo = LineWidthRange[0],
+ hi = LineWidthRange[1];
+ return randomFloatFromRange(lo, hi);
+};
+
+randomImage = function(w,h) {
+ var img;
+ var r = Math.random();
+ if (r < 0.25) {
+ img = document.createElement('canvas');
+ img.width = w; img.height = h;
+ img.getContext('2d').fillRect(0,0,w,h);
+ } else if (r < 0.5) {
+ img = document.createElement('video');
+ img.muted = true;
+ img.width = w; img.height = h;
+ } else if (r < 0.75) {
+ img = document.createElement('img');
+ img.width = w; img.height = h;
+ } else {
+ img = canvas2D.getContext('2d').createImageData(w,h);
+ }
+ return img
+};
+
+mutateArgs = function(args) {
+ var mutateCount = randomIntFromRange(1, args.length);
+ var newArgs = Array.from(args);
+ for (var i=0; i<mutateCount; i++) {
+ var idx = randomInt(args.length);
+ newArgs[idx] = generateRandomArg(idx, args.length);
+ }
+ return newArgs;
+};
+
+// Calls testFunction numberOfTests times with arguments generated by
+// argGen.generate() (or empty arguments if no generate present).
+//
+// The arguments testFunction is called with are the generated args,
+// the argGen, and what argGen.setup() returned or [] if argGen has not setup
+// method. I.e. testFunction(generatedArgs, argGen, setupVars).
+//
+argGeneratorTestRunner = function(argGen, testFunction, numberOfTests) {
+ // do argument generator setup if needed
+ var setupVars = argGen.setup ? argGen.setup() : [];
+ var error;
+ for (var i=0; i<numberOfTests; i++) {
+ var failed = false;
+ // generate arguments if argGen has a generate method
+ var generatedArgs = argGen.generate ? argGen.generate.apply(argGen, setupVars) : [];
+ try {
+ // call testFunction with the generated args
+ testFunction.call(this, generatedArgs, argGen, setupVars);
+ } catch (e) {
+ failed = true;
+ error = e;
+ }
+ // if argGen needs cleanup for generated args, do it here
+ if (argGen.cleanup)
+ argGen.cleanup.apply(argGen, generatedArgs);
+ if (failed) break;
+ }
+ // if argGen needs to do a final cleanup for setupVars, do it here
+ if (argGen.teardown)
+ argGen.teardown.apply(argGen, setupVars);
+ if (error) throw(error);
+};
+
+// TODO: Remove this
+// WebKit or at least Chrome is really slow at laying out strings with
+// unprintable characters. Without this tests can take 30-90 seconds.
+// With this they're instant.
+sanitize = function(str) {
+ var newStr = [];
+ for (var ii = 0; ii < str.length; ++ii) {
+ var c = str.charCodeAt(ii);
+ newStr.push((c > 31 && c < 128) ? str[ii] : "?");
+ }
+ return newStr.join('');
+};
+
+argsToString = function(args) {
+ return sanitize(args.map(function(a){return Object.toSource(a)}).join(","));
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPIBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPIBadArgs.html
new file mode 100644
index 0000000000..fb65bf2ad1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/quickCheckAPIBadArgs.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="quickCheckAPI.js"></script>
+
+<script type="application/javascript">
+
+// Test that all GL functions specified in ArgGenerators fail
+// when called with randomly generated invalid arguments
+// Works only on tests with checkArgValidity defined
+Tests.testInvalidArgs = function() {
+ var randomTestCount = 100;
+ for (var name in ArgGenerators) {
+ try {
+ if (!GL[name])
+ throw (new Error(name + " is missing from the WebGL context"));
+ var argGen = ArgGenerators[name];
+ var alreadyTriedArgs = {};
+ if (!argGen.generate || !argGen.checkArgValidity) continue;
+ // test each GL function with randomTestCount randomly generated valid args
+ argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+ var mutatedArgs;
+ var foundArgs = false;
+ for (var j=0; j<100; j++) {
+ mutatedArgs = mutateArgs(args);
+ var validArgs = false;
+ try {
+ validArgs = gen.checkArgValidity.apply(gen, mutatedArgs);
+ } catch(e) {}
+ if (!validArgs) {
+ if (gen.noAlreadyTriedCheck) {
+ foundArgs = true;
+ break; // found new invalid args
+ }
+ var src = Object.toSource(mutatedArgs);
+ if (!alreadyTriedArgs[src]) {
+ alreadyTriedArgs[src] = true;
+ foundArgs = true;
+ break; // found new invalid args
+ }
+ }
+ }
+ if (!foundArgs)
+ return true;
+ var ok = false;
+ var rv;
+ // assert that GL function fails when called with invalid args
+ assertFail("This should fail: "+name+"("+argsToString(mutatedArgs)+")",
+ function(){
+ GL.getError(); // clear off existing error
+ rv = GL[name].apply(GL, mutatedArgs);
+ throwError(GL, name);
+ ok = true;
+ });
+ // if we need to cleanup the return value, do it here
+ // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+ if (gen.returnValueCleanup && rv != null) {
+ assertOk("Cleaning up return value after "+name+"("+argsToString(mutatedArgs)+")",
+ function() { gen.returnValueCleanup(rv); });
+ }
+ GL.getError();
+ return !ok;
+ }, argGen.testCount || randomTestCount);
+ } catch(e) {
+ testFailed(name, e.name, formatError(e));
+ }
+ }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/webGLArrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/webGLArrays.html
new file mode 100644
index 0000000000..bd3eba036d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/conformance/webGLArrays.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+
+<script type="application/javascript">
+
+function assertIdxs(name, arr, length) {
+// assertOk(name+": Read with negative idx should work", function(){ return arr[-1] });
+// assertOk(name+": Read with too large idx should work", function(){ return arr[length] });
+// assertOk(name+": Write with negative idx should work", function(){ arr[-1] = 0 });
+// assertOk(name+": Write with too large idx should work", function(){ arr[length] = 0 });
+// arr[0] = 2;
+// assertEquals(name+": Test that write worked", 2, arr[0]);
+// assertOk(name+": Write with bad value should work", function(){ arr[0] = {x:"foo"} });
+// assertEquals(name+": Test that bad write didn't work", 2, arr[0]);
+ assertOk(name+": Read and writes with OK idxs should work", function(){
+ for (var i=0; i<length; i++) arr[i] = i + 1;
+ for (var i=0; i<length; i++) arr[i] = arr[i] + 1;
+ for (var i=0; i<length; i++) assertEquals(name+": Test that reads and writes work", i+2, arr[i]);
+ });
+}
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ prog = new Shader(gl, 'vert', 'frag');
+ prog.use();
+ prog.uniform4f('c', 255, 0, 0, 255);
+ va = prog.attrib('Vertex');
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ return [gl];
+}
+
+Tests.endUnit = function() {
+ prog.destroy();
+}
+
+Tests.testCreateFromArray = function() {
+ var a = new Float32Array([1,2,3,4,5,6]);
+ assertIdxs('Float', a, 6);
+ var a = new Int32Array([1,2,3,4,5,6]);
+ assertIdxs('Int', a, 6);
+ var a = new Int16Array([1,2,3,4,5,6]);
+ assertIdxs('Short', a, 6);
+ var a = new Int8Array([1,2,3,4,5,6]);
+ assertIdxs('Byte', a, 6);
+ var a = new Uint32Array([1,2,3,4,5,6]);
+ assertIdxs('UInt', a, 6);
+ var a = new Uint16Array([1,2,3,4,5,6]);
+ assertIdxs('UShort', a, 6);
+ var a = new Uint8Array([1,2,3,4,5,6]);
+ assertIdxs('UByte', a, 6);
+}
+Tests.testCreateFromCount = function() {
+ var a = new Float32Array(6);
+ assertIdxs('Float', a, 6);
+ var a = new Int32Array(6);
+ assertIdxs('Int', a, 6);
+ var a = new Int16Array(6);
+ assertIdxs('Short', a, 6);
+ var a = new Int8Array(6);
+ assertIdxs('Byte', a, 6);
+ var a = new Uint32Array(6);
+ assertIdxs('UInt', a, 6);
+ var a = new Uint16Array(6);
+ assertIdxs('UShort', a, 6);
+ var a = new Uint8Array(6);
+ assertIdxs('UByte', a, 6);
+}
+Tests.testCreateFromBuffer = function() {
+ var sz = 24;
+ var b = new ArrayBuffer(sz);
+ var a = new Float32Array(b);
+ assertIdxs('Float', a, sz/4);
+ var a = new Int32Array(b);
+ assertIdxs('Int', a, sz/4);
+ var a = new Int16Array(b);
+ assertIdxs('Short', a, sz/2);
+ var a = new Int8Array(b);
+ assertIdxs('Byte', a, sz/1);
+ var a = new Uint32Array(b);
+ assertIdxs('UInt', a, sz/4);
+ var a = new Uint16Array(b);
+ assertIdxs('UShort', a, sz/2);
+ var a = new Uint8Array(b);
+ assertIdxs('UByte', a, sz/1);
+}
+
+Tests.testThatWritesChangeDrawing = function(gl) {
+ var verts = [
+ 0,0,
+ 1,0,
+ 1,1,
+
+ 0,0,
+ 1,1,
+ 0,1
+ ];
+ var a = new Float32Array(verts);
+ var arr = [];
+ for (var i=0; i<12; i++)
+ arr[i] = a[i];
+ assertEquals("Test that reads work from an array-initialized Float32Array", arr, verts);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(va, 2, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(va);
+
+ var id = new Uint8Array(4);
+ gl.readPixels(8,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertEquals([0, 0, 0, 0], [id[0], id[1], id[2], id[3]]);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ gl.readPixels(8,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertEquals([255, 0, 0, 255], [id[0], id[1], id[2], id[3]]);
+ gl.readPixels(0,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertEquals([0, 0, 0, 0], [id[0], id[1], id[2], id[3]]);
+
+ a[0] = a[6] = a[10] = -1;
+ gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(va, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ gl.readPixels(8,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertEquals([255, 0, 0, 255], [id[0], id[1], id[2], id[3]]);
+ gl.readPixels(0,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertEquals("Test that Float32Array#[]= worked and drawArrays drew a full-width rectangle",
+ [255, 0, 0, 255], [id[0], id[1], id[2], id[3]]);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertEquals([0, 0, 0, 0], [id[0], id[1], id[2], id[3]]);
+}
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+ attribute vec2 Vertex;
+ void main()
+ {
+ gl_Position = vec4(Vertex, 0.0, 1.0);
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+ precision mediump float;
+
+ uniform vec4 c;
+ void main()
+ {
+ gl_FragColor = c;
+ }
+</script>
+<style>canvas{border: 1px solid black}</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBuffer.html
new file mode 100644
index 0000000000..9011d76168
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBuffer.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testBindBufferARRAY_BUFFER = function(gl) {
+ var b = gl.createBuffer();
+ assert(gl.NO_ERROR == checkError(gl, "genBuffers"));
+ gl.bindBuffer(gl.ARRAY_BUFFER, b);
+ assert(gl.NO_ERROR == checkError(gl, "bindBuffer"));
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ assert(gl.NO_ERROR == checkError(gl, "bindBuffer 0"));
+ gl.deleteBuffer(b);
+ assert(gl.NO_ERROR == checkError(gl, "deleteBuffers"));
+}
+
+Tests.testBindBufferELEMENT_ARRAY_BUFFER = function(gl) {
+ var b = gl.createBuffer();
+ assert(gl.NO_ERROR == checkError(gl, "genBuffers"));
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, b);
+ assert(gl.NO_ERROR == checkError(gl, "bindBuffer"));
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ assert(gl.NO_ERROR == checkError(gl, "bindBuffer 0"));
+ gl.deleteBuffer(b);
+ assert(gl.NO_ERROR == checkError(gl, "deleteBuffers"));
+}
+
+</script>
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBufferBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBufferBadArgs.html
new file mode 100644
index 0000000000..09797cb3d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindBufferBadArgs.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testBindBufferARRAY_BUFFER = function(gl) {
+ var b = gl.createBuffer();
+ assertOk("bind buffer", function(){gl.bindBuffer(gl.ARRAY_BUFFER, b)});
+ assertFail("bufferData to null buffer", function() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([10]), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([10]));
+ });
+ assertFail("bind to number", function(){
+ gl.bindBuffer(gl.ARRAY_BUFFER, 1000000000);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([10]), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([10]));
+ });
+ assertOk("bind to null", function(){gl.bindBuffer(gl.ARRAY_BUFFER, null)});
+ gl.deleteBuffer(b);
+}
+
+Tests.testBindBufferELEMENT_ARRAY_BUFFER = function(gl) {
+ var b = gl.createBuffer();
+ assertOk("bind buffer", function(){gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, b)});
+ assertFail("bufferData to null buffer", function() {
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Float32Array([10]), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([10]));
+ });
+ assertFail("bind to number", function(){
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, 1000000000);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Float32Array([10]), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([10]));
+ });
+ assertOk("bind to null",
+ function(){gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null)});
+ gl.deleteBuffer(b);
+}
+Tests.testBindBuffer = function(gl) {
+ assertFail("bind ARRAY_BUFFER to number",
+ function(){gl.bindBuffer(gl.ARRAY_BUFFER, 1);});
+ assertFail("bind ELEMENT_ARRAY_BUFFER to number",
+ function(){gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, 1);});
+ assertFail("bind bad target",
+ function(){gl.bindBuffer(gl.FLOAT, 0);});
+ assertFail("bind ARRAY_BUFFER to string",
+ function(){gl.bindBuffer(gl.ARRAY_BUFFER, "foo");});
+ assertFail("bind ELEMENT_ARRAY_BUFFER to string",
+ function(){gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, "foo");});
+}
+
+</script>
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindFramebufferLeaveNonZero.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindFramebufferLeaveNonZero.html
new file mode 100644
index 0000000000..1c0bab8e00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bindFramebufferLeaveNonZero.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<title>OpenGL for the web</title>
+
+<script type="application/javascript" src="../util.js"></script>
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+
+ <script type="application/javascript">
+Tests.message = "This was segfaulting when the GL context got GC'd (in glXDestroyContext)";
+Tests.testSeg = function () {
+ var canvas = document.getElementById('canvas');
+ var gl = getGLContext(canvas);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+}
+</script>
+
+</head><body>
+ <canvas id="canvas" width="400" height="400"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferData.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferData.html
new file mode 100644
index 0000000000..25d53e6b7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferData.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var buf = gl.createBuffer();
+ var ebuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuf);
+ return [gl, buf, ebuf];
+}
+
+Tests.testBufferData = function(gl, buf, ebuf) {
+ var data = [0,0,0,0, 1,0,0,0, 0,1,0,0];
+ gl.bufferData(gl.ARRAY_BUFFER, 12, gl.STATIC_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([]), gl.STATIC_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STATIC_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STREAM_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STREAM_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.DYNAMIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.DYNAMIC_DRAW);
+
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array(data), gl.STATIC_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array(data), gl.STREAM_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array(data), gl.DYNAMIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*2);
+ throwError(gl, "array bufferSubData");
+}
+Tests.testBufferDataElement = function(gl, buf, ebuf) {
+ var data = [0,0,0,0, 1,0,0,0, 0,1,0,0];
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.STATIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STATIC_DRAW);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.STREAM_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STREAM_DRAW);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.DYNAMIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_USAGE), gl.DYNAMIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE), 12*2);
+ throwError(gl, "element array bufferSubData");
+}
+
+Tests.endUnit = function(gl, buf, ebuf) {
+ gl.deleteBuffer(buf);
+ gl.deleteBuffer(ebuf);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferDataBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferDataBadArgs.html
new file mode 100644
index 0000000000..4a473be0d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferDataBadArgs.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var buf = gl.createBuffer();
+ var ebuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuf);
+ return [gl, buf, ebuf];
+}
+
+Tests.testBufferData = function(gl) {
+ assertOk("zero size data",
+ function(){gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(0), gl.STATIC_DRAW);});
+ assertFail("bad target",
+ function(){gl.bufferData(gl.TEXTURE_2D, new Float32Array([1,2,3]), gl.STATIC_DRAW);});
+// assertFail("array for data",
+// function(){gl.bufferData(gl.ARRAY_BUFFER, [1,2,3], gl.STATIC_DRAW);});
+ assertFail("bad usage",
+ function(){gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,2,3]), gl.TEXTURE_2D);});
+ assertFail("null data",
+ function(){gl.bufferData(gl.ARRAY_BUFFER, null, gl.STATIC_DRAW);});
+ assertFail("undefined data",
+ function(){gl.bufferData(gl.ARRAY_BUFFER, undefined, gl.STATIC_DRAW);});
+ assertOk(function(){gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Float32Array([1,2,3]), gl.STATIC_DRAW);});
+ throwError(gl, 'bufferData');
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ assertFail(function(){gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,2,3]), gl.STATIC_DRAW);});
+ throwError(gl, 'bufferData');
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ assertFail(function(){gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([1,2,3]), gl.STATIC_DRAW);});
+ throwError(gl, 'bufferData');
+}
+
+Tests.endUnit = function(gl, buf, ebuf) {
+ gl.deleteBuffer(buf);
+ gl.deleteBuffer(ebuf);
+}
+
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubData.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubData.html
new file mode 100644
index 0000000000..df03cf2835
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubData.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = getGLContext(canvas);
+ var buf = gl.createBuffer();
+ var ebuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuf);
+ return [gl, buf, ebuf];
+}
+
+Tests.testBufferSubData = function(gl, buf, ebuf) {
+ var data = [0,0,0,0, 1,0,0,0, 0,1,0,0];
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3,4]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Float32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 32, new Float32Array([1,1,1,1]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STATIC_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STREAM_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Float32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3,4]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STREAM_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Float32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3,4]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Int32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Int16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Int8Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint8Array([1,1,1,1]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.DYNAMIC_DRAW);
+
+ gl.bufferData(gl.ARRAY_BUFFER, 12, gl.STATIC_DRAW);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STATIC_DRAW);
+
+ gl.bufferData(gl.ARRAY_BUFFER, 12*4, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3,4]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Float32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 32, new Float32Array([1,1,1,1]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STATIC_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, 12*4, gl.STREAM_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Float32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3,4]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.STREAM_DRAW);
+ gl.bufferData(gl.ARRAY_BUFFER, 12*4, gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Float32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3,4]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Int32Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Int16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Int8Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint8Array([1,1,1,1]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*4);
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE), gl.DYNAMIC_DRAW);
+
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array(data), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Uint16Array([1,2,3,4]));
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array(data), gl.STREAM_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Uint16Array([1,2,3,4]));
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array(data), gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Uint16Array([1,2,3,4]));
+ assertEquals(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE), 12*2);
+ throwError(gl, "array bufferSubData");
+}
+Tests.testBufferSubDataElement = function(gl, buf, ebuf) {
+ var data = [0,0,0,0, 1,0,0,0, 0,1,0,0];
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array([1,2,3,4]));
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.STREAM_DRAW);
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array([1,2,3,4]));
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 16, new Uint16Array([1,1,1,1]));
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array([1,2,3,4]));
+ assertEquals(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE), 12*2);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(data), gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 4, new Uint8Array([1,1,1,1]));
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint8Array([1,2,3,4]));
+ assertEquals(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE), 12);
+ throwError(gl, "element array bufferSubData");
+}
+
+Tests.endUnit = function(gl, buf, ebuf) {
+ gl.deleteBuffer(buf);
+ gl.deleteBuffer(ebuf);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubDataBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubDataBadArgs.html
new file mode 100644
index 0000000000..a12adf8ff8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/bufferSubDataBadArgs.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var buf = gl.createBuffer();
+ var ebuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuf);
+ return [gl, buf, ebuf];
+}
+
+Tests.testBufferData = function(gl) {
+ var data = [0,0,0,0, 1,0,0,0, 0,1,0,0];
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STREAM_DRAW);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.STREAM_DRAW);
+ assertOk("zero length data",
+ function(){gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array(0));});
+ assertFail("number for data",
+ function(){gl.bufferSubData(gl.ARRAY_BUFFER, 0, 12);});
+ assertFail("bad target",
+ function(){gl.bufferSubData(gl.TEXTURE_2D, 0, new Float32Array([1,2,3]));});
+ assertFail("array for data",
+ function(){gl.bufferSubData(gl.ARRAY_BUFFER, 0, [1,2,3]);});
+ assertOk("floats in element buffer",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Float32Array([1,2,3]));});
+ assertFail("negative offset",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, -1, new Uint16Array([1,2,3]));});
+ assertFail("offset out of range",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 24, new Uint16Array([1,2,3]));});
+ assertFail("offset out of range",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 2400000, new Uint16Array([1,2,3]));});
+ assertFail("offset out of range",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 19, new Uint16Array([1,2,3]));});
+ assertFail("data too large",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array(data.concat([1])));});
+ assertOk("offset + data.length = end",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 18, new Uint16Array([1,2,3]));});
+ assertOk("offset Infinity",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, Infinity, new Uint16Array([1,2,3]));});
+ assertOk("offset -Infinity",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, -Infinity, new Uint16Array([1,2,3]));});
+ assertOk("offset NaN",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, NaN, new Uint16Array([1,2,3]));});
+ assertOk("good args",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array([1,2,3]));});
+ throwError(gl, 'bufferData0');
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ assertFail("setting buffer 0",
+ function(){gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([1,2,3]));});
+ throwError(gl, 'bufferData1');
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ assertFail("setting buffer 0",
+ function(){gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array([1,2,3]));});
+ throwError(gl, 'bufferData2');
+}
+
+Tests.endUnit = function(gl, buf, ebuf) {
+ gl.deleteBuffer(buf);
+ gl.deleteBuffer(ebuf);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2D.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2D.html
new file mode 100644
index 0000000000..8aaebf396d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2D.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var texCubeMap = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex, texCubeMap) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.deleteTexture(tex);
+ gl.deleteTexture(texCubeMap);
+}
+
+Tests.testTexImage2D = function(gl) {
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,1,1,0);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,2,1,0);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,1,2,0);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,16,16,0);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 15,15,1,1,0);
+ var valid_targets = [
+ gl.TEXTURE_2D,
+ 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
+ ];
+ valid_targets.forEach(function(t) {
+ assertOk(function(){gl.copyTexImage2D(t, 0, gl.RGBA, 0,0,1,1,0);});
+ });
+}
+Tests.testRoundtrip = function(gl) {
+ var sh = new Filter(gl, 'identity-flip-vert', 'identity-frag');
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var buf = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ assertEquals([255,0,0,255], [buf[0], buf[1], buf[2], buf[3]]);
+ // red texture
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,16,16,0);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // blue framebuffer
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ assertEquals([0,0,255,255], [buf[0], buf[1], buf[2], buf[3]]);
+ sh.apply(); // paint it with texture
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ assertEquals([255,0,0,255], [buf[0], buf[1], buf[2], buf[3]]);
+ sh.destroy();
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="identity-flip-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, 0.0, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="identity-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D Texture;
+
+varying vec4 texCoord0;
+void main()
+{
+ vec4 c = texture2D(Texture, texCoord0.st);
+ gl_FragColor = c;
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2DBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2DBadArgs.html
new file mode 100644
index 0000000000..802fbc971f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexImage2DBadArgs.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+Tests.testTexImage2D = function(gl) {
+ assertOk("height > backHeight", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 17,1,0);
+ });
+ assertOk("width > backWidth", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 1,17,0);
+ });
+ assertOk("x + width > backWidth", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16,0, 1,1,0);
+ });
+ assertOk("y + height > backHeight", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,16, 1,1,0);
+ });
+ assertOk("Negative X", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, -1,0, 1,1,0);
+ });
+ assertOk("Negative Y", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,-1, 1,1,0);
+ });
+ assertFail("Negative height", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, -1,1,0);
+ });
+ assertFail("Negative width", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 1,-1,0);
+ });
+ assertFail("Non 0 border", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 1,1,1);
+ });
+ assertFail("Negative border",function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 1,1,-1);
+ });
+ assertOk("Good Args", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 16,16,0);
+ });
+ assertFail("NPOT texture to > level 0", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 1, gl.RGBA, 0,0, 15,16,0);
+ });
+ assertFail("Bad target", function(){
+ gl.copyTexImage2D(gl.FLOAT, 0, gl.RGBA, 0,0, 16,16,0);
+ });
+ assertFail("Bad internal format", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.FLOAT, 0,0, 16,16,0);
+ });
+ assertFail("Negative level", function(){
+ gl.copyTexImage2D(gl.TEXTURE_2D, -1, gl.RGBA, 0,0, 16,16,0);
+ });
+}
+
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2D.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2D.html
new file mode 100644
index 0000000000..82262e3d68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2D.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var texCubeMap = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex,texCubeMap) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.deleteTexture(tex);
+ gl.deleteTexture(texCubeMap);
+}
+
+
+Tests.testTexImage2D = function(gl) {
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,16,16,0);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0,1,1);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0,2,1);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0,1,2);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0,16,16);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 15,15,1,1);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 1,1, 0,0,15,15);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 15,15, 0,0,1,1);
+ var valid_targets = [
+ gl.TEXTURE_2D,
+ 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
+ ];
+ valid_targets.forEach(function(t) {
+ assertOk(function(){
+ gl.copyTexImage2D(t, 0, gl.RGBA, 0,0,1,1,0);
+ gl.copyTexSubImage2D(t, 0, 0,0,0,0,1,1);
+ });
+ });
+}
+Tests.testRoundtrip = function(gl) {
+ var sh = new Filter(gl, 'identity-flip-vert', 'identity-frag');
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var buf = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ assertEquals([255,0,0,255], [buf[0], buf[1], buf[2], buf[3]]);
+ // red texture
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, document.getElementById('gl'));
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0,0,0,16,16);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // blue framebuffer
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ assertEquals([0,0,255,255], [buf[0], buf[1], buf[2], buf[3]]);
+ sh.apply(); // paint with texture
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ assertEquals([255,0,0,255], [buf[0], buf[1], buf[2], buf[3]]);
+ sh.destroy();
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="identity-flip-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, 0.0, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="identity-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D Texture;
+
+varying vec4 texCoord0;
+void main()
+{
+ vec4 c = texture2D(Texture, texCoord0.st);
+ gl_FragColor = c;
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2DBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2DBadArgs.html
new file mode 100644
index 0000000000..a170c6c78e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/copyTexSubImage2DBadArgs.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+Tests.testTexImage2D = function(gl) {
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0, 16,16, 0);
+ assertGLError(gl, gl.INVALID_VALUE, "width > dst tex width", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0, 17,1);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "height > dst tex height", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0, 1,17);
+ });
+ // The spec says the source image dimensions can be out of range.
+ assertOk("x > dst tex width", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 16,0, 1,1);
+ });
+ assertOk("y > dst tex width", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,16, 1,1);
+ });
+ assertOk("x < 0", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, -1,0, 1,1);
+ });
+ assertOk("y < 0", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,-1, 1,1);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "width < 0", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0, -1,1);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "height < 0", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0, 1,-1);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "xoffset < 0", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, -1,0, 0,0, 16,16);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "yoffset < 0", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,-1, 0,0, 16,16);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "dimension out of range", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 4,0, 0,0, 16,16);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "dimension out of range", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,4, 0,0, 16,16);
+ });
+ assertOk("x < 0 full width", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, -1,0, 16,16);
+ });
+ assertOk("y < 0 full height", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,-1, 16,16);
+ });
+ assertOk(function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, 0,0, 16,16);
+ });
+ assertGLError(gl, gl.INVALID_ENUM, "bad target", function(){
+ gl.copyTexSubImage2D(gl.FLOAT, 0, 0,0, 0,0, 16,16);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "", function(){
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, -1, 0,0, 0,0, 16,16);
+ });
+}
+
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/deleteBufferBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/deleteBufferBadArgs.html
new file mode 100644
index 0000000000..a373448631
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/deleteBufferBadArgs.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = getGLContext(canvas);
+ return [gl];
+}
+
+Tests.testDeleteBuffer = function(gl) {
+ assertThrowNoGLError(gl, "number ", function(){ gl.deleteBuffer(1); });
+ assertGLError(gl, gl.NO_ERROR, "null", function(){ gl.deleteBuffer(null); });
+ assertThrowNoGLError(gl, "0", function(){ gl.deleteBuffer(0); });
+ assertThrowNoGLError(gl, "false", function(){ gl.deleteBuffer(false); });
+ assertThrowNoGLError(gl, "true", function(){ gl.deleteBuffer(true); });
+ assertThrowNoGLError(gl, "{}", function(){ gl.deleteBuffer({}); });
+ var tex = gl.createTexture();
+ assertThrowNoGLError(gl, "tex as buf", function(){ gl.deleteBuffer(tex); });
+ var buf = gl.createBuffer();
+ assertOk(function(){ gl.deleteBuffer(buf); });
+ assertOk(function(){ gl.deleteBuffer(buf); });
+ assertOk(function(){ gl.deleteBuffer(buf); });
+ assertOk(function(){ gl.deleteTexture(tex); });
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawArrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawArrays.html
new file mode 100644
index 0000000000..7fdefbb636
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawArrays.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+var verts = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0];
+var normals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
+var texcoords = [0.0,0.0, 1.0,0.0, 0.0,1.0];
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var prog = new Shader(gl, 'vert', 'frag');
+ prog.use();
+ var sh = prog.shader.program;
+// log(gl.getShaderInfoLog(prog.shaders[1]));
+ var v = gl.getAttribLocation(sh, 'Vertex');
+ var n = gl.getAttribLocation(sh, 'Normal');
+ var t = gl.getAttribLocation(sh, 'Tex');
+ return [gl,prog,v,n,t];
+}
+
+Tests.setup = function(gl, prog, v,n,t) {
+ assert(0 == gl.getError());
+ return [gl, prog, v,n,t];
+}
+Tests.teardown = function(gl, prog, v,n,t) {
+ gl.disableVertexAttribArray(v);
+ gl.disableVertexAttribArray(n);
+ gl.disableVertexAttribArray(t);
+}
+
+Tests.endUnit = function(gl, prog, v,n,t) {
+ prog.destroy();
+}
+
+Tests.testDrawArraysVBO = function(gl, prog, v,n,t) {
+ var vbo = new VBO(gl, {size:3, data:Quad.vertices});
+ vbo.draw(v);
+ assert(0 == checkError(gl, "vbo.draw"));
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 5, 1);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 6);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 1, 5);});
+ vbo.destroy();
+ assert(0 == checkError(gl, "vbo.destroy"));
+}
+
+Tests.testDrawArraysVBOMulti = function(gl, prog, v,n,t) {
+ // creates VBOs for the quad arrays, binds them with
+ // vertexAttribPointer and calls drawArrays
+ var vbo = new VBO(gl,
+ {size:3, data:Quad.vertices},
+ {size:3, data:Quad.normals},
+ {size:2, data:Quad.texcoords});
+ vbo.draw(v, n, t);
+ assert(0 == checkError(gl, "vbo.draw"));
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 5, 1);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 6);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 1, 5);});
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo.vbos[1]);
+ gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 5, 1);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 6);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 1, 5);});
+ vbo.destroy();
+ assert(0 == checkError(gl, "vbo.destroy"));
+}
+
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+ attribute vec3 Vertex;
+ attribute vec3 Normal;
+ attribute vec2 Tex;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ gl_Position = vec4(Vertex * Normal, 1.0);
+ texCoord0 = vec4(Tex,0.0,0.0) + gl_Position;
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+ precision mediump float;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ vec4 c = texCoord0;
+ gl_FragColor = c;
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawElements.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawElements.html
new file mode 100644
index 0000000000..f0c3bb3d27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/drawElements.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+var verts = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0];
+var normals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
+var texcoords = [0.0,0.0, 1.0,0.0, 0.0,1.0];
+var indices = [0,1,2]
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var prog = new Shader(gl, 'vert', 'frag');
+ prog.use();
+ var sh = prog.shader.program;
+ var v = gl.getAttribLocation(sh, 'Vertex');
+ var n = gl.getAttribLocation(sh, 'Normal');
+ var t = gl.getAttribLocation(sh, 'Tex');
+ return [gl,prog,v,n,t];
+}
+
+Tests.setup = function(gl, prog, v,n,t) {
+ assert(0 == gl.getError());
+ return [gl, prog, v,n,t];
+}
+Tests.teardown = function(gl, prog, v,n,t) {
+ gl.disableVertexAttribArray(v);
+ gl.disableVertexAttribArray(n);
+ gl.disableVertexAttribArray(t);
+}
+
+Tests.endUnit = function(gl, prog, v,n,t) {
+ prog.destroy();
+}
+
+Tests.testDrawElementsVBO = function(gl, prog, v,n,t) {
+ var vbo = new VBO(gl,
+ {size:3, data:Quad.vertices},
+ {elements:true, data:Quad.indices});
+ vbo.draw(v);
+ assert(gl.NO_ERROR == checkError(gl, "vbo.draw"));
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 5, gl.UNSIGNED_SHORT, 1*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 0, gl.UNSIGNED_SHORT, 2*1);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 5*2);});
+ vbo.destroy();
+ assert(gl.NO_ERROR == checkError(gl, "vbo.destroy"));
+}
+
+Tests.testDrawElementsVBOMulti = function(gl, prog, v,n,t) {
+ // creates VBOs for the quad arrays, binds them with
+ // vertexAttribPointer and calls drawElements
+ var vbo = new VBO(gl,
+ {size:3, data:Quad.vertices},
+ {size:3, data:Quad.normals},
+ {size:2, data:Quad.texcoords},
+ {elements:true, data:Quad.indices});
+ vbo.draw(v, n, t);
+ assert(gl.NO_ERROR == checkError(gl, "vbo.draw"));
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 5, gl.UNSIGNED_SHORT, 1*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 0, gl.UNSIGNED_SHORT, 2*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 5*2);});
+ assertGLError(gl, gl.INVALID_OPERATION, "count + offset out of range",
+ function(){gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 6*2);});
+ assertGLError(gl, gl.INVALID_OPERATION, "count + offset out of range 2",
+ function(){gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 1*2);});
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo.vbos[1]);
+ gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 5, gl.UNSIGNED_SHORT, 1*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 0, gl.UNSIGNED_SHORT, 2*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0*2);});
+ assertOk(function(){gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 5*2);});
+ assertGLError(gl, gl.INVALID_OPERATION, "count + offset out of range 3",
+ function(){gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 6*2);});
+ assertGLError(gl, gl.INVALID_OPERATION, "count + offset out of range 4",
+ function(){gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 1*2);});
+ vbo.destroy();
+ assert(gl.NO_ERROR == checkError(gl, "vbo.destroy"));
+}
+
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+ attribute vec3 Vertex;
+ attribute vec3 Normal;
+ attribute vec2 Tex;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ gl_Position = vec4(Vertex * Normal, 1.0);
+ texCoord0 = vec4(Tex,0.0,0.0) + gl_Position;
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+ precision mediump float;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ vec4 c = texCoord0;
+ gl_FragColor = c;
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTests.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTests.html
new file mode 100644
index 0000000000..54c1cb0603
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTests.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testIs = function(gl) {
+ var tex = loadTexture(gl, document.getElementById('2d'));
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var fbo = new FBO(gl, 1, 1);
+ fbo.use();
+ var prog = gl.createProgram();
+ var sh1 = gl.createShader(gl.VERTEX_SHADER);
+ var sh2 = gl.createShader(gl.FRAGMENT_SHADER);
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ assert("tex", gl.isTexture(tex));
+ assert("fbo", gl.isFramebuffer(fbo.fbo));
+ assert("rbo", gl.isRenderbuffer(fbo.rbo));
+ assert("prog", gl.isProgram(prog));
+ assert("sh1", gl.isShader(sh1));
+ assert("sh2", gl.isShader(sh2));
+ assert("buf", gl.isBuffer(buf));
+ gl.deleteTexture(tex);
+ gl.deleteFramebuffer(fbo.fbo);
+ gl.deleteRenderbuffer(fbo.rbo);
+ gl.deleteProgram(prog);
+ gl.deleteShader(sh1);
+ gl.deleteShader(sh2);
+ gl.deleteBuffer(buf);
+ // NOTE: we purposely do not unbind things.
+ assert("tex", !gl.isTexture(tex));
+ assert("fbo", !gl.isFramebuffer(fbo.fbo));
+ assert("rbo", !gl.isRenderbuffer(fbo.rbo));
+ assert("prog", !gl.isProgram(prog));
+ assert("sh1", !gl.isShader(sh1));
+ assert("sh2", !gl.isShader(sh2));
+ assert("buf", !gl.isBuffer(buf));
+}
+
+</script>
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+ <canvas id="2d" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTestsBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTestsBadArgs.html
new file mode 100644
index 0000000000..4d7548140b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/isTestsBadArgs.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas_element" width="1" height="1"></canvas>
+<script type="application/javascript">
+
+function runTest()
+{
+ shouldThrow("gl.isBuffer(gl.createFramebuffer())");
+ shouldThrow("gl.isBuffer(gl.createProgram())");
+ shouldThrow("gl.isBuffer(gl.createRenderbuffer())");
+ shouldThrow("gl.isBuffer(gl.createShader(gl.VERTEX_SHADER))");
+ shouldThrow("gl.isBuffer(gl.createTexture())");
+
+ shouldThrow("gl.isFramebuffer(gl.createBuffer())");
+ shouldThrow("gl.isFramebuffer(gl.createProgram())");
+ shouldThrow("gl.isFramebuffer(gl.createRenderbuffer())");
+ shouldThrow("gl.isFramebuffer(gl.createShader(gl.VERTEX_SHADER))");
+ shouldThrow("gl.isFramebuffer(gl.createTexture())");
+
+ shouldThrow("gl.isProgram(gl.createBuffer())");
+ shouldThrow("gl.isProgram(gl.createFramebuffer())");
+ shouldThrow("gl.isProgram(gl.createRenderbuffer())");
+ shouldThrow("gl.isProgram(gl.createShader(gl.VERTEX_SHADER))");
+ shouldThrow("gl.isProgram(gl.createTexture())");
+
+ shouldThrow("gl.isRenderbuffer(gl.createBuffer())");
+ shouldThrow("gl.isRenderbuffer(gl.createFramebuffer())");
+ shouldThrow("gl.isRenderbuffer(gl.createProgram())");
+ shouldThrow("gl.isRenderbuffer(gl.createShader(gl.VERTEX_SHADER))");
+ shouldThrow("gl.isRenderbuffer(gl.createTexture())");
+
+ shouldThrow("gl.isShader(gl.createBuffer())");
+ shouldThrow("gl.isShader(gl.createFramebuffer())");
+ shouldThrow("gl.isShader(gl.createProgram())");
+ shouldThrow("gl.isShader(gl.createRenderbuffer())");
+ shouldThrow("gl.isShader(gl.createTexture())");
+
+ shouldThrow("gl.isTexture(gl.createBuffer())");
+ shouldThrow("gl.isTexture(gl.createFramebuffer())");
+ shouldThrow("gl.isTexture(gl.createProgram())");
+ shouldThrow("gl.isTexture(gl.createRenderbuffer())");
+ shouldThrow("gl.isTexture(gl.createShader(gl.VERTEX_SHADER))");
+
+ shouldBe("gl.isBuffer(null)", "false");
+ shouldBe("gl.isBuffer(undefined)", "false");
+
+ shouldBe("gl.isFramebuffer(null)", "false");
+ shouldBe("gl.isFramebuffer(undefined)", "false");
+
+ shouldBe("gl.isProgram(null)", "false");
+ shouldBe("gl.isProgram(undefined)", "false");
+
+ shouldBe("gl.isRenderbuffer(null)", "false");
+ shouldBe("gl.isRenderbuffer(undefined)", "false");
+
+ shouldBe("gl.isShader(null)", "false");
+ shouldBe("gl.isShader(undefined)", "false");
+
+ shouldBe("gl.isTexture(null)", "false");
+ shouldBe("gl.isTexture(undefined)", "false");
+}
+
+description("Tests type checking for isX() functions");
+var gl = WebGLTestUtils.create3DContext(document.getElementById("canvas_element"));
+runTest();
+var successfullyParsed = true;
+</script>
+
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixels.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixels.html
new file mode 100644
index 0000000000..61589b0a80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixels.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testReadPixels = function(gl) {
+ var id = new Uint8Array(16 * 16 * 4);
+ assertOk(function(){gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);});
+ assertOk(function(){gl.readPixels(0,0,16,16,gl.RGBA, gl.UNSIGNED_BYTE, id);});
+ assertOk(function(){gl.readPixels(15,15,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);});
+}
+Tests.testReadPixelsRGBA = function(gl) {
+ gl.clearColor(1, 0, 1, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var id = new Uint8Array(4);
+ gl.readPixels(1,2,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+ assertArrayEquals([255, 0, 255, 0], id);
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixelsBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixelsBadArgs.html
new file mode 100644
index 0000000000..3d155ed61b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/readPixelsBadArgs.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="../../../js/webgl-test-utils.js"></script>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+<canvas id="c" width="128" height="128"></canvas>
+<img id="i">
+<script type="application/javascript">
+var wtu = WebGLTestUtils;
+var defaultImgUrl = "https://get.webgl.org/conformance-resources/opengl_logo.jpg";
+var localImgUrl = "../../../resources/opengl_logo.jpg";
+
+Tests.autoinit = false; // Prevents the test from running until the image is loaded
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testReadPixels = function(gl) {
+ // we can't know if this is going to fail because of negative width
+ // or because the buffer size doesn't match the dimensions.
+ assertSomeGLError(gl, "negative width",
+ function(){gl.readPixels(0,0,-1,1, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));});
+ assertSomeGLError(gl, "negative height",
+ function(){gl.readPixels(0,0,1,-1, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));});
+ assertOk("negative x",
+ function(){gl.readPixels(-1,0,1,1, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));});
+ assertOk("negative y",
+ function(){gl.readPixels(0,-1,1,1, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));});
+ assertOk("height > backbuffer height",
+ function(){gl.readPixels(0,0,16,17, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(16*17*4));});
+ assertOk("width > backbuffer width",
+ function(){gl.readPixels(0,0,17,16, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(17*16*4));});
+ assertOk("width, height = 0",
+ function(){gl.readPixels(0,0,0,0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(0));});
+ // we can't know if this is going to fail because of negative width
+ // or because the buffer size doesn't match the dimensions.
+ assertSomeGLError(gl, "bad format",
+ function(){gl.readPixels(0,0,1,1, gl.FLOAT, gl.UNSIGNED_BYTE,
+ new Uint8Array(4*4));});
+ // we can't know if this is going to fail because of negative width
+ // or because the buffer size doesn't match the dimensions.
+ assertSomeGLError(gl, "bad type",
+ function(){gl.readPixels(0,0,1,1, gl.ALPHA, gl.FLOAT,
+ new Uint8Array(1*4));});
+}
+
+Tests.testReadPixelsSOPIMG = function(gl) {
+ var img = document.getElementById("i");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ // SOP failure
+ assertThrowNoGLError(gl, "throw because img is from another domain",
+ function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);});
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ assertOk("canvas still origin-clean",
+ function(){gl.readPixels(0,0,1,1, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));});
+ gl.deleteTexture(tex);
+}
+Tests.testReadPixelsSOPCanvas = function(gl) {
+ var img = document.getElementById("i");
+ var c = document.getElementById("c");
+ c.getContext("2d").drawImage(img, 0, 0);
+ assertFail("canvas throws because not origin clean",
+ function(){c.getContext("2d").getImageData(0,0,1,1);});
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ // SOP failure
+ assertThrowNoGLError(gl, "throw because canvas is not origin clean",
+ function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);});
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ assertOk("canvas still origin-clean",
+ function(){gl.readPixels(0,0,1,1, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));});
+ gl.deleteTexture(tex);
+}
+
+Tests.endUnit = function(gl) {
+};
+
+(async function() {
+ const img = document.getElementById('i');
+ try {
+ await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
+ } catch (e) {
+ testFailed(`Image setup failed (${e}).`);
+ finishTest();
+ return;
+ }
+ initTests();
+})();
+</script>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2D.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2D.html
new file mode 100644
index 0000000000..5da8b6313f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2D.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var texCubeMap = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex,texCubeMap) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.deleteTexture(tex);
+ gl.deleteTexture(texCubeMap);
+}
+
+Tests.testTexImage2D = function(gl) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0]));
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0]));
+ var valid_targets = [
+ gl.TEXTURE_2D,
+ 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
+ ];
+ valid_targets.forEach(function(t) {
+ assertOk(function(){gl.texImage2D(t, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));});
+ });
+}
+
+Tests.testTexImage2DNull = function(gl) {
+ assertOk(function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);});
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DBadArgs.html
new file mode 100644
index 0000000000..c818d1b1a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DBadArgs.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+Tests.testTexImage2D = function(gl) {
+ var data = new Uint8Array(4);
+ assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,1,0,gl.RGBA,gl.UNSIGNED_BYTE, data);
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,2,0,gl.RGBA,gl.UNSIGNED_BYTE, data);
+ });
+ assertGLError(gl, gl.INVALID_ENUM, "bad target", function(){
+ gl.texImage2D(gl.FLOAT, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
+ });
+ assertGLErrorIn(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE],
+ "bad internal format/format", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.FLOAT, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "border > 0", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,48,gl.RGBA,gl.UNSIGNED_BYTE, null);
+ });
+ // The spec says zero size is OK. If you disagree please list the section
+ // in the spec that details this issue.
+ assertOk("zero size", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "negative width", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, -1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "negative height", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,-1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
+ });
+ assertGLErrorIn(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "bad format", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null);
+ });
+ assertGLErrorIn(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "bad type", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.TEXTURE_2D, null);
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array(3));
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "format and type incompatible",function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_SHORT_5_6_5, null);
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "format and type incompatible",function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1,1,0,gl.RGB,gl.UNSIGNED_SHORT_4_4_4_4, null);
+ });
+
+ assertThrows(gl, true, "too few args", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE);
+ });
+ assertThrows(gl, false, "too many args", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null, null);
+ });
+
+ assertThrows(gl, true, "bad TexSourceType", function(){
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, window);
+ });
+ assertThrows(gl, true, "fake TexSourceType", function(){
+ var fakeObj = {
+ get width() { throw 7 },
+ get height() { throw 7 },
+ data: new Uint8ClampedArray(10)
+ };
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, fakeObj);
+ });
+}
+
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTML.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTML.html
new file mode 100644
index 0000000000..5cc78d1635
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTML.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="../../../js/webgl-test-utils.js"></script>
+<script id="identity-flip-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, 0.0, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="identity-hflip-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(1.0-Tex.s, Tex.t, 0.0, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="identity-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D Texture;
+
+varying vec4 texCoord0;
+void main()
+{
+ vec4 c = texture2D(Texture, texCoord0.st);
+ gl_FragColor = c;
+}
+</script>
+</head>
+<body>
+<canvas id="gl" width="256" height="256"></canvas>
+<canvas id="c" width="256" height="256"></canvas>
+<img id="i" width="256" height="256" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAATVElEQVR4nO3d+VPUd57Hcf2b9k9Y+z44+qK7OZoGFVA5VfBGzah9cxpNzGEOoRua5lBEue/DK4fZ7MapmSm3Mlshu8xOdCpDJt3v/aEBAUHAOMG4z0fV53fqU/V6fd7fT/e32bEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwOvBkar7l+3+GwBsk8xUrT0rTb8vx2Q45janlu7YsWPnsgXgTeYwak85U3Xv5ZiM3+XbUh/l2dICBc6080WZ1ur92baSHRQB8GayGdUWu1HzoSNFO+ZM1f2cbTLM51lT5woc5rkDObbZ/Vm2SEm23VvsyjhV5nJQBsCbxGZQVtmN6p4Mo/YPdqNGHKlayUrXJ9zWlESh0xIvzsmYL3HZ54pzMm6VuRyRMpfTW+pyUAbAm8BmVNVnGNTTdqP6vzOMGrGnaMSZqpNsk17ybKlS6DTL/ixbotRlj5flOubL3I65MpfjVrnbEalYKINSl335vQGA3wKbUW2xGdWRDKP66wyjWhYLwJGiFWeaTrJNBnFbU2SP3ST7s6xSmmuXcrczUe52xstzHfPlbsdcudt5qyzX3lKWlxkszXGeK8mxnyzJySjeQRkArzebQVllM6p7bUb149UF4EjVSmaaTrLS9eKypMgee7ocyLZJmdshFXmZUpHnXFEGB/OzJsrdjqEyt/NmWa49XJbt9Ja6Mk4Vu7hEBF5LNr2q3mZQz9gM6u9XFEBqsgCcaTrJXJgEci0pstdhkv3ZNinNTZbAofwsOZSfJQfzMqU8z5kodzsSZbmOeIXb+XW52zFa5nLcKnPZI2ULl4jFfKIAvB7MOrXFZlBHbAb11zaj+kmGUbNuAWSm65dKYHdGmhRlWqQ8zyFHCnLk+L5cOV6UK0cKXVK5J1sO5mdKhdspZavKoDTX0VPiciTLIHtFGVAIwK/NYlBW2fTqXptB/dhmSJ7+LyqArHS95JiTJVDgNEllQZZ4KgulrrpU6qtLJXBsv5wt3yMn9rvlaIFLDi8vg1xH4mB+5p+Wl0Fpjr2lJMcRLM6ynyvOzjhxIIt7A+BXY9Gr6q0L4/9SAaRoxL7w/L9WAWSbDJJrTZFid4Z4jxZJU/1xufHhOem+ek6il0/LB74qaTxTJoGj++Vs2R45vj9XjhTkyOHdC48JC2VwaHfmnyrczn+vcDsmynLtQyU5GTeLczLCpTk2T3GW7VhxVsae7d4f4I1l1qktVoM6YjOovrYa1D8sFoB9WQE415kA8u1pcvRAjnwUOiLDLQG5190o9242ylRHnQyG/XLz6nmJXqqWD3yV0nC6VPxH98nZst1yfF+uHC10SdXebDmUnyyDqoLs7w7lZ35b7nb8scxt/7dSl32kJCejqyQn40pJTkbZDiYC4NWzaJVVVr2q12ZQPbYa1H9fuwB0SwWQla6XLFOyAAoyTfLW4T3SfuWM3L3RIA/7L8vD/svyZe8l+ezW23Kvu1EmO2ploNkn3VfPSevb1fK+t1Iaz5RJ7cli8R0pktOl+XKsKFkGBxfKoHJv1l8P5mf+uSLP8fvyXMdMmdsRKXc5qotdGQXbvV/AG8WiV9Vb9aoZq141azOoxWbcXAHkWlOkJC9Dak8Xy61PL8iDnotLBbBUBH2X5Yvbl+RBz0W5e6NBJtprpL/ZJzc/Oi/XP3hLWi6ekvc8h6WuukS8Vc/KYPEC8WhhzpOqguzvKvdmfXV4d2b3wfzM9w/lZTENAK+CWaewWHWqiE2v+tqqV/2w2QLINhkkP2Nh/K89ImNtIfmi99Kz8Pcl15dL65J80XtJPr/1tty/2Sh3uxvkzvV6GY+FpO+aV65/8DuJXDwpVzyHpO7UQhmU5MvRIpdU7c2RQ7uz5MR+9x+OFbnuHi3MiVQVuKoP784u2u79A37TLFpllVWn6rXqVY+tetWPGxbAsgvAvU6TvHVot8SunJY7N+rly761g/9lb3J9sWx9fvuSfH77bXnQc1HudTfITFedjLWFpPeaR7o+eEvCjSflyoVDUlddKsHjB+TC4UI5VZwnVQU5ibcq9nx1ujS/58QB99XqYnf5DqYB4OVYdM/Gf6te9Y/k8//GBeCyGKXEnSE11Qek55Pzcv9m48rQrxP8L25fki9uvy2fr1qf3bqYnAxuNMh0Z52MRINy+1OPXP/wd9J+5Yw015+Qd84flJqTxXLhcIGcLM77+UhBzt8uVBa2nqvce/ZsxZ6y7d5L4Ddlcfy36FVfW/SqH6wGlawugMWvATvTlhWAySB5GalydH+OfFRzREajQfn81tvrh/6FwV9cF+WzWxflwa2Lcr/notzrbpSZ6/Uy1VUnkx21MtwSkJ5PLkjHe2elqf64XD53UEInDiQuHC6Yry7Omz1W5HrY+FbF4R1MA8DmWLTKKsuy8d9qUL+wAJZ/C3CPM13OHtwtbe+elunr9fLFusF/PvSf31o7+A96nq37PRflfk+j3L+Z/Fjx7o0Gme6qk4n2Ghlq8UvPx+el/coZuVZ3XC6fq/i57lTx32pOHngUOlUc/jR4lEtCYCMWnareolfNWPSqWatB9dOaBbDGl4BcFqMUu20SOnVAbn58Tu52N27qtP98g9A/WAz9QvAX173FEuhukLvdDcnJoLNWxmM1Mhjxy82Pzknn+2cSsXdPz4cbT8x+GKh8+FHwSO0OSgBYm1mnsJh1qohFr1wY/5XxZwWw/teAs9KTvwtwZH+2XA1VyXBrUB70XFz/tF9nzN9K8O91N8i9hfAvrjs3GuTOjXqZXnhEGG+vkdFoUAbD/p97Pj7/t56r57/pu+b5pOXd6qPbvdfAa8ei3VVl0al6LXrlY4tO+aNFr0pstgD2ONLlzMHdEn2nWqY66+SzlxzzHywb858L/TrBv3vjWfgX18z15JruqpOpzlqZaA8lxmKhv49Gg3/oD/s+3u69Bl47Fp2i3qJVzVh0ylmrTvmTVZ+8AFz5HsDzBZBjNkpxrk2Cpw5I90fn5M6Nhhee9lsOfvfmg3/n+rPwz1yvk5muOpleWJMdtfHJjprvJjtqKABgueT4r4iYdcqvzbpdP1j0yvjqArCv9SJQul7ctlSp2pctHwYrZaglIPdvNq5/2r/gYm9Twb+x9eBPd9XJVHISmJ/qrP1murOGRwBgOZN2V5VFp+y1aBfGf50ysVQAa3wHYLEAstL1stuRLqcr8qX18imZ7KiVBz0XXxj6jZ/vNxn86xsHP/kIUCdTnXXx6c7av0x11PRs914Drx2TTlFv0ipmzDrlrEWn/MmiV8lmCiDbbJADuTYJntwvN67+Tmau1ydDvmbot36x9yz49S8Z/NrFNT/dVfv7qc66k9u918BrxaxePf4r4hsVgHPh9wBzrSlSVZQtHwQqZTDil7vdjVs77bcY/JmtB1+mOmsTkx21T6a6ake2e6+B145Ju6vKpFP2mrTKx2bts/F/8VuALyqA3fY0OV2eLy2XTspEe43cf8Gz/TYEXyY7amWyoyY+1VHz/VRnXfN27zXw2lka/7XKWYtW+ZNFp5TNFEC2ySD7XVYJnNgnXR++JdNddZs+7X+d4NfKZEeNTHbUzE921Dya5PIPWClNrbCYtcnx36Td9YNZp4hbdKqNC2Bh/K8szJL3/YdlIOyTOzcatvwx3sY3+r8o+DLZEUpMtNc8mehg/AeeY1LvqjJplb0mjeKxWav40axVJlYXwFpvAmam6STfnibVZXkSefukjMVCcrd7EyP+eqf9loJfu2HwJzpqZKK9RsbbQ/HJ9tD3k501jP/AaiaNot6kSY7/Zq3iJ7NOKYsXgC8qgCyTQfblWMV/fJ90fnBWJjtrV4z3Wzntn7vRv/586Lca/GcrND/RHno02c74D6yQplZYTFpFxKRVLI3/Kwvg+ReB7CnJ3wFwWVLkcGGWvOc/LP3NXpm5Xv/LT/tNBn9yE8EfT4Y/MR4LPRlvDzH+A6uZNYpKk3ZXb/rC+G/SKhKbLYC8jDQ5VZYn4YsnZLQtKHdubC70mx3zf0nwx9tDMh4LyVgsFB+PBb8fb2f8B56TrlHUp2sV0yaNYmn830wBZKXrZV+2RXzH90nH+2dloqMmWQCv4LR/+eCHloK/EH4ZjwXnx2PBR2PtQcZ/YDmTRpmarlY0mTS7vkrTKP5q0ip+NuuUYtmgABypWnFZjHKoIFOueA9JX5NHprvqNh36zZ72vyT4C+FPjLYFn4zHgoz/wGomza7d6ZpdMZNG8Y1Jo3hi1i48/2+iAPIyUuVkqVuaGk/ISDQoM9df3Wm/Mvg1Ww7+WCwkY21BGW0Lxkfbgt+PxUKM/8BqaZpdu9PUiiaTRvGVSav4y9InABsUQGa6XoqyLeI9ViTt752R8fbQqsC/4tN+i8EfawvKaDQoI9HA/Ghb8JuxKOM/8ByT5l9T09SKQLpGMWTSKv7TrFU8NeuUieUFYFv1YyCOVK3kmJPj/7veg9J7zSNTnbWv6LR/BcFfWCPRQHwkGvjLSDTAm3/AetLVyjyTRvmOSauYNOsU35p1yn9sVABuW6qcLM2Vaw3HZbg1INNdr+a0X/sz/K0FfzQalNFoIHn6RwO/H2kL8uYf8CImza5Ck27Xe2atcsqiU8bXLYAUjWSm66QwyyzeY4USu3JaxmKhtUP/i0/7mhWhXxH8tvWCH5SRaEBGo4HESKv/yWhrgMs/YDPSdcois1bxvkWnfGrRK+NrFYA9RSvZZoMc3OuUdzwH5fa1CzLRUfNPPe3H1zjt1wv+4hpuDcRHooHvR6IBLv+AzTLrlEVmnfKhRad8al3z58C04ralyImSXLnWcEyGWv0y2VkrU13Ph/6lTvsNgj+6QfBHWgMy3BqQ4Vb//HBr4NFI1M/lH7AVFr0qYNGrHlr1qqc2gyq+/E1AZ5pOCrNM4jlaIG1XTstoW/Cfd9q/VPADMtzqTwy3+J8MM/4DL2XnihIwquI2o1rsKRrJNhmkYq9DLl+okFufnJfx9ppnoV/vc/utnvaxNcb8TQU/IMOtfhlq8ceHW/zfD0cDF7Z7I4Hfqp02vSpg06se2gzqpxlGTdyeopFca4ocL3HJp/VHZTDik4mOzY34L33ab+7EXwz+wvLND7cEbo20BjK3exOB37KdNqM6YDOoH2YY1U+dabp4QaZJLhzZK9F3q2UkGpCJDU/70Ks77TcMvl+GWnyJwYjvyVBL4J3t3jzgTbDTZlQHMoyah9lm/dOKPc74pfPl0vPxORmLhX6d035TwV9YEV98sMU/NRDm8g94VXbaU7UBl8X48ESJ6+kn9Ud+Hgh7EuPtoVdz2rdtJvQvDv5gxLewvH8ciHg7hloClu3eNOBNstNtSw34jxc9bH2nenaoxTc33h6aH4uF4uPtwcR48n/u/RNO+80G3ydDEd//DIR99wbCvsbt3izgTbTzaqgy0PPxufBINBAbbw89Go+FZsdjobnx9tDcaCw4P9oWjI/FgomxWCAx+gpO++G1xvxVwR+M+GQw7P1xMOx7PBj29fZHvFXbvVHAm2rn4prsrKkd6wiFR9tDsfH2mthILPRorC04O9YWmhuNheZG2wLzI9FgfLQtkBiNBhLPhf4XnPaLayDik4GwTwbC3v8daPY+HIj4Pupv9jL+A7+CncvXeHtN7WgsGB6NhWKjsVBsJBp8NBoNzo5EA3MLa364NRAfafUnhpPr5U77lcGXgbD37wNhz5/7m70jA2HPmW3eE+D/rZWF0BasHW4LhkeigdhILBQbbg08Gm4NzA63+OeGW/xzQ63++aEWf3yoxZdIrmWhb3k+9INLoV8KvvQ3e+MDzd4f+ps9/9Ef9rYNRHyObd4DAAtWFMJoW7B2uDUYHooGYkPRQGyoxf9oqMU3OxTxzQ1FfHNDLb75oYgvPhjxJpZWeO3gJ8PvSfQ3eX8aCHtn+5u9M33NXP4Br7MVhTDcGqgdbvWHB1v9scFWf2ww4n80GPHNDoa9c4MR39xg2Ds3EPbOD4S98YGwJzEQ9iT6m73S3+yVvmbPfH+zZ76vyfO0v9n7p75mb29/M5d/wG/Jc4Uw1OIP90f8scGIP9Yf8ccGwr5HA2Hv7ECzd26g2TvXlwx9vK/Z821/s+e/+po83/Y3eT7ra/Y0cfkH/LbtXL2GWny1A2FfuC/sjfWHvbH+Zs+jvrD3Zm+TZ6i3yTPW1+yZ7GvyXO9r9vi3908H8M+wohB6m7xlt695Tw6EfecGw15ff5Pnnb5mT6D32oUD2/x3AvgV7dyxY8fOgSavu7/Jk9V3zave7j8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICV/g9tPJEQu1XvmQAAAABJRU5ErkJggg==">
+<img id="i2">
+
+<script>
+var wtu = WebGLTestUtils;
+var defaultImgUrl = "https://get.webgl.org/conformance-resources/thunderbird-logo-64x64.png";
+var localImgUrl = "../../../resources/thunderbird-logo-64x64.png";
+
+Tests.autoinit = false; // Prevents the test from running until the image is loaded
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ gl.viewport(0,0,canvas.width,canvas.height);
+ gl.clearColor(0,0,1,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.disable(gl.DEPTH_TEST);
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var texCubeMap = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap);
+ return [gl]
+}
+
+Tests.teardown = function(gl, tex, texCubeMap) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.deleteTexture(texCubeMap);
+}
+
+Tests.testTexImage2D = function(gl) {
+ gl.enable(gl.BLEND);
+ var img = document.getElementById('i');
+ var c = document.getElementById('c');
+ var ctx = c.getContext('2d');
+ ctx.drawImage(img,0,0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ var f = new Filter(gl, 'identity-flip-vert', 'identity-frag');
+ gl.blendFunc(gl.ONE, gl.ZERO);
+ f.apply();
+ f.destroy();
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ f = new Filter(gl, 'identity-hflip-vert', 'identity-frag');
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ f.apply();
+ f.destroy();
+ var valid_targets = [
+ gl.TEXTURE_2D,
+ 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
+ ];
+ valid_targets.forEach(function(t) {
+ assertOk(function(){gl.texImage2D(t, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);});
+ assertOk(function(){gl.texImage2D(t, 1, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);});
+ });
+}
+
+Tests.testTexImage2DNonSOP = function(gl) {
+ var img = document.getElementById('i2');
+ var c = document.getElementById('c');
+ var ctx = c.getContext('2d');
+ ctx.drawImage(img,0,0);
+ assertThrowNoGLError(gl, "texImage2D with cross-origin image should throw exception.",
+ function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);});
+ assertThrowNoGLError(gl, "texImage2D with dirty origin canvas should throw exception.",
+ function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);});
+}
+
+Tests.endUnit = function(gl) {
+};
+
+(async function() {
+ const img = document.getElementById('i2');
+ try {
+ await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
+ } catch (e) {
+ testFailed(`Image setup failed (${e}).`);
+ finishTest();
+ return;
+ }
+ initTests();
+})();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTMLBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTMLBadArgs.html
new file mode 100644
index 0000000000..0953cd8884
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texImage2DHTMLBadArgs.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<meta charset="utf-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ return [gl, tex];
+}
+
+Tests.testTexImage2D = function(gl) {
+ var b = document.createElement('b');
+ var div = document.createElement('div');
+ var c = document.getElementById('c');
+ assertFail("bad element b",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, b); });
+ assertFail("bad element div",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, div); });
+ assertFail("no element",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, 0); });
+ assertFail("string as data",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, "foo"); });
+ assertOk("canvas as data",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertFail("bad target",
+ function() {gl.texImage2D(gl.FLOAT, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+}
+
+Tests.endUnit = function(gl, tex) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+<canvas id="c" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2D.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2D.html
new file mode 100644
index 0000000000..ef0912aa8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2D.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var texCubeMap = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex,texCubeMap) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.deleteTexture(texCubeMap);
+}
+
+Tests.testTexSubImage2D = function(gl) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 2,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,2,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 1,0, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,1, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 1,1, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texImage2D(gl.TEXTURE_2D, 1,gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texSubImage2D(gl.TEXTURE_2D, 1, 0,0, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ var valid_targets = [
+ gl.TEXTURE_2D,
+ 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
+ ];
+ valid_targets.forEach(function(t) {
+ assertOk(function(){
+ gl.texImage2D(t, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ gl.texSubImage2D(t, 0, 0,0, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ });
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DBadArgs.html
new file mode 100644
index 0000000000..9573607b3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DBadArgs.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ return [gl]
+}
+
+Tests.teardown = function(gl,tex) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+Tests.testTexImage2D = function(gl) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));
+ assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 2,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 1,2,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_ENUM, "bad target", function(){
+ gl.texSubImage2D(gl.FLOAT, 0, 0,0, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "width out of range", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 3,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "height out of range", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 1,3,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "dimension out of range", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D,0, 1,1, 2,1, gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "dimension out of range", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D,0, 1,1, 1,2, gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]));
+ });
+ assertOk("zero size", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 0,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertSomeGLError(gl, "negative width", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, -1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertSomeGLError(gl, "negative height", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 1,-1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "negative x", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,-1,1,1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_VALUE, "negative y", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0,1,-1,1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLErrorIn(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], "bad format", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1,gl.FLOAT,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
+ });
+ assertGLErrorIn(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], "bad type", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1,gl.RGBA,gl.TEXTURE_2D, new Uint8Array([0,0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "format does not match internal format", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1,gl.RGB,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0]));
+ });
+ assertGLError(gl, gl.INVALID_OPERATION, "type does not match original", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1,gl.RGBA,gl.UNSIGNED_SHORT_4_4_4_4, new Uint16Array([0]));
+ });
+
+ assertThrows(gl, true, "too few args", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE);
+ });
+ assertThrows(gl, false, "too many args", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]), null);
+ });
+
+ assertThrows(gl, true, "bad TexSourceType", function(){
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, window);
+ });
+ assertThrows(gl, true, "fake TexSourceType", function(){
+ var fakeObj = {
+ get width() { throw 7 },
+ get height() { throw 7 },
+ data: new Uint8ClampedArray(10)
+ };
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, fakeObj);
+ });
+}
+
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTML.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTML.html
new file mode 100644
index 0000000000..4f8ec2aa09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTML.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript" src="../../../js/webgl-test-utils.js"></script>
+<script id="identity-flip-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, 0.0, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="identity-hflip-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(1.0-Tex.s, Tex.t, 0.0, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="identity-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D Texture;
+
+varying vec4 texCoord0;
+void main()
+{
+ vec4 c = texture2D(Texture, texCoord0.st);
+ gl_FragColor = c;
+}
+</script>
+</head><body>
+<canvas id="gl" width="256" height="256"></canvas>
+<canvas id="c" width="256" height="256"></canvas>
+<img id="i" width="256" height="256" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAATVElEQVR4nO3d+VPUd57Hcf2b9k9Y+z44+qK7OZoGFVA5VfBGzah9cxpNzGEOoRua5lBEue/DK4fZ7MapmSm3Mlshu8xOdCpDJt3v/aEBAUHAOMG4z0fV53fqU/V6fd7fT/e32bEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwOvBkar7l+3+GwBsk8xUrT0rTb8vx2Q45janlu7YsWPnsgXgTeYwak85U3Xv5ZiM3+XbUh/l2dICBc6080WZ1ur92baSHRQB8GayGdUWu1HzoSNFO+ZM1f2cbTLM51lT5woc5rkDObbZ/Vm2SEm23VvsyjhV5nJQBsCbxGZQVtmN6p4Mo/YPdqNGHKlayUrXJ9zWlESh0xIvzsmYL3HZ54pzMm6VuRyRMpfTW+pyUAbAm8BmVNVnGNTTdqP6vzOMGrGnaMSZqpNsk17ybKlS6DTL/ixbotRlj5flOubL3I65MpfjVrnbEalYKINSl335vQGA3wKbUW2xGdWRDKP66wyjWhYLwJGiFWeaTrJNBnFbU2SP3ST7s6xSmmuXcrczUe52xstzHfPlbsdcudt5qyzX3lKWlxkszXGeK8mxnyzJySjeQRkArzebQVllM6p7bUb149UF4EjVSmaaTrLS9eKypMgee7ocyLZJmdshFXmZUpHnXFEGB/OzJsrdjqEyt/NmWa49XJbt9Ja6Mk4Vu7hEBF5LNr2q3mZQz9gM6u9XFEBqsgCcaTrJXJgEci0pstdhkv3ZNinNTZbAofwsOZSfJQfzMqU8z5kodzsSZbmOeIXb+XW52zFa5nLcKnPZI2ULl4jFfKIAvB7MOrXFZlBHbAb11zaj+kmGUbNuAWSm65dKYHdGmhRlWqQ8zyFHCnLk+L5cOV6UK0cKXVK5J1sO5mdKhdspZavKoDTX0VPiciTLIHtFGVAIwK/NYlBW2fTqXptB/dhmSJ7+LyqArHS95JiTJVDgNEllQZZ4KgulrrpU6qtLJXBsv5wt3yMn9rvlaIFLDi8vg1xH4mB+5p+Wl0Fpjr2lJMcRLM6ynyvOzjhxIIt7A+BXY9Gr6q0L4/9SAaRoxL7w/L9WAWSbDJJrTZFid4Z4jxZJU/1xufHhOem+ek6il0/LB74qaTxTJoGj++Vs2R45vj9XjhTkyOHdC48JC2VwaHfmnyrczn+vcDsmynLtQyU5GTeLczLCpTk2T3GW7VhxVsae7d4f4I1l1qktVoM6YjOovrYa1D8sFoB9WQE415kA8u1pcvRAjnwUOiLDLQG5190o9242ylRHnQyG/XLz6nmJXqqWD3yV0nC6VPxH98nZst1yfF+uHC10SdXebDmUnyyDqoLs7w7lZ35b7nb8scxt/7dSl32kJCejqyQn40pJTkbZDiYC4NWzaJVVVr2q12ZQPbYa1H9fuwB0SwWQla6XLFOyAAoyTfLW4T3SfuWM3L3RIA/7L8vD/svyZe8l+ezW23Kvu1EmO2ploNkn3VfPSevb1fK+t1Iaz5RJ7cli8R0pktOl+XKsKFkGBxfKoHJv1l8P5mf+uSLP8fvyXMdMmdsRKXc5qotdGQXbvV/AG8WiV9Vb9aoZq141azOoxWbcXAHkWlOkJC9Dak8Xy61PL8iDnotLBbBUBH2X5Yvbl+RBz0W5e6NBJtprpL/ZJzc/Oi/XP3hLWi6ekvc8h6WuukS8Vc/KYPEC8WhhzpOqguzvKvdmfXV4d2b3wfzM9w/lZTENAK+CWaewWHWqiE2v+tqqV/2w2QLINhkkP2Nh/K89ImNtIfmi99Kz8Pcl15dL65J80XtJPr/1tty/2Sh3uxvkzvV6GY+FpO+aV65/8DuJXDwpVzyHpO7UQhmU5MvRIpdU7c2RQ7uz5MR+9x+OFbnuHi3MiVQVuKoP784u2u79A37TLFpllVWn6rXqVY+tetWPGxbAsgvAvU6TvHVot8SunJY7N+rly761g/9lb3J9sWx9fvuSfH77bXnQc1HudTfITFedjLWFpPeaR7o+eEvCjSflyoVDUlddKsHjB+TC4UI5VZwnVQU5ibcq9nx1ujS/58QB99XqYnf5DqYB4OVYdM/Gf6te9Y/k8//GBeCyGKXEnSE11Qek55Pzcv9m48rQrxP8L25fki9uvy2fr1qf3bqYnAxuNMh0Z52MRINy+1OPXP/wd9J+5Yw015+Qd84flJqTxXLhcIGcLM77+UhBzt8uVBa2nqvce/ZsxZ6y7d5L4Ddlcfy36FVfW/SqH6wGlawugMWvATvTlhWAySB5GalydH+OfFRzREajQfn81tvrh/6FwV9cF+WzWxflwa2Lcr/notzrbpSZ6/Uy1VUnkx21MtwSkJ5PLkjHe2elqf64XD53UEInDiQuHC6Yry7Omz1W5HrY+FbF4R1MA8DmWLTKKsuy8d9qUL+wAJZ/C3CPM13OHtwtbe+elunr9fLFusF/PvSf31o7+A96nq37PRflfk+j3L+Z/Fjx7o0Gme6qk4n2Ghlq8UvPx+el/coZuVZ3XC6fq/i57lTx32pOHngUOlUc/jR4lEtCYCMWnareolfNWPSqWatB9dOaBbDGl4BcFqMUu20SOnVAbn58Tu52N27qtP98g9A/WAz9QvAX173FEuhukLvdDcnJoLNWxmM1Mhjxy82Pzknn+2cSsXdPz4cbT8x+GKh8+FHwSO0OSgBYm1mnsJh1qohFr1wY/5XxZwWw/teAs9KTvwtwZH+2XA1VyXBrUB70XFz/tF9nzN9K8O91N8i9hfAvrjs3GuTOjXqZXnhEGG+vkdFoUAbD/p97Pj7/t56r57/pu+b5pOXd6qPbvdfAa8ei3VVl0al6LXrlY4tO+aNFr0pstgD2ONLlzMHdEn2nWqY66+SzlxzzHywb858L/TrBv3vjWfgX18z15JruqpOpzlqZaA8lxmKhv49Gg3/oD/s+3u69Bl47Fp2i3qJVzVh0ylmrTvmTVZ+8AFz5HsDzBZBjNkpxrk2Cpw5I90fn5M6Nhhee9lsOfvfmg3/n+rPwz1yvk5muOpleWJMdtfHJjprvJjtqKABgueT4r4iYdcqvzbpdP1j0yvjqArCv9SJQul7ctlSp2pctHwYrZaglIPdvNq5/2r/gYm9Twb+x9eBPd9XJVHISmJ/qrP1murOGRwBgOZN2V5VFp+y1aBfGf50ysVQAa3wHYLEAstL1stuRLqcr8qX18imZ7KiVBz0XXxj6jZ/vNxn86xsHP/kIUCdTnXXx6c7av0x11PRs914Drx2TTlFv0ipmzDrlrEWn/MmiV8lmCiDbbJADuTYJntwvN67+Tmau1ydDvmbot36x9yz49S8Z/NrFNT/dVfv7qc66k9u918BrxaxePf4r4hsVgHPh9wBzrSlSVZQtHwQqZTDil7vdjVs77bcY/JmtB1+mOmsTkx21T6a6ake2e6+B145Ju6vKpFP2mrTKx2bts/F/8VuALyqA3fY0OV2eLy2XTspEe43cf8Gz/TYEXyY7amWyoyY+1VHz/VRnXfN27zXw2lka/7XKWYtW+ZNFp5TNFEC2ySD7XVYJnNgnXR++JdNddZs+7X+d4NfKZEeNTHbUzE921Dya5PIPWClNrbCYtcnx36Td9YNZp4hbdKqNC2Bh/K8szJL3/YdlIOyTOzcatvwx3sY3+r8o+DLZEUpMtNc8mehg/AeeY1LvqjJplb0mjeKxWav40axVJlYXwFpvAmam6STfnibVZXkSefukjMVCcrd7EyP+eqf9loJfu2HwJzpqZKK9RsbbQ/HJ9tD3k501jP/AaiaNot6kSY7/Zq3iJ7NOKYsXgC8qgCyTQfblWMV/fJ90fnBWJjtrV4z3Wzntn7vRv/586Lca/GcrND/RHno02c74D6yQplZYTFpFxKRVLI3/Kwvg+ReB7CnJ3wFwWVLkcGGWvOc/LP3NXpm5Xv/LT/tNBn9yE8EfT4Y/MR4LPRlvDzH+A6uZNYpKk3ZXb/rC+G/SKhKbLYC8jDQ5VZYn4YsnZLQtKHdubC70mx3zf0nwx9tDMh4LyVgsFB+PBb8fb2f8B56TrlHUp2sV0yaNYmn830wBZKXrZV+2RXzH90nH+2dloqMmWQCv4LR/+eCHloK/EH4ZjwXnx2PBR2PtQcZ/YDmTRpmarlY0mTS7vkrTKP5q0ip+NuuUYtmgABypWnFZjHKoIFOueA9JX5NHprvqNh36zZ72vyT4C+FPjLYFn4zHgoz/wGomza7d6ZpdMZNG8Y1Jo3hi1i48/2+iAPIyUuVkqVuaGk/ISDQoM9df3Wm/Mvg1Ww7+WCwkY21BGW0Lxkfbgt+PxUKM/8BqaZpdu9PUiiaTRvGVSav4y9InABsUQGa6XoqyLeI9ViTt752R8fbQqsC/4tN+i8EfawvKaDQoI9HA/Ghb8JuxKOM/8ByT5l9T09SKQLpGMWTSKv7TrFU8NeuUieUFYFv1YyCOVK3kmJPj/7veg9J7zSNTnbWv6LR/BcFfWCPRQHwkGvjLSDTAm3/AetLVyjyTRvmOSauYNOsU35p1yn9sVABuW6qcLM2Vaw3HZbg1INNdr+a0X/sz/K0FfzQalNFoIHn6RwO/H2kL8uYf8CImza5Ck27Xe2atcsqiU8bXLYAUjWSm66QwyyzeY4USu3JaxmKhtUP/i0/7mhWhXxH8tvWCH5SRaEBGo4HESKv/yWhrgMs/YDPSdcois1bxvkWnfGrRK+NrFYA9RSvZZoMc3OuUdzwH5fa1CzLRUfNPPe3H1zjt1wv+4hpuDcRHooHvR6IBLv+AzTLrlEVmnfKhRad8al3z58C04ralyImSXLnWcEyGWv0y2VkrU13Ph/6lTvsNgj+6QfBHWgMy3BqQ4Vb//HBr4NFI1M/lH7AVFr0qYNGrHlr1qqc2gyq+/E1AZ5pOCrNM4jlaIG1XTstoW/Cfd9q/VPADMtzqTwy3+J8MM/4DL2XnihIwquI2o1rsKRrJNhmkYq9DLl+okFufnJfx9ppnoV/vc/utnvaxNcb8TQU/IMOtfhlq8ceHW/zfD0cDF7Z7I4Hfqp02vSpg06se2gzqpxlGTdyeopFca4ocL3HJp/VHZTDik4mOzY34L33ab+7EXwz+wvLND7cEbo20BjK3exOB37KdNqM6YDOoH2YY1U+dabp4QaZJLhzZK9F3q2UkGpCJDU/70Ks77TcMvl+GWnyJwYjvyVBL4J3t3jzgTbDTZlQHMoyah9lm/dOKPc74pfPl0vPxORmLhX6d035TwV9YEV98sMU/NRDm8g94VXbaU7UBl8X48ESJ6+kn9Ud+Hgh7EuPtoVdz2rdtJvQvDv5gxLewvH8ciHg7hloClu3eNOBNstNtSw34jxc9bH2nenaoxTc33h6aH4uF4uPtwcR48n/u/RNO+80G3ydDEd//DIR99wbCvsbt3izgTbTzaqgy0PPxufBINBAbbw89Go+FZsdjobnx9tDcaCw4P9oWjI/FgomxWCAx+gpO++G1xvxVwR+M+GQw7P1xMOx7PBj29fZHvFXbvVHAm2rn4prsrKkd6wiFR9tDsfH2mthILPRorC04O9YWmhuNheZG2wLzI9FgfLQtkBiNBhLPhf4XnPaLayDik4GwTwbC3v8daPY+HIj4Pupv9jL+A7+CncvXeHtN7WgsGB6NhWKjsVBsJBp8NBoNzo5EA3MLa364NRAfafUnhpPr5U77lcGXgbD37wNhz5/7m70jA2HPmW3eE+D/rZWF0BasHW4LhkeigdhILBQbbg08Gm4NzA63+OeGW/xzQ63++aEWf3yoxZdIrmWhb3k+9INLoV8KvvQ3e+MDzd4f+ps9/9Ef9rYNRHyObd4DAAtWFMJoW7B2uDUYHooGYkPRQGyoxf9oqMU3OxTxzQ1FfHNDLb75oYgvPhjxJpZWeO3gJ8PvSfQ3eX8aCHtn+5u9M33NXP4Br7MVhTDcGqgdbvWHB1v9scFWf2ww4n80GPHNDoa9c4MR39xg2Ds3EPbOD4S98YGwJzEQ9iT6m73S3+yVvmbPfH+zZ76vyfO0v9n7p75mb29/M5d/wG/Jc4Uw1OIP90f8scGIP9Yf8ccGwr5HA2Hv7ECzd26g2TvXlwx9vK/Z821/s+e/+po83/Y3eT7ra/Y0cfkH/LbtXL2GWny1A2FfuC/sjfWHvbH+Zs+jvrD3Zm+TZ6i3yTPW1+yZ7GvyXO9r9vi3908H8M+wohB6m7xlt695Tw6EfecGw15ff5Pnnb5mT6D32oUD2/x3AvgV7dyxY8fOgSavu7/Jk9V3zave7j8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICV/g9tPJEQu1XvmQAAAABJRU5ErkJggg==">
+<img id="i2">
+
+<script>
+var wtu = WebGLTestUtils;
+var defaultImgUrl = "https://get.webgl.org/conformance-resources/thunderbird-logo-64x64.png";
+var localImgUrl = "../../../resources/thunderbird-logo-64x64.png";
+
+Tests.autoinit = false; // Prevents the test from running until the image is loaded
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+
+ gl.viewport(0,0,canvas.width,canvas.height);
+ gl.clearColor(0,0,1,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.disable(gl.DEPTH_TEST);
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var texCubeMap = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap);
+ return [gl]
+}
+
+Tests.teardown = function(gl, tex, texCubeMap) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.deleteTexture(texCubeMap);
+}
+
+Tests.testTexImage2D = function(gl) {
+ gl.enable(gl.BLEND);
+ var img = document.getElementById('i');
+ var c = document.getElementById('c');
+ var ctx = c.getContext('2d');
+ ctx.drawImage(img,0,0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ var f = new Filter(gl, 'identity-flip-vert', 'identity-frag');
+ gl.blendFunc(gl.ONE, gl.ZERO);
+ f.apply();
+ f.destroy();
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ f = new Filter(gl, 'identity-hflip-vert', 'identity-frag');
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ f.apply();
+ f.destroy();
+ var valid_targets = [
+ gl.TEXTURE_2D,
+ 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
+ ];
+ valid_targets.forEach(function(t) {
+ assertOk(function(){
+ gl.texImage2D(t, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ gl.texSubImage2D(t, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ });
+ assertOk(function(){
+ gl.texImage2D(t, 1, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ gl.texSubImage2D(t, 1, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ });
+ });
+}
+
+Tests.testTexImage2DNonSOP = function(gl) {
+ var img = document.getElementById('i2');
+ var c = document.getElementById('c');
+ var ctx = c.getContext('2d');
+ ctx.drawImage(img,0,0);
+ assertThrowNoGLError(gl, "texImage2D with cross-origin image should throw exception.",
+ function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);});
+ assertThrowNoGLError(gl, "texSubImage2D with cross-origin image should throw exception.",
+ function(){gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, img);});
+ assertThrowNoGLError(gl, "texImage2D with dirty origin canvas should throw exception.",
+ function(){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);});
+ assertThrowNoGLError(gl, "texSubImage2D with dirty origin canvas should throw exception.",
+ function(){gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, c);});
+}
+
+Tests.endUnit = function(gl) {
+};
+
+(async function() {
+ const img = document.getElementById('i2');
+ try {
+ await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
+ } catch (e) {
+ testFailed(`Image setup failed (${e}).`);
+ finishTest();
+ return;
+ }
+ initTests();
+})();
+</script>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTMLBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTMLBadArgs.html
new file mode 100644
index 0000000000..0d860bcaaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/texSubImage2DHTMLBadArgs.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ return [gl, tex];
+}
+
+Tests.testTexImage2D = function(gl) {
+ var b = document.createElement('b');
+ var div = document.createElement('div');
+ var c = document.getElementById('c');
+ assertOk("make texture",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_VALUE, "y + height > texture height",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 1, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_VALUE, "x + width > texture width",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_VALUE, "negative x",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_VALUE, "negative y",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, -1, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_VALUE, "negative level",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, -1, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertThrowNoGLError(gl, "bad element b",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, b); });
+ assertThrowNoGLError(gl, "bad element div",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, div); });
+ assertThrowNoGLError(gl, "no element",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, 0); });
+ assertThrowNoGLError(gl, "string as data",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, gl.RGBA, gl.UNSIGNED_BYTE, "foo"); });
+ assertGLError(gl, gl.INVALID_ENUM, "bad target",
+ function() {gl.texSubImage2D(gl.FLOAT, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertOk("good args",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_OPERATION, "format not same as original",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGB, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_OPERATION, "type not same as original",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, c); });
+ assertOk("make texture RGB",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, c); });
+ assertOk("format same as original RGB",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGB, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_OPERATION, "format not same as original RGB",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_OPERATION, "type not same as original RGB",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, c); });
+ assertOk("make texture RGBA 4_4_4_4",
+ function() {gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, c); });
+ assertOk("format same as original RGBA 4_4_4_4",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, c); });
+ assertGLError(gl, gl.INVALID_OPERATION, "format not same as original RGBA 4_4_4_4",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGB, gl.UNSIGNED_BYTE, c); });
+ assertGLError(gl, gl.INVALID_OPERATION, "type not same as original RGBA 4_4_4_4",
+ function() {gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, c); });
+}
+
+Tests.endUnit = function(gl, tex) {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+<canvas id="c" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrix.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrix.html
new file mode 100644
index 0000000000..cae388fd4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrix.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testUniformf = function(gl) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var foo = f.uniform('foo');
+ var bar = f.uniform('bar');
+ var bar3 = f.uniform('bar3');
+ gl.uniformMatrix4fv(foo, false, [1,0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);
+ gl.uniformMatrix2fv(bar, false, [2,1, 2,2]);
+ gl.uniformMatrix3fv(bar3, false, [2,2,2, 2,2,2, 2,1,2]);
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertEquals([1,2,3,8], [d[0], d[1], d[2], d[3]]);
+ sh.destroy();
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform mat2 bar;
+uniform mat3 bar3;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, bar[0][1]+bar3[2][1], 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform mat4 foo;
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(foo[0][0]/256.0, foo[1][1]/256.0, foo[2][2]/256.0, foo[3][3]*texCoord0.z/256.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrixBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrixBadArgs.html
new file mode 100644
index 0000000000..1355cd547f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformMatrixBadArgs.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var unwrappedGL = getGLContext(canvas);
+ var gl = wrapGLContext(unwrappedGL);
+ return [gl, unwrappedGL];
+}
+
+Tests.testUniformf = function(gl, unwrappedGL) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var fm4 = f.uniform('fm4');
+ var fm2 = f.uniform('fm2');
+ var fm3 = f.uniform('fm3');
+ assertGLError(gl, gl.INVALID_VALUE, "bad transpose 4fv",
+ function(){gl.uniformMatrix4fv(fm4, true, [1,0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);});
+ assertGLError(gl, gl.INVALID_VALUE, "bad transpose 3fv",
+ function(){gl.uniformMatrix3fv(fm3, true, [1,0,0, 0,2,0, 0,0,3]);});
+ assertGLError(gl, gl.INVALID_VALUE, "bad transpose 2fv",
+ function(){gl.uniformMatrix2fv(fm2, true, [1,0, 0,2]);});
+ assertThrowNoGLError(gl, "bad location",
+ function(){gl.uniformMatrix4fv(588939, false, [1,0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);});
+ assertThrowNoGLError(gl, "bad location (negative)",
+ function(){gl.uniformMatrix4fv(-588939, false, [1,0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);});
+ assertGLError(gl, gl.INVALID_VALUE, "17 values to 4fv",
+ function(){gl.uniformMatrix4fv(fm4, false, [0,1,0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);});
+ assertGLError(gl, gl.INVALID_VALUE, "5 values to 2fv",
+ function(){gl.uniformMatrix2fv(fm2, false, [0,2,1, 2,2]);});
+ assertGLError(gl, gl.INVALID_VALUE, "10 values to 3fv",
+ function(){gl.uniformMatrix3fv(fm3, false, [0,2,2,2, 2,2,2, 2,1,2]);});
+ assertGLError(gl, gl.INVALID_VALUE, "too few values to 4fv",
+ function(){gl.uniformMatrix4fv(fm4, false, [0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);});
+ assertGLError(gl, gl.INVALID_VALUE, "too few values to 2fv",
+ function(){gl.uniformMatrix2fv(fm2, false, [1, 2,2]);});
+ assertGLError(gl, gl.INVALID_VALUE, "too few values to 2fv",
+ function(){gl.uniformMatrix2fv(fm2, false, []);});
+ assertThrowNoGLError(gl, "string for data",
+ function(){gl.uniformMatrix2fv(fm2, false, "fm4");});
+ assertGLError(gl, gl.INVALID_VALUE, "too few values to 3fv",
+ function(){gl.uniformMatrix3fv(fm3, false, [2,2, 2,2,2, 2,1,2]);});
+ gl.uniformMatrix4fv(fm4, false, [1,0,0,0, 0,2,0,0, 0,0,3,0, 0,0,0,4]);
+ gl.uniformMatrix2fv(fm2, false, [2,1, 2,2]);
+ gl.uniformMatrix3fv(fm3, false, [2,2,2, 2,2,2, 2,1,2]);
+ assertGLError(gl, gl.INVALID_OPERATION, "3fv on mat4",
+ function(){gl.uniformMatrix3fv(fm4, false, [1,0,0, 0,2,0, 0,0,3]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "3fv on mat2",
+ function(){gl.uniformMatrix3fv(fm2, false, [0,2,1, 0,2,2, 0,0,0]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "2fv om mat3",
+ function(){gl.uniformMatrix2fv(fm3, false, [2,2, 2,2]);});
+ for (var ii = 2; ii <= 4; ++ii) {
+ var all = [];
+ var mats = [[],[]];
+ for (var jj = 0; jj < 2; ++jj) {
+ for (var kk = 0; kk < ii * ii; ++kk) {
+ mats[jj].push(jj + 1);
+ all.push(jj + 1);
+ }
+ }
+ var loc0Name = 'am' + ii + '[0]';
+ var loc1Name = 'am' + ii + '[1]';
+ var loc0 = f.uniform(loc0Name);
+ var loc1 = f.uniform(loc1Name);
+ var fname = "uniformMatrix" + ii + "fv";
+ assert(loc0Name, loc0 != null);
+ assert(loc1Name, loc1 != null);
+ assertOk("set array of 2 matrices " + ii + "fv",
+ function(){gl[fname].call(gl,loc0, false, all);});
+ var actual = unwrappedGL.getUniform(sh.shader.program, loc0);
+ assert("got value for loc0",
+ gl.NO_ERROR == checkError(gl, "getUniform loc0"));
+ assertArrayEquals(mats[0], actual);
+ var actual = unwrappedGL.getUniform(sh.shader.program, loc1);
+ assert("got value for loc1",
+ gl.NO_ERROR == checkError(gl, "getUniform loc1"));
+ assertArrayEquals(mats[1], actual);
+ assertOk("set array of second array of 2 matrixes",
+ function(){gl[fname].call(gl, loc1, false, mats[0]);});
+ var actual = unwrappedGL.getUniform(sh.shader.program, loc1);
+ assert("got value for loc1",
+ gl.NO_ERROR == checkError(gl, "getUniform loc1"));
+ assertArrayEquals(mats[0], actual);
+ var big = mats[1].concat([3]);
+ assertGLError(gl, gl.INVALID_VALUE, "set array of first array of 2 matrixes plus 1 value",
+ function(){gl[fname].call(gl, loc0, false, big);});
+ }
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertArrayEqualsWithEpsilon([1,2,3,8], d, [1,1,1,1]);
+ sh.destroy();
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform mat2 fm2;
+uniform mat3 fm3;
+uniform mat2 am2[2];
+uniform mat3 am3[2];
+uniform mat4 am4[2];
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, fm2[0][1]+fm3[2][1], 0.0);
+ float d = am2[0][1][1] + am3[0][2][2] + am4[0][3][3] +
+ am2[1][1][1] + am3[1][2][2] + am4[1][3][3];
+ gl_Position = vec4(Vertex, 1.0 + d * 0.0001);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform mat4 fm4;
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(fm4[0][0]/256.0, fm4[1][1]/256.0, fm4[2][2]/256.0, fm4[3][3]*texCoord0.z/256.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformf.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformf.html
new file mode 100644
index 0000000000..3c968c7a0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformf.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testUniformf = function(gl) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var foo = f.uniform('foo');
+ var bar = f.uniform('bar');
+ gl.uniform4fv(foo, [1,2,3,4]);
+ gl.uniform1fv(bar, [2]);
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertEquals([1,2,3,8], [d[0], d[1], d[2], d[3]]);
+ sh.apply(function(f){
+ var foo = f.uniform('foo');
+ var bar = f.uniform('bar');
+ gl.uniform4f(foo, 2,2,3,4);
+ gl.uniform1f(bar, 3);
+ });
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertEquals([2,2,3,12], [d[0], d[1], d[2], d[3]]);
+ sh.destroy();
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform float bar;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, bar, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform vec4 foo;
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(foo.r/255.0, foo.g/255.0, foo.b/255.0, foo.a*texCoord0.z/255.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfArrayLen1.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfArrayLen1.html
new file mode 100644
index 0000000000..3b210f1f1e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfArrayLen1.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testUniformArray = function(gl) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var uniV4 = f.uniform('uniV4');
+ var uniFloat = f.uniform('uniFloat');
+ assertOk("1fv on 1fv",
+ function(){gl.uniform1fv(uniFloat, [2]);});
+ assertOk("5 values on 1fv",
+ function(){gl.uniform1fv(uniFloat, [2,3,4,5,6]);});
+ assertOk("4fv on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4]);});
+ assertOk("8 values on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4, 5, 6, 7, 8]);});
+
+ var uniformsFound = 0;
+ var numUniforms = gl.getProgramParameter(f.shader.program, gl.ACTIVE_UNIFORMS);
+ for (var i = 0; i < numUniforms; ++i) {
+ var uniformName = gl.getActiveUniform(f.shader.program, i).name;
+ if (uniformName.indexOf('uniV4') == 0 || uniformName.indexOf('uniFloat') == 0) {
+ assert("Uniform array of length 1 ends with [0]", uniformName.indexOf("[0]") != -1);
+ ++uniformsFound;
+ }
+ }
+ assert("Both uniforms found", uniformsFound == 2);
+
+ uniV4 = f.uniform('uniV4[0]');
+ uniFloat = f.uniform('uniFloat[0]');
+ assertOk("1fv on 1fv",
+ function(){gl.uniform1fv(uniFloat, [2]);});
+ assertOk("5 values on 1fv",
+ function(){gl.uniform1fv(uniFloat, [2,3,4,5,6]);});
+ assertOk("4fv on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4]);});
+ assertOk("8 values on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4, 5, 6, 7, 8]);});
+
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertArrayEquals([1,2,3,8], d);
+ sh.destroy();
+ throwError(gl);
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform float uniFloat[1];
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, uniFloat[0], 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform vec4 uniV4[1];
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(
+ uniV4[0].r/255.0,
+ uniV4[0].g/255.0,
+ uniV4[0].b/255.0,
+ uniV4[0].a*texCoord0.z/255.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfBadArgs.html
new file mode 100644
index 0000000000..32b2c4babc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformfBadArgs.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testUniformf = function(gl) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var uniV4 = f.uniform('uniV4');
+ var uniFloat = f.uniform('uniFloat');
+ assertThrowNoGLError(gl, "number for location",
+ function(){gl.uniform4fv(58882929, [1,2,3,4]);});
+ assertThrowNoGLError(gl, "negative number for location",
+ function(){gl.uniform4fv(-58882929, [1,2,3,4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "1fv on 4fv",
+ function(){gl.uniform1fv(uniV4, [1,2,3,4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "more than enough values 1fv",
+ function(){gl.uniform1fv(uniFloat, [2,3,4,5,6]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "4fv on float",
+ function(){gl.uniform4fv(uniFloat, [2,3,4,5]);});
+ assertOk("4fv on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4]);});
+ assertGLError(gl, gl.INVALID_VALUE, "5 values on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4, 5]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "8 values on 4fv",
+ function(){gl.uniform4fv(uniV4, [1, 2, 3, 4, 5, 6, 7, 8]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "3fv on float",
+ function(){gl.uniform3fv(uniFloat, [2,3,4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "2fv on float",
+ function(){gl.uniform2fv(uniFloat, [2,3]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "3fv on 4fv",
+ function(){gl.uniform3fv(uniV4, [4,5,6]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "2fv on 4fv",
+ function(){gl.uniform2fv(uniV4, [5,6]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "1fv on 4fv",
+ function(){gl.uniform1fv(uniV4, [6]);});
+ assertOk("1fv on 1fv",
+ function(){gl.uniform1fv(uniFloat, [2]);});
+ assertGLError(gl, gl.INVALID_VALUE, "not enough values on 1fv",
+ function(){gl.uniform1fv(uniFloat, []);});
+ assertGLError(gl, gl.INVALID_VALUE, "not enough values on 4fv",
+ function(){gl.uniform4fv(uniV4, [3,3,4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "4iv on 4fv",
+ function(){gl.uniform4iv(uniV4, [1, 2, 3, 4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "1iv on 1fv",
+ function(){gl.uniform1iv(uniFloat, [2]);});
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertArrayEquals([1,2,3,8], d);
+ sh.destroy();
+ throwError(gl);
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform float uniFloat;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, uniFloat, 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform vec4 uniV4;
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(
+ uniV4.r/255.0,
+ uniV4.g/255.0,
+ uniV4.b/255.0,
+ uniV4.a*texCoord0.z/255.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformi.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformi.html
new file mode 100644
index 0000000000..252626a735
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformi.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testUniformi = function(gl) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var foo = f.uniform('foo');
+ var bar = f.uniform('bar');
+ gl.uniform4iv(foo, [1,2,3,4]);
+ gl.uniform1iv(bar, [2]);
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertEquals([1,2,3,8], [d[0], d[1], d[2], d[3]]);
+ sh.apply(function(f){
+ var foo = f.uniform('foo');
+ var bar = f.uniform('bar');
+ gl.uniform4i(foo, 2,2,3,4);
+ gl.uniform1i(bar, 3);
+ });
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertEquals([2,2,3,12], [d[0], d[1], d[2], d[3]]);
+ sh.destroy();
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform int bar;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, float(bar), 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform ivec4 foo;
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(float(foo.r)/256.0, float(foo.g)/256.0, float(foo.b)/256.0, float(foo.a)*texCoord0.z/256.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformiBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformiBadArgs.html
new file mode 100644
index 0000000000..4741ffebac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/uniformiBadArgs.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.testUniformf = function(gl) {
+ var sh = new Filter(gl, 'foobar-vert', 'foobar-frag');
+ sh.apply(function(f){
+ var uniIV4 = f.uniform('uniIV4');
+ var uniInt = f.uniform('uniInt');
+ assertThrowNoGLError(gl, "number as location",
+ function(){gl.uniform4iv(58882929, [1,2,3,4]);});
+ assertThrowNoGLError(gl, "negative number as location",
+ function(){gl.uniform4iv(-58882929, [1,2,3,4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "more than 1 value to 1iv",
+ function(){gl.uniform1iv(uniInt, [2,3,4,5,6]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "4iv on int",
+ function(){gl.uniform4iv(uniInt, [2,3,4,5]);});
+ assertOk("4iv on 4iv",
+ function(){gl.uniform4iv(uniIV4, [1, 2, 3, 4]);});
+ assertGLError(gl, gl.INVALID_VALUE, "5 values on 4iv",
+ function(){gl.uniform4iv(uniIV4, [1, 2, 3, 4, 5]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "8 values on 4iv",
+ function(){gl.uniform4iv(uniIV4, [1, 2, 3, 4, 5, 6, 7, 8]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "3iv on int",
+ function(){gl.uniform3iv(uniInt, [2,3,4]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "2iv on int",
+ function(){gl.uniform2iv(uniInt, [2,3]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "3iv on 4iv",
+ function(){gl.uniform3iv(uniIV4, [4,5,6]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "2iv on 4iv",
+ function(){gl.uniform2iv(uniIV4, [5,6]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "1iv on 4iv",
+ function(){gl.uniform1iv(uniIV4, [6]);});
+ assertGLError(gl, gl.INVALID_VALUE, "not enough values",
+ function(){gl.uniform1iv(uniInt, []);});
+ assertGLError(gl, gl.INVALID_OPERATION, "1fv on int",
+ function(){gl.uniform1fv(uniInt, [2]);});
+ assertGLError(gl, gl.INVALID_OPERATION, "4fv on ivec4",
+ function(){gl.uniform4fv(uniIV4, [2,3,4,5]);});
+ gl.uniform1iv(uniInt, [2]);
+ gl.uniform4iv(uniIV4, [1, 2, 3, 4]);
+ });
+ var d = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, d);
+ assertArrayEquals([1,2,3,8], d);
+ sh.destroy();
+ throwError(gl);
+}
+
+Tests.endUnit = function(gl) {
+}
+
+</script>
+<script id="foobar-vert" type="x-shader/x-vertex">
+attribute vec3 Vertex;
+attribute vec2 Tex;
+
+uniform int uniInt;
+
+varying vec4 texCoord0;
+void main()
+{
+ texCoord0 = vec4(Tex.s, 1.0-Tex.t, float(uniInt), 0.0);
+ gl_Position = vec4(Vertex, 1.0);
+}
+</script>
+<script id="foobar-frag" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform ivec4 uniIV4;
+
+varying vec4 texCoord0;
+void main()
+{
+ gl_FragColor = vec4(
+ float(uniIV4.x)/256.0,
+ float(uniIV4.y)/256.0,
+ float(uniIV4.z)/256.0,
+ float(uniIV4.a)*texCoord0.z/256.0);
+}
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttrib.html
new file mode 100644
index 0000000000..866c95da1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttrib.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+var verts = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0];
+var normals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
+var texcoords = [0.0,0.0, 1.0,0.0, 0.0,1.0];
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var prog = new Shader(gl, 'vert', 'frag');
+ prog.use();
+ var sh = prog.shader.program;
+// log(gl.getShaderInfoLog(prog.shaders[1]));
+ var v = gl.getAttribLocation(sh, 'Vertex');
+ var n = gl.getAttribLocation(sh, 'Normal');
+ var t = gl.getAttribLocation(sh, 'Tex');
+ return [gl,prog,v,n,t];
+}
+
+Tests.setup = function(gl, prog, v,n,t) {
+ assert(0 == gl.getError());
+ return [gl, prog, v,n,t];
+}
+Tests.teardown = function(gl, prog, v,n,t) {
+ gl.disableVertexAttribArray(v);
+ gl.disableVertexAttribArray(n);
+ gl.disableVertexAttribArray(t);
+}
+
+Tests.endUnit = function(gl, prog, v,n,t) {
+ prog.destroy();
+}
+
+Tests.testVertexAttrib = function(gl, prog, v,n,t) {
+ var vbo = gl.createBuffer();
+ var vertsArr = new Float32Array(verts);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, vertsArr, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(v);
+ gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
+ gl.vertexAttrib1fv(v, [1]);
+ gl.vertexAttrib2fv(v, [1,2]);
+ gl.vertexAttrib3fv(v, [1,2,3]);
+ gl.vertexAttrib4fv(v, [1,2,3,4]);
+ gl.vertexAttrib1f(v, 1);
+ gl.vertexAttrib2f(v, 1,2);
+ gl.vertexAttrib3f(v, 1,2,3);
+ gl.vertexAttrib4f(v, 1,2,3,4);
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
+ throwError(gl);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(vbo);
+ throwError(gl);
+}
+Tests.testVertexAttribVBO = function(gl, prog, v,n,t) {
+ var vbo = gl.createBuffer();
+ var vertsArr = new Float32Array(verts);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, vertsArr, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(v);
+ gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
+ gl.vertexAttrib1fv(v, [1]);
+ gl.vertexAttrib2fv(v, [1,2]);
+ gl.vertexAttrib3fv(v, [1,2,3]);
+ gl.vertexAttrib4fv(v, [1,2,3,4]);
+ gl.vertexAttrib1f(v, 1);
+ gl.vertexAttrib2f(v, 1,2);
+ gl.vertexAttrib3f(v, 1,2,3);
+ gl.vertexAttrib4f(v, 1,2,3,4);
+ assertOk(function(){gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);});
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
+ gl.vertexAttrib4fv(v, [1,2,3,4]);
+ assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
+ throwError(gl);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(vbo);
+ throwError(gl);
+}
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+ attribute vec3 Vertex;
+ attribute vec3 Normal;
+ attribute vec2 Tex;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ gl_Position = vec4(Vertex * Normal, 1.0);
+ texCoord0 = vec4(Tex,0.0,0.0) + gl_Position;
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+ precision mediump float;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ vec4 c = texCoord0;
+ gl_FragColor = c;
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribBadArgs.html
new file mode 100644
index 0000000000..67e44a5b87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribBadArgs.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+var verts = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0];
+var normals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
+var texcoords = [0.0,0.0, 1.0,0.0, 0.0,1.0];
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var prog = new Shader(gl, 'vert', 'frag');
+ prog.use();
+ var sh = prog.shader.program;
+// log(gl.getShaderInfoLog(prog.shaders[1]));
+ var v = gl.getAttribLocation(sh, 'Vertex');
+ var n = gl.getAttribLocation(sh, 'Normal');
+ var t = gl.getAttribLocation(sh, 'Tex');
+ return [gl,prog,v,n,t];
+}
+
+Tests.setup = function(gl, prog, v,n,t) {
+ assert(0 == gl.getError());
+ return [gl, prog, v,n,t];
+}
+Tests.teardown = function(gl, prog, v,n,t) {
+ gl.disableVertexAttribArray(v);
+ gl.disableVertexAttribArray(n);
+ gl.disableVertexAttribArray(t);
+}
+
+Tests.endUnit = function(gl, prog, v,n,t) {
+ prog.destroy();
+}
+
+
+Tests.testVertexAttrib = function(gl, prog, v,n,t) {
+ var vbo = gl.createBuffer();
+ var vertsArr = new Float32Array(verts);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, vertsArr, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(v);
+ gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
+ assertFail("bad index",
+ function(){gl.vertexAttrib1f(-1, 1);});
+ assertFail("bad index (big negative)",
+ function(){gl.vertexAttrib1f(-69092342, 1);});
+ assertFail("bad index (big positive)",
+ function(){gl.vertexAttrib1f(58928938, 1);});
+ assertOk("array too large",
+ function(){gl.vertexAttrib1fv(v, [1,2,3,4,5]);});
+ assertFail("array too small",
+ function(){gl.vertexAttrib1fv(v, []);});
+ assertOk("draw",
+ function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
+ throwError(gl);
+}
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+ attribute vec3 Vertex;
+ attribute vec3 Normal;
+ attribute vec2 Tex;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ gl_Position = vec4(Vertex * Normal, 1.0);
+ texCoord0 = vec4(Tex,0.0,0.0) + gl_Position;
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+ precision mediump float;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ vec4 c = texCoord0;
+ gl_FragColor = c;
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointer.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointer.html
new file mode 100644
index 0000000000..838f7d61e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointer.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+var verts = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0];
+var normals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
+var texcoords = [0.0,0.0, 1.0,0.0, 0.0,1.0];
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = wrapGLContext(getGLContext(canvas));
+ var prog = new Shader(gl, 'vert', 'frag');
+ prog.use();
+ var sh = prog.shader.program;
+// log(gl.getShaderInfoLog(prog.shaders[1]));
+ var v = gl.getAttribLocation(sh, 'Vertex');
+ var n = gl.getAttribLocation(sh, 'Normal');
+ var t = gl.getAttribLocation(sh, 'Tex');
+ return [gl,prog,v,n,t];
+}
+
+Tests.setup = function(gl, prog, v,n,t) {
+ assert(0 == gl.getError());
+ return [gl, prog, v,n,t];
+}
+Tests.teardown = function(gl, prog, v,n,t) {
+ gl.disableVertexAttribArray(v);
+ gl.disableVertexAttribArray(n);
+ gl.disableVertexAttribArray(t);
+}
+
+Tests.endUnit = function(gl, prog, v,n,t) {
+ prog.destroy();
+}
+
+Tests.testVertexAttribPointerVBO = function(gl, prog, v,n,t) {
+ var vbo = gl.createBuffer();
+ var vertsArr = new Float32Array(verts);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, vertsArr, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 4);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(vbo);
+}
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+ attribute vec3 Vertex;
+ attribute vec3 Normal;
+ attribute vec2 Tex;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ gl_Position = vec4(Vertex * Normal, 1.0);
+ texCoord0 = vec4(Tex,0.0,0.0) + gl_Position;
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+ precision mediump float;
+
+ varying vec4 texCoord0;
+ void main()
+ {
+ vec4 c = texCoord0;
+ gl_FragColor = c;
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointerBadArgs.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointerBadArgs.html
new file mode 100644
index 0000000000..124d0258e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/functions/vertexAttribPointerBadArgs.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.createElement('canvas');
+ var gl = wrapGLContext(getGLContext(canvas));
+ return [gl];
+}
+
+Tests.setup = function(gl) {
+ assert(0 == gl.getError());
+ return [gl];
+}
+
+Tests.teardown = function(gl) {
+}
+
+Tests.endUnit = function(gl) {
+}
+
+Tests.testVertexAttribPointerVBO = function(gl) {
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(4), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ assertFail("negative offset",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, -4);});
+ assertOk("out of range offset (OK because we can change the buffer later)",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 1200);});
+ assertFail("Offset that is incompatible with type",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 3);});
+ assertFail("negative stride",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, -1, 0);});
+ assertFail("bad size",
+ function(){gl.vertexAttribPointer(0, 5, gl.FLOAT, false, 0, 0);});
+ assertFail("stride that doesn't match type",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 1, 0);});
+ assertFail("bad type",
+ function(){gl.vertexAttribPointer(0, 3, gl.TEXTURE_2D, false, 0, 0);});
+ assertFail("bad index",
+ function(){gl.vertexAttribPointer(-1, 3, gl.FLOAT, false, 0, 0);});
+ assertFail("bad index (big negative)",
+ function(){gl.vertexAttribPointer(-8693948, 3, gl.FLOAT, false, 0, 0);});
+ assertFail("bad index (big positive)",
+ function(){gl.vertexAttribPointer(8693948, 3, gl.FLOAT, false, 0, 0);});
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ assertOk("binding to null buffer with offset=0",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);});
+ assertFail("binding to null buffer with offset!=0",
+ function(){gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 16);});
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(vbo);
+ throwError(gl);
+}
+
+</script>
+</head><body>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/arrayOutOfBounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/arrayOutOfBounds.html
new file mode 100644
index 0000000000..195b224a9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/arrayOutOfBounds.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = getGLContext(canvas);
+ return [gl];
+}
+
+Tests.testOk = function(gl) {
+ var sh = new Filter(gl, 'okvert', 'frag');
+ assertOk(function(){sh.apply();});
+ sh.destroy();
+
+ var sh = new Filter(gl, 'vert', 'okfrag');
+ assertOk(function(){sh.apply();});
+ sh.destroy();
+
+ var sh = new Filter(gl, 'vert', 'frag');
+ assertOk(function(){sh.apply();});
+ sh.destroy();
+}
+
+var arr = ['cr', 'cw', 'vr', 'vw'];
+arr.forEach(function(e){
+ if (e == 'cr' || e == 'cw') {
+ Tests['test'+e+'vert'] = function(gl) {
+ var sh = new Filter(gl, e+'vert', 'frag');
+ assertFail(function(){sh.apply();});
+ sh.destroy();
+ }
+ }
+ Tests['test'+e+'frag'] = function(gl) {
+ var sh = new Filter(gl, 'vert', e+'frag');
+ assertFail(function(){sh.apply();});
+ sh.destroy();
+ }
+});
+
+
+</script>
+<script id="okvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex;
+ attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Tex;
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ gl_Position = vec4(Vertex, x[2]);
+ }
+</script>
+<script id="crvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex;
+ attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Tex;
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ gl_Position = vec4(Vertex, x[4]);
+ }
+</script>
+<script id="cwvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex;
+ attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Tex;
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ x[4] = Vertex.z;
+ gl_Position = vec4(Vertex, x[4]);
+ }
+</script>
+<!-- This one can't be required to fail compilation, because vertex shaders must support arbitrary array indexing -->
+<script id="vrvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex;
+ attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Tex;
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ int idx = 4 * int(max(1.0, Vertex.x*20.0));
+ gl_Position = vec4(Vertex, x[idx]);
+ }
+</script>
+<!-- This one can't be required to fail compilation, because vertex shaders must support arbitrary array indexing -->
+<script id="vwvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex;
+ attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Tex;
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ int idx = 4 * int(max(1.0, Vertex.x*20.0));
+ x[idx] = Vertex.z;
+ gl_Position = vec4(Vertex, x[idx]);
+ }
+</script>
+<script id="vert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex;
+ attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Tex;
+ gl_Position = vec4(Vertex, 0.0);
+ }
+</script>
+
+<script id="okfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ varying vec2 TexCoord;
+
+ void main()
+ {
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ gl_FragColor = vec4(1.0, 0.0, TexCoord.s, x[2]);
+ }
+</script>
+<script id="crfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ varying vec2 TexCoord;
+
+ void main()
+ {
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+ gl_FragColor = vec4(1.0, 0.0, TexCoord.s, x[4]);
+ }
+</script>
+<script id="cwfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ varying vec2 TexCoord;
+
+ void main()
+ {
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+
+ x[4] = 6.0;
+ gl_FragColor = vec4(1.0, 0.0, TexCoord.s, x[4]);
+ }
+</script>
+<!-- This one actually fails because of WebGL's restrictions on indexing expressions in fragment shaders -->
+<script id="vrfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ varying vec2 TexCoord;
+
+ void main()
+ {
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+
+ int idx = 4 * int(max(1.0, TexCoord.x*20.0));
+ gl_FragColor = vec4(1.0, 0.0, TexCoord.s, x[idx]);
+ }
+</script>
+<!-- This one actually fails because of WebGL's restrictions on indexing expressions in fragment shaders -->
+<script id="vwfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ varying vec2 TexCoord;
+
+ void main()
+ {
+ float x[3];
+ x[0] = 1.0;
+ x[1] = 2.0;
+ x[2] = 3.0;
+
+ int idx = 4 * int(max(1.0, TexCoord.x*20.0));
+ x[idx] = 6.0;
+ gl_FragColor = vec4(1.0, 0.0, TexCoord.s, x[idx]);
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ varying vec2 TexCoord;
+
+ void main()
+ {
+ gl_FragColor = vec4(1.0, 0.0, TexCoord.s, 1.0);
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="16" height="16"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/uniformOutOfBounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/uniformOutOfBounds.html
new file mode 100644
index 0000000000..c53347e604
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/glsl/uniformOutOfBounds.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/javascript" src="../unit.js"></script>
+<script type="application/javascript" src="../util.js"></script>
+<script type="application/javascript">
+
+Tests.startUnit = function () {
+ var canvas = document.getElementById('gl');
+ var gl = getGLContext(canvas);
+ return [gl];
+}
+
+var arr = ['cr', 'cw', 'vr', 'vw', 'tvw'];
+arr.forEach(function(e){
+ Tests['test'+e+'vert'] = function(gl) {
+ var sh = new Filter(gl, e+'vert', 'frag');
+ assertFail(function(){sh.apply(function(f){
+ f.uniform3fv('x', [0.0, 1.0, 2.0]);
+ throwError(e+"vert");
+ });});
+ sh.destroy();
+ }
+ Tests['test'+e+'frag'] = function(gl) {
+ var sh = new Filter(gl, 'vert', e+'frag');
+ assertFail(function(){sh.apply(function(f){
+ f.uniform3fv('x', [0.0, 1.0, 2.0]);
+ throwError(e+"frag");
+ });});
+ sh.destroy();
+ }
+});
+
+</script>
+<script id="crvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex; attribute vec2 Tex;
+ uniform float x[3];
+ void main()
+ {
+ gl_Position = vec4(Vertex.st, Tex.s, x[4]);
+ }
+</script>
+<script id="cwvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex; attribute vec2 Tex;
+ uniform float x[3];
+ void main()
+ {
+ x[4] = Vertex.z;
+ gl_Position = vec4(Vertex.st, Tex.s, x[4]);
+ }
+</script>
+<script id="vrvert" type="x-shader/x-vertex">
+
+
+ uniform float x[3];
+ attribute vec3 Vertex; attribute vec2 Tex;
+ void main()
+ {
+ float idx = 40.0 * max(1.0, Vertex.x*20.0);
+ gl_Position = vec4(Vertex, x[2] + Tex.s + x[int(idx)]);
+ }
+</script>
+<script id="vwvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex; attribute vec2 Tex;
+ uniform float x[3];
+ void main()
+ {
+ int idx = 4 * int(max(1.0, Vertex.x*20.0));
+ x[idx] = Vertex.z;
+ gl_Position = vec4(Vertex.st, Tex.s, x[idx]);
+ }
+</script>
+<script id="tvwvert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex; attribute vec2 Tex;
+ uniform float x[3];
+ void main()
+ {
+ int idx = 4 * int(max(1.0, Vertex.x*20.0));
+ x[2] = Vertex[idx];
+ gl_Position = vec4(Vertex.st, Tex.s, x[2]);
+ }
+</script>
+<script id="vert" type="x-shader/x-vertex">
+
+
+ attribute vec3 Vertex; attribute vec2 Tex;
+ varying vec2 TexCoord;
+ void main()
+ {
+ TexCoord = Vertex.st;
+ gl_Position = vec4(Vertex, Tex.s);
+ }
+</script>
+
+<script id="crfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ uniform float x[3];
+
+ varying vec2 TexCoord;
+ void main()
+ {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, x[4]);
+ }
+</script>
+<script id="cwfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ uniform float x[3];
+
+ varying vec2 TexCoord;
+ void main()
+ {
+ x[4] = 6.0;
+ gl_FragColor = vec4(1.0, 0.0, 0.0, x[4]);
+ }
+</script>
+<script id="vrfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ uniform float x[3];
+
+ varying vec2 TexCoord;
+ void main()
+ {
+ int idx = 4 * int(max(1.0, TexCoord.s*20.0));
+ gl_FragColor = vec4(1.0, 0.0, 0.0, x[idx]);
+ }
+</script>
+<script id="vwfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ uniform float x[3];
+
+ varying vec2 TexCoord;
+ void main()
+ {
+ int idx = 4 * int(max(1.0, TexCoord.s*20.0));
+ x[idx] = 6.0;
+ gl_FragColor = vec4(1.0, 0.0, 0.0, x[idx]);
+ }
+</script>
+<script id="tvwfrag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ uniform float x[3];
+
+ varying vec2 TexCoord;
+ void main()
+ {
+ int idx = 4 * int(max(1.0, TexCoord.s*20.0));
+ x[2] = TexCoord[idx];
+ gl_FragColor = vec4(1.0, 0.0, 0.0, x[2]);
+ }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+
+
+ precision mediump float;
+
+ void main()
+ {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+</script>
+
+
+<style>canvas{ position:absolute; }</style>
+</head><body>
+ <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/index.html b/dom/canvas/test/webgl-conf/checkout/conformance/more/index.html
new file mode 100644
index 0000000000..2be2bd3a8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/index.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+ <head>
+<meta charset="utf-8">
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+ <title>WebGL tests</title>
+ </head>
+ <body>
+
+ <h1>Tests for the WebGL canvas context</h1>
+
+ <h2>These tests are intended to serve the following purposes:</h2>
+ <ul>
+ <li>Assert spec conformance (so that WebGL pages work the same across browsers and hardware)</li>
+ <li>Check the safety of the GL binding (bounds checking, same origin policy)</li>
+ <li>Provide performance numbers for developers</li>
+ </ul>
+
+ <h2>Test runners</h2>
+ <ul>
+ <li><a href="all_tests_linkonly.html">Run tests manually</a></li>
+ <li><a href="all_tests.html">Run all tests in parallel</a></li>
+ <li><a href="all_tests_sequential.html">Run all tests sequentially</a></li>
+ </ul>
+
+
+ <h2>Demos</h2>
+ <ul>
+ <li><a href="demos/opengl_web.html">OpenGL for the web</a> (requires working FBOs and null textures or using canvases as textures)</li>
+ <li><a href="demos/video.html">Green screen video demo with a color remapping filter</a> (requires loading &lt;video> to texture with texImage2D)</li>
+ </ul>
+
+ <h2>Running the tests</h2>
+
+ <ol>
+ <li><a href="http://learningwebgl.com/blog/?p=11">Install a browser with WebGL support</a></li>
+ <li>Open one of the test runners linked above in your browser.</li>
+ <li>For more control over the tests, go the <a href="http://github.com/kig/canvas3d-tests">GitHub page</a>, see the readme, and clone the repo.</li>
+ </ol>
+
+ <h2>Want to contribute?</h2>
+
+ <p>See the <a href="README.md">README</a>.</p>
+ <p>See the <a href="http://github.com/kig/canvas3d-tests">GitHub page</a>.</p>
+ <p>Mail me at <a href="mailto:ilmari.heikkinen@gmail.com">ilmari.heikkinen@gmail.com</a></p>
+
+
+ <h2>For more information on WebGL</h2>
+
+ <ul>
+ <li><a href="http://planet-webgl.org">Planet WebGL</a></li>
+ <li><a href="http://learningwebgl.com">Learning WebGL</a></li>
+ <li><a href="http://www.khronos.org/message_boards/viewforum.php?f=34">WebGL on Khronos Message Boards</a></li>
+ </ul>
+
+ <h2>Developer links</h2>
+ <ul>
+ <li><a href="https://bugzilla.mozilla.org/buglist.cgi?quicksearch=webgl">WebGL on Mozilla Bugzilla</a></li>
+ <li><a href="https://bugzilla.webkit.org/buglist.cgi?quicksearch=webgl">WebGL on WebKit Bugzilla</a></li>
+ <li><a href="http://code.google.com/p/chromium/issues/list?q=label:3D-WebGL">WebGL on Chromium Bugzilla</a></li>
+ </ul>
+
+
+ <h2>License</h2>
+
+ <p>
+ These tests are released under the BSD license. The images and videos used in the tests are the respective property of their authors.
+ </p>
+
+ </body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/unit.css b/dom/canvas/test/webgl-conf/checkout/conformance/more/unit.css
new file mode 100644
index 0000000000..0758b43bd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/unit.css
@@ -0,0 +1,66 @@
+/*
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009 Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is 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 Software.
+
+THE SOFTWARE IS 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 SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+.ok {
+ color: green;
+}
+.fail {
+ color: red;
+}
+canvas {
+ display: none;
+}
+#test-status {
+ font-size: large;
+}
+
+#test-log {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ background: white;
+ color: black;
+}
+#test-log > div {
+ padding-bottom: 0.5em;
+}
+#test-log h2 {
+ font-size: 1em;
+ margin-bottom: 0em;
+ padding-top: 0.5em;
+}
+#test-log h3 {
+ font-size: small;
+ margin-left: 1.5em;
+ margin-bottom: 0em;
+ margin-top: 0.5em;
+}
+#test-log p {
+ margin-left: 4em;
+ font-size: small;
+ margin-top: 0em;
+ margin-bottom: 0.2em;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/unit.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/unit.js
new file mode 100644
index 0000000000..3ca21c4cae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/unit.js
@@ -0,0 +1,970 @@
+/*
+Unit testing library for the OpenGL ES 2.0 HTML Canvas context
+*/
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+/* -- plaform specific code -- */
+
+// WebKit
+if (window.testRunner && !window.layoutTestController) {
+ window.layoutTestController = window.testRunner;
+}
+
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+
+ // 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() { };
+
+ // RAF doesn't work in LayoutTests. Disable it so the tests will
+ // use setTimeout instead.
+ window.requestAnimationFrame = undefined;
+ window.webkitRequestAnimationFrame = undefined;
+}
+
+if (window.internals) {
+ window.internals.settings.setWebGLErrorsToConsoleEnabled(false);
+}
+
+/* -- end platform specific code --*/
+Tests = {
+ autorun : true,
+ message : null,
+ delay : 0,
+ autoinit: true,
+
+ startUnit : function(){ return []; },
+ setup : function() { return arguments; },
+ teardown : function() {},
+ endUnit : function() {}
+}
+
+var __testSuccess__ = true;
+var __testFailCount__ = 0;
+var __testLog__;
+var __backlog__ = [];
+
+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;
+ }
+ })();
+}
+
+Object.toSource = function(a, seen){
+ if (a == null) return "null";
+ if (typeof a == 'boolean') return a ? "true" : "false";
+ if (typeof a == 'string') return '"' + a.replace(/"/g, '\\"') + '"';
+ if (a instanceof HTMLElement) return a.toString();
+ if (a.width && a.height && a.data) return "[ImageData]";
+ if (a instanceof Array) {
+ if (!seen) seen = [];
+ var idx = seen.indexOf(a);
+ if (idx != -1) return '#'+(idx+1)+'#';
+ seen.unshift(a);
+ var srcs = a.map(function(o){ return Object.toSource(o,seen) });
+ var prefix = '';
+ idx = seen.indexOf(a);
+ if (idx != -1) prefix = '#'+(idx+1)+'=';
+ return prefix + '[' + srcs.join(", ") + ']';
+ }
+ if (typeof a == 'object') {
+ if (!seen) seen = [];
+ var idx = seen.indexOf(a);
+ if (idx != -1) return '#'+(idx+1)+'#';
+ seen.unshift(a);
+ var members = [];
+ var name;
+ try {
+ for (var i in a) {
+ if (i.search(/^[a-zA-Z0-9]+$/) != -1)
+ name = i;
+ else
+ name = '"' + i.replace(/"/g, '\\"') + '"';
+ var ai;
+ try { ai = a[i]; }
+ catch(e) { ai = 'null /*ERROR_ACCESSING*/'; }
+ var s = name + ':' + Object.toSource(ai, seen);
+ members.push(s);
+ }
+ } catch (e) {}
+ var prefix = '';
+ idx = seen.indexOf(a);
+ if (idx != -1) prefix = '#'+(idx+1)+'=';
+ return prefix + '{' + members.join(", ") + '}'
+ }
+ if (typeof a == 'function')
+ return '('+a.toString().replace(/\n/g, " ").replace(/\s+/g, " ")+')';
+ return a.toString();
+}
+
+function formatError(e) {
+ if (window.console) console.log(e);
+ var pathSegs = location.href.toString().split("/");
+ var currentDoc = e.lineNumber != null ? pathSegs[pathSegs.length - 1] : null;
+ var trace = (e.filename || currentDoc) + ":" + e.lineNumber + (e.trace ? "\n"+e.trace : "");
+ return e.message + "\n" + trace;
+}
+
+function runTests() {
+ var h = document.getElementById('test-status');
+ if (h == null) {
+ h = document.createElement('h1');
+ h.id = 'test-status';
+ document.body.appendChild(h);
+ }
+ h.textContent = "";
+ var log = document.getElementById('test-log');
+ if (log == null) {
+ log = document.createElement('div');
+ log.id = 'test-log';
+ document.body.appendChild(log);
+ }
+ while (log.childNodes.length > 0)
+ log.removeChild(log.firstChild);
+
+ var setup_args = [];
+
+ if (Tests.startUnit != null) {
+ __testLog__ = document.createElement('div');
+ try {
+ setup_args = Tests.startUnit();
+ if (__testLog__.childNodes.length > 0)
+ log.appendChild(__testLog__);
+ } catch(e) {
+ testFailed("startUnit", formatError(e));
+ log.appendChild(__testLog__);
+ printTestStatus();
+ return;
+ }
+ }
+
+ var testsRun = false;
+ var allTestsSuccessful = true;
+
+ for (var i in Tests) {
+ if (i.substring(0,4) != "test") continue;
+ __testLog__ = document.createElement('div');
+ __testSuccess__ = true;
+ try {
+ doTestNotify (i);
+ var args = setup_args;
+ if (Tests.setup != null)
+ args = Tests.setup.apply(Tests, setup_args);
+ Tests[i].apply(Tests, args);
+ if (Tests.teardown != null)
+ Tests.teardown.apply(Tests, args);
+ }
+ catch (e) {
+ testFailed(i, e.name, formatError(e));
+ }
+ if (__testSuccess__ == false) {
+ ++__testFailCount__;
+ }
+ var h = document.createElement('h2');
+ h.textContent = i;
+ __testLog__.insertBefore(h, __testLog__.firstChild);
+ log.appendChild(__testLog__);
+ allTestsSuccessful = allTestsSuccessful && __testSuccess__ == true;
+ reportTestResultsToHarness(__testSuccess__, i);
+ doTestNotify (i+"--"+(__testSuccess__?"OK":"FAIL"));
+ testsRun = true;
+ }
+
+ printTestStatus(testsRun);
+ if (Tests.endUnit != null) {
+ __testLog__ = document.createElement('div');
+ try {
+ Tests.endUnit.apply(Tests, setup_args);
+ if (__testLog__.childNodes.length > 0)
+ log.appendChild(__testLog__);
+ } catch(e) {
+ testFailed("endUnit", e.name, formatError(e));
+ log.appendChild(__testLog__);
+ }
+ }
+ notifyFinishedToHarness(allTestsSuccessful, "finished tests");
+}
+
+function doTestNotify(name) {
+ //try {
+ // var xhr = new XMLHttpRequest();
+ // xhr.open("GET", "http://localhost:8888/"+name, true);
+ // xhr.send(null);
+ //} catch(e) {}
+}
+
+function testFailed(assertName, name) {
+ var d = document.createElement('div');
+ var h = document.createElement('h3');
+ var d1 = document.createElement("span");
+ h.appendChild(d1);
+ d1.appendChild(document.createTextNode("FAIL: "));
+ d1.style.color = "red";
+ h.appendChild(document.createTextNode(
+ name==null ? assertName : name + " (in " + assertName + ")"));
+ d.appendChild(h);
+ var args = []
+ for (var i=2; i<arguments.length; i++) {
+ var a = arguments[i];
+ var p = document.createElement('p');
+ p.style.whiteSpace = 'pre';
+ p.textContent = (a == null) ? "null" :
+ (typeof a == 'boolean' || typeof a == 'string') ? a : Object.toSource(a);
+ args.push(p.textContent);
+ d.appendChild(p);
+ }
+ __testLog__.appendChild(d);
+ __testSuccess__ = false;
+ doTestNotify([assertName, name].concat(args).join("--"));
+}
+
+function testPassed(assertName, name) {
+ if (!quietMode()) {
+ var d = document.createElement('div');
+ var h = document.createElement('h3');
+ var d1 = document.createElement("span");
+ h.appendChild(d1);
+ d1.appendChild(document.createTextNode("PASS: "));
+ d1.style.color = "green";
+ h.appendChild(document.createTextNode(
+ name==null ? assertName : name + " (in " + assertName + ")"));
+ d.appendChild(h);
+ var args = []
+ for (var i=2; i<arguments.length; i++) {
+ var a = arguments[i];
+ var p = document.createElement('p');
+ p.style.whiteSpace = 'pre';
+ p.textContent = (a == null) ? "null" :
+ (typeof a == 'boolean' || typeof a == 'string') ? a : Object.toSource(a);
+ args.push(p.textContent);
+ d.appendChild(p);
+ }
+ __testLog__.appendChild(d);
+ }
+ doTestNotify([assertName, name].concat(args).join("--"));
+}
+
+function checkTestSuccess() {
+ return __testFailCount__ == 0;
+}
+
+window.addEventListener('load', function(){
+ for (var i=0; i<__backlog__.length; i++)
+ log(__backlog__[i]);
+}, false);
+
+function log(msg) {
+ var p = document.createElement('p');
+ var a = [];
+ for (var i=0; i<arguments.length; i++)
+ a.push(arguments[i]);
+ p.textContent = a.join(", ");
+ if (!__testLog__) {
+ if (document.body)
+ document.body.appendChild(p);
+ else
+ __backlog__.push(msg);
+ } else {
+ __testLog__.appendChild(p);
+ }
+}
+
+function printTestStatus(testsRun) {
+ var status = document.getElementById('test-status');
+ if (testsRun) {
+ status.className = checkTestSuccess() ? 'ok' : 'fail';
+ status.textContent = checkTestSuccess() ? "PASS" : "FAIL";
+ } else {
+ status.className = 'fail';
+ status.textContent = "NO TESTS FOUND";
+ }
+}
+
+function assertFail(name, f) {
+ if (f == null) { f = name; name = null; }
+ var r = false;
+ try { f(); } catch(e) { r=true; }
+ if (!r) {
+ testFailed("assertFail", name, f);
+ return false;
+ } else {
+ testPassed("assertFail", name, f);
+ return true;
+ }
+}
+
+function assertOk(name, f) {
+ if (f == null) { f = name; name = null; }
+ var r = false;
+ var err;
+ try { f(); r=true; } catch(e) { err = e; }
+ if (!r) {
+ testFailed("assertOk", name, f, err.toString());
+ return false;
+ } else {
+ testPassed("assertOk", name, f);
+ return true;
+ }
+}
+
+function assert(name, v) {
+ if (v == null) { v = name; name = null; }
+ if (!v) {
+ testFailed("assert", name, v);
+ return false;
+ } else {
+ testPassed("assert", name, v);
+ return true;
+ }
+}
+
+function assertProperty(name, v, p) {
+ if (p == null) { p = v; v = name; name = p; }
+ if (v[p] == null) {
+ testFailed("assertProperty", name);
+ return false;
+ } else {
+ testPassed("assertProperty", name);
+ return true;
+ }
+}
+
+function compare(a,b) {
+ if (typeof a == 'number' && typeof b == 'number') {
+ return a == b;
+ } else {
+ return Object.toSource(a) == Object.toSource(b);
+ }
+}
+
+function assertEquals(name, v, p) {
+ if (p == null) { p = v; v = name; name = null; }
+ if (!compare(v, p)) {
+ testFailed("assertEquals", name, v, p);
+ return false;
+ } else {
+ testPassed("assertEquals", name, v, p);
+ return true;
+ }
+}
+
+function assertArrayEquals(name, v, p) {
+ if (p == null) { p = v; v = name; name = null; }
+ if (!v) {
+ testFailed("assertArrayEquals: first array undefined", name, v, p);
+ return false;
+ }
+ if (!p) {
+ testFailed("assertArrayEquals: second array undefined", name, v, p);
+ return false;
+ }
+ if (v.length != p.length) {
+ testFailed("assertArrayEquals", name, v, p);
+ return false;
+ }
+ for (var ii = 0; ii < v.length; ++ii) {
+ if (v[ii] != p[ii]) {
+ testFailed("assertArrayEquals", name, v, p);
+ return false;
+ }
+ }
+ testPassed("assertArrayEquals", name, v, p);
+ return true;
+}
+
+function assertArrayEqualsWithEpsilon(name, v, p, l) {
+ if (l == null) { l = p; p = v; v = name; name = null; }
+ if (!v) {
+ testFailed("assertArrayEqualsWithEpsilon: first array undefined", name, v, p);
+ return false;
+ }
+ if (!p) {
+ testFailed("assertArrayEqualsWithEpsilon: second array undefined", name, v, p);
+ return false;
+ }
+ if (!l) {
+ testFailed("assertArrayEqualsWithEpsilon: limit array undefined", name, v, p);
+ return false;
+ }
+ if (v.length != p.length) {
+ testFailed("assertArrayEqualsWithEpsilon", name, v, p, l);
+ return false;
+ }
+ if (v.length != l.length) {
+ testFailed("assertArrayEqualsWithEpsilon", name, v, p, l);
+ return false;
+ }
+ for (var ii = 0; ii < v.length; ++ii) {
+ if (Math.abs(v[ii]- p[ii])>l[ii]) {
+ testFailed("assertArrayEqualsWithEpsilon", name, v, p, l);
+ return false;
+ }
+ }
+ testPassed("assertArrayEqualsWithEpsilon", name, v, p, l);
+ return true;
+}
+
+function assertNotEquals(name, v, p) {
+ if (p == null) { p = v; v = name; name = null; }
+ if (compare(v, p)) {
+ testFailed("assertNotEquals", name, v, p)
+ return false;
+ } else {
+ testPassed("assertNotEquals", name, v, p)
+ return true;
+ }
+}
+
+function time(elementId, f) {
+ var s = document.getElementById(elementId);
+ var t0 = new Date().getTime();
+ f();
+ var t1 = new Date().getTime();
+ s.textContent = 'Elapsed: '+(t1-t0)+' ms';
+}
+
+function randomFloat () {
+ // note that in fuzz-testing, this can used as the size of a buffer to allocate.
+ // so it shouldn't return astronomic values. The maximum value 10000000 is already quite big.
+ var fac = 1.0;
+ var r = Math.random();
+ if (r < 0.25)
+ fac = 10;
+ else if (r < 0.4)
+ fac = 100;
+ else if (r < 0.5)
+ fac = 1000;
+ else if (r < 0.6)
+ fac = 100000;
+ else if (r < 0.7)
+ fac = 10000000;
+ else if (r < 0.8)
+ fac = NaN;
+ return -0.5*fac + Math.random() * fac;
+}
+function randomFloatFromRange(lo, hi) {
+ var r = Math.random();
+ if (r < 0.05)
+ return lo;
+ else if (r > 0.95)
+ return hi;
+ else
+ return lo + Math.random()*(hi-lo);
+}
+function randomInt (sz) {
+ if (sz != null)
+ return Math.floor(Math.random()*sz);
+ else
+ return Math.floor(randomFloat());
+}
+function randomIntFromRange(lo, hi) {
+ return Math.floor(randomFloatFromRange(lo, hi));
+}
+function randomLength () {
+ var l = Math.floor(Math.random() * 256);
+ if (Math.random < 0.5) l = l / 10;
+ if (Math.random < 0.3) l = l / 10;
+ return l;
+}
+function randomSmallIntArray () {
+ var l = randomLength();
+ var s = new Array(l);
+ for (var i=0; i<l; i++)
+ s[i] = Math.floor(Math.random() * 256)-1;
+ return s;
+}
+function randomFloatArray () {
+ var l = randomLength();
+ var s = new Array(l);
+ for (var i=0; i<l; i++)
+ s[i] = randomFloat();
+ return s;
+}
+function randomIntArray () {
+ var l = randomLength();
+ var s = new Array(l);
+ for (var i=0; i<l; i++)
+ s[i] = randomFloat();
+ return s;
+}
+function randomMixedArray () {
+ var l = randomLength();
+ var s = new Array(l);
+ for (var i=0; i<l; i++)
+ s[i] = randomNonArray();
+ return s;
+}
+function randomArray () {
+ var r = Math.random();
+ if (r < 0.3)
+ return randomFloatArray();
+ else if (r < 0.6)
+ return randomIntArray();
+ else if (r < 0.8)
+ return randomSmallIntArray();
+ else
+ return randomMixedArray();
+}
+function randomString () {
+ return String.fromCharCode.apply(String, randomSmallIntArray());
+}
+function randomGLConstant () {
+ return GLConstants[Math.floor(Math.random() * GLConstants.length)];
+}
+
+function randomNonArray() {
+ var r = Math.random();
+ if (r < 0.25) {
+ return randomFloat();
+ } else if (r < 0.6) {
+ return randomInt();
+ } else if (r < 0.7) {
+ return (r < 0.65);
+ } else if (r < 0.87) {
+ return randomString();
+ } else if (r < 0.98) {
+ return randomGLConstant();
+ } else {
+ return null;
+ }
+}
+
+function generateRandomArg(pos, count) {
+ if (pos == 0 && Math.random() < 0.5)
+ return randomGLConstant();
+ if (pos == count-1 && Math.random() < 0.25)
+ if (Math.random() < 0.5)
+ return randomString();
+ else
+ return randomArray();
+ var r = Math.random();
+ if (r < 0.25) {
+ return randomFloat();
+ } else if (r < 0.6) {
+ return randomInt();
+ } else if (r < 0.7) {
+ return (r < 0.65);
+ } else if (r < 0.77) {
+ return randomString();
+ } else if (r < 0.84) {
+ return randomArray();
+ } else if (r < 0.98) {
+ return randomGLConstant();
+ } else {
+ return null;
+ }
+}
+
+
+function generateRandomArgs(count) {
+ var arr = new Array(count);
+ for (var i=0; i<count; i++)
+ arr[i] = generateRandomArg(i, count);
+ return arr;
+}
+
+// qc (arg1gen, arg2gen, ..., predicate)
+// qc (randomString, randomInt, randomInt, function(s,i,j){ s.substring(i,j) })
+function qc() {
+}
+
+GLConstants = [
+1,
+0x00000100,
+0x00000400,
+0x00004000,
+0x0000,
+0x0001,
+0x0002,
+0x0003,
+0x0004,
+0x0005,
+0x0006,
+0,
+1,
+0x0300,
+0x0301,
+0x0302,
+0x0303,
+0x0304,
+0x0305,
+0x0306,
+0x0307,
+0x0308,
+0x8006,
+0x8009,
+0x8009,
+0x883D,
+0x800A,
+0x800B,
+0x80C8,
+0x80C9,
+0x80CA,
+0x80CB,
+0x8001,
+0x8002,
+0x8003,
+0x8004,
+0x8005,
+0x8892,
+0x8893,
+0x8894,
+0x8895,
+0x88E0,
+0x88E4,
+0x88E8,
+0x8764,
+0x8765,
+0x8626,
+0x0404,
+0x0405,
+0x0408,
+0x0DE1,
+0x0B44,
+0x0BE2,
+0x0BD0,
+0x0B90,
+0x0B71,
+0x0C11,
+0x8037,
+0x809E,
+0x80A0,
+0,
+0x0500,
+0x0501,
+0x0502,
+0x0505,
+0x0900,
+0x0901,
+0x0B21,
+0x846D,
+0x846E,
+0x0B45,
+0x0B46,
+0x0B70,
+0x0B72,
+0x0B73,
+0x0B74,
+0x0B91,
+0x0B92,
+0x0B94,
+0x0B95,
+0x0B96,
+0x0B97,
+0x0B93,
+0x0B98,
+0x8800,
+0x8801,
+0x8802,
+0x8803,
+0x8CA3,
+0x8CA4,
+0x8CA5,
+0x0BA2,
+0x0C10,
+0x0C22,
+0x0C23,
+0x0CF5,
+0x0D05,
+0x0D33,
+0x0D3A,
+0x0D50,
+0x0D52,
+0x0D53,
+0x0D54,
+0x0D55,
+0x0D56,
+0x0D57,
+0x2A00,
+0x8038,
+0x8069,
+0x80A8,
+0x80A9,
+0x80AA,
+0x80AB,
+0x86A2,
+0x86A3,
+0x1100,
+0x1101,
+0x1102,
+0x8192,
+0x1400,
+0x1401,
+0x1402,
+0x1403,
+0x1404,
+0x1405,
+0x1406,
+0x140C,
+0x1902,
+0x1906,
+0x1907,
+0x1908,
+0x1909,
+0x190A,
+0x8033,
+0x8034,
+0x8363,
+0x8B30,
+0x8B31,
+0x8869,
+0x8DFB,
+0x8DFC,
+0x8B4D,
+0x8B4C,
+0x8872,
+0x8DFD,
+0x8B4F,
+0x8B80,
+0x8B82,
+0x8B83,
+0x8B85,
+0x8B86,
+0x8B87,
+0x8B89,
+0x8B8A,
+0x8B8C,
+0x8B8D,
+0x0200,
+0x0201,
+0x0202,
+0x0203,
+0x0204,
+0x0205,
+0x0206,
+0x0207,
+0x1E00,
+0x1E01,
+0x1E02,
+0x1E03,
+0x150A,
+0x8507,
+0x8508,
+0x1F00,
+0x1F01,
+0x1F02,
+0x1F03,
+0x2600,
+0x2601,
+0x2700,
+0x2701,
+0x2702,
+0x2703,
+0x2800,
+0x2801,
+0x2802,
+0x2803,
+0x1702,
+0x8513,
+0x8514,
+0x8515,
+0x8516,
+0x8517,
+0x8518,
+0x8519,
+0x851A,
+0x851C,
+0x84C0,
+0x84C1,
+0x84C2,
+0x84C3,
+0x84C4,
+0x84C5,
+0x84C6,
+0x84C7,
+0x84C8,
+0x84C9,
+0x84CA,
+0x84CB,
+0x84CC,
+0x84CD,
+0x84CE,
+0x84CF,
+0x84D0,
+0x84D1,
+0x84D2,
+0x84D3,
+0x84D4,
+0x84D5,
+0x84D6,
+0x84D7,
+0x84D8,
+0x84D9,
+0x84DA,
+0x84DB,
+0x84DC,
+0x84DD,
+0x84DE,
+0x84DF,
+0x84E0,
+0x2901,
+0x812F,
+0x8370,
+0x8B50,
+0x8B51,
+0x8B52,
+0x8B53,
+0x8B54,
+0x8B55,
+0x8B56,
+0x8B57,
+0x8B58,
+0x8B59,
+0x8B5A,
+0x8B5B,
+0x8B5C,
+0x8B5E,
+0x8B60,
+0x8622,
+0x8623,
+0x8624,
+0x8625,
+0x886A,
+0x8645,
+0x889F,
+0x8B9A,
+0x8B9B,
+0x8B81,
+0x8B84,
+0x8B88,
+0x8DFA,
+0x8DF8,
+0x8DF9,
+0x8DF0,
+0x8DF1,
+0x8DF2,
+0x8DF3,
+0x8DF4,
+0x8DF5,
+0x8D40,
+0x8D41,
+0x8056,
+0x8057,
+0x8D62,
+0x81A5,
+0x1901,
+0x8D48,
+0x8D42,
+0x8D43,
+0x8D44,
+0x8D50,
+0x8D51,
+0x8D52,
+0x8D53,
+0x8D54,
+0x8D55,
+0x8CD0,
+0x8CD1,
+0x8CD2,
+0x8CD3,
+0x8CE0,
+0x8D00,
+0x8D20,
+0,
+0x8CD5,
+0x8CD6,
+0x8CD7,
+0x8CD9,
+0x8CDD,
+0x8CA6,
+0x8CA7,
+0x84E8,
+0x0506,
+0x809D
+];
+
+function reportTestResultsToHarness(success, msg) {
+ if (window.parent.webglTestHarness) {
+ window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg);
+ }
+}
+
+function notifyFinishedToHarness() {
+ if (window.parent.webglTestHarness) {
+ window.parent.webglTestHarness.notifyFinished(window.location.pathname);
+ }
+}
+
+function initTests() {
+ if (Tests.message != null) {
+ var h = document.getElementById('test-message');
+ if (h == null) {
+ h = document.createElement('p');
+ h.id = 'test-message';
+ document.body.insertBefore(h, document.body.firstChild);
+ }
+ h.textContent = Tests.message;
+ }
+ if (Tests.autorun) {
+ runTests();
+ } else {
+ var h = document.getElementById('test-run');
+ if (h == null) {
+ h = document.createElement('input');
+ h.type = 'submit';
+ h.value = "Run tests";
+ h.addEventListener('click', function(ev){
+ runTests();
+ ev.preventDefault();
+ }, false);
+ h.id = 'test-run';
+ document.body.insertBefore(h, document.body.firstChild);
+ }
+ h.textContent = Tests.message;
+ }
+
+}
+
+window.addEventListener('load', function(){
+ if (Tests.autoinit) {
+ // let the browser hopefully finish updating the gl canvas surfaces if we are given a delay
+ if (Tests.delay)
+ setTimeout(initTests, Tests.delay);
+ else
+ initTests()
+ }
+}, false);
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/more/util.js b/dom/canvas/test/webgl-conf/checkout/conformance/more/util.js
new file mode 100644
index 0000000000..78cc08a652
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/more/util.js
@@ -0,0 +1,1287 @@
+/*
+Utilities for the OpenGL ES 2.0 HTML Canvas context
+*/
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+function loadTexture(gl, elem, mipmaps) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elem);
+ if (mipmaps != false)
+ gl.generateMipmap(gl.TEXTURE_2D);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ if (mipmaps)
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ else
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ return tex;
+}
+
+function getShader(gl, id) {
+ var shaderScript = document.getElementById(id);
+ if (!shaderScript) {
+ throw(new Error("No shader element with id: "+id));
+ }
+
+ var str = "";
+ var k = shaderScript.firstChild;
+ while (k) {
+ if (k.nodeType == 3)
+ str += k.textContent;
+ k = k.nextSibling;
+ }
+
+ var shader;
+ if (shaderScript.type == "x-shader/x-fragment") {
+ shader = gl.createShader(gl.FRAGMENT_SHADER);
+ } else if (shaderScript.type == "x-shader/x-vertex") {
+ shader = gl.createShader(gl.VERTEX_SHADER);
+ } else {
+ throw(new Error("Unknown shader type "+shaderScript.type));
+ }
+
+ gl.shaderSource(shader, str);
+ gl.compileShader(shader);
+
+ if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) != 1) {
+ var ilog = gl.getShaderInfoLog(shader);
+ gl.deleteShader(shader);
+ throw(new Error("Failed to compile shader "+shaderScript.id + ", Shader info log: " + ilog));
+ }
+ return shader;
+}
+
+function loadShaderArray(gl, shaders) {
+ var id = gl.createProgram();
+ var shaderObjs = [];
+ for (var i=0; i<shaders.length; ++i) {
+ try {
+ var sh = getShader(gl, shaders[i]);
+ shaderObjs.push(sh);
+ gl.attachShader(id, sh);
+ } catch (e) {
+ var pr = {program: id, shaders: shaderObjs};
+ deleteShader(gl, pr);
+ throw (e);
+ }
+ }
+ var prog = {program: id, shaders: shaderObjs};
+ gl.linkProgram(id);
+ gl.validateProgram(id);
+ if (gl.getProgramParameter(id, gl.LINK_STATUS) != 1) {
+ deleteShader(gl,prog);
+ throw(new Error("Failed to link shader"));
+ }
+ if (gl.getProgramParameter(id, gl.VALIDATE_STATUS) != 1) {
+ deleteShader(gl,prog);
+ throw(new Error("Failed to validate shader"));
+ }
+ return prog;
+}
+function loadShader(gl) {
+ var sh = [];
+ for (var i=1; i<arguments.length; ++i)
+ sh.push(arguments[i]);
+ return loadShaderArray(gl, sh);
+}
+
+function deleteShader(gl, sh) {
+ gl.useProgram(null);
+ sh.shaders.forEach(function(s){
+ gl.detachShader(sh.program, s);
+ gl.deleteShader(s);
+ });
+ gl.deleteProgram(sh.program);
+}
+
+function getGLErrorAsString(ctx, err) {
+ if (err === ctx.NO_ERROR) {
+ return "NO_ERROR";
+ }
+ for (var name in ctx) {
+ if (ctx[name] === err) {
+ return name;
+ }
+ }
+ return err.toString();
+}
+
+function checkError(gl, msg) {
+ var e = gl.getError();
+ if (e != gl.NO_ERROR) {
+ log("Error " + getGLErrorAsString(gl, e) + " at " + msg);
+ }
+ return e;
+}
+
+function throwError(gl, msg) {
+ var e = gl.getError();
+ if (e != 0) {
+ throw(new Error("Error " + getGLErrorAsString(gl, e) + " at " + msg));
+ }
+}
+
+Math.cot = function(z) { return 1.0 / Math.tan(z); }
+
+/*
+ Matrix utilities, using the OpenGL element order where
+ the last 4 elements are the translation column.
+
+ Uses flat arrays as matrices for performance.
+
+ Most operations have in-place variants to avoid allocating temporary matrices.
+
+ Naming logic:
+ Matrix.method operates on a 4x4 Matrix and returns a new Matrix.
+ Matrix.method3x3 operates on a 3x3 Matrix and returns a new Matrix. Not all operations have a 3x3 version (as 3x3 is usually only used for the normal matrix: Matrix.transpose3x3(Matrix.inverseTo3x3(mat4x4)))
+ Matrix.method[3x3]InPlace(args, target) stores its result in the target matrix.
+
+ Matrix.scale([sx, sy, sz]) -- non-uniform scale by vector
+ Matrix.scale1(s) -- uniform scale by scalar
+ Matrix.scale3(sx, sy, sz) -- non-uniform scale by scalars
+
+ Ditto for translate.
+*/
+Matrix = {
+ identity : [
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0
+ ],
+
+ newIdentity : function() {
+ return [
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0
+ ];
+ },
+
+ newIdentity3x3 : function() {
+ return [
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0
+ ];
+ },
+
+ copyMatrix : function(src, dst) {
+ for (var i=0; i<16; i++) dst[i] = src[i];
+ return dst;
+ },
+
+ to3x3 : function(m) {
+ return [
+ m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10]
+ ];
+ },
+
+ // orthonormal matrix inverse
+ inverseON : function(m) {
+ var n = this.transpose4x4(m);
+ var t = [m[12], m[13], m[14]];
+ n[3] = n[7] = n[11] = 0;
+ n[12] = -Vec3.dot([n[0], n[4], n[8]], t);
+ n[13] = -Vec3.dot([n[1], n[5], n[9]], t);
+ n[14] = -Vec3.dot([n[2], n[6], n[10]], t);
+ return n;
+ },
+
+ inverseTo3x3 : function(m) {
+ return this.inverse4x4to3x3InPlace(m, this.newIdentity3x3());
+ },
+
+ inverseTo3x3InPlace : function(m,n) {
+ var a11 = m[10]*m[5]-m[6]*m[9],
+ a21 = -m[10]*m[1]+m[2]*m[9],
+ a31 = m[6]*m[1]-m[2]*m[5],
+ a12 = -m[10]*m[4]+m[6]*m[8],
+ a22 = m[10]*m[0]-m[2]*m[8],
+ a32 = -m[6]*m[0]+m[2]*m[4],
+ a13 = m[9]*m[4]-m[5]*m[8],
+ a23 = -m[9]*m[0]+m[1]*m[8],
+ a33 = m[5]*m[0]-m[1]*m[4];
+ var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
+ if (det == 0) // no inverse
+ return [1,0,0,0,1,0,0,0,1];
+ var idet = 1 / det;
+ n[0] = idet*a11;
+ n[1] = idet*a21;
+ n[2] = idet*a31;
+ n[3] = idet*a12;
+ n[4] = idet*a22;
+ n[5] = idet*a32;
+ n[6] = idet*a13;
+ n[7] = idet*a23;
+ n[8] = idet*a33;
+ return n;
+ },
+
+ inverse3x3 : function(m) {
+ return this.inverse3x3InPlace(m, this.newIdentity3x3());
+ },
+
+ inverse3x3InPlace : function(m,n) {
+ var a11 = m[8]*m[4]-m[5]*m[7],
+ a21 = -m[8]*m[1]+m[2]*m[7],
+ a31 = m[5]*m[1]-m[2]*m[4],
+ a12 = -m[8]*m[3]+m[5]*m[6],
+ a22 = m[8]*m[0]-m[2]*m[6],
+ a32 = -m[5]*m[0]+m[2]*m[3],
+ a13 = m[7]*m[4]-m[4]*m[8],
+ a23 = -m[7]*m[0]+m[1]*m[6],
+ a33 = m[4]*m[0]-m[1]*m[3];
+ var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
+ if (det == 0) // no inverse
+ return [1,0,0,0,1,0,0,0,1];
+ var idet = 1 / det;
+ n[0] = idet*a11;
+ n[1] = idet*a21;
+ n[2] = idet*a31;
+ n[3] = idet*a12;
+ n[4] = idet*a22;
+ n[5] = idet*a32;
+ n[6] = idet*a13;
+ n[7] = idet*a23;
+ n[8] = idet*a33;
+ return n;
+ },
+
+ frustum : function (left, right, bottom, top, znear, zfar) {
+ var X = 2*znear/(right-left);
+ var Y = 2*znear/(top-bottom);
+ var A = (right+left)/(right-left);
+ var B = (top+bottom)/(top-bottom);
+ var C = -(zfar+znear)/(zfar-znear);
+ var D = -2*zfar*znear/(zfar-znear);
+
+ return [
+ X, 0, 0, 0,
+ 0, Y, 0, 0,
+ A, B, C, -1,
+ 0, 0, D, 0
+ ];
+ },
+
+ perspective : function (fovy, aspect, znear, zfar) {
+ var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
+ var ymin = -ymax;
+ var xmin = ymin * aspect;
+ var xmax = ymax * aspect;
+
+ return this.frustum(xmin, xmax, ymin, ymax, znear, zfar);
+ },
+
+ mul4x4 : function (a,b) {
+ return this.mul4x4InPlace(a,b,this.newIdentity());
+ },
+
+ mul4x4InPlace : function (a, b, c) {
+ c[0] = b[0] * a[0] +
+ b[0+1] * a[4] +
+ b[0+2] * a[8] +
+ b[0+3] * a[12];
+ c[0+1] = b[0] * a[1] +
+ b[0+1] * a[5] +
+ b[0+2] * a[9] +
+ b[0+3] * a[13];
+ c[0+2] = b[0] * a[2] +
+ b[0+1] * a[6] +
+ b[0+2] * a[10] +
+ b[0+3] * a[14];
+ c[0+3] = b[0] * a[3] +
+ b[0+1] * a[7] +
+ b[0+2] * a[11] +
+ b[0+3] * a[15];
+ c[4] = b[4] * a[0] +
+ b[4+1] * a[4] +
+ b[4+2] * a[8] +
+ b[4+3] * a[12];
+ c[4+1] = b[4] * a[1] +
+ b[4+1] * a[5] +
+ b[4+2] * a[9] +
+ b[4+3] * a[13];
+ c[4+2] = b[4] * a[2] +
+ b[4+1] * a[6] +
+ b[4+2] * a[10] +
+ b[4+3] * a[14];
+ c[4+3] = b[4] * a[3] +
+ b[4+1] * a[7] +
+ b[4+2] * a[11] +
+ b[4+3] * a[15];
+ c[8] = b[8] * a[0] +
+ b[8+1] * a[4] +
+ b[8+2] * a[8] +
+ b[8+3] * a[12];
+ c[8+1] = b[8] * a[1] +
+ b[8+1] * a[5] +
+ b[8+2] * a[9] +
+ b[8+3] * a[13];
+ c[8+2] = b[8] * a[2] +
+ b[8+1] * a[6] +
+ b[8+2] * a[10] +
+ b[8+3] * a[14];
+ c[8+3] = b[8] * a[3] +
+ b[8+1] * a[7] +
+ b[8+2] * a[11] +
+ b[8+3] * a[15];
+ c[12] = b[12] * a[0] +
+ b[12+1] * a[4] +
+ b[12+2] * a[8] +
+ b[12+3] * a[12];
+ c[12+1] = b[12] * a[1] +
+ b[12+1] * a[5] +
+ b[12+2] * a[9] +
+ b[12+3] * a[13];
+ c[12+2] = b[12] * a[2] +
+ b[12+1] * a[6] +
+ b[12+2] * a[10] +
+ b[12+3] * a[14];
+ c[12+3] = b[12] * a[3] +
+ b[12+1] * a[7] +
+ b[12+2] * a[11] +
+ b[12+3] * a[15];
+ return c;
+ },
+
+ mulv4 : function (a, v) {
+ c = new Array(4);
+ for (var i=0; i<4; ++i) {
+ var x = 0;
+ for (var k=0; k<4; ++k)
+ x += v[k] * a[k*4+i];
+ c[i] = x;
+ }
+ return c;
+ },
+
+ rotate : function (angle, axis) {
+ axis = Vec3.normalize(axis);
+ var x=axis[0], y=axis[1], z=axis[2];
+ var c = Math.cos(angle);
+ var c1 = 1-c;
+ var s = Math.sin(angle);
+ return [
+ x*x*c1+c, y*x*c1+z*s, z*x*c1-y*s, 0,
+ x*y*c1-z*s, y*y*c1+c, y*z*c1+x*s, 0,
+ x*z*c1+y*s, y*z*c1-x*s, z*z*c1+c, 0,
+ 0,0,0,1
+ ];
+ },
+ rotateInPlace : function(angle, axis, m) {
+ axis = Vec3.normalize(axis);
+ var x=axis[0], y=axis[1], z=axis[2];
+ var c = Math.cos(angle);
+ var c1 = 1-c;
+ var s = Math.sin(angle);
+ var tmpMatrix = this.tmpMatrix;
+ var tmpMatrix2 = this.tmpMatrix2;
+ tmpMatrix[0] = x*x*c1+c; tmpMatrix[1] = y*x*c1+z*s; tmpMatrix[2] = z*x*c1-y*s; tmpMatrix[3] = 0;
+ tmpMatrix[4] = x*y*c1-z*s; tmpMatrix[5] = y*y*c1+c; tmpMatrix[6] = y*z*c1+x*s; tmpMatrix[7] = 0;
+ tmpMatrix[8] = x*z*c1+y*s; tmpMatrix[9] = y*z*c1-x*s; tmpMatrix[10] = z*z*c1+c; tmpMatrix[11] = 0;
+ tmpMatrix[12] = 0; tmpMatrix[13] = 0; tmpMatrix[14] = 0; tmpMatrix[15] = 1;
+ this.copyMatrix(m, tmpMatrix2);
+ return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m);
+ },
+
+ scale : function(v) {
+ return [
+ v[0], 0, 0, 0,
+ 0, v[1], 0, 0,
+ 0, 0, v[2], 0,
+ 0, 0, 0, 1
+ ];
+ },
+ scale3 : function(x,y,z) {
+ return [
+ x, 0, 0, 0,
+ 0, y, 0, 0,
+ 0, 0, z, 0,
+ 0, 0, 0, 1
+ ];
+ },
+ scale1 : function(s) {
+ return [
+ s, 0, 0, 0,
+ 0, s, 0, 0,
+ 0, 0, s, 0,
+ 0, 0, 0, 1
+ ];
+ },
+ scale3InPlace : function(x, y, z, m) {
+ var tmpMatrix = this.tmpMatrix;
+ var tmpMatrix2 = this.tmpMatrix2;
+ tmpMatrix[0] = x; tmpMatrix[1] = 0; tmpMatrix[2] = 0; tmpMatrix[3] = 0;
+ tmpMatrix[4] = 0; tmpMatrix[5] = y; tmpMatrix[6] = 0; tmpMatrix[7] = 0;
+ tmpMatrix[8] = 0; tmpMatrix[9] = 0; tmpMatrix[10] = z; tmpMatrix[11] = 0;
+ tmpMatrix[12] = 0; tmpMatrix[13] = 0; tmpMatrix[14] = 0; tmpMatrix[15] = 1;
+ this.copyMatrix(m, tmpMatrix2);
+ return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m);
+ },
+ scale1InPlace : function(s, m) { return this.scale3InPlace(s, s, s, m); },
+ scaleInPlace : function(s, m) { return this.scale3InPlace(s[0],s[1],s[2],m); },
+
+ translate3 : function(x,y,z) {
+ return [
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ x, y, z, 1
+ ];
+ },
+
+ translate : function(v) {
+ return this.translate3(v[0], v[1], v[2]);
+ },
+ tmpMatrix : [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0],
+ tmpMatrix2 : [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0],
+ translate3InPlace : function(x,y,z,m) {
+ var tmpMatrix = this.tmpMatrix;
+ var tmpMatrix2 = this.tmpMatrix2;
+ tmpMatrix[0] = 1; tmpMatrix[1] = 0; tmpMatrix[2] = 0; tmpMatrix[3] = 0;
+ tmpMatrix[4] = 0; tmpMatrix[5] = 1; tmpMatrix[6] = 0; tmpMatrix[7] = 0;
+ tmpMatrix[8] = 0; tmpMatrix[9] = 0; tmpMatrix[10] = 1; tmpMatrix[11] = 0;
+ tmpMatrix[12] = x; tmpMatrix[13] = y; tmpMatrix[14] = z; tmpMatrix[15] = 1;
+ this.copyMatrix(m, tmpMatrix2);
+ return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m);
+ },
+ translateInPlace : function(v,m){ return this.translate3InPlace(v[0], v[1], v[2], m); },
+
+ lookAt : function (eye, center, up) {
+ var z = Vec3.direction(eye, center);
+ var x = Vec3.normalizeInPlace(Vec3.cross(up, z));
+ var y = Vec3.normalizeInPlace(Vec3.cross(z, x));
+
+ var m = [
+ x[0], y[0], z[0], 0,
+ x[1], y[1], z[1], 0,
+ x[2], y[2], z[2], 0,
+ 0, 0, 0, 1
+ ];
+
+ var t = [
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ -eye[0], -eye[1], -eye[2], 1
+ ];
+
+ return this.mul4x4(m,t);
+ },
+
+ transpose4x4 : function(m) {
+ return [
+ m[0], m[4], m[8], m[12],
+ m[1], m[5], m[9], m[13],
+ m[2], m[6], m[10], m[14],
+ m[3], m[7], m[11], m[15]
+ ];
+ },
+
+ transpose4x4InPlace : function(m) {
+ var tmp = 0.0;
+ tmp = m[1]; m[1] = m[4]; m[4] = tmp;
+ tmp = m[2]; m[2] = m[8]; m[8] = tmp;
+ tmp = m[3]; m[3] = m[12]; m[12] = tmp;
+ tmp = m[6]; m[6] = m[9]; m[9] = tmp;
+ tmp = m[7]; m[7] = m[13]; m[13] = tmp;
+ tmp = m[11]; m[11] = m[14]; m[14] = tmp;
+ return m;
+ },
+
+ transpose3x3 : function(m) {
+ return [
+ m[0], m[3], m[6],
+ m[1], m[4], m[7],
+ m[2], m[5], m[8]
+ ];
+ },
+
+ transpose3x3InPlace : function(m) {
+ var tmp = 0.0;
+ tmp = m[1]; m[1] = m[3]; m[3] = tmp;
+ tmp = m[2]; m[2] = m[6]; m[6] = tmp;
+ tmp = m[5]; m[5] = m[7]; m[7] = tmp;
+ return m;
+ },
+}
+
+Vec3 = {
+ make : function() { return [0,0,0]; },
+ copy : function(v) { return [v[0],v[1],v[2]]; },
+
+ add : function (u,v) {
+ return [u[0]+v[0], u[1]+v[1], u[2]+v[2]];
+ },
+
+ sub : function (u,v) {
+ return [u[0]-v[0], u[1]-v[1], u[2]-v[2]];
+ },
+
+ negate : function (u) {
+ return [-u[0], -u[1], -u[2]];
+ },
+
+ direction : function (u,v) {
+ return this.normalizeInPlace(this.sub(u,v));
+ },
+
+ normalizeInPlace : function(v) {
+ var imag = 1.0 / Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+ v[0] *= imag; v[1] *= imag; v[2] *= imag;
+ return v;
+ },
+
+ normalize : function(v) {
+ return this.normalizeInPlace(this.copy(v));
+ },
+
+ scale : function(f, v) {
+ return [f*v[0], f*v[1], f*v[2]];
+ },
+
+ dot : function(u,v) {
+ return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
+ },
+
+ inner : function(u,v) {
+ return [u[0]*v[0], u[1]*v[1], u[2]*v[2]];
+ },
+
+ cross : function(u,v) {
+ return [
+ u[1]*v[2] - u[2]*v[1],
+ u[2]*v[0] - u[0]*v[2],
+ u[0]*v[1] - u[1]*v[0]
+ ];
+ }
+}
+
+Shader = function(gl){
+ this.gl = gl;
+ this.shaders = [];
+ this.uniformLocations = {};
+ this.attribLocations = {};
+ for (var i=1; i<arguments.length; i++) {
+ this.shaders.push(arguments[i]);
+ }
+}
+Shader.prototype = {
+ id : null,
+ gl : null,
+ compiled : false,
+ shader : null,
+ shaders : [],
+
+ destroy : function() {
+ if (this.shader != null) deleteShader(this.gl, this.shader);
+ },
+
+ compile : function() {
+ this.shader = loadShaderArray(this.gl, this.shaders);
+ },
+
+ use : function() {
+ if (this.shader == null)
+ this.compile();
+ this.gl.useProgram(this.shader.program);
+ },
+
+ uniform1fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform1fv(loc, value);
+ },
+
+ uniform2fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform2fv(loc, value);
+ },
+
+ uniform3fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform3fv(loc, value);
+ },
+
+ uniform4fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform4fv(loc, value);
+ },
+
+ uniform1f : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform1f(loc, value);
+ },
+
+ uniform2f : function(name, v1,v2) {
+ var loc = this.uniform(name);
+ this.gl.uniform2f(loc, v1,v2);
+ },
+
+ uniform3f : function(name, v1,v2,v3) {
+ var loc = this.uniform(name);
+ this.gl.uniform3f(loc, v1,v2,v3);
+ },
+
+ uniform4f : function(name, v1,v2,v3,v4) {
+ var loc = this.uniform(name);
+ this.gl.uniform4f(loc, v1, v2, v3, v4);
+ },
+
+ uniform1iv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform1iv(loc, value);
+ },
+
+ uniform2iv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform2iv(loc, value);
+ },
+
+ uniform3iv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform3iv(loc, value);
+ },
+
+ uniform4iv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform4iv(loc, value);
+ },
+
+ uniform1i : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniform1i(loc, value);
+ },
+
+ uniform2i : function(name, v1,v2) {
+ var loc = this.uniform(name);
+ this.gl.uniform2i(loc, v1,v2);
+ },
+
+ uniform3i : function(name, v1,v2,v3) {
+ var loc = this.uniform(name);
+ this.gl.uniform3i(loc, v1,v2,v3);
+ },
+
+ uniform4i : function(name, v1,v2,v3,v4) {
+ var loc = this.uniform(name);
+ this.gl.uniform4i(loc, v1, v2, v3, v4);
+ },
+
+ uniformMatrix4fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniformMatrix4fv(loc, false, value);
+ },
+
+ uniformMatrix3fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniformMatrix3fv(loc, false, value);
+ },
+
+ uniformMatrix2fv : function(name, value) {
+ var loc = this.uniform(name);
+ this.gl.uniformMatrix2fv(loc, false, value);
+ },
+
+ attrib : function(name) {
+ if (this.attribLocations[name] == null) {
+ var loc = this.gl.getAttribLocation(this.shader.program, name);
+ this.attribLocations[name] = loc;
+ }
+ return this.attribLocations[name];
+ },
+
+ uniform : function(name) {
+ if (this.uniformLocations[name] == null) {
+ var loc = this.gl.getUniformLocation(this.shader.program, name);
+ this.uniformLocations[name] = loc;
+ }
+ return this.uniformLocations[name];
+ }
+}
+Filter = function(gl, shader) {
+ Shader.apply(this, arguments);
+}
+Filter.prototype = new Shader();
+Filter.prototype.apply = function(init) {
+ this.use();
+ var va = this.attrib("Vertex");
+ var ta = this.attrib("Tex");
+ var vbo = Quad.getCachedVBO(this.gl);
+ if (init) init(this);
+ vbo.draw(va, null, ta);
+}
+
+
+VBO = function(gl) {
+ this.gl = gl;
+ this.data = [];
+ this.elementsVBO = null;
+ for (var i=1; i<arguments.length; i++) {
+ if (arguments[i].elements)
+ this.elements = arguments[i];
+ else
+ this.data.push(arguments[i]);
+ }
+}
+
+VBO.prototype = {
+ initialized : false,
+ length : 0,
+ vbos : null,
+ type : 'TRIANGLES',
+ elementsVBO : null,
+ elements : null,
+
+ setData : function() {
+ this.destroy();
+ this.data = [];
+ for (var i=0; i<arguments.length; i++) {
+ if (arguments[i].elements)
+ this.elements = arguments[i];
+ else
+ this.data.push(arguments[i]);
+ }
+ },
+
+ destroy : function() {
+ if (this.vbos != null)
+ for (var i=0; i<this.vbos.length; i++)
+ this.gl.deleteBuffer(this.vbos[i]);
+ if (this.elementsVBO != null)
+ this.gl.deleteBuffer(this.elementsVBO);
+ this.length = this.elementsLength = 0;
+ this.vbos = this.elementsVBO = null;
+ this.initialized = false;
+ },
+
+ init : function() {
+ this.destroy();
+ var gl = this.gl;
+
+ gl.getError();
+ var vbos = [];
+ var length = 0;
+ for (var i=0; i<this.data.length; i++)
+ vbos.push(gl.createBuffer());
+ if (this.elements != null)
+ this.elementsVBO = gl.createBuffer();
+ try {
+ throwError(gl, "genBuffers");
+ for (var i = 0; i<this.data.length; i++) {
+ var d = this.data[i];
+ var dlen = Math.floor(d.data.length / d.size);
+ if (i == 0 || dlen < length)
+ length = dlen;
+ if (!d.floatArray)
+ d.floatArray = new Float32Array(d.data);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbos[i]);
+ throwError(gl, "bindBuffer");
+ gl.bufferData(gl.ARRAY_BUFFER, d.floatArray, gl.STATIC_DRAW);
+ throwError(gl, "bufferData");
+ }
+ if (this.elementsVBO != null) {
+ var d = this.elements;
+ this.elementsLength = d.data.length;
+ this.elementsType = d.type == gl.UNSIGNED_BYTE ? d.type : gl.UNSIGNED_SHORT;
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementsVBO);
+ throwError(gl, "bindBuffer ELEMENT_ARRAY_BUFFER");
+ if (this.elementsType == gl.UNSIGNED_SHORT && !d.ushortArray) {
+ d.ushortArray = new Uint16Array(d.data);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, d.ushortArray, gl.STATIC_DRAW);
+ } else if (this.elementsType == gl.UNSIGNED_BYTE && !d.ubyteArray) {
+ d.ubyteArray = new Uint8Array(d.data);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, d.ubyteArray, gl.STATIC_DRAW);
+ }
+ throwError(gl, "bufferData ELEMENT_ARRAY_BUFFER");
+ }
+ } catch(e) {
+ for (var i=0; i<vbos.length; i++)
+ gl.deleteBuffer(vbos[i]);
+ throw(e);
+ }
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+
+ this.length = length;
+ this.vbos = vbos;
+
+ this.initialized = true;
+ },
+
+ use : function() {
+ if (!this.initialized) this.init();
+ var gl = this.gl;
+ for (var i=0; i<arguments.length; i++) {
+ if (arguments[i] == null || arguments[i] == -1) continue;
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vbos[i]);
+ gl.vertexAttribPointer(arguments[i], this.data[i].size, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(arguments[i]);
+ }
+ if (this.elementsVBO != null) {
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementsVBO);
+ }
+ },
+
+ draw : function() {
+ var args = [];
+ this.use.apply(this, arguments);
+ var gl = this.gl;
+ if (this.elementsVBO != null) {
+ gl.drawElements(gl[this.type], this.elementsLength, this.elementsType, 0);
+ } else {
+ gl.drawArrays(gl[this.type], 0, this.length);
+ }
+ }
+}
+
+FBO = function(gl, width, height, use_depth) {
+ this.gl = gl;
+ this.width = width;
+ this.height = height;
+ if (use_depth != null)
+ this.useDepth = use_depth;
+}
+FBO.prototype = {
+ initialized : false,
+ useDepth : true,
+ fbo : null,
+ rbo : null,
+ texture : null,
+
+ destroy : function() {
+ if (this.fbo) this.gl.deleteFramebuffer(this.fbo);
+ if (this.rbo) this.gl.deleteRenderbuffer(this.rbo);
+ if (this.texture) this.gl.deleteTexture(this.texture);
+ },
+
+ init : function() {
+ var gl = this.gl;
+ var w = this.width, h = this.height;
+ var fbo = this.fbo != null ? this.fbo : gl.createFramebuffer();
+ var rb;
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ checkError(gl, "FBO.init bindFramebuffer");
+ if (this.useDepth) {
+ rb = this.rbo != null ? this.rbo : gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ checkError(gl, "FBO.init bindRenderbuffer");
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h);
+ checkError(gl, "FBO.init renderbufferStorage");
+ }
+
+ var tex = this.texture != null ? this.texture : gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ try {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ } catch (e) { // argh, no null texture support
+ var tmp = this.getTempCanvas(w,h);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tmp);
+ }
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ checkError(gl, "FBO.init tex");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ checkError(gl, "FBO.init bind tex");
+
+ if (this.useDepth) {
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
+ checkError(gl, "FBO.init bind depth buffer");
+ }
+
+ var fbstat = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (fbstat != gl.FRAMEBUFFER_COMPLETE) {
+ var glv;
+ for (var v in gl) {
+ try { glv = gl[v]; } catch (e) { glv = null; }
+ if (glv == fbstat) { fbstat = v; break; }}
+ log("Framebuffer status: " + fbstat);
+ }
+ checkError(gl, "FBO.init check fbo");
+
+ this.fbo = fbo;
+ this.rbo = rb;
+ this.texture = tex;
+ this.initialized = true;
+ },
+
+ getTempCanvas : function(w, h) {
+ if (!FBO.tempCanvas) {
+ FBO.tempCanvas = document.createElement('canvas');
+ }
+ FBO.tempCanvas.width = w;
+ FBO.tempCanvas.height = h;
+ return FBO.tempCanvas;
+ },
+
+ use : function() {
+ if (!this.initialized) this.init();
+ this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo);
+ }
+}
+
+function GLError(err, msg, fileName, lineNumber) {
+ this.message = msg;
+ this.glError = err;
+}
+
+GLError.prototype = new Error();
+
+function makeGLErrorWrapper(gl, fname) {
+ return (function() {
+ try {
+ var rv = gl[fname].apply(gl, arguments);
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ throw(new GLError(
+ err, "GL error "+getGLErrorAsString(gl, err)+" in "+fname));
+ }
+ return rv;
+ } catch (e) {
+ if (e.glError !== undefined) {
+ throw e;
+ }
+ throw(new Error("Threw " + e.name +
+ " in " + fname + "\n" +
+ e.message + "\n" +
+ arguments.callee.caller));
+ }
+ });
+}
+
+function wrapGLContext(gl) {
+ var wrap = {};
+ for (var i in gl) {
+ try {
+ if (typeof gl[i] == 'function') {
+ wrap[i] = makeGLErrorWrapper(gl, i);
+ } else {
+ wrap[i] = gl[i];
+ }
+ } catch (e) {
+ // log("wrapGLContext: Error accessing " + i);
+ }
+ }
+ wrap.getError = function(){ return gl.getError(); };
+ return wrap;
+}
+
+function getGLContext(canvas) {
+ return canvas.getContext(GL_CONTEXT_ID, {antialias: false});
+}
+
+// Assert that f generates a specific GL error.
+function assertGLError(gl, err, name, f) {
+ if (f == null) { f = name; name = null; }
+ var r = false;
+ var glErr = 0;
+ try { f(); } catch(e) { r=true; glErr = e.glError; }
+ if (glErr !== err) {
+ if (glErr === undefined) {
+ testFailed("assertGLError: UNEXPECTED EXCEPTION", name, f);
+ } else {
+ testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) +
+ " actual: " + getGLErrorAsString(gl, glErr), name, f);
+ }
+ return false;
+ }
+ return true;
+}
+
+// Assert that f generates a GL error from a list.
+function assertGLErrorIn(gl, expectedErrorList, name, f) {
+ if (f == null) { f = name; name = null; }
+
+ var actualError = 0;
+ try {
+ f();
+ } catch(e) {
+ if ('glError' in e) {
+ actualError = e.glError;
+ } else {
+ testFailed("assertGLError: UNEXPCETED EXCEPTION", name, f);
+ return false;
+ }
+ }
+
+ var expectedErrorStrList = [];
+ var expectedErrorSet = {};
+ for (var i in expectedErrorList) {
+ var cur = expectedErrorList[i];
+ expectedErrorSet[cur] = true;
+ expectedErrorStrList.push(getGLErrorAsString(gl, cur));
+ }
+ var expectedErrorListStr = "[" + expectedErrorStrList.join(", ") + "]";
+
+ if (actualError in expectedErrorSet) {
+ return true;
+ }
+
+ testFailed("assertGLError: expected: " + expectedErrorListStr +
+ " actual: " + getGLErrorAsString(gl, actualError), name, f);
+ return false;
+}
+
+// Assert that f generates some GL error. Used in situations where it's
+// ambigious which of multiple possible errors will be generated.
+function assertSomeGLError(gl, name, f) {
+ if (f == null) { f = name; name = null; }
+ var r = false;
+ var glErr = 0;
+ var err = 0;
+ try { f(); } catch(e) { r=true; glErr = e.glError; }
+ if (glErr === 0) {
+ if (glErr === undefined) {
+ testFailed("assertGLError: UNEXPECTED EXCEPTION", name, f);
+ } else {
+ testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) +
+ " actual: " + getGLErrorAsString(gl, glErr), name, f);
+ }
+ return false;
+ }
+ return true;
+}
+
+// Assert that f throws an exception but does not generate a GL error.
+function assertThrowNoGLError(gl, name, f) {
+ if (f == null) { f = name; name = null; }
+ var r = false;
+ var glErr = undefined;
+ var exp;
+ try { f(); } catch(e) { r=true; glErr = e.glError; exp = e;}
+ if (!r) {
+ testFailed(
+ "assertThrowNoGLError: should have thrown exception", name, f);
+ return false;
+ } else {
+ if (glErr !== undefined) {
+ testFailed(
+ "assertThrowNoGLError: should be no GL error but generated: " +
+ getGLErrorAsString(gl, glErr), name, f);
+ return false;
+ }
+ }
+ testPassed("assertThrowNoGLError", name, f);
+ return true;
+}
+
+function assertThrows(gl, shouldThrow, info, func) {
+ var didThrow = false;
+ try {
+ func();
+ } catch (e) {
+ var didGLError = (e instanceof GLError);
+ if (!didGLError) {
+ didThrow = true;
+ }
+ }
+
+ var text = shouldThrow ? "Should throw: "
+ : "Should not throw: ";
+ var func = (didThrow == shouldThrow) ? testPassed : testFailed;
+
+ func(text + info);
+}
+
+Quad = {
+ vertices : [
+ -1,-1,0,
+ 1,-1,0,
+ -1,1,0,
+ 1,-1,0,
+ 1,1,0,
+ -1,1,0
+ ],
+ normals : [
+ 0,0,-1,
+ 0,0,-1,
+ 0,0,-1,
+ 0,0,-1,
+ 0,0,-1,
+ 0,0,-1
+ ],
+ texcoords : [
+ 0,0,
+ 1,0,
+ 0,1,
+ 1,0,
+ 1,1,
+ 0,1
+ ],
+ indices : [0,1,2,1,5,2],
+ makeVBO : function(gl) {
+ return new VBO(gl,
+ {size:3, data: Quad.vertices},
+ {size:3, data: Quad.normals},
+ {size:2, data: Quad.texcoords}
+ )
+ },
+ cache: {},
+ getCachedVBO : function(gl) {
+ if (!this.cache[gl])
+ this.cache[gl] = this.makeVBO(gl);
+ return this.cache[gl];
+ }
+}
+Cube = {
+ vertices : [ 0.5, -0.5, 0.5, // +X
+ 0.5, -0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ 0.5, 0.5, 0.5,
+
+ 0.5, 0.5, 0.5, // +Y
+ 0.5, 0.5, -0.5,
+ -0.5, 0.5, -0.5,
+ -0.5, 0.5, 0.5,
+
+ 0.5, 0.5, 0.5, // +Z
+ -0.5, 0.5, 0.5,
+ -0.5, -0.5, 0.5,
+ 0.5, -0.5, 0.5,
+
+ -0.5, -0.5, 0.5, // -X
+ -0.5, 0.5, 0.5,
+ -0.5, 0.5, -0.5,
+ -0.5, -0.5, -0.5,
+
+ -0.5, -0.5, 0.5, // -Y
+ -0.5, -0.5, -0.5,
+ 0.5, -0.5, -0.5,
+ 0.5, -0.5, 0.5,
+
+ -0.5, -0.5, -0.5, // -Z
+ -0.5, 0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ 0.5, -0.5, -0.5,
+ ],
+
+ normals : [ 1, 0, 0,
+ 1, 0, 0,
+ 1, 0, 0,
+ 1, 0, 0,
+
+ 0, 1, 0,
+ 0, 1, 0,
+ 0, 1, 0,
+ 0, 1, 0,
+
+ 0, 0, 1,
+ 0, 0, 1,
+ 0, 0, 1,
+ 0, 0, 1,
+
+ -1, 0, 0,
+ -1, 0, 0,
+ -1, 0, 0,
+ -1, 0, 0,
+
+ 0,-1, 0,
+ 0,-1, 0,
+ 0,-1, 0,
+ 0,-1, 0,
+
+ 0, 0,-1,
+ 0, 0,-1,
+ 0, 0,-1,
+ 0, 0,-1
+ ],
+
+ indices : [],
+ create : function(){
+ for (var i = 0; i < 6; i++) {
+ Cube.indices.push(i*4 + 0);
+ Cube.indices.push(i*4 + 1);
+ Cube.indices.push(i*4 + 3);
+ Cube.indices.push(i*4 + 1);
+ Cube.indices.push(i*4 + 2);
+ Cube.indices.push(i*4 + 3);
+ }
+ },
+
+ makeVBO : function(gl) {
+ return new VBO(gl,
+ {size:3, data: Cube.vertices},
+ {size:3, data: Cube.normals},
+ {elements: true, data: Cube.indices}
+ )
+ },
+ cache : {},
+ getCachedVBO : function(gl) {
+ if (!this.cache[gl])
+ this.cache[gl] = this.makeVBO(gl);
+ return this.cache[gl];
+ }
+}
+Cube.create();
+
+Sphere = {
+ vertices : [],
+ normals : [],
+ indices : [],
+ create : function(){
+ var r = 0.75;
+ function vert(theta, phi)
+ {
+ var r = 0.75;
+ var x, y, z, nx, ny, nz;
+
+ nx = Math.sin(theta) * Math.cos(phi);
+ ny = Math.sin(phi);
+ nz = Math.cos(theta) * Math.cos(phi);
+ Sphere.normals.push(nx);
+ Sphere.normals.push(ny);
+ Sphere.normals.push(nz);
+
+ x = r * Math.sin(theta) * Math.cos(phi);
+ y = r * Math.sin(phi);
+ z = r * Math.cos(theta) * Math.cos(phi);
+ Sphere.vertices.push(x);
+ Sphere.vertices.push(y);
+ Sphere.vertices.push(z);
+ }
+ for (var phi = -Math.PI/2; phi < Math.PI/2; phi += Math.PI/20) {
+ var phi2 = phi + Math.PI/20;
+ for (var theta = -Math.PI/2; theta <= Math.PI/2; theta += Math.PI/20) {
+ vert(theta, phi);
+ vert(theta, phi2);
+ }
+ }
+ }
+}
+
+Sphere.create();
+
+initGL_CONTEXT_ID = function(){
+ var c = document.createElement('canvas');
+ var contextNames = ['webgl', 'experimental-webgl'];
+ GL_CONTEXT_ID = null;
+ for (var i=0; i<contextNames.length; i++) {
+ try {
+ if (c.getContext(contextNames[i])) {
+ GL_CONTEXT_ID = contextNames[i];
+ break;
+ }
+ } catch (e) {
+ }
+ }
+ if (!GL_CONTEXT_ID) {
+ log("No WebGL context found. Unable to run tests.");
+ }
+}
+
+initGL_CONTEXT_ID();
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/00_test_list.txt
new file mode 100644
index 0000000000..8c8154a542
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/00_test_list.txt
@@ -0,0 +1,12 @@
+context-attribute-preserve-drawing-buffer.html
+context-creation.html
+context-creation-worker.html
+context-lost.html
+context-lost-worker.html
+context-lost-restored.html
+context-lost-restored-worker.html
+methods.html
+methods-worker.html
+offscreencanvas-resize.html
+--min-version 1.0.4 offscreencanvas-timer-query.html
+--min-version 1.0.4 offscreencanvas-transfer-image-bitmap.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-attribute-preserve-drawing-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-attribute-preserve-drawing-buffer.html
new file mode 100644
index 0000000000..d230b69d9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-attribute-preserve-drawing-buffer.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>OffscreenCanavs context attribute preserveDrawingBuffer</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="canvases"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test checks whether OffscreenCanvas webgl context honors the preserveDrawingBuffer flag.");
+const wtu = WebGLTestUtils;
+const pixels = new Uint8Array(4);
+
+function checkPixels(color) {
+ return (color[0] === pixels[0]) &&
+ (color[1] === pixels[1]) &&
+ (color[2] === pixels[2]) &&
+ (color[3] === pixels[3]);
+}
+
+const nextFrame = () => new Promise(r => requestAnimationFrame(r));
+
+async function getPixelsFromOffscreenWebgl(preserveFlag, color, msg) {
+ const canvas = document.createElement("canvas");
+ document.getElementById("canvases").appendChild(canvas);
+ const offscreenCanvas = transferredOffscreenCanvasCreation(canvas, 10, 10);
+ const gl = offscreenCanvas.getContext("webgl", {preserveDrawingBuffer: preserveFlag});
+
+ // Draw some color on gl
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ let t;
+ const t0 = await nextFrame();
+ const timeDuration = preserveFlag ? 500 : 2000;
+ for (;;) {
+ t = await nextFrame();
+
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ if (preserveFlag) {
+ if (!checkPixels(color)) {
+ testFailed(msg + '\nexpected: ' + color.toString() + ' was ' + pixels.toString());
+ return;
+ }
+ } else {
+ if (checkPixels(color)) {
+ testPassed(msg);
+ return;
+ }
+ }
+
+ // Keep checking until it takes up to a certain time.
+ // preserveDrawingBuffer:false seems flaky on Chrome's test bots; run that test for longer.
+ if (t > t0 + timeDuration) {
+ break;
+ }
+ }
+
+ if (preserveFlag) {
+ testPassed(msg);
+ } else {
+ testFailed(msg + '\nafter ' + timeDuration + ' ms, expected: ' + color.toString() + ' was ' + pixels.toString());
+ }
+}
+
+(async () => {
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ } else {
+ // Test if OffscreenCanvas.webgl retains contents if preserveDrawingBuffer is true.
+ await getPixelsFromOffscreenWebgl(true, [255,0,255,255], "should be preserved");
+
+ // Test if OffscreenCanvas.webgl loses contents if preserveDrawingBuffer is false.
+ await getPixelsFromOffscreenWebgl(false, [0, 0, 0, 0], "should not be preserved");
+ }
+ finishTest();
+})();
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.html
new file mode 100644
index 0000000000..38b348ae36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Context Creation Test for OffscreenCanvas in a worker</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL context can be created on an OffscreenCanvas.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+} else {
+ var worker = new Worker('context-creation-worker.js');
+ worker.postMessage("Start worker");
+ worker.onmessage = function(e) {
+ if (e.data == "Test passed") {
+ testPassed("All tests have passed");
+ } else {
+ testFailed("Some tests failed");
+ }
+ finishTest();
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.js
new file mode 100644
index 0000000000..b0d867a1d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation-worker.js
@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+importScripts("../../js/tests/canvas-tests-utils.js");
+self.onmessage = function(e) {
+ if (contextCreation('webgl'))
+ self.postMessage("Test passed");
+ else
+ self.postMessage("Test failed");
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation.html
new file mode 100644
index 0000000000..73c911b5d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-creation.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Context Creation Test for OffscreenCanvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test ensures that the WebGL context can be created on an OffscreenCanvas.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+} else {
+ if (contextCreation('webgl')) {
+ testPassed("WebGL context created correctly.");
+ } else {
+ testFailed("WebGL context creation failed");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.html
new file mode 100644
index 0000000000..62d6ef60a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.html
@@ -0,0 +1,43 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script>
+function init()
+{
+ description("Tests behavior under a restored context for OffscreenCanvas in a worker.");
+
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ return;
+ }
+
+ var worker = new Worker('context-lost-restored-worker.js');
+ worker.postMessage("Start worker");
+ worker.onmessage = function(e) {
+ if (e.data == "Test passed") {
+ testPassed("All tests have passed");
+ } else {
+ testFailed("Some test failed");
+ }
+ finishTest();
+ return;
+ }
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.js
new file mode 100644
index 0000000000..76f59dce7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored-worker.js
@@ -0,0 +1,51 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+importScripts("../../js/tests/canvas-tests-utils.js");
+self.onmessage = function(e) {
+ if (!setupTest())
+ self.postMessage("Test failed");
+
+ canvas.addEventListener("webglcontextlost", function(e) {
+ if (!testLostContext(e))
+ self.postMessage("Test failed");
+ // restore the context after this event has exited.
+ setTimeout(function() {
+ // we didn't call prevent default so we should not be able to restore the context
+ if (!compareGLError(gl.INVALID_OPERATION, "WEBGL_lose_context.restoreContext()"))
+ self.postMessage("Test failed");
+ testLosingAndRestoringContext().then(function() {
+ self.postMessage("Test passed");
+ }, function() {
+ self.postMessage("Test failed");
+ });
+ }, 0);
+ });
+ canvas.addEventListener("webglcontextrestored", function() {
+ self.postMessage("Test failed");
+ });
+ allowRestore = false;
+ contextLostEventFired = false;
+ contextRestoredEventFired = false;
+
+ if (!testOriginalContext())
+ self.postMessage("Test failed");
+ WEBGL_lose_context.loseContext();
+ // The context should be lost immediately.
+ if (!gl.isContextLost())
+ self.postMessage("Test failed");
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
+ self.postMessage("Test failed");
+ if (gl.getError() != gl.NO_ERROR)
+ self.postMessage("Test failed");
+ // gl methods should be no-ops
+ if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
+ self.postMessage("Test failed");
+ // but the event should not have been fired.
+ if (contextLostEventFired)
+ self.postMessage("Test failed");
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored.html
new file mode 100644
index 0000000000..28e1878179
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-restored.html
@@ -0,0 +1,88 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+<script>
+
+function init()
+{
+ description("Tests behavior under a restored context for OffscreenCanvas.");
+
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ return;
+ }
+
+ if (!setupTest()) {
+ testFailed("Cannot initialize test");
+ finishTest();
+ return;
+ }
+
+ canvas.addEventListener("webglcontextlost", function(e) {
+ if (!testLostContext(e)) {
+ testFailed("Some test failed");
+ finishTest();
+ return;
+ }
+ // restore the context after this event has exited.
+ setTimeout(function() {
+ // we didn't call prevent default so we should not be able to restore the context
+ if (!compareGLError(gl.INVALID_OPERATION, "WEBGL_lose_context.restoreContext()")) {
+ testFailed("Some test failed");
+ finishTest();
+ return;
+ }
+ testLosingAndRestoringContext().then(function() {
+ testPassed("Test passed");
+ finishTest();
+ return;
+ }, function() {
+ testFailed("Some test failed");
+ finishTest();
+ return;
+ });
+ }, 0);
+ });
+ canvas.addEventListener("webglcontextrestored", function() {
+ testFailed("Some test failed");
+ finishTest();
+ return;
+ });
+ allowRestore = false;
+ contextLostEventFired = false;
+ contextRestoredEventFired = false;
+
+ if (!testOriginalContext()) {
+ testFailed("Some test failed");
+ finishTest();
+ return;
+ }
+ WEBGL_lose_context.loseContext();
+ // The context should be lost immediately.
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ // gl methods should be no-ops
+ shouldBeTrue(compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"));
+ // but the event should not have been fired.
+ shouldBeFalse("contextLostEventFired");
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.html
new file mode 100644
index 0000000000..a4846712de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.html
@@ -0,0 +1,43 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script>
+function init()
+{
+ description("Tests behavior under a lost context for OffscreenCanvas in a worker");
+
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ return;
+ }
+
+ var worker = new Worker('context-lost-worker.js');
+ worker.postMessage("Start worker");
+ worker.onmessage = function(e) {
+ if (e.data == "Test passed") {
+ testPassed("All tests have passed");
+ } else {
+ testFailed("Some tests failed");
+ }
+ finishTest();
+ return;
+ }
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.js
new file mode 100644
index 0000000000..75cd4b0045
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost-worker.js
@@ -0,0 +1,35 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+importScripts("../../js/tests/canvas-tests-utils.js");
+self.onmessage = function(e) {
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext('webgl');
+
+ // call testValidContext() before checking for the extension, because this is where we check
+ // for the isContextLost() method, which we want to do regardless of the extension's presence.
+ if (!testValidContext())
+ self.postMessage("Test failed");
+
+ extension = gl.getExtension("WEBGL_lose_context");
+ // need an extension that exposes new API methods.
+ OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
+ if (extension == null || OES_vertex_array_object == null)
+ self.postMessage("Test failed");
+
+ // We need to initialize |uniformLocation| before losing context.
+ // Otherwise gl.getUniform() when context is lost will throw.
+ uniformLocation = gl.getUniformLocation(program, "tex");
+ extension.loseContext();
+
+ canvas.addEventListener("webglcontextlost", function() {
+ if (testLostContextWithoutRestore())
+ self.postMessage("Test passed");
+ else
+ self.postMessage("Test failed");
+ }, false);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost.html
new file mode 100644
index 0000000000..0568ad229e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/context-lost.html
@@ -0,0 +1,69 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+<script>
+function init()
+{
+ description("Tests behavior under a lost context for OffscreenCanvas");
+
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ return;
+ }
+
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext('webgl');
+
+ // call testValidContext() before checking for the extension, because this is where we check
+ // for the isContextLost() method, which we want to do regardless of the extension's presence.
+ if (!testValidContext()) {
+ testFailed("Some tests failed");
+ finishTest();
+ return;
+ }
+
+ extension = gl.getExtension("WEBGL_lose_context");
+ // need an extension that exposes new API methods.
+ OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
+ if (extension == null || OES_vertex_array_object == null) {
+ testFailed("Some tests failed");
+ finishTest();
+ return;
+ }
+
+ // We need to initialize |uniformLocation| before losing context.
+ // Otherwise gl.getUniform() when context is lost will throw.
+ uniformLocation = gl.getUniformLocation(program, "tex");
+ extension.loseContext();
+
+ canvas.addEventListener("webglcontextlost", function() {
+ if (testLostContextWithoutRestore()) {
+ testPassed("All tests passed");
+ finishTest();
+ return;
+ } else {
+ testFailed("Some tests failed");
+ finishTest();
+ return;
+ }
+ }, false);
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.html
new file mode 100644
index 0000000000..929474c9b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Methods Test for OffscreenCanvas in a worker</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL context created for an OffscreenCanvas has all the methods in the specification.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+} else {
+ var worker = new Worker("methods-worker.js");
+ worker.postMessage("Start worker");
+ worker.onmessage = function(e) {
+ if (e.data == "Test passed") {
+ testPassed("All tests have passed");
+ } else {
+ testFailed("Some tests failed");
+ }
+ finishTest();
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.js
new file mode 100644
index 0000000000..154cac7fc6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods-worker.js
@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+importScripts("../../js/tests/canvas-tests-utils.js");
+self.onmessage = function(e) {
+ if (testAPIs('webgl'))
+ self.postMessage("Test passed");
+ else
+ self.postMessage("Test failed");
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods.html
new file mode 100644
index 0000000000..9129e76cfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/methods.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Methods Test for OffscreenCanvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL context created for an OffscreenCanvas has all the methods in the specification.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+} else {
+ if (testAPIs('webgl')) {
+ testPassed("All WebGL methods found");
+ } else {
+ testFailed("Some WebGL methods not found");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-resize.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-resize.html
new file mode 100644
index 0000000000..21107bba53
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-resize.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Resizing Test for OffscreenCanvas commit()</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test ensures that the OffscreenCanvas context returns the correct image size after resizing and calling commit().");
+
+function testResizeOnNewOffscreenCanvas() {
+ var canvas = new OffscreenCanvas(10, 20);
+ canvas.getContext("webgl");
+ canvas.width = 30;
+ canvas.height = 40;
+ assertWidthAndHeight(canvas, "canvas", 30, 40);
+ var imagebitmap = canvas.transferToImageBitmap();
+ assertWidthAndHeight(imagebitmap, "imagebitmap", 30, 40);
+}
+
+function testResizeOnTransferredOffscreenCanvas() {
+ var placeholder = document.createElement("canvas");
+ var offscreencanvas = transferredOffscreenCanvasCreation(placeholder, 10, 20);
+ var ctx = offscreencanvas.getContext("webgl");
+
+ // Verify that setting the size of an OffscreenCanvas that has a placeholder works.
+ offscreencanvas.width = 30;
+ offscreencanvas.height = 40;
+ assertWidthAndHeight(offscreencanvas, "resized offscreencanvas", 30, 40);
+ var imagebitmap = offscreencanvas.transferToImageBitmap();
+ assertWidthAndHeight(imagebitmap, "imagebitmap transferred from resized offscreencanvas" , 30, 40);
+
+ // Verify that setting the size of an OffscreenCanvas does not directly update the size of its placeholder canvas.
+ assertWidthAndHeight(placeholder, "placeholder canvas", 10, 20);
+
+ var asyncStepsCompleted = 0;
+ ctx.commit();
+ createImageBitmap(placeholder).then(image => {
+ // Verify that the placeholder was not updated synchronously.
+ assertWidthAndHeight(image, "imagebitmap from placeholder canvas", 10, 20);
+ asyncStepsCompleted++;
+ if (asyncStepsCompleted == 2) {
+ finishTest();
+ }
+ });
+
+ // Set timeout acts as a sync barrier to allow commit to propagate
+ setTimeout(function() {
+ // Verify that commit() asynchronously updates the size of its placeholder canvas.
+ assertWidthAndHeight(placeholder, "placeholder canvas", 30, 40);
+
+ // Verify that width/height attributes are not settable
+ shouldThrow("placeholder.width = 50");
+ shouldThrow("placeholder.height = 60");
+
+ assertWidthAndHeight(placeholder, "placeholder canvas after size reset", 30, 40);
+
+ createImageBitmap(placeholder).then(image => {
+ // Verify that an image grabbed from the placeholder has the correct dimensions
+ assertWidthAndHeight(image, "imagebitmap from placeholder canvas", 30, 40);
+ asyncStepsCompleted++;
+ if (asyncStepsCompleted == 2) {
+ finishTest();
+ }
+ });
+ }, 0);
+}
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+} else if (!new OffscreenCanvas(10, 20).getContext("webgl").commit) {
+ testPassed("commit() not supported");
+ finishTest();
+} else {
+ testResizeOnNewOffscreenCanvas();
+ testResizeOnTransferredOffscreenCanvas();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-timer-query.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-timer-query.html
new file mode 100644
index 0000000000..0d32f14c19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-timer-query.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test for Timer Query objects with OffscreenCanvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id='myWorker' type='text/worker'>
+ function tick(callback) {
+ function tickImpl() {
+ const res = callback();
+ if (res) {
+ if (requestAnimationFrame) {
+ requestAnimationFrame(tickImpl);
+ } else {
+ setTimeout(tickImpl, 10);
+ }
+ }
+ }
+
+ tickImpl();
+ }
+
+ self.onmessage = function(e) {
+ let canvas = new OffscreenCanvas(128, 128);
+ let gl = canvas.getContext("webgl");
+ let ext = gl.getExtension("EXT_disjoint_timer_query");
+ if (!ext) {
+ self.postMessage("PASSED - no EXT_disjoint_timer_query extension - this is legal");
+ return false;
+ }
+ let query = ext.createQueryEXT();
+ ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
+ ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ tick(function() {
+ const status = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
+ if (status) {
+ self.postMessage("PASSED - timer query object completed successfully on worker");
+ return false;
+ } else {
+ const err = gl.getError();
+ if (err != 0) {
+ self.postMessage("FAILED - GL error " + err);
+ return false;
+ }
+ }
+ return true;
+ });
+ };
+ </script>
+ <script>
+ "use strict";
+ description("This test ensures that timer query objects work with the WebGL 1.0 context created via OffscreenCanvas.");
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ } else {
+ var blob = new Blob([document.getElementById('myWorker').textContent]);
+ var worker = new Worker(URL.createObjectURL(blob));
+ worker.onmessage = function(msg) {
+ if (msg.data.startsWith("PASSED")) {
+ testPassed(msg.data);
+ } else {
+ testFailed(msg.data);
+ }
+ finishTest();
+ }
+ worker.postMessage("Start Worker");
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-transfer-image-bitmap.html b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-transfer-image-bitmap.html
new file mode 100644
index 0000000000..70b359216b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/offscreencanvas/offscreencanvas-transfer-image-bitmap.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test for OffscreenCanvas TransferToImageBitmap</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/offscreencanvas-transfer-image-bitmap.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ var canvas = new OffscreenCanvas(128, 128);
+ var gl = canvas.getContext("webgl");
+ gl.clearColor(1.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var image = canvas.transferToImageBitmap();
+
+ self.postMessage({ bitmap: image },
+ [ image ]);
+ };
+ </script>
+ <script>
+ "use strict";
+ description("This test ensures that the transferToImageBitmap function of OffscreenCanvas webgl context is functional.");
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ } else {
+ var blob = new Blob([document.getElementById('myWorker').textContent]);
+ var worker = new Worker(URL.createObjectURL(blob));
+
+ worker.onmessage = function(msg) {
+ testTransferToImageBitmap("webgl", msg.data.bitmap);
+ finishTest();
+ }
+ worker.postMessage("Start Worker");
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/00_test_list.txt
new file mode 100644
index 0000000000..4b4237c9fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/00_test_list.txt
@@ -0,0 +1,2 @@
+mustpass.run.txt
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_001_to_006.html
new file mode 100644
index 0000000000..b6578ff3de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: abs_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "abs_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "abs_float_frag_xvary.frag"
+ },
+ "name": "abs_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "abs_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "abs_vec2_frag_xvary.frag"
+ },
+ "name": "abs_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "abs_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "abs_vec3_frag_xvary.frag"
+ },
+ "name": "abs_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "abs_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "abs_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "abs_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "abs_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "abs_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "abs_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "abs_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "abs_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "abs_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary.frag
new file mode 100644
index 0000000000..23aee9561c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(abs(c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..604d0e86b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_frag_xvary_ref.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ if(c < 0.0) c *= -1.0;
+
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary.vert
new file mode 100644
index 0000000000..48d51ed05a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(abs(c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..71d1543400
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_float_vert_xvary_ref.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ if(c < 0.0) c *= -1.0;
+
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..ccb594c0e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(abs(c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..b0bbc5ec9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_frag_xvary_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ if((c[0] < 0.0)) c[0] *= -1.0;
+ if((c[1] < 0.0)) c[1] *= -1.0;
+
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..9845381038
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(abs(c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..f2b3ba0b3e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec2_vert_xvary_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ if((c[0] < 0.0)) c[0] *= -1.0;
+ if((c[1] < 0.0)) c[1] *= -1.0;
+
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..5014c6045c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(abs(c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..6a587accb8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_frag_xvary_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ if((c[0] < 0.0)) c[0] *= -1.0;
+ if((c[1] < 0.0)) c[1] *= -1.0;
+ if((c[2] < 0.0)) c[2] *= -1.0;
+
+
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..7a64d4efda
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(abs(c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..db5eb81863
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/abs_vec3_vert_xvary_ref.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ if((c[0] < 0.0)) c[0] *= -1.0;
+ if((c[1] < 0.0)) c[1] *= -1.0;
+ if((c[2] < 0.0)) c[2] *= -1.0;
+
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/input.run.txt
new file mode 100644
index 0000000000..ebf5dc91f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/abs/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+abs_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_001_to_006.html
new file mode 100644
index 0000000000..3fae3212ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: acos_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "acos_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "acos_float_frag_xvary.frag"
+ },
+ "name": "acos_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "acos_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "acos_vec2_frag_xvary.frag"
+ },
+ "name": "acos_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "acos_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "acos_vec3_frag_xvary.frag"
+ },
+ "name": "acos_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "acos_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "acos_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "acos_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "acos_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "acos_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "acos_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "acos_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "acos_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "acos_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary.frag
new file mode 100644
index 0000000000..db65737072
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(acos(c) / M_PI, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..3be16e453b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_frag_xvary_ref.frag
@@ -0,0 +1,94 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* The following files are direct copies of each other:
+ *
+ * GL/acos/acos_float_frag_xvary_ref.frag
+ * GL/asin/asin_float_frag_xvary_ref.frag
+ *
+ * Care should be taken to apply any changes to both. Only the last
+ * line where gl_FragColor is assigned should be different.
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float asinValues[17];
+ asinValues[0] = -1.5708;
+ asinValues[1] = -1.06544;
+ asinValues[2] = -0.848062;
+ asinValues[3] = -0.675132;
+ asinValues[4] = -0.523599;
+ asinValues[5] = -0.384397;
+ asinValues[6] = -0.25268;
+ asinValues[7] = -0.125328;
+ asinValues[8] = 0.0;
+ asinValues[9] = 0.125328;
+ asinValues[10] = 0.25268;
+ asinValues[11] = 0.384397;
+ asinValues[12] = 0.523599;
+ asinValues[13] = 0.675132;
+ asinValues[14] = 0.848062;
+ asinValues[15] = 1.06544;
+ asinValues[16] = 1.5708;
+
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (color.r - 0.5);
+
+ float arrVal = (c + 1.0) * 8.0;
+ int arr0 = int(floor(arrVal));
+ float weight = arrVal - floor(arrVal);
+ float asin_c = 0.0;
+
+ if (arr0 == 0)
+ asin_c = lerp(asinValues[0], asinValues[1], weight);
+ else if (arr0 == 1)
+ asin_c = lerp(asinValues[1], asinValues[2], weight);
+ else if (arr0 == 2)
+ asin_c = lerp(asinValues[2], asinValues[3], weight);
+ else if (arr0 == 3)
+ asin_c = lerp(asinValues[3], asinValues[4], weight);
+ else if (arr0 == 4)
+ asin_c = lerp(asinValues[4], asinValues[5], weight);
+ else if (arr0 == 5)
+ asin_c = lerp(asinValues[5], asinValues[6], weight);
+ else if (arr0 == 6)
+ asin_c = lerp(asinValues[6], asinValues[7], weight);
+ else if (arr0 == 7)
+ asin_c = lerp(asinValues[7], asinValues[8], weight);
+ else if (arr0 == 8)
+ asin_c = lerp(asinValues[8], asinValues[9], weight);
+ else if (arr0 == 9)
+ asin_c = lerp(asinValues[9], asinValues[10], weight);
+ else if (arr0 == 10)
+ asin_c = lerp(asinValues[10], asinValues[11], weight);
+ else if (arr0 == 11)
+ asin_c = lerp(asinValues[11], asinValues[12], weight);
+ else if (arr0 == 12)
+ asin_c = lerp(asinValues[12], asinValues[13], weight);
+ else if (arr0 == 13)
+ asin_c = lerp(asinValues[13], asinValues[14], weight);
+ else if (arr0 == 14)
+ asin_c = lerp(asinValues[14], asinValues[15], weight);
+ else if (arr0 == 15)
+ asin_c = lerp(asinValues[15], asinValues[16], weight);
+ else if (arr0 == 16)
+ asin_c = asinValues[16];
+
+ // acos(x) = PI/2 - asin(x)
+ gl_FragColor = vec4(0.5 - asin_c / M_PI, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary.vert
new file mode 100644
index 0000000000..57391c206a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(acos(c) / M_PI, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..a18618539f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_float_vert_xvary_ref.vert
@@ -0,0 +1,41 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (gtf_Color.r - 0.5);
+
+ float acos_c = 0.0;
+ float scale = 1.0;
+ float sign = 1.0;
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c < 0.0)
+ {
+ sign = -1.0;
+ c *= -1.0;
+ }
+
+ // Taylors series expansion for acos
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ acos_c += scale * pow(c, float(i)) / float(i);
+ scale *= float(i) / float(i + 1);
+ }
+ acos_c = M_PI / 2.0 - sign * acos_c;
+
+ color = vec4(acos_c / M_PI, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..603435cc60
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(acos(c) / M_PI, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..273f1a01a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_frag_xvary_ref.frag
@@ -0,0 +1,130 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* The following files are direct copies of each other:
+ *
+ * GL/acos/acos_vec2_frag_xvary_ref.frag
+ * GL/asin/asin_vec2_frag_xvary_ref.frag
+ *
+ * Care should be taken to apply any changes to both. Only the last
+ * line where gl_FragColor is assigned should be different.
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float asinValues[17];
+ asinValues[0] = -1.5708;
+ asinValues[1] = -1.06544;
+ asinValues[2] = -0.848062;
+ asinValues[3] = -0.675132;
+ asinValues[4] = -0.523599;
+ asinValues[5] = -0.384397;
+ asinValues[6] = -0.25268;
+ asinValues[7] = -0.125328;
+ asinValues[8] = 0.0;
+ asinValues[9] = 0.125328;
+ asinValues[10] = 0.25268;
+ asinValues[11] = 0.384397;
+ asinValues[12] = 0.523599;
+ asinValues[13] = 0.675132;
+ asinValues[14] = 0.848062;
+ asinValues[15] = 1.06544;
+ asinValues[16] = 1.5708;
+
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (color.rg - 0.5);
+
+ vec2 arrVal = (c + vec2(1.0, 1.0)) * 8.0;
+ int arr0x = int(floor(arrVal.x));
+ int arr0y = int(floor(arrVal.y));
+ vec2 weight = arrVal - floor(arrVal);
+ vec2 asin_c = vec2(0.0);
+
+ if (arr0x == 0)
+ asin_c.x = lerp(asinValues[0], asinValues[1], weight.x);
+ else if (arr0x == 1)
+ asin_c.x = lerp(asinValues[1], asinValues[2], weight.x);
+ else if (arr0x == 2)
+ asin_c.x = lerp(asinValues[2], asinValues[3], weight.x);
+ else if (arr0x == 3)
+ asin_c.x = lerp(asinValues[3], asinValues[4], weight.x);
+ else if (arr0x == 4)
+ asin_c.x = lerp(asinValues[4], asinValues[5], weight.x);
+ else if (arr0x == 5)
+ asin_c.x = lerp(asinValues[5], asinValues[6], weight.x);
+ else if (arr0x == 6)
+ asin_c.x = lerp(asinValues[6], asinValues[7], weight.x);
+ else if (arr0x == 7)
+ asin_c.x = lerp(asinValues[7], asinValues[8], weight.x);
+ else if (arr0x == 8)
+ asin_c.x = lerp(asinValues[8], asinValues[9], weight.x);
+ else if (arr0x == 9)
+ asin_c.x = lerp(asinValues[9], asinValues[10], weight.x);
+ else if (arr0x == 10)
+ asin_c.x = lerp(asinValues[10], asinValues[11], weight.x);
+ else if (arr0x == 11)
+ asin_c.x = lerp(asinValues[11], asinValues[12], weight.x);
+ else if (arr0x == 12)
+ asin_c.x = lerp(asinValues[12], asinValues[13], weight.x);
+ else if (arr0x == 13)
+ asin_c.x = lerp(asinValues[13], asinValues[14], weight.x);
+ else if (arr0x == 14)
+ asin_c.x = lerp(asinValues[14], asinValues[15], weight.x);
+ else if (arr0x == 15)
+ asin_c.x = lerp(asinValues[15], asinValues[16], weight.x);
+ else if (arr0x == 16)
+ asin_c.x = asinValues[16];
+
+ if (arr0y == 0)
+ asin_c.y = lerp(asinValues[0], asinValues[1], weight.y);
+ else if (arr0y == 1)
+ asin_c.y = lerp(asinValues[1], asinValues[2], weight.y);
+ else if (arr0y == 2)
+ asin_c.y = lerp(asinValues[2], asinValues[3], weight.y);
+ else if (arr0y == 3)
+ asin_c.y = lerp(asinValues[3], asinValues[4], weight.y);
+ else if (arr0y == 4)
+ asin_c.y = lerp(asinValues[4], asinValues[5], weight.y);
+ else if (arr0y == 5)
+ asin_c.y = lerp(asinValues[5], asinValues[6], weight.y);
+ else if (arr0y == 6)
+ asin_c.y = lerp(asinValues[6], asinValues[7], weight.y);
+ else if (arr0y == 7)
+ asin_c.y = lerp(asinValues[7], asinValues[8], weight.y);
+ else if (arr0y == 8)
+ asin_c.y = lerp(asinValues[8], asinValues[9], weight.y);
+ else if (arr0y == 9)
+ asin_c.y = lerp(asinValues[9], asinValues[10], weight.y);
+ else if (arr0y == 10)
+ asin_c.y = lerp(asinValues[10], asinValues[11], weight.y);
+ else if (arr0y == 11)
+ asin_c.y = lerp(asinValues[11], asinValues[12], weight.y);
+ else if (arr0y == 12)
+ asin_c.y = lerp(asinValues[12], asinValues[13], weight.y);
+ else if (arr0y == 13)
+ asin_c.y = lerp(asinValues[13], asinValues[14], weight.y);
+ else if (arr0y == 14)
+ asin_c.y = lerp(asinValues[14], asinValues[15], weight.y);
+ else if (arr0y == 15)
+ asin_c.y = lerp(asinValues[15], asinValues[16], weight.y);
+ else if (arr0y == 16)
+ asin_c.y = asinValues[16];
+
+ // acos(x) = PI/2 - asin(x)
+ gl_FragColor = vec4(0.5 - asin_c / M_PI, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..9496225fc8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(acos(c) / M_PI, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..3afa0be392
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec2_vert_xvary_ref.vert
@@ -0,0 +1,56 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ vec2 acos_c = vec2(0.0);
+ vec2 scale = vec2(1.0);
+ vec2 sign = vec2(1.0);
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.r < 0.0)
+ {
+ sign.r = -1.0;
+ c.r *= -1.0;
+ }
+
+ // Taylors series expansion for acos
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ acos_c.r += scale.r * pow(c.r, float(i)) / float(i);
+ scale.r *= float(i) / float(i + 1);
+ }
+ acos_c.r = M_PI / 2.0 - sign.r * acos_c.r;
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.g < 0.0)
+ {
+ sign.g = -1.0;
+ c.g *= -1.0;
+ }
+
+ // Taylors series expansion for acos
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ acos_c.g += scale.g * pow(c.g, float(i)) / float(i);
+ scale.g *= float(i) / float(i + 1);
+ }
+ acos_c.g = M_PI / 2.0 - sign.g * acos_c.g;
+
+ color = vec4(acos_c / M_PI, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..a39f0a5c7a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(acos(c) / M_PI, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..5d1b390f72
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_frag_xvary_ref.frag
@@ -0,0 +1,166 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* The following files are direct copies of each other:
+ *
+ * GL/acos/acos_vec3_frag_xvary_ref.frag
+ * GL/asin/asin_vec3_frag_xvary_ref.frag
+ *
+ * Care should be taken to apply any changes to both. Only the last
+ * line where gl_FragColor is assigned should be different.
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float asinValues[17];
+ asinValues[0] = -1.5708;
+ asinValues[1] = -1.06544;
+ asinValues[2] = -0.848062;
+ asinValues[3] = -0.675132;
+ asinValues[4] = -0.523599;
+ asinValues[5] = -0.384397;
+ asinValues[6] = -0.25268;
+ asinValues[7] = -0.125328;
+ asinValues[8] = 0.0;
+ asinValues[9] = 0.125328;
+ asinValues[10] = 0.25268;
+ asinValues[11] = 0.384397;
+ asinValues[12] = 0.523599;
+ asinValues[13] = 0.675132;
+ asinValues[14] = 0.848062;
+ asinValues[15] = 1.06544;
+ asinValues[16] = 1.5708;
+
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (color.rgb - 0.5);
+
+ vec3 arrVal = (c + vec3(1.0, 1.0, 1.0)) * 8.0;
+ int arr0x = int(floor(arrVal.x));
+ int arr0y = int(floor(arrVal.y));
+ int arr0z = int(floor(arrVal.z));
+ vec3 weight = arrVal - floor(arrVal);
+ vec3 asin_c = vec3(0.0);
+
+ if (arr0x == 0)
+ asin_c.x = lerp(asinValues[0], asinValues[1], weight.x);
+ else if (arr0x == 1)
+ asin_c.x = lerp(asinValues[1], asinValues[2], weight.x);
+ else if (arr0x == 2)
+ asin_c.x = lerp(asinValues[2], asinValues[3], weight.x);
+ else if (arr0x == 3)
+ asin_c.x = lerp(asinValues[3], asinValues[4], weight.x);
+ else if (arr0x == 4)
+ asin_c.x = lerp(asinValues[4], asinValues[5], weight.x);
+ else if (arr0x == 5)
+ asin_c.x = lerp(asinValues[5], asinValues[6], weight.x);
+ else if (arr0x == 6)
+ asin_c.x = lerp(asinValues[6], asinValues[7], weight.x);
+ else if (arr0x == 7)
+ asin_c.x = lerp(asinValues[7], asinValues[8], weight.x);
+ else if (arr0x == 8)
+ asin_c.x = lerp(asinValues[8], asinValues[9], weight.x);
+ else if (arr0x == 9)
+ asin_c.x = lerp(asinValues[9], asinValues[10], weight.x);
+ else if (arr0x == 10)
+ asin_c.x = lerp(asinValues[10], asinValues[11], weight.x);
+ else if (arr0x == 11)
+ asin_c.x = lerp(asinValues[11], asinValues[12], weight.x);
+ else if (arr0x == 12)
+ asin_c.x = lerp(asinValues[12], asinValues[13], weight.x);
+ else if (arr0x == 13)
+ asin_c.x = lerp(asinValues[13], asinValues[14], weight.x);
+ else if (arr0x == 14)
+ asin_c.x = lerp(asinValues[14], asinValues[15], weight.x);
+ else if (arr0x == 15)
+ asin_c.x = lerp(asinValues[15], asinValues[16], weight.x);
+ else if (arr0x == 16)
+ asin_c.x = asinValues[16];
+
+ if (arr0y == 0)
+ asin_c.y = lerp(asinValues[0], asinValues[1], weight.y);
+ else if (arr0y == 1)
+ asin_c.y = lerp(asinValues[1], asinValues[2], weight.y);
+ else if (arr0y == 2)
+ asin_c.y = lerp(asinValues[2], asinValues[3], weight.y);
+ else if (arr0y == 3)
+ asin_c.y = lerp(asinValues[3], asinValues[4], weight.y);
+ else if (arr0y == 4)
+ asin_c.y = lerp(asinValues[4], asinValues[5], weight.y);
+ else if (arr0y == 5)
+ asin_c.y = lerp(asinValues[5], asinValues[6], weight.y);
+ else if (arr0y == 6)
+ asin_c.y = lerp(asinValues[6], asinValues[7], weight.y);
+ else if (arr0y == 7)
+ asin_c.y = lerp(asinValues[7], asinValues[8], weight.y);
+ else if (arr0y == 8)
+ asin_c.y = lerp(asinValues[8], asinValues[9], weight.y);
+ else if (arr0y == 9)
+ asin_c.y = lerp(asinValues[9], asinValues[10], weight.y);
+ else if (arr0y == 10)
+ asin_c.y = lerp(asinValues[10], asinValues[11], weight.y);
+ else if (arr0y == 11)
+ asin_c.y = lerp(asinValues[11], asinValues[12], weight.y);
+ else if (arr0y == 12)
+ asin_c.y = lerp(asinValues[12], asinValues[13], weight.y);
+ else if (arr0y == 13)
+ asin_c.y = lerp(asinValues[13], asinValues[14], weight.y);
+ else if (arr0y == 14)
+ asin_c.y = lerp(asinValues[14], asinValues[15], weight.y);
+ else if (arr0y == 15)
+ asin_c.y = lerp(asinValues[15], asinValues[16], weight.y);
+ else if (arr0y == 16)
+ asin_c.y = asinValues[16];
+
+ if (arr0z == 0)
+ asin_c.z = lerp(asinValues[0], asinValues[1], weight.z);
+ else if (arr0z == 1)
+ asin_c.z = lerp(asinValues[1], asinValues[2], weight.z);
+ else if (arr0z == 2)
+ asin_c.z = lerp(asinValues[2], asinValues[3], weight.z);
+ else if (arr0z == 3)
+ asin_c.z = lerp(asinValues[3], asinValues[4], weight.z);
+ else if (arr0z == 4)
+ asin_c.z = lerp(asinValues[4], asinValues[5], weight.z);
+ else if (arr0z == 5)
+ asin_c.z = lerp(asinValues[5], asinValues[6], weight.z);
+ else if (arr0z == 6)
+ asin_c.z = lerp(asinValues[6], asinValues[7], weight.z);
+ else if (arr0z == 7)
+ asin_c.z = lerp(asinValues[7], asinValues[8], weight.z);
+ else if (arr0z == 8)
+ asin_c.z = lerp(asinValues[8], asinValues[9], weight.z);
+ else if (arr0z == 9)
+ asin_c.z = lerp(asinValues[9], asinValues[10], weight.z);
+ else if (arr0z == 10)
+ asin_c.z = lerp(asinValues[10], asinValues[11], weight.z);
+ else if (arr0z == 11)
+ asin_c.z = lerp(asinValues[11], asinValues[12], weight.z);
+ else if (arr0z == 12)
+ asin_c.z = lerp(asinValues[12], asinValues[13], weight.z);
+ else if (arr0z == 13)
+ asin_c.z = lerp(asinValues[13], asinValues[14], weight.z);
+ else if (arr0z == 14)
+ asin_c.z = lerp(asinValues[14], asinValues[15], weight.z);
+ else if (arr0z == 15)
+ asin_c.z = lerp(asinValues[15], asinValues[16], weight.z);
+ else if (arr0z == 16)
+ asin_c.z = asinValues[16];
+
+ // acos(x) = PI/2 - asin(x)
+ gl_FragColor = vec4(0.5 - asin_c / M_PI, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..5a37ca2c2d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(acos(c) / M_PI, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..37ace0f04f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/acos_vec3_vert_xvary_ref.vert
@@ -0,0 +1,72 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ vec3 acos_c = vec3(0.0);
+ vec3 scale = vec3(1.0);
+ vec3 sign = vec3(1.0);
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.r < 0.0)
+ {
+ sign.r = -1.0;
+ c.r *= -1.0;
+ }
+
+ // Taylors series expansion for acos
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ acos_c.r += scale.r * pow(c.r, float(i)) / float(i);
+ scale.r *= float(i) / float(i + 1);
+ }
+ acos_c.r = M_PI / 2.0 - sign.r * acos_c.r;
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.g < 0.0)
+ {
+ sign.g = -1.0;
+ c.g *= -1.0;
+ }
+
+ // Taylors series expansion for acos
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ acos_c.g += scale.g * pow(c.g, float(i)) / float(i);
+ scale.g *= float(i) / float(i + 1);
+ }
+ acos_c.g = M_PI / 2.0 - sign.g * acos_c.g;
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.b < 0.0)
+ {
+ sign.b = -1.0;
+ c.b *= -1.0;
+ }
+
+ // Taylors series expansion for acos
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ acos_c.b += scale.b * pow(c.b, float(i)) / float(i);
+ scale.b *= float(i) / float(i + 1);
+ }
+ acos_c.b = M_PI / 2.0 - sign.b * acos_c.b;
+
+ color = vec4(acos_c / M_PI, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/input.run.txt
new file mode 100644
index 0000000000..fc7eedaa08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/acos/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+acos_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_001_to_004.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_001_to_004.html
new file mode 100644
index 0000000000..eb28d05620
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_001_to_004.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: all_001_to_004.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "all_bvec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "all_bvec2_frag.frag"
+ },
+ "name": "all_bvec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "all_bvec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "all_bvec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "all_bvec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "all_bvec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "all_bvec3_frag.frag"
+ },
+ "name": "all_bvec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "all_bvec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "all_bvec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "all_bvec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag.frag
new file mode 100644
index 0000000000..43fe86a165
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(4.0 * color.rg); // 3/4 true, 1/4 false
+ gl_FragColor = vec4(vec3(all(bvec2(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag_ref.frag
new file mode 100644
index 0000000000..c9ff27bbb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_frag_ref.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bool _all(in bvec2 a)
+{
+ bool temp = true;
+
+ if(!a[0]) temp = false;
+ if(!a[1]) temp = false;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec2 c = floor(4.0 * color.rg); // 3/4 true, 1/4 false
+ gl_FragColor = vec4(vec3(_all(bvec2(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert.vert
new file mode 100644
index 0000000000..f22e037838
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(4.0 * gtf_Color.rg); // 3/4 true, 1/4 false
+ color = vec4(vec3(all(bvec2(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert_ref.vert
new file mode 100644
index 0000000000..5afd6a1a3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec2_vert_ref.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bool _all(in bvec2 a)
+{
+ bool temp = true;
+
+ if(!a[0]) temp = false;
+ if(!a[1]) temp = false;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec2 c = floor(4.0 * gtf_Color.rg); // 3/4 true, 1/4 false
+ color = vec4(vec3(_all(bvec2(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag.frag
new file mode 100644
index 0000000000..fdf6a0282f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(4.0 * color.rgb); // 3/4 true, 1/4 false
+ gl_FragColor = vec4(vec3(all(bvec3(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag_ref.frag
new file mode 100644
index 0000000000..dcb638186d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bool _all(in bvec3 a)
+{
+ bool temp = true;
+
+ if(!a[0]) temp = false;
+ if(!a[1]) temp = false;
+ if(!a[2]) temp = false;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec3 c = floor(4.0 * color.rgb); // 3/4 true, 1/4 false
+ gl_FragColor = vec4(vec3(_all(bvec3(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert.vert
new file mode 100644
index 0000000000..76ce8c0d9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(4.0 * gtf_Color.rgb); // 3/4 true, 1/4 false
+ color = vec4(vec3(all(bvec3(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert_ref.vert
new file mode 100644
index 0000000000..ebe83eec91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/all_bvec3_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bool _all(in bvec3 a)
+{
+ bool temp = true;
+
+ if(!a[0]) temp = false;
+ if(!a[1]) temp = false;
+ if(!a[2]) temp = false;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec3 c = floor(4.0 * gtf_Color.rgb); // 3/4 true, 1/4 false
+ color = vec4(vec3(_all(bvec3(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/input.run.txt
new file mode 100644
index 0000000000..420ac35bcd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/all/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+all_001_to_004.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_001_to_004.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_001_to_004.html
new file mode 100644
index 0000000000..094b97911d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_001_to_004.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: any_001_to_004.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "any_bvec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "any_bvec2_frag.frag"
+ },
+ "name": "any_bvec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "any_bvec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "any_bvec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "any_bvec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "any_bvec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "any_bvec3_frag.frag"
+ },
+ "name": "any_bvec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "any_bvec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "any_bvec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "any_bvec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag.frag
new file mode 100644
index 0000000000..23648e5321
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec3(any(bvec2(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag_ref.frag
new file mode 100644
index 0000000000..7023c98dff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_frag_ref.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bool _any(in bvec2 a)
+{
+ bool temp = false;
+
+ if(a[0]) temp = true;
+ if(a[1]) temp = true;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec3(_any(bvec2(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert.vert
new file mode 100644
index 0000000000..669877792c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ color = vec4(vec3(any(bvec2(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert_ref.vert
new file mode 100644
index 0000000000..a14c4c6a29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec2_vert_ref.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bool _any(in bvec2 a)
+{
+ bool temp = false;
+
+ if(a[0]) temp = true;
+ if(a[1]) temp = true;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ color = vec4(vec3(_any(bvec2(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag.frag
new file mode 100644
index 0000000000..d4859d7db9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec3(any(bvec3(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag_ref.frag
new file mode 100644
index 0000000000..29b07f520f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bool _any(in bvec3 a)
+{
+ bool temp = false;
+
+ if(a[0]) temp = true;
+ if(a[1]) temp = true;
+ if(a[2]) temp = true;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec3(_any(bvec3(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert.vert
new file mode 100644
index 0000000000..6ba4e5fb85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ color = vec4(vec3(any(bvec3(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert_ref.vert
new file mode 100644
index 0000000000..283c100d60
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/any_bvec3_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bool _any(in bvec3 a)
+{
+ bool temp = false;
+
+ if(a[0]) temp = true;
+ if(a[1]) temp = true;
+ if(a[2]) temp = true;
+
+ return temp;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ color = vec4(vec3(_any(bvec3(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/input.run.txt
new file mode 100644
index 0000000000..6ac4240676
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/any/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+any_001_to_004.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/array_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/array_001_to_006.html
new file mode 100644
index 0000000000..2439fd7a61
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/array_001_to_006.html
@@ -0,0 +1,201 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: array_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "new_mad2": {
+ "count": 2,
+ "type": "uniform1fv",
+ "value": [
+ 45.0,
+ 14.0
+ ]
+ }
+ },
+ "fragmentShader": "empty_uniform_array_float_frag.frag"
+ },
+ "name": "empty_uniform_array_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "empty_uniform_array_float_vert.vert",
+ "uniforms": {
+ "new_mad2": {
+ "count": 2,
+ "type": "uniform1fv",
+ "value": [
+ 45.0,
+ 14.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "empty_uniform_array_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "empty_empty_array_float_frag.frag"
+ },
+ "name": "empty_empty_array_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "empty_empty_array_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "empty_empty_array_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "initfunc_empty_array_float_frag.frag"
+ },
+ "name": "initfunc_empty_array_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "initfunc_empty_array_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "initfunc_empty_array_float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_frag.frag
new file mode 100644
index 0000000000..0210ea7c15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_frag.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int i=0;
+ float new_mad[2];
+ float gray = 0.0;
+
+ new_mad[0]=float(1);
+ new_mad[1]=float(2);
+
+ if( (new_mad[0] == 1.0) && (new_mad[1] == 2.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray,gray , gray, 1.0);
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_vert.vert
new file mode 100644
index 0000000000..f5f9741dfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_empty_array_float_vert.vert
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int i=0;
+ float new_mad[2];
+ float gray = 0.0;
+
+ new_mad[0]=float(1);
+ new_mad[1]=float(2);
+
+ if( (new_mad[0] == 1.0) && (new_mad[1] == 2.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_frag.frag
new file mode 100644
index 0000000000..8960e06733
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_frag.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+uniform float new_mad2[2];
+
+void main (void)
+{
+ int i=0;
+ float new_mad[2];
+ float gray = 0.0;
+
+ new_mad[0]=new_mad2[0];
+ new_mad[1]=new_mad2[1];
+
+ if( (new_mad[0] == 45.0) && (new_mad[1] == 14.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_vert.vert
new file mode 100644
index 0000000000..b81eea7f1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/empty_uniform_array_float_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const int array_size = 2;
+uniform float new_mad2[array_size];
+
+void main (void)
+{
+ int i=0;
+ float new_mad[array_size];
+ float gray = 0.0;
+
+ new_mad[0] = new_mad2[0];
+ new_mad[1] = new_mad2[1];
+
+ if( (new_mad[0] == 45.0) && (new_mad[1] == 14.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_frag.frag
new file mode 100644
index 0000000000..93fc911ae9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_frag.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+
+void initialise_array(out float array[2], float init_val);
+void main (void)
+{
+ int i=0;
+ float new_mad[2];
+ float gray = 0.0;
+ initialise_array(new_mad,25.0);
+ if( (new_mad[0] == 25.0) && (new_mad[1] == 25.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+void initialise_array(out float array[2], float init_val)
+{
+ int i=0;
+ array[0] = init_val;
+ array[1] = init_val;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_vert.vert
new file mode 100644
index 0000000000..c6347c99c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/initfunc_empty_array_float_vert.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void initialise_array(out float array[2], float init_val);
+
+void main (void)
+{
+ int i=0;
+ float new_mad[2];
+ float gray = 0.0;
+ initialise_array(new_mad,25.0);
+ if( (new_mad[0] == 25.0) && (new_mad[1] == 25.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+void initialise_array(out float array[2], float init_val)
+{
+ array[0] = init_val;
+ array[1] = init_val;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/input.run.txt
new file mode 100644
index 0000000000..c7cbc1049a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/array/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+array_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_001_to_006.html
new file mode 100644
index 0000000000..4d3ebe11db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: asin_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "asin_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "asin_float_frag_xvary.frag"
+ },
+ "name": "asin_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "asin_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "asin_vec2_frag_xvary.frag"
+ },
+ "name": "asin_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "asin_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "asin_vec3_frag_xvary.frag"
+ },
+ "name": "asin_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "asin_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "asin_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "asin_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "asin_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "asin_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "asin_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "asin_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "asin_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "asin_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary.frag
new file mode 100644
index 0000000000..1c9cf4fe29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(asin(c) / M_PI + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..92c81ec5f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_frag_xvary_ref.frag
@@ -0,0 +1,93 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* The following files are direct copies of each other:
+ *
+ * GL/acos/acos_float_frag_xvary_ref.frag
+ * GL/asin/asin_float_frag_xvary_ref.frag
+ *
+ * Care should be taken to apply any changes to both. Only the last
+ * line where gl_FragColor is assigned should be different.
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float asinValues[17];
+ asinValues[0] = -1.5708;
+ asinValues[1] = -1.06544;
+ asinValues[2] = -0.848062;
+ asinValues[3] = -0.675132;
+ asinValues[4] = -0.523599;
+ asinValues[5] = -0.384397;
+ asinValues[6] = -0.25268;
+ asinValues[7] = -0.125328;
+ asinValues[8] = 0.0;
+ asinValues[9] = 0.125328;
+ asinValues[10] = 0.25268;
+ asinValues[11] = 0.384397;
+ asinValues[12] = 0.523599;
+ asinValues[13] = 0.675132;
+ asinValues[14] = 0.848062;
+ asinValues[15] = 1.06544;
+ asinValues[16] = 1.5708;
+
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (color.r - 0.5);
+
+ float arrVal = (c + 1.0) * 8.0;
+ int arr0 = int(floor(arrVal));
+ float weight = arrVal - floor(arrVal);
+ float asin_c = 0.0;
+
+ if (arr0 == 0)
+ asin_c = lerp(asinValues[0], asinValues[1], weight);
+ else if (arr0 == 1)
+ asin_c = lerp(asinValues[1], asinValues[2], weight);
+ else if (arr0 == 2)
+ asin_c = lerp(asinValues[2], asinValues[3], weight);
+ else if (arr0 == 3)
+ asin_c = lerp(asinValues[3], asinValues[4], weight);
+ else if (arr0 == 4)
+ asin_c = lerp(asinValues[4], asinValues[5], weight);
+ else if (arr0 == 5)
+ asin_c = lerp(asinValues[5], asinValues[6], weight);
+ else if (arr0 == 6)
+ asin_c = lerp(asinValues[6], asinValues[7], weight);
+ else if (arr0 == 7)
+ asin_c = lerp(asinValues[7], asinValues[8], weight);
+ else if (arr0 == 8)
+ asin_c = lerp(asinValues[8], asinValues[9], weight);
+ else if (arr0 == 9)
+ asin_c = lerp(asinValues[9], asinValues[10], weight);
+ else if (arr0 == 10)
+ asin_c = lerp(asinValues[10], asinValues[11], weight);
+ else if (arr0 == 11)
+ asin_c = lerp(asinValues[11], asinValues[12], weight);
+ else if (arr0 == 12)
+ asin_c = lerp(asinValues[12], asinValues[13], weight);
+ else if (arr0 == 13)
+ asin_c = lerp(asinValues[13], asinValues[14], weight);
+ else if (arr0 == 14)
+ asin_c = lerp(asinValues[14], asinValues[15], weight);
+ else if (arr0 == 15)
+ asin_c = lerp(asinValues[15], asinValues[16], weight);
+ else if (arr0 == 16)
+ asin_c = asinValues[16];
+
+ gl_FragColor = vec4(asin_c / M_PI + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary.vert
new file mode 100644
index 0000000000..f2d55ea2e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(asin(c) / M_PI + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..18826e3e96
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_float_vert_xvary_ref.vert
@@ -0,0 +1,40 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * (gtf_Color.r - 0.5);
+
+ float asin_c = 0.0;
+ float scale = 1.0;
+ float sign = 1.0;
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c < 0.0)
+ {
+ sign = -1.0;
+ c *= -1.0;
+ }
+
+ // Taylors series expansion for asin
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ asin_c += scale * pow(c, float(i)) / float(i);
+ scale *= float(i) / float(i + 1);
+ }
+
+ color = vec4(sign * asin_c / M_PI + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..0b70bfb337
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(asin(c) / M_PI + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..97d0b539d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_frag_xvary_ref.frag
@@ -0,0 +1,129 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* The following files are direct copies of each other:
+ *
+ * GL/acos/acos_vec2_frag_xvary_ref.frag
+ * GL/asin/asin_vec2_frag_xvary_ref.frag
+ *
+ * Care should be taken to apply any changes to both. Only the last
+ * line where gl_FragColor is assigned should be different.
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float asinValues[17];
+ asinValues[0] = -1.5708;
+ asinValues[1] = -1.06544;
+ asinValues[2] = -0.848062;
+ asinValues[3] = -0.675132;
+ asinValues[4] = -0.523599;
+ asinValues[5] = -0.384397;
+ asinValues[6] = -0.25268;
+ asinValues[7] = -0.125328;
+ asinValues[8] = 0.0;
+ asinValues[9] = 0.125328;
+ asinValues[10] = 0.25268;
+ asinValues[11] = 0.384397;
+ asinValues[12] = 0.523599;
+ asinValues[13] = 0.675132;
+ asinValues[14] = 0.848062;
+ asinValues[15] = 1.06544;
+ asinValues[16] = 1.5708;
+
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (color.rg - 0.5);
+
+ vec2 arrVal = (c + vec2(1.0, 1.0)) * 8.0;
+ int arr0x = int(floor(arrVal.x));
+ int arr0y = int(floor(arrVal.y));
+ vec2 weight = arrVal - floor(arrVal);
+ vec2 asin_c = vec2(0.0);
+
+ if (arr0x == 0)
+ asin_c.x = lerp(asinValues[0], asinValues[1], weight.x);
+ else if (arr0x == 1)
+ asin_c.x = lerp(asinValues[1], asinValues[2], weight.x);
+ else if (arr0x == 2)
+ asin_c.x = lerp(asinValues[2], asinValues[3], weight.x);
+ else if (arr0x == 3)
+ asin_c.x = lerp(asinValues[3], asinValues[4], weight.x);
+ else if (arr0x == 4)
+ asin_c.x = lerp(asinValues[4], asinValues[5], weight.x);
+ else if (arr0x == 5)
+ asin_c.x = lerp(asinValues[5], asinValues[6], weight.x);
+ else if (arr0x == 6)
+ asin_c.x = lerp(asinValues[6], asinValues[7], weight.x);
+ else if (arr0x == 7)
+ asin_c.x = lerp(asinValues[7], asinValues[8], weight.x);
+ else if (arr0x == 8)
+ asin_c.x = lerp(asinValues[8], asinValues[9], weight.x);
+ else if (arr0x == 9)
+ asin_c.x = lerp(asinValues[9], asinValues[10], weight.x);
+ else if (arr0x == 10)
+ asin_c.x = lerp(asinValues[10], asinValues[11], weight.x);
+ else if (arr0x == 11)
+ asin_c.x = lerp(asinValues[11], asinValues[12], weight.x);
+ else if (arr0x == 12)
+ asin_c.x = lerp(asinValues[12], asinValues[13], weight.x);
+ else if (arr0x == 13)
+ asin_c.x = lerp(asinValues[13], asinValues[14], weight.x);
+ else if (arr0x == 14)
+ asin_c.x = lerp(asinValues[14], asinValues[15], weight.x);
+ else if (arr0x == 15)
+ asin_c.x = lerp(asinValues[15], asinValues[16], weight.x);
+ else if (arr0x == 16)
+ asin_c.x = asinValues[16];
+
+ if (arr0y == 0)
+ asin_c.y = lerp(asinValues[0], asinValues[1], weight.y);
+ else if (arr0y == 1)
+ asin_c.y = lerp(asinValues[1], asinValues[2], weight.y);
+ else if (arr0y == 2)
+ asin_c.y = lerp(asinValues[2], asinValues[3], weight.y);
+ else if (arr0y == 3)
+ asin_c.y = lerp(asinValues[3], asinValues[4], weight.y);
+ else if (arr0y == 4)
+ asin_c.y = lerp(asinValues[4], asinValues[5], weight.y);
+ else if (arr0y == 5)
+ asin_c.y = lerp(asinValues[5], asinValues[6], weight.y);
+ else if (arr0y == 6)
+ asin_c.y = lerp(asinValues[6], asinValues[7], weight.y);
+ else if (arr0y == 7)
+ asin_c.y = lerp(asinValues[7], asinValues[8], weight.y);
+ else if (arr0y == 8)
+ asin_c.y = lerp(asinValues[8], asinValues[9], weight.y);
+ else if (arr0y == 9)
+ asin_c.y = lerp(asinValues[9], asinValues[10], weight.y);
+ else if (arr0y == 10)
+ asin_c.y = lerp(asinValues[10], asinValues[11], weight.y);
+ else if (arr0y == 11)
+ asin_c.y = lerp(asinValues[11], asinValues[12], weight.y);
+ else if (arr0y == 12)
+ asin_c.y = lerp(asinValues[12], asinValues[13], weight.y);
+ else if (arr0y == 13)
+ asin_c.y = lerp(asinValues[13], asinValues[14], weight.y);
+ else if (arr0y == 14)
+ asin_c.y = lerp(asinValues[14], asinValues[15], weight.y);
+ else if (arr0y == 15)
+ asin_c.y = lerp(asinValues[15], asinValues[16], weight.y);
+ else if (arr0y == 16)
+ asin_c.y = asinValues[16];
+
+ gl_FragColor = vec4(asin_c / M_PI + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..a253bd14ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(asin(c) / M_PI + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..1ed1d47f66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec2_vert_xvary_ref.vert
@@ -0,0 +1,54 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ vec2 asin_c = vec2(0.0);
+ vec2 scale = vec2(1.0);
+ vec2 sign = vec2(1.0);
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.r < 0.0)
+ {
+ sign.r = -1.0;
+ c.r *= -1.0;
+ }
+
+ // Taylors series expansion for asin
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ asin_c.r += scale.r * pow(c.r, float(i)) / float(i);
+ scale.r *= float(i) / float(i + 1);
+ }
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.g < 0.0)
+ {
+ sign.g = -1.0;
+ c.g *= -1.0;
+ }
+
+ // Taylors series expansion for asin
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ asin_c.g += scale.g * pow(c.g, float(i)) / float(i);
+ scale.g *= float(i) / float(i + 1);
+ }
+
+ color = vec4(sign * asin_c / M_PI + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..d11988539e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(asin(c) / M_PI + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..2d21f0c547
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_frag_xvary_ref.frag
@@ -0,0 +1,165 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* The following files are direct copies of each other:
+ *
+ * GL/acos/acos_vec3_frag_xvary_ref.frag
+ * GL/asin/asin_vec3_frag_xvary_ref.frag
+ *
+ * Care should be taken to apply any changes to both. Only the last
+ * line where gl_FragColor is assigned should be different.
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float asinValues[17];
+ asinValues[0] = -1.5708;
+ asinValues[1] = -1.06544;
+ asinValues[2] = -0.848062;
+ asinValues[3] = -0.675132;
+ asinValues[4] = -0.523599;
+ asinValues[5] = -0.384397;
+ asinValues[6] = -0.25268;
+ asinValues[7] = -0.125328;
+ asinValues[8] = 0.0;
+ asinValues[9] = 0.125328;
+ asinValues[10] = 0.25268;
+ asinValues[11] = 0.384397;
+ asinValues[12] = 0.523599;
+ asinValues[13] = 0.675132;
+ asinValues[14] = 0.848062;
+ asinValues[15] = 1.06544;
+ asinValues[16] = 1.5708;
+
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (color.rgb - 0.5);
+
+ vec3 arrVal = (c + vec3(1.0, 1.0, 1.0)) * 8.0;
+ int arr0x = int(floor(arrVal.x));
+ int arr0y = int(floor(arrVal.y));
+ int arr0z = int(floor(arrVal.z));
+ vec3 weight = arrVal - floor(arrVal);
+ vec3 asin_c = vec3(0.0);
+
+ if (arr0x == 0)
+ asin_c.x = lerp(asinValues[0], asinValues[1], weight.x);
+ else if (arr0x == 1)
+ asin_c.x = lerp(asinValues[1], asinValues[2], weight.x);
+ else if (arr0x == 2)
+ asin_c.x = lerp(asinValues[2], asinValues[3], weight.x);
+ else if (arr0x == 3)
+ asin_c.x = lerp(asinValues[3], asinValues[4], weight.x);
+ else if (arr0x == 4)
+ asin_c.x = lerp(asinValues[4], asinValues[5], weight.x);
+ else if (arr0x == 5)
+ asin_c.x = lerp(asinValues[5], asinValues[6], weight.x);
+ else if (arr0x == 6)
+ asin_c.x = lerp(asinValues[6], asinValues[7], weight.x);
+ else if (arr0x == 7)
+ asin_c.x = lerp(asinValues[7], asinValues[8], weight.x);
+ else if (arr0x == 8)
+ asin_c.x = lerp(asinValues[8], asinValues[9], weight.x);
+ else if (arr0x == 9)
+ asin_c.x = lerp(asinValues[9], asinValues[10], weight.x);
+ else if (arr0x == 10)
+ asin_c.x = lerp(asinValues[10], asinValues[11], weight.x);
+ else if (arr0x == 11)
+ asin_c.x = lerp(asinValues[11], asinValues[12], weight.x);
+ else if (arr0x == 12)
+ asin_c.x = lerp(asinValues[12], asinValues[13], weight.x);
+ else if (arr0x == 13)
+ asin_c.x = lerp(asinValues[13], asinValues[14], weight.x);
+ else if (arr0x == 14)
+ asin_c.x = lerp(asinValues[14], asinValues[15], weight.x);
+ else if (arr0x == 15)
+ asin_c.x = lerp(asinValues[15], asinValues[16], weight.x);
+ else if (arr0x == 16)
+ asin_c.x = asinValues[16];
+
+ if (arr0y == 0)
+ asin_c.y = lerp(asinValues[0], asinValues[1], weight.y);
+ else if (arr0y == 1)
+ asin_c.y = lerp(asinValues[1], asinValues[2], weight.y);
+ else if (arr0y == 2)
+ asin_c.y = lerp(asinValues[2], asinValues[3], weight.y);
+ else if (arr0y == 3)
+ asin_c.y = lerp(asinValues[3], asinValues[4], weight.y);
+ else if (arr0y == 4)
+ asin_c.y = lerp(asinValues[4], asinValues[5], weight.y);
+ else if (arr0y == 5)
+ asin_c.y = lerp(asinValues[5], asinValues[6], weight.y);
+ else if (arr0y == 6)
+ asin_c.y = lerp(asinValues[6], asinValues[7], weight.y);
+ else if (arr0y == 7)
+ asin_c.y = lerp(asinValues[7], asinValues[8], weight.y);
+ else if (arr0y == 8)
+ asin_c.y = lerp(asinValues[8], asinValues[9], weight.y);
+ else if (arr0y == 9)
+ asin_c.y = lerp(asinValues[9], asinValues[10], weight.y);
+ else if (arr0y == 10)
+ asin_c.y = lerp(asinValues[10], asinValues[11], weight.y);
+ else if (arr0y == 11)
+ asin_c.y = lerp(asinValues[11], asinValues[12], weight.y);
+ else if (arr0y == 12)
+ asin_c.y = lerp(asinValues[12], asinValues[13], weight.y);
+ else if (arr0y == 13)
+ asin_c.y = lerp(asinValues[13], asinValues[14], weight.y);
+ else if (arr0y == 14)
+ asin_c.y = lerp(asinValues[14], asinValues[15], weight.y);
+ else if (arr0y == 15)
+ asin_c.y = lerp(asinValues[15], asinValues[16], weight.y);
+ else if (arr0y == 16)
+ asin_c.y = asinValues[16];
+
+ if (arr0z == 0)
+ asin_c.z = lerp(asinValues[0], asinValues[1], weight.z);
+ else if (arr0z == 1)
+ asin_c.z = lerp(asinValues[1], asinValues[2], weight.z);
+ else if (arr0z == 2)
+ asin_c.z = lerp(asinValues[2], asinValues[3], weight.z);
+ else if (arr0z == 3)
+ asin_c.z = lerp(asinValues[3], asinValues[4], weight.z);
+ else if (arr0z == 4)
+ asin_c.z = lerp(asinValues[4], asinValues[5], weight.z);
+ else if (arr0z == 5)
+ asin_c.z = lerp(asinValues[5], asinValues[6], weight.z);
+ else if (arr0z == 6)
+ asin_c.z = lerp(asinValues[6], asinValues[7], weight.z);
+ else if (arr0z == 7)
+ asin_c.z = lerp(asinValues[7], asinValues[8], weight.z);
+ else if (arr0z == 8)
+ asin_c.z = lerp(asinValues[8], asinValues[9], weight.z);
+ else if (arr0z == 9)
+ asin_c.z = lerp(asinValues[9], asinValues[10], weight.z);
+ else if (arr0z == 10)
+ asin_c.z = lerp(asinValues[10], asinValues[11], weight.z);
+ else if (arr0z == 11)
+ asin_c.z = lerp(asinValues[11], asinValues[12], weight.z);
+ else if (arr0z == 12)
+ asin_c.z = lerp(asinValues[12], asinValues[13], weight.z);
+ else if (arr0z == 13)
+ asin_c.z = lerp(asinValues[13], asinValues[14], weight.z);
+ else if (arr0z == 14)
+ asin_c.z = lerp(asinValues[14], asinValues[15], weight.z);
+ else if (arr0z == 15)
+ asin_c.z = lerp(asinValues[15], asinValues[16], weight.z);
+ else if (arr0z == 16)
+ asin_c.z = asinValues[16];
+
+ gl_FragColor = vec4(asin_c / M_PI + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..e49f94a085
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(asin(c) / M_PI + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..d8b6222608
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/asin_vec3_vert_xvary_ref.vert
@@ -0,0 +1,69 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ vec3 asin_c = vec3(0.0);
+ vec3 scale = vec3(1.0);
+ vec3 sign = vec3(1.0);
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.r < 0.0)
+ {
+ sign.r = -1.0;
+ c.r *= -1.0;
+ }
+
+ // Taylors series expansion for asin
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ asin_c.r += scale.r * pow(c.r, float(i)) / float(i);
+ scale.r *= float(i) / float(i + 1);
+ }
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.g < 0.0)
+ {
+ sign.g = -1.0;
+ c.g *= -1.0;
+ }
+
+ // Taylors series expansion for asin
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ asin_c.g += scale.g * pow(c.g, float(i)) / float(i);
+ scale.g *= float(i) / float(i + 1);
+ }
+
+ // pow can't handle negative numbers so take advantage of symmetry
+ if(c.b < 0.0)
+ {
+ sign.b = -1.0;
+ c.b *= -1.0;
+ }
+
+ // Taylors series expansion for asin
+ // 1000/2 iterations necessary to get the accuracy with this method
+ for(int i = 1; i < 1000; i += 2)
+ {
+ asin_c.b += scale.b * pow(c.b, float(i)) / float(i);
+ scale.b *= float(i) / float(i + 1);
+ }
+
+ color = vec4(sign * asin_c / M_PI + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/input.run.txt
new file mode 100644
index 0000000000..c2de8233ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/asin/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+asin_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_001_to_008.html
new file mode 100644
index 0000000000..05b3e5b461
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: atan_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_float_frag_xvary.frag"
+ },
+ "name": "atan_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec2_frag_xvary.frag"
+ },
+ "name": "atan_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec3_frag_xvary.frag"
+ },
+ "name": "atan_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_float_frag_xvaryyvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_float_frag_xvaryyvary.frag"
+ },
+ "name": "atan_float_frag_xvaryyvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec2_frag_xvaryyvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec2_frag_xvaryyvary.frag"
+ },
+ "name": "atan_vec2_frag_xvaryyvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec3_frag_xvaryyvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "atan_vec3_frag_xvaryyvary.frag"
+ },
+ "name": "atan_vec3_frag_xvaryyvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "atan_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "atan_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "atan_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "atan_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "atan_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "atan_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_009_to_012.html
new file mode 100644
index 0000000000..201c0282cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: atan_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "atan_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "atan_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "atan_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "atan_float_vert_xvaryyvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "atan_float_vert_xvaryyvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "atan_float_vert_xvaryyvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "atan_vec2_vert_xvaryyvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "atan_vec2_vert_xvaryyvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "atan_vec2_vert_xvaryyvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "atan_vec3_vert_xvaryyvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "atan_vec3_vert_xvaryyvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "atan_vec3_vert_xvaryyvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary.frag
new file mode 100644
index 0000000000..75b48dd621
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 4.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(atan(c) / M_PI + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..83546d9d72
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvary_ref.frag
@@ -0,0 +1,55 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 4.0 * 2.0 * (color.r - 0.5);
+ float atan_c = 0.0;
+ float scale = 1.0;
+ float sign = 1.0;
+ vec4 result;
+
+ if(c < 0.0)
+ {
+ sign = -1.0;
+ c *= -1.0;
+ }
+
+ if(c <= 1.0)
+ {
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * atan_c / M_PI + 0.5, 0.0, 0.0, 1.0);
+ }
+ else
+ {
+ c = 1.0 / c;
+
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * (M_PI / 2.0 - atan_c) / M_PI + 0.5, 0.0, 0.0, 1.0);
+ }
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary.frag
new file mode 100644
index 0000000000..20333090b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float x = 2.0 * (color.g - 0.5);
+ float y = 2.0 * (color.b - 0.5);
+ const float epsilon = 1.0e-4;
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x > epsilon || abs(y) > epsilon)
+ {
+ gl_FragColor = vec4(atan(y, x) / (2.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary_ref.frag
new file mode 100644
index 0000000000..5c341a2a52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_frag_xvaryyvary_ref.frag
@@ -0,0 +1,71 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float x = 2.0 * (color.g - 0.5);
+ float y = 2.0 * (color.b - 0.5);
+ float atan_c = 0.0;
+ float scale = 1.0;
+ float sign = 1.0;
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+ const float epsilon = 1.0e-4;
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x > epsilon || abs(y) > epsilon)
+ {
+ if(x < 0.0 ^^ y < 0.0)
+ {
+ sign = -1.0;
+ }
+
+ if(abs(y) <= abs(x))
+ {
+ float c = abs(y / x);
+
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * atan_c / (2.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ }
+ else
+ {
+ float c = abs(x / y);
+
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * (M_PI / 2.0 - atan_c) / (2.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ }
+
+ if(x < 0.0)
+ if(y < 0.0) result.r -= 0.5;
+ else if(y > 0.0) result.r += 0.5;
+ }
+
+ gl_FragColor = result;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary.vert
new file mode 100644
index 0000000000..45d4753a12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 4.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(atan(c) / M_PI + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..98838d98c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvary_ref.vert
@@ -0,0 +1,56 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 4.0 * 2.0 * (gtf_Color.r - 0.5);
+ float atan_c = 0.0;
+ float scale = 1.0;
+ float sign = 1.0;
+ vec4 result;
+
+ if(c < 0.0)
+ {
+ sign = -1.0;
+ c *= -1.0;
+ }
+
+ if(c <= 1.0)
+ {
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * atan_c / M_PI + 0.5, 0.0, 0.0, 1.0);
+ }
+ else
+ {
+ c = 1.0 / c;
+
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * (M_PI / 2.0 - atan_c) / M_PI + 0.5, 0.0, 0.0, 1.0);
+ }
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary.vert
new file mode 100644
index 0000000000..6da6ba13b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float x = 2.0 * (gtf_Color.g - 0.5);
+ float y = 2.0 * (gtf_Color.b - 0.5);
+ const float epsilon = 1.0e-4;
+ color = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x > epsilon || abs(y) > epsilon)
+ {
+ color = vec4(atan(y, x) / (2.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ }
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary_ref.vert
new file mode 100644
index 0000000000..b6c2d5f4ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_float_vert_xvaryyvary_ref.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float x = 2.0 * (gtf_Color.g - 0.5);
+ float y = 2.0 * (gtf_Color.b - 0.5);
+ float atan_c = 0.0;
+ float scale = 1.0;
+ float sign = 1.0;
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+ const float epsilon = 1.0e-4;
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x > epsilon || abs(y) > epsilon)
+ {
+ if(x < 0.0 ^^ y < 0.0)
+ {
+ sign = -1.0;
+ }
+
+ if(abs(y) <= abs(x))
+ {
+ float c = abs(y / x);
+
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * atan_c / (2.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ }
+ else
+ {
+ float c = abs(x / y);
+
+ // Taylors series expansion for atan
+ for(int i = 1; i < 12; i += 2)
+ {
+ atan_c += scale * pow(c, float(i)) / float(i);
+ scale *= -1.0;
+ }
+
+ result = vec4(sign * (M_PI / 2.0 - atan_c) / (2.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ }
+
+ if(x < 0.0)
+ if(y < 0.0) result.r -= 0.5;
+ else if(y > 0.0) result.r += 0.5;
+ }
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..46d927e57c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 4.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(atan(c) / M_PI + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..9358f869ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvary_ref.frag
@@ -0,0 +1,115 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 4.0 * 2.0 * (color.rg - 0.5);
+ vec2 atan_c = vec2(0.0);
+ vec2 scale = vec2(1.0);
+ vec2 sign = vec2(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if(c[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ c[0] *= -1.0;
+ }
+
+ if(c[0] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / M_PI + 0.5;
+ }
+ else
+ {
+ c[0] = 1.0 / c[0];
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / M_PI + 0.5;
+ }
+
+
+ if(c[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ c[1] *= -1.0;
+ }
+
+ if(c[1] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / M_PI + 0.5;
+ }
+ else
+ {
+ c[1] = 1.0 / c[1];
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / M_PI + 0.5;
+ }
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary.frag
new file mode 100644
index 0000000000..8bffcb3dad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 x = 2.0 * (color.gg - 0.5);
+ vec2 y = 2.0 * (color.bb - 0.5);
+ const float epsilon = 1.0e-4;
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ gl_FragColor[0] = atan(y[0], x[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+ gl_FragColor[1] = atan(y[1], x[1]) / (2.0 * M_PI) + 0.5;
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary_ref.frag
new file mode 100644
index 0000000000..bfd7117d48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_frag_xvaryyvary_ref.frag
@@ -0,0 +1,133 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 x = 2.0 * (color.gg - 0.5);
+ vec2 y = 2.0 * (color.bb - 0.5);
+ vec2 c;
+ vec2 atan_c = vec2(0.0);
+ vec2 scale = vec2(1.0);
+ vec2 sign = vec2(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+ const float epsilon = 1.0e-4;
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ if(x[0] < 0.0 ^^ y[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ }
+
+ if(abs(y[0]) <= abs(x[0]))
+ {
+ c[0] = abs(y[0] / x[0]);
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[0] = abs(x[0] / y[0]);
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[0] < 0.0)
+ if(y[0] < 0.0) result[0] -= 0.5;
+ else if(y[0] > 0.0) result[0] += 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+
+ if(x[1] < 0.0 ^^ y[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ }
+
+ if(abs(y[1]) <= abs(x[1]))
+ {
+ c[1] = abs(y[1] / x[1]);
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[1] = abs(x[1] / y[1]);
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] < 0.0)
+ if(y[1] < 0.0) result[1] -= 0.5;
+ else if(y[1] > 0.0) result[1] += 0.5;
+ }
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..5432f7244f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 4.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(atan(c) / M_PI + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..1ef2d5e83d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvary_ref.vert
@@ -0,0 +1,116 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 4.0 * 2.0 * (gtf_Color.rg - 0.5);
+ vec2 atan_c = vec2(0.0);
+ vec2 scale = vec2(1.0);
+ vec2 sign = vec2(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if(c[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ c[0] *= -1.0;
+ }
+
+ if(c[0] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / M_PI + 0.5;
+ }
+ else
+ {
+ c[0] = 1.0 / c[0];
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / M_PI + 0.5;
+ }
+
+
+ if(c[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ c[1] *= -1.0;
+ }
+
+ if(c[1] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / M_PI + 0.5;
+ }
+ else
+ {
+ c[1] = 1.0 / c[1];
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / M_PI + 0.5;
+ }
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary.vert
new file mode 100644
index 0000000000..bfa6448968
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 x = 2.0 * (gtf_Color.gg - 0.5);
+ vec2 y = 2.0 * (gtf_Color.bb - 0.5);
+ const float epsilon = 1.0e-4;
+ color = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ color[0] = atan(y[0], x[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+ color[1] = atan(y[1], x[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary_ref.vert
new file mode 100644
index 0000000000..eee41526ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec2_vert_xvaryyvary_ref.vert
@@ -0,0 +1,133 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 x = 2.0 * (gtf_Color.gg - 0.5);
+ vec2 y = 2.0 * (gtf_Color.bb - 0.5);
+ vec2 c;
+ vec2 atan_c = vec2(0.0);
+ vec2 scale = vec2(1.0);
+ vec2 sign = vec2(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+ const float epsilon = 1.0e-4;
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ if(x[0] < 0.0 ^^ y[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ }
+
+ if(abs(y[0]) <= abs(x[0]))
+ {
+ c[0] = abs(y[0] / x[0]);
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[0] = abs(x[0] / y[0]);
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[0] < 0.0)
+ if(y[0] < 0.0) result[0] -= 0.5;
+ else if(y[0] > 0.0) result[0] += 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+ if(x[1] < 0.0 ^^ y[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ }
+
+ if(abs(y[1]) <= abs(x[1]))
+ {
+ c[1] = abs(y[1] / x[1]);
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[1] = abs(x[1] / y[1]);
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] < 0.0)
+ if(y[1] < 0.0) result[1] -= 0.5;
+ else if(y[1] > 0.0) result[1] += 0.5;
+ }
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..f4101e3e59
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 4.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(atan(c) / M_PI + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..d5cfd01fa1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvary_ref.frag
@@ -0,0 +1,161 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 4.0 * 2.0 * (color.rgb - 0.5);
+ vec3 atan_c = vec3(0.0);
+ vec3 scale = vec3(1.0);
+ vec3 sign = vec3(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+
+
+ if(c[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ c[0] *= -1.0;
+ }
+
+ if(c[0] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / M_PI + 0.5;
+ }
+ else
+ {
+ c[0] = 1.0 / c[0];
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / M_PI + 0.5;
+ }
+
+ if(c[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ c[1] *= -1.0;
+ }
+
+ if(c[1] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / M_PI + 0.5;
+ }
+ else
+ {
+ c[1] = 1.0 / c[1];
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / M_PI + 0.5;
+ }
+
+
+ if(c[2] < 0.0)
+ {
+ sign[2] = -1.0;
+ c[2] *= -1.0;
+ }
+
+ if(c[2] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * atan_c[2] / M_PI + 0.5;
+ }
+ else
+ {
+ c[2] = 1.0 / c[2];
+
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * (M_PI / 2.0 - atan_c[2]) / M_PI + 0.5;
+ }
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary.frag
new file mode 100644
index 0000000000..0db560e1df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary.frag
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 x = 2.0 * (color.ggg - 0.5);
+ vec3 y = 2.0 * (color.bbb - 0.5);
+ const float epsilon = 1.0e-4;
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ gl_FragColor[0] = atan(y[0], x[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+ gl_FragColor[1] = atan(y[1], x[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[2] > epsilon || abs(y[2]) > epsilon)
+ {
+ gl_FragColor[2] = atan(y[2], x[2]) / (2.0 * M_PI) + 0.5;
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary_ref.frag
new file mode 100644
index 0000000000..c6b55f4a0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_frag_xvaryyvary_ref.frag
@@ -0,0 +1,186 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 x = 2.0 * (color.ggg - 0.5);
+ vec3 y = 2.0 * (color.bbb - 0.5);
+ vec3 c;
+ vec3 atan_c = vec3(0.0);
+ vec3 scale = vec3(1.0);
+ vec3 sign = vec3(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+ const float epsilon = 1.0e-4;
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ if(x[0] < 0.0 ^^ y[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ }
+
+ if(abs(y[0]) <= abs(x[0]))
+ {
+ c[0] = abs(y[0] / x[0]);
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[0] = abs(x[0] / y[0]);
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[0] < 0.0)
+ if(y[0] < 0.0) result[0] -= 0.5;
+ else if(y[0] > 0.0) result[0] += 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+
+ if(x[1] < 0.0 ^^ y[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ }
+
+ if(abs(y[1]) <= abs(x[1]))
+ {
+ c[1] = abs(y[1] / x[1]);
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[1] = abs(x[1] / y[1]);
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] < 0.0)
+ if(y[1] < 0.0) result[1] -= 0.5;
+ else if(y[1] > 0.0) result[1] += 0.5;
+ }
+
+ if(x[2] > epsilon || abs(y[2]) > epsilon)
+ {
+
+ if(x[2] < 0.0 ^^ y[2] < 0.0)
+ {
+ sign[2] = -1.0;
+ }
+
+ if(abs(y[2]) <= abs(x[2]))
+ {
+ c[2] = abs(y[2] / x[2]);
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * atan_c[2] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[2] = abs(x[2] / y[2]);
+
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * (M_PI / 2.0 - atan_c[2]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[2] < 0.0)
+ if(y[2] < 0.0) result[2] -= 0.5;
+ else if(y[2] > 0.0) result[2] += 0.5;
+ }
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..cf11d094d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 4.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(atan(c) / M_PI + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..4b811a1036
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvary_ref.vert
@@ -0,0 +1,161 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 4.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ vec3 atan_c = vec3(0.0);
+ vec3 scale = vec3(1.0);
+ vec3 sign = vec3(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if(c[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ c[0] *= -1.0;
+ }
+
+ if(c[0] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / M_PI + 0.5;
+ }
+ else
+ {
+ c[0] = 1.0 / c[0];
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / M_PI + 0.5;
+ }
+
+
+ if(c[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ c[1] *= -1.0;
+ }
+
+ if(c[1] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / M_PI + 0.5;
+ }
+ else
+ {
+ c[1] = 1.0 / c[1];
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / M_PI + 0.5;
+ }
+
+ if(c[2] < 0.0)
+ {
+ sign[2] = -1.0;
+ c[2] *= -1.0;
+ }
+
+ if(c[2] <= 1.0)
+ {
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * atan_c[2] / M_PI + 0.5;
+ }
+ else
+ {
+ c[2] = 1.0 / c[2];
+
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * (M_PI / 2.0 - atan_c[2]) / M_PI + 0.5;
+ }
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary.vert
new file mode 100644
index 0000000000..60d2cca63b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary.vert
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 x = 2.0 * (gtf_Color.ggg - 0.5);
+ vec3 y = 2.0 * (gtf_Color.bbb - 0.5);
+ const float epsilon = 1.0e-4;
+ color = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ color[0] = atan(y[0], x[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+ color[1] = atan(y[1], x[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[2] > epsilon || abs(y[2]) > epsilon)
+ {
+ color[2] = atan(y[2], x[2]) / (2.0 * M_PI) + 0.5;
+ }
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary_ref.vert
new file mode 100644
index 0000000000..9a46dec1ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/atan_vec3_vert_xvaryyvary_ref.vert
@@ -0,0 +1,185 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 x = 2.0 * (gtf_Color.ggg - 0.5);
+ vec3 y = 2.0 * (gtf_Color.bbb - 0.5);
+ vec3 c;
+ vec3 atan_c = vec3(0.0);
+ vec3 scale = vec3(1.0);
+ vec3 sign = vec3(1.0);
+ vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
+ const float epsilon = 1.0e-4;
+
+ // Avoid evaluating atan(0, x) for x < epsilon because it's implementation-dependent
+ if(x[0] > epsilon || abs(y[0]) > epsilon)
+ {
+ if(x[0] < 0.0 ^^ y[0] < 0.0)
+ {
+ sign[0] = -1.0;
+ }
+
+ if(abs(y[0]) <= abs(x[0]))
+ {
+ c[0] = abs(y[0] / x[0]);
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * atan_c[0] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[0] = abs(x[0] / y[0]);
+
+ // Taylors series expansion for atan
+ atan_c[0] += scale[0] * pow(c[0], float(1)) / float(1);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(3)) / float(3);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(5)) / float(5);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(7)) / float(7);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(9)) / float(9);
+ scale[0] *= -1.0;
+ atan_c[0] += scale[0] * pow(c[0], float(11)) / float(11);
+ scale[0] *= -1.0;
+
+ result[0] = sign[0] * (M_PI / 2.0 - atan_c[0]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[0] < 0.0)
+ if(y[0] < 0.0) result[0] -= 0.5;
+ else if(y[0] > 0.0) result[0] += 0.5;
+ }
+
+ if(x[1] > epsilon || abs(y[1]) > epsilon)
+ {
+ if(x[1] < 0.0 ^^ y[1] < 0.0)
+ {
+ sign[1] = -1.0;
+ }
+
+ if(abs(y[1]) <= abs(x[1]))
+ {
+ c[1] = abs(y[1] / x[1]);
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * atan_c[1] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[1] = abs(x[1] / y[1]);
+
+ // Taylors series expansion for atan
+ atan_c[1] += scale[1] * pow(c[1], float(1)) / float(1);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(3)) / float(3);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(5)) / float(5);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(7)) / float(7);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(9)) / float(9);
+ scale[1] *= -1.0;
+ atan_c[1] += scale[1] * pow(c[1], float(11)) / float(11);
+ scale[1] *= -1.0;
+
+ result[1] = sign[1] * (M_PI / 2.0 - atan_c[1]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[1] < 0.0)
+ if(y[1] < 0.0) result[1] -= 0.5;
+ else if(y[1] > 0.0) result[1] += 0.5;
+ }
+
+ if(x[2] > epsilon || abs(y[2]) > epsilon)
+ {
+ if(x[2] < 0.0 ^^ y[2] < 0.0)
+ {
+ sign[2] = -1.0;
+ }
+
+ if(abs(y[2]) <= abs(x[2]))
+ {
+ c[2] = abs(y[2] / x[2]);
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * atan_c[2] / (2.0 * M_PI) + 0.5;
+ }
+ else
+ {
+ c[2] = abs(x[2] / y[2]);
+
+ // Taylors series expansion for atan
+ atan_c[2] += scale[2] * pow(c[2], float(1)) / float(1);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(3)) / float(3);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(5)) / float(5);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(7)) / float(7);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(9)) / float(9);
+ scale[2] *= -1.0;
+ atan_c[2] += scale[2] * pow(c[2], float(11)) / float(11);
+ scale[2] *= -1.0;
+
+ result[2] = sign[2] * (M_PI / 2.0 - atan_c[2]) / (2.0 * M_PI) + 0.5;
+ }
+
+ if(x[2] < 0.0)
+ if(y[2] < 0.0) result[2] -= 0.5;
+ else if(y[2] > 0.0) result[2] += 0.5;
+ }
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/input.run.txt
new file mode 100644
index 0000000000..1c305f2111
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/atan/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+atan_001_to_008.html
+atan_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_001_to_008.html
new file mode 100644
index 0000000000..0a07bd0f0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: biConstants_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxCombinedTextureImageUnits_frag.frag"
+ },
+ "name": "gl_MaxCombinedTextureImageUnits_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxCombinedTextureImageUnits_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxCombinedTextureImageUnits_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxDrawBuffers_frag.frag"
+ },
+ "name": "gl_MaxDrawBuffers_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxDrawBuffers_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxDrawBuffers_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxFragmentUniformVectors_frag.frag"
+ },
+ "name": "gl_MaxFragmentUniformVectors_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxFragmentUniformVectors_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxFragmentUniformVectors_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxTextureImageUnits_frag.frag"
+ },
+ "name": "gl_MaxTextureImageUnits_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxTextureImageUnits_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxTextureImageUnits_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_009_to_016.html
new file mode 100644
index 0000000000..22e133df44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/biConstants_009_to_016.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: biConstants_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxVaryingVectors_frag.frag"
+ },
+ "name": "gl_MaxVaryingVectors_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxVaryingVectors_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxVaryingVectors_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxVertexAttribs_frag.frag"
+ },
+ "name": "gl_MaxVertexAttribs_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxVertexAttribs_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxVertexAttribs_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxVertexTextureImageUnits_frag.frag"
+ },
+ "name": "gl_MaxVertexTextureImageUnits_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxVertexTextureImageUnits_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxVertexTextureImageUnits_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_MaxVertexUniformVectors_frag.frag"
+ },
+ "name": "gl_MaxVertexUniformVectors_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "gl_MaxVertexUniformVectors_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "gl_MaxVertexUniformVectors_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_frag.frag
new file mode 100644
index 0000000000..2770f5605b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxCombinedTextureImageUnits is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxCombinedTextureImageUnits) / 8.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_vert.vert
new file mode 100644
index 0000000000..30411c8c48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxCombinedTextureImageUnits_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxCombinedTextureImageUnits is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxCombinedTextureImageUnits) / 8.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_frag.frag
new file mode 100644
index 0000000000..fd09da1135
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxDrawBuffers is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 1.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxDrawBuffers) / 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_vert.vert
new file mode 100644
index 0000000000..d7cd426572
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxDrawBuffers_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxDrawBuffers is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 1.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxDrawBuffers) / 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_frag.frag
new file mode 100644
index 0000000000..1cf64a5a23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxFragmentUniformVectors is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 16.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxFragmentUniformVectors) / 16.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_vert.vert
new file mode 100644
index 0000000000..75371e9105
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxFragmentUniformVectors_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxFragmentUniformVectors is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 16.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxFragmentUniformVectors) / 16.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_frag.frag
new file mode 100644
index 0000000000..2923d5faaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxTextureImageUnits is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxTextureImageUnits) / 8.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_vert.vert
new file mode 100644
index 0000000000..277821e160
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxTextureImageUnits_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxTextureImageUnits is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxTextureImageUnits) / 8.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_frag.frag
new file mode 100644
index 0000000000..d8acbc462e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVaryingVectors is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxVaryingVectors) / 8.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_vert.vert
new file mode 100644
index 0000000000..342e138ff4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVaryingVectors_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVaryingVectors is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxVaryingVectors) / 8.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_frag.frag
new file mode 100644
index 0000000000..60b5e21248
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVertexAttribs is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxVertexAttribs) / 8.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_vert.vert
new file mode 100644
index 0000000000..2bb5f5e290
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexAttribs_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVertexAttribs is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 8.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxVertexAttribs) / 8.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_frag.frag
new file mode 100644
index 0000000000..d36c93920a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVertexTextureImageUnits is set and that its
+ // value is greater than or equal to the minimum value.
+ if(gl_MaxVertexTextureImageUnits >= 0)
+ gl_FragColor = vec4(1.0);
+ else
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_vert.vert
new file mode 100644
index 0000000000..2310369a82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexTextureImageUnits_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVertexTextureImageUnits is set and that its
+ // value is greater than or equal to the minimum value.
+ if(gl_MaxVertexTextureImageUnits >= 0)
+ color = vec4(1.0);
+ else
+ color = vec4(0.0, 0.0, 0.0, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_frag.frag
new file mode 100644
index 0000000000..7f9e4055db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVertexUniformVectors is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 128.0 will get clamped to 1.0 or white.
+ gl_FragColor = vec4(float(gl_MaxVertexUniformVectors) / 128.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_vert.vert
new file mode 100644
index 0000000000..7cc6fe041f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/gl_MaxVertexUniformVectors_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // This test verifies that gl_MaxVertexUniformVectors is set and that its
+ // value is greater than or equal to the minimum value.
+ // Values greater than 128.0 will get clamped to 1.0 or white.
+ color = vec4(float(gl_MaxVertexUniformVectors) / 128.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/input.run.txt
new file mode 100644
index 0000000000..15c403b1a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biConstants/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+biConstants_001_to_008.html
+biConstants_009_to_016.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_frag.frag
new file mode 100644
index 0000000000..2cda606455
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+void main(void)
+{
+ gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_vert.vert
new file mode 100644
index 0000000000..a095711f1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/DepthRange_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main(void)
+{
+ color = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html
new file mode 100644
index 0000000000..18400ee704
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: biuDepthRange_001_to_002.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "name": "DepthRange_frag.test.html",
+ "pattern": "compare",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "DepthRange_frag.frag",
+ "builtin_uniforms": {
+ "min_required": 2,
+ "valid_values": [
+ "gl_DepthRange.near",
+ "gl_DepthRange.far",
+ "gl_DepthRange.diff"
+ ],
+ }
+ },
+ "state": {
+ "depthrange": {
+ "far": "0.75",
+ "near": "0.25"
+ }
+ },
+ "model": null
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "name": "DepthRange_vert.test.html",
+ "pattern": "compare",
+ "testProgram": {
+ "vertexShader": "DepthRange_vert.vert",
+ "fragmentShader": "../default/default.frag",
+ "builtin_uniforms": {
+ "min_required": 2,
+ "valid_values": [
+ "gl_DepthRange.near",
+ "gl_DepthRange.far",
+ "gl_DepthRange.diff"
+ ]
+ }
+ },
+ "state": {
+ "depthrange": {
+ "far": "0.75",
+ "near": "0.25"
+ }
+ },
+ "model": "grid"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/input.run.txt
new file mode 100644
index 0000000000..21f2fd2e19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/biuDepthRange/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+biuDepthRange_001_to_002.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Data_Types_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Data_Types_frag.frag
new file mode 100644
index 0000000000..4f31090ebf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Data_Types_frag.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ half h1; // Not a basic type.
+ half2 h2; // Not a basic type.
+ half3 h3; // Not a basic type.
+ half4 h4; // Not a basic type.
+ float2 f2; // Not a basic type.
+ float3 f3; // Not a basic type.
+ float4 f4; // Not a basic type.
+ fixed fx1; // Not a basic type.
+ fixed2 fx2; // Not a basic type.
+ fixed3 fx3; // Not a basic type.
+ fixed4 fx4; // Not a basic type.
+ float3x3 f3x3; // Not a basic type.
+ float2x4 f2x4; // Not a basic type.
+ half4x4 h4x4; // Not a basic type.
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Standard_Library_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Standard_Library_frag.frag
new file mode 100644
index 0000000000..392680ee1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CG_Standard_Library_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i = round(1.3); // round is not a built-in function.
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectBuiltInOveride_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectBuiltInOveride_frag.frag
new file mode 100644
index 0000000000..07ba3ef37b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectBuiltInOveride_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump int;
+#endif
+
+int radians(int f)
+{
+ return f;
+}
+
+void main()
+{
+ int f = 45;
+ f = radians(f);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectComma_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectComma_frag.frag
new file mode 100644
index 0000000000..8b671d79b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectComma_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ float f;
+ vec3 v;
+};
+
+void main()
+{
+ const vec4 v = (vec4(1,2,3,4), vec4(5,6,7,8)); // 5,6,7,8
+ const s s1 = (s(9.0, vec3(10,11,12)), s(13.0, vec3(14,15,16))); // 13,14,15,16
+ gl_FragColor = v + vec4(s1.f, s1.v); // 18, 20, 22, 24
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding1_vert.vert
new file mode 100644
index 0000000000..89a3bc584f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding1_vert.vert
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+
+ const struct s2 {
+ int i;
+ vec3 v3;
+ bvec4 bv4;
+ } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
+
+ struct s4 {
+ int ii;
+ vec4 v4;
+ };
+
+ const struct s1 {
+ s2 ss;
+ int i;
+ float f;
+ mat4 m;
+ s4 s44;
+ } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
+
+ const int field3 = s11.i * s11.ss.i; // constant folding (int * int)
+ const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
+ // 49, 64, 81, 100
+ const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]); // 10.0, 5.0, 16.0, 81.0
+ gl_Position = v4;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding2_vert.vert
new file mode 100644
index 0000000000..55c1367245
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstFolding2_vert.vert
@@ -0,0 +1,421 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ struct s5 {
+ float k;
+ };
+ const struct s {
+ int i;
+ float j;
+ s5 s55;
+ } ss = s(4,1.0, s5(1.0));
+
+
+ const struct s2 {
+ int i;
+ vec3 v3;
+ bvec4 bv4;
+ } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
+
+ struct s4 {
+ int ii;
+ vec4 v4;
+ };
+
+ const struct s1 {
+ s2 ss;
+ int i;
+ float f;
+ mat4 m;
+ s4 s44;
+ } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
+
+
+ const struct s7 {
+ int i;
+ mat3 m3;
+ } s77 = s7(12, mat3(15));
+
+ vec2 v21 = vec2(1); // Not a constant
+ const vec2 v22 = vec2(11); // 11.0, 11.0
+ const vec4 v41 = vec4(2); // 2.0, 2.0, 2.0, 2.0
+ const vec4 v43 = vec4(4,4,4,4); // 4.0, 4.0, 4.0, 4.0
+ const vec4 v44 = vec4(5.0, 5.0, 5.0, 5.0); // 5.0, 5.0, 5.0, 5.0
+ const vec4 v45 = vec4(v22, v22); // 11.0, 11.0, 11.0, 11.0
+ const vec4 v46 = vec4(vec2(20, 21), vec2(22, 23)); // 20.0, 21.0, 22.0, 23.0
+
+ const vec3 v31 = vec3(s22.v3); // 9.0, 10.0, 11.0
+ const vec3 v32 = vec3(s77.m3); // 15.0, 0, 0
+ const vec3 v33 = vec3(s77.m3[2]); // 0, 0, 15.0
+ const vec3 v34 = vec3(s77.m3[2][0]); // 0,0,0
+
+
+ const mat4 m41 = mat4(1); // 1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1
+ const mat4 m42 = mat4(v44, v44, v44, v44); // all 5s
+ const mat4 m43 = mat4( v43.x); // 4,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,4
+
+ const vec4 v47 = vec4(m41[0][0]); // 1.0,1.0,1.0,1.0
+
+ const mat4 m45 = mat4(s22.v3, v44, v45, v32, 50, 52); //9,10,11,5,5,5,5,11,11,11,11,15.0, 0,0, 50.0, 52.0
+ //const mat3 m31 = mat3(1, mat2(1), 2.0, vec3(1)); // 1.0, 1,0,0,1,2,1,1,1
+ const vec4 v48 = vec4(v31[0], v22[1], v41[0], v43[3]); //9, 11, 2, 4
+ const vec4 v49 = vec4(s22.v3.xy, s22.v3.zx); // 9,10,11,9
+ const vec4 v410 = vec4(v44.xy, v43.zx); //5,5,4,4
+
+ const vec4 v411 = vec4(m42[3]); // 5,5,5,5
+ const vec4 v412 = vec4(m43[2]); // 0,0,4,0
+
+ const vec2 v23 = vec2(m41); // 1,0
+
+ const vec2 v24 = vec2(33, s11.i); // 33, 2
+
+ const vec4 v413 = vec4(vec2(1.0,2.0),ivec2(3.0,4.0)); // 1,2,3,4
+ const ivec4 i41 = ivec4(1.0, 2.0, 3.0, 4.0); // 1,2,3,4
+
+ const ivec4 i42 = ivec4(6); // 6,6,6,6
+ const ivec4 i43 = ivec4(v45); //11,11,11,11
+
+ const ivec4 i44 = ivec4(v44[0]); // 5,5,5,5
+ const ivec4 i45 = ivec4(vec2(20, 21), vec2(22, 23)); // 20, 21, 22, 23
+ const vec4 v414 = vec4(ivec2(29, 30), ivec2(31, 32)); // 29.0, 30.0, 31.0, 32.0
+ const ivec4 i46 = ivec4(ivec2(2.0,3.0), ivec3(4.0,5.0,6.0));
+ const ivec4 i47 = ivec4(i46); // 2,3,4,5
+ const ivec4 i48 = ivec4(v414.x); // 29,29,29,29
+
+ const ivec4 i49 = ivec4(vec4(1)); // 1,1,1,1
+ const ivec4 i414 = ivec4(mat4(14)); // 14, 0,0,0,
+ const ivec4 i410 = ivec4(m43); // 4,0,0,0
+ const ivec4 i411 = ivec4(m43[1]); // 0, 4, 0, 0
+ const ivec4 i412 = ivec4(s77.i); // 12, 12, 12, 12
+ const ivec4 i416 = ivec4(s22.v3.zyx, 12); // 11, 10, 9, 12
+
+ const vec4 v415 = vec4(ivec2(35), ivec2(36)); // 35.0, 35.0 ,36.0 , 36.0
+
+ const bvec4 b41 = bvec4(1.0, 2.0, 3.0, 4.0); // true,true,true,true
+
+ const bvec4 b42 = bvec4(6); // true,true,true,true
+ const bvec4 b43 = bvec4(v45); //true,true,true,true
+
+ const bvec4 b44 = bvec4(v44[0]); // true,true,true,true
+ const bvec4 b45 = bvec4(vec2(0, 21), vec2(0, 1)); // false, true, false, true
+ const bvec4 b46 = bvec4(ivec2(0.0,3.0), ivec3(0,5.0,6.0)); // false, true, false, true
+ const bvec4 b47 = bvec4(i46); // true,true,true,true
+ const bvec4 b48 = bvec4(v414.x); // true,true,true,true
+
+ const bvec4 b49 = bvec4(vec4(0)); // false,false,false,false
+ const bvec4 b414 = bvec4(mat4(14)); // true, false,false,false,
+ const bvec4 b410 = bvec4(m43); // true,false,false,false
+ const bvec4 b411 = bvec4(m43[1]); // false, true, false, false
+ const bvec4 b412 = bvec4(s77.i) ; // true, true, true, true
+
+ const vec3 v35 = vec3(s11.s44.v4); // 7.0,8.0,9.0
+
+
+ struct s10 {
+ int k;
+ };
+ struct s9 {
+ float f;
+ s10 s101;
+ };
+ const struct s8 {
+ int i;
+ s9 s99;
+ } s88 = s8(1, s9(2.0, s10(5)));
+
+ struct st4 {
+ int m;
+ vec3 v3;
+ };
+ struct st3 {
+ int k;
+ int l;
+ st4 st44;
+ };
+ struct st2 {
+ float f;
+ st3 st33;
+ };
+ const struct st1 {
+ int i;
+ st2 st22;
+ } st11 = st1(1, st2(2.0, st3(5, 6, st4(7, v35))));
+
+ const vec4 v416 = vec4(s88.s99.s101.k); // all 5s
+ const vec4 v417 = vec4(st11.st22.st33.st44.v3, s88.s99.s101.k); // 7.0, 8.0, 9.0, 5.0
+ const vec3 v36 = vec3(s11.ss.v3); // 9, 10, 11
+
+ vec4 v418 = v416; // all 5s
+ const float f1 = v416[0]; // 5.0
+ vec4 v419;
+ v419.xyz = st11.st22.st33.st44.v3;
+ mat4 m47;
+
+ struct struct2 {
+ int k;
+ } struct22 = struct2(4);
+
+ const struct struct1 {
+ struct2 sst2;
+ } struct11 = struct1(struct2(2));
+
+ const vec4 v420 = v417; // 7.0, 8.0, 9.0 , 5.0
+
+ vec4 v421 = vec4(s11.m); // 5, 0, 0, 0
+ vec4 v422 = v420; // 7.0, 8.0, 9.0 , 5.0
+
+ vec4 v423 = s11.s44.v4; // 7, 8, 9, 10
+
+ int int1 = ss.i * ss.i; // 16
+ int int2 = ss.i * 2; // 8
+
+ const vec4 v425 = v420 * v420; // 49, 64, 81, 25
+ const vec4 v426 = s11.m * s11.s44.v4; // 35, 40, 45, 50
+ const vec4 v427 = s11.s44.v4 * s11.m; // 35, 40, 45, 50
+
+ float ff = 2.0;
+ const float ffConst = 2.0;
+
+ vec4 v428 = ff + v425; // ordinary assignment with binary node
+ vec3 v39 = vec3(5);
+
+ vec3 v310 = s22.v3 + v39; //14, 15, 16
+
+ const vec4 v429 = v420 + v420; // 14, 16, 18, 10
+ const vec4 v430 = v420 + ffConst; // 9, 10, 11,7
+ const vec4 v432 = v429 + s11.f; // 18, 20, 22, 14
+
+ const vec4 v433 = vec4(s11.f + s11.f); // all 8s
+ const vec4 v434 = v432 + vec4(3); // 21, 23, 25, 17
+ const mat4 m48 = s11.m + ffConst; // diagonal 7s and others 2s
+ const mat4 m49 = mat4(ffConst + s11.f); // diagonal 6s
+ const mat4 m410 = m48 + s11.f; // diagonal 11, others - 6s
+
+ const mat4 m413 = m48 + m48 ; // diagonal 14, others 4
+ const mat4 m414 = m413 + ffConst ; // diagonal 16, others 6
+
+ const vec4 v435 = ffConst + v420; // 9, 10, 11,7
+ const vec4 v436 = s11.f + v429; // 18, 20, 22, 14
+ const mat4 m415 = ffConst + s11.m; // diagonal 7s and others 2s
+ const mat4 m416 = s11.f + m48 ; // diagonal 11, others - 6s
+ const mat4 m417 = ffConst + m413 ; // diagonal 16, others 6
+
+ const vec4 v437 = v420 - v420; // 0, 0, 0, 0
+ const vec4 v438 = v420 - ffConst; // 5, 6, 7,3
+ const vec4 v440 = v429 - s11.f; // 10, 12, 14, 6
+
+ const vec4 v441 = vec4(s11.f - s11.f); // all 0s
+ const vec4 v442 = v432 - vec4(3); // 15, 17, 19, 11
+ const mat4 m418 = s11.m - ffConst; // diagonal 3s and others -2s
+ const mat4 m419 = mat4(ffConst - s11.f); // diagonal -> -2s
+ const mat4 m420 = m48 - s11.f; // diagonal 3, others -> -2
+
+ const mat4 m423 = m48 - m48 ; // All 0s
+ const mat4 m424 = m413 - ffConst ; // diagonal 12, others 2
+
+ const vec4 v443 = ffConst - v420; // -5, -6, -7,-3
+ const vec4 v444 = s11.f - v429; // -10, -12, -14, -6
+ const mat4 m425 = ffConst - s11.m; // diagonal -3s and others 2s
+ const mat4 m426 = s11.f - m48 ; // diagonal -3, others 2s
+ const mat4 m427 = ffConst - m413 ; // diagonal -12, others -2
+
+ const vec4 v445 = v420 * v420; // 49, 64, 81, 25
+ const vec4 v446 = v420 * ffConst; // 14, 16, 18,10
+ const vec4 v448 = v429 * s11.f; // 56, 46, 72, 40
+
+ const vec4 v449 = vec4(s11.f * s11.f); // all 16
+ const vec4 v450 = v432 * vec4(3); // 54, 60, 66, 42
+ const mat4 m428 = s11.m * ffConst; // diagonal 10 and others 0s
+ const mat4 m429 = mat4(ffConst * s11.f); // diagonal 8
+ const mat4 m430 = m48 * s11.f; // diagonal 28, others 8
+
+ const mat4 m433 = m48 * m48 ; // diagonal 61, others 36
+ const mat4 m434 = m413 * ffConst ; // diagonal 28, others 8
+
+ const vec4 v451 = ffConst * v420; // 14, 16, 18,10
+ const vec4 v452 = s11.f * v429; // 56, 64, 72, 40
+ const mat4 m435 = ffConst * s11.m; // diagonal 10 and others 0s
+ const mat4 m436 = s11.f * m48 ; // diagonal 28, others - 8s
+ const mat4 m437 = ffConst * m413 ; // diagonal 28, others 8
+
+ const vec4 v453 = v420 / v420; // 1, 1, 1, 1
+ const vec4 v454 = v420 / ffConst; // 3.5, 4, 4.5,2.5
+
+ const vec4 v457 = vec4(s11.f / s11.f); // all 1s
+ const vec4 v458 = v432 / vec4(3); // 6, 6.6666, 7.333, 4.6666
+ const mat4 m438 = s11.m / ffConst; // diagonal 2.5 and others 0s
+ const mat4 m439 = mat4(ffConst / s11.f); // diagonal 0.5s
+ const mat4 m440 = m48 / s11.f; // diagonal 1.75, others 0.5s
+
+ const mat4 m443 = m48 / m48 ; // All 1s
+ const mat4 m444 = m413 / ffConst ; // diagonal 7, others 2
+
+ const vec4 v459 = ffConst / v420; // .2857 , .25, .22, .4
+ const vec4 v460 = s11.f / v429; // .2857, .25, .22, .4
+ //const mat4 m445 = ffConst / s11.m; // divide by zero error
+ const mat4 m446 = s11.f / m48 ; // diagonal .571, others 2
+ const mat4 m447 = ffConst / m413 ; // diagonal .1428, others 0.5
+
+ const vec4 v461 = v453 * m428; // 10, 10, 10, 10
+ const vec4 v462 = v453 * m437; // 52, 52, 52, 52
+ const vec4 v463 = m428 * v451; // 140, 160, 180, 100
+ const vec4 v464 = m437 * v451; // 744, 784, 824, 664
+
+ int ii = 2;
+ const int iiConst = 2;
+
+ const ivec4 i420 = ivec4( 7,8,9,5); // 7, 8, 9, 5
+
+ const ivec4 i429 = i420 + i420; // 14, 16, 18, 10
+ const ivec4 i430 = i420 + iiConst; // 9, 10, 11,7
+ const ivec4 i432 = i429 + ss.i; // 18, 20, 22, 14
+
+ const ivec4 i433 = ivec4(ss.i + ss.i); // all 8s
+
+ const ivec4 i435 = iiConst + i420; // 9, 10, 11,7
+ const ivec4 i436 = ss.i + i429; // 18, 20, 22, 14
+
+ const ivec4 i437 = i420 - i420; // 0, 0, 0, 0
+ const ivec4 i438 = i420 - iiConst; // 5, 6, 7,3
+ const ivec4 i440 = i429 - ss.i; // 10, 12, 14, 6
+
+ const ivec4 i441 = ivec4(ss.i - ss.i); // all 0s
+
+ const ivec4 i443 = iiConst - i420; // -5, -6, -7,-3
+ const ivec4 i444 = ss.i - i429; // -10, -12, -14, -6
+
+ const ivec4 i445 = i420 * i420; // 49, 64, 81, 25
+ const ivec4 i446 = i420 * iiConst; // 14, 16, 18,10
+ const ivec4 i448 = i429 * ss.i; // 56, 64, 72, 40
+
+ const ivec4 i449 = ivec4(ss.i * ss.i); // all 16
+
+ const ivec4 i451 = iiConst * i420; // 14, 16, 18,10
+ const ivec4 i452 = ss.i * i429; // 56, 64, 72, 40
+
+ const ivec4 i453 = i420 / i420; // 1, 1, 1, 1
+ const ivec4 i454 = i420 / iiConst; // 3, 4, 4,2
+ const ivec4 i456 = i429 / ss.i; // 3, 4, 4, 2
+
+ const ivec4 i457 = ivec4(ss.i / ss.i); // all 1s
+
+ const ivec4 i459 = iiConst / i420; // 0 , 0, 0,0
+ const ivec4 i460 = ss.i / i429; // 0, 0, 0,0
+
+ const bvec4 b424 = bvec4(s22.bv4);
+
+ const bool b1 = s22.bv4 == b424; // true
+ const bool b2 = i420 == i420; // true
+ const bool b3 = i420 == i445; // false
+ const bool b4 = v420 == v420; // true
+ const bool b5 = m430 == m434; // true
+
+ const vec4 v465 = -v420; // -7, -8, -9, -5
+ const mat4 m448 = -m447 ; // diagonal -.1428, others -0.5
+ const ivec4 i465 = -i456 ; // -3, -4, -4,-2
+
+ const bool b7 = s22 == s22;
+
+ const vec4 v466 = v432 + vec4(3,4,5,6); // 21, 24, 27, 20
+ const vec4 v467 = v432 + vec4(vec2(3,4),5,6); // 21, 24, 27, 20
+ const vec4 v468 = v432 + vec4(3, vec2(4, 5),vec2(6,7)); // 21, 24, 27, 20
+ const vec4 v469 = vec4(v468) + vec4(3) + v468 + vec4(s77.m3[2][0]); // 45, 51, 57, 43
+
+ const bool b8 = ss == ss; // true
+
+ struct st6 {
+ vec3 v;
+ };
+
+ struct st5 {
+ int i;
+ float f;
+ st6 st66;
+ } st55;
+
+ const st5 st551 = st5(2, 4.0, st6(vec3(7)));
+ const st5 st552 = st5(2, 4.0, st6(vec3(7)));
+
+ const bool b10 = st551 == st552; // true
+
+ const bool b11 = st551.st66 == st552.st66; // true
+
+ const st5 st553 = st5(2, 4.0, st6(vec3(8)));
+
+ const bool b12 = st551.st66 == st553.st66; // false
+ const bool b13 = st551 == st553; // false
+
+ const bool b14 = st551 != st552; // false
+ const bool b15 = st551.st66 != st552.st66; // false
+ const bool b16 = st551.st66 != st553.st66; // true
+ const bool b17 = st551 != st553; // true
+
+ const bool b18 = s22.bv4 != b424; // false
+ const bool b19 = i420 != i420; // false
+ const bool b20 = i420 != i445; // true
+ const bool b21 = v420 != v420; // false
+ const bool b22 = m430 != m434; // false
+
+ const int int10 = i420.xy.y; // 8
+
+ //float f = v470.x;
+
+
+
+ const int int13 = -ss.i;
+
+ const vec4 v474 = -vec4(0.5);
+
+ int int14 = ii++;
+ int array[3];
+ array[2];
+
+ const vec4 v478 = v466 * 2.0; // 42, 48, 54, 40
+
+ const vec4 v479 = iiConst > 1 ? v466 : v478; // 21, 24, 27, 20
+
+ const struct st7 {
+ int i;
+ bool b;
+ } st77 = st7(ss.i, true);
+
+ const vec4 v481 = vec4(st77.i);
+
+ const struct st8 {
+ int i;
+ } ;
+
+
+ const struct st9 {
+ s2 ss;
+ } st99 = st9(s22);
+
+ const vec3 v312 = st99.ss.v3; // 9, 10, 11
+ const vec4 v482 = mat4(1)[0]; // 1, 0, 0 , 0
+
+ const mat4 m450 = mat4(ss.i); // mat4(4)
+ const mat4 m451 = mat4(b20); // mat4(1)
+ const mat4 m452 = mat4(st77.b); // mat4(1)
+
+ const vec4 v483 = vec4(vec4(3).x); // 3,3,3,3
+ const mat4 m453 = mat4(vec4(5).x); // mat5(5)
+
+ const vec4 v484 = vec4(mat4(6)[1]); // 0,6,0,0
+ const mat4 m454 = mat4(mat4(6)[1][1]); // mat4(6)
+
+ const vec4 v485 = vec4(st7(8, true).b); // 1,1,1,1
+
+ const vec4 v487 = vec4(vec4(12, 13, 14, 15).ab, 12, 14);
+
+ int i20 = ss.i;
+ const vec4 v489 = -vec4(7,8,9,5); // -7, -8, -9, -5
+
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstruct_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstruct_vert.vert
new file mode 100644
index 0000000000..e8d9b378e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectConstruct_vert.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+struct s {
+ float f;
+} s1 = s(1.0);
+
+struct s3 {
+ int i;
+} s3Inst;
+
+struct s2 {
+ float f;
+ s3 s3Inst;
+} s2Inst = s2(1.0, s3(1));
+
+void main()
+{
+ vec3 i = vec3(5.0, 4.0, ivec2(2.0, 1.0));
+ ivec4 v2 = ivec4(1.0);
+ vec4 v4 = vec4(v2);
+ bvec4 v5 = bvec4(v2);
+ vec3 v6 = vec3(v5);
+ vec3 v = vec3(2, 2.0, 1);
+ vec3 v1 = vec3(1.2, v);
+
+ mat3 m1 = mat3(v,v,v);
+ mat2 m2 = mat2(v, v6.x);
+
+ gl_Position = vec4(1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension10_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension10_V100_frag.frag
new file mode 100644
index 0000000000..9f7eb6a022
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension10_V100_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#version 100
+#extension extensionfoo : enable // warning extension not supported
+#extension extensionfoo : disable // warning extension not supported
+#extension extensionfoo : warn // warning extension not supported
+
+#extension all : disable // no error in the program
+#extension all : warn // no error in the program
+
+#extension extensionfoo : enable // warning extension not supported
+#extension extensionfoo : disable // warning extension not supported
+#extension extensionfoo : warn // warning extension not supported
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension1_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension1_V100_frag.frag
new file mode 100644
index 0000000000..34d497d433
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension1_V100_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#extension all : disable // no error in the program
+#extension all : warn // no error in the program
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension4_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension4_V100_frag.frag
new file mode 100644
index 0000000000..e013e85f89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectExtension4_V100_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#extension extensionfoo : enable // warning extension not supported
+#extension extensionfoo : disable // warning extension not supported
+#extension extensionfoo : warn // warning extension not supported
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFull_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFull_vert.vert
new file mode 100644
index 0000000000..30f14ad27b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFull_vert.vert
@@ -0,0 +1,654 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+struct gtf_MaterialParameters
+{
+vec4 emission;
+vec4 ambient;
+vec4 diffuse;
+vec4 specular;
+float shininess;
+};
+struct gtf_LightSourceParameters
+{
+vec4 ambient;
+vec4 diffuse;
+vec4 specular;
+vec4 position;
+vec4 halfVector;
+vec3 spotDirection;
+float spotExponent;
+float spotCutoff;
+float spotCosCutoff;
+float constantAttenuation;
+float linearAttenuation;
+float quadraticAttenuation;
+};
+struct gtf_PointParameters {
+float size;
+float sizeMin;
+float sizeMax;
+float fadeThresholdSize;
+float distanceConstantAttenuation;
+float distanceLinearAttenuation;
+float distanceQuadraticAttenuation;
+};
+struct gtf_DepthRangeParameters {
+float near;
+float far;
+float diff;
+};
+struct gtf_LightModelParameters {
+vec4 ambient;
+};
+struct gtf_LightModelProducts {
+vec4 sceneColor;
+};
+struct gtf_LightProducts {
+vec4 ambient;
+vec4 diffuse;
+vec4 specular;
+};
+struct gtf_FogParameters {
+vec4 color;
+float density;
+float start;
+float end;
+float scale;
+};
+uniform int gtf_MaxFragmentUniformComponents;
+uniform int gtf_MaxVertexUniformComponents;
+uniform int gtf_MaxVertexTextureImageUnits;
+uniform int gtf_MaxLights;
+uniform int gtf_MaxClipPlanes;
+uniform int gtf_MaxCombinedTextureImageUnits;
+uniform int gtf_MaxTextureCoords;
+uniform int gtf_MaxVertexAttribs;
+uniform int gtf_MaxVaryingFloats;
+uniform int gtf_MaxTextureUnits;
+uniform int gtf_MaxDrawBuffers;
+uniform int gtf_MaxTextureImageUnits;
+uniform gtf_LightProducts gtf_FrontLightProduct[8];
+uniform gtf_LightModelProducts gtf_FrontLightModelProduct;
+uniform gtf_DepthRangeParameters gtf_DepthRange;
+uniform gtf_FogParameters gtf_Fog;
+uniform gtf_PointParameters gtf_Point;
+uniform gtf_LightModelParameters gtf_LightModel;
+varying vec4 gtf_FogFragCoord;
+varying vec4 gtf_BackColor;
+varying vec4 gtf_BackSecondaryColor;
+varying vec4 gtf_FrontSecondaryColor;
+varying vec4 gtf_TexCoord[2];
+varying vec4 gtf_FrontColor;
+uniform gtf_MaterialParameters gtf_FrontMaterial;
+uniform gtf_LightSourceParameters gtf_LightSource[8];
+attribute vec4 gtf_MultiTexCoord1;
+attribute vec4 gtf_MultiTexCoord2;
+attribute vec4 gtf_SecondaryColor;
+attribute vec4 gtf_Color;
+attribute vec4 gtf_MultiTexCoord3;
+attribute vec4 gtf_MultiTexCoord0;
+attribute vec4 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_NormalMatrix;
+uniform mat4 gtf_ProjectionMatrix;
+uniform mat4 gtf_TextureMatrix[8];
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+void test_function(const in int in_int, inout int out_int);
+int test_function1(in int in_int1, inout int in_out_int);
+
+uniform float array_float[2];
+
+struct nested
+{
+ int a;
+ float f;
+};
+
+struct light1
+{
+ float intensity;
+ vec3 position;
+ int test_int[2];
+ nested light2;
+} lightVar;
+light1 ll2;
+
+void Assign (out light1 out1, in light1 in1)
+{
+ out1.intensity = in1.intensity;
+ out1.position = in1.position;
+ out1.test_int[0] = in1.test_int[0];
+ out1.test_int[1] = in1.test_int[1];
+ out1.light2 = in1.light2;
+}
+
+struct light3 {
+ float i;
+};
+
+struct light4 {
+ float i;
+};
+
+struct light5 {
+ float i ;
+ float a[2];
+} light5_inst;
+
+uniform light3 uniformLight3;
+
+struct light6 {
+ float i;
+};
+uniform light6 uniformLight6;
+
+struct slight10{
+ float f;
+ };
+struct slight9{
+ slight10 light10;
+ };
+struct slight8{
+ slight9 light9;
+ };
+struct light7 {
+ slight8 light8;
+} ;
+
+
+light3 struct_var = light3(5.0);
+
+// Attribtue variables can only be Global
+attribute float flt_attrib;
+attribute vec2 vec2_attrib;
+attribute vec3 vec3_attrib;
+attribute vec4 vec4_attrib;
+attribute mat2 mat2_attrib;
+attribute mat3 mat3_attrib;
+attribute mat4 mat4_attrib;
+
+uniform float flt_uniform;
+uniform vec3 uniform_vec3;
+uniform mat3 uniform_mat3;
+
+uniform sampler2D samp[3];
+uniform sampler2D samp1;
+
+const struct light12 {
+ int a;
+} uniform_struct = light12(2);
+
+varying vec3 varying_vec3;
+varying vec2 varying_vec2;
+varying vec4 varying_vec4;
+varying mat4 varying_mat4;
+varying mat2 varying_mat2;
+varying mat3 varying_mat3;
+varying float varying_flt;
+
+float frequencies[2];
+
+void test_function2(int func_int)
+{
+}
+
+void test_function3(light3);
+void test_function4(light5 ll20);
+void test_function5(light1);
+light6 test_function6(int a);
+
+const float FloatConst1 = 3.0 * 8.0, floatConst2 = 4.0;
+const bool BoolConst1 = true && true || false;
+const bool BoolConst2 = false || !false && false;
+
+void main(void)
+{
+
+ int test_int1 = 2;
+ const int const_test_int1 = 2;
+
+ struct structMain {
+ float i;
+ } testStruct;
+
+ struct {
+ structMain a;
+ } aStruct;
+
+ testStruct.i = 5.0 ;
+ struct_var.i = 5.0;
+
+ structMain newStruct, newStruct1;
+ testStruct = newStruct;
+ newStruct = newStruct1;
+
+ lightVar.light2.f = 1.1;
+
+ light1 ll1;
+ ll1.light2.a = 1;
+
+ const struct const_struct {
+ float i;
+ } const_struct_inst = const_struct(1.0);
+
+ //ll1 = ll2;
+ Assign (ll1, ll2);
+ ll1.light2 = ll2.light2;
+ ll1.light2 = ll1.light2;
+ ll1.light2.f = ll2.light2.f;
+ ll1.light2.f = ll1.light2.f;
+
+ // lightVar = ll2;
+ // ll2 = lightVar;
+ Assign (lightVar, ll2);
+ Assign (ll2, lightVar);
+
+ light5 ll10;
+
+ light7 ll7[4];
+ structMain newStruct2[2];
+ newStruct2[0].i = 1.1;
+
+ ll7[0].light8.light9.light10.f = 1.1;
+
+
+ bool test_bool4 = false ;
+
+ bool test_bool5 = 1.2 > 3.0 ;
+
+ int test_int2 = 047;
+ int test_int4 = 0xa8; // testing for hexadecimal numbers
+
+ float test_float1 = 1.5;
+ float test_float2 = .01;
+ float test_float3 = 10.;
+ float test_float4 = 10.01;
+ float test_float5 = 23e+2;
+ float test_float6 = 23E-3;
+ float test_float8 = 23E2;
+ bool test_bool6 = BoolConst1 && ! (test_int1 != 0) && ! BoolConst1 && ! (FloatConst1 != 0.0) && (FloatConst1 != 0.0) && (test_float1 != 0.0);
+
+ vec4 color = vec4(0.0, 1.0, 0.0, 1.0);
+ vec4 color2 = vec4(0.0);
+
+ vec3 color4 = vec3(test_float8);
+
+ ivec4 test_int_vect1 = ivec4(1.0,1.0,1.0,1.0);
+ ivec3 test_int_vec3 = ivec3(1, 1, 1) ;
+
+ bvec4 test_bool_vect1 = bvec4(1., 1., 1. , 1. );
+
+ vec2 test_vec2 = vec2(1., 1.);
+ vec2 test_vec3 = vec2(1., 1);
+ vec4 test_vec4 = vec4(test_int_vect1);
+
+ vec2 test_vec5 = vec2(color4);
+ vec3 test_vec7 = vec3(color);
+ vec3 test_vec8 = vec3(test_vec2, test_float4);
+ vec3 test_vec9 = vec3(test_float4, test_vec2);
+
+ vec4 test_vec10 = vec4(test_vec9, 0.01);
+ vec4 test_vec11 = vec4(0.01, test_vec9);
+
+ vec4 test_vec12 = vec4(test_vec2, test_vec2);
+
+ mat2 test_mat2 = mat2(test_float3);
+ mat3 test_mat3 = mat3(test_float3);
+ mat4 test_mat4 = mat4(test_float3);
+
+ mat2 test_mat7 = mat2(test_vec2, test_vec2);
+ mat2 test_mat8 = mat2(01.01, 2.01, 3.01, 4.01);
+
+ mat3 test_mat9 = mat3(test_vec7, test_vec7, test_vec7);
+ mat4 test_mat10 = mat4(test_vec10, test_vec10, test_vec10, test_vec10);
+ test_mat10[1] = test_vec10;
+
+
+ mat2 test_mat12 = mat2(test_vec2, 0.01, 0.01);
+ mat2 test_mat13 = mat2(0.01, 5., test_vec2);
+ mat2 test_mat15 = mat2(0.1, 5., test_vec2 );
+
+ //mat2 test_mat16 = mat2(test_mat9);
+ //mat2 test_mat17 = mat2(test_mat10);
+
+ float freq1[2];
+ float freq2[25];
+
+ for (int i=0; i<100; i++)
+ {
+ if (test_float1 < 1.0)
+ {
+
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ freq2[1] = 1.9 ;
+ const int array_index = 2;
+ freq2[const_test_int1] = 1.9 ;
+ freq2[array_index] = 1.8;
+
+ const int const_int = 5;
+
+ test_float1 = varying_flt;
+
+ int out_int;
+ int intArray[6];
+ test_function(test_int1, test_int1);
+ test_function(test_int1, intArray[2]);
+
+ vec3 vv = vec3(test_function1(test_int1, out_int));
+ bool bool_var = true;
+ int test_int6 = int(bool_var);
+ test_float1 = float(bool_var);
+ test_float1 = float(test_int6);
+ test_int6 = int(test_float1);
+ bool_var = bool(test_int6);
+ bool_var = bool(test_float1);
+ test_float1 = float(test_vec9);
+
+ test_vec2.x = 1.2;
+ test_vec2.y = 1.4;
+ test_vec2.xy;
+
+
+ color.zy = test_vec2;
+
+ test_vec2[1] = 1.1;
+
+ test_mat2[0][0] = 1.1;
+
+ test_float1 += 1.0;
+ test_float1 -= 1.0;
+ test_float1 *= 1.0;
+ test_float1 /= 1.0;
+
+ test_mat12 *= test_mat13 ;
+ test_mat12 *= test_float1;
+ test_vec2 *= test_float1;
+ test_vec2 *= test_mat12;
+ test_float1++;
+ test_float1--;
+ --test_float1;
+ ++test_float1;
+ test_float1;
+ test_int1++;
+ test_int1--;
+
+ test_vec2 = test_vec2 + test_float1;
+ test_vec2 = test_float1 + test_vec2;
+
+ test_mat12 = test_mat12 * test_mat13;
+ test_vec2 = test_vec2 * test_vec5;
+
+ test_vec2++;
+ test_mat2++;
+
+ bool test_bool2 = test_float2 > test_float3;
+
+ bool test_bool3 = test_int1 > test_int6 ;
+
+ test_bool3 = test_vec2 == test_vec5;
+
+ test_bool2 = test_bool3 && test_bool4;
+ test_bool2 = test_bool3 || test_bool4;
+ test_bool2 = test_bool3 ^^ test_bool4;
+
+ test_bool2 = !test_bool3;
+
+ test_bool3 = !(test_int1 > test_int6) ;
+
+ test_float1 = test_int1 > test_int6 ? test_float2 : test_float3;
+ test_vec2 = test_int1 > test_int6 ? test_vec2 : test_vec5;
+ if(test_bool2)
+ test_float1++;
+ else
+ test_float1--;
+
+ if(test_float1 > test_float2)
+ test_float1++;
+
+ if( test_bool2 )
+ {
+ int if_int;
+ test_float1++;
+ }
+
+ if(test_bool2)
+ if(test_bool3)
+ if(test_bool3)
+ test_float1++;
+
+ for(int for_int=0; for_int < 5; for_int++)
+ {
+ // do nothing as such
+ }
+
+
+ for(int x1=0; x1 < 10; x1++)
+ {
+ if (!test_bool2)
+ break;
+
+ int for_int;
+ }
+
+ for(int x2=-10; x2 < 100; x2++)
+ {
+ test_bool2 = (test_float1 > test_float2);
+ if (!test_bool2)
+ break;
+ }
+
+ for(int for_int1 = 0; for_int1 < 100; for_int1++)
+ {
+ if (!test_bool2)
+ break;
+
+ int for_int;
+ }
+
+ for(int for_int1 = 0; for_int1 < 100; for_int1++)
+ {
+ if (!test_bool2)
+ continue;
+
+ int for_int;
+ }
+
+
+ for(int i=0; i<100; i++)
+ {
+ if (!(test_float1 > test_float2))
+ {
+ break;
+ }
+
+ break;
+ continue;
+ }
+
+ for(int i=0; i<100; i++)
+ {
+ if (!test_bool2)
+ break;
+
+ break;
+ }
+
+ for (int i=0; i<100; i++)
+ {
+ int dowhile_int;
+ dowhile_int = 3;
+
+ if (!test_bool2)
+ break;
+ }
+
+ gl_Position = vec4(2.0, 3.0, 1.0, 1.1);
+ gl_Position = gtf_Vertex;
+
+
+ // VERTEX SHADER BUILT-IN ATTRIBUTES
+
+ vec4 builtInV4 = gtf_Color + gtf_SecondaryColor + gtf_Vertex + gtf_MultiTexCoord0 + gtf_MultiTexCoord1 + gtf_MultiTexCoord2 + gtf_MultiTexCoord3;
+
+
+ int builtInI = gtf_MaxLights + gtf_MaxClipPlanes + gtf_MaxTextureUnits + gtf_MaxTextureCoords + gtf_MaxVertexAttribs + gtf_MaxVertexUniformComponents + gtf_MaxVaryingFloats + gtf_MaxVertexTextureImageUnits + gtf_MaxCombinedTextureImageUnits + gtf_MaxTextureImageUnits + gtf_MaxFragmentUniformComponents + gtf_MaxDrawBuffers ;
+
+
+ mat4 builtInM4 = gtf_ModelViewMatrix + gtf_ModelViewProjectionMatrix + gtf_ProjectionMatrix;
+
+ gtf_NormalMatrix;
+
+ gtf_TextureMatrix[gtf_MaxTextureCoords-1];
+ gtf_TextureMatrix;
+
+ gtf_DepthRange.near ;
+
+ test_float1 = gtf_DepthRange.near;
+ test_float1 = gtf_DepthRange.far;
+ test_float1 = gtf_DepthRange.diff;
+
+ gtf_Point.size;
+ gtf_Point.sizeMin;
+ gtf_Point.sizeMax;
+ gtf_Point.fadeThresholdSize ;
+ gtf_Point.distanceConstantAttenuation;
+ gtf_Point.distanceLinearAttenuation ;
+ gtf_Point.distanceQuadraticAttenuation;
+
+ gtf_MaterialParameters test;
+ gtf_FrontMaterial.emission;
+
+ color = gtf_FrontMaterial.emission;
+ color = gtf_FrontMaterial.ambient;
+ color = gtf_FrontMaterial.diffuse;
+ color = gtf_FrontMaterial.specular;
+ test_float1 = gtf_FrontMaterial.shininess;
+
+ gtf_LightSourceParameters lightSource;
+
+ float builtInFloat1 = gtf_LightSource[0].spotExponent;
+ color = gtf_LightSource[0].ambient;
+ color = lightSource.ambient;
+ color = lightSource.diffuse;
+ color = lightSource.specular;
+ color = lightSource.position;
+ color = lightSource.halfVector;
+ color4 = lightSource.spotDirection;
+ test_float1 = lightSource.spotExponent;
+ test_float1 = lightSource.spotCutoff;
+ test_float1 = lightSource.spotCosCutoff;
+ test_float1 = lightSource.constantAttenuation;
+ test_float1 = lightSource.linearAttenuation;
+ test_float1 = lightSource.quadraticAttenuation;
+
+ color = gtf_LightModel.ambient;
+
+ gtf_LightModelParameters lightModel;
+ color = gtf_LightModel.ambient;
+ color = lightModel.ambient;
+
+ color = gtf_FrontLightModelProduct.sceneColor ;
+
+ gtf_LightModelProducts lightModelProd;
+
+ color = lightModelProd.sceneColor;
+ color = gtf_FrontLightModelProduct.sceneColor;
+
+ color = gtf_FrontLightProduct[0].ambient;
+ color = gtf_FrontLightProduct[0].ambient;
+ gtf_LightProducts lightProd;
+
+ color = lightProd.ambient;
+ color = lightProd.diffuse;
+ color = lightProd.specular;
+
+
+ test_float1 = gtf_Fog.density ;
+ test_float1 = gtf_Fog.start ;
+ test_float1 = gtf_Fog.end ;
+ test_float1 = gtf_Fog.scale ;
+ color = gtf_Fog.color ;
+
+ gtf_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
+ gtf_BackColor = vec4(1.0, 1.0, 1.0, 1.0);
+ gtf_FrontSecondaryColor = vec4(1.0, 1.0, 1.0, 1.0);
+ gtf_BackSecondaryColor = vec4(1.0, 1.0, 1.0, 1.0);
+
+
+ // VARYING VARIABLES AVAILABLE IN FRAGMENT AND VERTEX SHADERS BOTH
+ gtf_TexCoord[0] = vec4(1.0, 1.0, 1.0, 1.0);
+ gtf_FogFragCoord = vec4(1.0, 1.0, 1.0, 1.0);
+
+}
+
+void test_function(const in int in_int, inout int out_int)
+{
+ out_int = 5;
+ int i = 5;
+ return ;
+}
+
+int test_function1(in int in_int1, inout int in_out_int)
+{
+ float ff;
+ in_int1 = 5;
+ return in_int1;
+}
+
+void test_function3(light3 ll)
+{
+ ll.i = 5.0;
+ varying_flt = 1.2;
+}
+
+void test_function4(light5 ll20)
+{
+ ll20.i = 10.0;
+}
+
+void test_function5(light1 struct_light1)
+{
+ struct_light1.light2.a = 1;
+ light5 ll5;
+ struct_light1.light2.f = ll5.i;
+ struct_light1.light2.f++;
+ struct_light1.light2.a++;
+}
+
+light6 test_function6(int a)
+{
+ int x;
+ light6 funcStruct;
+ light7 funcStruct1;
+ -x;
+ x = x - x ;
+ mat2 m;
+ m++;
+ -m;
+ (m)++;
+ return funcStruct;
+}
+
+float test_function7(light1 ll1, int light1 )
+{
+ float f;
+
+ struct ss1 {
+ int a;
+ };
+
+ return float(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_frag.frag
new file mode 100644
index 0000000000..58e9a9554b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_frag.frag
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void testVoid (vec4 v, vec4 v1)
+{
+}
+
+void testVoid (ivec4 v, ivec4 v1)
+{
+}
+
+void main(void)
+{
+ vec4 v;
+ ivec4 i;
+ testVoid(i, i);
+ testVoid(v, v);
+ gl_FragColor = v;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_vert.vert
new file mode 100644
index 0000000000..752f7e607b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFuncOverload_vert.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+struct S2
+{
+ float f;
+};
+
+struct S1
+{
+ float f;
+ S2 s2;
+};
+
+float process(S1 s1);
+float process(S2 s2);
+
+void main()
+{
+ S1 s1 = S1(1.0, S2(1.0));
+ gl_Position = vec4(process(s1));
+}
+
+float process(S1 s1)
+{
+ return s1.f + process(s1.s2);
+}
+
+float process(S2 s2)
+{
+ return s2.f;
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFunction1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFunction1_vert.vert
new file mode 100644
index 0000000000..f384cc57b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectFunction1_vert.vert
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+vec3 bar(vec3, vec3);
+
+uniform vec2 v;
+
+bool foo(out vec3);
+
+void main()
+{
+ bool b1, b2, b3, b4, b5, b6;
+
+ b1 = any(lessThan(v, v));
+
+ b2 = all(lessThanEqual(v, v));
+
+ b3 = any(not(greaterThan(v, v)));
+
+ b4 = any(greaterThanEqual(v, v));
+
+ b5 = any(notEqual(v, v));
+
+ b6 = any(equal(v, v));
+
+ vec2 u;
+ if (b1 && b2 && b3 && b4 && b5 && b6)
+ u = v;
+
+ gl_Position = vec4(u, u);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectModule_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectModule_frag.frag
new file mode 100644
index 0000000000..d3bc69815f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectModule_frag.frag
@@ -0,0 +1,64 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+vec4 test_function4(float);
+vec4 test_function1(float);
+vec4 test_function2(float);
+vec4 test_function3(float);
+float f = 2.6;
+
+
+vec4 test_function1(float ff)
+{
+ vec4 func_vec4 = vec4(ff+f);
+ return func_vec4;
+}
+
+float f1 = 1.5;
+
+vec4 test_function4(float ff)
+{
+ vec4 func_vec4 = vec4(f1);
+ return func_vec4;
+}
+
+float f2 = 3.5;
+
+void main()
+{
+ vec4 v1 = test_function4(f2);
+ vec4 v2 = test_function1(f2);
+ vec4 v3 = test_function2(f2);
+ vec4 v4 = test_function3(f2);
+
+ if (f1 > f2) {
+ gl_FragColor = v1 + v2 + v3 + v4;
+ } else
+ gl_FragColor = v1 + v2 + v3 + v4;
+}
+
+float f4 = 5.5;
+vec4 test_function3(float ff)
+{
+ if (ff > f4)
+ return vec4(ff);
+ else
+ return vec4(f4);
+}
+
+float f3 = 4.5;
+vec4 test_function2(float ff)
+{
+ vec4 func_vec4 = vec4(ff+f3);
+ return func_vec4;
+}
+
+float f5 = 6.5;
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse1_frag.frag
new file mode 100644
index 0000000000..65a9fb07fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse1_frag.frag
@@ -0,0 +1,51 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec3 a[8];
+
+uniform bool ub;
+varying mat4 vm;
+
+int foo(float);
+
+float bar(int i)
+{
+ return float(i);
+}
+
+void main (void)
+{
+ const int x = 3;
+ mat4 a[4];
+ vec4 v;
+
+ for (float f = 0.0; f != 3.0; ++f)
+ {
+ }
+
+ vec3 v3[x + x];
+
+ int vi = foo(2.3);
+
+ vec3 v3_1 = v3[x];
+
+ float f1 = a[x][2].z * float(x);
+ f1 = a[x][2][2] * float(x);
+ f1 = v[2] * v[1];
+
+ const int ci = 2;
+
+}
+
+int foo(float f)
+{
+ return 2;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_frag.frag
new file mode 100644
index 0000000000..6bfe2ec57a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_frag.frag
@@ -0,0 +1,136 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+const float FloatConst1 = 3.0 * 8.0, floatConst2 = 4.0;
+const bool BoolConst1 = true && true || false;
+const bool BoolConst2 = false || !false && false;
+
+void main (void)
+{
+ float float1 = 4.0, float2 = floatConst2;
+ int int_1 = int(FloatConst1);
+ vec4 vec4_1;
+ vec3 vec3_1;
+// unsigned int unsigned_int_1;
+ bool bool4, bool5;
+
+ bool4 = bool5;
+ //float1 = bool5;
+ //bool5 = float1;
+
+ bool4 = 4.0 > 5.0;
+ bool4 = !(3.2 != 0.0);
+ bool4 = bool(float1);
+ bool4 = bool(int_1);
+ float1 = float(bool4);
+ float1 = float(int_1);
+ int_1 = int(float1);
+ int_1 = int(bool4);
+
+ {
+ int a, b, c;
+
+ a = b;
+ b = c;
+ {
+ int b, c, d;
+
+ b = c;
+ c = d;
+ {
+ int a, d, e;
+
+ a = d;
+ d = e;
+ }
+ {
+ int a, b, c;
+ a = b;
+ b = c;
+ }
+ }
+ a = b;
+ b = c;
+ }
+
+ {
+ float f1, f2;
+ vec3 v31, v32;
+
+ max(f1, f2);
+ max(v31, v32);
+
+ vec4 v4 = vec4(3.0);
+ vec3 v3 = -vec3(2.0, 1.0, 3.0);
+ mat2 m2 = mat2(3.0, 4.0, 6.0, 3.0);
+ //mat4 m4 = mat4(1.0, m2, v3, v4, m2);
+ }
+
+ if (BoolConst1)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (BoolConst2)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (BoolConst1 || BoolConst2)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (BoolConst2 && BoolConst1)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (FloatConst1 != 0.0)
+ --int_1;
+ else
+ ++int_1;
+
+ if (0 != 0)
+ ++int_1;
+ else
+ --int_1;
+
+ bool4 = BoolConst1 && ! (int_1 != 0) && ! BoolConst1 && ! (FloatConst1 != 0.0) && (FloatConst1 != 0.0) && (float1 != 0.0);
+
+ float1 = 5 != 0 ? float1 : float(int_1);
+ float1 = 0 != 0 ? float1 : float(int_1);
+
+ if (float1 != float1)
+ ++int_1;
+ else
+ --int_1;
+
+ float1 = float1 != float1 ? float1 : float(int_1);
+
+ --int_1;
+ ++float1;
+ (vec4_1.x)--;
+ vec3_1++;
+
+ if (int_1 != 4)
+ discard;
+
+ float1 = 4.0 + 6.0;
+ int ii,jj,kk;
+ float ff;
+ ii = jj, kk, ff;
+
+ vec4_1 = vec4_1 + 2.0;
+ ivec4 iv;
+ iv = iv + 2;
+ gl_FragColor = vec4(float1+float1, float1, float1, float(int_1));
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_vert.vert
new file mode 100644
index 0000000000..d2686442a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParse2_vert.vert
@@ -0,0 +1,149 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+const float FloatConst1 = 3.0 * 8.0, floatConst2 = 4.0;
+const bool BoolConst1 = true && true || false;
+const bool BoolConst2 = false || !false && false;
+
+void main (void)
+{
+ float float1 = 4.0, float2 = floatConst2;
+ int int_1 = int(FloatConst1);
+ vec4 vec4_1;
+ vec3 vec3_1 = vec3(1, 1, 1);
+ vec3 vec3_2 = vec3(0, 0, 0);
+// unsigned int unsigned_int_1;
+ bool bool4, bool5;
+
+ bool4 = bool5;
+ //float1 = bool5;
+ //bool5 = float1;
+
+ bool4 = 4 > 5;
+ bool4 = !(3.2 != 0.0);
+ bool4 = bool(float1);
+ bool4 = bool(int_1);
+ float1 = float(bool4);
+ float1 = float(int_1);
+ int_1 = int(float1);
+ int_1 = int(bool4);
+
+ {
+ int a, b, c;
+
+ a = b;
+ b = c;
+ {
+ int b, c, d;
+
+ b = c;
+ c = d;
+ {
+ int a, d, e;
+
+ a = d;
+ d = e;
+ }
+ {
+ int a, b, c;
+ a = b;
+ b = c;
+ }
+ }
+ a = b;
+ b = c;
+ }
+
+ {
+ float f1, f2;
+ vec3 v31, v32;
+
+ max(f1, f2);
+ max(v31, v32);
+
+ vec4 v4 = vec4(3.0);
+ vec3 v3 = -vec3(2.0, 1.0, 3.0);
+ mat2 m2 = mat2(3.0, 4.0, 6.0, 3.0);
+ //mat4 m4 = mat4(1.0, m2, v3, v4, m2);
+ }
+
+ if (BoolConst1)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (BoolConst2)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (BoolConst1 || BoolConst2)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (BoolConst2 && BoolConst1)
+ ++vec3_1;
+ else
+ --vec3_1;
+
+ if (FloatConst1 != 0.0)
+ --int_1;
+ else
+ ++int_1;
+
+ if (0 != 0)
+ ++int_1;
+ else
+ --int_1;
+
+ bool4 = BoolConst1 && ! (int_1 != 0) && ! BoolConst1 && ! (FloatConst1 != 0.0) && (FloatConst1 != 0.0) && (float1 != 0.0);
+
+ float1 = 5 != 0 ? float1 : float(int_1);
+ float1 = BoolConst1 ? float1 : float(int_1);
+
+ if (float1 != float1)
+ ++int_1;
+ else
+ --int_1;
+
+ float1 = float1 != float1 ? float1 : float(int_1);
+
+ --int_1;
+ ++float1;
+ (vec4_1.x)--;
+ vec3_1++;
+
+ if (vec3_1.x > vec3_2.x)
+ float1 = 4.0 + 6.0;
+
+ if (bool4 ^^ bool5)
+ float1 *= 2.4;
+
+ if (false ^^ false)
+ float1 *= 2.5;
+
+ if (true ^^ false)
+ float1 *= 2.6;
+
+ {
+ int i;
+ }
+
+ if (bool4) {
+ int i;
+ } else {
+ int i;
+ i = 5;
+ }
+
+ mat4 m1;
+ m1[2][1] = 4.0;
+
+ gl_Position = vec4(float1+float1, float1, float1, float(int_1));
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest1_frag.frag
new file mode 100644
index 0000000000..05c106103b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest1_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ vec4 v;
+} s2;
+
+void main()
+{
+ s s1 = s(vec4(ivec4(4.0, vec2(5,6), 7.0)));
+ vec4 v = vec4(2,ivec2(3.0, 4.0), 5.0);
+ vec4 v4 = vec4(ivec4(8.0));
+
+ gl_FragColor = v4 + v + s1.v;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest_frag.frag
new file mode 100644
index 0000000000..46b6ddc601
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectParseTest_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s{
+ float f;
+ vec3 v;
+} s1 ;
+void main()
+{
+ vec4 v = vec4(float(vec2(1,2)), 5,6,7); // 1, 5, 6, 7
+ vec4 v1 = vec4(3, vec2(ivec2(1,2)), 4); // 3, 1, 2, 4
+ vec4 v2 = vec4(8, 9, vec4(ivec4(1,2,3,4))); // 8,9, 1,2
+ vec2 v3 = vec2(v2); // 8,9
+ vec4 v4 = vec4(v3, v2.z, v2.w); // 8,9,1,2
+
+ const vec4 v5 = vec4(2.0, s(2.0, vec3(3,4,5)).v); // 2,3,4,5
+ gl_FragColor = v5 + v + v1 + v4 ; // 14, 18, 13, 18
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess5_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess5_frag.frag
new file mode 100644
index 0000000000..1dbac1a011
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess5_frag.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//mutiple line macros - test case.
+
+#define test 5
+#define t1 1
+#define t2 2
+#define token (t1+t2)
+#define test1 int sum =1; sum = test; sum = test+test;
+
+#define test2 { test1 sum = sum +token; sum = t2*t1; }
+
+void main(void)
+{
+ int test3=1;
+ test1
+ test2;
+ test3 = test;
+ sum = test3;
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess8_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess8_frag.frag
new file mode 100644
index 0000000000..01a3466e9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess8_frag.frag
@@ -0,0 +1,115 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// Extensive testing on #if #else #elif #ifdef, #ifndef and #endif.
+
+
+#define t1 1
+
+#if(t1==1)
+ #define t2 2
+#endif
+
+#if (t2!=2)
+ #define t3 33
+#else
+ #define t3 3
+#endif
+
+#if (t3!=3)
+ #define t4 4
+#elif (t3==3)
+ #define t4 44
+#else
+ #define t4 0
+#endif
+
+#if defined(t5)
+ #define t6 6
+#elif (t3!=3)
+ #define t5 5
+#elif (t3==3)
+ #define t5 5
+#endif
+
+#ifdef t5
+ #define t6 6
+#else
+ #define t7 7
+#endif
+
+#ifndef t8
+ #define t8 8
+#endif
+
+#if defined t8
+ #define t9
+ #ifdef t9
+ #define t10 10
+ #endif
+#elif
+ #define t11 11
+#endif
+
+#ifndef t8
+ #define t12 12
+#else
+ #define t12 12
+ #ifndef t13
+ #define t13 13
+ #endif
+ #ifdef t14
+ #define t15 15
+ #else
+ #if defined t8
+ #define t16 16
+ #endif
+ #endif
+#endif
+
+#ifdef t1
+ #ifdef t10
+ #if defined t8
+ #if defined(t3)
+ #ifndef t20
+ #define t25 25
+ #endif
+ #else
+ #define t15 15
+ #define t24 24
+ #endif
+ #endif
+ #endif
+#else
+ #ifdef t21
+ #define t22 22
+ #else
+ #define t23 23
+ #endif
+#endif
+#define t7 7
+#define t11 11
+#define t14 14
+#define t15 15
+#define t20 20
+#define t22 22
+#define t23 23
+#define t24 42
+
+void main(void)
+{
+ int sum =0;
+ sum = t1+t2+t3+t4+t5;
+ sum = t6+t7+t8+t9+t10;
+ sum = t11+t12+t13+t14+t15;
+ sum = t16+t20+t22+t23+t25+t24;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess9_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess9_frag.frag
new file mode 100644
index 0000000000..4946312934
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectPreprocess9_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#define t1 2.3333333333333333
+#define t2 (0.978293600-1.0)
+#define t3 .9090909090
+#define t4 26578235.000000083487
+#define t5 78e-03
+#define t6 78.100005E+05
+#define t7 6278.78e-5
+
+void main(void){
+ float tes=2e-3;
+ float test=3.2e-5;
+ float test1=0.99995500;
+ float test2=6789.983;
+
+ test = t1+t2;
+ test = t3-t4;
+ tes = t5 * t6;
+ test2 = t7;
+
+ gl_FragColor = vec4(test, tes, test1, test2);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_frag.frag
new file mode 100644
index 0000000000..9226f186c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v = vec2(1,5);
+ // at the end of next statement, values in
+ // v.x = 12, v.y = 12
+ v.xy += v.yx += v.xy;
+ // v1 and v2, both are initialized with 12
+ vec2 v1 = v, v2 = v;
+
+ v1.xy += v2.yx += ++(v.xy); // v1 = 37, v2 = 25 each
+ v1.xy += v2.yx += (v.xy)++; // v1 = 75, v2 = 38 each
+ gl_FragColor = vec4(v1,v2); // 75, 75, 38, 38
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_vert.vert
new file mode 100644
index 0000000000..06ce3b3ee3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle1_vert.vert
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Normal;
+uniform mat4 gtf_NormalMatrix;
+void main(void)
+{
+ vec4 v = vec4(1,2,3,4);
+ vec3 v3 = vec3(5,6,7);
+ vec4 v4 = vec4(normalize(v3.yzy).xyz.zyx, 1.0);
+ gl_Position = v4 + vec4(normalize(gtf_NormalMatrix * gtf_Normal).xyz.zyx, v4.y);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_frag.frag
new file mode 100644
index 0000000000..24074aa2a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_frag.frag
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f, f1, f2;
+ f = f1 = f2;
+ f += f1 += f2;
+
+ vec4 v, v1, v2;
+ v = v1 = v2;
+ v += v1 += v2;
+ v.wx = v1.zx = v2.yx;
+ v.wx += v1.zx += v2.yx;
+
+ mat4 m, m1, m2;
+ m = m1 = m2;
+ m += m1 += m2;
+ m[3].wx = m1[2].zx = m2[1].yx;
+ m[3].wx += m1[2].zx += m2[1].yx;
+
+ mat4 am[4], am1[4], am2[4];
+ am[3] = am1[2] = am2[1];
+ am[3] += am1[2] += am2[1];
+ am[3][3].wx = am1[2][2].zx = am2[1][1].yx;
+ am[3][3].wx += am1[2][2].zx += am2[1][1].yx;
+ am[3][3].wx += am1[2][2].zx += ++(am2[1][1].yx);
+ am[3][3].wx += am1[2][2].zx += (am2[1][1].yx)++;
+
+ gl_FragColor = vec4(am[3][3].z, m[3].w, v.w, f);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_vert.vert
new file mode 100644
index 0000000000..b197cc0bac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle2_vert.vert
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ vec4 v1 = vec4(5,6,7,8);
+ vec4 v2 = vec4(9,10, 11, 12);
+ vec3 v3 = (v1 * v2).ywx;
+ float f = (v2 * v1).z;
+ vec3 v4 = normalize((v1.ywx * v3).xyz).xyz;
+ gl_Position = vec4(v4, f);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle3_frag.frag
new file mode 100644
index 0000000000..4f2665c13e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectSwizzle3_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec4 v = vec4(5,6,7,8);
+ // value changes for lhs
+ // 8765, 6758, 857, 75 i.e. replace v.zx
+ // value changes for rhs
+ // 8765, 6758, 86 i.e replace with v.wy
+ // replace v.z with v.w
+ // replace v.x with v.y
+ // add 1.000000 to v.w and v.y
+ v.wzyx.zywx.wzy.zy = (v.wzyx.zywx.wx)++;
+ gl_FragColor = vec4(v); // 6,7,8,9
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectVersion_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectVersion_V100_frag.frag
new file mode 100644
index 0000000000..1a0405a264
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/CorrectVersion_V100_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#version 100
+#ifdef GL_ES
+precision mediump float;
+#endif
+/* #version can only be followed by number 100. The only statements before
+ #version can be comment or white spaces */
+
+void main()
+{
+ gl_FragColor = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/DuplicateVersion1_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/DuplicateVersion1_V100_frag.frag
new file mode 100644
index 0000000000..fce81e58b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/DuplicateVersion1_V100_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#version 100
+#version 100
+#ifdef GL_ES
+precision mediump float;
+#endif
+/* Two version statements are not allowed since any #version must be the first non-whitespace, non-comment */
+
+void main()
+{
+ gl_FragColor = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/FunctionParam_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/FunctionParam_vert.vert
new file mode 100644
index 0000000000..4b74943bdf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/FunctionParam_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+int y = 1;
+
+int foo(int, int b[y]) // array size should be constant
+{
+ return 1;
+}
+
+void main()
+{
+ int a[1];
+
+ gl_Position = vec4(1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Include_Preprocessor_Directive_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Include_Preprocessor_Directive_frag.frag
new file mode 100644
index 0000000000..0b7d674b8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Include_Preprocessor_Directive_frag.frag
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#include "GL/build/NVIDIA_Test_Include_frag.frag"
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Low_Level_Assembly_Reserved_Words_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Low_Level_Assembly_Reserved_Words_frag.frag
new file mode 100644
index 0000000000..4086830477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Low_Level_Assembly_Reserved_Words_frag.frag
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float MIN;
+uniform float R0;
+uniform float FOGC;
+uniform float CUBE;
+uniform float f;
+uniform float o;
+uniform float p;
+uniform float w;
+uniform float x;
+uniform float y;
+uniform float z;
+
+void main()
+{
+ gl_FragColor = vec4(f, o, p, w);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Main_Parameters_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Main_Parameters_vert.vert
new file mode 100644
index 0000000000..200f39d74b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Main_Parameters_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main(vec4 position : POSITION)
+{
+ gl_Position = position;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest3_frag.frag
new file mode 100644
index 0000000000..1242467a08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const vec4 v = vec4(normalize(vec4(1))); // Builtin functions are constant expressions if all their parameters are constant expressions - code ok
+ const vec4 v1 = vec4(clamp(1.0, .20, 3.0)); // Builtin functions are constant expressions if all their parameters are constant expressions - code ok
+ float f = 1.0;
+ const vec4 v2 = vec4(float(vec4(1,2,3,f))); // f is not constant - code fails and test does not compile (expected)
+
+ gl_FragColor = v + v1 + v2;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest4_frag.frag
new file mode 100644
index 0000000000..60ef6d31b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/ParseTest4_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const vec4 v = vec2(2.0, 3.0);
+ gl_FragColor = v;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Constant_Conversions_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Constant_Conversions_frag.frag
new file mode 100644
index 0000000000..526d62b20d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Constant_Conversions_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f = 2; // Should be 2.0
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Scalar_Vector_Expressions_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Scalar_Vector_Expressions_frag.frag
new file mode 100644
index 0000000000..cc67c7ffb1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Permissive_Scalar_Vector_Expressions_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v = vec2(1.0, 2.0);
+ v *= 2.0; // Legal in GLSL.
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/TernaryOp_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/TernaryOp_frag.frag
new file mode 100644
index 0000000000..2356f00596
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/TernaryOp_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ mat4 m;
+ vec4 v;
+ bool b;
+ gl_FragColor = b ? v : m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Texture_Rectangle_Samplers_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Texture_Rectangle_Samplers_frag.frag
new file mode 100644
index 0000000000..48bb0d609e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/Texture_Rectangle_Samplers_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2DRect samp;
+
+void main()
+{
+ gl_FragColor = texture2DRect(samp, vec2(0.0, 0.0));
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array10_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array10_frag.frag
new file mode 100644
index 0000000000..a46681cf36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array10_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+void main()
+{
+ float f[];
+ float flt = f[5];
+ float f[3]; // higher array index has already been used
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array11_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array11_frag.frag
new file mode 100644
index 0000000000..dfd7abdadf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array11_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f[];
+ int f[4]; // array redeclared with a different type
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array1_frag.frag
new file mode 100644
index 0000000000..ab402ba92b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array1_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int array[2][2]; // two dimentional arrays are not allowed
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array2_frag.frag
new file mode 100644
index 0000000000..37d0cbc242
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array2_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const int array[2]; // cannot declare const arrays
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array3_frag.frag
new file mode 100644
index 0000000000..d8d7061bd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array3_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int array1[2], array2[2];
+ bool b = array1 == array2; // equality operator does not work on arrays but works on array elements
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array4_frag.frag
new file mode 100644
index 0000000000..92abeb826c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array4_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f[-2]; // cannot declare arrays with negative size
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array5_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array5_frag.frag
new file mode 100644
index 0000000000..e413562084
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array5_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i = 3;
+ float f[i]; // arrays should be declared with a constant size
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array6_frag.frag
new file mode 100644
index 0000000000..483f49af9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array6_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const float index = 3.0;
+ float f[index]; // arrays should be declared with an integer expression not float
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array7_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array7_frag.frag
new file mode 100644
index 0000000000..44dd6e6d9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array7_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f[5];
+ f[]; // array used without a size
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array8_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array8_frag.frag
new file mode 100644
index 0000000000..97db8819d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array8_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f[5];
+ float f[]; // redeclaration of array already declared with a size
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array9_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array9_frag.frag
new file mode 100644
index 0000000000..f75edc75dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/array9_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 array[2];
+ array.xy; // arrays cannot directly be swizzled, however, an element of array can be swizzled
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute1_vert.vert
new file mode 100644
index 0000000000..bb2f1be6d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute1_vert.vert
@@ -0,0 +1,14 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute int i; // attributes cannot be int or bool
+
+void main()
+{
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute2_vert.vert
new file mode 100644
index 0000000000..2e3309b530
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute2_vert.vert
@@ -0,0 +1,14 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute float f[2]; // attributes cannot be arrays
+
+void main()
+{
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_frag.frag
new file mode 100644
index 0000000000..894197be37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ attribute float foo; // attributes can be declared at global scope in vertex shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_vert.vert
new file mode 100644
index 0000000000..9cf16299a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/attribute_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ attribute float foo; // attributes can be declared at a global scope only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/break_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/break_frag.frag
new file mode 100644
index 0000000000..6bfdcbd367
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/break_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ break; // break keyword allowed only inside the loops
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_001_to_008.html
new file mode 100644
index 0000000000..3ff10f436e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_001_to_008.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectBuiltInOveride_frag.frag"
+ },
+ "name": "CorrectBuiltInOveride_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectComma_frag.frag"
+ },
+ "name": "CorrectComma_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectConstFolding1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectConstFolding1_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectConstFolding2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectConstFolding2_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectConstruct_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectConstruct_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectExtension10_V100_frag.frag"
+ },
+ "name": "CorrectExtension10_V100_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectExtension1_V100_frag.frag"
+ },
+ "name": "CorrectExtension1_V100_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectExtension4_V100_frag.frag"
+ },
+ "name": "CorrectExtension4_V100_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_009_to_016.html
new file mode 100644
index 0000000000..c3f6658290
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_009_to_016.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectFull_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectFull_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectFuncOverload_frag.frag"
+ },
+ "name": "CorrectFuncOverload_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectFuncOverload_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectFuncOverload_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectFunction1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectFunction1_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectModule_frag.frag"
+ },
+ "name": "CorrectModule_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectParse1_frag.frag"
+ },
+ "name": "CorrectParse1_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectParse2_frag.frag"
+ },
+ "name": "CorrectParse2_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectParse2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectParse2_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_017_to_024.html
new file mode 100644
index 0000000000..1869eca48c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_017_to_024.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectParseTest1_frag.frag"
+ },
+ "name": "CorrectParseTest1_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectParseTest_frag.frag"
+ },
+ "name": "CorrectParseTest_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectPreprocess5_frag.frag"
+ },
+ "name": "CorrectPreprocess5_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectPreprocess8_frag.frag"
+ },
+ "name": "CorrectPreprocess8_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectPreprocess9_frag.frag"
+ },
+ "name": "CorrectPreprocess9_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectSwizzle1_frag.frag"
+ },
+ "name": "CorrectSwizzle1_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectSwizzle1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectSwizzle1_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectSwizzle2_frag.frag"
+ },
+ "name": "CorrectSwizzle2_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_025_to_032.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_025_to_032.html
new file mode 100644
index 0000000000..132f0ce734
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_025_to_032.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_025_to_032.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "CorrectSwizzle2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "CorrectSwizzle2_vert.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectSwizzle3_frag.frag"
+ },
+ "name": "CorrectSwizzle3_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "DuplicateVersion1_V100_frag.frag"
+ },
+ "name": "DuplicateVersion1_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "CorrectVersion_V100_frag.frag"
+ },
+ "name": "CorrectVersion_V100_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "FunctionParam_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "FunctionParam_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ParseTest3_frag.frag"
+ },
+ "name": "ParseTest3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ParseTest4_frag.frag"
+ },
+ "name": "ParseTest4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array10_frag.frag"
+ },
+ "name": "array10_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_033_to_040.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_033_to_040.html
new file mode 100644
index 0000000000..52c70b73f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_033_to_040.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_033_to_040.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array11_frag.frag"
+ },
+ "name": "array11_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array1_frag.frag"
+ },
+ "name": "array1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array2_frag.frag"
+ },
+ "name": "array2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array3_frag.frag"
+ },
+ "name": "array3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array4_frag.frag"
+ },
+ "name": "array4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array5_frag.frag"
+ },
+ "name": "array5_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array6_frag.frag"
+ },
+ "name": "array6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array7_frag.frag"
+ },
+ "name": "array7_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_041_to_048.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_041_to_048.html
new file mode 100644
index 0000000000..c516edb190
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_041_to_048.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_041_to_048.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array8_frag.frag"
+ },
+ "name": "array8_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array9_frag.frag"
+ },
+ "name": "array9_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "attribute1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "attribute1_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "attribute2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "attribute2_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "attribute_frag.frag"
+ },
+ "name": "attribute_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "attribute_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "attribute_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "break_frag.frag"
+ },
+ "name": "break_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "comma1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "comma1_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_049_to_056.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_049_to_056.html
new file mode 100644
index 0000000000..db09be970e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_049_to_056.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_049_to_056.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "comma2_frag.frag"
+ },
+ "name": "comma2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "comma2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "comma2_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "comma3_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "comma3_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "comment_frag.frag"
+ },
+ "name": "comment_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "conditional1_frag.frag"
+ },
+ "name": "conditional1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "conditional2_frag.frag"
+ },
+ "name": "conditional2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "conditional3_frag.frag"
+ },
+ "name": "conditional3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "constFunc_frag.frag"
+ },
+ "name": "constFunc_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_057_to_064.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_057_to_064.html
new file mode 100644
index 0000000000..8ce48b7a17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_057_to_064.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_057_to_064.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "constructor1_frag.frag"
+ },
+ "name": "constructor1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "constructor2_frag.frag"
+ },
+ "name": "constructor2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "constructor3_V100_frag.frag"
+ },
+ "name": "constructor3_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "continue_frag.frag"
+ },
+ "name": "continue_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType10_frag.frag"
+ },
+ "name": "dataType10_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType11_frag.frag"
+ },
+ "name": "dataType11_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType12_frag.frag"
+ },
+ "name": "dataType12_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType13_frag.frag"
+ },
+ "name": "dataType13_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_065_to_072.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_065_to_072.html
new file mode 100644
index 0000000000..cf5b0217df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_065_to_072.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_065_to_072.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType19_frag.frag"
+ },
+ "name": "dataType19_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType1_frag.frag"
+ },
+ "name": "dataType1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType2_frag.frag"
+ },
+ "name": "dataType2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType3_frag.frag"
+ },
+ "name": "dataType3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType4_frag.frag"
+ },
+ "name": "dataType4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType5_frag.frag"
+ },
+ "name": "dataType5_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType6_frag.frag"
+ },
+ "name": "dataType6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType7_frag.frag"
+ },
+ "name": "dataType7_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_073_to_080.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_073_to_080.html
new file mode 100644
index 0000000000..a09643f167
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_073_to_080.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_073_to_080.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType8_frag.frag"
+ },
+ "name": "dataType8_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dataType9_frag.frag"
+ },
+ "name": "dataType9_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dowhile_frag.frag"
+ },
+ "name": "dowhile_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dvec2_frag.frag"
+ },
+ "name": "dvec2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dvec3_frag.frag"
+ },
+ "name": "dvec3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dvec4_frag.frag"
+ },
+ "name": "dvec4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension2_V100_frag.frag"
+ },
+ "name": "extension2_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension3_V100_frag.frag"
+ },
+ "name": "extension3_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_081_to_088.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_081_to_088.html
new file mode 100644
index 0000000000..3a06c23a38
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_081_to_088.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_081_to_088.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension5_V100_frag.frag"
+ },
+ "name": "extension5_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension6_V100_frag.frag"
+ },
+ "name": "extension6_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension7_V100_frag.frag"
+ },
+ "name": "extension7_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension8_V100_frag.frag"
+ },
+ "name": "extension8_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "extension9_V100_frag.frag"
+ },
+ "name": "extension9_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float2_frag.frag"
+ },
+ "name": "float2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float3_frag.frag"
+ },
+ "name": "float3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float4_frag.frag"
+ },
+ "name": "float4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_089_to_096.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_089_to_096.html
new file mode 100644
index 0000000000..992594a604
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_089_to_096.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_089_to_096.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "fragmentOnly1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "fragmentOnly1_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "fragmentOnly2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "fragmentOnly2_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "fragmentOnly3_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "fragmentOnly3_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "fragmentOnly4_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "fragmentOnly4_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "fragmentOnly_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "fragmentOnly_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function10_frag.frag"
+ },
+ "name": "function10_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function1_frag.frag"
+ },
+ "name": "function1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function2_V100_frag.frag"
+ },
+ "name": "function2_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_097_to_104.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_097_to_104.html
new file mode 100644
index 0000000000..27ce540c91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_097_to_104.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_097_to_104.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function3_frag.frag"
+ },
+ "name": "function3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function4_frag.frag"
+ },
+ "name": "function4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function6_frag.frag"
+ },
+ "name": "function6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function7_frag.frag"
+ },
+ "name": "function7_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function8_frag.frag"
+ },
+ "name": "function8_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "function9_frag.frag"
+ },
+ "name": "function9_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "hvec2_frag.frag"
+ },
+ "name": "hvec2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "hvec3_frag.frag"
+ },
+ "name": "hvec3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_105_to_112.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_105_to_112.html
new file mode 100644
index 0000000000..684fa98f86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_105_to_112.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_105_to_112.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "hvec4_frag.frag"
+ },
+ "name": "hvec4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "identifier1_frag.frag"
+ },
+ "name": "identifier1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "identifier2_frag.frag"
+ },
+ "name": "identifier2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "identifier3_frag.frag"
+ },
+ "name": "identifier3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "if1_frag.frag"
+ },
+ "name": "if1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "if2_frag.frag"
+ },
+ "name": "if2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "increment1_frag.frag"
+ },
+ "name": "increment1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "increment2_frag.frag"
+ },
+ "name": "increment2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_113_to_120.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_113_to_120.html
new file mode 100644
index 0000000000..5c18100083
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_113_to_120.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_113_to_120.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "increment3_frag.frag"
+ },
+ "name": "increment3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "increment4_frag.frag"
+ },
+ "name": "increment4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "increment6_frag.frag"
+ },
+ "name": "increment6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "main1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "main1_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "main2_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "main2_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "main3_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "main3_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "matrix_V100_frag.frag"
+ },
+ "name": "matrix_V100_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "normal_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "normal_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_121_to_128.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_121_to_128.html
new file mode 100644
index 0000000000..d645465e27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_121_to_128.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_121_to_128.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser10_frag.frag"
+ },
+ "name": "parser10_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "parser1_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "parser1_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser3_frag.frag"
+ },
+ "name": "parser3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser4_frag.frag"
+ },
+ "name": "parser4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser5_frag.frag"
+ },
+ "name": "parser5_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser6_frag.frag"
+ },
+ "name": "parser6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser7_frag.frag"
+ },
+ "name": "parser7_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser8_frag.frag"
+ },
+ "name": "parser8_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_129_to_136.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_129_to_136.html
new file mode 100644
index 0000000000..9abe40c351
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_129_to_136.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_129_to_136.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "parser9_frag.frag"
+ },
+ "name": "parser9_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess0_frag.frag"
+ },
+ "name": "preprocess0_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess10_frag.frag"
+ },
+ "name": "preprocess10_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess1_frag.frag"
+ },
+ "name": "preprocess1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess2_frag.frag"
+ },
+ "name": "preprocess2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess3_frag.frag"
+ },
+ "name": "preprocess3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess4_frag.frag"
+ },
+ "name": "preprocess4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess6_frag.frag"
+ },
+ "name": "preprocess6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_137_to_144.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_137_to_144.html
new file mode 100644
index 0000000000..48d233809f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_137_to_144.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_137_to_144.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "preprocess7_frag.frag"
+ },
+ "name": "preprocess7_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "scoping1_frag.frag"
+ },
+ "name": "scoping1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "scoping2_frag.frag"
+ },
+ "name": "scoping2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct10_frag.frag"
+ },
+ "name": "struct10_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct11_frag.frag"
+ },
+ "name": "struct11_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct1_frag.frag"
+ },
+ "name": "struct1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct2_frag.frag"
+ },
+ "name": "struct2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct3_frag.frag"
+ },
+ "name": "struct3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_145_to_152.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_145_to_152.html
new file mode 100644
index 0000000000..08920dd824
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_145_to_152.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_145_to_152.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct4_frag.frag"
+ },
+ "name": "struct4_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct5_frag.frag"
+ },
+ "name": "struct5_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct6_frag.frag"
+ },
+ "name": "struct6_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct7_frag.frag"
+ },
+ "name": "struct7_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct8_frag.frag"
+ },
+ "name": "struct8_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct9_frag.frag"
+ },
+ "name": "struct9_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "swizzle1_frag.frag"
+ },
+ "name": "swizzle1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "swizzle2_frag.frag"
+ },
+ "name": "swizzle2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_153_to_160.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_153_to_160.html
new file mode 100644
index 0000000000..eb950e3cfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_153_to_160.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_153_to_160.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "swizzle3_frag.frag"
+ },
+ "name": "swizzle3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "typecast_frag.frag"
+ },
+ "name": "typecast_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "uniform1_frag.frag"
+ },
+ "name": "uniform1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "uniform_frag.frag"
+ },
+ "name": "uniform_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "varying1_frag.frag"
+ },
+ "name": "varying1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "varying2_frag.frag"
+ },
+ "name": "varying2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "varying3_frag.frag"
+ },
+ "name": "varying3_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "varying_frag.frag"
+ },
+ "name": "varying_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_161_to_168.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_161_to_168.html
new file mode 100644
index 0000000000..9c66171bfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_161_to_168.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_161_to_168.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vector_frag.frag"
+ },
+ "name": "vector_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "version2_V100_frag.frag"
+ },
+ "name": "version2_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "version3_V100_frag.frag"
+ },
+ "name": "version3_V100_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vertexOnly2_frag.frag"
+ },
+ "name": "vertexOnly2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vertexOnly_frag.frag"
+ },
+ "name": "vertexOnly_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "vertex_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "vertex_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "while1_frag.frag"
+ },
+ "name": "while1_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "while2_frag.frag"
+ },
+ "name": "while2_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_169_to_176.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_169_to_176.html
new file mode 100644
index 0000000000..1bd3c63c47
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_169_to_176.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_169_to_176.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "while_frag.frag"
+ },
+ "name": "while_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "TernaryOp_frag.frag"
+ },
+ "name": "TernaryOp_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "CG_Data_Types_frag.frag"
+ },
+ "name": "CG_Data_Types_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "CG_Standard_Library_frag.frag"
+ },
+ "name": "CG_Standard_Library_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "Include_Preprocessor_Directive_frag.frag"
+ },
+ "name": "Include_Preprocessor_Directive_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "Low_Level_Assembly_Reserved_Words_frag.frag"
+ },
+ "name": "Low_Level_Assembly_Reserved_Words_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "Main_Parameters_vert.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "Main_Parameters_vert.test.html",
+ "linkstat": false,
+ "compstat": false
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "Permissive_Constant_Conversions_frag.frag"
+ },
+ "name": "Permissive_Constant_Conversions_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_177_to_178.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_177_to_178.html
new file mode 100644
index 0000000000..cdc2b38bcc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/build_177_to_178.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: build_177_to_178.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "Permissive_Scalar_Vector_Expressions_frag.frag"
+ },
+ "name": "Permissive_Scalar_Vector_Expressions_frag.test.html",
+ "linkstat": true,
+ "compstat": true
+ },
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "Texture_Rectangle_Samplers_frag.frag"
+ },
+ "name": "Texture_Rectangle_Samplers_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma1_vert.vert
new file mode 100644
index 0000000000..26473e46e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma1_vert.vert
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ int i, j, k;
+ float f;
+ i = j, k, f;
+ i = (j, k, f); // float cannot be assigned to int
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_frag.frag
new file mode 100644
index 0000000000..c7061f7ae7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const vec4 v = (vec4(1,2,3,4), vec4(5,6,7,8), 1.2); // right most value of comma operator shoul be a vec4
+ const vec4 v1 = (vec3(0.2, 2.0), vec4(1,2,3,4), vec4(5,6,7,8));
+ const vec4 v2 = (vec4(1,2,3,4), vec2(2.1, 2), vec4(5,6,7,8));
+ gl_FragColor = v + v1 + v2;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_vert.vert
new file mode 100644
index 0000000000..9c323689f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma2_vert.vert
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ int i, j, k;
+ float f;
+ i = j, k, f;
+ i = (j = k, f = 1.0); // float cannot be assigned to int
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma3_vert.vert
new file mode 100644
index 0000000000..9edcb98b21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comma3_vert.vert
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ int i, j, k;
+ float f;
+ i = j, k, f;
+ i = j = k, f = 1.0;
+ i = j, k = (3, f); // float cannot be assigned to int
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comment_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comment_frag.frag
new file mode 100644
index 0000000000..8d0a382874
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/comment_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ /****** // comment not closed
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional1_frag.frag
new file mode 100644
index 0000000000..eb830f4fcc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional1_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f1,f2;
+ int i;
+ float f3 = i ? f1 : f2; // expression must be boolean and not int
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional2_frag.frag
new file mode 100644
index 0000000000..451a8bd9eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional2_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f1,f2;
+ int i;
+ bool b;
+ float f3 = b ? i : f2; // second and third expression should of the type float
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional3_frag.frag
new file mode 100644
index 0000000000..65b1b46bbb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/conditional3_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f1,f2;
+ bool b;
+ int i = b ? f1 : f2; // second and third expression type does not match the lvalue type
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constFunc_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constFunc_frag.frag
new file mode 100644
index 0000000000..8e3a2a6524
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constFunc_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+vec2 func()
+{
+ vec2 v;
+ return v;
+}
+
+void main()
+{
+ const vec3 v = vec3(1.0, func()); // user defined functions do not return const value
+ gl_FragColor = vec4(v, v);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor1_frag.frag
new file mode 100644
index 0000000000..ff73bcdeae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor1_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec4 v = vec4(1,2,3); // insufficient data provided for constructor, 4 values are required
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor2_frag.frag
new file mode 100644
index 0000000000..127bdba564
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor2_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec3 v;
+ vec4 v1 = vec4(v); // insufficient data specified for construction
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor3_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor3_V100_frag.frag
new file mode 100644
index 0000000000..5312587710
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/constructor3_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec3 v;
+ vec4 v1 = vec4(v,v,v); // too many arguments in the constructor
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/continue_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/continue_frag.frag
new file mode 100644
index 0000000000..bdf83e2abe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/continue_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ continue; // continue keyword allowed only inside the loops
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType10_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType10_frag.frag
new file mode 100644
index 0000000000..4456d64178
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType10_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f;
+ float f; // redeclaration of a variable
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType11_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType11_frag.frag
new file mode 100644
index 0000000000..ffecbbf8f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType11_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i = 08; // invalid octal number
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType12_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType12_frag.frag
new file mode 100644
index 0000000000..4cf8b18af0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType12_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i = 0xa8g; // invalid hexadecimal number
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType13_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType13_frag.frag
new file mode 100644
index 0000000000..7a21e6f633
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType13_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i = 1;
+ float f = 1.2;
+ float result = f * i; // auto promotion now allowed
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType19_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType19_frag.frag
new file mode 100644
index 0000000000..fb98c75308
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType19_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D s;
+void main()
+{
+ int i = int(s); // conversion not allowed
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType1_frag.frag
new file mode 100644
index 0000000000..6f3baa2b19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType1_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ void v; // variable cannot be declared of the type void
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType2_frag.frag
new file mode 100644
index 0000000000..dec2aa0574
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType2_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D samp1;
+uniform sampler2D samp2 = samp1; // uniforms are read only
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType3_frag.frag
new file mode 100644
index 0000000000..726ba88814
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType3_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform int i = 1; // uniforms are read only
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType4_frag.frag
new file mode 100644
index 0000000000..8baea0a624
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType4_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i = 1.0; // automatic type conversion does not take place, float cannot be converted to int
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType5_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType5_frag.frag
new file mode 100644
index 0000000000..7e1ff75209
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType5_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f = 1; // int cannot be converted to float, use constructor to do the conversion explicitly
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType6_frag.frag
new file mode 100644
index 0000000000..e6ff4213e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType6_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const float f; // constants must be initialized
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType7_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType7_frag.frag
new file mode 100644
index 0000000000..be31a3cba1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType7_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float f;
+void main()
+{
+ f = 1.0; // uniforms are read only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType8_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType8_frag.frag
new file mode 100644
index 0000000000..dddecc4a17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType8_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying float f;
+void main()
+{
+ f = 1.0; // varyings cannot be written to in a fragment shader, they can be written to in a vertex shader
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType9_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType9_frag.frag
new file mode 100644
index 0000000000..1029d3d445
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dataType9_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying float f;
+void main()
+{
+ float flt = 1.0;
+ flt++;
+ f++; // varyings in a fragment shader are read only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.frag
new file mode 100644
index 0000000000..af7b0e05a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main (void)
+{
+ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.vert
new file mode 100644
index 0000000000..8c736abd5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/default.vert
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+void main (void)
+{
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dowhile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dowhile_frag.frag
new file mode 100644
index 0000000000..4143dc4c36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dowhile_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f;
+ do {
+ } while(f); // condition should be boolean
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec2_frag.frag
new file mode 100644
index 0000000000..9451b55d6f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec2_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ dvec2 d; // dvec2 is not a valid datatype, reserved for future use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec3_frag.frag
new file mode 100644
index 0000000000..b7f7817168
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec3_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ dvec3 d; // dvec3 is not a valid datatype, reserved for future use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec4_frag.frag
new file mode 100644
index 0000000000..56beb6a5a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/dvec4_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ dvec4 d; // dvec4 is not a valid datatype, reserved for future use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension2_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension2_V100_frag.frag
new file mode 100644
index 0000000000..085a7e3535
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension2_V100_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension all : require // cannot use require or enable with all
+#extension all : enable // cannot use require or enable with all
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension3_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension3_V100_frag.frag
new file mode 100644
index 0000000000..0005c14edf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension3_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension foo : require // error extension not supported
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension5_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension5_V100_frag.frag
new file mode 100644
index 0000000000..6198d6ffe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension5_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension all : ddisablee // error, behavior is not supported
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension6_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension6_V100_frag.frag
new file mode 100644
index 0000000000..6a33fa4feb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension6_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension // error name and behavior not specified
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension7_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension7_V100_frag.frag
new file mode 100644
index 0000000000..0e636d5125
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension7_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension foo // ":" missing after extension name
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension8_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension8_V100_frag.frag
new file mode 100644
index 0000000000..7c12432568
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension8_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension foo : // behavior not specified
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension9_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension9_V100_frag.frag
new file mode 100644
index 0000000000..dd7d69dcaf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/extension9_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+#extension foo behavior // ":" missing after extension name
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float2_frag.frag
new file mode 100644
index 0000000000..23a31ca990
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float2_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float2 f; // float2 is not a valid datatype
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float3_frag.frag
new file mode 100644
index 0000000000..a73d3d4454
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float3_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float3 f; // float3 is not a valid datatype
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float4_frag.frag
new file mode 100644
index 0000000000..d381373ad8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/float4_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float4 f; // float4 is not a valid datatype
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly1_vert.vert
new file mode 100644
index 0000000000..5ebba33d94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly1_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ gl_FrontFacing = true; // can be used in fragment shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly2_vert.vert
new file mode 100644
index 0000000000..480056b079
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly2_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ gl_FragCoord = vec4(1.0); // can be used in fragment shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly3_vert.vert
new file mode 100644
index 0000000000..8e9cb00815
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly3_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ gl_FragColor = vec4(1.0); // can be used in fragment shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly4_vert.vert
new file mode 100644
index 0000000000..4f6448369f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly4_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ discard; // can be used in fragment shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly_vert.vert
new file mode 100644
index 0000000000..28ea00ef4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/fragmentOnly_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ gl_FragDepth = 1.0; // can be used in fragment shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function10_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function10_frag.frag
new file mode 100644
index 0000000000..17dfadbfd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function10_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(in int i);
+
+void main()
+{
+ float f;
+ // overloaded function not present
+ function(f);
+}
+
+void function(in int i)
+{
+ i = 3;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function1_frag.frag
new file mode 100644
index 0000000000..a3327a6adb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function1_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(int i)
+{
+ return i; // void function cannot return a value
+}
+
+void main()
+{
+ int i;
+ function(i);
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function2_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function2_V100_frag.frag
new file mode 100644
index 0000000000..5b9d57dc51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function2_V100_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(int i[]) // size of array must be specified
+{
+}
+
+void main()
+{
+ int i[2];
+ function(i);
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function3_frag.frag
new file mode 100644
index 0000000000..44835de7fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function3_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(const int i)
+{
+ i = 3; // const value cant be modified
+}
+
+void main()
+{
+ int i;
+ function(i);
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function4_frag.frag
new file mode 100644
index 0000000000..eeabde9b7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function4_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform int uniformInt;
+
+void function(out int i)
+{
+ i = 1;
+}
+
+void main()
+{
+ function(uniformInt); // out and inout parameters cannot be uniform since uniforms cannot be modified
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function6_frag.frag
new file mode 100644
index 0000000000..cbcc433eb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function6_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(const out int i)
+{ // out parameters cannot be const
+ i = 3;
+}
+
+void main()
+{
+ int i;
+ function(i);
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function7_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function7_frag.frag
new file mode 100644
index 0000000000..4c0902881c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function7_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(uniform int i)
+{ // uniform qualifier cannot be used with function parameters
+}
+
+void main()
+{
+ int i;
+ function(i);
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function8_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function8_frag.frag
new file mode 100644
index 0000000000..debe6e8058
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function8_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(const inout int i)
+{ // inout parameters cannot be const
+ i = 3;
+}
+
+void main()
+{
+ int i;
+ function(i);
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function9_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function9_frag.frag
new file mode 100644
index 0000000000..96af74bf97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/function9_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void function(inout int i);
+
+void main()
+{
+ int i;
+ function(i);
+}
+
+// function definition has different parameter qualifiers than function declaration
+void function(in int i)
+{
+ i = 3;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec2_frag.frag
new file mode 100644
index 0000000000..8911b69e64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec2_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ hvec2 f; // hvec2 is not a valid datatype, reserved for future use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec3_frag.frag
new file mode 100644
index 0000000000..a3b61df2e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec3_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ hvec3 f; // hvec3 is not a valid datatype, reserved for future use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec4_frag.frag
new file mode 100644
index 0000000000..94e7970fa8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/hvec4_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ hvec4 f; // hvec4 is not a valid datatype, reserved for future use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier1_frag.frag
new file mode 100644
index 0000000000..70d1d9c80e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier1_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int 1i; // incorrect identifier name
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier2_frag.frag
new file mode 100644
index 0000000000..316e934519
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier2_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int gl_int; // identifier name cannot begin with "gl_"
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier3_frag.frag
new file mode 100644
index 0000000000..9bbeaf6520
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/identifier3_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i;
+ x; // identifier x used without being declared
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if1_frag.frag
new file mode 100644
index 0000000000..0301684831
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if1_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i;
+ if (i) // condition of if statement must be a boolean
+ i++;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if2_frag.frag
new file mode 100644
index 0000000000..04fbfdfc23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/if2_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v;
+ int i;
+ if (v) // vectors cannot be used as conditional expression for if statement
+ i++;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment1_frag.frag
new file mode 100644
index 0000000000..4eeb5b60bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment1_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ int i;
+} s1;
+
+void main()
+{
+ s1.i++;
+ s1++; // structure cannot be incremented
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment2_frag.frag
new file mode 100644
index 0000000000..561678b0ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment2_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i;
+ (i+i)++; // i+i is not an l-value
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment3_frag.frag
new file mode 100644
index 0000000000..0a32504734
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment3_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D sampler2d;
+
+void main()
+{
+ sampler2d++; // uniforms cannot be modified
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment4_frag.frag
new file mode 100644
index 0000000000..23ff6b43e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment4_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i;
+ i++ = 5; // i++ is not an l-value
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment6_frag.frag
new file mode 100644
index 0000000000..0bc50043ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/increment6_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i;
+ ++i++; // ++i++ is equivalent to ++(i++) which fails because i++ is not an lvalue. (++i)++; is legal.
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/input.run.txt
new file mode 100644
index 0000000000..78dde7d629
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/input.run.txt
@@ -0,0 +1,24 @@
+# this file is auto-generated. DO NOT EDIT.
+build_001_to_008.html
+build_009_to_016.html
+build_017_to_024.html
+build_025_to_032.html
+build_033_to_040.html
+build_041_to_048.html
+build_049_to_056.html
+build_057_to_064.html
+build_065_to_072.html
+build_073_to_080.html
+build_081_to_088.html
+build_089_to_096.html
+build_097_to_104.html
+build_105_to_112.html
+build_113_to_120.html
+build_121_to_128.html
+build_129_to_136.html
+build_137_to_144.html
+build_145_to_152.html
+build_153_to_160.html
+build_161_to_168.html
+build_169_to_176.html
+build_177_to_178.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main1_vert.vert
new file mode 100644
index 0000000000..95c266310a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main1_vert.vert
@@ -0,0 +1,11 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+main() // return type of main should be void
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main2_vert.vert
new file mode 100644
index 0000000000..8cdfe98b46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main2_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main(int i) // main function cannot take any parameters
+{
+ gl_Position = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main3_vert.vert
new file mode 100644
index 0000000000..09a21a9e92
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/main3_vert.vert
@@ -0,0 +1,12 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+int main() // return type of main should be void
+{
+ return 1;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/matrix_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/matrix_V100_frag.frag
new file mode 100644
index 0000000000..f3dc0adb64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/matrix_V100_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ mat3 m;
+ mat4 m1 = mat4(m);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/normal_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/normal_vert.vert
new file mode 100644
index 0000000000..369bce99f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/normal_vert.vert
@@ -0,0 +1,13 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Normal;
+void main()
+{
+ gtf_Normal = vec3(1.0,2.0,3.0); // cannot be modified an attribute
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser10_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser10_frag.frag
new file mode 100644
index 0000000000..6c25734473
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser10_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ 5 += 5; // l-value missing
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser1_vert.vert
new file mode 100644
index 0000000000..90a6263dd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser1_vert.vert
@@ -0,0 +1,13 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+void main()
+{
+ int a // semicolon missing at the end of the statement
+ gl_Position = vec4(a);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser3_frag.frag
new file mode 100644
index 0000000000..7b543ad8fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser3_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f[3];
+ f[3] = 1.0; // index of array greater than the size of the array
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser4_frag.frag
new file mode 100644
index 0000000000..c73e4b3d31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser4_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ const int i = 5;
+ i++; // const cannot be modified
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser5_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser5_frag.frag
new file mode 100644
index 0000000000..ee9cbdaac5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser5_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v;
+ v.z = 1.2; // vec2 does not have a z component
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser6_frag.frag
new file mode 100644
index 0000000000..2d4d021fd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser6_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f1,f2,f3;
+ f3 = f1 > f2; // f1 > f2 result in a bool that cannot be assigned to a float
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser7_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser7_frag.frag
new file mode 100644
index 0000000000..49032310cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser7_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ mat2 m1,m2;
+ bool b = m1 > m2; // greater-than operator can not operate on matrices, however, equal (==) and not equal (!=) operators can be used with matrices
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser8_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser8_frag.frag
new file mode 100644
index 0000000000..76649c54ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser8_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v2;
+ vec3 v3;
+ bool b = v2 == v3; // equal operator cannot operator on vectors of different sizes
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser9_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser9_frag.frag
new file mode 100644
index 0000000000..1283c2268d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/parser9_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f1,f2;
+ bool b = f1 && f2; // &&, || and ^^ operate on a boolean expression only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess0_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess0_frag.frag
new file mode 100644
index 0000000000..e9d1d9fcd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess0_frag.frag
@@ -0,0 +1,63 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//test for else elif mismatch
+#define test(x,y) (x+y)
+
+void main(void){
+ int sum =0;
+ #define x 8
+ #endif
+ #if (x==8)
+ #undef x
+ #endif
+
+ #if 1
+ #undef x
+ #endif
+
+ #if 1
+ #define t4 4
+ #endif
+
+ sum=test(3,6)+t4;
+ #if 1
+ #if 1
+ #if 1
+ #if 1
+ #if 0
+ #undef test
+ #else
+ #if 1
+ #undef test
+ #endif
+ #if 0
+ #undef test
+ #else
+ #if 0
+ #undef test
+ #else
+ #if 1
+ #undef test
+ #else
+ #undef test
+ #else
+ #jdhgj
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess10_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess10_frag.frag
new file mode 100644
index 0000000000..feb227970d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess10_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+/* The program should terminate with an error message and not get into an
+ infinite loop */
+#ifdef name
+
+void main()
+{
+ gl_FragColor = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess1_frag.frag
new file mode 100644
index 0000000000..72f4d14258
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess1_frag.frag
@@ -0,0 +1,64 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// tests for macro redifinition (t2) and the #if and #else nestings.
+// takes care of elif also.
+
+#define t1 (1+2)
+#define t2 2
+#define t2 3
+
+// testing the if depth
+#if (t1==3)
+ #define t3 3
+ #if defined t2
+ #define t4 4
+ #if defined(t3)
+ #define t5 5
+ #ifdef t5
+ #define t6 6
+ #ifndef t7
+ #define t7 7
+ #else
+ #define t8 8
+ #endif
+ #endif
+ #else
+ #ifndef t8
+ #define t8 8
+ #elif (t8==8)
+ #define t9 9
+ #else
+ #if defined t7
+ #define t9 9
+ #endif
+ #endif
+ #endif
+ #else
+ #define t10 10
+ #endif
+#endif
+
+
+#define t8 8
+#define t9 9
+#define t10 10
+
+void main(void)
+{
+ int sum=1 ;
+ sum = t1+t2;
+ sum = t3+t4;
+ sum = t5+t6;
+ sum = t7+t8;
+ sum = t9+t10;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess2_frag.frag
new file mode 100644
index 0000000000..9aa00e849d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess2_frag.frag
@@ -0,0 +1,60 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// #line directive-- test cases.
+// chks for Invalid directives, all possible #line errors
+// Also checks the correct verions of #line dorective.
+
+#define t1 1
+#define t2 2
+
+#
+#
+#
+#
+#line 8
+#line ""
+#line 3 3
+
+#linekfj
+#line c c
+#line t1 t2
+#line 77 89
+#line 65.4
+#line message to the user
+#line
+#line345
+
+void main(void)
+{
+ int sum =1;
+ sum = __LINE__;
+ sum = __FILE__;
+ #line 4 5
+ sum = __LINE__;
+ sum = __FILE__;
+ #line 9
+ sum = __LINE__ + __FILE__ ;
+ sum = __FILE__;
+ #
+ #
+ sum = __VERSION__;
+ sum = sum + __LINE__ ;
+ #line 4 5
+ #line 5 8
+ sum = __LINE__;
+ sum = __FILE__;
+ sum = __VERSION__;
+
+}
+
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess3_frag.frag
new file mode 100644
index 0000000000..c9e2006a97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess3_frag.frag
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// simple macro expansions.
+// Tests for Too few macro arguments, too many macro arguments.
+// Macros with no arguments.
+
+#define t1 -1
+#define t2 2
+
+#define test -258
+#define test1 (test*test)
+#define test2(x) (x+test1)
+#define test3() (test2(8)*(test*test1))
+#define test4(x,y) (x+y)
+
+void main(void)
+{
+ int sum =0;
+ sum = test3();
+ sum = test3(3);
+
+ sum = test2(9);
+ sum = test2(9,8);
+
+ sum = test4;
+ sum = test2(8,5,78,9);
+ sum = sum + test1;
+ sum = 8+58+sum;
+ sum = sum +test;
+ sum = (t1+t2);
+ sum = test4(test3(),test2(test3()));
+ sum = test4(3,8,5);
+ sum = test4();
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess4_frag.frag
new file mode 100644
index 0000000000..5d9c756a63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess4_frag.frag
@@ -0,0 +1,60 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// #error and #pragma directives -- test cases.
+// tests for errors in #pragma directive.
+
+#pragma optimize(on)
+#pragma debug(off)
+
+int foo(int);
+
+void main(void)
+{
+ int sum =0;
+ #error ;
+ #error 78
+ #error c
+ #error "message to the user "
+ #error message to the user
+ #error
+ #error
+ #define t1 1
+ sum = t1*t1;
+ foo(sum);
+
+}
+
+#pragma optimize(off)
+#pragma bind(on)
+#pragma pack(off)
+
+int foo(int test)
+{
+ int binding=0;
+ binding = test;
+ return binding;
+}
+
+#line 4
+#pragma
+#line 5 6
+#pragma optmimize on
+#pragma debug off
+#pragma debug(off
+#line 9
+#prgma bind(off)
+#pragma bind
+#pragma (on)
+#pragma on (on)
+#pragma optmize(on
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess6_frag.frag
new file mode 100644
index 0000000000..836bd0223f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess6_frag.frag
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// operator precedence and some macro expansions.
+
+#define test (1+2)
+#define test1 (test*4)
+#define test2 (test1/test)
+//#define test3 (-1+2*3/4%test)
+#define test3 (-1+2*3/4)
+//#define test4 (test & test1 |test2)
+#define test4 (test)
+#define test5 (!8+~4+4-6)
+#define test6 (test1>>1)
+#define test7 (test1<<1)
+#define test8 (test2^6)
+#define test9 (test4 || test5 && test1)
+#define test10 (0)
+
+void main(void)
+{
+ int sum =0;
+ sum = test4;
+ sum = test3*test2+test1-test;
+// sum = test3/test6 + test4*test7 - test7 % test9;
+// sum = test3/test6 + test4*test7 - test7;
+ sum = test10*test5;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess7_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess7_frag.frag
new file mode 100644
index 0000000000..08f62b1110
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/preprocess7_frag.frag
@@ -0,0 +1,51 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// testing for char constants in #if and #elif
+// Also checking whether reserved words can be redefined.
+
+#define t1 c
+#define t2 d
+#define asm a
+
+ #if(t1==c)
+ #define t3 3
+ #elif(t1==d)
+ #define t4 4
+ #elif(t2==c)
+ #define t5 5
+ #endif
+
+ #ifndef t1
+ #define t7 7
+ #elif (t2==d)
+ #define t6 6
+ #endif
+
+ #if (t2=='d')
+ #define half 5
+ #else
+ #define half 8
+ #endif
+
+ #ifdef t22
+ #define x 5
+ #endif
+
+ void main(void)
+ {
+ int sum =0,a=9;
+
+ sum = half + sum;
+ sum = asm + a;
+
+ }
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping1_frag.frag
new file mode 100644
index 0000000000..89c9a51209
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping1_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ bool b;
+ if (b)
+ {
+ int i = 1;
+ i++;
+ }
+ i++; // i is not declared in this scope
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping2_frag.frag
new file mode 100644
index 0000000000..8667f40061
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/scoping2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ {
+ int i = 1;
+ i++;
+ }
+ i++; // i is not declared in this scope
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct10_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct10_frag.frag
new file mode 100644
index 0000000000..fb0c78299d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct10_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ int i;
+} s1[2];
+
+void main()
+{
+ s1.i = 1; // s1 is an array. s1[0].i is correct to use
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct11_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct11_frag.frag
new file mode 100644
index 0000000000..152ce49aed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct11_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ int i;
+} s1;
+
+void main()
+{
+ s1 = -s1; // cannot calculate negative of a structure
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct1_frag.frag
new file mode 100644
index 0000000000..0fcbb8599f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct1_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ int i;
+} uniform uniformStruct; // uniform keyword should be used before the keyword struct
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct2_frag.frag
new file mode 100644
index 0000000000..5682f67dfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct2_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ int i = 1.0; // struct members cannot be initialized at the time of structure declaration
+} s1;
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct3_frag.frag
new file mode 100644
index 0000000000..2ec1e53616
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct3_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ uniform int i; // structure members cannot be declared with const qualifier
+} s1;
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct4_frag.frag
new file mode 100644
index 0000000000..ae7d547ae1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct4_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ const int i = 1; // structure members cannot be declared with const qualifier
+} s1;
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct5_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct5_frag.frag
new file mode 100644
index 0000000000..fd62320761
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct5_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform struct s {
+ int i;
+} s1;
+
+void main()
+{
+ s1.i = 1; // uniforms are read only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct6_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct6_frag.frag
new file mode 100644
index 0000000000..dd98cc01c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct6_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying struct s {
+ int i;
+} s1; // structures cannot be declared with varying qualifier
+
+void main()
+{
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct7_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct7_frag.frag
new file mode 100644
index 0000000000..01a3206505
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct7_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ struct s {
+ } s1; // structures have to be declared with atleast one member
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct8_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct8_frag.frag
new file mode 100644
index 0000000000..c900bc90c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct8_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct s {
+ int i;
+} s1;
+
+struct ss {
+ int i;
+} s2;
+
+void main()
+{
+ s1 = s2; // two different structures cannot be assigned to each other
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct9_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct9_frag.frag
new file mode 100644
index 0000000000..c661d25012
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/struct9_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+const struct s {
+ int i;
+} s1 = s(1);
+
+void main()
+{
+ s1.i = 1; // const struct members cannot be modified
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle1_frag.frag
new file mode 100644
index 0000000000..b11ea3cf91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle1_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v;
+ v.xy = 1.2; // swizzle needs two values, v.xy = vec2(1.2) is correct
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle2_frag.frag
new file mode 100644
index 0000000000..705bd18776
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle2_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v;
+ v.xx = vec2(1,1); // x cannot be used twice in l-value
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle3_frag.frag
new file mode 100644
index 0000000000..b5b9fd6048
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/swizzle3_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec2 v;
+ vec3 v3 = v.xyz; // v is a vec2 and does not have a z component
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/typecast_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/typecast_frag.frag
new file mode 100644
index 0000000000..fa1b124f66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/typecast_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ vec4 v;
+ vec4 v1 = (vec4) v; // incorrect typecasting, vec4(v) is correct
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform1_frag.frag
new file mode 100644
index 0000000000..1270647faa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform1_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct gtf_FogParameters {
+vec4 color;
+float density;
+float start;
+float end;
+float scale;
+};
+uniform gtf_FogParameters gtf_Fog;
+void main()
+{
+ gtf_Fog.density = 1.0; // cannot modify a uniform
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform_frag.frag
new file mode 100644
index 0000000000..195eaced46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/uniform_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ uniform float foo; // uniforms can only be declared at a global scope
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying1_frag.frag
new file mode 100644
index 0000000000..9f5122ea98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying1_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying float foo;
+
+void main()
+{
+ foo = 5.0; // varying cannot be written by a fragment shader
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying2_frag.frag
new file mode 100644
index 0000000000..74cc9f49f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying2_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying int foo; // varyings cannot be int or bool
+
+void main()
+{
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying3_frag.frag
new file mode 100644
index 0000000000..62ab65ec99
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying3_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 v = vec4(1,1,1,1);//gl_TexCoord[0]; // varyings cannot be initialized
+
+void main()
+{
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying_frag.frag
new file mode 100644
index 0000000000..f85d9fdb7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/varying_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ varying float foo; // varyings can only be declared at a global scope
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vector_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vector_frag.frag
new file mode 100644
index 0000000000..62c298eb1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vector_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ ivec4 v4;
+ v4 = v4 + 2.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version2_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version2_V100_frag.frag
new file mode 100644
index 0000000000..b83fc6a467
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version2_V100_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#pragma debug(on)
+#version 100 // error #version should be the first statement in the program
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+
+void main()
+{
+ gl_FragColor = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version3_V100_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version3_V100_frag.frag
new file mode 100644
index 0000000000..21dfcc33ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/version3_V100_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+/* This is a comment*/ int i; // This is a global decl
+#version 100 // error #version should be the first statement in the program
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+
+void main()
+{
+ gl_FragColor = vec4(1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly2_frag.frag
new file mode 100644
index 0000000000..1c85e221ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly2_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ gl_Position = vec4(4.0); // can be used in vertex shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly_frag.frag
new file mode 100644
index 0000000000..41ada2bf08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertexOnly_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct gtf_PointParameters {
+float size;
+float sizeMin;
+float sizeMax;
+float fadeThresholdSize;
+float distanceConstantAttenuation;
+float distanceLinearAttenuation;
+float distanceQuadraticAttenuation;
+};
+uniform gtf_FogParameters gtf_Point;
+void main()
+{
+ gtf_PointSize = 4.0; // can be used in vertex shader only
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertex_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertex_vert.vert
new file mode 100644
index 0000000000..ab8cc4555e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/vertex_vert.vert
@@ -0,0 +1,13 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+void main()
+{
+ gtf_Vertex = vec4(1.0,2.0,3.0, 4.0); // cannot modify an attribute
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while1_frag.frag
new file mode 100644
index 0000000000..89e2c6bbb2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while1_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ int i;
+ while(i) { // condition should be boolean
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while2_frag.frag
new file mode 100644
index 0000000000..31e75cfa90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while2_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ while(float f = 5.0) { // cannot declare variables in condition
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while_frag.frag
new file mode 100644
index 0000000000..891d0992b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/build/while_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main()
+{
+ float f;
+ while(f) { // condition should be boolean
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/built_in_varying_array_out_of_bounds_001_to_001.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/built_in_varying_array_out_of_bounds_001_to_001.html
new file mode 100644
index 0000000000..2477c00ddd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/built_in_varying_array_out_of_bounds_001_to_001.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: built_in_varying_array_out_of_bounds_001_to_001.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "pattern": "build",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_Color_array_index_out_of_bounds_frag.frag"
+ },
+ "name": "gl_Color_array_index_out_of_bounds_frag.test.html",
+ "linkstat": false,
+ "compstat": false
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/gl_Color_array_index_out_of_bounds_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/gl_Color_array_index_out_of_bounds_frag.frag
new file mode 100644
index 0000000000..311ac4b559
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/gl_Color_array_index_out_of_bounds_frag.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main(void)
+{
+ gl_FragColor = vec4(color[1], color[2], color[3], color[4]);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/input.run.txt
new file mode 100644
index 0000000000..be6485a1f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/built_in_varying_array_out_of_bounds/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+built_in_varying_array_out_of_bounds_001_to_001.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_001_to_006.html
new file mode 100644
index 0000000000..8b63e0789b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: ceil_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ceil_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ceil_float_frag_xvary.frag"
+ },
+ "name": "ceil_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ceil_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ceil_vec2_frag_xvary.frag"
+ },
+ "name": "ceil_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ceil_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ceil_vec3_frag_xvary.frag"
+ },
+ "name": "ceil_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "ceil_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "ceil_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ceil_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "ceil_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "ceil_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ceil_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "ceil_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "ceil_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ceil_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary.frag
new file mode 100644
index 0000000000..c58b7464d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4((ceil(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..234b80aa4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_frag_xvary_ref.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float ceil_ref(float x)
+{
+ if(x != floor(x)) x = floor(x) + 1.0;
+ return x;
+}
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4((ceil_ref(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary.vert
new file mode 100644
index 0000000000..cdcb87cdd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4((ceil(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..b6926d6a4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_float_vert_xvary_ref.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+float ceil_ref(float x)
+{
+ if(x != floor(x)) x = floor(x) + 1.0;
+ return x;
+}
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4((ceil_ref(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..1746348114
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4((ceil(c) + 10.0) / 20.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..d037971dbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_frag_xvary_ref.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+vec2 ceil_ref(vec2 x)
+{
+ if(x[0] != floor(x[0])) x[0] = floor(x[0]) + 1.0;
+ if(x[1] != floor(x[1])) x[1] = floor(x[1]) + 1.0;
+ return x;
+}
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4((ceil_ref(c) + 10.0) / 20.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..8c5a773779
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4((ceil(c) + 10.0) / 20.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..c79d18a6a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec2_vert_xvary_ref.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+vec2 ceil_ref(vec2 x)
+{
+ if(x[0] != floor(x[0])) x[0] = floor(x[0]) + 1.0;
+ if(x[1] != floor(x[1])) x[1] = floor(x[1]) + 1.0;
+ return x;
+}
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4((ceil_ref(c) + 10.0) / 20.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..c7597619d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4((ceil(c) + 10.0) / 20.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..638c735a73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_frag_xvary_ref.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+vec3 ceil_ref(vec3 x)
+{
+ if(x[0] != floor(x[0])) x[0] = floor(x[0]) + 1.0;
+ if(x[1] != floor(x[1])) x[1] = floor(x[1]) + 1.0;
+ if(x[2] != floor(x[2])) x[2] = floor(x[2]) + 1.0;
+ return x;
+}
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4((ceil_ref(c) + 10.0) / 20.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..0304b41782
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4((ceil(c) + 10.0) / 20.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..c8a8fcd859
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/ceil_vec3_vert_xvary_ref.vert
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+vec3 ceil_ref(vec3 x)
+{
+ if(x[0] != floor(x[0])) x[0] = floor(x[0]) + 1.0;
+ if(x[1] != floor(x[1])) x[1] = floor(x[1]) + 1.0;
+ if(x[2] != floor(x[2])) x[2] = floor(x[2]) + 1.0;
+ return x;
+}
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4((ceil_ref(c) + 10.0) / 20.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/input.run.txt
new file mode 100644
index 0000000000..ed1a87ffad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/ceil/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+ceil_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_001_to_006.html
new file mode 100644
index 0000000000..3a7a027c09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: clamp_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "clamp_float_frag_xvary_yconstquarter_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "clamp_float_frag_xvary_yconstquarter.frag"
+ },
+ "name": "clamp_float_frag_xvary_yconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "clamp_vec2_frag_xvary_yconstquarter_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "clamp_vec2_frag_xvary_yconstquarter.frag"
+ },
+ "name": "clamp_vec2_frag_xvary_yconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "clamp_vec3_frag_xvary_yconstquarter_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "clamp_vec3_frag_xvary_yconstquarter.frag"
+ },
+ "name": "clamp_vec3_frag_xvary_yconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "clamp_float_vert_xvary_yconstquarter_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "clamp_float_vert_xvary_yconstquarter.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "clamp_float_vert_xvary_yconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "clamp_vec2_vert_xvary_yconstquarter_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "clamp_vec2_vert_xvary_yconstquarter.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "clamp_vec2_vert_xvary_yconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "clamp_vec3_vert_xvary_yconstquarter_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "clamp_vec3_vert_xvary_yconstquarter.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "clamp_vec3_vert_xvary_yconstquarter.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter.frag
new file mode 100644
index 0000000000..97c16a5ace
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ float c = color.r;
+ gl_FragColor = vec4(clamp(c, min_c, max_c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter_ref.frag
new file mode 100644
index 0000000000..beba604303
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_frag_xvary_yconstquarter_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ float c = color.r;
+ if(c > max_c) c = max_c;
+ if(c < min_c) c = min_c;
+
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter.vert
new file mode 100644
index 0000000000..37b17f8f45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ float c = gtf_Color.r;
+ color = vec4(clamp(c, min_c, max_c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter_ref.vert
new file mode 100644
index 0000000000..5ba7a86b1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_float_vert_xvary_yconstquarter_ref.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ float c = gtf_Color.r;
+ if(c > max_c) c = max_c;
+ if(c < min_c) c = min_c;
+
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter.frag
new file mode 100644
index 0000000000..78c4fa92b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 min_c = vec2(0.25, 0.25);
+ const vec2 max_c = vec2(0.75, 0.75);
+ vec2 c = color.rg;
+ gl_FragColor = vec4(clamp(c, min_c, max_c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter_ref.frag
new file mode 100644
index 0000000000..2e445dfbcb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_frag_xvary_yconstquarter_ref.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 min_c = vec2(0.25, 0.25);
+ const vec2 max_c = vec2(0.75, 0.75);
+ vec2 c = color.rg;
+ if(c[0] < min_c[0]) c[0] = min_c[0];
+ if(c[1] < min_c[1]) c[1] = min_c[1];
+ if(c[0] > max_c[0]) c[0] = max_c[0];
+ if(c[1] > max_c[1]) c[1] = max_c[1];
+
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter.vert
new file mode 100644
index 0000000000..a4e2719168
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ vec2 c = gtf_Color.rg;
+ color = vec4(clamp(c, min_c, max_c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter_ref.vert
new file mode 100644
index 0000000000..e98e400d49
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec2_vert_xvary_yconstquarter_ref.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ vec2 c = gtf_Color.rg;
+ if(c[0] > max_c) c[0] = max_c;
+ if(c[0] < min_c) c[0] = min_c;
+ if(c[1] > max_c) c[1] = max_c;
+ if(c[1] < min_c) c[1] = min_c;
+
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter.frag
new file mode 100644
index 0000000000..9b67fee7cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 min_c = vec3(0.25, 0.25, 0.25);
+ const vec3 max_c = vec3(0.75, 0.75, 0.75);
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(clamp(c, min_c, max_c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter_ref.frag
new file mode 100644
index 0000000000..88341fc06a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_frag_xvary_yconstquarter_ref.frag
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 min_c = vec3(0.25, 0.25, 0.25);
+ const vec3 max_c = vec3(0.75, 0.75, 0.75);
+ vec3 c = color.rgb;
+ if(c[0] < min_c[0]) c[0] = min_c[0];
+ if(c[1] < min_c[1]) c[1] = min_c[1];
+ if(c[2] < min_c[2]) c[2] = min_c[2];
+ if(c[0] > max_c[0]) c[0] = max_c[0];
+ if(c[1] > max_c[1]) c[1] = max_c[1];
+ if(c[2] > max_c[2]) c[2] = max_c[2];
+
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter.vert
new file mode 100644
index 0000000000..d9052ed643
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ vec3 c = gtf_Color.rgb;
+ color = vec4(clamp(c, min_c, max_c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter_ref.vert
new file mode 100644
index 0000000000..735597e449
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/clamp_vec3_vert_xvary_yconstquarter_ref.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.25;
+ const float max_c = 0.75;
+ vec3 c = gtf_Color.rgb;
+ if(c[0] > max_c) c[0] = max_c;
+ if(c[0] < min_c) c[0] = min_c;
+ if(c[1] > max_c) c[1] = max_c;
+ if(c[1] < min_c) c[1] = min_c;
+ if(c[2] > max_c) c[2] = max_c;
+ if(c[2] < min_c) c[2] = min_c;
+
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/input.run.txt
new file mode 100644
index 0000000000..2fafa275a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/clamp/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+clamp_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_001_to_008.html
new file mode 100644
index 0000000000..c2ce553938
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: control_flow_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "for_break_frag.frag"
+ },
+ "name": "for_break_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "for_break_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "for_break_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "for_continue_frag.frag"
+ },
+ "name": "for_continue_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "for_continue_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "for_continue_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "for_nested_break_frag.frag"
+ },
+ "name": "for_nested_break_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "for_nested_break_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "for_nested_break_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "for_nested_continue_frag.frag"
+ },
+ "name": "for_nested_continue_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "for_nested_continue_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "for_nested_continue_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_009_to_010.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_009_to_010.html
new file mode 100644
index 0000000000..8c15bf9c4d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/control_flow_009_to_010.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: control_flow_009_to_010.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "nested_if_else_frag.frag"
+ },
+ "name": "nested_if_else_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "nested_if_else_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "nested_if_else_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_frag.frag
new file mode 100644
index 0000000000..1efed30ea7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_frag.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int count = 0;
+ for(int i=0;i<5;i++)
+ {
+ count++;
+ if(count == 3)
+ break;
+ }
+
+ float gray;
+ if( count == 3)
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_vert.vert
new file mode 100644
index 0000000000..b25c3bf323
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_break_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int count = 0;
+ for(int i=0;i<45;i++)
+ {
+ count++;
+ if(count == 29)
+ break;
+ }
+ float gray;
+ if( count == 29)
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_frag.frag
new file mode 100644
index 0000000000..ba9d84df33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_frag.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int count=0;
+ int val=0;
+
+ for(int i=0;i<10;i++)
+ {
+ count++;
+ if(count == 5)
+ continue;
+ else
+ val += count;
+ }
+
+ float gray;
+ if( val == 50)
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_vert.vert
new file mode 100644
index 0000000000..93b4dfee01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_continue_vert.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int count=0;
+ int val=0;
+ for(int i=0;i<10;i++)
+ {
+ count++;
+ if(count == 5)
+ continue;
+ else
+ val += count;
+ }
+
+
+ float gray;
+ if( val == 50)
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_frag.frag
new file mode 100644
index 0000000000..63525fdfe4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_frag.frag
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int count1 = 0, count2 = 0;
+ for(int i=0;i<4;i++)
+ {
+ count1++;
+ count2 = 0;
+ for(int j=0;j<4;j++)
+ {
+ count2++;
+ if(count2 == 3)
+ break;
+ }
+ if(count1 == 2)
+ break;
+ }
+ float gray;
+ if( (count1 == 2) && (count2 == 3))
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_vert.vert
new file mode 100644
index 0000000000..871be994b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_break_vert.vert
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int count1 = 0, count2 = 0;
+ for(int i=0;i<45;i++)
+ {
+ count1++;
+ count2 = 0;
+ for(int j=0;j<45;j++)
+ {
+ count2++;
+ if(count2 == 29)
+ break;
+ }
+ if(count1 == 29)
+ break;
+ }
+ float gray;
+ if( (count1 == 29) && (count2 == 29))
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_frag.frag
new file mode 100644
index 0000000000..7c952c1633
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_frag.frag
@@ -0,0 +1,44 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int count1 = 0, count2 = 0;
+ int val1 = 0, val2 = 0;
+ for(int i=0;i<4;i++)
+ {
+ count1++;
+ count2 = 0;
+ for(int j=0;j<4;j++)
+ {
+ count2++;
+ if(count2 == 2)
+ continue;
+ else
+ val2 += count2;
+
+ }
+
+
+ if(count1 == 2)
+ continue;
+ else
+ val1 += count1;
+
+ }
+ float gray;
+ if( (val1 == 8) && (val2 == 32) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_vert.vert
new file mode 100644
index 0000000000..2496202eb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/for_nested_continue_vert.vert
@@ -0,0 +1,44 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int count1 = 0, count2 = 0;
+ int val1 = 0, val2 = 0;
+ for(int i=0;i<10;i++)
+ {
+ count1++;
+ count2 = 0;
+ for(int j=0;j<10;j++)
+ {
+ count2++;
+ if(count2 == 5)
+ continue;
+ else
+ val2 += count2;
+
+ }
+
+
+ if(count1 == 5)
+ continue;
+ else
+ val1 += count1;
+
+ }
+ float gray;
+ if( (val1 == 50) && (val2 == 500) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/input.run.txt
new file mode 100644
index 0000000000..fddcaa48ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+control_flow_001_to_008.html
+control_flow_009_to_010.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_frag.frag
new file mode 100644
index 0000000000..bac0d0596c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_frag.frag
@@ -0,0 +1,40 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int setval = 30;
+
+ if(--setval!=29)
+ if( (setval+=11) == 40)
+ if(setval/4 == 11)
+ setval = 11;
+ else if(setval/4 == 10)
+ if(setval-3 == 37)
+ setval=12;
+ else setval = 9;
+ else setval = 10;
+ else setval = 30;
+ else if(setval == 29)
+ if((setval+=19) != 48)
+ setval = 13;
+ else if((setval+=19) == 29)
+ setval = 28;
+ else setval = 53;
+ else setval = 32;
+ float gray;
+ if( setval == 53 )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_vert.vert
new file mode 100644
index 0000000000..12b66d8b79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/control_flow/nested_if_else_vert.vert
@@ -0,0 +1,40 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int setval = 30;
+
+ if(--setval!=29)
+ if( (setval+=11) == 40)
+ if(setval/4 == 11)
+ setval = 11;
+ else if(setval/4 == 10)
+ if(setval-3 == 37)
+ setval=12;
+ else setval = 9;
+ else setval = 10;
+ else setval = 30;
+ else if(setval == 29)
+ if((setval+=19) != 48)
+ setval = 13;
+ else if((setval+=19) == 29)
+ setval = 28;
+ else setval = 53;
+ else setval = 32;
+ float gray;
+ if( setval == 53 )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_001_to_006.html
new file mode 100644
index 0000000000..d15f070e75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: cos_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cos_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cos_float_frag_xvary.frag"
+ },
+ "name": "cos_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cos_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cos_vec2_frag_xvary.frag"
+ },
+ "name": "cos_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cos_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cos_vec3_frag_xvary.frag"
+ },
+ "name": "cos_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "cos_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "cos_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "cos_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "cos_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "cos_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "cos_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "cos_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "cos_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "cos_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary.frag
new file mode 100644
index 0000000000..c1f5bcad68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ gl_FragColor = vec4(0.5 * cos(2.0 * M_PI * color.r) + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..6dace29eb4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_frag_xvary_ref.frag
@@ -0,0 +1,53 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * ( fract(abs(color.r)) - 0.5 );
+ float sign = 1.0;
+ float cos_c = -1.0;
+ float fact_even = 1.0;
+ float fact_odd = 1.0;
+ float sum;
+
+ // At this point c is in the range [-PI, PI)
+
+ // Taylor-Maclaurin series expansion for cosine
+ //
+ // Apply the property that pow(a, b + c) = pow(a, b) * pow(a, c)
+ // and the property that 1.0/(a*b) = 1.0/a * 1.0/b
+ // to make sure no register ever overflows the range (-16384, +16384)
+ // mandated for mediump variables.
+
+ for(int i = 2; i <= 10; i += 2)
+ {
+ // fact_even will hold at most the value 3840.
+ fact_even *= float(i);
+
+ // fact_odd will always be smaller than fact_even
+ fact_odd *= float(i-1);
+
+ // pow(c, float(i/2)) takes at most the value pow(PI, 5), which is approx. 306
+ // abs(sum) is at most PI/2.0
+ sum = sign * pow(abs(c), float(i/2))/fact_even;
+
+ // abs(sum/fact_odd) is at most PI/2.0
+ // cos_c is always bound in the range [-1.0, 1.0)
+ cos_c += pow(abs(c), float(i/2))*(sum/fact_odd);
+
+ sign = -sign;
+ }
+
+ gl_FragColor = vec4(0.5 * cos_c + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary.vert
new file mode 100644
index 0000000000..e240263025
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ color = vec4(0.5 * cos(2.0 * M_PI * gtf_Color.r) + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..38b68b78ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_float_vert_xvary_ref.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * gtf_Color.r;
+ float sign = -1.0;
+ float cos_c = 1.0;
+ float fact = 1.0;
+
+ // Taylor-Maclaurin series expansion for cosine
+ for(int i = 2; i <= 20; i += 2)
+ {
+ fact *= float(i)*float(i-1);
+ cos_c += sign*pow(c, float(i))/fact;
+ sign = -sign;
+ }
+
+ color = vec4(0.5 * cos_c + 0.5, 0.0, 0.0, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..92f3d3990a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ gl_FragColor = vec4(0.5 * cos(2.0 * M_PI * color.rg) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..ad44ee73f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_frag_xvary_ref.frag
@@ -0,0 +1,57 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * ( fract(abs(color.rg)) - 0.5 );
+ float sign = 1.0;
+ vec2 cos_c = vec2(-1.0, -1.0);
+ float fact_even = 1.0;
+ float fact_odd = 1.0;
+ vec2 sum;
+ vec2 exp;
+
+ // At this point c is in the range [-PI, PI)
+
+ // Taylor-Maclaurin series expansion for cosine
+ //
+ // Apply the property that pow(a, b + c) = pow(a, b) * pow(a, c)
+ // and the property that 1.0/(a*b) = 1.0/a * 1.0/b
+ // to make sure no register ever overflows the range (-16384, +16384)
+ // mandated for mediump variables.
+
+ for(int i = 2; i <= 10; i += 2)
+ {
+ // fact_even will hold at most the value 3840.
+ fact_even *= float(i);
+
+ // fact_odd will always be smaller than fact_even
+ fact_odd *= float(i-1);
+
+ // exp is at most (5,5)
+ exp = vec2(float(i/2), float(i/2));
+
+ // pow(c, exp) takes at most the value pow(PI, 5), which is approx. 306
+ // abs(sum) is at most PI/2.0
+ sum = sign * pow(abs(c), exp)/fact_even;
+
+ // abs(sum/fact_odd) is at most PI/2.0
+ // cos_c is always bound in the range [-1.0, 1.0)
+ cos_c += pow(abs(c), exp)*(sum/fact_odd);
+
+ sign = -sign;
+ }
+
+ gl_FragColor = vec4(0.5 * cos_c + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..c3aeba8ccd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ color = vec4(0.5 * cos(2.0 * M_PI * gtf_Color.rg) + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..4aa50e3b88
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec2_vert_xvary_ref.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * gtf_Color.rg;
+ float sign = -1.0;
+ vec2 cos_c = vec2(1.0, 1.0);
+ float fact = 1.0;
+
+ // Taylor-Maclaurin series expansion for cosine
+ for(int i = 2; i <= 20; i += 2)
+ {
+ fact *= float(i)*float(i-1);
+ cos_c += sign*pow(c, vec2(float(i), float(i)))/fact;
+ sign = -sign;
+ }
+
+ color = vec4(0.5 * cos_c + 0.5, 0.0, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..a51a52db02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ gl_FragColor = vec4(0.5 * cos(2.0 * M_PI * color.rgb) + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..c228a078e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_frag_xvary_ref.frag
@@ -0,0 +1,57 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * ( fract(abs(color.rgb)) - 0.5 );
+ float sign = 1.0;
+ vec3 cos_c = vec3(-1.0, -1.0, -1.0);
+ float fact_even = 1.0;
+ float fact_odd = 1.0;
+ vec3 sum;
+ vec3 exp;
+
+ // At this point c is in the range [-PI, PI)
+
+ // Taylor-Maclaurin series expansion for cosine
+ //
+ // Apply the property that pow(a, b + c) = pow(a, b) * pow(a, c)
+ // and the property that 1.0/(a*b) = 1.0/a * 1.0/b
+ // to make sure no register ever overflows the range (-16384, +16384)
+ // mandated for mediump variables.
+
+ for(int i = 2; i <= 10; i += 2)
+ {
+ // fact_even will hold at most the value 3840.
+ fact_even *= float(i);
+
+ // fact_odd will always be smaller than fact_even
+ fact_odd *= float(i-1);
+
+ // exp is at most (5,5,5)
+ exp = vec3(float(i/2), float(i/2), float(i/2));
+
+ // pow(c, exp) takes at most the value pow(PI, 5), which is approx. 306
+ // abs(sum) is at most PI/2.0
+ sum = sign * pow(abs(c), exp)/fact_even;
+
+ // abs(sum/fact_odd) is at most PI/2.0
+ // cos_c is always bound in the range [-1.0, 1.0)
+ cos_c += pow(abs(c), exp)*(sum/fact_odd);
+
+ sign = -sign;
+ }
+
+ gl_FragColor = vec4(0.5 * cos_c + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..7c1d8b6270
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ color = vec4(0.5 * cos(2.0 * M_PI * gtf_Color.rgb) + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..63ebd02500
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/cos_vec3_vert_xvary_ref.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * gtf_Color.rgb;
+ float sign = -1.0;
+ vec3 cos_c = vec3(1.0,1.0,1.0);
+ float fact = 1.0;
+
+ // Taylor-Maclaurin series expansion for cosine
+ for(int i = 2; i <= 20; i += 2)
+ {
+ fact *= float(i)*float(i-1);
+ cos_c += sign*pow(c, vec3(float(i),float(i),float(i)))/fact;
+ sign = -sign;
+ }
+
+ color = vec4(0.5 * cos_c + 0.5, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/input.run.txt
new file mode 100644
index 0000000000..64f23d8c39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cos/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+cos_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_001_to_002.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_001_to_002.html
new file mode 100644
index 0000000000..210807e5e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_001_to_002.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: cross_001_to_002.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cross_vec3_frag_xvaryyconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "cross_vec3_frag_xvaryyconst.frag"
+ },
+ "name": "cross_vec3_frag_xvaryyconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "cross_vec3_vert_xvaryyconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "cross_vec3_vert_xvaryyconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "cross_vec3_vert_xvaryyconst.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst.frag
new file mode 100644
index 0000000000..5109326e41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = vec3(1.0, 0.0, 0.0);
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ gl_FragColor = vec4((cross(v1, v2) + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst_ref.frag
new file mode 100644
index 0000000000..024710b282
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_frag_xvaryyconst_ref.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = vec3(1.0, 0.0, 0.0);
+ vec3 v3;
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+ v3.x = v1.y * v2.z - v2.y * v1.z;
+ v3.y = v2.x * v1.z - v1.x * v2.z;
+ v3.z = v1.x * v2.y - v2.x * v1.y;
+ gl_FragColor = vec4((v3 + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst.vert
new file mode 100644
index 0000000000..4faad3c659
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = vec3(1.0, 0.0, 0.0);
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+ color = vec4((cross(v1, v2) + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst_ref.vert
new file mode 100644
index 0000000000..8e02aecc17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/cross_vec3_vert_xvaryyconst_ref.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = vec3(1.0, 0.0, 0.0);
+ vec3 v3;
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+ v3.x = v1.y * v2.z - v2.y * v1.z;
+ v3.y = v2.x * v1.z - v1.x * v2.z;
+ v3.z = v1.x * v2.y - v2.x * v1.y;
+ color = vec4((v3 + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/input.run.txt
new file mode 100644
index 0000000000..4ce9794db5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/cross/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+cross_001_to_002.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.frag
new file mode 100644
index 0000000000..48175cd07e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.vert
new file mode 100644
index 0000000000..319999cb93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_001_to_001.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_001_to_001.html
new file mode 100644
index 0000000000..7b41e42798
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_001_to_001.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: default_001_to_001.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "default.vert",
+ "fragmentShader": "default.frag"
+ },
+ "name": "default.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.frag
new file mode 100644
index 0000000000..48cd225675
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+varying vec4 color;
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ gl_FragColor = texture2D(gtf_Texture0, gtf_TexCoord[0].xy);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.vert
new file mode 100644
index 0000000000..0088a62147
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/default_textured.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 gtf_TexCoord[1];
+attribute vec4 gtf_MultiTexCoord0;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gtf_TexCoord[0] = gtf_MultiTexCoord0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/expected.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/expected.frag
new file mode 100644
index 0000000000..a57779cd1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/expected.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec4 result;
+
+void main (void)
+{
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/input.run.txt
new file mode 100644
index 0000000000..44c03e906b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/default/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+default_001_to_001.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_001_to_006.html
new file mode 100644
index 0000000000..503996c534
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: degrees_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "degrees_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "degrees_float_frag_xvary.frag"
+ },
+ "name": "degrees_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "degrees_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "degrees_vec2_frag_xvary.frag"
+ },
+ "name": "degrees_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "degrees_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "degrees_vec3_frag_xvary.frag"
+ },
+ "name": "degrees_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "degrees_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "degrees_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "degrees_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "degrees_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "degrees_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "degrees_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "degrees_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "degrees_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "degrees_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary.frag
new file mode 100644
index 0000000000..977123df4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(degrees(c) / (2.0 * 360.0) + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..1c19a3811e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4((c * 180.0 / M_PI) / (2.0 * 360.0) + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary.vert
new file mode 100644
index 0000000000..25f0e95d84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(degrees(c) / (2.0 * 360.0) + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..dabf62da94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_float_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4((c * 180.0 / M_PI) / (2.0 * 360.0) + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..24df526729
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(degrees(c) / (2.0 * 360.0) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..cbff75621f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4((c * 180.0 / M_PI) / (2.0 * 360.0) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..57f5af257f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(degrees(c) / (2.0 * 360.0) + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..28bafb275b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec2_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4((c * 180.0 / M_PI) / (2.0 * 360.0) + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..b57c486a74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(degrees(c) / (2.0 * 360.0) + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..855d837054
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4((c * 180.0 / M_PI) / (2.0 * 360.0) + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..d3089d30c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(degrees(c) / (2.0 * 360.0) + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..a8aeff87f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/degrees_vec3_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4((c * 180.0 / M_PI) / (2.0 * 360.0) + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/input.run.txt
new file mode 100644
index 0000000000..caa0c110d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/degrees/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+degrees_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_001_to_002.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_001_to_002.html
new file mode 100644
index 0000000000..d976162551
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_001_to_002.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: discard_001_to_002.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "discard_frag.frag"
+ },
+ "name": "discard_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "discard_cond_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "discard_cond_frag.frag"
+ },
+ "name": "discard_cond_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag.frag
new file mode 100644
index 0000000000..31de4525c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ bool toDiscard = false;
+ if(color.r > 0.75) toDiscard = true;
+ else if(color.g > 0.75) toDiscard = true;
+ else if(color.b > 0.75) toDiscard = true;
+
+ if (toDiscard) discard;
+
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag_ref.frag
new file mode 100644
index 0000000000..f455d1f57e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_cond_frag_ref.frag
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ if(color.r > 0.75 || color.g > 0.75 || color.b > 0.75)
+ {
+ /* The background color is black by default.
+ * Setting the fragment color to it simulates a discarded fragment.
+ */
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ }
+ else
+ {
+ gl_FragColor = color;
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_frag.frag
new file mode 100644
index 0000000000..c88776fb38
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/discard_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+ discard;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/input.run.txt
new file mode 100644
index 0000000000..ff9bfa993d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/discard/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+discard_001_to_002.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_001_to_006.html
new file mode 100644
index 0000000000..04d2aee15f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: distance_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "distance_float_frag_xvaryyhalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "distance_float_frag_xvaryyhalf.frag"
+ },
+ "name": "distance_float_frag_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "distance_vec2_frag_xvaryyhalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "distance_vec2_frag_xvaryyhalf.frag"
+ },
+ "name": "distance_vec2_frag_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "distance_vec3_frag_xvaryyhalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "distance_vec3_frag_xvaryyhalf.frag"
+ },
+ "name": "distance_vec3_frag_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "distance_float_vert_xvaryyhalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "distance_float_vert_xvaryyhalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "distance_float_vert_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "distance_vec2_vert_xvaryyhalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "distance_vec2_vert_xvaryyhalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "distance_vec2_vert_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "distance_vec3_vert_xvaryyhalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "distance_vec3_vert_xvaryyhalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "distance_vec3_vert_xvaryyhalf.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf.frag
new file mode 100644
index 0000000000..0d0a2e8a4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(distance(color.r, 0.5)), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf_ref.frag
new file mode 100644
index 0000000000..46d1e32f30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_frag_xvaryyhalf_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(sqrt(pow(abs(color.r - 0.5), 2.0))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf.vert
new file mode 100644
index 0000000000..9c915dc981
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(distance(gtf_Color.r, 0.5)), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf_ref.vert
new file mode 100644
index 0000000000..a66dee0a24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_float_vert_xvaryyhalf_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(sqrt(pow(abs(gtf_Color.r - 0.5), 2.0))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf.frag
new file mode 100644
index 0000000000..bec06c2a9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(distance(color.rg, vec2(0.5))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf_ref.frag
new file mode 100644
index 0000000000..ff73840933
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_frag_xvaryyhalf_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(sqrt(pow(abs(color.r - 0.5), 2.0) + pow(abs(color.g - 0.5), 2.0))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf.vert
new file mode 100644
index 0000000000..398e1cfb7a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(distance(gtf_Color.rg, vec2(0.5))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf_ref.vert
new file mode 100644
index 0000000000..c2cd4c9361
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec2_vert_xvaryyhalf_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(sqrt(pow(abs(gtf_Color.r - 0.5), 2.0) + pow(abs(gtf_Color.g - 0.5), 2.0))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf.frag
new file mode 100644
index 0000000000..b65a37d5aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(distance(color.rgb, vec3(0.5))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf_ref.frag
new file mode 100644
index 0000000000..a4517828d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_frag_xvaryyhalf_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(sqrt(pow(abs(color.r - 0.5), 2.0) + pow(abs(color.g - 0.5), 2.0) + pow(abs(color.b - 0.5), 2.0))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf.vert
new file mode 100644
index 0000000000..2efe949b12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(distance(gtf_Color.rgb, vec3(0.5))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf_ref.vert
new file mode 100644
index 0000000000..0d24c7ce82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/distance_vec3_vert_xvaryyhalf_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(sqrt(pow(abs(gtf_Color.r - 0.5), 2.0) + pow(abs(gtf_Color.g - 0.5), 2.0) + pow(abs(gtf_Color.b - 0.5), 2.0))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/input.run.txt
new file mode 100644
index 0000000000..bfbce99ed1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/distance/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+distance_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_001_to_006.html
new file mode 100644
index 0000000000..975dde6742
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: dot_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dot_float_frag_xvaryyone_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dot_float_frag_xvaryyone.frag"
+ },
+ "name": "dot_float_frag_xvaryyone.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dot_vec2_frag_xvaryyhalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dot_vec2_frag_xvaryyhalf.frag"
+ },
+ "name": "dot_vec2_frag_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dot_vec3_frag_xvaryythird_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "dot_vec3_frag_xvaryythird.frag"
+ },
+ "name": "dot_vec3_frag_xvaryythird.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "dot_float_vert_xvaryyone_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "dot_float_vert_xvaryyone.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "dot_float_vert_xvaryyone.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "dot_vec2_vert_xvaryyhalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "dot_vec2_vert_xvaryyhalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "dot_vec2_vert_xvaryyhalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "dot_vec3_vert_xvaryythird_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "dot_vec3_vert_xvaryythird.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "dot_vec3_vert_xvaryythird.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone.frag
new file mode 100644
index 0000000000..ddb6ade7c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(dot(color.r, 1.0)), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone_ref.frag
new file mode 100644
index 0000000000..9e5672b1d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_frag_xvaryyone_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(color.r), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone.vert
new file mode 100644
index 0000000000..3c3e8d0c86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(dot(gtf_Color.r, 1.0)), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone_ref.vert
new file mode 100644
index 0000000000..940b53e278
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_float_vert_xvaryyone_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(gtf_Color.r), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf.frag
new file mode 100644
index 0000000000..de74683979
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(dot(color.rg, vec2(0.5))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf_ref.frag
new file mode 100644
index 0000000000..82935af669
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_frag_xvaryyhalf_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(color.r + color.g) * 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf.vert
new file mode 100644
index 0000000000..8098142fab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(dot(gtf_Color.rg, vec2(0.5))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf_ref.vert
new file mode 100644
index 0000000000..81206d3dfb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec2_vert_xvaryyhalf_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(gtf_Color.r + gtf_Color.g) * 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird.frag
new file mode 100644
index 0000000000..13e1ac8134
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(dot(color.rgb, vec3(0.3333))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird_ref.frag
new file mode 100644
index 0000000000..d3a96d5be5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_frag_xvaryythird_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(color.r + color.g + color.b) * 0.3333, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird.vert
new file mode 100644
index 0000000000..506d16c89e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(dot(gtf_Color.rgb, vec3(0.3333))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird_ref.vert
new file mode 100644
index 0000000000..daba538dab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/dot_vec3_vert_xvaryythird_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(gtf_Color.r + gtf_Color.g + gtf_Color.b) * 0.3333, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/input.run.txt
new file mode 100644
index 0000000000..e87547fd33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/dot/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+dot_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_001_to_008.html
new file mode 100644
index 0000000000..40ab967057
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: equal_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_vec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_vec2_frag.frag"
+ },
+ "name": "equal_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "equal_vec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "equal_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equal_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_vec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_vec3_frag.frag"
+ },
+ "name": "equal_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "equal_vec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "equal_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equal_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_ivec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_ivec2_frag.frag"
+ },
+ "name": "equal_ivec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "equal_ivec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "equal_ivec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equal_ivec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_ivec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_ivec3_frag.frag"
+ },
+ "name": "equal_ivec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "equal_ivec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "equal_ivec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equal_ivec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_009_to_012.html
new file mode 100644
index 0000000000..6d61182c36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: equal_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_bvec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_bvec2_frag.frag"
+ },
+ "name": "equal_bvec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "equal_bvec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "equal_bvec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equal_bvec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_bvec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equal_bvec3_frag.frag"
+ },
+ "name": "equal_bvec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "equal_bvec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "equal_bvec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equal_bvec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag.frag
new file mode 100644
index 0000000000..572c0646dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(equal(bvec2(c), bvec2(true)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag_ref.frag
new file mode 100644
index 0000000000..5433b3967a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 eq(in bvec2 a, in bvec2 b)
+{
+ bvec2 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(eq(bvec2(c), bvec2(true)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert.vert
new file mode 100644
index 0000000000..50cf29351a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(equal(bvec2(c), bvec2(true)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert_ref.vert
new file mode 100644
index 0000000000..015c0cbb36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 eq(in bvec2 a, in bvec2 b)
+{
+ bvec2 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(eq(bvec2(c), bvec2(true)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag.frag
new file mode 100644
index 0000000000..abce71547a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(equal(bvec3(c), bvec3(true)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag_ref.frag
new file mode 100644
index 0000000000..b8b7137e5d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 eq(in bvec3 a, in bvec3 b)
+{
+ bvec3 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] == b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(eq(bvec3(c), bvec3(true)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert.vert
new file mode 100644
index 0000000000..85872d7d52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(equal(bvec3(c), bvec3(true)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert_ref.vert
new file mode 100644
index 0000000000..d37018d75b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_bvec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 eq(in bvec3 a, in bvec3 b)
+{
+ bvec3 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] == b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(eq(bvec3(c), bvec3(true)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag.frag
new file mode 100644
index 0000000000..4ed1070ef4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(equal(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag_ref.frag
new file mode 100644
index 0000000000..0c32cb1061
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec2 eq(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(eq(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert.vert
new file mode 100644
index 0000000000..fde98be8b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(equal(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert_ref.vert
new file mode 100644
index 0000000000..65983106ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 eq(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(eq(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag.frag
new file mode 100644
index 0000000000..dab4bc460f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(equal(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag_ref.frag
new file mode 100644
index 0000000000..2af8c6dd1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 eq(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] == b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(eq(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert.vert
new file mode 100644
index 0000000000..914b7e92a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(equal(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert_ref.vert
new file mode 100644
index 0000000000..53f8da4e29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_ivec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 eq(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] == b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(eq(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag.frag
new file mode 100644
index 0000000000..3c45eda536
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(equal(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag_ref.frag
new file mode 100644
index 0000000000..f59b45642d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 eq(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(eq(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert.vert
new file mode 100644
index 0000000000..2477448f50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(equal(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert_ref.vert
new file mode 100644
index 0000000000..845aeaf897
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 eq(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(eq(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag.frag
new file mode 100644
index 0000000000..95c11a4ec9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(equal(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag_ref.frag
new file mode 100644
index 0000000000..b71c3e6f07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 eq(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] == b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(eq(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert.vert
new file mode 100644
index 0000000000..3d7c06cb73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(equal(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert_ref.vert
new file mode 100644
index 0000000000..ae86feabf3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/equal_vec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 eq(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] == b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] == b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] == b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(eq(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/input.run.txt
new file mode 100644
index 0000000000..cd4a81eb51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/equal/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+equal_001_to_008.html
+equal_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_001_to_008.html
new file mode 100644
index 0000000000..4e2bca1c08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: exp_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_float_frag_xvary.frag"
+ },
+ "name": "exp_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec2_frag_xvary.frag"
+ },
+ "name": "exp_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec3_frag_xvary.frag"
+ },
+ "name": "exp_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_float_frag_xvaryneg_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_float_frag_xvaryneg.frag"
+ },
+ "name": "exp_float_frag_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec2_frag_xvaryneg_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec2_frag_xvaryneg.frag"
+ },
+ "name": "exp_vec2_frag_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec3_frag_xvaryneg_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp_vec3_frag_xvaryneg.frag"
+ },
+ "name": "exp_vec3_frag_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_009_to_012.html
new file mode 100644
index 0000000000..95531a316f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: exp_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "exp_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp_float_vert_xvaryneg_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp_float_vert_xvaryneg.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp_float_vert_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp_vec2_vert_xvaryneg_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp_vec2_vert_xvaryneg.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp_vec2_vert_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp_vec3_vert_xvaryneg_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp_vec3_vert_xvaryneg.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp_vec3_vert_xvaryneg.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary.frag
new file mode 100644
index 0000000000..3e25c3022d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp3 = 20.0855;
+ float c = color.r;
+ gl_FragColor = vec4(exp(3.0 * c) / exp3, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..5fb281520b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvary_ref.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ const float exp3 = 20.0855;
+ float c = color.r;
+ gl_FragColor = vec4(pow(exp1, 3.0 * c) / exp3, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg.frag
new file mode 100644
index 0000000000..92f3e8fb79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = -color.r;
+ gl_FragColor = vec4(exp(3.0 * c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg_ref.frag
new file mode 100644
index 0000000000..f165cebe8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_frag_xvaryneg_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ float c = color.r;
+ gl_FragColor = vec4(1.0 / pow(exp1, 3.0 * c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary.vert
new file mode 100644
index 0000000000..70700362a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp3 = 20.0855;
+ float c = gtf_Color.r;
+ color = vec4(exp(3.0 * c) / exp3, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..9928f9b245
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvary_ref.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ const float exp3 = 20.0855;
+ float c = gtf_Color.r;
+ color = vec4(pow(exp1, 3.0 * c) / exp3, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg.vert
new file mode 100644
index 0000000000..c5e2ea8b76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = -gtf_Color.r;
+ color = vec4(exp(3.0 * c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg_ref.vert
new file mode 100644
index 0000000000..8fb130dec5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_float_vert_xvaryneg_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ float c = gtf_Color.r;
+ color = vec4(1.0 / pow(exp1, 3.0 * c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..f330458f15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp3 = 20.0855;
+ vec2 c = color.rg;
+ gl_FragColor = vec4(exp(3.0 * c) / exp3, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..c263a4c88f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvary_ref.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ const float exp3 = 20.0855;
+ vec2 c = color.rg;
+ gl_FragColor = vec4(pow(vec2(exp1), 3.0 * c) / exp3, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg.frag
new file mode 100644
index 0000000000..895a88b055
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = -color.rg;
+ gl_FragColor = vec4(exp(3.0 * c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg_ref.frag
new file mode 100644
index 0000000000..8e408bc9bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_frag_xvaryneg_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ vec2 c = color.rg;
+ gl_FragColor = vec4(1.0 / pow(vec2(exp1), 3.0 * c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..ee96286fd8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp3 = 20.0855;
+ vec2 c = gtf_Color.rg;
+ color = vec4(exp(3.0 * c) / exp3, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..313fad0127
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvary_ref.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ const float exp3 = 20.0855;
+ vec2 c = gtf_Color.rg;
+ color = vec4(pow(vec2(exp1), 3.0 * c) / exp3, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg.vert
new file mode 100644
index 0000000000..c4ed25c8f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = -gtf_Color.rg;
+ color = vec4(exp(3.0 * c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg_ref.vert
new file mode 100644
index 0000000000..2d26b842ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec2_vert_xvaryneg_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ vec2 c = gtf_Color.rg;
+ color = vec4(1.0 / pow(vec2(exp1), 3.0 * c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..df08194b65
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp3 = 20.0855;
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(exp(3.0 * c) / exp3, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..2bfe2e58d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvary_ref.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ const float exp3 = 20.0855;
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(pow(vec3(exp1), 3.0 * c) / exp3, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg.frag
new file mode 100644
index 0000000000..d4f553fec6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = -color.rgb;
+ gl_FragColor = vec4(exp(3.0 * c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg_ref.frag
new file mode 100644
index 0000000000..af2433457c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_frag_xvaryneg_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(1.0 / pow(vec3(exp1), 3.0 * c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..fa8b8e82ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp3 = 20.0855;
+ vec3 c = gtf_Color.rgb;
+ color = vec4(exp(3.0 * c) / exp3, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..22e8f94256
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvary_ref.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ const float exp3 = 20.0855;
+ vec3 c = gtf_Color.rgb;
+ color = vec4(pow(vec3(exp1), 3.0 * c) / exp3, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg.vert
new file mode 100644
index 0000000000..c49da07289
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = -gtf_Color.rgb;
+ color = vec4(exp(3.0 * c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg_ref.vert
new file mode 100644
index 0000000000..c078b1aa72
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/exp_vec3_vert_xvaryneg_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float exp1 = 2.7183;
+ vec3 c = gtf_Color.rgb;
+ color = vec4(1.0 / pow(vec3(exp1), 3.0 * c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/input.run.txt
new file mode 100644
index 0000000000..4f56a2b329
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+exp_001_to_008.html
+exp_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_001_to_008.html
new file mode 100644
index 0000000000..0c4be1d366
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: exp2_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_float_frag_xvary.frag"
+ },
+ "name": "exp2_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec2_frag_xvary.frag"
+ },
+ "name": "exp2_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec3_frag_xvary.frag"
+ },
+ "name": "exp2_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_float_frag_xvaryneg_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_float_frag_xvaryneg.frag"
+ },
+ "name": "exp2_float_frag_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec2_frag_xvaryneg_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec2_frag_xvaryneg.frag"
+ },
+ "name": "exp2_vec2_frag_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec3_frag_xvaryneg_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "exp2_vec3_frag_xvaryneg.frag"
+ },
+ "name": "exp2_vec3_frag_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp2_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp2_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp2_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp2_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp2_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp2_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_009_to_012.html
new file mode 100644
index 0000000000..331710c39c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: exp2_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "exp2_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp2_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp2_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp2_float_vert_xvaryneg_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp2_float_vert_xvaryneg.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp2_float_vert_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp2_vec2_vert_xvaryneg_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp2_vec2_vert_xvaryneg.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp2_vec2_vert_xvaryneg.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "exp2_vec3_vert_xvaryneg_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "exp2_vec3_vert_xvaryneg.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "exp2_vec3_vert_xvaryneg.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary.frag
new file mode 100644
index 0000000000..c3e2d04a6a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = color.r;
+ gl_FragColor = vec4(exp2(5.0 * c) / 32.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..cdad89f953
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = color.r;
+ gl_FragColor = vec4(pow(2.0, 5.0 * c) / 32.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg.frag
new file mode 100644
index 0000000000..8d285849aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = -color.r;
+ gl_FragColor = vec4(exp2(5.0 * c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg_ref.frag
new file mode 100644
index 0000000000..efad77cddb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_frag_xvaryneg_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = color.r;
+ gl_FragColor = vec4(1.0 / pow(2.0, 5.0 * c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary.vert
new file mode 100644
index 0000000000..393a4f42e6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = gtf_Color.r;
+ color = vec4(exp2(5.0 * c) / 32.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..3a95dc1a14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = gtf_Color.r;
+ color = vec4(pow(2.0, 5.0 * c) / 32.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg.vert
new file mode 100644
index 0000000000..5e3ce879ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = -gtf_Color.r;
+ color = vec4(exp2(5.0 * c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg_ref.vert
new file mode 100644
index 0000000000..4303b64954
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_float_vert_xvaryneg_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = gtf_Color.r;
+ color = vec4(1.0 / pow(2.0, 5.0 * c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..436c856de2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = color.rg;
+ gl_FragColor = vec4(exp2(5.0 * c) / 32.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..58fc9b2a11
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = color.rg;
+ gl_FragColor = vec4(pow(vec2(2.0), 5.0 * c) / 32.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg.frag
new file mode 100644
index 0000000000..d3112c7991
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = -color.rg;
+ gl_FragColor = vec4(exp2(5.0 * c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg_ref.frag
new file mode 100644
index 0000000000..ca1a4e2424
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_frag_xvaryneg_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = color.rg;
+ gl_FragColor = vec4(1.0 / pow(vec2(2.0), 5.0 * c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..dffd2f6b8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = gtf_Color.rg;
+ color = vec4(exp2(5.0 * c) / 32.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..f9ae9fa180
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = gtf_Color.rg;
+ color = vec4(pow(vec2(2.0), 5.0 * c) / 32.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg.vert
new file mode 100644
index 0000000000..5b46f97f82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = -gtf_Color.rg;
+ color = vec4(exp2(5.0 * c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg_ref.vert
new file mode 100644
index 0000000000..15a19d450f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec2_vert_xvaryneg_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = gtf_Color.rg;
+ color = vec4(1.0 / pow(vec2(2.0), 5.0 * c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..bbe41d3002
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(exp2(5.0 * c) / 32.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..51719fc226
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(pow(vec3(2.0), 5.0 * c) / 32.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg.frag
new file mode 100644
index 0000000000..6f799874ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = -color.rgb;
+ gl_FragColor = vec4(exp2(5.0 * c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg_ref.frag
new file mode 100644
index 0000000000..b7807d4c6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_frag_xvaryneg_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(1.0 / pow(vec3(2.0), 5.0 * c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..ace9f91be0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = gtf_Color.rgb;
+ color = vec4(exp2(5.0 * c) / 32.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..020a56e708
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = gtf_Color.rgb;
+ color = vec4(pow(vec3(2.0), 5.0 * c) / 32.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg.vert
new file mode 100644
index 0000000000..708cd0494c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = -gtf_Color.rgb;
+ color = vec4(exp2(5.0 * c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg_ref.vert
new file mode 100644
index 0000000000..3a0238f59c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/exp2_vec3_vert_xvaryneg_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = gtf_Color.rgb;
+ color = vec4(1.0 / pow(vec3(2.0), 5.0 * c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/input.run.txt
new file mode 100644
index 0000000000..f893cd413e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/exp2/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+exp2_001_to_008.html
+exp2_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_001_to_006.html
new file mode 100644
index 0000000000..911e8cfebb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: faceforward_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "faceforward_float_frag_nvaryiconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "faceforward_float_frag_nvaryiconst.frag"
+ },
+ "name": "faceforward_float_frag_nvaryiconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "faceforward_float_vert_nvaryiconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "faceforward_float_vert_nvaryiconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "faceforward_float_vert_nvaryiconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "faceforward_vec2_frag_nvaryiconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "faceforward_vec2_frag_nvaryiconst.frag"
+ },
+ "name": "faceforward_vec2_frag_nvaryiconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "faceforward_vec2_vert_nvaryiconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "faceforward_vec2_vert_nvaryiconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "faceforward_vec2_vert_nvaryiconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "faceforward_vec3_frag_nvaryiconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "faceforward_vec3_frag_nvaryiconst.frag"
+ },
+ "name": "faceforward_vec3_frag_nvaryiconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "faceforward_vec3_vert_nvaryiconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "faceforward_vec3_vert_nvaryiconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "faceforward_vec3_vert_nvaryiconst.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst.frag
new file mode 100644
index 0000000000..41fb495458
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (color.g * 2.0) - 1.0;
+ float v2 = (color.b * 2.0) - 1.0;
+
+ gl_FragColor = vec4((faceforward(v1, v2, v1) + 1.0) / 2.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst_ref.frag
new file mode 100644
index 0000000000..788d24b1e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_frag_nvaryiconst_ref.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (color.g * 2.0) - 1.0;
+ float v2 = (color.b * 2.0) - 1.0;
+
+ if(dot(v1, v2) >= 0.0) v1 *= -1.0;
+ gl_FragColor = vec4((v1 + 1.0) / 2.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst.vert
new file mode 100644
index 0000000000..9f806e727e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (gtf_Color.g * 2.0) - 1.0;
+ float v2 = (gtf_Color.b * 2.0) - 1.0;
+
+ color = vec4((faceforward(v1, v2, v1) + 1.0) / 2.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst_ref.vert
new file mode 100644
index 0000000000..df8ccb1fd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_float_vert_nvaryiconst_ref.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (gtf_Color.g * 2.0) - 1.0;
+ float v2 = (gtf_Color.b * 2.0) - 1.0;
+
+ if(dot(v1, v2) >= 0.0) v1 *= -1.0;
+ color = vec4((v1 + 1.0) / 2.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst.frag
new file mode 100644
index 0000000000..d877115396
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ gl_FragColor = vec4((faceforward(v1, v2, v1) + 1.0) / 2.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst_ref.frag
new file mode 100644
index 0000000000..16cf215c66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_frag_nvaryiconst_ref.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ if(dot(v1, v2) >= 0.0) v1 *= -1.0;
+ gl_FragColor = vec4((v1 + 1.0) / 2.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst.vert
new file mode 100644
index 0000000000..18d5e26477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ color = vec4((faceforward(v1, v2, v1) + 1.0) / 2.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst_ref.vert
new file mode 100644
index 0000000000..3a102015bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec2_vert_nvaryiconst_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ if(dot(v1, v2) >= 0.0) v1 *= -1.0;
+ color = vec4((v1 + 1.0) / 2.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst.frag
new file mode 100644
index 0000000000..dd50453018
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ gl_FragColor = vec4((faceforward(v1, v2, v1) + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst_ref.frag
new file mode 100644
index 0000000000..6316f78ba3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_frag_nvaryiconst_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ if(dot(v1, v2) >= 0.0) v1 *= -1.0;
+ gl_FragColor = vec4((v1 + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst.vert
new file mode 100644
index 0000000000..30cb98c6e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ color = vec4((faceforward(v1, v2, v1) + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst_ref.vert
new file mode 100644
index 0000000000..a6c8e6b2ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/faceforward_vec3_vert_nvaryiconst_ref.vert
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ if(dot(v1, v2) >= 0.0) v1 *= -1.0;
+ color = vec4((v1 + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/input.run.txt
new file mode 100644
index 0000000000..4107e63979
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/faceforward/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+faceforward_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_001_to_006.html
new file mode 100644
index 0000000000..433abdcede
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: floor_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "floor_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "floor_float_frag_xvary.frag"
+ },
+ "name": "floor_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "floor_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "floor_vec2_frag_xvary.frag"
+ },
+ "name": "floor_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "floor_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "floor_vec3_frag_xvary.frag"
+ },
+ "name": "floor_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "floor_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "floor_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "floor_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "floor_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "floor_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "floor_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "floor_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "floor_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "floor_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary.frag
new file mode 100644
index 0000000000..5b74e045b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4((floor(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..6d7a786a98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_frag_xvary_ref.frag
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float floor_ref(float x)
+{
+ if(x >= 0.0)
+ x = float(int(x));
+ else
+ x = float(int(x) - 1);
+ return x;
+}
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4((floor_ref(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary.vert
new file mode 100644
index 0000000000..987259940a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4((floor(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..9fe17c740f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_float_vert_xvary_ref.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+float floor_ref(float x)
+{
+ if(x >= 0.0)
+ x = float(int(x));
+ else
+ x = float(int(x) - 1);
+ return x;
+}
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4((floor_ref(c) + 10.0) / 20.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..54a6d9a15f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4((floor(c) + 10.0) / 20.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..3f537cc357
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_frag_xvary_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+vec2 floor_ref(vec2 x)
+{
+ if(x[0] >= 0.0)
+ x[0] = float(int(x[0]));
+ else
+ x[0] = float(int(x[0]) - 1);
+ if(x[1] >= 0.0)
+ x[1] = float(int(x[1]));
+ else
+ x[1] = float(int(x[1]) - 1);
+ return x;
+}
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4((floor_ref(c) + 10.0) / 20.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..3b53e23dad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4((floor(c) + 10.0) / 20.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..fabb3a0f0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec2_vert_xvary_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+vec2 floor_ref(vec2 x)
+{
+ if(x[0] >= 0.0)
+ x[0] = float(int(x[0]));
+ else
+ x[0] = float(int(x[0]) - 1);
+ if(x[1] >= 0.0)
+ x[1] = float(int(x[1]));
+ else
+ x[1] = float(int(x[1]) - 1);
+ return x;
+}
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4((floor_ref(c) + 10.0) / 20.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..55bd572178
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4((floor(c) + 10.0) / 20.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..279f765c40
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_frag_xvary_ref.frag
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+vec3 floor_ref(vec3 x)
+{
+ if(x[0] >= 0.0)
+ x[0] = float(int(x[0]));
+ else
+ x[0] = float(int(x[0]) - 1);
+ if(x[1] >= 0.0)
+ x[1] = float(int(x[1]));
+ else
+ x[1] = float(int(x[1]) - 1);
+ if(x[2] >= 0.0)
+ x[2] = float(int(x[2]));
+ else
+ x[2] = float(int(x[2]) - 1);
+ return x;
+}
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4((floor_ref(c) + 10.0) / 20.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..feacc63fb2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4((floor(c) + 10.0) / 20.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..8913a2b00c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/floor_vec3_vert_xvary_ref.vert
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+vec3 floor_ref(vec3 x)
+{
+ if(x[0] >= 0.0)
+ x[0] = float(int(x[0]));
+ else
+ x[0] = float(int(x[0]) - 1);
+ if(x[1] >= 0.0)
+ x[1] = float(int(x[1]));
+ else
+ x[1] = float(int(x[1]) - 1);
+ if(x[2] >= 0.0)
+ x[2] = float(int(x[2]));
+ else
+ x[2] = float(int(x[2]) - 1);
+ return x;
+}
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4((floor_ref(c) + 10.0) / 20.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/input.run.txt
new file mode 100644
index 0000000000..337787db8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/floor/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+floor_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_001_to_006.html
new file mode 100644
index 0000000000..5ccf6937f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: fract_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "fract_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "fract_float_frag_xvary.frag"
+ },
+ "name": "fract_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "fract_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "fract_vec2_frag_xvary.frag"
+ },
+ "name": "fract_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "fract_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "fract_vec3_frag_xvary.frag"
+ },
+ "name": "fract_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "fract_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "fract_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "fract_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "fract_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "fract_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "fract_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "fract_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "fract_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "fract_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary.frag
new file mode 100644
index 0000000000..0900f58dbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ c = abs(fract(c) - 0.5) * 2.0;
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..00d2a14648
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ c = abs((c - floor(c)) - 0.5) * 2.0;
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary.vert
new file mode 100644
index 0000000000..eb8d560b8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ c = abs(fract(c) - 0.5) * 2.0;
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..2a644b2fb0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_float_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ c = abs((c - floor(c)) - 0.5) * 2.0;
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..8288fc5fe9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ c = abs(fract(c) - 0.5) * 2.0;
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..7df7e9d88f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ c = abs((c - floor(c)) - 0.5) * 2.0;
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..8c702a8257
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ c = abs(fract(c) - 0.5) * 2.0;
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..1f81541af7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec2_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ c = abs((c - floor(c)) - 0.5) * 2.0;
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..30ce9d00dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ c = abs(fract(c) - 0.5) * 2.0;
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..f11dcf5f21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ c = abs((c - floor(c)) - 0.5) * 2.0;
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..1a2ef5d454
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ c = abs(fract(c) - 0.5) * 2.0;
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..69dbc4ef9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/fract_vec3_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ c = abs((c - floor(c)) - 0.5) * 2.0;
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/input.run.txt
new file mode 100644
index 0000000000..74ccc68b54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/fract/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+fract_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_frag.frag
new file mode 100644
index 0000000000..a3f81289c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_frag.frag
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+
+
+void qualifiers(in float a[4], out float b[4], inout float c[4], const in float d[4], float e[4])
+{
+ b[0] = a[0];
+ c[0] += d[0];
+ a[0] += 1.0;
+ e[0] += 1.0;
+
+ b[1] = a[1];
+ c[1] += d[1];
+ a[1] += 1.0;
+ e[1] += 1.0;
+
+ b[2] = a[2];
+ c[2] += d[2];
+ a[2] += 1.0;
+ e[2] += 1.0;
+
+ b[3] = a[3];
+ c[3] += d[3];
+ a[3] += 1.0;
+ e[3] += 1.0;
+}
+
+
+
+void main (void)
+{
+ float a[4];
+ float b[4];
+ float c[4];
+ float d[4];
+ float e[4];
+ float q = 0.0;
+ float q2 = 0.0;
+
+ a[0] = 1.0;
+ b[0] = 2.0;
+ c[0] = 3.0;
+ d[0] = 4.0;
+ e[0] = 1.0;
+
+ a[1] = 1.0;
+ b[1] = 2.0;
+ c[1] = 3.0;
+ d[1] = 4.0;
+ e[1] = 1.0;
+
+ a[2] = 1.0;
+ b[2] = 2.0;
+ c[2] = 3.0;
+ d[2] = 4.0;
+ e[2] = 1.0;
+
+ a[3] = 1.0;
+ b[3] = 2.0;
+ c[3] = 3.0;
+ d[3] = 4.0;
+ e[3] = 1.0;
+
+ qualifiers(a, b, c, d, e);
+
+ // randomly test a value
+ if(a[0] == 1.0) q += 1.0;
+ if(b[1] == 1.0) q += 2.0;
+ if(c[2] == 7.0) q += 4.0;
+ if(d[3] == 4.0) q2 += 1.0;
+ if(e[0] == 1.0) q2 += 2.0;
+
+ gl_FragColor = vec4(vec2(q / 7.0, q2 / 3.0), 1.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_vert.vert
new file mode 100644
index 0000000000..79493b346f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/array_float_vert.vert
@@ -0,0 +1,86 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+void qualifiers(in float a[4], out float b[4], inout float c[4], const in float d[4], float e[4])
+{
+ b[0] = a[0];
+ c[0] += d[0];
+ a[0] += 1.0;
+ e[0] += 1.0;
+
+ b[1] = a[1];
+ c[1] += d[1];
+ a[1] += 1.0;
+ e[1] += 1.0;
+
+ b[2] = a[2];
+ c[2] += d[2];
+ a[2] += 1.0;
+ e[2] += 1.0;
+
+ b[3] = a[3];
+ c[3] += d[3];
+ a[3] += 1.0;
+ e[3] += 1.0;
+}
+
+
+
+
+void main (void)
+{
+ float a[4];
+ float b[4];
+ float c[4];
+ float d[4];
+ float e[4];
+ float q = 0.0;
+ float q2 = 0.0;
+
+ a[0] = 1.0;
+ b[0] = 2.0;
+ c[0] = 3.0;
+ d[0] = 4.0;
+ e[0] = 1.0;
+
+ a[1] = 1.0;
+ b[1] = 2.0;
+ c[1] = 3.0;
+ d[1] = 4.0;
+ e[1] = 1.0;
+
+ a[2] = 1.0;
+ b[2] = 2.0;
+ c[2] = 3.0;
+ d[2] = 4.0;
+ e[2] = 1.0;
+
+ a[3] = 1.0;
+ b[3] = 2.0;
+ c[3] = 3.0;
+ d[3] = 4.0;
+ e[3] = 1.0;
+
+ qualifiers(a, b, c, d, e);
+
+ // randomly test a value
+ if(a[0] == 1.0) q += 1.0;
+ if(b[1] == 1.0) q += 2.0;
+ if(c[2] == 7.0) q += 4.0;
+ if(d[3] == 4.0) q2 += 1.0;
+ if(e[0] == 1.0) q2 += 2.0;
+
+ color = vec4(vec2(q / 7.0, q2 / 3.0), 1.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_frag.frag
new file mode 100644
index 0000000000..17aab5dd42
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bool function(bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+bool function(bool par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_vert.vert
new file mode 100644
index 0000000000..588457ecde
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bool function(bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+bool function(bool par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_frag.frag
new file mode 100644
index 0000000000..45cec23fd6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bool function(bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(par && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(bool par)
+{
+ // Return the value of the parameter.
+ if(par)
+ {
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_vert.vert
new file mode 100644
index 0000000000..6e8ef52a31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_empty_bool_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bool function(bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(par && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(bool par)
+{
+ // Return the value of the parameter.
+ if(par)
+ {
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_frag.frag
new file mode 100644
index 0000000000..5444ddb914
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bool function(in bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(in bool par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_vert.vert
new file mode 100644
index 0000000000..9494f5f61b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bool function(in bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(in bool par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_frag.frag
new file mode 100644
index 0000000000..432124dabb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bool function(in bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(par && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(in bool par)
+{
+ // Return the value of the parameter.
+ if(par)
+ {
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_vert.vert
new file mode 100644
index 0000000000..7027edc7b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_in_bool_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bool function(in bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(par && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(in bool par)
+{
+ // Return the value of the parameter.
+ if(par)
+ {
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_frag.frag
new file mode 100644
index 0000000000..793e765b15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bool function(inout bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(inout bool par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_vert.vert
new file mode 100644
index 0000000000..e881eda25b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bool function(inout bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(inout bool par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_frag.frag
new file mode 100644
index 0000000000..cb20cb4604
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bool function(inout bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(!par && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(inout bool par)
+{
+ // Return the value of the parameter.
+ if(par)
+ {
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_vert.vert
new file mode 100644
index 0000000000..a1a9597bc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_inout_bool_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bool function(inout bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(!par && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(inout bool par)
+{
+ // Return the value of the parameter.
+ if(par)
+ {
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_frag.frag
new file mode 100644
index 0000000000..aa7e08b1cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_frag.frag
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bool function(out bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(out bool par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_vert.vert
new file mode 100644
index 0000000000..485c22e687
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_array_vert.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bool function(out bool par[3]);
+bool is_all(const in bool array[3], const in bool value);
+void set_all(out bool array[3], const in bool value);
+
+void main (void)
+{
+ bool par[3];
+ bool ret = false;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, true);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(out bool par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return true;
+}
+
+bool is_all(const in bool array[3], const in bool value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bool array[3], const in bool value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_frag.frag
new file mode 100644
index 0000000000..2c0ffe7410
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_frag.frag
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bool function(out bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(!par && ret)
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bool function(out bool par)
+{
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_vert.vert
new file mode 100644
index 0000000000..21510b94bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bool_empty_out_bool_empty_vert.vert
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bool function(out bool par);
+
+void main (void)
+{
+ bool par = true;
+ bool ret = false;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(!par && ret)
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bool function(out bool par)
+{
+ // Test parameter qualifier (default is "in").
+ par = false;
+
+ return true;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_frag.frag
new file mode 100644
index 0000000000..269f051e0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, bvec4(true, true, true, true)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+bvec4 function(bvec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_vert.vert
new file mode 100644
index 0000000000..ce77807866
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, bvec4(true, true, true, true)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+bvec4 function(bvec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_frag.frag
new file mode 100644
index 0000000000..3bab4609dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bvec4 function(bvec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_vert.vert
new file mode 100644
index 0000000000..36ac4882ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_empty_bvec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bvec4 function(bvec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_frag.frag
new file mode 100644
index 0000000000..360cbd268c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(in bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, bvec4(true, true, true, true)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+bvec4 function(in bvec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_vert.vert
new file mode 100644
index 0000000000..bd8fb8cd83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(in bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, bvec4(true, true, true, true)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+bvec4 function(in bvec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_frag.frag
new file mode 100644
index 0000000000..79b00fb08e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(in bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bvec4 function(in bvec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_vert.vert
new file mode 100644
index 0000000000..a0c0379b20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_in_bvec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(in bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return true.
+ if(is_all(par, true) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bvec4 function(in bvec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_frag.frag
new file mode 100644
index 0000000000..571268392c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(inout bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, bvec4(false, false, false, false)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+bvec4 function(inout bvec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_vert.vert
new file mode 100644
index 0000000000..3d4974f447
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(inout bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, bvec4(false, false, false, false)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+bvec4 function(inout bvec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_frag.frag
new file mode 100644
index 0000000000..d4ede0875f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_frag.frag
@@ -0,0 +1,112 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(inout bvec4 par[10]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[10], const in bvec4 value);
+void set_all(out bvec4 array[10], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[10];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, bvec4(false, false, false, false)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+bvec4 function(inout bvec4 par[10])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[10], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+ if(array[3] != value)
+ ret = false;
+ if(array[4] != value)
+ ret = false;
+ if(array[5] != value)
+ ret = false;
+ if(array[6] != value)
+ ret = false;
+ if(array[7] != value)
+ ret = false;
+ if(array[8] != value)
+ ret = false;
+ if(array[9] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[10], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+ array[3] = value;
+ array[4] = value;
+ array[5] = value;
+ array[6] = value;
+ array[7] = value;
+ array[8] = value;
+ array[9] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_vert.vert
new file mode 100644
index 0000000000..7107c7b67d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_bigarray_vert.vert
@@ -0,0 +1,112 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(inout bvec4 par[10]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[10], const in bvec4 value);
+void set_all(out bvec4 array[10], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[10];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, bvec4(false, false, false, false)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+bvec4 function(inout bvec4 par[10])
+{
+ // Return the value of the array.
+ if(is_all(par, bvec4(true, true, true, true)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[10], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+ if(array[3] != value)
+ ret = false;
+ if(array[4] != value)
+ ret = false;
+ if(array[5] != value)
+ ret = false;
+ if(array[6] != value)
+ ret = false;
+ if(array[7] != value)
+ ret = false;
+ if(array[8] != value)
+ ret = false;
+ if(array[9] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[10], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+ array[3] = value;
+ array[4] = value;
+ array[5] = value;
+ array[6] = value;
+ array[7] = value;
+ array[8] = value;
+ array[9] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_frag.frag
new file mode 100644
index 0000000000..f592dbafea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(inout bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bvec4 function(inout bvec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_vert.vert
new file mode 100644
index 0000000000..3983515e5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_inout_bvec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(inout bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bvec4 function(inout bvec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, true))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+ }
+ else
+ return bvec4(false, false, false, false);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_frag.frag
new file mode 100644
index 0000000000..e729340ad5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_frag.frag
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(out bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, bvec4(false, false, false, false)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+bvec4 function(out bvec4 par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_vert.vert
new file mode 100644
index 0000000000..6146e5ba68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_array_vert.vert
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+bvec4 function(out bvec4 par[3]);
+bool is_all(const in bvec4 par, const in bool value);
+bool is_all(const in bvec4 array[3], const in bvec4 value);
+void set_all(out bvec4 array[3], const in bvec4 value);
+
+void main (void)
+{
+ bvec4 par[3];
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to true.
+ set_all(par, bvec4(true, true, true, true));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, bvec4(false, false, false, false)) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+bvec4 function(out bvec4 par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, bvec4(false, false, false, false));
+
+ return bvec4(true, true, true, true);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in bvec4 array[3], const in bvec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 array[3], const in bvec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_frag.frag
new file mode 100644
index 0000000000..b5cae27c4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_frag.frag
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(out bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+bvec4 function(out bvec4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_vert.vert
new file mode 100644
index 0000000000..172df26f56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/bvec4_empty_out_bvec4_empty_vert.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+bvec4 function(out bvec4 par);
+bool is_all(const in bvec4 par, const in bool value);
+void set_all(out bvec4 par, const in bool value);
+
+void main (void)
+{
+ bvec4 par = bvec4(true, true, true, true);
+ bvec4 ret = bvec4(false, false, false, false);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return true.
+ if(is_all(par, false) && is_all(ret, true))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+bvec4 function(out bvec4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, false);
+
+ return bvec4(true, true, true, true);
+}
+
+bool is_all(const in bvec4 par, const in bool value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out bvec4 par, const in bool value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_frag.frag
new file mode 100644
index 0000000000..ce4b5ec188
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+float function(float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+float function(float par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_vert.vert
new file mode 100644
index 0000000000..fbdca2f413
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+float function(float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+float function(float par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_frag.frag
new file mode 100644
index 0000000000..73893e49b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+float function(float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if((par == 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(float par)
+{
+ // Return the value of the parameter.
+ if(par == 1.0)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_vert.vert
new file mode 100644
index 0000000000..e8adae115d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_empty_float_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+float function(float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if((par == 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(float par)
+{
+ // Return the value of the parameter.
+ if(par == 1.0)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_frag.frag
new file mode 100644
index 0000000000..ec02504e37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+float function(in float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(in float par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_vert.vert
new file mode 100644
index 0000000000..44617e0cfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+float function(in float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(in float par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_frag.frag
new file mode 100644
index 0000000000..ae16d2fd72
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+float function(in float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if((par == 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(in float par)
+{
+ // Return the value of the parameter.
+ if(par == 1.0)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_vert.vert
new file mode 100644
index 0000000000..cb5194e9a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_in_float_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+float function(in float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if((par == 1.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(in float par)
+{
+ // Return the value of the parameter.
+ if(par == 1.0)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_frag.frag
new file mode 100644
index 0000000000..ba3d159934
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+float function(inout float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(inout float par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_vert.vert
new file mode 100644
index 0000000000..28f9778f02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+float function(inout float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(inout float par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_frag.frag
new file mode 100644
index 0000000000..c0f08f4ed5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+float function(inout float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if((par == 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(inout float par)
+{
+ // Return the value of the parameter.
+ if(par == 1.0)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_vert.vert
new file mode 100644
index 0000000000..a4ccd8b159
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_inout_float_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+float function(inout float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if((par == 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(inout float par)
+{
+ // Return the value of the parameter.
+ if(par == 1.0)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+ }
+ else
+ return 0.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_frag.frag
new file mode 100644
index 0000000000..7a8b3b2e34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_frag.frag
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+float function(out float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(out float par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_vert.vert
new file mode 100644
index 0000000000..5bcd67d5ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_array_vert.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+float function(out float par[3]);
+bool is_all(const in float array[3], const in float value);
+void set_all(out float array[3], const in float value);
+
+void main (void)
+{
+ float par[3];
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, 1.0);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(out float par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return 1.0;
+}
+
+bool is_all(const in float array[3], const in float value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out float array[3], const in float value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_frag.frag
new file mode 100644
index 0000000000..fc7870209f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_frag.frag
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+float function(out float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if((par == 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+float function(out float par)
+{
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_vert.vert
new file mode 100644
index 0000000000..a9f4da5dd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/float_empty_out_float_empty_vert.vert
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+float function(out float par);
+
+void main (void)
+{
+ float par = 1.0;
+ float ret = 0.0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if((par == 0.0) && (ret == 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+float function(out float par)
+{
+ // Test parameter qualifier (default is "in").
+ par = 0.0;
+
+ return 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_001_to_008.html
new file mode 100644
index 0000000000..c4a96140a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "qualifiers_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "qualifiers_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "qualifiers_float_frag.frag"
+ },
+ "name": "qualifiers_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "qualifiers_struct_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "qualifiers_struct_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "qualifiers_struct_frag.frag"
+ },
+ "name": "qualifiers_struct_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "array_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "array_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array_float_frag.frag"
+ },
+ "name": "array_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "void_empty_empty_void_empty_frag.frag"
+ },
+ "name": "void_empty_empty_void_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "void_empty_empty_void_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "void_empty_empty_void_empty_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_009_to_016.html
new file mode 100644
index 0000000000..07308dbe1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_009_to_016.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_empty_bool_empty_frag.frag"
+ },
+ "name": "bool_empty_empty_bool_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_empty_bool_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_empty_bool_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_empty_bool_array_frag.frag"
+ },
+ "name": "bool_empty_empty_bool_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_empty_bool_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_empty_bool_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_in_bool_empty_frag.frag"
+ },
+ "name": "bool_empty_in_bool_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_in_bool_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_in_bool_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_in_bool_array_frag.frag"
+ },
+ "name": "bool_empty_in_bool_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_in_bool_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_in_bool_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_017_to_024.html
new file mode 100644
index 0000000000..9433423860
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_017_to_024.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_inout_bool_empty_frag.frag"
+ },
+ "name": "bool_empty_inout_bool_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_inout_bool_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_inout_bool_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_inout_bool_array_frag.frag"
+ },
+ "name": "bool_empty_inout_bool_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_inout_bool_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_inout_bool_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_out_bool_empty_frag.frag"
+ },
+ "name": "bool_empty_out_bool_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_out_bool_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_out_bool_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bool_empty_out_bool_array_frag.frag"
+ },
+ "name": "bool_empty_out_bool_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bool_empty_out_bool_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bool_empty_out_bool_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_025_to_032.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_025_to_032.html
new file mode 100644
index 0000000000..f8fd671a46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_025_to_032.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_025_to_032.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_empty_int_empty_frag.frag"
+ },
+ "name": "int_empty_empty_int_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_empty_int_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_empty_int_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_empty_int_array_frag.frag"
+ },
+ "name": "int_empty_empty_int_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_empty_int_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_empty_int_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_in_int_empty_frag.frag"
+ },
+ "name": "int_empty_in_int_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_in_int_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_in_int_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_in_int_array_frag.frag"
+ },
+ "name": "int_empty_in_int_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_in_int_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_in_int_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_033_to_040.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_033_to_040.html
new file mode 100644
index 0000000000..6b54e7d96b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_033_to_040.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_033_to_040.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_inout_int_empty_frag.frag"
+ },
+ "name": "int_empty_inout_int_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_inout_int_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_inout_int_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_inout_int_array_frag.frag"
+ },
+ "name": "int_empty_inout_int_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_inout_int_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_inout_int_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_out_int_empty_frag.frag"
+ },
+ "name": "int_empty_out_int_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_out_int_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_out_int_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "int_empty_out_int_array_frag.frag"
+ },
+ "name": "int_empty_out_int_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "int_empty_out_int_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "int_empty_out_int_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_041_to_048.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_041_to_048.html
new file mode 100644
index 0000000000..cc41133577
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_041_to_048.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_041_to_048.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_empty_float_empty_frag.frag"
+ },
+ "name": "float_empty_empty_float_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_empty_float_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_empty_float_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_empty_float_array_frag.frag"
+ },
+ "name": "float_empty_empty_float_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_empty_float_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_empty_float_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_in_float_empty_frag.frag"
+ },
+ "name": "float_empty_in_float_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_in_float_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_in_float_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_in_float_array_frag.frag"
+ },
+ "name": "float_empty_in_float_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_in_float_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_in_float_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_049_to_056.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_049_to_056.html
new file mode 100644
index 0000000000..a78074c302
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_049_to_056.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_049_to_056.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_inout_float_empty_frag.frag"
+ },
+ "name": "float_empty_inout_float_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_inout_float_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_inout_float_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_inout_float_array_frag.frag"
+ },
+ "name": "float_empty_inout_float_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_inout_float_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_inout_float_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_out_float_empty_frag.frag"
+ },
+ "name": "float_empty_out_float_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_out_float_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_out_float_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "float_empty_out_float_array_frag.frag"
+ },
+ "name": "float_empty_out_float_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "float_empty_out_float_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "float_empty_out_float_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_057_to_064.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_057_to_064.html
new file mode 100644
index 0000000000..05e1e9b9f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_057_to_064.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_057_to_064.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_empty_bvec4_empty_frag.frag"
+ },
+ "name": "bvec4_empty_empty_bvec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_empty_bvec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_empty_bvec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_empty_bvec4_array_frag.frag"
+ },
+ "name": "bvec4_empty_empty_bvec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_empty_bvec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_empty_bvec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_in_bvec4_empty_frag.frag"
+ },
+ "name": "bvec4_empty_in_bvec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_in_bvec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_in_bvec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_in_bvec4_array_frag.frag"
+ },
+ "name": "bvec4_empty_in_bvec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_in_bvec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_in_bvec4_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_065_to_072.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_065_to_072.html
new file mode 100644
index 0000000000..85a1425d58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_065_to_072.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_065_to_072.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_inout_bvec4_empty_frag.frag"
+ },
+ "name": "bvec4_empty_inout_bvec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_inout_bvec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_inout_bvec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_inout_bvec4_array_frag.frag"
+ },
+ "name": "bvec4_empty_inout_bvec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_inout_bvec4_bigarray_frag.frag"
+ },
+ "name": "bvec4_empty_inout_bvec4_bigarray_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_inout_bvec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_inout_bvec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_inout_bvec4_bigarray_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_inout_bvec4_bigarray_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_out_bvec4_empty_frag.frag"
+ },
+ "name": "bvec4_empty_out_bvec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_out_bvec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_out_bvec4_empty_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_073_to_080.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_073_to_080.html
new file mode 100644
index 0000000000..6d8d5a69ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_073_to_080.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_073_to_080.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_empty_out_bvec4_array_frag.frag"
+ },
+ "name": "bvec4_empty_out_bvec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_empty_out_bvec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_empty_out_bvec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_empty_ivec4_empty_frag.frag"
+ },
+ "name": "ivec4_empty_empty_ivec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_empty_ivec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_empty_ivec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_empty_ivec4_array_frag.frag"
+ },
+ "name": "ivec4_empty_empty_ivec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_empty_ivec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_empty_ivec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_in_ivec4_empty_frag.frag"
+ },
+ "name": "ivec4_empty_in_ivec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_in_ivec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_in_ivec4_empty_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_081_to_088.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_081_to_088.html
new file mode 100644
index 0000000000..9fc2a45079
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_081_to_088.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_081_to_088.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_in_ivec4_array_frag.frag"
+ },
+ "name": "ivec4_empty_in_ivec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_in_ivec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_in_ivec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_inout_ivec4_empty_frag.frag"
+ },
+ "name": "ivec4_empty_inout_ivec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_inout_ivec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_inout_ivec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_inout_ivec4_array_frag.frag"
+ },
+ "name": "ivec4_empty_inout_ivec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_inout_ivec4_bigarray_frag.frag"
+ },
+ "name": "ivec4_empty_inout_ivec4_bigarray_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_inout_ivec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_inout_ivec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_inout_ivec4_bigarray_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_inout_ivec4_bigarray_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_089_to_096.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_089_to_096.html
new file mode 100644
index 0000000000..df95fcdace
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_089_to_096.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_089_to_096.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_out_ivec4_empty_frag.frag"
+ },
+ "name": "ivec4_empty_out_ivec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_out_ivec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_out_ivec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec4_empty_out_ivec4_array_frag.frag"
+ },
+ "name": "ivec4_empty_out_ivec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec4_empty_out_ivec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec4_empty_out_ivec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_empty_vec4_empty_frag.frag"
+ },
+ "name": "vec4_empty_empty_vec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_empty_vec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_empty_vec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_empty_vec4_array_frag.frag"
+ },
+ "name": "vec4_empty_empty_vec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_empty_vec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_empty_vec4_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_097_to_104.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_097_to_104.html
new file mode 100644
index 0000000000..ecb3f995f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_097_to_104.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_097_to_104.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_in_vec4_empty_frag.frag"
+ },
+ "name": "vec4_empty_in_vec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_in_vec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_in_vec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_in_vec4_array_frag.frag"
+ },
+ "name": "vec4_empty_in_vec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_in_vec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_in_vec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_inout_vec4_empty_frag.frag"
+ },
+ "name": "vec4_empty_inout_vec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_inout_vec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_inout_vec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_inout_vec4_array_frag.frag"
+ },
+ "name": "vec4_empty_inout_vec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_inout_vec4_bigarray_frag.frag"
+ },
+ "name": "vec4_empty_inout_vec4_bigarray_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_105_to_112.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_105_to_112.html
new file mode 100644
index 0000000000..0c11edbe92
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_105_to_112.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_105_to_112.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_inout_vec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_inout_vec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_inout_vec4_bigarray_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_inout_vec4_bigarray_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_out_vec4_empty_frag.frag"
+ },
+ "name": "vec4_empty_out_vec4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_out_vec4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_out_vec4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_empty_out_vec4_array_frag.frag"
+ },
+ "name": "vec4_empty_out_vec4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_empty_out_vec4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_empty_out_vec4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_empty_mat4_empty_frag.frag"
+ },
+ "name": "mat4_empty_empty_mat4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_empty_mat4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_empty_mat4_empty_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_113_to_120.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_113_to_120.html
new file mode 100644
index 0000000000..aab1f2991e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_113_to_120.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_113_to_120.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_empty_mat4_array_frag.frag"
+ },
+ "name": "mat4_empty_empty_mat4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_empty_mat4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_empty_mat4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_in_mat4_empty_frag.frag"
+ },
+ "name": "mat4_empty_in_mat4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_in_mat4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_in_mat4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_in_mat4_array_frag.frag"
+ },
+ "name": "mat4_empty_in_mat4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_in_mat4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_in_mat4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_inout_mat4_empty_frag.frag"
+ },
+ "name": "mat4_empty_inout_mat4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_inout_mat4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_inout_mat4_empty_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_121_to_126.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_121_to_126.html
new file mode 100644
index 0000000000..31d06809d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/functions_121_to_126.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: functions_121_to_126.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_inout_mat4_array_frag.frag"
+ },
+ "name": "mat4_empty_inout_mat4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_inout_mat4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_inout_mat4_array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_out_mat4_empty_frag.frag"
+ },
+ "name": "mat4_empty_out_mat4_empty_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_out_mat4_empty_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_out_mat4_empty_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_empty_out_mat4_array_frag.frag"
+ },
+ "name": "mat4_empty_out_mat4_array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_empty_out_mat4_array_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_empty_out_mat4_array_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/input.run.txt
new file mode 100644
index 0000000000..00b4fa8fa6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/input.run.txt
@@ -0,0 +1,17 @@
+# this file is auto-generated. DO NOT EDIT.
+functions_001_to_008.html
+functions_009_to_016.html
+functions_017_to_024.html
+functions_025_to_032.html
+functions_033_to_040.html
+functions_041_to_048.html
+functions_049_to_056.html
+functions_057_to_064.html
+functions_065_to_072.html
+functions_073_to_080.html
+functions_081_to_088.html
+functions_089_to_096.html
+functions_097_to_104.html
+functions_105_to_112.html
+functions_113_to_120.html
+functions_121_to_126.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_frag.frag
new file mode 100644
index 0000000000..ed0cd8448a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+int function(int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+int function(int par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_vert.vert
new file mode 100644
index 0000000000..14c6e128ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+int function(int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+int function(int par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_frag.frag
new file mode 100644
index 0000000000..65da05bbb0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+int function(int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if((par == 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(int par)
+{
+ // Return the value of the parameter.
+ if(par == 1)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_vert.vert
new file mode 100644
index 0000000000..7bda7a7e29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_empty_int_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+int function(int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if((par == 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(int par)
+{
+ // Return the value of the parameter.
+ if(par == 1)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_frag.frag
new file mode 100644
index 0000000000..e57c9fa1d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+int function(in int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(in int par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_vert.vert
new file mode 100644
index 0000000000..df6e4a1bb4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+int function(in int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(in int par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_frag.frag
new file mode 100644
index 0000000000..f231711c7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+int function(in int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if((par == 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(in int par)
+{
+ // Return the value of the parameter.
+ if(par == 1)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_vert.vert
new file mode 100644
index 0000000000..595313758e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_in_int_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+int function(in int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if((par == 1) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(in int par)
+{
+ // Return the value of the parameter.
+ if(par == 1)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_frag.frag
new file mode 100644
index 0000000000..f68223b0ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+int function(inout int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(inout int par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_vert.vert
new file mode 100644
index 0000000000..d4bb19272a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_array_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+int function(inout int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(inout int par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_frag.frag
new file mode 100644
index 0000000000..a9ff21b164
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+int function(inout int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if((par == 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(inout int par)
+{
+ // Return the value of the parameter.
+ if(par == 1)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_vert.vert
new file mode 100644
index 0000000000..81a43a3a84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_inout_int_empty_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+int function(inout int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if((par == 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(inout int par)
+{
+ // Return the value of the parameter.
+ if(par == 1)
+ {
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_frag.frag
new file mode 100644
index 0000000000..aa2c2c04b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_frag.frag
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+int function(out int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(out int par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_vert.vert
new file mode 100644
index 0000000000..ecbd64bcf2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_array_vert.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+int function(out int par[3]);
+bool is_all(const in int array[3], const in int value);
+void set_all(out int array[3], const in int value);
+
+void main (void)
+{
+ int par[3];
+ int ret = 0;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, 1);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(out int par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return 1;
+}
+
+bool is_all(const in int array[3], const in int value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out int array[3], const in int value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_frag.frag
new file mode 100644
index 0000000000..55bc54d191
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_frag.frag
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+int function(out int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if((par == 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+int function(out int par)
+{
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_vert.vert
new file mode 100644
index 0000000000..efe8841aba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/int_empty_out_int_empty_vert.vert
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+int function(out int par);
+
+void main (void)
+{
+ int par = 1;
+ int ret = 0;
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if((par == 0) && (ret == 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+int function(out int par)
+{
+ // Test parameter qualifier (default is "in").
+ par = 0;
+
+ return 1;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_frag.frag
new file mode 100644
index 0000000000..2f33f935e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, ivec4(1, 1, 1, 1)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+ivec4 function(ivec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_vert.vert
new file mode 100644
index 0000000000..8b6b5703dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, ivec4(1, 1, 1, 1)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+ivec4 function(ivec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_frag.frag
new file mode 100644
index 0000000000..f23078171e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+ivec4 function(ivec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_vert.vert
new file mode 100644
index 0000000000..20e691c73a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_empty_ivec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+ivec4 function(ivec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_frag.frag
new file mode 100644
index 0000000000..5fbcd07600
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(in ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, ivec4(1, 1, 1, 1)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+ivec4 function(in ivec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_vert.vert
new file mode 100644
index 0000000000..ef859a4f61
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(in ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, ivec4(1, 1, 1, 1)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+ivec4 function(in ivec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_frag.frag
new file mode 100644
index 0000000000..273424504f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(in ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+ivec4 function(in ivec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_vert.vert
new file mode 100644
index 0000000000..29840bd98c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_in_ivec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(in ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.
+ if(is_all(par, 1) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+ivec4 function(in ivec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_frag.frag
new file mode 100644
index 0000000000..120d99b4ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(inout ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, ivec4(0, 0, 0, 0)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+ivec4 function(inout ivec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_vert.vert
new file mode 100644
index 0000000000..27f136927c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(inout ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, ivec4(0, 0, 0, 0)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+ivec4 function(inout ivec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_frag.frag
new file mode 100644
index 0000000000..091ca82e94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_frag.frag
@@ -0,0 +1,112 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(inout ivec4 par[10]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[10], const in ivec4 value);
+void set_all(out ivec4 array[10], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[10];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, ivec4(0, 0, 0, 0)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+ivec4 function(inout ivec4 par[10])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[10], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+ if(array[3] != value)
+ ret = false;
+ if(array[4] != value)
+ ret = false;
+ if(array[5] != value)
+ ret = false;
+ if(array[6] != value)
+ ret = false;
+ if(array[7] != value)
+ ret = false;
+ if(array[8] != value)
+ ret = false;
+ if(array[9] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[10], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+ array[3] = value;
+ array[4] = value;
+ array[5] = value;
+ array[6] = value;
+ array[7] = value;
+ array[8] = value;
+ array[9] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_vert.vert
new file mode 100644
index 0000000000..08e15a0451
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_bigarray_vert.vert
@@ -0,0 +1,112 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(inout ivec4 par[10]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[10], const in ivec4 value);
+void set_all(out ivec4 array[10], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[10];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, ivec4(0, 0, 0, 0)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+ivec4 function(inout ivec4 par[10])
+{
+ // Return the value of the array.
+ if(is_all(par, ivec4(1, 1, 1, 1)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[10], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+ if(array[3] != value)
+ ret = false;
+ if(array[4] != value)
+ ret = false;
+ if(array[5] != value)
+ ret = false;
+ if(array[6] != value)
+ ret = false;
+ if(array[7] != value)
+ ret = false;
+ if(array[8] != value)
+ ret = false;
+ if(array[9] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[10], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+ array[3] = value;
+ array[4] = value;
+ array[5] = value;
+ array[6] = value;
+ array[7] = value;
+ array[8] = value;
+ array[9] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_frag.frag
new file mode 100644
index 0000000000..4714af5f98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(inout ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+ivec4 function(inout ivec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_vert.vert
new file mode 100644
index 0000000000..d51f33952b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_inout_ivec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(inout ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+ivec4 function(inout ivec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+ }
+ else
+ return ivec4(0, 0, 0, 0);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_frag.frag
new file mode 100644
index 0000000000..cb968348b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_frag.frag
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(out ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, ivec4(0, 0, 0, 0)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+ivec4 function(out ivec4 par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_vert.vert
new file mode 100644
index 0000000000..398a683e27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_array_vert.vert
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+ivec4 function(out ivec4 par[3]);
+bool is_all(const in ivec4 par, const in int value);
+bool is_all(const in ivec4 array[3], const in ivec4 value);
+void set_all(out ivec4 array[3], const in ivec4 value);
+
+void main (void)
+{
+ ivec4 par[3];
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.
+ set_all(par, ivec4(1, 1, 1, 1));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, ivec4(0, 0, 0, 0)) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+ivec4 function(out ivec4 par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, ivec4(0, 0, 0, 0));
+
+ return ivec4(1, 1, 1, 1);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in ivec4 array[3], const in ivec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 array[3], const in ivec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_frag.frag
new file mode 100644
index 0000000000..d74a722f6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_frag.frag
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(out ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+ivec4 function(out ivec4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_vert.vert
new file mode 100644
index 0000000000..34ff61d5d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/ivec4_empty_out_ivec4_empty_vert.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+ivec4 function(out ivec4 par);
+bool is_all(const in ivec4 par, const in int value);
+void set_all(out ivec4 par, const in int value);
+
+void main (void)
+{
+ ivec4 par = ivec4(1, 1, 1, 1);
+ ivec4 ret = ivec4(0, 0, 0, 0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.
+ if(is_all(par, 0) && is_all(ret, 1))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+ivec4 function(out ivec4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0);
+
+ return ivec4(1, 1, 1, 1);
+}
+
+bool is_all(const in ivec4 par, const in int value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out ivec4 par, const in int value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_frag.frag
new file mode 100644
index 0000000000..f2f0704cd4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_frag.frag
@@ -0,0 +1,124 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, mat_ones) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+mat4 function(mat4 par[2])
+{
+ // Return the value of the array.
+ if(is_all(par, mat_ones))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+ }
+ else
+ return mat_zeros;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_vert.vert
new file mode 100644
index 0000000000..ff293ced8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_array_vert.vert
@@ -0,0 +1,124 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, mat_ones) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+mat4 function(mat4 par[2])
+{
+ // Return the value of the array.
+ if(is_all(par, mat_ones))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+ }
+ else
+ return mat_zeros;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_frag.frag
new file mode 100644
index 0000000000..4a075bad93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_frag.frag
@@ -0,0 +1,128 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+mat4 function(mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+mat4 function(mat4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_vert.vert
new file mode 100644
index 0000000000..bbbcf59ece
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_empty_mat4_empty_vert.vert
@@ -0,0 +1,128 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+mat4 function(mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+mat4 function(mat4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_frag.frag
new file mode 100644
index 0000000000..c7eac72b97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_frag.frag
@@ -0,0 +1,124 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(in mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, mat_ones) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+mat4 function(in mat4 par[2])
+{
+ // Return the value of the array.
+ if(is_all(par, mat_ones))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+ }
+ else
+ return mat_zeros;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_vert.vert
new file mode 100644
index 0000000000..0b57cc9907
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_array_vert.vert
@@ -0,0 +1,124 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(in mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, mat_ones) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+mat4 function(in mat4 par[2])
+{
+ // Return the value of the array.
+ if(is_all(par, mat_ones))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+ }
+ else
+ return mat_zeros;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_frag.frag
new file mode 100644
index 0000000000..87cb50e8a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_frag.frag
@@ -0,0 +1,128 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+mat4 function(in mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+mat4 function(in mat4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_vert.vert
new file mode 100644
index 0000000000..b78e227891
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_in_mat4_empty_vert.vert
@@ -0,0 +1,128 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+mat4 function(in mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+mat4 function(in mat4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_frag.frag
new file mode 100644
index 0000000000..1fd7215414
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_frag.frag
@@ -0,0 +1,124 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(inout mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, mat_zeros) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+mat4 function(inout mat4 par[2])
+{
+ // Return the value of the array.
+ if(is_all(par, mat_ones))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+ }
+ else
+ return mat_zeros;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_vert.vert
new file mode 100644
index 0000000000..d2e6f02581
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_array_vert.vert
@@ -0,0 +1,124 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(inout mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, mat_zeros) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+mat4 function(inout mat4 par[2])
+{
+ // Return the value of the array.
+ if(is_all(par, mat_ones))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+ }
+ else
+ return mat_zeros;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_frag.frag
new file mode 100644
index 0000000000..8aee0309fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_frag.frag
@@ -0,0 +1,128 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+mat4 function(inout mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+mat4 function(inout mat4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_vert.vert
new file mode 100644
index 0000000000..210f5addb6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_inout_mat4_empty_vert.vert
@@ -0,0 +1,128 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+mat4 function(inout mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+mat4 function(inout mat4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_frag.frag
new file mode 100644
index 0000000000..52ece666f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_frag.frag
@@ -0,0 +1,118 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(out mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, mat_zeros) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+mat4 function(out mat4 par[2])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_vert.vert
new file mode 100644
index 0000000000..ee52d45730
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_array_vert.vert
@@ -0,0 +1,118 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const mat4 mat_ones = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+const mat4 mat_zeros = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+// Function declarations.
+mat4 function(out mat4 par[2]);
+bool is_all(const in mat4 par, const in float value);
+bool is_all(const in mat4 array[2], const in mat4 value);
+void set_all(out mat4 array[2], const in mat4 value);
+
+void main (void)
+{
+ mat4 par[2];
+ mat4 ret = mat_zeros;
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, mat_ones);
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, mat_zeros) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+mat4 function(out mat4 par[2])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, mat_zeros);
+
+ return mat_ones;
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in mat4 array[2], const in mat4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 array[2], const in mat4 value)
+{
+ array[0] = value;
+ array[1] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_frag.frag
new file mode 100644
index 0000000000..f88bba050b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_frag.frag
@@ -0,0 +1,119 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+mat4 function(out mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+mat4 function(out mat4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_vert.vert
new file mode 100644
index 0000000000..c593be2a56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/mat4_empty_out_mat4_empty_vert.vert
@@ -0,0 +1,119 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+mat4 function(out mat4 par);
+bool is_all(const in mat4 par, const in float value);
+void set_all(out mat4 par, const in float value);
+
+void main (void)
+{
+ mat4 par = mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+ mat4 ret = mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+mat4 function(out mat4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return mat4(1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0);
+}
+
+bool is_all(const in mat4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0][0] != value)
+ ret = false;
+ if(par[0][1] != value)
+ ret = false;
+ if(par[0][2] != value)
+ ret = false;
+ if(par[0][3] != value)
+ ret = false;
+
+ if(par[1][0] != value)
+ ret = false;
+ if(par[1][1] != value)
+ ret = false;
+ if(par[1][2] != value)
+ ret = false;
+ if(par[1][3] != value)
+ ret = false;
+
+ if(par[2][0] != value)
+ ret = false;
+ if(par[2][1] != value)
+ ret = false;
+ if(par[2][2] != value)
+ ret = false;
+ if(par[2][3] != value)
+ ret = false;
+
+ if(par[3][0] != value)
+ ret = false;
+ if(par[3][1] != value)
+ ret = false;
+ if(par[3][2] != value)
+ ret = false;
+ if(par[3][3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out mat4 par, const in float value)
+{
+ par[0][0] = value;
+ par[0][1] = value;
+ par[0][2] = value;
+ par[0][3] = value;
+
+ par[1][0] = value;
+ par[1][1] = value;
+ par[1][2] = value;
+ par[1][3] = value;
+
+ par[2][0] = value;
+ par[2][1] = value;
+ par[2][2] = value;
+ par[2][3] = value;
+
+ par[3][0] = value;
+ par[3][1] = value;
+ par[3][2] = value;
+ par[3][3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_frag.frag
new file mode 100644
index 0000000000..880331e3af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_frag.frag
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+
+
+float qualifiers(in float a, out float b, inout float c, const in float d, float e)
+{
+ b = a;
+ c += d;
+ a += 1.0;
+ return e;
+}
+
+
+
+void main (void)
+{
+ float a = 1.0, b = 2.0, c = 3.0, d = 4.0, e = 1.0, f = 0.0;
+ float q = 0.0;
+ float q2 = 0.0;
+
+ f = qualifiers(a, b, c, d, e);
+
+ if(a == 1.0) q += 1.0;
+ if(b == 1.0) q += 2.0;
+ if(c == 7.0) q += 4.0;
+ if(d == 4.0) q2 += 1.0;
+ if(e == 1.0) q2 += 2.0;
+ if(f == 1.0) q2 += 4.0;
+
+ gl_FragColor = vec4(vec2(q / 7.0, q2 / 7.0), 1.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_vert.vert
new file mode 100644
index 0000000000..5142df2f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_float_vert.vert
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+float qualifiers(in float a, out float b, inout float c, const in float d, float e)
+{
+ b = a;
+ c += d;
+ a += 1.0;
+ return e;
+}
+
+
+
+void main (void)
+{
+ float a = 1.0, b = 2.0, c = 3.0, d = 4.0, e = 1.0, f = 0.0;
+ float q = 0.0;
+ float q2 = 0.0;
+
+ f = qualifiers(a, b, c, d, e);
+
+ if(a == 1.0) q += 1.0;
+ if(b == 1.0) q += 2.0;
+ if(c == 7.0) q += 4.0;
+ if(d == 4.0) q2 += 1.0;
+ if(e == 1.0) q2 += 2.0;
+ if(f == 1.0) q2 += 4.0;
+
+ color = vec4(vec2(q / 7.0, q2 / 7.0), 1.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_frag.frag
new file mode 100644
index 0000000000..6d1a7e75c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+
+
+sabcd qualifiers(in sabcd a, out sabcd b, inout sabcd c, const in sabcd d,
+sabcd e)
+{
+ sabcd one = sabcd(1.0, 1.0, 1.0, 1.0);
+
+ b = a;
+
+ c.a += d.a;
+ c.b += d.b;
+ c.c += d.c;
+ c.d += d.d;
+
+ a.a += one.a;
+ a.b += one.b;
+ a.c += one.c;
+ a.d += one.d;
+
+ return e;
+}
+
+void main (void)
+{
+ sabcd a = sabcd(1.0, 1.0, 1.0, 1.0);
+ sabcd b = sabcd(2.0, 2.0, 2.0, 2.0);
+ sabcd c = sabcd(3.0, 3.0, 3.0, 3.0);
+ sabcd d = sabcd(4.0, 4.0, 4.0, 4.0);
+ sabcd e = sabcd(1.0, 1.0, 1.0, 1.0);
+ sabcd f = sabcd(0.0, 0.0, 0.0, 0.0);
+ sabcd one = sabcd(1.0, 1.0, 1.0, 1.0);
+ sabcd four = sabcd(4.0, 4.0, 4.0, 4.0);
+ sabcd seven = sabcd(7.0, 7.0, 7.0, 7.0);
+ float q = 0.0;
+ float q2 = 0.0;
+
+ f = qualifiers(a, b, c, d, e);
+
+ if(a == one) q += 1.0;
+ if(b == one) q += 2.0;
+ if(c == seven) q += 4.0;
+ if(d == four) q2 += 1.0;
+ if(e == one) q2 += 2.0;
+ if(f == one) q2 += 4.0;
+
+ gl_FragColor = vec4(vec2(q / 7.0, q2 / 7.0), 1.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_vert.vert
new file mode 100644
index 0000000000..201f3f5eff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/qualifiers_struct_vert.vert
@@ -0,0 +1,70 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+
+
+sabcd qualifiers(in sabcd a, out sabcd b, inout sabcd c, const in sabcd d,
+sabcd e)
+{
+ sabcd one = sabcd(1.0, 1.0, 1.0, 1.0);
+
+ b = a;
+
+ c.a += d.a;
+ c.b += d.b;
+ c.c += d.c;
+ c.d += d.d;
+
+ a.a += one.a;
+ a.b += one.b;
+ a.c += one.c;
+ a.d += one.d;
+
+ return e;
+}
+
+void main (void)
+{
+ sabcd a = sabcd(1.0, 1.0, 1.0, 1.0);
+ sabcd b = sabcd(2.0, 2.0, 2.0, 2.0);
+ sabcd c = sabcd(3.0, 3.0, 3.0, 3.0);
+ sabcd d = sabcd(4.0, 4.0, 4.0, 4.0);
+ sabcd e = sabcd(1.0, 1.0, 1.0, 1.0);
+ sabcd f = sabcd(0.0, 0.0, 0.0, 0.0);
+ sabcd one = sabcd(1.0, 1.0, 1.0, 1.0);
+ sabcd four = sabcd(4.0, 4.0, 4.0, 4.0);
+ sabcd seven = sabcd(7.0, 7.0, 7.0, 7.0);
+ float q = 0.0;
+ float q2 = 0.0;
+
+ f = qualifiers(a, b, c, d, e);
+
+ if(a == one) q += 1.0;
+ if(b == one) q += 2.0;
+ if(c == seven) q += 4.0;
+ if(d == four) q2 += 1.0;
+ if(e == one) q2 += 2.0;
+ if(f == one) q2 += 4.0;
+
+ color = vec4(vec2(q / 7.0, q2 / 7.0), 1.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_frag.frag
new file mode 100644
index 0000000000..26ffd695ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+vec4 function(vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+vec4 function(vec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_vert.vert
new file mode 100644
index 0000000000..3c83eade81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+vec4 function(vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+vec4 function(vec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_frag.frag
new file mode 100644
index 0000000000..ca027ab8de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+vec4 function(vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+vec4 function(vec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_vert.vert
new file mode 100644
index 0000000000..2f714a5728
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_empty_vec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+vec4 function(vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+vec4 function(vec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_frag.frag
new file mode 100644
index 0000000000..23258c69b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+vec4 function(in vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+vec4 function(in vec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_vert.vert
new file mode 100644
index 0000000000..3618544577
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+vec4 function(in vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+vec4 function(in vec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_frag.frag
new file mode 100644
index 0000000000..6e94bd9ed5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+vec4 function(in vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+vec4 function(in vec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_vert.vert
new file mode 100644
index 0000000000..58bed576b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_in_vec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+vec4 function(in vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should remain unchanged by the function and the function should return 1.0.
+ if(is_all(par, 1.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+vec4 function(in vec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_frag.frag
new file mode 100644
index 0000000000..1569b5639e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_frag.frag
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+vec4 function(inout vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, vec4(0.0, 0.0, 0.0, 0.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+vec4 function(inout vec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_vert.vert
new file mode 100644
index 0000000000..dc547134dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_array_vert.vert
@@ -0,0 +1,91 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+vec4 function(inout vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, vec4(0.0, 0.0, 0.0, 0.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+vec4 function(inout vec4 par[3])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_frag.frag
new file mode 100644
index 0000000000..1b1a81cc09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_frag.frag
@@ -0,0 +1,112 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+vec4 function(inout vec4 par[10]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[10], const in vec4 value);
+void set_all(out vec4 array[10], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[10];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, vec4(0.0, 0.0, 0.0, 0.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+vec4 function(inout vec4 par[10])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[10], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+ if(array[3] != value)
+ ret = false;
+ if(array[4] != value)
+ ret = false;
+ if(array[5] != value)
+ ret = false;
+ if(array[6] != value)
+ ret = false;
+ if(array[7] != value)
+ ret = false;
+ if(array[8] != value)
+ ret = false;
+ if(array[9] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[10], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+ array[3] = value;
+ array[4] = value;
+ array[5] = value;
+ array[6] = value;
+ array[7] = value;
+ array[8] = value;
+ array[9] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_vert.vert
new file mode 100644
index 0000000000..e7e57e376b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_bigarray_vert.vert
@@ -0,0 +1,112 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+vec4 function(inout vec4 par[10]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[10], const in vec4 value);
+void set_all(out vec4 array[10], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[10];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, vec4(0.0, 0.0, 0.0, 0.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+vec4 function(inout vec4 par[10])
+{
+ // Return the value of the array.
+ if(is_all(par, vec4(1.0, 1.0, 1.0, 1.0)))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[10], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+ if(array[3] != value)
+ ret = false;
+ if(array[4] != value)
+ ret = false;
+ if(array[5] != value)
+ ret = false;
+ if(array[6] != value)
+ ret = false;
+ if(array[7] != value)
+ ret = false;
+ if(array[8] != value)
+ ret = false;
+ if(array[9] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[10], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+ array[3] = value;
+ array[4] = value;
+ array[5] = value;
+ array[6] = value;
+ array[7] = value;
+ array[8] = value;
+ array[9] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_frag.frag
new file mode 100644
index 0000000000..1d144cac57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_frag.frag
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+vec4 function(inout vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+vec4 function(inout vec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_vert.vert
new file mode 100644
index 0000000000..e4e75320f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_inout_vec4_empty_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+vec4 function(inout vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+vec4 function(inout vec4 par)
+{
+ // Return the value of the parameter.
+ if(is_all(par, 1.0))
+ {
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_frag.frag
new file mode 100644
index 0000000000..4968a7eb24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_frag.frag
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declarations.
+vec4 function(out vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, vec4(0.0, 0.0, 0.0, 0.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definitions.
+vec4 function(out vec4 par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_vert.vert
new file mode 100644
index 0000000000..125a40f979
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_array_vert.vert
@@ -0,0 +1,85 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declarations.
+vec4 function(out vec4 par[3]);
+bool is_all(const in vec4 par, const in float value);
+bool is_all(const in vec4 array[3], const in vec4 value);
+void set_all(out vec4 array[3], const in vec4 value);
+
+void main (void)
+{
+ vec4 par[3];
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ // Initialize the entire array to 1.0.
+ set_all(par, vec4(1.0, 1.0, 1.0, 1.0));
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, vec4(0.0, 0.0, 0.0, 0.0)) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definitions.
+vec4 function(out vec4 par[3])
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, vec4(0.0, 0.0, 0.0, 0.0));
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+bool is_all(const in vec4 array[3], const in vec4 value)
+{
+ bool ret = true;
+
+ if(array[0] != value)
+ ret = false;
+ if(array[1] != value)
+ ret = false;
+ if(array[2] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 array[3], const in vec4 value)
+{
+ array[0] = value;
+ array[1] = value;
+ array[2] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_frag.frag
new file mode 100644
index 0000000000..ee357ab5a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_frag.frag
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+// Function declaration.
+vec4 function(out vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+vec4 function(out vec4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_vert.vert
new file mode 100644
index 0000000000..c26956cf07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/vec4_empty_out_vec4_empty_vert.vert
@@ -0,0 +1,68 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+// Function declaration.
+vec4 function(out vec4 par);
+bool is_all(const in vec4 par, const in float value);
+void set_all(out vec4 par, const in float value);
+
+void main (void)
+{
+ vec4 par = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 ret = vec4(0.0, 0.0, 0.0, 0.0);
+
+ float gray = 0.0;
+
+ ret = function(par);
+
+ // The parameter should be changed by the function and the function should return 1.0.
+ if(is_all(par, 0.0) && is_all(ret, 1.0))
+ {
+ gray = 1.0;
+ }
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+vec4 function(out vec4 par)
+{
+ // Test parameter qualifier (default is "in").
+ set_all(par, 0.0);
+
+ return vec4(1.0, 1.0, 1.0, 1.0);
+}
+
+bool is_all(const in vec4 par, const in float value)
+{
+ bool ret = true;
+
+ if(par[0] != value)
+ ret = false;
+ if(par[1] != value)
+ ret = false;
+ if(par[2] != value)
+ ret = false;
+ if(par[3] != value)
+ ret = false;
+
+ return ret;
+}
+
+void set_all(out vec4 par, const in float value)
+{
+ par[0] = value;
+ par[1] = value;
+ par[2] = value;
+ par[3] = value;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_frag.frag
new file mode 100644
index 0000000000..cb277863d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float gray = 0.0;
+
+// Function declaration.
+void function(void);
+
+void main (void)
+{
+ gray = 0.0;
+
+ function();
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
+// Function definition.
+void function(void)
+{
+ gray = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_vert.vert
new file mode 100644
index 0000000000..8f5130c26e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/functions/void_empty_empty_void_empty_vert.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+float gray = 0.0;
+
+// Function declaration.
+void function(void);
+
+void main (void)
+{
+ gray = 0.0;
+
+ function();
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+// Function definition.
+void function(void)
+{
+ gray = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html
new file mode 100644
index 0000000000..2118dfa105
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: gl_FragCoord_001_to_003.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_FragCoord_xy_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_FragCoord_xy_frag.frag"
+ },
+ "name": "gl_FragCoord_xy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "gl_FragCoord_z_frag_ref.vert",
+ "fragmentShader": "gl_FragCoord_z_frag_ref.frag",
+ "builtin_uniforms": {
+ "min_required": 2,
+ "valid_values": [
+ "gl_DepthRange.near",
+ "gl_DepthRange.far",
+ "gl_DepthRange.diff"
+ ],
+ }
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_FragCoord_z_frag.frag"
+ },
+ "name": "gl_FragCoord_z_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.5,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_FragCoord_w_frag.frag"
+ },
+ "name": "gl_FragCoord_w_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_w_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_w_frag.frag
new file mode 100644
index 0000000000..ee8be18726
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_w_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main(void)
+{
+ gl_FragColor = vec4(vec3(gl_FragCoord.w), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag.frag
new file mode 100644
index 0000000000..772661fc5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float viewportwidth;
+uniform float viewportheight;
+
+void main(void)
+{
+ // The image width is 500 so scale the position to 0...1 for color
+ gl_FragColor = vec4(gl_FragCoord.x /viewportwidth , gl_FragCoord.y/viewportheight, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag_ref.frag
new file mode 100644
index 0000000000..deea9c581b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_xy_frag_ref.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main(void)
+{
+ // The image width is 500x500 and the rectangle is 434x434
+ // The green component corresponds to x (0...1 left to right) and the
+ // blue component corresponds to y (0...1 bottom to top)
+ gl_FragColor = vec4((434.0 / 500.0) * (color.gb - 0.5) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag.frag
new file mode 100644
index 0000000000..e81a81d803
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag.frag
@@ -0,0 +1,15 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main(void)
+{
+ gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.frag
new file mode 100644
index 0000000000..d66db17deb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 position;
+
+void main(void)
+{
+ // Normalized device coordinates
+ float z = position.z / position.w;
+ float f = gl_DepthRange.far;
+ float n = gl_DepthRange.near;
+
+ // Window coordinates
+ z = ((f - n) / 2.0) * z + (f + n) / 2.0;
+
+ gl_FragColor = vec4(vec3(z), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.vert
new file mode 100644
index 0000000000..3c11ffb73d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/gl_FragCoord_z_frag_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 position;
+
+void main(void)
+{
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+ // Vertex's clip coordinates
+ position = gl_Position;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/input.run.txt
new file mode 100644
index 0000000000..588cde7bff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FragCoord/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+gl_FragCoord_001_to_003.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_001_to_001.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_001_to_001.html
new file mode 100644
index 0000000000..dc1fe1ac87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_001_to_001.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: gl_FrontFacing_001_to_001.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "frontbacksquare",
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "gl_FrontFacing_frag.frag"
+ },
+ "name": "gl_FrontFacing_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_frag.frag
new file mode 100644
index 0000000000..f4143574bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main(void)
+{
+ if(gl_FrontFacing)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/input.run.txt
new file mode 100644
index 0000000000..6244419195
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/gl_FrontFacing/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+gl_FrontFacing_001_to_001.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_001_to_008.html
new file mode 100644
index 0000000000..2c9740ad06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: greaterThan_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_vec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_vec2_frag.frag"
+ },
+ "name": "greaterThan_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThan_vec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThan_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThan_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_vec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_vec3_frag.frag"
+ },
+ "name": "greaterThan_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThan_vec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThan_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThan_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_ivec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_ivec2_frag.frag"
+ },
+ "name": "greaterThan_ivec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThan_ivec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThan_ivec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThan_ivec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_ivec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThan_ivec3_frag.frag"
+ },
+ "name": "greaterThan_ivec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThan_ivec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThan_ivec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThan_ivec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag.frag
new file mode 100644
index 0000000000..9fb6954e74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThan(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag_ref.frag
new file mode 100644
index 0000000000..5a24063df2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec2 gt(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gt(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert.vert
new file mode 100644
index 0000000000..68bfd31ec0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThan(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert_ref.vert
new file mode 100644
index 0000000000..3dac9d7dcc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 gt(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gt(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag.frag
new file mode 100644
index 0000000000..4d077b328b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThan(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag_ref.frag
new file mode 100644
index 0000000000..36775a9bc4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 gt(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] > b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gt(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert.vert
new file mode 100644
index 0000000000..6f722d6557
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThan(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert_ref.vert
new file mode 100644
index 0000000000..3363f2aaef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_ivec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 gt(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] > b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gt(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag.frag
new file mode 100644
index 0000000000..73dbc4a72b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThan(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag_ref.frag
new file mode 100644
index 0000000000..9c73b1ac5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 gt(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gt(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert.vert
new file mode 100644
index 0000000000..686e78e6fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThan(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert_ref.vert
new file mode 100644
index 0000000000..ab886147e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 gt(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gt(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag.frag
new file mode 100644
index 0000000000..9e48f7e345
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThan(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag_ref.frag
new file mode 100644
index 0000000000..140d288498
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 gt(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] > b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gt(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert.vert
new file mode 100644
index 0000000000..dcdec7463f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThan(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert_ref.vert
new file mode 100644
index 0000000000..c52adae9b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/greaterThan_vec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 gt(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] > b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] > b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] > b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gt(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/input.run.txt
new file mode 100644
index 0000000000..9d2acae74d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThan/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+greaterThan_001_to_008.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_001_to_008.html
new file mode 100644
index 0000000000..950ea6db78
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: greaterThanEqual_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_vec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_vec2_frag.frag"
+ },
+ "name": "greaterThanEqual_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThanEqual_vec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThanEqual_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThanEqual_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_vec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_vec3_frag.frag"
+ },
+ "name": "greaterThanEqual_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThanEqual_vec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThanEqual_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThanEqual_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_ivec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_ivec2_frag.frag"
+ },
+ "name": "greaterThanEqual_ivec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThanEqual_ivec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThanEqual_ivec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThanEqual_ivec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_ivec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "greaterThanEqual_ivec3_frag.frag"
+ },
+ "name": "greaterThanEqual_ivec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "greaterThanEqual_ivec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "greaterThanEqual_ivec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "greaterThanEqual_ivec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag.frag
new file mode 100644
index 0000000000..946f60b19f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThanEqual(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag_ref.frag
new file mode 100644
index 0000000000..2ca0347a77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec2 gte(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gte(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert.vert
new file mode 100644
index 0000000000..6dbe5ea25d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThanEqual(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert_ref.vert
new file mode 100644
index 0000000000..3f2f41a6e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 gte(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gte(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag.frag
new file mode 100644
index 0000000000..f240a680e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThanEqual(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag_ref.frag
new file mode 100644
index 0000000000..346676cea4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 gte(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] >= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gte(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert.vert
new file mode 100644
index 0000000000..96b12a1f66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThanEqual(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert_ref.vert
new file mode 100644
index 0000000000..8a595186f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_ivec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 gte(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] >= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gte(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag.frag
new file mode 100644
index 0000000000..037e4ae5cc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThanEqual(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag_ref.frag
new file mode 100644
index 0000000000..4987b571eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 gte(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gte(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert.vert
new file mode 100644
index 0000000000..0112876421
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(greaterThanEqual(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert_ref.vert
new file mode 100644
index 0000000000..bc2c4b74f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 gte(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(gte(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag.frag
new file mode 100644
index 0000000000..fa0b97c87d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThanEqual(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag_ref.frag
new file mode 100644
index 0000000000..c81f489341
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 gte(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] >= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gte(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert.vert
new file mode 100644
index 0000000000..1cf6bf0373
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(greaterThanEqual(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert_ref.vert
new file mode 100644
index 0000000000..0907e38fc5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/greaterThanEqual_vec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 gte(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] >= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] >= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] >= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(gte(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/input.run.txt
new file mode 100644
index 0000000000..4562883013
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/greaterThanEqual/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+greaterThanEqual_001_to_008.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/input.run.txt
new file mode 100644
index 0000000000..6eb579d476
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+inversesqrt_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_001_to_006.html
new file mode 100644
index 0000000000..f5dd42094f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: inversesqrt_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "inversesqrt_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "inversesqrt_float_frag_xvary.frag"
+ },
+ "name": "inversesqrt_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "inversesqrt_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "inversesqrt_vec2_frag_xvary.frag"
+ },
+ "name": "inversesqrt_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "inversesqrt_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "inversesqrt_vec3_frag_xvary.frag"
+ },
+ "name": "inversesqrt_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "inversesqrt_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "inversesqrt_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "inversesqrt_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "inversesqrt_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "inversesqrt_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "inversesqrt_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "inversesqrt_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "inversesqrt_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "inversesqrt_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary.frag
new file mode 100644
index 0000000000..64c0b286c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = (color.r * 99.0) + 1.0;
+ gl_FragColor = vec4(inversesqrt(c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..d4fffeaf95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = (color.r * 99.0) + 1.0;
+ gl_FragColor = vec4(1.0 / sqrt(c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary.vert
new file mode 100644
index 0000000000..762b8395e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = (gtf_Color.r * 99.0) + 1.0;
+ color = vec4(inversesqrt(c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..d38c5c9481
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_float_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = (gtf_Color.r * 99.0) + 1.0;
+ color = vec4(1.0 / sqrt(c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..1d4f981d44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (color.rg * 99.0) + 1.0;
+ gl_FragColor = vec4(inversesqrt(c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..0204ede208
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (color.rg * 99.0) + 1.0;
+ gl_FragColor = vec4(1.0 / sqrt(c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..528df8a99a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (gtf_Color.rg * 99.0) + 1.0;
+ color = vec4(inversesqrt(c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..45aee3f073
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec2_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (gtf_Color.rg * 99.0) + 1.0;
+ color = vec4(1.0 / sqrt(c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..1a48139095
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (color.rgb * 99.0) + 1.0;
+ gl_FragColor = vec4(inversesqrt(c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..9b0e603912
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (color.rgb * 99.0) + 1.0;
+ gl_FragColor = vec4(1.0 / sqrt(c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..4aee12d5e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (gtf_Color.rgb * 99.0) + 1.0;
+ color = vec4(inversesqrt(c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..7929585b70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/inversesqrt/inversesqrt_vec3_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (gtf_Color.rgb * 99.0) + 1.0;
+ color = vec4(1.0 / sqrt(c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/input.run.txt
new file mode 100644
index 0000000000..9a3147ec3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+length_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_001_to_006.html
new file mode 100644
index 0000000000..cdcc97b5b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: length_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "length_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "length_float_frag_xvary.frag"
+ },
+ "name": "length_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "length_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "length_vec2_frag_xvary.frag"
+ },
+ "name": "length_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "length_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "length_vec3_frag_xvary.frag"
+ },
+ "name": "length_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "length_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "length_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "length_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "length_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "length_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "length_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "length_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "length_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "length_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary.frag
new file mode 100644
index 0000000000..6b69eceeeb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(length(color.r)), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..9e5672b1d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_frag_xvary_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(color.r), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary.vert
new file mode 100644
index 0000000000..984e83943b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(length(gtf_Color.r)), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..940b53e278
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_float_vert_xvary_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(gtf_Color.r), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..bbba3bfa75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(length(color.rg) / 2.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..18a2913050
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_frag_xvary_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(sqrt(color.r*color.r + color.g*color.g) / 2.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..3d422ce046
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(length(gtf_Color.rg) / 2.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..9540f93c8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec2_vert_xvary_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(sqrt(gtf_Color.r*gtf_Color.r + gtf_Color.g*gtf_Color.g) / 2.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..00ae4460b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(length(color.rgb) / 3.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..4c092c505d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_frag_xvary_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(vec3(sqrt(color.r*color.r + color.g*color.g + color.b*color.b) / 3.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..469e2ebda9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(length(gtf_Color.rgb) / 3.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..a29e150036
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/length/length_vec3_vert_xvary_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vec3(sqrt(gtf_Color.r*gtf_Color.r + gtf_Color.g*gtf_Color.g + gtf_Color.b*gtf_Color.b) / 3.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/input.run.txt
new file mode 100644
index 0000000000..f49c916d97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+lessThan_001_to_008.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_001_to_008.html
new file mode 100644
index 0000000000..963a3a229a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: lessThan_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_vec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_vec2_frag.frag"
+ },
+ "name": "lessThan_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThan_vec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThan_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThan_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_vec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_vec3_frag.frag"
+ },
+ "name": "lessThan_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThan_vec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThan_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThan_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_ivec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_ivec2_frag.frag"
+ },
+ "name": "lessThan_ivec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThan_ivec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThan_ivec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThan_ivec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_ivec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThan_ivec3_frag.frag"
+ },
+ "name": "lessThan_ivec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThan_ivec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThan_ivec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThan_ivec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag.frag
new file mode 100644
index 0000000000..efb9f70969
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThan(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag_ref.frag
new file mode 100644
index 0000000000..5a5f597262
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec2 lt(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lt(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert.vert
new file mode 100644
index 0000000000..0b4b12f187
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThan(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert_ref.vert
new file mode 100644
index 0000000000..9ec55e8551
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 lt(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lt(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag.frag
new file mode 100644
index 0000000000..39fa872d14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThan(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag_ref.frag
new file mode 100644
index 0000000000..3cbf48f982
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 lt(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] < b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lt(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert.vert
new file mode 100644
index 0000000000..8d64ec8bb6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThan(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert_ref.vert
new file mode 100644
index 0000000000..68719abf80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_ivec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 lt(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] < b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lt(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag.frag
new file mode 100644
index 0000000000..2cdfccb869
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThan(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag_ref.frag
new file mode 100644
index 0000000000..1b841e4b15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 lt(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lt(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert.vert
new file mode 100644
index 0000000000..b341e510e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThan(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert_ref.vert
new file mode 100644
index 0000000000..10206861a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 lt(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lt(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag.frag
new file mode 100644
index 0000000000..ca0bfea25c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThan(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag_ref.frag
new file mode 100644
index 0000000000..4b97bd6eb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 lt(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] < b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lt(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert.vert
new file mode 100644
index 0000000000..d4f15c1b43
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThan(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert_ref.vert
new file mode 100644
index 0000000000..a6e703d6f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThan/lessThan_vec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 lt(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] < b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] < b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] < b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lt(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/input.run.txt
new file mode 100644
index 0000000000..656332ccca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+lessThanEqual_001_to_008.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_001_to_008.html
new file mode 100644
index 0000000000..35adf22fbf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: lessThanEqual_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_vec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_vec2_frag.frag"
+ },
+ "name": "lessThanEqual_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThanEqual_vec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThanEqual_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThanEqual_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_vec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_vec3_frag.frag"
+ },
+ "name": "lessThanEqual_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThanEqual_vec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThanEqual_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThanEqual_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_ivec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_ivec2_frag.frag"
+ },
+ "name": "lessThanEqual_ivec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThanEqual_ivec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThanEqual_ivec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThanEqual_ivec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_ivec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "lessThanEqual_ivec3_frag.frag"
+ },
+ "name": "lessThanEqual_ivec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "lessThanEqual_ivec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "lessThanEqual_ivec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "lessThanEqual_ivec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag.frag
new file mode 100644
index 0000000000..4747c3a849
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThanEqual(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag_ref.frag
new file mode 100644
index 0000000000..b8be19b56b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec2 lte(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lte(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert.vert
new file mode 100644
index 0000000000..d276f0c8de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThanEqual(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert_ref.vert
new file mode 100644
index 0000000000..8a8890f5d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 lte(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lte(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag.frag
new file mode 100644
index 0000000000..d4dc9a1209
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThanEqual(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag_ref.frag
new file mode 100644
index 0000000000..b3295149c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 lte(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] <= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lte(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert.vert
new file mode 100644
index 0000000000..7d7c0c91fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThanEqual(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert_ref.vert
new file mode 100644
index 0000000000..895f0679a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_ivec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 lte(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] <= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lte(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag.frag
new file mode 100644
index 0000000000..319360bdad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThanEqual(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag_ref.frag
new file mode 100644
index 0000000000..82e2190ac9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 lte(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lte(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert.vert
new file mode 100644
index 0000000000..86809ef8d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lessThanEqual(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert_ref.vert
new file mode 100644
index 0000000000..a99efb0185
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 lte(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(lte(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag.frag
new file mode 100644
index 0000000000..060af8d974
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThanEqual(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag_ref.frag
new file mode 100644
index 0000000000..b07c24e908
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 lte(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] <= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lte(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert.vert
new file mode 100644
index 0000000000..e5e479657e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lessThanEqual(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert_ref.vert
new file mode 100644
index 0000000000..61b87b7885
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/lessThanEqual/lessThanEqual_vec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 lte(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] <= b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] <= b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] <= b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(lte(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/input.run.txt
new file mode 100644
index 0000000000..beb1561c1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+log_001_to_008.html
+log_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_001_to_008.html
new file mode 100644
index 0000000000..a3afd6a33c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: log_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_float_frag_xvary.frag"
+ },
+ "name": "log_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_float_frag_xvary01_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_float_frag_xvary01.frag"
+ },
+ "name": "log_float_frag_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec2_frag_xvary.frag"
+ },
+ "name": "log_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec2_frag_xvary01_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec2_frag_xvary01.frag"
+ },
+ "name": "log_vec2_frag_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec3_frag_xvary.frag"
+ },
+ "name": "log_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec3_frag_xvary01_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log_vec3_frag_xvary01.frag"
+ },
+ "name": "log_vec3_frag_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log_float_vert_xvary01_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log_float_vert_xvary01.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log_float_vert_xvary01.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_009_to_012.html
new file mode 100644
index 0000000000..f4d4c0268e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: log_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "log_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log_vec2_vert_xvary01_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log_vec2_vert_xvary01.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log_vec2_vert_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log_vec3_vert_xvary01_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log_vec3_vert_xvary01.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log_vec3_vert_xvary01.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary.frag
new file mode 100644
index 0000000000..c0e84b2d36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 31.0 * color.r + 1.0;
+ gl_FragColor = vec4(log(c) / 3.466, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01.frag
new file mode 100644
index 0000000000..ca08d35579
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = (color.r + 0.01) / 1.01;
+ gl_FragColor = vec4(log(c) / -4.61, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01_ref.frag
new file mode 100644
index 0000000000..cd6b25a410
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary01_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float x = (color.r + 0.01) / 1.01;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0;
+
+ gl_FragColor = vec4(y / -4.61, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..a85b33cba3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_frag_xvary_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float x = 31.0 * color.r + 1.0;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0;
+
+ gl_FragColor = vec4(y / 3.466, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary.vert
new file mode 100644
index 0000000000..2e85fb99b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 31.0 * gtf_Color.r + 1.0;
+ color = vec4(log(c) / 3.466, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01.vert
new file mode 100644
index 0000000000..e365003cf1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = (gtf_Color.r + 0.01) / 1.01;
+ color = vec4(log(c) / -4.61, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01_ref.vert
new file mode 100644
index 0000000000..059566e7ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary01_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float x = (gtf_Color.r + 0.01) / 1.01;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0;
+
+ color = vec4(y / -4.61, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..afbfb3ebf9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_float_vert_xvary_ref.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float x = 31.0 * gtf_Color.r + 1.0;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0;
+
+ color = vec4(y / 3.466, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..5dadc29457
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 31.0 * color.rg + 1.0;
+ gl_FragColor = vec4(log(c) / 3.466, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01.frag
new file mode 100644
index 0000000000..0d47567874
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (color.rg + 0.01) / 1.01;
+ gl_FragColor = vec4(log(c) / -4.61, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01_ref.frag
new file mode 100644
index 0000000000..4f3cc1c805
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary01_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 x = (color.rg + 0.01) / 1.01;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0;
+
+ gl_FragColor = vec4(y / -4.61, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..0095d68920
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_frag_xvary_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 x = 31.0 * color.rg + 1.0;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0;
+
+ gl_FragColor = vec4(y / 3.466, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..f5fe9e8e1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 31.0 * gtf_Color.rg + 1.0;
+ color = vec4(log(c) / 3.466, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01.vert
new file mode 100644
index 0000000000..1f39279f1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (gtf_Color.rg + 0.01) / 1.01;
+ color = vec4(log(c) / -4.61, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01_ref.vert
new file mode 100644
index 0000000000..41197b1783
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary01_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 x = (gtf_Color.rg + 0.01) / 1.01;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0;
+
+ color = vec4(y / -4.61, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..b86606a71c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec2_vert_xvary_ref.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 x = 31.0 * gtf_Color.rg + 1.0;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0;
+
+ color = vec4(y / 3.466, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..7424e3a6c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 31.0 * color.rgb + 1.0;
+ gl_FragColor = vec4(log(c) / 3.466, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01.frag
new file mode 100644
index 0000000000..7e9de5561e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (color.rgb + 0.01) / 1.01;
+ gl_FragColor = vec4(log(c) / -4.61, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01_ref.frag
new file mode 100644
index 0000000000..d27f807db6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary01_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 x = (color.rgb + 0.01) / 1.01;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0;
+
+ gl_FragColor = vec4(y / -4.61, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..a5d21f6f35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_frag_xvary_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 x = 31.0 * color.rgb + 1.0;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0;
+
+ gl_FragColor = vec4(y / 3.466, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..6e3b77b53e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 31.0 * gtf_Color.rgb + 1.0;
+ color = vec4(log(c) / 3.466, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01.vert
new file mode 100644
index 0000000000..d1e06dc358
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (gtf_Color.rgb + 0.01) / 1.01;
+ color = vec4(log(c) / -4.61, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01_ref.vert
new file mode 100644
index 0000000000..d5c67acde3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary01_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 x = (gtf_Color.rgb + 0.01) / 1.01;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0;
+
+ color = vec4(y / -4.61, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..204c6dab9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log/log_vec3_vert_xvary_ref.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 x = 31.0 * gtf_Color.rgb + 1.0;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0;
+
+ color = vec4(y / 3.466, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/input.run.txt
new file mode 100644
index 0000000000..4205bf17ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+log2_001_to_008.html
+log2_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_001_to_008.html
new file mode 100644
index 0000000000..53dc3e0f8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: log2_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_float_frag_xvary.frag"
+ },
+ "name": "log2_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_float_frag_xvary01_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_float_frag_xvary01.frag"
+ },
+ "name": "log2_float_frag_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec2_frag_xvary.frag"
+ },
+ "name": "log2_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec2_frag_xvary01_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec2_frag_xvary01.frag"
+ },
+ "name": "log2_vec2_frag_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec3_frag_xvary.frag"
+ },
+ "name": "log2_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec3_frag_xvary01_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "log2_vec3_frag_xvary01.frag"
+ },
+ "name": "log2_vec3_frag_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log2_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log2_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log2_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log2_float_vert_xvary01_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log2_float_vert_xvary01.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log2_float_vert_xvary01.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_009_to_012.html
new file mode 100644
index 0000000000..a7644b3792
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: log2_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "log2_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log2_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log2_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log2_vec2_vert_xvary01_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log2_vec2_vert_xvary01.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log2_vec2_vert_xvary01.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log2_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log2_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log2_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "log2_vec3_vert_xvary01_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "log2_vec3_vert_xvary01.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "log2_vec3_vert_xvary01.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary.frag
new file mode 100644
index 0000000000..ad8169e98b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 31.0 * color.r + 1.0;
+ gl_FragColor = vec4(log2(c) / 5.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01.frag
new file mode 100644
index 0000000000..ccbdc87177
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = (color.r + 0.01) / 1.01;
+ gl_FragColor = vec4(log2(c) / -8.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01_ref.frag
new file mode 100644
index 0000000000..ff9edaee40
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary01_ref.frag
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ float x = (color.r + 0.01) / 1.01;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0 / ln2;
+
+ gl_FragColor = vec4(y / -8.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..778cdcd14a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_frag_xvary_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ float x = 31.0 * color.r + 1.0;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0 / ln2;
+
+ gl_FragColor = vec4(y / 5.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary.vert
new file mode 100644
index 0000000000..4015613d2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 31.0 * gtf_Color.r + 1.0;
+ color = vec4(log2(c) / 5.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01.vert
new file mode 100644
index 0000000000..1cf60f89c7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = (gtf_Color.r + 0.01) / 1.01;
+ color = vec4(log2(c) / -8.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01_ref.vert
new file mode 100644
index 0000000000..8589a5eb35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary01_ref.vert
@@ -0,0 +1,40 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ float x = (gtf_Color.r + 0.01) / 1.01;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0 / ln2;
+
+ color = vec4(y / -8.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..ed2d0feb45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_float_vert_xvary_ref.vert
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+void main (void)
+{
+ float x = 31.0 * gtf_Color.r + 1.0;
+ float y = 0.0;
+ float z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ float p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0 / ln2;
+
+ color = vec4(y / 5.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..2ee68d590c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 31.0 * color.rg + 1.0;
+ gl_FragColor = vec4(log2(c) / 5.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01.frag
new file mode 100644
index 0000000000..3dd8484bc8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (color.rg + 0.01) / 1.01;
+ gl_FragColor = vec4(log2(c) / -8.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01_ref.frag
new file mode 100644
index 0000000000..ab307fadc5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary01_ref.frag
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec2 x = (color.rg + 0.01) / 1.01;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0 / ln2;
+
+ gl_FragColor = vec4(y / -8.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..9f54de2a2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_frag_xvary_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec2 x = 31.0 * color.rg + 1.0;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0 / ln2;
+
+ gl_FragColor = vec4(y / 5.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..2f07daaa42
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 31.0 * gtf_Color.rg + 1.0;
+ color = vec4(log2(c) / 5.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01.vert
new file mode 100644
index 0000000000..64312ac8d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = (gtf_Color.rg + 0.01) / 1.01;
+ color = vec4(log2(c) / -8.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01_ref.vert
new file mode 100644
index 0000000000..e0a8cf3419
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary01_ref.vert
@@ -0,0 +1,40 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec2 x = (gtf_Color.rg + 0.01) / 1.01;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0 / ln2;
+
+ color = vec4(y / -8.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..744dfda43f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec2_vert_xvary_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec2 x = 31.0 * gtf_Color.rg + 1.0;
+ vec2 y = vec2(0.0);
+ vec2 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec2 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0 / ln2;
+
+ color = vec4(y / 5.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..5cecf12102
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 31.0 * color.rgb + 1.0;
+ gl_FragColor = vec4(log2(c) / 5.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01.frag
new file mode 100644
index 0000000000..098e2f9555
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (color.rgb + 0.01) / 1.01;
+ gl_FragColor = vec4(log2(c) / -8.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01_ref.frag
new file mode 100644
index 0000000000..5cdf6af9ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary01_ref.frag
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec3 x = (color.rgb + 0.01) / 1.01;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0 / ln2;
+
+ gl_FragColor = vec4(y / -8.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..d7303ef677
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_frag_xvary_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec3 x = 31.0 * color.rgb + 1.0;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0 / ln2;
+
+ gl_FragColor = vec4(y / 5.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..26a270b80d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 31.0 * gtf_Color.rgb + 1.0;
+ color = vec4(log2(c) / 5.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01.vert
new file mode 100644
index 0000000000..3f8c464f31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = (gtf_Color.rgb + 0.01) / 1.01;
+ color = vec4(log2(c) / -8.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01_ref.vert
new file mode 100644
index 0000000000..97bfe7775d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary01_ref.vert
@@ -0,0 +1,40 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec3 x = (gtf_Color.rgb + 0.01) / 1.01;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ // Note: z will always be negative between 0.01 and 1.0 and
+ // so will y since it is raised to an odd power, and the shader spec
+ // does not support pow(-x, y) where y is not a compile time constant
+ z = abs((x - 1.0) / (x + 1.0));
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= -2.0 / ln2;
+
+ color = vec4(y / -8.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..de23394ff0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/log2/log2_vec3_vert_xvary_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+const float ln2 = 0.69314718055994530941723212145818;
+
+
+
+void main (void)
+{
+ vec3 x = 31.0 * gtf_Color.rgb + 1.0;
+ vec3 y = vec3(0.0);
+ vec3 z; // x-1 / x+1
+ int n = 50;
+
+ // ln(x) = 2[x-1 + 1 (x-1)^3 + 1 (x-1)^5 + ...] for x > 0
+ // [x+1 3 (x+1) 5 (x+1) ]
+ z = (x - 1.0) / (x + 1.0);
+ vec3 p = z;
+ for(int i = 1; i <= 101; i += 2)
+ {
+ y += p / float(i);
+ p *= z * z;
+ }
+ y *= 2.0 / ln2;
+
+ color = vec4(y / 5.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_frag.frag
new file mode 100644
index 0000000000..46ea31cf8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_frag.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const int array_size = 2;
+
+void main (void)
+{
+ const mat2 a = mat2(1.0, 2.0, 3.0, 4.0);
+ const mat2 b = mat2(5.0, 6.0, 7.0, 8.0);
+ mat2 array[array_size];
+ float gray;
+
+ array[0] = a;
+ array[1] = b;
+
+ if((array[0] == a) && (array[1] == b))
+ gray = 1.0;
+ else
+ gray = 0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_vert.vert
new file mode 100644
index 0000000000..83845e66ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat2_vert.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const int array_size = 2;
+
+void main (void)
+{
+ const mat2 a = mat2(1.0, 2.0, 3.0, 4.0);
+ const mat2 b = mat2(5.0, 6.0, 7.0, 8.0);
+ mat2 array[array_size];
+ float gray;
+
+ array[0] = a;
+ array[1] = b;
+
+ if((array[0] == a) && (array[1] == b))
+ gray = 1.0;
+ else
+ gray = 0.0;
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_frag.frag
new file mode 100644
index 0000000000..1d0cdf2824
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_frag.frag
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const int array_size = 2;
+
+void main (void)
+{
+ const mat3 a = mat3(1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0);
+ const mat3 b = mat3(10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0,
+ 16.0, 17.0, 18.0);
+ mat3 array[array_size];
+ float gray;
+
+ array[0] = a;
+ array[1] = b;
+
+ if((array[0] == a) && (array[1] == b))
+ gray = 1.0;
+ else
+ gray = 0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_vert.vert
new file mode 100644
index 0000000000..a0237d63c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat3_vert.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const int array_size = 2;
+
+void main (void)
+{
+ const mat3 a = mat3(1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0);
+ const mat3 b = mat3(10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0,
+ 16.0, 17.0, 18.0);
+ mat3 array[array_size];
+ float gray;
+
+ array[0] = a;
+ array[1] = b;
+
+ if((array[0] == a) && (array[1] == b))
+ gray = 1.0;
+ else
+ gray = 0.0;
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_frag.frag
new file mode 100644
index 0000000000..28262c2fa0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_frag.frag
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+const int array_size = 2;
+
+void main (void)
+{
+ const mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+ const mat4 b = mat4(17.0, 18.0, 19.0, 20.0,
+ 21.0, 22.0, 23.0, 24.0,
+ 25.0, 26.0, 27.0, 28.0,
+ 29.0, 30.0, 31.0, 32.0);
+ mat4 array[array_size];
+ float gray;
+
+ array[0] = a;
+ array[1] = b;
+
+ if((array[0] == a) && (array[1] == b))
+ gray = 1.0;
+ else
+ gray = 0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_vert.vert
new file mode 100644
index 0000000000..ebc80931e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/array_const_mat4_vert.vert
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+const int array_size = 2;
+
+void main (void)
+{
+ const mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+ const mat4 b = mat4(17.0, 18.0, 19.0, 20.0,
+ 21.0, 22.0, 23.0, 24.0,
+ 25.0, 26.0, 27.0, 28.0,
+ 29.0, 30.0, 31.0, 32.0);
+ mat4 array[array_size];
+ float gray;
+
+ array[0] = a;
+ array[1] = b;
+
+ if((array[0] == a) && (array[1] == b))
+ gray = 1.0;
+ else
+ gray = 0.0;
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_frag.frag
new file mode 100644
index 0000000000..1f88596733
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_frag.frag
@@ -0,0 +1,56 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 2 by 2 matrix with unique elements.
+ const mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Copy the constant matrix to another non-const matrix.
+ mat2 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[1][0] != 4.0) elms = false;
+ if(b[1][1] != 8.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_vert.vert
new file mode 100644
index 0000000000..1a87e5e4f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_copy_vert.vert
@@ -0,0 +1,55 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a constant 2 by 2 matrix with unique elements.
+ const mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Copy the constant matrix to another non-const matrix.
+ mat2 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[1][0] != 4.0) elms = false;
+ if(b[1][1] != 8.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_frag.frag
new file mode 100644
index 0000000000..d827f2a666
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_frag.frag
@@ -0,0 +1,53 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 2 by 2 matrix with unique elements.
+ const mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[1][0] != 4.0) elms = false;
+ if(a[1][1] != 8.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_vert.vert
new file mode 100644
index 0000000000..4a68460ed2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat2_vert.vert
@@ -0,0 +1,52 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a constant 2 by 2 matrix with unique elements.
+ const mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[1][0] != 4.0) elms = false;
+ if(a[1][1] != 8.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_frag.frag
new file mode 100644
index 0000000000..68764145ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 3 by 3 matrix with unique elements.
+ const mat3 a = mat3( 1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0);
+
+ // Copy the constant matrix to another non-const matrix.
+ mat3 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 3.0) elms = false;
+ if(b[1][0] != 4.0) elms = false;
+ if(b[1][1] != 5.0) elms = false;
+ if(b[1][2] != 6.0) elms = false;
+ if(b[2][0] != 7.0) elms = false;
+ if(b[2][1] != 8.0) elms = false;
+ if(b[2][2] != 9.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0];
+ if( x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON ) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON ) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2];
+ if(x < 18.0-ERROR_EPSILON || x > 18.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2];
+ if( x < 6.0-ERROR_EPSILON || x > 6.0+ERROR_EPSILON ) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2];
+ if(x < 24.0-ERROR_EPSILON || x > 24.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_vert.vert
new file mode 100644
index 0000000000..c4b5dbc84d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_copy_vert.vert
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a constant 3 by 3 matrix with unique elements.
+ const mat3 a = mat3( 1.0, 2.0, 4.0, // 1.0 8.0 64.0
+ 8.0, 16.0, 32.0, // 2.0 16.0 128.0
+ 64.0, 128.0, 256.0); // 4.0 32.0 256.0
+
+ // Copy the constant matrix to another non-const matrix.
+ mat3 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 4.0) elms = false;
+ if(b[1][0] != 8.0) elms = false;
+ if(b[1][1] != 16.0) elms = false;
+ if(b[1][2] != 32.0) elms = false;
+ if(b[2][0] != 64.0) elms = false;
+ if(b[2][1] != 128.0) elms = false;
+ if(b[2][2] != 256.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0];
+ x = b[0][0] + b[1][0] + b[2][0];
+ if( x < 73.0-ERROR_EPSILON || x > 73.0+ERROR_EPSILON ) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1];
+ if(x < 146.0-ERROR_EPSILON || x > 146.0+ERROR_EPSILON ) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2];
+ if(x < 292.0-ERROR_EPSILON || x > 292.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2];
+ if( x < 7.0-ERROR_EPSILON || x > 7.0+ERROR_EPSILON ) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2];
+ if(x < 56.0-ERROR_EPSILON || x > 56.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2];
+ if(x < 448.0-ERROR_EPSILON || x > 448.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_frag.frag
new file mode 100644
index 0000000000..605dc39298
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_frag.frag
@@ -0,0 +1,63 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 3 by 3 matrix with unique elements.
+ const mat3 a = mat3( 1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0);
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 3.0) elms = false;
+ if(a[1][0] != 4.0) elms = false;
+ if(a[1][1] != 5.0) elms = false;
+ if(a[1][2] != 6.0) elms = false;
+ if(a[2][0] != 7.0) elms = false;
+ if(a[2][1] != 8.0) elms = false;
+ if(a[2][2] != 9.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0];
+ if( x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON ) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON ) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2];
+ if(x < 18.0-ERROR_EPSILON || x > 18.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2];
+ if( x < 6.0-ERROR_EPSILON || x > 6.0+ERROR_EPSILON ) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2];
+ if(x < 24.0-ERROR_EPSILON || x > 24.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_vert.vert
new file mode 100644
index 0000000000..5b66a4ff24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat3_vert.vert
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a constant 3 by 3 matrix with unique elements.
+ const mat3 a = mat3( 1.0, 2.0, 4.0, // 1.0 8.0 64.0
+ 8.0, 16.0, 32.0, // 2.0 16.0 128.0
+ 64.0, 128.0, 256.0); // 4.0 32.0 256.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 4.0) elms = false;
+ if(a[1][0] != 8.0) elms = false;
+ if(a[1][1] != 16.0) elms = false;
+ if(a[1][2] != 32.0) elms = false;
+ if(a[2][0] != 64.0) elms = false;
+ if(a[2][1] != 128.0) elms = false;
+ if(a[2][2] != 256.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0];
+ if( x < 73.0-ERROR_EPSILON || x > 73.0+ERROR_EPSILON ) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1];
+ if(x < 146.0-ERROR_EPSILON || x > 146.0+ERROR_EPSILON ) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2];
+ if(x < 292.0-ERROR_EPSILON || x > 292.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2];
+ if( x < 7.0-ERROR_EPSILON || x > 7.0+ERROR_EPSILON ) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2];
+ if(x < 56.0-ERROR_EPSILON || x > 56.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2];
+ if(x < 448.0-ERROR_EPSILON || x > 448.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_frag.frag
new file mode 100644
index 0000000000..c9fc9222a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_frag.frag
@@ -0,0 +1,78 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 4 by 4 matrix with unique elements.
+ const mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+
+ // Copy the constant matrix to another non-const matrix.
+ mat4 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 3.0) elms = false;
+ if(b[0][3] != 4.0) elms = false;
+ if(b[1][0] != 5.0) elms = false;
+ if(b[1][1] != 6.0) elms = false;
+ if(b[1][2] != 7.0) elms = false;
+ if(b[1][3] != 8.0) elms = false;
+ if(b[2][0] != 9.0) elms = false;
+ if(b[2][1] != 10.0) elms = false;
+ if(b[2][2] != 11.0) elms = false;
+ if(b[2][3] != 12.0) elms = false;
+ if(b[3][0] != 13.0) elms = false;
+ if(b[3][1] != 14.0) elms = false;
+ if(b[3][2] != 15.0) elms = false;
+ if(b[3][3] != 16.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0] + b[3][0];
+ if(x < 28.0-ERROR_EPSILON || x > 28.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1] + b[3][1];
+ if(x < 32.0-ERROR_EPSILON || x > 32.0+ERROR_EPSILON) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2] + b[3][2];
+ if(x < 36.0-ERROR_EPSILON || x > 36.0+ERROR_EPSILON) rows = false;
+ x = b[0][3] + b[1][3] + b[2][3] + b[3][3];
+ if(x < 40.0-ERROR_EPSILON || x > 40.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2] + b[0][3];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2] + b[1][3];
+ if(x < 26.0-ERROR_EPSILON || x > 26.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2] + b[2][3];
+ if(x < 42.0-ERROR_EPSILON || x > 42.0+ERROR_EPSILON) cols = false;
+ x = b[3][0] + b[3][1] + b[3][2] + b[3][3];
+ if(x < 58.0-ERROR_EPSILON || x > 58.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_vert.vert
new file mode 100644
index 0000000000..083f626b8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_copy_vert.vert
@@ -0,0 +1,77 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a constant 4 by 4 matrix with unique elements.
+ const mat4 a = mat4( 1.0, 2.0, 4.0, 8.0, // 1.0 16.0 256.0 4096.0
+ 16.0, 32.0, 64.0, 128.0, // 2.0 32.0 512.0 8192.0
+ 256.0, 512.0, 1024.0, 2048.0, // 4.0 64.0 1024.0 16384.0
+ 4096.0, 8192.0, 16384.0, 32768.0); // 8.0 128.0 2048.0 32768.0
+
+ // Copy the constant matrix to another non-const matrix.
+ mat4 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 4.0) elms = false;
+ if(b[0][3] != 8.0) elms = false;
+ if(b[1][0] != 16.0) elms = false;
+ if(b[1][1] != 32.0) elms = false;
+ if(b[1][2] != 64.0) elms = false;
+ if(b[1][3] != 128.0) elms = false;
+ if(b[2][0] != 256.0) elms = false;
+ if(b[2][1] != 512.0) elms = false;
+ if(b[2][2] != 1024.0) elms = false;
+ if(b[2][3] != 2048.0) elms = false;
+ if(b[3][0] != 4096.0) elms = false;
+ if(b[3][1] != 8192.0) elms = false;
+ if(b[3][2] != 16384.0) elms = false;
+ if(b[3][3] != 32768.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0] + b[3][0];
+ if(x < 4369.0-ERROR_EPSILON || x > 4369.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1] + b[3][1];
+ if(x < 8738.0-ERROR_EPSILON || x > 8738.0+ERROR_EPSILON) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2] + b[3][2];
+ if(x < 17476.0-ERROR_EPSILON || x > 17476.0+ERROR_EPSILON) rows = false;
+ x = b[0][3] + b[1][3] + b[2][3] + b[3][3];
+ if(x < 34952.0-ERROR_EPSILON || x > 34952.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2] + b[0][3];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2] + b[1][3];
+ if(x < 240.0-ERROR_EPSILON || x > 240.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2] + b[2][3];
+ if(x < 3840.0-ERROR_EPSILON || x > 3840.0+ERROR_EPSILON) cols = false;
+ x = b[3][0] + b[3][1] + b[3][2] + b[3][3];
+ if(x < 61440.0-ERROR_EPSILON || x > 61440.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_frag.frag
new file mode 100644
index 0000000000..bca12dbbed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_frag.frag
@@ -0,0 +1,75 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 4 by 4 matrix with unique elements.
+ const mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 3.0) elms = false;
+ if(a[0][3] != 4.0) elms = false;
+ if(a[1][0] != 5.0) elms = false;
+ if(a[1][1] != 6.0) elms = false;
+ if(a[1][2] != 7.0) elms = false;
+ if(a[1][3] != 8.0) elms = false;
+ if(a[2][0] != 9.0) elms = false;
+ if(a[2][1] != 10.0) elms = false;
+ if(a[2][2] != 11.0) elms = false;
+ if(a[2][3] != 12.0) elms = false;
+ if(a[3][0] != 13.0) elms = false;
+ if(a[3][1] != 14.0) elms = false;
+ if(a[3][2] != 15.0) elms = false;
+ if(a[3][3] != 16.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0] + a[3][0];
+ if(x < 28.0-ERROR_EPSILON || x > 28.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1] + a[3][1];
+ if(x < 32.0-ERROR_EPSILON || x > 32.0+ERROR_EPSILON) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2] + a[3][2];
+ if(x < 36.0-ERROR_EPSILON || x > 36.0+ERROR_EPSILON) rows = false;
+ x = a[0][3] + a[1][3] + a[2][3] + a[3][3];
+ if(x < 40.0-ERROR_EPSILON || x > 40.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2] + a[0][3];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2] + a[1][3];
+ if(x < 26.0-ERROR_EPSILON || x > 26.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2] + a[2][3];
+ if(x < 42.0-ERROR_EPSILON || x > 42.0+ERROR_EPSILON) cols = false;
+ x = a[3][0] + a[3][1] + a[3][2] + a[3][3];
+ if(x < 58.0-ERROR_EPSILON || x > 58.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_vert.vert
new file mode 100644
index 0000000000..8010ab7752
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/const_mat4_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a constant 4 by 4 matrix with unique elements.
+ const mat4 a = mat4( 1.0, 2.0, 4.0, 8.0, // 1.0 16.0 256.0 4096.0
+ 16.0, 32.0, 64.0, 128.0, // 2.0 32.0 512.0 8192.0
+ 256.0, 512.0, 1024.0, 2048.0, // 4.0 64.0 1024.0 16384.0
+ 4096.0, 8192.0, 16384.0, 32768.0); // 8.0 128.0 2048.0 32768.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 4.0) elms = false;
+ if(a[0][3] != 8.0) elms = false;
+ if(a[1][0] != 16.0) elms = false;
+ if(a[1][1] != 32.0) elms = false;
+ if(a[1][2] != 64.0) elms = false;
+ if(a[1][3] != 128.0) elms = false;
+ if(a[2][0] != 256.0) elms = false;
+ if(a[2][1] != 512.0) elms = false;
+ if(a[2][2] != 1024.0) elms = false;
+ if(a[2][3] != 2048.0) elms = false;
+ if(a[3][0] != 4096.0) elms = false;
+ if(a[3][1] != 8192.0) elms = false;
+ if(a[3][2] != 16384.0) elms = false;
+ if(a[3][3] != 32768.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0] + a[3][0];
+ if(x < 4369.0-ERROR_EPSILON || x > 4369.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1] + a[3][1];
+ if(x < 8738.0-ERROR_EPSILON || x > 8738.0+ERROR_EPSILON) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2] + a[3][2];
+ if(x < 17476.0-ERROR_EPSILON || x > 17476.0+ERROR_EPSILON) rows = false;
+ x = a[0][3] + a[1][3] + a[2][3] + a[3][3];
+ if(x < 34952.0-ERROR_EPSILON || x > 34952.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2] + a[0][3];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2] + a[1][3];
+ if(x < 240.0-ERROR_EPSILON || x > 240.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2] + a[2][3];
+ if(x < 3840.0-ERROR_EPSILON || x > 3840.0+ERROR_EPSILON) cols = false;
+ x = a[3][0] + a[3][1] + a[3][2] + a[3][3];
+ if(x < 61440.0-ERROR_EPSILON || x > 61440.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/input.run.txt
new file mode 100644
index 0000000000..730999d88d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/input.run.txt
@@ -0,0 +1,7 @@
+# this file is auto-generated. DO NOT EDIT.
+mat_001_to_008.html
+mat_009_to_016.html
+mat_017_to_024.html
+mat_025_to_032.html
+mat_033_to_040.html
+mat_041_to_046.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_frag.frag
new file mode 100644
index 0000000000..a4c35d387d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m = mat2(color.rg, color.ba);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if(m[0][0] != color.r) result = black;
+ if(m[0][1] != color.g) result = black;
+ if(m[1][0] != color.b) result = black;
+ if(m[1][1] != color.a) result = black;
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_vert.vert
new file mode 100644
index 0000000000..68bc1cc1b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_2vec2_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m = mat2(gtf_Color.rg, gtf_Color.ba);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+
+ if(m[0][0] != gtf_Color.r) result = black;
+ if(m[0][1] != gtf_Color.g) result = black;
+ if(m[1][0] != gtf_Color.b) result = black;
+ if(m[1][1] != gtf_Color.a) result = black;
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_frag.frag
new file mode 100644
index 0000000000..d4d03d3a18
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m = mat2(color.r, color.g, color.b, color.a);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if(m[0][0] != color.r) result = black;
+ if(m[0][1] != color.g) result = black;
+ if(m[1][0] != color.b) result = black;
+ if(m[1][1] != color.a) result = black;
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_vert.vert
new file mode 100644
index 0000000000..204511e73c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_4float_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m = mat2(gtf_Color.r, gtf_Color.g, gtf_Color.b, gtf_Color.a);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+
+ if(m[0][0] != gtf_Color.r) result = black;
+ if(m[0][1] != gtf_Color.g) result = black;
+ if(m[1][0] != gtf_Color.b) result = black;
+ if(m[1][1] != gtf_Color.a) result = black;
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_frag.frag
new file mode 100644
index 0000000000..de941ae60c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_frag.frag
@@ -0,0 +1,56 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a 2 by 2 matrix with unique elements.
+ mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Copy the matrix to another non-const matrix.
+ mat2 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[1][0] != 4.0) elms = false;
+ if(b[1][1] != 8.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_vert.vert
new file mode 100644
index 0000000000..7659358d4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_copy_vert.vert
@@ -0,0 +1,55 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a 2 by 2 matrix with unique elements.
+ mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Copy the matrix to another non-const matrix.
+ mat2 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[1][0] != 4.0) elms = false;
+ if(b[1][1] != 8.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_frag.frag
new file mode 100644
index 0000000000..05630af9cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_frag.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m = mat2(0.5);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if((m[0][0] != 0.5))
+ result = black;
+ if((m[0][1] != 0.0))
+ result = black;
+
+ if((m[1][0] != 0.0))
+ result = black;
+ if((m[1][1] != 0.5))
+ result = black;
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_vert.vert
new file mode 100644
index 0000000000..71ceb36970
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_float_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m = mat2(0.5);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if((m[0][0] != 0.5))
+ result = black;
+ if((m[0][1] != 0.0))
+ result = black;
+ if((m[1][0] != 0.0))
+ result = black;
+ if((m[1][1] != 0.5))
+ result = black;
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_frag.frag
new file mode 100644
index 0000000000..765949d942
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_frag.frag
@@ -0,0 +1,53 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a 2 by 2 matrix with unique elements.
+ mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[1][0] != 4.0) elms = false;
+ if(a[1][1] != 8.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_vert.vert
new file mode 100644
index 0000000000..cb2b46fd2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat2_vert.vert
@@ -0,0 +1,52 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a 2 by 2 matrix with unique elements.
+ mat2 a = mat2(1.0, 2.0, // 1.0 4.0
+ 4.0, 8.0); // 2.0 8.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[1][0] != 4.0) elms = false;
+ if(a[1][1] != 8.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0];
+ if(x < 5.0-ERROR_EPSILON || x > 5.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1];
+ if(x < 3.0-ERROR_EPSILON || x > 3.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1];
+ if(x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_frag.frag
new file mode 100644
index 0000000000..b040e0b2e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_frag.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m = mat3(color.rgb, color.rgb, color.rgb);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if(m[0][0] != color.r) result = black;
+ if(m[0][1] != color.g) result = black;
+ if(m[0][2] != color.b) result = black;
+ if(m[1][0] != color.r) result = black;
+ if(m[1][1] != color.g) result = black;
+ if(m[1][2] != color.b) result = black;
+ if(m[2][0] != color.r) result = black;
+ if(m[2][1] != color.g) result = black;
+ if(m[2][2] != color.b) result = black;
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_vert.vert
new file mode 100644
index 0000000000..c0e79d0c3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_3vec3_vert.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m = mat3(gtf_Color.rgb, gtf_Color.rgb, gtf_Color.rgb);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if(m[0][0] != gtf_Color.r) result = black;
+ if(m[0][1] != gtf_Color.g) result = black;
+ if(m[0][2] != gtf_Color.b) result = black;
+ if(m[1][0] != gtf_Color.r) result = black;
+ if(m[1][1] != gtf_Color.g) result = black;
+ if(m[1][2] != gtf_Color.b) result = black;
+ if(m[2][0] != gtf_Color.r) result = black;
+ if(m[2][1] != gtf_Color.g) result = black;
+ if(m[2][2] != gtf_Color.b) result = black;
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_frag.frag
new file mode 100644
index 0000000000..ac54f6162d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_frag.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m = mat3(color.r, color.g, color.b, color.r, color.g, color.b, color.r, color.g, color.b);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if(m[0][0] != color.r) result = black;
+ if(m[0][1] != color.g) result = black;
+ if(m[0][2] != color.b) result = black;
+ if(m[1][0] != color.r) result = black;
+ if(m[1][1] != color.g) result = black;
+ if(m[1][2] != color.b) result = black;
+ if(m[2][0] != color.r) result = black;
+ if(m[2][1] != color.g) result = black;
+ if(m[2][2] != color.b) result = black;
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_vert.vert
new file mode 100644
index 0000000000..1752e5799d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_9float_vert.vert
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m = mat3(gtf_Color.r, gtf_Color.g, gtf_Color.b, gtf_Color.r, gtf_Color.g, gtf_Color.b, gtf_Color.r, gtf_Color.g, gtf_Color.b);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+
+ if(m[0][0] != gtf_Color.r) result = black;
+ if(m[0][1] != gtf_Color.g) result = black;
+ if(m[0][2] != gtf_Color.b) result = black;
+ if(m[1][0] != gtf_Color.r) result = black;
+ if(m[1][1] != gtf_Color.g) result = black;
+ if(m[1][2] != gtf_Color.b) result = black;
+ if(m[2][0] != gtf_Color.r) result = black;
+ if(m[2][1] != gtf_Color.g) result = black;
+ if(m[2][2] != gtf_Color.b) result = black;
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_frag.frag
new file mode 100644
index 0000000000..cead1e7a20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a 3 by 3 matrix with unique elements.
+ mat3 a = mat3( 1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0);
+
+ // Copy the matrix to another non-const matrix.
+ mat3 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 3.0) elms = false;
+ if(b[1][0] != 4.0) elms = false;
+ if(b[1][1] != 5.0) elms = false;
+ if(b[1][2] != 6.0) elms = false;
+ if(b[2][0] != 7.0) elms = false;
+ if(b[2][1] != 8.0) elms = false;
+ if(b[2][2] != 9.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0];
+ if( x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON ) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON ) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2];
+ if(x < 18.0-ERROR_EPSILON || x > 18.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2];
+ if( x < 6.0-ERROR_EPSILON || x > 6.0+ERROR_EPSILON ) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2];
+ if(x < 24.0-ERROR_EPSILON || x > 24.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_vert.vert
new file mode 100644
index 0000000000..2432aba504
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_copy_vert.vert
@@ -0,0 +1,65 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a 3 by 3 matrix with unique elements.
+ mat3 a = mat3( 1.0, 2.0, 4.0, // 1.0 8.0 64.0
+ 8.0, 16.0, 32.0, // 2.0 16.0 128.0
+ 64.0, 128.0, 256.0); // 4.0 32.0 256.0
+
+ // Copy the matrix to another non-const matrix.
+ mat3 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 4.0) elms = false;
+ if(b[1][0] != 8.0) elms = false;
+ if(b[1][1] != 16.0) elms = false;
+ if(b[1][2] != 32.0) elms = false;
+ if(b[2][0] != 64.0) elms = false;
+ if(b[2][1] != 128.0) elms = false;
+ if(b[2][2] != 256.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0];
+ if( x < 73.0-ERROR_EPSILON || x > 73.0+ERROR_EPSILON ) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1];
+ if(x < 146.0-ERROR_EPSILON || x > 146.0+ERROR_EPSILON ) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2];
+ if(x < 292.0-ERROR_EPSILON || x > 292.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2];
+ if( x < 7.0-ERROR_EPSILON || x > 7.0+ERROR_EPSILON ) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2];
+ if(x < 56.0-ERROR_EPSILON || x > 56.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2];
+ if(x < 448.0-ERROR_EPSILON || x > 448.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_frag.frag
new file mode 100644
index 0000000000..26d9662bc8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_frag.frag
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m = mat3(0.5);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if((m[0][0] != 0.5))
+ result = black;
+ if((m[0][1] != 0.0))
+ result = black;
+ if((m[0][2] != 0.0))
+ result = black;
+
+ if((m[1][0] != 0.0))
+ result = black;
+ if((m[1][1] != 0.5))
+ result = black;
+ if((m[1][2] != 0.0))
+ result = black;
+
+ if((m[2][0] != 0.0))
+ result = black;
+ if((m[2][1] != 0.0))
+ result = black;
+ if((m[2][2] != 0.5))
+ result = black;
+
+ gl_FragColor = result;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_vert.vert
new file mode 100644
index 0000000000..f3e846d1b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_float_vert.vert
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m = mat3(0.5);
+ vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 result = vec4(1.0, 1.0, 1.0, 1.0);
+
+ if((m[0][0] != 0.5))
+ result = black;
+ if((m[0][1] != 0.0))
+ result = black;
+ if((m[0][2] != 0.0))
+ result = black;
+
+ if((m[1][0] != 0.0))
+ result = black;
+ if((m[1][1] != 0.5))
+ result = black;
+ if((m[1][2] != 0.0))
+ result = black;
+
+ if((m[2][0] != 0.0))
+ result = black;
+ if((m[2][1] != 0.0))
+ result = black;
+ if((m[2][2] != 0.5))
+ result = black;
+
+ color = result;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_frag.frag
new file mode 100644
index 0000000000..f7bc3e0b8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_frag.frag
@@ -0,0 +1,63 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a 3 by 3 matrix with unique elements.
+ mat3 a = mat3( 1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0);
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 3.0) elms = false;
+ if(a[1][0] != 4.0) elms = false;
+ if(a[1][1] != 5.0) elms = false;
+ if(a[1][2] != 6.0) elms = false;
+ if(a[2][0] != 7.0) elms = false;
+ if(a[2][1] != 8.0) elms = false;
+ if(a[2][2] != 9.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0];
+ if( x < 12.0-ERROR_EPSILON || x > 12.0+ERROR_EPSILON ) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON ) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2];
+ if(x < 18.0-ERROR_EPSILON || x > 18.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2];
+ if( x < 6.0-ERROR_EPSILON || x > 6.0+ERROR_EPSILON ) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2];
+ if(x < 24.0-ERROR_EPSILON || x > 24.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_vert.vert
new file mode 100644
index 0000000000..6fee73b959
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat3_vert.vert
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a 3 by 3 matrix with unique elements.
+ mat3 a = mat3( 1.0, 2.0, 4.0, // 1.0 8.0 64.0
+ 8.0, 16.0, 32.0, // 2.0 16.0 128.0
+ 64.0, 128.0, 256.0); // 4.0 32.0 256.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 4.0) elms = false;
+ if(a[1][0] != 8.0) elms = false;
+ if(a[1][1] != 16.0) elms = false;
+ if(a[1][2] != 32.0) elms = false;
+ if(a[2][0] != 64.0) elms = false;
+ if(a[2][1] != 128.0) elms = false;
+ if(a[2][2] != 256.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0];
+ if( x < 73.0-ERROR_EPSILON || x > 73.0+ERROR_EPSILON ) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1];
+ if(x < 146.0-ERROR_EPSILON || x > 146.0+ERROR_EPSILON ) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2];
+ if(x < 292.0-ERROR_EPSILON || x > 292.0+ERROR_EPSILON ) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2];
+ if( x < 7.0-ERROR_EPSILON || x > 7.0+ERROR_EPSILON ) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2];
+ if(x < 56.0-ERROR_EPSILON || x > 56.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2];
+ if(x < 448.0-ERROR_EPSILON || x > 448.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_frag.frag
new file mode 100644
index 0000000000..44a8076999
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_frag.frag
@@ -0,0 +1,57 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+ float gray,sum1=0.0,sum2=0.0,sum3=0.0,sum4=0.0;
+ int i;
+
+
+ sum1 += a[0][0];
+ sum2 += a[1][0];
+ sum3 += a[2][0];
+ sum4 += a[3][0];
+
+ sum1 += a[0][1];
+ sum2 += a[1][1];
+ sum3 += a[2][1];
+ sum4 += a[3][1];
+
+ sum1 += a[0][2];
+ sum2 += a[1][2];
+ sum3 += a[2][2];
+ sum4 += a[3][2];
+
+ sum1 += a[0][3];
+ sum2 += a[1][3];
+ sum3 += a[2][3];
+ sum4 += a[3][3];
+
+ if( ( sum1 > 10.0-ERROR_EPSILON && sum1 < 10.0+ERROR_EPSILON ) &&
+ ( sum2 > 26.0-ERROR_EPSILON && sum2 < 26.0+ERROR_EPSILON) &&
+ ( sum3 > 42.0-ERROR_EPSILON && sum3 < 42.0+ERROR_EPSILON) &&
+ ( sum4 > 58.0-ERROR_EPSILON && sum4 < 58.0+ERROR_EPSILON) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_vert.vert
new file mode 100644
index 0000000000..2e3622f679
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_16float_vert.vert
@@ -0,0 +1,54 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ mat4 a = mat4(1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+
+ float gray,sum1=0.0,sum2=0.0,sum3=0.0,sum4=0.0;
+ int i;
+
+ sum1 = sum1 + a[0][0];
+ sum2 = sum2 + a[1][0];
+ sum3 = sum3 + a[2][0];
+ sum4 = sum4 + a[3][0];
+
+ sum1 = sum1 + a[0][1];
+ sum2 = sum2 + a[1][1];
+ sum3 = sum3 + a[2][1];
+ sum4 = sum4 + a[3][1];
+
+ sum1 = sum1 + a[0][2];
+ sum2 = sum2 + a[1][2];
+ sum3 = sum3 + a[2][2];
+ sum4 = sum4 + a[3][2];
+
+ sum1 = sum1 + a[0][3];
+ sum2 = sum2 + a[1][3];
+ sum3 = sum3 + a[2][3];
+ sum4 = sum4 + a[3][3];
+
+ if( ( sum1 > 10.0-ERROR_EPSILON && sum1 < 10.0+ERROR_EPSILON ) &&
+ ( sum2 > 26.0-ERROR_EPSILON && sum2 < 26.0+ERROR_EPSILON) &&
+ ( sum3 > 42.0-ERROR_EPSILON && sum3 < 42.0+ERROR_EPSILON) &&
+ ( sum4 > 58.0-ERROR_EPSILON && sum4 < 58.0+ERROR_EPSILON) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_frag.frag
new file mode 100644
index 0000000000..053a5739b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_frag.frag
@@ -0,0 +1,59 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ vec4 L1 = vec4(1.0, 2.0, 3.0, 4.0);
+ vec4 L2 = vec4(5.0, 6.0, 7.0, 8.0);
+ vec4 L3 = vec4(9.0, 10.0, 11.0, 12.0);
+ vec4 L4 = vec4(13.0, 14.0, 15.0, 16.0);
+
+ mat4 a = mat4(L1,L2,L3,L4);
+
+ float gray,sum1=0.0,sum2=0.0,sum3=0.0,sum4=0.0;
+ int i;
+
+ sum1 = sum1 + a[0][0];
+ sum2 = sum2 + a[1][0];
+ sum3 = sum3 + a[2][0];
+ sum4 = sum4 + a[3][0];
+
+ sum1 = sum1 + a[0][1];
+ sum2 = sum2 + a[1][1];
+ sum3 = sum3 + a[2][1];
+ sum4 = sum4 + a[3][1];
+
+ sum1 = sum1 + a[0][2];
+ sum2 = sum2 + a[1][2];
+ sum3 = sum3 + a[2][2];
+ sum4 = sum4 + a[3][2];
+
+ sum1 = sum1 + a[0][3];
+ sum2 = sum2 + a[1][3];
+ sum3 = sum3 + a[2][3];
+ sum4 = sum4 + a[3][3];
+
+ if( ( sum1 > 10.0-ERROR_EPSILON && sum1 < 10.0+ERROR_EPSILON ) &&
+ ( sum2 > 26.0-ERROR_EPSILON && sum2 < 26.0+ERROR_EPSILON) &&
+ ( sum3 > 42.0-ERROR_EPSILON && sum3 < 42.0+ERROR_EPSILON) &&
+ ( sum4 > 58.0-ERROR_EPSILON && sum4 < 58.0+ERROR_EPSILON) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_vert.vert
new file mode 100644
index 0000000000..c238cdcd15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_4vec4_vert.vert
@@ -0,0 +1,56 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ vec4 L1 = vec4(1.0, 2.0, 3.0, 4.0);
+ vec4 L2 = vec4(5.0, 6.0, 7.0, 8.0);
+ vec4 L3 = vec4(9.0, 10.0, 11.0, 12.0);
+ vec4 L4 = vec4(13.0, 14.0, 15.0, 16.0);
+
+ mat4 a = mat4(L1,L2,L3,L4);
+
+ float gray,sum1=0.0,sum2=0.0,sum3=0.0,sum4=0.0;
+ int i;
+
+ sum1 = sum1 + a[0][0];
+ sum2 = sum2 + a[1][0];
+ sum3 = sum3 + a[2][0];
+ sum4 = sum4 + a[3][0];
+
+ sum1 = sum1 + a[0][1];
+ sum2 = sum2 + a[1][1];
+ sum3 = sum3 + a[2][1];
+ sum4 = sum4 + a[3][1];
+
+ sum1 = sum1 + a[0][2];
+ sum2 = sum2 + a[1][2];
+ sum3 = sum3 + a[2][2];
+ sum4 = sum4 + a[3][2];
+
+ sum1 = sum1 + a[0][3];
+ sum2 = sum2 + a[1][3];
+ sum3 = sum3 + a[2][3];
+ sum4 = sum4 + a[3][3];
+
+ if( ( sum1 > 10.0-ERROR_EPSILON && sum1 < 10.0+ERROR_EPSILON ) &&
+ ( sum2 > 26.0-ERROR_EPSILON && sum2 < 26.0+ERROR_EPSILON) &&
+ ( sum3 > 42.0-ERROR_EPSILON && sum3 < 42.0+ERROR_EPSILON) &&
+ ( sum4 > 58.0-ERROR_EPSILON && sum4 < 58.0+ERROR_EPSILON) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_frag.frag
new file mode 100644
index 0000000000..b36313425f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_frag.frag
@@ -0,0 +1,78 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a constant 4 by 4 matrix with unique elements.
+ mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+
+ // Copy the matrix to another non-const matrix.
+ mat4 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 3.0) elms = false;
+ if(b[0][3] != 4.0) elms = false;
+ if(b[1][0] != 5.0) elms = false;
+ if(b[1][1] != 6.0) elms = false;
+ if(b[1][2] != 7.0) elms = false;
+ if(b[1][3] != 8.0) elms = false;
+ if(b[2][0] != 9.0) elms = false;
+ if(b[2][1] != 10.0) elms = false;
+ if(b[2][2] != 11.0) elms = false;
+ if(b[2][3] != 12.0) elms = false;
+ if(b[3][0] != 13.0) elms = false;
+ if(b[3][1] != 14.0) elms = false;
+ if(b[3][2] != 15.0) elms = false;
+ if(b[3][3] != 16.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0] + b[3][0];
+ if(x < 28.0-ERROR_EPSILON || x > 28.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1] + b[3][1];
+ if(x < 32.0-ERROR_EPSILON || x > 32.0+ERROR_EPSILON) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2] + b[3][2];
+ if(x < 36.0-ERROR_EPSILON || x > 36.0+ERROR_EPSILON) rows = false;
+ x = b[0][3] + b[1][3] + b[2][3] + b[3][3];
+ if(x < 40.0-ERROR_EPSILON || x > 40.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2] + b[0][3];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2] + b[1][3];
+ if(x < 26.0-ERROR_EPSILON || x > 26.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2] + b[2][3];
+ if(x < 42.0-ERROR_EPSILON || x > 42.0+ERROR_EPSILON) cols = false;
+ x = b[3][0] + b[3][1] + b[3][2] + b[3][3];
+ if(x < 58.0-ERROR_EPSILON || x > 58.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_vert.vert
new file mode 100644
index 0000000000..3c06f3258d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_copy_vert.vert
@@ -0,0 +1,77 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a 4 by 4 matrix with unique elements.
+ mat4 a = mat4( 1.0, 2.0, 4.0, 8.0, // 1.0 16.0 256.0 4096.0
+ 16.0, 32.0, 64.0, 128.0, // 2.0 32.0 512.0 8192.0
+ 256.0, 512.0, 1024.0, 2048.0, // 4.0 64.0 1024.0 16384.0
+ 4096.0, 8192.0, 16384.0, 32768.0); // 8.0 128.0 2048.0 32768.0
+
+ // Copy the matrix to another non-const matrix.
+ mat4 b = a;
+
+ // Check each element of the copy.
+ bool elms = true;
+ if(b[0][0] != 1.0) elms = false;
+ if(b[0][1] != 2.0) elms = false;
+ if(b[0][2] != 4.0) elms = false;
+ if(b[0][3] != 8.0) elms = false;
+ if(b[1][0] != 16.0) elms = false;
+ if(b[1][1] != 32.0) elms = false;
+ if(b[1][2] != 64.0) elms = false;
+ if(b[1][3] != 128.0) elms = false;
+ if(b[2][0] != 256.0) elms = false;
+ if(b[2][1] != 512.0) elms = false;
+ if(b[2][2] != 1024.0) elms = false;
+ if(b[2][3] != 2048.0) elms = false;
+ if(b[3][0] != 4096.0) elms = false;
+ if(b[3][1] != 8192.0) elms = false;
+ if(b[3][2] != 16384.0) elms = false;
+ if(b[3][3] != 32768.0) elms = false;
+
+ // Add up each row of the copy.
+ bool rows = true;
+ x = b[0][0] + b[1][0] + b[2][0] + b[3][0];
+ if(x < 4369.0-ERROR_EPSILON || x > 4369.0+ERROR_EPSILON) rows = false;
+ x = b[0][1] + b[1][1] + b[2][1] + b[3][1];
+ if(x < 8738.0-ERROR_EPSILON || x > 8738.0+ERROR_EPSILON) rows = false;
+ x = b[0][2] + b[1][2] + b[2][2] + b[3][2];
+ if(x < 17476.0-ERROR_EPSILON || x > 17476.0+ERROR_EPSILON) rows = false;
+ x = b[0][3] + b[1][3] + b[2][3] + b[3][3];
+ if(x < 34952.0-ERROR_EPSILON || x > 34952.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = b[0][0] + b[0][1] + b[0][2] + b[0][3];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = b[1][0] + b[1][1] + b[1][2] + b[1][3];
+ if(x < 240.0-ERROR_EPSILON || x > 240.0+ERROR_EPSILON) cols = false;
+ x = b[2][0] + b[2][1] + b[2][2] + b[2][3];
+ if(x < 3840.0-ERROR_EPSILON || x > 3840.0+ERROR_EPSILON) cols = false;
+ x = b[3][0] + b[3][1] + b[3][2] + b[3][3];
+ if(x < 61440.0-ERROR_EPSILON || x > 61440.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_frag.frag
new file mode 100644
index 0000000000..92c3f7c890
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_frag.frag
@@ -0,0 +1,75 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+/* This epsilon will work as long as the magnitude of the float is < 128.
+ * This can be seen by taking the spec relative mediump precision of 2^-10:
+ * 0.125 / 2^-10 = 128
+ */
+#define ERROR_EPSILON (0.125)
+
+void main (void)
+{
+ float x;
+ // Declare a 4 by 4 matrix with unique elements.
+ mat4 a = mat4( 1.0, 2.0, 3.0, 4.0,
+ 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0,
+ 13.0, 14.0, 15.0, 16.0);
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 3.0) elms = false;
+ if(a[0][3] != 4.0) elms = false;
+ if(a[1][0] != 5.0) elms = false;
+ if(a[1][1] != 6.0) elms = false;
+ if(a[1][2] != 7.0) elms = false;
+ if(a[1][3] != 8.0) elms = false;
+ if(a[2][0] != 9.0) elms = false;
+ if(a[2][1] != 10.0) elms = false;
+ if(a[2][2] != 11.0) elms = false;
+ if(a[2][3] != 12.0) elms = false;
+ if(a[3][0] != 13.0) elms = false;
+ if(a[3][1] != 14.0) elms = false;
+ if(a[3][2] != 15.0) elms = false;
+ if(a[3][3] != 16.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0] + a[3][0];
+ if(x < 28.0-ERROR_EPSILON || x > 28.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1] + a[3][1];
+ if(x < 32.0-ERROR_EPSILON || x > 32.0+ERROR_EPSILON) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2] + a[3][2];
+ if(x < 36.0-ERROR_EPSILON || x > 36.0+ERROR_EPSILON) rows = false;
+ x = a[0][3] + a[1][3] + a[2][3] + a[3][3];
+ if(x < 40.0-ERROR_EPSILON || x > 40.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column of the copy.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2] + a[0][3];
+ if(x < 10.0-ERROR_EPSILON || x > 10.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2] + a[1][3];
+ if(x < 26.0-ERROR_EPSILON || x > 26.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2] + a[2][3];
+ if(x < 42.0-ERROR_EPSILON || x > 42.0+ERROR_EPSILON) cols = false;
+ x = a[3][0] + a[3][1] + a[3][2] + a[3][3];
+ if(x < 58.0-ERROR_EPSILON || x > 58.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the fragment color.
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_vert.vert
new file mode 100644
index 0000000000..d0953158a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat4_vert.vert
@@ -0,0 +1,74 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.1
+
+void main (void)
+{
+ float x;
+ // Declare a 4 by 4 matrix with unique elements.
+ mat4 a = mat4( 1.0, 2.0, 4.0, 8.0, // 1.0 16.0 256.0 4096.0
+ 16.0, 32.0, 64.0, 128.0, // 2.0 32.0 512.0 8192.0
+ 256.0, 512.0, 1024.0, 2048.0, // 4.0 64.0 1024.0 16384.0
+ 4096.0, 8192.0, 16384.0, 32768.0); // 8.0 128.0 2048.0 32768.0
+
+ // Check each element.
+ bool elms = true;
+ if(a[0][0] != 1.0) elms = false;
+ if(a[0][1] != 2.0) elms = false;
+ if(a[0][2] != 4.0) elms = false;
+ if(a[0][3] != 8.0) elms = false;
+ if(a[1][0] != 16.0) elms = false;
+ if(a[1][1] != 32.0) elms = false;
+ if(a[1][2] != 64.0) elms = false;
+ if(a[1][3] != 128.0) elms = false;
+ if(a[2][0] != 256.0) elms = false;
+ if(a[2][1] != 512.0) elms = false;
+ if(a[2][2] != 1024.0) elms = false;
+ if(a[2][3] != 2048.0) elms = false;
+ if(a[3][0] != 4096.0) elms = false;
+ if(a[3][1] != 8192.0) elms = false;
+ if(a[3][2] != 16384.0) elms = false;
+ if(a[3][3] != 32768.0) elms = false;
+
+ // Add up each row.
+ bool rows = true;
+ x = a[0][0] + a[1][0] + a[2][0] + a[3][0];
+ if(x < 4369.0-ERROR_EPSILON || x > 4369.0+ERROR_EPSILON) rows = false;
+ x = a[0][1] + a[1][1] + a[2][1] + a[3][1];
+ if(x < 8738.0-ERROR_EPSILON || x > 8738.0+ERROR_EPSILON) rows = false;
+ x = a[0][2] + a[1][2] + a[2][2] + a[3][2];
+ if(x < 17476.0-ERROR_EPSILON || x > 17476.0+ERROR_EPSILON) rows = false;
+ x = a[0][3] + a[1][3] + a[2][3] + a[3][3];
+ if(x < 34952.0-ERROR_EPSILON || x > 34952.0+ERROR_EPSILON) rows = false;
+
+ // Add up each column.
+ bool cols = true;
+ x = a[0][0] + a[0][1] + a[0][2] + a[0][3];
+ if(x < 15.0-ERROR_EPSILON || x > 15.0+ERROR_EPSILON) cols = false;
+ x = a[1][0] + a[1][1] + a[1][2] + a[1][3];
+ if(x < 240.0-ERROR_EPSILON || x > 240.0+ERROR_EPSILON) cols = false;
+ x = a[2][0] + a[2][1] + a[2][2] + a[2][3];
+ if(x < 3840.0-ERROR_EPSILON || x > 3840.0+ERROR_EPSILON) cols = false;
+ x = a[3][0] + a[3][1] + a[3][2] + a[3][3];
+ if(x < 61440.0-ERROR_EPSILON || x > 61440.0+ERROR_EPSILON) cols = false;
+
+ // Check if all of the operations were successful.
+ float gray = elms && rows && cols ? 1.0 : 0.0;
+
+ // Assign the varying variable color.
+ color = vec4(gray, gray, gray, 1.0);
+
+ // Transform the vertex position.
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_001_to_008.html
new file mode 100644
index 0000000000..e53b2780a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "const_mat2_frag.frag"
+ },
+ "name": "const_mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "const_mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "const_mat2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "const_mat3_frag.frag"
+ },
+ "name": "const_mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "const_mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "const_mat3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "const_mat4_frag.frag"
+ },
+ "name": "const_mat4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "const_mat4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "const_mat4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "const_mat2_copy_frag.frag"
+ },
+ "name": "const_mat2_copy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "const_mat2_copy_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "const_mat2_copy_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_009_to_016.html
new file mode 100644
index 0000000000..0a3e5c1916
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_009_to_016.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "const_mat3_copy_frag.frag"
+ },
+ "name": "const_mat3_copy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "const_mat3_copy_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "const_mat3_copy_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "const_mat4_copy_frag.frag"
+ },
+ "name": "const_mat4_copy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "const_mat4_copy_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "const_mat4_copy_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat2_frag.frag"
+ },
+ "name": "mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat3_frag.frag"
+ },
+ "name": "mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_017_to_024.html
new file mode 100644
index 0000000000..9f0ef60dd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_017_to_024.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_frag.frag"
+ },
+ "name": "mat4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat2_copy_frag.frag"
+ },
+ "name": "mat2_copy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat2_copy_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat2_copy_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat3_copy_frag.frag"
+ },
+ "name": "mat3_copy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat3_copy_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3_copy_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_copy_frag.frag"
+ },
+ "name": "mat4_copy_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_copy_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_copy_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_025_to_032.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_025_to_032.html
new file mode 100644
index 0000000000..58ac71f99a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_025_to_032.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat_025_to_032.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat2_float_frag.frag"
+ },
+ "name": "mat2_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mat2_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat2_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat2_4float_frag.frag"
+ },
+ "name": "mat2_4float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mat2_4float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat2_4float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat2_2vec2_frag.frag"
+ },
+ "name": "mat2_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mat2_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat2_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat3_float_frag.frag"
+ },
+ "name": "mat3_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mat3_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3_float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_033_to_040.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_033_to_040.html
new file mode 100644
index 0000000000..93245d25f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_033_to_040.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat_033_to_040.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat3_9float_frag.frag"
+ },
+ "name": "mat3_9float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mat3_9float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3_9float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat3_3vec3_frag.frag"
+ },
+ "name": "mat3_3vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mat3_3vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3_3vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_4vec4_frag.frag"
+ },
+ "name": "mat4_4vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_4vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_4vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mat4_16float_frag.frag"
+ },
+ "name": "mat4_16float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat4_16float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat4_16float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_041_to_046.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_041_to_046.html
new file mode 100644
index 0000000000..ddb93574a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat/mat_041_to_046.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat_041_to_046.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array_const_mat2_frag.frag"
+ },
+ "name": "array_const_mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "array_const_mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "array_const_mat2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array_const_mat3_frag.frag"
+ },
+ "name": "array_const_mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "array_const_mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "array_const_mat3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "array_const_mat4_frag.frag"
+ },
+ "name": "array_const_mat4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "array_const_mat4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "array_const_mat4_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/input.run.txt
new file mode 100644
index 0000000000..f79e127c27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+mat3_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3_001_to_006.html
new file mode 100644
index 0000000000..cd332fa805
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3_001_to_006.html
@@ -0,0 +1,343 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mat3_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.25,
+ 0.125,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat3arraysimple_vert.vert",
+ "uniforms": {
+ "testmat3": {
+ "count": 2,
+ "type": "uniformMatrix3fv",
+ "transpose": false,
+ "value": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.25
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3arraysimple_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 0.75,
+ 0.625,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat3arrayindirect0_vert.vert",
+ "uniforms": {
+ "testmat3": {
+ "count": 2,
+ "type": "uniformMatrix3fv",
+ "transpose": false,
+ "value": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.25
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3arrayindirect0_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.25,
+ 0.125,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mat3arrayindirect1_vert.vert",
+ "uniforms": {
+ "testmat3": {
+ "count": 2,
+ "type": "uniformMatrix3fv",
+ "transpose": false,
+ "value": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.25
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mat3arrayindirect1_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.25,
+ 0.125,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "testmat3": {
+ "count": 2,
+ "type": "uniformMatrix3fv",
+ "transpose": false,
+ "value": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.25
+ ]
+ }
+ },
+ "fragmentShader": "mat3arraysimple_frag.frag"
+ },
+ "name": "mat3arraysimple_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 0.75,
+ 0.625,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "testmat3": {
+ "count": 2,
+ "type": "uniformMatrix3fv",
+ "transpose": false,
+ "value": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.25
+ ]
+ }
+ },
+ "fragmentShader": "mat3arrayindirect0_frag.frag"
+ },
+ "name": "mat3arrayindirect0_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.25,
+ 0.125,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "testmat3": {
+ "count": 2,
+ "type": "uniformMatrix3fv",
+ "transpose": false,
+ "value": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.25,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.25
+ ]
+ }
+ },
+ "fragmentShader": "mat3arrayindirect1_frag.frag"
+ },
+ "name": "mat3arrayindirect1_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_frag.frag
new file mode 100644
index 0000000000..d1aba8a919
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_frag.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// mat3arrayindirect0_frag.frag: Fragment shader solid color
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform mat3 testmat3[2];
+varying vec4 color;
+
+void main(void)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ /*
+ // No indirect indexing in fragment shaders
+ for(int j = 0; j < 3; j++)
+ {
+ result += testmat3[0][j] + testmat3[1][j];
+ }
+ */
+ result += testmat3[0][0] + testmat3[1][0];
+ result += testmat3[0][1] + testmat3[1][1];
+ result += testmat3[0][2] + testmat3[1][2];
+ gl_FragColor = vec4(result/2.0, 0.5);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_vert.vert
new file mode 100644
index 0000000000..12f3396d26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect0_vert.vert
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// mat3arrayindirect0_vert.vert: Vertex shader solid color
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform mat3 testmat3[2];
+varying vec4 color;
+
+
+void main(void)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ for(int j = 0; j < 3; j++)
+ {
+ result += testmat3[0][j] + testmat3[1][j];
+ }
+
+ color = vec4(result/2.0, 0.5);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_frag.frag
new file mode 100644
index 0000000000..c9a7bf7075
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_frag.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// mat3arrayindirect1_frag.frag: Fragment shader solid color testing indirect referencing into uniforms
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform mat3 testmat3[2];
+varying vec4 color;
+
+void main(void)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ /*
+ // No indirect indexing in fragment shaders
+ for(int j = 0; j < 3; j++)
+ {
+ result += testmat3[1][j];
+ }
+*/
+ result += testmat3[1][0];
+ result += testmat3[1][1];
+ result += testmat3[1][2];
+ gl_FragColor = vec4(result/2.0, 0.5);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_vert.vert
new file mode 100644
index 0000000000..6f66656626
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arrayindirect1_vert.vert
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// mat3arrayindirect1_vert.vert: Vertex shader solid color testing indirect referencing into uniforms
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform mat3 testmat3[2];
+varying vec4 color;
+
+
+void main(void)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ for(int j = 0; j < 3; j++)
+ {
+ result += testmat3[1][j];
+ }
+
+
+ color = vec4(result/2.0, 0.5);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_frag.frag
new file mode 100644
index 0000000000..4e0ee397ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+// mat3arraysimple_frag.frag: Fragment shader solid color testing indirect referencing into uniforms
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform mat3 testmat3[2];
+varying vec4 color;
+
+void main(void)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ result = testmat3[1][0] + testmat3[1][1] + testmat3[1][2];
+ gl_FragColor = vec4(result/2.0, 0.5);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_vert.vert
new file mode 100644
index 0000000000..b05e52a9a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mat3/mat3arraysimple_vert.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// mat3arraysimple_vert.vert: Vertex shader solid color testing indirect referencing into uniforms
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform mat3 testmat3[2];
+varying vec4 color;
+
+
+void main(void)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ result = testmat3[1][0] + testmat3[1][1] + testmat3[1][2];
+
+ color = vec4(result/2.0, 0.5);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/input.run.txt
new file mode 100644
index 0000000000..91d20c86eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+matrixCompMult_001_to_004.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixCompMult_001_to_004.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixCompMult_001_to_004.html
new file mode 100644
index 0000000000..ad6c1d3cdd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixCompMult_001_to_004.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: matrixCompMult_001_to_004.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "matrixMultComp_mat2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "matrixMultComp_mat2_frag.frag"
+ },
+ "name": "matrixMultComp_mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "matrixMultComp_mat2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "matrixMultComp_mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "matrixMultComp_mat2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "matrixMultComp_mat3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "matrixMultComp_mat3_frag.frag"
+ },
+ "name": "matrixMultComp_mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "matrixMultComp_mat3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "matrixMultComp_mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "matrixMultComp_mat3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag.frag
new file mode 100644
index 0000000000..f8e6b692bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m1 = mat2(color.rg, color.ba);
+ mat2 m2 = mat2(1.0, 0.5, 0.5, 1.0);
+ mat2 m3 = mat2(0.0);
+
+ m3 = matrixCompMult(m1, m2);
+ gl_FragColor = vec4(m3[0][0], m3[1][0], m3[0][1], m3[1][1]);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag_ref.frag
new file mode 100644
index 0000000000..5c482c354c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_frag_ref.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m1 = mat2(color.rg, color.ba);
+ mat2 m2 = mat2(1.0, 0.5, 0.5, 1.0);
+ mat2 m3 = mat2(0.0);
+
+ m3[0][0] = m1[0][0] * m2[0][0];
+ m3[0][1] = m1[0][1] * m2[0][1];
+ m3[1][0] = m1[1][0] * m2[1][0];
+ m3[1][1] = m1[1][1] * m2[1][1];
+
+ gl_FragColor = vec4(m3[0][0], m3[1][0], m3[0][1], m3[1][1]);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert.vert
new file mode 100644
index 0000000000..8dcb323df9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m1 = mat2(gtf_Color.r, gtf_Color.g, gtf_Color.b, gtf_Color.a);
+ mat2 m2 = mat2(1.0, 0.5, 0.5, 1.0);
+ mat2 m3 = mat2(0.0);
+
+ m3 = matrixCompMult(m1, m2);
+ color = vec4(m3[0][0], m3[1][0], m3[0][1], m3[1][1]);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert_ref.vert
new file mode 100644
index 0000000000..949181a180
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat2_vert_ref.vert
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat2 m1 = mat2(gtf_Color.r, gtf_Color.g, gtf_Color.b, gtf_Color.a);
+ mat2 m2 = mat2(1.0, 0.5, 0.5, 1.0);
+ mat2 m3 = mat2(0.0);
+
+ m3[0][0] = m1[0][0] * m2[0][0];
+ m3[0][1] = m1[0][1] * m2[0][1];
+ m3[1][0] = m1[1][0] * m2[1][0];
+ m3[1][1] = m1[1][1] * m2[1][1];
+
+ color = vec4(m3[0][0], m3[1][0], m3[0][1], m3[1][1]);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag.frag
new file mode 100644
index 0000000000..823478c2c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m1 = mat3(color.rgb, color.rgb, color.rgb);
+ mat3 m2 = mat3(1.0, 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0);
+ mat3 m3 = mat3(0.0);
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ m3 = matrixCompMult(m1, m2);
+
+ result[0] += m3[0][0];
+ result[0] += m3[0][1];
+ result[0] += m3[0][2];
+
+ result[1] += m3[1][0];
+ result[1] += m3[1][1];
+ result[1] += m3[1][2];
+
+ result[2] += m3[2][0];
+ result[2] += m3[2][1];
+ result[2] += m3[2][2];
+
+ gl_FragColor = vec4(result / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag_ref.frag
new file mode 100644
index 0000000000..6b10418621
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_frag_ref.frag
@@ -0,0 +1,42 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m1 = mat3(color.rgb, color.rgb, color.rgb);
+ mat3 m2 = mat3(1.0, 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0);
+ mat3 m3 = mat3(0.0);
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ m3[0][0] = m1[0][0] * m2[0][0];
+ m3[0][1] = m1[0][1] * m2[0][1];
+ m3[0][2] = m1[0][2] * m2[0][2];
+ m3[1][0] = m1[1][0] * m2[1][0];
+ m3[1][1] = m1[1][1] * m2[1][1];
+ m3[1][2] = m1[1][2] * m2[1][2];
+ m3[2][0] = m1[2][0] * m2[2][0];
+ m3[2][1] = m1[2][1] * m2[2][1];
+ m3[2][2] = m1[2][2] * m2[2][2];
+
+ result[0] += m3[0][0];
+ result[0] += m3[0][1];
+ result[0] += m3[0][2];
+ result[1] += m3[1][0];
+ result[1] += m3[1][1];
+ result[1] += m3[1][2];
+ result[2] += m3[2][0];
+ result[2] += m3[2][1];
+ result[2] += m3[2][2];
+
+ gl_FragColor = vec4(result / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert.vert
new file mode 100644
index 0000000000..82825a3030
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m1 = mat3(gtf_Color.rgb, gtf_Color.rgb, gtf_Color.rgb);
+ mat3 m2 = mat3(1.0, 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0);
+ mat3 m3 = mat3(0.0);
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ m3 = matrixCompMult(m1, m2);
+
+ result[0] += m3[0][0];
+ result[0] += m3[0][1];
+ result[0] += m3[0][2];
+
+ result[1] += m3[1][0];
+ result[1] += m3[1][1];
+ result[1] += m3[1][2];
+
+ result[2] += m3[2][0];
+ result[2] += m3[2][1];
+ result[2] += m3[2][2];
+
+ color = vec4(result / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert_ref.vert
new file mode 100644
index 0000000000..8d4c68cd34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/matrixCompMult/matrixMultComp_mat3_vert_ref.vert
@@ -0,0 +1,47 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ mat3 m1 = mat3(gtf_Color.rgb, gtf_Color.rgb, gtf_Color.rgb);
+ mat3 m2 = mat3(1.0, 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0);
+ mat3 m3 = mat3(0.0);
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ m3[0][0] = m1[0][0] * m2[0][0];
+ m3[0][1] = m1[0][1] * m2[0][1];
+ m3[0][2] = m1[0][2] * m2[0][2];
+
+ m3[1][0] = m1[1][0] * m2[1][0];
+ m3[1][1] = m1[1][1] * m2[1][1];
+ m3[1][2] = m1[1][2] * m2[1][2];
+
+ m3[2][0] = m1[2][0] * m2[2][0];
+ m3[2][1] = m1[2][1] * m2[2][1];
+ m3[2][2] = m1[2][2] * m2[2][2];
+
+ result[0] += m3[0][0];
+ result[0] += m3[0][1];
+ result[0] += m3[0][2];
+
+ result[1] += m3[1][0];
+ result[1] += m3[1][1];
+ result[1] += m3[1][2];
+
+ result[2] += m3[2][0];
+ result[2] += m3[2][1];
+ result[2] += m3[2][2];
+
+ color = vec4(result / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/input.run.txt
new file mode 100644
index 0000000000..552692d678
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+max_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_001_to_006.html
new file mode 100644
index 0000000000..6f36d22cde
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: max_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "max_float_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "max_float_frag_xvary_yconsthalf.frag"
+ },
+ "name": "max_float_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "max_vec2_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "max_vec2_frag_xvary_yconsthalf.frag"
+ },
+ "name": "max_vec2_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "max_vec3_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "max_vec3_frag_xvary_yconsthalf.frag"
+ },
+ "name": "max_vec3_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "max_float_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "max_float_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "max_float_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "max_vec2_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "max_vec2_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "max_vec2_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "max_vec3_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "max_vec3_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "max_vec3_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..f67b0b4bf7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float max_c = 0.5;
+ float c = color.r;
+ gl_FragColor = vec4(max(c, max_c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..4aadedb023
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float max_c = 0.5;
+ float c = color.r;
+ if(c < max_c) c = max_c;
+
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..31624e13fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float max_c = 0.5;
+ float c = gtf_Color.r;
+ color = vec4(max(c, max_c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..c8e5054b2d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_float_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float max_c = 0.5;
+ float c = gtf_Color.r;
+ if(c < max_c) c = max_c;
+
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..63f8f0bf70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 max_c = vec2(0.5, 0.5);
+ vec2 c = color.rg;
+ gl_FragColor = vec4(max(c, max_c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..4935dbd0c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 max_c = vec2(0.5, 0.5);
+ vec2 c = color.rg;
+ if(c[0] < max_c[0]) c[0] = max_c[0];
+ if(c[1] < max_c[1]) c[1] = max_c[1];
+
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..94089c7628
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 max_c = vec2(0.5, 0.5);
+ vec2 c = gtf_Color.rg;
+ color = vec4(max(c, max_c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..5705a9438f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec2_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 max_c = vec2(0.5, 0.5);
+ vec2 c = gtf_Color.rg;
+ if(c[0] < max_c[0]) c[0] = max_c[0];
+ if(c[1] < max_c[1]) c[1] = max_c[1];
+
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..a0709c9477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 max_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(max(c, max_c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..be1c59119c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 max_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = color.rgb;
+ if(c[0] < max_c[0]) c[0] = max_c[0];
+ if(c[1] < max_c[1]) c[1] = max_c[1];
+ if(c[2] < max_c[2]) c[2] = max_c[2];
+
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..1738973213
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 max_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = gtf_Color.rgb;
+ color = vec4(max(c, max_c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..5e09dede0b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/max/max_vec3_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 max_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = gtf_Color.rgb;
+ if(c[0] < max_c[0]) c[0] = max_c[0];
+ if(c[1] < max_c[1]) c[1] = max_c[1];
+ if(c[2] < max_c[2]) c[2] = max_c[2];
+
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/input.run.txt
new file mode 100644
index 0000000000..5c675deae6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+min_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_001_to_006.html
new file mode 100644
index 0000000000..119071f891
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: min_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "min_float_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "min_float_frag_xvary_yconsthalf.frag"
+ },
+ "name": "min_float_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "min_vec2_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "min_vec2_frag_xvary_yconsthalf.frag"
+ },
+ "name": "min_vec2_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "min_vec3_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "min_vec3_frag_xvary_yconsthalf.frag"
+ },
+ "name": "min_vec3_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "min_float_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "min_float_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "min_float_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "min_vec2_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "min_vec2_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "min_vec2_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "min_vec3_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "min_vec3_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "min_vec3_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..033cb89760
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.5;
+ float c = color.r;
+ gl_FragColor = vec4(min(c, min_c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..698b5341d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.5;
+ float c = color.r;
+ if(c > min_c) c = min_c;
+
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..aadc185f2a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.5;
+ float c = gtf_Color.r;
+ color = vec4(min(c, min_c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..140ce28e20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_float_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float min_c = 0.5;
+ float c = gtf_Color.r;
+ if(c > min_c) c = min_c;
+
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..d707e8946c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 min_c = vec2(0.5, 0.5);
+ vec2 c = color.rg;
+ gl_FragColor = vec4(min(c, min_c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..2390a8ea1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 min_c = vec2(0.5, 0.5);
+ vec2 c = color.rg;
+ if(c[0] > min_c[0]) c[0] = min_c[0];
+ if(c[1] > min_c[1]) c[1] = min_c[1];
+
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..0965d586c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 min_c = vec2(0.5, 0.5);
+ vec2 c = gtf_Color.rg;
+ color = vec4(min(c, min_c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..90729852b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec2_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 min_c = vec2(0.5, 0.5);
+ vec2 c = gtf_Color.rg;
+ if(c[0] > min_c[0]) c[0] = min_c[0];
+ if(c[1] > min_c[1]) c[1] = min_c[1];
+
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..d2ef6bbbb0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 min_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(min(c, min_c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..2045641652
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 min_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = color.rgb;
+ if(c[0] > min_c[0]) c[0] = min_c[0];
+ if(c[1] > min_c[1]) c[1] = min_c[1];
+ if(c[2] > min_c[2]) c[2] = min_c[2];
+
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..234368010d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 min_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = gtf_Color.rgb;
+ color = vec4(min(c, min_c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..c4a158d399
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/min/min_vec3_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 min_c = vec3(0.5, 0.5, 0.5);
+ vec3 c = gtf_Color.rgb;
+ if(c[0] > min_c[0]) c[0] = min_c[0];
+ if(c[1] > min_c[1]) c[1] = min_c[1];
+ if(c[2] > min_c[2]) c[2] = min_c[2];
+
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/input.run.txt
new file mode 100644
index 0000000000..f1c7ead980
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+mix_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_001_to_006.html
new file mode 100644
index 0000000000..27ee005d9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mix_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mix_float_frag_xvary_yconsthalf_aconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mix_float_frag_xvary_yconsthalf_aconsthalf.frag"
+ },
+ "name": "mix_float_frag_xvary_yconsthalf_aconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mix_vec2_frag_xvary_yconsthalf_aconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mix_vec2_frag_xvary_yconsthalf_aconsthalf.frag"
+ },
+ "name": "mix_vec2_frag_xvary_yconsthalf_aconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mix_vec3_frag_xvary_yconsthalf_aconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mix_vec3_frag_xvary_yconsthalf_aconsthalf.frag"
+ },
+ "name": "mix_vec3_frag_xvary_yconsthalf_aconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "mix_float_vert_xvary_yconsthalf_aconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mix_float_vert_xvary_yconsthalf_aconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mix_float_vert_xvary_yconsthalf_aconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "mix_vec2_vert_xvary_yconsthalf_aconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mix_vec2_vert_xvary_yconsthalf_aconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mix_vec2_vert_xvary_yconsthalf_aconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "mix_vec3_vert_xvary_yconsthalf_aconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mix_vec3_vert_xvary_yconsthalf_aconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mix_vec3_vert_xvary_yconsthalf_aconsthalf.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf.frag
new file mode 100644
index 0000000000..f921b5752a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float y = 0.5;
+ const float a = 0.5;
+ float c = color.r;
+ gl_FragColor = vec4(mix(c, y, a), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf_ref.frag
new file mode 100644
index 0000000000..f9aec91bde
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_frag_xvary_yconsthalf_aconsthalf_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float y = 0.5;
+ const float a = 0.5;
+ float c = color.r;
+
+ gl_FragColor = vec4(c * (1.0 - a) + y * a, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf.vert
new file mode 100644
index 0000000000..7dd10983fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float y = 0.5;
+ const float a = 0.5;
+ float c = gtf_Color.r;
+ color = vec4(mix(c, y, a), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf_ref.vert
new file mode 100644
index 0000000000..7379a1eb0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_float_vert_xvary_yconsthalf_aconsthalf_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float y = 0.5;
+ const float a = 0.5;
+ float c = gtf_Color.r;
+
+ color = vec4(c * (1.0 - a) + y * a, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf.frag
new file mode 100644
index 0000000000..1392a167df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 y = vec2(0.5, 0.5);
+ const vec2 a = vec2(0.5, 0.5);
+ gl_FragColor = vec4(mix(color.rg, y, a), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf_ref.frag
new file mode 100644
index 0000000000..0b814b8127
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_frag_xvary_yconsthalf_aconsthalf_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 y = vec2(0.5, 0.5);
+ const vec2 a = vec2(0.5, 0.5);
+ vec2 c = color.rg;
+
+ gl_FragColor = vec4(c * (1.0 - a) + y * a, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf.vert
new file mode 100644
index 0000000000..98b357af33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 y = vec2(0.5, 0.5);
+ const vec2 a = vec2(0.5, 0.5);
+ color = vec4(mix(gtf_Color.rg, y, a), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf_ref.vert
new file mode 100644
index 0000000000..19af8d1028
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec2_vert_xvary_yconsthalf_aconsthalf_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 y = vec2(0.5, 0.5);
+ const vec2 a = vec2(0.5, 0.5);
+ vec2 c = gtf_Color.rg;
+
+ color = vec4(c * (1.0 - a) + y * a, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf.frag
new file mode 100644
index 0000000000..9a55d3ff09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 y = vec3(0.5, 0.5, 0.5);
+ const vec3 a = vec3(0.5, 0.5, 0.5);
+ gl_FragColor = vec4(mix(color.rgb, y, a), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf_ref.frag
new file mode 100644
index 0000000000..88e44aae9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_frag_xvary_yconsthalf_aconsthalf_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 y = vec3(0.5, 0.5, 0.5);
+ const vec3 a = vec3(0.5, 0.5, 0.5);
+ vec3 c = color.rgb;
+
+ gl_FragColor = vec4(c * (1.0 - a) + y * a, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf.vert
new file mode 100644
index 0000000000..a7abbd653d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 y = vec3(0.5, 0.5, 0.5);
+ const vec3 a = vec3(0.5, 0.5, 0.5);
+ color = vec4(mix(gtf_Color.rgb, y, a), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf_ref.vert
new file mode 100644
index 0000000000..64aba2a9a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mix/mix_vec3_vert_xvary_yconsthalf_aconsthalf_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 y = vec3(0.5, 0.5, 0.5);
+ const vec3 a = vec3(0.5, 0.5, 0.5);
+ vec3 c = gtf_Color.rgb;
+
+ color = vec4(c * (1.0 - a) + y * a, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/input.run.txt
new file mode 100644
index 0000000000..d369e576f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+mod_001_to_008.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_001_to_008.html
new file mode 100644
index 0000000000..23577304e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_001_to_008.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: mod_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_float_frag_xvary_yconst1_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_float_frag_xvary_yconst1.frag"
+ },
+ "name": "mod_float_frag_xvary_yconst1.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_vec2_frag_xvary_yconst1_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_vec2_frag_xvary_yconst1.frag"
+ },
+ "name": "mod_vec2_frag_xvary_yconst1.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_vec3_frag_xvary_yconst1_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_vec3_frag_xvary_yconst1.frag"
+ },
+ "name": "mod_vec3_frag_xvary_yconst1.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "mod_float_vert_xvary_yconst1_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mod_float_vert_xvary_yconst1.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mod_float_vert_xvary_yconst1.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "mod_vec2_vert_xvary_yconst1_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mod_vec2_vert_xvary_yconst1.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mod_vec2_vert_xvary_yconst1.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "mod_vec3_vert_xvary_yconst1_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "mod_vec3_vert_xvary_yconst1.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mod_vec3_vert_xvary_yconst1.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4f",
+ "value": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "mod_x_large_y_large_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "mod_x_large_y_large_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4f",
+ "value": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "mod_x_large_y_large_frag.frag"
+ },
+ "name": "mod_x_large_y_large_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1.frag
new file mode 100644
index 0000000000..c3ec59b9e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(mod(c, 1.0), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1_ref.frag
new file mode 100644
index 0000000000..616e907f34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_frag_xvary_yconst1_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (color.r - 0.5);
+ c = c - 1.0 * floor(c / 1.0);
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1.vert
new file mode 100644
index 0000000000..85f4a97008
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(mod(c, 1.0), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1_ref.vert
new file mode 100644
index 0000000000..fa709a91a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_float_vert_xvary_yconst1_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 10.0 * 2.0 * (gtf_Color.r - 0.5);
+ c = c - 1.0 * floor(c / 1.0);
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1.frag
new file mode 100644
index 0000000000..b65b6054d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(mod(c, 1.0), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1_ref.frag
new file mode 100644
index 0000000000..4490d64569
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_frag_xvary_yconst1_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (color.rg - 0.5);
+ c = c - 1.0 * floor(c / 1.0);
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1.vert
new file mode 100644
index 0000000000..d622b9a359
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(mod(c, 1.0), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1_ref.vert
new file mode 100644
index 0000000000..62f9c46b00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec2_vert_xvary_yconst1_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 10.0 * 2.0 * (gtf_Color.rg - 0.5);
+ c = c - 1.0 * floor(c / 1.0);
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1.frag
new file mode 100644
index 0000000000..9ecd423dd8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(mod(c, 1.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1_ref.frag
new file mode 100644
index 0000000000..e9cbffb7ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_frag_xvary_yconst1_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (color.rgb - 0.5);
+ c = c - 1.0 * floor(c / 1.0);
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1.vert
new file mode 100644
index 0000000000..3b14becf8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(mod(c, 1.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1_ref.vert
new file mode 100644
index 0000000000..242fcf07b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_vec3_vert_xvary_yconst1_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 10.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ c = c - 1.0 * floor(c / 1.0);
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_frag.frag
new file mode 100644
index 0000000000..7e7128ec27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4(mod(300.0, 100.0), 0.0, 0.0, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_vert.vert
new file mode 100644
index 0000000000..1d168308b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/mod/mod_x_large_y_large_vert.vert
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(mod(300.0, 100.0), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/input.run.txt
new file mode 100644
index 0000000000..56ce6dcbe7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+normalize_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_001_to_006.html
new file mode 100644
index 0000000000..62b9d239d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: normalize_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "normalize_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "normalize_float_frag_xvary.frag"
+ },
+ "name": "normalize_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "normalize_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "normalize_vec2_frag_xvary.frag"
+ },
+ "name": "normalize_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "normalize_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "normalize_vec3_frag_xvary.frag"
+ },
+ "name": "normalize_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "normalize_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "normalize_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "normalize_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "normalize_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "normalize_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "normalize_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "normalize_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "normalize_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "normalize_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary.frag
new file mode 100644
index 0000000000..805f05753e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = color + vec4(0.25);
+ gl_FragColor = vec4(normalize(tmp_Color.r), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..f6cba372fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = color + vec4(0.25);
+ gl_FragColor = vec4(tmp_Color.r / length(tmp_Color.r), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary.vert
new file mode 100644
index 0000000000..988c7a6064
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = gtf_Color + vec4(0.25);
+ color = vec4(normalize(tmp_Color.r), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..3e30cfd84d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_float_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = gtf_Color + vec4(0.25);
+ color = vec4(tmp_Color.r / length(tmp_Color.r), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..c9df5ecc65
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = color + vec4(0.25);
+ gl_FragColor = vec4(normalize(tmp_Color.rg), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..e329881062
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = color + vec4(0.25);
+ gl_FragColor = vec4(tmp_Color.rg / length(tmp_Color.rg), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..837b149468
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = gtf_Color + vec4(0.25);
+ color = vec4(normalize(tmp_Color.rg), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..ecfdfbbc87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec2_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = gtf_Color + vec4(0.25);
+ color = vec4(tmp_Color.rg / length(tmp_Color.rg), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..78115d7e8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = color + vec4(0.25);
+ gl_FragColor = vec4(normalize(tmp_Color.rgb), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..aa89b52583
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = color + vec4(0.25);
+ gl_FragColor = vec4(tmp_Color.rgb / length(tmp_Color.rgb), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..747b879203
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = gtf_Color + vec4(0.25);
+ color = vec4(normalize(tmp_Color.rgb), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..70b06e99ba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/normalize/normalize_vec3_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 tmp_Color = gtf_Color + vec4(0.25);
+ color = vec4(tmp_Color.rgb / length(tmp_Color.rgb), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/input.run.txt
new file mode 100644
index 0000000000..89038b7445
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+not_001_to_004.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_001_to_004.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_001_to_004.html
new file mode 100644
index 0000000000..c505a2f601
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_001_to_004.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: not_001_to_004.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "not_bvec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "not_bvec2_frag.frag"
+ },
+ "name": "not_bvec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "not_bvec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "not_bvec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "not_bvec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "not_bvec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "not_bvec3_frag.frag"
+ },
+ "name": "not_bvec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "not_bvec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "not_bvec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "not_bvec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag.frag
new file mode 100644
index 0000000000..0a89d7ba84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec2(not(bvec2(c))), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag_ref.frag
new file mode 100644
index 0000000000..7bd26175f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_frag_ref.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 _not(in bvec2 a)
+{
+ bvec2 result;
+ if(a[0]) result[0] = false;
+ else result[0] = true;
+ if(a[1]) result[1] = false;
+ else result[1] = true;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec2(_not(bvec2(c))), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert.vert
new file mode 100644
index 0000000000..9006e480d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ color = vec4(vec2(not(bvec2(c))), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert_ref.vert
new file mode 100644
index 0000000000..bd3528fa94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec2_vert_ref.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 _not(in bvec2 a)
+{
+ bvec2 result;
+ if(a[0]) result[0] = false;
+ else result[0] = true;
+ if(a[1]) result[1] = false;
+ else result[1] = true;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ color = vec4(vec2(_not(bvec2(c))), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag.frag
new file mode 100644
index 0000000000..a0d6beaf91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec3(not(bvec3(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag_ref.frag
new file mode 100644
index 0000000000..5cfc127c63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_frag_ref.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 _not(in bvec3 a)
+{
+ bvec3 result;
+ if(a[0]) result[0] = false;
+ else result[0] = true;
+ if(a[1]) result[1] = false;
+ else result[1] = true;
+ if(a[2]) result[2] = false;
+ else result[2] = true;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ gl_FragColor = vec4(vec3(_not(bvec3(c))), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert.vert
new file mode 100644
index 0000000000..48d99112be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ color = vec4(vec3(not(bvec3(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert_ref.vert
new file mode 100644
index 0000000000..7d54ec2cfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/not/not_bvec3_vert_ref.vert
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 _not(in bvec3 a)
+{
+ bvec3 result;
+ if(a[0]) result[0] = false;
+ else result[0] = true;
+ if(a[1]) result[1] = false;
+ else result[1] = true;
+ if(a[2]) result[2] = false;
+ else result[2] = true;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ color = vec4(vec3(_not(bvec3(c))), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/input.run.txt
new file mode 100644
index 0000000000..9bc23768ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/input.run.txt
@@ -0,0 +1,3 @@
+# this file is auto-generated. DO NOT EDIT.
+notEqual_001_to_008.html
+notEqual_009_to_012.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_001_to_008.html
new file mode 100644
index 0000000000..5ad5a6bcc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: notEqual_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_vec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_vec2_frag.frag"
+ },
+ "name": "notEqual_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "notEqual_vec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "notEqual_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "notEqual_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_vec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_vec3_frag.frag"
+ },
+ "name": "notEqual_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "notEqual_vec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "notEqual_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "notEqual_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_ivec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_ivec2_frag.frag"
+ },
+ "name": "notEqual_ivec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "notEqual_ivec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "notEqual_ivec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "notEqual_ivec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_ivec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_ivec3_frag.frag"
+ },
+ "name": "notEqual_ivec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "notEqual_ivec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "notEqual_ivec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "notEqual_ivec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_009_to_012.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_009_to_012.html
new file mode 100644
index 0000000000..c2693e7fec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_009_to_012.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: notEqual_009_to_012.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_bvec2_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_bvec2_frag.frag"
+ },
+ "name": "notEqual_bvec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "notEqual_bvec2_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "notEqual_bvec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "notEqual_bvec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_bvec3_frag_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "notEqual_bvec3_frag.frag"
+ },
+ "name": "notEqual_bvec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "notEqual_bvec3_vert_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "notEqual_bvec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "notEqual_bvec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag.frag
new file mode 100644
index 0000000000..49df59dfb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(notEqual(bvec2(c), bvec2(true)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag_ref.frag
new file mode 100644
index 0000000000..b436a76ce2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 ne(in bvec2 a, in bvec2 b)
+{
+ bvec2 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(ne(bvec2(c), bvec2(true)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert.vert
new file mode 100644
index 0000000000..974111cdad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(notEqual(bvec2(c), bvec2(true)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert_ref.vert
new file mode 100644
index 0000000000..022d3b2186
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 ne(in bvec2 a, in bvec2 b)
+{
+ bvec2 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(1.5 * gtf_Color.rg); // 1/3 true, 2/3 false
+ vec2 result = vec2(ne(bvec2(c), bvec2(true)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag.frag
new file mode 100644
index 0000000000..ee17b824a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(notEqual(bvec3(c), bvec3(true)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag_ref.frag
new file mode 100644
index 0000000000..86607e8449
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 ne(in bvec3 a, in bvec3 b)
+{
+ bvec3 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] != b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(ne(bvec3(c), bvec3(true)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert.vert
new file mode 100644
index 0000000000..beed0319b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(notEqual(bvec3(c), bvec3(true)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert_ref.vert
new file mode 100644
index 0000000000..0a9a60b77b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_bvec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 ne(in bvec3 a, in bvec3 b)
+{
+ bvec3 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] != b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(1.5 * gtf_Color.rgb); // 1/3 true, 2/3 false
+ vec3 result = vec3(ne(bvec3(c), bvec3(true)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag.frag
new file mode 100644
index 0000000000..f996de0530
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(notEqual(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag_ref.frag
new file mode 100644
index 0000000000..9c15d3941b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_frag_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec2 ne(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(ne(ivec2(c), ivec2(0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert.vert
new file mode 100644
index 0000000000..7305ff1599
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(notEqual(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert_ref.vert
new file mode 100644
index 0000000000..824b870db8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 ne(in ivec2 a, in ivec2 b)
+{
+ bvec2 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(ne(ivec2(c), ivec2(0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag.frag
new file mode 100644
index 0000000000..48ada5f7b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(notEqual(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag_ref.frag
new file mode 100644
index 0000000000..4401b1d798
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 ne(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] != b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(ne(ivec3(c), ivec3(0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert.vert
new file mode 100644
index 0000000000..4aa2e34cc2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(notEqual(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert_ref.vert
new file mode 100644
index 0000000000..eb07abcf64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_ivec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 ne(in ivec3 a, in ivec3 b)
+{
+ bvec3 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] != b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(ne(ivec3(c), ivec3(0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag.frag
new file mode 100644
index 0000000000..ab1b496119
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(notEqual(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag_ref.frag
new file mode 100644
index 0000000000..71320e67c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_frag_ref.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+varying vec4 color;
+
+bvec2 ne(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(ne(c, vec2(0.0)));
+ gl_FragColor = vec4(result, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert.vert
new file mode 100644
index 0000000000..c7931c787b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(notEqual(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert_ref.vert
new file mode 100644
index 0000000000..1892d3ad89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec2_vert_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec2 ne(in vec2 a, in vec2 b)
+{
+ bvec2 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec2 c = floor(10.0 * gtf_Color.rg - 4.5); // round to the nearest integer
+ vec2 result = vec2(ne(c, vec2(0.0)));
+ color = vec4(result, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag.frag
new file mode 100644
index 0000000000..fe7d7a1153
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(notEqual(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag_ref.frag
new file mode 100644
index 0000000000..8a18ea0327
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_frag_ref.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+bvec3 ne(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] != b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(ne(c, vec3(0.0)));
+ gl_FragColor = vec4(result, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert.vert
new file mode 100644
index 0000000000..a97081973a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(notEqual(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert_ref.vert
new file mode 100644
index 0000000000..a6c5687e24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/notEqual/notEqual_vec3_vert_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+bvec3 ne(in vec3 a, in vec3 b)
+{
+ bvec3 result;
+ if(a[0] != b[0]) result[0] = true;
+ else result[0] = false;
+ if(a[1] != b[1]) result[1] = true;
+ else result[1] = false;
+ if(a[2] != b[2]) result[2] = true;
+ else result[2] = false;
+ return result;
+}
+
+void main (void)
+{
+ vec3 c = floor(10.0 * gtf_Color.rgb - 4.5); // round to the nearest integer
+ vec3 result = vec3(ne(c, vec3(0.0)));
+ color = vec4(result, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_frag.frag
new file mode 100644
index 0000000000..e6b6950392
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ int resultadd = m + k;
+ int resultsubtract = m - k;
+ float gray;
+ if( ( resultadd == 114 ) && ( resultsubtract == 90 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_vert.vert
new file mode 100644
index 0000000000..fc2b8ca837
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/addsubtract_vert.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ int resultadd = m + k;
+ int resultsubtract = m - k;
+ float gray;
+ if( ( resultadd == 114 ) && ( resultsubtract == 90 ) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_frag.frag
new file mode 100644
index 0000000000..07757a8733
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_frag.frag
@@ -0,0 +1,61 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 12;
+ int n = 102;
+ bool result = true;
+ int r = m;
+
+ if( r==12 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r += m;
+
+ if( r == 24 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r-= m;
+
+ if( r == 12 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r*= m;
+
+ if ( r == 144 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r/= m;
+
+ // Integer divide can be implemented via float reciprocal,
+ // so the result need not be exact
+ if( r >= 11 && r <= 13 )
+ result = result && true;
+ else
+ result = result && false;
+
+ float gray;
+ if( result )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_vert.vert
new file mode 100644
index 0000000000..4ce8bea9b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/assignments_vert.vert
@@ -0,0 +1,61 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = 12;
+ int n = 102;
+ bool result = true;
+ int r = m;
+
+ if( r==12 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r += m;
+
+ if( r == 24 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r-= m;
+
+ if( r == 12 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r*= m;
+
+ if ( r == 144 )
+ result = result && true;
+ else
+ result = result && false;
+
+ r/= m;
+
+ // Integer divide can be implemented via float reciprocal,
+ // so the result need not be exact
+ if( r >= 11 && r <= 13 )
+ result = result && true;
+ else
+ result = result && false;
+
+ float gray;
+ if( result )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_frag.frag
new file mode 100644
index 0000000000..e46ca4ea9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ int result = m/k;
+ float gray;
+ // The rounding mode for integer divide is implementation-dependent
+ if( ( result == 8 ) || ( result == 9 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_vert.vert
new file mode 100644
index 0000000000..a3c2d39bf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/division_vert.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ int result = m/k;
+ float gray;
+ // The rounding mode for integer divide is implementation-dependent
+ if( ( result == 8 ) || ( result == 9 ) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_frag.frag
new file mode 100644
index 0000000000..03bd0024a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ bool equalto = (m == 102);
+ bool notequalto = (k != 102);
+
+ float gray;
+ if( equalto && notequalto )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_vert.vert
new file mode 100644
index 0000000000..f33596562a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/equality_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ bool equalto = (m == 102);
+ bool notequalto = (k != 102);
+
+ float gray;
+ if( equalto && notequalto )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/input.run.txt
new file mode 100644
index 0000000000..b6e176588b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/input.run.txt
@@ -0,0 +1,5 @@
+# this file is auto-generated. DO NOT EDIT.
+operators_001_to_008.html
+operators_009_to_016.html
+operators_017_to_024.html
+operators_025_to_026.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_frag.frag
new file mode 100644
index 0000000000..c6749092d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_frag.frag
@@ -0,0 +1,94 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+bool result = true;
+ bool a = true;
+ bool b = true;
+
+ if( (a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( !(a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ a = true;
+ b = false;
+
+ if( !(a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ a = false;
+ b = true;
+
+ if( !(a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ a = false;
+ b = false;
+
+ if( !(a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( !(a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( !(a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ float gray;
+ if( result )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_vert.vert
new file mode 100644
index 0000000000..1d5deb2c92
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/logical_vert.vert
@@ -0,0 +1,94 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ bool result = true;
+ bool a = true;
+ bool b = true;
+
+ if( (a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( !(a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ a = true;
+ b = false;
+
+ if( !(a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ a = false;
+ b = true;
+
+ if( !(a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( (a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ a = false;
+ b = false;
+
+ if( !(a&&b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( !(a||b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ if( !(a^^b) )
+ result = result && true;
+ else
+ result = result && false;
+
+ float gray;
+ if( result )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_frag.frag
new file mode 100644
index 0000000000..9c1b56acb6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ int result = m*k;
+ float gray;
+ if( ( result == 1224 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_vert.vert
new file mode 100644
index 0000000000..a2146c8016
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/multiplicative_vert.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ int result = m*k;
+ float gray;
+ if( ( result == 1224 ) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_001_to_008.html
new file mode 100644
index 0000000000..01f0a0d408
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: operators_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "postfixincrement_frag.frag"
+ },
+ "name": "postfixincrement_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "postfixincrement_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "postfixincrement_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "postfixdecrement_frag.frag"
+ },
+ "name": "postfixdecrement_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "postfixdecrement_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "postfixdecrement_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "prefixincrement_frag.frag"
+ },
+ "name": "prefixincrement_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "prefixincrement_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "prefixincrement_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "prefixdecrement_frag.frag"
+ },
+ "name": "prefixdecrement_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "prefixdecrement_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "prefixdecrement_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_009_to_016.html
new file mode 100644
index 0000000000..247592ce6d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_009_to_016.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: operators_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "unary_frag.frag"
+ },
+ "name": "unary_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "unary_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "unary_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "multiplicative_frag.frag"
+ },
+ "name": "multiplicative_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "multiplicative_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "multiplicative_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "division_frag.frag"
+ },
+ "name": "division_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "division_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "division_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "addsubtract_frag.frag"
+ },
+ "name": "addsubtract_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "addsubtract_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "addsubtract_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_017_to_024.html
new file mode 100644
index 0000000000..c9ee23c3c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_017_to_024.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: operators_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "relational_frag.frag"
+ },
+ "name": "relational_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "relational_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "relational_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "equality_frag.frag"
+ },
+ "name": "equality_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "equality_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "equality_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "logical_frag.frag"
+ },
+ "name": "logical_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "logical_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "logical_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "selection_frag.frag"
+ },
+ "name": "selection_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "selection_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "selection_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_025_to_026.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_025_to_026.html
new file mode 100644
index 0000000000..20329db2eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/operators_025_to_026.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: operators_025_to_026.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "assignments_frag.frag"
+ },
+ "name": "assignments_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "assignments_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "assignments_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_frag.frag
new file mode 100644
index 0000000000..67b5cb4274
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 23;
+ int k = m--;
+ float gray;
+ if( ( k == 23 ) && ( m == 22 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_vert.vert
new file mode 100644
index 0000000000..02f39bed10
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixdecrement_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m=23;
+ int k = m--;
+ float gray;
+ if( (k==23) && (m==22) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_frag.frag
new file mode 100644
index 0000000000..4d81f908c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 23;
+ int k = m++;
+ float gray;
+ if( ( k == 23 ) && ( m == 24 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_vert.vert
new file mode 100644
index 0000000000..4b074f1e91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/postfixincrement_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m=23;
+ int k = m++;
+ float gray;
+ if( (k==23) && (m==24) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_frag.frag
new file mode 100644
index 0000000000..fa558e2944
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 23;
+ int k = --m;
+ float gray;
+ if( ( k == 22 ) && ( m == 22 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_vert.vert
new file mode 100644
index 0000000000..2c2b7f18db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixdecrement_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m=23;
+ int k = --m;
+ float gray;
+ if( (k==22) && (m==22) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_frag.frag
new file mode 100644
index 0000000000..2369cd0e26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 23;
+ int k = ++m;
+ float gray;
+ if( ( k == 24 ) && ( m == 24 ) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_vert.vert
new file mode 100644
index 0000000000..5cf4494b59
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/prefixincrement_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m=23;
+ int k = ++m;
+ float gray;
+ if( (k==24) && (m==24) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_frag.frag
new file mode 100644
index 0000000000..015633727e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_frag.frag
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ bool lessthan = (m<k);
+ bool greaterthan = (m>k);
+ bool lessthanorequalto = (m <= 102);
+ bool greaterthanorequalto = (k >=12);
+ float gray;
+ if( !lessthan && greaterthan && lessthanorequalto && greaterthanorequalto )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_vert.vert
new file mode 100644
index 0000000000..99a58b1414
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/relational_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = 102;
+ int k = 12;
+ bool lessthan = (m<k);
+ bool greaterthan = (m>k);
+ bool lessthanorequalto = (m <= 102);
+ bool greaterthanorequalto = (k >=12);
+
+ float gray;
+ if( !lessthan && greaterthan && lessthanorequalto && greaterthanorequalto )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_frag.frag
new file mode 100644
index 0000000000..c69f56b7c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_frag.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int j = 30;
+ int k = 37;
+ int y = 10;
+ int n = 12;
+ bool result1 = false;
+ bool result2 = false;
+ (j>k)?( result1 = true ):( result1 = false );
+ (y<n)?( result2 = true ):( result2 = false );
+ float gray;
+ if( !result1 && result2 )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_vert.vert
new file mode 100644
index 0000000000..bf038a1bc7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/selection_vert.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int j = 30;
+ int k = 37;
+ int y = 10;
+ int n = 12;
+ bool result1 = false;
+ bool result2 = false;
+ (j>k)?( result1 = true ):( result1 = false );
+ (y<n)?( result2 = true ):( result2 = false );
+ float gray;
+ if( !result1 && result2 )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_frag.frag
new file mode 100644
index 0000000000..6a59b278e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ int m = +23;
+ int k = -m;
+ bool a = false;
+ bool b = !a;
+ float gray;
+ if( (m==23) && (k==-23) && (b) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_vert.vert
new file mode 100644
index 0000000000..0b10409794
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/operators/unary_vert.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ int m = +23;
+ int k = -m;
+ bool a = false;
+ bool b = !a;
+ float gray;
+ if( (m==23) && (k==-23) && (b) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/input.run.txt
new file mode 100644
index 0000000000..c9bfeda779
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/input.run.txt
@@ -0,0 +1,4 @@
+# this file is auto-generated. DO NOT EDIT.
+pow_001_to_008.html
+pow_009_to_016.html
+pow_017_to_024.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_001_to_008.html
new file mode 100644
index 0000000000..ce0d5901db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: pow_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xvary_yconst2_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xvary_yconst2.frag"
+ },
+ "name": "pow_float_frag_xvary_yconst2.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xvary_yconst2_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xvary_yconst2.frag"
+ },
+ "name": "pow_vec2_frag_xvary_yconst2.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xvary_yconst2_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xvary_yconst2.frag"
+ },
+ "name": "pow_vec3_frag_xvary_yconst2.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xconst2_yvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xconst2_yvary.frag"
+ },
+ "name": "pow_float_frag_xconst2_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xconst2_yvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xconst2_yvary.frag"
+ },
+ "name": "pow_vec2_frag_xconst2_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xconst2_yvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xconst2_yvary.frag"
+ },
+ "name": "pow_vec3_frag_xconst2_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xvary_yconsthalf.frag"
+ },
+ "name": "pow_float_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xvary_yconsthalf.frag"
+ },
+ "name": "pow_vec2_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_009_to_016.html
new file mode 100644
index 0000000000..7eb6d3d008
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_009_to_016.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: pow_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xvary_yconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xvary_yconsthalf.frag"
+ },
+ "name": "pow_vec3_frag_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xconsthalf_yvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_float_frag_xconsthalf_yvary.frag"
+ },
+ "name": "pow_float_frag_xconsthalf_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xconsthalf_yvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec2_frag_xconsthalf_yvary.frag"
+ },
+ "name": "pow_vec2_frag_xconsthalf_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xconsthalf_yvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "pow_vec3_frag_xconsthalf_yvary.frag"
+ },
+ "name": "pow_vec3_frag_xconsthalf_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_float_vert_xvary_yconst2_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_float_vert_xvary_yconst2.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_float_vert_xvary_yconst2.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec2_vert_xvary_yconst2_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec2_vert_xvary_yconst2.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec2_vert_xvary_yconst2.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec3_vert_xvary_yconst2_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec3_vert_xvary_yconst2.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec3_vert_xvary_yconst2.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_float_vert_xconst2_yvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_float_vert_xconst2_yvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_float_vert_xconst2_yvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_017_to_024.html
new file mode 100644
index 0000000000..1c7a0ca3e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_017_to_024.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: pow_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec2_vert_xconst2_yvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec2_vert_xconst2_yvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec2_vert_xconst2_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec3_vert_xconst2_yvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec3_vert_xconst2_yvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec3_vert_xconst2_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_float_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_float_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_float_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec2_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec2_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec2_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec3_vert_xvary_yconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec3_vert_xvary_yconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec3_vert_xvary_yconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_float_vert_xconsthalf_yvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_float_vert_xconsthalf_yvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_float_vert_xconsthalf_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec2_vert_xconsthalf_yvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec2_vert_xconsthalf_yvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec2_vert_xconsthalf_yvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "pow_vec3_vert_xconsthalf_yvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "pow_vec3_vert_xconsthalf_yvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "pow_vec3_vert_xconsthalf_yvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary.frag
new file mode 100644
index 0000000000..5483af5014
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(pow(2.0, 2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary_ref.frag
new file mode 100644
index 0000000000..41ab8fee37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconst2_yvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(exp2(2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary.frag
new file mode 100644
index 0000000000..fa48023b3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(pow(0.5, 2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary_ref.frag
new file mode 100644
index 0000000000..e21d8ff815
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xconsthalf_yvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = -2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(exp2(2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2.frag
new file mode 100644
index 0000000000..e3b91e98f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 4.0 * (color.r);
+ gl_FragColor = vec4(pow(c, 2.0) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2_ref.frag
new file mode 100644
index 0000000000..cfb2a0cf74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconst2_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 4.0 * (color.r);
+ gl_FragColor = vec4(c * c / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..6aea7b50cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 16.0 * color.r;
+ gl_FragColor = vec4(pow(c, 0.5) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..871b1b722b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 16.0 * color.r;
+ gl_FragColor = vec4(sqrt(c) / 4.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary.vert
new file mode 100644
index 0000000000..c8c54ebb73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(pow(2.0, 2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary_ref.vert
new file mode 100644
index 0000000000..9dfba0f5b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconst2_yvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(exp2(2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary.vert
new file mode 100644
index 0000000000..34b0ffc3c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(pow(0.5, 2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary_ref.vert
new file mode 100644
index 0000000000..e3c71fe606
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xconsthalf_yvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = -2.0 * (gtf_Color.r - 0.5);
+ color = vec4(exp2(2.0 * c) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2.vert
new file mode 100644
index 0000000000..417da137ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 4.0 * (gtf_Color.r);
+ color = vec4(pow(c, 2.0) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2_ref.vert
new file mode 100644
index 0000000000..a4aea47dd4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconst2_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 4.0 * (gtf_Color.r);
+ color = vec4(c * c / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..c5dde20ee3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 16.0 * gtf_Color.r;
+ color = vec4(pow(c, 0.5) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..cd892b69d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_float_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 16.0 * gtf_Color.r;
+ color = vec4(sqrt(c) / 4.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary.frag
new file mode 100644
index 0000000000..c6186399c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(pow(vec2(2.0), 2.0 * c) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary_ref.frag
new file mode 100644
index 0000000000..78afa91058
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconst2_yvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(exp2(2.0 * c) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary.frag
new file mode 100644
index 0000000000..61de4a7c81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(pow(vec2(0.5), 2.0 * c) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary_ref.frag
new file mode 100644
index 0000000000..9b51524d9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xconsthalf_yvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = -2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(exp2(2.0 * c) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2.frag
new file mode 100644
index 0000000000..8b2b2d2dea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 4.0 * (color.rg);
+ gl_FragColor = vec4(pow(c, vec2(2.0)) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2_ref.frag
new file mode 100644
index 0000000000..bb55c7789d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconst2_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 4.0 * (color.rg);
+ gl_FragColor = vec4(c * c / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..13d18c46eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 16.0 * color.rg;
+ gl_FragColor = vec4(pow(c, vec2(0.5)) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..558b7c32f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 16.0 * color.rg;
+ gl_FragColor = vec4(sqrt(c) / 4.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary.vert
new file mode 100644
index 0000000000..981673e5b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(pow(vec2(2.0), 2.0 * c) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary_ref.vert
new file mode 100644
index 0000000000..f3e95dc4a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconst2_yvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(exp2(2.0 * c) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary.vert
new file mode 100644
index 0000000000..e2a3a51a08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(pow(vec2(0.5), 2.0 * c) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary_ref.vert
new file mode 100644
index 0000000000..2d76b7689e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xconsthalf_yvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = -2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(exp2(2.0 * c) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2.vert
new file mode 100644
index 0000000000..f7d2c22907
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 4.0 * (gtf_Color.rg);
+ color = vec4(pow(c, vec2(2.0)) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2_ref.vert
new file mode 100644
index 0000000000..05968e48b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconst2_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 4.0 * (gtf_Color.rg);
+ color = vec4(c * c / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..96bd4f2bd6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 16.0 * gtf_Color.rg;
+ color = vec4(pow(c, vec2(0.5)) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..8830c4e9a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec2_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 16.0 * gtf_Color.rg;
+ color = vec4(sqrt(c) / 4.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary.frag
new file mode 100644
index 0000000000..8d0e893f0a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(pow(vec3(2.0), 2.0 * c) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary_ref.frag
new file mode 100644
index 0000000000..f037a62bc2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconst2_yvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(exp2(2.0 * c) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary.frag
new file mode 100644
index 0000000000..991c9b804d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(pow(vec3(0.5), 2.0 * c) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary_ref.frag
new file mode 100644
index 0000000000..56a18afdba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xconsthalf_yvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = -2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(exp2(2.0 * c) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2.frag
new file mode 100644
index 0000000000..a54698468b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(pow(c, vec3(2.0)) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2_ref.frag
new file mode 100644
index 0000000000..9b63625665
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconst2_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = color.rgb;
+ gl_FragColor = vec4(c * c / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf.frag
new file mode 100644
index 0000000000..cd057ed727
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 16.0 * color.rgb;
+ gl_FragColor = vec4(pow(c, vec3(0.5)) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf_ref.frag
new file mode 100644
index 0000000000..d9aadd9fb6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_frag_xvary_yconsthalf_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 16.0 * color.rgb;
+ gl_FragColor = vec4(sqrt(c) / 4.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary.vert
new file mode 100644
index 0000000000..beda501bb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(pow(vec3(2.0), 2.0 * c) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary_ref.vert
new file mode 100644
index 0000000000..5b4377d889
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconst2_yvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(exp2(2.0 * c) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary.vert
new file mode 100644
index 0000000000..69dfa29e46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(pow(vec3(0.5), 2.0 * c) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary_ref.vert
new file mode 100644
index 0000000000..cdc33face5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xconsthalf_yvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = -2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(exp2(2.0 * c) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2.vert
new file mode 100644
index 0000000000..567bab0ffe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 4.0 * (gtf_Color.rgb);
+ color = vec4(pow(c, vec3(2.0)) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2_ref.vert
new file mode 100644
index 0000000000..d49c633e5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconst2_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 4.0 * (gtf_Color.rgb);
+ color = vec4(c * c / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf.vert
new file mode 100644
index 0000000000..1b318d99db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 16.0 * gtf_Color.rgb;
+ color = vec4(pow(c, vec3(0.5)) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf_ref.vert
new file mode 100644
index 0000000000..5577b7ce72
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/pow/pow_vec3_vert_xvary_yconsthalf_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 16.0 * gtf_Color.rgb;
+ color = vec4(sqrt(c) / 4.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/input.run.txt
new file mode 100644
index 0000000000..891a82745f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+radians_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_001_to_006.html
new file mode 100644
index 0000000000..fbdbf593e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: radians_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "radians_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "radians_float_frag_xvary.frag"
+ },
+ "name": "radians_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "radians_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "radians_vec2_frag_xvary.frag"
+ },
+ "name": "radians_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "radians_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "radians_vec3_frag_xvary.frag"
+ },
+ "name": "radians_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "radians_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "radians_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "radians_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "radians_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "radians_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "radians_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "radians_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "radians_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "radians_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary.frag
new file mode 100644
index 0000000000..4f878f3409
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 360.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(radians(c) / (4.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..9b84f2601d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 360.0 * 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4((c * M_PI / 180.0) / (4.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary.vert
new file mode 100644
index 0000000000..d64ea1c2d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 360.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(radians(c) / (4.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..18197e13da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_float_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 360.0 * 2.0 * (gtf_Color.r - 0.5);
+ color = vec4((c * M_PI / 180.0) / (4.0 * M_PI) + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..5f9f2c34c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 360.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(radians(c) / (4.0 * M_PI) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..8c4c033dd3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 360.0 * 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4((c * M_PI / 180.0) / (4.0 * M_PI) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..a894ab318a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 360.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(radians(c) / (4.0 * M_PI) + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..807b66d408
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec2_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 360.0 * 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4((c * M_PI / 180.0) / (4.0 * M_PI) + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..dd6983c72a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 360.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(radians(c) / (4.0 * M_PI) + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..ec834496f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_frag_xvary_ref.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 360.0 * 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4((c * M_PI / 180.0) / (4.0 * M_PI) + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..b1b46bff50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 360.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(radians(c) / (4.0 * M_PI) + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..1003e32af6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/radians/radians_vec3_vert_xvary_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 360.0 * 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4((c * M_PI / 180.0) / (4.0 * M_PI) + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/input.run.txt
new file mode 100644
index 0000000000..b32c960e6c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+reflect_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_001_to_006.html
new file mode 100644
index 0000000000..95273c41bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: reflect_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "reflect_float_frag_ivarynconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "reflect_float_frag_ivarynconst.frag"
+ },
+ "name": "reflect_float_frag_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "reflect_float_vert_ivarynconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "reflect_float_vert_ivarynconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "reflect_float_vert_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "reflect_vec2_frag_ivarynconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "reflect_vec2_frag_ivarynconst.frag"
+ },
+ "name": "reflect_vec2_frag_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "reflect_vec2_vert_ivarynconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "reflect_vec2_vert_ivarynconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "reflect_vec2_vert_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "reflect_vec3_frag_ivarynconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "reflect_vec3_frag_ivarynconst.frag"
+ },
+ "name": "reflect_vec3_frag_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "reflect_vec3_vert_ivarynconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "reflect_vec3_vert_ivarynconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "reflect_vec3_vert_ivarynconst.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst.frag
new file mode 100644
index 0000000000..33a20805ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (color.g + 1.0) / 2.0;
+ float v2 = (color.b + 1.0) / 2.0;
+
+ gl_FragColor = vec4((reflect(v1, v2) + 1.0) / 2.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst_ref.frag
new file mode 100644
index 0000000000..066c91bd24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_frag_ivarynconst_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (color.g + 1.0) / 2.0;
+ float v2 = (color.b + 1.0) / 2.0;
+
+ gl_FragColor = vec4((v1 - 2.0 * dot(v2, v1) * v2 + 1.0) / 2.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst.vert
new file mode 100644
index 0000000000..ecfc76140c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (gtf_Color.g + 1.0) / 2.0;
+ float v2 = (gtf_Color.b + 1.0) / 2.0;
+
+ color = vec4((reflect(v1, v2) + 1.0) / 2.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst_ref.vert
new file mode 100644
index 0000000000..d9b9908636
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_float_vert_ivarynconst_ref.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (gtf_Color.g + 1.0) / 2.0;
+ float v2 = (gtf_Color.b + 1.0) / 2.0;
+
+ color = vec4((v1 - 2.0 * dot(v2, v1) * v2 + 1.0) / 2.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst.frag
new file mode 100644
index 0000000000..1e852dd7f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ gl_FragColor = vec4((reflect(v1, v2) + 1.0) / 2.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst_ref.frag
new file mode 100644
index 0000000000..2a832a62e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_frag_ivarynconst_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ gl_FragColor = vec4((v1 - 2.0 * dot(v2, v1) * v2 + 1.0) / 2.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst.vert
new file mode 100644
index 0000000000..644024fec8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ color = vec4((reflect(v1, v2) + 1.0) / 2.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst_ref.vert
new file mode 100644
index 0000000000..a333ed5da0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec2_vert_ivarynconst_ref.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ color = vec4((v1 - 2.0 * dot(v2, v1) * v2 + 1.0) / 2.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst.frag
new file mode 100644
index 0000000000..776dbcaedb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ gl_FragColor = vec4((reflect(v1, v2) + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst_ref.frag
new file mode 100644
index 0000000000..fd741cd29b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_frag_ivarynconst_ref.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ gl_FragColor = vec4((v1 - 2.0 * dot(v2, v1) * v2 + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst.vert
new file mode 100644
index 0000000000..43913886ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ color = vec4((reflect(v1, v2) + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst_ref.vert
new file mode 100644
index 0000000000..8cdbc8a7bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/reflect/reflect_vec3_vert_ivarynconst_ref.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ color = vec4((v1 - 2.0 * dot(v2, v1) * v2 + vec3(1.0)) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/input.run.txt
new file mode 100644
index 0000000000..c7deedd54c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+refract_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_001_to_006.html
new file mode 100644
index 0000000000..333ec6943c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: refract_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "refract_float_frag_ivarynconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "refract_float_frag_ivarynconst.frag"
+ },
+ "name": "refract_float_frag_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "refract_float_vert_ivarynconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "refract_float_vert_ivarynconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "refract_float_vert_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "refract_vec2_frag_ivarynconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "refract_vec2_frag_ivarynconst.frag"
+ },
+ "name": "refract_vec2_frag_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "refract_vec2_vert_ivarynconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "refract_vec2_vert_ivarynconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "refract_vec2_vert_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "refract_vec3_frag_ivarynconst_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "refract_vec3_frag_ivarynconst.frag"
+ },
+ "name": "refract_vec3_frag_ivarynconst.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "refract_vec3_vert_ivarynconst_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "refract_vec3_vert_ivarynconst.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "refract_vec3_vert_ivarynconst.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst.frag
new file mode 100644
index 0000000000..1a271b0ba5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (color.g + 1.0) / 2.0;
+ float v2 = (color.b + 1.0) / 2.0;
+
+ gl_FragColor = vec4((refract(v1, v2, 0.5) + 1.0) / 2.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst_ref.frag
new file mode 100644
index 0000000000..dec5f10dc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_frag_ivarynconst_ref.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ // Both are unit vectors
+ float v1 = (color.g + 1.0) / 2.0;
+ float v2 = (color.b + 1.0) / 2.0;
+
+ float result;
+ float eta = 0.5;
+ float k = 1.0 - eta * eta * (1.0 - dot(v1, v2) * dot(v1, v2));
+ if(k < 0.0)
+ result = 0.0;
+ else
+ result = eta * v1 - (eta * dot(v1, v2) + sqrt(k)) * v2;
+
+ gl_FragColor = vec4((result + 1.0) / 2.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst.vert
new file mode 100644
index 0000000000..3abae8b31c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ // Both are unit vectors
+ float v1 = (gtf_Color.g + 1.0) / 2.0;
+ float v2 = (gtf_Color.b + 1.0) / 2.0;
+
+ color = vec4((refract(v1, v2, 0.5) + 1.0) / 2.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst_ref.vert
new file mode 100644
index 0000000000..4adc177cf5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_float_vert_ivarynconst_ref.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ float v1 = (gtf_Color.g + 1.0) / 2.0;
+ float v2 = (gtf_Color.b + 1.0) / 2.0;
+
+ float result;
+ float eta = 0.5;
+ float k = 1.0 - eta * eta * (1.0 - dot(v1, v2) * dot(v1, v2));
+ if(k < 0.0)
+ result = 0.0;
+ else
+ result = eta * v1 - (eta * dot(v1, v2) + sqrt(k)) * v2;
+
+ color = vec4((result + 1.0) / 2.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst.frag
new file mode 100644
index 0000000000..3205e8fe2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ gl_FragColor = vec4((refract(v1, v2, 0.5) + 1.0) / 2.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst_ref.frag
new file mode 100644
index 0000000000..480191c477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_frag_ivarynconst_ref.frag
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ vec2 result;
+ float eta = 0.5;
+ float k = 1.0 - eta * eta * (1.0 - dot(v1, v2) * dot(v1, v2));
+ if(k < 0.0)
+ result = vec2(0.0);
+ else
+ result = eta * v1 - (eta * dot(v1, v2) + sqrt(k)) * v2;
+
+ gl_FragColor = vec4((result + 1.0) / 2.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst.vert
new file mode 100644
index 0000000000..0c5fe5053a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst.vert
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ color = vec4((refract(v1, v2, 0.5) + 1.0) / 2.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst_ref.vert
new file mode 100644
index 0000000000..5902cea9b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec2_vert_ivarynconst_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec2 v1;
+ vec2 v2 = normalize(vec2(1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+
+ vec2 result;
+ float eta = 0.5;
+ float k = 1.0 - eta * eta * (1.0 - dot(v1, v2) * dot(v1, v2));
+ if(k < 0.0)
+ result = vec2(0.0);
+ else
+ result = eta * v1 - (eta * dot(v1, v2) + sqrt(k)) * v2;
+
+ color = vec4((result + 1.0) / 2.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst.frag
new file mode 100644
index 0000000000..90df8fd8aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ gl_FragColor = vec4((refract(v1, v2, 0.5) + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst_ref.frag
new file mode 100644
index 0000000000..00064a2b79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_frag_ivarynconst_ref.frag
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+
+ float theta = color.g * 2.0 * M_PI;
+ float phi = color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ vec3 result;
+ float eta = 0.5;
+ float k = 1.0 - eta * eta * (1.0 - dot(v1, v2) * dot(v1, v2));
+ if(k < 0.0)
+ result = vec3(0.0);
+ else
+ result = eta * v1 - (eta * dot(v1, v2) + sqrt(k)) * v2;
+
+ gl_FragColor = vec4((result + 1.0) / 2.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst.vert
new file mode 100644
index 0000000000..29b38d23f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ color = vec4((refract(v1, v2, 0.5) + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst_ref.vert
new file mode 100644
index 0000000000..5d1872fa74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/refract/refract_vec3_vert_ivarynconst_ref.vert
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+
+ // Both are unit vectors
+ vec3 v1;
+ vec3 v2 = normalize(vec3(1.0, 1.0, 1.0));
+
+ float theta = gtf_Color.g * 2.0 * M_PI;
+ float phi = gtf_Color.b * 2.0 * M_PI;
+ v1.x = cos(theta) * sin(phi);
+ v1.y = sin(theta) * sin(phi);
+ v1.z = cos(phi);
+
+ vec3 result;
+ float eta = 0.5;
+ float k = 1.0 - eta * eta * (1.0 - dot(v1, v2) * dot(v1, v2));
+ if(k < 0.0)
+ result = vec3(0.0);
+ else
+ result = eta * v1 - (eta * dot(v1, v2) + sqrt(k)) * v2;
+
+ color = vec4((result + 1.0) / 2.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/input.run.txt
new file mode 100644
index 0000000000..b22bf9d68e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+sign_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_001_to_006.html
new file mode 100644
index 0000000000..ff486de206
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: sign_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sign_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sign_float_frag_xvary.frag"
+ },
+ "name": "sign_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sign_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sign_vec2_frag_xvary.frag"
+ },
+ "name": "sign_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sign_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sign_vec3_frag_xvary.frag"
+ },
+ "name": "sign_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sign_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sign_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sign_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sign_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sign_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sign_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sign_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sign_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sign_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary.frag
new file mode 100644
index 0000000000..8532d11a07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ gl_FragColor = vec4(c * sign(c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..d670310ac4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_frag_xvary_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (color.r - 0.5);
+ if(c > 0.0) c = 1.0 * c;
+ if(c < 0.0) c = -1.0 * c;
+
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary.vert
new file mode 100644
index 0000000000..dbc85e3d6a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ color = vec4(c * sign(c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..81bd9e70cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_float_vert_xvary_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 2.0 * (gtf_Color.r - 0.5);
+ if(c > 0.0) c = 1.0 * c;
+ if(c < 0.0) c = -1.0 * c;
+
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..bc98bc6395
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ gl_FragColor = vec4(c * sign(c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..b352db6400
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_frag_xvary_ref.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (color.rg - 0.5);
+ if(c[0] > 0.0) c[0] = 1.0 * c[0];
+ if(c[0] < 0.0) c[0] = -1.0 * c[0];
+ if(c[1] > 0.0) c[1] = 1.0 * c[1];
+ if(c[1] < 0.0) c[1] = -1.0 * c[1];
+
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..54572fb4c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ color = vec4(c * sign(c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..14706e2498
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec2_vert_xvary_ref.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 2.0 * (gtf_Color.rg - 0.5);
+ if(c[0] > 0.0) c[0] = 1.0 * c[0];
+ if(c[0] < 0.0) c[0] = -1.0 * c[0];
+ if(c[1] > 0.0) c[1] = 1.0 * c[1];
+ if(c[1] < 0.0) c[1] = -1.0 * c[1];
+
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..0ba38a1596
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+ gl_FragColor = vec4(c * (sign(c)), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..1097bac9a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_frag_xvary_ref.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (color.rgb - 0.5);
+
+ if(c[0] > 0.0) c[0] = 1.0 * c[0];
+ if(c[0] < 0.0) c[0] = -1.0 * c[0];
+ if(c[1] > 0.0) c[1] = 1.0 * c[1];
+ if(c[1] < 0.0) c[1] = -1.0 * c[1];
+ if(c[2] > 0.0) c[2] = 1.0 * c[2];
+ if(c[2] < 0.0) c[2] = -1.0 * c[2];
+
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..a6dec9a51f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+ color = vec4(c * sign(c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..98bdc7fac9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sign/sign_vec3_vert_xvary_ref.vert
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 2.0 * (gtf_Color.rgb - 0.5);
+
+ if(c[0] > 0.0) c[0] = 1.0 * c[0];
+ if(c[0] < 0.0) c[0] = -1.0 * c[0];
+ if(c[1] > 0.0) c[1] = 1.0 * c[1];
+ if(c[1] < 0.0) c[1] = -1.0 * c[1];
+ if(c[2] > 0.0) c[2] = 1.0 * c[2];
+ if(c[2] < 0.0) c[2] = -1.0 * c[2];
+
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/input.run.txt
new file mode 100644
index 0000000000..2995c56588
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+sin_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_001_to_006.html
new file mode 100644
index 0000000000..16e5039800
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: sin_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sin_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sin_float_frag_xvary.frag"
+ },
+ "name": "sin_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sin_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sin_vec2_frag_xvary.frag"
+ },
+ "name": "sin_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sin_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sin_vec3_frag_xvary.frag"
+ },
+ "name": "sin_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sin_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sin_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sin_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sin_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sin_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sin_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sin_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sin_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sin_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary.frag
new file mode 100644
index 0000000000..d3eb4c8702
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ gl_FragColor = vec4(0.5 * sin(2.0 * M_PI * color.r) + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..b8f6613004
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_frag_xvary_ref.frag
@@ -0,0 +1,84 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float sinValues[17];
+ sinValues[0] = 0.0;
+ sinValues[1] = 0.382683;
+ sinValues[2] = 0.707107;
+ sinValues[3] = 0.92388;
+ sinValues[4] = 1.0;
+ sinValues[5] = 0.92388;
+ sinValues[6] = 0.707107;
+ sinValues[7] = 0.382683;
+ sinValues[8] = 0.0;
+ sinValues[9] = -0.382683;
+ sinValues[10] = -0.707107;
+ sinValues[11] = -0.92388;
+ sinValues[12] = -1.0;
+ sinValues[13] = -0.923879;
+ sinValues[14] = -0.707107;
+ sinValues[15] = -0.382683;
+ sinValues[16] = 0.0;
+
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * color.r;
+
+ float arrVal = c * 2.546478971;
+ int arr0 = int(floor(arrVal));
+ float weight = arrVal - floor(arrVal);
+ float sin_c = 0.0;
+
+ if (arr0 == 0)
+ sin_c = lerp(sinValues[0], sinValues[1], weight);
+ else if (arr0 == 1)
+ sin_c = lerp(sinValues[1], sinValues[2], weight);
+ else if (arr0 == 2)
+ sin_c = lerp(sinValues[2], sinValues[3], weight);
+ else if (arr0 == 3)
+ sin_c = lerp(sinValues[3], sinValues[4], weight);
+ else if (arr0 == 4)
+ sin_c = lerp(sinValues[4], sinValues[5], weight);
+ else if (arr0 == 5)
+ sin_c = lerp(sinValues[5], sinValues[6], weight);
+ else if (arr0 == 6)
+ sin_c = lerp(sinValues[6], sinValues[7], weight);
+ else if (arr0 == 7)
+ sin_c = lerp(sinValues[7], sinValues[8], weight);
+ else if (arr0 == 8)
+ sin_c = lerp(sinValues[8], sinValues[9], weight);
+ else if (arr0 == 9)
+ sin_c = lerp(sinValues[9], sinValues[10], weight);
+ else if (arr0 == 10)
+ sin_c = lerp(sinValues[10], sinValues[11], weight);
+ else if (arr0 == 11)
+ sin_c = lerp(sinValues[11], sinValues[12], weight);
+ else if (arr0 == 12)
+ sin_c = lerp(sinValues[12], sinValues[13], weight);
+ else if (arr0 == 13)
+ sin_c = lerp(sinValues[13], sinValues[14], weight);
+ else if (arr0 == 14)
+ sin_c = lerp(sinValues[14], sinValues[15], weight);
+ else if (arr0 == 15)
+ sin_c = lerp(sinValues[15], sinValues[16], weight);
+ else if (arr0 == 16)
+ sin_c = sinValues[16];
+
+ gl_FragColor = vec4(0.5 * sin_c + 0.5, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary.vert
new file mode 100644
index 0000000000..fe39395cce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ color = vec4(0.5 * sin(2.0 * M_PI * gtf_Color.r) + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..68292455db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_float_vert_xvary_ref.vert
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 2.0 * M_PI * gtf_Color.r;
+ float sign = 1.0;
+
+ float sin_c = 0.0;
+ float fact;
+ float fact_of;
+
+ // Taylors series expansion for sin
+ for(int i = 0; i < 12; i++)
+ {
+ fact = 1.0;
+ for(int j = 2; j <= 23; j++)
+ if (j <= 2 * i + 1)
+ fact *= float(j);
+
+ sin_c += sign * pow(c, 2.0 * float(i) + 1.0) / fact;
+ sign *= -1.0;
+ }
+
+ color = vec4(0.5 * sin_c + 0.5, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..efb9c543b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ gl_FragColor = vec4(0.5 * sin(2.0 * M_PI * color.rg) + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..504e8b98b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_frag_xvary_ref.frag
@@ -0,0 +1,120 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float sinValues[17];
+ sinValues[0] = 0.0;
+ sinValues[1] = 0.382683;
+ sinValues[2] = 0.707107;
+ sinValues[3] = 0.92388;
+ sinValues[4] = 1.0;
+ sinValues[5] = 0.92388;
+ sinValues[6] = 0.707107;
+ sinValues[7] = 0.382683;
+ sinValues[8] = 0.0;
+ sinValues[9] = -0.382683;
+ sinValues[10] = -0.707107;
+ sinValues[11] = -0.92388;
+ sinValues[12] = -1.0;
+ sinValues[13] = -0.923879;
+ sinValues[14] = -0.707107;
+ sinValues[15] = -0.382683;
+ sinValues[16] = 0.0;
+
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * color.rg;
+
+ vec2 arrVal = c * 2.546478971;
+ int arr0x = int(floor(arrVal.x));
+ int arr0y = int(floor(arrVal.y));
+ vec2 weight = arrVal - floor(arrVal);
+ vec2 sin_c = vec2(0.0, 0.0);
+
+ if (arr0x == 0)
+ sin_c.x = lerp(sinValues[0], sinValues[1], weight.x);
+ else if (arr0x == 1)
+ sin_c.x = lerp(sinValues[1], sinValues[2], weight.x);
+ else if (arr0x == 2)
+ sin_c.x = lerp(sinValues[2], sinValues[3], weight.x);
+ else if (arr0x == 3)
+ sin_c.x = lerp(sinValues[3], sinValues[4], weight.x);
+ else if (arr0x == 4)
+ sin_c.x = lerp(sinValues[4], sinValues[5], weight.x);
+ else if (arr0x == 5)
+ sin_c.x = lerp(sinValues[5], sinValues[6], weight.x);
+ else if (arr0x == 6)
+ sin_c.x = lerp(sinValues[6], sinValues[7], weight.x);
+ else if (arr0x == 7)
+ sin_c.x = lerp(sinValues[7], sinValues[8], weight.x);
+ else if (arr0x == 8)
+ sin_c.x = lerp(sinValues[8], sinValues[9], weight.x);
+ else if (arr0x == 9)
+ sin_c.x = lerp(sinValues[9], sinValues[10], weight.x);
+ else if (arr0x == 10)
+ sin_c.x = lerp(sinValues[10], sinValues[11], weight.x);
+ else if (arr0x == 11)
+ sin_c.x = lerp(sinValues[11], sinValues[12], weight.x);
+ else if (arr0x == 12)
+ sin_c.x = lerp(sinValues[12], sinValues[13], weight.x);
+ else if (arr0x == 13)
+ sin_c.x = lerp(sinValues[13], sinValues[14], weight.x);
+ else if (arr0x == 14)
+ sin_c.x = lerp(sinValues[14], sinValues[15], weight.x);
+ else if (arr0x == 15)
+ sin_c.x = lerp(sinValues[15], sinValues[16], weight.x);
+ else if (arr0x == 16)
+ sin_c.x = sinValues[16];
+
+ if (arr0y == 0)
+ sin_c.y = lerp(sinValues[0], sinValues[1], weight.y);
+ else if (arr0y == 1)
+ sin_c.y = lerp(sinValues[1], sinValues[2], weight.y);
+ else if (arr0y == 2)
+ sin_c.y = lerp(sinValues[2], sinValues[3], weight.y);
+ else if (arr0y == 3)
+ sin_c.y = lerp(sinValues[3], sinValues[4], weight.y);
+ else if (arr0y == 4)
+ sin_c.y = lerp(sinValues[4], sinValues[5], weight.y);
+ else if (arr0y == 5)
+ sin_c.y = lerp(sinValues[5], sinValues[6], weight.y);
+ else if (arr0y == 6)
+ sin_c.y = lerp(sinValues[6], sinValues[7], weight.y);
+ else if (arr0y == 7)
+ sin_c.y = lerp(sinValues[7], sinValues[8], weight.y);
+ else if (arr0y == 8)
+ sin_c.y = lerp(sinValues[8], sinValues[9], weight.y);
+ else if (arr0y == 9)
+ sin_c.y = lerp(sinValues[9], sinValues[10], weight.y);
+ else if (arr0y == 10)
+ sin_c.y = lerp(sinValues[10], sinValues[11], weight.y);
+ else if (arr0y == 11)
+ sin_c.y = lerp(sinValues[11], sinValues[12], weight.y);
+ else if (arr0y == 12)
+ sin_c.y = lerp(sinValues[12], sinValues[13], weight.y);
+ else if (arr0y == 13)
+ sin_c.y = lerp(sinValues[13], sinValues[14], weight.y);
+ else if (arr0y == 14)
+ sin_c.y = lerp(sinValues[14], sinValues[15], weight.y);
+ else if (arr0y == 15)
+ sin_c.y = lerp(sinValues[15], sinValues[16], weight.y);
+ else if (arr0y == 16)
+ sin_c.y = sinValues[16];
+
+ gl_FragColor = vec4(0.5 * sin_c + 0.5, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..910f090ce6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ color = vec4(0.5 * sin(2.0 * M_PI * gtf_Color.rg) + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..3d1567e142
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec2_vert_xvary_ref.vert
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float sinValues[17];
+ sinValues[0] = 0.0;
+ sinValues[1] = 0.382683;
+ sinValues[2] = 0.707107;
+ sinValues[3] = 0.92388;
+ sinValues[4] = 1.0;
+ sinValues[5] = 0.92388;
+ sinValues[6] = 0.707107;
+ sinValues[7] = 0.382683;
+ sinValues[8] = 0.0;
+ sinValues[9] = -0.382683;
+ sinValues[10] = -0.707107;
+ sinValues[11] = -0.92388;
+ sinValues[12] = -1.0;
+ sinValues[13] = -0.923879;
+ sinValues[14] = -0.707107;
+ sinValues[15] = -0.382683;
+ sinValues[16] = 0.0;
+
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 2.0 * M_PI * gtf_Color.rg;
+ float sign = 1.0;
+
+ vec2 sin_c = vec2(0.0);
+ float fact;
+ float fact_of;
+
+ // Taylors series expansion for sin
+ for(int i = 0; i < 12; i++)
+ {
+ fact = 1.0;
+ for(int j = 2; j <= 23; j++)
+ if (j <= 2 * i + 1)
+ fact *= float(j);
+
+ sin_c += sign * pow(c, vec2(2.0 * float(i) + 1.0)) / fact;
+ sign *= -1.0;
+ }
+
+ color = vec4(0.5 * sin_c + 0.5, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..21f6124e41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ gl_FragColor = vec4(0.5 * sin(2.0 * M_PI * color.rgb) + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..86aada5af7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_frag_xvary_ref.frag
@@ -0,0 +1,156 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float sinValues[17];
+ sinValues[0] = 0.0;
+ sinValues[1] = 0.382683;
+ sinValues[2] = 0.707107;
+ sinValues[3] = 0.92388;
+ sinValues[4] = 1.0;
+ sinValues[5] = 0.92388;
+ sinValues[6] = 0.707107;
+ sinValues[7] = 0.382683;
+ sinValues[8] = 0.0;
+ sinValues[9] = -0.382683;
+ sinValues[10] = -0.707107;
+ sinValues[11] = -0.92388;
+ sinValues[12] = -1.0;
+ sinValues[13] = -0.923879;
+ sinValues[14] = -0.707107;
+ sinValues[15] = -0.382683;
+ sinValues[16] = 0.0;
+
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * color.rgb;
+
+ vec3 arrVal = c * 2.546478971;
+ int arr0x = int(floor(arrVal.x));
+ int arr0y = int(floor(arrVal.y));
+ int arr0z = int(floor(arrVal.z));
+ vec3 weight = arrVal - floor(arrVal);
+ vec3 sin_c = vec3(0.0, 0.0, 0.0);
+
+ if (arr0x == 0)
+ sin_c.x = lerp(sinValues[0], sinValues[1], weight.x);
+ else if (arr0x == 1)
+ sin_c.x = lerp(sinValues[1], sinValues[2], weight.x);
+ else if (arr0x == 2)
+ sin_c.x = lerp(sinValues[2], sinValues[3], weight.x);
+ else if (arr0x == 3)
+ sin_c.x = lerp(sinValues[3], sinValues[4], weight.x);
+ else if (arr0x == 4)
+ sin_c.x = lerp(sinValues[4], sinValues[5], weight.x);
+ else if (arr0x == 5)
+ sin_c.x = lerp(sinValues[5], sinValues[6], weight.x);
+ else if (arr0x == 6)
+ sin_c.x = lerp(sinValues[6], sinValues[7], weight.x);
+ else if (arr0x == 7)
+ sin_c.x = lerp(sinValues[7], sinValues[8], weight.x);
+ else if (arr0x == 8)
+ sin_c.x = lerp(sinValues[8], sinValues[9], weight.x);
+ else if (arr0x == 9)
+ sin_c.x = lerp(sinValues[9], sinValues[10], weight.x);
+ else if (arr0x == 10)
+ sin_c.x = lerp(sinValues[10], sinValues[11], weight.x);
+ else if (arr0x == 11)
+ sin_c.x = lerp(sinValues[11], sinValues[12], weight.x);
+ else if (arr0x == 12)
+ sin_c.x = lerp(sinValues[12], sinValues[13], weight.x);
+ else if (arr0x == 13)
+ sin_c.x = lerp(sinValues[13], sinValues[14], weight.x);
+ else if (arr0x == 14)
+ sin_c.x = lerp(sinValues[14], sinValues[15], weight.x);
+ else if (arr0x == 15)
+ sin_c.x = lerp(sinValues[15], sinValues[16], weight.x);
+ else if (arr0x == 16)
+ sin_c.x = sinValues[16];
+
+ if (arr0y == 0)
+ sin_c.y = lerp(sinValues[0], sinValues[1], weight.y);
+ else if (arr0y == 1)
+ sin_c.y = lerp(sinValues[1], sinValues[2], weight.y);
+ else if (arr0y == 2)
+ sin_c.y = lerp(sinValues[2], sinValues[3], weight.y);
+ else if (arr0y == 3)
+ sin_c.y = lerp(sinValues[3], sinValues[4], weight.y);
+ else if (arr0y == 4)
+ sin_c.y = lerp(sinValues[4], sinValues[5], weight.y);
+ else if (arr0y == 5)
+ sin_c.y = lerp(sinValues[5], sinValues[6], weight.y);
+ else if (arr0y == 6)
+ sin_c.y = lerp(sinValues[6], sinValues[7], weight.y);
+ else if (arr0y == 7)
+ sin_c.y = lerp(sinValues[7], sinValues[8], weight.y);
+ else if (arr0y == 8)
+ sin_c.y = lerp(sinValues[8], sinValues[9], weight.y);
+ else if (arr0y == 9)
+ sin_c.y = lerp(sinValues[9], sinValues[10], weight.y);
+ else if (arr0y == 10)
+ sin_c.y = lerp(sinValues[10], sinValues[11], weight.y);
+ else if (arr0y == 11)
+ sin_c.y = lerp(sinValues[11], sinValues[12], weight.y);
+ else if (arr0y == 12)
+ sin_c.y = lerp(sinValues[12], sinValues[13], weight.y);
+ else if (arr0y == 13)
+ sin_c.y = lerp(sinValues[13], sinValues[14], weight.y);
+ else if (arr0y == 14)
+ sin_c.y = lerp(sinValues[14], sinValues[15], weight.y);
+ else if (arr0y == 15)
+ sin_c.y = lerp(sinValues[15], sinValues[16], weight.y);
+ else if (arr0y == 16)
+ sin_c.y = sinValues[16];
+
+ if (arr0z == 0)
+ sin_c.z = lerp(sinValues[0], sinValues[1], weight.z);
+ else if (arr0z == 1)
+ sin_c.z = lerp(sinValues[1], sinValues[2], weight.z);
+ else if (arr0z == 2)
+ sin_c.z = lerp(sinValues[2], sinValues[3], weight.z);
+ else if (arr0z == 3)
+ sin_c.z = lerp(sinValues[3], sinValues[4], weight.z);
+ else if (arr0z == 4)
+ sin_c.z = lerp(sinValues[4], sinValues[5], weight.z);
+ else if (arr0z == 5)
+ sin_c.z = lerp(sinValues[5], sinValues[6], weight.z);
+ else if (arr0z == 6)
+ sin_c.z = lerp(sinValues[6], sinValues[7], weight.z);
+ else if (arr0z == 7)
+ sin_c.z = lerp(sinValues[7], sinValues[8], weight.z);
+ else if (arr0z == 8)
+ sin_c.z = lerp(sinValues[8], sinValues[9], weight.z);
+ else if (arr0z == 9)
+ sin_c.z = lerp(sinValues[9], sinValues[10], weight.z);
+ else if (arr0z == 10)
+ sin_c.z = lerp(sinValues[10], sinValues[11], weight.z);
+ else if (arr0z == 11)
+ sin_c.z = lerp(sinValues[11], sinValues[12], weight.z);
+ else if (arr0z == 12)
+ sin_c.z = lerp(sinValues[12], sinValues[13], weight.z);
+ else if (arr0z == 13)
+ sin_c.z = lerp(sinValues[13], sinValues[14], weight.z);
+ else if (arr0z == 14)
+ sin_c.z = lerp(sinValues[14], sinValues[15], weight.z);
+ else if (arr0z == 15)
+ sin_c.z = lerp(sinValues[15], sinValues[16], weight.z);
+ else if (arr0z == 16)
+ sin_c.z = sinValues[16];
+
+ gl_FragColor = vec4(0.5 * sin_c + 0.5, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..25ea3a6a49
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ color = vec4(0.5 * sin(2.0 * M_PI * gtf_Color.rgb) + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..962f1d8e9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sin/sin_vec3_vert_xvary_ref.vert
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+float lerp(float a, float b, float s)
+{
+ return a + (b - a) * s;
+}
+
+void main (void)
+{
+ float sinValues[17];
+ sinValues[0] = 0.0;
+ sinValues[1] = 0.382683;
+ sinValues[2] = 0.707107;
+ sinValues[3] = 0.92388;
+ sinValues[4] = 1.0;
+ sinValues[5] = 0.92388;
+ sinValues[6] = 0.707107;
+ sinValues[7] = 0.382683;
+ sinValues[8] = 0.0;
+ sinValues[9] = -0.382683;
+ sinValues[10] = -0.707107;
+ sinValues[11] = -0.92388;
+ sinValues[12] = -1.0;
+ sinValues[13] = -0.923879;
+ sinValues[14] = -0.707107;
+ sinValues[15] = -0.382683;
+ sinValues[16] = 0.0;
+
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 2.0 * M_PI * gtf_Color.rgb;
+ float sign = 1.0;
+
+ vec3 sin_c = vec3(0.0);
+ float fact;
+ float fact_of;
+
+ // Taylors series expansion for sin
+ for(int i = 0; i < 12; i++)
+ {
+ fact = 1.0;
+ for(int j = 2; j <= 23; j++)
+ if (j <= 2 * i + 1)
+ fact *= float(j);
+
+ sin_c += sign * pow(c, vec3(2.0 * float(i) + 1.0)) / fact;
+ sign *= -1.0;
+ }
+
+ color = vec4(0.5 * sin_c + 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/input.run.txt
new file mode 100644
index 0000000000..4121dd5f8c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+smoothstep_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_001_to_006.html
new file mode 100644
index 0000000000..cec8b66e41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: smoothstep_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "smoothstep_float_frag_xvary_edgeconstquarter_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "smoothstep_float_frag_xvary_edgeconstquarter.frag"
+ },
+ "name": "smoothstep_float_frag_xvary_edgeconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "smoothstep_vec2_frag_xvary_edgeconstquarter_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "smoothstep_vec2_frag_xvary_edgeconstquarter.frag"
+ },
+ "name": "smoothstep_vec2_frag_xvary_edgeconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "smoothstep_vec3_frag_xvary_edgeconstquarter_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "smoothstep_vec3_frag_xvary_edgeconstquarter.frag"
+ },
+ "name": "smoothstep_vec3_frag_xvary_edgeconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "smoothstep_float_vert_xvary_edgeconstquarter_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "smoothstep_float_vert_xvary_edgeconstquarter.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "smoothstep_float_vert_xvary_edgeconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "smoothstep_vec2_vert_xvary_edgeconstquarter_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "smoothstep_vec2_vert_xvary_edgeconstquarter.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "smoothstep_vec2_vert_xvary_edgeconstquarter.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "smoothstep_vec3_vert_xvary_edgeconstquarter_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "smoothstep_vec3_vert_xvary_edgeconstquarter.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "smoothstep_vec3_vert_xvary_edgeconstquarter.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter.frag
new file mode 100644
index 0000000000..051294c841
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float edge0 = 0.25;
+ const float edge1 = 0.75;
+ gl_FragColor = vec4(smoothstep(edge0, edge1, color.r), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter_ref.frag
new file mode 100644
index 0000000000..811dcdd942
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_frag_xvary_edgeconstquarter_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float edge0 = 0.25;
+ const float edge1 = 0.75;
+ float c = clamp((color.r - edge0) / (edge1 - edge0), 0.0, 1.0);
+
+ gl_FragColor = vec4(c * c * (3.0 - 2.0 * c), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter.vert
new file mode 100644
index 0000000000..a42ca379dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float edge0 = 0.25;
+ const float edge1 = 0.75;
+ color = vec4(smoothstep(edge0, edge1, gtf_Color.r), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter_ref.vert
new file mode 100644
index 0000000000..8bd69f3b62
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_float_vert_xvary_edgeconstquarter_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float edge0 = 0.25;
+ const float edge1 = 0.75;
+ float c = clamp((gtf_Color.r - edge0) / (edge1 - edge0), 0.0, 1.0);
+
+ color = vec4(c * c * (3.0 - 2.0 * c), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter.frag
new file mode 100644
index 0000000000..6d32c3d4b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge0 = vec2(0.25, 0.25);
+ const vec2 edge1 = vec2(0.75, 0.75);
+ gl_FragColor = vec4(smoothstep(edge0, edge1, color.rg), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter_ref.frag
new file mode 100644
index 0000000000..ffb365002f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_frag_xvary_edgeconstquarter_ref.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge0 = vec2(0.25, 0.25);
+ const vec2 edge1 = vec2(0.75, 0.75);
+ vec2 c = clamp((color.rg - edge0) / (edge1 - edge0), 0.0, 1.0);
+ gl_FragColor = vec4(c * c * (3.0 - 2.0 * c), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter.vert
new file mode 100644
index 0000000000..0c55476372
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge0 = vec2(0.25, 0.25);
+ const vec2 edge1 = vec2(0.75, 0.75);
+ color = vec4(smoothstep(edge0, edge1, gtf_Color.rg), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter_ref.vert
new file mode 100644
index 0000000000..0864a3af9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec2_vert_xvary_edgeconstquarter_ref.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge0 = vec2(0.25, 0.25);
+ const vec2 edge1 = vec2(0.75, 0.75);
+ vec2 c = clamp((gtf_Color.rg - edge0) / (edge1 - edge0), 0.0, 1.0);
+ color = vec4(c * c * (3.0 - 2.0 * c), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter.frag
new file mode 100644
index 0000000000..caca3c1f95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge0 = vec3(0.25, 0.25, 0.25);
+ const vec3 edge1 = vec3(0.75, 0.75, 0.75);
+ gl_FragColor = vec4(smoothstep(edge0, edge1, color.rgb), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter_ref.frag
new file mode 100644
index 0000000000..e9ea52ad64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_frag_xvary_edgeconstquarter_ref.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge0 = vec3(0.25, 0.25, 0.25);
+ const vec3 edge1 = vec3(0.75, 0.75, 0.75);
+ vec3 c = clamp((color.rgb - edge0) / (edge1 - edge0), 0.0, 1.0);
+
+ gl_FragColor = vec4(c * c * (3.0 - 2.0 * c), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter.vert
new file mode 100644
index 0000000000..6aa8d8c3e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge0 = vec3(0.25, 0.25, 0.25);
+ const vec3 edge1 = vec3(0.75, 0.75, 0.75);
+ color = vec4(smoothstep(edge0, edge1, gtf_Color.rgb), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter_ref.vert
new file mode 100644
index 0000000000..2f12993b0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/smoothstep/smoothstep_vec3_vert_xvary_edgeconstquarter_ref.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge0 = vec3(0.25, 0.25, 0.25);
+ const vec3 edge1 = vec3(0.75, 0.75, 0.75);
+ vec3 c = clamp((gtf_Color.rgb - edge0) / (edge1 - edge0), 0.0, 1.0);
+
+ color = vec4(c * c * (3.0 - 2.0 * c), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/input.run.txt
new file mode 100644
index 0000000000..a151ee6448
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+sqrt_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_001_to_006.html
new file mode 100644
index 0000000000..48f368604e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: sqrt_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sqrt_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sqrt_float_frag_xvary.frag"
+ },
+ "name": "sqrt_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sqrt_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sqrt_vec2_frag_xvary.frag"
+ },
+ "name": "sqrt_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sqrt_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "sqrt_vec3_frag_xvary.frag"
+ },
+ "name": "sqrt_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sqrt_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sqrt_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sqrt_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sqrt_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sqrt_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sqrt_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "sqrt_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "sqrt_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "sqrt_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary.frag
new file mode 100644
index 0000000000..c061c08adb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = sqrt(100.0 * color.r);
+ gl_FragColor = vec4(c * c / 100.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..5fe62a689a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ float c = 100.0 * color.r;
+ gl_FragColor = vec4(c / 100.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary.vert
new file mode 100644
index 0000000000..f680e0ae54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = sqrt(100.0 * gtf_Color.r);
+ color = vec4(c * c / 100.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..8307cf719b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_float_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ float c = 100.0 * gtf_Color.r;
+ color = vec4(c / 100.0, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..9de98d8ced
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = sqrt(100.0 * color.rg);
+ gl_FragColor = vec4(c * c / 100.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..9735f24aee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 100.0 * color.rg;
+ gl_FragColor = vec4(c / 100.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..2ebedb1720
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = sqrt(100.0 * gtf_Color.rg);
+ color = vec4(c * c / 100.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..1275313c18
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec2_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 c = 100.0 * gtf_Color.rg;
+ color = vec4(c / 100.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..2c53829b64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = sqrt(100.0 * color.rgb);
+ gl_FragColor = vec4(c * c / 100.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..f23b5f87ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_frag_xvary_ref.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 100.0 * color.rgb;
+ gl_FragColor = vec4(c / 100.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..baed8763f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = sqrt(100.0 * gtf_Color.rgb);
+ color = vec4(c * c / 100.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..39983c3079
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/sqrt/sqrt_vec3_vert_xvary_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 c = 100.0 * gtf_Color.rgb;
+ color = vec4(c / 100.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/input.run.txt
new file mode 100644
index 0000000000..6b8ac005dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+step_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_001_to_006.html
new file mode 100644
index 0000000000..1a4297a415
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: step_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "step_float_frag_xvary_edgeconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "step_float_frag_xvary_edgeconsthalf.frag"
+ },
+ "name": "step_float_frag_xvary_edgeconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "step_vec2_frag_xvary_edgeconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "step_vec2_frag_xvary_edgeconsthalf.frag"
+ },
+ "name": "step_vec2_frag_xvary_edgeconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "step_vec3_frag_xvary_edgeconsthalf_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "step_vec3_frag_xvary_edgeconsthalf.frag"
+ },
+ "name": "step_vec3_frag_xvary_edgeconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "step_float_vert_xvary_edgeconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "step_float_vert_xvary_edgeconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "step_float_vert_xvary_edgeconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "step_vec2_vert_xvary_edgeconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "step_vec2_vert_xvary_edgeconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "step_vec2_vert_xvary_edgeconsthalf.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "step_vec3_vert_xvary_edgeconsthalf_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "step_vec3_vert_xvary_edgeconsthalf.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "step_vec3_vert_xvary_edgeconsthalf.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf.frag
new file mode 100644
index 0000000000..a79fab9e71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float edge = 0.5;
+ gl_FragColor = vec4(step(edge, color.r), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf_ref.frag
new file mode 100644
index 0000000000..b5ac9648e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_frag_xvary_edgeconsthalf_ref.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float edge = 0.5;
+ float c = color.r;
+ if(c >= edge) c = 1.0;
+ else c = 0.0;
+
+ gl_FragColor = vec4(c, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf.vert
new file mode 100644
index 0000000000..b7cf8c7c2d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float edge = 0.5;
+ color = vec4(step(edge, gtf_Color.r), 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf_ref.vert
new file mode 100644
index 0000000000..6e298d4c68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_float_vert_xvary_edgeconsthalf_ref.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float edge = 0.5;
+ float c = gtf_Color.r;
+ if(c >= edge) c = 1.0;
+ else c = 0.0;
+
+ color = vec4(c, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf.frag
new file mode 100644
index 0000000000..6882df1b7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge = vec2(0.5, 0.5);
+ gl_FragColor = vec4(step(edge, color.rg), 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf_ref.frag
new file mode 100644
index 0000000000..6643e48d8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_frag_xvary_edgeconsthalf_ref.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge = vec2(0.5, 0.5);
+ vec2 c = color.rg;
+ if(c[0] >= edge[0])
+ {
+ c[0] = 1.0;
+ }
+ else
+ {
+ c[0] = 0.0;
+ }
+ if(c[1] >= edge[1])
+ {
+ c[1] = 1.0;
+ }
+ else
+ {
+ c[1] = 0.0;
+ }
+
+ gl_FragColor = vec4(c, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf.vert
new file mode 100644
index 0000000000..c6c44ff0b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge = vec2(0.5, 0.5);
+ color = vec4(step(edge, gtf_Color.rg), 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf_ref.vert
new file mode 100644
index 0000000000..177e9d3c5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec2_vert_xvary_edgeconsthalf_ref.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec2 edge = vec2(0.5, 0.5);
+ vec2 c = gtf_Color.rg;
+ if(c[0] >= edge[0])
+ {
+ c[0] = 1.0;
+ }
+ else
+ {
+ c[0] = 0.0;
+ }
+ if(c[1] >= edge[1])
+ {
+ c[1] = 1.0;
+ }
+ else
+ {
+ c[1] = 0.0;
+ }
+
+ color = vec4(c, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf.frag
new file mode 100644
index 0000000000..b27d163c46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge = vec3(0.5, 0.5, 0.5);
+ gl_FragColor = vec4(step(edge, color.rgb), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf_ref.frag
new file mode 100644
index 0000000000..1dfc326ccb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_frag_xvary_edgeconsthalf_ref.frag
@@ -0,0 +1,44 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge = vec3(0.5, 0.5, 0.5);
+ vec3 c = color.rgb;
+ if(c[0] >= edge[0])
+ {
+ c[0] = 1.0;
+ }
+ else
+ {
+ c[0] = 0.0;
+ }
+ if(c[1] >= edge[1])
+ {
+ c[1] = 1.0;
+ }
+ else
+ {
+ c[1] = 0.0;
+ }
+ if(c[2] >= edge[2])
+ {
+ c[2] = 1.0;
+ }
+ else
+ {
+ c[2] = 0.0;
+ }
+
+ gl_FragColor = vec4(c, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf.vert
new file mode 100644
index 0000000000..a943b02201
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge = vec3(0.5, 0.5, 0.5);
+ color = vec4(step(edge, gtf_Color.rgb), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf_ref.vert
new file mode 100644
index 0000000000..c8d2442fa6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/step/step_vec3_vert_xvary_edgeconsthalf_ref.vert
@@ -0,0 +1,45 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const vec3 edge = vec3(0.5, 0.5, 0.5);
+ vec3 c = gtf_Color.rgb;
+ if(c[0] >= edge[0])
+ {
+ c[0] = 1.0;
+ }
+ else
+ {
+ c[0] = 0.0;
+ }
+ if(c[1] >= edge[1])
+ {
+ c[1] = 1.0;
+ }
+ else
+ {
+ c[1] = 0.0;
+ }
+ if(c[2] >= edge[2])
+ {
+ c[2] = 1.0;
+ }
+ else
+ {
+ c[2] = 0.0;
+ }
+
+ color = vec4(c, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/input.run.txt
new file mode 100644
index 0000000000..89c3da16ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/input.run.txt
@@ -0,0 +1,8 @@
+# this file is auto-generated. DO NOT EDIT.
+struct_001_to_008.html
+struct_009_to_016.html
+struct_017_to_024.html
+struct_025_to_032.html
+struct_033_to_040.html
+struct_041_to_048.html
+struct_049_to_056.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_frag.frag
new file mode 100644
index 0000000000..bc0fdd01a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_frag.frag
@@ -0,0 +1,99 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+#define ERROR_EPSILON 0.125
+
+void main (void){
+ struct second_nest
+ {
+ float sc_nt;
+ mat2 sc_mt2;
+ vec4 sc_vc4;
+ };
+
+ struct nest
+ {
+ ivec3 nt_ivc3;
+ bvec4 nt_bvc4;
+ second_nest nt_scne;
+ };
+
+ struct test_t
+ {
+ float t_fl;
+ vec2 t_vc2;
+ vec3 t_vc3;
+ mat4 t_mt4;
+ nest t_nested;
+ float t_2fl;
+ };
+
+ vec4 mt1 = vec4(31.0, 32.0, 33.0, 34.0);
+ vec4 mt2 = vec4(35.0, 36.0, 37.0, 38.0);
+ vec4 mt3 = vec4(39.0, 40.0, 41.0, 42.0);
+ vec4 mt4 = vec4(43.0, 44.0, 45.0, 46.0);
+ int i=0;
+ float sum1=0.0, sum2=0.0, sum3=0.0, sum4=0.0;
+
+ test_t a = test_t(23.0, vec2(12.0, 13.0),
+
+ vec3(163.0, 173.0, 183.0),
+
+ mat4(mt1, mt2, mt3, mt4),
+
+ nest( ivec3(73, 74, 75),
+
+ bvec4(12, 0, 17.0, 193.0 ),
+
+ second_nest(144.0, mat2(22.0, 23.0, 24.0, 25.0), vec4(57.0, 58.0, 59.0, 60.0 )
+ )
+ ),
+
+ 203.0
+ );
+
+ sum1 = a.t_mt4[0][0] + a.t_mt4[0][1] + a.t_mt4[0][2] + a.t_mt4[0][3];
+ sum2 = a.t_mt4[1][0] + a.t_mt4[1][1] + a.t_mt4[1][2] + a.t_mt4[1][3];
+ sum3 = a.t_mt4[2][0] + a.t_mt4[2][1] + a.t_mt4[2][2] + a.t_mt4[2][3];
+ sum4 = a.t_mt4[3][0] + a.t_mt4[3][1] + a.t_mt4[3][2] + a.t_mt4[3][3];
+
+ float gray;
+ if( ( a.t_fl == 23.0 ) &&
+
+ (a.t_vc2[0] == 12.0) && (a.t_vc2[1] == 13.0) &&
+
+ (a.t_vc3[0] == 163.0) && (a.t_vc3[1] == 173.0) && (a.t_vc3[2] == 183.0) &&
+
+ (sum1 > 130.0-ERROR_EPSILON && sum1 < 130.0+ERROR_EPSILON ) && (sum2 > 146.0-ERROR_EPSILON && sum2 < 146.0+ERROR_EPSILON ) && (sum3 >162.0-ERROR_EPSILON && sum3 < 162.0+ERROR_EPSILON ) && (sum4 > 178.0-ERROR_EPSILON && sum4 < 178.0+ERROR_EPSILON ) &&
+ (a.t_nested.nt_ivc3[0] == 73 ) && (a.t_nested.nt_ivc3[1] == 74 ) && (a.t_nested.nt_ivc3[2] == 75 ) &&
+
+ (a.t_nested.nt_bvc4[0] == true) && (a.t_nested.nt_bvc4[1] == false) &&
+
+ (a.t_nested.nt_bvc4[2] == true ) && (a.t_nested.nt_bvc4[0] == true) &&
+
+ (a.t_nested.nt_scne.sc_nt == 144.0) &&
+
+ (a.t_nested.nt_scne.sc_mt2[0][0] == 22.0 ) && (a.t_nested.nt_scne.sc_mt2[0][1] == 23.0 ) &&
+
+ (a.t_nested.nt_scne.sc_mt2[1][0] == 24.0 ) && (a.t_nested.nt_scne.sc_mt2[1][1] == 25.0 ) &&
+
+ (a.t_nested.nt_scne.sc_vc4[0] == 57.0 ) && (a.t_nested.nt_scne.sc_vc4[1] == 58.0 ) &&
+
+ (a.t_nested.nt_scne.sc_vc4[2] == 59.0 ) && (a.t_nested.nt_scne.sc_vc4[3] == 60.0) &&
+
+ (a.t_2fl == 203.0)
+ )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_vert.vert
new file mode 100644
index 0000000000..32cf5252f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/nestedstructcomb_various_vert.vert
@@ -0,0 +1,102 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+#define ERROR_EPSILON 0.125
+
+void main (void)
+{
+ struct second_nest
+ {
+ float sc_nt;
+ mat2 sc_mt2;
+ vec4 sc_vc4;
+ };
+
+ struct nest
+ {
+ ivec3 nt_ivc3;
+ bvec4 nt_bvc4;
+ second_nest nt_scne;
+ };
+
+ struct test_t
+ {
+ float t_fl;
+ vec2 t_vc2;
+ vec3 t_vc3;
+ mat4 t_mt4;
+ nest t_nested;
+ float t_2fl;
+ };
+
+ vec4 mt1 = vec4(31.0, 32.0, 33.0, 34.0);
+ vec4 mt2 = vec4(35.0, 36.0, 37.0, 38.0);
+ vec4 mt3 = vec4(39.0, 40.0, 41.0, 42.0);
+ vec4 mt4 = vec4(43.0, 44.0, 45.0, 46.0);
+ int i=0;
+ float sum1=0.0, sum2=0.0, sum3=0.0, sum4=0.0;
+
+ test_t a = test_t(23.0, vec2(12.0, 13.0),
+
+ vec3(163.0, 173.0, 183.0),
+
+ mat4(mt1, mt2, mt3, mt4),
+
+ nest( ivec3(73, 74, 75),
+
+ bvec4(12, 0, 17.0, 193.0 ),
+
+ second_nest(144.0, mat2(22.0, 23.0, 24.0, 25.0), vec4(57.0, 58.0, 59.0, 60.0 )
+ )
+ ),
+
+ 203.0
+ );
+
+ sum1 = a.t_mt4[0][0] + a.t_mt4[0][1] + a.t_mt4[0][2] + a.t_mt4[0][3];
+ sum2 = a.t_mt4[1][0] + a.t_mt4[1][1] + a.t_mt4[1][2] + a.t_mt4[1][3];
+ sum3 = a.t_mt4[2][0] + a.t_mt4[2][1] + a.t_mt4[2][2] + a.t_mt4[2][3];
+ sum4 = a.t_mt4[3][0] + a.t_mt4[3][1] + a.t_mt4[3][2] + a.t_mt4[3][3];
+
+ float gray;
+ if( ( a.t_fl == 23.0 ) &&
+
+ (a.t_vc2[0] == 12.0) && (a.t_vc2[1] == 13.0) &&
+
+ (a.t_vc3[0] == 163.0) && (a.t_vc3[1] == 173.0) && (a.t_vc3[2] == 183.0) &&
+
+ (sum1 > 130.0-ERROR_EPSILON && sum1 < 130.0+ERROR_EPSILON ) && (sum2 > 146.0-ERROR_EPSILON && sum2 < 146.0+ERROR_EPSILON ) && (sum3 >162.0-ERROR_EPSILON && sum3 < 162.0+ERROR_EPSILON ) && (sum4 > 178.0-ERROR_EPSILON && sum4 < 178.0+ERROR_EPSILON ) &&
+ (a.t_nested.nt_ivc3[0] == 73 ) && (a.t_nested.nt_ivc3[1] == 74 ) && (a.t_nested.nt_ivc3[2] == 75 ) &&
+
+ (a.t_nested.nt_bvc4[0] == true) && (a.t_nested.nt_bvc4[1] == false) &&
+
+ (a.t_nested.nt_bvc4[2] == true ) && (a.t_nested.nt_bvc4[0] == true) &&
+
+ (a.t_nested.nt_scne.sc_nt == 144.0) &&
+
+ (a.t_nested.nt_scne.sc_mt2[0][0] == 22.0 ) && (a.t_nested.nt_scne.sc_mt2[0][1] == 23.0 ) &&
+
+ (a.t_nested.nt_scne.sc_mt2[1][0] == 24.0 ) && (a.t_nested.nt_scne.sc_mt2[1][1] == 25.0 ) &&
+
+ (a.t_nested.nt_scne.sc_vc4[0] == 57.0 ) && (a.t_nested.nt_scne.sc_vc4[1] == 58.0 ) &&
+
+ (a.t_nested.nt_scne.sc_vc4[2] == 59.0 ) && (a.t_nested.nt_scne.sc_vc4[3] == 60.0) &&
+
+ (a.t_2fl == 203.0)
+ )
+ gray=1.0;
+ else gray=0.0;
+
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_001_to_008.html
new file mode 100644
index 0000000000..226e152da8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_float_frag.frag"
+ },
+ "name": "struct_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_float_frag.frag"
+ },
+ "name": "structcopy_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_float_frag.frag"
+ },
+ "name": "structnest_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_bool_frag.frag"
+ },
+ "name": "struct_bool_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_bool_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_bool_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_009_to_016.html
new file mode 100644
index 0000000000..aacd4526e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_009_to_016.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_bool_frag.frag"
+ },
+ "name": "structcopy_bool_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_bool_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_bool_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_bool_frag.frag"
+ },
+ "name": "structnest_bool_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_bool_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_bool_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_vec2_frag.frag"
+ },
+ "name": "struct_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_vec2_frag.frag"
+ },
+ "name": "structcopy_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_vec2_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_017_to_024.html
new file mode 100644
index 0000000000..c04ca16563
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_017_to_024.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_vec2_frag.frag"
+ },
+ "name": "structnest_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_vec3_frag.frag"
+ },
+ "name": "struct_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_vec3_frag.frag"
+ },
+ "name": "structcopy_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_vec3_frag.frag"
+ },
+ "name": "structnest_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_vec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_025_to_032.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_025_to_032.html
new file mode 100644
index 0000000000..cbbc42181b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_025_to_032.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_025_to_032.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_vec4_frag.frag"
+ },
+ "name": "struct_vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_vec4_frag.frag"
+ },
+ "name": "structcopy_vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_vec4_frag.frag"
+ },
+ "name": "structnest_vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_bvec2bvec3bvec4_frag.frag"
+ },
+ "name": "struct_bvec2bvec3bvec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_bvec2bvec3bvec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_bvec2bvec3bvec4_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_033_to_040.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_033_to_040.html
new file mode 100644
index 0000000000..3fa57169f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_033_to_040.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_033_to_040.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_bvec2bvec3bvec4_frag.frag"
+ },
+ "name": "structcopy_bvec2bvec3bvec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_bvec2bvec3bvec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_bvec2bvec3bvec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_bvec2bvec3bvec4_frag.frag"
+ },
+ "name": "structnest_bvec2bvec3bvec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_bvec2bvec3bvec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_bvec2bvec3bvec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_mat2_frag.frag"
+ },
+ "name": "struct_mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_mat2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_mat2_frag.frag"
+ },
+ "name": "structcopy_mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_mat2_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_041_to_048.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_041_to_048.html
new file mode 100644
index 0000000000..7cc87e2f57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_041_to_048.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_041_to_048.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_mat2_frag.frag"
+ },
+ "name": "structnest_mat2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_mat2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_mat2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_mat3_frag.frag"
+ },
+ "name": "struct_mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_mat3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_mat3_frag.frag"
+ },
+ "name": "structcopy_mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_mat3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_mat3_frag.frag"
+ },
+ "name": "structnest_mat3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_mat3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_mat3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_049_to_056.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_049_to_056.html
new file mode 100644
index 0000000000..9356340e4d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_049_to_056.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: struct_049_to_056.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "struct_mat4_frag.frag"
+ },
+ "name": "struct_mat4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "struct_mat4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "struct_mat4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structcopy_mat4_frag.frag"
+ },
+ "name": "structcopy_mat4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structcopy_mat4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structcopy_mat4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "structnest_mat4_frag.frag"
+ },
+ "name": "structnest_mat4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "structnest_mat4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "structnest_mat4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "nestedstructcomb_various_frag.frag"
+ },
+ "name": "nestedstructcomb_various_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "nestedstructcomb_various_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "nestedstructcomb_various_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_frag.frag
new file mode 100644
index 0000000000..88affd9767
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ bool a;
+ bool b;
+ bool c;
+ bool d;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(bool(12), bool(0), bool(25.5), bool(0.0));
+ float gray = 0.0;
+ if( (s.a==true) && (s.b==false) && (s.c == true) && (s.d==false))
+ gray=1.0;
+ else
+ gray =0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_vert.vert
new file mode 100644
index 0000000000..0a3b81b46d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bool_vert.vert
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ bool a;
+ bool b;
+ bool c;
+ bool d;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(bool(12), bool(0), bool(25.5), bool(0.0));
+ float gray = 0.0;
+ if( (s.a==true) && (s.b==false) && (s.c == true) && (s.d==false))
+ gray=1.0;
+ else
+ gray =0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_frag.frag
new file mode 100644
index 0000000000..1f8c7cfb6a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_frag.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ bvec2 a;
+ bvec3 b;
+ bvec4 c;
+};
+
+void main (void)
+{
+ sabcd s = sabcd( bvec2(12, 13), bvec3(14.0, 0.0, 139.0), bvec4(25.5, 17.0, 145, 163 ) );
+ float gray = 0.0;
+ if( (s.a[0]) && (s.a[1]) && (s.b[0]) && (!s.b[1]) && (s.b[2]) && (s.c[0]) && (s.c[1]) && (s.c[2]) )
+ gray=1.0;
+ else
+ gray =0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_vert.vert
new file mode 100644
index 0000000000..f82612477d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_bvec2bvec3bvec4_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ bvec2 a;
+ bvec3 b;
+ bvec4 c;
+};
+
+void main (void)
+{
+ sabcd s = sabcd( bvec2(12, 13), bvec3(14.0, 0.0, 139.0), bvec4(25.5, 17.0, 145, 163 ) );
+ float gray = 0.0;
+ if( (s.a[0]) && (s.a[1]) && (s.b[0]) && (!s.b[1]) && (s.b[2]) && (s.c[0]) && (s.c[1]) && (s.c[2]) )
+ gray=1.0;
+ else
+ gray =0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_frag.frag
new file mode 100644
index 0000000000..50c29bf575
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(1.0, 2.0, 4.0, 8.0);
+ gl_FragColor = vec4(vec3((s.a + s.b + s.c + s.d) / 15.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_vert.vert
new file mode 100644
index 0000000000..27ad8c0fde
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_float_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(1.0, 2.0, 4.0, 8.0);
+ color = vec4(vec3((s.a + s.b + s.c + s.d) / 15.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_frag.frag
new file mode 100644
index 0000000000..043c948f4d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ mat2 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat2(12.0, 29.0, 13.0, 26.0) );
+ gl_FragColor = vec4( vec3( (s.a[0][0] + s.a[0][1] + s.a[1][0] + s.a[1][1]) / 80.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_vert.vert
new file mode 100644
index 0000000000..6298630d07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat2_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ mat2 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat2(12.0, 29.0, 13.0, 26.0) );
+ color = vec4( vec3( (s.a[0][0] + s.a[0][1] + s.a[1][0] + s.a[1][1]) / 80.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_frag.frag
new file mode 100644
index 0000000000..1caa22aa7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_frag.frag
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ mat3 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat3(12.0, 29.0, 13.0, 26.0, 71.0, 63.0, 90.0, 118.0, 128.0) );
+ float sum=0.0;
+ int i,j;
+
+ sum = sum + s.a[0][0];
+ sum = sum + s.a[0][1];
+ sum = sum + s.a[0][2];
+ sum = sum + s.a[1][0];
+ sum = sum + s.a[1][1];
+ sum = sum + s.a[1][2];
+ sum = sum + s.a[2][0];
+ sum = sum + s.a[2][1];
+ sum = sum + s.a[2][2];
+
+ gl_FragColor = vec4( vec3( sum / 550.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_vert.vert
new file mode 100644
index 0000000000..f2880dc29d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat3_vert.vert
@@ -0,0 +1,37 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ mat3 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat3(12.0, 29.0, 13.0, 26.0, 71.0, 63.0, 90.0, 118.0, 128.0) );
+ float sum=0.0;
+
+ sum = sum + s.a[0][0];
+ sum = sum + s.a[0][1];
+ sum = sum + s.a[0][2];
+
+ sum = sum + s.a[1][0];
+ sum = sum + s.a[1][1];
+ sum = sum + s.a[1][2];
+
+ sum = sum + s.a[2][0];
+ sum = sum + s.a[2][1];
+ sum = sum + s.a[2][2];
+
+ color = vec4( vec3( sum / 550.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_frag.frag
new file mode 100644
index 0000000000..bfb6fe1918
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ mat4 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat4(12.0, 29.0, 13.0, 26.0,
+ 71.0, 63.0, 90.0, 118.0,
+ 128.0, 44.0, 57.0, 143.0,
+ 151.0, 14.0, 15.0, 21.0 ) );
+ float sum=0.0;
+ int i,j;
+
+ sum = sum + s.a[0][0];
+ sum = sum + s.a[0][1];
+ sum = sum + s.a[0][2];
+ sum = sum + s.a[0][3];
+ sum = sum + s.a[1][0];
+ sum = sum + s.a[1][1];
+ sum = sum + s.a[1][2];
+ sum = sum + s.a[1][3];
+ sum = sum + s.a[2][0];
+ sum = sum + s.a[2][1];
+ sum = sum + s.a[2][2];
+ sum = sum + s.a[2][3];
+ sum = sum + s.a[3][0];
+ sum = sum + s.a[3][1];
+ sum = sum + s.a[3][2];
+ sum = sum + s.a[3][3];
+
+ gl_FragColor = vec4( vec3( sum / 995.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_vert.vert
new file mode 100644
index 0000000000..5f21dea131
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_mat4_vert.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ mat4 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat4(12.0, 29.0, 13.0, 26.0,
+ 71.0, 63.0, 90.0, 118.0,
+ 128.0, 44.0, 57.0, 143.0,
+ 151.0, 14.0, 15.0, 21.0 ) );
+ float sum=0.0;
+
+ sum = sum + s.a[0][0];
+ sum = sum + s.a[0][1];
+ sum = sum + s.a[0][2];
+ sum = sum + s.a[0][3];
+
+ sum = sum + s.a[1][0];
+ sum = sum + s.a[1][1];
+ sum = sum + s.a[1][2];
+ sum = sum + s.a[1][3];
+
+ sum = sum + s.a[2][0];
+ sum = sum + s.a[2][1];
+ sum = sum + s.a[2][2];
+ sum = sum + s.a[2][3];
+
+ sum = sum + s.a[3][0];
+ sum = sum + s.a[3][1];
+ sum = sum + s.a[3][2];
+ sum = sum + s.a[3][3];
+
+ color = vec4( vec3( sum / 995.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_frag.frag
new file mode 100644
index 0000000000..1e8e54360d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ vec2 a;
+ vec2 b;
+};
+
+
+void main (void)
+{
+ sabcd s = sabcd(vec2(12.0, 29.0), vec2(13.0, 26.0) );
+
+ gl_FragColor = vec4( vec3( (s.a[0] + s.a[1] + s.b[0] + s.b[1]) / 80.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_vert.vert
new file mode 100644
index 0000000000..b7c7588767
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec2_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ vec2 a;
+ vec2 b;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(vec2(12.0, 29.0), vec2(13.0, 26.0) );
+ color = vec4( vec3( (s.a[0] + s.a[1] + s.b[0] + s.b[1]) / 80.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_frag.frag
new file mode 100644
index 0000000000..aba8516a94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ vec3 a;
+ vec3 b;
+};
+
+
+void main (void)
+{
+ sabcd s = sabcd(vec3(12.0, 29.0, 32.0), vec3(13.0, 26.0, 38.0 ) );
+
+ gl_FragColor = vec4( vec3( (s.a[0] + s.a[1] + s.a[2] + s.b[0] + s.b[1] + s.b[2]) / 150.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_vert.vert
new file mode 100644
index 0000000000..09c5bb54c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec3_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ vec3 a;
+ vec3 b;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(vec3(12.0, 29.0, 32.0), vec3(13.0, 26.0, 38.0 ) );
+ color = vec4( vec3( (s.a[0] + s.a[1] + s.a[2] + s.b[0] + s.b[1] + s.b[2]) / 150.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_frag.frag
new file mode 100644
index 0000000000..3d03168955
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ vec4 a;
+ vec4 b;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(vec4(12.0, 29.0, 32.0, 47.0), vec4(13.0, 26.0, 38.0, 53.0 ) );
+ gl_FragColor = vec4( vec3( (s.a[0] + s.a[1] + s.a[2] + s.a[3] + s.b[0] + s.b[1] + s.b[2] + s.b[3]) / 250.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_vert.vert
new file mode 100644
index 0000000000..3cd7d37047
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/struct_vec4_vert.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ vec4 a;
+ vec4 b;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(vec4(12.0, 29.0, 32.0, 47.0), vec4(13.0, 26.0, 38.0, 53.0 ) );
+ color = vec4( vec3( (s.a[0] + s.a[1] + s.a[2] + s.a[3] + s.b[0] + s.b[1] + s.b[2] + s.b[3]) / 250.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_frag.frag
new file mode 100644
index 0000000000..39e2a1054b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_frag.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ bool a;
+ bool b;
+ bool c;
+ bool d;
+};
+
+
+
+void main (void)
+{
+ sabcd s1 = sabcd(bool(12), bool(0), bool(25.5), bool(0.0));
+ sabcd s2 = sabcd(bool(0.0), bool(0.0), bool(0.0), bool(0.0));
+ s2 = s1;
+ float gray = 0.0;
+ if( (s2.a==true) && (s2.b==false) && (s2.c == true) && (s2.d==false))
+ gray=1.0;
+ else
+ gray =0.0;
+ gl_FragColor = vec4(gray,gray,gray,1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_vert.vert
new file mode 100644
index 0000000000..7149f8848c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bool_vert.vert
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ bool a;
+ bool b;
+ bool c;
+ bool d;
+};
+
+
+
+void main (void)
+{
+ sabcd s1 = sabcd(bool(12), bool(0), bool(25.5), bool(0.0));
+ sabcd s2 = sabcd(bool(0.0), bool(0.0), bool(0.0), bool(0.0));
+ s2 = s1;
+ float gray = 0.0;
+ if( (s2.a==true) && (s2.b==false) && (s2.c == true) && (s2.d==false))
+ gray=1.0;
+ else
+ gray =0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_frag.frag
new file mode 100644
index 0000000000..d30d390c81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_frag.frag
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ bvec2 a;
+ bvec3 b;
+ bvec4 c;
+};
+
+void main (void)
+{
+ sabcd s = sabcd( bvec2(12, 13), bvec3(14.0, 0.0, 139.0), bvec4(25.5, 17.0, 145, 163 ) );
+ sabcd s2 = sabcd( bvec2(0, 0), bvec3(0.0, 0.0, 0.0), bvec4(0.0, 0.0, 0.0, 0.0 ) );
+ s2 = s;
+ float gray = 0.0;
+ if( (s2.a[0]) && (s2.a[1]) && (s2.b[0]) && (!s2.b[1]) && (s2.b[2]) && (s2.c[0]) && (s2.c[1]) && (s2.c[2]) )
+ gray=1.0;
+ else
+ gray =0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_vert.vert
new file mode 100644
index 0000000000..24f3981d03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_bvec2bvec3bvec4_vert.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ bvec2 a;
+ bvec3 b;
+ bvec4 c;
+};
+
+void main (void)
+{
+ sabcd s = sabcd( bvec2(12, 13), bvec3(14.0, 0.0, 139.0), bvec4(25.5, 17.0, 145, 163 ) );
+ sabcd s2 = sabcd( bvec2(0, 0), bvec3(0.0, 0.0, 0.0), bvec4(0.0, 0.0, 0.0, 0.0 ) );
+ s2 = s;
+ float gray = 0.0;
+ if( (s2.a[0]) && (s2.a[1]) && (s2.b[0]) && (!s2.b[1]) && (s2.b[2]) && (s2.c[0]) && (s2.c[1]) && (s2.c[2]) && (s2.c[3]) )
+ gray=1.0;
+ else
+ gray =0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_frag.frag
new file mode 100644
index 0000000000..de34d38e48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_frag.frag
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(1.0, 2.0, 4.0, 8.0);
+ sabcd s2 = sabcd(0.0, 0.0, 0.0, 0.0);
+ s2 = s;
+ gl_FragColor = vec4((s.a + s.b + s.c + s.d) / 15.0, (s2.a + s2.b + s2.c + s2.d) / 15.0, 1.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_vert.vert
new file mode 100644
index 0000000000..baf2c7afe7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_float_vert.vert
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+
+
+void main (void)
+{
+ sabcd s = sabcd(1.0, 2.0, 4.0, 8.0);
+ sabcd s2 = sabcd(0.0, 0.0, 0.0, 0.0);
+ s2 = s;
+ color = vec4((s.a + s.b + s.c + s.d) / 15.0, (s2.a + s2.b + s2.c + s2.d) / 15.0, 1.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_frag.frag
new file mode 100644
index 0000000000..78de99d99b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ mat2 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat2(12.0, 29.0, 13.0, 26.0) );
+ sabcd s2 = sabcd(mat2(0.0, 0.0, 0.0, 0.0) );
+ s2 = s;
+ gl_FragColor = vec4( vec3( (s2.a[0][0] + s2.a[0][1] + s2.a[1][0] + s2.a[1][1]) / 80.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_vert.vert
new file mode 100644
index 0000000000..1f7222178a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat2_vert.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ mat2 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat2(12.0, 29.0, 13.0, 26.0) );
+ sabcd s2 = sabcd(mat2(0.0, 0.0, 0.0, 0.0) );
+ s2 = s;
+ color = vec4( vec3( (s2.a[0][0] + s2.a[0][1] + s2.a[1][0] + s2.a[1][1]) / 80.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_frag.frag
new file mode 100644
index 0000000000..fe7c54f2e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_frag.frag
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ mat3 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat3(12.0, 29.0, 13.0, 26.0, 71.0, 63.0, 90.0, 118.0, 128.0) );
+ sabcd s2 = sabcd(mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
+ s2 = s;
+ float sum=0.0;
+ int i,j;
+
+ sum = sum + s2.a[0][0];
+ sum = sum + s2.a[0][1];
+ sum = sum + s2.a[0][2];
+ sum = sum + s2.a[1][0];
+ sum = sum + s2.a[1][1];
+ sum = sum + s2.a[1][2];
+ sum = sum + s2.a[2][0];
+ sum = sum + s2.a[2][1];
+ sum = sum + s2.a[2][2];
+
+ gl_FragColor = vec4( vec3( sum / 550.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_vert.vert
new file mode 100644
index 0000000000..c836dc75eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat3_vert.vert
@@ -0,0 +1,39 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ mat3 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat3(12.0, 29.0, 13.0, 26.0, 71.0, 63.0, 90.0, 118.0, 128.0) );
+ sabcd s2 = sabcd(mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
+ s2 = s;
+ float sum=0.0;
+
+ sum = sum + s2.a[0][0];
+ sum = sum + s2.a[0][1];
+ sum = sum + s2.a[0][2];
+
+ sum = sum + s2.a[1][0];
+ sum = sum + s2.a[1][1];
+ sum = sum + s2.a[1][2];
+
+ sum = sum + s2.a[2][0];
+ sum = sum + s2.a[2][1];
+ sum = sum + s2.a[2][2];
+
+ color = vec4( vec3( sum / 550.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_frag.frag
new file mode 100644
index 0000000000..ab3c925fa9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_frag.frag
@@ -0,0 +1,51 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ mat4 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat4(12.0, 29.0, 13.0, 26.0,
+ 71.0, 63.0, 90.0, 118.0,
+ 128.0, 44.0, 57.0, 143.0,
+ 151.0, 14.0, 15.0, 21.0 ) );
+ sabcd s2 = sabcd(mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0 ) );
+ s2 = s;
+ float sum=0.0;
+ int i,j;
+
+ sum = sum + s2.a[0][0];
+ sum = sum + s2.a[0][1];
+ sum = sum + s2.a[0][2];
+ sum = sum + s2.a[0][3];
+ sum = sum + s2.a[1][0];
+ sum = sum + s2.a[1][1];
+ sum = sum + s2.a[1][2];
+ sum = sum + s2.a[1][3];
+ sum = sum + s2.a[2][0];
+ sum = sum + s2.a[2][1];
+ sum = sum + s2.a[2][2];
+ sum = sum + s2.a[2][3];
+ sum = sum + s2.a[3][0];
+ sum = sum + s2.a[3][1];
+ sum = sum + s2.a[3][2];
+ sum = sum + s2.a[3][3];
+
+ gl_FragColor = vec4( vec3( sum / 995.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_vert.vert
new file mode 100644
index 0000000000..fdb5a889fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_mat4_vert.vert
@@ -0,0 +1,53 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ mat4 a;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(mat4(12.0, 29.0, 13.0, 26.0,
+ 71.0, 63.0, 90.0, 118.0,
+ 128.0, 44.0, 57.0, 143.0,
+ 151.0, 14.0, 15.0, 21.0 ) );
+ sabcd s2 = sabcd(mat4(0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0 ) );
+ s2 = s;
+ float sum=0.0;
+
+ sum = sum + s2.a[0][0];
+ sum = sum + s2.a[0][1];
+ sum = sum + s2.a[0][2];
+ sum = sum + s2.a[0][3];
+
+ sum = sum + s2.a[1][0];
+ sum = sum + s2.a[1][1];
+ sum = sum + s2.a[1][2];
+ sum = sum + s2.a[1][3];
+
+ sum = sum + s2.a[2][0];
+ sum = sum + s2.a[2][1];
+ sum = sum + s2.a[2][2];
+ sum = sum + s2.a[2][3];
+
+ sum = sum + s2.a[3][0];
+ sum = sum + s2.a[3][1];
+ sum = sum + s2.a[3][2];
+ sum = sum + s2.a[3][3];
+
+ color = vec4( vec3( sum / 995.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_frag.frag
new file mode 100644
index 0000000000..9acaeaa23f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ vec2 a;
+ vec2 b;
+};
+
+
+void main (void)
+{
+ sabcd s1 = sabcd(vec2(12.0, 29.0), vec2(13.0, 26.0) );
+ sabcd s2 = sabcd(vec2(0.0, 0.0), vec2(0.0, 0.0) );
+ s2 = s1;
+ gl_FragColor = vec4( vec3( (s2.a[0] + s2.a[1] + s2.b[0] + s2.b[1]) / 80.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_vert.vert
new file mode 100644
index 0000000000..54f7de5b5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec2_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ vec2 a;
+ vec2 b;
+};
+
+
+
+void main (void)
+{
+ sabcd s1 = sabcd(vec2(12.0, 29.0), vec2(13.0, 26.0) );
+ sabcd s2 = sabcd(vec2(0.0, 0.0), vec2(0.0, 0.0) );
+ s2 = s1;
+ color = vec4( vec3( (s2.a[0] + s2.a[1] + s2.b[0] + s2.b[1]) / 80.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_frag.frag
new file mode 100644
index 0000000000..cd3f12ccb1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_frag.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct sabcd
+{
+ vec3 a;
+ vec3 b;
+};
+
+
+void main (void)
+{
+ sabcd s = sabcd(vec3(12.0, 29.0, 32.0), vec3(13.0, 26.0, 38.0 ) );
+ sabcd s2 = sabcd(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0 ) );
+ s2 = s;
+ gl_FragColor = vec4( vec3( (s2.a[0] + s2.a[1] + s2.a[2] + s2.b[0] + s2.b[1] + s2.b[2]) / 150.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_vert.vert
new file mode 100644
index 0000000000..eeddebe2ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec3_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+
+
+struct sabcd
+{
+ vec3 a;
+ vec3 b;
+};
+
+
+
+void main (void)
+{
+ sabcd s1 = sabcd(vec3(12.0, 29.0, 32.0), vec3(13.0, 26.0, 38.0 ) );
+ sabcd s2 = sabcd(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0 ) );
+ s2 = s1;
+ color = vec4( vec3( (s2.a[0] + s2.a[1] + s2.a[2] + s2.b[0] + s2.b[1] + s2.b[2]) / 150.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_frag.frag
new file mode 100644
index 0000000000..bf02e6cd61
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_frag.frag
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct sabcd
+{
+ vec4 a;
+ vec4 b;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(vec4(12.0, 29.0, 32.0, 47.0), vec4(13.0, 26.0, 38.0, 53.0 ) );
+ sabcd s2 = sabcd(vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0 ) );
+ s2 = s;
+ gl_FragColor = vec4( vec3( (s2.a[0] + s2.a[1] + s2.a[2] + s2.a[3] + s2.b[0] + s2.b[1] + s2.b[2] + s2.b[3]) / 250.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_vert.vert
new file mode 100644
index 0000000000..af30524ed2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structcopy_vec4_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct sabcd
+{
+ vec4 a;
+ vec4 b;
+};
+
+void main (void)
+{
+ sabcd s = sabcd(vec4(12.0, 29.0, 32.0, 47.0), vec4(13.0, 26.0, 38.0, 53.0 ) );
+ sabcd s2 = sabcd(vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0 ) );
+ s2 = s;
+ color = vec4( vec3( (s2.a[0] + s2.a[1] + s2.a[2] + s2.a[3] + s2.b[0] + s2.b[1] + s2.b[2] + s2.b[3]) / 250.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_frag.frag
new file mode 100644
index 0000000000..74c30e5103
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_frag.frag
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ bool b;
+};
+
+struct nesta
+{
+ bool a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(bool(1.0), nestb(bool(0.0))));
+ float gray = 0.0;
+
+ if( (s.nest_a.a == true) && (s.nest_a.nest_b.b == false))
+ gray=1.0;
+ else
+ gray =0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_vert.vert
new file mode 100644
index 0000000000..3cfc2cf722
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bool_vert.vert
@@ -0,0 +1,41 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ bool b;
+};
+
+struct nesta
+{
+ bool a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(bool(1.0), nestb(bool(0.0))));
+ float gray = 0.0;
+
+ if( (s.nest_a.a == true) && (s.nest_a.nest_b.b == false))
+ gray=1.0;
+ else
+ gray =0.0;
+ color = vec4(gray, gray, gray, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_frag.frag
new file mode 100644
index 0000000000..d4515dbd2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_frag.frag
@@ -0,0 +1,54 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+struct nestb
+{
+ bvec2 a2;
+ bvec3 b2;
+ bvec4 c2;
+};
+
+struct nesta
+{
+ bvec2 a1;
+ bvec3 b1;
+ bvec4 c1;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest( nesta( bvec2(12, 13), bvec3(14.0, 0.0, 139.0), bvec4(25.5, 17.0, 145, 163 ),
+ nestb( bvec2(28, 0), bvec3(0.0, 0.0, 1.0), bvec4(0.0, 17.0, 145, 0 )
+ )
+ )
+ );
+ float gray = 0.0;
+ if( ( s.nest_a.a1[0] ) && ( s.nest_a.a1[1] ) &&
+ ( s.nest_a.b1[0] ) && (! (s.nest_a.b1[1]) ) && ( s.nest_a.b1[2] ) &&
+ ( s.nest_a.c1[0] ) && ( s.nest_a.c1[1] ) && ( s.nest_a.c1[2] ) && ( s.nest_a.c1[3] ) &&
+ ( s.nest_a.nest_b.a2[0] ) && ( !( s.nest_a.nest_b.a2[1] ) ) &&
+ (! ( s.nest_a.nest_b.b2[0] ) ) && (! ( s.nest_a.nest_b.b2[1] ) ) && (s.nest_a.nest_b.b2[2]) &&
+ (! ( s.nest_a.nest_b.c2[0] ) ) && (s.nest_a.nest_b.c2[1]) && (s.nest_a.nest_b.c2[2]) && (! ( s.nest_a.nest_b.c2[3] ) )
+ )
+ gray=1.0;
+ else
+ gray =0.0;
+
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_vert.vert
new file mode 100644
index 0000000000..c0ca10fc08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_bvec2bvec3bvec4_vert.vert
@@ -0,0 +1,57 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ bvec2 a2;
+ bvec3 b2;
+ bvec4 c2;
+};
+
+struct nesta
+{
+ bvec2 a1;
+ bvec3 b1;
+ bvec4 c1;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+
+ nest s = nest( nesta( bvec2(12, 13), bvec3(14.0, 0.0, 139.0), bvec4(25.5, 17.0, 145, 163 ),
+ nestb( bvec2(28, 0), bvec3(0.0, 0.0, 1.0), bvec4(0.0, 17.0, 145, 0 )
+ )
+ )
+ );
+
+ float gray = 0.0;
+
+ if( ( s.nest_a.a1[0] ) && ( s.nest_a.a1[1] ) &&
+ ( s.nest_a.b1[0] ) && (! (s.nest_a.b1[1]) ) && ( s.nest_a.b1[2] ) &&
+ ( s.nest_a.c1[0] ) && ( s.nest_a.c1[1] ) && ( s.nest_a.c1[2] ) && ( s.nest_a.c1[3] ) &&
+ ( s.nest_a.nest_b.a2[0] ) && ( !( s.nest_a.nest_b.a2[1] ) ) &&
+ (! ( s.nest_a.nest_b.b2[0] ) ) && (! ( s.nest_a.nest_b.b2[1] ) ) && (s.nest_a.nest_b.b2[2]) &&
+ (! ( s.nest_a.nest_b.c2[0] ) ) && (s.nest_a.nest_b.c2[1]) && (s.nest_a.nest_b.c2[2]) && (! ( s.nest_a.nest_b.c2[3] ) )
+ )
+ gray=1.0;
+ else
+ gray =0.0;
+ color = vec4(gray, gray, gray, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_frag.frag
new file mode 100644
index 0000000000..b914193aa1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ float b;
+};
+
+struct nesta
+{
+ float a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(1.0, nestb(2.0)));
+ gl_FragColor = vec4(vec3((s.nest_a.a + s.nest_a.nest_b.b) / 3.0), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_vert.vert
new file mode 100644
index 0000000000..98436ea212
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_float_vert.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ float b;
+};
+
+struct nesta
+{
+ float a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(1.0, nestb(2.0)));
+ color = vec4(vec3((s.nest_a.a + s.nest_a.nest_b.b) / 3.0), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_frag.frag
new file mode 100644
index 0000000000..9b16175271
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_frag.frag
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ mat2 b;
+};
+
+struct nesta
+{
+ mat2 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta( mat2(11, 13, 29, 33), nestb( mat2(12, 19, 79, 81) ) ) );
+
+
+ gl_FragColor = vec4( vec3( (s.nest_a.a[0][0] + s.nest_a.a[0][1] + s.nest_a.a[1][0] + s.nest_a.a[1][1] + s.nest_a.nest_b.b[0][0] + s.nest_a.nest_b.b[0][1] + s.nest_a.nest_b.b[1][0] + s.nest_a.nest_b.b[1][1] ) / 277.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_vert.vert
new file mode 100644
index 0000000000..1aae92236d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat2_vert.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ mat2 b;
+};
+
+struct nesta
+{
+ mat2 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta( mat2(11, 13, 29, 33), nestb( mat2(12, 19, 79, 81) ) ) );
+ color = vec4( vec3( (s.nest_a.a[0][0] + s.nest_a.a[0][1] + s.nest_a.a[1][0] + s.nest_a.a[1][1] + s.nest_a.nest_b.b[0][0] + s.nest_a.nest_b.b[0][1] + s.nest_a.nest_b.b[1][0] + s.nest_a.nest_b.b[1][1] ) / 277.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_frag.frag
new file mode 100644
index 0000000000..407981499c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_frag.frag
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ mat3 b;
+};
+
+struct nesta
+{
+ mat3 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta( mat3(11, 13, 29, 33, 63, 13, 49, 57, 71), nestb( mat3(12, 19, 79, 81, 35, 51, 73, 66, 23) ) ) );
+ float sum1=0.0,sum2=0.0;
+ int i,j;
+
+ sum1 = sum1 + s.nest_a.a[0][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][0];
+
+ sum1 = sum1 + s.nest_a.a[0][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][1];
+
+ sum1 = sum1 + s.nest_a.a[0][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][2];
+
+ sum1 = sum1 + s.nest_a.a[1][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][0];
+
+ sum1 = sum1 + s.nest_a.a[1][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][1];
+
+ sum1 = sum1 + s.nest_a.a[1][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][2];
+
+ sum1 = sum1 + s.nest_a.a[2][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][0];
+
+ sum1 = sum1 + s.nest_a.a[2][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][1];
+
+ sum1 = sum1 + s.nest_a.a[2][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][2];
+
+ gl_FragColor = vec4( vec3( ( sum1 + sum2 )/ 778.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_vert.vert
new file mode 100644
index 0000000000..4870801b7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat3_vert.vert
@@ -0,0 +1,57 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ mat3 b;
+};
+
+struct nesta
+{
+ mat3 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta( mat3(11, 13, 29, 33, 63, 13, 49, 57, 71), nestb( mat3(12, 19, 79, 81, 35, 51, 73, 66, 23) ) ) );
+ float sum1=0.0,sum2=0.0;
+
+ sum1 = sum1 + s.nest_a.a[0][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][0];
+ sum1 = sum1 + s.nest_a.a[0][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][1];
+ sum1 = sum1 + s.nest_a.a[0][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][2];
+
+ sum1 = sum1 + s.nest_a.a[1][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][0];
+ sum1 = sum1 + s.nest_a.a[1][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][1];
+ sum1 = sum1 + s.nest_a.a[1][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][2];
+
+ sum1 = sum1 + s.nest_a.a[2][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][0];
+ sum1 = sum1 + s.nest_a.a[2][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][1];
+ sum1 = sum1 + s.nest_a.a[2][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][2];
+
+ color = vec4( vec3( ( sum1 + sum2 )/ 778.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_frag.frag
new file mode 100644
index 0000000000..147b8c5ba4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_frag.frag
@@ -0,0 +1,83 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ mat4 b;
+};
+
+struct nesta
+{
+ mat4 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta( mat4(11, 13, 29, 33, 63, 13, 49, 57, 71, 47, 91, 101, 167, 21, 39, 41), nestb( mat4(12, 19, 79, 81, 35, 51, 73, 66, 23, 134, 121, 156, 76, 23, 24, 78) ) ) );
+ float sum1=0.0,sum2=0.0;
+ int i,j;
+
+ sum1 = sum1 + s.nest_a.a[0][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][0];
+
+ sum1 = sum1 + s.nest_a.a[0][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][1];
+
+ sum1 = sum1 + s.nest_a.a[0][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][2];
+
+ sum1 = sum1 + s.nest_a.a[0][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][3];
+
+ sum1 = sum1 + s.nest_a.a[1][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][0];
+
+ sum1 = sum1 + s.nest_a.a[1][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][1];
+
+ sum1 = sum1 + s.nest_a.a[1][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][2];
+
+ sum1 = sum1 + s.nest_a.a[1][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][3];
+
+ sum1 = sum1 + s.nest_a.a[2][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][0];
+
+ sum1 = sum1 + s.nest_a.a[2][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][1];
+
+ sum1 = sum1 + s.nest_a.a[2][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][2];
+
+ sum1 = sum1 + s.nest_a.a[2][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][3];
+
+ sum1 = sum1 + s.nest_a.a[3][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][0];
+
+ sum1 = sum1 + s.nest_a.a[3][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][1];
+
+ sum1 = sum1 + s.nest_a.a[3][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][2];
+
+ sum1 = sum1 + s.nest_a.a[3][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][3];
+
+ gl_FragColor = vec4( vec3( ( sum1 + sum2 )/ 1897.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_vert.vert
new file mode 100644
index 0000000000..b6bd4a21d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_mat4_vert.vert
@@ -0,0 +1,72 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ mat4 b;
+};
+
+struct nesta
+{
+ mat4 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta( mat4(11, 13, 29, 33, 63, 13, 49, 57, 71, 47, 91, 101, 167, 21, 39, 41), nestb( mat4(12, 19, 79, 81, 35, 51, 73, 66, 23, 134, 121, 156, 76, 23, 24, 78) ) ) );
+ float sum1=0.0,sum2=0.0;
+
+ sum1 = sum1 + s.nest_a.a[0][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][0];
+ sum1 = sum1 + s.nest_a.a[0][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][1];
+ sum1 = sum1 + s.nest_a.a[0][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][2];
+ sum1 = sum1 + s.nest_a.a[0][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[0][3];
+
+ sum1 = sum1 + s.nest_a.a[1][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][0];
+ sum1 = sum1 + s.nest_a.a[1][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][1];
+ sum1 = sum1 + s.nest_a.a[1][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][2];
+ sum1 = sum1 + s.nest_a.a[1][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[1][3];
+
+ sum1 = sum1 + s.nest_a.a[2][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][0];
+ sum1 = sum1 + s.nest_a.a[2][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][1];
+ sum1 = sum1 + s.nest_a.a[2][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][2];
+ sum1 = sum1 + s.nest_a.a[2][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[2][3];
+
+ sum1 = sum1 + s.nest_a.a[3][0];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][0];
+ sum1 = sum1 + s.nest_a.a[3][1];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][1];
+ sum1 = sum1 + s.nest_a.a[3][2];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][2];
+ sum1 = sum1 + s.nest_a.a[3][3];
+ sum2 = sum2 + s.nest_a.nest_b.b[3][3];
+
+ color = vec4( vec3( ( sum1 + sum2 )/ 1897.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_frag.frag
new file mode 100644
index 0000000000..e59911fec9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_frag.frag
@@ -0,0 +1,33 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ vec2 b;
+};
+
+struct nesta
+{
+ vec2 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(vec2(11, 13), nestb(vec2(12, 19) ) ) );
+
+ gl_FragColor = vec4( vec3( (s.nest_a.a[0] + s.nest_a.a[1] + s.nest_a.nest_b.b[0] + s.nest_a.nest_b.b[1] ) / 55.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_vert.vert
new file mode 100644
index 0000000000..b7a6bfd88c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec2_vert.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ vec2 b;
+};
+
+struct nesta
+{
+ vec2 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(vec2(11, 13), nestb(vec2(12, 19) ) ) );
+ color = vec4( vec3( (s.nest_a.a[0] + s.nest_a.a[1] + s.nest_a.nest_b.b[0] + s.nest_a.nest_b.b[1] ) / 55.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_frag.frag
new file mode 100644
index 0000000000..fa650ac2ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ vec3 b;
+};
+
+struct nesta
+{
+ vec3 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(vec3(11, 13, 17), nestb(vec3(12, 19, 29) ) ) );
+ gl_FragColor = vec4( vec3( (s.nest_a.a[0] + s.nest_a.a[1] + s.nest_a.a[2] + s.nest_a.nest_b.b[0] + s.nest_a.nest_b.b[1] + s.nest_a.nest_b.b[2]) / 101.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_vert.vert
new file mode 100644
index 0000000000..6d9247639d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec3_vert.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ vec3 b;
+};
+
+struct nesta
+{
+ vec3 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(vec3(11, 13, 17), nestb(vec3(12, 19, 29) ) ) );
+ color = vec4( vec3( (s.nest_a.a[0] + s.nest_a.a[1] + s.nest_a.a[2] + s.nest_a.nest_b.b[0] + s.nest_a.nest_b.b[1] + s.nest_a.nest_b.b[2]) / 101.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_frag.frag
new file mode 100644
index 0000000000..bdd595424b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+struct nestb
+{
+ vec4 b;
+};
+
+struct nesta
+{
+ vec4 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(vec4(11, 13, 17, 31), nestb(vec4(12, 19, 29, 69) ) ) );
+ gl_FragColor = vec4( vec3( (s.nest_a.a[0] + s.nest_a.a[1] + s.nest_a.a[2] + s.nest_a.a[3] + s.nest_a.nest_b.b[0] + s.nest_a.nest_b.b[1] + s.nest_a.nest_b.b[2] + s.nest_a.nest_b.b[3]) / 201.0 ), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_vert.vert
new file mode 100644
index 0000000000..46fad09a83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/struct/structnest_vec4_vert.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+struct nestb
+{
+ vec4 b;
+};
+
+struct nesta
+{
+ vec4 a;
+ nestb nest_b;
+};
+
+struct nest
+{
+ nesta nest_a;
+};
+
+void main (void)
+{
+ nest s = nest(nesta(vec4(11, 13, 17, 31), nestb(vec4(12, 19, 29, 69) ) ) );
+ color = vec4( vec3( (s.nest_a.a[0] + s.nest_a.a[1] + s.nest_a.a[2] + s.nest_a.a[3] + s.nest_a.nest_b.b[0] + s.nest_a.nest_b.b[1] + s.nest_a.nest_b.b[2] + s.nest_a.nest_b.b[3]) / 201.0 ), 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/input.run.txt
new file mode 100644
index 0000000000..11fe45566a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/input.run.txt
@@ -0,0 +1,16 @@
+# this file is auto-generated. DO NOT EDIT.
+swizzlers_001_to_008.html
+swizzlers_009_to_016.html
+swizzlers_017_to_024.html
+swizzlers_025_to_032.html
+swizzlers_033_to_040.html
+swizzlers_041_to_048.html
+swizzlers_049_to_056.html
+swizzlers_057_to_064.html
+swizzlers_065_to_072.html
+swizzlers_073_to_080.html
+swizzlers_081_to_088.html
+swizzlers_089_to_096.html
+swizzlers_097_to_104.html
+swizzlers_105_to_112.html
+swizzlers_113_to_120.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_001_to_008.html
new file mode 100644
index 0000000000..3331c6a6cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_001_to_008.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_xyzw_1vec4_frag.frag"
+ },
+ "name": "vec4_xyzw_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_xyzw_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_xyzw_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_zwxy_1vec4_frag.frag"
+ },
+ "name": "vec4_zwxy_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_zwxy_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_zwxy_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_yxwz_1vec4_frag.frag"
+ },
+ "name": "vec4_yxwz_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_yxwz_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_yxwz_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_wxzy_1vec4_frag.frag"
+ },
+ "name": "vec4_wxzy_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_wxzy_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_wxzy_1vec4_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html
new file mode 100644
index 0000000000..74677ea969
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_xyz_w_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_xyz_w_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_xyz_w_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_xyz_w_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_zwx_y_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_zwx_y_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_zwx_y_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_zwx_y_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_yxw_z_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_yxw_z_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_yxw_z_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_yxw_z_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_wxz_y_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_wxz_y_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_wxz_y_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_wxz_y_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_017_to_024.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_017_to_024.html
new file mode 100644
index 0000000000..812c44ea48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_017_to_024.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_017_to_024.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_xy_zw_2vec2_frag.frag"
+ },
+ "name": "vec4_xy_zw_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_xy_zw_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_xy_zw_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_zx_wy_2vec2_frag.frag"
+ },
+ "name": "vec4_zx_wy_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_zx_wy_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_zx_wy_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_yx_wz_2vec2_frag.frag"
+ },
+ "name": "vec4_yx_wz_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_yx_wz_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_yx_wz_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_wx_zy_2vec2_frag.frag"
+ },
+ "name": "vec4_wx_zy_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_wx_zy_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_wx_zy_2vec2_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_025_to_032.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_025_to_032.html
new file mode 100644
index 0000000000..6dd61f8f61
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_025_to_032.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_025_to_032.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_x_y_z_w_4float_frag.frag"
+ },
+ "name": "vec4_x_y_z_w_4float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_x_y_z_w_4float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_x_y_z_w_4float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_xyz_1vec3_frag.frag"
+ },
+ "name": "vec3_xyz_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_xyz_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_xyz_1vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_yxz_1vec3_frag.frag"
+ },
+ "name": "vec3_yxz_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_yxz_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_yxz_1vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_zyx_1vec3_frag.frag"
+ },
+ "name": "vec3_zyx_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_zyx_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_zyx_1vec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_033_to_040.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_033_to_040.html
new file mode 100644
index 0000000000..2352584bfd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_033_to_040.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_033_to_040.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_xy_z_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_xy_z_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_xy_z_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_xy_z_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_xz_y_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_xz_y_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_xz_y_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_xz_y_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_yz_x_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_yz_x_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_yz_x_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_yz_x_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_zx_y_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_zx_y_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_zx_y_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_zx_y_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_041_to_048.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_041_to_048.html
new file mode 100644
index 0000000000..8f6ae6e13b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_041_to_048.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_041_to_048.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_rgba_1vec4_frag.frag"
+ },
+ "name": "vec4_rgba_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_rgba_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_rgba_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_barg_1vec4_frag.frag"
+ },
+ "name": "vec4_barg_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_barg_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_barg_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_grab_1vec4_frag.frag"
+ },
+ "name": "vec4_grab_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_grab_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_grab_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_arbg_1vec4_frag.frag"
+ },
+ "name": "vec4_arbg_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_arbg_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_arbg_1vec4_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_049_to_056.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_049_to_056.html
new file mode 100644
index 0000000000..0a0c5fb477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_049_to_056.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_049_to_056.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_rgb_a_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_rgb_a_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_rgb_a_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_rgb_a_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_bar_g_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_bar_g_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_bar_g_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_bar_g_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_gra_b_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_gra_b_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_gra_b_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_gra_b_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_arb_g_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_arb_g_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_arb_g_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_arb_g_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_057_to_064.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_057_to_064.html
new file mode 100644
index 0000000000..4418250007
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_057_to_064.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_057_to_064.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_rg_ba_2vec2_frag.frag"
+ },
+ "name": "vec4_rg_ba_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_rg_ba_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_rg_ba_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_br_ag_2vec2_frag.frag"
+ },
+ "name": "vec4_br_ag_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_br_ag_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_br_ag_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_gr_ab_2vec2_frag.frag"
+ },
+ "name": "vec4_gr_ab_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_gr_ab_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_gr_ab_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_ar_bg_2vec2_frag.frag"
+ },
+ "name": "vec4_ar_bg_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_ar_bg_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_ar_bg_2vec2_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_065_to_072.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_065_to_072.html
new file mode 100644
index 0000000000..fcd80d4009
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_065_to_072.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_065_to_072.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_r_g_b_a_4float_frag.frag"
+ },
+ "name": "vec4_r_g_b_a_4float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_r_g_b_a_4float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_r_g_b_a_4float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_rgb_1vec3_frag.frag"
+ },
+ "name": "vec3_rgb_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_rgb_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_rgb_1vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_grb_1vec3_frag.frag"
+ },
+ "name": "vec3_grb_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_grb_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_grb_1vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_bgr_1vec3_frag.frag"
+ },
+ "name": "vec3_bgr_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_bgr_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_bgr_1vec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_073_to_080.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_073_to_080.html
new file mode 100644
index 0000000000..7e23ef6f19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_073_to_080.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_073_to_080.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_rg_b_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_rg_b_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_rg_b_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_rg_b_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_rb_g_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_rb_g_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_rb_g_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_rb_g_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_gb_r_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_gb_r_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_gb_r_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_gb_r_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_br_g_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_br_g_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_br_g_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_br_g_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_081_to_088.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_081_to_088.html
new file mode 100644
index 0000000000..e9d888c8d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_081_to_088.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_081_to_088.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_stpq_1vec4_frag.frag"
+ },
+ "name": "vec4_stpq_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_stpq_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_stpq_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_pqst_1vec4_frag.frag"
+ },
+ "name": "vec4_pqst_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_pqst_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_pqst_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_tsqp_1vec4_frag.frag"
+ },
+ "name": "vec4_tsqp_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_tsqp_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_tsqp_1vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_qspt_1vec4_frag.frag"
+ },
+ "name": "vec4_qspt_1vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_qspt_1vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_qspt_1vec4_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_089_to_096.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_089_to_096.html
new file mode 100644
index 0000000000..24a16ba7d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_089_to_096.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_089_to_096.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_stp_q_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_stp_q_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_stp_q_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_stp_q_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_pqs_t_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_pqs_t_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_pqs_t_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_pqs_t_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_tsq_p_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_tsq_p_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_tsq_p_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_tsq_p_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_qsp_t_1vec3_1float_frag.frag"
+ },
+ "name": "vec4_qsp_t_1vec3_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_qsp_t_1vec3_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_qsp_t_1vec3_1float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_097_to_104.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_097_to_104.html
new file mode 100644
index 0000000000..7d29fca4b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_097_to_104.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_097_to_104.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_st_pq_2vec2_frag.frag"
+ },
+ "name": "vec4_st_pq_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_st_pq_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_st_pq_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_ps_qt_2vec2_frag.frag"
+ },
+ "name": "vec4_ps_qt_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_ps_qt_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_ps_qt_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_ts_qp_2vec2_frag.frag"
+ },
+ "name": "vec4_ts_qp_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_ts_qp_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_ts_qp_2vec2_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_qs_pt_2vec2_frag.frag"
+ },
+ "name": "vec4_qs_pt_2vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_qs_pt_2vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_qs_pt_2vec2_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_105_to_112.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_105_to_112.html
new file mode 100644
index 0000000000..38d95f6232
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_105_to_112.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_105_to_112.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_s_t_p_q_4float_frag.frag"
+ },
+ "name": "vec4_s_t_p_q_4float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec4_s_t_p_q_4float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_s_t_p_q_4float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_stp_1vec3_frag.frag"
+ },
+ "name": "vec3_stp_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_stp_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_stp_1vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_tsp_1vec3_frag.frag"
+ },
+ "name": "vec3_tsp_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_tsp_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_tsp_1vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_pts_1vec3_frag.frag"
+ },
+ "name": "vec3_pts_1vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_pts_1vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_pts_1vec3_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_113_to_120.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_113_to_120.html
new file mode 100644
index 0000000000..f62ab3800f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/swizzlers_113_to_120.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: swizzlers_113_to_120.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_st_p_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_st_p_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_st_p_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_st_p_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_sp_t_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_sp_t_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_sp_t_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_sp_t_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_tp_s_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_tp_s_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_tp_s_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_tp_s_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_ps_t_1vec2_1float_frag.frag"
+ },
+ "name": "vec3_ps_t_1vec2_1float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "vec3_ps_t_1vec2_1float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_ps_t_1vec2_1float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_frag.frag
new file mode 100644
index 0000000000..a2776d9430
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ vec3 t = m.bgr;
+ vec4 a = vec4(t.b, t.g, t.r ,al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_vert.vert
new file mode 100644
index 0000000000..3bf609e92a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_bgr_1vec3_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec3 t = m.bgr;
+ vec4 a = vec4(t.b, t.g, t.r, lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..037da28f85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ float k = m.g;
+ vec2 n = m.br;
+ vec4 a = vec4(n.g, k, n.r, al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..7f638fd239
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_br_g_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec2 t = m.br;
+ float k = m.g;
+ vec4 a = vec4(t.g, k, t.r, lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..372d722cf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ float k = m.r;
+ vec2 n = m.gb;
+ vec4 a = vec4(k, n.r, n.g, al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..b497ab3cb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_gb_r_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec2 t = m.gb;
+ float k = m.r;
+ vec4 a = vec4(k, t.r, t.g, lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_frag.frag
new file mode 100644
index 0000000000..0e236aadd4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ vec3 t = m.grb;
+ vec4 a = vec4(t.g, t.r, t.b ,al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_vert.vert
new file mode 100644
index 0000000000..a1ad9dae56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_grb_1vec3_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec3 t = m.grb;
+ vec4 a = vec4(t.g, t.r, t.b, lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..3d207a26ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ float k = m.t;
+ vec2 n = m.ps;
+ vec4 a = vec4(n.t, k, n.s, al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..3f17f0602b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_ps_t_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec2 t = m.ps;
+ float k = m.t;
+ vec4 a = vec4(t.t, k, t.s, lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_frag.frag
new file mode 100644
index 0000000000..308bbad045
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ vec3 t = m.pts;
+ vec4 a = vec4(t.p, t.t, t.s ,al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_vert.vert
new file mode 100644
index 0000000000..6d1b1f1bf1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_pts_1vec3_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec3 t = m.pts;
+ vec4 a = vec4(t.p, t.t, t.s, lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..a249894a26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ float k = m.g;
+ vec2 n = m.rb;
+ vec4 a = vec4(n.r, k, n.g, al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..95d3b9afd8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rb_g_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec2 t = m.rb;
+ float k = m.g;
+ vec4 a = vec4(t.r, k, t.g, lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..8451056b91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ float k = m.b;
+ vec2 n = m.rg;
+ vec4 a = vec4(n, k, al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..2a5386ad67
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rg_b_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec2 t = m.rg;
+ float k = m.b;
+ vec4 a = vec4(t, k, lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_frag.frag
new file mode 100644
index 0000000000..10df1fe982
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ vec4 a = vec4(m.rgb,al.a);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_vert.vert
new file mode 100644
index 0000000000..6b8ab108d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_rgb_1vec3_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ vec4 a = vec4(m.rgb,lightloc.a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..1a7a95d56d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ float k = m.t;
+ vec2 n = m.sp;
+ vec4 a = vec4(n.s, k, n.t, al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..5972e92745
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_sp_t_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec2 t = m.sp;
+ float k = m.t;
+ vec4 a = vec4(t.s, k, t.t, lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..e9259b0daf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ float k = m.p;
+ vec2 n = m.st;
+ vec4 a = vec4(n, k, al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..99ff032ee7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_st_p_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec2 t = m.st;
+ float k = m.p;
+ vec4 a = vec4(t, k, lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_frag.frag
new file mode 100644
index 0000000000..e0010e2ee1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ vec4 a = vec4(m.stp,al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_vert.vert
new file mode 100644
index 0000000000..d73986f5c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_stp_1vec3_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec4 a = vec4(m.stp,lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..8ffdb56fd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ float k = m.s;
+ vec2 n = m.tp;
+ vec4 a = vec4(k, n.s, n.t, al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..97f3814bbf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tp_s_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec2 t = m.tp;
+ float k = m.s;
+ vec4 a = vec4(k, t.s, t.t, lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_frag.frag
new file mode 100644
index 0000000000..6a72e98da7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ vec3 t = m.tsp;
+ vec4 a = vec4(t.t, t.s, t.p ,al.q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_vert.vert
new file mode 100644
index 0000000000..010fd37584
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_tsp_1vec3_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ vec3 t = m.tsp;
+ vec4 a = vec4(t.t, t.s, t.p, lightloc.q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..09f2e91c54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ float k = m.z;
+ vec2 n = m.xy;
+ vec4 a = vec4(n, k, al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..9f55aa7865
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xy_z_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec2 t = m.xy;
+ float k = m.z;
+ vec4 a = vec4(t, k, lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_frag.frag
new file mode 100644
index 0000000000..f712b9115c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ vec4 a = vec4(m.xyz,al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_vert.vert
new file mode 100644
index 0000000000..009b1b1279
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xyz_1vec3_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec4 a = vec4(m.xyz,lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..1ad1201999
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ float k = m.y;
+ vec2 n = m.xz;
+ vec4 a = vec4(n.x, k, n.y, al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..c316eb2883
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_xz_y_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec2 t = m.xz;
+ float k = m.y;
+ vec4 a = vec4(t.x, k, t.y, lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_frag.frag
new file mode 100644
index 0000000000..8f0c4c8909
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ vec3 t = m.yxz;
+ vec4 a = vec4(t.y, t.x, t.z ,al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_vert.vert
new file mode 100644
index 0000000000..0e821301e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yxz_1vec3_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec3 t = m.yxz;
+ vec4 a = vec4(t.y, t.x, t.z, lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..92a36a3c7c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ float k = m.x;
+ vec2 n = m.yz;
+ vec4 a = vec4(k, n.x, n.y, al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..63cffb9f00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_yz_x_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec2 t = m.yz;
+ float k = m.x;
+ vec4 a = vec4(k, t.x, t.y, lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_frag.frag
new file mode 100644
index 0000000000..2da5e7a29d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_frag.frag
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ float k = m.y;
+ vec2 n = m.zx;
+ vec4 a = vec4(n.y, k, n.x, al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_vert.vert
new file mode 100644
index 0000000000..d3ffff954b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zx_y_1vec2_1float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec2 t = m.zx;
+ float k = m.y;
+ vec4 a = vec4(t.y, k, t.x, lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_frag.frag
new file mode 100644
index 0000000000..ecb1a826a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ vec3 t = m.zyx;
+ vec4 a = vec4(t.z, t.y, t.x ,al.w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_vert.vert
new file mode 100644
index 0000000000..b99908f3d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec3_zyx_1vec3_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ vec3 t = m.zyx;
+ vec4 a = vec4(t.z, t.y, t.x, lightloc.w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_frag.frag
new file mode 100644
index 0000000000..ef69029678
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.ar;
+ vec2 n = al.bg;
+ vec4 a = vec4(m.g, n.g, n.r, m.r);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_vert.vert
new file mode 100644
index 0000000000..61640a32ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ar_bg_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.ar;
+ vec2 n = lightloc.bg;
+ vec4 a = vec4(m.g, n.g, n.r, m.r);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..166b0e64c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.arb;
+ float g = al.g;
+ vec4 a = vec4(m.g, g, m.b, m.r);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..a89418a204
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arb_g_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.arb;
+ float g = lightloc.g;
+ vec4 a = vec4(m.g, g, m.b, m.r);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_frag.frag
new file mode 100644
index 0000000000..8cbced527f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.arbg;
+ vec4 a = vec4(m.g, m.a, m.b, m.r);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_vert.vert
new file mode 100644
index 0000000000..1da338eb80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_arbg_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.arbg;
+ vec4 a = vec4(m.g, m.a, m.b, m.r);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..9c6ddb8d86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.bar;
+ float g = al.g;
+ vec4 a = vec4(m.b, g, m.r, m.g);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..5d319a6932
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_bar_g_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.bar;
+ float g = lightloc.g;
+ vec4 a = vec4(m.b, g, m.r, m.g);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_frag.frag
new file mode 100644
index 0000000000..c472bb1a20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.barg;
+ vec4 a = vec4(m.b, m.a, m.r, m.g);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_vert.vert
new file mode 100644
index 0000000000..4b9fb8cb3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_barg_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.barg;
+ vec4 a = vec4(m.b, m.a, m.r, m.g);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_frag.frag
new file mode 100644
index 0000000000..684dd7bf2a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.br;
+ vec2 n = al.ag;
+ vec4 a = vec4(m.g, n.g, m.r, n.r);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_vert.vert
new file mode 100644
index 0000000000..759aeebda8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_br_ag_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.br;
+ vec2 n = lightloc.ag;
+ vec4 a = vec4(m.g, n.g, m.r, n.r);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_frag.frag
new file mode 100644
index 0000000000..75300c6d8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.gr;
+ vec2 n = al.ab;
+ vec4 a = vec4(m.g, m.r, n.g, n.r);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_vert.vert
new file mode 100644
index 0000000000..5a329a7213
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gr_ab_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.gr;
+ vec2 n = lightloc.ab;
+ vec4 a = vec4(m.g, m.r, n.g, n.r);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..317a577627
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.gra;
+ float b = al.b;
+ vec4 a = vec4(m.g, m.r, b, m.b);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..43237d1aad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_gra_b_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.gra;
+ float b = lightloc.b;
+ vec4 a = vec4(m.g, m.r, b, m.b);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_frag.frag
new file mode 100644
index 0000000000..7ff712d481
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.grab;
+ vec4 a = vec4(m.g, m.r, m.a, m.b);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_vert.vert
new file mode 100644
index 0000000000..07bf632f3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_grab_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.grab;
+ vec4 a = vec4(m.g, m.r, m.a, m.b);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..6ffc5c8a36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.pqs;
+ float t = al.t;
+ vec4 a = vec4(m.p, t, m.s, m.t);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..52219ee965
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqs_t_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.pqs;
+ float t = lightloc.t;
+ vec4 a = vec4(m.p, t, m.s, m.t);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_frag.frag
new file mode 100644
index 0000000000..47671ad158
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.pqst;
+ vec4 a = vec4(m.p, m.q, m.s, m.t);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_vert.vert
new file mode 100644
index 0000000000..083ada8e3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_pqst_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.pqst;
+ vec4 a = vec4(m.p, m.q, m.s, m.t);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_frag.frag
new file mode 100644
index 0000000000..437ff91f76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.ps;
+ vec2 n = al.qt;
+ vec4 a = vec4(m.t, n.t, m.s, n.s);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_vert.vert
new file mode 100644
index 0000000000..4661630a8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ps_qt_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.ps;
+ vec2 n = lightloc.qt;
+ vec4 a = vec4(m.t, n.t, m.s, n.s);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_frag.frag
new file mode 100644
index 0000000000..12a1b7059b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.qs;
+ vec2 n = al.pt;
+ vec4 a = vec4(m.t, n.t, n.s, m.s);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_vert.vert
new file mode 100644
index 0000000000..d6431ecc7c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qs_pt_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.qs;
+ vec2 n = lightloc.pt;
+ vec4 a = vec4(m.t, n.t, n.s, m.s);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..95ca6a056f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.qsp;
+ float t = al.t;
+ vec4 a = vec4(m.t, t, m.p, m.s);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..e49030cbfb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qsp_t_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.qsp;
+ float t = lightloc.t;
+ vec4 a = vec4(m.t, t, m.p, m.s);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_frag.frag
new file mode 100644
index 0000000000..7573162261
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.qspt;
+ vec4 a = vec4(m.t, m.q, m.p, m.s);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_vert.vert
new file mode 100644
index 0000000000..7f6c261151
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_qspt_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.qspt;
+ vec4 a = vec4(m.t, m.q, m.p, m.s);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_frag.frag
new file mode 100644
index 0000000000..52fe031673
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ float r = al.r;
+ float g = al.g;
+ float b = al.b;
+ float a = al.a;
+ vec4 m = vec4(r,g,b,a);
+ gl_FragColor = m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_vert.vert
new file mode 100644
index 0000000000..14c4866968
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_r_g_b_a_4float_vert.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ float r = lightloc.r;
+ float g = lightloc.g;
+ float b = lightloc.b;
+ float a = lightloc.a;
+ vec4 m = vec4(r, g, b, a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_frag.frag
new file mode 100644
index 0000000000..4118f7ddf1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.rg;
+ vec2 n = al.ba;
+ vec4 a = vec4(m,n);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_vert.vert
new file mode 100644
index 0000000000..ac954debff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rg_ba_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.rg;
+ vec2 n = lightloc.ba;
+ vec4 a = vec4(m,n);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..92622af66a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.rgb;
+ float a = al.a;
+ vec4 b = vec4(m, a);
+ gl_FragColor = b;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..c55fb9fc87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgb_a_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.rgb;
+ float a = lightloc.a;
+ vec4 b = vec4(m, a);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * b;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_frag.frag
new file mode 100644
index 0000000000..1ef518f324
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.rgba;
+ gl_FragColor = m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_vert.vert
new file mode 100644
index 0000000000..2242839919
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_rgba_1vec4_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.rgba;
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_frag.frag
new file mode 100644
index 0000000000..78819c9054
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ float s = al.s;
+ float t = al.t;
+ float p = al.p;
+ float q = al.q;
+ vec4 m = vec4(s,t,p,q);
+ gl_FragColor = m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_vert.vert
new file mode 100644
index 0000000000..4f935e09b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_s_t_p_q_4float_vert.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ float s = lightloc.s;
+ float t = lightloc.t;
+ float p = lightloc.p;
+ float q = lightloc.q;
+ vec4 m = vec4(s, t, p, q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_frag.frag
new file mode 100644
index 0000000000..da5f862976
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.st;
+ vec2 n = al.pq;
+ vec4 a = vec4(m,n);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_vert.vert
new file mode 100644
index 0000000000..2209220d51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_st_pq_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.st;
+ vec2 n = lightloc.pq;
+ vec4 a = vec4(m,n);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..34b906d56b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.stp;
+ float q = al.q;
+ vec4 a = vec4(m, q);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..16f955e55a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stp_q_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.stp;
+ float q = lightloc.q;
+ vec4 a = vec4(m, q);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_frag.frag
new file mode 100644
index 0000000000..593d052c89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.stpq;
+ gl_FragColor = m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_vert.vert
new file mode 100644
index 0000000000..ff907fdd75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_stpq_1vec4_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.stpq;
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_frag.frag
new file mode 100644
index 0000000000..ad542e6998
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.ts;
+ vec2 n = al.qp;
+ vec4 a = vec4(m.t, m.s, n.t, n.s);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_vert.vert
new file mode 100644
index 0000000000..fc3fa55523
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_ts_qp_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.ts;
+ vec2 n = lightloc.qp;
+ vec4 a = vec4(m.t, m.s, n.t, n.s);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..54e551dd13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.tsq;
+ float p = al.p;
+ vec4 a = vec4(m.t, m.s, p, m.p);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..5a0cf0e953
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsq_p_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.tsq;
+ float p = lightloc.p;
+ vec4 a = vec4(m.t, m.s, p, m.p);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_frag.frag
new file mode 100644
index 0000000000..f5bf88f717
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.tsqp;
+ vec4 a = vec4(m.t, m.s, m.q, m.p);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_vert.vert
new file mode 100644
index 0000000000..45c526341e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_tsqp_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.tsqp;
+ vec4 a = vec4(m.t, m.s, m.q, m.p);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_frag.frag
new file mode 100644
index 0000000000..faa8c0fbf2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.wx;
+ vec2 n = al.zy;
+ vec4 a = vec4(m.y, n.y, n.x, m.x);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_vert.vert
new file mode 100644
index 0000000000..494eaf153d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wx_zy_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.wx;
+ vec2 n = lightloc.zy;
+ vec4 a = vec4(m.y, n.y, n.x, m.x);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..bafad02b8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.wxz;
+ float y = al.y;
+ vec4 a = vec4(m.y, y, m.z, m.x);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..084f3d4a1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxz_y_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.wxz;
+ float y = lightloc.y;
+ vec4 a = vec4(m.y, y, m.z, m.x);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_frag.frag
new file mode 100644
index 0000000000..abaaa1aa77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.wxzy;
+ vec4 a = vec4(m.y, m.w, m.z, m.x);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_vert.vert
new file mode 100644
index 0000000000..8f2b037b06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_wxzy_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.wxzy;
+ vec4 a = vec4(m.y, m.w, m.z, m.x);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_frag.frag
new file mode 100644
index 0000000000..994da3ce0a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ float x = al.x;
+ float y = al.y;
+ float z = al.z;
+ float w = al.w;
+ vec4 m = vec4(x,y,z,w);
+ gl_FragColor = m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_vert.vert
new file mode 100644
index 0000000000..5e7f41e394
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_x_y_z_w_4float_vert.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ float x = lightloc.x;
+ float y = lightloc.y;
+ float z = lightloc.z;
+ float w = lightloc.w;
+ vec4 m = vec4(x, y, z, w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_frag.frag
new file mode 100644
index 0000000000..711da4cf75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.xy;
+ vec2 n = al.zw;
+ vec4 a = vec4(m,n);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_vert.vert
new file mode 100644
index 0000000000..0748e4cb54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xy_zw_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.xy;
+ vec2 n = lightloc.zw;
+ vec4 a = vec4(m,n);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..99f089d135
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.xyz;
+ float w = al.w;
+ vec4 a = vec4(m, w);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..2a25017092
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyz_w_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.xyz;
+ float w = lightloc.w;
+ vec4 a = vec4(m, w);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_frag.frag
new file mode 100644
index 0000000000..6dff1ea7f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_frag.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.xyzw;
+ gl_FragColor = m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_vert.vert
new file mode 100644
index 0000000000..c0b6cdd40d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_xyzw_1vec4_vert.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.xyzw;
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * m;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_frag.frag
new file mode 100644
index 0000000000..f95d684285
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.yx;
+ vec2 n = al.wz;
+ vec4 a = vec4(m.y, m.x, n.y, n.x);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_vert.vert
new file mode 100644
index 0000000000..1267691845
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yx_wz_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.yx;
+ vec2 n = lightloc.wz;
+ vec4 a = vec4(m.y, m.x, n.y, n.x);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..82aba37d4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.yxw;
+ float z = al.z;
+ vec4 a = vec4(m.y, m.x, z, m.z);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..c524df25fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxw_z_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.yxw;
+ float z = lightloc.z;
+ vec4 a = vec4(m.y, m.x, z, m.z);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_frag.frag
new file mode 100644
index 0000000000..14310197ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.yxwz;
+ vec4 a = vec4(m.y, m.x, m.w, m.z);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_vert.vert
new file mode 100644
index 0000000000..067db03781
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_yxwz_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.yxwz;
+ vec4 a = vec4(m.y, m.x, m.w, m.z);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_frag.frag
new file mode 100644
index 0000000000..f29772e7b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec3 m = al.zwx;
+ float y = al.y;
+ vec4 a = vec4(m.z, y, m.x, m.y);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_vert.vert
new file mode 100644
index 0000000000..246b73233a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwx_y_1vec3_1float_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec3 m = lightloc.zwx;
+ float y = lightloc.y;
+ vec4 a = vec4(m.z, y, m.x, m.y);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_frag.frag
new file mode 100644
index 0000000000..ac70137458
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec4 m = al.zwxy;
+ vec4 a = vec4(m.z, m.w, m.x, m.y);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_vert.vert
new file mode 100644
index 0000000000..dd3dc55b69
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zwxy_1vec4_vert.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec4 m = lightloc.zwxy;
+ vec4 a = vec4(m.z, m.w, m.x, m.y);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_frag.frag
new file mode 100644
index 0000000000..ea23356bd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main (void)
+{
+ vec4 al = color;
+ vec2 m = al.zx;
+ vec2 n = al.wy;
+ vec4 a = vec4(m.y, n.y, m.x, n.x);
+ gl_FragColor = a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_vert.vert
new file mode 100644
index 0000000000..ffad811987
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/swizzlers/vec4_zx_wy_2vec2_vert.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 lightloc = gtf_Vertex;
+ vec2 m = lightloc.zx;
+ vec2 n = lightloc.wy;
+ vec4 a = vec4(m.y, n.y, m.x, n.x);
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * a;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/input.run.txt
new file mode 100644
index 0000000000..443a00f700
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+tan_001_to_006.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_001_to_006.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_001_to_006.html
new file mode 100644
index 0000000000..25451bfc5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_001_to_006.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: tan_001_to_006.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "tan_float_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "tan_float_frag_xvary.frag"
+ },
+ "name": "tan_float_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "tan_vec2_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "tan_vec2_frag_xvary.frag"
+ },
+ "name": "tan_vec2_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "tan_vec3_frag_xvary_ref.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "tan_vec3_frag_xvary.frag"
+ },
+ "name": "tan_vec3_frag_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "tan_float_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "tan_float_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "tan_float_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "tan_vec2_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "tan_vec2_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "tan_vec2_vert_xvary.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "tan_vec3_vert_xvary_ref.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": "grid",
+ "testProgram": {
+ "vertexShader": "tan_vec3_vert_xvary.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "tan_vec3_vert_xvary.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary.frag
new file mode 100644
index 0000000000..6235d05d08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 0.5 * M_PI * 2.0 * (color.r - 0.5);
+ float o;
+
+ if(abs(c) < 0.5) // -45..45
+ o = 0.5 * tan(c) + 0.5;
+ else // 45..90, -45..-90
+ o = 0.5 / tan(c) + 0.5;
+ gl_FragColor = vec4(o, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary_ref.frag
new file mode 100644
index 0000000000..308e399685
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_frag_xvary_ref.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 0.5 * M_PI * 2.0 * (color.r - 0.5);
+ float o;
+ if(abs(c) < 0.5) // -45..45
+ o = 0.5 * (sin(c) / cos(c)) + 0.5;
+ else // 45..90, -45..-90
+ o = 0.5 * (cos(c) / sin(c)) + 0.5;
+ gl_FragColor = vec4(o, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary.vert
new file mode 100644
index 0000000000..3a2bfc0968
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 0.5 * M_PI * 2.0 * (gtf_Color.r - 0.5);
+ float o;
+
+ if(abs(c) < 0.5) // -45..45
+ o = 0.5 * tan(c) + 0.5;
+ else // 45..90, -45..-90
+ o = 0.5 / tan(c) + 0.5;
+ color = vec4(o, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary_ref.vert
new file mode 100644
index 0000000000..074502f61d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_float_vert_xvary_ref.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float c = 0.5 * M_PI * 2.0 * (gtf_Color.r - 0.5);
+ float o;
+ if(abs(c) < 0.5) // -45..45
+ o = 0.5 * (sin(c) / cos(c)) + 0.5;
+ else // 45..90, -45..-90
+ o = 0.5 * (cos(c) / sin(c)) + 0.5;
+ color = vec4(o, 0.0, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary.frag
new file mode 100644
index 0000000000..523a66208b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 0.5 * M_PI * 2.0 * (color.rg - 0.5);
+ vec2 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * tan(c.r) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 / tan(c.r) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * tan(c.g) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 / tan(c.g) + 0.5;
+
+ gl_FragColor = vec4(o, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary_ref.frag
new file mode 100644
index 0000000000..5cf357da34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_frag_xvary_ref.frag
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 0.5 * M_PI * 2.0 * (color.rg - 0.5);
+ vec2 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * (sin(c.r) / cos(c.r)) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 * (cos(c.r) / sin(c.r)) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * (sin(c.g) / cos(c.g)) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 * (cos(c.g) / sin(c.g)) + 0.5;
+
+ gl_FragColor = vec4(o, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary.vert
new file mode 100644
index 0000000000..7c04171302
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary.vert
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 0.5 * M_PI * 2.0 * (gtf_Color.rg - 0.5);
+ vec2 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * tan(c.r) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 / tan(c.r) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * tan(c.g) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 / tan(c.g) + 0.5;
+
+ color = vec4(o, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary_ref.vert
new file mode 100644
index 0000000000..01b0079917
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec2_vert_xvary_ref.vert
@@ -0,0 +1,31 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec2 c = 0.5 * M_PI * 2.0 * (gtf_Color.rg - 0.5);
+ vec2 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * (sin(c.r) / cos(c.r)) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 * (cos(c.r) / sin(c.r)) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * (sin(c.g) / cos(c.g)) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 * (cos(c.g) / sin(c.g)) + 0.5;
+
+ color = vec4(o, 0.0, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary.frag
new file mode 100644
index 0000000000..4f1c5cdad7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary.frag
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 0.5 * M_PI * 2.0 * (color.rgb - 0.5);
+ vec3 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * tan(c.r) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 / tan(c.r) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * tan(c.g) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 / tan(c.g) + 0.5;
+
+ if(abs(c.b) < 0.5) // -45..45
+ o.b = 0.5 * tan(c.b) + 0.5;
+ else // 45..90, -45..-90
+ o.b = 0.5 / tan(c.b) + 0.5;
+
+ gl_FragColor = vec4(o, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary_ref.frag
new file mode 100644
index 0000000000..4e3f7bd792
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_frag_xvary_ref.frag
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 0.5 * M_PI * 2.0 * (color.rgb - 0.5);
+ vec3 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * (sin(c.r) / cos(c.r)) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 * (cos(c.r) / sin(c.r)) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * (sin(c.g) / cos(c.g)) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 * (cos(c.g) / sin(c.g)) + 0.5;
+
+ if(abs(c.b) < 0.5) // -45..45
+ o.b = 0.5 * (sin(c.b) / cos(c.b)) + 0.5;
+ else // 45..90, -45..-90
+ o.b = 0.5 * (cos(c.b) / sin(c.b)) + 0.5;
+
+ gl_FragColor = vec4(o, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary.vert
new file mode 100644
index 0000000000..0fdecde16d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary.vert
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 0.5 * M_PI * 2.0 * (gtf_Color.rgb - 0.5);
+ vec3 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * tan(c.r) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 / tan(c.r) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * tan(c.g) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 / tan(c.g) + 0.5;
+
+ if(abs(c.b) < 0.5) // -45..45
+ o.b = 0.5 * tan(c.b) + 0.5;
+ else // 45..90, -45..-90
+ o.b = 0.5 / tan(c.b) + 0.5;
+
+ color = vec4(o, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary_ref.vert
new file mode 100644
index 0000000000..8f38b30f87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/tan/tan_vec3_vert_xvary_ref.vert
@@ -0,0 +1,36 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ vec3 c = 0.5 * M_PI * 2.0 * (gtf_Color.rgb - 0.5);
+ vec3 o;
+ if(abs(c.r) < 0.5) // -45..45
+ o.r = 0.5 * (sin(c.r) / cos(c.r)) + 0.5;
+ else // 45..90, -45..-90
+ o.r = 0.5 * (cos(c.r) / sin(c.r)) + 0.5;
+
+ if(abs(c.g) < 0.5) // -45..45
+ o.g = 0.5 * (sin(c.g) / cos(c.g)) + 0.5;
+ else // 45..90, -45..-90
+ o.g = 0.5 * (cos(c.g) / sin(c.g)) + 0.5;
+
+ if(abs(c.b) < 0.5) // -45..45
+ o.b = 0.5 * (sin(c.b) / cos(c.b)) + 0.5;
+ else // 45..90, -45..-90
+ o.b = 0.5 * (cos(c.b) / sin(c.b)) + 0.5;
+
+ color = vec4(o, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_frag.frag
new file mode 100644
index 0000000000..2cdd4c00bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ bvec4 a = bvec4(0, 23, 0.0, 23.0);
+ float gray;
+ if( (a[0] == false) && (a[1] == true) && (a[2] == false) && (a[3] == true) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_vert.vert
new file mode 100644
index 0000000000..01c1e9e9de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/bvec4_2int_2float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ bvec4 a = bvec4(0, 23, 0.0, 23.0);
+ float gray;
+ if( (a[0] == false) && (a[1] == true) && (a[2] == false) && (a[3] == true) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/input.run.txt
new file mode 100644
index 0000000000..e5ba07f12c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/input.run.txt
@@ -0,0 +1,4 @@
+# this file is auto-generated. DO NOT EDIT.
+vec_001_to_008.html
+vec_009_to_016.html
+vec_017_to_018.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_frag.frag
new file mode 100644
index 0000000000..6bbb90cf26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ ivec3 a = ivec3(20, 13, 17);
+ float gray;
+ if( (a[0] == 20) && (a[1] == 13) && (a[2] == 17) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_vert.vert
new file mode 100644
index 0000000000..b0000f85f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/ivec3_3int_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ ivec3 a = ivec3(20, 13, 17);
+ float gray;
+ if( (a[0] == 20) && (a[1] == 13) && (a[2] == 17) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_frag.frag
new file mode 100644
index 0000000000..34aa150a83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 a = vec2(13.0,53.0);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_vert.vert
new file mode 100644
index 0000000000..44080bf8d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_2float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 a = vec2(13.0,53.0);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_frag.frag
new file mode 100644
index 0000000000..ef702ec599
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 b = vec3(13.0, 53.0, 139.0);
+ vec2 a = vec2(b);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_vert.vert
new file mode 100644
index 0000000000..403e573141
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec2_vec3_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 b = vec3(13.0, 53.0, 139.0);
+ vec2 a = vec2(b);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_frag.frag
new file mode 100644
index 0000000000..455d116a7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 b = vec2(53.0, 139.0);
+ vec3 a = vec3(13.0, b);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_vert.vert
new file mode 100644
index 0000000000..7aa19d0c9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_float_vec2_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 b = vec2(53.0, 139.0);
+ vec3 a = vec3(13.0, b);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_frag.frag
new file mode 100644
index 0000000000..b6efa60724
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec2 b = vec2(13.0, 53.0);
+ vec3 a = vec3(b, 139.0);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_vert.vert
new file mode 100644
index 0000000000..ecdbf1d919
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec2_float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec2 b = vec2(13.0, 53.0);
+ vec3 a = vec3(b,139.0);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_frag.frag
new file mode 100644
index 0000000000..21e072d5fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec4 b = vec4(13.0, 53.0, 139.0, 217.0);
+ vec3 a = vec3(b);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_vert.vert
new file mode 100644
index 0000000000..1123d6d4fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec3_vec4_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 b = vec4(13.0, 53.0, 139.0, 217.0);
+ vec3 a = vec3(b);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_frag.frag
new file mode 100644
index 0000000000..f593564381
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ ivec4 init = ivec4(2,3,5,9);
+ vec4 a = vec4(init);
+ float gray;
+ if( (a[0] == 2.0) && (a[1] == 3.0) && (a[2] == 5.0) && (a[3] == 9.0) )
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_vert.vert
new file mode 100644
index 0000000000..e556f398d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_ivec4_vert.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ ivec4 init = ivec4(2,3,5,9);
+ vec4 a = vec4(init);
+ float gray;
+ if( (a[0] == 2.0) && (a[1] == 3.0) && (a[2] == 5.0) && (a[3] == 9.0) )
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_frag.frag
new file mode 100644
index 0000000000..9ab9f585ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_frag.frag
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ vec3 b = vec3(13.0, 53.0, 139.0);
+ vec4 a = vec4(b, 217.0);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) && (a[3] == 217.0))
+ gray=1.0;
+ else gray=0.0;
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_vert.vert
new file mode 100644
index 0000000000..f11b422a51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec4_vec3_float_vert.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ vec3 b = vec3(13.0, 53.0, 139.0);
+ vec4 a = vec4(b, 217.0);
+ float gray;
+ if( (a[0] == 13.0) && (a[1] == 53.0) && (a[2] == 139.0) && (a[3] == 217.0))
+ gray=1.0;
+ else gray=0.0;
+ color = vec4(gray, gray, gray, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_001_to_008.html
new file mode 100644
index 0000000000..251efd5e84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_001_to_008.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: vec_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec2_2float_frag.frag"
+ },
+ "name": "vec2_2float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec2_2float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec2_2float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_ivec4_frag.frag"
+ },
+ "name": "vec4_ivec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_ivec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_ivec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "ivec3_3int_frag.frag"
+ },
+ "name": "ivec3_3int_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "ivec3_3int_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "ivec3_3int_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "bvec4_2int_2float_frag.frag"
+ },
+ "name": "bvec4_2int_2float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "bvec4_2int_2float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "bvec4_2int_2float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_009_to_016.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_009_to_016.html
new file mode 100644
index 0000000000..b846cfb195
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_009_to_016.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: vec_009_to_016.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec2_vec3_frag.frag"
+ },
+ "name": "vec2_vec3_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec2_vec3_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec2_vec3_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_vec4_frag.frag"
+ },
+ "name": "vec3_vec4_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3_vec4_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_vec4_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_vec2_float_frag.frag"
+ },
+ "name": "vec3_vec2_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3_vec2_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_vec2_float_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec3_float_vec2_frag.frag"
+ },
+ "name": "vec3_float_vec2_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3_float_vec2_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3_float_vec2_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_017_to_018.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_017_to_018.html
new file mode 100644
index 0000000000..f82639522d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec/vec_017_to_018.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: vec_017_to_018.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "vec4_vec3_float_frag.frag"
+ },
+ "name": "vec4_vec3_float_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec4_vec3_float_vert.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec4_vec3_float_vert.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/input.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/input.run.txt
new file mode 100644
index 0000000000..1d1f9189d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/input.run.txt
@@ -0,0 +1,2 @@
+# this file is auto-generated. DO NOT EDIT.
+vec3_001_to_008.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3_001_to_008.html b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3_001_to_008.html
new file mode 100644
index 0000000000..6c4c642388
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3_001_to_008.html
@@ -0,0 +1,313 @@
+<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: vec3_001_to_008.html</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css" />
+<link rel="stylesheet" href="../../../../resources/ogles-tests.css" />
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../ogles-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run({
+ "tests": [
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 2,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.0,
+ 0.75,
+ 0.25,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "vec3array_frag.frag"
+ },
+ "name": "vec3array_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3single_vert.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 1,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.5
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3single_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.5,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3arrayindirect_vert.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 2,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.0,
+ 0.75,
+ 0.25,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3arrayindirect_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.5,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3arraydirect_vert.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 2,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.0,
+ 0.75,
+ 0.25,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3arraydirect_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "fragmentShader": "../default/default.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "vec3array_vert.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 2,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.0,
+ 0.75,
+ 0.25,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/default.frag"
+ },
+ "name": "vec3array_vert.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 1,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.5
+ ]
+ }
+ },
+ "fragmentShader": "vec3single_frag.frag"
+ },
+ "name": "vec3single_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.5,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 2,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.0,
+ 0.75,
+ 0.25,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "vec3arrayindirect_frag.frag"
+ },
+ "name": "vec3arrayindirect_frag.test.html",
+ "pattern": "compare"
+ },
+ {
+ "referenceProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "result": {
+ "count": 1,
+ "type": "uniform4fv",
+ "value": [
+ 0.5,
+ 0.5,
+ 0.5,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "../default/expected.frag"
+ },
+ "model": null,
+ "testProgram": {
+ "vertexShader": "../default/default.vert",
+ "uniforms": {
+ "lightPosition": {
+ "count": 2,
+ "type": "uniform3fv",
+ "value": [
+ 0.25,
+ 0.75,
+ 0.0,
+ 0.75,
+ 0.25,
+ 1.0
+ ]
+ }
+ },
+ "fragmentShader": "vec3arraydirect_frag.frag"
+ },
+ "name": "vec3arraydirect_frag.test.html",
+ "pattern": "compare"
+ }
+ ]
+});
+var successfullyParsed = true;
+</script>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_frag.frag
new file mode 100644
index 0000000000..0b13eee69d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_frag.frag
@@ -0,0 +1,32 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// vec3array_frag.frag: Simple Fragment shader using vec3 to get colors.
+//
+//
+
+varying vec4 color;
+
+uniform vec3 lightPosition[2];
+
+void main(void)
+{
+ vec3 v[2];
+
+ v[1] = vec3(color.r, color.g, color.b);
+
+
+ v[0] = lightPosition[1];
+
+
+ gl_FragColor = vec4(v[1] + v[1], 0.0)/2.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_vert.vert
new file mode 100644
index 0000000000..91651bccee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3array_vert.vert
@@ -0,0 +1,30 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// vec3array_vert.vert: Simple vertex shader using vec3 to get colors.
+//
+//
+
+varying vec4 color;
+uniform vec3 lightPosition[2];
+
+void main(void)
+{
+ vec3 v[2];
+
+ v[1] = vec3(gtf_Color.r, gtf_Color.g, gtf_Color.b);
+
+ v[0] = lightPosition[1];
+
+ color = vec4(v[1] + v[1], 0.0)/2.0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_frag.frag
new file mode 100644
index 0000000000..042af3233d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// vec3arraydirect_frag.frag: Fragment shader solid color
+//
+//
+//
+
+uniform vec3 lightPosition[2];
+varying vec4 color;
+
+void main(void)
+{
+ gl_FragColor = vec4(lightPosition[0] + lightPosition[1], 0.0) * 0.5;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_vert.vert
new file mode 100644
index 0000000000..a68009f5e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arraydirect_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// vec3arraydirect_vert.vert: Vertex shader solid color
+//
+//
+//
+
+uniform vec3 lightPosition[2];
+varying vec4 color;
+
+void main(void)
+{
+
+ color = vec4(lightPosition[0] + lightPosition[1], 0.0) * 0.5;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_frag.frag
new file mode 100644
index 0000000000..a1252a9253
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_frag.frag
@@ -0,0 +1,38 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// vec3arrayindirect_frag.frag: Fragment shader solid color
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform vec3 lightPosition[2];
+varying vec4 color;
+
+void main(void)
+{
+ int i;
+
+ gl_FragColor = vec4(0.0);
+
+ /*
+ // No indirect indexing in fragment shaders
+ for (i = 0; i < 2; i++)
+ {
+ gl_FragColor += vec4(lightPosition[i], 0.0);
+ }
+ */
+ gl_FragColor += vec4(lightPosition[0], 0.0);
+ gl_FragColor += vec4(lightPosition[1], 0.0);
+
+ gl_FragColor /= 2.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_vert.vert
new file mode 100644
index 0000000000..8da406319f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3arrayindirect_vert.vert
@@ -0,0 +1,34 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// vec3arrayindirect_vert.vert: Vertex shader solid color
+// The vec3 values are determined at runtime.
+//
+//
+
+uniform vec3 lightPosition[2];
+varying vec4 color;
+
+void main(void)
+{
+ color = vec4(0.0);
+
+ for (int i = 0; i < 2; i++)
+ {
+ color += vec4(lightPosition[i], 0.0);
+ }
+
+ color /= 2.0;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_frag.frag
new file mode 100644
index 0000000000..73148c40ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_frag.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// vec3Matrix_frag.frag: Fragment shader solid color
+//
+//
+//
+
+uniform vec3 lightPosition;
+varying vec4 color;
+
+void main(void)
+{
+ gl_FragColor = vec4(lightPosition, 0.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_vert.vert
new file mode 100644
index 0000000000..386aaacde5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL/vec3/vec3single_vert.vert
@@ -0,0 +1,28 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+//
+// vec3Matrix_vert.vert: Vertex shader solid color
+//
+//
+//
+
+uniform vec3 lightPosition;
+varying vec4 color;
+
+void main(void)
+{
+
+ color = vec4(lightPosition, 0.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.frag
new file mode 100644
index 0000000000..ad6b60241a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+varying vec4 color;
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ gl_FragColor = color * texture2D(gtf_Texture0, gtf_TexCoord[0].xy);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.vert
new file mode 100644
index 0000000000..f16ba31304
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/compressed_paletted_texture/compressed_paletted_texture.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 gtf_TexCoord[1];
+attribute vec4 gtf_MultiTexCoord0;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gtf_TexCoord[0] = gtf_MultiTexCoord0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.frag
new file mode 100644
index 0000000000..4371f9a7fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.frag
@@ -0,0 +1,51 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+// This fragment shader computes an image representation of the derivative of
+// sine. The derivative of sine is cosine. This shader's output is compared to
+// the reference shader that computes an image representation of cosine
+// directly.
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float sine;
+ float cosine;
+
+#ifdef GL_OES_standard_derivatives
+ sine = sin(fract(gl_FragCoord.x / 128.0) * (2.0 * M_PI));
+ cosine = REDUCE_RANGE((128.0 / (2.0 * M_PI)) * dFdx(sine));
+#else
+ cosine = 0.5;
+#endif
+
+ if( gl_FragCoord.x < SAFETY_BOUND )
+ {
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.frag
new file mode 100644
index 0000000000..263b5b7f3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.frag
@@ -0,0 +1,44 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float cosine;
+
+ if( gl_FragCoord.x < SAFETY_BOUND )
+ {
+ // horizontal cosine wave with a period of 128 pixels
+#ifdef GL_OES_standard_derivatives
+ cosine = REDUCE_RANGE(cos(fract(gl_FragCoord.x / 128.0) * (2.0 * M_PI)));
+#else
+ cosine = 0.5;
+#endif
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdx/dFdx_frag_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.frag
new file mode 100644
index 0000000000..6956f59620
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.frag
@@ -0,0 +1,51 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+// This fragment shader computes an image representation of the derivative of
+// sine. The derivative of sine is cosine. This shader's output is compared to
+// the reference shader that computes an image representation of cosine
+// directly.
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float sine;
+ float cosine;
+
+#ifdef GL_OES_standard_derivatives
+ sine = sin(fract(gl_FragCoord.y / 128.0) * (2.0 * M_PI));
+ cosine = REDUCE_RANGE((128.0 / (2.0 * M_PI)) * dFdy(sine));
+#else
+ cosine = 0.5;
+#endif
+
+ if( gl_FragCoord.y < SAFETY_BOUND )
+ {
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.vert
new file mode 100644
index 0000000000..642c65f958
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.frag
new file mode 100644
index 0000000000..bd4555a47a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.frag
@@ -0,0 +1,47 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float cosine;
+
+ if( gl_FragCoord.y < SAFETY_BOUND )
+ {
+ // vertical cosine wave with a period of 128 pixels
+
+#ifdef GL_OES_standard_derivatives
+ cosine = REDUCE_RANGE(cos(fract(gl_FragCoord.y / 128.0) * (2.0 * M_PI)));
+#else
+ cosine = 0.5;
+#endif
+
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.vert
new file mode 100644
index 0000000000..642c65f958
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/dFdy/dFdy_frag_ref.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.frag
new file mode 100644
index 0000000000..48175cd07e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.vert
new file mode 100644
index 0000000000..dc31499b90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.frag
new file mode 100644
index 0000000000..48cd225675
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+varying vec4 color;
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ gl_FragColor = texture2D(gtf_Texture0, gtf_TexCoord[0].xy);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.vert
new file mode 100644
index 0000000000..0088a62147
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/default_shaders/default_textured.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 gtf_TexCoord[1];
+attribute vec4 gtf_MultiTexCoord0;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gtf_TexCoord[0] = gtf_MultiTexCoord0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.frag
new file mode 100644
index 0000000000..ebe8461533
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+
+varying vec2 vertXY;
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float func;
+ float funcfwidth;
+
+#ifdef GL_OES_standard_derivatives
+ // fwidth of average of horizontal and vertical sine waves with periods of 128 pixels, scaled to go from -1 to +1
+ func = 0.5 * (sin(fract(gl_FragCoord.x / 128.0) * (2.0 * M_PI)) + sin(fract(gl_FragCoord.y / 128.0) * (2.0 * M_PI)));
+ funcfwidth = REDUCE_RANGE((128.0 / (2.0 * M_PI)) * fwidth(func));
+#else
+ funcfwidth = 0.5;
+#endif
+
+ if( (gl_FragCoord.x < SAFETY_BOUND) && (gl_FragCoord.y < SAFETY_BOUND) )
+ {
+ gl_FragColor = vec4(funcfwidth, funcfwidth, funcfwidth, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.frag
new file mode 100644
index 0000000000..cc5be437d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+varying vec2 vertXY;
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float cosine;
+ float sine;
+
+#ifdef GL_OES_standard_derivatives
+ // fwidth of horizontal sine wave with a period of 128 pixels, scaled to go from -1 to +1
+ sine = sin(fract(gl_FragCoord.x / 128.0) * (2.0 * M_PI));
+ cosine = REDUCE_RANGE((128.0 / (2.0 * M_PI)) * fwidth(sine));
+#else
+ cosine = 0.5;
+#endif
+
+ if( (gl_FragCoord.x < SAFETY_BOUND) && (gl_FragCoord.y < SAFETY_BOUND) )
+ {
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dx.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.frag
new file mode 100644
index 0000000000..cd555f623e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.frag
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+
+varying vec2 vertXY;
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float cosine;
+ float sine;
+
+#ifdef GL_OES_standard_derivatives
+ // fwidth of vertical sine wave with a period of 128 pixels, scaled to go from -1 to +1
+ sine = sin(fract(gl_FragCoord.y / 128.0) * (2.0 * M_PI));
+ cosine = REDUCE_RANGE((128.0 / (2.0 * M_PI)) * fwidth(sine));
+#else
+ cosine = 0.5;
+#endif
+
+ if( (gl_FragCoord.x < SAFETY_BOUND) && (gl_FragCoord.y < SAFETY_BOUND) )
+ {
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_dy.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.frag
new file mode 100644
index 0000000000..c80b0007d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.frag
@@ -0,0 +1,47 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float func;
+
+ if( (gl_FragCoord.x < SAFETY_BOUND) && (gl_FragCoord.y < SAFETY_BOUND) )
+ {
+ // average of horizontal and vertical abs cosine waves with periods of 128 pixels
+
+#ifdef GL_OES_standard_derivatives
+ func = REDUCE_RANGE(0.5 * (abs(cos(fract(gl_FragCoord.x / 128.0) * (2.0 * M_PI))) + abs(cos(fract(gl_FragCoord.y / 128.0) * (2.0 * M_PI)))));
+#else
+ func = 0.5;
+#endif
+
+ gl_FragColor = vec4(func, func, func, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.frag
new file mode 100644
index 0000000000..045591208e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0]..
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float cosine;
+
+ if( (gl_FragCoord.x < SAFETY_BOUND) && (gl_FragCoord.y < SAFETY_BOUND) )
+ {
+ // horizontal abs cosine wave with a period of 128 pixels
+
+#ifdef GL_OES_standard_derivatives
+ cosine = REDUCE_RANGE(abs(cos(fract(gl_FragCoord.x / 128.0) * (2.0 * M_PI))));
+#else
+ cosine = 0.5;
+#endif
+
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dx.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.frag
new file mode 100644
index 0000000000..d187cf8de0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.frag
@@ -0,0 +1,47 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+#extension GL_OES_standard_derivatives : enable
+precision mediump float;
+#endif
+
+// setting a boundary for cases where screen sizes may exceed the precision
+// of the arithmetic used.
+#define SAFETY_BOUND 500.0
+
+// Macro to scale/bias the range of output. If input is [-1.0, 1.0], maps to [0.5, 1.0].
+// Accounts for precision errors magnified by derivative operation.
+#define REDUCE_RANGE(A) ((A) + 3.0) / 4.0
+
+
+uniform float viewportwidth;
+uniform float viewportheight;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ const float M_PI = 3.14159265358979323846;
+ float cosine;
+
+ if( (gl_FragCoord.x < SAFETY_BOUND) && (gl_FragCoord.y < SAFETY_BOUND) )
+ {
+ // vertical abs cosine wave with a period of 128 pixels
+
+#ifdef GL_OES_standard_derivatives
+ cosine = REDUCE_RANGE(abs(cos(fract(gl_FragCoord.y / 128.0) * (2.0 * M_PI))));
+#else
+ cosine = 0.5;
+#endif
+
+ gl_FragColor = vec4(cosine, cosine, cosine, 1.0);
+ }
+ else discard;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.vert
new file mode 100644
index 0000000000..57ebf867ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2ExtensionTests/fwidth/fwidth_frag_ref_dy.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying vec2 vertXY;
+
+void main (void)
+{
+ vertXY = gtf_Vertex.xy;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.frag
new file mode 100644
index 0000000000..ff3ef82b98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+varying vec4 color;
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ gl_FragColor = texture2D(gtf_Texture0, gtf_TexCoord[0].st, 1.0) * color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.vert
new file mode 100644
index 0000000000..9b8f753d58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects.vert
@@ -0,0 +1,144 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_MultiTexCoord0;
+
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform mat3 gtf_NormalMatrix;
+
+varying vec4 gtf_TexCoord[1];
+varying vec4 color;
+
+vec4 Ambient;
+vec4 Diffuse;
+vec4 Specular;
+
+const vec3 lightPosition = vec3(0.0, 0.0, 1.0);
+const vec3 spotDirection = vec3(0.0, 0.0, -1.0);
+const float spotCutoff = 180.0;
+const float spotExponent = 0.0;
+
+const float lightAttenuationConstant = 1.0;
+const float lightAttenuationLinear = 0.0;
+const float lightAttenuationQuadratic = 0.0;
+
+const vec4 lightAmbient = vec4(0.0, 0.0, 0.0, 0.0);
+vec4 lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
+vec4 lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);
+
+const float materialShininess = 0.0;
+
+const vec4 sceneColor = vec4(0.0, 0.0, 0.0, 0.0);
+
+void spotLight(in int i,
+ in vec3 normal,
+ in vec3 eye,
+ in vec3 ecPosition3
+ )
+{
+ float nDotVP; // normal . light direction
+ float nDotHV; // normal . light half vector
+ float pf; // power factor
+ float spotDot; // cosine of angle between spotlight
+ float spotAttenuation; // spotlight attenuation factor
+ float attenuation; // computed attenuation factor
+ float d; // distance from surface to light source
+ vec3 VP; // direction from surface to light position
+ vec3 halfVector; // direction of maximum highlights
+
+ // Compute vector from surface to light position
+ VP = lightPosition - ecPosition3;
+
+ // Compute distance between surface and light position
+ d = length(VP);
+
+ // Normalize the vector from surface to light position
+ VP = normalize(VP);
+
+ // Compute attenuation
+ attenuation = 1.0 / (lightAttenuationConstant +
+ lightAttenuationLinear * d +
+ lightAttenuationQuadratic * d * d);
+
+ // See if point on surface is inside cone of illumination
+ spotDot = dot(-VP, normalize(spotDirection));
+
+ if (spotDot < cos(radians(spotCutoff)))
+ spotAttenuation = 0.0; // light adds no contribution
+ else
+ spotAttenuation = pow(spotDot, spotExponent);
+
+ // Combine the spotlight and distance attenuation.
+ attenuation *= spotAttenuation;
+
+ halfVector = normalize(VP + eye);
+
+ nDotVP = max(0.0, dot(normal, VP));
+ nDotHV = max(0.0, dot(normal, halfVector));
+
+ if (nDotVP == 0.0)
+ pf = 0.0;
+ else
+ pf = pow(nDotHV, materialShininess);
+
+ Ambient += lightAmbient * attenuation;
+ Diffuse += lightDiffuse * nDotVP * attenuation;
+ Specular += lightSpecular * pf * attenuation;
+}
+
+vec3 fnormal(void)
+{
+ //Compute the normal
+ vec3 normal = gtf_NormalMatrix * gtf_Normal;
+ normal = normalize(normal);
+
+ return normal;
+}
+
+void flight(in vec3 normal, in vec4 ecPosition, float alphaFade)
+{
+ vec3 ecPosition3;
+ vec3 eye;
+
+ ecPosition3 = (vec3 (ecPosition)) / ecPosition.w;
+ eye = vec3 (0.0, 0.0, 1.0);
+
+ // Clear the light intensity accumulators
+ Ambient = vec4 (0.0);
+ Diffuse = vec4 (0.0);
+ Specular = vec4 (0.0);
+
+ //lightSpecular = gtf_Color;
+
+ spotLight(0, normal, eye, ecPosition3);
+
+ color = sceneColor +
+ Ambient * gtf_Color +
+ Diffuse * gtf_Color;
+ color += Specular * gtf_Color;
+ color = clamp( color, 0.0, 1.0 );
+
+ color.a *= alphaFade;
+}
+
+void main (void)
+{
+ vec3 transformedNormal;
+ float alphaFade = 1.0;
+
+ vec4 ecPosition = gtf_Vertex;
+
+ color = gtf_Color;
+ gtf_TexCoord[0] = gtf_MultiTexCoord0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ transformedNormal = fnormal();
+ flight(transformedNormal, ecPosition, alphaFade);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.frag
new file mode 100644
index 0000000000..509c7c1f42
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+uniform sampler2D gtf_Texture1;
+
+varying vec4 color;
+varying vec4 gtf_TexCoord[2];
+
+void main (void)
+{
+ gl_FragColor = texture2D(gtf_Texture0, gtf_TexCoord[0].st, 1.0);
+ gl_FragColor += texture2D(gtf_Texture1, gtf_TexCoord[1].st, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.vert
new file mode 100644
index 0000000000..e98a85ca14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_multitexturing.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_MultiTexCoord0;
+attribute vec4 gtf_MultiTexCoord1;
+
+varying vec4 color;
+varying vec4 gtf_TexCoord[2];
+
+void main (void)
+{
+ color = gtf_Color;
+ gtf_TexCoord[0] = gtf_MultiTexCoord0;
+ gtf_TexCoord[1] = gtf_MultiTexCoord1;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.frag
new file mode 100644
index 0000000000..48175cd07e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.vert
new file mode 100644
index 0000000000..53ffa4bf18
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/buffer_objects/buffer_objects_pointSize.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+attribute float gtf_PointSize;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = gtf_PointSize;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/copy_texture/copy_texture.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/copy_texture/copy_texture.frag
new file mode 100644
index 0000000000..51f59a41a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/copy_texture/copy_texture.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+varying vec4 color;
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ if (gtf_TexCoord[0].s == 1.0)
+ gl_FragColor = color;
+ else
+ gl_FragColor = texture2D(gtf_Texture0, gtf_TexCoord[0].st, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.frag
new file mode 100644
index 0000000000..48175cd07e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.vert
new file mode 100644
index 0000000000..319999cb93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.frag
new file mode 100644
index 0000000000..48cd225675
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D gtf_Texture0;
+varying vec4 color;
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ gl_FragColor = texture2D(gtf_Texture0, gtf_TexCoord[0].xy);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.vert
new file mode 100644
index 0000000000..0088a62147
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/default_shaders/default_textured.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 gtf_TexCoord[1];
+attribute vec4 gtf_MultiTexCoord0;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gtf_TexCoord[0] = gtf_MultiTexCoord0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.frag
new file mode 100644
index 0000000000..55ec693c20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.vert
new file mode 100644
index 0000000000..cdccf706ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse.vert
@@ -0,0 +1,132 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform mat3 gtf_NormalMatrix;
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+attribute vec3 gtf_Normal;
+
+varying vec4 color;
+
+vec4 Ambient;
+vec4 Diffuse;
+vec4 Specular;
+
+const vec3 lightPosition = vec3(0.0, 0.0, 10.0);
+const float lightAttenuationConstant = 1.0;
+const float lightAttenuationLinear = 0.0;
+const float lightAttenuationQuadratic = 0.0;
+
+const vec4 lightAmbient = vec4(0.0, 0.0, 0.0, 0.0);
+vec4 lightDiffuse = vec4(1.0, 0.0, 0.0, 1.0);
+
+const vec4 materialAmbient = vec4(0.0, 0.0, 0.0, 1.0);
+const vec4 materialDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
+const vec4 materialSpecular = vec4(0.0, 0.0, 0.0, 0.0);
+const float materialShininess = 20.0;
+
+const vec4 sceneColor = vec4(0.0, 0.0, 0.0, 0.0);
+
+
+void pointLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3)
+{
+ float nDotVP; // normal . light direction
+ float nDotHV; // normal . light half vector
+ float pf; // power factor
+ float attenuation; // computed attenuation factor
+ float d; // distance from surface to light source
+ vec3 VP; // direction from surface to light position
+ vec3 halfVector; // direction of maximum highlights
+
+ // Compute vector from surface to light position
+ VP = lightPosition - ecPosition3;
+
+ // Compute distance between surface and light position
+ d = length(VP);
+
+ // Normalize the vector from surface to light position
+ VP = normalize(VP);
+
+ // Compute attenuation
+ attenuation = 1.0 / (lightAttenuationConstant +
+ lightAttenuationLinear * d +
+ lightAttenuationQuadratic * d * d);
+
+ halfVector = normalize(VP + eye);
+
+ nDotVP = max(0.0, dot(normal, VP));
+ nDotHV = max(0.0, dot(normal, halfVector));
+
+ if (nDotVP == 0.0)
+ {
+ pf = 0.0;
+ }
+ else
+ {
+ pf = pow(nDotHV, materialShininess);
+
+ }
+ Ambient += lightAmbient * attenuation;
+ Diffuse += lightDiffuse * nDotVP * attenuation;
+// Specular += lightSpecular * pf * attenuation;
+}
+
+vec3 fnormal(void)
+{
+ //Compute the normal
+ vec3 normal = gtf_Normal * gtf_NormalMatrix;
+ normal = normalize(normal);
+
+ // This should change to "return normal" but for this test, we force a normal pointing towards the light
+ // return normal
+ return vec3(0.0, 0.0, 1.0);
+}
+
+void flight(in vec3 normal, in vec4 ecPosition, float alphaFade)
+{
+ vec3 ecPosition3;
+ vec3 eye;
+
+ ecPosition3 = (vec3 (ecPosition)) / ecPosition.w;
+ eye = vec3 (0.0, 0.0, 1.0);
+
+ // Clear the light intensity accumulators
+ Ambient = vec4 (0.0);
+ Diffuse = vec4 (0.0);
+ Specular = vec4 (0.0);
+
+ lightDiffuse = gtf_Color;
+
+ pointLight(0, normal, eye, ecPosition3);
+
+ color = sceneColor +
+ Ambient * materialAmbient +
+ Diffuse * materialDiffuse;
+ color += Specular * materialSpecular;
+ color = clamp( color, 0.0, 1.0 );
+
+ color.a *= alphaFade;
+}
+
+
+void main (void)
+{
+ vec3 transformedNormal;
+ float alphaFade = 1.0;
+
+ // Eye-coordinate position of vertex, needed in various calculations
+ vec4 ecPosition = gtf_ModelViewMatrix * gtf_Vertex;
+
+ // Do fixed functionality vertex transform
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ transformedNormal = fnormal();
+ flight(transformedNormal, ecPosition, alphaFade);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.frag
new file mode 100644
index 0000000000..48175cd07e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.vert
new file mode 100644
index 0000000000..7d58312714
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/lighting_diffuse/lighting_diffuse_ref.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.frag
new file mode 100644
index 0000000000..48175cd07e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.vert
new file mode 100644
index 0000000000..b4e21c7d50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_rasterization/point_rasterization.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform float gtf_PointSize;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = gtf_PointSize;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.frag
new file mode 100644
index 0000000000..f5da783f45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.frag
@@ -0,0 +1,14 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+uniform sampler2D gtf_Texture0;
+
+void main (void)
+{
+ gl_FragColor = texture2D(gtf_Texture0, gl_PointCoord.st);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.vert
new file mode 100644
index 0000000000..8123bf829f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/point_sprites/point_sprites.vert
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute float gtf_PointSize;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+void main (void)
+{
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = gtf_PointSize;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.frag
new file mode 100644
index 0000000000..d332207839
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec4 color;
+varying float dotClip[2];
+
+void main (void)
+{
+ if (dotClip[0] >= 0.0 || dotClip[1] >= 0.0)
+ discard;
+
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.vert
new file mode 100644
index 0000000000..48d13d3d8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2FixedTests/user_clip_planes/user_clip_planes.vert
@@ -0,0 +1,27 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+varying float dotClip[2];
+
+void main (void)
+{
+ vec4 userClipPlanes[2];
+ userClipPlanes[0] = vec4(0.0, 1.0, 0.0, 0.0);
+ userClipPlanes[1] = vec4(-1.0, 0.0, 0.0, 0.0);
+
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+
+ dotClip[0] = dot(userClipPlanes[0], gl_Position);
+ dotClip[1] = dot(userClipPlanes[1], gl_Position);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_frag.frag
new file mode 100644
index 0000000000..4f3fe797b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float GrainSize;
+uniform vec3 DarkColor;
+uniform vec3 colorSpread;
+
+varying float lightIntensity;
+varying vec3 Position;
+
+void main (void)
+{
+ //
+ // cheap noise
+ //
+ vec3 location = Position;
+
+ vec3 floorvec = vec3(floor(Position.x * 10.0), 0.0, floor(Position.z * 10.0));
+ vec3 noise = Position * 10.0 - floorvec - 0.5;
+ noise *= noise;
+ location += noise * 0.12;
+
+ //
+ // distance from axis
+ //
+ float dist = location.x * location.x + location.z * location.z;
+ float grain = dist / GrainSize;
+
+ //
+ // grain effects as function of distance
+ //
+ float brightness = fract(grain);
+ if (brightness > 0.5)
+ brightness = (1.0 - brightness);
+ vec3 color = DarkColor + 0.5 * brightness * (colorSpread);
+
+ brightness = fract(grain*7.0);
+ if (brightness > 0.5)
+ brightness = 1.0 - brightness;
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // also as a function of lines parallel to the axis
+ //
+ brightness = fract(grain*47.0);
+ float line = fract(Position.z + Position.x);
+ float snap = floor(line * 30.0) * (1.0/30.0);
+ if (line < snap + 0.004)
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // apply lighting effects from vertex processor
+ //
+ color *= lightIntensity;
+ color = clamp(color, 0.0, 1.0);
+
+ gl_FragColor = vec4(color, 0.1)
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_vert.vert
new file mode 100644
index 0000000000..b04c21efe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/attach_shader/unsuccessfulcompile_vert.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex_Color;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.frag
new file mode 100644
index 0000000000..2d895c8c8c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.frag
@@ -0,0 +1,47 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.vert
new file mode 100644
index 0000000000..44564ce7cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/bind_attribute_location/brick.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute vec3 myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2[1]);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/brick.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/brick.vert
new file mode 100644
index 0000000000..b04c21efe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/brick.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex_Color;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/texture.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/texture.frag
new file mode 100644
index 0000000000..fdab13ace1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/texture.frag
@@ -0,0 +1,35 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+//
+// wobble.frag: Fragment shader for wobbling a texture
+//
+// author: Antonio Tejada
+//
+//
+
+varying vec3 Position;
+varying float lightIntensity;
+
+/* Constants */
+
+uniform sampler2D sampler2d; // value of sampler2d = 0
+varying vec4 gtf_TexCoord[1];
+
+void main (void)
+{
+ vec3 lightColor = vec3(texture2D(sampler2d, vec2(gtf_TexCoord[0]))) * lightIntensity;
+
+ vec3 ct = clamp(lightColor, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.frag
new file mode 100644
index 0000000000..4f3fe797b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float GrainSize;
+uniform vec3 DarkColor;
+uniform vec3 colorSpread;
+
+varying float lightIntensity;
+varying vec3 Position;
+
+void main (void)
+{
+ //
+ // cheap noise
+ //
+ vec3 location = Position;
+
+ vec3 floorvec = vec3(floor(Position.x * 10.0), 0.0, floor(Position.z * 10.0));
+ vec3 noise = Position * 10.0 - floorvec - 0.5;
+ noise *= noise;
+ location += noise * 0.12;
+
+ //
+ // distance from axis
+ //
+ float dist = location.x * location.x + location.z * location.z;
+ float grain = dist / GrainSize;
+
+ //
+ // grain effects as function of distance
+ //
+ float brightness = fract(grain);
+ if (brightness > 0.5)
+ brightness = (1.0 - brightness);
+ vec3 color = DarkColor + 0.5 * brightness * (colorSpread);
+
+ brightness = fract(grain*7.0);
+ if (brightness > 0.5)
+ brightness = 1.0 - brightness;
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // also as a function of lines parallel to the axis
+ //
+ brightness = fract(grain*47.0);
+ float line = fract(Position.z + Position.x);
+ float snap = floor(line * 30.0) * (1.0/30.0);
+ if (line < snap + 0.004)
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // apply lighting effects from vertex processor
+ //
+ color *= lightIntensity;
+ color = clamp(color, 0.0, 1.0);
+
+ gl_FragColor = vec4(color, 0.1)
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/compile_shader/wood.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/delete_object/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/detach_shader/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.frag
new file mode 100644
index 0000000000..03a0aa8703
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.frag
@@ -0,0 +1,29 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec4 color;
+varying vec4 texCoord[1];
+
+uniform sampler2D gtf_Texture0;
+uniform int gtf_UseTexture;
+
+void main (void)
+{
+ if ( gtf_UseTexture == 1 )
+ {
+ gl_FragColor = texture2D(gtf_Texture0, texCoord[0].xy);
+ }
+ else
+ {
+ gl_FragColor = color;
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.vert
new file mode 100644
index 0000000000..f1edf81011
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/framebuffer_objects/fboShader0.vert
@@ -0,0 +1,23 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Color;
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_MultiTexCoord0;
+
+varying vec4 texCoord[1];
+varying vec4 color;
+
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+void main (void)
+{
+ color = gtf_Color;
+ texCoord[0] = gtf_MultiTexCoord0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat2.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat2.vert
new file mode 100644
index 0000000000..17102a01c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat2.vert
@@ -0,0 +1,45 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec3 gtf_Normal;
+attribute mat2 myAttrib2m;
+
+uniform mat3 gtf_NormalMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ float f = myAttrib2m[0][0];
+
+ float spec = clamp(dot(reflectVec, viewVec), f, 1.0);
+ //float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat3.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat3.vert
new file mode 100644
index 0000000000..d6fea1125b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat3.vert
@@ -0,0 +1,45 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec3 gtf_Normal;
+attribute mat3 myAttrib3m;
+
+uniform mat3 gtf_NormalMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ float f = myAttrib3m[0][0];
+
+ float spec = clamp(dot(reflectVec, viewVec), f, 1.0);
+ //float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat4.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat4.vert
new file mode 100644
index 0000000000..5c28d78aaf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_mat4.vert
@@ -0,0 +1,45 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec3 gtf_Normal;
+attribute mat4 myAttrib4m;
+
+uniform mat3 gtf_NormalMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ float f = myAttrib4m[0][0];
+
+ float spec = clamp(dot(reflectVec, viewVec), f, 1.0);
+ //float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_vec.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_vec.vert
new file mode 100644
index 0000000000..c36a4e1133
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_attribute/brick_vec.vert
@@ -0,0 +1,48 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec3 gtf_Normal;
+attribute float myAttrib1f;
+attribute vec2 myAttrib2f;
+attribute vec3 myAttrib3f;
+attribute vec4 myAttrib4f;
+
+uniform mat3 gtf_NormalMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ float f = myAttrib1f + myAttrib2f[0] + myAttrib3f[0] + myAttrib4f[0];
+
+ float spec = clamp(dot(reflectVec, viewVec), f, 1.0);
+ //float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.frag
new file mode 100644
index 0000000000..3d926c53ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.frag
@@ -0,0 +1,45 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.vert
new file mode 100644
index 0000000000..8629782a45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_active_uniform/brick.vert
@@ -0,0 +1,71 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+varying float lightIntensity;
+varying vec3 Position;
+
+ // Used in the vertex shader.
+uniform mat3 gtf_NormalMatrix; //< 1
+uniform mat4 gtf_ModelViewMatrix; //< 2
+uniform mat4 gtf_ModelViewProjectionMatrix; //< 3
+uniform float myAttrib1f; //< 4
+uniform vec2 myAttrib2f; //< 5
+uniform vec3 LightPosition; //< 6
+uniform vec4 myAttrib4f; //< 7
+uniform int myAttrib1i; //< 8
+uniform ivec2 myAttrib2i; //< 9
+uniform ivec3 myAttrib3i; //< 10
+uniform ivec4 myAttrib4i; //< 11
+uniform bool myAttrib1b; //< 12
+uniform bvec2 myAttrib2b; //< 13
+uniform bvec3 myAttrib3b; //< 14
+uniform bvec4 myAttrib4b; //< 15
+uniform mat2 myAttrib2m; //< 16
+uniform mat3 myAttrib3m; //< 17
+uniform mat4 myAttrib4m; //< 18
+uniform float myUniformfv[5]; //< 19
+ // Used in the fragment shader.
+uniform vec3 brickColor; //< 20
+uniform vec3 mortarColor; //< 21
+uniform float brickMortarWidth; //< 22
+uniform float brickMortarHeight; //< 23
+uniform float mwf; //< 24
+uniform float mhf; //< 25
+
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ float f = myAttrib1f + myAttrib2f[0] + myAttrib4f[0]
+ + float(myAttrib1i) + float(myAttrib2i[0]) + float(myAttrib3i[0]) + float(myAttrib4i[0])
+ + float(myAttrib1b) + float(myAttrib2b[0]) + float(myAttrib3b[0]) + float(myAttrib4b[0])
+ + myAttrib2m[0][0] + myAttrib3m[0][0] + myAttrib4m[0][0]
+ + myUniformfv[0] + myUniformfv[1] + myUniformfv[2] + myUniformfv[3] + myUniformfv[4];
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), f, 1.0);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.frag
new file mode 100644
index 0000000000..3d830261ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec3 colors;
+
+void main (void)
+{
+ gl_FragColor = vec4 (colors, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.vert
new file mode 100644
index 0000000000..3b0c0ba6f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_attribute_location/brick.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute float myAttribute1;
+attribute float myAttribute2;
+attribute float myAttribute3;
+
+varying vec3 colors;
+
+void main(void)
+{
+ colors = vec3(myAttribute1, 0, 0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_handle/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.vert
new file mode 100644
index 0000000000..35b8ecbafc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/get_uniform_location/brick.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.frag
new file mode 100644
index 0000000000..3ee1988465
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec3 tc;
+
+void main (void)
+{
+ vec3 foo = tc;
+ gl_FragColor = vec4 (foo, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.vert
new file mode 100644
index 0000000000..03666713db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramInfoLog_2.0/simple.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform vec3 triangleColor;
+varying vec3 tc;
+
+void main(void)
+{
+ tc = triangleColor;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.vert
new file mode 100644
index 0000000000..35b8ecbafc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetProgramiv_2.0/brick.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.frag
new file mode 100644
index 0000000000..3ee1988465
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.frag
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec3 tc;
+
+void main (void)
+{
+ vec3 foo = tc;
+ gl_FragColor = vec4 (foo, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.vert
new file mode 100644
index 0000000000..03666713db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetShaderInfoLog_2.0/simple.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform vec3 triangleColor;
+varying vec3 tc;
+
+void main(void)
+{
+ tc = triangleColor;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.frag
new file mode 100644
index 0000000000..2c0fc9e2c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.frag
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform bool funi1;
+uniform bvec2 funi2;
+uniform bvec3 funi3;
+uniform bvec4 funi4;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 temp = vec4(0.0, 0.0, 0.0, 0.0);
+ if(funi1 || funi2[0] && funi2[1] && funi3[0] && funi3[1] && funi3[2] || funi4[0] && funi4[1] && funi4[2] && funi4[3])
+ temp = vec4(1.0, 0.0, 0.5, 1.0);
+ gl_FragColor = temp + color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.vert
new file mode 100644
index 0000000000..33bcf06a9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/bvec_tests.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform bool vuni1;
+uniform bvec2 vuni2;
+uniform bvec3 vuni3;
+uniform bvec4 vuni4;
+varying vec4 color;
+
+void main (void)
+{
+ if(vuni1 || vuni2[0] && vuni2[1] && vuni3[0] && vuni3[1] && vuni3[2] || vuni4[0] && vuni4[1] && vuni4[2] && vuni4[3])
+ color = vec4(1.0, 0.0, 0.5, 1.0);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.frag
new file mode 100644
index 0000000000..4d0cabe58d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform int funi1;
+uniform ivec2 funi2;
+uniform ivec3 funi3;
+uniform ivec4 funi4;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 temp = vec4(float(funi1), float(funi2[0] + funi2[1]), float(funi3[0] + funi3[1] + funi3[2]), float(funi4[0] + funi4[1] + funi4[2] + funi4[3]));
+ gl_FragColor = temp + color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.vert
new file mode 100644
index 0000000000..ce7159c386
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/ivec_tests.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform int vuni1;
+uniform ivec2 vuni2;
+uniform ivec3 vuni3;
+uniform ivec4 vuni4;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(float(vuni1), float(vuni2[0] + vuni2[1]), float(vuni3[0] + vuni3[1] + vuni3[2]), float(vuni4[0] + vuni4[1] + vuni4[2] + vuni4[3]) );
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.frag
new file mode 100644
index 0000000000..f963f96f36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.frag
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform mat2 funi2;
+uniform mat3 funi3;
+uniform mat4 funi4;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 temp = vec4( funi2[0][0] + funi2[0][1] + funi2[1][0] + funi2[1][1],
+
+ funi3[0][0] + funi3[0][1] + funi3[0][2] + funi3[1][0] + funi3[1][1] + funi3[1][2] + funi3[2][0] + funi3[2][1] + funi3[2][2],
+
+ funi4[0][0] + funi4[0][1] + funi4[0][2] + funi4[0][3] + funi4[1][0] + funi4[1][1] + funi4[1][2] + funi4[1][3] + funi4[2][0] + funi4[2][1] + funi4[2][2] + funi4[2][3] + funi4[3][0] + funi4[3][1] + funi4[3][2] + funi4[3][3], 1.0 );
+ gl_FragColor = temp + color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.vert
new file mode 100644
index 0000000000..9479dc919b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/mat_tests.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform mat2 vuni2;
+uniform mat3 vuni3;
+uniform mat4 vuni4;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4( vuni2[0][0] + vuni2[0][1] + vuni2[1][0] + vuni2[1][1],
+
+ vuni3[0][0] + vuni3[0][1] + vuni3[0][2] + vuni3[1][0] + vuni3[1][1] + vuni3[1][2] + vuni3[2][0] + vuni3[2][1] + vuni3[2][2],
+
+ vuni4[0][0] + vuni4[0][1] + vuni4[0][2] + vuni4[0][3] + vuni4[1][0] + vuni4[1][1] + vuni4[1][2] + vuni4[1][3] + vuni4[2][0] + vuni4[2][1] + vuni4[2][2] + vuni4[2][3] + vuni4[3][0] + vuni4[3][1] + vuni4[3][2] + vuni4[3][3], 1.0 );
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.frag
new file mode 100644
index 0000000000..18f3e349a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float funi1;
+uniform vec2 funi2;
+uniform vec3 funi3;
+uniform vec4 funi4;
+varying vec4 color;
+
+void main (void)
+{
+ vec4 temp = vec4(funi1, funi2[0] + funi2[1], funi3[0] + funi3[1] + funi3[2], funi4[0] + funi4[1] + funi4[2] + funi4[3]);
+ gl_FragColor = temp + color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.vert
new file mode 100644
index 0000000000..25f96f4464
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetUniform/vec_tests.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform float vuni1;
+uniform vec2 vuni2;
+uniform vec3 vuni3;
+uniform vec4 vuni4;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(vuni1, vuni2[0] + vuni2[1], vuni3[0] + vuni3[1] + vuni3[2], vuni4[0] + vuni4[1] + vuni4[2] + vuni4[3]);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests.vert
new file mode 100644
index 0000000000..a9ba12e213
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute mat3 att3;
+attribute mat4 att4;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4( 1.0,
+
+ att3[0][0] + att3[0][1] + att3[0][2] + att3[1][0] + att3[1][1] + att3[1][2] + att3[2][0] + att3[2][1] + att3[2][2],
+
+ att4[0][0] + att4[0][1] + att4[0][2] + att4[0][3] + att4[1][0] + att4[1][1] + att4[1][2] + att4[1][3] + att4[2][0] + att4[2][1] + att4[2][2] + att4[2][3] + att4[3][0] + att4[3][1] + att4[3][2] + att4[3][3], 1.0 );
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests2.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests2.vert
new file mode 100644
index 0000000000..06bba63ae6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/mat_tests2.vert
@@ -0,0 +1,24 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute mat2 att2;
+attribute mat3 att3;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4( att2[0][0] + att2[0][1] + att2[1][0] + att2[1][1],
+
+ att3[0][0] + att3[0][1] + att3[0][2] + att3[1][0] + att3[1][1] + att3[1][2] + att3[2][0] + att3[2][1] + att3[2][2],
+
+ 1.0, 1.0 );
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/vec_tests.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/vec_tests.vert
new file mode 100644
index 0000000000..3218e9a73f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glGetVertexAttrib/vec_tests.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute float att1;
+attribute vec2 att2;
+attribute vec3 att3;
+attribute vec4 att4;
+varying vec4 color;
+
+void main (void)
+{
+ color = vec4(att1, att2.x + att2.y, att3.x + att3.y + att3.z, att4.x + att4.y + att4.z + att4.w);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_frag.frag
new file mode 100644
index 0000000000..b2813604c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform bool color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (float(color), 0.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.frag
new file mode 100644
index 0000000000..fcd1d2e0d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying float col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.vert
new file mode 100644
index 0000000000..8fcd8c1bd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1b_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform bool color;
+varying float col;
+void main (void)
+{
+ col = float(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_frag.frag
new file mode 100644
index 0000000000..8494f30c37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color, 0.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.frag
new file mode 100644
index 0000000000..fdd9357a9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying float col;
+void main (void)
+{
+ gl_FragColor = vec4 (col, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.vert
new file mode 100644
index 0000000000..ece9ee5e84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1f_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform float color;
+varying float col;
+void main (void)
+{
+ col = color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_frag.frag
new file mode 100644
index 0000000000..f733d43d48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform int color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color, 0.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.frag
new file mode 100644
index 0000000000..fdd9357a9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.frag
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying float col;
+void main (void)
+{
+ gl_FragColor = vec4 (col, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.vert
new file mode 100644
index 0000000000..5070175baf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/1i_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform int color;
+varying float col;
+void main (void)
+{
+ col = float(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21f_frag.frag
new file mode 100644
index 0000000000..42a72c719e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21f_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float color[2];
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0], color[1], 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21i_frag.frag
new file mode 100644
index 0000000000..d222ed18cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/21i_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform int color[2];
+
+void main (void)
+{
+ float r = float(color[0]);
+ float g = float(color[1]);
+ gl_FragColor = vec4 (r/256.0, g/256.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22f_frag.frag
new file mode 100644
index 0000000000..b44a935cf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22f_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec2 color[2];
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0][0], color[0][1], color[1][0], color[1][1]);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22i_frag.frag
new file mode 100644
index 0000000000..f2b0ae1b3e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/22i_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform ivec2 color[2];
+
+void main (void)
+{
+ float r = float(color[0][0]);
+ float g = float(color[0][1]);
+ float b = float(color[1][0]);
+ float a = float(color[1][1]);
+
+ gl_FragColor = vec4 (r/256.0, g/256.0, b/256.0, a/256.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23f_frag.frag
new file mode 100644
index 0000000000..c89502f293
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23f_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec3 color[2];
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0][0] + color[0][1] + color[0][2],
+ color[1][0] + color[1][1] + color[1][2],
+ 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23i_frag.frag
new file mode 100644
index 0000000000..b2fb09f2c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/23i_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform ivec3 color[2];
+
+void main (void)
+{
+ float r = float(color[0][0] + color[0][1] + color[0][2]);
+ float g = float(color[1][0] + color[1][1] + color[1][2]);
+
+ gl_FragColor = vec4(r/256.0, g/256.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24f_frag.frag
new file mode 100644
index 0000000000..787ecba389
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24f_frag.frag
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec4 color[2];
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0][0] + color[0][1] + color[0][2] + color[0][3],
+ color[1][0] + color[1][1] + color[1][2] + color[1][3],
+ 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24i_frag.frag
new file mode 100644
index 0000000000..aef4a8489c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/24i_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform ivec4 color[2];
+
+void main (void)
+{
+ float r = float(color[0][0] + color[0][1] + color[0][2] + color[0][3]);
+ float g = float(color[1][0] + color[1][1] + color[1][2] + color[1][3]);
+
+ gl_FragColor = vec4 (r/256.0, g/256.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_frag.frag
new file mode 100644
index 0000000000..7b6eb3f2b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform bvec2 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (vec2(color), 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.frag
new file mode 100644
index 0000000000..83bf3e6539
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec2 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col[0], col[1], 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.vert
new file mode 100644
index 0000000000..8285a0eb87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2b_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform bvec2 color;
+varying vec2 col;
+void main (void)
+{
+ col = vec2(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_frag.frag
new file mode 100644
index 0000000000..2039a887a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec2 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.frag
new file mode 100644
index 0000000000..44dac79c82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec2 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.vert
new file mode 100644
index 0000000000..159d66c795
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2f_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform vec2 color;
+varying vec2 col;
+void main (void)
+{
+ col = color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_frag.frag
new file mode 100644
index 0000000000..4494014822
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform ivec2 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0], color[1], 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.frag
new file mode 100644
index 0000000000..44dac79c82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec2 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.vert
new file mode 100644
index 0000000000..fd14f20c5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2i_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform ivec2 color;
+varying vec2 col;
+void main (void)
+{
+ col = vec2(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2m_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2m_frag.frag
new file mode 100644
index 0000000000..fe562e63d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/2m_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform mat2 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0][0] + color[0][1], color[1][0] + color[1][1], 0.0, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_frag.frag
new file mode 100644
index 0000000000..bd97506459
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform bvec3 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (vec3(color), 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.frag
new file mode 100644
index 0000000000..c17b9a1480
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec3 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col[0], col[1], col[2], 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.vert
new file mode 100644
index 0000000000..b9b8fd4893
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3b_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform bvec3 color;
+varying vec3 col;
+void main (void)
+{
+ col = vec3(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_frag.frag
new file mode 100644
index 0000000000..f0fa6853c7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec3 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color, 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.frag
new file mode 100644
index 0000000000..2e98a8660c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec3 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.vert
new file mode 100644
index 0000000000..c5562f04b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3f_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform vec3 color;
+varying vec3 col;
+void main (void)
+{
+ col = color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_frag.frag
new file mode 100644
index 0000000000..e17402b6da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform ivec3 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0], color[1], color[2], 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.frag
new file mode 100644
index 0000000000..2e98a8660c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec3 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.vert
new file mode 100644
index 0000000000..7b2aa4bb25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3i_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform ivec3 color;
+varying vec3 col;
+void main (void)
+{
+ col = vec3(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3m_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3m_frag.frag
new file mode 100644
index 0000000000..bcc8f4a5a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/3m_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform mat3 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0][0] + color[0][1] + color[0][2],
+ color[1][0] + color[1][1] + color[1][2],
+ color[2][0] + color[2][1] + color[2][2],
+ 1.0);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_frag.frag
new file mode 100644
index 0000000000..de9abd75bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform bvec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (float(color[0]), float(color[1]), float(color[2]), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_vert.frag
new file mode 100644
index 0000000000..c6c01468a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_firstthree_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col[0], col[1], col[2], 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_frag.frag
new file mode 100644
index 0000000000..8d84731315
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform bvec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (float(color[1]), float(color[2]), float(color[3]), 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_vert.frag
new file mode 100644
index 0000000000..869d183e06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_lastthree_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col[1], col[2], col[3], 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_vert.vert
new file mode 100644
index 0000000000..c09ce89491
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4b_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform bvec4 color;
+varying vec4 col;
+void main (void)
+{
+ col = vec4(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_frag.frag
new file mode 100644
index 0000000000..7b071c0347
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0], color[1], color[2], color[3]);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.frag
new file mode 100644
index 0000000000..96b06e0786
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col[0], col[1], col[2], col[3]);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.vert
new file mode 100644
index 0000000000..71d88d9610
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4f_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform vec4 color;
+varying vec4 col;
+void main (void)
+{
+ col = color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_frag.frag
new file mode 100644
index 0000000000..55d9053c52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_frag.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform ivec4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0], color[1], color[2], color[3]);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.frag
new file mode 100644
index 0000000000..96b06e0786
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 col;
+
+void main (void)
+{
+ gl_FragColor = vec4 (col[0], col[1], col[2], col[3]);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.vert
new file mode 100644
index 0000000000..42cdfaa4e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4i_vert.vert
@@ -0,0 +1,18 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute vec4 gtf_Color;
+uniform ivec4 color;
+varying vec4 col;
+void main (void)
+{
+ col = vec4(color);
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4m_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4m_frag.frag
new file mode 100644
index 0000000000..d0600049bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/4m_frag.frag
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform mat4 color;
+
+void main (void)
+{
+ gl_FragColor = vec4 (color[0][0] + color[0][1] + color[0][2] + color[0][3],
+ color[1][0] + color[1][1] + color[1][2] + color[1][3],
+ color[2][0] + color[2][1] + color[2][2] + color[2][3],
+ color[3][0] + color[3][1] + color[3][2] + color[3][3]);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/default.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/default.vert
new file mode 100644
index 0000000000..b62c57df92
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/default.vert
@@ -0,0 +1,16 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+void main (void)
+{
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+ gl_PointSize = 1.0;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.frag
new file mode 100644
index 0000000000..e08688b5a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color; // Apply it on a per vertex level
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.vert
new file mode 100644
index 0000000000..b2edd70556
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2VSU.vert
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform mat4 transforms;
+uniform mat4 anotherMatrix;
+
+varying vec4 color;
+
+void main(void)
+{
+ color = gtf_Color; // color is per vertex and matches glColor already used by Vertex
+
+ gl_Position = gtf_ModelViewProjectionMatrix* transforms * anotherMatrix * gtf_Vertex;
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.frag
new file mode 100644
index 0000000000..e08688b5a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color; // Apply it on a per vertex level
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.vert
new file mode 100644
index 0000000000..59e6497387
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrix2arrayVSU.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform mat4 transforms[2];
+
+varying vec4 color;
+
+void main(void)
+{
+ color = gtf_Color; // color is per vertex and matches glColor already used by Vertex
+
+ gl_Position = gtf_ModelViewProjectionMatrix* transforms[0] * transforms[1] * gtf_Vertex;
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.frag
new file mode 100644
index 0000000000..e08688b5a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color; // Apply it on a per vertex level
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.vert
new file mode 100644
index 0000000000..4643a15bec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/glUniform/matrixVSU.vert
@@ -0,0 +1,21 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+uniform mat4 transforms;
+varying vec4 color;
+
+void main(void)
+{
+ color = gtf_Color; // color is per vertex and matches glColor used
+
+ gl_Position = gtf_ModelViewProjectionMatrix* transforms * gtf_Vertex;
+
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_frag.frag
new file mode 100644
index 0000000000..4f3fe797b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float GrainSize;
+uniform vec3 DarkColor;
+uniform vec3 colorSpread;
+
+varying float lightIntensity;
+varying vec3 Position;
+
+void main (void)
+{
+ //
+ // cheap noise
+ //
+ vec3 location = Position;
+
+ vec3 floorvec = vec3(floor(Position.x * 10.0), 0.0, floor(Position.z * 10.0));
+ vec3 noise = Position * 10.0 - floorvec - 0.5;
+ noise *= noise;
+ location += noise * 0.12;
+
+ //
+ // distance from axis
+ //
+ float dist = location.x * location.x + location.z * location.z;
+ float grain = dist / GrainSize;
+
+ //
+ // grain effects as function of distance
+ //
+ float brightness = fract(grain);
+ if (brightness > 0.5)
+ brightness = (1.0 - brightness);
+ vec3 color = DarkColor + 0.5 * brightness * (colorSpread);
+
+ brightness = fract(grain*7.0);
+ if (brightness > 0.5)
+ brightness = 1.0 - brightness;
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // also as a function of lines parallel to the axis
+ //
+ brightness = fract(grain*47.0);
+ float line = fract(Position.z + Position.x);
+ float snap = floor(line * 30.0) * (1.0/30.0);
+ if (line < snap + 0.004)
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // apply lighting effects from vertex processor
+ //
+ color *= lightIntensity;
+ color = clamp(color, 0.0, 1.0);
+
+ gl_FragColor = vec4(color, 0.1)
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_vert.vert
new file mode 100644
index 0000000000..b04c21efe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/link_program/unsuccessfulcompile_vert.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex_Color;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.frag
new file mode 100644
index 0000000000..01fae5b25f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.frag
@@ -0,0 +1,14 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+varying mediump vec4 color;
+
+void main (void)
+{
+ gl_FragColor = color;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.vert
new file mode 100644
index 0000000000..bc68fc3881
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/precision_specifiers/precision_specifiers.vert
@@ -0,0 +1,25 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute highp vec4 gtf_Color;
+attribute highp vec4 gtf_Vertex;
+uniform highp mat4 gtf_ModelViewProjectionMatrix;
+varying highp vec4 color;
+
+void main (void)
+{
+ mediump int x = 5;
+ lowp int y = 3;
+ mediump float x2 = 5.0;
+ lowp float y2 = 1.0;
+
+ color = vec4(x + y, x2 * y2, x, 1.0);
+
+ color = gtf_Color;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.frag
new file mode 100644
index 0000000000..863acf1776
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.frag
@@ -0,0 +1,17 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 tc;
+
+void main (void)
+{
+ gl_FragColor = tc;
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.vert
new file mode 100644
index 0000000000..453cfeb4dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/relink_program/simple.vert
@@ -0,0 +1,20 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+attribute float gtf_Color;
+
+varying vec4 tc;
+
+void main (void)
+{
+ tc = vec4(gtf_Color, 0.0, 0.0, 1.0);
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_frag.frag
new file mode 100644
index 0000000000..4f3fe797b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float GrainSize;
+uniform vec3 DarkColor;
+uniform vec3 colorSpread;
+
+varying float lightIntensity;
+varying vec3 Position;
+
+void main (void)
+{
+ //
+ // cheap noise
+ //
+ vec3 location = Position;
+
+ vec3 floorvec = vec3(floor(Position.x * 10.0), 0.0, floor(Position.z * 10.0));
+ vec3 noise = Position * 10.0 - floorvec - 0.5;
+ noise *= noise;
+ location += noise * 0.12;
+
+ //
+ // distance from axis
+ //
+ float dist = location.x * location.x + location.z * location.z;
+ float grain = dist / GrainSize;
+
+ //
+ // grain effects as function of distance
+ //
+ float brightness = fract(grain);
+ if (brightness > 0.5)
+ brightness = (1.0 - brightness);
+ vec3 color = DarkColor + 0.5 * brightness * (colorSpread);
+
+ brightness = fract(grain*7.0);
+ if (brightness > 0.5)
+ brightness = 1.0 - brightness;
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // also as a function of lines parallel to the axis
+ //
+ brightness = fract(grain*47.0);
+ float line = fract(Position.z + Position.x);
+ float snap = floor(line * 30.0) * (1.0/30.0);
+ if (line < snap + 0.004)
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // apply lighting effects from vertex processor
+ //
+ color *= lightIntensity;
+ color = clamp(color, 0.0, 1.0);
+
+ gl_FragColor = vec4(color, 0.1)
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_vert.vert
new file mode 100644
index 0000000000..514042bd8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/shader_source/unsuccessfulcompile_vert.vert
@@ -0,0 +1,44 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Vertex_Color;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex_Color;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos);
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/three_uniforms/4f_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/three_uniforms/4f_frag.frag
new file mode 100644
index 0000000000..a0493e9158
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/three_uniforms/4f_frag.frag
@@ -0,0 +1,22 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec4 color;
+uniform ivec4 icolor;
+uniform bool flag;
+
+void main (void)
+{
+ if(flag)
+ gl_FragColor = vec4 (icolor[0], icolor[1], icolor[2], icolor[3]);
+ else
+ gl_FragColor = vec4 (color[0], color[1], color[2], color[3]);
+} \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_frag.frag
new file mode 100644
index 0000000000..4f3fe797b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float GrainSize;
+uniform vec3 DarkColor;
+uniform vec3 colorSpread;
+
+varying float lightIntensity;
+varying vec3 Position;
+
+void main (void)
+{
+ //
+ // cheap noise
+ //
+ vec3 location = Position;
+
+ vec3 floorvec = vec3(floor(Position.x * 10.0), 0.0, floor(Position.z * 10.0));
+ vec3 noise = Position * 10.0 - floorvec - 0.5;
+ noise *= noise;
+ location += noise * 0.12;
+
+ //
+ // distance from axis
+ //
+ float dist = location.x * location.x + location.z * location.z;
+ float grain = dist / GrainSize;
+
+ //
+ // grain effects as function of distance
+ //
+ float brightness = fract(grain);
+ if (brightness > 0.5)
+ brightness = (1.0 - brightness);
+ vec3 color = DarkColor + 0.5 * brightness * (colorSpread);
+
+ brightness = fract(grain*7.0);
+ if (brightness > 0.5)
+ brightness = 1.0 - brightness;
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // also as a function of lines parallel to the axis
+ //
+ brightness = fract(grain*47.0);
+ float line = fract(Position.z + Position.x);
+ float snap = floor(line * 30.0) * (1.0/30.0);
+ if (line < snap + 0.004)
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // apply lighting effects from vertex processor
+ //
+ color *= lightIntensity;
+ color = clamp(color, 0.0, 1.0);
+
+ gl_FragColor = vec4(color, 0.1)
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_vert.vert
new file mode 100644
index 0000000000..b04c21efe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/use_program/unsuccessfulcompile_vert.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex_Color;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_frag.frag
new file mode 100644
index 0000000000..b251b07f03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_frag.frag
@@ -0,0 +1,46 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float mortarThickness;
+uniform vec3 brickColor;
+uniform vec3 mortarColor;
+
+uniform float brickMortarWidth;
+uniform float brickMortarHeight;
+uniform float mwf;
+uniform float mhf;
+
+varying vec3 Position;
+varying float lightIntensity;
+
+void main (void)
+{
+ vec3 ct;
+ float ss, tt, w, h;
+
+ vec3 pos = Position;
+
+ ss = pos.x / brickMortarWidth;
+ tt = pos.z / brickMortarHeight;
+
+ if (fract (tt * 0.5) > 0.5)
+ ss += 0.5;
+
+ ss = fract (ss);
+ tt = fract (tt);
+
+ w = step (mwf, ss) - step (1.0 - mwf, ss);
+ h = step (mhf, tt) - step (1.0 - mhf, tt);
+
+ ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0);
+
+ gl_FragColor = vec4 (ct, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_vert.vert
new file mode 100644
index 0000000000..19faf8698b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/successfulcompile_vert.vert
@@ -0,0 +1,26 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform float Scale;
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;
+ Position = vec3(gtf_Vertex) * Scale;
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_frag.frag b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_frag.frag
new file mode 100644
index 0000000000..4f3fe797b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_frag.frag
@@ -0,0 +1,66 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform float GrainSize;
+uniform vec3 DarkColor;
+uniform vec3 colorSpread;
+
+varying float lightIntensity;
+varying vec3 Position;
+
+void main (void)
+{
+ //
+ // cheap noise
+ //
+ vec3 location = Position;
+
+ vec3 floorvec = vec3(floor(Position.x * 10.0), 0.0, floor(Position.z * 10.0));
+ vec3 noise = Position * 10.0 - floorvec - 0.5;
+ noise *= noise;
+ location += noise * 0.12;
+
+ //
+ // distance from axis
+ //
+ float dist = location.x * location.x + location.z * location.z;
+ float grain = dist / GrainSize;
+
+ //
+ // grain effects as function of distance
+ //
+ float brightness = fract(grain);
+ if (brightness > 0.5)
+ brightness = (1.0 - brightness);
+ vec3 color = DarkColor + 0.5 * brightness * (colorSpread);
+
+ brightness = fract(grain*7.0);
+ if (brightness > 0.5)
+ brightness = 1.0 - brightness;
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // also as a function of lines parallel to the axis
+ //
+ brightness = fract(grain*47.0);
+ float line = fract(Position.z + Position.x);
+ float snap = floor(line * 30.0) * (1.0/30.0);
+ if (line < snap + 0.004)
+ color -= 0.5 * brightness * colorSpread;
+
+ //
+ // apply lighting effects from vertex processor
+ //
+ color *= lightIntensity;
+ color = clamp(color, 0.0, 1.0);
+
+ gl_FragColor = vec4(color, 0.1)
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_vert.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_vert.vert
new file mode 100644
index 0000000000..b04c21efe3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/validate_program/unsuccessfulcompile_vert.vert
@@ -0,0 +1,43 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec3 gtf_Normal;
+attribute vec4 gtf_Vertex;
+uniform mat3 gtf_NormalMatrix;
+uniform mat4 gtf_ModelViewMatrix;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying float lightIntensity;
+varying vec3 Position;
+uniform vec3 LightPosition;
+uniform vec3 NotActiveOne;
+attribute float myAttribute1;
+attribute float myAttribute2;
+
+const float specularContribution = 0.7;
+const float diffuseContribution = (1.0 - specularContribution);
+
+void main(void) {
+ vec4 pos = gtf_ModelViewMatrix * gtf_Vertex_Color;
+ Position = vec3(gtf_Vertex);
+ vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);
+ vec3 lightVec = normalize(LightPosition - vec3(pos));
+ vec3 reflectVec = reflect(lightVec, tnorm);
+ vec3 viewVec = normalize(vec3(pos));
+
+ //float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
+ float spec = clamp(dot(reflectVec, viewVec), myAttribute1, myAttribute2);
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+ spec = spec * spec;
+
+ lightIntensity = diffuseContribution * dot(lightVec, tnorm) +
+ specularContribution * spec;
+
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/vertex_program_point_size/point_size.vert b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/vertex_program_point_size/point_size.vert
new file mode 100644
index 0000000000..1632a0ee88
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/GL2Tests/vertex_program_point_size/point_size.vert
@@ -0,0 +1,19 @@
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+attribute vec4 gtf_Vertex;
+attribute vec4 gtf_Color;
+uniform mat4 gtf_ModelViewProjectionMatrix;
+varying vec4 color;
+
+void main (void)
+{
+ color = gtf_Color;
+ gl_PointSize = 20.0;
+ gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/README.md b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/README.md
new file mode 100644
index 0000000000..e44d84eae4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/README.md
@@ -0,0 +1,20 @@
+OpenGL ES 2.0 GLSL conformance tests
+====================================
+
+The python script, process-ogles2-tests.py, in this folder generates some
+WebGL conformance tests from a subset of the OpenGL ES 2.0 conformance
+tests.
+
+To run it you must have a copy of the OpenGL ES 2.0 conformance test
+source then run it like this
+
+ python process-ogles2-tests.py <path/to/ogles2tests>/GTF_ES/glsl/GTF/mustpass.run
+
+Note: Before running you can safely delete the GTF_ES folder in this
+folder. Everything inside will be regenerated by the script above.
+
+IMPORTANT: From the OpenGL ES 2.0 conformance tests only the .vert and
+.frag files are open source licenesed. All other files in that suite are
+not open source.
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/mustpass.run.txt b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/mustpass.run.txt
new file mode 100644
index 0000000000..e6b87db93a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/mustpass.run.txt
@@ -0,0 +1,64 @@
+# this file is auto-generated. DO NOT EDIT.
+GL/abs/input.run.txt
+GL/acos/input.run.txt
+GL/all/input.run.txt
+GL/any/input.run.txt
+GL/array/input.run.txt
+GL/asin/input.run.txt
+GL/atan/input.run.txt
+GL/biConstants/input.run.txt
+GL/biuDepthRange/input.run.txt
+GL/build/input.run.txt
+GL/built_in_varying_array_out_of_bounds/input.run.txt
+GL/ceil/input.run.txt
+GL/clamp/input.run.txt
+GL/control_flow/input.run.txt
+GL/cos/input.run.txt
+GL/cross/input.run.txt
+GL/default/input.run.txt
+GL/degrees/input.run.txt
+GL/discard/input.run.txt
+GL/distance/input.run.txt
+GL/dot/input.run.txt
+GL/equal/input.run.txt
+GL/exp/input.run.txt
+GL/exp2/input.run.txt
+GL/faceforward/input.run.txt
+GL/floor/input.run.txt
+GL/fract/input.run.txt
+GL/functions/input.run.txt
+GL/gl_FragCoord/input.run.txt
+GL/gl_FrontFacing/input.run.txt
+GL/greaterThan/input.run.txt
+GL/greaterThanEqual/input.run.txt
+GL/inversesqrt/input.run.txt
+GL/length/input.run.txt
+GL/lessThan/input.run.txt
+GL/lessThanEqual/input.run.txt
+GL/log/input.run.txt
+GL/log2/input.run.txt
+GL/mat/input.run.txt
+GL/mat3/input.run.txt
+GL/matrixCompMult/input.run.txt
+GL/max/input.run.txt
+GL/min/input.run.txt
+GL/mix/input.run.txt
+GL/mod/input.run.txt
+GL/normalize/input.run.txt
+GL/not/input.run.txt
+GL/notEqual/input.run.txt
+GL/operators/input.run.txt
+GL/pow/input.run.txt
+GL/radians/input.run.txt
+GL/reflect/input.run.txt
+GL/refract/input.run.txt
+GL/sign/input.run.txt
+GL/sin/input.run.txt
+GL/smoothstep/input.run.txt
+GL/sqrt/input.run.txt
+GL/step/input.run.txt
+GL/struct/input.run.txt
+GL/swizzlers/input.run.txt
+GL/tan/input.run.txt
+GL/vec/input.run.txt
+GL/vec3/input.run.txt
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js
new file mode 100644
index 0000000000..b2a1500496
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js
@@ -0,0 +1,791 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+OpenGLESTestRunner = (function(){
+var wtu = WebGLTestUtils;
+var gl;
+
+var HALF_GRID_MAX_SIZE = 32;
+var KNOWN_ATTRIBS = [
+ "gtf_Vertex",
+ "gtf_Color"
+];
+
+var GTFPIXELTOLERANCE = 24;
+var GTFACCEPTABLEFAILURECONT = 10;
+var GTFAMDPIXELTOLERANCE = 12;
+var GTFSCORETOLERANCE = 0.65;
+var GTFNCCTOLARANCEZERO = 0.25;
+var GTFKERNALSIZE = 5;
+
+function log(msg) {
+ // debug(msg);
+}
+
+function compareImages(refData, tstData, width, height, diff) {
+ function isPixelSame(offset) {
+ // First do simple check
+ if (Math.abs(refData[offset + 0] - tstData[offset + 0]) <= GTFPIXELTOLERANCE &&
+ Math.abs(refData[offset + 1] - tstData[offset + 1]) <= GTFPIXELTOLERANCE &&
+ Math.abs(refData[offset + 2] - tstData[offset + 2]) <= GTFPIXELTOLERANCE) {
+ return true;
+ }
+
+ // TODO: Implement crazy check that's used in OpenGL ES 2.0 conformance tests.
+ // NOTE: on Desktop things seem to be working. Maybe the more complex check
+ // is needed for embedded systems?
+ return false;
+ }
+
+ var same = true;
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ var diffOffset = ((height - yy - 1) * width + xx) * 4;
+ diff[diffOffset + 0] = 0;
+ diff[diffOffset + 1] = 0;
+ diff[diffOffset + 2] = 0;
+ diff[diffOffset + 3] = 255;
+ if (!isPixelSame(offset)) {
+ diff[diffOffset] = 255;
+ if (same) {
+ same = false;
+ testFailed("pixel @ (" + xx + ", " + yy + " was [" +
+ tstData[offset + 0] + "," +
+ tstData[offset + 1] + "," +
+ tstData[offset + 2] + "," +
+ tstData[offset + 3] + "] expected [" +
+ refData[offset + 0] + "," +
+ refData[offset + 1] + "," +
+ refData[offset + 2] + "," +
+ refData[offset + 3] + "]")
+ }
+ }
+ }
+ }
+ return same;
+}
+
+function persp(fovy, aspect, n, f) {
+ var dz = f - n;
+ var rad = fovy / 2.0 * 3.14159265 / 180;
+
+ var s = Math.sin(rad);
+ if (dz == 0 || s == 0 || aspect == 0)
+ return;
+
+ var cot = Math.cos(rad) / s;
+
+ return [
+ cot / aspect,
+ 0.0,
+ 0.0,
+ 0.0,
+
+ 0.0,
+ cot,
+ 0.0,
+ 0.0,
+
+ 0.0,
+ 0.0,
+ -(f + n) / dz,
+ -1.0,
+
+ 0.0,
+ 0.0,
+ -2.0 * f * n / dz,
+ 0.0
+ ];
+}
+
+function setAttribs(attribs, buffers) {
+ for (var name in attribs) {
+ var buffer = buffers[name];
+ if (!buffer) {
+ testFailed("no buffer for attrib:" + name);
+ continue;
+ }
+ var loc = attribs[name];
+ log("setup attrib: " + loc + " as " + name);
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(buffer.data), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribPointer(loc, buffer.numComponents, gl.FLOAT, false, 0, 0);
+ }
+}
+
+function drawSquare(attribs) {
+ var buffers = {
+ "gtf_Vertex": {
+ data: [
+ 1.0, -1.0, -2.0,
+ 1.0, 1.0, -2.0,
+ -1.0, -1.0, -2.0,
+ -1.0, 1.0, -2.0
+ ],
+ numComponents: 3
+ },
+ "gtf_Color": {
+ data: [
+ 0.5, 1.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 0.5, 0.0, 1.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_SecondaryColor": {
+ data: [
+ 0.5, 0.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 0.5, 1.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_Normal": {
+ data: [
+ 0.5, 0.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 0.5, 1.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_MultiTexCoord0": {
+ data: [
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 0.0,
+ 0.0, 1.0
+ ],
+ numComponents: 2,
+ },
+ "gtf_FogCoord": {
+ data: [
+ 0.0,
+ 1.0,
+ 0.0,
+ 1.0
+ ],
+ numComponents: 1,
+ }
+ };
+ setAttribs(attribs, buffers);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+}
+
+function drawFrontBackSquare(attribs) {
+ var front = {
+ "gtf_Vertex": {
+ data: [
+ 1.0, -1.0, -2.0,
+ 1.0, 0.0, -2.0,
+ -1.0, -1.0, -2.0,
+ -1.0, 0.0, -2.0
+ ],
+ numComponents: 3
+ },
+ "gtf_Color": {
+ data: [
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_MultiTexCoord0": {
+ data: [
+ 1.0, 0.0,
+ 1.0, 0.5,
+ 0.0, 0.0,
+ 0.0, 0.5
+ ],
+ numComponents: 2,
+ }
+ };
+ setAttribs(attribs, front);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ var back = {
+ "gtf_Vertex": {
+ data: [
+ 1.0, 1.0, -2.0,
+ 1.0, 0.0, -2.0,
+ -1.0, 1.0, -2.0,
+ -1.0, 0.0, -2.0
+ ],
+ numComponents: 3
+ },
+ "gtf_Color": {
+ data: [
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_MultiTexCoord0": {
+ data: [
+ 1.0, 0.1,
+ 1.0, 0.5,
+ 0.0, 0.1,
+ 0.0, 0.5
+ ],
+ numComponents: 2,
+ }
+ };
+ setAttribs(attribs, back);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+}
+
+function drawGrid(attribs, width, height) {
+ var n = Math.min(Math.floor(Math.max(width, height) / 4), HALF_GRID_MAX_SIZE);
+
+ var numVertices = (n + n) * (n + n) * 6;
+
+ var gridVertices = [];
+ var gridColors = [];
+ var gridSecColors = [];
+ var gridNormals = [];
+ var gridFogCoords = [];
+ var gridTexCoords0 = [];
+
+ var currentVertex = 0;
+ var currentColor = 0;
+ var currentSecColor = 0;
+ var currentTexCoord0 = 0;
+ var currentNormal = 0;
+ var currentFogCoord = 0;
+
+ var z = -2.0;
+ for(var i = -n; i < n; ++i)
+ {
+ var x1 = i / n;
+ var x2 = (i + 1) / n;
+ for(var j = -n; j < n; ++j)
+ {
+ var y1 = j / n;
+ var y2 = (j + 1) / n;
+
+ // VERTEX 0
+ gridVertices[currentVertex++] = x1;
+ gridVertices[currentVertex++] = y1;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x1 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
+
+ // VERTEX 1
+ gridVertices[currentVertex++] = x2;
+ gridVertices[currentVertex++] = y1;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x2 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
+
+ // VERTEX 2
+ gridVertices[currentVertex++] = x2;
+ gridVertices[currentVertex++] = y2;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x2 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
+
+ // VERTEX 2
+ gridVertices[currentVertex++] = x2;
+ gridVertices[currentVertex++] = y2;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x2 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
+
+ // VERTEX 3
+ gridVertices[currentVertex++] = x1;
+ gridVertices[currentVertex++] = y2;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x1 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
+
+ // VERTEX 0
+ gridVertices[currentVertex++] = x1;
+ gridVertices[currentVertex++] = y1;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x1 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
+ }
+ }
+
+ var buffers = {
+ "gtf_Vertex": { data: gridVertices, numComponents: 3 },
+ "gtf_Color": { data: gridColors, numComponents: 3 },
+ "gtf_SecondaryColor": { data: gridSecColors, numComponents: 3 },
+ "gtf_Normal": { data: gridNormals, numComponents: 3 },
+ "gtf_FogCoord": { data: gridFogCoords, numComponents: 1 },
+ "gtf_MultiTexCoord0": { data: gridTexCoords0, numComponents: 2 }
+ };
+ setAttribs(attribs, buffers);
+ gl.drawArrays(gl.TRIANGLES, 0, numVertices);
+}
+
+var MODEL_FUNCS = {
+ square: drawSquare,
+ frontbacksquare: drawFrontBackSquare,
+ grid: drawGrid
+};
+
+function drawWithProgram(program, programInfo, test) {
+ gl.useProgram(program);
+ var attribs = { };
+
+ var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
+ for (var ii = 0; ii < numAttribs; ++ii) {
+ var info = gl.getActiveAttrib(program, ii);
+ var name = info.name;
+ var location = gl.getAttribLocation(program, name);
+ attribs[name] = location;
+
+ if (KNOWN_ATTRIBS.indexOf(name) < 0) {
+ testFailed("unknown attrib:" + name)
+ }
+ }
+
+ var uniforms = { };
+ var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ for (var ii = 0; ii < numUniforms; ++ii) {
+ var info = gl.getActiveUniform(program, ii);
+ var name = info.name;
+ if (name.match(/\[0\]$/)) {
+ name = name.substr(0, name.length - 3);
+ }
+ var location = gl.getUniformLocation(program, name);
+ uniforms[name] = {location: location};
+ }
+
+ var getUniformLocation = function(name) {
+ var uniform = uniforms[name];
+ if (uniform) {
+ uniform.used = true;
+ return uniform.location;
+ }
+ return null;
+ }
+
+ // Set known uniforms
+ var loc = getUniformLocation("gtf_ModelViewProjectionMatrix");
+ if (loc) {
+ gl.uniformMatrix4fv(
+ loc,
+ false,
+ persp(60, 1, 1, 30));
+ }
+ var loc = getUniformLocation("viewportwidth");
+ if (loc) {
+ gl.uniform1f(loc, gl.canvas.width);
+ }
+ var loc = getUniformLocation("viewportheight");
+ if (loc) {
+ gl.uniform1f(loc, gl.canvas.height);
+ }
+
+ // Set test specific uniforms
+ for (var name in programInfo.uniforms) {
+ var location = getUniformLocation(name);
+ if (!location) {
+ continue;
+ }
+ var uniform = programInfo.uniforms[name];
+ var type = uniform.type;
+ var value = uniform.value;
+ var transpose = uniform.transpose;
+ if (transpose !== undefined) {
+ log("gl." + type + '("' + name + '", ' + transpose + ", " + value + ")");
+ gl[type](location, transpose, value);
+ } else if (!type.match("v$")) {
+ var args = [location];
+ for (var ii = 0; ii < value.length; ++ii) {
+ args.push(value[ii]);
+ }
+ gl[type].apply(gl, args);
+ log("gl." + type + '("' + name + '", ' + args.slice(1) + ")");
+ } else {
+ log("gl." + type + '("' + name + '", ' + value + ")");
+ gl[type](location, value);
+ }
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ testFailed(wtu.glEnumToString(gl, err) + " generated setting uniform: " + name);
+ }
+ }
+
+ // Filter out specified built-in uniforms
+ if (programInfo.builtin_uniforms) {
+ var num_builtins_found = 0;
+ var valid_values = programInfo.builtin_uniforms.valid_values;
+ for (var index in valid_values) {
+ var uniform = uniforms[valid_values[index]];
+ if (uniform) {
+ ++num_builtins_found;
+ uniform.builtin = true;
+ }
+ }
+
+ var min_required = programInfo.builtin_uniforms.min_required;
+ if (num_builtins_found < min_required) {
+ testFailed("only found " + num_builtins_found + " of " + min_required +
+ " required built-in uniforms: " + valid_values);
+ }
+ }
+
+ // Check for unset uniforms
+ for (var name in uniforms) {
+ var uniform = uniforms[name];
+ if (!uniform.used && !uniform.builtin) {
+ testFailed("uniform " + name + " never set");
+ }
+ }
+
+
+ for (var state in test.state) {
+ var fields = test.state[state];
+ switch (state) {
+ case 'depthrange':
+ gl.depthRange(fields.near, fields.far);
+ break;
+ default:
+ testFailed("unknown state: " + state)
+ }
+ }
+
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var model = test.model || "square";
+ var fn = MODEL_FUNCS[model];
+ if (!fn) {
+ testFailed("unknown model type: " + model)
+ } else {
+ log("draw as: " + model)
+ fn(attribs, gl.canvas.width, gl.canvas.height);
+ }
+
+ var pixels = new Uint8Array(gl.canvas.width * gl.canvas.height * 4);
+ gl.readPixels(0, 0, gl.canvas.width, gl.canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ return {
+ width: gl.canvas.width,
+ height: gl.canvas.height,
+ pixels: pixels,
+ img: wtu.makeImageFromCanvas(gl.canvas)
+ };
+}
+
+function runProgram(programInfo, test, label, callback) {
+ var shaders = [];
+ var source = [];
+ var count = 0;
+
+ function loadShader(path, type, index) {
+ wtu.loadTextFileAsync(path, function(success, text) {
+ addShader(success, text, type, path, index);
+ });
+ }
+
+ function addShader(success, text, type, path, index) {
+ ++count;
+ if (!success) {
+ testFailed("could not load: " + path);
+ } else {
+ var shader = wtu.loadShader(gl, text, type);
+ shaders.push(shader);
+ source[index] = text;
+ }
+ if (count == 2) {
+ var result;
+ if (shaders.length == 2) {
+ debug("");
+ if (!quietMode()) {
+ var consoleDiv = document.getElementById("console");
+ wtu.addShaderSources(
+ gl, consoleDiv, label + " vertex shader", shaders[0], source[0],
+ programInfo.vertexShader);
+ wtu.addShaderSources(
+ gl, consoleDiv, label + " fragment shader", shaders[1], source[1],
+ programInfo.fragmentShader);
+ }
+ var program = wtu.createProgram(gl, shaders[0], shaders[1]);
+ result = drawWithProgram(program, programInfo, test);
+ }
+ callback(result);
+ }
+ }
+
+ loadShader(programInfo.vertexShader, gl.VERTEX_SHADER, 0);
+ loadShader(programInfo.fragmentShader, gl.FRAGMENT_SHADER, 1);
+}
+
+function compareResults(expected, actual) {
+ var width = expected.width;
+ var height = expected.height;
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ var imgData = ctx.getImageData(0, 0, width, height);
+ var tolerance = 0;
+
+ var expData = expected.pixels;
+ var actData = actual.pixels;
+
+ var same = compareImages(expData, actData, width, height, imgData.data);
+
+ var console = document.getElementById("console");
+ var diffImg = null;
+ if (!same) {
+ ctx.putImageData(imgData, 0, 0);
+ diffImg = wtu.makeImageFromCanvas(canvas);
+ }
+
+ if (!quietMode()) {
+ var div = document.createElement("div");
+ div.className = "testimages";
+ wtu.insertImage(div, "reference", expected.img);
+ wtu.insertImage(div, "test", actual.img);
+ if (diffImg) {
+ wtu.insertImage(div, "diff", diffImg);
+ }
+ div.appendChild(document.createElement('br'));
+
+ console.appendChild(div);
+ }
+
+ if (!same) {
+ testFailed("images are different");
+ } else {
+ testPassed("images are the same");
+ }
+
+ if (!quietMode())
+ console.appendChild(document.createElement('hr'));
+}
+
+function runCompareTest(test, callback) {
+ debug("");
+ debug("test: " + test.name);
+ var results = [];
+ var count = 0;
+
+ function storeResults(index) {
+ return function(result) {
+ results[index] = result;
+ ++count;
+ if (count == 2) {
+ compareResults(results[0], results[1]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ callback();
+ }
+ }
+ }
+
+ runProgram(test.referenceProgram, test, "reference", storeResults(0));
+ runProgram(test.testProgram, test, "test", storeResults(1));
+}
+
+function runBuildTest(test, callback) {
+ debug("");
+ debug("test: " + test.name);
+
+ var shaders = [null, null];
+ var source = ["",""];
+ var success = [undefined, undefined];
+ var count = 0;
+
+ function loadShader(path, type, index) {
+ if (path == "empty") {
+ shaders[index] = gl.createShader();
+ success[index] = true;
+ source[index] = "/* empty */";
+ attachAndLink();
+ } else {
+ wtu.loadTextFileAsync(path, function(loadSuccess, text) {
+ if (!loadSuccess) {
+ success[index] = false;
+ source[index] = "/* could not load */";
+ testFailed("could not load:" + path);
+ } else {
+ source[index] = text;
+ shaders[index] = wtu.loadShader(gl, text, type, function(index) {
+ return function(msg) {
+ success[index] = false
+ }
+ }(index));
+ if (success[index] === undefined) {
+ success[index] = true;
+ }
+ }
+ attachAndLink();
+ });
+ }
+ }
+
+ function attachAndLink() {
+ ++count;
+ if (count == 2) {
+ if (!quietMode()) {
+ debug("");
+ var c = document.getElementById("console");
+ wtu.addShaderSource(
+ c, "vertex shader", source[0], test.testProgram.vertexShader);
+ debug("compile: " + (success[0] ? "success" : "fail"));
+ wtu.addShaderSource(
+ c, "fragment shader", source[1], test.testProgram.fragmentShader);
+ debug("compile: " + (success[1] ? "success" : "fail"));
+ }
+ compileSuccess = (success[0] && success[1]);
+ if (!test.compstat) {
+ if (compileSuccess) {
+ testFailed("expected compile failure but was successful");
+ } else {
+ testPassed("expected compile failure and it failed");
+ }
+ } else {
+ if (compileSuccess) {
+ testPassed("expected compile success and it was successful");
+ } else {
+ testFailed("expected compile success but it failed");
+ }
+ var linkSuccess = true;
+ var program = wtu.createProgram(gl, shaders[0], shaders[1], function() {
+ linkSuccess = false;
+ });
+ if (linkSuccess !== test.linkstat) {
+ testFailed("expected link to " + (test.linkstat ? "succeed" : "fail"));
+ } else {
+ testPassed("shaders compiled and linked as expected.");
+ }
+ }
+ callback();
+ }
+ }
+
+ loadShader(test.testProgram.vertexShader, gl.VERTEX_SHADER, 0);
+ loadShader(test.testProgram.fragmentShader, gl.FRAGMENT_SHADER, 1);
+}
+
+var testPatterns = {
+ compare: runCompareTest,
+ build: runBuildTest,
+
+ dummy: null // just here to mark the end
+};
+
+function LogGLCall(functionName, args) {
+ console.log("gl." + functionName + "(" +
+ WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")");
+}
+
+// Runs the tests async since they will load shaders.
+function run(obj) {
+ description();
+
+ var canvas = document.getElementById("example");
+ gl = wtu.create3DContext(canvas);
+ if (window.WebGLDebugUtils) {
+ gl = WebGLDebugUtils.makeDebugContext(gl, undefined, LogGLCall);
+ }
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ if (gl.canvas.width != 500 || gl.canvas.height != 500) {
+ testFailed("canvas must be 500x500 pixels: Several shaders are hard coded to this size.");
+ }
+
+ var tests = obj.tests;
+ var ndx = 0;
+
+ function runNextTest() {
+ if (ndx < tests.length) {
+ var test = tests[ndx++];
+ var fn = testPatterns[test.pattern];
+ if (!fn) {
+ testFailed("test pattern: " + test.pattern + " not supoprted")
+ runNextTest();
+ } else {
+ fn(test, runNextTest);
+ }
+ } else {
+ finishTest();
+ }
+ }
+ runNextTest();
+}
+
+return {
+ run: run,
+};
+}());
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/process-ogles2-tests.py b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/process-ogles2-tests.py
new file mode 100644
index 0000000000..49d9f874d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/process-ogles2-tests.py
@@ -0,0 +1,568 @@
+#! /usr/bin/env python2
+
+"""generates tests from OpenGL ES 2.0 .run/.test files."""
+
+import os
+import os.path
+import sys
+import re
+import json
+import shutil
+from optparse import OptionParser
+from xml.dom.minidom import parse
+
+if sys.version < '2.6':
+ print 'Wrong Python Version !!!: Need >= 2.6'
+ sys.exit(1)
+
+# each shader test generates up to 3 512x512 images.
+# a 512x512 image takes 1meg of memory so set this
+# number apporpriate for the platform with
+# the smallest memory issue. At 8 that means
+# at least 24 meg is needed to run the test.
+MAX_TESTS_PER_SET = 8
+
+VERBOSE = False
+
+FILTERS = [
+ re.compile("GL/"),
+]
+
+LICENSE = """
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+""".strip()
+
+COMMENT_RE = re.compile("/\*\n\*\*\s+Copyright.*?\*/",
+ re.IGNORECASE | re.DOTALL)
+REMOVE_COPYRIGHT_RE = re.compile("\/\/\s+Copyright.*?\n",
+ re.IGNORECASE | re.DOTALL)
+MATRIX_RE = re.compile("Matrix(\\d)")
+
+VALID_UNIFORM_TYPES = [
+ "uniform1f",
+ "uniform1fv",
+ "uniform1fv",
+ "uniform1i",
+ "uniform1iv",
+ "uniform1iv",
+ "uniform2f",
+ "uniform2fv",
+ "uniform2fv",
+ "uniform2i",
+ "uniform2iv",
+ "uniform2iv",
+ "uniform3f",
+ "uniform3fv",
+ "uniform3fv",
+ "uniform3i",
+ "uniform3iv",
+ "uniform3iv",
+ "uniform4f",
+ "uniform4fv",
+ "uniform4fv",
+ "uniform4i",
+ "uniform4iv",
+ "uniform4ivy",
+ "uniformMatrix2fv",
+ "uniformMatrix2fv",
+ "uniformMatrix3fv",
+ "uniformMatrix3fv",
+ "uniformMatrix4fv",
+ "uniformMatrix4fv",
+]
+
+SUBSTITUTIONS = [
+ ("uniformmat3fv", "uniformMatrix3fv"),
+ ("uniformmat4fv", "uniformMatrix4fv"),
+]
+
+
+def Log(msg):
+ global VERBOSE
+ if VERBOSE:
+ print msg
+
+
+def TransposeMatrix(values, dim):
+ size = dim * dim
+ count = len(values) / size
+ for m in range(0, count):
+ offset = m * size
+ for i in range(0, dim):
+ for j in range(i + 1, dim):
+ t = values[offset + i * dim + j]
+ values[offset + i * dim + j] = values[offset + j * dim + i]
+ values[offset + j * dim + i] = t
+
+
+def GetValidTypeName(type_name):
+ global VALID_UNIFORM_TYPES
+ global SUBSTITUTIONS
+ for subst in SUBSTITUTIONS:
+ type_name = type_name.replace(subst[0], subst[1])
+ if not type_name in VALID_UNIFORM_TYPES:
+ print "unknown type name: ", type_name
+ raise SyntaxError
+ return type_name
+
+
+def WriteOpen(filename):
+ dirname = os.path.dirname(filename)
+ if len(dirname) > 0 and not os.path.exists(dirname):
+ os.makedirs(dirname)
+ return open(filename, "wb")
+
+
+class TxtWriter():
+ def __init__(self, filename):
+ self.filename = filename
+ self.lines = []
+
+ def Write(self, line):
+ self.lines.append(line)
+
+ def Close(self):
+ if len(self.lines) > 0:
+ Log("Writing: %s" % self.filename)
+ f = WriteOpen(self.filename)
+ f.write("# this file is auto-generated. DO NOT EDIT.\n")
+ f.write("".join(self.lines))
+ f.close()
+
+
+def ReadFileAsLines(filename):
+ f = open(filename, "r")
+ lines = f.readlines()
+ f.close()
+ return [line.strip() for line in lines]
+
+
+def ReadFile(filename):
+ f = open(filename, "r")
+ content = f.read()
+ f.close()
+ return content.replace("\r\n", "\n")
+
+
+def Chunkify(list, chunk_size):
+ """divides an array into chunks of chunk_size"""
+ return [list[i:i + chunk_size] for i in range(0, len(list), chunk_size)]
+
+
+def GetText(nodelist):
+ """Gets the text of from a list of nodes"""
+ rc = []
+ for node in nodelist:
+ if node.nodeType == node.TEXT_NODE:
+ rc.append(node.data)
+ return ''.join(rc)
+
+
+def GetElementText(node, name):
+ """Gets the text of an element"""
+ elements = node.getElementsByTagName(name)
+ if len(elements) > 0:
+ return GetText(elements[0].childNodes)
+ else:
+ return None
+
+
+def GetBoolElement(node, name):
+ text = GetElementText(node, name)
+ return text.lower() == "true"
+
+
+def GetModel(node):
+ """Gets the model"""
+ model = GetElementText(node, "model")
+ if model and len(model.strip()) == 0:
+ elements = node.getElementsByTagName("model")
+ if len(elements) > 0:
+ model = GetElementText(elements[0], "filename")
+ return model
+
+
+def RelativizePaths(base, paths, template):
+ """converts paths to relative paths"""
+ rels = []
+ for p in paths:
+ #print "---"
+ #print "base: ", os.path.abspath(base)
+ #print "path: ", os.path.abspath(p)
+ relpath = os.path.relpath(os.path.abspath(p), os.path.dirname(os.path.abspath(base))).replace("\\", "/")
+ #print "rel : ", relpath
+ rels.append(template % relpath)
+ return "\n".join(rels)
+
+
+def CopyFile(filename, src, dst):
+ s = os.path.abspath(os.path.join(os.path.dirname(src), filename))
+ d = os.path.abspath(os.path.join(os.path.dirname(dst), filename))
+ dst_dir = os.path.dirname(d)
+ if not os.path.exists(dst_dir):
+ os.makedirs(dst_dir)
+ shutil.copyfile(s, d)
+
+
+def CopyShader(filename, src, dst):
+ s = os.path.abspath(os.path.join(os.path.dirname(src), filename))
+ d = os.path.abspath(os.path.join(os.path.dirname(dst), filename))
+ text = ReadFile(s)
+ # By agreement with the Khronos OpenGL working group we are allowed
+ # to open source only the .vert and .frag files from the OpenGL ES 2.0
+ # conformance tests. All other files from the OpenGL ES 2.0 conformance
+ # tests are not included.
+ marker = "insert-copyright-here"
+ new_text = COMMENT_RE.sub(marker, text)
+ if new_text == text:
+ print "no matching license found:", s
+ raise RuntimeError
+ new_text = REMOVE_COPYRIGHT_RE.sub("", new_text)
+ glsl_license = '/*\n' + LICENSE + '\n*/'
+ new_text = new_text.replace(marker, glsl_license)
+ f = WriteOpen(d)
+ f.write(new_text)
+ f.close()
+
+
+def IsOneOf(string, regexs):
+ for regex in regexs:
+ if re.match(regex, string):
+ return True
+ return False
+
+
+def CheckForUnknownTags(valid_tags, node, depth=1):
+ """do a hacky check to make sure we're not missing something."""
+ for child in node.childNodes:
+ if child.localName and not IsOneOf(child.localName, valid_tags[0]):
+ print "unsupported tag:", child.localName
+ print "depth:", depth
+ raise SyntaxError
+ else:
+ if len(valid_tags) > 1:
+ CheckForUnknownTags(valid_tags[1:], child, depth + 1)
+
+
+def IsFileWeWant(filename):
+ for f in FILTERS:
+ if f.search(filename):
+ return True
+ return False
+
+
+class TestReader():
+ """class to read and parse tests"""
+
+ def __init__(self, basepath):
+ self.tests = []
+ self.modes = {}
+ self.patterns = {}
+ self.basepath = basepath
+
+ def Print(self, msg):
+ if self.verbose:
+ print msg
+
+ def MakeOutPath(self, filename):
+ relpath = os.path.relpath(os.path.abspath(filename), os.path.dirname(os.path.abspath(self.basepath)))
+ return relpath
+
+ def ReadTests(self, filename):
+ """reads a .run file and parses."""
+ Log("reading %s" % filename)
+ outname = self.MakeOutPath(filename + ".txt")
+ f = TxtWriter(outname)
+ dirname = os.path.dirname(filename)
+ lines = ReadFileAsLines(filename)
+ count = 0
+ tests_data = []
+ for line in lines:
+ if len(line) > 0 and not line.startswith("#"):
+ fname = os.path.join(dirname, line)
+ if line.endswith(".run"):
+ if self.ReadTests(fname):
+ f.Write(line + ".txt\n")
+ count += 1
+ elif line.endswith(".test"):
+ tests_data.extend(self.ReadTest(fname))
+ else:
+ print "Error in %s:%d:%s" % (filename, count, line)
+ raise SyntaxError()
+ if len(tests_data):
+ global MAX_TESTS_PER_SET
+ sets = Chunkify(tests_data, MAX_TESTS_PER_SET)
+ id = 1
+ for set in sets:
+ suffix = "_%03d_to_%03d" % (id, id + len(set) - 1)
+ test_outname = self.MakeOutPath(filename + suffix + ".html")
+ if os.path.basename(test_outname).startswith("input.run"):
+ dname = os.path.dirname(test_outname)
+ folder_name = os.path.basename(dname)
+ test_outname = os.path.join(dname, folder_name + suffix + ".html")
+ self.WriteTests(filename, test_outname, {"tests":set})
+ f.Write(os.path.basename(test_outname) + "\n")
+ id += len(set)
+ count += 1
+ f.Close()
+ return count
+
+ def ReadTest(self, filename):
+ """reads a .test file and parses."""
+ Log("reading %s" % filename)
+ dom = parse(filename)
+ tests = dom.getElementsByTagName("test")
+ tests_data = []
+ outname = self.MakeOutPath(filename + ".html")
+ for test in tests:
+ if not IsFileWeWant(filename):
+ self.CopyShaders(test, filename, outname)
+ else:
+ test_data = self.ProcessTest(test, filename, outname, len(tests_data))
+ if test_data:
+ tests_data.append(test_data)
+ return tests_data
+
+ def ProcessTest(self, test, filename, outname, id):
+ """Process a test"""
+ mode = test.getAttribute("mode")
+ pattern = test.getAttribute("pattern")
+ self.modes[mode] = 1
+ self.patterns[pattern] = 1
+ Log ("%d: mode: %s pattern: %s" % (id, mode, pattern))
+ method = getattr(self, 'Process_' + pattern)
+ test_data = method(test, filename, outname)
+ if test_data:
+ test_data["pattern"] = pattern
+ return test_data
+
+ def WriteTests(self, filename, outname, tests_data):
+ Log("Writing %s" % outname)
+ template = """<!DOCTYPE html>
+<!-- this file is auto-generated. DO NOT EDIT. -->
+%(license)s
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL conformance test: %(title)s</title>
+%(css)s
+%(scripts)s
+</head>
+<body>
+<canvas id="example" width="500" height="500" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+<script>
+"use strict";
+OpenGLESTestRunner.run(%(tests_data)s);
+var successfullyParsed = true;
+</script>
+</html>
+"""
+ css = [
+ "../../resources/js-test-style.css",
+ "../../resources/ogles-tests.css",
+ ]
+ scripts = [
+ "../../resources/js-test-pre.js",
+ "../../resources/webgl-test-utils.js",
+ "ogles-utils.js",
+ ]
+ css_html = RelativizePaths(outname, css, '<link rel="stylesheet" href="%s" />')
+ scripts_html = RelativizePaths(outname, scripts, '<script src="%s"></script>')
+
+ html_license = '<!--\n' + LICENSE + '\n-->'
+ f = WriteOpen(outname)
+ f.write(template % {
+ "license": html_license,
+ "css": css_html,
+ "scripts": scripts_html,
+ "title": os.path.basename(outname),
+ "tests_data": json.dumps(tests_data, indent=2)
+ })
+ f.close()
+
+
+ def CopyShaders(self, test, filename, outname):
+ """For tests we don't actually support yet, at least copy the shaders"""
+ shaders = test.getElementsByTagName("shader")
+ for shader in shaders:
+ for name in ["vertshader", "fragshader"]:
+ s = GetElementText(shader, name)
+ if s and s != "empty":
+ CopyShader(s, filename, outname)
+
+ #
+ # pattern handlers.
+ #
+
+ def Process_compare(self, test, filename, outname):
+ global MATRIX_RE
+
+ valid_tags = [
+ ["shader", "model", "glstate"],
+ ["uniform", "vertshader", "fragshader", "filename", "depthrange"],
+ ["name", "count", "transpose", "uniform*", "near", "far"],
+ ]
+ CheckForUnknownTags(valid_tags, test)
+
+ # parse the test
+ shaders = test.getElementsByTagName("shader")
+ shaderInfos = []
+ for shader in shaders:
+ v = GetElementText(shader, "vertshader")
+ f = GetElementText(shader, "fragshader")
+ CopyShader(v, filename, outname)
+ CopyShader(f, filename, outname)
+ info = {
+ "vertexShader": v,
+ "fragmentShader": f,
+ }
+ shaderInfos.append(info)
+ uniformElems = shader.getElementsByTagName("uniform")
+ if len(uniformElems) > 0:
+ uniforms = {}
+ info["uniforms"] = uniforms
+ for uniformElem in uniformElems:
+ uniform = {"count": 1}
+ for child in uniformElem.childNodes:
+ if child.localName == None:
+ pass
+ elif child.localName == "name":
+ uniforms[GetText(child.childNodes)] = uniform
+ elif child.localName == "count":
+ uniform["count"] = int(GetText(child.childNodes))
+ elif child.localName == "transpose":
+ uniform["transpose"] = (GetText(child.childNodes) == "true")
+ else:
+ if "type" in uniform:
+ print "utype was:", uniform["type"], " found ", child.localName
+ raise SyntaxError
+ type_name = GetValidTypeName(child.localName)
+ uniform["type"] = type_name
+ valueText = GetText(child.childNodes).replace(",", " ")
+ uniform["value"] = [float(t) for t in valueText.split()]
+ m = MATRIX_RE.search(type_name)
+ if m:
+ # Why are these backward from the API?!?!?
+ TransposeMatrix(uniform["value"], int(m.group(1)))
+ data = {
+ "name": os.path.basename(outname),
+ "model": GetModel(test),
+ "referenceProgram": shaderInfos[1],
+ "testProgram": shaderInfos[0],
+ }
+ gl_states = test.getElementsByTagName("glstate")
+ if len(gl_states) > 0:
+ state = {}
+ data["state"] = state
+ for gl_state in gl_states:
+ for state_name in gl_state.childNodes:
+ if state_name.localName:
+ values = {}
+ for field in state_name.childNodes:
+ if field.localName:
+ values[field.localName] = GetText(field.childNodes)
+ state[state_name.localName] = values
+ return data
+
+ def Process_shaderload(self, test, filename, outname):
+ """no need for shaderload tests"""
+ self.CopyShaders(test, filename, outname)
+
+ def Process_extension(self, test, filename, outname):
+ """no need for extension tests"""
+ self.CopyShaders(test, filename, outname)
+
+ def Process_createtests(self, test, filename, outname):
+ Log("createtests Not implemented: %s" % filename)
+ self.CopyShaders(test, filename, outname)
+
+ def Process_GL2Test(self, test, filename, outname):
+ Log("GL2Test Not implemented: %s" % filename)
+ self.CopyShaders(test, filename, outname)
+
+ def Process_uniformquery(self, test, filename, outname):
+ Log("uniformquery Not implemented: %s" % filename)
+ self.CopyShaders(test, filename, outname)
+
+ def Process_egl_image_external(self, test, filename, outname):
+ """no need for egl_image_external tests"""
+ self.CopyShaders(test, filename, outname)
+
+ def Process_dismount(self, test, filename, outname):
+ Log("dismount Not implemented: %s" % filename)
+ self.CopyShaders(test, filename, outname)
+
+ def Process_build(self, test, filename, outname):
+ """don't need build tests"""
+ valid_tags = [
+ ["shader", "compstat", "linkstat"],
+ ["vertshader", "fragshader"],
+ ]
+ CheckForUnknownTags(valid_tags, test)
+
+ shader = test.getElementsByTagName("shader")
+ if not shader:
+ return None
+ vs = GetElementText(shader[0], "vertshader")
+ fs = GetElementText(shader[0], "fragshader")
+ if vs and vs != "empty":
+ CopyShader(vs, filename, outname)
+ if fs and fs != "empty":
+ CopyShader(fs, filename, outname)
+ data = {
+ "name": os.path.basename(outname),
+ "compstat": bool(GetBoolElement(test, "compstat")),
+ "linkstat": bool(GetBoolElement(test, "linkstat")),
+ "testProgram": {
+ "vertexShader": vs,
+ "fragmentShader": fs,
+ },
+ }
+ attach = test.getElementsByTagName("attach")
+ if len(attach) > 0:
+ data["attachError"] = GetElementText(attach[0], "attacherror")
+ return data
+
+ def Process_coverage(self, test, filename, outname):
+ Log("coverage Not implemented: %s" % filename)
+ self.CopyShaders(test, filename, outname)
+
+ def Process_attributes(self, test, filename, outname):
+ Log("attributes Not implemented: %s" % filename)
+ self.CopyShaders(test, filename, outname)
+
+ def Process_fixed(self, test, filename, outname):
+ """no need for fixed function tests"""
+ self.CopyShaders(test, filename, outname)
+
+
+def main(argv):
+ """This is the main function."""
+ global VERBOSE
+
+ parser = OptionParser()
+ parser.add_option(
+ "-v", "--verbose", action="store_true",
+ help="prints more output.")
+
+ (options, args) = parser.parse_args(args=argv)
+
+ if len(args) < 1:
+ pass # fix me
+
+ os.chdir(os.path.dirname(__file__) or '.')
+
+ VERBOSE = options.verbose
+
+ filename = args[0]
+ test_reader = TestReader(filename)
+ test_reader.ReadTests(filename)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/programs/00_test_list.txt
new file mode 100644
index 0000000000..061caa574a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/00_test_list.txt
@@ -0,0 +1,12 @@
+get-active-test.html
+gl-bind-attrib-location-test.html
+--min-version 1.0.2 gl-bind-attrib-location-long-names-test.html
+gl-get-active-attribute.html
+gl-get-active-uniform.html
+gl-getshadersource.html
+gl-shader-test.html
+invalid-UTF-16.html
+--min-version 1.0.4 program-handling.html
+--min-version 1.0.4 program-infolog.html
+program-test.html
+--min-version 1.0.2 use-program-crash-with-discard-in-fragment-shader.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/get-active-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/get-active-test.html
new file mode 100644
index 0000000000..ce2b4f9b1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/get-active-test.html
@@ -0,0 +1,119 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test of getActiveAttrib and getActiveUniform");
+
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var context2 = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+var program2 = wtu.loadProgramFromFile(context2,
+ "../../resources/intArrayUniformShader.vert",
+ "../../resources/noopUniformShader.frag");
+
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+shouldBe("context.getActiveUniform(program, 0).name", "'u_modelViewProjMatrix'");
+shouldBe("context.getActiveUniform(program, 0).type", "context.FLOAT_MAT4");
+shouldBe("context.getActiveUniform(program, 0).size", "1");
+shouldBeNull("context.getActiveUniform(program, 1)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+shouldBeNull("context.getActiveUniform(program, -1)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+shouldThrow("context.getActiveUniform(null, 0)");
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+
+// we don't know the order the attribs will appear.
+var info = [
+ context.getActiveAttrib(program, 0),
+ context.getActiveAttrib(program, 1)
+];
+for (var ii = 0; ii < info.length; ++ii)
+ shouldBeNonNull("info[ii]");
+
+var expected = [
+ { name: 'a_normal', type: context.FLOAT_VEC3, size: 1 },
+ { name: 'a_vertex', type: context.FLOAT_VEC4, size: 1 }
+];
+
+if (info[0].name != expected[0].name) {
+ var t = info[0];
+ info[0] = info[1];
+ info[1] = t;
+}
+
+for (var ii = 0; ii < info.length; ++ii) {
+ shouldBe("info[ii].name", "expected[ii].name");
+ shouldBe("info[ii].type", "expected[ii].type");
+ shouldBe("info[ii].size", "expected[ii].size");
+}
+
+// we don't know the order the uniforms will appear.
+var info2 = [
+ context2.getActiveUniform(program2, 0),
+ context2.getActiveUniform(program2, 1)
+];
+for (var ii = 0; ii < info2.length; ++ii)
+ shouldBeNonNull("info2[ii]");
+
+var expected2 = [
+ { name: 'ival', type: context2.INT, size: 1 },
+ { name: 'ival2[0]', type: context2.INT, size: 2 }
+];
+
+if (info2[0].name != expected2[0].name) {
+ t = info2[0];
+ info2[0] = info2[1];
+ info2[1] = t;
+}
+
+for (var ii = 0; ii < info2.length; ++ii) {
+ shouldBe("info2[ii].name", "expected2[ii].name");
+ shouldBe("info2[ii].type", "expected2[ii].type");
+ shouldBe("info2[ii].size", "expected2[ii].size");
+}
+
+shouldBeNull("context.getActiveAttrib(program, 2)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+shouldBeNull("context.getActiveAttrib(program, -1)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+shouldThrow("context.getActiveAttrib(null, 0)");
+wtu.glErrorShouldBe(context, context.NO_ERROR);
+
+wtu.glErrorShouldBe(context2, context.NO_ERROR);
+
+debug("Check trying to get attribs from different context");
+shouldBeNull("context2.getActiveAttrib(program, 0)");
+wtu.glErrorShouldBe(context2, context2.INVALID_OPERATION);
+shouldBeNull("context2.getActiveUniform(program, 0)");
+wtu.glErrorShouldBe(context2, context2.INVALID_OPERATION);
+
+debug("Check trying to get attribs from deleted program");
+context.deleteProgram(program);
+shouldBeNull("context.getActiveUniform(program, 0)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+shouldBeNull("context.getActiveAttrib(program, 0)");
+wtu.glErrorShouldBe(context, context.INVALID_VALUE);
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-long-names-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-long-names-test.html
new file mode 100644
index 0000000000..90328bee45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-long-names-test.html
@@ -0,0 +1,153 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BindAttribLocation Long Names Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas style="border: 1px solid black;" id="canvas" width="50" height="50"></canvas>
+<script id="vshader" type="text/something-not-javascript">
+attribute vec4 vPosition$(suffix);
+attribute vec4 vColor$(suffix);
+varying vec4 color;
+void main()
+{
+ gl_Position = vPosition$(suffix);
+ color = vColor$(suffix);
+}
+</script>
+<script id="fshader" type="text/something-not-javascript">
+precision mediump float;
+
+varying vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("This test checks using long names with bindAttribLocation work.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+shouldBeNonNull("gl");
+
+debug("");
+debug("Checking gl.bindAttribLocation with long names.");
+
+var program = gl.createProgram();
+
+var suffix = "long";
+for (var ii = 0; ii < 5; ++ii) {
+ suffix = suffix + suffix;
+}
+var replacements = {
+ suffix: suffix
+};
+
+var vsrc = wtu.replaceParams(wtu.getScript("vshader"), replacements);
+var fsrc = wtu.replaceParams(wtu.getScript("fshader"), replacements);
+
+var vs = wtu.loadShader(gl, vsrc, gl.VERTEX_SHADER);
+var fs = wtu.loadShader(gl, fsrc, gl.FRAGMENT_SHADER);
+
+var attribs = {
+ vPosition: "vPosition" + suffix,
+ vColor: "vColor" + suffix
+};
+
+gl.attachShader(program, vs);
+gl.attachShader(program, fs);
+
+var positions = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positions);
+gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, -1.0, 0.0]),
+ gl.STATIC_DRAW);
+
+var colors = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colors);
+gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [ 0,1,0,1,
+ 0,1,0,1,
+ 0,1,0,1,
+ 0,1,0,1,
+ 0,1,0,1,
+ 0,1,0,1]),
+ gl.STATIC_DRAW);
+
+function setBindLocations(colorLocation, positionLocation) {
+ gl.bindAttribLocation(program, positionLocation, attribs.vPosition);
+ gl.bindAttribLocation(program, colorLocation, attribs.vColor);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+ var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
+ assertMsg(linked, "program linked successfully");
+
+ debug("vPosition:" + gl.getAttribLocation(program, attribs.vPosition))
+ debug("vColor :" + gl.getAttribLocation(program, attribs.vColor))
+ assertMsg(gl.getAttribLocation(program, attribs.vPosition) == positionLocation,
+ "location of vPosition should be " + positionLocation);
+ assertMsg(gl.getAttribLocation(program, attribs.vColor) == colorLocation,
+ "location of vColor should be " + colorLocation);
+
+ var ploc = gl.getAttribLocation(program, attribs.vPosition);
+ var cloc = gl.getAttribLocation(program, attribs.vColor);
+ gl.bindBuffer(gl.ARRAY_BUFFER, positions);
+ gl.enableVertexAttribArray(positionLocation);
+ gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colors);
+ gl.enableVertexAttribArray(colorLocation);
+ gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
+}
+
+function checkDraw(colorLocation, positionLocation, r, g, b, a) {
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [r, g, b, a], "should be green");
+
+ gl.disableVertexAttribArray(positionLocation);
+ gl.disableVertexAttribArray(colorLocation);
+}
+
+setBindLocations(2, 3);
+checkDraw(2, 3, 0, 255, 0, 255);
+
+setBindLocations(0, 3);
+gl.disableVertexAttribArray(0);
+gl.vertexAttrib4f(0, 1, 0, 0, 1);
+checkDraw(0, 3, 255, 0, 0, 255);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-test.html
new file mode 100644
index 0000000000..6909c64491
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-bind-attrib-location-test.html
@@ -0,0 +1,139 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BindAttribLocation Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas style="border: 1px solid black;" id="canvas" width="50" height="50"></canvas>
+<script id="vshader" type="text/something-not-javascript">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main()
+{
+ gl_Position = vPosition;
+ color = vColor;
+}
+</script>
+<script id="fshader" type="text/something-not-javascript">
+precision mediump float;
+
+varying vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("This test ensures WebGL implementations don't allow names that start with 'gl_' when calling bindAttribLocation.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+shouldBeNonNull("gl");
+
+debug("");
+debug("Checking gl.bindAttribLocation.");
+
+var program = gl.createProgram();
+gl.bindAttribLocation(program, 0, "gl_foo");
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "bindAttribLocation should return INVALID_OPERATION if name starts with 'gl_'");
+gl.bindAttribLocation(program, 0, "gl_TexCoord0");
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "bindAttribLocation should return INVALID_OPERATION if name starts with 'gl_'");
+
+var vs = wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER);
+var fs = wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER);
+gl.attachShader(program, vs);
+gl.attachShader(program, fs);
+
+var positions = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positions);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+
+var colors = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colors);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0,1,0,1,
+ 0,1,0,1,
+ 0,1,0,1]), gl.STATIC_DRAW);
+
+function setBindLocations(colorLocation, positionLocation) {
+ gl.bindAttribLocation(program, positionLocation, "vPosition");
+ gl.bindAttribLocation(program, colorLocation, "vColor");
+ gl.linkProgram(program);
+ gl.useProgram(program);
+ var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
+ assertMsg(linked, "program linked successfully");
+
+ debug("vPosition:" + gl.getAttribLocation(program, "vPosition"))
+ debug("vColor :" + gl.getAttribLocation(program, "vColor"))
+ assertMsg(gl.getAttribLocation(program, "vPosition") == positionLocation,
+ "location of vPosition should be " + positionLocation);
+ assertMsg(gl.getAttribLocation(program, "vColor") == colorLocation,
+ "location of vColor should be " + colorLocation);
+
+ var ploc = gl.getAttribLocation(program, "vPosition");
+ var cloc = gl.getAttribLocation(program, "vColor");
+ gl.bindBuffer(gl.ARRAY_BUFFER, positions);
+ gl.enableVertexAttribArray(positionLocation);
+ gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colors);
+ gl.enableVertexAttribArray(colorLocation);
+ gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
+}
+
+function checkDraw(colorLocation, positionLocation, r, g, b, a) {
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ var width = 50;
+ var height = 50;
+
+ // Test several locations
+ wtu.checkCanvasRect(gl, 0, 0, width, 1, [0, 0, 0, 255],
+ "First line should be all black");
+ wtu.checkCanvasRect(gl, 20, 15, 10, 1, [r, g, b, a],
+ "Line 15 should be red for at least 10 rgba pixels starting 20 pixels in");
+ wtu.checkCanvasRect(gl, 0, height - 1, width, 0, [0, 0, 0, 255],
+ "Last line should be all black");
+
+ gl.disableVertexAttribArray(positionLocation);
+ gl.disableVertexAttribArray(colorLocation);
+}
+
+setBindLocations(2, 3);
+checkDraw(2, 3, 0, 255, 0, 255);
+
+setBindLocations(0, 3);
+gl.disableVertexAttribArray(0);
+gl.vertexAttrib4f(0, 1, 0, 0, 1);
+checkDraw(0, 3, 255, 0, 0, 255);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-attribute.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-attribute.html
new file mode 100644
index 0000000000..76dc422eae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-attribute.html
@@ -0,0 +1,85 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL getActiveAttrib conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute $type attr0;
+void main()
+{
+ gl_Position = vec4(0, 0, 0, attr0$access);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(0,1,0,1);
+}
+</script>
+<script>
+"use strict";
+description("Tests getActiveAttrib for various types");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var tests = [
+{ glType: gl.FLOAT, size: 1, type: 'float', access: ''},
+{ glType: gl.FLOAT_VEC2, size: 1, type: 'vec2', access: '[1]'},
+{ glType: gl.FLOAT_VEC3, size: 1, type: 'vec3', access: '[2]'},
+{ glType: gl.FLOAT_VEC4, size: 1, type: 'vec4', access: '[3]'},
+{ glType: gl.FLOAT_MAT2, size: 1, type: 'mat2', access: '[1][1]'},
+{ glType: gl.FLOAT_MAT3, size: 1, type: 'mat3', access: '[2][2]'},
+{ glType: gl.FLOAT_MAT4, size: 1, type: 'mat4', access: '[3][3]'},
+];
+
+var source = document.getElementById('vshader').text;
+var fs = wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER);
+for (var tt = 0; tt < tests.length; ++tt) {
+ var t = tests[tt];
+ var vs = wtu.loadShader(
+ gl,
+ source.replace('$type', t.type).replace('$access', t.access),
+ gl.VERTEX_SHADER);
+ var program = wtu.setupProgram(gl, [vs, fs]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from setup");
+ var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
+ var found = false;
+ for (var ii = 0; ii < numAttribs; ++ii) {
+ var info = gl.getActiveAttrib(program, ii);
+ if (info.name == 'attr0') {
+ found = true;
+ assertMsg(info.type == t.glType,
+ "type must be " + wtu.glEnumToString(gl, t.glType) + " was " +
+ wtu.glEnumToString(gl, info.type));
+ assertMsg(info.size == t.size,
+ "size must be " + t.size + ' was ' + info.size);
+ }
+ }
+ if (!found) {
+ testFailed("attrib 'attr0' not found");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-uniform.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-uniform.html
new file mode 100644
index 0000000000..295b5987cc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-get-active-uniform.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL getActiveUniform conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+void main()
+{
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform $type uniform0;
+void main()
+{
+ gl_FragColor = vec4(0,$access,0,1);
+}
+</script>
+<script id="fshaderA" type="x-shader/x-fragment">
+precision mediump float;
+uniform float uniform0;
+void main()
+{
+ gl_FragColor = vec4(0,uniform0,0,1);
+}
+</script>
+<script id="fshaderB" type="x-shader/x-fragment">
+precision mediump float;
+uniform float uniform0;
+uniform float uniform1;
+void main()
+{
+ gl_FragColor = vec4(0,uniform0,uniform1,1);
+}
+</script>
+<script>
+"use strict";
+description("Tests getActiveUniform for various types");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var tests = [
+ { glType: gl.FLOAT, size: 1, type: 'float', access: 'uniform0'},
+ { glType: gl.FLOAT_VEC2, size: 1, type: 'vec2', access: 'uniform0[1]'},
+ { glType: gl.FLOAT_VEC3, size: 1, type: 'vec3', access: 'uniform0[2]'},
+ { glType: gl.FLOAT_VEC4, size: 1, type: 'vec4', access: 'uniform0[3]'},
+ { glType: gl.FLOAT_MAT2, size: 1, type: 'mat2', access: 'uniform0[1][1]'},
+ { glType: gl.FLOAT_MAT3, size: 1, type: 'mat3', access: 'uniform0[2][2]'},
+ { glType: gl.FLOAT_MAT3, size: 1, type: 'mat3', access: 'uniform0[2][2]'},
+ { glType: gl.FLOAT_MAT4, size: 1, type: 'mat4', access: 'uniform0[3][3]'},
+ { glType: gl.INT, size: 1, type: 'int', access: 'float(uniform0)'},
+ { glType: gl.INT_VEC2, size: 1, type: 'ivec2', access: 'float(uniform0[1])'},
+ { glType: gl.INT_VEC3, size: 1, type: 'ivec3', access: 'float(uniform0[2])'},
+ { glType: gl.INT_VEC4, size: 1, type: 'ivec4', access: 'float(uniform0[3])'},
+ { glType: gl.BOOL, size: 1, type: 'bool', access: 'float(uniform0)'},
+ { glType: gl.BOOL_VEC2, size: 1, type: 'bvec2', access: 'float(uniform0[1])'},
+ { glType: gl.BOOL_VEC3, size: 1, type: 'bvec3', access: 'float(uniform0[2])'},
+ { glType: gl.BOOL_VEC4, size: 1, type: 'bvec4', access: 'float(uniform0[3])'},
+ { glType: gl.SAMPLER_2D, size: 1, type: 'sampler2D', access: 'texture2D(uniform0, vec2(0,0)).x'},
+ { glType: gl.SAMPLER_CUBE, size: 1, type: 'samplerCube', access: 'textureCube(uniform0, vec3(0,1,0)).x'}
+];
+
+var vs = wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER);
+var source = document.getElementById('fshader').text;
+
+function createProgram(type, access) {
+ var fs = wtu.loadShader(
+ gl,
+ source.replace('$type', type).replace('$access', access),
+ gl.FRAGMENT_SHADER);
+ var program = wtu.setupProgram(gl, [vs, fs]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from setup");
+ return program;
+}
+
+for (var tt = 0; tt < tests.length; ++tt) {
+ var t = tests[tt];
+ var program = createProgram(t.type, t.access);
+ var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ var found = false;
+ for (var ii = 0; ii < numUniforms; ++ii) {
+ var info = gl.getActiveUniform(program, ii);
+ if (info.name == 'uniform0') {
+ found = true;
+ assertMsg(info.type == t.glType,
+ "type must be " + wtu.glEnumToString(gl, t.glType) + " was " +
+ wtu.glEnumToString(gl, info.type));
+ assertMsg(info.size == t.size,
+ "size must be " + t.size + ' was ' + info.size);
+ }
+ }
+ if (!found) {
+ testFailed("uniform 'uniform0' not found");
+ }
+}
+
+var p1 = wtu.setupProgram(gl, [vs, 'fshaderA']);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from program A");
+var p2 = wtu.setupProgram(gl, [vs, 'fshaderB']);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from program B");
+var l1 = gl.getUniformLocation(p1, 'uniform0');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors getting location of uniform0 p1");
+var l2 = gl.getUniformLocation(p2, 'uniform0');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors getting location of uniform0 p2");
+
+gl.useProgram(p2);
+gl.uniform1f(l2, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors setting uniform 0");
+gl.uniform1f(l1, 2);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "setting a uniform using a location from another program");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-getshadersource.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-getshadersource.html
new file mode 100644
index 0000000000..3461537d4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-getshadersource.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+ <title>WebGL getShaderSource conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">abc//defNOTASCII</script>
+<script>
+"use strict";
+description("Tests that the source that goes into a shader is what comes out.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var original = document.getElementById("vshader").text;
+var shader = gl.createShader(gl.VERTEX_SHADER);
+gl.shaderSource(shader, original);
+var source = gl.getShaderSource(shader);
+shouldBe("source", "original");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-shader-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-shader-test.html
new file mode 100644
index 0000000000..6566f77303
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/gl-shader-test.html
@@ -0,0 +1,94 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ShaderL Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<script id="vs" type="x-shader/x-fragment">
+attribute vec4 vPosition;
+varying vec2 texCoord;
+void main() {
+ gl_Position = vPosition;
+ texCoord = vPosition.xy * 0.5 + 0.5;
+}
+</script>
+<script id="fs-green" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragData[0] = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fs-red" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragData[0] = vec4(1, 0, 0, 1);
+}
+</script>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks a few things about WebGL Shaders.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking shaders.");
+
+ // Create the shader object
+ var shader = gl.createShader(desktopGL['GEOMETRY_SHADER_ARB']);
+ assertMsg(shader == null,
+ "should not be able to create GEOMETRY shader");
+
+ checkDeferredCompliation()
+}
+
+function checkDeferredCompliation() {
+ var vs = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vs, document.getElementById("vs").text);
+ gl.compileShader(vs);
+ var fs = gl.createShader(gl.FRAGMENT_SHADER);
+ // Compile the green shader
+ gl.shaderSource(fs, document.getElementById("fs-green").text);
+ gl.compileShader(fs);
+ // Load the red shader source but do NOT compile it
+ gl.shaderSource(fs, document.getElementById("fs-red").text);
+ var p = gl.createProgram();
+ gl.attachShader(p, vs);
+ gl.attachShader(p, fs);
+ gl.bindAttribLocation(p, 0, "vPosition");
+ gl.linkProgram(p);
+ gl.useProgram(p);
+ wtu.setupUnitQuad(gl, 0, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/invalid-UTF-16.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/invalid-UTF-16.html
new file mode 100644
index 0000000000..238552a5e6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/invalid-UTF-16.html
@@ -0,0 +1,48 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css">
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+"use strict";
+description('This test verifies that the internal conversion from UTF16 to UTF8 is robust to invalid inputs. Any DOM entry point which converts an incoming string to UTF8 could be used for this test.');
+
+var array = [];
+array.push(String.fromCharCode(0x48)); // H
+array.push(String.fromCharCode(0x69)); // i
+array.push(String.fromCharCode(0xd87e)); // Bogus
+var string = array.join('');
+
+// In order to make this test not depend on WebGL, the following were
+// attempted:
+// - Send a string to console.log
+// - Submit a mailto: form containing a text input with the bogus
+// string
+// The first code path does not perform a utf8 conversion of the
+// incoming string unless Console::shouldPrintExceptions() returns
+// true. The second seems to sanitize the form's input before
+// converting it to a UTF8 string.
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var program = gl.createProgram();
+gl.bindAttribLocation(program, 0, string);
+testPassed("bindAttribLocation with invalid UTF-16 did not crash");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-handling.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-handling.html
new file mode 100644
index 0000000000..54138becf1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-handling.html
@@ -0,0 +1,142 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Program Handling Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 a_position;
+ uniform vec4 u_color;
+ varying vec4 v_color;
+ void main()
+ {
+ v_color = u_color;
+ gl_Position = a_position;
+ }
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+ precision mediump float;
+ varying vec4 v_color;
+ void main()
+ {
+ gl_FragColor = v_color;
+ }
+</script>
+<script id="fshader-not-link" type="x-shader/x-fragment">
+ precision mediump float;
+ varying vec4 foo;
+ void main()
+ {
+ gl_FragColor = foo;
+ }
+</script>
+
+<canvas id="canvas" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+function compile(gl, shader, src) {
+ var shaderSource = document.getElementById(src).text;
+ gl.shaderSource(shader, shaderSource);
+ gl.compileShader(shader);
+}
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+}
+
+function testProgramInvalidation() {
+ debug('');
+ debug('== Testing invalidation of the current program ==');
+ var vs = wtu.loadShaderFromScript(gl, "vshader");
+ var fs = wtu.loadShaderFromScript(gl, "fshader");
+ var prg = wtu.createProgram(gl, vs, fs);
+ gl.useProgram(prg);
+ const positionLoc = gl.getAttribLocation(prg, 'a_position');
+ const colorLoc = gl.getUniformLocation(prg, 'u_color');
+
+ wtu.setupUnitQuad(gl, positionLoc);
+
+ debug("Draw red with valid program");
+ gl.uniform4fv(colorLoc, [1, 0, 0, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+ debug("Change fragment shader to one that will not link");
+ compile(gl, fs, "fshader-not-link");
+ debug("Draw orange");
+ gl.uniform4fv(colorLoc, [1, 127/255, 0, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 127, 0, 255], "should be orange");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors before relink");
+
+ debug("Try linking");
+ gl.linkProgram(prg);
+ assertMsg(gl.getProgramParameter(prg, gl.LINK_STATUS) == false, "link should fail");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after linkProgram");
+ debug("Attempt to draw green; because link failed, in WebGL, the draw should generate INVALID_OPERATION");
+ gl.uniform4fv(colorLoc, [0, 1, 0, 1]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "because the current program has been invalidated, uniform* calls generate INVALID_OPERATION");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors before draw");
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "draw with invalidated program should fail");
+ wtu.checkCanvas(gl, [255, 127, 0, 255], "should still be orange");
+}
+
+function testProgramShaderRemoval() {
+ debug('');
+ debug('== Testing removal of shaders from the current program ==');
+ var vs = wtu.loadShaderFromScript(gl, "vshader");
+ var fs = wtu.loadShaderFromScript(gl, "fshader");
+ var prg = wtu.createProgram(gl, vs, fs);
+ gl.useProgram(prg);
+ const positionLoc = gl.getAttribLocation(prg, 'a_position');
+ const colorLoc = gl.getUniformLocation(prg, 'u_color');
+
+ wtu.setupUnitQuad(gl, positionLoc);
+
+ debug("Draw red with valid program");
+ gl.uniform4fv(colorLoc, [1, 0, 0, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+ debug("Detach and delete shaders");
+ gl.detachShader(prg, vs);
+ gl.detachShader(prg, fs);
+ gl.deleteShader(vs);
+ gl.deleteShader(fs);
+
+ debug("Draw blue to show even though shaders are gone program is still valid");
+ gl.uniform4fv(colorLoc, [0, 0, 1, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "should be blue");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+
+testProgramInvalidation();
+testProgramShaderRemoval();
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-infolog.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-infolog.html
new file mode 100644
index 0000000000..02fa19d912
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-infolog.html
@@ -0,0 +1,62 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Program Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script id="vertexShader" language="x-shader/x-vertex">
+void main()
+{
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fragmentShader" language="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description('getProgramInfoLog should not return \\0');
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+}
+
+debug("");
+
+var program = wtu.loadProgramFromScript(gl, 'vertexShader', 'fragmentShader');
+var infolog = gl.getProgramInfoLog(program);
+if (infolog === '\0') {
+ testFailed("getProgramInfoLog should not return '\\0'");
+} else {
+ testPassed("getProgramInfoLog didn't return '\\0'");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-test.html
new file mode 100644
index 0000000000..34ca68f1d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/program-test.html
@@ -0,0 +1,406 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Program Compiling/Linking Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+</script>
+<script id="fshader-red" type="x-shader/x-fragment">
+ void main()
+ {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+</script>
+<script id="fshader-green" type="x-shader/x-fragment">
+ void main()
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+</script>
+<script id="fshader-settable" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform vec4 u_color;
+ void main()
+ {
+ gl_FragColor = u_color;
+ }
+</script>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script type="application/javascript">
+var wtu = WebGLTestUtils;
+let gl;
+function go() {
+ description("Tests that program compiling/linking/using works correctly.");
+
+ debug("");
+ debug("Canvas.getContext");
+
+ gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+
+ testPassed("context exists");
+
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ function doArraysHaveSameContents(a, b) {
+ var flags = [];
+ function hasUnusedValue(a, value) {
+ for (var ii = 0; ii < a.length; ++ii) {
+ if (a[ii] === value && !flags[ii]) {
+ flags[ii] = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ try {
+ if (a.length !== b.length) {
+ return false;
+ }
+ for (var ii = 0; ii < a.length; ii++) {
+ if (!hasUnusedValue(b, a[ii])) {
+ return false;
+ }
+ }
+ } catch (ex) {
+ return false;
+ }
+ return true;
+ }
+
+/////// Check compileShader() /////////////////////////////
+
+ var vs = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vs, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }");
+ gl.compileShader(vs);
+
+ assertMsg(gl.getShaderParameter(vs, gl.COMPILE_STATUS) == true,
+ "good vertex shader should compile");
+
+ // Verify that constants removed from the WebGL spec generate INVALID_ENUM errors
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point");
+ assertMsg(gl.getShaderParameter(vs, desktopGL['INFO_LOG_LENGTH']) === null, "invalid call to getShaderParameter should return null");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "INFO_LOG_LENGTH is not a valid argument to getShaderParameter in WebGL");
+ assertMsg(gl.getShaderParameter(vs, desktopGL['SHADER_SOURCE_LENGTH']) === null, "invalid call to getShaderParameter should return null");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "SHADER_SOURCE_LENGTH is not a valid argument to getShaderParameter in WebGL");
+
+ var vs2 = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vs2, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex * 0.5; }");
+ gl.compileShader(vs2);
+
+ assertMsg(gl.getShaderParameter(vs2, gl.COMPILE_STATUS) == true,
+ "good vertex shader #2 should compile");
+
+ var vsBad = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vsBad, "WILL NOT COMPILE;");
+ gl.compileShader(vsBad);
+
+ // GLSL 1.0.17 section 10.27. compile shader does not have to return failure.
+ //assertMsg(gl.getShaderParameter(vsBad, gl.COMPILE_STATUS) == false,
+ // "bad vertex shader should fail to compile");
+
+ var fs = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }");
+ gl.compileShader(fs);
+
+ assertMsg(gl.getShaderParameter(fs, gl.COMPILE_STATUS) == true,
+ "good fragment shader should compile");
+
+ var fs2 = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs2, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor * 0.5; }");
+ gl.compileShader(fs2);
+
+ assertMsg(gl.getShaderParameter(fs2, gl.COMPILE_STATUS) == true,
+ "good fragment shader #2 should compile");
+
+ var fsBad = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fsBad, "WILL NOT COMPILE;");
+ gl.compileShader(fsBad);
+
+ // GLSL 1.0.17 section 10.27. compile shader does not have to return failure.
+ //assertMsg(gl.getShaderParameter(fsBad, gl.COMPILE_STATUS) == false,
+ // "bad fragment shader should fail to compile");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point");
+
+/////// Check attachShader() /////////////////////////////
+
+ function checkAttachShader(already_attached_shaders, shader, expected_error_code, errmsg) {
+ var prog = gl.createProgram();
+ for (var i = 0; i < already_attached_shaders.length; ++i)
+ gl.attachShader(prog, already_attached_shaders[i]);
+ if(gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in attachShader()");
+ gl.attachShader(prog, shader);
+ wtu.glErrorShouldBe(gl, expected_error_code, errmsg);
+ }
+
+ checkAttachShader([], vs, gl.NO_ERROR, "attaching a vertex shader should succeed");
+ checkAttachShader([vs], vs, gl.INVALID_OPERATION,
+ "attaching an already attached vertex shader should generate INVALID_OPERATION");
+ checkAttachShader([], fs, gl.NO_ERROR, "attaching a fragment shader should succeed");
+ checkAttachShader([fs], fs, gl.INVALID_OPERATION,
+ "attaching an already attached fragment shader should generate INVALID_OPERATION");
+ checkAttachShader([vs], vs2, gl.INVALID_OPERATION,
+ "attaching shaders of the same type to a program should generate INVALID_OPERATION");
+ checkAttachShader([fs], fs2, gl.INVALID_OPERATION,
+ "attaching shaders of the same type to a program should generate INVALID_OPERATION");
+
+/////// Check detachShader() /////////////////////////////
+
+ function checkDetachShader(already_attached_shaders, shader, expected_error_code, errmsg) {
+ var prog = gl.createProgram();
+ for (var i = 0; i < already_attached_shaders.length; ++i)
+ gl.attachShader(prog, already_attached_shaders[i]);
+ if(gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in attachShader()");
+ gl.detachShader(prog, shader);
+ wtu.glErrorShouldBe(gl, expected_error_code, errmsg);
+ }
+
+ checkDetachShader([vs], vs, gl.NO_ERROR, "detaching a vertex shader should succeed");
+ checkDetachShader([fs], vs, gl.INVALID_OPERATION,
+ "detaching a not already attached vertex shader should generate INVALID_OPERATION");
+ checkDetachShader([fs], fs, gl.NO_ERROR, "detaching a fragment shader should succeed");
+ checkDetachShader([vs], fs, gl.INVALID_OPERATION,
+ "detaching a not already attached fragment shader should generate INVALID_OPERATION");
+
+/////// Check getAttachedShaders() /////////////////////////////
+
+ function checkGetAttachedShaders(shaders_to_attach, shaders_to_detach, expected_shaders, errmsg) {
+ prog = gl.createProgram();
+ for (var i = 0; i < shaders_to_attach.length; ++i)
+ gl.attachShader(prog, shaders_to_attach[i]);
+ if(gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in attachShader()");
+ for (var i = 0; i < shaders_to_detach.length; ++i)
+ gl.detachShader(prog, shaders_to_detach[i]);
+ if(gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in detachShader()");
+ assertMsg(doArraysHaveSameContents(gl.getAttachedShaders(prog), expected_shaders), errmsg);
+ shouldBe('gl.getProgramParameter(prog, gl.ATTACHED_SHADERS)', `${expected_shaders.length}`);
+ }
+ checkGetAttachedShaders([], [], [], "getAttachedShaders should return an empty list by default");
+ checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should give the expected list");
+ checkGetAttachedShaders([fs, vs], [], [fs, vs],
+ "attaching some shaders should give the expected list");
+ checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it should leave an empty list");
+ checkGetAttachedShaders([fs, vs], [fs, vs], [],
+ "attaching some shaders and detaching them in same order should leave an empty list");
+ checkGetAttachedShaders([fs, vs], [vs, fs], [],
+ "attaching some shaders and detaching them in random order should leave an empty list");
+ checkGetAttachedShaders([fs, vs], [vs], [fs],
+ "attaching and detaching some shaders should leave the difference list");
+ checkGetAttachedShaders([fs, vs], [fs], [vs],
+ "attaching and detaching some shaders should leave the difference list");
+ checkGetAttachedShaders([fsBad], [], [fsBad],
+ "attaching a shader that failed to compile should still show it in the list");
+ checkGetAttachedShaders([fs, vsBad], [], [fs, vsBad],
+ "attaching shaders, including one that failed to compile, should still show the it in the list");
+
+/////// Check linkProgram() and useProgram /////////////////////////////
+
+ function checkLinkAndUse(shaders, deleteShaderAfterAttach, expected_status, testInvalidEnums, errmsg) {
+ var prog = gl.createProgram();
+ for (var i = 0; i < shaders.length; ++i) {
+ gl.attachShader(prog, shaders[i]);
+ if (deleteShaderAfterAttach)
+ gl.deleteShader(shaders[i]);
+ }
+ gl.bindAttribLocation(prog, 0, "aVertex");
+ gl.bindAttribLocation(prog, 1, "aColor");
+ gl.linkProgram(prog);
+ if (gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in linkProgram()");
+ assertMsg(gl.getProgramParameter(prog, gl.LINK_STATUS) == expected_status, errmsg);
+ var infolog = gl.getProgramInfoLog(prog);
+ if (gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in getProgramInfoLog()");
+ if (typeof(infolog) != "string")
+ assertMsg(false, "getProgramInfoLog() did not return a string");
+ if (expected_status == true && gl.getProgramParameter(prog, gl.LINK_STATUS) == false)
+ debug(infolog);
+ if (gl.getError() != gl.NO_ERROR)
+ assertMsg(false, "unexpected error in getProgramParameter()");
+
+ if (testInvalidEnums) {
+ // Verify that constants removed from the WebGL spec generate INVALID_ENUM errors
+ assertMsg(gl.getProgramParameter(prog, desktopGL['INFO_LOG_LENGTH']) === null, "invalid call to getProgramParameter should return null");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "INFO_LOG_LENGTH is not a valid argument to getProgramParameter in WebGL");
+ assertMsg(gl.getProgramParameter(prog, desktopGL['ACTIVE_ATTRIBUTE_MAX_LENGTH']) === null, "invalid call to getProgramParameter should return null");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "ACTIVE_ATTRIBUTE_MAX_LENGTH is not a valid argument to getProgramParameter in WebGL");
+ assertMsg(gl.getProgramParameter(prog, desktopGL['ACTIVE_UNIFORM_MAX_LENGTH']) === null, "invalid call to getProgramParameter should return null");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "ACTIVE_UNIFORM_MAX_LENGTH is not a valid argument to getProgramParameter in WebGL");
+ }
+
+ gl.useProgram(prog);
+ if (expected_status == true)
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "using a valid program should succeed");
+ if (expected_status == false)
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "using an invalid program should generate INVALID_OPERATION");
+ return prog;
+ }
+
+ var progGood1 = checkLinkAndUse([vs, fs], false, true, true, "valid program should link");
+ var progGood2 = checkLinkAndUse([vs, fs2], false, true, false, "valid program #2 should link");
+ var progBad1 = checkLinkAndUse([vs], false, false, false, "program with no fragment shader should fail to link");
+ var progBad2 = checkLinkAndUse([fs], false, false, false, "program with no vertex shader should fail to link");
+ var progBad3 = checkLinkAndUse([vsBad, fs], false, false, false, "program with bad vertex shader should fail to link");
+ var progBad4 = checkLinkAndUse([vs, fsBad], false, false, false, "program with bad fragment shader should fail to link");
+ var progBad5 = checkLinkAndUse([vsBad, fsBad], false, false, false, "program with bad shaders should fail to link");
+
+ gl.useProgram(progGood1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "using a valid program shouldn't generate a GL error");
+
+ var vbuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
+ gl.bufferData(gl.ARRAY_BUFFER,
+ new Float32Array([
+ 0.0, 0.0, 0.0, 1.0,
+ 1.0, 0.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0]),
+ gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttrib3f(1, 1.0, 0.0, 0.0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point #2");
+
+ gl.useProgram(null);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawing with a null program should generate INVALID_OPERATION");
+
+ gl.useProgram(progGood1);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't generate a GL error");
+
+ gl.useProgram(progBad1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "using an invalid program should generate INVALID_OPERATION");
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Try to use an invalid program should not change the current rendering state");
+
+ gl.useProgram(progGood2);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't generate a GL error");
+ gl.detachShader(progGood2, fs2);
+ gl.attachShader(progGood2, fsBad);
+ gl.linkProgram(progGood2);
+ assertMsg(gl.getProgramParameter(progGood2, gl.LINK_STATUS) == false,
+ "linking should fail with in-use formerly good program, with new bad shader attached");
+
+ // In WebGL, an unsuccessful link immediately invalidates the previous valid program.
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawing with a newly-invalidated program should generate INVALID_OPERATION");
+
+ gl.useProgram(progGood1);
+ gl.drawArrays(gl.TRIANGLES, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid when last used program shouldn't generate a GL error");
+
+ var progGood1 = checkLinkAndUse([vs, fs], true, true, false, "delete shaders after attaching them and before linking program should not affect linkProgram");
+ gl.useProgram(progGood1);
+ gl.drawArrays(gl.TRIANGLES, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid when last used program shouldn't generate a GL error");
+
+/////// Check deleteProgram() and deleteShader() /////////////////////////////
+
+ gl.useProgram(progGood1);
+ gl.deleteProgram(progGood1);
+ gl.drawArrays(gl.TRIANGLES, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "delete the current program shouldn't change the current rendering state");
+
+ gl.linkProgram(progGood1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "The current program shouldn't be deleted");
+
+ var fs3 = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs3, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }");
+ gl.compileShader(fs3);
+
+ assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true,
+ "good fragment shader should compile");
+
+ gl.deleteShader(fs3);
+ gl.compileShader(fs3);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "an unattached shader should be deleted immediately");
+
+ fs3 = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs3, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }");
+ gl.compileShader(fs3);
+
+ assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true,
+ "good fragment shader should compile");
+
+ gl.detachShader(progGood1, fs);
+ gl.attachShader(progGood1, fs3);
+
+ gl.deleteShader(fs3);
+ gl.compileShader(fs3);
+ assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true,
+ "an attached shader shouldn't be deleted");
+
+ gl.useProgram(null);
+ gl.linkProgram(progGood1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked program should be deleted once it's no longer the current program");
+
+ gl.compileShader(fs3);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked shader should be deleted once all its attachments are removed");
+
+//////// Check linkProgram() with relinked program //////////
+ var vs = wtu.loadShaderFromScript(gl, "vshader");
+ var fs = wtu.loadShaderFromScript(gl, "fshader-red");
+ var prg = wtu.createProgram(gl, vs, fs);
+ gl.useProgram(prg);
+ var posLoc = gl.getAttribLocation(prg, "a_position");
+ wtu.setupUnitQuad(gl, posLoc);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+ gl.shaderSource(fs, wtu.getScript("fshader-green"));
+ gl.compileShader(fs);
+ gl.linkProgram(prg);
+ // Program should be new program at this point without calling useProgram
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ var prg = wtu.setupProgram(gl, ["vshader", "fshader-settable"], ["a_position"]);
+ var colorLoc = gl.getUniformLocation(prg, "u_color");
+ gl.uniform4f(colorLoc, 1, 0, 0, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+ gl.linkProgram(prg);
+ // Program's uniforms should be cleared at this point without calling useProgram
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "should be tranparent black");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+
+debug("");
+go();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/programs/use-program-crash-with-discard-in-fragment-shader.html b/dom/canvas/test/webgl-conf/checkout/conformance/programs/use-program-crash-with-discard-in-fragment-shader.html
new file mode 100644
index 0000000000..27dac9a9ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/programs/use-program-crash-with-discard-in-fragment-shader.html
@@ -0,0 +1,77 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Program Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script id="vertexShader" language="x-shader/x-vertex">
+attribute vec4 ATTR0;
+void main()
+{
+ gl_Position = ATTR0;
+}
+</script>
+<script id="fragmentShader" language="x-shader/x-fragment">
+precision mediump float;
+void main()
+{
+ float _Intensity = exp2(gl_FragCoord.w);
+ if (_Intensity < 0.5) {
+ discard;
+ }
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description('Regression test for crash in Mac OS AMD OpenGL driver related to use of discard in fragment shader.<br><br>More specifically, triggering the crash seems to require examination of gl_FragCoord.w, use of exp2, and a call to discard in the fragment shader. Thanks to Sheheryar Zakaria and Michael Braithwaite at Turbulenz for the original test case.<br><a href="https://bugs.webkit.org/show_bug.cgi?id=73932">WebKit bug 73932</a><br>');
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+}
+
+debug("");
+
+var program = wtu.loadProgramFromScript(gl, 'vertexShader', 'fragmentShader');
+if (program) {
+ testPassed("Program linked successfully");
+} else {
+ testFailed("Program failed to link");
+}
+
+// Crash occurs here on affected machines
+gl.useProgram(program);
+
+// In some browsers, such as Chrome, the above crash only causes a
+// lost context event to be dispatched, and not synchronously. To verify
+// that everything worked, clear and read back the frame buffer.
+gl.clearColor(1.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 0, 255],
+ "Color should be red");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt
new file mode 100644
index 0000000000..8651fbd83f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt
@@ -0,0 +1,3 @@
+--min-version 1.0.4 fbo-remains-unchanged-after-read-pixels.html
+read-pixels-pack-alignment.html
+read-pixels-test.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html b/dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html
new file mode 100644
index 0000000000..00e8dcd9a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html
@@ -0,0 +1,105 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="4" height="4"></canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 a_pos;
+attribute vec4 a_color;
+varying vec4 v_color;
+
+void main()
+{
+ v_color = a_color;
+ gl_Position = vec4(a_pos.xyz, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 v_color;
+
+void main()
+{
+ gl_FragColor = v_color;
+}
+</script>
+
+<script>
+"use strict";
+
+description("when antialias is enabled, verify default fbo pixels would not be changed between two readPixels without drawing operations");
+var wtu = WebGLTestUtils;
+var N = 4;
+
+var vertices = new Float32Array([
+ 1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0]);
+var colors = new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255]);
+
+var canvas = document.getElementById('canvas');
+var gl = wtu.create3DContext(canvas, {antialias: true});
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_pos", "a_color"]);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var colorOffset = vertices.byteLength;
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, colorOffset + colors.byteLength, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
+ gl.bufferSubData(gl.ARRAY_BUFFER, colorOffset, colors);
+
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, colorOffset);
+ gl.enableVertexAttribArray(1);
+ gl.drawArrays(gl.LINES, 0, vertices.length / 3);
+
+ var result_1 = new Uint8Array(N * N * 4);
+ var result_2 = new Uint8Array(N * N * 4);
+ gl.readPixels(0, 0, N, N, gl.RGBA, gl.UNSIGNED_BYTE, result_1);
+ gl.readPixels(0, 0, N, N, gl.RGBA, gl.UNSIGNED_BYTE, result_2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var tolerance = 0;
+ var diff = new Uint8Array(N * N * 4);
+ var failed = wtu.comparePixels(result_1, result_2, tolerance, diff);
+
+ if (failed) {
+ testFailed("default fbo pixels had be changed between two readPixels without drawing operations");
+ } else {
+ testPassed("default fbo pixels had not be changed between two readPixels without drawing operations.");
+ }
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(vbo);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html
new file mode 100644
index 0000000000..3090284b05
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html
@@ -0,0 +1,251 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 pos;
+attribute vec4 colorIn;
+varying vec4 color;
+
+void main()
+{
+ color = colorIn;
+ gl_Position = vec4(pos.xyz, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<canvas id="example2" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+// The below declarations need to be global for "shouldBe" to see them
+var wtu = WebGLTestUtils;
+var gl = null;
+var array = null;
+var pixel = [ 0, 0, 0, 0 ];
+var expectedColor = [ 0, 0, 0, 0 ];
+
+function calculatePixelBytes(format, type)
+{
+ var size = 0;
+ switch (format) {
+ case gl.ALPHA:
+ size = 1;
+ break;
+ case gl.RGB:
+ size = 3;
+ break;
+ case gl.RGBA:
+ size = 4;
+ break;
+ default:
+ return -1;
+ }
+ switch (type) {
+ case gl.UNSIGNED_BYTE:
+ break;
+ case gl.UNSIGNED_SHORT_5_6_5:
+ if (format != gl.RGB)
+ return -1;
+ size = 2;
+ break;
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ if (format != gl.RGBA)
+ return -1;
+ size = 2;
+ break;
+ default:
+ return -1;
+ }
+ return size;
+}
+
+function calculatePaddingBytes(bytesPerPixel, packAlignment, width)
+{
+ var padding = 0;
+ switch (packAlignment) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ padding = (bytesPerPixel * width) % packAlignment;
+ if (padding > 0)
+ padding = packAlignment - padding;
+ break;
+ default:
+ return -1;
+ }
+ return padding;
+}
+
+function packColor(format, type, r, g, b, a)
+{
+ // FIXME: not sure if the color packing is correct for UNSIGNED_SHORT_*.
+ var color = [ 0, 0, 0, 0 ];
+ switch (type) {
+ case gl.UNSIGNED_BYTE:
+ switch (format) {
+ case gl.ALPHA:
+ color[0] = a;
+ break;
+ case gl.RGB:
+ color[0] = r;
+ color[1] = g;
+ color[2] = b;
+ break;
+ case gl.RGBA:
+ color[0] = r;
+ color[1] = g;
+ color[2] = b;
+ color[3] = a;
+ break;
+ default:
+ return null;
+ }
+ break;
+ case gl.UNSIGNED_SHORT_5_6_5:
+ if (format != gl.RGB)
+ return null;
+ r >>= 3;
+ g >>= 2;
+ b >>= 3;
+ color[0] = (r << 11) + (g << 5) + b;
+ break;
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ if (format != gl.RGBA)
+ return null;
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ a >>= 4;
+ color[0] = (r << 12) + (g << 8) + (b << 4) + a;
+ break;
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ if (format != gl.RGBA)
+ return null;
+ r >>= 3;
+ g >>= 3;
+ b >>= 3;
+ a >>= 7;
+ color[0] = (r << 11) + (g << 6) + (b << 1) + a;
+ break;
+ Default:
+ return null;
+ }
+ return color;
+}
+
+function runTestIteration(format, type, packAlignment, width, height)
+{
+ debug("Testing PACK_ALIGNMENT = " + packAlignment + ", width = " + width + ", height = " + height);
+ gl.clearColor(1, 0.4, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ var bytesPerPixel = calculatePixelBytes(format, type);
+ var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width);
+ var size = bytesPerPixel * width * height + padding * (height - 1);
+ if (type != gl.UNSIGNED_BYTE) {
+ throw "test error: only UNSIGNED_BYTE is valid to ReadPixels";
+ }
+ if (size < 0)
+ size = 0;
+ array = new Uint8Array(size);
+ gl.readPixels(0, 0, width, height, format, type, array);
+ if (width < 0 || height < 0) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ if (!array.length)
+ return;
+
+ // Check the last pixel of the last row.
+ var bytesPerRow = width * bytesPerPixel + padding;
+ var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel;
+ var numComponents = bytesPerPixel;
+ for (var i = 0; i < numComponents; ++i)
+ pixel[i] = array[pos + i];
+ for (var i = numComponents; i < 4; ++i)
+ pixel[i] = 0;
+ expectedColor = packColor(format, type, 255, 102, 0, 255);
+ shouldBeNonNull("expectedColor");
+ shouldBe("pixel", "expectedColor");
+}
+
+description('Verify readPixels() works fine with various PACK_ALIGNMENT values.');
+
+
+debug("<h1>antialias = false</h1>");
+shouldBeNonNull("gl = wtu.create3DContext('example', {antialias: false})")
+var formats = [ gl.RGBA ];
+var formatNames = [ "RGBA" ];
+runAllIterations();
+debug("<h1>antialias = true</h1>");
+shouldBeNonNull("gl = wtu.create3DContext('example2', {antialias: true})")
+runAllIterations();
+
+function runAllIterations() {
+ shouldBeNonNull("program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn'])");
+
+ for (var i = 0; i < formats.length; ++i) {
+ var format = formats[i];
+
+ debug("Testing format = " + formatNames[i] + " and type = UNSIGNED_BYTE");
+ runTestIteration(format, gl.UNSIGNED_BYTE, 1, 1, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 1, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 1, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 2, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 2, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 3, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 3, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 4, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 4, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 1);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 5, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 6, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 7, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 8, 2);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 1, 0, 0);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 2, 0, 0);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, 0);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, 0, 0);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1);
+ runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1);
+ }
+}
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html
new file mode 100644
index 0000000000..078b436427
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html
@@ -0,0 +1,428 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ReadPixels conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="200" height="200" style="width: 20px; height: 20px"></canvas>
+<canvas id="example2" width="200" height="200" style="width: 20px; height: 20px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Checks that ReadPixels works as expected.");
+
+var wtu = WebGLTestUtils;
+let gl;
+
+debug("<h1>antialias = false</h1>")
+runTest(document.getElementById("example"), false);
+debug("<h1>antialias = true</h1>")
+runTest(document.getElementById("example2"), true);
+finishTest();
+
+var actual;
+var expected;
+
+function runTest(canvas, antialias) {
+ gl = wtu.create3DContext(canvas, {antialias: antialias});
+ var contextVersion = wtu.getDefault3DContextVersion();
+
+ var width = 2;
+ var height = 2;
+ var continueTestFunc = continueTestPart1;
+
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Resize the canvas to 2x2. This is an attempt to get stuff in the backbuffer.
+ // that shouldn't be there.
+ canvas.addEventListener("webglcontextlost", function(e) { e.preventDefault(); }, false);
+ canvas.addEventListener("webglcontextrestored", continueTestAfterContextRestored, false);
+ canvas.width = width;
+ canvas.height = height;
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL) {
+ continueTestPart1();
+ }
+
+ function continueTestAfterContextRestored() {
+ window.gl = wtu.create3DContext(canvas);
+ var func = continueTestFunc;
+ window.continueTestFunc = function() { testFailed("should not be here"); };
+ func();
+ }
+
+ function continueTestPart1() {
+ gl.clearColor(0.2, 0.6, 0.4, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var innerColor = [51, 153, 102, 255]; // (0.2, 0.6, 0.4, 1)
+ var outerColor = [19, 72, 0, 198]; // Random color other than [0, 0, 0, 0]
+
+ var tests = [
+ { msg: 'in range', checkColor: innerColor, x: 0, y: 0,
+ oneColor: innerColor, oneX: 0, oneY: 0},
+ { msg: 'off top left', checkColor: outerColor, x: -1, y: -1,
+ oneColor: innerColor, oneX: 1, oneY: 1},
+ { msg: 'off bottom right', checkColor: outerColor, x: 1, y: 1,
+ oneColor: innerColor, oneX: 0, oneY: 0},
+ { msg: 'completely off top ', checkColor: outerColor, x: 0, y: -2,
+ oneColor: outerColor, oneX: 0, oneY: 0},
+ { msg: 'completely off bottom', checkColor: outerColor, x: 0, y: 2,
+ oneColor: outerColor, oneX: 0, oneY: 0},
+ { msg: 'completely off left', checkColor: outerColor, x: -2, y: 0,
+ oneColor: outerColor, oneX: 0, oneY: 0},
+ { msg: 'completeley off right', checkColor: outerColor, x: 2, y: 0,
+ oneColor: outerColor, oneX: 0, oneY: 0}
+ ];
+
+ for (var tt = 0; tt < tests.length; ++tt) {
+ var test = tests[tt];
+ debug("");
+ debug("checking: " + test.msg);
+ checkBuffer(test.checkColor, test.x, test.y,
+ test.oneColor, test.oneX, test.oneY);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors");
+
+ function checkBuffer(checkColor, x, y, oneColor, oneX, oneY) {
+ var buf = new Uint8Array(width * height * 4);
+ // Initialize buf.
+ for (var ii = 0; ii < width * height; ++ii) {
+ buf[ii * 4] = outerColor[0];
+ buf[ii * 4 + 1] = outerColor[1];
+ buf[ii * 4 + 2] = outerColor[2];
+ buf[ii * 4 + 3] = outerColor[3];
+ }
+ gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ var expectedColors = (oneX == xx && oneY == yy) ? oneColor : checkColor;
+ var mismatch = false;
+ for (var cc = 0; cc < 4; ++cc) {
+ var expectedColor = expectedColors[cc];
+ var color = buf[offset + cc];
+ var diff = Math.abs(expectedColor - color);
+ if (diff >= 3) {
+ mismatch = true;
+ break;
+ }
+ }
+ assertMsg(!mismatch,
+ "color pixel at " + xx + ", " + yy + " should be about " + expectedColors +
+ ", was = " + [buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]]);
+ }
+ }
+ }
+
+ continueTestPart2();
+ }
+
+ function continueTestPart2() {
+ let neverValidFormats = [gl.DEPTH_COMPONENT, gl.DEPTH_STENCIL, desktopGL.R8, gl.RGBA4];
+ let maybeValidFormats = [gl.LUMINANCE, gl.LUMINANCE_ALPHA];
+ if (contextVersion < 2) {
+ // They are valid in WebGL 2 or higher
+ maybeValidFormats = maybeValidFormats.concat([desktopGL.RED, desktopGL.RG_INTEGER, desktopGL.RGBA_INTEGER]);
+ }
+
+ let neverValidTypeInfo = [
+ {type: desktopGL.UNSIGNED_INT_24_8, dest: new Uint32Array(4)}
+ ];
+ let maybeValidTypeInfo = [];
+ if (contextVersion < 2) {
+ // They are valid in WebGL 2 or Higher
+ maybeValidTypeInfo = maybeValidTypeInfo.concat([
+ {type: gl.UNSIGNED_SHORT, dest: new Uint16Array(4)},
+ {type: gl.SHORT, dest: new Int16Array(4)},
+ {type: gl.BYTE, dest: new Int8Array(4)},
+ {type: gl.UNSIGNED_INT, dest: new Uint32Array(4)},
+ {type: desktopGL.UNSIGNED_INT_2_10_10_10_REV, dest: new Uint32Array(4)}
+ ]);
+ }
+
+ debug("");
+ debug("check non-default format or type");
+ for (let format of neverValidFormats) {
+ var buf = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, format, gl.UNSIGNED_BYTE, buf);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Should not be able to read as " + wtu.glEnumToString(gl, format));
+ }
+ for (let format of maybeValidFormats) {
+ var buf = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, format, gl.UNSIGNED_BYTE, buf);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "Should not be able to read as " + wtu.glEnumToString(gl, format));
+ }
+
+ for (let info of neverValidTypeInfo) {
+ var type = info.type;
+ var dest = info.dest;
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, type, dest);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Should not be able to read as " + wtu.glEnumToString(gl, type));
+ }
+ for (let info of maybeValidTypeInfo) {
+ var type = info.type;
+ var dest = info.dest;
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, type, dest);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "Should not be able to read as " + wtu.glEnumToString(gl, type));
+ }
+
+
+ // -
+
+ const combinations = [
+ {
+ format: gl.RGB,
+ type: gl.UNSIGNED_SHORT_5_6_5,
+ dest: new Uint8Array(3),
+ },
+ {
+ format: gl.RGBA,
+ type: gl.UNSIGNED_SHORT_5_5_5_1,
+ dest: new Uint16Array(1),
+ },
+ {
+ format: gl.RGBA,
+ type: gl.UNSIGNED_SHORT_4_4_4_4,
+ dest: new Uint16Array(1),
+ },
+ ];
+
+ const FORMATS = [
+ {
+ format: gl.RGBA,
+ channels: 4,
+ }, {
+ format: gl.RGB,
+ channels: 3,
+ }, {
+ format: gl.LUMINANCE_ALPHA,
+ channels: 2,
+ }, {
+ format: gl.ALPHA,
+ channels: 1,
+ }, {
+ format: gl.LUMINANCE,
+ channels: 3,
+ },
+ ];
+ if (contextVersion >= 2) {
+ FORMATS.push(
+ {
+ format: gl.RED,
+ channels: 1,
+ }, {
+ format: gl.RG,
+ channels: 1,
+ }, {
+ format: gl.RGBA_INTEGER,
+ channels: 4,
+ }, {
+ format: gl.RGB_INTEGER,
+ channels: 3,
+ }, {
+ format: gl.RG_INTEGER,
+ channels: 2,
+ }, {
+ format: gl.RED_INTEGER,
+ channels: 1,
+ }
+ );
+ }
+
+ // -
+
+ const TYPES = [
+ {
+ type: gl.UNSIGNED_BYTE,
+ ctor: Uint8Array,
+ }, {
+ type: gl.BYTE,
+ ctor: Int8Array,
+ }, {
+ type: gl.UNSIGNED_SHORT,
+ ctor: Uint16Array,
+ }, {
+ type: gl.SHORT,
+ ctor: Int16Array,
+ }, {
+ type: gl.UNSIGNED_INT,
+ ctor: Uint32Array,
+ }, {
+ type: gl.INT,
+ ctor: Int32Array,
+ }, {
+ type: gl.FLOAT,
+ ctor: Float32Array,
+ }
+ ];
+
+ if (contextVersion >= 2) {
+ TYPES.push(
+ {
+ type: gl.HALF_FLOAT,
+ ctor: Uint16Array,
+ }
+ );
+ }
+
+ const ext = gl.getExtension('OES_texture_half_float');
+ if (ext) {
+ TYPES.push(
+ {
+ type: ext.HALF_FLOAT_OES,
+ ctor: Uint16Array,
+ }
+ );
+ }
+
+ for (const t of TYPES) {
+ for (const f of FORMATS) {
+ const desc = Object.assign({}, f, t);
+ desc.dest = new desc.ctor(desc.channels);
+ combinations.push(desc);
+ }
+ }
+
+ // -
+
+ debug("");
+ debug("check invalid combinations of format/type");
+
+ var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
+ var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
+ debug("IMPLEMENTATION_COLOR_READ_FORMAT: " + wtu.glEnumToString(gl, implFormat));
+ debug("IMPLEMENTATION_COLOR_READ_TYPE: " + wtu.glEnumToString(gl, implType));
+
+ for (var tt = 0; tt < combinations.length; ++ tt) {
+ var info = combinations[tt];
+ var format = info.format;
+ var type = info.type;
+ var dest = info.dest;
+ gl.readPixels(0, 0, 1, 1, format, type, dest);
+ // Only two format/type parameter pairs are accepted. GL_RGBA/GL_UNSIGNED_BYTE is always
+ // accepted on default readbuffer. The other acceptable pair can be discovered by querying
+ // GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
+ if ((format == gl.RGBA && type == gl.UNSIGNED_BYTE) || (format == implFormat && type == implType)) {
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR,
+ "Should be able to read as " + wtu.glEnumToString(gl, format) +
+ " / " + wtu.glEnumToString(gl, type));
+ } else {
+ wtu.glErrorShouldBe(
+ gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM],
+ "Should not be able to read as " + wtu.glEnumToString(gl, format) +
+ " / " + wtu.glEnumToString(gl, type));
+ }
+ }
+
+ debug("");
+ debug("check reading with lots of drawing");
+ continueTestFunc = continueTestPart3;
+ width = 1024;
+ height = 1024;
+ canvas.width = width;
+ canvas.height = height;
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL) {
+ continueTestPart3();
+ }
+ }
+
+ function continueTestPart3() {
+ gl.viewport(0, 0, 1024, 1024);
+ var program = wtu.setupTexturedQuad(gl);
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+ var colors = [[255, 0, 0, 255], [0, 255, 0, 255], [0, 0, 255, 255]];
+ var textures = [];
+ var results = [];
+ for (var ii = 0; ii < colors.length; ++ii) {
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ var tex = gl.createTexture();
+ wtu.fillTexture(gl, tex, 1, 1, colors[ii]);
+ textures.push(tex);
+ }
+ for (var ii = 0; ii < colors.length; ++ii) {
+ for (var jj = 0; jj < 300 + ii + 1; ++jj) {
+ gl.uniform1i(loc, jj % 3);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ var buf = new Uint8Array(4);
+ gl.readPixels(512, 512, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ results.push(buf);
+ for (var kk = 0; kk < 99; ++kk) {
+ gl.uniform1i(loc, (jj + kk) % 3);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ }
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var buf = results[ii];
+ var color = colors[ii];
+ actual = [buf[0], buf[1], buf[2], buf[3]];
+ expected = [color[0], color[1], color[2], color[3]];
+ shouldBe("actual", "expected");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors");
+
+ debug("");
+ debug("check readback into Uint8ClampedArray");
+ continueTestFunc = continueTestPart4;
+ const kSize = 32;
+ canvas.width = kSize;
+ canvas.height = kSize;
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL) {
+ continueTestPart4();
+ }
+ }
+
+ function continueTestPart4() {
+ const kSize = 32;
+ gl.viewport(0, 0, kSize, kSize);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var buf = new Uint8ClampedArray(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors reading back into a Uint8ClampedArray");
+ if (buf[0] == 0 && buf[1] == 255 && buf[2] == 0 && buf[3] == 255) {
+ testPassed("Readback into Uint8ClampedArray worked successfully");
+ } else {
+ assertMsg(false,
+ "color pixel at 0, 0 should be [0, 255, 0, 255], was " +
+ [buf[0], buf[1], buf[2], buf[3]]);
+ }
+
+ const validDatas = [
+ `new Uint8Array(4)`,
+ `new Uint8Array(new ArrayBuffer(4))`,
+ `new Uint8ClampedArray(4)`,
+ `new Uint8ClampedArray(new ArrayBuffer(4))`,
+ ];
+ if (window.SharedArrayBuffer) {
+ validDatas.push(
+ `new Uint8Array(new SharedArrayBuffer(4))`,
+ `new Uint8ClampedArray(new SharedArrayBuffer(4))`
+ );
+ }
+ for (const x of validDatas) {
+ shouldNotThrow(`gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
+ }
+ }
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/00_test_list.txt
new file mode 100644
index 0000000000..af2c30e473
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/00_test_list.txt
@@ -0,0 +1,8 @@
+--min-version 1.0.3 feedback-loop.html
+--max-version 1.9.9 framebuffer-object-attachment.html
+--min-version 1.0.2 framebuffer-state-restoration.html
+--max-version 1.9.9 framebuffer-test.html
+renderbuffer-initialization.html
+--min-version 1.0.4 depth-renderbuffer-initialization.html
+--min-version 1.0.4 stencil-renderbuffer-initialization.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/depth-renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/depth-renderbuffer-initialization.html
new file mode 100644
index 0000000000..ce3e4b89aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/depth-renderbuffer-initialization.html
@@ -0,0 +1,132 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description('Verify depth renderbuffers are initialized to 1.0 before being read in WebGL');
+
+var gl = wtu.create3DContext("testbed");
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ // Set the clear color to green. It should never show up.
+ gl.clearColor(0, 1, 0, 1);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.STENCIL_TEST);
+
+ let c = gl.canvas;
+ for (let i = 0; i < 2; ++i) {
+ runTest(gl, {alloc1: {w: c.width, h: c.height}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height}});
+ // Tests for initially allocating at the wrong size.
+ runTest(gl, {alloc1: {w: 5, h: 5}, alloc2: {w: c.width, h: c.height}});
+ }
+
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[0, 1, 0, 1]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+}
+
+function runTest(gl, params) {
+ debug("Test for depth buffer: " + JSON.stringify(params));
+ let final = params.alloc2 ? params.alloc2 : params.alloc1;
+ gl.viewport(0, 0, final.w, final.h);
+ wtu.checkCanvasRect(gl, 0, 0, final.w, final.h,
+ [0, 0, 0, 0],
+ "internal buffers have been initialized to 0");
+
+ gl.disable(gl.DEPTH_TEST);
+
+ // fill the back buffer so we know that reading below happens from
+ // the renderbuffer.
+ gl.clearDepth(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // Set up (color+depth) test buffer.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var buffer = gl.createRenderbuffer();
+ var depthBuffer = gl.createRenderbuffer();
+
+ if (params.alloc1) {
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ allocStorage(gl.RGBA4, params.alloc1.w, params.alloc1.h);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ allocStorage(gl.DEPTH_COMPONENT16, params.alloc1.w, params.alloc1.h);
+ }
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ if (params.alloc2) {
+ if (params.alloc1) {
+ // Clear the FBO in order to make sure framebufferRenderbuffer is
+ // committed.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ }
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ allocStorage(gl.RGBA4, params.alloc2.w, params.alloc2.h);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ allocStorage(gl.DEPTH_COMPONENT16, params.alloc2.w, params.alloc2.h);
+ }
+
+ function allocStorage(format, width, height) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no error after renderbufferStorage.");
+ }
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ // fbo depth should now be the default value of 1.0.
+
+ // Draw a blue quad (at clip z = 0.0, so depth = 0.5) (should pass the depth test: 0.5 < 1.0)
+ gl.depthFunc(gl.LESS);
+ gl.enable(gl.DEPTH_TEST);
+ wtu.setupColorQuad(gl);
+ wtu.setFloatDrawColor(gl, [0, 0, 1, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, final.w, final.h,
+ [0, 0, 255, 255]);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(buffer);
+
+ gl.canvas.width += 1;
+ gl.canvas.height += 1;
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/feedback-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/feedback-loop.html
new file mode 100644
index 0000000000..e86db74857
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/feedback-loop.html
@@ -0,0 +1,104 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>WebGL Rendering Feedback Loop</title>
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"> </script>
+ </head>
+ <body>
+ <canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+ <div id="description"></div>
+ <div id="console"></div>
+
+ <script id="vs" type="text/something-not-javascript">
+ attribute vec4 a_position;
+ attribute vec2 a_texCoord;
+ varying vec2 v_texCoord;
+ void main() {
+ gl_Position = a_position;
+ v_texCoord = a_texCoord;
+ }
+ </script>
+ <script id="fs" type="text/something-not-javascript">
+ precision mediump float;
+ varying vec2 v_texCoord;
+ uniform sampler2D u_texture;
+ void main() {
+ // Shader swizzles color channels so we can tell if the draw succeeded.
+ gl_FragColor = texture2D(u_texture, v_texCoord).gbra;
+ }
+ </script>
+ <script>
+ "use strict";
+ description("Checks that rendering feedback loops fail correctly.");
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([255, 0, 0, 255]));
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+
+ var framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ assertMsg(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE,
+ "framebuffer should be FRAMEBUFFER_COMPLETE.");
+
+ var program = wtu.setupProgram(gl, ["vs", "fs"], ["a_position", "a_texCoord"]);
+ gl.uniform1i(gl.getUniformLocation(program, "u_texture"), 0);
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initWebGL");
+
+ // Drawing with a texture that is also bound to the current framebuffer should fail
+ var bufferObjects = wtu.setupUnitQuad(gl, 0, 1);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "after draw with invalid feedback loop");
+
+ // Ensure that the texture contents did not change after the previous render
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "Should be blue.");
+
+ // Drawing when texture is bound to an inactive uniform should succeed
+ var texture2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([0, 255, 0, 255]));
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after draw where framebuffer texture is bound to inactive texture unit");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red.");
+
+ var successfullyParsed = true;
+ </script>
+
+ <script src="../../js/js-test-post.js"></script>
+
+ </body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-object-attachment.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-object-attachment.html
new file mode 100644
index 0000000000..b15e1386c7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-object-attachment.html
@@ -0,0 +1,678 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+var fbo;
+var depthBuffer;
+var stencilBuffer;
+var depthStencilBuffer;
+var colorBuffer;
+var width;
+var height;
+
+var ALLOW_COMPLETE = 0x01;
+var ALLOW_UNSUPPORTED = 0x02;
+var ALLOW_INCOMPLETE_ATTACHMENT = 0x04;
+
+function checkFramebufferForAllowedStatuses(allowedStatuses)
+{
+ // If the framebuffer is in an error state for multiple reasons,
+ // we can't guarantee which one will be reported.
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ var statusAllowed = ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRAMEBUFFER_COMPLETE)) ||
+ ((allowedStatuses & ALLOW_UNSUPPORTED) && (status == gl.FRAMEBUFFER_UNSUPPORTED)) ||
+ ((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) && (status == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
+ var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) returned " + status;
+ if (statusAllowed)
+ testPassed(msg);
+ else
+ testFailed(msg);
+}
+
+function checkBufferBits(attachment0, attachment1)
+{
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
+ return;
+
+ var haveDepthBuffer = attachment0 == gl.DEPTH_ATTACHMENT ||
+ attachment0 == gl.DEPTH_STENCIL_ATTACHMENT ||
+ attachment1 == gl.DEPTH_ATTACHMENT ||
+ attachment1 == gl.DEPTH_STENCIL_ATTACHMENT;
+ var haveStencilBuffer = attachment0 == gl.STENCIL_ATTACHMENT ||
+ attachment0 == gl.DEPTH_STENCIL_ATTACHMENT ||
+ attachment1 == gl.STENCIL_ATTACHMENT ||
+ attachment1 == gl.DEPTH_STENCIL_ATTACHMENT;
+
+ shouldBeTrue("gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS) + gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16");
+
+ if (haveDepthBuffer)
+ shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) >= 16");
+ else
+ shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) == 0");
+
+ if (haveStencilBuffer)
+ shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) >= 8");
+ else
+ shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) == 0");
+}
+
+function testAttachment(attachment, buffer, allowedStatuses)
+{
+ shouldBeNonNull("fbo = gl.createFramebuffer()");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebufferForAllowedStatuses(allowedStatuses);
+ if ((allowedStatuses & ALLOW_COMPLETE) == 0) {
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(width * height * 4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
+ }
+ checkBufferBits(attachment);
+ gl.deleteFramebuffer(fbo);
+}
+
+function testAttachments(attachment0, buffer0, attachment1, buffer1, allowedStatuses)
+{
+ shouldBeNonNull("fbo = gl.createFramebuffer()");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment0, gl.RENDERBUFFER, buffer0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebufferForAllowedStatuses(allowedStatuses);
+ checkBufferBits(attachment0, attachment1);
+ gl.deleteFramebuffer(fbo);
+}
+
+function testColorRenderbuffer(internalformat, allowedStatuses)
+{
+ shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalformat, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, allowedStatuses);
+}
+
+function testDepthStencilRenderbuffer(allowedStatuses)
+{
+ shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // OpenGL itself doesn't seem to guarantee that e.g. a 2 x 0
+ // renderbuffer will report 2 for its width when queried.
+ if (!(height == 0 && width > 0))
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)", "width");
+ if (!(width == 0 && height > 0))
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)", "height");
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT)", "gl.DEPTH_STENCIL");
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_RED_SIZE)", "0");
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE)", "0");
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE)", "0");
+ shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)", "0");
+ // Avoid verifying these for zero-sized renderbuffers for the time
+ // being since it appears that even OpenGL doesn't guarantee them.
+ if (width > 0 && height > 0) {
+ shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE) > 0");
+ shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_STENCIL_SIZE) > 0");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatuses);
+ testDepthStencilDepthStencil();
+}
+
+function testDepthStencilDepthStencil()
+{
+ if (!width || !height) {
+ return;
+ }
+
+ var tests = [
+ { firstFormat: gl.DEPTH_COMPONENT16,
+ firstAttach: gl.DEPTH_ATTACHMENT,
+ secondFormat: gl.DEPTH_STENCIL,
+ secondAttach: gl.DEPTH_STENCIL_ATTACHMENT
+ },
+ { firstFormat: gl.DEPTH_STENCIL,
+ firstAttach: gl.DEPTH_STENCIL_ATTACHMENT,
+ secondFormat: gl.DEPTH_COMPONENT16,
+ secondAttach: gl.DEPTH_ATTACHMENT
+ }
+ ];
+ for (var ii = 0; ii < tests.length; ++ii) {
+ var test = tests[ii];
+ for (var jj = 0; jj < 2; ++jj) {
+ var fbo = gl.createFramebuffer();
+ var tex = gl.createTexture();
+ var firstRb = gl.createRenderbuffer();
+
+ debug("");
+ debug("test: " + wtu.glEnumToString(gl, test.firstFormat) + " vs " + wtu.glEnumToString(gl, test.secondFormat) + " with " + (jj ? "unbind" : "delete"));
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ // attach texture as color
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+
+ // attach first
+ gl.bindRenderbuffer(gl.RENDERBUFFER, firstRb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, test.firstFormat, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, test.firstAttach, gl.RENDERBUFFER, firstRb);
+
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.enable(gl.DEPTH_TEST);
+ var program = wtu.setupColorQuad(gl);
+ // Test it works
+ wtu.drawUByteColorQuad(gl, [0, 255, 0, 255]);
+ wtu.drawUByteColorQuad(gl, [255, 0, 0, 255]); // should not draw since DEPTH_FUNC == LESS
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], "should be green");
+
+ var secondRb = gl.createRenderbuffer();
+
+ // attach second
+ gl.bindRenderbuffer(gl.RENDERBUFFER, secondRb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, test.secondFormat, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, test.secondAttach, gl.RENDERBUFFER, secondRb);
+
+ if (jj == 0) {
+ // now delete it
+ debug("test deleting second renderbuffer");
+ gl.deleteRenderbuffer(secondRb);
+ } else {
+ // unbind it
+ debug("test unbinding second renderbuffer");
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, test.secondAttach, gl.RENDERBUFFER, null);
+ }
+
+ // If the first attachment is not restored this may fail
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // If the first attachment is not restored this may fail.
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ wtu.drawUByteColorQuad(gl, [0, 255, 0, 255]);
+ wtu.drawUByteColorQuad(gl, [255, 0, 0, 255]); // should not draw since DEPTH_FUNC == LESS
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], "should be green");
+ gl.disable(gl.DEPTH_TEST);
+
+ if (jj == 1) {
+ gl.deleteRenderbuffer(secondRb);
+ }
+
+ gl.deleteRenderbuffer(secondRb);
+ gl.deleteFramebuffer(fbo);
+ }
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+description("Test framebuffer object attachment behaviors");
+
+shouldBeNonNull("gl = wtu.create3DContext()");
+
+function testFramebufferRequiredCombinations() {
+ debug("Checking combinations of framebuffer attachments required to be valid");
+
+ // Per discussion with the OpenGL ES working group, the following framebuffer attachment
+ // combinations are required to work in all WebGL implementations:
+ // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
+ // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
+ // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var width = 64;
+ var height = 64;
+
+ // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
+ 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);
+ 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, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
+ checkBufferBits();
+
+ // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
+ checkBufferBits(gl.DEPTH_ATTACHMENT);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
+
+ // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
+ checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
+
+ // Clean up
+ gl.deleteRenderbuffer(renderbuffer);
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+}
+
+testFramebufferRequiredCombinations();
+
+for (width = 0; width <= 2; width += 2)
+{
+ for (height = 0; height <= 2; height += 2)
+ {
+ debug("");
+ debug("Dimensions " + width + " x " + height);
+
+ debug("Create renderbuffers");
+ shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeNonNull("depthBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeNonNull("stencilBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var allowedStatusForGoodCase
+ = (width == 0 || height == 0) ? ALLOW_INCOMPLETE_ATTACHMENT : ALLOW_COMPLETE;
+
+ // some cases involving stencil seem to be implementation-dependent
+ var allowedStatusForImplDependentCase = allowedStatusForGoodCase | ALLOW_UNSUPPORTED;
+
+ debug("Attach depth using DEPTH_ATTACHMENT");
+ testAttachment(gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForGoodCase);
+ debug("Attach depth using STENCIL_ATTACHMENT");
+ testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+ debug("Attach depth using DEPTH_STENCIL_ATTACHMENT");
+ testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+ debug("Attach stencil using STENCIL_ATTACHMENT");
+ testAttachment(gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForImplDependentCase);
+ debug("Attach stencil using DEPTH_ATTACHMENT");
+ testAttachment(gl.DEPTH_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+ debug("Attach stencil using DEPTH_STENCIL_ATTACHMENT");
+ testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+ debug("Attach depthStencil using DEPTH_STENCIL_ATTACHMENT");
+ testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForGoodCase);
+ debug("Attach depthStencil using DEPTH_ATTACHMENT");
+ testAttachment(gl.DEPTH_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+ debug("Attach depthStencil using STENCIL_ATTACHMENT");
+ testAttachment(gl.STENCIL_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+
+ var allowedStatusForConflictedAttachment
+ = (width == 0 || height == 0) ? ALLOW_UNSUPPORTED | ALLOW_INCOMPLETE_ATTACHMENT
+ : ALLOW_UNSUPPORTED;
+
+ debug("Attach depth, then stencil, causing conflict");
+ testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment);
+ debug("Attach stencil, then depth, causing conflict");
+ testAttachments(gl.STENCIL_ATTACHMENT, stencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
+ debug("Attach depth, then depthStencil, causing conflict");
+ testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForConflictedAttachment);
+ debug("Attach depthStencil, then depth, causing conflict");
+ testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
+ debug("Attach stencil, then depthStencil, causing conflict");
+ testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForConflictedAttachment);
+ debug("Attach depthStencil, then stencil, causing conflict");
+ testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment);
+
+ debug("Attach color renderbuffer with internalformat == RGBA4");
+ testColorRenderbuffer(gl.RGBA4, allowedStatusForGoodCase);
+
+ debug("Attach color renderbuffer with internalformat == RGB5_A1");
+ testColorRenderbuffer(gl.RGB5_A1, allowedStatusForGoodCase);
+
+ debug("Attach color renderbuffer with internalformat == RGB565");
+ testColorRenderbuffer(gl.RGB565, allowedStatusForGoodCase);
+
+ debug("Create and attach depthStencil renderbuffer");
+ testDepthStencilRenderbuffer(allowedStatusForGoodCase);
+ }
+}
+
+// Determine if we can attach both color and depth or color and depth_stencil
+var depthFormat;
+var depthAttachment;
+
+function checkValidColorDepthCombination() {
+ 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);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+
+ shouldBeNonNull("depthBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+
+ return tryDepth(gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT) || tryDepth(gl.DEPTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT);
+
+ function tryDepth(try_format, try_attachment) {
+ if (depthAttachment) {
+ // If we've tried once unattach the old one.
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, null);
+ }
+ depthFormat = try_format;
+ depthAttachment = try_attachment;
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ return gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE;
+ }
+}
+
+if (checkValidColorDepthCombination()) {
+ testFramebufferIncompleteDimensions();
+ testFramebufferIncompleteAttachment();
+ testFramebufferIncompleteMissingAttachment();
+ testUsingIncompleteFramebuffer();
+ testReadingFromMissingAttachment();
+ testBindRenderbufferBeforeFramebufferAttach();
+}
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) should be " + wtu.glEnumToString(gl, expected) + " was " + wtu.glEnumToString(gl, actual);
+ if (expected != gl.FRAMEBUFFER_COMPLETE) {
+ msg += " or FRAMEBUFFER_UNSUPPORTED";
+ }
+ if (actual == expected ||
+ (expected != gl.FRAMEBUFFER_COMPLETE &&
+ actual == gl.FRAMBUFFER_UNSUPPORTED)) {
+ testPassed(msg);
+ } else {
+ testFailed(msg);
+ }
+}
+
+function testUsingIncompleteFramebuffer() {
+ debug("");
+ debug("Test drawing or reading from an incomplete framebuffer");
+ var program = wtu.setupTexturedQuad(gl);
+ var tex = gl.createTexture();
+ wtu.fillTexture(gl, tex, 1, 1, [0,255,0,255]);
+
+ 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);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+
+ shouldBeNonNull("depthBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+
+ // We pick this combination because it works on desktop OpenGL but should not work on OpenGL ES 2.0
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 32, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+ debug("");
+ debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
+ testRenderingAndReading();
+
+ shouldBeNonNull("fbo2 = gl.createFramebuffer()");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+ debug("");
+ debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
+ testRenderingAndReading();
+
+ shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
+ debug("");
+ debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
+ testRenderingAndReading();
+
+ function testRenderingAndReading() {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "drawArrays with incomplete framebuffer");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "readPixels from incomplete framebuffer");
+ // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because
+ // the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments
+ // the framebuffer is not of a compatible type.
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION], "copyTexImage2D from incomplete framebuffer");
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 1, 1, 0);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION], "copyTexSubImage2D from incomplete framebuffer");
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "clear with incomplete framebuffer");
+ }
+}
+
+function testFramebufferIncompleteAttachment() {
+ 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);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+
+ debug("");
+ debug("Wrong storage type for type of attachment be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0 4.4.5)");
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+
+ debug("");
+ debug("0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0 4.4.5)");
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function testFramebufferIncompleteMissingAttachment() {
+ debug("");
+ debug("No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT (OpenGL ES 2.0 4.4.5)");
+ shouldBeNonNull("fbo = gl.createFramebuffer()");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+
+ shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function testFramebufferIncompleteDimensions() {
+ debug("");
+ debug("Attachments of different sizes should be FRAMEBUFFER_INCOMPLETE_DIMENSIONS (OpenGL ES 2.0 4.4.5)");
+
+ 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);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+
+ shouldBeNonNull("depthBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 32, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 32);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ return;
+ }
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function testReadingFromMissingAttachment() {
+ debug("");
+ debug("Test drawing or reading from a missing framebuffer attachment");
+
+ shouldBeNonNull("fbo = gl.createFramebuffer()");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var size = 16;
+
+ // The only scenario we can verify is an attempt to read or copy
+ // from a missing color attachment while the framebuffer is still
+ // complete.
+ shouldBeNonNull("depthBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After depth renderbuffer setup");
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Unable to allocate a framebuffer with just a depth attachment; this is legal");
+ // Try just a depth/stencil renderbuffer
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
+ shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After depth+stencil renderbuffer setup");
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Unable to allocate a framebuffer with just a depth+stencil attachment; this is legal");
+ return;
+ }
+ }
+
+ // The FBO has no color attachment. ReadPixels, CopyTexImage2D,
+ // and CopyTexSubImage2D should all generate INVALID_OPERATION.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before ReadPixels from missing attachment");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After ReadPixels from missing attachment");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexImage2D from missing attachment");
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, size, size, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexImage2D from missing attachment");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexSubImage2D from missing attachment");
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexSubImage2D from missing attachment");
+}
+
+// [OpenGL ES 2.0.25] Section 4.4.3 page 112
+// [OpenGL ES 3.0.2] Section 4.4.2 page 201
+// 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
+// type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
+function testBindRenderbufferBeforeFramebufferAttach() {
+ debug("");
+ debug("Test calling framebufferRenderbuffer before bindRenderbuffer.");
+
+ let fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ let attachmentTypes = [
+ gl.COLOR_ATTACHMENT0,
+ gl.DEPTH_ATTACHMENT,
+ gl.STENCIL_ATTACHMENT,
+ gl.DEPTH_STENCIL_ATTACHMENT
+ ];
+
+ attachmentTypes.forEach(function(attachmentType) {
+ let strAttachmentType = wtu.glEnumToString(gl, attachmentType);
+ debug("");
+ debug("Testing " + strAttachmentType);
+ let rbo = gl.createRenderbuffer();
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentType, gl.RENDERBUFFER, rbo);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bindRenderbuffer must be called before attachment to " + strAttachmentType);
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl." + strAttachmentType + ", gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachmentType, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Only OBJECT_TYPE can be queried when no image is attached");
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentType, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(rbo);
+ });
+
+ gl.deleteFramebuffer(fbo);
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-state-restoration.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-state-restoration.html
new file mode 100644
index 0000000000..f05a1172c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-state-restoration.html
@@ -0,0 +1,112 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Framebuffer state restoration Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description();
+
+function test() {
+ var gl = wtu.create3DContext("example", {preserveDrawingBuffer: true});
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+ var program = wtu.setupColorQuad(gl);
+ var colorLoc = gl.getUniformLocation(program, "u_color");
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LESS);
+
+ var testDrawToBackBuffer = function(label) {
+ debug("");
+ debug("drawing to backbuffer " + label);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Draw in green
+ gl.uniform4fv(colorLoc, [0, 1, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ // Draw in red, should not draw because of depth test.
+ gl.uniform4fv(colorLoc, [1, 0, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should still be green");
+ }
+
+ var testDrawToFBO = function(label ) {
+ debug("");
+ debug("drawing to framebuffer " + label);
+ // Draw in green
+ gl.uniform4fv(colorLoc, [0, 1, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ // Draw in red as there is not depth buffer.
+ gl.uniform4fv(colorLoc, [1, 0, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+ }
+
+ testDrawToBackBuffer("start");
+
+ var fbo = gl.createFramebuffer();
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 50, 50, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ finishTest();
+ return;
+ }
+
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "should be zero");
+ testDrawToFBO("start");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ testDrawToBackBuffer("after drawing to framebuffer");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ testDrawToFBO("after drawing to backbuffer");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.waitForComposite(function() {
+ testDrawToBackBuffer("after composite");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ testDrawToFBO("after drawing to backbuffer after composite");
+ wtu.waitForComposite(function() {
+ testDrawToFBO("after composite");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ testDrawToBackBuffer("after drawing to framebuffer after composite");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+}
+test();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-test.html
new file mode 100644
index 0000000000..6bf4878cab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/framebuffer-test.html
@@ -0,0 +1,176 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Framebuffer Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/desktop-gl-constants.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This tests framebuffer/renderbuffer-related functions");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking framebuffer/renderbuffer stuff.");
+
+ gl.getFramebufferAttachmentParameter(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "calling getFramebufferAttachmentParameter on the default framebuffer should generate INVALID_OPERATION.");
+
+ assertMsg(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE,
+ "calling checkFramebufferStatus on the default framebuffer should generate FRAMEBUFFER_COMPLETE.");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ canvas.width, // width
+ canvas.height, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ gl.framebufferTexture2D(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ tex,
+ 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "trying to attach a texture to default framebuffer should generate INVALID_OPERATION.");
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.RENDERBUFFER,
+ null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "trying to detach default renderbuffer from default framebuffer should generate INVALID_OPERATION.");
+
+ var rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, canvas.width, canvas.height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "allocating renderbuffer storage of a newly created renderbuffer should succeed.");
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.RENDERBUFFER,
+ rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "trying to attach a renderbuffer to the default framebuffer should generate INVALID_OPERATION.");
+
+ var fbtex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, fbtex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fb = gl.createFramebuffer();
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "binding a newly created framebuffer should succeed.");
+
+ var target = desktopGL.READ_FRAMEBUFFER
+ gl.getFramebufferAttachmentParameter(
+ target,
+ gl.COLOR_ATTACHMENT0,
+ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling getFramebufferAttachmentParameter with target = READ_FRAMEBUFFER should generate INVALID_ENUM.");
+ assertMsg(gl.checkFramebufferStatus(target) == 0,
+ "calling checkFramebufferStatus with target = READ_FRAMEBUFFER should return 0.");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling checkFramebufferStatus with target = READ_FRAMEBUFFER should generate INVALID_ENUM.");
+ gl.bindFramebuffer(target, gl.createFramebuffer());
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling bindFramebuffer with target = READ_FRAMEBUFFER should generate INVALID_ENUM.");
+ assertMsg(fb == gl.getParameter(gl.FRAMEBUFFER_BINDING),
+ "calling bindFramebuffer with target = READ_FRAMEBUFFER should not change FRAMEBUFFER_BINDING.");
+ gl.getFramebufferAttachmentParameter(target, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling getFramebufferAttachmentParameter with target = READ_FRAMEBUFFER should generate INVALID_ENUM.");
+ gl.framebufferTexture2D(target, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling framebufferTexImage2D with target = READ_FRAMEBUFFER should generate INVALID_ENUM.");
+ gl.framebufferRenderbuffer(target, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling framebufferRenderbuffer with target = READ_FRAMEBUFFER should generate INVALID_ENUM.");
+
+ var attachment = desktopGL.COLOR_ATTACHMENT1
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling framebufferTexImage2D with attachment = COLOR_ATTACHMENT1 should generate INVALID_ENUM.");
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling framebufferRenderbuffer with attachment = COLOR_ATTACHMENT1 should generate INVALID_ENUM.");
+
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ desktopGL.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "calling getFramebufferAttachmentParameter with pname = GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING should generate INVALID_ENUM.");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "attaching a texture to a framebuffer should succeed.");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "detaching a texture from a framebuffer should succeed.");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling framebufferTexture2D with non-zero mipmap level should generate INVALID_VALUE.");
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "attaching a renderbuffer to a framebuffer should succeed.");
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "detaching a renderbuffer from a framebuffer should succeed.");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "binding default (null) framebuffer should succeed.");
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/renderbuffer-initialization.html
new file mode 100644
index 0000000000..83406552bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/renderbuffer-initialization.html
@@ -0,0 +1,99 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="400" height="400" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description('Verify renderbuffers are initialized to 0 before being read in WebGL');
+
+var gl = wtu.create3DContext("testbed");
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ // Set the clear color to green. It should never show up.
+ gl.clearColor(0, 1, 0, 1);
+
+ runTest(gl, gl.canvas.width, gl.canvas.height, 0);
+ runTest(gl, gl.canvas.width, gl.canvas.height, 1);
+ runTest(gl, gl.canvas.width, gl.canvas.height, 0);
+ runTest(gl, gl.canvas.width, gl.canvas.height, 1);
+
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[0, 1, 0, 1]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+}
+
+function runTest(gl, width, height, order)
+{
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0,0,0,0],
+ "internal buffers have been initialized to 0");
+
+ // fill the back buffer so we know that reading below happens from
+ // the renderbuffer.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var colorbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
+ switch (order) {
+ case 0:
+ allocStorage(width, height);
+ attachBuffer(colorbuffer);
+ break;
+ case 1:
+ attachBuffer(colorbuffer);
+ allocStorage(width, height);
+ break;
+ }
+
+ function allocStorage(width, height) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no error after renderbufferStorage(internalformat = RGBA4).');
+ }
+
+ function attachBuffer(colorbuffer) {
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorbuffer);
+ }
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed('Framebuffer incomplete.');
+ return;
+ }
+
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0,0,0,0],
+ "user buffers have been initialized to 0");
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(colorbuffer);
+
+ // this clear should not matter we are about to resize
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.canvas.width += 1;
+ gl.canvas.height += 1;
+
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/stencil-renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/stencil-renderbuffer-initialization.html
new file mode 100644
index 0000000000..46dec1fcbf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/renderbuffers/stencil-renderbuffer-initialization.html
@@ -0,0 +1,132 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description('Verify stencil renderbuffers are initialized to 0 before being read in WebGL');
+
+var gl = wtu.create3DContext("testbed");
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ // Set the clear color to green. It should never show up.
+ gl.clearColor(0, 1, 0, 1);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.STENCIL_TEST);
+
+ let c = gl.canvas;
+ for (let i = 0; i < 2; ++i) {
+ runTest(gl, {alloc1: {w: c.width, h: c.height}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height}});
+ // Tests for initially allocating at the wrong size.
+ runTest(gl, {alloc1: {w: 5, h: 5}, alloc2: {w: c.width, h: c.height}});
+ }
+
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[0, 1, 0, 1]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+}
+
+function runTest(gl, params) {
+ debug("Test for stencil buffer: " + JSON.stringify(params));
+ let final = params.alloc2 ? params.alloc2 : params.alloc1;
+ gl.viewport(0, 0, final.w, final.h);
+ wtu.checkCanvasRect(gl, 0, 0, final.w, final.h,
+ [0, 0, 0, 0],
+ "internal buffers have been initialized to 0");
+
+ gl.disable(gl.STENCIL_TEST);
+
+ // fill the back buffer so we know that reading below happens from
+ // the renderbuffer.
+ gl.clearStencil(2);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Set up (color+stencil) test buffer.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var buffer = gl.createRenderbuffer();
+ var stencilBuffer = gl.createRenderbuffer();
+
+ if (params.alloc1) {
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ allocStorage(gl.RGBA4, params.alloc1.w, params.alloc1.h);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
+ allocStorage(gl.STENCIL_INDEX8, params.alloc1.w, params.alloc1.h);
+ }
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilBuffer);
+ if (params.alloc2) {
+ if (params.alloc1) {
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ // Clear the FBO in order to make sure framebufferRenderbuffer is
+ // committed.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ }
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ allocStorage(gl.RGBA4, params.alloc2.w, params.alloc2.h);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
+ allocStorage(gl.STENCIL_INDEX8, params.alloc2.w, params.alloc2.h);
+ }
+
+ function allocStorage(format, width, height) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no error after renderbufferStorage.");
+ }
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ // fbo depth should now be the default value of 0.
+
+ // Draw a blue quad (stencil = 1) (should pass the stencil test: 1 > 0)
+ gl.stencilFunc(gl.GREATER, 1, 0xffffffff);
+ gl.enable(gl.STENCIL_TEST);
+ wtu.setupColorQuad(gl);
+ wtu.setFloatDrawColor(gl, [0, 0, 1, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, final.w, final.h,
+ [0, 0, 255, 255]);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(buffer);
+
+ gl.canvas.width += 1;
+ gl.canvas.height += 1;
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt
new file mode 100644
index 0000000000..9cd801f558
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt
@@ -0,0 +1,44 @@
+--min-version 1.0.4 bind-framebuffer-flush-bug.html
+--min-version 1.0.4 blending.html
+--min-version 1.0.4 canvas-alpha-bug.html
+--min-version 1.0.4 clear-default-framebuffer-with-scissor-test.html
+--min-version 1.0.4 --max-version 1.9.9 clipping-wide-points.html
+--min-version 1.0.4 color-mask-preserved-during-implicit-clears.html
+--min-version 1.0.4 color-mask-should-not-affect-antialiased-framebuffer-resolution.html
+--min-version 1.0.2 culling.html
+--min-version 1.0.4 default-texture-draw-bug.html
+draw-arrays-out-of-bounds.html
+draw-elements-out-of-bounds.html
+--min-version 1.0.4 draw-webgl-to-canvas-2d-repeatedly.html
+--min-version 1.0.4 draw-with-changing-start-vertex-bug.html
+--min-version 1.0.3 framebuffer-switch.html
+--min-version 1.0.3 framebuffer-texture-switch.html
+gl-clear.html
+--min-version 1.0.3 gl-drawarrays.html
+gl-drawelements.html
+gl-scissor-test.html
+--min-version 1.0.2 gl-scissor-fbo-test.html
+--min-version 1.0.3 gl-scissor-canvas-dimensions.html
+--min-version 1.0.3 gl-viewport-test.html
+--min-version 1.0.4 line-rendering-quality.html
+--min-version 1.0.3 many-draw-calls.html
+more-than-65536-indices.html
+multisample-corruption.html
+--min-version 1.0.3 negative-one-index.html
+out-of-bounds-array-buffers.html
+out-of-bounds-index-buffers.html
+--min-version 1.0.3 point-no-attributes.html
+point-size.html
+--min-version 1.0.4 point-specific-shader-variables.html
+--min-version 1.0.3 point-with-gl-pointcoord-in-fragment-shader.html
+--min-version 1.0.3 polygon-offset.html
+--min-version 1.0.4 preservedrawingbuffer-leak.html
+--min-version 1.0.4 rendering-sampling-feedback-loop.html
+--min-version 1.0.4 scissor-rect-repeated-rendering.html
+--min-version 1.0.2 simple.html
+triangle.html
+line-loop-tri-fan.html
+--min-version 1.0.4 framebuffer-texture-clear.html
+--min-version 1.0.4 clear-after-copyTexImage2D.html
+--min-version 1.0.4 texture-switch-performance.html
+--min-version 1.0.4 rendering-stencil-large-viewport.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html
new file mode 100644
index 0000000000..357af132a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html
@@ -0,0 +1,146 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+
+function runTest() {
+ let canvas = document.createElement('canvas');
+ document.body.appendChild(canvas);
+ const gl = wtu.create3DContext(canvas);
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ const size = 100;
+
+ debug('Setup');
+ canvas.width = size;
+ canvas.height = size;
+
+ const texture = gl.createTexture();
+ 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);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ const backbuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, backbuffer);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ const vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([
+ 1, 1,
+ 1, -1,
+ -1, 1,
+ -1, -1,
+ ]));
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 8, 0);
+ gl.enableVertexAttribArray(0);
+
+ const blitTextureProgram = gl.createProgram();
+ const blitTextureVertex = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(blitTextureVertex, `
+ precision mediump float;
+ attribute vec2 pos;
+ varying vec2 uv;
+ void main(){
+ uv = (pos + vec2(1.0)) / 2.0;
+ gl_Position=vec4(pos*2.-1.,0.,1.);
+ }
+ `);
+ gl.compileShader(blitTextureVertex);
+ gl.attachShader(blitTextureProgram, blitTextureVertex);
+ const blitTextureFragment = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(blitTextureFragment, `
+ precision mediump float;
+ uniform sampler2D texture;
+ varying vec2 uv;
+ void main(){
+ gl_FragColor=texture2D(texture, uv);
+ }
+ `);
+ gl.compileShader(blitTextureFragment);
+ gl.attachShader(blitTextureProgram, blitTextureFragment);
+ gl.linkProgram(blitTextureProgram);
+
+ const solidColorProgram = gl.createProgram();
+ const solidColorVertex = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(solidColorVertex, `
+ precision mediump float;
+ attribute vec2 pos;
+ void main(){
+ gl_Position=vec4(pos,0.,1.);
+ }
+ `);
+ gl.compileShader(solidColorVertex);
+ gl.attachShader(solidColorProgram, solidColorVertex);
+ const solidColorFragment = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(solidColorFragment, `
+ precision mediump float;
+ void main(){
+ gl_FragColor=vec4(0.,0.,1.,1.);
+ }
+ `);
+ gl.compileShader(solidColorFragment);
+ gl.attachShader(solidColorProgram, solidColorFragment);
+ gl.bindAttribLocation(solidColorProgram, 0, "pos");
+ gl.linkProgram(solidColorProgram);
+ gl.clearColor(1, 0, 0, 1);
+
+ debug('Drawing');
+ // Draw blue rectangle to backbuffer texture
+ gl.bindFramebuffer(gl.FRAMEBUFFER, backbuffer);
+ gl.useProgram(solidColorProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ // Blit backbuffer texture to screen
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.useProgram(blitTextureProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ // Clear backbuffer texture to red
+ gl.bindFramebuffer(gl.FRAMEBUFFER, backbuffer);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Blit backbuffer texture to screen
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.useProgram(blitTextureProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ debug('Expected: canvas should be red');
+ debug('Buggy: canvas is blue');
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 0], 'should be red');
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verifies workaround for bug in Intel drivers where clear and drawArrays calls are reordered across bindFramebuffer.');
+debug('Regression test for <a href="http://crbug.com/1018028">http://crbug.com/1018028</a>');
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
new file mode 100644
index 0000000000..b14705cd50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
@@ -0,0 +1,266 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="eVsSrc" type="text/plain">
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+
+<script id="eFsSrc" type="text/plain">
+precision mediump float;
+uniform vec4 uColor;
+
+void main()
+{
+ gl_FragColor = uColor;
+}
+</script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Blending tests');
+
+const wtu = WebGLTestUtils;
+
+function CreateContext() {
+ const gl = wtu.create3DContext();
+ gl.viewport(0, 0, 1, 1);
+
+ gl.prog = wtu.setupProgram(gl, [eVsSrc.innerHTML, eFsSrc.innerHTML]);
+ gl.prog.uColor = (() => {
+ const loc = gl.getUniformLocation(gl.prog, 'uColor');
+ return x => gl.uniform4fv(loc, x);
+ })();
+ gl.useProgram(gl.prog);
+ gl.prog.uColor([1 / 255, 2 / 255, 3 / 255, 4 / 255]);
+
+ gl.drawAndRead = type => {
+ gl.drawArrays(gl.POINTS, 0, 1);
+ let ret;
+ if (type == gl.UNSIGNED_BYTE) {
+ ret = new Uint8Array(4);
+ } else if (type == gl.FLOAT) {
+ ret = new Float32Array(4);
+ }
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, type, ret);
+ return ret;
+ };
+
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
+
+ return gl;
+}
+
+function CreateValidFb(gl, formats) {
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ for (let i in formats) {
+ i = i|0; // Otherwise i is a string. :(
+ const f = formats[i];
+ if (!f)
+ continue;
+ if (f.length == 1) {
+ const rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, f[0], 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
+ gl.RENDERBUFFER, rb);
+ continue;
+ }
+ if (f.length == 3) {
+ let internalFormat = f[0];
+ if (internalFormat === undefined) {
+ internalFormat = f[1];
+ }
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1,1,0, f[1],f[2], null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
+ gl.TEXTURE_2D, tex, 0);
+ continue;
+ }
+ throw new Error('Invalid format length: ' + f);
+ }
+
+ const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE) {
+ gl.deleteFramebuffer(fb);
+ return null;
+ }
+ return fb;
+}
+
+let was, fb;
+
+const TESTS = [
+ () => {
+ debug('');
+ debug('Clamping of blendColor args:');
+
+ const gl = wtu.create3DContext();
+ if (!gl.texImage3D) { // WebGL 1.0
+ // WebGL 1.0 clamps without EXT_color_buffer_half_float or WEBGL_color_buffer_float.
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.getParameter(gl.BLEND_COLOR);
+ expectArray(was, [1, 1, 1, 1]);
+
+ const ext = gl.getExtension('EXT_color_buffer_half_float') ||
+ gl.getExtension('WEBGL_color_buffer_float');
+ if (!ext) return;
+ }
+
+ // WebGL 2.0 or extended WebGL 1.0 may still clamp the value on store
+ // when the underlying platform does the same.
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.getParameter(gl.BLEND_COLOR);
+ if (was[0] == 1000) {
+ expectArray(was, [1000, 1, 1, 1]);
+ } else {
+ debug("Platform does not support unclamped blend color.")
+ expectArray(was, [1, 1, 1, 1]);
+ }
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA8:');
+
+ const gl = CreateContext();
+ fb = CreateValidFb(gl, [[gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE]]);
+ shouldBeNonNull('fb');
+
+ // Regardless of the context version and enabled extensions,
+ // the value will be clamped at draw time,
+ gl.blendColor(10, 1, 1, 1);
+ const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
+ expectArray(was, [1, 2, 3, 4]);
+
+ if (gl.getExtension('EXT_color_buffer_half_float') ||
+ gl.getExtension('WEBGL_color_buffer_float') ||
+ gl.getExtension('EXT_color_buffer_float'))
+ {
+ debug('Enable floating-point color buffers and retest');
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
+ expectArray(was, [1, 2, 3, 4]);
+ }
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA16F:');
+
+ const gl = CreateContext();
+
+ // Set the value before enabling the extension.
+ // It must be clamped only on WebGL 1.0 contexts.
+ gl.blendColor(10, 1, 1, 1);
+ if (!gl.getExtension('EXT_color_buffer_half_float')) {
+ testPassed('Missing ext EXT_color_buffer_half_float is optional, skipping.');
+ return;
+ }
+ if (!gl.texImage3D) { // WebGL 1.0
+ const ext = gl.getExtension('OES_texture_half_float');
+ gl.HALF_FLOAT = ext.HALF_FLOAT_OES; // These aren't the same value, but this'll work.
+ }
+
+ fb = CreateValidFb(gl, [[gl.RGBA16F, gl.RGBA, gl.HALF_FLOAT]]);
+ shouldBeNonNull('fb');
+ gl.prog.uColor([1, 2, 3, 4]);
+
+ let was = gl.drawAndRead(gl.FLOAT);
+ if (!gl.texImage3D) { // WebGL 1.0
+ expectArray(was, [1, 2, 3, 4]);
+ } else {
+ // Some WebGL 2.0 implementations may clamp the blend color anyway.
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ expectArray(was, [r, 2, 3, 4]);
+ }
+
+ // Re-set the value after the extension was enabled.
+ gl.blendColor(100, 1, 1, 1);
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ was = gl.drawAndRead(gl.FLOAT);
+ expectArray(was, [r, 2, 3, 4]);
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA32F:');
+
+ const gl = CreateContext();
+
+ // Set the value before enabling the extension.
+ // It must be clamped only on WebGL 1.0 contexts.
+ gl.blendColor(10, 1, 1, 1);
+ if (gl.texImage3D) { // WebGL 2.0
+ if (!gl.getExtension('EXT_color_buffer_float')) {
+ testPassed('Missing ext EXT_color_buffer_float is optional, skipping.');
+ return;
+ }
+ } else {
+ if (!gl.getExtension('WEBGL_color_buffer_float')) {
+ testPassed('Missing ext WEBGL_color_buffer_float is optional, skipping.');
+ return;
+ }
+ gl.getExtension('OES_texture_float');
+ }
+ fb = CreateValidFb(gl, [[gl.RGBA32F, gl.RGBA, gl.FLOAT]]);
+ shouldBeNonNull('fb');
+ gl.prog.uColor([1, 2, 3, 4]);
+
+ let was = gl.drawAndRead(gl.FLOAT);
+ if (!gl.texImage3D) { // WebGL 1.0
+ expectArray(was, [1, 2, 3, 4]);
+ } else {
+ // Some WebGL 2.0 implementations may clamp the blend color anyway.
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ expectArray(was, [r, 2, 3, 4]);
+ }
+
+ // Re-set the value after the extension was enabled.
+ gl.blendColor(100, 1, 1, 1);
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ was = gl.drawAndRead(gl.FLOAT);
+
+ if (!gl.getExtension('EXT_float_blend')) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'Should not be able to blend 32F formats.');
+ return;
+ }
+ wtu.glErrorShouldBe(gl, 0, 'Should be able to blend 32F formats.');
+ expectArray(was, [r, 2, 3, 4]);
+ },
+];
+
+async function Test() {
+ for (const fn of TESTS) {
+ await wtu.dispatchPromise(fn);
+ }
+ wtu.destroyAllContexts();
+ finishTest();
+}
+
+Test();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html
new file mode 100644
index 0000000000..f6225ffae2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html
@@ -0,0 +1,116 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Alpha blending bug on WebGL canvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 a_position;
+varying vec2 v_uv;
+void main()
+{
+ v_uv = a_position.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5);
+ gl_Position = vec4(a_position.xy, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 v_uv;
+uniform sampler2D u_texture;
+uniform vec4 u_color;
+void main()
+{
+ vec4 tex = texture2D(u_texture, v_uv);
+ gl_FragColor = tex * u_color;
+}
+</script>
+
+<script>
+"use strict";
+// This test exposes an Intel driver issue on macOS.
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+
+var program;
+var offscreen_tex;
+var fbo;
+
+function init()
+{
+ // Init program
+ program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position"]);
+
+ // Init offscreen render targets and specify the format of offscreen texture to be RGB.
+ offscreen_tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, offscreen_tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, canvas.width, canvas.height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, offscreen_tex, 0);
+
+ // Init blend state
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+}
+
+function draw_rect()
+{
+ gl.useProgram(program);
+
+ gl.bindTexture(gl.TEXTURE_2D, offscreen_tex);
+ var u_tex_loc = gl.getUniformLocation(program, 'u_texture');
+ gl.uniform1i(u_tex_loc, 0);
+
+ wtu.setupUnitQuad(gl);
+ wtu.drawFloatColorQuad(gl, [1.0, 1.0, 1.0, 1.0]);
+}
+
+function test_canvas_alpha() {
+ init();
+
+ // Clear offscreen texture to Green
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Clear default framebuffer
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Enable alpha blending and render to default framebuffer
+ gl.enable(gl.BLEND);
+ draw_rect();
+ wtu.checkCanvasRect(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, [0, 255, 0, 255]);
+}
+
+test_canvas_alpha();
+
+description("Exposes alpha blending bug in Intel drivers on macOS - see https://crbug.com/886970");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html
new file mode 100644
index 0000000000..576b0cc6ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html
@@ -0,0 +1,64 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL clear after copyTexImage2D with a non-pure color</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+"use strict";
+// This test verifies a Intel D3D driver bug.
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", {"antialias" : "true"});
+
+function testClearAfterCopyTexImage2DWithoutPureOneOrZero(clearColor, expectedColor)
+{
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var width = 16;
+ var height = 16;
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0);
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.checkCanvasRect(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, expectedColor);
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(texture);
+}
+
+description("Test that if clear with a color that has non-0/1 RGB components after copyTexImage2D, the final render color should be consistent with the clear color.");
+
+for(var index = 0; index < 3; index++)
+{
+ var clearColor = [0, 0, 0, 1];
+ var expectedColor = [0, 0, 0, 255];
+ clearColor[index] = 0.8;
+ expectedColor[index] = 255 * clearColor[index];
+ testClearAfterCopyTexImage2DWithoutPureOneOrZero(clearColor, expectedColor);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html
new file mode 100644
index 0000000000..d33555f2bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html
@@ -0,0 +1,68 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Clear with scissor bug on WebGL canvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas-webgl" width="20" height="20"> </canvas>
+<canvas id="canvas-2d" width="20" height="20"> </canvas>
+
+<script>
+"use strict";
+// This test exposes an issue in older Intel D3D drivers.
+var wtu = WebGLTestUtils;
+
+function test_clear_with_scissor_on_canvas()
+{
+ var canvasWebGL = document.getElementById("canvas-webgl");
+ var gl = canvasWebGL.getContext("webgl", { antialias:false });
+ const scissorRectSize = 16;
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(0, 0, scissorRectSize, scissorRectSize);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // The issue is found in the Chromium compositor so we need another canvas element for reproduction.
+ var canvas2D = document.getElementById("canvas-2d");
+ var context2D = canvas2D.getContext('2d');
+ context2D.drawImage(canvasWebGL, 0, 0);
+ context2D.fill();
+
+ var imageData =
+ context2D.getImageData(0, canvas2D.clientHeight - scissorRectSize, scissorRectSize, scissorRectSize);
+ var data = imageData.data;
+ var expectedColor = [0, 255, 0, 255];
+ for (var pixelIndex = 0; pixelIndex < scissorRectSize * scissorRectSize; ++pixelIndex) {
+ for (var colorIndex = 0; colorIndex < 4; ++colorIndex) {
+ if (data[pixelIndex * 4 + colorIndex] !== expectedColor[colorIndex]) {
+ var y = Math.floor(pixelIndex / scissorRectSize);
+ var x = pixelIndex % scissorRectSize;
+ testFailed("The canvas color at (" + x + ", " + y + ") is not expected");
+ return;
+ }
+ }
+ }
+}
+
+test_clear_with_scissor_on_canvas();
+
+description("Exposes clearing WebGL canvas with scissor bug on Intel D3D drivers - see https://crbug.com/1206763");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html
new file mode 100644
index 0000000000..f38aa0c4d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clipping wide points test</title>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="1" height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/clipping-wide-points.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html
new file mode 100644
index 0000000000..4aa8740cbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ColorMask Must Be Preserved During Implicit Clears</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="canvases"></div>
+<div id="console"></div>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+const sz = 128;
+let frames;
+let gl;
+let tests = [
+ { alpha: false, antialias: false, premultipliedAlpha: false },
+ { alpha: false, antialias: false, premultipliedAlpha: true },
+ { alpha: false, antialias: true, premultipliedAlpha: false },
+ { alpha: false, antialias: true, premultipliedAlpha: true },
+];
+let currentTest;
+let testIndex = 0;
+
+function initTest() {
+ description();
+ debug('ColorMask must be preserved during implicit clears of textures.');
+ debug('Regression test for <a href="http://crbug.com/911918">http://crbug.com/911918</a>');
+
+ requestAnimationFrame(nextTest);
+}
+
+function nextTest() {
+ if (testIndex >= tests.length) {
+ finishTest();
+ return;
+ }
+
+ frames = 20;
+ let canvases = document.getElementById('canvases');
+ let canvas = document.createElement('canvas');
+ canvas.width = sz;
+ canvas.height = sz;
+ canvases.appendChild(canvas);
+ currentTest = tests[testIndex];
+ ++testIndex;
+ gl = wtu.create3DContext(canvas, currentTest);
+ requestAnimationFrame(runTest);
+}
+
+function runTest() {
+ // Create a user-defined framebuffer which has an alpha channel.
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ // Set color mask to disable alpha writes. This is important; see below.
+ gl.colorMask(true, true, true, false);
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sz, sz, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ // Upload a sub-rectangle. In Chrome, this was lazily clearing level 0 of the
+ // texture using OpenGL, setting the driver's color mask to (true, true, true,
+ // true) in the process. Because the user's color mask was set to (true, true,
+ // true, false) above, incorrect caching code was failing to reset the
+ // driver's color mask later. On macOS, Chrome implements alpha:false WebGL
+ // contexts on top of RGBA textures whose alpha channel is cleared to 1.0 and
+ // where the color mask is set to (true, true, true, false) during all writes.
+ // This bug was allowing that texture's alpha channel to be destroyed.
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ // We have to issue one clear to this framebuffer to get the color mask
+ // latched into the internal caching code.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Switch back to default framebuffer.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ // Set clear color to transparent green.
+ gl.clearColor(0, 1, 0, 0);
+ // Clear. Result should be opaque green. Was transparent green when
+ // bug was encountered.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz,
+ [ 0, 255, 0, 255 ],
+ "default framebuffer should be opaque green for " + JSON.stringify(currentTest));
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+
+ --frames;
+ if (frames == 0) {
+ requestAnimationFrame(nextTest);
+ } else {
+ requestAnimationFrame(runTest);
+ }
+}
+
+requestAnimationFrame(initTest);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html
new file mode 100644
index 0000000000..7bba52e9a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html
@@ -0,0 +1,71 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ColorMask Should Not Affect Antialiased Framebuffer Resolution</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description("This test verifies that the colorMask state does not affect resolution of the antialiased framebuffer.");
+
+debug('Regression test for <a href="https://crbug.com/1257769">https://crbug.com/1257769</a> and <a href="https://bugs.webkit.org/show_bug.cgi?id=220129">https://bugs.webkit.org/show_bug.cgi?id=220129</a>');
+
+function run() {
+ const gl = wtu.create3DContext("canvas", { antialias: true, alpha: true });
+
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+ return;
+ }
+
+ testPassed("WebGL context exists");
+
+ const program = wtu.setupColorQuad(gl);
+
+ // Clear the default (multisampled) framebuffer to red.
+ gl.clearColor(1, 0, 0, 1);
+ gl.colorMask(true, true, true, true);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw a transparent green quad.
+ gl.useProgram(program);
+ wtu.drawFloatColorQuad(gl, [ 0, 255, 0, 0 ]);
+
+ // Clear the alpha channel.
+ gl.colorMask(false, false, false, true);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // At this point, even setting the colorMask to all-true won't
+ // work around the bug, since that state is latched inside ANGLE
+ // only during draws / clears.
+
+ wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "should be green", 1);
+ finishTest();
+}
+
+var successfullyParsed = true;
+
+requestAnimationFrame(run);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html
new file mode 100644
index 0000000000..74321f5cdd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html
@@ -0,0 +1,127 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 0, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 col;
+
+void main()
+{
+ gl_FragColor = col;
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+function draw(gl, arr, colLoc, col) {
+ var vertices = new Float32Array(arr);
+ var vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ gl.uniform4fv(colLoc, col);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 2);
+}
+
+function clear(gl, col) {
+ gl.clearColor(col[0], col[1], col[2], col[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+}
+
+function check(gl, winding, shoulddraw) {
+ var msg = winding + ' face was ' + (shoulddraw ? '' : 'not ') + 'drawn.';
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255], msg);
+}
+
+function runTest() {
+ var cwVertices = [-1, -1, -1, 1, 1, -1, 1, 1];
+ var ccwVertices = [-1, 1, -1, -1, 1, 1, 1, -1];
+ var red = [1, 0, 0, 1];
+ var green = [0, 1, 0, 1];
+ var ok;
+
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos']);
+ var colLoc = gl.getUniformLocation(program, 'col');
+
+ gl.enableVertexAttribArray(0);
+
+ debug('CULL_FACE should be off by default');
+ clear(gl, red);
+ draw(gl, ccwVertices, colLoc, green);
+ check(gl, 'CCW', true);
+ clear(gl, red);
+ draw(gl, cwVertices, colLoc, green);
+ check(gl, 'CW', true);
+
+ debug('Enabling CULL_FACE');
+ gl.enable(gl.CULL_FACE);
+
+ debug('BACK and CCW should be set by default');
+ clear(gl, red);
+ draw(gl, ccwVertices, colLoc, green);
+ check(gl, 'CCW', true);
+ clear(gl, green);
+ draw(gl, cwVertices, colLoc, red);
+ check(gl, 'CW', false);
+
+ var tests = [{ cullFace : 'BACK', frontFace : 'CCW', drawCCW : true, drawCW : false},
+ { cullFace : 'BACK', frontFace : 'CW', drawCCW : false, drawCW : true},
+ { cullFace : 'FRONT', frontFace : 'CCW', drawCCW : false, drawCW : true },
+ { cullFace : 'FRONT', frontFace : 'CW', drawCCW : true, drawCW : false},
+ { cullFace : 'FRONT_AND_BACK', frontFace : 'CCW', drawCCW : false, drawCW : false},
+ { cullFace : 'FRONT_AND_BACK', frontFace : 'CW', drawCCW : false, drawCW : false}];
+
+ for (var i = 0; i < tests.length; ++i) {
+ var t = tests[i];
+ debug('Setting ' + t.cullFace + ' and ' + t.frontFace);
+ gl.cullFace(gl[t.cullFace]);
+ gl.frontFace(gl[t.frontFace]);
+ clear(gl, t.drawCCW ? red : green);
+ draw(gl, ccwVertices, colLoc, t.drawCCW ? green : red);
+ check(gl, 'CCW', t.drawCCW);
+ clear(gl, t.drawCW ? red : green);
+ draw(gl, cwVertices, colLoc, t.drawCW ? green : red);
+ check(gl, 'CW', t.drawCW);
+ }
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="16" height="16" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that culling works');
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html
new file mode 100644
index 0000000000..0d71a0aaa5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html
@@ -0,0 +1,69 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Default Texture Draw Bug Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+</head>
+<body>
+<canvas id="c"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test attempts to provoke a Chrome bug that occured when drawing with textures when one was never bound. <a href='http://crbug.com/524144'>crbug.com/524144</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c");
+var canvas = gl.canvas;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runDrawTests();
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runDrawTests(drawType) {
+ debug("Test that drawing with a texture when no textures have been bound gives the expected black output");
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ // Set up a program that will draw with a texture
+ var program = wtu.setupNoTexCoordTextureProgram(gl);
+
+ wtu.setupIndexedQuad(gl);
+ for (var i = 0 ; i < 100 && _bufferedConsoleLogs != null; ++i) {
+ // Clear to white.
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // Draw without binding any textures.
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+
+ // Check to ensure the entire canvas is black.
+ wtu.checkCanvasRect(gl, 0.0, 0.0, canvas.width, canvas.height,
+ [0.0, 0.0, 0.0], "Draw should pass", 2);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html
new file mode 100644
index 0000000000..6577fa0b0a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html
@@ -0,0 +1,33 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/out-of-bounds-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test of drawArrays with out-of-bounds parameters");
+
+OutOfBoundsTest.runDrawArraysTest('gl.drawArrays(gl.TRIANGLES, $(offset), $(count))',
+ WebGLTestUtils.create3DContext(), WebGLTestUtils);
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html
new file mode 100644
index 0000000000..74f7f8eaf5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html
@@ -0,0 +1,33 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/out-of-bounds-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test of drawElements with out-of-bounds parameters");
+
+OutOfBoundsTest.runDrawElementsTest("gl.drawElements(gl.TRIANGLES, $(count), $(type), $(offset))",
+ WebGLTestUtils.create3DContext(), WebGLTestUtils);
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html
new file mode 100644
index 0000000000..d9a83e9166
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Draw WebGL to Canvas2D Repeatedly</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas-webgl" width="256" height="256"></canvas>
+<canvas id="canvas-2d" width="256" height="256"></canvas>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+
+const sz = 256;
+
+function drawTo2DCanvas(c2, webGLCanvas) {
+ // Always clear 2D canvas to solid green first.
+ c2.clearRect(0, 0, sz, sz);
+ c2.fillStyle = 'rgb(0,255,0)';
+ c2.fillRect(0, 0, sz, sz);
+ // Draw WebGL canvas to this canvas.
+ c2.drawImage(webGLCanvas, 0, 0);
+}
+
+function runTest() {
+ description();
+ debug('Repeatedly drawing a WebGL canvas to a 2D canvas should only draw the most recently rendered WebGL content.');
+ debug('Regression test for <a href="http://crbug.com/894021">http://crbug.com/894021</a>');
+
+ let c2 = document.getElementById('canvas-2d').getContext('2d');
+ let webGLCanvas = document.getElementById('canvas-webgl');
+ let gl = wtu.create3DContext(webGLCanvas, { alpha: true, antialias: false, premultipliedAlpha: true });
+ let tolerance = 2;
+
+ // Clear left half of WebGL canvas to red and right half to
+ // transparent black.
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.scissor(0, 0, sz / 2, sz);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Draw to 2D canvas.
+ drawTo2DCanvas(c2, webGLCanvas);
+
+ // Clear right half of WebGL canvas to red and left half to
+ // transparent black.
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.scissor(sz / 2, 0, sz / 2, sz);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Draw to 2D canvas.
+ drawTo2DCanvas(c2, webGLCanvas);
+
+ // Clear WebGL canvas to transparent black.
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Draw to 2D canvas.
+ drawTo2DCanvas(c2, webGLCanvas);
+
+ // 2D canvas should be green.
+ // In the error case, the rendering results from earlier draws were
+ // being accumulated, so the 2D canvas was ultimately red.
+ wtu.checkCanvasRect(c2, 0, 0, sz, sz,
+ [ 0, 255, 0, 255 ],
+ "should be green",
+ tolerance);
+
+ finishTest();
+}
+
+requestAnimationFrame(runTest);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html
new file mode 100644
index 0000000000..8b8dc71f59
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html
@@ -0,0 +1,114 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+This bug would occur after the app would render several times with the
+same vertex attributes and buffers, but using a different start offset.
+One of the buffers would likely have to be DYNAMIC.
+
+See http://anglebug.com/1327 and http://crbug.com/594509
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Draw with changing start vertex test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute mediump vec4 position;
+attribute mediump vec4 test;
+attribute mediump vec4 expected;
+varying mediump vec4 color;
+void main(void)
+{
+ gl_Position = position;
+ vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
+ color = vec4(lessThanEqual(abs(test - expected), threshold));
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+varying mediump vec4 color;
+void main(void)
+{
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+"use strict";
+description("Test calling drawArrays with repeatedly with a different start vertex");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas1");
+var gl = wtu.create3DContext(canvas);
+
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position", "test", "expected"]);
+
+var vertexCount = 24;
+var testData = new Float32Array(vertexCount);
+
+for (var index = 0; index < vertexCount; ++index) {
+ testData[index] = index;
+}
+
+var quadData = new Float32Array(14)
+quadData[0] = -1.0; quadData[1] = 1.0;
+quadData[2] = -1.0; quadData[3] = -1.0;
+quadData[4] = 1.0; quadData[5] = -1.0;
+quadData[6] = -1.0; quadData[7] = 1.0;
+quadData[8] = 1.0; quadData[9] = -1.0;
+quadData[10] = 1.0; quadData[11] = 1.0;
+quadData[12] = 0.0; quadData[13] = 0.0;
+
+var quadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, quadData, gl.STATIC_DRAW);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(0);
+
+// Must be STATIC to trigger the bug.
+var testBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, testBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, testData, gl.STATIC_DRAW);
+gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(1);
+
+// Must be DYNAMIC to trigger the bug.
+var expectedBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, expectedBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, testData, gl.DYNAMIC_DRAW);
+gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(2);
+
+function check() {
+ wtu.checkCanvas(gl, [255, 255, 255, 255], "should be white");
+}
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+check()
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+check()
+
+gl.drawArrays(gl.TRIANGLES, 1, 6);
+check()
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html
new file mode 100644
index 0000000000..df2a9ef55e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer switching conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test framebuffer switching. The test switches between two framebuffers, copying rendering results from one to the other.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupTexturedQuad(gl);
+
+var tex1 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex1);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+var fb1 = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+
+var tex2 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex2);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+var fb2 = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0);
+
+gl.bindTexture(gl.TEXTURE_2D, tex1);
+gl.clearColor(1.0, 1.0, 1.0, 1.0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var iterate = function(checkFBOs, iterations) {
+ for (var i = 0; i < iterations; ++i) {
+ debug("Clearing framebuffer 1 to white");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ debug("Copying framebuffer 1 to framebuffer 2");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ // Read what is in fb2
+ wtu.checkCanvas(gl, [255,255,255,255], "Framebuffer 2 should be white");
+};
+
+debug("");
+debug("Warm-up iteration");
+iterate(true, 1);
+
+debug("");
+debug("Iterating the test a few times since at least one bug it has exposed is somewhat flaky.");
+for (var i = 0; i < 3; ++i) {
+ debug("");
+ debug("Iteration " + (i + 1));
+ iterate(false, 2);
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html
new file mode 100644
index 0000000000..dc5d60def8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer clearColor with pure 0/1</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+// This test verifies a Mac Intel HD 6000/6100 driver bug. See crbug.com/710443.
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+
+function InitializeRGBAData(width, height)
+{
+ var size = 4 * width * height;
+ var data = new Uint8Array(size);
+ for (var i = 0; i < size; i++) {
+ data[i] = 128;
+ }
+ return data;
+}
+
+function testFramebufferTextureClearWithPureZeroOrOne(clearColor, expectedColor) {
+ var width = 32;
+ var height = 32;
+ var texture0 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ // It seems that if we add texParameteri here, all cases can pass no matter
+ // you use texParameteri or not in Line 85.
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ var texData = InitializeRGBAData(width, height);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, texData);
+
+ var fbo0 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture0, 0);
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var texture1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fbo1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0);
+
+ wtu.setupTexturedQuad(gl);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
+ gl.viewport(0, 0, width, height);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, expectedColor);
+
+ gl.deleteTexture(texture0);
+ gl.deleteFramebuffer(fbo0);
+ gl.deleteTexture(texture1);
+ gl.deleteFramebuffer(fbo1);
+}
+
+description("Test that if clear fbo texture color with pure 0/1 and sample this texture to draw to another fbo, the final render color should be consistent with the clear color.");
+
+for(var index = 0; index < 16; index++)
+{
+ var r = (index & 8) / 8;
+ var g = (index & 4) / 4;
+ var b = (index & 2) / 2;
+ var a = index & 1;
+ var clearColor = [r, g, b, a];
+ var expectedColor = [r * 255, g * 255, b * 255, a * 255];
+ testFramebufferTextureClearWithPureZeroOrOne(clearColor, expectedColor);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html
new file mode 100644
index 0000000000..0043bc74de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html
@@ -0,0 +1,87 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer texture attachment switching conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test framebuffer texture attachment switching. The test uses one framebuffer object and switches its color attachment.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupTexturedQuad(gl);
+
+var fb = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+var tex2 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex2);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+var tex1 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex1);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+gl.clearColor(1.0, 1.0, 1.0, 1.0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var iterate = function(checkFBOs, iterations) {
+ for (var i = 0; i < iterations; ++i) {
+ debug("Clearing tex1 to white");
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ debug("Copying tex1 to tex2");
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ // Read what is in tex2
+ wtu.checkCanvas(gl, [255,255,255,255], "tex2 should be white");
+};
+
+debug("");
+debug("Warm-up iteration");
+iterate(true, 1);
+
+debug("");
+debug("Iterating the test a few times since at least one bug it has exposed is somewhat flaky.");
+for (var i = 0; i < 3; ++i) {
+ debug("");
+ debug("Iteration " + (i + 1));
+ iterate(false, 2);
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html
new file mode 100644
index 0000000000..e9c7210e81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html
@@ -0,0 +1,67 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL clear conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="1" height="1" style="width: 256px; height: 48px;"></canvas>
+<div id="description"></div><div id="console"></div>
+<script>
+"use strict";
+description("Test clear.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [0,0,0,0], "should be 0,0,0,0");
+
+gl.clearColor(1,1,1,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [255,255,255,255], "should be 255,255,255,255");
+
+gl.clearColor(0,0,0,0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [0,0,0,0], "should be 0,0,0,0");
+
+gl.colorMask(false, false, false, true);
+gl.clearColor(1,1,1,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [0,0,0,255], "should be 0,0,0,255");
+
+var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([128, 128, 128, 192]));
+
+gl.disable(gl.DEPTH_TEST);
+gl.disable(gl.BLEND);
+gl.colorMask(true, true, true, true);
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+wtu.checkCanvas(gl, [128,128,128,192], "should be 128,128,128,192");
+
+gl.colorMask(false, false, false, true);
+gl.clearColor(1,1,1,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [128,128,128,255], "should be 128,128,128,255");
+
+// TODO: Test depth and stencil clearing.
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.html
new file mode 100644
index 0000000000..7d06e99897
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.html
@@ -0,0 +1,82 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL drawArrays Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description(document.title);
+
+ function checkDrawArrays(mode, count, expect, msg) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(mode, 0, count);
+ wtu.glErrorShouldBe(gl, expect, msg);
+ }
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ 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.enableVertexAttribArray(0);
+
+ checkDrawArrays(gl.TRIANGLES, 3,
+ gl.INVALID_OPERATION, "gl.DrawArrays with no buffer attached to VAO should return INVALID_OPERATION");
+
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ checkDrawArrays(gl.TRIANGLES, 3,
+ gl.NO_ERROR, "can call gl.DrawArrays with gl.TRIANGLES");
+
+ checkDrawArrays(
+ desktopGL['QUAD_STRIP'], 4,
+ gl.INVALID_ENUM, "gl.DrawArrays with QUAD_STRIP should return INVALID_ENUM");
+ checkDrawArrays(
+ desktopGL['QUADS'], 4,
+ gl.INVALID_ENUM, "gl.DrawArrays with QUADS should return INVALID_ENUM");
+ checkDrawArrays(
+ desktopGL['POLYGON'], 4,
+ gl.INVALID_ENUM, "gl.DrawArrays with POLYGON should return INVALID_ENUM");
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html
new file mode 100644
index 0000000000..347d539dbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL drawElements Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>"use strict";
+description(document.title);
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+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.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 0, 1, 2]), gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)");
+
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2, 0]), gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0)");
+
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(desktopGL.QUAD_STRIP, 4, gl.UNSIGNED_BYTE, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(desktopGL.QUADS, 4, gl.UNSIGNED_BYTE, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(desktopGL.POLYGON, 4, gl.UNSIGNED_BYTE, 0)");
+
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([ 0, 1, 2]), gl.STATIC_DRAW);
+
+wtu.shouldGenerateGLError(gl,
+ wtu.getDefault3DContextVersion() > 1 ? gl.NO_ERROR : gl.INVALID_ENUM,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)");
+
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.FLOAT, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.SHORT, 0)");
+
+// Index validation
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2,2000, 40802, 5887992]), gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 1)");
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.drawElements(gl.TRIANGLES, 2, gl.UNSIGNED_SHORT, 2)");
+var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 2)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 3)");
+wtu.shouldGenerateGLError(gl, indexValidationError,
+ "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 7, gl.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 2)");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html
new file mode 100644
index 0000000000..6e2f2baf30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Scissor Canvas Dimensions Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid #000;
+ width: 64px;
+ height: 64px;
+}
+</style>
+</head>
+<body>
+<canvas id="canvas1" width="16" height="16"> </canvas>
+<canvas id="canvas2" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Check that scissoring is initially disabled and that the scissor rect does not change when canvas size changes.");
+
+var wtu = WebGLTestUtils;
+
+function testInit(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ debug("Testing that scissor test is initially disabled");
+ // Setting the scissor rect should have no effect on drawing.
+ gl.scissor(0, 0, 1, 1);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255], "whole canvas should be green");
+}
+
+function testCanvasSizeChange(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ debug("Testing that scissor rect dimensions do not change if the canvas is resized.");
+ canvas.width = 32;
+ canvas.height = 32;
+ gl.viewport(0, 0, 32, 32);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0, 255, 0, 255], "area inside scissor should be green");
+ wtu.checkCanvasRect(gl, 0, 16, 32, 16, [0, 0, 0, 0], "area outside scissor should be black");
+ wtu.checkCanvasRect(gl, 16, 0, 16, 16, [0, 0, 0, 0], "area outside scissor should be black");
+}
+
+testInit(document.getElementById("canvas1"), {antialias: false});
+debug("");
+testCanvasSizeChange(document.getElementById("canvas2"), {antialias: false});
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html
new file mode 100644
index 0000000000..9b402a8206
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html
@@ -0,0 +1,121 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Scissor FBO Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="16" height="16" style="width: 40px; height: 40px;"> </canvas>
+<canvas id="canvas2" width="16" height="16" style="width: 40px; height: 40px;"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Checks the scissor does not change when switching framebuffers.");
+
+var wtu = WebGLTestUtils;
+var gl;
+
+function makeFramebuffer(width, height) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ return fb;
+}
+
+function checkCanvasRect(x, y, width, height, color, msg) {
+ debug("checking: " + x + ", " + y + ", " + width + ", " + height);
+ wtu.checkCanvasRect(gl, x, y, width, height, color, msg);
+}
+
+function runEntireTest(canvasName, antialias) {
+ debug("");
+ debug("== Running scissor fbo test with antialias:" + antialias + " ==");
+ debug("");
+
+ gl = wtu.create3DContext(canvasName, {antialias: antialias});
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ testPassed("context exists");
+
+ var fb8x8 = makeFramebuffer(8, 8);
+ var fb32x32 = makeFramebuffer(32, 32);
+
+ var testScissor = function(scissorX, scissorY, scissorWidth, scissorHeight, msg) {
+ debug("");
+ debug(msg);
+
+ var test = function(fb, size) {
+ debug("");
+ debug("checking size: " + size);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var scissorRight = Math.min(scissorX + scissorWidth, size);
+ var scissorTop = Math.min(scissorY + scissorHeight, size);
+ var scWidth = scissorRight - scissorX;
+ var scHeight = scissorTop - scissorY;
+ var rightWidth = Math.min(size - scissorRight, 0);
+ var topHeight = Math.max(size - scissorTop, 0);
+ checkCanvasRect(scissorX, scissorY, scWidth, scHeight, [0, 255, 0, 255], "should be green");
+ checkCanvasRect(0, 0, size, scissorY, [255, 0, 0, 255], "should be red");
+ checkCanvasRect(0, scissorTop, size, topHeight, [255, 0, 0, 255], "should be red");
+ checkCanvasRect(0, 0, scissorX, size, [255, 0, 0, 255], "should be red");
+ checkCanvasRect(scissorRight, 0, scissorX, rightWidth, [255, 0, 0, 255], "should be red");
+ };
+
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(1, 0, 0, 1);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb8x8);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb32x32);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb32x32);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(scissorX, scissorY, scissorWidth, scissorHeight);
+ test(null, 16);
+ test(fb8x8, 8);
+ test(fb32x32, 32);
+ test(null, 16);
+ };
+
+ testScissor(2, 4, 12, 10, "test scissor in middle");
+ testScissor(0, 0, 12, 10, "test scissor at 0,0");
+ testScissor(0, 0, 16, 16, "test scissor with size that matches drawingbuffer");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+runEntireTest("canvas", false);
+runEntireTest("canvas2", true);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html
new file mode 100644
index 0000000000..fe78e0452e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html
@@ -0,0 +1,95 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Scissor Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid #000;
+ width: 64px;
+ height: 64px;
+}
+</style>
+</head>
+<body>
+<canvas id="canvas1" width="16" height="16"> </canvas>
+<canvas id="canvas2" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Check if glScissor setting works.");
+
+var wtu = WebGLTestUtils;
+
+function test(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+
+ function test(func) {
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0,0,0,0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.enable(gl.SCISSOR_TEST);
+
+ var size = 16;
+ for (var ii = 0; ii < size; ++ii) {
+ // clear a portion of the WebGL drawing buffer
+ gl.scissor(ii, ii, 1, 1);
+ func();
+ }
+
+ for (var ii = 0; ii < size; ++ii) {
+ wtu.checkCanvasRect(gl, 0, ii, ii, 1, [0, 0, 0, 0], "should be black");
+ wtu.checkCanvasRect(gl, ii, ii, 1, 1, [0, 255, 0, 255], "should be green");
+ wtu.checkCanvasRect(gl, ii + 1, ii, size - ii - 1, 1, [0, 0, 0, 0], "should be black");
+ }
+ }
+
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ debug("");
+ debug("test with clear");
+ test(function() {
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ });
+
+ wtu.setupColorQuad(gl);
+
+ debug("");
+ debug("test with draw");
+ test(function() {
+ wtu.drawFloatColorQuad(gl, [0, 1, 0, 1]);
+ });
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+debug("test antialias: false");
+test(document.getElementById("canvas1"), {antialias: false});
+
+debug("");
+debug("test antialias: true");
+test(document.getElementById("canvas2"), {antialias: true});
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html
new file mode 100644
index 0000000000..d56588098f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html
@@ -0,0 +1,112 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Viewport Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<style>
+canvas {
+ border: 1px solid #000;
+}
+</style>
+</head>
+<body>
+<canvas id="canvas1" width="64" height="128"> </canvas>
+<canvas id="canvas2" width="64" height="128"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+
+function test(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ var blue = [0, 0, 255, 255];
+ var black = [0, 0, 0, 0];
+
+ var draw = function(viewportX, viewportY, viewportWidth, viewportHeight) {
+ gl.viewport(viewportX, viewportY, viewportWidth, viewportHeight);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.drawUByteColorQuad(gl, blue);
+ };
+
+ var drawAndCheck = function(viewportX, viewportY, viewportWidth, viewportHeight) {
+ var clipSpaceToPixelSpace = function(clip, viewportOffset, viewportSize, max) {
+ var pixel = viewportSize / 2 * clip + viewportOffset + viewportSize / 2;
+ return Math.min(max, Math.max(0, pixel));
+ };
+
+ var x1 = clipSpaceToPixelSpace(-0.5, viewportX, viewportWidth, gl.canvas.width);
+ var x2 = clipSpaceToPixelSpace( 0.5, viewportX, viewportWidth, gl.canvas.width);
+ var y1 = clipSpaceToPixelSpace(-0.5, viewportY, viewportHeight, gl.canvas.height);
+ var y2 = clipSpaceToPixelSpace( 0.5, viewportY, viewportHeight, gl.canvas.height);
+ var width = x2 - x1;
+ var height = y2 - y1;
+
+ debug("checking viewport: " + viewportX + ", " + viewportY + ", " + viewportWidth + ", " + viewportHeight);
+ debug("rect: " + x1 + ", " + y1 + ", " + width + ", " + height);
+ draw(viewportX, viewportY, viewportWidth, viewportHeight);
+ wtu.checkAreaInAndOut(gl, x1, y1, width, height, blue, black);
+ };
+
+ var program = wtu.setupSimpleColorProgram(gl);
+ wtu.setupQuad(gl, {scale: 0.5});
+
+ var w = gl.canvas.width;
+ var h = gl.canvas.height;
+
+ drawAndCheck(0, 0, w, h);
+ drawAndCheck(0, 0, w/2, h/4);
+ drawAndCheck(0, 0, w/4, h/2);
+ drawAndCheck(0, 0, w*2, h*2);
+
+ drawAndCheck(-w, 0, w, h);
+ drawAndCheck(0, -h, w, h);
+ drawAndCheck(w, 0, w, h);
+ drawAndCheck(0, h, w, h);
+
+ drawAndCheck(w/4, h/2, w, h);
+ drawAndCheck(w/4, h/2, w/2, h/4);
+ drawAndCheck(w/2, h/4, w/4, h/2);
+ drawAndCheck(w/2, h/4, w, h*2);
+
+ drawAndCheck(-w, 0, w*2, h);
+ drawAndCheck(0, -h/4, w/2, h);
+ drawAndCheck(-w/4, 0, w, h/2);
+ drawAndCheck(0, -h, w*2, h*2);
+
+ debug("");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+debug("test antialias: false");
+test(document.getElementById("canvas1"), {antialias: false});
+
+debug("");
+debug("test antialias: true");
+test(document.getElementById("canvas2"), {antialias: true});
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html
new file mode 100644
index 0000000000..e024157fc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html
@@ -0,0 +1,229 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 0, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ gl_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+// Check a single 32-bit RGBA pixel.
+function checkPixel(buf, index, correct) {
+ for (var i = 0; i < 4; ++i) {
+ if (buf[index + i] != correct[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check the line loop by reading the pixels and making sure just the edge
+// pixels are green and the rest are black.
+function checkLineLoop(gl, w) {
+ var buf = new Uint8Array(w * w * 4);
+ gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var green = [0,255,0,255];
+ var black = [0,0,0,255];
+ var isCorrect = true;
+ for (var j = 0; j < w * w * 4; j += 4) {
+ var correct = black;
+ if (j < w * 4 || j > w * (w - 1) * 4 || j % (w * 4) == 0 || j % (w * 4) == (w - 1) * 4) {
+ correct = green;
+ }
+ // ignore corner pixels
+ if ((j == 0) || (j == 4*(w-1)) || (j == 4*w*(w-1)) || (j== 4*(w*w - 1))) {
+ continue;
+ }
+ if (!checkPixel(buf, j, correct)) {
+ isCorrect = false;
+ break;
+ }
+ }
+ if (isCorrect) {
+ testPassed("Line loop was drawn correctly.");
+ } else {
+ testFailed("Line loop was drawn incorrectly.");
+ }
+}
+
+// Check the tri fan by reading the pixels and making sure they are all green.
+function checkTriFan(gl, w) {
+ var buf = new Uint8Array(w * w * 4);
+ gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var filled = true;
+ for (var j = 0; j < w * w * 4; j += 4) {
+ if (!checkPixel(buf, j, [0,255,0,255])) {
+ filled = false;
+ break;
+ }
+ }
+ if (filled) {
+ testPassed("Triangle fan was drawn correctly.");
+ } else {
+ testFailed("Triangle fan was drawn incorrectly.");
+ }
+}
+
+function runTest() {
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ gl.clearColor(0, 0, 0, 1);
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos'])
+ var w = document.getElementById('testbed').width;
+
+ gl.enableVertexAttribArray(0);
+
+ //---------- LINE_LOOP----------
+ var d = 1/w;
+ var vertices = new Float32Array([-1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
+ var vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ var indBuf = gl.createBuffer();
+ var indices = new Uint16Array([0, 1, 2, 3]);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a square using a line loop and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.LINE_LOOP, 0, vertices.length / 2);
+ checkLineLoop(gl, w);
+
+ debug('Draw a square using an indexed line loop and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
+ checkLineLoop(gl, w);
+
+ vertices = new Float32Array([0, 0, 0, 0, 0, 0, -1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indBuf = gl.createBuffer();
+ indices = new Uint16Array([0, 1, 2, 3, 4, 5, 6]);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a square using a line loop with a vertex buffer offset and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.LINE_LOOP, 3, vertices.length / 2 - 3);
+ checkLineLoop(gl, w);
+
+ debug('Draw a square using an indexed line loop with an index buffer offset and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.LINE_LOOP, indices.length - 3, gl.UNSIGNED_SHORT, 3 * 2);
+ checkLineLoop(gl, w);
+
+ //---------- LINE_LOOP UBYTE ----------
+ var degenVerts = new Array(252 * 2);
+ for (var j = 0; j < 252 * 2; ++j) {
+ degenVerts[j] = -1+d;
+ }
+ degenVerts = degenVerts.concat([-1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
+ vertices = new Float32Array(degenVerts);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indBuf = gl.createBuffer();
+ var degenInd = new Array(252);
+ for (var j = 0; j < 252; ++j) {
+ degenInd[j] = j;
+ }
+ degenInd = degenInd.concat([252, 253, 254, 255]);
+ indices = new Uint16Array(degenInd);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a square using an ubyte indexed line loop with 256 indices and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
+ checkLineLoop(gl, w);
+
+ //---------- TRIANGLE_FAN ----------
+ vertices = new Float32Array([0, 0, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1]);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indices = new Uint16Array([0,1,2,3,4,5]);
+ indBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a filled square using a triangle fan and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length / 2);
+ checkTriFan(gl, w);
+
+ debug('Draw a filled square using an indexed triangle fan and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLE_FAN, indices.length, gl.UNSIGNED_SHORT, 0);
+ checkTriFan(gl, w);
+
+ vertices = new Float32Array([1, 1, 1, 1, 1, 1, 0, 0, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1]);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indices = new Uint16Array([0,1,2,3,4,5,6,7,8]);
+ indBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a filled square using a triangle fan with a vertex buffer offset and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLE_FAN, 3, vertices.length / 2 - 3);
+ checkTriFan(gl, w);
+
+ debug('Draw a filled square using an indexed triangle fan with an index buffer offset and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLE_FAN, indices.length - 3, gl.UNSIGNED_SHORT, 3 * 2);
+ checkTriFan(gl, w);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="10" height="10" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that LINE_LOOP and TRIANGLE_FAN works correctly.');
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html
new file mode 100644
index 0000000000..15faa02c2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Line rendering quality test</title>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="256" height="256"></canvas>
+<canvas id="testbed2" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/line-rendering-quality.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html
new file mode 100644
index 0000000000..2c0a2232ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html
@@ -0,0 +1,138 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<script id="vshader" type="x-shader/x-vertex">
+uniform mat4 transformMatrix;
+uniform vec3 positionOffset;
+attribute vec2 aPosition;
+void main() {
+ gl_Position = transformMatrix * vec4(aPosition, 0.0, 1.0) + vec4(positionOffset, 0.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+void main() {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<div id="description"></div>
+<canvas id="canvas" width="256" height="256"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Test many draw calls and uniform updates per frame");
+
+debug('Regression test for Chromium <a href="http://crbug.com/320724">Issue 320724</a> and <a href="http://crbug.com/322726">Issue 322726</a>');
+debug('');
+
+var contextWasLost = false;
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById('canvas');
+var gl = wtu.create3DContext(canvas);
+canvas.addEventListener('webglcontextlost', function(event) { contextWasLost = true; }, false);
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], [ "aPosition" ]);
+if (!program) {
+ testFailed("failed to create test program");
+}
+
+gl.useProgram(program);
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.enableVertexAttribArray(0);
+
+// Initialize vertices
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1.0, 1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0 ]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+gl.clearColor(0.3, 0.3, 0.3, 1.0);
+
+// Initialize uniforms
+var transformLoc = gl.getUniformLocation(program, 'transformMatrix');
+var offsetLoc = gl.getUniformLocation(program, 'positionOffset');
+
+// This many draw calls appear to be necessary to trigger the original bug reliably.
+var tilesPerSide = 100;
+var numDrawsThisFrame = 0;
+
+var doNextDraw = function() {
+ // Sometimes, the original bug can't be caught cooperatively, and it
+ // causes the entire tab to hang irrevocably.
+ if (contextWasLost) {
+ testFailed("WebGL context was lost while running the test");
+ finishTest();
+ return;
+ }
+
+ var totalDraws = tilesPerSide * tilesPerSide;
+ if (numDrawsThisFrame >= totalDraws) {
+ testPassed("All draw calls completed successfully");
+ finishTest();
+ return;
+ }
+
+ numDrawsThisFrame += tilesPerSide;
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var transformMatrix = new Float32Array(16);
+ transformMatrix[15] = 1.0;
+ var scaleFactor = 1.0 / tilesPerSide;
+ transformMatrix[0] = scaleFactor;
+ transformMatrix[5] = scaleFactor;
+ transformMatrix[10] = scaleFactor;
+
+ var offset = new Float32Array(3);
+
+ var drawsDoneThisFrame = 0;
+ for (var yy = 0; yy < tilesPerSide; ++yy) {
+ for (var xx = 0; xx < tilesPerSide; ++xx) {
+ if (drawsDoneThisFrame >= numDrawsThisFrame)
+ break;
+
+ gl.uniformMatrix4fv(transformLoc, false, transformMatrix);
+
+ offset[0] = 2.0 * ((0.5 + xx) / tilesPerSide) - 1.0;
+ offset[1] = 2.0 * ((0.5 + yy) / tilesPerSide) - 1.0;
+ gl.uniform3f(offsetLoc, offset[0], offset[1], offset[2]);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ ++drawsDoneThisFrame;
+ }
+
+ if (drawsDoneThisFrame >= numDrawsThisFrame)
+ break;
+ }
+
+ var iterations = numDrawsThisFrame / tilesPerSide;
+ if (iterations % 10 === 0) {
+ // Needed to avoid test timeout within the harness on some slower platforms
+ testPassed("Completed " + iterations + " iterations");
+ }
+
+ wtu.requestAnimFrame(doNextDraw);
+}
+
+wtu.requestAnimFrame(doNextDraw);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html
new file mode 100644
index 0000000000..02a0fe594e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html
@@ -0,0 +1,123 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL More than 65536 indices.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vs" type="text/something-not-javascript">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main() {
+ gl_Position = vPosition;
+ gl_PointSize = 1.0;
+ color = vColor;
+}
+</script>
+<script id="fs" type="text/something-not-javascript">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("checks that rendering with more than 65536 indices works.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
+var bufferObjects = wtu.setupUnitQuad(gl, 0, 1);
+
+gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[0]);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, 1,
+ 1, 1,
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, 1,
+ -1, -1,
+ 1, -1]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[1]);
+gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after program setup");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+var numQuads = Math.floor(65536 / 6) + 4;
+var numPoints = numQuads * 6;
+debug("numQuads: " + numQuads);
+debug("numPoints: " + numPoints);
+var indexBuf = new ArrayBuffer(numPoints);
+var indices = new Uint8Array(indexBuf);
+var indexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
+
+var modes = [
+ {mode: 'POINTS', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'LINES', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'LINE_LOOP', offsets: [0, 1, 2, 3, 2, 1], skip: 1},
+ {mode: 'LINE_STRIP', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'TRIANGLES', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'TRIANGLE_STRIP', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'TRIANGLE_FAN', offsets: [0, 1, 3, 2, 2, 1], skip: 1}
+];
+
+for (var mm = 0; mm < modes.length; ++mm) {
+ var modeInfo = modes[mm];
+ var mode = modeInfo.mode;
+ var offsets = modeInfo.offsets;
+ var skip = modeInfo.skip;
+
+ for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ var quad = (ii == 0 || ii == (numQuads - 1)) ? 4 : 0;
+ for (var jj = 0; jj < 6; ++jj) {
+ indices[offset + jj] = quad + offsets[jj];
+ }
+ }
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug("");
+ debug("testing: " + mode);
+ // Draw without last 6 points.
+ gl.drawElements(gl[mode], numPoints - (skip + 1) * 6, gl.UNSIGNED_BYTE, skip * 6);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red.");
+ // Draw with last 6 points.
+ gl.drawElements(gl[mode], numPoints, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green.");
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html
new file mode 100644
index 0000000000..3836949e6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Multisample Renderbuffer Corruption Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/iterable-test.js"> </script>
+</head>
+<body>
+<canvas id="example" width="2048" height="2048" style="width: 128px; height: 128px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+enableJSTestPreVerboseLogging();
+description(document.title);
+debug('Regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=137303">Chromium bug 137303</a>');
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext("example", {antialias: true, preserveDrawingBuffer: true});
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var test = IterableTest.createMultisampleCorruptionTest(gl);
+ var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 25;
+ IterableTest.run(test, iterations);
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html
new file mode 100644
index 0000000000..69a59940a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>-1 Index Rendering Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(0.0,1.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description(document.title);
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var contextVersion = wtu.getDefault3DContextVersion();
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ var vertexData = new Float32Array(65536 * 3);
+ vertexData[0 * 3 + 0] = 0.0;
+ vertexData[0 * 3 + 1] = 0.5;
+ vertexData[0 * 3 + 2] = 0.0;
+ vertexData[1 * 3 + 0] = -0.5;
+ vertexData[1 * 3 + 1] = -0.5;
+ vertexData[1 * 3 + 2] = 0.0;
+ vertexData[65535 * 3 + 0] = 0.5;
+ vertexData[65535 * 3 + 1] = -0.5;
+ vertexData[65535 * 3 + 2] = 0.0;
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indices = new Uint16Array([0, 1, -1]);
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+
+ if (contextVersion <= 1) {
+ // This should render a green triangle in the middle of the canvas.
+ // Some implementations may incorrectly interpret the -1 index as
+ // a primitive restart and not render anything.
+
+ // Test several locations
+ // First line should be all black
+ wtu.checkCanvasRect(gl, 0, 0, 50, 1, [0, 0, 0, 0]);
+
+ // Line 15 should be green for at least 10 pixels starting from row 20
+ wtu.checkCanvasRect(gl, 20, 15, 10, 1, [0, 255, 0, 255]);
+
+ // Last line should be all black
+ wtu.checkCanvasRect(gl, 0, 49, 50, 1, [0, 0, 0, 0]);
+ } else {
+ // For WebGL 2, PRIMITIVE_RESTART_FIXED_INDEX is always enabled.
+ // Nothing should be drawn on the canvas.
+ wtu.checkCanvasRect(gl, 0, 0, 50, 50, [0, 0, 0, 0]);
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html
new file mode 100644
index 0000000000..04d4d55af1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL Out-of-Bounds Array Buffer Conformance Test</title>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
+ precision mediump float;
+ attribute vec2 position;
+ attribute vec4 vecRandom;
+ varying vec4 v_color;
+
+ // Per the spec, each component can either contain existing contents
+ // of the buffer or 0.
+ bool testFloatComponent(float component) {
+ return (component == 0.2 || component == 0.0);
+ }
+ // The last component is additionally allowed to be 1.0.
+ bool testLastFloatComponent(float component) {
+ return testFloatComponent(component) || component == 1.0;
+ }
+
+ void main() {
+ if (testFloatComponent(vecRandom.x) &&
+ testFloatComponent(vecRandom.y) &&
+ testFloatComponent(vecRandom.z) &&
+ testLastFloatComponent(vecRandom.w)) {
+ v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- We're good
+ } else {
+ v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
+ }
+ gl_Position = vec4(position, 0.0, 1.0);
+ }
+</script>
+<script>
+"use strict";
+description("This test verifies that out-of-bounds array buffers behave according to spec.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+var numberOfQuads = 200;
+
+// Draw out-of-bounds beginning with the start offset passed in.
+// Ensure that drawArrays flags either no error or INVALID_OPERATION. In the case of INVALID_OPERATION,
+// no canvas pixels can be touched. In the case of NO_ERROR, all written values must either be the
+// zero vertex or a value in the vertex buffer. See vsCheckOutOfBounds shader.
+function drawAndVerifyOutOfBoundsArrays(gl, first, count) {
+ gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.drawArrays(gl.TRIANGLES, first, count);
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawArrays flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawArrays flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawArrays. Should be INVALID_OPERATION or NO_ERROR");
+ }
+}
+
+// Create a vertex buffer with 200 properly formed triangle quads. These quads will cover the
+// canvas texture such that every single pixel is touched by the fragment shader.
+var glQuadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glQuadBuffer);
+var quadPositions = new Float32Array(numberOfQuads * /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/6);
+for (var i = 0; i < quadPositions.length; i += /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/6) {
+ quadPositions[i+0] = -1.0; // upper left
+ quadPositions[i+1] = 1.0;
+ quadPositions[i+2] = 1.0; // upper right
+ quadPositions[i+3] = 1.0;
+ quadPositions[i+4] = -1.0; // lower left
+ quadPositions[i+5] = -1.0;
+ quadPositions[i+6] = 1.0; // upper right
+ quadPositions[i+7] = 1.0;
+ quadPositions[i+8] = 1.0; // lower right
+ quadPositions[i+9] = -1.0;
+ quadPositions[i+10] = -1.0; // lower left
+ quadPositions[i+11] = -1.0;
+}
+gl.bufferData(gl.ARRAY_BUFFER, quadPositions, gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+
+// Create a small vertex buffer with determined-ahead-of-time "random" values (0.2). This buffer will be
+// the one read past the end.
+var glVertexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glVertexBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.2, 0.2, 0.2, 0.2, 0.2, 0.2]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+
+// Setup the verification program.
+var glProgram = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup should not generate errors");
+
+debug("Test -- Draw off the end of the vertex buffer near the beginning of the out of bounds area.");
+drawAndVerifyOutOfBoundsArrays(gl, /*first*/6, /*count*/6);
+
+debug("");
+
+debug("Test -- Draw off the end of the vertex buffer near the end of the out of bounds area.")
+drawAndVerifyOutOfBoundsArrays(gl, /*first*/(numberOfQuads - 1) * 6, /*count*/6);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html
new file mode 100644
index 0000000000..0eb2bfebfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL Out-of-Bounds Index Buffer Conformance Test</title>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
+ precision mediump float;
+ attribute vec2 position;
+ attribute vec4 vecRandom;
+ varying vec4 v_color;
+
+ // Per the spec, each component can either contain existing contents
+ // of the buffer or 0.
+ bool testFloatComponent(float component) {
+ return (component == 0.2 || component == 0.0);
+ }
+ // The last component is additionally allowed to be 1.0.
+ bool testLastFloatComponent(float component) {
+ return testFloatComponent(component) || component == 1.0;
+ }
+
+ void main() {
+ if (testFloatComponent(vecRandom.x) &&
+ testFloatComponent(vecRandom.y) &&
+ testFloatComponent(vecRandom.z) &&
+ testLastFloatComponent(vecRandom.w)) {
+ v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- We're good
+ } else {
+ v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
+ }
+ gl_Position = vec4(position, 0.0, 1.0);
+ }
+</script>
+<script>
+"use strict";
+description("This test verifies that out-of-bounds index buffers behave according to spec.");
+
+// Prepare an element array buffer that indexes out-of-bounds beginning with the start index passed in.
+// Ensure that drawElements flags either no error or INVALID_OPERATION. In the case of INVALID_OPERATION,
+// no canvas pixels can be touched. In the case of NO_ERROR, all written values must either be the
+// zero vertex or a value in the vertex buffer. See vsCheckOutOfBounds shader.
+function drawAndVerifyOutOfBoundsIndex(gl, startIndex) {
+ gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ prepareElementArrayBuffer(gl, /*StartIndex*/startIndex);
+
+ gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, /*offset*/0);
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
+ }
+}
+
+// Create an element array buffer with a tri-strip that starts at startIndex and make
+// it the active element array buffer.
+function prepareElementArrayBuffer(gl, startIndex) {
+ var glElementArrayBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, glElementArrayBuffer);
+ var quadIndices = new Uint16Array(4);
+ for (var i = 0; i < quadIndices.length; i++) {
+ quadIndices[i] = startIndex + i;
+ }
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, quadIndices, gl.STATIC_DRAW);
+}
+
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+var numberOfQuads = 200;
+
+// Create a vertex buffer with 200 properly formed tri-strip quads. These quads will cover the canvas texture
+// such that every single pixel is touched by the fragment shader.
+var glQuadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glQuadBuffer);
+var quadPositions = new Float32Array(numberOfQuads * /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4);
+for (var i = 0; i < quadPositions.length; i += /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4) {
+ quadPositions[i+0] = -1.0; // upper left
+ quadPositions[i+1] = 1.0;
+ quadPositions[i+2] = 1.0; // upper right
+ quadPositions[i+3] = 1.0;
+ quadPositions[i+4] = -1.0; // lower left
+ quadPositions[i+5] = -1.0;
+ quadPositions[i+6] = 1.0; // lower right
+ quadPositions[i+7] = -1.0;
+}
+gl.bufferData(gl.ARRAY_BUFFER, quadPositions, gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+// Create a small vertex buffer with determined-ahead-of-time "random" values (0.2). This buffer will be
+// the one indexed off the end.
+var glVertexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glVertexBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.2, 0.2, 0.2, 0.2]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+
+// Setup the verification program.
+var glProgram = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup should not generate errors");
+
+debug("Test -- Index off the end of the vertex buffer near the beginning of the out of bounds area.");
+drawAndVerifyOutOfBoundsIndex(gl, /*StartIndex*/4);
+
+debug("");
+
+debug("Test -- Index off the end of the vertex buffer near the end of the out of bounds area.")
+drawAndVerifyOutOfBoundsIndex(gl, /*StartIndex*/numberOfQuads - 4);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html
new file mode 100644
index 0000000000..3b67f34942
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html
@@ -0,0 +1,55 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="1" height="1" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that drawing a point without enabling any attributes succeeds');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('testbed');
+
+var program1 = wtu.setupProgram(gl, ['vshader', 'fshader']);
+
+debug('Draw a point with a shader that takes no attributes and verify it fills the whole canvas.');
+
+gl.drawArrays(gl.POINTS, 0, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+wtu.checkCanvas(gl, [0, 255, 0, 255]);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html
new file mode 100644
index 0000000000..d458428221
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html
@@ -0,0 +1,129 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 pos;
+attribute vec4 colorIn;
+uniform float pointSize;
+varying vec4 color;
+
+void main()
+{
+ gl_PointSize = pointSize;
+ color = colorIn;
+ gl_Position = vec4(pos, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify GL_VERTEX_PROGRAM_POINT_SIZE is enabled in WebGL');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('testbed', { antialias: false });
+shouldBeNonNull("gl");
+
+gl.disable(gl.BLEND);
+
+// The choice of (0.4, 0.4) ensures that the centers of the surrounding
+// pixels are not contained within the point when it is of size 1, but
+// that they definitely are when it is of size 2.
+var vertices = new Float32Array([
+ 0.4, 0.4, 0.0]);
+var colors = new Uint8Array([
+ 255, 0, 0, 255]);
+
+var colorOffset = vertices.byteLength;
+
+var buf = new Uint8Array(2 * 2 * 4);
+var index = 0;
+
+var vbo = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+gl.bufferData(gl.ARRAY_BUFFER, colorOffset + colors.byteLength, gl.STATIC_DRAW);
+gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
+gl.bufferSubData(gl.ARRAY_BUFFER, colorOffset, colors);
+
+function test(program) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, colorOffset);
+ gl.enableVertexAttribArray(1);
+
+ var locPointSize = gl.getUniformLocation(program, 'pointSize');
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ debug('Draw a point of size 1 and verify it does not touch any other pixels.');
+
+ gl.uniform1f(locPointSize, 1.0);
+ gl.drawArrays(gl.POINTS, 0, vertices.length / 3);
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ for (var y = 0; y < 2; ++y) {
+ for (var x = 0; x < 2; ++x) {
+ var correctColor = (x == 1 && y == 1) ? [255, 0, 0] : [0, 0, 0];
+ wtu.checkCanvasRect(gl, x, y, 1, 1, correctColor);
+ }
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ debug('Draw a point of size 2 and verify it fills the appropriate region.');
+
+ var pointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
+ if (pointSizeRange[1] >= 2.0) {
+ gl.uniform1f(locPointSize, 2.0);
+ gl.drawArrays(gl.POINTS, 0, vertices.length / 3);
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ wtu.checkCanvasRect(gl, 0, 0, 2, 2, [255, 0, 0]);
+ }
+}
+
+debug('');
+debug('Pass 1');
+var program1 = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn']);
+shouldBe('gl.getError()', 'gl.NO_ERROR');
+test(program1);
+
+// Under some versions of ANGLE point sprite shader programs were
+// incorrectly reloaded from cache. Rebuilding the shader program and
+// repeating the test simulates the conditions that caused it to fail
+debug('');
+debug('Pass 2');
+var program2 = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn']);
+shouldBe('gl.getError()', 'gl.NO_ERROR');
+test(program2);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html
new file mode 100644
index 0000000000..71f0bcad50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html
@@ -0,0 +1,166 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Point-specific shader variables test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="c" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vs-assign" type="x-shader/x-vertex">
+attribute vec2 aPosition;
+
+varying vec2 vPos;
+
+void main()
+{
+ gl_Position = vec4(aPosition, 0, 1);
+ vPos = aPosition;
+
+ gl_PointSize = 1.0;
+}
+</script>
+
+<script id="vs-conditional" type="x-shader/x-vertex">
+uniform float renderingPoints; // not assigned, equal to 0.0
+attribute vec2 aPosition;
+
+varying vec2 vPos;
+
+void main()
+{
+ gl_Position = vec4(aPosition, 0, 1);
+ vPos = aPosition;
+
+ if (renderingPoints > 0.0) {
+ gl_PointSize = 1.0;
+ }
+}
+</script>
+
+<script id="fs-overwrite" type="x-shader/x-fragment">
+varying mediump vec2 vPos;
+
+void main()
+{
+ gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
+ gl_FragColor = vec4(vPos * -2.0, 0, 1);
+}
+</script>
+
+<script id="fs-unused-branch" type="x-shader/x-fragment">
+varying mediump vec2 vPos;
+uniform mediump float uDefaultsToZero;
+
+void main()
+{
+ gl_FragColor = vec4(vPos * -2.0, 0, 1);
+ if (uDefaultsToZero == 1.0) {
+ gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
+ }
+}
+</script>
+
+<script>
+"use strict";
+description(document.title);
+
+debug('This test verifies rendering with programs referencing shader variables specific to rendering of POINTS primitives.');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", {depth: false});
+
+var prog_overwrite = wtu.setupProgram(gl, ["vs-assign", "fs-overwrite"], ["aPosition"]);
+var prog_branch = wtu.setupProgram(gl, ["vs-assign", "fs-unused-branch"], ["aPosition"]);
+var prog_cond_overwrite = wtu.setupProgram(gl, ["vs-conditional", "fs-overwrite"], ["aPosition"]);
+var prog_cond_branch = wtu.setupProgram(gl, ["vs-conditional", "fs-unused-branch"], ["aPosition"]);
+
+var vertData = new Float32Array([
+ -1, -1,
+ +1, -1,
+ -1, +1,
+]);
+
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(gl.ARRAY_BUFFER, vertData, gl.STATIC_DRAW);
+
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+//////////
+
+debug("");
+debug("prog-overwrite");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_overwrite);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+
+//////////
+
+debug("");
+debug("prog-branch");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_branch);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+//////////
+
+debug("");
+debug("prog-cond-overwrite");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_cond_overwrite);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+
+//////////
+
+debug("");
+debug("prog-cond-branch");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_cond_branch);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html
new file mode 100644
index 0000000000..802d5f1172
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html
@@ -0,0 +1,119 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Point with gl_PointCoord in Fragment Shader Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">
+varying vec4 v_color;
+
+// The X and Y coordinates of the center of the point.
+attribute vec2 a_vertex;
+
+uniform float u_pointSize;
+
+void main(void) {
+ gl_PointSize = u_pointSize;
+ gl_Position = vec4(a_vertex, 0.0, 1.0);
+
+ // The color of the point.
+ v_color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 v_color;
+
+void main(void) {
+ // It seems as long as this mathematical expression references
+ // gl_PointCoord, the fragment's color is incorrect.
+ vec2 diff = gl_PointCoord - vec2(.5, .5);
+ if (length(diff) > 0.5)
+ discard;
+
+ // The point should be a solid color.
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+// Radar 13239314
+description("This is a regression test for a graphics driver bug affecting end caps on roads in MapsGL.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var canvasWidth = canvas.width;
+var canvasHeight = canvas.height;
+var output = document.getElementById("console");
+var gl = wtu.create3DContext(canvas);
+
+function runTest() {
+ var pointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
+ // This test can't really run without a maximum point size of at least 2
+ if (pointSizeRange[1] < 2.0) {
+ debug("This test needs a maximum ALIASED_POINT_SIZE_RANGE of at least 2");
+ return;
+ }
+
+ var vs = wtu.loadShaderFromScript(gl, "vs", gl.VERTEX_SHADER);
+ var fs = wtu.loadShaderFromScript(gl, "fs", gl.FRAGMENT_SHADER);
+ if (!vs || !fs) {
+ testFailed("Loading shaders failed");
+ return;
+ }
+
+ var program = wtu.setupProgram(gl, [vs, fs], ['a_vertex']);
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+
+ gl.useProgram(program);
+ gl.clearColor(0, 0, 0, 1.0);
+ gl.disable(gl.DEPTH_TEST);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // uniform float u_pointSize;
+ var uni = gl.getUniformLocation(program, 'u_pointSize');
+ gl.uniform1f(uni, Math.min(20.0, pointSizeRange[1]));
+
+ // vertex
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ var vertexData = new Float32Array([
+ 0, 0,
+ ]);
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.checkCanvasRect(gl, canvasWidth / 2, canvasHeight / 2, 1, 1,
+ [0, 255, 0, 255], "Center pixel should be green", 2);
+}
+
+runTest();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html
new file mode 100644
index 0000000000..dfc0a0cca9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html
@@ -0,0 +1,173 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 col;
+
+void main()
+{
+ gl_FragColor = col;
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+function draw(gl, arr, colLoc, col)
+{
+ var vertices = new Float32Array(arr);
+ var vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.uniform4fv(colLoc, col);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 3);
+}
+
+function clear(gl, col, z)
+{
+ gl.clearColor(col[0], col[1], col[2], col[3]);
+ gl.clearDepth(z);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+}
+
+function check(gl)
+{
+ wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0, 255, 0, 255], 'result should be green');
+}
+
+function runTest()
+{
+ var flatSquare = [-1, -1, 0,
+ -1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0];
+ var slantedSquare = [-1, -1, -0.5,
+ -1, 1, -0.5,
+ 1, -1, 0.5,
+ 1, 1, 0.5];
+ var red = [1, 0, 0, 1];
+ var green = [0, 1, 0, 1];
+ var blue = [0, 0, 1, 1];
+
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl)
+ {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos']);
+ var colLoc = gl.getUniformLocation(program, 'col');
+
+ gl.enableVertexAttribArray(0);
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LEQUAL);
+
+ debug('Polygon offset fill should be off by default');
+ clear(gl, red, 1.0);
+ draw(gl, slantedSquare, colLoc, blue);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Polygon offset units should have no effect when fill is off');
+ clear(gl, red, 1.0);
+ draw(gl, slantedSquare, colLoc, blue);
+ gl.polygonOffset(0, 10);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Polygon offset factor should have no effect when fill is off');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0, 0);
+ draw(gl, slantedSquare, colLoc, blue);
+ gl.polygonOffset(1.0, 0);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Zero polygon offset units and factor should have no effect');
+ clear(gl, red, 1.0);
+ gl.enable(gl.POLYGON_OFFSET_FILL);
+ gl.polygonOffset(0, 0);
+ draw(gl, slantedSquare, colLoc, blue);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ // It appears to be VERY common for drivers to implement the units offset in
+ // floating-point arithmetic, which results in rount-to-nearest-even to cause
+ // an offset of 1 to sometimes not alter the order between these polygons.
+ debug('Polygon offset units of 2 should alter order of flat polygons');
+ clear(gl, red, 1.0);
+ draw(gl, flatSquare, colLoc, green);
+ gl.polygonOffset(0, 2);
+ draw(gl, flatSquare, colLoc, blue);
+ check(gl);
+
+ debug('Polygon offset factor of 0.1 should alter order of slanted polygons');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0, 0);
+ draw(gl, slantedSquare, colLoc, green);
+ gl.polygonOffset(0.1, 0);
+ draw(gl, slantedSquare, colLoc, blue);
+ check(gl);
+
+ debug('Polygon offset factor of 0.1 should not alter order of flat polygons');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0, 0);
+ draw(gl, flatSquare, colLoc, blue);
+ gl.polygonOffset(0.1, 0);
+ draw(gl, flatSquare, colLoc, green);
+ check(gl);
+
+ debug('Disabling polygon offset fill should leave order unaffected');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0.1, 1);
+ gl.disable(gl.POLYGON_OFFSET_FILL);
+ draw(gl, slantedSquare, colLoc, blue);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Enabling polygon offset fill should affect order again');
+ clear(gl, red, 1.0);
+ draw(gl, slantedSquare, colLoc, green);
+ gl.enable(gl.POLYGON_OFFSET_FILL);
+ draw(gl, slantedSquare, colLoc, blue);
+ check(gl);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="16" height="16" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that polygon offset works');
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html
new file mode 100644
index 0000000000..2002db1836
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL PreserveDrawingBuffer Leak Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/iterable-test.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4096" height="4096" style="width: 128px; height: 128px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+enableJSTestPreVerboseLogging();
+description(document.title);
+debug('Regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=682482">Chromium bug 682482</a>');
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext("example", {preserveDrawingBuffer: true});
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var test = IterableTest.createPreserveDrawingBufferLeakTest(gl);
+ var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 50;
+ IterableTest.run(test, iterations);
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html
new file mode 100644
index 0000000000..888ee99aec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html
@@ -0,0 +1,183 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Rendering and Sampling Feedback Loop Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vs100" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+attribute vec2 aTexCoord;
+varying vec2 texCoord;
+void main() {
+ gl_Position = aPosition;
+ texCoord = aTexCoord;
+}
+</script>
+
+<script id="fs100" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2D(tex, texCoord);
+ gl_FragData[1] = texture2D(tex, texCoord);
+}
+</script>
+
+<script id="fs100-no-ext-draw-buffers" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2D(tex, texCoord);
+}
+</script>
+
+<script id="vs300" type="x-shader/x-vertex">#version 300 es
+in highp vec4 aPosition;
+in vec2 aTexCoord;
+out vec2 texCoord;
+void main() {
+ gl_Position = aPosition;
+ texCoord = aTexCoord;
+}
+</script>
+
+<script id="fs300" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform sampler2D tex;
+in vec2 texCoord;
+out vec4 oColor;
+void main() {
+ oColor = texture(tex, texCoord);
+}
+</script>
+
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description("This test verifies the functionality of rendering to the same texture where it samples from.");
+
+const gl = wtu.create3DContext("example");
+
+const width = 8;
+const height = 8;
+let tex;
+let fbo;
+let drawBuffers = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (gl.drawBuffers) {
+ debug("Using webgl2.drawBuffers.");
+ drawBuffers = (x) => gl.drawBuffers(x);
+ } else {
+ const ext = gl.getExtension("WEBGL_draw_buffers");
+ if (ext) {
+ debug("Using WEBGL_draw_buffers.drawBuffersWEBGL.");
+ drawBuffers = (x) => ext.drawBuffersWEBGL(x);
+ }
+ }
+
+ init();
+
+ // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
+ allocate_resource();
+
+ rendering_sampling_feedback_loop(null);
+ if (drawBuffers) {
+ rendering_sampling_feedback_loop([gl.NONE]);
+ rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0,
+ gl.COLOR_ATTACHMENT0+1]);
+ rendering_sampling_feedback_loop([gl.NONE,
+ gl.COLOR_ATTACHMENT0+1]);
+ }
+}
+
+function init() {
+ let shaders = ["vs100", "fs100"];
+ if (gl.texStorage2D) {
+ shaders = ["vs300", "fs300"];
+ } else if (!drawBuffers) {
+ shaders = ["vs100", "fs100-no-ext-draw-buffers"];
+ }
+ const program = wtu.setupProgram(gl, shaders, ["aPosition", "aTexCoord"], [0, 1]);
+ const positionLoc = gl.getAttribLocation(program, "aPosition");
+ const texCoordLoc = gl.getAttribLocation(program, "aTexCoord");
+ if (!program || positionLoc < 0 || texCoordLoc < 0) {
+ testFailed("Set up program failed");
+ return;
+ }
+ const texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+ testPassed("Set up program succeeded");
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ gl.viewport(0, 0, width, height);
+}
+
+function allocate_resource() {
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+}
+
+function rendering_sampling_feedback_loop(draw_buffers) {
+ debug("draw_buffers: " + JSON.stringify(draw_buffers));
+
+ if (draw_buffers) {
+ drawBuffers(draw_buffers);
+ }
+
+ // Make sure framebuffer is complete before feedback loop detection
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Feedback loop detection should ignore drawBuffers settings.");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+ // The texture will be mipmap incomplete, so feedback cannot occur nor be consistently evaluated.
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Feedback loop detection should ignore sampled incomplete textures.");
+
+ if (draw_buffers) {
+ drawBuffers([gl.COLOR_ATTACHMENT0]);
+ }
+}
+
+gl.deleteTexture(tex);
+gl.deleteFramebuffer(fbo);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html
new file mode 100644
index 0000000000..1202106c13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html
@@ -0,0 +1,92 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Rendering Stencil large viewport Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="vs" type="x-shader/x-vertex">
+attribute vec4 a_Position;
+void main()
+{
+ gl_Position = a_Position;
+}
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_draw_color;
+void main()
+{
+ gl_FragColor = u_draw_color;
+}
+</script>
+
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test reproduces a driver bug on Intel windows platforms http://crbug.com/782317.");
+
+var gl = wtu.create3DContext("example", {stencil: true});
+
+var program, colorLoc;
+
+// Rendering with large viewport and stencil buffer enabled will lead to
+// memory leak and driver crash on d3d11 driver on Intel platforms.
+function render_stencil() {
+ var canvas = document.getElementById("example");
+ gl.uniform4f(colorLoc, 1.0, 0.0, 0.0, 1.0);
+
+ canvas.width = 32767;
+ canvas.height = 32767;
+ gl.viewport(0, 0, 32767, 32767);
+
+ gl.enable(gl.STENCIL_TEST);
+
+ var kStencilRef = 4;
+ gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
+ gl.stencilFunc(gl.ALWAYS, kStencilRef, 0xFF);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 0, 255],
+ "stencil test should be red");
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ program = wtu.setupProgram(gl, ["vs", "fs"], ["a_Position"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after program initialization");
+ shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+
+ colorLoc = gl.getUniformLocation(program, "u_draw_color")
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "query uniform location");
+ shouldBeNonNull('colorLoc');
+ wtu.setupUnitQuad(gl, 0);
+
+ render_stencil();
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html
new file mode 100644
index 0000000000..f76da1614a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html
@@ -0,0 +1,63 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Scissor Rectangle Repeated Rendering Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="128" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description();
+debug('Regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=778770">Chromium bug 778770</a>');
+
+var wtu = WebGLTestUtils;
+
+// These context creation attributes are significant to reproduce the bug.
+var gl = wtu.create3DContext("example", {alpha: false, antialias: false});
+
+// Draw into the upper right quadrant.
+var x = 64;
+var y = 64;
+var width = 64;
+var height = 64;
+
+var numRenders = 10;
+
+function render() {
+ gl.viewport(x, y, width, height);
+ gl.scissor(x, y, width, height);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // If anything but black is ever seen in the un-drawn region of
+ // the canvas, the test fails.
+ var black = [0, 0, 0, 255];
+ wtu.checkCanvasRect(gl, 10, 10, 10, 10, black, "should be black", 1);
+
+ if (--numRenders > 0) {
+ window.requestAnimationFrame(render);
+ } else {
+ finishTest();
+ }
+}
+
+window.requestAnimationFrame(render);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html
new file mode 100644
index 0000000000..c01d213577
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html
@@ -0,0 +1,77 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Simple Rendering Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+There is supposed to be an example drawing here, but it's not important.
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_Position;
+void main()
+{
+ gl_Position = a_Position;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(0,1,0,1);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+function init()
+{
+ description();
+
+ var gl = wtu.create3DContext("example");
+ var program = wtu.loadProgramFromScript(gl, "vshader", "fshader");
+ gl.useProgram(program);
+ var loc = gl.getAttribLocation(program, "a_Position");
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [ 1, 1,
+ -1, 1,
+ -1, -1,
+ 1, 1,
+ -1, -1,
+ 1, -1]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.checkCanvas(gl, [0,0,0,0], "should be black", 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0,255,0,255], "should be green", 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html
new file mode 100644
index 0000000000..bdc9099a6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html
@@ -0,0 +1,101 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Texture Switch Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Ensures that switching the texture referenced by a sampler uniform performs reasonably well.");
+var wtu = WebGLTestUtils;
+var canvas = document.createElement('canvas');
+canvas.width = 32;
+canvas.height = 32;
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var program = wtu.setupTexturedQuad(gl);
+ var tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var tex2 = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var loc = gl.getUniformLocation(program, "tex");
+
+ var RUNTIME = 2000;
+ var THRESHOLD = 0.8;
+ var baseStartTime = 0;
+ var baseFrameCount = 0;
+ var testStartTime = 0;
+ var testFrameCount = 0;
+
+ baseStartTime = Date.now();
+ function drawBaseline() {
+ for (var i = 0; i < 400; ++i) {
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ ++baseFrameCount;
+
+ if (Date.now() - baseStartTime > RUNTIME) {
+ testStartTime = Date.now();
+ requestAnimationFrame(drawTest);
+ } else {
+ requestAnimationFrame(drawBaseline);
+ }
+ }
+
+ function drawTest() {
+ for (var i = 0; i < 400; ++i) {
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.uniform1i(loc, 1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ ++testFrameCount;
+
+ if (Date.now() - testStartTime > RUNTIME) {
+ var perfString = " - achieved " + testFrameCount + " frames in " + ((Date.now() - testStartTime) / 1000.0) +
+ " seconds (" + (testFrameCount / baseFrameCount).toFixed(2) + " times baseline performance)";
+ if (testFrameCount > baseFrameCount * THRESHOLD) {
+ testPassed("Texture switching did not significantly hurt performance" + perfString);
+ } else {
+ testFailed("Texture switching significantly hurt performance" + perfString);
+ }
+ console.log(testFrameCount);
+ finishTest();
+ } else {
+ requestAnimationFrame(drawTest);
+ }
+ }
+
+ requestAnimationFrame(drawBaseline);
+}
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html
new file mode 100644
index 0000000000..98a04c9050
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html
@@ -0,0 +1,73 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Rendering Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+There is supposed to be an example drawing here, but it's not important.
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description(document.title);
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ 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.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ // Test several locations
+ // First line should be all black
+ wtu.checkCanvasRect(gl, 0, 0, 50, 1, [0, 0, 0, 0]);
+
+ // Line 15 should be red for at least 10 red pixels starting 20 pixels in
+ wtu.checkCanvasRect(gl, 20, 15, 10, 1, [255, 0, 0, 255]);
+
+ // Last line should be all black
+ wtu.checkCanvasRect(gl, 0, 49, 50, 1, [0, 0, 0, 0]);
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html
new file mode 100644
index 0000000000..7b014e1d66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Vertex Texture Fetch.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vs" type="text/something-not-javascript">
+attribute vec4 a_position;
+attribute vec2 a_texCoord;
+uniform sampler2D u_texture;
+varying vec4 color;
+void main() {
+ gl_Position = a_position;
+ color = texture2D(u_texture, a_texCoord);
+}
+</script>
+<script id="fs" type="text/something-not-javascript">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("checks that vertex texture fetch, if supported, operates correctly.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+if (!gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS)) {
+ testPassed("No vertex texture image units (vertex texture fetch not supported) -- this is legal");
+} else {
+ var texture = 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([
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 0, 255, 255,
+ 255, 255, 0, 255]));
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+
+ var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vTexCoord"]);
+ gl.uniform1i(gl.getUniformLocation(program, "u_texture"), 0);
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initWebGL");
+ var bufferObjects = wtu.setupUnitQuad(gl, 0);
+ gl.disableVertexAttribArray(1);
+
+ gl.vertexAttrib2f(1, 0, 0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red.");
+
+ gl.vertexAttrib2f(1, 1, 0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green.");
+
+ gl.vertexAttrib2f(1, 0, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "Should be blue.");
+
+ gl.vertexAttrib2f(1, 1, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 255, 0, 255], "Should be yellow.");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/state/00_test_list.txt
new file mode 100644
index 0000000000..8af8f296a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/00_test_list.txt
@@ -0,0 +1,9 @@
+--min-version 1.0.4 fb-attach-implicit-target-assignment.html
+gl-enable-enum-test.html
+--max-version 1.9.9 gl-enum-tests.html
+gl-get-calls.html
+gl-geterror.html
+--max-version 1.9.9 gl-getstring.html
+--min-version 1.0.4 gl-initial-state.html
+--max-version 1.9.9 gl-object-get-calls.html
+--min-version 1.0.3 state-uneffected-after-compositing.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/fb-attach-implicit-target-assignment.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/fb-attach-implicit-target-assignment.html
new file mode 100644
index 0000000000..1247c1f856
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/fb-attach-implicit-target-assignment.html
@@ -0,0 +1,94 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset='utf-8'>
+<title>WebGL gl calls Conformance Tests</title>
+<link rel='stylesheet' href='../../resources/js-test-style.css'/>
+<script src='../../js/js-test-pre.js'></script>
+<script src='../../js/webgl-test-utils.js'></script>
+</head>
+<body>
+<div id='description'></div>
+<div id='console'></div>
+<canvas id='canvas' width='2' height='2'> </canvas>
+<script>
+'use strict';
+description('Test implicit target assignment during FB attachment');
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext('canvas');
+let fb, rb, tex;
+
+(() => {
+ if (!gl) {
+ testFailed('context does not exist');
+ return;
+ }
+
+ fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ wtu.glErrorShouldBe(gl, 0, 'No errors');
+
+ // -
+
+ debug('');
+ debug('framebufferRenderbuffer');
+
+ rb = gl.createRenderbuffer();
+ shouldBe('gl.isRenderbuffer(rb)', 'false');
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ shouldBe('gl.isRenderbuffer(rb)', 'true');
+
+ rb = gl.createRenderbuffer();
+ shouldBe('gl.isRenderbuffer(rb)', 'false');
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'framebufferRenderbuffer must be preceeded by some bindRenderbuffer');
+ shouldBe('gl.isRenderbuffer(rb)', 'false');
+
+ wtu.glErrorShouldBe(gl, 0, 'No errors');
+
+ // -
+
+ debug('');
+ debug('framebufferTexture2D');
+
+ tex = gl.createTexture();
+ shouldBe('gl.isTexture(tex)', 'false');
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ shouldBe('gl.isTexture(tex)', 'true');
+
+ tex = gl.createTexture();
+ shouldBe('gl.isTexture(tex)', 'false');
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1636524 :
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'framebufferTexture2D must be preceeded by some bindTexture');
+ shouldBe('gl.isTexture(tex)', 'false');
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ wtu.glErrorShouldBe(gl, 0, 'No errors after bindTexture');
+
+ tex = gl.createTexture();
+ shouldBe('gl.isTexture(tex)', 'false');
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'framebufferTexture2D must be preceeded by some bindTexture');
+ shouldBe('gl.isTexture(tex)', 'false');
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.glErrorShouldBe(gl, 0, 'No errors after bindTexture');
+})();
+
+debug('');
+var successfullyParsed = true;
+
+</script>
+<script src='../../js/js-test-post.js'></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enable-enum-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enable-enum-test.html
new file mode 100644
index 0000000000..89efc94209
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enable-enum-test.html
@@ -0,0 +1,171 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl.ENABLE enums Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test ensures WebGL implementations allow OpenGL ES 2.0 features to be turned on but not non OpenGL ES 2.0 features.");
+
+var wtu = WebGLTestUtils;
+
+var invalidEnums = [
+ 'ALPHA_TEST',
+ 'AUTO_NORMAL',
+ 'CLIP_PLANE0',
+ 'CLIP_PLANE1',
+ 'COLOR_LOGIC_OP',
+ 'COLOR_MATERIAL',
+ 'COLOR_SUM',
+ 'COLOR_TABLE',
+ //'CONVOLUTION_1D',
+ //'CONVOLUTION_2D',
+ 'FOG',
+ 'HISTOGRAM',
+ 'INDEX_LOGIC_OP',
+ 'LIGHT0',
+ 'LIGHT1',
+ 'LIGHTING',
+ 'LINE_SMOOTH',
+ 'LINE_STIPPLE',
+ 'MAP1_COLOR_4',
+ 'MAP1_INDEX',
+ 'MAP1_NORMAL',
+ 'MAP1_TEXTURE_COORD_1',
+ 'MAP1_TEXTURE_COORD_2',
+ 'MAP1_TEXTURE_COORD_3',
+ 'MAP1_TEXTURE_COORD_4',
+ 'MAP1_VERTEX_3',
+ 'MAP1_VERTEX_4',
+ 'MAP2_COLOR_4',
+ 'MAP2_INDEX',
+ 'MAP2_NORMAL',
+ 'MAP2_TEXTURE_COORD_1',
+ 'MAP2_TEXTURE_COORD_2',
+ 'MAP2_TEXTURE_COORD_3',
+ 'MAP2_TEXTURE_COORD_4',
+ 'MAP2_VERTEX_3',
+ 'MAP2_VERTEX_4',
+ 'MINMAX',
+ 'MULTISAMPLE',
+ 'NORMALIZE',
+ 'POINT_SMOOTH',
+ 'POINT_SPRITE',
+ 'POLYGON_OFFSET_LINE',
+ 'POLYGON_OFFSET_POINT',
+ 'POLYGON_SMOOTH',
+ 'POLYGON_STIPPLE',
+ 'POST_COLOR_MATRIX_COLOR_TABLE',
+ 'POST_CONVOLUTION_COLOR_TABLE',
+ 'RESCALE_NORMAL',
+ 'SAMPLE_ALPHA_TO_ONE',
+ //'SEPARABLE_2D',
+ 'TEXTURE_1D',
+ 'TEXTURE_2D',
+ 'TEXTURE_3D',
+ 'TEXTURE_CUBE_MAP',
+ 'TEXTURE_GEN_Q',
+ 'TEXTURE_GEN_R',
+ 'TEXTURE_GEN_S',
+ 'TEXTURE_GEN_T',
+ 'VERTEX_PROGRAM_POINT_SIZE',
+ 'VERTEX_PROGRAM_TWO_SIDE'
+];
+var validEnums = [
+ 'BLEND',
+ 'CULL_FACE',
+ 'DEPTH_TEST',
+ 'DITHER',
+ 'POLYGON_OFFSET_FILL',
+ 'SAMPLE_ALPHA_TO_COVERAGE',
+ 'SAMPLE_COVERAGE',
+ 'SCISSOR_TEST',
+ 'STENCIL_TEST'
+];
+
+var gl;
+
+function runNegativeTests() {
+ debug("");
+ debug("Running negative tests");
+
+ gl = wtu.create3DContext();
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ testPassed("context exists");
+
+ for (var ii = 0; ii < invalidEnums.length; ++ii) {
+ var name = invalidEnums[ii];
+ gl.enable(desktopGL[name]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "gl.enable must set INVALID_ENUM when passed GL_" + name );
+ }
+}
+
+function runPositiveTestsWithParameters(params) {
+ debug("");
+ debug("Running positive tests with parameters: " + JSON.stringify(params));
+
+ // Pass null for the canvas, to make sure we create a new context each time.
+ var newgl = wtu.create3DContext(null, params);
+ if (gl == newgl) {
+ testFailed("got an old context");
+ return;
+ }
+ gl = newgl;
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ testPassed("context exists");
+
+ debug("Checking gl.ENABLE enums.");
+
+ for (var ii = 0; ii < validEnums.length; ++ii) {
+ var name = validEnums[ii];
+ gl.enable(gl[name]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.enable must succeed when passed gl." + name );
+ shouldBe('gl.isEnabled(gl.' + name + ')', 'true');
+ shouldBe('gl.getParameter(gl.' + name + ')', 'true');
+ gl.disable(gl[name]);
+ shouldBe('gl.isEnabled(gl.' + name + ')', 'false');
+ shouldBe('gl.getParameter(gl.' + name + ')', 'false');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.isEnabled and gl.GetParameter must not set errors when passed GL_" + name );
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+runNegativeTests();
+runPositiveTestsWithParameters({alpha: true, antialias: true, stencil: true, depth: true});
+runPositiveTestsWithParameters({alpha: false, antialias: true, stencil: true, depth: true});
+runPositiveTestsWithParameters({alpha: true, antialias: false, stencil: true, depth: true});
+runPositiveTestsWithParameters({alpha: true, antialias: true, stencil: false, depth: true});
+runPositiveTestsWithParameters({alpha: true, antialias: true, stencil: true, depth: false});
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enum-tests.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enum-tests.html
new file mode 100644
index 0000000000..9c3d244d79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-enum-tests.html
@@ -0,0 +1,29 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl enums Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/test-eval.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/gl-enum-tests.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-get-calls.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-get-calls.html
new file mode 100644
index 0000000000..a1a27d8e6c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-get-calls.html
@@ -0,0 +1,198 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl calls Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test ensures basic functionality of the underlying graphics library");
+
+debug("");
+debug("Canvas.getContext");
+
+var minimumRequiredStencilMask = 0;
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext("canvas");
+if (!context)
+ testFailed("context does not exist");
+else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Context contains getError");
+ if ("getError" in context)
+ testPassed("context contains getError");
+ else
+ testFailed("context does not contains getError");
+
+ debug("");
+ debug("Check default values");
+ shouldBe('context.getParameter(context.ACTIVE_TEXTURE)', 'context.TEXTURE0');
+ shouldBe('(context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[0] <= 1) && (context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[0] > 0) && (context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[1] >= 1)', 'true');
+ shouldBe('(context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[0] <= 1) && (context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[0] > 0) && (context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[1] >= 1)', 'true');
+ shouldBeType('context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)', 'Float32Array');
+ shouldBeType('context.getParameter(context.ALIASED_POINT_SIZE_RANGE)', 'Float32Array');
+ shouldBe('context.getParameter(context.ARRAY_BUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.BLEND)', 'false');
+ shouldBe('context.getParameter(context.BLEND_COLOR)', '[0, 0, 0, 0]');
+ shouldBeType('context.getParameter(context.BLEND_COLOR)', 'Float32Array');
+ shouldBe('context.getParameter(context.BLEND_DST_ALPHA)', '0');
+ shouldBe('context.getParameter(context.BLEND_DST_RGB)', '0');
+ shouldBe('context.getParameter(context.BLEND_EQUATION_ALPHA)', 'context.FUNC_ADD');
+ shouldBe('context.getParameter(context.BLEND_EQUATION_RGB)', 'context.FUNC_ADD');
+ shouldBe('context.getParameter(context.BLEND_SRC_ALPHA)', '1');
+ shouldBe('context.getParameter(context.BLEND_SRC_RGB)', '1');
+ shouldBe('context.getParameter(context.COLOR_CLEAR_VALUE)', '[0, 0, 0, 0]');
+ shouldBeType('context.getParameter(context.COLOR_CLEAR_VALUE)', 'Float32Array');
+ shouldBe('context.getParameter(context.COLOR_WRITEMASK)', '[true, true, true, true]');
+ shouldBeType('context.getParameter(context.COMPRESSED_TEXTURE_FORMATS)', 'Uint32Array');
+ shouldBe('context.getParameter(context.CULL_FACE)', 'false');
+ shouldBe('context.getParameter(context.CULL_FACE_MODE)', 'context.BACK');
+ shouldBe('context.getParameter(context.CURRENT_PROGRAM)', 'null');
+ shouldBe('context.getParameter(context.DEPTH_CLEAR_VALUE)', '1');
+ shouldBe('context.getParameter(context.DEPTH_FUNC)', 'context.LESS');
+ shouldBe('context.getParameter(context.DEPTH_RANGE)', '[0, 1]');
+ shouldBeType('context.getParameter(context.DEPTH_RANGE)', 'Float32Array');
+ shouldBe('context.getParameter(context.DEPTH_TEST)', 'false');
+ shouldBe('context.getParameter(context.DEPTH_WRITEMASK)', 'true');
+ shouldBe('context.getParameter(context.DITHER)', 'true');
+ shouldBe('context.getParameter(context.ELEMENT_ARRAY_BUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.FRONT_FACE)', 'context.CCW');
+ shouldBe('context.getParameter(context.GENERATE_MIPMAP_HINT)', 'context.DONT_CARE');
+ shouldBe('context.getParameter(context.LINE_WIDTH)', '1');
+ shouldBe('context.getParameter(context.PACK_ALIGNMENT)', '4');
+ shouldBe('context.getParameter(context.POLYGON_OFFSET_FACTOR)', '0');
+ shouldBe('context.getParameter(context.POLYGON_OFFSET_FILL)', 'false');
+ shouldBe('context.getParameter(context.POLYGON_OFFSET_UNITS)', '0');
+ shouldBe('context.getParameter(context.RENDERBUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.SAMPLE_COVERAGE_INVERT)', 'false');
+ shouldBe('context.getParameter(context.SAMPLE_COVERAGE_VALUE)', '1');
+ shouldBe('context.getParameter(context.SCISSOR_BOX)[0]', '0');
+ shouldBe('context.getParameter(context.SCISSOR_BOX)[1]', '0');
+ shouldBe('context.getParameter(context.SCISSOR_BOX)[2]', 'context.getParameter(context.VIEWPORT)[2]');
+ shouldBe('context.getParameter(context.SCISSOR_BOX)[3]', 'context.getParameter(context.VIEWPORT)[3]');
+ shouldBeType('context.getParameter(context.SCISSOR_BOX)', Int32Array);
+ shouldBe('context.getParameter(context.SCISSOR_TEST)', 'false');
+ shouldBe('context.getParameter(context.STENCIL_BACK_FAIL)', 'context.KEEP');
+ shouldBe('context.getParameter(context.STENCIL_BACK_FUNC)', 'context.ALWAYS');
+ shouldBe('context.getParameter(context.STENCIL_BACK_PASS_DEPTH_FAIL)', 'context.KEEP');
+ shouldBe('context.getParameter(context.STENCIL_BACK_PASS_DEPTH_PASS)', 'context.KEEP');
+ shouldBe('context.getParameter(context.STENCIL_BACK_REF)', '0');
+
+ // WebGL 1.0.2 - 5.14.3 types / ES 2.0.25 - 6.2 State tables - 6.18 page 152
+ shouldBeType('context.getParameter(context.SUBPIXEL_BITS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.SUBPIXEL_BITS)', '4');
+
+ shouldBeType('context.getParameter(context.SAMPLE_BUFFERS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.SAMPLE_BUFFERS)', '0');
+
+ shouldBeType('context.getParameter(context.SAMPLES)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.SAMPLES)', '0');
+
+ shouldBeType('context.getParameter(context.DEPTH_BITS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.DEPTH_BITS)', '0');
+ shouldBeType('context.getParameter(context.RED_BITS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.RED_BITS)', '0');
+ shouldBeType('context.getParameter(context.GREEN_BITS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.GREEN_BITS)', '0');
+ shouldBeType('context.getParameter(context.BLUE_BITS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.BLUE_BITS)', '0');
+ shouldBeType('context.getParameter(context.ALPHA_BITS)', 'Number');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.ALPHA_BITS)', '0');
+ shouldBeType('context.getParameter(context.STENCIL_BITS)', 'Number');
+
+ var stencilBits = context.getParameter(context.STENCIL_BITS);
+ minimumRequiredStencilMask = (1 << stencilBits) - 1;
+
+ shouldBe('context.getParameter(context.STENCIL_BACK_VALUE_MASK) & minimumRequiredStencilMask', 'minimumRequiredStencilMask');
+ shouldBe('context.getParameter(context.STENCIL_BACK_WRITEMASK) & minimumRequiredStencilMask', 'minimumRequiredStencilMask');
+
+ // If EXT_packed_depth_stencil is supported, STENCIL_BITS > 0; otherwise, STENCIL_BITS == 0.
+ shouldBe('context.getParameter(context.STENCIL_BITS) >= 0', 'true');
+ shouldBe('context.getParameter(context.STENCIL_CLEAR_VALUE)', '0');
+ shouldBe('context.getParameter(context.STENCIL_FAIL)', 'context.KEEP');
+ shouldBe('context.getParameter(context.STENCIL_FUNC)', 'context.ALWAYS');
+ shouldBe('context.getParameter(context.STENCIL_PASS_DEPTH_FAIL)', 'context.KEEP');
+ shouldBe('context.getParameter(context.STENCIL_PASS_DEPTH_PASS)', 'context.KEEP');
+ shouldBe('context.getParameter(context.STENCIL_REF)', '0');
+ shouldBe('context.getParameter(context.STENCIL_TEST)', 'false');
+
+ shouldBe('context.getParameter(context.STENCIL_VALUE_MASK) & minimumRequiredStencilMask', 'minimumRequiredStencilMask');
+ shouldBe('context.getParameter(context.STENCIL_WRITEMASK) & minimumRequiredStencilMask', 'minimumRequiredStencilMask');
+
+ shouldBe('context.getParameter(context.TEXTURE_BINDING_2D)', 'null');
+ shouldBe('context.getParameter(context.TEXTURE_BINDING_CUBE_MAP)', 'null');
+ shouldBe('context.getParameter(context.UNPACK_ALIGNMENT)', '4');
+ shouldBe('context.getParameter(context.UNPACK_FLIP_Y_WEBGL)', 'false');
+ shouldBe('context.getParameter(context.UNPACK_PREMULTIPLY_ALPHA_WEBGL)', 'false');
+ shouldBe('context.getParameter(context.VIEWPORT)', '[0, 0, 2, 2]');
+ shouldBeType('context.getParameter(context.VIEWPORT)', 'Int32Array');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_COMBINED_TEXTURE_IMAGE_UNITS)', '8');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_CUBE_MAP_TEXTURE_SIZE)', '16');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_FRAGMENT_UNIFORM_VECTORS)', '16');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_RENDERBUFFER_SIZE)', '1');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_TEXTURE_IMAGE_UNITS)', '8');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_TEXTURE_SIZE)', '64');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VARYING_VECTORS)', '8');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VERTEX_ATTRIBS)', '8');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VERTEX_TEXTURE_IMAGE_UNITS)', '0');
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VERTEX_UNIFORM_VECTORS)', '128');
+ // Note: This requirement should be removed from the spec IMO. Many impelementations
+ // will be based on FBOs and FBOs might have a restriction smaller than the current screen size.
+ // especially if there are multiple screens.
+ shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[0] >= window.screen.width');
+ shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[1] >= window.screen.height');
+ shouldBeType('context.getParameter(context.MAX_VIEWPORT_DIMS)', 'Int32Array');
+
+ debug("");
+ debug("check texture values");
+ var maxTextures = context.getParameter(context.MAX_TEXTURE_IMAGE_UNITS);
+ for (var ii = 0; ii < maxTextures; ++ii) {
+ context.activeTexture(context.TEXTURE0 + ii);
+ debug("check texture unit: " + ii);
+ shouldBe('context.getParameter(context.TEXTURE_BINDING_2D)', 'null');
+ shouldBe('context.getParameter(context.TEXTURE_BINDING_CUBE_MAP)', 'null');
+ }
+
+ debug("");
+ debug("check attrib values");
+ var maxAttribs = context.getParameter(context.MAX_VERTEX_ATTRIBS);
+ for (var ii = 0; ii < maxAttribs; ++ii) {
+ debug("check attrib: " + ii);
+ shouldBe('context.getVertexAttrib(ii, context.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)', 'null');
+ shouldBe('context.getVertexAttrib(ii, context.VERTEX_ATTRIB_ARRAY_ENABLED)', 'false');
+ shouldBe('context.getVertexAttrib(ii, context.VERTEX_ATTRIB_ARRAY_SIZE)', '4');
+ shouldBe('context.getVertexAttrib(ii, context.VERTEX_ATTRIB_ARRAY_STRIDE)', '0');
+ shouldBe('context.getVertexAttrib(ii, context.VERTEX_ATTRIB_ARRAY_TYPE)', 'context.FLOAT');
+ shouldBe('context.getVertexAttrib(ii, context.VERTEX_ATTRIB_ARRAY_NORMALIZED)', 'false');
+ shouldBe('context.getVertexAttrib(ii, context.CURRENT_VERTEX_ATTRIB)', '[0, 0, 0, 1]');
+ shouldBeType('context.getVertexAttrib(ii, context.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('context.getVertexAttribOffset(ii, context.VERTEX_ATTRIB_ARRAY_POINTER)', '0');
+ }
+
+ shouldBe('context.getError()', 'context.NO_ERROR');
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-geterror.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-geterror.html
new file mode 100644
index 0000000000..ad5c18e267
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-geterror.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL get error conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="1" height="1" style="width: 256px; height: 48px;"></canvas>
+<div id="description"></div><div id="console"></div>
+<script>
+"use strict";
+description("Test getError.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+gl.enable(desktopGL.ALPHA_TEST);
+wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "should generate INVALID_ENUM");
+gl.viewport(-1, -1, -1, -1);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "should generate INVALID_VALUE");
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should generate INVALID_OPERATION");
+
+// Generate 2 errors of each type for 6 total possible errors.
+// The OpenGL ES 2.0 spec section 2.5 says the implementation is allowed to
+// either return the first error or many errors in an unspecied order.
+gl.viewport(-1, -1, -1, -1);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.enable(desktopGL.ALPHA_TEST);
+gl.viewport(-1, -1, -1, -1);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+// Note: This error is specifically last because we know it will be synthasized
+// by WebGL at least when implemented on top of Desktop OpenGL
+gl.enable(desktopGL.ALPHA_TEST);
+
+var err1 = gl.getError();
+var err2 = gl.getError();
+var err3 = gl.getError();
+var err4 = gl.getError();
+var err5 = gl.getError();
+var err6 = gl.getError();
+
+debug("");
+if (err2 == gl.NO_ERROR) {
+ debug("This WebGL implementation looks like it uses the 'first error' method");
+ debug("There should be 1 error, the first one generated");
+ shouldBeTrue('err1 == gl.INVALID_VALUE && err2 == gl.NO_ERROR && err3 == gl.NO_ERROR');
+} else {
+ debug("This WebGL implementation looks like it uses the many error method");
+ debug("Check is that at least one of the errors is the first error");
+ shouldBeTrue('err1 == gl.INVALID_VALUE || ' +
+ 'err2 == gl.INVALID_VALUE || ' +
+ 'err3 == gl.INVALID_VALUE || ' +
+ 'err4 == gl.INVALID_VALUE || ' +
+ 'err5 == gl.INVALID_VALUE || ' +
+ 'err6 == gl.INVALID_VALUE');
+ shouldBeTrue('gl.getError() == gl.NO_ERROR');
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-getstring.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-getstring.html
new file mode 100644
index 0000000000..3594cc678e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-getstring.html
@@ -0,0 +1,60 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl.getParameter Strings Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks getParameter returns strings in the correct format");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ checkPrefix("WebGL 1.0", "VERSION");
+ checkPrefix("WebGL GLSL ES 1.0", "SHADING_LANGUAGE_VERSION");
+ shouldBeNonNull("gl.getParameter(gl.VENDOR)");
+ shouldBeNonNull("gl.getParameter(gl.RENDERER)");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function checkPrefix(expected, enum_val) {
+ var s = gl.getParameter(gl[enum_val]);
+ if (s != null &&
+ s.length >= expected.length &&
+ s.substring(0, expected.length) == expected) {
+ testPassed("getParameter(gl." + enum_val + ") correctly started with " + expected);
+ } else {
+ testFailed("getParameter(gl." + enum_val + ") did not start with " + expected);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-initial-state.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-initial-state.html
new file mode 100644
index 0000000000..024eaa109b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-initial-state.html
@@ -0,0 +1,58 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl.getParameter initial values Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks the initial value of the OpenGL state");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ checkParameterInitialValue("ONE", "BLEND_SRC_RGB");
+ checkParameterInitialValue("ONE", "BLEND_SRC_ALPHA");
+ checkParameterInitialValue("ZERO", "BLEND_DST_RGB");
+ checkParameterInitialValue("ZERO", "BLEND_DST_ALPHA");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function checkParameterInitialValue(expected, enum_val) {
+ var s = gl.getParameter(gl[enum_val]);
+ if (s === gl[expected]) {
+ testPassed("getParameter(gl." + enum_val + ") returned " + expected + " which is " + gl[expected]);
+ } else {
+ testFailed("getParameter(gl." + enum_val + ") returned " + s + " expected: " + expected + " which is " + gl[expected]);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-object-get-calls.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-object-get-calls.html
new file mode 100644
index 0000000000..7aa2cedf99
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/gl-object-get-calls.html
@@ -0,0 +1,24 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/gl-object-get-calls.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/state/state-uneffected-after-compositing.html b/dom/canvas/test/webgl-conf/checkout/conformance/state/state-uneffected-after-compositing.html
new file mode 100644
index 0000000000..f428156c17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/state/state-uneffected-after-compositing.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL: Check that state is not lost by compositing</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="16" height="16" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+
+function runTest()
+{
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+
+ var program = wtu.setupTexturedQuad(gl);
+ var tex = gl.createTexture();
+ var fb = gl.createFramebuffer();
+
+ var step1 = function() {
+ wtu.fillTexture(gl, tex, 1, 1, [0, 255, 0, 255]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "drawing with texture should be green");
+ };
+
+ var step2 = function() {
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "drawing with texture after composite without rebinding should be green");
+
+ // Clear background to red
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Bind framebuffer with green texture.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255], "reading from fbo with attached texture should be green");
+ };
+
+ var step3 = function() {
+ // Should still have fb bound and reading should be green
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255], "reading from fbo after composite without rebinding should be green");
+ };
+
+ var steps = [
+ step1,
+ step2,
+ step3,
+ ];
+
+ var stepIndex = 0;
+ var runNextStep = function() {
+ steps[stepIndex++]();
+ if (stepIndex == steps.length) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ finishTest();
+ return;
+ }
+ wtu.waitForComposite(runNextStep);
+ };
+ runNextStep();
+}
+
+runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/00_test_list.txt
new file mode 100644
index 0000000000..c6041ff82f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/00_test_list.txt
@@ -0,0 +1,14 @@
+misc/00_test_list.txt
+canvas/00_test_list.txt
+--min-version 1.0.4 canvas_sub_rectangle/00_test_list.txt
+image/00_test_list.txt
+image_data/00_test_list.txt
+--min-version 1.0.4 svg_image/00_test_list.txt
+video/00_test_list.txt
+webgl_canvas/00_test_list.txt
+image_bitmap_from_image_data/00_test_list.txt
+image_bitmap_from_image/00_test_list.txt
+image_bitmap_from_video/00_test_list.txt
+image_bitmap_from_canvas/00_test_list.txt
+image_bitmap_from_blob/00_test_list.txt
+image_bitmap_from_image_bitmap/00_test_list.txt
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..4d9e90a89a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..555ec9f7bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..3e2dd533f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..c1048aba4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..55177f4657
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..3db61ef492
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..f6dafa9a51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..054ad8f7d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..42b25dbe45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..443bbeee85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..03d6aff9b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..c3d2dcb1e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..e841cd8b3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..b41edb8f31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..0b33104d30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..fe394c6ae3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..99a6d0aca0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..044c4d2334
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..a0eb04e7f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..af6f0ffbf3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..a5f6adbd7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4e9fcfb323
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..11033be46d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..57b5a3075b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..3a0f359d58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..63137f0c12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..28b68bb2c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..c8712cc226
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..c7f5406d8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..3a94793561
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..011716760c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..84ea95ec34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_blob/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..60bc8c96ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..d69fbc1ff3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..c141ecd96e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..ad2f120c9f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..b89d10cc62
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..e6d6e105ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..3c9564a31c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..4aae144b39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..9d371e7a7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..ad59d05e7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..d7a9ce4f9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..d61f6ebf8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..a3eeee8a9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f818adaa8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..2b78f918e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..f314b58319
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..14f6624c93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..0802d11106
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..68ec518abb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..35b1e3bb85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..6c55d536c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..69cbc37d95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..eae074f55f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..c0702275b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_bitmap/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..aead08998d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..af81a29c07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..c5b1d52ecd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..66ef9b8475
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..0bca358b3e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..91dc8e25c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..bc519e2e6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..2359b91b59
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..299282586d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..7471323b4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..b700257b99
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..065dd77bc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..6f1125132a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..e58c1612dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..e49c039885
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..b5eeeb3b0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..7b1b1ebd6a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..88ceac1072
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..c953c8be91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..4650594945
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..49744f65f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..95bd9686c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..9d80cf6927
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..b7a529f4ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/00_test_list.txt
new file mode 100644
index 0000000000..c86c269d56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/00_test_list.txt
@@ -0,0 +1,58 @@
+--min-version 1.0.4 canvas-teximage-after-multiple-drawimages.html
+--max-version 1.9.9 compressed-tex-image.html
+copy-tex-image-and-sub-image-2d.html
+--min-version 1.0.2 copy-tex-image-2d-formats.html
+--min-version 1.0.4 copy-tex-image-crash.html
+--min-version 1.0.4 copytexsubimage2d-large-partial-copy-corruption.html
+--min-version 1.0.4 copytexsubimage2d-subrects.html
+--min-version 1.0.4 cube-incomplete-fbo.html
+--min-version 1.0.4 cube-map-uploads-out-of-order.html
+--min-version 1.0.3 default-texture.html
+--min-version 1.0.4 exif-orientation.html
+--min-version 1.0.4 format-filterable-renderable.html
+--min-version 1.0.2 --max-version 1.9.9 gl-get-tex-parameter.html
+gl-pixelstorei.html
+gl-teximage.html
+--min-version 1.0.2 mipmap-fbo.html
+origin-clean-conformance.html
+--min-version 1.0.4 origin-clean-conformance-offscreencanvas.html
+tex-image-and-sub-image-2d-with-array-buffer-view.html
+tex-image-and-uniform-binding-bugs.html
+--min-version 1.0.3 tex-image-canvas-corruption.html
+--min-version 1.0.2 tex-image-webgl.html
+tex-image-with-format-and-type.html
+tex-image-with-invalid-data.html
+--max-version 1.9.9 tex-input-validation.html
+tex-sub-image-2d-bad-args.html
+tex-sub-image-2d.html
+--min-version 1.0.4 tex-video-using-tex-unit-non-zero.html
+texparameter-test.html
+texture-active-bind-2.html
+texture-active-bind.html
+--min-version 1.0.2 texture-attachment-formats.html
+--min-version 1.0.2 texture-clear.html
+texture-complete.html
+--min-version 1.0.4 texture-copying-and-deletion.html
+--min-version 1.0.3 texture-copying-feedback-loops.html
+--min-version 1.0.4 texture-corner-case-videos.html
+--min-version 1.0.4 texture-cube-as-fbo-attachment.html
+--min-version 1.0.3 texture-draw-with-2d-and-cube.html
+--min-version 1.0.3 --max-version 1.9.9 texture-fakeblack.html
+--min-version 1.0.2 --max-version 1.9.9 texture-formats-test.html
+--min-version 1.0.2 texture-hd-dpi.html
+texture-mips.html
+--max-version 1.9.9 texture-npot-video.html
+--max-version 1.9.9 texture-npot.html
+texture-size.html
+texture-size-cube-maps.html
+--min-version 1.0.2 texture-size-limit.html
+--min-version 1.0.4 texture-srgb-upload.html
+--min-version 1.0.2 texture-sub-image-cube-maps.html
+texture-transparent-pixels-initialized.html
+--min-version 1.0.2 texture-upload-cube-maps.html
+--min-version 1.0.3 texture-upload-size.html
+--min-version 1.0.4 texture-video-transparent.html
+--min-version 1.0.4 texture-with-flip-y-and-premultiply-alpha.html
+--min-version 1.0.4 upload-from-srcset-with-empty-data.html
+--min-version 1.0.4 video-rotation.html
+--min-version 1.0.4 png-image-types.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/canvas-teximage-after-multiple-drawimages.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/canvas-teximage-after-multiple-drawimages.html
new file mode 100644
index 0000000000..0c5d45b7b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/canvas-teximage-after-multiple-drawimages.html
@@ -0,0 +1,100 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>TexImage2D of 2D Canvas after multiple drawImages</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+
+const sz = 512;
+let greenImage = null;
+
+function loadImageAndStart(startFunc) {
+ let c = document.createElement('canvas');
+ c.width = sz;
+ c.height = sz;
+ let ctx = c.getContext('2d');
+ ctx.fillStyle = 'rgb(0,255,0)';
+ ctx.fillRect(0, 0, sz, sz);
+ greenImage = wtu.makeImageFromCanvas(c, startFunc);
+}
+
+function runTest() {
+ description();
+ debug('Regression test for <a href="http://crbug.com/878545">http://crbug.com/878545</a>');
+ // Mimics the image-to-texture upload path from the old JavaScript
+ // port of O3D, salvaged at https://github.com/petersont/o3d .
+
+ // Create a canvas and draw the entire image into it.
+ let bigCanvas = document.createElement('canvas');
+ bigCanvas.width = greenImage.naturalWidth;
+ bigCanvas.height = greenImage.naturalHeight;
+ let bc = bigCanvas.getContext('2d');
+ bc.drawImage(greenImage, 0, 0, bigCanvas.width, bigCanvas.height);
+ // Create a temp canvas to flip vertically.
+ let tempCanvas = document.createElement('canvas');
+ tempCanvas.width = bigCanvas.width;
+ tempCanvas.height = bigCanvas.height;
+ let tc = tempCanvas.getContext('2d');
+ tc.translate(0, tempCanvas.height);
+ tc.scale(1, -1);
+ tc.drawImage(bigCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
+ // Set up to draw via WebGL.
+ let c3d = document.getElementById('canvas');
+ let gl = wtu.create3DContext(c3d);
+ let prog = wtu.setupTexturedQuad(gl);
+ gl.uniform1i(gl.getUniformLocation(prog, 'tex'), 0);
+ let tex = gl.createTexture();
+ // Iterate through the large canvas, drawing pieces of it to a
+ // scratch canvas.
+ let scratchCanvas = document.createElement('canvas');
+ const width = tempCanvas.width / 2;
+ const height = tempCanvas.height / 2;
+ let bb = new Uint8Array(4 * c3d.width * c3d.height);
+ for (let jj = 0; jj < 2; ++jj) {
+ for (let ii = 0; ii < 2; ++ii) {
+ // Prepare texture.
+ scratchCanvas.width = width;
+ scratchCanvas.height = height;
+ let ctx = scratchCanvas.getContext('2d');
+ ctx.save();
+ ctx.translate(-(ii * width), -(jj * height));
+ ctx.scale(1.0, 1.0);
+ ctx.drawImage(tempCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
+ scratchCanvas);
+ ctx.restore();
+ gl.generateMipmap(gl.TEXTURE_2D);
+ // Draw and check that rendering occurred properly.
+ gl.uniform1i(gl.getUniformLocation(prog, 'tex'), 0);
+ wtu.drawUnitQuad(gl);
+ let tolerance = 2;
+ wtu.checkCanvasRect(gl, 1, 1, c3d.width - 2, c3d.height - 2,
+ [ 0, 255, 0, 255 ],
+ "should be green",
+ tolerance);
+
+ }
+ }
+
+ finishTest();
+}
+</script>
+</head>
+<body onload="loadImageAndStart(runTest)">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="40" height="40"></canvas>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/compressed-tex-image.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/compressed-tex-image.html
new file mode 100644
index 0000000000..d019a65254
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/compressed-tex-image.html
@@ -0,0 +1,24 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+const contextVersion = 1;
+</script>
+<script src="../../../js/tests/compressed-tex-image.js"></script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-2d-formats.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-2d-formats.html
new file mode 100644
index 0000000000..fd44f9cc73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-2d-formats.html
@@ -0,0 +1,173 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Verify copyTexImage2D follows format restictions</title>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="2" height="2"></canvas>
+<canvas id="canvasNoAlpha" width="2" height="2"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+
+function getChannelsFromFormat(format) {
+ switch (gl[format]) {
+ case gl.ALPHA:
+ return 0x0001;
+ case gl.LUMINANCE:
+ case gl.RGB:
+ return 0x1110;
+ case gl.LUMINANCE_ALPHA:
+ case gl.RGBA:
+ return 0x1111;
+ default:
+ return 0;
+ }
+}
+
+var formats = [
+ 'ALPHA',
+ 'LUMINANCE',
+ 'LUMINANCE_ALPHA',
+ 'RGB',
+ 'RGBA'
+];
+
+var isRenderable = {
+ 'ALPHA': false,
+ 'LUMINANCE': false,
+ 'LUMINANCE_ALPHA': false,
+ 'RGB': true,
+ 'RGBA': true
+};
+
+var gl = null;
+var wtu = WebGLTestUtils;
+
+description();
+
+var canvas = document.getElementById("canvas");
+var canvasNoAlpha = document.getElementById("canvasNoAlpha");
+var gl = wtu.create3DContext(canvas, {alpha:true});
+var glNoAlpha = wtu.create3DContext(canvasNoAlpha, {alpha:false});
+
+debug("test with an RGBA backbuffer");
+var program = wtu.setupTexturedQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "During Initialization");
+testFormats('RGBA');
+
+testBackbufferFormats();
+
+debug("test with an RGB backbuffer");
+var gl = glNoAlpha;
+var program = wtu.setupTexturedQuad(gl);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "During Initialization");
+testFormats('RGB');
+
+function testBackbufferFormats() {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ for (var ii = 0; ii < formats.length; ++ii) {
+ var backFormat = formats[ii];
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[backFormat], 2, 2, 0, gl[backFormat], gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ debug('');
+ if (status == gl.FRAMEBUFFER_COMPLETE) {
+ if (!isRenderable[backFormat]) {
+ testFailed('Creating framebuffer from ' + backFormat + ' texture succeeded even though it is not a renderable format');
+ } else {
+ debug('test with ' + backFormat + ' fbo');
+ testFormats(backFormat);
+ }
+ } else {
+ debug(backFormat + ' not supported as a renderbuffer attachment');
+ }
+ }
+}
+
+function testFormats(backFormat) {
+ for (var ii = 0; ii < formats.length; ++ii) {
+ testCopyTexImage2D(backFormat, formats[ii]);
+ }
+}
+
+function toChannels(value) {
+ return ((value & 0x1000) ? 'R' : '_') +
+ ((value & 0x0100) ? 'G' : '_') +
+ ((value & 0x0010) ? 'B' : '_') +
+ ((value & 0x0001) ? 'A' : '_');
+}
+
+function testCopyTexImage2D(backFormat, texFormat) {
+ var need = getChannelsFromFormat(texFormat);
+ var have = getChannelsFromFormat(backFormat);
+ var shouldPass = (need & have) == need;
+
+ //debug("need: " + toChannels(need));
+ //debug("have: " + toChannels(have));
+ //debug("both: " + toChannels(have & need));
+
+ // clear backbuffer
+ gl.clearColor(0.25, 1, 0.75, 0.5);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ 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);
+
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl[texFormat], 0, 0, 2, 2, 0);
+ if (!shouldPass) {
+ wtu.glErrorShouldBe(
+ gl, gl.INVALID_OPERATION,
+ "should not be able to copyTexImage2D " + texFormat + " from " + backFormat);
+ return;
+ }
+
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR,
+ "should be able to copyTexImage2D " + texFormat + " from " + backFormat);
+
+ // Draw
+ wtu.clearAndDrawUnitQuad(gl);
+
+ var expectedColors = {
+ 'ALPHA': [0, 0, 0, 127],
+ 'LUMINANCE': [64, 64, 64, 255],
+ 'LUMINANCE_ALPHA': [64, 64, 64, 127],
+ 'RGB': [64, 255, 191, 255],
+ 'RGBA': [64, 255, 191, 127]
+ };
+
+ var color = expectedColors[texFormat];
+
+ wtu.checkCanvas(gl, color, "should be " + color, 16);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-and-sub-image-2d.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-and-sub-image-2d.html
new file mode 100644
index 0000000000..a751582472
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-and-sub-image-2d.html
@@ -0,0 +1,137 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script>
+"use strict";
+var successfullyParsed = false;
+
+function init()
+{
+ description('Verify copyTexImage2D and copyTexSubImage2D');
+
+ runTest();
+}
+
+var gl = null;
+var wtu = WebGLTestUtils;
+
+function runTestIteration(antialias)
+{
+ var canvas = document.getElementById(
+ antialias ? "antialiasOn" : "antialiasOff");
+ var attribs = antialias ? { antialias: true } : { antialias: false };
+ gl = wtu.create3DContext(canvas, attribs);
+ var program = wtu.setupTexturedQuad(gl);
+ var textureLoc = gl.getUniformLocation(program, "tex");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "During Initialization");
+
+ gl.colorMask(1, 1, 1, 1);
+ gl.disable(gl.BLEND);
+ debug('Testing copyTexImage2D');
+
+ // Red canvas
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ // Set up texture
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.uniform1i(textureLoc, 0);
+
+ var colors = [
+ [1, 0, 0, 1],
+ [0, 1, 0, 1],
+ [0, 0, 1, 1],
+ [0.5, 0.5, 0.5, 0.5],
+ ];
+ var data = new Uint8Array(2 * 2 * 4);
+ for (var ii = 0; ii < 2 * 2 * 4; ++ii)
+ data[ii] = 136; // A random number other than 0.
+ var count = 0;
+ for (var yy = -2; yy <= 2; ++yy) {
+ for (var xx = -2; xx <= 2; ++xx) {
+ for (var ii = 0; ii < 2; ++ii) {
+ var texColor = colors[count];
+ var clearColor = colors[(count + 1) % colors.length];
+ // clear to some color
+ gl.clearColor(texColor[0], texColor[1], texColor[2], texColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // copy that color to the texture.
+ switch (ii) {
+ case 0:
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, xx, yy, 2, 2, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "using copyTexImage2D: x = " + xx + ", y = " + yy);
+ break;
+ case 1:
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, xx, yy, 2, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "using copyTexSubImage2D: x = " + xx + ", y = " + yy);
+ break;
+ }
+
+ // clear to some other color.
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl);
+
+ // check the rendering results
+ for (var iy = 0; iy < 2; ++iy) {
+ for (var ix = 0; ix < 2; ++ix) {
+ var x = xx + ix;
+ var y = yy + iy;
+ var expectedColor = (x < 0 || y < 0 || x >= 2 || y >= 2) ?
+ (ii == 0 ? [0, 0, 0, 0] : [136, 136, 136, 136]) :
+ [Math.floor(255 * texColor[0]),
+ Math.floor(255 * texColor[1]),
+ Math.floor(255 * texColor[2]),
+ Math.floor(255 * texColor[3])];
+ wtu.checkCanvasRect(gl, ix, iy, 1, 1, expectedColor,
+ "" + ix + ", " + iy + " should render " + expectedColor + " (+/-1)", 1);
+ }
+ }
+ count = (count + 1) % colors.length;
+ }
+ }
+ }
+
+ debug("");
+}
+
+function runTest(antialias)
+{
+ debug("Testing with antialias on");
+ runTestIteration(true);
+ debug("Testing with antialias off");
+ runTestIteration(false);
+
+ finishTest();
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="antialiasOn" width="2" height="2"></canvas>
+<canvas id="antialiasOff" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-crash.html
new file mode 100644
index 0000000000..994051672a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-image-crash.html
@@ -0,0 +1,69 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>copyTexImage2D should not crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas"></canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Draw into source of copyTexSubImage2D shouldn't crash: regression test for https://crbug.com/707445");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+canvas.width = 16;
+canvas.height = 16;
+var gl = wtu.create3DContext(canvas);
+
+function runTest() {
+ // Setup/clear source texture
+ let tex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ let fb1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Setup/clear destination texture
+ let tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ let fb2 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Copy from source to destination texture
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 16, 16, 0);
+
+ // Draw into source texture
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ let program = wtu.setupColorQuad(gl); // Used as a trivial shader; any shader will work.
+ gl.useProgram(program);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-large-partial-copy-corruption.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-large-partial-copy-corruption.html
new file mode 100644
index 0000000000..41fe47008f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-large-partial-copy-corruption.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CopyTexSubImage2D partial destination texture test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas"></canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Verifies that copyTexSubImage2D redefining part of the destination texture works as expected.");
+
+function runTest() {
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("canvas");
+ canvas.width = 256;
+ canvas.height = 256;
+ var gl = wtu.create3DContext(canvas);
+ // Try this test multiple times.
+ for (var ii = 0; ii < 10; ++ii) {
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ // Allocate a texture twice as tall as the canvas.
+ // Conceptually, it is filled with zeros.
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, 2 * canvas.height,
+ 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ // Copy the entire framebuffer into the top part of this texture.
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, canvas.width, canvas.height);
+ // Draw the texture back into the canvas.
+ var program = wtu.setupTexturedQuad(gl);
+ wtu.drawUnitQuad(gl);
+ gl.deleteProgram(program);
+ gl.deleteTexture(tex);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height / 2, [0, 255, 0, 255],
+ "should be green");
+ wtu.checkCanvasRect(gl, 0, canvas.height / 2, canvas.width, canvas.height / 2, [0, 0, 0, 0],
+ "should be transparent black");
+ }
+}
+
+runTest();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-subrects.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-subrects.html
new file mode 100644
index 0000000000..d4a1791790
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copytexsubimage2d-subrects.html
@@ -0,0 +1,170 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CopyTexSubImage2D partial destination texture test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas"></canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Verifies that copyTexSubImage2D redefining part of the destination texture works as expected.");
+
+////
+
+var kWidth = 16;
+var kHeight = 16;
+
+////
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+
+canvas.width = kWidth;
+canvas.height = kHeight;
+var gl = wtu.create3DContext(canvas);
+
+////
+
+function clearTo(color) {
+ gl.clearColor(color[0], color[1], color[2], color[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+}
+
+function readInto(view) {
+ gl.readPixels(0, 0, kWidth, kHeight, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(view.buffer));
+}
+
+////
+
+function runTest() {
+ gl.enable(gl.SCISSOR_TEST);
+
+ gl.scissor(0, 0, kWidth/2, kHeight/2);
+ clearTo([1,0,0,1]);
+ gl.scissor(kWidth/2, 0, kWidth/2, kHeight/2);
+ clearTo([0,1,0,1]);
+ gl.scissor(0, kHeight/2, kWidth/2, kHeight/2);
+ clearTo([0,0,1,1]);
+ gl.scissor(kWidth/2, kHeight/2, kWidth/2, kHeight/2);
+ clearTo([0,1,1,1]);
+
+ var srcData = new Uint32Array(kWidth * kHeight);
+ readInto(srcData);
+ console.log('0x' + srcData[0].toString(16));
+
+ ////
+
+ var dstTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, dstTex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, kWidth, kHeight,
+ 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // Uploads zeros.
+ var dstRefData = new Uint32Array(kWidth * kHeight); // Also cleared to zeros!
+ var dstTestData = new Uint32Array(kWidth * kHeight);
+
+ var dstFB = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, dstFB);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, dstTex, 0);
+
+ ////
+
+ function pixelPos(x, y) {
+ return y * kWidth + x;
+ }
+
+ function testCmd(tuple) {
+ var dstX0, dstY0, srcX0, srcY0, width, height;
+ [dstX0, dstY0, srcX0, srcY0, width, height] = tuple
+ debug("copyTexSubImage2D(" +
+ [dstX0+','+dstY0, srcX0+','+srcY0, width+','+height].join(', ') +
+ ")");
+
+ // Test
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0,
+ dstX0, dstY0, srcX0, srcY0, width, height);
+
+ // Emulate for reference
+ for (var x = 0; x < width; x++) {
+ var srcX = srcX0 + x;
+ var dstX = dstX0 + x;
+ if (srcX < 0 || srcX >= kWidth ||
+ dstX < 0 || dstX >= kWidth)
+ {
+ continue;
+ }
+
+ for (var y = 0; y < height; y++) {
+ var srcY = srcY0 + y;
+ var dstY = dstY0 + y;
+ if (srcY < 0 || srcY >= kHeight ||
+ dstY < 0 || dstY >= kHeight)
+ {
+ continue;
+ }
+
+
+ var srcPos = pixelPos(srcX, srcY);
+ var dstPos = pixelPos(dstX, dstY);
+ dstRefData[dstPos] = srcData[srcPos];
+ }
+ }
+
+ // Compare
+ gl.bindFramebuffer(gl.FRAMEBUFFER, dstFB);
+ readInto(dstTestData);
+
+ for (var x = 0; x < kWidth; x++) {
+ for (var y = 0; y < kHeight; y++) {
+ var pos = pixelPos(x, y);
+ var refPixel = dstRefData[pos];
+ var testPixel = dstTestData[pos];
+
+ //console.log([x, y].join(",") + ":",
+ // testPixel.toString(16), refPixel.toString(16))
+ if (testPixel == refPixel)
+ continue;
+
+ testFailed("Mismatch at (" + [x, y].join(", ") + "): " +
+ " Should be 0x" + refPixel.toString(16) +
+ ", was 0x" + testPixel.toString(16));
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ var tests = [
+ [0,0, 0,0, 2,3],
+ [0,0, 5,8, 2,3],
+ [1,0, 0,0, 2,3],
+ [1,7, 0,0, 2,3],
+ ];
+
+ tests.every(x => testCmd(x));
+}
+
+runTest();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-incomplete-fbo.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-incomplete-fbo.html
new file mode 100644
index 0000000000..d08801f085
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-incomplete-fbo.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test that cube incomplete textures can not be used as FBO attachments</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example");
+
+var testIncompleteCubemapFaceInFBO = function() {
+ // Create a cube map texture that's not cube complete.
+ var tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex2);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+ var cube_map_faces = [
+ 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
+ ];
+ // Fill in all but 1 cube map face
+ for (var i = 0; i < cube_map_faces.length - 1; ++i) {
+ gl.texImage2D(cube_map_faces[i], 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+
+ var fb2 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex2, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors after attaching cube map face.");
+ debug("Cubemap has 1 missing face, so framebuffer should not be complete.");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+
+ debug("");
+
+ // Fill in missing cube map face
+ gl.texImage2D(cube_map_faces[5], 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ debug("Missing face is added, so framebuffer should become complete.");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+}
+
+testIncompleteCubemapFaceInFBO();
+
+var successfullyParsed = true;
+finishTest();
+
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-map-uploads-out-of-order.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-map-uploads-out-of-order.html
new file mode 100644
index 0000000000..88ea83e325
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/cube-map-uploads-out-of-order.html
@@ -0,0 +1,90 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL cube map out of order upload test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="64" height="64">
+</canvas>
+<script>
+"use strict";
+description("Test out of order cube map uploads.");
+debug("Regression test for crbug.com/473739 / Apple Radar 20444072.");
+
+<!-- Thanks to Gregg Tavares for the original report and test case. -->
+
+var wtu = WebGLTestUtils;
+
+var canvas = document.getElementById("example");
+canvas.addEventListener('webglcontextlost', contextLost, false);
+
+var contextWasLost = false;
+
+function contextLost(e) {
+ e.preventDefault();
+ contextWasLost = true;
+ debug("***context lost -- should not happen***");
+}
+
+var dataWidth = 256;
+var dataHeight = 256;
+var gl = wtu.create3DContext(canvas);
+var tex = gl.createTexture();
+// start with 1x1 pixel cubemap
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+var color = new Uint8Array([128, 192, 255, 255]);
+for (var ii = 0; ii < 6; ++ii) {
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, color);
+}
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+gl.generateMipmap(gl.TEXTURE_CUBE_MAP); // there's no need to call this but the code doesn't check the size.
+
+var textureData = new Uint8Array(dataWidth * dataHeight * 4);
+
+// The first texture has downloaded
+var first = 1;
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + first, 0, gl.RGBA, dataWidth, dataHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
+
+// Now because the first face downloaded doesn't match the other 5 faces upload the same image to the other 5
+// 1x1 faces
+for (var ii = 0; ii < 6; ++ii) {
+ if (ii !== first) {
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, gl.RGBA, dataWidth, dataHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
+ }
+}
+gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+
+// Now as each new face comes in add it
+for (var ii = 0; ii < 6; ++ii) {
+ if (ii !== first) {
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, gl.RGBA, dataWidth, dataHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ }
+}
+
+gl.flush();
+
+setTimeout(function() {
+ shouldBe("contextWasLost", "false");
+ finishTest();
+}, 1000);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/default-texture.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/default-texture.html
new file mode 100644
index 0000000000..0f8cd21cf6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/default-texture.html
@@ -0,0 +1,42 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Tests texture access with no texture bound</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+// When no texture is bound, it is considered an incomplete texture,
+// therefore, [0, 0, 0, 1] should be returned.
+// See OpenGL ES spec 2.0.25, section F.3.5.
+wtu.checkCanvas(gl, [0, 0, 0, 255]);
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/exif-orientation.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/exif-orientation.html
new file mode 100644
index 0000000000..3fd596d445
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/exif-orientation.html
@@ -0,0 +1,167 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verifies EXIF orientation is respected when uploading images to WebGL textures</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+</head>
+<body onload="run()">
+<canvas id="c" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+let wtu = WebGLTestUtils;
+let tiu = TexImageUtils;
+let canvas = document.getElementById("c");
+let gl = wtu.create3DContext(canvas);
+let program = tiu.setupTexturedQuad(gl, gl.RGBA);
+const resourcePath = "../../../resources/";
+const tolerance = 5;
+
+// The locations are written assuming flipY = false. For flipY = true, y = 1.0-y.
+const expectedColors = {
+ top: { location: [ 0.5, 0.25 ], color: [ 255, 0, 0 ] },
+ left: { location: [ 0.4, 0.5 ], color: [ 0, 0, 255 ] },
+ right: { location: [ 0.6, 0.5 ], color: [ 255, 255, 0 ] },
+ bottom: { location: [ 0.5, 0.75 ], color: [ 0, 255, 0 ] },
+}
+
+function output(str)
+{
+ debug(str);
+ bufferedLogToConsole(str);
+}
+
+function checkPixels(flipY)
+{
+ for (let place in expectedColors) {
+ let color = expectedColors[place];
+ let loc = color.location;
+ let x = loc[0];
+ let y = (flipY ? 1.0 - loc[1] : loc[1]);
+ output(" Checking " + place);
+ wtu.checkCanvasRect(gl, Math.floor(canvas.width * x), Math.floor(canvas.height * y), 1, 1,
+ color.color, "shouldBe " + color.color + " +/-" + tolerance, tolerance);
+ }
+}
+
+async function testImageBitmapFromBlobWithFlipY(blob, flipY)
+{
+ let bitmap;
+ // As a concession to Firefox, which doesn't yet implement
+ // createImageBitmap with creation options, skip the tests
+ // involving flipY=true if ImageBitmap creation throws an
+ // exception, and use the single-argument constructor for the
+ // flipY=false case.
+ if (flipY) {
+ try {
+ bitmap = await createImageBitmap(blob, {imageOrientation: flipY});
+ } catch (e) {
+ output(" (createImageBitmap options not supported - skipping flipY=true case)");
+ return;
+ }
+ } else {
+ bitmap = await createImageBitmap(blob);
+ }
+
+ output(" Testing texImage2D, flipY = " + flipY);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ checkPixels(flipY);
+
+ output(" Testing texSubImage2D, flipY = " + flipY);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, bitmap.width, bitmap.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ checkPixels(flipY);
+}
+
+async function testImageBitmapFromBlob(filename)
+{
+ let response = await fetch(resourcePath + filename);
+ let blob = await response.blob();
+ output("----------------------------------------------------------------");
+ output("Testing " + filename + " via ImageBitmap from Blob");
+ await testImageBitmapFromBlobWithFlipY(blob, true);
+ await testImageBitmapFromBlobWithFlipY(blob, false);
+}
+
+async function testImageElementWithFlipY(image, flipY)
+{
+ output(" Testing texImage2D, flipY = " + flipY);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ checkPixels(flipY);
+
+ output(" Testing texSubImage2D, flipY = " + flipY);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ checkPixels(flipY);
+}
+
+async function testImageElement(filename)
+{
+ let image = new Image();
+ image.src = resourcePath + filename;
+ await image.decode();
+
+ output("----------------------------------------------------------------");
+ output("Testing " + filename + " via HTMLImageElement");
+
+ await testImageElementWithFlipY(image, true);
+ await testImageElementWithFlipY(image, false);
+}
+
+async function testSingleImage(filename)
+{
+ await testImageBitmapFromBlob(filename);
+ await testImageElement(filename);
+}
+
+async function run()
+{
+ let tex = gl.createTexture();
+ // Bind the texture to the default texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ const filenames = [
+ "exif-orientation-test-1-normal.jpg",
+ "exif-orientation-test-2-mirror-horizontal.jpg",
+ "exif-orientation-test-3-rotate-180.jpg",
+ "exif-orientation-test-4-mirror-vertical.jpg",
+ "exif-orientation-test-5-mirror-horizontal-90-ccw.jpg",
+ "exif-orientation-test-6-90-ccw.jpg",
+ "exif-orientation-test-7-mirror-horizontal-90-cw.jpg",
+ "exif-orientation-test-8-90-cw.jpg",
+ ];
+
+ for (let fn of filenames) {
+ await testSingleImage(fn);
+ }
+
+ finishTest();
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/format-filterable-renderable.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/format-filterable-renderable.html
new file mode 100644
index 0000000000..df7694b821
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/format-filterable-renderable.html
@@ -0,0 +1,378 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description();
+
+const gl = wtu.create3DContext();
+gl.canvas.width = gl.canvas.height = 1;
+
+function makeTexImage(format, unpackFormat, unpackType, data) {
+ data = data || null;
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[format], 2, 2, 0,
+ gl[unpackFormat], gl[unpackType], null);
+ return tex;
+}
+
+const DUMMY_COLOR = makeTexImage('RGBA', 'RGBA', 'UNSIGNED_BYTE');
+
+function makeProgram(gl, vsSrc, fsSrc) {
+ function makeShader(prog, type, src) {
+ const shader = gl.createShader(gl[type]);
+ gl.shaderSource(shader, src.trim());
+ gl.compileShader(shader);
+ gl.attachShader(prog, shader);
+ gl.deleteShader(shader);
+ };
+
+ const prog = gl.createProgram();
+ makeShader(prog, 'VERTEX_SHADER', vsSrc);
+ makeShader(prog, 'FRAGMENT_SHADER', fsSrc);
+ gl.linkProgram(prog);
+
+ if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
+ throw 'Program linking failed' + fsSrc;
+ }
+ return prog;
+}
+
+const TEX_FILTER_PROG_T = (version, samplerT) => makeProgram(gl, `\
+ ${version}
+ void main() {
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0.5,0.5,0,1);
+ }`,`\
+ ${version}
+ precision mediump float;
+ uniform ${samplerT} u_tex0;
+ #if __VERSION__ == 300
+ out vec4 o_FragColor;
+ #else
+ #define o_FragColor gl_FragColor
+ #define texture texture2D
+ #endif
+ void main() {
+ o_FragColor = vec4(texture(u_tex0, vec2(0.8)));
+ }`);
+const TEX_FILTER_PROG_BY_TYPEISH = {
+ 'float': TEX_FILTER_PROG_T('', 'sampler2D'),
+};
+if (wtu.isWebGL2(gl)) {
+ TEX_FILTER_PROG_BY_TYPEISH['int'] =
+ TEX_FILTER_PROG_T('#version 300 es', 'highp isampler2D');
+ TEX_FILTER_PROG_BY_TYPEISH['uint'] =
+ TEX_FILTER_PROG_T('#version 300 es', 'highp usampler2D');
+}
+
+function runPixelProgram(gl, prog) {
+ gl.useProgram(prog);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ const bytes = new Uint8Array(4);
+ gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, bytes);
+ return [].map.call(bytes, x => x/255.0);
+}
+
+// GLES 2.0.25 p63
+const FORMAT_INFO_WEBGL1 = {
+ RGBA8 : { filter: true, render: true , unpack: ['RGBA', 'UNSIGNED_BYTE'] },
+ RGB8 : { filter: true, render: undefined, unpack: ['RGB', 'UNSIGNED_BYTE'] },
+ RGBA4 : { filter: true, render: undefined, unpack: ['RGBA', 'UNSIGNED_SHORT_4_4_4_4'] },
+ RGB5_A1: { filter: true, render: undefined, unpack: ['RGBA', 'UNSIGNED_SHORT_5_5_5_1'] },
+ RGB565 : { filter: true, render: undefined, unpack: ['RGB', 'UNSIGNED_SHORT_5_6_5'] },
+ LA8 : { filter: true, render: false , unpack: ['LUMINANCE_ALPHA', 'UNSIGNED_BYTE'] },
+ L8 : { filter: true, render: false , unpack: ['LUMINANCE', 'UNSIGNED_BYTE'] },
+ A8 : { filter: true, render: false , unpack: ['ALPHA', 'UNSIGNED_BYTE'] },
+};
+
+// GLES 3.0.6 p130-132
+const FORMAT_INFO_WEBGL2 = {
+ R8 : { render: true , filter: true , unpack: ['RED', 'UNSIGNED_BYTE'] },
+ R8_SNORM : { render: false, filter: true , unpack: ['RED', 'BYTE'] },
+ RG8 : { render: true , filter: true , unpack: ['RG', 'UNSIGNED_BYTE'] },
+ RG8_SNORM : { render: false, filter: true , unpack: ['RG', 'BYTE'] },
+ RGB8 : { render: true , filter: true , unpack: ['RGB', 'UNSIGNED_BYTE'] },
+ RGB8_SNORM : { render: false, filter: true , unpack: ['RGB', 'BYTE'] },
+ RGB565 : { render: true , filter: true , unpack: ['RGB', 'UNSIGNED_SHORT_5_6_5'] },
+ RGBA4 : { render: true , filter: true , unpack: ['RGBA', 'UNSIGNED_SHORT_4_4_4_4'] },
+ RGB5_A1 : { render: true , filter: true , unpack: ['RGBA', 'UNSIGNED_SHORT_5_5_5_1'] },
+ RGBA8 : { render: true , filter: true , unpack: ['RGBA', 'UNSIGNED_BYTE'] },
+ RGBA8_SNORM : { render: false, filter: true , unpack: ['RGBA', 'BYTE'] },
+ RGB10_A2 : { render: true , filter: true , unpack: ['RGBA', 'UNSIGNED_INT_10_10_10_2'] },
+ RGB10_A2UI : { render: true , filter: false, unpack: ['RGBA', 'UNSIGNED_INT_10_10_10_2'] },
+ SRGB8 : { render: false, filter: true , unpack: ['RGB', 'UNSIGNED_BYTE'] },
+ SRGB8_ALPHA8 : { render: true , filter: true , unpack: ['RGBA', 'UNSIGNED_BYTE'] },
+ R16F : { render: false, filter: true , unpack: ['RED', 'FLOAT'] },
+ RG16F : { render: false, filter: true , unpack: ['RG', 'FLOAT'] },
+ RGB16F : { render: false, filter: true , unpack: ['RGB', 'FLOAT'] },
+ RGBA16F : { render: false, filter: true , unpack: ['RGBA', 'FLOAT'] },
+ R32F : { render: false, filter: false, unpack: ['RED', 'FLOAT'] },
+ RG32F : { render: false, filter: false, unpack: ['RG', 'FLOAT'] },
+ RGB32F : { render: false, filter: false, unpack: ['RGB', 'FLOAT'] },
+ RGBA32F : { render: false, filter: false, unpack: ['RGBA', 'FLOAT'] },
+ R11F_G11F_B10F: { render: false, filter: true , unpack: ['RGB', 'FLOAT'] },
+ RGB9_E5 : { render: false, filter: true , unpack: ['RGB', 'FLOAT'] },
+ R8I : { render: true , filter: false, unpack: ['RED', 'BYTE'] },
+ R8UI : { render: true , filter: false, unpack: ['RED', 'UNSIGNED_BYTE'] },
+ R16I : { render: true , filter: false, unpack: ['RED', 'BYTE'] },
+ R16UI : { render: true , filter: false, unpack: ['RED', 'UNSIGNED_BYTE'] },
+ R32I : { render: true , filter: false, unpack: ['RED', 'BYTE'] },
+ R32UI : { render: true , filter: false, unpack: ['RED', 'UNSIGNED_BYTE'] },
+ RG8I : { render: true , filter: false, unpack: ['RG', 'BYTE'] },
+ RG8UI : { render: true , filter: false, unpack: ['RG', 'UNSIGNED_BYTE'] },
+ RG16I : { render: true , filter: false, unpack: ['RG', 'SHORT'] },
+ RG16UI : { render: true , filter: false, unpack: ['RG', 'UNSIGNED_SHORT'] },
+ RG32I : { render: true , filter: false, unpack: ['RG', 'INT'] },
+ RG32UI : { render: true , filter: false, unpack: ['RG', 'UNSIGNED_INT'] },
+ RGB8I : { render: false, filter: false, unpack: ['RGB', 'BYTE'] },
+ RGB8UI : { render: false, filter: false, unpack: ['RGB', 'UNSIGNED_BYTE'] },
+ RGB16I : { render: false, filter: false, unpack: ['RGB', 'SHORT'] },
+ RGB16UI : { render: false, filter: false, unpack: ['RGB', 'UNSIGNED_SHORT'] },
+ RGB32I : { render: false, filter: false, unpack: ['RGB', 'INT'] },
+ RGB32UI : { render: false, filter: false, unpack: ['RGB', 'UNSIGNED_INT'] },
+ RGBA8I : { render: true , filter: false, unpack: ['RGBA', 'BYTE'] },
+ RGBA8UI : { render: true , filter: false, unpack: ['RGBA', 'UNSIGNED_BYTE'] },
+ RGBA16I : { render: true , filter: false, unpack: ['RGBA', 'SHORT'] },
+ RGBA16UI : { render: true , filter: false, unpack: ['RGBA', 'UNSIGNED_SHORT'] },
+ RGBA32I : { render: true , filter: false, unpack: ['RGBA', 'INT'] },
+ RGBA32UI : { render: true , filter: false, unpack: ['RGBA', 'UNSIGNED_INT'] },
+
+ DEPTH_COMPONENT16: { render: 'DEPTH_ATTACHMENT', filter: false },
+ DEPTH_COMPONENT24: { render: 'DEPTH_ATTACHMENT', filter: false },
+ DEPTH_COMPONENT32F: { render: 'DEPTH_ATTACHMENT', filter: false },
+ DEPTH24_STENCIL8: { render: 'DEPTH_STENCIL_ATTACHMENT', filter: false },
+ DEPTH32F_STENCIL8: { render: 'DEPTH_STENCIL_ATTACHMENT', filter: false },
+};
+
+const ONE_BY_TYPE = {
+ 'BYTE': (1<<7)-1,
+ 'UNSIGNED_BYTE': (1<<8)-1,
+ 'SHORT': (1<<15)-1,
+ 'UNSIGNED_SHORT': (1<<16)-1,
+ 'INT': (1<<31)-1,
+ 'UNSIGNED_INT': Math.pow(2,32)-1,
+ 'FLOAT': 1,
+};
+
+const ABV_BY_TYPE = {
+ 'BYTE': Int8Array,
+ 'UNSIGNED_BYTE': Uint8Array,
+ 'SHORT': Int16Array,
+ 'UNSIGNED_SHORT': Uint16Array,
+ 'INT': Int32Array,
+ 'UNSIGNED_INT': Uint32Array,
+ 'FLOAT': Float32Array,
+};
+
+function pushBitsUnorm(prev, bitCount, floatVal) {
+ let ret = prev << bitCount;
+ ret |= floatVal * ((1 << bitCount)-1);
+ return ret;
+}
+
+const CHANNELS_BY_FORMAT = {
+ 'RED': 1,
+ 'LUMINANCE': 1,
+ 'ALPHA': 1,
+ 'LUMINANCE_ALPHA': 2,
+ 'RG': 2,
+ 'RGB': 3,
+ 'RGBA': 4,
+};
+
+function throwv(val) {
+ throw val;
+}
+
+function pixelDataForUnpack(format, type, floatVal) {
+ switch (type) {
+ case 'UNSIGNED_SHORT_5_6_5': {
+ let bits = 0;
+ bits = pushBitsUnorm(bits, 5, floatVal);
+ bits = pushBitsUnorm(bits, 6, floatVal);
+ bits = pushBitsUnorm(bits, 5, floatVal);
+ return new Uint16Array([bits]);
+ }
+ case 'UNSIGNED_SHORT_4_4_4_4': {
+ let bits = 0;
+ bits = pushBitsUnorm(bits, 4, floatVal);
+ bits = pushBitsUnorm(bits, 4, floatVal);
+ bits = pushBitsUnorm(bits, 4, floatVal);
+ bits = pushBitsUnorm(bits, 4, floatVal);
+ return new Uint16Array([bits]);
+ }
+ case 'UNSIGNED_SHORT_5_5_5_1': {
+ let bits = 0;
+ bits = pushBitsUnorm(bits, 5, floatVal);
+ bits = pushBitsUnorm(bits, 5, floatVal);
+ bits = pushBitsUnorm(bits, 5, floatVal);
+ bits = pushBitsUnorm(bits, 1, floatVal); // Ok, silly for 1 bit here.
+ return new Uint16Array([bits]);
+ }
+ case 'UNSIGNED_INT_10_10_10_2': {
+ let bits = 0;
+ bits = pushBitsUnorm(bits, 10, floatVal);
+ bits = pushBitsUnorm(bits, 10, floatVal);
+ bits = pushBitsUnorm(bits, 10, floatVal);
+ bits = pushBitsUnorm(bits, 2, floatVal); // 2 bits isn't much more useful
+ return new Uint32Array([bits]);
+ }
+ }
+
+ const channels = CHANNELS_BY_FORMAT[format] || throwv(format);
+ const one = ONE_BY_TYPE[type] || throwv('240', type);
+ const abvType = ABV_BY_TYPE[type] || throwv('241', type);
+
+ const val = floatVal * one;
+ const arr = [];
+ for (const i of range(channels)) {
+ arr.push(val);
+ }
+ return new abvType(arr);
+}
+
+function expect(name, was, expected) {
+ let text = `${name} was ${was}`;
+ const cond = was == expected;
+ if (!cond) {
+ text += `, but expected ${expected}`;
+ }
+ expectTrue(cond, text);
+}
+
+function toTypeish(sizedFormat) {
+ if (sizedFormat.endsWith('UI')) {
+ return 'int';
+ } else if (sizedFormat.endsWith('I')) {
+ return 'uint';
+ }
+ return 'float';
+}
+
+call(async () => {
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ let formatList = FORMAT_INFO_WEBGL1;
+ if (wtu.isWebGL2(gl)) {
+ formatList = FORMAT_INFO_WEBGL2;
+ }
+ for (const [sizedFormat, info] of Object.entries(formatList)) {
+ await wtu.dispatchPromise();
+ debug(``);
+ debug(`${sizedFormat}: ${JSON.stringify(info)}`);
+
+ const typeish = toTypeish(sizedFormat);
+
+ // |---|---|
+ // | 0 | 1 |
+ // |---|---|
+ // 0| 0 | 0 |
+ // |---|---|
+ // 0
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ if (gl.texStorage2D) {
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl[sizedFormat], 2, 2);
+ } else {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[info.unpack[0]],
+ 2, 2, 0, gl[info.unpack[0]], gl[info.unpack[1]], null);
+ }
+
+ if (info.unpack) {
+ const one = pixelDataForUnpack(...info.unpack, 1.0);
+ const data = new one.constructor(one.length*4);
+ data.set(one, one.length*3);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0,
+ 2,2, gl[info.unpack[0]], gl[info.unpack[1]], data);
+ } else {
+ info.render || throwv(`${sizedFormat} without unpack or render`);
+ }
+
+ // -
+ // color-renderable test
+
+ {
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let attach = info.render || true;
+ const isColor = (attach === true);
+ if (isColor) {
+ attach = 'COLOR_ATTACHMENT0';
+ } else {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, DUMMY_COLOR, 0);
+ }
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[attach],
+ gl.TEXTURE_2D, tex, 0);
+ const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ const wasRenderable = (status == gl.FRAMEBUFFER_COMPLETE);
+ if (info.render === undefined) {
+ debug(`Non-normative: color-renderable was ${wasRenderable}`);
+ } else {
+ expect('color-renderable', wasRenderable, !!info.render);
+ }
+ if (wasRenderable) {
+ gl.clearColor(0,0,0,0);
+ gl.clearDepth(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(1,1,1,1);
+ gl.clearColor(1,1,1,1);
+ gl.clearDepth(1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.disable(gl.SCISSOR_TEST);
+ }
+ gl.deleteFramebuffer(fb);
+ if (!wasRenderable && !info.unpack) {
+ testFailed('No unpack provided and !wasRenderable, skipping filtering subtest...');
+ continue;
+ }
+ }
+
+ // -
+ // filterable test
+
+ const prog = TEX_FILTER_PROG_BY_TYPEISH[typeish];
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.clearColor(0,0,0,0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.viewport(0,0,1,1);
+ const v = runPixelProgram(gl, prog);
+ if (sizedFormat != 'A8') {
+ v[3] = 0; // Incomplete no-alpha formats put 1 in alpha.
+ }
+ const wasFilterable = v.some(x => !!x);
+ expect('filterable', wasFilterable, info.filter);
+ }
+
+ finishTest();
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-get-tex-parameter.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-get-tex-parameter.html
new file mode 100644
index 0000000000..fbfc2c510a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-get-tex-parameter.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL getTexParameter test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../../js/tests/gl-get-tex-parameter.js"></script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-pixelstorei.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-pixelstorei.html
new file mode 100644
index 0000000000..161a45271b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-pixelstorei.html
@@ -0,0 +1,96 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL pixelStorei Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="50" height="50"></canvas>
+<canvas id="2d00" width="50" height="50"></canvas>
+<canvas id="2d01" width="50" height="50"></canvas>
+<canvas id="2d02" width="50" height="50"></canvas>
+<canvas id="2d03" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main() {
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+function init() {
+ description("This test checks that drawImage and readPixels are not effected by gl.Pixelstorei(gl.PACK_ALIGNMENT) and visa versa");
+
+ debug("There should be 5 red triangles on 5 black squares above");
+ debug("");
+
+ var wtu = WebGLTestUtils;
+ var canvas3d = document.getElementById("example");
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ 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.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ function checkData(ctx, name) {
+ // Test several locations
+ // First line should be all black
+ wtu.checkCanvasRect(ctx, 0, 0, 50, 1, [0, 0, 0, 0]);
+
+ // Line 25 should be red for at least 6 red pixels starting 22 pixels in
+ wtu.checkCanvasRect(ctx, 22, 25, 6, 1, [255, 0, 0, 255]);
+
+ // Last line should be all black
+ wtu.checkCanvasRect(ctx, 0, 49, 50, 1, [0, 0, 0, 0]);
+ }
+
+ var ctx2d;
+
+ function checkColors() {
+ checkData(gl, "3d context");
+ checkData(ctx2d, "2d context");
+ }
+
+ var table = [1, 2, 4, 8];
+ for (var ii = 0; ii < table.length; ++ii) {
+ gl.pixelStorei(gl.PACK_ALIGNMENT, table[ii]);
+ ctx2d = document.getElementById("2d0" + ii).getContext("2d");
+ ctx2d.globalCompositeOperation = 'copy';
+ ctx2d.drawImage(canvas3d, 0, 0);
+ checkColors();
+ assertMsg(gl.getParameter(gl.PACK_ALIGNMENT) == table[ii],
+ "PACK_ALIGNMENT is " + table[ii]);
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-teximage.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-teximage.html
new file mode 100644
index 0000000000..897377534c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/gl-teximage.html
@@ -0,0 +1,406 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texImage2D conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="16" style="width: 256px; height: 48px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Test texImage2D conversions.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+gl.disable(gl.DITHER);
+var program = wtu.setupTexturedQuad(gl);
+var successfullyParsed;
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var imgURLs = [
+ '../../../resources/1-channel.jpg',
+ '../../../resources/gray-ramp-256-with-128-alpha.png',
+ '../../../resources/gray-ramp-256.png',
+ '../../../resources/gray-ramp-default-gamma.png',
+ '../../../resources/gray-ramp-gamma0.1.png',
+ '../../../resources/gray-ramp-gamma1.0.png',
+ '../../../resources/gray-ramp-gamma2.0.png',
+ '../../../resources/gray-ramp-gamma4.0.png',
+ '../../../resources/gray-ramp-gamma9.0.png',
+ '../../../resources/gray-ramp.png',
+ '../../../resources/zero-alpha.png',
+ '../../../resources/3x3.png',
+ '../../../resources/blue-1x1.jpg',
+ '../../../resources/red-indexed.png',
+ '../../../resources/transparent-on-left-indexed.png',
+ '../../../resources/green-2x2-16bit.png',
+ '../../../resources/small-square-with-colorspin-profile.jpg',
+ '../../../resources/small-square-with-colorspin-profile.png',
+ '../../../resources/small-square-with-cie-rgb-profile.png',
+ '../../../resources/small-square-with-colormatch-profile.png',
+ '../../../resources/small-square-with-e-srgb-profile.png',
+ '../../../resources/small-square-with-smpte-c-profile.png',
+ '../../../resources/small-square-with-srgb-iec61966-2.1-profile.png'];
+
+
+wtu.loadImagesAsync(imgURLs, runTests);
+
+function runTests(imgs) {
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+
+ var width = gl.canvas.width;
+ var height = gl.canvas.height;
+
+ function checkPixel(x, y, color) {
+ wtu.checkCanvasRect(gl, x, y, 1, 1, color);
+ }
+
+ function checkPixelRange(x, y, color, allowedRange) {
+ var msg = "pixel " + x + ", " + y + " should be within " +
+ allowedRange + " units of " +
+ color[0] + ", " +
+ color[1] + ", " +
+ color[2] + ", " +
+ color[3];
+ wtu.checkCanvasRect(gl, x, y, 1, 1, color, msg, allowedRange);
+ }
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ var buf = new Uint8Array(width * height * 4);
+
+ debug("");
+ debug("check pixels are NOT pre-multiplied");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/zero-alpha.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+
+ var left = 0;
+ var middle = Math.floor(width / 2);
+ var right = width - 1;
+ var bottom = 0;
+ var center = Math.floor(height / 2);
+ var top = height - 1;
+ checkPixel(left, top, [ 0, 0, 0, 255]);
+ checkPixel(middle, top, [255, 0, 255, 255]);
+ checkPixel(right, top, [ 0, 0, 255, 255]);
+ checkPixel(left, center, [128, 128, 128, 255]);
+ checkPixel(middle, center, [255, 255, 255, 255]);
+ checkPixel(right, center, [ 0, 255, 255, 255]);
+ checkPixel(left, bottom, [255, 0, 0, 255]);
+ checkPixel(middle, bottom, [255, 255, 0, 255]);
+ checkPixel(right, bottom, [ 0, 255, 0, 255]);
+
+ debug("");
+ debug("check quantization");
+ var quantInfo = [
+ {format: gl.RGBA, type: gl.UNSIGNED_BYTE, counts: [256, 256, 256, 256]},
+ {format: gl.RGBA, type: gl.UNSIGNED_SHORT_4_4_4_4, counts: [ 16, 16, 16, 16]},
+ {format: gl.RGB, type: gl.UNSIGNED_SHORT_5_6_5, counts: [ 32, 64, 32, 1]},
+ {format: gl.RGBA, type: gl.UNSIGNED_SHORT_5_5_5_1, counts: [ 32, 32, 32, 2]}];
+ for (var qq = 0; qq < quantInfo.length; ++qq) {
+ var info = quantInfo[qq];
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, info.format, info.format, info.type,
+ imgs['../../../resources/gray-ramp-256.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+ wtu.clearAndDrawUnitQuad(gl);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var counts = [{ }, { }, { }, { }];
+ var numUniqueValues = [0, 0, 0, 0];
+ // Count the number of unique values in each channel.
+ for (var ii = 0; ii < width * height * 4; ii += 4) {
+ for (var jj = 0; jj < 4; ++jj) {
+ var v = buf[ii + jj];
+ if (!counts[jj][v]) {
+ counts[jj][v] = 1;
+ ++numUniqueValues[jj];
+ } else {
+ ++counts[jj][v];
+ }
+ }
+ }
+ for (var ii = 0; ii < 4; ++ii) {
+ assertMsg(numUniqueValues[ii] == info.counts[ii],
+ "There should be " + info.counts[ii] +
+ " unique values in channel " + ii + ". Found " +
+ numUniqueValues[ii]);
+ }
+ }
+
+ debug("");
+ debug("Check that gamma settings don't effect 8bit pngs");
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/gray-ramp-default-gamma.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+ wtu.clearAndDrawUnitQuad(gl);
+ var ref = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
+
+ var gammaImages = [
+ '../../../resources/gray-ramp-gamma0.1.png',
+ '../../../resources/gray-ramp-gamma1.0.png',
+ '../../../resources/gray-ramp-gamma2.0.png',
+ '../../../resources/gray-ramp-gamma4.0.png',
+ '../../../resources/gray-ramp-gamma9.0.png'];
+ for (var ii = 0; ii < gammaImages.length; ++ii) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs[gammaImages[ii]]);
+ wtu.clearAndDrawUnitQuad(gl);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var same = true;
+ for (var jj = 0; jj < width * height * 4; ++jj) {
+ if (buf[jj] != ref[jj]) {
+ same = false;
+ break;
+ }
+ }
+ assertMsg(same, "pixels should be same regardless of gamma settings.");
+ }
+
+ debug("");
+ debug("check pixels are UN pre-multiplied");
+ for (var ii = 0; ii < 2; ++ii) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ if (ii == 0) {
+ var canvas2d = document.createElement("canvas");
+ canvas2d.width = 256;
+ canvas2d.height = 1;
+ var ctx = canvas2d.getContext("2d");
+ ctx.drawImage(imgs['../../../resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
+ } else {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/gray-ramp-256-with-128-alpha.png']);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+ wtu.clearAndDrawUnitQuad(gl);
+ var buf = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var lt128Count = [0, 0, 0];
+ var ge128Count = [0, 0, 0];
+ for (var jj = 0; jj < width; ++jj) {
+ var off = jj * 4;
+ for (var cc = 0; cc < 3; ++cc) {
+ if (buf[off + cc] < 128) {
+ ++lt128Count[cc];
+ } else {
+ ++ge128Count[cc];
+ }
+ }
+ }
+ // Not sure the exact count here because gamma does effect drawing into the
+ // canvas but it should be close to 50% so I'll pass 45%
+ for (var jj = 0; jj < 3; ++jj) {
+ assertMsg(ge128Count[jj] > 256 * 0.45,
+ "Half the pixels in channel " + jj +
+ " should be >= 128,128,128. found " +
+ ((ge128Count[jj] / 256) * 100).toFixed() + "%");
+ assertMsg(lt128Count[jj] > 256 * 0.45,
+ "Half the pixels in channel " + jj +
+ " should be < 128,128,128. found " +
+ ((lt128Count[jj] / 256) * 100).toFixed() + "%");
+ }
+ }
+
+ debug("");
+ debug("check canvas pixels are UN pre-multiplied");
+ var canvas2d = document.createElement("canvas");
+ canvas2d.width = 1;
+ canvas2d.height = 1;
+ var ctx = canvas2d.getContext("2d");
+ ctx.fillStyle ="rgba(255,255,255,0.5)";
+ ctx.fillRect(0, 0, 256, 1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+ checkPixelRange(0, 0, [255, 255, 255, 127], 4);
+
+ debug("");
+ debug("check canvas pixels are pre-multiplied");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+ checkPixelRange(0, 0, [127, 127, 127, 127], 4);
+
+
+ debug("");
+ debug("check pixels are pre-multiplied");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+ // TODO(gman): use different texture that won't pass on failure
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/zero-alpha.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+ var same = true;
+ for (var jj = 0; jj < width * height * 4; ++jj) {
+ if (buf[jj] != 0) {
+ same = false;
+ break;
+ }
+ }
+ assertMsg(same, "pixels should all be 0.");
+
+ debug("");
+ debug("check pixels are flipped");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/3x3.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+
+ checkPixel(left, top, [255, 0, 0, 255]);
+ checkPixel(middle, top, [255, 255, 0, 255]);
+ checkPixel(right, top, [255, 0, 0, 255]);
+ checkPixel(left, center, [255, 0, 255, 255]);
+ checkPixel(middle, center, [255, 0, 0, 255]);
+ checkPixel(right, center, [ 0, 255, 0, 255]);
+ checkPixel(left, bottom, [ 0, 0, 0, 255]);
+ checkPixel(middle, bottom, [ 0, 0, 255, 255]);
+ checkPixel(right, bottom, [255, 0, 0, 255]);
+
+ debug("");
+ debug("check uploading of images with no alpha channel works");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/blue-1x1.jpg']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ checkPixelRange(middle, center, [ 0, 0, 255, 255], 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ debug("");
+ debug("check uploading of 16-bit images");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/green-2x2-16bit.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ checkPixelRange(middle, center, [ 15, 121, 0, 255], 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ debug("");
+ debug("check uploading of images with ICC profiles");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/small-square-with-colorspin-profile.jpg']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ // The image is red. However, if we ignore the color profile, it is blue.
+ checkPixelRange(middle, center, [ 0, 0, 255, 255], 10);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/small-square-with-colorspin-profile.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ // The image is red. However, if we ignore the color profile, it is blue.
+ checkPixelRange(middle, center, [ 0, 0, 255, 255], 10);
+
+ var iccPNGs = [
+ '../../../resources/small-square-with-cie-rgb-profile.png',
+ '../../../resources/small-square-with-colormatch-profile.png',
+ '../../../resources/small-square-with-e-srgb-profile.png',
+ '../../../resources/small-square-with-smpte-c-profile.png',
+ '../../../resources/small-square-with-srgb-iec61966-2.1-profile.png'];
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ for (var ii = 0; ii < iccPNGs.length; ++ii) {
+ var buf2 = new Uint8Array(width * height * 4);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs[iccPNGs[ii]]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+ var same = true;
+ for (var jj = 0; jj < buf.length; ++jj) {
+ if (buf[jj] != buf2[jj]) {
+ same = false;
+ break;
+ }
+ }
+ assertMsg(same, "uploading PNGs with same data but various ICC profiles should generate the same results");
+ }
+
+ debug("");
+ debug("check uploading of indexed PNG images");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/red-indexed.png']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ // The image should be red.
+ checkPixelRange(middle, center, [ 255, 0, 0, 255 ], 10);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/transparent-on-left-indexed.png']);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, 128, 16, [255, 0, 255, 0], "should be transparent purple");
+ wtu.checkCanvasRect(gl, 128, 0,128, 16, [255, 255, 0, 255], "should be yellow");
+
+ debug("");
+ debug("check uploading of 1-channel JPG images");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+ imgs['../../../resources/1-channel.jpg']);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ // The image should be gray.
+ checkPixelRange(middle, center, [ 128, 128, 128, 255 ], 28);
+
+ debug("")
+ debug("check calling texImage2D with NULL clears the texture");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB,
+ imgs['../../../resources/red-indexed.png'].width,
+ imgs['../../../resources/red-indexed.png'].height,
+ 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+ wtu.clearAndDrawUnitQuad(gl);
+ // The image should be white.
+ checkPixelRange(middle, center, [ 0, 0, 0, 255 ], 10);
+
+ debug("");
+ debug("check zero size cases");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 2, 0, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, new Uint8Array());
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from zero sized textures");
+
+ debug("");
+ successfullyParsed = true;
+ shouldBeTrue("successfullyParsed");
+ debug('<br /><span class="pass">TEST COMPLETE</span>');
+ notifyFinishedToHarness();
+}
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/mipmap-fbo.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/mipmap-fbo.html
new file mode 100644
index 0000000000..1fe851d738
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/mipmap-fbo.html
@@ -0,0 +1,109 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test if mipmap incomplete textures can be used as FBO attachments, and mipmap generation on a texture filled by an FBO works correctly</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example");
+
+function testMipmapGeneration() {
+ // setup render target texture //
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ // setup framebuffer //
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ // fill the framebuffer //
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.viewport(0, 0, 32, 32);
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ // generate mipmap //
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.generateMipmap(gl.TEXTURE_2D);
+
+ var program = wtu.setupTexturedQuad(gl);
+ gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ // readback //
+ wtu.checkCanvas(gl, [255, 0, 255, 255]);
+}
+
+var testCubemapFaceWithIncompleteMipmapInFBO = function() {
+ // Create a cube map texture that's not mipmap complete.
+ var tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex2);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+
+ var cube_map_faces = [
+ 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 i = 0; i < cube_map_faces.length; ++i) {
+ gl.texImage2D(cube_map_faces[i], 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+
+ var fb2 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex2, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors after attaching cube map face.");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+
+ var colorProgram = wtu.setupColorQuad(gl);
+ var colorLocation = gl.getUniformLocation(colorProgram, 'u_color');
+ gl.uniform4f(colorLocation, 0.0, 1.0, 0.0, 1.0);
+ gl.viewport(0, 0, 32, 32);
+ wtu.drawUnitQuad(gl);
+ // Read what's in the framebuffer - note that we need to use checkCanvasRect since the
+ // FB dimensions are different from canvas dimensions.
+ wtu.checkCanvasRect(gl, 0, 0, 32, 32, [0, 255, 0, 255],
+ "Framebuffer with a non-mipmap complete cube map attachment should be green");
+}
+
+testMipmapGeneration();
+debug("");
+testCubemapFaceWithIncompleteMipmapInFBO();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance-offscreencanvas.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance-offscreencanvas.html
new file mode 100644
index 0000000000..208696e98a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance-offscreencanvas.html
@@ -0,0 +1,125 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Origin Restrictions Conformance Tests for OffscreenCanvas</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas"></canvas>
+<img id="img" style="display:none;">
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+// Checks if function throws an exception.
+function causedException(func) {
+ var hadException = false;
+ try {
+ func();
+ } catch(e) {
+ hadException = true;
+ }
+ return hadException;
+}
+
+var defaultImgUrl = "https://get.webgl.org/conformance-resources/opengl_logo.jpg";
+var localImgUrl = "../../../resources/opengl_logo.jpg";
+
+var imgDomain;
+var pageDomain;
+
+function imageLoaded(img) {
+ description("This test ensures WebGL implementations for OffscreenCanvas follow proper same-origin restrictions.");
+
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ return;
+ }
+
+ assertMsg(img.width > 0 && img.height > 0, "img was loaded");
+ imgDomain = wtu.getBaseDomain(wtu.getHost(img.src));
+ pageDomain = wtu.getBaseDomain(window.location.host);
+ assertMsg(imgDomain != pageDomain,
+ "img domain (" + imgDomain + ") and page domain (" + pageDomain + ") are not the same.");
+
+ function makeTexImage2D(gl, src) {
+ return function() {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeTexSubImage2D(gl, src) {
+ return function() {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeReadPixels(gl) {
+ return function() {
+ var buf = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ };
+ }
+
+ var offscreencanvas = new OffscreenCanvas(10, 10);
+ var gl = wtu.create3DContext(offscreencanvas);
+
+ debug("");
+ debug("check that an attempt to upload an image from another origin throws an exception.");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ assertMsg(causedException(makeTexImage2D(gl, img)),
+ "texImage2D with cross-origin image should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, img)),
+ "texSubImage2D with cross-origin image should throw exception.");
+
+ debug("check that readPixels continues to work against this offscreencanvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+
+ debug("check that an attempt to upload a tainted canvas throws an exception.");
+ var canvas = document.getElementById("canvas");
+ var ctx2d = canvas.getContext("2d");
+ ctx2d.drawImage(img, 0, 0);
+ assertMsg(causedException(makeTexImage2D(gl, canvas)),
+ "texImage2D with NON origin clean canvas should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, canvas)),
+ "texSubImage2D with NON origin clean canvas should throw exception.");
+
+ debug("check that readPixels continues to work against this offscreencanvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+
+ // TODO: Should check video.
+ // TODO: Should check CORS support.
+
+ finishTest();
+}
+
+(async function() {
+ const img = document.getElementById('img');
+ try {
+ await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
+ } catch (e) {
+ testFailed(`Image setup failed (${e}).`);
+ finishTest();
+ return;
+ }
+ imageLoaded(img);
+})();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance.html
new file mode 100644
index 0000000000..fb7f572173
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/origin-clean-conformance.html
@@ -0,0 +1,137 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Origin Restrictions Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas1"></canvas>
+<canvas id="canvas2"></canvas>
+<img id="img" style="display:none;">
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+// Checks if function throws an exception.
+function causedException(func) {
+ var hadException = false;
+ try {
+ func();
+ } catch(e) {
+ hadException = true;
+ }
+ return hadException;
+}
+
+var defaultImgUrl = "https://get.webgl.org/conformance-resources/opengl_logo.jpg";
+var localImgUrl = "../../../resources/opengl_logo.jpg";
+
+var imgDomain;
+var pageDomain;
+var successfullyParsed;
+
+function imageLoaded(img) {
+ description("This test ensures WebGL implementations follow proper same-origin restrictions.");
+
+ assertMsg(img.width > 0 && img.height > 0, "img was loaded");
+ imgDomain = wtu.getBaseDomain(wtu.getHost(img.src));
+ pageDomain = wtu.getBaseDomain(window.location.host);
+ assertMsg(imgDomain != pageDomain,
+ "img domain (" + imgDomain + ") and page domain (" + pageDomain + ") are not the same.");
+
+ function makeTexImage2D(gl, src) {
+ return function() {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeTexSubImage2D(gl, src) {
+ return function() {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeReadPixels(gl) {
+ return function() {
+ var buf = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ };
+ }
+
+ function makeToDataURL(canvas) {
+ return function() {
+ var data = canvas.toDataURL();
+ }
+ }
+
+ var canvas1 = document.getElementById("canvas1");
+ var gl = wtu.create3DContext(canvas1);
+
+ debug("");
+ debug("check that an attempt to upload an image from another origin throws an exception.");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ assertMsg(causedException(makeTexImage2D(gl, img)),
+ "texImage2D with cross-origin image should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, img)),
+ "texSubImage2D with cross-origin image should throw exception.");
+
+ debug("check that readPixels and toDataURL continue to work against this canvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+ assertMsg(!causedException(makeToDataURL(canvas1)),
+ "should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.");
+
+ debug("check that an attempt to upload a tainted canvas throws an exception.");
+ var canvas2 = document.getElementById("canvas2");
+ var ctx2d = canvas2.getContext("2d");
+ ctx2d.drawImage(img, 0, 0);
+ assertMsg(causedException(makeToDataURL(canvas2)),
+ "should throw exception by toDataURL for NON origin clean canvas.");
+ assertMsg(causedException(makeTexImage2D(gl, canvas2)),
+ "texImage2D with NON origin clean canvas should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, canvas2)),
+ "texSubImage2D with NON origin clean canvas should throw exception.");
+
+ debug("check that readPixels and toDataURL continue to work against this canvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+ assertMsg(!causedException(makeToDataURL(canvas1)),
+ "should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.");
+
+ // TODO: Should check video.
+ // TODO: Should check CORS support.
+
+ debug("");
+ successfullyParsed = true;
+ shouldBeTrue("successfullyParsed");
+ debug('<br /><span class="pass">TEST COMPLETE</span>');
+ notifyFinishedToHarness();
+}
+
+(async function() {
+ const img = document.getElementById('img');
+ try {
+ await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
+ } catch (e) {
+ testFailed(`Image setup failed (${e}).`);
+ finishTest();
+ return;
+ }
+ imageLoaded(img);
+})();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/png-image-types.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/png-image-types.html
new file mode 100644
index 0000000000..4eb98b1405
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/png-image-types.html
@@ -0,0 +1,164 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="../../../resources/js-test-style.css" />
+ <script src="../../../js/js-test-pre.js"></script>
+ <script src="../../../js/webgl-test-utils.js"></script>
+</head>
+
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script>
+"use strict";
+description("This test verifies correct channel mapping of different PNG image types.");
+
+const testData = {
+ "Grayscale": {
+ src: [
+ // [0x40]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NwAAAAQgBBg7nsrQAAAABJRU5ErkJggg==",
+ // [0x4040]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAAAAABq7kcWAAAAC0lEQVQI12NwcAAAAMMAgUenLEIAAAAASUVORK5CYII="
+ ],
+ expectations: [
+ { color: [0x00, 0x00, 0x00, 0xFF], format: "ALPHA" },
+ { color: [0x40, 0x40, 0x40, 0xFF], format: "RGB" },
+ { color: [0x40, 0x40, 0x40, 0xFF], format: "RGBA" },
+ { color: [0x40, 0x40, 0x40, 0xFF], format: "LUMINANCE" },
+ { color: [0x40, 0x40, 0x40, 0xFF], format: "LUMINANCE_ALPHA" },
+ { color: [0x40, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
+ { color: [0x40, 0x40, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
+ ]
+ },
+ "Grayscale Alpha": {
+ src: [
+ // [0x40, 0x80]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQI12NwaAAAAQMAwUxZTl4AAAAASUVORK5CYII=",
+ // [0x4040, 0x8080]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAQAAADljNBBAAAADUlEQVQI12NwcGhoAAADRQGBoxssPgAAAABJRU5ErkJggg=="
+ ],
+ expectations: [
+ { color: [0x00, 0x00, 0x00, 0x80], format: "ALPHA" },
+ { color: [0x40, 0x40, 0x40, 0xFF], format: "RGB" },
+ { color: [0x40, 0x40, 0x40, 0x80], format: "RGBA" },
+ { color: [0x40, 0x40, 0x40, 0xFF], format: "LUMINANCE" },
+ { color: [0x40, 0x40, 0x40, 0x80], format: "LUMINANCE_ALPHA" },
+ { color: [0x40, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
+ { color: [0x40, 0x40, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
+ ]
+ },
+ "Color": {
+ src: [
+ // [0xBF, 0x7F, 0xFF]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12PYX/8fAAQ+Aj5BqwprAAAAAElFTkSuQmCC",
+ // [0xBFBF, 0x7F7F, 0xFFFF]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAIAAADA54+dAAAAD0lEQVQI12PYv7++/v9/AA6yBHvtbgBNAAAAAElFTkSuQmCC"
+ ],
+ expectations: [
+ { color: [0x00, 0x00, 0x00, 0xFF], format: "ALPHA" },
+ { color: [0xBF, 0x7F, 0xFF, 0xFF], format: "RGB" },
+ { color: [0xBF, 0x7F, 0xFF, 0xFF], format: "RGBA" },
+ { color: [0xBF, 0xBF, 0xBF, 0xFF], format: "LUMINANCE" },
+ { color: [0xBF, 0xBF, 0xBF, 0xFF], format: "LUMINANCE_ALPHA" },
+ { color: [0xBF, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
+ { color: [0xBF, 0x7F, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
+ ]
+
+ },
+ "Color Alpha": {
+ src: [
+ // [0xBF, 0x7F, 0xFF, 0x40]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQI12PYX//fAQAGvAJ+xPMwKQAAAABJRU5ErkJggg==",
+ // [0xBFBF, 0x7F7F, 0xFFFF, 0x4040]
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAYAAABPhRjKAAAAEUlEQVQI12PYv7++/v9/BwcAGGgE+8YN4XUAAAAASUVORK5CYII="
+ ],
+ expectations: [
+ { color: [0x00, 0x00, 0x00, 0x40], format: "ALPHA" },
+ { color: [0xBF, 0x7F, 0xFF, 0xFF], format: "RGB" },
+ { color: [0xBF, 0x7F, 0xFF, 0x40], format: "RGBA" },
+ { color: [0xBF, 0xBF, 0xBF, 0xFF], format: "LUMINANCE" },
+ { color: [0xBF, 0xBF, 0xBF, 0x40], format: "LUMINANCE_ALPHA" },
+ { color: [0xBF, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
+ { color: [0xBF, 0x7F, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
+ ]
+ }
+};
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext();
+
+wtu.setupTexturedQuad(gl);
+gl.bindTexture(gl.TEXTURE_2D, gl.createTexture());
+
+(async () => {
+ for (const [type, testCase] of Object.entries(testData)) {
+ if (testCase.src.length != 2) throw new Error('testCase.src.length != 2');
+ let images = testCase.src.map(src => loadImage(src));
+ images = await Promise.all(images);
+ debug("");
+ debug("");
+ debug(`PNG image type ${type} with RGBA values of ${testCase.expectations[2].color}`);
+ let formats = testCase.expectations;
+ if (!wtu.isWebGL2(gl)) {
+ formats = formats.filter((f) => !f.internalformat);
+ }
+ for (const f of formats) {
+ debug("");
+ debug(`GL format: ${f.format}`);
+
+ function check(data, description) {
+ debug(`Upload ${description}`);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl[f.internalformat || f.format],
+ gl[f.format],
+ gl.UNSIGNED_BYTE,
+ data
+ );
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, f.color, undefined, 1);
+ }
+
+ check(images[0].image, "8-bit PNG from Image");
+ check(images[1].image, "16-bit PNG from Image");
+
+ if (images[0].bitmap) {
+ check(images[0].bitmap, "8-bit PNG from ImageBitmap");
+ check(images[1].bitmap, "16-bit PNG from ImageBitmap");
+ }
+ }
+ }
+ finishTest();
+})();
+
+async function loadImage(src) {
+ const img = new Image();
+ img.src = src;
+ await img.decode();
+ const ret = { image: img };
+ if (self.createImageBitmap) {
+ try {
+ ret.bitmap = await createImageBitmap(img, {
+ premultiplyAlpha: "none",
+ });
+ } catch {}
+ }
+ return ret;
+}
+
+var successfullyParsed = true;
+ </script>
+</body>
+
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html
new file mode 100644
index 0000000000..34c94a68a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html
@@ -0,0 +1,304 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verifies texImage2D and texSubImage2D code paths taking ArrayBufferView');
+
+var wtu = WebGLTestUtils;
+
+function roundUpToAlignment(value, alignment) {
+ return Math.floor((value + alignment - 1) / alignment) * alignment;
+}
+
+function generateRGBAData(type, unpackAlignment, sourceData, width, height)
+{
+ var numColors = sourceData.length / 4;
+ var colorOffset = function(y) {
+ return 4 * Math.floor(y * numColors / height);
+ };
+
+ switch (type) {
+ case gl.UNSIGNED_BYTE: {
+ var rowWidth = roundUpToAlignment(width * 4, unpackAlignment);
+ var data = new Uint8Array(height * rowWidth);
+ for (var y = 0; y < height; ++y) {
+ var index = y * rowWidth;
+ var offset = colorOffset(y);
+ for (var element = 0; element < width * 4; ++element) {
+ data[index + element] = sourceData[offset + element % 4];
+ }
+ }
+ return data;
+ }
+ case gl.UNSIGNED_SHORT_4_4_4_4: {
+ var rowWidth = roundUpToAlignment(width * 2, unpackAlignment) / 2;
+ var data = new Uint16Array(height * rowWidth);
+ for (var y = 0; y < height; ++y) {
+ var offset = colorOffset(y);
+ for (var x = 0; x < width; ++x) {
+ var index = y * rowWidth + x;
+ data[index] = (((sourceData[offset + 0] & 0xF0) << 8)
+ | ((sourceData[offset + 1] & 0xF0) << 4)
+ | ((sourceData[offset + 2] & 0xF0) >> 0)
+ | ((sourceData[offset + 3] & 0xF0) >> 4));
+ }
+ }
+ return data;
+ }
+ case gl.UNSIGNED_SHORT_5_5_5_1: {
+ var rowWidth = roundUpToAlignment(width * 2, unpackAlignment) / 2;
+ var data = new Uint16Array(height * rowWidth);
+ for (var y = 0; y < height; ++y) {
+ var offset = colorOffset(y);
+ for (var x = 0; x < width; ++x) {
+ var index = y * rowWidth + x;
+ data[index] = (((sourceData[offset + 0] & 0xF8) << 8)
+ | ((sourceData[offset + 1] & 0xF8) << 3)
+ | ((sourceData[offset + 2] & 0xF8) >> 2)
+ | ((sourceData[offset + 3] & 0x80) >> 7));
+ }
+ }
+ return data;
+ }
+ }
+}
+
+function typeToString(type)
+{
+ switch (type) {
+ case gl.UNSIGNED_BYTE: return 'UNSIGNED_BYTE';
+ case gl.UNSIGNED_SHORT_5_5_5_1: return 'UNSIGNED_SHORT_5_5_5_1';
+ case gl.UNSIGNED_SHORT_4_4_4_4: return 'UNSIGNED_SHORT_4_4_4_4';
+ }
+ return 'Unknown type ' + type;
+}
+
+function runOneIteration(useTexSubImage2D, type, unpackAlignment, flipY, premultiplyAlpha,
+ topColor, bottomColor, extraColor, bindingTarget, program)
+{
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with type=' + typeToString(type) +
+ ', unpackAlignment=' + unpackAlignment +
+ ', flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP'));
+ gl.colorMask(true, true, true, true);
+ gl.clearColor(0, 0, 0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Enable writes to the RGB channels
+ gl.colorMask(true, true, true, false);
+ 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_ALIGNMENT, unpackAlignment);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
+ // Generate the data
+ var sourceData = [ 255, 0, 0, 255,
+ 0, 255, 0, 0 ];
+ var texWidth = 5; // this must be mod 4 + 1 to test unpackAlignment
+ // cube map texture must be square.
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP)
+ texWidth = 16;
+ var texHeight = 16;
+ var data = generateRGBAData(type, unpackAlignment, sourceData, texWidth, texHeight);
+ if (gl.getError() != gl.NO_ERROR)
+ testFailed("GL error before texture upload");
+ 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.RGBA, texWidth, texHeight, 0,
+ gl.RGBA, type, null);
+ if (gl.getError() != gl.NO_ERROR)
+ testFailed("GL error after texImage2D(null)");
+ gl.texSubImage2D(targets[tt], 0, 0, 0, texWidth, texHeight, gl.RGBA, type, data);
+ if (gl.getError() != gl.NO_ERROR)
+ testFailed("GL error after texSubImage2D");
+ } else {
+ gl.texImage2D(targets[tt], 0, gl.RGBA, texWidth, texHeight, 0, gl.RGBA, type, data);
+ if (gl.getError() != gl.NO_ERROR)
+ testFailed("GL error after texImage2D");
+ }
+ }
+
+ var testWidth = gl.drawingBufferWidth;
+ var testHeight = gl.drawingBufferHeight / 2;
+
+ 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 the top pixel and bottom pixel and make sure they have
+ // the right color.
+ var rects = [wtu.makeCheckRect(0, 0, testWidth, testHeight, bottomColor, "bottom pixel should be " + bottomColor, 0),
+ wtu.makeCheckRect(0, testHeight, testWidth, testHeight, topColor, "top pixel should be " + topColor, 0)];
+ wtu.checkCanvasRects(gl, rects);
+ }
+
+ // Change part of the texture.
+ var partWidth = 16;
+ var partHeight = 16;
+ // make texture double res of part.
+ var data = generateRGBAData(type, unpackAlignment, sourceData, partWidth * 2, partHeight * 2);
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.texImage2D(targets[tt], 0, gl.RGBA, partWidth * 2, partHeight * 2, 0, gl.RGBA, type, data);
+ }
+ // set part.
+ var extraData = [
+ 255, 0, 0, 255,
+ 0, 0, 255, 0
+ ];
+ var data = generateRGBAData(type, unpackAlignment, extraData, partWidth, partHeight);
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.texSubImage2D(targets[tt], 0, 0, 0, partWidth, partHeight, gl.RGBA, type, data);
+ }
+ var halfWidth = gl.drawingBufferWidth / 2;
+ var halfHeight = gl.drawingBufferHeight / 2;
+ var quarterHeight = gl.drawingBufferHeight / 4;
+ var red = [255, 0, 0, 255];
+ var tcolor0 = flipY ? extraColor : red;
+ var tcolor1 = flipY ? red : extraColor;
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ var rects = [wtu.makeCheckRect(0, 0, halfWidth, quarterHeight, tcolor0, "bottom left bottom pixels should be " + tcolor0, 0),
+ wtu.makeCheckRect(0, quarterHeight, halfWidth, quarterHeight, tcolor1, "bottom left top pixels should be " + tcolor1, 0),
+ wtu.makeCheckRect(halfWidth, 0, halfWidth, halfHeight, bottomColor, "bottom right pixels should be " + bottomColor, 0),
+ wtu.makeCheckRect(0, halfHeight, testWidth, halfHeight, topColor, "top pixels should be " + topColor, 0)];
+ wtu.checkCanvasRects(gl, rects);
+ }
+
+ // set far corner.
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.texSubImage2D(targets[tt], 0, partWidth, partHeight, partWidth, partHeight, gl.RGBA, type, data);
+ }
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ var rects = [wtu.makeCheckRect(0, 0, halfWidth, quarterHeight, tcolor0, "bottom left bottom pixels should be " + tcolor0, 0),
+ wtu.makeCheckRect(0, quarterHeight, halfWidth, quarterHeight, tcolor1, "bottom left top pixels should be " + tcolor1, 0),
+ wtu.makeCheckRect(halfWidth, 0, halfWidth, halfHeight, bottomColor, "bottom left pixels should be " + bottomColor, 0),
+ wtu.makeCheckRect(0, halfHeight, halfWidth, halfHeight, topColor, "top right pixels should be " + topColor, 0),
+ wtu.makeCheckRect(halfWidth, halfHeight, halfWidth, quarterHeight, tcolor0, "top right bottom pixels should be " + tcolor0, 0),
+ wtu.makeCheckRect(halfWidth, halfHeight + quarterHeight, halfWidth, quarterHeight, tcolor1, "top right top pixels should be " + tcolor1, 0)];
+ wtu.checkCanvasRects(gl, rects);
+ }
+}
+
+function runTest(bindingTarget, program)
+{
+ var red = [255, 0, 0, 255];
+ var green = [0, 255, 0, 255];
+ var blue = [0, 0, 255, 255];
+ var redPremultiplyAlpha = [255, 0, 0, 255];
+ var greenPremultiplyAlpha = [0, 0, 0, 255];
+ var bluePremultiplyAlpha = [0, 0, 0, 255];
+
+ var types = [ gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_5_5_1, gl.UNSIGNED_SHORT_4_4_4_4 ];
+ var unpackAlignments = [ 1, 2, 4, 8 ];
+
+ var cases = [
+ { sub: false, flipY: true, premultiplyAlpha: false, topColor: red, bottomColor: green, extraColor: blue },
+ { sub: false, flipY: false, premultiplyAlpha: false, topColor: green, bottomColor: red, extraColor: blue },
+ { sub: false, flipY: true, premultiplyAlpha: true, topColor: redPremultiplyAlpha, bottomColor: greenPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
+ { sub: false, flipY: false, premultiplyAlpha: true, topColor: greenPremultiplyAlpha, bottomColor: redPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
+ { sub: true, flipY: true, premultiplyAlpha: false, topColor: red, bottomColor: green, extraColor: blue },
+ { sub: true, flipY: false, premultiplyAlpha: false, topColor: green, bottomColor: red, extraColor: blue },
+ { sub: true, flipY: true, premultiplyAlpha: true, topColor: redPremultiplyAlpha, bottomColor: greenPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
+ { sub: true, flipY: false, premultiplyAlpha: true, topColor: greenPremultiplyAlpha, bottomColor: redPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
+ ];
+
+ for (var i in types) {
+ for (var j in unpackAlignments) {
+ for (var k in cases) {
+ runOneIteration(cases[k].sub, types[i], unpackAlignments[j], cases[k].flipY, cases[k].premultiplyAlpha,
+ cases[k].topColor, cases[k].bottomColor, cases[k].extraColor, bindingTarget, program);
+ }
+ }
+ }
+}
+
+var gl = wtu.create3DContext("example");
+
+var program = wtu.setupTexturedQuad(gl);
+runTest(gl.TEXTURE_2D, program);
+program = wtu.setupTexturedQuadWithCubeMap(gl);
+runTest(gl.TEXTURE_CUBE_MAP, program);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+const tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+const validDatas = [
+ `new Uint8Array(4)`,
+ `new Uint8Array(new ArrayBuffer(4))`,
+ `new Uint8ClampedArray(4)`,
+ `new Uint8ClampedArray(new ArrayBuffer(4))`,
+];
+if (window.SharedArrayBuffer) {
+ validDatas.push(
+ `new Uint8Array(new SharedArrayBuffer(4))`,
+ `new Uint8ClampedArray(new SharedArrayBuffer(4))`
+ );
+}
+for (const x of validDatas) {
+ shouldNotThrow(`gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1, 0, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ shouldNotThrow(`gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-uniform-binding-bugs.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-uniform-binding-bugs.html
new file mode 100644
index 0000000000..292f94a8b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-and-uniform-binding-bugs.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+description('Tests passing a vec4 to a uniform and a canvas to texImage2D');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var floatProgram = wtu.loadProgramFromFile(gl, "../../../resources/floatUniformShader.vert", "../../../resources/noopUniformShader.frag");
+shouldBeUndefined("gl.useProgram(floatProgram)");
+var fval4Loc = gl.getUniformLocation(floatProgram, "fval4");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined("gl.uniform4fv(fval4Loc, new Float32Array([0.1, 0.2, 0.4, 1.0]));");
+
+var tmpcanvas = document.createElement("canvas");
+tmpcanvas.width = 2;
+tmpcanvas.height = 2;
+var texture = gl.createTexture();
+shouldBeUndefined("gl.bindTexture(gl.TEXTURE_2D, texture)");
+shouldBeUndefined("gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tmpcanvas)");
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-canvas-corruption.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-canvas-corruption.html
new file mode 100644
index 0000000000..4277917644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-canvas-corruption.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Testing 3D canvas is usable after being used as texImage2D source</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="512" height="512"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+// Regression test for http://crbug.com/368582
+description();
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var ctx = canvas.getContext("2d");
+
+var gl = wtu.create3DContext();
+var texture = gl.createTexture();
+
+var image = wtu.makeImage('../../../resources/blue-1x1.jpg', function() {
+ renderToCanvas();
+ renderToCanvas();
+ wtu.checkCanvas(ctx, [0, 0, 255, 255], "All pixels should be blue", 2);
+ finishTest();
+});
+
+function renderToCanvas() {
+ // Clear the 2d canvas then draw the image to it (a blue pixel)
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
+
+ // Upload the results to a WebGL texture
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-webgl.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-webgl.html
new file mode 100644
index 0000000000..653f8d9820
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-webgl.html
@@ -0,0 +1,78 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texImage2D from WebGL conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="16" style="width: 256px; height: 48px;"></canvas>
+<canvas id="source" width="256" height="16" style="width: 256px; height: 48px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test texImage2D from a webgl canvas.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+gl.disable(gl.DITHER);
+var program = wtu.setupTexturedQuad(gl);
+var gl1 = wtu.create3DContext("source");
+gl1.disable(gl.DITHER);
+gl1.disable(gl.BLEND);
+gl1.disable(gl.DEPTH_TEST);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.glErrorShouldBe(gl1, gl1.NO_ERROR, "Should be no errors from setup.");
+
+gl.disable(gl.BLEND);
+gl.disable(gl.DEPTH_TEST);
+
+gl1.clearColor(1.0, 0.0, 0.0, 1.0);
+gl1.clear(gl1.COLOR_BUFFER_BIT);
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, gl1.canvas);
+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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+wtu.clearAndDrawUnitQuad(gl);
+
+wtu.checkCanvas(gl, [255, 0, 0, 255], "Canvas should be red");
+
+gl1.clearColor(0.0, 1.0, 0.0, 1.0);
+gl1.clear(gl1.COLOR_BUFFER_BIT);
+
+var program1 = wtu.setupTexturedQuad(gl1);
+var tex1 = gl1.createTexture();
+gl1.bindTexture(gl.TEXTURE_2D, tex1);
+gl1.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255]));
+
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, gl1.canvas);
+wtu.clearAndDrawUnitQuad(gl);
+
+wtu.checkCanvas(gl, [0, 255, 0, 255], "Canvas should be green");
+
+// Test a scenario from Chrome where a WebGL context would lose its active texture binding when its
+// canvas was used as the texture source for another WebGL context.
+wtu.clearAndDrawUnitQuad(gl1);
+
+wtu.checkCanvas(gl1, [0, 0, 255, 255], "Canvas should be blue");
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-format-and-type.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-format-and-type.html
new file mode 100644
index 0000000000..1fbf4c6ccb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-format-and-type.html
@@ -0,0 +1,722 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/pnglib.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = null;
+var textureLoc = null;
+var successfullyParsed = false;
+
+//----------------------------------------------------------------------
+// Harness
+
+var testCases = [];
+
+var DataMode = {
+ IMAGE: 0,
+ IMAGE_DATA: 1,
+
+ NUM_HTML_MODES: 2,
+
+ RAW_DATA: 2,
+
+ // This must remain the last mode.
+ NUM_MODES: 3
+};
+
+function init()
+{
+ description('Verify texImage2D and texSubImage2D code paths taking both HTML and user-specified data with all format/type combinations');
+
+ var canvas = document.getElementById("example");
+ gl = wtu.create3DContext(canvas);
+ gl.disable(gl.DITHER);
+ var program = wtu.setupTexturedQuad(gl);
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ textureLoc = gl.getUniformLocation(program, "tex");
+
+ initializeTests();
+}
+
+function initializeTests()
+{
+ // Verify that uploading to packed pixel formats performs the
+ // required conversion and associated loss of precision.
+ for (var dataMode = 0; dataMode < DataMode.NUM_HTML_MODES; ++dataMode) {
+ for (var useTexSubImage2D = 0; useTexSubImage2D < 2; ++useTexSubImage2D) {
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ verifier: allChannelsIncreaseByNoMoreThan,
+ threshold: 1,
+ numOccurrences: 1,
+ description: "RGBA/UNSIGNED_BYTE should maintain full precision of data"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_SHORT_4_4_4_4,
+ verifier: allChannelsIncreaseByAtLeast,
+ threshold: 15,
+ numOccurrences: 10,
+ description: "RGBA/UNSIGNED_SHORT_4_4_4_4 must drop low four bits of precision"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_SHORT_5_5_5_1,
+ verifier: allChannelsIncreaseByAtLeast,
+ threshold: 7,
+ numOccurrences: 20,
+ description: "RGBA/UNSIGNED_SHORT_5_5_5_1 must drop low three bits of precision"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ verifier: allChannelsIncreaseByNoMoreThan,
+ threshold: 1,
+ numOccurrences: 1,
+ description: "RGB/UNSIGNED_BYTE should maintain full precision of data"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.RGB,
+ type: gl.UNSIGNED_SHORT_5_6_5,
+ verifier: allChannelsIncreaseByAtLeast,
+ threshold: 3,
+ numOccurrences: 20,
+ description: "RGB/UNSIGNED_SHORT_5_6_5 must drop low two or three bits of precision"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTranslucentGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ verifier: alphaChannelIncreasesByNoMoreThan,
+ threshold: 1,
+ numOccurrences: 1,
+ description: "ALPHA/UNSIGNED_BYTE should maintain full precision of data"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.LUMINANCE,
+ type: gl.UNSIGNED_BYTE,
+ verifier: allChannelsIncreaseByNoMoreThan,
+ threshold: 1,
+ numOccurrences: 1,
+ description: "LUMINANCE/UNSIGNED_BYTE should maintain full precision of data"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateOpaqueGrayscaleRamp,
+ premultiplyAlpha: false,
+ format: gl.LUMINANCE_ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ verifier: allChannelsIncreaseByNoMoreThan,
+ threshold: 1,
+ numOccurrences: 1,
+ description: "LUMINANCE_ALPHA/UNSIGNED_BYTE should maintain full precision of data"
+ });
+ }
+ }
+
+ // Verify that setting the UNPACK_PREMULTIPLY_ALPHA_WEBGL pixel
+ // store parameter and sending down a zero alpha causes the color
+ // channels to go to zero.
+ for (var dataMode = 0; dataMode < DataMode.NUM_MODES; ++dataMode) {
+ for (var useTexSubImage2D = 0; useTexSubImage2D < 2; ++useTexSubImage2D) {
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_BYTE"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_SHORT_4_4_4_4,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_SHORT_4_4_4_4"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_SHORT_5_5_5_1,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_SHORT_5_5_5_1"
+ });
+ // The following few tests are invalid for the raw data
+ // mode because there is either no alpha channel or no
+ // separate alpha channel.
+ if (dataMode != DataMode.RAW_DATA) {
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGB/UNSIGNED_BYTE"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.RGB,
+ type: gl.UNSIGNED_SHORT_5_6_5,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGB/UNSIGNED_SHORT_5_6_5"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with ALPHA/UNSIGNED_BYTE"
+ });
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.LUMINANCE,
+ type: gl.UNSIGNED_BYTE,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with LUMINANCE/UNSIGNED_BYTE"
+ });
+ }
+ testCases.push({
+ dataMode: dataMode,
+ useTexSubImage2D: !!useTexSubImage2D,
+ width: 256,
+ height: 1,
+ generator: generateTransparentGrayscaleRamp,
+ premultiplyAlpha: true,
+ format: gl.LUMINANCE_ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ verifier: colorChannelsAreZero,
+ description: "UNPACK_PREMULTIPLY_ALPHA_WEBGL with LUMINANCE_ALPHA/UNSIGNED_BYTE"
+ });
+ }
+ }
+
+ // Produce data for all testcases. Because we load images, some of
+ // these may generate their data asynchronously.
+ generateTestData();
+}
+
+function generateTestData()
+{
+ for (var i = 0; i < testCases.length; i++) {
+ var testCase = testCases[i];
+ var wrapper = null;
+ switch (testCase.dataMode) {
+ case DataMode.IMAGE:
+ wrapper = new ImageWrapper(testCase.width, testCase.height);
+ break;
+ case DataMode.IMAGE_DATA:
+ wrapper = new ImageDataWrapper(testCase.width, testCase.height);
+ break;
+ case DataMode.RAW_DATA:
+ switch (testCase.type) {
+ case gl.UNSIGNED_BYTE:
+ switch (testCase.format) {
+ case gl.RGBA:
+ wrapper = new RGBA8DataWrapper(testCase.width, testCase.height);
+ break;
+ case gl.RGB:
+ wrapper = new RGB8DataWrapper(testCase.width, testCase.height);
+ break;
+ case gl.ALPHA:
+ wrapper = new A8DataWrapper(testCase.width, testCase.height);
+ break;
+ case gl.LUMINANCE:
+ wrapper = new L8DataWrapper(testCase.width, testCase.height);
+ break;
+ case gl.LUMINANCE_ALPHA:
+ wrapper = new LA8DataWrapper(testCase.width, testCase.height);
+ break;
+ }
+ break;
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ wrapper = new RGBA4444DataWrapper(testCase.width, testCase.height);
+ break;
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ wrapper = new RGBA5551DataWrapper(testCase.width, testCase.height);
+ break;
+ case gl.UNSIGNED_SHORT_5_6_5:
+ wrapper = new RGB565DataWrapper(testCase.width, testCase.height);
+ break;
+ }
+ }
+ testCase.wrapper = wrapper;
+ testCase.generator(wrapper);
+ testCase.wrapper.generateData();
+ }
+
+ // See whether we need to run the tests, in case all of them
+ // generated their results synchronously.
+ maybeRunTests();
+}
+
+var ranTests = false;
+
+function maybeRunTests()
+{
+ if (!ranTests)
+ for (var i = 0; i < testCases.length; ++i)
+ if (!testCases[i].wrapper || !testCases[i].wrapper.data)
+ return;
+
+ ranTests = true;
+
+ for (var i = 0; i < testCases.length; ++i)
+ runOneTest(testCases[i]);
+
+ finishTest();
+}
+
+function testCaseToString(testCase)
+{
+ var mode;
+ switch (testCase.dataMode) {
+ case DataMode.IMAGE:
+ mode = "Image";
+ break;
+ case DataMode.IMAGE_DATA:
+ mode = "ImageData";
+ break;
+ case DataMode.RAW_DATA:
+ mode = "raw data";
+ break;
+ }
+ return (testCase.useTexSubImage2D ? "texSubImage2D" : "texImage2D") +
+ " with " + mode + " at " + testCase.width + "x" + testCase.height;
+}
+
+function runOneTest(testCase)
+{
+ debug("Testing " + testCaseToString(testCase));
+ var data = testCase.wrapper.data;
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0.
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ // Set up texture parameters.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // Set up pixel store parameters.
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, testCase.premultiplyAlpha);
+ // Upload the image into the texture.
+ if (testCase.useTexSubImage2D) {
+ // Initialize the texture to black first.
+ gl.texImage2D(gl.TEXTURE_2D, 0, testCase.format, testCase.width, testCase.height, 0,
+ testCase.format, testCase.type, null);
+ }
+ switch (testCase.dataMode) {
+ case DataMode.IMAGE:
+ case DataMode.IMAGE_DATA:
+ if (testCase.useTexSubImage2D)
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, testCase.format, testCase.type, data);
+ else
+ gl.texImage2D(gl.TEXTURE_2D, 0, testCase.format, testCase.format, testCase.type, data);
+ break;
+ case DataMode.RAW_DATA:
+ if (testCase.useTexSubImage2D)
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, testCase.width, testCase.height, testCase.format, testCase.type, data);
+ else
+ gl.texImage2D(gl.TEXTURE_2D, 0, testCase.format, testCase.width, testCase.height, 0, testCase.format, testCase.type, data);
+ break;
+ }
+ // Point the uniform sampler to texture unit 0.
+ gl.uniform1i(textureLoc, 0);
+ // Draw the triangles.
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ // Clean up the texture.
+ gl.deleteTexture(texture);
+
+ // Read back the rendering results.
+ var buf = new Uint8Array(testCase.width * testCase.height * 4);
+ gl.readPixels(0, 0, testCase.width, testCase.height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ // Run the verification routine.
+ if (testCase.verifier(buf, testCase.threshold, testCase.numOccurrences))
+ testPassed(testCase.description);
+ else
+ testFailed(testCase.description);
+}
+
+//----------------------------------------------------------------------
+// Wrappers for programmatic construction of Image, ImageData and raw texture data
+//
+
+function ImageWrapper(width, height)
+{
+ this.pngBuilder_ = new PNGlib(width, height, 256);
+}
+
+ImageWrapper.prototype.getWidth = function() {
+ return this.pngBuilder_.width;
+};
+
+ImageWrapper.prototype.getHeight = function() {
+ return this.pngBuilder_.height;
+};
+
+ImageWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ this.pngBuilder_.buffer[this.pngBuilder_.index(x, y)] = this.pngBuilder_.color(r, g, b, a);
+};
+
+// Generates data into "data" property, possibly asynchronously.
+ImageWrapper.prototype.generateData = function() {
+ var that = this;
+ var url = "data:image/png;base64," + this.pngBuilder_.getBase64();
+ var img = wtu.makeImage(url, function() {
+ that.data = img;
+ maybeRunTests();
+ });
+};
+
+function ImageDataWrapper(width, height)
+{
+ if (!ImageDataWrapper.tempCanvas) {
+ ImageDataWrapper.tempCanvas = document.createElement("canvas");
+ }
+ this.imageData_ = ImageDataWrapper.tempCanvas.getContext("2d").createImageData(width, height);
+}
+
+ImageDataWrapper.tempCanvas = null;
+
+ImageDataWrapper.prototype.getWidth = function() {
+ return this.imageData_.width;
+};
+
+ImageDataWrapper.prototype.getHeight = function() {
+ return this.imageData_.height;
+};
+
+ImageDataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var index = 4 * (this.imageData_.width * y + x);
+ this.imageData_.data[index] = r;
+ this.imageData_.data[index + 1] = g;
+ this.imageData_.data[index + 2] = b;
+ this.imageData_.data[index + 3] = a;
+};
+
+ImageDataWrapper.prototype.generateData = function() {
+ this.data = this.imageData_;
+ maybeRunTests();
+};
+
+function TextureDataWrapper(width, height)
+{
+ this.width_ = width;
+ this.height_ = height;
+}
+
+TextureDataWrapper.prototype.getWidth = function() {
+ return this.width_;
+};
+
+TextureDataWrapper.prototype.getHeight = function() {
+ return this.height_;
+};
+
+TextureDataWrapper.prototype.generateData = function() {
+ this.data = this.data_;
+ maybeRunTests();
+};
+
+function RGBA8DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint8Array(4 * width * height);
+}
+
+RGBA8DataWrapper.prototype = new TextureDataWrapper;
+
+RGBA8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var index = 4 * (this.width_ * y + x);
+ this.data_[index] = r;
+ this.data_[index + 1] = g;
+ this.data_[index + 2] = b;
+ this.data_[index + 3] = a;
+};
+
+function RGBA5551DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint16Array(width * height);
+}
+
+RGBA5551DataWrapper.prototype = new TextureDataWrapper;
+
+RGBA5551DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var value = (((r & 0xF8) << 8)
+ | ((g & 0xF8) << 3)
+ | ((b & 0xF8) >> 2)
+ | (a >> 7));
+ this.data_[this.width_ * y + x] = value;
+};
+
+function RGBA4444DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint16Array(width * height);
+}
+
+RGBA4444DataWrapper.prototype = new TextureDataWrapper;
+
+RGBA4444DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var value = (((r & 0xF0) << 8)
+ | ((g & 0xF0) << 4)
+ | (b & 0xF0)
+ | (a >> 4));
+ this.data_[this.width_ * y + x] = value;
+};
+
+function RGB8DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint8Array(3 * width * height);
+}
+
+RGB8DataWrapper.prototype = new TextureDataWrapper;
+
+RGB8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var index = 3 * (this.width_ * y + x);
+ this.data_[index] = r;
+ this.data_[index + 1] = g;
+ this.data_[index + 2] = b;
+};
+
+function RGB565DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint16Array(width * height);
+}
+
+RGB565DataWrapper.prototype = new TextureDataWrapper;
+
+RGB565DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var value = (((r & 0xF8) << 8)
+ | ((g & 0xFC) << 3)
+ | ((b & 0xF8) >> 3));
+ this.data_[this.width_ * y + x] = value;
+};
+
+function A8DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint8Array(width * height);
+}
+
+A8DataWrapper.prototype = new TextureDataWrapper;
+
+A8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ this.data_[this.width_ * y + x] = a;
+};
+
+function L8DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint8Array(width * height);
+}
+
+L8DataWrapper.prototype = new TextureDataWrapper;
+
+L8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ this.data_[this.width_ * y + x] = r;
+};
+
+function LA8DataWrapper(width, height)
+{
+ TextureDataWrapper.call(this, width, height);
+ this.data_ = new Uint8Array(2 * width * height);
+}
+
+LA8DataWrapper.prototype = new TextureDataWrapper;
+
+LA8DataWrapper.prototype.setPixel = function(x, y, r, g, b, a) {
+ var index = 2 * (this.width_ * y + x);
+ this.data_[index] = r;
+ this.data_[index + 1] = a;
+};
+
+//----------------------------------------------------------------------
+// Color ramp generation functions
+//
+
+function generateOpaqueGrayscaleRamp(wrapper)
+{
+ var width = wrapper.getWidth();
+ var height = wrapper.getHeight();
+ for (var x = 0; x < width; ++x) {
+ var value = Math.round(255.0 * x / width);
+ for (var y = 0; y < height; ++y)
+ wrapper.setPixel(x, y, value, value, value, 255);
+ }
+}
+
+function generateTranslucentGrayscaleRamp(wrapper)
+{
+ var width = wrapper.getWidth();
+ var height = wrapper.getHeight();
+ for (var x = 0; x < width; ++x) {
+ var value = Math.round(255.0 * x / width);
+ for (var y = 0; y < height; ++y)
+ wrapper.setPixel(x, y, value, value, value, value);
+ }
+}
+
+function generateTransparentGrayscaleRamp(wrapper)
+{
+ var width = wrapper.getWidth();
+ var height = wrapper.getHeight();
+ for (var x = 0; x < width; ++x) {
+ var value = Math.round(255.0 * x / width);
+ for (var y = 0; y < height; ++y)
+ wrapper.setPixel(x, y, value, value, value, 0);
+ }
+}
+
+//----------------------------------------------------------------------
+// Verification routines
+//
+
+function allChannelsIncreaseByNoMoreThan(array, threshold, numOccurrences) {
+ var numFound = 0;
+ for (var i = 4; i < array.length; i += 4)
+ for (var j = 0; j < 4; j++)
+ if (array[i + j] - array[i + j - 4] > threshold)
+ ++numFound;
+
+ return numFound < numOccurrences;
+}
+
+function alphaChannelIncreasesByNoMoreThan(array, threshold, numOccurrences) {
+ var numFound = 0;
+ for (var i = 7; i < array.length; i += 4)
+ if (array[i] - array[i - 4] > threshold)
+ ++numFound;
+
+ return numFound < numOccurrences;
+}
+
+function allChannelsIncreaseByAtLeast(array, threshold, numOccurrences) {
+ var numFound = 0;
+ for (var i = 4; i < array.length; i += 4)
+ for (var j = 0; j < 4; ++j)
+ if (array[i + j] - array[i + j - 4] > threshold)
+ ++numFound;
+
+ return numFound > numOccurrences;
+}
+
+function colorChannelsAreZero(array, threshold, numOccurrences) {
+ var passed = true;
+ var numFailures = 0;
+
+ for (var i = 4; i < array.length; i += 4)
+ for (var j = 0; j < 3; ++j)
+ if (array[i + j] != 0) {
+ passed = false;
+ if (++numFailures <= 5)
+ debug(" array[" + (i + j) + "] should have been 0, was " + array[i + j]);
+ }
+
+ return passed;
+}
+
+</script>
+</head>
+<body onload="init()">
+<canvas id="example" width="256" height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-invalid-data.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-invalid-data.html
new file mode 100644
index 0000000000..4500624c81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-image-with-invalid-data.html
@@ -0,0 +1,158 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+ <title>texImage2D and texSubImage2D tests with invalid data</title>
+ <link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+ <script src="../../../js/js-test-pre.js"></script>
+ <script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script type="application/javascript">
+description("texImage2D and texSubImage2D tests with invalid data");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var contextVersion = wtu.getDefault3DContextVersion();
+var gl = wtu.create3DContext(canvas);
+if (!gl)
+ testFailed("Context created.");
+else
+ testPassed("Context created.");
+
+var tex;
+
+function setup() {
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+}
+
+function teardown() {
+ gl.deleteTexture(tex);
+}
+
+function test(desc, func, expected) {
+ debug(desc);
+
+ var exc = null;
+ try {
+ func();
+ } catch (x) {
+ exc = x;
+ }
+
+ if (expected == gl.INVALID_OPERATION) {
+ wtu.glErrorShouldBe(gl, expected);
+ } else if (expected == "exception") {
+ if (exc) {
+ testPassed("threw exception");
+ } else {
+ testFailed("did not throw exception");
+ }
+ }
+}
+
+test("Calling texImage2D with no WebGLTexture bound generates INVALID_OPERATION",
+ function () {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ },
+ gl.INVALID_OPERATION);
+
+test("Calling texSubImage2D with no WebGLTexture bound generates INVALID_OPERATION",
+ function () {
+ var buffer = new Uint8Array(4);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
+ },
+ gl.INVALID_OPERATION);
+
+setup();
+
+test("Passing a buffer not large enough to texImage2D should generate an INVALID_OPERATION",
+ function () {
+ var tooSmall = new Uint8Array(64);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, tooSmall);
+ },
+ gl.INVALID_OPERATION);
+
+if (contextVersion < 2) {
+ test("Passing texImage2D parameter data of Number type should throw an exception",
+ function () {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, 42);
+ },
+ "exception");
+} else {
+ test("Passing texImage2D parameter data of Number type should generate an INVALID_OPERATION",
+ function () {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, 42);
+ },
+ gl.INVALID_OPERATION);
+}
+
+if (contextVersion < 2) {
+ test("Passing texImage2D parameter data of String type should throw a TypeError",
+ function () {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
+ },
+ "exception");
+} else {
+ test("Passing texImage2D parameter data of String type should generate an INVALID_OPERATION",
+ function () {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
+ },
+ gl.INVALID_OPERATION);
+}
+
+test("Passing a buffer not large enough to texSubImage2D should generate an INVALID_OPERATION",
+ function () {
+ var tooSmall = new Uint8Array(64);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, tooSmall);
+ },
+ gl.INVALID_OPERATION);
+
+if (contextVersion < 2) {
+ test("Passing texSubImage2D parameter data of Number type should throw a TypeError",
+ function () {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, 42);
+ },
+ "exception");
+} else {
+ test("Passing texSubImage2D parameter data of Number type should generate an INVALID_OPERATION",
+ function () {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, 42);
+ },
+ gl.INVALID_OPERATION);
+}
+
+if (contextVersion < 2) {
+ test("Passing texSubImage2D parameter data of String type should throw a TypeError",
+ function () {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
+ },
+ "exception");
+} else {
+ test("Passing texSubImage2D parameter data of String type should generate an INVALID_OPERATION",
+ function () {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
+ },
+ gl.INVALID_OPERATION);
+}
+
+teardown();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-input-validation.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-input-validation.html
new file mode 100644
index 0000000000..b0910422f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-input-validation.html
@@ -0,0 +1,24 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../../js/tests/tex-input-validation.js"></script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d-bad-args.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d-bad-args.html
new file mode 100644
index 0000000000..8cbd00cce9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d-bad-args.html
@@ -0,0 +1,133 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="16" height="16"></canvas>
+<canvas id="c" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests texSubImage2D with bad arguments');
+
+var wtu = WebGLTestUtils;
+var contextVersion = wtu.getDefault3DContextVersion();
+var c = document.getElementById("c");
+
+var gl = wtu.create3DContext("testbed");
+var tex = gl.createTexture();
+var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+var maxTextureLevel = Math.floor(Math.log2(maxTextureSize)) + 1;
+
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 1, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "no previously defined texture image");
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup should succeed");
+
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 1, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "y + height > texture height");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "x + width > texture width");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "negative x");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, -1, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "negative y");
+gl.texSubImage2D(gl.TEXTURE_2D, -1, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "negative level");
+shouldThrow("gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "null pixels");
+
+// GL_INVALID_VALUE may be generated if level is greater than log 2 max, where max is the returned value of GL_MAX_TEXTURE_SIZE.
+// GL_INVALID_OPERATION is generated if the texture array has not been defined by a previous glTexImage2D or glCopyTexImage2D operation whose internalformat matches the format of glTexSubImage2D.
+gl.texSubImage2D(gl.TEXTURE_2D, maxTextureLevel + 1, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_OPERATION], "too high level");
+
+gl.texSubImage2D(gl.FLOAT, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "bad target");
+if (contextVersion > 1) {
+ gl.texSubImage2D(gl.TEXTURE_3D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "bad target");
+}
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "good args");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original");
+if (contextVersion < 2) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, c);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original");
+}
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "make texture RGB");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "format same as original RGB");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original RGB");
+if (contextVersion < 2) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, c);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original RGB");
+}
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "make texture RGBA UNSIGNED_BYTE");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "format same as original");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original");
+if (contextVersion < 2) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, c);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original");
+}
+
+// Large canvas will trigger GPU-to-GPU fast path in chrome,
+// while small canvas will go into normal path, i.e. read pixles from canvas then upload to texture.
+var largeCanvas = document.createElement("canvas");
+largeCanvas.width = 257;
+largeCanvas.height = 257;
+var largeCanvasContext = largeCanvas.getContext("2d");
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, largeCanvas);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "make texture RGBA UNSIGNED_BYTE");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "format same as original");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original");
+if (contextVersion < 2) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, c);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original");
+}
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, largeCanvas);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "format same as original");
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, largeCanvas);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original");
+if (contextVersion < 2) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, largeCanvas);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original");
+}
+
+var maxCubeMapTextureSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
+var maxCubeMapTextureLevel = Math.floor(Math.log2(maxCubeMapTextureSize)) + 1;
+for (var f = 0; f < 6; f++) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + f, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, c);
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + f, maxCubeMapTextureLevel + 1, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, c);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_OPERATION], "too high level");
+ gl.deleteTexture(tex);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d.html
new file mode 100644
index 0000000000..0d72946613
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-sub-image-2d.html
@@ -0,0 +1,101 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D tex;
+varying vec2 texCoord;
+
+void main()
+{
+ float intensity = texture2D(tex, texCoord).a;
+ gl_FragColor = vec4(intensity, intensity, intensity, 1.0);
+}
+</script>
+
+</head>
+<body>
+<canvas id="example" width="256" height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests texSubImage2D upload path from Uint8Array');
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+gl.disable(gl.DITHER);
+var program = wtu.setupProgram(
+ gl,
+ [wtu.simpleTextureVertexShader, "fshader"],
+ ['vPosition', 'texCoord0']);
+wtu.setupUnitQuad(gl);
+var textureWidth = 256;
+var textureHeight = 1;
+
+var textureLoc = gl.getUniformLocation(program, "tex");
+
+var texture = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, texture);
+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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+// Allocate the texture object
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, textureWidth, textureHeight, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null);
+// Prepare the image data
+var array = new Uint8Array(textureWidth);
+for (var i = 0; i < textureWidth; i++)
+ array[i] = i;
+// Fill the texture object with data -- this is actually the code path being tested
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, gl.ALPHA, gl.UNSIGNED_BYTE, array);
+
+// Clear and set up
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.useProgram(program);
+gl.uniform1i(textureLoc, 0);
+// Draw the texture to the frame buffer
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+// Read back the frame buffer
+var buf = new Uint8Array(textureWidth * textureHeight * 4);
+gl.readPixels(0, 0, textureWidth, textureHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+// Verify the frame buffer's contents
+var passed = true;
+for (var i = 0; i < textureWidth; i++) {
+ var val = i;
+ if (buf[4 * i + 0] != val ||
+ buf[4 * i + 1] != val ||
+ buf[4 * i + 2] != val) {
+ testFailed("pixel at (" + i + ", 0) was (" +
+ buf[4 * i + 0] + ", " +
+ buf[4 * i + 1] + ", " +
+ buf[4 * i + 2] + "), should be (" +
+ val + ", " + val + ", " + val + ")");
+ passed = false;
+ break;
+ }
+}
+
+if (passed)
+ testPassed("");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-video-using-tex-unit-non-zero.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-video-using-tex-unit-non-zero.html
new file mode 100644
index 0000000000..ee9bad4341
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/tex-video-using-tex-unit-non-zero.html
@@ -0,0 +1,191 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Texture uploading from video through tex unit 1 bug</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="640" height="480"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<img id="src-image">
+<script id="shader-fs" type="x-shader/x-fragment">
+ precision mediump float;
+
+ uniform sampler2D uTexture0;
+ uniform sampler2D uTexture1;
+
+ varying vec2 vUV;
+
+ void main(void) {
+ vec4 texture0Color = texture2D(uTexture0, vUV);
+ vec4 texture1Color = texture2D(uTexture1, vUV);
+
+ gl_FragColor = mix(texture0Color, texture1Color, 0.5);
+ }
+</script>
+<script id="shader-vs" type="x-shader/x-vertex">
+ attribute vec3 aVertexPosition;
+ attribute vec2 aTextureCoord;
+
+ varying vec2 vUV;
+
+ void main(void) {
+ vUV = aTextureCoord;
+ gl_Position = vec4(aVertexPosition, 1.0);
+ }
+</script>
+
+<script>
+"use strict";
+
+(async function test() {
+ var wtu = WebGLTestUtils;
+ description("Regression test for crbug.com/676719");
+
+ var gl = wtu.create3DContext("example", {preserveDrawingBuffer: true});
+
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ var program = wtu.setupProgram(gl, ["shader-vs", "shader-fs"],
+ ["aVertexPosition", "aTextureCoord"], [0, 1]);
+
+ if (!program) {
+ testFailed("program does not exist");
+ finishTest();
+ return;
+ }
+
+ var loc0 = gl.getUniformLocation(program, "uTexture0");
+ var loc1 = gl.getUniformLocation(program, "uTexture1");
+ if (!loc0 || !loc1) {
+ testFailed("Failed to query uniform locations");
+ finishTest();
+ return;
+ }
+ gl.uniform1i(loc0, 0);
+ gl.uniform1i(loc1, 1);
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ // Load textures
+ var imageSrc = "data:type/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AwVEx4QrzHJHAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAABm4SURBVHja7d15eN11nejxT3KSnGxN2qbpku5JWwpdkIIszuCwWWxlExFx7kVleUYF1OHqPMgz3AsyzAVRmasiijrORR2duV4Z2gLKUugIc1kKLWhZuqTQtE26pm3S7Nv9Q6cPe5vfSdq05/V6Hv6g7e8sv3PO97zPb/n+cqpufbovAICskmsVAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAAAQAFYBAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAABYBUAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAANkq70h4Epu/elJWvFjjb3vGOxbIekV5OTF3bEnMqyqN4/70X1VZ2tiajQEAwJEpJ/pixqiifV/27xtXGkeNKoq8lA3YAgAOA5lspbLlh2wypiQv3ldVuu8L/9ixJVGa9lUlAAA4oq34wvFWwkFiGwoACAAAQAAAAAIAABAAAIAAAAAEAAAwZJkHAIDDyt6O7vj9lpZYWd8SK+qbY2X9XvMHZGsADMZMaZleX8DsbQCZ6+7pjTU722Jl/d4//dcSq3e0Rl/kWDkCAIAjRUNTR6xs2Bsr/vRl/2LD3mjr7nvLv/LlLwAAOKKccNcLVoIAIKmRRamYO7YkZo8piemjimLcsIIYW1oQ5YWpKMzLjcK83Ojp64u2rt5o6eyNhubO2NzUEWvfsJltT0evFQkJDSvIjTNrhse88aVx1KjimDw8HaXpVJQWpKKnty9au3qisbU76vZ0xKW/WmMMQACQ3FGjCuP8Y0bFmdXlMXts6QG98Om8VAwvihhfno4TYti+v+vu6Y3lm5vjwdW74tertg/oQPC/PlIdH59TmWjZ2p2tMf8nq6K9py+jx1CYlxMPXzYnaiqKEi3/f/6wPa59YP3b/jzT40bezWBfSfBQX6nwUNz/YN3n8VUlcfXJVXF6dXkU5KXe8d/kpyIK81Mxsrggxg0ryLoxAAHAAMiJvjj/6Iq4/ISxcfz4YQP3pkjlximTyuOUSeVx/V9MjHtf2hHf/n+bo765K+Pbvv6h12JeVUnUVBT3e9maiuK44YxJccMjGzJ6DDeeMTnxl//aHa1x/UOvefPxJmNK8uL2BdVx1rQR/fsM52TfGMDQYR6Aw9TpU8vj0cvnxPfOnz6gH/y3Ki5IxX89bkz87q+Ojes+OCEKMnzHtHX3xefuWxftXT2Jlv/0caPjzycnf75nVJfHp+aNSfbYu3r++Ni7+7wB2eesmvJ47Mq5/f7y/8+v8GwbAxAAJFSezo1vn1MdP//EzJg5uuSg3W9Rfiq++IHx8dvL5sTRlUUZ3dbL29vi5sfqkr1hc3PjjoU1MSzBKDSiMBXfWlid+HHftHRDvLqjzZuQfT45d1T844UzYnhRfrJf8DnZOQYgAOin6RWF8ZvPzImLZlcessdwVGVxLL50VsyfNjyj27ln5bZ4cPXORMuOL0/H38+f0u/lvrGgOkaXJtvnuuSVnfHzF7Z7E7LPR48ZGd9cWBN5qeTDaE4WjwEIAA7QSRNKY/Gls2LyiMJD/liKC1Lx4wunxyVzRmV0O19+cH1s3N2eaNmPza6MhTMOfJPrJ+aMigVHjUx0X6/vaouv/Ga9NyH7nDihNKOtScYABAAHZN64kvjpx4+KssKhc8xmKjc3bl8wNRbMSP4roKmjN65atC66epIdYfz1D0+JUcX7XycTywvia2dOTnQfnd098flF62Jvp6Og36q3NzvXSVk6N+46b1qk3+Uo/35tAcjJ7jEAAcB7qBqWH/d8/KgoTQ+9EzZSublx57nTYs6Y4sS3saKhJb7+u42Jlh1ZXBDf3M+vsJzoi++cUxPDEg6c/3PZxvj9llZvxHeQrYdC3nb21BhXlh6Q28oxBiAAeCd5ORE//Oj0GFmcP2QfY2F+Ku46f1oU5yc/mvn7TzfEsvW7Ey37oWkj4pNz330z5NUnV8WJE8sS3fYjaxvjR89t9UZ8twDI0gI4/5iB2+yds59NANkyBnCIvmOsgqHr6pPHxXFVmZ3e09vbG8te2xOP1e6O5zbvjYbmztjd1h3pvNyoKM6L46pK44ya4XHezJHvOnHJ/lSPLIrrPjgxblya7Mj+yMmJLyxZF49ePifGDOv/L6ubzpwcT25oio17Ot/057NGF8WX/3x8ooe0eU9H/PUD9vvbAjC4cowBCADeqmpYflxzyviMbmPZ+t1xw8Ovx2u7O972d91dvdGypzPq9jTGolca4/bfbYrbzp4SZ9SMSHRfn543Jn66cmvUNnYkWr6xrSe+sKQ2fnnJzEjl9m/DVGk6L759Tk187J9f3neFsHQqJ+48d1qiAa27pzeuXrwudrf3eCO+5xYACZD5FgBjAAKAt/jiB8ZHcUHyg4xuXVYXdz7dcOC/eJs641O/Wh1fO2tyXHHCuH7fX34qN679swlxzZLaxI/5P+qa486n6uNLfzah38ueNLEsPnfiuPj+s1siIuJvT58YMyqT7Zf81pObYvnmvf1e7r2miD3U0+0Ohl7f/2/S09sbyzftjcfX746n65piW0tX7Gjtis7uvigvzIuqsoKYPaY4TplUFmfWDI/hRfnvuQUgG8cABEDWG1mUiotmJ9/PeMeTm/r1wd/3iy5y4sZHN8TE8nTMn97/U+bOmTkybnm8LrbsTT5d6Dee2BQnTyqLkxLst//KqRPisfW7Y0xpQVyWcLa/J17bHd99qj5cblQA9MdjtbvilsfrYvWOdz6tdWdbd+xs644/bG2NX/5+R6RyIs6ePiI+e+JYYwCHjIMAh6CPzRoVRfnJyn/F5ua448lNie+7L3Li+odeTzRVb34qNy7O8LzgvsiJqxeti8bW/g8ghfmpuPO8aXHHwurIze3/W3vb3s64enHtvt0I7Oe1sgsgenp747rfro9Lf7XmXb/833G5vogH1+yK83/+ijEAAcAbK7oi8bI3P1aX8RfYlr1dce9LyWbpW5hwsp03atjbFf/tgWSbEY8ZXZLoFK2e3t744pLa2NnW7Q1oC8CBPf/e3rh6ce2gzBCZ7WMAAiArjShMxbyqZPN7v7KtJdG+63eytHZXouXmjC2NMSWZ71l6pHZP/Gh5w0Fb73c+3RBPbGjyBuzXL8Xs9o/Pb40lrzYaAwZpDEAAZJ0Txpcm2nwdEfHw2l0D9jj+sDX55DfzxpcOyGO45bG6eLFh76Cv82c3NsU3n9jkzdfvLQDZmwCvNbbFrcs2GgMGeQxAAGSV4zK4rOezm5oH7HHsbE1+EM+8qoG5NGl3X8TnF62N5vbB2yzf2NoVVy1a54A2WwD69+v/uS3R0dNnDBjkMYDBZTvNEFMzMvmFPv75E0cPiecwdQAvVrJhd2d89aHX4nvnTx+Ux3rtA7XR4IjlZAGQpQXQ2tkd/3fVDmPAQRoDsAUga0wsTx/2z2FCecGA3t59rzTGL1/cNuCP84fPNsSjtXu86WwD6Jf/2NAUzYN4cShjAAIgS40pzT/sn8PokoF/Djc8/Hqs2T5wF+V5ob45/v5x05bSfyvr9xoDDsEYgAA44pXkpw7751A8CM+hvacvPnvf2mjtzHx63qb27vj8onXRbb8/SQKgocUYcAjGAATAEa8w//B/SYoG6Tms2dke//Zy5vteH1jdGHVvuXAQSWTnhEmb9nQYAw7RGIAAYIjLSw3O2+rYscXx8dmZzzJ28ZxRccpERyln/PU/AN//RXmHX0Q0dbhI1KEaAxAAR7S2rl4r4R2UpXPjBxdMT3y50jdK5ebGnefVxMgimykzGuQHoADK0offa9A8yAFgDEAAZKnWLr8u3skdC2ti0vCBO7Vo7LB0fPfcadl7LtsAKBiAX+9lhYffmciDdf6/MQABkOW2OSf9bS4/fkwsGIT5xU+rHh7XnFJlBSeUzktFToanAs4YVWRFGgM4REwENMRs3NMRc8clm0bz2O88Hztaj6yL2cwZUxw3nD5x0G7/b06dEM9sbB6w+dOzTVF+brR2JY+A2WNKrERjALYAEBGxfld74mVnjSk+otZFaUFu3H3B9EjnDd5+4rxUbtx1/rQYXpi9xwP09Cbf51yezuw3xIkTHIxpDEAAEBERKzL4JXqkDabfWlgdkw/ClKJVZen49jk1WXs8QEcGEyKMzmDSmvFlBXHiBBeNMQYgAIiIiOcz+PBfNHtUxvtkh4rPHDc6o2ui99dZ00bE504aN2i339WT/Fd2YWpwT5XL5KCzmork+/A/Obcy8VXvjAFH/hiAAMg6O9u6Y2V9sit6TSgvjAUzRh6Sxz1rdFH84uKjBuy2/vsZkxIt+1pjWzS2Jpvk57oPTojjxg3OPunO7uQBMG7Y4M6rvr0l+UFnSX9xVg3Lj8+eONYH3hiAAOCNlrzSmHjZv/vQ5BhWcPBe1hkVhfG9c2vit5+ZHX9RPTzj2yvJ/+N+/8IEU4l29fTGNUtq48sPvpbovgvyUvH986dFWXrg19+eDM4d/8DkskF9DRuak8+KuHDGiCjs5+mAOdEXt509NYoLHINsDEAA8Ca/fmlHtCfcLDt2WDp+9NHpg77Z+P3jS+MnF06PpVfMiQtmjRqwTbnfXDA1po5Mtln5H57cFC80tMTD63bHz1ZuTXQbE4cXxj98pGbA19eODH5lX3XyuChPD95Hde3O5AedVZQUxK1nTz3wBfr64o6F1XHmtBE+6MYABABv+7Jo7Y57X9qZePlTpw6Pf7lkZowvG9hNxyMKU3HZvNGx9PLZcd+ls+LsGSMH9EN/6fsq47xjkk31u3xjU3znqfp9/3/Toxti3Y5kVw/88IyRcfnxYwZ03dVlMH/8lBFFsfSKuXHNyePi+KqSqCjKi4H8gffy1swubnPxnMq45UOTY3/Tv08sL4hfXjIzLp472ofcGMAQYBvcEPXdpzbHhbMqEm0Kj4h4/8SyWHbl3Pj+Mw3xs5VbY3vCc4OrR6Tj1CnlsWDGiDhlUtmgzfF9TGVR3HTm5ETLNrd3xzVLaqPvDRenae/pi6sWr4sln5qV6DTCG06fGMs3Nccftg7MJYjX7mjLaPlxZem4/rT+HRcx/rZnDujfPbWxOePnd9nxY+ODU8rj5y9sjcdq90R9c0f09UWMKS2ImZVFce7Mipg/fUQUF5h+2Rjw3jZ/9aSDvq6T3ueBfsYEAP38xdgZdz5dH185NfkkOMUFqfjyqRPiSx+oiic3NMXTdU2xamtrrN/VFk3tPbG3syd6+iKK8nKjtCA3xpWlY3xZQcwYVRSzRpfEseNKoqosPejPtTg/J36QcL9/RMTfPvJ6bGp6+37sl7a1xdf/fVP8jwRhkc5LxQ8umBbzf7IqWgZgbvblm5uH7Httc1NnrNneGjMqMzuHvKaiKG48c0rceKbPrzEAAUBG7nyqPuZPG5F4VrB9L3IqN06rHh6nDdEDdG7/cHXi08kWv7wjfv0em0rvfrYhTqsujw9O7f9znzKiKL61sDo+t2hdxs/xmY3N0drZM2R/AS96ZWf8TaVJZIwBZBM7b4awrt6IK+5dk/i0tsPBXx5bGR+dlWy//+Y9HXHdQ/s54j8nJ750f23idXju0RXxqeMy32fd3t0Xj67bNWRfh1+8uC06ul2ExhiAAGDIqG/uik//ak00tx9583vPHFUUN5+VbL9/T29vfOn+2mjq2P/m+W0t3YlPDYyIuPGMSXFMZeYXrfnxc1uG7GuxraU7/uX32w/6/d79TL0PeRaPAQgA9mNFQ0v85b++GrvbjpyrhBXl5cTdF0yLooT7/e9+dku/Dl57eN3u+OmKZF/Ahfmp+MEF06Mow8vfPl/fEr9Z3ThkX5Pbf7fpoP7SvO+lHXHzY3U+4Fk6BiAA6McA8JF7XorV21uPiOdz24enxrRRyfY5r9qyN77+7xv7vdxNS+tiTcL1V1NRFLcvmJrx877+odeivqljSL4mu9t74q/vXx+9vb2Dfl/3vrQ9vnB/bUROjg93lo4BCAD64fXdHfGRe1bFPz2/JaMruA20rp7eWPTyjjjnnlUH9O8vmTMqLppdmei+Wjt74qrF6yLJ9Ws6evri6sXrEu/rvnBWZXxy7qiM1tX21u74L//66pCNgKXr98TXBvlX+Y+XN8QXl9RGrynrs3YMQACQQFt3X9zwyIY496cvxVN1ew7pY1nf2Ba3LauLk+5aGVctro2VDfufUGZGRWH83YemJL7PWx6vi9rG5F+eL29vi1uXbUy8/M1nTYkZFZldoXDNzvZY+L9XDdndAT9+bmt89bfro3OADwrc29EdVy1aGzcurXvTnA1k1xjA0OE0wMPUi1ta46JfvBonTSiNvzpxXJxRXR4FeYN/ilnd7vb4zerGuP/VxljRzw97YV5O3H3B9MSnwi1dtyvuWbkt4+fwo+Vb4vTq4YnmLS8uSMXdF0yPBfesivYMLqO7vbU7rvy3tXF8VUlcecLYOGva0Jok52cvbI9VW1vjGwumxtGjM79A0v2v7oyvLd0Q9c32YWfzGIAAYAA9s2lvPLNpbYwoTMW5R1fEGdXlccqksihND8xLu6OlM1bU740nX2+KJ17fE2symDf+1vlTEk82s6OlM659YP3ArLQ/nRq49Io5UVHS/6lSZ1QWx63zp8S1GZxZ8J+er2+J5xfXRmFeTpw4YVi8f8KwmF5RFJOGp6OyJD/K06koyMuN/NTB31i3sqEl5v/TqrjwmIq48v1jY87Y/p2L3tndEw+u3hU/XN4QL26x39oYwFCTU3Xr0/bEHWFSOREzK/84k9fM0cUxqTwdY0rzY3RpfpQUpCKdyo10Xk709kV0dPdGW1dv7Gjtih0tXbG5qTPWN7ZHbWNbrNra+o4z7JGdpg5Px2nV5TFvfGlUjyiMqrJ0lBakIp2XE21dvbGnvSfq9rTHq9vb4qm6pli2fs+AzKKIMQABAAAMEAcBAoAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAN7o/wMPKI9LWOVgigAAAABJRU5ErkJggg==";
+ var imageElement = document.getElementById("src-image");
+ imageElement.src = imageSrc;
+ await imageElement.decode();
+
+ var resourcePath = "../../../resources/";
+
+ 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.bt601.vp9.webm",
+ type: 'video/webm; codecs="vp9"' },
+ { src: resourcePath + "red-green.theora.ogv",
+ type: 'video/ogg; codecs="theora, vorbis"' },
+ ];
+ var currentVideo = null;
+
+ for (const info of videos) {
+ currentVideo = info;
+ debug("");
+ debug("testing: " + info.type);
+ const video = document.createElement("video");
+ video.muted = true;
+ var canPlay = true;
+ if (!video.canPlayType) {
+ testFailed("video.canPlayType required method missing");
+ continue;
+ }
+ if(!video.canPlayType(info.type).replace(/no/, '')) {
+ debug(info.type + " unsupported");
+ continue;
+ }
+ document.body.appendChild(video);
+ video.type = info.type;
+ video.src = info.src;
+ await new Promise(res => {
+ wtu.startPlayingAndWaitForVideo(video, res);
+ });
+ video.pause();
+
+ var texture0 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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.bindTexture(gl.TEXTURE_2D, null);
+
+ var texture1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageElement);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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.bindTexture(gl.TEXTURE_2D, null);
+
+ // <-- Begin Observed -->
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, texture1);
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
+
+ wtu.clearAndDrawUnitQuad(gl, [255, 0, 255, 255]);
+
+ var observedPixels = new Uint8Array(640 * 480 * 4);
+ gl.readPixels(0, 0, 640, 480, gl.RGBA, gl.UNSIGNED_BYTE, observedPixels);
+ // <-- End Observed -->
+
+ // <-- Begin Expected -->
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
+
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, texture1);
+
+ wtu.clearAndDrawUnitQuad(gl, [255, 0, 255, 255]);
+
+ var expectedPixels = new Uint8Array(640 * 480 * 4);
+ gl.readPixels(0, 0, 640, 480, gl.RGBA, gl.UNSIGNED_BYTE, expectedPixels);
+ // <-- End Expected -->
+
+ // Compare results
+ const tolerance = 1;
+ var numDifferentPixels = wtu.comparePixels(observedPixels, expectedPixels, tolerance, undefined);
+ if (numDifferentPixels) {
+ testFailed("Texture states were incorrect for " + currentVideo.type +
+ ", rendering was wrong: found " + numDifferentPixels + " differing pixels");
+ } else {
+ testPassed(`Texture states were correct +/-${tolerance}, rendering as expected`);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+
+ debug("");
+ finishTest();
+})();
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texparameter-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texparameter-test.html
new file mode 100644
index 0000000000..e6e33874cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texparameter-test.html
@@ -0,0 +1,129 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL TexParameter conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas_drawing" width="12" height="12"></canvas>
+<canvas id="canvas_texture" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Tests TexParameter works as expected");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas_drawing");
+var canvas_texture = null;
+var texParam = [
+ gl.REPEAT,
+ gl.CLAMP_TO_EDGE,
+ gl.MIRRORED_REPEAT,
+];
+var color = [200, 0, 254, 255];
+var textures = [];
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ wtu.setupTexturedQuadWithTexCoords(gl, [-2.5, -2.5], [3.5, 3.5]);
+
+ setupCanvasTexture();
+ setupTextures();
+ for (var ii = 0; ii < texParam.length; ++ii) {
+ runDrawingTest(textures[ii], texParam[ii]);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function setupCanvasTexture() {
+ canvas_texture = document.getElementById("canvas_texture");
+ var ctx2d = canvas_texture.getContext("2d");
+ ctx2d.fillStyle = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + color[3] + ")";
+ ctx2d.fillRect(0, 0, 1, 1);
+}
+
+function setupTextures() {
+ for (var ii = 0; ii < texParam.length; ++ii) {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas_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, texParam[ii]);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParam[ii]);
+ textures[ii] = texture;
+ }
+}
+
+function runDrawingTest(texture, param) {
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ checkPixels(param);
+}
+
+function checkPixels(param) {
+ var buf = new Uint8Array(12 * 12 * 4);
+ gl.readPixels(0, 0, 12, 12, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var passed = true;
+ for (var yy = 0; yy < 12; ++yy) {
+ for (var xx = 0; xx < 12; ++xx) {
+ var ec = [0, 0, 0, 0];
+ switch (param) {
+ case gl.REPEAT:
+ if (xx % 2 == 1 && yy % 2 == 1) {
+ ec = color;
+ }
+ break;
+ case gl.CLAMP_TO_EDGE:
+ if (xx < 6 && yy < 6) {
+ ec = color;
+ }
+ break;
+ case gl.MIRRORED_REPEAT:
+ if (xx % 4 < 2 && yy % 4 < 2) {
+ ec = color;
+ }
+ break;
+ }
+ var off = (yy * 12 + xx) * 4;
+ if (buf[off + 0] != ec[0] || buf[off + 1] != ec[1] ||
+ buf[off + 2] != ec[2] || buf[off + 3] != ec[3]) {
+ var msg = 'at (' + xx + ', ' + yy + ') expected: ' +
+ ec[0] + ', ' + ec[1] + ', ' + ec[2] + ', ' + ec[3] + ' found: ' +
+ buf[off + 0] + ', ' + buf[off + 1] + ', ' + buf[off + 2] + ', ' + buf[off + 3];
+ testFailed(msg);
+ passed = false;
+ }
+ }
+ }
+ if (passed) {
+ testPassed("Drawing with wrap " + wtu.glEnumToString(gl, param) + " as expected");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind-2.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind-2.html
new file mode 100644
index 0000000000..f459924ad1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind-2.html
@@ -0,0 +1,210 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ActiveTexture BindTexture conformance test #2</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<canvas id="canvas2d" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+uniform mat4 world;
+attribute vec3 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = world * vec4(vPosition, 1);
+ texCoord = texCoord0;
+}
+</script>
+<script id="fshader2d" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform sampler2D tex2d;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex2d, texCoord);
+}
+</script>
+<script id="fshaderCube" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform samplerCube texCube;
+void main()
+{
+ gl_FragColor = textureCube(texCube, vec3(0,1,0));
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description(
+ "Tests that binding both TEXTURE_2D and TEXTURE_CUBE_MAP to the same " +
+ "active texture unit works as long as they are not used " +
+ "simultaneously in the same shader program.");
+
+ var canvas2d = document.getElementById("canvas2d");
+ var ctx2d = canvas2d.getContext("2d");
+ ctx2d.globalCompositeOperation = "copy";
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(
+ gl, ["vshader", "fshader2d"], ["vPosition", "texCoord0"]);
+
+ var program2d = program;
+ var programCube = wtu.setupProgram(
+ gl, ["vshader", "fshaderCube"], ["vPosition", "texCoord0"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([-1, 1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([ 0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ // Make texture unit 1 active.
+ gl.activeTexture(gl.TEXTURE1);
+
+ // Make a 2d texture
+ var tex2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+ ctx2d.fillStyle = "rgba(0, 0, 255, 255)";
+ ctx2d.fillRect(0, 0, 1, 1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+
+ // make a cube texture
+ var texCube = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ ctx2d.fillStyle = "rgba(255, 0, 255, 255)";
+ ctx2d.fillRect(0, 0, 1, 1);
+ 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 ii = 0; ii < targets.length; ++ii) {
+ gl.texImage2D(targets[ii], 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+ }
+
+ // Setup program2d and programCube
+ var tex2dLoc = gl.getUniformLocation(program2d, "tex2d");
+ var world2dLoc = gl.getUniformLocation(program2d, "world");
+ var texCubeLoc = gl.getUniformLocation(programCube, "texCube");
+ var worldCubeLoc = gl.getUniformLocation(programCube, "world");
+
+ gl.useProgram(program2d);
+ gl.uniform1i(tex2dLoc, 1);
+ gl.useProgram(programCube);
+ gl.uniform1i(texCubeLoc, 1);
+
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var programs = [program2d, programCube];
+ var worldLocs = [world2dLoc, worldCubeLoc];
+ for (var ii = 0; ii < 4; ++ii) {
+ var x = ii % 2;
+ var y = Math.floor(ii / 2);
+ gl.useProgram(programs[x]);
+ gl.uniformMatrix4fv(
+ worldLocs[x], false,
+ [0.5, 0, 0, 0,
+ 0, 0.5, 0, 0,
+ 0, 0, 1, 0,
+ -0.5 + x, -0.5 + y, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ var colors = [
+ [0,0,255,255],
+ [255,0,255,255],
+ [0,0,255,255],
+ [255,0,255,255]];
+
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var c = colors[ii];
+ var x = ii % 2;
+ var y = Math.floor(ii / 2);
+ wtu.checkCanvasRect(gl, x, y, 1, 1, c);
+ }
+
+ // Test that binding to one target does not affect the other
+ debug("");
+ debug("Testing texture target binding/unbinding");
+
+ var worldMatrix = [
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1];
+
+ gl.activeTexture(gl.TEXTURE2);
+
+ // Unbinding the TEXTURE_CUBE_MAP target should not affect the TEXTURE_2D target
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+
+ gl.useProgram(program2d);
+ gl.uniform1i(tex2dLoc, 2);
+ gl.uniformMatrix4fv(world2dLoc, false, worldMatrix);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.checkCanvasRect(gl, 0, 0, 2, 2, [0,0,255,255]);
+
+ // Unbinding the TEXTURE_2D target should not affect the TEXTURE_CUBE_MAP target
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ gl.useProgram(programCube);
+ gl.uniform1i(texCubeLoc, 2);
+ gl.uniformMatrix4fv(worldCubeLoc, false, worldMatrix);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.checkCanvasRect(gl, 0, 0, 2, 2, [255,0,255,255]);
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind.html
new file mode 100644
index 0000000000..f24bd9b1f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-active-bind.html
@@ -0,0 +1,179 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ActiveTexture BindTexture conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<canvas id="canvas2d" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+uniform mat4 world;
+attribute vec3 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = world * vec4(vPosition, 1);
+ texCoord = texCoord0;
+}
+</script>
+<script id="trivial-vs" type="text/plain">
+void main()
+{
+ gl_Position = vec4(0,0,0,1);
+ gl_PointSize = 1.0;
+}
+</script>
+<script id="tex-point-fs" type="text/plain">
+precision mediump float;
+uniform sampler2D uSampler;
+void main()
+{
+ gl_FragColor = texture2D(uSampler, vec2(0));
+}
+</script>
+<script>
+"use strict";
+var gl;
+
+function init()
+{
+ description(
+ "Tests that glActiveTexture and glBindTexture work as expected" +
+ "Specifically texture targets are per active texture unit.");
+
+ var canvas2d = document.getElementById("canvas2d");
+ var ctx2d = canvas2d.getContext("2d");
+
+ var wtu = WebGLTestUtils;
+ gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(
+ gl,
+ ["vshader", wtu.simpleTextureFragmentShader],
+ ['vPosition', 'texCoord0']);
+ wtu.setupUnitQuad(gl);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var colors = [
+ [0,192,128,255],
+ [128,64,255,255],
+ [192,255,64,255],
+ [200,0,255,255]];
+
+ // Make 4 textures by using 4 active texture units if available.
+ var texunits = Math.min(colors.length, gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS))
+ var textures = [];
+ for (var ii = 0; ii < texunits; ++ii) {
+ var tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ textures[ii] = tex;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // now use each texture unit to write into the textures,
+ for (var ii = 0; ii < texunits; ++ii) {
+ var c = colors[ii];
+ ctx2d.fillStyle =
+ "rgba(" + c[0] + "," + c[1] + "," + c[2] + "," + c[3] + ")";
+ ctx2d.fillRect(0, 0, 1, 1);
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var textureLoc = gl.getUniformLocation(program, "tex");
+ var worldLoc = gl.getUniformLocation(program, "world");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ for (var ii = 0; ii < texunits; ++ii) {
+ var x = ii % 2;
+ var y = Math.floor(ii / 2);
+ gl.uniform1i(textureLoc, ii);
+ gl.uniformMatrix4fv(
+ worldLoc, false,
+ [0.5, 0, 0, 0,
+ 0, 0.5, 0, 0,
+ 0, 0, 1, 0,
+ -0.5 + x, -0.5 + y, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ for (var ii = 0; ii < texunits; ++ii) {
+ var x = ii % 2;
+ var y = Math.floor(ii / 2);
+ wtu.checkCanvasRect(gl, x, y, 1, 1, colors[ii]);
+ }
+
+ debug("");
+ debug("Swizzle applied to correct ActiveTexture index");
+
+ {
+ const prog = wtu.setupProgram(
+ gl,
+ ["trivial-vs", "tex-point-fs"]);
+ prog.uSampler = gl.getUniformLocation(prog, "uSampler");
+ gl.useProgram(prog);
+ gl.viewport(0, 0, 1, 1);
+ gl.activeTexture(gl.TEXTURE0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ const tex0_rgba8 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex0_rgba8);
+ const tex0_rgba8_data = new Uint8Array([10, 20, 30, 40]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, tex0_rgba8_data);
+
+ const tex2_a8 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2_a8);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, 1, 1, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null);
+
+ window.control = new Uint8Array(4);
+ window.after_swizzle_applied = new Uint8Array(4);
+
+ gl.bindTexture(gl.TEXTURE_2D, tex0_rgba8);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, window.control);
+ shouldBeString("window.control", tex0_rgba8_data.toString());
+
+ gl.activeTexture(gl.TEXTURE2);
+ gl.bindTexture(gl.TEXTURE_2D, tex2_a8);
+ gl.uniform1i(prog.uSampler, 2);
+ gl.activeTexture(gl.TEXTURE0);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ // Firefox would apply the A8-on-R8 swizzle to whatever tex-unit was active.
+
+ gl.uniform1i(prog.uSampler, 0);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, window.after_swizzle_applied);
+ shouldBeString("window.after_swizzle_applied", tex0_rgba8_data.toString());
+ // Firefox would then get 0,0,0,10 here, as the [ZERO,ZERO,ZERO,RED] swizzle was applied to our
+ // 10,20,30,40 texture.
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-attachment-formats.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-attachment-formats.html
new file mode 100644
index 0000000000..b569ca061d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-attachment-formats.html
@@ -0,0 +1,176 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Texture Attachment Format Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2" style="width: 100px; height:100px; border: 1px solid black;"> </canvas>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking texture formats.");
+
+ var numValidFormats = 0;
+ var clearColor = [0.25, 0.5, 0.75, 0.25];
+
+ var floatToBits = function(value, bits) {
+ var range = (1 << bits) - 1;
+ var result = 0;
+ if (range > 0) {
+ result = Math.floor(Math.floor(value * range) * 255 / range);
+ }
+
+ //debug("v = " + value + ", bits = " + bits + ", range = " + range + ", result = " + result);
+ return result;
+ }
+
+ var testFormat = function(info) {
+ debug("");
+ debug("testing: " + info.format + ", " + info.type);
+
+ var format = gl[info.format];
+ var type = gl[info.type];
+
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ format, // internalFormat
+ 16, // width
+ 16, // height
+ 0, // border
+ format, // format
+ type, // type
+ null); // data
+ var fbStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ debug(wtu.glEnumToString(gl, fbStatus));
+ if (fbStatus != gl.FRAMEBUFFER_COMPLETE) {
+ debug("format unsupported");
+ if (info.mustBeFramebufferComplete) {
+ testFailed(info.format + " must be FRAMEBUFFER_COMPLETE");
+ }
+ return;
+ }
+
+ ++numValidFormats;
+
+ var startExpected = [0, 0, 0, info.channels[3] < 0 ? 255 : 0];
+
+ var expected = [];
+ var tolerance = [];
+ for (var ii = 0; ii < 4; ++ii) {
+ var color = 0;
+ var channel = info.channels[ii];
+ if (channel < 0) {
+ color = ii < 3 ? 0 : 255
+ } else {
+ color = floatToBits(clearColor[channel], info.bits[ii]);
+ }
+ expected.push(color);
+ tolerance.push(channel < 0 ? 0 : (1 + (1 << (8 - info.bits[ii]))));
+ }
+
+ wtu.checkCanvas(gl, startExpected, "should be " + startExpected);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, expected, "should be " + expected + " with tolerance " + tolerance, tolerance);
+ }
+
+ var validFormats = [
+ { format: 'RGBA',
+ type: 'UNSIGNED_BYTE',
+ channels: [0, 1, 2, 3],
+ bits: [8, 8, 8, 8],
+ mustBeFramebufferComplete: true
+ },
+ { format: 'ALPHA',
+ type: 'UNSIGNED_BYTE',
+ channels: [-1, -1, -1, 3],
+ bits: [0, 0, 0, 8],
+ mustBeFramebufferComplete: false
+ },
+ { format: 'RGB',
+ type: 'UNSIGNED_BYTE',
+ channels: [0, 1, 2, -1],
+ bits: [8, 8, 8, 0],
+ mustBeFramebufferComplete: false
+ },
+ { format: 'RGB',
+ type: 'UNSIGNED_SHORT_5_6_5',
+ channels: [0, 1, 2, -1],
+ bits: [5, 6, 5, 0],
+ mustBeFramebufferComplete: false
+ },
+ { format: 'RGBA',
+ type: 'UNSIGNED_SHORT_5_5_5_1',
+ channels: [0, 1, 2, 3],
+ bits: [5, 5, 5, 1],
+ mustBeFramebufferComplete: false
+ },
+ { format: 'RGBA',
+ type: 'UNSIGNED_SHORT_4_4_4_4',
+ channels: [0, 1, 2, 3],
+ bits: [4, 4, 4, 4],
+ mustBeFramebufferComplete: false
+ },
+ { format: 'LUMINANCE',
+ type: 'UNSIGNED_BYTE',
+ channels: [0, 0, 0, -1],
+ bits: [8, 8, 8, -1],
+ mustBeFramebufferComplete: false
+ },
+ { format: 'LUMINANCE_ALPHA',
+ type: 'UNSIGNED_BYTE',
+ channels: [0, 0, 0, 3],
+ bits: [8, 8, 8, 8],
+ mustBeFramebufferComplete: false
+ }
+ ];
+
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.framebufferTexture2D(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+
+ for (var ii = 0; ii < validFormats.length; ++ii) {
+ var info = validFormats[ii];
+ testFormat(info);
+ }
+
+ debug("");
+ shouldBeTrue("numValidFormats > 0");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-clear.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-clear.html
new file mode 100644
index 0000000000..6e658f5b4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-clear.html
@@ -0,0 +1,43 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture clear conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,255,0,255]));
+wtu.clearAndDrawUnitQuad(gl);
+wtu.checkCanvas(
+ gl, [0, 255, 0, 255], "should be green");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-complete.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-complete.html
new file mode 100644
index 0000000000..370f6d5fa2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-complete.html
@@ -0,0 +1,63 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL "Texture Complete" texture conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<canvas id="canvas2d" width="16" height="16" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function init()
+{
+ description(
+ "Checks that a texture that is not -texture-complete- does not draw if"+
+ " filtering needs mips");
+
+ var canvas2d = document.getElementById("canvas2d");
+ var ctx2d = canvas2d.getContext("2d");
+ ctx2d.fillStyle = "rgba(0,192,128,1)";
+ ctx2d.fillRect(0, 0, 16, 16);
+
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("example");
+ var gl = wtu.create3DContext(canvas);
+ var program = wtu.setupTexturedQuad(gl);
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ // 16x16 texture no mips
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0,0,0,255],
+ "texture that is not -texture-complete- when " +
+ "TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255");
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-and-deletion.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-and-deletion.html
new file mode 100644
index 0000000000..1caff3d224
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-and-deletion.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Texture Copying and Deletion Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description('Checks that texture copying and deletion work correctly together.');
+debug('Regression test for <a href="http://anglebug.com/4267">http://anglebug.com/4267</a>');
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("example");
+canvas.addEventListener('webglcontextlost', contextLost, false);
+
+let contextWasLost = false;
+function contextLost(e) {
+ e.preventDefault();
+ contextWasLost = true;
+ debug("***context lost -- should not happen***");
+}
+
+const gl = wtu.create3DContext(canvas);
+
+const texture = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+const texture2 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, texture2);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+const framebuffer = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+assertMsg(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE,
+ "framebuffer should be FRAMEBUFFER_COMPLETE.");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setup");
+
+// This test does not call getError, because doing so seems to cause
+// an implicit flush which intermittently masks the bug.
+
+debug("");
+debug("testing copyTexImage2D");
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.copyTexImage2D(gl.TEXTURE_2D, 1, gl.RGBA, 0, 0, 2, 2, 0);
+// Not necessary to do any CopyTexImage2D operations to texture2.
+
+debug("");
+debug("testing copyTexSubImage2D");
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
+gl.bindTexture(gl.TEXTURE_2D, texture2);
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+
+debug('deleting framebuffer');
+gl.deleteFramebuffer(framebuffer);
+debug('deleting texture');
+gl.deleteTexture(texture);
+debug('deleting texture2');
+// On buggy driver, crashes during this deleteTexture call.
+gl.deleteTexture(texture2);
+
+setTimeout(function() {
+ shouldBe("contextWasLost", "false");
+ finishTest();
+}, 1000);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-feedback-loops.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-feedback-loops.html
new file mode 100644
index 0000000000..0ff4e0ec4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-copying-feedback-loops.html
@@ -0,0 +1,82 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Texture Copying Feedback Loops Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Checks that texture copying feedback loops fail correctly.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var texture = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+var texture2 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, texture2);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+var framebuffer = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+assertMsg(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE,
+ "framebuffer should be FRAMEBUFFER_COMPLETE.");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setup");
+
+debug("");
+debug("testing copyTexImage2D");
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.copyTexImage2D(gl.TEXTURE_2D, 1, gl.RGBA, 0, 0, 2, 2, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "after copyTexImage2D to same texture but different level");
+gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 2, 2, 0);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "after copyTexImage2D to same texture same level, invalid feedback loop");
+gl.bindTexture(gl.TEXTURE_2D, texture2);
+gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 2, 2, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "after copyTexImage2D to different texture");
+
+debug("");
+debug("testing copyTexSubImage2D");
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "after copyTexSubImage2D to same texture but different level");
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "after copyTexSubImage2D to same texture same level, invalid feedback loop");
+gl.bindTexture(gl.TEXTURE_2D, texture2);
+gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "after copyTexSubImage2D to different texture");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-corner-case-videos.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-corner-case-videos.html
new file mode 100644
index 0000000000..0d7061c83f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-corner-case-videos.html
@@ -0,0 +1,47 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/texture-corner-case-videos.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<canvas id="c2d" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest(
+ 'Verify uploading various corner-case videos to 2D textures',
+ "RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "", 1,
+ [
+ // Regression test for http://crbug.com/701060.
+ // Generated with the following command line:
+ // ffmpeg -r 25 -i red-green-480-272.png -vframes 10 -vcodec h264 -vf setsar=136:135,setdar=16:9 -pix_fmt yuv420p ...
+ {
+ comment: "Video whose natural size is larger than coded size due to uncommon pixel shape (Sample Aspect Ratio)",
+ src: "../../../resources/red-green-480x272-sar-136x135-dar-16x9.mp4",
+ type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ // A fairly high tolerance is used because colorspace conversion seems to differ widely between
+ // hardware-accelerated video decoders. At least on Windows / NVIDIA, this test was seen to convert
+ // (0,255,0) to (13,238,14), and (255,0,0) to (238,14,14).
+ tolerance: 18,
+ }
+ ])();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-cube-as-fbo-attachment.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-cube-as-fbo-attachment.html
new file mode 100644
index 0000000000..5e09d3240f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-cube-as-fbo-attachment.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture cube as FBO color attachment</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var gl;
+
+function run()
+{
+ description(
+ "Tests using a cube map face as the color attachment of a framebuffer object. " +
+ "This test covers an ANGLE validation bug. See https://code.google.com/p/angleproject/issues/detail?id=849 .");
+
+ var wtu = WebGLTestUtils;
+ gl = wtu.create3DContext("example");
+ var textureCube = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, textureCube);
+ var faces = [
+ 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
+ ];
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ for (var ii = 0; ii < faces.length; ++ii) {
+ gl.texImage2D(faces[ii], 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ for (var ii = 0; ii < faces.length; ++ii) {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, faces[ii], textureCube, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors for face " + wtu.glEnumToString(gl, faces[ii]));
+ }
+}
+
+run();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-draw-with-2d-and-cube.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-draw-with-2d-and-cube.html
new file mode 100644
index 0000000000..c905c5595a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-draw-with-2d-and-cube.html
@@ -0,0 +1,103 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ActiveTexture BindTexture conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<canvas id="canvas2d" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec3 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vec4(vPosition, 1);
+ texCoord = texCoord0;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 texCoord;
+uniform sampler2D tex2D;
+uniform samplerCube texCube;
+void main()
+{
+ gl_FragColor = texture2D(tex2D, texCoord);
+ gl_FragColor += textureCube(texCube, vec3(texCoord, 0));
+}
+</script>
+<script>
+"use strict";
+var gl;
+
+function init()
+{
+ description(
+ "Tests drawing with two textures of different type. " +
+ "This test covers an ANGLE validation bug. See http://crbug.com/390412.");
+
+ var canvas2d = document.getElementById("canvas2d");
+ var ctx2d = canvas2d.getContext("2d");
+
+ var wtu = WebGLTestUtils;
+ gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(
+ gl,
+ ["vshader", "fshader"],
+ ['vPosition', 'texCoord0']);
+ wtu.setupUnitQuad(gl);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var texture2D = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, texture2D);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var textureCube = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, textureCube);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var texture2DLoc = gl.getUniformLocation(program, "tex2D");
+ var textureCubeLoc = gl.getUniformLocation(program, "texCube");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.uniform1i(texture2DLoc, 0);
+ gl.uniform1i(textureCubeLoc, 1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-fakeblack.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-fakeblack.html
new file mode 100644
index 0000000000..ecd1d40ca5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-fakeblack.html
@@ -0,0 +1,94 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Tests if fake black textures are corectly implemented on desktops</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+function createTexture(gl,r,g,b,a) {
+ // setup render target texture //
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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, 3, 3, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ // setup framebuffer //
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ // fill the framebuffer //
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.clearColor(r, g, b, a);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ gl.deleteFramebuffer(fbo);
+
+ return texture;
+}
+
+function init() {
+ /*
+ * This test has been written due to a bug found in firefox's code
+ * and fixed in the following patch :
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=879952#c5
+ */
+ var wtu = WebGLTestUtils;
+ description();
+
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupTexturedQuad(gl);
+
+ var texture0 = createTexture(gl,1,0,0,1);
+ var texture1 = createTexture(gl,0,1,0,1);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [255, 0, 0, 255]);
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 0, 0, 255]);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture1);
+ 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.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 0, 0, 255]);
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-formats-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-formats-test.html
new file mode 100644
index 0000000000..863ab53a0b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-formats-test.html
@@ -0,0 +1,274 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Texture Format Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/desktop-gl-constants.js"></script>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas2d" width="2" height="2" style="width: 50px; height: 50px; border: 1px solid black;"></canvas>
+<canvas id="canvas" width="2" height="2" style="width: 100px; height:100px; border: 1px solid black;"></canvas>
+<script>
+"use strict";
+description("This test ensures WebGL implementations allow the OpenGL ES 2.0 texture formats and do not allow DesktopGL texture formats.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking texture formats.");
+
+ var createTexture = function(internalFormat, format, opt_border) {
+ var border = (opt_border === undefined) ? 0 : opt_border;
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ internalFormat, // internalFormat
+ 16, // width
+ 16, // height
+ border, // border
+ format, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ }
+
+ var testValidFormat = function(internalFormat, formatName) {
+ createTexture(internalFormat, internalFormat);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "was able to create texture of " + formatName);
+ }
+
+ var testInvalidFormat = function(internalFormat, formatName) {
+ createTexture(internalFormat, internalFormat);
+ var err = gl.getError();
+ if (err == gl.NO_ERROR) {
+ testFailed("should NOT be able to create texture of type " + formatName);
+ } else if (err == gl.INVALID_ENUM || err == gl.INVALID_VALUE) {
+ testPassed("not able to create invalid format: " + formatName);
+ }
+ }
+
+ var invalidEnums = [
+ '1',
+ '2',
+ '3',
+ '4',
+ 'RGB4',
+ 'RGB5',
+ 'RGB8',
+ 'RGB10',
+ 'RGB12',
+ 'RGB16',
+ 'RGBA2',
+ 'RGBA4',
+ 'RGB5_A1',
+ 'RGBA8',
+ 'RGB10_A2',
+ 'RGBA12',
+ 'RGBA16',
+ 'BGR',
+ 'BGRA',
+ 'ALPHA4_EXT',
+ 'ALPHA8_EXT',
+ 'ALPHA12_EXT',
+ 'ALPHA16_EXT',
+ 'COMPRESSED_ALPHA',
+ 'COMPRESSED_LUMINANCE',
+ 'COMPRESSED_LUMINANCE_ALPHA',
+ 'COMPRESSED_INTENSITY',
+ 'COMPRESSED_RGB',
+ 'COMPRESSED_RGBA',
+ 'DEPTH_COMPONENT16',
+ 'DEPTH_COMPONENT24',
+ 'DEPTH_COMPONENT32',
+ 'LUMINANCE4_EXT',
+ 'LUMINANCE8_EXT',
+ 'LUMINANCE12_EXT',
+ 'LUMINANCE16_EXT',
+ 'LUMINANCE4_ALPHA4_EXT',
+ 'LUMINANCE6_ALPHA2_EXT',
+ 'LUMINANCE8_ALPHA8_EXT',
+ 'LUMINANCE12_ALPHA4_EXT',
+ 'LUMINANCE12_ALPHA12_EXT',
+ 'LUMINANCE16_ALPHA16_EXT',
+ 'INTENSITY_EXT',
+ 'INTENSITY4_EXT',
+ 'INTENSITY8_EXT',
+ 'INTENSITY12_EXT',
+ 'INTENSITY16_EXT',
+ 'RGB4_EXT',
+ 'RGB5_EXT',
+ 'RGB8_EXT',
+ 'RGB10_EXT',
+ 'RGB12_EXT',
+ 'RGB16_EXT',
+ 'RGBA2_EXT',
+ 'RGBA4_EXT',
+ 'RGB5_A1_EXT',
+ 'RGBA8_EXT',
+ 'RGB10_A2_EXT',
+ 'RGBA12_EXT',
+ 'RGBA16_EXT',
+ 'SLUMINANCE_EXT',
+ 'SLUMINANCE8_EXT',
+ 'SLUMINANCE_ALPHA_EXT',
+ 'SLUMINANCE8_ALPHA8_EXT',
+ 'SRGB_EXT',
+ 'SRGB8_EXT',
+ 'SRGB_ALPHA_EXT',
+ 'SRGB8_ALPHA8'
+ ];
+
+ for (var ii = 0; ii < invalidEnums.length; ++ii) {
+ var formatName = invalidEnums[ii]
+ if (desktopGL[formatName] === undefined) {
+ debug("bad format" + formatName)
+ } else {
+ testInvalidFormat(desktopGL[formatName], "GL_" + formatName);
+ }
+ }
+
+ var validEnums = [
+ 'ALPHA',
+ 'RGB',
+ 'RGBA',
+ 'LUMINANCE',
+ 'LUMINANCE_ALPHA'
+ ];
+
+ for (var ii = 0; ii < validEnums.length; ++ii) {
+ var formatName = validEnums[ii]
+ testValidFormat(gl[formatName], "gl." + formatName);
+ }
+
+ debug("");
+ debug("checking non 0 border parameter to gl.TexImage2D");
+ createTexture(gl['RGBA'], gl['RGBA'], 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "non 0 border to gl.TexImage2D should return INVALID_VALUE");
+
+
+ var checkTypes = function() {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+
+ var checkType = function(r, g, b, a, type, format, buf) {
+ var typeName = wtu.glEnumToString(gl, type);
+ var formatName = wtu.glEnumToString(gl, format);
+ var desc = "format: " + formatName + ", type: " + typeName;
+ debug("");
+ debug("checking gl.texImage2D with " + desc + " and buffer type " +
+ buf.constructor.name);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ format, // internalFormat
+ 2, // width
+ 2, // height
+ 0, // border
+ format, // format
+ type, // type
+ buf); // data
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D with " + desc + " should generate NO_ERROR");
+
+ wtu.clearAndDrawUnitQuad(gl, [255, 0, 0, 255]);
+ wtu.checkCanvas(gl, [r,g,b,a],
+ "texture " + desc + " should draw with " +
+ r + ", " + g + ", " + b + ", " + a);
+
+ }
+ checkType(
+ 0, 255, 0, 255, gl.UNSIGNED_BYTE, gl.RGBA,
+ new Uint8Array(
+ [ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]));
+ checkType(
+ 0, 255, 0, 255, gl.UNSIGNED_BYTE, gl.RGBA,
+ new Uint8ClampedArray(
+ [ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]));
+ checkType(
+ 0, 0, 255, 255, gl.UNSIGNED_SHORT_4_4_4_4, gl.RGBA,
+ new Uint16Array(
+ [ 255, 255,
+ 255, 255,
+ 255, 255,
+ 255, 255]));
+ checkType(
+ 0, 255, 0, 255, gl.UNSIGNED_SHORT_5_6_5, gl.RGB,
+ new Uint16Array(
+ [ 2016, 2016,
+ 2016, 2016,
+ 2016, 2016,
+ 2016, 2016]));
+ checkType(
+ 0, 0, 255, 255, gl.UNSIGNED_SHORT_5_5_5_1, gl.RGBA,
+ new Uint16Array(
+ [ 63, 63,
+ 63, 63,
+ 63, 63,
+ 63, 63]));
+ checkType(
+ 255, 255, 255, 255, gl.UNSIGNED_BYTE, gl.LUMINANCE,
+ new Uint8Array([
+ 255,
+ 255,
+ 255,
+ 255]));
+ checkType(
+ 0, 0, 0, 128, gl.UNSIGNED_BYTE, gl.ALPHA,
+ new Uint8Array([
+ 128,
+ 128,
+ 128,
+ 128]));
+ checkType(
+ 128, 128, 128, 192, gl.UNSIGNED_BYTE, gl.LUMINANCE_ALPHA,
+ new Uint8Array([
+ 128, 192,
+ 128, 192,
+ 128, 192,
+ 128, 192]));
+ }
+ var program = wtu.setupTexturedQuad(gl);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+ checkTypes();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-hd-dpi.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-hd-dpi.html
new file mode 100644
index 0000000000..5126fad9f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-hd-dpi.html
@@ -0,0 +1,117 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL HD-DPI issues texture conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+function fillInMips(gl, size) {
+ // fill in the mips
+ var level = 1;
+ for (;;) {
+ size /= 2;
+ if (size < 1) {
+ break;
+ }
+ var numBytes = size * size * 4;
+ var pixels = new Uint8Array(numBytes);
+ for (var jj = 0; jj < numBytes; jj += 4) {
+ pixels[jj + 0] = 0;
+ pixels[jj + 1] = 255;
+ pixels[jj + 2] = 0;
+ pixels[jj + 3] = 255;
+ }
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ }
+}
+
+function testCanvas(size) {
+ debug("");
+ debug("testing 2D canvas size " + size + ", " + size);
+
+ var canvas = document.createElement("canvas");
+ canvas.width = size;
+ canvas.height = size;
+ var ctx = canvas.getContext("2d");
+ ctx.fillStyle = "rgb(0,255,0)";
+ ctx.fillRect(0, 0, size, size);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+
+ fillInMips(gl, size);
+
+ // Draw. If this an HD-DPI device and the 2d canvas is double res or larger
+ // the implementation must scale to CSS pixels (ie, canvas.width, canvas.height)(
+ // when doing the copy in texImage2D. If it has not scaled and instead done
+ // a direct copy of the larger texture this test will not have created enough mips
+ // and will therefore not be "texture complete" and will render in black.
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function testWebGL(size) {
+ debug("");
+ debug("testing WebGL canvas size " + size + ", " + size);
+
+ var canvas = document.createElement("canvas");
+ canvas.width = size;
+ canvas.height = size;
+ var gl2 = wtu.create3DContext(canvas);
+ gl2.clearColor(0,1,0,1);
+ gl2.clear(gl.COLOR_BUFFER_BIT);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+
+ fillInMips(gl, size);
+
+ // Draw. If this an HD-DPI device check for 2 possible bugs.
+ //
+ // 1) the WebGL canvas is double res or larger. That's just a bug period and
+ // is checked for in another test but would also fail here.
+ //
+ // 2) the WebGL canvas is single res but the code the scales a double res
+ // 2d canvas also mistakenly scales a single res WebGL canvas.
+ //
+ // If it has been scaled then we'll have the wrong kind of mips chain here.
+ // Level 0 will be half resolution. Level 1 will be the same resolution
+ // and will therefore not be "texture complete" and will render in black.
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+testCanvas(4);
+testCanvas(512);
+testWebGL(4);
+testWebGL(512);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-mips.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-mips.html
new file mode 100644
index 0000000000..6f038b8475
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-mips.html
@@ -0,0 +1,297 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture mips conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+uniform vec4 uMult;
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition * uMult;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+<script>
+"use strict";
+var canvas;
+var wtu = WebGLTestUtils;
+function init()
+{
+ description("Checks mip issues");
+
+ canvas = document.getElementById("example");
+ shouldBe("canvas.width", "2");
+ shouldBe("canvas.height", "2");
+
+ var gl = wtu.create3DContext(canvas);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "for generateMipmap with mip 0 is 0x0");
+ gl.texImage2D(
+ gl.TEXTURE_2D, 1, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4));
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "for generateMipmap with mip 0 is 0x0");
+
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "for generateMipmap with mip 0 is 0x0");
+
+ var faces = [
+ 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 ii = 0; ii < faces.length; ++ii) {
+ gl.texImage2D(
+ faces[ii], 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(4 * 2 * 2));
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ wtu.glErrorShouldBe(gl, ii == 5 ? gl.NO_ERROR : gl.INVALID_OPERATION, "for generateMipmap with " + (ii + 1) + " faces");
+ }
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ var colors = {
+ blue: [0, 0, 255, 255],
+ red: [255, 0, 0, 255],
+ green: [0, 255, 0, 255],
+ cyan: [128, 255, 255, 255],
+ black: [0, 0, 0, 255],
+ blank: [0, 0, 0, 0]
+ };
+
+ var mips = [
+ ];
+
+ var texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+ var multLoc = gl.getUniformLocation(program, "uMult");
+
+ // ----------------------------------------------------
+ var clearTex = createTexture();
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+ gl.bindTexture(gl.TEXTURE_2D, clearTex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ debug('gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);');
+ setMipData(0, 16, 'blank');
+ makeDivMipChain();
+ generateMipmap();
+ check('blank', "texture created with null that has all mips");
+
+ // ----------------------------------------------------
+ var tex = createTexture();
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ // 16x16 texture no mips
+ fillLevel(tex, 0, 16, 'cyan');
+
+ check('black',
+ "texture that is missing mips when TEXTURE_MIN_FILTER not NEAREST or LINEAR");
+
+ generateMipmap();
+
+ check('cyan', "texture that has all mips");
+
+ // Fill in the bottom 2 mips with a different color.
+ fillLevel(tex, 4, 1, 'green');
+ fillLevel(tex, 3, 2, 'green');
+
+ // Choose the nearest mip
+ texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+
+ check('green', "texture that is only using the smallest 2 mips");
+
+ gl.uniform4f(multLoc, 16, 16, 1, 1);
+
+ check('cyan', "texture that is using only the largest 2 mips");
+
+ // Set the top level
+ fillLevel(tex, 0, 1, 'red');
+ check('red',
+ "texture that is only using the top level even though other levels are defined");
+
+ // Set the top 2 levels using generateMipmap
+ fillLevel(tex, 0, 2, 'blue');
+ generateMipmap();
+
+ check('blue',
+ "texture that is only using the top 2 levels even though other levels are defined");
+
+ // Set the top 2 levels back to sizes that end up using levels 2, 3, and 4 again.
+ fillLevel(tex, 0, 16, 'blue');
+ fillLevel(tex, 1, 8, 'blue');
+ check('blue', "texture that is only using the largest 2 mips");
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+ check('green', "texture that is only using the smallest 2 mips");
+
+ // ----------------------------------------------------
+ var tex = createTexture();
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+ fillLevel(tex, 0, 8, 'cyan');
+ generateMipmap();
+ check('cyan', "texture that has 3 mips");
+
+ fillLevel(tex, 0, 16, 'blue');
+ texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ check('blue', "texture that is only using top mips");
+
+ fillLevel(tex, 0, 8, 'red');
+ texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+ check('cyan', "texture that is only using smallest mips");
+
+ gl.uniform4f(multLoc, 16, 16, 1, 1);
+ check('red', "texture that is using only the largest mip");
+
+ // ----------------------------------------------------
+ var tex = createTexture();
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+ fillLevel(tex, 2, 1, 'green');
+ fillLevel(tex, 1, 2, 'green');
+ fillLevel(tex, 0, 4, 'green');
+ check('green', "texture that was built smallest mip first");
+
+ // ----------------------------------------------------
+ var tex = createTexture();
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+ fillLevel(tex, 0, 16, 'red');
+ generateMipmap();
+ check('red', "texture with 1 genmipmaps");
+ fillLevel(tex, 0, 16, 'blue');
+ generateMipmap();
+ fillLevel(tex, 0, 16, 'green');
+ generateMipmap();
+ check('green', "texture with 2 genmipmaps");
+
+ // ----------------------------------------------------
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+ function createTexture() {
+ debug("<hr/>gl.createTexture()");
+ mips = [];
+ makeDivMipChain();
+ return gl.createTexture();
+ }
+
+ function texParameteri(target, pname, value) {
+ debug("gl.texParameteri(" +
+ wtu.glEnumToString(gl, target) + ", " +
+ wtu.glEnumToString(gl, pname) + ", " +
+ wtu.glEnumToString(gl, value) + ")")
+ gl.texParameteri(target, pname, value);
+ }
+
+ function generateMipmap() {
+ debug("gl.generateMipmap(gl.TEXTURE_2D)");
+ gl.generateMipmap(gl.TEXTURE_2D);
+ var mip0 = mips[0];
+ var size = mip0.size;
+ var level = 1;
+ for(;;) {
+ size = Math.floor(size / 2);
+ if (!size) {
+ break;
+ }
+ setMipData(level, size, mip0.color);
+ ++level;
+ }
+ makeDivMipChain();
+ }
+
+ function check(color, msg) {
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, colors[color], msg + " should draw with " + color);
+ }
+
+ function fillLevel(tex, level, size, color) {
+ setMipData(level, size, color);
+ debug("gl.texImage2D(gl.TEXTURE_2D, " + level + ", gl.RGBA, " + size + ", " + size +
+ ", 0, gl.RGBA, gl.UNSIGNED_BYTE, " + color + ");");
+ wtu.fillTexture(gl, tex, size, size, colors[color], level);
+ makeDivMipChain();
+ }
+
+ function setMipData(level, size, color) {
+ mips[level] = {
+ size: size,
+ color: color
+ };
+ }
+
+ function makeDivMipChain(color) {
+ var html = [
+ '<div style="height: 68px; margin-top: 5px">',
+ '<div style="float:left;">mips: </div>'];
+ for (var ii = 0; ii < 5; ++ii) {
+ var mip = mips[ii];
+ if (mip) {
+ html.push(makeDivSquare(mip.size, mip.color));
+ } else {
+ html.push(makeDivSquare(16, undefined));
+ }
+ }
+ html.push("</div>");
+ debug(html.join(""));
+ }
+
+ function makeDivSquare(size, color) {
+ size *= 4;
+ var c = color ? colors[color] : [255,255,255];
+ var border = color ? 'solid' : 'dashed';
+ return '<div style="float:left; width: ' + size + 'px; height: ' + size +
+ 'px; background-color: ' + rgb(c) +
+ '; border: 1px ' + border + ' black; margin-right: 3px;"></div>';
+ }
+
+ function rgb(c) {
+ return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] +')';
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot-video.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot-video.html
new file mode 100644
index 0000000000..ef979d4c5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot-video.html
@@ -0,0 +1,160 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = null;
+var textureLoc = null;
+var successfullyParsed = false;
+
+initTestingHarness();
+
+function logVisibility(isOnload)
+{
+ let prefix = '';
+ if (isOnload)
+ prefix = 'Upon load: ';
+ if (document.hidden) {
+ console.log(prefix + '*** Tab was backgrounded (if running in automated test harness, why?) ***');
+ } else {
+ console.log(prefix + 'Tab was foregrounded');
+ }
+}
+
+function init()
+{
+ description('Verify npot video');
+
+ document.addEventListener("visibilitychange", visibilityChanged, false);
+
+ logVisibility(true);
+
+ var canvas = document.getElementById("example");
+ gl = wtu.create3DContext(canvas);
+ var program = wtu.setupTexturedQuad(gl);
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+
+ textureLoc = gl.getUniformLocation(program, "tex");
+
+ var video = document.getElementById("vid");
+ wtu.startPlayingAndWaitForVideo(video, runTest);
+}
+
+function visibilityChanged() {
+ logVisibility(false);
+}
+
+function runOneIteration(videoElement, useTexSubImage2D, flipY, topColor, bottomColor, badMinFilter, badClamp, genMips)
+{
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ // Upload the videoElement into the texture
+ debug("size: " + videoElement.videoWidth + "x" + videoElement.videoHeight);
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
+ videoElement.videoWidth, videoElement.videoHeight, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
+ } else {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
+ }
+
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ if (badMinFilter) {
+ debug("bad min filter");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+ } else {
+ debug("good min filter");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ }
+ if (badClamp) {
+ debug("bad clamp");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+ } else {
+ debug("good clamp");
+ 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);
+ }
+ if (genMips) {
+ debug("generate mips");
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should be INVALID_OPERATION");
+ }
+
+// 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);
+
+ // Point the uniform sampler to texture unit 0
+ gl.uniform1i(textureLoc, 0);
+ // 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);
+ debug("");
+}
+
+function runTest(videoElement)
+{
+ var red = [255, 0, 0];
+ var green = [0, 255, 0];
+ var black = [0, 0, 0];
+ runOneIteration(videoElement, false, true, black, black, true, true, true);
+ runOneIteration(videoElement, false, true, black, black, true, false, false);
+ runOneIteration(videoElement, false, true, black, black, false, true, false);
+ runOneIteration(videoElement, false, true, black, black, true, true, false);
+ runOneIteration(videoElement, false, true, green, red, false, false, false);
+ runOneIteration(videoElement, false, false, red, green, false, false, false);
+ runOneIteration(videoElement, true, true, green, red, false, false, false);
+ runOneIteration(videoElement, true, false, red, green, false, false, false);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="example" width="64" height="48"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<video id="vid" style="display:none;" muted>
+ <source src="../../../resources/npot-video.mp4" type='video/mp4; codecs="avc1.42E01E"' />
+ <source src="../../../resources/npot-video.webmvp8.webm" type='video/webm; codecs="vp8"' />
+ <source src="../../../resources/npot-video.theora.ogv" type='video/ogg; codecs="theora"' />
+</video>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot.html
new file mode 100644
index 0000000000..73ea4011f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-npot.html
@@ -0,0 +1,305 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Non-Power of 2 texture conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform samplerCube tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = textureCube(tex, normalize(vec3(texCoord, 1)));
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var tests = [
+ { format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ color: [192, 0, 128, 64],
+ expected: [192, 0, 128, 64],
+ tolerance: 0,
+ },
+ { format: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ color: [192, 0, 128],
+ expected: [192, 0, 128, 255],
+ tolerance: 0,
+ },
+ { format: gl.LUMINANCE,
+ type: gl.UNSIGNED_BYTE,
+ color: [192],
+ expected: [192, 192, 192, 255],
+ tolerance: 0,
+ },
+ { format: gl.ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ color: [64],
+ expected: [0, 0, 0, 64],
+ tolerance: 0,
+ },
+ { format: gl.LUMINANCE_ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ color: [192, 64],
+ expected: [192, 192, 192, 64],
+ tolerance: 0,
+ },
+ // { format: gl.RGBA,
+ // type: gl.UNSIGNED_SHORT_4_4_4_4,
+ // color: [0x48FC],
+ // expected: [0x44, 0x88, 0xFF, 0xCC],
+ // tolerance: 16,
+ // },
+ // { format: gl.RGBA,
+ // type: gl.UNSIGNED_SHORT_5_5_5_1,
+ // color: [0x8309], // 10000 01000 00100 1
+ // expected: [128, 64, 32, 255],
+ // tolerance: 16,
+ // },
+ // { format: gl.RGB,
+ // type: gl.UNSIGNED_SHORT_5_6_5,
+ // color: [0x8404], // 10000 010000 00100
+ // expected: [128, 64, 32],
+ // tolerance: 16,
+ // },
+];
+
+tests.forEach(function(test) {
+ debug("");
+ debug("test " + wtu.glEnumToString(gl, test.format) + "/" + wtu.glEnumToString(gl, test.type));
+ var tex = gl.createTexture();
+
+ // Check that an NPOT texture not on level 0 generates INVALID_VALUE
+ wtu.fillTexture(gl, tex, 5, 3, test.color, 1, test.format, test.type);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl.texImage2D with NPOT texture with level > 0 should return INVALID_VALUE");
+
+ // Check that an NPOT texture on level 0 succeeds
+ wtu.fillTexture(gl, tex, 5, 3, test.color, 0, test.format, test.type);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D with NPOT texture at level 0 should succeed");
+
+ // Check that generateMipmap fails on NPOT
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "gl.generateMipmap with NPOT texture should return INVALID_OPERATION");
+
+ // Check that nothing is drawn if filtering is not correct for NPOT
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 0, 0, 255],
+ "NPOT texture with TEXTURE_WRAP set to REPEAT should draw with 0,0,0,255");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 0, 0, 255],
+ "NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, test.expected,
+ "NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw.");
+
+ gl.copyTexImage2D(gl.TEXTURE_2D, 1, test.format, 0, 0, 5, 3, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "copyTexImage2D with NPOT texture with level > 0 should return INVALID_VALUE.");
+
+ // Check that generateMipmap for an POT texture succeeds
+ wtu.fillTexture(gl, tex, 4, 4, test.color, 0, test.format);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D and gl.generateMipmap with POT texture at level 0 should succeed");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, test.expected,
+ "POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw.");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+});
+
+var testCubemap = function(switchTextureUnitBeforeDraw) {
+ debug("");
+ var title = "check using cubemap";
+ if (switchTextureUnitBeforeDraw) {
+ title += " and switch texture unit before draw to check for Chromium bug";
+ }
+ debug(title);
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+ var tex = gl.createTexture();
+
+ // Check that an NPOT texture not on level 0 generates INVALID_VALUE
+ fillCubeTexture(gl, tex, 5, 3, [0, 192, 128, 255], 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl.texImage2D with NPOT texture with level > 0 should return INVALID_VALUE");
+
+ // Check that an NPOT texture on level 0 succeeds
+ fillCubeTexture(gl, tex, 5, 5, [0, 192, 128, 255]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D with NPOT texture at level 0 should succeed");
+
+ // Check that generateMipmap fails on NPOT
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "gl.generateMipmap with NPOT texture should return INVALID_OPERATION");
+
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+
+ // Check that nothing is drawn if filtering is not correct for NPOT
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ if (switchTextureUnitBeforeDraw) {
+ debug("Switching active texture unit to gl.TEXTURE1");
+ // Test for http://crbug.com/390514
+ gl.activeTexture(gl.TEXTURE1);
+ }
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 0, 0, 255],
+ "NPOT cubemap with TEXTURE_WRAP set to REPEAT should draw with 0,0,0,255");
+
+ if (switchTextureUnitBeforeDraw) {
+ var error = gl.getError();
+ if (error === gl.NO_ERROR) {
+ testPassed("getError was expected value: NO_ERROR : Should be no errors from draw.");
+ } else if (error === gl.INVALID_ENUM) {
+ testFailed("getError returned INVALID_ENUM. Possibly Chromium bug where texture unit is set to 0 instead of GL_TEXTURE0.");
+ } else {
+ testFailed("Drawing resulted in error: " + wtu.glEnumToString(gl, error));
+ }
+ gl.activeTexture(gl.TEXTURE0);
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from draw.");
+ }
+
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 0, 0, 255],
+ "NPOT cubemap with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 192, 128, 255],
+ "NPOT cubemap with TEXTURE_MIN_FILTER set to LINEAR should draw.");
+
+ // Check that an POT texture on level 0 succeeds
+ fillCubeTexture(gl, tex, 4, 4, [0, 192, 128, 255]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D with POT texture at level 0 should succeed");
+
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 0, 0, 255],
+ "POT cubemap with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR but no mips draw with 0,0,0,255");
+
+ // Check that generateMipmap succeeds on POT
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.generateMipmap with POT texture should return succeed");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, [0, 192, 128, 255],
+ "POT cubemap with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw.");
+};
+
+testCubemap(false);
+testCubemap(true);
+
+var successfullyParsed = true;
+
+function fillCubeTexture(gl, tex, width, height, color, opt_level) {
+ opt_level = opt_level || 0;
+ var canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ var ctx2d = canvas.getContext('2d');
+ ctx2d.fillStyle = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + color[3] + ")";
+ ctx2d.fillRect(0, 0, width, height);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ 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], opt_level, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+ }
+};
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-cube-maps.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-cube-maps.html
new file mode 100644
index 0000000000..c38d897e18
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-cube-maps.html
@@ -0,0 +1,331 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture size cube map conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="256" height="256" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+uniform mat4 rotation;
+varying vec3 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ vec4 direction = vec4(vPosition.x * 0.5, vPosition.y * 0.5, 1, 1);
+ texCoord = normalize((rotation * direction).xyz);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform samplerCube tex;
+varying vec3 texCoord;
+void main()
+{
+ gl_FragColor = textureCube(tex, normalize(texCoord));
+}
+</script>
+<script>
+"use strict";
+var canvas;
+description("Checks issues with size of cube map textures");
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+
+var gl = wtu.create3DContext(canvas);
+wtu.setupUnitQuad(gl, 0, 1);
+var program = wtu.setupProgram(
+ gl,
+ ['vshader', 'fshader'],
+ ['vPosition', 'texCoord0'], [0, 1]);
+var rotLoc = gl.getUniformLocation(program, "rotation");
+
+gl.disable(gl.DEPTH_TEST);
+gl.disable(gl.BLEND);
+
+var maxSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
+debug("max cube map size: " + maxSize);
+maxSize = Math.min(512, maxSize);
+
+// a cube map of 512x512 takes 6meg. I'm assuming it's not
+// unreasonable to expect to be able to allocate a 6meg texture
+
+var colors = [
+ {name: 'red', color: [255, 0, 0, 255]},
+ {name: 'green', color: [ 0, 255, 0, 255]},
+ {name: 'blue', color: [ 0, 0, 255, 255]},
+ {name: 'yellow', color: [255, 255, 0, 255]},
+ {name: 'cyan', color: [ 0, 255, 255, 255]},
+ {name: 'magenta', color: [255, 0, 255, 255]}
+];
+
+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];
+
+var rotations = [
+ {axis: [0, 1, 0], angle: Math.PI / 2},
+ {axis: [0, 1, 0], angle: -Math.PI / 2},
+ {axis: [1, 0, 0], angle: -Math.PI / 2},
+ {axis: [1, 0, 0], angle: Math.PI / 2},
+ {axis: [0, 1, 0], angle: 0},
+ {axis: [0, 1, 0], angle: Math.PI},
+];
+
+var halfRotations = [
+ {colors: [3, 4], rotations: [{axis: [1, 0, 0], angle: Math.PI / 4}]},
+ {colors: [4, 2], rotations: [{axis: [1, 0, 0], angle: -Math.PI / 4}]},
+ {colors: [5, 3], rotations: [{axis: [1, 0, 0], angle: Math.PI / 4 * 3}]},
+ {colors: [2, 5], rotations: [{axis: [1, 0, 0], angle: -Math.PI / 4 * 3}]},
+ {colors: [3, 0], rotations: [{axis: [0, 1, 0], angle: Math.PI / 2},
+ {axis: [1, 0, 0], angle: Math.PI / 4}]},
+ {colors: [0, 2], rotations: [{axis: [0, 1, 0], angle: Math.PI / 2},
+ {axis: [1, 0, 0], angle: -Math.PI / 4}]},
+];
+
+var count = 0;
+var sizeCount = 0;
+
+test();
+
+function test() {
+ var size = Math.pow(2, sizeCount);
+ if (size > maxSize || !testSize(size)) {
+ finishTest();
+ } else {
+ ++sizeCount;
+ setTimeout(test, 0);
+ }
+}
+
+function testSize(size) {
+ debug("");
+ debug("testing size: " + size);
+ var canvasSize = Math.max(size / 4, 2);
+ canvas.width = canvasSize;
+ canvas.height = canvasSize;
+ gl.viewport(0, 0, canvasSize, canvasSize);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+
+ // Seems like I should be using LINEAR here with some other math
+ // to make sure I get more mip coverage but that's easier said
+ // than done.
+
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ for (var jj = 0; jj < 2; ++jj) {
+ for (var tt = 0; tt < targets.length; ++tt) {
+ var color = colors[(tt + count) % colors.length];
+ fillLevel(targets[tt], 0, size, color.color);
+ }
+ if (jj == 1) {
+ debug("use mipmap");
+ gl.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER,
+ gl.NEAREST_MIPMAP_NEAREST);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ }
+
+ var err = gl.getError();
+ if (err == gl.OUT_OF_MEMORY) {
+ debug("out of memory");
+ return false;
+ }
+ if (err != gl.NO_ERROR) {
+ testFailed("unexpected gl error: " + wtu.glEnumToString(gl, err));
+ }
+
+
+ for (var rr = 0; rr < rotations.length; ++rr) {
+ var rot = rotations[rr];
+ var color = colors[(rr + count) % colors.length];
+ var rotMat = axisRotation(rot.axis, rot.angle);
+ gl.uniformMatrix4fv(rotLoc, false, rotMat);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, color.color,
+ wtu.glEnumToString(gl, targets[rr]) + " should be " + color.name);
+ }
+
+ for (var rr = 0; rr < halfRotations.length; ++rr) {
+ var h = halfRotations[rr];
+ var rots = h.rotations;
+ var rotMat = axisRotation(rots[0].axis, rots[0].angle);
+ for (var ii = 1; ii < rots.length; ++ii) {
+ var tmpMat = axisRotation(rots[ii].axis, rots[ii].angle);
+ var rotMat = mulMatrix(tmpMat, rotMat);
+ }
+ gl.uniformMatrix4fv(rotLoc, false, rotMat);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ for (var ii = 0; ii < 2; ++ii) {
+ checkRect(
+ 0,
+ canvasSize / 2 * ii,
+ canvasSize,
+ canvasSize / 2,
+ colors[(h.colors[ii] + count) % colors.length]);
+ }
+ }
+ ++count;
+ }
+
+ gl.deleteTexture(tex);
+ return true;
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+function checkRect(x, y, width, height, color) {
+ wtu.checkCanvasRect(
+ gl,
+ x,
+ y,
+ width,
+ height,
+ color.color,
+ "" + x + ", " + y + ", " + width + ", " + height +
+ " should be " + color.name);
+}
+
+function fillLevel(target, level, size, color) {
+ var numPixels = size * size;
+ var pixels = new Uint8Array(numPixels * 4);
+ var pixelRow = new Uint8Array(size * 4);
+ for (var jj = 0; jj < size; ++jj) {
+ var off = jj * 4;
+ pixelRow[off + 0] = color[0];
+ pixelRow[off + 1] = color[1];
+ pixelRow[off + 2] = color[2];
+ pixelRow[off + 3] = color[3];
+ }
+ for (var jj = 0; jj < size; ++jj) {
+ var off = jj * size * 4;
+ pixels.set(pixelRow, off);
+ }
+ gl.texImage2D(
+ target, level, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ pixels);
+}
+
+function printMat(mat) {
+ debug("" + mat[0] + ", " + mat[1] + ", " + mat[2] + ", " + mat[3] + ", ");
+ debug("" + mat[4] + ", " + mat[5] + ", " + mat[6] + ", " + mat[7] + ", ");
+ debug("" + mat[8] + ", " + mat[9] + ", " + mat[10] + ", " + mat[11] + ", ");
+ debug("" + mat[12] + ", " + mat[13] + ", " + mat[14] + ", " + mat[15] + ", ");
+}
+
+function axisRotation(axis, angle) {
+ var dst = new Float32Array(16);
+ var x = axis[0];
+ var y = axis[1];
+ var z = axis[2];
+ var n = Math.sqrt(x * x + y * y + z * z);
+ x /= n;
+ y /= n;
+ z /= n;
+ var xx = x * x;
+ var yy = y * y;
+ var zz = z * z;
+ var c = Math.cos(angle);
+ var s = Math.sin(angle);
+ var oneMinusCosine = 1 - c;
+
+ dst[ 0] = xx + (1 - xx) * c;
+ dst[ 1] = x * y * oneMinusCosine + z * s;
+ dst[ 2] = x * z * oneMinusCosine - y * s;
+ dst[ 3] = 0;
+ dst[ 4] = x * y * oneMinusCosine - z * s;
+ dst[ 5] = yy + (1 - yy) * c;
+ dst[ 6] = y * z * oneMinusCosine + x * s;
+ dst[ 7] = 0;
+ dst[ 8] = x * z * oneMinusCosine + y * s;
+ dst[ 9] = y * z * oneMinusCosine - x * s;
+ dst[10] = zz + (1 - zz) * c;
+ dst[11] = 0;
+ dst[12] = 0;
+ dst[13] = 0;
+ dst[14] = 0;
+ dst[15] = 1;
+
+ return dst;
+};
+
+function mulMatrix(a, b) {
+ var dst = new Float32Array(16);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a10 = a[ 4 + 0];
+ var a11 = a[ 4 + 1];
+ var a12 = a[ 4 + 2];
+ var a13 = a[ 4 + 3];
+ var a20 = a[ 8 + 0];
+ var a21 = a[ 8 + 1];
+ var a22 = a[ 8 + 2];
+ var a23 = a[ 8 + 3];
+ var a30 = a[12 + 0];
+ var a31 = a[12 + 1];
+ var a32 = a[12 + 2];
+ var a33 = a[12 + 3];
+ var b00 = b[0];
+ var b01 = b[1];
+ var b02 = b[2];
+ var b03 = b[3];
+ var b10 = b[ 4 + 0];
+ var b11 = b[ 4 + 1];
+ var b12 = b[ 4 + 2];
+ var b13 = b[ 4 + 3];
+ var b20 = b[ 8 + 0];
+ var b21 = b[ 8 + 1];
+ var b22 = b[ 8 + 2];
+ var b23 = b[ 8 + 3];
+ var b30 = b[12 + 0];
+ var b31 = b[12 + 1];
+ var b32 = b[12 + 2];
+ var b33 = b[12 + 3];
+ dst[ 0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
+ dst[ 1] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
+ dst[ 2] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
+ dst[ 3] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
+ dst[ 4] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
+ dst[ 5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
+ dst[ 6] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
+ dst[ 7] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
+ dst[ 8] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
+ dst[ 9] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
+ dst[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
+ dst[11] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
+ dst[12] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
+ dst[13] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
+ dst[14] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
+ dst[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
+ return dst;
+};
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-limit.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-limit.html
new file mode 100644
index 0000000000..3e093b3a53
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size-limit.html
@@ -0,0 +1,167 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture size limit conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Checks various size limits of textures")
+var canvas;
+
+function numLevelsFromSize(size) {
+ var levels = 0;
+ while ((size >> levels) > 0) {
+ ++levels;
+ }
+ return levels;
+}
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var tests = [
+ { format: gl.ALPHA, type: gl.UNSIGNED_BYTE, size: 1, dataType: Uint8Array },
+ { format: gl.LUMINANCE, type: gl.UNSIGNED_BYTE, size: 1, dataType: Uint8Array },
+ { format: gl.LUMINANCE_ALPHA, type: gl.UNSIGNED_BYTE, size: 2, dataType: Uint8Array },
+ { format: gl.RGB, type: gl.UNSIGNED_BYTE, size: 3, dataType: Uint8Array },
+ { format: gl.RGB, type: gl.UNSIGNED_SHORT_5_6_5, size: 1, dataType: Uint16Array },
+ { format: gl.RGBA, type: gl.UNSIGNED_BYTE, size: 4, dataType: Uint8Array },
+ { format: gl.RGBA, type: gl.UNSIGNED_SHORT_4_4_4_4, size: 1, dataType: Uint16Array },
+ { format: gl.RGBA, type: gl.UNSIGNED_SHORT_5_5_5_1, size: 1, dataType: Uint16Array }
+];
+
+// Note: We expressly only use 2 textures because first a texture will be defined
+// using all mip levels of 1 format, then for a moment it will have mixed formats which
+// may uncover bugs.
+var targets = [
+ { target: gl.TEXTURE_2D,
+ maxSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),
+ maxLevel: 1000,
+ targets: [gl.TEXTURE_2D]
+ },
+ { target: gl.TEXTURE_CUBE_MAP,
+ maxSize: gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE),
+ maxLevel: 5,
+ 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
+ ]
+ }
+];
+
+gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+var trg = 0;
+var tt = 0;
+var tex = null;
+runNextTest();
+
+function runNextTest() {
+ var t = targets[trg];
+
+ if (tt == 0) {
+ gl.deleteTexture(tex);
+ tex = gl.createTexture();
+ gl.bindTexture(t.target, tex);
+
+ debug("");
+ debug("max size for " + wtu.glEnumToString(gl, t.target) + ": " + t.maxSize);
+ var numLevels = numLevelsFromSize(t.maxSize);
+ debug("num levels " + numLevels);
+ }
+
+ var test = tests[tt];
+ testFormatType(t, test);
+ ++tt;
+ if (tt == tests.length) {
+ tt = 0;
+ ++trg;
+ if (trg == targets.length) {
+ finishTest();
+ return;
+ }
+ }
+ wtu.dispatchPromise(runNextTest);
+}
+
+function testFormatType(t, test) {
+ debug("");
+ debug("testing: " + wtu.glEnumToString(gl, test.format) + ", " + wtu.glEnumToString(gl, test.type));
+
+ for (var j = 0; j < t.targets.length; ++j) {
+ var target = t.targets[j];
+ debug("");
+ debug(wtu.glEnumToString(gl, target));
+ var numLevels = numLevelsFromSize(t.maxSize);
+
+ // out of bounds tests
+ for (var i = 0; i < numLevels; i++) {
+ // width and height out of bounds
+ var size = t.maxSize >> i;
+ gl.texImage2D(target, i, test.format, size + 1, size + 1, 0, test.format, test.type, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "width or height out of bounds: should generate INVALID_VALUE: level is " + i + ", size is "
+ + (size + 1) + "x" + (size + 1));
+ }
+ // level out of bounds
+ gl.texImage2D(target, numLevels, test.format, 1, 1, 0, test.format, test.type, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "level out of bounds: should generate INVALID_VALUE: level is: "
+ + numLevels + ", size is 1x1.");
+
+ // Probe to discover the max non-OOM level.
+ // For instance, on some drivers (at least Intel+Mesa) we can create
+ // a maxLevel L8 texture, but only a maxLevel-1 RGB8 texture.
+ var maxLevelsForFormat = numLevels;
+ while (true) {
+ gl.texImage2D(target, maxLevelsForFormat-1, test.format, 1, 1, 0, test.format, test.type, null);
+ var err = gl.getError();
+ if (err == gl.OUT_OF_MEMORY) {
+ debug("Probe failed for level=" + (maxLevelsForFormat-1) + ", reducing...");
+ maxLevelsForFormat -= 1;
+ if (!maxLevelsForFormat) {
+ testFailed("Failed to allocate any levels for format " + test.format);
+ return;
+ }
+ continue;
+ }
+ if (err) {
+ testFailed("Should not hit non-OOM errors during max level probing.");
+ return;
+ }
+ break;
+ }
+ var numTestLevels = Math.min(maxLevelsForFormat, t.maxLevel);
+ for (var l = 0; l < numTestLevels; ++l) {
+ // Do bottom levels first;
+ var size = 1 << l;
+ var level = maxLevelsForFormat - l - 1;
+ var otherDimension = t.target == gl.TEXTURE_2D ? 1 : size;
+ gl.texImage2D(target, level, test.format, size, otherDimension, 0, test.format, test.type, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no error for level: " + level + " " + size + "x" + otherDimension);
+ if (otherDimension != size) {
+ gl.texImage2D(target, level, test.format, otherDimension, size, 0, test.format, test.type, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no error for level: " + level + " " + otherDimension + "x" + size);
+ }
+ }
+ }
+}
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size.html
new file mode 100644
index 0000000000..12d99ac89f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-size.html
@@ -0,0 +1,217 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture size conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec3 texCoord0;
+varying vec3 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform samplerCube tex;
+varying vec3 texCoord;
+void main()
+{
+ gl_FragColor = textureCube(tex, normalize(texCoord));
+}
+</script>
+<script>
+"use strict";
+description("Checks that various sizes of textures render")
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program2D = wtu.setupTexturedQuad(gl);
+var programCubeMap = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+gl.disable(gl.DEPTH_TEST);
+gl.disable(gl.BLEND);
+var tex = gl.createTexture();
+var max2DSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+var maxCubeMapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
+debug("MAX_TEXTURE_SIZE:" + max2DSize);
+debug("MAX_CUBE_MAP_TEXTURE_SIZE:" + maxCubeMapSize);
+// Assuming 2048x2048xRGBA (22meg with mips) will run on all WebGL platforms
+var max2DSquareSize = Math.min(max2DSize, 2048);
+// I'd prefer this to be 2048 but that's 16meg x 6 faces or 128meg (with mips)
+// 1024 is 33.5 meg (with mips)
+var maxCubeMapSize = Math.min(maxCubeMapSize, 1024);
+
+var colors = [
+ { name: "green", rgba: [0, 0, 255, 255] },
+ { name: "red", rgba: [255, 0, 0, 255] },
+ { name: "blue", rgba: [0, 255, 0, 255] },
+ { name: "yellow", rgba: [255, 255, 0, 255] },
+ { name: "magenta", rgba: [255, 0, 255, 255] },
+ { name: "cyan", rgba: [0, 255, 255, 255] }
+];
+
+var count = 0;
+var power = 0;
+runTest();
+
+function runTest() {
+ function doTest() {
+ var size = Math.pow(2, power);
+ if (size > max2DSize) {
+ return false;
+ }
+ gl.useProgram(program2D);
+ if (!checkTexture(size, 1, false)) return false;
+ if (!checkTexture(1, size, false)) return false;
+ if (size <= max2DSquareSize) {
+ if (!checkTexture(size, size, false)) {
+ return false;
+ }
+ }
+ if (size <= maxCubeMapSize) {
+ gl.useProgram(programCubeMap);
+ if (!checkTexture(size, size, true)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (doTest()) {
+ ++power;
+ setTimeout(runTest, 0);
+ } else {
+ finishTest();
+ }
+}
+
+function checkTexture(width, height, cubeMap) {
+ debug("");
+ count = (count + 1) % colors.length;
+ var color = colors[count];
+ var tex = gl.createTexture();
+ var target = cubeMap ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
+ var type = cubeMap ? "cube map" : "2D texture";
+ debug("check " + width + ", " + height + " " + type);
+ gl.bindTexture(target, tex);
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ fillLevel(0, width, height, color.rgba, cubeMap);
+ var err = gl.getError();
+ if (err == gl.OUT_OF_MEMORY) {
+ debug("out of memory");
+ return false;
+ }
+ if (err != gl.NO_ERROR) {
+ testFailed("unexpected gl error: " + wtu.glEnumToString(gl, err));
+ }
+ wtu.clearAndDrawUnitQuad(gl);
+ var tolerance = 3;
+ wtu.checkCanvas(gl, color.rgba,
+ type + " of size " + width + "x" + height + " with no mips should draw with " + color.name,
+ tolerance);
+ count = (count + 1) % colors.length;
+ color = colors[count];
+ fillLevel(0, width, height, color.rgba, cubeMap);
+ gl.generateMipmap(target);
+ var err = gl.getError();
+ if (err == gl.OUT_OF_MEMORY) {
+ debug("out of memory");
+ return false;
+ }
+ if (err != gl.NO_ERROR) {
+ testFailed("unexpected gl error: " + wtu.glEnumToString(gl, err));
+ }
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, color.rgba,
+ type + " of size " + width + "x" + height + " with mips should draw with " + color.name,
+ tolerance);
+
+ count = (count + 1) % colors.length;
+ color = colors[count];
+ fillLevel(0, width, height, color.rgba, cubeMap, true);
+ gl.generateMipmap(target);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, color.rgba,
+ type + " of size " + width + "x" + height + " with mips should draw with " + color.name,
+ tolerance);
+
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+ return true;
+}
+
+function fillLevel(level, width, height, color, opt_cubemap, opt_subTex) {
+ var numPixels = width * height;
+ var pixels = null;
+ var largeDim = Math.max(width, height);
+ var smallDim = Math.min(width, height);
+
+ var pixelRow = new Uint8Array(largeDim * 4);
+ for (var jj = 0; jj < largeDim; ++jj) {
+ var off = jj * 4;
+ pixelRow[off + 0] = color[0];
+ pixelRow[off + 1] = color[1];
+ pixelRow[off + 2] = color[2];
+ pixelRow[off + 3] = color[3];
+ }
+
+ if (largeDim == numPixels) {
+ pixels = pixelRow;
+ } else {
+ var pixels = new Uint8Array(numPixels * 4);
+ for (var jj = 0; jj < smallDim; ++jj) {
+ var off = jj * largeDim * 4;
+ pixels.set(pixelRow, off);
+ }
+ }
+
+ var targets = opt_cubemap ? [
+ 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] :
+ [gl.TEXTURE_2D];
+
+ for (var ii = 0; ii < targets.length; ++ii) {
+ // debug(wtu.glEnumToString(gl, targets[ii]));
+ var index = (ii + power) % targets.length;
+ var target = targets[index];
+ if (opt_subTex) {
+ gl.texSubImage2D(
+ target, level, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE,
+ pixels);
+ } else {
+ gl.texImage2D(
+ target, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ pixels);
+ }
+ }
+}
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-srgb-upload.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-srgb-upload.html
new file mode 100644
index 0000000000..3508670563
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-srgb-upload.html
@@ -0,0 +1,253 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Upload texture from video into srgb internalformats</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <div>
+ Video:
+ <canvas id="e_rgba" width="300" height="200"></canvas>
+ 0x7f: <canvas id="e_rgba_color" width="30" height="200"></canvas>
+ <div>GL.RGBA</div>
+ </div>
+ <hr>
+ <div>
+ Video:
+ <canvas id="e_srgb8" width="300" height="200"></canvas>
+ 0x7f: <canvas id="e_srgb8_color" width="30" height="200"></canvas>
+ <div>GL.SRGB8</div>
+ </div>
+ <hr>
+ <div>
+ Video:
+ <canvas id="e_srgb8_alpha8" width="300" height="200"></canvas>
+ 0x7f: <canvas id="e_srgb8_alpha8_color" width="30" height="200"></canvas>
+ <div>GL.SRGB8_ALPHA8</div>
+ </div>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+description();
+
+const DATA_URL_FOR_720p_png_bt709_bt709_tv_yuv420p_vp9_webm = '\
+data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEA\
+AAAAAAMBEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggElTbuMU6u\
+EHFO7a1OsggLr7AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQ\
+kBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua9quAQAAAAAAAFHXgQFzxYgAAAAAAAAAAZyBACK1\
+nIN1bmSGhVZfVlA5g4EBI+ODhAJiWgDgAQAAAAAAAB6wggUAuoIC0JqBAlWwkFW6gQFVsYEBVbuBAVW\
+5gQESVMNn43NzAQAAAAAAAFljwItjxYgAAAAAAAAAAWfIAQAAAAAAABxFo4dFTkNPREVSRIePTGF2Yy\
+BsaWJ2cHgtdnA5Z8iiRaOIRFVSQVRJT05Eh5QwMDowMDowMC4wNDAwMDAwMDAAAB9DtnVBWOeBAKNBU\
+oEAAICCSYNCQE/wLPYAOCQcGAAYAFB/N9H/HZUjnnscu9GvIJt3936AAAAAACh4E4g/fJ8GmILlgmQ6\
+iUMwWlrCvdZpJAjY24ONeWCZEIrug5k4YTeAAAAAaXgTiD98nwaYguWCZDq6Zy9PLtRqFgTRRWpDzEC\
+RrKr8wtgzCibnQJwWtOOaHH9ZRjl4+aOQHHoHk/YUdplRSYiwuJO6LIyUXumq92uzm/wLAqBN0N9kRR\
+evcxyTv6VcsFqLJ5W5INE4AAAAAGN4E3vgaWsaGceNeWlTmlA/W7BnrSNUEx9X/o/hlK8PPDCgN5Kpw\
+0gRJkKtiMQMtYO7DQAUWLnf3+GjIUUj4hiAGdY+FNLJIdswhZLCeSDQfqV1btKL/ns57OfXQc0R3HFz\
+YyB4E3vgaWsaGceNeWjppQzBaWtIcWVNbYO5ARh7kHkq6WBosnlbkfoAHFO7a5G7j7OBALeK94EB8YI\
+BjfCBAw==';
+
+function invoke(fn) { return fn(); }
+
+invoke(async () => {
+ const video = document.createElement("video");
+ video.src = DATA_URL_FOR_720p_png_bt709_bt709_tv_yuv420p_vp9_webm;
+ //video.src = "Big_Buck_Bunny_360_10s_1MB.mp4";
+ //video.src = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
+ video.muted = true;
+ video.loop = true;
+ video.crossOrigin = "anonymous";
+ await video.play();
+
+ function renderTex(canvas, fn_tex_image) {
+ const gl = canvas.gl = wtu.create3DContext(canvas);
+
+ const vs = `
+attribute float a_VertexID;
+varying vec2 v_uv;
+void main() {
+ float id = a_VertexID;
+ v_uv.x = mod(id, 2.0);
+ id -= v_uv.x;
+ id /= 2.0;
+ v_uv.y = mod(id, 2.0);
+ gl_Position = vec4(2.0 * v_uv - 1.0, 0, 1);
+}`;
+
+ const fs = `
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 v_uv;
+void main() {
+ gl_FragColor = texture2D(tex, v_uv);
+}`;
+
+ const program = gl.createProgram();
+ let shader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(shader, vs);
+ gl.compileShader(shader);
+ gl.attachShader(program, shader);
+ shader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(shader, fs);
+ gl.compileShader(shader);
+ gl.attachShader(program, shader);
+ gl.bindAttribLocation(program, 0, 'a_VertexID');
+ gl.linkProgram(program);
+ gl.useProgram(program);
+ if (gl.getError()) throw 'Error during linking';
+
+ const vbuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,1,2,3]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+
+ const texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ const draw = function() {
+ //requestAnimationFrame(draw);
+ fn_tex_image(gl);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ };
+ draw();
+
+ if (gl.getError()) throw 'Error during drawing';
+ }
+
+ const GL = WebGL2RenderingContext;
+ const COLOR_DATA = new Uint8Array([127, 127, 127, 255]);
+
+ function internalformat_webgl1or2(gl, internalformat_name) {
+ let internalformat = gl[internalformat_name];
+ if (!internalformat) {
+ const ext = gl.getExtension('EXT_srgb');
+ if (!ext) {
+ testPassed('EXT_srgb not supported. (ok!)');
+ return;
+ }
+ switch (internalformat_name) {
+ case 'SRGB8':
+ internalformat = ext.SRGB_EXT;
+ break;
+ case 'SRGB8_ALPHA8':
+ internalformat = ext.SRGB_ALPHA_EXT;
+ break;
+ default:
+ throw internalformat_name;
+ }
+ }
+ return internalformat;
+ }
+
+ function begin(e_video, e_color, internalformat_name, unpackformat) {
+ renderTex(e_video, gl => {
+ const internalformat = internalformat_webgl1or2(gl, internalformat_name);
+ if (!gl.SRGB8) {
+ unpackformat = internalformat; // Must match in webgl1.
+ }
+ gl.texImage2D(GL.TEXTURE_2D, 0, internalformat,
+ unpackformat, GL.UNSIGNED_BYTE, video);
+ });
+ renderTex(e_color, gl => {
+ const internalformat = internalformat_webgl1or2(gl, internalformat_name);
+ if (!gl.SRGB8) {
+ unpackformat = internalformat; // Must match in webgl1.
+ }
+ gl.texImage2D(GL.TEXTURE_2D, 0, internalformat, 1, 1, 0,
+ unpackformat, GL.UNSIGNED_BYTE, COLOR_DATA);
+ });
+ }
+
+ begin(e_rgba, e_rgba_color, 'RGBA', GL.RGBA);
+ begin(e_srgb8, e_srgb8_color, 'SRGB8', GL.RGB);
+ begin(e_srgb8_alpha8, e_srgb8_alpha8_color, 'SRGB8_ALPHA8', GL.RGBA);
+
+ // -
+
+ const GREY50_COLOR_COORD = {
+ x: 0,
+ y: 0,
+ };
+ const GREY50_TEX_COORD = {
+ x: e_rgba.width/2 + 1,
+ y: e_rgba.height/2 + 1,
+ };
+ const fn_test = (canvas, coord, data) => {
+ wtu.checkCanvasRect(canvas.gl, coord.x, coord.y, 1, 1, data,
+ `${canvas.id} @${JSON.stringify(coord)}`);
+ }
+
+ debug('');
+ debug('e_rgba');
+ fn_test(e_rgba_color, GREY50_COLOR_COORD, [0x7f, 0x7f, 0x7f, 0xff]);
+ fn_test(e_rgba, GREY50_TEX_COORD, [0x7f, 0x7f, 0x7f, 0xff]);
+
+ debug('');
+ debug('e_srgb8');
+ fn_test(e_srgb8_color, GREY50_COLOR_COORD, [0x36, 0x36, 0x36, 0xff]);
+ fn_test(e_srgb8, GREY50_TEX_COORD, [0x36, 0x36, 0x36, 0xff]);
+
+ debug('');
+ debug('e_srgb8_alpha8');
+ fn_test(e_srgb8_alpha8_color, GREY50_COLOR_COORD, [0x36, 0x36, 0x36, 0xff]);
+ fn_test(e_srgb8_alpha8, GREY50_TEX_COORD, [0x36, 0x36, 0x36, 0xff]);
+
+ finishTest();
+});
+
+/*
+async function blobToDataURL(blob) {
+ const fr = new FileReader();
+ return await new Promise((yes, no) => {
+ fr.addEventListener('loadend', ev => {
+ if (fr.result) {
+ return yes(fr.result);
+ }
+ return no(fr.error);
+ });
+ fr.readAsDataURL(blob);
+ });
+}
+
+async function fetchDataUrl(url, wrapAt) {
+ const r = await fetch(url);
+ const b = await r.blob();
+ const durl = await blobToDataURL(b);
+ return durl;
+}
+
+function wrapLines(str, wrapAt) {
+ const lines = [];
+ let remaining = str;
+ while (remaining) {
+ lines.push(remaining.slice(0, wrapAt));
+ remaining = remaining.slice(wrapAt);
+ }
+ return lines;
+}
+
+(async () => {
+ const url = '720p.png.bt709.bt709.tv.yuv420p.vp9.webm';
+ const ident = 'DATA_URL_FOR_' + url.replaceAll('.', '_');
+ const durl = await fetchDataUrl(url);
+ const lines = wrapLines(durl, 79);
+ console.log(ident, '= \'\\\n' + lines.join('\\\n') + '\';');
+})();
+*/
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-sub-image-cube-maps.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-sub-image-cube-maps.html
new file mode 100644
index 0000000000..ca5740766a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-sub-image-cube-maps.html
@@ -0,0 +1,316 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture texSubImage2Ds cube map conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="256" height="256" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+uniform mat4 rotation;
+varying vec3 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ vec4 direction = vec4(vPosition.x * 0.5, vPosition.y * 0.5, 1, 1);
+ texCoord = normalize((rotation * direction).xyz);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform samplerCube tex;
+varying vec3 texCoord;
+void main()
+{
+ gl_FragColor = textureCube(tex, normalize(texCoord));
+}
+</script>
+<script>
+"use strict";
+var canvas;
+description("Checks issues with size of cube map textures");
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+
+var gl = wtu.create3DContext(canvas);
+wtu.setupUnitQuad(gl, 0, 1);
+var program = wtu.setupProgram(
+ gl,
+ ['vshader', 'fshader'],
+ ['vPosition', 'texCoord0'], [0, 1]);
+var rotLoc = gl.getUniformLocation(program, "rotation");
+
+var size = 16;
+
+var colors = [
+ {name: 'red', color: [255, 0, 0, 255]},
+ {name: 'green', color: [ 0, 255, 0, 255]},
+ {name: 'blue', color: [ 0, 0, 255, 255]},
+ {name: 'yellow', color: [255, 255, 0, 255]},
+ {name: 'cyan', color: [ 0, 255, 255, 255]},
+ {name: 'magenta', color: [255, 0, 255, 255]}
+];
+
+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];
+
+var rotations = [
+ {axis: [0, 1, 0], angle: Math.PI / 2},
+ {axis: [0, 1, 0], angle: -Math.PI / 2},
+ {axis: [1, 0, 0], angle: -Math.PI / 2},
+ {axis: [1, 0, 0], angle: Math.PI / 2},
+ {axis: [0, 1, 0], angle: 0},
+ {axis: [0, 1, 0], angle: Math.PI},
+];
+
+var halfRotations = [
+ {colors: [3, 4], rotations: [{axis: [1, 0, 0], angle: Math.PI / 4}]},
+ {colors: [4, 2], rotations: [{axis: [1, 0, 0], angle: -Math.PI / 4}]},
+ {colors: [5, 3], rotations: [{axis: [1, 0, 0], angle: Math.PI / 4 * 3}]},
+ {colors: [2, 5], rotations: [{axis: [1, 0, 0], angle: -Math.PI / 4 * 3}]},
+ {colors: [3, 0], rotations: [{axis: [0, 1, 0], angle: Math.PI / 2},
+ {axis: [1, 0, 0], angle: Math.PI / 4}]},
+ {colors: [0, 2], rotations: [{axis: [0, 1, 0], angle: Math.PI / 2},
+ {axis: [1, 0, 0], angle: -Math.PI / 4}]},
+];
+
+var count = 0;
+testSize(size);
+
+function testSize(size) {
+ debug("");
+ debug("testing size: " + size);
+ var canvasSize = Math.max(size / 4, 2);
+ canvas.width = canvasSize;
+ canvas.height = canvasSize;
+ gl.viewport(0, 0, canvasSize, canvasSize);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+
+ // Seems like I should be using LINEAR here with some other math
+ // to make sure I get more mip coverage but that's easier said
+ // than done.
+
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ for (var jj = 0; jj < 2; ++jj) {
+ for (var tt = 0; tt < targets.length; ++tt) {
+ var color = colors[(tt + count) % colors.length];
+ fillLevel(targets[tt], 0, size, color.color);
+ }
+ if (jj == 1) {
+ debug("use mipmap");
+ gl.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER,
+ gl.NEAREST_MIPMAP_NEAREST);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ }
+
+ var err = gl.getError();
+ if (err == gl.OUT_OF_MEMORY) {
+ debug("out of memory");
+ return false;
+ }
+ if (err != gl.NO_ERROR) {
+ testFailed("unexpected gl error: " + wtu.glEnumToString(gl, err));
+ }
+
+
+ for (var rr = 0; rr < rotations.length; ++rr) {
+ var rot = rotations[rr];
+ var color = colors[(rr + count) % colors.length];
+ var rotMat = axisRotation(rot.axis, rot.angle);
+ gl.uniformMatrix4fv(rotLoc, false, rotMat);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, color.color,
+ wtu.glEnumToString(gl, targets[rr]) + " should be " + color.name);
+ }
+
+ for (var rr = 0; rr < halfRotations.length; ++rr) {
+ var h = halfRotations[rr];
+ var rots = h.rotations;
+ var rotMat = axisRotation(rots[0].axis, rots[0].angle);
+ for (var ii = 1; ii < rots.length; ++ii) {
+ var tmpMat = axisRotation(rots[ii].axis, rots[ii].angle);
+ var rotMat = mulMatrix(tmpMat, rotMat);
+ }
+ gl.uniformMatrix4fv(rotLoc, false, rotMat);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ for (var ii = 0; ii < 2; ++ii) {
+ checkRect(
+ 0,
+ canvasSize / 2 * ii,
+ canvasSize,
+ canvasSize / 2,
+ colors[(h.colors[ii] + count) % colors.length]);
+ }
+ }
+ ++count;
+ }
+
+ gl.deleteTexture(tex);
+ return true;
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+
+function checkRect(x, y, width, height, color) {
+ wtu.checkCanvasRect(
+ gl,
+ x,
+ y,
+ width,
+ height,
+ color.color,
+ "" + x + ", " + y + ", " + width + ", " + height +
+ " should be " + color.name);
+}
+
+function fillLevel(target, level, size, color) {
+ var numPixels = size * size;
+ var halfPixelRow = new Uint8Array(size * 2);
+ for (var jj = 0; jj < size; ++jj) {
+ var off = jj * 4;
+ halfPixelRow[off + 0] = color[0];
+ halfPixelRow[off + 1] = color[1];
+ halfPixelRow[off + 2] = color[2];
+ halfPixelRow[off + 3] = color[3];
+ }
+ gl.texImage2D(
+ target, level, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ null);
+ for (var jj = 0; jj < size; ++jj) {
+ gl.texSubImage2D(
+ target, level, 0, jj, size / 2, 1, gl.RGBA, gl.UNSIGNED_BYTE, halfPixelRow);
+ gl.texSubImage2D(
+ target, level, size / 2, jj, size / 2, 1, gl.RGBA, gl.UNSIGNED_BYTE, halfPixelRow);
+ }
+}
+
+function printMat(mat) {
+ debug("" + mat[0] + ", " + mat[1] + ", " + mat[2] + ", " + mat[3] + ", ");
+ debug("" + mat[4] + ", " + mat[5] + ", " + mat[6] + ", " + mat[7] + ", ");
+ debug("" + mat[8] + ", " + mat[9] + ", " + mat[10] + ", " + mat[11] + ", ");
+ debug("" + mat[12] + ", " + mat[13] + ", " + mat[14] + ", " + mat[15] + ", ");
+}
+
+function axisRotation(axis, angle) {
+ var dst = new Float32Array(16);
+ var x = axis[0];
+ var y = axis[1];
+ var z = axis[2];
+ var n = Math.sqrt(x * x + y * y + z * z);
+ x /= n;
+ y /= n;
+ z /= n;
+ var xx = x * x;
+ var yy = y * y;
+ var zz = z * z;
+ var c = Math.cos(angle);
+ var s = Math.sin(angle);
+ var oneMinusCosine = 1 - c;
+
+ dst[ 0] = xx + (1 - xx) * c;
+ dst[ 1] = x * y * oneMinusCosine + z * s;
+ dst[ 2] = x * z * oneMinusCosine - y * s;
+ dst[ 3] = 0;
+ dst[ 4] = x * y * oneMinusCosine - z * s;
+ dst[ 5] = yy + (1 - yy) * c;
+ dst[ 6] = y * z * oneMinusCosine + x * s;
+ dst[ 7] = 0;
+ dst[ 8] = x * z * oneMinusCosine + y * s;
+ dst[ 9] = y * z * oneMinusCosine - x * s;
+ dst[10] = zz + (1 - zz) * c;
+ dst[11] = 0;
+ dst[12] = 0;
+ dst[13] = 0;
+ dst[14] = 0;
+ dst[15] = 1;
+
+ return dst;
+};
+
+function mulMatrix(a, b) {
+ var dst = new Float32Array(16);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a10 = a[ 4 + 0];
+ var a11 = a[ 4 + 1];
+ var a12 = a[ 4 + 2];
+ var a13 = a[ 4 + 3];
+ var a20 = a[ 8 + 0];
+ var a21 = a[ 8 + 1];
+ var a22 = a[ 8 + 2];
+ var a23 = a[ 8 + 3];
+ var a30 = a[12 + 0];
+ var a31 = a[12 + 1];
+ var a32 = a[12 + 2];
+ var a33 = a[12 + 3];
+ var b00 = b[0];
+ var b01 = b[1];
+ var b02 = b[2];
+ var b03 = b[3];
+ var b10 = b[ 4 + 0];
+ var b11 = b[ 4 + 1];
+ var b12 = b[ 4 + 2];
+ var b13 = b[ 4 + 3];
+ var b20 = b[ 8 + 0];
+ var b21 = b[ 8 + 1];
+ var b22 = b[ 8 + 2];
+ var b23 = b[ 8 + 3];
+ var b30 = b[12 + 0];
+ var b31 = b[12 + 1];
+ var b32 = b[12 + 2];
+ var b33 = b[12 + 3];
+ dst[ 0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
+ dst[ 1] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
+ dst[ 2] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
+ dst[ 3] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
+ dst[ 4] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
+ dst[ 5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
+ dst[ 6] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
+ dst[ 7] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
+ dst[ 8] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
+ dst[ 9] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
+ dst[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
+ dst[11] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
+ dst[12] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
+ dst[13] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
+ dst[14] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
+ dst[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
+ return dst;
+};
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-transparent-pixels-initialized.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-transparent-pixels-initialized.html
new file mode 100644
index 0000000000..7fcf384edc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-transparent-pixels-initialized.html
@@ -0,0 +1,87 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = null;
+var texture;
+var textureLoc = null;
+var successfullyParsed = false;
+
+function init()
+{
+ description('Tests there is no garbage in transparent regions of images uploaded as textures');
+
+ wtu = WebGLTestUtils;
+ gl = wtu.create3DContext("example");
+ var program = wtu.setupTexturedQuad(gl);
+ gl.clearColor(0.5,0.5,0.5,1);
+ gl.clearDepth(1);
+
+ textureLoc = gl.getUniformLocation(program, "tex");
+
+ // The input texture has 8 characters; take the leftmost one
+ var coeff = 1.0 / 8.0;
+ var texCoords = new Float32Array([
+ coeff, 1.0,
+ 0.0, 1.0,
+ 0.0, 0.0,
+ coeff, 1.0,
+ 0.0, 0.0,
+ coeff, 0.0]);
+
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ texture = wtu.loadTexture(gl, "../../../resources/bug-32888-texture.png", runTest);
+}
+
+// These two declarations need to be global for "shouldBe" to see them
+var buf = null;
+var idx = 0;
+
+function runTest()
+{
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ // Bind the texture to texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ // Point the uniform sampler to texture unit 0
+ gl.uniform1i(textureLoc, 0);
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ // Spot check a couple of 2x2 regions in the upper and lower left
+ // corners; they should be the rgb values in the texture.
+ var color = [0, 0, 0];
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 1, gl.canvas.height - 3, 2, 2, color,
+ "shouldBe " + color);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 1, 1, 2, 2, color,
+ "shouldBe " + color);
+
+ finishTest();
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-cube-maps.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-cube-maps.html
new file mode 100644
index 0000000000..c0104fe127
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-cube-maps.html
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests texImage2D and texSubImage2D upload path for TEXTURE_CUBE_MAP');
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+function testOneTarget(target, width, height) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from bindTexture(TEXTURE_CUBE_MAP).");
+
+ gl.texImage2D(target, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from texImage2D.");
+
+ var buf = new Uint8Array(width * height * 3);
+ gl.texSubImage2D(target, 0, 0, 0, width, height, gl.RGB, gl.UNSIGNED_BYTE, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from texSubImage2D.");
+}
+
+testOneTarget(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 16, 16);
+testOneTarget(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 16, 16);
+testOneTarget(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 16, 16);
+testOneTarget(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 16, 16);
+testOneTarget(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 16, 16);
+testOneTarget(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 16, 16);
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-size.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-size.html
new file mode 100644
index 0000000000..a0f30dc89f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-upload-size.html
@@ -0,0 +1,151 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture upload size conformance test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Checks that the size of a texture uploaded from an element is set correctly.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+var testUpload = function(upload, expectedWidth, expectedHeight) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, upload);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "when calling texImage2D");
+ wtu.checkTextureSize(gl, expectedWidth, expectedHeight);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, upload);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "when calling texSubImage2D with the same texture upload");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, upload);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "when calling texSubImage2D with the same texture upload with offset 1, 1");
+};
+
+var testImage = function(test, img) {
+ var width = img.width;
+ var height = img.height;
+ testUpload(img, width, height);
+
+ debug("Testing changing the width and height attributes of the image");
+ img.width *= 2;
+ img.height *= 2;
+ if (test.isSVG) {
+ testUpload(img, img.width, img.height);
+ } else {
+ testUpload(img, width, height);
+ }
+};
+
+var testVideo = function(test, video) {
+ // Assuming that the video is not anamorphic, nor has clean aperture data
+ // that would make the frame size in pixels different.
+ var width = video.videoWidth;
+ var height = video.videoHeight;
+ testUpload(video, width, height);
+
+ debug("Testing changing the width and height attributes of the video");
+ video.width *= 2;
+ video.height *= 2;
+ testUpload(video, width, height);
+};
+
+var createCanvas2DContext = function(width, height) {
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ ctx.fillRect(0, 0, width, height);
+ return ctx;
+};
+
+var testImageData = function(test) {
+ var ctx = createCanvas2DContext(test.width, test.height);
+ var imageData = ctx.getImageData(0, 0, test.width, test.height);
+ testUpload(imageData, test.width, test.height);
+};
+
+var testCanvas = function(test) {
+ var ctx = createCanvas2DContext(test.width, test.height);
+ testUpload(ctx.canvas, test.width, test.height);
+
+ debug("Testing changing the dimensions of the same canvas");
+ ctx.canvas.width = test.width + 1;
+ ctx.canvas.height = test.height + 1;
+ testUpload(ctx.canvas, ctx.canvas.width, ctx.canvas.height);
+};
+
+var tests = [
+ {type: "ImageData", width: 123, height: 456},
+ {type: "canvas", width: 123, height: 456},
+ {type: "img", isSVG: false, src: "../../../resources/red-green.png"},
+ {type: "img", isSVG: true, src: "../../../resources/red-green.svg"},
+ {type: "video", src: "../../../resources/red-green.mp4", videoType: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'},
+ {type: "video", src: "../../../resources/red-green.bt601.vp9.webm", videoType: 'video/webm; codecs="vp9"'},
+ {type: "video", src: "../../../resources/red-green.webmvp8.webm", videoType: 'video/webm; codecs="vp8, vorbis"'},
+ {type: "video", src: "../../../resources/red-green.theora.ogv", videoType: 'video/ogg; codecs="theora, vorbis"'},
+];
+
+var testIndex = 0;
+
+var runNextTest = function() {
+ if (testIndex < tests.length) {
+ debug("");
+ var test = tests[testIndex];
+ ++testIndex;
+ if (test.type == "img") {
+ debug("HTMLImageElement" + (test.isSVG ? " (SVG)" : ""));
+ var img = wtu.makeImage(test.src, function() {
+ testImage(test, img);
+ setTimeout(runNextTest, 0);
+ }, function () {
+ testFailed("could not create image" + (test.isSVG ? " (SVG)" : ""));
+ setTimeout(runNextTest, 0);
+ });
+ } else if (test.type == "video") {
+ debug("HTMLVideoElement (" + test.videoType + ")");
+ var video = wtu.makeVideo(test.src);
+ if(!video.canPlayType(test.videoType).replace(/no/, '')) {
+ debug(test.videoType + " unsupported");
+ setTimeout(runNextTest, 0);
+ return;
+ }
+ wtu.startPlayingAndWaitForVideo(video, function() {
+ testVideo(test, video);
+ setTimeout(runNextTest, 0);
+ });
+ } else if (test.type == "ImageData") {
+ debug("ImageData");
+ testImageData(test);
+ setTimeout(runNextTest, 0);
+ } else if (test.type == "canvas") {
+ debug("HTMLCanvasElement");
+ testCanvas(test);
+ setTimeout(runNextTest, 0);
+ }
+ } else {
+ finishTest();
+ }
+};
+
+runNextTest();
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-video-transparent.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-video-transparent.html
new file mode 100644
index 0000000000..9cc34debb8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-video-transparent.html
@@ -0,0 +1,164 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Upload texture from animating transparent WebM or HEVC</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+let gl;
+let successfullyParsed;
+let video;
+
+initTestingHarness();
+
+function logVisibility(isOnload)
+{
+ let prefix = '';
+ if (isOnload)
+ prefix = 'Upon load: ';
+ if (document.hidden) {
+ console.log(prefix + '*** Tab was backgrounded (if running in automated test harness, why?) ***');
+ } else {
+ console.log(prefix + 'Tab was foregrounded');
+ }
+}
+
+function init()
+{
+ description("Upload texture from animating transparent WebM or HEVC");
+
+ document.addEventListener("visibilitychange", visibilityChanged, false);
+
+ logVisibility(true);
+
+ const canvas = document.getElementById("example");
+ gl = wtu.create3DContext(canvas);
+
+ const program = wtu.setupTexturedQuad(gl);
+ const texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ const textureLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(textureLoc, 0);
+
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+
+ video = document.getElementById("vid");
+ const typeWebM = 'video/webm; codecs="vp8"';
+ const typeHEVC = 'video/mp4; codecs="hvc1"';
+ if (!video.canPlayType) {
+ testFailed("video.canPlayType required method missing");
+ finishTest();
+ return;
+ }
+ if (!video.canPlayType(typeWebM).replace(/no/, '') && !video.canPlayType(typeHEVC).replace(/no/, '')) {
+ debug(typeWebM + " unsupported");
+ debug(typeHEVC + " unsupported");
+ finishTest();
+ return;
+ };
+ wtu.startPlayingAndWaitForVideo(video, runTest);
+}
+
+function visibilityChanged() {
+ logVisibility(false);
+}
+
+function runTest(videoElement)
+{
+ let i = 0;
+ requestAnimationFrame(function frame() {
+ runOneIteration(videoElement, false);
+ runOneIteration(videoElement, true);
+
+ ++i;
+ if (i < 120) {
+ requestAnimationFrame(frame);
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+ });
+
+}
+
+function runOneIteration(videoElement, useTexSubImage2D)
+{
+ // Upload the videoElement into the texture
+ if (useTexSubImage2D) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
+ } else {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
+ }
+
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [255, 0, 0, 255]);
+
+ const tolerance = 20;
+ const red = [255, 0, 0];
+ const green = [0, 255, 0];
+ const blue = [0, 0, 255];
+
+ // Check the left and right sides. Make sure that EITHER:
+
+ // - Left is green and right is transparent-blended-with-red
+ let leftIsGreen = false, leftIsRed = false, rightIsBlue = false, rightIsRed = false;
+ let greenRedError = "", redBlueError = "";
+ let leftGreenError = "", rightBlueError = "";
+ let bufLeft, bufRight;
+ wtu.checkCanvasRectColor(gl, 4, 4, 8, 24, green, tolerance,
+ /* sameFn */ () => { leftIsGreen = true; }, /* differentFn */ (m, b) => { leftGreenError = m; bufLeft = b;}, debug);
+ wtu.checkCanvasRectColor(gl, 20, 4, 8, 24, red, tolerance,
+ /* sameFn */ () => { rightIsRed = true; }, /* differentFn */ (m, b) => { greenRedError = m; bufRight = b;}, debug);
+
+ // - Right is blue and left is transparent-blended-with-red
+ wtu.checkCanvasRectColor(gl, 20, 4, 8, 24, blue, tolerance,
+ /* sameFn */ () => { rightIsBlue = true; }, /* differentFn */ (m, b) => { rightBlueError = m; bufRight = b;}, debug);
+ wtu.checkCanvasRectColor(gl, 4, 4, 8, 24, red, tolerance,
+ /* sameFn */ () => { leftIsRed = true; }, /* differentFn */ (m, b) => { redBlueError = m; bufLeft = b;}, debug);
+
+ if (leftIsGreen) {
+ if (rightIsRed) {
+ testPassed("left is green, right is transparent-blended-with-red");
+ } else {
+ testFailed("left is green, but: " + greenRedError + "\n" + bufRight);
+ }
+ } else if (rightIsBlue) {
+ if (leftIsRed) {
+ testPassed("right is blue, left is transparent-blended-with-red");
+ } else {
+ testFailed("right is blue, but: " + redBlueError + "\n" + bufLeft);
+ }
+ } else {
+ testFailed("neither left is green nor right is blue \n" + leftGreenError + "\n" + rightBlueError + "\n" + bufLeft + "\n" + bufRight);
+ }
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<video id="vid" style="display:none;">
+ <source src="../../../resources/transparent-2frames.mp4" type='video/mp4; codecs="hvc1"' />
+ <source src="../../../resources/transparent-2frames.webm" type='video/webm; codecs="vp8"' />
+</video>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-with-flip-y-and-premultiply-alpha.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-with-flip-y-and-premultiply-alpha.html
new file mode 100644
index 0000000000..6f080f0eea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/texture-with-flip-y-and-premultiply-alpha.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture upload with FlipY and PremultiplyAlpha.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+// Regression test for crbug.com/765469
+"use strict";
+description("Checks uploading textures with FlipY and PremultiplyAlpha generates INVALID_OPERATION with invalid format/type");
+
+var canvas;
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+function testUpload() {
+ // Because WEBGL_depth_texture is enabled, UNSIGNED_SHORT becomes a valid type, but RGBA/UNSIGNED_SHORT is invalid.
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_SHORT, new Uint16Array(2*2*4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D() with invalid format/type combination");
+}
+
+var ext = gl.getExtension('WEBGL_depth_texture');
+if (ext) {
+ debug("");
+ debug("Testing with FlipY = false, PremultiplyAlpha = false");
+ testUpload();
+
+ debug("");
+ debug("Testing with FlipY = true, PremultiplyAlpha = false");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);
+ testUpload();
+
+ debug("");
+ debug("Testing with FlipY = false, PremultiplyAlpha = true");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
+ testUpload();
+
+ debug("");
+ debug("Testing with FlipY = true, PremultiplyAlpha = true");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
+ testUpload();
+} else {
+ testPassed("WEBGL_depth_texture not supported, skipping tests.");
+}
+
+gl.deleteTexture(tex);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/upload-from-srcset-with-empty-data.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/upload-from-srcset-with-empty-data.html
new file mode 100644
index 0000000000..6899e31334
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/upload-from-srcset-with-empty-data.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<title>Upload From Srcset With Empty Data</title>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<img srcset="data:,a 1x, data:,b 1w" id="i">
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+var successfullyParsed;
+
+description("This test ensures WebGL implementations handle srcsets with empty data.");
+debug("Regression test for <a href='http://crbug.com/1085044'>http://crbug.com/1085044</a>");
+
+let gl = wtu.create3DContext();
+
+// Note we run this test synchronously, rather than running it in an async
+// function called after "wtu.awaitOrTimeout(img.decode());". This reproduces
+// the bug more reliably.
+let img = document.getElementById("i");
+let tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+// Implementations can decide how to respond to these kinds of bad
+// inputs, as long as they don't crash.
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
+
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/video-rotation.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/video-rotation.html
new file mode 100644
index 0000000000..b336ed6ede
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/video-rotation.html
@@ -0,0 +1,167 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title>Verifies rotation metadata tag is respected when uploading videos to WebGL textures.</title>
+ <link rel="stylesheet" href="../../../resources/js-test-style.css" />
+ <script src="../../../js/js-test-pre.js"></script>
+ <script src="../../../js/webgl-test-utils.js"></script>
+ <script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+</head>
+
+<body onload="run()">
+ <canvas id="c" width="256" height="256"></canvas>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script>
+ "use strict";
+ description();
+ let wtu = WebGLTestUtils;
+ let tiu = TexImageUtils;
+ let canvas = document.getElementById("c");
+ let gl = wtu.create3DContext(canvas);
+ let program = tiu.setupTexturedQuad(gl, gl.RGBA);
+ const resourcePath = "../../../resources/";
+ const mp4Tolerance = 10;
+ // Significantly higher tolerance needed for VP9 tests. http://crbug.com/1219015 .
+ const vp9Tolerance = 45;
+
+ const expectedColors = {
+ top: { location: [0.5, 0.25], color: [255, 0, 0] },
+ left: { location: [0.4, 0.5], color: [0, 0, 255] },
+ right: { location: [0.6, 0.5], color: [255, 255, 0] },
+ bottom: { location: [0.5, 0.75], color: [0, 255, 0] },
+ }
+
+ function output(str) {
+ debug(str);
+ bufferedLogToConsole(str);
+ }
+
+ function checkPixels(tolerance) {
+ for (let place in expectedColors) {
+ let color = expectedColors[place];
+ let loc = color.location;
+ let x = loc[0];
+ let y = loc[1];
+ output(" Checking " + place);
+ wtu.checkCanvasRect(gl, Math.floor(canvas.width * x), Math.floor(canvas.height * y), 1, 1,
+ color.color, "shouldBe " + color.color + " +/-" + tolerance, tolerance);
+ }
+ }
+
+ function loadVideoElement(filename) {
+ return new Promise((resolve) => {
+ const video = document.createElement('video');
+ video.crossOrigin = 'anonymous';
+ video.src = resourcePath + filename;
+ wtu.startPlayingAndWaitForVideo(video, resolve);
+ });
+ }
+
+ async function testVideoElement(filename, isVP9) {
+ const video = await loadVideoElement(filename);
+
+ output("----------------------------------------------------------------");
+ output("Testing " + filename + " via HTMLVideoElement");
+
+ output(" Testing texImage2D");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ const localTolerance = isVP9 ? vp9Tolerance : mp4Tolerance;
+ checkPixels(localTolerance);
+
+ output(" Testing texSubImage2D");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, video.videoWidth, video.videoHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ checkPixels(localTolerance);
+ }
+
+ async function run() {
+ await (async () => {
+ const video = document.createElement('video');
+ if (!video.canPlayType) {
+ testFailed("video.canPlayType required method missing");
+ return;
+ }
+
+ let supports_h264 = !!video.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/no/, '');
+ let supports_vp9 = !!video.canPlayType('video/mp4; codecs="vp09.00.10.08"').replace(/no/, '');
+ if (!supports_h264 && !supports_vp9) {
+ testFailed("No supported video types.");
+ return;
+ }
+
+ let tex = gl.createTexture();
+ // Bind the texture to the default texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ // These files were created by converting exif-orientation-test.psd to mp4
+ // files, rotating them using the transpose filter, and adding rotate metadata, all
+ // using the ffmpeg command-line tool.
+ //
+ // From sdk/tests/resources/ directory:
+ //
+ // 0:
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96 -pix_fmt yuv420p -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 video-rotation-0.mp4
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 video-rotation-0.vp9.mp4
+ //
+ // 90:
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2 -pix_fmt yuv420p -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 video-rotation-90.mp4
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 video-rotation-90.vp9.mp4
+ //
+ // 180:
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2,transpose=2 -pix_fmt yuv420p -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 video-rotation-180.mp4
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2,transpose=2 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 video-rotation-180.vp9.mp4
+ //
+ // 270:
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=1 -pix_fmt yuv420p -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 video-rotation-270.mp4
+ // ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=1 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
+ // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 video-rotation-270.vp9.mp4
+
+ const filenames = [
+ "video-rotation-0",
+ "video-rotation-90",
+ "video-rotation-180",
+ "video-rotation-270",
+ ];
+
+ if (supports_h264) {
+ for (let fn of filenames)
+ await testVideoElement(fn + ".mp4", false);
+ }
+
+ if (supports_vp9) {
+ for (let fn of filenames)
+ await testVideoElement(fn + ".vp9.mp4", true);
+ }
+ })();
+
+ finishTest();
+ }
+
+ var successfullyParsed = true;
+ </script>
+</body>
+
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..549e0808ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..3bdd311bde
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..27ace886fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..38b37c8422
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..fd87fd2053
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f8955c891d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..b9491232cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..cee000e426
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/svg_image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..c2f1c72e7e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..d985f3875d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..4c6e263474
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..6eaf2065d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..a4675599ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..b07d911e1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..df27fd9932
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..de35a7b355
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/00_test_list.txt
new file mode 100644
index 0000000000..66a3a84456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/00_test_list.txt
@@ -0,0 +1,8 @@
+tex-2d-rgb-rgb-unsigned_byte.html
+tex-2d-rgb-rgb-unsigned_short_5_6_5.html
+tex-2d-rgba-rgba-unsigned_byte.html
+tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
+tex-2d-luminance-luminance-unsigned_byte.html
+tex-2d-alpha-alpha-unsigned_byte.html
+tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-alpha-alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-alpha-alpha-unsigned_byte.html
new file mode 100644
index 0000000000..5870ebaba7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-alpha-alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("ALPHA", "ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html
new file mode 100644
index 0000000000..9c551d0232
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE", "LUMINANCE", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
new file mode 100644
index 0000000000..d25216cb87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("LUMINANCE_ALPHA", "LUMINANCE_ALPHA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..889b5f1fe5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..ceb0f09ff9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..20711c46dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..bebf83cd01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..0d448009eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 1)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/00_test_list.txt
new file mode 100644
index 0000000000..732aad646c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/00_test_list.txt
@@ -0,0 +1,7 @@
+array-buffer-crash.html
+array-buffer-view-crash.html
+array-unit-tests.html
+data-view-crash.html
+data-view-test.html
+--min-version 1.0.2 typed-arrays-in-workers.html
+--min-version 1.0.3 array-large-array-tests.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-crash.html
new file mode 100644
index 0000000000..59348727e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-crash.html
@@ -0,0 +1,40 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+description('Test ArrayBuffer.byteLength');
+
+// The following used to cause a crash in Chrome.
+
+// Note that because the argument to ArrayBuffer's constructor is not
+// optional, an implementation might throw an exception on the expression
+// below rather than implicitly passing undefined. Either way is acceptable
+// from the point of view of this test, but implementations must not crash.
+try {
+ new ArrayBuffer().byteLength;
+} catch (e) {
+}
+
+testPassed("new ArrayBuffer().byteLength did not crash");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-view-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-view-crash.html
new file mode 100644
index 0000000000..cecb8138c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-buffer-view-crash.html
@@ -0,0 +1,41 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+description('Verify that constructing a typed array view with no arguments and fetching its length does not crash');
+
+
+// The following used to cause a crash in both Safari and Chrome.
+
+// Note that because the argument to ArrayBuffer's constructor is not
+// optional, an implementation might throw an exception on the expression
+// below rather than implicitly passing undefined. Either way is acceptable
+// from the point of view of this test, but implementations must not crash.
+try {
+ new Uint32Array().length;
+} catch (e) {
+}
+
+testPassed("new Uint32Array().length did not crash");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-large-array-tests.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-large-array-tests.html
new file mode 100644
index 0000000000..8af76136aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-large-array-tests.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/tests/typed-array-test-cases.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+description("Verifies allocation of large array buffers");
+
+var currentlyRunning = '';
+var allPassed = true;
+function running(str) {
+ currentlyRunning = str;
+}
+
+function output(str) {
+ debug(str);
+}
+
+function pass() {
+ testPassed(currentlyRunning);
+}
+
+function fail(str) {
+ allPassed = false;
+ var exc;
+ if (str)
+ exc = currentlyRunning + ': ' + str;
+ else
+ exc = currentlyRunning;
+ testFailed(exc);
+}
+
+function assertEq(prefix, expected, val) {
+ if (expected != val) {
+ var str = prefix + ': expected ' + expected + ', got ' + val;
+ throw str;
+ }
+}
+
+function assert(prefix, expected) {
+ if (!expected) {
+ var str = prefix + ': expected value / true';
+ throw str;
+ }
+}
+
+function printSummary() {
+ if (allPassed) {
+ debug("Test passed.");
+ } else {
+ debug("TEST FAILED");
+ }
+}
+
+
+function testConstructionOfHugeArray(type, name, sz) {
+ if (sz == 1)
+ return;
+ try {
+ // Construction of huge arrays must fail because byteLength is
+ // an unsigned long
+ array = new type(3000000000);
+ testFailed("Construction of huge " + name + " should throw exception");
+ } catch (e) {
+ testPassed("Construction of huge " + name + " threw exception");
+ }
+}
+
+function runTests() {
+ allPassed = true;
+
+ for (var i = 0; i < testCases.length; i++) {
+ var testCase = testCases[i];
+ running(testCase.name);
+ if (!(testCase.name in window)) {
+ fail("does not exist");
+ continue;
+ }
+ var type = window[testCase.name];
+ var name = testCase.name;
+ testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);
+ }
+}
+
+runTests();
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html
new file mode 100644
index 0000000000..22f0e452ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html
@@ -0,0 +1,1103 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/test-eval.js"></script>
+<script src="../../js/tests/typed-array-test-cases.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+description("Verifies the functionality of the new array-like objects in the TypedArray spec");
+
+var currentlyRunning = '';
+var allPassed = true;
+function running(str) {
+ currentlyRunning = str;
+}
+
+function output(str) {
+ debug(str);
+}
+
+function pass() {
+ testPassed(currentlyRunning);
+}
+
+function fail(str) {
+ allPassed = false;
+ var exc;
+ if (str)
+ exc = currentlyRunning + ': ' + str;
+ else
+ exc = currentlyRunning;
+ testFailed(exc);
+}
+
+function assertEq(prefix, expected, val) {
+ if (expected != val) {
+ var str = prefix + ': expected ' + expected + ', got ' + val;
+ throw str;
+ }
+}
+
+function assert(prefix, expected) {
+ if (!expected) {
+ var str = prefix + ': expected value / true';
+ throw str;
+ }
+}
+
+function printSummary() {
+ if (allPassed) {
+ debug("Test passed.");
+ } else {
+ debug("TEST FAILED");
+ }
+}
+
+var buffer;
+var byteLength;
+var subBuffer;
+var subArray;
+function testSlice() {
+ function test(subBuf, starts, size) {
+ byteLength = size;
+ subBuffer = TestEval(subBuf);
+ subArray = new Int8Array(subBuffer);
+ assertEq(subBuf, subBuffer.byteLength, byteLength);
+ for (var i = 0; i < size; ++i)
+ assertEq('Element ' + i, starts + i, subArray[i]);
+ }
+
+ try {
+ running('testSlice');
+ buffer = new ArrayBuffer(32);
+ var array = new Int8Array(buffer);
+ for (var i = 0; i < 32; ++i)
+ array[i] = i;
+
+ test("buffer.slice(0)", 0, 32);
+ test("buffer.slice(16)", 16, 16);
+ test("buffer.slice(24)", 24, 8);
+ test("buffer.slice(32)", 32, 0);
+ test("buffer.slice(40)", 32, 0);
+ test("buffer.slice(80)", 32, 0);
+
+ test("buffer.slice(-8)", 24, 8);
+ test("buffer.slice(-16)", 16, 16);
+ test("buffer.slice(-24)", 8, 24);
+ test("buffer.slice(-32)", 0, 32);
+ test("buffer.slice(-40)", 0, 32);
+ test("buffer.slice(-80)", 0, 32);
+
+ test("buffer.slice(0, 32)", 0, 32);
+ test("buffer.slice(0, 16)", 0, 16);
+ test("buffer.slice(8, 24)", 8, 16);
+ test("buffer.slice(16, 32)", 16, 16);
+ test("buffer.slice(24, 16)", 24, 0);
+
+ test("buffer.slice(16, -8)", 16, 8);
+ test("buffer.slice(-20, 30)", 12, 18);
+
+ test("buffer.slice(-8, -20)", 24, 0);
+ test("buffer.slice(-20, -8)", 12, 12);
+ test("buffer.slice(-40, 16)", 0, 16);
+ test("buffer.slice(-40, 40)", 0, 32);
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testArrayBufferIsViewMethod() {
+ debug('test ArrayBuffer.isView() with various values');
+
+ try {
+ if (!ArrayBuffer.isView) {
+ testFailed('ArrayBuffer.isView() method does not exist');
+ } else {
+ testPassed('ArrayBuffer.isView() method exists');
+
+ shouldBe('ArrayBuffer.isView(new Int8Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Uint8Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Uint8ClampedArray(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Int16Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Uint16Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Int32Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Uint32Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Float32Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new Float64Array(1))', 'true');
+ shouldBe('ArrayBuffer.isView(new DataView(new ArrayBuffer(8)))', 'true');
+
+ shouldBe('ArrayBuffer.isView(undefined)', 'false');
+ shouldBe('ArrayBuffer.isView(null)', 'false');
+ shouldBe('ArrayBuffer.isView(true)', 'false');
+ shouldBe('ArrayBuffer.isView(false)', 'false');
+ shouldBe('ArrayBuffer.isView(0)', 'false');
+ shouldBe('ArrayBuffer.isView(1)', 'false');
+ shouldBe('ArrayBuffer.isView(1.0)', 'false');
+ shouldBe('ArrayBuffer.isView("hello")', 'false');
+ shouldBe('ArrayBuffer.isView({})', 'false');
+ shouldBe('ArrayBuffer.isView(function() {})', 'false');
+ shouldBe('ArrayBuffer.isView(new Array(1))', 'false');
+ }
+ } catch (e) {
+ testFailed('Exception thrown while testing ArrayBuffer.isView method: ' + e);
+ }
+}
+
+function testInheritanceHierarchy() {
+ debug('test inheritance hierarchy of typed array views');
+
+ try {
+ var foo = ArrayBufferView;
+ testFailed('ArrayBufferView is a typedef and should not be defined');
+ } catch (e) {
+ testPassed('ArrayBufferView is a typedef and was (correctly) not defined');
+ }
+
+ // Uint8ClampedArray inherited from Uint8Array in earlier versions
+ // of the typed array specification. Since this is no longer the
+ // case, assert the new behavior.
+ shouldBe('new Uint8ClampedArray(1) instanceof Uint8Array', 'false');
+
+ if (Object.getPrototypeOf(Int8Array.prototype) == Object.prototype) {
+ // ES5 behavior.
+ shouldBe('Object.getPrototypeOf(Int8Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Uint8Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Uint8ClampedArray.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Int16Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Uint16Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Int32Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Uint32Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Float32Array.prototype)', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Float64Array.prototype)', 'Object.prototype');
+ } else {
+ // As of ES6, the prototypes for typed array constructors point to an intrinsic object whose internal
+ // prototype is Object.prototype. Relevant spec section is 22.2.5.2: TypedArray.prototype.
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Int8Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint8Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint8ClampedArray.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Int16Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint16Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Int32Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint32Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Float32Array.prototype))', 'Object.prototype');
+ shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Float64Array.prototype))', 'Object.prototype');
+ }
+
+ shouldBe('Object.getPrototypeOf(DataView.prototype)', 'Object.prototype');
+}
+
+//
+// Tests for unsigned array variants
+//
+
+function testSetAndGet10To1(type, name) {
+ running('test ' + name + ' SetAndGet10To1');
+ try {
+ var array = new type(10);
+ for (var i = 0; i < 10; i++) {
+ array[i] = 10 - i;
+ }
+ for (var i = 0; i < 10; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testConstructWithArrayOfUnsignedValues(type, name) {
+ running('test ' + name + ' ConstructWithArrayOfUnsignedValues');
+ try {
+ var array = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
+ assertEq('Array length', 10, array.length);
+ for (var i = 0; i < 10; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testConstructWithTypedArrayOfUnsignedValues(type, name) {
+ running('test ' + name + ' ConstructWithTypedArrayOfUnsignedValues');
+ try {
+ var tmp = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
+ var array = new type(tmp);
+ assertEq('Array length', 10, array.length);
+ for (var i = 0; i < 10; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+//
+// Tests for signed array variants
+//
+
+function testSetAndGetPos10ToNeg10(type, name) {
+ running('test ' + name + ' SetAndGetPos10ToNeg10');
+ try {
+ var array = new type(21);
+ for (var i = 0; i < 21; i++) {
+ array[i] = 10 - i;
+ }
+ for (var i = 0; i < 21; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testConstructWithArrayOfSignedValues(type, name) {
+ running('test ' + name + ' ConstructWithArrayOfSignedValues');
+ try {
+ var array = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]);
+ assertEq('Array length', 21, array.length);
+ for (var i = 0; i < 21; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testConstructWithTypedArrayOfSignedValues(type, name) {
+ running('test ' + name + ' ConstructWithTypedArrayOfSignedValues');
+ try {
+ var tmp = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]);
+ var array = new type(tmp);
+ assertEq('Array length', 21, array.length);
+ for (var i = 0; i < 21; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+//
+// Test cases for integral types.
+// Some JavaScript engines need separate copies of this code in order
+// to exercise all of their optimized code paths.
+//
+
+function testIntegralArrayTruncationBehavior(type, name, unsigned) {
+ running('test integral array truncation behavior for ' + name);
+
+ var sourceData;
+ var expectedResults;
+
+ if (unsigned) {
+ sourceData = [0.6, 10.6, 0.2, 10.2, 10.5, 11.5];
+ if (type === Uint8ClampedArray) {
+ expectedResults = [1, 11, 0, 10, 10, 12];
+ } else {
+ expectedResults = [0, 10, 0, 10, 10, 11];
+ }
+ } else {
+ sourceData = [0.6, 10.6, -0.6, -10.6];
+ expectedResults = [0, 10, 0, -10];
+ }
+
+ var numIterations = 10;
+ var array = new type(numIterations);
+
+ // The code block in each of the case statements below is identical, but some
+ // JavaScript engines need separate copies in order to exercise all of
+ // their optimized code paths.
+
+ try {
+ switch (type) {
+ case Int8Array:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ case Int16Array:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ case Int32Array:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ case Uint8Array:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ case Uint8ClampedArray:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ case Uint16Array:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ case Uint32Array:
+ for (var ii = 0; ii < sourceData.length; ++ii) {
+ for (var jj = 0; jj < numIterations; ++jj) {
+ array[jj] = sourceData[ii];
+ assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+ }
+ }
+ break;
+ default:
+ fail("Unhandled type");
+ break;
+ }
+
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+
+//
+// Test cases for both signed and unsigned types
+//
+
+function testGetWithOutOfRangeIndices(type, name) {
+ debug('Testing ' + name + ' GetWithOutOfRangeIndices');
+ // See below for declaration of this global variable
+ array = new type([2, 3]);
+ shouldBeUndefined("array[2]");
+ shouldBeUndefined("array[-1]");
+ shouldBeUndefined("array[0x20000000]");
+}
+
+function testOffsetsAndSizes(type, name, elementSizeInBytes) {
+ running('test ' + name + ' OffsetsAndSizes');
+ try {
+ var len = 10;
+ assertEq('type.BYTES_PER_ELEMENT', elementSizeInBytes, type.BYTES_PER_ELEMENT);
+ var array = new type(len);
+ assert('array.buffer', array.buffer);
+ assertEq('array.byteOffset', 0, array.byteOffset);
+ assertEq('array.length', len, array.length);
+ assertEq('array.byteLength', len * elementSizeInBytes, array.byteLength);
+ array = new type(array.buffer, elementSizeInBytes, len - 1);
+ assert('array.buffer', array.buffer);
+ assertEq('array.byteOffset', elementSizeInBytes, array.byteOffset);
+ assertEq('array.length', len - 1, array.length);
+ assertEq('array.byteLength', (len - 1) * elementSizeInBytes, array.byteLength);
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testSetFromTypedArray(type, name) {
+ running('test ' + name + ' SetFromTypedArray');
+ try {
+ var array = new type(10);
+ var array2 = new type(5);
+ for (var i = 0; i < 10; i++) {
+ assertEq('Element ' + i, 0, array[i]);
+ }
+ for (var i = 0; i < array2.length; i++) {
+ array2[i] = i;
+ }
+ array.set(array2);
+ for (var i = 0; i < array2.length; i++) {
+ assertEq('Element ' + i, i, array[i]);
+ }
+ array.set(array2, 5);
+ for (var i = 0; i < array2.length; i++) {
+ assertEq('Element ' + i, i, array[5 + i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function negativeTestSetFromTypedArray(type, name) {
+ running('negativeTest ' + name + ' SetFromTypedArray');
+ try {
+ var array = new type(5);
+ var array2 = new type(6);
+ for (var i = 0; i < 5; i++) {
+ assertEq('Element ' + i, 0, array[i]);
+ }
+ for (var i = 0; i < array2.length; i++) {
+ array2[i] = i;
+ }
+ try {
+ array.set(array2);
+ fail('Expected exception from array.set(array2)');
+ return;
+ } catch (e) {
+ }
+ try {
+ array2.set(array, 2);
+ fail('Expected exception from array2.set(array, 2)');
+ return;
+ } catch (e) {
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testSetFromArray(type, name) {
+ running('test ' + name + ' SetFromArray');
+ try {
+ var array = new type(10);
+ var array2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
+ for (var i = 0; i < 10; i++) {
+ assertEq('Element ' + i, 0, array[i]);
+ }
+ array.set(array2, 0);
+ for (var i = 0; i < array2.length; i++) {
+ assertEq('Element ' + i, 10 - i, array[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function negativeTestSetFromArray(type, name) {
+ running('negativeTest ' + name + ' SetFromArray');
+ try {
+ var array = new type([2, 3]);
+ try {
+ array.set([4, 5], 1);
+ fail();
+ return;
+ } catch (e) {
+ }
+ try {
+ array.set([4, 5, 6]);
+ fail();
+ return;
+ } catch (e) {
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+var subarray;
+function testSubarray(type, name) {
+ running('test ' + name + ' Subarray');
+ try {
+ var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ var subarray = array.subarray(0, 5);
+ assertEq('subarray.length', 5, subarray.length);
+ for (var i = 0; i < 5; i++) {
+ assertEq('Element ' + i, i, subarray[i]);
+ }
+ subarray = array.subarray(4, 10);
+ assertEq('subarray.length', 6, subarray.length);
+ for (var i = 0; i < 6; i++) {
+ assertEq('Element ' + i, 4 + i, subarray[i]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testSubarrayOffsetAndLengthClamping(type, name) {
+ running('test ' + name + ' Subarray offset and length clamping');
+ try {
+ var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ var subarray1 = array.subarray(0, 5);
+ var subarray2 = subarray1.subarray(-2, 10);
+ assertEq('subarray2.length', 2, subarray2.length);
+ assertEq('Element ' + 0, 3, subarray2[0]);
+ assertEq('Element ' + 1, 4, subarray2[1]);
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function negativeTestSubarray(type, name) {
+ running('negativeTest ' + name + ' Subarray');
+ try {
+ var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ subarray = array.subarray(5, 11);
+ if (subarray.length != 5) {
+ fail();
+ return;
+ }
+ subarray = array.subarray(10, 10);
+ if (subarray.length != 0) {
+ fail();
+ return;
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testSetBoundaryConditions(type, name, testValues, expectedValues) {
+ running('test ' + name + ' SetBoundaryConditions');
+ try {
+ var array = new type(1);
+ assertEq('Array length', 1, array.length);
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ for (var jj = 0; jj < 10; ++jj) {
+ array[0] = testValues[ii];
+ assertEq('Element 0', expectedValues[ii], array[0]);
+ }
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testConstructionBoundaryConditions(type, name, testValues, expectedValues) {
+ running('test ' + name + ' ConstructionBoundaryConditions');
+ try {
+ var array = new type(testValues);
+ assertEq('Array length', testValues.length, array.length);
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ assertEq('Element ' + ii, expectedValues[ii], array[ii]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+function testConstructionWithNullBuffer(type, name) {
+ var array;
+ try {
+ array = new type(null);
+ assertEq("Length of " + name + " constructed with null", 0, array.length);
+ testPassed("Construction of " + name + " with null produced a " + name + " of length 0");
+ } catch (e) {
+ // This used to be correct, but TC39 has changed the behavior of these constructors.
+ testPassed("Construction of " + name + " with null threw exception");
+ }
+ try {
+ array = new type(null, 0);
+ assertEq("Length of " + name + " constructed with null", 0, array.length);
+ testPassed("Construction of " + name + " with null produced a " + name + " of length 0");
+ } catch (e) {
+ // This used to be correct, but TC39 has changed the behavior of these constructors.
+ testPassed("Construction of " + name + " with (null, 0) threw exception");
+ }
+ try {
+ array = new type(null, 0, 0);
+ assertEq("Length of " + name + " constructed with null", 0, array.length);
+ testPassed("Construction of " + name + " with null produced a " + name + " of length 0");
+ } catch (e) {
+ // This used to be correct, but TC39 has changed the behavior of these constructors.
+ testPassed("Construction of " + name + " with (null, 0, 0) threw exception");
+ }
+}
+
+function testConstructionWithExceptionThrowingObject(type, name) {
+ var o = {};
+ Object.defineProperty(o, "length", { get: function() { throw "bail;" }});
+ try {
+ var array = new type(o);
+ } catch (e) {
+ }
+ testPassed("Construction of " + name + " with exception-throwing array-like object didn't crash unexpectedly");
+}
+
+function shouldThrowIndexSizeErr(func, text) {
+ var errorText = text + " should throw an exception";
+ try {
+ func();
+ testFailed(errorText);
+ } catch (e) {
+ testPassed(text + " threw an exception");
+ }
+}
+
+function shouldThrowTypeError(func, text) {
+ var ok = false;
+ try {
+ func();
+ } catch (e) {
+ if (e instanceof TypeError) {
+ ok = true;
+ }
+ }
+ if (ok) {
+ testPassed(text + " threw TypeError");
+ } else {
+ testFailed(text + " should throw TypeError");
+ }
+}
+
+function testConstructionWithOutOfRangeValues(type, name) {
+ shouldThrowIndexSizeErr(function() {
+ var buffer = new ArrayBuffer(4);
+ var array = new type(buffer, 4, 0x3FFFFFFF);
+ }, "Construction of " + name + " with out-of-range number of elements");
+ shouldThrowIndexSizeErr(function() {
+ var buffer = new ArrayBuffer(4);
+ var array = new type(buffer, 8);
+ }, "Construction of " + name + " with out-of-range offset");
+}
+
+function testConstructionWithNegativeOutOfRangeValues(type, name) {
+ try {
+ var buffer = new ArrayBuffer(-1);
+ testFailed("Construction of ArrayBuffer with negative size should throw exception");
+ } catch (e) {
+ testPassed("Construction of ArrayBuffer with negative size threw exception");
+ }
+ try {
+ var array = new type(-1);
+ testFailed("Construction of " + name + " with negative size should throw exception");
+ } catch (e) {
+ testPassed("Construction of " + name + " with negative size threw exception");
+ }
+ shouldThrowIndexSizeErr(function() {
+ var buffer = new ArrayBuffer(4);
+ var array = new type(buffer, 4, -2147483648);
+ }, "Construction of " + name + " with negative out-of-range values");
+}
+
+function testConstructionWithUnalignedOffset(type, name, elementSizeInBytes) {
+ if (elementSizeInBytes > 1) {
+ shouldThrowIndexSizeErr(function() {
+ var buffer = new ArrayBuffer(32);
+ var array = new type(buffer, 1, elementSizeInBytes);
+ }, "Construction of " + name + " with unaligned offset");
+ }
+}
+
+function testConstructionWithUnalignedLength(type, name, elementSizeInBytes) {
+ if (elementSizeInBytes > 1) {
+ shouldThrowIndexSizeErr(function() {
+ var buffer = new ArrayBuffer(elementSizeInBytes + 1);
+ var array = new type(buffer, 0);
+ }, "Construction of " + name + " with unaligned length");
+ }
+}
+
+function testConstructionWithBothArrayBufferAndLength(type, name, elementSizeInBytes) {
+ var bufByteLength = 1000 * elementSizeInBytes;
+ var buf = new ArrayBuffer(bufByteLength);
+ var array1 = new type(buf);
+ var array2 = new type(bufByteLength / elementSizeInBytes);
+ if (array1.length == array2.length) {
+ testPassed("Array lengths matched with explicit and implicit creation of ArrayBuffer");
+ } else {
+ testFailed("Array lengths DID NOT MATCH with explicit and implicit creation of ArrayBuffer");
+ }
+}
+
+function testConstructionWithSubPortionOfArrayBuffer(type, name, elementSizeInBytes) {
+ if (elementSizeInBytes > 1) {
+ // Test construction with a valid sub-portion of an array buffer
+ // (whose size is not an integral multiple of the element size).
+ var size = 4 * elementSizeInBytes + (elementSizeInBytes / 2);
+ var buf = new ArrayBuffer(size);
+ try {
+ var array = new type(buf, 0, 2);
+ testPassed("new " + name + "(new ArrayBuffer(" + size + "), 0, 2) succeeded");
+ } catch (e) {
+ testFailed("new " + name + "(new ArrayBuffer(" + size + "), 0, 2) failed: " + e);
+ }
+ }
+}
+
+// These need to be global for shouldBe to see them
+var array;
+var typeSize;
+
+function testSubarrayWithOutOfRangeValues(type, name, sz) {
+ debug("Testing subarray of " + name);
+ try {
+ var buffer = new ArrayBuffer(32);
+ array = new type(buffer);
+ typeSize = sz;
+ shouldBe("array.length", "32 / typeSize");
+ try {
+ shouldBe("array.subarray(4, 0x3FFFFFFF).length", "(32 / typeSize) - 4");
+ shouldBe("array.subarray(4, -2147483648).length", "0");
+ // Test subarray() against overflows.
+ array = array.subarray(2);
+ if (sz > 1) {
+ // Full byte offset is +1 larger than the maximum unsigned long int.
+ // Make sure subarray() still handles it correctly. Otherwise overflow would happen and
+ // offset would be 0, and array.length array.length would incorrectly be 1.
+ var start = 4294967296 / sz - 2;
+ array = array.subarray(start, start + 1);
+ shouldBe("array.length", "0");
+ }
+ } catch (e) {
+ testFailed("Subarray of " + name + " threw exception");
+ }
+ } catch (e) {
+ testFailed("Exception: " + e);
+ }
+}
+
+function testSubarrayWithDefaultValues(type, name, sz) {
+ debug("Testing subarray with default inputs of " + name);
+ try {
+ var buffer = new ArrayBuffer(32);
+ array = new type(buffer);
+ typeSize = sz;
+ shouldBe("array.length", "32 / typeSize");
+ try {
+ shouldBe("array.subarray(0).length", "(32 / typeSize)");
+ shouldBe("array.subarray(2).length", "(32 / typeSize) - 2");
+ shouldBe("array.subarray(-2).length", "2");
+ shouldBe("array.subarray(-2147483648).length", "(32 / typeSize)");
+ } catch (e) {
+ testFailed("Subarray of " + name + " threw exception");
+ }
+ } catch (e) {
+ testFailed("Exception: " + e);
+ }
+}
+
+function setWithInvalidOffset(type, name, length,
+ sourceType, sourceName, sourceLength,
+ offset, offsetDescription) {
+ var webglArray = new type(length);
+ var sourceArray = new sourceType(sourceLength);
+ for (var i = 0; i < sourceLength; i++)
+ sourceArray[i] = 42 + i;
+ try {
+ webglArray.set(sourceArray, offset);
+ testFailed("Setting " + name + " from " + sourceName + " with " +
+ offsetDescription + " offset was not caught");
+ } catch (e) {
+ testPassed("Setting " + name + " from " + sourceName + " with " +
+ offsetDescription + " offset was caught");
+ }
+}
+
+function setWithValidOffset(type, name, length,
+ sourceType, sourceName, sourceLength,
+ offset, offsetDescription) {
+ running("Setting " + name + " from " + sourceName + " with " +
+ offsetDescription + " offset");
+ var webglArray = new type(length);
+ var sourceArray = new sourceType(sourceLength);
+ for (var i = 0; i < sourceLength; i++)
+ sourceArray[i] = 42 + i;
+ try {
+ webglArray.set(sourceArray, offset);
+ offset = Math.floor(offset);
+ for (var i = 0; i < sourceLength; i++) {
+ assertEq("Element " + i + offset, sourceArray[i], webglArray[i + offset]);
+ }
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+
+function testSettingFromArrayWithOutOfRangeOffset(type, name) {
+ setWithInvalidOffset(type, name, 32, Array, "array", 16,
+ 0x7FFFFFF8, "out-of-range");
+}
+
+function testSettingFromTypedArrayWithOutOfRangeOffset(type, name) {
+ setWithInvalidOffset(type, name, 32, type, name, 16,
+ 0x7FFFFFF8, "out-of-range");
+}
+
+function testSettingFromArrayWithNegativeOffset(type, name) {
+ setWithInvalidOffset(type, name, 32, Array, "array", 16,
+ -1, "negative");
+}
+
+function testSettingFromTypedArrayWithNegativeOffset(type, name) {
+ setWithInvalidOffset(type, name, 32, type, name, 16,
+ -1, "negative");
+}
+
+function testSettingFromArrayWithMinusZeroOffset(type, name) {
+ setWithValidOffset(type, name, 32, Array, "array", 16,
+ -0, "-0");
+}
+
+function testSettingFromTypedArrayWithMinusZeroOffset(type, name) {
+ setWithValidOffset(type, name, 32, type, name, 16,
+ -0, "-0");
+}
+
+function testSettingFromArrayWithBoundaryOffset(type, name) {
+ setWithValidOffset(type, name, 32, Array, "array", 16,
+ 16, "boundary");
+}
+
+function testSettingFromTypedArrayWithBoundaryOffset(type, name) {
+ setWithValidOffset(type, name, 32, type, name, 16,
+ 16, "boundary");
+}
+
+function testSettingFromArrayWithNonIntegerOffset(type, name) {
+ setWithValidOffset(type, name, 32, Array, "array", 16,
+ 16.999, "non-integer");
+}
+
+function testSettingFromTypedArrayWithNonIntegerOffset(type, name) {
+ setWithValidOffset(type, name, 32, type, name, 16,
+ 16.999, "non-integer");
+}
+
+function testSettingFromFakeArrayWithOutOfRangeLength(type, name) {
+ var webglArray = new type(32);
+ var array = {};
+ array.length = 0x80000000;
+ try {
+ webglArray.set(array, 8);
+ testFailed("Setting " + name + " from fake array with invalid length was not caught");
+ } catch (e) {
+ testPassed("Setting " + name + " from fake array with invalid length was caught");
+ }
+}
+
+
+function negativeTestGetAndSetMethods(type, name) {
+ array = new type([2, 3]);
+ shouldBeUndefined("array.get");
+ var exceptionThrown = false;
+ // We deliberately check for an exception here rather than using
+ // shouldThrow here because the precise contents of the syntax
+ // error are not specified.
+ try {
+ webGLArray.set(0, 1);
+ } catch (e) {
+ exceptionThrown = true;
+ }
+ var output = "array.set(0, 1) ";
+ if (exceptionThrown) {
+ testPassed(output + "threw exception.");
+ } else {
+ testFailed(output + "did not throw exception.");
+ }
+}
+
+function testNaNConversion(type, name) {
+ running('test storing NaN in ' + name);
+
+ var array = new type([1, 1]);
+ var results = [];
+
+ // The code block in each of the case statements below is identical, but some
+ // JavaScript engines need separate copies in order to exercise all of
+ // their optimized code paths.
+ try {
+ switch (type) {
+ case Float32Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Float64Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Int8Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Int16Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Int32Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Uint8Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Uint8ClampedArray:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Uint16Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ case Uint32Array:
+ for (var i = 0; i < array.length; ++i) {
+ array[i] = NaN;
+ results[i] = array[i];
+ }
+ break;
+ default:
+ fail("Unhandled type");
+ break;
+ }
+
+ // Some types preserve NaN values; all other types convert NaN to zero.
+ if (type === Float32Array || type === Float64Array) {
+ assert('initial NaN preserved', isNaN(new type([NaN])[0]));
+ for (var i = 0; i < array.length; ++i)
+ assert('NaN preserved via setter', isNaN(results[i]));
+ } else {
+ assertEq('initial NaN converted to zero', 0, new type([NaN])[0]);
+ for (var i = 0; i < array.length; ++i)
+ assertEq('NaN converted to zero by setter', 0, results[i]);
+ }
+
+ pass();
+ } catch (e) {
+ fail(e);
+ }
+}
+
+//
+// Test driver
+//
+
+function runTests() {
+ allPassed = true;
+
+ testSlice();
+ testArrayBufferIsViewMethod();
+ testInheritanceHierarchy();
+
+ for (var i = 0; i < testCases.length; i++) {
+ var testCase = testCases[i];
+ running(testCase.name);
+ if (!(testCase.name in window)) {
+ fail("does not exist");
+ continue;
+ }
+ var type = window[testCase.name];
+ var name = testCase.name;
+ if (testCase.unsigned) {
+ testSetAndGet10To1(type, name);
+ testConstructWithArrayOfUnsignedValues(type, name);
+ testConstructWithTypedArrayOfUnsignedValues(type, name);
+ } else {
+ testSetAndGetPos10ToNeg10(type, name);
+ testConstructWithArrayOfSignedValues(type, name);
+ testConstructWithTypedArrayOfSignedValues(type, name);
+ }
+ if (testCase.integral) {
+ testIntegralArrayTruncationBehavior(type, name, testCase.unsigned);
+ }
+ testGetWithOutOfRangeIndices(type, name);
+ testOffsetsAndSizes(type, name, testCase.elementSizeInBytes);
+ testSetFromTypedArray(type, name);
+ negativeTestSetFromTypedArray(type, name);
+ testSetFromArray(type, name);
+ negativeTestSetFromArray(type, name);
+ testSubarray(type, name);
+ testSubarrayOffsetAndLengthClamping(type, name);
+ negativeTestSubarray(type, name);
+ testSetBoundaryConditions(type,
+ name,
+ testCase.testValues,
+ testCase.expectedValues);
+ testConstructionBoundaryConditions(type,
+ name,
+ testCase.testValues,
+ testCase.expectedValues);
+ testConstructionWithNullBuffer(type, name);
+ testConstructionWithExceptionThrowingObject(type, name);
+ testConstructionWithOutOfRangeValues(type, name);
+ testConstructionWithNegativeOutOfRangeValues(type, name);
+ testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
+ testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes);
+ testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes);
+ testConstructionWithSubPortionOfArrayBuffer(type, name, testCase.elementSizeInBytes);
+ testSubarrayWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
+ testSubarrayWithDefaultValues(type, name, testCase.elementSizeInBytes);
+ testSettingFromArrayWithOutOfRangeOffset(type, name);
+ testSettingFromTypedArrayWithOutOfRangeOffset(type, name);
+ testSettingFromArrayWithNegativeOffset(type, name);
+ testSettingFromTypedArrayWithNegativeOffset(type, name);
+ testSettingFromArrayWithMinusZeroOffset(type, name);
+ testSettingFromTypedArrayWithMinusZeroOffset(type, name);
+ testSettingFromArrayWithBoundaryOffset(type, name);
+ testSettingFromTypedArrayWithBoundaryOffset(type, name);
+ testSettingFromArrayWithNonIntegerOffset(type, name);
+ testSettingFromTypedArrayWithNonIntegerOffset(type, name);
+ testSettingFromFakeArrayWithOutOfRangeLength(type, name);
+ negativeTestGetAndSetMethods(type, name);
+ testNaNConversion(type, name);
+ }
+
+ printSummary();
+}
+
+runTests();
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-crash.html
new file mode 100644
index 0000000000..f634660181
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-crash.html
@@ -0,0 +1,33 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test that DataView does not crash with bad offset or length.");
+
+var array = new Uint8Array([164, 112, 157, 63]);
+var view;
+shouldThrow("view = new DataView(array.buffer, -4500000000)");
+shouldThrow("view = new DataView(array.buffer, -4500000000, 4500000000)");
+var value = view ? view.getFloat32(0, true) : 0;
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-test.html
new file mode 100644
index 0000000000..1413227578
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/data-view-test.html
@@ -0,0 +1,421 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/test-eval.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test DataView.");
+
+var intArray1 = [0, 1, 2, 3, 100, 101, 102, 103, 128, 129, 130, 131, 252, 253, 254, 255];
+var intArray2 = [31, 32, 33, 0, 1, 2, 3, 100, 101, 102, 103, 128, 129, 130, 131, 252, 253, 254, 255];
+var emptyArray = [204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204];
+
+var arrayBuffer = null;
+var view = null;
+var viewStart = 0;
+var viewLength = 0;
+
+function getElementSize(func)
+{
+ switch (func) {
+ case "Int8":
+ case "Uint8":
+ return 1;
+ case "Int16":
+ case "Uint16":
+ return 2;
+ case "Int32":
+ case "Uint32":
+ case "Float32":
+ return 4;
+ case "Float64":
+ return 8;
+ default:
+ debug("Should not reached");
+ }
+}
+
+function checkGet(func, index, expected, littleEndian)
+{
+ var expr = "view.get" + func + "(" + index;
+ if (littleEndian != undefined) {
+ expr += ", ";
+ expr += littleEndian ? "true" : "false";
+ }
+ expr += ")";
+ if (index >= 0 && index + getElementSize(func) - 1 < view.byteLength)
+ shouldBe(expr, expected);
+ else
+ shouldThrow(expr);
+}
+
+function checkSet(func, index, value, littleEndian)
+{
+ var expr = "view.set" + func + "(" + index + ", " + value;
+ if (littleEndian != undefined) {
+ expr += ", ";
+ expr += littleEndian ? "true" : "false";
+ }
+ expr += ")";
+ if (index >= 0 && index + getElementSize(func) - 1 < view.byteLength) {
+ shouldBeUndefined(expr);
+ checkGet(func, index, value, littleEndian);
+ } else
+ shouldThrow(expr);
+}
+
+function checkGetWithoutArgument(func, expected)
+{
+ var threw = false;
+ var value;
+ try {
+ value = view["get" + func]();
+ } catch (e) {
+ threw = true;
+ }
+
+ if (threw) {
+ // This used to be correct, but TC39 has changed the behavior of these methods.
+ testPassed("view.get" + func + " with no arguments throws.");
+ } else {
+ if (value === expected) {
+ testPassed("view.get" + func + " treats missing argument as 0.");
+ } else {
+ testFailed("view.get" + func + " accepts a missing argument but does not cast it to 0.");
+ }
+ }
+}
+
+function checkSetWithoutSecondArgument(func, index, isFloat)
+{
+ var expected = isFloat ? NaN : 0;
+ var threw = false;
+ var value;
+ try {
+ value = view["set" + func](index);
+ } catch (e) {
+ threw = true;
+ }
+
+ if (threw) {
+ // This used to be correct, but TC39 has changed the behavior of these methods.
+ testPassed("view.set" + func + " with missing second argument throws.");
+ } else {
+ var stored = view["get" + func](index);
+ if (value === undefined && isFloat ? isNaN(stored) : stored === expected) {
+ testPassed("view.set" + func + " treats missing second argument as " + expected + ".");
+ } else {
+ testFailed("view.set" + func + " accepts a missing second argument but does not cast it to " + expected + ".");
+ }
+ }
+}
+
+function checkSetWithoutArguments(func, isFloat)
+{
+ var expected = isFloat ? NaN : 0;
+ var threw = false;
+ var value;
+ try {
+ value = view["set" + func]();
+ } catch (e) {
+ threw = true;
+ }
+
+ if (threw) {
+ // This used to be correct, but TC39 has changed the behavior of these methods.
+ testPassed("view.set" + func + " with no arguments throws.");
+ } else {
+ var stored = view["get" + func](0);
+ if (value === undefined && isFloat ? isNaN(stored) : stored === expected) {
+ testPassed("view.set" + func + " treats missing first argument as 0.");
+ } else {
+ testFailed("view.set" + func + " accepts a missing first argument but does not cast it to 0.");
+ }
+ }
+}
+
+function testMissingArguments(func, constructor, isFloat)
+{
+ view = new DataView((new constructor(3)).buffer);
+ view["set" + func](0, 1);
+ view["set" + func](getElementSize(func), 2);
+ checkGetWithoutArgument(func, 1);
+ checkSetWithoutSecondArgument(func, getElementSize(func), isFloat);
+ view = new DataView((new constructor(3)).buffer);
+ view["set" + func](0, 1);
+ checkSetWithoutArguments(func, isFloat);
+}
+
+function test(isTestingGet, func, index, value, littleEndian)
+{
+ if (isTestingGet)
+ checkGet(func, index, value, littleEndian);
+ else
+ checkSet(func, index, value, littleEndian);
+}
+
+function createDataView(array, frontPaddingNum, littleEndian, start, length)
+{
+ if (!littleEndian)
+ array.reverse();
+ var paddingArray = new Array(frontPaddingNum);
+ arrayBuffer = (new Uint8Array(paddingArray.concat(array))).buffer;
+ viewStart = (start != undefined) ? start : 0;
+ viewLength = (length != undefined) ? length : arrayBuffer.byteLength - viewStart;
+ view = new DataView(arrayBuffer, viewStart, viewLength);
+ if (!littleEndian)
+ array.reverse(); // restore the array.
+}
+
+function runIntegerTestCases(isTestingGet, array, start, length)
+{
+ createDataView(array, 0, true, start, length);
+
+ test(isTestingGet, "Int8", 0, "0");
+ test(isTestingGet, "Int8", 8, "-128");
+ test(isTestingGet, "Int8", 15, "-1");
+
+ test(isTestingGet, "Uint8", 0, "0");
+ test(isTestingGet, "Uint8", 8, "128");
+ test(isTestingGet, "Uint8", 15, "255");
+
+ // Little endian.
+ test(isTestingGet, "Int16", 0, "256", true);
+ test(isTestingGet, "Int16", 5, "26213", true);
+ test(isTestingGet, "Int16", 9, "-32127", true);
+ test(isTestingGet, "Int16", 14, "-2", true);
+
+ // Big endian.
+ test(isTestingGet, "Int16", 0, "1");
+ test(isTestingGet, "Int16", 5, "25958");
+ test(isTestingGet, "Int16", 9, "-32382");
+ test(isTestingGet, "Int16", 14, "-257");
+
+ // Little endian.
+ test(isTestingGet, "Uint16", 0, "256", true);
+ test(isTestingGet, "Uint16", 5, "26213", true);
+ test(isTestingGet, "Uint16", 9, "33409", true);
+ test(isTestingGet, "Uint16", 14, "65534", true);
+
+ // Big endian.
+ test(isTestingGet, "Uint16", 0, "1");
+ test(isTestingGet, "Uint16", 5, "25958");
+ test(isTestingGet, "Uint16", 9, "33154");
+ test(isTestingGet, "Uint16", 14, "65279");
+
+ // Little endian.
+ test(isTestingGet, "Int32", 0, "50462976", true);
+ test(isTestingGet, "Int32", 3, "1717920771", true);
+ test(isTestingGet, "Int32", 6, "-2122291354", true);
+ test(isTestingGet, "Int32", 9, "-58490239", true);
+ test(isTestingGet, "Int32", 12, "-66052", true);
+
+ // Big endian.
+ test(isTestingGet, "Int32", 0, "66051");
+ test(isTestingGet, "Int32", 3, "56911206");
+ test(isTestingGet, "Int32", 6, "1718059137");
+ test(isTestingGet, "Int32", 9, "-2122152964");
+ test(isTestingGet, "Int32", 12, "-50462977");
+
+ // Little endian.
+ test(isTestingGet, "Uint32", 0, "50462976", true);
+ test(isTestingGet, "Uint32", 3, "1717920771", true);
+ test(isTestingGet, "Uint32", 6, "2172675942", true);
+ test(isTestingGet, "Uint32", 9, "4236477057", true);
+ test(isTestingGet, "Uint32", 12, "4294901244", true);
+
+ // Big endian.
+ test(isTestingGet, "Uint32", 0, "66051");
+ test(isTestingGet, "Uint32", 3, "56911206");
+ test(isTestingGet, "Uint32", 6, "1718059137");
+ test(isTestingGet, "Uint32", 9, "2172814332");
+ test(isTestingGet, "Uint32", 12, "4244504319");
+}
+
+function testFloat(isTestingGet, func, array, start, expected)
+{
+ // Little endian.
+ createDataView(array, 0, true, start);
+ test(isTestingGet, func, 0, expected, true);
+ createDataView(array, 3, true, start);
+ test(isTestingGet, func, 3, expected, true);
+ createDataView(array, 7, true, start);
+ test(isTestingGet, func, 7, expected, true);
+ createDataView(array, 10, true, start);
+ test(isTestingGet, func, 10, expected, true);
+
+ // Big endian.
+ createDataView(array, 0, false);
+ test(isTestingGet, func, 0, expected, false);
+ createDataView(array, 3, false);
+ test(isTestingGet, func, 3, expected, false);
+ createDataView(array, 7, false);
+ test(isTestingGet, func, 7, expected, false);
+ createDataView(array, 10, false);
+ test(isTestingGet, func, 10, expected, false);
+}
+
+function runFloatTestCases(isTestingGet, start)
+{
+ testFloat(isTestingGet, "Float32", isTestingGet ? [0, 0, 32, 65] : emptyArray, start, "10");
+ testFloat(isTestingGet, "Float32", isTestingGet ? [164, 112, 157, 63] : emptyArray, start, "1.2300000190734863");
+ testFloat(isTestingGet, "Float32", isTestingGet ? [95, 53, 50, 199] : emptyArray, start, "-45621.37109375");
+ testFloat(isTestingGet, "Float32", isTestingGet ? [255, 255, 255, 127] : emptyArray, start, "NaN");
+ testFloat(isTestingGet, "Float32", isTestingGet ? [255, 255, 255, 255] : emptyArray, start, "-NaN");
+
+ testFloat(isTestingGet, "Float64", isTestingGet ? [0, 0, 0, 0, 0, 0, 36, 64] : emptyArray, start, "10");
+ testFloat(isTestingGet, "Float64", isTestingGet ? [174, 71, 225, 122, 20, 174, 243, 63] : emptyArray, start, "1.23");
+ testFloat(isTestingGet, "Float64", isTestingGet ? [181, 55, 248, 30, 242, 179, 87, 193] : emptyArray, start, "-6213576.4839");
+ testFloat(isTestingGet, "Float64", isTestingGet ? [255, 255, 255, 255, 255, 255, 255, 127] : emptyArray, start, "NaN");
+ testFloat(isTestingGet, "Float64", isTestingGet ? [255, 255, 255, 255, 255, 255, 255, 255] : emptyArray, start, "-NaN");
+}
+
+function runNegativeIndexTests(isTestingGet)
+{
+ createDataView(intArray1, 0, true, 0, 16);
+
+ test(isTestingGet, "Int8", -1, "0");
+ test(isTestingGet, "Int8", -2, "0");
+
+ test(isTestingGet, "Uint8", -1, "0");
+ test(isTestingGet, "Uint8", -2, "0");
+
+ test(isTestingGet, "Int16", -1, "0");
+ test(isTestingGet, "Int16", -2, "0");
+ test(isTestingGet, "Int16", -3, "0");
+
+ test(isTestingGet, "Uint16", -1, "0");
+ test(isTestingGet, "Uint16", -2, "0");
+ test(isTestingGet, "Uint16", -3, "0");
+
+ test(isTestingGet, "Int32", -1, "0");
+ test(isTestingGet, "Int32", -3, "0");
+ test(isTestingGet, "Int32", -5, "0");
+
+ test(isTestingGet, "Uint32", -1, "0");
+ test(isTestingGet, "Uint32", -3, "0");
+ test(isTestingGet, "Uint32", -5, "0");
+
+ createDataView([0, 0, 0, 0, 0, 0, 36, 64], 0, true, 0, 8);
+
+ test(isTestingGet, "Float32", -1, "0");
+ test(isTestingGet, "Float32", -3, "0");
+ test(isTestingGet, "Float32", -5, "0");
+
+ test(isTestingGet, "Float64", -1, "0");
+ test(isTestingGet, "Float64", -5, "0");
+ test(isTestingGet, "Float64", -9, "0");
+}
+
+function runConstructorTests()
+{
+ arrayBuffer = (new Uint8Array([1, 2])).buffer;
+
+ debug("");
+ debug("Test for constructor taking 1 argument");
+ shouldBeDefined("view = new DataView(arrayBuffer)");
+ shouldBe("view.byteOffset", "0");
+ shouldBe("view.byteLength", "2");
+
+ debug("");
+ debug("Test for constructor taking 2 arguments");
+ shouldBeDefined("view = new DataView(arrayBuffer, 1)");
+ shouldBe("view.byteOffset", "1");
+ shouldBe("view.byteLength", "1");
+
+ debug("");
+ debug("Test for constructor taking 3 arguments");
+ shouldBeDefined("view = new DataView(arrayBuffer, 0, 1)");
+ shouldBe("view.byteOffset", "0");
+ shouldBe("view.byteLength", "1");
+
+ debug("");
+ debug("Test for constructor throwing exception");
+ shouldThrow("view = new DataView(arrayBuffer, 0, 3)");
+ shouldThrow("view = new DataView(arrayBuffer, 1, 2)");
+ shouldThrow("view = new DataView(arrayBuffer, 2, 1)");
+}
+
+function runGetTests()
+{
+ debug("");
+ debug("Test for get methods that work");
+ runIntegerTestCases(true, intArray1, 0, 16);
+ runFloatTestCases(true, 0);
+
+ debug("");
+ debug("Test for get methods that might read beyond range");
+ runIntegerTestCases(true, intArray2, 3, 2);
+ runFloatTestCases(true, 3);
+
+ debug("");
+ debug("Test for get methods that read from negative index");
+ runNegativeIndexTests(true);
+}
+
+function runSetTests()
+{
+ debug("");
+ debug("Test for set methods that work");
+ runIntegerTestCases(false, emptyArray, 0, 16);
+ runFloatTestCases(false);
+
+ debug("");
+ debug("Test for set methods that might write beyond the range");
+ runIntegerTestCases(false, emptyArray, 3, 2);
+ runFloatTestCases(false, 7);
+
+ debug("");
+ debug("Test for set methods that write to negative index");
+ runNegativeIndexTests(false);
+}
+
+function runMissingArgumentTests()
+{
+ debug("");
+ debug("Test for get and set methods missing arguments");
+ testMissingArguments("Int8", Int8Array);
+ testMissingArguments("Uint8", Uint8Array);
+ testMissingArguments("Int16", Int16Array);
+ testMissingArguments("Uint16", Uint16Array);
+ testMissingArguments("Int32", Int32Array);
+ testMissingArguments("Uint32", Uint32Array);
+ testMissingArguments("Float32", Float32Array, true);
+ testMissingArguments("Float64", Float64Array, true);
+}
+
+function runIndexingTests()
+{
+ debug("");
+ debug("Test for indexing that should not work");
+ view = new DataView((new Uint8Array([1, 2])).buffer);
+ shouldBeUndefined("view[0]");
+ shouldBeDefined("view[0] = 3");
+ shouldBe("view.getUint8(0)", "1");
+}
+
+runConstructorTests();
+runGetTests();
+runSetTests();
+runMissingArgumentTests();
+runIndexingTests();
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/typed-arrays-in-workers.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/typed-arrays-in-workers.html
new file mode 100644
index 0000000000..69eb057589
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/typed-arrays-in-workers.html
@@ -0,0 +1,257 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/test-eval.js"></script>
+<script src="../../js/tests/typed-array-test-cases.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var testQueue = [];
+var transferSupported = true;
+
+function nextTest() {
+ if (testQueue[0].subTests.length > 0) {
+ testQueue[0].subTests.shift();
+ }
+
+ while (testQueue.length > 0 && testQueue[0].subTests.length == 0) {
+ testQueue.shift();
+ }
+
+ if (testQueue.length == 0) {
+ finishTest();
+ return;
+ }
+
+ testQueue[0].subTests[0].runner();
+}
+
+function handleMessage(event) {
+ if (testQueue.length == 0)
+ return;
+
+ if (testQueue[0].subTests.length == 0)
+ return;
+
+ testQueue[0].subTests[0].checker(event);
+ nextTest();
+}
+
+function setupTest(testCase, runner, checker) {
+ testCase.subTests.push({ runner: runner.bind(null, testCase), checker: checker.bind(null, testCase) });
+}
+
+function arrayToString(arr) {
+ var result = "[ ";
+ for (var ii = 0; ii < arr.length; ++ii) {
+ if (ii > 0)
+ result += ", ";
+ result += arr[ii];
+ }
+ return result + " ]";
+}
+
+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);
+ }
+}
+
+// Test runner / checker pairs
+function runTestWithData(command, testCase) {
+ worker.postMessage({command: command, type: testCase.name, subType: testCase.subType, elementSizeInBytes: testCase.elementSizeInBytes, data: testCase.testValues});
+}
+
+function checkArraysEqual(testKind, testCase, event) {
+ var array = event.data;
+ var testName = testKind + " " + testCase.name + " from worker to main thread";
+ if (areArraysEqual(array, testCase.expectedValues)) {
+ testPassed(testName);
+ } else {
+ testFailed(testName + ": expected " + arrayToString(testCase.expectedValues) + ", received " + arrayToString(array));
+ }
+}
+
+function checkBufferContentsEqual(testKind, testCase, event) {
+ var array = constructTypedArray(testCase.name, event.data);
+ var testName = testKind + " containing " + testCase.name + " values from worker to main thread";
+ if (areArraysEqual(array, testCase.expectedValues)) {
+ testPassed(testName);
+ } else {
+ testFailed(testName + ": expected " + arrayToString(testCase.expectedValues) + ", received " + arrayToString(array));
+ }
+}
+
+function checkDataViewContents(testKind, testCase, event) {
+ var dataView = event.data;
+ var testName = testKind + " " + testCase.name + " containing " + testCase.subType + " from worker to main thread";
+ var byteOffset = 0;
+ var allPassed = true;
+ for (var ii = 0; ii < testCase.expectedValues.length; ++ii) {
+ var expected = testCase.expectedValues[ii];
+ var received = dataView['get' + testCase.subType](byteOffset);
+ if (received != expected) {
+ allPassed = false;
+ testFailed(testName + ": at byte offset " + byteOffset + ": expected " + expected + ", received " + received);
+ }
+ byteOffset += testCase.elementSizeInBytes;
+ }
+ if (allPassed) {
+ testPassed(testName);
+ }
+}
+
+// Missing test: copy or transfer ArrayBuffer, wrap in DataView on this end, verify contents.
+
+function noop() {
+}
+
+function checkArraysEqualAndPingPong(testKind, transfer, testCase, event) {
+ checkArraysEqual(testKind, testCase, event);
+ var transferables = [];
+ if (transfer) {
+ transferables.push(event.data.buffer);
+ }
+ try {
+ worker.postMessage({ command: 'pong', data: event.data, transferables: transferables }, transferables);
+ } catch (e) {
+ testFailed("unexpected exception: " + e);
+ }
+}
+
+function checkBufferContentsEqualAndPingPong(testKind, transfer, testCase, event) {
+ checkBufferContentsEqual(testKind, testCase, event);
+ var transferables = [];
+ if (transfer) {
+ transferables.push(event.data);
+ }
+ try {
+ worker.postMessage({ command: 'pong', data: event.data, transferables: transferables }, transferables);
+ } catch (e) {
+ testFailed("unexpected exception: " + e);
+ }
+}
+
+function checkDataViewContentsAndPingPong(testKind, transfer, testCase, event) {
+ checkDataViewContents(testKind, testCase, event);
+ var transferables = [];
+ if (transfer) {
+ transferables.push(event.data.buffer);
+ }
+ try {
+ worker.postMessage({ command: 'pong', data: event.data, transferables: transferables }, transferables);
+ } catch (e) {
+ testFailed("unexpected exception: " + e);
+ }
+}
+
+description("Tests copying and transferring typed arrays and ArrayBuffers to and from workers");
+
+// See whether workers are supported at all
+if (window.Worker) {
+ // Start up the worker
+ var worker = new Worker('../../js/tests/typed-array-worker.js');
+ worker.onmessage = handleMessage;
+
+ // See whether transferables are supported
+ var buffer = new ArrayBuffer(16);
+ try {
+ worker.postMessage({ command: 'ignore', data: buffer }, [buffer]);
+ if (buffer.byteLength > 0)
+ transferSupported = false;
+ } catch (e) {
+ transferSupported = false;
+ }
+
+ // Iterate down the tests, queueing them up
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var testCase = testCases[ii];
+ testCase.subTests = [];
+ setupTest(testCase, runTestWithData.bind(null, 'copy'), checkArraysEqual.bind(null, 'copy'));
+ setupTest(testCase, runTestWithData.bind(null, 'copyBuffer'), checkBufferContentsEqual.bind(null, 'copy ArrayBuffer'));
+ setupTest(testCase, runTestWithData.bind(null, 'transfer'), checkArraysEqual.bind(null, 'transfer'));
+ setupTest(testCase, runTestWithData.bind(null, 'transferBuffer'), checkBufferContentsEqual.bind(null, 'transfer ArrayBuffer'));
+
+ // These two must run back-to-back
+ setupTest(testCase, runTestWithData.bind(null, 'copy'), checkArraysEqualAndPingPong.bind(null, 'copy', false));
+ setupTest(testCase, noop, checkArraysEqual.bind(null, 'ping-pong with copy'));
+
+ // These two must run back-to-back
+ setupTest(testCase, runTestWithData.bind(null, 'copyBuffer'), checkBufferContentsEqualAndPingPong.bind(null, 'copy ArrayBuffer', false));
+ setupTest(testCase, noop, checkBufferContentsEqual.bind(null, 'ping-pong with copy'));
+
+ // These two must run back-to-back
+ setupTest(testCase, runTestWithData.bind(null, 'transfer'), checkArraysEqualAndPingPong.bind(null, 'transfer', true));
+ setupTest(testCase, noop, checkArraysEqual.bind(null, 'ping-pong with transfer'));
+
+ // These two must run back-to-back
+ setupTest(testCase, runTestWithData.bind(null, 'transferBuffer'), checkBufferContentsEqualAndPingPong.bind(null, 'transfer ArrayBuffer', false));
+ setupTest(testCase, noop, checkBufferContentsEqual.bind(null, 'ping-pong with transfer'));
+
+ testQueue.push(testCase);
+
+ // Add just a couple of DataView tests; the behavior of that view type is thoroughly tested elsewhere
+ if (testCase.name == "Float32Array" || testCase.name == "Int32Array") {
+ var subTypeName = (testCase.name == "Float32Array" ? "Float32" : "Int32");
+ var dataViewTestCase = { name: "DataView",
+ subType: subTypeName,
+ elementSizeInBytes: testCase.elementSizeInBytes,
+ testValues: testCase.testValues,
+ expectedValues: testCase.expectedValues,
+ subTests: [] };
+ setupTest(dataViewTestCase, runTestWithData.bind(null, 'copy'), checkDataViewContents.bind(null, 'copy'));
+ setupTest(dataViewTestCase, runTestWithData.bind(null, 'transfer'), checkDataViewContents.bind(null, 'transfer'));
+
+ // These two must run back-to-back
+ setupTest(dataViewTestCase, runTestWithData.bind(null, 'copy'), checkDataViewContentsAndPingPong.bind(null, 'copy', false));
+ setupTest(dataViewTestCase, noop, checkDataViewContents.bind(null, 'ping-pong with copy'));
+
+ // These two must run back-to-back
+ setupTest(dataViewTestCase, runTestWithData.bind(null, 'transfer'), checkDataViewContentsAndPingPong.bind(null, 'transfer', false));
+ setupTest(dataViewTestCase, noop, checkDataViewContents.bind(null, 'ping-pong with transfer'));
+
+ testQueue.push(dataViewTestCase);
+ }
+ }
+
+ // Kick things off
+ testQueue[0].subTests[0].runner();
+} else {
+ debug("Workers not supported -- skipping test");
+ finishTest();
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/00_test_list.txt
new file mode 100644
index 0000000000..2da0fc47a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/00_test_list.txt
@@ -0,0 +1,31 @@
+gl-uniform-arrays.html
+# This test is no longer valid with the new packing restrictions
+#--min-version 1.0.02 gl-uniform-unused-array-elements-get-truncated.html
+gl-uniform-bool.html
+--min-version 1.0.4 gl-get-uniform-non-current-program.html
+gl-uniformmatrix4fv.html
+gl-unknown-uniform.html
+no-over-optimization-on-uniform-array-00.html
+no-over-optimization-on-uniform-array-01.html
+no-over-optimization-on-uniform-array-02.html
+no-over-optimization-on-uniform-array-03.html
+no-over-optimization-on-uniform-array-04.html
+no-over-optimization-on-uniform-array-05.html
+no-over-optimization-on-uniform-array-06.html
+no-over-optimization-on-uniform-array-07.html
+no-over-optimization-on-uniform-array-08.html
+no-over-optimization-on-uniform-array-09.html
+no-over-optimization-on-uniform-array-10.html
+no-over-optimization-on-uniform-array-11.html
+no-over-optimization-on-uniform-array-12.html
+no-over-optimization-on-uniform-array-13.html
+no-over-optimization-on-uniform-array-14.html
+no-over-optimization-on-uniform-array-15.html
+no-over-optimization-on-uniform-array-16.html
+no-over-optimization-on-uniform-array-17.html
+null-uniform-location.html
+--min-version 1.0.2 out-of-bounds-uniform-array-access.html
+--min-version 1.0.2 uniform-default-values.html
+--min-version 1.0.3 uniform-values-per-program.html
+uniform-location.html
+uniform-samplers-test.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-get-uniform-non-current-program.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-get-uniform-non-current-program.html
new file mode 100644
index 0000000000..f6628748f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-get-uniform-non-current-program.html
@@ -0,0 +1,79 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL getUniform from non-current program</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+ <script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ </script>
+
+ <script id="fshader" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform float color;
+ void main()
+ {
+ gl_FragColor = vec4(color);
+ }
+ </script>
+<script>
+"use strict";
+description("This test ensures WebGL implementations handle getUniform when the program is not the current program");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program1 = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+var program2 = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+var loc = gl.getUniformLocation(program1, "color");
+
+debug("check we can call getUniform when the program is current")
+gl.useProgram(program1);
+shouldBe("gl.getUniform(program1, loc)", "0");
+debug("check we can call getUniform when a different program is current")
+gl.useProgram(program2);
+shouldBe("gl.getUniform(program1, loc)", "0");
+debug("check we can call getUniform when no program is current")
+gl.useProgram(null);
+shouldBe("gl.getUniform(program1, loc)", "0");
+
+debug("check we can call getUniform when the program is current")
+gl.useProgram(program1);
+gl.uniform1f(loc, 123)
+shouldBe("gl.getUniform(program1, loc)", "123");
+debug("check we can call getUniform when a different program is current")
+gl.useProgram(program2);
+shouldBe("gl.getUniform(program1, loc)", "123");
+debug("check we can call getUniform when no program is current")
+gl.useProgram(null);
+shouldBe("gl.getUniform(program1, loc)", "123");
+
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should no errors");
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-arrays.html
new file mode 100644
index 0000000000..7ffde96d84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-arrays.html
@@ -0,0 +1,738 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform $(type) color[3];
+ void main()
+ {
+ gl_FragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
+ }
+</script>
+<script id="vshader300" type="x-shader/x-vertex">
+ #version 300 es
+ in vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+</script>
+
+<script id="fshader300" type="x-shader/x-fragment">
+ #version 300 es
+ precision mediump float;
+ uniform $(type) color[3];
+ out vec4 o_FragColor;
+ void main()
+ {
+ o_FragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
+ }
+</script>
+<script>
+"use strict";
+description();
+debug("");
+// MaxInt32 is 2^32-1. We need +1 of that to test overflow conditions.
+var MaxInt32PlusOne = 4294967296;
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+
+const contextVersion = wtu.getDefault3DContextVersion();
+
+let [vElemId, fElemId] = ["vshader", "fshader"];
+if (contextVersion >= 2) {
+ [vElemId, fElemId] = ["vshader300", "fshader300"];
+}
+
+var vSrc = wtu.getScript(vElemId).trim();
+var fTemplate = wtu.getScript(fElemId).trim();
+
+const typeInfos = [
+ { type: 'float',
+ jsTypeOf: 'number',
+ setter: 'uniform1fv',
+ elem: '',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform2fv(loc, [1, 2]);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return srcValues[index].toString();
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : value.toString();
+ },
+ checkType: function(value) {
+ return typeof value === 'number';
+ },
+ checkValue: function(typeInfo, index, value) {
+ return typeInfo.srcValues[index] == value;
+ },
+ srcValues: [16, 15, 14],
+ srcValuesLess: [],
+ srcValuesLessMultiple: [16],
+ srcValuesMoreMultiple: [16, 15, 14, 13],
+ srcValuesNonMultiple: null,
+ },
+ { type: 'vec2',
+ jsTypeOf: 'Float32Array',
+ setter: 'uniform2fv',
+ elem: '[1]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1fv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1fv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 2 + 0].toString() + ", " +
+ srcValues[index * 2 + 1].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 2;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 2 + 0] == value[0] &&
+ typeInfo.srcValues[index * 2 + 1] == value[1];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesLess: [16],
+ srcValuesLessMultiple: [16, 15, 14, 13],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
+ },
+ { type: 'vec3',
+ jsTypeOf: 'Float32Array',
+ setter: 'uniform3fv',
+ elem: '[2]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1fv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1fv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 3 + 0].toString() + ", " +
+ srcValues[index * 3 + 1].toString() + ", " +
+ srcValues[index * 3 + 2].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 3;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 3 + 0] == value[0] &&
+ typeInfo.srcValues[index * 3 + 1] == value[1] &&
+ typeInfo.srcValues[index * 3 + 2] == value[2];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesLess: [16, 15],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
+ },
+ { type: 'vec4',
+ jsTypeOf: 'Float32Array',
+ setter: 'uniform4fv',
+ elem: '[3]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1fv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1fv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 4 + 0].toString() + ", " +
+ srcValues[index * 4 + 1].toString() + ", " +
+ srcValues[index * 4 + 2].toString() + ", " +
+ srcValues[index * 4 + 3].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] +
+ ", " + value[2] + ", " + value[3] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 4;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 4 + 0] == value[0] &&
+ typeInfo.srcValues[index * 4 + 1] == value[1] &&
+ typeInfo.srcValues[index * 4 + 2] == value[2] &&
+ typeInfo.srcValues[index * 4 + 3] == value[3];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesLess: [16, 15, 14],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
+ }
+];
+
+if (contextVersion >= 2) {
+ const more = [
+ { type: 'int',
+ jsTypeOf: 'number',
+ setter: 'uniform1iv',
+ elem: '',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform2iv(loc, [1, 2]);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return srcValues[index].toString();
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : value.toString();
+ },
+ checkType: function(value) {
+ return typeof value === 'number';
+ },
+ checkValue: function(typeInfo, index, value) {
+ return typeInfo.srcValues[index] == value;
+ },
+ srcValues: [16, 15, 14],
+ srcValuesLess: [],
+ srcValuesLessMultiple: [16],
+ srcValuesMoreMultiple: [16, 15, 14, 13],
+ srcValuesNonMultiple: null,
+ },
+ { type: 'ivec2',
+ jsTypeOf: 'Int32Array',
+ setter: 'uniform2iv',
+ elem: '[1]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1iv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1iv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 2 + 0].toString() + ", " +
+ srcValues[index * 2 + 1].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 2;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 2 + 0] == value[0] &&
+ typeInfo.srcValues[index * 2 + 1] == value[1];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesLess: [16],
+ srcValuesLessMultiple: [16, 15, 14, 13],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
+ },
+ { type: 'ivec3',
+ jsTypeOf: 'Int32Array',
+ setter: 'uniform3iv',
+ elem: '[2]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1iv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1iv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 3 + 0].toString() + ", " +
+ srcValues[index * 3 + 1].toString() + ", " +
+ srcValues[index * 3 + 2].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 3;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 3 + 0] == value[0] &&
+ typeInfo.srcValues[index * 3 + 1] == value[1] &&
+ typeInfo.srcValues[index * 3 + 2] == value[2];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesLess: [16, 15],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
+ },
+ { type: 'ivec4',
+ jsTypeOf: 'Int32Array',
+ setter: 'uniform4iv',
+ elem: '[3]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1iv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1iv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 4 + 0].toString() + ", " +
+ srcValues[index * 4 + 1].toString() + ", " +
+ srcValues[index * 4 + 2].toString() + ", " +
+ srcValues[index * 4 + 3].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] +
+ ", " + value[2] + ", " + value[3] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 4;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 4 + 0] == value[0] &&
+ typeInfo.srcValues[index * 4 + 1] == value[1] &&
+ typeInfo.srcValues[index * 4 + 2] == value[2] &&
+ typeInfo.srcValues[index * 4 + 3] == value[3];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesLess: [16, 15, 14],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
+ },
+
+
+ { type: 'uint',
+ jsTypeOf: 'number',
+ setter: 'uniform1uiv',
+ elem: '',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform2uiv(loc, [1, 2]);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return srcValues[index].toString();
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : value.toString();
+ },
+ checkType: function(value) {
+ return typeof value === 'number';
+ },
+ checkValue: function(typeInfo, index, value) {
+ return typeInfo.srcValues[index] == value;
+ },
+ srcValues: [16, 15, 14],
+ srcValuesLess: [],
+ srcValuesLessMultiple: [16],
+ srcValuesMoreMultiple: [16, 15, 14, 13],
+ srcValuesNonMultiple: null,
+ },
+ { type: 'uvec2',
+ jsTypeOf: 'Uint32Array',
+ setter: 'uniform2uiv',
+ elem: '[1]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1uiv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1uiv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 2 + 0].toString() + ", " +
+ srcValues[index * 2 + 1].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 2;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 2 + 0] == value[0] &&
+ typeInfo.srcValues[index * 2 + 1] == value[1];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesLess: [16],
+ srcValuesLessMultiple: [16, 15, 14, 13],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
+ },
+ { type: 'uvec3',
+ jsTypeOf: 'Uint32Array',
+ setter: 'uniform3uiv',
+ elem: '[2]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1uiv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1uiv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 3 + 0].toString() + ", " +
+ srcValues[index * 3 + 1].toString() + ", " +
+ srcValues[index * 3 + 2].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 3;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 3 + 0] == value[0] &&
+ typeInfo.srcValues[index * 3 + 1] == value[1] &&
+ typeInfo.srcValues[index * 3 + 2] == value[2];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesLess: [16, 15],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
+ },
+ { type: 'uvec4',
+ jsTypeOf: 'Uint32Array',
+ setter: 'uniform4uiv',
+ elem: '[3]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1uiv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1uiv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 4 + 0].toString() + ", " +
+ srcValues[index * 4 + 1].toString() + ", " +
+ srcValues[index * 4 + 2].toString() + ", " +
+ srcValues[index * 4 + 3].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] +
+ ", " + value[2] + ", " + value[3] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 4;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 4 + 0] == value[0] &&
+ typeInfo.srcValues[index * 4 + 1] == value[1] &&
+ typeInfo.srcValues[index * 4 + 2] == value[2] &&
+ typeInfo.srcValues[index * 4 + 3] == value[3];
+ },
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesLess: [16, 15, 14],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
+ },
+
+
+ { type: 'bool',
+ jsTypeOf: 'boolean',
+ setter: 'uniform1iv',
+ elem: '',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform2iv(loc, [1, 2]);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return srcValues[index].toString();
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : value.toString();
+ },
+ checkType: function(value) {
+ return typeof value === 'boolean';
+ },
+ checkValue: function(typeInfo, index, value) {
+ return typeInfo.srcValues[index] == value;
+ },
+ srcValues: [true, true, true],
+ srcValuesLess: [],
+ srcValuesLessMultiple: [16],
+ srcValuesMoreMultiple: [16, 15, 14, 13],
+ srcValuesNonMultiple: null,
+ },
+ { type: 'bvec2',
+ jsTypeOf: 'Float32Array',
+ setter: 'uniform2fv',
+ elem: '[1]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1iv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1iv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 2 + 0].toString() + ", " +
+ srcValues[index * 2 + 1].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 2;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 2 + 0] == value[0] &&
+ typeInfo.srcValues[index * 2 + 1] == value[1];
+ },
+ srcValues: [true, true, true, true, true, true],
+ srcValuesLess: [16],
+ srcValuesLessMultiple: [16, 15, 14, 13],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
+ },
+ { type: 'bvec3',
+ jsTypeOf: 'Int32Array',
+ setter: 'uniform3iv',
+ elem: '[2]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1iv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1iv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 3 + 0].toString() + ", " +
+ srcValues[index * 3 + 1].toString() + ", " +
+ srcValues[index * 3 + 2].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 3;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 3 + 0] == value[0] &&
+ typeInfo.srcValues[index * 3 + 1] == value[1] &&
+ typeInfo.srcValues[index * 3 + 2] == value[2];
+ },
+ srcValues: [true, true, true, true, true, true, true, true, true],
+ srcValuesLess: [16, 15],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
+ },
+ { type: 'bvec4',
+ jsTypeOf: 'Uint32Array',
+ setter: 'uniform4uiv',
+ elem: '[3]',
+ numSrcValues: 3,
+ invalidSet: function(loc) {
+ gl.uniform1iv(loc, [2]);
+ },
+ illegalSet: function(loc) {
+ gl.uniform1iv(loc, 2);
+ },
+ srcValueAsString: function(index, srcValues) {
+ return "[" + srcValues[index * 4 + 0].toString() + ", " +
+ srcValues[index * 4 + 1].toString() + ", " +
+ srcValues[index * 4 + 2].toString() + ", " +
+ srcValues[index * 4 + 3].toString() + "]";
+ },
+ returnValueAsString: function(value) {
+ return value === null ? 'null' :
+ ("[" + value[0] + ", " + value[1] +
+ ", " + value[2] + ", " + value[3] + "]");
+ },
+ checkType: function(value) {
+ return value &&
+ typeof value.length === 'number' &&
+ value.length == 4;
+ },
+ checkValue: function(typeInfo, index, value) {
+ return value !== null &&
+ typeInfo.srcValues[index * 4 + 0] == value[0] &&
+ typeInfo.srcValues[index * 4 + 1] == value[1] &&
+ typeInfo.srcValues[index * 4 + 2] == value[2] &&
+ typeInfo.srcValues[index * 4 + 3] == value[3];
+ },
+ srcValues: [true, true, true, true, true, true, true, true, true, true, true, true],
+ srcValuesLess: [16, 15, 14],
+ srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
+ }
+ ];
+ typeInfos.push(...more);
+}
+
+let loc;
+for (var tt = 0; tt < typeInfos.length; ++tt) {
+ var typeInfo = typeInfos[tt];
+ debug("");
+ debug("check " + typeInfo.type);
+ var fSrc = wtu.replaceParams(fTemplate, typeInfo);
+ //debug("fSrc: " + fSrc);
+ var program = wtu.loadProgram(gl, vSrc, fSrc);
+
+ var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ assertMsg(numUniforms == 1, "1 uniform found");
+ var info = gl.getActiveUniform(program, 0);
+ assertMsg(info.name == "color[0]",
+ "uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10");
+ shouldBeNull("gl.getUniformLocation(program, 'color[" + MaxInt32PlusOne + "]');");
+ loc = gl.getUniformLocation(program, "color[0]");
+ if (!loc) throw 'Missing loc';
+ var srcValues = typeInfo.srcValues;
+ var srcValuesLess = typeInfo.srcValuesLess;
+ var srcValuesLessMultiple = typeInfo.srcValuesLessMultiple;
+ var srcValuesMoreMultiple = typeInfo.srcValuesMoreMultiple;
+ var srcValuesNonMultiple = typeInfo.srcValuesNonMultiple;
+
+ // Try setting the value before using the program
+ gl[typeInfo.setter](loc, srcValues);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "should fail if there is no current program");
+
+ gl.useProgram(program);
+ gl[typeInfo.setter](loc, srcValuesLess);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "should fail with insufficient array size with gl." + typeInfo.setter);
+ if (srcValuesNonMultiple) {
+ gl[typeInfo.setter](loc, srcValuesNonMultiple);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "should fail with non-multiple array size with gl." + typeInfo.setter);
+ }
+
+ const validDatas = [
+ `new Float32Array(${srcValues.length})`,
+ `new Float32Array(new ArrayBuffer(4*${srcValues.length}))`,
+ ];
+ if (window.SharedArrayBuffer) {
+ validDatas.push(
+ `new Float32Array(new SharedArrayBuffer(4*${srcValues.length}))`
+ );
+ }
+ for (const x of validDatas) {
+ shouldNotThrow(`gl.${typeInfo.setter}(loc, ${x});`);
+ }
+
+ gl[typeInfo.setter](loc, srcValues);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter);
+ gl[typeInfo.setter](loc, srcValuesLessMultiple);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can partially set an array of uniforms with gl." + typeInfo.setter + " with a smaller array");
+ gl[typeInfo.setter](loc, srcValuesMoreMultiple);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter + " with a larger array");
+
+ var values = gl.getUniform(program, loc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can call gl.getUniform");
+ assertMsg(typeInfo.checkType(values),
+ "gl.getUniform returns the correct type. " + `(was ${values.constructor.name})`);
+ for (var ii = 0; ii < typeInfo.numSrcValues; ++ii) {
+ shouldBeNull("gl.getUniformLocation(program, 'color[" + (MaxInt32PlusOne + ii) + "]')");
+ var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can get location of element " + ii +
+ " of array from gl.getUniformLocation");
+ var value = gl.getUniform(program, elemLoc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can get value of element " + ii + " of array from gl.getUniform");
+ assertMsg(typeInfo.checkValue(typeInfo, ii, value),
+ "value put in (" + typeInfo.srcValueAsString(ii, srcValues) +
+ ") matches value pulled out (" +
+ typeInfo.returnValueAsString(value) + ")");
+ }
+ typeInfo.invalidSet(loc);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "using the wrong size of gl.Uniform fails");
+ var exceptionCaught = false;
+ if (typeInfo.illegalSet) {
+ try {
+ typeInfo.illegalSet(loc);
+ } catch (e) {
+ exceptionCaught = true;
+ }
+ assertMsg(exceptionCaught, "passing non-array to glUniform*fv should throw TypeError");
+ }
+
+ gl.useProgram(null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can call gl.useProgram(null)");
+}
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-bool.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-bool.html
new file mode 100644
index 0000000000..4f23cb4cf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-bool.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniformMatrix Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+ <script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ </script>
+
+ <script id="fshader" type="x-shader/x-fragment">
+ uniform bool color;
+ void main()
+ {
+ gl_FragColor = vec4(float(color),0.0,0.0,1.0);
+ }
+ </script>
+<script>
+"use strict";
+description("This test ensures WebGL implementations handle bool uniforms in a OpenGL ES 2.0 spec compliant way");
+
+debug("");
+debug("NOTE: Some OpenGL drivers do not handle this correctly");
+debug("");
+debug("Checking gl.uniform1f with bool.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+var loc = gl.getUniformLocation(program, "color");
+gl.uniform1f(loc, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be able to set bool with gl.uniform1f");
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-struct-unused.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-struct-unused.html
new file mode 100644
index 0000000000..b755e59ee2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-struct-unused.html
@@ -0,0 +1,83 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform struct Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+uniform vec4 u0;
+struct MyStruct {
+ vec4 var1;
+ vec4 var2;
+ vec4 var3;
+ vec4 var4;
+};
+uniform MyStruct u1;
+uniform vec4 u2;
+varying vec4 v_color;
+void main()
+{
+ gl_Position = vPosition;
+ v_color = (u0 + u2 + u1.var1) - vec4(2.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main()
+{
+ gl_FragColor = v_color;
+}
+</script>
+
+<script>
+"use strict";
+description("This test ensures WebGL implementations handle unused members at the end of structs correctly.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var c = document.getElementById("console");
+program = wtu.setupProgram(gl, ["vshader", "fshader"], [ "vPosition"]);
+
+wtu.setupUnitQuad(gl, [0, 1]);
+var white = [1.0, 1.0, 1.0, 1.0];
+var black = [0.0, 0.0, 0.0, 0.0];
+gl.uniform4fv(gl.getUniformLocation(program, "u0"), white);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var1"), white);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var2"), black);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var3"), black);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var4"), black);
+gl.uniform4fv(gl.getUniformLocation(program, "u2"), white);
+wtu.clearAndDrawUnitQuad(gl);
+wtu.checkCanvas(gl, [255, 255, 255, 255], "should be white", 0);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var2"), black);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var3"), black);
+gl.uniform4fv(gl.getUniformLocation(program, "u1.var4"), black);
+wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 0]);
+wtu.checkCanvas(gl, [255, 255, 255, 255], "should still be white", 0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no GL errors");
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-unused-array-elements-get-truncated.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-unused-array-elements-get-truncated.html
new file mode 100644
index 0000000000..f8322cca01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniform-unused-array-elements-get-truncated.html
@@ -0,0 +1,114 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform unused array elements get truncated Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+</script>
+<script id="fshader-max" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform vec4 colora[$(numUniformVectors)];
+ void main()
+ {
+ gl_FragColor = vec4(colora[$(usedUniformVector)]);
+ }
+</script>
+<script>
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var vSrc = wtu.getScript("vshader");
+var uniforms;
+// This test is to test drivers the have bugs related to optimizing
+// an array of uniforms when only 1 of those uniforms is used.
+debug("");
+var maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
+var tests = [
+ { desc: "using 5th element",
+ maxUniformVectors: maxUniformVectors,
+ numUniformVectors: maxUniformVectors * 2,
+ usedUniformVector: 5,
+ shader: "fshader-max",
+ color: [0, 1, 0, 1],
+ arrayName: "colora",
+ },
+];
+
+// According to the spec unused array elements must be truncated.
+var requiredUniformLocationsExist;
+function testUniformIssues(testIndex) {
+ var test = tests[testIndex];
+ debug("");
+ debug(test.desc);
+ var fSrc = test.source;
+ if (!fSrc) {
+ fSrc = wtu.replaceParams(wtu.getScript(test.shader), test);
+ }
+
+ var consoleElem = document.getElementById("console");
+ wtu.addShaderSource(
+ consoleElem, "vertex shader", vSrc);
+ wtu.addShaderSource(
+ consoleElem, "fragment shader", fSrc);
+
+ var program = wtu.loadProgram(gl, vSrc, fSrc);
+ gl.useProgram(program);
+ uniforms = wtu.getUniformMap(gl, program);
+ shouldBe('uniforms["' + test.arrayName + '[0]"].size', (test.usedUniformVector + 1).toString());
+
+ requiredUniformLocationsExist = true;
+ for (var ii = 0; ii <= test.usedUniformVector + 1; ++ii) {
+ var name = test.arrayName + "[" + ii + "]";
+ var colorLocation = gl.getUniformLocation(program, name);
+ if (ii <= test.usedUniformVector) {
+ if (!colorLocation) {
+ requiredUniformLocationsExist = false
+ }
+ } else {
+ if (colorLocation) {
+ testFailed("uniform array was not truncated as specified in OpenGL ES 2.0.25 section 2.10.4");
+ }
+ }
+ }
+ shouldBeTrue("requiredUniformLocationsExist");
+}
+
+var testIndex = 0;
+function runNextTest() {
+ testUniformIssues(testIndex++);
+ if (testIndex < tests.length) {
+ setTimeout(runNextTest, 0);
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ debug("");
+ finishTest();
+ }
+}
+runNextTest();
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniformmatrix4fv.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniformmatrix4fv.html
new file mode 100644
index 0000000000..eb4977a6fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-uniformmatrix4fv.html
@@ -0,0 +1,149 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniformMatrix Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+
+<script id="vshader" type="x-shader/x-vertex">
+uniform mat2 world2x2;
+uniform mat3 world3x3;
+uniform mat4 world4x4;
+void main() {
+ gl_Position.x += world2x2[0][0];
+ gl_Position.x += world3x3[0][0];
+ gl_Position.x += world4x4[0][0];
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main() {}
+</script>
+
+<script id="vshader300" type="x-shader/x-vertex">
+#version 300 es
+uniform mat2 world2x2;
+uniform mat2x3 world2x3;
+uniform mat2x4 world2x4;
+uniform mat3x2 world3x2;
+uniform mat3 world3x3;
+uniform mat3x4 world3x4;
+uniform mat4x2 world4x2;
+uniform mat4x3 world4x3;
+uniform mat4 world4x4;
+void main() {
+ gl_Position.x += world2x2[0][0];
+ gl_Position.x += world2x3[0][0];
+ gl_Position.x += world2x4[0][0];
+ gl_Position.x += world3x2[0][0];
+ gl_Position.x += world3x3[0][0];
+ gl_Position.x += world3x4[0][0];
+ gl_Position.x += world4x2[0][0];
+ gl_Position.x += world4x3[0][0];
+ gl_Position.x += world4x4[0][0];
+}
+</script>
+
+<script id="fshader300" type="x-shader/x-fragment">
+#version 300 es
+void main() {}
+</script>
+
+<script>
+"use strict";
+description("This test ensures WebGL implementations handle uniformMatrix in a OpenGL ES 2.0 spec compliant way");
+
+debug("");
+debug("Checking gl.uniformMatrix.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var contextVersion = wtu.getDefault3DContextVersion();
+
+let shaders = ["vshader", "fshader"];
+const dims = [
+ [2, 2, 'uniformMatrix2fv'],
+ [3, 3, 'uniformMatrix3fv'],
+ [4, 4, 'uniformMatrix4fv'],
+];
+
+if (contextVersion >= 2) {
+ shaders = ["vshader300", "fshader300"];
+ dims.push(
+ [2, 3, 'uniformMatrix2x3fv'],
+ [2, 4, 'uniformMatrix2x4fv'],
+ [3, 2, 'uniformMatrix3x2fv'],
+ [3, 4, 'uniformMatrix3x4fv'],
+ [4, 2, 'uniformMatrix4x2fv'],
+ [4, 3, 'uniformMatrix4x3fv']
+ );
+}
+
+const program = wtu.setupProgram(gl, shaders);
+let loc;
+
+for (const [A, B, name] of dims) {
+ loc = gl.getUniformLocation(program, `world${A}x${B}`);
+ if (!loc) throw 'missing loc';
+
+ const mat = [];
+ for (let a = 0; a < A; ++a) {
+ for (let b = 0; b < B; ++b) {
+ mat.push((a == b) ? 1 : 0);
+ }
+ }
+ const matLess = mat.slice(0, mat.length-2);
+ const matMore = mat.concat([1]);
+
+ gl[name](loc, false, matLess);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with insufficient array size for " + name);
+ gl[name](loc, false, mat);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should succeed with correct array size for " + name);
+ gl[name](loc, false, matMore);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with more than 1 array size for " + name);
+
+ const validDatas = [
+ `new Float32Array(${mat.length})`,
+ `new Float32Array(new ArrayBuffer(4*${mat.length}))`,
+ ];
+ if (window.SharedArrayBuffer) {
+ validDatas.push(
+ `new Float32Array(new SharedArrayBuffer(4*${mat.length}))`
+ );
+ }
+ for (const x of validDatas) {
+ shouldNotThrow(`gl.${name}(loc, false, ${x});`);
+ }
+
+ gl[name](loc, false, mat);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "can call " + name + "with transpose = false");
+ if (contextVersion <= 1) {
+ gl[name](loc, true, mat);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, name + " should return INVALID_VALUE with transpose = true");
+ } else {
+ gl[name](loc, true, mat);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "can call " + name + "with transpose = true");
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-unknown-uniform.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-unknown-uniform.html
new file mode 100644
index 0000000000..825fd23831
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/gl-unknown-uniform.html
@@ -0,0 +1,67 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Unknown Uniform Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+<script>
+"use strict";
+description("Tests that unknown uniforms don't cause errors.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+ // Get the location of an unknown uniform.
+ var loc = gl.getUniformLocation(program, "someUnknownUniform");
+ assertMsg(loc === null, "location of unknown uniform should be null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "there should be no error from getting an unknown uniform");
+ gl.uniform1f(loc, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "there should be no error from trying to set an unknown uniform");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-00.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-00.html
new file mode 100644
index 0000000000..d331fa9299
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-00.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 0;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-01.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-01.html
new file mode 100644
index 0000000000..a60c1af473
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-01.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 1;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-02.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-02.html
new file mode 100644
index 0000000000..670d553802
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-02.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 2;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-03.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-03.html
new file mode 100644
index 0000000000..5702b78033
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-03.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 3;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-04.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-04.html
new file mode 100644
index 0000000000..b46e8915e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-04.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 4;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-05.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-05.html
new file mode 100644
index 0000000000..43caca6c9f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-05.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 5;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-06.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-06.html
new file mode 100644
index 0000000000..e18b69ea5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-06.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 6;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-07.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-07.html
new file mode 100644
index 0000000000..365890dc90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-07.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 7;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-08.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-08.html
new file mode 100644
index 0000000000..442cea6bed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-08.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 8;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-09.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-09.html
new file mode 100644
index 0000000000..4543434e77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-09.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 9;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-10.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-10.html
new file mode 100644
index 0000000000..dd4827f5f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-10.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 10;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-11.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-11.html
new file mode 100644
index 0000000000..93b34b906b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-11.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 11;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-12.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-12.html
new file mode 100644
index 0000000000..e802600741
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-12.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 12;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-13.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-13.html
new file mode 100644
index 0000000000..0606ef5a28
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-13.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 13;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-14.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-14.html
new file mode 100644
index 0000000000..7e33adce4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-14.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 14;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-15.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-15.html
new file mode 100644
index 0000000000..46b50679b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-15.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 15;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-16.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-16.html
new file mode 100644
index 0000000000..881b76b560
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-16.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 16;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-17.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-17.html
new file mode 100644
index 0000000000..9dcb8ae9b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/no-over-optimization-on-uniform-array-17.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/no-over-optimizations-on-uniform-array.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description();
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var testIndex = 17;
+var testSet = NoOverOptimizeOnUniformArrayTester.setupTests(gl);
+var testCases = [testSet[testIndex]];
+
+NoOverOptimizeOnUniformArrayTester.runTests(gl, testCases)
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/null-uniform-location.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/null-uniform-location.html
new file mode 100644
index 0000000000..0c49bdb2f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/null-uniform-location.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests calling the various uniform[Matrix]* APIs with a null uniform location");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var program = wtu.loadStandardProgram(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined("gl.useProgram(program)");
+var floatArray = new Float32Array([1, 2, 3, 4]);
+var intArray = new Int32Array([1, 2, 3, 4]);
+
+function callUniformFunction(name) {
+ var isArrayVariant = (name.charAt(name.length - 1) == 'v');
+ var isMatrix = (name.indexOf("Matrix") != -1);
+ var isFloat =
+ (name.charAt(name.length - 1) == 'f' ||
+ name.charAt(name.length - 2) == 'f');
+ var sizeIndex = (isArrayVariant ? name.length - 3 : name.length - 2);
+ var size = parseInt(name.substring(sizeIndex, sizeIndex + 1));
+ // Initialize argument list with null uniform location
+ var args = [ null ];
+ if (isArrayVariant) {
+ // Call variant which takes values as array
+ if (isMatrix) {
+ size = size * size;
+ args.push(false);
+ }
+ var array = (isFloat ? new Float32Array(size) : new Int32Array(size));
+ for (var i = 0; i < size; i++) {
+ array[i] = i;
+ }
+ args.push(array);
+ } else {
+ // Call variant which takes values as parameters
+ for (var i = 0; i < size; i++) {
+ args.push(i);
+ }
+ }
+ var func = gl[name];
+ return func.apply(gl, args);
+}
+
+var funcs = [ "uniform1f", "uniform1fv", "uniform1i", "uniform1iv",
+ "uniform2f", "uniform2fv", "uniform2i", "uniform2iv",
+ "uniform3f", "uniform3fv", "uniform3i", "uniform3iv",
+ "uniform4f", "uniform4fv", "uniform4i", "uniform4iv",
+ "uniformMatrix2fv", "uniformMatrix3fv", "uniformMatrix4fv" ];
+var callString;
+
+for (var i = 0; i < funcs.length; i++) {
+ callString = "callUniformFunction('" + funcs[i] + "')";
+ shouldBeUndefined(callString);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/out-of-bounds-uniform-array-access.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/out-of-bounds-uniform-array-access.html
new file mode 100644
index 0000000000..1defc8ee0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/out-of-bounds-uniform-array-access.html
@@ -0,0 +1,168 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL out of bounds uniform array access.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="example" width="128" height="128" style="background: black;">
+</canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 v_color;
+uniform float lineWidth;
+uniform int elemMult;
+uniform vec4 colorArray[6];
+void main()
+{
+ vec2 texcoord = vec2(vPosition.xy * 0.5 + vec2(0.5, 0.5));
+ int index = int(texcoord.x + texcoord.y * lineWidth) * elemMult;
+ v_color = colorArray[index];
+ gl_Position = vPosition;
+ gl_PointSize = 1.0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main()
+{
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+debug("Tests a WebGL program that accesses out of bounds uniform array elements");
+
+var gl;
+var gridRes = 127;
+var lineWidthLoc;
+var elemMultLoc;
+var width = 128;
+var height = 128;
+var pixels = new Uint8Array(width * height * 4);
+
+var lineWidth = 0;
+var elemMult = 0;
+
+var knownColors = [
+ 1.0, 0.0, 0.0, 1.0, // Red
+ 0.0, 1.0, 0.0, 1.0, // Green
+ 0.0, 0.0, 1.0, 1.0, // Blue
+ 0.0, 1.0, 1.0, 1.0, // Cyan
+ 1.0, 0.0, 1.0, 1.0, // Magenta
+ 1.0, 1.0, 0.0, 1.0 // Yellow
+];
+
+function main() {
+ var wtu = WebGLTestUtils;
+ gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(
+ gl,
+ ['vshader', 'fshader'],
+ ['vPosition'], [0]);
+
+ // setupQuad produces the geometry we want for a gridRes x gridRes grid
+ // of points. No interpolation will be performed across the points, so
+ // according to the WebGL specification for out-of-bounds array accesses,
+ // we will get exactly the input colors from the uniform colorArray, or
+ // zero, for each pixel on the canvas.
+ wtu.setupIndexedQuad(gl, gridRes, 0);
+ var colorArrayLoc = gl.getUniformLocation(program, "colorArray[0]");
+ assertMsg(colorArrayLoc != null, "color array uniform should be found");
+ var colors = new Float32Array(knownColors);
+ gl.uniform4fv(colorArrayLoc, colors);
+ lineWidthLoc = gl.getUniformLocation(program, "lineWidth");
+ elemMultLoc = gl.getUniformLocation(program, "elemMult");
+ assertMsg(gl.getError() == gl.NO_ERROR, "Should be no errors from setup.");
+ runOneIteration();
+}
+
+function withinEpsilon(val1, val2) {
+ return Math.abs(val1 - val2) < 0.0001;
+}
+
+function isKnownColor(r, g, b) {
+ if (r == 0 && g == 0 && b == 0)
+ return true;
+ for (var ii = 0; ii < knownColors.length; ii += 4) {
+ if (withinEpsilon(r / 255.0, knownColors[ii + 0]) &&
+ withinEpsilon(g / 255.0, knownColors[ii + 1]) &&
+ withinEpsilon(b / 255.0, knownColors[ii + 2]))
+ return true;
+ }
+ return false;
+}
+
+function runOneIteration() {
+ if (elemMult < 2048) {
+ var ok = true;
+ var startingLineWidth = lineWidth;
+ var firstFailingPixel = null;
+ var firstFailingValue = null;
+ for (; lineWidth < 2540; lineWidth += 31) {
+ // Draw
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.uniform1f(lineWidthLoc, lineWidth);
+ gl.uniform1i(elemMultLoc, elemMult);
+ gl.drawArrays(gl.POINTS, 0, gridRes * gridRes);
+
+ // Read back
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+
+ // Verify
+ for (var y = 0; y < height; ++y) {
+ for (var x = 0; x < width; ++x) {
+ if (!isKnownColor(pixels[4 * (width * y + x) + 0],
+ pixels[4 * (width * y + x) + 1],
+ pixels[4 * (width * y + x) + 2])) {
+ ok = false;
+ if (firstFailingPixel == null) {
+ firstFailingPixel = [x, y];
+ firstFailingValue = [pixels[4 * (width * y + x) + 0],
+ pixels[4 * (width * y + x) + 1],
+ pixels[4 * (width * y + x) + 2]];
+ }
+ }
+ }
+ }
+ }
+ var endingLineWidth = lineWidth - 31;
+ lineWidth -= 2540;
+ if (ok) {
+ testPassed("Good rendering results for lineWidths " +
+ startingLineWidth + "..." + endingLineWidth +
+ " at elemMult=" + elemMult);
+ } else {
+ testFailed("for lineWidth=" + lineWidth + ", elemMult=" + elemMult +
+ ": first failing pixel (" + firstFailingPixel[0] + ", " + firstFailingPixel[1] + ") was (" +
+ firstFailingValue[0] + ", " +
+ firstFailingValue[1] + ", " +
+ firstFailingValue[2] + "), should be (0, 0, 0) or one of known colors");
+ }
+ elemMult += 73;
+ setTimeout(runOneIteration, 0);
+ } else {
+ finishTest();
+ }
+}
+
+main();
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-default-values.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-default-values.html
new file mode 100644
index 0000000000..862182c272
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-default-values.html
@@ -0,0 +1,339 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform default values</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/test-eval.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader0" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshader0" type="x-shader/x-fragment">
+precision mediump float;
+uniform $(type) u_uniform;
+
+bool isZero($(type) value) {
+ $(check);
+}
+
+void main()
+{
+ gl_FragColor = isZero(u_uniform) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script id="vshader1" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 v_color;
+uniform $(type) u_uniform;
+
+bool isZero($(type) value) {
+ $(check);
+}
+
+void main()
+{
+ gl_Position = vPosition;
+ v_color = isZero(u_uniform) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script id="fshader1" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main()
+{
+ gl_FragColor = v_color;
+}
+</script>
+<script id="vshader2" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshader2" type="x-shader/x-fragment">
+precision mediump float;
+uniform $(type) u_uniform[2];
+
+bool isZero($(type) value) {
+ $(check);
+}
+
+void main()
+{
+ gl_FragColor = isZero(u_uniform[1]) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script id="vshader3" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 v_color;
+uniform $(type) u_uniform[2];
+
+bool isZero($(type) value) {
+ $(check);
+}
+
+void main()
+{
+ gl_Position = vPosition;
+ v_color = isZero(u_uniform[1]) ? vec4(0,1,0,1) : vec4(1,0,0,1);
+}
+</script>
+<script id="fshader3" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main()
+{
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+description();
+
+var tests = [
+{ type: 'float',
+ check: "return value == 0.0",
+ setFn: function(gl, loc) { gl.uniform1f(loc, 3.0); }
+},
+{ type: 'int',
+ check: "return value == 0",
+ setFn: function(gl, loc) { gl.uniform1i(loc, 3.0); }
+},
+{ type: 'bool',
+ check: "return value == false",
+ setFn: function(gl, loc) { gl.uniform1i(loc, 1); }
+},
+{ type: 'vec2',
+ check: "return value[0] == 0.0 && value[1] == 0.0",
+ setFn: function(gl, loc) { gl.uniform2f(loc, 3.0, 3.0); }
+},
+{ type: 'vec3',
+ check: "return value[0] == 0.0 && value[1] == 0.0 && value[2] == 0.0",
+ setFn: function(gl, loc) { gl.uniform3f(loc, 3.0, 3.0, 3.0); }
+},
+{ type: 'vec4',
+ check: "return value[0] == 0.0 && value[1] == 0.0 && value[2] == 0.0 && value[3] == 0.0",
+ setFn: function(gl, loc) { gl.uniform4f(loc, 3.0, 3.0, 3.0, 3.0); }
+},
+{ type: 'ivec2',
+ check: "return value[0] == 0 && value[1] == 0",
+ setFn: function(gl, loc) { gl.uniform2i(loc, 3, 3); }
+},
+{ type: 'ivec3',
+ check: "return value[0] == 0 && value[1] == 0 && value[2] == 0",
+ setFn: function(gl, loc) { gl.uniform3i(loc, 3, 3, 3); }
+},
+{ type: 'ivec4',
+ check: "return value[0] == 0 && value[1] == 0 && value[2] == 0 && value[3] == 0",
+ setFn: function(gl, loc) { gl.uniform4i(loc, 3, 3, 3, 3); }
+},
+{ type: 'bvec2',
+ check: "return value[0] == false && value[1] == false",
+ setFn: function(gl, loc) { gl.uniform2i(loc, 1, 1); }
+},
+{ type: 'bvec3',
+ check: "return value[0] == false && value[1] == false && value[2] == false",
+ setFn: function(gl, loc) { gl.uniform3i(loc, 1, 1, 1); }
+},
+{ type: 'bvec4',
+ check: "return value[0] == false && value[1] == false && value[2] == false && value[3] == false",
+ setFn: function(gl, loc) { gl.uniform4i(loc, 1, 1, 1, 1); }
+},
+{ type: 'mat2',
+ check:
+ "return " +
+ "value[0][0] == 0.0 && value[0][1] == 0.0 && " +
+ "value[1][0] == 0.0 && value[1][0] == 0.0",
+ valueCheck:
+ "return " +
+ "value[0] == 0.0 && value[1] == 0.0 && " +
+ "value[2] == 0.0 && value[3] == 0.0",
+ setFn: function(gl, loc) { gl.uniformMatrix2fv(loc, false, [1, 1, 1, 1]); }
+},
+{ type: 'mat3',
+ check:
+ "return " +
+ "value[0][0] == 0.0 && value[1][0] == 0.0 && value[2][0] == 0.0 && " +
+ "value[0][1] == 0.0 && value[1][1] == 0.0 && value[2][1] == 0.0 && " +
+ "value[0][2] == 0.0 && value[1][2] == 0.0 && value[2][2] == 0.0",
+ valueCheck:
+ "return " +
+ "value[0] == 0.0 && value[1] == 0.0 && value[2] == 0.0 && " +
+ "value[3] == 0.0 && value[4] == 0.0 && value[5] == 0.0 && " +
+ "value[6] == 0.0 && value[7] == 0.0 && value[8] == 0.0",
+ setFn: function(gl, loc) { gl.uniformMatrix3fv(loc, false, [1, 1, 1, 1, 1, 1, 1, 1, 1]); }
+},
+{ type: 'mat4',
+ check:
+ "return " +
+ "value[0][0] == 0.0 && value[1][0] == 0.0 && value[2][0] == 0.0 && value[3][0] == 0.0 && " +
+ "value[0][1] == 0.0 && value[1][1] == 0.0 && value[2][1] == 0.0 && value[3][1] == 0.0 && " +
+ "value[0][2] == 0.0 && value[1][2] == 0.0 && value[2][2] == 0.0 && value[3][2] == 0.0 && " +
+ "value[0][3] == 0.0 && value[1][3] == 0.0 && value[2][3] == 0.0 && value[3][3] == 0.0",
+ valueCheck:
+ "return " +
+ "value[ 0] == 0.0 && value[ 1] == 0.0 && value[ 2] == 0.0 && value[ 3] == 0.0 && " +
+ "value[ 4] == 0.0 && value[ 5] == 0.0 && value[ 6] == 0.0 && value[ 7] == 0.0 && " +
+ "value[ 8] == 0.0 && value[ 9] == 0.0 && value[10] == 0.0 && value[11] == 0.0 && " +
+ "value[12] == 0.0 && value[13] == 0.0 && value[14] == 0.0 && value[15] == 0.0",
+ setFn: function(gl, loc) { gl.uniformMatrix4fv(loc, false, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); }
+},
+{ type: 'sampler2D',
+ check:
+ "vec4 v = texture2D(value, vec2(0, 0));" +
+ "return v.x == 1.0 && v.y == 1.0 && v.z == 1.0 && v.w == 1.0",
+ valueCheck:
+ "return value == 0",
+ setFn: function(gl, loc) { gl.uniform1i(loc, 1); }
+},
+{ type: 'samplerCube',
+ check:
+ "vec4 v = textureCube(value, vec3(0, 0, 0));" +
+ "return v.x == 1.0 && v.y == 1.0 && v.z == 1.0 && v.w == 1.0",
+ valueCheck:
+ "return value == 0",
+ setFn: function(gl, loc) { gl.uniform1i(loc, 1); }
+},
+];
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var c = document.getElementById("console");
+var checkFn;
+
+wtu.setupUnitQuad(gl, [0, 1]);
+
+// Set unit 0 to a non-0 texture.
+var haveVertexTextureImageUnits =
+ gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) >= 2;
+var tex2D = gl.createTexture();
+var texCube = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex2D);
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+
+var pixel = new Uint8Array([255, 255, 255, 255]);
+var targets = [
+ gl.TEXTURE_2D,
+ 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 ii = 0; ii < targets.length; ++ii) {
+ gl.texImage2D(
+ targets[ii], 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+}
+
+var shaderTemplates = [
+{ vs: "vshader0", fs: "fshader0", type: 'f' },
+{ vs: "vshader1", fs: "fshader1", type: 'v' },
+{ vs: "vshader2", fs: "fshader2", type: 'f' },
+{ vs: "vshader3", fs: "fshader3", type: 'v' },
+];
+
+// Get shader templates
+for (var ii = 0; ii < shaderTemplates.length; ++ii) {
+ var template = shaderTemplates[ii];
+ template.vs = wtu.getScript(template.vs);
+ template.fs = wtu.getScript(template.fs);
+}
+
+function testType(test) {
+ debug("");
+ debug("testing: " + test.type);
+
+ for (var ii = 0; ii < shaderTemplates.length; ++ii) {
+ var template = shaderTemplates[ii];
+
+ if (test.type.substring(0, 7) == "sampler" &&
+ template.type == 'v' &&
+ !haveVertexTextureImageUnits) {
+ continue;
+ }
+
+ var vs = wtu.replaceParams(template.vs, test);
+ var fs = wtu.replaceParams(template.fs, test);
+
+ wtu.addShaderSource(c, "vertex shader", vs);
+ wtu.addShaderSource(c, "fragment shader", fs);
+
+ var vs = wtu.loadShader(gl, vs, gl.VERTEX_SHADER);
+ var fs = wtu.loadShader(gl, fs, gl.FRAGMENT_SHADER);
+ var program = wtu.createProgram(gl, vs, fs);
+
+ gl.useProgram(program);
+
+ var loc = gl.getUniformLocation(program, "u_uniform[1]");
+ if (!loc) {
+ var loc = gl.getUniformLocation(program, "u_uniform");
+ }
+
+ var value = gl.getUniform(program, loc);
+ TestEval("checkFn = function(value) {" + (test.valueCheck ? test.valueCheck : test.check) + ";}");
+ if (checkFn(value)) {
+ testPassed("uniform is zero");
+ } else {
+ testFailed("uniform is not zero");
+ }
+
+ debug("default value should be zero");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
+
+ debug("test test by setting value");
+ test.setFn(gl, loc);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red", 0);
+
+ debug("re-linking should reset to defaults");
+ gl.linkProgram(program);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
+
+ gl.deleteProgram(program);
+ gl.deleteShader(vs);
+ gl.deleteShader(fs);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no GL errors");
+ }
+}
+
+var testNdx = 0;
+function runNextTest() {
+ testType(tests[testNdx++]);
+ if (testNdx >= tests.length) {
+ finishTest();
+ } else {
+ setTimeout(runNextTest, 0);
+ }
+}
+
+runNextTest();
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-location.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-location.html
new file mode 100644
index 0000000000..3b1c185caf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-location.html
@@ -0,0 +1,96 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests the WebGLUniformLocation API");
+
+var wtu = WebGLTestUtils;
+var contextA = wtu.create3DContext();
+var contextB = wtu.create3DContext();
+var programA1 = wtu.loadStandardProgram(contextA);
+var programA2 = wtu.loadStandardProgram(contextA);
+var programB = wtu.loadStandardProgram(contextB);
+var programS = wtu.loadProgramFromFile(contextA, "../../resources/structUniformShader.vert", "../../resources/fragmentShader.frag");
+var programV = wtu.loadProgramFromFile(contextA, "../../resources/floatUniformShader.vert", "../../resources/noopUniformShader.frag");
+var locationA = contextA.getUniformLocation(programA1, 'u_modelViewProjMatrix');
+var locationB = contextB.getUniformLocation(programB, 'u_modelViewProjMatrix');
+var locationSx = contextA.getUniformLocation(programS, "u_struct.x");
+var locationSx2;
+var locationArray0 = contextA.getUniformLocation(programS, "u_array[0]");
+var locationArray1 = contextA.getUniformLocation(programS, "u_array[1]");
+var locationVec4 = contextA.getUniformLocation(programV, "fval4");
+
+var vec = [1, 2, 3, 4];
+var mat = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
+
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.useProgram(programA2)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationA, false, mat)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.useProgram(programA1)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniformMatrix4fv(locationA, false, mat)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniformMatrix4fv(null, false, mat)");
+
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.useProgram(programS)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform1i(locationSx, 333)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform1f(locationArray0, 4.0)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform1f(locationArray1, 5.0)");
+
+shouldBe("contextA.getUniform(programS, locationSx)", "333");
+shouldBe("contextA.getUniform(programS, locationArray0)", "4.0");
+shouldBe("contextA.getUniform(programS, locationArray1)", "5.0");
+
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.useProgram(programV)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform4fv(locationVec4, vec)");
+shouldBe("contextA.getUniform(programV, locationVec4)", "vec");
+
+shouldBeNull("contextA.getUniformLocation(programV, \"IDontExist\")");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.linkProgram(programA1)");
+// After linking all boxes are bad.
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationA, false, mat)");
+
+// after re-linking the same program, all uniform locations become invalid.
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.useProgram(programS)");
+contextA.stencilMask(1);
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.linkProgram(programS)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1i(locationSx, 3)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programS, locationSx)");
+
+// Retrieve the locations again, and they should be good.
+locationSx = contextA.getUniformLocation(programS, "u_struct.x");
+locationArray0 = contextA.getUniformLocation(programS, "u_array[0]");
+debug("here");
+contextA.stencilMask(0);
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform1i(locationSx, 3)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform1f(locationArray0, 123)");
+shouldBe("contextA.getUniform(programS, locationSx)", "3");
+shouldBe("contextA.getUniform(programS, locationArray0)", "123");
+
+// getUniformLocation should return a different object everytime, should not cache and return the same object
+debug("Testing that getUniformLocation returns a different object everytime");
+locationSx = contextA.getUniformLocation(programS, "u_struct.x");
+locationSx2 = contextA.getUniformLocation(programS, "u_struct.x");
+shouldBeFalse("locationSx === locationSx2");
+locationSx.foo = {};
+locationSx2.foo = {};
+shouldBeFalse("locationSx.foo === locationSx2.foo");
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-samplers-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-samplers-test.html
new file mode 100644
index 0000000000..fc680c0eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-samplers-test.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL sampler uniforms conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+function init()
+{
+ description(
+ "Tests that only Uniform1i and Uniform1iv can be used to set" +
+ "sampler uniforms.");
+
+ var canvas2d = document.getElementById("canvas2d");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupTexturedQuad(gl);
+
+ var textureLoc = gl.getUniformLocation(program, "tex");
+
+ gl.uniform1i(textureLoc, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "uniform1i can set a sampler uniform");
+ gl.uniform1iv(textureLoc, [1]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "uniform1iv can set a sampler uniform");
+ gl.uniform1f(textureLoc, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "uniform1f returns INVALID_OPERATION if attempting to set a sampler uniform");
+ gl.uniform1fv(textureLoc, [1]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "uniform1fv returns INVALID_OPERATION if attempting to set a sampler uniform");
+
+ var maxTextureUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+
+ var testUniformi = function() {
+ var success = true;
+ for (var ii = 0; ii < maxTextureUnits; ++ii) {
+ gl.uniform1i(textureLoc, ii);
+ success = success && (gl.getError() == gl.NO_ERROR);
+ }
+ expectTrue(success, "uniform1i works for any valid texture unit");
+ };
+
+ var testUniformiv = function() {
+ var success = true;
+ for (var ii = 0; ii < maxTextureUnits; ++ii) {
+ gl.uniform1iv(textureLoc, [ii]);
+ success = success && (gl.getError() == gl.NO_ERROR);
+ }
+ expectTrue(success, "uniform1iv works for any valid texture unit");
+ };
+
+ var steps = [
+ testUniformi,
+ testUniformiv,
+ ];
+
+ var generateInvalidUniformiTests = function(start, end) {
+ return function() {
+ var success = true;
+ for (var ii = start; ii < end; ++ii) {
+ gl.uniform1i(textureLoc, ii);
+ success = success && (gl.getError() == gl.INVALID_VALUE);
+ }
+ expectTrue(success, "uniform1i generates INVALID_VALUE for invalid texture units 0x" + start.toString(16) + " to 0x" + end.toString(16));
+ };
+ };
+
+ var generateInvalidUniformivTests = function(start, end) {
+ return function() {
+ var success = true;
+ for (var ii = start; ii < end; ++ii) {
+ gl.uniform1iv(textureLoc, [ii]);
+ success = success && (gl.getError() == gl.INVALID_VALUE);
+ }
+ expectTrue(success, "uniform1iv generates INVALID_VALUE for invalid texture units 0x" + start.toString(16) + " to 0x" + end.toString(16));
+ };
+ };
+
+ var step = 0x1000;
+ for (var ii = maxTextureUnits; ii < 0x10000; ii += step) {
+ steps.push(generateInvalidUniformiTests(ii, ii + step));
+ steps.push(generateInvalidUniformivTests(ii, ii + step));
+ }
+
+ steps.push(finishTest);
+ wtu.runSteps(steps);
+}
+
+init();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-values-per-program.html b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-values-per-program.html
new file mode 100644
index 0000000000..6ff693f347
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/uniforms/uniform-values-per-program.html
@@ -0,0 +1,179 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform values are per program conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main() {
+ gl_FragColor = v_color;
+}
+</script>
+<script id="vshaderTest" type="x-shader/x-vertex">
+attribute vec4 a_position;
+uniform $(type) $(name1);
+uniform $(type) $(name2);
+uniform bool u_select;
+varying vec4 v_color;
+void main() {
+ $(type) value = u_select ? $(name2) : $(name1);
+ v_color = $(conversion);
+ gl_Position = a_position;
+}
+</script>
+<script id="fshaderTest" type="x-shader/x-fragment">
+precision mediump float;
+uniform $(type) $(name1);
+uniform $(type) $(name2);
+uniform bool u_select;
+void main() {
+ $(type) value = u_select ? $(name2) : $(name1);
+ gl_FragColor = $(conversion);
+}
+</script>
+<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function init() {
+ description();
+
+ var console = document.getElementById("console");
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ wtu.setupUnitQuad(gl);
+ var vtemplate = wtu.getScript("vshader");
+ var ftemplate = wtu.getScript("fshader");
+ var vtemplateTest = wtu.getScript("vshaderTest");
+ var ftemplateTest = wtu.getScript("fshaderTest");
+
+ var shaders = [
+ [vtemplate, ftemplateTest],
+ [vtemplateTest, ftemplate],
+ ];
+
+ var names = [
+ ["u_value1", "u_value2"],
+ ["a", "b"],
+ ["x", "y"],
+ ["y", "z"],
+ ["y", "u"],
+ ["a00000", "a00001"],
+ ];
+ var testList = [
+ { type: "float",
+ conversion: "vec4(value, 0, 0, 0)",
+ values: [[64], [128]],
+ func: 'uniform1fv',
+ },
+ { type: "vec2",
+ conversion: "vec4(value, 0, 0)",
+ values: [[64, 128], [128, 64]],
+ func: 'uniform2fv',
+ },
+ { type: "vec3",
+ conversion: "vec4(value, 0)",
+ values: [[64, 128, 192], [192, 128, 64]],
+ func: 'uniform3fv',
+ },
+ { type: "vec4",
+ conversion: "vec4(value)",
+ values: [[64, 128, 192, 255], [255, 192, 128, 64]],
+ func: 'uniform4fv',
+ },
+ ];
+
+ var clone = function(obj) {
+ var n = { };
+ for (var $key in obj) {
+ n[$key] = obj[$key];
+ }
+ return n;
+ };
+
+ var tests = [];
+ names.forEach(function(namePair) {
+ testList.forEach(function(test) {
+ var t = clone(test);
+ t.name1 = namePair[0];
+ t.name2 = namePair[1];
+ tests.push(t);
+ });
+ });
+
+ var runTest = function(test) {
+ debug("");
+ debug("testing: " + test.type);
+ shaders.forEach(function(shaderPair) {
+ var progs = [];
+ for (var ii = 0; ii < 2; ++ii) {
+ var vsource = wtu.replaceParams(shaderPair[0], test);
+ var fsource = wtu.replaceParams(shaderPair[1], test);
+ if (!ii) {
+ wtu.addShaderSource(console, "vertex shader: type = " + test.type + " with names " + test.name1 + ", " + test.name2, vsource);
+ wtu.addShaderSource(console, "fragment shader: type = " + test.type + " with names " + test.name1 + ", " + test.name2, fsource);
+ }
+ var program = wtu.setupProgram(gl, [vsource, fsource], ["a_position"]);
+ var info = {
+ program: program,
+ valueLocs: [gl.getUniformLocation(program, test.name1),
+ gl.getUniformLocation(program, test.name2)],
+ selectLoc: gl.getUniformLocation(program, "u_select"),
+ };
+ var v1 = test.values[0];
+ var v2 = test.values[1];
+ if (ii) {
+ var t = v1;
+ v1 = v2;
+ v2 = t;
+ }
+ info.expect = [v1, v2];
+ for (var jj = 0; jj < 2; ++jj) {
+ var input = info.expect[jj].map(function(v) { return v / 255; });
+ gl[test.func](info.valueLocs[jj], input);
+ }
+ progs.push(info);
+ }
+ for (var ii = 0; ii < 2; ++ii) {
+ progs.forEach(function(info) {
+ gl.useProgram(info.program);
+ gl.uniform1i(info.selectLoc, ii);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, info.expect[ii], undefined, 1);
+ });
+ }
+ progs.forEach(function(info) {
+ gl.deleteProgram(info.program);
+ });
+ });
+ }
+ tests.forEach(function(test){
+ runTest(test);
+ });
+}
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/00_test_list.txt
new file mode 100644
index 0000000000..e251dc9758
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/00_test_list.txt
@@ -0,0 +1,20 @@
+attribs/00_test_list.txt
+buffers/00_test_list.txt
+canvas/00_test_list.txt
+context/00_test_list.txt
+extensions/00_test_list.txt
+glsl3/00_test_list.txt
+misc/00_test_list.txt
+--min-version 2.0.1 offscreencanvas/00_test_list.txt
+programs/00_test_list.txt
+query/00_test_list.txt
+reading/00_test_list.txt
+renderbuffers/00_test_list.txt
+rendering/00_test_list.txt
+samplers/00_test_list.txt
+state/00_test_list.txt
+sync/00_test_list.txt
+textures/00_test_list.txt
+transform_feedback/00_test_list.txt
+uniforms/00_test_list.txt
+vertex_arrays/00_test_list.txt
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
new file mode 100644
index 0000000000..08ef3bdac8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
@@ -0,0 +1,8 @@
+--min-version 2.0.1 gl-bindAttribLocation-aliasing-inactive.html
+gl-vertex-attrib.html
+gl-vertex-attrib-i-render.html
+--min-version 2.0.1 gl-vertex-attrib-normalized-int.html
+gl-vertexattribipointer.html
+gl-vertexattribipointer-offsets.html
+--min-version 2.0.1 invalid-vertex-attribs.html
+--min-version 2.0.1 render-no-enabled-attrib-arrays.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html
new file mode 100644
index 0000000000..abbbc43d6a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html
@@ -0,0 +1,55 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/gl-bindattriblocation-aliasing.js"></script>
+<title>bindAttribLocation with aliasing - inactive attributes</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script id="vertexShaderStaticallyUsedButInactive" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+in $(type_1) a_1;
+in $(type_2) a_2;
+void main() {
+ gl_Position = true ? $(gl_Position_1) : $(gl_Position_2);
+}
+</script>
+<script id="vertexShaderUnused" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+in $(type_1) a_1;
+in $(type_2) a_2;
+void main() {
+ gl_Position = vec4(0.0);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies combinations of valid inactive attributes cannot be bound to the same location with bindAttribLocation. GLSL ES 3.00.6 section 12.46.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false}, 2);
+var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShaderESSL300, gl.FRAGMENT_SHADER);
+
+debug("Testing with shader that has statically used but inactive attributes.");
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShaderStaticallyUsedButInactive'));
+
+debug("");
+debug("Testing with shader that has entirely unused attributes.");
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShaderUnused'));
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-i-render.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-i-render.html
new file mode 100644
index 0000000000..5fcbc786fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-i-render.html
@@ -0,0 +1,108 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>#version 300 es
+layout(location=0) in ivec2 p;
+layout(location=1) in ivec4 a;
+void main()
+{
+ gl_Position = vec4(p.x + a.x + a.y + a.z + a.w, p.y, 0.0, 10.0);
+}
+</script>
+<script id='vshader_unsigned' type='x-shader/x-vertex'>#version 300 es
+layout(location=0) in ivec2 p;
+layout(location=1) in uvec4 a;
+void main()
+{
+ gl_Position = vec4(p.x + int(a.x + a.y + a.z + a.w), p.y, 0.0, 10.0);
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+void main()
+{
+ oColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+function checkRedPortion(gl, w, low, high) {
+ var buf = new Uint8Array(w * w * 4);
+ gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var i = 0;
+ for (; i < w; ++i) {
+ if (buf[i * 4 + 0] == 255 && buf[i * 4 + 1] == 0 && buf[i * 4 + 2] == 0 && buf[i * 4 + 3] == 255) {
+ break;
+ }
+ }
+ return low <= i && i <= high;
+}
+
+function runTest() {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('testbed', { preserveDrawingBuffer : true }, 2);
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ var program_unsigned = wtu.setupProgram(gl, ['vshader_unsigned', 'fshader']);
+
+ gl.enableVertexAttribArray(0);
+ var pos = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, pos);
+ gl.bufferData(gl.ARRAY_BUFFER, new Int32Array([-10, -10, 10, -10, -10, 10, 10, 10]), gl.STATIC_DRAW);
+
+ gl.vertexAttribIPointer(0, 2, gl.INT, 4 * 2, 0);
+
+ debug('Test vertexAttribI4[ui][v] by setting different combinations that add up to 15 and use that when rendering.');
+ var vals = [[2, -3, 6, 10], [1, 3, 1, 10], [-10, 3, 2, 20], [5, 6, 2, 2]];
+ var tests = ['vertexAttribI4i', 'vertexAttribI4ui', 'vertexAttribI4iv', 'vertexAttribI4uiv'];
+
+ for (var ii = 0; ii < 4; ++ii) {
+ if (ii % 2 == 0) {
+ gl.useProgram(program);
+ } else {
+ gl.useProgram(program_unsigned);
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (ii < 2) {
+ gl[tests[ii]](1, vals[ii][0], vals[ii][1], vals[ii][2], vals[ii][3]);
+ } else {
+ gl[tests[ii]](1, vals[ii]);
+ }
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ if (checkRedPortion(gl, 50, 50 * 0.7, 50 * 0.8)) {
+ testPassed('Attribute of ' + tests[ii] + ' was set correctly');
+ } else {
+ testFailed('Attribute of ' + tests[ii] + ' was not set correctly');
+ }
+ }
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that using constant attributes for vertexAttribI* works.');
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-normalized-int.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-normalized-int.html
new file mode 100644
index 0000000000..e1e24be608
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib-normalized-int.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <title>WebGL 2 Normalized Vertex Attributes Conformance Test</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+</head>
+<body>
+ <canvas width=1 height=1></canvas>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id="vertex-shader" type="x-shader/x-vertex">#version 300 es
+ layout(location = 0) in vec3 vertex;
+
+ out float normAttrib;
+
+ void main(void) {
+ gl_Position = vec4(vertex.xy, 0, 1);
+ normAttrib = vertex.z;
+ }
+ </script>
+ <script id="fragment-shader" type="x-shader/x-fragment">#version 300 es
+ in lowp float normAttrib;
+
+ layout(location=0) out lowp vec4 fragColor;
+
+ void main(void) {
+ fragColor = vec4(vec3(normAttrib == -1.0 ? 1.0 : 0.0), 1);
+ }
+ </script>
+ <script src="../../js/js-test-pre.js"></script>
+ <script src="../../js/webgl-test-utils.js"></script>
+ <script>
+ (function () {
+ 'use strict';
+
+ var wtu = WebGLTestUtils;
+
+ var gl = wtu.create3DContext(document.querySelector('canvas'), null, 2);
+
+ var program = wtu.setupProgram(gl, ['vertex-shader', 'fragment-shader']);
+
+ gl.useProgram(program);
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Int8Array([
+ // Here we set the third component (the one that's actually tested)
+ // to (MIN_INT + 1). If non-zero-preserving rules are used, it'll be
+ // converted to a float that's slightly greater than -1. If zero-preserving
+ // rules are used, as the GLES 3 spec requires, result of conversion
+ // should be exactly -1.
+ -0x80, 0x7f, -0x7f,
+ 0x7f, 0x7f, -0x7f,
+ -0x80, -0x7f, -0x7f,
+ -0x80, -0x7f, -0x7f,
+ 0x7f, 0x7f, -0x7f,
+ 0x7f, -0x80, -0x7f
+ ]), gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.BYTE, true, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 6);
+
+ wtu.checkCanvas(gl, [255, 255, 255, 255], "should be opaque white");
+ }());
+ </script>
+ <script>
+ description('Verify that conversion of normalized signed int attributes to floats uses zero-preserving rule.');
+ window.successfullyParsed = true;
+ </script>
+ <script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib.html
new file mode 100644
index 0000000000..1d12f088d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertex-attrib.html
@@ -0,0 +1,28 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL vertexAttrib Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/gl-vertex-attrib.js"></script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer-offsets.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer-offsets.html
new file mode 100644
index 0000000000..37f6554647
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer-offsets.html
@@ -0,0 +1,154 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>vertexAttribIPointer offsets tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+There is supposed to be an example drawing here, but it's not important.
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+layout(location=0) in ivec4 aPosition;
+layout(location=1) in vec4 aColor;
+out vec4 vColor;
+void main()
+{
+ gl_Position = vec4(aPosition);
+ vColor = aColor;
+}
+</script>
+
+<script id="vshader_unsigned" type="x-shader/x-vertex">#version 300 es
+layout(location=0) in uvec4 aPosition;
+layout(location=1) in vec4 aColor;
+out vec4 vColor;
+void main()
+{
+ gl_Position = vec4(aPosition);
+ vColor = aColor;
+}
+
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+in vec4 vColor;
+layout(location=0) out vec4 oColor;
+void main()
+{
+ oColor = vColor;
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description("test vertexAttribIPointer offsets work");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example", undefined, 2);
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"]);
+ var program_unsigned = wtu.setupProgram(gl, ["vshader_unsigned", "fshader"]);
+
+ var tests = [
+ { data: new Int32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.INT,
+ componentSize: 4,
+ },
+ { data: new Uint32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_INT,
+ componentSize: 4,
+ },
+ { data: new Uint16Array([ 0, 32767, 0, 32767, 0, 0, 0, 0, 0 ]),
+ type: gl.SHORT,
+ componentSize: 2,
+ },
+ { data: new Uint16Array([ 0, 65535, 0, 65535, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_SHORT,
+ componentSize: 2,
+ },
+ { data: new Uint8Array([ 0, 127, 0, 127, 0, 0, 0, 0, 0 ]),
+ type: gl.BYTE,
+ componentSize: 1,
+ },
+ { data: new Uint8Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
+ type: gl.UNSIGNED_BYTE,
+ componentSize: 1,
+ }
+ ];
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+
+ var kNumVerts = 3;
+ var kNumComponents = 3;
+
+ var count = 0;
+ for (var tt = 0; tt < tests.length; ++tt) {
+ var test = tests[tt];
+ for (var oo = 0; oo < 3; ++oo) {
+ for (var ss = 0; ss < 3; ++ss) {
+ var offset = (oo + 1) * test.componentSize;
+ var color = (count % 2) ? [1, 0, 0, 1] : [0, 1, 0, 1];
+ var stride = test.componentSize * kNumComponents + test.componentSize * ss;
+ debug("");
+ debug("check with " + wtu.glEnumToString(gl, test.type) + " at offset: " + offset + " with stride:" + stride);
+ if (test.type == gl.INT || test.type == gl.SHORT || test.type == gl.BYTE) {
+ gl.useProgram(program);
+ } else {
+ gl.useProgram(program_unsigned);
+ }
+ gl.vertexAttrib4fv(1, color);
+ var data = new Uint8Array(test.componentSize * kNumVerts * kNumComponents + stride * (kNumVerts - 1));
+ var view = new Uint8Array(test.data.buffer);
+ var size = test.componentSize * kNumComponents;
+ for (var jj = 0; jj < kNumVerts; ++jj) {
+ var off1 = jj * size;
+ var off2 = jj * stride;
+ for (var zz = 0; zz < size; ++zz) {
+ data[off2 + zz] = view[off1 + zz];
+ }
+ }
+ gl.bufferSubData(gl.ARRAY_BUFFER, offset, data);
+ gl.vertexAttribIPointer(0, 3, test.type, stride, offset);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ var buf = new Uint8Array(50 * 50 * 4);
+ gl.readPixels(0, 0, 50, 50, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+ var black = [0, 0, 0, 0];
+ var other = [color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255];
+ var otherMsg = "should be " + ((count % 2) ? "red" : "green")
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, black, "should be black", 0);
+ wtu.checkCanvasRect(gl, 0, 49, 1, 1, black, "should be black", 0);
+ wtu.checkCanvasRect(gl, 26, 40, 1, 1, other, otherMsg, 0);
+ wtu.checkCanvasRect(gl, 26, 27, 1, 1, other, otherMsg, 0);
+ wtu.checkCanvasRect(gl, 40, 27, 1, 1, other, otherMsg, 0);
+ ++count;
+ }
+ }
+ }
+}
+
+init();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer.html
new file mode 100644
index 0000000000..ecefc6d4e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-vertexattribipointer.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL vertexAttribIPointer Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks vertexAttribIPointer behaviors in WebGL 2.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking gl.vertexAttribIPointer.");
+
+ gl.vertexAttribIPointer(0, 3, gl.INT, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "vertexAttribIPointer should succeed if no buffer is bound and offset is zero");
+
+ gl.vertexAttribIPointer(0, 3, gl.INT, 0, 12);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "vertexAttribIPointer should fail if no buffer is bound and offset is non-zero");
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Int32Array(0), gl.STATIC_DRAW);
+
+ gl.vertexAttribIPointer(0, 1, gl.FLOAT, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "vertexAttribIPointer should not support FLOAT");
+
+ var checkVertexAttribIPointer = function(
+ gl, err, reason, size, type, stride, offset) {
+ gl.vertexAttribIPointer(0, size, type, stride, offset);
+ wtu.glErrorShouldBe(gl, err,
+ "gl.vertexAttribIPointer(0, " + size +
+ ", gl." + wtu.glEnumToString(gl, type) +
+ ", " + stride +
+ ", " + offset +
+ ") should " + (err == gl.NO_ERROR ? "succeed " : "fail ") + reason);
+ }
+
+ var types = [
+ { type:gl.BYTE, bytesPerComponent: 1 },
+ { type:gl.UNSIGNED_BYTE, bytesPerComponent: 1 },
+ { type:gl.SHORT, bytesPerComponent: 2 },
+ { type:gl.UNSIGNED_SHORT, bytesPerComponent: 2 },
+ { type:gl.INT, bytesPerComponent: 4 },
+ { type:gl.UNSIGNED_INT, bytesPerComponent: 4 },
+ ];
+
+ for (var ii = 0; ii < types.length; ++ii) {
+ var info = types[ii];
+ debug("");
+ for (var size = 1; size <= 4; ++size) {
+ debug("");
+ debug("checking: " + wtu.glEnumToString(gl, info.type) + " with size " + size);
+ var bytesPerElement = size * info.bytesPerComponent;
+ var offsetSet = [
+ 0,
+ 1,
+ info.bytesPerComponent - 1,
+ info.bytesPerComponent,
+ info.bytesPerComponent + 1,
+ info.bytesPerComponent * 2];
+ for (var jj = 0; jj < offsetSet.length; ++jj) {
+ var offset = offsetSet[jj];
+ for (var kk = 0; kk < offsetSet.length; ++kk) {
+ var stride = offsetSet[kk];
+ var err = gl.NO_ERROR;
+ var reason = ""
+ if (offset % info.bytesPerComponent != 0) {
+ reason = "because offset is bad";
+ err = gl.INVALID_OPERATION;
+ }
+ if (stride % info.bytesPerComponent != 0) {
+ reason = "because stride is bad";
+ err = gl.INVALID_OPERATION;
+ }
+ checkVertexAttribIPointer(
+ gl, err, reason, size, info.type, stride, offset);
+ }
+ var stride = Math.floor(255 / info.bytesPerComponent) * info.bytesPerComponent;
+
+ if (offset == 0) {
+ checkVertexAttribIPointer(
+ gl, gl.NO_ERROR, "at stride limit",
+ size, info.type, stride, offset);
+ checkVertexAttribIPointer(
+ gl, gl.INVALID_VALUE, "over stride limit",
+ size, info.type, stride + info.bytesPerComponent, offset);
+ }
+ }
+ }
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/invalid-vertex-attribs.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/invalid-vertex-attribs.html
new file mode 100644
index 0000000000..8f9f975001
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/invalid-vertex-attribs.html
@@ -0,0 +1,73 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 draw functions have expected behavior with invalid vertex attribs</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/invalid-vertex-attrib-test.js"></script>
+<style>
+body {
+ height: 3000px;
+}
+</style>
+</head>
+<body>
+<!-- Important to put the canvas at the top so that it's always visible even in the test suite runner.
+ Otherwise it just doesn't get composited in Firefox. -->
+<div id="description"></div>
+<canvas id="canvas" width="16" height="16"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+
+description(`\
+This test ensures WebGL implementations correctly generate INVALID_OPERATION
+when an attribute is enabled but no buffer is bound`);
+debug("");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext('canvas', undefined, 2);
+
+async function runInvalidAttribTests() {
+ const invalidAttribTestFn = createInvalidAttribTestFn(gl);
+
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ function drawArraysInstanced(gl) {
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, 1);
+ }
+
+ function drawElementsInstanced(gl) {
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1);
+ }
+
+ function drawRangeElements(gl) {
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ await invalidAttribTestFn(drawArrays);
+ await invalidAttribTestFn(drawElements);
+ await invalidAttribTestFn(drawArraysInstanced);
+ await invalidAttribTestFn(drawElementsInstanced);
+ await invalidAttribTestFn(drawRangeElements);
+ finishTest();
+}
+runInvalidAttribTests();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/render-no-enabled-attrib-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/render-no-enabled-attrib-arrays.html
new file mode 100644
index 0000000000..841119fecb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/render-no-enabled-attrib-arrays.html
@@ -0,0 +1,66 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Verify drawing without any enabled vertex attribute arrays</title>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>#version 300 es
+layout(location=0) in vec4 inColor;
+out vec4 varyingColor;
+void main()
+{
+ varyingColor = inColor;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_PointSize = 1.0;
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+in vec4 varyingColor;
+layout(location=0) out vec4 oColor;
+void main()
+{
+ oColor = varyingColor;
+}
+</script>
+<script>
+"use strict";
+
+function runTest() {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("testCanvas", undefined, 2);
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ gl.disableVertexAttribArray(0);
+ gl.vertexAttrib4f(0, 0.0, 1.0, 0.0, 1.0);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "Canvas should be covered by a single green point");
+}
+</script>
+</head>
+<body>
+<canvas id="testCanvas" width="1" height="1" style="width: 32px; height: 32px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt
new file mode 100644
index 0000000000..21e4bb2bc4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt
@@ -0,0 +1,13 @@
+bound-buffer-size-change-test.html
+buffer-copying-contents.html
+buffer-copying-restrictions.html
+buffer-data-and-buffer-sub-data-sub-source.html
+buffer-type-restrictions.html
+buffer-overflow-test.html
+--min-version 2.0.1 delete-buffer.html
+get-buffer-sub-data.html
+--min-version 2.0.1 get-buffer-sub-data-validity.html
+one-large-uniform-buffer.html
+uniform-buffers.html
+--min-version 2.0.1 uniform-buffers-second-compile.html
+--min-version 2.0.1 uniform-buffers-state-restoration.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html
new file mode 100644
index 0000000000..a61d154eb1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html
@@ -0,0 +1,119 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL buffer size change test for bindBufferBase/bindBufferRange</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("WebGL buffer size change for bindings through bindBufferBase/bindBufferRange");
+
+// This test verifies the ES3 behavior, that the bound buffer range (offset, size) is not
+// limited by the actual buffer size, and the driver is responsible that no out-of-range
+// access may happen.
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+debug("");
+debug("bindBufferBase with TRANSFORM_FEEDBACK_BUFFER target");
+var buffer1 = gl.createBuffer();
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Calling bindBufferBase on a buffer where no storage is allocated should succeed.");
+shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "buffer1");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer1");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "0");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "0");
+
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4, gl.STATIC_DRAW);
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer1");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "0");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "0");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("bindBufferBase with UNIFORM_BUFFER target");
+var buffer2 = gl.createBuffer();
+gl.bindBufferBase(gl.UNIFORM_BUFFER, 1, buffer2);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Calling bindBufferBase on a buffer where no storage is allocated should succeed.");
+shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "buffer2");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer2");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "0");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "0");
+
+gl.bufferData(gl.UNIFORM_BUFFER, 8, gl.STATIC_DRAW);
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer2");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "0");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "0");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("bindBufferRange with TRANSFORM_FEEDBACK_BUFFER target");
+var buffer3 = gl.createBuffer();
+gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer3, 4, 8);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Calling bindBufferRange on a buffer where no storage is allocated should succeed.");
+shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "buffer3");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4");
+
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4, gl.STATIC_DRAW);
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4");
+
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 12, gl.STATIC_DRAW);
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8");
+shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("bindBufferRange with UNIFORM_BUFFER target");
+var buffer4 = gl.createBuffer();
+var offset = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+gl.bindBufferRange(gl.UNIFORM_BUFFER, 1, buffer4, offset, 12);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Calling bindBufferRange on a buffer where no storage is allocated should succeed.");
+shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "buffer4");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer4");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "12");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "offset");
+
+gl.bufferData(gl.UNIFORM_BUFFER, offset + 8, gl.STATIC_DRAW);
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer4");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "12");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "offset");
+
+gl.bufferData(gl.UNIFORM_BUFFER, offset + 12, gl.STATIC_DRAW);
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer4");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "12");
+shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "offset");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-contents.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-contents.html
new file mode 100644
index 0000000000..47d11093b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-contents.html
@@ -0,0 +1,176 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL buffer copying contents test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test copying a buffer's contents to another buffer governed by the WebGL 2 spec.");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var vertices = [
+ 1.1, 1.0, 1.3,
+ -1.0, -1.0, -5.0,
+ 5.3, -1.0, 1.0
+];
+
+debug("");
+debug("Test copying between buffers returns correct data");
+
+function testCopyBuffers(srcTarget, dstTarget, copyRead, copyWrite) {
+ var msg = "Copying from " + targetToString(gl, srcTarget) +
+ " to " + targetToString(gl, dstTarget)
+ if (copyRead && copyWrite)
+ msg += " via COPY_READ_BUFFER and COPY_WRITE_BUFFER"
+ else if (copyRead)
+ msg += " via COPY_READ_BUFFER"
+ else if (copyWrite)
+ msg += " via COPY_WRITE_BUFFER"
+ else
+ msg += " directly"
+ debug("")
+ debug(msg)
+
+ var srcBuffer = gl.createBuffer(), dstBuffer = gl.createBuffer();
+ var originalData = new Float32Array(vertices);
+ var length = vertices.length * 4;
+
+ gl.bindBuffer(srcTarget, srcBuffer);
+ gl.bufferData(srcTarget, originalData, gl.STATIC_DRAW);
+ if (copyRead)
+ gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer);
+
+ gl.bindBuffer(dstTarget, dstBuffer);
+ gl.bufferData(dstTarget, new Float32Array(length), gl.STATIC_DRAW);
+ if (copyWrite)
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, dstBuffer);
+
+ var expectedGLError = gl.NO_ERROR;
+
+ if (srcTarget == dstTarget) {
+ if (!copyRead && copyWrite) {
+ // srcBuffer isn't bound to any targets because of setting up dstBuffer.
+ gl.bindBuffer(srcTarget, srcBuffer);
+ }
+ if (!copyRead && !copyWrite) {
+ // Same buffer object, overlapping range.
+ expectedGLError = gl.INVALID_VALUE;
+ }
+ }
+ if ((srcTarget == gl.ELEMENT_ARRAY_BUFFER &&
+ dstTarget != gl.ELEMENT_ARRAY_BUFFER) ||
+ (srcTarget != gl.ELEMENT_ARRAY_BUFFER &&
+ dstTarget == gl.ELEMENT_ARRAY_BUFFER)) {
+ expectedGLError = gl.INVALID_OPERATION;
+ }
+
+ gl.copyBufferSubData(copyRead ? gl.COPY_READ_BUFFER : srcTarget,
+ copyWrite ? gl.COPY_WRITE_BUFFER : dstTarget,
+ 0, 0, length);
+ if (expectedGLError == gl.NO_ERROR) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Copying should work");
+
+ var retBuffer = new Uint8Array(length);
+ gl.getBufferSubData(dstTarget, 0, retBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.getBufferSubData(" + targetToString(gl, dstTarget) +
+ ", 0, retBuffer) should work");
+
+ var failed = false;
+ var retArray = new Float32Array(retBuffer.buffer);
+ for (var i = 0; i < vertices.length; i++) {
+ if (originalData[i] != retArray[i]) {
+ failed = true;
+ break;
+ }
+ }
+ if (failed)
+ testFailed("The returned array buffer fails to match original data");
+ else
+ testPassed("The returned array buffer matches original data");
+ } else {
+ wtu.glErrorShouldBe(gl, expectedGLError, "Copying should fail");
+ }
+
+ gl.deleteBuffer(srcBuffer);
+ gl.deleteBuffer(dstBuffer);
+ shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.COPY_READ_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.COPY_WRITE_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.PIXEL_PACK_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.PIXEL_UNPACK_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)");
+ shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+}
+
+function targetToString(gl, target) {
+ switch (target) {
+ case gl.ARRAY_BUFFER:
+ return "ARRAY_BUFFER";
+ case gl.COPY_READ_BUFFER:
+ return "COPY_READ_BUFFER";
+ case gl.COPY_WRITE_BUFFER:
+ return "COPY_WRITE_BUFFER";
+ case gl.ELEMENT_ARRAY_BUFFER:
+ return "ELEMENT_ARRAY_BUFFER";
+ case gl.PIXEL_PACK_BUFFER:
+ return "PIXEL_PACK_BUFFER";
+ case gl.PIXEL_UNPACK_BUFFER:
+ return "PIXEL_UNPACK_BUFFER";
+ case gl.TRANSFORM_FEEDBACK_BUFFER:
+ return "TRANSFORM_FEEDBACK_BUFFER";
+ case gl.UNIFORM_BUFFER:
+ return "UNIFORM_BUFFER";
+ default:
+ return "UNKNOWN BUFFER";
+ }
+}
+
+var targets = [
+ gl.ARRAY_BUFFER,
+ gl.ELEMENT_ARRAY_BUFFER,
+ gl.PIXEL_PACK_BUFFER,
+ gl.PIXEL_UNPACK_BUFFER,
+ gl.TRANSFORM_FEEDBACK_BUFFER,
+ gl.UNIFORM_BUFFER,
+]
+
+for (var srcIndex in targets) {
+ for (var dstIndex in targets) {
+ if (targets[srcIndex] != gl.TRANSFORM_FEEDBACK_BUFFER &&
+ targets[dstIndex] != gl.TRANSFORM_FEEDBACK_BUFFER) {
+ testCopyBuffers(targets[srcIndex], targets[dstIndex], true, true);
+ }
+ if (targets[srcIndex] != gl.TRANSFORM_FEEDBACK_BUFFER) {
+ testCopyBuffers(targets[srcIndex], targets[dstIndex], true, false);
+ }
+ if (targets[dstIndex] != gl.TRANSFORM_FEEDBACK_BUFFER) {
+ testCopyBuffers(targets[srcIndex], targets[dstIndex], false, true);
+ }
+ testCopyBuffers(targets[srcIndex], targets[dstIndex], false, false);
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html
new file mode 100644
index 0000000000..3bfe0e3e80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html
@@ -0,0 +1,102 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL buffer copying restrictions test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test buffer copying restrictions governed by the WebGL 2 spec. The test makes sure that copyBufferSubData acts as expected.");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+var validTargets = [gl.ARRAY_BUFFER, gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER,
+ gl.ELEMENT_ARRAY_BUFFER, gl.PIXEL_PACK_BUFFER,
+ gl.PIXEL_UNPACK_BUFFER, gl.TRANSFORM_FEEDBACK_BUFFER,
+ gl.UNIFORM_BUFFER];
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var testCopyBuffer = function(srcTarget, dstTarget) {
+ var srcTargetStr = wtu.glEnumToString(gl, srcTarget),
+ dstTargetStr = wtu.glEnumToString(gl, dstTarget);
+ var srcBuffer = gl.createBuffer(),
+ dstBuffer = gl.createBuffer();
+ var testCopyStr = "copying from a gl." + wtu.glEnumToString(gl, srcTarget) + " buffer to a gl."
+ + wtu.glEnumToString(gl, dstTarget) + " buffer"
+
+ gl.bindBuffer(srcTarget, srcBuffer);
+ gl.bufferData(srcTarget, new Float32Array(32), gl.STATIC_DRAW);
+ gl.bindBuffer(dstTarget, dstBuffer);
+ gl.bufferData(dstTarget, new Float32Array(32), gl.STATIC_DRAW);
+ gl.copyBufferSubData(srcTarget, dstTarget, 8, 0, 4);
+ if (srcTarget == dstTarget)
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, testCopyStr + " should work.");
+ else if (srcTarget == gl.ELEMENT_ARRAY_BUFFER || dstTarget == gl.ELEMENT_ARRAY_BUFFER )
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, testCopyStr + " should fail.");
+ else
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, testCopyStr + " should work.");
+
+ // Special case: COPY_READ_BUFFER and COPY_WRITE_BUFFER are compatible with ELEMENT_ARRAY_BUFFER
+ // only if the buffer had been initially bound to an ELEMENT_ARRAY_BUFFER
+ if (srcTarget == gl.ELEMENT_ARRAY_BUFFER &&
+ (dstTarget == gl.COPY_READ_BUFFER || dstTarget == gl.COPY_WRITE_BUFFER)) {
+ dstBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, dstBuffer);
+ } else if (dstTarget == gl.ELEMENT_ARRAY_BUFFER &&
+ (srcTarget == gl.COPY_READ_BUFFER || srcTarget == gl.COPY_WRITE_BUFFER)) {
+ srcBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, srcBuffer);
+ } else {
+ return;
+ }
+
+ gl.bindBuffer(srcTarget, srcBuffer);
+ gl.bufferData(srcTarget, new Float32Array(32), gl.STATIC_DRAW);
+ gl.bindBuffer(dstTarget, dstBuffer);
+ gl.bufferData(dstTarget, new Float32Array(32), gl.STATIC_DRAW);
+ gl.copyBufferSubData(srcTarget, dstTarget, 8, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, testCopyStr + " should work if all buffers were initially bound to ELEMENT_ARRAY_BUFFER.");
+};
+
+for (var i = 0; i < validTargets.length; i++) {
+ debug("");
+ debug("Copying data from a " + wtu.glEnumToString(gl, validTargets[i])
+ + " buffer to another target");
+ for (var j = 0; j < validTargets.length; j++)
+ testCopyBuffer(validTargets[i], validTargets[j]);
+}
+
+debug("");
+debug("Test copying a buffer of other data (gl.ARRAY_BUFFER) bound to gl.COPY_READ_BUFFER to a "
+ + "buffer bound to gl.ELEMENT_ARRAY_BUFFER");
+var srcBuffer = gl.createBuffer(), dstBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, srcBuffer);
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, dstBuffer);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Float32Array(32), gl.STATIC_DRAW);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(32), gl.STATIC_DRAW);
+gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer);
+gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ELEMENT_ARRAY_BUFFER, 0, 0, 4);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Copying gl.ARRAY_BUFFER bound to "
+ + "gl.COPY_READ_BUFFER to a buffer bound to gl.ELEMENT_ARRAY_BUFFER should fail.");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html
new file mode 100644
index 0000000000..ed9a131f77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html
@@ -0,0 +1,183 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test bufferData/bufferSubData with ArrayBufferView sub source input");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+function verifyBufferData(testCase, sourceByteOffset, size, data) {
+ var readbackBuffer = new ArrayBuffer(testCase.size * size);
+ var readbackView = new window[testCase.type](readbackBuffer);
+ gl.getBufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, readbackView);
+ var pass = true;
+ var offset = sourceByteOffset / testCase.size;
+ for (var ii = 0; ii < size; ++ii) {
+ if (readbackView[ii] != data[ii]) {
+ testFailed("expected data at " + ii + ": " + data[ii] + ", got " + readbackView[ii]);
+ pass = false;
+ }
+ }
+ if (pass) {
+ testPassed("buffer data uploaded correctly");
+ }
+}
+
+function bufferDataTest(testCases) {
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ var test = testCases[idx];
+ debug("");
+ debug("Test bufferData with " + test.type);
+
+ var buf = gl.createBuffer();
+ shouldBeNonNull(buf);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var count = 4;
+ var arrayBuffer = new ArrayBuffer(test.size * count);
+ var view = new window[test.type](arrayBuffer);
+ for (var ii = 0; ii < count; ++ii) {
+ view[ii] = ii;
+ }
+
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, 0, count + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferData when srcOffset + length is larger than source size");
+
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, count + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferData when srcOffset + length is larger than source size");
+
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, count - 1, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferData when srcOffset + length is larger than source size");
+
+ var offset = 2;
+ var size = count - offset;
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, offset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferData with valid sub source should succeed");
+ verifyBufferData(test, 0, size, view.slice(offset, offset + size));
+
+ offset = 1;
+ size = 1;
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, offset, size);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferData with valid sub source should succeed");
+ verifyBufferData(test, 0, size, view.slice(offset, offset + size));
+
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, count);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferData with valid sub source of size 0 should succeed");
+
+ gl.deleteBuffer(buf);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no GL error");
+ }
+}
+
+function bufferSubDataTest(testCases) {
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ var test = testCases[idx];
+ debug("");
+ debug("Test bufferSubData with " + test.type);
+
+ var count = 4;
+ var totalBufferBytes = test.size * count * 2;
+ var buf = gl.createBuffer();
+ shouldBeNonNull(buf);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, totalBufferBytes, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var arrayBuffer = new ArrayBuffer(test.size * count);
+ var view = new window[test.type](arrayBuffer);
+ for (var ii = 0; ii < count; ++ii) {
+ view[ii] = ii;
+ }
+
+ var sourceByteOffset = test.size * 2;
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, 0, count + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferSubData when srcOffset + length is larger than source size");
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, count + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferSubData when srcOffset + length is larger than source size");
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, count - 1, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling bufferSubData when srcOffset + length is larger than source size");
+
+ var offset = 2;
+ var size = count - offset;
+ gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, offset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferSubData with valid sub source should succeed");
+ verifyBufferData(test, sourceByteOffset, size, view.slice(offset, offset + size));
+
+ offset = 1;
+ size = 1;
+ gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, offset, size);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferSubData with valid sub source should succeed");
+ verifyBufferData(test, sourceByteOffset, size, view.slice(offset, offset + size));
+
+ gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, count);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling bufferSubData with valid sub source of size 0 should succeed");
+
+ gl.deleteBuffer(buf);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no GL error");
+ }
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ var testCases = [
+ {type: "Uint8Array", size: 1},
+ {type: "Int8Array", size: 1},
+ {type: "Int16Array", size: 2},
+ {type: "Uint16Array", size: 2},
+ {type: "Uint32Array", size: 4},
+ {type: "Int32Array", size: 4},
+ {type: "Float32Array", size: 4},
+ {type: "Float64Array", size: 8}
+ ];
+
+ bufferDataTest(testCases);
+ bufferSubDataTest(testCases);
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html
new file mode 100644
index 0000000000..9334ba5cb6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL buffer overflow test for bindBufferRange</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("WebGL buffer overflow test: buffer overflow will not lead to failure in bindBufferRange");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+debug("");
+var buffer1 = gl.createBuffer();
+gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer1, 0, 4);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Calling bindBufferRange on a buffer where no storage is allocated should succeed.");
+shouldBe("buffer1", "gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)");
+shouldBe("4", "gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)");
+shouldBe("0", "gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)");
+
+var buffer2 = gl.createBuffer();
+gl.bindBuffer(gl.UNIFORM_BUFFER, buffer2);
+gl.bufferData(gl.UNIFORM_BUFFER, 4, gl.STATIC_DRAW);
+gl.bindBufferRange(gl.UNIFORM_BUFFER, 1, buffer2, 0, 8);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Calling bindBufferRange on a buffer where the storage is not big enough should succeed.");
+shouldBe("buffer2", "gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)");
+shouldBe("8", "gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)");
+shouldBe("0", "gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)");
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html
new file mode 100644
index 0000000000..438b66df02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html
@@ -0,0 +1,110 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL buffer binding restrictions test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test binding restrictions governed by the WebGL 2 spec. The test makes sure that bindBuffer,"
+ + "bindBufferRange, and bindBufferBase acts as expected with every target combination.");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+var validTargets = [gl.ARRAY_BUFFER, gl.ELEMENT_ARRAY_BUFFER, gl.COPY_READ_BUFFER,
+ gl.COPY_WRITE_BUFFER, gl.PIXEL_PACK_BUFFER, gl.PIXEL_UNPACK_BUFFER,
+ gl.TRANSFORM_FEEDBACK_BUFFER, gl.UNIFORM_BUFFER];
+
+var bindFunctions = ["bindBuffer", "bindBufferRange", "bindBufferBase"];
+
+var isCopyTarget = function(target) {
+ return target == gl.COPY_READ_BUFFER || target == gl.COPY_WRITE_BUFFER;
+}
+
+var noElementArrayVsOtherDataConflicts = function(first, second) {
+ return isCopyTarget(second) || ((first == gl.ELEMENT_ARRAY_BUFFER) == (second == gl.ELEMENT_ARRAY_BUFFER));
+};
+
+
+var bind = function(bindFn, target, buffer) {
+ if (bindFn == "bindBuffer")
+ gl.bindBuffer(target, buffer);
+ else if (bindFn == "bindBufferRange")
+ gl.bindBufferRange(target, 0, buffer, 0, 4);
+ else if (bindFn == "bindBufferBase")
+ gl.bindBufferBase(target, 0, buffer);
+ else
+ throw new Error("Cannot bind unknown function: " + bindFn);
+}
+
+var testBindingFn = function(firstBindFn, secondBindFn, firstTarget, secondTarget) {
+ var firstTargetStr = wtu.glEnumToString(gl, firstTarget),
+ secondTargetStr = wtu.glEnumToString(gl, secondTarget);
+ var buffer = gl.createBuffer();
+
+ bind(firstBindFn, firstTarget, buffer);
+ bind(firstBindFn, firstTarget, null);
+ bind(secondBindFn, secondTarget, buffer);
+ bind(secondBindFn, secondTarget, null);
+
+ var messagePrefix = "Binding buffer first with " + firstBindFn + " to gl." + firstTargetStr
+ + " and then binding buffer with " + secondBindFn + " to gl." + secondTargetStr + " should ";
+ if (firstTarget == secondTarget || noElementArrayVsOtherDataConflicts(firstTarget, secondTarget))
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, messagePrefix + "WORK");
+ else
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, messagePrefix + "FAIL");
+}
+
+var testBinding = function(firstTarget, secondTarget) {
+ for (var i = 0; i < bindFunctions.length; i++)
+ if (i == 0 || firstTarget == gl.UNIFORM_BUFFER || firstTarget == gl.TRANSFORM_FEEDBACK_BUFFER)
+ for (var j = 0; j < bindFunctions.length; j++)
+ if (j == 0 || secondTarget == gl.UNIFORM_BUFFER || secondTarget == gl.TRANSFORM_FEEDBACK_BUFFER)
+ testBindingFn(bindFunctions[i], bindFunctions[j], firstTarget, secondTarget);
+};
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+debug("");
+debug("Testing each binding function");
+
+var buffer1 = gl.createBuffer();
+bind("bindBuffer", gl.ARRAY_BUFFER, buffer1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBuffer(gl.ARRAY_BUFFER, buffer1) should WORK");
+
+var buffer2 = gl.createBuffer();
+bind("bindBufferRange", gl.UNIFORM_BUFFER, buffer2);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBufferRange(gl.UNIFORM_BUFFER, 0, buffer2, 0, 4) should WORK");
+
+var buffer3 = gl.createBuffer();
+bind("bindBufferBase", gl.UNIFORM_BUFFER, buffer3);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBufferBase(gl.UNIFORM_BUFFER, 0, buffer3) should WORK");
+
+for (var i = 0; i < validTargets.length; i++) {
+ debug("");
+ debug("Testing binding a buffer first to " + wtu.glEnumToString(gl, validTargets[i])
+ + " and then to another target");
+ for (var j = 0; j < validTargets.length; j++)
+ testBinding(validTargets[i], validTargets[j]);
+}
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/delete-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/delete-buffer.html
new file mode 100644
index 0000000000..d438d65521
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/delete-buffer.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL buffer deletion behavior test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test buffer deletion behavior.");
+// This is a regression test for https://crbug.com/822976
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+function runTexImageTest(gl) {
+ debug("");
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, 4, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, buffer);
+ gl.deleteBuffer(buffer);
+ // Indexed uniform buffer bindings should not prevent a buffer from being
+ // deleted. Therefore, PIXEL_UNPACK_BUFFER binding should also be 0.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ var data = new Uint8Array(1024);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 16, 16, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D should succeed");
+
+ // Clean up bindings just in case an implementation gets it wrong.
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, null);
+}
+
+function runReadPixelsTest(gl) {
+ debug("");
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_PACK_BUFFER, 4, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, buffer);
+ gl.deleteBuffer(buffer);
+ // Indexed transform feedback buffer bindings should not prevent a buffer
+ // from being deleted. Therefore, PIXEL_PACK_BUFFER binding should also be 0.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+
+ var buffer = new Uint8Array(1024);
+ gl.readPixels(0, 0, 16, 16, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should succeed");
+
+ // Clean up bindings just in case an implementation gets it wrong.
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, null);
+}
+
+runTexImageTest(gl);
+runReadPixelsTest(gl);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data-validity.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data-validity.html
new file mode 100644
index 0000000000..06ce2ecb5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data-validity.html
@@ -0,0 +1,250 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 getBufferSubData validity tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in uint in_data;
+flat out uint out_data;
+void main() {
+ out_data = in_data;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+void main() {}
+</script>
+
+<script>
+"use strict";
+description("Test that getBufferSubData returns valid data in edge cases");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+const srcData = new Uint8Array([ 1, 2, 3, 4, 5, 6, 7, 8 ]);
+const noData = new Uint8Array(8);
+
+const srcBuffer = gl.createBuffer();
+gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer);
+gl.bufferData(gl.COPY_READ_BUFFER, srcData, gl.STATIC_DRAW);
+
+const badBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, 8, gl.STATIC_DRAW);
+
+let readbackBuffer;
+function deleteReadbackBuffer() {
+ gl.deleteBuffer(readbackBuffer);
+}
+function recreateReadbackBuffer() {
+ readbackBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
+ gl.bufferData(gl.COPY_WRITE_BUFFER, 8, gl.STREAM_READ);
+}
+recreateReadbackBuffer();
+
+const dest = new Uint8Array(8);
+
+// Makes a new "resolvable" Promise
+function resolvable() {
+ let resolve;
+ const promise = new Promise(res => { resolve = res; });
+ promise.resolve = resolve;
+ return promise;
+}
+
+function wait() {
+ return new Promise(res => {
+ setTimeout(res, 0);
+ });
+}
+
+async function fence() {
+ const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ gl.flush();
+
+ let status;
+ do {
+ await wait();
+ status = gl.clientWaitSync(sync, 0, 0);
+ } while (status != gl.ALREADY_SIGNALED && status != gl.CONDITION_SATISFIED);
+ gl.deleteSync(sync);
+}
+
+function checkGetBufferSubData(err, data) {
+ dest.fill(0);
+ wtu.shouldGenerateGLError(gl, err, "gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)");
+ if (!err) {
+ shouldBeTrue(`areArraysEqual(dest, ${data})`);
+ }
+}
+
+const tfProgram = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_data"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+shouldBeNonNull("tfProgram");
+const tf = gl.createTransformFeedback();
+
+function copyBufferUsingTransformFeedback(src, dst) {
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, src);
+ gl.vertexAttribIPointer(0, 1, gl.UNSIGNED_INT, 0, 0);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, dst);
+
+ gl.drawBuffers([gl.NONE]);
+
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.beginTransformFeedback(gl.POINTS);
+ // treats the input and output data as two uint32s
+ gl.drawArrays(gl.POINTS, 0, 2);
+ gl.endTransformFeedback();
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+}
+
+(async () => {
+ debug("");
+ debug("write-read");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("fence-wait-write-read");
+ await fence();
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-read-fence-wait");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+ await fence();
+
+ debug("");
+ debug("write-fence-fence-wait-read");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ fence(); // no await
+ await fence();
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-fence-wait-read");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ await fence();
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-fence-wait-write-read");
+ gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ await fence();
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-fence-write-wait-read");
+ gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ {
+ const p = fence();
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ await p;
+ }
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-fence-transformfeedback-wait-read");
+ gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ {
+ const p = fence();
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
+ copyBufferUsingTransformFeedback(srcBuffer, readbackBuffer);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
+ await p;
+ }
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-unbind-fence-wait-bind-read");
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
+ gl.bindBuffer(gl.ARRAY_BUFFER, readbackBuffer);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ARRAY_BUFFER, 0, 0, 8);
+ gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer);
+ await fence();
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
+ checkGetBufferSubData(gl.NO_ERROR, "srcData");
+
+ debug("");
+ debug("write-fence-wait-delete-read");
+ gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ await fence();
+ deleteReadbackBuffer();
+ checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
+ recreateReadbackBuffer();
+
+ debug("");
+ debug("write-fence-delete-wait-read");
+ gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ {
+ const p = fence();
+ deleteReadbackBuffer();
+ await p;
+ }
+ checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
+ recreateReadbackBuffer();
+
+ debug("");
+ debug("write-fence-delete-wait-read");
+ gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ deleteReadbackBuffer();
+ await fence();
+ checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
+ recreateReadbackBuffer();
+
+ // crbug.com/941930
+ {
+ debug("");
+ debug("write-delete-recreate-fence-wait-read");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ deleteReadbackBuffer();
+ recreateReadbackBuffer();
+ await fence();
+ checkGetBufferSubData(gl.NO_ERROR, "noData");
+
+ debug("");
+ debug("write-delete-fence-wait-read");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ {
+ const p = fence();
+ deleteReadbackBuffer();
+ await p;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+
+ finishTest();
+})();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html
new file mode 100644
index 0000000000..5919a86996
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html
@@ -0,0 +1,223 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL getBufferSubData test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test makes sure that getBufferSubData acts as expected governed by WebGL 2.");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+var vertices = [
+ 1.1, 1.0, 1.3,
+ -1.0, -1.0, -5.0,
+ 5.3, -1.0, 1.0
+];
+var floatArray = new Float32Array(vertices);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var buffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW);
+
+var uninitializedBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, 36, gl.STATIC_DRAW);
+gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from buffer setup.");
+
+gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+debug("");
+debug("Test that getBufferSubData successfully works reading buffer data from gl.ARRAY_BUFFER");
+var retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)");
+
+debug("Argument must be ArrayBufferView, not ArrayBuffer")
+shouldThrow("gl.getBufferSubData(gl.ARRAY_BUFFER, 0, new ArrayBuffer(4))");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should not generate GL error");
+debug("Argument must be ArrayBufferView, not null")
+shouldThrow("gl.getBufferSubData(gl.ARRAY_BUFFER, 0, null)");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should not generate GL error");
+
+debug("Check array data to match original data set by the buffer");
+shouldBeTrue("areArraysEqual(retArray, floatArray)");
+
+debug("Test that getBufferSubData successfully works with dstOffset");
+retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(2), floatArray.slice(0, floatArray.length - 2))");
+
+retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length)");
+shouldBeTrue("areArraysEqual(retArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])");
+
+debug("Test that getBufferSubData fails when given a dstOffset beyond the end of retArray");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length + 1)");
+
+debug("Test that getBufferSubData successfully works with dstOffset and length");
+retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2, 2)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(2, 4), floatArray.slice(0, 2))");
+shouldBeTrue("areArraysEqual(retArray.slice(4), [0, 0, 0, 0, 0])");
+
+retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 1)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 8), [0, 0, 0, 0, 0, 0, 0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(8), floatArray.slice(0, 1))");
+
+debug("Test that getBufferSubData fails when given a dstOffset+length beyond the end of retArray");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 2)");
+
+debug("Test that getBufferSubData successfully works with srcByteOffset");
+retArray = new Float32Array(vertices.length - 2);
+const float32Size = Float32Array.BYTES_PER_ELEMENT;
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 2*float32Size, retArray)");
+shouldBeTrue("areArraysEqual(retArray, floatArray.slice(2))");
+
+retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 2*float32Size, retArray, 2)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(2), floatArray.slice(2))");
+
+retArray = new Float32Array(vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 4*float32Size, retArray, 3, 3)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 3), [0, 0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(3, 6), floatArray.slice(4, 7))");
+shouldBeTrue("areArraysEqual(retArray.slice(6), [0, 0, 0])");
+
+debug("Test that getBufferSubData fails when given a buffer with its size larger than the original data");
+var extraLargeBuffer = new Float32Array(vertices.length + 1);
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE,
+ "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, extraLargeBuffer)",
+ "Extra length should generate INVALID_VALUE.");
+extraLargeBuffer = new Float32Array(vertices.length - 1);
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE,
+ "gl.getBufferSubData(gl.ARRAY_BUFFER, 2*float32Size, extraLargeBuffer)",
+ "Extra length should generate INVALID_VALUE.");
+
+debug("Test that getBufferSubData fails when offset summed with buffer length is larger than the size of the original data size");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE,
+ "gl.getBufferSubData(gl.ARRAY_BUFFER, retArray.byteLength + 1, retArray)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 1, retArray)");
+
+debug("Test that getBufferSubData successfully works with offset view into ArrayBuffer");
+const verticesLengthInBytes = vertices.length * float32Size;
+const retStorage = new ArrayBuffer(4* verticesLengthInBytes); // Over allocate 4x
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)");
+shouldBeTrue("areArraysEqual(retArray, floatArray)");
+
+debug("Test that getBufferSubData successfully works with offset view into ArrayBuffer and dstOffset");
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(2), floatArray.slice(0, floatArray.length - 2))");
+
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length)");
+shouldBeTrue("areArraysEqual(retArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])");
+
+debug("Test that getBufferSubData fails when given a dstOffset beyond the end of offset view into ArrayBuffer");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length + 1)");
+
+debug("Test that getBufferSubData successfully works with offset view into ArrayBuffer and dstOffset and length");
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2, 2)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(2, 4), floatArray.slice(0, 2))");
+shouldBeTrue("areArraysEqual(retArray.slice(4), [0, 0, 0, 0, 0])");
+
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 1)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 8), [0, 0, 0, 0, 0, 0, 0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(8), floatArray.slice(0, 1))");
+
+debug("Test that getBufferSubData fails when given a dstOffset+length beyond the end of offset view into ArrayBuffer");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 2)");
+
+debug("Test that getBufferSubData successfully works with offset view into ArrayBuffer and srcByteOffset");
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length - 2);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 2*float32Size, retArray)");
+shouldBeTrue("areArraysEqual(retArray, floatArray.slice(2))");
+
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 2*float32Size, retArray, 2)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(2), floatArray.slice(2))");
+
+retArray = new Float32Array(retStorage, verticesLengthInBytes, vertices.length);
+retArray.fill(0);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 4*float32Size, retArray, 3, 3)");
+shouldBeTrue("areArraysEqual(retArray.slice(0, 3), [0, 0, 0])");
+shouldBeTrue("areArraysEqual(retArray.slice(3, 6), floatArray.slice(4, 7))");
+shouldBeTrue("areArraysEqual(retArray.slice(6), [0, 0, 0])");
+
+debug("Test that getBufferSubData fails when 0 is bound to the target");
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.getBufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, retArray)");
+
+debug("Test that getBufferSubData fails when offset is less than 0");
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, -1, retArray)");
+
+debug("");
+debug("Test that getBufferSubData successfully works with uninitialized buffers");
+retArray = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
+gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)");
+shouldBeTrue("areArraysEqual(retArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])");
+
+debug("");
+debug("Test that getBufferSubData works when a buffer is immediately resized to be too small");
+
+retArray = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
+gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)");
+gl.bufferData(gl.ARRAY_BUFFER, 4, gl.STATIC_DRAW);
+shouldBeTrue("areArraysEqual(retArray, floatArray)");
+
+debug("");
+debug("Test that getBufferSubData works when a buffer is immediately deleted");
+retArray = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
+gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)");
+gl.deleteBuffer(buffer);
+shouldBeTrue("areArraysEqual(retArray, floatArray)");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html
new file mode 100644
index 0000000000..a2bddce04c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html
@@ -0,0 +1,195 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uniform Buffers Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform uni {
+ vec4 color;
+};
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("This test covers ANGLE bugs when using a large uniform blocks. ANGLE would confuse an internal clipped uniform buffer size and produce an assert or error. Also there were issues with readback of large UBOs. See http://crbug.com/660670.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var quadVB;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ debug("");
+ debug("Testing uniform block with large data store");
+ runTest();
+
+ debug("");
+ debug("Testing readback on uniform block with large data store");
+ runReadbackTest();
+}
+
+function getQuadVerts(depth) {
+ var quadVerts = new Float32Array(3 * 6);
+ quadVerts[0] = -1.0; quadVerts[1] = 1.0; quadVerts[2] = depth;
+ quadVerts[3] = -1.0; quadVerts[4] = -1.0; quadVerts[5] = depth;
+ quadVerts[6] = 1.0; quadVerts[7] = -1.0; quadVerts[8] = depth;
+ quadVerts[9] = -1.0; quadVerts[10] = 1.0; quadVerts[11] = depth;
+ quadVerts[12] = 1.0; quadVerts[13] = -1.0; quadVerts[14] = depth;
+ quadVerts[15] = 1.0; quadVerts[16] = 1.0; quadVerts[17] = depth;
+ return quadVerts;
+}
+
+function drawQuad(depth) {
+ if (!quadVB) {
+ quadVB = gl.createBuffer()
+ }
+
+ var quadVerts = getQuadVerts(depth);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadVB);
+ gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+}
+
+function runTest() {
+
+ // Create the program
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position"]);
+ if (!program) {
+ testFailed("Failed to set up the program");
+ return;
+ }
+
+ // Init uniform buffer. To trigger the bug, it's necessary to use the
+ // DYNAMIC_DRAW usage. This makes ANGLE attempt to map the buffer internally
+ // with an incorrect copy size.
+ var ubo = gl.createBuffer();
+ var big_size = 4096 * 64;
+ var data = new Float32Array([0.5, 0.75, 0.25, 1.0]);
+ gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
+ gl.bufferData(gl.UNIFORM_BUFFER, big_size, gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, data);
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
+ var buffer_index = gl.getUniformBlockIndex(program, "uni");
+ if (buffer_index == -1) {
+ testFailed("Failed to get uniform block index");
+ return;
+ }
+ gl.uniformBlockBinding(program, buffer_index, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up uniform block should succeed");
+
+ // Draw the quad
+ gl.useProgram(program);
+ drawQuad(0.5);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw with uniform block should succeed");
+
+ // Verify the output color
+ var color = [127, 191, 64, 255];
+ wtu.checkCanvas(gl, color, "canvas should be same as input uniform", 1);
+}
+
+function runReadbackTest() {
+
+ // Create the program
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position"]);
+ if (!program) {
+ testFailed("Failed to set up the program");
+ return;
+ }
+
+ // Init uniform buffer. To trigger the bug, it's necessary to use the
+ // DYNAMIC_DRAW usage. This makes ANGLE attempt to map the buffer internally
+ // with an incorrect copy size.
+ var ubo = gl.createBuffer();
+ var num_floats = 4096 * 16;
+ var expected_data = new Float32Array(num_floats);
+ for (var index = 0; index < num_floats; ++index) {
+ expected_data[index] = index;
+ }
+
+ expected_data[0] = 0.5;
+ expected_data[1] = 0.75;
+ expected_data[2] = 0.25;
+ expected_data[3] = 1.0;
+
+ gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
+ gl.bufferData(gl.UNIFORM_BUFFER, expected_data, gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, expected_data);
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
+ var buffer_index = gl.getUniformBlockIndex(program, "uni");
+ if (buffer_index == -1) {
+ testFailed("Failed to get uniform block index");
+ return;
+ }
+ gl.uniformBlockBinding(program, buffer_index, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up uniform block should succeed");
+
+ // Draw the quad
+ gl.useProgram(program);
+ drawQuad(0.5);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw with uniform block should succeed");
+
+ // Verify the output color
+ var color = [127, 191, 64, 255];
+ wtu.checkCanvas(gl, color, "canvas should be same as input uniform", 1);
+
+ // Verify readback
+ var actual_data = new Float32Array(num_floats);
+ gl.getBufferSubData(gl.UNIFORM_BUFFER, 0, actual_data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Readback from uniform block should succeed");
+
+ for (var index = 0; index < num_floats; ++index) {
+ if (actual_data[index] != expected_data[index]) {
+ testFailed("Expected and actual buffer data do not match");
+ return;
+ }
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-second-compile.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-second-compile.html
new file mode 100644
index 0000000000..936126856e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-second-compile.html
@@ -0,0 +1,104 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uniform Buffers should work on second compile</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>
+#version 300 es
+
+layout(location=0) in vec4 position;
+layout(std140, column_major) uniform Uniforms1 {
+ mat4 transform;
+};
+out vec3 vColor;
+
+void main() {
+ gl_Position = transform * position;
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>
+#version 300 es
+precision highp float;
+
+layout(std140) uniform Uniforms2 {
+ vec4 color;
+};
+out vec4 fragColor;
+
+void main(){
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies that getUniformBlockIndex isn't broken on second compile.");
+
+debug("This is a regression test for <a href='http://crbug.com/716018'>http://crbug.com/716018</a>");
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+// Initialize
+gl.clearColor(0, 0, 0, 1);
+var vsSource = document.getElementById("vshader").text.trim();
+var fsSource = document.getElementById("fshader").text.trim();
+
+function runTest() {
+ // Run twice to make sure that the second build does not cause errors
+ // (i.e. due to caching).
+ for (var i = 0; i < 2; ++i) {
+ debug("Compile/test iteration " + i);
+
+ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vertexShader, vsSource);
+ gl.compileShader(vertexShader);
+ // Note: if COMPILE_STATUS is retrieved here, it hides the bug.
+
+ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fragmentShader, fsSource);
+ gl.compileShader(fragmentShader);
+ // Note: if COMPILE_STATUS is retrieved here, it hides the bug.
+
+ var program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+
+ gl.useProgram(program);
+
+ var uniforms1Location = gl.getUniformBlockIndex(program, "Uniforms1");
+ gl.uniformBlockBinding(program, uniforms1Location, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uniforms1Location was " + uniforms1Location);
+
+ var uniforms2Location = gl.getUniformBlockIndex(program, "Uniforms2");
+ gl.uniformBlockBinding(program, uniforms2Location, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uniforms2Location was " + uniforms2Location);
+
+ debug("");
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-state-restoration.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-state-restoration.html
new file mode 100644
index 0000000000..51edd6ec07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers-state-restoration.html
@@ -0,0 +1,101 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uniform Buffers State Restoration Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>#version 300 es
+layout(location=0) in vec3 p;
+void main()
+{
+ gl_Position = vec4(p.xyz, 1.0);
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+uniform UBOData {
+ vec4 uboColor;
+};
+
+void main()
+{
+ oColor = uboColor;
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This is a regression test verifying that uniform buffer bindings persist correctly across frames: <a href='http://crbug.com/722060'>crbug.com/722060</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var greenBuf = null;
+var throwawayBuf = null;
+var red = new Float32Array([1, 0, 0, 1]);
+var green = new Float32Array([0, 1, 0, 1]);
+var frame = 0;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ initTest();
+ wtu.waitForComposite(runTest);
+}
+
+function initTest() {
+ wtu.setupUnitQuad(gl);
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ if (!program) {
+ testFailed("Could not compile shader with uniform blocks without error");
+ return;
+ }
+ var uboLocation = gl.getUniformBlockIndex(program, "UBOData");
+ gl.uniformBlockBinding(program, uboLocation, 0);
+
+ greenBuf = gl.createBuffer();
+ throwawayBuf = gl.createBuffer();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createBuffer should not set an error");
+
+ // Bind uniform buffer (both index 0 AND generic binding points) to greenBuf
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, greenBuf);
+ gl.bufferData(gl.UNIFORM_BUFFER, green, gl.STATIC_DRAW);
+ // Bind throwaray uniform buffer (from only the generic binding point)
+ gl.bindBuffer(gl.UNIFORM_BUFFER, throwawayBuf);
+}
+
+function runTest() {
+ // ONLY the binding point at index 0 (not the generic binding point) should be greenBuf.
+ // (The generic binding point should point at throwawayBuf.)
+ // So this bufferData should go into throwawayBuf.
+ gl.bufferData(gl.UNIFORM_BUFFER, red, gl.STATIC_DRAW);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "draw call should set canvas to green", 2);
+ finishTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers.html
new file mode 100644
index 0000000000..a6bd1b4bc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers.html
@@ -0,0 +1,576 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uniform Buffers Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>#version 300 es
+layout(location=0) in vec3 p;
+void main()
+{
+ gl_Position = vec4(p.xyz, 1.0);
+}
+</script>
+<script id='fbadshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+uniform UBOData {
+ float UBORed;
+ float UBOGreen;
+ float UBOBlue;
+};
+
+uniform Color {
+ float Red;
+ float UBOGreen;
+ float Blue;
+};
+
+void main()
+{
+ oColor = vec4(UBORed * Red, UBOGreen * UBOGreen, UBOBlue * Blue, 1.0);
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+uniform UBOData {
+ float UBORed;
+ float UBOGreen;
+ float UBOBlue;
+};
+
+uniform UBOD {
+ float UBOR;
+ float UBOG;
+ float UBOB;
+};
+
+void main()
+{
+ oColor = vec4(UBORed * UBOR, UBOGreen * UBOG, UBOBlue * UBOB, 1.0);
+}
+</script>
+<script id='fshadernamed' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+uniform UBOData {
+ float Red;
+ float Green;
+ float Blue;
+} UBOA;
+
+void main()
+{
+ oColor = vec4(UBOA.Red, UBOA.Green, UBOA.Blue, 1.0);
+}
+</script>
+<script id='fshadernamedarray' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+uniform UBOData {
+ float Red;
+ float Green;
+ float Blue;
+} UBOA[2];
+
+void main()
+{
+ oColor = vec4((UBOA[0].Red + UBOA[1].Red) / 2.0,
+ (UBOA[0].Green + UBOA[1].Green) / 2.0,
+ (UBOA[0].Blue + UBOA[1].Blue) / 2.0, 1.0);
+}
+</script>
+<script id='fshadernestedstruct' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+struct color_t {
+ float red;
+ float green;
+ float blue;
+};
+
+struct wrapper_t {
+ color_t color;
+};
+
+uniform UBOData {
+ wrapper_t UBOStruct;
+};
+
+// This is intended to reproduce a specific ANGLE bug that triggers when the wrapper struct is passed to a function.
+// https://bugs.chromium.org/p/angleproject/issues/detail?id=2084
+void processColor(wrapper_t wrapper) {
+ oColor = vec4(wrapper.color.red, wrapper.color.green, wrapper.color.blue, 1.0);
+}
+
+void main()
+{
+ processColor(UBOStruct);
+}
+</script>
+<script id='fshaderarrayofstructs' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+struct color_t {
+ float red;
+ float green;
+ float blue;
+};
+
+uniform UBOData {
+ color_t UBOColors[2];
+};
+
+// This is intended to reproduce a specific ANGLE bug that triggers when a struct from an array of structs in an interface block is passed to a function.
+// https://bugs.chromium.org/p/angleproject/issues/detail?id=2084
+vec3 processColor(color_t color) {
+ return vec3(color.red, color.green, color.blue);
+}
+
+void main()
+{
+ oColor = vec4(processColor(UBOColors[0]) + processColor(UBOColors[1]), 1.0);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the Uniform Buffer objects");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var b1 = null;
+var b2 = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ wtu.setupUnitQuad(gl);
+
+ runBindingTest();
+ runBadShaderTest();
+ runUniformBufferOffsetAlignmentTest();
+ runDrawTest();
+ runNamedDrawTest();
+ runNamedArrayDrawTest();
+ runNestedStructsDrawTest();
+ runArrayOfStructsDrawTest();
+}
+
+function runBindingTest() {
+ debug("");
+ debug("Testing uniform buffer binding behavior");
+ shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "UNIFORM_BUFFER_BINDING query should succeed");
+
+ debug("Testing basic uniform buffer binding and unbinding");
+ b1 = gl.createBuffer();
+ b2 = gl.createBuffer();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createBuffer should not set an error");
+ shouldBeNonNull("b1");
+ shouldBeNonNull("b2");
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to bind uniform buffer");
+ shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "b1");
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to update uniform buffer binding");
+ shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "b2");
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to unbind uniform buffer");
+
+ debug("Testing deleting uniform buffers");
+ gl.deleteBuffer(b1);
+ gl.deleteBuffer(b2);
+ shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+
+ // Shouldn't be able to bind a deleted buffer.
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted buffer should generate INVALID_OPERATION");
+ shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+}
+
+function runBadShaderTest() {
+ debug("");
+ var testProgram = wtu.setupProgram(gl, ['vshader', 'fbadshader']);
+ if (testProgram) {
+ testFailed("To define the same uniform in two uniform blocks should fail");
+ } else {
+ testPassed("To define the same uniform in two uniform blocks should fail");
+ }
+}
+
+function runUniformBufferOffsetAlignmentTest() {
+ debug("");
+ var offsetAlignment = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+
+ if (offsetAlignment % 4 != 0) {
+ testFailed("Unexpected UNIFORM_BUFFER_OFFSET_ALIGNMENT - should be aligned on a 4-byte boundary");
+ } else {
+ testPassed("UNIFORM_BUFFER_OFFSET_ALIGNMENT is divisible by four");
+ }
+}
+
+function setRGBValuesToFloat32Array(floatView, red, green, blue) {
+ floatView[0] = red;
+ floatView[1] = green;
+ floatView[2] = blue;
+}
+
+function checkFloat32UniformOffsetsInStd140Layout(uniformOffsets, expectedInitialOffset) {
+ if (expectedInitialOffset === undefined)
+ {
+ expectedInitialOffset = 0;
+ }
+ // Verify that the uniform offsets are set according to the std140 layout, which WebGL enforces.
+ // This function checks this for 32-bit float values, which are expected to be tightly packed.
+ for (var i = 0; i < uniformOffsets.length; ++i)
+ {
+ if (uniformOffsets[i] != expectedInitialOffset + i * Float32Array.BYTES_PER_ELEMENT)
+ {
+ testFailed("Uniform offsets are not according to std140 layout");
+ return false;
+ }
+ }
+ return true;
+}
+
+function runDrawTest() {
+ debug("");
+ debug("Testing drawing with uniform buffers");
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ if (!program) {
+ testFailed("Could not compile shader with uniform blocks without error");
+ return;
+ }
+
+ var blockIndex_1 = gl.getUniformBlockIndex(program, "UBOData");
+ var blockSize_1 = gl.getActiveUniformBlockParameter(program, blockIndex_1, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices_1 = gl.getUniformIndices(program, ["UBORed", "UBOGreen", "UBOBlue"]);
+ var uniformOffsets_1 = gl.getActiveUniforms(program, uniformIndices_1, gl.UNIFORM_OFFSET);
+ var blockIndex_2 = gl.getUniformBlockIndex(program, "UBOD");
+ var blockSize_2 = gl.getActiveUniformBlockParameter(program, blockIndex_2, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices_2 = gl.getUniformIndices(program, ["UBOR", "UBOG", "UBOB"]);
+ var uniformOffsets_2 = gl.getActiveUniforms(program, uniformIndices_2, gl.UNIFORM_OFFSET);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error");
+
+ if (uniformOffsets_1.length < 3 || uniformOffsets_2.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ if (!checkFloat32UniformOffsetsInStd140Layout(uniformOffsets_1) || !checkFloat32UniformOffsetsInStd140Layout(uniformOffsets_2))
+ {
+ return;
+ }
+
+ var uboArray_1 = new ArrayBuffer(blockSize_1);
+ var uboFloatView_1 = new Float32Array(uboArray_1);
+ setRGBValuesToFloat32Array(uboFloatView_1, 1.0, 0.0, 0.0); // UBORed, UBOGreen, UBOBlue
+ var uboArray_2 = new ArrayBuffer(blockSize_2);
+ var uboFloatView_2 = new Float32Array(uboArray_2);
+ setRGBValuesToFloat32Array(uboFloatView_2, 1.0, 1.0, 1.0); // UBOR, UBOG, UBOB
+
+ var b_1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b_1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView_1, gl.DYNAMIC_DRAW);
+ var b_2 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b_2);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView_2, gl.DYNAMIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors");
+
+ var bindings = [1, 2];
+ gl.uniformBlockBinding(program, blockIndex_1, bindings[0]);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, bindings[0], b_1);
+ gl.uniformBlockBinding(program, blockIndex_2, bindings[1]);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, bindings[1], b_2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferBase without errors");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+
+ debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call");
+ setRGBValuesToFloat32Array(uboFloatView_1, 0.0, 0.0, 1.0); // UBORed, UBOGreen, UBOBlue
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b_1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView_1, gl.DYNAMIC_DRAW);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "draw call should set canvas to blue", 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runNamedDrawTest() {
+ debug("");
+ debug("Testing drawing with named uniform buffers");
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshadernamed']);
+ if (!program) {
+ testFailed("Could not compile shader with named uniform blocks without error");
+ return;
+ }
+
+ var blockIndex = gl.getUniformBlockIndex(program, "UBOData");
+ var blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices = gl.getUniformIndices(program, ["UBOData.Red", "UBOData.Green", "UBOData.Blue"]);
+ var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error");
+
+ if (uniformOffsets.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ if (!checkFloat32UniformOffsetsInStd140Layout(uniformOffsets))
+ {
+ return;
+ }
+
+ var uboArray = new ArrayBuffer(blockSize);
+ var uboFloatView = new Float32Array(uboArray);
+ setRGBValuesToFloat32Array(uboFloatView, 1.0, 0.0, 0.0);
+
+ b1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors");
+
+ var binding = 3;
+ gl.uniformBlockBinding(program, blockIndex, binding);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, b1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferBase without errors");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+
+ debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call");
+ setRGBValuesToFloat32Array(uboFloatView, 0.0, 0.0, 1.0);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "draw call should set canvas to blue", 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runNamedArrayDrawTest() {
+ debug("");
+ debug("Testing drawing with named uniform buffer arrays");
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshadernamedarray']);
+ if (!program) {
+ testFailed("could not compile shader with named uniform block arrays without error");
+ return;
+ }
+
+ var blockIndex = [gl.getUniformBlockIndex(program, "UBOData[0]"),
+ gl.getUniformBlockIndex(program, "UBOData[1]")];
+ if (blockIndex[0] == gl.INVALID_INDEX ||
+ blockIndex[1] == gl.INVALID_INDEX) {
+ testFailed("Could not query uniform block index");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block indices without error");
+ var blockSize = [gl.getActiveUniformBlockParameter(program, blockIndex[0], gl.UNIFORM_BLOCK_DATA_SIZE),
+ gl.getActiveUniformBlockParameter(program, blockIndex[1], gl.UNIFORM_BLOCK_DATA_SIZE)];
+ if (blockSize[0] != blockSize[1]) {
+ testFailed("uniform block instance array with different block sizes");
+ }
+ var uniformIndices = gl.getUniformIndices(program, ["UBOData.Red", "UBOData.Green", "UBOData.Blue"]);
+ if (uniformIndices < 3 ||
+ uniformIndices[0] == gl.INVALID_INDEX ||
+ uniformIndices[1] == gl.INVALID_INDEX ||
+ uniformIndices[2] == gl.INVALID_INDEX) {
+ testFailed("Could not query uniform indices");
+ return;
+ }
+ var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error");
+ if (uniformOffsets.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ if (!checkFloat32UniformOffsetsInStd140Layout(uniformOffsets))
+ {
+ return;
+ }
+
+ var offsetAlignment = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ var offset = Math.ceil(blockSize[0] / offsetAlignment) * offsetAlignment;
+
+ var bufferSize = offset + blockSize[1];
+ var uboArray = new ArrayBuffer(bufferSize);
+ var uboFloatView = new Float32Array(uboArray);
+ setRGBValuesToFloat32Array(uboFloatView, 1.0, 0.0, 0.0);
+ var uboFloatView2 = new Float32Array(uboArray, offset);
+ setRGBValuesToFloat32Array(uboFloatView2, 0.0, 0.0, 1.0);
+
+ b1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors");
+
+ var bindings = [4, 5];
+ gl.uniformBlockBinding(program, blockIndex[0], bindings[0]);
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, bindings[0], b1, 0, blockSize[0]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferRange without errors");
+ gl.uniformBlockBinding(program, blockIndex[1], bindings[1]);
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, bindings[1], b1, offset, blockSize[1]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferRange without errors");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [127, 0, 127, 255], "draw call should set canvas to (0.5, 0, 0.5)", 2);
+
+ debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call");
+ setRGBValuesToFloat32Array(uboFloatView, 0.0, 1.0, 1.0);
+ setRGBValuesToFloat32Array(uboFloatView2, 0.0, 0.0, 1.0);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 127, 255, 255], "draw call should set canvas to (0, 0.5, 1)", 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runNestedStructsDrawTest() {
+ debug("");
+ debug("Testing drawing with nested struct inside uniform block. The wrapper struct is passed to a function.");
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshadernestedstruct'], undefined, undefined, true);
+ if (!program) {
+ testFailed("Could not compile shader with nested structs without error");
+ return;
+ }
+
+ var blockIndex = gl.getUniformBlockIndex(program, "UBOData");
+ var blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices = gl.getUniformIndices(program, ["UBOStruct.color.red", "UBOStruct.color.green", "UBOStruct.color.blue"]);
+ var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error");
+
+ if (uniformOffsets.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ if (!checkFloat32UniformOffsetsInStd140Layout(uniformOffsets))
+ {
+ return;
+ }
+
+ var uboArray = new ArrayBuffer(blockSize);
+ var uboFloatView = new Float32Array(uboArray);
+ setRGBValuesToFloat32Array(uboFloatView, 0.0, 1.0, 0.0);
+
+ b1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors");
+
+ var binding = 3;
+ gl.uniformBlockBinding(program, blockIndex, binding);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, b1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferBase without errors");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "draw call should set canvas to green", 2);
+
+ debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call");
+ setRGBValuesToFloat32Array(uboFloatView, 0.0, 0.0, 1.0);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "draw call should set canvas to blue", 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runArrayOfStructsDrawTest() {
+ debug("");
+ debug("Testing drawing with array of structs inside uniform block. A struct in the block is passed to a function.");
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshaderarrayofstructs'], undefined, undefined, true);
+ if (!program) {
+ testFailed("Could not compile shader with an array of structs in an interface block without error");
+ return;
+ }
+
+ var blockIndex = gl.getUniformBlockIndex(program, "UBOData");
+ var blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices = gl.getUniformIndices(program, ["UBOColors[0].red", "UBOColors[0].green", "UBOColors[0].blue"]);
+ var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ var uniformIndices_2 = gl.getUniformIndices(program, ["UBOColors[1].red", "UBOColors[1].green", "UBOColors[1].blue"]);
+ var uniformOffsets_2 = gl.getActiveUniforms(program, uniformIndices_2, gl.UNIFORM_OFFSET);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error");
+
+ if (uniformOffsets.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ if (!checkFloat32UniformOffsetsInStd140Layout(uniformOffsets))
+ {
+ return;
+ }
+ if (!checkFloat32UniformOffsetsInStd140Layout(uniformOffsets_2, uniformOffsets_2[0]))
+ {
+ return;
+ }
+
+ var uboArray = new ArrayBuffer(blockSize);
+ var uboFloatView = new Float32Array(uboArray);
+ setRGBValuesToFloat32Array(uboFloatView, 0.0, 0.5, 0.0);
+ var uboFloatView2 = new Float32Array(uboArray, uniformOffsets_2[0]);
+ setRGBValuesToFloat32Array(uboFloatView2, 0.0, 0.5, 0.0);
+
+ b1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, b1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors");
+
+ var binding = 3;
+ gl.uniformBlockBinding(program, blockIndex, binding);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, b1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferBase without errors");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "draw call should set canvas to green", 2);
+
+ debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call");
+ setRGBValuesToFloat32Array(uboFloatView, 1.0, 0.0, 0.0);
+ setRGBValuesToFloat32Array(uboFloatView2, 0.0, 0.0, 1.0);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 255, 255], "draw call should set canvas to purple", 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/00_test_list.txt
new file mode 100644
index 0000000000..35e011f3bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/00_test_list.txt
@@ -0,0 +1 @@
+--min-version 2.0.1 to-data-url-with-pack-params.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/compositing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/compositing.html
new file mode 100644
index 0000000000..cd9bf594fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/compositing.html
@@ -0,0 +1,92 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 draw functions have expected behavior with compositing</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+<script src="../../js/tests/compositing-test.js"></script>
+<style>
+body {
+ height: 3000px;
+}
+</style>
+</head>
+<body>
+<!-- Important to put the canvas at the top so that it's always visible even in the test suite runner.
+ Otherwise it just doesn't get composited in Firefox. -->
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description(`\
+This test ensures WebGL implementations correctly clear the drawing buffer
+on composite if preserveDrawingBuffer is false and is not cleared if
+preserveDrawingBuffer is true.`);
+debug("");
+
+const wtu = WebGLTestUtils;
+
+async function runCompositingTests() {
+ const compositingTestFn = createCompositingTestFn({
+ webglVersion: 2,
+ shadersFn(gl) {
+ const vs = `\
+ #version 300 es
+ in vec4 position;
+ void main() {
+ gl_Position = position;
+ }
+ `;
+ const fs = `\
+ #version 300 es
+ precision mediump float;
+ out vec4 fragColor;
+ void main() {
+ fragColor = vec4(1, 0, 0, 1);
+ }
+ `;
+ return [vs, fs];
+ },
+ });
+
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ function drawArraysInstanced(gl) {
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, 1);
+ }
+
+ function drawElementsInstanced(gl) {
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1);
+ }
+
+ function drawRangeElements(gl) {
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ await compositingTestFn(drawArrays);
+ await compositingTestFn(drawElements);
+ await compositingTestFn(drawArraysInstanced);
+ await compositingTestFn(drawElementsInstanced);
+ await compositingTestFn(drawRangeElements);
+ finishTest();
+}
+runCompositingTests();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/to-data-url-with-pack-params.html b/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/to-data-url-with-pack-params.html
new file mode 100644
index 0000000000..354ac2642f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/canvas/to-data-url-with-pack-params.html
@@ -0,0 +1,73 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>toDataURL() runs fine with WebGL2 PIXEL PACK parameters</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="test"></canvas>
+<script>
+"use strict";
+description("This test verifies toDataURL() runs fine with WebGL2 PIXEL PACK parameters");
+// This is a regression test for crbug.com/740603
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("test");
+var gl = wtu.create3DContext(canvas, null, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Testing PACK_SKIP_ROWS");
+ gl.pixelStorei(gl.PACK_SKIP_ROWS, 100);
+ var img = new Image();
+ img.src = canvas.toDataURL(); // This should not crash in ASAN
+ gl.pixelStorei(gl.PACK_SKIP_ROWS, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Test should not generate GL error");
+
+ debug("");
+ debug("Testing PACK_SKIP_PIXELS");
+ gl.pixelStorei(gl.PACK_SKIP_PIXELS, 10000);
+ img = new Image();
+ img.src = canvas.toDataURL(); // This should not crash in ASAN
+ gl.pixelStorei(gl.PACK_SKIP_PIXELS, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Test should not generate GL error");
+
+ debug("");
+ debug("Testing PACK_ROW_LENGTH");
+ gl.pixelStorei(gl.PACK_ROW_LENGTH, 2048);
+ img = new Image();
+ img.src = canvas.toDataURL(); // This should not crash in ASAN
+ gl.pixelStorei(gl.PACK_ROW_LENGTH, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Test should not generate GL error");
+
+ debug("");
+ debug("Testing PIXEL_PACK_BUFFER");
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer);
+ img = new Image();
+ img.src = canvas.toDataURL(); // This should not crash in ASAN
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Test should not generate GL error");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/context/00_test_list.txt
new file mode 100644
index 0000000000..fc4f8b8c07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/00_test_list.txt
@@ -0,0 +1,10 @@
+constants-and-properties-2.html
+context-attributes-depth-stencil-antialias-obeyed.html
+--min-version 2.0.1 context-mode.html
+--min-version 2.0.1 context-sharing-texture2darray-texture3d-data-bug.html
+context-type-test-2.html
+--min-version 2.0.1 context-resize-changes-buffer-binding-bug.html
+--min-version 2.0.1 incorrect-context-object-behaviour.html
+methods-2.html
+--min-version 2.0.1 no-experimental-webgl2.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/constants-and-properties-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/constants-and-properties-2.html
new file mode 100644
index 0000000000..f4e2bfc30e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/constants-and-properties-2.html
@@ -0,0 +1,835 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Constants and Properties Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<script>
+"use strict";
+description("This test ensures that the WebGL context has all the constants and (non-function) properties in the specification.");
+
+var constants = {
+ /* ClearBufferMask */
+DEPTH_BUFFER_BIT : 0x00000100,
+STENCIL_BUFFER_BIT : 0x00000400,
+COLOR_BUFFER_BIT : 0x00004000,
+
+ /* BeginMode */
+POINTS : 0x0000,
+LINES : 0x0001,
+LINE_LOOP : 0x0002,
+LINE_STRIP : 0x0003,
+TRIANGLES : 0x0004,
+TRIANGLE_STRIP : 0x0005,
+TRIANGLE_FAN : 0x0006,
+
+ /* AlphaFunction (not supported in ES20) */
+ /* NEVER */
+ /* LESS */
+ /* EQUAL */
+ /* LEQUAL */
+ /* GREATER */
+ /* NOTEQUAL */
+ /* GEQUAL */
+ /* ALWAYS */
+
+ /* BlendingFactorDest */
+ZERO : 0,
+ONE : 1,
+SRC_COLOR : 0x0300,
+ONE_MINUS_SRC_COLOR : 0x0301,
+SRC_ALPHA : 0x0302,
+ONE_MINUS_SRC_ALPHA : 0x0303,
+DST_ALPHA : 0x0304,
+ONE_MINUS_DST_ALPHA : 0x0305,
+
+ /* BlendingFactorSrc */
+ /* ZERO */
+ /* ONE */
+DST_COLOR : 0x0306,
+ONE_MINUS_DST_COLOR : 0x0307,
+SRC_ALPHA_SATURATE : 0x0308,
+ /* SRC_ALPHA */
+ /* ONE_MINUS_SRC_ALPHA */
+ /* DST_ALPHA */
+ /* ONE_MINUS_DST_ALPHA */
+
+ /* BlendEquationSeparate */
+FUNC_ADD : 0x8006,
+BLEND_EQUATION : 0x8009,
+BLEND_EQUATION_RGB : 0x8009, /* same as BLEND_EQUATION */
+BLEND_EQUATION_ALPHA : 0x883D,
+
+ /* BlendSubtract */
+FUNC_SUBTRACT : 0x800A,
+FUNC_REVERSE_SUBTRACT : 0x800B,
+
+ /* Separate Blend Functions */
+BLEND_DST_RGB : 0x80C8,
+BLEND_SRC_RGB : 0x80C9,
+BLEND_DST_ALPHA : 0x80CA,
+BLEND_SRC_ALPHA : 0x80CB,
+CONSTANT_COLOR : 0x8001,
+ONE_MINUS_CONSTANT_COLOR : 0x8002,
+CONSTANT_ALPHA : 0x8003,
+ONE_MINUS_CONSTANT_ALPHA : 0x8004,
+BLEND_COLOR : 0x8005,
+
+ /* Buffer Objects */
+ARRAY_BUFFER : 0x8892,
+ELEMENT_ARRAY_BUFFER : 0x8893,
+ARRAY_BUFFER_BINDING : 0x8894,
+ELEMENT_ARRAY_BUFFER_BINDING : 0x8895,
+
+STREAM_DRAW : 0x88E0,
+STATIC_DRAW : 0x88E4,
+DYNAMIC_DRAW : 0x88E8,
+
+BUFFER_SIZE : 0x8764,
+BUFFER_USAGE : 0x8765,
+
+CURRENT_VERTEX_ATTRIB : 0x8626,
+
+ /* CullFaceMode */
+FRONT : 0x0404,
+BACK : 0x0405,
+FRONT_AND_BACK : 0x0408,
+
+ /* DepthFunction */
+ /* NEVER */
+ /* LESS */
+ /* EQUAL */
+ /* LEQUAL */
+ /* GREATER */
+ /* NOTEQUAL */
+ /* GEQUAL */
+ /* ALWAYS */
+
+ /* EnableCap */
+ /* TEXTURE_2D */
+CULL_FACE : 0x0B44,
+BLEND : 0x0BE2,
+DITHER : 0x0BD0,
+STENCIL_TEST : 0x0B90,
+DEPTH_TEST : 0x0B71,
+SCISSOR_TEST : 0x0C11,
+POLYGON_OFFSET_FILL : 0x8037,
+SAMPLE_ALPHA_TO_COVERAGE : 0x809E,
+SAMPLE_COVERAGE : 0x80A0,
+
+ /* ErrorCode */
+NO_ERROR : 0,
+INVALID_ENUM : 0x0500,
+INVALID_VALUE : 0x0501,
+INVALID_OPERATION : 0x0502,
+OUT_OF_MEMORY : 0x0505,
+
+ /* FrontFaceDirection */
+CW : 0x0900,
+CCW : 0x0901,
+
+ /* GetPName */
+LINE_WIDTH : 0x0B21,
+ALIASED_POINT_SIZE_RANGE : 0x846D,
+ALIASED_LINE_WIDTH_RANGE : 0x846E,
+CULL_FACE_MODE : 0x0B45,
+FRONT_FACE : 0x0B46,
+DEPTH_RANGE : 0x0B70,
+DEPTH_WRITEMASK : 0x0B72,
+DEPTH_CLEAR_VALUE : 0x0B73,
+DEPTH_FUNC : 0x0B74,
+STENCIL_CLEAR_VALUE : 0x0B91,
+STENCIL_FUNC : 0x0B92,
+STENCIL_FAIL : 0x0B94,
+STENCIL_PASS_DEPTH_FAIL : 0x0B95,
+STENCIL_PASS_DEPTH_PASS : 0x0B96,
+STENCIL_REF : 0x0B97,
+STENCIL_VALUE_MASK : 0x0B93,
+STENCIL_WRITEMASK : 0x0B98,
+STENCIL_BACK_FUNC : 0x8800,
+STENCIL_BACK_FAIL : 0x8801,
+STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802,
+STENCIL_BACK_PASS_DEPTH_PASS : 0x8803,
+STENCIL_BACK_REF : 0x8CA3,
+STENCIL_BACK_VALUE_MASK : 0x8CA4,
+STENCIL_BACK_WRITEMASK : 0x8CA5,
+VIEWPORT : 0x0BA2,
+SCISSOR_BOX : 0x0C10,
+ /* SCISSOR_TEST */
+COLOR_CLEAR_VALUE : 0x0C22,
+COLOR_WRITEMASK : 0x0C23,
+UNPACK_ALIGNMENT : 0x0CF5,
+PACK_ALIGNMENT : 0x0D05,
+MAX_TEXTURE_SIZE : 0x0D33,
+MAX_VIEWPORT_DIMS : 0x0D3A,
+SUBPIXEL_BITS : 0x0D50,
+RED_BITS : 0x0D52,
+GREEN_BITS : 0x0D53,
+BLUE_BITS : 0x0D54,
+ALPHA_BITS : 0x0D55,
+DEPTH_BITS : 0x0D56,
+STENCIL_BITS : 0x0D57,
+POLYGON_OFFSET_UNITS : 0x2A00,
+ /* POLYGON_OFFSET_FILL */
+POLYGON_OFFSET_FACTOR : 0x8038,
+TEXTURE_BINDING_2D : 0x8069,
+SAMPLE_BUFFERS : 0x80A8,
+SAMPLES : 0x80A9,
+SAMPLE_COVERAGE_VALUE : 0x80AA,
+SAMPLE_COVERAGE_INVERT : 0x80AB,
+
+ /* GetTextureParameter */
+ /* TEXTURE_MAG_FILTER */
+ /* TEXTURE_MIN_FILTER */
+ /* TEXTURE_WRAP_S */
+ /* TEXTURE_WRAP_T */
+
+COMPRESSED_TEXTURE_FORMATS : 0x86A3,
+
+ /* HintMode */
+DONT_CARE : 0x1100,
+FASTEST : 0x1101,
+NICEST : 0x1102,
+
+ /* HintTarget */
+GENERATE_MIPMAP_HINT : 0x8192,
+
+ /* DataType */
+BYTE : 0x1400,
+UNSIGNED_BYTE : 0x1401,
+SHORT : 0x1402,
+UNSIGNED_SHORT : 0x1403,
+INT : 0x1404,
+UNSIGNED_INT : 0x1405,
+FLOAT : 0x1406,
+
+ /* PixelFormat */
+DEPTH_COMPONENT : 0x1902,
+ALPHA : 0x1906,
+RGB : 0x1907,
+RGBA : 0x1908,
+LUMINANCE : 0x1909,
+LUMINANCE_ALPHA : 0x190A,
+
+ /* PixelType */
+ /* UNSIGNED_BYTE */
+UNSIGNED_SHORT_4_4_4_4 : 0x8033,
+UNSIGNED_SHORT_5_5_5_1 : 0x8034,
+UNSIGNED_SHORT_5_6_5 : 0x8363,
+
+ /* Shaders */
+FRAGMENT_SHADER : 0x8B30,
+VERTEX_SHADER : 0x8B31,
+MAX_VERTEX_ATTRIBS : 0x8869,
+MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB,
+MAX_VARYING_VECTORS : 0x8DFC,
+MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D,
+MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C,
+MAX_TEXTURE_IMAGE_UNITS : 0x8872,
+MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD,
+SHADER_TYPE : 0x8B4F,
+DELETE_STATUS : 0x8B80,
+LINK_STATUS : 0x8B82,
+VALIDATE_STATUS : 0x8B83,
+ATTACHED_SHADERS : 0x8B85,
+ACTIVE_UNIFORMS : 0x8B86,
+ACTIVE_ATTRIBUTES : 0x8B89,
+SHADING_LANGUAGE_VERSION : 0x8B8C,
+CURRENT_PROGRAM : 0x8B8D,
+
+ /* StencilFunction */
+NEVER : 0x0200,
+LESS : 0x0201,
+EQUAL : 0x0202,
+LEQUAL : 0x0203,
+GREATER : 0x0204,
+NOTEQUAL : 0x0205,
+GEQUAL : 0x0206,
+ALWAYS : 0x0207,
+
+ /* StencilOp */
+ /* ZERO */
+KEEP : 0x1E00,
+REPLACE : 0x1E01,
+INCR : 0x1E02,
+DECR : 0x1E03,
+INVERT : 0x150A,
+INCR_WRAP : 0x8507,
+DECR_WRAP : 0x8508,
+
+ /* StringName */
+VENDOR : 0x1F00,
+RENDERER : 0x1F01,
+VERSION : 0x1F02,
+
+ /* TextureMagFilter */
+NEAREST : 0x2600,
+LINEAR : 0x2601,
+
+ /* TextureMinFilter */
+ /* NEAREST */
+ /* LINEAR */
+NEAREST_MIPMAP_NEAREST : 0x2700,
+LINEAR_MIPMAP_NEAREST : 0x2701,
+NEAREST_MIPMAP_LINEAR : 0x2702,
+LINEAR_MIPMAP_LINEAR : 0x2703,
+
+ /* TextureParameterName */
+TEXTURE_MAG_FILTER : 0x2800,
+TEXTURE_MIN_FILTER : 0x2801,
+TEXTURE_WRAP_S : 0x2802,
+TEXTURE_WRAP_T : 0x2803,
+
+ /* TextureTarget */
+TEXTURE_2D : 0x0DE1,
+TEXTURE : 0x1702,
+
+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,
+MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C,
+
+ /* TextureUnit */
+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,
+
+ /* TextureWrapMode */
+REPEAT : 0x2901,
+CLAMP_TO_EDGE : 0x812F,
+MIRRORED_REPEAT : 0x8370,
+
+ /* Uniform Types */
+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_2D : 0x8B5E,
+SAMPLER_CUBE : 0x8B60,
+
+ /* Vertex Arrays */
+VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622,
+VERTEX_ATTRIB_ARRAY_SIZE : 0x8623,
+VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624,
+VERTEX_ATTRIB_ARRAY_TYPE : 0x8625,
+VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A,
+VERTEX_ATTRIB_ARRAY_POINTER : 0x8645,
+VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
+
+ /* Shader Source */
+COMPILE_STATUS : 0x8B81,
+
+ /* Shader Precision-Specified Types */
+LOW_FLOAT : 0x8DF0,
+MEDIUM_FLOAT : 0x8DF1,
+HIGH_FLOAT : 0x8DF2,
+LOW_INT : 0x8DF3,
+MEDIUM_INT : 0x8DF4,
+HIGH_INT : 0x8DF5,
+
+ /* Framebuffer Object. */
+FRAMEBUFFER : 0x8D40,
+RENDERBUFFER : 0x8D41,
+
+RGBA4 : 0x8056,
+RGB5_A1 : 0x8057,
+RGB565 : 0x8D62,
+DEPTH_COMPONENT16 : 0x81A5,
+STENCIL_INDEX8 : 0x8D48,
+DEPTH_STENCIL : 0x84F9,
+
+RENDERBUFFER_WIDTH : 0x8D42,
+RENDERBUFFER_HEIGHT : 0x8D43,
+RENDERBUFFER_INTERNAL_FORMAT : 0x8D44,
+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_ATTACHMENT_OBJECT_TYPE : 0x8CD0,
+FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3,
+
+COLOR_ATTACHMENT0 : 0x8CE0,
+DEPTH_ATTACHMENT : 0x8D00,
+STENCIL_ATTACHMENT : 0x8D20,
+DEPTH_STENCIL_ATTACHMENT : 0x821A,
+
+NONE : 0,
+
+FRAMEBUFFER_COMPLETE : 0x8CD5,
+FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6,
+FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7,
+FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9,
+FRAMEBUFFER_UNSUPPORTED : 0x8CDD,
+
+FRAMEBUFFER_BINDING : 0x8CA6,
+RENDERBUFFER_BINDING : 0x8CA7,
+MAX_RENDERBUFFER_SIZE : 0x84E8,
+
+INVALID_FRAMEBUFFER_OPERATION : 0x0506,
+
+IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A,
+IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B,
+
+/* WebGL-specific enums */
+UNPACK_FLIP_Y_WEBGL : 0x9240,
+UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241,
+CONTEXT_LOST_WEBGL : 0x9242,
+UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243,
+BROWSER_DEFAULT_WEBGL : 0x9244,
+
+/* WebGL2 enums */
+READ_BUFFER : 0x0C02,
+UNPACK_ROW_LENGTH : 0x0CF2,
+UNPACK_SKIP_ROWS : 0x0CF3,
+UNPACK_SKIP_PIXELS : 0x0CF4,
+PACK_ROW_LENGTH : 0x0D02,
+PACK_SKIP_ROWS : 0x0D03,
+PACK_SKIP_PIXELS : 0x0D04,
+COLOR : 0x1800,
+DEPTH : 0x1801,
+STENCIL : 0x1802,
+RED : 0x1903,
+RGB8 : 0x8051,
+RGBA8 : 0x8058,
+RGB10_A2 : 0x8059,
+TEXTURE_BINDING_3D : 0x806A,
+UNPACK_SKIP_IMAGES : 0x806D,
+UNPACK_IMAGE_HEIGHT : 0x806E,
+TEXTURE_3D : 0x806F,
+TEXTURE_WRAP_R : 0x8072,
+MAX_3D_TEXTURE_SIZE : 0x8073,
+UNSIGNED_INT_2_10_10_10_REV : 0x8368,
+MAX_ELEMENTS_VERTICES : 0x80E8,
+MAX_ELEMENTS_INDICES : 0x80E9,
+TEXTURE_MIN_LOD : 0x813A,
+TEXTURE_MAX_LOD : 0x813B,
+TEXTURE_BASE_LEVEL : 0x813C,
+TEXTURE_MAX_LEVEL : 0x813D,
+MIN : 0x8007,
+MAX : 0x8008,
+DEPTH_COMPONENT24 : 0x81A6,
+MAX_TEXTURE_LOD_BIAS : 0x84FD,
+TEXTURE_COMPARE_MODE : 0x884C,
+TEXTURE_COMPARE_FUNC : 0x884D,
+CURRENT_QUERY : 0x8865,
+QUERY_RESULT : 0x8866,
+QUERY_RESULT_AVAILABLE : 0x8867,
+STREAM_READ : 0x88E1,
+STREAM_COPY : 0x88E2,
+STATIC_READ : 0x88E5,
+STATIC_COPY : 0x88E6,
+DYNAMIC_READ : 0x88E9,
+DYNAMIC_COPY : 0x88EA,
+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,
+MAX_FRAGMENT_UNIFORM_COMPONENTS : 0x8B49,
+MAX_VERTEX_UNIFORM_COMPONENTS : 0x8B4A,
+SAMPLER_3D : 0x8B5F,
+SAMPLER_2D_SHADOW : 0x8B62,
+FRAGMENT_SHADER_DERIVATIVE_HINT : 0x8B8B,
+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,
+SRGB8_ALPHA8 : 0x8C43,
+COMPARE_REF_TO_TEXTURE : 0x884E,
+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,
+MAX_VARYING_COMPONENTS : 0x8B4B,
+TEXTURE_2D_ARRAY : 0x8C1A,
+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,
+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,
+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,
+RGB_INTEGER : 0x8D98,
+RGBA_INTEGER : 0x8D99,
+SAMPLER_2D_ARRAY : 0x8DC1,
+SAMPLER_2D_ARRAY_SHADOW : 0x8DC4,
+SAMPLER_CUBE_SHADOW : 0x8DC5,
+UNSIGNED_INT_VEC2 : 0x8DC6,
+UNSIGNED_INT_VEC3 : 0x8DC7,
+UNSIGNED_INT_VEC4 : 0x8DC8,
+INT_SAMPLER_2D : 0x8DCA,
+INT_SAMPLER_3D : 0x8DCB,
+INT_SAMPLER_CUBE : 0x8DCC,
+INT_SAMPLER_2D_ARRAY : 0x8DCF,
+UNSIGNED_INT_SAMPLER_2D : 0x8DD2,
+UNSIGNED_INT_SAMPLER_3D : 0x8DD3,
+UNSIGNED_INT_SAMPLER_CUBE : 0x8DD4,
+UNSIGNED_INT_SAMPLER_2D_ARRAY : 0x8DD7,
+DEPTH_COMPONENT32F : 0x8CAC,
+DEPTH32F_STENCIL8 : 0x8CAD,
+FLOAT_32_UNSIGNED_INT_24_8_REV : 0x8DAD,
+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,
+UNSIGNED_INT_24_8 : 0x84FA,
+DEPTH24_STENCIL8 : 0x88F0,
+UNSIGNED_NORMALIZED : 0x8C17,
+DRAW_FRAMEBUFFER_BINDING : 0x8CA6,
+READ_FRAMEBUFFER : 0x8CA8,
+DRAW_FRAMEBUFFER : 0x8CA9,
+READ_FRAMEBUFFER_BINDING : 0x8CAA,
+RENDERBUFFER_SAMPLES : 0x8CAB,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER : 0x8CD4,
+MAX_COLOR_ATTACHMENTS : 0x8CDF,
+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,
+FRAMEBUFFER_INCOMPLETE_MULTISAMPLE : 0x8D56,
+MAX_SAMPLES : 0x8D57,
+HALF_FLOAT : 0x140B,
+RG : 0x8227,
+RG_INTEGER : 0x8228,
+R8 : 0x8229,
+RG8 : 0x822B,
+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,
+VERTEX_ARRAY_BINDING : 0x85B5,
+R8_SNORM : 0x8F94,
+RG8_SNORM : 0x8F95,
+RGB8_SNORM : 0x8F96,
+RGBA8_SNORM : 0x8F97,
+SIGNED_NORMALIZED : 0x8F9C,
+COPY_READ_BUFFER : 0x8F36,
+COPY_WRITE_BUFFER : 0x8F37,
+COPY_READ_BUFFER_BINDING : 0x8F36,
+COPY_WRITE_BUFFER_BINDING : 0x8F37,
+UNIFORM_BUFFER : 0x8A11,
+UNIFORM_BUFFER_BINDING : 0x8A28,
+UNIFORM_BUFFER_START : 0x8A29,
+UNIFORM_BUFFER_SIZE : 0x8A2A,
+MAX_VERTEX_UNIFORM_BLOCKS : 0x8A2B,
+MAX_FRAGMENT_UNIFORM_BLOCKS : 0x8A2D,
+MAX_COMBINED_UNIFORM_BLOCKS : 0x8A2E,
+MAX_UNIFORM_BUFFER_BINDINGS : 0x8A2F,
+MAX_UNIFORM_BLOCK_SIZE : 0x8A30,
+MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS : 0x8A31,
+MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS : 0x8A33,
+UNIFORM_BUFFER_OFFSET_ALIGNMENT : 0x8A34,
+ACTIVE_UNIFORM_BLOCKS : 0x8A36,
+UNIFORM_TYPE : 0x8A37,
+UNIFORM_SIZE : 0x8A38,
+UNIFORM_BLOCK_INDEX : 0x8A3A,
+UNIFORM_OFFSET : 0x8A3B,
+UNIFORM_ARRAY_STRIDE : 0x8A3C,
+UNIFORM_MATRIX_STRIDE : 0x8A3D,
+UNIFORM_IS_ROW_MAJOR : 0x8A3E,
+UNIFORM_BLOCK_BINDING : 0x8A3F,
+UNIFORM_BLOCK_DATA_SIZE : 0x8A40,
+UNIFORM_BLOCK_ACTIVE_UNIFORMS : 0x8A42,
+UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES : 0x8A43,
+UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER : 0x8A44,
+UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER : 0x8A46,
+INVALID_INDEX : 0xFFFFFFFF,
+MAX_VERTEX_OUTPUT_COMPONENTS : 0x9122,
+MAX_FRAGMENT_INPUT_COMPONENTS : 0x9125,
+MAX_SERVER_WAIT_TIMEOUT : 0x9111,
+OBJECT_TYPE : 0x9112,
+SYNC_CONDITION : 0x9113,
+SYNC_STATUS : 0x9114,
+SYNC_FLAGS : 0x9115,
+SYNC_FENCE : 0x9116,
+SYNC_GPU_COMMANDS_COMPLETE : 0x9117,
+UNSIGNALED : 0x9118,
+SIGNALED : 0x9119,
+ALREADY_SIGNALED : 0x911A,
+TIMEOUT_EXPIRED : 0x911B,
+CONDITION_SATISFIED : 0x911C,
+WAIT_FAILED : 0x911D,
+SYNC_FLUSH_COMMANDS_BIT : 0x00000001,
+TIMEOUT_IGNORED : -1,
+VERTEX_ATTRIB_ARRAY_DIVISOR : 0x88FE,
+ANY_SAMPLES_PASSED : 0x8C2F,
+ANY_SAMPLES_PASSED_CONSERVATIVE : 0x8D6A,
+SAMPLER_BINDING : 0x8919,
+RGB10_A2UI : 0x906F,
+INT_2_10_10_10_REV : 0x8D9F,
+TRANSFORM_FEEDBACK : 0x8E22,
+TRANSFORM_FEEDBACK_PAUSED : 0x8E23,
+TRANSFORM_FEEDBACK_ACTIVE : 0x8E24,
+TRANSFORM_FEEDBACK_BINDING : 0x8E25,
+TEXTURE_IMMUTABLE_FORMAT : 0x912F,
+MAX_ELEMENT_INDEX : 0x8D6B,
+TEXTURE_IMMUTABLE_LEVELS : 0x82DF,
+
+/* WebGL-specific enums */
+MAX_CLIENT_WAIT_TIMEOUT_WEBGL: 0x9247
+};
+
+// Other non-function properties on the WebGL object
+var otherProperties = {
+drawingBufferWidth : "number",
+drawingBufferHeight : "number",
+drawingBufferColorSpace : "string",
+unpackColorSpace : "string",
+canvas : "implementation-dependent"
+};
+
+// Properties to be ignored (as a list of strings) because they were
+// added in versions of the spec that are backward-compatible with
+// this version
+var ignoredProperties = [
+];
+
+// Constants removed from the WebGL spec compared to ES 3.0
+var removedConstants = {
+BUFFER_ACCESS_FLAGS : 0x911F,
+BUFFER_MAP_LENGTH : 0x9120,
+BUFFER_MAP_OFFSET : 0x9121,
+NUM_COMPRESSED_TEXTURE_FORMATS : 0x86A2,
+FIXED : 0x140C,
+ACTIVE_UNIFORM_MAX_LENGTH : 0x8B87,
+ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH : 0x8A35,
+ACTIVE_ATTRIBUTE_MAX_LENGTH : 0x8B8A,
+EXTENSIONS : 0x1F03,
+UNIFORM_NAME_LENGTH : 0x8A39,
+UNIFORM_BLOCK_NAME_LENGTH : 0x8A41,
+INFO_LOG_LENGTH : 0x8B84,
+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,
+SHADER_SOURCE_LENGTH : 0x8B88,
+SHADER_COMPILER : 0x8DFA,
+SHADER_BINARY_FORMATS : 0x8DF8,
+NUM_SHADER_BINARY_FORMATS : 0x8DF9,
+TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH : 0x8C76,
+FRAMEBUFFER_UNDEFINED : 0x8219,
+PROGRAM_BINARY_RETRIEVABLE_HINT : 0x8257,
+PROGRAM_BINARY_LENGTH : 0x8741,
+PROGRAM_BINARY_FORMATS : 0x87FE,
+NUM_PROGRAM_BINARY_FORMATS : 0x87FF,
+TEXTURE_SWIZZLE_A : 0x8E45,
+TEXTURE_SWIZZLE_B : 0x8E44,
+TEXTURE_SWIZZLE_G : 0x8E43,
+TEXTURE_SWIZZLE_R : 0x8E42,
+PRIMITIVE_RESTART_FIXED_INDEX : 0x8D69,
+};
+
+function assertProperty(v, p) {
+ if (p in v) {
+ return true;
+ } else {
+ testFailed("Property does not exist: " + p)
+ return false;
+ }
+}
+
+function assertNoProperty(v, p) {
+ if (p in v) {
+ testFailed("Property is defined and should not be: " + p)
+ return false;
+ } else {
+ return true;
+ }
+}
+
+function assertMsg_(bool, msg) {
+ if (!bool) // show only failures to avoid spamming result list
+ assertMsg(bool, msg);
+ return bool;
+}
+
+debug("");
+debug("Canvas.getContext");
+
+var canvas = document.getElementById("canvas");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(canvas, null, 2);
+var passed = true;
+for (var i in constants) {
+ var r = assertProperty(gl, i) && assertMsg_(gl[i] == constants[i], "Property "+i+" value test "+gl[i]+" == "+constants[i]);
+ passed = passed && r;
+}
+if (passed) {
+ testPassed("All WebGL constants found to have correct values.");
+}
+passed = true;
+for (var i in removedConstants) {
+ var r = assertNoProperty(gl, i);
+ passed = passed && r;
+}
+if (passed) {
+ testPassed("All constants removed from WebGL spec were absent from WebGL context.");
+}
+var extended = false;
+for (var i in gl) {
+ if (constants[i] !== undefined) {
+ // OK; known constant
+ } else if (ignoredProperties.indexOf(i) != -1) {
+ // OK; constant that should be ignored because it was added in a later version of the spec
+ } else if (otherProperties[i] !== undefined &&
+ (otherProperties[i] == "implementation-dependent" || typeof gl[i] == otherProperties[i])) {
+ // OK; known property of known type
+ } else if (typeof gl[i] != "function" && removedConstants[i] === undefined) {
+ if (!extended) {
+ extended = true;
+ testFailed("Also found the following extra properties:");
+ }
+ testFailed(i);
+ }
+}
+
+if (!extended) {
+ testPassed("No extra properties found on WebGL context.");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-attributes-depth-stencil-antialias-obeyed.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-attributes-depth-stencil-antialias-obeyed.html
new file mode 100644
index 0000000000..7cd91959f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-attributes-depth-stencil-antialias-obeyed.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+function getWebGL(attribs) {
+ var canvas = document.createElement("canvas");
+ if (!canvas)
+ return null;
+
+ // We can't use wtu.create3DContext because it defaults to antialias=false.
+ var names = ["webgl2"];
+ var gl = null;
+ for (var i = 0; i < names.length; ++i) {
+ try {
+ gl = canvas.getContext(names[i], attribs);
+ } catch (e) {
+ }
+ if (gl) {
+ break;
+ }
+ }
+ if (!gl)
+ return null;
+ return gl;
+}
+
+function testAttribs(attribs) {
+ var antialias, depth, stencil;
+ if (!attribs) {
+ antialias = true;
+ depth = true;
+ stencil = false;
+ debug("Testing default attributes: { antialias: true, depth: true, stencil:false }");
+ } else {
+ antialias = attribs.antialias;
+ depth = attribs.depth;
+ stencil = attribs.stencil;
+ debug("Testing specified attributes: { antialias: " + antialias + ", depth: " + depth + ", stencil: " + stencil + " }");
+ }
+ var gl = getWebGL(attribs);
+ if (!gl) {
+ testFailed("Fail to create a context");
+ return;
+ }
+ var actual_attribs = gl.getContextAttributes();
+ if (antialias != actual_attribs.antialias)
+ testFailed("antialias = " + antialias + " is not obeyed")
+ if (depth != actual_attribs.depth)
+ testFailed("depth = " + depth + " is not obeyed")
+ if (stencil != actual_attribs.stencil)
+ testFailed("stencil = " + stencil + " is not obeyed")
+ if (antialias == actual_attribs.antialias &&
+ depth == actual_attribs.depth &&
+ stencil == actual_attribs.stencil) {
+ testPassed("Context created with the correct antialias, depth, and stencil.");
+ }
+}
+
+description('Verify WebGLContextAttributes are working as specified, including depth, stencil, antialias');
+testAttribs(null); // Default attribs
+testAttribs({antialias: true, depth: true, stencil: true});
+testAttribs({antialias: false, depth: true, stencil: true});
+testAttribs({antialias: true, depth: false, stencil: true});
+testAttribs({antialias: false, depth: false, stencil: true});
+testAttribs({antialias: true, depth: true, stencil: false});
+testAttribs({antialias: false, depth: true, stencil: false});
+testAttribs({antialias: true, depth: false, stencil: false});
+testAttribs({antialias: false, depth: false, stencil: false});
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-mode.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-mode.html
new file mode 100644
index 0000000000..d896604c50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-mode.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Canvas Context Mode Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test ensures WebGL 2.0 implementations respect the canvas's context mode.");
+
+debug("");
+
+assertMsg(window.WebGLRenderingContext,
+ "WebGL2RenderingContext should be a member of window");
+assertMsg('WebGL2RenderingContext' in window,
+ "WebGL2RenderingContext should be 'in' window");
+
+function testContextMode(mode, altMode) {
+ debug("Testing " + mode + " context type");
+
+ let c = document.createElement('canvas');
+ c.width = 2;
+ c.height = 2;
+ let gl = c.getContext(mode);
+ assertMsg(c.getContext(mode) == gl,
+ "Canvas.getContext('" + mode + "') should return the same value every time");
+ try {
+ assertMsg(c.getContext(altMode) == null,
+ "Canvas.getContext('" + altMode + "') after getContext('" + mode + "') should return null");
+ } catch (e) {
+ testFailed("Canvas.getContext('" + altMode + "') after getContext('" + mode + "') should not throw an exception");
+ }
+}
+
+testContextMode('webgl2', 'webgl');
+testContextMode('webgl', 'webgl2');
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-resize-changes-buffer-binding-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-resize-changes-buffer-binding-bug.html
new file mode 100644
index 0000000000..e6682295a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-resize-changes-buffer-binding-bug.html
@@ -0,0 +1,49 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Context Resize Bug Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="test"></canvas>
+<script>
+"use strict";
+description("This test verifies canvas resize does not affect PIXEL_UNPACK_BUFFER binding.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("test");
+var gl = wtu.create3DContext(canvas, null, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+ var texture1= gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, texture1);
+ var buffer0= gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer0);
+
+ canvas.width = 682;
+ // Resizing canvas incorrectly cleared the PIXEL_UNPACK_BUFFER binding to 0
+ // and caused a crash from the following line in Chrome. crbug.com/673929.
+ gl.texImage3D(gl.TEXTURE_3D, 1, gl.R8, 225,664 , 143, 0,
+ gl.LUMINANCE_ALPHA, gl.UNSIGNED_SHORT_4_4_4_4, 0x41414141);
+ testPassed("no crash from texImage3D");
+}
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-sharing-texture2darray-texture3d-data-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-sharing-texture2darray-texture3d-data-bug.html
new file mode 100644
index 0000000000..8ef6dd74b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-sharing-texture2darray-texture3d-data-bug.html
@@ -0,0 +1,150 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Multiple WebGL2 Context sharing texture2darray/texture3d data bug test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas1" width="64" height="64"> </canvas>
+<canvas id="canvas2" width="64" height="64"> </canvas>
+<div id="console"></div>
+
+<!-- WebGL 2 Shaders -->
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+in vec4 a_position;
+in vec2 a_coord;
+out vec2 v_coord;
+void main() {
+ gl_Position = a_position;
+ v_coord = a_coord;
+}
+</script>
+
+<script id="fs_texture_3d" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+in vec2 v_coord;
+uniform mediump sampler3D u_sampler;
+out vec4 o_color;
+void main () {
+ o_color = texture(u_sampler, vec3(v_coord, 0.0));
+}
+</script>
+
+<script id="fs_texture_2d_array" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+in vec2 v_coord;
+uniform mediump sampler2DArray u_sampler;
+out vec4 o_color;
+void main () {
+ o_color = texture(u_sampler, vec3(v_coord, 0.0));
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies that 2 different contexts both using 2d array texture or 3d texture does not share the texture data among them due to context save/restore bug. https://bugs.chromium.org/p/chromium/issues/detail?id=788448");
+debug("");
+
+function render(gl, width, height, expectedColor, msg) {
+ wtu.setupUnitQuad(gl, 0, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, msg);
+}
+
+function StateSetup(gl, texture_type, texture_color, width, height) {
+
+ // create a buffer to hold texture data
+ const depth = 4;
+ var size = width * height * depth * 4;
+ var buf = new Uint8Array(size);
+ for (var i = 0; i < size; i += 4) {
+ buf[i + 0] = texture_color[0];
+ buf[i + 1] = texture_color[1];
+ buf[i + 2] = texture_color[2];
+ buf[i + 3] = texture_color[3];
+ }
+ gl.viewport(0, 0, width, height);
+
+ // choose texture type and fragment shader type
+ var tex_type = gl.TEXTURE_2D;
+ var fragment_shader = "", vertex_shader = "vs";
+ if(texture_type === "3d") {
+ tex_type = gl.TEXTURE_3D, fragment_shader = "fs_texture_3d";
+ } else if(texture_type === "2d_array") {
+ tex_type = gl.TEXTURE_2D_ARRAY, fragment_shader = "fs_texture_2d_array";
+ } else {
+ testFailed("Texture type must be 3d or 2darray");
+ }
+
+ var program = wtu.setupProgram(gl, [vertex_shader, fragment_shader], ['a_position', 'a_coord'], [0, 1]);
+
+ // create a texture
+ var texture = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+
+ // program texture parameters
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(tex_type, texture);
+ gl.texImage3D(tex_type, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ gl.texParameteri(tex_type, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(tex_type, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ // bind sampler to the texture
+ var samplerLoc = gl.getUniformLocation(program, "u_sampler");
+ gl.uniform1i(samplerLoc, 0);
+
+ // flush all gl commands
+ gl.flush();
+}
+
+var wtu = WebGLTestUtils;
+var canvas1 = document.getElementById("canvas1");
+var gl1 = wtu.create3DContext(canvas1, null, 2); //context1
+
+var canvas2 = document.getElementById("canvas2");
+var gl2 = wtu.create3DContext(canvas2, null, 2); // context2
+
+if (gl1 && gl2)
+{
+ testPassed("Created 2 WebGL2 context successfully");
+ var red = [255, 0, 0, 255], green = [0,255,0,255], blue = [0,0,255,255];
+ var width = 64, height = 64;
+ var texture_type = "3d", texture_color = green;
+ StateSetup(gl1,texture_type, texture_color, width, height);// context1 state setup
+ texture_color = red;
+ StateSetup(gl2, texture_type, texture_color, width, height);// context2 state setup
+ render(gl1, width, height, green, "Result pixels rendering from context1 with 3d texture should be green");// render context1
+
+ texture_type = "2d_array", texture_color = blue;
+ StateSetup(gl1, texture_type, texture_color, width, height);// context1 state setup
+ texture_color = green;
+ StateSetup(gl2, texture_type, texture_color, width, height);// context2 state setup
+ render(gl1, width, height, blue, "Result pixels rendering from context1 with 2darray texture should be blue");//render context1
+}
+else if(!gl1)
+{
+ testFailed("Fail to get 1st WebGL2 context");
+}
+else
+{
+ testFailed("Fail to get 2nd WebGL2 context");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-type-test-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-type-test-2.html
new file mode 100644
index 0000000000..42ca0f3742
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/context-type-test-2.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas1" style="width: 50px; height: 50px;"> </canvas>
+<canvas id="canvas2" style="width: 50px; height: 50px;"> </canvas>
+<script>
+"use strict";
+description("This test ensures WebGL2 implementations interact correctly with the canvas tag.");
+
+debug("");
+debug("Canvas.getContext");
+
+function runTest() {
+ assertMsg(window.WebGL2RenderingContext,
+ "WebGL2RenderingContext should be a member of window");
+ assertMsg('WebGL2RenderingContext' in window,
+ "WebGL2RenderingContext should be 'in' window");
+
+ const wtu = WebGLTestUtils;
+ let canvas2 = document.getElementById("canvas2");
+ let gl2 = wtu.create3DContext(canvas2, null, 2);
+ if (!gl2) {
+ testFailed("Could not fetch WebGL 2.0 context");
+ return;
+ }
+ testPassed("Fetched WebGL2 context successfully");
+
+ debug("Checking WebGL2 context type");
+ assertMsg(gl2 instanceof WebGL2RenderingContext,
+ "context type should be WebGL2RenderingContext");
+
+ // WebGL1 contexts do not respond to the WebGL2 context type, and vice versa.
+ let canvas1 = document.getElementById("canvas1");
+ let gl1 = wtu.create3DContext(canvas1, null, 1);
+ if (!gl1) {
+ testFailed("Could not fetch WebGL 1.0 context");
+ return;
+ }
+
+ debug("Checking WebGL1 context type");
+ assertMsg(gl1 instanceof WebGLRenderingContext,
+ "context type should be WebGLRenderingContext");
+
+ let msg1 = "A canvas which has created a WebGL 1.0 context should not return it for a 'webgl2' context request";
+ if (canvas1.getContext("webgl2"))
+ testFailed(msg1);
+ else
+ testPassed(msg1);
+
+ let msg2 = "A canvas which has created a WebGL 2.0 context should not return it for a 'webgl' context request";
+ if (canvas2.getContext("webgl"))
+ testFailed(msg2);
+ else
+ testPassed(msg2);
+}
+
+runTest();
+debug("");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/incorrect-context-object-behaviour.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/incorrect-context-object-behaviour.html
new file mode 100644
index 0000000000..3f0b54fc6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/incorrect-context-object-behaviour.html
@@ -0,0 +1,230 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="tf-vshader" type="x-shader/x-vertex">#version 300 es
+in uint in_data;
+flat out uint out_data;
+void main() {
+ out_data = in_data;
+}
+</script>
+<script id="tf-fshader" type="x-shader/x-fragment">#version 300 es
+void main() {}
+</script>
+
+<script>
+"use strict";
+description("Tests calling WebGL 2.0 APIs with objects from other contexts");
+
+function loadTFProgram(context) {
+ const tfProgram = wtu.setupTransformFeedbackProgram(context, ["tf-vshader", "tf-fshader"],
+ ["out_data"], context.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(context, context.NO_ERROR, "linking transform feedback shader should not set an error");
+ return tfProgram;
+}
+
+function create2DTextureArray4x4x4(context) {
+ const texture = context.createTexture();
+ context.bindTexture(context.TEXTURE_2D_ARRAY, texture);
+ context.texImage3D(context.TEXTURE_2D_ARRAY, 0, context.RGBA8, 4, 4, 4, 0, context.RGBA, context.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(context, context.NO_ERROR, "allocating 2D texture array should not set an error");
+ return texture;
+}
+
+var wtu = WebGLTestUtils;
+var contextA = wtu.create3DContext(undefined, undefined, 2);
+var contextB = wtu.create3DContext(undefined, undefined, 2);
+var bufferA = contextA.createBuffer();
+var bufferB = contextB.createBuffer();
+var frameBufferA = contextA.createFramebuffer();
+var frameBufferB = contextB.createFramebuffer();
+var programB = wtu.loadStandardProgram(contextB);
+var queryB = contextB.createQuery();
+var samplerA = contextA.createSampler();
+var samplerB = contextB.createSampler();
+var syncB = contextB.fenceSync(contextB.SYNC_GPU_COMMANDS_COMPLETE, 0);
+var transformFeedbackA = contextA.createTransformFeedback();
+var transformFeedbackB = contextB.createTransformFeedback();
+var vertexArrayA = contextA.createVertexArray();
+var vertexArrayB = contextB.createVertexArray();
+var tfProgramB = loadTFProgram(contextB);
+var texture2DArrayA = create2DTextureArray4x4x4(contextA);
+var texture2DArrayB = create2DTextureArray4x4x4(contextB);
+var locationB = contextB.getUniformLocation(programB, 'u_modelViewProjMatrix');
+var uniformData = [];
+
+function generateFloat32Array(length) {
+ uniformData = new Float32Array(length);
+}
+
+function generateFloatArray(length) {
+ uniformData = new Array(length);
+ for (var i = 0; i < length; i++) {
+ uniformData[i] = 0.0;
+ }
+}
+
+function generateInt32Array(length) {
+ uniformData = new Int32Array(length);
+}
+
+function generateIntArray(length) {
+ uniformData = new Array(length);
+ for (var i = 0; i < length; i++) {
+ uniformData[i] = 0;
+ }
+}
+
+function generateUint32Array(length) {
+ uniformData = new Uint32Array(length);
+}
+
+// Make the bindable objects valid in both contexts first.
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, bufferA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, bufferB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, null)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTransformFeedback(contextA.TRANSFORM_FEEDBACK, transformFeedbackA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTransformFeedback(contextA.TRANSFORM_FEEDBACK, null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTransformFeedback(contextB.TRANSFORM_FEEDBACK, transformFeedbackB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTransformFeedback(contextB.TRANSFORM_FEEDBACK, null)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindVertexArray(vertexArrayA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindVertexArray(null)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindVertexArray(vertexArrayB)");
+wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindVertexArray(null)");
+
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferA)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferTextureLayer(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, texture2DArrayB, 0, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getFragDataLocation(tfProgramB, 'nonexistent_variable')");
+// Unsigned int uniforms
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1ui(locationB, 0)");
+generateUint32Array(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1uiv(locationB, uniformData)");
+generateIntArray(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1uiv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2ui(locationB, 0, 0)");
+generateUint32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2uiv(locationB, uniformData)");
+generateIntArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2uiv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3ui(locationB, 0, 0, 0)");
+generateUint32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3uiv(locationB, uniformData)");
+generateIntArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3uiv(locationB, uniformData)");
+ wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4ui(locationB, 0, 0, 0, 0)");
+generateUint32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4uiv(locationB, uniformData)");
+generateIntArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4uiv(locationB, uniformData)");
+// New uniform entry points with offsets
+generateFloat32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData, 1)");
+generateFloatArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData, 1)");
+generateInt32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData, 1)");
+generateIntArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData, 1)");
+generateFloat32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData, 1)");
+generateFloatArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData, 1)");
+generateInt32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData, 1)");
+generateIntArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData, 1)");
+generateFloat32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData, 1)");
+generateFloatArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData, 1)");
+generateInt32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData, 1)");
+generateIntArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData, 1)");
+generateFloat32Array(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData, 1)");
+generateFloatArray(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData, 1)");
+generateInt32Array(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData, 1)");
+generateIntArray(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData, 1)");
+generateFloat32Array(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData, 1)");
+generateFloatArray(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData, 1)");
+generateFloat32Array(10); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData, 1)");
+generateFloatArray(10); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData, 1)");
+generateFloat32Array(17); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData, 1)");
+generateFloatArray(17); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData, 1)");
+// Non-rectangular matrix uniform entry points
+generateFloat32Array(6);
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x2fv(locationB, false, uniformData)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x3fv(locationB, false, uniformData)");
+generateFloatArray(6);
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x2fv(locationB, false, uniformData)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x3fv(locationB, false, uniformData)");
+generateFloat32Array(8);
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x2fv(locationB, false, uniformData)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x4fv(locationB, false, uniformData)");
+generateFloatArray(8);
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x2fv(locationB, false, uniformData)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x4fv(locationB, false, uniformData)");
+generateFloat32Array(12);
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x3fv(locationB, false, uniformData)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x4fv(locationB, false, uniformData)");
+generateFloatArray(12);
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x3fv(locationB, false, uniformData)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x4fv(locationB, false, uniformData)");
+
+// Query objects
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteQuery(queryB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isQuery(queryB)");
+shouldBeFalse("contextA.isQuery(queryB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.beginQuery(contextA.ANY_SAMPLES_PASSED, queryB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getQueryParameter(queryB, contextA.QUERY_RESULT_AVAILABLE)");
+
+// Sampler objects
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteSampler(samplerB)");
+wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "contextB.deleteSampler(samplerA)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindSampler(0, samplerB)");
+wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "contextB.bindSampler(0, samplerA)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isSampler(samplerB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextB.isSampler(samplerA)");
+shouldBeFalse("contextA.isSampler(samplerB)");
+shouldBeFalse("contextB.isSampler(samplerA)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.samplerParameteri(samplerB, contextA.TEXTURE_WRAP_S, contextA.CLAMP_TO_EDGE)");
+wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "contextB.samplerParameteri(samplerA, contextB.TEXTURE_WRAP_S, contextB.CLAMP_TO_EDGE)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.samplerParameterf(samplerB, contextA.TEXTURE_MIN_LOD, -500.5)");
+wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "contextB.samplerParameterf(samplerA, contextB.TEXTURE_MIN_LOD, -500.5)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getSamplerParameter(samplerB, contextA.TEXTURE_WRAP_S)");
+wtu.shouldGenerateGLError(contextB, contextB.INVALID_OPERATION, "contextB.getSamplerParameter(samplerA, contextB.TEXTURE_WRAP_S)");
+
+// Sync objects
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteSync(syncB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isSync(syncB)");
+shouldBeFalse("contextA.isSync(syncB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.clientWaitSync(syncB, 0, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.waitSync(syncB, 0, contextA.TIMEOUT_IGNORED)");
+
+// Transform feedback
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteTransformFeedback(transformFeedbackB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isTransformFeedback(transformFeedbackB)");
+shouldBeFalse("contextA.isTransformFeedback(transformFeedbackB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindTransformFeedback(contextA.TRANSFORM_FEEDBACK, transformFeedbackB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.transformFeedbackVaryings(tfProgramB, ['out_data'], contextA.SEPARATE_ATTRIBS)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getTransformFeedbackVarying(tfProgramB, 0)");
+
+// Uniform buffer objects and transform feedback buffers
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindBufferBase(contextA.UNIFORM_BUFFER, 0, bufferB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindBufferRange(contextA.UNIFORM_BUFFER, 0, bufferB, 0, 4)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformIndices(programB, ['u_modelViewProjMatrix'])");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniforms(programB, [0], contextA.UNIFORM_TYPE)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformBlockIndex(programB, 'nonexistent_uniform_block_name')");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniformBlockParameter(programB, 0, contextA.UNIFORM_BLOCK_BINDING)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniformBlockName(programB, 0)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformBlockBinding(programB, 0, 0)");
+
+// Vertex Array objects
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteVertexArray(vertexArrayB)");
+wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isVertexArray(vertexArrayB)");
+shouldBeFalse("contextA.isVertexArray(vertexArrayB)");
+wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindVertexArray(vertexArrayB)");
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/methods-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/methods-2.html
new file mode 100644
index 0000000000..a389329aa3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/methods-2.html
@@ -0,0 +1,268 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Methods Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/context-methods.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<script>
+"use strict";
+description("This test ensures that the WebGL context has all the methods in the specification.");
+
+const methods = [
+ "getContextAttributes",
+ "activeTexture",
+ "attachShader",
+ "bindAttribLocation",
+ "bindBuffer",
+ "bindFramebuffer",
+ "bindRenderbuffer",
+ "bindTexture",
+ "blendColor",
+ "blendEquation",
+ "blendEquationSeparate",
+ "blendFunc",
+ "blendFuncSeparate",
+ "bufferData",
+ "bufferSubData",
+ "checkFramebufferStatus",
+ "clear",
+ "clearColor",
+ "clearDepth",
+ "clearStencil",
+ "colorMask",
+ "compileShader",
+ "compressedTexImage2D",
+ "compressedTexSubImage2D",
+ "copyTexImage2D",
+ "copyTexSubImage2D",
+ "createBuffer",
+ "createFramebuffer",
+ "createProgram",
+ "createRenderbuffer",
+ "createShader",
+ "createTexture",
+ "cullFace",
+ "deleteBuffer",
+ "deleteFramebuffer",
+ "deleteProgram",
+ "deleteRenderbuffer",
+ "deleteShader",
+ "deleteTexture",
+ "depthFunc",
+ "depthMask",
+ "depthRange",
+ "detachShader",
+ "disable",
+ "disableVertexAttribArray",
+ "drawArrays",
+ "drawElements",
+ "enable",
+ "enableVertexAttribArray",
+ "finish",
+ "flush",
+ "framebufferRenderbuffer",
+ "framebufferTexture2D",
+ "frontFace",
+ "generateMipmap",
+ "getActiveAttrib",
+ "getActiveUniform",
+ "getAttachedShaders",
+ "getAttribLocation",
+ "getParameter",
+ "getBufferParameter",
+ "getError",
+ "getExtension",
+ "getFramebufferAttachmentParameter",
+ "getProgramParameter",
+ "getProgramInfoLog",
+ "getRenderbufferParameter",
+ "getShaderParameter",
+ "getShaderInfoLog",
+ "getShaderPrecisionFormat",
+ "getShaderSource",
+ "getSupportedExtensions",
+ "getTexParameter",
+ "getUniform",
+ "getUniformLocation",
+ "getVertexAttrib",
+ "getVertexAttribOffset",
+ "hint",
+ "isBuffer",
+ "isContextLost",
+ "isEnabled",
+ "isFramebuffer",
+ "isProgram",
+ "isRenderbuffer",
+ "isShader",
+ "isTexture",
+ "lineWidth",
+ "linkProgram",
+ "pixelStorei",
+ "polygonOffset",
+ "readPixels",
+ "renderbufferStorage",
+ "sampleCoverage",
+ "scissor",
+ "shaderSource",
+ "stencilFunc",
+ "stencilFuncSeparate",
+ "stencilMask",
+ "stencilMaskSeparate",
+ "stencilOp",
+ "stencilOpSeparate",
+ "texImage2D",
+ "texParameterf",
+ "texParameteri",
+ "texSubImage2D",
+ "uniform1f",
+ "uniform1fv",
+ "uniform1i",
+ "uniform1iv",
+ "uniform2f",
+ "uniform2fv",
+ "uniform2i",
+ "uniform2iv",
+ "uniform3f",
+ "uniform3fv",
+ "uniform3i",
+ "uniform3iv",
+ "uniform4f",
+ "uniform4fv",
+ "uniform4i",
+ "uniform4iv",
+ "uniformMatrix2fv",
+ "uniformMatrix3fv",
+ "uniformMatrix4fv",
+ "useProgram",
+ "validateProgram",
+ "vertexAttrib1f",
+ "vertexAttrib1fv",
+ "vertexAttrib2f",
+ "vertexAttrib2fv",
+ "vertexAttrib3f",
+ "vertexAttrib3fv",
+ "vertexAttrib4f",
+ "vertexAttrib4fv",
+ "vertexAttribPointer",
+ "viewport",
+
+ // WebGL2 methods
+ "getBufferSubData",
+ "copyBufferSubData",
+ "blitFramebuffer",
+ "framebufferTextureLayer",
+ "getInternalformatParameter",
+ "invalidateFramebuffer",
+ "invalidateSubFramebuffer",
+ "readBuffer",
+ "renderbufferStorageMultisample",
+ "texImage3D",
+ "texStorage2D",
+ "texStorage3D",
+ "texSubImage3D",
+ "copyTexSubImage3D",
+ "compressedTexImage3D",
+ "compressedTexSubImage3D",
+ "getFragDataLocation",
+ "uniform1ui",
+ "uniform2ui",
+ "uniform3ui",
+ "uniform4ui",
+ "uniform1uiv",
+ "uniform2uiv",
+ "uniform3uiv",
+ "uniform4uiv",
+ "uniformMatrix2x3fv",
+ "uniformMatrix3x2fv",
+ "uniformMatrix2x4fv",
+ "uniformMatrix4x2fv",
+ "uniformMatrix3x4fv",
+ "uniformMatrix4x3fv",
+ "vertexAttribI4i",
+ "vertexAttribI4iv",
+ "vertexAttribI4ui",
+ "vertexAttribI4uiv",
+ "vertexAttribIPointer",
+ "vertexAttribDivisor",
+ "drawArraysInstanced",
+ "drawElementsInstanced",
+ "drawRangeElements",
+ "drawBuffers",
+ "clearBufferiv",
+ "clearBufferuiv",
+ "clearBufferfv",
+ "clearBufferfi",
+ "createQuery",
+ "deleteQuery",
+ "isQuery",
+ "beginQuery",
+ "endQuery",
+ "getQuery",
+ "getQueryParameter",
+ "createSampler",
+ "deleteSampler",
+ "isSampler",
+ "bindSampler",
+ "samplerParameteri",
+ "samplerParameterf",
+ "getSamplerParameter",
+ "fenceSync",
+ "isSync",
+ "deleteSync",
+ "clientWaitSync",
+ "waitSync",
+ "getSyncParameter",
+ "createTransformFeedback",
+ "deleteTransformFeedback",
+ "isTransformFeedback",
+ "bindTransformFeedback",
+ "beginTransformFeedback",
+ "endTransformFeedback",
+ "transformFeedbackVaryings",
+ "getTransformFeedbackVarying",
+ "pauseTransformFeedback",
+ "resumeTransformFeedback",
+ "bindBufferBase",
+ "bindBufferRange",
+ "getIndexedParameter",
+ "getUniformIndices",
+ "getActiveUniforms",
+ "getUniformBlockIndex",
+ "getActiveUniformBlockParameter",
+ "getActiveUniformBlockName",
+ "uniformBlockBinding",
+ "createVertexArray",
+ "deleteVertexArray",
+ "isVertexArray",
+ "bindVertexArray",
+];
+
+debug("");
+debug("Canvas.getContext");
+
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("canvas");
+const gl = wtu.create3DContext(canvas, null, 2);
+
+testContextMethods(gl, methods);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/context/no-experimental-webgl2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/context/no-experimental-webgl2.html
new file mode 100644
index 0000000000..65aa9cb16d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/context/no-experimental-webgl2.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<canvas id="canvas2d" width="40" height="40"> </canvas>
+<script>
+"use strict";
+description("This test ensures WebGL2 implementations do not respond to experimental-webgl2.");
+
+debug("");
+
+var canvas = document.getElementById("canvas");
+shouldBeNull('canvas.getContext("experimental-webgl2")');
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/00_test_list.txt
new file mode 100644
index 0000000000..559071ff06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/00_test_list.txt
@@ -0,0 +1,19 @@
+ext-color-buffer-float.html
+--min-version 2.0.1 ext-color-buffer-half-float.html
+ext-disjoint-timer-query-webgl2.html
+--min-version 2.0.1 ext-texture-filter-anisotropic.html
+--min-version 2.0.1 ext-texture-norm16.html
+promoted-extensions.html
+promoted-extensions-in-shaders.html
+--min-version 2.0.1 oes-draw-buffers-indexed.html
+--min-version 2.0.1 ovr_multiview2.html
+--min-version 2.0.1 ovr_multiview2_depth.html
+--min-version 2.0.1 ovr_multiview2_draw_buffers.html
+--min-version 2.0.1 ovr_multiview2_flat_varying.html
+--min-version 2.0.1 ovr_multiview2_instanced_draw.html
+--min-version 2.0.1 ovr_multiview2_non_multiview_shaders.html
+--min-version 2.0.1 ovr_multiview2_single_view_operations.html
+--min-version 2.0.1 ovr_multiview2_timer_query.html
+--min-version 2.0.1 ovr_multiview2_transform_feedback.html
+--min-version 2.0.1 required-extensions.html
+--min-version 2.0.1 webgl-multi-draw-instanced-base-vertex-base-instance.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html
new file mode 100644
index 0000000000..b57a6ca10d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html
@@ -0,0 +1,508 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_color_buffer_float Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing floating-point textures -->
+<script id="testFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+uniform vec4 subtractor;
+varying vec2 texCoord;
+void main()
+{
+ vec4 color = texture2D(tex, texCoord);
+ if (abs(color.r - subtractor.r) +
+ abs(color.g - subtractor.g) +
+ abs(color.b - subtractor.b) +
+ abs(color.a - subtractor.a) < 16.0) {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ } else {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+}
+</script>
+<!-- Shaders for testing floating-point render targets -->
+<script id="floatingPointFragmentShader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(1000.0, 1000.0, 1000.0, 1000.0);
+}
+</script>
+<script>
+"use strict";
+
+function allocateTexture()
+{
+ 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);
+ 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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
+ return texture;
+}
+
+function checkRenderingResults()
+{
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function arrayToString(arr, size) {
+ var mySize;
+ if (!size)
+ mySize = arr.length;
+ else
+ mySize = size;
+ var out = "[";
+ for (var ii = 0; ii < mySize; ++ii) {
+ if (ii > 0) {
+ out += ", ";
+ }
+ out += arr[ii];
+ }
+ return out + "]";
+}
+
+function runReadbackTest(testProgram, subtractor)
+{
+ // Verify floating point readback
+ debug("Checking readback of floating-point values");
+ var buf = new Float32Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT , buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels from floating-point framebuffer should succeed");
+ var ok = true;
+ var tolerance = 8.0; // TODO: factor this out from both this test and the subtractor shader above.
+ for (var ii = 0; ii < buf.length; ++ii) {
+ if (Math.abs(buf[ii] - subtractor[ii]) > tolerance) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ testPassed("readPixels of float-type data from floating-point framebuffer succeeded");
+ } else {
+ testFailed("readPixels of float-type data from floating-point framebuffer failed: expected "
+ + arrayToString(subtractor, 4) + ", got " + arrayToString(buf));
+ }
+}
+
+function runFloatTextureRenderTargetTest(enabled, internalFormat, format, testProgram, numberOfChannels, subtractor, texSubImageCover)
+{
+ var formatString = wtu.glEnumToString(gl, internalFormat);
+ debug("");
+ debug("testing floating-point " + formatString + " texture render target" + (texSubImageCover > 0 ? " after calling texSubImage" : ""));
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, gl.FLOAT, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed");
+
+ // Try to use this texture as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (!enabled) {
+ if (completeStatus == gl.FRAMEBUFFER_COMPLETE && !enabled)
+ testFailed("floating-point " + formatString + " render target should not be supported without enabling EXT_color_buffer_float");
+ else
+ testPassed("floating-point " + formatString + " render target should not be supported without enabling EXT_color_buffer_float");
+ return;
+ }
+
+ if (completeStatus != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("floating-point " + formatString + " render target not supported");
+ return;
+ }
+
+ if (texSubImageCover > 0) {
+ // Ensure that replacing the whole texture or a part of it with texSubImage2D doesn't affect renderability
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ var data = new Float32Array(width * height * numberOfChannels * texSubImageCover);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height * texSubImageCover, format, gl.FLOAT, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed if EXT_color_buffer_float is enabled");
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("render target support changed after calling texSubImage2D");
+ return;
+ }
+ }
+
+ var renderProgram =
+ wtu.setupProgram(gl,
+ [wtu.simpleVertexShader, "floatingPointFragmentShader"],
+ ['vPosition'],
+ [0]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed");
+
+ // Now sample from the floating-point texture and verify we got the correct values.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.useProgram(testProgram);
+ gl.uniform1i(gl.getUniformLocation(testProgram, "tex"), 0);
+ gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from floating-point texture should succeed");
+ checkRenderingResults();
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ runReadbackTest(testProgram, subtractor);
+}
+
+function runFloatRenderbufferRenderTargetTest(enabled, internalFormat, testProgram, numberOfChannels, subtractor)
+{
+ var formatString = wtu.glEnumToString(gl, internalFormat);
+ var samples = [0];
+ if (enabled) {
+ samples = Array.prototype.slice.call(gl.getInternalformatParameter(gl.RENDERBUFFER, internalFormat, gl.SAMPLES));
+ samples.push(0);
+ }
+ for (var ndx = 0; ndx < samples.length; ++ndx) {
+ debug("");
+ debug("testing floating-point " + formatString + " renderbuffer render target with number of samples " + samples[ndx]);
+
+ var colorbuffer = gl.createRenderbuffer();
+ var width = 2;
+ var height = 2;
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
+ if (samples[ndx] == 0)
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, width, height);
+ else
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[ndx], internalFormat, width, height);
+ if (!enabled) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point renderbuffer allocation should fail if EXT_color_buffer_float is not enabled");
+ return;
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point renderbuffer allocation should succeed if EXT_color_buffer_float is enabled");
+ }
+
+ // Try to use this renderbuffer as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorbuffer);
+
+ var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (completeStatus != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("floating-point " + formatString + " render target not supported");
+ return;
+ }
+ var resolveColorRbo = null;
+ var resolveFbo = null;
+ if (samples[ndx] > 0) {
+ resolveColorRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, resolveColorRbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, width, height);
+ resolveFbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resolveColorRbo);
+ completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (completeStatus != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Failed to create resolve framebuffer");
+ return;
+ }
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.clearColor(1000.0, 1000.0, 1000.0, 1000.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ if (samples[ndx] > 0) {
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFbo);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, resolveFbo);
+ }
+ runReadbackTest(testProgram, subtractor);
+ }
+}
+
+function runRGB16FNegativeTest()
+{
+ debug("");
+ debug("testing RGB16F isn't color renderable");
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB16F, width, height, 0, gl.RGB, gl.FLOAT, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "RGB16F texture allocation should succeed");
+
+ // Try to use this texture as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (completeStatus == gl.FRAMEBUFFER_COMPLETE)
+ testFailed("RGB16F render target should not be supported with or without enabling EXT_color_buffer_float");
+ else
+ testPassed("RGB16F render target should not be supported with or without enabling EXT_color_buffer_float");
+ gl.deleteTexture(texture);
+
+ var colorbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB16F, width, height);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "RGB16F renderbuffer allocation should fail with or without enabling EXT_color_buffer_float");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(colorbuffer);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ gl.getExtension("EXT_color_buffer_float").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("EXT_color_buffer_float").myProperty', '2');
+}
+
+function runInternalFormatQueryTest()
+{
+ debug("");
+ debug("testing the internal format query");
+
+ var maxSamples = gl.getParameter(gl.MAX_SAMPLES);
+ const formats = [gl.RGBA16F, gl.R32F, gl.RG32F, gl.RGBA32F, gl.R16F, gl.RG16F, gl.R11F_G11F_B10F];
+ var firstMultiOnlyFormat = 4;
+ for (var fmt = 0; fmt < formats.length; ++fmt) {
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, formats[fmt], gl.SAMPLES);
+ if (fmt >= firstMultiOnlyFormat && (samples.length == 0 || samples[0] < maxSamples)) {
+ testFailed("the maximum value in SAMPLES should be at least " + maxSamples);
+ return;
+ }
+
+ var prevSampleCount = 0;
+ var sampleCount;
+ for (var ndx = 0; ndx < samples.length; ++ndx, prevSampleCount = sampleCount) {
+ sampleCount = samples[ndx];
+ // sample count must be > 0
+ if (sampleCount <= 0) {
+ testFailed("Expected sample count to be at least one; got " + sampleCount);
+ return;
+ }
+
+ // samples must be ordered descending
+ if (ndx > 0 && sampleCount >= prevSampleCount) {
+ testFailed("Expected sample count to be ordered in descending order; got " + prevSampleCount + " at index " + (ndx - 1) + ", and " + sampleCount + " at index " + ndx);
+ return;
+ }
+ }
+ }
+ testPassed("Internal format query succeeded");
+}
+
+function runCopyTexImageTest(enabled)
+{
+ var width = 16;
+ var height = 16;
+ var level = 0;
+ var cases = [
+ {
+ internalformat: "RGBA16F",
+ format: "RGBA",
+ type: "HALF_FLOAT",
+ destInternalformat: "R16F",
+ data: new Uint16Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA32F",
+ format: "RGBA",
+ type: "FLOAT",
+ destInternalformat: "R32F",
+ data: new Float32Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA16F",
+ format: "RGBA",
+ type: "HALF_FLOAT",
+ destInternalformat: "RG16F",
+ data: new Uint16Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA32F",
+ format: "RGBA",
+ type: "FLOAT",
+ destInternalformat: "RG32F",
+ data: new Float32Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA16F",
+ format: "RGBA",
+ type: "HALF_FLOAT",
+ destInternalformat: "RGB16F",
+ data: new Uint16Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA32F",
+ format: "RGBA",
+ type: "FLOAT",
+ destInternalformat: "RGB32F",
+ data: new Float32Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA16F",
+ format: "RGBA",
+ type: "HALF_FLOAT",
+ destInternalformat: "RGBA16F",
+ data: new Uint16Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA32F",
+ format: "RGBA",
+ type: "FLOAT",
+ destInternalformat: "RGBA32F",
+ data: new Float32Array(width * height * 4)
+ },
+ {
+ internalformat: "R11F_G11F_B10F",
+ format: "RGB",
+ type: "FLOAT",
+ destInternalformat: "R11F_G11F_B10F",
+ data: new Float32Array(width * height * 3)
+ }
+ ];
+ cases.forEach(function(testcase) {
+ debug("");
+ debug("Testing CopyTexImage2D for internalformat: " + testcase.destInternalformat);
+
+ var internalformat = gl[testcase.internalformat];
+ var format = gl[testcase.format];
+ var type = gl[testcase.type];
+ var destInternalformat = gl[testcase.destInternalformat];
+ var texSrc = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texSrc);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ var data = testcase.data;
+ gl.texImage2D(gl.TEXTURE_2D, level, internalformat, width, height, 0, format, type, data);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texSrc, level);
+ var texDest = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texDest);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+ if (enabled) {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.copyTexImage2D(gl.TEXTURE_2D, level, destInternalformat, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "CopyTexImage2D should succeed.");
+ } else {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ gl.copyTexImage2D(gl.TEXTURE_2D, level, destInternalformat, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_FRAMEBUFFER_OPERATION], "CopyTexImage2D should fail.");
+ }
+
+ gl.deleteTexture(texDest);
+ gl.deleteTexture(texSrc);
+ gl.deleteFramebuffer(fbo);
+ });
+}
+
+description("This test verifies the functionality of the EXT_color_buffer_float extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ var texturedShaders = [
+ wtu.simpleTextureVertexShader,
+ "testFragmentShader"
+ ];
+ var testProgram =
+ wtu.setupProgram(gl,
+ texturedShaders,
+ ['vPosition', 'texCoord0'],
+ [0, 1]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+
+ // Ensure these formats can't be used for rendering if the extension is disabled
+ runFloatTextureRenderTargetTest(false, gl.R16F, gl.RED);
+ runFloatTextureRenderTargetTest(false, gl.RG16F, gl.RG);
+ runFloatTextureRenderTargetTest(false, gl.RGBA16F, gl.RGBA);
+ runFloatTextureRenderTargetTest(false, gl.R32F, gl.RED);
+ runFloatTextureRenderTargetTest(false, gl.RG32F, gl.RG);
+ runFloatTextureRenderTargetTest(false, gl.RGBA32F, gl.RGBA);
+ runFloatTextureRenderTargetTest(false, gl.R11F_G11F_B10F, gl.RGB);
+
+ runFloatRenderbufferRenderTargetTest(false, gl.R16F);
+ runFloatRenderbufferRenderTargetTest(false, gl.RG16F);
+ runFloatRenderbufferRenderTargetTest(false, gl.RGBA16F);
+ runFloatRenderbufferRenderTargetTest(false, gl.R32F);
+ runFloatRenderbufferRenderTargetTest(false, gl.RG32F);
+ runFloatRenderbufferRenderTargetTest(false, gl.RGBA32F);
+ runFloatRenderbufferRenderTargetTest(false, gl.R11F_G11F_B10F);
+
+ // Ensure RGB16F can't be used for rendering.
+ runRGB16FNegativeTest();
+
+ runCopyTexImageTest(false);
+
+ if (!gl.getExtension("EXT_color_buffer_float")) {
+ testPassed("No EXT_color_buffer_float support -- this is legal");
+ } else {
+ testPassed("Successfully enabled EXT_color_buffer_float extension");
+
+ runInternalFormatQueryTest();
+
+ runFloatTextureRenderTargetTest(true, gl.R16F, gl.RED, testProgram, 1, [1000, 1, 1, 1], 0);
+ runFloatTextureRenderTargetTest(true, gl.RG16F, gl.RG, testProgram, 2, [1000, 1000, 1, 1], 0);
+ runFloatTextureRenderTargetTest(true, gl.RGBA16F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 0);
+ runFloatTextureRenderTargetTest(true, gl.R32F, gl.RED, testProgram, 1, [1000, 1, 1, 1], 0);
+ runFloatTextureRenderTargetTest(true, gl.RG32F, gl.RG, testProgram, 2, [1000, 1000, 1, 1], 0);
+ runFloatTextureRenderTargetTest(true, gl.RGBA32F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 0);
+ runFloatTextureRenderTargetTest(true, gl.R11F_G11F_B10F, gl.RGB, testProgram, 3, [1000, 1000, 1000, 1], 0);
+ runFloatTextureRenderTargetTest(true, gl.RGBA32F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 1);
+ runFloatTextureRenderTargetTest(true, gl.RGBA32F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 0.5);
+
+ runFloatRenderbufferRenderTargetTest(true, gl.R16F, testProgram, 1, [1000, 1, 1, 1]);
+ runFloatRenderbufferRenderTargetTest(true, gl.RG16F, testProgram, 2, [1000, 1000, 1, 1]);
+ runFloatRenderbufferRenderTargetTest(true, gl.RGBA16F, testProgram, 4, [1000, 1000, 1000, 1000]);
+ runFloatRenderbufferRenderTargetTest(true, gl.R32F, testProgram, 1, [1000, 1, 1, 1]);
+ runFloatRenderbufferRenderTargetTest(true, gl.RG32F, testProgram, 2, [1000, 1000, 1, 1]);
+ runFloatRenderbufferRenderTargetTest(true, gl.RGBA32F, testProgram, 4, [1000, 1000, 1000, 1000]);
+ runFloatRenderbufferRenderTargetTest(true, gl.R11F_G11F_B10F, testProgram, 3, [1000, 1000, 1000, 1]);
+
+ // Ensure EXT_color_buffer_float does not enable RGB16F as color renderable.
+ runRGB16FNegativeTest();
+
+ runCopyTexImageTest(true);
+
+ runUniqueObjectTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-half-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-half-float.html
new file mode 100644
index 0000000000..4ced76e0fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-half-float.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 EXT_color_buffer_half_float Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head> 
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+var version = 2;
+</script>
+<script src="../../js/tests/ext-color-buffer-half-float.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-disjoint-timer-query-webgl2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-disjoint-timer-query-webgl2.html
new file mode 100644
index 0000000000..c051fa36a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-disjoint-timer-query-webgl2.html
@@ -0,0 +1,316 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 EXT_disjoint_timer_query_webgl2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_disjoint_timer_query_webgl2 extension, if it is available.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var ext = null;
+var query = null;
+var query2 = null;
+var elapsed_query = null;
+var timestamp_query1 = null;
+var timestamp_query2 = null;
+var availability_retry = 500;
+var timestamp_counter_bits = 0;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+} else {
+ testPassed("WebGL context exists");
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_disjoint_timer_query_webgl2");
+ if (!ext) {
+ testPassed("No EXT_disjoint_timer_query_webgl2 support -- this is legal");
+ finishTest();
+ } else {
+ runSanityTests();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // Clear disjoint value.
+ gl.getParameter(ext.GPU_DISJOINT_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ runElapsedTimeTest();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ timestamp_counter_bits = gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT);
+ if (timestamp_counter_bits > 0) {
+ runTimeStampTest();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+ verifyQueryResultsNotAvailable();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ window.requestAnimationFrame(checkQueryResults);
+ }
+}
+
+function runSanityTests() {
+ debug("");
+ debug("Testing other query types");
+ query = gl.createQuery();
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, query);
+ shouldBeTrue("gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY) !== null");
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "enabling EXT_disjoint_timer_query_webgl2 should not break other queries");
+
+ debug("");
+ debug("Testing timer query expectations");
+
+ shouldBe("ext.QUERY_COUNTER_BITS_EXT", "0x8864");
+ shouldBe("ext.TIME_ELAPSED_EXT", "0x88BF");
+ shouldBe("ext.TIMESTAMP_EXT", "0x8E28");
+ shouldBe("ext.GPU_DISJOINT_EXT", "0x8FBB");
+
+ shouldBe("gl.isQuery(null)", "false");
+
+ shouldBeTrue("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY) === null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeTrue("gl.getQuery(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ shouldBeTrue("gl.getQuery(ext.TIMESTAMP_EXT, gl.CURRENT_QUERY) === null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ // Certain drivers set timestamp counter bits to 0 as they don't support timestamps
+ shouldBeTrue("gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30 || " +
+ "gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) === 0");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing time elapsed query lifecycle");
+ query = gl.createQuery();
+ shouldBe("gl.isQuery(query)", "false");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query creation must succeed.");
+ gl.beginQuery(ext.TIMESTAMP_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Beginning a timestamp query should fail.");
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
+ shouldBe("gl.isQuery(query)", "true");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Beginning an inactive time elapsed query should succeed.");
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to begin an active query should fail.");
+ gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability of an active query should fail.");
+ gl.getQueryParameter(query, gl.QUERY_RESULT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result of an active query should fail.");
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
+ gl.endQuery(ext.TIME_ELAPSED_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Ending an active time elapsed query should succeed.");
+ gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Fetching query result availability after query end should succeed.");
+ gl.endQuery(ext.TIME_ELAPSED_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to end an inactive query should fail.");
+ ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should not be able to use time elapsed query to store a timestamp.");
+ gl.deleteQuery(query);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query deletion must succeed.");
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning a deleted query must fail.");
+ gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability after query deletion should fail.");
+ shouldBe("gl.isQuery(query)", "false");
+
+ debug("");
+ debug("Testing timestamp counter");
+ query = gl.createQuery();
+ shouldThrow("ext.queryCounterEXT(null, ext.TIMESTAMP_EXT)");
+ ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp counter queries should work.");
+ gl.deleteQuery(query);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Performing parameter sanity checks");
+ gl.getParameter(ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter timestamp calls should work.");
+ gl.getParameter(ext.GPU_DISJOINT_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter disjoint calls should work.");
+
+ debug("");
+ debug("Testing current query conditions");
+ query = gl.createQuery();
+ query2 = gl.createQuery();
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "null");
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing failed begin query should not change the current query.");
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning an elapsed query without ending should fail.");
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing beginning a timestamp query is invalid and should not change the elapsed query.");
+ gl.beginQuery(ext.TIMESTAMP_EXT, query2)
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing timestamp queries end immediately so are never current.");
+ ext.queryCounterEXT(query2, ext.TIMESTAMP_EXT);
+ shouldBe("gl.getQuery(ext.TIMESTAMP_EXT, gl.CURRENT_QUERY)", "null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing ending the query should clear the current query.");
+ gl.endQuery(ext.TIME_ELAPSED_EXT);
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Testing beginning a elapsed query using a timestamp query should fail and not affect current query.")
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching query targets should fail.");
+ shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.deleteQuery(query);
+ gl.deleteQuery(query2);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at end of sanity tests");
+}
+
+function runElapsedTimeTest() {
+ debug("");
+ debug("Testing elapsed time query");
+
+ elapsed_query = gl.createQuery();
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, elapsed_query);
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.endQuery(ext.TIME_ELAPSED_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Time elapsed query should have no errors");
+}
+
+function runTimeStampTest() {
+ debug("");
+ debug("Testing timestamp query");
+
+ timestamp_query1 = gl.createQuery();
+ timestamp_query2 = gl.createQuery();
+ ext.queryCounterEXT(timestamp_query1, ext.TIMESTAMP_EXT);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.queryCounterEXT(timestamp_query2, ext.TIMESTAMP_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp queries should have no errors");
+}
+
+function verifyQueryResultsNotAvailable() {
+ debug("");
+ debug("Verifying queries' results don't become available too early");
+
+ // Verify as best as possible that the implementation doesn't
+ // allow a query's result to become available the same frame, by
+ // spin-looping for some time and ensuring that none of the
+ // queries' results become available.
+ var startTime = Date.now();
+ while (Date.now() - startTime < 2000) {
+ gl.finish();
+ if (gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT_AVAILABLE)) {
+ testFailed("One of the queries' results became available too early");
+ return;
+ }
+ if (timestamp_counter_bits > 0) {
+ if (gl.getQueryParameter(timestamp_query1, gl.QUERY_RESULT_AVAILABLE) ||
+ gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT_AVAILABLE)) {
+ testFailed("One of the queries' results became available too early");
+ return;
+ }
+ }
+ }
+
+ testPassed("Queries' results didn't become available in a spin loop");
+}
+
+function checkQueryResults() {
+ if (availability_retry > 0) {
+ // Make a reasonable attempt to wait for the queries' results to become available.
+ if (!gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT_AVAILABLE) ||
+ (timestamp_counter_bits > 0 && !gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT_AVAILABLE))) {
+ var error = gl.getError();
+ if (error != gl.NO_ERROR) {
+ testFailed("getQueryParameter should have no errors: " + wtu.glEnumToString(gl, error));
+ debug("");
+ finishTest();
+ return;
+ }
+ availability_retry--;
+ window.requestAnimationFrame(checkQueryResults);
+ return;
+ }
+ }
+
+ debug("");
+ debug("Testing query results");
+
+ // Make sure queries are available.
+ shouldBe("gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT_AVAILABLE)", "true");
+ if (timestamp_counter_bits > 0) {
+ shouldBe("gl.getQueryParameter(timestamp_query1, gl.QUERY_RESULT_AVAILABLE)", "true");
+ shouldBe("gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT_AVAILABLE)", "true");
+ }
+
+ var disjoint_value = gl.getParameter(ext.GPU_DISJOINT_EXT);
+ if (disjoint_value) {
+ // Cannot validate results make sense, but this is okay.
+ testPassed("Disjoint triggered.");
+ } else {
+ var elapsed_result = gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT);
+ if (timestamp_counter_bits > 0) {
+ var timestamp_result1 = gl.getQueryParameter(timestamp_query1, gl.QUERY_RESULT);
+ var timestamp_result2 = gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT);
+ }
+ // Do some basic validity checking of the elapsed time query. There's no way it should
+ // take more than about half a second for a no-op query.
+ var halfSecondInNanos = 0.5 * 1000 * 1000 * 1000;
+ if (elapsed_result < 0 || elapsed_result > halfSecondInNanos) {
+ testFailed("Time elapsed query returned invalid data: " + elapsed_result);
+ } else {
+ testPassed("Time elapsed query results were valid.");
+ }
+
+ if (timestamp_counter_bits > 0) {
+ if (timestamp_result1 <= 0 ||
+ timestamp_result2 <= 0 ||
+ timestamp_result2 <= timestamp_result1) {
+ testFailed("Timestamp queries returned invalid data: timestamp_result1 = " +
+ timestamp_result1 + ", timestamp_result2 = " + timestamp_result2);
+ } else {
+ testPassed("Timestamp query results were valid.");
+ }
+ }
+ }
+
+ debug("");
+ finishTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-filter-anisotropic.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-filter-anisotropic.html
new file mode 100644
index 0000000000..c75a8e0cae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-filter-anisotropic.html
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2.0 EXT_texture_filter_anisotropic Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/ext-texture-filter-anisotropic.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-norm16.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-norm16.html
new file mode 100644
index 0000000000..add9fc038d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-texture-norm16.html
@@ -0,0 +1,253 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_texture_norm16 Conformance Tests</title>
+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the EXT_texture_norm16 extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(null, null, 2);
+var ext;
+
+var formats = null;
+var textures;
+var fbos;
+var renderbuffer;
+var readbackBuf = new Uint16Array(4);
+
+function generateFormatColor(format, value, alpha) {
+ alpha = alpha !== undefined ? alpha : 255;
+ switch(format) {
+ case gl.RED:
+ return [value, 0, 0, alpha];
+ case gl.RG:
+ return [value, value, 0, alpha];
+ case gl.RGB:
+ return [value, value, value, alpha];
+ case gl.RGBA:
+ return [value, value, value, value];
+ default:
+ wtu.error("Unreachable: Unknown format.");
+ return null;
+ }
+}
+
+function testNorm16Texture(internalFormat, format, type, error="NO_ERROR") {
+ debug(`\ntestNorm16Texture(${[].slice.call(arguments).join(", ")})`);
+ let pixelValue;
+ let expectedValue;
+ let imageData;
+
+ switch(gl[type]) {
+ case gl.SHORT:
+ pixelValue = 0x7fff;
+ expectedValue = 0xff;
+ imageData = new Int16Array(4).fill(pixelValue);
+ break;
+ case gl.UNSIGNED_SHORT:
+ pixelValue = 0x6a35;
+ expectedValue = pixelValue >> 8;
+ imageData = new Uint16Array(4).fill(pixelValue);
+ break;
+ default:
+ wtu.error("Unreachable: Unknown texture type.");
+ break;
+ }
+
+ // Texture sampled from
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, textures[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext[internalFormat] || gl[internalFormat],
+ 1, 1, 0, gl[format], gl[type], imageData);
+
+ wtu.glErrorShouldBe(gl, gl[error], `texImage should generate error:${error}`);
+ if (gl[error]) return;
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ // Read back as gl.UNSIGNED_BYTE
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, generateFormatColor(gl[format], expectedValue));
+}
+
+function testNorm16Render(interalFormat, format, type, tolerance) {
+ // Only UNSIGNED_SHORT are renderable
+ let pixelValue = 0x6a35;
+ let expectedValue = pixelValue;
+ let imageData = new Uint16Array(4).fill(pixelValue);
+
+ // Render to fbo texture attachment test
+ gl.bindTexture(gl.TEXTURE_2D, textures[1]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, interalFormat, 1, 1, 0, format, type, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rtt bindings succeed");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbos[0]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[1], 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fbo bindings succeed");
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, textures[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, interalFormat, 1, 1, 0, format, type, imageData);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture bindings succeed");
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, generateFormatColor(format, expectedValue, 0xffff), undefined, tolerance, readbackBuf, type);
+
+ // Renderbuffer test
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbos[1]);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, interalFormat, 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER,
+ renderbuffer);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "renderbuffer bindings succeed");
+
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, generateFormatColor(format, 0xffff, 0xffff), undefined, tolerance, readbackBuf, type);
+
+ // Copy from renderbuffer to textures[1] test
+ gl.bindTexture(gl.TEXTURE_2D, textures[1]);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copy succeed");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbos[0]);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, generateFormatColor(format, 0xffff, 0xffff), undefined, tolerance, readbackBuf, type);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+}
+
+function testExtFormatUnrenderable(internalFormatName, format, type) {
+ gl.bindTexture(gl.TEXTURE_2D, textures[1]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext[internalFormatName], 1, 1, 0, format, type, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture definition succeeded");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbos[0]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[1], 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fbo binding succeeded");
+
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, gl.FRAMEBUFFER_UNSUPPORTED ],
+ `framebuffer should not be complete with ${internalFormatName} texture attached`);
+}
+
+function runInternalFormatQueryTest()
+{
+ debug("");
+ debug("testing the internal format query");
+
+ var maxSamples = gl.getParameter(gl.MAX_SAMPLES);
+ const formats = [ext.R16_EXT, ext.RG16_EXT, ext.RGBA16_EXT];
+ for (const format of formats) {
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, format, gl.SAMPLES);
+ if (samples == null || samples.length == 0 || samples[0] < maxSamples) {
+ testFailed("the maximum value in SAMPLES should be at least " + maxSamples);
+ return;
+ }
+ }
+ testPassed("Internal format query succeeded");
+}
+
+function runTestExtension() {
+ textures = [gl.createTexture(), gl.createTexture()];
+ fbos = [gl.createFramebuffer(), gl.createFramebuffer()];
+ renderbuffer = gl.createRenderbuffer();
+
+ for (let i = 0; i < 2; i++) {
+ gl.bindTexture(gl.TEXTURE_2D, textures[i]);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture and framebuffer setup succeed");
+
+ let program300 = wtu.setupSimpleTextureProgramESSL300(gl);
+ let program100 = wtu.setupTexturedQuad(gl, 0, 1, wtu.simpleHighPrecisionTextureFragmentShader);
+
+ debug("");
+ debug("Texture creation");
+ testNorm16Texture("R16_EXT", "RED", "UNSIGNED_SHORT");
+ testNorm16Texture("RG16_EXT", "RG", "UNSIGNED_SHORT");
+ testNorm16Texture("RGB16_EXT", "RGB", "UNSIGNED_SHORT");
+ testNorm16Texture("RGBA16_EXT", "RGBA", "UNSIGNED_SHORT");
+ testNorm16Texture("R16_SNORM_EXT", "RED", "SHORT");
+ testNorm16Texture("RG16_SNORM_EXT", "RG", "SHORT");
+ testNorm16Texture("RGB16_SNORM_EXT", "RGB", "SHORT");
+ testNorm16Texture("RGBA16_SNORM_EXT", "RGBA", "SHORT");
+
+ testNorm16Texture("RGBA", "RGBA", "UNSIGNED_SHORT", "INVALID_OPERATION");
+ testNorm16Texture("RGBA", "RGBA", "SHORT", "INVALID_OPERATION");
+
+ debug("");
+ debug("Texture renderability");
+
+ testNorm16Render(ext.R16_EXT, gl.RED, gl.UNSIGNED_SHORT, 8);
+ testNorm16Render(ext.RG16_EXT, gl.RG, gl.UNSIGNED_SHORT, 8);
+ testNorm16Render(ext.RGBA16_EXT, gl.RGBA, gl.UNSIGNED_SHORT, 8);
+
+ gl.useProgram(program300);
+
+ testNorm16Render(ext.R16_EXT, gl.RED, gl.UNSIGNED_SHORT, 0);
+ testNorm16Render(ext.RG16_EXT, gl.RG, gl.UNSIGNED_SHORT, 0);
+ testExtFormatUnrenderable("RGB16_EXT", gl.RGB, gl.UNSIGNED_SHORT);
+ testNorm16Render(ext.RGBA16_EXT, gl.RGBA, gl.UNSIGNED_SHORT, 0);
+
+ testExtFormatUnrenderable("R16_SNORM_EXT", gl.RED, gl.SHORT);
+ testExtFormatUnrenderable("RG16_SNORM_EXT", gl.RG, gl.SHORT);
+ testExtFormatUnrenderable("RGB16_SNORM_EXT", gl.RGB, gl.SHORT);
+ testExtFormatUnrenderable("RGBA16_SNORM_EXT", gl.RGBA, gl.SHORT);
+};
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ ext = gl.getExtension("EXT_texture_norm16");
+
+ wtu.runExtensionSupportedTest(gl, "EXT_texture_norm16", ext !== null);
+
+ if (ext !== null) {
+ runInternalFormatQueryTest();
+ runTestExtension();
+ } else {
+ testPassed("No EXT_texture_norm16 support -- this is legal");
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/oes-draw-buffers-indexed.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/oes-draw-buffers-indexed.html
new file mode 100644
index 0000000000..700bb053c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/oes-draw-buffers-indexed.html
@@ -0,0 +1,573 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OES_draw_buffers_indexed Conformance Tests</title>
+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the OES_draw_buffers_indexed extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", null, 2);
+var ext;
+
+const vs = `#version 300 es
+layout(location=0) in vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+`;
+
+const fs = `#version 300 es
+precision lowp float;
+layout(location = 0) out vec4 o_color0;
+layout(location = 1) out vec4 o_color1;
+void main()
+{
+ o_color0 = vec4(1, 0, 0, 0);
+ o_color1 = vec4(1, 0, 0, 0);
+}
+`;
+
+function setup() {
+ const program = wtu.setupProgram(gl, [vs, fs]);
+ gl.useProgram(program);
+ wtu.setupUnitQuad(gl, 0);
+ wtu.glErrorShouldBe(gl, 0, 'No errors from program');
+
+ const tex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, 0, 'Create texture 1 successfully');
+
+ const tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, 0, 'Create texture 2 successfully');
+
+ const attachments = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1];
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, tex1, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, tex2, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.drawBuffers(attachments);
+ wtu.glErrorShouldBe(gl, 0, 'Set draw buffers without errors');
+}
+
+function enableDisableTest() {
+ debug("Testing enableiOES/disableiOES");
+
+ // Invalid input
+ ext.enableiOES(gl.DEPTH_TEST, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND');
+
+ ext.disableiOES(gl.DEPTH_TEST, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND');
+
+ gl.disable(gl.BLEND);
+
+ // Valid input
+ ext.enableiOES(gl.BLEND, 0);
+ shouldBe('gl.isEnabled(gl.BLEND)', 'true');
+ ext.disableiOES(gl.BLEND, 0);
+ ext.enableiOES(gl.BLEND, 1);
+ shouldBe('gl.isEnabled(gl.BLEND)', 'false');
+ gl.enable(gl.BLEND);
+ shouldBe('gl.isEnabled(gl.BLEND)', 'true');
+ wtu.glErrorShouldBe(gl, 0, 'No errors from enable and disable draw buffers blend state');
+}
+
+function constantAlphaBlendColorValidationTest() {
+ debug("Testing CONSTANT_COLOR/ALPHA blend functions limit validation");
+ function isConstantColorAndAlphaBlendFunctions(first, second)
+ {
+ return (first == gl.CONSTANT_COLOR || first == gl.ONE_MINUS_CONSTANT_COLOR) &&
+ (second == gl.CONSTANT_ALPHA || second == gl.ONE_MINUS_CONSTANT_ALPHA);
+ }
+
+ function checkBlendFunctions(src, dst)
+ {
+ if (isConstantColorAndAlphaBlendFunctions(src, dst) ||
+ isConstantColorAndAlphaBlendFunctions(dst, src))
+ {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'invalid combinations');
+ return false;
+ }
+ else
+ {
+ wtu.glErrorShouldBe(gl, 0, 'No error');
+ return true;
+ }
+ }
+
+ const srcFunc = [
+ gl.ZERO,
+ gl.ONE,
+ gl.SRC_COLOR,
+ gl.ONE_MINUS_SRC_COLOR,
+ gl.DST_COLOR,
+ gl.ONE_MINUS_DST_COLOR,
+ gl.SRC_ALPHA,
+ gl.ONE_MINUS_SRC_ALPHA,
+ gl.DST_ALPHA,
+ gl.ONE_MINUS_DST_ALPHA,
+ gl.CONSTANT_COLOR,
+ gl.ONE_MINUS_CONSTANT_COLOR,
+ gl.CONSTANT_ALPHA,
+ gl.ONE_MINUS_CONSTANT_ALPHA,
+ gl.SRC_ALPHA_SATURATE,
+ ];
+
+ const dstFunc = [
+ gl.ZERO, gl.ONE,
+ gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR,
+ gl.DST_COLOR, gl.ONE_MINUS_DST_COLOR,
+ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,
+ gl.DST_ALPHA, gl.ONE_MINUS_DST_ALPHA,
+ gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_COLOR,
+ gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_ALPHA,
+ ];
+
+ let src, dst;
+
+ // CONSTANT_COLOR/ALPHA invalid combination check
+ for (let i = 0, leni = srcFunc.length; i < leni; i++)
+ {
+ src = srcFunc[i];
+ for (let j = 0, lenj = dstFunc.length; j < lenj; j++)
+ {
+ dst = dstFunc[j];
+ ext.blendFunciOES(0, src, dst);
+ checkBlendFunctions(src, dst);
+ ext.blendFuncSeparateiOES(0, src, dst, gl.ONE, gl.ONE);
+ checkBlendFunctions(src, dst);
+ }
+ }
+}
+
+function indexedBlendColorTest() {
+ debug('');
+ debug("Testing blendEquationiOES and blendFunciOES");
+ wtu.glErrorShouldBe(gl, 0, 'top of indexedBlendColorTest');
+
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ ext.blendEquationiOES(0, gl.FUNC_ADD);
+ ext.blendFunciOES(0, gl.ONE, gl.ONE);
+ ext.blendEquationiOES(1, gl.FUNC_ADD);
+ ext.blendFunciOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 255]);
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]);
+
+ debug("Testing blendEquationSeparateiOES and blendFuncSeparateiOES");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ ext.blendEquationSeparateiOES(0, gl.FUNC_ADD, gl.FUNC_SUBTRACT);
+ ext.blendFuncSeparateiOES(0, gl.ONE, gl.ONE, gl.ZERO, gl.ZERO);
+ ext.blendEquationSeparateiOES(1, gl.FUNC_ADD, gl.FUNC_SUBTRACT);
+ ext.blendFuncSeparateiOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ZERO);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 0]);
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]);
+
+ debug("Testing colorMaskiOES");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ ext.colorMaskiOES(0, false, false, false, false);
+ ext.colorMaskiOES(1, true, true, true, true);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]);
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]);
+
+ debug('');
+ debug(`Testing that new tokens aren't on the extension.`);
+ shouldBe('ext.BLEND_EQUATION_RGB', 'undefined');
+ shouldBe('ext.BLEND_EQUATION_ALPHA', 'undefined');
+ shouldBe('ext.BLEND_SRC_RGB', 'undefined');
+ shouldBe('ext.BLEND_SRC_ALPHA', 'undefined');
+ shouldBe('ext.BLEND_DST_RGB', 'undefined');
+ shouldBe('ext.BLEND_DST_ALPHA', 'undefined');
+ shouldBe('ext.COLOR_WRITEMASK', 'undefined');
+
+ debug("Testing new tokens for getIndexedParameterTest");
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_ADD');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_SUBTRACT');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.ONE');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ZERO');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ZERO');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_ADD');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_SUBTRACT');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.SRC_ALPHA');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.ONE_MINUS_SRC_ALPHA');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ZERO');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ZERO');
+
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[false, false, false, false]');
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, true, true, true]');
+
+ debug("Testing non-indexed getParamter get state from draw buffer 0");
+ shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE');
+ shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.ONE');
+ shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ZERO');
+ shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ZERO');
+ shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_ADD');
+ shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_SUBTRACT');
+ shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[false, false, false, false]');
+
+ debug("Testing non-indexed calls modify all draw buffers state");
+ gl.blendEquationSeparate(gl.FUNC_SUBTRACT, gl.FUNC_ADD);
+ gl.blendFuncSeparate(gl.ONE_MINUS_DST_ALPHA, gl.DST_ALPHA, gl.ONE, gl.ONE);
+ gl.colorMask(true, false, true, false);
+ wtu.glErrorShouldBe(gl, 0, 'Non-indexed state set without errors');
+
+ shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_SUBTRACT');
+ shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_ADD');
+ shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE_MINUS_DST_ALPHA');
+ shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.DST_ALPHA');
+ shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ONE');
+ shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ONE');
+ shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[true, false, true, false]');
+
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_SUBTRACT');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_ADD');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE_MINUS_DST_ALPHA');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.DST_ALPHA');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ONE');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ONE');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_SUBTRACT');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_ADD');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.ONE_MINUS_DST_ALPHA');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.DST_ALPHA');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ONE');
+ shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ONE');
+
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, true, false]');
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, false, true, false]');
+}
+
+function runTestExtension() {
+ setup();
+
+ testInvalidValues();
+
+ enableDisableTest();
+
+ // blending should be enabled for drawBuffers 0 and 1 at this point
+
+ constantAlphaBlendColorValidationTest();
+
+ indexedBlendColorTest();
+
+ testColorMaskDrawNoOp();
+
+ testColorMaskAfterComposite();
+}
+
+function runInvalidEnumsTest() {
+ debug("Testing new enums for getIndexedParameterTest being invalid before requesting the extension");
+ shouldBeNull("gl.getIndexedParameter(0x8009, 0)"); // BLEND_EQUATION_RGB
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_RGB');
+ shouldBeNull("gl.getIndexedParameter(0x883D, 0)"); // BLEND_EQUATION_ALPHA
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_ALPHA');
+ shouldBeNull("gl.getIndexedParameter(0x80C9, 0)"); // BLEND_SRC_RGB
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_RGB');
+ shouldBeNull("gl.getIndexedParameter(0x80CB, 0)"); // BLEND_SRC_ALPHA
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_ALPHA');
+ shouldBeNull("gl.getIndexedParameter(0x80C8, 0)"); // BLEND_DST_RGB
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_RGB');
+ shouldBeNull("gl.getIndexedParameter(0x80CA, 0)"); // BLEND_DST_ALPHA
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_ALPHA');
+ shouldBeNull("gl.getIndexedParameter(0x0C23, 0)"); // COLOR_WRITEMASK
+ wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], 'invalid operations or invalid enums for COLOR_WRITEMASK');
+}
+
+function testInvalidValues() {
+ const numDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
+ if (!numDrawBuffers) throw new Error('!numDrawBuffers');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, -1)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, ${numDrawBuffers})`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.enableiOES(gl.BLEND, ${numDrawBuffers-1})`);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, -1)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, ${numDrawBuffers})`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.disableiOES(gl.BLEND, ${numDrawBuffers-1})`);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(-1, gl.FUNC_ADD)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(${numDrawBuffers}, gl.FUNC_ADD)`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationiOES(${numDrawBuffers-1}, gl.FUNC_ADD)`);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(-1, gl.FUNC_ADD, gl.FUNC_ADD)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(${numDrawBuffers}, gl.FUNC_ADD, gl.FUNC_ADD)`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationSeparateiOES(${numDrawBuffers-1}, gl.FUNC_ADD, gl.FUNC_ADD)`);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(-1, gl.ONE, gl.ONE)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(${numDrawBuffers}, gl.ONE, gl.ONE)`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.blendFunciOES(${numDrawBuffers-1}, gl.ONE, gl.ONE)`);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(-1, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(${numDrawBuffers}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.blendFuncSeparateiOES(${numDrawBuffers-1}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(-1, 1,1,1,1)`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(${numDrawBuffers}, 1,1,1,1)`);
+ wtu.shouldGenerateGLError(gl, 0, `ext.colorMaskiOES(${numDrawBuffers-1}, 1,1,1,1)`);
+}
+
+function* range(n) {
+ for (let i = 0; i < n; i++) {
+ yield i;
+ }
+}
+
+function testColorMaskDrawNoOp() {
+ debug('');
+ debug('testColorMaskDrawNoOp')
+ // > If any draw buffer with an attachment does not have a defined
+ // fragment shader output, draws generate INVALID_OPERATION,
+ // unless all 4 channels of colorMask are set to false.
+ const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ shouldBeTrue(`${NUM_OUTPUTS} > 1`);
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.viewport(0,0,1,1);
+
+ const DRAW_BUFFERS = [];
+ for (const i of range(NUM_OUTPUTS)) {
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1, 1);
+ const ca = gl.COLOR_ATTACHMENT0+i;
+ DRAW_BUFFERS.push(ca)
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, ca,
+ gl.TEXTURE_2D, tex, 0);
+ }
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.drawBuffers(DRAW_BUFFERS);
+ gl.colorMask(1, 1, 1, 1);
+ gl.disable(gl.BLEND);
+
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ for (const i of range(NUM_OUTPUTS)) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0], `COLOR_ATTACHMENT${i} initially black`);
+ }
+
+ for (const validOutput of range(NUM_OUTPUTS)) {
+ const invalidOutput = validOutput ^ 0b11;
+ debug(`validOutput: ${validOutput}, invalidOutput: ${invalidOutput}`);
+ const prog = wtu.setupProgram(gl, [
+ `\
+#version 300 es
+void main() {
+ gl_Position = vec4(0,0,0,1);
+ gl_PointSize = 1.0f;
+}
+`,
+ `\
+#version 300 es
+precision mediump float;
+layout(location=${validOutput}) out vec4 o_color;
+void main() {
+ o_color = vec4(1,1,1,1);
+}
+`
+ ]);
+ gl.useProgram(prog);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ 'After init.');
+
+ gl.colorMask(1,1,1,1);
+ gl.drawBuffers(DRAW_BUFFERS);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ 'Drawing with unmasked undefined color outputs.');
+
+ gl.colorMask(0,0,0,0);
+ gl.drawBuffers(DRAW_BUFFERS);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ 'Drawing with colorMask-masked-out undefined color outputs.');
+
+ gl.colorMask(1,1,1,1);
+ gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == invalidOutput) ? x : 0));
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ 'Drawing with wrong-id drawBuffer-masked-out undefined color outputs.');
+
+ gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0));
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ 'Drawing with drawBuffer-masked-out undefined color outputs.');
+
+ gl.colorMask(0,0,0,0);
+ gl.drawBuffers([]);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ 'Drawing with colorMask+drawBuffer-masked-out undefined color outputs.');
+
+ const testMask = (r,g,b,a) => {
+ debug(`testMask(${[r,g,b,a]})`);
+ gl.drawBuffers(DRAW_BUFFERS);
+
+ gl.colorMask(1,1,1,1);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.colorMask(0,0,0,0);
+ ext.colorMaskiOES(validOutput, r,g,b,a);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ `Drawing with sole defined color${validOutput} output writemask: ${[r,g,b,a]}.`);
+
+ for (const i of range(NUM_OUTPUTS)) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
+ let expect = [0,0,0,0];
+ if (i == validOutput) {
+ expect = [r,g,b,a].map(x => 0xff*x);
+ }
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`);
+ }
+
+ gl.colorMask(1,1,1,1);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.colorMask(r,g,b,a);
+ for (const i of range(NUM_OUTPUTS)) {
+ if (i == validOutput) continue;
+ ext.colorMaskiOES(i, 0,0,0,0);
+ }
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ `Drawing with sole remaining defined color${validOutput} output writemask: ${[r,g,b,a]}.`);
+
+ for (const i of range(NUM_OUTPUTS)) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
+ let expect = [0,0,0,0];
+ if (i == validOutput) {
+ expect = [r,g,b,a].map(x => 0xff*x);
+ }
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`);
+ }
+
+ if (r || g || b || a) {
+ gl.colorMask(0,0,0,0);
+ ext.colorMaskiOES(invalidOutput, r,g,b,a);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ `Drawing with wrong-id undefined color output color masked: ${[r,g,b,a]}.`);
+
+ gl.drawBuffers([]);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ 'Drawing with wrong-id colorMask, but all-off drawBuffers.');
+
+ gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0));
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ 'Drawing with wrong-id colorMask, but right-id drawBuffers masked.');
+ }
+ };
+
+ testMask(0,0,0,0);
+ testMask(1,0,0,0);
+ testMask(0,1,0,0);
+ testMask(0,0,1,0);
+ testMask(0,0,0,1);
+ testMask(1,1,1,1);
+ }
+}
+
+function testColorMaskAfterComposite() {
+ debug('');
+ debug('testColorMaskAfterComposite')
+
+ const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ shouldBeTrue(`${NUM_OUTPUTS} > 2`);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.colorMask(0, 0, 1, 0);
+ ext.colorMaskiOES(0, 1, 0, 0, 0);
+ ext.colorMaskiOES(1, 0, 1, 0, 0);
+
+ function check() {
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, false, false]');
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[false, true, false, false]');
+ shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 2)', '[false, false, true, false]');
+ finishTest();
+ }
+
+ wtu.waitForComposite(check);
+}
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ runInvalidEnumsTest();
+
+ ext = gl.getExtension("OES_draw_buffers_indexed");
+
+ wtu.runExtensionSupportedTest(gl, "OES_draw_buffers_indexed", ext !== null);
+
+ if (ext !== null) {
+ runTestExtension();
+ } else {
+ testPassed("No OES_draw_buffers_indexed support -- this is legal");
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html
new file mode 100644
index 0000000000..ba74d1398b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html
@@ -0,0 +1,524 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+<script id="requireDefine_GL_OVR_multiview2" type="x-shader/x-fragment">#version 300 es
+#ifndef GL_OVR_multiview2
+ #error no GL_OVR_multiview2
+#endif
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="forbidDefine_GL_OVR_multiview" type="x-shader/x-fragment">#version 300 es
+#ifdef GL_OVR_multiview
+ #error legacy GL_OVR_multiview support must be forbidden
+#endif
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="legacyMultiview1Shader" type="x-shader/x-fragment">#version 300 es
+#extension GL_OVR_multiview: require
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runExtensionDisabledTest()
+{
+ debug("");
+ debug("Testing queries with extension disabled");
+
+ let maxViews = gl.getParameter(0x9631);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query MAX_VIEWS_OVR without enabling OVR_multiview2");
+
+ let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9630);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR without enabling OVR_multiview2");
+ let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9632);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling OVR_multiview2");
+}
+
+function runQueryTest()
+{
+ debug("");
+ debug("Testing querying MAX_VIEWS_OVR");
+
+ let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from querying MAX_VIEWS_OVR");
+ if (typeof maxViews != 'number') {
+ testFailed("Type of the value of MAX_VIEWS_OVR should be number, was " + (typeof maxViews));
+ }
+ if (maxViews < 2) {
+ testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews);
+ }
+}
+
+function runDefaultFramebufferQueryTest()
+{
+ debug("");
+ debug("Testing querying base view index and num views on the default framebuffer");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ // Same behavior as FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR is INVALID_ENUM for default framebuffer");
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR is INVALID_ENUM for default framebuffer");
+}
+
+function runInvalidTextureTypeTest()
+{
+ debug("");
+ debug("Testing invalid texture types");
+ let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 2D texture");
+
+ let texCube = createTextureWithNearestFiltering(gl.TEXTURE_CUBE_MAP);
+ gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 128, 128);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a cube map texture");
+
+ let tex3D = createTextureWithNearestFiltering(gl.TEXTURE_3D);
+ gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 128, 128, 2);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 3D texture");
+}
+
+/**
+ * If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations.
+ */
+function runFramebufferQueryTest(allocateStorage)
+{
+ debug("");
+ debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage ? "allocated" : "not allocated") + ".");
+
+ let checkQueryResult = function(actual, expected, name) {
+ if (actual != expected) {
+ testFailed('Unexpected ' + name + ': ' + actual + ' when it was set to ' + expected);
+ } else {
+ testPassed(name + ' was ' + actual + ' when queried from the framebuffer');
+ }
+ }
+
+ let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) {
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, levelSet, baseViewIndexSet, numViewsSet);
+ let objectType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ if (objectType != gl.TEXTURE) {
+ testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ', should be TEXTURE');
+ } else {
+ testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE');
+ }
+
+ let level = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
+ checkQueryResult(level, levelSet, "level");
+
+ let textureName = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ checkQueryResult(textureName, colorTex, "texture object");
+
+ let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
+ checkQueryResult(baseViewIndex, baseViewIndexSet, "baseViewIndex");
+
+ let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
+ checkQueryResult(numViews, numViewsSet, "numViews");
+
+ let layer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
+ checkQueryResult(layer, baseViewIndexSet, "texture layer (should match baseViewIndex)");
+ }
+
+ let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) {
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews);
+ let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != expectedStatus) {
+ testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus) + ' - ' + msg);
+ } else {
+ testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value - ' + msg);
+ }
+ }
+
+ let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying baseViewIndex from a nonexistent attachment");
+ if (baseViewIndex != null) {
+ testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on a framebuffer without attachments');
+ } else {
+ testPassed('Querying baseViewIndex returned null on a framebuffer without attachments');
+ }
+ let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying numViews from a nonexistent attachment");
+ if (numViews != null) {
+ testFailed('Unexpected numViews ' + numViews + ' on a framebuffer without attachments');
+ } else {
+ testPassed('Querying numViews returned null on a framebuffer without attachments');
+ }
+
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ if (allocateStorage) {
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 2, gl.RGBA8, 128, 128, maxViews);
+ }
+ setupAndQuery(colorTex, 0, 0, maxViews);
+ setupAndQuery(colorTex, 1, 0, 2);
+ setupAndQuery(colorTex, 0, 1, maxViews - 1);
+
+ // Test matching and mismatching attachments for framebuffer status.
+ let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ if (allocateStorage) {
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 128, 128, maxViews);
+ }
+ setupSecondAttachmentAndQueryStatus(colorTex2, 1, maxViews - 1, allocateStorage ? gl.FRAMEBUFFER_COMPLETE : gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 'matching baseViewIndex and numViews on different attachments');
+ if (allocateStorage) {
+ setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'baseViewIndex mismatch');
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
+ setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch');
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries");
+}
+
+function runInvalidViewsTest()
+{
+ debug("");
+ debug("Testing invalid out-of-range values for baseViewIndex and numViews");
+
+ let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
+ let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ // Don't allocate storage since it's not needed for the validation.
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views");
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views");
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified negative baseViewIndex");
+
+ let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews);
+ // baseViewIndex + numViews = (maxLayers - maxViews + 1) + maxViews = maxLayers + 1
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified so many views that baseViewIndex + numViews is greater than MAX_ARRAY_TEXTURE_LAYERS");
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex + numViews is exactly MAX_ARRAY_TEXTURE_LAYERS");
+}
+
+function runDetachTest()
+{
+ debug("");
+ debug("Testing detaching multiview attachments");
+
+ let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
+ let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex and numViews are not validated when detaching");
+ let objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ if (objectType != gl.NONE) {
+ testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
+ } else {
+ testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
+ }
+
+ ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Can detach with framebufferTexture2D as well.");
+ objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ if (objectType != gl.NONE) {
+ testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
+ } else {
+ testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
+ }
+}
+
+function runShaderCompileTest(extensionEnabled)
+{
+ debug("");
+ debug("Testing shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
+
+ let prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "requireDefine_GL_OVR_multiview2"], undefined, undefined, true);
+ expectTrue(!extensionEnabled == !prog,
+ "GL_OVR_multiview2 must be defined by the preprocessor iff OVR_multiview2 is enabled by getExtension.");
+ if (extensionEnabled) {
+ prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "forbidDefine_GL_OVR_multiview"], undefined, undefined, true);
+ expectTrue(prog, "GL_OVR_multiview must never be defined by the preprocessor.");
+
+ prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "legacyMultiview1Shader"], undefined, undefined, true);
+ expectTrue(!prog, "#extension GL_OVR_multiview must be forbidden.");
+ }
+
+ if (!extensionEnabled) {
+ let multiviewShaders = [
+ getMultiviewPassthroughVertexShader(2),
+ getMultiviewColorFragmentShader()
+ ];
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (testProgram) {
+ testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail.");
+ } else {
+ testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled.");
+ }
+ }
+}
+
+function runClearTest()
+{
+ debug("");
+ debug("Testing that calling clear() clears all views");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+
+ gl.clearColor(0, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = [0, 255, 255, 255];
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be cyan');
+ }
+}
+
+function runFragmentShaderRenderTest()
+{
+ debug("");
+ debug("Testing rendering with different colors in fragment shader");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewPassthroughVertexShader(views),
+ getMultiviewColorFragmentShader()
+ ];
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
+ }
+}
+
+function runVertexShaderRenderTest()
+{
+ debug("");
+ debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewOffsetVertexShader(views),
+ getMultiviewColorFragmentShader()
+ ];
+
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+
+ checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
+ }
+}
+
+function runRealisticUseCaseRenderTest()
+{
+ debug("");
+ debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewRealisticUseCaseVertexShader(views),
+ getMultiviewColorFragmentShader()
+ ];
+
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+
+ let transformLocation = gl.getUniformLocation(testProgram, 'transform');
+ let transformData = new Float32Array (views * 16);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ let scaleX = 1.0 / views;
+ // offsetX is the position of the left edge of the quad we want to get in normalized device coordinates
+ let offsetX = viewIndex / views * 2.0 - 1.0;
+
+ setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX);
+ }
+ gl.uniformMatrix4fv(transformLocation, false, transformData);
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+
+ checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
+ }
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ gl.getExtension("OVR_multiview2").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("OVR_multiview2").myProperty', '2');
+}
+
+description("This test verifies the functionality of the OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runExtensionDisabledTest();
+
+ runShaderCompileTest(false);
+
+ debug("");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ runShaderCompileTest(true);
+
+ runQueryTest();
+
+ runDefaultFramebufferQueryTest();
+
+ runInvalidTextureTypeTest();
+
+ runFramebufferQueryTest(true);
+ runFramebufferQueryTest(false);
+
+ runInvalidViewsTest();
+
+ runDetachTest();
+
+ runClearTest();
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runFragmentShaderRenderTest();
+ runVertexShaderRenderTest();
+ runRealisticUseCaseRenderTest();
+ runUniqueObjectTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_depth.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_depth.html
new file mode 100644
index 0000000000..9ea071f25c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_depth.html
@@ -0,0 +1,138 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+<script id="macroFragmentShader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+#ifdef GL_OVR_multiview2
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+#else
+ // Error expected
+ #error no GL_OVR_multiview2;
+#endif
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runDepthRenderTest()
+{
+ debug("");
+ debug("Testing rendering with a depth texture array and depth test on");
+
+ let width = 64;
+ let height = 64;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewPassthroughVertexShader(views),
+ getMultiviewColorFragmentShader()
+ ];
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ let depthTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.DEPTH32F_STENCIL8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, depthTex, 0, 0, views);
+
+ let expectedStatus = gl.FRAMEBUFFER_COMPLETE;
+ let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != expectedStatus) {
+ testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus));
+ } else {
+ testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value');
+ }
+
+ // Draw so that the depth test succeeds for all pixels.
+ gl.viewport(0, 0, width, height);
+ gl.enable(gl.DEPTH_TEST);
+ gl.clearDepth(1.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when depth test succeeds");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
+ }
+
+ // Draw so that the depth test fails for all pixels.
+ gl.clearDepth(0.0);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when depth test fails");
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = [0, 0, 0, 0];
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
+ }
+}
+
+description("This test verifies drawing to depth buffers with the OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ debug("");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runDepthRenderTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_draw_buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_draw_buffers.html
new file mode 100644
index 0000000000..5da29d80b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_draw_buffers.html
@@ -0,0 +1,158 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runDrawBuffersClearTest()
+{
+ debug("");
+ debug("Testing that calling clear() clears all views in all draw buffers");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = [null, null, null];
+ let drawBuffers = [0, 0, 0];
+ for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
+ colorTex[texIndex] = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
+ drawBuffers[texIndex] = gl.COLOR_ATTACHMENT0 + texIndex;
+ }
+
+ gl.viewport(0, 0, width, height);
+ gl.drawBuffers(drawBuffers);
+
+ gl.clearColor(0, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex[texIndex], 0, viewIndex);
+ let expectedColor = [0, 255, 255, 255];
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' of color attachment ' + texIndex + ' should be cyan');
+ }
+ debug("");
+ }
+}
+
+function runDrawBuffersRenderTest()
+{
+ debug("");
+ debug("Testing rendering into multiple draw buffers with a different transformation matrix chosen from a uniform array according to ViewID");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = [null, null, null];
+ let drawBuffers = [0, 0, 0];
+ for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
+ colorTex[texIndex] = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
+ drawBuffers[texIndex] = gl.COLOR_ATTACHMENT0 + texIndex;
+ }
+
+ let multiviewShaders = [
+ getMultiviewRealisticUseCaseVertexShader(views),
+ getMultiviewColorFragmentShaderForDrawBuffers(colorTex.length)
+ ];
+
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ gl.viewport(0, 0, width, height);
+ gl.drawBuffers(drawBuffers);
+
+ let transformLocation = gl.getUniformLocation(testProgram, 'transform');
+ let transformData = new Float32Array (views * 16);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ let scaleX = 1.0 / views;
+ // offsetX is the position of the left edge of the quad we want to get in normalized device coordinates
+ let offsetX = viewIndex / views * 2.0 - 1.0;
+
+ setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX);
+ }
+ gl.uniformMatrix4fv(transformLocation, false, transformData);
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex[texIndex], 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex + texIndex);
+
+ checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex + ' of color attachment ' + texIndex);
+ }
+ debug("");
+ }
+}
+
+description("This test verifies the functionality of the OVR_multiview2 extension when used with multiple draw buffers, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ runDrawBuffersClearTest();
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runDrawBuffersRenderTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_flat_varying.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_flat_varying.html
new file mode 100644
index 0000000000..9a99de7e84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_flat_varying.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runFlatVaryingTest()
+{
+ debug("");
+ debug("Testing rendering with different colors in fragment shader");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewFlatVaryingVertexShader(views),
+ getMultiviewFlatVaryingFragmentShader()
+ ];
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
+ }
+}
+
+description("This test verifies that flat varyings work in multiview shaders using OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runFlatVaryingTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_instanced_draw.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_instanced_draw.html
new file mode 100644
index 0000000000..b55d0cfc03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_instanced_draw.html
@@ -0,0 +1,105 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runInstancedDrawTest()
+{
+ debug("");
+ debug("Testing instanced rendering");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewInstancedVertexShader(views),
+ getInstanceColorFragmentShader()
+ ];
+
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let colorRegionLeftEdge = (width / (views * 2)) * viewIndex;
+ let colorRegionRightEdge = (width / (views * 2)) * (viewIndex + 2);
+ let stripWidth = (colorRegionRightEdge - colorRegionLeftEdge) / 2;
+ if (colorRegionLeftEdge > 0) {
+ wtu.checkCanvasRect(gl, 0, 0, Math.floor(colorRegionLeftEdge) - 1, height, [0, 0, 0, 0], 'the left edge of view ' + viewIndex + ' should be untouched');
+ }
+ if (colorRegionRightEdge < width) {
+ wtu.checkCanvasRect(gl, colorRegionRightEdge + 1, 0, width - colorRegionRightEdge - 1, height, [0, 0, 0, 0], 'the right edge of view ' + viewIndex + ' should be untouched');
+ }
+ let expectedColor = getExpectedColor(0);
+ wtu.checkCanvasRect(gl, colorRegionLeftEdge + 1, 0, stripWidth - 2, height, expectedColor, 'a thin strip in view ' + viewIndex + ' drawn by instance 0 should be colored ' + expectedColor);
+ expectedColor = getExpectedColor(1);
+ wtu.checkCanvasRect(gl, colorRegionLeftEdge + stripWidth + 1, 0, stripWidth - 2, height, expectedColor, 'a thin strip in view ' + viewIndex + ' drawn by instance 1 should be colored ' + expectedColor);
+ }
+}
+
+description("This test verifies instanced draws together with the OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runInstancedDrawTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_non_multiview_shaders.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_non_multiview_shaders.html
new file mode 100644
index 0000000000..44e2ea02ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_non_multiview_shaders.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runNonMultiviewShaderTest()
+{
+ debug("");
+ debug("Testing rendering with shaders that don't declare num_views");
+
+ let width = 256;
+ let height = 256;
+ let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
+
+ let testProgram = wtu.setupSimpleColorProgram(gl);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let colorUniformLocation = gl.getUniformLocation(testProgram, 'u_color');
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
+
+ gl.viewport(0, 0, width, height);
+
+ gl.uniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when using a non-multiview shader as long as the number of views is 1");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], 'view 0 should be green');
+
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "draw should generate an INVALID_OPERATION error when using a non-multiview shader and the number of views is > 1");
+}
+
+description("This test verifies that non-multiview shaders work correctly with OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runNonMultiviewShaderTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_single_view_operations.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_single_view_operations.html
new file mode 100644
index 0000000000..0e01a3e3b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_single_view_operations.html
@@ -0,0 +1,253 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+
+function runSingleViewReadTest()
+{
+ debug("");
+ debug("Testing reading from a multiview framebuffer with num_views = 1");
+
+ let width = 256;
+ let height = 256;
+ let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
+
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(0.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ let buf = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from readPixels");
+
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'view 0 should be cyan');
+ gl.getError();
+
+ // Also test for the error case with two views
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to read from a framebuffer with two views");
+}
+
+function runSingleViewBlitTest()
+{
+ debug("");
+ debug("Testing blitting from a multiview framebuffer with num_views = 1");
+
+ let width = 256;
+ let height = 256;
+ let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
+
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(0.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ gl.canvas.width = width;
+ gl.canvas.height = height;
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0)
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from blitFramebuffer");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'view 0 blitted to the default framebuffer should be cyan');
+
+ // Also test for the error case with multiview blit target
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to blit to a multiview framebuffer even if it has just one view");
+
+ // Also test for the error case with two views
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to blit from a framebuffer with two views");
+}
+
+function runSingleViewCopyTexImage2DTest()
+{
+ debug("");
+ debug("Testing copyTexImage2D from a multiview framebuffer with num_views = 1");
+
+ let width = 256;
+ let height = 256;
+ let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
+
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(0.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ let copyTargetTex = createTextureWithNearestFiltering(gl.TEXTURE_2D);
+ gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from copyTexImage2D");
+
+ let copyFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, copyFb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, copyTargetTex, 0);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'copy of view 0 in the 2D texture should be cyan');
+
+ // Also test for the error case with two views
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
+ gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to copy from a framebuffer with two views");
+}
+
+function runSingleViewCopyTexSubImage2DTest()
+{
+ debug("");
+ debug("Testing copyTexSubImage2D from a multiview framebuffer with num_views = 1");
+
+ let width = 256;
+ let height = 256;
+ let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
+
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(0.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ let copyTargetTex = createTextureWithNearestFiltering(gl.TEXTURE_2D);
+ gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from copyTexImage2D");
+
+ let copyFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, copyFb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, copyTargetTex, 0);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'copy of view 0 in the 2D texture should be cyan');
+
+ // Also test for the error case with two views
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
+ gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to copy from a framebuffer with two views");
+}
+
+function runSingleViewCopyTexSubImage3DTest()
+{
+ debug("");
+ debug("Testing copyTexSubImage3D from a multiview framebuffer with num_views = 1");
+
+ let width = 256;
+ let height = 256;
+ let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
+
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(0.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
+
+ let copyTargetTex = createTextureWithNearestFiltering(gl.TEXTURE_3D);
+ gl.bindTexture(gl.TEXTURE_3D, copyTargetTex);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from copyTexSubImage3D");
+
+ let copyFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, copyFb);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, copyTargetTex, 0, 0);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'copy of view 0 in the 3D texture should be cyan');
+
+ // Also test for the error case with two views
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
+ gl.bindTexture(gl.TEXTURE_3D, copyTargetTex);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to copy from a framebuffer with two views");
+}
+
+description("This test verifies that framebuffers with only one view can be read from with OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ runSingleViewReadTest();
+
+ runSingleViewBlitTest();
+
+ runSingleViewCopyTexImage2DTest();
+
+ runSingleViewCopyTexSubImage2DTest();
+
+ runSingleViewCopyTexSubImage3DTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_timer_query.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_timer_query.html
new file mode 100644
index 0000000000..9f76fadf98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_timer_query.html
@@ -0,0 +1,142 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+let queryExt = null;
+
+function runClearTest()
+{
+ debug("");
+ debug("Testing clear");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+
+ gl.clearColor(1, 0, 0, 1);
+
+ let query = gl.createQuery();
+ gl.beginQuery(queryExt.TIME_ELAPSED_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from setup");
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "multiview clear should generate invalid operation when a timer query is active");
+
+ gl.endQuery(queryExt.TIME_ELAPSED_EXT);
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = [0, 0, 0, 0];
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be untouched');
+ }
+}
+
+function runFragmentShaderRenderTest()
+{
+ debug("");
+ debug("Testing rendering with different colors in fragment shader");
+
+ let width = 256;
+ let height = 256;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewPassthroughVertexShader(views),
+ getMultiviewColorFragmentShader()
+ ];
+ let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ gl.viewport(0, 0, width, height);
+
+ let query = gl.createQuery();
+ gl.beginQuery(queryExt.TIME_ELAPSED_EXT, query);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from setup");
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "multiview draw should generate invalid operation when a timer query is active");
+
+ gl.endQuery(queryExt.TIME_ELAPSED_EXT);
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = [0, 0, 0, 0];
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be untouched');
+ }
+}
+
+description("This test verifies the functionality of the OVR_multiview2 extension and its interaction with EXT_disjoint_timer_query_webgl2, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2") || !gl.getExtension("EXT_disjoint_timer_query_webgl2")) {
+ testPassed("No OVR_multiview2 support or no EXT_disjoint_timer_query_webgl2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 and EXT_disjoint_timer_query_webgl2 extensions");
+ ext = gl.getExtension('OVR_multiview2');
+ queryExt = gl.getExtension('EXT_disjoint_timer_query_webgl2');
+
+ runClearTest();
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runFragmentShaderRenderTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_transform_feedback.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_transform_feedback.html
new file mode 100644
index 0000000000..297dd43f1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_transform_feedback.html
@@ -0,0 +1,125 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL OVR_multiview2 Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/ovr_multiview2_util.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+let wtu = WebGLTestUtils;
+let gl = wtu.create3DContext(null, null, 2);
+let ext = null;
+let queryExt = null;
+
+function runTransformFeedbackTest()
+{
+ debug("");
+ debug("Testing transform feedback combined with multiview rendering");
+
+ let width = 64;
+ let height = 64;
+
+ let views = gl.getParameter(ext.MAX_VIEWS_OVR);
+
+ let multiviewShaders = [
+ getMultiviewVaryingVertexShader(views),
+ getMultiviewVaryingFragmentShader()
+ ];
+ let testProgram = wtu.setupTransformFeedbackProgram(gl, multiviewShaders, ['testVarying'], gl.SEPARATE_ATTRIBS, ['a_position'], [0], true);
+ if (!testProgram) {
+ testFailed("Compilation with extension enabled failed.");
+ return;
+ }
+
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
+ ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
+
+ let xfb = gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, xfb);
+
+ let xfbBuffer = gl.createBuffer();
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 128, gl.DYNAMIC_DRAW);
+
+ gl.viewport(0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from setup");
+
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "rendering to a multiview framebuffer with more than one view when there's an active transform feedback should result in invalid operation");
+
+ gl.pauseTransformFeedback();
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when rendering to a multiview framebuffer with more than one view when there's an active paused transform feedback");
+
+ let readFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
+ }
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when transform feedback is unbound");
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
+ for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
+ let expectedColor = getExpectedColor(viewIndex);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
+ }
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, xfb);
+ gl.endTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from ending transform feedback");
+}
+
+description("This test verifies interaction between transform feedback and the OVR_multiview2 extension, if it is available.");
+
+debug("");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (!gl.getExtension("OVR_multiview2")) {
+ testPassed("No OVR_multiview2 support -- this is legal");
+ } else {
+ testPassed("Successfully enabled OVR_multiview2 extension");
+ ext = gl.getExtension('OVR_multiview2');
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ runTransformFeedbackTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions-in-shaders.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions-in-shaders.html
new file mode 100644
index 0000000000..b2b4d1257f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions-in-shaders.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Extensions promoted to core should not be possible to use in shaders</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fragShaderRequire" type="x-shader/x-fragment">
+#extension $(ext) : require
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="fragShaderIfdef" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+#ifdef $(ext)
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+#else
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+#endif
+}
+</script>
+<script id="fragShader300Require" type="x-shader/x-fragment">#version 300 es
+#extension $(ext) : require
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="fragShader300Ifdef" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+#ifdef $(ext)
+ my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+#else
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+#endif
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+
+var shaderTemplateRequire = wtu.getScript('fragShaderRequire');
+var shaderTemplate300Require = wtu.getScript('fragShader300Require');
+var shaderTemplateIfdef = wtu.getScript('fragShaderIfdef');
+var shaderTemplate300Ifdef = wtu.getScript('fragShader300Ifdef');
+
+var extensions = [
+ 'GL_EXT_draw_buffers',
+ 'GL_EXT_frag_depth',
+ 'GL_EXT_shader_texture_lod',
+ 'GL_OES_standard_derivatives'
+];
+
+var tests = [];
+
+for (var i = 0; i < extensions.length; ++i) {
+ var shaderSrcRequire = wtu.replaceParams(shaderTemplateRequire, {'ext': extensions[i]});
+ tests.push({
+ fShaderSource: shaderSrcRequire,
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "ESSL 1.00 Fragment shader that requires " + extensions[i] + " should not compile."
+ });
+ var shaderSrc300Require = wtu.replaceParams(shaderTemplate300Require, {'ext': extensions[i]});
+ tests.push({
+ fShaderSource: shaderSrc300Require,
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "ESSL 3.00 Fragment shader that requires " + extensions[i] + " should not compile."
+ });
+
+ var shaderSrcIfdef = wtu.replaceParams(shaderTemplateIfdef, {'ext': extensions[i]});
+ tests.push({
+ fShaderSource: shaderSrcIfdef,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: extensions[i] + " should not be defined in ESSL 1.00 fragment shader."
+ });
+ var shaderSrc300Ifdef = wtu.replaceParams(shaderTemplate300Ifdef, {'ext': extensions[i]});
+ tests.push({
+ fShaderSource: shaderSrc300Ifdef,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: extensions[i] + " should not be defined in ESSL 3.00 fragment shader."
+ });
+}
+
+GLSLConformanceTester.runTests(tests, 2);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions.html
new file mode 100644
index 0000000000..7e22942c4d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/promoted-extensions.html
@@ -0,0 +1,64 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+
+function checkExtensionNotAvailable(extension, extensions) {
+ if (extensions.indexOf(extension) >= 0) {
+ testFailed(extension + " was exposed in the WebGL 2.0 context but should not have been");
+ } else {
+ testPassed(extension + " was not exposed in the WebGL 2.0 context");
+ }
+}
+
+description("Promoted extensions from WebGL 1.0 should not be exposed in WebGL 2.0");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
+
+var exts = gl.getSupportedExtensions();
+
+var promotedExtensions = [
+ "ANGLE_instanced_arrays",
+ "EXT_blend_minmax",
+ "EXT_frag_depth",
+ "EXT_shader_texture_lod",
+ "EXT_sRGB",
+ "OES_element_index_uint",
+ "OES_standard_derivatives",
+ "OES_texture_float",
+ "OES_texture_half_float",
+ "OES_texture_half_float_linear",
+ "OES_vertex_array_object",
+ "WEBGL_depth_texture",
+ "WEBGL_draw_buffers",
+]
+
+for (var i = 0; i < promotedExtensions.length; ++i) {
+ checkExtensionNotAvailable(promotedExtensions[i], exts);
+}
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/required-extensions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/required-extensions.html
new file mode 100644
index 0000000000..c3de2a5677
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/required-extensions.html
@@ -0,0 +1,58 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+let gl;
+
+description("Ensure that required extensions are supported");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
+
+const supportedExts = gl.getSupportedExtensions();
+
+function hasExt(name) {
+ return supportedExts.indexOf(name) >= 0;
+}
+
+const has_s3tc = hasExt('WEBGL_compressed_texture_s3tc');
+const has_s3tc_srgb = hasExt('WEBGL_compressed_texture_s3tc_srgb');
+const has_rgtc = hasExt('EXT_texture_compression_rgtc');
+const has_etc = hasExt('WEBGL_compressed_texture_etc');
+
+debug(`has_s3tc: ${has_s3tc}`);
+debug(`has_s3tc_srgb: ${has_s3tc_srgb}`);
+debug(`has_rgtc: ${has_rgtc}`);
+debug(`has_etc: ${has_etc}`);
+
+shouldBeTrue("((has_s3tc && has_s3tc_srgb && has_rgtc) || has_etc)");
+
+// ETC1 extension must not be exposed on WebGL 2.0 contexts without ETC2.
+debug("");
+const has_etc1 = hasExt('WEBGL_compressed_texture_etc1');
+debug(`has_etc1: ${has_etc1}`);
+shouldBeTrue("has_etc1 == has_etc");
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-multi-draw-instanced-base-vertex-base-instance.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-multi-draw-instanced-base-vertex-base-instance.html
new file mode 100644
index 0000000000..37f3e23762
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-multi-draw-instanced-base-vertex-base-instance.html
@@ -0,0 +1,1021 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL ANGLE_base_vertex_base_instance Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/compositing-test.js"></script>
+<script src="../../js/tests/invalid-vertex-attrib-test.js"></script>
+</head>
+<body>
+<script id="vshaderBaseInstanceWithoutExt" type="x-shader/x-vertex">#version 300 es
+layout(location = 0) in vec2 vPosition;
+out vec4 color;
+void main()
+{
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_Position = vec4(vPosition * 2.0 - 1.0, gl_BaseInstance, 1);
+}
+</script>
+<!-- Check gl_InstanceID starts at 0 regardless of gl_BaseInstance -->
+<script id="vshaderInstanceIDCheck" type="x-shader/x-vertex">#version 300 es
+layout(location = 0) in vec2 vPosition;
+out vec4 color;
+void main()
+{
+ if (gl_InstanceID == 0) {
+ color = vec4(0, 1, 0, 1);
+ } else {
+ color = vec4(1, 0, 0, 1);
+ }
+ gl_Position = vec4(vPosition * 2.0 - 1.0, 0, 1);
+}
+</script>
+<script id="vshaderBaseVertexWithoutExt" type="x-shader/x-vertex">#version 300 es
+layout(location = 0) in vec2 vPosition;
+out vec4 color;
+void main()
+{
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_Position = vec4(vPosition * 2.0 - 1.0, gl_BaseVertex, 1);
+}
+</script>
+<script id="vshaderWithExt" type="x-shader/x-vertex">#version 300 es
+#extension GL_ANGLE_base_vertex_base_instance : require
+layout(location = 0) in vec2 vPosition;
+out vec4 color;
+void main()
+{
+ color = vec4(0, 1, 0, 1);
+ gl_Position = vec4(vPosition * 2.0 - 1.0, 0, 1);
+}
+</script>
+<!-- Check gl_VertexID starts at gl_BaseVertex -->
+<script id="vshaderVertexIDCheck" type="x-shader/x-vertex">#version 300 es
+layout(location = 0) in vec2 vPosition;
+out vec4 color;
+void main()
+{
+ if (gl_VertexID >= 3) {
+ color = vec4(0, 1, 0, 1);
+ } else {
+ color = vec4(1, 0, 0, 1);
+ }
+ gl_Position = vec4(vPosition * 2.0 - 1.0, 0, 1);
+}
+</script>
+<script id="vshaderSimple" type="x-shader/x-vertex">#version 300 es
+ layout(location = 0) in vec2 vPosition;
+ layout(location = 1) in float vInstance;
+ out vec4 color;
+ void main()
+ {
+ if (vInstance <= 0.0) {
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+ } else if (vInstance <= 1.0) {
+ color = vec4(0.0, 1.0, 0.0, 1.0);
+ } else if (vInstance <= 2.0) {
+ color = vec4(0.0, 0.0, 1.0, 1.0);
+ } else {
+ color = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+
+ gl_Position = vec4(vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
+ }
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+ precision mediump float;
+ in vec4 color;
+ out vec4 oColor;
+ void main() {
+ oColor = color;
+ }
+</script>
+<div id="description"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_[multi]_draw_basevertex_base_instance extension, if it is available.");
+
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("canvas");
+canvas.style.backgroundColor = '#000';
+canvas.style.imageRendering = 'pixelated'; // Because Chrome doesn't support crisp-edges.
+canvas.style.imageRendering = 'crisp-edges';
+const attribs = {
+ antialias: false,
+};
+const gl = wtu.create3DContext(canvas, attribs, 2);
+
+const width = gl.canvas.width;
+const height = gl.canvas.height;
+const x_count = 8;
+const y_count = 8;
+const quad_count = x_count * y_count;
+const tri_count = quad_count * 2;
+const tileSize = [ 1/x_count, 1/y_count ];
+const tilePixelSize = [ Math.floor(width / x_count), Math.floor(height / y_count) ];
+const quadRadius = [ 0.25 * tileSize[0], 0.25 * tileSize[1] ];
+const pixelCheckSize = [ Math.floor(quadRadius[0] * width), Math.floor(quadRadius[1] * height) ];
+const bufferUsageSet = [ gl.STATIC_DRAW, gl.DYNAMIC_DRAW ];
+
+function getTileCenter(x, y) {
+ return [ tileSize[0] * (0.5 + x), tileSize[1] * (0.5 + y) ];
+}
+
+function getQuadVertices(x, y) {
+ const center = getTileCenter(x, y);
+ return [
+ [center[0] - quadRadius[0], center[1] - quadRadius[1], 0],
+ [center[0] + quadRadius[0], center[1] - quadRadius[1], 0],
+ [center[0] + quadRadius[0], center[1] + quadRadius[1], 0],
+ [center[0] - quadRadius[0], center[1] + quadRadius[1], 0],
+ ];
+}
+
+const indicesData = [];
+let verticesData = [];
+let nonIndexedVerticesData = [];
+const instanceIDsData = Array.from(Array(x_count).keys());
+const is = new Uint16Array([0, 1, 2, 0, 2, 3]);
+// Rects in the same column are within a vertex array, testing gl_VertexID, gl_BaseVertex
+// Rects in the same row are drawn by instancing, testing gl_InstanceID, gl_BaseInstance
+for (let y = 0; y < y_count; ++y) {
+ // v3 ---- v2
+ // | |
+ // | |
+ // v0 ---- v1
+
+ // Get only one column of quad vertices as our geometry
+ // Rely on BaseInstance to duplicate on x axis
+ const vs = getQuadVertices(0, y);
+
+ for (let i = 0; i < vs.length; ++i) {
+ verticesData = verticesData.concat(vs[i]);
+ }
+
+ for (let i = 0; i < is.length; ++i) {
+ nonIndexedVerticesData = nonIndexedVerticesData.concat(vs[is[i]]);
+ }
+}
+
+// Build the indicesData used by drawElements*
+for (let i = 0; i < y_count; ++i) {
+ let oi = 6 * i;
+ let ov = 4 * i;
+ for (let j = 0; j < is.length; ++j) {
+ indicesData[oi + j] = is[j] + ov;
+ }
+}
+
+const indices = new Uint16Array(indicesData);
+const vertices = new Float32Array(verticesData);
+const nonIndexedVertices = new Float32Array(nonIndexedVerticesData);
+const instanceIDs = new Float32Array(instanceIDsData);
+
+const indexBuffer = gl.createBuffer();
+const vertexBuffer = gl.createBuffer();
+const nonIndexedVertexBuffer = gl.createBuffer();
+const instanceIDBuffer = gl.createBuffer();
+
+const drawArraysDrawCount = x_count / 2;
+let drawArraysParams = {
+ drawCount: drawArraysDrawCount,
+ firsts: new Uint32Array(drawArraysDrawCount).fill(0),
+ counts: new Uint32Array(drawArraysDrawCount).fill(y_count * 6),
+ instances: new Uint32Array(drawArraysDrawCount).fill(2),
+ baseInstances: new Uint32Array(drawArraysDrawCount)
+};
+
+for (let i = 0; i < x_count / 2; ++i) {
+ drawArraysParams.baseInstances[i] = i * 2;
+}
+
+const drawElementsDrawCount = x_count * y_count / 2;
+let drawElementsParams = {
+ drawCount: drawElementsDrawCount,
+ offsets: new Uint32Array(drawElementsDrawCount).fill(0),
+ counts: new Uint32Array(drawElementsDrawCount).fill(6),
+ instances: new Uint32Array(drawElementsDrawCount).fill(2),
+ baseVertices: new Uint32Array(drawElementsDrawCount),
+ baseInstances: new Uint32Array(drawElementsDrawCount)
+};
+
+let b = 0;
+for (let v = 0; v < y_count; ++v) {
+ for (let i = 0; i < x_count; i+=2) {
+ drawElementsParams.baseVertices[b] = v * 4;
+ drawElementsParams.baseInstances[b] = i;
+ ++b;
+ }
+}
+
+function setupGeneralBuffers(bufferUsage) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, bufferUsage);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, bufferUsage);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonIndexedVertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, nonIndexedVertices, bufferUsage);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceIDBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, instanceIDs, bufferUsage);
+}
+
+// Check if the extension is either both enabled and supported or
+// not enabled and not supported.
+function runSupportedTest(extensionName, extensionEnabled) {
+ const supported = gl.getSupportedExtensions();
+ if (supported.indexOf(extensionName) >= 0) {
+ if (extensionEnabled) {
+ testPassed(extensionName + ' listed as supported and getExtension succeeded');
+ return true;
+ } else {
+ testFailed(extensionName + ' listed as supported but getExtension failed');
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed(extensionName + ' not listed as supported but getExtension succeeded');
+ } else {
+ testPassed(extensionName + ' not listed as supported and getExtension failed -- this is legal');
+ }
+ }
+ return false;
+}
+
+function runTest() {
+ if (!gl) {
+ return function() {
+ testFailed('WebGL context does not exist');
+ }
+ }
+
+ doTest('WEBGL_draw_instanced_base_vertex_base_instance', false);
+ doTest('WEBGL_multi_draw_instanced_base_vertex_base_instance', true);
+
+ testGlslBuiltins();
+}
+
+// -
+
+function* range(n) {
+ for (let i = 0; i < n; i++) {
+ yield i;
+ }
+}
+
+function crossCombine(...args) {
+ function crossCombine2(listA, listB) {
+ const listC = [];
+ for (const a of listA) {
+ for (const b of listB) {
+ const c = Object.assign({}, a, b);
+ listC.push(c);
+ }
+ }
+ return listC;
+ }
+
+ let res = [{}];
+ while (args.length) {
+ const next = args.shift();
+ next[0].defined;
+ res = crossCombine2(res, next);
+ }
+ return res;
+}
+
+// -
+
+const PASSTHROUGH_FRAG_SRC = `\
+#version 300 es
+precision mediump float;
+in vec4 v_color;
+out vec4 o_color;
+
+void main() {
+ o_color = v_color;
+}
+`;
+
+function testGlslBuiltins() {
+ const EXT = gl.getExtension('WEBGL_draw_instanced_base_vertex_base_instance');
+
+ const vertid_prog = (() => {
+ const vert_src = `\
+#version 300 es
+#line 405
+layout(location = 0) in int a_vertex_id; // Same as gl_VertexID
+out vec4 v_color;
+
+void main() {
+ gl_Position = vec4(0,0,0,1);
+ gl_PointSize = 1.0;
+ v_color = vec4(float(gl_VertexID), float(a_vertex_id),0,0);
+ v_color /= 255.0;
+}
+`;
+ const prog = wtu.setupProgram(gl, [vert_src, PASSTHROUGH_FRAG_SRC],
+ undefined, undefined, /*logShaders*/ true);
+ expectTrue(!!prog, `make_vertid_prog failed`);
+ return prog;
+ })();
+
+ const instid_prog = (() => {
+ const vert_src = `\
+#version 300 es
+#line 425
+layout(location = 0) in int a_vertex_id; // Same as gl_VertexID
+layout(location = 1) in int a_instance_div1; // Same as base_instance+gl_InstanceID
+layout(location = 2) in int a_instance_div2; // Same as base_instance+floor(gl_InstanceID/2)
+layout(location = 3) in int a_instance_div3; // Same as base_instance+floor(gl_InstanceID/3)
+out vec4 v_color;
+
+void main() {
+ gl_Position = vec4(0,0,0,1);
+ gl_PointSize = 1.0;
+ v_color = vec4(float(gl_InstanceID), float(a_instance_div1),
+ float(a_instance_div2), float(a_instance_div3));
+ v_color /= 255.0;
+}
+`;
+ const prog = wtu.setupProgram(gl, [vert_src, PASSTHROUGH_FRAG_SRC],
+ undefined, undefined, /*logShaders*/ true);
+ expectTrue(!!prog, `make_instid_prog failed`);
+ return prog;
+ })();
+
+ const COUNT_UP_DATA = new Int32Array(1000);
+ for (const i in COUNT_UP_DATA) {
+ COUNT_UP_DATA[i] = i;
+ }
+
+ const vertex_id_buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertex_id_buf);
+ gl.bufferData(gl.ARRAY_BUFFER, COUNT_UP_DATA, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribIPointer(0, 1, gl.INT, 0, 0);
+
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribIPointer(1, 1, gl.INT, 0, 0);
+ gl.vertexAttribDivisor(1, 1);
+
+ gl.enableVertexAttribArray(2);
+ gl.vertexAttribIPointer(2, 1, gl.INT, 0, 0);
+ gl.vertexAttribDivisor(2, 2);
+
+ gl.enableVertexAttribArray(3);
+ gl.vertexAttribIPointer(3, 1, gl.INT, 0, 0);
+ gl.vertexAttribDivisor(3, 3);
+
+ const index_buf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, COUNT_UP_DATA, gl.STATIC_DRAW);
+
+ gl.canvas.width = gl.canvas.height = 1;
+ gl.canvas.style.width = gl.canvas.style.height = '1em';
+ gl.viewport(0, 0, 1, 1);
+
+ const expect_pixel = (() => {
+ const was = new Uint8Array(4);
+ return (desc, subtest, expected) => {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, was);
+ if (!areArraysEqual(was, expected)) {
+ testFailed(`${subtest}: Expected [${expected}], was [${was}]. desc: ${JSON.stringify(desc)}`);
+ } else {
+ debug(`${subtest}: Was [${was}] as expected.`);
+ }
+ };
+ })();
+
+ // Common setup complete
+ // -
+ // Create testcases
+
+ const DRAW_FUNC_COMBINER = [{
+ name: 'drawArraysInstanced',
+ draw: desc => {
+ if (desc.base_vert) return false;
+ if (desc.base_inst) return false;
+ gl.drawArraysInstanced(gl[desc.mode], desc.first_vert,
+ desc.vert_count, desc.inst_count);
+ return true;
+ },
+ }, {
+ name: 'drawElementsInstanced',
+ draw: desc => {
+ if (desc.base_vert) return false;
+ if (desc.base_inst) return false;
+ gl.drawElementsInstanced(gl[desc.mode], desc.vert_count,
+ gl.UNSIGNED_INT, 4*desc.first_vert, desc.inst_count);
+ return true;
+ },
+ }, {
+ name: 'drawArraysInstancedBaseInstanceWEBGL',
+ draw: desc => {
+ if (desc.base_vert) return false;
+ if (!EXT) return false;
+ EXT.drawArraysInstancedBaseInstanceWEBGL(gl[desc.mode],
+ desc.first_vert, desc.vert_count, desc.inst_count,
+ desc.base_inst);
+ return true;
+ },
+ }, {
+ name: 'drawElementsInstancedBaseVertexBaseInstanceWEBGL',
+ draw: desc => {
+ if (!EXT) return false;
+ EXT.drawElementsInstancedBaseVertexBaseInstanceWEBGL(
+ gl[desc.mode], desc.vert_count, gl.UNSIGNED_INT, 4*desc.first_vert,
+ desc.inst_count, desc.base_vert, desc.base_inst);
+ return true;
+ },
+ }];
+
+ // -
+
+ function make_key_combiner(key, vals) {
+ const ret = [];
+ for (const v of vals) {
+ const cur = {};
+ cur[key] = v;
+ ret.push(cur);
+ }
+ return ret;
+ }
+
+ const TEST_DESCS = crossCombine(
+ DRAW_FUNC_COMBINER,
+ make_key_combiner('base_vert', [0,1,2]),
+ make_key_combiner('vert_count', [0,1,2]),
+ make_key_combiner('base_inst', [0,1,2]),
+ make_key_combiner('inst_count', range(10)),
+ make_key_combiner('first_vert', [0,1,2]),
+ );
+ console.log('TEST_DESCS', TEST_DESCS);
+
+ // -
+ // Run testcases
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.STENCIL_TEST);
+ gl.disable(gl.BLEND);
+
+ for (const desc of TEST_DESCS) {
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearBufferfv(gl.COLOR, 0, [1,0,0,1]);
+
+ // From OpenGL ES 3.2 spec section 10.5
+ // https://www.khronos.org/registry/OpenGL/specs/es/3.2/es_spec_3.2.pdf
+ // The index of any element transferred to the GL by DrawArraysOneInstance
+ // is referred to as its vertex ID, and may be read by a vertex shader as gl_VertexID.
+ // The vertex ID of the ith element transferred is first + i.
+ const last_gl_vert_id = desc.base_vert + desc.first_vert + desc.vert_count - 1;
+ const last_vert_id = last_gl_vert_id;
+ const last_inst_id = desc.inst_count - 1;
+ const last_inst_div1 = desc.base_inst + last_inst_id;
+ const last_inst_div2 = desc.base_inst + Math.floor(last_inst_id / 2);
+ const last_inst_div3 = desc.base_inst + Math.floor(last_inst_id / 3);
+
+ gl.useProgram(vertid_prog);
+ if (!desc.draw(desc)) continue;
+ debug('\ndesc: ' + JSON.stringify(desc));
+
+ wtu.glErrorAssert(gl, 0);
+ if (!desc.vert_count || !desc.inst_count) {
+ expect_pixel(desc, 'vertid_prog', [255, 0, 0, 255]);
+ continue;
+ }
+
+ expect_pixel(desc, 'vertid_prog', [last_gl_vert_id, last_vert_id, 0, 0]);
+
+ gl.useProgram(instid_prog);
+ desc.draw(desc);
+ expect_pixel(desc, 'instid_prog', [last_inst_id, last_inst_div1, last_inst_div2, last_inst_div3]);
+ }
+}
+
+// -
+
+function doTest(extensionName, multiDraw) {
+ const ext = gl.getExtension(extensionName);
+ if (!runSupportedTest(extensionName, ext)) {
+ return;
+ }
+
+ function getShaderSource(countX, countY, config) {
+ const vs = [
+ '#version 300 es',
+ config.isMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '',
+ '#define kCountX ' + countX.toString(),
+ '#define kCountY ' + countY.toString(),
+ 'layout(location = 0) in vec2 vPosition;',
+ 'layout(location = 1) in float vInstanceID;',
+ 'out vec4 color;',
+ 'void main()',
+ '{',
+ ' const float xStep = 1.0 / float(kCountX);',
+ ' const float yStep = 1.0 / float(kCountY);',
+ ' float xID = vInstanceID;',
+ ' float xColor = 1.0 - xStep * xID;',
+ ' float yID = floor(float(gl_VertexID) / ' + (config.isDrawArrays ? '6.0' : '4.0') + ' + 0.01);',
+ ' color = vec4(xColor, 1.0 - yStep * yID, 1.0',
+ ' , 1.0);',
+ ' mat3 transform = mat3(1.0);',
+ ' transform[2][0] = xID * xStep;',
+ ' gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1.0);',
+ '}'
+ ].join('\n');
+
+ const fs = document.getElementById('fshader').text.trim();
+
+ return [vs, fs];
+ }
+
+ function runValidationTests(bufferUsage) {
+ const vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.2,0.2, 0.8,0.2, 0.5,0.8 ]), bufferUsage);
+
+ const indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2 ]), bufferUsage);
+
+ const instanceBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2 ]), bufferUsage);
+
+ const program = wtu.setupProgram(gl, ['vshaderSimple', 'fshader'], ['vPosition, vInstanceID'], [0, 1], true);
+ expectTrue(program != null, "can compile simple program");
+
+ function setupInstanced() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(1, 1);
+ }
+
+ setupInstanced();
+
+ function setupDrawArrays() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ }
+
+ function setupDrawElements() {
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ }
+
+ function makeDrawValidationCheck(drawFunc, setup) {
+ if (!drawFunc) {
+ return function() {};
+ }
+ return function(f_args, expect, msg) {
+ setup();
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ drawFunc.apply(ext, f_args);
+ wtu.glErrorShouldBe(gl, expect, drawFunc.name + " " + msg);
+ gl.disableVertexAttribArray(0);
+ }
+ }
+
+ if (!multiDraw) {
+ const checkDrawArraysInstancedBaseInstance = makeDrawValidationCheck(
+ ext.drawArraysInstancedBaseInstanceWEBGL, setupDrawArrays);
+ const checkDrawElementsInstancedBaseVertexBaseInstance = makeDrawValidationCheck(
+ ext.drawElementsInstancedBaseVertexBaseInstanceWEBGL, setupDrawElements);
+ checkDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, 0, 3, 1, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES"
+ );
+ checkDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0, 1, 0, 0],
+ gl.NO_ERROR, "with gl.TRIANGLES"
+ );
+
+ checkDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, 0, 3, 1, 3],
+ [gl.NO_ERROR, gl.INVALID_OPERATION],
+ "with baseInstance leading to out of bounds"
+ );
+ checkDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0, 1, 2, 0],
+ [gl.NO_ERROR, gl.INVALID_OPERATION],
+ "with baseVertex leading to out of bounds"
+ );
+ checkDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0, 1, 0, 3],
+ [gl.NO_ERROR, gl.INVALID_OPERATION],
+ "with baseInstance leading to out of bounds"
+ );
+ checkDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0, 1, 2, 3],
+ [gl.NO_ERROR, gl.INVALID_OPERATION],
+ "with both baseVertex and baseInstance leading to out of bounds"
+ );
+ } else {
+ const checkMultiDrawArraysInstancedBaseInstance = makeDrawValidationCheck(
+ ext.multiDrawArraysInstancedBaseInstanceWEBGL, setupDrawArrays);
+ const checkMultiDrawElementsInstancedBaseVertexBaseInstance = makeDrawValidationCheck(
+ ext.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL, setupDrawElements);
+
+ // Check that drawing a single triangle works
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, [0], 0, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 0, [0], 0, 1],
+ gl.NO_ERROR, "with gl.TRIANGLES"
+ );
+
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, [3], 0, 1],
+ [gl.NO_ERROR, gl.INVALID_OPERATION], "with baseInstance leads to out of bounds"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [2], 0, [0], 0, 1],
+ [gl.NO_ERROR, gl.INVALID_OPERATION], "with baseVertex leads to out of bounds"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 0, [3], 0, 1],
+ [gl.NO_ERROR, gl.INVALID_OPERATION], "with baseInstance leads to out of bounds"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [2], 0, [3], 0, 1],
+ [gl.NO_ERROR, gl.INVALID_OPERATION],
+ "with both baseVertex and baseInstance lead to out of bounds"
+ );
+
+ // Zero drawcount permitted
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, [0], 0, 0],
+ gl.NO_ERROR, "with drawcount == 0"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 0, [0], 0, 0],
+ gl.NO_ERROR, "with drawcount == 0"
+ );
+
+ // Check negative drawcount
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, [0], 0, -1],
+ gl.INVALID_VALUE, "with drawcount < 0"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 0, [0], 0, -1],
+ gl.INVALID_VALUE, "with drawcount < 0"
+ );
+
+ // Check offsets greater than array length
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 1, [3], 0, [1], 0, [0], 0, 1],
+ gl.INVALID_OPERATION, "with firstsStart >= firstsList.length"
+ );
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 1, [1], 0, [0], 0, 1],
+ gl.INVALID_OPERATION, "with countsStart >= countsList.length"
+ );
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 1, [0], 0, 1],
+ gl.INVALID_OPERATION, "with instanceCountsStart >= instanceCountsList.length"
+ );
+ checkMultiDrawArraysInstancedBaseInstance(
+ [gl.TRIANGLES, [0], 0, [3], 0, [1], 0, [0], 1, 1],
+ gl.INVALID_OPERATION, "with baseInstancesStart >= baseInstancesList.length"
+ );
+
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 1, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 0, [0], 0, 1],
+ gl.INVALID_OPERATION, "with countsStart >= countsList.length"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 1, [1], 0, [0], 0, [0], 0, 1],
+ gl.INVALID_OPERATION, "with offsetsStart >= offsetsList.length"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 1, [0], 0, [0], 0, 1],
+ gl.INVALID_OPERATION, "with instanceCountsStart >= instanceCountsList.length"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 1, [0], 0, 1],
+ gl.INVALID_OPERATION, "with baseVerticesStart >= baseVerticesList.length"
+ );
+ checkMultiDrawElementsInstancedBaseVertexBaseInstance(
+ [gl.TRIANGLES, [3], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [0], 0, [0], 1, 1],
+ gl.INVALID_OPERATION, "with baseInstancesStart >= baseInstancesList.length"
+ );
+ }
+ }
+
+ function runShaderTests(bufferUsage) {
+ let badProgram;
+
+ badProgram = wtu.setupProgram(gl, ["vshaderBaseInstanceWithoutExt", "fshader"]);
+ expectTrue(!badProgram, "cannot compile program with gl_BaseInstance but no extension directive");
+ badProgram = wtu.setupProgram(gl, ["vshaderBaseVertexWithoutExt", "fshader"]);
+ expectTrue(!badProgram, "cannot compile program with gl_BaseVertex but no extension directive");
+
+ badProgram = wtu.setupProgram(gl, ["vshaderWithExt", "fshader"]);
+ expectTrue(!badProgram, "cannot compile program with #extension GL_ANGLE_base_vertex_base_instance");
+
+ const x = Math.floor(width * 0.4);
+ const y = Math.floor(height * 0.4);
+ const xSize = Math.floor(width * 0.2);
+ const ySize = Math.floor(height * 0.2);
+
+ // gl_InstanceID
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0.5,1, 0,1, 0.5,0, 1,1 ]), bufferUsage);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ const instanceIDProgram = wtu.setupProgram(gl, ["vshaderInstanceIDCheck", "fshader"], ["vPosition"], [0]);
+ expectTrue(instanceIDProgram !== null, "can compile program with gl_InstanceID");
+ gl.useProgram(instanceIDProgram);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (!multiDraw) {
+ ext.drawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, 0, 6, 1, 5);
+ } else {
+ ext.multiDrawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, [0], 0, [6], 0, [1], 0, [5], 0, 1);
+ }
+
+ wtu.checkCanvasRect(gl, x, y, xSize, ySize, [0, 255, 0, 255], "gl_InstanceID should always starts from 0");
+
+ // gl_VertexID
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0.5,1, 0,1, 0.5,0, 1,1, 0,0, 1,0, 0.5,1, 0,1 ]), bufferUsage);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3, 4, 5]), bufferUsage);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ const vertexIDProgram = wtu.setupProgram(gl, ["vshaderVertexIDCheck", "fshader"], ["vPosition"], [0]);
+ expectTrue(vertexIDProgram !== null, "can compile program with gl_VertexID");
+ gl.useProgram(vertexIDProgram);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (!multiDraw) {
+ ext.drawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1, 3, 0);
+ } else {
+ ext.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, [6], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [3], 0, [0], 0, 1);
+ }
+
+ wtu.checkCanvasRect(gl, x, y, xSize, ySize, [0, 255, 0, 255], "gl_VertexID should always starts from 0");
+ }
+
+ function runPixelTests() {
+
+ function checkResult(config) {
+ const rects = [];
+ const expected = [
+ [255, 0, 0, 255],
+ [0, 255, 0, 255],
+ [0, 0, 255, 255],
+ ];
+ const msg = config.drawFunc.name + (
+ config.useBaseVertexBuiltin ? ' gl_BaseVertex' : ''
+ ) + (
+ config.useBaseInstanceBuiltin ? ' gl_BaseInstance' : ' InstanceIDArray'
+ );
+ for (let y = 0; y < y_count; ++y) {
+ for (let x = 0; x < x_count; ++x) {
+ const center_x = x * tilePixelSize[0] + Math.floor(tilePixelSize[0] / 2);
+ const center_y = y * tilePixelSize[1] + Math.floor(tilePixelSize[1] / 2);
+
+ rects.push(wtu.makeCheckRect(
+ center_x - Math.floor(pixelCheckSize[0] / 2),
+ center_y - Math.floor(pixelCheckSize[1] / 2),
+ pixelCheckSize[0],
+ pixelCheckSize[1],
+ [
+ 256.0 * (1.0 - x / x_count),
+ 256.0 * (1.0 - y / y_count),
+ (!config.isDrawArrays && config.useBaseVertexBuiltin) ? 256.0 * (1.0 - y / y_count) : 255.0,
+ 255.0
+ ],
+ msg + ' (' + x + ',' + y + ')', 1.0
+ ));
+ }
+ }
+ wtu.checkCanvasRects(gl, rects);
+ }
+
+ // Draw functions variations
+
+ function drawArraysInstancedBaseInstance() {
+ const countPerDraw = y_count * 6;
+ for (let x = 0; x < x_count; x += 2) {
+ ext.drawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, 0, countPerDraw, 2, x);
+ }
+ }
+
+ function multiDrawArraysInstancedBaseInstance() {
+ ext.multiDrawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, drawArraysParams.firsts, 0, drawArraysParams.counts, 0, drawArraysParams.instances, 0, drawArraysParams.baseInstances, 0, drawArraysParams.drawCount);
+ }
+
+ function drawElementsInstancedBaseVertexBaseInstance() {
+ const countPerDraw = 6;
+ for (let v = 0; v < y_count; ++v) {
+ for (let x = 0; x < x_count; x += 2) {
+ ext.drawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, countPerDraw, gl.UNSIGNED_SHORT, 0, 2, v * 4, x);
+ }
+ }
+ }
+
+ function multiDrawElementsInstancedBaseVertexBaseInstance() {
+ ext.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, drawElementsParams.counts, 0, gl.UNSIGNED_SHORT, drawElementsParams.offsets, 0, drawElementsParams.instances, 0, drawElementsParams.baseVertices, 0, drawElementsParams.baseInstances, 0, drawElementsParams.drawCount);
+ }
+
+ function checkDraw(config) {
+ const program = wtu.setupProgram(
+ gl,
+ getShaderSource(x_count, y_count, config),
+ !config.useBaseInstanceBuiltin ? ['vPosition'] : ['vPosition', 'vInstanceID']
+ );
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ if (config.isDrawArrays) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonIndexedVertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ } else {
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ }
+
+ if (!config.useBaseInstanceBuiltin) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, instanceIDBuffer);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(1, 1);
+ }
+
+ config.drawFunc();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ checkResult(config);
+ }
+
+ checkDraw({
+ drawFunc: multiDraw ? multiDrawArraysInstancedBaseInstance : drawArraysInstancedBaseInstance,
+ isDrawArrays: true,
+ isMultiDraw: multiDraw,
+ useBaseVertexBuiltin: false,
+ useBaseInstanceBuiltin: false
+ });
+
+ checkDraw({
+ drawFunc: multiDraw ? multiDrawElementsInstancedBaseVertexBaseInstance : drawElementsInstancedBaseVertexBaseInstance,
+ isDrawArrays: false,
+ isMultiDraw: multiDraw,
+ useBaseVertexBuiltin: false,
+ useBaseInstanceBuiltin: false
+ });
+ }
+
+ for (let i = 0; i < bufferUsageSet.length; i++) {
+ let bufferUsage = bufferUsageSet[i];
+ debug("Testing with BufferUsage = " + bufferUsage);
+ setupGeneralBuffers(bufferUsage);
+ runValidationTests(bufferUsage);
+ runShaderTests(bufferUsage);
+ runPixelTests();
+ }
+}
+
+
+async function runDrawTests(testFn) {
+ function drawArrays(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ function drawElements(gl) {
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ }
+
+ function drawArraysInstanced(gl) {
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, 1);
+ }
+
+ function drawElementsInstanced(gl) {
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1);
+ }
+
+ function drawArraysInstancedBaseInstanceWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_draw_instanced_base_vertex_base_instance');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_draw_instanced_base_vertex_base_instance';
+ }
+
+ ext.drawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, 0, 6, 1, 0);
+ }
+
+ function drawElementsInstancedBaseVertexBaseInstanceWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_draw_instanced_base_vertex_base_instance');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_draw_instanced_base_vertex_base_instance';
+ }
+
+ ext.drawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1, 0, 0);
+ }
+
+ function multiDrawArraysInstancedBaseInstanceWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_multi_draw_instanced_base_vertex_base_instance';
+ }
+ ext.multiDrawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, [0], 0, [6], 0, [1], 0, [0], 0, 1);
+ }
+
+ function multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(gl) {
+ const ext = gl.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance');
+ if (!ext) {
+ throw 'Should not have run this test without WEBGL_multi_draw_instanced_base_vertex_base_instance';
+ }
+ ext.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(
+ gl.TRIANGLES,
+ [6], 0, // counts
+ gl.UNSIGNED_BYTE,
+ [0], 0, // offsets
+ [1], 0, // instances
+ [0], 0, // baseVerts
+ [0], 0, // baseInstances
+ 1, // drawCount
+ );
+ }
+
+ await testFn(drawArrays); // sanity check
+ await testFn(drawElements); // sanity check
+ await testFn(drawArraysInstanced); // sanity check
+ await testFn(drawElementsInstanced); // sanity check
+
+ // It's only legal to call testFn if the extension is supported,
+ // since the invalid vertex attrib tests, in particular, expect the
+ // draw function to have an effect.
+ if (gl.getExtension('WEBGL_draw_instanced_base_vertex_base_instance')) {
+ await testFn(drawArraysInstancedBaseInstanceWEBGL);
+ await testFn(drawElementsInstancedBaseVertexBaseInstanceWEBGL);
+ }
+ if (gl.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance')) {
+ await testFn(multiDrawArraysInstancedBaseInstanceWEBGL);
+ await testFn(multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL);
+ }
+}
+
+async function runCompositingTests() {
+ const compositingTestFn = createCompositingTestFn({
+ webglVersion: 2,
+ shadersFn(gl) {
+ const vs = `\
+ #version 300 es
+ layout(location = 0) in vec4 position;
+ void main() {
+ gl_Position = position;
+ }
+ `;
+ const fs = `\
+ #version 300 es
+ precision highp float;
+ out vec4 fragColor;
+ void main() {
+ fragColor = vec4(1, 0, 0, 1);
+ }
+ `;
+ return [vs, fs];
+ },
+ });
+ await runDrawTests(compositingTestFn);
+}
+
+async function runInvalidAttribTests(gl) {
+ const invalidAttribTestFn = createInvalidAttribTestFn(gl);
+ await runDrawTests(invalidAttribTestFn);
+}
+
+async function main() {
+ runTest();
+ await runInvalidAttribTests(gl);
+ await runCompositingTests();
+ finishTest();
+}
+main();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
new file mode 100644
index 0000000000..5a47d470f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
@@ -0,0 +1,59 @@
+array-as-return-value.html
+array-assign.html
+array-assign-constructor.html
+array-complex-indexing.html
+array-element-increment.html
+array-equality.html
+array-in-complex-expression.html
+--min-version 2.0.1 array-initialize-with-same-name-array.html
+--min-version 2.0.1 array-length-side-effects.html
+attrib-location-length-limits.html
+bool-type-cast-bug-uint-ivec-uvec.html
+compare-structs-containing-arrays.html
+compound-assignment-type-combination.html
+const-array-init.html
+--min-version 2.0.1 const-struct-from-array-as-function-parameter.html
+--min-version 2.0.1 float-parsing.html
+forbidden-operators.html
+--min-version 2.0.1 forward-declaration.html
+frag-depth.html
+--min-version 2.0.1 fragment-shader-loop-crash.html
+--min-version 2.0.1 gradient-in-discontinuous-loop.html
+--min-version 2.0.1 input-with-interpotaion-as-lvalue.html
+invalid-default-precision.html
+invalid-invariant.html
+loops-with-side-effects.html
+--min-version 2.0.1 matrix-row-major.html
+--min-version 2.0.1 matrix-row-major-dynamic-indexing.html
+misplaced-version-directive.html
+--min-version 2.0.1 no-attribute-vertex-shader.html
+--min-version 2.0.1 precision-side-effects-bug.html
+--min-version 2.0.1 reciprocal-sqrt-of-sum-of-squares-crash.html
+sampler-no-precision.html
+--min-version 2.0.1 sampler-array-indexing.html
+sequence-operator-returns-non-constant.html
+shader-linking.html
+shader-with-1024-character-define.html
+shader-with-1024-character-identifier.frag.html
+shader-with-1025-character-define.html
+shader-with-1025-character-identifier.frag.html
+shader-with-invalid-characters.html
+shader-with-mis-matching-uniform-block.html
+short-circuiting-in-loop-condition.html
+--min-version 2.0.1 switch-case.html
+--min-version 2.0.1 texture-offset-non-constant-offset.html
+texture-offset-out-of-range.html
+--min-version 2.0.1 texture-offset-uniform-texture-coordinate.html
+--min-version 2.0.1 tricky-loop-conditions.html
+--min-version 2.0.1 uint-int-shift-bug.html
+--min-version 2.0.1 unary-minus-operator-in-dynamic-loop.html
+uniform-block-layouts.html
+uniform-block-layout-match.html
+uniform-location-length-limits.html
+--min-version 2.0.1 uniform-struct-with-non-square-matrix.html
+--min-version 2.0.1 uninitialized-local-global-variables.html
+valid-invariant.html
+--min-version 2.0.1 varying-struct-inline-definition.html
+vector-dynamic-indexing.html
+--min-version 2.0.1 vector-dynamic-indexing-nv-driver-bug.html
+--min-version 2.0.1 vector-dynamic-indexing-swizzled-lvalue.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-as-return-value.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-as-return-value.html
new file mode 100644
index 0000000000..45d7353111
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-as-return-value.html
@@ -0,0 +1,150 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array as return value test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderReturnedArrayNotUsed" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] plus() {
+ ++g;
+ return int[2](g, g);
+}
+
+void main() {
+ // The function call should be evaluated even if the returned array is not used.
+ plus();
+ my_FragColor = vec4(0.0, ((g == 1) ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderCompareReturnedArray" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] createArray() {
+ ++g;
+ return int[2](g, g);
+}
+
+void main() {
+ // Comparing a returned array should work.
+ if (createArray() == int[2](1, 1)) {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ } else {
+ my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+}
+</script>
+<script id="fshaderReturnReturnedArray" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] foo() {
+ ++g;
+ return int[2](g, g);
+}
+
+int[2] bar(int addition) {
+ g += addition;
+ // Returning a returned array should work.
+ return foo();
+}
+
+void main() {
+ int a[2] = bar(1);
+ bool arrayCorrect = true;
+ for (int i = 0; i < 2; ++i) {
+ if (a[i] != 2) {
+ arrayCorrect = false;
+ }
+ }
+ my_FragColor = vec4(0.0, ((g == 2 && arrayCorrect) ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderReturnedArrayAsParameter" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] createArray() {
+ ++g;
+ return int[2](g, g);
+}
+
+bool isSuccess(int[2] a) {
+ bool arrayCorrect = true;
+ for (int i = 0; i < 2; ++i) {
+ if (a[i] != 1) {
+ arrayCorrect = false;
+ }
+ }
+ return arrayCorrect;
+}
+
+void main() {
+ bool success = isSuccess(createArray());
+ my_FragColor = vec4(0.0, (success ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Arrays as return values should work");
+debug("");
+debug("This test is targeted to stress syntax tree transformations that might need to be done in shader translation when the platform doesn't natively support arrays as return values.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderReturnedArrayNotUsed',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where a returned array is not used'
+},
+{
+ fShaderId: 'fshaderCompareReturnedArray',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where a returned array is compared'
+},
+{
+ fShaderId: 'fshaderReturnReturnedArray',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where a returned array is returned again'
+},
+{
+ fShaderId: 'fshaderReturnedArrayAsParameter',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where a returned array is passed as a parameter'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign-constructor.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign-constructor.html
new file mode 100644
index 0000000000..c47f3d7123
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign-constructor.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array constructor assignment test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderNonConstantConstructorParameter" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform int u;
+
+out vec4 my_FragColor;
+
+void main() {
+ // Test assigning a constructor result as opposed to initializing with a
+ // constructor result.
+ int a[3];
+ a = int[3](0, 1, u);
+ bool fail = false;
+ for (int i = 0; i < 2; ++i) {
+ if (a[i] != i) {
+ fail = true;
+ }
+ }
+ if (a[2] != u) {
+ fail = true;
+ }
+ my_FragColor = vec4(0.0, (fail ? 0.0 : 1.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderArrayOfStructs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+struct S {
+ int foo;
+};
+
+void main() {
+ // Test assigning a constructor result as opposed to initializing with a
+ // constructor result.
+ S a[3];
+ a = S[3](S(0), S(1), S(2));
+ bool fail = false;
+ for (int i = 0; i < 3; ++i) {
+ if (a[i].foo != i) {
+ fail = true;
+ }
+ }
+ my_FragColor = vec4(0.0, (fail ? 0.0 : 1.0), 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Assigning return values of array constructors should work.");
+debug("");
+
+// This test only covers cases which are not covered by the dEQP tests.
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderNonConstantConstructorParameter',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Assigning a constructor result',
+ uniforms: [{name: "u", functionName: "uniform1i", value: 5}]
+},
+{
+ fShaderId: 'fshaderArrayOfStructs',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Assigning an array of structs'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign.html
new file mode 100644
index 0000000000..94c1507b29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-assign.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array assignment test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderSimple" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ // This simple test uses the ESSL1 style array initialization in order
+ // to be able to test array assignment independently of array constructors.
+ int a[3];
+ int b[3];
+ for (int i = 0; i < 3; ++i) {
+ a[i] = 0;
+ b[i] = i;
+ }
+ a = b;
+ bool fail = false;
+ for (int i = 0; i < 3; ++i) {
+ if (a[i] != i) {
+ fail = true;
+ }
+ }
+ my_FragColor = vec4(0.0, (fail ? 0.0 : 1.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderArrayOfStructs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+struct S {
+ int foo;
+};
+
+void main() {
+ // This simple test uses the ESSL1 style array initialization in order
+ // to be able to test array assignment independently of array constructors.
+ S a[3];
+ S b[3];
+ for (int i = 0; i < 3; ++i) {
+ a[i].foo = 0;
+ b[i].foo = i;
+ }
+ a = b;
+ bool fail = false;
+ for (int i = 0; i < 3; ++i) {
+ if (a[i].foo != i) {
+ fail = true;
+ }
+ }
+ my_FragColor = vec4(0.0, (fail ? 0.0 : 1.0), 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Assigning arrays should work.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderSimple',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Arrays of integers'
+},
+{
+ fShaderId: 'fshaderArrayOfStructs',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Arrays of structs'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-complex-indexing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-complex-indexing.html
new file mode 100644
index 0000000000..2ff9fa1c5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-complex-indexing.html
@@ -0,0 +1,87 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL Indexing complex array expressions</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!--
+Array indexing is detailed in the ESSL 3.00 spec section 5.9
+ESSL 3.00 revisions after 3.00.4 changed the definition from 'subscripted array names' to 'subscripted arrays'
+-->
+<script id="fshader-assignment" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+
+void main() {
+ float a[2] = float[2](0.0, 0.0);
+ float b[2] = float[2](2.0, 1.0);
+ float c = (a = b)[0];
+ color = (c == 2.0) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);
+}
+</script>
+<script id="fshader-function" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+bool hasRan = false;
+
+float[2] functionReturnArray() {
+ hasRan = true;
+ return float[2](2.0, 1.0);
+}
+
+void main() {
+ float c = (functionReturnArray())[0];
+ color = ((c == 2.0) && hasRan) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);
+}
+</script>
+<script id="fshader-array-initialization" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+
+void main() {
+ float a = (float[3](2.0, 1.0, 0.0))[0];
+ color = (a == 2.0) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Indexing complex array expressions");
+debug("");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshader-assignment',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test indexing a variable assignment: (a = b)[0]'
+},
+{
+ fShaderId: 'fshader-function',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test indexing a function return with a side-effect: (functionReturnArray())[0]'
+},
+{
+ fShaderId: 'fshader-array-initialization',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test indexing an array initialization: (float[3](2.0, 1.0, 0.0))[0]'
+},
+], 2);
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-element-increment.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-element-increment.html
new file mode 100644
index 0000000000..2a3e555472
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-element-increment.html
@@ -0,0 +1,131 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL initialized array element increment/decrement test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderFloatArrayIncrement" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ float A[2] = float[2](0.0, 1.0);
+ A[0]++;
+ my_FragColor = vec4(1.0 - A[0], A[0], 0.0, 1.0);
+}
+</script>
+<script id="fshaderVectorArrayIncrement" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ vec4 V[2] = vec4[2](vec4(0.0, 2.0, 3.0, 4.0), vec4(5.0, 6.0, 7.0, 8.0));
+ V[0][0]++;
+ my_FragColor = vec4(1.0 - V[0][0], V[0][0], 0.0, 1.0);
+}
+</script>
+<script id="fshaderVectorElementIncrement" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ vec4 v = vec4(0.0, 2.0, 3.0, 4.0);
+ v[0]++;
+ my_FragColor = vec4(1.0 - v[0], v[0], 0.0, 1.0);
+}
+</script>
+<script id="fshaderFloatArrayDecrement" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ float A[2] = float[2](2.0, 1.0);
+ A[0]--;
+ my_FragColor = vec4(1.0 - A[0], A[0], 0.0, 1.0);
+}
+</script>
+<script id="fshaderVectorArrayDecrement" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ vec4 V[2] = vec4[2](vec4(2.0, 2.0, 3.0, 4.0), vec4(5.0, 6.0, 7.0, 8.0));
+ V[0][0]--;
+ my_FragColor = vec4(1.0 - V[0][0], V[0][0], 0.0, 1.0);
+}
+</script>
+<script id="fshaderVectorElementDecrement" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ vec4 v = vec4(2.0, 2.0, 3.0, 4.0);
+ v[0]--;
+ my_FragColor = vec4(1.0 - v[0], v[0], 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Incrementing or decrementing elements of arrays with initializers should work.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderFloatArrayIncrement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Increment an element of a vector array'
+},
+{
+ fShaderId: 'fshaderVectorArrayIncrement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Increment an element of a vector array'
+},
+{
+ fShaderId: 'fshaderVectorElementIncrement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Increment an element of a vector'
+},
+{
+ fShaderId: 'fshaderFloatArrayDecrement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Decrement an element of a vector array'
+},
+{
+ fShaderId: 'fshaderVectorArrayDecrement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Decrement an element of a vector array'
+},
+{
+ fShaderId: 'fshaderVectorElementDecrement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Decrement an element of a vector'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-equality.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-equality.html
new file mode 100644
index 0000000000..dcffa2c0a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-equality.html
@@ -0,0 +1,240 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array equality test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderSimple" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ // This simple test uses the ESSL1 style array initialization in order
+ // to be able to test array equality independently of array constructors.
+ int a[3];
+ int b[3];
+ int c[3];
+ for (int i = 0; i < 3; ++i) {
+ a[i] = i;
+ b[i] = i;
+ c[i] = i + 1;
+ }
+ bool success = (a == b) && (a != c);
+ my_FragColor = vec4(0.0, (success ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderArrayOfStructs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+struct S {
+ int foo;
+};
+
+void main() {
+ // This simple test uses the ESSL1 style array initialization in order
+ // to be able to test array equality independently of array constructors.
+ S a[3];
+ S b[3];
+ S c[3];
+ for (int i = 0; i < 3; ++i) {
+ a[i].foo = i;
+ b[i].foo = i;
+ c[i].foo = i + 1;
+ }
+ bool success = (a == b) && (a != c);
+ my_FragColor = vec4(0.0, (success ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="simple-float-array-fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+uniform float a[3];
+uniform float b[3];
+
+out vec4 fragColor;
+
+void main(void) {
+ fragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ fragColor.g = 1.0;
+ }
+}
+</script>
+<script id="simple-vec-array-fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+uniform vec3 a[3];
+uniform vec3 b[3];
+
+out vec4 fragColor;
+
+void main(void) {
+ fragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ fragColor.g = 1.0;
+ }
+}
+</script>
+<script id="simple-mat-array-fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+uniform mat3 a[3];
+uniform mat3 b[3];
+
+out vec4 fragColor;
+
+void main(void) {
+ fragColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+ if (a == b) {
+ fragColor.g = 1.0;
+ }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Comparing arrays should work.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderSimple',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Arrays of integers'
+},
+{
+ fShaderId: 'fshaderArrayOfStructs',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Arrays of structs'
+},
+{
+ fShaderId: "simple-float-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple float array with default values",
+},
+{
+ fShaderId: "simple-float-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ renderColor: [0, 0, 0, 255],
+ uniforms: [
+ { name: 'a', functionName: 'uniform1fv', value: [1, 2, 3]},
+ { name: 'b', functionName: 'uniform1fv', value: [1, 2, 4]},
+ ],
+ passMsg: "Simple float array with different values",
+},
+{
+ fShaderId: "simple-float-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ uniforms: [
+ { name: 'a', functionName: 'uniform1fv', value: [1, 2, 3]},
+ { name: 'b', functionName: 'uniform1fv', value: [1, 2, 3]},
+ ],
+ passMsg: "Simple float array with same values",
+},
+{
+ fShaderId: "simple-vec-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple vec array with default values",
+},
+{
+ fShaderId: "simple-vec-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ renderColor: [0, 0, 0, 255],
+ uniforms: [
+ { name: 'a', functionName: 'uniform3fv', value: [1, 2, 3, 4, 5, 6, 7, 8, 9]},
+ { name: 'b', functionName: 'uniform3fv', value: [1, 2, 3, 4, 5, 6, 7, 8, 10]},
+ ],
+ passMsg: "Simple vec array with different values",
+},
+{
+ fShaderId: "simple-vec-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ uniforms: [
+ { name: 'a', functionName: 'uniform3fv', value: [1, 2, 3, 4, 5, 6, 7, 8, 9]},
+ { name: 'b', functionName: 'uniform3fv', value: [1, 2, 3, 4, 5, 6, 7, 8, 9]},
+ ],
+ passMsg: "Simple vec array with same values",
+},
+{
+// "simple-mat-array-fs"
+ fShaderId: "simple-mat-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ passMsg: "Simple mat array with default values",
+},
+{
+ fShaderId: "simple-mat-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ renderColor: [0, 0, 0, 255],
+ uniforms: [
+ { name: 'a', functionName: 'uniformMatrix3fv', value: [
+ 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ ]},
+ { name: 'b', functionName: 'uniformMatrix3fv', value: [
+ 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 31, 32, 33, 34, 35, 36, 37, 30, 39,
+ ]},
+ ],
+ passMsg: "Simple vec array with different values",
+},
+{
+ fShaderId: "simple-mat-array-fs",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ render: true,
+ uniforms: [
+ { name: 'a', functionName: 'uniformMatrix3fv', value: [
+ 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ ]},
+ { name: 'b', functionName: 'uniformMatrix3fv', value: [
+ 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ ]},
+ ],
+ passMsg: "Simple vec array with same values",
+},
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-in-complex-expression.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-in-complex-expression.html
new file mode 100644
index 0000000000..9e55a0a016
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-in-complex-expression.html
@@ -0,0 +1,144 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array in complex expression test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderAndShortCircuits" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] plus() {
+ ++g;
+ return int[2](g, g);
+}
+
+bool minus() {
+ --g;
+ return false;
+}
+
+void main() {
+ int a[2] = int[2](0, 0);
+ // The function call must not be evaluated, since && short-circuits
+ minus() && (a == plus());
+ my_FragColor = vec4(0.0, ((g == -1) ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderOrShortCircuits" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] plus() {
+ ++g;
+ return int[2](g, g);
+}
+
+bool minus() {
+ --g;
+ return true;
+}
+
+void main() {
+ int a[2] = int[2](0, 0);
+ // The function call must not be evaluated, since || short-circuits.
+ minus() || (a == plus());
+ my_FragColor = vec4(0.0, ((g == -1) ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderTernaryOnlyEvaluatesOneOperand" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int g = 0;
+
+int[2] plus() {
+ ++g;
+ return int[2](g, g);
+}
+
+void main() {
+ int a[2] = int[2](0, 0);
+ // The function call must not be evaluated, since the condition is true.
+ (g == 0) ? true : (a == plus());
+ my_FragColor = vec4(0.0, ((g == 0) ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script id="fshaderSequenceSideEffectsAffectingComparedArrayContent" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int[2] func(int param) {
+ return int[2](param, param);
+}
+
+void main() {
+ int a[2];
+ for (int i = 0; i < 2; ++i) {
+ a[i] = 1;
+ }
+ int j = 0;
+ // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
+ // The function call that returns the array needs to be evaluated after ++j
+ // for the expression to return the correct value (true).
+ bool result = ((++j), (a == func(j)));
+ my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Arrays in complex expressions should work");
+debug("");
+debug("This test is targeted to stress syntax tree transformations that might need to be done in shader translation when the platform doesn't natively support arrays as return values.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderAndShortCircuits',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Expression where an array is returned from a function call inside an operand to && that doesn't get evaluated as result of short-circuiting"
+},
+{
+ fShaderId: 'fshaderOrShortCircuits',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Expression where an array is returned from a function call inside an operand to || that doesn't get evaluated as result of short-circuiting"
+},
+{
+ fShaderId: 'fshaderTernaryOnlyEvaluatesOneOperand',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Expression where an array is returned from a function call in an operand of a ternary operator that doesn't get evaluated"
+},
+{
+ fShaderId: 'fshaderSequenceSideEffectsAffectingComparedArrayContent',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Expression where first operand of a sequence operator has side effects which affect the second operand that returns an array'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-initialize-with-same-name-array.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-initialize-with-same-name-array.html
new file mode 100644
index 0000000000..cf81f84dd0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-initialize-with-same-name-array.html
@@ -0,0 +1,48 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array initializer that references an array with the same name</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderInitArray" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ float foo[2] = float[2](1.0, 1.0);
+ {
+ float foo[2] = foo;
+ my_FragColor = vec4(0.0, foo[0], 0.0, foo[1]);
+ }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Initializing an array with another array with the same name should work. See GLSL ES 3.00.6 section 4.2.2.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderInitArray',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Array that is initialized with an array of the same name from an outer scope'
+},
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-length-side-effects.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-length-side-effects.html
new file mode 100644
index 0000000000..fb32153c66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/array-length-side-effects.html
@@ -0,0 +1,100 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL: test that length() method called on a complex expression works</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderLengthOfAssignment" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ int a[3] = int[3](1, 2, 3);
+ int b[3] = int[3](4, 5, 6);
+ int c = (a = b).length();
+ if (c == 3 && a[0] == 4 && a[1] == 5 && a[2] == 6) {
+ my_FragColor = vec4(0, 1, 0, 1);
+ } else {
+ my_FragColor = vec4(1, 0, 0, 1);
+ }
+}
+</script>
+<script id="fshaderLengthOfFunctionCall" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+int sideEffectCounter = 0;
+
+int[2] func() {
+ ++sideEffectCounter;
+ int a[2];
+ return a;
+}
+
+void main() {
+ int b = (func()).length();
+ if (sideEffectCounter == 1 && b == 2) {
+ my_FragColor = vec4(0, 1, 0, 1);
+ } else {
+ my_FragColor = vec4(1, 0, 0, 1);
+ }
+}
+</script>
+<script id="fshaderLengthOfConstructor" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+void main() {
+ int a = (int[1](0)).length();
+ if (a == 1) {
+ my_FragColor = vec4(0, 1, 0, 1);
+ } else {
+ my_FragColor = vec4(1, 0, 0, 1);
+ }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+debug('length() method is allowed to be called on arbitrary expressions returning arrays. ESSL 3.00 section 5.9 says that length is allowed on "array names", but ESSL 3.20 has newer, clarified wording that says that it is allowed for "arrays". This was always the intent of the spec.');
+GLSLConformanceTester.runRenderTests([
+ {
+ fShaderId: "fshaderLengthOfAssignment",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Fragment shader which tries to evaluate the length of an assignment operation should succeed."
+ },
+ {
+ fShaderId: "fshaderLengthOfFunctionCall",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Fragment shader which tries to evaluate the length of a return value should succeed."
+ },
+ {
+ fShaderId: "fshaderLengthOfConstructor",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Fragment shader which tries to evaluate the length of a newly constructed array should succeed."
+ }
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/bool-type-cast-bug-uint-ivec-uvec.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/bool-type-cast-bug-uint-ivec-uvec.html
new file mode 100644
index 0000000000..88af6137c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/bool-type-cast-bug-uint-ivec-uvec.html
@@ -0,0 +1,368 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify uint(bool), ivec(bvec), and uvec(bvec) work correctly (Mac AMD driver bug)</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader-uint-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out uint uvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ uvalue = uint(bvalue);
+}
+</script>
+<script id="fshader-uint-1" type="x-shader/x-fragment">#version 300 es
+flat in uint uvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (uvalue == 1u)
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == 0u)
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-simple" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-uint-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ uint uvalue = uint(bvalue);
+
+ if (uvalue == 1u)
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == 0u)
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-ivec2-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out ivec2 ivalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ ivalue = ivec2(bvec2(bvalue, bvalue));
+}
+</script>
+<script id="fshader-ivec2-1" type="x-shader/x-fragment">#version 300 es
+flat in ivec2 ivalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (ivalue == ivec2(1, 1))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == ivec2(0, 0))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader-ivec2-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ ivec2 ivalue = ivec2(bvec2(bvalue, bvalue));
+
+ if (ivalue == ivec2(1, 1))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == ivec2(0, 0))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-uvec2-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out uvec2 uvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ uvalue = uvec2(bvec2(bvalue, bvalue));
+}
+</script>
+<script id="fshader-uvec2-1" type="x-shader/x-fragment">#version 300 es
+flat in uvec2 uvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (uvalue == uvec2(1u, 1u))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == uvec2(0u, 0u))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader-uvec2-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ uvec2 uvalue = uvec2(bvec2(bvalue, bvalue));
+
+ if (uvalue == uvec2(1u, 1u))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == uvec2(0u, 0u))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-ivec3-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out ivec3 ivalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ ivalue = ivec3(bvec3(bvalue, bvalue, bvalue));
+}
+</script>
+<script id="fshader-ivec3-1" type="x-shader/x-fragment">#version 300 es
+flat in ivec3 ivalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (ivalue == ivec3(1, 1, 1))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == ivec3(0, 0, 0))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader-ivec3-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ ivec3 ivalue = ivec3(bvec3(bvalue, bvalue, bvalue));
+
+ if (ivalue == ivec3(1, 1, 1))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == ivec3(0, 0, 0))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-uvec3-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out uvec3 uvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ uvalue = uvec3(bvec3(bvalue, bvalue, bvalue));
+}
+</script>
+<script id="fshader-uvec3-1" type="x-shader/x-fragment">#version 300 es
+flat in uvec3 uvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (uvalue == uvec3(1u, 1u, 1u))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == uvec3(0u, 0u, 0u))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader-uvec3-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ uvec3 uvalue = uvec3(bvec3(bvalue, bvalue, bvalue));
+
+ if (uvalue == uvec3(1u, 1u, 1u))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == uvec3(0u, 0u, 0u))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-ivec4-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out ivec4 ivalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ ivalue = ivec4(bvec4(bvalue, bvalue, bvalue, bvalue));
+}
+</script>
+<script id="fshader-ivec4-1" type="x-shader/x-fragment">#version 300 es
+flat in ivec4 ivalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (ivalue == ivec4(1, 1, 1, 1))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == ivec4(0, 0, 0, 0))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader-ivec4-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ ivec4 ivalue = ivec4(bvec4(bvalue, bvalue, bvalue, bvalue));
+
+ if (ivalue == ivec4(1, 1, 1, 1))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (ivalue == ivec4(0, 0, 0, 0))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-uvec4-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out uvec4 uvalue;
+uniform bool bvalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ uvalue = uvec4(bvec4(bvalue, bvalue, bvalue, bvalue));
+}
+</script>
+<script id="fshader-uvec4-1" type="x-shader/x-fragment">#version 300 es
+flat in uvec4 uvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (uvalue == uvec4(1u, 1u, 1u, 1u))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == uvec4(0u, 0u, 0u, 0u))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader-uvec4-2" type="x-shader/x-fragment">#version 300 es
+uniform bool bvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ uvec4 uvalue = uvec4(bvec4(bvalue, bvalue, bvalue, bvalue));
+
+ if (uvalue == uvec4(1u, 1u, 1u, 1u))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (uvalue == uvec4(0u, 0u, 0u, 0u))
+ myFragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script type="application/javascript">
+"use strict";
+description("Verify uint(bool), ivec(bvec), and uvec(bvec) work correctly");
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas", undefined, 2);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ wtu.setupUnitQuad(gl);
+
+ var testCases = [
+ { vshader: "vshader-uint-1", fshader: "fshader-uint-1", desc: "vertex shader uint" },
+ { vshader: "vshader-simple", fshader: "fshader-uint-2", desc: "fragment shader uint" },
+ { vshader: "vshader-ivec2-1", fshader: "fshader-ivec2-1", desc: "vertex shader ivec2" },
+ { vshader: "vshader-simple", fshader: "fshader-ivec2-2", desc: "fragment shader ivec2" },
+ { vshader: "vshader-uvec2-1", fshader: "fshader-uvec2-1", desc: "vertex shader uvec2" },
+ { vshader: "vshader-simple", fshader: "fshader-uvec2-2", desc: "fragment shader uvec2" },
+ { vshader: "vshader-ivec3-1", fshader: "fshader-ivec3-1", desc: "vertex shader ivec3" },
+ { vshader: "vshader-simple", fshader: "fshader-ivec3-2", desc: "fragment shader ivec3" },
+ { vshader: "vshader-uvec3-1", fshader: "fshader-uvec3-1", desc: "vertex shader uvec3" },
+ { vshader: "vshader-simple", fshader: "fshader-uvec3-2", desc: "fragment shader uvec3" },
+ { vshader: "vshader-ivec4-1", fshader: "fshader-ivec4-1", desc: "vertex shader ivec4" },
+ { vshader: "vshader-simple", fshader: "fshader-ivec4-2", desc: "fragment shader ivec4" },
+ { vshader: "vshader-uvec4-1", fshader: "fshader-uvec4-1", desc: "vertex shader uvec4" },
+ { vshader: "vshader-simple", fshader: "fshader-uvec4-2", desc: "fragment shader uvec4" },
+ ];
+
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ var test = testCases[idx];
+
+ debug("");
+ var program = wtu.setupProgram(gl, [test.vshader, test.fshader], ["aPosition"]);
+ if (!program) {
+ testFailed("Fail to set up program");
+ } else {
+ var uniformLoc = gl.getUniformLocation(program, 'bvalue');
+ debug("Testing " + test.desc + " with false");
+ gl.uniform1i(uniformLoc, 0);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ debug("Testing " + test.desc + " with true");
+ gl.uniform1i(uniformLoc, 1);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255]);
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from testing");
+ }
+ }
+};
+
+test();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compare-structs-containing-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compare-structs-containing-arrays.html
new file mode 100644
index 0000000000..4748ae5153
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compare-structs-containing-arrays.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL array equality test with structs containing arrays</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!--
+Structure array comparisons are detailed in the ESSL 3.00 spec section 5.7
+-->
+<script id="fshader-same-struct" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+
+struct MyStruct {
+ bool a[2];
+};
+
+void main() {
+ MyStruct b;
+ b.a[0] = true;
+ b.a[1] = false;
+
+ MyStruct c;
+ c.a[0] = true;
+ c.a[1] = false;
+
+ color = b == c ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);
+}
+</script>
+<script id="fshader-different-struct" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+
+struct MyStruct {
+ bool a[2];
+};
+
+void main() {
+ MyStruct b;
+ b.a[0] = true;
+ b.a[1] = true;
+
+ MyStruct c;
+ c.a[0] = true;
+ c.a[1] = false;
+
+ color = b != c ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Comparing structs containing arrays should work.");
+debug("");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshader-same-struct',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Comparing two structs containing arrays with the same values should equal to each other'
+},
+{
+ fShaderId: 'fshader-different-struct',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Comparing two structs containing arrays with different values should not equal to each other'
+},
+], 2);
+
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compound-assignment-type-combination.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compound-assignment-type-combination.html
new file mode 100644
index 0000000000..76d70efd7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/compound-assignment-type-combination.html
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Result type should match the l-value type in compound assignment</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+<script src="../../js/tests/compound-assignment-type-combination.js"></script>
+</head>
+<body onload="runTest(2)">
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+description();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-array-init.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-array-init.html
new file mode 100644
index 0000000000..c992c03b63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-array-init.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Constant array initialization test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderGlobalConstArray" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+
+const vec4 constants[2] = vec4[] (
+ vec4(0.6, 0.3, 0.0, 3.0),
+ vec4(-0.6, 0.7, 0.0, -2.0)
+);
+
+void main()
+{
+ my_FragColor = constants[0] + constants[1];
+ return;
+}
+</script>
+<script id="fshaderGlobalConstArrayWithReferenceToConstArray" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+
+const vec4 constants[2] = vec4[] (
+ vec4(0.6, 0.3, 0.0, 3.0),
+ vec4(-0.6, 0.7, 0.0, -2.0)
+);
+
+const vec4 constants2[2] = vec4[] (
+ constants[1],
+ constants[0]
+);
+
+void main()
+{
+ my_FragColor = constants2[0] + constants2[1];
+ return;
+}
+</script>
+<script id="fshaderGlobalConstArrayInitializedToConstArray" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+
+const vec4 constants[2] = vec4[] (
+ vec4(0.6, 0.3, 0.0, 3.0),
+ vec4(-0.6, 0.7, 0.0, -2.0)
+);
+
+const vec4 constants2[2] = constants;
+
+void main()
+{
+ my_FragColor = constants2[0] + constants2[1];
+ return;
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("Test initializing a constant global array");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderGlobalConstArray',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Global constant array with vec4 constructors and literals in the initializer"
+},
+{
+ fShaderId: 'fshaderGlobalConstArrayWithReferenceToConstArray',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Global constant array which indexes another global constant array in the initializer"
+},
+{
+ fShaderId: 'fshaderGlobalConstArrayInitializedToConstArray',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Global constant array initialized to another global constant array"
+}
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-struct-from-array-as-function-parameter.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-struct-from-array-as-function-parameter.html
new file mode 100644
index 0000000000..e67e0e0dd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/const-struct-from-array-as-function-parameter.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL passing struct from a const array into a function parameter bug</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fShaderTest" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+struct S { float member; };
+
+const S s[2] = S[]( S(1.), S(2.));
+
+bool useStruct( S s) { return s.member > 0.0; }
+
+out vec4 outColor;
+
+void main( void )
+{
+ outColor = vec4(0.0, 0.0, 0.0, 1.0);
+ for (int i = 0; i < 2; ++i) {
+ if (useStruct(s[i])) {
+ outColor.g++;
+ }
+ }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+// Covers bug:
+// http://crbug.com/871434
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fShaderTest',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Passing a struct from a dynamically indexed const array into a non-const function parameter should work.',
+ render: true
+}
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/float-parsing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/float-parsing.html
new file mode 100644
index 0000000000..fcd4d8a731
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/float-parsing.html
@@ -0,0 +1,167 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Float parsing corner cases</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderParsedFloatOverflowToInfinity" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ // Out-of-range floats should overflow to infinity
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity"
+ float correct = isinf(1.0e40) ? 1.0 : 0.0;
+ my_FragColor = vec4(0.0, correct, 0.0, 1.0);
+}
+</script>
+<script id="fshaderParsedFloatUnderflowToZero" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "A value with a magnitude too small to be represented as a mantissa and exponent is converted to zero."
+ // 1.0e-50 is small enough that it can't even be stored as subnormal.
+ float correct = (1.0e-50 == 0.0) ? 1.0 : 0.0;
+ my_FragColor = vec4(0.0, correct, 0.0, 1.0);
+}
+</script>
+<script id="fshaderParsedFloatSmallMantissa" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "There is no limit on the number of digits in any digit-sequence."
+ // The below float string has 100 zeros after the decimal point, but represents 1.0.
+ float x = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e101;
+ my_FragColor = vec4(0.0, x, 0.0, 1.0);
+}
+</script>
+<script id="fshaderParsedFloatLargeMantissa" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "There is no limit on the number of digits in any digit-sequence."
+ // The below float string has 100 zeros, but represents 1.0.
+ float x = 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0e-100;
+ my_FragColor = vec4(0.0, x, 0.0, 1.0);
+}
+</script>
+<script id="fshaderParsedFloatExponentAboveMaxInt" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ // Out-of-range floats should overflow to infinity
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity"
+ float correct = isinf(1.0e2147483649) ? 1.0 : 0.0;
+ my_FragColor = vec4(0.0, correct, 0.0, 1.0);
+}
+</script>
+<script id="fshaderNonConstFloatIsInfinity" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+uniform float u; // Assumed to have the default value 0.0
+
+void main()
+{
+ // Out-of-range floats should overflow to infinity
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity"
+ float f = 1.0e2048 - u;
+ float correct = (isinf(f) && f > 0.0) ? 1.0 : 0.0;
+ my_FragColor = vec4(0.0, correct, 0.0, 1.0);
+}
+</script>
+<script id="fshaderNonConstFloatIsNegativeInfinity" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+
+uniform float u; // Assumed to have the default value 0.0
+
+void main()
+{
+ // Out-of-range floats should overflow to infinity
+ // GLSL ES 3.00.6 section 4.1.4 Floats:
+ // "If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity"
+ float f = -1.0e2048 + u;
+ float correct = (isinf(f) && f < 0.0) ? 1.0 : 0.0;
+ my_FragColor = vec4(0.0, correct, 0.0, 1.0);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description();
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderParsedFloatOverflowToInfinity',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Floats of too large magnitude should be converted infinity."
+},
+{
+ fShaderId: 'fshaderParsedFloatUnderflowToZero',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Floats of too small magnitude should be converted to zero."
+},
+{
+ fShaderId: 'fshaderParsedFloatSmallMantissa',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Number of digits in any digit-sequence is not limited - test with a small mantissa and large exponent."
+},
+{
+ fShaderId: 'fshaderParsedFloatLargeMantissa',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Number of digits in any digit-sequence is not limited - test with a large mantissa and negative exponent."
+},
+{
+ fShaderId: 'fshaderParsedFloatExponentAboveMaxInt',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Test that an exponent that slightly overflows signed 32-bit int range works."
+},
+{
+ fShaderId: 'fshaderNonConstFloatIsInfinity',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Test that a non-constant float that has infinity as a value is processed correctly by isinf()."
+},
+{
+ fShaderId: 'fshaderNonConstFloatIsNegativeInfinity',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "Test that a non-constant float that has negative infinity as a value is processed correctly by isinf()."
+}
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forbidden-operators.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forbidden-operators.html
new file mode 100644
index 0000000000..ec5c7c9bfb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forbidden-operators.html
@@ -0,0 +1,124 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests - Unsupported variants of operators</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshader-array-ternary-operator" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+void main()
+{
+ float a[3];
+ float b[3];
+ float c[3] = true ? a : b;
+}
+</script>
+<script id="fshader-struct-array-ternary-operator" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+struct MyStruct {
+ bool a[3];
+};
+
+void main()
+{
+ MyStruct b;
+ MyStruct c;
+ MyStruct d = true ? b : c;
+}
+</script>
+<script id="fshader-void-ternary-operator" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+void foo() {}
+
+void main()
+{
+ true ? foo() : foo();
+}
+</script>
+<script id="fshader-array-sequence-operator" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+void main()
+{
+ float a[3];
+ float b[3] = (true, a);
+}
+</script>
+<script id="fshader-struct-array-sequence-operator" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+struct MyStruct {
+ bool a[3];
+};
+
+void main()
+{
+ MyStruct b;
+ MyStruct c = (true, b);
+}
+</script>
+<script id="fshader-void-sequence-operator" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+void foo() {}
+
+void main()
+{
+ (foo(), foo());
+}
+</script>
+<script>
+"use strict";
+description("Check unsupported variants of operators.");
+
+// WebGL 2.0 spec section "Unsupported variants of GLSL ES 3.00 operators"
+
+GLSLConformanceTester.runTests([
+{ fShaderId: 'fshader-array-ternary-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using ternary operators with arrays is not allowed",
+},
+{ fShaderId: 'fshader-struct-array-ternary-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using ternary operators with structs containing arrays is not allowed",
+},
+{ fShaderId: 'fshader-void-ternary-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using ternary operators with void is not allowed",
+},
+{ fShaderId: 'fshader-array-sequence-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using sequence operators with arrays is not allowed",
+},
+{ fShaderId: 'fshader-struct-array-sequence-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using sequence operators with structs containing arrays is not allowed",
+},
+{ fShaderId: 'fshader-void-sequence-operator',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Using sequence operators with void is not allowed",
+}
+], 2);
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forward-declaration.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forward-declaration.html
new file mode 100644
index 0000000000..b3afcb846d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/forward-declaration.html
@@ -0,0 +1,90 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL 3.00 forward declaration test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderForwardDecl" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+
+// Forward declaration. Breaks on Pixel C due to flattening of
+// precision qualifiers. It seems the GLSL compiler can't handle the
+// precision qualifier on the return value.
+float identity(float val);
+
+float identity(float val) {
+ return val;
+}
+
+void main(void) {
+ gl_Position = vec4(identity(1.0), 0.0, 0.0, 1.0);
+}
+</script>
+<script id="vertexShader" type="x-shader/x-vertex">#version 300 es
+void main(void) {
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+void main(void) {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="fragmentShaderForwardDecl" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+// Forward declaration. Breaks on Pixel C due to flattening of
+// precision qualifiers. It seems the GLSL compiler can't handle the
+// precision qualifier on the return value.
+float identity(float val);
+
+float identity(float val) {
+ return val;
+}
+
+out vec4 my_FragColor;
+void main(void) {
+ my_FragColor = vec4(0.0, identity(1.0), 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Forward declarations of functions should succeed.");
+
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "vertexShaderForwardDecl",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with forward declaration must pass",
+ },
+ {
+ vShaderId: "vertexShader",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderForwardDecl",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "fragment shader with forward declaration must pass",
+ },
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/frag-depth.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/frag-depth.html
new file mode 100644
index 0000000000..afbbfad741
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/frag-depth.html
@@ -0,0 +1,157 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Frag Depth Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing fragment depth writing -->
+
+<!-- Shader omitting the required #version -->
+<script id="fragmentShaderESSL1" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = 1.0;
+}
+</script>
+<!-- Shader with required #version -->
+<script id="fragmentShaderESSL3" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = 1.0;
+}
+</script>
+<!-- Shader using the EXT suffix -->
+<script id="fragmentShaderESSL3EXT" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepthEXT = 1.0;
+}
+</script>
+<!-- Shaders to link with test fragment shaders -->
+<script id="vertexShaderESSL1" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+<script id="vertexShaderESSL3" type="x-shader/x-vertex">#version 300 es
+in vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+
+<!-- Shader to test output -->
+<script id="outputFragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform float uDepth;
+
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = uDepth;
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies the functionality of setting fragment depth in a shader.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runShaderTests();
+ debug("");
+ runOutputTests();
+}
+
+function runShaderTests() {
+ debug("");
+ debug("Testing various shader compiles");
+
+ // Always expect ESSL1 shaders to fail
+ var fragmentProgramESSL1 = wtu.loadProgramFromScriptExpectError(gl, "vertexShaderESSL1", "fragmentShaderESSL1");
+ if (fragmentProgramESSL1) {
+ testFailed("gl_FragDepth allowed in ESSL1 shader - should be disallowed");
+ } else {
+ testPassed("gl_FragDepth disallowed in ESSL1 shader");
+ }
+
+ // Try to compile a shader using the built-ins that should only succeed if enabled
+ var testFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "vertexShaderESSL3", "fragmentShaderESSL3");
+ if (testFragmentProgram) {
+ testPassed("gl_FragDepth allowed in ESSL3 shader");
+ } else {
+ testFailed("gl_FragDepth disallowed in ESSL3 shader");
+ }
+
+ var testFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "vertexShaderESSL3", "fragmentShaderESSL3EXT");
+ if (testFragmentProgram) {
+ testFailed("gl_FragDepthEXT allowed in ESSL3 shader - should only allow gl_FragDepth");
+ } else {
+ testPassed("gl_FragDepthEXT disallowed in ESSL3 shader");
+ }
+}
+
+function runOutputTests() {
+ debug("Testing rendering results from writing to gl_FragData");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ // Enable depth testing with a clearDepth of 0.5
+ // This makes it so that fragments are only rendered when
+ // gl_FragDepth is < 0.5
+ gl.clearDepth(0.5);
+ gl.enable(gl.DEPTH_TEST);
+
+ var positionLoc = 0;
+ var texcoordLoc = 1;
+ var program = wtu.setupProgram(gl, ["vertexShaderESSL3", "outputFragmentShader"], ['vPosition'], [0]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+ var depthUniform = gl.getUniformLocation(program, "uDepth");
+
+ // Draw 1: Greater than clear depth
+ gl.uniform1f(depthUniform, 1.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 255, 255, 255]);
+
+ // Draw 2: Less than clear depth
+ gl.uniform1f(depthUniform, 0.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255]);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/fragment-shader-loop-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/fragment-shader-loop-crash.html
new file mode 100644
index 0000000000..a171b94e26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/fragment-shader-loop-crash.html
@@ -0,0 +1,72 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Fragment shader containing loop should not crash</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+precision highp float;
+out vec2 v_tex_coord;
+uniform mat4 matrix;
+
+void main() {
+ v_tex_coord = vec2(0.0, 0.0);
+ gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+
+in vec2 v_tex_coord;
+out vec4 out_color;
+
+uniform sampler2D texture_1;
+uniform vec2 resolution;
+
+vec4 do_loops(vec4 z)
+{
+ vec4 v[16];
+ for (int i = 0; i < 16; i++)
+ {
+ v[i] = z;
+ }
+ return v[1];
+}
+
+void main() {
+ out_color = do_loops(vec4(0.2, 0.4, 0.6, 1.0)) - texture(texture_1, v_tex_coord);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+const wtu = WebGLTestUtils;
+const tests = [
+ {
+ vShaderSource: wtu.getScript('vshader'),
+ fShaderSource: wtu.getScript('fshader'),
+ vShaderSuccess: true,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Fragment shader containing a simple loop should compile and link'
+ }
+];
+
+GLSLConformanceTester.runTests(tests, 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/gradient-in-discontinuous-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/gradient-in-discontinuous-loop.html
new file mode 100644
index 0000000000..db13d61f6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/gradient-in-discontinuous-loop.html
@@ -0,0 +1,75 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Short circuit in loop condition test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertex-shader" type="x-shader/x-vertex">#version 300 es
+ precision highp float;
+ in vec4 aPosition;
+
+ void main() {
+ gl_Position = aPosition;
+ }
+</script>
+<script id="fragment-shader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+precision highp int;
+
+uniform vec4 iMouse;
+uniform sampler2D iChannel0;
+
+float map(float p)
+{
+ return texture(iChannel0, vec2(p, p), 0.0).y;
+}
+
+out vec4 outColor;
+
+void main(void)
+{
+ float sum = 0.0;
+
+ for(int i=0; i<1000; i++)
+ {
+ if( sum > 0.99 ) break;
+ float p = iMouse.x + gl_FragCoord.x;
+ sum = map(p);
+ }
+
+ outColor = vec4(sum);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("Test an HLSL compiler freeze on a gradient inside a discontinuous loop.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+wtu.setupUnitQuad(gl);
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ var program = wtu.setupProgram(gl, ["vertex-shader", "fragment-shader"], ['aPosition'], undefined, true);
+ if (!program) {
+ testFailed('Program compilation failed');
+ }
+}
+var successfullyParsed = true;
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/input-with-interpotaion-as-lvalue.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/input-with-interpotaion-as-lvalue.html
new file mode 100644
index 0000000000..fa6d87cd12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/input-with-interpotaion-as-lvalue.html
@@ -0,0 +1,83 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Negative tests for writting to a shader input with interpolation qualifier</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!--
+According to ESSL 3.00.6 section 4.3.4:
+"Variables declared as in or centroid in may not be written to during shader execution.",
+these tests ensure that a compile error is generated when using a shader input with interpolation qualifier as l-value.
+-->
+<script type="application/javascript">
+"use strict";
+description();
+
+var vertexShaderTemplate = [
+ '#version 300 es',
+ '$(InterpolationQualifier) out float v_float_varying;',
+ 'void main()',
+ '{',
+ ' v_float_varying = 1.0;',
+ ' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);',
+ '}'
+].join('\n');
+
+var fragmentShaderTemplate = [
+ '#version 300 es',
+ 'precision mediump float;',
+ '$(InterpolationQualifier) in float v_float_varying;',
+ 'out vec4 my_color;',
+ 'void main()',
+ '{',
+ ' v_float_varying = 1.0;',
+ ' my_color = vec4(1.0, 0.0, 0.0, v_float_varying);',
+ '}'
+].join('\n');
+
+var errorMessageTemplate = "Writting to shader inputs with '$(InterpolationQualifier)' qualifier must fail";
+
+var testDataList = [
+{
+ InterpolationQualifier: 'flat'
+},
+{
+ InterpolationQualifier: 'smooth'
+},
+{
+ InterpolationQualifier: 'centroid'
+}
+];
+
+var wtu = WebGLTestUtils;
+
+var tests = [];
+for (var i = 0; i < testDataList.length; ++i) {
+ tests.push({
+ vShaderSource: wtu.replaceParams(vertexShaderTemplate, testDataList[i]),
+ vShaderSuccess: true,
+ fShaderSource: wtu.replaceParams(fragmentShaderTemplate, testDataList[i]),
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: wtu.replaceParams(errorMessageTemplate, testDataList[i])
+ });
+}
+
+GLSLConformanceTester.runTests(tests, 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-default-precision.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-default-precision.html
new file mode 100644
index 0000000000..375c95610c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-default-precision.html
@@ -0,0 +1,71 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Default precision qualifiers should only work with int, float and sampler types</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!-- See ESSL 3.00 section 4.5.4 -->
+<script id="precisionVec" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+precision mediump vec2;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="precisionVoid" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+precision mediump void;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="precisionUint" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+precision mediump uint;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ fShaderId: "precisionVec",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "default precision qualifier shouldn't work with vec2"
+ },
+ {
+ fShaderId: "precisionVoid",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "default precision qualifier shouldn't work with void"
+ },
+ {
+ fShaderId: "precisionUint",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "default precision qualifier shouldn't work with uint"
+ }
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-invariant.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-invariant.html
new file mode 100644
index 0000000000..f0d2b46ad1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/invalid-invariant.html
@@ -0,0 +1,88 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Negative tests for the use of the invariant qualifier and pragma</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderInvariant" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+invariant out vec4 v_varying;
+
+void main()
+{
+ v_varying = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position = v_varying;
+}
+</script>
+<script id="fragmentShaderVariant" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+
+in vec4 v_varying;
+out vec4 my_color;
+
+void main()
+{
+ my_color = v_varying;
+}
+</script>
+<script id="fragmentShaderInputInvariant" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+
+invariant in vec4 v_varying;
+out vec4 my_color;
+
+void main()
+{
+ my_color = v_varying;
+}
+</script>
+<script id="fragmentShaderGlobalInvariant" type="text/something-not-javascript">#version 300 es
+#pragma STDGL invariant(all)
+precision mediump float;
+
+in vec4 v_varying;
+out vec4 my_color;
+
+void main()
+{
+ my_color = v_varying;
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderGlobalInvariant",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "fragment shader with global invariant pragma must fail",
+ },
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderInputInvariant",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "fragment shader with an input variable which is invariant must fail",
+ },
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/loops-with-side-effects.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/loops-with-side-effects.html
new file mode 100644
index 0000000000..c8a977b8ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/loops-with-side-effects.html
@@ -0,0 +1,211 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Loops and side-effects test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+
+<!-- Variations on counter functions that used to give incorrect result on OSX 10.9 -->
+<script id="counter0" type="x-shader/x-shader">
+bool s0 = false;
+while(true) {
+ bool bar = s0;
+ if (!bar) {
+ bar = i < 3;
+ i = i + 1;
+ }
+ bool foo = !bar;
+ if (foo) {
+ break;
+ }
+ s0 = false;
+ n ++;
+}
+return n;
+</script>
+<script id="counter1" type="x-shader/x-shader">
+while(true) {
+ bool bar = i < 3;
+ i = i + 1;
+ bool foo = !bar;
+ if (foo) {
+ break;
+ }
+ n ++;
+}
+return n;
+</script>
+<script id="counter2" type="x-shader/x-shader">
+bool s0 = true;
+while(true) {
+ bool bar = s0;
+ if (!bar) {
+ bar = i < 3;
+ i = i + 1;
+ }
+ bool foo = !bar;
+ if (foo) {
+ break;
+ }
+ s0 = false;
+ n ++;
+}
+return n;
+</script>
+<script id="counter3" type="x-shader/x-shader">
+bool s0 = true;
+while(true) {
+ bool bar = s0;
+ if (!bar) {
+ bar = i++ < 3;
+ }
+ bool foo = !bar;
+ if (foo) {
+ break;
+ }
+ s0 = false;
+ n ++;
+}
+return n;
+</script>
+<script id="counter4" type="x-shader/x-shader">
+bool s0 = true;
+while(true) {
+ bool bar = s0 || (i++ < 3);
+ bool foo = !bar;
+ if (foo) {
+ break;
+ }
+ s0 = false;
+ n ++;
+}
+return n;
+</script>
+<script id="counter5" type="x-shader/x-shader">
+bool s0 = true;
+while(true) {
+ if (!(s0 || (i++ < 3))) {
+ break;
+ }
+ s0 = false;
+ n ++;
+}
+return n;
+</script>
+<script id="counter6" type="x-shader/x-shader">
+bool s0 = true;
+while(s0 || (i++ < 3)) {
+ s0 = false;
+ n ++;
+}
+return n;
+</script>
+
+<script id="counter7" type="x-shader/x-shader">
+do {
+ n++;
+} while (i++ < 3);
+return n;
+</script>
+<script>
+"use strict";
+description("This test checks for bugs related to loops and side-effects.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ for (var i = 0; i < 8; i++) {
+ tryCounter(document.getElementById("counter" + i).text);
+ debug("");
+ }
+}
+
+function evaluateCounter(source) {
+ var jsSource = "(function(n, i) {" +
+ source.split("bool").join("var") +
+ "})(0, 0)";
+
+ return eval(jsSource);
+}
+
+function makeFSSource(source) {
+ var fsSource =
+ "#version 300 es\n" +
+ "precision highp float;\n" +
+ "in float vertexCounter;\n" +
+ "uniform int uVertZero;\n" +
+ "uniform int uReference;\n" +
+ "out vec4 fragColor;\n" +
+ "int counter(int n, int i) {\n" +
+ source +
+ "}\n" +
+ "void main() {\n" +
+ " fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n" +
+ " fragColor.r = float(counter(uVertZero, uVertZero) == uReference);\n" +
+ " fragColor.g = float(int(vertexCounter) == uReference);\n" +
+ "}\n";
+ return fsSource;
+}
+
+function makeVSSource(source) {
+ var vsSource =
+ "#version 300 es\n" +
+ "out float vertexCounter;\n" +
+ "uniform int uFragZero;\n" +
+ "in vec4 vPosition;\n" +
+ "int counter(int n, int i) {\n" +
+ source +
+ "}\n" +
+ "void main() {\n" +
+ " gl_Position = vPosition;\n" +
+ " vertexCounter = float(counter(uFragZero, uFragZero));\n" +
+ "}\n";
+ return vsSource;
+}
+
+function tryCounter(source) {
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ var program = wtu.setupProgram(gl, [makeVSSource(source), makeFSSource(source)], ['vPosition'], [0], true);
+
+ gl.uniform1i(gl.getUniformLocation(program, "uVertZero"), 0);
+ gl.uniform1i(gl.getUniformLocation(program, "uFragZero"), 0);
+
+ var reference = evaluateCounter(source);
+ gl.uniform1i(gl.getUniformLocation(program, "uReference"), reference);
+
+ gl.useProgram(program);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 0]);
+ wtu.checkCanvas(gl, [255, 255, 0, 255]);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major-dynamic-indexing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major-dynamic-indexing.html
new file mode 100644
index 0000000000..ec6a9bbd1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major-dynamic-indexing.html
@@ -0,0 +1,118 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Dynamically-indexed row-major matrix test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderIndexRowMajorMatrixArrayInUniformBlock" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+layout(row_major) uniform a {
+ mat4 u_mats[1];
+};
+
+void main() {
+ float f = u_mats[u_zero + 0][2][1];
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderRowMatrixIndexedByRowMatrixInUniformBlock" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+uniform Stuff {
+ layout(row_major) mat4 u_mat[3];
+ layout(row_major) mat4 u_ndx[3];
+} stuff;
+
+
+out vec4 my_FragColor;
+
+void main() {
+ vec4 row = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2];
+ my_FragColor = row == vec4(9, 10, 11, 12) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Indexing row-major matrices within a uniform block should work");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderIndexRowMajorMatrixArrayInUniformBlock',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: '',
+ uniformBlocks: [{name: "a", value: new Float32Array([
+ 0, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ])}],
+},
+{
+ fShaderId: 'fshaderRowMatrixIndexedByRowMatrixInUniformBlock',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: '',
+ uniformBlocks: [{name: "Stuff", value: new Float32Array([
+ // mat4 u_mat[3]
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16,
+
+ // +-- we should be pulling out this column
+ // |
+ // V
+ 1, 5, 9, 13,
+ 2, 6, 10, 14,
+ 3, 7, 11, 15,
+ 4, 8, 12, 16,
+
+ 2, 10, 18, 22,
+ 4, 12, 20, 28,
+ 6, 14, 22, 30,
+ 8, 16, 24, 32,
+
+ // mat4 u_ndx[3]
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+
+ 0, 0, 0, 0,
+ 0, 0, 0, 2,
+ 0, 0, 0, 0,
+ 0, 1, 0, 0,
+ // ^
+ // |
+ // +-- we should be reading this value as an index into u_mat
+
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ])}],
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major.html
new file mode 100644
index 0000000000..3c56bdacf1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/matrix-row-major.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Row-major matrix test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderUniformMatrixRowMajor" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out highp vec4 my_FragColor;
+layout(std140, row_major) uniform b {
+ mat4x3 m;
+};
+void main() {
+ // If the matrix is interpreted as row-major, then the translation components will be 0,1,0, or solid green.
+ my_FragColor = mat4(m) * vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Row-major matrix layouts should work.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderUniformMatrixRowMajor',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: '',
+ uniformBlocks: [{name: "b", value: new Float32Array([
+ 0, 0, 0, 0, // Red
+ 0, 0, 0, 1, // Green
+ 0, 0, 0, 0, // Blue
+ ])}]
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/misplaced-version-directive.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/misplaced-version-directive.html
new file mode 100644
index 0000000000..e0168c5830
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/misplaced-version-directive.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>#version directive should be on the very first line of a OpenGL ES Shading Language 3.00 shader</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!-- Version directive should be on the very first line in ESSL 3, see ESSL 3 section 3.3 -->
+<script id="VertexShaderCommentBeforeVersion" type="x-shader/x-vertex">// This shader is wrong, this is the first line that should have version
+#version 300 es
+precision mediump float;
+in vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="VertexShaderNewlineBeforeVersion" type="x-shader/x-vertex">
+#version 300 es
+precision mediump float;
+in vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="CorrectVertexShader" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+in vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="FragmentShaderCommentBeforeVersion" type="x-shader/x-fragment">// This shader is wrong, this is the first line that should have version
+#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="FragmentShaderNewlineBeforeVersion" type="x-shader/x-fragment">
+#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="CorrectFragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "VertexShaderNewlineBeforeVersion",
+ vShaderSuccess: false,
+ fShaderId: "CorrectFragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Vertex shader with a newline before the version directive should fail."
+ },
+ {
+ vShaderId: "VertexShaderCommentBeforeVersion",
+ vShaderSuccess: false,
+ fShaderId: "CorrectFragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Vertex shader with a comment before the version directive should fail."
+ },
+ {
+ vShaderId: "CorrectVertexShader",
+ vShaderSuccess: true,
+ fShaderId: "FragmentShaderCommentBeforeVersion",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Fragment shader with a comment before the version directive should fail."
+ },
+ {
+ vShaderId: "CorrectVertexShader",
+ vShaderSuccess: true,
+ fShaderId: "FragmentShaderNewlineBeforeVersion",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "Fragment shader with a newline before the version directive should fail."
+ }
+], 2);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/no-attribute-vertex-shader.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/no-attribute-vertex-shader.html
new file mode 100644
index 0000000000..eabbd9779d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/no-attribute-vertex-shader.html
@@ -0,0 +1,63 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test no attribute vertex shaders</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertex-shader" type="x-shader/x-vertex">#version 300 es
+
+void main() {
+ ivec2 xy = ivec2(
+ gl_VertexID % 2,
+ (gl_VertexID / 2 + gl_VertexID / 3) % 2);
+ gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 result;
+void main() {
+ result = vec4(0, 1, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description("Test no attribute shaders work as expected");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+function test() {
+ debug("");
+ var program = wtu.setupProgram(gl, ["vertex-shader", "fshader"], undefined, undefined, true);
+ if (!program) {
+ testFailed('Program compilation failed');
+ return;
+ }
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
+};
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ test();
+}
+var successfullyParsed = true;
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/precision-side-effects-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/precision-side-effects-bug.html
new file mode 100644
index 0000000000..c717c4ee94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/precision-side-effects-bug.html
@@ -0,0 +1,125 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify precision side effects (Adreno driver bug)</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader-simple" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1.0);
+}
+</script>
+<script id="fshader-int" type="x-shader/x-fragment">#version 300 es
+out highp vec4 myFragColor;
+void main() {
+ highp int t;
+ t = 0 | (int(t == t) * 0x8000);
+
+ if (t == 0x8000)
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fshader-ivec2" type="x-shader/x-fragment">#version 300 es
+out highp vec4 myFragColor;
+void main() {
+ highp ivec2 t;
+ t = 0 | (ivec2(t == t) * 0x8000);
+
+ if (t == ivec2(0x8000))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fshader-ivec3" type="x-shader/x-fragment">#version 300 es
+out highp vec4 myFragColor;
+void main() {
+ highp ivec3 t;
+ t = 0 | (ivec3(t == t) * 0x8000);
+
+ if (t == ivec3(0x8000))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script id="fshader-ivec4" type="x-shader/x-fragment">#version 300 es
+out highp vec4 myFragColor;
+void main() {
+ highp ivec4 t;
+ t = 0 | (ivec4(t == t) * 0x8000);
+
+ if (t == ivec4(0x8000))
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Verify precision side effects");
+debug("");
+debug("When this test is run on Adreno (no repros on other vendors so far):");
+debug(" - the result of the expression 0 | (int(e0 == e0) * 0x8000) somehow returns -32768 instead of 32768 despite the variable using highp precision;");
+debug(" - splitting the expression along | fixes the issue (could also be observed with other operators).");
+debug('For additional reference see this <a href="https://github.com/KhronosGroup/WebGL/pull/3192">pull request</a> and <a href="http://crbug.com/1155942">Chromium bug</a>');
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas", undefined, 2);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ wtu.setupUnitQuad(gl);
+
+ var testCases = [
+ { vshader: "vshader-simple", fshader: "fshader-int", desc: "fragment shader int" },
+ { vshader: "vshader-simple", fshader: "fshader-ivec2", desc: "fragment shader ivec2" },
+ { vshader: "vshader-simple", fshader: "fshader-ivec3", desc: "fragment shader ivec3" },
+ { vshader: "vshader-simple", fshader: "fshader-ivec4", desc: "fragment shader ivec4" },
+ ];
+
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ var test = testCases[idx];
+
+ debug("");
+ var program = wtu.setupProgram(gl, [test.vshader, test.fshader], ["aPosition"]);
+ if (!program) {
+ testFailed("Fail to set up program");
+ } else {
+ debug("Testing " + test.desc);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255]);
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from testing");
+ }
+ }
+};
+
+test();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/reciprocal-sqrt-of-sum-of-squares-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/reciprocal-sqrt-of-sum-of-squares-crash.html
new file mode 100644
index 0000000000..691523aea0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/reciprocal-sqrt-of-sum-of-squares-crash.html
@@ -0,0 +1,66 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Shader identified as containing reciprocal square root of sum of squares should not crash</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+void main() {
+ gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+
+#define CRASH 1
+
+out vec4 fragmentColor;
+void main()
+{
+ vec2 p = gl_FragCoord.xy;
+ // This expression meets the requirement of being the reciprocal
+ // square root of a sum of squares.
+ float d = 1.0 / length(p);
+#if CRASH
+ if (p.x > 0.0)
+ {
+ d *= 2.0;
+ }
+#endif
+ fragmentColor = vec4(d);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+debug('Regression test for <a href="https://crbug.com/1079309">crbug.com/1079309</a>');
+const wtu = WebGLTestUtils;
+const tests = [
+ {
+ vShaderSource: wtu.getScript('vshader'),
+ fShaderSource: wtu.getScript('fshader'),
+ vShaderSuccess: true,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Shader containing expression that driver recognizes as reciprocal square root of sum of squares should compile and link'
+ }
+];
+
+GLSLConformanceTester.runTests(tests, 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-array-indexing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-array-indexing.html
new file mode 100644
index 0000000000..f2f124873b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-array-indexing.html
@@ -0,0 +1,94 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>ESSL300 sampler array indexing rules</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vs" type="text/plain">#version 300 es
+void main() {}
+</script>
+<script id="fs_constant_integer_expression" type="text/plain">#version 300 es
+precision mediump float;
+uniform sampler2D u_tex[2];
+
+void main()
+{
+ texture(u_tex[0], vec2(0));
+ texture(u_tex[1], vec2(0));
+}
+</script>
+<script id="fs_constant_index_expression" type="text/plain">#version 300 es
+precision mediump float;
+uniform sampler2D u_tex[2];
+
+void main()
+{
+ for (int i = 0; i < 2; i++) {
+ texture(u_tex[i], vec2(0));
+ }
+}
+</script>
+<script id="fs_constant_integer_expression_switch" type="text/plain">#version 300 es
+precision mediump float;
+uniform sampler2D u_tex[2];
+
+void main()
+{
+ for (int i = 0; i < 2; i++) {
+ switch (i) {
+ case 0:
+ texture(u_tex[0], vec2(0));
+ break;
+ case 1:
+ texture(u_tex[1], vec2(0));
+ break;
+ }
+ }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "vs",
+ vShaderSuccess: true,
+ fShaderId: "fs_constant_integer_expression",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "indexing into an array of samplers with constant-integer-expression is required",
+ },
+ {
+ vShaderId: "vs",
+ vShaderSuccess: true,
+ fShaderId: "fs_constant_index_expression",
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: "indexing into an array of samplers with constant-index-expression is forbidden in essl300",
+ },
+ {
+ vShaderId: "vs",
+ vShaderSuccess: true,
+ fShaderId: "fs_constant_integer_expression_switch",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "constant-index-expression can be converted into fs_constant_integer_expression via a switch",
+ },
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-no-precision.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-no-precision.html
new file mode 100644
index 0000000000..8205fa5c25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sampler-no-precision.html
@@ -0,0 +1,88 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL sampler with no precision qualifier test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshaderSamplerNoPrecision" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+
+uniform $(samplerType) u_sampler;
+
+void main() {
+ gl_Position = vec4(0.0);
+}
+</script>
+<script id="fshaderSamplerNoPrecision" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform $(samplerType) u_sampler;
+
+void main() {
+ my_FragColor = vec4(0.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("ESSL3 sampler with no precision qualifier should not compile.");
+
+var wtu = WebGLTestUtils;
+
+var fragmentShaderTemplate = wtu.getScript('fshaderSamplerNoPrecision');
+var vertexShaderTemplate = wtu.getScript('vshaderSamplerNoPrecision');
+
+// ESSL 3.00.4 section 4.5.4 types with no predefined precision.
+var samplerTypes = [
+ 'sampler3D',
+ 'samplerCubeShadow',
+ 'sampler2DShadow',
+ 'sampler2DArray',
+ 'sampler2DArrayShadow',
+ 'isampler2D',
+ 'isampler3D',
+ 'isamplerCube',
+ 'isampler2DArray',
+ 'usampler2D',
+ 'usampler3D',
+ 'usamplerCube',
+ 'usampler2DArray'
+];
+
+var tests = [];
+
+for (var i = 0; i < samplerTypes.length; ++i) {
+ var type = samplerTypes[i];
+ var vertexShaderSrc = wtu.replaceParams(vertexShaderTemplate, {'samplerType': type});
+ tests.push({
+ vShaderSource: vertexShaderSrc,
+ vShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Vertex shader with a ' + type + ' uniform with no precision qualifier should not compile'
+ });
+ var fragmentShaderSrc = wtu.replaceParams(fragmentShaderTemplate, {'samplerType': type});
+ tests.push({
+ fShaderSource: fragmentShaderSrc,
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Fragment shader with a ' + type + ' uniform with no precision qualifier should not compile'
+ });
+}
+
+GLSLConformanceTester.runTests(tests, 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sequence-operator-returns-non-constant.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sequence-operator-returns-non-constant.html
new file mode 100644
index 0000000000..d5d0e5eb71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/sequence-operator-returns-non-constant.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Sequence operator returns non-constant test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!--
+Sequence operator and non-constant expressions are detailed in the ESSL 3.00 spec section 12.43
+-->
+<script id="fshader-non-const-expression" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+void main() {
+ const float a = (0.0, 1.0);
+}
+</script>
+<script id="fshader-non-const-expression-as-array-size" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+void main() {
+ float a[(2, 3)];
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Checks sequence operators returning non-constants and cannot be used as an array size.");
+debug("");
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshader-non-const-expression',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Sequence operator cannot return a constant expression'
+},
+{
+ fShaderId: 'fshader-non-const-expression-as-array-size',
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Sequence operator return value cannot be used as an array size'
+},
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-linking.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-linking.html
new file mode 100644
index 0000000000..6210e0577b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-linking.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>OpenGL ES Shading Language 1.00 and OpenGL ES Shading Language 3.00 shaders should not link with each other</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="ES3VertexShader" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+in vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="ES3FragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="ESSL1VertexShader" type="x-shader/x-vertex">
+precision mediump float;
+attribute vec4 aPosition;
+
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+<script id="ESSL1FragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+// See OpenGL ES Shading Language 3.00 spec section 1.5 or 3.3
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "ES3VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "ES3FragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "OpenGL ES Shading Language 3.00 vertex shader should link with OpenGL ES Shading Language 3.00 fragment shader."
+ },
+ {
+ vShaderId: "ES3VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "ESSL1FragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "OpenGL ES Shading Language 3.00 vertex shader should not link with OpenGL ES Shading Language 1.00 fragment shader."
+ },
+ {
+ vShaderId: "ESSL1VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "ES3FragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "OpenGL ES Shading Language 1.00 vertex shader should not link with OpenGL ES Shading Language 3.00 fragment shader."
+ }
+], 2);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-invalid-characters.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-invalid-characters.html
new file mode 100644
index 0000000000..5494c46dcd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-invalid-characters.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL GLSL Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShader" type="text/something-not-javascript">
+// vertex shader that uses backlash character in comments should succeed
+// This is a li\ne wi\th backlash \\ characters \
+in comments
+
+void main()
+{
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+GLSLConformanceTester.runTest();
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-mis-matching-uniform-block.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-mis-matching-uniform-block.html
new file mode 100644
index 0000000000..2bf41a3825
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/shader-with-mis-matching-uniform-block.html
@@ -0,0 +1,59 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL mis-matching uniform block</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader-uniform-block-precision" type="text/something-not-javascript">#version 300 es
+uniform Block {
+ mediump vec4 val;
+};
+
+void main()
+{
+ gl_Position = val;
+}
+</script>
+<script id="fshader-uniform-block-precision" type="text/something-not-javascript">#version 300 es
+uniform Block {
+ highp vec4 val;
+};
+
+out highp vec4 out_FragColor;
+void main()
+{
+ out_FragColor = val;
+}
+</script>
+<script>
+"use strict";
+description("Shaders with precision mis-matching uniform blocks should fail");
+
+GLSLConformanceTester.runTests([
+{
+ vShaderId: 'vshader-uniform-block-precision',
+ vShaderSuccess: true,
+ fShaderId: 'fshader-uniform-block-precision',
+ fShaderSuccess: true,
+ linkSuccess: false,
+ passMsg: "Shaders with precision mis-matching uniform blocks should fail"
+},
+], 2);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/short-circuiting-in-loop-condition.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/short-circuiting-in-loop-condition.html
new file mode 100644
index 0000000000..802d67aa4a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/short-circuiting-in-loop-condition.html
@@ -0,0 +1,180 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Short circuit in loop condition test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderWhile" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform bool u;
+out vec4 result;
+int sideEffectCounter;
+
+bool foo() {
+ ++sideEffectCounter;
+ return true;
+}
+
+void main() {
+ sideEffectCounter = 0;
+ int iterations = 0;
+
+ while(u && foo()) {
+ ++iterations;
+ if (iterations >= 10) {
+ break;
+ }
+ }
+
+ bool success = (u && sideEffectCounter == 10) || (!u && sideEffectCounter == 0);
+ result = success ? vec4(0, 1.0, 0, 1.0) : vec4(0, 1.0, 0, 0);
+}
+</script>
+<script id="fshaderForCondition" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform bool u;
+out vec4 result;
+int sideEffectCounter;
+
+bool foo() {
+ ++sideEffectCounter;
+ return true;
+}
+
+void main() {
+ sideEffectCounter = 0;
+ for(int iterations = 0; u && foo();) {
+ ++iterations;
+ if (iterations >= 10) {
+ break;
+ }
+ }
+
+ bool success = (u && sideEffectCounter == 10) || (!u && sideEffectCounter == 0);
+ result = success ? vec4(0, 1.0, 0, 1.0) : vec4(0, 1.0, 0, 0);
+}
+</script>
+<script id="fshaderFor" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform bool u;
+out vec4 result;
+int sideEffectCounter;
+
+bool foo() {
+ ++sideEffectCounter;
+ return true;
+}
+
+void main() {
+ sideEffectCounter = 0;
+ for(int iterations = 0; true; u && foo()) {
+ ++iterations;
+ if (iterations > 10) {
+ break;
+ }
+ }
+
+ bool success = (u && sideEffectCounter == 10) || (!u && sideEffectCounter == 0);
+ result = success ? vec4(0, 1.0, 0, 1.0) : vec4(0, 1.0, 0, 0);
+}
+</script>
+<script id="fshaderDoWhile" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform bool u;
+out vec4 result;
+int sideEffectCounter;
+
+bool foo() {
+ ++sideEffectCounter;
+ return true;
+}
+
+void main() {
+ sideEffectCounter = 0;
+ int iterations = 0;
+
+ do {
+ ++iterations;
+ if (iterations > 10) {
+ break;
+ }
+ } while (u && foo());
+
+ bool success = (u && sideEffectCounter == 10) || (!u && sideEffectCounter == 0);
+ result = success ? vec4(0, 1.0, 0, 1.0) : vec4(0, 1.0, 0, 0);
+}
+</script>
+<script id="fshaderSequence" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform bool u;
+out vec4 result;
+int sideEffectCounter;
+
+bool foo() {
+ ++sideEffectCounter;
+ return true;
+}
+
+void main() {
+ sideEffectCounter = 0;
+ int iterations = 0;
+
+ while(u, u && foo()) {
+ ++iterations;
+ if (iterations >= 10) {
+ break;
+ }
+ }
+
+ bool success = (u && sideEffectCounter == 10) || (!u && sideEffectCounter == 0);
+ result = success ? vec4(0, 1.0, 0, 1.0) : vec4(0, 1.0, 0, 0);
+}
+</script>
+<script type="text/javascript">
+"use strict";
+description("Test behavior of a short-circuiting operator in a loop using a function call with side effects");
+
+var testShaders = [
+ {fShaderId: 'fshaderWhile', description: 'in while loop condition'},
+ {fShaderId: 'fshaderForCondition', description: 'in for loop condition'},
+ {fShaderId: 'fshaderFor', description: 'in for loop expression'},
+ {fShaderId: 'fshaderDoWhile', description: 'in do-while loop condition'},
+ {fShaderId: 'fshaderSequence', description: 'inside a sequence in while loop condition'}
+];
+
+var testList = [];
+
+for (var i = 0; i < testShaders.length; ++i) {
+ testList.push({
+ fShaderId: testShaders[i].fShaderId,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Short-circuiting operator with a true condition ' + testShaders[i].description,
+ uniforms: [{name: "u", functionName: "uniform1i", value: 1}]
+ });
+ testList.push({
+ fShaderId: testShaders[i].fShaderId,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Short-circuiting operator with a false condition ' + testShaders[i].description,
+ uniforms: [{name: "u", functionName: "uniform1i", value: 0}]
+ });
+}
+
+GLSLConformanceTester.runRenderTests(testList, 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
new file mode 100644
index 0000000000..4ab422c958
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
@@ -0,0 +1,351 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL switch/case corner case test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderDeclarationInsideSwitch" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ my_FragColor = vec4(1, 0, 0, 1);
+ switch (u_zero)
+ {
+ case 0:
+ ivec2 i;
+ i = ivec2(1, 0);
+ my_FragColor = vec4(0, i[0], 0, 1);
+ }
+}
+</script>
+<script id="fshaderDeclarationInsideSwitchDefault" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ my_FragColor = vec4(1, 0, 0, 1);
+ switch (u_zero)
+ {
+ default:
+ ivec2 i;
+ i = ivec2(1, 0);
+ my_FragColor = vec4(0, i[0], 0, 1);
+ }
+}
+</script>
+<script id="fshaderDeclarationInsideSwitchLiteral" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ my_FragColor = vec4(1, 0, 0, 1);
+ switch (0)
+ {
+ case 0:
+ ivec2 i;
+ i = ivec2(1, 0);
+ my_FragColor = vec4(0, i[0], 0, 1);
+ }
+}
+</script>
+<script id="fshaderDeclarationInsideSwitchLiteralDefault" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+out vec4 my_FragColor;
+
+void main()
+{
+ my_FragColor = vec4(1, 0, 0, 1);
+ switch (0)
+ {
+ default:
+ ivec2 i;
+ i = ivec2(1, 0);
+ my_FragColor = vec4(0, i[0], 0, 1);
+ }
+}
+</script>
+<script id="fshaderDeclarationInsideSwitchScope" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+// GLSL ES 3.10 clarifies the scoping rules that are relevant here. In section 4.2.2 it says:
+// "The statement following a switch (...) forms a nested scope."
+// There are no other special scoping rules with regards to switch statements.
+
+void main()
+{
+ my_FragColor = vec4(1, 0, 0, 1);
+ switch (u_zero)
+ {
+ case 0:
+ ivec2 i;
+ i = ivec2(1, 0);
+ default:
+ my_FragColor = vec4(0, i[0], 0, 1);
+ }
+}
+</script>
+<script id="fshaderFallThroughAll" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ int i = 0;
+ // switch should fall through both cases.
+ switch(u_zero)
+ {
+ case 0:
+ i += 1;
+ case 1:
+ i += 2;
+ }
+ if (i == 3)
+ {
+ my_FragColor = vec4(0, 1, 0, 1);
+ }
+ else
+ {
+ my_FragColor = vec4(1, 0, 0, 1);
+ }
+}
+</script>
+<script id="fshaderEmptySwitchStatement" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ switch(u_zero)
+ {
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fshaderLastCaseHasEmptyDeclaration" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ // Empty declaration should count as a statement.
+ switch(u_zero)
+ {
+ case 0:
+ int;
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fshaderLastCaseHasEmptyBlock" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ // Empty block should count as a statement.
+ switch(u_zero)
+ {
+ case 0:
+ {}
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fshaderLastCaseHasConstantStatement" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ // Empty statement should count as a statement.
+ switch(u_zero)
+ {
+ case 0:
+ 0;
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fshaderLastCaseHasEmptyStatement" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ // Empty statement should count as a statement.
+ switch(u_zero)
+ {
+ case 0:
+ ;
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script id="fshaderCaseInsideBlock" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ // Case statements must not be nested in blocks.
+ // GLSL ES 3.00 spec is a bit vague on this but GLSL ES 3.10 section 6.2 is clearer.
+ switch(u_zero)
+ {
+ case 1:
+ {
+ case 0:
+ my_FragColor = vec4(1, 0, 0, 1);
+ }
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+// Covers bugs:
+// http://anglebug.com/2177
+// http://anglebug.com/2178
+// http://anglebug.com/2179
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshaderDeclarationInsideSwitch',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Declaration inside switch should work.',
+ render: true
+},
+{
+ fShaderId: 'fshaderDeclarationInsideSwitchDefault',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Declaration inside switch default case should work.',
+ render: true
+},
+{
+ fShaderId: 'fshaderDeclarationInsideSwitchLiteral',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Declaration inside switch with literal value should work.',
+ render: true
+},
+{
+ fShaderId: 'fshaderDeclarationInsideSwitchLiteralDefault',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Declaration inside switch with literal value and default case should work.',
+ render: true
+},
+{
+ fShaderId: 'fshaderDeclarationInsideSwitchScope',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Declaration inside switch should be scoped until the end of the switch statement.',
+ render: true
+},
+{
+ fShaderId: 'fshaderFallThroughAll',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Falling through all cases in switch/case should work.',
+ render: true
+},
+{
+ fShaderId: 'fshaderEmptySwitchStatement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Empty switch statements are valid.'
+},
+{
+ fShaderId: 'fshaderLastCaseHasEmptyDeclaration',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Empty declaration should count as a statement for the purposes of switch statement validation.'
+},
+{
+ fShaderId: 'fshaderLastCaseHasEmptyBlock',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Empty block should count as a statement for the purposes of switch statement validation.'
+},
+{
+ fShaderId: 'fshaderLastCaseHasConstantStatement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Constant statement should count as a statement for the purposes of switch statement validation.'
+},
+{
+ fShaderId: 'fshaderLastCaseHasEmptyStatement',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Empty statement should count as a statement for the purposes of switch statement validation.'
+},
+{
+ fShaderId: 'fshaderCaseInsideBlock',
+ fShaderSuccess: false,
+ passMsg: 'Case statements must not be nested inside blocks.'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html
new file mode 100644
index 0000000000..8fd483140d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html
@@ -0,0 +1,170 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL texture offset with non-constant offset test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderTextureOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureOffset(u_sampler, u_texCoord, offset);
+}
+</script>
+<script id="fshaderTextureProjOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureProjOffset(u_sampler, u_texCoord, offset);
+}
+</script>
+<script id="fshaderTextureLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform float u_lod;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureLodOffset(u_sampler, u_texCoord, u_lod, offset);
+}
+</script>
+<script id="fshaderTextureProjLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform float u_lod;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureProjLodOffset(u_sampler, u_texCoord, u_lod, offset);
+}
+</script>
+<script id="fshaderTextureGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, offset);
+}
+</script>
+<script id="fshaderTextureProjGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureProjGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, offset);
+}
+</script>
+<script id="fshaderTexelFetchOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_lod;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = texelFetchOffset(u_sampler, ivec2(u_texCoord), int(u_lod), offset);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("A non-constant offset is not valid in texture offset functions.");
+
+var wtu = WebGLTestUtils;
+
+var shaderTextureOffsetSrc = wtu.getScript('fshaderTextureOffset');
+var shaderTextureLodOffsetSrc = wtu.getScript('fshaderTextureLodOffset');
+var shaderTextureGradOffsetSrc = wtu.getScript('fshaderTextureGradOffset');
+var shaderTextureProjOffsetSrc = wtu.getScript('fshaderTextureProjOffset');
+var shaderTextureProjLodOffsetSrc = wtu.getScript('fshaderTextureProjLodOffset');
+var shaderTextureProjGradOffsetSrc = wtu.getScript('fshaderTextureProjGradOffset');
+var shaderTexelFetchOffsetSrc = wtu.getScript('fshaderTexelFetchOffset');
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+if (!gl) {
+ testFailed("Unable to initialize WebGL 2.0 context.");
+} else {
+ GLSLConformanceTester.runTests([
+ {
+ fShaderSource: shaderTextureOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureLodOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureLodOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureGradOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureGradOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureProjOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureProjOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureProjLodOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureProjLodOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureProjGradOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureProjGradOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTexelFetchOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'texelFetchOffset with non-constant offset is invalid'
+ }
+ ], 2);
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-out-of-range.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-out-of-range.html
new file mode 100644
index 0000000000..99e698fb6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-out-of-range.html
@@ -0,0 +1,106 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL out-of-range texture offset test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshaderInvalidOffset" type="x-shader/x-vertex">#version 300 es
+in vec4 a_position;
+in vec2 a_in0;
+out vec2 v_texCoord;
+
+void main()
+{
+ gl_Position = a_position;
+ v_texCoord = a_in0;
+}
+</script>
+<script id="fshaderInvalidOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+in vec2 v_texCoord;
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform int x;
+
+void main() {
+ my_FragColor = textureOffset(u_sampler, v_texCoord, ivec2(0, $(yoffset)));
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Out-of-range texture offset should not compile.");
+
+var wtu = WebGLTestUtils;
+
+var vshader = wtu.getScript('vshaderInvalidOffset');
+var fshaderTemplate = wtu.getScript('fshaderInvalidOffset');
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+if (!gl) {
+ testFailed("Unable to initialize WebGL 2.0 context.");
+} else {
+ var minOffset = gl.getParameter(gl.MIN_PROGRAM_TEXEL_OFFSET);
+ var maxOffset = gl.getParameter(gl.MAX_PROGRAM_TEXEL_OFFSET);
+
+ var shaderSrcValidMin = wtu.replaceParams(fshaderTemplate, {'yoffset': minOffset});
+ var shaderSrcValidMax = wtu.replaceParams(fshaderTemplate, {'yoffset': maxOffset});
+ var shaderSrcBelowMin = wtu.replaceParams(fshaderTemplate, {'yoffset': (minOffset - 1)});
+ var shaderSrcAboveMax = wtu.replaceParams(fshaderTemplate, {'yoffset': (maxOffset + 1)});
+ var shaderSrcDynamic = wtu.replaceParams(fshaderTemplate, {'yoffset': 'x'});
+
+ GLSLConformanceTester.runTests([
+ {
+ vShaderSource: vshader,
+ fShaderSource: shaderSrcValidMin,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Minimum in-range texture offset should compile'
+ },
+ {
+ vShaderSource: vshader,
+ fShaderSource: shaderSrcValidMax,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Maximum in-range texture offset should compile'
+ },
+ {
+ vShaderSource: vshader,
+ fShaderSource: shaderSrcBelowMin,
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Texture offset below minimum valid value should not compile'
+ },
+ {
+ vShaderSource: vshader,
+ fShaderSource: shaderSrcAboveMax,
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Texture offset above maximum valid value should not compile'
+ },
+ {
+ vShaderSource: vshader,
+ fShaderSource: shaderSrcDynamic,
+ fShaderSuccess: false,
+ linkSuccess: false,
+ passMsg: 'Dynamic texture offset should not compile'
+ }
+ ], 2);
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-uniform-texture-coordinate.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-uniform-texture-coordinate.html
new file mode 100644
index 0000000000..56caf47f46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-uniform-texture-coordinate.html
@@ -0,0 +1,170 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL texture offset with uniform texture coordinates test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderTextureOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+
+void main() {
+ my_FragColor = textureOffset(u_sampler, u_texCoord, ivec2(0, 1));
+}
+</script>
+<script id="fshaderTextureProjOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+
+void main() {
+ my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec2(0, 1));
+}
+</script>
+<script id="fshaderTextureLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform float u_lod;
+
+void main() {
+ my_FragColor = textureLodOffset(u_sampler, u_texCoord, u_lod, ivec2(0, 1));
+}
+</script>
+<script id="fshaderTextureProjLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform float u_lod;
+
+void main() {
+ my_FragColor = textureProjLodOffset(u_sampler, u_texCoord, u_lod, ivec2(0, 1));
+}
+</script>
+<script id="fshaderTextureGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+ my_FragColor = textureGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, ivec2(0, 1));
+}
+</script>
+<script id="fshaderTextureProjGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+ my_FragColor = textureProjGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, ivec2(0, 1));
+}
+</script>
+<script id="fshaderTexelFetchOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_lod;
+
+void main() {
+ my_FragColor = texelFetchOffset(u_sampler, ivec2(u_texCoord), int(u_lod), ivec2(0, 1));
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Texture coordinates expressed as uniform variable should not crash in texture offset functions.");
+
+var wtu = WebGLTestUtils;
+
+var shaderTextureOffsetSrc = wtu.getScript('fshaderTextureOffset');
+var shaderTextureLodOffsetSrc = wtu.getScript('fshaderTextureLodOffset');
+var shaderTextureGradOffsetSrc = wtu.getScript('fshaderTextureGradOffset');
+var shaderTextureProjOffsetSrc = wtu.getScript('fshaderTextureProjOffset');
+var shaderTextureProjLodOffsetSrc = wtu.getScript('fshaderTextureProjLodOffset');
+var shaderTextureProjGradOffsetSrc = wtu.getScript('fshaderTextureProjGradOffset');
+var shaderTexelFetchOffsetSrc = wtu.getScript('fshaderTexelFetchOffset');
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+if (!gl) {
+ testFailed("Unable to initialize WebGL 2.0 context.");
+} else {
+ GLSLConformanceTester.runTests([
+ {
+ fShaderSource: shaderTextureOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'textureOffset with uniform texture coordinates should not crash'
+ },
+ {
+ fShaderSource: shaderTextureLodOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'textureLodOffset with uniform texture coordinates should not crash'
+ },
+ {
+ fShaderSource: shaderTextureGradOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'textureGradOffset with uniform texture coordinates should not crash'
+ },
+ {
+ fShaderSource: shaderTextureProjOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'textureProjOffset with uniform texture coordinates should not crash'
+ },
+ {
+ fShaderSource: shaderTextureProjLodOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'textureProjLodOffset with uniform texture coordinates should not crash'
+ },
+ {
+ fShaderSource: shaderTextureProjGradOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'textureProjGradOffset with uniform texture coordinates should not crash'
+ },
+ {
+ fShaderSource: shaderTexelFetchOffsetSrc,
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'texelFetchOffset with uniform texture coordinates should not crash'
+ }
+ ], 2);
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/tricky-loop-conditions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/tricky-loop-conditions.html
new file mode 100644
index 0000000000..1bf57d1a02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/tricky-loop-conditions.html
@@ -0,0 +1,327 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL tricky loop conditions and loop expressions</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!--
+Some tricky shader expressions might be subject to syntax tree transformations that need to create
+new statements. Ensure that these expressions also work inside loop conditions and loop expressions.
+-->
+<script type="application/javascript">
+"use strict";
+description("Indexing complex array expressions");
+debug("");
+
+// All the templates run the given sequence:
+// 1. loopExpression or loopCondition
+// 2. loopContents
+// 3. Break loop if it's done loopIterations iterations, else go back to 1.
+
+var forLoopExpressionTemplate = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'out vec4 color;',
+ '$(globalScopePrefix)',
+ 'void main() {',
+ '$(mainPrefix)',
+ ' for (int i = 0; true; $(loopExpression))',
+ ' {',
+ ' ++i;',
+ ' if (i > 1) {',
+ ' $(loopContents)',
+ ' if (i > $(loopIterations)) { break; }',
+ ' }',
+ ' }',
+ ' color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
+ '}'
+].join('\n');
+
+var forLoopConditionTemplate = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'out vec4 color;',
+ '$(globalScopePrefix)',
+ 'void main() {',
+ '$(mainPrefix)',
+ ' for (int i = 1; $(loopCondition); ++i)',
+ ' {',
+ ' $(loopContents)',
+ ' if (i >= $(loopIterations)) { break; }',
+ ' }',
+ ' color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
+ '}'
+].join('\n');
+
+var whileLoopConditionTemplate = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'out vec4 color;',
+ '$(globalScopePrefix)',
+ 'void main() {',
+ '$(mainPrefix)',
+ ' int i = 0;',
+ ' while ($(loopCondition))',
+ ' {',
+ ' $(loopContents)',
+ ' ++i;',
+ ' if (i >= $(loopIterations)) { break; }',
+ ' }',
+ ' color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
+ '}'
+].join('\n');
+
+var doWhileLoopConditionTemplate = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'out vec4 color;',
+ '$(globalScopePrefix)',
+ 'void main() {',
+ '$(mainPrefix)',
+ ' int i = 0;',
+ // Run the loop condition one extra time to make the different test types behave the same
+ ' $(loopCondition);',
+ ' do {',
+ ' $(loopContents)',
+ ' ++i;',
+ ' if (i >= $(loopIterations)) { break; }',
+ ' }',
+ ' while ($(loopCondition));',
+ ' color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
+ '}'
+].join('\n');
+
+var testDataList = [
+{
+ description: 'indexing an array assignment',
+ globalScopePrefix: '',
+ mainPrefix: [
+ 'float a[2] = float[2](0.0, 0.0);',
+ 'float b[2] = float[2](2.0, 1.0);',
+ 'float c = 0.0;'
+ ].join('\n'),
+ loopExpression: 'c = (a = b)[0]',
+ loopCondition: 'bool((c = (a = b)[0]) + 1.0)',
+ loopContents: 'b[0] += 1.0;',
+ loopIterations: 3,
+ passCondition: 'abs(c - 4.0) < 0.01'
+},
+{
+ description: 'indexing a function returning an array',
+ globalScopePrefix: [
+ 'int sideEffectCounter = 0;',
+ 'float[2] functionReturnArray() {',
+ ' ++sideEffectCounter;',
+ ' return float[2](float(sideEffectCounter), 1.0);',
+ '}'
+ ].join('\n'),
+ mainPrefix: 'float c = 0.0;',
+ loopExpression: 'c = functionReturnArray()[0]',
+ loopCondition: 'bool(c = functionReturnArray()[0])',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'abs(c - 3.0) < 0.01 && sideEffectCounter == 3'
+},
+{
+ description: 'indexing an array constructor',
+ globalScopePrefix: '',
+ mainPrefix: 'int c = 0;',
+ loopExpression: 'c = (int[2](c + 1, c + 2))[1]',
+ loopCondition: 'bool(c = (int[2](c + 1, c + 2))[1])',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'c == 6'
+},
+{
+ description: 'indexing an array constructor inside a sequence operator',
+ globalScopePrefix: [
+ 'int sideEffectCounter = 0;',
+ 'int func() {',
+ ' sideEffectCounter++;',
+ ' return sideEffectCounter;',
+ '}'
+ ].join('\n'),
+ mainPrefix: 'int c = 0;',
+ loopExpression: 'c = (func(), (int[2](c + 1, c + 2))[1])',
+ loopCondition: 'bool(c = (func(), (int[2](c + 1, c + 2))[1]))',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'c == 6 && sideEffectCounter == 3'
+},
+{
+ description: 'dynamic indexing of a vector',
+ globalScopePrefix: '',
+ mainPrefix: [
+ 'vec4 v = vec4(1.0, 2.0, 3.0, 4.0);',
+ 'float c = 0.0;',
+ 'int j = 0;'
+ ].join('\n'),
+ loopExpression: 'c = v[j]',
+ loopCondition: 'bool(c = v[j])',
+ loopContents: '++j;',
+ loopIterations: 3,
+ passCondition: 'abs(c - 3.0) < 0.01'
+},
+{
+ description: 'short-circuiting operator',
+ globalScopePrefix: [
+ 'int sideEffectCounter = 0;',
+ 'bool func() {',
+ ' sideEffectCounter++;',
+ ' return sideEffectCounter > 0;',
+ '}'
+ ].join('\n'),
+ mainPrefix: '',
+ loopExpression: 'func() && func()',
+ loopCondition: 'func() && func()',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'sideEffectCounter == 6'
+},
+{
+ description: 'short-circuiting operator',
+ globalScopePrefix: [
+ 'int sideEffectCounter = 0;',
+ 'bool func() {',
+ ' sideEffectCounter++;',
+ ' return sideEffectCounter > 0;',
+ '}'
+ ].join('\n'),
+ mainPrefix: '',
+ loopExpression: 'func() || func()',
+ loopCondition: 'func() || func()',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'sideEffectCounter == 3'
+},
+{
+ description: 'short-circuiting operator',
+ globalScopePrefix: [
+ 'int sideEffectCounterA = 0;',
+ 'bool funcA() {',
+ ' sideEffectCounterA++;',
+ ' return sideEffectCounterA > 1;',
+ '}',
+ 'int sideEffectCounterB = 0;',
+ 'bool funcB() {',
+ ' sideEffectCounterB++;',
+ ' return sideEffectCounterB > 0;',
+ '}'
+ ].join('\n'),
+ mainPrefix: '',
+ loopExpression: 'funcA() ? true : funcB()',
+ loopCondition: 'funcA() ? true : funcB()',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'sideEffectCounterA == 3 && sideEffectCounterB == 1'
+},
+{
+ description: 'high-precision constant',
+ globalScopePrefix: [
+ 'const highp float f = 2048.5;',
+ 'uniform mediump float u_zero;'
+ ].join('\n'),
+ mainPrefix: 'float c = 0.0;',
+ loopExpression: 'c = fract(u_zero + f)',
+ loopCondition: 'bool(c = fract(u_zero + f))',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'abs(c - 0.5) < 0.01'
+},
+{
+ description: 'l-value indexing side effects combined with static indexing of a vector',
+ globalScopePrefix: [
+ 'int sideEffectCounter = 0;',
+ 'int func() {',
+ ' sideEffectCounter++;',
+ ' return sideEffectCounter > 1 ? 1 : 0;',
+ '}'
+ ].join('\n'),
+ mainPrefix: [
+ 'vec4[2] V;',
+ 'V[0] = vec4(1.0);',
+ 'V[1] = vec4(3.0);'
+ ].join('\n'),
+ loopExpression: 'V[func()][0]++',
+ loopCondition: 'bool(V[func()][0]++)',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'abs(V[0][0] - 2.0) < 0.01 && abs(V[1][0] - 5.0) < 0.01 && sideEffectCounter == 3'
+},
+{
+ description: 'l-value indexing side effects combined with dynamically indexing a vector',
+ globalScopePrefix: [
+ 'int sideEffectCounter = 0;',
+ 'uniform int u_zero;',
+ 'int func() {',
+ ' sideEffectCounter++;',
+ ' return sideEffectCounter > 1 ? 1 : 0;',
+ '}'
+ ].join('\n'),
+ mainPrefix: [
+ 'vec4[2] V;',
+ 'V[0] = vec4(1.0);',
+ 'V[1] = vec4(3.0);'
+ ].join('\n'),
+ loopExpression: 'V[func()][u_zero + 1]++',
+ loopCondition: 'bool(V[func()][u_zero + 1]++)',
+ loopContents: '',
+ loopIterations: 3,
+ passCondition: 'abs(V[0][1] - 2.0) < 0.01 && abs(V[1][1] - 5.0) < 0.01 && sideEffectCounter == 3'
+}
+];
+
+var tests = [];
+
+var wtu = WebGLTestUtils;
+
+for (var i = 0; i < testDataList.length; ++i) {
+ var testData = testDataList[i];
+ if ('loopCondition' in testData) {
+ tests.push({
+ fShaderSource: wtu.replaceParams(forLoopConditionTemplate, testData),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a for loop condition'
+ });
+ tests.push({
+ fShaderSource: wtu.replaceParams(whileLoopConditionTemplate, testData),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a while loop condition'
+ });
+ tests.push({
+ fShaderSource: wtu.replaceParams(doWhileLoopConditionTemplate, testData),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a do-while loop condition'
+ });
+ }
+ if ('loopExpression' in testData) {
+ tests.push({
+ fShaderSource: wtu.replaceParams(forLoopExpressionTemplate, testData),
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Test ' + testData.description + ': ' + testData.loopExpression + ' inside a for loop expression'
+ });
+ }
+}
+
+GLSLConformanceTester.runRenderTests(tests, 2);
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uint-int-shift-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uint-int-shift-bug.html
new file mode 100644
index 0000000000..499d266e7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uint-int-shift-bug.html
@@ -0,0 +1,106 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify (uint(int) >> 31) works correctly (Adreno driver bug)</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader-uint-1" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+flat out highp uint uvalue;
+uniform highp int ivalue;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+ uvalue = uint(ivalue) >> 31u;
+}
+</script>
+<script id="fshader-uint-1" type="x-shader/x-fragment">#version 300 es
+flat in highp uint uvalue;
+out highp vec4 myFragColor;
+
+void main() {
+ if (uvalue == 1u)
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="vshader-simple" type="x-shader/x-vertex">#version 300 es
+in vec3 aPosition;
+
+void main() {
+ gl_Position = vec4(aPosition, 1);
+}
+</script>
+<script id="fshader-uint-2" type="x-shader/x-fragment">#version 300 es
+uniform highp int ivalue;
+out highp vec4 myFragColor;
+
+void main() {
+ uint uvalue = uint(ivalue) >> 31u;
+
+ if (uvalue == 1u)
+ myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script type="application/javascript">
+"use strict";
+description("Verify (uint(int) >> 31) works correctly");
+debug("");
+var wtu = WebGLTestUtils;
+function test() {
+ var gl = wtu.create3DContext("canvas", undefined, 2);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ wtu.setupUnitQuad(gl);
+
+ var testCases = [
+ { vshader: "vshader-uint-1", fshader: "fshader-uint-1", desc: "vertex shader uint" },
+ { vshader: "vshader-simple", fshader: "fshader-uint-2", desc: "fragment shader uint" },
+ ];
+
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ var test = testCases[idx];
+
+ debug("");
+ var program = wtu.setupProgram(gl, [test.vshader, test.fshader], ["aPosition"]);
+ if (!program) {
+ testFailed("Fail to set up program");
+ } else {
+ var uniformLoc = gl.getUniformLocation(program, 'ivalue');
+ gl.uniform1i(uniformLoc, -1);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255]);
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from testing");
+ }
+ }
+};
+
+test();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/unary-minus-operator-in-dynamic-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/unary-minus-operator-in-dynamic-loop.html
new file mode 100644
index 0000000000..200acbe6de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/unary-minus-operator-in-dynamic-loop.html
@@ -0,0 +1,248 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+<meta charset="utf-8">
+<title>Unary minus operator on int or uint variables in a dynamic loop in vertex shader should work</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+
+<body>
+<canvas id="canvas" style="border: none;" width="1024" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="shader-vs-int" type="x-shader/x-vertex">#version 300 es
+in highp vec4 pos;
+
+uniform int u_one;
+uniform int u_two;
+uniform int u_three;
+
+out mediump vec4 v_color;
+void main() {
+ int array[3];
+ array[0] = u_one; // array[0] should be 1
+ array[1] = -u_two; // array[1] should be -2
+ array[2] = u_three; // array[2] should be 3
+ int result = 0;
+ for (int i = 0; i < u_three; i++) {
+ result += array[i];
+ }
+ v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = pos;
+}
+</script>
+
+<script id="shader-vs-uint" type="x-shader/x-vertex">#version 300 es
+in highp vec4 pos;
+
+uniform uint u_one;
+uniform uint u_two;
+uniform uint u_three;
+
+out mediump vec4 v_color;
+void main() {
+ uint array[3];
+ array[0] = u_one; // array[0] should be 1u
+ array[1] = -u_two; // array[1] should be -2u
+ array[2] = u_three; // array[2] should be 3u
+ uint result = 0u;
+ for (uint i = 0u; i < u_three; i++) {
+ result += array[i];
+ }
+ v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = pos;
+}
+</script>
+
+<script id="shader-vs-int-multiple-brackets" type="x-shader/x-vertex">#version 300 es
+in highp vec4 pos;
+
+uniform int u_one;
+uniform int u_two;
+uniform int u_three;
+
+out mediump vec4 v_color;
+void main() {
+ int array[3];
+ array[0] = u_one; // array[0] should be 1
+ array[1] = -(-(-u_two + 1) + 1); // array[1] should be -2
+ array[2] = u_three; // array[2] should be 3
+ int result = 0;
+ for (int i = 0; i < u_three; i++) {
+ result += array[i];
+ }
+ v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = pos;
+}
+</script>
+
+<script id="shader-vs-uint-multiple-brackets" type="x-shader/x-vertex">#version 300 es
+in highp vec4 pos;
+
+uniform uint u_one;
+uniform uint u_two;
+uniform uint u_three;
+
+out mediump vec4 v_color;
+void main() {
+ uint array[3];
+ array[0] = u_one; // array[0] should be 1u
+ array[1] = -(-(-u_two + 1u) + 1u); // array[1] should be -2u
+ array[2] = u_three; // array[2] should be 3u
+ uint result = 0u;
+ for (uint i = 0u; i < u_three; i++) {
+ result += array[i];
+ }
+ v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = pos;
+}
+</script>
+
+<script id="shader-vs-int-implicit-unary-minus" type="x-shader/x-vertex">#version 300 es
+in highp vec4 pos;
+
+uniform int u_one;
+uniform int u_two;
+uniform int u_three;
+
+out mediump vec4 v_color;
+void main() {
+ int array[3];
+ array[0] = u_one; // array[0] should be 1
+ array[1] = 1 - u_two;
+ array[2] = u_three; // array[2] should be 3
+ int result = 0;
+ array[1] -= 1; // array[1] should be -u_two == -2
+ for (int i = 0; i < u_three; i++) {
+ result += array[i];
+ }
+ v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = pos;
+}
+</script>
+
+<script id="shader-vs-uint-implicit-unary-minus" type="x-shader/x-vertex">#version 300 es
+in highp vec4 pos;
+
+uniform uint u_one;
+uniform uint u_two;
+uniform uint u_three;
+
+out mediump vec4 v_color;
+void main() {
+ uint array[3];
+ array[0] = u_one; // array[0] should be 1u
+ array[1] = 1u - u_two;
+ array[2] = u_three; // array[2] should be 3u
+ uint result = 0u;
+ array[1] -= 1u; // array[1] should be -u_two == -2u
+ for (uint i = 0u; i < u_three; i++) {
+ result += array[i];
+ }
+ v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+ gl_Position = pos;
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">#version 300 es
+in mediump vec4 v_color;
+out mediump vec4 o_color;
+
+void main() {
+ o_color = v_color;
+}
+</script>
+
+<script>
+"use strict";
+
+function test() {
+ description();
+ debug("This test exposes an Intel driver bug on Windows.");
+ debug("");
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("canvas", undefined, 2);
+ if (!gl) {
+ testFailed("WebGL 2 context does not exist");
+ return;
+ }
+
+ var testNum = 0;
+ var border = 10; // border between test squares for visibility
+ var squareSize = 128;
+ var expectedColor = [0, 255, 0, 255]; // green
+
+ function subTest_int(message, VertexShader) {
+ debug(message);
+ var startX = (squareSize + border) * testNum;
+ var program = wtu.setupProgram(
+ gl, [VertexShader, "shader-fs"], ["pos"], null, true);
+ gl.viewport(startX, 0, squareSize, squareSize);
+
+ var one = gl.getUniformLocation(program, "u_one");
+ var two = gl.getUniformLocation(program, "u_two");
+ var three = gl.getUniformLocation(program, "u_three");
+ gl.uniform1i(one, 1);
+ gl.uniform1i(two, 2);
+ gl.uniform1i(three, 3);
+
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(
+ gl, startX, 0, squareSize, squareSize,
+ expectedColor, "square should be green", 1);
+ debug("");
+ testNum++;
+ }
+
+ function subTest_uint(message, VertexShader) {
+ debug(message);
+ var startX = (squareSize + border) * testNum;
+ var program = wtu.setupProgram(
+ gl, [VertexShader, "shader-fs"], ["pos"], null, true);
+ gl.viewport(startX, 0, squareSize, squareSize);
+
+ var one = gl.getUniformLocation(program, "u_one");
+ var two = gl.getUniformLocation(program, "u_two");
+ var three = gl.getUniformLocation(program, "u_three");
+ gl.uniform1ui(one, 1);
+ gl.uniform1ui(two, 2);
+ gl.uniform1ui(three, 3);
+
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(
+ gl, startX, 0, squareSize, squareSize,
+ expectedColor, "square should be green", 1);
+ debug("");
+ testNum++;
+ }
+
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ wtu.setupUnitQuad(gl);
+ subTest_int("Test unary minus operator on int.", "shader-vs-int");
+ subTest_uint("Test unary minus operator on unsigned int.", "shader-vs-uint");
+ subTest_int("Test unary minus operator on int with multiple brackets.", "shader-vs-int-multiple-brackets");
+ subTest_uint("Test unary minus operator on unsigned int with multiple brackets.", "shader-vs-uint-multiple-brackets");
+ subTest_int("Test implicit unary minus operator on int.", "shader-vs-int-implicit-unary-minus");
+ subTest_uint("Test implicit unary minus operator on unsigned int.", "shader-vs-uint-implicit-unary-minus");
+ }
+}
+
+test();
+var successfullyParsed = true;
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layout-match.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layout-match.html
new file mode 100644
index 0000000000..b92cefc882
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layout-match.html
@@ -0,0 +1,57 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Uniform Block Layout Behavior Testing</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="ES3VertexShader" type="x-shader/x-vertex">#version 300 es
+layout(std140) uniform Block
+{
+ highp vec4 val;
+};
+
+void main() {
+ gl_Position = vec4(val);
+}
+</script>
+<script id="ES3FragmentShader" type="x-shader/x-fragment">#version 300 es
+uniform Block
+{
+ highp vec4 val;
+};
+out highp vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(val);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "ES3VertexShader",
+ vShaderSuccess: true,
+ fShaderId: "ES3FragmentShader",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "A uniform block's layout defaults to std140 if not specified."
+ },
+], 2);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layouts.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layouts.html
new file mode 100644
index 0000000000..2dbfc664ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-block-layouts.html
@@ -0,0 +1,63 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Disallowed uniform block layouts</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderPackedUniformBlock" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+layout(packed) uniform foo {
+ vec4 bar;
+};
+
+void main() {
+ my_FragColor = bar;
+}
+</script>
+<script id="fshaderSharedUniformBlock" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+layout(shared) uniform foo {
+ vec4 bar;
+};
+
+void main() {
+ my_FragColor = bar;
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("WebGL does not allow interface blocks with shared or packed layouts.");
+
+GLSLConformanceTester.runTests([
+{
+ fShaderId: 'fshaderPackedUniformBlock',
+ fShaderSuccess: false,
+ passMsg: 'Packed uniform buffers are disallowed'
+},
+{
+ fShaderId: 'fshaderSharedUniformBlock',
+ fShaderSuccess: false,
+ passMsg: 'Shared uniform buffers are disallowed'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-struct-with-non-square-matrix.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-struct-with-non-square-matrix.html
new file mode 100644
index 0000000000..9df7b5a88f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uniform-struct-with-non-square-matrix.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL uniform struct with a non-square matrix test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderUniformStructWithNonSquareMatrixAndBoolean" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out highp vec4 my_color;
+struct S
+{
+ mat2x4 m;
+ bool b;
+};
+uniform S uni;
+void main()
+{
+ my_color = vec4(0, 1, 0, 1);
+ if (!uni.b) { my_color.g = 0.0; }
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderUniformStructWithNonSquareMatrixAndBoolean',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Set a boolean member in a uniform struct that also contains a non-square-matrix',
+ uniforms: [{name: "uni.b", functionName: "uniform1i", value: 1}]
+},
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uninitialized-local-global-variables.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uninitialized-local-global-variables.html
new file mode 100644
index 0000000000..0d5be3da22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/uninitialized-local-global-variables.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Uninitialized local/global variables should be initialized (ESSL 3.00 cases)</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+
+<!--
+This test covers cases that can't be tested with ESSL 1.00 due to Appendix A limitations.
+The ESSL 1.00 cases are covered in conformance/glsl/misc/uninitialized-local-global-variables.html
+-->
+
+<script id="vs_uninit_in_frag" type="x-shader/x-vertex">#version 300 es
+precision highp float;
+in vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+
+<!-- Uninitialized variables in a for loop initializer in fragment shader -->
+<script id="fs_uninit_variables_in_loop_in_frag" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+ int i = 0;
+ for (vec4 uninit, uninit2[2] = vec4[2](uninit, uninit); i < 1; ++i) {
+ my_FragColor = uninit2[0];
+ }
+}
+</script>
+
+<!-- Uninitialized nameless struct in a for loop initializer in fragment shader -->
+<script id="fs_uninit_nameless_struct_in_loop_in_frag" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+ int i = 0;
+ for (struct { vec4 v; } uninit; i < 1; ++i) {
+ my_FragColor = uninit.v;
+ }
+}
+</script>
+
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Uninitialized local/global variables should be initialized: http://anglebug.com/1966');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", undefined, 2);
+wtu.setupUnitQuad(gl);
+
+var cases = [
+ {
+ name: "Uninitialized variables in a for loop initializer in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_variables_in_loop_in_frag"],
+ },
+ {
+ name: "Uninitialized nameless struct in a for loop initializer in fragment shader",
+ prog: ["vs_uninit_in_frag", "fs_uninit_nameless_struct_in_loop_in_frag"],
+ }
+];
+
+function runTest() {
+ for (var i = 0; i < cases.length; ++i) {
+ debug("");
+ debug(cases[i].name);
+ var program = wtu.setupProgram(gl, cases[i].prog, ["a_position"], undefined, true);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 0, 0]);
+ }
+
+ debug("");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/valid-invariant.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/valid-invariant.html
new file mode 100644
index 0000000000..a4fffaf061
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/valid-invariant.html
@@ -0,0 +1,95 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Positive tests for the use of the invariant qualifier and pragma</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertexShaderInvariant" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+invariant out vec4 v_varying;
+
+void main()
+{
+ v_varying = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderSeparateInvariant" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+out vec4 v_varying;
+invariant v_varying;
+
+void main()
+{
+ v_varying = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position = v_varying;
+}
+</script>
+<script id="vertexShaderGlobalInvariant" type="text/something-not-javascript">#version 300 es
+#pragma STDGL invariant(all)
+precision mediump float;
+out vec4 v_varying;
+
+void main()
+{
+ v_varying = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position = v_varying;
+}
+</script>
+<script id="fragmentShaderVariant" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+
+in vec4 v_varying;
+out vec4 my_color;
+
+void main()
+{
+ my_color = v_varying;
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+GLSLConformanceTester.runTests([
+ {
+ vShaderId: "vertexShaderInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant varying and fragment shader with variant varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderGlobalInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant (global setting) varying and fragment shader with variant varying must succeed",
+ },
+ {
+ vShaderId: "vertexShaderSeparateInvariant",
+ vShaderSuccess: true,
+ fShaderId: "fragmentShaderVariant",
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: "vertex shader with invariant (separately set) varying and fragment shader with variant varying must succeed",
+ },
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/varying-struct-inline-definition.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/varying-struct-inline-definition.html
new file mode 100644
index 0000000000..f3ac2485e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/varying-struct-inline-definition.html
@@ -0,0 +1,62 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL varying struct with inline definition test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+
+in vec4 vPosition;
+
+flat out struct S {
+ int field;
+} v_s;
+
+void main() {
+ v_s.field = 1;
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+
+flat in struct S {
+ int field;
+} v_s;
+
+out vec4 my_FragColor;
+
+void main() {
+ my_FragColor = vec4(1 - v_s.field, v_s.field, 0, 1);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description();
+
+GLSLConformanceTester.runRenderTests([
+{
+ vShaderId: 'vshader',
+ vShaderSuccess: true,
+ fShaderId: 'fshader',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Vertex output struct / fragment input struct with an inline definition should compile and link'
+}
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html
new file mode 100644
index 0000000000..767bfd915d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html
@@ -0,0 +1,67 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL dynamic vector and matrix indexing test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderLValueVectorBeingIndexedHasSideEffects" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+int sideEffectCounter = 0;
+
+int funcWithSideEffects() {
+ sideEffectCounter++;
+ return 1;
+}
+
+void main() {
+ vec4 V[2];
+ V[0] = vec4(1.0, 2.0, 3.0, 4.0);
+ V[1] = vec4(5.0, 6.0, 7.0, 8.0);
+ // In case this is broken down to two expressions where one reads V[funcWithSideEffects()]
+ // and another writes it, it needs to be made sure that funcWithSideEffects() only gets called once.
+ V[funcWithSideEffects()][u_zero + 1]++;
+ vec4 expectedV0 = vec4(1.0, 2.0, 3.0, 4.0);
+ vec4 expectedV1 = vec4(5.0, 7.0, 7.0, 8.0);
+ float f = 1.0 - distance(V[0], expectedV0) - distance(V[1], expectedV1);
+ if (sideEffectCounter != 1) {
+ f = 0.0;
+ }
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Dynamic indexing of vectors and matrices should work.");
+
+debug("This test exposes a NVidia driver bug on Linux");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderLValueVectorBeingIndexedHasSideEffects',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index a vector expression that itself has side effects, in an l-value'
+},
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
new file mode 100644
index 0000000000..4b82d6ed30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL swizzled vector l-value dynamic indexing test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!--
+ The shader first assigns v.x to v.z (1.0)
+ Then v.y to v.y (2.0)
+ Then v.z to v.x (1.0)
+-->
+<script id="fshaderSwizzledLValueIndexing" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+void main() {
+ vec3 v = vec3(1.0, 2.0, 3.0);
+ for (int i = 0; i < 3; i++) {
+ v.zyx[i] = v[i];
+ }
+ my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Dynamic indexing of swizzled l-values should work.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderSwizzledLValueIndexing',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index an l-value swizzled vector'
+},
+], 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing.html
new file mode 100644
index 0000000000..5bf60578ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/vector-dynamic-indexing.html
@@ -0,0 +1,369 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL dynamic vector and matrix indexing test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderIndexMatrixTwice" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main() {
+ mat2 m = mat2(0.0, 0.0, 0.0, 1.0);
+ float f = m[u_zero + 1][u_zero + 1];
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexWithValueFromIndexingExpression" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main() {
+ ivec2 i = ivec2(0, 2);
+ vec4 v = vec4(0.0, 0.2, 1.0, 0.4);
+ float f = v[i[u_zero + 1]];
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexLValue" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ v[u_zero + 1] = 5.0;
+ vec4 expected = vec4(1.0, 5.0, 3.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexLValueWithValueFromIndexingExpression" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main() {
+ ivec2 i = ivec2(0, 2);
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ v[i[u_zero + 1]] = 5.0;
+ vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexBuiltInFunctionCallOutParameter" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ modf(5.5, v[u_zero + 3]);
+ vec4 expected = vec4(1.0, 2.0, 3.0, 5.0);
+ float f = 1.0 - distance(v, expected);
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexUserDefinedFunctionCallOutParameter" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void foo(out float f) {
+ modf(5.5, f);
+}
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ foo(v[u_zero + 3]);
+ vec4 expected = vec4(1.0, 2.0, 3.0, 5.0);
+ float f = 1.0 - distance(v, expected);
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexUserDefinedFunctionCallInOutParameter" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void foo(inout float f) {
+ float g = f + 2.5;
+ modf(g, f);
+}
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ foo(v[u_zero + 2]);
+ vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexWithSideEffects" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+int sideEffectCounter = 0;
+
+int funcWithSideEffects() {
+ sideEffectCounter++;
+ return 2;
+}
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ v[funcWithSideEffects()] = 5.0;
+ vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ if (sideEffectCounter != 1) {
+ f = 0.0;
+ }
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexInOutWithSideEffects" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+int sideEffectCounter = 0;
+
+int funcWithSideEffects() {
+ sideEffectCounter++;
+ return 2;
+}
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ v[funcWithSideEffects()]++;
+ vec4 expected = vec4(1.0, 2.0, 4.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ if (sideEffectCounter != 1) {
+ f = 0.0;
+ }
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexUserDefinedFunctionCallInOutParameterWithIndexWithSideEffects" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+int sideEffectCounter = 0;
+
+void foo(inout float f) {
+ float g = f + 2.5;
+ modf(g, f);
+}
+
+int funcWithSideEffects() {
+ sideEffectCounter++;
+ return 2;
+}
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ foo(v[funcWithSideEffects()]);
+ vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ if (sideEffectCounter != 1) {
+ f = 0.0;
+ }
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexLValueWithUint" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform uint u_zero;
+
+void main() {
+ vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+ v[u_zero] = 5.0;
+ vec4 expected = vec4(5.0, 2.0, 3.0, 4.0);
+ float f = 1.0 - distance(v, expected);
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script id="fshaderIndexUniform" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform vec4 u_zeroVec;
+uniform uint u_zero;
+
+void main() {
+ // This test is just to catch a crash bug that occurred in ANGLE's workaround.
+ // Rendering result is not meaningful.
+ float f = u_zeroVec[u_zero];
+ my_FragColor = vec4(f, 1.0, 0.0, 1.0);
+}
+</script>
+<script id="fshaderSequenceDynamicIndexingVectorLvalue" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform int u_zero;
+
+int sideEffectCounter = 0;
+float func() {
+ ++sideEffectCounter;
+ return -1.0;
+}
+
+void main() {
+ vec4 v = vec4(0.0, 2.0, 4.0, 6.0);
+ float f = (func(), (++v[u_zero + sideEffectCounter]));
+ my_FragColor = (abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCounter == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script id="fshaderIndexMatrixTwiceInLValue" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main() {
+ mat2 m = mat2(0.0, 0.0, 0.0, 0.0);
+ m[u_zero + 1][u_zero + 1] = float(u_zero + 1);
+ float f = m[1][1];
+ my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("Dynamic indexing of vectors and matrices should work.");
+
+debug("Dynamic indexing of vectors and matrices requires complex workarounds on HLSL backends. Try to test possible bugs those workarounds might have.");
+
+GLSLConformanceTester.runRenderTests([
+{
+ fShaderId: 'fshaderIndexMatrixTwice',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index matrix and then index the resulting vector in the same expression'
+},
+{
+ fShaderId: 'fshaderIndexWithValueFromIndexingExpression',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index a vector with an index that is the result of indexing'
+},
+{
+ fShaderId: 'fshaderIndexLValue',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index on the left-hand side of assignment'
+},
+{
+ fShaderId: 'fshaderIndexLValueWithValueFromIndexingExpression',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index on the left-hand side of assignment with an index that is the result of indexing'
+},
+{
+ fShaderId: 'fshaderIndexBuiltInFunctionCallOutParameter',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index the out parameter passed to built-in modf'
+},
+{
+ fShaderId: 'fshaderIndexUserDefinedFunctionCallOutParameter',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index an out parameter passed to an user-defined function'
+},
+{
+ fShaderId: 'fshaderIndexUserDefinedFunctionCallInOutParameter',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index an inout parameter passed to an user-defined function'
+},
+{
+ fShaderId: 'fshaderIndexWithSideEffects',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Use expression with side effects as an index of an l-value'
+},
+{
+ fShaderId: 'fshaderIndexInOutWithSideEffects',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Use expression with side effects as an index of an l-value that is both read and written'
+},
+{
+ fShaderId: 'fshaderIndexUserDefinedFunctionCallInOutParameterWithIndexWithSideEffects',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index an inout parameter passed to an user-defined function with an index with side effects'
+},
+{
+ fShaderId: 'fshaderIndexLValueWithUint',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index on the left-hand side of assignment with an uint'
+},
+{
+ fShaderId: 'fshaderIndexUniform',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index a uniform with a uniform'
+},
+{
+ fShaderId: 'fshaderSequenceDynamicIndexingVectorLvalue',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Sequence operator with dynamic indexing of a vector as an l-value inside'
+},
+{
+ fShaderId: 'fshaderIndexMatrixTwiceInLValue',
+ fShaderSuccess: true,
+ linkSuccess: true,
+ passMsg: 'Index matrix and then index the resulting vector in the same expression inside an l-value'
+}
+], 2);
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt
new file mode 100644
index 0000000000..8f1343f91d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt
@@ -0,0 +1,8 @@
+--min-version 2.0.1 blend-integer.html
+expando-loss-2.html
+getextension-while-pbo-bound-stability.html
+instanceof-test.html
+--min-version 2.0.1 null-object-behaviour-2.html
+object-deletion-behaviour-2.html
+uninitialized-test-2.html
+views-with-offsets.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html
new file mode 100644
index 0000000000..40ccfd0d86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html
@@ -0,0 +1,176 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Blend Integer Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css" />
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="outputVertexShader" type="x-shader/x-vertex">
+#version 300 es
+in vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="outputFragmentShaderSigned" type="x-shader/x-fragment">
+#version 300 es
+layout(location = 1) out highp vec4 o_drawBuffer1;
+layout(location = 2) out highp ivec4 o_drawBuffer2;
+layout(location = 3) out highp vec4 o_drawBuffer3;
+void main(void)
+{
+ o_drawBuffer1 = vec4(0, 0, 0, 0);
+ o_drawBuffer2 = ivec4(0, 0, 0, 0);
+ o_drawBuffer3 = vec4(0, 0, 0, 0);
+}
+</script>
+<script id="outputFragmentShaderUnsigned" type="x-shader/x-fragment">
+ #version 300 es
+ layout(location = 1) out highp vec4 o_drawBuffer1;
+ layout(location = 2) out highp uvec4 o_drawBuffer2;
+ layout(location = 3) out highp vec4 o_drawBuffer3;
+ void main(void)
+ {
+ o_drawBuffer1 = vec4(0, 0, 0, 0);
+ o_drawBuffer2 = uvec4(0, 0, 0, 0);
+ o_drawBuffer3 = vec4(0, 0, 0, 0);
+ }
+ </script>
+
+<script>
+"use strict";
+description("This test verifies correct behavior of min/max blending operations on integer attachments.");
+
+debug("");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext(null, undefined, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ debug("")
+ debug("GL_MIN");
+ runTest(false, gl.MIN);
+ runTest(true, gl.MIN);
+
+ debug("")
+ debug("GL_MAX");
+ runTest(false, gl.MAX);
+ runTest(true, gl.MAX);
+}
+
+function compareValue(value, attachment, isSigned) {
+ const pixel = isSigned ? new Int32Array(4) : new Uint32Array(4);
+ gl.readBuffer(attachment);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA_INTEGER, isSigned ? gl.INT : gl.UNSIGNED_INT, pixel);
+ let pass = true;
+ for (let i = 0; i < 4; i++) {
+ if (value[i] != pixel[i]) {
+ testFailed(`Read value of channel ${i} should be ${pixel[i]}, was ${value[i]}.`);
+ pass = false;
+ }
+ }
+ return pass;
+}
+
+function runTest(isSigned, operation) {
+ gl.viewport(0, 0, 1, 1);
+ gl.disable(gl.BLEND);
+
+ const program = wtu.setupProgram(gl,
+ ["outputVertexShader",
+ isSigned ? "outputFragmentShaderSigned" : "outputFragmentShaderUnsigned"],
+ ['vPosition'], [0]);
+ const quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+
+ // Setup render targets
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ const rb1 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb1);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 50, 50);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, rb1);
+
+ const rb2 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb2);
+ gl.renderbufferStorage(gl.RENDERBUFFER, isSigned ? gl.RGBA32I : gl.RGBA32UI, 50, 50);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.RENDERBUFFER, rb2);
+
+ const rb3 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb3);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 50, 50);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT3, gl.RENDERBUFFER, rb3);
+
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3]);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Pipeline setup complete.");
+
+ if (isSigned) {
+ const clearValue = new Int32Array([-1, 2, -3, 4]);
+ gl.clearBufferiv(gl.COLOR, 2, clearValue);
+ if (compareValue(clearValue, gl.COLOR_ATTACHMENT2, isSigned)) {
+ testPassed("Signed clear passed.");
+ } else {
+ testFailed("Signed clear failed.");
+ }
+ } else {
+ const clearValue = new Uint32Array([1, 2, 3, 4]);
+ gl.clearBufferuiv(gl.COLOR, 2, clearValue);
+ if (compareValue(clearValue, gl.COLOR_ATTACHMENT2, isSigned)) {
+ testPassed("Unsigned clear passed.");
+ } else {
+ testFailed("Unsigned clear failed.");
+ }
+ }
+
+ gl.blendEquation(operation);
+ gl.enable(gl.BLEND);
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw complete.");
+
+ if (isSigned) {
+ const drawValue = new Int32Array([0, 0, 0, 0]);
+ if (compareValue(drawValue, gl.COLOR_ATTACHMENT2, isSigned)) {
+ testPassed("Signed draw passed.");
+ } else {
+ testFailed("Signed draw failed.");
+ }
+ } else {
+ const drawValue = new Uint32Array([0, 0, 0, 0]);
+ if (compareValue(drawValue, gl.COLOR_ATTACHMENT2, isSigned)) {
+ testPassed("Unsigned draw passed.");
+ } else {
+ testFailed("Unsigned draw failed.");
+ }
+ }
+ gl.deleteRenderbuffer(rb1);
+ gl.deleteRenderbuffer(rb2);
+ gl.deleteRenderbuffer(rb3);
+ gl.deleteFramebuffer(fb);
+ gl.deleteProgram(program);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html
new file mode 100644
index 0000000000..141a5377a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html
@@ -0,0 +1,285 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL 2 Object Expandos Conformance Test</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script>
+"use strict";
+description("This test verifies that WebGL object expandos are preserved across garbage collections.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false}, 2);
+
+// Helpers that set expandos and verify they are set to the correct value.
+var expandoValue = "WebGL is awesome!"
+function setTestExpandos(instance, extra) {
+ instance.expando1 = expandoValue;
+ instance.expando2 = { subvalue : expandoValue };
+ instance.expando_extra = extra;
+}
+function verifyTestExpandos(instance, msg, extra) {
+ assertMsg(instance.expando1 === expandoValue, msg + ": Expect basic expando to survive despite GC.");
+ assertMsg(instance.expando2 && instance.expando2.subvalue === expandoValue, msg + ": Expect subobject expando to survive despite GC.");
+ assertMsg(instance.expando_extra === extra, msg + ": Expect extra expando to survive despite GC.");
+}
+
+// Tests that we don't get expando loss for bound resources where the
+// only remaining reference is internal to WebGL
+function testBasicBindings() {
+ debug('Basic Bindings');
+
+ // Test data that describes how to create, bind, and retrieve an object off of the context
+ var glProt = Object.getPrototypeOf(gl);
+ var simpleData = [
+ {
+ typeName: 'WebGLSampler',
+ creationFn: glProt.createSampler,
+ bindFn: glProt.bindSampler,
+ bindConstant: 0,
+ retrieveConstant: glProt.SAMPLER_BINDING,
+ name: "SAMPLER_BINDING",
+ },
+ {
+ typeName: 'WebGLTransformFeedback',
+ creationFn: glProt.createTransformFeedback,
+ bindFn: glProt.bindTransformFeedback,
+ bindConstant: glProt.TRANSFORM_FEEDBACK,
+ retrieveConstant: glProt.TRANSFORM_FEEDBACK_BINDING,
+ name: "TRANSFORM_FEEDBACK_BINDING",
+ },
+ {
+ typeName: 'WebGLVertexArrayObject',
+ creationFn: glProt.createVertexArray,
+ bindFn: glProt.bindVertexArray,
+ bindConstant: null,
+ retrieveConstant: glProt.VERTEX_ARRAY_BINDING,
+ name: "VERTEX_ARRAY_BINDING",
+ },
+ {
+ typeName: 'WebGLTexture',
+ creationFn: glProt.createTexture,
+ bindFn: glProt.bindTexture,
+ bindConstant: glProt.TEXTURE_3D,
+ retrieveConstant: glProt.TEXTURE_BINDING_3D,
+ name: "TEXTURE_BINDING_3D",
+ },
+ {
+ typeName: 'WebGLTexture',
+ creationFn: glProt.createTexture,
+ bindFn: glProt.bindTexture,
+ bindConstant: glProt.TEXTURE_2D_ARRAY,
+ retrieveConstant: glProt.TEXTURE_BINDING_2D_ARRAY,
+ name: "TEXTURE_BINDING_2D_ARRAY",
+ },
+ {
+ typeName: 'WebGLFramebuffer',
+ creationFn: glProt.createFramebuffer,
+ bindFn: glProt.bindFramebuffer,
+ bindConstant: glProt.READ_FRAMEBUFFER,
+ retrieveConstant: glProt.READ_FRAMEBUFFER_BINDING,
+ name: "READ_FRAMEBUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLFramebuffer',
+ creationFn: glProt.createFramebuffer,
+ bindFn: glProt.bindFramebuffer,
+ bindConstant: glProt.DRAW_FRAMEBUFFER,
+ retrieveConstant: glProt.DRAW_FRAMEBUFFER_BINDING,
+ name: "DRAW_FRAMEBUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.COPY_READ_BUFFER,
+ retrieveConstant: glProt.COPY_READ_BUFFER_BINDING,
+ name: "COPY_READ_BUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.COPY_WRITE_BUFFER,
+ retrieveConstant: glProt.COPY_WRITE_BUFFER_BINDING,
+ name: "COPY_WRITE_BUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.PIXEL_PACK_BUFFER,
+ retrieveConstant: glProt.PIXEL_PACK_BUFFER_BINDING,
+ name: "PIXEL_PACK_BUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.PIXEL_UNPACK_BUFFER,
+ retrieveConstant: glProt.PIXEL_UNPACK_BUFFER_BINDING,
+ name: "PIXEL_UNPACK_BUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.TRANSFORM_FEEDBACK_BUFFER,
+ retrieveConstant: glProt.TRANSFORM_FEEDBACK_BUFFER_BINDING,
+ name: "TRANSFORM_FEEDBACK_BUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBuffer,
+ bindConstant: glProt.UNIFORM_BUFFER,
+ retrieveConstant: glProt.UNIFORM_BUFFER_BINDING,
+ name: "UNIFORM_BUFFER_BINDING",
+ },
+ ];
+
+ simpleData.forEach(function(test) {
+ var instance = test.creationFn.call(gl);
+ var msg = "getParameter(" + test.name + ")";
+ setTestExpandos(instance);
+
+ if (test.bindConstant === null) {
+ test.bindFn.call(gl, instance);
+ } else {
+ test.bindFn.call(gl, test.bindConstant, instance);
+ }
+ assertMsg(instance === gl.getParameter(test.retrieveConstant), msg + " returns instance that was bound.");
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ instance = null;
+ webglHarnessCollectGarbage();
+
+ var retrievedObject = gl.getParameter(test.retrieveConstant);
+ verifyTestExpandos(retrievedObject, msg);
+ shouldBeType(retrievedObject, test.typeName);
+ debug('');
+ });
+}
+
+function testIndexedBindings() {
+ debug('Indexed Bindings');
+
+ // Test data that describes how to create, bind, and retrieve an indexed object off of the context
+ var glProt = Object.getPrototypeOf(gl);
+ var simpleData = [
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBufferBase,
+ indexMax: gl.getParameter(glProt.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) - 1,
+ bindConstant: glProt.TRANSFORM_FEEDBACK_BUFFER,
+ retrieveConstant: glProt.TRANSFORM_FEEDBACK_BUFFER_BINDING,
+ name: "TRANSFORM_FEEDBACK_BUFFER_BINDING",
+ },
+ {
+ typeName: 'WebGLBuffer',
+ creationFn: glProt.createBuffer,
+ bindFn: glProt.bindBufferBase,
+ indexMax: gl.getParameter(glProt.MAX_UNIFORM_BUFFER_BINDINGS) - 1,
+ bindConstant: glProt.UNIFORM_BUFFER,
+ retrieveConstant: glProt.UNIFORM_BUFFER_BINDING,
+ name: "UNIFORM_BUFFER_BINDING",
+ },
+ ];
+
+ simpleData.forEach(function(test) {
+ // This test sets all of the separate indexed bindings first, then
+ // tests them all. It puts a different extra expando on each indexed
+ // parameter so that we can ensure they're all distinct.
+ var instances = [];
+ for (var i = 0; i <= test.indexMax; i++) {
+ var instance = test.creationFn.call(gl);
+ var msg = "getIndexedParameter(" + test.name + ", " + i + ")";
+ setTestExpandos(instance, i);
+ instances[i] = instance;
+ test.bindFn.call(gl, test.bindConstant, i, instance);
+ }
+
+ for (var i = 0; i <= test.indexMax; i++) {
+ var msg = "getIndexedParameter(" + test.name + ", " + i + ")";
+ assertMsg(instances[i] === gl.getIndexedParameter(test.retrieveConstant, i), msg + " returns instance that was bound.");
+ }
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ instances = null;
+ webglHarnessCollectGarbage();
+
+ for (var i = 0; i <= test.indexMax; i++) {
+ var msg = "getIndexedParameter(" + test.name + ", " + i + ")";
+ var retrievedObject = gl.getIndexedParameter(test.retrieveConstant, i);
+ verifyTestExpandos(retrievedObject, msg, i);
+ shouldBeType(retrievedObject, test.typeName);
+ debug('');
+ }
+ });
+}
+
+function testQueries() {
+ debug('Query');
+
+ expandoValue = "First query";
+ var query1 = gl.createQuery();
+ setTestExpandos(query1);
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, query1);
+
+ expandoValue = "Second query";
+ var query2 = gl.createQuery();
+ setTestExpandos(query2);
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query2);
+
+
+ assertMsg(query1 === gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY), "CURRENT_QUERY returns instance that was bound.");
+ assertMsg(query2 === gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY), "CURRENT_QUERY returns instance that was bound.");
+
+ // Garbage collect Javascript references. Remaining references should be internal to WebGL.
+ query1 = null;
+ query2 = null;
+ webglHarnessCollectGarbage();
+
+ var retrievedQuery1 = gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY);
+ var retrievedQuery2 = gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY);
+ expandoValue = "First query";
+ verifyTestExpandos(retrievedQuery1, "Query");
+ shouldBeType(retrievedQuery1, 'WebGLQuery');
+
+ expandoValue = "Second query";
+ verifyTestExpandos(retrievedQuery2, "Query");
+ shouldBeType(retrievedQuery2, 'WebGLQuery');
+
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+
+ debug('');
+}
+
+// Run tests
+testBasicBindings();
+testIndexedBindings();
+testQueries();
+
+// FYI: There's no need to test WebGLSync objects because there is no notion of an "active" sync,
+// and thus no way to query them back out of the context.
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html
new file mode 100644
index 0000000000..73e34fdc1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html
@@ -0,0 +1,57 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 getExtension while PBO bound stability conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+
+function runTest(extension_name) {
+ debug("");
+ debug("getExtension('" + extension_name + "') while PIXEL_UNPACK_BUFFER bound should be stable");
+
+ var gl = wtu.create3DContext(null, undefined, 2);
+ if (!gl) {
+ testFailed("Fail to get a WebGL context");
+ return;
+ }
+
+ var pbo = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo);
+ var ext = gl.getExtension('EXT_color_buffer_float');
+ var gl_texture_float_linear = gl.getExtension(extension_name);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Late-enable of extension should succeed");
+ if (pbo != gl.getParameter(gl.PIXEL_UNPACK_BUFFER_BINDING)) {
+ testFailed("Fail to maintain PIXEL_UNPACK_BUFFER binding when enabling extension " + extension_name);
+ }
+}
+
+function runTests() {
+ debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=641643'>Chromium Issue 641642</a>");
+ runTest('EXT_color_buffer_float');
+ runTest('OES_texture_float_linear');
+}
+
+runTests();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.html
new file mode 100644
index 0000000000..4ecbd6e2d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL instanceof test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 color;
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/instanceof-test.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html
new file mode 100644
index 0000000000..1a65dc57bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html
@@ -0,0 +1,61 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Tests calling WebGL 2 APIs without providing the necessary objects");
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+var shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+
+for (let nullOrUndefined of [null, undefined]) {
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteQuery(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isQuery(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteSync(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isSync(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteTransformFeedback(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isTransformFeedback(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteSampler(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isSampler(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteVertexArray(${nullOrUndefined})`);
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isVertexArray(${nullOrUndefined})`);
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindSampler(0, ${nullOrUndefined})`);
+ shouldThrow(`gl.samplerParameteri(${nullOrUndefined}, gl.TEXTURE_MAG_FILTER, gl.NEAREST)`);
+ shouldThrow(`gl.samplerParameterf(${nullOrUndefined}, gl.TEXTURE_MAX_LOD, 1)`);
+ shouldThrow(`gl.getSamplerParameter(${nullOrUndefined}, gl.TEXTURE_MAX_LOD)`);
+
+ shouldThrow(`gl.waitSync(${nullOrUndefined}, 0, 0)`);
+ shouldThrow(`gl.clientWaitSync(${nullOrUndefined}, 0, 0)`);
+ shouldThrow(`gl.getSyncParameter(${nullOrUndefined}, gl.OBJECT_TYPE)`);
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, ${nullOrUndefined})`);
+ shouldThrow(`gl.transformFeedbackVaryings(${nullOrUndefined}, [], gl.SEPARATE_ATTRIBS)`);
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindVertexArray(${nullOrUndefined})`);
+}
+
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.html
new file mode 100644
index 0000000000..0551a1bd97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.html
@@ -0,0 +1,114 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests deletion behavior for WebGL2 buffer, sampler, vertexArray and transformFeedback objects.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+var shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+debug("");
+debug("buffer deletion");
+
+var bufferBaseUniform = gl.createBuffer();
+shouldBeNonNull("bufferBaseUniform");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, bufferBaseUniform)");
+shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "bufferBaseUniform");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferBaseUniform)");
+shouldBeFalse("gl.isBuffer(bufferBaseUniform)");
+shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, bufferBaseUniform)");
+shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+
+var bufferBaseTransformFeedback = gl.createBuffer();
+shouldBeNonNull("bufferBaseTransformFeedback");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferBaseTransformFeedback)");
+shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "bufferBaseTransformFeedback");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferBaseTransformFeedback)");
+shouldBeFalse("gl.isBuffer(bufferBaseTransformFeedback)");
+shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferBaseTransformFeedback)");
+shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)");
+
+var bufferRangeUniform = gl.createBuffer();
+shouldBeNonNull("bufferRangeUniform");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufferRangeUniform, 0, gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT)");
+shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "bufferRangeUniform");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferRangeUniform)");
+shouldBeFalse("gl.isBuffer(bufferRangeUniform)");
+shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufferRangeUniform, 0, gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT)");
+shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)");
+
+var bufferRangeTransformFeedback = gl.createBuffer();
+shouldBeNonNull("bufferRangeTransformFeedback");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferRangeTransformFeedback, 0, 4)");
+shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "bufferRangeTransformFeedback");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferRangeTransformFeedback)");
+shouldBeFalse("gl.isBuffer(bufferRangeTransformFeedback)");
+shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferRangeTransformFeedback, 0, 4)");
+shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)");
+
+debug("");
+debug("sampler deletion");
+
+var sampler = gl.createSampler();
+shouldBeNonNull("sampler");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindSampler(0, sampler)");
+shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "sampler");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteSampler(sampler)");
+shouldBeFalse("gl.isSampler(sampler)");
+shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindSampler(0, sampler)");
+shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)");
+
+debug("");
+debug("vertexArray deletion");
+
+var vertexArray = gl.createVertexArray();
+shouldBeNonNull("vertexArray");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindVertexArray(vertexArray)");
+shouldBe("gl.getParameter(gl.VERTEX_ARRAY_BINDING)", "vertexArray");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteVertexArray(vertexArray)");
+shouldBeFalse("gl.isVertexArray(vertexArray)");
+shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindVertexArray(vertexArray)");
+shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)");
+
+debug("");
+debug("transformFeedback deletion");
+
+var transformFeedback = gl.createTransformFeedback();
+shouldBeNonNull("transformFeedback");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback)");
+shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "transformFeedback");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTransformFeedback(transformFeedback)");
+shouldBeFalse("gl.isTransformFeedback(transformFeedback)");
+shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback)");
+shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)");
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html
new file mode 100644
index 0000000000..4befe35c93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html
@@ -0,0 +1,583 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Uninitialized GL Resources Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("Tests to check user code cannot access uninitialized data from GL resources.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", undefined, 2);
+if (!gl)
+ testFailed("Context created.");
+else
+ testPassed("Context created.");
+
+// This is the maximum size that will end up being allocated with the tests
+// currently written as they are. It could need to be increased later.
+var scratchBuffer = new ArrayBuffer(1024 * 1024 * 8 * 4);
+function zeroArrayBuffer(arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ arr[i] = 0;
+ }
+}
+function getUint32Array(length) {
+ var arr = new Uint32Array(scratchBuffer, 0, length);
+ zeroArrayBuffer(arr);
+ return arr;
+}
+function getInt32Array(length) {
+ var arr = new Int32Array(scratchBuffer, 0, length);
+ zeroArrayBuffer(arr);
+ return arr;
+}
+function getUint8Array(length) {
+ var arr = new Uint8Array(scratchBuffer, 0, length);
+ zeroArrayBuffer(arr);
+ return arr;
+}
+function getInt8Array(length) {
+ var arr = new Int8Array(scratchBuffer, 0, length);
+ zeroArrayBuffer(arr);
+ return arr;
+}
+
+function setupTexture(target, texWidth, texHeight, texDepth) {
+ var is3d = (target == gl.TEXTURE_3D || target == gl.TEXTURE_2D_ARRAY);
+ var texture = gl.createTexture();
+ gl.bindTexture(target, texture);
+ if (is3d) {
+ gl.texImage3D(target, 0, gl.RGBA8, texWidth, texHeight, texDepth, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ } else if (target == gl.TEXTURE_2D) {
+ gl.texImage2D(target, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ } else {
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+
+ // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
+ // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem)
+ // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time.
+
+ var badData = getUint8Array(texWidth * texHeight * texDepth * 4);
+ for (var i = 0; i < badData.length; ++i)
+ badData[i] = i % 255;
+
+ if (is3d) {
+ gl.texSubImage3D(target, 0, 0, 0, 0, texWidth, texHeight, texDepth, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ } else if (target == gl.TEXTURE_2D) {
+ gl.texSubImage2D(target, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ } else {
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData);
+ }
+ gl.finish(); // make sure it has been uploaded
+
+ gl.deleteTexture(texture);
+ gl.finish(); // make sure it has been deleted
+
+ var texture = gl.createTexture();
+ gl.bindTexture(target, texture);
+ return texture;
+}
+
+function checkNonZeroPixels(texture, target, format, type, texWidth, texHeight, level, layer, exceptions) {
+ var tol = 2;
+ var is3d = (target == gl.TEXTURE_3D || target == gl.TEXTURE_2D_ARRAY);
+ switch (target) {
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_X:
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ break;
+ default:
+ gl.bindTexture(target, null);
+ break;
+ }
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ if (is3d) {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level, layer);
+ } else {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, texture, level);
+ }
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ var data;
+ switch (type) {
+ case gl.UNSIGNED_INT:
+ data = getUint32Array(texWidth * texHeight * 4);
+ break;
+ case gl.INT:
+ data = getInt32Array(texWidth * texHeight * 4);
+ break;
+ case gl.UNSIGNED_BYTE:
+ default:
+ data = getUint8Array(texWidth * texHeight * 4);
+ break;
+ }
+ gl.readPixels(0, 0, texWidth, texHeight, format, type, data);
+
+ var k = 0;
+ var failed_exceptions = 0;
+ for (var y = 0; y < texHeight; ++y) {
+ for (var x = 0; x < texWidth; ++x) {
+ var index = (y * texWidth + x) * 4;
+ var is_exception = false;
+ for (var ii = 0; ii < exceptions.length; ++ii) {
+ if (exceptions[ii].x == x && exceptions[ii].y == y) {
+ is_exception = true;
+ if (Math.abs(data[index] - exceptions[ii].r) > tol ||
+ Math.abs(data[index + 1] - exceptions[ii].g) > tol ||
+ Math.abs(data[index + 2] - exceptions[ii].b) > tol ||
+ Math.abs(data[index + 3] - exceptions[ii].a) > tol) {
+ failed_exceptions++;
+ }
+ }
+ }
+ if (is_exception)
+ continue;
+ for (var i = 0; i < 4; ++i) {
+ if (data[index + i] != 0) {
+ k++;
+ }
+ }
+ }
+ }
+ var info = "Level = " + level;
+ if (is3d)
+ info += ", layer = " + layer;
+ info += " : ";
+ if (k) {
+ testFailed(info + "found " + k + " non-zero elements");
+ } else {
+ testPassed(info + "all data initialized");
+ }
+ if (exceptions.length > 0) {
+ if (failed_exceptions) {
+ testFailed(info + "found " + failed_exceptions + " elements incorrectly overwritten");
+ } else {
+ testPassed(info + "all initialized elements stay untouched");
+ }
+ }
+}
+
+function testTexImage3D() {
+
+ var max_3d_texture_size = Math.min(gl.getParameter(gl.MAX_3D_TEXTURE_SIZE), 1024);
+
+ var test_cases = [
+ // TEXTURE_3D + RGBA8
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256
+ height: 256,
+ depth: 8,
+ exceptions: [ { x: 0, y: 0, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256
+ height: 256,
+ depth: 8,
+ exceptions: [],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: max_3d_texture_size,
+ height: max_3d_texture_size,
+ depth: 4,
+ exceptions: [ { x: 0, y: 128, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: max_3d_texture_size,
+ height: max_3d_texture_size,
+ depth: 4,
+ exceptions: [],
+ },
+
+ // TEXTURE_3D + RGBA8UI
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256
+ height: 256,
+ depth: 8,
+ exceptions: [ { x: 0, y: 255, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256
+ height: 256,
+ depth: 8,
+ exceptions: [],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: max_3d_texture_size,
+ height: max_3d_texture_size,
+ depth: 4,
+ exceptions: [ { x: 128, y: 0, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: max_3d_texture_size,
+ height: max_3d_texture_size,
+ depth: 4,
+ exceptions: [],
+ },
+
+ // TEXTURE_3D + RGBA8I
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256
+ height: 256,
+ depth: 8,
+ exceptions: [ { x: 128, y: 255, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256
+ height: 256,
+ depth: 8,
+ exceptions: [],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: max_3d_texture_size,
+ height: max_3d_texture_size,
+ depth: 4,
+ exceptions: [ { x: 128, y: 128, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_3D",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: max_3d_texture_size,
+ height: max_3d_texture_size,
+ depth: 4,
+ exceptions: [],
+ },
+
+ // TEXTURE_2D_ARRAY + RGBA8
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: 1024,
+ height: 1024,
+ depth: 8,
+ exceptions: [ { x: 1023, y: 0, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: 1024,
+ height: 1024,
+ depth: 8,
+ exceptions: [],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: 64,
+ height: 64,
+ depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256
+ exceptions: [ { x: 63, y: 32, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8",
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_BYTE,
+ width: 64,
+ height: 64,
+ depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256
+ exceptions: [],
+ },
+
+ // TEXTURE_2D_ARRAY + RGBA8UI
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: 1024,
+ height: 1024,
+ depth: 8,
+ exceptions: [ { x: 1023, y: 1023, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: 1024,
+ height: 1024,
+ depth: 8,
+ exceptions: [],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: 64,
+ height: 64,
+ depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256
+ exceptions: [ { x: 0, y: 0, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8UI",
+ format: gl.RGBA_INTEGER,
+ type: gl.UNSIGNED_BYTE,
+ read_type: gl.UNSIGNED_INT,
+ width: 64,
+ height: 64,
+ depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256
+ exceptions: [],
+ },
+
+ // TEXTURE_2D_ARRAY + RGBA8I
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: 1024,
+ height: 1024,
+ depth: 8,
+ exceptions: [ { x: 512, y: 1023, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: 1024,
+ height: 1024,
+ depth: 8,
+ exceptions: [],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: 64,
+ height: 64,
+ depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256
+ exceptions: [ { x: 63, y: 32, r: 108, g: 72, b: 36, a: 9 } ],
+ },
+ {
+ target: "TEXTURE_2D_ARRAY",
+ internal_format: "RGBA8I",
+ format: gl.RGBA_INTEGER,
+ type: gl.BYTE,
+ read_type: gl.INT,
+ width: 64,
+ height: 64,
+ depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256
+ exceptions: [],
+ },
+
+ // If more tests are added here, make sure to increase the size of
+ // scratchBuffer above, if needed.
+ ];
+
+ for (var ii = 0; ii < test_cases.length; ++ii) {
+ debug("");
+ var test = test_cases[ii];
+ debug("TexImage3D with target = " + test.target + ", internal_format = " + test.internal_format +
+ ", width = " + test.width + ", height = " + test.height + ", depth = " + test.depth);
+ var tex = setupTexture(gl[test.target], test.width, test.height, test.depth);
+ gl.texImage3D(gl[test.target], 0, gl[test.internal_format], test.width, test.height, test.depth, 0, test.format, test.type, null);
+ for (var jj = 0; jj < test.exceptions.length; ++jj) {
+ var exception = test.exceptions[jj];
+ var data;
+ switch (test.type) {
+ case gl.BYTE:
+ data = getInt8Array(4 * test.depth);
+ break;
+ case gl.UNSIGNED_BYTE:
+ data = getUint8Array(4 * test.depth);
+ break;
+ default:
+ assert(false);
+ }
+ for (var pixel = 0; pixel < test.depth; ++pixel) {
+ data[pixel * 4] = exception.r;
+ data[pixel * 4 + 1] = exception.g;
+ data[pixel * 4 + 2] = exception.b;
+ data[pixel * 4 + 3] = exception.a;
+ }
+ gl.texSubImage3D(gl[test.target], 0, exception.x, exception.y, 0, 1, 1, test.depth, test.format, test.type, data);
+ }
+ for (var layer = 0; layer < test.depth; ++layer)
+ checkNonZeroPixels(tex, gl[test.target], test.format, test.read_type, test.width, test.height, 0, layer, test.exceptions);
+ gl.deleteTexture(tex);
+ gl.finish();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+}
+
+function testTexStorage2D() {
+ var targets = [ "TEXTURE_2D", "TEXTURE_CUBE_MAP" ];
+ var width = 512;
+ var height = 512;
+ var levels = 5;
+
+ for (var ii = 0; ii < targets.length; ++ii) {
+ debug("");
+ debug("Reading an uninitialized texture (texStorage2D) should succeed with all bytes set to 0 : target = " + targets[ii]);
+ var tex = setupTexture(gl[targets[ii]], width, height, 1);
+ gl.texStorage2D(gl[targets[ii]], levels, gl.RGBA8, width, height);
+ for (var level = 0; level < levels; ++level) {
+ if (gl[targets[ii]] == gl.TEXTURE_2D) {
+ checkNonZeroPixels(tex, gl[targets[ii]], gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ } else {
+ checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_X, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []);
+ }
+ }
+ gl.deleteTexture(tex);
+ gl.finish();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+}
+
+function testTexStorage3D() {
+ var targets = [ "TEXTURE_3D", "TEXTURE_2D_ARRAY" ];
+ var internal_formats = [ "RGBA8", "RGBA8UI", "RGBA8I" ];
+ var formats = [ gl.RGBA, gl.RGBA_INTEGER, gl.RGBA_INTEGER ];
+ var read_types = [ gl.UNSIGNED_BYTE, gl.UNSIGNED_INT, gl.INT ];
+ var width = 256; // minimum MAX_3D_TEXTURE_SIZE is 256
+ var height = 256; // minimum MAX_3D_TEXTURE_SIZE is 256
+ var depth = 8;
+ var levels = 5;
+
+ for (var ii = 0; ii < targets.length; ++ii) {
+ debug("");
+ debug("Reading an uninitialized texture (texStorage3D) should succeed with all bytes set to 0 : target = " + targets[ii]);
+ for (var jj = 0; jj < internal_formats.length; ++jj) {
+ debug("");
+ debug("Internal format : " + internal_formats[jj]);
+ var tex = setupTexture(gl[targets[ii]], width, height, depth);
+ gl.texStorage3D(gl[targets[ii]], levels, gl[internal_formats[jj]], width, height, depth);
+ var level_depth = depth;
+ for (var level = 0; level < levels; ++level) {
+ for (var layer = 0; layer < level_depth; ++layer) {
+ checkNonZeroPixels(tex, gl[targets[ii]], formats[jj], read_types[jj], width, height, level, layer, []);
+ }
+ if (gl[targets[ii]] == gl.TEXTURE_3D)
+ level_depth = Math.max(1, level_depth >> 1);
+ }
+ gl.deleteTexture(tex);
+ gl.finish();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+ }
+}
+
+testTexImage3D();
+testTexStorage2D();
+testTexStorage3D();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html
new file mode 100644
index 0000000000..8e89b4b78a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html
@@ -0,0 +1,320 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Tests texture uploads with ArrayBufferView+offsets");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(null, undefined, 2);
+console.log(gl.getParameter(gl.VERSION));
+
+////
+
+function arrToStr(arr) {
+ return "[" + arr.map(x => x.toString()).join(", ") + "]";
+}
+
+function shouldBeWas(shouldBe, was, info) {
+ var text = "Should be " + shouldBe + ", was " + was + ".";
+ if (info) {
+ text = info + ": " + text;
+ }
+
+ if (shouldBe == was) {
+ testPassed(text);
+ return true;
+ } else {
+ testFailed(text);
+ return false;
+ }
+}
+
+function shouldBeWasArr(shouldBe, was, info) {
+ if (shouldBe.length != was.length) {
+ testFailed("Length should be " + shouldBe.length + ", was " + was.length + ".");
+ return false;
+ }
+
+ return shouldBeWas(arrToStr(shouldBe), arrToStr(was), info);
+}
+
+////
+
+// Textures
+
+var fibArr = [
+ 0, 1, 1, 2,
+ 3, 5, 8, 13,
+ 21, 34, 55, 89,
+ 144, 233,
+];
+
+var fb = gl.createFramebuffer();
+
+function probeWithBadOffset(fnTest, info) {
+ fnTest(+(-1|0));
+ if (!gl.getError()) {
+ testFailed("Does not support " + info + " with offsets into views.");
+ return false;
+ }
+ return true;
+}
+
+// fn(view, offset, expectedError, expectedResult)
+
+do {
+ var readPixelView = new Uint8Array(4);
+ var testView = new Uint8Array(fibArr);
+
+ function testTexOrSubImage(funcName, fnTexOrSubImage) {
+ debug("");
+ debug(funcName);
+
+ var fnProbe = function(viewOffset) {
+ fnTexOrSubImage(gl.RGBA, gl.UNSIGNED_BYTE, testView, viewOffset);
+ };
+
+ if (!probeWithBadOffset(fnProbe, funcName))
+ return;
+
+ for (var i = 0; i <= testView.length+1; i++) {
+ debug("offset=" + i);
+
+ fnTexOrSubImage(gl.RGBA, gl.UNSIGNED_BYTE, testView, i);
+
+ var effectiveViewLen = testView.length - i;
+
+ if (effectiveViewLen >= 4) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelView);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeWasArr(testView.slice(i, i+4), readPixelView);
+
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ }
+ }
+
+ debug("");
+
+ var yellow565 = (0x1f << 11) | (0x3f << 5);
+ var cyan565 = (0x3f << 5) | 0x1f;
+ var arr565 = [yellow565, cyan565];
+ var view565 = new Uint16Array(arr565);
+
+ function rgb888to565(arr888) {
+ return ((arr888[0] >> 3) << 11) | ((arr888[1] >> 2) << 5) | (arr888[2] >> 3);
+ }
+
+ for (var i = 0; i <= arr565.length+1; i++) {
+ debug("rgb565, offset=" + i);
+
+ fnTexOrSubImage(gl.RGB, gl.UNSIGNED_SHORT_5_6_5, view565, i);
+
+ var effectiveViewLen = arr565.length - i;
+
+ if (effectiveViewLen >= 1) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelView);
+ debug(arrToStr(readPixelView));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeWas(arr565[i], rgb888to565(readPixelView));
+
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ }
+ }
+ }
+
+ var fn2D = function(format, type, view, viewOffset) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, 1, 1, 0, format, type, view, viewOffset);
+ }
+
+ var fnSub2D = function(format, type, view, viewOffset) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, 1, 1, 0, format, type, null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, format, type, view, viewOffset);
+ }
+
+ var fn3D = function(format, type, view, viewOffset) {
+ gl.texImage3D(gl.TEXTURE_3D, 0, format, 1, 1, 1, 0, format, type, view, viewOffset);
+ }
+
+ var fnSub3D = function(format, type, view, viewOffset) {
+ gl.texImage3D(gl.TEXTURE_3D, 0, format, 1, 1, 1, 0, format, type, null);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, format, type, view, viewOffset);
+ }
+
+ ////
+
+ var tex2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2d, 0);
+
+ testTexOrSubImage("texImage2D", fn2D);
+ testTexOrSubImage("texSubImage2D", fnSub2D);
+
+ ////
+
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0);
+
+ testTexOrSubImage("texImage3D", fn3D);
+ testTexOrSubImage("texSubImage3D", fnSub3D);
+} while (false);
+
+
+do {
+ var compressedFormat = 0;
+ var compressedByteCount;
+
+ if (gl.getExtension("WEBGL_compressed_texture_s3tc")) {
+ var e = gl.getExtension("WEBGL_compressed_texture_s3tc");
+ compressedFormat = e.COMPRESSED_RGB_S3TC_DXT1_EXT;
+ compressedByteCount = 8;
+ } else if (gl.getExtension("WEBGL_compressed_texture_etc")) {
+ var e = gl.getExtension("WEBGL_compressed_texture_etc");
+ compressedFormat = e.COMPRESSED_RGB8_ETC2;
+ compressedByteCount = 8;
+ } else {
+ debug("No compressed texture format found. Skipping compressedTex(Sub)Image tests.");
+ break;
+ }
+
+ ////
+
+ var view = new Uint8Array(compressedByteCount+1);
+
+ var fn2D = function(viewOffset) {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, compressedFormat, 4, 4, 0,
+ view, viewOffset, compressedByteCount);
+ };
+
+ var fnSub2D = function(viewOffset) {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, compressedFormat, 4, 4, 0,
+ view, 0, compressedByteCount);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, compressedFormat,
+ view, viewOffset, compressedByteCount);
+ };
+
+ var fn3D = function(viewOffset) {
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, compressedFormat, 4, 4, 1, 0,
+ view, viewOffset, compressedByteCount);
+ };
+
+ var fnSub3D = function(viewOffset) {
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, compressedFormat, 4, 4, 1, 0,
+ view, 0, compressedByteCount);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 1, compressedFormat,
+ view, viewOffset, compressedByteCount);
+ };
+
+ ////
+
+ var testFunc = function(funcName, fnToTest) {
+ debug("");
+ debug(funcName);
+
+ if (!probeWithBadOffset(fnToTest, funcName))
+ return;
+
+ var viewLength = view.length;
+ var subViewLength = compressedByteCount;
+
+ for (var i = 0; i <= viewLength+1; i++) {
+ debug("offset=" + i);
+
+ fnToTest(i);
+ var effectiveViewLen = viewLength - i;
+
+ if (effectiveViewLen >= subViewLength) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ }
+ }
+ };
+
+ var tex2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+ testFunc("compressedTexImage2D" , fn2D );
+ testFunc("compressedTexSubImage2D", fnSub2D);
+
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex3d);
+ testFunc("compressedTexImage3D" , fn3D );
+ testFunc("compressedTexSubImage3D", fnSub3D);
+} while (false);
+
+do {
+ debug("");
+ debug("readPixels");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ var testColor = [10, 20, 30, 40];
+ gl.clearColor(testColor[0]/255.0,
+ testColor[1]/255.0,
+ testColor[2]/255.0,
+ testColor[3]/255.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var readPixelView = new Uint8Array(6);
+
+ function doReadPixels(viewOffset) {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelView, viewOffset);
+ return readPixelView;
+ }
+
+ if (!probeWithBadOffset(doReadPixels, "doReadPixels"))
+ break;
+
+ for (var i = 0; i <= readPixelView.length+1; i++) {
+ debug("offset=" + i);
+ var res = doReadPixels(i);
+ var effectiveViewLen = readPixelView.length - i;
+
+ if (effectiveViewLen >= 4) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeWasArr(testColor, res.slice(i,i+4));
+
+ } else if (effectiveViewLen >= 0) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ }
+ }
+} while (false);
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/00_test_list.txt
new file mode 100644
index 0000000000..2aff6e699d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/00_test_list.txt
@@ -0,0 +1,8 @@
+context-creation.html
+context-creation-worker.html
+methods-2.html
+methods-2-worker.html
+--min-version 2.0.1 offscreencanvas-query.html
+--min-version 2.0.1 offscreencanvas-sync.html
+--min-version 2.0.1 offscreencanvas-timer-query.html
+--min-version 2.0.1 offscreencanvas-transfer-image-bitmap.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.html
new file mode 100644
index 0000000000..9362a0a4ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Context Creation Test for OffscreenCanvas in a worker</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL context can be created on an OffscreenCanvas.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+} else {
+ var worker = new Worker('context-creation-worker.js');
+ worker.postMessage("Start worker");
+ worker.onmessage = function(e) {
+ if (e.data == "Test passed") {
+ testPassed("All tests have passed");
+ } else {
+ testFailed("Some tests failed");
+ }
+ finishTest();
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.js
new file mode 100644
index 0000000000..67bf406482
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation-worker.js
@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+importScripts("../../js/tests/canvas-tests-utils.js");
+self.onmessage = function(e) {
+ if (contextCreation('webgl2'))
+ self.postMessage("Test passed");
+ else
+ self.postMessage("Test failed");
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation.html
new file mode 100644
index 0000000000..c3f1d2657d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/context-creation.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Context Creation Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL2 context can be created on an OffscreenCanvas.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+} else {
+ if (contextCreation('webgl2')) {
+ testPassed("WebGL2 context created correctly.");
+ } else {
+ testFailed("WebGL2 context creation failed");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.html
new file mode 100644
index 0000000000..582fd556a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Methods Test for OffscreenCanvas in a worker</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL context created for an OffscreenCanvas has all the methods in the specification.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+} else {
+ var worker = new Worker('methods-2-worker.js');
+ worker.postMessage("Start worker");
+ worker.onmessage = function(e) {
+ if (e.data == "Test passed") {
+ testPassed("All test have passed");
+ } else {
+ testFailed("Some tests failed");
+ }
+ finishTest();
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.js b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.js
new file mode 100644
index 0000000000..94c1378f0d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2-worker.js
@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+importScripts("../../js/tests/canvas-tests-utils.js");
+self.onmessage = function(e) {
+ if (testAPIs('webgl2'))
+ self.postMessage("Test passed");
+ else
+ self.postMessage("Test failed");
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2.html
new file mode 100644
index 0000000000..c4250f5724
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/methods-2.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Methods Test for OffscreenCanvas in a worker</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/canvas-tests-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("This test ensures that the WebGL context has all the methods in the specification.");
+
+if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+} else {
+ if (testAPIs('webgl2')) {
+ testPassed("All WebGL2 methods found");
+ } else {
+ testFailed("Some WebGL2 methods not found");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-query.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-query.html
new file mode 100644
index 0000000000..8d9e92e511
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-query.html
@@ -0,0 +1,79 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test for Query objects with OffscreenCanvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id='myWorker' type='text/worker'>
+ function tick(callback) {
+ function tickImpl() {
+ const res = callback();
+ if (res) {
+ if (requestAnimationFrame) {
+ requestAnimationFrame(tickImpl);
+ } else {
+ setTimeout(tickImpl, 10);
+ }
+ }
+ }
+
+ tickImpl();
+ }
+
+ self.onmessage = function(e) {
+ let canvas = new OffscreenCanvas(128, 128);
+ let gl = canvas.getContext("webgl2");
+ let query = gl.createQuery();
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, query);
+ gl.endQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ tick(function() {
+ const status = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
+ if (status) {
+ self.postMessage("PASSED - query object completed successfully from worker");
+ return false;
+ } else {
+ const err = gl.getError();
+ if (err != 0) {
+ self.postMessage("FAILED - GL error " + err);
+ return false;
+ }
+ }
+ return true;
+ });
+ };
+ </script>
+ <script>
+ "use strict";
+ description("This test ensures that query objects work with the WebGL 2.0 context created via OffscreenCanvas.");
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ } else {
+ var blob = new Blob([document.getElementById("myWorker").textContent]);
+ var worker = new Worker(URL.createObjectURL(blob));
+ worker.onmessage = function(msg) {
+ if (msg.data.startsWith("PASSED")) {
+ testPassed(msg.data);
+ } else {
+ testFailed(msg.data);
+ }
+ finishTest();
+ }
+ worker.postMessage("Start Worker");
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-sync.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-sync.html
new file mode 100644
index 0000000000..dc70a60bbd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-sync.html
@@ -0,0 +1,77 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test for Sync objects with OffscreenCanvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id='myWorker' type='text/worker'>
+ function tick(callback) {
+ function tickImpl() {
+ const res = callback();
+ if (res) {
+ if (requestAnimationFrame) {
+ requestAnimationFrame(tickImpl);
+ } else {
+ setTimeout(tickImpl, 10);
+ }
+ }
+ }
+
+ tickImpl();
+ }
+
+ self.onmessage = function(e) {
+ let canvas = new OffscreenCanvas(128, 128);
+ let gl = canvas.getContext("webgl2");
+ let sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ tick(function() {
+ const status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
+ if (status == gl.SIGNALED) {
+ self.postMessage("PASSED - Sync object signaled successfully from worker");
+ return false;
+ } else {
+ const err = gl.getError();
+ if (err != 0) {
+ self.postMessage("FAILED - GL error " + err);
+ return false;
+ }
+ }
+ return true;
+ });
+ };
+ </script>
+ <script>
+ "use strict";
+ description("This test ensures that sync objects work with the WebGL 2.0 context created via OffscreenCanvas.");
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ } else {
+ var blob = new Blob([document.getElementById("myWorker").textContent]);
+ var worker = new Worker(URL.createObjectURL(blob));
+ worker.onmessage = function(msg) {
+ if (msg.data.startsWith("PASSED")) {
+ testPassed(msg.data);
+ } else {
+ testFailed(msg.data);
+ }
+ finishTest();
+ }
+ worker.postMessage("Start Worker");
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-timer-query.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-timer-query.html
new file mode 100644
index 0000000000..8714956fd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-timer-query.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test for Timer Query objects with OffscreenCanvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id='myWorker' type='text/worker'>
+ function tick(callback) {
+ function tickImpl() {
+ const res = callback();
+ if (res) {
+ if (requestAnimationFrame) {
+ requestAnimationFrame(tickImpl);
+ } else {
+ setTimeout(tickImpl, 10);
+ }
+ }
+ }
+
+ tickImpl();
+ }
+
+ self.onmessage = function(e) {
+ let canvas = new OffscreenCanvas(128, 128);
+ let gl = canvas.getContext("webgl2");
+ let ext = gl.getExtension("EXT_disjoint_timer_query_webgl2");
+ if (!ext) {
+ self.postMessage("PASSED - no EXT_disjoint_timer_query_webgl2 extension - this is legal");
+ return false;
+ }
+ let query = gl.createQuery();
+ gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
+ gl.endQuery(ext.TIME_ELAPSED_EXT);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ tick(function() {
+ const status = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
+ if (status) {
+ self.postMessage("PASSED - timer query object completed successfully on worker");
+ return false;
+ } else {
+ const err = gl.getError();
+ if (err != 0) {
+ self.postMessage("FAILED - GL error " + err);
+ return false;
+ }
+ }
+ return true;
+ });
+ };
+ </script>
+ <script>
+ "use strict";
+ description("This test ensures that timer query objects work with the WebGL 2.0 context created via OffscreenCanvas.");
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ } else {
+ var blob = new Blob([document.getElementById('myWorker').textContent]);
+ var worker = new Worker(URL.createObjectURL(blob));
+ worker.onmessage = function(msg) {
+ if (msg.data.startsWith("PASSED")) {
+ testPassed(msg.data);
+ } else {
+ testFailed(msg.data);
+ }
+ finishTest();
+ }
+ worker.postMessage("Start Worker");
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-transfer-image-bitmap.html b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-transfer-image-bitmap.html
new file mode 100644
index 0000000000..cb9232b65a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/offscreencanvas/offscreencanvas-transfer-image-bitmap.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test for OffscreenCanvas TransferToImageBitmap</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../js/tests/offscreencanvas-transfer-image-bitmap.js"></script>
+</head>
+<body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ var canvas = new OffscreenCanvas(128, 128);
+ var gl = canvas.getContext("webgl2");
+ gl.clearColor(1.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var image = canvas.transferToImageBitmap();
+
+ self.postMessage({ bitmap: image },
+ [ image ]);
+ };
+ </script>
+ <script>
+ "use strict";
+ description("This test ensures that the transferToImageBitmap function of OffscreenCanvas webgl2 context is functional.");
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ } else {
+ var blob = new Blob([document.getElementById('myWorker').textContent]);
+ var worker = new Worker(URL.createObjectURL(blob));
+
+ worker.onmessage = function(msg) {
+ testTransferToImageBitmap("webgl2", msg.data.bitmap);
+ finishTest();
+ }
+ worker.postMessage("Start Worker");
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/programs/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/00_test_list.txt
new file mode 100644
index 0000000000..c88d255dab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/00_test_list.txt
@@ -0,0 +1,4 @@
+active-built-in-attribs.html
+--min-version 2.0.1 get-uniform-indices.html
+gl-get-frag-data-location.html
+--min-version 2.0.1 sampler-uniforms.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/programs/active-built-in-attribs.html b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/active-built-in-attribs.html
new file mode 100644
index 0000000000..68b62cdcf2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/active-built-in-attribs.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests: Verify validation for active built-in attribs</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 64px; height: 64px;"> </canvas>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+void main() {
+ gl_Position = vec4(gl_VertexID % 2, (gl_VertexID/2) % 2, 0, 1);
+}
+</script>
+
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 fragColor;
+void main() {
+ fragColor = vec4(0, 1, 0, 1);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies validation for active built-in attribs.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ runTests();
+}
+
+var activeInfo, attribLoc;
+
+function runTests() {
+ var prog = wtu.setupProgram(gl, ["vs", "fs"]);
+ if (!prog) {
+ testFailed("Set up program failed");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ var numActive = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES);
+ if (numActive != 1) {
+ testFailed('ACTIVE_ATTRIBUTES should be 1.');
+ return;
+ }
+ testPassed('ACTIVE_ATTRIBUTES should be 1.');
+
+ activeInfo = gl.getActiveAttrib(prog, 0);
+ if (!activeInfo) {
+ testFailed('getActiveAttrib should return an info object.');
+ return;
+ }
+
+ shouldBe('activeInfo.name', '"gl_VertexID"');
+ attribLoc = gl.getAttribLocation(prog, 'gl_VertexID');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be able to request the location of a built-in.");
+ shouldBe('attribLoc', '-1');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/programs/get-uniform-indices.html b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/get-uniform-indices.html
new file mode 100644
index 0000000000..d42add065c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/get-uniform-indices.html
@@ -0,0 +1,121 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("This test verifies getUniformIndices behaviors.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+
+const e_canvas = document.createElement('canvas');
+const gl = e_canvas.getContext('webgl2');
+
+const VSRC = `\
+ #version 300 es
+ precision mediump float;
+ uniform float u_vert_scalar;
+ uniform float u_vert_arr[3];
+ uniform float u_both_scalar;
+ uniform float u_both_arr[3];
+ void main() {
+ gl_Position = vec4(0, 0, 0, 1);
+ gl_Position.r += u_vert_scalar;
+ gl_Position.r += u_vert_arr[1];
+ gl_Position.r += u_both_scalar;
+ gl_Position.r += u_both_arr[1];
+ }
+`;
+
+const FSRC = `\
+ #version 300 es
+ precision mediump float;
+ uniform float u_frag_scalar;
+ uniform float u_frag_arr[3];
+ uniform float u_both_scalar;
+ uniform float u_both_arr[3];
+ out vec4 o_frag_color;
+ void main() {
+ o_frag_color = vec4(0, 0, 0, 1);
+ o_frag_color.r += u_frag_scalar;
+ o_frag_color.r += u_frag_arr[1];
+ o_frag_color.r += u_both_scalar;
+ o_frag_color.r += u_both_arr[1];
+ }
+`;
+
+(() => {
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ return;
+ }
+
+ window.prog = wtu.setupProgram(gl, [VSRC, FSRC]);
+ if (!prog) {
+ testFailed("Setting up program failed");
+ return;
+ }
+ let err = gl.getError();
+ if (err) throw err;
+
+ const IS_ACTIVE_BY_NAME = {
+ 'u_vert_scalar' : true,
+ 'u_vert_scalar[0]': false,
+ 'u_vert_arr' : true,
+ 'u_vert_arr[0]' : true, // Even if the [0] is unused, the name enumerated
+ // via getActiveUniforms for this array is 'u_vert_arr[0]'.
+ 'u_vert_arr[1]' : false,
+
+ 'u_frag_scalar' : true,
+ 'u_frag_scalar[0]': false,
+ 'u_frag_arr' : true,
+ 'u_frag_arr[0]' : true,
+ 'u_frag_arr[1]' : false,
+
+ 'u_both_scalar' : true,
+ 'u_both_scalar[0]': false,
+ 'u_both_arr' : true,
+ 'u_both_arr[0]' : true,
+ 'u_both_arr[1]' : false,
+ };
+ const NAMES = Object.keys(IS_ACTIVE_BY_NAME);
+ const active_ids = gl.getUniformIndices(prog, NAMES);
+
+ err = gl.getError();
+ if (err) throw err;
+
+ NAMES.forEach((name, i) => {
+ const active_id_was = active_ids[i];
+ const is_active_expected = IS_ACTIVE_BY_NAME[name];
+ const is_active_was = active_id_was != gl.INVALID_INDEX;
+ expectTrue(is_active_was == is_active_expected,
+ `getUniformIndices([, '${name}' ,]) -> [, ${active_id_was} ,], should be [, ${is_active_expected ? '0<=N<INVALID_INDEX' : 'INVALID_INDEX'} ,]`);
+ if (is_active_was) {
+ const info = gl.getActiveUniform(prog, active_id_was);
+ expectTrue(info.name.startsWith(name), `'${info.name}'.startsWith('${name}')`);
+ }
+ });
+})();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/programs/gl-get-frag-data-location.html b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/gl-get-frag-data-location.html
new file mode 100644
index 0000000000..1e006ebd28
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/gl-get-frag-data-location.html
@@ -0,0 +1,121 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests: Verify getFragDataLocation</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 4px; height: 4px;"> </canvas>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+void main() {
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout(location = 2) out vec4 fragColor0;
+layout(location = 0) out vec4 fragColor1;
+void main() {
+ fragColor0 = vec4(0, 1, 0, 1);
+ fragColor1 = vec4(1, 0, 0, 1);
+}
+</script>
+
+<script id="fs-array" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 fragColor[2];
+void main() {
+ fragColor[0] = vec4(0, 1, 0, 1);
+ fragColor[1] = vec4(1, 0, 0, 1);
+}
+</script>
+
+<script id="vs-es2" type="x-shader/x-vertex">
+void main() {
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fs-es2" type="x-shader/x-fragment">
+precision mediump float;
+void main() {
+ gl_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies getFragDataLocation behaviors.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ runTests();
+}
+
+function runTests() {
+ window.program = wtu.setupProgram(gl, ["vs", "fs"]);
+ window.programArray = wtu.setupProgram(gl, ["vs", "fs-array"]);
+ window.programEs2 = wtu.setupProgram(gl, ["vs-es2", "fs-es2"]);
+ if (!program || !programArray || !programEs2) {
+ testFailed("Set up program failed");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ shouldBe("gl.getFragDataLocation(program, 'gl_FragColor')", "-1");
+ shouldBe("gl.getFragDataLocation(programArray, 'gl_FragColor')", "-1");
+ shouldBe("gl.getFragDataLocation(programEs2, 'gl_FragColor')", "-1");
+ shouldBe("gl.getFragDataLocation(program, 'gl_FragData')", "-1");
+ shouldBe("gl.getFragDataLocation(programArray, 'gl_FragData')", "-1");
+ shouldBe("gl.getFragDataLocation(programEs2, 'gl_FragData')", "-1");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from gl_* queries");
+
+ var loc0 = gl.getFragDataLocation(program, "fragColor0");
+ var loc1 = gl.getFragDataLocation(program, "fragColor1");
+ if (loc0 != 2 || loc1 != 0) {
+ testFailed("Fail to query scalar output variable locations, " +
+ "expected: fragColor0->2, fragColor1->0, " +
+ "got: fragColor0->" + loc0 + ", fragColor1->" + loc1);
+ } else {
+ testPassed("getFragDataLocation on scalar variables works fine");
+ }
+
+ var loc = gl.getFragDataLocation(programArray, "fragColor");
+ loc0 = gl.getFragDataLocation(programArray, "fragColor[0]");
+ loc1 = gl.getFragDataLocation(programArray, "fragColor[1]");
+ if (loc < 0 || loc0 < 0 || loc1 < 0 || loc != loc0 || loc0 + 1 != loc1) {
+ testFailed("Fail to query scalar output variable locations, " +
+ "expected: fragColor->0, fragColor[0]->0, fragColor[1]->1, " +
+ "got: fragColor->" + loc + ", fragColor[0]->" + loc0 + ", fragColor[1]->" + loc1);
+ } else {
+ testPassed("getFragDataLocation on variable arrays works fine");
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from testing");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/programs/sampler-uniforms.html b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/sampler-uniforms.html
new file mode 100644
index 0000000000..4df60d3ee3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/sampler-uniforms.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 getActiveUniform conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+void main()
+{
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform mediump $type uniform0;
+out vec4 myFragColor;
+void main()
+{
+ myFragColor = vec4(0,$access,0,1);
+}
+</script>
+<script>
+"use strict";
+description("Tests getActiveUniform for various types");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var tests = [
+ { glType: gl.SAMPLER_2D, size: 1, type: 'sampler2D', access: 'texture(uniform0, vec2(0,0)).x'},
+ { glType: gl.SAMPLER_CUBE, size: 1, type: 'samplerCube', access: 'texture(uniform0, vec3(0,1,0)).x'},
+ { glType: gl.SAMPLER_3D, size: 1, type: 'sampler3D', access: 'texture(uniform0, vec3(0,1,0)).x'},
+ { glType: gl.SAMPLER_2D_ARRAY, size: 1, type: 'sampler2DArray', access: 'texture(uniform0, vec3(0,1,0)).x'},
+
+ { glType: gl.SAMPLER_2D_SHADOW, size: 1, type: 'sampler2DShadow', access: 'texture(uniform0, vec3(0,1,0))'},
+ { glType: gl.SAMPLER_CUBE_SHADOW, size: 1, type: 'samplerCubeShadow', access: 'texture(uniform0, vec4(0,1,0,0))'},
+ { glType: gl.SAMPLER_2D_ARRAY_SHADOW, size: 1, type: 'sampler2DArrayShadow', access: 'texture(uniform0, vec4(0,1,0,0))'},
+
+ { glType: gl.INT_SAMPLER_2D, size: 1, type: 'isampler2D', access: 'texture(uniform0, vec2(0,0)).x'},
+ { glType: gl.INT_SAMPLER_CUBE, size: 1, type: 'isamplerCube', access: 'texture(uniform0, vec3(0,1,0)).x'},
+ { glType: gl.INT_SAMPLER_3D, size: 1, type: 'isampler3D', access: 'texture(uniform0, vec3(0,1,0)).x'},
+ { glType: gl.INT_SAMPLER_2D_ARRAY, size: 1, type: 'isampler2DArray', access: 'texture(uniform0, vec3(0,1,0)).x'},
+
+ { glType: gl.UNSIGNED_INT_SAMPLER_2D, size: 1, type: 'usampler2D', access: 'texture(uniform0, vec2(0,0)).x'},
+ { glType: gl.UNSIGNED_INT_SAMPLER_CUBE, size: 1, type: 'usamplerCube', access: 'texture(uniform0, vec3(0,1,0)).x'},
+ { glType: gl.UNSIGNED_INT_SAMPLER_3D, size: 1, type: 'usampler3D', access: 'texture(uniform0, vec3(0,1,0)).x'},
+ { glType: gl.UNSIGNED_INT_SAMPLER_2D_ARRAY, size: 1, type: 'usampler2DArray', access: 'texture(uniform0, vec3(0,1,0)).x'},
+];
+
+var vs = wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER);
+var source = document.getElementById('fshader').text;
+
+function createProgram(type, access) {
+ var fs = wtu.loadShader(
+ gl,
+ source.replace('$type', type).replace('$access', access),
+ gl.FRAGMENT_SHADER);
+ var program = wtu.setupProgram(gl, [vs, fs]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from setup");
+ return program;
+}
+
+for (var tt = 0; tt < tests.length; ++tt) {
+ var t = tests[tt];
+ debug("");
+ debug("Testing uniform sampler type : " + t.type);
+ var program = createProgram(t.type, t.access);
+ var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ assertMsg(numUniforms >= 1, "at least 1 sampler uniform");
+ var found = false;
+ for (var ii = 0; ii < numUniforms; ++ii) {
+ var info = gl.getActiveUniform(program, ii);
+ if (info.name == 'uniform0') {
+ found = true;
+ assertMsg(info.type == t.glType,
+ "type must be " + wtu.glEnumToString(gl, t.glType) + " was " +
+ wtu.glEnumToString(gl, info.type));
+ assertMsg(info.size == t.size,
+ "size must be " + t.size + ' was ' + info.size);
+ }
+ }
+ assertMsg(found, "uniform 'uniform0' should exist");
+ var loc = gl.getUniformLocation(program, 'uniform0');
+ assertMsg(loc != null, "getUniformLocation must return non null");
+ gl.uniform1i(loc, tt + 1);
+ var val = gl.getUniform(program, loc);
+ assertMsg(val == tt + 1, "getUniform must return set value");
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors running the tests");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/query/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/query/00_test_list.txt
new file mode 100644
index 0000000000..c40921bf88
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/query/00_test_list.txt
@@ -0,0 +1,2 @@
+occlusion-query.html
+query.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/query/occlusion-query.html b/dom/canvas/test/webgl-conf/checkout/conformance2/query/occlusion-query.html
new file mode 100644
index 0000000000..3655ed8783
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/query/occlusion-query.html
@@ -0,0 +1,137 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Occlusion Query Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of occlusion query objects.");
+
+debug("");
+
+var tests = [];
+var currentTest;
+var currentTestIndex = 0;
+var numberOfTestAttempts = 4; // Just to stress implementations a bit more.
+var query;
+var numberOfCompletionAttempts = 0;
+
+function setupTests(gl) {
+ tests = [
+ {
+ target: gl.ANY_SAMPLES_PASSED_CONSERVATIVE,
+ name: "ANY_SAMPLES_PASSED_CONSERVATIVE",
+ result: 1,
+ },
+ {
+ target: gl.ANY_SAMPLES_PASSED,
+ name: "ANY_SAMPLES_PASSED",
+ result: 1,
+ },
+ ];
+}
+
+function runOcclusionQueryTest() {
+ currentTest = tests[currentTestIndex];
+
+ debug("");
+ debug("Testing completion and behavior of " + currentTest.name + " occlusion query");
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ var program = wtu.setupSimpleColorProgram(gl, 0);
+ gl.uniform4f(gl.getUniformLocation(program, "u_color"), 0, 1, 0, 1);
+ wtu.setupUnitQuad(gl, 0);
+ query = gl.createQuery();
+ var target = currentTest.target;
+ gl.beginQuery(target, query);
+ wtu.drawUnitQuad(gl);
+ gl.endQuery(target);
+
+ // Verify as best as possible that the implementation doesn't
+ // allow a query's result to become available the same frame, by
+ // spin-looping for some time and ensuring that none of the
+ // queries' results become available.
+ var numEarlyTests = 20000;
+ while (--numEarlyTests > 0) {
+ gl.finish();
+ if (gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) {
+ testFailed("Query's result became available too early");
+ finishTest();
+ return;
+ }
+ }
+
+ testPassed("Query's result didn't become available too early");
+ numberOfCompletionAttempts = 0;
+ requestAnimationFrame(completeOcclusionQueryTest);
+}
+
+function completeOcclusionQueryTest() {
+ ++numberOfCompletionAttempts;
+
+ if (numberOfCompletionAttempts > 500) {
+ testFailed("Query didn't become available in a reasonable time");
+ finishTest();
+ return;
+ }
+
+ if (!gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) {
+ requestAnimationFrame(completeOcclusionQueryTest);
+ return;
+ }
+
+ // No matter whether the test was run with ANY_SAMPLES_PASSED or
+ // ANY_SAMPLES_PASSED_CONSERVATIVE, the query object should always
+ // report a non-zero result.
+ var result = gl.getQueryParameter(query, gl.QUERY_RESULT);
+ if (result == currentTest.result) {
+ testPassed("Occlusion query " + currentTest.name + " returned a correct result (" + result + ")");
+ } else {
+ testFailed("Occlusion query " + currentTest.name + " returned an incorrect result " + result + " (expected " + currentTest.result + ")");
+ }
+
+ gl.deleteQuery(query);
+ query = null;
+
+ ++currentTestIndex;
+ if (currentTestIndex >= tests.length) {
+ --numberOfTestAttempts;
+ if (numberOfTestAttempts == 0) {
+ finishTest();
+ } else {
+ currentTestIndex = 0;
+ requestAnimationFrame(runOcclusionQueryTest);
+ }
+ } else {
+ requestAnimationFrame(runOcclusionQueryTest);
+ }
+}
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ setupTests(gl);
+ runOcclusionQueryTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/query/query.html b/dom/canvas/test/webgl-conf/checkout/conformance2/query/query.html
new file mode 100644
index 0000000000..03a1124be7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/query/query.html
@@ -0,0 +1,167 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Query Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+attribute vec4 a_color;
+varying vec4 v_color;
+void main(void) {
+ gl_Position = a_position;
+ v_color = a_color;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main(void) {
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of the Query objects.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var q1 = null;
+var q2 = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runCurrentQueryTest();
+ runObjectTest();
+ // TODO: Test buffer binding, drawing, etc.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runCurrentQueryTest() {
+ debug("");
+ debug("Testing Beginning, Ending, and checking the state of query objects");
+
+ shouldBe("gl.ANY_SAMPLES_PASSED", "0x8C2F");
+ shouldBe("gl.ANY_SAMPLES_PASSED_CONSERVATIVE", "0x8D6A");
+ shouldBe("gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN", "0x8C88");
+
+ gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "ANY_SAMPLES_PASSED query should succeed");
+
+ gl.getQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, gl.CURRENT_QUERY);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "ANY_SAMPLES_PASSED query should succeed");
+
+ gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "ANY_SAMPLES_PASSED query should succeed");
+
+ // Default value is null
+ shouldBeNull("gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY)");
+ shouldBeNull("gl.getQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, gl.CURRENT_QUERY)");
+ shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
+
+ q1 = gl.createQuery();
+ q2 = gl.createQuery();
+ shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
+ shouldBeTrue("gl.isQuery(q1)");
+ shouldBe("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)", "q1");
+
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Can't begin a query while one is already active");
+ shouldBe("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)", "q1");
+
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
+
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Can't end a query if one is not active");
+
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, q1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Can't re-use query objects for incompatible targets");
+ shouldBeNull("gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY)");
+
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, q2);
+ shouldBe("gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY)", "q2");
+
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, q2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Can't call beginQuery on an already active query object");
+ shouldBeNull("gl.getQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, gl.CURRENT_QUERY)");
+
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be able to have multiple unrelated query types active at once");
+ shouldBe("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)", "q1");
+
+ gl.deleteQuery(q1);
+ gl.deleteQuery(q2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "deleting queries should not produce errors");
+
+ shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
+ shouldBeNull("gl.getQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, gl.CURRENT_QUERY)");
+
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "beginning a deleted query object");
+ shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
+
+ debug("");
+ debug("Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1636525");
+
+ q1 = gl.createQuery();
+ gl.deleteQuery(q1);
+ wtu.glErrorShouldBe(gl, 0, "DeleteQuery after CreateQuery");
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Begining a deleted query");
+ shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
+}
+
+function runObjectTest() {
+ debug("");
+ debug("Testing object creation");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should have no previous errors");
+
+ q1 = gl.createQuery();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createQuery should not set an error");
+ shouldBeNonNull("q1");
+
+ // Expect false if never bound
+ shouldBeFalse("gl.isQuery(q1)");
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
+ shouldBeTrue("gl.isQuery(q1)");
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ shouldBeTrue("gl.isQuery(q1)");
+ gl.deleteQuery(q1);
+ shouldBeFalse("gl.isQuery(q1)");
+
+ shouldBeFalse("gl.isQuery(null)");
+
+ q1 = null;
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/reading/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/00_test_list.txt
new file mode 100644
index 0000000000..d5fe8b664e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/00_test_list.txt
@@ -0,0 +1,5 @@
+--min-version 2.0.1 format-r11f-g11f-b10f.html
+read-pixels-from-fbo-test.html
+--min-version 2.0.1 read-pixels-from-rgb8-into-pbo-bug.html
+read-pixels-into-pixel-pack-buffer.html
+read-pixels-pack-parameters.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/reading/format-r11f-g11f-b10f.html b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/format-r11f-g11f-b10f.html
new file mode 100644
index 0000000000..5534a6884f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/format-r11f-g11f-b10f.html
@@ -0,0 +1,266 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test Format R11F_G11F_B10F</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 pos;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+
+void main() {
+ gl_Position = vec4(pos, 0.0, 1.0);
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec3 u_color;
+uniform vec3 u_tol;
+uniform sampler2D u_tex;
+varying vec2 texCoord;
+
+void main() {
+ vec4 sample = texture2D(u_tex, texCoord);
+ vec3 rgb = sample.xyz;
+ if (abs(rgb[0] - u_color[0]) > u_tol[0] ||
+ abs(rgb[1] - u_color[1]) > u_tol[1] ||
+ abs(rgb[2] - u_color[2]) > u_tol[2]) {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ } else {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+}
+</script>
+<script>
+"use strict";
+description("This tests format R11F_G11F_B10F works as expected");
+debug("MacOSX driver bug. See https://github.com/KhronosGroup/WebGL/issues/1832");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+
+var testValues = [100, 1000, 2047, 2500, 4095, 5000,
+ 8191, 8192, 10000, 16383, 16384];
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+ if (gl.getExtension("EXT_color_buffer_float")) {
+ testPassed("Extension EXT_color_buffer_float is available");
+
+ testRenderbufferReadback(4, 4);
+ testTextureReadback(4, 4);
+ testTextureSampling(4, 4);
+ } else {
+ testPassed("Extension EXT_color_buffer_float is unavailable - this is legal");
+ }
+}
+
+function setupColor(testR, testG, testB, value) {
+ var data = new Float32Array(4);
+ data[0] = testR ? value : 0;
+ data[1] = testG ? value : 0;
+ data[2] = testB ? value : 0;
+ data[3] = 1; // Doesn't really matter for RGB formats.
+ return data;
+}
+
+// The definition of <Unsinged 11-Bit Floating-Point Number> in GLES 3.0.4:
+// https://www.khronos.org/registry/gles/specs/3.0/es_spec_3.0.4.pdf#nameddest=section-2.1.3
+// The definition of <Unsinged 10-Bit Floating-Point Number> in GLES 3.0.4:
+// https://www.khronos.org/registry/gles/specs/3.0/es_spec_3.0.4.pdf#nameddest=section-2.1.4
+function setTolerance (testR, testG, testB, value) {
+ var tol = new Float32Array(3);
+ var exponent;
+ if (value < Math.pow(2, -14)) {
+ exponent = -14;
+ } else {
+ exponent = Math.floor(Math.log(value) / Math.LN2);
+ }
+ var tol11F = Math.pow(2, exponent) / 64;
+ var tol10F = Math.pow(2, exponent) / 32;
+ tol[0] = testR ? tol11F : 0;
+ tol[1] = testG ? tol11F : 0;
+ tol[2] = testB ? tol10F : 0;
+ return tol;
+}
+
+function clearAndVerifyColor(width, height, testR, testG, testB, value) {
+ var data = setupColor(testR, testG, testB, value);
+ var tol = setTolerance(testR, testG, testB, value);
+ gl.clearBufferfv(gl.COLOR, 0, data);
+ var buffer = new Float32Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.FLOAT, buffer);
+ for (var ii = 0; ii < width * height; ++ii) {
+ var pixel = [buffer[ii * 4], buffer[ii * 4 + 1], buffer[ii * 4 + 2], buffer[ii * 4 + 3]];
+ if (isNaN(pixel[0]) || isNaN(pixel[1]) || isNaN(pixel[2]) ||
+ Math.abs(pixel[0] - data[0]) > tol[0] ||
+ Math.abs(pixel[1] - data[1]) > tol[1] ||
+ Math.abs(pixel[2] - data[2]) > tol[2]) {
+ testFailed("ReadPixels " + ii + " : got [" + pixel + "], expected [" + data + "], tol [" + tol + "]");
+ return;
+ }
+ }
+ testPassed("ReadPixels success : [" + data + "]");
+}
+
+function clearDrawAndVerifyColor(fbo, program, testR, testG, testB, value) {
+ var data = setupColor(testR, testG, testB, value);
+ var tol = setTolerance(testR, testG, testB, value);
+ debug("Testing : [" + data + "] with tolerance = [" + tol + "]");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.clearBufferfv(gl.COLOR, 0, data);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearColor(0, 0, 0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform3fv(program.colorPos, data.slice(0, 3));
+ gl.uniform3fv(program.tolPos, tol);
+
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "Should pass (green color instead of red)");
+}
+
+
+function testReadPixelsFromColorChannelsWithVariousValues(width, height) {
+ debug("Testing R channel");
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ clearAndVerifyColor(width, height, true, false, false, testValues[ii]);
+ }
+ debug("Testing G channel");
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ clearAndVerifyColor(width, height, false, true, false, testValues[ii]);
+ }
+ debug("Testing B channel");
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ clearAndVerifyColor(width, height, false, false, true, testValues[ii]);
+ }
+}
+
+function testSampleTextureFromColorChannelsWithVariousValues(fbo, program) {
+ debug("Testing R channel");
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ clearDrawAndVerifyColor(fbo, program, true, false, false, testValues[ii]);
+ }
+ debug("Testing G channel");
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ clearDrawAndVerifyColor(fbo, program, false, true, false, testValues[ii]);
+ }
+ debug("Testing B channel");
+ for (var ii = 0; ii < testValues.length; ++ii) {
+ clearDrawAndVerifyColor(fbo, program, false, false, true, testValues[ii]);
+ }
+}
+
+function testRenderbufferReadback(width, height) {
+ debug("");
+ debug("Checking clearing and readback of a color image of renderbuffer with R11F_G11F_B10F format.");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.R11F_G11F_B10F, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer);
+ shouldBe("gl.FRAMEBUFFER_COMPLETE", "gl.checkFramebufferStatus(gl.FRAMEBUFFER)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with renderbuffer should succeed.");
+
+ testReadPixelsFromColorChannelsWithVariousValues(width, height);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(renderbuffer);
+}
+
+function testTextureReadback(width, height) {
+ debug("");
+ debug("Checking clearing and readback of a color image of texture with R11F_G11F_B10F format.");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R11F_G11F_B10F, width, height, 0, gl.RGB, gl.FLOAT, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe("gl.FRAMEBUFFER_COMPLETE", "gl.checkFramebufferStatus(gl.FRAMEBUFFER)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+
+ testReadPixelsFromColorChannelsWithVariousValues(width, height);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(tex);
+}
+
+function setupProgram() {
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["pos", "texCoord0"]);
+ if (!program)
+ return null;
+ program.colorPos = gl.getUniformLocation(program, "u_color");
+ program.tolPos = gl.getUniformLocation(program, "u_tol");
+ var texPos = gl.getUniformLocation(program, "u_tex");
+ program.buffers = wtu.setupUnitQuad(gl, 0, 1);
+ if (!program.colorPos || !program.tolPos || !texPos || program.buffers.length == 0) {
+ gl.deleteProgram(program);
+ return null;
+ }
+ gl.useProgram(program);
+ gl.uniform1i(texPos, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup program should succeed.");
+ return program;
+}
+
+function testTextureSampling(width, height) {
+ debug("");
+ debug("Checking sampling of a texture with R11_G11F_B10F format");
+
+ var program = setupProgram();
+ if (!program) {
+ testFailed("Failed to setup program");
+ return;
+ }
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R11F_G11F_B10F, width, height, 0, gl.RGB, gl.FLOAT, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe("gl.FRAMEBUFFER_COMPLETE", "gl.checkFramebufferStatus(gl.FRAMEBUFFER)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+
+ testSampleTextureFromColorChannelsWithVariousValues(fbo, program);
+
+ gl.deleteTexture(tex);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteProgram(program);
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from tests.");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-fbo-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-fbo-test.html
new file mode 100644
index 0000000000..c06e9988ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-fbo-test.html
@@ -0,0 +1,642 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 ReadPixels Test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Checks that ReadPixels from a fbo works as expected.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+gl.pixelStorei(gl.PACK_ALIGNMENT, 1);
+
+function getChannelCount(format) {
+ switch (format) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ case gl.ALPHA:
+ case gl.LUMINANCE:
+ return 1;
+ case gl.RB:
+ case gl.RB_INTEGER:
+ case gl.LUMINANCE_ALPHA:
+ return 2;
+ case gl.RGB:
+ case gl.RGB_INTEGER:
+ return 3;
+ case gl.RGBA:
+ case gl.RGBA_INTEGER:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+function getUnpackInfo(type) {
+ switch (type) {
+ case gl.UNSIGNED_SHORT_5_6_5:
+ return {bitsCount: [5, 6, 5], isReverse: false};
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ return {bitsCount: [4, 4, 4, 4], isReverse: false};
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ return {bitsCount: [5, 5, 5, 1], isReverse: false};
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ return {bitsCount: [2, 10, 10, 10], isReverse: true};
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ return {bitsCount: [10, 11, 11], isReverse: true};
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ return {bitsCount: [5, 9, 9, 9], isReverse: true};
+ default:
+ return null;
+ }
+}
+
+// bitsCount is an array contains bit count for each component.
+function unpack(value, channelCount, bitsCount, isReverse) {
+ var result = new Array(channelCount);
+
+ var accumBitsCount = 0;
+ for (var i = channelCount - 1; i >= 0; --i) {
+ var currentChannel = isReverse ? (channelCount - i - 1) : i;
+ var mask = 0xFFFFFFFF >>> (32 - bitsCount[i]);
+ result[currentChannel] = ((value >> accumBitsCount) & mask);
+ accumBitsCount += bitsCount[i];
+ }
+
+ return result;
+}
+
+function getColor(buf, index, readFormat, readType) {
+ var channelCount = getChannelCount(readFormat);
+ var result = new Array(channelCount);
+
+ var unpackInfo = getUnpackInfo(readType);
+ if (unpackInfo) {
+ result = unpack(buf[index], channelCount, unpackInfo.bitsCount, unpackInfo.isReverse);
+ } else {
+ for (var i = 0; i < channelCount; ++i) {
+ result[i] = buf[index + i];
+ }
+ }
+
+ return result;
+}
+
+function convertToSRGB(val) {
+ if (val <= 0) {
+ return 0;
+ } else if (val < 0.0031308) {
+ return 12.92 * val;
+ } else if (val < 1) {
+ return 1.055 * Math.pow(val, 0.41666) - 0.055;
+ } else {
+ return 1;
+ }
+}
+
+function denormalizeColor(srcInternalFormat, destType, color) {
+ var result = color.slice();
+ var tol = 0;
+
+ var srcIsNormalized = false;
+
+ switch (srcInternalFormat) {
+ case gl.R8:
+ case gl.RG8:
+ case gl.RGB8:
+ case gl.RGBA8:
+ case gl.RGB5_A1:
+ case gl.SRGB8_ALPHA8:
+ case gl.RGB10_A2:
+ srcIsNormalized = true;
+ tol = 6;
+ break;
+ case gl.RGB565:
+ // RGB565 needs slightly extra tolerance, at least on Google Pixel. crbug.com/682753
+ srcIsNormalized = true;
+ tol = 7;
+ break;
+ case gl.RGBA4:
+ srcIsNormalized = true;
+ tol = 10;
+ break;
+ }
+
+ if (!srcIsNormalized) {
+ return { color: result, tol: tol };
+ }
+
+ if (srcInternalFormat == gl.SRGB8_ALPHA8) {
+ for (var i = 0; i < 3; ++i) {
+ result[i] = convertToSRGB(result[i]);
+ }
+ }
+
+ switch (destType) {
+ case gl.UNSIGNED_BYTE:
+ result = result.map(val => { return val * 0xFF});
+ break;
+ case gl.UNSIGNED_SHORT:
+ // On Linux NVIDIA, tol of 33 is necessary to pass the test.
+ tol = 40;
+ result = result.map(val => { return val * 0xFFFF});
+ break;
+ case gl.UNSIGNED_INT:
+ tol = 40;
+ result = result.map(val => { return val * 0xFFFFFFFF});
+ break;
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ result = result.map(val => { return val * 0xF});
+ break;
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ result[0] = result[0] * 0x1F;
+ result[1] = result[1] * 0x1F;
+ result[2] = result[2] * 0x1F;
+ result[3] = result[3] * 0x1;
+ break;
+ case gl.UNSIGNED_SHORT_5_6_5:
+ result[0] = result[0] * 0x1F;
+ result[1] = result[1] * 0x3F;
+ result[2] = result[2] * 0x1F;
+ break;
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ tol = 25;
+ result[0] = result[0] * 0x3FF;
+ result[1] = result[1] * 0x3FF;
+ result[2] = result[2] * 0x3FF;
+ result[3] = result[3] * 0x3;
+ break;
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ result[0] = result[0] * 0x1FF;
+ result[1] = result[1] * 0x1FF;
+ result[2] = result[2] * 0x1FF;
+ result[3] = result[3] * 0x1F;
+ break;
+ }
+
+ return { color: result, tol: tol };
+}
+
+function compareColor(buf, index, expectedColor, srcInternalFormat,
+ srcFormat, srcType, readFormat, readType) {
+ var srcChannelCount = getChannelCount(srcFormat);
+ var readChannelCount = getChannelCount(readFormat);
+
+ var color = getColor(buf, index, readFormat, readType);
+ expectedColor = denormalizeColor(srcInternalFormat, readType, expectedColor);
+
+ var minChannel = Math.min(srcChannelCount, readChannelCount);
+ for (var i = 0; i < minChannel; ++i) {
+ if (Math.abs(expectedColor.color[i] - color[i]) > expectedColor.tol) {
+ testFailed("Expected color = " + expectedColor.color + ", was = " + color);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+var textureTestCases = [
+ {
+ texInternalFormat: 'R8', texFormat: 'RED', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.0, 0.0, 0],
+ },
+ {
+ texInternalFormat: 'R8UI', texFormat: 'RED_INTEGER', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [250, 0, 0, 0],
+ },
+ {
+ texInternalFormat: 'R8I', texFormat: 'RED_INTEGER', texType: 'BYTE',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-126, 0, 0, 0],
+ },
+ {
+ texInternalFormat: 'R16UI', texFormat: 'RED_INTEGER', texType: 'UNSIGNED_SHORT',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [30001, 0, 0, 0],
+ },
+ {
+ texInternalFormat: 'R16I', texFormat: 'RED_INTEGER', texType: 'SHORT',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-14189, 0, 0, 0],
+ },
+ {
+ texInternalFormat: 'R32UI', texFormat: 'RED_INTEGER', texType: 'UNSIGNED_INT',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [126726, 0, 0, 0],
+ },
+ {
+ texInternalFormat: 'R32I', texFormat: 'RED_INTEGER', texType: 'INT',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-126726, 0, 0, 0],
+ },
+
+ {
+ texInternalFormat: 'RG8', texFormat: 'RG', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.7, 0.0, 0],
+ },
+ {
+ texInternalFormat: 'RG8UI', texFormat: 'RG_INTEGER', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [250, 124, 0, 0],
+ },
+ {
+ texInternalFormat: 'RG8I', texFormat: 'RG_INTEGER', texType: 'BYTE',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-55, 124, 0, 0],
+ },
+ {
+ texInternalFormat: 'RG16UI', texFormat: 'RG_INTEGER', texType: 'UNSIGNED_SHORT',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [30001, 18, 0, 0],
+ },
+ {
+ texInternalFormat: 'RG16I', texFormat: 'RG_INTEGER', texType: 'SHORT',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-14189, 6735, 0, 0],
+ },
+ {
+ texInternalFormat: 'RG32UI', texFormat: 'RG_INTEGER', texType: 'UNSIGNED_INT',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [126726, 1976, 0, 0],
+ },
+ {
+ texInternalFormat: 'RG32I', texFormat: 'RG_INTEGER', texType: 'INT',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-126726, 126726, 0, 0],
+ },
+
+ {
+ texInternalFormat: 'RGB8', texFormat: 'RGB', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 1, 0, 0],
+ },
+ {
+ texInternalFormat: 'RGB565', texFormat: 'RGB', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.7, 0.2, 0],
+ },
+ {
+ texInternalFormat: 'RGB565', texFormat: 'RGB', texType: 'UNSIGNED_SHORT_5_6_5',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.7, 0.2, 0],
+ },
+
+ {
+ texInternalFormat: 'RGBA8', texFormat: 'RGBA', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0, 1, 0.7],
+ },
+ {
+ texInternalFormat: 'SRGB8_ALPHA8', texFormat: 'RGBA', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0, 1, 0.7],
+ },
+ {
+ texInternalFormat: 'RGB5_A1', texFormat: 'RGBA', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0, 0.7, 1],
+ },
+ {
+ texInternalFormat: 'RGB5_A1', texFormat: 'RGBA', texType: 'UNSIGNED_SHORT_5_5_5_1',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.7, 1, 0],
+ },
+ {
+ texInternalFormat: 'RGB5_A1', texFormat: 'RGBA', texType: 'UNSIGNED_INT_2_10_10_10_REV',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.7, 0, 1],
+ },
+ {
+ texInternalFormat: 'RGBA4', texFormat: 'RGBA', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.5, 0.7, 1, 0],
+ },
+ {
+ texInternalFormat: 'RGBA4', texFormat: 'RGBA', texType: 'UNSIGNED_SHORT_4_4_4_4',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [1, 0, 0.5, 0.7],
+ },
+ {
+ texInternalFormat: 'RGBA8UI', texFormat: 'RGBA_INTEGER', texType: 'UNSIGNED_BYTE',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [127, 0, 255, 178],
+ },
+ {
+ texInternalFormat: 'RGBA8I', texFormat: 'RGBA_INTEGER', texType: 'BYTE',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [-55, 56, 80, 127],
+ },
+ {
+ texInternalFormat: 'RGB10_A2UI', texFormat: 'RGBA_INTEGER', texType: 'UNSIGNED_INT_2_10_10_10_REV',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [178, 0, 127, 3],
+ },
+ {
+ texInternalFormat: 'RGBA16UI', texFormat: 'RGBA_INTEGER', texType: 'UNSIGNED_SHORT',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [14189, 6735, 0, 19],
+ },
+ {
+ texInternalFormat: 'RGBA16I', texFormat: 'RGBA_INTEGER', texType: 'SHORT',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [14189, -6735, 0, 19],
+ },
+ {
+ texInternalFormat: 'RGBA32UI', texFormat: 'RGBA_INTEGER', texType: 'UNSIGNED_INT',
+ readFormat: 'RGBA_INTEGER', readType: 'UNSIGNED_INT',
+ clearColor: [126726, 6726, 98765, 2015],
+ },
+ {
+ texInternalFormat: 'RGBA32I', texFormat: 'RGBA_INTEGER', texType: 'INT',
+ readFormat: 'RGBA_INTEGER', readType: 'INT',
+ clearColor: [126726, -6726, -98765, 2015],
+ },
+
+ {
+ texInternalFormat: 'RGB10_A2', texFormat: 'RGBA', texType: 'UNSIGNED_INT_2_10_10_10_REV',
+ readFormat: 'RGBA', readType: 'UNSIGNED_BYTE',
+ clearColor: [0.7, 0, 0.5, 1],
+ },
+
+ // TODO(zmo): add float/half_float test cases with extension supports.
+];
+
+function getArrayTypeFromReadPixelsType(gl, type) {
+ switch (type) {
+ case gl.UNSIGNED_BYTE:
+ return Uint8Array;
+ case gl.BYTE:
+ return Int8Array;
+ 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 Uint16Array;
+ case gl.SHORT:
+ return Int16Array;
+ case gl.UNSIGNED_INT:
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ return Uint32Array;
+ case gl.INT:
+ return Int32Array;
+ case gl.HALF_FLOAT:
+ return Uint16Array;
+ case gl.FLOAT:
+ return Float32Array;
+ default:
+ return null;
+ }
+}
+
+function getFormatString(gl, format) {
+ switch (format) {
+ case gl.RED:
+ return 'RED';
+ case gl.RED_INTEGER:
+ return 'RED_INTEGER';
+ case gl.RG:
+ return 'RG';
+ case gl.RG_INTEGER:
+ return 'RG_INTEGER';
+ case gl.RGB:
+ return 'RGB';
+ case gl.RGB_INTEGER:
+ return 'RGB_INTEGER';
+ case gl.RGBA:
+ return 'RGBA';
+ case gl.RGBA_INTEGER:
+ return 'RGBA_INTEGER';
+ case gl.LUMINANCE:
+ return 'LUMINANCE';
+ case gl.LUMINANCE_ALPHA:
+ return 'LUMINANCE_ALPHA';
+ case gl.ALPHA:
+ return 'ALPHA';
+ default:
+ return '';
+ };
+}
+
+function getTypeString(gl, type) {
+ switch (type) {
+ case gl.UNSIGNED_BYTE:
+ return 'UNSIGNED_BYTE';
+ case gl.BYTE:
+ return 'BYTE';
+ case gl.UNSIGNED_SHORT:
+ return 'UNSIGNED_SHORT';
+ case gl.SHORT:
+ return 'SHORT';
+ case gl.UNSIGNED_INT:
+ return 'UNSIGNED_INT';
+ case gl.INT:
+ return 'INT';
+ case gl.UNSIGNED_SHORT_5_6_5:
+ return 'UNSIGNED_SHORT_5_6_5';
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ return 'UNSIGNED_SHORT_5_5_5_1';
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ return 'UNSIGNED_INT_2_10_10_10_REV';
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ return 'UNSIGNED_SHORT_4_4_4_4';
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ return 'UNSIGNED_INT_10F_11F_11F_REV';
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ return 'UNSIGNED_INT_5_9_9_9_REV';
+ default:
+ return '';
+ };
+}
+
+function elementCountPerPixel(gl, readFormat, readType) {
+ switch (readFormat) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ case gl.ALPHA:
+ case gl.LUMINANCE:
+ return 1;
+ case gl.RG:
+ case gl.RG_INTEGER:
+ case gl.LUMINANCE_ALPHA:
+ return 2;
+ case gl.RGB:
+ case gl.RGB_INTEGER:
+ switch (readType) {
+ case gl.UNSIGNED_SHORT_5_6_5:
+ return 1;
+ default:
+ return 3;
+ }
+ case gl.RGBA:
+ case gl.RGBA_INTEGER:
+ switch (readType) {
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ return 1;
+ default:
+ return 4;
+ }
+ default:
+ testFailed("Unexpected read format/type = " + readFormat + "/" + readType);
+ return 0;
+ }
+}
+
+function testReadPixels(gl, srcInternalFormat, srcFormat, srcType,
+ readFormat, readType, expectedColor) {
+ var arrayType = getArrayTypeFromReadPixelsType(gl, readType);
+ var buf = new arrayType(width * height * 4);
+ gl.readPixels(0, 0, width, height, readFormat, readType, buf);
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR, "readPixels should generate no error");
+ var diffFound = false;
+ for (var ii = 0; ii < width * height; ++ii) {
+ var offset = ii * elementCountPerPixel(gl, readFormat, readType);
+ if (!compareColor(buf, offset, expectedColor, srcInternalFormat, srcFormat, srcType,
+ readFormat, readType)) {
+ diffFound = true;
+ break;
+ }
+ }
+ if (!diffFound) {
+ testPassed("Color read back as expected");
+ }
+}
+
+function clearBuffer(gl, texInternalFormat, clearColor) {
+ var value;
+ switch (texInternalFormat) {
+ case gl.R8UI:
+ case gl.R16UI:
+ case gl.R32UI:
+ case gl.RG8UI:
+ case gl.RG16UI:
+ case gl.RG32UI:
+ case gl.RGBA8UI:
+ case gl.RGBA16UI:
+ case gl.RGBA32UI:
+ case gl.RGB10_A2UI:
+ value = new Uint32Array(4);
+ for (var ii = 0; ii < 4; ++ii)
+ value[ii] = clearColor[ii];
+ gl.clearBufferuiv(gl.COLOR, 0, value);
+ break;
+ case gl.R8I:
+ case gl.R16I:
+ case gl.R32I:
+ case gl.RG8I:
+ case gl.RG16I:
+ case gl.RG32I:
+ case gl.RGBA8I:
+ case gl.RGBA16I:
+ case gl.RGBA32I:
+ value = new Int32Array(4);
+ for (var ii = 0; ii < 4; ++ii)
+ value[ii] = clearColor[ii];
+ gl.clearBufferiv(gl.COLOR, 0, value);
+ break;
+ default:
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ break;
+ }
+}
+
+for (var tt = 0; tt < textureTestCases.length; ++tt) {
+ var test = textureTestCases[tt];
+ debug("");
+ debug("ReadPixels from fbo with texture = (" + test.texInternalFormat +
+ ", " + test.texFormat + ", " + test.texType +
+ "), format = " + test.readFormat + ", type = " + test.readType);
+ var width = 2;
+ var height = 2;
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var colorImage = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, colorImage);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[test.texInternalFormat], width, height, 0,
+ gl[test.texFormat], gl[test.texType], null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, colorImage, 0);
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR, "Setting up fbo should generate no error");
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("fbo is not complete, skip");
+ continue;
+ }
+ clearBuffer(gl, gl[test.texInternalFormat], test.clearColor);
+ wtu.glErrorShouldBe(
+ gl, gl.NO_ERROR, "Clear color should generate no error");
+
+ var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
+ var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
+ var implFormatString = getFormatString(gl, implFormat);
+ var implTypeString = getTypeString(gl, implType);
+
+ if (gl[test.texInternalFormat] == gl.RGB10_A2) {
+ // This is a special case where three read format/type are supported.
+ var readTypes = [gl.UNSIGNED_BYTE, gl.UNSIGNED_INT_2_10_10_10_REV];
+ var readTypeStrings = ['UNSIGNED_BYTE', 'UNSIGNED_INT_2_10_10_10_REV'];
+ if (implFormat == gl.RGBA && implTypeString != '') {
+ readTypes.push(implType);
+ readTypeStrings.push(implTypeString);
+ } else {
+ testFailed("Unimplemented Implementation dependent color read format/type = " +
+ implFormat + "/" + implType);
+ }
+ for (var rr = 0; rr < readTypes.length; ++rr) {
+ debug("Special case RGB10_A2, format = RGBA, type = " + readTypeStrings[rr]);
+ testReadPixels(gl, gl[test.texInternalFormat], gl[test.texFormat], gl[test.texType],
+ gl.RGBA, readTypes[rr], test.clearColor);
+ }
+ } else {
+ testReadPixels(gl, gl[test.texInternalFormat], gl[test.texFormat], gl[test.texType],
+ gl[test.readFormat], gl[test.readType], test.clearColor);
+
+ debug("Testing implementation dependent color read format = " + implFormatString +
+ ", type = " + implTypeString);
+ if (implFormatString == '') {
+ testFailed("Invalid IMPLEMENTATION_COLOR_READ_FORMAT = " + implFormat);
+ continue;
+ }
+ if (implTypeString == '') {
+ testFailed("Invalid IMPLEMENTATION_COLOR_READ_TYPE = " + implType);
+ continue;
+ }
+ testReadPixels(gl, gl[test.texInternalFormat], gl[test.texFormat], gl[test.texType],
+ implFormat, implType, test.clearColor);
+
+ gl.deleteTexture(colorImage);
+ gl.deleteFramebuffer(fbo);
+ }
+}
+
+debug("")
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-rgb8-into-pbo-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-rgb8-into-pbo-bug.html
new file mode 100644
index 0000000000..b4f91f1d3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-from-rgb8-into-pbo-bug.html
@@ -0,0 +1,85 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Conformance Test: readPixels from RGB8 Buffer Into Pixel Pack Buffer.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+debug("");
+description("Verifies readPixels from RGB8 buffer into PIXEL_PACK buffer works");
+
+debug("On MacOSX with AMD GPUs, the alpha channel is readback as 0 instead of 255");
+
+var wtu = WebGLTestUtils;
+var pixel = [0, 0, 0, 0];
+var expectedColor = [255, 102, 0, 255];
+
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var width = 4;
+ var height = 4;
+
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB8, width, height);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer);
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("framebuffer with RGB8 color buffer is incomplete");
+ } else {
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var pbo = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
+ gl.bufferData(gl.PIXEL_PACK_BUFFER, width * height * 4, gl.STATIC_COPY);
+
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+
+ var data = new Uint8Array(width * height * 4);
+ gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
+
+ for (var ii = 0; ii < width * height; ++ii) {
+ if (data[ii * 4] != 255 ||
+ data[ii * 4 + 1] != 0 ||
+ data[ii * 4 + 2] != 0 ||
+ data[ii * 4 + 3] != 255) {
+ testFailed("Expected in pixel " + ii + ": [255,0,0,255], got: " +
+ [data[ii * 4], data[ii * 4 + 1], data[ii * 4 + 2], data[ii * 4 + 3]]);
+ break;
+ }
+ }
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Tests should complete without gl errors");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-into-pixel-pack-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-into-pixel-pack-buffer.html
new file mode 100644
index 0000000000..7d646a6ecd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-into-pixel-pack-buffer.html
@@ -0,0 +1,152 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Conformance Test: ReadPixels Into Pixel Pack Buffer.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+function checkFormatAndType()
+{
+ debug("");
+ debug("check format / type");
+ var invalidFormat = [gl.DEPTH_COMPONENT, gl.DEPTH_STENCIL, gl.R8, gl.RGBA4, gl.LUMINANCE, gl.LUMINANCE_ALPHA];
+ var invalidType = [gl.UNSIGNED_INT_24_8];
+ for (var ff = 0; ff < invalidFormat.length; ++ff) {
+ var format = invalidFormat[ff];
+ gl.readPixels(0, 0, 1, 1, format, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Format should not be able to read as " + wtu.glEnumToString(gl, format));
+ }
+ for (var tt = 0; tt < invalidType.length; ++tt) {
+ var type = invalidType[tt];
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, type, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Type should not be able to read as " + wtu.glEnumToString(gl, type));
+ }
+
+ debug("");
+ debug("check combinations of format and type");
+ var combinations = [
+ {format: gl.RGBA, type: gl.UNSIGNED_BYTE},
+ {format: gl.RGB, type: gl.UNSIGNED_BYTE},
+ {format: gl.RGB, type: gl.UNSIGNED_SHORT_5_6_5},
+ {format: gl.RGBA, type: gl.UNSIGNED_SHORT_5_5_5_1},
+ {format: gl.RGBA, type: gl.UNSIGNED_SHORT_4_4_4_4},
+ {format: gl.ALPHA, type: gl.UNSIGNED_BYTE},
+ {format: gl.RED, type: gl.UNSIGNED_BYTE},
+ {format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT},
+ {format: gl.RGBA_INTEGER, type: gl.INT}
+ ];
+
+ var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
+ var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
+ for (var tt = 0; tt < combinations.length; ++ tt) {
+ var info = combinations[tt];
+ var format = info.format;
+ var type = info.type;
+ gl.readPixels(0, 0, 1, 1, format, type, 0);
+ // Only two format/type parameter pairs are accepted. GL_RGBA/GL_UNSIGNED_BYTE is always
+ // accepted on default readbuffer. The other acceptable pair can be discovered by querying
+ // GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
+ if ((format == gl.RGBA && type == gl.UNSIGNED_BYTE) || (format == implFormat && type == implType)) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "The combination of format/type should be able to read as " +
+ wtu.glEnumToString(gl, format) + " / " + wtu.glEnumToString(gl, type));
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The combination of format/type should not be able to read as " +
+ wtu.glEnumToString(gl, format) + " / " + wtu.glEnumToString(gl, type));
+ }
+ }
+}
+
+function validatePixelPackBufferAndParameters(canvasWidth, canvasHeight)
+{
+ debug("");
+ debug("Validate PIXEL_PACK buffer and readPixels' parameters");
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.pixelStorei(gl.PACK_ALIGNMENT, 1);
+
+ var size = canvasWidth * canvasHeight * 4;
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_PACK_BUFFER, size, gl.STATIC_DRAW);
+ var array = new Uint8Array(size);
+
+ debug("");
+ debug("PIXEL_PACK buffer is bound");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should generate INVALID_OPERATION if pixel pack buffer is bound");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Validate the offset of PIXEL_PACK buffer and buffer size");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, -1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "offset < 0");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, size);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "offset > buffer size");
+ gl.readPixels(0, 0, canvasWidth + 1, canvasHeight, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "pixel pack buffer is not large enough");
+
+ debug("");
+ debug("Validate the reading area of framebuffer");
+ gl.readPixels(-1, -2, canvasWidth, canvasHeight, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "reading pixels outside of the framebuffer should succeed.");
+ gl.readPixels(2, 1, canvasWidth, canvasHeight, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "reading pixels outside of the framebuffer should succeed.");
+ gl.readPixels(2, 1, -1, -1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "reading pixels with negative width / height should generate INVALID_VALUE.");
+
+ checkFormatAndType();
+
+ debug("");
+ debug("no PIXEL_PACK buffer bound");
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "no pixel pack buffer bound");
+
+ gl.deleteBuffer(buffer);
+}
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var pixel = [0, 0, 0, 0];
+var expectedColor = [255, 102, 0, 255];
+
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ description('ReadPixels into PIXEL_PACK buffer');
+ validatePixelPackBufferAndParameters(4, 4);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-pack-parameters.html b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-pack-parameters.html
new file mode 100644
index 0000000000..8d4559fb93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/reading/read-pixels-pack-parameters.html
@@ -0,0 +1,353 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict"
+
+var wtu = WebGLTestUtils;
+var initialColor = [1, 2, 3, 4];
+var expectedColor = [[249, 102, 0, 255],
+ [2, 200, 102, 255],
+ [134, 87, 234, 255],
+ [99, 5, 76, 255]];
+
+function calculatePaddingBytes(bytesPerPixel, packAlignment, width)
+{
+ var padding = 0;
+ switch (packAlignment) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ padding = (bytesPerPixel * width) % packAlignment;
+ if (padding > 0)
+ padding = packAlignment - padding;
+ return padding;
+ default:
+ testFailed("should not reach here");
+ return;
+ }
+}
+
+function paintWebGLCanvas(gl)
+{
+ var program = wtu.setupTexturedQuad(gl);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ var data = new Uint8Array(4 * 4);
+ for (var ii = 0; ii < 4; ++ii) {
+ data[ii * 4] = expectedColor[ii][0];
+ data[ii * 4 + 1] = expectedColor[ii][1];
+ data[ii * 4 + 2] = expectedColor[ii][2];
+ data[ii * 4 + 3] = expectedColor[ii][3];
+ }
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+
+ wtu.clearAndDrawUnitQuad(gl);
+}
+
+function samePixel(array, index, refPixel, row, pixelTag)
+{
+ for (var ii = 0; ii < refPixel.length; ++ii) {
+ if (array[index] == refPixel[ii][0] &&
+ array[index + 1] == refPixel[ii][1] &&
+ array[index + 2] == refPixel[ii][2] &&
+ array[index + 3] == refPixel[ii][3]) {
+ return true;
+ }
+ }
+ var refPixelText = "";
+ for (var ii = 0; ii < refPixel.length; ++ii) {
+ if (ii > 0)
+ refPixelText += " or ";
+ refPixelText += "[" + refPixel[ii] + "]";
+ }
+ testFailed(pixelTag + " pixel of row " + row + ": expected " + refPixelText + ", got [" +
+ [array[index], array[index + 1], array[index + 2], array[index + 3]] + "]");
+ return false;
+}
+
+function runTestIteration(xoffset, yoffset, width, height, packParams, usePixelPackBuffer, packParamsValid)
+{
+ if (!("alignment" in packParams))
+ packParams.alignment = 4;
+ if (!("rowLength" in packParams))
+ packParams.rowLength = 0;
+ if (!("skipPixels" in packParams))
+ packParams.skipPixels = 0;
+ if (!("skipRows" in packParams))
+ packParams.skipRows = 0;
+ debug("Testing xoffset = " + xoffset + ", yoffset " + yoffset +
+ ", width = " + width + ", height = " + height +
+ ", PACK_ALIGNMENT = " + packParams.alignment + ", PACK_ROW_LENGTH = " + packParams.rowLength +
+ ", PACK_SKIP_PIXELS = " + packParams.skipPixels + " , PACK_SKIP_ROWS = " + packParams.skipRows);
+ gl.pixelStorei(gl.PACK_ALIGNMENT, packParams.alignment);
+ gl.pixelStorei(gl.PACK_ROW_LENGTH, packParams.rowLength);
+ gl.pixelStorei(gl.PACK_SKIP_PIXELS, packParams.skipPixels);
+ gl.pixelStorei(gl.PACK_SKIP_ROWS, packParams.skipRows);
+
+ var actualWidth = packParams.rowLength > 0 ? packParams.rowLength : width;
+
+ var bytesPerPixel = 4; // see readPixels' parameters below, the format is gl.RGBA, type is gl.UNSIGNED_BYTE
+ var padding = calculatePaddingBytes(bytesPerPixel, packParams.alignment, actualWidth);
+ var bytesPerRow = actualWidth * bytesPerPixel + padding;
+
+ var size = bytesPerRow * (height - 1) + bytesPerPixel * width;
+ var skipSize = packParams.skipPixels * bytesPerPixel + packParams.skipRows * bytesPerRow;
+ var array = new Uint8Array(skipSize + size);
+ for (var ii = 0; ii < skipSize + size; ++ii) {
+ array[ii] = initialColor[ii % bytesPerPixel];
+ }
+ var arrayWrongSize = null;
+ if (size > 0)
+ arrayWrongSize = new Uint8Array(skipSize + size - 1);
+ if (usePixelPackBuffer) {
+ var offset = 0;
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer);
+ if (size > 0) {
+ gl.bufferData(gl.PIXEL_PACK_BUFFER, arrayWrongSize, gl.STATIC_DRAW);
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, offset);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+ }
+ gl.bufferData(gl.PIXEL_PACK_BUFFER, array, gl.STATIC_DRAW);
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, offset);
+ } else {
+ if (size > 0) {
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, arrayWrongSize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+ }
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ }
+ if (packParamsValid) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Invalid pack params combination");
+ return;
+ }
+
+ if (size == 0)
+ return;
+
+ if (usePixelPackBuffer) {
+ array = new Uint8Array(skipSize + size);
+ gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, array);
+ }
+
+ // Check skipped bytes are unchanged.
+ for (var ii = 0; ii < skipSize; ++ii) {
+ if (array[ii] != initialColor[ii % bytesPerPixel]) {
+ testFailed("skipped bytes changed at index " + ii + ": expected " +
+ initialColor[ii % bytesPerPixel] + " got " + array[ii]);
+ break;
+ }
+ }
+ // Check the first and last pixels of each row.
+ var canvasWidth = 4;
+ var canvasHeight = 4;
+ for (var row = 0; row < height; ++row) {
+ var refColor;
+ var yIndex = yoffset + row;
+ var xIndex;
+
+ // First pixel
+ var pos = skipSize + bytesPerRow * row;
+ xIndex = xoffset;
+ if (xIndex < 0 || xIndex >= canvasWidth || yIndex < 0 || yIndex >= canvasHeight) {
+ if (row > 0 && usePixelPackBuffer && packParams.rowLength > 0 && packParams.rowLength < width)
+ refColor = [initialColor, expectedColor[yIndex - 1]];
+ else
+ refColor = [initialColor];
+ } else {
+ refColor = [expectedColor[yIndex]];
+ }
+ samePixel(array, pos, refColor, row, "first");
+
+ // Last pixel
+ var xSpan;
+ if (row + 1 == height || packParams.rowLength > width)
+ xSpan = width;
+ else
+ xSpan = actualWidth;
+ xIndex = xoffset + xSpan - 1;
+ pos += (xSpan - 1) * bytesPerPixel;
+ if (xIndex < 0 || xIndex >= canvasWidth || yIndex < 0 || yIndex >= canvasHeight) {
+ if (row > 0 && usePixelPackBuffer && packParams.rowLength > 0 && packParams.rowLength < width)
+ refColor = [initialColor, expectedColor[yIndex - 1]];
+ else
+ refColor = [initialColor];
+ } else {
+ refColor = [expectedColor[yIndex]];
+ }
+ samePixel(array, pos, refColor, row, "last");
+
+ // Check padding bytes are unchanged and bytes beyond rowLength set correctly.
+ pos += bytesPerPixel;
+ if (row + 1 < height) {
+ // Beyond bytes filled for PACK_ROW_LENGTH, the row could have extra bytes due to
+ // padding. These extra bytes could be either filled with pixel data if
+ // PACK_ROW_LENGTH is set to be less than width, or they could be left unchanged
+ // if they are beyond |width| pixels.
+ if (packParams.rowLength > 0 && packParams.rowLength < width) {
+ var trailingBytes = Math.min((width - packParams.rowLength) * bytesPerPixel,
+ bytesPerRow - packParams.rowLength * bytesPerPixel);
+ for (var ii = 0; ii < trailingBytes; ++ii) {
+ if (array[pos + ii] != refColor[0][ii % bytesPerPixel]) {
+ testFailed("Trailing byte " + ii + " after rowLength of row " + row + " : expected " +
+ refColor[0][ii % bytesPerPixel] + ", got " + array[pos + ii]);
+ break;
+ }
+ }
+ pos += trailingBytes;
+ }
+ var paddingBytes = skipSize + bytesPerRow * (row + 1) - pos;
+ for (var ii = 0; ii < paddingBytes; ++ii) {
+ if (array[pos + ii] != initialColor[ii % bytesPerPixel]) {
+ testFailed("Padding byte " + ii + " of row " + row + " changed: expected " +
+ initialColor[ii % bytesPerPixel] + ", got " + array[pos + ii]);
+ break;
+ }
+ }
+ }
+ }
+}
+
+function testPackParameters(usePixelPackBuffer)
+{
+ debug("");
+ var destText = usePixelPackBuffer ? "PIXEL_PACK buffer" : "array buffer";
+ debug("Verify that reading pixels to " + destText + " works fine with various pack alignments.");
+ runTestIteration(0, 0, 1, 3, {alignment:1}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 1, 3, {alignment:2}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 1, 3, {alignment:4}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 1, 3, {alignment:8}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 2, 3, {alignment:4}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 2, 3, {alignment:8}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 3, 3, {alignment:4}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 3, 3, {alignment:8}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 0, 0, {alignment:1}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 1, 3, {alignment:4}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 1, 3, {alignment:8}, usePixelPackBuffer, true);
+
+ debug("");
+ debug("Verify that reading pixels to " + destText + " is disallowed when PACK_ROW_LENGTH < width.");
+ runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
+ runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:1}, usePixelPackBuffer, false);
+
+ debug("");
+ debug("Verify that reading pixels to " + destText + " works fine with PACK_ROW_LENGTH == width.");
+ runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+ runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
+
+ debug("");
+ debug("Verify that reading pixels to " + destText + " works fine with PACK_ROW_LENGTH > width and with no padding");
+ runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+ runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
+
+ debug("");
+ debug("Verify that reading pixels to " + destText + " works fine with PACK_ROW_LENGTH > width and with padding");
+ runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+ runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
+
+ debug("");
+ debug("Verify that reading pixels to " + destText + " works fine with pack skip parameters.");
+ runTestIteration(0, 0, 3, 3, {alignment:8, skipPixels:2}, usePixelPackBuffer, false);
+ runTestIteration(0, 0, 3, 3, {alignment:8, skipPixels:1, skipRows:3}, usePixelPackBuffer, false);
+ runTestIteration(0, 0, 3, 3, {alignment:8, skipRows:3}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 2, 3, {alignment:8, skipPixels:2}, usePixelPackBuffer, false);
+ runTestIteration(0, 0, 2, 3, {alignment:8, skipPixels:1, skipRows:3}, usePixelPackBuffer, false);
+ runTestIteration(0, 0, 2, 3, {alignment:8, skipRows:3}, usePixelPackBuffer, true);
+ runTestIteration(0, 0, 2, 3, {skipPixels:1, rowLength:4}, usePixelPackBuffer, true);
+}
+
+debug("");
+debug("Canvas.getContext");
+
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ description('ReadPixels into array buffer');
+ paintWebGLCanvas(gl);
+ var usePixelPackBuffer = false;
+ testPackParameters(usePixelPackBuffer);
+ usePixelPackBuffer = true;
+ testPackParameters(usePixelPackBuffer);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt
new file mode 100644
index 0000000000..c06bbe3770
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt
@@ -0,0 +1,10 @@
+framebuffer-object-attachment.html
+framebuffer-test.html
+framebuffer-texture-layer.html
+invalidate-framebuffer.html
+multisampled-renderbuffer-initialization.html
+--min-version 2.0.1 multisampled-depth-renderbuffer-initialization.html
+--min-version 2.0.1 multisampled-stencil-renderbuffer-initialization.html
+--min-version 2.0.1 multisample-with-full-sample-counts.html
+--min-version 2.0.1 multisample-draws-between-blits.html
+readbuffer.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html
new file mode 100644
index 0000000000..754ff2cc73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html
@@ -0,0 +1,508 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (expected.indexOf(actual) < 0) {
+ var msg = "checkFramebufferStatus expects [";
+ for (var index = 0; index < expected.length; ++index) {
+ msg += wtu.glEnumToString(gl, expected[index]);
+ if (index + 1 < expected.length)
+ msg += ", ";
+ }
+ msg += "], was " + wtu.glEnumToString(gl, actual);
+ testFailed(msg);
+ } else {
+ var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
+ " as expected";
+ testPassed(msg);
+ }
+}
+
+function checkBufferBits(attachment0, attachment1) {
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
+ return;
+ var haveDepthBuffer = attachment0 == gl.DEPTH_ATTACHMENT ||
+ attachment0 == gl.DEPTH_STENCIL_ATTACHMENT ||
+ attachment1 == gl.DEPTH_ATTACHMENT ||
+ attachment1 == gl.DEPTH_STENCIL_ATTACHMENT;
+ var haveStencilBuffer = attachment0 == gl.STENCIL_ATTACHMENT ||
+ attachment0 == gl.DEPTH_STENCIL_ATTACHMENT ||
+ attachment1 == gl.STENCIL_ATTACHMENT ||
+ attachment1 == gl.DEPTH_STENCIL_ATTACHMENT;
+ shouldBeTrue("gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS) + " +
+ "gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16");
+ if (haveDepthBuffer)
+ shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) >= 16");
+ else
+ shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) == 0");
+ if (haveStencilBuffer)
+ shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) >= 8");
+ else
+ shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) == 0");
+}
+
+
+function testFramebufferWebGL1RequiredCombinations() {
+ debug("Checking combinations of framebuffer attachments required to be valid by WebGL 1");
+
+ // Per discussion with the OpenGL ES working group, the following framebuffer attachment
+ // combinations are required to work in all WebGL 1 implementations:
+ // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
+ // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
+ // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var width = 64;
+ var height = 64;
+
+ // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
+ 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);
+ 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, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits();
+
+ // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_ATTACHMENT);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
+
+ // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
+
+ // Clean up
+ gl.deleteRenderbuffer(renderbuffer);
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+}
+
+function testDepthStencilAttachmentBehaviors() {
+ debug("");
+ debug("Checking ES3 DEPTH_STENCIL_ATTACHMENT behaviors are implemented for WebGL 2");
+ // DEPTH_STENCIL_ATTACHMENT is treated as an independent attachment point in WebGL 1;
+ // however, in WebGL 2, it is treated as an alias for DEPTH_ATTACHMENT + STENCIL_ATTACHMENT.
+ var size = 16;
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var colorBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, size, size);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ var depthBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
+
+ var stencilBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, size, size);
+
+ var depthStencilBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("color + depth");
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_ATTACHMENT);
+
+ debug("");
+ debug("color + depth + stencil: depth != stencil");
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", stencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+
+ debug("");
+ debug("color + depth: DEPTH_STENCIL for DEPTH_ATTACHMENT");
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_ATTACHMENT);
+
+ debug("");
+ debug("color + depth + stencil: DEPTH_STENCIL for DEPTH_ATTACHMENT and STENCIL_ATTACHMENT");
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
+
+ debug("");
+ debug("color + depth_stencil");
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH24_STENCIL8, size, size, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, texture, 0);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", texture);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", texture);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", texture);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, null, 0);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
+
+ debug("");
+ debug("DEPTH_STENCIL_ATTACHMENT overwrites DEPTH_ATTACHMENT/STENCIL_ATTACHMENT")
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits();
+
+ debug("");
+ debug("STENCIL_ATTACHMENT overwrites stencil set by DEPTH_STENCIL_ATTACHMENT")
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ checkBufferBits(gl.DEPTH_ATTACHMENT);
+}
+
+function testFramebufferIncompleteAttachment() {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var colorBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ debug("");
+ debug("Wrong storage type for type of attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ debug("");
+ debug("0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
+
+ gl.deleteRenderbuffer(colorBuffer);
+ gl.deleteFramebuffer(fbo);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function testFramebufferIncompleteMissingAttachment() {
+ debug("");
+ debug("No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT");
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]);
+
+ var colorBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]);
+
+ gl.deleteRenderbuffer(colorBuffer);
+ gl.deleteFramebuffer(fbo);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function testFramebufferWithImagesOfDifferentSizes() {
+ debug("");
+ debug("Attachments of different sizes should NOT be allowed");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var colorBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
+
+ var depthBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 32, 16);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 32);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]);
+ }
+
+ gl.deleteTexture(tex);
+ gl.deleteRenderbuffer(depthBuffer);
+ gl.deleteRenderbuffer(colorBuffer);
+ gl.deleteFramebuffer(fbo);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+function testUsingIncompleteFramebuffer() {
+ debug("");
+ debug("Test drawing or reading from an incomplete framebuffer");
+ var program = wtu.setupTexturedQuad(gl);
+ var tex = gl.createTexture();
+ wtu.fillTexture(gl, tex, 1, 1, [0,255,0,255]);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]);
+ debug("");
+ debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
+ testRenderingAndReading();
+
+ var colorBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
+ debug("");
+ debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
+ testRenderingAndReading();
+
+ function testRenderingAndReading() {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "drawArrays with incomplete framebuffer");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "readPixels from incomplete framebuffer");
+ // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because
+ // the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments
+ // the framebuffer is not of a compatible type.
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION],
+ "copyTexImage2D from incomplete framebuffer");
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 1, 1, 0);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION],
+ "copyTexSubImage2D from incomplete framebuffer");
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "clear with incomplete framebuffer");
+ }
+
+ gl.deleteRenderbuffer(colorBuffer);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(tex);
+ gl.deleteProgram(program);
+}
+
+function testReadingFromMissingAttachment() {
+ debug("");
+ debug("Test drawing or reading from a framebuffer with no color image");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var object_type = gl.getFramebufferAttachmentParameter(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ if (object_type != gl.NONE)
+ testFailed("object type from empty attachment point should be NONE");
+ else
+ testPassed("object type from empty attachment point is NONE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query should not generate error");
+
+ var object_name = gl.getFramebufferAttachmentParameter(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ if (object_name)
+ testFailed("object name from empty attachment point should be null");
+ else
+ testPassed("object name from empty attachment point is null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query should not generate error");
+
+ var size = 16;
+
+ // The only scenario we can verify is an attempt to read or copy
+ // from a missing color attachment while the framebuffer is still
+ // complete.
+ var depthBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After depth renderbuffer setup");
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // The FBO has no color attachment. ReadPixels, CopyTexImage2D,
+ // and CopyTexSubImage2D should all generate INVALID_OPERATION.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before ReadPixels from missing attachment");
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After ReadPixels from missing attachment");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexImage2D from missing attachment");
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, size, size, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexImage2D from missing attachment");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexSubImage2D from missing attachment");
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexSubImage2D from missing attachment");
+
+ gl.deleteTexture(tex);
+ }
+
+ gl.deleteRenderbuffer(depthBuffer);
+ gl.deleteFramebuffer(fbo);
+}
+
+description("Test framebuffer object attachment behaviors");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
+
+testFramebufferWebGL1RequiredCombinations();
+testDepthStencilAttachmentBehaviors();
+testFramebufferIncompleteAttachment();
+testFramebufferIncompleteMissingAttachment();
+testFramebufferWithImagesOfDifferentSizes();
+testUsingIncompleteFramebuffer();
+testReadingFromMissingAttachment();
+
+// -
+
+debug("");
+debug("Test calling framebufferTexture2D with impossible mip levels.");
+
+const fb = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+const tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 1000);
+wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Mip level attachment impossibly high.");
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 10);
+wtu.glErrorShouldBe(gl, 0, "Mip level attachment within acceptable range.");
+
+// Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1636517 :
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 1000);
+wtu.glErrorShouldBe(gl, 0, "Mip level detachment can be impossibly high.");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "0");
+
+// -
+
+debug("")
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html
new file mode 100644
index 0000000000..5aa6c91847
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html
@@ -0,0 +1,288 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Framebuffer Test Against WebGL 2</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+
+function testFramebufferRenderbuffer() {
+ debug("");
+ debug("Checking framebuffer/renderbuffer stuff.");
+
+ gl.getFramebufferAttachmentParameter(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "getFramebufferAttachmentParameter(COLOR_ATTACHMENT0) on the default framebuffer.");
+ gl.getFramebufferAttachmentParameter(
+ gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "getFramebufferAttachmentParameter(BACK) on the default framebuffer.");
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "checkFramebufferStatus on the default framebuffer.");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "attach a texture to default framebuffer.");
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "detach default renderbuffer from default framebuffer.");
+
+ var rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, canvas.width, canvas.height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "allocate renderbuffer storage of a newly created renderbuffer.");
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "attach a renderbuffer to the default framebuffer.");
+
+ var fbtex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, fbtex);
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fb = gl.createFramebuffer();
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind a newly created framebuffer.");
+
+ var target = gl.READ_FRAMEBUFFER;
+ gl.getFramebufferAttachmentParameter(
+ target, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getFramebufferAttachmentParameter(READ_FRAMEBUFFER).");
+ assertMsg(gl.checkFramebufferStatus(target) != 0,
+ "checkFramebufferStatus(READ_FRAMEBUFFER) should succeed.");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "checkFramebufferStatus(READ_FRAMEBUFFER).");
+ var readFB = gl.createFramebuffer();
+ gl.bindFramebuffer(target, readFB);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindFramebuffer(READ_FRAMEBUFFER).");
+ assertMsg(readFB == gl.getParameter(gl.READ_FRAMEBUFFER_BINDING),
+ "bindFramebuffer(READ_FRAMEBUFFER) should change READ_FRAMEBUFFER_BINDING.");
+ assertMsg(fb == gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING),
+ "bindFramebuffer(READ_FRAMEBUFFER) should not change DRAW_FRAMEBUFFER_BINDING.");
+ gl.getFramebufferAttachmentParameter(
+ target, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) with no attachment.");
+ gl.framebufferTexture2D(target, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferTexImage2D(READ_FRAMEBUFFER).");
+ gl.framebufferRenderbuffer(target, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferRenderbuffer(READ_FRAMEBUFFER).");
+
+ var colorAttachmentsNum = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ if (colorAttachmentsNum >= 2) {
+ var attachment = gl.COLOR_ATTACHMENT1;
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferTexImage2D(COLOR_ATTACHMENT1).");
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, null, 0);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferRenderbuffer(COLOR_ATTACHMENT1).");
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null);
+ }
+
+ gl.getFramebufferAttachmentParameter(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "with no attachment.");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attach a texture to a framebuffer.");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a texture from a framebuffer.");
+
+ function numLevelsFromSize(size) {
+ var levels = 0;
+ while ((size >> levels) > 0) {
+ ++levels;
+ }
+ return levels;
+ }
+
+ var maxTexSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+ var maxLevels = numLevelsFromSize(maxTexSize);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, maxLevels - 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferTexture2D with an appropriate mipmap level.");
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, maxLevels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "framebufferTexture2D with a mipmap level out of range.");
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attach a renderbuffer to a framebuffer.");
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a renderbuffer from a framebuffer.");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind default (null) framebuffer.");
+
+ // attach/detach a 2d texture to one framebuffer binding point,
+ // while no attachment to the other binding point.
+ function attachAndDetachTexture(targetA, targetB) {
+ gl.framebufferTexture2D(targetA, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "attach a texture to read/draw framebuffer binding point.");
+ gl.getFramebufferAttachmentParameter(
+ targetA, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on read/draw framebuffer.");
+ gl.getFramebufferAttachmentParameter(
+ targetB, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on read/draw framebuffer with no attachment.");
+ gl.framebufferTexture2D(targetA, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a texture from read/draw framebuffer.");
+ }
+
+ var readFBWithTexture = gl.createFramebuffer();
+ var drawFBWithTexture = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFBWithTexture);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFBWithTexture);
+ attachAndDetachTexture(gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER);
+ attachAndDetachTexture(gl.DRAW_FRAMEBUFFER, gl.READ_FRAMEBUFFER);
+
+ // attach different textures as color attachment to read and draw framebuffer respectively,
+ // then detach these attachments.
+ var fbtex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, fbtex1);
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RG8, canvas.width, canvas.height, 0, gl.RG, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex1, 0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.READ_FRAMEBUFFER, ' +
+ 'gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ' +
+ 'gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)', '0');
+
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.getFramebufferAttachmentParameter(
+ gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on read framebuffer with no attachment.");
+ gl.getFramebufferAttachmentParameter(
+ gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on draw framebuffer.");
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.getFramebufferAttachmentParameter(
+ gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on draw framebuffer with no attachment.");
+
+ // attach/detach a renderbuffer to one framebuffer binding point,
+ // while no attachment to the other binding point.
+ function attachAndDetachRenderbuffer(targetA, targetB) {
+ gl.framebufferRenderbuffer(targetA, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attaching a renderbuffer to a read/draw framebuffer.");
+ gl.getFramebufferAttachmentParameter(
+ targetA, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on read/draw framebuffer.");
+ gl.getFramebufferAttachmentParameter(
+ targetB, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " +
+ "on read/draw framebuffer with no attachment.");
+ gl.framebufferRenderbuffer(targetA, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a renderbuffer from a read/draw framebuffer.");
+ }
+
+ var readFBWithRenderbuffer = gl.createFramebuffer();
+ var drawFBWithRenderbuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFBWithRenderbuffer);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFBWithRenderbuffer);
+ attachAndDetachRenderbuffer(gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER);
+ attachAndDetachRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.READ_FRAMEBUFFER);
+
+ // attach different renderbuffers to read and draw framebuffer respectively,
+ // then detach these attachments.
+ var depthRB = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthRB);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, canvas.width, canvas.height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "allocating renderbuffer storage of a newly created renderbuffer.");
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRB);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.READ_FRAMEBUFFER, ' +
+ 'gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE)');
+ gl.getFramebufferAttachmentParameter(
+ gl.READ_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_DEPTH_SIZE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) " +
+ "on read framebuffer without depth attachment.");
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, ' +
+ 'gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)');
+ gl.getFramebufferAttachmentParameter(
+ gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_RED_SIZE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) " +
+ "on draw framebuffer without color attachment.");
+
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.getFramebufferAttachmentParameter(
+ gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_RED_SIZE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) " +
+ "on read framebuffer with no attachment.");
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, ' +
+ 'gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)');
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
+ gl.getFramebufferAttachmentParameter(
+ gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_DEPTH_SIZE);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) " +
+ "on draw framebuffer with no attachment.");
+
+ // binding read/draw framebuffer to default framebuffer
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind read framebuffer to default (null) framebuffer.");
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind draw framebuffer to default (null) framebuffer.");
+}
+
+description("This tests framebuffer/renderbuffer-related functions");
+
+var canvas = document.getElementById("canvas");
+shouldBeNonNull("gl = wtu.create3DContext(canvas, undefined, 2)");
+
+testFramebufferRenderbuffer();
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html
new file mode 100644
index 0000000000..0e435d6a2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html
@@ -0,0 +1,144 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL FramebufferTextureLayer Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+var canvas = document.getElementById("canvas");
+
+function numLevelsFromSize(size) {
+ var levels = 0;
+ while ((size >> levels) > 0) {
+ ++levels;
+ }
+ return levels;
+}
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (expected.indexOf(actual) < 0) {
+ var msg = "checkFramebufferStatus expects [";
+ for (var index = 0; index < expected.length; ++index) {
+ msg += wtu.glEnumToString(gl, expected[index]);
+ if (index + 1 < expected.length)
+ msg += ", ";
+ }
+ msg += "], was " + wtu.glEnumToString(gl, actual);
+ testFailed(msg);
+ } else {
+ var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
+ " as expected";
+ testPassed(msg);
+ }
+}
+
+function testFramebufferTextureLayer() {
+ debug("");
+ debug("Checking FramebufferTextureLayer stuff.");
+
+ var tex3d = gl.createTexture();
+ var fb = gl.createFramebuffer();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texImage3D(gl.TEXTURE_3D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ 1, // width
+ 1, // height
+ 1, // depth
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ new Uint8Array([0xff, 0x00, 0x00, 0x00])); // data
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "attaching a texture to default framebuffer should generate INVALID_OPERATION.");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "attaching a texture to a framebuffer should succeed.");
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "detaching a texture from a framebuffer should succeed.");
+
+ var maxTexSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);
+ var maxLevels = numLevelsFromSize(maxTexSize);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, maxLevels - 1, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling framebufferTextureLayer with an appropriate mipmap level should succeed.");
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, maxLevels, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling framebufferTextureLayer with a mipmap level out of range should generate INVALID_VALUE.");
+
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, -1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling framebufferTextureLayer with a negative texture layer should generate INVALID_VALUE.");
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, maxTexSize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling framebufferTextureLayer with a texture layer out of range should generate INVALID_VALUE.");
+
+ var tex2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2d);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2d, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "attaching a 2d texture to a framebuffer should generate INVALID_OPERATION.");
+
+ var texDepthStencil = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, texDepthStencil);
+ var fbDepthStencil = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbDepthStencil);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY,
+ 0, // level
+ gl.DEPTH24_STENCIL8, // internalFormat
+ 1, // width
+ 1, // height
+ 1, // depth
+ 0, // border
+ gl.DEPTH_STENCIL, // format
+ gl.UNSIGNED_INT_24_8, // type
+ new Uint32Array([0])); // data
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, texDepthStencil, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "attaching a depth_stencil texture to a framebuffer should succeed.");
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ // Clean up
+ gl.deleteTexture(tex3d);
+ gl.deleteTexture(texDepthStencil);
+ gl.deleteTexture(tex2d);
+ gl.deleteFramebuffer(fb);
+ gl.deleteFramebuffer(fbDepthStencil);
+}
+
+description("This tests framebufferTextureLayer.");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
+
+testFramebufferTextureLayer();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html
new file mode 100644
index 0000000000..426148cf5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html
@@ -0,0 +1,230 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Invalidate Framebuffer Against WebGL 2</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script>
+"use strict";
+description("This tests invalidateFramebuffer and invalidateSubFramebuffer");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, { depth : true, stencil : false }, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("invalidate framebuffer.");
+
+ gl.clearColor(0, 0, 0, 0);
+
+ // setup framebuffer with depth attachment and multi-sampled color attachment
+ var fb_m = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb_m);
+
+ var rb_m = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb_m);
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb_m);
+ // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the attached renderbuffer
+ invalidateIncompleteAttachment(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.RGBA8, canvas.width, canvas.height);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no errors after attaching a multi-sampled renderbuffer to fbo.");
+
+ var rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
+ // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the attached renderbuffer
+ invalidateIncompleteAttachment(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.DEPTH_COMPONENT16, canvas.width, canvas.height);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no errors after attaching a renderbuffer to fbo.");
+
+ // in real world case, after some drawing, we can invalidate the depth attachment of the bound fbo
+ invalidation(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.STENCIL_ATTACHMENT);
+
+ // set up framebuffer to blit to and read back from
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ var buffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, canvas.width, canvas.height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no errors after attaching a renderbuffer to fbo.");
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb_m);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
+ gl.blitFramebuffer(0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no errors after bliting framebuffer.");
+
+ // invalidate the multi-sampled color attachment of the bound read framebuffer after blitFramebuffer.
+ invalidation(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.DEPTH_ATTACHMENT);
+
+ var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ gl.invalidateSubFramebuffer(gl.READ_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0 + maxColorAttachments], 5, 5, 10, 10);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM],
+ "calling invalidateSubFramebuffer to invalidate a COLOR_ATTACHMENT that exceeds MAX_COLOR_ATTACHMENT should generate INVALID_ENUM or INVALID_OPERATION.");
+ gl.invalidateFramebuffer(gl.READ_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0 + maxColorAttachments]);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM],
+ "calling invalidateFramebuffer to invalidate a COLOR_ATTACHMENT that exceeds MAX_COLOR_ATTACHMENT should generate INVALID_ENUM or INVALID_OPERATION.");
+
+ // invalidate the default framebuffer
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ invalidation(gl.FRAMEBUFFER, gl.DEPTH, gl.STENCIL);
+
+ gl.deleteFramebuffer(fb_m);
+ gl.deleteRenderbuffer(rb_m);
+ gl.deleteRenderbuffer(rb);
+ gl.deleteFramebuffer(fb);
+ gl.deleteRenderbuffer(buffer);
+
+ testInvalidateRGBThenDraw();
+ testInvalidateWithBlend();
+}
+
+function invalidation(target, valid_attachment, invalid_attachment) {
+ gl.invalidateSubFramebuffer(target, [invalid_attachment], 5, 5, 10, 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateSubFramebuffer to invalidate a specified attachment that does not exist will be ignored. There should be no errors.");
+ gl.invalidateSubFramebuffer(target, [valid_attachment], 5, 5, 10, 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateSubFramebuffer should succeed.");
+
+ gl.invalidateSubFramebuffer(target, [valid_attachment], 5, 5, -5, -5);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "calling invalidateSubFramebuffer should generate INVALID_VALUE if width < 0 or height < 0.");
+
+ gl.invalidateSubFramebuffer(target, [valid_attachment], -5, -5, 10, 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateSubFramebuffer should succeed, even the invalidated pixels may be outside of the framebuffer allocated to current context. These pixels are ignored.");
+ gl.invalidateSubFramebuffer(target, [valid_attachment], 5, 5, 20, 20);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateSubFramebuffer should succeed, even the invalidated pixels may be outside of the framebuffer allocated to current context. These pixels are ignored.");
+
+ gl.invalidateFramebuffer(target, [invalid_attachment]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateFramebuffer to invalidate a specified attachment that does not exist will be ignored. There should be no errors.");
+ gl.invalidateFramebuffer(target, [valid_attachment]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateFramebuffer should succeed.");
+}
+
+function invalidateIncompleteAttachment(target, incomplete_attachment) {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)",
+ "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ gl.invalidateSubFramebuffer(target, [incomplete_attachment], 5, 5, 10, 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateSubFramebuffer to invalidate an incomplete attachment will be ignored. There should be no errors");
+ gl.invalidateFramebuffer(target, [incomplete_attachment]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateFramebuffer to invalidate an incomplete attachment will be ignored. There should be no errors.");
+}
+
+function testInvalidateRGBThenDraw() {
+ const program = wtu.setupColorQuad(gl);
+
+ const texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+
+ const fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE);
+
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Verify that clearing alpha is ineffective on an RGB format.
+ const black = [0, 0, 0, 255];
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, black, `should be black`);
+
+ // Invalidate the framebuffer contents.
+ gl.invalidateFramebuffer(gl.FRAMEBUFFER, [gl.COLOR_ATTACHMENT0]);
+
+ // Without an explicit clear, draw blue and make sure alpha is unaffected. If RGB is emulated
+ // with RGBA, the previous invalidate shouldn't affect the alpha value.
+ wtu.drawFloatColorQuad(gl, [0, 0, 1, 1]);
+ const blue = [0, 0, 255, 255];
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, blue, `should be blue`);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteProgram(program);
+}
+
+function testInvalidateWithBlend() {
+ // Create the framebuffer that will be invalidated
+ const renderTarget = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, renderTarget);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ const drawFBO = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFBO);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, renderTarget, 0);
+
+ // Clear the framebuffer and invalidate it.
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.invalidateFramebuffer(gl.DRAW_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0]);
+
+ // Upload data to it
+ const cyan = new Uint8Array([0, 255, 255, 255]);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, cyan);
+
+ // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, drawFBO);
+
+ const program = wtu.setupColorQuad(gl);
+
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ wtu.drawFloatColorQuad(gl, [1, 0, 0, 0.5]);
+ const expected = [127, 127, 127, 191];
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, expected, `should be ${expected}`, 1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling invalidateFramebuffer and then uploading data to texture in framebuffer. There should be no errors");
+
+ gl.deleteTexture(renderTarget);
+ gl.deleteFramebuffer(drawFBO);
+ gl.deleteProgram(program);
+ gl.disable(gl.BLEND);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-draws-between-blits.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-draws-between-blits.html
new file mode 100644
index 0000000000..bc4ea25a95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-draws-between-blits.html
@@ -0,0 +1,207 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="128" height="64" style="width: 32px; height: 32px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description(' Test multisample with blitting between draws');
+
+const gl = wtu.create3DContext("canvas", null, 2);
+const w = 128;
+const h = 64;
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ gl.viewport(0, 0, w, h);
+ runTest(gl, 4);
+}
+
+function runTest(gl, sampleCount) {
+ const vs = `#version 300 es
+
+ layout(location = 0) in vec4 position;
+ uniform mat4 mat;
+
+ void main() {
+ gl_Position = mat * position;
+ }
+ `;
+
+ const fs = `#version 300 es
+ precision mediump float;
+ uniform vec4 color;
+ out vec4 outColor;
+ void main() {
+ outColor = color;
+ }
+ `;
+
+ const texVS = `#version 300 es
+
+ layout(location = 0) in vec4 position;
+ out vec2 texcoord;
+ uniform mat4 mat;
+
+ void main() {
+ gl_Position = mat * position;
+ texcoord = position.xy;
+ }
+ `;
+
+ const texFS = `#version 300 es
+ precision mediump float;
+ in vec2 texcoord;
+ uniform sampler2D tex;
+ out vec4 outColor;
+ void main() {
+ outColor = texture(tex, texcoord);
+ }
+ `;
+
+ const msRB = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, msRB);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, w, h);
+
+ const msFB = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, msFB);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msRB);
+
+ const dTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, dTex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, w, h);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+ const dFB = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dFB);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, dTex, 0);
+
+ const positionLoc = 0; // hard coded in shaders so they match
+ const buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0, 0,
+ 1, 0,
+ 0, 1,
+ 0, 1,
+ 1, 0,
+ 1, 1,
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ const program = wtu.setupProgram(gl, [vs, fs]);
+ const texProgram = wtu.setupProgram(gl, [texVS, texFS]);
+
+ const colorLoc = gl.getUniformLocation(program, 'color');
+ const matLoc = gl.getUniformLocation(program, 'mat');
+ const texMatLoc = gl.getUniformLocation(texProgram, 'mat');
+
+ gl.useProgram(program);
+
+ const drawAndResolve = (color, mat) => {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, msFB);
+ gl.uniform4fv(colorLoc, color);
+ gl.uniformMatrix4fv(matLoc, false, mat);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dFB);
+ gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ };
+
+ const check = (x, y, w, h, expected, msg) => {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, dFB);
+ const tolerance = 2; // For multisampling resolution differences between GPUs
+ wtu.checkCanvasRect(gl, x, y, w, h, expected, msg, tolerance);
+ };
+
+ const f32Red = [1, 0, 0, 1];
+ const f32Green = [0, 1, 0, 1];
+ const f32Gray = [0.5, 0.5, 0.5, 1];
+
+ const u8Red = [255, 0, 0, 255];
+ const u8Green = [ 0, 255, 0, 255];
+ const u8LightRed = [255, 128, 128, 255];
+ const u8LightGreen = [128, 255, 128, 255];
+
+ debug('fill with red');
+ drawAndResolve(f32Red, [
+ 2, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ -1, -1, 0, 1,
+ ]);
+ check(0, 0, w, h, u8Red, 'whole thing');
+
+ debug('draw right in green');
+ drawAndResolve(f32Green, [
+ 1, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ 0, -1, 0, 1,
+ ]);
+ check(0, 0, w / 2, h, u8Red, 'left');
+ check(w / 2, 0, w / 2, h, u8Green, 'right');
+
+ debug('draw middle in gray with blending');
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ONE);
+ drawAndResolve(f32Gray, [
+ 1, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ -0.5, -1, 0, 1,
+ ]);
+ gl.disable(gl.BLEND);
+
+ /*
+ expected
+ +-----+-------+---------+--------+
+ | red | ltRed | ltGreen | green |
+ +-----+-------+---------+--------+
+ 0,0
+ */
+
+ check(0, 0, w / 4, h , u8Red, 'left edge')
+ check(w * 3 / 4, 0, w / 4, h, u8Green, 'right edge');
+ check(w / 4, 0, w / 4, h, u8LightRed, 'left of center');
+ check(w / 2, 0, w / 4, h, u8LightGreen, 'right of center');
+
+ // show it
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.useProgram(texProgram);
+ gl.uniformMatrix4fv(texMatLoc, false, [
+ 2, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 1, 0,
+ -1, -1, 0, 1,
+ ]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ gl.deleteRenderbuffer(msRB);
+ gl.deleteTexture(dTex);
+ gl.deleteFramebuffer(msFB);
+ gl.deleteFramebuffer(dFB);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html
new file mode 100644
index 0000000000..2e04385f28
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="32" height="32" style="width: 32px; height: 32px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description(' Test multisample with sample number from 1 to max sample number which also includes the samples that may not be in the supported sample list');
+
+var gl = wtu.create3DContext("canvas", null, 2);
+var size = 32;
+var program;
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ program = wtu.setupColorQuad(gl);
+ gl.viewport(0, 0, size, size);
+ var supportedSampleCountArray = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES);
+ var iterationCount = supportedSampleCountArray[0] + 1;
+ for (var i = 1; i < iterationCount; i++)
+ {
+ runTest(gl, i, false);
+ runTest(gl, i, true);
+ }
+}
+
+function runTest(gl, sampleCount, isInverted) {
+ // Setup multi-sample RBO
+ var msColorRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, msColorRbo);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, sampleCount, gl.RGBA8, size, size);
+
+ // Setup multi-sample FBO.
+ var msFbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, msFbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msColorRbo);
+
+ // Setup resolve color RBO.
+ var resolveColorRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, resolveColorRbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, size, size);
+ // Setup resolve FBO
+ var resolveFbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resolveColorRbo);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, msFbo);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.enable(gl.SAMPLE_COVERAGE);
+ var coverageValue = isInverted ? 0.0 : 1.0;
+ gl.sampleCoverage(coverageValue, isInverted);
+
+ var quadColor = [1.0, 0.0, 0.0, 1.0];
+ gl.useProgram(program);
+ wtu.drawFloatColorQuad(gl, quadColor);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFbo);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo);
+ wtu.checkCanvasRect(gl, 0, 0, size, size, [255, 0, 0, 255],
+ "User buffer has been rendered to red with sample = "
+ + sampleCount + ", coverageValue = " + coverageValue
+ + " and isInverted = " + isInverted, 3);
+
+ gl.disable(gl.SAMPLE_COVERAGE);
+ gl.deleteRenderbuffer(msColorRbo);
+ gl.deleteRenderbuffer(resolveColorRbo);
+ gl.deleteFramebuffer(msFbo);
+ gl.deleteFramebuffer(resolveFbo);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html
new file mode 100644
index 0000000000..7bd87890e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html
@@ -0,0 +1,180 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description('Verify multisampled depth renderbuffers are initialized to 1.0 before being read in WebGL');
+
+var gl = wtu.create3DContext("testbed", null, 2);
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ // Set the clear color to green. It should never show up.
+ gl.clearColor(0, 1, 0, 1);
+
+ debug("Test renderbufferStorageMultisample with webgl1's DEPTH_STENCIL.");
+ {
+ const rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ wtu.shouldGenerateGLError(gl, 0,
+ "gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 0, gl.DEPTH_STENCIL, 1, 1)");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 1, gl.DEPTH_STENCIL, 1, 1)");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, gl.DEPTH_STENCIL, 1, 1)");
+ gl.deleteRenderbuffer(rb);
+ }
+
+ let c = gl.canvas;
+ var maxSamples = gl.getInternalformatParameter(
+ gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES)[0];
+ for (let i = 0; i < 2; ++i) {
+ // Non-multisampled tests
+ runTest(gl, {alloc1: {w: c.width, h: c.height, s: 0}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height, s: 0}});
+ // Multisampled tests
+ runTest(gl, {alloc1: {w: c.width, h: c.height, s: maxSamples}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+
+ // Tests for initially allocating at the wrong size.
+ // This is caused by a Qualcomm driver bug: http://crbug.com/696126
+ runTest(gl, {alloc1: {w: 5, h: 5, s: maxSamples}, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+ }
+
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[0, 1, 0, 1]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+}
+
+function runTest(gl, params) {
+ debug("");
+ debug("Test for depth buffer: " + JSON.stringify(params));
+ let resolve = params.alloc2 ? params.alloc2 : params.alloc1;
+ gl.viewport(0, 0, resolve.w, resolve.h);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 0, 0, 0],
+ "internal buffers have been initialized to 0");
+
+ gl.disable(gl.DEPTH_TEST);
+
+ // fill the back buffer so we know that reading below happens from
+ // the renderbuffer.
+ gl.clearDepth(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // Set up (color+depth) non-multisampled buffer to blit to and read back from.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var buffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, resolve.w, resolve.h);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);
+ var depthBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, resolve.w, resolve.h);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ gl.clearDepth(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 255, 0, 255],
+ "user buffer has been cleared to green");
+
+ // Set up (depth-only) multisampled buffer to test.
+ var fbo_m = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_m);
+ var buffer_m = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer_m);
+
+ if (params.alloc1) {
+ allocStorage(params.alloc1.w, params.alloc1.h, params.alloc1.s);
+ }
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, buffer_m);
+ if (params.alloc2) {
+ if (params.alloc1) {
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ // Clear the FBO in order to make sure framebufferRenderbuffer is
+ // committed. (In Firefox, framebufferRenderbuffer is deferred, so this
+ // is needed to trigger the bug.)
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ }
+ allocStorage(params.alloc2.w, params.alloc2.h, params.alloc2.s);
+ }
+
+ function allocStorage(width, height, samples) {
+ gl.renderbufferStorageMultisample(
+ gl.RENDERBUFFER, samples, gl.DEPTH_COMPONENT16, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no error after renderbufferStorageMultisample(DEPTH_COMPONENT16).");
+ }
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ // Blit from multisampled buffer to non-multisampled buffer.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_m);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo);
+ gl.clearDepth(0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ // Blit depth from fbo_m (should be default value of 1.0) to fbo (should be 0.0).
+ gl.blitFramebuffer(0, 0, resolve.w, resolve.h,
+ 0, 0, resolve.w, resolve.h,
+ gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ // fbo depth should now be 1.0.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ // Draw a blue quad (at clip z = 0.0, so depth = 0.5) (should pass the depth test: 0.5 < 1.0)
+ gl.depthFunc(gl.LESS);
+ gl.enable(gl.DEPTH_TEST);
+ wtu.setupColorQuad(gl);
+ wtu.setFloatDrawColor(gl, [0, 0, 1, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 0, 255, 255]);
+
+ gl.deleteFramebuffer(fbo_m);
+ gl.deleteRenderbuffer(buffer_m);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(buffer);
+
+ gl.canvas.width += 1;
+ gl.canvas.height += 1;
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html
new file mode 100644
index 0000000000..0b27da661d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html
@@ -0,0 +1,149 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description('Verify multisampled renderbuffers are initialized to 0 before being read in WebGL');
+
+var gl = wtu.create3DContext("testbed", null, 2);
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ // Set the clear color to green. It should never show up.
+ gl.clearColor(0, 1, 0, 1);
+
+ let c = gl.canvas;
+ var maxSamples = gl.getInternalformatParameter(
+ gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES)[0];
+ for (let i = 0; i < 2; ++i) {
+ runTest(gl, {alloc1: {w: c.width, h: c.height, s: maxSamples}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+
+ // Tests for initially allocating at the wrong size.
+ // This is caused by a Qualcomm driver bug: http://crbug.com/696126
+ runTest(gl, {alloc1: {w: 5, h: 5, s: maxSamples}, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+ runTest(gl, {alloc1: {w: 5, h: 5, s: maxSamples}, alloc2: {w: c.width, h: c.height, s: 0}});
+ runTest(gl, {alloc1: {w: 5, h: 5, s: 0}, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+ }
+
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[0, 1, 0, 1]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+}
+
+function runTest(gl, params) {
+ debug("Test for color buffer: " + JSON.stringify(params));
+ let resolve = params.alloc2 ? params.alloc2 : params.alloc1;
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 0, 0, 0],
+ "internal buffers have been initialized to 0");
+
+ // fill the back buffer so we know that reading below happens from
+ // the renderbuffer.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Set up non-multisampled buffer to blit to and read back from.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var buffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, resolve.w, resolve.h);
+ attachBuffer(buffer);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)",
+ "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 255, 0, 255],
+ "user buffer has been cleared to green");
+
+ // Set up multisampled buffer to test.
+ var fbo_m = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_m);
+ var buffer_m = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer_m);
+
+ if (params.alloc1) {
+ allocStorage(params.alloc1.w, params.alloc1.h, params.alloc1.s);
+ }
+ attachBuffer(buffer_m);
+ if (params.alloc2) {
+ if (params.alloc1) {
+ // Clear the FBO in order to make sure framebufferRenderbuffer is
+ // committed. (In Firefox, framebufferRenderbuffer is deferred, so
+ // this is needed to trigger the bug.)
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+ allocStorage(params.alloc2.w, params.alloc2.h, params.alloc2.s);
+ }
+
+ function allocStorage(width, height, samples) {
+ gl.renderbufferStorageMultisample(
+ gl.RENDERBUFFER, samples, gl.RGBA8, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no error after renderbufferStorageMultisample(RGBA8).");
+ }
+
+ function attachBuffer(buffer) {
+ gl.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no error after framebufferRenderbuffer.");
+ }
+
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)",
+ "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ // Blit from multisampled buffer to non-multisampled buffer.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_m);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo);
+ // Blit color from fbo_m (should be black) to fbo (should be green)
+ gl.blitFramebuffer(0, 0, resolve.w, resolve.h,
+ 0, 0, resolve.w, resolve.h,
+ gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 0, 0, 0],
+ "user buffer has been initialized to 0");
+
+ gl.deleteFramebuffer(fbo_m);
+ gl.deleteRenderbuffer(buffer_m);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(buffer);
+
+ // this clear should not matter we are about to resize
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.canvas.width += 1;
+ gl.canvas.height += 1;
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-stencil-renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-stencil-renderbuffer-initialization.html
new file mode 100644
index 0000000000..cb351454d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-stencil-renderbuffer-initialization.html
@@ -0,0 +1,167 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description('Verify multisampled stencil renderbuffers are initialized to 0 before being read in WebGL');
+
+var gl = wtu.create3DContext("testbed", null, 2);
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ // Set the clear color to green. It should never show up.
+ gl.clearColor(0, 1, 0, 1);
+ gl.disable(gl.DEPTH_TEST);
+
+ let c = gl.canvas;
+ var maxSamples = gl.getInternalformatParameter(
+ gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES)[0];
+ for (let i = 0; i < 2; ++i) {
+ // Non-multisampled tests
+ runTest(gl, {alloc1: {w: c.width, h: c.height, s: 0}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height, s: 0}});
+ // Multisampled tests
+ runTest(gl, {alloc1: {w: c.width, h: c.height, s: maxSamples}, alloc2: null});
+ runTest(gl, {alloc1: null, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+
+ // Tests for initially allocating at the wrong size.
+ // This is caused by a Qualcomm driver bug: http://crbug.com/696126
+ runTest(gl, {alloc1: {w: 5, h: 5, s: maxSamples}, alloc2: {w: c.width, h: c.height, s: maxSamples}});
+ }
+
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[0, 1, 0, 1]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+}
+
+function runTest(gl, params) {
+ debug("Test for stencil buffer: " + JSON.stringify(params));
+ let resolve = params.alloc2 ? params.alloc2 : params.alloc1;
+ gl.viewport(0, 0, resolve.w, resolve.h);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 0, 0, 0],
+ "internal buffers have been initialized to 0");
+
+ gl.disable(gl.STENCIL_TEST);
+
+ // fill the back buffer so we know that reading below happens from
+ // the renderbuffer.
+ gl.clearStencil(2);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Set up (color+stencil) non-multisampled buffer to blit to and read back from.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var buffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, resolve.w, resolve.h);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);
+ var stencilBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, resolve.w, resolve.h);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilBuffer);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ gl.clearStencil(2);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 255, 0, 255],
+ "user buffer has been cleared to green");
+
+ // Set up (stencil-only) multisampled buffer to test.
+ var fbo_m = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_m);
+ var buffer_m = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, buffer_m);
+
+ if (params.alloc1) {
+ allocStorage(params.alloc1.w, params.alloc1.h, params.alloc1.s);
+ }
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, buffer_m);
+ if (params.alloc2) {
+ if (params.alloc1) {
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ // Clear the FBO in order to make sure framebufferRenderbuffer is
+ // committed. (In Firefox, framebufferRenderbuffer is deferred, so this
+ // is needed to trigger the bug.)
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ }
+ allocStorage(params.alloc2.w, params.alloc2.h, params.alloc2.s);
+ }
+
+ function allocStorage(width, height, samples) {
+ gl.renderbufferStorageMultisample(
+ gl.RENDERBUFFER, samples, gl.STENCIL_INDEX8, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "should be no error after renderbufferStorageMultisample(STENCIL_INDEX8).");
+ }
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("Skip: framebuffer is allowed to be incomplete.");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ // Blit from multisampled buffer to non-multisampled buffer.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_m);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo);
+ gl.clearStencil(2);
+ gl.clear(gl.STENCIL_BUFFER_BIT);
+ // Blit stencil from fbo_m (should be default value of 0) to fbo (should be 2).
+ gl.blitFramebuffer(0, 0, resolve.w, resolve.h,
+ 0, 0, resolve.w, resolve.h,
+ gl.STENCIL_BUFFER_BIT, gl.NEAREST);
+ // fbo stencil should now be 0.
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ // Draw a blue quad (with stencil = 1) (should pass the stencil test: 1 > 0)
+ gl.stencilFunc(gl.GREATER, 1, 0xffffffff);
+ gl.enable(gl.STENCIL_TEST);
+ wtu.setupColorQuad(gl);
+ wtu.setFloatDrawColor(gl, [0, 0, 1, 1]);
+ wtu.drawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, resolve.w, resolve.h,
+ [0, 0, 255, 255]);
+
+ gl.deleteFramebuffer(fbo_m);
+ gl.deleteRenderbuffer(buffer_m);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(buffer);
+
+ gl.canvas.width += 1;
+ gl.canvas.height += 1;
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors');
+ debug('');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html
new file mode 100644
index 0000000000..56bfd656a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html
@@ -0,0 +1,174 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test readBuffer Against WebGL 2</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script>
+"use strict";
+description("This tests reading from fbo");
+
+var clearDrawingbuffer = function(color) {
+ gl.clearColor(color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+}
+
+var validateReadingFromFramebuffer = function(color, expected, msg) {
+ var pixels = new Uint8Array(1 * 1 * 4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ wtu.glErrorShouldBe(gl, expected, msg);
+ if (expected == gl.NO_ERROR)
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, color,
+ "the color should be [" + color + "]");
+}
+
+var setupRenderbuffer = function(attachment) {
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, canvas.width, canvas.height);
+ return renderbuffer;
+}
+
+var testReadBufferOnDefaultFB = function() {
+ gl.readBuffer(gl.NONE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling readBuffer with GL_NONE on the default framebuffer should succeed.");
+ var pixels = new Uint8Array(1 * 1 * 4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "should generate INVALID_OPERATION when reading from framebuffer and read buffer is GL_NONE.");
+ gl.readBuffer(gl.BACK);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling readBuffer with GL_BACK on the default framebuffer should succeed.");
+
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "calling readBuffer with GL_COLOR_ATTACHMENT0 on the default framebuffer should generate INVALID_OPERATION.");
+}
+
+var testReadBufferOnFBO = function() {
+ gl.readBuffer(gl.BACK);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "calling readBuffer with GL_BACK on fbo should generate INVALID_OPERATION.");
+
+ gl.readBuffer(gl.NONE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling readBuffer with GL_NONE on fbo should succeed.");
+ var pixels = new Uint8Array(1 * 1 * 4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "should generate INVALID_OPERATION when reading from framebuffer and read buffer is GL_NONE.");
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling readBuffer with GL_COLOR_ATTACHMENT0 on fbo should succeed.");
+
+ var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ gl.readBuffer(gl.COLOR_ATTACHMENT0 + maxColorAttachments);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "calling readBuffer with GL_COLOR_ATTACHMENTi that exceeds MAX_COLOR_ATTACHMENT on fbo should generate INVALID_OPERATION.");
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "calling readBuffer with GL_COLOR_ATTACHMENT1 on the fbo should succeed.");
+ shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT1');
+}
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking reading from framebuffer.");
+
+ // Test on the default framebuffer. Read buffer is GL_BACK by default.
+ var backColor = [0, 0, 0, 255];
+ clearDrawingbuffer(backColor);
+ validateReadingFromFramebuffer(backColor, gl.NO_ERROR,
+ "should be no errors when reading from GL_BACK on the default framebuffer.");
+
+ shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.BACK');
+ testReadBufferOnDefaultFB();
+
+ // Test on fbo. Read buffer is GL_COLOR_ATTACHMENT0 by default
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ var colorbuffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0);
+ var red = [255, 0, 0, 255];
+ clearDrawingbuffer(red);
+ validateReadingFromFramebuffer(red, gl.NO_ERROR,
+ "should be no errors when reading from GL_COLOR_ATTACHMENT0 on fbo.");
+
+ shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT0');
+ testReadBufferOnFBO();
+
+ // Test on user defined read buffer (GL_COLOR_ATTACHMENT1) with or without corresponding image on fbo.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ var colorbuffer1 = setupRenderbuffer(gl.COLOR_ATTACHMENT1);
+ var green = [0, 255, 0, 255];
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ clearDrawingbuffer(green);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after setup and clear render buffer");
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ validateReadingFromFramebuffer(green, gl.NO_ERROR,
+ "should be no errors when reading from GL_COLOR_ATTACHMENT1 on fbo.");
+ shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT1');
+ // Need to reset draw buffers, otherwise it triggers a mac driver bug.
+ // We add a separate test for that bug: conformance2/rendering/framebuffer-completeness-unaffected.html
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, null)
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ validateReadingFromFramebuffer(null, gl.INVALID_OPERATION,
+ "should generate INVALID_OPERATION when reading from GL_COLOR_ATTACHMENT1 but this attachment has no image currently.");
+
+ // switch to another fbo, read buffer is GL_COLOR_ATTACHMENT0, not GL_COLOR_ATTACHMENT1
+ var fb1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ var buffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0);
+ shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT0');
+ var blue = [0, 0, 255, 255];
+ clearDrawingbuffer(blue);
+ validateReadingFromFramebuffer(blue, gl.NO_ERROR,
+ "should be no errors when reading from GL_COLOR_ATTACHMENT0 on another fbo.");
+
+ // switch from fbo to default fb, read buffer will switch to GL_BACK from GL_COLOR_ATTACHMENT0
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.BACK');
+ validateReadingFromFramebuffer(backColor, gl.NO_ERROR,
+ "should be no errors when reading from GL_BACK on the default framebuffer.");
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteRenderbuffer(colorbuffer);
+ gl.deleteRenderbuffer(colorbuffer1);
+ gl.deleteFramebuffer(fb1);
+ gl.deleteRenderbuffer(buffer);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/00_test_list.txt
new file mode 100644
index 0000000000..92ce232ee2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/00_test_list.txt
@@ -0,0 +1,51 @@
+attrib-type-match.html
+blitframebuffer-filter-outofbounds.html
+blitframebuffer-filter-srgb.html
+blitframebuffer-multisampled-readbuffer.html
+--min-version 2.0.1 blitframebuffer-outside-readbuffer.html
+--min-version 2.0.1 blitframebuffer-r11f-g11f-b10f.html
+--min-version 2.0.1 blitframebuffer-resolve-to-back-buffer.html
+blitframebuffer-scissor-enabled.html
+blitframebuffer-size-overflow.html
+--min-version 2.0.1 blitframebuffer-srgb-and-linear-drawbuffers.html
+--min-version 2.0.1 blitframebuffer-stencil-only.html
+blitframebuffer-test.html
+--min-version 2.0.1 blitframebuffer-unaffected-by-colormask.html
+--min-version 2.0.1 builtin-vert-attribs.html
+canvas-resizing-with-pbo-bound.html
+--min-version 2.0.1 clearbuffer-sub-source.html
+--min-version 2.0.1 clearbufferfv-with-alpha-false.html
+clear-func-buffer-type-match.html
+--min-version 2.0.1 clear-srgb-color-buffer.html
+--min-version 2.0.1 clipping-wide-points.html
+--min-version 2.0.1 depth-stencil-feedback-loop.html
+draw-buffers.html
+--min-version 2.0.1 draw-buffers-dirty-state-bug.html
+--min-version 2.0.1 draw-buffers-driver-hang.html
+--min-version 2.0.1 draw-buffers-sparse-output-locations.html
+--min-version 2.0.1 draw-with-integer-texture-base-level.html
+element-index-uint.html
+--min-version 2.0.1 framebuffer-completeness-draw-framebuffer.html
+framebuffer-completeness-unaffected.html
+--min-version 2.0.1 framebuffer-mismatched-attachment-targets.html
+--min-version 2.0.1 framebuffer-render-to-layer.html
+--min-version 2.0.1 framebuffer-render-to-layer-angle-issue.html
+--min-version 2.0.1 framebuffer-texture-changing-base-level.html
+--min-version 2.0.1 framebuffer-texture-level1.html
+--min-version 2.0.1 framebuffer-to-texture.html
+framebuffer-unsupported.html
+--min-version 2.0.1 fs-color-type-mismatch-color-buffer-type.html
+instanced-arrays.html
+--min-version 2.0.1 instanced-rendering-bug.html
+--min-version 2.0.1 instanced-rendering-large-divisor.html
+--min-version 2.0.1 line-rendering-quality.html
+--min-version 2.0.1 multisampling-depth-resolve.html
+--min-version 2.0.1 multisampling-fragment-evaluation.html
+out-of-bounds-index-buffers-after-copying.html
+--min-version 2.0.1 rasterizer-discard-and-implicit-clear.html
+--min-version 2.0.1 read-draw-when-missing-image.html
+rgb-format-support.html
+uniform-block-buffer-size.html
+--min-version 2.0.1 texture-switch-performance.html
+--min-version 2.0.1 vertex-id.html
+--min-version 2.0.1 vertex-id-large-count.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/attrib-type-match.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/attrib-type-match.html
new file mode 100644
index 0000000000..5b1b2884aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/attrib-type-match.html
@@ -0,0 +1,561 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests: Vertex Attribute Type Match</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing instanced draws -->
+<script id="outputVertexShader" type="x-shader/x-vertex">#version 300 es
+in vec4 aPosition;
+in ivec2 aOffsetI;
+in uvec2 aOffsetU;
+in vec4 aColor;
+out vec4 vColor;
+void main() {
+ vColor = aColor;
+ vec2 offset = vec2(float(aOffsetI.x) + float(aOffsetU.x),
+ float(aOffsetI.y) + float(aOffsetU.y));
+ gl_Position = aPosition + vec4(offset, 0.0, 0.0);
+}
+</script>
+
+<script id="outputFragmentShader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+in vec4 vColor;
+out vec4 fragColor;
+void main() {
+ fragColor = vColor;
+}
+</script>
+
+<script id='vshader_inactive_attrib' type='x-shader/x-vertex'>#version 300 es
+in ivec4 p;
+in ivec4 a;
+void main()
+{
+ gl_Position = vec4(p);
+}
+</script>
+<script id='vshader_active_attrib_int' type='x-shader/x-vertex'>#version 300 es
+in ivec4 p;
+in ivec4 a;
+in uvec4 b;
+void main()
+{
+ gl_Position = vec4(p) + vec4(a) + vec4(b);
+}
+</script>
+<script id='vshader_active_attrib_float' type='x-shader/x-vertex'>#version 300 es
+in vec4 p;
+in vec4 a;
+in vec4 c;
+void main()
+{
+ gl_Position = vec4(p) + vec4(a) + vec4(c);
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+void main()
+{
+ oColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+
+<script>
+"use strict";
+description("This test verifies an active vertex attribute's base type has to match the verexAttrib function type.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ testGenericAttribs();
+ runTests();
+}
+
+function testGenericAttribs() {
+ debug("");
+ debug("Test Generic Vertex Attributes for some corner cases");
+
+ var pIndex = 2;
+ var aIndex = 3;
+ var bIndex = 4;
+ var cIndex = 5;
+ var program0 = wtu.setupProgram(gl, ["vshader_inactive_attrib", "fshader"],
+ ['p', 'a'], [pIndex, aIndex]);
+ var program1 = wtu.setupProgram(gl, ["vshader_active_attrib_int", "fshader"],
+ ['p', 'a', 'b'], [pIndex, aIndex, bIndex]);
+ var program2 = wtu.setupProgram(gl, ["vshader_active_attrib_float", "fshader"],
+ ['p', 'a', 'c'], [pIndex, aIndex, cIndex]);
+ if (!program0 || !program1 || !program2) {
+ testFailed("Set up program failed");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ wtu.setupUnitQuad(gl, 0);
+
+ debug("Inactive input in vertex shader");
+ gl.useProgram(program0);
+ gl.vertexAttribI4i(pIndex, 1, 0, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays succeeds: type in shader mismatch default vertex type is valid for inactive attrib");
+
+ gl.vertexAttrib4f(aIndex, 0.0, 1.0, 0.0, 0.0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays succeeds: type in shader mismatch vertexAttrib type is valid for inactive attrib");
+
+ debug("active int/uint inputs in vertex shader");
+ gl.useProgram(program1);
+ gl.vertexAttribI4i(pIndex, 1, 0, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Type mismatch: type in shader mismatch the default type for a vertex attrib");
+ gl.vertexAttribI4i(aIndex, 0, 1, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Type mismatch: type in shader mismatch the default type for a vertex attrib");
+ gl.vertexAttribI4ui(bIndex, 0, 0, 1, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays succeeds");
+
+ debug("active float input in vertex shader");
+ gl.useProgram(program2);
+ gl.vertexAttrib4f(pIndex, 1.0, 0.0, 0.0, 0.0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Type mismatch: generic attrib is valid per context. 'a' is set to int type by previous test case");
+ gl.vertexAttrib4f(aIndex, 0.0, 1.0, 0.0, 0.0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays succeeds: default type of generic attrib is float");
+}
+
+function setupAttribValues(offsetILoc, offsetULoc, colorLoc) {
+ gl.vertexAttribI4i(offsetILoc, -1, -2, 0, 0);
+ gl.vertexAttribI4ui(offsetULoc, 1, 2, 0, 0);
+ gl.vertexAttrib4f(colorLoc, 1.0, 0, 0, 1.0);
+}
+
+function setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetIBuffer);
+ gl.vertexAttribIPointer(offsetILoc, 2, gl.INT, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetUBuffer);
+ gl.vertexAttribIPointer(offsetULoc, 2, gl.UNSIGNED_INT, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+}
+
+function runTests() {
+ debug("");
+ debug("Test vertexAttrib with drawArrays and drawArraysInstanced");
+
+ var instanceCount = 4;
+
+ var positionLoc = 0;
+ var offsetILoc = 2;
+ var offsetULoc = 3;
+ var colorLoc = 4;
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"],
+ ['aPosition', 'aOffsetI', 'aOffsetU','aColor'],
+ [positionLoc, offsetILoc, offsetULoc, colorLoc]);
+ if (!program) {
+ testFailed("Set up program failed");
+ return;
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ wtu.setupUnitQuad(gl, 0);
+
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+
+ debug("int type function on uint type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4i(offsetULoc, 1, 2, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("float type function on uint type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttrib4f(offsetULoc, 1.0, 2.0, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("uint type function on int type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4ui(offsetILoc, 1, 2, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("float type function on int type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttrib4f(offsetILoc, 1.0, 2.0, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("int type function on float type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4i(colorLoc, 1, 0, 0, 1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("uint type function on float type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4ui(colorLoc, 1, 0, 0, 1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("");
+ debug("Test vertexAttrib with drawElements, drawRangeElements, and drawElementsInstanced");
+ wtu.setupIndexedQuad(gl, 1, 0);
+
+ debug("Correct setup");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawRangeElements succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 0, 0, 255]);
+
+ debug("int type function on uint type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4i(offsetULoc, 1, 2, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("float type function on uint type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttrib4f(offsetULoc, 1.0, 2.0, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("uint type function on int type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4ui(offsetILoc, 1, 2, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("float type function on int type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttrib4f(offsetILoc, 1.0, 2.0, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("int type function on float type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4i(colorLoc, 1, 0, 0, 1);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("uint type function on float type attrib");
+ setupAttribValues(offsetILoc, offsetULoc, colorLoc);
+ gl.vertexAttribI4ui(colorLoc, 1, 0, 0, 1);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+
+ var offsetIBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetIBuffer);
+ var offsetI = new Int32Array([-1, -2,
+ -1, -2,
+ -1, -2,
+ -1, -2,
+ -1, -2,
+ -1, -2]);
+ gl.bufferData(gl.ARRAY_BUFFER, offsetI, gl.STATIC_DRAW);
+
+ var offsetUBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetUBuffer);
+ var offsetU = new Uint32Array([1, 2,
+ 1, 2,
+ 1, 2,
+ 1, 2,
+ 1, 2,
+ 1, 2]);
+ gl.bufferData(gl.ARRAY_BUFFER, offsetU, gl.STATIC_DRAW);
+
+ var offsetFBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetFBuffer);
+ var offsetF = new Float32Array([1.0, 2.0,
+ 1.0, 2.0,
+ 1.0, 2.0,
+ 1.0, 2.0,
+ 1.0, 2.0,
+ 1.0, 2.0]);
+ gl.bufferData(gl.ARRAY_BUFFER, offsetF, gl.STATIC_DRAW);
+
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ var colors = new Float32Array([0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0]);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+
+ var colorUBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorUBuffer);
+ var colorsU = new Uint32Array([0, 1, 0, 1,
+ 0, 1, 0, 1,
+ 0, 1, 0, 1,
+ 0, 1, 0, 1,
+ 0, 1, 0, 1,
+ 0, 1, 0, 1]);
+ gl.bufferData(gl.ARRAY_BUFFER, colorsU, gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(offsetILoc);
+ gl.enableVertexAttribArray(offsetULoc);
+ gl.enableVertexAttribArray(colorLoc);
+
+ debug("");
+ debug("Test vertexAttrib{I}Pointer with drawArrays and drawArraysInstanced");
+ wtu.setupUnitQuad(gl, 0);
+
+ debug("Correct setup");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255]);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255]);
+
+ debug("vertexAttribIPointer with int type on uint type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetIBuffer);
+ gl.vertexAttribIPointer(offsetULoc, 2, gl.INT, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribPointer on uint type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetFBuffer);
+ gl.vertexAttribPointer(offsetULoc, 2, gl.FLOAT, false, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("VertexAttribIPointer with uint type on int type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetUBuffer);
+ gl.vertexAttribIPointer(offsetILoc, 2, gl.UNSIGNED_INT, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribPointer on int type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetFBuffer);
+ gl.vertexAttribPointer(offsetILoc, 2, gl.FLOAT, false, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribIPointer with uint type on float type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorUBuffer);
+ gl.vertexAttribIPointer(colorLoc, 4, gl.UNSIGNED_INT, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribIPointer with int type on float type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorUBuffer);
+ gl.vertexAttribIPointer(colorLoc, 4, gl.INT, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("");
+ debug("Test vertexAttrib{I}Pointer with drawElements, drawRangeElements, and drawElementsInstanced");
+ wtu.setupIndexedQuad(gl, 1, 0);
+
+ debug("Correct setup");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up succeeds");
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255]);
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawRangeElements succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255]);
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced succeeds");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255]);
+
+ debug("vertexAttribIPointer with int type on uint type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetIBuffer);
+ gl.vertexAttribIPointer(offsetULoc, 2, gl.INT, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribPointer on uint type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetFBuffer);
+ gl.vertexAttribPointer(offsetULoc, 2, gl.FLOAT, false, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("VertexAttribIPointer with uint type on int type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetUBuffer);
+ gl.vertexAttribIPointer(offsetILoc, 2, gl.UNSIGNED_INT, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribPointer on int type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetFBuffer);
+ gl.vertexAttribPointer(offsetILoc, 2, gl.FLOAT, false, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribIPointer with uint type on float type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorUBuffer);
+ gl.vertexAttribIPointer(colorLoc, 4, gl.UNSIGNED_INT, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+
+ debug("vertexAttribIPointer with int type on float type attrib");
+ setupAttribPointers(offsetILoc, offsetULoc, colorLoc,
+ offsetIBuffer, offsetUBuffer, colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorUBuffer);
+ gl.vertexAttribIPointer(colorLoc, 4, gl.INT, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "type mismatch");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-outofbounds.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-outofbounds.html
new file mode 100644
index 0000000000..f1fda162d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-outofbounds.html
@@ -0,0 +1,172 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer when src/dst region are out-of-bounds.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function checkPixel(color, expectedColor) {
+ var tolerance = 3;
+ return (Math.abs(color[0] - expectedColor[0]) <= tolerance &&
+ Math.abs(color[1] - expectedColor[1]) <= tolerance &&
+ Math.abs(color[2] - expectedColor[2]) <= tolerance &&
+ Math.abs(color[3] - expectedColor[3]) <= tolerance);
+}
+
+function blitframebuffer_filter_outofbounds(readbufferFormat, drawbufferFormat, filter) {
+ debug("");
+ debug("blitting pixels out-of-bounds, read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat) + ", draw buffer format is: " + wtu.glEnumToString(gl, drawbufferFormat) + ", filter is: " + wtu.glEnumToString(gl, filter));
+
+ // Initiate data to read framebuffer
+ var size = 8;
+ var uint_read = new Uint8Array(size * size * 4);
+ var color = 0x20;
+ for (var ii = 0; ii < size * size * 4; ii += 4) {
+ for (var jj = 0; jj < 3; ++jj) {
+ uint_read[ii + jj] = color;
+ }
+ uint_read[ii + 3] = 0xff;
+ }
+
+ // Create read framebuffer and feed data to read buffer
+ // Read buffer may have srgb image
+ var tex_read = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_read);
+ gl.texImage2D(gl.TEXTURE_2D, 0, readbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint_read);
+
+ var fbo_read = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0);
+
+ // Create draw framebuffer. Color in draw buffer is initialized to 0.
+ // Draw buffer may have srgb image
+ var tex_draw = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_draw);
+ gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var fbo_draw = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_draw, 0);
+
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // Blit read framebuffer to the image in draw framebuffer.
+ var tests = [
+ // [srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1]
+
+ { args: [-2, -2, 4, 4, 1, 1, 4, 4], changedDstRect: [2, 2, 4, 4], desc: 'only src region is out-of-bounds, dst region has different width/height as src region.'},
+ { args: [-2, -2, 4, 4, 1, 1, 7, 7], changedDstRect: [3, 3, 7, 7], desc: 'only src region is out-of-bounds, dst region has the same width/height as src region.'},
+ { args: [0, 0, 6, 6, 7, 7, 10, 10], changedDstRect: [7, 7, 8, 8], desc: 'only dst region is out-of-bounds, dst region has different width/height as src region after dst region is clipped to the bounds of draw buffer.'},
+ { args: [0, 0, 6, 6, 4, 4, 10, 10], changedDstRect: [4, 4, 8, 8], desc: 'only dst region is out-of-bounds, dst region has the same width/height as src region after dst region is clipped to the bounds of draw buffer.'},
+ { args: [-2, -2, 4, 4, 7, 7, 10, 10], changedDstRect: [8, 8, 8, 8], desc: 'both src and dst region are out-of-bounds, dst region has different width/height as src region after dst region is clipped to the bounds of draw buffer.'},
+ { args: [-2, -2, 4, 4, 4, 4, 10, 10], changedDstRect: [6, 6, 8, 8], desc: 'both src and dst region are out-of-bounds, dst region has the same width/height as src region after dst region is clipped to the bounds of draw buffer.'},
+ { args: [-2, -2, 4, 4, 2, 2, 10, 10], changedDstRect: [2 + 2/6*8, 2 + 2/6*8, 8, 8], desc: 'both src and dst region are out-of-bounds. There are some dst pixels (x and y are within [4, 8] , and x or y equals to 4) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying outside the real sampling area.'},
+ { args: [-2, -2, 4, 4, 3, 3, 10, 10], changedDstRect: [5, 5, 8, 8], desc: 'both src and dst region are out-of-bounds. There are some dst pixels (x and y are within [4, 7] , and x or y equals to 5) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying inside the real sampling area.'},
+ { args: [-2, -2, 4, 4, 10, 10, 2, 2], changedDstRect: [2, 2, 7, 7], desc: 'both src and dst region are out-of-bounds, and the dst coordinates are reversed. There are some dst pixels (x and y are within [2, 7] , and x or y equals to 7) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying outside the real sampling area.'},
+ { args: [-2, -2, 4, 4, 10, 10, 3, 3], changedDstRect: [3, 3, 8, 8], desc: 'both src and dst region are out-of-bounds, and the dst coordinates are reversed. There are some dst pixels (x and y are within [3, 7] , and x or y equals to 7) whose corresponding src pixels are partially inside and partially outside the read sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying inside the real sampling area.'},
+ ];
+
+ var readbufferHasSRGBImage = (readbufferFormat == gl.SRGB8_ALPHA8);
+ var drawbufferHasSRGBImage = (drawbufferFormat == gl.SRGB8_ALPHA8);
+
+ for (const test of tests) {
+ const args = test.args;
+ const changedDstRect = test.changedDstRect;
+ debug("");
+ debug("Both the read framebuffer and draw framebuffer bounds are [0, 0, 8, 8]");
+ debug(`Blitting from src region [${args.slice(0, 4)}] to dst region [${args.slice(4, 8)}]`);
+ debug(`Expects changed dst region of [${changedDstRect}]`);
+ debug(`Explaination: ${test.desc}`);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindTexture(gl.TEXTURE_2D, tex_draw);
+ gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.blitFramebuffer(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], gl.COLOR_BUFFER_BIT, filter);
+
+ // Read pixels and check the correctness.
+ var pixels = new Uint8Array(size * size * 4);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
+ gl.readPixels(0, 0, size, size, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+
+
+ for (var ii = 0; ii < size; ++ii) {
+ for (var jj = 0; jj < size; ++jj) {
+ var loc = ii * size + jj;
+ var color = [pixels[loc * 4], pixels[loc * 4 + 1], pixels[loc * 4 + 2], pixels[loc * 4 + 3]];
+
+ var expectedColor = [0, 0, 0, 0];
+ if (ii >= changedDstRect[0] && ii < changedDstRect[2] && jj >= changedDstRect[1] && jj < changedDstRect[3]) {
+ expectedColor = [0x20, 0x20, 0x20, 0xff];
+
+ // We may need to covert the color space for pixels in blit region
+ if (readbufferHasSRGBImage ^ drawbufferHasSRGBImage) {
+ if (drawbufferHasSRGBImage) {
+ expectedColor = wtu.linearToSRGB(expectedColor);
+ } else {
+ expectedColor = wtu.sRGBToLinear(expectedColor);
+ }
+ }
+ }
+
+ if (checkPixel(color, expectedColor) == true) {
+ testPassed("pixel at [" + jj + ", " + ii + "] is (" + color + "). It is correct!");
+ } else {
+ testFailed("pixel at [" + jj + ", " + ii + "] should be (" + expectedColor + "), but the actual color is (" + color + ")");
+ }
+ }
+ }
+ }
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo_read);
+ gl.deleteFramebuffer(fbo_draw);
+ gl.deleteTexture(tex_read);
+ gl.deleteTexture(tex_draw);
+};
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ var filters = [gl.LINEAR, gl.NEAREST];
+ for (var ii = 0; ii < filters.length; ++ii) {
+ blitframebuffer_filter_outofbounds(gl.RGBA8, gl.RGBA8, filters[ii]);
+ break;
+ blitframebuffer_filter_outofbounds(gl.RGBA8, gl.SRGB8_ALPHA8, filters[ii]);
+ blitframebuffer_filter_outofbounds(gl.SRGB8_ALPHA8, gl.RGBA8, filters[ii]);
+ blitframebuffer_filter_outofbounds(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8, filters[ii]);
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-srgb.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-srgb.html
new file mode 100644
index 0000000000..4054a0af25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-filter-srgb.html
@@ -0,0 +1,161 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer with sRGB framebuffers.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function checkPixel(color, expectedColor) {
+ var tolerance = 7;
+ return (Math.abs(color[0] - expectedColor[0]) <= tolerance &&
+ Math.abs(color[1] - expectedColor[1]) <= tolerance &&
+ Math.abs(color[2] - expectedColor[2]) <= tolerance &&
+ Math.abs(color[3] - expectedColor[3]) <= tolerance);
+}
+
+var tex_read = gl.createTexture();
+var tex_draw = gl.createTexture();
+var fbo_read = gl.createFramebuffer();
+var fbo_draw = gl.createFramebuffer();
+var size_read = 4;
+var size_draw = 0;
+
+function blitframebuffer_helper(readbufferFormat, drawbufferFormat, filter, data) {
+ // Create read framebuffer and feed data to read buffer
+ gl.bindTexture(gl.TEXTURE_2D, tex_read);
+ gl.texImage2D(gl.TEXTURE_2D, 0, readbufferFormat, size_read, size_read, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0);
+
+ // Create draw framebuffer and feed 0 to draw buffer
+ gl.bindTexture(gl.TEXTURE_2D, tex_draw);
+ gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size_draw, size_draw, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_draw, 0);
+
+ gl.blitFramebuffer(0, 0, size_read, size_read, 0, 0, size_draw, size_draw, gl.COLOR_BUFFER_BIT, filter);
+
+ // Read pixels for comparision
+ var pixels = new Uint8Array(size_draw * size_draw * 4);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
+ gl.readPixels(0, 0, size_draw, size_draw, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ return pixels;
+}
+
+function blitframebuffer_filter_srgb(readbufferFormat, drawbufferFormat, filter, minified) {
+ debug("");
+ debug("Test srgb filtering for blitFramebuffer, the current filter is: " + wtu.glEnumToString(gl, filter));
+ var min_mag = minified ? "minified to half the size." : "magnified to double the size.";
+ debug("read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat) + ", draw buffer format is: " + wtu.glEnumToString(gl, drawbufferFormat) + ", minify/magnify: " + min_mag);
+
+ // Initiate data to read framebuffer
+ var src_buffer = new Uint8Array(size_read * size_read * 4);
+ var start = 0;
+ for (var ii = 0; ii < size_read * size_read * 4; ii += 4) {
+ for (var jj = 0; jj < 3; ++jj) {
+ src_buffer[ii + jj] = start;
+ }
+ src_buffer[ii + 3] = 0xff;
+ start += 0x10;
+ }
+
+ // We may need to decode srgb to linear for reference data
+ var ref_buffer = new Uint8Array(size_read * size_read * 4);
+ for (var ii = 0; ii < size_read * size_read * 4; ii += 4) {
+ var color = [src_buffer[ii], src_buffer[ii + 1], src_buffer[ii + 2], src_buffer[ii + 3]];
+ var ref_color;
+ if (readbufferFormat == gl.SRGB8_ALPHA8) {
+ ref_color = wtu.sRGBToLinear(color);
+ } else {
+ ref_color = color;
+ }
+ for (var jj = 0; jj < 4; ++jj) {
+ ref_buffer[ii + jj] = ref_color[jj];
+ }
+ }
+
+ // Blit framebuffer to filter srgb image, but the reference data is always retrieved by blitFramebuffer against linear image
+ size_draw = minified ? size_read / 2 : size_read * 2;
+ var pixels = blitframebuffer_helper(readbufferFormat, drawbufferFormat, filter, src_buffer);
+ var temp = blitframebuffer_helper(gl.RGBA, gl.RGBA, filter, ref_buffer);
+
+ // We may need to encode linear to srgb for reference data
+ var ref_pixels = new Uint8Array(size_draw * size_draw * 4);
+ for (var ii = 0; ii < size_draw * size_draw * 4; ii += 4) {
+ var color = [temp[ii], temp[ii + 1], temp[ii + 2], temp[ii + 3]];
+ var ref_color;
+ if (drawbufferFormat == gl.SRGB8_ALPHA8) {
+ ref_color = wtu.linearToSRGB(color);
+ } else {
+ ref_color = color;
+ }
+ for (var jj = 0; jj < 4; ++jj) {
+ ref_pixels[ii + jj] = ref_color[jj];
+ }
+ }
+
+ // Compare
+ for (var ii = 0; ii < size_draw; ++ii) {
+ for (var jj = 0; jj < size_draw; ++jj) {
+ var index = ii * size_draw * 4 + jj;
+ var color = [pixels[index], pixels[index + 1], pixels[index + 2], pixels[index + 3]];
+ var expectedColor = [ref_pixels[index], ref_pixels[index + 1], ref_pixels[index + 2], ref_pixels[index + 3]];
+ if (checkPixel(color, expectedColor) == true) {
+ testPassed("pixel at [" + jj + ", " + ii + "] is (" + color + "). It is correct!");
+ } else {
+ testFailed("pixel at [" + jj + ", " + ii + "] should be (" + expectedColor + "), but the actual color is (" + color + ")");
+ }
+ }
+ }
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ var filters = [gl.LINEAR, gl.NEAREST];
+ for (var ii = 0; ii < filters.length; ++ii) {
+ blitframebuffer_filter_srgb(gl.RGBA8, gl.SRGB8_ALPHA8, filters[ii], true);
+ blitframebuffer_filter_srgb(gl.RGBA8, gl.SRGB8_ALPHA8, filters[ii], false);
+ blitframebuffer_filter_srgb(gl.SRGB8_ALPHA8, gl.RGBA8, filters[ii], true);
+ blitframebuffer_filter_srgb(gl.SRGB8_ALPHA8, gl.RGBA8, filters[ii], false);
+ blitframebuffer_filter_srgb(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8, filters[ii], true);
+ blitframebuffer_filter_srgb(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8, filters[ii], false);
+ }
+}
+
+gl.bindTexture(gl.TEXTURE_2D, null);
+gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+gl.deleteFramebuffer(fbo_read);
+gl.deleteFramebuffer(fbo_draw);
+gl.deleteTexture(tex_read);
+gl.deleteTexture(tex_draw);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-multisampled-readbuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-multisampled-readbuffer.html
new file mode 100644
index 0000000000..73f8e8b735
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-multisampled-readbuffer.html
@@ -0,0 +1,112 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer with multisampled sRGB color buffer.");
+
+var gl = wtu.create3DContext("canvas", undefined, 2);
+
+var tex_blit = gl.createTexture();
+var fb0 = gl.createFramebuffer();
+var rb0 = gl.createRenderbuffer();
+var fbo_blit = gl.createFramebuffer();
+var size = 32;
+var program;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ init();
+
+ var filters = [gl.LINEAR, gl.NEAREST];
+ for (var ii = 0; ii < filters.length; ++ii) {
+ blitframebuffer_multisampled_readbuffer(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8, filters[ii]);
+ }
+}
+
+function init() {
+ program = wtu.setupColorQuad(gl);
+ gl.viewport(0, 0, size, size);
+}
+
+function blitframebuffer_helper(readbufferFormat, drawbufferFormat, filter) {
+ // Create draw framebuffer and feed 0 to draw buffer
+ gl.bindTexture(gl.TEXTURE_2D, tex_blit);
+ gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_blit);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_blit, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup draw framebuffer should succeed");
+
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, filter);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitframebuffer should succeed");
+}
+
+function blitframebuffer_multisampled_readbuffer(readbufferFormat, drawbufferFormat, filter) {
+ debug("");
+ debug("Test blitFramebuffer when the read buffer is a multisampled srgb image. The filter is: " + wtu.glEnumToString(gl, filter));
+ debug("read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat) + ", draw buffer format is: " + wtu.glEnumToString(gl, drawbufferFormat));
+
+ // Draw to a multi-sampled srgb image, and blit to a srgb image.
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb0);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, readbufferFormat, size, size);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb0);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ var color = [252, 122, 15, 255];
+ var expectedColor = wtu.linearToSRGB(color);
+ for (var i = 0; i < 4; ++i) {
+ color[i] = color[i] / 255;
+ }
+ // Draw a rectangle. Fill it with solid color.
+ // Note that the draw buffer is a multisampled srgb image. So during drawing, the color will be converted into srgb color space.
+ gl.useProgram(program);
+ wtu.drawFloatColorQuad(gl, color);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ blitframebuffer_helper(readbufferFormat, drawbufferFormat, filter);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Blit from a multi-sampled srgb image to a srgb image should succeed");
+
+ // Compare
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_blit);
+ wtu.checkCanvasRect(gl, 0, 0, size, size, expectedColor);
+}
+
+gl.bindTexture(gl.TEXTURE_2D, null);
+gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+gl.deleteRenderbuffer(rb0);
+gl.deleteTexture(tex_blit);
+gl.deleteFramebuffer(fb0);
+gl.deleteFramebuffer(fbo_blit);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-outside-readbuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-outside-readbuffer.html
new file mode 100644
index 0000000000..a2e87034eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-outside-readbuffer.html
@@ -0,0 +1,267 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function checkPixel(color, expectedColor) {
+ var tolerance = 3;
+ return (Math.abs(color[0] - expectedColor[0]) <= tolerance &&
+ Math.abs(color[1] - expectedColor[1]) <= tolerance &&
+ Math.abs(color[2] - expectedColor[2]) <= tolerance &&
+ Math.abs(color[3] - expectedColor[3]) <= tolerance);
+}
+
+function blitframebuffer_outside_readbuffer(readbufferFormat, drawbufferFormat) {
+ debug("");
+ debug("blitting outside of read framebuffer, read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat) + ", draw buffer format is: " + wtu.glEnumToString(gl, drawbufferFormat));
+
+ // Initiate data to read framebuffer
+ var size_read = 3;
+ var uint_read = new Uint8Array(size_read * size_read * 4);
+ var start = 0x20;
+ for (var ii = 0; ii < size_read * size_read * 4; ii += 4) {
+ for (var jj = 0; jj < 3; ++jj) {
+ uint_read[ii + jj] = start;
+ }
+ uint_read[ii + 3] = 0xff;
+ start += 0x10;
+ }
+
+ // Create read framebuffer and feed data to read buffer
+ // Read buffer may has srgb image
+ var tex_read = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_read);
+ gl.texImage2D(gl.TEXTURE_2D, 0, readbufferFormat, size_read, size_read, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint_read);
+
+ var fbo_read = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0);
+
+ // Initiate data to draw framebuffer
+ var size_draw = 7;
+ var uint_draw = new Uint8Array(size_draw * size_draw * 4);
+ for (var ii = 0; ii < size_draw * size_draw * 4; ii += 4) {
+ for (var jj = 0; jj < 3; ++jj) {
+ uint_draw[ii + jj] = 0x10;
+ }
+ uint_draw[ii + 3] = 0xff;
+ }
+
+ // Create draw framebuffer and feed data to draw buffer
+ // Draw buffer may has srgb image
+ var tex_draw = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_draw);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size_draw, size_draw, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint_draw);
+
+ var fbo_draw = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_draw, 0);
+
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ var ref = [
+ // The reference pixels of the 1st line: (0, 0) ~ (6, 0)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+
+ // The reference pixels of the 2nd line: (0, 1) ~ (6, 1)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+
+ // The reference pixels of the 3rd line: (0, 2) ~ (6, 2)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x20, 0x20, 0x20, 0xff], [0x30, 0x30, 0x30, 0xff],
+ [0x40, 0x40, 0x40, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+
+ // The reference pixels of the 4th line: (0, 3) ~ (6, 3)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x50, 0x50, 0x50, 0xff], [0x60, 0x60, 0x60, 0xff],
+ [0x70, 0x70, 0x70, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+
+ // The reference pixels of the 5th line: (0, 4) ~ (6, 4)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x80, 0x80, 0x80, 0xff], [0x90, 0x90, 0x90, 0xff],
+ [0xa0, 0xa0, 0xa0, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+
+ // The reference pixels of the 6th line: (0, 5) ~ (6, 5)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+
+ // The reference pixels of the 7th line: (0, 6) ~ (6, 6)
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+ [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
+ ];
+
+ // The 1st round test: blit read framebuffer to the image in draw framebuffer
+ // All directions of the read region have pixels outside of the read buffer
+ // The src region and/or dst region may be reversed during blitting.
+ var test1 = [
+ [-1, 4, 1, 6], // reverse neither src nor dst
+ [4, -1, 1, 6], // reverse src only
+ [-1, 4, 6, 1], // reverse dst only
+ [4, -1, 6, 1] // reverse both src and dst
+ ];
+
+ var readbufferHasSRGBImage = (readbufferFormat == gl.SRGB8_ALPHA8);
+ var drawbufferHasSRGBImage = (drawbufferFormat == gl.SRGB8_ALPHA8);
+
+ for (var i = 0; i < 4; ++i) {
+ debug("");
+ switch (i) {
+ case 0: debug("reverse neither src region nor dst region"); break;
+ case 1: debug("reverse src region only"); break;
+ case 2: debug("reverse dst region only"); break;
+ case 3: debug("reverse both src region and dst region"); break;
+ }
+ var srcStart = test1[i][0];
+ var srcEnd = test1[i][1];
+ var dstStart = test1[i][2];
+ var dstEnd = test1[i][3];
+ var realBlittedDstStart = 2;
+ var realBlittedDstEnd = 5;
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.blitFramebuffer(srcStart, srcStart, srcEnd, srcEnd, dstStart, dstStart, dstEnd, dstEnd, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+
+ // Read pixels and check the correctness.
+ var pixels = new Uint8Array(size_draw * size_draw * 4);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
+ gl.readPixels(0, 0, size_draw, size_draw, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+
+ for (var ii = 0; ii < size_draw; ++ii) {
+ for (var jj = 0; jj < size_draw; ++jj) {
+ var loc = ii * size_draw + jj;
+ var color = [pixels[loc * 4], pixels[loc * 4 + 1], pixels[loc * 4 + 2], pixels[loc * 4 + 3]];
+
+ // We may need to reverse the reference loc if necessary
+ var ref_loc = loc;
+ var reverse_src = (srcStart < srcEnd);
+ var reverse_dst = (dstStart < dstEnd);
+ var reversed = reverse_src ^ reverse_dst;
+ if (reversed) {
+ ref_loc = (size_draw - ii - 1) * size_draw + (size_draw - jj -1);
+ }
+ var expectedColor = ref[ref_loc];
+
+ // We may need to covert the color space for pixels in blit region
+ if ((readbufferHasSRGBImage ^ drawbufferHasSRGBImage) &&
+ (ii >= realBlittedDstStart && ii < realBlittedDstEnd && jj >= realBlittedDstStart && jj < realBlittedDstEnd)) {
+ if (drawbufferHasSRGBImage) {
+ expectedColor = wtu.linearToSRGB(expectedColor);
+ } else {
+ expectedColor = wtu.sRGBToLinear(expectedColor);
+ }
+ }
+ if (checkPixel(color, expectedColor) == true) {
+ testPassed("pixel at [" + jj + ", " + ii + "] is (" + color + "). It is correct!");
+ } else {
+ testFailed("pixel at [" + jj + ", " + ii + "] should be (" + expectedColor + "), but the actual color is (" + color + ")");
+ }
+ }
+ }
+ }
+
+ // The 2nd round test: blit read framebuffer to the image in draw framebuffer
+ // Only one direction of the read region have pixels outside of the read buffer
+ var tests = [
+ [-1, 0], // pixels are outside the left edge of the read buffer
+ [0, -1], // pixels are outside the bottom edge of the read buffer
+ [1, 0], // pixels are outside the right edge of the read buffer
+ [0, 1] // pixels are outside the top edge of the read buffer
+ ];
+ for (var i = 0; i < 4; ++i) {
+ debug("");
+ switch (i) {
+ case 0: debug("verify that pixels lying outside the left edge of the read buffer should remain untouched"); break;
+ case 1: debug("verify that pixels lying outside the bottom edge of the read buffer should remain untouched"); break;
+ case 2: debug("verify that pixels lying outside the right edge of the read buffer should remain untouched"); break;
+ case 3: debug("verify that pixels lying outside the top edge of the read buffer should remain untouched"); break;
+ }
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ var srcX = tests[i][0];
+ var srcY = tests[i][1];
+ var offset = dstStart - srcStart;
+ gl.blitFramebuffer(srcX, srcY, srcX + size_read, srcY + size_read,
+ srcX + offset, srcY + offset, srcX + offset + size_read, srcY + offset + size_read,
+ gl.COLOR_BUFFER_BIT, gl.LINEAR);
+
+ // Read pixels and check the correctness.
+ var pixels = new Uint8Array(size_draw * size_draw * 4);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
+ gl.readPixels(0, 0, size_draw, size_draw, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ for (var ii = srcY + offset; ii < srcY + offset + size_read; ++ii) {
+ for (var jj = srcX + offset; jj < srcX + offset + size_read; ++jj) {
+ var loc = ii * size_draw + jj;
+ var color = [pixels[loc * 4], pixels[loc * 4 + 1], pixels[loc * 4 + 2], pixels[loc * 4 + 3]];
+ var expectedColor = ref[loc];
+ // We may need to covert the color space for pixels in blit region
+ if ((readbufferHasSRGBImage ^ drawbufferHasSRGBImage) &&
+ (ii >= realBlittedDstStart && ii < realBlittedDstEnd && jj >= realBlittedDstStart && jj < realBlittedDstEnd)) {
+ if (drawbufferHasSRGBImage) {
+ expectedColor = wtu.linearToSRGB(expectedColor);
+ } else {
+ expectedColor = wtu.sRGBToLinear(expectedColor);
+ }
+ }
+ if (checkPixel(color, expectedColor) == true) {
+ testPassed("pixel at [" + jj + ", " + ii + "] is (" + color + "). It is correct!");
+ } else {
+ testFailed("pixel at [" + jj + ", " + ii + "] should be (" + expectedColor + "), but the actual color is (" + color + ")");
+ }
+ }
+ }
+ }
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo_read);
+ gl.deleteFramebuffer(fbo_draw);
+ gl.deleteTexture(tex_read);
+ gl.deleteTexture(tex_draw);
+};
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ blitframebuffer_outside_readbuffer(gl.RGBA8, gl.RGBA8);
+ blitframebuffer_outside_readbuffer(gl.RGBA8, gl.SRGB8_ALPHA8);
+ blitframebuffer_outside_readbuffer(gl.SRGB8_ALPHA8, gl.RGBA8);
+ blitframebuffer_outside_readbuffer(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-r11f-g11f-b10f.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-r11f-g11f-b10f.html
new file mode 100644
index 0000000000..636e76ac29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-r11f-g11f-b10f.html
@@ -0,0 +1,113 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL R11F_G11F_B10F BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This tests multisample blitting with the R11F_G11F_B10F format.");
+
+var width = 8;
+var height = 8;
+
+function runWithContextCreationArguments(args) {
+ debug('');
+ debug('Running test with arguments: ' + JSON.stringify(args));
+
+ var canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+
+ var gl = wtu.create3DContext(canvas, args, 2);
+ if (!gl) {
+ testFailed("WebGL 2.0 context does not exist");
+ return;
+ }
+
+ var ext = gl.getExtension("EXT_color_buffer_float");
+ if (!ext) {
+ testPassed("EXT_color_buffer_float extension not supported");
+ return;
+ }
+
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.R11F_G11F_B10F, gl.SAMPLES);
+
+ // Set up source framebuffer.
+ var rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.R11F_G11F_B10F, width, height);
+ var readfb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, readfb);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after multisampled R11F_G11F_B10F FBO setup");
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Source framebuffer incomplete.");
+ return;
+ }
+
+ // Draw something to that framebuffer.
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after clearing R11F_G11F_B10F framebuffer");
+
+ // Set up destination framebuffer for resolving MSAA.
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R11F_G11F_B10F, width, height, 0, gl.RGB, gl.UNSIGNED_INT_10F_11F_11F_REV, null);
+ var drawfb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawfb);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after destination R11F_G11F_B10F FBO setup");
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ // Attempt a blit.
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after blitFramebuffer for multisample resolve");
+
+ // Try a readback.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, drawfb);
+ var readBackBuf = new Float32Array(width * height * 4);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0.0, 1.0, 0.0], "should be green", undefined, readBackBuf, gl.FLOAT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after floating-point canvas readback");
+
+ // If default backbuffer is RGB and non-antialiased, test blitting to it too.
+ if (args && !args['alpha'] && !args['antialias']) {
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, drawfb);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after blit to default back buffer");
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "default back buffer should be green");
+ }
+}
+
+// The format of the back buffer should have no effect on the behavior of this test.
+runWithContextCreationArguments(undefined);
+runWithContextCreationArguments({ alpha: true, antialias: true });
+runWithContextCreationArguments({ alpha: true, antialias: false });
+runWithContextCreationArguments({ alpha: false, antialias: true });
+runWithContextCreationArguments({ alpha: false, antialias: false });
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-resolve-to-back-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-resolve-to-back-buffer.html
new file mode 100644
index 0000000000..addbdc4e9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-resolve-to-back-buffer.html
@@ -0,0 +1,245 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Resolve to Back Buffer</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="canvasHeader"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the behavior of blitFramebuffer when resolving directly to the back buffer.");
+
+debug("Regression test for <a href='http://crbug.com/699566'>http://crbug.com/699566</a>");
+
+function runTest(testParams) {
+ const sz = 64;
+
+ if (testParams.multisampled === undefined) {
+ testParams.multisampled = true;
+ }
+
+ debug('');
+ debug('Testing with alpha = ' + testParams.attribs.alpha +
+ ', antialias = ' + testParams.attribs.antialias +
+ ', internalformat = ' + testParams.internalformat +
+ ', multisampled = ' + testParams.multisampled);
+
+ var canvas = document.createElement('canvas');
+ canvas.width = sz;
+ canvas.height = sz;
+ document.getElementById('canvasHeader').appendChild(canvas);
+ var gl = wtu.create3DContext(canvas, testParams.attribs, 2);
+
+ // Find the supported samples for a multisampled renderbuffer of the appropriate internal format.
+ let samples = [0];
+ if (testParams.multisampled) {
+ samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl[testParams.internalformat], gl.SAMPLES);
+ if (!samples || !samples.length) {
+ testFailed("At least one multisampled format is required to be supported");
+ return;
+ }
+ }
+
+ // Create a framebuffer with a multisampled renderbuffer.
+ let rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl[testParams.internalformat], sz, sz);
+
+ // Create a framebuffer.
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+
+ // Check for completeness.
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Rendering to a multisampled renderbuffer of format " + testParams.internalformat + " is required by the spec");
+ return;
+ }
+
+ // Clear to specified color.
+ gl.clearColor.apply(gl, testParams.clearColor);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Unbind draw framebuffer. Read framebuffer is now user framebuffer;
+ // draw framebuffer is default framebuffer.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors before blit");
+
+ // Blit from user framebuffer to default framebuffer.
+ gl.blitFramebuffer(0, 0, sz, sz, 0, 0, sz, sz, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+
+ if (testParams.shouldSucceed) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be legal to blit/resolve to default back buffer");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "incompatible src/dest blitFramebuffer combination must fail");
+ }
+
+ // Unbind user framebuffer completely.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+
+ if (testParams.shouldSucceed) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error before readback");
+ wtu.checkCanvasRect(gl, 0, 0, 8, 8, testParams.resultColor);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+}
+
+var tests = [
+ // No-alpha, no-antialias, RGB8 source
+ {
+ attribs: {
+ alpha: false,
+ antialias: false,
+ },
+ internalformat: 'RGB8',
+ clearColor: [ 0.0, 1.0, 0.0, 0.5 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: true,
+ },
+ // No-alpha, no-antialias, RGBA8 source
+ {
+ attribs: {
+ alpha: false,
+ antialias: false,
+ },
+ internalformat: 'RGBA8',
+ clearColor: [ 0.0, 1.0, 0.0, 0.5 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: false,
+ },
+ // No-alpha, no-antialias, RGBA8 source, single-sampled blit
+ {
+ attribs: {
+ alpha: false,
+ antialias: false,
+ },
+ internalformat: 'RGBA8',
+ clearColor: [ 0.0, 1.0, 0.0, 0.5 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: true,
+ multisampled: false,
+ },
+ // Alpha, no-antialias, RGB8 source
+ {
+ attribs: {
+ alpha: true,
+ antialias: false,
+ },
+ internalformat: 'RGB8',
+ clearColor: [ 0.0, 1.0, 0.0, 1.0 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: false,
+ },
+ // No-alpha, no-antialias, RGBA8 source
+ // premultiplyAlpha:false just to avoid semantically incorrect
+ // colors (should only affect rendering, not contents of WebGL
+ // back buffer)
+ {
+ attribs: {
+ alpha: false,
+ antialias: false,
+ premultiplyAlpha: false,
+ },
+ internalformat: 'RGBA8',
+ clearColor: [ 0.0, 1.0, 0.0, 1.0 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: false,
+ },
+ // Alpha, no-antialias, RGBA8 source
+ // premultiplyAlpha:false just to avoid semantically incorrect
+ // colors (should only affect rendering, not contents of WebGL
+ // back buffer)
+ {
+ attribs: {
+ alpha: true,
+ antialias: false,
+ premultiplyAlpha: false,
+ },
+ internalformat: 'RGBA8',
+ clearColor: [ 0.0, 1.0, 0.0, 0.0 ],
+ resultColor: [ 0, 255, 0, 0 ],
+ shouldSucceed: true,
+ },
+
+ // All attempts to blit to an antialiased back buffer should fail.
+
+ // No-alpha, antialias, RGB8 source
+ {
+ attribs: {
+ alpha: false,
+ antialias: true,
+ },
+ internalformat: 'RGB8',
+ clearColor: [ 0.0, 1.0, 0.0, 1.0 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: false,
+ },
+ // Alpha, antialias, RGB8 source
+ {
+ attribs: {
+ alpha: true,
+ antialias: true,
+ },
+ internalformat: 'RGB8',
+ clearColor: [ 0.0, 1.0, 0.0, 1.0 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: false,
+ },
+ // No-alpha, antialias, RGBA8 source
+ // premultiplyAlpha:false just to avoid semantically incorrect
+ // colors (should only affect rendering, not contents of WebGL
+ // back buffer)
+ {
+ attribs: {
+ alpha: false,
+ antialias: true,
+ premultiplyAlpha: false,
+ },
+ internalformat: 'RGBA8',
+ clearColor: [ 0.0, 1.0, 0.0, 1.0 ],
+ resultColor: [ 0, 255, 0, 255 ],
+ shouldSucceed: false,
+ },
+ // Alpha, antialias, RGBA8 source
+ // premultiplyAlpha:false just to avoid semantically incorrect
+ // colors (should only affect rendering, not contents of WebGL
+ // back buffer)
+ {
+ attribs: {
+ alpha: true,
+ antialias: true,
+ premultiplyAlpha: false,
+ },
+ internalformat: 'RGBA8',
+ clearColor: [ 0.0, 1.0, 0.0, 0.0 ],
+ resultColor: [ 0, 255, 0, 0 ],
+ shouldSucceed: false,
+ },
+];
+
+for (var ii in tests) {
+ runTest(tests[ii]);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-scissor-enabled.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-scissor-enabled.html
new file mode 100644
index 0000000000..d0e2dfaefa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-scissor-enabled.html
@@ -0,0 +1,160 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer when scissor test is enabled.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+// Define the src region and dst region for blitFramebuffer
+var blit_src = [0, 0, 4, 4];
+var blit_dst = [2, 2, 6, 6];
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ var bounds = [
+ [0, 0, 4, 4], // Partially intersects with blitFramebuffer's dst region
+ [0, 0, 2, 2], // No intersection with blitFramebuffer's dst region
+ ];
+
+ // We can compute the real drawing area by intersecting the scissor bound with dst region of blitting.
+ var intersections = [
+ [2, 2, 4, 4],
+ [0, 0, 0, 0],
+ ];
+
+ for (var ii = 0; ii < bounds.length; ++ii) {
+ blitframebuffer_scissor(gl.RGBA8, gl.RGBA8, bounds[ii], intersections[ii]);
+ blitframebuffer_scissor(gl.RGBA8, gl.SRGB8_ALPHA8, bounds[ii], intersections[ii]);
+ blitframebuffer_scissor(gl.SRGB8_ALPHA8, gl.RGBA8, bounds[ii], intersections[ii]);
+ blitframebuffer_scissor(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8, bounds[ii], intersections[ii]);
+ }
+}
+
+function checkPixel(color, expectedColor) {
+ var tolerance = 3;
+ return (Math.abs(color[0] - expectedColor[0]) <= tolerance &&
+ Math.abs(color[1] - expectedColor[1]) <= tolerance &&
+ Math.abs(color[2] - expectedColor[2]) <= tolerance &&
+ Math.abs(color[3] - expectedColor[3]) <= tolerance);
+}
+
+function blitframebuffer_scissor(readbufferFormat, drawbufferFormat, bound, intersection) {
+ debug("");
+ debug("read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat) + ", draw buffer format is: " + wtu.glEnumToString(gl, drawbufferFormat));
+
+
+ // Initiate data to read framebuffer
+ var size = 8;
+ var data = new Uint8Array(size * size * 4);
+ var color = [250, 100, 15, 255];
+ for (var ii = 0; ii < size * size * 4; ii += 4) {
+ for (var jj = 0; jj < 4; ++jj) {
+ data[ii + jj] = color[jj];
+ }
+ }
+
+ // Feed data to read buffer. Feed 0 to draw buffer.
+ var tex_read = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_read);
+ gl.texImage2D(gl.TEXTURE_2D, 0, readbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+
+ var fbo_read = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0);
+
+ var tex_draw = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_draw);
+ gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var fbo_draw = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_draw, 0);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ // Enable scissor test. Then blit framebuffer.
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(bound[0], bound[1], bound[2], bound[3]);
+ gl.blitFramebuffer(blit_src[0], blit_src[1], blit_src[2], blit_src[3], blit_dst[0], blit_dst[1], blit_dst[2], blit_dst[3], gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitframebuffer should succeed");
+
+ // Read pixels and Comparison
+ var pixels = new Uint8Array(size * size * 4);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
+ gl.readPixels(0, 0, size, size, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should succeed");
+
+ var blitColor;
+ var expectedColor;
+ var clearColor = [0, 0, 0, 0];
+
+ if (readbufferFormat == drawbufferFormat) {
+ blitColor = color;
+ } else if (readbufferFormat == gl.SRGB8_ALPHA8) {
+ blitColor = wtu.sRGBToLinear(color);
+ } else {
+ blitColor = wtu.linearToSRGB(color);
+ }
+
+ var failed = false;
+ for (var ii = 0; ii < size; ++ii) {
+ for (var jj = 0; jj < size; ++jj) {
+ if (ii >= intersection[0] && jj >= intersection[1] && ii < intersection[2] && jj < intersection[3]) {
+ expectedColor = blitColor;
+ } else {
+ expectedColor = clearColor;
+ }
+ var index = (ii * size + jj) * 4;
+ var pixelColor = [pixels[index], pixels[index + 1], pixels[index + 2], pixels[index + 3]];
+ if (checkPixel(pixelColor, expectedColor) == false) {
+ failed = true;
+ debug("Pixels comparison failed. Pixel at [" + jj + ", " + ii + "] should be (" + expectedColor + "), but the actual color is (" + pixelColor + ")");
+ }
+ }
+ }
+ if (failed == false) {
+ testPassed("All pixels comparision passed!");
+ }
+
+ // Deinit
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo_read);
+ gl.deleteFramebuffer(fbo_draw);
+ gl.deleteTexture(tex_read);
+ gl.deleteTexture(tex_draw);
+};
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-size-overflow.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-size-overflow.html
new file mode 100644
index 0000000000..512946cb82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-size-overflow.html
@@ -0,0 +1,98 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies blitFramebuffer won't cause a crash when the computed sizes might overflow.");
+
+var width = 8;
+var height = 8;
+
+var gl = wtu.create3DContext("example", undefined, 2);
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ blit_region_test();
+}
+
+function blit_region_test() {
+
+ debug("");
+ debug("Begin to run blitFramebuffer. The computed width/height of src and/or dst region might overflow during blitting.");
+ var tex0 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fb0 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex0, 0);
+
+ var tex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fb1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+ if ((gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) ||
+ (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ var max = 0x7fffffff;
+ gl.blitFramebuffer(0, 0, max, max, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.blitFramebuffer(0, 0, max, max, 0, 0, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Using max 32-bit integer as blitFramebuffer parameter should succeed.");
+
+ gl.blitFramebuffer(-1, -1, max - 1, max - 1, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.blitFramebuffer(0, 0, width, height, -1, -1, max - 1, max - 1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.blitFramebuffer(-1, -1, max - 1, max - 1, -1, -1, max - 1, max - 1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Using blitFramebuffer parameters where calculated width/height matches max 32-bit integer should succeed.");
+
+ gl.blitFramebuffer(-1, -1, max, max, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using source width/height greater than max 32-bit integer should fail.");
+ gl.blitFramebuffer(max, max, -1, -1, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using source width/height greater than max 32-bit integer should fail.");
+ gl.blitFramebuffer(0, 0, width, height, -1, -1, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using destination width/height greater than max 32-bit integer should fail.");
+ gl.blitFramebuffer(0, 0, width, height, max, max, -1, -1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using destination width/height greater than max 32-bit integer should fail.");
+ gl.blitFramebuffer(-1, -1, max, max, -1, -1, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using both source and destination width/height greater than max 32-bit integer should fail.");
+ gl.blitFramebuffer(-max - 1, -max - 1, max, max, -max - 1, -max - 1, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using minimum and maximum integers for all boundaries should fail.");
+
+ gl.bindTexture(gl.TEXTURE_2D, null)
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteTexture(tex0);
+ gl.deleteTexture(tex1);
+ gl.deleteFramebuffer(fb0);
+ gl.deleteFramebuffer(fb1);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-srgb-and-linear-drawbuffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-srgb-and-linear-drawbuffers.html
new file mode 100644
index 0000000000..35b8c3ddab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-srgb-and-linear-drawbuffers.html
@@ -0,0 +1,207 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer with multiple draw buffers (srgb image and linear image).");
+
+var gl = wtu.create3DContext("canvas", undefined, 2);
+var linearMask = 1;
+var srgbMask = 2;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ var filters = [gl.LINEAR, gl.NEAREST];
+ var drawbuffersFormats = [linearMask, srgbMask, linearMask | srgbMask];
+ for (var ii = 0; ii < filters.length; ++ii) {
+ for (var jj = 0; jj < drawbuffersFormats.length; ++jj) {
+ blitframebuffer_srgb_and_linear_drawbuffers(gl.SRGB8_ALPHA8, drawbuffersFormats[jj], filters[ii]);
+ blitframebuffer_srgb_and_linear_drawbuffers(gl.RGBA8, drawbuffersFormats[jj], filters[ii]);
+ }
+ }
+}
+
+function blitframebuffer_srgb_and_linear_drawbuffers(readbufferFormat, drawbuffersFormatMask, filter) {
+ debug("");
+ debug("The filter is: " + wtu.glEnumToString(gl, filter));
+ debug("Read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat));
+ var drawbuffersFormat = "\0";
+ if (drawbuffersFormatMask & linearMask) {
+ drawbuffersFormat += " linear ";
+ }
+ if (drawbuffersFormatMask & srgbMask) {
+ drawbuffersFormat += " srgb ";
+ }
+ debug("The test have multiple draw buffers, the images are: " + drawbuffersFormat);
+
+ var tex_srgb0 = gl.createTexture();
+ var tex_srgb1 = gl.createTexture();
+ var tex_linear0 = gl.createTexture();
+ var tex_linear1 = gl.createTexture();
+ var tex_read = gl.createTexture();
+ var fbo_read = gl.createFramebuffer();
+ var fbo_draw = gl.createFramebuffer();
+
+ // Create read buffer and feed data to the read buffer
+ var size = 8;
+ var data = new Uint8Array(size * size * 4);
+ var color = [250, 100, 15, 255];
+ for (var ii = 0; ii < size * size * 4; ii += 4) {
+ for (var jj = 0; jj < 4; ++jj) {
+ data[ii + jj] = color[jj];
+ }
+ }
+ gl.bindTexture(gl.TEXTURE_2D, tex_read);
+ gl.texImage2D(gl.TEXTURE_2D, 0, readbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup read framebuffer should succeed");
+
+ // Create multiple textures. Attach them as fbo's draw buffers.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+
+ var drawbuffers = [gl.NONE, gl.NONE, gl.NONE, gl.NONE];
+ if (drawbuffersFormatMask & srgbMask) {
+ gl.bindTexture(gl.TEXTURE_2D, tex_srgb0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_srgb0, 0);
+ gl.bindTexture(gl.TEXTURE_2D, tex_srgb1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, tex_srgb1, 0);
+ drawbuffers[0] = gl.COLOR_ATTACHMENT0;
+ drawbuffers[2] = gl.COLOR_ATTACHMENT2;
+ }
+
+ if (drawbuffersFormatMask & linearMask) {
+ gl.bindTexture(gl.TEXTURE_2D, tex_linear0);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex_linear0, 0);
+ gl.bindTexture(gl.TEXTURE_2D, tex_linear1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT3, gl.TEXTURE_2D, tex_linear1, 0);
+ drawbuffers[1] = gl.COLOR_ATTACHMENT1;
+ drawbuffers[3] = gl.COLOR_ATTACHMENT3;
+ }
+
+ gl.drawBuffers(drawbuffers);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup draw framebuffer should succeed");
+
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete when setup draw framebuffer.");
+ return;
+ }
+
+ // Blit to multiple draw buffers with srgb images and linear images
+ var dstSize = size - 1;
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, dstSize, dstSize, gl.COLOR_BUFFER_BIT, filter);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitframebuffer should succeed");
+
+ // Read pixels from srgb images and linear images
+ var srgbPixels0 = new Uint8Array(dstSize * dstSize * 4);
+ var srgbPixels1 = new Uint8Array(dstSize * dstSize * 4);
+ var linearPixels0 = new Uint8Array(dstSize * dstSize * 4);
+ var linearPixels1 = new Uint8Array(dstSize * dstSize * 4);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
+ if (drawbuffersFormatMask & srgbMask) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, srgbPixels0);
+ gl.readBuffer(gl.COLOR_ATTACHMENT2);
+ gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, srgbPixels1);
+ }
+
+ if (drawbuffersFormatMask & linearMask) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, linearPixels0);
+ gl.readBuffer(gl.COLOR_ATTACHMENT3);
+ gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, linearPixels1);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readpixels should succeed");
+
+ // Compare
+ var expectedSRGBColor = (readbufferFormat == gl.SRGB8_ALPHA8) ? color : wtu.linearToSRGB(color);
+ var expectedLinearColor = (readbufferFormat == gl.SRGB8_ALPHA8) ? wtu.sRGBToLinear(color) : color;
+ var failed = false;
+ for (var ii = 0; ii < dstSize; ++ii) {
+ for (var jj = 0; jj < dstSize; ++jj) {
+ var index = (ii * dstSize + jj) * 4;
+ if (drawbuffersFormatMask & srgbMask) {
+ var srgbColor0 = [srgbPixels0[index], srgbPixels0[index + 1], srgbPixels0[index + 2], srgbPixels0[index + 3]];
+ if (checkPixel(srgbColor0, expectedSRGBColor) == false) {
+ failed = true;
+ debug("Pixels comparison failed for the 1st sRGB image. Pixel at [" + jj + ", " + ii + "] should be (" + expectedSRGBColor + "), but the actual color is (" + srgbColor0 + ")");
+ }
+ var srgbColor1 = [srgbPixels1[index], srgbPixels1[index + 1], srgbPixels1[index + 2], srgbPixels1[index + 3]];
+ if (checkPixel(srgbColor1, expectedSRGBColor) == false) {
+ failed = true;
+ debug("Pixels comparison failed for the 2nd sRGB image. Pixel at [" + jj + ", " + ii + "] should be (" + expectedSRGBColor + "), but the actual color is (" + srgbColor1 + ")");
+ }
+ }
+
+ if (drawbuffersFormatMask & linearMask) {
+ var linearColor0 = [linearPixels0[index], linearPixels0[index + 1], linearPixels0[index + 2], linearPixels0[index + 3]];
+ if (checkPixel(linearColor0, expectedLinearColor) == false) {
+ failed = true;
+ debug("Pixel comparison failed for the 1st linear image. Pixel at [" + jj + ", " + ii + "] should be (" + color + "), but the actual color is (" + linearColor0 + ")");
+ }
+ var linearColor1 = [linearPixels1[index], linearPixels1[index + 1], linearPixels1[index + 2], linearPixels1[index + 3]];
+ if (checkPixel(linearColor1, expectedLinearColor) == false) {
+ failed = true;
+ debug("Pixel comparison failed for the 2nd linear image. Pixel at [" + jj + ", " + ii + "] should be (" + color + "), but the actual color is (" + linearColor1 + ")");
+ }
+ }
+ }
+ }
+ if (failed == false) {
+ testPassed("All pixels comparision passed!");
+ }
+
+ // deinit
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteTexture(tex_srgb0);
+ gl.deleteTexture(tex_linear0);
+ gl.deleteTexture(tex_srgb1);
+ gl.deleteTexture(tex_linear1);
+ gl.deleteTexture(tex_read);
+ gl.deleteFramebuffer(fbo_read);
+ gl.deleteFramebuffer(fbo_draw);
+}
+
+function checkPixel(color, expectedColor) {
+ var tolerance = 3;
+ return (Math.abs(color[0] - expectedColor[0]) <= tolerance &&
+ Math.abs(color[1] - expectedColor[1]) <= tolerance &&
+ Math.abs(color[2] - expectedColor[2]) <= tolerance &&
+ Math.abs(color[3] - expectedColor[3]) <= tolerance);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-stencil-only.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-stencil-only.html
new file mode 100644
index 0000000000..b14acf3456
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-stencil-only.html
@@ -0,0 +1,170 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Stencil-only Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+in vec4 position;
+void main() {
+ gl_Position = position;
+}
+</script>
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+out mediump vec4 colorOut;
+uniform mediump vec3 color;
+void main() {
+ colorOut = vec4(color, 1.0);
+}
+</script>
+
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test covers some edge cases of blitFramebuffer with stencil.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var program, colorLoc;
+
+function init_buffer(format) {
+ var buf = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, buf)
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 16, 16);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ var rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, 16, 16);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER,
+ gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
+
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after buffer init");
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ return { fbo: buf, color: tex, depthStencil: rbo };
+}
+
+var quadVB;
+
+function drawQuad(depth) {
+ if (!quadVB) {
+ quadVB = gl.createBuffer()
+ }
+
+ var quadVerts = new Float32Array(3 * 6);
+ quadVerts[0] = -1.0; quadVerts[1] = 1.0; quadVerts[2] = depth;
+ quadVerts[3] = -1.0; quadVerts[4] = -1.0; quadVerts[5] = depth;
+ quadVerts[6] = 1.0; quadVerts[7] = -1.0; quadVerts[8] = depth;
+ quadVerts[9] = -1.0; quadVerts[10] = 1.0; quadVerts[11] = depth;
+ quadVerts[12] = 1.0; quadVerts[13] = -1.0; quadVerts[14] = depth;
+ quadVerts[15] = 1.0; quadVerts[16] = 1.0; quadVerts[17] = depth;
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadVB);
+ gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawQuad");
+}
+
+// Test based on dEQP-GLES3.functional.blit.depth_stencil.depth_24_stencil8_stencil_only
+function test_stencil_only_blit(format) {
+ debug("testing format: " + wtu.glEnumToString(gl, format))
+
+ var src = init_buffer(format);
+ var dest = init_buffer(format);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, src.fbo);
+ gl.viewport(0, 0, 16, 16);
+
+ // Fill source with red, depth = 0.5, stencil = 7
+ gl.enable(gl.DEPTH_TEST);
+ gl.enable(gl.STENCIL_TEST);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ gl.stencilFunc(gl.ALWAYS, 7, 0xFF);
+ gl.uniform3f(colorLoc, 1.0, 0.0, 0.0);
+ drawQuad(0.5);
+
+ // Fill dest with yellow, depth = 0.0, stencil = 1
+ gl.bindFramebuffer(gl.FRAMEBUFFER, dest.fbo);
+ gl.stencilFunc(gl.ALWAYS, 1, 0xff);
+ gl.uniform3f(colorLoc, 1.0, 1.0, 0.0);
+ drawQuad(0.0);
+
+ // Perform copy.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, src.fbo);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dest.fbo);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.STENCIL_BUFFER_BIT, gl.NEAREST);
+
+ // Render blue where depth < 0, decrement on depth failure.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, dest.fbo);
+ gl.stencilOp(gl.KEEP, gl.DECR, gl.KEEP);
+ gl.stencilFunc(gl.ALWAYS, 0, 0xff);
+
+ gl.uniform3f(colorLoc, 0.0, 0.0, 1.0);
+ drawQuad(0.0);
+
+ // Render green where stencil == 6.
+ gl.disable(gl.DEPTH_TEST);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ gl.stencilFunc(gl.EQUAL, 6, 0xff);
+
+ gl.uniform3f(colorLoc, 0.0, 1.0, 0.0);
+ drawQuad(0.0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after test");
+ wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0, 255, 0, 255],
+ "stencil test should be green");
+
+ gl.deleteFramebuffer(src.fbo);
+ gl.deleteFramebuffer(dest.fbo);
+ gl.deleteTexture(src.color);
+ gl.deleteTexture(dest.color);
+ gl.deleteRenderbuffer(src.depthStencil);
+ gl.deleteRenderbuffer(dest.depthStencil);
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ program = wtu.setupProgram(gl, ["vs", "fs"], ["position"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after program initialization");
+ shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+
+ colorLoc = gl.getUniformLocation(program, "color")
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "query uniform location");
+ shouldBeNonNull('colorLoc')
+
+ test_stencil_only_blit(gl.DEPTH24_STENCIL8);
+ test_stencil_only_blit(gl.DEPTH32F_STENCIL8);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-test.html
new file mode 100644
index 0000000000..c470b02e4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-test.html
@@ -0,0 +1,361 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL BlitFramebuffer Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of blitFramebuffer for some corner cases.");
+
+var width = 8;
+var height = 8;
+
+var gl = wtu.create3DContext("example", undefined, 2);
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ blit_framebuffer_repeated();
+ blit_framebuffer_feedback_loop();
+ blit_framebuffer_multisampling_srgb();
+}
+
+function blit_framebuffer_repeated() {
+ debug("");
+ debug("This test verifies repeated calls to blitFramebuffer.");
+
+ // Create offscreen fbo and its color attachment.
+ var tex_2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_2d);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ var prog = wtu.setupColorQuad(gl, 0);
+ wtu.setFloatDrawColor(gl, [ 1.0, 0.0, 0.0, 1.0 ]);
+ wtu.drawUnitQuad(gl);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvas(gl, [ 255, 0, 0, 255 ], "should be red at first");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ wtu.setFloatDrawColor(gl, [ 0.0, 1.0, 0.0, 1.0 ]);
+ wtu.drawUnitQuad(gl);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "should be green");
+}
+
+function blit_framebuffer_feedback_loop() {
+
+ debug("");
+ debug("This test checks whether the src resource and dst resource have identical images.");
+ // Create read fbo and its color attachment.
+ var tex_2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex_2d);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+
+ var fb0 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ // Create draw fbo and its color attachment.
+ var rb0 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb0);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, width, height);
+
+ var fb1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb0);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ // Blit framebuffer, all conditions are OK.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed.");
+
+ // Blit framebuffer, the src buffer and the dst buffer should not be identical.
+ // Exactly the same read/draw fbo
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb0);
+ gl.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffer are identical.");
+
+ // Exactly the same read/draw framebuffer: default framebuffer
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffer are identical.");
+
+ // The same image with the same level bound to read/draw buffer.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw color buffer are identical.");
+
+ // The same image in read/draw buffer, but different levels are bound to read/draw buffer respectively.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 1);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed if read/draw buffer has the same image with different levels.");
+
+ // The same cube_map image in read/draw buffer, but different faces are bound to read/draw buffer respectively.
+ var tex_cube_map = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex_cube_map);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, tex_cube_map, 0);
+ if ((gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) ||
+ (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed if read/draw buffer has the same CUBE_MAP image with different faces.");
+
+ // The same 3D/2D_ARRAY image in read/draw buffer, but different layers are bound to read/draw buffer respectively.
+ var tex_2d_array = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex_2d_array);
+ var depth = 2;
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ var level = 0, layer = 0;
+ gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex_2d_array, level, layer);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ layer = 1;
+ gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex_2d_array, level, layer);
+ if ((gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) ||
+ (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed if read/draw buffer has the same 3D/2D_ARRAY image with different layers.");
+
+ // The same image are bound as depth buffer in both read framebuffer and draw framebuffer
+ var rb1 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb1);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, width, height);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb1);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, tex_cube_map, 0);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb1);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ // But the mask doesn't have depth buffer bit.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed.");
+
+ // The mask has depth buffer bit.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw framebuffer have identical depth buffer attachment.");
+
+ // The same image are bound as stencil buffer in both read framebuffer and draw framebuffer
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb1);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb1);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ // But the mask doesn't have stencil buffer bit.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed.");
+
+ // The mask has stencil buffer bit.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw framebuffer have identical stencil buffer attachment.");
+
+ // The same image are bound as color buffer in both read framebuffer and draw framebuffer
+ var rb2 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb2);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, width, height);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb2);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, tex_cube_map, 0);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb1);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ // But the mask doesn't have color buffer bit.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed.");
+
+ // The mask has color buffer bit, but the same image is not specified as draw buffer.
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed.");
+
+ // The mask has color buffer bit, the same image is specified as both read buffer and draw buffer.
+ gl.drawBuffers([gl.COLOR_ATTACHENT0, gl.COLOR_ATTACHMENT1]);
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffers have identical color buffer attachment.");
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteTexture(tex_2d);
+ gl.deleteTexture(tex_cube_map);
+ gl.deleteTexture(tex_2d_array);
+ gl.deleteRenderbuffer(rb0);
+ gl.deleteRenderbuffer(rb1);
+ gl.deleteRenderbuffer(rb2);
+ gl.deleteFramebuffer(fb0);
+ gl.deleteFramebuffer(fb1);
+};
+
+function blit_framebuffer_multisampling_srgb() {
+
+ debug("");
+ debug("This test vefify the functionality of blitframebuffer from or to a multisampled srgb image.");
+
+ // Read buffer can have multisampled srgb image, but draw buffers can not.
+ var rb0 = gl.createRenderbuffer();
+ var fb0 = gl.createFramebuffer();
+ var rb1 = gl.createRenderbuffer();
+ var fb1 = gl.createFramebuffer();
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, gl.SAMPLES);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb0);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.SRGB8_ALPHA8, width, height);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb0);
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb1);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, width, height);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb1);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer from multisampled srgb image should succeed.");
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb1);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.SRGB8_ALPHA8, width, height);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb1);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer to a multisampled srgb image should generate INVALID_OPERATION.");
+
+ // BlitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same.
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb1);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, width, height);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb1);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 2, 2, 4, 4, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same.");
+
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 4, 4, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same.");
+
+ // BlitFramebuffer from a multisampled srgb image, the format/type must be exactly the same. So blit from a multisampled srgb image to a linear image is invalid.
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer from a multisampled srgb image, the format/type must be exactly the same.");
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.deleteRenderbuffer(rb0);
+ gl.deleteRenderbuffer(rb1);
+ gl.deleteTexture(tex);
+ gl.deleteFramebuffer(fb0);
+ gl.deleteFramebuffer(fb1);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-unaffected-by-colormask.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-unaffected-by-colormask.html
new file mode 100644
index 0000000000..3d2d7f54bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/blitframebuffer-unaffected-by-colormask.html
@@ -0,0 +1,102 @@
+<!--
+Copyright (c) 2021 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>BlitFramebuffer Should Be Unaffected by ColorMask</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description("This test verifies that the blitFramebuffer is unaffected by the colorMask state.");
+
+debug('Regression test for <a href="https://crbug.com/1257769">https://crbug.com/1257769</a> and <a href="https://bugs.webkit.org/show_bug.cgi?id=220129">https://bugs.webkit.org/show_bug.cgi?id=220129</a>');
+
+function allocateTexture(gl, size) {
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ return tex;
+}
+
+function allocateFBO(gl, tex) {
+ const fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ return fbo;
+}
+
+function run() {
+ const gl = wtu.create3DContext("canvas", { antialias: false }, 2);
+
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+ return;
+ }
+
+ const size = 8;
+
+ testPassed("WebGL context exists");
+
+ // Allocate source and destination textures and framebuffer objects.
+ const sourceTex = allocateTexture(gl, size);
+ const sourceFBO = allocateFBO(gl, sourceTex);
+
+ const destTex = allocateTexture(gl, size);
+ const destFBO = allocateFBO(gl, destTex);
+
+ const program = wtu.setupColorQuad(gl);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, sourceFBO);
+
+ // Clear the source framebuffer to red.
+ gl.clearColor(1, 0, 0, 1);
+ gl.colorMask(true, true, true, true);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw a transparent green quad.
+ gl.useProgram(program);
+ wtu.drawFloatColorQuad(gl, [ 0, 255, 0, 0 ]);
+
+ // Clear the alpha channel.
+ gl.colorMask(false, false, false, true);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // At this point, even setting the colorMask to all-true won't
+ // work around the bug, since that state is latched inside ANGLE
+ // only during draws / clears.
+
+ // Blit source to dest.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, destFBO);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, destFBO);
+
+ // Note that the on-screen canvas is always black - we don't blit the result to it.
+ wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "should be green", 1);
+ finishTest();
+}
+
+var successfullyParsed = true;
+
+requestAnimationFrame(run);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/builtin-vert-attribs.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/builtin-vert-attribs.html
new file mode 100644
index 0000000000..cc64c9034b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/builtin-vert-attribs.html
@@ -0,0 +1,408 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<link rel=stylesheet href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id=e_canvas width=1 height=1 style="width: 100px; height: 100px;"></canvas>
+<div id=description></div>
+<div id=console></div>
+<script>
+"use strict";
+description('gl_VertexID and gl_InstanceID should behave as per spec.');
+
+//
+
+/*
+So what are gl_VertexID and gl_InstanceID supposed to do?
+In ES 3.0 and GL 4.1 (Core), this is all we get:
+
+# ES 3.0
+
+> (p78) gl_VertexID holds the integer index i implicitly passed by DrawArrays or
+> one of the other drawing commands defined in section 2.9.3. The value of
+> gl_VertexID is defined if and only if all enabled vertex arrays have non-zero buffer
+> object bindings.
+> gl_InstanceID holds the integer instance number of the current primitive in
+> an instanced draw call (see section 2.9.3).
+
+
+# GL 4.1 (Core)
+
+> (p102) gl_VertexID holds the integer index i implicitly passed by DrawArrays or
+> one of the other drawing commands defined in section 2.8.3.
+> gl_InstanceID holds the integer index of the current primitive in an
+> instanced draw call (see section 2.8.3).
+
+
+# ES 3.1
+
+ES 3.1 retains the wording from ES 3.0, but adds the following clarifications:
+
+gl_VertexID:
+> (p252) The index of any element transferred to the GL by DrawArraysOneInstance
+> is referred to as its vertex ID, and may be read by a vertex shader as gl_VertexID.
+> The vertex ID of the ith element transferred is first + i.
+
+> (p254) The index of any element transferred to the GL by
+> DrawElementsOneInstance is referred to as its vertex ID, and may be read by a vertex shader as
+> gl_VertexID. If no element array buffer is bound, the vertex ID of the ith element
+> transferred is indices[i] + basevertex. Otherwise, the vertex ID of the ith
+> element transferred is the sum of basevertex and the value stored in the currently
+> bound element array buffer at offset indices + i.
+
+gl_InstanceID
+> (p255) If an enabled vertex attribute array is instanced (it has a non-zero divisor as
+> specified by VertexAttribDivisor), the element index that is transferred to the GL,
+> for all vertices, is given by
+> `floor(instance / divisor) + baseinstance`
+
+
+# Errata
+
+Drivers generally do implement the ES 3.1 behavior.
+A notable exception is Mac's legacy GL (4.1) driver which has two bugs here.
+(Both ANGLE-on-Metal and the system M1+ GL driver seem correct though)
+
+## gl_InstanceID random for DrawArrays calls
+Use ERRATA.IGNORE_GL_INSTANCE_ID to cause these tests to pass.
+
+## Adds `first` to user-attrib instanced fetch ids in DrawArrays calls.
+Use ERRATA.FIRST_ADDS_TO_INSTANCE to cause these tests to pass.
+*/
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext('e_canvas');
+
+const ERRATA = {};
+//ERRATA.IGNORE_GL_INSTANCE_ID = true; // Chrome on ANGLE-on-Mac-GL needs this.
+//ERRATA.FIRST_ADDS_TO_INSTANCE = true; // Firefox with MOZ_WEBGL_WORKAROUND_FIRST_AFFECTS_INSTANCE_ID=0 would need this.
+
+debug(`ERRATA: ${JSON.stringify(ERRATA)}`);
+
+function make_vs_point(vid, iid) {
+ return `\
+ #version 300 es
+
+ ${vid.name == 'gl_VertexID' ? '// ' : ''}layout(location=${vid.loc}) in highp int ${vid.name};
+ ${iid.name == 'gl_InstanceID' ? '// ' :''}layout(location=${iid.loc}) in highp int ${iid.name};
+ out vec4 v_color;
+
+ void main() {
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ v_color = vec4(1.0, float(${vid.name}) / 255.0, float(${iid.name}) / 255.0, 1.0);
+#if ${(iid.name == 'gl_InstanceID' && ERRATA.IGNORE_GL_INSTANCE_ID)|0}
+ v_color.b = 0.0;
+#endif
+ }`;
+}
+
+function make_vs_tri(vid, iid) {
+ return `\
+ #version 300 es
+
+ ${vid.name == 'gl_VertexID' ? '// ' : ''}layout(location=${vid.loc}) in highp int ${vid.name};
+ ${iid.name == 'gl_InstanceID' ? '// ' :''}layout(location=${iid.loc}) in highp int ${iid.name};
+ out vec4 v_color;
+
+ void main() {
+ int prim_vert_id = ${vid.name} % 3;
+ int flat_vert_id = ${vid.name} - prim_vert_id + 2;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position.x = (prim_vert_id == 1) ? 2.0 : -1.0;
+ gl_Position.y = (prim_vert_id == 2) ? 2.0 : -1.0;
+ v_color = vec4(1.0, float(flat_vert_id) / 255.0, float(${iid.name}) / 255.0, 1.0);
+#if ${(iid.name == 'gl_InstanceID' && ERRATA.IGNORE_GL_INSTANCE_ID)|0}
+ v_color.b = 0.0;
+#endif
+ }`;
+}
+
+const FS = `\
+ #version 300 es
+ precision mediump float;
+
+ in vec4 v_color;
+ out vec4 o_color;
+
+ void main() {
+ o_color = v_color;
+ }
+`;
+
+
+function crossCombine(...args) {
+ function crossCombine2(listA, listB) {
+ const listC = [];
+ for (const a of listA) {
+ for (const b of listB) {
+ const c = Object.assign({}, a, b);
+ listC.push(c);
+ }
+ }
+ return listC;
+ }
+
+ let res = [{}];
+ while (args.length) {
+ const next = args.shift();
+ next[0].defined;
+ res = crossCombine2(res, next);
+ }
+ return res;
+}
+
+/// makeCombiner('foo', [5, 3]) -> [{foo: 5}, {foo: 3}]
+function makeCombiner(key, vals) {
+ const ret = [];
+ for (const val of vals) {
+ const cur = {};
+ cur[key] = val;
+ ret.push(cur);
+ }
+ return ret;
+}
+
+debug('Draw a point with a shader that takes no attributes and verify it fills the whole canvas.');
+
+
+let TESTS = [
+ makeCombiner('vid', [
+ {name: 'a_VertexID', loc:0},
+ {name: 'a_VertexID', loc:2}, // Test 2, so that we're not only testing 0.
+ {name: 'gl_VertexID', loc:-1},
+ {name: 'gl_VertexID', loc:0}, // Enable a vertex array, despite not using it.
+ {name: 'gl_VertexID', loc:2}, // Enable a vertex array, despite not using it.
+ ]),
+ makeCombiner('iid', [
+ {name: 'a_InstanceID', loc:1},
+ {name: 'gl_InstanceID', loc:-1},
+ {name: 'gl_InstanceID', loc:1}, // Enable a vertex array, despite not using it.
+ ]),
+ makeCombiner('separate_vbufs', [true, false]),
+];
+//console.log('a', {TESTS});
+TESTS = crossCombine(...TESTS);
+//console.log('b', {TESTS});
+
+
+let vdata = new Int32Array(1000);
+vdata = vdata.map((v,i) => i);
+const vbuf = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
+gl.bufferData(gl.ARRAY_BUFFER, vdata, gl.STATIC_DRAW);
+
+
+const vbuf2 = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vbuf2);
+gl.bufferData(gl.ARRAY_BUFFER, vdata, gl.STATIC_DRAW);
+
+
+let index_data = new Uint32Array(1000);
+index_data = index_data.map((x,i) => 10+i);
+const index_buffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, index_data, gl.STATIC_DRAW);
+
+
+gl.disable(gl.DEPTH_TEST);
+
+(async () => {
+ for (const desc of TESTS) {
+ await wtu.dispatchPromise(); // Yield, for responsiveness.
+ debug('');
+ debug('---------------------');
+ debug(`desc: ${JSON.stringify(desc)}`);
+
+ let fn = (vs) => {
+ //console.log({vs});
+ const prog = wtu.setupProgram(gl, [vs, FS]);
+
+ {
+ const WEBGL_debug_shaders = gl.getExtension('WEBGL_debug_shaders');
+ let i = -1;
+ for (const s of gl.getAttachedShaders(prog)) {
+ i += 1;
+ debug('');
+ debug(`shader[${i}] getShaderSource() -> `);
+ debug(gl.getShaderSource(s));
+ if (WEBGL_debug_shaders) {
+ debug(`shader[${i}] getTranslatedShaderSource() -> `);
+ debug(WEBGL_debug_shaders.getTranslatedShaderSource(s));
+ }
+ }
+ }
+ return prog;
+ };
+ const point_prog = fn(make_vs_point(desc.vid, desc.iid));
+ const tri_prog = fn(make_vs_tri(desc.vid, desc.iid));
+
+ // -
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ for (let i = 0; i <= 2; i++) {
+ gl.disableVertexAttribArray(i);
+ gl.vertexAttribPointer(i, 4, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(i, 0);
+ }
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
+ let loc = desc.vid.loc;
+ if (loc != -1) {
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribIPointer(loc, 1, gl.INT, 0, 0);
+ };
+
+ if (desc.separate_vbufs) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbuf2);
+ }
+ loc = desc.iid.loc;
+ if (loc != -1) {
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribIPointer(loc, 1, gl.INT, 0, 0);
+ gl.vertexAttribDivisor(loc, 1);
+ };
+
+ {
+ const err = gl.getError();
+ if (err) throw err; // Broken init.
+ }
+
+ // -
+
+ fn = (eval_str, expected_arr) => {
+ if (ERRATA.IGNORE_GL_INSTANCE_ID) {
+ if (desc.iid.name == 'gl_InstanceID') {
+ expected_arr = expected_arr.map(x => x);
+ expected_arr[2] = 0;
+ }
+ }
+
+ debug('');
+ //debug(`${eval_str} -> [${expected_arr.join(', ')}]`);
+ eval(eval_str);
+
+ const err = gl.getError();
+ if (err) throw err; // Broken subtest.
+
+ wtu.checkCanvas(gl, expected_arr, eval_str);
+ }
+
+ gl.useProgram(point_prog);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawArrays(gl.POINTS, 0, 0)`, [0, 0, 0, 0]);
+ fn(`gl.drawArrays(gl.POINTS, 0, 1)`, [255, 0, 0, 255]);
+ fn(`gl.drawArrays(gl.POINTS, 0, 2)`, [255, 1, 0, 255]);
+ if (ERRATA.FIRST_ADDS_TO_INSTANCE) {
+ fn(`gl.drawArrays(gl.POINTS, 100, 2)`, [255, 100+2-1, 100, 255]);
+ } else {
+ fn(`gl.drawArrays(gl.POINTS, 100, 2)`, [255, 100+2-1, 0, 255]);
+ }
+ fn(`gl.drawArrays(gl.POINTS, 0, 255)`, [255, 254, 0, 255]);
+ fn(`gl.drawArrays(gl.POINTS, 0, 256)`, [255, 255, 0, 255]);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 0, 1)`, [0, 0, 0, 0]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 1, 0)`, [0, 0, 0, 0]);
+
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 1, 1)`, [255, 0, 0, 255]);
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 2, 1)`, [255, 1, 0, 255]);
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 1, 2)`, [255, 0, 1, 255]);
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 2, 2)`, [255, 1, 1, 255]);
+ if (ERRATA.FIRST_ADDS_TO_INSTANCE) {
+ fn(`gl.drawArraysInstanced(gl.POINTS, 100, 2, 2)`, [255, 100+2-1, 101, 255]);
+ } else {
+ fn(`gl.drawArraysInstanced(gl.POINTS, 100, 2, 2)`, [255, 100+2-1, 1, 255]);
+ }
+ fn(`gl.drawArraysInstanced(gl.POINTS, 0, 255, 255)`, [255, 254, 254, 255]);
+
+ // -
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_INT, 4*0)`, [0, 0, 0, 0]);
+ fn(`gl.drawElements(gl.POINTS, 1, gl.UNSIGNED_INT, 4*0)`, [255, 10+0, 0, 255]);
+ fn(`gl.drawElements(gl.POINTS, 2, gl.UNSIGNED_INT, 4*0)`, [255, 10+1, 0, 255]);
+ fn(`gl.drawElements(gl.POINTS, 2, gl.UNSIGNED_INT, 4*100)`, [255, 100+10+1, 0, 255]);
+ fn(`gl.drawElements(gl.POINTS, 245, gl.UNSIGNED_INT, 4*0)`, [255, 10+244, 0, 255]);
+ fn(`gl.drawElements(gl.POINTS, 246, gl.UNSIGNED_INT, 4*0)`, [255, 10+245, 0, 255]);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 0, gl.UNSIGNED_INT, 4*0, 1)`, [0, 0, 0, 0]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 1, gl.UNSIGNED_INT, 4*0, 0)`, [0, 0, 0, 0]);
+
+ fn(`gl.drawElementsInstanced(gl.POINTS, 1, gl.UNSIGNED_INT, 4*0, 1)`, [255, 10+0, 0, 255]);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 2, gl.UNSIGNED_INT, 4*0, 1)`, [255, 10+1, 0, 255]);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 1, gl.UNSIGNED_INT, 4*0, 2)`, [255, 10+0, 1, 255]);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 2, gl.UNSIGNED_INT, 4*0, 2)`, [255, 10+1, 1, 255]);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 2, gl.UNSIGNED_INT, 4*100, 2)`, [255, 100+10+1, 1, 255]);
+ fn(`gl.drawElementsInstanced(gl.POINTS, 245, gl.UNSIGNED_INT, 4*0, 255)`, [255, 10+244, 254, 255]);
+
+ // -
+
+ gl.useProgram(tri_prog);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawArrays(gl.TRIANGLES, 0, 0*3)`, [0, 0, 0, 0]);
+ fn(`gl.drawArrays(gl.TRIANGLES, 0, 1*3)`, [255, 1*3-1, 0, 255]);
+ fn(`gl.drawArrays(gl.TRIANGLES, 0, 2*3)`, [255, 2*3-1, 0, 255]);
+ if (ERRATA.FIRST_ADDS_TO_INSTANCE) {
+ fn(`gl.drawArrays(gl.TRIANGLES, 90, 2*3)`, [255, 90+2*3-1, 90, 255]);
+ } else {
+ fn(`gl.drawArrays(gl.TRIANGLES, 90, 2*3)`, [255, 90+2*3-1, 0, 255]);
+ }
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 0, 0, 1)`, [0, 0, 0, 0]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 0, 1*3, 0)`, [0, 0, 0, 0]);
+
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 0, 1*3, 1)`, [255, 1*3-1, 0, 255]);
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 0, 2*3, 1)`, [255, 2*3-1, 0, 255]);
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 0, 1*3, 2)`, [255, 1*3-1, 1, 255]);
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 0, 2*3, 2)`, [255, 2*3-1, 1, 255]);
+ if (ERRATA.FIRST_ADDS_TO_INSTANCE) {
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 90, 2*3, 2)`, [255, 90+2*3-1, 91, 255]);
+ } else {
+ fn(`gl.drawArraysInstanced(gl.TRIANGLES, 90, 2*3, 2)`, [255, 90+2*3-1, 1, 255]);
+ }
+
+ // -
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawElements(gl.TRIANGLES, 0*3, gl.UNSIGNED_INT, 4*0)`, [0, 0, 0, 0]);
+ fn(`gl.drawElements(gl.TRIANGLES, 1*3, gl.UNSIGNED_INT, 4*0)`, [255, 10+1*3-1, 0, 255]);
+ fn(`gl.drawElements(gl.TRIANGLES, 2*3, gl.UNSIGNED_INT, 4*0)`, [255, 10+2*3-1, 0, 255]);
+ fn(`gl.drawElements(gl.TRIANGLES, 2*3, gl.UNSIGNED_INT, 4*100)`, [255, 100+10+2*3-1, 0, 255]);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 0*3, gl.UNSIGNED_INT, 4*0, 1)`, [0, 0, 0, 0]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 1*3, gl.UNSIGNED_INT, 4*0, 0)`, [0, 0, 0, 0]);
+
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 1*3, gl.UNSIGNED_INT, 4*0, 1)`, [255, 10+1*3-1, 0, 255]);
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 2*3, gl.UNSIGNED_INT, 4*0, 1)`, [255, 10+2*3-1, 0, 255]);
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 1*3, gl.UNSIGNED_INT, 4*0, 2)`, [255, 10+1*3-1, 1, 255]);
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 2*3, gl.UNSIGNED_INT, 4*0, 2)`, [255, 10+2*3-1, 1, 255]);
+ fn(`gl.drawElementsInstanced(gl.TRIANGLES, 2*3, gl.UNSIGNED_INT, 4*100, 2)`, [255, 100+10+2*3-1, 1, 255]);
+ }
+
+ finishTest();
+})();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/canvas-resizing-with-pbo-bound.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/canvas-resizing-with-pbo-bound.html
new file mode 100644
index 0000000000..713c88f515
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/canvas-resizing-with-pbo-bound.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Resizing With PBO Bound Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas1" style="width: 256px; height: 256px;"> </canvas>
+<canvas id="canvas2" style="width: 256px; height: 256px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+
+description("Verifies that resizing the canvas (recreating the backing framebuffer) works correctly while a PBO is bound.");
+
+debug("");
+debug("Regression test for Chromium <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=644572'>Issue 644572</a>");
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas;
+var largeSize = 256;
+var smallSize = 128;
+var currentSize;
+var gl;
+var numFrames = 0;
+var testNumber = 0;
+var pbo;
+
+function nextTest() {
+ ++testNumber;
+ numFrames = 0;
+ currentSize = largeSize;
+ if (testNumber > 2) {
+ finishTest();
+ return;
+ }
+
+ canvas = document.getElementById("canvas" + testNumber);
+ canvas.width = currentSize;
+ canvas.height = currentSize;
+ var usePreserveDrawingBuffer = (testNumber == 1) ? true : false;
+ debug("Testing preserveDrawingBuffer = " + usePreserveDrawingBuffer);
+ gl = wtu.create3DContext(canvas, { preserveDrawingBuffer: usePreserveDrawingBuffer }, 2);
+
+ if (!gl) {
+ testFailed("context does not exist");
+
+ wtu.requestAnimFrame(nextTest);
+ } else {
+ testPassed("context exists");
+
+ gl.clearColor(0, 1, 0, 1);
+
+ pbo = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo);
+
+ wtu.requestAnimFrame(render);
+ }
+}
+
+function render() {
+ if (++numFrames < 4) {
+ if (currentSize == largeSize) {
+ canvas.height = smallSize;
+ currentSize = smallSize;
+ } else {
+ canvas.height = largeSize;
+ currentSize = largeSize;
+ }
+ }
+
+ gl.viewport(0, 0, largeSize, currentSize);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Check the four corners
+ var green = [ 0, 255, 0, 255 ];
+ var inset = 3;
+ wtu.checkCanvasRect(gl, inset, inset, 1, 1, green, "lower left should be green", 1);
+ wtu.checkCanvasRect(gl, largeSize - inset, inset, 1, 1, green, "lower right should be green", 1);
+ wtu.checkCanvasRect(gl, inset, currentSize - inset, 1, 1, green, "upper left should be green", 1);
+ wtu.checkCanvasRect(gl, largeSize - inset, currentSize - inset, 1, 1, green, "upper right should be green", 1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error");
+ if (gl.getParameter(gl.PIXEL_UNPACK_BUFFER_BINDING) != pbo) {
+ testFailed("Pixel unpack buffer binding was lost");
+ }
+
+ if (numFrames < 4) {
+ wtu.requestAnimFrame(render);
+ } else {
+ wtu.requestAnimFrame(nextTest);
+ }
+}
+
+wtu.requestAnimFrame(nextTest);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-func-buffer-type-match.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-func-buffer-type-match.html
new file mode 100644
index 0000000000..8054d74df2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-func-buffer-type-match.html
@@ -0,0 +1,145 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test clear and clearBuffer functions have to match fbo's buffer format</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script>
+"use strict";
+description("This tests the WebGL2 specific constraint that clear or clearBuffer* functions have to be compatible with fbo's buffer format");
+
+var setupRenderbuffer = function(attachment, format) {
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, canvas.width, canvas.height);
+ return renderbuffer;
+}
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ debug("");
+ debug("Signed integer buffer");
+
+ var colorbuffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0, gl.RGBA8);
+ var colorbuffer1 = setupRenderbuffer(gl.COLOR_ATTACHMENT1, gl.RGBA32I);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clear and INT buffer");
+
+ gl.clearBufferfv(gl.COLOR, 1, new Float32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferfv and INT buffer");
+
+ gl.clearBufferuiv(gl.COLOR, 1, new Uint32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferuiv and INT buffer");
+
+ debug("Set up draw buffer so INT buffer is set to NONE");
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clear and INT buffer is NONE");
+
+ gl.clearBufferfv(gl.COLOR, 1, new Float32Array(4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBufferfv and INT buffer is NONE");
+
+ gl.clearBufferuiv(gl.COLOR, 0, new Uint32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferuiv and float buffer");
+
+ debug("");
+ debug("Unsigned integer buffer");
+
+ colorbuffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0, gl.RGBA32UI);
+ colorbuffer1 = setupRenderbuffer(gl.COLOR_ATTACHMENT1, gl.RGBA8);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clear and UINT buffer");
+
+ gl.clearBufferfv(gl.COLOR, 0, new Float32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferfv and UINT buffer");
+
+ gl.clearBufferiv(gl.COLOR, 0, new Int32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferiv and UINT buffer");
+
+ debug("Set up draw buffer so INT buffer is set to NONE");
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clear and UINT buffer is NONE");
+
+ gl.clearBufferfv(gl.COLOR, 0, new Float32Array(4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBufferfv and UINT buffer is NONE");
+
+ gl.clearBufferiv(gl.COLOR, 1, new Int32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferiv and float buffer");
+
+ debug("");
+ debug("Float buffer");
+
+ colorbuffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0, gl.RGBA8);
+ var numAttachments = 1;
+ var ext = gl.getExtension("EXT_color_buffer_float");
+ var bufferType = "float buffer";
+ if (ext) {
+ debug("EXT_color_buffer_float is available: testing RGBA8 + RGBA32F");
+ colorbuffer1 = setupRenderbuffer(gl.COLOR_ATTACHMENT1, gl.RGBA32F);
+ ++numAttachments;
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ } else {
+ debug("EXT_color_buffer_float is unavailable: testing RGBA8");
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ bufferType = "RGBA8 buffer";
+ }
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clear and " + bufferType);
+
+ for (var ii = 0; ii < numAttachments; ++ii) {
+ gl.clearBufferfv(gl.COLOR, ii, new Float32Array(4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBufferfv and " + bufferType);
+
+ gl.clearBufferiv(gl.COLOR, ii, new Int32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferiv and " + bufferType);
+
+ gl.clearBufferuiv(gl.COLOR, ii, new Uint32Array(4));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "clearBufferuiv and " + bufferType);
+ }
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteRenderbuffer(colorbuffer);
+ gl.deleteRenderbuffer(colorbuffer1);
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-srgb-color-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-srgb-color-buffer.html
new file mode 100644
index 0000000000..b88518635e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clear-srgb-color-buffer.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Clear sRGB Color Buffer</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of clearing srgb color buffer.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var tex = gl.createTexture();
+var fbo = gl.createFramebuffer();
+var size = 8;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Create a srgb color buffer
+ init();
+
+ clear_srgb_color_buffer(0);
+ clear_srgb_color_buffer(1);
+}
+
+function init() {
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ } else {
+ testPassed("framebuffer complete!");
+ }
+}
+
+function clear_srgb_color_buffer(iter) {
+ debug("");
+ debug("Clear sRGB color buffer through glClear or glClearBufferfv");
+
+ var color = [0x33, 0x88, 0xbb, 0xff];
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ if (iter == 0) {
+ gl.clearColor(color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ } else {
+ var data = new Float32Array([color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255]);
+ gl.clearBufferfv(gl.COLOR, 0, data);
+ }
+
+ var color_ref = wtu.linearToSRGB(color);
+ var tolerance = 3;
+ var msg = "";
+ wtu.checkCanvasRect(gl, 0, 0, size, size, color_ref, msg, tolerance);
+}
+
+gl.bindTexture(gl.TEXTURE_2D, null);
+gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+gl.deleteTexture(tex);
+gl.deleteFramebuffer(fbo);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html
new file mode 100644
index 0000000000..051066c8ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html
@@ -0,0 +1,216 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test clearBuffer with drawing</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body onload="runTest()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="64" height="64" style="position:fixed;left:0;top:0"> </canvas>
+<script>
+"use strict";
+description("This tests the operation of clearBuffer followed by a draw call.");
+
+debug("Verifies that these combined with preserveDrawingBuffer's implicit clears work properly together.");
+debug("Regression test for <a href='http://crbug.com/828262'>Chromium bug 828262</a>.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl;
+var testIndex = 0;
+var iterations = 0;
+var maxIterations = 10;
+var prog;
+var tests;
+var stage = 0;
+var blackUint8 = [0, 0, 0, 255];
+var redFloat = [1.0, 0.0, 0.0, 0.0];
+var redUint8 = [255, 0, 0, 255];
+var greenFloat = [0.0, 1.0, 0.0, 0.0];
+var greenUint8 = [0, 255, 0, 255];
+
+function verifyOnePixel(kind, x, y, readFormat, readType, arrayType, expectedColor) {
+ var buffer = new arrayType(4);
+ gl.readPixels(Math.floor(x), Math.floor(y), 1, 1, readFormat, readType, buffer);
+ if (buffer[0] == expectedColor[0] &&
+ buffer[1] == expectedColor[1] &&
+ buffer[2] == expectedColor[2] &&
+ buffer[3] == expectedColor[3]) {
+ testPassed(kind + " succeeded");
+ } else {
+ testFailed(kind + " failed. Expected: " + expectedColor + ", got: " + buffer);
+ }
+}
+
+function testClearBufferAndDraw(test) {
+ gl.stencilFunc(gl.EQUAL, 0, 0xFF);
+ test['clear']();
+ wtu.setFloatDrawColor(gl, greenFloat);
+ wtu.drawUnitQuad(gl);
+ // Back buffer has no alpha channel.
+ let readFormat = gl.RGBA;
+ let readType = gl.UNSIGNED_BYTE;
+ if (stage == 2) {
+ verifyOnePixel("Clearing outside scissor",63, 63, readFormat, readType, Uint8Array, blackUint8);
+ verifyOnePixel("Drawing outside scissor", 40, 40, readFormat, readType, Uint8Array, blackUint8);
+ }
+ verifyOnePixel("Clearing", 0, 0, readFormat, readType, Uint8Array, test['bgColor']);
+ verifyOnePixel("Drawing", 32, 32, readFormat, readType, Uint8Array, test['drawColor']);
+}
+
+function runNextTest() {
+ if (testIndex >= tests.length) {
+ // Restore after the last clearBufferiv test
+ gl.enable(gl.DEPTH_TEST);
+ if (stage == 0) {
+ debug('');
+ debug('Enabling full-canvas scissor');
+ gl.enable(gl.SCISSOR_TEST);
+ } else if (stage == 1) {
+ debug('');
+ debug('Limiting scissor rect');
+ gl.scissor(0, 0, 33, 33);
+ } else if (stage == 2) {
+ finishTest();
+ return;
+ }
+ testIndex = 0;
+ stage++;
+ }
+
+
+ let test = tests[testIndex];
+ if (iterations == 0) {
+ debug('');
+ debug('Testing: ' + test['desc'])
+ }
+ testClearBufferAndDraw(test);
+
+ if (++iterations == maxIterations) {
+ iterations = 0;
+ ++testIndex;
+
+ // Clear to yellow between the tests to ensure that
+ // subsequent tests do not rely on past results.
+ gl.clearColor(1.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+
+ wtu.waitForComposite(runNextTest);
+}
+
+function runTest() {
+ gl = wtu.create3DContext(canvas, { alpha: false, stencil: true }, 2);
+
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ } else {
+ testPassed("context exists");
+ }
+
+ prog = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
+
+ tests = [
+ {
+ desc: 'Implicit clear',
+ clear: function() {},
+ bgColor: blackUint8,
+ // The implicit clear clears depth to 1.0, and since the quad is
+ // drawn at a depth of 0.0, it's always discarded.
+ drawColor: blackUint8,
+ },
+ {
+ desc: 'clearBufferfi only',
+ clear: function() {
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 1);
+ gl.stencilFunc(gl.EQUAL, 1, 0xFF);
+ },
+ bgColor: blackUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBufferfv only',
+ clear: function() {
+ gl.clearBufferfv(gl.DEPTH, 0, [0.0]);
+ },
+ bgColor: blackUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBufferfv and clear',
+ clear: function() {
+ gl.clearBufferfv(gl.COLOR, 0, redFloat);
+ gl.clearDepth(0.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ },
+ bgColor: redUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBufferfv (no-op) and clear',
+ clear: function() {
+ gl.clearBufferfv(gl.COLOR, 1, greenFloat);
+ gl.clearDepth(0.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ },
+ bgColor: blackUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBuffer{fv} and {fi}',
+ clear: function() {
+ gl.clearBufferfv(gl.COLOR, 0, redFloat);
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 2);
+ gl.stencilFunc(gl.EQUAL, 2, 0xFF);
+ },
+ bgColor: redUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBufferiv only',
+ clear: function() {
+ gl.disable(gl.DEPTH_TEST);
+ gl.clearBufferiv(gl.STENCIL, 0, [3]);
+ gl.stencilFunc(gl.EQUAL, 3, 0xFF);
+ },
+ bgColor: blackUint8,
+ drawColor: greenUint8,
+ },
+ ];
+
+ // Clear canvas to something other than black to start.
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.enable(gl.DEPTH_TEST);
+ // Unreal Engine's depth test is reversed from the
+ // default. Including the clear of the depth buffer in this test
+ // case highlights the rendering error more clearly, since neither
+ // the background nor any rendered object show up.
+ gl.depthFunc(gl.GEQUAL);
+
+ gl.enable(gl.STENCIL_TEST);
+
+ // Must run in a requestAnimationFrame loop to provoke implicit
+ // clears of the canvas.
+ wtu.waitForComposite(runNextTest);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-sub-source.html
new file mode 100644
index 0000000000..616d2bda4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-sub-source.html
@@ -0,0 +1,110 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test clearBuffer functions with optional srcOffset argument</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script>
+"use strict";
+description("This tests clearBuffer* functions with optional srcOffset argument");
+
+function verifyOnePixel(readFormat, readType, arrayType, expectedColor) {
+ var buffer = new arrayType(4);
+ gl.readPixels(0, 0, 1, 1, readFormat, readType, buffer);
+ if (buffer[0] == expectedColor[0] &&
+ buffer[1] == expectedColor[1] &&
+ buffer[2] == expectedColor[2] &&
+ buffer[3] == expectedColor[3]) {
+ testPassed("clearBuffer sets the renderbuffer with the correct data");
+ } else {
+ testFailed("clearBuffer fails to work. Expected: " + expectedColor + ", got: " + buffer);
+ }
+}
+
+function testClearBuffer(func, format, arrayType, readFormat, readType) {
+ debug("");
+ debug("Testing " + func);
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, canvas.width, canvas.height);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ var srcData = new arrayType([1, 2, 3, 4, 5, 6]);
+ gl[func](gl.COLOR, 0, srcData);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBuffer with no srcOffset should succeed");
+ verifyOnePixel(readFormat, readType, arrayType, [1,2,3,4]);
+
+ gl[func](gl.COLOR, 0, srcData, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBuffer with srcOffset = 0 should succeed");
+ verifyOnePixel(readFormat, readType, arrayType, [1,2,3,4]);
+
+ gl[func](gl.COLOR, 0, srcData, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBuffer with srcOffset = 2 should succeed");
+ verifyOnePixel(readFormat, readType, arrayType, [3,4, 5, 6]);
+
+ gl[func](gl.COLOR, 0, srcData, 4);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "clearBuffer with srcOffset = 4 should fail: out of bounds");
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteRenderbuffer(renderbuffer);
+}
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var testCases = [
+ {
+ func: "clearBufferiv", format: gl.RGBA32I, arrayType: Int32Array,
+ readFormat: gl.RGBA_INTEGER, readType: gl.INT,
+ },
+ {
+ func: "clearBufferuiv", format: gl.RGBA32UI, arrayType: Uint32Array,
+ readFormat: gl.RGBA_INTEGER, readType: gl.UNSIGNED_INT,
+ },
+ {
+ func: "clearBufferfv", format: gl.RGBA32F, arrayType: Float32Array,
+ readFormat: gl.RGBA, readType: gl.FLOAT,
+ extension: "EXT_color_buffer_float",
+ },
+ ];
+
+ for (var tt = 0; tt < testCases.length; ++tt) {
+ var test = testCases[tt];
+ if (test.extension && !gl.getExtension(test.extension))
+ continue;
+ testClearBuffer(test.func, test.format, test.arrayType, test.readFormat, test.readType);
+ }
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbufferfv-with-alpha-false.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbufferfv-with-alpha-false.html
new file mode 100644
index 0000000000..a50b6f8e2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbufferfv-with-alpha-false.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test clearBufferfv with alpha:false canvas</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script>
+"use strict";
+description("This tests the operation of clearBufferfv with the back buffer of an alpha:false canvas.");
+
+function verifyOnePixel(readFormat, readType, arrayType, expectedColor) {
+ var buffer = new arrayType(4);
+ gl.readPixels(0, 0, 1, 1, readFormat, readType, buffer);
+ if (buffer[0] == expectedColor[0] &&
+ buffer[1] == expectedColor[1] &&
+ buffer[2] == expectedColor[2] &&
+ buffer[3] == expectedColor[3]) {
+ testPassed("clearBufferfv set the color buffer to the correct value");
+ } else {
+ testFailed("clearBufferfv failed to work. Expected: " + expectedColor + ", got: " + buffer);
+ }
+}
+
+function testClearBuffer(func, format, arrayType, readFormat, readType, readArrayType) {
+ debug("");
+ debug("Testing " + func);
+
+ var srcData = new arrayType([0, 1, 0, 0]);
+ gl[func](gl.COLOR, 0, srcData);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearBuffer with no srcOffset should succeed");
+ // Back buffer has no alpha channel
+ verifyOnePixel(readFormat, readType, Uint8Array, [0, 255, 0, 255]);
+}
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, { alpha:false }, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var testCases = [
+ {
+ func: "clearBufferfv", format: gl.RGBA, arrayType: Float32Array,
+ readFormat: gl.RGBA, readType: gl.UNSIGNED_BYTE, readArrayType: Uint8Array,
+ },
+ ];
+
+ for (var tt = 0; tt < testCases.length; ++tt) {
+ var test = testCases[tt];
+ if (test.extension && !gl.getExtension(test.extension))
+ continue;
+ testClearBuffer(test.func, test.format, test.arrayType,
+ test.readFormat, test.readType, test.readArrayType);
+ }
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clipping-wide-points.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clipping-wide-points.html
new file mode 100644
index 0000000000..ab2457a6a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clipping-wide-points.html
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clipping wide points test</title>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="1" height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/clipping-wide-points.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/depth-stencil-feedback-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/depth-stencil-feedback-loop.html
new file mode 100644
index 0000000000..e7678017ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/depth-stencil-feedback-loop.html
@@ -0,0 +1,165 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Rendering and Sampling Feedback Loop Tests for Depth/Stencil Buffer</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in highp vec4 aPosition;
+in vec2 aTexCoord;
+out vec2 texCoord;
+void main() {
+ gl_Position = aPosition;
+ texCoord = aTexCoord;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform sampler2D tex;
+in vec2 texCoord;
+out vec4 oColor;
+void main() {
+ oColor = texture(tex, texCoord);
+}
+</script>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of rendering to the same texture where it samples from.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var width = 8;
+var height = 8;
+var tex0;
+var tex1;
+var tex2;
+var fbo;
+var program;
+var positionLoc;
+var texCoordLoc;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ init();
+ detect_depth_stencil_feedback_loop();
+ deinit();
+}
+
+function init() {
+ // Setup program
+ program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['aPosition', 'aTexCoord'], [0, 1]);
+ positionLoc = gl.getAttribLocation(program, "aPosition");
+ texCoordLoc = gl.getAttribLocation(program, "aTexCoord");
+ if (!program || positionLoc < 0 || texCoordLoc < 0) {
+ testFailed("Set up program failed");
+ return;
+ }
+ testPassed("Set up program succeeded");
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ gl.viewport(0, 0, width, height);
+
+ var texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+
+ // Create textures and allocate storage
+ tex0 = gl.createTexture();
+ tex1 = gl.createTexture();
+ tex2 = gl.createTexture();
+ wtu.fillTexture(gl, tex0, width, height, [0x0, 0xff, 0x0, 0xff], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ wtu.fillTexture(gl, tex1, width, height, [0x80], 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, gl.DEPTH_COMPONENT16);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ wtu.fillTexture(gl, tex2, width, height, [0x40], 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, gl.DEPTH24_STENCIL8);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Succeed to create textures.");
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex0, 0);
+}
+
+function detect_depth_stencil_feedback_loop() {
+ // Test rendering and sampling feedback loop for depth buffer
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, tex1, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+ gl.enable(gl.DEPTH_TEST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The test samples from a image. The same image is used as depth buffer during rendering.");
+
+ gl.depthMask(gl.FALSE);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The test samples from a image. The same image is used as depth buffer. A feedback loop is formed regardless of the status of depth mask.");
+
+ gl.depthMask(gl.TRUE);
+ gl.disable(gl.DEPTH_TEST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The test samples from a image. The same image is used as depth buffer. A feedback loop is formed regardless of whether the depth test is enabled.");
+
+ // Test rendering and sampling feedback loop for stencil buffer
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, null, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex2, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ gl.enable(gl.STENCIL_TEST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The test samples from a image. The same image is used as stencil buffer during rendering.");
+
+ gl.stencilMask(0x0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The test sampls from a image. The same image is used as stencil buffer. A feedback loop is formed regardless of the status of stencil mask.");
+
+ gl.stencilMask(0xffff);
+ gl.disable(gl.STENCIL_TEST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "The test samples from a image. The same image is used as stencil buffer. A feedback loop is formed regardless of whether the stencil test is enabled.");
+}
+
+function deinit() {
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteTexture(tex0);
+ gl.deleteTexture(tex1);
+ gl.deleteTexture(tex2);
+ gl.deleteFramebuffer(fbo);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-dirty-state-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-dirty-state-bug.html
new file mode 100644
index 0000000000..2b54d4c255
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-dirty-state-bug.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Draw Buffers Dirty State Bug Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(1, 0, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies a bug in draw buffers dirty state management in Chrome (crbug.com/678153).");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runTest();
+
+ debug("");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runTest() {
+ debug("");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position"]);
+ wtu.setupUnitQuad(gl);
+
+ var width = 2, height = 2;
+
+ var colorTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, colorTex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var depthTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, depthTex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT24, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup should cause no GL errors");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Clear and draw should cause no GL errors");
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [255, 0, 0, 255], "should be red");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Clear and draw should cause no GL errors");
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, null, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
+
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [255, 0, 0, 255], "should be red");
+
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Previously in Chrome, switching around the attachments on a framebuffer
+ // affected a DrawBuffers cache that was maintained properly during draw
+ // calls, but not clears.
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], "should be green");
+
+ gl.deleteProgram(program);
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(colorTex);
+ gl.deleteTexture(depthTex);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-driver-hang.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-driver-hang.html
new file mode 100644
index 0000000000..70a8360d6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-driver-hang.html
@@ -0,0 +1,187 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Draw Buffers Driver Hang Conformance Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(1, 0, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description("This is a regression test for a driver bug causing a hang in the driver and thereby the browser (crbug.com/696187).")
+
+debug("Thanks to Andre Weissflog (@FlohOfWoe / @floooh) for this test.");
+debug("If the bug exists, this test doesn't fail or time out per the harness; the browser basically hangs.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, { depth: true, stencil: true, alpha: false }, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runTest();
+}
+
+function runTest() {
+ // create a global VAO
+ let vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+
+ // create a 3 MSAA 'offscreen render targets', each consisting of:
+ // - 1 color texture which will hold the MSAA resolve result
+ // - 1 MSAA color renderbuffer
+ // plus one depth-stencil renderbuffer
+ let tex0 = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex0);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 0);
+ 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.RGBA8, 200, 200, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ let c_rb0 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, c_rb0);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 200, 200);
+ let ds_rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, ds_rb);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.DEPTH24_STENCIL8, 200, 200);
+
+ // 2nd offscreen render target
+ let tex1 = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 0);
+ 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.RGBA8, 200, 200, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ let c_rb1 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, c_rb1);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 200, 200);
+
+ // 3rd offscreen render target
+ let tex2 = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 0);
+ 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.RGBA8, 200, 200, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ let c_rb2 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, c_rb2);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 200, 200);
+
+ // an MRT framebuffer with the 3 MSAA renderbuffers and MSAA depth/stencil attachments
+ let mrt_fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, mrt_fb);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, c_rb0);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, c_rb1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.RENDERBUFFER, c_rb2);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, ds_rb);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, ds_rb);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // 3 'MSAA resolve framebuffers' which are the target for the MSAA-resolve-blit,
+ // with the 3 color textures as color attachments
+ let res_fb0 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, res_fb0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex0, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ let res_fb1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, res_fb1);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex1, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ let res_fb2 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, res_fb2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, tex2, 0);
+ let frameNumber = 0;
+
+ function draw() {
+ // draw one frame
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.viewport(0, 0, 1024, 768);
+
+ //--- BEGIN: comment out the block begin BEGIN/END to make the demo run
+ // clear the 3 MSAA offscreen color renderbuffers and depth/stencil renderbuffer
+ gl.bindFramebuffer(gl.FRAMEBUFFER, mrt_fb);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
+ gl.viewport(0, 0, 200, 200);
+ gl.depthMask(true);
+ gl.clearBufferfv(gl.COLOR, 0, [0.25,0.0,0.0,1.0]);
+ gl.clearBufferfv(gl.COLOR, 1, [0.0,0.25,0.0,1.0]);
+ gl.clearBufferfv(gl.COLOR, 2, [0.0,0.0,0.25,1.0]);
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ // the MSAA resolve operation
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, mrt_fb);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, res_fb0);
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ gl.blitFramebuffer(0, 0, 200, 200, 0, 0, 200, 200, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, res_fb1);
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ gl.blitFramebuffer(0, 0, 200, 200, 0, 0, 200, 200, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, res_fb2);
+ gl.readBuffer(gl.COLOR_ATTACHMENT2);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ gl.blitFramebuffer(0, 0, 200, 200, 0, 0, 200, 200, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+//--- END
+
+ // bind and clear the default framebuffer
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.viewport(0, 0, 1024, 768);
+ gl.clearColor(0.5, 0.5, 0.5, 1.0);
+ gl.clearDepth(1.0);
+ gl.clearStencil(0);
+ gl.clear(gl.COLOR_BUFFER_BIT|gl.STENCIL_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
+
+ if (++frameNumber < 10) {
+ requestAnimationFrame(draw);
+ } else {
+ finishTest();
+ }
+ }
+
+ // Start the rendering loop
+ draw();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-sparse-output-locations.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-sparse-output-locations.html
new file mode 100644
index 0000000000..4c679df6a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers-sparse-output-locations.html
@@ -0,0 +1,108 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests: Verify drawBuffers sparse output locations</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="1" height="1" style="width: 4px; height: 4px;"> </canvas>
+<div id="console"></div>
+
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+void main() {
+ gl_PointSize = 100.0;
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+// fragment shader only outputs to attachments 1 and 3
+precision highp float;
+layout(location = 1) out vec4 output1;
+layout(location = 3) out vec4 output2;
+void main()
+{
+ output1 = vec4(0.0, 1.0, 0.0, 1.0);
+ output2 = vec4(0.0, 0.0, 1.0, 1.0);
+}
+
+</script>
+<script>
+"use strict";
+description("This test verifies sparse output locations of fragment shaders render correctly");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ runTests();
+}
+
+function testAttachment(attachment, expected) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachment);
+ wtu.checkCanvas(gl, expected, `check COLOR_ATTACHMENT${attachment}`, 1);
+}
+
+function runTests() {
+ var program = wtu.setupProgram(gl, ["vs", "fs"]);
+ if (!program) {
+ testFailed("Set up program failed");
+ return;
+ }
+ gl.useProgram(program);
+
+ // create a framebuffer with 4 1x1 pixel color attachments
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ for (let i = 0; i < 4; ++i) {
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, tex, 0);
+ }
+
+ // draw only to the 1st and 3rd attachments
+ gl.drawBuffers([
+ gl.NONE,
+ gl.COLOR_ATTACHMENT1,
+ gl.NONE,
+ gl.COLOR_ATTACHMENT3,
+ ]);
+
+ // draw
+ gl.drawArrays(gl.POINTS, 0, 1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ // check we got the correct values
+ testAttachment(0, [0, 0, 0, 0]);
+ testAttachment(1, [0, 255, 0, 255]);
+ testAttachment(2, [0, 0, 0, 0]);
+ testAttachment(3, [0, 0, 255, 255]);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from testing");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers.html
new file mode 100644
index 0000000000..0e2ecb8f47
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-buffers.html
@@ -0,0 +1,598 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Draw Buffers Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/webgl-draw-buffers-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vshaderESSL3" type="x-shader/x-vertex">#version 300 es
+in vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+<script id="vshaderESSL1" type="x-shader/x-vertex">
+attribute vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform vec4 u_colors[$(numDrawingBuffers)];
+
+// Only one out variable - does not need explicit output layout (ESSL 3 section 4.3.8.2)
+out vec4 my_FragData[$(numDrawingBuffers)];
+void main() {
+$(assignUColorsToFragData)
+}
+</script>
+<script id="fshaderDiscard" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform vec4 u_colors[$(numDrawingBuffers)];
+uniform float u_zero;
+
+// Only one out variable - does not need explicit output layout (ESSL 3 section 4.3.8.2)
+out vec4 my_FragData[$(numDrawingBuffers)];
+void main() {
+$(assignUColorsToFragData)
+ if (u_zero < 1.0) {
+ discard;
+ }
+}
+</script>
+<script id="fshaderRed" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = vec4(1, 0, 0, 1);
+}
+</script>
+<script id="fshaderBlueESSL1" type="x-shader/x-fragment">
+precision mediump float;
+
+void main() {
+ gl_FragColor = vec4(0, 0, 1, 1);
+}
+</script>
+<script id="fshaderBuiltInConstEnabled" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+void main() {
+ my_FragColor = (gl_MaxDrawBuffers == $(numDrawingBuffers)) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of Multiple Render Targets.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var drawBuffersUtils;
+let fb;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ drawBuffersUtils = WebGLDrawBuffersUtils(gl);
+
+ if (testParameters()) {
+ runShadersTest();
+ runAttachmentTest();
+ runDrawTests();
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function createDrawBuffersProgram(scriptId, sub) {
+ var fsource = wtu.getScript(scriptId);
+ fsource = wtu.replaceParams(fsource, sub);
+ return wtu.setupProgram(gl, ["vshaderESSL3", fsource], ["a_position"], undefined, true);
+}
+
+function runShadersTest() {
+ debug("");
+ debug("test shaders");
+
+ var sub = {numDrawingBuffers: gl.getParameter(gl.MAX_DRAW_BUFFERS)};
+ var program = createDrawBuffersProgram("fshaderBuiltInConstEnabled", sub);
+ wtu.setupUnitQuad(gl);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+ gl.deleteProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function makeArray(size, value) {
+ var array = []
+ for (var ii = 0; ii < size; ++ii) {
+ array.push(value);
+ }
+ return array;
+}
+
+function runAttachmentTest() {
+ debug("");
+ debug("test attachment enabled");
+
+ var maxDrawingBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
+ var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+
+ var tex = gl.createTexture();
+ fb = gl.createFramebuffer();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachments, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "should not be able to attach pass the max attachment point: gl.COLOR_ATTACHMENT0 + " + maxColorAttachments);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachments - 1, gl.TEXTURE_2D, tex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to attach to the max attachment point: gl.COLOR_ATTACHMENT0 + " + (maxColorAttachments - 1));
+ gl.drawBuffers(makeArray(maxDrawingBuffers, gl.NONE));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with array NONE of size " + maxColorAttachments);
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(maxDrawingBuffers);
+ gl.drawBuffers(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with array attachments of size " + maxColorAttachments);
+ bufs[0] = gl.NONE;
+ gl.drawBuffers(bufs);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with mixed array attachments of size " + maxColorAttachments);
+ if (maxDrawingBuffers > 1) {
+ bufs[0] = gl.COLOR_ATTACHMENT1;
+ bufs[1] = gl.COLOR_ATTACHMENT0;
+ gl.drawBuffers(bufs);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be able to call drawBuffers with out of order attachments of size " + maxColorAttachments);
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(Math.floor(maxDrawingBuffers / 2));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with short array of attachments of size " + bufs.length);
+ }
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug("Testing drawBuffers and getParameter with bindFramebuffer, without drawing.");
+ fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0+1)", "gl.NONE");
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawBuffers([gl.NONE])");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.BACK");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.NONE");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawBuffers([gl.NONE,gl.COLOR_ATTACHMENT0+1])");
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.NONE");
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0+1)", "gl.COLOR_ATTACHMENT0+1");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawBuffers([gl.COLOR_ATTACHMENT0,gl.COLOR_ATTACHMENT0+1])");
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0+1)", "gl.COLOR_ATTACHMENT0+1");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fb)");
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.BACK");
+}
+
+function makeColorByIndex(index) {
+ var low = (index - 1) % 15 + 1;
+ var high = (index - 1) / 15;
+
+ var zeroOrOne = function(v) {
+ return v ? 1 : 0;
+ };
+
+ var oneOrTwo = function(v) {
+ return v ? 2 : 1;
+ }
+
+ var makeComponent = function(b0, b1, b2) {
+ return Math.floor(255 * zeroOrOne(b0) / oneOrTwo(b1) / oneOrTwo(b2));
+ };
+ return [
+ makeComponent(low & (1 << 0), high & (1 << 0), high & (1 << 4)),
+ makeComponent(low & (1 << 1), high & (1 << 1), high & (1 << 5)),
+ makeComponent(low & (1 << 2), high & (1 << 2), high & (1 << 6)),
+ makeComponent(low & (1 << 3), high & (1 << 3), high & (1 << 7)),
+ ];
+}
+
+function runDrawTests() {
+ debug("");
+ debug("--------- draw tests -----------");
+ var fb = gl.createFramebuffer();
+ var fb2 = gl.createFramebuffer();
+ var halfFB1 = gl.createFramebuffer();
+ var halfFB2 = gl.createFramebuffer();
+ var endsFB = gl.createFramebuffer();
+ var middleFB = gl.createFramebuffer();
+
+ var maxDrawingBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
+ var maxUsable = drawBuffersUtils.getMaxUsableColorAttachments();
+ var half = Math.floor(maxUsable / 2);
+ var bufs = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ var nones = makeArray(maxUsable, gl.NONE);
+
+ [fb, fb2, halfFB1, halfFB2, endsFB, middleFB].forEach(function(fbo) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.drawBuffers(bufs);
+ });
+
+ var checkProgram = wtu.setupTexturedQuad(gl);
+ var redProgram = wtu.setupProgram(gl, ["vshaderESSL3", "fshaderRed"], ["a_position"]);
+ var blueProgramESSL1 = wtu.setupProgram(gl, ["vshaderESSL1", "fshaderBlueESSL1"], ["a_position"]);
+
+ var assignCode = [];
+ for (var i = 0; i < maxDrawingBuffers; ++i) {
+ assignCode.push(" my_FragData[" + i + "] = u_colors[" + i + "];");
+ }
+
+ var drawProgram = createDrawBuffersProgram("fshader",
+ {numDrawingBuffers: maxDrawingBuffers, assignUColorsToFragData: assignCode.join("\n")});
+ var width = 64;
+ var height = 64;
+ var attachments = [];
+ // Makes 6 framebuffers.
+ // fb and fb2 have all the attachments.
+ // halfFB1 has the first half of the attachments
+ // halfFB2 has the second half of the attachments
+ // endsFB has the first and last attachments
+ // middleFB has all but the first and last attachments
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, ii < half ? halfFB1 : halfFB2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, (ii == 0 || ii == (maxUsable - 1)) ? endsFB : middleFB);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
+ var location = gl.getUniformLocation(drawProgram, "u_colors[" + ii + "]");
+ var color = makeColorByIndex(ii + 1);
+ var floatColor = [color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255];
+ gl.uniform4fv(location, floatColor);
+ attachments.push({
+ texture: tex,
+ color: color
+ });
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ var drawAndCheckAttachments = function(testFB, msg, testFn) {
+ debug("test clearing " + msg);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
+
+ attachments.forEach(function(attachment, index) {
+ debug("attachment: " + index + " = " + wtu.glEnumToString(gl, gl.getParameter(gl.DRAW_BUFFER0 + index)) +
+ ", " + wtu.glEnumToString(gl, gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + index, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)));
+ });
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ debug("framebuffer not complete");
+ debug("");
+ return;
+ }
+
+ // Clear all the attachments
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ //drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ // return [0, 0, 0, 0];
+ //});
+ //debug("--");
+
+ // Clear some attachments using testFB
+ gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
+
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return testFn(attachment, index) ? [0, 255, 0, 255] : [0, 0, 0, 0];
+ });
+
+ debug("test drawing to " + msg);
+
+ // Draw to some attachments using testFB
+ gl.useProgram(drawProgram);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return testFn(attachment, index) ? attachment.color : [0, 0, 0, 0];
+ });
+ };
+
+ gl.useProgram(drawProgram);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.drawBuffers(bufs);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+
+ wtu.drawUnitQuad(gl);
+
+ debug("test that each texture got the correct color.");
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments);
+
+ debug("test clearing clears all the textures");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
+
+ debug("test that NONE draws nothing");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(nones);
+ gl.useProgram(redProgram);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
+
+ // GLES3 spec section 3.9.2 Shader Outputs
+ debug("test that gl_FragColor only writes to color number zero");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+ gl.useProgram(blueProgramESSL1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Active draw buffers with missing frag outputs.");
+ gl.enable(gl.RASTERIZER_DISCARD);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors when RASTERIZER_DISCARD is enabled.");
+ gl.disable(gl.RASTERIZER_DISCARD);
+ gl.colorMask(false, false, false, false);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors when all 4 channels of color mask are disabled.");
+ gl.colorMask(false, true, false, false);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "partially diabled color mask shall have no impact.");
+ gl.colorMask(true, true, true, true);
+
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return (index == 0) ? [0, 0, 255, 255] : [0, 255, 0, 255];
+ });
+
+ // If there is only a single output, the location defaults to zero if not specified.
+ // See GLSL ES Spec 3.00.4, Section 4.3.8.2, Output Layout Qualifiers.
+ debug("test that an OpenGL ES Shading Language 3.00 shader with a single output color defaults to color number zero");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+ gl.useProgram(redProgram);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Active draw buffers with missing frag outputs.");
+
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return (index == 0) ? [255, 0, 0, 255] : [0, 255, 0, 255];
+ });
+
+ if (maxUsable > 1) {
+ // Prepare for following tests by clearing all attachments to red.
+ debug("prepare by clearing all attachments to red");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ var bufs1 = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ var bufs2 = drawBuffersUtils.makeColorAttachmentArray(maxUsable);
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ if (ii < half) {
+ bufs1[ii] = gl.NONE;
+ } else {
+ bufs2[ii] = gl.NONE;
+ }
+ }
+
+ debug("test setting first half to NONE and clearing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs1);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? [255, 0, 0, 255] : [0, 255, 0, 255];
+ });
+
+ debug("test setting first half to NONE and drawing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? [255, 0, 0, 255] : attachment.color;
+ });
+
+ debug("test setting second half to NONE and clearing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawBuffers(bufs2);
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? [0, 0, 255, 255] : [255, 0, 0, 255];
+ });
+
+ debug("test setting second half to NONE and drawing");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+
+ drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return index < half ? attachment.color : [255, 0, 0, 255];
+ });
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB1);
+ gl.drawBuffers(bufs);
+ drawAndCheckAttachments(
+ halfFB1, "framebuffer that only has first half of attachments",
+ function(attachment, index) {
+ return index < half;
+ });
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB2);
+ gl.drawBuffers(bufs);
+ drawAndCheckAttachments(
+ halfFB2, "framebuffer that only has second half of attachments",
+ function(attachment, index) {
+ return index >= half;
+ });
+
+ if (maxUsable > 2) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, endsFB);
+ gl.drawBuffers(bufs);
+ drawAndCheckAttachments(
+ endsFB, "framebuffer that only has first and last attachments",
+ function(attachment, index) {
+ return index == 0 || index == (maxUsable - 1);
+ });
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, middleFB);
+ gl.drawBuffers(bufs);
+ drawAndCheckAttachments(
+ middleFB,
+ "framebuffer that has all but the first and last attachments",
+ function(attachment, index) {
+ return index != 0 && index != (maxUsable - 1);
+ });
+ }
+ }
+
+ debug("test switching between fbos keeps drawbuffer state");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.drawBuffers(nones);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.useProgram(drawProgram);
+ wtu.drawUnitQuad(gl);
+ drawBuffersUtils.checkAttachmentsForColor(attachments);
+
+ debug("test that none of the attachments are written in case the fragment shader discards");
+ var discardProgram = createDrawBuffersProgram("fshaderDiscard",
+ {numDrawingBuffers: maxDrawingBuffers, assignUColorsToFragData: assignCode.join("\n")});
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.drawBuffers(bufs);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.useProgram(discardProgram);
+ wtu.drawUnitQuad(gl);
+ drawBuffersUtils.checkAttachmentsForColor(attachments, [0, 0, 0, 0]);
+
+ debug("test queries");
+ debug("check framebuffer with all attachments on");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0 + " + ii + ")", "gl.COLOR_ATTACHMENT0 + " + ii);
+ }
+
+ debug("check framebuffer with all attachments off");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ for (var ii = 0; ii < maxUsable; ++ii) {
+ shouldBe("gl.getParameter(gl.DRAW_BUFFER0 + " + ii + ")", "gl.NONE");
+ }
+
+ // WebGL generates FRAMEBUFFER_INCOMPLETE_DIMENSIONS when attached images have different sizes.
+ // This behavior differs from GLES 3.
+ debug("");
+ debug("test attachment size mis-match");
+ gl.bindTexture(gl.TEXTURE_2D, attachments[0].texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * 2, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+
+ // TODO: Rendering when framebuffer attachments have mismatched size should be tested, maybe in a separate test.
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteFramebuffer(fb2);
+ gl.deleteFramebuffer(halfFB1);
+ gl.deleteFramebuffer(halfFB2);
+ attachments.forEach(function(attachment) {
+ gl.deleteTexture(attachment.texture);
+ });
+ gl.deleteProgram(checkProgram);
+ gl.deleteProgram(redProgram);
+ gl.deleteProgram(drawProgram);
+}
+
+function testParameters() {
+ debug("");
+ debug("check that MAX_DRAW_BUFFERS and MAX_COLOR_ATTACHMENTS are valid");
+ var maxDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
+ var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ debug("MAX_DRAW_BUFFERS = " + maxDrawBuffers);
+ debug("MAX_COLOR_ATTACHMENTS = " + maxColorAttachments);
+ if (maxDrawBuffers != maxColorAttachments) {
+ testFailed("MAX_DRAW_BUFFERS and MAX_COLOR_ATTACHMENTS should be the same");
+ return false;
+ }
+ if (maxDrawBuffers < 4) {
+ testFailed("MAX_DRAW_BUFFERS should be at least 4");
+ return false;
+ }
+ return true;
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-with-integer-texture-base-level.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-with-integer-texture-base-level.html
new file mode 100644
index 0000000000..e2f9fd13c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/draw-with-integer-texture-base-level.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Draw With Integer Texture Base Level Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/tex-image-and-sub-image-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var canvas;
+var wtu = WebGLTestUtils;
+canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+var tiu = TexImageUtils;
+
+// Both Chrome and Firefox fail on this test on NVIDIA Windows, see crbug.com/679639.
+function testDrawIntegerTextureBaseLevel()
+{
+ description("This test verifies the functionality of rendering with integer texture non-zero base level.");
+
+ var green = [0, 255, 0, 255];
+
+ var width = 16;
+ var height = 16;
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ var texture = gl.createTexture();
+ var level = 1;
+ 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);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, level);
+ wtu.fillTexture(gl, texture, width, height, green, level, gl.RGBA_INTEGER, gl.UNSIGNED_BYTE, gl.RGBA8UI);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var program = tiu.setupTexturedQuad(gl, "RGBA8UI");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.checkCanvas(gl, green);
+}
+
+testDrawIntegerTextureBaseLevel();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/element-index-uint.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/element-index-uint.html
new file mode 100644
index 0000000000..123254f4cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/element-index-uint.html
@@ -0,0 +1,432 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uint element indices Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="vs" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main() {
+ gl_Position = vPosition;
+ color = vColor;
+}
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
+ precision mediump float;
+ attribute vec2 position;
+ attribute vec4 vecRandom;
+ varying vec4 v_color;
+
+ // Per the spec, each component can either contain existing contents
+ // of the buffer or 0.
+ bool testFloatComponent(float component) {
+ return (component == 0.2 || component == 0.0);
+ }
+ // The last component is additionally allowed to be 1.0.
+ bool testLastFloatComponent(float component) {
+ return testFloatComponent(component) || component == 1.0;
+ }
+
+ void main() {
+ if (testFloatComponent(vecRandom.x) &&
+ testFloatComponent(vecRandom.y) &&
+ testFloatComponent(vecRandom.z) &&
+ testLastFloatComponent(vecRandom.w)) {
+ v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- Out of range
+ } else {
+ v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
+ }
+ gl_Position = vec4(position, 0.0, 1.0);
+ }
+</script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the Uint element indices.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = null;
+var canvas = null;
+
+// Test both STATIC_DRAW and DYNAMIC_DRAW as a regression test
+// for a bug in ANGLE which has since been fixed.
+for (var ii = 0; ii < 2; ++ii) {
+ canvas = document.createElement("canvas");
+ canvas.width = 50;
+ canvas.height = 50;
+
+ gl = wtu.create3DContext(canvas, null, 2);
+
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ } else {
+ testPassed("WebGL context exists");
+
+ var drawType = (ii == 0) ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
+ debug("Testing " + ((ii == 0) ? "STATIC_DRAW" : "DYNAMIC_DRAW"));
+
+ runDrawTests(drawType);
+
+ // These tests are tweaked duplicates of the buffers/index-validation* tests
+ // using unsigned int indices to ensure that behavior remains consistent
+ runIndexValidationTests(drawType);
+ runIndexOutOfRangeTests(drawType);
+ runResizedBufferTests(drawType);
+ runCrashWithBufferSubDataTests(drawType);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+function runDrawTests(drawType) {
+ debug("Test that draws with unsigned integer indices produce the expected results");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var program = wtu.setupNoTexCoordTextureProgram(gl);
+
+ function setupDraw(s) {
+ // Create a vertex buffer that cannot be fully indexed via shorts
+ var quadArrayLen = 65537 * 3;
+ var quadArray = new Float32Array(quadArrayLen);
+
+ // Leave all but the last 4 values zero-ed out
+ var idx = quadArrayLen - 12;
+
+ // Initialized the last 4 values to a quad
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ quadArray[idx++] = 1.0 * s;
+ quadArray[idx++] = -1.0 * s;
+ quadArray[idx++] = 0.0;
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, quadArray, drawType);
+
+ // Create an unsigned int index buffer that indexes the last 4 vertices
+ var baseIndex = (quadArrayLen / 3) - 4;
+
+ var indexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([
+ baseIndex + 0,
+ baseIndex + 1,
+ baseIndex + 2,
+ baseIndex + 2,
+ baseIndex + 3,
+ baseIndex + 0]), drawType);
+
+ var opt_positionLocation = 0;
+ gl.enableVertexAttribArray(opt_positionLocation);
+ gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0);
+ };
+ function readLocation(x, y) {
+ var pixels = new Uint8Array(1 * 1 * 4);
+ gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ return pixels;
+ };
+ function testPixel(blockList, allowList) {
+ function testList(list, expected) {
+ for (var n = 0; n < list.length; n++) {
+ var l = list[n];
+ var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2;
+ var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2;
+ var source = readLocation(x, y);
+ if (Math.abs(source[0] - expected) > 2) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return testList(blockList, 0) && testList(allowList, 255);
+ };
+ function verifyDraw(drawNumber, s) {
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
+
+ var blockList = [];
+ var allowList = [];
+ var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
+ for (var n = 0; n < points.length; n++) {
+ if (points[n] <= s) {
+ blockList.push(points[n]);
+ } else {
+ allowList.push(points[n]);
+ }
+ }
+ if (testPixel(blockList, allowList)) {
+ testPassed("Draw " + drawNumber + " passed pixel test");
+ } else {
+ testFailed("Draw " + drawNumber + " failed pixel test");
+ }
+ };
+
+ setupDraw(0.5);
+ verifyDraw(0, 0.5);
+}
+
+function runIndexValidationTests(drawType) {
+ description("Tests that index validation verifies the correct number of indices");
+
+ function sizeInBytes(type) {
+ switch (type) {
+ case gl.BYTE:
+ case gl.UNSIGNED_BYTE:
+ return 1;
+ case gl.SHORT:
+ case gl.UNSIGNED_SHORT:
+ return 2;
+ case gl.INT:
+ case gl.UNSIGNED_INT:
+ case gl.FLOAT:
+ return 4;
+ default:
+ throw "unknown type";
+ }
+ }
+
+ var program = wtu.loadStandardProgram(gl);
+
+ // 3 vertices => 1 triangle, interleaved data
+ var dataComplete = new Float32Array([0, 0, 0, 1,
+ 0, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 1,
+ 1, 1, 1, 1,
+ 0, 0, 1]);
+ var dataIncomplete = new Float32Array([0, 0, 0, 1,
+ 0, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 1,
+ 1, 1, 1, 1]);
+ var indices = new Uint32Array([0, 1, 2]);
+
+ debug("Testing with valid indices");
+
+ var bufferComplete = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferComplete);
+ gl.bufferData(gl.ARRAY_BUFFER, dataComplete, drawType);
+ var elements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
+ gl.useProgram(program);
+ var vertexLoc = gl.getAttribLocation(program, "a_vertex");
+ var normalLoc = gl.getAttribLocation(program, "a_normal");
+ gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
+ gl.enableVertexAttribArray(vertexLoc);
+ gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+ gl.enableVertexAttribArray(normalLoc);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var bufferIncomplete = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
+ gl.bufferData(gl.ARRAY_BUFFER, dataIncomplete, drawType);
+ gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
+ gl.enableVertexAttribArray(vertexLoc);
+ gl.disableVertexAttribArray(normalLoc);
+ debug("Enable vertices, valid");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("Test with enabled attribute that does not belong to current program");
+
+ gl.disableVertexAttribArray(normalLoc);
+ var extraLoc = Math.max(vertexLoc, normalLoc) + 1;
+ gl.enableVertexAttribArray(extraLoc);
+ debug("Enable an extra attribute with null");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+ debug("Enable an extra attribute with insufficient data buffer");
+ gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+ debug("Pass large negative index to vertexAttribPointer");
+ gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
+}
+
+function runIndexOutOfRangeTests(drawType) {
+ debug("Testing with out-of-range indices");
+
+ var bufferPos = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferPos);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]), drawType);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var bufferIncomplete = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]), drawType);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+
+ var glProgram = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup successfully");
+
+ var indices = new Uint32Array([0, 1, 2, 0, 2, 3]);
+ var elements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
+
+ gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+
+
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
+ }
+
+ debug("Test that client data is always copied during bufferData and bufferSubData calls");
+
+ indices[5] = 1;
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
+ }
+}
+
+function runResizedBufferTests(drawType) {
+ debug("Test that updating the size of a vertex buffer is properly noticed by the WebGL implementation.");
+
+ var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initialization");
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [-1,1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0]), drawType);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex setup");
+
+ var texCoordObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
+ [0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1]), drawType);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coord setup");
+
+ // Now resize these buffers because we want to change what we're drawing.
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0,
+ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0]), drawType);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex redefinition");
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]), drawType);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coordinate / color redefinition");
+
+ var numQuads = 2;
+ var indices = new Uint32Array(numQuads * 6);
+ for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ var quad = (ii == (numQuads - 1)) ? 4 : 0;
+ indices[offset + 0] = quad + 0;
+ indices[offset + 1] = quad + 1;
+ indices[offset + 2] = quad + 2;
+ indices[offset + 3] = quad + 2;
+ indices[offset + 4] = quad + 1;
+ indices[offset + 5] = quad + 3;
+ }
+ var indexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
+ gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_INT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+}
+
+function runCrashWithBufferSubDataTests(drawType) {
+ debug('Verifies that the index validation code which is within bufferSubData does not crash.')
+
+ var elementBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, drawType);
+ var data = new Uint32Array(127);
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 64, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "after attempting to update a buffer outside of the allocated bounds");
+ testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-draw-framebuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-draw-framebuffer.html
new file mode 100644
index 0000000000..1c0709e0b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-draw-framebuffer.html
@@ -0,0 +1,74 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test draw framebuffer completeness when an incomplete framebuffer is bound to read framebuffer</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+// This exposes a bug in Chrome 67: If the read framebuffer is incomplete, then draw can fail even if the draw framebuffer is complete.
+// http://anglebug.com/2737
+
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var incompleteFb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, incompleteFb);
+ var incompleteTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, incompleteTex);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, incompleteTex, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT');
+
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ var testProgram = wtu.setupSimpleColorProgram(gl, 0);
+
+ // If this is changed to gl.FRAMEBUFFER, the rendering succeeds on Chrome 67.
+ var drawFbTarget = gl.DRAW_FRAMEBUFFER;
+
+ var completeFb = gl.createFramebuffer();
+ gl.bindFramebuffer(drawFbTarget, completeFb);
+ var completeTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, completeTex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
+ gl.framebufferTexture2D(drawFbTarget, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, completeTex, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after setup");
+
+ shouldBe('gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER)', 'gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT');
+ shouldBe('gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.viewport(0, 0, 128, 128);
+ gl.uniform4f(gl.getUniformLocation(testProgram, 'u_color'), 0, 1, 0, 1);
+ wtu.drawUnitQuad(gl);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after draw");
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, completeFb);
+ wtu.checkCanvasRect(gl, 0, 0, 128, 128, [0, 255, 0, 255], 'should be green', 2);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-unaffected.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-unaffected.html
new file mode 100644
index 0000000000..74b6106419
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-completeness-unaffected.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test drawBuffers, readBuffer, and fbo completeness</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="20" height="20"> </canvas>
+<script>
+// In MacOSX, if drawBuffers() and readBuffer() both select an attachment with no image attached,
+// fbo becomes incomplete. However, drawBuffers() and readBuffer() should not affect fbo completeness.
+
+"use strict";
+description("This tests drawBuffers, readBuffer, and fbo completeness");
+
+var setupRenderbuffer = function(attachment) {
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, canvas.width, canvas.height);
+ return renderbuffer;
+}
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ debug("fbo with two color images attached should be complete");
+ var colorbuffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0);
+ var colorbuffer1 = setupRenderbuffer(gl.COLOR_ATTACHMENT1);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ debug("drawBuffers selects ATTACHMENT1, fbo should be complete");
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ debug("remove image attached to ATTACHMENT1, fbo should be complete");
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, null);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ debug("set read buffer to ATTACHMENT1, fbo should be complete");
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ debug("drawBuffers selects ATTACHMENT0, fbo should be complete");
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ debug("drawBuffers selects ATTACHMENT1, fbo should be complete");
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ debug("set read buffer to ATTACHMENT0, fbo should be complete");
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteRenderbuffer(colorbuffer);
+ gl.deleteRenderbuffer(colorbuffer1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after setup and clear render buffer");
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-mismatched-attachment-targets.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-mismatched-attachment-targets.html
new file mode 100644
index 0000000000..a8a28d6444
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-mismatched-attachment-targets.html
@@ -0,0 +1,162 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 can render to framebuffer attachments with different targets</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+void main(void) {
+ gl_Position = vec4(-0.5, -0.5, 0, 1);
+ gl_PointSize = 1.0;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 outColor;
+void main() {
+ outColor = vec4(0, 1, 0, 1);
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="1", height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Test framebuffer attachments with different targets");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext("example", undefined, 2);
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+function newResource(target, mipLevels, format, size) {
+ let ret;
+ switch (target) {
+ case gl.RENDERBUFFER: {
+ ret = gl.createRenderbuffer();
+ ret.mips = [ ret ];
+ for (let i = 1; i < mipLevels; i++) {
+ ret.mips.push(gl.createRenderbuffer());
+ }
+ for (const i in ret.mips) {
+ const rb = ret.mips[i];
+ gl.bindRenderbuffer(target, rb);
+ gl.renderbufferStorage(target, format, size>>i, size>>i);
+ }
+ ret.attach = (attachEnum, mipLevel) => {
+ const rb = ret.mips[mipLevel];
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachEnum, gl.RENDERBUFFER, rb);
+ };
+ break;
+ }
+ case gl.TEXTURE_2D:
+ case gl.TEXTURE_CUBE_MAP: {
+ ret = gl.createTexture();
+ gl.bindTexture(target, ret);
+ gl.texStorage2D(target, mipLevels, format, size, size);
+ let imageTarget = target;
+ if (imageTarget == gl.TEXTURE_CUBE_MAP) {
+ imageTarget = gl.TEXTURE_CUBE_MAP_POSITIVE_X+2; // Deliberately don't choose the first image.
+ }
+ ret.attach = (attachEnum, mipLevel) => {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachEnum, imageTarget, ret, mipLevel);
+ };
+ break;
+ }
+ case gl.TEXTURE_3D:
+ case gl.TEXTURE_2D_ARRAY: {
+ ret = gl.createTexture();
+ gl.bindTexture(target, ret);
+ gl.texStorage3D(target, mipLevels, format, size, size, 1);
+ ret.attach = (attachEnum, mipLevel) => {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, attachEnum, ret, mipLevel, 0);
+ };
+ break;
+ }
+ default:
+ throw new Error();
+ }
+ ret.target = wtu.glEnumToString(gl, target);
+ ret.format = wtu.glEnumToString(gl, format);
+ return ret;
+}
+
+function runTest() {
+ const MIP_LEVELS = 2;
+ const SIZE = 2;
+
+ gl.clearColor(1, 0, 0, 1);
+
+ const program = wtu.setupProgram(gl, ['vshader','fshader'], [], console.log.bind(console));
+ gl.useProgram(program);
+
+ const colorResList = [
+ newResource(gl.RENDERBUFFER, MIP_LEVELS, gl.RGBA8, SIZE),
+ newResource(gl.TEXTURE_2D, MIP_LEVELS, gl.RGBA8, SIZE),
+ newResource(gl.TEXTURE_CUBE_MAP, MIP_LEVELS, gl.RGBA8, SIZE),
+ newResource(gl.TEXTURE_3D, MIP_LEVELS, gl.RGBA8, SIZE),
+ newResource(gl.TEXTURE_2D_ARRAY, MIP_LEVELS, gl.RGBA8, SIZE),
+ ];
+
+ const depthResList = [
+ newResource(gl.RENDERBUFFER, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
+ newResource(gl.TEXTURE_2D, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
+ newResource(gl.TEXTURE_CUBE_MAP, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
+ //newResource(gl.TEXTURE_3D, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE), // Depth formats forbidden for TEXTURE_3D.
+ newResource(gl.TEXTURE_2D_ARRAY, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
+ ];
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ for (const color of colorResList) {
+ for (const depth of depthResList) {
+ debug(`\ncolor: ${color.target}; depth: ${depth.target}`);
+ for (let mipLevel = 0; mipLevel < MIP_LEVELS; mipLevel++) {
+ debug(`mipLevel: ${mipLevel}`);
+ color.attach(gl.COLOR_ATTACHMENT0, mipLevel);
+ depth.attach(gl.DEPTH_ATTACHMENT, mipLevel);
+ const maybeStatus = wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [gl.FRAMEBUFFER_COMPLETE, gl.FRAMEBUFFER_UNSUPPORTED]);
+ if (!maybeStatus || maybeStatus[0] != gl.FRAMEBUFFER_COMPLETE) {
+ continue;
+ }
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], `framebuffer layer ${mipLevel} should be cleared red`);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], `framebuffer layer ${mipLevel} should be drawn green`);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors`);
+ }
+ }
+ }
+
+ // make sure we were not rendering to the canvas.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null)
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be zero");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer-angle-issue.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer-angle-issue.html
new file mode 100644
index 0000000000..1fbdb6bbeb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer-angle-issue.html
@@ -0,0 +1,90 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 can render to layers in 3D texture angle issue check</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+void main(void) {
+ gl_Position = vec4(0, 0, 0, 1);
+ gl_PointSize = 1.0;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 outColor;
+void main() {
+ outColor = vec4(0, 1, 0, 1);
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="1", height="1"></canvas>
+<div id="description"></div>
+<a href='https://bugs.chromium.org/p/angleproject/issues/detail?id=4417'>ANGLE issue #4417</a>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Test that WebGL2 can render to layers in 3D textures");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+function runTest() {
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, gl.canvas.width, gl.canvas.height, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ for (let i = 0; i < 2; i++) {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, i);
+
+ const rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, gl.canvas.width, gl.canvas.height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
+
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE);
+
+ const program = wtu.setupProgram(gl, ['vshader','fshader'], [], console.log.bind(console));
+ gl.useProgram(program);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors`);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], `framebuffer layer ${i} should be green`);
+ }
+
+ // make sure we were not rendering to the canvas.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null)
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be zero");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer.html
new file mode 100644
index 0000000000..c34f2a4143
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-render-to-layer.html
@@ -0,0 +1,440 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 can render to layers in 3D and 2D_ARRAY textures</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+void main(void) {
+ gl_Position = vec4(0, 0, 0, 1);
+ gl_PointSize = 1.0;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Test that WebGL2 can render to layers in 3D and 2D_ARRAY textures");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+function runTest() {
+ const texWidth = 1;
+ const texHeight = 1;
+ const texDepth = 2;
+
+ function makeFragmentShader(typeInfo) {
+ const src = `#version 300 es
+ precision mediump float;
+ out ${typeInfo.outType} color;
+ void main() {
+ color = ${typeInfo.outValue};
+ }
+ `;
+ return src;
+ }
+
+ const textureInternalFormatInfo = {};
+ {
+ const t = textureInternalFormatInfo;
+ // unsized formats
+ // If understand correctly these 3 unsized formats are not required to be color renderable
+ t[gl.ALPHA] = { textureFormat: gl.ALPHA, colorRenderable: false, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.LUMINANCE] = { textureFormat: gl.LUMINANCE, colorRenderable: false, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.LUMINANCE_ALPHA] = { textureFormat: gl.LUMINANCE_ALPHA, colorRenderable: false, textureFilterable: true, bytesPerElement: [2, 4, 4, 8], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+
+ t[gl.RGB] = { textureFormat: gl.RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 6, 6, 12, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_5_6_5], };
+ t[gl.RGBA] = { textureFormat: gl.RGBA, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 8, 8, 16, 2, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_4_4_4_4, gl.UNSIGNED_SHORT_5_5_5_1], };
+
+ // sized formats
+ t[gl.R8] = { textureFormat: gl.RED, colorRenderable: true, textureFilterable: true, bytesPerElement: [1], type: [gl.UNSIGNED_BYTE], };
+ t[gl.R8_SNORM] = { textureFormat: gl.RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [1], type: [gl.BYTE], };
+ t[gl.R16F] = { textureFormat: gl.RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [4, 2], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.R32F] = { textureFormat: gl.RED, colorRenderable: false, textureFilterable: false, bytesPerElement: [4], type: [gl.FLOAT], };
+ t[gl.R8UI] = { textureFormat: gl.RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [gl.UNSIGNED_BYTE], };
+ t[gl.R8I] = { textureFormat: gl.RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [gl.BYTE], };
+ t[gl.R16UI] = { textureFormat: gl.RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [gl.UNSIGNED_SHORT], };
+ t[gl.R16I] = { textureFormat: gl.RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [gl.SHORT], };
+ t[gl.R32UI] = { textureFormat: gl.RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT], };
+ t[gl.R32I] = { textureFormat: gl.RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.INT], };
+ t[gl.RG8] = { textureFormat: gl.RG, colorRenderable: true, textureFilterable: true, bytesPerElement: [2], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RG8_SNORM] = { textureFormat: gl.RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [2], type: [gl.BYTE], };
+ t[gl.RG16F] = { textureFormat: gl.RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [8, 4], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RG32F] = { textureFormat: gl.RG, colorRenderable: false, textureFilterable: false, bytesPerElement: [8], type: [gl.FLOAT], };
+ t[gl.RG8UI] = { textureFormat: gl.RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RG8I] = { textureFormat: gl.RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [gl.BYTE], };
+ t[gl.RG16UI] = { textureFormat: gl.RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RG16I] = { textureFormat: gl.RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.SHORT], };
+ t[gl.RG32UI] = { textureFormat: gl.RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [gl.UNSIGNED_INT], };
+ t[gl.RG32I] = { textureFormat: gl.RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [gl.INT], };
+ t[gl.RGB8] = { textureFormat: gl.RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.SRGB8] = { textureFormat: gl.RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGB565] = { textureFormat: gl.RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 2], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_6_5], };
+ t[gl.RGB8_SNORM] = { textureFormat: gl.RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [gl.BYTE], };
+ t[gl.R11F_G11F_B10F] = { textureFormat: gl.RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_10F_11F_11F_REV], };
+ t[gl.RGB9_E5] = { textureFormat: gl.RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_5_9_9_9_REV], };
+ t[gl.RGB16F] = { textureFormat: gl.RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RGB32F] = { textureFormat: gl.RGB, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [gl.FLOAT], };
+ t[gl.RGB8UI] = { textureFormat: gl.RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGB8I] = { textureFormat: gl.RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [gl.BYTE], };
+ t[gl.RGB16UI] = { textureFormat: gl.RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RGB16I] = { textureFormat: gl.RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [gl.SHORT], };
+ t[gl.RGB32UI] = { textureFormat: gl.RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [gl.UNSIGNED_INT], };
+ t[gl.RGB32I] = { textureFormat: gl.RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [gl.INT], };
+ t[gl.RGBA8] = { textureFormat: gl.RGBA, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.SRGB8_ALPHA8] = { textureFormat: gl.RGBA, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGBA8_SNORM] = { textureFormat: gl.RGBA, colorRenderable: false, textureFilterable: true, bytesPerElement: [4], type: [gl.BYTE], };
+ t[gl.RGB5_A1] = { textureFormat: gl.RGBA, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2, 4], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_5_5_1, gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA4] = { textureFormat: gl.RGBA, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_4_4_4_4], };
+ t[gl.RGB10_A2] = { textureFormat: gl.RGBA, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA16F] = { textureFormat: gl.RGBA, colorRenderable: false, textureFilterable: true, bytesPerElement: [16, 8], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RGBA32F] = { textureFormat: gl.RGBA, colorRenderable: false, textureFilterable: false, bytesPerElement: [16], type: [gl.FLOAT], };
+ t[gl.RGBA8UI] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGBA8I] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.BYTE], };
+ t[gl.RGB10_A2UI] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA16UI] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RGBA16I] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [gl.SHORT], };
+ t[gl.RGBA32I] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [gl.INT], };
+ t[gl.RGBA32UI] = { textureFormat: gl.RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [gl.UNSIGNED_INT], };
+
+ // Sized Internal
+ t[gl.DEPTH_COMPONENT16] = { textureFormat: gl.DEPTH_COMPONENT, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [gl.UNSIGNED_SHORT, gl.UNSIGNED_INT], };
+ t[gl.DEPTH_COMPONENT24] = { textureFormat: gl.DEPTH_COMPONENT, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT], };
+ t[gl.DEPTH_COMPONENT32F] = { textureFormat: gl.DEPTH_COMPONENT, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.FLOAT], };
+ t[gl.DEPTH24_STENCIL8] = { textureFormat: gl.DEPTH_STENCIL, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT_24_8], };
+ t[gl.DEPTH32F_STENCIL8] = { textureFormat: gl.DEPTH_STENCIL, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [gl.FLOAT_32_UNSIGNED_INT_24_8_REV], };
+
+ Object.keys(t).forEach(function(internalFormat) {
+ const info = t[internalFormat];
+ info.bytesPerElementMap = {};
+ info.bytesPerElement.forEach(function(bytesPerElement, ndx) {
+ const type = info.type[ndx];
+ info.bytesPerElementMap[type] = bytesPerElement;
+ });
+ });
+ }
+
+ const validChannelsByTextureFormat = {};
+ {
+ const v = validChannelsByTextureFormat;
+ v[gl.RED] = [1, 0, 0, 0];
+ v[gl.RG] = [1, 1, 0, 0];
+ v[gl.RGB] = [1, 1, 1, 0];
+ v[gl.RGBA] = [1, 1, 1, 1];
+ v[gl.RED_INTEGER] = [1, 0, 0, 0];
+ v[gl.RG_INTEGER] = [1, 1, 0, 0];
+ v[gl.RGB_INTEGER] = [1, 1, 1, 0];
+ v[gl.RGBA_INTEGER] = [1, 1, 1, 1];
+ }
+
+ const depthTextureFormats = [
+ gl.DEPTH_COMPONENT16,
+ gl.DEPTH_COMPONENT24,
+ gl.DEPTH_COMPONENT32F,
+ gl.DEPTH24_STENCIL8,
+ gl.DEPTH32F_STENCIL8,
+ ];
+
+ const intTextureFormats = [
+ gl.R8I,
+ gl.R16I,
+ gl.R32I,
+ gl.RG8I,
+ gl.RG16I,
+ gl.RG32I,
+ gl.RGB8I,
+ gl.RGB16I,
+ gl.RGB32I,
+ gl.RGBA8I,
+ gl.RGBA16I,
+ gl.RGBA32I,
+ ];
+
+ const unsignedIntTextureFormats = [
+ gl.R8UI,
+ gl.R16UI,
+ gl.R32UI,
+ gl.RG8UI,
+ gl.RG16UI,
+ gl.RG32UI,
+ gl.RGB8UI,
+ gl.RGB16UI,
+ gl.RGB32UI,
+ gl.RGBA8UI,
+ gl.RGB10_A2UI,
+ gl.RGBA16UI,
+ gl.RGBA32UI,
+ ];
+
+ const floatTextureFormats = Object.keys(textureInternalFormatInfo).map(function(v) {
+ return parseInt(v);
+ }).filter(function(format) {
+ return intTextureFormats.indexOf(format) < 0 &&
+ unsignedIntTextureFormats.indexOf(format) < 0 &&
+ depthTextureFormats.indexOf(format);
+ });
+
+ const expectedColorByInternalFormat = {};
+ expectedColorByInternalFormat[gl.SRGB8_ALPHA8] = [225, 188, 137, 255];
+
+ function clearFloat(gl) {
+ gl.clearBufferfv(gl.COLOR, 0, [0, 0, 0, 0]);
+ }
+
+ function clearInt(gl) {
+ gl.clearBufferiv(gl.COLOR, 0, [0, 0, 0, 0]);
+ }
+
+ function clearUint(gl) {
+ gl.clearBufferuiv(gl.COLOR, 0, [0, 0, 0, 0]);
+ }
+
+
+ function checkData(data, expected, internalFormat, tolerance) {
+ const internalFormatInfo = textureInternalFormatInfo[internalFormat];
+ const validChannels = validChannelsByTextureFormat[internalFormatInfo.textureFormat];
+ if (!validChannels) {
+ testFailed('oops');
+ return;
+ }
+ for (let y = 0; y < texHeight; ++y) {
+ for (let x = 0; x < texWidth; ++x) {
+ for (let c = 0; c < validChannels.length; ++c) {
+ if (validChannels[c]) {
+ const offset = (y * texWidth + x) * 4 + c;
+ const pixel = data[offset];
+ const diff = Math.abs(pixel - expected[c]);
+ if (diff > tolerance) {
+ testFailed(`pixel ${x},${y} channel ${c} was ${pixel} expected ${expected[c]} +/- ${tolerance}`);
+ return;
+ }
+ }
+ }
+ }
+ }
+ testPassed(`data was ${expected.join(',')}`);
+ }
+
+ function checkFloat(gl, textureInfo, expected) {
+ const data = new Uint8Array(texWidth * texHeight * 4);
+ gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ const internalFormat = textureInfo.internalFormat;
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from readPixels with ${wtu.glEnumToString(gl, internalFormat)}`);
+ checkData(data, expected, internalFormat, 9);
+ }
+
+ function checkInt(gl, textureInfo, expected) {
+ const data = new Int32Array(texWidth * texHeight * 4);
+ gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA_INTEGER, gl.INT, data);
+ const internalFormat = textureInfo.internalFormat;
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from readPixels with ${wtu.glEnumToString(gl, internalFormat)}`);
+ checkData(data, expected, internalFormat, 0);
+ }
+
+ function checkUint(gl, textureInfo, expected) {
+ const data = new Uint32Array(texWidth * texHeight * 4);
+ gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA_INTEGER, gl.UNSIGNED_INT, data);
+ const internalFormat = textureInfo.internalFormat;
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from readPixels with ${wtu.glEnumToString(gl, internalFormat)}`);
+ checkData(data, expected, internalFormat, 0);
+ }
+
+ const expectedFloatColor = [.75 * 255 | 0, .5 * 255 | 0, .25 * 255 | 0, 1 * 255 | 0];
+ const floatTypes = [
+ { outType: 'vec4', outValue: 'vec4(.75, .5, .25, 1)', expected: expectedFloatColor, clear: clearFloat, check: checkFloat, target: gl.TEXTURE_2D, },
+ { outType: 'vec4', outValue: 'vec4(.75, .5, .25, 1)', expected: expectedFloatColor, clear: clearFloat, check: checkFloat, target: gl.TEXTURE_3D, },
+ { outType: 'vec4', outValue: 'vec4(.75, .5, .25, 1)', expected: expectedFloatColor, clear: clearFloat, check: checkFloat, target: gl.TEXTURE_2D_ARRAY, },
+ ];
+
+ const expectedIntColor = [1, 2, 4, 3];
+ const signedIntTypes = [
+ { outType: 'ivec4', outValue: 'ivec4(1, 2, 4, 3)', expected: expectedIntColor, clear: clearInt, check: checkInt, target: gl.TEXTURE_2D, },
+ { outType: 'ivec4', outValue: 'ivec4(1, 2, 4, 3)', expected: expectedIntColor, clear: clearInt, check: checkInt, target: gl.TEXTURE_3D, },
+ { outType: 'ivec4', outValue: 'ivec4(1, 2, 4, 3)', expected: expectedIntColor, clear: clearInt, check: checkInt, target: gl.TEXTURE_2D_ARRAY, },
+ ];
+
+ const expectedUintColor = [1, 2, 4, 3];
+ const unsignedIntTypes = [
+ { outType: 'uvec4', outValue: 'uvec4(1, 2, 4, 3)', expected: expectedUintColor, clear: clearUint, check: checkUint, target: gl.TEXTURE_2D, },
+ { outType: 'uvec4', outValue: 'uvec4(1, 2, 4, 3)', expected: expectedUintColor, clear: clearUint, check: checkUint, target: gl.TEXTURE_3D, },
+ { outType: 'uvec4', outValue: 'uvec4(1, 2, 4, 3)', expected: expectedUintColor, clear: clearUint, check: checkUint, target: gl.TEXTURE_2D_ARRAY, },
+ ];
+
+ /**
+ * Gets the number of bytes per element for a given internalFormat / type
+ * @param {number} internalFormat The internalFormat parameter from texImage2D etc..
+ * @param {number} type The type parameter for texImage2D etc..
+ * @return {number} the number of bytes per element for the given internalFormat, type combo
+ * @memberOf module:twgl/textures
+ */
+ function getBytesPerElementForInternalFormat(internalFormat, type) {
+ const info = textureInternalFormatInfo[internalFormat];
+ if (!info) {
+ throw "unknown internal format";
+ }
+ const bytesPerElement = info.bytesPerElementMap[type];
+ if (bytesPerElement === undefined) {
+ throw "unknown internal format";
+ }
+ return bytesPerElement;
+ }
+
+ function make2DTexture(gl, target, internalFormat, format, type) {
+ gl.texImage2D(target, 0, internalFormat, texWidth, texHeight, 0, format, type, null);
+ }
+
+ function make3DTexture(gl, target, internalFormat, format, type) {
+ gl.texImage3D(target, 0, internalFormat, texWidth, texHeight, texDepth, 0, format, type, null);
+ }
+
+ function attach2DTexture(gl, target, texture) {
+ const level = 0;
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, texture, level);
+ }
+
+ function attach3DTexture(gl, target, texture) {
+ const level = 0;
+ const slice = texDepth - 1;
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level, slice);
+ }
+
+ const targets = {};
+ targets[gl.TEXTURE_2D] = { make: make2DTexture, attach: attach2DTexture, },
+ targets[gl.TEXTURE_3D] = { make: make3DTexture, attach: attach3DTexture, },
+ targets[gl.TEXTURE_2D_ARRAY] = { make: make3DTexture, attach: attach3DTexture, },
+
+ debug("create textures");
+ Object.keys(targets).forEach(function(target) {
+ debug("");
+ target = parseInt(target);
+ debug(wtu.glEnumToString(gl, target))
+ const targetInfo = targets[target];
+ targetInfo.textures = [];
+ Object.keys(textureInternalFormatInfo).forEach(function(internalFormat) {
+ internalFormat = parseInt(internalFormat);
+ const isDepthFormat = depthTextureFormats.indexOf(internalFormat) >= 0;
+ if (isDepthFormat) {
+ return;
+ }
+ const info = textureInternalFormatInfo[internalFormat];
+ if (!info.colorRenderable) {
+ return;
+ }
+ const texture = gl.createTexture();
+ gl.bindTexture(target, texture);
+ targetInfo.make(gl, target, internalFormat, info.textureFormat, info.type[0]);
+ targetInfo.textures.push({
+ internalFormat: internalFormat,
+ texture: texture,
+ });
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from setup for ${wtu.glEnumToString(gl, target)} ${wtu.glEnumToString(gl, internalFormat)}`);
+ });
+ });
+
+ // set the canvas to a known color
+ const half = 127 / 255;
+ gl.clearColor(half, half, half, half);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.clearColor(0, 0, 0, 0);
+
+ const framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.viewport(0, 0, texWidth, texHeight);
+
+ const rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, texWidth, texHeight);
+
+ testTypes('float', floatTypes, floatTextureFormats);
+ testTypes('int', signedIntTypes, intTextureFormats);
+ testTypes('unsigned', unsignedIntTypes, unsignedIntTextureFormats);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ wtu.checkCanvas(gl, [127, 127, 127, 127], "canvas should be [127, 127, 127, 127]");
+
+ function testTypes(label, types, compatibleFormats) {
+ debug('');
+ types.forEach(function(typeInfo) {
+ debug(`\nchecking ${wtu.glEnumToString(gl, typeInfo.target)} with ${label} texture formats`);
+ const program = wtu.setupProgram(gl, ['vshader', makeFragmentShader(typeInfo)], [], console.log.bind(console));
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ const target = typeInfo.target;
+ const targetInfo = targets[target];
+ targetInfo.textures.filter(function(textureInfo) {
+ return compatibleFormats.indexOf(textureInfo.internalFormat) >= 0;
+ }).forEach(function(textureInfo) {
+ const internalFormat = textureInfo.internalFormat;
+ const desc = `${wtu.glEnumToString(gl, target)} ${wtu.glEnumToString(gl, internalFormat)}`;
+ const expected = expectedColorByInternalFormat[internalFormat] || typeInfo.expected;
+
+ debug('');
+ debug(desc);
+
+ targetInfo.attach(gl, target, textureInfo.texture);
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE, `for ${desc}`);
+ typeInfo.clear(gl);
+ if (wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from clear to ${desc}`)) {
+ return;
+ }
+ typeInfo.check(gl, textureInfo, [0, 0, 0, 0]);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ if (wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from render to ${desc}`)) {
+ return;
+ }
+ typeInfo.check(gl, textureInfo, expected);
+
+ typeInfo.clear(gl);
+ if (wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from clear to ${desc}`)) {
+ return;
+ }
+ typeInfo.check(gl, textureInfo, [0, 0, 0, 0]);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE, `for ${desc} with depth renderbuffer`);
+ gl.clearBufferfv(gl.DEPTH, 0, [1]);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from render to ${desc}`);
+
+ typeInfo.check(gl, textureInfo, expected);
+ });
+ });
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-changing-base-level.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-changing-base-level.html
new file mode 100644
index 0000000000..de462d6015
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-changing-base-level.html
@@ -0,0 +1,107 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer using a non-square texture with a changing base level</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+// http://anglebug.com/2291
+
+var wtu = WebGLTestUtils;
+var gl;
+
+function testNonSquareFramebufferTextureWithChangingBaseLevel() {
+ var program = wtu.setupSimpleTextureProgram(gl);
+ wtu.setupUnitQuad(gl);
+
+ var width = 8;
+ var height = 4;
+
+ debug("");
+ debug("Text texture width " + width + " x height " + height);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level.
+ var level = 0;
+ var levelW = width;
+ var levelH = height;
+ gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, levelW, levelH, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ while (levelW > 1 || levelH > 1)
+ {
+ ++level;
+ levelW = Math.max(1, Math.floor(width / Math.pow(2, level)));
+ levelH = Math.max(1, Math.floor(height / Math.pow(2, level)));
+ gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, levelW, levelH, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+
+ // Clear each level of the texture using an FBO. Change the base level to match the level used for the FBO on each iteration.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ level = 0;
+ levelW = width;
+ levelH = height;
+ while (levelW > 1 || levelH > 1)
+ {
+ var levelW = Math.floor(width / Math.pow(2, level));
+ var levelH = Math.floor(height / Math.pow(2, level));
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, level);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, level);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Clearing the texture level " + level + " to green should succeed.");
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255], "should be green");
+ ++level;
+ }
+
+ debug("");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 0);
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Drawing the texture to default framebuffer with base level 0 should succeed.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+}
+
+description();
+
+var canvas = document.getElementById("canvas");
+shouldBeNonNull("gl = wtu.create3DContext(canvas, undefined, 2)");
+
+testNonSquareFramebufferTextureWithChangingBaseLevel();
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-level1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-level1.html
new file mode 100644
index 0000000000..d5ac8cb1e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-texture-level1.html
@@ -0,0 +1,64 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer using texture level 1</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+
+function testFramebufferTextureWithNonZeroBaseLevel(level) {
+ if (level < 1) {
+ throw "This test is incorrect if level < 1";
+ }
+ var width = 32;
+ var height = 16;
+ 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);
+ 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, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, level);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, level);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+}
+
+description("Test fbo completeness when using non level 0 texture images");
+
+var canvas = document.getElementById("canvas");
+shouldBeNonNull("gl = wtu.create3DContext(canvas, undefined, 2)");
+
+testFramebufferTextureWithNonZeroBaseLevel(1);
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html
new file mode 100644
index 0000000000..926e14beab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html
@@ -0,0 +1,201 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer to texture conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test resolving and copying the framebuffer to a texture, and drawing the result.");
+debug('Reduced test case for <a href="http://anglebug.com/6972">http://anglebug.com/6972</a>');
+
+// Reproduces two behaviors:
+//
+// 1) The initial draw disappearing entirely from the default back
+// buffer. The current test case does not show this behavior
+// independently from the other, but a previous iteration, with the
+// textured quad scaled to half size and translated (-0.5, -0.5), did.
+//
+// 2) With Metal debug layers and load/store validation turned on on
+// Intel Macs, the transparent area of the texture prior to the bug
+// fix was magenta = undefined. Similar behavior would presumably
+// reproduce on M1 hardware without debug layers or validation.
+
+const size = 64;
+const halfSize = size / 2;
+const green = [ 0, 255, 0, 255 ];
+const transparent = [ 0, 0, 0, 0 ];
+
+let wtu = WebGLTestUtils;
+let canvas = document.getElementById("canvas");
+canvas.width = size;
+canvas.height = size;
+
+let gl = wtu.create3DContext("canvas", {
+ // Antialiasing is crucial for reproducing the bug.
+ antialias: true,
+ // Depth testing is not.
+ depth: false,
+}, 2);
+
+function allocateTexture(sz) {
+ let texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, sz, sz);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ return texture;
+}
+
+// Allocate destination texture
+let destTexture = allocateTexture(halfSize);
+
+// Set up half-size solid color quad in center
+let colorQuadVAO = gl.createVertexArray();
+gl.bindVertexArray(colorQuadVAO);
+let colorQuadProgram = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
+
+// Setup textured quad covering the entire renderable area
+let quadVAO = gl.createVertexArray();
+gl.bindVertexArray(quadVAO);
+let quadProgram = wtu.setupTexturedQuad(gl, 0, 1);
+gl.useProgram(quadProgram);
+let quadTexLoc = gl.getUniformLocation(quadProgram, "tex");
+gl.uniform1i(quadTexLoc, 0);
+
+gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
+gl.activeTexture(gl.TEXTURE0); // To match quadTexLoc=0
+
+function runTest() {
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.disable(gl.BLEND);
+ gl.bindVertexArray(colorQuadVAO);
+ gl.useProgram(colorQuadProgram);
+ wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]);
+
+ gl.bindTexture(gl.TEXTURE_2D, destTexture);
+ // Copy the upper right corner of the framebuffer to the texture.
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.useProgram(quadProgram);
+ gl.enable(gl.BLEND);
+ gl.bindVertexArray(quadVAO);
+ gl.bindTexture(gl.TEXTURE_2D, destTexture);
+ // Magnify and blend this texture over the current framebuffer.
+ wtu.drawUnitQuad(gl);
+}
+
+function runUserDefinedFBOTest() {
+ let fbo1 = gl.createFramebuffer();
+ let fbo2 = gl.createFramebuffer();
+ let rb = gl.createRenderbuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, size, size);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]);
+
+ let tex = allocateTexture(size, size);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]);
+
+ // Same rendering steps as in the default-framebuffer test, with appropriate framebuffer blits interspersed.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1);
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.disable(gl.BLEND);
+ gl.bindVertexArray(colorQuadVAO);
+ gl.useProgram(colorQuadProgram);
+ wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]);
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
+
+ gl.bindTexture(gl.TEXTURE_2D, destTexture);
+ // Copy the upper right corner of the framebuffer to the texture.
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1);
+
+ gl.useProgram(quadProgram);
+ gl.enable(gl.BLEND);
+ gl.bindVertexArray(quadVAO);
+ gl.bindTexture(gl.TEXTURE_2D, destTexture);
+ // Magnify and blend this texture over the current framebuffer.
+ wtu.drawUnitQuad(gl);
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
+
+ // No longer easy to put these results on the canvas, because it's
+ // antialiased and we can't blitFramebuffer to it. Let's assume
+ // that if failures occur, they'll be straightforward to debug.
+}
+
+function checkRenderingResults(prefix) {
+ // Center quad should be rendered correctly.
+ wtu.checkCanvasRect(gl,
+ halfSize / 2 + 1, halfSize / 2 + 1,
+ halfSize - 2, halfSize - 2,
+ green,
+ prefix + ": center quad should be green");
+
+ // Overlapping lower-left quad should be green as well.
+ wtu.checkCanvasRect(gl,
+ 1, 1,
+ halfSize - 2, halfSize - 2,
+ green,
+ prefix + ": lower left quad should be green");
+
+ // Leftmost area above the lower-left quad should be transparent.
+ wtu.checkCanvasRect(gl,
+ 1, halfSize + 1,
+ halfSize / 2 - 2, halfSize / 2 - 2,
+ transparent,
+ prefix + ": leftmost area above lower left quad should be transparent");
+
+ // Bottommost area to the right of the lower-left quad should be transparent.
+ wtu.checkCanvasRect(gl,
+ halfSize + 1, 1,
+ halfSize / 2 - 2, halfSize / 2 - 2,
+ transparent,
+ prefix + ": bottommost area to the right of lower left quad should be transparent");
+}
+
+runTest();
+checkRenderingResults("default back buffer");
+
+runUserDefinedFBOTest();
+checkRenderingResults("user-defined framebuffer");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-unsupported.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-unsupported.html
new file mode 100644
index 0000000000..1780650ed6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-unsupported.html
@@ -0,0 +1,134 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL FRAMEBUFFER_UNSUPPORTED Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+var canvas = document.getElementById("canvas");
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (expected.indexOf(actual) < 0) {
+ var msg = "checkFramebufferStatus expects [";
+ for (var index = 0; index < expected.length; ++index) {
+ msg += wtu.glEnumToString(gl, expected[index]);
+ if (index + 1 < expected.length)
+ msg += ", ";
+ }
+ msg += "], was " + wtu.glEnumToString(gl, actual);
+ testFailed(msg);
+ } else {
+ var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
+ " as expected";
+ testPassed(msg);
+ }
+}
+
+function testImageAttachedTwoPoints() {
+ debug("");
+ debug("Checking an image is attached to more than one color attachment in a framebuffer.");
+
+ var tex1 = gl.createTexture();
+ var tex2 = gl.createTexture();
+ var fb = gl.createFramebuffer();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ 1, // width
+ 1, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ new Uint8Array(4)); // data
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture creation should succeed.");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex2, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, tex1, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fb);
+ fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ var texCube = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ for (var target = gl.TEXTURE_CUBE_MAP_POSITIVE_X; target < gl.TEXTURE_CUBE_MAP_POSITIVE_X + 6; target++) {
+ gl.texImage2D(target, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ }
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, texCube, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_CUBE_MAP_POSITIVE_X, texCube, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
+
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fb);
+ fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texImage3D(gl.TEXTURE_3D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ 2, // width
+ 2, // height
+ 2, // depth
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ new Uint8Array(4 * 2 * 2 * 2)); // data
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, tex3d, 0, 1);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, tex3d, 0, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
+
+ // Clean up
+ gl.deleteTexture(tex1);
+ gl.deleteTexture(tex2);
+ gl.deleteTexture(texCube);
+ gl.deleteTexture(tex3d);
+ gl.deleteFramebuffer(fb);
+}
+
+description("This tests FRAMEBUFFER_UNSUPPORTED.");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
+
+testImageAttachedTwoPoints();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/fs-color-type-mismatch-color-buffer-type.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/fs-color-type-mismatch-color-buffer-type.html
new file mode 100644
index 0000000000..36f5f50a72
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/fs-color-type-mismatch-color-buffer-type.html
@@ -0,0 +1,169 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>The Color Types of Fragment Shader's Outputs Should Match The Data Types of Color Buffers</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in highp vec4 aPosition;
+void main() {
+ gl_Position = aPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 oColor;
+void main() {
+ oColor = vec4(1.0, 0.0, 0.0, 0.0);
+}
+</script>
+
+<script id="fshaderMRT" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 oColor[2];
+void main() {
+ oColor[0] = vec4(1.0, 0.0, 0.0, 0.0);
+}
+</script>
+
+<script id="fshaderRealMRT" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 oColor[2];
+void main() {
+ oColor[0] = vec4(1.0, 0.0, 0.0, 0.0);
+ oColor[1] = vec4(0.0, 1.0, 0.0, 0.0);
+}
+</script>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies that the color types of fragment shader's outputs should match color buffers' types.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var width = 8;
+var height = 8;
+var tex0;
+var tex1;
+var rb0;
+var rb1;
+var fbo = gl.createFramebuffer();
+var program0;
+var program1;
+var program2;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ init();
+
+ // COLOR_ATTACHMENT0 is fixed-point data, which can be converted to float.
+ // COLOR_ATTACHMENT1 is integer data. The fragment outputs are all float.
+ allocate_textures();
+ check_type_match();
+ allocate_renderbuffers();
+ check_type_match();
+}
+
+function check_type_match() {
+ gl.useProgram(program0);
+ rendering([gl.COLOR_ATTACHMENT0, gl.NONE], gl.NO_ERROR);
+ rendering([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1], gl.INVALID_OPERATION);
+
+ gl.useProgram(program1);
+ rendering([gl.COLOR_ATTACHMENT0, gl.NONE], gl.NO_ERROR);
+ rendering([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1], gl.INVALID_OPERATION);
+
+ gl.useProgram(program2);
+ rendering([gl.COLOR_ATTACHMENT0, gl.NONE], gl.NO_ERROR);
+ rendering([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1], gl.INVALID_OPERATION);
+}
+
+function init() {
+ program0 = wtu.setupProgram(gl, ['vshader', 'fshader'], ['aPosition'], [0]);
+ program1 = wtu.setupProgram(gl, ['vshader', 'fshaderMRT'], ['aPosition'], [0]);
+ program2 = wtu.setupProgram(gl, ['vshader', 'fshaderRealMRT'], ['aPosition'], [0]);
+ if (!program0 || !program1 || !program2) {
+ testFailed("Failed to set up program");
+ return;
+ }
+ testPassed("Succeed to set up program");
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ gl.viewport(0, 0, width, height);
+}
+
+function allocate_textures() {
+ tex0 = gl.createTexture();
+ tex1 = gl.createTexture();
+ wtu.fillTexture(gl, tex0, width, height, [0xff, 0x0, 0x0, 0xff], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA);
+ wtu.fillTexture(gl, tex1, width, height, [0x0, 0xff, 0x0, 0xff], 0, gl.RGBA_INTEGER, gl.UNSIGNED_BYTE, gl.RGBA8UI);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex0, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex1, 0);
+}
+
+function allocate_renderbuffers() {
+ rb0 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb0);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, width, height);
+ rb1 = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb1);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8UI, width, height);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb0);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, rb1);
+}
+
+function rendering(draw_buffers, error) {
+ gl.drawBuffers(draw_buffers);
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, error, "If color buffers' type mismatch the type of fragment shader's outputs, geneate INVALID_OPERATION. Otherwise, it should be NO_ERROR");
+}
+
+gl.bindTexture(gl.TEXTURE_2D, null);
+gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+gl.useProgram(null);
+gl.deleteTexture(tex0);
+gl.deleteTexture(tex1);
+gl.deleteRenderbuffer(rb0);
+gl.deleteRenderbuffer(rb1);
+gl.deleteFramebuffer(fbo);
+gl.deleteProgram(program0);
+gl.deleteProgram(program1);
+gl.deleteProgram(program2);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-arrays.html
new file mode 100644
index 0000000000..65009ea5b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-arrays.html
@@ -0,0 +1,271 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Instanced Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<!-- Shaders for testing instanced draws -->
+<script id="outputVertexShader" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+attribute vec2 aOffset;
+attribute vec4 aColor;
+varying vec4 vColor;
+void main() {
+ vColor = aColor;
+ gl_Position = aPosition + vec4(aOffset, 0.0, 0.0);
+}
+</script>
+
+<script id="outputFragmentShader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 vColor;
+void main() {
+ gl_FragColor = vColor;
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies the functionality of Instanced Arrays.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runDivisorTest();
+ runOutputTests();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runDivisorTest() {
+ debug("Testing VERTEX_ATTRIB_ARRAY_DIVISOR");
+
+ shouldBe("gl.VERTEX_ATTRIB_ARRAY_DIVISOR", "0x88FE");
+
+ var max_vertex_attribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+
+ for (var i = 0; i < max_vertex_attribs; ++i) {
+ var queried_value = gl.getVertexAttrib(i, gl.VERTEX_ATTRIB_ARRAY_DIVISOR);
+ if(queried_value == 0){
+ testPassed("Vertex attribute " + i + " must has a default divisor of 0");
+ }
+ else{
+ testFailed("Default divisor of vertex attribute " + i + " should be: 0, returned value was: " + queried_value);
+ }
+ }
+
+ gl.vertexAttribDivisor(max_vertex_attribs, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "vertexAttribDivisor index set greater than or equal to MAX_VERTEX_ATTRIBS should be an invalid value");
+
+ gl.vertexAttribDivisor(max_vertex_attribs-1, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "vertexAttribDivisor index set less than MAX_VERTEX_ATTRIBS should succeed");
+
+ var queried_value = gl.getVertexAttrib(max_vertex_attribs-1, gl.VERTEX_ATTRIB_ARRAY_DIVISOR);
+ if(queried_value == 2){
+ testPassed("Set value of VERTEX_ATTRIB_ARRAY_DIVISOR matches expecation");
+ }
+ else{
+ testFailed("Set value of VERTEX_ATTRIB_ARRAY_DIVISOR should be: 2, returned value was: " + queried_value);
+ }
+}
+
+function runOutputTests() {
+ var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
+ var instanceCount = 4;
+
+ debug("Testing various draws for valid built-in function behavior");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.clearColor(0, 0, 0, 0);
+
+ var positionLoc = 0;
+ var offsetLoc = 2;
+ var colorLoc = 3;
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['aPosition', 'aOffset', 'aColor'], [positionLoc, offsetLoc, colorLoc]);
+
+ var offsets = new Float32Array([
+ -1.0, 1.0,
+ 1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0,
+ ]);
+ var offsetBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(offsetLoc);
+ gl.vertexAttribPointer(offsetLoc, 2, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(offsetLoc, 1);
+
+ var colors = new Float32Array([
+ 1.0, 0.0, 0.0, 1.0, // Red
+ 0.0, 1.0, 0.0, 1.0, // Green
+ 0.0, 0.0, 1.0, 1.0, // Blue
+ 1.0, 1.0, 0.0, 1.0, // Yellow
+ // extra data when colorLoc divisor is set back to 0
+ 1.0, 1.0, 0.0, 1.0, // Yellow
+ 1.0, 1.0, 0.0, 1.0, // Yellow
+ ]);
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(colorLoc, 1);
+
+ // Draw 1: Draw Non-indexed instances
+ debug("Testing drawArraysInstanced");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.setupUnitQuad(gl, 0);
+
+ // Test drawArraysInstanced error conditions
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.checkCanvasRect(gl, 0, canvas.height/2, canvas.width/2, canvas.height/2, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, canvas.height/2, canvas.width/2, canvas.height/2, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width/2, canvas.height/2, [0, 0, 255, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, 0, canvas.width/2, canvas.height/2, [255, 255, 0, 255]);
+
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, -1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawArraysInstanced cannot have a primcount less than 0");
+
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, -1, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawArraysInstanced cannot have a count less than 0");
+
+ gl.vertexAttribDivisor(positionLoc, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawArraysInstanced");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawArrays");
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "Nothing should be drawn on the framebuffer when all attributes have non-zero divisors (not enough vertices per instance to form a triangle)");
+ gl.vertexAttribDivisor(positionLoc, 0);
+
+ gl.drawArraysInstanced(gl.POINTS, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced with POINTS should succeed");
+ gl.drawArraysInstanced(gl.LINES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced with LINES should succeed");
+ gl.drawArraysInstanced(gl.LINE_LIST, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced with LINE_LIST should return succeed");
+ gl.drawArraysInstanced(gl.TRI_LIST, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced with TRI_LIST should succeed");
+
+ gl.drawArraysInstanced(desktopGL['QUAD_STRIP'], 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstanced with QUAD_STRIP should return INVALID_ENUM");
+ gl.drawArraysInstanced(desktopGL['QUADS'], 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstanced with QUADS should return INVALID_ENUM");
+ gl.drawArraysInstanced(desktopGL['POLYGON'], 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstanced with POLYGON should return INVALID_ENUM");
+
+ debug("Testing drawArraysInstanced with param 'first' > 0");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.setupQuad(gl, {
+ positionLocation: 0,
+ scale: 0.5
+ });
+ var offsetsHalf = new Float32Array([
+ -0.5, 0.5,
+ 0.5, 0.5,
+ -0.5, -0.5,
+ 0.5, -0.5
+ ]);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsetsHalf, gl.STATIC_DRAW);
+
+ gl.drawArraysInstanced(gl.TRIANGLES, 3, 3, instanceCount);
+ var w = Math.floor(0.25*canvas.width),
+ h = Math.floor(0.25*canvas.height);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [0, 0, 255, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
+
+ debug("Testing drawArraysInstanced with attributes 'divisor' reset to 0");
+ debug("Correct rendering output: 4 yellow triangles");
+ debug("Possible incorrect rendering output: missing triangles, or triangles with different color at each vertex");
+ gl.vertexAttribDivisor(colorLoc, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArraysInstanced(gl.TRIANGLES, 3, 3, instanceCount);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [255, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
+ gl.vertexAttribDivisor(colorLoc, 1);
+
+ wtu.setupUnitQuad(gl, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+
+ // Draw 2: Draw indexed instances
+ debug("Testing drawElementsInstanced");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.setupIndexedQuad(gl, 1, 0);
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.checkCanvasRect(gl, 0, canvas.height/2, canvas.width/2, canvas.height/2, [255, 0, 0, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, canvas.height/2, canvas.width/2, canvas.height/2, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width/2, canvas.height/2, [0, 0, 255, 255]);
+ wtu.checkCanvasRect(gl, canvas.width/2, 0, canvas.width/2, canvas.height/2, [255, 255, 0, 255]);
+
+ // Test drawElementsInstanced error conditions
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, -1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawElementsInstanced cannot have a primcount less than 0");
+
+ gl.drawElementsInstanced(gl.TRIANGLES, -1, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawElementsInstanced cannot have a count less than 0");
+
+ gl.vertexAttribDivisor(positionLoc, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawElementsInstanced");
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawElements");
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "Nothing should be drawn on the framebuffer when all attributes have non-zero divisors (not enough vertices per instance to form a triangle)");
+ gl.vertexAttribDivisor(positionLoc, 0);
+
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced with UNSIGNED_BYTE should succeed");
+
+ gl.drawElementsInstanced(gl.POINTS, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced with POINTS should succeed");
+ gl.drawElementsInstanced(gl.LINES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced with LINES should succeed");
+ gl.drawElementsInstanced(gl.LINE_LIST, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced with LINE_LIST should return succeed");
+ gl.drawElementsInstanced(gl.TRI_LIST, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced with TRI_LIST should succeed");
+
+ gl.drawElementsInstanced(desktopGL['QUAD_STRIP'], 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawElementsInstanced with QUAD_STRIP should return INVALID_ENUM");
+ gl.drawElementsInstanced(desktopGL['QUADS'], 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawElementsInstanced with QUADS should return INVALID_ENUM");
+ gl.drawElementsInstanced(desktopGL['POLYGON'], 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawElementsInstanced with POLYGON should return INVALID_ENUM");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-bug.html
new file mode 100644
index 0000000000..59f25096d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-bug.html
@@ -0,0 +1,254 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Instanced Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 128px; height: 128px;"> </canvas>
+<div id="console"></div>
+<script id="outputVertexShader" type="x-shader/x-vertex">#version 300 es
+in highp vec2 aPosition;
+in highp float aOffset;
+in highp float aColor;
+out mediump float vColor;
+void main() {
+ gl_Position = vec4(aPosition, 0.0, 1.0) + vec4(aOffset, 0.0, 0.0, 0.0);
+ vColor = aColor;
+}
+</script>
+
+<script id="outputFragmentShader" type="x-shader/x-fragment">#version 300 es
+layout(location = 0) out mediump vec4 oColor;
+in mediump float vColor;
+void main() {
+ oColor = vec4(vColor, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies a bug related with instanced rendering on Mac AMD.");
+debug("http://crbug.com/645298");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+// The second and fourth test cases fail - it seems if the divisor doesn't change,
+// the next instanced draw call behaves incorrectly.
+// Also note that if we don't perform a readPixels (in wtu.checkCanvasRect), the bug
+// isn't triggered.
+var testCases = [
+ { instanceCount: 8, divisor: 4 },
+ { instanceCount: 6, divisor: 4 },
+ { instanceCount: 6, divisor: 3 },
+ { instanceCount: 8, divisor: 3 },
+];
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ runDrawArraysTest(testCases[ii].instanceCount, testCases[ii].divisor);
+ }
+
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ runDrawElementsTest(testCases[ii].instanceCount, testCases[ii].divisor);
+ }
+}
+
+function runDrawArraysTest(instanceCount, divisor) {
+ debug("");
+ debug("Testing drawArraysInstanced: instanceCount = " + instanceCount + ", divisor = " + divisor);
+
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"]);
+ var positionLoc = gl.getAttribLocation(program, "aPosition");
+ var offsetLoc = gl.getAttribLocation(program, "aOffset");
+ var colorLoc = gl.getAttribLocation(program, "aColor");
+ if (!program || positionLoc < 0 || offsetLoc < 0 || colorLoc < 0) {
+ testFailed("Set up program failed");
+ return;
+ }
+ testPassed("Set up program succeeded");
+
+ var scale = 1.0 / instanceCount;
+
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribDivisor(positionLoc, 0);
+ var positions = new Float32Array([
+ 1.0 * scale, 1.0,
+ -1.0 * scale, 1.0,
+ -1.0 * scale, -1.0,
+ 1.0 * scale, 1.0,
+ -1.0 * scale, -1.0,
+ 1.0 * scale, -1.0,
+ ]);
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.enableVertexAttribArray(offsetLoc);
+ gl.vertexAttribDivisor(offsetLoc, 1);
+ var offsets = new Float32Array(instanceCount);
+ for (var ii = 0; ii < instanceCount; ++ii) {
+ offsets[ii] = scale * (1 - instanceCount + ii * 2);
+ }
+ var offsetBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(offsetLoc, 1, gl.FLOAT, false, 0, 0);
+
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribDivisor(colorLoc, divisor);
+ var colorCount = instanceCount / divisor;
+ if ((instanceCount % divisor) != 0)
+ colorCount++;
+ var colors = new Float32Array(colorCount);
+ for (var ii = 0; ii < colorCount; ++ii) {
+ colors[ii] = 1.0 / colorCount * (ii + 1);
+ }
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(colorLoc, 1, gl.FLOAT, false, 0, 0);
+
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced should succeed");
+
+ var colorIndex = -1;
+ for (var ii = 0; ii < instanceCount; ++ii) {
+ if ((ii % divisor) == 0)
+ colorIndex++;
+ var refColor = [ Math.floor(colors[colorIndex] * 255), 0, 0, 255 ];
+ wtu.checkCanvasRect(gl, Math.floor(canvas.width / instanceCount * ii) + 1, 0, 1, canvas.height, refColor,
+ "instance " + ii + " should be " + refColor, 2);
+ }
+
+ gl.deleteBuffer(positionBuffer);
+ gl.deleteBuffer(offsetBuffer);
+ gl.deleteBuffer(colorBuffer);
+ gl.deleteProgram(program);
+ gl.deleteVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.useProgram(null);
+ gl.bindVertexArray(null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clean up should succeed");
+}
+
+function runDrawElementsTest(instanceCount, divisor) {
+ debug("");
+ debug("Testing drawElementsInstanced: instanceCount = " + instanceCount + ", divisor = " + divisor);
+
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"]);
+ var positionLoc = gl.getAttribLocation(program, "aPosition");
+ var offsetLoc = gl.getAttribLocation(program, "aOffset");
+ var colorLoc = gl.getAttribLocation(program, "aColor");
+ if (!program || positionLoc < 0 || offsetLoc < 0 || colorLoc < 0) {
+ testFailed("Set up program failed");
+ return;
+ }
+ testPassed("Set up program succeeded");
+
+ var scale = 1.0 / instanceCount;
+
+ gl.enableVertexAttribArray(positionLoc);
+ gl.vertexAttribDivisor(positionLoc, 0);
+ var positions = new Float32Array([
+ 1.0 * scale, 1.0,
+ -1.0 * scale, 1.0,
+ -1.0 * scale, -1.0,
+ 1.0 * scale, -1.0,
+ ]);
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.enableVertexAttribArray(offsetLoc);
+ gl.vertexAttribDivisor(offsetLoc, 1);
+ var offsets = new Float32Array(instanceCount);
+ for (var ii = 0; ii < instanceCount; ++ii) {
+ offsets[ii] = scale * (1 - instanceCount + ii * 2);
+ }
+ var offsetBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(offsetLoc, 1, gl.FLOAT, false, 0, 0);
+
+ gl.enableVertexAttribArray(colorLoc);
+ gl.vertexAttribDivisor(colorLoc, divisor);
+ var colorCount = instanceCount / divisor;
+ if ((instanceCount % divisor) != 0)
+ colorCount++;
+ var colors = new Float32Array(colorCount);
+ for (var ii = 0; ii < colorCount; ++ii) {
+ colors[ii] = 1.0 / colorCount * (ii + 1);
+ }
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(colorLoc, 1, gl.FLOAT, false, 0, 0);
+
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ var indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced should succeed");
+
+ var colorIndex = -1;
+ for (var ii = 0; ii < instanceCount; ++ii) {
+ if ((ii % divisor) == 0)
+ colorIndex++;
+ var refColor = [ Math.floor(colors[colorIndex] * 255), 0, 0, 255 ];
+ wtu.checkCanvasRect(gl, Math.floor(canvas.width / instanceCount * ii) + 1, 0, 1, canvas.height, refColor,
+ "instance " + ii + " should be " + refColor, 2);
+ }
+
+ gl.deleteBuffer(positionBuffer);
+ gl.deleteBuffer(offsetBuffer);
+ gl.deleteBuffer(colorBuffer);
+ gl.deleteBuffer(indexBuffer);
+ gl.deleteProgram(program);
+ gl.deleteVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ gl.useProgram(null);
+ gl.bindVertexArray(null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clean up should succeed");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-large-divisor.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-large-divisor.html
new file mode 100644
index 0000000000..229649ee3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/instanced-rendering-large-divisor.html
@@ -0,0 +1,145 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Instanced Arrays Conformance Tests - large vertex attrib divisors</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas"> </canvas>
+<div id="console"></div>
+<script id="outputVertexShader" type="x-shader/x-vertex">#version 300 es
+layout(location = 0) in vec2 a_position;
+layout(location = 1) in float a_positionOffset;
+layout(location = 2) in vec4 a_color;
+out vec4 v_color;
+void main()
+{
+ gl_Position = vec4(a_position.x * 0.05 + a_positionOffset, a_position.y * 0.05, 0.0, 1.0);
+ v_color = a_color;
+}
+</script>
+
+<script id="outputFragmentShader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+in vec4 v_color;
+out vec4 my_FragColor;
+void main()
+{
+ my_FragColor = v_color;
+}
+</script>
+
+<script>
+"use strict";
+description("Test switching vertex attrib divisor of one attribute between different large values");
+// This is a regression test for http://anglebug.com/2832
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+canvas.width = 256;
+canvas.height = 256;
+var gl = wtu.create3DContext(canvas, null, 2);
+
+var colorDivisor = 65536 * 2;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runTest();
+}
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"]);
+
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
+
+ wtu.setupIndexedQuadWithOptions(gl, {positionLocation: 0});
+
+ var offsetBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuf);
+ // Note that only the first two offsets below should be used for rendering.
+ // We add some extra ones to the buffer since it can reveal if a too small divisor is used on the WebGL backend.
+ var offsetData = [];
+ for (var i = 0; i < 4; ++i) {
+ offsetData.push(0.0 + i * 0.25);
+ }
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(offsetData), gl.DYNAMIC_DRAW);
+
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up vertex buffer should succeed");
+
+ var colorBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuf);
+ // Red and green colors.
+ var colorData = new Float32Array([1.0, 0.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0]);
+ gl.bufferData(gl.ARRAY_BUFFER, colorData, gl.DYNAMIC_DRAW);
+
+ gl.enableVertexAttribArray(2);
+ gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(2, colorDivisor);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up color buffer should succeed");
+
+ var divisorsToTry = [
+ 256,
+ 65536,
+ 65536 * 2
+ ];
+
+ for (var i = 0; i < divisorsToTry.length; ++i) {
+ runDrawElementsTest(divisorsToTry[i]);
+ }
+}
+
+function runDrawElementsTest(divisor) {
+ debug("Using divisor " + divisor);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.vertexAttribDivisor(1, divisor);
+
+ var instanceCount = divisor + 1;
+ var quadsRendered = Math.floor((instanceCount - 1) / divisor) + 1;
+
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Instanced draw should succeed");
+
+ for (var quadIndex = 0; quadIndex < quadsRendered + 1; ++quadIndex) {
+ var quadX = Math.floor((quadIndex / 8) * 256 + 128);
+ var quadY = 128;
+ if (quadIndex < quadsRendered) {
+ var quadColorIndex = Math.floor((quadIndex * divisor) / colorDivisor);
+ if (quadColorIndex == 0) {
+ wtu.checkCanvasRect(gl, quadX, quadY, 1, 1, [255, 0, 0, 255]);
+ } else {
+ wtu.checkCanvasRect(gl, quadX, quadY, 1, 1, [0, 255, 0, 255]);
+ }
+ } else {
+ wtu.checkCanvasRect(gl, quadX, quadY, 1, 1, [0, 0, 255, 255]);
+ }
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/line-rendering-quality.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/line-rendering-quality.html
new file mode 100644
index 0000000000..24442ea3c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/line-rendering-quality.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Line rendering quality test</title>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="testbed" width="256" height="256"></canvas>
+<canvas id="testbed2" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/line-rendering-quality.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-depth-resolve.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-depth-resolve.html
new file mode 100644
index 0000000000..14aeab4f87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-depth-resolve.html
@@ -0,0 +1,179 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL framebuffer to texture conformance test.</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test resolving multisample depth buffer");
+debug('Reduced test case for <a href="https://bugs.webkit.org/show_bug.cgi?id=238118">https://bugs.webkit.org/show_bug.cgi?id=238118</a>');
+
+// Reproduces an inconistent behavior where if:
+// 1) You render into a multisampling frame buffer
+// 2) Geometry is drawn with DEPTH_TEST disabled and then enabled
+// 3) More than one frame is rendered via requestAnimationFrame
+
+const size = 64;
+const halfSize = size / 2;
+
+let wtu = WebGLTestUtils;
+let canvas = document.getElementById("canvas");
+canvas.width = size;
+canvas.height = size;
+
+let gl = wtu.create3DContext("canvas", {}, 2);
+
+function createTexture(res, format, bytes) {
+ let texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, res, res);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ return texture;
+}
+
+function createRenderBuffer(res, format, samples) {
+ let rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ if (samples > 1)
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, format, res, res);
+ else
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, res, res);
+ return rb;
+}
+
+let yellowQuadVAO = gl.createVertexArray();
+gl.bindVertexArray(yellowQuadVAO);
+let yellowQuadProgram = wtu.setupColorQuad(gl, 0, { scale: 0.75 });
+
+let blueQuadVAO = gl.createVertexArray();
+gl.bindVertexArray(blueQuadVAO);
+let blueQuadProgram = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
+
+let fsVAO = gl.createVertexArray();
+gl.bindVertexArray(fsVAO);
+let fsProgram = wtu.setupTexturedQuad(gl, 0, 1);
+gl.useProgram(fsProgram);
+let fsTexLoc = gl.getUniformLocation(fsProgram, "tex");
+gl.uniform1i(fsTexLoc, 0);
+
+// An incorrect render can occur if...
+
+// 1) You use renderbufferStorageMultisample.
+const msaaSamples = 4;
+const colorRB = createRenderBuffer(size, gl.RGBA8, msaaSamples);
+const depthRB = createRenderBuffer(size, gl.DEPTH_COMPONENT16, msaaSamples);
+const resolveTex = createTexture(size, gl.RGBA8);
+
+let renderFBO = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, renderFBO);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRB);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRB);
+
+let resolveFBO = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFBO);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, resolveTex, 0);
+gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+gl.disable(gl.CULL_FACE);
+gl.disable(gl.BLEND);
+
+var frameCount = 0;
+function runTest() {
+ // 2) Render from requestAnimationFrame, only starting with the 2nd frame.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, renderFBO);
+
+ // Clear background red
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
+
+ // 3) You disable gl.DEPTH_TEST
+ gl.disable(gl.DEPTH_TEST);
+ gl.depthMask(false);
+
+ gl.bindVertexArray(yellowQuadVAO);
+ gl.useProgram(yellowQuadProgram);
+ wtu.drawUByteColorQuad(gl, [ 255, 255, 0, 255 ]);
+
+ // 4) And re-enable gl.DEPTH_TEST
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthMask(true);
+
+ gl.bindVertexArray(blueQuadVAO);
+ gl.useProgram(blueQuadProgram);
+ wtu.drawUByteColorQuad(gl, [ 0, 0, 255, 255 ]);
+
+ // Resolve the multisample framebuffer to a texture
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, renderFBO);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFBO);
+ gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 0.0]);
+ gl.blitFramebuffer(0, 0, size, size,
+ 0, 0, size, size,
+ gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+
+ // Draw the resolved texture to the backbuffer
+ gl.bindTexture(gl.TEXTURE_2D, resolveTex);
+ gl.useProgram(fsProgram);
+ gl.bindVertexArray(fsVAO);
+ wtu.drawUnitQuad(gl);
+
+ // 5) The incorrect render can occur on the second rendered frame, called from
+ // requestAnimationFrame.
+ frameCount++;
+ if (frameCount == 2) {
+ checkRenderingResults("multisampling-depth-resolve");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
+ finishTest();
+ } else {
+ requestAnimationFrame(runTest);
+ }
+}
+
+requestAnimationFrame(runTest);
+
+function checkRenderingResults(prefix) {
+ // Outer color should be red
+ wtu.checkCanvasRect(gl,
+ 1, 1,
+ 2, 2,
+ [255, 0, 0, 255],
+ prefix + ": outer pixels should be red");
+
+ // Outer quad should be rendered yellow.
+ wtu.checkCanvasRect(gl,
+ 10, 10,
+ 2, 2,
+ [255, 255, 0, 255],
+ prefix + ": outer quad should be yellow");
+
+ // Center quad should be rendered blue.
+ wtu.checkCanvasRect(gl,
+ halfSize / 2 + 1, halfSize / 2 + 1,
+ 2, 2,
+ [0, 0, 255, 255],
+ prefix + ": center quad should be blue");
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-fragment-evaluation.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-fragment-evaluation.html
new file mode 100644
index 0000000000..df7bce9b09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/multisampling-fragment-evaluation.html
@@ -0,0 +1,143 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL multisampling fragment shader evaluation</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+layout(location=0) in vec4 aPosition;
+out vec4 vPosition;
+void main()
+{
+ gl_Position = vec4(aPosition);
+ vPosition = aPosition;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+in vec4 vPosition;
+layout(location=0) out vec4 oColor;
+void main()
+{
+ if (vPosition.x < 0.0) {
+ oColor = vec4(1, 0, 0, 1);
+ } else if (vPosition.y < 0.0) {
+ oColor = vec4(0, 1, 0, 1);
+ } else {
+ oColor = vec4(0, 0, 1, 1);
+ }
+}
+</script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("Verify that fragment shader is evaluated only once per framebuffer pixel when multisampling is used.");
+
+// GLES 3.0.5 section 3.6.3. Polygon Multisample Rasterization:
+// "Polygon rasterization produces a fragment for each framebuffer pixel with one or more sample points that satisfy
+// the point sampling criteria described in section 3.6.1."
+
+debug("Regression test for <a href='http://crbug.com/682815'>http://crbug.com/682815</a>");
+
+function runTest(testParams) {
+ let canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = 1;
+ let gl = wtu.create3DContext(canvas, {antialias: false}, 2);
+
+ // Find the supported samples for a multisampled renderbuffer of the appropriate internal format.
+ let samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl[testParams.internalformat], gl.SAMPLES);
+ if (!samples || !samples.length) {
+ testFailed("Could not query supported sample counts for required multisampling format " + testParams.internalformat);
+ return;
+ }
+
+ // Note that supported sample counts are required to be reported in descending order.
+ debug('Testing with sample count ' + samples[0]);
+ // Create a framebuffer with a multisampled renderbuffer with the maximum supported number of samples.
+ let rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl[testParams.internalformat], 1, 1);
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Rendering to a multisampled renderbuffer of format " + testParams.internalformat + " is required.");
+ return;
+ }
+
+ // Create a program that will choose between one of different possible colors in the fragment shader.
+ // It should be evaluated only once per framebuffer pixel, so only one of the colors will end up in the framebuffer.
+ // However, if the multisampling mode is incorrectly implemented by supersampling, the samples may have different
+ // colors.
+ let program = wtu.setupProgram(gl, ["vshader", "fshader"], ["aPosition"]);
+
+ // Render one triangle using the program. The triangle needs to extend far outside the viewport on all sides, so
+ // that we can safely assume all samples fall inside the triangle. GLES 3.0.5:
+ // "The sample points associated with a pixel may be located inside or outside of the unit square that is considered to bound the pixel."
+ // Here we assume that sample points are less than 9999 pixels away from the pixel they are associated with.
+ let buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 10000, 30000,
+ -30000, -10000,
+ 10000, -10000]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.blitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+
+ let readBuffer = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readBuffer);
+
+ // Check that the canvas is one of the colors that the fragment shader may generate, and not a blend of them.
+ let possibleColors = [
+ [255, 0, 0, 255],
+ [0, 255, 0, 255],
+ [0, 0, 255, 255]
+ ];
+ let anyColorMatched = false;
+ for (let i = 0; i < possibleColors.length; ++i) {
+ let colorMatched = true;
+ for (let j = 0; j < 4; ++j) {
+ if (Math.abs(readBuffer[j] - possibleColors[i][j]) > 2) {
+ colorMatched = false;
+ }
+ }
+ if (colorMatched) {
+ anyColorMatched = true;
+ }
+ }
+ if (!anyColorMatched) {
+ testFailed("Color in framebuffer was not one of the colors generated by the fragment shader: " + readBuffer);
+ } else {
+ testPassed("Color in framebuffer was one of the colors generated by the fragment shader: " + readBuffer);
+ }
+}
+
+runTest({internalformat: 'RGBA8'});
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/out-of-bounds-index-buffers-after-copying.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/out-of-bounds-index-buffers-after-copying.html
new file mode 100644
index 0000000000..39bbb5e348
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/out-of-bounds-index-buffers-after-copying.html
@@ -0,0 +1,187 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<title>WebGL Out-of-Bounds Index Buffer Caused by CopyBufferSubData Conformance Test</title>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
+ #define TEST_CASE_IN_BOUND 1
+ #define TEST_CASE_OUT_OF_BOUND 2
+
+ precision mediump float;
+ attribute vec2 position;
+ attribute vec4 vecRandom;
+ varying vec4 v_color;
+ uniform int u_testCase;
+
+ bool testFloatComponentAccurate(float component) {
+ return component == 0.2;
+ }
+ // Per the spec, each component can either contain existing contents
+ // of the buffer or 0.
+ bool testFloatComponent(float component) {
+ return (component == 0.2 || component == 0.0);
+ }
+ // The last component is additionally allowed to be 1.0.
+ bool testLastFloatComponent(float component) {
+ return testFloatComponent(component) || component == 1.0;
+ }
+
+ bool testData(vec4 data) {
+ if (u_testCase == TEST_CASE_IN_BOUND) {
+ return (testFloatComponentAccurate(data.x) &&
+ testFloatComponentAccurate(data.y) &&
+ testFloatComponentAccurate(data.z) &&
+ testFloatComponentAccurate(data.w));
+ } else if (u_testCase == TEST_CASE_OUT_OF_BOUND) {
+ return (testFloatComponent(data.x) &&
+ testFloatComponent(data.y) &&
+ testFloatComponent(data.z) &&
+ testLastFloatComponent(data.w));
+ }
+ return false;
+ }
+
+ void main() {
+ if (testData(vecRandom)) {
+ v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- We're good
+ } else {
+ v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
+ }
+ gl_Position = vec4(position, 0.0, 1.0);
+ }
+</script>
+<script>
+"use strict";
+description("This test verifies that out-of-bounds index buffers caused by CopyBufferSubData behave according to spec.");
+
+// Ensure that drawElements flags either no error or INVALID_OPERATION. In the case of INVALID_OPERATION,
+// no canvas pixels can be touched. In the case of NO_ERROR, all written values must either be the
+// zero vertex or a value in the vertex buffer. See vsCheckOutOfBounds shader.
+function verifyOutOfBoundsIndex(gl) {
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
+ }
+}
+
+// Create an element array buffer with a tri-strip that starts at startIndex and make
+// it the active element array buffer.
+function prepareElementArrayBuffer(gl, startIndex) {
+ var glElementArrayBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, glElementArrayBuffer);
+ var quadIndices = new Uint16Array(4);
+ for (var i = 0; i < quadIndices.length; i++) {
+ quadIndices[i] = startIndex + i;
+ }
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, quadIndices, gl.STATIC_DRAW);
+ return glElementArrayBuffer;
+}
+
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false}, 2);
+
+var numberOfQuads = 200;
+
+// Create a vertex buffer with 200 properly formed tri-strip quads. These quads will cover the canvas texture
+// such that every single pixel is touched by the fragment shader.
+var quadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+var quadPositions = new Float32Array(numberOfQuads * /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4);
+for (var i = 0; i < quadPositions.length; i += /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4) {
+ quadPositions[i+0] = -1.0; // upper left
+ quadPositions[i+1] = 1.0;
+ quadPositions[i+2] = 1.0; // upper right
+ quadPositions[i+3] = 1.0;
+ quadPositions[i+4] = -1.0; // lower left
+ quadPositions[i+5] = -1.0;
+ quadPositions[i+6] = 1.0; // lower right
+ quadPositions[i+7] = -1.0;
+}
+gl.bufferData(gl.ARRAY_BUFFER, quadPositions, gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+// Create a small vertex buffer with determined-ahead-of-time "random" values (0.2). This buffer will be
+// the one indexed off the end.
+var vertexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+gl.bufferData(gl.ARRAY_BUFFER,
+ new Float32Array([0.2, 0.2, 0.2, 0.2,
+ 0.2, 0.2, 0.2, 0.2,
+ 0.2, 0.2, 0.2, 0.2,
+ 0.2, 0.2, 0.2, 0.2]),
+ gl.STATIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+
+// Setup the verification program.
+var program = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup should generate no errors");
+var loc = gl.getUniformLocation(program, "u_testCase");
+shouldBeNonNull(loc);
+
+debug("");
+debug("Test -- Vertex indices are in bounds.");
+gl.uniform1i(loc, 1); // TEST_CASE_IN_BOUND == 1
+gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+var elementArrayBuffer = prepareElementArrayBuffer(gl, /*StartIndex*/0);
+gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, /*offset*/0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw call should generate no errors");
+wtu.checkCanvas(gl, [0, 255, 0, 255]);
+
+debug("");
+debug("Test -- Index off the end of the vertex buffer near the beginning of the out of bounds area.");
+gl.uniform1i(loc, 2); // TEST_CASE_OUT_OF_BOUND == 2
+gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+var outOfBoundsElementArrayBuffer = prepareElementArrayBuffer(gl, /*StartIndex*/4);
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, outOfBoundsElementArrayBuffer);
+gl.bindBuffer(gl.COPY_WRITE_BUFFER, elementArrayBuffer);
+gl.copyBufferSubData(gl.ELEMENT_ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 4 * Uint16Array.BYTES_PER_ELEMENT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copyBufferSubData should generate no errors");
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
+gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, /*offset*/0);
+verifyOutOfBoundsIndex(gl);
+
+debug("");
+debug("Test -- Index off the end of the vertex buffer near the end of the out of bounds area.")
+gl.uniform1i(loc, 2); // TEST_CASE_OUT_OF_BOUND == 2
+gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+outOfBoundsElementArrayBuffer = prepareElementArrayBuffer(gl, /*StartIndex*/numberOfQuads - 4);
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
+gl.bindBuffer(gl.COPY_READ_BUFFER, outOfBoundsElementArrayBuffer);
+gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ELEMENT_ARRAY_BUFFER, 0, 0, 4 * Uint16Array.BYTES_PER_ELEMENT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copyBufferSubData should generate no errors");
+gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, /*offset*/0);
+verifyOutOfBoundsIndex(gl);
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Running tests should generate no errors");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rasterizer-discard-and-implicit-clear.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rasterizer-discard-and-implicit-clear.html
new file mode 100644
index 0000000000..f605a25f26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rasterizer-discard-and-implicit-clear.html
@@ -0,0 +1,149 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>RASTERIZER_DISCARD doesn't affect implicit clears</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+layout(location=0) in vec2 vPosition;
+uniform float xTranslation;
+void main(void) {
+ gl_Position = vec4(vPosition[0] + xTranslation, vPosition[1], 0.0, 1.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform vec4 color;
+out vec4 outColor;
+void main() {
+ outColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Enabling RASTERIZER_DISCARD should not affect implicit clears");
+
+const wtu = WebGLTestUtils;
+const canvas = document.getElementById("example");
+const sz = canvas.width = canvas.height = 256;
+const gl = wtu.create3DContext(canvas, undefined, 2);
+const NUM_FRAMES = 15;
+let framesToGo = NUM_FRAMES;
+let xTranslationLoc;
+let colorLoc;
+const positionLocation = 0;
+const red = [ 1.0, 0.0, 0.0, 1.0 ];
+const green = [ 0.0, 1.0, 0.0, 1.0 ];
+const transparentBlackRender = [ 0, 0, 0, 0 ];
+const greenRender = [ 0, 255, 0, 255 ];
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+ finishTest();
+} else {
+ testPassed("WebGL context creation succeeded");
+ runDrawTest();
+}
+
+function runDrawTest() {
+ debug("Verify that draws with rasterizer discard enabled do not interfere with implicit clears");
+ let prog = wtu.loadProgramFromScript(gl, "vshader", "fshader");
+ gl.useProgram(prog);
+ xTranslationLoc = gl.getUniformLocation(prog, "xTranslation");
+ colorLoc = gl.getUniformLocation(prog, "color");
+ let leftRectBuffer = gl.createBuffer();
+ gl.enableVertexAttribArray(positionLocation);
+ gl.bindBuffer(gl.ARRAY_BUFFER, leftRectBuffer);
+ // Create a rectangle covering the left half of the viewport, in
+ // normalized device coordinates.
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 0.0, 1.0,
+ -1.0, -1.0,
+ 0.0, -1.0]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+ requestAnimationFrame(renderDrawTestFrame);
+}
+
+function renderDrawTestFrame() {
+ // Animation is required in order to expose this bug. When it
+ // occurs, the rectangle leaves trails behind it.
+ gl.uniform1f(xTranslationLoc, 0.0);
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.uniform4fv(colorLoc, red);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ // Animate the rectangle from the left to the right half of the viewport.
+ gl.uniform1f(xTranslationLoc, (NUM_FRAMES - framesToGo) / NUM_FRAMES);
+ // Draw the last frame with green so any (incorrect) trails are visibly red.
+ if (framesToGo == 0)
+ gl.uniform4fv(colorLoc, green);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ if (framesToGo-- == 0) {
+ // The left half of the canvas should be transparent black,
+ // which comes from the implicit clear just before drawing the
+ // rectangle without rasterizer discard enabled.
+ wtu.checkCanvasRect(gl, 0, 0, sz / 2, sz, transparentBlackRender, "left half of canvas should be clear", 3);
+ // The right half of the canvas should be solid green, from
+ // the last render of the translated rectangle.
+ wtu.checkCanvasRect(gl, sz / 2, 0, sz / 2, sz, greenRender, "right half of canvas should be green", 3);
+ runReadPixelsTest();
+ } else {
+ requestAnimationFrame(renderDrawTestFrame);
+ }
+}
+
+function runReadPixelsTest() {
+ debug("Verify that readPixels with rasterizer discard enabled receives implicitly cleared data");
+ framesToGo = NUM_FRAMES; // Reset state.
+ // Clear to transparent black.
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Start with rasterizer discard enabled.
+ gl.enable(gl.RASTERIZER_DISCARD);
+ requestAnimationFrame(renderReadPixelsTestFrame);
+}
+
+function renderReadPixelsTestFrame() {
+ // Rasterizer discard is enabled at the beginning of this test.
+
+ // The canvas should always contain transparent black at the beginning of the frame.
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz, transparentBlackRender, undefined, 3);
+
+ gl.disable(gl.RASTERIZER_DISCARD);
+ // Clear to red.
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Enable rasterizer discard again.
+ gl.enable(gl.RASTERIZER_DISCARD);
+
+ if (--framesToGo == 0) {
+ finishTest();
+ } else {
+ requestAnimationFrame(renderReadPixelsTestFrame);
+ }
+}
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/read-draw-when-missing-image.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/read-draw-when-missing-image.html
new file mode 100644
index 0000000000..a9d8c74b9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/read-draw-when-missing-image.html
@@ -0,0 +1,288 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Read or Draw when Attachment(s) Miss Image</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of reading/drawing when color attachment(s) miss image.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var tex_read = gl.createTexture();
+var tex_draw = gl.createTexture();
+var tex_depth = gl.createTexture();
+var tex_stencil = gl.createTexture();
+var fbo_read = gl.createFramebuffer();
+var fbo_draw = gl.createFramebuffer();
+var size = 8;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // READ_FRAMEBUFFER has image at COLOR_ATTACHMENT0. READ_FRAMEBUFFER is framebuffer complete.
+ // Read from COLOR_ATTACHMENT1, which has no image attached.
+ init_read_fbo();
+ read();
+
+ // DRAW_FRAMEBUFFER has image at COLOR_ATTACHMENT0. DRAW_FRAMEBUFFER is framebuffer complete.
+ // Clear and draw COLOR_ATTACHMENT1 or COLOR_ATTACHMENT0 + COLOR_ATTACHMENT1 attaching point(s).
+ init_draw_fbo();
+ clear();
+ draw();
+
+ blit();
+}
+
+function init_read_fbo() {
+ gl.bindTexture(gl.TEXTURE_2D, tex_read);
+ wtu.fillTexture(gl, tex_read, size, size, [0x0, 0xff, 0xff, 0xff], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0);
+ if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ } else {
+ testPassed("framebuffer complete!");
+ }
+}
+
+function init_draw_fbo() {
+ gl.bindTexture(gl.TEXTURE_2D, tex_draw);
+ wtu.fillTexture(gl, tex_draw, size, size, [0x0, 0xff, 0xff, 0xff], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8);
+ wtu.fillTexture(gl, tex_depth, size, size, [0x80], 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, gl.DEPTH_COMPONENT16);
+ wtu.fillTexture(gl, tex_stencil, size, size, [0x40], 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, gl.DEPTH24_STENCIL8);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_draw, 0);
+ if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ } else {
+ testPassed("framebuffer complete!");
+ }
+}
+
+function read() {
+ debug("");
+ debug("read from a color buffer which has no image attached");
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_read);
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+
+ var data = new Uint8Array(size * size * 4);
+ gl.readPixels(0, 0, size, size, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image.");
+
+ var copy_2d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, copy_2d);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, size, size, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image.");
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, size / 2, size / 2, 0, 0, size / 2, size / 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image.");
+
+ var copy_3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, copy_3d);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, size, size, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, size / 2, size / 2, 0, 0, 0, size / 2, size / 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image.");
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(copy_2d);
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.deleteTexture(copy_3d);
+}
+
+function checkTextureValue(fbo, buffer, value) {
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo);
+ gl.readBuffer(buffer);
+ wtu.checkCanvas(gl, value);
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+}
+
+function clear() {
+ debug("");
+ debug("clear a color buffer which has no image attached");
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ var color = [0.0, 1.0, 0.0, 1.0];
+ gl.clearColor(color[0], color[1], color[2], color[3]);
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 should be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 0, 255]);
+
+ var data = new Float32Array(color);
+ gl.clearBufferfv(gl.COLOR, 1, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+}
+
+function draw() {
+ debug("");
+ debug("draw to a color buffer which has no image attached");
+
+ var program = wtu.setupSimpleColorProgram(gl, 0);
+ gl.uniform4f(gl.getUniformLocation(program, "u_color"), 1, 0, 0, 1);
+ wtu.setupUnitQuad(gl, 0);
+
+ // Call to drawArrays
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 0, 255]);
+
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 should be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 0, 0, 255]);
+
+ // Call to drawElements
+ gl.uniform4f(gl.getUniformLocation(program, "u_color"), 1, 1, 0, 1);
+ wtu.setupIndexedQuad(gl, 1);
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ wtu.drawIndexedQuad(gl, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 0, 0, 255]);
+
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ wtu.drawIndexedQuad(gl, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 should be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 255, 0, 255]);
+}
+
+function blit() {
+ debug("");
+ debug("blit color buffer(s) which have no image attached");
+ // Some or all draw buffers have no image. Read buffer have image. It should be OK.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 255, 0, 255]);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 in draw fbo should be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]);
+
+ // Draw buffer(s) have no image. Read buffer have no image. It should be OK.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]);
+
+ // Read buffer have no image. Some or all draw buffers have image. It should generate INVALID_OPERATION.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when read buffer misses image.");
+ // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.readBuffer(gl.COLOR_ATTACHMENT1);
+ gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when read buffer misses image.");
+ // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed.
+ checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]);
+
+ // Depth buffer in read fbo has no image. It should generate INVALID_OPERATION if depth buffer in draw fbo has image.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, tex_depth, 0);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when depth buffer misses image.");
+
+ // Depth buffer in read fbo has no image. It should be OK if depth buffer in draw fbo has no image too.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, null, 0);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // Validate some other parameters as usual
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.DEPTH_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid filter");
+
+ // Stencil buffer in read fbo has no image. It should generate INVALID_OPERATION if stencil buffer in draw fbo has image.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex_stencil, 0);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.STENCIL_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when stencil buffer misses image.");
+
+ // Stencil buffer in read fbo has no image. It should be OK if stencil buffer in draw fbo has no image too.
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, null, 0);
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.STENCIL_BUFFER_BIT, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error.");
+ // Validate some other parameters as usual
+ gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.STENCIL_BUFFER_BIT, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid filter");
+}
+
+gl.bindTexture(gl.TEXTURE_2D, null);
+gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+gl.deleteTexture(tex_read);
+gl.deleteTexture(tex_draw);
+gl.deleteTexture(tex_depth);
+gl.deleteTexture(tex_stencil);
+gl.deleteFramebuffer(fbo_read);
+gl.deleteFramebuffer(fbo_draw);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rgb-format-support.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rgb-format-support.html
new file mode 100644
index 0000000000..46712ae68b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/rgb-format-support.html
@@ -0,0 +1,111 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+description("Verify RGB/RGB8 textures and renderbuffers support");
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+function testRenderbuffer(width, height) {
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGB8, gl.SAMPLES);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from getInternalformatParameter()");
+
+ if (!samples || samples.length == 0) {
+ testFailed("getInternalformatParameter on RGB8 fails to return valid samples");
+ return;
+ }
+
+ for (var idx = 0; idx < samples.length + 2; ++idx) {
+ debug("");
+ var renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ var sampleCount = 0;
+ switch (idx) {
+ case samples.length:
+ sampleCount = 0;
+ break;
+ case samples.length + 1:
+ sampleCount = -1; // non multisampled
+ break;
+ default:
+ sampleCount = samples[idx];
+ }
+
+ if (sampleCount < 0) {
+ debug("test non-multisampled RGB8 renderbuffer");
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB8, 2, 2);
+ } else {
+ debug("test RGB8 renderbuffer with " + sampleCount + " samples");
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, sampleCount, gl.RGB8, width, height);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from renderbufferStorage{Multisample}");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("framebuffer with renderbuffer is incomplete");
+ } else {
+ testPassed("framebuffer with renderbuffer is complete");
+ }
+
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear()");
+ }
+}
+
+function testTexture(width, height) {
+ var formats = [ "RGB", "RGB8" ];
+ for (var idx = 0; idx < formats.length; ++idx) {
+ debug("");
+ debug("test texture format " + formats[idx]);
+ var internalformat = gl[formats[idx]];
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture setup");
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("framebuffer with texture is incomplete");
+ } else {
+ testPassed("framebuffer with texture is complete");
+ }
+
+ gl.clearColor(1, 0, 1, 1);
+ gl.clear(gl.COLOR_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear()");
+ }
+}
+
+if (!gl) {
+ testFailed('canvas.getContext() failed');
+} else {
+ testRenderbuffer(2, 2);
+ testTexture(2, 2);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/texture-switch-performance.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/texture-switch-performance.html
new file mode 100644
index 0000000000..da7a9e2f57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/texture-switch-performance.html
@@ -0,0 +1,101 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Texture Switch Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Ensures that switching the texture referenced by a sampler uniform performs reasonably well.");
+var wtu = WebGLTestUtils;
+var canvas = document.createElement('canvas');
+canvas.width = 32;
+canvas.height = 32;
+var gl = wtu.create3DContext(canvas, undefined, 2);
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var program = wtu.setupTexturedQuad(gl);
+ var tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var tex2 = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var loc = gl.getUniformLocation(program, "tex");
+
+ var RUNTIME = 2000;
+ var THRESHOLD = 0.8;
+ var baseStartTime = 0;
+ var baseFrameCount = 0;
+ var testStartTime = 0;
+ var testFrameCount = 0;
+
+ baseStartTime = Date.now();
+ function drawBaseline() {
+ for (var i = 0; i < 400; ++i) {
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ ++baseFrameCount;
+
+ if (Date.now() - baseStartTime > RUNTIME) {
+ testStartTime = Date.now();
+ requestAnimationFrame(drawTest);
+ } else {
+ requestAnimationFrame(drawBaseline);
+ }
+ }
+
+ function drawTest() {
+ for (var i = 0; i < 400; ++i) {
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.uniform1i(loc, 1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ ++testFrameCount;
+
+ if (Date.now() - testStartTime > RUNTIME) {
+ var perfString = " - achieved " + testFrameCount + " frames in " + ((Date.now() - testStartTime) / 1000.0) +
+ " seconds (" + (testFrameCount / baseFrameCount).toFixed(2) + " times baseline performance)";
+ if (testFrameCount > baseFrameCount * THRESHOLD) {
+ testPassed("Texture switching did not significantly hurt performance" + perfString);
+ } else {
+ testFailed("Texture switching significantly hurt performance" + perfString);
+ }
+ console.log(testFrameCount);
+ finishTest();
+ } else {
+ requestAnimationFrame(drawTest);
+ }
+ }
+
+ requestAnimationFrame(drawBaseline);
+}
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/uniform-block-buffer-size.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/uniform-block-buffer-size.html
new file mode 100644
index 0000000000..35cc5205d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/uniform-block-buffer-size.html
@@ -0,0 +1,228 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL UniformBlock Buffer Size Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id='vshader' type='x-shader/x-vertex'>#version 300 es
+layout(location=0) in vec3 p;
+void main()
+{
+ gl_Position = vec4(p.xyz, 1.0);
+}
+</script>
+<script id='fshader' type='x-shader/x-fragment'>#version 300 es
+precision mediump float;
+layout(location=0) out vec4 oColor;
+
+uniform UBOData {
+ float UBORed;
+ float UBOGreen;
+ float UBOBlue;
+};
+
+void main()
+{
+ oColor = vec4(UBORed, UBOGreen, UBOBlue, 1.0);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies an active UniformBlock should be populated with a large enough buffer object");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runDrawArraysTests();
+ runDrawElementsTests();
+}
+
+function runDrawArraysTests() {
+ debug("");
+ debug("Testing drawArrays and drawArraysInstanced");
+
+ var instanceCount = 4;
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ if (!program) {
+ testFailed("Could not compile shader with uniform blocks without error");
+ return;
+ }
+
+ var blockIndex = gl.getUniformBlockIndex(program, "UBOData");
+ var blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices = gl.getUniformIndices(program, ["UBORed", "UBOGreen", "UBOBlue"]);
+ var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+
+ if (uniformOffsets.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ var uboArray = new ArrayBuffer(blockSize);
+ var uboFloatView = new Float32Array(uboArray);
+ uboFloatView[uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBORed
+ uboFloatView[uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOGreen
+ uboFloatView[uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOBlue
+
+ var binding = 1;
+ gl.uniformBlockBinding(program, blockIndex, binding);
+
+ wtu.setupUnitQuad(gl);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up succeeded");
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArrays: UniformBlock is not backed by a buffer");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArraysInstanced: UniformBlock is not backed by a buffer");
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, buffer);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArrays: UniformBlock is backed by a buffer with no data store");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArraysInstanced: UniformBlock is backed by a buffer with no data store");
+
+ var arrayNotLargeEnough = new ArrayBuffer(blockSize - 1);
+ gl.bufferData(gl.UNIFORM_BUFFER, arrayNotLargeEnough, gl.DYNAMIC_DRAW);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArrays: UniformBlock not populated with a large enough buffer");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArraysInstanced: UniformBlock not populated with a large enough buffer");
+
+ gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView, gl.DYNAMIC_DRAW);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays: should be able to draw with sufficient data for UniformBlock");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArraysInstanced: should be able to draw with sufficient data for UniformBlock");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, binding, buffer, 0, blockSize -1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArrays: bindBufferRange set size too small for UniformBlock");
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArraysInstanced: bindBufferRange set size too small for UniformBlock");
+}
+
+function runDrawElementsTests() {
+ debug("");
+ debug("Testing drawElements, drawRangeElements and drawElementsInstanced");
+
+ var instanceCount = 4;
+
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
+ if (!program) {
+ testFailed("Could not compile shader with uniform blocks without error");
+ return;
+ }
+
+ var blockIndex = gl.getUniformBlockIndex(program, "UBOData");
+ var blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ var uniformIndices = gl.getUniformIndices(program, ["UBORed", "UBOGreen", "UBOBlue"]);
+ var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+
+ if (uniformOffsets.length < 3) {
+ testFailed("Could not query uniform offsets");
+ return;
+ }
+
+ var uboArray = new ArrayBuffer(blockSize);
+ var uboFloatView = new Float32Array(uboArray);
+ uboFloatView[uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBORed
+ uboFloatView[uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOGreen
+ uboFloatView[uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOBlue
+
+ var binding = 1;
+ gl.uniformBlockBinding(program, blockIndex, binding);
+
+ wtu.setupIndexedQuad(gl, 1, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up succeeded");
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
+
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElements: UniformBlock is not backed by a buffer");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawRangeElements: UniformBlock is not backed by a buffer");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElementsInstanced: UniformBlock is not backed a buffer");
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, buffer);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElements: UniformBlock is populated with a buffer with no data store");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawRangeElements: UniformBlock is populated with a buffer with no data store");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElementsInstanced: UniformBlock is populated with a buffer with no data store");
+
+ var arrayNotLargeEnough = new ArrayBuffer(blockSize - 1);
+ gl.bufferData(gl.UNIFORM_BUFFER, arrayNotLargeEnough, gl.DYNAMIC_DRAW);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElements: UniformBlock not populated with a large enough buffer");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawRangeElements: UniformBlock not populated with a large enough buffer");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElementsInstanced: UniformBlock not populated with a large enough buffer");
+
+ gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView, gl.DYNAMIC_DRAW);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements: should be able to draw with sufficient data for UniformBlock");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawRangeElements: should be able to draw with sufficient data for UniformBlock");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElementsInstanced: should be able to draw with sufficient data for UniformBlock");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2);
+
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, binding, buffer, 0, blockSize -1);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElements: bindBufferRange set size too small for UniformBlock");
+ gl.drawRangeElements(gl.TRIANGLES, 0, 5, 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawRangeElements: bindBufferRange set size too small for UniformBlock");
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElementsInstanced: bindBufferRange set size too small for UniformBlock");
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id-large-count.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id-large-count.html
new file mode 100644
index 0000000000..a68f5d911c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id-large-count.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 gl_VertexID Large Count Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!-- Shaders for testing instanced draws -->
+<script id="vs" type="text/plain">
+#version 300 es
+
+uniform ivec2 resolution;
+void main() {
+ ivec2 pixel = ivec2(
+ gl_VertexID % resolution.x,
+ gl_VertexID / resolution.x);
+ vec2 xy = (vec2(pixel) + 0.5) / vec2(resolution) * 2.0 - 1.0;
+
+ gl_Position = vec4(xy, 0, 1);
+ gl_PointSize = 1.0;
+}
+</script>
+<script id="fs" type="text/plain">
+#version 300 es
+precision mediump float;
+uniform vec4 color;
+out vec4 fragColor;
+void main() {
+ fragColor = color;
+}
+</script>
+
+<script>
+"use strict";
+description("Test gl_VertexID");
+
+debug("");
+
+const wtu = WebGLTestUtils;
+const canvas = document.createElement("canvas");
+const size = 2048;
+canvas.width = size;
+canvas.height = size;
+const gl = wtu.create3DContext(canvas, null, 2);
+
+// document.body.appendChild(gl.canvas);
+// gl.canvas.style.background = 'yellow';
+// gl.canvas.style.margin = '20px';
+// const ext = gl.getExtension('WEBGL_debug_renderer_info');
+// if (ext) {
+// debug(gl.getParameter(ext.UNMASKED_RENDERER_WEBGL));
+// }
+
+(function() {
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ return;
+ }
+ testPassed("WebGL context exists");
+
+ const vs = document.getElementById("vs").innerHTML.trim();
+ const fs = document.getElementById("fs").innerHTML.trim();
+ const prog = wtu.loadProgram(gl, vs, fs);
+ gl.useProgram(prog);
+ const resolutionLoc = gl.getUniformLocation(prog, 'resolution');
+ const colorLoc = gl.getUniformLocation(prog, 'color');
+
+ // -
+
+ debug("");
+ debug("----------------");
+ debug("drawArrays");
+
+ const u8Color = c => c.map(v => v * 255 | 0);
+ const transparentBlack = [0, 0, 0, 0];
+ const red = [1, 0, 0, 1];
+ const green = [0, 1, 0, 1];
+ const blue = [0, 0, 1, 1];
+
+ const test = function(first, count, color) {
+ debug("");
+ debug(`drawArrays(first: ${first}, count: ${count})`);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.uniform4fv(colorLoc, color);
+ gl.uniform2i(resolutionLoc, size, size);
+ gl.drawArrays(gl.POINTS, first, count);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ const y = first / size;
+ const height = count / size;
+
+ // The shader draws 1 pixel points by looking at gl_VertexID
+ // as a 1D index into a 2D array. In other words
+ // row = gl_VertexID / width;
+ // col = gl_VertexID % width;
+ // Setting first to a value of rows * width (ie, y * size)
+ // lets us skip y rows when drawing so we then check that
+ // from y to height rows are the expected color and everything
+ // else is the cleared color.
+ wtu.checkCanvasRect(gl, 0, y, size, height, u8Color(color));
+ wtu.checkCanvasRect(gl, 0, 0, size, size - height, transparentBlack);
+ };
+
+ test(0, size * size, red);
+ test(size * size / 2, size * size / 2, green);
+ test(size * size / 4, size * size / 4 * 3, blue);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "There should be no remaining errors");
+})();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id.html
new file mode 100644
index 0000000000..ec4bd05ad4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/vertex-id.html
@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 gl_VertexID Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<!-- Shaders for testing instanced draws -->
+<script id="vs" type="text/plain">
+#version 300 es
+flat out highp int vVertexID;
+
+void main() {
+ vVertexID = gl_VertexID;
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0,0,0,1);
+}
+</script>
+<script id="fs" type="text/plain">
+#version 300 es
+flat in highp int vVertexID;
+out highp int oVertexID;
+void main() {
+ oVertexID = vVertexID;
+}
+</script>
+
+<script>
+"use strict";
+description("Test gl_VertexID");
+
+debug("");
+
+const wtu = WebGLTestUtils;
+const canvas = document.createElement("canvas");
+canvas.width = 1;
+canvas.height = 1;
+const gl = wtu.create3DContext(canvas, null, 2);
+
+(function() {
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ return;
+ }
+ testPassed("WebGL context exists");
+
+ const vs = document.getElementById("vs").innerHTML.trim();
+ const fs = document.getElementById("fs").innerHTML.trim();
+ const prog = wtu.loadProgram(gl, vs, fs);
+ gl.useProgram(prog);
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl.R32I, 1, 1);
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors after setup");
+
+ function shouldBeVal(prefix, expected, was) {
+ let text = prefix + "Should be " + expected;
+ let func = testPassed;
+ if (was != expected) {
+ text = text + ", was " + was;
+ func = testFailed;
+ }
+ func(text);
+ };
+
+ const readValData = new Int32Array(10000);
+ function ensureVal(prefix, expected) {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA_INTEGER, gl.INT, readValData);
+ const was = readValData[0];
+ shouldBeVal(prefix, expected, was);
+ };
+
+ gl.clearBufferiv(gl.COLOR, 0, new Int32Array([42, 0, 0, 0]));
+ ensureVal("After clear", 42);
+
+ // -
+
+ debug("");
+ debug("----------------");
+ debug("drawArrays");
+
+ let test = function(first, count) {
+ debug("");
+ debug(`drawArrays(first: ${first}, count: ${count})`);
+ gl.drawArrays(gl.POINTS, first, count);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ ensureVal("", first+count-1);
+ };
+
+ test(0, 1);
+ test(1, 1);
+ test(10000, 1);
+ test(100000, 1);
+ test(1000000, 1);
+
+ test(0, 2);
+ test(1, 2);
+ test(10000, 2);
+ test(100000, 2);
+ test(1000000, 2);
+
+ const INT32_MAX = 0x7fffffff;
+
+ test = function(first, count) {
+ debug("");
+ debug(`drawArrays(first: ${first}, count: ${count})`);
+ gl.drawArrays(gl.POINTS, first, count);
+ if (!wtu.glErrorShouldBe(gl, [gl.NO_ERROR, gl.OUT_OF_MEMORY])) {
+ ensureVal("", first+count-1);
+ }
+ };
+
+ test(INT32_MAX-2, 1);
+ test(INT32_MAX-1, 1);
+ test(INT32_MAX, 1);
+
+ // -
+
+ debug("");
+ debug("----------------");
+ debug("drawElements");
+
+ const indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ const indexData = new Uint16Array([1, 2, 5, 3, 10000]);
+ debug("indexData: " + indexData);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
+
+ test = function(first, count) {
+ debug("");
+ debug(`drawElements(first: ${first}, count: ${count})`);
+ gl.drawElements(gl.POINTS, count, gl.UNSIGNED_SHORT, first*2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ ensureVal("", indexData[first+count-1]);
+ };
+
+ for (let f = 0; f < indexData.length; ++f) {
+ for (let c = 1; f + c <= indexData.length; ++c) {
+ test(f, c);
+ }
+ }
+
+ // -
+
+ debug("");
+ debug("----------------");
+ debug("Via transform feedback");
+
+ gl.transformFeedbackVaryings(prog, ["vVertexID"], gl.INTERLEAVED_ATTRIBS);
+ wtu.linkProgram(gl, prog);
+ gl.useProgram(prog);
+
+ const tfBuffer = gl.createBuffer();
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*10000, gl.DYNAMIC_READ);
+
+ test = function(offset, count) {
+ debug("");
+ debug("drawArrays(" + offset + ", " + count + ")");
+ gl.beginTransformFeedback(gl.POINTS);
+ gl.drawArrays(gl.POINTS, offset, count);
+ gl.endTransformFeedback();
+ gl.getBufferSubData(gl.TRANSFORM_FEEDBACK_BUFFER, 0, readValData);
+ let ok = true;
+ for (let i = 0; i < readValData.length; i++) {
+ if (i >= count)
+ break;
+ const expected = offset + i;
+ const was = readValData[i];
+ if (was != expected) {
+ testFailed("[" + i + "] expected " + expected + ", was " + was);
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ testPassed("ok");
+ }
+ };
+
+ test(0, 1);
+ test(1, 1);
+ test(10000, 1);
+
+ test(0, 2);
+ test(1, 2);
+ test(10000, 2);
+
+ test(10000, 10000);
+
+ // -
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "There should be no remaining errors");
+})();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/00_test_list.txt
new file mode 100644
index 0000000000..eeca822298
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/00_test_list.txt
@@ -0,0 +1,3 @@
+--min-version 2.0.1 multi-context-sampler-test.html
+samplers.html
+sampler-drawing-test.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/multi-context-sampler-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/multi-context-sampler-test.html
new file mode 100644
index 0000000000..05e0f20480
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/multi-context-sampler-test.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Multi-Context Sampler Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas_drawing" width="12" height="12"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Tests that samplers' state doesn't leak across contexts");
+debug("");
+debug('Regression test for <a href="http://crbug.com/713127">http://crbug.com/713127</a>');
+
+function runTest() {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("canvas_drawing", undefined, 2);
+ var texture = null;
+ var color = [0, 255, 0, 255];
+
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ return;
+ }
+
+ testPassed("WebGL context exists");
+
+ wtu.setupTexturedQuad(gl);
+ texture = gl.createTexture();
+ // Create a texture bigger than 1x1 so that it would need mipmaps in
+ // order to be complete.
+ wtu.fillTexture(gl, texture, 2, 2, color, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8);
+ // Set texture parameters so that this texture is complete.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ // Set up a secondary context with a sampler bound to texture unit
+ // 0. This should not interfere with the primary context.
+ var altGL = wtu.create3DContext(undefined, undefined, 2);
+ if (!altGL) {
+ testFailed("Error creating secondary WebGL context");
+ return;
+ }
+
+ var sampler = altGL.createSampler();
+ // Note that the sampler's default TEXTURE_MIN_FILTER is
+ // NEAREST_MIPMAP_LINEAR.
+ altGL.bindSampler(0, sampler);
+ altGL.clearColor(1, 0, 0, 1);
+ altGL.clear(altGL.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(altGL, 0, 0, 1, 1, [ 255, 0, 0, 255 ],
+ "should be red");
+
+ // Now switch back to the main context and draw the texture.
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.drawUnitQuad(gl);
+ // The presence of the sampler on the other context should not
+ // have interfered with the completeness of the texture.
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, color,
+ "should be green");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/sampler-drawing-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/sampler-drawing-test.html
new file mode 100644
index 0000000000..ec6aa515ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/sampler-drawing-test.html
@@ -0,0 +1,124 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Sampler Drawing Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas_drawing" width="12" height="12"></canvas>
+<canvas id="canvas_texture" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Tests drawing with sampler works as expected");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas_drawing", null, 2);
+var canvas_texture = null;
+var samplerParam = [
+ gl.REPEAT,
+ gl.CLAMP_TO_EDGE,
+ gl.MIRRORED_REPEAT,
+];
+var color = [200, 0, 254, 255];
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ wtu.setupTexturedQuadWithTexCoords(gl, [-2.5, -2.5], [3.5, 3.5]);
+
+ setupCanvasTexture();
+ for (var ii = 0; ii < samplerParam.length; ++ii) {
+ runDrawingTest(samplerParam[ii]);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function setupCanvasTexture() {
+ canvas_texture = document.getElementById("canvas_texture");
+ var ctx2d = canvas_texture.getContext("2d");
+ ctx2d.fillStyle = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + color[3] + ")";
+ ctx2d.fillRect(0, 0, 1, 1);
+}
+
+function runDrawingTest(param) {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas_texture);
+
+ var sampler = gl.createSampler();
+ gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, param);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, param);
+
+ gl.clearColor(1,1,1,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.bindSampler(0, sampler);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 6);
+
+ checkPixels(param);
+}
+
+function checkPixels(param) {
+ var buf = new Uint8Array(12 * 12 * 4);
+ gl.readPixels(0, 0, 12, 12, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var passed = true;
+ for (var yy = 0; yy < 12; ++yy) {
+ for (var xx = 0; xx < 12; ++xx) {
+ var ec = [0, 0, 0, 0];
+ switch (param) {
+ case gl.REPEAT:
+ if (xx % 2 == 1 && yy % 2 == 1) {
+ ec = color;
+ }
+ break;
+ case gl.CLAMP_TO_EDGE:
+ if (xx < 6 && yy < 6) {
+ ec = color;
+ }
+ break;
+ case gl.MIRRORED_REPEAT:
+ if (xx % 4 < 2 && yy % 4 < 2) {
+ ec = color;
+ }
+ break;
+ }
+ var off = (yy * 12 + xx) * 4;
+ if (buf[off + 0] != ec[0] || buf[off + 1] != ec[1] ||
+ buf[off + 2] != ec[2] || buf[off + 3] != ec[3]) {
+ var msg = 'at (' + xx + ', ' + yy + ') expected: ' +
+ ec[0] + ', ' + ec[1] + ', ' + ec[2] + ', ' + ec[3] + ' found: ' +
+ buf[off + 0] + ', ' + buf[off + 1] + ', ' + buf[off + 2] + ', ' + buf[off + 3];
+ testFailed(msg);
+ passed = false;
+ }
+ }
+ }
+ if (passed) {
+ testPassed("Drawing with wrap " + wtu.glEnumToString(gl, param) + " as expected");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/samplers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/samplers.html
new file mode 100644
index 0000000000..e6fbc69011
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/samplers/samplers.html
@@ -0,0 +1,230 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Sampler Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the Sampler objects.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var s = null;
+var s1 = null;
+var s2 = null;
+var testCases = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runBindingTest();
+ runObjectTest();
+ runParameterTest();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function runBindingTest() {
+ debug("Testing binding enum");
+
+ shouldBe("gl.SAMPLER_BINDING", "0x8919");
+
+ // Default value is null
+ shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "SAMPLER_BINDING query should succeed");
+
+ debug("Testing binding a Sampler object");
+ s1 = gl.createSampler();
+ s2 = gl.createSampler();
+ gl.bindSampler(0, s1);
+ shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "s1");
+ gl.bindSampler(0, s2);
+ shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "s2");
+
+ // Bindings should not affect other units.
+ gl.bindSampler(1, s1);
+ shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "s2");
+ gl.activeTexture(gl.TEXTURE1);
+ shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "s1");
+ gl.activeTexture(gl.TEXTURE0);
+
+ // Should be able to bind a single sampler to multiple texture units.
+ gl.bindSampler(0, s1);
+ shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "s1");
+
+ // Deleting samplers should unbind them.
+ gl.deleteSampler(s1);
+ gl.deleteSampler(s2);
+ shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)");
+ gl.activeTexture(gl.TEXTURE1);
+ shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)");
+ gl.activeTexture(gl.TEXTURE0);
+
+ // Shouldn't be able to bind a deleted sampler.
+ gl.bindSampler(0, s2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted Sampler object");
+ gl.bindSampler(0, null);
+ shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runObjectTest() {
+ debug("Testing object creation");
+
+ s1 = gl.createSampler();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createSampler should not set an error");
+ shouldBeNonNull("s1");
+
+ // Expect true, even if never bound
+ shouldBeTrue("gl.isSampler(s1)");
+ gl.bindSampler(0, s1);
+ shouldBeTrue("gl.isSampler(s1)");
+ gl.bindSampler(0, null);
+ shouldBeTrue("gl.isSampler(s1)");
+ gl.deleteSampler(s1);
+ shouldBeFalse("gl.isSampler(s1)");
+
+ shouldBeFalse("gl.isSampler(null)");
+
+ s1 = null;
+}
+
+function runParameterTest() {
+ debug("Testing getSamplerParameter and samplerParameter[if]");
+
+ s = gl.createSampler();
+ gl.bindSampler(0, s);
+
+ debug("Checking default param for getSamplerParameter");
+
+ testCases = [
+ { pname: gl.TEXTURE_WRAP_S, defaultParam: gl.REPEAT },
+ { pname: gl.TEXTURE_WRAP_T, defaultParam: gl.REPEAT },
+ { pname: gl.TEXTURE_WRAP_R, defaultParam: gl.REPEAT },
+ { pname: gl.TEXTURE_MIN_FILTER, defaultParam: gl.NEAREST_MIPMAP_LINEAR },
+ { pname: gl.TEXTURE_MAG_FILTER, defaultParam: gl.LINEAR },
+ { pname: gl.TEXTURE_COMPARE_MODE, defaultParam: gl.NONE },
+ { pname: gl.TEXTURE_COMPARE_FUNC, defaultParam: gl.LEQUAL },
+ { pname: gl.TEXTURE_MIN_LOD, defaultParam: -1000 },
+ { pname: gl.TEXTURE_MAX_LOD, defaultParam: 1000 },
+ ];
+
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var pname = testCases[ii].pname;
+ var defaultParam = testCases[ii].defaultParam;
+ shouldBe("gl.getSamplerParameter(s, " + pname + ")", defaultParam.toString());
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+
+ debug("Checking valid pname and param for samplerParameteri");
+
+ testCases = [
+ { pname: gl.TEXTURE_WRAP_S, param: gl.REPEAT },
+ { pname: gl.TEXTURE_WRAP_S, param: gl.MIRRORED_REPEAT },
+ { pname: gl.TEXTURE_WRAP_S, param: gl.CLAMP_TO_EDGE },
+ { pname: gl.TEXTURE_WRAP_T, param: gl.REPEAT },
+ { pname: gl.TEXTURE_WRAP_T, param: gl.MIRRORED_REPEAT },
+ { pname: gl.TEXTURE_WRAP_T, param: gl.CLAMP_TO_EDGE },
+ { pname: gl.TEXTURE_WRAP_R, param: gl.REPEAT },
+ { pname: gl.TEXTURE_WRAP_R, param: gl.MIRRORED_REPEAT },
+ { pname: gl.TEXTURE_WRAP_R, param: gl.CLAMP_TO_EDGE },
+ { pname: gl.TEXTURE_MIN_FILTER, param: gl.NEAREST },
+ { pname: gl.TEXTURE_MIN_FILTER, param: gl.LINEAR },
+ { pname: gl.TEXTURE_MIN_FILTER, param: gl.NEAREST_MIPMAP_NEAREST },
+ { pname: gl.TEXTURE_MIN_FILTER, param: gl.NEAREST_MIPMAP_LINEAR },
+ { pname: gl.TEXTURE_MIN_FILTER, param: gl.LINEAR_MIPMAP_NEAREST },
+ { pname: gl.TEXTURE_MIN_FILTER, param: gl.LINEAR_MIPMAP_LINEAR },
+ { pname: gl.TEXTURE_MAG_FILTER, param: gl.NEAREST },
+ { pname: gl.TEXTURE_MAG_FILTER, param: gl.LINEAR },
+ { pname: gl.TEXTURE_COMPARE_MODE, param: gl.NONE },
+ { pname: gl.TEXTURE_COMPARE_MODE, param: gl.COMPARE_REF_TO_TEXTURE },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.LEQUAL },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.GEQUAL },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.LESS },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.GREATER },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.EQUAL },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.NOTEQUAL },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.ALWAYS },
+ { pname: gl.TEXTURE_COMPARE_FUNC, param: gl.NEVER },
+ ];
+
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var pname = testCases[ii].pname;
+ var param = testCases[ii].param;
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.samplerParameteri(s, " + pname + ", " + param + ")");
+ shouldBe("gl.getSamplerParameter(s, " + pname + ")", param);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+
+ debug("Checking valid pname and param for samplerParameterf");
+ testCases = [
+ { pname: gl.TEXTURE_MIN_LOD, param: -500 },
+ { pname: gl.TEXTURE_MIN_LOD, param: 0 },
+ { pname: gl.TEXTURE_MIN_LOD, param: 10.0 },
+ { pname: gl.TEXTURE_MAX_LOD, param: 500 },
+ { pname: gl.TEXTURE_MAX_LOD, param: 0 },
+ { pname: gl.TEXTURE_MAX_LOD, param: 10.0 },
+ ];
+
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var pname = testCases[ii].pname;
+ var param = testCases[ii].param;
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.samplerParameterf(s, " + pname + ", " + param + ")");
+ shouldBe("gl.getSamplerParameter(s, " + pname + ")", param.toString());
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ }
+
+ debug("Checking invalid pname and param");
+
+ testCases = [
+ { pname: gl.TEXTURE_IMMUTABLE_FORMAT, param: null, expectedError: gl.INVALID_ENUM },
+ { pname: gl.TEXTURE_BASE_LEVEL, param: null, expectedError: gl.INVALID_ENUM },
+ { pname: gl.TEXTURE_MAX_LEVEL, param: null, expectedError: gl.INVALID_ENUM },
+ { pname: gl.TEXTURE_WRAP_S, param: 0x812D,/* GL_CLAMP_TO_BORDER */ expectedError: gl.INVALID_ENUM },
+ { pname: gl.TEXTURE_WRAP_T, param: 0x812D,/* GL_CLAMP_TO_BORDER */ expectedError: gl.INVALID_ENUM },
+ { pname: gl.TEXTURE_MAG_FILTER, param: gl.LINEAR_MIPMAP_NEAREST, expectedError: gl.INVALID_ENUM },
+ ];
+
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var pname = testCases[ii].pname;
+ var param = testCases[ii].param;
+ var expectedError = testCases[ii].expectedError;
+ if (param == null) {
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.getSamplerParameter(s, " + pname + ")");
+ } else {
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getSamplerParameter(s, " + pname + ")");
+ }
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.samplerParameteri(s, " + pname + ", " + param + ")");
+ wtu.shouldGenerateGLError(gl, expectedError, "gl.samplerParameterf(s, " + pname + ", " + param + ")");
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/state/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/state/00_test_list.txt
new file mode 100644
index 0000000000..5bbd184e4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/state/00_test_list.txt
@@ -0,0 +1,4 @@
+gl-enum-tests.html
+gl-get-calls.html
+gl-getstring.html
+gl-object-get-calls.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-enum-tests.html b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-enum-tests.html
new file mode 100644
index 0000000000..76ff4b5b5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-enum-tests.html
@@ -0,0 +1,29 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl enums Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/test-eval.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/gl-enum-tests.js"></script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-get-calls.html b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-get-calls.html
new file mode 100644
index 0000000000..6f0991a9d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-get-calls.html
@@ -0,0 +1,177 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl calls Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test ensures getParameter is working correct with WebGL 2 pnames");
+
+debug("");
+debug("Canvas.getContext");
+
+var minimumRequiredStencilMask = 0;
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext("canvas", null, 2);
+if (!context)
+ testFailed("context does not exist");
+else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Context contains getError");
+ if ("getError" in context)
+ testPassed("context contains getError");
+ else
+ testFailed("context does not contains getError");
+
+ debug("");
+ debug("Check default values");
+
+ shouldBe('context.getParameter(context.COPY_READ_BUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.COPY_WRITE_BUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.DRAW_BUFFER0)', 'context.BACK');
+ shouldBe('context.getParameter(context.DRAW_FRAMEBUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.FRAGMENT_SHADER_DERIVATIVE_HINT)', 'context.DONT_CARE');
+ shouldBe('context.getParameter(context.PACK_ROW_LENGTH)', '0');
+ shouldBe('context.getParameter(context.PACK_SKIP_PIXELS)', '0');
+ shouldBe('context.getParameter(context.PACK_SKIP_ROWS)', '0');
+ shouldBe('context.getParameter(context.PIXEL_PACK_BUFFER_BINDING)', 'null');
+
+ shouldBe('context.getParameter(context.PIXEL_UNPACK_BUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.RASTERIZER_DISCARD)', 'false');
+ shouldBe('context.getParameter(context.READ_BUFFER)', 'context.BACK');
+ shouldBe('context.getParameter(context.READ_FRAMEBUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.SAMPLE_ALPHA_TO_COVERAGE)', 'false');
+ shouldBe('context.getParameter(context.SAMPLE_COVERAGE)', 'false');
+ shouldBe('context.getParameter(context.SAMPLER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.TEXTURE_BINDING_2D_ARRAY)', 'null');
+ shouldBe('context.getParameter(context.TEXTURE_BINDING_3D)', 'null');
+ shouldBe('context.getParameter(context.TRANSFORM_FEEDBACK_ACTIVE)', 'false');
+ shouldBe('context.getParameter(context.TRANSFORM_FEEDBACK_BINDING)', 'null');
+ shouldBe('context.getParameter(context.TRANSFORM_FEEDBACK_BUFFER_BINDING)', 'null');
+ shouldBe('context.getParameter(context.TRANSFORM_FEEDBACK_PAUSED)', 'false');
+ shouldBe('context.getParameter(context.UNIFORM_BUFFER_BINDING)', 'null');
+
+ shouldBe('context.getParameter(context.UNPACK_IMAGE_HEIGHT)', '0');
+ shouldBe('context.getParameter(context.UNPACK_ROW_LENGTH)', '0');
+ shouldBe('context.getParameter(context.UNPACK_SKIP_IMAGES)', '0');
+ shouldBe('context.getParameter(context.UNPACK_SKIP_PIXELS)', '0');
+ shouldBe('context.getParameter(context.UNPACK_SKIP_ROWS)', '0');
+ shouldBe('context.getParameter(context.VERTEX_ARRAY_BINDING)', 'null');
+
+ debug("");
+ debug("Check minimum values");
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_3D_TEXTURE_SIZE)', '256');
+ shouldBeType('context.getParameter(context.MAX_3D_TEXTURE_SIZE)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_ARRAY_TEXTURE_LAYERS)', '256');
+ shouldBeType('context.getParameter(context.MAX_ARRAY_TEXTURE_LAYERS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_CLIENT_WAIT_TIMEOUT_WEBGL)', '0');
+ shouldBeType('context.getParameter(context.MAX_CLIENT_WAIT_TIMEOUT_WEBGL)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_COLOR_ATTACHMENTS)', '4');
+ shouldBeType('context.getParameter(context.MAX_COLOR_ATTACHMENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_COMBINED_UNIFORM_BLOCKS)', '24');
+ shouldBeType('context.getParameter(context.MAX_COMBINED_UNIFORM_BLOCKS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_DRAW_BUFFERS)', '4');
+ shouldBeType('context.getParameter(context.MAX_DRAW_BUFFERS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_ELEMENT_INDEX)', '16777215'); // 2^24 - 1
+ shouldBeType('context.getParameter(context.MAX_ELEMENT_INDEX)', 'Number');
+
+ shouldBeType('context.getParameter(context.MAX_ELEMENTS_INDICES)', 'Number');
+ shouldBeType('context.getParameter(context.MAX_ELEMENTS_VERTICES)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_FRAGMENT_INPUT_COMPONENTS)', '60');
+ shouldBeType('context.getParameter(context.MAX_FRAGMENT_INPUT_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_FRAGMENT_UNIFORM_BLOCKS)', '12');
+ shouldBeType('context.getParameter(context.MAX_FRAGMENT_INPUT_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_FRAGMENT_UNIFORM_COMPONENTS)', '896');
+ shouldBeType('context.getParameter(context.MAX_FRAGMENT_UNIFORM_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_PROGRAM_TEXEL_OFFSET)', '7');
+ shouldBeType('context.getParameter(context.MAX_PROGRAM_TEXEL_OFFSET)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_SAMPLES)', '4');
+ shouldBeType('context.getParameter(context.MAX_PROGRAM_TEXEL_OFFSET)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_SERVER_WAIT_TIMEOUT)', '0');
+ shouldBeType('context.getParameter(context.MAX_SERVER_WAIT_TIMEOUT)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_TEXTURE_LOD_BIAS)', '2.0');
+ shouldBeType('context.getParameter(context.MAX_TEXTURE_LOD_BIAS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS)', '64');
+ shouldBeType('context.getParameter(context.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)', '4');
+ shouldBeType('context.getParameter(context.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS)', '4');
+ shouldBeType('context.getParameter(context.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_UNIFORM_BLOCK_SIZE)', '16384');
+ shouldBeType('context.getParameter(context.MAX_UNIFORM_BLOCK_SIZE)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_UNIFORM_BUFFER_BINDINGS)', '24');
+ shouldBeType('context.getParameter(context.MAX_UNIFORM_BUFFER_BINDINGS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VARYING_COMPONENTS)', '60');
+ shouldBeType('context.getParameter(context.MAX_VARYING_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VERTEX_OUTPUT_COMPONENTS)', '64');
+ shouldBeType('context.getParameter(context.MAX_VERTEX_OUTPUT_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VERTEX_UNIFORM_BLOCKS)', '12');
+ shouldBeType('context.getParameter(context.MAX_VERTEX_UNIFORM_BLOCKS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_VERTEX_UNIFORM_COMPONENTS)', '1024');
+ shouldBeType('context.getParameter(context.MAX_VERTEX_UNIFORM_COMPONENTS)', 'Number');
+
+ shouldBeLessThanOrEqual('context.getParameter(context.MIN_PROGRAM_TEXEL_OFFSET)', '-8');
+ shouldBeType('context.getParameter(context.MIN_PROGRAM_TEXEL_OFFSET)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.UNIFORM_BUFFER_OFFSET_ALIGNMENT)', '1');
+ shouldBeType('context.getParameter(context.UNIFORM_BUFFER_OFFSET_ALIGNMENT)', 'Number');
+
+ var minCombinedFragmentUniformComponents = context.getParameter(context.MAX_FRAGMENT_UNIFORM_BLOCKS) * context.getParameter(context.MAX_UNIFORM_BLOCK_SIZE) / 4 + context.getParameter(context.MAX_FRAGMENT_UNIFORM_COMPONENTS);
+ var minCombinedVertexUniformComponents = context.getParameter(context.MAX_VERTEX_UNIFORM_BLOCKS) * context.getParameter(context.MAX_UNIFORM_BLOCK_SIZE) / 4 + context.getParameter(context.MAX_VERTEX_UNIFORM_COMPONENTS);
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS)', minCombinedFragmentUniformComponents + '');
+ shouldBeType('context.getParameter(context.MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS)', 'Number');
+
+ shouldBeGreaterThanOrEqual('context.getParameter(context.MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS)', minCombinedVertexUniformComponents + '');
+ shouldBeType('context.getParameter(context.MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS)', 'Number');
+
+ shouldBe('context.getError()', 'context.NO_ERROR');
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-getstring.html b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-getstring.html
new file mode 100644
index 0000000000..2e494589eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-getstring.html
@@ -0,0 +1,60 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL gl.getParameter Strings Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks getParameter returns strings in the correct format");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", null, 2);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ checkPrefix("WebGL 2.0", "VERSION");
+ checkPrefix("WebGL GLSL ES 3.00", "SHADING_LANGUAGE_VERSION");
+ shouldBeNonNull("gl.getParameter(gl.VENDOR)");
+ shouldBeNonNull("gl.getParameter(gl.RENDERER)");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function checkPrefix(expected, enum_val) {
+ var s = gl.getParameter(gl[enum_val]);
+ if (s != null &&
+ s.length >= expected.length &&
+ s.substring(0, expected.length) == expected) {
+ testPassed("getParameter(gl." + enum_val + ") correctly started with " + expected);
+ } else {
+ testFailed("getParameter(gl." + enum_val + ") did not start with " + expected);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-object-get-calls.html b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-object-get-calls.html
new file mode 100644
index 0000000000..62ed70d5bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/state/gl-object-get-calls.html
@@ -0,0 +1,23 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../js/tests/gl-object-get-calls.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/sync/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/sync/00_test_list.txt
new file mode 100644
index 0000000000..474af6c765
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/sync/00_test_list.txt
@@ -0,0 +1 @@
+sync-webgl-specific.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html b/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
new file mode 100644
index 0000000000..a9ec78e3be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
@@ -0,0 +1,156 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 specific sync object behaviors</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+description("This test checks WebGL2 specific sync object behaviors");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", null, 2);
+var sync = null;
+var pixel = new Uint8Array(4);
+
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ testPassed("context exists");
+
+ debug("");
+ shouldBe("gl.TIMEOUT_IGNORED", "-1");
+ shouldBe("gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL", "0x9247");
+ var max = gl.getParameter(gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL);
+ debug("Querying gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ debug("gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL returns " + max + "ns");
+ if (max < 0) {
+ testFailed("gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL < 0");
+ } else if (max > 1000 * 1000 * 1000) {
+ // This is not demanded by the WebGL2 spec, but anything larger than 1000ms
+ // is bad idea and no implementation should allow it.
+ testFailed("gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL should not exceed 1000ms");
+ } else {
+ testPassed("gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL returns a valid value");
+ }
+ sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ shouldBeNonNull("sync");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ gl.clientWaitSync(sync, 0, max);
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ gl.clientWaitSync(sync, 0, max + 1);
+ shouldBe("gl.getError()", "gl.INVALID_OPERATION");
+
+ requestAnimationFrame(runGetSyncParameterTest);
+}
+
+var numRetries = 20000;
+var iteration = 0;
+
+function syncWithGLServer() {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+}
+
+function runGetSyncParameterTest() {
+ debug("");
+ debug("Verifying sync object isn't signaled too early");
+ sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ // Verify as best as possible that the implementation doesn't allow a sync
+ // object to become signaled until returning control to the event loop, by
+ // spin-looping for some time.
+ var iter = numRetries;
+ while (--iter > 0) {
+ syncWithGLServer();
+ if (gl.getSyncParameter(sync, gl.SYNC_STATUS) == gl.SIGNALED) {
+ testFailed("Sync object was signaled too early");
+ finishTest();
+ return;
+ }
+ }
+ testPassed("Sync object wasn't signaled too early");
+ iteration = numRetries;
+ requestAnimationFrame(finishSyncParameterTest);
+}
+
+
+function finishSyncParameterTest() {
+ if (--iteration == 0) {
+ testFailed("Sync object wasn't signaled in a reasonable timeframe (" + numRetries + " iterations)");
+ finishTest();
+ return;
+ }
+ var res = gl.getSyncParameter(sync, gl.SYNC_STATUS);
+ if (res == gl.SIGNALED) {
+ testPassed("Sync object was signaled");
+ requestAnimationFrame(runClientWaitSyncTest);
+ return;
+ }
+ // Try again.
+ syncWithGLServer();
+ requestAnimationFrame(finishSyncParameterTest);
+}
+
+function runClientWaitSyncTest() {
+ debug("");
+ debug("Verifying clientWaitSync doesn't complete too early");
+
+ sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ // Verify as best as possible that the implementation doesn't allow
+ // clientWaitSync to return CONDITION_SATISFIED or ALREADY_SIGNALED until
+ // returning control to the event loop, by spin-looping for some time.
+ var iter = numRetries;
+ while (--iter > 0) {
+ syncWithGLServer();
+ var res = gl.clientWaitSync(sync, 0, 0);
+ if (res == gl.CONDITION_SATISFIED || res == gl.ALREADY_SIGNALED) {
+ testFailed("clientWaitSync completed successfully too early");
+ finishTest();
+ return;
+ }
+ }
+ testPassed("clientWaitSync didn't complete successfully too early");
+ iteration = numRetries;
+ requestAnimationFrame(finishClientWaitSyncTest);
+}
+
+function finishClientWaitSyncTest() {
+ if (--iteration == 0) {
+ testFailed("clientWaitSync didn't complete in a reasonable timeframe (" + numRetries + " iterations)");
+ finishTest();
+ return;
+ }
+ var res = gl.clientWaitSync(sync, 0, 0);
+ if (res == gl.CONDITION_SATISFIED || res == gl.ALREADY_SIGNALED) {
+ testPassed("clientWaitSync completed successfully");
+ // This is the last test right now.
+ finishTest();
+ return;
+ }
+ // Try again.
+ syncWithGLServer();
+ requestAnimationFrame(finishClientWaitSyncTest);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/00_test_list.txt
new file mode 100644
index 0000000000..32867b54c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/00_test_list.txt
@@ -0,0 +1,14 @@
+misc/00_test_list.txt
+canvas/00_test_list.txt
+canvas_sub_rectangle/00_test_list.txt
+image/00_test_list.txt
+image_data/00_test_list.txt
+svg_image/00_test_list.txt
+video/00_test_list.txt
+webgl_canvas/00_test_list.txt
+image_bitmap_from_image_data/00_test_list.txt
+image_bitmap_from_image/00_test_list.txt
+image_bitmap_from_video/00_test_list.txt
+image_bitmap_from_canvas/00_test_list.txt
+image_bitmap_from_blob/00_test_list.txt
+image_bitmap_from_image_bitmap/00_test_list.txt
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..8c801c4c9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..05f02544ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..36bd2e93d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..46da6a2987
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..82f9b02997
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..7d22382c83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..386ba29a39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..c7a4277084
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..03e4239af3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..5aba67f310
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..514c6b9bac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..4fd44a8c02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..a5a70f80df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..36bc410800
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..973470922f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..f5876b7b44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..fddec39e89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..9dce82e56c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..39c2aea9d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..d86acccec7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..8708171759
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..48fec819dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..06563eae3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..487f31dba3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..1370103dfe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..4991fa6284
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..fb7ffa57eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..156de2a707
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..57ff4c5ffe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..60ef5bcf15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..9aab72ff23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..39137ef896
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..34f3c2e24d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..7bce656cf3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..4aef15a592
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..3e5f79e8ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..070e764f13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..07e504ad01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..1b296d9f0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..b562f71549
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..0c0d824598
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..d5521e370c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..52f2344394
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..7a02c62556
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..1381c0a484
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..df3dfc0f8c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..e66ae71d97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..ccc3d13c44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..9deeff0840
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..f16c2759f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..ede0abb981
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..7f87bcfdd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..c503df8492
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..6f2286d00a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..1112ac8c2a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..2179eda930
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..7277738228
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..9308dffd3e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..2c5ad98f43
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..894c690426
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..d4703bdf95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..31ee95ac9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..a7581fa954
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..304f121ac1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c2fdcbbc55
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..5a5691b6d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..aa8ca643f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..7e5e0bea87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..a1344af710
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..dd5bf39e70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..46b5e3fe64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..f074cf6de5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..fc0a6b755d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..05a48a7981
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..60527987f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..7aec66910e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..dec1f81cc5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..7c6595b817
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..8ef399dcc8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..76c765b6fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..b238b76243
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..c7e2b78cfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..5ab513162e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..a27d31944c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..2ff8b6235f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..33ddf9b0c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..742b207464
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..08619238ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..74aa42c9d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..ee376bd2b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..16cca51a01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..f628182f39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..e433920c07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..d318d09de6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..54b43b1c89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..b6f1956ec9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..98ef9407eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..1cf6990056
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..421a887106
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4b3f3d9e7c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..337c011bc4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..3d9c86cc82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..5f64d6f88e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..e7b0478a5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..6ede1146a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..03ecaeb211
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..cde19ef1bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..0068bf2495
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..c13290a670
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6202000171
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..2db57ea345
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..5d959f1ba6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..a32c6ff7c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..8291d7b7cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..1b2e3f3715
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..5f51df5cc5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..82b7010278
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..4ad053eb8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..eb1e8d9987
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..27cbf617fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..945337ff74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..603f69522f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..90f4be79fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..daee9a0c6d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..1efe3dcb22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..6e0b8def24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..d7a95ab819
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..4783419363
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..9de09db382
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..6c0e65e573
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..e013f66d77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..9e2ed794a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..b06d2b155c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..87d5c9aade
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..9d09b5fb76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..fd95a5dfc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/canvas_sub_rectangle/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..6ea3292110
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..841d8fc61c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..4c199d2901
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..e2bd06e440
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..5ddcae6a40
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..f93e42c6c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..0ea44bde5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..624b3399bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..90836ed8b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..9f260cf8e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..e5baf2069e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..c77bc24ab4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..e1e35ea54c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..83023a85b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..5b2a1e6a16
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..e988a7d5f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..6b64f9e217
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..32a8cb6d73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..2ad6725924
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..60668ece42
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..a89cb3e39e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..5823a6944b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..f8516a6f19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..61f186a309
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..a101504cca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..24f5db7540
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..4661fd0978
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..3702959597
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..62176ed6db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..3955375f0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..79f6939ff7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..db68f6c16e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..6b14cb7e2c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..654a310535
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..f76a52359e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..d8b1bfa3c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..7cb17eb625
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..8d06eaafd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..4e0874924b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..d94582329d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..34819efa67
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..730754b09d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..433588f223
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..e45398f29a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..42c1f7779d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..0abcc546df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..2ff03c17f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..3f6591dfd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..41529a4043
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..3d563318c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..105bca0261
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..e52398c49f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..3f190c01c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..eed7125484
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..3dcbab2ef0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..dba17ff312
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..07c2bbc422
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..2e15aeb30d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..79afb795ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..bbf137a8e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..cf21cda985
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..4dff791e8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..5940abde8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..c96b864366
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..5b23b9e0a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..33ad6a49ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..62a0ccbb50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c4ecaf62d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..aa052b6130
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..3261c23797
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..6c0f3c2689
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..9af1fa3532
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..a2ec49eca0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..272ea5e54e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..e832be3297
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..42079acf19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..38e7234b71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..c2243248ba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..6c0106457f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..3c2e6c14f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..66c2a626e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..519cf98b83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..b40e839f2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..0fc1149007
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..bae44d2cc8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..d0b2f47134
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..49261e54bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f4ede9024f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..01835049b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..ac54fb75ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..fcf008ed25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..b3081c52ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..77d3318623
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..a753121769
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..de58b2af94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..5b08d77cd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c83dc2a731
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..6e4e5a54d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4ccbe826a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..42736a2da2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..878757e353
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..978df556d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..5fa9f21a2c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..a1df113ca0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..066f900887
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..3987980699
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..4117593187
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..0155fde0b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..4a0d9cf1de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..16295386b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..6aa5fafbd7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..a43ddbd38e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..7348e8185e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..e28076ac71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..c01144c4eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..2e924d8e65
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..8287f00830
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..6d78d8843a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..6b1c6fbad1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..7afcaa0b3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..0a5a97e90c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..0f4b97deef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..34319b3e58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..3f68db2d1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..f5fb2e1fbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..d7fea8caad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..e823230325
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..ef59f2c15d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..f4711efefa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..dc5b703253
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..b78cb598a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..6fe341ee26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..3801969d4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..9b3f961133
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..0ecafe0628
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..da0644b6b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_blob/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..e92d04252d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..971df799c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..2d20a8007f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..132326f467
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..c7ff8d75d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..e68fe461be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..c467928207
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4f403c6f88
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..de04f033d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..85794f50a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..79f0f445fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..a98f49d5db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6b38cd13f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..64661eebea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..438ea17de9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..5fd088cfe7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..5f7c70d391
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..3600cdee52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..96d7f72bbd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4c151a2412
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..117e4ba805
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..a0588dec51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..23b56763b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..f4f85ca644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..d891379473
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..3f4f4bf17f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..916df976de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..d9ee243502
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..025ce676f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..fadaf85708
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..bbc7d924ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..7a3c4da940
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..249c1b315f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..1368cf93d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..84d2ea6130
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..a5ad80eef5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..e0e2d02c84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..79616a9193
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..37a1b86476
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..92016d3b78
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..6fde64957f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..ceec9bafdf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..2641f866fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..561d23bbd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..8c39d4e1a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..202ffa2444
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..3e0efbfde2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..900d4ed33f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..9b650ec281
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..7184d79e1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..0cad5e4f0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..f8bbdb3477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..97c8dc9e8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..0f28e71e57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..64b776c932
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..0ba53b4d5d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..23e7b04d9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..fb2df020d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..9185dca389
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..f49947da4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..03187ad3bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..022ce5d83d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..31557d5e50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..73b1b4f11d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..48713129f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..d207cb1bcd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..498e87b29f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..fbddf50be3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..a8c9362426
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..c673de8258
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..e4537fb278
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..ddb1aebf10
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..8c04fd16f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..70e9470c6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..5120a28724
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..3122847542
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..d88a0d3646
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..1f6e19e66f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..efbcf1c6ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..6e26c12a5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..a084604893
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..d89d37128e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..70b5526c29
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..3b948a54dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..84bd197c87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..983abc6ee4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..26e7267d12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4678fe2c76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..735706afc5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..7c5dee4f66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6e24630442
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..fe45185497
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..d41fd3a548
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..7a807854a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..594c7695d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..d189da14c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..fd0689a529
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..4589fb7b4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..25ca3f9038
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..c5f24faae0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..ee632f3d31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c0f7a778da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..95bd113972
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..d9d1b51cdd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..59035ca60d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..e018012ba3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..18c8b3cf15
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..988763acf2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..f94b3c8152
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4f95e95f30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..281ec20441
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..d5bf860b3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..59434bbe03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..ea79d07022
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..b5d02dfc79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..91e79980f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..65b6e1dcb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..e035ca3aec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..40f296d5ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..f0d51be51f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..0f8c9d75e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..cdb0e1e6d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..e3cc424271
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..9373a6e00f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..886db8b75d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..c9639636bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..e8ae94988b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..e18874689c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..e3f401eb0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..3cadef2674
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..6b19d39105
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..150f516d06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..09075ed879
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..e6a5546459
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..f3246700b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..fa1bbabbbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..09a91d39a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..8ee9563a76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..e1cc853b0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..fc30a91404
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..3c6b29ddad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..687a1e4c89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..898b40c62a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..c1390729e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..dfbf46134b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..00387d08ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..9113d16c77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..17af648224
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..d9f0fa5bf3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..75b910870b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..d85aed8e1e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..23f5727e6d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..41185647a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..a033877321
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..374fa01fc4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..b8880a4c86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..09af2b8a07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..c79586f626
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..01b8fe5d34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..b5e922c90d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..aff000cb63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..f49e1396e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..bab3796e3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..4e908ce8b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..0ed79ae542
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..765ef1358d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..231eebd539
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4f82923db3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..00874ae56b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..0318312b1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..cd31e97ba2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..82437ce839
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..3da4de658d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..a3b6ac5e49
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..88745fa9ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..4f8e472b1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..236014e67d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6ab0d85749
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..bff07471f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..35fe3616f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..ec06ee79d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..fc28bd70a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..00ae72a33b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..8cdb57cbea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..e933f3bbb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..d420ee0a00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..3f5f4408fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..c9e16e3cba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..a39a3648e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..254e68c19e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..ca5d04ddbf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..d3de225f86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..8916044cd0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..e5603af9dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..7753af57cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..b8b2ea4303
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..a9e07ea2ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..0ef26a1c86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..d67446841e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..981be92d5b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..07334a9398
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..a370da8ad1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..e3685b2471
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..245868490d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_bitmap/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..29308085c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..c46f4b8e62
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..e9d897a88c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..5654b473e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..ba6e83d449
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..ff89676426
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..dacb34d122
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..f51420f051
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..cdc08d87e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..9ae36f898a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..b78e4903f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..fcb150ea1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..5191af5d61
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..94588d7c68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..b235f006c7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..d6e1b4ad00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..7a88d6b87b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..87211acd3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..6c8de5ef23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..5ec5cc699d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..e404eb534f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..e74b7eaedb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..17dd9a91bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..a476294806
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..3201755760
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..43cb93d7f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..97bd18f654
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..8044b4c3fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..98a8a0bc69
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..a0a68fbf28
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f559aeec41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..5f8f3590d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..46c83fc72b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f1a32c833d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..105f2fa157
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..86e77ad110
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..4a8f2f6072
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..9d1167ddf3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..e8c0c8d0a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..5847430157
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..d7c22a5341
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..d698fc5031
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..3985828577
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..2154f6e1aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..a0d674fb73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..5da6a5e8ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..1bdd88b7a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..1a76138a34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..b72a8c6b82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..1e044af0e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..1fc7f7769d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..d9baa61e58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..b70ae64f32
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..eecd272bc6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..db49a55a25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..cea155c856
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..49d949b5f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..9d94f89eb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..c5225b8e7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..1235d2c6de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..04d386ffcb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..b216f0b7d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..42fc43a397
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..dfa84fd9fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..364288dbd5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..d19eab640b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..6b2b06bb00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..949d8e9005
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..b4456c29b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..67741e9ab9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..04da85fd65
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..447a746f87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..7eafd3d2af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..fbaadd6fbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..26db1ed18a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4ea71275c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..9d42d06a90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..0572c094e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..db21b1378d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..cbdbc0f8f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..53d6ab3f74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..690e06ca36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..bb73c5066b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..5577516559
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..ba13ad89bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..ae4a929fb4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..e00359b1c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4f506c3387
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..62fb78b594
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..56c4abdb3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..66ee91fe80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..ed73f42f5d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..04d37ffc71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..707223260e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..ded868fb64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..08b5d2c094
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..371a9271fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..c58c6b02b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..dbeb44121f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..ebdfcd1a0d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..8c432743ba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..de290dd9a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..580027631d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..ae5928c01d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..aff08d4ec4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..c848f27d1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..ca7ae2dc43
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..fe40d0e695
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..98c0e3d673
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..df3fd4cd80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..e1838bd156
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..d0b9eb02d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..b104e93f83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..b5b3d074e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..b6d4eca749
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..4cf4c8dfb1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..17a117dd13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..aff864a307
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..01eb72baa3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..20576dd927
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..8dc5e7607f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f36d054001
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..fa54481e8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..1e909ca69c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..29d9cef86e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..16b3a480a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..dae9dab170
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..08a3408030
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..e70455bf5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..a3b68544ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..a9326befcc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..7428cf0c2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..ebdabf8909
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..1084c444ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..c1815a512e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..8a9e683380
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_bitmap_from_video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..7276d9ff93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..8aa7bd05b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..8f607613cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..d77a9454f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..2f737ebb17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..5d67d54beb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..0d90998a06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..a781744957
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..925c197369
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..66641ccf85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..87dd6d60a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..94595222c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..dca4bef18b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..1db719eabc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..f0b4d1bbf8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..784834a12e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..9be67acf79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..f053fa8ee7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..2484c4e5af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..d3b0f4c42c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..83dcc33772
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..2f43bf07c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..004bab7f8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..358bfda906
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..1460586195
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..38e925c060
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..11d8b58244
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..6c68bb49aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c5bd77413a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..58770e5ec7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..b8ab3290ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..24ce7f7f27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..723577adcf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..7083a0545b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..86bb1fd8ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..2d98cd10c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..550727d1f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..34d2f6d304
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..39cb9ce30a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..2668d82c82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r32f-red-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..d0c3f8c66a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..d1cc9d25c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..036b5ef9fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..bb433ffb36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..ec113d8b1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..ec4f7edd2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4aada97d3e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..39e95ada97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..b18ddf8b73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..f1c9021eba
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..faf230d11b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..3e43e99d7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..993dd3bb3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..8c95937ea5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..c27cf260d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..3bdff9c5a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..5c7d59967b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..be249149a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..808fb30d25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..eb03a0f38f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..9ad5fb2040
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..ad4cc39f68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..7df80309f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..a4573fa124
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..88f85ea36c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..e1f917d406
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..4ac2bc5e3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..a52d387880
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/image_data/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-image-data.js"></script>
+</head>
+<body>
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt
new file mode 100644
index 0000000000..17f8312e58
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt
@@ -0,0 +1,40 @@
+--min-version 2.0.1 active-3d-texture-bug.html
+--min-version 2.0.1 angle-stuck-depth-textures.html
+canvas-remains-unchanged-after-used-in-webgl-texture.html
+--min-version 2.0.1 compressed-tex-from-pbo-crash.html
+--min-version 2.0.1 compressed-tex-image.html
+--min-version 2.0.1 copy-texture-cube-map-AMD-bug.html
+--min-version 2.0.1 copy-texture-cube-map-bug.html
+copy-texture-image.html
+copy-texture-image-luma-format.html
+--min-version 2.0.1 copy-texture-image-same-texture.html
+copy-texture-image-webgl-specific.html
+--min-version 2.0.1 generate-mipmap-with-large-base-level.html
+gl-get-tex-parameter.html
+--min-version 2.0.1 immutable-tex-render-feedback.html
+--min-version 2.0.1 integer-cubemap-texture-sampling.html
+--min-version 2.0.1 integer-cubemap-specification-order-bug.html
+mipmap-fbo.html
+--min-version 2.0.1 npot-video-sizing.html
+--min-version 2.0.1 tex-3d-mipmap-levels-intel-bug.html
+--min-version 2.0.1 origin-clean-conformance-offscreencanvas.html
+tex-3d-size-limit.html
+--min-version 2.0.1 tex-base-level-bug.html
+tex-image-and-sub-image-with-array-buffer-view-sub-source.html
+tex-image-with-bad-args.html
+tex-image-with-bad-args-from-dom-elements.html
+tex-image-with-different-data-source.html
+tex-input-validation.html
+tex-mipmap-levels.html
+tex-new-formats.html
+--min-version 2.0.1 tex-srgb-mipmap.html
+tex-storage-2d.html
+tex-storage-and-subimage-3d.html
+tex-storage-compressed-formats.html
+--min-version 2.0.1 tex-subimage3d-canvas-bug.html
+--min-version 2.0.1 tex-subimage3d-pixel-buffer-bug.html
+tex-unpack-params.html
+--min-version 2.0.1 tex-unpack-params-imagedata.html
+--min-version 2.0.1 tex-unpack-params-with-flip-y-and-premultiply-alpha.html
+texel-fetch-undefined.html
+texture-npot.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html
new file mode 100644
index 0000000000..fe86514dd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html
@@ -0,0 +1,124 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Active TEXTURE1 Bug Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+precision mediump float;
+in vec4 a_position;
+in vec2 a_coord;
+out vec2 v_coord;
+void main() {
+ gl_Position = a_position;
+ v_coord = a_coord;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+in vec2 v_coord;
+uniform mediump sampler3D u_sampler;
+out vec4 o_color;
+void main () {
+ o_color = texture(u_sampler, vec3(v_coord, 0.0));
+}
+</script>
+<script>
+"use strict";
+description("Test for a MacOSX 10.12 with Intel GPUs driver crash bug activating TEXTURE1 for 3d texture");
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var samplerLoc;
+
+function render(textureUnit, width, height, expectedColor, msg) {
+ gl.uniform1i(samplerLoc, textureUnit);
+ wtu.setupUnitQuad(gl, 0, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, msg);
+}
+
+function activeTextureTest() {
+ var texture = gl.createTexture();
+ var sampler = gl.createSampler();
+ var width = 64;
+ var height = 64;
+ var depth = 4;
+ var black = [0, 0, 0, 255];
+ var size = width * height * depth * 4;
+
+ var buf = new Uint8Array(size);
+ for (var i = 0; i < size; i += 4) {
+ buf[i + 0] = 0;
+ buf[i + 1] = 255;
+ buf[i + 2] = 0;
+ buf[i + 3] = 255;
+ }
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ['a_position', 'a_coord'], [0, 1]);
+ samplerLoc = gl.getUniformLocation(program, "u_sampler");
+
+ gl.viewport(0, 0, width, height);
+
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ // texture is unbound from the default texture unit TEXTURE0,
+ // then a default black texture will be bound to TEXTURE0.
+ gl.bindTexture(gl.TEXTURE_3D, null);
+
+ // Active TEXTURE1 and 3d texture are necessary to reproduce the crash bug.
+ gl.activeTexture(gl.TEXTURE1);
+
+ gl.bindSampler(0, sampler);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ // Render using sampler
+ // When rendering from texture unit 0, the black texture will be drawn.
+ render(0, width, height, black, "Result pixels rendering from TEXTURE0 should be black");
+
+ gl.bindSampler(0, null);
+ gl.deleteSampler(sampler);
+
+ // Render using texture
+ // When rendering from texture unit 0, the black texture will be drawn.
+ // Crash happens when calling gl.drawArrays during this rendering.
+ render(0, width, height, black, "Result pixels rendering from TEXTURE0 should be black");
+
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.deleteTexture(texture);
+ gl.deleteProgram(program);
+}
+
+if (!gl) {
+ testFailed("Fail to get a WebGL2 context");
+} else {
+ testPassed("Created WebGL2 context successfully");
+ activeTextureTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/angle-stuck-depth-textures.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/angle-stuck-depth-textures.html
new file mode 100644
index 0000000000..17cb0ac916
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/angle-stuck-depth-textures.html
@@ -0,0 +1,197 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Textures Misc Tests: "Stuck" Depth Textures</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script id="draw-vs" type="x-shader/x-vertex">#version 100
+attribute vec3 vertex;
+void main () {
+ gl_Position = vec4(vertex.x, vertex.y, vertex.z * 2.0 - 1.0, 1);
+}
+</script>
+<script id="draw-fs" type="x-shader/x-fragment">#version 100
+void main () {
+ gl_FragColor = vec4 (1.);
+}
+</script>
+
+<script id="blit-vs" type="x-shader/x-vertex">#version 100
+attribute vec2 vertex;
+varying vec2 position;
+void main () {
+ position = vertex * .5 + .5;
+ gl_Position = vec4(vertex, 0, 1);
+}
+</script>
+<script id="blit-fs" type="x-shader/x-fragment">#version 100
+precision mediump float;
+uniform sampler2D texture;
+varying vec2 position;
+void main () {
+ gl_FragColor = vec4 (texture2D (texture, position).rrr, 1.);
+}
+</script>
+
+</head>
+<body>
+<canvas id="example" width="128" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+description("This test covers an ANGLE bug where an AMD workaround would cause depth textures to stick. See http://anglebug.com/1664.");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var WEBGL_depth_texture;
+
+var drawProgram, blitProgram, textureLoc;
+
+var quadVB;
+
+function drawQuad(depth) {
+ if (!quadVB) {
+ quadVB = gl.createBuffer()
+ }
+
+ var quadVerts = new Float32Array(3 * 6);
+ quadVerts[0] = -1.0; quadVerts[1] = 1.0; quadVerts[2] = depth;
+ quadVerts[3] = -1.0; quadVerts[4] = -1.0; quadVerts[5] = depth;
+ quadVerts[6] = 1.0; quadVerts[7] = -1.0; quadVerts[8] = depth;
+ quadVerts[9] = -1.0; quadVerts[10] = 1.0; quadVerts[11] = depth;
+ quadVerts[12] = 1.0; quadVerts[13] = -1.0; quadVerts[14] = depth;
+ quadVerts[15] = 1.0; quadVerts[16] = 1.0; quadVerts[17] = depth;
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadVB);
+ gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawQuad");
+}
+
+// Test based on dEQP-GLES3.functional.blit.depth_stencil.depth_24_stencil8_stencil_only
+function run_test() {
+
+ var colorTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, colorTex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 128, 128, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ var depthTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, depthTex);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+ var levels = Math.log2(128);
+ for (var mipLevel = 0; mipLevel <= levels; ++mipLevel)
+ {
+ var size = 128 >> mipLevel;
+ gl.texImage2D(gl.TEXTURE_2D, mipLevel, gl.DEPTH24_STENCIL8, size, size, 0, gl.DEPTH_STENCIL,
+ gl.UNSIGNED_INT_24_8, null);
+ }
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after init textures");
+
+ var framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after init framebuffer");
+
+ gl.depthRange(0.0, 1.0);
+ gl.viewport(0, 0, 128, 128);
+ gl.clearColor(0, 0, 0, 1);
+
+ // Draw loop.
+ for (var frame = 0; frame < 4; ++frame)
+ {
+ // draw into FBO
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ gl.enable(gl.DEPTH_TEST);
+
+ gl.useProgram(drawProgram);
+ if (frame % 2 != 0) {
+ drawQuad(0.0);
+ } else {
+ drawQuad(1.0);
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ // blit FBO
+ gl.disable(gl.DEPTH_TEST);
+
+ gl.useProgram(blitProgram);
+ gl.uniform1i(textureLoc, 0);
+ gl.bindTexture(gl.TEXTURE_2D, depthTex);
+
+ drawQuad(0.5);
+
+ if (frame % 2 != 0) {
+ wtu.checkCanvasRect(gl, 0, 0, 128, 128, [0, 0, 0, 255],
+ "depth texture should be black on odd iterations");
+
+ } else {
+ wtu.checkCanvasRect(gl, 0, 0, 128, 128, [255, 255, 255, 255],
+ "depth texture should be white on even iterations");
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after draw");
+ }
+
+ gl.deleteTexture(colorTex);
+ gl.deleteTexture(depthTex);
+ gl.deleteFramebuffer(framebuffer);
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ drawProgram = wtu.setupProgram(gl, ["draw-vs", "draw-fs"], ["vertex"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after draw program initialization");
+ shouldBe('gl.getProgramParameter(drawProgram, gl.LINK_STATUS)', 'true');
+
+ blitProgram = wtu.setupProgram(gl, ["blit-vs", "blit-fs"], ["vertex"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after blit program initialization");
+ shouldBe('gl.getProgramParameter(blitProgram, gl.LINK_STATUS)', 'true');
+
+ textureLoc = gl.getUniformLocation(blitProgram, "texture")
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "query texture location");
+ shouldBeNonNull('textureLoc')
+
+ run_test();
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/canvas-remains-unchanged-after-used-in-webgl-texture.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/canvas-remains-unchanged-after-used-in-webgl-texture.html
new file mode 100644
index 0000000000..5c81552793
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/canvas-remains-unchanged-after-used-in-webgl-texture.html
@@ -0,0 +1,73 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="c" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests canvas remains unchanged after it is used in webgl texutre');
+
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=446380'>Chromium Issue 446380</a>");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", undefined, 2);
+
+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 runTest(width, height) {
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ ctx.fillStyle = "rgba(1, 63, 127, 1)";
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ var refCanvas = document.createElement("canvas");
+ refCanvas.width = width;
+ refCanvas.height = height;
+ var refCtx = refCanvas.getContext("2d");
+ refCtx.fillStyle = "rgba(1, 63, 127, 1)";
+ refCtx.fillRect(0, 0, canvas.width, canvas.height);
+ // A refCanvas with same data as canvas is used to get original image data, since
+ // getImageData may change hardware accelerated status of canvas and we don't want to
+ // omit testing for hardware accelerated canvas.
+ var imageDataBefore = refCtx.getImageData(0, 0, refCanvas.width, refCanvas.height);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TexImage2D should succeed");
+ checkSourceCanvasImageData(imageDataBefore, ctx.getImageData(0, 0, canvas.width, canvas.height));
+ gl.deleteTexture(tex);
+}
+
+runTest(2, 2);
+runTest(257, 257);
+
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-from-pbo-crash.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-from-pbo-crash.html
new file mode 100644
index 0000000000..74444d32fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-from-pbo-crash.html
@@ -0,0 +1,44 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Regression test for compressedTex with PBO</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+
+// The following statement caused a crash in Chrome. See crbug.com/690335.
+// Because no PBO is bound, the last parameter is interprected as a pointer
+// to the client side data.
+gl.compressedTexImage2D(gl.TEXTURE_2D, 0, 0, 4, 4, 0, 8, 3);
+
+wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE, gl.INVALID_OPERATION],
+ "should not crash and generate a GL error");
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-image.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-image.html
new file mode 100644
index 0000000000..818d6e8dff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-image.html
@@ -0,0 +1,24 @@
+<!--
+Copyright (c) 2020 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+const contextVersion = 2;
+</script>
+<script src="../../../js/tests/compressed-tex-image.js"></script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-AMD-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-AMD-bug.html
new file mode 100644
index 0000000000..008ac88459
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-AMD-bug.html
@@ -0,0 +1,104 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL copy into cube map texture conformance test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+
+function runTest() {
+ var width = 16;
+ var height = 16;
+ var level = 0;
+ var cases = [
+ {
+ internalformat: "RGBA8",
+ format: "RGBA",
+ type: "UNSIGNED_BYTE",
+ data: new Uint8Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA8I",
+ format: "RGBA_INTEGER",
+ type: "BYTE",
+ data: new Int8Array(width * height * 4)
+ },
+ {
+ internalformat: "RGBA8UI",
+ format: "RGBA_INTEGER",
+ type: "UNSIGNED_BYTE",
+ data: new Uint8Array(width * height * 4)
+ }
+ ];
+ if (gl.getExtension("EXT_color_buffer_float")) {
+ cases.push({
+ internalformat: "RGBA32F",
+ format: "RGBA",
+ type: "FLOAT",
+ data: new Float32Array(width * height * 4)
+ });
+ }
+ cases.forEach(function(testcase) {
+ debug("");
+ debug("Testing internalformat: " + testcase.internalformat);
+
+ var internalformat = gl[testcase.internalformat];
+ var format = gl[testcase.format];
+ var type = gl[testcase.type];
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ var data = testcase.data;
+ gl.texImage2D(gl.TEXTURE_2D, level, internalformat, width, height, 0, format, type, data);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, level);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+
+ var cubeTexture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeTexture);
+
+ for (var face = gl.TEXTURE_CUBE_MAP_POSITIVE_X; face < gl.TEXTURE_CUBE_MAP_POSITIVE_X + 6; face++) {
+ gl.copyTexImage2D(face, level, internalformat, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "CopyTexImage2D should succeed.");
+ gl.copyTexSubImage2D(face, level, 0, 0, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "CopyTexSubImage2D should succeed.");
+ }
+
+ gl.deleteTexture(cubeTexture);
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+ });
+}
+
+description();
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=712117'>Chromium Issue 712117</a>");
+
+var canvas = document.getElementById("canvas");
+shouldBeNonNull("gl = wtu.create3DContext(canvas, undefined, 2)");
+
+runTest();
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-bug.html
new file mode 100644
index 0000000000..77a811cdaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-cube-map-bug.html
@@ -0,0 +1,49 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL copy into cube map texture bug conformance test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="1024" height="1024"></canvas>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+
+function runTest() {
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH,5);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 5, gl.RGBA, 75, 10, 2, 2, 0);
+ // Note that this bug only manifest with Chrome ASAN build on MacOSX with Intel drivers.
+ // At this point ASAN build will crash inside Intel driver code.
+ testPassed("Chrome ASAN build on MacOSX with Intel driver should have crashed at this point with this bug");
+}
+
+description();
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=892282'>Chromium Issue 892282</a>");
+
+var canvas = document.getElementById("canvas");
+shouldBeNonNull("gl = wtu.create3DContext(canvas, undefined, 2)");
+
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html
new file mode 100644
index 0000000000..249716deda
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html
@@ -0,0 +1,165 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL CopyTexSubImage Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64px" height="32px"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in highp vec4 a_position;
+in highp vec2 a_coord;
+out highp vec2 v_coord;
+void main(void) {
+ gl_Position = a_position;
+ v_coord = a_coord;
+}
+</script>
+<script id="fshader_luminance_alpha" type="x-shader/x-fragment">#version 300 es
+in highp vec2 v_coord;
+uniform highp sampler3D u_sampler0;
+out highp vec4 o_color0;
+void main (void) {
+ o_color0 = vec4(texture(u_sampler0,vec3(v_coord, 0)));
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the behavior of copTexSubImage3D with luminance textures.");
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+function copytexsubimage3D_luma_format() {
+
+ var testGroup = [
+ {
+ name: '3d_alpha',
+ format: gl.ALPHA,
+ width: 64,
+ height: 32,
+ depth: 2
+ },
+ {
+ name: '3d_luminance',
+ format: gl.LUMINANCE,
+ width: 64,
+ height: 32,
+ depth: 2
+ },
+ {
+ name: '3d_luminance_alpha',
+ format: gl.LUMINANCE_ALPHA,
+ width: 64,
+ height: 32,
+ depth: 2
+ }
+ ];
+
+ testGroup.forEach(function(testcase) {
+ debug("");
+ debug("Testing copytexsubimage3d_luma_format_" + testcase.name);
+
+ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ var layer = 0;
+ var width = testcase.width;
+ var height = testcase.height;
+ var depth = testcase.depth;
+ var msg;
+ var uint1 = new Uint8Array(width * height * 4);
+ for (var i = 0; i < uint1.length - 1; ++i) {
+ uint1[i + 1] = (uint1[i] + 10) % 255;
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint1);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.bindTexture(gl.TEXTURE_3D, texture[1]);
+ setUpTexStatus();
+ gl.texImage3D(gl.TEXTURE_3D, 0, testcase.format, width, height, depth, 0, testcase.format, gl.UNSIGNED_BYTE, null);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer, 0, 0,width, height);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader_luminance_alpha"], ["a_position", "a_coord"]);
+ wtu.setupUnitQuad(gl, 0, 1);
+ wtu.drawUnitQuad(gl);
+
+ for (var y = 0; y < height; ++y) {
+ for (var x = 0; x < width; ++x) {
+ var cur = y * width * 4 + x * 4;
+ if (testcase.format == gl.ALPHA) {
+ wtu.checkCanvasRect(gl, x, y, 1, 1, [ 0, 0,
+ 0, uint1[cur + 3]], msg, [1, 1, 1, 1]);
+ } else if (testcase.format == gl.LUMINANCE) {
+ wtu.checkCanvasRect(gl, x, y, 1, 1, [uint1[cur], uint1[cur],
+ uint1[cur], 255], msg, [1, 1, 1, 1]);
+ } else { // gl.LUMINANCE_ALPHA
+ wtu.checkCanvasRect(gl, x, y, 1, 1, [uint1[cur], uint1[cur],
+ uint1[cur], uint1[cur + 3]], msg, [1, 1, 1, 1]);
+ }
+ }
+ }
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ gl.deleteProgram(program);
+ });
+}
+
+function setUpTexStatus() {
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
+ );
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
+ );
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE
+ );
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE
+ );
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE
+ );
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ copytexsubimage3D_luma_format();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-same-texture.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-same-texture.html
new file mode 100644
index 0000000000..c247cabc48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-same-texture.html
@@ -0,0 +1,144 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL CopyTexImage from/to the same texture Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+// https://bugs.chromium.org/p/chromium/issues/detail?id=797235
+description("This test verifies CopyTexImage2D works if source/destination images belong to the same texture");
+debug("");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (expected.indexOf(actual) < 0) {
+ var msg = "checkFramebufferStatus expects [";
+ for (var index = 0; index < expected.length; ++index) {
+ msg += wtu.glEnumToString(gl, expected[index]);
+ if (index + 1 < expected.length)
+ msg += ", ";
+ }
+ msg += "], was " + wtu.glEnumToString(gl, actual);
+ testFailed(msg);
+ } else {
+ var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
+ " as expected";
+ testPassed(msg);
+ }
+}
+
+function checkTextureLevelColor(texture, level, level_width, level_height, x, y, width, height, color) {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var color_renderable_tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, color_renderable_tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, level_width, level_height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, color_renderable_tex, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ var program = wtu.setupTexturedQuad(gl);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, level);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, level);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvasRect(gl, x, y, width, height, color);
+
+ gl.deleteTexture(color_renderable_tex);
+ gl.deleteFramebuffer(fbo);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Check texture level color should generate no GL errors.");
+}
+
+function testChangeTargetTextureLevelSize() {
+ debug("");
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var texture = gl.createTexture();
+ wtu.fillTexture(gl, texture, 64, 64, [255, 0, 0, 255], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 1);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ // fbo source texture is |texture| level 1, 32x32. Target is |texture| level 2, 64x64.
+ // Only one quarter of the target 64x64 will come from the source.
+ // Implementations may insert internal commands before copying over 32x32 in order to
+ // initialize undefined three quarters to 0 as WebGL spec requires. This will actually create
+ // a 64x64 image at level 2 and make the fbo incomplete, thus, the copying will fail.
+ gl.copyTexImage2D(gl.TEXTURE_2D, 2, gl.RGBA8, 0, 0, 64, 64, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copyTexImage2D should succeed.");
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
+
+ checkTextureLevelColor(texture, 2, 64, 64, 0, 0, 32, 32, [255, 0, 0, 255]);
+ checkTextureLevelColor(texture, 2, 64, 64, 0, 32, 64, 32, [0, 0, 0, 0]);
+ checkTextureLevelColor(texture, 2, 64, 64, 32, 32, 32, 32, [0, 0, 0, 0]);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Test should generate no GL errors.");
+}
+
+function testChangeTargetTextureLevelFormat() {
+ debug("");
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var texture = gl.createTexture();
+ wtu.fillTexture(gl, texture, 64, 64, [255, 0, 0, 255], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 1);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ // Using LUNIMANCE_ALPHA format may trigger implementations' emulation code path
+ // on desktop core profile GL, which might change level 2 image definition first
+ // and make the fbo incomplete, thus, the actual copying will fail.
+ gl.copyTexImage2D(gl.TEXTURE_2D, 2, gl.LUMINANCE_ALPHA, 0, 0, 16, 16, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copyTexImage2D should succeed.");
+ checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
+
+ checkTextureLevelColor(texture, 2, 16, 16, 0, 0, 16, 16, [255, 255, 255, 255]);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Test should generate no GL errors.");
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ testChangeTargetTextureLevelSize();
+ testChangeTargetTextureLevelFormat();
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-webgl-specific.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-webgl-specific.html
new file mode 100644
index 0000000000..ae969e0795
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-webgl-specific.html
@@ -0,0 +1,303 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL CopyTexImage Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of copyTexImage.");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function copytexsubimage3d_invalid_operation_feedbackloops() {
+ debug("");
+ debug("Testing copytexsubimage3d_invalid_operation_feedbackloops");
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ var uint8 = new Uint8Array(32);
+ var layer = 0;
+ var width = 2;
+ var height = 2;
+ var depth = 2;
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, layer);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "gl.INVALID_OPERATION is generated");
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+};
+
+function copytexsubimage3d_valid_operation_diff_level() {
+ debug("");
+ debug("Testing copytexsubimage3d_valid_operation_diff_level");
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ var uint8 = new Uint8Array(32);
+ var level1 = 0;
+ var level2 = 1;
+ var width = 2;
+ var height = 2;
+ var depth = 2;
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ gl.generateMipmap(gl.TEXTURE_3D);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level1, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, level2, 0, 0, 0, 0, 0, width/2, height/2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed.");
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+};
+
+function copytexsubimage3d_valid_operation_diff_layer() {
+ debug("");
+ debug("Testing copytexsubimage3d_valid_operation_diff_layer");
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ var uint8 = new Uint8Array(32);
+ var layer1 = 0;
+ var layer2 = 1;
+ var width = 2;
+ var height = 2;
+ var depth = 2;
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, layer1);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer2, 0, 0, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed.");
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+}
+
+function copytexsubimage3d_texture_wrongly_initialized() {
+ debug("");
+ debug("Testing copytexsubimage3d_texture_wrongly_initialized");
+ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ var layer = 0;
+ var width = 2;
+ var height = 2;
+ var depth = 2;
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ var uint = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.bindTexture(gl.TEXTURE_3D, texture[1]);
+ gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, width, height, depth);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer, 0, 0, width, height);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture[1], 0, layer);
+ var bytes = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, bytes);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readpixel should succeed.");
+ for (var x = 0; x < width * height * 4; x++) {
+ if (bytes[x] != uint[x]) {
+ testFailed("byte comparison failure, byte at "+ x + " was " + bytes[x] +
+ ", should be " + uint[x]);
+ break;
+ }
+ }
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+};
+
+function copytexsubimage3d_out_of_bounds_test_helper(xx, yy, copyWidth, copyHeight) {
+ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ var layer = 0;
+ var width = 2;
+ var height = 2;
+ var depth = 2;
+ var width2 = 4;
+ var height2 = 4;
+ var xoffset = 0;
+ var yoffset = 0;
+ var uint = new Uint8Array(width * height * 4);
+ for (var i = 0; i < uint.length; i++) {
+ uint[i] = 0x01;
+ }
+ var uint2 = new Uint8Array(width2 * height2 * depth * 4);
+ for (var i = 0; i < uint2.length; i++) {
+ uint2[i] = 0xFF;
+ }
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.bindTexture(gl.TEXTURE_3D, texture[1]);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width2, height2, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint2);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, xoffset, yoffset, layer, xx, yy, copyWidth, copyHeight);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "using copyTexSubImage3D: x = " + xx + ", y = " + yy + " width = " + copyWidth + ", height = " + copyHeight);
+
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture[1], 0, layer);
+ var bytes = new Uint8Array(width2 * height2 * 4);
+ gl.readPixels(0, 0, width2, height2, gl.RGBA, gl.UNSIGNED_BYTE, bytes);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readpixel should succeed.");
+
+ var sourceX = new Object();
+ var sourceY = new Object();
+ Clip(xx, copyWidth, width, sourceX);
+ Clip(yy, copyHeight, height, sourceY);
+ var destX = sourceX.start - xx + xoffset;
+ var rangeX = sourceX.range;
+ var destY = sourceY.start - yy + yoffset;
+ var rangeY = sourceY.range;
+ for (var y = 0; y < height2; y++) {
+ for (var x = 0; x < width2 * 4; x++) {
+ var current = y * height2 * 4 + x;
+ // pixels copied from read framebuffer should be 0x01
+ if (x >= destX * 4 && x < (destX + rangeX) * 4 && y >= destY && y < destY + rangeY) {
+ if (bytes[current] != 0x01) {
+ testFailed("byte comparison failure, byte at "+ (current) + " was " +
+ bytes[current] +", should be 1");
+ break;
+ }
+ // pixels out-of-bounds should be untouched
+ } else {
+ if (bytes[current] != 0xFF) {
+ testFailed("byte comparison failure, byte at "+ (current) + " was " +
+ bytes[current] + ", should be 255");
+ break;
+ }
+ }
+ }
+ // Test failed; abort
+ if (x < width2 * 4) {
+ break;
+ }
+ }
+ } else {
+ testFailed("framebuffer not complete");
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+}
+
+function copytexsubimage3d_out_of_bounds() {
+ debug("");
+ debug("Test pixels outside of read framebuffer for CopyTexSubImage3D");
+
+ for(var i=0; i < testlist.length; i++) {
+ copytexsubimage3d_out_of_bounds_test_helper(testlist[i][0], testlist[i][1], testlist[i][2], testlist[i][3]);
+ }
+};
+
+/**
+ * This array defines some copy areas for CopyTexSubImage3D.
+ * A copy area is defined by x coordinate, y coordinate, copyWidth and copyHeight.
+ * the source read framebuffer is (0, 0, 2, 2).
+ */
+var testlist = [
+ [-1, -1, 4, 4],
+
+ [0, 0, 3, 3],
+ [-1, -1, 3, 3],
+ [-1, 0, 3, 3],
+ [0, -1, 3, 3],
+
+ [0, 0, 2, 3],
+ [0, 0, 3, 2],
+ [-1, 0, 3, 2],
+ [0, -1, 2, 3],
+
+ [-2, -2, 3, 3],
+ [-2, 1, 3, 3],
+ [1, -2, 3, 3],
+ [1, 1, 3, 3],
+
+ [2 , 2 ,3, 3]
+];
+
+
+function Clip(start, range, sourceRange, target) {
+ if (start < 0) {
+ range += start;
+ start = 0;
+ }
+ var end = start + range;
+ if(end > sourceRange) {
+ range -= end - sourceRange;
+ }
+ target.start = start;
+ target.range = range;
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ copytexsubimage3d_invalid_operation_feedbackloops();
+ copytexsubimage3d_valid_operation_diff_level();
+ copytexsubimage3d_valid_operation_diff_layer();
+ copytexsubimage3d_texture_wrongly_initialized();
+ copytexsubimage3d_out_of_bounds();
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html
new file mode 100644
index 0000000000..3ffdf0a94f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html
@@ -0,0 +1,249 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL CopyTexImage Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test verifies the functionality of copyTexImage2D.");
+debug("");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function checkFramebuffer(expected) {
+ var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (expected.indexOf(actual) < 0) {
+ var msg = "checkFramebufferStatus expects [";
+ for (var index = 0; index < expected.length; ++index) {
+ msg += wtu.glEnumToString(gl, expected[index]);
+ if (index + 1 < expected.length)
+ msg += ", ";
+ }
+ msg += "], was " + wtu.glEnumToString(gl, actual);
+ testFailed(msg);
+ } else {
+ var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
+ " as expected";
+ testPassed(msg);
+ }
+}
+
+var testInternalformat = function () {
+ var goodUnormFormats = [
+ "RGB",
+ "RGBA",
+ "LUMINANCE_ALPHA",
+ "LUMINANCE",
+ "ALPHA",
+ "R8",
+ "RG8",
+ "RGB8",
+ "RGBA8",
+ ];
+ var goodUnormFormatsWithUnmatchedComponentSizes = [
+ "RGB565",
+ "RGBA4",
+ "RGB5_A1",
+ "RGB10_A2",
+ ];
+ var goodSRGBFormats = [
+ "SRGB8",
+ "SRGB8_ALPHA8",
+ ];
+ var goodIntFormats = [
+ "R32I",
+ "RG32I",
+ "RGB32I",
+ "RGBA32I",
+ ];
+ var goodIntFormatsWithUnmatchedComponentSizes = [
+ "R8I",
+ "R16I",
+ "RG8I",
+ "RG16I",
+ "RGB8I",
+ "RGB16I",
+ "RGBA8I",
+ "RGBA16I",
+ ];
+ var goodUnsignedIntFormats = [
+ "R32UI",
+ "RG32UI",
+ "RGB32UI",
+ "RGBA32UI",
+ ];
+ var goodUnsignedIntFormatsWithUnmatchedComponentSizes = [
+ "R8UI",
+ "R16UI",
+ "RG8UI",
+ "RG16UI",
+ "RGB10_A2UI",
+ "RGB8UI",
+ "RGB16UI",
+ "RGBA8UI",
+ "RGBA16UI",
+ ];
+ const snormFormats = [
+ "R8_SNORM",
+ "RG8_SNORM",
+ "RGB8_SNORM",
+ "RGBA8_SNORM",
+ ];
+ const float16Formats = [
+ "R16F",
+ "RG16F",
+ "RGB16F",
+ "RGBA16F",
+ ];
+ const float32Formats = [
+ "R32F",
+ "RG32F",
+ "RGB32F",
+ "RGBA32F",
+ ];
+ const float11Formats = [
+ "R11F_G11F_B10F",
+ ];
+ const depthAndOrStencilFormats = [
+ "DEPTH_COMPONENT16",
+ "DEPTH_COMPONENT24",
+ "DEPTH_COMPONENT32F",
+ "DEPTH24_STENCIL8",
+ ];
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ function testFormat(internalformat, srcTexFormatsTypes, fboAttachmentType, expected, msg) {
+ var fbo = gl.createFramebuffer();
+ var srcTexture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, srcTexture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[srcTexFormatsTypes.internalformat], 64, 64, 0, srcTexFormatsTypes.format, srcTexFormatsTypes.type, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, fboAttachmentType, gl.TEXTURE_2D, srcTexture, 0);
+ checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl[internalformat], 0, 0, 64, 64, 0);
+ wtu.glErrorShouldBe(gl, expected, msg + srcTexFormatsTypes.internalformat + '=>' + internalformat);
+
+ gl.deleteTexture(srcTexture);
+ gl.deleteFramebuffer(fbo);
+ }
+
+ goodUnormFormats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA", format: gl.RGBA, type: gl.UNSIGNED_BYTE };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat ");
+ srcTexFormatsTypes = { internalformat: "RGBA8", format: gl.RGBA, type: gl.UNSIGNED_BYTE };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat ");
+ });
+ goodUnormFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA8", format: gl.RGBA, type: gl.UNSIGNED_BYTE };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION,
+ "copyTexImage2D should fail for good internalformat with unmatched component sizes ");
+ });
+
+ goodSRGBFormats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "SRGB8_ALPHA8", format: gl.RGBA, type: gl.UNSIGNED_BYTE };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat ");
+ });
+
+ goodIntFormats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA32I", format: gl.RGBA_INTEGER, type: gl.INT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat ");
+ });
+ goodIntFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA32I", format: gl.RGBA_INTEGER, type: gl.INT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION,
+ "copyTexImage2D should fail for good internalformat with unmatched component sizes ");
+ });
+
+ goodUnsignedIntFormats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA32UI", format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat ");
+ });
+ goodUnsignedIntFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA32UI", format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION,
+ "copyTexImage2D should fail for good internalformat with unmatched component sizes ");
+ });
+
+ snormFormats.forEach(function(internalformat) {
+ const srcTexFormatsTypes = { internalformat: "RGBA8", format: gl.RGBA, type: gl.UNSIGNED_BYTE };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "copyTexImage2D should fail for snorm internalformat ");
+ });
+
+ if (gl.getExtension("EXT_color_buffer_float")) {
+ float16Formats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA16F", format: gl.RGBA, type: gl.FLOAT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for float16 internalformat ");
+ });
+ float32Formats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA32F", format: gl.RGBA, type: gl.FLOAT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for float32 internalformat ");
+ });
+ float11Formats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "R11F_G11F_B10F", format: gl.RGB, type: gl.FLOAT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for R11F_G11F_B10F internalformat ");
+ });
+
+ float32Formats.concat(float11Formats).forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA16F", format: gl.RGBA, type: gl.FLOAT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION,
+ "copyTexImage2D should fail for non-float16 internalformat (unmatched component sizes) ");
+ });
+ float16Formats.concat(float11Formats).forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "RGBA32F", format: gl.RGBA, type: gl.FLOAT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION,
+ "copyTexImage2D should fail for non-float32 internalformat (unmatched component sizes) ");
+ });
+ float16Formats.concat(float32Formats).forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "R11F_G11F_B10F", format: gl.RGB, type: gl.FLOAT };
+ testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION,
+ "copyTexImage2D should fail for non-R11F_G11F_B10F internalformat (unmatched component sizes) ");
+ });
+ }
+
+ depthAndOrStencilFormats.forEach(function(internalformat) {
+ var srcTexFormatsTypes = { internalformat: "DEPTH24_STENCIL8", format: gl.DEPTH_STENCIL, type: gl.UNSIGNED_INT_24_8};
+ testFormat(internalformat, srcTexFormatsTypes, gl.DEPTH_STENCIL_ATTACHMENT,
+ [gl.INVALID_ENUM, gl.INVALID_OPERATION],
+ "copyTexImage2D should fail for depth internalformat ");
+ });
+
+ gl.deleteTexture(texture);
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ testInternalformat();
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/generate-mipmap-with-large-base-level.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/generate-mipmap-with-large-base-level.html
new file mode 100644
index 0000000000..010cc0f913
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/generate-mipmap-with-large-base-level.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test if GenerateMipmap on immutable texture with large BASE_LEVEL triggers a crash</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This is a regression test for crbug.com/913301");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", null, 2);
+gl.clearColor(0, 1, 0, 1);
+
+var targets = [gl.TEXTURE_2D, gl.TEXTURE_3D];
+for (var ii = 0; ii < targets.length; ++ii) {
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var target = targets[ii];
+ var tex = gl.createTexture();
+ gl.bindTexture(target, tex);
+ gl.texParameteri(target, gl.TEXTURE_BASE_LEVEL, 1416354905);
+ gl.texParameteri(target, gl.TEXTURE_MAX_LEVEL, 5);
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ if (target == gl.TEXTURE_2D)
+ gl.texStorage2D(target, 5, gl.R8, 32, 32);
+ else
+ gl.texStorage3D(target, 5, gl.R8, 32, 32, 32);
+ // Should not crash calling generateMipmap.
+ gl.generateMipmap(target);
+ gl.deleteTexture(tex);
+ // If crashed, readPixels() won't be able to work correctly.
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 5);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html
new file mode 100644
index 0000000000..babe388d14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL getTexParameter test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../../js/tests/gl-get-tex-parameter.js"></script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html
new file mode 100644
index 0000000000..c94e359d64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html
@@ -0,0 +1,221 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Ensure sampling-feedback detection can allow certain immutable texture uses</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description();
+
+const gl = wtu.create3DContext(undefined, undefined, 2);
+
+function* range(a, b) {
+ a.required;
+ if (b === undefined) {
+ b = a;
+ a = 0;
+ }
+ for (let i = a; i < b; i += 1) {
+ yield i;
+ }
+}
+
+const VS = `\
+void main() {
+ gl_PointSize = 1.0;
+}
+`;
+
+const FS = `\
+uniform sampler2D u_tex0;
+void main() {
+ gl_FragColor = texture2D(u_tex0, vec2(0));
+}
+`;
+
+const prog = wtu.loadProgram(gl, VS, FS);
+gl.useProgram(prog);
+
+(() => {
+ const MIPS = 3;
+ const SIZE = 10;
+
+ const immutTex = gl.createTexture();
+ immutTex.name = "immutTex";
+ immutTex.immutable = true;
+ gl.bindTexture(gl.TEXTURE_2D, immutTex);
+ gl.texStorage2D(gl.TEXTURE_2D, MIPS, gl.RGBA8, SIZE, SIZE);
+
+ const mutTex = gl.createTexture();
+ mutTex.name = "mutTex";
+ mutTex.immutable = false;
+ gl.bindTexture(gl.TEXTURE_2D, mutTex);
+ for (const mip of range(MIPS)) {
+ const size = SIZE >> mip;
+ gl.texImage2D(gl.TEXTURE_2D, mip, gl.RGBA8, size, size, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+
+ const MAG_FILTERS = [
+ 'LINEAR',
+ 'NEAREST',
+ ];
+ const MIN_FILTERS = [
+ ['LINEAR',false],
+ ['LINEAR_MIPMAP_LINEAR',true],
+ ['LINEAR_MIPMAP_NEAREST',true],
+ ['NEAREST',false],
+ ['NEAREST_MIPMAP_LINEAR',true],
+ ['NEAREST_MIPMAP_NEAREST',true],
+ ];
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ debug(`
+ mips: ${MIPS}: [0,${MIPS-1}] (inclusive)
+ size: ${SIZE}`);
+ const texs = [
+ immutTex,
+ mutTex,
+ ];
+ for (const tex of texs) {
+ debug(`\
+
+ immutable: ${tex.immutable}`);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ for (const level_prime_base of range(MIPS+1)) { // `level_base` in GLES
+ // ES 3.0.6 p150
+ let _level_base = level_prime_base;
+ if (tex.immutable) {
+ _level_base = Math.min(_level_base, MIPS-1);
+ }
+ const level_base = _level_base;
+
+ for (let _level_prime_max of range(level_prime_base-1, MIPS+2)) { // `q` in GLES
+ if (_level_prime_max < 0) continue;
+ if (_level_prime_max == MIPS+1) {
+ _level_prime_max = 10000; // This is the default, after all!
+ }
+ const level_prime_max = _level_prime_max;
+
+ // ES 3.0.6 p150
+ let _level_max = level_prime_max;
+ if (tex.immutable) {
+ _level_max = Math.min(Math.max(level_base, level_prime_max), MIPS-1);
+ }
+ const level_max = _level_max;
+
+ const p = Math.floor(Math.log2(SIZE)) + level_base;
+ const q = Math.min(p, level_max);
+
+ debug(`\
+
+ level_prime_base/max: [${level_prime_base}, ${level_prime_max}] (inclusive)
+ level_base/max: [${level_base}, ${level_max}] (inclusive)
+ q: ${q}`);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL,
+ level_prime_base);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL,
+ level_prime_max);
+
+ const mipComplete = (q <= MIPS-1);
+
+ for (const [minFilter,useMips] of MIN_FILTERS) {
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
+ gl[minFilter]);
+
+ // ES3.0 p211
+ const srcMaxSampledMip = (useMips ? q : level_base);
+
+ // ES3.0 p160-161
+ const textureComplete = (srcMaxSampledMip <= MIPS-1) &&
+ (level_base <= level_max);
+
+ for (const magFilter of MAG_FILTERS) {
+ debug(`\
+
+ min: ${minFilter}, mag: ${magFilter}`);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,
+ gl[magFilter]);
+
+ for (const dstMip of range(0,MIPS+1)) {
+ debug(`
+ mip: ${dstMip}`);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, tex, dstMip);
+
+ // -
+
+ // ES3.0 p213-214
+ let fbComplete = true;
+
+ // * "The width and height of `image` are non-zero"
+ fbComplete &= (0 <= dstMip && dstMip <= MIPS-1);
+
+ if (!tex.immutable) { // "...does not name an immutable-format texture..."
+ // * "...the value of [level] must be in the range `[level_base, q]`"
+ fbComplete &= (level_base <= dstMip && dstMip <= q);
+
+ // * "...the value of [level] is not `level_base`, then the texture must be mipmap complete"
+ if (dstMip != level_base) {
+ fbComplete &= mipComplete;
+ }
+ }
+
+ // -
+
+ let expectError = 0;
+ let expectStatus = gl.FRAMEBUFFER_COMPLETE;
+
+ // ES3.0 p211
+ let samplingFeedback = (level_base <= dstMip && dstMip <= srcMaxSampledMip);
+ if (!textureComplete) {
+ // Incomplete textures are safe
+ samplingFeedback = false;
+ }
+ if (samplingFeedback) {
+ expectError = gl.INVALID_OPERATION;
+ }
+ if (!fbComplete) {
+ expectStatus = gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ expectError = gl.INVALID_FRAMEBUFFER_OPERATION;
+ }
+
+ // -
+
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER,
+ expectStatus, `{immutable: ${tex.immutable}, level_prime_base/max: [${level_prime_base}, ${level_prime_max}], minFilter: ${minFilter}, dest: ${dstMip}}`);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expectError, "after draw with texture");
+ }
+ }
+ }
+ }
+ }
+ }
+})();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html
new file mode 100644
index 0000000000..99ee766227
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html
@@ -0,0 +1,216 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Integer Cubemap Texture Specification Order Bug Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="128" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+ precision highp float;
+ in vec4 a_position;
+ void main(){
+ gl_Position = a_position;
+ }
+</script>
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+ precision highp float;
+ // This program samples both textures at varying Lod and exposes
+ // both of them, the regular on top, and the weird on the bottom.
+ // On the NVIDIA driver the top is both green and red while the bottom
+ // is only green. This is a driver bug because both textures should be
+ // exactly the same.
+ // I think that because of our level specification order weirdness, the
+ // driver gets confused as to which levels are complete and thinks only
+ // level 0 is complete. Then when sampling the texture it clamps the sampling
+ // to only level 0, resulting in green for all Lod values.
+ layout(location = 0) out vec4 fragColor;
+ uniform highp isamplerCube texRegular;
+ uniform highp isamplerCube texWeird;
+ void main() {
+ vec2 fragPos = gl_FragCoord.xy / vec2(128.0, 128.0);
+ float lod = (fragPos.x - 0.5) * 10.0 + 0.5;
+
+ ivec4 colorRegular = textureLod(texRegular, vec3(1.0, 0.0, 0.0), lod);
+ ivec4 colorWeird = textureLod(texWeird, vec3(1.0, 0.0, 0.0), lod);
+
+ if (fragPos.y > 0.51) {
+ fragColor = vec4(vec2(colorRegular.rg), 0.0, 1.0);
+ } else if (fragPos.y < 0.49){
+ fragColor = vec4(vec2(colorWeird.rg), 0.0, 1.0);
+ } else {
+ fragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ }
+</script>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+
+description("Test for a driver bug when specifying integer cubemaps in weird order");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function createTextureCube(layers, maxLevel) {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+
+ layers.forEach(function(layer) {
+ var level = layer.level;
+ var face = layer.face;
+ var color = layer.color;
+
+ var levelSize = 1 << (maxLevel - level);
+
+ var backingBuffer = new ArrayBuffer(levelSize * levelSize * 2);
+ new Int16Array(backingBuffer).fill(color);
+ gl.texImage2D(face + gl.TEXTURE_CUBE_MAP_POSITIVE_X, level, gl.RG8I, levelSize, levelSize, 0, gl.RG_INTEGER, gl.BYTE, new Int8Array(backingBuffer));
+ });
+
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ return texture;
+}
+
+function makePermutedLayers(layers, permutation) {
+ return permutation.map(i => layers[i]);
+}
+
+function test() {
+ var kMaxLevel = 4;
+ var kBlack = 0x0000;
+ var kGreen = 0x7F00;
+ var kRed = 0x007F;
+
+ // Create two integer cubemaps with green on level 0 and red on the others.
+
+ // The "regular" cube map is filled in a sensible manner.
+ var regularLayers = [];
+ for (var level = 0; level <= kMaxLevel; level ++) {
+ for (var face = 0; face < 6; face ++) {
+ if (level == 0) {
+ regularLayers.push({level: level, face: face, color: kGreen});
+ } else {
+ regularLayers.push({level: level, face: face, color: kRed});
+ }
+ }
+ }
+
+ // The "weird" cube map has all its >= 1 levels filled, then the first level,
+ // then the >= 1 levels again but for one face. This replicates what the
+ // Chromium command buffer "cubemap completeness" workaround is doing.
+ var weirdLayers = [];
+ for (var level = 1; level <= kMaxLevel; level ++) {
+ for (var face = 0; face < 5; face ++) {
+ weirdLayers.push({level: level, face: face, color: kBlack});
+ }
+ weirdLayers.push({level: level, face: 5, color: kRed});
+ }
+ for (var level = 0; level <= kMaxLevel; level ++) {
+ for (var face = 0; face < 6; face ++) {
+ if (level == 0) {
+ weirdLayers.push({level: level, face: face, color: kGreen});
+ } else {
+ if (face != 5) {
+ weirdLayers.push({level: level, face: face, color: kRed});
+ }
+ }
+ }
+ }
+
+ var regularTex = createTextureCube(regularLayers, kMaxLevel);
+
+ var sampleProgram = wtu.setupProgram(gl, ["vs", "fs"], ["a_position"]);
+ var regularLocation = gl.getUniformLocation(sampleProgram, "texRegular");
+ var weirdLocation = gl.getUniformLocation(sampleProgram, "texWeird");
+
+ wtu.setupQuad(gl, gl.getAttribLocation(sampleProgram, "a_position"));
+
+ gl.uniform1i(regularLocation, 0);
+ gl.uniform1i(weirdLocation, 1);
+
+ function testcase(layers1, casename) {
+ var tex1 = createTextureCube(layers1, kMaxLevel);
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, regularTex);
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex1);
+ // At this point both textures should be the same.
+ wtu.drawUnitQuad(gl);
+
+ gl.deleteTexture(tex1);
+
+ wtu.checkCanvasRect(gl, 96, 32, 1, 1, [255, 0, 0, 255], "should be green: " + casename);
+ wtu.checkCanvasRect(gl, 96, 96, 1, 1, [255, 0, 0, 255], "should be green: " + casename);
+ wtu.checkCanvasRect(gl, 32, 32, 1, 1, [0, 255, 0, 255], "should be red: " + casename);
+ wtu.checkCanvasRect(gl, 32, 96, 1, 1, [0, 255, 0, 255], "should be red: " + casename);
+ }
+
+ testcase(weirdLayers, "original");
+ const cases = [
+ [10,23,3,19,26,29,14,9,4,11,27,28,13,24,20,12,17,21,16,5,6,25,1,15,22,8,7,18,0,2],
+ [10,27,3,29,17,28,13,20,18,25,9,2,8,4,24,12,15,7,19,11,6,14,16,21,1,26,23,22,0,5],
+ [11,4,15,13,26,24,25,2,19,20,16,23,1,18,28,27,6,21,14,8,17,29,3,10,12,9,22,7,0,5],
+ [14,2,6,28,7,25,11,26,22,13,19,21,24,4,16,29,9,27,3,17,18,15,12,20,8,23,10,1,0,5],
+ [14,20,22,16,11,27,17,21,15,3,5,28,6,2,9,12,7,24,1,26,8,19,23,25,18,13,29,10,0,4],
+ [14,20,22,16,11,27,17,21,15,3,5,28,6,2,9,12,7,24,1,26,8,19,23,25,18,13,29,10,0,4],
+ [14,22,27,1,12,24,13,21,6,10,20,28,23,16,5,18,7,3,25,2,11,19,17,26,8,29,15,9,0,4],
+ [15,22,13,28,6,12,19,9,18,11,3,23,17,8,10,20,5,14,4,25,27,26,21,16,29,24,7,0,1,2],
+ [15,22,13,28,6,12,19,9,18,11,3,23,17,8,10,20,5,14,4,25,27,26,21,16,29,24,7,0,1,2],
+ [16,22,18,15,19,6,21,27,4,14,29,17,7,9,11,20,24,23,28,25,2,13,10,26,8,12,3,0,5,1],
+ [16,26,18,7,20,25,11,24,2,1,28,13,29,10,27,21,6,15,5,19,17,12,14,9,23,22,8,3,0,4],
+ [2,22,25,12,19,16,7,27,9,10,8,17,18,24,1,21,20,14,13,4,11,29,15,5,23,26,6,28,0,3],
+ [2,9,16,26,6,15,4,3,17,13,21,10,7,22,23,29,19,18,12,24,14,25,8,5,20,28,11,27,0,1],
+ [2,9,16,26,6,15,4,3,17,13,21,10,7,22,23,29,19,18,12,24,14,25,8,5,20,28,11,27,0,1],
+ [20,21,24,15,5,13,6,12,2,17,10,14,27,16,8,22,9,25,29,1,28,11,4,19,7,23,26,18,0,3],
+ [21,14,19,12,28,6,10,7,16,27,11,22,20,24,25,26,3,8,4,18,5,2,9,15,17,23,13,29,0,1],
+ [22,4,18,7,11,6,23,17,14,3,13,21,15,19,25,28,9,8,10,12,29,16,27,2,24,1,20,26,0,5],
+ [22,4,18,7,11,6,23,17,14,3,13,21,15,19,25,28,9,8,10,12,29,16,27,2,24,1,20,26,0,5],
+ [23,21,9,28,22,15,25,12,24,18,29,2,17,1,14,4,16,26,3,11,27,13,8,7,6,20,10,19,0,5],
+ [23,6,15,13,19,2,12,7,11,29,3,20,17,10,4,18,1,22,16,27,24,9,21,25,14,26,8,28,0,5],
+ [25,12,1,4,9,22,16,28,6,11,14,29,15,2,5,13,10,20,21,19,23,27,18,26,7,8,17,24,0,3],
+ [25,13,29,26,28,17,19,23,7,24,10,1,15,8,3,11,18,21,27,22,12,5,9,6,16,14,20,2,0,4],
+ [25,18,28,12,27,13,11,4,29,8,21,15,9,6,26,20,22,23,24,17,5,16,2,7,14,19,10,0,1,3],
+ [25,19,3,10,23,15,27,18,12,8,7,24,16,14,26,4,21,5,9,1,22,28,20,29,6,11,13,17,0,2],
+ [25,24,12,9,13,10,23,4,19,29,16,1,15,8,21,26,18,11,17,7,20,28,22,14,27,6,0,2,5,3],
+ [25,9,29,8,3,6,10,27,11,28,13,23,18,16,17,19,5,22,12,26,21,4,7,14,24,15,2,20,0,1],
+ [27,23,20,2,12,14,6,19,3,28,18,10,29,11,13,22,21,7,15,9,8,17,25,16,26,24,4,5,0,1],
+ [27,7,2,5,19,10,3,26,22,18,23,16,9,24,21,17,6,28,12,14,25,29,13,15,8,20,11,4,0,1],
+ [28,7,10,9,29,27,2,20,1,26,11,5,12,23,25,3,17,16,24,13,8,6,14,18,21,19,15,22,0,4],
+ [28,8,23,13,18,29,20,9,10,27,15,21,3,19,14,4,26,5,24,1,6,17,11,12,16,7,25,22,0,2],
+ [29,12,13,2,22,19,16,7,14,11,24,23,28,15,17,9,20,21,18,26,27,25,10,5,8,6,4,3,0,1],
+ [29,8,5,4,7,15,19,17,3,26,13,9,23,6,25,22,27,24,14,16,10,21,11,18,28,12,2,20,0,1],
+ [5,18,6,17,19,16,13,11,28,8,10,4,29,26,20,24,9,7,21,25,27,23,22,2,15,14,12,0,3,1],
+ [5,23,2,15,7,13,19,11,27,3,22,14,4,26,28,20,17,18,8,25,16,29,10,24,12,9,6,21,0,1],
+ [7,24,27,26,16,18,22,20,10,11,9,19,23,12,17,13,4,2,6,1,21,25,15,28,8,3,29,14,0,5],
+ ];
+ for (const c of cases) {
+ testcase(makePermutedLayers(regularLayers, c), "case " + c.toString());
+ }
+}
+
+test();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-texture-sampling.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-texture-sampling.html
new file mode 100644
index 0000000000..8ad4967608
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-texture-sampling.html
@@ -0,0 +1,169 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Integer Cubemap Texture Sampling Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="128" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+
+description("Verify sampling works fine with integer cubemap textures");
+debug("https://github.com/KhronosGroup/WebGL/issues/1819");
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var testCases = [
+ { internalFormat: "R8UI", format: "RED_INTEGER", type: "UNSIGNED_BYTE" },
+ { internalFormat: "RG8UI", format: "RG_INTEGER", type: "UNSIGNED_BYTE" },
+ { internalFormat: "RGB8UI", format: "RGB_INTEGER", type: "UNSIGNED_BYTE" },
+ { internalFormat: "RGBA8UI", format: "RGBA_INTEGER", type: "UNSIGNED_BYTE" },
+];
+
+function setupData(internalFormat, size) {
+ var numComponents = 0;
+ switch (gl[internalFormat]) {
+ case gl.R8UI:
+ numComponents = 1;
+ break;
+ case gl.RG8UI:
+ numComponents = 2;
+ break;
+ case gl.RGB8UI:
+ numComponents = 3;
+ break;
+ case gl.RGBA8UI:
+ numComponents = 4;
+ break;
+ }
+ if (numComponents == 0) {
+ testFailed("This should never be reached");
+ return null;
+ }
+ var data = new Uint8Array(numComponents * size * size);
+ for (var ii = 0; ii < size * size; ++ii) {
+ // Set all pixels to RED.
+ data[ii * numComponents] = 255;
+ if (numComponents > 1)
+ data[ii * numComponents + 1] = 0;
+ if (numComponents > 2)
+ data[ii * numComponents + 2] = 0;
+ if (numComponents > 3)
+ data[ii * numComponents + 3] = 255;
+ }
+ return data;
+}
+
+function checkIntegerTextureValues(internalFormat, size) {
+ var buffer = new Uint32Array(4 * size * size);
+ gl.readPixels(0, 0, size, size, gl.RGBA_INTEGER, gl.UNSIGNED_INT, buffer);
+ for (var y = 0; y < size; ++y) {
+ for (var x = 0; x < size; ++x) {
+ var index = (y * size + x) * 4;
+ if (buffer[index] != 255 || buffer[index + 1] != 0 || buffer[index + 2] != 0) {
+ testFailed("At (" + x + ", " + y + "), expected 255,0,0,255, was " +
+ [buffer[index], buffer[index + 1], buffer[index + 2], buffer[index + 3]]);
+ return;
+ }
+ }
+ }
+ testPassed("All pixels are as expected");
+}
+
+function runOneTest(internalFormat, format, type, size) {
+ debug("");
+ debug("Testing internalformat = " + internalFormat + ", format = " + format + ", type = " + type + ", size = " + size);
+
+ gl.clearColor(1, 1, 0, 1);
+ gl.clearDepth(1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ 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];
+ var data = setupData(internalFormat, size);
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], size, size, 0, gl[format], gl[type], data);
+ }
+
+ debug("1) Reading back texture data");
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, targets[tt], tex, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ checkIntegerTextureValues(internalFormat, size);
+ }
+ }
+ gl.deleteFramebuffer(fbo);
+
+ debug("2) Rendering with texture");
+ var program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ var loc = gl.getUniformLocation(program, "face");
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.uniform1i(loc, targets[tt]);
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+ wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [255, 0, 0, 255], "Should be red");
+ }
+ gl.deleteProgram(program);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL errors");
+
+ var m = wtu.makeImageFromCanvas(gl.canvas);
+ document.getElementById("console").appendChild(m);
+ document.getElementById("console").appendChild(document.createElement("hr"));
+}
+
+function runTests() {
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 2);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 4);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 8);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 16);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 32);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 64);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 65);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 127);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 128);
+ runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 129);
+ }
+}
+
+runTests();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/mipmap-fbo.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/mipmap-fbo.html
new file mode 100644
index 0000000000..cd48bb77c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/mipmap-fbo.html
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test if mipmap incomplete textures can be used as FBO attachments</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="24" height="24"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var testIncompleteMipmapInFBO = function () {
+ // Create a texture that's not mipmap complete.
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ // Framebuffer should be incomplete for incomplete texture.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 1);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+}
+
+testIncompleteMipmapInFBO();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/npot-video-sizing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/npot-video-sizing.html
new file mode 100644
index 0000000000..3ce3917da3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/npot-video-sizing.html
@@ -0,0 +1,181 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl = null;
+var textureLoc = null;
+var expectedVideoHeightLoc = null;
+var successfullyParsed = false;
+var resourcePath = "../../../resources/";
+// Test each format separately because many browsers implement each
+// differently. Some might be GPU accelerated, some might not. Etc...
+var videos = [
+ { src: resourcePath + "npot-video-1920x1080.mp4" ,
+ type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ // It was found that Firefox's videoHeight doesn't report the
+ // correct answer for this video resource, though the uploaded
+ // video texture is the correct size.
+ expectedHeight: 1080,
+ },
+ // Should port this to other formats. See tex-image-and-sub-image-2d-with-video.js.
+];
+var videoNdx = 0;
+var videoInfo;
+var video;
+
+initTestingHarness();
+
+var vertexShader = [
+ '#version 300 es',
+ 'in vec4 vPosition;',
+ 'in vec2 texCoord0;',
+ 'out vec2 texCoord;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' texCoord = texCoord0;',
+ '}'].join('\n');
+
+// ESSL 3.00 and WebGL 2.0 are used in order to gain access to the
+// "textureSize" built-in function. This was the most reliable way to
+// verify the behavior of video-to-texture uploads.
+
+var fragmentShader = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump sampler2D tex;',
+ 'uniform int expectedVideoHeight;',
+ 'in vec2 texCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' if (textureSize(tex, 0).y == expectedVideoHeight) {',
+ ' fragData = vec4(0.0, 1.0, 0.0, 1.0);',
+ ' } else {',
+ ' fragData = vec4(1.0, 0.0, 0.0, 1.0);',
+ ' }',
+ '}'].join('\n');
+
+function init()
+{
+ description('Verify sizing of npot videos uploaded to textures');
+
+ debug('Verifies that the size of a texture, uploaded from a video, is exactly the expected size of the video.');
+ debug('Regression test for <a href="http://crbug.com/672895">http://crbug.com/672895</a>');
+
+ var canvas = document.getElementById("example");
+ gl = wtu.create3DContext(canvas, { preserveDrawingBuffer: true }, 2);
+ wtu.setupUnitQuad(gl);
+ var program = wtu.setupProgram(
+ gl,
+ [vertexShader, fragmentShader],
+ ['vPosition', 'texCoord0'],
+ [0, 1]);
+
+ if (!program) {
+ testFailed("Error creating program");
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+
+ textureLoc = gl.getUniformLocation(program, "tex");
+ expectedVideoHeightLoc = gl.getUniformLocation(
+ program, "expectedVideoHeight");
+
+ requestAnimationFrame(runNextVideo);
+}
+
+function runNextVideo() {
+ if (video) {
+ video.pause();
+ }
+
+ if (videoNdx == videos.length) {
+ finishTest();
+ return;
+ }
+
+ videoInfo = videos[videoNdx++];
+ debug("");
+ debug("testing: " + videoInfo.type);
+ video = document.createElement("video");
+ video.muted = true;
+ var canPlay = true;
+ if (!video.canPlayType) {
+ testFailed("video.canPlayType required method missing");
+ requestAnimationFrame(runNextVideo);
+ return;
+ }
+
+ if (!video.canPlayType(videoInfo.type).replace(/no/, '')) {
+ debug(videoInfo.type + " unsupported");
+ requestAnimationFrame(runNextVideo);
+ return;
+ };
+
+ document.body.appendChild(video);
+ video.style = "display:none;";
+ video.type = videoInfo.type;
+ video.src = videoInfo.src;
+ wtu.startPlayingAndWaitForVideo(video, runTest);
+}
+
+function runTest()
+{
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+ // Upload the video element into the texture
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, video);
+ // Point the uniform sampler to texture unit 0
+ gl.uniform1i(textureLoc, 0);
+ // Set up the expected video size
+ debug('video\'s expected height: ' + videoInfo.expectedHeight);
+ debug('video\'s reported width and height: ' + video.videoWidth + ' x ' + video.videoHeight);
+ // We only verify the height. Chrome was generating the wrong
+ // height for some video resources. As it stands, not all browsers
+ // match the video's width exactly.
+ gl.uniform1i(expectedVideoHeightLoc, videoInfo.expectedHeight);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ // Verify that the video texture's size was as expected
+ wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height,
+ [0, 255, 0, 255],
+ "Should be green -- that indicates the video texture's height was correct",
+ 1);
+
+ requestAnimationFrame(runNextVideo);
+}
+
+</script>
+</head>
+<body onload="init()">
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/origin-clean-conformance-offscreencanvas.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/origin-clean-conformance-offscreencanvas.html
new file mode 100644
index 0000000000..2c6a118cc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/origin-clean-conformance-offscreencanvas.html
@@ -0,0 +1,146 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Origin Restrictions Conformance Tests for OffscreenCanvas</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas"></canvas>
+<img id="img" style="display:none;">
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+// Checks if function throws an exception.
+function causedException(func) {
+ var hadException = false;
+ try {
+ func();
+ } catch(e) {
+ hadException = true;
+ }
+ return hadException;
+}
+
+var defaultImgUrl = "https://get.webgl.org/conformance-resources/opengl_logo.jpg";
+var localImgUrl = "../../../resources/opengl_logo.jpg";
+
+var imgDomain;
+var pageDomain;
+
+function imageLoaded(img) {
+ description("This test ensures WebGL2 implementations for OffscreenCanvas follow proper same-origin restrictions.");
+
+ if (!window.OffscreenCanvas) {
+ testPassed("No OffscreenCanvas support");
+ finishTest();
+ return;
+ }
+
+ assertMsg(img.width > 0 && img.height > 0, "img was loaded");
+ imgDomain = wtu.getBaseDomain(wtu.getHost(img.src));
+ pageDomain = wtu.getBaseDomain(window.location.host);
+ assertMsg(imgDomain != pageDomain,
+ "img domain (" + imgDomain + ") and page domain (" + pageDomain + ") are not the same.");
+
+ function makeTexImage2D(gl, src) {
+ return function() {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 10, 10, 0, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeTexSubImage2D(gl, src) {
+ return function() {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeTexImage3D(gl, src) {
+ return function() {
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 10, 10, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeTexSubImage3D(gl, src) {
+ return function() {
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 10, 10, 1, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeReadPixels(gl) {
+ return function() {
+ var buf = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ };
+ }
+
+ var offscreencanvas = new OffscreenCanvas(10, 10);
+ var gl = wtu.create3DContext(offscreencanvas, null, 2);
+
+ debug("");
+ debug("check that an attempt to upload an image from another origin throws an exception.");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ assertMsg(causedException(makeTexImage2D(gl, img)),
+ "texImage2D with cross-origin image should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, img)),
+ "texSubImage2D with cross-origin image should throw exception.");
+ assertMsg(causedException(makeTexImage3D(gl, img)),
+ "texImage3D with cross-origin image should throw exception.");
+ assertMsg(causedException(makeTexSubImage3D(gl, img)),
+ "texSubImage3D with cross-origin image should throw exception.");
+
+
+ debug("check that readPixels continues to work against this offscreencanvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL2 canvas.");
+
+ debug("check that an attempt to upload a tainted canvas throws an exception.");
+ var canvas = document.getElementById("canvas");
+ var ctx2d = canvas.getContext("2d");
+ ctx2d.drawImage(img, 0, 0);
+ assertMsg(causedException(makeTexImage2D(gl, canvas)),
+ "texImage2D with NON origin clean canvas should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, canvas)),
+ "texSubImage2D with NON origin clean canvas should throw exception.");
+ assertMsg(causedException(makeTexImage3D(gl, canvas)),
+ "texImage3D with NON origin clean canvas should throw exception.");
+ assertMsg(causedException(makeTexSubImage3D(gl, canvas)),
+ "texSubImage3D with NON origin clean canvas should throw exception.");
+
+ debug("check that readPixels continues to work against this offscreencanvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL2 canvas.");
+
+ // TODO: Should check video.
+ // TODO: Should check CORS support.
+
+ finishTest();
+}
+
+(async function() {
+ const img = document.getElementById('img');
+ try {
+ await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl), 1000);
+ } catch (e) {
+ testFailed(`Image setup failed (${e}).`);
+ finishTest();
+ return;
+ }
+ imageLoaded(img);
+})();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-mipmap-levels-intel-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-mipmap-levels-intel-bug.html
new file mode 100644
index 0000000000..594938c089
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-mipmap-levels-intel-bug.html
@@ -0,0 +1,82 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 3D texture mipmap level conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 2px; height: 2px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader_texsize" type="x-shader/x-vertex">#version 300 es
+in vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader_texsize_3d" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform highp sampler3D tex;
+uniform int lod;
+uniform ivec3 texSize;
+out vec4 fragColor;
+void main()
+{
+ fragColor = (textureSize(tex, lod) == texSize ? vec4(255, 0, 0, 255) : vec4(0, 0, 0, 255));
+}
+</script>
+
+
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+// This test fails on Intel Mesa, see crbug.com/666384.
+(function() {
+ debug("");
+ debug("Test textureSize should work correctly with non-zero base level for texStorage3D");
+ var program = wtu.setupProgram(
+ gl, ['vshader_texsize', 'fshader_texsize_3d'], ['vPosition'], [0]);
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+ gl.uniform1i(gl.getUniformLocation(program, "lod"), 1);
+ gl.uniform3i(gl.getUniformLocation(program, "texSize"), 8, 4, 2);
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAG_FILTER) should succeed");
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed");
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_BASE_LEVEL, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed");
+ gl.texStorage3D(gl.TEXTURE_3D, 4, gl.RGBA8, 32, 16, 8);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]");
+ gl.deleteTexture(tex3d);
+})();
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html
new file mode 100644
index 0000000000..6c2fbc4fa9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html
@@ -0,0 +1,189 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL FramebufferTextureLayer Test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var gl;
+var canvas = document.getElementById("canvas");
+
+function numLevelsFromSize(size) {
+ var levels = 0;
+ while ((size >> levels) > 0) {
+ ++levels;
+ }
+ return levels;
+}
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function test3DTextureDimensions() {
+ debug("");
+ debug("Checking 3D texture dimensions.");
+
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ var maxTexSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);
+ var maxLevels = numLevelsFromSize(maxTexSize);
+
+ gl.texImage3D(gl.TEXTURE_3D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ 1, // width
+ 1, // height
+ -1, // depth
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "texImage3D should fail for dimension out of range.");
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, maxTexSize + 1, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "texImage3D should fail for dimension out of range.");
+
+ for (var i = 0; i < maxLevels; ++i) {
+ var level = maxLevels - i - 1;
+ var badSize = 1 << (i + 1);
+
+ gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, badSize, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texImage3D should fail for dimension out of range.");
+ gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 2, badSize, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texImage3D should fail for dimension out of range.");
+ gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 2, 2, badSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texImage3D should fail for dimension out of range.");
+ }
+
+ // Probe to discover the max non-OOM level.
+ var numTestLevels = maxLevels;
+ while (true) {
+ gl.texImage3D(gl.TEXTURE_3D, numTestLevels-1, gl.RGBA, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var err = gl.getError();
+ if (err == gl.OUT_OF_MEMORY) {
+ debug("Probe failed for level=" + (numTestLevels-1) + ", reducing...");
+ numTestLevels -= 1;
+ if (!numTestLevels) {
+ testFailed("Failed to allocate any levels");
+ return;
+ }
+ continue;
+ }
+ if (err) {
+ testFailed("Should not hit non-OOM errors during max level probing.");
+ return;
+ }
+ break;
+ }
+
+ for (var i = 0; i < numTestLevels; ++i) {
+ var level = numTestLevels - i - 1;
+ var size = 1 << i;
+
+ gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, size, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed for level: " + level + " " + size + "x1x1.");
+ gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 1, size, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed for level: " + level + " 1x" + size + "x1.");
+ gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 1, 1, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed for level: " + level + " 1x1x" + size + ".");
+ }
+
+ // Clean up
+ gl.deleteTexture(tex3d);
+}
+
+function test3DTexturePixelSize() {
+ debug("");
+ debug("Checking pixel data array is big enough for request.");
+
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ var tests = [
+ {
+ internalformat: gl.RGBA,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ size: 4,
+ dataType: Uint8Array
+ },
+ {
+ internalformat: gl.R8,
+ format: gl.RED,
+ type: gl.UNSIGNED_BYTE,
+ size: 1,
+ dataType: Uint8Array
+ },
+ {
+ internalformat: gl.RGB565,
+ format: gl.RGB,
+ type: gl.UNSIGNED_SHORT_5_6_5,
+ size: 1,
+ dataType: Uint16Array
+ },
+ {
+ internalformat: gl.RGBA32I,
+ format: gl.RGBA_INTEGER,
+ type: gl.INT,
+ size: 4,
+ dataType: Int32Array
+ },
+ {
+ internalformat: gl.RGBA32F,
+ format: gl.RGBA,
+ type: gl.FLOAT,
+ size: 4,
+ dataType: Float32Array
+ },
+ ];
+
+ tests.forEach(function(test) {
+ debug("");
+ debug("Testing internalformat " + enumToString(test.internalformat)
+ + ", format " + enumToString(test.format)
+ + ", type " + enumToString(test.type));
+
+ var pixels = new test.dataType(256 * 256 * 4 * test.size);
+ gl.texImage3D(gl.TEXTURE_3D, 0, test.internalformat, 256, 256, 256, 0, test.format, test.type, pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "ArrayBufferView not big enough for request by texImage3D.");
+ gl.texImage3D(gl.TEXTURE_3D, 0, test.internalformat, 256, 256, 4, 0, test.format, test.type, pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "ArrayBufferView big enough for request by texImage3D.");
+ pixels = new test.dataType(256 * 256 * 1 * test.size);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 256, 256, 2, test.format, test.type, pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "ArrayBufferView not big enough for request by texSubImage3D.");
+ });
+
+ gl.deleteTexture(tex3d);
+}
+
+description("This tests size limits of 3D textures.");
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
+
+test3DTextureDimensions();
+test3DTexturePixelSize();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-base-level-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-base-level-bug.html
new file mode 100644
index 0000000000..47f049fd8a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-base-level-bug.html
@@ -0,0 +1,76 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 texture base level bug conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 2px; height: 2px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext("example", undefined, 2);
+var tiu = TexImageUtils;
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+function runtest() {
+ debug("");
+ debug("This is a regression test for <a href='https://crbug.com/705865'>Chromium Issue 705865</a>");
+ var tex = gl.createTexture();
+ var program = tiu.setupTexturedQuad(gl, "RGBA");
+
+ // Test that filling partial levels is enough for mipmapping.
+ var width = 2;
+ var height = 2;
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.fillTexture(gl, tex, width, height, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture setup should succeed");
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]");
+
+ width = 1;
+ height = 1;
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D should succeed");
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,"checkCanvas should succeed");
+
+ gl.deleteTexture(tex);
+
+};
+
+runtest();
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html
new file mode 100644
index 0000000000..0abd2b5a3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html
@@ -0,0 +1,197 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verifies tex{Sub}Image{2|3}D code paths taking partial ArrayBufferView');
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+
+function createSource(width, height, depth, viewType, offset) {
+ var size = width * height * depth * 4; // RGBA
+ var buf = new window[viewType](size + offset);
+ for (var ii = 0; ii < size; ++ii) {
+ if (viewType == "Float32Array")
+ buf[ii + offset] = ii / 255.0;
+ else
+ buf[ii + offset] = ii;
+ }
+ return buf;
+}
+
+function comparePixels(ref, refOffset, data, tol) {
+ for (var ii = 0; ii < data.length; ++ii) {
+ // Skip alpha due to shader's handling of alpha values.
+ if (ii % 4 == 3)
+ continue;
+ var src = ref[ii + refOffset];
+ if (ref instanceof Float32Array)
+ src *= 255;
+ if (Math.abs(src - data[ii]) > tol) {
+ testFailed("Element " + ii + ": expected " + src + ", got " + data[ii]);
+ return;
+ }
+ }
+ return testPassed("texture data uploaded correctly");
+}
+
+function run2DTest(gl, test, width, height, srcOffset, tol) {
+ debug("");
+ debug("Tesing tex{Sub}Image2D with sub source: internalformat = " + test.internalformat +
+ ", format = " + test.format + ", type = " + test.type);
+
+ var program = tiu.setupTexturedQuad(gl, test.internalformat);
+ if (!program) {
+ testFailed("Failed to set up program");
+ return;
+ }
+
+ var buf = createSource(width, height, 1, test.viewType, srcOffset);
+
+ 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);
+ 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[test.internalformat], width, height, 0,
+ gl[test.format], gl[test.type], buf, srcOffset + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[test.internalformat], width, height, 0,
+ gl[test.format], gl[test.type], buf, srcOffset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D succeeds with correct buffer and srcOffset");
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ var readBuf = new Uint8Array(width * height * 4);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+ var tol = 0.5;
+ comparePixels(buf, srcOffset, readBuf, tol);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[test.internalformat], width, height, 0,
+ gl[test.format], gl[test.type], null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl[test.format], gl[test.type],
+ buf, srcOffset + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl[test.format], gl[test.type],
+ buf, srcOffset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D succeeds with correct buffer and srcOffset");
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+ comparePixels(buf, srcOffset, readBuf, tol);
+
+ gl.deleteTexture(texture);
+ gl.deleteProgram(program);
+}
+
+function run3DTest(gl, test, width, height, srcOffset, tol) {
+ debug("");
+ debug("Tesing tex{Sub}Image3D with sub source: internalformat = " + test.internalformat +
+ ", format = " + test.format + ", type = " + test.type);
+
+ var program = tiu.setupTexturedQuadWith3D(gl, test.internalformat);
+ if (!program) {
+ testFailed("Failed to set up program");
+ return;
+ }
+
+ var depth = 1;
+ var buf = createSource(width, height, depth, test.viewType, srcOffset);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl[test.internalformat], width, height, depth, 0,
+ gl[test.format], gl[test.type], buf, srcOffset + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large");
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl[test.internalformat], width, height, depth, 0,
+ gl[test.format], gl[test.type], buf, srcOffset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D succeeds with correct buffer and srcOffset");
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ var readBuf = new Uint8Array(width * height * 4);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+ var tol = 0.5;
+ comparePixels(buf, srcOffset, readBuf, tol);
+
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl[test.internalformat], width, height, depth, 0,
+ gl[test.format], gl[test.type], null);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl[test.format], gl[test.type],
+ buf, srcOffset + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl[test.format], gl[test.type],
+ buf, srcOffset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D succeeds with correct buffer and srcOffset");
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+ comparePixels(buf, srcOffset, readBuf, tol);
+
+ gl.deleteTexture(texture);
+ gl.deleteProgram(program);
+}
+
+var gl = wtu.create3DContext("example", undefined, 2);
+if (!gl) {
+ testFailed("Fail to get a WebGL context");
+} else {
+ var testCases = [
+ { internalformat: 'RGBA8', format: 'RGBA', type: 'UNSIGNED_BYTE',
+ viewType: 'Uint8Array', },
+ { internalformat: 'RGBA8I', format: 'RGBA_INTEGER', type: 'BYTE',
+ viewType: 'Int8Array', },
+ { internalformat: 'RGBA16UI', format: 'RGBA_INTEGER', type: 'UNSIGNED_SHORT',
+ viewType: 'Uint16Array', },
+ { internalformat: 'RGBA16I', format: 'RGBA_INTEGER', type: 'SHORT',
+ viewType: 'Int16Array', },
+ { internalformat: 'RGBA32UI', format: 'RGBA_INTEGER', type: 'UNSIGNED_INT',
+ viewType: 'Uint32Array', },
+ { internalformat: 'RGBA32I', format: 'RGBA_INTEGER', type: 'INT',
+ viewType: 'Int32Array', },
+ { internalformat: 'RGBA32F', format: 'RGBA', type: 'FLOAT',
+ viewType: 'Float32Array', },
+ ];
+
+ var srcOffset = 3;
+ var tol = 0.5;
+
+ for (var idx = 0; idx < testCases.length; ++idx) {
+ run2DTest(gl, testCases[idx], gl.drawingBufferWidth, gl.drawingBufferHeight, srcOffset, tol);
+ run3DTest(gl, testCases[idx], gl.drawingBufferWidth, gl.drawingBufferHeight, srcOffset, tol);
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html
new file mode 100644
index 0000000000..f1616e81d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html
@@ -0,0 +1,128 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="c" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests texImage2D with invalid internalformat/format/type combinations from various dom elements');
+
+debug("<a href='https://www.khronos.org/registry/webgl/specs/latest/2.0/#TEXTURE_TYPES_FORMATS_FROM_DOM_ELEMENTS_TABLE'>Valid internalformat/format/type combinations</a>");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", undefined, 2);
+
+var doTexImage = function(domElement) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, domElement);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM, gl.INVALID_OPERATION], "TexImage2D taking RGB10_A2UI/RGBA_INTEGER/UNSIGNED_INT_2_10_10_10_REV should fail");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG8, gl.RG, gl.FLOAT, domElement);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "TexImage2D taking RG8/RG/FLOAT should fail");
+ gl.deleteTexture(tex);
+}
+
+var createCanvas2DContext = function(width, height) {
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ ctx.fillRect(0, 0, width, height);
+ return ctx;
+};
+
+var testImage = function(test) {
+ debug("HTMLImageElement");
+ var img = wtu.makeImage(test.src, function() {
+ doTexImage(img);
+ setTimeout(runNextTest, 0);
+ });
+}
+
+var testVideo = function(test) {
+ debug("HTMLVideoElement (" + test.videoType + ")");
+ var video = wtu.makeVideo(test.src);
+ if(!video.canPlayType(test.videoType).replace(/no/, '')) {
+ debug(test.videoType + " unsupported");
+ setTimeout(runNextTest, 0);
+ return;
+ }
+ wtu.startPlayingAndWaitForVideo(video, function() {
+ doTexImage(video);
+ setTimeout(runNextTest, 0);
+ });
+}
+
+var testCanvas = function(test) {
+ var ctx = createCanvas2DContext(test.width, test.height);
+ debug("HTMLCanvasElement");
+ doTexImage(ctx.canvas);
+ setTimeout(runNextTest, 0);
+}
+
+var testImageData = function(test) {
+ var ctx = createCanvas2DContext(test.width, test.height);
+ var imageData = ctx.getImageData(0, 0, test.width, test.height);
+ debug("ImageData");
+ doTexImage(imageData);
+ setTimeout(runNextTest, 0);
+}
+
+var testImageBitmap = function(test) {
+ debug("ImageBitmap");
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ debug("ImageBitmap isn't supported");
+ setTimeout(runNextTest, 0);
+ return;
+ }
+ var ctx = createCanvas2DContext(test.width, test.height);
+ createImageBitmap(ctx.canvas, 0, 0, test.width, test.height).then(function(imageBitmap) {
+ doTexImage(imageBitmap);
+ setTimeout(runNextTest, 0);
+ }, function() {
+ debug("createImageBitmap was rejected");
+ setTimeout(runNextTest, 0);
+ });
+}
+
+var tests = [
+ { type: "canvas", width: 64, height: 64, run: testCanvas },
+ { type: "image", src: "../../../resources/red-green.png", run: testImage },
+ { type: "ImageBitmap",width: 64, height: 64, run: testImageBitmap },
+ { type: "ImageData", width: 64, height: 64, run: testImageData },
+ { type: "video", src: "../../../resources/red-green.mp4", videoType: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', run: testVideo },
+ { type: "video", src: "../../../resources/red-green.bt601.vp9.webm", videoType: 'video/webm; codecs="vp9"', run: testVideo },
+ { type: "video", src: "../../../resources/red-green.webmvp8.webm", videoType: 'video/webm; codecs="vp8, vorbis"', run: testVideo },
+ { type: "video", src: "../../../resources/red-green.theora.ogv", videoType: 'video/ogg; codecs="theora, vorbis"', run: testVideo },
+];
+
+var testIndex = 0;
+var runNextTest = function() {
+ if (testIndex < tests.length) {
+ debug("");
+ var test = tests[testIndex];
+ ++testIndex;
+ test.run(test);
+ } else {
+ finishTest();
+ }
+};
+
+runNextTest();
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html
new file mode 100644
index 0000000000..514e5eebc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html
@@ -0,0 +1,57 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="c" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests texImage2D with invalid internalformat/format/type combinations');
+debug("This includes a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=656889'>Chromium Issue 656889</a>");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", null, 2);
+var ext = null;
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+}
+
+var doTexImage = function(test) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, test.internalformat, 64, 64, 0, test.format, test.type, null);
+ wtu.glErrorShouldBe(gl, test.errors, "TexImage2D taking " + wtu.glEnumToString(gl, test.internalformat) + "/" +
+ wtu.glEnumToString(gl, test.format) + "/" + wtu.glEnumToString(gl, test.type));
+ gl.deleteTexture(tex);
+}
+
+var tests = [
+ { internalformat: gl.RGBA, format: gl.RGBA, type: gl.UNSIGNED_BYTE, errors: [gl.NO_ERROR] },
+ { internalformat: gl.RGBA, format: gl.RGBA, type: gl.FLOAT, errors: [gl.INVALID_OPERATION] },
+ { internalformat: gl.RGBA, format: gl.RGBA, type: gl.HALF_FLOAT, errors: [gl.INVALID_OPERATION] },
+ { internalformat: gl.LUMINANCE, format: gl.LUMINANCE, type: gl.FLOAT, errors: [gl.INVALID_OPERATION] },
+ { internalformat: gl.LUMINANCE_ALPHA, format: gl.LUMINANCE_ALPHA, type: gl.HALF_FLOAT, errors: [gl.INVALID_OPERATION] },
+ { internalformat: 0x822A /*GL_R16_EXT*/ , format: gl.RED, type: gl.UNSIGNED_SHORT, errors: [gl.INVALID_VALUE, gl.INVALID_OPERATION] },
+ { internalformat: gl.RED, format: gl.RED, type: gl.UNSIGNED_SHORT, errors: [gl.INVALID_VALUE, gl.INVALID_OPERATION] },
+];
+
+tests.forEach(doTexImage);
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html
new file mode 100644
index 0000000000..0343f83786
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html
@@ -0,0 +1,51 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas1" width="16" height="16"></canvas>
+<canvas id="canvas2" width="16" height="16"></canvas>
+<canvas id="c" width="16" height="16"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Tests texImage2D with different data source');
+
+var wtu = WebGLTestUtils;
+var c = document.getElementById("c");
+var gl = wtu.create3DContext("canvas1", undefined, 2);
+var tex = gl.createTexture();
+
+// Do TexImage2D taking a canvas source first.
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE, c);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TexImage2D taking a canvas source should succeed");
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, 16, 16, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, null);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Teximage2D taking a null array buffer should succeed");
+gl.deleteTexture(tex);
+
+// Do TexImage2D taking an array buffer first.
+gl = wtu.create3DContext("canvas2", undefined, 2);
+tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, 16, 16, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, null);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Teximage2D taking a null array buffer should succeed");
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, c);
+wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM], "TexImage2D taking RGB10_A2UI internalformat and a canvas source should fail");
+gl.deleteTexture(tex);
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html
new file mode 100644
index 0000000000..ec73e9e1d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html
@@ -0,0 +1,24 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 2;
+</script>
+<script src="../../../js/tests/tex-input-validation.js"></script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html
new file mode 100644
index 0000000000..adf3d20d17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html
@@ -0,0 +1,225 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 texture mipmap level conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 2px; height: 2px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+uniform vec4 uMult;
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition * uMult;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+
+<script id="vshader_texsize" type="x-shader/x-vertex">#version 300 es
+in vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader_texsize_2d" type="x-shader/x-fragment">#version 300 es
+
+precision mediump float;
+uniform sampler2D tex;
+uniform int lod;
+uniform ivec2 texSize;
+out vec4 fragColor;
+void main()
+{
+ fragColor = (textureSize(tex, lod) == texSize ? vec4(255, 0, 0, 255) : vec4(0, 0, 0, 255));
+}
+</script>
+
+
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+(function() {
+ debug("");
+ debug("test mipmap level ranges");
+ var tex = gl.createTexture();
+ wtu.setupUnitQuad(gl, 0, 1);
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+ gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+
+ var multLoc = gl.getUniformLocation(program, "uMult");
+ gl.uniform4f(multLoc, 1, 1, 1, 1);
+
+ // Test that filling partial levels is enough for mipmapping.
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.fillTexture(gl, tex, 8, 8, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(8x8, level=2) should succeed");
+ wtu.fillTexture(gl, tex, 4, 4, [0, 255, 0, 255], 3, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(4x4, level=3) should succeed");
+ wtu.fillTexture(gl, tex, 2, 2, [0, 0, 255, 255], 4, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(2x2, level=4) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAX_LEVEL) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAG_FILTER) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed");
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "filling partial levels: should draw with [0, 0, 255, 255]");
+
+ // Test that generateMipmap works with partial levels.
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "generateMipmap with partial levels: should draw with [255, 0, 0, 255]");
+ gl.deleteTexture(tex);
+
+ // Test incompleteless for partial levels.
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.fillTexture(gl, tex, 8, 8, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(8x8, level=2) should succeed");
+ wtu.fillTexture(gl, tex, 4, 4, [255, 0, 0, 255], 3, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(4x4, level=3) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAX_LEVEL) should succeed");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed");
+ wtu.checkCanvas(gl, [0, 0, 0, 255], "incomplete texture should draw with [0, 0, 0, 255]");
+ gl.deleteTexture(tex);
+
+ // Test base level texture isn't specified.
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.fillTexture(gl, tex, 8, 8, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(8x8, level=2) should succeed");
+ wtu.fillTexture(gl, tex, 4, 4, [255, 0, 0, 255], 3, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(4x4, level=3) should succeed");
+ wtu.fillTexture(gl, tex, 2, 2, [0, 0, 255, 255], 4, gl.RGBA, gl.UNSIGNED_BYTE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(2x2, level=4) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed");
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail if base level texture is not specified");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed");
+ gl.deleteTexture(tex);
+
+ // Test 3D texture.
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texImage3D( gl.TEXTURE_3D, 0, gl.RGBA, 8, 8, 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 8 * 4));
+ gl.generateMipmap(gl.TEXTURE_3D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed");
+ gl.texSubImage3D(gl.TEXTURE_3D, 1, 0, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4 * 4 * 4 * 4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed");
+ gl.deleteTexture(tex3d);
+
+ // Test 2D array texture.
+ var tex2dArray = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex2dArray);
+ gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 8, 8, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 4 * 4));
+ gl.generateMipmap(gl.TEXTURE_2D_ARRAY);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed");
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4 * 4 * 4 * 4));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed");
+ gl.deleteTexture(tex2dArray);
+
+ // Test sized internal format should be both color-renderable and texture-filterable
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail for zero-size texture");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 8, 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 4));
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8UI, 8, 8, 0, gl.RGBA_INTEGER, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 4));
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail for non-texture-filterable format");
+ if (gl.getExtension('EXT_color_buffer_float')) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 8, 8, 0, gl.RGBA, gl.FLOAT, new Float32Array(8 * 8 * 4));
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail for float texture");
+ }
+ if (gl.getExtension('EXT_color_buffer_float') && gl.getExtension('OES_texture_float_linear')) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 0, 0, 0, gl.RGBA, gl.FLOAT, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail for zero-size texture");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 8, 8, 0, gl.RGBA, gl.FLOAT, new Float32Array(8 * 8 * 4));
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed");
+ }
+ gl.deleteTexture(tex);
+
+ // Test textureSize should work correctly with non-zero base level for texStorage2D
+ var program = wtu.setupProgram(
+ gl, ['vshader_texsize', 'fshader_texsize_2d'], ['vPosition'], [0]);
+
+ gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+ gl.uniform1i(gl.getUniformLocation(program, "lod"), 1);
+ gl.uniform2i(gl.getUniformLocation(program, "texSize"), 7, 4);
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAG_FILTER) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed");
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed");
+ gl.texStorage2D(gl.TEXTURE_2D, 4, gl.RGBA8, 31, 17);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage2D should succeed");
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "non-zero base level texStorage2D: should draw with [255, 0, 0, 255]");
+ gl.deleteTexture(tex);
+
+})();
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html
new file mode 100644
index 0000000000..df10edb4d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html
@@ -0,0 +1,565 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Conformance test for WebGL2 texture image formats specification</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+
+
+<script>
+"use strict";
+description("This test verifies that texture image specification entry points " +
+ "accept new formats introduced in WebGL2, and accept sized internalformats.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var vao = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runTexFormatsTest();
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function runTexFormatsTest()
+{
+ // texFormats is Table 3.2 and Table 3.3 from the OpenGL ES 3.0.4 spec.
+ var texFormats = [
+ {
+ sizedformat: "RGBA8",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGB5_A1",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGBA4",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "SRGB8_ALPHA8",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGBA8_SNORM",
+ unsizedformat: "RGBA",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "RGBA4",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_SHORT_4_4_4_4",
+ },
+ {
+ sizedformat: "RGB5_A1",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_SHORT_5_5_5_1",
+ },
+ {
+ sizedformat: "RGB10_A2",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_INT_2_10_10_10_REV",
+ },
+ {
+ sizedformat: "RGB5_A1",
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_INT_2_10_10_10_REV",
+ },
+ {
+ sizedformat: "RGBA16F",
+ unsizedformat: "RGBA",
+ type: "HALF_FLOAT",
+ },
+ {
+ sizedformat: "RGBA32F",
+ unsizedformat: "RGBA",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RGBA16F",
+ unsizedformat: "RGBA",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RGBA8UI",
+ unsizedformat: "RGBA_INTEGER",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGBA8I",
+ unsizedformat: "RGBA_INTEGER",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "RGBA16UI",
+ unsizedformat: "RGBA_INTEGER",
+ type: "UNSIGNED_SHORT",
+ },
+ {
+ sizedformat: "RGBA16I",
+ unsizedformat: "RGBA_INTEGER",
+ type: "SHORT",
+ },
+ {
+ sizedformat: "RGBA32UI",
+ unsizedformat: "RGBA_INTEGER",
+ type: "UNSIGNED_INT",
+ },
+ {
+ sizedformat: "RGBA32I",
+ unsizedformat: "RGBA_INTEGER",
+ type: "INT",
+ },
+ {
+ sizedformat: "RGB10_A2UI",
+ unsizedformat: "RGBA_INTEGER",
+ type: "UNSIGNED_INT_2_10_10_10_REV",
+ },
+ {
+ sizedformat: "RGB8",
+ unsizedformat: "RGB",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGB565",
+ unsizedformat: "RGB",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "SRGB8",
+ unsizedformat: "RGB",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGB8_SNORM",
+ unsizedformat: "RGB",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "RGB565",
+ unsizedformat: "RGB",
+ type: "UNSIGNED_SHORT_5_6_5",
+ },
+ {
+ sizedformat: "R11F_G11F_B10F",
+ unsizedformat: "RGB",
+ type: "UNSIGNED_INT_10F_11F_11F_REV",
+ },
+ {
+ sizedformat: "RGB9_E5",
+ unsizedformat: "RGB",
+ type: "UNSIGNED_INT_5_9_9_9_REV",
+ },
+ {
+ sizedformat: "RGB16F",
+ unsizedformat: "RGB",
+ type: "HALF_FLOAT",
+ },
+ {
+ sizedformat: "R11F_G11F_B10F",
+ unsizedformat: "RGB",
+ type: "HALF_FLOAT",
+ },
+ {
+ sizedformat: "RGB9_E5",
+ unsizedformat: "RGB",
+ type: "HALF_FLOAT",
+ },
+ {
+ sizedformat: "RGB32F",
+ unsizedformat: "RGB",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RGB16F",
+ unsizedformat: "RGB",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "R11F_G11F_B10F",
+ unsizedformat: "RGB",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RGB9_E5",
+ unsizedformat: "RGB",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RGB8UI",
+ unsizedformat: "RGB_INTEGER",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RGB8I",
+ unsizedformat: "RGB_INTEGER",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "RGB16UI",
+ unsizedformat: "RGB_INTEGER",
+ type: "UNSIGNED_SHORT",
+ },
+ {
+ sizedformat: "RGB16I",
+ unsizedformat: "RGB_INTEGER",
+ type: "SHORT",
+ },
+ {
+ sizedformat: "RGB32UI",
+ unsizedformat: "RGB_INTEGER",
+ type: "UNSIGNED_INT",
+ },
+ {
+ sizedformat: "RGB32I",
+ unsizedformat: "RGB_INTEGER",
+ type: "INT",
+ },
+ {
+ sizedformat: "RG8",
+ unsizedformat: "RG",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RG8_SNORM",
+ unsizedformat: "RG",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "RG16F",
+ unsizedformat: "RG",
+ type: "HALF_FLOAT",
+ },
+ {
+ sizedformat: "RG32F",
+ unsizedformat: "RG",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RG16F",
+ unsizedformat: "RG",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "RG8UI",
+ unsizedformat: "RG_INTEGER",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "RG8I",
+ unsizedformat: "RG_INTEGER",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "RG16UI",
+ unsizedformat: "RG_INTEGER",
+ type: "UNSIGNED_SHORT",
+ },
+ {
+ sizedformat: "RG16I",
+ unsizedformat: "RG_INTEGER",
+ type: "SHORT",
+ },
+ {
+ sizedformat: "RG32UI",
+ unsizedformat: "RG_INTEGER",
+ type: "UNSIGNED_INT",
+ },
+ {
+ sizedformat: "RG32I",
+ unsizedformat: "RG_INTEGER",
+ type: "INT",
+ },
+ {
+ sizedformat: "R8",
+ unsizedformat: "RED",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "R8_SNORM",
+ unsizedformat: "RED",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "R16F",
+ unsizedformat: "RED",
+ type: "HALF_FLOAT",
+ },
+ {
+ sizedformat: "R32F",
+ unsizedformat: "RED",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "R16F",
+ unsizedformat: "RED",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "R8UI",
+ unsizedformat: "RED_INTEGER",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: "R8I",
+ unsizedformat: "RED_INTEGER",
+ type: "BYTE",
+ },
+ {
+ sizedformat: "R16UI",
+ unsizedformat: "RED_INTEGER",
+ type: "UNSIGNED_SHORT",
+ },
+ {
+ sizedformat: "R16I",
+ unsizedformat: "RED_INTEGER",
+ type: "SHORT",
+ },
+ {
+ sizedformat: "R32UI",
+ unsizedformat: "RED_INTEGER",
+ type: "UNSIGNED_INT",
+ },
+ {
+ sizedformat: "R32I",
+ unsizedformat: "RED_INTEGER",
+ type: "INT",
+ },
+ {
+ sizedformat: "DEPTH_COMPONENT16",
+ unsizedformat: "DEPTH_COMPONENT",
+ type: "UNSIGNED_SHORT",
+ },
+ {
+ sizedformat: "DEPTH_COMPONENT24",
+ unsizedformat: "DEPTH_COMPONENT",
+ type: "UNSIGNED_INT",
+ },
+ {
+ sizedformat: "DEPTH_COMPONENT16",
+ unsizedformat: "DEPTH_COMPONENT",
+ type: "UNSIGNED_INT",
+ },
+ {
+ sizedformat: "DEPTH_COMPONENT32F",
+ unsizedformat: "DEPTH_COMPONENT",
+ type: "FLOAT",
+ },
+ {
+ sizedformat: "DEPTH24_STENCIL8",
+ unsizedformat: "DEPTH_STENCIL",
+ type: "UNSIGNED_INT_24_8",
+ },
+ // No good typed array type for this format, just allow this format when pixel is null.
+ {
+ sizedformat: "DEPTH32F_STENCIL8",
+ unsizedformat: "DEPTH_STENCIL",
+ type: "FLOAT_32_UNSIGNED_INT_24_8_REV",
+ },
+ // internalFormat of texImage2D may be unsized format according Table 3.3 in OpenGL ES 3.0.4 spec.
+ {
+ sizedformat: undefined,
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_SHORT_4_4_4_4",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "RGBA",
+ type: "UNSIGNED_SHORT_5_5_5_1",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "RGB",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "RGB",
+ type: "UNSIGNED_SHORT_5_6_5",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "LUMINANCE_ALPHA",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "LUMINANCE",
+ type: "UNSIGNED_BYTE",
+ },
+ {
+ sizedformat: undefined,
+ unsizedformat: "ALPHA",
+ type: "UNSIGNED_BYTE",
+ },
+ ];
+
+ texFormats.forEach(function(texformat){
+ debug("");
+ debug("Testing sized format " + texformat.sizedformat
+ + ", unsized format " + texformat.unsizedformat
+ + ", type " + texformat.type);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ var sizedformat = gl[texformat.sizedformat];
+ var unsizedformat = gl[texformat.unsizedformat];
+ var type = gl[texformat.type];
+
+ // prepare some good data to feed texImage2D and friends for this type
+ var data;
+ switch(type) {
+ case gl.UNSIGNED_BYTE:
+ data = new Uint8Array(4);
+ break;
+ case gl.BYTE:
+ data = new Int8Array(4);
+ break;
+ case gl.UNSIGNED_SHORT:
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ case gl.UNSIGNED_SHORT_5_6_5:
+ case gl.HALF_FLOAT:
+ data = new Uint16Array(4);
+ break;
+ case gl.SHORT:
+ data = new Int16Array(4);
+ break;
+ case gl.UNSIGNED_INT:
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ case gl.UNSIGNED_INT_24_8:
+ data = new Uint32Array(4);
+ break;
+ case gl.INT:
+ data = new Int32Array(4);
+ break;
+ case gl.FLOAT:
+ data = new Float32Array(4);
+ break;
+ case gl.FLOAT_32_UNSIGNED_INT_24_8_REV:
+ data = null;
+ }
+
+ // prepare some bad data that doesn't fit this type
+ var baddata = (data instanceof Float32Array)
+ ? new Uint8Array(4)
+ : new Float32Array(4);
+
+ // test texImage2D with unsized internalformat
+ if (!sizedformat) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, unsizedformat, 1, 1, 0, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D should succeed with unsized internalformat");
+ gl.texImage2D(gl.TEXTURE_2D, 0, unsizedformat, 1, 1, 0, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D should fail with unsized internalformat and data of wrong type");
+ } else {
+ // test texImage2D with sized internalformat
+ gl.texImage2D(gl.TEXTURE_2D, 0, sizedformat, 1, 1, 0, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D should succeed with sized internalformat");
+ gl.texImage2D(gl.TEXTURE_2D, 0, sizedformat, 1, 1, 0, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D should fail with sized internalformat and data of wrong type");
+ }
+
+ // test texSubImage2D
+ if (gl.FLOAT_32_UNSIGNED_INT_24_8_REV != type) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage2D should fail with data of wrong type");
+ }
+
+ // test texStorage2D
+ if (sizedformat) {
+ gl.texStorage2D(gl.TEXTURE_2D, 1, sizedformat, 1, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage2D should succeed");
+ if (gl.FLOAT_32_UNSIGNED_INT_24_8_REV != type) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed on immutable-format texture");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage2D should fail on immutable-format texture with data of wrong type");
+ }
+ }
+
+ // Test a 3D texture.
+ // Formats containing a depth component can't be used for 3D textures.
+ var isdepthformat =
+ unsizedformat == gl.DEPTH_COMPONENT ||
+ unsizedformat == gl.DEPTH_STENCIL;
+ if (!isdepthformat) {
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+
+ // test texImage3D with unsized internalformat
+ if (!sizedformat) {
+ gl.texImage3D(gl.TEXTURE_3D, 0, unsizedformat, 1, 1, 1, 0, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed with unsized internalformat");
+ gl.texImage3D(gl.TEXTURE_3D, 0, unsizedformat, 1, 1, 1, 0, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D should fail with unsized internalformat and data of wrong type");
+ } else {
+ // test texImage3D with sized internalformat
+ gl.texImage3D(gl.TEXTURE_3D, 0, sizedformat, 1, 1, 1, 0, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed with sized internalformat");
+ gl.texImage3D(gl.TEXTURE_3D, 0, sizedformat, 1, 1, 1, 0, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D should fail with sized internalformat and data of wrong type");
+ }
+
+ // test texSubImage3D
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D should fail with data of wrong type");
+
+ if (sizedformat) {
+ gl.texStorage3D(gl.TEXTURE_3D, 1, sizedformat, 1, 1, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed on immutable-format texture");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, baddata);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D should fail on immutable-format texture with data of wrong type");
+ }
+ }
+ });
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-srgb-mipmap.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-srgb-mipmap.html
new file mode 100644
index 0000000000..9764987d8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-srgb-mipmap.html
@@ -0,0 +1,220 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texture mipmap conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 16px; height: 16px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas, undefined, 2);
+
+description("Test srgb emulation for generateMipmap.");
+function generateMipmap()
+{
+ debug("Generate mipmaps for sRGB texture");
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ var colors = {
+ blank: [0, 0, 0, 0],
+ srgba: [0, 63, 127, 255],
+ };
+
+ var texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+
+ var width = 128;
+ var height = 128;
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ var srgbTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, srgbTex);
+ // Set full texture as srgba color first.
+ wtu.fillTexture(gl, srgbTex, width, height, colors['srgba'], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8);
+ // Set up-left region of the texture as red color.
+ // In order to make sure bi-linear interpolation operates on different colors, red region
+ // is 1 pixel smaller than a quarter of the full texture on each side.
+ var redWidth = width / 2 - 1;
+ var redHeight = height / 2 - 1;
+ var buf = new Uint8Array(redWidth * redHeight * 4);
+ for (var i = 0; i < redWidth * redHeight; i++) {
+ buf[4 * i + 0] = 255;
+ buf[4 * i + 1] = 0;
+ buf[4 * i + 2] = 0;
+ buf[4 * i + 3] = 255;
+ }
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+
+ // Decode the srgba texture to a linear texture which will be used as reference.
+ var linearTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, linearTex);
+ wtu.fillTexture(gl, linearTex, width, height, wtu.sRGBToLinear(colors['srgba']), 0, gl.RGBA, gl.UNSIGNED_BYTE);
+ // Set up-left region of the texture as red color.
+ // In order to make sure bi-linear interpolation operates on different colors, red region
+ // is 1 pixel smaller than a quarter of the full texture on each side.
+ for (var i = 0; i < redWidth * redHeight; i++) {
+ buf[4 * i + 0] = 255;
+ buf[4 * i + 1] = 0;
+ buf[4 * i + 2] = 0;
+ buf[4 * i + 3] = 255;
+ }
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+
+ // Change canvas to a small size.
+ width = 64;
+ height = 64;
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ // Draw with srgb texture and linear texture respectively.
+ gl.bindTexture(gl.TEXTURE_2D, srgbTex);
+ wtu.clearAndDrawUnitQuad(gl);
+ var result = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, result);
+ gl.bindTexture(gl.TEXTURE_2D, linearTex);
+ wtu.clearAndDrawUnitQuad(gl);
+ var reference = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, reference);
+
+ gl.deleteTexture(srgbTex);
+ gl.deleteTexture(linearTex);
+
+ var tolerance = 7;
+ var diff = new Uint8Array(width * height * 4);
+ var failed = wtu.comparePixels(result, reference, tolerance, diff);
+ if (failed) {
+ testFailed("Generate wrong mipmaps for sRGB texture.");
+ wtu.displayImageDiff(result, reference, diff, width, height);
+ } else {
+ testPassed("Generate correct mipmaps for sRGB texture.");
+ }
+}
+
+function generateMipmap_immutableTexture()
+{
+ debug("Generate mipmaps for immutable texture.");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, Math.log2(canvas.width), gl.SRGB8_ALPHA8, canvas.width, canvas.height);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "GenerateMipmap should succeed.");
+
+ gl.deleteTexture(tex);
+}
+
+function generateMipmap_widthHeightNotEqual()
+{
+ debug("Generate mipmaps when width and height are not equal.");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, 64, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "GenerateMipmap should succeed.");
+
+ gl.deleteTexture(tex);
+}
+
+function generateMipmap_maxLevelLessThanFullMipmapLevel()
+{
+ debug("Generate mipmaps when maxLevel is less than full mipmap level.");
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
+
+ var colors = [0, 63, 127, 255];
+
+ var texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+
+ var width = 16;
+ var height = 16;
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ var srgbTex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, srgbTex);
+ wtu.fillTexture(gl, srgbTex, width, height, colors, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8);
+
+ // Set max level, check if the max level mipmap is generated.
+ var max_level = 3;
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, max_level);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+
+ width >>= max_level;
+ height >>= max_level;
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ gl.bindTexture(gl.TEXTURE_2D, srgbTex);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ var reference = wtu.sRGBToLinear(colors);
+ var msg;
+ wtu.checkCanvasRect(gl, 0, 0, width, height, reference, msg, [1,1,1,1]);
+
+ gl.deleteTexture(srgbTex);
+}
+
+generateMipmap();
+generateMipmap_immutableTexture();
+generateMipmap_widthHeightNotEqual();
+generateMipmap_maxLevelLessThanFullMipmapLevel();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html
new file mode 100644
index 0000000000..34bff4d3a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html
@@ -0,0 +1,290 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>texStorage2D conformance test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+
+
+<script>
+"use strict";
+description("This test verifies the functionality of texStorage2D.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var vao = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runTexStorage2DTest();
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function runTexStorage2DTest()
+{
+ var texStorage2DTestCases = [
+ {
+ target: gl.TEXTURE_2D,
+ mipmap: false,
+ sizedformat: gl.RGBA8,
+ unsizedformat: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ alpha: true,
+ redpixel: new Uint8Array([0xff, 0x00, 0x00, 0x00]),
+ },
+ {
+ target: gl.TEXTURE_2D,
+ mipmap: true,
+ sizedformat: gl.R11F_G11F_B10F,
+ unsizedformat: gl.RGB,
+ type: gl.UNSIGNED_INT_10F_11F_11F_REV,
+ alpha: false,
+ // Red is unsigned floating point with 5 exponent bits followed by 6 mantissa bits.
+ // The effective value is 2^(exponent - 15) * (1 + mantissa / 64)
+ // See OpenGL ES 3.0.3 spec, section 2.1.3
+ // Here we want to encode the value 1.0, which we achieve with a zero mantissa
+ // and an exponent of 15.
+ redpixel: new Uint32Array([15<<6]),
+ },
+ {
+ target: gl.TEXTURE_2D,
+ mipmap: true,
+ sizedformat: gl.RGBA32F,
+ unsizedformat: gl.RGBA,
+ type: gl.FLOAT,
+ alpha: true,
+ redpixel: new Float32Array([1, 0, 0, 0]),
+ },
+ {
+ target: gl.TEXTURE_CUBE_MAP,
+ mipmap: true,
+ sizedformat: gl.RGBA8,
+ unsizedformat: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ alpha: true,
+ redpixel: new Uint8Array([0xff, 0x00, 0x00, 0x00]),
+ },
+ {
+ target: gl.TEXTURE_CUBE_MAP,
+ mipmap: false,
+ sizedformat: gl.RGB8,
+ unsizedformat: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ alpha: false,
+ redpixel: new Uint8Array([0xff, 0x00, 0x00]),
+ },
+ {
+ target: gl.TEXTURE_CUBE_MAP,
+ mipmap: true,
+ sizedformat: gl.RGB10_A2UI,
+ unsizedformat: gl.UNSIGNED_INT_2_10_10_10_REV, // type enum, bad as format
+ },
+ {
+ target: gl.TEXTURE_CUBE_MAP,
+ mipmap: false,
+ sizedformat: gl.R11F_G11F_B10F,
+ unsizedformat: gl.RGB,
+ }
+ ];
+
+ texStorage2DTestCases.forEach(function(testcase){
+ var target = testcase.target;
+ var imageTargets;
+
+ if (target == gl.TEXTURE_2D) {
+ imageTargets = [ gl.TEXTURE_2D ];
+ } else {
+ imageTargets = [ 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 ];
+ }
+
+ var tex = gl.createTexture();
+ gl.bindTexture(target, tex);
+ var texsize = 4;
+ var levels = testcase.mipmap
+ ? Math.floor(Math.log(texsize) / Math.log(2)) + 1
+ : 1;
+
+ debug("");
+ debug("Testing texStorage2D with target " + enumToString(target) + ", " +
+ (testcase.mipmap ? "mipmap" : "no mipmap") + ", " +
+ "internalformat: " + enumToString(testcase.sizedformat));
+
+ gl.texStorage2D(target, levels, testcase.sizedformat,
+ 0, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for zero width");
+ gl.texStorage2D(target, levels, testcase.sizedformat,
+ texsize, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for zero height");
+ gl.texStorage2D(target, levels, testcase.sizedformat,
+ texsize, -texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for negative height");
+ gl.texStorage2D(target, 0, testcase.sizedformat,
+ texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for zero levels");
+ gl.texStorage2D(target,
+ Math.ceil(Math.log(texsize) / Math.log(2)) + 2,
+ testcase.sizedformat,
+ texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage2D should fail for too many levels");
+ gl.texStorage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, levels, testcase.sizedformat,
+ texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage2D should fail for bad target TEXTURE_CUBE_MAP_NEGATIVE_X");
+
+ gl.bindTexture(target, null);
+ gl.texStorage2D(target, levels, testcase.sizedformat,
+ texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage2D should fail when no texture is bound");
+ gl.bindTexture(target, tex);
+
+ // texStorage2D should only accept sized internalformats
+ gl.texStorage2D(target, levels, testcase.unsizedformat,
+ texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage2D should fail for bad internalformat " + enumToString(testcase.unsizedformat));
+
+ // OK, now let's finally do the successfull texStorage2D call
+ gl.texStorage2D(target, levels, testcase.sizedformat,
+ texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage2D should succeed with a good sized internalformat");
+
+ // check TEXTURE_IMMUTABLE_FORMAT
+ var immutable = gl.getTexParameter(target, gl.TEXTURE_IMMUTABLE_FORMAT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getTexParameter should succeed with TEXTURE_IMMUTABLE_FORMAT");
+ assertMsg(immutable != 0, "getTexParameter with TEXTURE_IMMUTABLE_FORMAT should not return 0");
+
+ // check operations disallowed on immutable texture
+ gl.texImage2D(imageTargets[0], 0, gl.RGBA, texsize, texsize, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D should fail on immutable texture");
+ var s3tc = gl.getExtension("WEBGL_compressed_texture_s3tc");
+ // FIXME - should eventually use a compressed format that's core in WebGL2, but
+ // I wanted something that I can run in Firefox today, which doesn't support the new formats yet.
+ if (s3tc) {
+ gl.compressedTexImage2D(imageTargets[0], 0, s3tc.COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ texsize, texsize, 0,
+ new Uint8Array(texsize * texsize));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexImage2D should fail on immutable texture");
+ }
+ gl.copyTexImage2D(imageTargets[0], 0, gl.RGBA, 0, 0, texsize, texsize, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "copyTexImage2D should fail on immutable texture");
+
+ if ('redpixel' in testcase) {
+ // At this point, the texture images have only been defined by
+ // texStorage2D, which per spec should be equivalent to having
+ // defined texture images with null data, which should sample as RGBA 0,0,0,0.
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER,
+ testcase.mipmap ? gl.NEAREST_MIPMAP_NEAREST : gl.NEAREST);
+ if (testcase.type == gl.FLOAT) {
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ }
+
+ // Now upload some red texture data
+ var s = texsize;
+ var pixels;
+ if (testcase.redpixel instanceof Uint8Array) {
+ pixels = new Uint8Array(texsize * texsize * testcase.redpixel.length);
+ } else if (testcase.redpixel instanceof Uint16Array) {
+ pixels = new Uint16Array(texsize * texsize * testcase.redpixel.length);
+ } else if (testcase.redpixel instanceof Uint32Array) {
+ pixels = new Uint32Array(texsize * texsize * testcase.redpixel.length);
+ } else if (testcase.redpixel instanceof Float32Array) {
+ pixels = new Float32Array(texsize * texsize * testcase.redpixel.length);
+ }
+ for (var i = 0; i < texsize * texsize; i++) {
+ for (var j = 0; j < testcase.redpixel.length; j++) {
+ pixels[i * testcase.redpixel.length + j] = testcase.redpixel[j];
+ }
+ }
+
+ if (target == gl.TEXTURE_2D) {
+ wtu.setupTexturedQuad(gl);
+ } else if (target == gl.TEXTURE_CUBE_MAP) {
+ wtu.setupTexturedQuadWithCubeMap(gl);
+ }
+
+ wtu.clearAndDrawUnitQuad(gl);
+ var alpha = testcase.alpha ? 0 : 255;
+ wtu.checkCanvas(gl, [0, 0, 0, alpha], "texture should sample as uninitialized texture after texStorage2D");
+
+ if (target == gl.TEXTURE_2D) {
+ for (var l = 0; l < levels; l++) {
+ gl.texSubImage2D(gl.TEXTURE_2D,
+ l, 0, 0,
+ s, s,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed on immutable texture as long as the format is compatible");
+ s /= 2;
+ }
+ } else if (target == gl.TEXTURE_CUBE_MAP) {
+ for (var l = 0; l < levels; l++) {
+ for (var f = 0; f < 6; f++) {
+ gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + f,
+ l, 0, 0,
+ s, s,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed on immutable texture as long as the format is compatible");
+ }
+ s /= 2;
+ }
+ }
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, alpha], "texture should sample as red after uploading red pixels with texSubImage2D");
+ }
+ });
+
+ debug("");
+ debug("Test non-square images:");
+ const levels = 4;
+ const maxSize = 1 << (levels-1);
+
+ function expectOk(x,y) {
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, levels, gl.RGBA8, x, y);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "texStorage2D should succeed with size [" + ([x,y].join(', ')) + "].");
+ gl.deleteTexture(tex);
+ }
+ expectOk(maxSize, maxSize);
+ expectOk(maxSize, 1);
+ expectOk( 1, maxSize);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-and-subimage-3d.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-and-subimage-3d.html
new file mode 100644
index 0000000000..c81fcffb4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-and-subimage-3d.html
@@ -0,0 +1,242 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>texStorage3D and texSubImage3D conformance test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+
+
+<script>
+"use strict";
+description("This test verifies the functionality of texStorage3D and texSubImage3D.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var vao = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runTexStorageAndSubImage3DTest();
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function runTexStorageAndSubImage3DTest()
+{
+ var texStorage3DTestCases = [
+ {
+ target: gl.TEXTURE_3D,
+ mipmap: false,
+ sizedformat: gl.RGBA8,
+ unsizedformat: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ alpha: true,
+ redpixel: new Uint8Array([0xff, 0x00, 0x00, 0x00]),
+ },
+ {
+ target: gl.TEXTURE_3D,
+ mipmap: true,
+ sizedformat: gl.R11F_G11F_B10F,
+ unsizedformat: gl.RGB,
+ type: gl.UNSIGNED_INT_10F_11F_11F_REV,
+ alpha: false,
+ // Red is unsigned floating point with 5 exponent bits followed by 6 mantissa bits.
+ // The effective value is 2^(exponent - 15) * (1 + mantissa / 64)
+ // See OpenGL ES 3.0.3 spec, section 2.1.3
+ // Here we want to encode the value 1.0, which we achieve with a zero mantissa
+ // and an exponent of 15.
+ redpixel: new Uint32Array([15<<6]),
+ },
+ {
+ target: gl.TEXTURE_3D,
+ mipmap: true,
+ sizedformat: gl.RGBA32F,
+ unsizedformat: gl.RGBA,
+ type: gl.FLOAT,
+ alpha: true,
+ redpixel: new Float32Array([1, 0, 0, 0]),
+ },
+ ];
+
+ texStorage3DTestCases.forEach(function(testcase){
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex);
+ var texsize = 4;
+ var levels = testcase.mipmap
+ ? Math.floor(Math.log(texsize) / Math.log(2)) + 1
+ : 1;
+
+ debug("");
+ debug("Testing texStorage3D with " +
+ (testcase.mipmap ? "mipmap" : "no mipmap") + ", " +
+ "internalformat: " + enumToString(testcase.sizedformat));
+
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ 0, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero width");
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ texsize, 0, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero height");
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ texsize, texsize, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero depth");
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ texsize, -texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for negative height");
+ gl.texStorage3D(gl.TEXTURE_3D, 0, testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero levels");
+ if (testcase.mipmap) {
+ gl.texStorage3D(gl.TEXTURE_3D,
+ levels + 1,
+ testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage3D should fail for too many levels");
+ }
+ gl.texStorage3D(gl.TEXTURE_2D,
+ levels,
+ testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage3D should fail for target TEXTURE_2D");
+ gl.texStorage3D(gl.TEXTURE_CUBE_MAP,
+ levels,
+ testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage3D should fail for target TEXTURE_CUBE_MAP");
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage3D should fail when no texture is bound");
+ gl.bindTexture(gl.TEXTURE_3D, tex);
+
+ // texStorage3D should only accept sized internalformats
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.unsizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage3D should fail for bad internalformat " + enumToString(testcase.unsizedformat));
+
+ var pixels;
+ var number_of_pixels = texsize * texsize * texsize;
+ if (testcase.redpixel instanceof Uint8Array) {
+ pixels = new Uint8Array(number_of_pixels * testcase.redpixel.length);
+ } else if (testcase.redpixel instanceof Uint16Array) {
+ pixels = new Uint16Array(number_of_pixels * testcase.redpixel.length);
+ } else if (testcase.redpixel instanceof Uint32Array) {
+ pixels = new Uint32Array(number_of_pixels * testcase.redpixel.length);
+ } else if (testcase.redpixel instanceof Float32Array) {
+ pixels = new Float32Array(number_of_pixels * testcase.redpixel.length);
+ }
+ for (var i = 0; i < number_of_pixels; i++) {
+ for (var j = 0; j < testcase.redpixel.length; j++) {
+ pixels[i * testcase.redpixel.length + j] = testcase.redpixel[j];
+ }
+ }
+
+ gl.texSubImage3D(gl.TEXTURE_2D,
+ 0, 0, 0, 0,
+ texsize, texsize, texsize,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
+ "texSubImage3D should generate INVALID_ENUM if passed TEXTURE_2D target");
+ gl.texSubImage3D(gl.TEXTURE_3D,
+ 0, 0, 0, 0,
+ texsize, texsize, texsize,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "texSubImage3D should fail if texStorage3D has not succeeded");
+
+ // OK, now let's finally do the successfull texStorage3D call
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed with a good sized internalformat");
+
+ // Subsequent texStorage3D calls should fail, even identical ones.
+ gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat,
+ texsize, texsize, texsize);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage3D should fail on immutable-format texture");
+
+ var s = texsize;
+ for (var l = 0; l < levels; l++) {
+ gl.texSubImage3D(gl.TEXTURE_3D,
+ l, 0, 0, 0,
+ s, s, s,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ s /= 2;
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed on immutable texture as long as the format is compatible");
+ }
+ gl.texSubImage3D(gl.TEXTURE_3D,
+ levels, 0, 0, 0,
+ texsize, texsize, texsize,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D should fail for too-high level");
+ gl.texSubImage3D(gl.TEXTURE_3D,
+ 0, 1, 0, 0,
+ texsize, texsize, texsize,
+ testcase.unsizedformat, testcase.type,
+ pixels);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texSubImage3D should fail for dimension out of range");
+ });
+
+ debug("");
+ debug("Test non-square images:");
+ const levels = 4;
+ const maxSize = 1 << (levels-1);
+
+ function expectOk(target, x,y,z, err) {
+ debug("(target=" + target + ", size=[" + ([x,y,z].join(', ')) + "])");
+ const tex = gl.createTexture();
+ gl.bindTexture(gl[target], tex);
+ gl.texStorage3D(gl[target], levels+1, gl.RGBA8, x, y, z);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "levels=levels+1");
+
+ gl.texStorage3D(gl[target], levels, gl.RGBA8, x, y, z);
+ wtu.glErrorShouldBe(gl, gl[err], "levels=levels");
+ gl.deleteTexture(tex);
+ }
+ expectOk("TEXTURE_3D", maxSize, maxSize, maxSize, "NO_ERROR");
+ expectOk("TEXTURE_3D", maxSize, maxSize, 1, "NO_ERROR");
+ expectOk("TEXTURE_3D", maxSize, 1, maxSize, "NO_ERROR");
+ expectOk("TEXTURE_3D", maxSize, 1, 1, "NO_ERROR");
+ expectOk("TEXTURE_3D", 1, maxSize, maxSize, "NO_ERROR");
+ expectOk("TEXTURE_3D", 1, maxSize, 1, "NO_ERROR");
+ expectOk("TEXTURE_3D", 1, 1, maxSize, "NO_ERROR");
+
+ expectOk("TEXTURE_2D_ARRAY", maxSize, maxSize, 10, "NO_ERROR");
+ expectOk("TEXTURE_2D_ARRAY", maxSize, 1, 10, "NO_ERROR");
+ expectOk("TEXTURE_2D_ARRAY", 1, maxSize, 10, "NO_ERROR");
+ expectOk("TEXTURE_2D_ARRAY", 1, 1, 10, "INVALID_OPERATION");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-compressed-formats.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-compressed-formats.html
new file mode 100644
index 0000000000..e154631ead
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-compressed-formats.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Conformance test for WebGL2 texStorage2D and texStorage3D with compressed format</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+
+
+<script>
+"use strict";
+description("This test verifies that texStorage2D and texStorage3D " +
+ "accept compressed internalformats.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+// Either of these extensions should be available on all WebGL 2.0 contexts
+const WEBGL_compressed_texture_etc = gl.getExtension("WEBGL_compressed_texture_etc");
+const WEBGL_compressed_texture_s3tc = gl.getExtension("WEBGL_compressed_texture_s3tc");
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (WEBGL_compressed_texture_etc) {
+ debug("Testing WEBGL_compressed_texture_etc formats");
+
+ // These compressed formats are in Table 3.19 from the OpenGL ES 3.0.4 spec.
+ runTexCompressedFormatsTest([
+ WEBGL_compressed_texture_etc.COMPRESSED_R11_EAC,
+ WEBGL_compressed_texture_etc.COMPRESSED_SIGNED_R11_EAC,
+ WEBGL_compressed_texture_etc.COMPRESSED_RG11_EAC,
+ WEBGL_compressed_texture_etc.COMPRESSED_SIGNED_RG11_EAC,
+ WEBGL_compressed_texture_etc.COMPRESSED_RGB8_ETC2,
+ WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_ETC2,
+ WEBGL_compressed_texture_etc.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ WEBGL_compressed_texture_etc.COMPRESSED_RGBA8_ETC2_EAC,
+ WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+ ]);
+ } else {
+ testPassed("No WEBGL_compressed_texture_etc support -- this is legal");
+ }
+
+ if (WEBGL_compressed_texture_s3tc) {
+ debug("Testing WEBGL_compressed_texture_s3tc formats");
+
+ runTexCompressedFormatsTest([
+ WEBGL_compressed_texture_s3tc.COMPRESSED_RGB_S3TC_DXT1_EXT,
+ WEBGL_compressed_texture_s3tc.COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ WEBGL_compressed_texture_s3tc.COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ WEBGL_compressed_texture_s3tc.COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ ]);
+ } else {
+ testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal");
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function runTexCompressedFormatsTest(texCompressedFormats)
+{
+ wtu.setupUnitQuad(gl);
+
+ gl.useProgram(wtu.setupSimpleTextureProgramESSL300(gl, undefined, undefined,
+ `#version 300 es
+ precision mediump float;
+ uniform mediump sampler2DArray tex;
+ in vec2 texCoord;
+ out vec4 out_color;
+ void main() {
+ out_color = texture(tex, vec3(texCoord, 0));
+ }`
+ ));
+
+ texCompressedFormats.forEach(function(internalformat){
+ // Test a 2D texture.
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, internalformat, 4, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "texStorage2D should succeed for " + enumToString(internalformat));
+ gl.deleteTexture(tex);
+
+ // GLES 3.0.4 p147: + EXT_texture_compression_s3tc:
+ // If internalformat is an ETC2/EAC/DXT1/DXT3/DXT5
+ // format, CompressedTexImage3D will generate an INVALID_OPERATION error if
+ // target is not TEXTURE_2D_ARRAY.
+
+ // Test the 3D texture targets.
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texStorage3D(gl.TEXTURE_3D, 1, internalformat, 4, 4, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
+ "texStorage3D(TEXTURE_3D) should fail for " + enumToString(internalformat));
+ gl.deleteTexture(tex3d);
+
+ var tex2dArr = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex2dArr);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, internalformat, 4, 4, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "texStorage3D(TEXTURE_2D_ARRAY) should succeed for " + enumToString(internalformat));
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad from empty texture");
+ gl.deleteTexture(tex2dArr);
+ });
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-canvas-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-canvas-bug.html
new file mode 100644
index 0000000000..2c2d021d5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-canvas-bug.html
@@ -0,0 +1,56 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test bug of TexSubImage3D with canvas</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 2px; height: 2px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description(document.title);
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=859400'>Chromium Issue 859400</a>");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+function runTest() {
+ var ctx = document.createElement('canvas').getContext("2d");
+ var maxTexSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+ var width = Math.ceil(Math.sqrt(maxTexSize));
+ var height = width;
+ var depth = width + 1;
+ ctx.canvas.width = width;
+ // Set canvas height to a value larger than MAX_TEXTURE_SIZE.
+ // This triggers a validation bug in Chrome.
+ ctx.canvas.height = height * depth;
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from TexStorage3D.");
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, depth,
+ gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from TexSubImage3D.");
+}
+
+runTest();
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-pixel-buffer-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-pixel-buffer-bug.html
new file mode 100644
index 0000000000..181a4819fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-subimage3d-pixel-buffer-bug.html
@@ -0,0 +1,90 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test bug of TexSubImage3D with pixel buffer</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="2" height="2" style="width: 2px; height: 2px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader_texsize" type="x-shader/x-vertex">#version 300 es
+in vec4 vPosition;
+void main()
+{
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader_texsize_3d" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform highp sampler3D tex;
+uniform int lod;
+uniform ivec3 texSize;
+out vec4 fragColor;
+void main()
+{
+ fragColor = (textureSize(tex, lod) == texSize ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));
+}
+</script>
+
+
+<script>
+"use strict";
+description(document.title);
+debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=666384'>Chromium Issue 666384</a>");
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+function runTest() {
+ wtu.setupUnitQuad(gl, 0, 1);
+
+ var program = wtu.setupProgram(
+ gl, ['vshader_texsize', 'fshader_texsize_3d'], ['vPosition'], [0]);
+
+ var width = 32;
+ var height = 16;
+ var depth = 8;
+ gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+ gl.uniform1i(gl.getUniformLocation(program, "lod"), 2);
+ gl.uniform3i(gl.getUniformLocation(program, "texSize"), 8, 4, 2);
+ var tex3d = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex3d);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed");
+ gl.texStorage3D(gl.TEXTURE_3D, 4, gl.RGBA8, width, height, depth);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed");
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, new Uint8Array(width * height * depth * 4), gl.DYNAMIC_DRAW);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Update texture data with texSubImage3D from pixel buffer should succeed");
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed");
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]");
+ gl.deleteTexture(tex3d);
+ gl.deleteBuffer(buffer);
+}
+
+runTest();
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-imagedata.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-imagedata.html
new file mode 100644
index 0000000000..d6c0765bbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-imagedata.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 TexImage3D from ImageData with unpack params tests.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+let actual;
+
+description("TexImage3D from ImageData with unpack params");
+
+debug("TexImage3D from ImageData with UNPACK_IMAGE_HEIGHT set (crbug.com/804123)");
+
+// framebuffer for readback
+const fbo = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+function makeTestData(size, start) {
+ const data = new Uint8ClampedArray(size);
+ for (let i = 0; i < size; ++i) {
+ data[i] = (start + i) % 256;
+ }
+ return data;
+}
+
+// source data
+//
+// dstWidth = 4
+// <-->
+// xxxx ^ ^ ^ ^
+// xxxx | | |
+// xxxx | | |
+// xxxx | | v dstHeight = 4
+// ---- | |
+// ---- | |
+// ---- | v unpackImageHeight = 7
+// xxxx | |
+// xxxx |
+// xxxx |
+// xxxx |
+// ---- |
+// ---- |
+// ---- |
+// xxxx | |
+// xxxx |
+// xxxx |
+// xxxx |
+// ---- |
+// ---- |
+// ---- |
+// xxxx | v dstDepth = 4
+// xxxx |
+// xxxx |
+// xxxx v srcHeight = 25
+// <-->
+// srcWidth = 4
+const unpackImageHeight = 7;
+const dstWidth = 4;
+const dstHeight = 4;
+const dstDepth = 4;
+const srcWidth = dstWidth;
+const srcHeight = (dstDepth - 1) * unpackImageHeight + dstHeight;
+const srcSize = srcWidth * srcHeight;
+const sizeofR8 = 1;
+const sizeofRGBA8 = 4;
+const imageData = new ImageData(makeTestData(srcSize * sizeofRGBA8, 1), srcWidth, srcHeight);
+const texture = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_3D, texture);
+
+debug("");
+// upload
+gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 2);
+gl.texImage3D(gl.TEXTURE_3D, 0, gl.R8, 1, 1, 1, 0, gl.RED, gl.UNSIGNED_BYTE, imageData);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "small upload");
+// check
+actual = new Uint8Array(sizeofRGBA8);
+gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, 0);
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+ shouldBeTrue(`areArraysEqual(actual, [1, 0, 0, 255])`);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+} else {
+ debug("framebuffer incomplete: skipped");
+}
+
+debug("");
+// upload
+gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
+gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, dstWidth, dstHeight, dstDepth, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, imageData);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "larger upload");
+// check
+actual = new Uint8Array(dstWidth * dstHeight * sizeofRGBA8);
+let expected;
+for (let z = 0; z < dstDepth; ++z) {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, z);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.readPixels(0, 0, dstWidth, dstHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+ debug(`for z = ${z}:`);
+ expected = makeTestData(dstWidth * dstHeight * sizeofRGBA8,
+ 1 + z * dstWidth * unpackImageHeight * sizeofRGBA8);
+ shouldBeTrue('areArraysEqual(actual, expected)');
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+gl.deleteTexture(texture);
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-with-flip-y-and-premultiply-alpha.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-with-flip-y-and-premultiply-alpha.html
new file mode 100644
index 0000000000..b80b01c69a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-with-flip-y-and-premultiply-alpha.html
@@ -0,0 +1,499 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 texture unpack parameters with FLIP_Y / PREMULTIPLY_ALPHA conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+var __verbose__ = false;
+
+// Some drivers (for example, NVIDIA Linux) incorrectly require padding for
+// the last row. The below flag is only for testing convenience. Browsers should
+// work around the bug.
+var __apply_alignment_workaround__ = false;
+
+function setupArrayBuffer(size, initData) {
+ var array = new Uint8Array(size);
+ if (initData) {
+ for (var ii = 0; ii < size; ++ii) {
+ array[ii] = ii % 255;
+ }
+ }
+ return array;
+}
+
+function calculatePaddingBytes(bytesPerPixel, alignment, width) {
+ var padding = 0;
+ switch (alignment) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ padding = (bytesPerPixel * width) % alignment;
+ if (padding > 0)
+ padding = alignment - padding;
+ return padding;
+ default:
+ testFailed("should not reach here");
+ return;
+ }
+}
+
+function computeImageSizes2D(width, height, testCase) {
+ // Assume RGBA8/UNSIGNED_BYTE
+ var bytesPerPixel = 4;
+ var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength;
+ var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth);
+ var bytesPerRow = actualWidth * bytesPerPixel + padding;
+ var bytesLastRow = bytesPerPixel * width;
+ var size = bytesPerRow * (height - 1) + bytesLastRow;
+ var skipSize = 0;
+ if (testCase.skipPixels > 0)
+ skipSize += bytesPerPixel * testCase.skipPixels;
+ if (testCase.skipRows > 0)
+ skipSize += bytesPerRow * testCase.skipRows;
+ return {size: size,
+ bytesPerRow: bytesPerRow,
+ bytesLastRow: bytesLastRow,
+ padding: padding,
+ skipSize: skipSize,
+ totalSize: size + skipSize};
+}
+
+function copyData(srcData, srcIndex, dstData, dstIndex, size, premultiply_alpha) {
+ for (var ii = 0; ii < size / 4; ++ii) {
+ var factor = 1.0;
+ if (premultiply_alpha)
+ factor = srcData[srcIndex + ii * 4 + 3] / 255.0;
+ dstData[dstIndex + ii * 4] = srcData[srcIndex + ii * 4] * factor;
+ dstData[dstIndex + ii * 4 + 1] = srcData[srcIndex + ii * 4 + 1] * factor;
+ dstData[dstIndex + ii * 4 + 2] = srcData[srcIndex + ii * 4 + 2] * factor;
+ dstData[dstIndex + ii * 4 + 3] = srcData[srcIndex + ii * 4 + 3];
+ }
+}
+
+function unpackPixels(srcData, width, height, imageSizes, flip_y, premultiply_alpha) {
+ var bytesPerPixel = 4;
+ var unpackedSize = width * height * bytesPerPixel;
+ var dstData = setupArrayBuffer(unpackedSize, false);
+ var srcIndex = imageSizes.skipSize;
+ var dstIndex = 0;
+ var inc = width * bytesPerPixel;
+ if (flip_y)
+ dstIndex += (height - 1) * inc;
+ for (var y = 0; y < height; ++y) {
+ copyData(srcData, srcIndex, dstData, dstIndex, width * bytesPerPixel, premultiply_alpha);
+ srcIndex += imageSizes.bytesPerRow;
+ if (flip_y)
+ dstIndex -= inc;
+ else
+ dstIndex += inc;
+ }
+ if (flip_y)
+ dstIndex += height * inc;
+ return dstData;
+}
+
+function getPixelsFromTexture2D(gl, tex, xoffset, yoffset, width, height) {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ var bytesPerReadbackPixel = 4;
+ var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false);
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ return readbackBuffer;
+}
+
+function comparePixels(buffer1, buffer2, tolerance) {
+ if (buffer1.length != buffer2.length || buffer1.length % 4 != 0) {
+ testFailed("compare pixels: invalid buffer size");
+ return;
+ }
+ var count = 0;
+ for (var ii = 0; ii < buffer1.length / 4; ++ii) {
+ var distance = 0;
+ for (var jj = 0; jj < 4; ++jj) {
+ var diff = buffer1[ii * 4 + jj] - buffer2[ii * 4 + jj];
+ distance += diff * diff;
+ }
+ if (Math.sqrt(diff) > tolerance) {
+ if (__verbose__) {
+ debug("Pixel " + ii + ": expected (" +
+ [buffer1[ii * 4], buffer1[ii * 4 + 1], buffer1[ii * 4 + 2], buffer1[ii * 4 + 3]] + "), got (" +
+ [buffer2[ii * 4], buffer2[ii * 4 + 1], buffer2[ii * 4 + 2], buffer2[ii * 4 + 3]] + ")");
+ }
+ count++;
+ }
+ }
+ if (count > 0) {
+ testFailed("compare pixels: " + count + " pixels differ");
+ } else {
+ testPassed("compare pixels: as expected");
+ }
+}
+
+function runTestIteration2D(gl, testCase, flip_y, premultiply_alpha) {
+ debug("");
+ debug("Texture upload with : flip_y = " + flip_y + ", premultiply_alpha = " + premultiply_alpha +
+ ", alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength +
+ ", skipPixels = " + testCase.skipPixels + ", skipRows = " + testCase.skipRows);
+ debug("TexImage2D : size = (" + testCase.width + ", " + testCase.height + ")");
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength);
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip_y);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiply_alpha);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed");
+
+ var tol = 3;
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ var imageSizes = computeImageSizes2D(testCase.width, testCase.height, testCase);
+ var bufferSize = imageSizes.totalSize;
+ var array;
+
+ // Verify buffer with less than enough size will fail.
+ array = setupArrayBuffer(bufferSize - 1, false);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, testCase.width, testCase.height, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+
+ if (__apply_alignment_workaround__)
+ bufferSize += imageSizes.padding;
+ array = setupArrayBuffer(bufferSize, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, testCase.width, testCase.height, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, array);
+ if (testCase.validUnpackParams2D) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D with correct buffer size should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, testCase.width, testCase.height, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded.");
+ return;
+ }
+
+ var buffer1 = unpackPixels(array, testCase.width, testCase.height, imageSizes, flip_y, premultiply_alpha);
+ var buffer2 = getPixelsFromTexture2D(gl, tex, 0, 0, testCase.width, testCase.height);
+ comparePixels(buffer1, buffer2, tol);
+
+ var subWidth = testCase.width - testCase.xoffset;
+ var subHeight = testCase.height - testCase.yoffset;
+ debug("TexSubImage2D : offset = (" + testCase.xoffset + ", " + testCase.yoffset +
+ "), size = (" + subWidth + ", " + subHeight + ")");
+ imageSizes = computeImageSizes2D(subWidth, subHeight, testCase);
+ bufferSize = imageSizes.totalSize;
+
+ array = setupArrayBuffer(bufferSize - 1, false);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset,
+ subWidth, subHeight, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+
+ if (__apply_alignment_workaround__)
+ bufferSize += imageSizes.padding;
+ array = setupArrayBuffer(bufferSize, true);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset, subWidth, subHeight,
+ gl.RGBA, gl.UNSIGNED_BYTE, array);
+ if (testCase.validUnpackParamsForSub2D) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D with correct buffer size should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
+ return;
+ }
+
+ var buffer1 = unpackPixels(array, subWidth, subHeight, imageSizes, flip_y, premultiply_alpha);
+ var buffer2 = getPixelsFromTexture2D(
+ gl, tex, testCase.xoffset, testCase.yoffset, subWidth, subHeight);
+ comparePixels(buffer1, buffer2, tol);
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+}
+
+function runTests(gl) {
+ var testCases = [
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 2, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 6, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 8, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+
+ // ROW_LENGTH == width
+ { width: 10, height: 9, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 10, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+
+ // ROW_LENGTH < width
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 4, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 2, rowLength: 4, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 4, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 4, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: false },
+
+ // ROW_LENGTH > width
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 6, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 2, rowLength: 7, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 8, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 9, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+
+ // IMAGE_HEIGHT == height
+ { width: 6, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+
+ // IMAGE_HEIGHT < height
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 2, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+
+ // IMAGE_HEIGHT > height
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 6, height: 7, xoffset: 2, yoffset: 2,
+ alignment: 2, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 7, height: 7, xoffset: 2, yoffset: 4,
+ alignment: 4, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 8, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 0, skipPixels: 0, skipRows: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+
+ // SKIP parameters
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 0, skipPixels: 10, skipRows: 0,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 2, rowLength: 0, skipPixels: 2, skipRows: 8,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 0, skipPixels: 3, skipRows: 5,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 8, rowLength: 0, skipPixels: 7, skipRows: 0,
+ validUnpackParams2D: false },
+
+ // all mixed.
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 1, rowLength: 6, skipPixels: 3, skipRows: 5,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 2, rowLength: 4, skipPixels: 7, skipRows: 2,
+ validUnpackParams2D: false },
+ { width: 5, height: 7, xoffset: 2, yoffset: 3,
+ alignment: 4, rowLength: 10, skipPixels: 0, skipRows: 3,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ { width: 1, height: 1, xoffset: 0, yoffset: 0,
+ alignment: 2, rowLength: 3, skipPixels: 3, skipRows: 5,
+ validUnpackParams2D: false },
+ { width: 17, height: 6, xoffset: 12, yoffset: 3,
+ alignment: 2, rowLength: 4, skipPixels: 1, skipRows: 4,
+ validUnpackParams2D: false },
+ { width: 8, height: 17, xoffset: 2, yoffset: 13,
+ alignment: 4, rowLength: 9, skipPixels: 0, skipRows: 3,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true },
+ ];
+
+ var groups = [
+ // { flip_y: false, premultiply_alpha: false },
+ { flip_y: true, premultiply_alpha: false },
+ { flip_y: false, premultiply_alpha: true },
+ { flip_y: true, premultiply_alpha: true },
+ ];
+
+ for (var jj = 0; jj < groups.length; ++jj) {
+ var group = groups[jj];
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var testCase = testCases[ii];
+ runTestIteration2D(gl, testCase, group.flip_y, group.premultiply_alpha);
+ }
+ }
+}
+
+function runNegativeTests(gl) {
+ debug("");
+ debug("Test tex{Sub}Image2D from pbo fails with FLIP_Y = true or PREMULTIPLY_ALPHA = true");
+
+ var width = 16, height = 16, depth = 2;
+
+ // Restore default values.
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0);
+ 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_FLIP_Y_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ var bufferSize = width * height * 4; // RGBA8
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize, gl.DYNAMIC_DRAW);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D from pbo works with default pixel store settings");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D from pbo works with default pixel store settings");
+
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D from pbo with FLIP_Y=true should fail");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage2D from pbo with FLIP_Y=true should fail");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
+
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D from pbo with PREMULTIPLY_ALPHA=true should fail");
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage2D from pbo with PREMULTIPLY_ALPHA=true should fail");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+
+ debug("");
+ debug("Test tex{Sub}Image3D from pbo fails with FLIP_Y = true or PREMULTIPLY_ALPHA = true");
+
+ gl.deleteTexture(tex);
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex);
+
+ bufferSize = width * height * depth * 4; // RGBA8
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize, gl.DYNAMIC_DRAW);
+
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D from pbo works with default pixel store settings");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D from pbo works with default pixel store settings");
+
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D from pbo with FLIP_Y=true should fail");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D from pbo with FLIP_Y=true should fail");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
+
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+
+ debug("");
+ debug("Test tex{Sub}Image3D from client array fails with FLIP_Y = true or PREMULTIPLY_ALPHA = true");
+
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ gl.deleteBuffer(buffer);
+ buffer = null;
+ var array = setupArrayBuffer(bufferSize, false);
+
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D from client array works with default pixel store settings");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D from client array works with default pixel store settings");
+
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D from client array with FLIP_Y=true should fail");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D from client array with FLIP_Y=true should fail");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
+
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, array);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+}
+
+function runRegressionTests(gl) {
+ debug("");
+ debug("The following test serves as a regression test for crbug.com/774174");
+ var array = new Uint16Array(32);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 4);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 6);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texSubImage2D(gl.TEXTURE_2D, 4, 7, 5, 8, 5, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, array);
+ // At this point, the Chrome ASAN build used to crash.
+ testPassed("The regression test for crbug.com/774174 doesn't crash");
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Calling texSubImage2D without initializing the texture is illegal");
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+}
+
+var gl = wtu.create3DContext("example", undefined, 2);
+if (!gl) {
+ testFailed("Fail to get a WebGL context");
+} else {
+ runTests(gl);
+ runNegativeTests(gl);
+ runRegressionTests(gl);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params.html
new file mode 100644
index 0000000000..2cdfd4bd7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params.html
@@ -0,0 +1,591 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 texture unpack parameters conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+var __verbose__ = false;
+
+// Some drivers (for example, NVIDIA Linux) incorrectly require padding for
+// the last row. The below flag is only for testing convenience. Browsers should
+// work around the bug.
+var __apply_alignment_workaround__ = false;
+
+function setupArrayBuffer(size, initData) {
+ var array = new Uint8Array(size);
+ if (initData) {
+ for (var ii = 0; ii < size; ++ii) {
+ array[ii] = ii % 255;
+ }
+ }
+ return array;
+}
+
+function calculatePaddingBytes(bytesPerPixel, alignment, width) {
+ var padding = 0;
+ switch (alignment) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ padding = (bytesPerPixel * width) % alignment;
+ if (padding > 0)
+ padding = alignment - padding;
+ return padding;
+ default:
+ testFailed("should not reach here");
+ return;
+ }
+}
+
+function computeImageSizes2D(width, height, testCase) {
+ // Assume RGB8/UNSIGNED_BYTE
+ var bytesPerPixel = 3;
+ var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength;
+ var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth);
+ var bytesPerRow = actualWidth * bytesPerPixel + padding;
+ var bytesLastRow = bytesPerPixel * width;
+ var size = bytesPerRow * (height - 1) + bytesLastRow;
+ var skipSize = 0;
+ if (testCase.skipPixels > 0)
+ skipSize += bytesPerPixel * testCase.skipPixels;
+ if (testCase.skipRows > 0)
+ skipSize += bytesPerRow * testCase.skipRows;
+ return {size: size,
+ bytesPerRow: bytesPerRow,
+ bytesLastRow: bytesLastRow,
+ padding: padding,
+ skipSize: skipSize,
+ totalSize: size + skipSize};
+}
+
+function computeImageSizes3D(width, height, depth, testCase) {
+ // Assume RGB8/UNSIGNED_BYTE
+ var bytesPerPixel = 3;
+ var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength;
+ var actualHeight = testCase.imageHeight == 0 ? height : testCase.imageHeight;
+ var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth);
+ var bytesPerRow = actualWidth * bytesPerPixel + padding;
+ var bytesLastRow = bytesPerPixel * width;
+ var bytesPerImage = bytesPerRow * actualHeight;
+ var bytesLastImage = bytesPerRow * (height - 1) + bytesLastRow;
+ var size = bytesPerImage * (depth - 1) + bytesLastImage;
+ var skipSize = 0;
+ if (testCase.skipPixels > 0)
+ skipSize += bytesPerPixel * testCase.skipPixels;
+ if (testCase.skipRows > 0)
+ skipSize += bytesPerRow * testCase.skipRows;
+ if (testCase.skipImages > 0)
+ skipSize += bytesPerImage * testCase.skipImages;
+ return {size: size,
+ bytesPerRow: bytesPerRow,
+ bytesLastRow: bytesLastRow,
+ bytesPerImage: bytesPerImage,
+ bytesLastImage: bytesLastImage,
+ padding: padding,
+ skipSize: skipSize,
+ totalSize: size + skipSize};
+}
+
+function copyData(srcData, srcIndex, dstData, dstIndex, size) {
+ for (var ii = 0; ii < size; ++ii)
+ dstData[dstIndex + ii] = srcData[srcIndex + ii];
+}
+
+function unpackPixels(srcData, width, height, depth, imageSizes) {
+ var bytesPerPixel = 3;
+ var unpackedSize = width * height * depth * bytesPerPixel;
+ var dstData = setupArrayBuffer(unpackedSize, false);
+ var srcIndex = imageSizes.skipSize;
+ var dstIndex = 0;
+ for (var z = 0; z < depth; ++z) {
+ var srcIndexPerImage = srcIndex;
+ for (var y = 0; y < height; ++y) {
+ copyData(srcData, srcIndexPerImage, dstData, dstIndex, width * 3);
+ srcIndexPerImage += imageSizes.bytesPerRow;
+ dstIndex += width * 3;
+ }
+ if (depth > 1)
+ srcIndex += imageSizes.bytesPerImage;
+ }
+ return dstData;
+}
+
+function getPixelsFromTexture2D(gl, tex, xoffset, yoffset, width, height) {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ var bytesPerReadbackPixel = 4;
+ var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false);
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed");
+ var bytesPerPixel = 3;
+ var buffer = setupArrayBuffer(width * height * bytesPerPixel, false);
+ var srcIndex = 0;
+ var dstIndex = 0;
+ for (var y = 0; y < height; ++y) {
+ for (var x = 0; x < width; ++x) {
+ buffer[dstIndex++] = readbackBuffer[srcIndex++]; // R
+ buffer[dstIndex++] = readbackBuffer[srcIndex++]; // G
+ buffer[dstIndex++] = readbackBuffer[srcIndex++]; // B
+ srcIndex++; // A
+ }
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ return buffer;
+}
+
+function getPixelsFromTexture3D(gl, tex, xoffset, yoffset, zoffset, width, height, depth) {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var bytesPerReadbackPixel = 4;
+ var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false);
+ var bytesPerPixel = 3;
+ var buffer = setupArrayBuffer(width * height * depth * bytesPerPixel, false);
+ var dstIndex = 0;
+ for (var zz = 0; zz < depth; ++zz) {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, zz + zoffset);
+ gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed");
+ var srcIndex = 0;
+ for (var y = 0; y < height; ++y) {
+ for (var x = 0; x < width; ++x) {
+ buffer[dstIndex++] = readbackBuffer[srcIndex++]; // R
+ buffer[dstIndex++] = readbackBuffer[srcIndex++]; // G
+ buffer[dstIndex++] = readbackBuffer[srcIndex++]; // B
+ srcIndex++; // A
+ }
+ }
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ return buffer;
+}
+
+function comparePixels(buffer1, buffer2) {
+ if (buffer1.length != buffer2.length || buffer1.length % 3 != 0) {
+ testFailed("compare pixels: invalid buffer size");
+ return;
+ }
+ var count = 0;
+ for (var ii = 0; ii < buffer1.length / 3; ++ii) {
+ if (buffer1[ii * 3] != buffer2[ii * 3] ||
+ buffer1[ii * 3 + 1] != buffer2[ii * 3 + 1] ||
+ buffer1[ii * 3 + 2] != buffer2[ii * 3 + 2]) {
+ if (__verbose__) {
+ debug("Pixel " + ii + ": expected (" +
+ [buffer1[ii * 3], buffer1[ii * 3 + 1], buffer1[ii * 3 + 2]] + "), got (" +
+ [buffer2[ii * 3], buffer2[ii * 3 + 1], buffer2[ii * 3 + 2]] + ")");
+ }
+ count++;
+ }
+ }
+ if (count > 0) {
+ testFailed("compare pixels: " + count + " pixels differ");
+ } else {
+ testPassed("compare pixels: as expected");
+ }
+}
+
+function runTestIteration2D(gl, testCase, useUnpackBuffer) {
+ debug("");
+ debug("Texture upload from " + (useUnpackBuffer ? "unpack buffer" : "client data") +
+ " : alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength +
+ ", skipPixels = " + testCase.skipPixels + ", skipRows = " + testCase.skipRows);
+ debug("TexImage2D : size = (" + testCase.width + ", " + testCase.height + ")");
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength);
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ var imageSizes = computeImageSizes2D(testCase.width, testCase.height, testCase);
+ var bufferSize = imageSizes.totalSize;
+ var buffer = null;
+ var array;
+
+ // Verify buffer with less than enough size will fail.
+ if (useUnpackBuffer) {
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, 0);
+ } else {
+ array = setupArrayBuffer(bufferSize - 1, false);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, array);
+ }
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+
+ if (__apply_alignment_workaround__)
+ bufferSize += imageSizes.padding;
+ array = setupArrayBuffer(bufferSize, true);
+ if (useUnpackBuffer) {
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
+ }
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
+ if (testCase.validUnpackParams2D) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D with correct buffer size should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
+ if (!useUnpackBuffer) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded.");
+ }
+ return;
+ }
+
+ var buffer1 = unpackPixels(array, testCase.width, testCase.height, 1, imageSizes);
+ var buffer2 = getPixelsFromTexture2D(gl, tex, 0, 0, testCase.width, testCase.height);
+ comparePixels(buffer1, buffer2);
+
+ var subWidth = testCase.width - testCase.xoffset;
+ var subHeight = testCase.height - testCase.yoffset;
+ debug("TexSubImage2D : offset = (" + testCase.xoffset + ", " + testCase.yoffset +
+ "), size = (" + subWidth + ", " + subHeight + ")");
+ imageSizes = computeImageSizes2D(subWidth, subHeight, testCase);
+ bufferSize = imageSizes.totalSize;
+
+ if (useUnpackBuffer) {
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset,
+ subWidth, subHeight, gl.RGB, gl.UNSIGNED_BYTE, 0);
+ } else {
+ array = setupArrayBuffer(bufferSize - 1, false);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset,
+ subWidth, subHeight, gl.RGB, gl.UNSIGNED_BYTE, array);
+ }
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+
+ if (__apply_alignment_workaround__)
+ bufferSize += imageSizes.padding;
+ array = setupArrayBuffer(bufferSize, true);
+ if (useUnpackBuffer) {
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
+ }
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset, subWidth, subHeight,
+ gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
+ if (testCase.validUnpackParamsForSub2D) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D with correct buffer size should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
+ return;
+ }
+
+ var buffer1 = unpackPixels(array, subWidth, subHeight, 1, imageSizes);
+ var buffer2 = getPixelsFromTexture2D(
+ gl, tex, testCase.xoffset, testCase.yoffset, subWidth, subHeight);
+ comparePixels(buffer1, buffer2);
+
+ if (buffer) {
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ gl.deleteBuffer(buffer);
+ }
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+}
+
+function runTestIteration3D(gl, testCase, useUnpackBuffer) {
+ debug("");
+ debug("Texture upload from " + (useUnpackBuffer ? "unpack buffer" : "client data") +
+ " : alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength +
+ ", imageHeight = " + testCase.imageHeight + ", skipPixels = " + testCase.skipPixels +
+ ", skipRows = " + testCase.skipRows + ", skipImages = " + testCase.skipImages);
+ debug("TexImage3D : size = (" + testCase.width + ", " + testCase.height + ", " + testCase.depth + ")");
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, testCase.imageHeight);
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, testCase.skipImages);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, tex);
+
+ var imageSizes = computeImageSizes3D(testCase.width, testCase.height, testCase.depth, testCase);
+ var buffer = null;
+ var array;
+ var bufferSize = imageSizes.totalSize;
+
+ // Verify buffer with less than enough size will fail.
+ if (useUnpackBuffer) {
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, 0);
+ } else {
+ array = setupArrayBuffer(bufferSize - 1, false);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, array);
+ }
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+
+ if (__apply_alignment_workaround__)
+ bufferSize += imageSizes.padding;
+ array = setupArrayBuffer(bufferSize, true);
+ if (useUnpackBuffer) {
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
+ }
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
+ if (testCase.validUnpackParams3D) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D with correct buffer size should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
+ if (!useUnpackBuffer) {
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
+ gl.RGB, gl.UNSIGNED_BYTE, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded.");
+ }
+ return;
+ }
+
+ var buffer1 = unpackPixels(array, testCase.width, testCase.height, testCase.depth, imageSizes);
+ var buffer2 = getPixelsFromTexture3D(
+ gl, tex, 0, 0, 0, testCase.width, testCase.height, testCase.depth);
+ comparePixels(buffer1, buffer2);
+
+ var subWidth = testCase.width - testCase.xoffset;
+ var subHeight = testCase.height - testCase.yoffset;
+ var subDepth = testCase.depth - testCase.zoffset;
+ debug("TexSubImage3D : offset = (" + testCase.xoffset + ", " + testCase.yoffset + ", " +
+ testCase.zoffset + "), size = (" + subWidth + ", " + subHeight + ", " + subDepth + ")");
+ imageSizes = computeImageSizes3D(subWidth, subHeight, subDepth, testCase);
+ bufferSize = imageSizes.totalSize;
+
+ if (useUnpackBuffer) {
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset,
+ subWidth, subHeight, subDepth, gl.RGB, gl.UNSIGNED_BYTE, 0);
+ } else {
+ array = setupArrayBuffer(bufferSize - 1, false);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset,
+ subWidth, subHeight, subDepth, gl.RGB, gl.UNSIGNED_BYTE, array);
+ }
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
+
+ if (__apply_alignment_workaround__)
+ bufferSize += imageSizes.padding;
+ array = setupArrayBuffer(bufferSize, true);
+ if (useUnpackBuffer) {
+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
+ }
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset,
+ subWidth, subHeight, subDepth,
+ gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
+ if (testCase.validUnpackParamsForSub3D) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D with correct buffer size should succeed");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
+ return;
+ }
+
+ buffer1 = unpackPixels(array, subWidth, subHeight, subDepth, imageSizes);
+ buffer2 = getPixelsFromTexture3D(gl, tex, testCase.xoffset, testCase.yoffset, testCase.zoffset,
+ subWidth, subHeight, subDepth);
+ comparePixels(buffer1, buffer2);
+
+ if (buffer) {
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ gl.deleteBuffer(buffer);
+ }
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ gl.deleteTexture(tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
+}
+
+function runTests() {
+ var gl = wtu.create3DContext("example", undefined, 2);
+ if (!gl) {
+ testFailed("Fail to get a WebGL context");
+ return;
+ }
+
+ // For 2D cases, depth, zoffset, imageHeight, skipImages are ignored.
+ var testCases = [
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 5, height: 7, depth: 4, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 2, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 6, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 5, height: 8, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 8, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+
+ // ROW_LENGTH == width
+ { width: 10, height: 9, depth: 2, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 10, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+
+ // ROW_LENGTH < width
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 2, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 8, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+
+ // ROW_LENGTH > width
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 6, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 2, rowLength: 7, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 8, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 5, height: 7, depth: 5, xoffset: 2, yoffset: 3, zoffset: 2,
+ alignment: 8, rowLength: 9, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+
+ // IMAGE_HEIGHT == height
+ { width: 6, height: 7, depth: 4, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 8, rowLength: 0, imageHeight: 7, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+
+ // IMAGE_HEIGHT < height
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 2, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 8, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: false },
+
+ // IMAGE_HEIGHT > height
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 0, imageHeight: 8, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 6, height: 7, depth: 3, xoffset: 2, yoffset: 2, zoffset: 1,
+ alignment: 2, rowLength: 0, imageHeight: 9, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 7, height: 7, depth: 3, xoffset: 2, yoffset: 4, zoffset: 1,
+ alignment: 4, rowLength: 0, imageHeight: 10, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+ { width: 8, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 8, rowLength: 0, imageHeight: 11, skipPixels: 0, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: true, validUnpackParamsForSub3D: true },
+
+ // SKIP parameters
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 0, imageHeight: 0, skipPixels: 10, skipRows: 0, skipImages: 0,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 2, rowLength: 0, imageHeight: 0, skipPixels: 2, skipRows: 8, skipImages: 0,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 0, imageHeight: 0, skipPixels: 3, skipRows: 5, skipImages: 1,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 8, rowLength: 0, imageHeight: 0, skipPixels: 7, skipRows: 0, skipImages: 2,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+
+ // all mixed.
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 1, rowLength: 6, imageHeight: 6, skipPixels: 3, skipRows: 5, skipImages: 1,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 2, rowLength: 4, imageHeight: 8, skipPixels: 7, skipRows: 2, skipImages: 2,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
+ alignment: 4, rowLength: 10, imageHeight: 2, skipPixels: 0, skipRows: 3, skipImages: 1,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: false },
+ { width: 1, height: 1, depth: 1, xoffset: 0, yoffset: 0, zoffset: 0,
+ alignment: 2, rowLength: 3, imageHeight: 2, skipPixels: 3, skipRows: 5, skipImages: 1,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 17, height: 6, depth: 4, xoffset: 12, yoffset: 3, zoffset: 2,
+ alignment: 2, rowLength: 4, imageHeight: 8, skipPixels: 1, skipRows: 4, skipImages: 2,
+ validUnpackParams2D: false, validUnpackParams3D: false },
+ { width: 8, height: 17, depth: 3, xoffset: 2, yoffset: 13, zoffset: 1,
+ alignment: 4, rowLength: 9, imageHeight: 2, skipPixels: 0, skipRows: 3, skipImages: 1,
+ validUnpackParams2D: true, validUnpackParamsForSub2D: true,
+ validUnpackParams3D: false },
+ ];
+
+ // Upload textures from client data
+ var useUnpackBuffer = false;
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var testCase = testCases[ii];
+ runTestIteration2D(gl, testCase, useUnpackBuffer);
+ runTestIteration3D(gl, testCase, useUnpackBuffer);
+ }
+
+ // Upload textures from unpack buffer
+ useUnpackBuffer = true;
+ for (var ii = 0; ii < testCases.length; ++ii) {
+ var testCase = testCases[ii];
+ runTestIteration2D(gl, testCase, useUnpackBuffer);
+ runTestIteration3D(gl, testCase, useUnpackBuffer);
+ }
+}
+
+runTests();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texel-fetch-undefined.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texel-fetch-undefined.html
new file mode 100644
index 0000000000..056deade3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texel-fetch-undefined.html
@@ -0,0 +1,82 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL texel fetch test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="c" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vertex-shader" type="x-shader/x-vertex">#version 300 es
+ precision highp float;
+ in vec4 aPosition;
+
+ void main() {
+ gl_Position = aPosition;
+ }
+</script>
+<script id="fragment-shader" type="x-shader/x-fragment">#version 300 es
+ precision mediump float;
+ uniform sampler2D uSampler;
+ uniform ivec2 uTestPos;
+
+ out vec4 my_FragColor;
+ void main() {
+ my_FragColor = texelFetch(uSampler, uTestPos, 0);
+ }
+</script>
+<script>
+"use strict";
+description("This test makes sure that texelFetch works to the WebGL 2.0 spec when retrieving a texel outside of the texture's size.");
+
+var wtu = WebGLTestUtils;
+var textureSize = 24;
+
+var gl = wtu.create3DContext('c', undefined, 2);
+
+function testFetchAt(x, y, expectedColor) {
+ debug("");
+ debug("Test fetching a texel of the texture at x = " + x +", y = " + y);
+ gl.uniform2i(uTestPos, x, y);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, expectedColor);
+}
+
+var program = wtu.setupProgram(gl, ["vertex-shader", "fragment-shader"]);
+var aPosition = gl.getAttribLocation(program, "aPosition");
+var uTestPos = gl.getUniformLocation(program, "uTestPos");
+
+debug('Creating a texture with size ' + textureSize + '*' + textureSize);
+var tex = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex);
+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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+wtu.fillTexture(gl, tex, textureSize, textureSize, [0, 255, 0, 255]);
+
+wtu.setupUnitQuad(gl, aPosition);
+
+testFetchAt(0, 0, [0, 255, 0, 255]);
+testFetchAt(textureSize - 1, textureSize - 1, [0, 255, 0, 255]);
+testFetchAt(textureSize, 0, [0, 0, 0, 0]);
+testFetchAt(0, textureSize, [0, 0, 0, 0]);
+testFetchAt(-1, 0, [0, 0, 0, 0]);
+testFetchAt(0, -1, [0, 0, 0, 0]);
+testFetchAt(-1, 1, [0, 0, 0, 0]);
+
+finishTest();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html
new file mode 100644
index 0000000000..1d63130eeb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html
@@ -0,0 +1,160 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL2 Non-Power of 2 texture conformance test.</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="example" width="5" height="3" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform samplerCube tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = textureCube(tex, normalize(vec3(texCoord, 1)));
+}
+</script>
+<script>
+"use strict";
+description(document.title);
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+var program = wtu.setupTexturedQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var tests = [
+ { format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ color: [192, 0, 128, 64],
+ expected: [192, 0, 128, 64],
+ tolerance: 0,
+ },
+ { format: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ color: [192, 0, 128],
+ expected: [192, 0, 128, 255],
+ tolerance: 0,
+ },
+ { format: gl.LUMINANCE,
+ type: gl.UNSIGNED_BYTE,
+ color: [192],
+ expected: [192, 192, 192, 255],
+ tolerance: 0,
+ },
+ { format: gl.ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ color: [64],
+ expected: [0, 0, 0, 64],
+ tolerance: 0,
+ },
+ { format: gl.LUMINANCE_ALPHA,
+ type: gl.UNSIGNED_BYTE,
+ color: [192, 64],
+ expected: [192, 192, 192, 64],
+ tolerance: 0,
+ },
+];
+
+tests.forEach(function(test) {
+ debug("");
+ debug("test " + wtu.glEnumToString(gl, test.format) + "/" + wtu.glEnumToString(gl, test.type));
+ var tex = gl.createTexture();
+
+ // Check that an NPOT texture not on level 0 does not generate INVALID_VALUE
+ wtu.fillTexture(gl, tex, 5, 3, test.color, 1, test.format, test.type);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D with NPOT texture with level > 0 should succeed");
+
+ // Check that an NPOT texture on level 0 succeeds
+ wtu.fillTexture(gl, tex, 5, 3, test.color, 0, test.format, test.type);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D with NPOT texture at level 0 should succeed");
+
+ // Check that generateMipmap succeeds on NPOT
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.generateMipmap with NPOT texture should succeed");
+
+ // Check that nothing is drawn if filtering is not correct for NPOT
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, test.expected,
+ "NPOT texture with TEXTURE_WRAP set to REPEAT should draw");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, test.expected,
+ "NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, test.expected,
+ "NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw.");
+
+ gl.copyTexImage2D(gl.TEXTURE_2D, 1, test.format, 0, 0, 5, 3, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "copyTexImage2D with NPOT texture with level > 0 should succeed.");
+
+ // Check that generateMipmap for an POT texture succeeds
+ wtu.fillTexture(gl, tex, 2, 2, test.color, 0, test.format);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "gl.texImage2D and gl.generateMipmap with POT texture at level 0 should succeed");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(
+ gl, test.expected,
+ "POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw.");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+});
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..70c3afdd2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..cdfaa83586
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..9aa9b1b354
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..041b7efc30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..2ef4285bce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..98689741a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..912bd48e8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..1eee7614a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..588df337b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..c4e1b6c71e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..65ab812099
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..56f109c1b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..87a76f8f3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..a43a4e6677
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..8f78281514
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..5e0b208afd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..2163766665
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..3e08c1f3e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..6c50461f75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4af3e733c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..8286845c1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..15118cd8e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..4d4c701e27
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..389243484a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..8fe5f31e01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..5f40dd0126
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..d66ef95477
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..d2ae8a5d37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..f71f0ab9bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..07453b5d6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..9bcf07331a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..0a584f8e1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..0a4b73be41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..89d949a817
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..931574072c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..0d3736b7d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..28edaf8484
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..375f4a34f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..be0c2169cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..5d008b9dd6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..33c0c30d57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..a167338ba8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..841df79968
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..9b58b96884
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..241b5779a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..b0564b4d08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..c94c1a06ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..205041bd2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..75a8c64adf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..1f9704ab9f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..8f20b94f34
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..7953d7df1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..ab30dfdb47
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..37da0e3c77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..ca52e1a021
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..fc1d4c82ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..01bfb29bf0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..76f4dd17cc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..f1801ef2ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..c6b03d38ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..f93af67120
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..69bf81a48f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..920b2f303d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..73347d83f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..dc4276bec9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..0bb5af2704
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..6c0f8a9dfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c21c22330f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/svg_image/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-svg-image.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..8da33f479d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..de224234d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..ff48aca140
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..48f19f8fc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..53d24ec47b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..4482661a5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..c87153e45b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..437aa3e9b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..5d08f8ce16
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..de3935fb3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..11737a84da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..0d4f5793a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..20ba3058e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..ea3417f308
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..60d9f40110
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..72302bac90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..8afa91dec0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..e199aad6ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..f4f441038e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..89bb430792
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..8e600928e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..89694c37b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..cc6413ea96
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..35fa5802bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..9a94bdf215
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..68753476de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..5eaec79917
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..9400dbf128
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..7392552897
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..21227a4232
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..ac9e136b96
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..5ede605e54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..5647dcb4f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..4158166a8b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..8267be44db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..148b0348e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..5191af8499
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..96424f67bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..d2ea68c28e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..7cadbdd50a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..1cc91b08ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..104b0c3c7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..fff3874e6f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..cb02da362d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..13d9bd2149
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..742d80875d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6bec2e0e1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..2101029838
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..39f2fe0609
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..8bca6ac885
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..02f26d4844
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..30aa25e21f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..6b34875b80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..e6dce95067
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..5ad8bd6bf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..62ffa4d71c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..924be8799a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..6d339d91f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..cd8015ad8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..eb297d466c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..bc3b520d36
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..38ae56c603
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..fb83b5984b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..3ae82983f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..999c0601f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..bb8fb1894c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..1b97731549
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..73433f67fe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/video/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-video.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/00_test_list.txt
new file mode 100644
index 0000000000..934fa86eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/00_test_list.txt
@@ -0,0 +1,68 @@
+tex-2d-r8-red-unsigned_byte.html
+tex-2d-r16f-red-half_float.html
+tex-2d-r16f-red-float.html
+tex-2d-r32f-red-float.html
+tex-2d-r8ui-red_integer-unsigned_byte.html
+tex-2d-rg8-rg-unsigned_byte.html
+tex-2d-rg16f-rg-half_float.html
+tex-2d-rg16f-rg-float.html
+tex-2d-rg32f-rg-float.html
+tex-2d-rg8ui-rg_integer-unsigned_byte.html
+tex-2d-rgb8-rgb-unsigned_byte.html
+tex-2d-srgb8-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_byte.html
+tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-2d-r11f_g11f_b10f-rgb-half_float.html
+tex-2d-r11f_g11f_b10f-rgb-float.html
+tex-2d-rgb9_e5-rgb-half_float.html
+tex-2d-rgb9_e5-rgb-float.html
+tex-2d-rgb16f-rgb-half_float.html
+tex-2d-rgb16f-rgb-float.html
+tex-2d-rgb32f-rgb-float.html
+tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-2d-rgba8-rgba-unsigned_byte.html
+tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_byte.html
+tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-2d-rgba4-rgba-unsigned_byte.html
+tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-2d-rgba16f-rgba-half_float.html
+tex-2d-rgba16f-rgba-float.html
+tex-2d-rgba32f-rgba-float.html
+tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
+tex-3d-r8-red-unsigned_byte.html
+tex-3d-r16f-red-half_float.html
+tex-3d-r16f-red-float.html
+tex-3d-r32f-red-float.html
+tex-3d-r8ui-red_integer-unsigned_byte.html
+tex-3d-rg8-rg-unsigned_byte.html
+tex-3d-rg16f-rg-half_float.html
+tex-3d-rg16f-rg-float.html
+tex-3d-rg32f-rg-float.html
+tex-3d-rg8ui-rg_integer-unsigned_byte.html
+tex-3d-rgb8-rgb-unsigned_byte.html
+tex-3d-srgb8-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_byte.html
+tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
+tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
+tex-3d-r11f_g11f_b10f-rgb-half_float.html
+tex-3d-r11f_g11f_b10f-rgb-float.html
+tex-3d-rgb9_e5-rgb-half_float.html
+tex-3d-rgb9_e5-rgb-float.html
+tex-3d-rgb16f-rgb-half_float.html
+tex-3d-rgb16f-rgb-float.html
+tex-3d-rgb32f-rgb-float.html
+tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
+tex-3d-rgba8-rgba-unsigned_byte.html
+tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_byte.html
+tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
+tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
+tex-3d-rgba4-rgba-unsigned_byte.html
+tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
+tex-3d-rgba16f-rgba-half_float.html
+tex-3d-rgba16f-rgba-float.html
+tex-3d-rgba32f-rgba-float.html
+tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..f2ad493097
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..572663d228
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..3b451cda0e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-float.html
new file mode 100644
index 0000000000..14da0a40f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-half_float.html
new file mode 100644
index 0000000000..63ecff5a46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r32f-red-float.html
new file mode 100644
index 0000000000..58412cc6e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..51461d9611
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6f791ef39f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-float.html
new file mode 100644
index 0000000000..519a8fd783
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..2d8c646176
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg32f-rg-float.html
new file mode 100644
index 0000000000..95562187df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..6c09f94fb5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..52d6638f01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..19e1f0618e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..6dad747733
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..536ca73944
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..fcb7a1f6bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..cd4d7f2b87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..92b0986a76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..8b5d03bfc7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..d306085a26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..ac91e3352d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6153033352
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..f9b1eabcd8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..a79e67496c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..c06adc5bc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..bf88f69b53
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..6bd3b2ae64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..1768f8be8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..43ec606dbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..c77410acf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..1a1b69f8ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..69f2892b62
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..517daedcbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html
new file mode 100644
index 0000000000..66fcf4e320
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html
new file mode 100644
index 0000000000..58e257d4f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
new file mode 100644
index 0000000000..e124673126
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R11F_G11F_B10F", "RGB", "UNSIGNED_INT_10F_11F_11F_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-float.html
new file mode 100644
index 0000000000..a6b6d216fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-half_float.html
new file mode 100644
index 0000000000..908d5935fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r16f-red-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R16F", "RED", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r32f-red-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r32f-red-float.html
new file mode 100644
index 0000000000..6960f8bce8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r32f-red-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R32F", "RED", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8-red-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8-red-unsigned_byte.html
new file mode 100644
index 0000000000..a37d1c4bf0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8-red-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8", "RED", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html
new file mode 100644
index 0000000000..38801bd3f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-r8ui-red_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("R8UI", "RED_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-float.html
new file mode 100644
index 0000000000..69cf2e9141
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-half_float.html
new file mode 100644
index 0000000000..50d04e6b7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg16f-rg-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG16F", "RG", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg32f-rg-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg32f-rg-float.html
new file mode 100644
index 0000000000..463a0ef19b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg32f-rg-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG32F", "RG", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8-rg-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8-rg-unsigned_byte.html
new file mode 100644
index 0000000000..ee97689f18
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8-rg-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8", "RG", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html
new file mode 100644
index 0000000000..6fec968239
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rg8ui-rg_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RG8UI", "RG_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
new file mode 100644
index 0000000000..6450a174d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB10_A2", "RGBA", "UNSIGNED_INT_2_10_10_10_REV", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-float.html
new file mode 100644
index 0000000000..4fcb222ba2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-half_float.html
new file mode 100644
index 0000000000..7dd91adc70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb16f-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB16F", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb32f-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb32f-rgb-float.html
new file mode 100644
index 0000000000..a6b5c973e6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb32f-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB32F", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..1293e5a5fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
new file mode 100644
index 0000000000..7aa3770fee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb565-rgb-unsigned_short_5_6_5.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB565", "RGB", "UNSIGNED_SHORT_5_6_5", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..05a09947f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
new file mode 100644
index 0000000000..2529c36698
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB5_A1", "RGBA", "UNSIGNED_SHORT_5_5_5_1", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..a38c237d33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
new file mode 100644
index 0000000000..c3563665ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB8UI", "RGB_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-float.html
new file mode 100644
index 0000000000..1d4d0200aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-half_float.html
new file mode 100644
index 0000000000..a9ae2f904d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGB9_E5", "RGB", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-float.html
new file mode 100644
index 0000000000..aee016ff9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-half_float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-half_float.html
new file mode 100644
index 0000000000..dcbe835102
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba16f-rgba-half_float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA16F", "RGBA", "HALF_FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba32f-rgba-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba32f-rgba-float.html
new file mode 100644
index 0000000000..d26fbf5eb1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba32f-rgba-float.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA32F", "RGBA", "FLOAT", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..700e4482ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
new file mode 100644
index 0000000000..c33d936c97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba4-rgba-unsigned_short_4_4_4_4.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA4", "RGBA", "UNSIGNED_SHORT_4_4_4_4", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..a7da2df13d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
new file mode 100644
index 0000000000..061d12d12f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("RGBA8UI", "RGBA_INTEGER", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8-rgb-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8-rgb-unsigned_byte.html
new file mode 100644
index 0000000000..d14b5eeaf8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8-rgb-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8", "RGB", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
new file mode 100644
index 0000000000..20b6f7cc5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/webgl_canvas/tex-3d-srgb8_alpha8-rgba-unsigned_byte.html
@@ -0,0 +1,38 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("SRGB8_ALPHA8", "RGBA", "UNSIGNED_BYTE", testPrologue, "../../../resources/", 2)();
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/00_test_list.txt
new file mode 100644
index 0000000000..35caba6ccd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/00_test_list.txt
@@ -0,0 +1,9 @@
+--min-version 2.0.1 non-existent-varying.html
+--min-version 2.0.1 default_transform_feedback.html
+transform_feedback.html
+two-unreferenced-varyings.html
+--min-version 2.0.1 too-small-buffers.html
+unwritten-output-defaults-to-zero.html
+--min-version 2.0.1 same-buffer-two-binding-points.html
+--min-version 2.0.1 simultaneous_binding.html
+--min-version 2.0.1 switching-objects.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/default_transform_feedback.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/default_transform_feedback.html
new file mode 100644
index 0000000000..1d5e72811a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/default_transform_feedback.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Transform Feedback Conformance Test - Default Transform Feedback</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in float in_value;
+out float out_value;
+
+void main() {
+ out_value = in_value * 2.;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 dummy;
+void main() {
+ dummy = vec4(1);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies using the default transform feedback object");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runDefaultTransformFeedbackTest();
+ finishTest();
+}
+
+function runDefaultTransformFeedbackTest() {
+ const prog = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_value"], gl.SEPARATE_ATTRIBS,
+ ["in_value"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+
+ const inLoc = 0;
+ const outLoc = 0;
+
+ const srcBuffer1 = createBuffer(gl, new Float32Array([1, 2, 3]));
+ const srcVAO1 = createVAO(gl, srcBuffer1, inLoc);
+
+ const dstBuffer = createBuffer(gl, Float32Array.BYTES_PER_ELEMENT * 3);
+
+ const tf = null; // use the default transform feedback gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.useProgram(prog);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, outLoc, dstBuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors binding a buffer to the default transform feedback");
+
+ runFeedback(gl, prog, srcVAO1, tf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors having drawn with the default transform feedback");
+
+ const expected = [2, 4, 6];
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, dstBuffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors after readback");
+}
+
+function runFeedback(gl, prog, srcVAO, tf, dstBufferInfo) {
+ gl.enable(gl.RASTERIZER_DISCARD);
+
+ gl.useProgram(prog);
+ gl.bindVertexArray(srcVAO);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors setting up to draw with the default transform feedback");
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ gl.endTransformFeedback();
+
+ gl.disable(gl.RASTERIZER_DISCARD);
+}
+
+function createBuffer(gl, dataOrSize) {
+ const buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, dataOrSize, gl.STATIC_DRAW);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null); // Clear this or we'll have tfo/non-tfo simultaneous usage.
+ return buf;
+}
+
+function createVAO(gl, buf, inLoc) {
+ const vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.enableVertexAttribArray(inLoc);
+ gl.vertexAttribPointer(inLoc, 1, gl.FLOAT, false, 0, 0);
+ gl.bindVertexArray(null);
+ return vao;
+}
+</script>
+</body>
+</html>
+
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/non-existent-varying.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/non-existent-varying.html
new file mode 100644
index 0000000000..80800c2dc5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/non-existent-varying.html
@@ -0,0 +1,70 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Transform Feedback Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec3 position;
+void main()
+{
+ gl_Position = vec4(position, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+void main()
+{
+ color = vec4(0);
+}
+</script>
+<script>
+"use strict";
+description("Test that specifying non-existent varyings for transform feedback causes the program to fail to link. This test covers an ANGLE bug.");
+
+// Spec: GLES 3.0.5 section 2.12.8:
+// "A program will fail to link if:"
+// "any variable name specified in the varyings array is not declared as an output in the vertex shader;"
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ runTest("bogus");
+ runTest("gl_Bogus");
+}
+
+function runTest(nonExistentVaryingName) {
+ var program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ [nonExistentVaryingName], gl.INTERLEAVED_ATTRIBS,
+ ["position"]);
+ var msg = "Program should fail to link when a nonexistent varying '" + nonExistentVaryingName + "' is specified for transform feedback.";
+ if (program) {
+ testFailed(msg);
+ } else {
+ testPassed(msg);
+ }
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/same-buffer-two-binding-points.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/same-buffer-two-binding-points.html
new file mode 100644
index 0000000000..86e7a5d402
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/same-buffer-two-binding-points.html
@@ -0,0 +1,176 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Transform Feedback Conformance Tests - one buffer bound to two binding points</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+
+in vec4 in_data;
+out vec4 out_add;
+out vec4 out_mul;
+void main(void) {
+ out_add = in_data + vec4(2.0, 3.0, 4.0, 5.0);
+ out_mul = in_data * vec4(2.0, 3.0, 4.0, 5.0);
+}
+</script>
+<script>
+"use strict";
+description();
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(null, null, 2);
+var program = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ runTwoOutFeedbackTest();
+}
+
+function doDrawWithTransformFeedback(expectedError, msg) {
+ gl.beginTransformFeedback(gl.POINTS);
+ wtu.glErrorShouldBe(gl, expectedError, msg);
+ gl.drawArrays(gl.POINTS, 0, 3);
+ gl.endTransformFeedback();
+ gl.getError();
+}
+
+function runTwoOutFeedbackTest() {
+ debug("");
+ debug("Test binding the same buffer to two transform feedback binding points. Buffer should be untouched and an error should be generated.")
+
+ // Build the input and output buffers
+ var in_data = [
+ 1.0, 2.0, 3.0, 4.0,
+ 2.0, 4.0, 8.0, 16.0,
+ 0.75, 0.5, 0.25, 0.0
+ ];
+
+ var in_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
+
+ // Create the transform feedback shader
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", wtu.simpleColorFragmentShaderESSL300],
+ ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeNonNull("program");
+
+ // Draw the the transform feedback buffers
+ var tf = gl.createTransformFeedback();
+
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0);
+
+ var out_buffer = gl.createBuffer();
+ var out_buffer2 = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+
+ // Test binding the same buffer to two transform feedback binding points with bindBufferBase.
+ debug("");
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length * 2, gl.STATIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_buffer);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, out_buffer);
+
+ doDrawWithTransformFeedback(gl.INVALID_OPERATION, "same buffer bound to two transform feedback binding points with bindBufferBase");
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, null);
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ // Check buffer contents.
+ var expectedZeroes = [];
+ for (var i = 0; i < in_data.length * 2; ++i)
+ {
+ expectedZeroes.push(0.0);
+ }
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ debug("buffer should be untouched - filled with zeroes");
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expectedZeroes);
+
+ // Test binding the same buffer to two transform feedback binding points with bindBufferRange. The ranges overlap just slightly.
+ debug("");
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length * 2, gl.STATIC_DRAW);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_buffer, 0, in_data.length * 4);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 1, out_buffer, (in_data.length - 1) * 4, in_data.length * 4);
+
+ doDrawWithTransformFeedback(gl.INVALID_OPERATION, "same buffer bound to two transform feedback binding points with bindBufferRange, overlapping ranges");
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, null);
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ // Check buffer contents.
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ debug("buffer should be untouched - filled with zeroes");
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expectedZeroes);
+
+ // Test non-overlapping ranges.
+ debug("");
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length * 2, gl.STATIC_DRAW);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_buffer, 0, in_data.length * 4);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 1, out_buffer, in_data.length * 4, in_data.length * 4);
+
+ doDrawWithTransformFeedback(gl.INVALID_OPERATION, "same buffer bound to two transform feedback binding points with bindBufferRange, non-overlapping ranges");
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, null);
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ // Check buffer contents.
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ debug("buffer should be untouched - filled with zeroes");
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expectedZeroes);
+
+ // Test binding the same buffer to a binding point that doesn't have a corresponding output in the vertex shader.
+ debug("");
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer2);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length * 2, gl.STATIC_DRAW);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length * 2, gl.STATIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_buffer);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, out_buffer2);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 2, out_buffer); // No corresponding output.
+
+ doDrawWithTransformFeedback(gl.INVALID_OPERATION, "same buffer bound to two transform feedback binding points with bindBufferBase, but one of the binding points doesn't have a corresponding shader output");
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 2, null);
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ // Check buffer contents.
+ debug("buffers should be untouched - filled with zeroes");
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expectedZeroes);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer2);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expectedZeroes);
+
+ finishTest();
+}
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/simultaneous_binding.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/simultaneous_binding.html
new file mode 100644
index 0000000000..228b4ab5cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/simultaneous_binding.html
@@ -0,0 +1,330 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Simultaneous binding</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in float in_value;
+in float in_value2;
+out float out_value;
+
+void main() {
+ out_value = in_value * 2.;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 dummy;
+uniform UniformBlock {
+ float fragment_value;
+};
+void main() {
+ dummy = vec4(fragment_value);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies that access to a buffer simultaneously bound to a transform feedback object and a non-transform-feedback binding point is forbidden.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+}
+
+function drawWithFeedbackBound(gl, drawFunction, prog, vao, tf, enableFeedback) {
+ gl.useProgram(prog);
+ gl.bindVertexArray(vao);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ if (enableFeedback) gl.beginTransformFeedback(gl.POINTS);
+ let error = gl.getError();
+ if (error != gl.NO_ERROR) testFailed("Unexpected error before drawing: " + error)
+ drawFunction();
+ if (enableFeedback) gl.endTransformFeedback();
+ gl.bindVertexArray(null);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+}
+
+function createBuffer(gl, dataOrSize) {
+ const buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, dataOrSize, gl.STATIC_DRAW);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ return buf;
+}
+
+function createVAO(gl, vertexBuffer, vertexBuffer2, indexBuffer) {
+ const vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer2);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+ gl.vertexAttribDivisor(1, 2);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindVertexArray(null);
+ return vao;
+}
+
+const prog = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_value"], gl.SEPARATE_ATTRIBS,
+ ["in_value", "in_value2"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+
+const vertexBuffer = createBuffer(gl, new Float32Array([1, 2, 3, 4]));
+const vertexBuffer2 = createBuffer(gl, new Float32Array([1, 2, 3, 4]));
+const vertexBuffer3 = createBuffer(gl, new Float32Array([1, 2, 3, 4]));
+
+const indexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([0, 1, 2, 3]), gl.STATIC_DRAW);
+
+const tfBuffer = createBuffer(gl, new Float32Array([0, 0, 0, 0]));
+
+const vao = createVAO(gl, vertexBuffer, vertexBuffer2, indexBuffer);
+// This tests that having a transform feedback buffer bound in an unbound VAO
+// does not affect anything.
+const unboundVao = createVAO(gl, tfBuffer, tfBuffer, indexBuffer);
+
+const tf = gl.createTransformFeedback();
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+gl.useProgram(prog);
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer);
+// this binds the default (id = 0) TRANSFORM_FEEBACK buffer
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+
+const uniformBuffer = createBuffer(gl, new Float32Array([1, 0, 0, 0]));
+const ubi = gl.getUniformBlockIndex(prog, "UniformBlock");
+gl.uniformBlockBinding(prog, ubi, 0);
+gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uniformBuffer);
+
+const drawFunctions = [
+ [
+ ()=>gl.drawArrays(gl.POINTS, 0, 4),
+ ()=>gl.drawElements(gl.POINTS, 4, gl.UNSIGNED_SHORT, 0),
+ ],
+ [
+ ()=>gl.drawArraysInstanced(gl.POINTS, 0, 4, 1),
+ ()=>gl.drawElementsInstanced(gl.POINTS, 4, gl.UNSIGNED_SHORT, 0, 1),
+ ],
+ [
+ ()=>gl.drawArrays(gl.POINTS, 0, 4),
+ ()=>gl.drawRangeElements(gl.POINTS, 0, 3, 4, gl.UNSIGNED_SHORT, 0),
+ ],
+ ];
+
+for (let [drawArrays, drawElements] of drawFunctions) {
+ debug("<h3>With draw functions " + drawArrays + " and " + drawElements + "</h3>");
+ debug("<hr/>Test baseline");
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 16, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bufferData to TRANSFORM_FEEDBACK_BUFFER");
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements should be successful");
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should be successful");
+
+ const expected = [2, 4, 6, 8];
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected);
+
+ debug("<hr/>Test generic bind point set to null");
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements should be successful");
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should be successful");
+
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected);
+
+ debug("<hr/>Test generic bind point set to vertex buffer");
+ // The TRANSFORM_FEEDBACK_BUFFER generic binding point is not part of the
+ // transform feedback object and not written to by transform feedback. Only
+ // the indexed binding points are written to. So it should be legal to draw
+ // from a buffer bound to the generic binding point.
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, vertexBuffer);
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements should be successful");
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should be successful");
+
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected);
+
+ debug("<hr/>Test ARRAY_BUFFER");
+ // this should fail because the transform feedback's buffer #0 and the
+ // badVao's buffer #0 are the same buffer
+ const badVao = createVAO(gl, tfBuffer, vertexBuffer2, indexBuffer);
+ drawWithFeedbackBound(gl, drawArrays, prog, badVao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArrays: buffer used as vertex attrib and tf simultaneously");
+ drawWithFeedbackBound(gl, drawElements, prog, badVao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElements: buffer used as vertex attrib and tf simultaneously");
+ drawWithFeedbackBound(gl, drawArrays, prog, badVao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer used as vertex attrib and tf simultaneously");
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected, "should be the same as before as nothing has executed");
+
+ debug("<hr/>Test UNIFORM_BUFFER");
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, tfBuffer);
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null); // tfBuffer is still bound at index 0
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawArrays: buffer used as uniform buffer and tf simultaneously");
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "drawElements: buffer used as uniform buffer and tf simultaneously");
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer used as uniform buffer and tf simultaneously");
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uniformBuffer);
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays: tf buffer not used as uniform buffer anymore");
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements: tf buffer not used as uniform buffer anymore");
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "tf buffer not used as uniform buffer anymore");
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ const tfBuffer2 = createBuffer(gl, Float32Array.BYTES_PER_ELEMENT * 4);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer2);
+ drawWithFeedbackBound(gl, drawArrays, prog, badVao, tf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "buffer is no longer bound for transform feedback");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer);
+
+ debug("<hr/>Test TF buffer bound to target unused by draw");
+ // Even if the TF buffer is bound to a target that's not used by the draw, it's
+ // still an error.
+ gl.bindBuffer(gl.COPY_READ_BUFFER, tfBuffer);
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, true);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "tf enabled");
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawArrays: tf disabled");
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawElements: tf disabled");
+ gl.bindBuffer(gl.COPY_READ_BUFFER, null);
+
+ debug("<hr/>Test TF buffer bound to disabled vertex attrib");
+ // Having a TF buffer bound to a disabled vertex attrib should not be an error
+ // when TF is not enabled, because the buffer is not used.
+ gl.bindVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, tfBuffer);
+ gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 0, 0);
+ gl.disableVertexAttribArray(2);
+ gl.bindVertexArray(null);
+ drawWithFeedbackBound(gl, drawArrays, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "tf disabled, draw should succeed");
+ drawWithFeedbackBound(gl, drawElements, prog, vao, tf, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "tf disabled, draw should succeed");
+ // Remove the TF buffer binding from the VAO after the test.
+ gl.bindVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer3);
+ gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 0, 0);
+ gl.disableVertexAttribArray(2);
+ gl.bindVertexArray(null);
+}
+
+debug("<h1>Non-drawing tests</h1>");
+
+debug("<hr/>Test bufferData");
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 16, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bufferData to TRANSFORM_FEEDBACK_BUFFER");
+gl.bindBuffer(gl.COPY_WRITE_BUFFER, tfBuffer);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 16, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bufferData with double bound buffer");
+gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
+
+// The value of the TRANSFORM_FEEDBACK_BUFFER generic bind point should not
+// affect the legality of any operation.
+let genericBindPointValues = [()=>null, ()=>tfBuffer, ()=>vertexBuffer];
+
+for (let genericBindPointValue of genericBindPointValues) {
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ debug("<h3>With TRANSFORM_FEEDBACK_BUFFER generic bind point value " + genericBindPointValue + "</h3>");
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, genericBindPointValue());
+
+ debug("<hr/>Test PIXEL_UNPACK_BUFFER");
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, vertexBuffer);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "PIXEL_UNPACK_BUFFER is not bound for transform feedback");
+
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, tfBuffer);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "PIXEL_UNPACK_BUFFER is bound for transform feedback");
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+
+ debug("<hr/>Test PIXEL_PACK_BUFFER");
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, vertexBuffer);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "PIXEL_PACK_BUFFER is not bound for transform feedback");
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, tfBuffer);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "PIXEL_PACK_BUFFER is bound for transform feedback");
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null)
+
+ debug("<hr/>Test bufferData family with tf object bound");
+
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, tfBuffer);
+ gl.bufferData(gl.COPY_WRITE_BUFFER, 16, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bufferData with double bound buffer");
+ gl.bufferSubData(gl.COPY_WRITE_BUFFER, 0, new Uint8Array([0]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bufferSubData with double bound buffer");
+ gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, new Uint8Array([0]), 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "getBufferSubData with double bound buffer");
+
+ gl.bindBuffer(gl.COPY_READ_BUFFER, vertexBuffer);
+ gl.copyBufferSubData(gl.COPY_WRITE_BUFFER, gl.COPY_READ_BUFFER, 0, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "copyBufferSubData with double bound buffer");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "copyBufferSubData with double bound buffer");
+
+ debug("<hr/>Test bufferData family with tf object unbound");
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, tfBuffer);
+ gl.bufferData(gl.COPY_WRITE_BUFFER, 16, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bufferData should succeed");
+ gl.bufferSubData(gl.COPY_WRITE_BUFFER, 0, new Uint8Array([0]));
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bufferSubData should succeed");
+ gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, new Uint8Array([0]), 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getBufferSubData should succeed");
+
+ gl.bindBuffer(gl.COPY_READ_BUFFER, vertexBuffer);
+ gl.copyBufferSubData(gl.COPY_WRITE_BUFFER, gl.COPY_READ_BUFFER, 0, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copyBufferSubData should succeed");
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "copyBufferSubData should succeed");
+}
+
+finishTest();
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/switching-objects.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/switching-objects.html
new file mode 100644
index 0000000000..fce82dd21f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/switching-objects.html
@@ -0,0 +1,231 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Switching transform feedback objects</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in float in_value;
+out float out_value1;
+out float out_value2;
+
+void main() {
+ out_value1 = in_value * 2.;
+ out_value2 = in_value * 4.;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 dummy;
+void main() {
+ dummy = vec4(0.);
+}
+</script>
+<script>
+"use strict";
+description("Tests switching transform feedback objects.");
+
+debug("<h3>Setup</h3>")
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+if (!gl) {
+ testFailed("WebGL context does not exist");
+}
+
+// Setup
+const prog_interleaved = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_value1", "out_value2"], gl.INTERLEAVED_ATTRIBS,
+ ["in_value"]);
+const prog_no_varyings = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ [], gl.INTERLEAVED_ATTRIBS,
+ ["in_value"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "shader compilation");
+const vertexBuffer = createBuffer(gl, new Float32Array([1, 2, 3, 4]));
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+gl.useProgram(prog_interleaved);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "vertex buffer and program setup");
+
+const tf1 = gl.createTransformFeedback();
+const tf2 = gl.createTransformFeedback();
+const tfBuffer1 = createBuffer(gl, new Float32Array([0, 0]));
+const tfBuffer2 = createBuffer(gl, new Float32Array([0, 0]));
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer1);
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer2);
+const expected_tf_output = [2, 4];
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TF object setup");
+
+debug("<h3>Baseline transform feedback success case</h3>");
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+gl.beginTransformFeedback(gl.POINTS);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin TF");
+gl.drawArrays(gl.POINTS, 0, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "draw");
+gl.endTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end TF");
+
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
+
+debug("<h3>Generic binding is not changed when switching TF object</h3>");
+
+// According to the GL ES spec historically, TRANSFORM_FEEDBACK_BUFFER_BINDING is listed as part
+// of the transform feedback object state. However, many drivers treat it as global context state
+// and not part of the tranform feedback object, which means that it does not change when
+// bindTransformFeedback is called. Khronos has resolved to change the spec to specify the latter
+// behavior: https://gitlab.khronos.org/opengl/API/issues/66 (Khronos private link). This tests
+// for the new behavior.
+
+// Set each buffer to contain its buffer number. We use this to check which
+// buffer is *really* bound at the driver level by reading the buffer contents.
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([1]), gl.STREAM_READ);
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer2);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([2]), gl.STREAM_READ);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bufferData");
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+checkParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, tfBuffer2);
+checkIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, tfBuffer1);
+wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [2]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readback");
+
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
+checkParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, null);
+checkIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, tfBuffer2);
+
+debug("<h3>Error switching TF object while TF is enabled</h3>");
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([0, 0]), gl.STREAM_READ);
+gl.beginTransformFeedback(gl.POINTS);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin");
+checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf1);
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bind while unpaused");
+
+// Check that nothing actually changed and rendering still works
+checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf1);
+gl.drawArrays(gl.POINTS, 0, 1);
+gl.endTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should complete successfully");
+wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
+
+
+debug("<h3>Successfully switching TF object while TF is paused</h3>");
+
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([0, 0]), gl.STREAM_READ);
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer2);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([0, 0]), gl.STREAM_READ);
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
+gl.beginTransformFeedback(gl.POINTS);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin on tf2");
+checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf2);
+
+gl.pauseTransformFeedback();
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind while paused");
+gl.beginTransformFeedback(gl.POINTS);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin on tf1");
+checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf1);
+gl.drawArrays(gl.POINTS, 0, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "draw should succeed");
+gl.endTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end on tf1");
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
+
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
+gl.endTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end on tf2");
+
+debug("<h3>Misc. invalid operations</h3>")
+
+gl.endTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "endTransformFeedback before begin");
+gl.pauseTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "pauseTransformFeedback when not active");
+gl.resumeTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "pauseTransformFeedback when not active");
+
+gl.beginTransformFeedback(gl.POINTS);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should begin successfully");
+gl.drawArrays(gl.TRIANGLE_STRIP, 0, 1);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "wrong primitive mode");
+gl.useProgram(prog_no_varyings);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "switch program while active");
+gl.resumeTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "resumeTransformFeedback when not paused");
+gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bindTransformFeedback when active");
+gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer2);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBuffer(TRANSFORM_FEEDBACK_BUFFER) when active");
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer2);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bindBufferBase(TRANSFORM_FEEDBACK_BUFFER) when active");
+
+gl.pauseTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "pause");
+gl.pauseTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "already paused");
+gl.endTransformFeedback();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end while paused");
+
+finishTest();
+
+// Helper functions
+function createBuffer(gl, dataOrSize) {
+ const buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, dataOrSize, gl.STATIC_DRAW);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ return buf;
+}
+
+function checkParameter(param, expected) {
+ const value = gl.getParameter(param);
+ if (value != expected) {
+ testFailed(wtu.glEnumToString(gl, param) + " was " + value + ", but expected " + expected);
+ } else {
+ testPassed(wtu.glEnumToString(gl, param) + " was " + value + ", matching expected " + expected);
+ }
+}
+
+function checkIndexedParameter(param, index, expected) {
+ const value = gl.getIndexedParameter(param, index);
+ if (value != expected) {
+ testFailed(wtu.glEnumToString(gl, param) + "[" + index + "] was " + value + ", but expected " + expected);
+ } else {
+ testPassed(wtu.glEnumToString(gl, param) + "[" + index + "] was " + value + ", matching expected " + expected);
+ }
+}
+
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/too-small-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/too-small-buffers.html
new file mode 100644
index 0000000000..64acfbad7b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/too-small-buffers.html
@@ -0,0 +1,242 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>TF too small buffers</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in float in_value1;
+in float in_value2;
+out float out_value1;
+out float out_value2;
+void main() {
+ out_value1 = in_value1 * 2.;
+ out_value2 = in_value2 * 2.;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 dummy;
+void main() {
+ dummy = vec4(0.);
+}
+</script>
+<script>
+"use strict";
+description("Transform feedback into buffers that are too small should produce errors.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+}
+
+const progInterleaved = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_value1", "out_value2"], gl.INTERLEAVED_ATTRIBS,
+ ["in_value1", "in_value2"]);
+const progSeparate = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_value1", "out_value2"], gl.SEPARATE_ATTRIBS,
+ ["in_value1", "in_value2"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "program compilation");
+
+// Attrib 1 contains 4 vertices. Attrib 2 contains 4 instance indices.
+const vertexBuffer0 = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer0);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), gl.STATIC_DRAW);
+const vertexBuffer1 = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), gl.STATIC_DRAW);
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer0);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+gl.vertexAttribDivisor(1, 1);
+
+let tfBuffer0 = gl.createBuffer();
+let tfBuffer1 = gl.createBuffer();
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup");
+
+const sizeOfFloat = 4;
+
+let cases = [
+ { name: "drawArrays",
+ drawFunction: ()=>gl.drawArrays(gl.POINTS, 0, 4),
+ result: [[2, 4, 6, 8], [2, 2, 2, 2]]},
+ { name: "drawArraysInstanced one instance",
+ drawFunction: ()=>gl.drawArraysInstanced(gl.POINTS, 0, 4, 1),
+ result: [[2, 4, 6, 8], [2, 2, 2, 2]]},
+ { name: "drawArraysInstanced four instances",
+ drawFunction: ()=>gl.drawArraysInstanced(gl.POINTS, 0, 1, 4),
+ result: [[2, 2, 2, 2], [2, 4, 6, 8]]},
+ ];
+
+for (let {name, drawFunction, result} of cases) {
+ debug("<h1>" + name + "</h1>")
+
+ let interleavedResult = [];
+ for (let i = 0; i < result[0].length; i++) {
+ interleavedResult.push(result[0][i], result[1][i]);
+ }
+
+ let doTransformFeedback = (drawFunction, error) => {
+ gl.beginTransformFeedback(gl.POINTS);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "before draw");
+ drawFunction();
+ wtu.glErrorShouldBe(gl, error, "draw");
+ gl.endTransformFeedback();
+ }
+
+ gl.useProgram(progInterleaved);
+
+ debug("<h3>interleaved - Baseline success case</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8*sizeOfFloat, gl.STREAM_READ);
+ doTransformFeedback(drawFunction, gl.NO_ERROR);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, interleavedResult);
+
+ debug("<h3>interleaved - Buffer too small</h3>")
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8*sizeOfFloat-1, gl.STREAM_READ);
+ doTransformFeedback(drawFunction, gl.INVALID_OPERATION);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER,
+ [0, 0, 0, 0, 0, 0, 0]);
+
+ debug("<h3>interleaved - Multiple draws success case</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8*sizeOfFloat*2, gl.STREAM_READ);
+ doTransformFeedback(()=>{drawFunction(); drawFunction()}, gl.NO_ERROR);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, interleavedResult.concat(interleavedResult))
+
+ debug("<h3>interleaved - Too small for multiple draws</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8*sizeOfFloat*2-1, gl.STREAM_READ);
+ doTransformFeedback(()=>{drawFunction(); drawFunction()}, gl.INVALID_OPERATION);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, interleavedResult.concat([0, 0, 0, 0, 0, 0, 0]))
+
+ debug("<h3>interleaved - bindBufferRange too small</h3>")
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8*sizeOfFloat, gl.STREAM_READ);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0, 0, 7*sizeOfFloat);
+ doTransformFeedback(drawFunction, gl.INVALID_OPERATION);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER,
+ [0, 0, 0, 0, 0, 0, 0, 0]);
+
+ debug("<h3>interleaved - bindBufferRange larger than buffer</h3>")
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8*sizeOfFloat-1, gl.STREAM_READ);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0, 0, 8*sizeOfFloat);
+ doTransformFeedback(drawFunction, gl.INVALID_OPERATION);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER,
+ [0, 0, 0, 0, 0, 0, 0]);
+
+ gl.useProgram(progSeparate);
+
+ debug("<h3>separate - Baseline success case</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat, gl.STREAM_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, tfBuffer1);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat, gl.STREAM_READ);
+ doTransformFeedback(drawFunction, gl.NO_ERROR);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer0);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, result[0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, result[1]);
+
+ debug("<h3>separate - Buffer too small</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat, gl.STREAM_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, tfBuffer1);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat-1, gl.STREAM_READ);
+ doTransformFeedback(drawFunction, gl.INVALID_OPERATION);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer0);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [0, 0, 0, 0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [0, 0, 0]);
+
+ debug("<h3>separate - multiple draws success case</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat*2, gl.STREAM_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, tfBuffer1);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat*2, gl.STREAM_READ);
+ doTransformFeedback(()=>{drawFunction(); drawFunction();}, gl.NO_ERROR);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer0);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, result[0].concat(result[0]));
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, result[1].concat(result[1]));
+
+ debug("<h3>separate - Too small for multiple draws</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat*2, gl.STREAM_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, tfBuffer1);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat*2-1, gl.STREAM_READ);
+ doTransformFeedback(()=>{drawFunction(); drawFunction();}, gl.INVALID_OPERATION);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer0);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, result[0].concat([0, 0, 0, 0]));
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, result[1].concat([0, 0, 0]));
+
+ debug("<h3>separate - bindBufferRange too small</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat, gl.STREAM_READ);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 1, tfBuffer1, 0, 3*sizeOfFloat);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat, gl.STREAM_READ);
+ doTransformFeedback(drawFunction, gl.INVALID_OPERATION);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer0);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [0, 0, 0, 0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [0, 0, 0]);
+
+ debug("<h3>separate - bindBufferRange larger than buffer</h3>")
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat, gl.STREAM_READ);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 1, tfBuffer1, 0, 4*sizeOfFloat);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4*sizeOfFloat-1, gl.STREAM_READ);
+ doTransformFeedback(drawFunction, gl.INVALID_OPERATION);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer0);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [0, 0, 0, 0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [0, 0, 0]);
+}
+
+debug("<h1>integer overflow</h1>")
+
+gl.useProgram(progInterleaved);
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer0);
+gl.bufferData(gl.ARRAY_BUFFER, (1<<16)*sizeOfFloat, gl.STREAM_READ);
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1);
+gl.bufferData(gl.ARRAY_BUFFER, (1<<16)*sizeOfFloat, gl.STREAM_READ);
+gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer0);
+gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, (1<<16)*sizeOfFloat*2, gl.STREAM_READ);
+
+gl.beginTransformFeedback(gl.POINTS);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "before draw");
+// If count and primcount are stored in 32-bit signed integers and then
+// multiplied to calculate the number of transform feedback vertices, the
+// calculation will overflow to 0.
+gl.drawArraysInstanced(gl.POINTS, 0, 1<<16, 1<<16);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "integer overflow and/or buffer too small");
+gl.endTransformFeedback();
+
+finishTest();
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html
new file mode 100644
index 0000000000..20256c6ace
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html
@@ -0,0 +1,645 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Transform Feedback Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+
+in vec4 in_data;
+out vec4 out_add;
+out vec4 out_mul;
+void main(void) {
+ out_add = in_data + vec4(2.0, 3.0, 4.0, 5.0);
+ out_mul = in_data * vec4(2.0, 3.0, 4.0, 5.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 out_color;
+void main(void) {
+ out_color = vec4(1.0, 1.0, 1.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of the Transform Feedback objects.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var tf = null;
+var tf1 = null;
+var buf = null;
+let out_add_buffer = null;
+var program = null;
+var activeInfo = null;
+var query = null;
+var numberOfQueryCompletionAttempts = 0;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runBindingTest();
+ runTFBufferBindingTest();
+ runObjectTest();
+ runGetBufferSubDataTest();
+ runUnboundDeleteTest();
+ runBoundDeleteTest();
+ runOneOutputFeedbackTest();
+ // Must be the last test, since it's asynchronous and calls finishTest().
+ runTwoOutputFeedbackTest();
+}
+
+function runBindingTest() {
+ debug("");
+ debug("Testing binding enum");
+
+ shouldBe("gl.TRANSFORM_FEEDBACK_BINDING", "0x8E25");
+
+ gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TRANSFORM_FEEDBACK_BINDING query should succeed");
+
+ // Default value is null
+ shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "null");
+
+ debug("Testing binding a Transform Feedback object");
+ tf = gl.createTransformFeedback();
+ tf1 = gl.createTransformFeedback();
+ shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "tf");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+ shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "tf1");
+ gl.deleteTransformFeedback(tf);
+ gl.deleteTransformFeedback(tf1);
+ shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted Transform Feedback object");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runTFBufferBindingTest() {
+ debug("");
+ debug("Testing binding and unbinding transform feedback objects and buffers");
+
+ buf = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 16, gl.STATIC_DRAW);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
+
+ tf = gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+
+ // gl.TRANSFORM_FEEDBACK_BUFFER is part of Transform Feedback objects'
+ // state. See OpenGL ES 3.0.5 Section 6.24.
+ //
+ // Since the TRANSFORM_FEEDBACK was just unbound, there should be nothing
+ // bound.
+ shouldBeNull('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)');
+
+ // Binding the buffer to the ARRAY_BUFFER binding point should succeed.
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "binding buffer to ARRAY_BUFFER");
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(buf);
+ buf = null;
+ gl.deleteTransformFeedback(tf);
+ tf = null;
+}
+
+function runObjectTest() {
+ debug("");
+ debug("Testing object creation");
+
+ tf = gl.createTransformFeedback();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createTransformFeedback should not set an error");
+ shouldBeNonNull("tf");
+
+ // Expect false if never bound
+ shouldBeFalse("gl.isTransformFeedback(tf)");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ shouldBeTrue("gl.isTransformFeedback(tf)");
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ shouldBeTrue("gl.isTransformFeedback(tf)");
+ gl.deleteTransformFeedback(tf);
+ shouldBeFalse("gl.isTransformFeedback(tf)");
+
+ shouldBeFalse("gl.isTransformFeedback(null)");
+
+ tf = null;
+}
+
+function runOneOutputFeedbackTest() {
+ debug("");
+ debug("Testing one-output transform feedback");
+
+ // Build the input and output buffers
+ var in_data = [
+ 1.0, 2.0, 3.0, 4.0,
+ 2.0, 4.0, 8.0, 16.0,
+ 0.75, 0.5, 0.25, 0.0
+ ];
+
+ var in_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
+
+ out_add_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW);
+
+ // Create the transform feedback shader
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_add"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeNonNull("program");
+
+ // Draw the the transform feedback buffers
+ tf = gl.createTransformFeedback();
+
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer);
+
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.beginTransformFeedback(gl.POINTS);
+
+ debug("Testing switching program while transform feedback is active");
+ gl.pauseTransformFeedback();
+ var program2 = wtu.setupSimpleColorProgram(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Switching program while transform feedback is active and paused should succeed");
+ gl.useProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Switching program while transform feedback is active and paused should succeed");
+ gl.resumeTransformFeedback();
+ gl.useProgram(program2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching program while transform feedback is active should fail");
+ shouldBe("gl.getParameter(gl.CURRENT_PROGRAM)", "program");
+
+ debug("Testing deleting an active transform feedback object");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors before testing deletion");
+ gl.deleteTransformFeedback(tf);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Deleting the transform feedback while active should fail, and have no effect");
+ shouldBe("gl.isTransformFeedback(tf)", "true");
+ debug("Resuming testing of single-output transform feedback");
+
+ gl.drawArrays(gl.POINTS, 0, 3);
+
+ gl.endTransformFeedback();
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+
+ // Verify the output buffer contents
+ var add_expected = [
+ 3.0, 5.0, 7.0, 9.0,
+ 4.0, 7.0, 12.0, 21.0,
+ 2.75, 3.5, 4.25, 5.0
+ ];
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, add_expected);
+
+ gl.deleteBuffer(in_buffer);
+ gl.deleteBuffer(out_add_buffer);
+ gl.deleteProgram(program);
+ gl.deleteTransformFeedback(tf);
+
+ tf = null;
+ program = null;
+}
+
+function runTwoOutputFeedbackTest() {
+ debug("");
+ debug("Testing two-output transform feedback");
+
+ // Build the input and output buffers
+ var in_data = [
+ 1.0, 2.0, 3.0, 4.0,
+ 2.0, 4.0, 8.0, 16.0,
+ 0.75, 0.5, 0.25, 0.0
+ ];
+
+ var in_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
+
+ out_add_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW);
+
+ var out_mul_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_mul_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW);
+
+ // Create the transform feedback shader
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeNonNull("program");
+
+ // Create a query object to check the number of primitives written
+ query = gl.createQuery();
+
+ // Draw the the transform feedback buffers
+ tf = gl.createTransformFeedback();
+
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, out_mul_buffer);
+
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.beginTransformFeedback(gl.POINTS);
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
+
+ gl.drawArrays(gl.POINTS, 0, 3);
+
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ gl.endTransformFeedback();
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, null);
+
+ // Verify the output buffer contents
+ var add_expected = [
+ 3.0, 5.0, 7.0, 9.0,
+ 4.0, 7.0, 12.0, 21.0,
+ 2.75, 3.5, 4.25, 5.0
+ ];
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, add_expected);
+
+ var mul_expected = [
+ 2.0, 6.0, 12.0, 20.0,
+ 4.0, 12.0, 32.0, 80.0,
+ 1.5, 1.5, 1.0, 0.0
+ ];
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_mul_buffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, mul_expected);
+
+ gl.deleteBuffer(in_buffer);
+ gl.deleteBuffer(out_add_buffer);
+ gl.deleteBuffer(out_mul_buffer);
+ gl.deleteProgram(program);
+ gl.deleteTransformFeedback(tf);
+
+ tf = null;
+ program = null;
+
+ // Check the result of the query. It should not be available yet.
+ // This constant was chosen arbitrarily to take around 1 second on
+ // one WebGL implementation on one desktop operating system. (Busy-
+ // loops based on calling Date.now() have been found unreliable.)
+ var numEarlyTests = 50000;
+ while (--numEarlyTests > 0) {
+ gl.finish();
+ if (gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) {
+ testFailed("Query's result became available too early");
+ finishTest();
+ return;
+ }
+ }
+ testPassed("TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query's result didn't become available too early");
+
+ // Complete the rest of the test asynchronously.
+ requestAnimationFrame(completeTransformFeedbackQueryTest);
+}
+
+function runUnboundDeleteTest() {
+ debug("");
+ debug("Testing deleting buffers attached to an unbound transform feedback object");
+
+ // Theoretically it would be possible to verify the result of performing
+ // transform feedback into a deleted buffer object. The buffer would have to
+ // be latched into a VAO as well as into the transform feedback object. In
+ // order to get the results out of the output buffer, it would be necessary
+ // to run transform feedback again, reading from the buffer bound to the
+ // VAO, and writing into a (non-deleted) buffer object latched into the
+ // transform feedback object. It's not possible to arrange things to be able
+ // to copyBufferSubData from the deleted buffer object into a temporary one
+ // for readback.
+
+ // This would be a lot of code to test an unlikely corner case, so instead,
+ // this test verifies simpler behaviors.
+
+ out_add_buffer = gl.createBuffer();
+ const output_buffer_length = Float32Array.BYTES_PER_ELEMENT * 16;
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, output_buffer_length, gl.STATIC_DRAW);
+
+ // Set up the transform feedback object
+ tf = gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer);
+
+ // Unbind transform feedback and delete out_add_buffer.
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.deleteBuffer(out_add_buffer);
+ debug("isBuffer should report false after deletion");
+ shouldBe("gl.isBuffer(out_add_buffer)", "false");
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ debug("Transform feedback object should keep output buffer alive");
+ shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "out_add_buffer");
+ // Deleting the buffer again while the transform feedback is bound shouldn't unbind it.
+ gl.deleteBuffer(out_add_buffer);
+ debug("Deleting output buffer again should be a no-op");
+ shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "out_add_buffer");
+
+ // Try unbinding and rebinding the transform feedback object just
+ // to make sure that has no effect on the attached output buffer.
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ debug("Transform feedback object should still keep output buffer alive");
+ shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "out_add_buffer");
+
+ gl.deleteTransformFeedback(tf);
+
+ tf = null;
+ out_add_buffer = null;
+}
+
+function runBoundDeleteTest() {
+ debug("");
+ debug("Testing deleting buffers attached to a bound transform feedback object");
+
+ out_add_buffer = gl.createBuffer();
+ const output_buffer_length = Float32Array.BYTES_PER_ELEMENT * 16;
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, output_buffer_length, gl.STATIC_DRAW);
+
+ // Set up the transform feedback object
+ tf = gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer);
+
+ // Delete the output buffer
+ gl.deleteBuffer(out_add_buffer);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ debug("Buffer should have been unbound from active transform feedback");
+ shouldBeNull("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)");
+
+ gl.deleteTransformFeedback(tf);
+
+ tf = null;
+ out_add_buffer = null;
+}
+
+var retArray;
+
+function verifyGetBufferSubData(expected) {
+ wtu.shouldGenerateGLError(gl, expected, "gl.getBufferSubData(gl.TRANSFORM_FEEDBACK_BUFFER, 0, retArray, 0, retArray.length)");
+}
+
+function runGetBufferSubDataTest() {
+ debug("");
+ debug("Test that getBufferSubData...");
+
+ // Build the input and output buffers
+ var in_data = [
+ 1.0, 2.0, 3.0, 4.0,
+ 2.0, 4.0, 8.0, 16.0,
+ 0.75, 0.5, 0.25, 0.0
+ ];
+
+ retArray = new Float32Array(in_data.length);
+
+ var in_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
+
+ out_add_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW);
+
+ // Create the transform feedback shader
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_add"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeNonNull("program");
+
+ // Draw the the transform feedback buffers
+ tf = gl.createTransformFeedback();
+
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+
+ debug("... passes when a transform feedback object is not bound");
+ verifyGetBufferSubData(gl.NO_ERROR);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer);
+
+ debug("... passes when a transform feedback object is bound but not active");
+ verifyGetBufferSubData(gl.NO_ERROR);
+
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.beginTransformFeedback(gl.POINTS);
+
+ debug("... fails when a transform feedback object is active");
+ verifyGetBufferSubData(gl.INVALID_OPERATION);
+
+ gl.drawArrays(gl.POINTS, 0, 3);
+
+ gl.endTransformFeedback();
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+
+ // Verify the output buffer contents
+ var add_expected = [
+ 3.0, 5.0, 7.0, 9.0,
+ 4.0, 7.0, 12.0, 21.0,
+ 2.75, 3.5, 4.25, 5.0
+ ];
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, add_expected);
+
+ tf = null;
+ program = null;
+}
+
+function completeTransformFeedbackQueryTest() {
+ debug("");
+ debug("Testing TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query");
+
+ ++numberOfQueryCompletionAttempts;
+ if (numberOfQueryCompletionAttempts > 500) {
+ testFailed("Query didn't become available in a reasonable time");
+ finishTest();
+ return;
+ }
+
+ if (!gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) {
+ requestAnimationFrame(completeTransformFeedbackQueryTest);
+ return;
+ }
+
+ var result = gl.getQueryParameter(query, gl.QUERY_RESULT);
+ if (result == 3) {
+ testPassed("TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query returned a correct result (3)");
+ } else {
+ testFailed("TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query returned an incorrect result " + result + " (expected 3)");
+ }
+
+ runVaryingsTest();
+}
+
+function verifyTransformFeedbackVarying(prog, index, valid, name) {
+ activeInfo = gl.getTransformFeedbackVarying(prog, index);
+ if (valid) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "Should be no errors from valid getTransformFeedbackVarying.");
+ shouldBeNonNull("activeInfo");
+ shouldBe("activeInfo.name", "'" + name + "'");
+ shouldBe("activeInfo.type", "gl.FLOAT_VEC4");
+ shouldBe("activeInfo.size", "1");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "Should be INVALID_VALUE when calling getTransformFeedbackVarying with an invalid index.");
+ shouldBeNull("activeInfo");
+ }
+}
+
+function runVaryingsTest() {
+ debug("");
+ debug("Testing transform feedback varyings");
+
+ // Create the transform feedback shader. This is explicitly run after runTwoOutputFeedbackTest,
+ // as re-linking the shader here will test browser caching.
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeNonNull("program");
+
+ // Check the varyings
+ shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "2");
+ verifyTransformFeedbackVarying(program, 0, true, "out_add");
+ verifyTransformFeedbackVarying(program, 1, true, "out_mul");
+ verifyTransformFeedbackVarying(program, 2, false);
+
+ // transformFeedbackVaryings() doesn't take effect until a successful link.
+ gl.transformFeedbackVaryings(program, ["out_mul"], gl.SEPARATE_ATTRIBS);
+ shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "2");
+ verifyTransformFeedbackVarying(program, 0, true, "out_add");
+ verifyTransformFeedbackVarying(program, 1, true, "out_mul");
+ verifyTransformFeedbackVarying(program, 2, false);
+
+ // Now relink.
+ gl.linkProgram(program);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)");
+ shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "1");
+ verifyTransformFeedbackVarying(program, 0, true, "out_mul");
+ verifyTransformFeedbackVarying(program, 1, false);
+ verifyTransformFeedbackVarying(program, 2, false);
+
+ // Test recompiling/relinking the program
+ // Regression test for http://crbug.com/716018
+ var skipCompileStatus = true;
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS,
+ ["in_data"], undefined, undefined, skipCompileStatus);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)");
+ shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "2");
+ verifyTransformFeedbackVarying(program, 0, true, "out_add");
+ verifyTransformFeedbackVarying(program, 1, true, "out_mul");
+ verifyTransformFeedbackVarying(program, 2, false);
+
+ runContextLostOneOutputFeedbackTest();
+}
+
+function runContextLostOneOutputFeedbackTest() {
+ var ext = gl.getExtension("WEBGL_lose_context");
+ if (!ext) {
+ debug("No WEBGL_lose_context support");
+ finishTest();
+ return;
+ }
+ debug("");
+ debug("Testing switching program after context lost while transform feedback is active");
+
+ var in_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(12), gl.STATIC_DRAW);
+
+ out_add_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * 12, gl.STATIC_DRAW);
+
+ // Create an extra program to try switching to
+ var program2 = wtu.setupSimpleColorProgram(gl);
+
+ // Create the transform feedback shader
+ program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_add"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
+ shouldBeNonNull("program");
+
+ // Draw the the transform feedback buffers
+ tf = gl.createTransformFeedback();
+
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer);
+
+ gl.beginTransformFeedback(gl.POINTS);
+
+ debug("Calling loseContext()");
+ ext.loseContext();
+ shouldBeTrue("gl.isContextLost()");
+ shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+ shouldBe("gl.getError()", "gl.NO_ERROR");
+ debug("Trying to switch program");
+ gl.useProgram(program2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No transform feedback error generated on lost context");
+ finishTest();
+}
+
+debug("");
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/two-unreferenced-varyings.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/two-unreferenced-varyings.html
new file mode 100644
index 0000000000..2173fd35ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/two-unreferenced-varyings.html
@@ -0,0 +1,136 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Transform Feedback Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec3 position;
+out vec3 outAttrib1;
+out vec3 outAttrib2;
+void main()
+{
+ outAttrib1 = position;
+ outAttrib2 = position;
+ gl_Position = vec4(position, 1);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 color;
+in vec3 outAttrib1;
+in vec3 outAttrib2;
+void main()
+{
+ color = vec4(0);
+}
+</script>
+<script>
+"use strict";
+description("This test covers an ANGLE bug with two transform feedback varyings. When the two are declared, but not referenced in the fragment shader, ANGLE would fail capture.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var quadVB;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ debug("");
+ debug("Testing transform feedback with two unreferenced outputs");
+ runTest();
+}
+
+function getQuadVerts(depth) {
+ var quadVerts = new Float32Array(3 * 6);
+ quadVerts[0] = -1.0; quadVerts[1] = 1.0; quadVerts[2] = depth;
+ quadVerts[3] = -1.0; quadVerts[4] = -1.0; quadVerts[5] = depth;
+ quadVerts[6] = 1.0; quadVerts[7] = -1.0; quadVerts[8] = depth;
+ quadVerts[9] = -1.0; quadVerts[10] = 1.0; quadVerts[11] = depth;
+ quadVerts[12] = 1.0; quadVerts[13] = -1.0; quadVerts[14] = depth;
+ quadVerts[15] = 1.0; quadVerts[16] = 1.0; quadVerts[17] = depth;
+ return quadVerts;
+}
+
+function drawQuad(depth) {
+ if (!quadVB) {
+ quadVB = gl.createBuffer()
+ }
+
+ var quadVerts = getQuadVerts(depth);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadVB);
+ gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+}
+
+function runTest() {
+
+ // Create the transform feedback program
+ var program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["outAttrib1", "outAttrib2"], gl.INTERLEAVED_ATTRIBS,
+ ["position"]);
+ if (!program) {
+ testFailed("Fail to set up the program");
+ return;
+ }
+
+ // Init transform feedback buffers
+ var out_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * 3 * 2 * 6,
+ gl.STREAM_DRAW);
+
+ var tf = gl.createTransformFeedback();
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_buffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Init transform feedback should succeed");
+
+ // Draw the quad
+ gl.useProgram(program)
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ drawQuad(0.5);
+ gl.endTransformFeedback();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw with transform feedback should succeed");
+
+ // Verify the output buffer contents
+ var quadVerts = getQuadVerts(0.5);
+ var expected_data = [];
+ for (var i = 0; i < quadVerts.length; i += 3) {
+ for (var count = 0; count < 2; count++) {
+ expected_data[expected_data.length] = quadVerts[i];
+ expected_data[expected_data.length] = quadVerts[i+1];
+ expected_data[expected_data.length] = quadVerts[i+2];
+ }
+ }
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_data);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/unwritten-output-defaults-to-zero.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/unwritten-output-defaults-to-zero.html
new file mode 100644
index 0000000000..615ab9bab1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/unwritten-output-defaults-to-zero.html
@@ -0,0 +1,133 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Transform Feedback Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 in_data;
+uniform int flag;
+out vec4 out_data;
+void main(void) {
+ if (flag > 0) {
+ out_data = in_data + vec4(2.0, 3.0, 4.0, 5.0);
+ }
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 out_color;
+void main(void) {
+ out_color = vec4(1.0, 1.0, 1.0, 1.0);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies if an output variable is specified to be streamed to a transform feedback buffer but not actually written, the value defaults to 0.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ debug("");
+ debug("Testing transform feedback works fine");
+ runTest(1);
+
+ debug("");
+ debug("Testing unwritten output variables default to zero");
+ runTest(0);
+}
+
+function runTest(flag) {
+ var in_data = [
+ 1.0, 2.0, 3.0, 4.0,
+ 2.0, 4.0, 8.0, 16.0,
+ 0.75, 0.5, 0.25, 0.0
+ ];
+
+ var in_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
+
+ var out_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW);
+
+ // Create the transform feedback program
+ var program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
+ ["out_data"], gl.SEPARATE_ATTRIBS,
+ ["in_data"]);
+ var loc = gl.getUniformLocation(program, "flag");
+ if (!program || !loc) {
+ testFailed("Fail to set up the program");
+ return;
+ }
+ gl.uniform1i(loc, flag);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up program should succeed");
+
+ // Draw the the transform feedback buffers
+ var tf = gl.createTransformFeedback();
+
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_buffer);
+
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gl.beginTransformFeedback(gl.POINTS);
+
+ gl.drawArrays(gl.POINTS, 0, 3);
+
+ gl.endTransformFeedback();
+ gl.disable(gl.RASTERIZER_DISCARD);
+
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+
+ // Verify the output buffer contents
+ var expected_data;
+ if (flag > 0) {
+ expected_data = [
+ 3.0, 5.0, 7.0, 9.0,
+ 4.0, 7.0, 12.0, 21.0,
+ 2.75, 3.5, 4.25, 5.0
+ ];
+ } else {
+ expected_data = [
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0
+ ];
+ }
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_buffer);
+ wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_data);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt
new file mode 100644
index 0000000000..05e01f554c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt
@@ -0,0 +1,9 @@
+--min-version 2.0.1 draw-with-uniform-blocks.html
+--min-version 2.0.1 gl-uniform-arrays-sub-source.html
+--min-version 2.0.1 query-uniform-blocks-after-shader-detach.html
+--min-version 2.0.1 uniform-blocks-with-arrays.html
+--min-version 2.0.1 simple-buffer-change.html
+--min-version 2.0.1 dependent-buffer-change.html
+--min-version 2.0.1 incompatible-texture-type-for-sampler.html
+--min-version 2.0.1 large-uniform-buffers.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html
new file mode 100644
index 0000000000..888305e6d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html
@@ -0,0 +1,121 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL draw with uniform blocks conformance tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+// Ported from: https://github.com/google/angle/blob/master/src/tests/gl_tests/UniformBufferTest.cpp#L1507
+description("Regression test for https://bugs.chromium.org/p/chromium/issues/detail?id=792966");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ var uboBuf1 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 1, 0, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ // Resize the buffer - triggers a re-allocation in the D3D11 back-end.
+ debug("draw upper triangle - should be green");
+ var bigData = new Float32Array(128 * 4);
+ bigData.set([ 0, 1, 0, 1 ]);
+ gl.bufferData(gl.UNIFORM_BUFFER, bigData, gl.STATIC_DRAW);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html
new file mode 100644
index 0000000000..3fa7949eac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html
@@ -0,0 +1,120 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL draw with uniform blocks conformance tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+description("Regression test for crbug.com/793307 and https://bugzilla.mozilla.org/show_bug.cgi?id=1424258");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ var uboBuf1 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 1, 0, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ debug("draw upper triangle - should be green");
+ var uboBuf2 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 1, uboBuf2);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 0, 1, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 1);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html
new file mode 100644
index 0000000000..7780a7ba01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html
@@ -0,0 +1,404 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform $(type) color[3];
+out vec4 myFragColor;
+void main() {
+ myFragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
+}
+</script>
+<script>
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var vSrc = wtu.getScript("vshader");
+var fTemplate = wtu.getScript("fshader");
+
+// |color| is defined in fragment shader as an array of 3 elements.
+var uniformArraySize = 3;
+var initialUniformValue = 99;
+
+var typeInfos = [
+ { type: 'float',
+ setter: 'uniform1fv',
+ elem: '',
+ numElementsPerType: 1,
+ srcValues: [16, 15],
+ srcValuesWithOffset: [0, 0, 16, 15],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
+ srcOffset: 2,
+ },
+ { type: 'int',
+ setter: 'uniform1iv',
+ elem: '',
+ numElementsPerType: 1,
+ srcValues: [16, 15],
+ srcValuesWithOffset: [0, 0, 16, 15],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
+ srcOffset: 2,
+ },
+ { type: 'uint',
+ setter: 'uniform1uiv',
+ elem: '',
+ numElementsPerType: 1,
+ srcValues: [16, 15],
+ srcValuesWithOffset: [0, 0, 16, 15],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
+ srcOffset: 2,
+ },
+ { type: 'vec2',
+ setter: 'uniform2fv',
+ elem: '[1]',
+ numElementsPerType: 2,
+ srcValues: [16, 15, 14, 13],
+ srcValuesWithOffset: [0, 16, 15, 14, 13],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
+ srcOffset: 1,
+ },
+ { type: 'ivec2',
+ setter: 'uniform2iv',
+ elem: '[1]',
+ numElementsPerType: 2,
+ srcValues: [16, 15, 14, 13],
+ srcValuesWithOffset: [0, 16, 15, 14, 13],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
+ srcOffset: 1,
+ },
+ { type: 'uvec2',
+ setter: 'uniform2uiv',
+ elem: '[1]',
+ numElementsPerType: 2,
+ srcValues: [16, 15, 14, 13],
+ srcValuesWithOffset: [0, 16, 15, 14, 13],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
+ srcOffset: 1,
+ },
+ { type: 'vec3',
+ setter: 'uniform3fv',
+ elem: '[2]',
+ numElementsPerType: 3,
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
+ srcOffset: 1,
+ },
+ { type: 'ivec3',
+ setter: 'uniform3iv',
+ elem: '[2]',
+ numElementsPerType: 3,
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
+ srcOffset: 1,
+ },
+ { type: 'uvec3',
+ setter: 'uniform3uiv',
+ elem: '[2]',
+ numElementsPerType: 3,
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
+ srcOffset: 1,
+ },
+ { type: 'vec4',
+ setter: 'uniform4fv',
+ elem: '[3]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+ { type: 'ivec4',
+ setter: 'uniform4iv',
+ elem: '[3]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+ { type: 'uvec4',
+ setter: 'uniform4uiv',
+ elem: '[3]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+
+ // Matrix
+ { type: 'mat2',
+ setter: 'uniformMatrix2fv',
+ elem: '[1][1]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+ { type: 'mat3',
+ setter: 'uniformMatrix3fv',
+ elem: '[2][2]',
+ numElementsPerType: 9,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0],
+ srcOffset: 3,
+ },
+ { type: 'mat4',
+ setter: 'uniformMatrix4fv',
+ elem: '[3][3]',
+ numElementsPerType: 16,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+ { type: 'mat2x3',
+ setter: 'uniformMatrix2x3fv',
+ elem: '[1][2]',
+ numElementsPerType: 6,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0],
+ srcOffset: 4,
+ },
+ { type: 'mat3x2',
+ setter: 'uniformMatrix3x2fv',
+ elem: '[2][1]',
+ numElementsPerType: 6,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0],
+ srcOffset: 3,
+ },
+ { type: 'mat2x4',
+ setter: 'uniformMatrix2x4fv',
+ elem: '[1][3]',
+ numElementsPerType: 8,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+ { type: 'mat4x2',
+ setter: 'uniformMatrix4x2fv',
+ elem: '[3][1]',
+ numElementsPerType: 8,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffset: [0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0],
+ srcOffset: 5,
+ },
+ { type: 'mat3x4',
+ setter: 'uniformMatrix3x4fv',
+ elem: '[2][3]',
+ numElementsPerType: 12,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+ { type: 'mat4x3',
+ setter: 'uniformMatrix4x3fv',
+ elem: '[3][2]',
+ numElementsPerType: 12,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+
+];
+
+function checkUniformValues(program, typeInfo, useInitialValues) {
+ var numSrcValues = typeInfo.srcValues.length / typeInfo.numElementsPerType;
+ for (var ii = 0; ii < uniformArraySize; ++ii) {
+ var expectedValues;
+ if (useInitialValues || ii >= numSrcValues) {
+ expectedValues = new Array(typeInfo.numElementsPerType);
+ for (var jj = 0; jj < typeInfo.numElementsPerType; ++jj) {
+ expectedValues[jj] = initialUniformValue;
+ }
+ } else {
+ expectedValues = typeInfo.srcValues.slice(
+ typeInfo.numElementsPerType * ii, typeInfo.numElementsPerType * (ii + 1));
+ }
+ var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can get location of element " + ii + " of array from gl.getUniformLocation");
+ var value = gl.getUniform(program, elemLoc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can get value of element " + ii + " of array from gl.getUniform");
+ var equal = true;
+ if (value === null) {
+ equal = false;
+ } else if (typeInfo.numElementsPerType == 1) {
+ if (value != expectedValues[0]) {
+ equal = false;
+ }
+ } else {
+ for (var jj = 0; jj < typeInfo.numElementsPerType; ++jj) {
+ if (value[jj] != expectedValues[jj]) {
+ equal = false;
+ break;
+ }
+ }
+ }
+ assertMsg(equal,
+ "value put in (" + expectedValues + ") matches value pulled out (" +
+ (value === null ? "null" : value) + ")");
+ }
+}
+
+for (var tt = 0; tt < typeInfos.length; ++tt) {
+ var typeInfo = typeInfos[tt];
+ debug("");
+ debug("check " + typeInfo.type);
+ var srcLength = typeInfo.srcValues.length;
+ var fSrc = wtu.replaceParams(fTemplate, typeInfo);
+ var program = wtu.loadProgram(gl, vSrc, fSrc);
+ if (!program) {
+ testFailed("Failed to create the program");
+ continue;
+ }
+ gl.useProgram(program);
+
+ var loc = gl.getUniformLocation(program, "color[0]");
+ if (!loc) {
+ testFailed("Failed to obtain the location of the uniform");
+ continue;
+ }
+
+ function setter(loc, array, srcOffset, srcLength) {
+ var isMatrix = (typeInfo.setter.indexOf("Matrix") == 7);
+ if (typeof(srcOffset) != 'undefined') {
+ if (isMatrix) {
+ gl[typeInfo.setter](loc, gl.FALSE, array, srcOffset, srcLength);
+ } else {
+ gl[typeInfo.setter](loc, array, srcOffset, srcLength);
+ }
+ } else if (typeof(srcLength) != 'undefined') {
+ if (isMatrix) {
+ gl[typeInfo.setter](loc, gl.FALSE, array, srcOffset);
+ } else {
+ gl[typeInfo.setter](loc, array, srcOffset);
+ }
+ } else {
+ if (isMatrix) {
+ gl[typeInfo.setter](loc, gl.FALSE, array);
+ } else {
+ gl[typeInfo.setter](loc, array);
+ }
+ }
+ }
+
+ // Initialize uniforms to value 99 and verify it.
+ var initValues = new Array(typeInfo.numElementsPerType * uniformArraySize);
+ for (var ii = 0; ii < typeInfo.numElementsPerType * uniformArraySize; ++ii) {
+ initValues[ii] = initialUniformValue;
+ }
+ setter(loc, initValues);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "no error from initializing uniforms to 99");
+ checkUniformValues(program, typeInfo, true);
+
+ setter(loc, typeInfo.srcValues);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " without srcOffset / srcLength");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValues, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = 0");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValues, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = 0 / srcLength = 0");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValuesWithOffset, typeInfo.srcOffset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = " + typeInfo.srcOffset);
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValuesWithOffset, typeInfo.srcOffset, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = " + typeInfo.srcOffset + " / srcLength = 0");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValuesWithOffsetAndLength, typeInfo.srcOffset, srcLength);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = " + typeInfo.srcOffset + " / srcLength = " + srcLength);
+ checkUniformValues(program, typeInfo);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors");
+
+ // Negative tests
+ setter(loc, typeInfo.srcValues, typeInfo.srcValues.length + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with srcOffset out-of-bounds");
+
+ setter(loc, typeInfo.srcValues, 0, typeInfo.srcValues.length + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with srcLength out-of-bounds");
+
+ setter(loc, typeInfo.srcValues, typeInfo.srcOffset, srcLength);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with srcOffset + srcLength out-of-bounds");
+
+ setter(loc, typeInfo.srcValues, typeInfo.srcValues.length);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with 0 data");
+
+ if (typeInfo.numElementsPerType > 1) {
+ setter(loc, typeInfo.srcValuesWithOffsetAndLength, typeInfo.srcOffset);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with array length minus srcOffset not multiple of " + typeInfo.type);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html
new file mode 100644
index 0000000000..90cb54317a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html
@@ -0,0 +1,335 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform samplers with incompatible texture formats tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+ gl_PointSize = 1.0;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Test that using an incompatible texture type generates INVALID_OPERATION at draw time");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function makeFragmentShader(samplerType, uvType) {
+ return `#version 300 es
+ precision mediump float;
+ uniform mediump ${samplerType} u_tex;
+ out vec4 color;
+ void main() {
+ color = vec4(texture(u_tex, ${uvType}));
+ }
+ `;
+}
+
+// Sampler types.
+const FLOAT = 1;
+const SIGNED = 2;
+const UNSIGNED = 3;
+const SHADOW = 4;
+
+const textureInternalFormatInfo = {};
+{
+ const t = textureInternalFormatInfo;
+ // unsized formats
+ t[gl.ALPHA] = { textureFormat: gl.ALPHA, samplerType: FLOAT, depth: false, bytesPerElement: [1, 2, 2, 4], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.LUMINANCE] = { textureFormat: gl.LUMINANCE, samplerType: FLOAT, depth: false, bytesPerElement: [1, 2, 2, 4], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.LUMINANCE_ALPHA] = { textureFormat: gl.LUMINANCE_ALPHA, samplerType: FLOAT, depth: false, bytesPerElement: [2, 4, 4, 8], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.RGB] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3, 6, 6, 12, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_5_6_5], };
+ t[gl.RGBA] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4, 8, 8, 16, 2, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_4_4_4_4, gl.UNSIGNED_SHORT_5_5_5_1], };
+
+ // sized formats
+ t[gl.R8] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [1], type: [gl.UNSIGNED_BYTE], };
+ t[gl.R8_SNORM] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [1], type: [gl.BYTE], };
+ t[gl.R16F] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [4, 2], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.R32F] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.FLOAT], };
+ t[gl.R8UI] = { textureFormat: gl.RED_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [1], type: [gl.UNSIGNED_BYTE], };
+ t[gl.R8I] = { textureFormat: gl.RED_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [1], type: [gl.BYTE], };
+ t[gl.R16UI] = { textureFormat: gl.RED_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [2], type: [gl.UNSIGNED_SHORT], };
+ t[gl.R16I] = { textureFormat: gl.RED_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [2], type: [gl.SHORT], };
+ t[gl.R32UI] = { textureFormat: gl.RED_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT], };
+ t[gl.R32I] = { textureFormat: gl.RED_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [4], type: [gl.INT], };
+ t[gl.RG8] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [2], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RG8_SNORM] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [2], type: [gl.BYTE], };
+ t[gl.RG16F] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [8, 4], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RG32F] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [8], type: [gl.FLOAT], };
+ t[gl.RG8UI] = { textureFormat: gl.RG_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [2], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RG8I] = { textureFormat: gl.RG_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [2], type: [gl.BYTE], };
+ t[gl.RG16UI] = { textureFormat: gl.RG_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RG16I] = { textureFormat: gl.RG_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [4], type: [gl.SHORT], };
+ t[gl.RG32UI] = { textureFormat: gl.RG_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [8], type: [gl.UNSIGNED_INT], };
+ t[gl.RG32I] = { textureFormat: gl.RG_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [8], type: [gl.INT], };
+ t[gl.RGB8] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.SRGB8] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGB565] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3, 2], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_6_5], };
+ t[gl.RGB8_SNORM] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3], type: [gl.BYTE], };
+ t[gl.R11F_G11F_B10F] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_10F_11F_11F_REV], };
+ t[gl.RGB9_E5] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_5_9_9_9_REV], };
+ t[gl.RGB16F] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12, 6], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RGB32F] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12], type: [gl.FLOAT], };
+ t[gl.RGB8UI] = { textureFormat: gl.RGB_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGB8I] = { textureFormat: gl.RGB_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [3], type: [gl.BYTE], };
+ t[gl.RGB16UI] = { textureFormat: gl.RGB_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [6], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RGB16I] = { textureFormat: gl.RGB_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [6], type: [gl.SHORT], };
+ t[gl.RGB32UI] = { textureFormat: gl.RGB_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [12], type: [gl.UNSIGNED_INT], };
+ t[gl.RGB32I] = { textureFormat: gl.RGB_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [12], type: [gl.INT], };
+ t[gl.RGBA8] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.SRGB8_ALPHA8] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGBA8_SNORM] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.BYTE], };
+ t[gl.RGB5_A1] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4, 2, 4], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_5_5_1, gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA4] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4, 2], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_4_4_4_4], };
+ t[gl.RGB10_A2] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA16F] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [16, 8], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RGBA32F] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [16], type: [gl.FLOAT], };
+ t[gl.RGBA8UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGBA8I] = { textureFormat: gl.RGBA_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [4], type: [gl.BYTE], };
+ t[gl.RGB10_A2UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA16UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [8], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RGBA16I] = { textureFormat: gl.RGBA_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [8], type: [gl.SHORT], };
+ t[gl.RGBA32I] = { textureFormat: gl.RGBA_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [16], type: [gl.INT], };
+ t[gl.RGBA32UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [16], type: [gl.UNSIGNED_INT], };
+
+ // Sized Internal
+ // Note that samplerType is FLOAT for depth formats, not SHADOW. Shadow
+ // samplers are handled as a special case in the test code because they have
+ // special rules about TEXTURE_COMPARE_MODE.
+ t[gl.DEPTH_COMPONENT16] = { textureFormat: gl.DEPTH_COMPONENT, samplerType: FLOAT, depth: true, bytesPerElement: [2, 4], type: [gl.UNSIGNED_SHORT, gl.UNSIGNED_INT], };
+ t[gl.DEPTH_COMPONENT24] = { textureFormat: gl.DEPTH_COMPONENT, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.UNSIGNED_INT], };
+ t[gl.DEPTH_COMPONENT32F] = { textureFormat: gl.DEPTH_COMPONENT, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.FLOAT], };
+ t[gl.DEPTH24_STENCIL8] = { textureFormat: gl.DEPTH_STENCIL, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.UNSIGNED_INT_24_8], };
+ t[gl.DEPTH32F_STENCIL8] = { textureFormat: gl.DEPTH_STENCIL, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.FLOAT_32_UNSIGNED_INT_24_8_REV], };
+
+ // TODO: Compressed formats.
+
+ Object.keys(t).forEach(function(internalFormat) {
+ const info = t[internalFormat];
+ info.bytesPerElementMap = {};
+ info.bytesPerElement.forEach(function(bytesPerElement, ndx) {
+ const type = info.type[ndx];
+ info.bytesPerElementMap[type] = bytesPerElement;
+ });
+ });
+}
+
+const floatSamplerTypes = [
+ { type: 'sampler2D', uvType: 'vec2(0)', target: gl.TEXTURE_2D, },
+ { type: 'sampler3D', uvType: 'vec3(0)', target: gl.TEXTURE_3D, },
+ { type: 'samplerCube', uvType: 'vec3(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'sampler2DArray', uvType: 'vec3(0)', target: gl.TEXTURE_2D_ARRAY, },
+];
+
+const signedIntSamplerTypes = [
+ { type: 'isampler2D', uvType: 'vec2(0)', target: gl.TEXTURE_2D, },
+ { type: 'isampler3D', uvType: 'vec3(0)', target: gl.TEXTURE_3D, },
+ { type: 'isamplerCube', uvType: 'vec3(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'isampler2DArray', uvType: 'vec3(0)', target: gl.TEXTURE_2D_ARRAY, },
+];
+
+const unsignedIntSamplerTypes = [
+ { type: 'usampler2D', uvType: 'vec2(0)', target: gl.TEXTURE_2D, },
+ { type: 'usampler3D', uvType: 'vec3(0)', target: gl.TEXTURE_3D, },
+ { type: 'usamplerCube', uvType: 'vec3(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'usampler2DArray', uvType: 'vec3(0)', target: gl.TEXTURE_2D_ARRAY, },
+];
+
+const shadowSamplerTypes = [
+ { type: 'sampler2DShadow', uvType: 'vec3(0)', target: gl.TEXTURE_2D, },
+ { type: 'samplerCubeShadow', uvType: 'vec4(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'sampler2DArrayShadow', uvType: 'vec4(0)', target: gl.TEXTURE_2D_ARRAY, },
+]
+
+/**
+ * Gets the number of bytes per element for a given internalFormat / type
+ * @param {number} internalFormat The internalFormat parameter from texImage2D etc..
+ * @param {number} type The type parameter for texImage2D etc..
+ * @return {number} the number of bytes per element for the given internalFormat, type combo
+ * @memberOf module:twgl/textures
+ */
+function getBytesPerElementForInternalFormat(internalFormat, type) {
+ const info = textureInternalFormatInfo[internalFormat];
+ if (!info) {
+ throw "unknown internal format";
+ }
+ const bytesPerElement = info.bytesPerElementMap[type];
+ if (bytesPerElement === undefined) {
+ throw "unknown internal format";
+ }
+ return bytesPerElement;
+}
+
+function make2DTexture(target, internalFormat, format, type) {
+ gl.texImage2D(target, 0, internalFormat, 1, 1, 0, format, type, null);
+}
+
+function make3DTexture(target, internalFormat, format, type) {
+ gl.texImage3D(target, 0, internalFormat, 1, 1, 1, 0, format, type, null);
+}
+
+function makeCubeMapTexture(target, internalFormat, format, type) {
+ [
+ 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,
+ ].forEach(function(target) {
+ gl.texImage2D(target, 0, internalFormat, 1, 1, 0, format, type, null);
+ });
+}
+
+function runTest() {
+ const targets = {};
+ targets[gl.TEXTURE_2D] = { fn: make2DTexture, },
+ targets[gl.TEXTURE_3D] = { fn: make3DTexture, },
+ targets[gl.TEXTURE_CUBE_MAP] = { fn: makeCubeMapTexture, },
+ targets[gl.TEXTURE_2D_ARRAY] = { fn: make3DTexture, },
+
+ Object.keys(targets).forEach(function(target) {
+ target = parseInt(target);
+ const targetInfo = targets[target];
+ targetInfo.textures = [];
+ Object.keys(textureInternalFormatInfo).forEach(function(internalFormat) {
+ internalFormat = parseInt(internalFormat);
+ const isDepthFormat = textureInternalFormatInfo[internalFormat].depth;
+ if (target === gl.TEXTURE_3D && isDepthFormat) {
+ return;
+ }
+ const info = textureInternalFormatInfo[internalFormat];
+ const texture = gl.createTexture();
+ gl.bindTexture(target, texture);
+ targetInfo.fn(target, internalFormat, info.textureFormat, info.type[0]);
+ targetInfo.textures.push({
+ internalFormat: internalFormat,
+ texture: texture,
+ });
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from setup for ${wtu.glEnumToString(gl, target)} ${wtu.glEnumToString(gl, internalFormat)}`);
+ });
+ });
+
+ const samplerObject = gl.createSampler();
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+
+ // The rules implemented here are:
+
+ // Float samplers accept only float textures and normalized integer textures
+ // (signed or unsigned) and depth textures with TEXTURE_COMPARE_MODE set to
+ // NONE.
+
+ // Signed samplers accept only signed unnormalized integer textures.
+
+ // Unsigned samplers accept only unsigned unnormalized integer textures.
+
+ // Shadow samplers accept only depth textures with
+ // TEXTURE_COMPARE_MODE set to COMPARE_REF_TO_TEXTURE.
+
+ testSamplerType(FLOAT, floatSamplerTypes);
+ testSamplerType(SIGNED, signedIntSamplerTypes);
+ testSamplerType(UNSIGNED, unsignedIntSamplerTypes);
+ testSamplerType(SHADOW, shadowSamplerTypes);
+
+ function testSamplerType(samplerType, samplerInfos) {
+ samplerInfos.forEach(function(samplerInfo) {
+ debug(`\nchecking ${samplerInfo.type}`);
+ const program = wtu.setupProgram(gl, ['vshader', makeFragmentShader(samplerInfo.type, samplerInfo.uvType)], [], console.log.bind(console));
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ const target = samplerInfo.target;
+ const targetInfo = targets[target];
+ targetInfo.textures.forEach(function(textureInfo) {
+ const internalFormat = textureInfo.internalFormat;
+ const desc = wtu.glEnumToString(gl, internalFormat);
+ const info = textureInternalFormatInfo[internalFormat];
+
+ // The texture object can have two values of TEXTURE_COMPARE_MODE: NONE or
+ // COMPARE_REF_TO_TEXTURE. However, the sampler can have three states:
+ // No sampler object bound, sampler object with NONE, and sampler object with
+ // COMPARE_REF_TO_TEXTURE. When a sampler object is bound, it overrides the
+ // texture object's state. We test 2*3=6 possible combinations of state.
+
+ // First test the three states that result in TEXTURE_COMPARE_MODE being NONE.
+ let expected = samplerType == info.samplerType ? gl.NONE : gl.INVALID_OPERATION;
+ gl.bindTexture(target, textureInfo.texture);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state NONE, no sampler object`);
+
+ gl.bindSampler(0, samplerObject);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state NONE, sampler state NONE`);
+
+ gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state COMPARE_REF_TO_TEXTURE, sampler state NONE`);
+
+ // Now test test the three states that result in TEXTURE_COMPARE_MODE being COMPARE_REF_TO_TEXTURE.
+ if (info.depth) {
+ expected = samplerType == SHADOW ? gl.NONE : gl.INVALID_OPERATION;
+ }
+ gl.bindSampler(0, null);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state COMPARE_REF_TO_TEXTURE, no sampler object`);
+
+ gl.bindSampler(0, samplerObject);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state COMPARE_REF_TO_TEXTURE, sampler state COMPARE_REF_TO_TEXTURE`);
+
+ gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state NONE, sampler state COMPARE_REF_TO_TEXTURE`);
+ gl.bindSampler(0, null);
+ });
+ });
+ };
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html
new file mode 100644
index 0000000000..5e67195ea8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html
@@ -0,0 +1,138 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL large uniform buffers conformance tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+description("Test for UBOs sized over 65536 - https://bugs.chromium.org/p/angleproject/issues/detail?id=3388");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ var uboBuf = gl.createBuffer();
+ var uboData = new Float32Array(0x20000);
+
+ var offs0 = 0x00000;
+ // Red
+ uboData[offs0 + 0] = 1;
+ uboData[offs0 + 1] = 0;
+ uboData[offs0 + 2] = 0;
+ uboData[offs0 + 3] = 1;
+
+ var offs1 = 0x10000;
+ const alignment = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ if (offs1 % alignment != 0)
+ testFailed("Platform has a strange uniform buffer offset alignment requirement: " + alignment);
+
+ // Green
+ uboData[offs1 + 0] = 0;
+ uboData[offs1 + 1] = 1;
+ uboData[offs1 + 2] = 0;
+ uboData[offs1 + 3] = 1;
+
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboData, gl.STATIC_DRAW);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, uboBuf, offs0 * 4, 0x10);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ debug("draw upper triangle - should be green");
+ var uboBuf2 = gl.createBuffer();
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, uboBuf, offs1 * 4, 0x10);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html
new file mode 100644
index 0000000000..24c7060e5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html
@@ -0,0 +1,93 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Uniform Buffers Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+
+in vec4 position;
+
+uniform localInputs
+{
+ mat4 projectionModelViewMatrix;
+};
+
+void main ()
+{
+ gl_Position = projectionModelViewMatrix * position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+
+out lowp vec4 resultColor;
+
+void main()
+{
+ resultColor = vec4(0,1,0,1);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+// Adopted from the test case provided in crbug.com/735784
+"use strict";
+description("This tests UBO block lookups still work after detaching shaders");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+function runTest(gl) {
+ var program = wtu.loadProgramFromScript(gl, "vshader", "fshader");
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+
+ var shaders = gl.getAttachedShaders(program);
+ if (!shaders || shaders.length != 2) {
+ testFailed("getAttachedShaders failed");
+ return;
+ }
+ gl.detachShader (program, shaders[0]);
+ gl.detachShader (program, shaders[1]);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ var index = gl.getUniformBlockIndex(program, "localInputs");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from getUniformBlockIndex");
+ if (index == gl.INVALID_INDEX) {
+ testFailed("getUniformBlockIndex returns INVALID_INDEX");
+ } else {
+ testPassed("getUniformBlockIndex returns valid index");
+ }
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ runTest(gl);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html
new file mode 100644
index 0000000000..c5646faae8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html
@@ -0,0 +1,122 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL draw with uniform blocks conformance tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+// Ported from: https://github.com/google/angle/blob/master/src/tests/gl_tests/UniformBufferTest.cpp#L1463
+description("Regression test for https://bugs.chromium.org/p/chromium/issues/detail?id=792966");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ var uboBuf1 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 1, 0, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ // Bind a second buffer to the same binding point (0). This should set to draw green.
+ debug("draw upper triangle - should be green");
+ var uboBuf2 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf2);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 0, 1, 0, 1 ]));
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html
new file mode 100644
index 0000000000..2d40a62c00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html
@@ -0,0 +1,115 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL uniform blocks containing arrays conformance tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshaderArraysOfStructs" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+struct light_t {
+ vec4 intensity;
+};
+const int maxLights = 2;
+layout(std140) uniform lightData { light_t lights[maxLights]; };
+vec4 processLight(vec4 lighting, light_t light)
+{
+ return lighting + light.intensity;
+}
+void main()
+{
+ vec4 lighting = vec4(0, 1, 0, 1);
+ for (int n = 0; n < maxLights; n++)
+ lighting = processLight(lighting, lights[n]);
+ my_FragColor = lighting;
+}
+</script>
+<script id="fshaderArraysOfStructsContainingArrays" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+struct light_t {
+ vec4 intensity[3];
+};
+const int maxLights = 2;
+layout(std140) uniform lightData { light_t lights[maxLights]; };
+vec4 processLight(vec4 lighting, light_t light)
+{
+ return lighting + light.intensity[1];
+}
+void main()
+{
+ vec4 lighting = vec4(0, 1, 0, 1);
+ for (int n = 0; n < maxLights; n++)
+ lighting = processLight(lighting, lights[n]);
+ my_FragColor = lighting;
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+// GLSL ES 3.00.6 section 4.3.7:
+// "Otherwise, built-in types, previously declared structures, and arrays of these are allowed as the type of a declarator in the same manner they are allowed outside a block."
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+function runTest(fragShader, bufferFloatCount, shaderBlockDescription) {
+ debug('');
+ debug('Testing fragment shader with an uniform block containing ' + shaderBlockDescription);
+ var program = wtu.setupProgram(gl, ['vshader', fragShader], ['vPosition'], undefined, true);
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+ var blockIndex = gl.getUniformBlockIndex(program, "lightData");
+
+ var uniformBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, uniformBuffer);
+ gl.bufferData(gl.UNIFORM_BUFFER, new Float32Array(bufferFloatCount), gl.DYNAMIC_READ);
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uniformBuffer);
+ gl.uniformBlockBinding(program, blockIndex, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from uniform buffer setup");
+
+ wtu.clearAndDrawUnitQuad(gl);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ wtu.checkCanvas(gl, [0, 255, 0, 255], 'should be green', 1);
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ wtu.setupUnitQuad(gl);
+ runTest("fshaderArraysOfStructs", 2 * 4, 'arrays of structs');
+ runTest("fshaderArraysOfStructsContainingArrays", 2 * 3 * 4, 'arrays of structs containing arrays');
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/00_test_list.txt
new file mode 100644
index 0000000000..8ce1225636
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/00_test_list.txt
@@ -0,0 +1,2 @@
+vertex-array-object.html
+--min-version 2.0.1 vertex-array-object-and-disabled-attributes.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object-and-disabled-attributes.html b/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object-and-disabled-attributes.html
new file mode 100644
index 0000000000..08abba728c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object-and-disabled-attributes.html
@@ -0,0 +1,132 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL 2 Disabled Vertex Array Object and Disabled Attributes Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="singlevshader" type="x-shader/x-vertex">
+attribute vec4 position;
+void main() {
+ gl_Position = position;
+}
+</script>
+
+<script id="singlefshader" type="x-shader/x-fragment">
+void main() {
+ gl_FragColor = vec4(1, 0, 0, 1);
+}
+</script>
+<script id="dualvshader" type="x-shader/x-vertex">#version 300 es
+in vec4 position;
+in vec4 color;
+out vec4 varyColor;
+void main() {
+ gl_Position = position;
+ varyColor = color;
+}
+</script>
+<script id="dualfshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+in vec4 varyColor;
+out vec4 colorOut;
+void main() {
+ colorOut = varyColor;
+}
+</script>
+
+<script>
+// Test that switching VAOs keeps the disabled "current value" attributes up-to-date.
+// Based on ANGLE test (StateChangeTestES3, VertexArrayObjectAndDisabledAttributes) from https://github.com/google/angle/blob/f7f0b8c3ab21c52cc2915048959361cf628d95f0/src/tests/gl_tests/StateChangeTest.cpp
+"use strict";
+var wtu = WebGLTestUtils;
+description();
+
+var gl = wtu.create3DContext("example", undefined, 2);
+
+// Location of "position" attribute must match between shaders.
+var singleProgram = wtu.setupProgram(gl, ['singlevshader', 'singlefshader'], ['position'], [0]);
+var dualProgram = wtu.setupProgram(gl, ['dualvshader', 'dualfshader'], ['position'], [0]);
+
+var positionLocation = gl.getAttribLocation(dualProgram, "position");
+var colorLocation = gl.getAttribLocation(dualProgram, "color");
+var singlePositionLocation = gl.getAttribLocation(singleProgram, "position");
+
+
+gl.useProgram(singleProgram);
+
+var positions = new Float32Array([
+ -1, 1,
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, -1,
+ 1, 1
+]);
+
+var positionBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+
+var vertexArray = gl.createVertexArray();
+gl.bindVertexArray(vertexArray);
+
+gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+gl.vertexAttribPointer(singlePositionLocation, 2, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(singlePositionLocation);
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+gl.bindVertexArray(null);
+gl.useProgram(dualProgram);
+gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(positionLocation);
+
+var greenBuffer = gl.createBuffer();
+var green = new Uint8Array(4 * 6);
+
+for (var i = 0; i < 6; ++i) {
+ var ci = i * 4;
+
+ green[ci] = 0;
+ green[ci + 1] = 255;
+ green[ci + 2] = 0;
+ green[ci + 3] = 255;
+}
+
+gl.bindBuffer(gl.ARRAY_BUFFER, greenBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, green, gl.STATIC_DRAW);
+gl.vertexAttribPointer(colorLocation, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+gl.enableVertexAttribArray(colorLocation);
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+
+gl.bindVertexArray(vertexArray);
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+wtu.checkCanvas(gl, [0, 0, 0, 255], "should be black");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object.html b/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object.html
new file mode 100644
index 0000000000..160a7f4ea6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/vertex_arrays/vertex-array-object.html
@@ -0,0 +1,671 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL vertex_array_object Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 a_position;
+attribute vec4 a_color;
+varying vec4 v_color;
+void main(void) {
+ gl_Position = a_position;
+ v_color = a_color;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main(void) {
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+description("This test verifies the functionality of the Vertex Array Objects.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+var vao = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runBindingTest();
+ runObjectTest();
+ runAttributeTests();
+ runAttributeValueTests();
+ runDrawTests();
+ runUnboundDeleteTests();
+ runBoundDeleteTests();
+ runArrayBufferBindTests();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runBindingTest() {
+ debug("Testing binding enum");
+
+ shouldBe("gl.VERTEX_ARRAY_BINDING", "0x85B5");
+
+ gl.getParameter(gl.VERTEX_ARRAY_BINDING);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "VERTEX_ARRAY_BINDING query should succeed");
+
+ // Default value is null
+ if (gl.getParameter(gl.VERTEX_ARRAY_BINDING) === null) {
+ testPassed("Default value of VERTEX_ARRAY_BINDING is null");
+ } else {
+ testFailed("Default value of VERTEX_ARRAY_BINDING is not null");
+ }
+
+ debug("Testing binding a VAO");
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+ shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)");
+ gl.bindVertexArray(vao0);
+ if (gl.getParameter(gl.VERTEX_ARRAY_BINDING) == vao0) {
+ testPassed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is expected VAO");
+ } else {
+ testFailed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is not expected VAO")
+ }
+ gl.bindVertexArray(vao1);
+ if (gl.getParameter(gl.VERTEX_ARRAY_BINDING) == vao1) {
+ testPassed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is expected VAO");
+ } else {
+ testFailed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is not expected VAO")
+ }
+ gl.deleteVertexArray(vao1);
+ shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)");
+ gl.bindVertexArray(vao1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted vertex array object");
+ gl.bindVertexArray(null);
+ shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)");
+ gl.deleteVertexArray(vao1);
+}
+
+function runObjectTest() {
+ debug("Testing object creation");
+
+ vao = gl.createVertexArray();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createVertexArray should not set an error");
+ shouldBeNonNull("vao");
+
+ // Expect false if never bound
+ shouldBeFalse("gl.isVertexArray(vao)");
+ gl.bindVertexArray(vao);
+ shouldBeTrue("gl.isVertexArray(vao)");
+ gl.bindVertexArray(null);
+ shouldBeTrue("gl.isVertexArray(vao)");
+
+ shouldBeFalse("gl.isVertexArray(null)");
+
+ gl.deleteVertexArray(vao);
+ vao = null;
+}
+
+function runAttributeTests() {
+ debug("Testing attributes work across bindings");
+
+ var states = [];
+
+ var attrCount = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+ for (var n = 0; n < attrCount; n++) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+
+ var state = {};
+ states.push(state);
+
+ var vao = state.vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+
+ var enableArray = (n % 2 == 0);
+ if (enableArray) {
+ gl.enableVertexAttribArray(n);
+ } else {
+ gl.disableVertexAttribArray(n);
+ }
+
+ if (enableArray) {
+ var buffer = state.buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(n, 1 + n % 4, gl.FLOAT, true, n * 4, n * 4);
+ }
+
+ if (enableArray) {
+ var elbuffer = state.elbuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elbuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
+ }
+
+ gl.bindVertexArray(null);
+ }
+
+ var anyMismatch = false;
+ for (var n = 0; n < attrCount; n++) {
+ var state = states[n];
+
+ gl.bindVertexArray(state.vao);
+
+ var shouldBeEnabled = (n % 2 == 0);
+ var isEnabled = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
+ if (shouldBeEnabled != isEnabled) {
+ testFailed("VERTEX_ATTRIB_ARRAY_ENABLED not preserved");
+ anyMismatch = true;
+ }
+
+ var buffer = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ if (shouldBeEnabled) {
+ if (buffer == state.buffer) {
+ // Matched
+ if ((gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_SIZE) == 1 + n % 4) &&
+ (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_TYPE) == gl.FLOAT) &&
+ (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED) == true) &&
+ (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_STRIDE) == n * 4) &&
+ (gl.getVertexAttribOffset(n, gl.VERTEX_ATTRIB_ARRAY_POINTER) == n * 4)) {
+ // Matched
+ } else {
+ testFailed("VERTEX_ATTRIB_ARRAY_* not preserved");
+ anyMismatch = true;
+ }
+ } else {
+ testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ } else {
+ // GL_CURRENT_VERTEX_ATTRIB is not preserved
+ if (buffer) {
+ testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ }
+
+ var elbuffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
+ if (shouldBeEnabled) {
+ if (elbuffer == state.elbuffer) {
+ // Matched
+ } else {
+ testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ } else {
+ if (elbuffer == null) {
+ // Matched
+ } else {
+ testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
+ anyMismatch = true;
+ }
+ }
+ }
+ gl.bindVertexArray(null);
+ if (!anyMismatch) {
+ testPassed("All attributes preserved across bindings");
+ }
+
+ for (var n = 0; n < attrCount; n++) {
+ var state = states[n];
+ gl.deleteVertexArray(state.vao);
+ }
+}
+
+function runAttributeValueTests() {
+ debug("Testing that attribute values are not attached to bindings");
+
+ var v;
+ var vao0 = gl.createVertexArray();
+ var anyFailed = false;
+
+ gl.bindVertexArray(null);
+ gl.vertexAttrib4f(0, 0, 1, 2, 3);
+
+ v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
+ if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) {
+ testFailed("Vertex attrib value not round-tripped?");
+ anyFailed = true;
+ }
+
+ gl.bindVertexArray(vao0);
+
+ v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
+ if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) {
+ testFailed("Vertex attrib value reset across bindings");
+ anyFailed = true;
+ }
+
+ gl.vertexAttrib4f(0, 4, 5, 6, 7);
+ gl.bindVertexArray(null);
+
+ v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
+ if (!(v[0] == 4 && v[1] == 5 && v[2] == 6 && v[3] == 7)) {
+ testFailed("Vertex attrib value bound to buffer");
+ anyFailed = true;
+ }
+
+ if (!anyFailed) {
+ testPassed("Vertex attribute values are not attached to bindings")
+ }
+
+ gl.bindVertexArray(null);
+ gl.deleteVertexArray(vao0);
+}
+
+function runDrawTests() {
+ debug("Testing draws with various VAO bindings");
+
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ var opt_positionLocation = 0;
+ var opt_texcoordLocation = 1;
+
+ var program = wtu.setupSimpleTextureProgram(gl, opt_positionLocation, opt_texcoordLocation);
+
+ function setupQuad(s) {
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0 * s, 1.0 * s, 0.0,
+ -1.0 * s, 1.0 * s, 0.0,
+ -1.0 * s, -1.0 * s, 0.0,
+ 1.0 * s, 1.0 * s, 0.0,
+ -1.0 * s, -1.0 * s, 0.0,
+ 1.0 * s, -1.0 * s, 0.0]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(opt_positionLocation);
+ gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0 * s, 1.0 * s,
+ 0.0 * s, 1.0 * s,
+ 0.0 * s, 0.0 * s,
+ 1.0 * s, 1.0 * s,
+ 0.0 * s, 0.0 * s,
+ 1.0 * s, 0.0 * s]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(opt_texcoordLocation);
+ gl.vertexAttribPointer(opt_texcoordLocation, 2, gl.FLOAT, false, 0, 0);
+ };
+
+ function readLocation(x, y) {
+ var pixels = new Uint8Array(1 * 1 * 4);
+ gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ return pixels;
+ };
+ function testPixel(blockList, allowList) {
+ function testList(list, expected) {
+ for (var n = 0; n < list.length; n++) {
+ var l = list[n];
+ var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2;
+ var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2;
+ var source = readLocation(x, y);
+ if (Math.abs(source[0] - expected) > 2) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return testList(blockList, 0) && testList(allowList, 255);
+ };
+ function verifyDraw(drawNumber, s) {
+ wtu.clearAndDrawUnitQuad(gl);
+ var blockList = [];
+ var allowList = [];
+ var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
+ for (var n = 0; n < points.length; n++) {
+ if (points[n] <= s) {
+ blockList.push(points[n]);
+ } else {
+ allowList.push(points[n]);
+ }
+ }
+ if (testPixel(blockList, allowList)) {
+ testPassed("Draw " + drawNumber + " passed pixel test");
+ } else {
+ testFailed("Draw " + drawNumber + " failed pixel test");
+ }
+ };
+
+ // Setup all bindings
+ setupQuad(1);
+ gl.bindVertexArray(vao0);
+ setupQuad(0.5);
+ gl.bindVertexArray(vao1);
+ setupQuad(0.25);
+
+ // Verify drawing
+ gl.bindVertexArray(null);
+ verifyDraw(0, 1);
+ gl.bindVertexArray(vao0);
+ verifyDraw(1, 0.5);
+ gl.bindVertexArray(vao1);
+ verifyDraw(2, 0.25);
+
+ gl.bindVertexArray(null);
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+
+ // Disable global vertex attrib array
+ gl.disableVertexAttribArray(opt_positionLocation);
+ gl.disableVertexAttribArray(opt_texcoordLocation);
+
+ // Draw with values.
+ var positionLoc = 0;
+ var colorLoc = 1;
+ var gridRes = 1;
+ wtu.setupIndexedQuad(gl, gridRes, positionLoc);
+ // Set the vertex color to red.
+ gl.vertexAttrib4f(colorLoc, 1, 0, 0, 1);
+
+ var vao0 = gl.createVertexArray();
+ gl.bindVertexArray(vao0);
+ var program = wtu.setupSimpleVertexColorProgram(gl, positionLoc, colorLoc);
+ wtu.setupIndexedQuad(gl, gridRes, positionLoc);
+ // Set the vertex color to green.
+ gl.vertexAttrib4f(colorLoc, 0, 1, 0, 1);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green")
+ gl.deleteVertexArray(vao0);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green")
+}
+
+function runUnboundDeleteTests() {
+ debug("Testing using buffers that are deleted when attached to unbound VAOs");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+ gl.useProgram(program);
+
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]),
+ gl.STATIC_DRAW);
+
+ var colors = [
+ [255, 0, 0, 255],
+ [ 0, 255, 0, 255],
+ [ 0, 0, 255, 255],
+ [ 0, 255, 255, 255]
+ ];
+ var colorBuffers = [];
+ var elementBuffers = [];
+ var vaos = [];
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var vao = gl.createVertexArray();
+ vaos.push(vao);
+ gl.bindVertexArray(vao);
+ // Set the position buffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var elementBuffer = gl.createBuffer();
+ elementBuffers.push(elementBuffer);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 0, 2, 3]),
+ gl.STATIC_DRAW);
+
+ // Setup the color attrib
+ var color = colors[ii];
+ if (ii < 3) {
+ var colorBuffer = gl.createBuffer();
+ colorBuffers.push(colorBuffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3]
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ } else {
+ gl.vertexAttrib4f(1, color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
+ }
+ }
+
+ // delete the color buffers AND the position buffer.
+ gl.bindVertexArray(null);
+ for (var ii = 0; ii < colorBuffers.length; ++ii) {
+ gl.deleteBuffer(colorBuffers[ii]);
+ gl.deleteBuffer(elementBuffers[ii]);
+ gl.bindVertexArray(vaos[ii]);
+ var boundBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ // The buffers should still be valid at this point, since it was attached to the VAO
+ if(boundBuffer != colorBuffers[ii]) {
+ testFailed("buffer removed too early");
+ }
+ }
+ gl.bindVertexArray(null);
+ gl.deleteBuffer(positionBuffer);
+
+ // Render with the deleted buffers. As they are referenced by VAOs they
+ // must still be around.
+ for (var ii = 0; ii < colors.length; ++ii) {
+ var color = colors[ii];
+ gl.bindVertexArray(vaos[ii]);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, color, "should be " + color);
+ }
+
+ // Clean up.
+ for (var ii = 0; ii < colorBuffers.length; ++ii) {
+ gl.deleteVertexArray(vaos[ii]);
+ }
+
+ for (var ii = 0; ii < colorBuffers.length; ++ii) {
+ // The buffers should no longer be valid now that the VAOs are deleted
+ if(gl.isBuffer(colorBuffers[ii])) {
+ testFailed("buffer not properly cleaned up after VAO deletion");
+ }
+ }
+}
+
+function runBoundDeleteTests() {
+ debug("Testing using buffers that are deleted when attached to bound VAOs");
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+ gl.useProgram(program);
+
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]),
+ gl.STATIC_DRAW);
+
+ // Setup the color attrib
+ var colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 0, 255, 255,
+ 0, 255, 255, 255
+ ]), gl.STATIC_DRAW);
+
+ var vaos = [];
+ var elementBuffers = [];
+ for (var ii = 0; ii < 4; ++ii) {
+ var vao = gl.createVertexArray();
+ vaos.push(vao);
+ gl.bindVertexArray(vao);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ var elementBuffer = gl.createBuffer();
+ elementBuffers.push(elementBuffer);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 0, 2, 3]),
+ gl.STATIC_DRAW);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ }
+
+ // delete the color buffers AND the position buffer, that are bound to the current VAO
+ for (var ii = 0; ii < vaos.length; ++ii) {
+ gl.bindVertexArray(vaos[ii]);
+
+ gl.deleteBuffer(colorBuffer);
+ gl.deleteBuffer(positionBuffer);
+
+ // After the first iteration, deleteBuffer will be a no-op, and will not unbind its matching
+ // bind points on the now-bound VAO like it did on the first iteration.
+ var expectRetained = (ii != 0);
+ var shouldBeStr = (expectRetained ? "retained" : "cleared");
+
+ var boundPositionBuffer = gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ if (expectRetained != (boundPositionBuffer == positionBuffer)) {
+ testFailed("Position attrib stored buffer should be " + shouldBeStr + ".");
+ }
+
+ var boundColorBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ if (expectRetained != (boundColorBuffer == colorBuffer)) {
+ testFailed("Color attrib stored buffer should be " + shouldBeStr + ".");
+ }
+
+ // If retained, everything should still work. If cleared, drawing should now fail.
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ var expectedError = (expectRetained ? gl.NO_ERROR : gl.INVALID_OPERATION);
+ wtu.glErrorShouldBe(gl, expectedError,
+ "Draw call should " + (expectRetained ? "not " : "") + "fail.");
+
+ if (gl.isBuffer(positionBuffer)) {
+ testFailed("References from unbound VAOs don't keep Position buffer alive.");
+ }
+ if (gl.isBuffer(colorBuffer)) {
+ testFailed("References from unbound VAOs don't keep Color buffer alive");
+ }
+ }
+}
+
+function runArrayBufferBindTests() {
+ debug("Testing that VAOs don't effect ARRAY_BUFFER binding.");
+
+ gl.bindVertexArray(null);
+
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_color", "a_position"]);
+ gl.useProgram(program);
+
+ // create shared element buuffer
+ var elementBuffer = gl.createBuffer();
+ // bind to default
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.bufferData(
+ gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 0, 2, 3]),
+ gl.STATIC_DRAW);
+
+ // first create the buffers for no vao draw.
+ var nonVAOColorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ ]), gl.STATIC_DRAW);
+
+ // shared position buffer.
+ var positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0]),
+ gl.STATIC_DRAW);
+
+ // attach position buffer to default
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ // now create vao
+ var vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+
+ // attach the position buffer vao
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ var vaoColorBuffer = gl.createBuffer();
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, vaoColorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
+ [ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+
+ // now set the buffer back to the nonVAOColorBuffer
+ gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer);
+
+ // bind to vao
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+ // unbind vao
+ gl.bindVertexArray(null);
+
+ // At this point the nonVAOColorBuffer should be still be bound.
+ // If the WebGL impl is emulating VAOs it must make sure
+ // it correctly restores this binding.
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/00_test_list.txt
new file mode 100644
index 0000000000..32ec5067a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/00_test_list.txt
@@ -0,0 +1,7 @@
+// files that end in .txt list other tests
+// other lines are assumed to be .html files
+
+--min-version 1.0.4 --max-version 1.9.9 data/gles2/shaders/00_test_list.txt
+--min-version 2.0.0 data/gles3/shaders/00_test_list.txt
+--min-version 2.0.0 framework/opengl/simplereference/00_test_list.txt
+--min-version 2.0.0 functional/gles3/00_test_list.txt
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/LICENSE b/dom/canvas/test/webgl-conf/checkout/deqp/LICENSE
new file mode 100644
index 0000000000..0a93ef7186
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/README.md b/dom/canvas/test/webgl-conf/checkout/deqp/README.md
new file mode 100644
index 0000000000..bdaf88f050
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/README.md
@@ -0,0 +1,21 @@
+DEQP tests for WebGL
+===========================================
+
+1. Running
+Tests can be run as part of the WebGL Conformance suite or individually
+by navigating to one of pages in functional/gles3 or in data/gles(2|3)/shaders/
+
+2. Filtering
+One can limit the tests to run with a 'filter' query. For example:
+
+functional/gles3/textureformat.html?filter=2d
+
+will executed only the tests with '2d' in the test name.
+Filter query accepts a regular expression.
+
+3. Compiling.
+The tests have been annotated for closure and can be compiled with run-closure script.
+
+4. Implementation notes.
+Tests use a minimal subset of google closure library for dependency management.
+The closure compiler is used solely for error checking. The compiler output is discarded.
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/build.py b/dom/canvas/test/webgl-conf/checkout/deqp/build.py
new file mode 100644
index 0000000000..7f452c634a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/build.py
@@ -0,0 +1,264 @@
+#!/usr/bin/env python2
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+# Author: Mobica LTD
+
+import sys
+import re
+import os
+import subprocess
+import threading
+from sys import stdout, stderr, argv
+
+# Running this script
+# 1. To rebuild all dependencies:
+# $ build.py deps
+# 2. To build all targets without rebuilding dependencies
+# $ build.py build
+# 3. To build a single target without rebuilding dependencies
+# $ build.py build <target>
+# See the table below for available targets
+# 4. To rebuild all dependencies and targets
+# $ build.py
+# 5. To build dependencies for a single target
+# $ build.py deps <target>
+# 6. To build dependencies for and compile a single target
+# $ build.py <target>
+
+# List of targets (short target name, closure namespace)
+targets = {
+ 'textureformat': 'functional.gles3.es3fTextureFormatTests',
+ 'fboCompletenessTests': 'functional.gles3.es3fFboCompletenessTests',
+ 'fbomultisampletests': 'functional.gles3.es3fFboMultisampleTests',
+ 'fbostencilbuffertests': 'functional.gles3.es3fFboStencilbufferTests',
+ 'fragmentoutput': 'functional.gles3.es3fFragmentOutputTests',
+ 'framebufferblittests': 'functional.gles3.es3fFramebufferBlitTests',
+ 'instancedrenderingtests': 'functional.gles3.es3fInstancedRenderingTests',
+ 'pixelBufferObjectTest': 'functional.gles3.es3fPixelBufferObjectTest',
+ 'primitiverestarttests': 'functional.gles3.es3fPrimitiveRestartTests',
+ 'samplerobjecttests': 'functional.gles3.es3fSamplerObjectTests',
+ 'transformFeedbackTests': 'functional.gles3.es3fTransformFeedbackTests',
+ 'uniformapi': 'functional.gles3.es3fUniformApiTests',
+ 'uniformbuffers': 'functional.gles3.es3fUniformBlockTests',
+ 'vertexarrays': 'functional.gles3.es3fVertexArrayTests',
+ 'shaderlibrary': 'modules.shared.glsShaderLibrary',
+ 'negativebuffer': 'functional.gles3.es3fNegativeBufferApiTests',
+ 'sglrReferenceContextTest': 'framework.opengl.simplereference.sglrReferenceContextTest',
+ 'lifetime': 'functional.gles3.es3fLifetimeTests',
+ 'draw': 'functional.gles3.es3fDrawTests',
+ 'attriblocation': 'functional.gles3.es3fAttribLocationTests',
+ 'textureShadowTests': 'functional.gles3.es3fTextureShadowTests',
+ 'texturewrap': 'functional.gles3.es3fTextureWrapTests',
+ 'negativetextureapi': 'functional.gles3.es3fNegativeTextureApiTests',
+ 'multisample': 'functional.gles3.es3fMultisampleTests',
+ 'negativefragmentapi': 'functional.gles3.es3fNegativeFragmentApiTests',
+ 'negativevertexarrayapi': 'functional.gles3.es3fNegativeVertexArrayApiTests',
+ 'negativestateapi' : 'functional.gles3.es3fNegativeStateApiTests',
+ 'negativeshaderapi' : 'functional.gles3.es3fNegativeShaderApiTests',
+ 'rasterizerdiscard' : 'functional.gles3.es3fRasterizerDiscardTests',
+ 'buffercopy' : 'functional.gles3.es3fBufferCopyTests',
+ 'shaderindexing' : 'functional.gles3.es3fShaderIndexingTests',
+ 'shaderloop' : 'functional.gles3.es3fShaderLoopTests',
+ 'shaderstruct' : 'functional.gles3.es3fShaderStructTests',
+ 'shaderswitch' : 'functional.gles3.es3fShaderSwitchTests',
+ 'fborender' : 'functional.gles3.es3fFboRenderTest',
+ 'shaderderivate' : 'functional.gles3.es3fShaderDerivateTests',
+ 'builtinprecision' : 'functional.gles3.es3fBuiltinPrecisionTests',
+ 'shaderbuiltinvar' : 'functional.gles3.es3fShaderBuiltinVarTests',
+ 'texturefiltering' : 'functional.gles3.es3fTextureFilteringTests',
+ 'fbocolor' : 'functional.gles3.es3fFboColorbufferTests',
+ 'fragdepth' : 'functional.gles3.es3fFragDepthTests',
+ 'shaderop' : 'functional.gles3.es3fShaderOperatorTests',
+ 'vao' : 'functional.gles3.es3fVertexArrayObjectTests',
+ 'clip' : 'functional.gles3.es3fClippingTests',
+ 'inv' : 'functional.gles3.es3fFboInvalidateTests',
+ 'defvertattr' : 'functional.gles3.es3fDefaultVertexAttributeTests',
+ 'occlusion' : 'functional.gles3.es3fOcclusionQueryTests',
+ 'shaderapi' : 'functional.gles3.es3fShaderApiTests',
+ 'shaderpackingfunction' : 'functional.gles3.es3fShaderPackingFunctionTests',
+ 'shadercommonfunction' : 'functional.gles3.es3fShaderCommonFunctionTests',
+ 'shadermatrix' : 'functional.gles3.es3fShaderMatrixTest',
+ 'shaderprecision' : 'functional.gles3.es3fShaderPrecisionTests',
+ 'bstate': 'functional.gles3.es3fBooleanStateQuery',
+ 'shaderstate': 'functional.gles3.es3fShaderStateQueryTests',
+ 'fbostate' : 'functional.gles3.es3fFboStateQueryTests',
+ 'rbostate' : 'functional.gles3.es3fRboStateQueryTests',
+ 'bufferstate' : 'functional.gles3.es3fBufferObjectQueryTests',
+ 'samplerstate' : 'functional.gles3.es3fSamplerStateQueryTests',
+ 'texstate' : 'functional.gles3.es3fTextureStateQuery',
+ 'internalformatstate' : 'functional.gles3.es3fInternalFormatQueryTests',
+ 'texturespecification' : 'functional.gles3.es3fTextureSpecificationTests',
+ 'shadertexturefunction' : 'functional.gles3.es3fShaderTextureFunctionTests',
+ 'sync' : 'functional.gles3.es3fSyncTests',
+ 'readpixel' : 'functional.gles3.es3fReadPixelTests',
+ 'stringquery' : 'functional.gles3.es3fStringQueryTests',
+ 'indexedstate' : 'functional.gles3.es3fIndexedStateQueryTests',
+ 'integerstate' : 'functional.gles3.es3fIntegerStateQueryTests',
+ 'floatstate' : 'functional.gles3.es3fFloatStateQueryTests'
+}
+
+total_errors = 0
+total_warnings = 0
+
+results = dict()
+
+def dep_filename(target):
+ return target + '.dep'
+
+def compiled_filename(target):
+ return target + '.compiled'
+
+def write_to_file(outfile, cmdLine, redirect_stderr):
+ stderr = None
+ if redirect_stderr:
+ stderr = subprocess.STDOUT
+
+ with open(outfile, "w") as out_file:
+ proc = subprocess.Popen(cmdLine, shell=True, stdout=subprocess.PIPE, stderr=stderr)
+ while proc.poll() is None:
+ line = proc.stdout.readline()
+ out_file.write(line)
+
+ out_file.flush()
+ proc.wait()
+
+def read_file(file_path):
+ #File exist
+ if not file_exists(file_path):
+ sys.exit(2)
+
+ fo = open(file_path)
+ lines = fo.read()
+ fo.close()
+ return lines
+
+def file_exists(file_path):
+ if not os.path.exists:
+ print "The file " + file_name + " doesn't exists"
+ return False
+ return True
+
+def build_deps(target, namespace):
+ cmdLine = 'python ../closure-library/closure/bin/build/closurebuilder.py --root=../closure-library --root=. --namespace=' + namespace
+ print cmdLine
+ write_to_file(dep_filename(target), cmdLine, False)
+
+def build_all_deps():
+ for target in targets.keys():
+ build_deps(target, targets[target])
+
+def buildDepsFile():
+ # the parameter "--root_with_prefix" is the relative path from the file goog/base.js to the root of the .js files we
+ # are working on.
+ cmdBuildDeps = 'python ../closure-library/closure/bin/build/depswriter.py --root_with_prefix=". ../../../deqp" > deqp-deps.js'
+
+ # Calls the python program that generates the google closure dependencies
+ # write_to_file('deqp-deps.js', cmdBuildDeps, False)
+ proc = subprocess.Popen(cmdBuildDeps, shell=True, stdout=subprocess.PIPE, stderr=None)
+ proc.wait()
+
+def build_target(target, namespace):
+ global total_errors
+ global total_warnings
+ deps = read_file(dep_filename(target))
+ cmdLine = 'java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --warning_level VERBOSE --jscomp_warning undefinedVars --externs compiler_additional_extern.js'
+ for dep in deps.split('\n'):
+ dep = dep.strip()
+ if len(dep) > 0:
+ cmdLine += ' --js ' + dep
+ cmdLine += ' --closure_entry_point=' + namespace
+ print cmdLine
+ filename = compiled_filename(target)
+ write_to_file(filename, cmdLine, True)
+ compiled = read_file(filename)
+ result = re.search(r'(\d*)\s*error\(s\),\s*(\d*)\s*warning\(s\)', compiled)
+ errors = 0
+ warnings = 0
+ if result:
+ print target + ': ' + result.group(0)
+ errors = int(result.group(1))
+ warnings = int(result.group(2))
+ total_errors += errors
+ total_warnings += warnings
+ results[target] = [errors, warnings]
+
+def build_all_targets():
+ for target in targets.keys():
+ build_target(target, targets[target])
+
+def format_target(target):
+ deps = read_file(dep_filename(target))
+ fixjsstyle = 'fixjsstyle.py'
+ reformat = 'reformatting_tool.py'
+ for dep in deps.split('\n'):
+ dep = dep.strip()
+ if len(dep) > 0 and not re.search('closure-library.*base\.js', dep):
+ print fixjsstyle + ' ' + dep
+ subprocess.call(['python', fixjsstyle, dep])
+ print reformat + ' -f ' + dep
+ subprocess.call(['python', reformat, '-f', dep])
+
+def format_all_targets():
+ for target in targets.keys():
+ format_target(target)
+
+def pass_or_fail():
+ if total_errors + total_warnings == 0:
+ print "Passed"
+ elif len(results) > 1: #display the summary only when building more than one target
+ passed = [k for k, v in results.iteritems() if v[0] + v[1] == 0]
+ failed = dict((k, v) for k, v in results.iteritems() if v[0] + v[1] != 0)
+ print "\nBuild Summary:"
+ # Print first the tests that passed
+ for target in passed:
+ print "{0:>30}\tPassed".format(target+":")
+
+ # Print tests that failed. Fixed-width to improve readability
+ for target in failed:
+ errors = failed[target][0]
+ warnings = failed[target][1]
+ print "{0:>30}\tErrors: {1:4}\tWarnings: {2:4}".format(target+":", errors, warnings)
+ print "Compilation failed: {} error(s), {} warning(s).".format(total_errors, total_warnings)
+
+def main(argv):
+ if len(argv) == 0:
+ build_all_deps()
+ build_all_targets()
+ buildDepsFile()
+ pass_or_fail()
+ elif (argv[0] == 'deps'):
+ if len(argv) == 2:
+ target = argv[1]
+ build_deps(target, targets[target])
+ else:
+ build_all_deps()
+ elif (argv[0] == 'format'):
+ if len(argv) == 2:
+ target = argv[1]
+ format_target(target)
+ else:
+ format_all_targets()
+ elif (argv[0] == 'build'):
+ if len(argv) == 2:
+ target = argv[1]
+ build_target(target, targets[target])
+ else:
+ build_all_targets()
+ pass_or_fail()
+ elif (argv[0] == 'depfile'):
+ buildDepsFile()
+ elif (argv[0] == 'list'):
+ print "List of available targets:"
+ for target in targets.keys():
+ print "\t{}".format(target)
+ else:
+ target = argv[0]
+ build_deps(target, targets[target])
+ build_target(target, targets[target])
+ pass_or_fail()
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/compiler_additional_extern.js b/dom/canvas/test/webgl-conf/checkout/deqp/compiler_additional_extern.js
new file mode 100644
index 0000000000..9f76119229
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/compiler_additional_extern.js
@@ -0,0 +1,94 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+/* Author: Mobica LTD */
+
+/**
+ * @typedef {function(*): boolean}
+ */
+ArrayBuffer.isView;
+
+/**
+ * @param {?string} msg
+ */
+function description(msg){};
+
+function finishTest(){};
+
+/** @type {string} */ var _currentTestName;
+/**
+ * @param {?string} name
+ */
+function setCurrentTestName(name){};
+
+/**
+ * @param {string} msg
+ */
+function bufferedLogToConsole(msg){};
+
+/**
+ * @constructor
+ * @param {string} message The error message.
+ */
+var TestFailedException = function (message) {};
+
+/**
+ * Shows a message in case expression test fails.
+ * @param {boolean} exp
+ * @param {string} message
+ */
+function checkMessage(exp, message) {};
+
+/**
+ * @param {boolean} assertion
+ * @param {?string} msg
+ * @param {boolean} verbose
+ * @param {boolean} exthrow
+ */
+function assertMsgOptions(assertion, msg, verbose, exthrow) {};
+
+/**
+ * @param {Object|string} msg
+ */
+function debug(msg){};
+
+/**
+ * @param {string} msg
+ * @param {boolean} exthrow
+ */
+function testFailedOptions(msg, exthrow){};
+
+/**
+ * @param {string} msg
+ * @param {boolean} exthrow
+ */
+function testPassedOptions(msg, exthrow){};
+
+/**
+ * @param {string=} msg
+ */
+function testFailed(msg){};
+
+/**
+ * @param {string=} msg
+ */
+function testPassed(msg){};
+
+/**
+ * Defines the exception type for a GL error.
+ * @constructor
+ * @param {string} message The error message.
+ * @param {number} error GL error code
+ */
+WebGLTestUtils.GLErrorException = function(message, error){ /** @type {string} */ this.message; };
+
+/** @type {WebGL2RenderingContext} */ var gl;
+/** @type {HTMLElement} */ var canvas;
+/** @type {Object} */ var wtu;
+
+/** @type {{create3DContext: function(string):WebGL2RenderingContext,
+ loadTextFileAsync: function(string, function(boolean, string)),
+ glEnumToString: function(WebGL2RenderingContext, number):string }} */ var WebGLTestUtils;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/00_test_list.txt
new file mode 100644
index 0000000000..3a9b9cf966
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/00_test_list.txt
@@ -0,0 +1,31 @@
+conditionals.html
+constants.html
+constant_expressions.html
+--min-version 1.0.4 conversions_matrix_combine.html
+--min-version 1.0.4 conversions_matrix_to_matrix.html
+--min-version 1.0.4 conversions_scalar_to_matrix.html
+--min-version 1.0.4 conversions_scalar_to_scalar.html
+--min-version 1.0.4 conversions_scalar_to_vector.html
+--min-version 1.0.4 conversions_vector_combine.html
+--min-version 1.0.4 conversions_vector_illegal.html
+--min-version 1.0.4 conversions_vector_to_scalar.html
+--min-version 1.0.4 conversions_vector_to_vector.html
+declarations.html
+fragdata.html
+functions.html
+invalid_texture_functions.html
+keywords.html
+linkage.html
+preprocessor.html
+qualification_order.html
+reserved_operators.html
+scoping.html
+--min-version 1.0.4 swizzles_bvec2.html
+--min-version 1.0.4 swizzles_bvec3.html
+--min-version 1.0.4 swizzles_bvec4.html
+--min-version 1.0.4 swizzles_ivec2.html
+--min-version 1.0.4 swizzles_ivec3.html
+--min-version 1.0.4 swizzles_ivec4.html
+--min-version 1.0.4 swizzles_vec2.html
+--min-version 1.0.4 swizzles_vec3.html
+--min-version 1.0.4 swizzles_vec4.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.html
new file mode 100644
index 0000000000..c80304c551
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conditionals';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.test
new file mode 100644
index 0000000000..7b5f591149
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conditionals.test
@@ -0,0 +1,333 @@
+group if "If Statements"
+
+ case single_statement
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ if (in0 >= 1.0)
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case compound_statement
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (in0 >= 1.0)
+ {
+ out0 = 1.0;
+ out1 = 0.0;
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sequence_statements
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (in0 >= 1.0)
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sequence_condition
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (false, in0 >= 1.0)
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex_condition
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (false || (in0 >= 1.0) && (in0 - 2.0*in0 < 0.0))
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_else
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 1.0)
+ out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_elseif
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ if (in0 >= 2.0)
+ out0 = 2.0;
+ else if (in0 >= 1.0)
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_elseif_else
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 2.0)
+ out0 = 2.0;
+ else if (in0 >= 1.0)
+ out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_if_elseif_else
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 2.0)
+ {
+ out0 = 2.0;
+ }
+ else if (in0 >= 1.0)
+ out0 = 2.0, out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # if
+
+group invalid_if "Invalid If Conditionals"
+
+ case missing_parenthesis
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if true
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unclosed_parenthesis
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (true
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (5)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_zero_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_one_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (1)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_uniform_condition
+ expect compile_fail
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ uniform int u0;
+ void main()
+ {
+ if (u0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case float_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (5.0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case float_zero_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (0.0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case float_one_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ if (1.0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case sampler_condition
+ expect compile_fail
+ both ""
+ precision mediump float;
+ uniform sampler2D s0;
+ void main()
+ {
+ if (s0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_if
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.html
new file mode 100644
index 0000000000..db92c09fbf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'constant_expressions';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.test
new file mode 100644
index 0000000000..355a4432a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constant_expressions.test
@@ -0,0 +1,288 @@
+group trivial "Trivial expressions"
+
+ case float
+ values { output float out0 = 5.0; }
+ both ""
+
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = 5.0;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ values { output int out0 = 5; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = 5;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ values { output bool out0 = true; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = true;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case cast
+ values { output float out0 = 1.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = float(int(bool(true)));
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # trivial
+
+group operators "Operators"
+
+ case math_float
+ values { output float out0 = 2.19; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = 6.0/3.5 + 1.8*2.6 - 4.2;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_vec
+ values { output float out0 = 15.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const vec3 a = (vec4(1.0, 2.0, 3.0, 4.0).zyx * vec3(1.0, 1.5, 3.0).xyz).xzy + (vec2(5.0)/vec2(2.5)).xxy;
+ out0 = a.x + a.y + a.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_int
+ values { output int out0 = 7; }
+ both ""
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = 5-1 + 2*3 - 9/3;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_ivec
+ values { output int out0 = 21; }
+ both ""
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const ivec3 a = ivec2(5-1, 4).xxy + ivec4(1*3, 9/3, 1+2, 8/4).xyz;
+ out0 = a.x + a.y + a.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_mat
+ values { output float out0 = 8.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const mat3 a = mat3(3.0) * mat3(4.0);
+ const mat4 b = mat4(a[1][1])*2.0;
+ const mat2 c = mat2(b[0][0]) / 3.0;
+ out0 = c[0][0]+c[1][0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical
+ values { output bool out0 = true; }
+ both ""
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = (!false || false) && (true ^^ false);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case compare
+ values { output bool out0 = true; }
+ both ""
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = (false == false) && (true != false) && (1 < 2) && (3 <= 3) && ((1 > 1) != (1 >= 1));
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case selection
+ values { output float out0 = 5.3; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = false ? 0.0 : (true ? 5.3 : 1.0);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # operators
+
+group complex_types "Arrays, structs & nested calls"
+
+ case struct
+ values { output float out0 = 260.922; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct S
+ {
+ vec4 a;
+ int b;
+ };
+
+ void main()
+ {
+ const S s = S(vec4(1.5), 123);
+ out0 = length(s.a.xy)*float(s.b);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_struct
+ values { output float out0 = 965.9; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct S
+ {
+ vec4 v;
+ int i;
+ };
+
+ struct T
+ {
+ S s;
+ bool b;
+ int i;
+ };
+
+ struct U
+ {
+ S s;
+ T t;
+ };
+
+ void main()
+ {
+ const S s = S(vec4(1.5), 123);
+ const T t = T(s, false, 3);
+ const U u = U(s, t);
+ const U v = U(S(vec4(1.3), 4), T(S(vec4(2.0), 5), true, 6));
+ out0 = float(u.s.i*v.t.i + v.t.s.i)*v.s.v.x; // float(123*6 + 5)*1.3
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array
+ values
+ {
+ input float in0 = [ 0.0 | 1.0];
+ output float out0 = [0.0 | 1.0];
+ }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a[int(max(-1.0, 2.0))];
+ a[0] = -1.0;
+ a[1] = in0;
+ out0 = a[int(min(1.0, 2.0))];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_builtin_funcs
+ values { output float out0 = 3.05; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = sqrt( atan(sin(1.5)/cos(1.5)) /*1.5*/ * log2(exp2(log(exp(6.2) + 0.1)) + 0.1) /*~6.2*/);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # complex_types
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.html
new file mode 100644
index 0000000000..d0c7c8662c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'constants';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.test
new file mode 100644
index 0000000000..c3887e7081
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/constants.test
@@ -0,0 +1,662 @@
+case float_input
+ values
+ {
+ input float in0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ output float out0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ }
+ values
+ {
+ input float in0 = [ -1.123 | -0.75 | 512.0 | -72.13 | -199.91 ];
+ output float out0 = [ -1.123 | -0.75 | 512.0 | -72.13 | -199.91 ];
+ }
+
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = in0;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_uniform
+ values
+ {
+ uniform float uni0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ output float out0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ }
+
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ uniform float uni0;
+ void main()
+ {
+ out0 = uni0;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_0
+ values { output float out0 = 1.123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = +1.123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_1
+ values { output float out0 = -1.123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_2
+ values { output float out0 = 123.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 123.;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_3
+ values { output float out0 = 0.123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = .123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_4
+ values { output float out0 = 123.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.23e+2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_5
+ values { output float out0 = -123.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.23E+2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_6
+ values { output float out0 = -123.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.23e2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_7
+ values { output float out0 = 0.123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.23e-1;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_8
+ values { output float out0 = 1000.0; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1e3;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_0
+ values { output int out0 = 123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_1
+ values { output int out0 = -321; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -321;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_2
+ values { output int out0 = 123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0x7B;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_3
+ values { output int out0 = 123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0X7b;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_4
+ values { output int out0 = 123; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0173;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case bool_0
+ values { output bool out0 = true; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = true;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case bool_1
+ values { output bool out0 = false; }
+ both ""
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = false;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_global
+ values { output float out0 = 1000.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 1000.0;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_main
+ values { output float out0 = -1000.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant = -1000.0;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_function
+ values { output float out0 = -0.012; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ float func()
+ {
+ const float theConstant = -0.012;
+ return theConstant;
+ }
+ void main()
+ {
+ out0 = func();
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_1
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant = 100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_2
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ void main()
+ {
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_3
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_4
+ values { output float out0 = 2.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ float func()
+ {
+ const float theConstant = 2.0;
+ return theConstant;
+ }
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = func();
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_operations_with_const
+ values { output float out0 = 21.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theGlobalConstant = 10.0;
+ float func()
+ {
+ const float theConstant = 2.0;
+ return theConstant;
+ }
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = func() * theGlobalConstant + theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_1
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant1 = 10.0;
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_2
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant1 = 10.0;
+ {
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_3
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant1 = 10.0;
+ void main()
+ {
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_4
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant1 = 10.0;
+ float func()
+ {
+ const float theConstant2 = theConstant1;
+ return theConstant2;
+ }
+ void main()
+ {
+ out0 = func();
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_uniform
+ expect compile_fail
+ values { output float out0 = 10.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform float theUniform;
+ void main()
+ {
+ const float theConstant = theUniform;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_varying
+ expect compile_fail
+ values { output float out0 = 10.0; }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying float theVarying;
+ void main()
+ {
+ theVarying = 1.0;
+ gl_Position = vec(1.0);
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying float theVarying;
+ void main()
+ {
+ const float theConstant = theVarying;
+ out0 = theConstant;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case const_float_function_gotcha
+ desc "Function constant parameters are not really constants, so using them as constant expressions should fail."
+ expect compile_fail
+ values { output float out0 = 20.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ float func(const float gotcha)
+ {
+ const float theConstant2 = gotcha;
+ return theConstant2*2.0;
+ }
+ void main()
+ {
+ const float theConstant = 10.0;
+ out0 = func(theConstant);
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_int
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = float(10);
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec2
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec2(1.0, 10.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec3
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec3(1.0, 10.0, 20.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec4
+ values { output float out0 = 10.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec4(1.0, 10.0, 20.0, -10.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_variable_1
+ expect compile_fail
+ values { output float out0 = 20.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ float theVariable = 20.0;
+ const float theConstant = theVariable;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_variable_2
+ expect compile_fail
+ values { output float out0 = 50.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ float theVariable = 20.0;
+ theVariable += 30.0;
+ const float theConstant = theVariable;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_user_func
+ expect compile_fail
+ values { output float out0 = 50.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ float func()
+ {
+ return 50.0;
+ }
+ void main()
+ {
+ const float theConstant = func();
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.template b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.template
new file mode 100644
index 0000000000..40aa8c8628
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.template
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.test
new file mode 100644
index 0000000000..51dd9c2374
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions.test
@@ -0,0 +1,5930 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group scalar_to_scalar "Scalar to Scalar Conversions"
+
+ case float_to_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_int
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 0 | -8 | -20 | 36 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bool
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_float
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 5.0 | 8.0 | 11.0 | -12.0 | -66.0 | -192.0 | 255.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_int
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output int out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bool
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_float
+ values
+ {
+ input bool in0 = [ true | false ];
+ output float out0 = [ 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_int
+ values
+ {
+ input bool in0 = [ true | false ];
+ output int out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bool
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_scalar
+group scalar_to_vector "Scalar to Vector Conversions"
+
+ case float_to_vec2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(3.5, 3.5) | vec2(-0.5, -0.5) | vec2(-8.25, -8.25) | vec2(-20.125, -20.125) | vec2(36.8125, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(3.5, 3.5, 3.5) | vec3(-0.5, -0.5, -0.5) | vec3(-8.25, -8.25, -8.25) | vec3(-20.125, -20.125, -20.125) | vec3(36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.5, 3.5, 3.5, 3.5) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-8.25, -8.25, -8.25, -8.25) | vec4(-20.125, -20.125, -20.125, -20.125) | vec4(36.8125, 36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(3, 3) | ivec2(0, 0) | ivec2(-8, -8) | ivec2(-20, -20) | ivec2(36, 36) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(0, 0, 0) | ivec3(-8, -8, -8) | ivec3(-20, -20, -20) | ivec3(36, 36, 36) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(0, 0, 0, 0) | ivec4(-8, -8, -8, -8) | ivec4(-20, -20, -20, -20) | ivec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(5.0, 5.0) | vec2(8.0, 8.0) | vec2(11.0, 11.0) | vec2(-12.0, -12.0) | vec2(-66.0, -66.0) | vec2(-192.0, -192.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(5.0, 5.0, 5.0) | vec3(8.0, 8.0, 8.0) | vec3(11.0, 11.0, 11.0) | vec3(-12.0, -12.0, -12.0) | vec3(-66.0, -66.0, -66.0) | vec3(-192.0, -192.0, -192.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(5.0, 5.0, 5.0, 5.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(11.0, 11.0, 11.0, 11.0) | vec4(-12.0, -12.0, -12.0, -12.0) | vec4(-66.0, -66.0, -66.0, -66.0) | vec4(-192.0, -192.0, -192.0, -192.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(5, 5) | ivec2(8, 8) | ivec2(11, 11) | ivec2(-12, -12) | ivec2(-66, -66) | ivec2(-192, -192) | ivec2(255, 255) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(5, 5, 5) | ivec3(8, 8, 8) | ivec3(11, 11, 11) | ivec3(-12, -12, -12) | ivec3(-66, -66, -66) | ivec3(-192, -192, -192) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(5, 5, 5, 5) | ivec4(8, 8, 8, 8) | ivec4(11, 11, 11, 11) | ivec4(-12, -12, -12, -12) | ivec4(-66, -66, -66, -66) | ivec4(-192, -192, -192, -192) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_vector
+group vector_to_scalar "Vector to Scalar Conversions"
+
+ case vec2_to_float
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_int
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bool
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_float
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_int
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bool
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_float
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_int
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bool
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_float
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_int
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bool
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_float
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_int
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bool
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_float
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_int
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bool
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_float
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_int
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bool
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_float
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_int
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bool
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_float
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_int
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bool
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_scalar
+group vector_illegal "Illegal Vector Conversions"
+
+ case vec2_to_vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_illegal
+group vector_to_vector "Vector to Vector Conversions"
+
+ case vec4_to_vec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec3
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec2
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec3
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec2
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec4 out0 = [ bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec3
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec2
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, -2.0, -4.0, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec3
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec2
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec3
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec2
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec3
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec2
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 1.0) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(0.0, 1.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec3
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec2
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 1, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec3
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec2
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec3
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec2
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec2
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec2
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec2
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec2
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec2
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec2
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_vector
+group scalar_to_matrix "Scalar to Matrix Conversions"
+
+ case float_to_mat4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25) | mat4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125) | mat4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5) | mat3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5) | mat3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25) | mat3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125) | mat3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.5, 0.0, 0.0, 3.5) | mat2(-0.5, 0.0, 0.0, -0.5) | mat2(-8.25, 0.0, 0.0, -8.25) | mat2(-20.125, 0.0, 0.0, -20.125) | mat2(36.8125, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0) | mat4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0) | mat4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0) | mat4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0) | mat3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0) | mat3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0) | mat3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(5.0, 0.0, 0.0, 5.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(11.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, -12.0) | mat2(-66.0, 0.0, 0.0, -66.0) | mat2(-192.0, 0.0, 0.0, -192.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_matrix
+group matrix_to_matrix "Matrix to Matrix Conversions"
+
+ case mat4_to_mat4
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.03125, 0.0625, 0.0, -0.75, 0.015625, 0.03125, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.03125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0) | mat3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_to_matrix
+group vector_combine "Vector Combine Constructors"
+
+ case vec2_vec2_to_vec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, -32.0, 64.0) | vec4(-32.0, 64.0, 1.0, 1.25) | vec4(1.0, 1.25, 0.0, 0.5) | vec4(0.0, 0.5, -0.5, -2.25) | vec4(-0.75, -0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_ivec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output ivec4 out0 = [ ivec4(0, -2, -32, 64) | ivec4(-32, 64, 1, 1) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_bvec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_vec4
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 1.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) | vec4(1.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_ivec4
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 1, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 1) | ivec4(0, 0, 1, 1) | ivec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_bvec4
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, false, false, false) | bvec4(false, true, false, true) | bvec4(false, false, true, true) | bvec4(true, true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_vec4
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 3.5, 3.5) | vec4(0.0, 36.8125, 36.8125, 36.8125) | vec4(-0.5, -8.25, -8.25, 1.0) | vec4(-8.25, 2.0, 1.0, -8.25) | vec4(3.5, 3.5, 2.0, 2.0) | vec4(-20.125, 1.0, 0.0, 0.0) | vec4(36.8125, -20.125, -20.125, -0.5) | vec4(2.0, -0.5, -0.5, -20.125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_ivec4
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 3, 3) | ivec4(0, 36, 36, 36) | ivec4(0, -8, -8, 1) | ivec4(-8, 2, 1, -8) | ivec4(3, 3, 2, 2) | ivec4(-20, 1, 0, 0) | ivec4(36, -20, -20, 0) | ivec4(2, 0, 0, -20) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_bvec4
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_vec4
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output vec4 out0 = [ vec4(-12.0, 2.0, 11.0, -192.0) | vec4(-66.0, 5.0, 255.0, -66.0) | vec4(2.0, -66.0, 5.0, 8.0) | vec4(5.0, 11.0, 8.0, -12.0) | vec4(8.0, -192.0, 2.0, 1.0) | vec4(-192.0, 8.0, -192.0, 2.0) | vec4(255.0, -12.0, -12.0, 0.0) | vec4(1.0, 1.0, -66.0, 255.0) | vec4(0.0, 255.0, 1.0, 5.0) | vec4(11.0, 0.0, 0.0, 11.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_ivec4
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output ivec4 out0 = [ ivec4(-12, 2, 11, -192) | ivec4(-66, 5, 255, -66) | ivec4(2, -66, 5, 8) | ivec4(5, 11, 8, -12) | ivec4(8, -192, 2, 1) | ivec4(-192, 8, -192, 2) | ivec4(255, -12, -12, 0) | ivec4(1, 1, -66, 255) | ivec4(0, 255, 1, 5) | ivec4(11, 0, 0, 11) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_bvec4
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_vec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 1.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_ivec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output ivec4 out0 = [ ivec4(1, 0, 1, 0) | ivec4(0, 1, 0, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_bvec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output bvec4 out0 = [ bvec4(true, false, true, false) | bvec4(false, true, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_vec4
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | true | false | true | false ];
+ input float in1 = [ 1.0 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 | -0.5 | 3.5 | -20.125 | 0.0 ];
+ input int in2 = [ -192 | -12 | 2 | -66 | 255 | 8 | 0 | 5 | 11 | 1 ];
+ input bool in3 = [ true | true | false | false | true | false | false | false | true | true ];
+ output vec4 out0 = [ vec4(1.0, 1.0, -192.0, 1.0) | vec4(1.0, 2.0, -12.0, 1.0) | vec4(1.0, 1.0, 2.0, 0.0) | vec4(0.0, 0.0, -66.0, 0.0) | vec4(0.0, 36.8125, 255.0, 1.0) | vec4(0.0, -8.25, 8.0, 0.0) | vec4(1.0, -0.5, 0.0, 0.0) | vec4(0.0, 3.5, 5.0, 0.0) | vec4(1.0, -20.125, 11.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_ivec4
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | true | false | true | false ];
+ input float in1 = [ 1.0 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 | -0.5 | 3.5 | -20.125 | 0.0 ];
+ input int in2 = [ -192 | -12 | 2 | -66 | 255 | 8 | 0 | 5 | 11 | 1 ];
+ input bool in3 = [ true | true | false | false | true | false | false | false | true | true ];
+ output ivec4 out0 = [ ivec4(1, 1, -192, 1) | ivec4(1, 2, -12, 1) | ivec4(1, 1, 2, 0) | ivec4(0, 0, -66, 0) | ivec4(0, 36, 255, 1) | ivec4(0, -8, 8, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 3, 5, 0) | ivec4(1, -20, 11, 1) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_bvec4
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | true | false | true | false ];
+ input float in1 = [ 1.0 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 | -0.5 | 3.5 | -20.125 | 0.0 ];
+ input int in2 = [ -192 | -12 | 2 | -66 | 255 | 8 | 0 | 5 | 11 | 1 ];
+ input bool in3 = [ true | true | false | false | true | false | false | false | true | true ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(false, false, true, false) | bvec4(false, true, true, true) | bvec4(false, true, true, false) | bvec4(true, true, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_vec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, 0.0, 0.0) | vec4(0.0, 0.5, 0.0, -2.0) | vec4(-32.0, 64.0, -32.0, 64.0) | vec4(1.0, 1.25, 0.0, 0.0) | vec4(-0.75, -0.0322580645161, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_ivec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(0, -2, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(-32, 64, -32, 64) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_bvec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(false, true, false, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_vec4
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(-32.0, 64.0, 0.0, 0.0) | vec4(-0.5, -2.25, 1.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.75, -0.0322580645161, 0.0, 1.0) | vec4(0.0, 0.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_ivec4
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(-32, 64, 0, 0) | ivec4(0, -2, 1, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_bvec4
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_vec4
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, true, false) | bvec3(true, true, true) ];
+ input float in1 = [ -8.25 | -20.125 | 2.0 | 0.0 | -0.5 | 3.5 | 36.8125 | 1.0 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, -8.25) | vec4(0.0, 0.0, 0.0, -20.125) | vec4(0.0, 0.0, 0.0, 2.0) | vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 0.0, 0.0, -0.5) | vec4(0.0, 1.0, 0.0, 3.5) | vec4(0.0, 1.0, 0.0, 36.8125) | vec4(1.0, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_ivec4
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, true, false) | bvec3(true, true, true) ];
+ input float in1 = [ -8.25 | -20.125 | 2.0 | 0.0 | -0.5 | 3.5 | 36.8125 | 1.0 ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, -8) | ivec4(0, 0, 0, -20) | ivec4(0, 0, 0, 2) | ivec4(0, 0, 0, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 3) | ivec4(0, 1, 0, 36) | ivec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_bvec4
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, true, false) | bvec3(true, true, true) ];
+ input float in1 = [ -8.25 | -20.125 | 2.0 | 0.0 | -0.5 | 3.5 | 36.8125 | 1.0 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, true) | bvec4(false, true, false, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_vec4
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | -20.125 ];
+ output vec4 out0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.0) | vec4(0.0, 0.5, 0.75, 2.0) | vec4(-0.5, -2.25, -4.875, 36.8125) | vec4(0.0, 0.5, 0.75, 3.5) | vec4(1.0, 1.25, 1.125, 1.0) | vec4(-0.5, -2.25, -4.875, -0.5) | vec4(-32.0, 64.0, -51.0, -8.25) | vec4(1.0, 1.25, 1.125, -20.125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_ivec4
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | -20.125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 2) | ivec4(0, -2, -4, 36) | ivec4(0, 0, 0, 3) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 0) | ivec4(-32, 64, -51, -8) | ivec4(1, 1, 1, -20) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_bvec4
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_vec4
+ values
+ {
+ input int in0 = [ -66 | 8 | -192 | 255 | 5 | -12 | 0 | 2 | 1 | 11 ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) ];
+ input int in2 = [ 8 | 2 | 11 | -192 | 255 | -12 | 0 | -66 | 1 | 5 ];
+ output vec4 out0 = [ vec4(-66.0, 0.0, 0.0, 8.0) | vec4(8.0, 0.0, 0.0, 2.0) | vec4(-192.0, -32.0, 64.0, 11.0) | vec4(255.0, -32.0, 64.0, -192.0) | vec4(5.0, 1.0, 1.0, 255.0) | vec4(-12.0, 0.0, 0.0, -12.0) | vec4(0.0, 1.0, 1.0, 0.0) | vec4(2.0, 0.0, -2.0, -66.0) | vec4(1.0, 0.0, -2.0, 1.0) | vec4(11.0, 0.0, 0.0, 5.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_ivec4
+ values
+ {
+ input int in0 = [ -66 | 8 | -192 | 255 | 5 | -12 | 0 | 2 | 1 | 11 ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) ];
+ input int in2 = [ 8 | 2 | 11 | -192 | 255 | -12 | 0 | -66 | 1 | 5 ];
+ output ivec4 out0 = [ ivec4(-66, 0, 0, 8) | ivec4(8, 0, 0, 2) | ivec4(-192, -32, 64, 11) | ivec4(255, -32, 64, -192) | ivec4(5, 1, 1, 255) | ivec4(-12, 0, 0, -12) | ivec4(0, 1, 1, 0) | ivec4(2, 0, -2, -66) | ivec4(1, 0, -2, 1) | ivec4(11, 0, 0, 5) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_bvec4
+ values
+ {
+ input int in0 = [ -66 | 8 | -192 | 255 | 5 | -12 | 0 | 2 | 1 | 11 ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) ];
+ input int in2 = [ 8 | 2 | 11 | -192 | 255 | -12 | 0 | -66 | 1 | 5 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(false, true, true, false) | bvec4(true, false, true, true) | bvec4(true, false, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_vec4
+ values
+ {
+ input bool in0 = [ true | true | true | true | false | false | false | false ];
+ input float in1 = [ 2.0 | 0.0 | 3.5 | -8.25 | 36.8125 | -20.125 | 1.0 | -0.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output vec4 out0 = [ vec4(1.0, 2.0, 0.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(1.0, 3.5, -32.0, 64.0) | vec4(1.0, -8.25, 1.0, 1.0) | vec4(0.0, 36.8125, 0.0, -2.0) | vec4(0.0, -20.125, 0.0, -2.0) | vec4(0.0, 1.0, 1.0, 1.0) | vec4(0.0, -0.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_ivec4
+ values
+ {
+ input bool in0 = [ true | true | true | true | false | false | false | false ];
+ input float in1 = [ 2.0 | 0.0 | 3.5 | -8.25 | 36.8125 | -20.125 | 1.0 | -0.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(1, 2, 0, 0) | ivec4(1, 0, 0, 0) | ivec4(1, 3, -32, 64) | ivec4(1, -8, 1, 1) | ivec4(0, 36, 0, -2) | ivec4(0, -20, 0, -2) | ivec4(0, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_bvec4
+ values
+ {
+ input bool in0 = [ true | true | true | true | false | false | false | false ];
+ input float in1 = [ 2.0 | 0.0 | 3.5 | -8.25 | 36.8125 | -20.125 | 1.0 | -0.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, false, true) | bvec4(false, true, false, true) | bvec4(false, true, true, true) | bvec4(false, true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_vec3
+ values
+ {
+ input float in0 = [ 3.5 | 2.0 | -20.125 | -8.25 | 36.8125 | 1.0 | 0.0 | -0.5 ];
+ input float in1 = [ -0.5 | 1.0 | 2.0 | -20.125 | 0.0 | -8.25 | 36.8125 | 3.5 ];
+ input float in2 = [ 0.0 | 1.0 | 3.5 | -8.25 | -0.5 | 36.8125 | -20.125 | 2.0 ];
+ output vec3 out0 = [ vec3(3.5, -0.5, 0.0) | vec3(2.0, 1.0, 1.0) | vec3(-20.125, 2.0, 3.5) | vec3(-8.25, -20.125, -8.25) | vec3(36.8125, 0.0, -0.5) | vec3(1.0, -8.25, 36.8125) | vec3(0.0, 36.8125, -20.125) | vec3(-0.5, 3.5, 2.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_ivec3
+ values
+ {
+ input float in0 = [ 3.5 | 2.0 | -20.125 | -8.25 | 36.8125 | 1.0 | 0.0 | -0.5 ];
+ input float in1 = [ -0.5 | 1.0 | 2.0 | -20.125 | 0.0 | -8.25 | 36.8125 | 3.5 ];
+ input float in2 = [ 0.0 | 1.0 | 3.5 | -8.25 | -0.5 | 36.8125 | -20.125 | 2.0 ];
+ output ivec3 out0 = [ ivec3(3, 0, 0) | ivec3(2, 1, 1) | ivec3(-20, 2, 3) | ivec3(-8, -20, -8) | ivec3(36, 0, 0) | ivec3(1, -8, 36) | ivec3(0, 36, -20) | ivec3(0, 3, 2) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_bvec3
+ values
+ {
+ input float in0 = [ 3.5 | 2.0 | -20.125 | -8.25 | 36.8125 | 1.0 | 0.0 | -0.5 ];
+ input float in1 = [ -0.5 | 1.0 | 2.0 | -20.125 | 0.0 | -8.25 | 36.8125 | 3.5 ];
+ input float in2 = [ 0.0 | 1.0 | 3.5 | -8.25 | -0.5 | 36.8125 | -20.125 | 2.0 ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_vec3
+ values
+ {
+ input int in0 = [ 0 | 2 | 1 | 5 | 255 | 8 | -66 | 11 | -12 | -192 ];
+ input int in1 = [ 2 | 8 | 11 | -12 | -192 | 1 | -66 | 5 | 255 | 0 ];
+ input int in2 = [ -192 | -12 | -66 | 8 | 1 | 2 | 5 | 11 | 255 | 0 ];
+ output vec3 out0 = [ vec3(0.0, 2.0, -192.0) | vec3(2.0, 8.0, -12.0) | vec3(1.0, 11.0, -66.0) | vec3(5.0, -12.0, 8.0) | vec3(255.0, -192.0, 1.0) | vec3(8.0, 1.0, 2.0) | vec3(-66.0, -66.0, 5.0) | vec3(11.0, 5.0, 11.0) | vec3(-12.0, 255.0, 255.0) | vec3(-192.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_ivec3
+ values
+ {
+ input int in0 = [ 0 | 2 | 1 | 5 | 255 | 8 | -66 | 11 | -12 | -192 ];
+ input int in1 = [ 2 | 8 | 11 | -12 | -192 | 1 | -66 | 5 | 255 | 0 ];
+ input int in2 = [ -192 | -12 | -66 | 8 | 1 | 2 | 5 | 11 | 255 | 0 ];
+ output ivec3 out0 = [ ivec3(0, 2, -192) | ivec3(2, 8, -12) | ivec3(1, 11, -66) | ivec3(5, -12, 8) | ivec3(255, -192, 1) | ivec3(8, 1, 2) | ivec3(-66, -66, 5) | ivec3(11, 5, 11) | ivec3(-12, 255, 255) | ivec3(-192, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_bvec3
+ values
+ {
+ input int in0 = [ 0 | 2 | 1 | 5 | 255 | 8 | -66 | 11 | -12 | -192 ];
+ input int in1 = [ 2 | 8 | 11 | -12 | -192 | 1 | -66 | 5 | 255 | 0 ];
+ input int in2 = [ -192 | -12 | -66 | 8 | 1 | 2 | 5 | 11 | 255 | 0 ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_vec3
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_ivec3
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_bvec3
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_vec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | false | true ];
+ input float in1 = [ 0.0 | 2.0 | 1.0 | -0.5 | -8.25 | 3.5 | -20.125 | 1.0 | 0.0 | 36.8125 ];
+ input int in2 = [ -12 | -192 | 2 | 5 | -66 | 255 | 11 | 0 | 8 | 1 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, -12.0) | vec3(1.0, 2.0, -192.0) | vec3(0.0, 1.0, 2.0) | vec3(1.0, -0.5, 5.0) | vec3(0.0, -8.25, -66.0) | vec3(1.0, 3.5, 255.0) | vec3(0.0, -20.125, 11.0) | vec3(1.0, 1.0, 0.0) | vec3(0.0, 0.0, 8.0) | vec3(1.0, 36.8125, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_ivec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | false | true ];
+ input float in1 = [ 0.0 | 2.0 | 1.0 | -0.5 | -8.25 | 3.5 | -20.125 | 1.0 | 0.0 | 36.8125 ];
+ input int in2 = [ -12 | -192 | 2 | 5 | -66 | 255 | 11 | 0 | 8 | 1 ];
+ output ivec3 out0 = [ ivec3(0, 0, -12) | ivec3(1, 2, -192) | ivec3(0, 1, 2) | ivec3(1, 0, 5) | ivec3(0, -8, -66) | ivec3(1, 3, 255) | ivec3(0, -20, 11) | ivec3(1, 1, 0) | ivec3(0, 0, 8) | ivec3(1, 36, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_bvec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | false | true ];
+ input float in1 = [ 0.0 | 2.0 | 1.0 | -0.5 | -8.25 | 3.5 | -20.125 | 1.0 | 0.0 | 36.8125 ];
+ input int in2 = [ -12 | -192 | 2 | 5 | -66 | 255 | 11 | 0 | 8 | 1 ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, false) | bvec3(false, false, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_vec3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input bool in1 = [ false | true | false | true | true ];
+ output vec3 out0 = [ vec3(-0.75, -0.0322580645161, 0.0) | vec3(1.0, 1.25, 1.0) | vec3(-0.5, -2.25, 0.0) | vec3(0.0, 0.5, 1.0) | vec3(-32.0, 64.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_ivec3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input bool in1 = [ false | true | false | true | true ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, 0) | ivec3(0, 0, 1) | ivec3(-32, 64, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_bvec3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input bool in1 = [ false | true | false | true | true ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, false) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_vec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input float in1 = [ 2.0 | 36.8125 | 0.0 | -20.125 | 1.0 | -0.5 | -8.25 | 3.5 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 2.0) | vec3(0.0, 0.0, 36.8125) | vec3(1.0, 0.0, 0.0) | vec3(0.0, 1.0, -20.125) | vec3(0.0, 0.0, 1.0) | vec3(0.0, 1.0, -0.5) | vec3(0.0, 0.0, -8.25) | vec3(1.0, 1.0, 3.5) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_ivec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input float in1 = [ 2.0 | 36.8125 | 0.0 | -20.125 | 1.0 | -0.5 | -8.25 | 3.5 ];
+ output ivec3 out0 = [ ivec3(1, 0, 2) | ivec3(0, 0, 36) | ivec3(1, 0, 0) | ivec3(0, 1, -20) | ivec3(0, 0, 1) | ivec3(0, 1, 0) | ivec3(0, 0, -8) | ivec3(1, 1, 3) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_bvec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input float in1 = [ 2.0 | 36.8125 | 0.0 | -20.125 | 1.0 | -0.5 | -8.25 | 3.5 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, true) | bvec3(true, false, false) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_vec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in1 = [ 0 | 255 | 1 | 2 | 8 | 11 | -192 | 5 | -12 | -66 ];
+ output vec3 out0 = [ vec3(0.0, 1.0, 0.0) | vec3(0.0, 1.0, 255.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 2.0) | vec3(0.0, 0.0, 8.0) | vec3(0.0, 0.0, 11.0) | vec3(1.0, 1.0, -192.0) | vec3(1.0, 0.0, 5.0) | vec3(1.0, 0.0, -12.0) | vec3(0.0, 0.0, -66.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_ivec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in1 = [ 0 | 255 | 1 | 2 | 8 | 11 | -192 | 5 | -12 | -66 ];
+ output ivec3 out0 = [ ivec3(0, 1, 0) | ivec3(0, 1, 255) | ivec3(1, 1, 1) | ivec3(0, 0, 2) | ivec3(0, 0, 8) | ivec3(0, 0, 11) | ivec3(1, 1, -192) | ivec3(1, 0, 5) | ivec3(1, 0, -12) | ivec3(0, 0, -66) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_bvec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in1 = [ 0 | 255 | 1 | 2 | 8 | 11 | -192 | 5 | -12 | -66 ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, false, true) | bvec3(false, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_vec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | true ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 0.0, -2.0) | vec3(0.0, 0.0, 0.0) | vec3(1.0, -32.0, 64.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_ivec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | true ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 0, -2) | ivec3(0, 0, 0) | ivec3(1, -32, 64) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_bvec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | true ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_vec2
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | -8.25 | -0.5 | 0.0 | -20.125 | 36.8125 | 1.0 ];
+ input float in1 = [ 3.5 | -20.125 | -0.5 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 ];
+ output vec2 out0 = [ vec2(2.0, 3.5) | vec2(3.5, -20.125) | vec2(-8.25, -0.5) | vec2(-0.5, 2.0) | vec2(0.0, 1.0) | vec2(-20.125, 0.0) | vec2(36.8125, 36.8125) | vec2(1.0, -8.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_ivec2
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | -8.25 | -0.5 | 0.0 | -20.125 | 36.8125 | 1.0 ];
+ input float in1 = [ 3.5 | -20.125 | -0.5 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 ];
+ output ivec2 out0 = [ ivec2(2, 3) | ivec2(3, -20) | ivec2(-8, 0) | ivec2(0, 2) | ivec2(0, 1) | ivec2(-20, 0) | ivec2(36, 36) | ivec2(1, -8) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_bvec2
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | -8.25 | -0.5 | 0.0 | -20.125 | 36.8125 | 1.0 ];
+ input float in1 = [ 3.5 | -20.125 | -0.5 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_vec2
+ values
+ {
+ input int in0 = [ 8 | 255 | -192 | 2 | 0 | 1 | -12 | 11 | -66 | 5 ];
+ input int in1 = [ -66 | 2 | 255 | 8 | -12 | 5 | -192 | 0 | 1 | 11 ];
+ output vec2 out0 = [ vec2(8.0, -66.0) | vec2(255.0, 2.0) | vec2(-192.0, 255.0) | vec2(2.0, 8.0) | vec2(0.0, -12.0) | vec2(1.0, 5.0) | vec2(-12.0, -192.0) | vec2(11.0, 0.0) | vec2(-66.0, 1.0) | vec2(5.0, 11.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_ivec2
+ values
+ {
+ input int in0 = [ 8 | 255 | -192 | 2 | 0 | 1 | -12 | 11 | -66 | 5 ];
+ input int in1 = [ -66 | 2 | 255 | 8 | -12 | 5 | -192 | 0 | 1 | 11 ];
+ output ivec2 out0 = [ ivec2(8, -66) | ivec2(255, 2) | ivec2(-192, 255) | ivec2(2, 8) | ivec2(0, -12) | ivec2(1, 5) | ivec2(-12, -192) | ivec2(11, 0) | ivec2(-66, 1) | ivec2(5, 11) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_bvec2
+ values
+ {
+ input int in0 = [ 8 | 255 | -192 | 2 | 0 | 1 | -12 | 11 | -66 | 5 ];
+ input int in1 = [ -66 | 2 | 255 | 8 | -12 | 5 | -192 | 0 | 1 | 11 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_vec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_ivec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_bvec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_vec2
+ values
+ {
+ input float in0 = [ 1.0 | -0.5 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | 2.0 | 1.0 | 0.0 ];
+ input int in1 = [ -192 | -66 | 255 | 1 | 2 | 0 | -12 | 5 | 11 | 8 ];
+ output vec2 out0 = [ vec2(1.0, -192.0) | vec2(-0.5, -66.0) | vec2(-20.125, 255.0) | vec2(0.0, 1.0) | vec2(3.5, 2.0) | vec2(-8.25, 0.0) | vec2(36.8125, -12.0) | vec2(2.0, 5.0) | vec2(1.0, 11.0) | vec2(0.0, 8.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_ivec2
+ values
+ {
+ input float in0 = [ 1.0 | -0.5 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | 2.0 | 1.0 | 0.0 ];
+ input int in1 = [ -192 | -66 | 255 | 1 | 2 | 0 | -12 | 5 | 11 | 8 ];
+ output ivec2 out0 = [ ivec2(1, -192) | ivec2(0, -66) | ivec2(-20, 255) | ivec2(0, 1) | ivec2(3, 2) | ivec2(-8, 0) | ivec2(36, -12) | ivec2(2, 5) | ivec2(1, 11) | ivec2(0, 8) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_bvec2
+ values
+ {
+ input float in0 = [ 1.0 | -0.5 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | 2.0 | 1.0 | 0.0 ];
+ input int in1 = [ -192 | -66 | 255 | 1 | 2 | 0 | -12 | 5 | 11 | 8 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_vec2
+ values
+ {
+ input float in0 = [ 2.0 | -20.125 | 0.0 | 1.0 | -8.25 | -0.5 | 36.8125 | 3.5 ];
+ input bool in1 = [ true | false | false | false | true | true | false | true ];
+ output vec2 out0 = [ vec2(2.0, 1.0) | vec2(-20.125, 0.0) | vec2(0.0, 0.0) | vec2(1.0, 0.0) | vec2(-8.25, 1.0) | vec2(-0.5, 1.0) | vec2(36.8125, 0.0) | vec2(3.5, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_ivec2
+ values
+ {
+ input float in0 = [ 2.0 | -20.125 | 0.0 | 1.0 | -8.25 | -0.5 | 36.8125 | 3.5 ];
+ input bool in1 = [ true | false | false | false | true | true | false | true ];
+ output ivec2 out0 = [ ivec2(2, 1) | ivec2(-20, 0) | ivec2(0, 0) | ivec2(1, 0) | ivec2(-8, 1) | ivec2(0, 1) | ivec2(36, 0) | ivec2(3, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_bvec2
+ values
+ {
+ input float in0 = [ 2.0 | -20.125 | 0.0 | 1.0 | -8.25 | -0.5 | 36.8125 | 3.5 ];
+ input bool in1 = [ true | false | false | false | true | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_vec2
+ values
+ {
+ input int in0 = [ 8 | 255 | 11 | -66 | 0 | -192 | -12 | 1 | 5 | 2 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true | false | true ];
+ output vec2 out0 = [ vec2(8.0, 1.0) | vec2(255.0, 0.0) | vec2(11.0, 1.0) | vec2(-66.0, 0.0) | vec2(0.0, 1.0) | vec2(-192.0, 0.0) | vec2(-12.0, 0.0) | vec2(1.0, 1.0) | vec2(5.0, 0.0) | vec2(2.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_ivec2
+ values
+ {
+ input int in0 = [ 8 | 255 | 11 | -66 | 0 | -192 | -12 | 1 | 5 | 2 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true | false | true ];
+ output ivec2 out0 = [ ivec2(8, 1) | ivec2(255, 0) | ivec2(11, 1) | ivec2(-66, 0) | ivec2(0, 1) | ivec2(-192, 0) | ivec2(-12, 0) | ivec2(1, 1) | ivec2(5, 0) | ivec2(2, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_bvec2
+ values
+ {
+ input int in0 = [ 8 | 255 | 11 | -66 | 0 | -192 | -12 | 1 | 5 | 2 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_combine
+group matrix_combine "Matrix Combine Constructors"
+
+ case vec2_vec2_to_mat2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) ];
+ input vec2 in1 = [ vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(1.0, 1.25) ];
+ output mat2 out0 = [ mat2(0.0, 0.5, -0.5, -2.25) | mat2(1.0, 1.25, -0.75, -0.0322580645161) | mat2(-32.0, 64.0, -32.0, 64.0) | mat2(-0.75, -0.0322580645161, 0.0, 0.5) | mat2(-0.5, -2.25, 1.0, 1.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_mat2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 1.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(0.0, 1.0, 1.0, 0.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_mat2
+ values
+ {
+ input float in0 = [ 0.0 | -0.5 | -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | -8.25 ];
+ input float in1 = [ -8.25 | 2.0 | -0.5 | -20.125 | 3.5 | 1.0 | 36.8125 | 0.0 ];
+ input float in2 = [ 36.8125 | -8.25 | 3.5 | 2.0 | -0.5 | -20.125 | 1.0 | 0.0 ];
+ input float in3 = [ 36.8125 | 0.0 | 2.0 | 3.5 | -8.25 | -0.5 | -20.125 | 1.0 ];
+ output mat2 out0 = [ mat2(0.0, -8.25, 36.8125, 36.8125) | mat2(-0.5, 2.0, -8.25, 0.0) | mat2(-20.125, -0.5, 3.5, 2.0) | mat2(2.0, -20.125, 2.0, 3.5) | mat2(36.8125, 3.5, -0.5, -8.25) | mat2(1.0, 1.0, -20.125, -0.5) | mat2(3.5, 36.8125, 1.0, -20.125) | mat2(-8.25, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_mat2
+ values
+ {
+ input int in0 = [ 2 | 0 | -66 | 8 | 1 | 255 | 5 | -12 | 11 | -192 ];
+ input int in1 = [ -192 | 2 | 5 | -12 | -66 | 255 | 8 | 1 | 11 | 0 ];
+ input int in2 = [ 2 | 11 | -192 | 255 | 1 | 5 | 0 | -12 | 8 | -66 ];
+ input int in3 = [ 255 | 0 | 11 | -66 | 2 | 8 | -192 | 1 | -12 | 5 ];
+ output mat2 out0 = [ mat2(2.0, -192.0, 2.0, 255.0) | mat2(0.0, 2.0, 11.0, 0.0) | mat2(-66.0, 5.0, -192.0, 11.0) | mat2(8.0, -12.0, 255.0, -66.0) | mat2(1.0, -66.0, 1.0, 2.0) | mat2(255.0, 255.0, 5.0, 8.0) | mat2(5.0, 8.0, 0.0, -192.0) | mat2(-12.0, 1.0, -12.0, 1.0) | mat2(11.0, 11.0, 8.0, -12.0) | mat2(-192.0, 0.0, -66.0, 5.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_mat2
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 1.0, 0.0) | mat2(1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_mat2
+ values
+ {
+ input bool in0 = [ false | true | true | false | false | true | true | true | false | false ];
+ input float in1 = [ -0.5 | -20.125 | 3.5 | 2.0 | 1.0 | 0.0 | 0.0 | 1.0 | 36.8125 | -8.25 ];
+ input int in2 = [ -66 | -192 | 5 | 255 | 0 | -12 | 11 | 1 | 2 | 8 ];
+ input bool in3 = [ true | false | true | false | false | false | true | false | true | true ];
+ output mat2 out0 = [ mat2(0.0, -0.5, -66.0, 1.0) | mat2(1.0, -20.125, -192.0, 0.0) | mat2(1.0, 3.5, 5.0, 1.0) | mat2(0.0, 2.0, 255.0, 0.0) | mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 0.0, -12.0, 0.0) | mat2(1.0, 0.0, 11.0, 1.0) | mat2(1.0, 1.0, 1.0, 0.0) | mat2(0.0, 36.8125, 2.0, 1.0) | mat2(0.0, -8.25, 8.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_mat2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output mat2 out0 = [ mat2(0.0, 0.5, -32.0, 64.0) | mat2(-32.0, 64.0, 0.0, 0.0) | mat2(-0.5, -2.25, 0.0, -2.0) | mat2(-0.75, -0.0322580645161, 0.0, 0.0) | mat2(1.0, 1.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_mat2
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) ];
+ output mat2 out0 = [ mat2(-32.0, 64.0, 0.0, 1.0) | mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, 1.0, 0.0) | mat2(1.0, 1.25, 0.0, 0.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_mat2
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ -20.125 | -0.5 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 1.0, 0.0, -20.125) | mat2(1.0, 1.0, 1.0, -0.5) | mat2(0.0, 0.0, 0.0, 3.5) | mat2(1.0, 0.0, 0.0, -8.25) | mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 2.0) | mat2(0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_mat2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -8.25 | 36.8125 | -0.5 | -20.125 | 1.0 | 2.0 | 0.0 | 3.5 ];
+ output mat2 out0 = [ mat2(0.0, 0.5, 0.75, -8.25) | mat2(1.0, 1.25, 1.125, 36.8125) | mat2(-0.75, -0.0322580645161, 0.0526315789474, -0.5) | mat2(-0.5, -2.25, -4.875, -20.125) | mat2(0.0, 0.5, 0.75, 1.0) | mat2(-32.0, 64.0, -51.0, 2.0) | mat2(-0.5, -2.25, -4.875, 0.0) | mat2(1.0, 1.25, 1.125, 3.5) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_mat2
+ values
+ {
+ input int in0 = [ -66 | 255 | 8 | 0 | 5 | -12 | 1 | -192 | 2 | 11 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input int in2 = [ 0 | -12 | 8 | -66 | 11 | 5 | 255 | 2 | 1 | -192 ];
+ output mat2 out0 = [ mat2(-66.0, 0.0, -2.0, 0.0) | mat2(255.0, 0.0, 0.0, -12.0) | mat2(8.0, -32.0, 64.0, 8.0) | mat2(0.0, 1.0, 1.0, -66.0) | mat2(5.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, 5.0) | mat2(1.0, -32.0, 64.0, 255.0) | mat2(-192.0, 0.0, -2.0, 2.0) | mat2(2.0, 0.0, 0.0, 1.0) | mat2(11.0, 1.0, 1.0, -192.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_mat2
+ values
+ {
+ input bool in0 = [ true | true | true | false | true | false | false | false ];
+ input float in1 = [ 0.0 | 1.0 | 2.0 | -0.5 | 3.5 | -20.125 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 1.0, 1.0) | mat2(1.0, 1.0, 1.0, 1.0) | mat2(1.0, 2.0, 0.0, -2.0) | mat2(0.0, -0.5, 0.0, 0.0) | mat2(1.0, 3.5, -32.0, 64.0) | mat2(0.0, -20.125, 0.0, -2.0) | mat2(0.0, 36.8125, 0.0, 0.0) | mat2(0.0, -8.25, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec3_to_mat3
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in1 = [ vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec3 in2 = [ vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 1.125, -0.5, -2.25, -4.875, -0.5, -2.25, -4.875) | mat3(-0.75, -0.0322580645161, 0.0526315789474, -0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.5, 0.75) | mat3(-32.0, 64.0, -51.0, 0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474) | mat3(-0.5, -2.25, -4.875, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(0.0, 0.5, 0.75, 1.0, 1.25, 1.125, 1.0, 1.25, 1.125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec3_to_mat3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, -2, -4) | ivec3(1, 1, 1) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(0, 0, 0) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec3 in2 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) ];
+ output mat3 out0 = [ mat3(0.0, -2.0, -4.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) | mat3(-32.0, 64.0, -51.0, 0.0, -2.0, -4.0, 0.0, 0.0, 0.0) | mat3(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_bool_to_mat3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input ivec2 in1 = [ ivec2(-32, 64) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) ];
+ input float in2 = [ -20.125 | -8.25 | 3.5 | 1.0 | 1.0 | -0.5 | 2.0 | 0.0 | 36.8125 | 0.0 ];
+ input float in3 = [ 0.0 | -0.5 | 1.0 | -20.125 | 36.8125 | 0.0 | -8.25 | 2.0 | 3.5 | 1.0 ];
+ input int in4 = [ 2 | 11 | 1 | 0 | 8 | 5 | -66 | 255 | -192 | -12 ];
+ input bool in5 = [ false | true | true | false | false | true | false | true | false | true ];
+ input bool in6 = [ false | true | false | false | true | true | true | true | false | false ];
+ output mat3 out0 = [ mat3(-0.75, -0.0322580645161, -32.0, 64.0, -20.125, 0.0, 2.0, 0.0, 0.0) | mat3(1.0, 1.25, 0.0, -2.0, -8.25, -0.5, 11.0, 1.0, 1.0) | mat3(0.0, 0.5, 1.0, 1.0, 3.5, 1.0, 1.0, 1.0, 0.0) | mat3(-32.0, 64.0, 0.0, 0.0, 1.0, -20.125, 0.0, 0.0, 0.0) | mat3(-0.5, -2.25, 0.0, 0.0, 1.0, 36.8125, 8.0, 0.0, 1.0) | mat3(-32.0, 64.0, 0.0, -2.0, -0.5, 0.0, 5.0, 1.0, 1.0) | mat3(-0.75, -0.0322580645161, -32.0, 64.0, 2.0, -8.25, -66.0, 0.0, 1.0) | mat3(1.0, 1.25, 0.0, 0.0, 0.0, 2.0, 255.0, 1.0, 1.0) | mat3(0.0, 0.5, 1.0, 1.0, 36.8125, 3.5, -192.0, 0.0, 0.0) | mat3(-0.5, -2.25, 0.0, 0.0, 0.0, 1.0, -12.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_float_to_mat3
+ values
+ {
+ input bool in0 = [ false | false | false | true | false | false | true | true | true | true ];
+ input float in1 = [ 3.5 | -20.125 | 36.8125 | 0.0 | 2.0 | -8.25 | 1.0 | -0.5 | 1.0 | 0.0 ];
+ input int in2 = [ 255 | -192 | 11 | 0 | 8 | 5 | -66 | 2 | -12 | 1 ];
+ input vec2 in3 = [ vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) ];
+ input bool in4 = [ true | true | false | false | false | true | false | true | false | true ];
+ input bvec2 in5 = [ bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) ];
+ input float in6 = [ 0.0 | 36.8125 | 3.5 | -0.5 | -8.25 | 1.0 | 0.0 | 1.0 | -20.125 | 2.0 ];
+ output mat3 out0 = [ mat3(0.0, 3.5, 255.0, 0.0, 0.5, 1.0, 0.0, 0.0, 0.0) | mat3(0.0, -20.125, -192.0, 0.0, 0.5, 1.0, 0.0, 0.0, 36.8125) | mat3(0.0, 36.8125, 11.0, -0.5, -2.25, 0.0, 1.0, 1.0, 3.5) | mat3(1.0, 0.0, 0.0, 1.0, 1.25, 0.0, 0.0, 1.0, -0.5) | mat3(0.0, 2.0, 8.0, -0.5, -2.25, 0.0, 1.0, 1.0, -8.25) | mat3(0.0, -8.25, 5.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0, 1.0) | mat3(1.0, 1.0, -66.0, -32.0, 64.0, 0.0, 1.0, 0.0, 0.0) | mat3(1.0, -0.5, 2.0, 1.0, 1.25, 1.0, 1.0, 0.0, 1.0) | mat3(1.0, 1.0, -12.0, -0.75, -0.0322580645161, 0.0, 0.0, 0.0, -20.125) | mat3(1.0, 0.0, 1.0, -32.0, 64.0, 1.0, 0.0, 1.0, 2.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_bool_to_mat3
+ values
+ {
+ input bool in0 = [ true | false | false | false | false | true | true | true | true | false ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) ];
+ input int in2 = [ 2 | -66 | 1 | 8 | -12 | 0 | 5 | 11 | 255 | -192 ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input bool in4 = [ false | false | true | true | true | false | true | false | false | true ];
+ output mat3 out0 = [ mat3(1.0, 1.0, 1.0, 2.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 0.0, 0.0, -66.0, -0.5, -2.25, -4.875, 9.0, 0.0) | mat3(0.0, 0.0, 1.0, 1.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(0.0, 0.0, 0.0, 8.0, 1.0, 1.25, 1.125, 1.75, 1.0) | mat3(0.0, 0.0, 0.0, -12.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(1.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(1.0, 0.0, 0.0, 5.0, 0.0, 0.5, 0.75, 0.825, 1.0) | mat3(1.0, 1.0, 1.0, 11.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 1.0, 0.0, 255.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(0.0, 0.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_bool_to_mat3
+ values
+ {
+ input float in0 = [ -0.5 | 36.8125 | 1.0 | 0.0 | -20.125 | 2.0 | -8.25 | 3.5 ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ input bool in3 = [ true | false | true | false | true | false | false | true ];
+ input bool in4 = [ false | true | false | true | false | false | true | true ];
+ output mat3 out0 = [ mat3(-0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0) | mat3(36.8125, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, 0.0, 1.0) | mat3(-20.125, 1.0, 1.0, 1.0, 1.0, 0.0, -2.0, 1.0, 0.0) | mat3(2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3(-8.25, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat3(3.5, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_vec4_to_mat4
+ values
+ {
+ input vec4 in0 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat4 out0 = [ mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.25, 1.125, 1.75, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0) | mat4(-0.5, -2.25, -4.875, 9.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 1.25, 1.125, 1.75) | mat4(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4(0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, -0.5, -2.25, -4.875, 9.0, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_ivec4_to_mat4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ input ivec4 in2 = [ ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in3 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, 1.0, 1.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 9.0) | mat4(0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_bvec4_bvec4_bvec4_to_mat4
+ values
+ {
+ input bvec4 in0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, false) ];
+ input bvec4 in2 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ input bvec4 in3 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat4(1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_ivec3_bvec3_vec4_ivec2_float_vec2_to_mat4
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, -2, -4) ];
+ input bvec3 in2 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input ivec2 in4 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in5 = [ 3.5 | -20.125 | -8.25 | 0.0 | 36.8125 | -0.5 | 1.0 | 2.0 ];
+ input vec2 in6 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ output mat4 out0 = [ mat4(-0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 0.0, 0.0, 3.5, -32.0, 64.0) | mat4(-20.125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, -2.0, -20.125, 1.0, 1.25) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, 0.0, -8.25, -0.75, -0.0322580645161) | mat4(2.0, -32.0, 64.0, -51.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, 0.0, -0.5, -2.25) | mat4(3.5, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 36.8125, 1.0, 1.25) | mat4(36.8125, 0.0, -2.0, -4.0, 1.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 0.0, -2.0, -0.5, 0.0, 0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 0.0, 1.0, 0.0, 0.5) | mat4(0.0, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.0, 2.0, -0.5, -2.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_combine
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.html
new file mode 100644
index 0000000000..8b36a38db8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_matrix_combine';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.test
new file mode 100644
index 0000000000..43e32a614e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_combine.test
@@ -0,0 +1,553 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group matrix_combine "Matrix Combine Constructors"
+
+ case vec2_vec2_to_mat2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) ];
+ input vec2 in1 = [ vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(1.0, 1.25) ];
+ output mat2 out0 = [ mat2(0.0, 0.5, -0.5, -2.25) | mat2(1.0, 1.25, -0.75, -0.0322580645161) | mat2(-32.0, 64.0, -32.0, 64.0) | mat2(-0.75, -0.0322580645161, 0.0, 0.5) | mat2(-0.5, -2.25, 1.0, 1.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_mat2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 1.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(0.0, 1.0, 1.0, 0.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_mat2
+ values
+ {
+ input float in0 = [ 0.0 | -0.5 | -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | -8.25 ];
+ input float in1 = [ -8.25 | 2.0 | -0.5 | -20.125 | 3.5 | 1.0 | 36.8125 | 0.0 ];
+ input float in2 = [ 36.8125 | -8.25 | 3.5 | 2.0 | -0.5 | -20.125 | 1.0 | 0.0 ];
+ input float in3 = [ 36.8125 | 0.0 | 2.0 | 3.5 | -8.25 | -0.5 | -20.125 | 1.0 ];
+ output mat2 out0 = [ mat2(0.0, -8.25, 36.8125, 36.8125) | mat2(-0.5, 2.0, -8.25, 0.0) | mat2(-20.125, -0.5, 3.5, 2.0) | mat2(2.0, -20.125, 2.0, 3.5) | mat2(36.8125, 3.5, -0.5, -8.25) | mat2(1.0, 1.0, -20.125, -0.5) | mat2(3.5, 36.8125, 1.0, -20.125) | mat2(-8.25, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_mat2
+ values
+ {
+ input int in0 = [ 2 | 0 | -66 | 8 | 1 | 255 | 5 | -12 | 11 | -192 ];
+ input int in1 = [ -192 | 2 | 5 | -12 | -66 | 255 | 8 | 1 | 11 | 0 ];
+ input int in2 = [ 2 | 11 | -192 | 255 | 1 | 5 | 0 | -12 | 8 | -66 ];
+ input int in3 = [ 255 | 0 | 11 | -66 | 2 | 8 | -192 | 1 | -12 | 5 ];
+ output mat2 out0 = [ mat2(2.0, -192.0, 2.0, 255.0) | mat2(0.0, 2.0, 11.0, 0.0) | mat2(-66.0, 5.0, -192.0, 11.0) | mat2(8.0, -12.0, 255.0, -66.0) | mat2(1.0, -66.0, 1.0, 2.0) | mat2(255.0, 255.0, 5.0, 8.0) | mat2(5.0, 8.0, 0.0, -192.0) | mat2(-12.0, 1.0, -12.0, 1.0) | mat2(11.0, 11.0, 8.0, -12.0) | mat2(-192.0, 0.0, -66.0, 5.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_mat2
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 1.0, 0.0) | mat2(1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_mat2
+ values
+ {
+ input bool in0 = [ false | true | true | false | false | true | true | true | false | false ];
+ input float in1 = [ -0.5 | -20.125 | 3.5 | 2.0 | 1.0 | 0.0 | 0.0 | 1.0 | 36.8125 | -8.25 ];
+ input int in2 = [ -66 | -192 | 5 | 255 | 0 | -12 | 11 | 1 | 2 | 8 ];
+ input bool in3 = [ true | false | true | false | false | false | true | false | true | true ];
+ output mat2 out0 = [ mat2(0.0, -0.5, -66.0, 1.0) | mat2(1.0, -20.125, -192.0, 0.0) | mat2(1.0, 3.5, 5.0, 1.0) | mat2(0.0, 2.0, 255.0, 0.0) | mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 0.0, -12.0, 0.0) | mat2(1.0, 0.0, 11.0, 1.0) | mat2(1.0, 1.0, 1.0, 0.0) | mat2(0.0, 36.8125, 2.0, 1.0) | mat2(0.0, -8.25, 8.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_mat2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output mat2 out0 = [ mat2(0.0, 0.5, -32.0, 64.0) | mat2(-32.0, 64.0, 0.0, 0.0) | mat2(-0.5, -2.25, 0.0, -2.0) | mat2(-0.75, -0.0322580645161, 0.0, 0.0) | mat2(1.0, 1.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_mat2
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) ];
+ output mat2 out0 = [ mat2(-32.0, 64.0, 0.0, 1.0) | mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, 1.0, 0.0) | mat2(1.0, 1.25, 0.0, 0.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_mat2
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ -20.125 | -0.5 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 1.0, 0.0, -20.125) | mat2(1.0, 1.0, 1.0, -0.5) | mat2(0.0, 0.0, 0.0, 3.5) | mat2(1.0, 0.0, 0.0, -8.25) | mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 2.0) | mat2(0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_mat2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -8.25 | 36.8125 | -0.5 | -20.125 | 1.0 | 2.0 | 0.0 | 3.5 ];
+ output mat2 out0 = [ mat2(0.0, 0.5, 0.75, -8.25) | mat2(1.0, 1.25, 1.125, 36.8125) | mat2(-0.75, -0.0322580645161, 0.0526315789474, -0.5) | mat2(-0.5, -2.25, -4.875, -20.125) | mat2(0.0, 0.5, 0.75, 1.0) | mat2(-32.0, 64.0, -51.0, 2.0) | mat2(-0.5, -2.25, -4.875, 0.0) | mat2(1.0, 1.25, 1.125, 3.5) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_mat2
+ values
+ {
+ input int in0 = [ -66 | 255 | 8 | 0 | 5 | -12 | 1 | -192 | 2 | 11 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input int in2 = [ 0 | -12 | 8 | -66 | 11 | 5 | 255 | 2 | 1 | -192 ];
+ output mat2 out0 = [ mat2(-66.0, 0.0, -2.0, 0.0) | mat2(255.0, 0.0, 0.0, -12.0) | mat2(8.0, -32.0, 64.0, 8.0) | mat2(0.0, 1.0, 1.0, -66.0) | mat2(5.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, 5.0) | mat2(1.0, -32.0, 64.0, 255.0) | mat2(-192.0, 0.0, -2.0, 2.0) | mat2(2.0, 0.0, 0.0, 1.0) | mat2(11.0, 1.0, 1.0, -192.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_mat2
+ values
+ {
+ input bool in0 = [ true | true | true | false | true | false | false | false ];
+ input float in1 = [ 0.0 | 1.0 | 2.0 | -0.5 | 3.5 | -20.125 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 1.0, 1.0) | mat2(1.0, 1.0, 1.0, 1.0) | mat2(1.0, 2.0, 0.0, -2.0) | mat2(0.0, -0.5, 0.0, 0.0) | mat2(1.0, 3.5, -32.0, 64.0) | mat2(0.0, -20.125, 0.0, -2.0) | mat2(0.0, 36.8125, 0.0, 0.0) | mat2(0.0, -8.25, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec3_to_mat3
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in1 = [ vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec3 in2 = [ vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 1.125, -0.5, -2.25, -4.875, -0.5, -2.25, -4.875) | mat3(-0.75, -0.0322580645161, 0.0526315789474, -0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.5, 0.75) | mat3(-32.0, 64.0, -51.0, 0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474) | mat3(-0.5, -2.25, -4.875, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(0.0, 0.5, 0.75, 1.0, 1.25, 1.125, 1.0, 1.25, 1.125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec3_to_mat3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, -2, -4) | ivec3(1, 1, 1) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(0, 0, 0) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec3 in2 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) ];
+ output mat3 out0 = [ mat3(0.0, -2.0, -4.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) | mat3(-32.0, 64.0, -51.0, 0.0, -2.0, -4.0, 0.0, 0.0, 0.0) | mat3(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_bool_to_mat3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input ivec2 in1 = [ ivec2(-32, 64) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) ];
+ input float in2 = [ -20.125 | -8.25 | 3.5 | 1.0 | 1.0 | -0.5 | 2.0 | 0.0 | 36.8125 | 0.0 ];
+ input float in3 = [ 0.0 | -0.5 | 1.0 | -20.125 | 36.8125 | 0.0 | -8.25 | 2.0 | 3.5 | 1.0 ];
+ input int in4 = [ 2 | 11 | 1 | 0 | 8 | 5 | -66 | 255 | -192 | -12 ];
+ input bool in5 = [ false | true | true | false | false | true | false | true | false | true ];
+ input bool in6 = [ false | true | false | false | true | true | true | true | false | false ];
+ output mat3 out0 = [ mat3(-0.75, -0.0322580645161, -32.0, 64.0, -20.125, 0.0, 2.0, 0.0, 0.0) | mat3(1.0, 1.25, 0.0, -2.0, -8.25, -0.5, 11.0, 1.0, 1.0) | mat3(0.0, 0.5, 1.0, 1.0, 3.5, 1.0, 1.0, 1.0, 0.0) | mat3(-32.0, 64.0, 0.0, 0.0, 1.0, -20.125, 0.0, 0.0, 0.0) | mat3(-0.5, -2.25, 0.0, 0.0, 1.0, 36.8125, 8.0, 0.0, 1.0) | mat3(-32.0, 64.0, 0.0, -2.0, -0.5, 0.0, 5.0, 1.0, 1.0) | mat3(-0.75, -0.0322580645161, -32.0, 64.0, 2.0, -8.25, -66.0, 0.0, 1.0) | mat3(1.0, 1.25, 0.0, 0.0, 0.0, 2.0, 255.0, 1.0, 1.0) | mat3(0.0, 0.5, 1.0, 1.0, 36.8125, 3.5, -192.0, 0.0, 0.0) | mat3(-0.5, -2.25, 0.0, 0.0, 0.0, 1.0, -12.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_float_to_mat3
+ values
+ {
+ input bool in0 = [ false | false | false | true | false | false | true | true | true | true ];
+ input float in1 = [ 3.5 | -20.125 | 36.8125 | 0.0 | 2.0 | -8.25 | 1.0 | -0.5 | 1.0 | 0.0 ];
+ input int in2 = [ 255 | -192 | 11 | 0 | 8 | 5 | -66 | 2 | -12 | 1 ];
+ input vec2 in3 = [ vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) ];
+ input bool in4 = [ true | true | false | false | false | true | false | true | false | true ];
+ input bvec2 in5 = [ bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) ];
+ input float in6 = [ 0.0 | 36.8125 | 3.5 | -0.5 | -8.25 | 1.0 | 0.0 | 1.0 | -20.125 | 2.0 ];
+ output mat3 out0 = [ mat3(0.0, 3.5, 255.0, 0.0, 0.5, 1.0, 0.0, 0.0, 0.0) | mat3(0.0, -20.125, -192.0, 0.0, 0.5, 1.0, 0.0, 0.0, 36.8125) | mat3(0.0, 36.8125, 11.0, -0.5, -2.25, 0.0, 1.0, 1.0, 3.5) | mat3(1.0, 0.0, 0.0, 1.0, 1.25, 0.0, 0.0, 1.0, -0.5) | mat3(0.0, 2.0, 8.0, -0.5, -2.25, 0.0, 1.0, 1.0, -8.25) | mat3(0.0, -8.25, 5.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0, 1.0) | mat3(1.0, 1.0, -66.0, -32.0, 64.0, 0.0, 1.0, 0.0, 0.0) | mat3(1.0, -0.5, 2.0, 1.0, 1.25, 1.0, 1.0, 0.0, 1.0) | mat3(1.0, 1.0, -12.0, -0.75, -0.0322580645161, 0.0, 0.0, 0.0, -20.125) | mat3(1.0, 0.0, 1.0, -32.0, 64.0, 1.0, 0.0, 1.0, 2.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_bool_to_mat3
+ values
+ {
+ input bool in0 = [ true | false | false | false | false | true | true | true | true | false ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) ];
+ input int in2 = [ 2 | -66 | 1 | 8 | -12 | 0 | 5 | 11 | 255 | -192 ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input bool in4 = [ false | false | true | true | true | false | true | false | false | true ];
+ output mat3 out0 = [ mat3(1.0, 1.0, 1.0, 2.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 0.0, 0.0, -66.0, -0.5, -2.25, -4.875, 9.0, 0.0) | mat3(0.0, 0.0, 1.0, 1.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(0.0, 0.0, 0.0, 8.0, 1.0, 1.25, 1.125, 1.75, 1.0) | mat3(0.0, 0.0, 0.0, -12.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(1.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(1.0, 0.0, 0.0, 5.0, 0.0, 0.5, 0.75, 0.825, 1.0) | mat3(1.0, 1.0, 1.0, 11.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 1.0, 0.0, 255.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(0.0, 0.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_bool_to_mat3
+ values
+ {
+ input float in0 = [ -0.5 | 36.8125 | 1.0 | 0.0 | -20.125 | 2.0 | -8.25 | 3.5 ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ input bool in3 = [ true | false | true | false | true | false | false | true ];
+ input bool in4 = [ false | true | false | true | false | false | true | true ];
+ output mat3 out0 = [ mat3(-0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0) | mat3(36.8125, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, 0.0, 1.0) | mat3(-20.125, 1.0, 1.0, 1.0, 1.0, 0.0, -2.0, 1.0, 0.0) | mat3(2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3(-8.25, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat3(3.5, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_vec4_to_mat4
+ values
+ {
+ input vec4 in0 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat4 out0 = [ mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.25, 1.125, 1.75, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0) | mat4(-0.5, -2.25, -4.875, 9.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 1.25, 1.125, 1.75) | mat4(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4(0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, -0.5, -2.25, -4.875, 9.0, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_ivec4_to_mat4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ input ivec4 in2 = [ ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in3 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, 1.0, 1.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 9.0) | mat4(0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_bvec4_bvec4_bvec4_to_mat4
+ values
+ {
+ input bvec4 in0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, false) ];
+ input bvec4 in2 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ input bvec4 in3 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat4(1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_ivec3_bvec3_vec4_ivec2_float_vec2_to_mat4
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, -2, -4) ];
+ input bvec3 in2 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input ivec2 in4 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in5 = [ 3.5 | -20.125 | -8.25 | 0.0 | 36.8125 | -0.5 | 1.0 | 2.0 ];
+ input vec2 in6 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ output mat4 out0 = [ mat4(-0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 0.0, 0.0, 3.5, -32.0, 64.0) | mat4(-20.125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, -2.0, -20.125, 1.0, 1.25) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, 0.0, -8.25, -0.75, -0.0322580645161) | mat4(2.0, -32.0, 64.0, -51.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, 0.0, -0.5, -2.25) | mat4(3.5, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 36.8125, 1.0, 1.25) | mat4(36.8125, 0.0, -2.0, -4.0, 1.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 0.0, -2.0, -0.5, 0.0, 0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 0.0, 1.0, 0.0, 0.5) | mat4(0.0, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.0, 2.0, -0.5, -2.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_combine
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.html
new file mode 100644
index 0000000000..c7def9ec14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_matrix_to_matrix';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.test
new file mode 100644
index 0000000000..86826940a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_matrix_to_matrix.test
@@ -0,0 +1,206 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group matrix_to_matrix "Matrix to Matrix Conversions"
+
+ case mat4_to_mat4
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.03125, 0.0625, 0.0, -0.75, 0.015625, 0.03125, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.03125, 0.0625, -0.75, 0.015625, 0.03125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.03125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0) | mat3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_to_matrix
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.html
new file mode 100644
index 0000000000..94dd7c4f8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_scalar_to_matrix';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.test
new file mode 100644
index 0000000000..d08377901f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_matrix.test
@@ -0,0 +1,206 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group scalar_to_matrix "Scalar to Matrix Conversions"
+
+ case float_to_mat4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25) | mat4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125) | mat4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5) | mat3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5) | mat3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25) | mat3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125) | mat3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.5, 0.0, 0.0, 3.5) | mat2(-0.5, 0.0, 0.0, -0.5) | mat2(-8.25, 0.0, 0.0, -8.25) | mat2(-20.125, 0.0, 0.0, -20.125) | mat2(36.8125, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0) | mat4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0) | mat4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0) | mat4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0) | mat3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0) | mat3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0) | mat3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(5.0, 0.0, 0.0, 5.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(11.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, -12.0) | mat2(-66.0, 0.0, 0.0, -66.0) | mat2(-192.0, 0.0, 0.0, -192.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_matrix
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.html
new file mode 100644
index 0000000000..4909afd403
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_scalar_to_scalar';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.test
new file mode 100644
index 0000000000..4fe66869b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_scalar.test
@@ -0,0 +1,206 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group scalar_to_scalar "Scalar to Scalar Conversions"
+
+ case float_to_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_int
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 0 | -8 | -20 | 36 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bool
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_float
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 5.0 | 8.0 | 11.0 | -12.0 | -66.0 | -192.0 | 255.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_int
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output int out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bool
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_float
+ values
+ {
+ input bool in0 = [ true | false ];
+ output float out0 = [ 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_int
+ values
+ {
+ input bool in0 = [ true | false ];
+ output int out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bool
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_scalar
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.html
new file mode 100644
index 0000000000..0cc94ce54c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_scalar_to_vector';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.test
new file mode 100644
index 0000000000..6bb14d8a63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_scalar_to_vector.test
@@ -0,0 +1,602 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group scalar_to_vector "Scalar to Vector Conversions"
+
+ case float_to_vec2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(3.5, 3.5) | vec2(-0.5, -0.5) | vec2(-8.25, -8.25) | vec2(-20.125, -20.125) | vec2(36.8125, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(3.5, 3.5, 3.5) | vec3(-0.5, -0.5, -0.5) | vec3(-8.25, -8.25, -8.25) | vec3(-20.125, -20.125, -20.125) | vec3(36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.5, 3.5, 3.5, 3.5) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-8.25, -8.25, -8.25, -8.25) | vec4(-20.125, -20.125, -20.125, -20.125) | vec4(36.8125, 36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(3, 3) | ivec2(0, 0) | ivec2(-8, -8) | ivec2(-20, -20) | ivec2(36, 36) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(0, 0, 0) | ivec3(-8, -8, -8) | ivec3(-20, -20, -20) | ivec3(36, 36, 36) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(0, 0, 0, 0) | ivec4(-8, -8, -8, -8) | ivec4(-20, -20, -20, -20) | ivec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec2
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec3
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec4
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(5.0, 5.0) | vec2(8.0, 8.0) | vec2(11.0, 11.0) | vec2(-12.0, -12.0) | vec2(-66.0, -66.0) | vec2(-192.0, -192.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(5.0, 5.0, 5.0) | vec3(8.0, 8.0, 8.0) | vec3(11.0, 11.0, 11.0) | vec3(-12.0, -12.0, -12.0) | vec3(-66.0, -66.0, -66.0) | vec3(-192.0, -192.0, -192.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(5.0, 5.0, 5.0, 5.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(11.0, 11.0, 11.0, 11.0) | vec4(-12.0, -12.0, -12.0, -12.0) | vec4(-66.0, -66.0, -66.0, -66.0) | vec4(-192.0, -192.0, -192.0, -192.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(5, 5) | ivec2(8, 8) | ivec2(11, 11) | ivec2(-12, -12) | ivec2(-66, -66) | ivec2(-192, -192) | ivec2(255, 255) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(5, 5, 5) | ivec3(8, 8, 8) | ivec3(11, 11, 11) | ivec3(-12, -12, -12) | ivec3(-66, -66, -66) | ivec3(-192, -192, -192) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(5, 5, 5, 5) | ivec4(8, 8, 8, 8) | ivec4(11, 11, 11, 11) | ivec4(-12, -12, -12, -12) | ivec4(-66, -66, -66, -66) | ivec4(-192, -192, -192, -192) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec2
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec3
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec4
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec3
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_vector
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.html
new file mode 100644
index 0000000000..81ec48f331
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_combine';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.test
new file mode 100644
index 0000000000..222d3e6bfe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_combine.test
@@ -0,0 +1,1844 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_combine "Vector Combine Constructors"
+
+ case vec2_vec2_to_vec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, -32.0, 64.0) | vec4(-32.0, 64.0, 1.0, 1.25) | vec4(1.0, 1.25, 0.0, 0.5) | vec4(0.0, 0.5, -0.5, -2.25) | vec4(-0.75, -0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_ivec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output ivec4 out0 = [ ivec4(0, -2, -32, 64) | ivec4(-32, 64, 1, 1) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_bvec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_vec4
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 1.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) | vec4(1.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_ivec4
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 1, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 1) | ivec4(0, 0, 1, 1) | ivec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_bvec4
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, false, false, false) | bvec4(false, true, false, true) | bvec4(false, false, true, true) | bvec4(true, true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_vec4
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 3.5, 3.5) | vec4(0.0, 36.8125, 36.8125, 36.8125) | vec4(-0.5, -8.25, -8.25, 1.0) | vec4(-8.25, 2.0, 1.0, -8.25) | vec4(3.5, 3.5, 2.0, 2.0) | vec4(-20.125, 1.0, 0.0, 0.0) | vec4(36.8125, -20.125, -20.125, -0.5) | vec4(2.0, -0.5, -0.5, -20.125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_ivec4
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 3, 3) | ivec4(0, 36, 36, 36) | ivec4(0, -8, -8, 1) | ivec4(-8, 2, 1, -8) | ivec4(3, 3, 2, 2) | ivec4(-20, 1, 0, 0) | ivec4(36, -20, -20, 0) | ivec4(2, 0, 0, -20) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_bvec4
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_vec4
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output vec4 out0 = [ vec4(-12.0, 2.0, 11.0, -192.0) | vec4(-66.0, 5.0, 255.0, -66.0) | vec4(2.0, -66.0, 5.0, 8.0) | vec4(5.0, 11.0, 8.0, -12.0) | vec4(8.0, -192.0, 2.0, 1.0) | vec4(-192.0, 8.0, -192.0, 2.0) | vec4(255.0, -12.0, -12.0, 0.0) | vec4(1.0, 1.0, -66.0, 255.0) | vec4(0.0, 255.0, 1.0, 5.0) | vec4(11.0, 0.0, 0.0, 11.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_ivec4
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output ivec4 out0 = [ ivec4(-12, 2, 11, -192) | ivec4(-66, 5, 255, -66) | ivec4(2, -66, 5, 8) | ivec4(5, 11, 8, -12) | ivec4(8, -192, 2, 1) | ivec4(-192, 8, -192, 2) | ivec4(255, -12, -12, 0) | ivec4(1, 1, -66, 255) | ivec4(0, 255, 1, 5) | ivec4(11, 0, 0, 11) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_bvec4
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_vec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 1.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_ivec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output ivec4 out0 = [ ivec4(1, 0, 1, 0) | ivec4(0, 1, 0, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_bvec4
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output bvec4 out0 = [ bvec4(true, false, true, false) | bvec4(false, true, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_vec4
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | true | false | true | false ];
+ input float in1 = [ 1.0 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 | -0.5 | 3.5 | -20.125 | 0.0 ];
+ input int in2 = [ -192 | -12 | 2 | -66 | 255 | 8 | 0 | 5 | 11 | 1 ];
+ input bool in3 = [ true | true | false | false | true | false | false | false | true | true ];
+ output vec4 out0 = [ vec4(1.0, 1.0, -192.0, 1.0) | vec4(1.0, 2.0, -12.0, 1.0) | vec4(1.0, 1.0, 2.0, 0.0) | vec4(0.0, 0.0, -66.0, 0.0) | vec4(0.0, 36.8125, 255.0, 1.0) | vec4(0.0, -8.25, 8.0, 0.0) | vec4(1.0, -0.5, 0.0, 0.0) | vec4(0.0, 3.5, 5.0, 0.0) | vec4(1.0, -20.125, 11.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_ivec4
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | true | false | true | false ];
+ input float in1 = [ 1.0 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 | -0.5 | 3.5 | -20.125 | 0.0 ];
+ input int in2 = [ -192 | -12 | 2 | -66 | 255 | 8 | 0 | 5 | 11 | 1 ];
+ input bool in3 = [ true | true | false | false | true | false | false | false | true | true ];
+ output ivec4 out0 = [ ivec4(1, 1, -192, 1) | ivec4(1, 2, -12, 1) | ivec4(1, 1, 2, 0) | ivec4(0, 0, -66, 0) | ivec4(0, 36, 255, 1) | ivec4(0, -8, 8, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 3, 5, 0) | ivec4(1, -20, 11, 1) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_bvec4
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | true | false | true | false ];
+ input float in1 = [ 1.0 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 | -0.5 | 3.5 | -20.125 | 0.0 ];
+ input int in2 = [ -192 | -12 | 2 | -66 | 255 | 8 | 0 | 5 | 11 | 1 ];
+ input bool in3 = [ true | true | false | false | true | false | false | false | true | true ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(false, false, true, false) | bvec4(false, true, true, true) | bvec4(false, true, true, false) | bvec4(true, true, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_vec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, 0.0, 0.0) | vec4(0.0, 0.5, 0.0, -2.0) | vec4(-32.0, 64.0, -32.0, 64.0) | vec4(1.0, 1.25, 0.0, 0.0) | vec4(-0.75, -0.0322580645161, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_ivec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(0, -2, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(-32, 64, -32, 64) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_bvec4
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(false, true, false, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_vec4
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(-32.0, 64.0, 0.0, 0.0) | vec4(-0.5, -2.25, 1.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.75, -0.0322580645161, 0.0, 1.0) | vec4(0.0, 0.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_ivec4
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(-32, 64, 0, 0) | ivec4(0, -2, 1, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_bvec4
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_vec4
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, true, false) | bvec3(true, true, true) ];
+ input float in1 = [ -8.25 | -20.125 | 2.0 | 0.0 | -0.5 | 3.5 | 36.8125 | 1.0 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, -8.25) | vec4(0.0, 0.0, 0.0, -20.125) | vec4(0.0, 0.0, 0.0, 2.0) | vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 0.0, 0.0, -0.5) | vec4(0.0, 1.0, 0.0, 3.5) | vec4(0.0, 1.0, 0.0, 36.8125) | vec4(1.0, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_ivec4
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, true, false) | bvec3(true, true, true) ];
+ input float in1 = [ -8.25 | -20.125 | 2.0 | 0.0 | -0.5 | 3.5 | 36.8125 | 1.0 ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, -8) | ivec4(0, 0, 0, -20) | ivec4(0, 0, 0, 2) | ivec4(0, 0, 0, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 3) | ivec4(0, 1, 0, 36) | ivec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_bvec4
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, true, false) | bvec3(true, true, true) ];
+ input float in1 = [ -8.25 | -20.125 | 2.0 | 0.0 | -0.5 | 3.5 | 36.8125 | 1.0 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, true) | bvec4(false, true, false, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_vec4
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | -20.125 ];
+ output vec4 out0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.0) | vec4(0.0, 0.5, 0.75, 2.0) | vec4(-0.5, -2.25, -4.875, 36.8125) | vec4(0.0, 0.5, 0.75, 3.5) | vec4(1.0, 1.25, 1.125, 1.0) | vec4(-0.5, -2.25, -4.875, -0.5) | vec4(-32.0, 64.0, -51.0, -8.25) | vec4(1.0, 1.25, 1.125, -20.125) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_ivec4
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | -20.125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 2) | ivec4(0, -2, -4, 36) | ivec4(0, 0, 0, 3) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 0) | ivec4(-32, 64, -51, -8) | ivec4(1, 1, 1, -20) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_bvec4
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_vec4
+ values
+ {
+ input int in0 = [ -66 | 8 | -192 | 255 | 5 | -12 | 0 | 2 | 1 | 11 ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) ];
+ input int in2 = [ 8 | 2 | 11 | -192 | 255 | -12 | 0 | -66 | 1 | 5 ];
+ output vec4 out0 = [ vec4(-66.0, 0.0, 0.0, 8.0) | vec4(8.0, 0.0, 0.0, 2.0) | vec4(-192.0, -32.0, 64.0, 11.0) | vec4(255.0, -32.0, 64.0, -192.0) | vec4(5.0, 1.0, 1.0, 255.0) | vec4(-12.0, 0.0, 0.0, -12.0) | vec4(0.0, 1.0, 1.0, 0.0) | vec4(2.0, 0.0, -2.0, -66.0) | vec4(1.0, 0.0, -2.0, 1.0) | vec4(11.0, 0.0, 0.0, 5.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_ivec4
+ values
+ {
+ input int in0 = [ -66 | 8 | -192 | 255 | 5 | -12 | 0 | 2 | 1 | 11 ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) ];
+ input int in2 = [ 8 | 2 | 11 | -192 | 255 | -12 | 0 | -66 | 1 | 5 ];
+ output ivec4 out0 = [ ivec4(-66, 0, 0, 8) | ivec4(8, 0, 0, 2) | ivec4(-192, -32, 64, 11) | ivec4(255, -32, 64, -192) | ivec4(5, 1, 1, 255) | ivec4(-12, 0, 0, -12) | ivec4(0, 1, 1, 0) | ivec4(2, 0, -2, -66) | ivec4(1, 0, -2, 1) | ivec4(11, 0, 0, 5) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_bvec4
+ values
+ {
+ input int in0 = [ -66 | 8 | -192 | 255 | 5 | -12 | 0 | 2 | 1 | 11 ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) ];
+ input int in2 = [ 8 | 2 | 11 | -192 | 255 | -12 | 0 | -66 | 1 | 5 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(false, true, true, false) | bvec4(true, false, true, true) | bvec4(true, false, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_vec4
+ values
+ {
+ input bool in0 = [ true | true | true | true | false | false | false | false ];
+ input float in1 = [ 2.0 | 0.0 | 3.5 | -8.25 | 36.8125 | -20.125 | 1.0 | -0.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output vec4 out0 = [ vec4(1.0, 2.0, 0.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(1.0, 3.5, -32.0, 64.0) | vec4(1.0, -8.25, 1.0, 1.0) | vec4(0.0, 36.8125, 0.0, -2.0) | vec4(0.0, -20.125, 0.0, -2.0) | vec4(0.0, 1.0, 1.0, 1.0) | vec4(0.0, -0.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_ivec4
+ values
+ {
+ input bool in0 = [ true | true | true | true | false | false | false | false ];
+ input float in1 = [ 2.0 | 0.0 | 3.5 | -8.25 | 36.8125 | -20.125 | 1.0 | -0.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(1, 2, 0, 0) | ivec4(1, 0, 0, 0) | ivec4(1, 3, -32, 64) | ivec4(1, -8, 1, 1) | ivec4(0, 36, 0, -2) | ivec4(0, -20, 0, -2) | ivec4(0, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_bvec4
+ values
+ {
+ input bool in0 = [ true | true | true | true | false | false | false | false ];
+ input float in1 = [ 2.0 | 0.0 | 3.5 | -8.25 | 36.8125 | -20.125 | 1.0 | -0.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, false, true) | bvec4(false, true, false, true) | bvec4(false, true, true, true) | bvec4(false, true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_vec3
+ values
+ {
+ input float in0 = [ 3.5 | 2.0 | -20.125 | -8.25 | 36.8125 | 1.0 | 0.0 | -0.5 ];
+ input float in1 = [ -0.5 | 1.0 | 2.0 | -20.125 | 0.0 | -8.25 | 36.8125 | 3.5 ];
+ input float in2 = [ 0.0 | 1.0 | 3.5 | -8.25 | -0.5 | 36.8125 | -20.125 | 2.0 ];
+ output vec3 out0 = [ vec3(3.5, -0.5, 0.0) | vec3(2.0, 1.0, 1.0) | vec3(-20.125, 2.0, 3.5) | vec3(-8.25, -20.125, -8.25) | vec3(36.8125, 0.0, -0.5) | vec3(1.0, -8.25, 36.8125) | vec3(0.0, 36.8125, -20.125) | vec3(-0.5, 3.5, 2.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_ivec3
+ values
+ {
+ input float in0 = [ 3.5 | 2.0 | -20.125 | -8.25 | 36.8125 | 1.0 | 0.0 | -0.5 ];
+ input float in1 = [ -0.5 | 1.0 | 2.0 | -20.125 | 0.0 | -8.25 | 36.8125 | 3.5 ];
+ input float in2 = [ 0.0 | 1.0 | 3.5 | -8.25 | -0.5 | 36.8125 | -20.125 | 2.0 ];
+ output ivec3 out0 = [ ivec3(3, 0, 0) | ivec3(2, 1, 1) | ivec3(-20, 2, 3) | ivec3(-8, -20, -8) | ivec3(36, 0, 0) | ivec3(1, -8, 36) | ivec3(0, 36, -20) | ivec3(0, 3, 2) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_bvec3
+ values
+ {
+ input float in0 = [ 3.5 | 2.0 | -20.125 | -8.25 | 36.8125 | 1.0 | 0.0 | -0.5 ];
+ input float in1 = [ -0.5 | 1.0 | 2.0 | -20.125 | 0.0 | -8.25 | 36.8125 | 3.5 ];
+ input float in2 = [ 0.0 | 1.0 | 3.5 | -8.25 | -0.5 | 36.8125 | -20.125 | 2.0 ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_vec3
+ values
+ {
+ input int in0 = [ 0 | 2 | 1 | 5 | 255 | 8 | -66 | 11 | -12 | -192 ];
+ input int in1 = [ 2 | 8 | 11 | -12 | -192 | 1 | -66 | 5 | 255 | 0 ];
+ input int in2 = [ -192 | -12 | -66 | 8 | 1 | 2 | 5 | 11 | 255 | 0 ];
+ output vec3 out0 = [ vec3(0.0, 2.0, -192.0) | vec3(2.0, 8.0, -12.0) | vec3(1.0, 11.0, -66.0) | vec3(5.0, -12.0, 8.0) | vec3(255.0, -192.0, 1.0) | vec3(8.0, 1.0, 2.0) | vec3(-66.0, -66.0, 5.0) | vec3(11.0, 5.0, 11.0) | vec3(-12.0, 255.0, 255.0) | vec3(-192.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_ivec3
+ values
+ {
+ input int in0 = [ 0 | 2 | 1 | 5 | 255 | 8 | -66 | 11 | -12 | -192 ];
+ input int in1 = [ 2 | 8 | 11 | -12 | -192 | 1 | -66 | 5 | 255 | 0 ];
+ input int in2 = [ -192 | -12 | -66 | 8 | 1 | 2 | 5 | 11 | 255 | 0 ];
+ output ivec3 out0 = [ ivec3(0, 2, -192) | ivec3(2, 8, -12) | ivec3(1, 11, -66) | ivec3(5, -12, 8) | ivec3(255, -192, 1) | ivec3(8, 1, 2) | ivec3(-66, -66, 5) | ivec3(11, 5, 11) | ivec3(-12, 255, 255) | ivec3(-192, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_bvec3
+ values
+ {
+ input int in0 = [ 0 | 2 | 1 | 5 | 255 | 8 | -66 | 11 | -12 | -192 ];
+ input int in1 = [ 2 | 8 | 11 | -12 | -192 | 1 | -66 | 5 | 255 | 0 ];
+ input int in2 = [ -192 | -12 | -66 | 8 | 1 | 2 | 5 | 11 | 255 | 0 ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_vec3
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_ivec3
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_bvec3
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_vec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | false | true ];
+ input float in1 = [ 0.0 | 2.0 | 1.0 | -0.5 | -8.25 | 3.5 | -20.125 | 1.0 | 0.0 | 36.8125 ];
+ input int in2 = [ -12 | -192 | 2 | 5 | -66 | 255 | 11 | 0 | 8 | 1 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, -12.0) | vec3(1.0, 2.0, -192.0) | vec3(0.0, 1.0, 2.0) | vec3(1.0, -0.5, 5.0) | vec3(0.0, -8.25, -66.0) | vec3(1.0, 3.5, 255.0) | vec3(0.0, -20.125, 11.0) | vec3(1.0, 1.0, 0.0) | vec3(0.0, 0.0, 8.0) | vec3(1.0, 36.8125, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_ivec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | false | true ];
+ input float in1 = [ 0.0 | 2.0 | 1.0 | -0.5 | -8.25 | 3.5 | -20.125 | 1.0 | 0.0 | 36.8125 ];
+ input int in2 = [ -12 | -192 | 2 | 5 | -66 | 255 | 11 | 0 | 8 | 1 ];
+ output ivec3 out0 = [ ivec3(0, 0, -12) | ivec3(1, 2, -192) | ivec3(0, 1, 2) | ivec3(1, 0, 5) | ivec3(0, -8, -66) | ivec3(1, 3, 255) | ivec3(0, -20, 11) | ivec3(1, 1, 0) | ivec3(0, 0, 8) | ivec3(1, 36, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_bvec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | false | true ];
+ input float in1 = [ 0.0 | 2.0 | 1.0 | -0.5 | -8.25 | 3.5 | -20.125 | 1.0 | 0.0 | 36.8125 ];
+ input int in2 = [ -12 | -192 | 2 | 5 | -66 | 255 | 11 | 0 | 8 | 1 ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, false) | bvec3(false, false, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_vec3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input bool in1 = [ false | true | false | true | true ];
+ output vec3 out0 = [ vec3(-0.75, -0.0322580645161, 0.0) | vec3(1.0, 1.25, 1.0) | vec3(-0.5, -2.25, 0.0) | vec3(0.0, 0.5, 1.0) | vec3(-32.0, 64.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_ivec3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input bool in1 = [ false | true | false | true | true ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, 0) | ivec3(0, 0, 1) | ivec3(-32, 64, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_bvec3
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input bool in1 = [ false | true | false | true | true ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, false) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_vec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input float in1 = [ 2.0 | 36.8125 | 0.0 | -20.125 | 1.0 | -0.5 | -8.25 | 3.5 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 2.0) | vec3(0.0, 0.0, 36.8125) | vec3(1.0, 0.0, 0.0) | vec3(0.0, 1.0, -20.125) | vec3(0.0, 0.0, 1.0) | vec3(0.0, 1.0, -0.5) | vec3(0.0, 0.0, -8.25) | vec3(1.0, 1.0, 3.5) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_ivec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input float in1 = [ 2.0 | 36.8125 | 0.0 | -20.125 | 1.0 | -0.5 | -8.25 | 3.5 ];
+ output ivec3 out0 = [ ivec3(1, 0, 2) | ivec3(0, 0, 36) | ivec3(1, 0, 0) | ivec3(0, 1, -20) | ivec3(0, 0, 1) | ivec3(0, 1, 0) | ivec3(0, 0, -8) | ivec3(1, 1, 3) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_bvec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input float in1 = [ 2.0 | 36.8125 | 0.0 | -20.125 | 1.0 | -0.5 | -8.25 | 3.5 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, true) | bvec3(true, false, false) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_vec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in1 = [ 0 | 255 | 1 | 2 | 8 | 11 | -192 | 5 | -12 | -66 ];
+ output vec3 out0 = [ vec3(0.0, 1.0, 0.0) | vec3(0.0, 1.0, 255.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 2.0) | vec3(0.0, 0.0, 8.0) | vec3(0.0, 0.0, 11.0) | vec3(1.0, 1.0, -192.0) | vec3(1.0, 0.0, 5.0) | vec3(1.0, 0.0, -12.0) | vec3(0.0, 0.0, -66.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_ivec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in1 = [ 0 | 255 | 1 | 2 | 8 | 11 | -192 | 5 | -12 | -66 ];
+ output ivec3 out0 = [ ivec3(0, 1, 0) | ivec3(0, 1, 255) | ivec3(1, 1, 1) | ivec3(0, 0, 2) | ivec3(0, 0, 8) | ivec3(0, 0, 11) | ivec3(1, 1, -192) | ivec3(1, 0, 5) | ivec3(1, 0, -12) | ivec3(0, 0, -66) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_bvec3
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in1 = [ 0 | 255 | 1 | 2 | 8 | 11 | -192 | 5 | -12 | -66 ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, false, true) | bvec3(false, false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_vec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | true ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 0.0, -2.0) | vec3(0.0, 0.0, 0.0) | vec3(1.0, -32.0, 64.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_ivec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | true ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 0, -2) | ivec3(0, 0, 0) | ivec3(1, -32, 64) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_bvec3
+ values
+ {
+ input bool in0 = [ false | true | false | true | true ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_vec2
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | -8.25 | -0.5 | 0.0 | -20.125 | 36.8125 | 1.0 ];
+ input float in1 = [ 3.5 | -20.125 | -0.5 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 ];
+ output vec2 out0 = [ vec2(2.0, 3.5) | vec2(3.5, -20.125) | vec2(-8.25, -0.5) | vec2(-0.5, 2.0) | vec2(0.0, 1.0) | vec2(-20.125, 0.0) | vec2(36.8125, 36.8125) | vec2(1.0, -8.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_ivec2
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | -8.25 | -0.5 | 0.0 | -20.125 | 36.8125 | 1.0 ];
+ input float in1 = [ 3.5 | -20.125 | -0.5 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 ];
+ output ivec2 out0 = [ ivec2(2, 3) | ivec2(3, -20) | ivec2(-8, 0) | ivec2(0, 2) | ivec2(0, 1) | ivec2(-20, 0) | ivec2(36, 36) | ivec2(1, -8) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_bvec2
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | -8.25 | -0.5 | 0.0 | -20.125 | 36.8125 | 1.0 ];
+ input float in1 = [ 3.5 | -20.125 | -0.5 | 2.0 | 1.0 | 0.0 | 36.8125 | -8.25 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_vec2
+ values
+ {
+ input int in0 = [ 8 | 255 | -192 | 2 | 0 | 1 | -12 | 11 | -66 | 5 ];
+ input int in1 = [ -66 | 2 | 255 | 8 | -12 | 5 | -192 | 0 | 1 | 11 ];
+ output vec2 out0 = [ vec2(8.0, -66.0) | vec2(255.0, 2.0) | vec2(-192.0, 255.0) | vec2(2.0, 8.0) | vec2(0.0, -12.0) | vec2(1.0, 5.0) | vec2(-12.0, -192.0) | vec2(11.0, 0.0) | vec2(-66.0, 1.0) | vec2(5.0, 11.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_ivec2
+ values
+ {
+ input int in0 = [ 8 | 255 | -192 | 2 | 0 | 1 | -12 | 11 | -66 | 5 ];
+ input int in1 = [ -66 | 2 | 255 | 8 | -12 | 5 | -192 | 0 | 1 | 11 ];
+ output ivec2 out0 = [ ivec2(8, -66) | ivec2(255, 2) | ivec2(-192, 255) | ivec2(2, 8) | ivec2(0, -12) | ivec2(1, 5) | ivec2(-12, -192) | ivec2(11, 0) | ivec2(-66, 1) | ivec2(5, 11) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_bvec2
+ values
+ {
+ input int in0 = [ 8 | 255 | -192 | 2 | 0 | 1 | -12 | 11 | -66 | 5 ];
+ input int in1 = [ -66 | 2 | 255 | 8 | -12 | 5 | -192 | 0 | 1 | 11 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_vec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_ivec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_bvec2
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_vec2
+ values
+ {
+ input float in0 = [ 1.0 | -0.5 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | 2.0 | 1.0 | 0.0 ];
+ input int in1 = [ -192 | -66 | 255 | 1 | 2 | 0 | -12 | 5 | 11 | 8 ];
+ output vec2 out0 = [ vec2(1.0, -192.0) | vec2(-0.5, -66.0) | vec2(-20.125, 255.0) | vec2(0.0, 1.0) | vec2(3.5, 2.0) | vec2(-8.25, 0.0) | vec2(36.8125, -12.0) | vec2(2.0, 5.0) | vec2(1.0, 11.0) | vec2(0.0, 8.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_ivec2
+ values
+ {
+ input float in0 = [ 1.0 | -0.5 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | 2.0 | 1.0 | 0.0 ];
+ input int in1 = [ -192 | -66 | 255 | 1 | 2 | 0 | -12 | 5 | 11 | 8 ];
+ output ivec2 out0 = [ ivec2(1, -192) | ivec2(0, -66) | ivec2(-20, 255) | ivec2(0, 1) | ivec2(3, 2) | ivec2(-8, 0) | ivec2(36, -12) | ivec2(2, 5) | ivec2(1, 11) | ivec2(0, 8) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_bvec2
+ values
+ {
+ input float in0 = [ 1.0 | -0.5 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | 2.0 | 1.0 | 0.0 ];
+ input int in1 = [ -192 | -66 | 255 | 1 | 2 | 0 | -12 | 5 | 11 | 8 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_vec2
+ values
+ {
+ input float in0 = [ 2.0 | -20.125 | 0.0 | 1.0 | -8.25 | -0.5 | 36.8125 | 3.5 ];
+ input bool in1 = [ true | false | false | false | true | true | false | true ];
+ output vec2 out0 = [ vec2(2.0, 1.0) | vec2(-20.125, 0.0) | vec2(0.0, 0.0) | vec2(1.0, 0.0) | vec2(-8.25, 1.0) | vec2(-0.5, 1.0) | vec2(36.8125, 0.0) | vec2(3.5, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_ivec2
+ values
+ {
+ input float in0 = [ 2.0 | -20.125 | 0.0 | 1.0 | -8.25 | -0.5 | 36.8125 | 3.5 ];
+ input bool in1 = [ true | false | false | false | true | true | false | true ];
+ output ivec2 out0 = [ ivec2(2, 1) | ivec2(-20, 0) | ivec2(0, 0) | ivec2(1, 0) | ivec2(-8, 1) | ivec2(0, 1) | ivec2(36, 0) | ivec2(3, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_bvec2
+ values
+ {
+ input float in0 = [ 2.0 | -20.125 | 0.0 | 1.0 | -8.25 | -0.5 | 36.8125 | 3.5 ];
+ input bool in1 = [ true | false | false | false | true | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_vec2
+ values
+ {
+ input int in0 = [ 8 | 255 | 11 | -66 | 0 | -192 | -12 | 1 | 5 | 2 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true | false | true ];
+ output vec2 out0 = [ vec2(8.0, 1.0) | vec2(255.0, 0.0) | vec2(11.0, 1.0) | vec2(-66.0, 0.0) | vec2(0.0, 1.0) | vec2(-192.0, 0.0) | vec2(-12.0, 0.0) | vec2(1.0, 1.0) | vec2(5.0, 0.0) | vec2(2.0, 1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_ivec2
+ values
+ {
+ input int in0 = [ 8 | 255 | 11 | -66 | 0 | -192 | -12 | 1 | 5 | 2 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true | false | true ];
+ output ivec2 out0 = [ ivec2(8, 1) | ivec2(255, 0) | ivec2(11, 1) | ivec2(-66, 0) | ivec2(0, 1) | ivec2(-192, 0) | ivec2(-12, 0) | ivec2(1, 1) | ivec2(5, 0) | ivec2(2, 1) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_bvec2
+ values
+ {
+ input int in0 = [ 8 | 255 | 11 | -66 | 0 | -192 | -12 | 1 | 5 | 2 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_combine
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.html
new file mode 100644
index 0000000000..95b31cf26b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_illegal';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.test
new file mode 100644
index 0000000000..3728ea7023
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_illegal.test
@@ -0,0 +1,548 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_illegal "Illegal Vector Conversions"
+
+ case vec2_to_vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_illegal
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.html
new file mode 100644
index 0000000000..0ce230eb20
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_to_scalar';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.test
new file mode 100644
index 0000000000..8d9bb65c53
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_scalar.test
@@ -0,0 +1,602 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_to_scalar "Vector to Scalar Conversions"
+
+ case vec2_to_float
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_int
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bool
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_float
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_int
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bool
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_float
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_int
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bool
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_float
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_int
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bool
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_float
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_int
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bool
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_float
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_int
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bool
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_float
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_int
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bool
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_float
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_int
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bool
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_float
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_int
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bool
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_scalar
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.html
new file mode 100644
index 0000000000..d2d1ce47e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_to_vector';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.test
new file mode 100644
index 0000000000..3ff9db6f8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/conversions_vector_to_vector.test
@@ -0,0 +1,1196 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_to_vector "Vector to Vector Conversions"
+
+ case vec4_to_vec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec3
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec2
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec3
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec2
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec4 out0 = [ bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec3
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec2
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, -2.0, -4.0, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec3
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec2
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec3
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec2
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec3
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec2
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 1.0) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(0.0, 1.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec3
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec2
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 1, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec3
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec2
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec3
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec2
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec2
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec2
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec2
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec2
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec2
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec2
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec2
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_vector
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.html
new file mode 100644
index 0000000000..f8f9435fb5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'declarations';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.test
new file mode 100644
index 0000000000..4dfb0a4a7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/declarations.test
@@ -0,0 +1,140 @@
+group invalid_declarations "Invalid declarations"
+ case attribute_in_vertex_main
+ expect compile_fail
+ vertex ""
+ void main()
+ {
+ attribute mediump float val;
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case attribute_in_fragment
+ expect compile_fail
+ vertex ""
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ attribute mediump float val;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_in_vertex_main
+ expect compile_fail
+ vertex ""
+ void main()
+ {
+ uniform mediump float val;
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_in_fragment_main
+ expect compile_fail
+ vertex ""
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ uniform mediump float val;
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case varying_in_vertex_main
+ expect compile_fail
+ vertex ""
+ void main()
+ {
+ varying mediump float val;
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ varying mediump float val;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case varying_in_fragment_main
+ expect compile_fail
+ vertex ""
+ varying mediump float val;
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ varying mediump float val;
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case invariant_attribute
+ expect compile_fail
+ vertex ""
+ invariant attribute mediump float val;
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+ case invariant_uniform
+ expect compile_fail
+ vertex ""
+ invariant uniform mediump float val;
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_declarations
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.html
new file mode 100644
index 0000000000..1e6f7e83ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'fragdata';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.test
new file mode 100644
index 0000000000..f7ba4f2957
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/fragdata.test
@@ -0,0 +1,76 @@
+
+case invalid_assign_to_1
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main (void)
+ {
+ gl_FragData[1] = vec4(1.0);
+ }
+ ""
+end
+
+case write_fragcolor_and_fragdata_simple
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main (void)
+ {
+ gl_FragColor = vec4(1.0);
+ gl_FragData[0] = vec4(1.0);
+ }
+ ""
+end
+
+case write_fragcolor_and_fragdata_static_if
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main (void)
+ {
+ if (false)
+ gl_FragColor = vec4(1.0);
+ else
+ gl_FragData[0] = vec4(1.0);
+ }
+ ""
+end
+
+case write_fragcolor_and_fragdata_unused_func
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void unused (void)
+ {
+ gl_FragData[0] = vec4(1.0);
+ }
+ void main (void)
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.html
new file mode 100644
index 0000000000..f197df89a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'functions';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.test
new file mode 100644
index 0000000000..2161a4c81b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/functions.test
@@ -0,0 +1,3475 @@
+# Tests todo:
+# - inout with varyings, attributes, uniforms (and arrays of 'em)
+# - inout with arrays, array elements
+# - inout with array elements
+# - inout by-value semantics (arrays & elements & structs)
+
+# Done:
+# - control flow: return, return in loop, etc.
+
+group datatypes "Function Parameter Data Types"
+
+ case float_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec2
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 1.0) | vec2(2.0, 2.5) ];
+ output float out0 = [ -1.0 | -4.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec2 a)
+ {
+ return -(a.x + a.y);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec3
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec3 a)
+ {
+ return -(a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec4
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, -2.0, 0.5) | vec4(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec4 a)
+ {
+ return -(a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat2
+ values
+ {
+ input mat2 in0 = mat2(0.5, -1.0, 0.2, -1.0);
+ output float out0 = 0.5;
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat2 a)
+ {
+ //return -(a[0][0] + a[0][1] + a[1][0] + a[1][1]);
+ return a[0][0];
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ values
+ {
+ input mat3 in0 = [ mat3(0.0, 1.0, -2.0, 0.5, 1.0, -1.0, 2.0, 4.0, -1.0) | mat3(2.0, 2.5, 4.0, -7.0, 2.5, 3.0, 0.5, -3.5, 1.0) ];
+ output float out0 = [ -4.5 | -5.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat3 a)
+ {
+ return -(a[0][0] + a[0][1] + a[0][2] + a[1][0] + a[1][1] + a[1][2] + a[2][0] + a[2][1] + a[2][2]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat4
+ values
+ {
+ input mat4 in0 = [ mat4(0.0, 1.0, -2.0, 0.5, 1.0, -1.0, 2.0, 4.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -2.0, -2.0) | mat4(2.0, 2.5, 4.0, -7.0, 2.5, 3.0, 0.5, -3.5, 1.0, 0.0, 2.0, -1.0, 1.0, 0.0, -1.0, 3.0) ];
+ output float out0 = [ -5.5 | -9.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat4 a)
+ {
+ return -(a[0][0] + a[0][1] + a[0][2] + a[0][3] + a[1][0] + a[1][1] + a[1][2] + a[1][3] + a[2][0] + a[2][1] + a[2][2] + a[2][3] + a[3][0] + a[3][1] + a[3][2] + a[3][3]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int
+ values
+ {
+ input int in0 = [ -1 | 0 | 1 | 4 ];
+ output int out0 = [ 1 | 0 | -1 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (int a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 0) | ivec2(1, 4) ];
+ output int out0 = [ 1 | -5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec2 a)
+ {
+ return -(a.x + a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec3
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 0, 2) | ivec3(1, 4, -8) ];
+ output int out0 = [ -1 | 3 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec3 a)
+ {
+ return -(a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec4
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 0, 2, 2) | ivec4(1, 4, -8, 2) ];
+ output int out0 = [ -3 | 1 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec4 a)
+ {
+ return -(a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bool a)
+ {
+ return !a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, true) ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec2 a)
+ {
+ return !(a.x == a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec3
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, true, false) | bvec3(true, false, false) ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec3 a)
+ {
+ return (a.x == a.y) == a.z;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, true, false) | bvec4(false, false, true, true) | bvec4(true, false, false, true) ];
+ output bool out0 = [ false | true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec4 a)
+ {
+ return ((a.x == a.y) == (a.z == a.w));
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ values
+ {
+ input mat2 in0 = [ mat2(-2.0, 0.5, -1.0, 1.0) | mat2(1.0, -3.5, -3.5, 2.5) | mat2(-2.0, -2.0, 3.5, 0.0) ];
+ output mat2 out0 = [ mat2(4.0, -1.0, 2.0, -2.0) | mat2(-2.0, 7.0, 7.0, -5.0) | mat2(4.0, 4.0, -7.0, -0.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2 func (mat2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3
+ values
+ {
+ input mat3 in0 = [ mat3(2.5, 0.0, 1.0, -2.5, 1.0, 3.0, 0.0, 2.0, 1.5) | mat3(-3.5, 2.0, 0.5, -1.5, -3.5, 2.5, 0.0, 1.5, 3.0) | mat3(1.5, 3.0, -1.0, 2.5, -0.5, 3.5, 3.0, -3.0, -2.5) ];
+ output mat3 out0 = [ mat3(-5.0, -0.0, -2.0, 5.0, -2.0, -6.0, -0.0, -4.0, -3.0) | mat3(7.0, -4.0, -1.0, 3.0, 7.0, -5.0, -0.0, -3.0, -6.0) | mat3(-3.0, -6.0, 2.0, -5.0, 1.0, -7.0, -6.0, 6.0, 5.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3 func (mat3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4
+ values
+ {
+ input mat4 in0 = [ mat4(-2.0, 3.5, -0.5, 1.0, -1.5, 0.0, -1.0, -1.0, 0.5, 0.5, 3.0, 1.5, 3.0, 2.5, 3.5, 1.5) | mat4(-2.5, 2.5, 3.5, 3.0, 0.5, 1.5, -2.0, 2.5, 0.5, -1.5, -3.5, 2.5, 3.5, -3.0, 2.5, -0.5) | mat4(-2.5, -1.5, 2.0, 3.0, -3.5, 1.0, -3.5, 1.5, -1.5, 3.0, 3.5, 0.0, 3.5, -1.5, -3.0, 0.5) ];
+ output mat4 out0 = [ mat4(4.0, -7.0, 1.0, -2.0, 3.0, -0.0, 2.0, 2.0, -1.0, -1.0, -6.0, -3.0, -6.0, -5.0, -7.0, -3.0) | mat4(5.0, -5.0, -7.0, -6.0, -1.0, -3.0, 4.0, -5.0, -1.0, 3.0, 7.0, -5.0, -7.0, 6.0, -5.0, 1.0) | mat4(5.0, 3.0, -4.0, -6.0, 7.0, -2.0, 7.0, -3.0, 3.0, -6.0, -7.0, -0.0, -7.0, 3.0, 6.0, -1.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4 func (mat4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_struct
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+
+ float func (Pos p)
+ {
+ return -(p.a + p.b + p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ out0 = func(p);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct_struct
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+
+ Pos func (Pos p)
+ {
+ return Pos(-p.a, -p.b, -p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ p = func(p);
+ out0 = p.a + p.b + p.c;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct_nested_struct
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+ struct Line { Pos start, end; };
+
+ Line func (Pos p)
+ {
+ return Line(p, Pos(-p.a, -p.b, -p.c));
+ }
+
+ float sum (Pos p)
+ {
+ return (p.a + p.b + p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ Line line = func(p);
+ out0 = sum(line.start) + (2.0 * sum(line.end));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # datatypes
+
+group qualifiers "Function Parameter Qualifiers"
+
+ case in_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_lowp_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in lowp float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_lowp_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out lowp float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_lowp_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout lowp float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_highp_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in highp float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_highp_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out highp float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_highp_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout highp float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (const float a)
+ {
+ float b = -a;
+ return 2.0 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_in_float
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (const in float a)
+ {
+ float b = -a;
+ return 2.0 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_lowp_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in lowp int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_lowp_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out lowp int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_lowp_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout lowp int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_highp_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in highp int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_highp_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out highp int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_highp_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout highp int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_in_int
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const in int a)
+ {
+ int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_bool
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a)
+ {
+ a = !a;
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = in0;
+ bool g = func(f);
+ out0 = (f != g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_bool
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (out bool a)
+ {
+ a = false;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = true;
+ func(f);
+ out0 = (in0 == f);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_bool
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (inout bool a)
+ {
+ a = !a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = true;
+ func(f);
+ out0 = (in0 == f);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # qualifiers
+
+group declarations "Function Declarations"
+
+ case void_vs_no_void
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func ();
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+
+ float func (void)
+ {
+ return -1.0;
+ }
+ ""
+ end
+
+ case in_vs_no_in
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+
+ float func (in float f)
+ {
+ return -f;
+ }
+ ""
+ end
+
+ case default_vs_explicit_precision
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+
+ float func (mediump float f)
+ {
+ return -f;
+ }
+ ""
+ end
+
+end # declarations
+
+group overloading "Function Overloading"
+
+ case user_func_arg_type_simple
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ int func (int a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ out0 = func(in0) * float(func(-1));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_float_types
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a) { return -a; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+
+ void main()
+ {
+ out0 = func(func(func(func(vec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_int_types
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(func(func(func(ivec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_bool_types
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(func(func(func(bvec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_basic_types
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a) { return -a; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ if (func(func(bvec4(false)).x))
+ out0 = func(in0) * float(func(-1));
+ else
+ out0 = float(func(func(ivec4(func(func(func(vec4(0.5)).xyz).xy).xxxx)).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_complex_types
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+ struct Line { Pos start, end; };
+
+ float func (float a) { return -a; }
+ float func (float a[4]) { return a[0] + a[3]; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+ vec4 func (vec4 a[4]) { return a[1] + a[2]; }
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+ Pos func (Pos a) { return a; }
+ Line func (Line a) { return Line(a.end, a.start); }
+
+ void main()
+ {
+ ${SETUP}
+ float arr[4];
+ vec4 arr2[4];
+ out0 = func(arr) + func(arr2).x;
+ if (func(func(bvec4(false)).x))
+ out0 = func(in0) * float(func(-1));
+ else
+ out0 = float(func(func(ivec4(func(func(func(vec4(0.5)).xyz).xy).xxxx)).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arguments
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ float func (float a, float b)
+ {
+ return a * b;
+ }
+
+ void main()
+ {
+ out0 = func(in0) * func(-0.5, -2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case builtin_sin
+ values
+ {
+ input int in0 = [ -1 | 0 | 1 | 4 ];
+ output int out0 = [ 1 | 0 | -1 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int sin(int a) { return -a; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = sin(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case builtin_step
+ values
+ {
+ input int in0 = [ -1 | 0 | 1 | 4 ];
+ output int out0 = [ 1 | 0 | -1 | -4 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int step (float i, float j, int a) { return -a; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = step(0.0, 1.0, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_size
+ values
+ {
+ output float out0 = [ 1.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f[3])
+ {
+ return f[0];
+ }
+
+ float func (float f[4])
+ {
+ return f[1];
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ float x[4];
+ x[0] = -1.0;
+ x[1] = 1.0;
+ x[2] = x[3] = 0.0;
+ out0 = func(x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # overloading
+
+group array_arguments "Arrays as Arguments"
+
+ case local_in_float
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (in float a[4])
+ {
+ a[0] = -1.0;
+ a[2] = -4.0;
+ a[3] = -3.0 * a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ float arr[4];
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_float
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (in float a[4])
+ {
+ a[0] = -1.0;
+ a[2] = -4.0;
+ a[3] = -3.0 * a[1];
+ return a[0];
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_in_int
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, -4) | ivec4(-7, -11, 13, 19) ];
+ output ivec4 out0 = [ ivec4(0, -1, -2, 4) | ivec4(7, 11, -13, -19) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a[4])
+ {
+ a[0] = -1;
+ a[2] = -4;
+ a[3] = -3 * a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int arr[4];
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ int f = func(arr);
+ out0 = f * ivec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_int
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, 4) | ivec4(-7, -11, 13, 19) ];
+ output ivec4 out0 = [ ivec4(0, -1, -2, -4) | ivec4(7, 11, -13, -19) ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a[4])
+ {
+ a[0] = -1;
+ a[2] = -4;
+ a[3] = -3 * a[1];
+ return a[0];
+ }
+
+ int arr[4];
+
+ void main()
+ {
+ ${SETUP}
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ int f = func(arr);
+ out0 = f * ivec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+
+ ""
+ end
+
+ case local_in_bool
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a[4])
+ {
+ a[0] = false;
+ a[2] = true;
+ a[3] = !a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool arr[4];
+ arr[0] = !in0.x;
+ arr[1] = !in0.y;
+ arr[2] = !in0.z;
+ arr[3] = !in0.w;
+ func(arr);
+ out0 = bvec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_bool
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a[4])
+ {
+ a[0] = false;
+ a[2] = true;
+ a[3] = !a[1];
+ return a[0];
+ }
+
+ bool arr[4];
+
+ void main()
+ {
+ ${SETUP}
+ arr[0] = !in0.x;
+ arr[1] = !in0.y;
+ arr[2] = !in0.z;
+ arr[3] = !in0.w;
+ func(arr);
+ out0 = bvec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case test_helpers
+ desc "Check that helper functions are supported properly."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output float out0 = [ 1.0 | 1.0 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ negate(arr);
+ out0 = float(test(arr, -in0));
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_local_in_on_call
+ desc "Check that local 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ a[0] = 2.123;
+ a[2] = -4.123;
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ out0 = in0 * func(arr, arr);
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_global_in_on_call
+ desc "Check that global 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ a[0] = 2.123;
+ a[2] = -4.123;
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ set(arr, in0);
+ out0 = in0 * func(arr, arr);
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_local_inout_on_call
+ desc "Check that local 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (inout float a[4], inout float b[4])
+ {
+ negate(a);
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ float m = func(arr, arr); // returns -1.0
+ float n = float(test(arr, in0) || test(arr, -in0));
+ out0 = in0 * m * n;
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_global_inout_on_call
+ desc "Check that global 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ negate(a);
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ set(arr, in0);
+ float m = func(arr, arr); // returns -1.0
+ float n = float(test(arr, in0) || test(arr, -in0));
+ out0 = in0 * m * n;
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+# vec4 get (in float arr[4]);
+# void set (out float arr[4], vec4 val);
+# void negate (inout float arr[4]);
+# bool test (in float arr[4], vec4 ref);
+# bool isEqual (in float a[4], in float b[4]);
+
+# float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+# vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+# void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+# void negate (inout float arr[4]) { set(arr, -get(arr)); }
+# bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+# bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+
+end # array_arguments
+
+#group qualifiers "Function Parameter Qualifiers"
+#
+#end # qualifiers
+
+group control_flow "Control Flow In Functions"
+
+ case simple_return
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ a = a * -1.0;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_if
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ if (a != 0.0)
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_else
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ if (a == 0.0)
+ return 1.0;
+ else
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_loop
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 1; i++)
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_loop_if
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ if (i == 1)
+ return a;
+ else if (i > 1)
+ return -1.0;
+ a = -a;
+ }
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_loop
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 5; i++)
+ a = -a;
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_break
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ a = -a;
+ if (i == 4)
+ break;
+ }
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_continue
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ if (i == 4)
+ continue;
+ a = -a;
+ }
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_nested_loop
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ a = -a;
+ for (int j = 0; j < 4; j++)
+ {
+ a = -a;
+ if (i == 1)
+ return a;
+ }
+ if (i == 4)
+ return 1.0;
+ }
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_loop_sequence
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++) // negate a
+ {
+ a = -a;
+ if (i == 4)
+ a = -a;
+ }
+
+ for (int i = 6; i < 10; i++) // keep a
+ {
+ if (i == 8)
+ continue;
+ else if (i == 9)
+ break;
+ a = -a;
+ }
+
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_return_break_continue
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ if (i == 0)
+ continue;
+ else if (i == 1)
+ {
+ }
+ else if (i == 3)
+ break;
+ else
+ return a;
+ a = -a;
+ }
+
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # control_flow
+
+group misc "Miscellaneous"
+
+ case multi_arg_float
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, -2.0, 0.5) | vec4(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ]; # -sum(in0)
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sum(vec4 v) { return (v.x + v.y + v.z + v.w); }
+
+ float func (float a, vec3 b, vec2 c, vec2 d, vec4 e)
+ {
+ return -sum(vec4(a, b) + vec4(c, d)) + sum(e);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0.y, in0.xzw, in0.wz, in0.yx, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multi_arg_int
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 0, 2, 2) | ivec4(1, 4, -8, 2) ];
+ output int out0 = [ -3 | 1 ];
+ }
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int sum(ivec4 v) { return (v.x + v.y + v.z + v.w); }
+
+ int func (int a, ivec3 b, ivec2 c, ivec2 d, ivec4 e)
+ {
+ return -sum(ivec4(a, b) + ivec4(c, d)) + sum(e);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0.y, in0.xzw, in0.wz, in0.yx, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case argument_eval_order_1
+ values
+ {
+ input int in0 = [ 0 | 1 | 3 | 5 ];
+ output int out0 = [ -1 | 5 | 11 | 17 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int func (float a, int b, bool c, int d)
+ {
+ if (c)
+ return b + int(a) + d;
+ else
+ return -1;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ float v0 = float(in0);
+ int v1 = in0;
+ out0 = func((v0 += 1.0), v1++, (v0 > 1.5), v1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case argument_eval_order_2
+ values
+ {
+ input int in0 = [ 0 | -1 | 3 | 5 ];
+ output int out0 = [ 3 | -1 | 9 | 13 ];
+ }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int g;
+
+ int modG (int v)
+ {
+ g += v;
+ return v;
+ }
+
+ int func (float a, int b, bool c, int d)
+ {
+ if (c)
+ return b + int(a) + d;
+ else
+ return -1;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ out0 = func(float(g = in0), modG(2), --g > 0, g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case missing_returns
+ values
+ {
+ input float in0 = [ 1.0 | 2.0 | 3.0 ];
+ output float out0 = [ -1.0 | -2.0 | -3.0 ];
+ }
+ both ""
+ // Note specification says that returned value is undefined if no return
+ // statement has been executed. In this case func() is called only with
+ // positive values.
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f)
+ {
+ if (f > 0.0)
+ return -f;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # misc
+
+group invalid "Invalid Functions"
+ case break_in_body
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func ()
+ {
+ break;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case continue_in_body
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func ()
+ {
+ continue;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_value_from_void_function
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func ()
+ {
+ return 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case extra_arguments
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (float f)
+ {
+ }
+
+ void main ()
+ {
+ func(1.0, 2.0);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_arguments
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (float f)
+ {
+ }
+
+ void main ()
+ {
+ func();
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_argument_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (in f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_basetype_mismatch
+ expect compile_fail
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ void func (float f)
+ {
+ }
+
+ void main ()
+ {
+ func(2);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_scalar_vector_mismatch
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec2 f)
+ {
+ }
+
+ void main ()
+ {
+ func(2.0);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_vector_size_mismatch
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ func(vec2(2.0));
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case duplicate_function
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f);
+
+ void func (vec3 f)
+ {
+ }
+
+ void func (vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f);
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ float func (vec3 f)
+ {
+ return f.x;
+ }
+ ""
+ end
+
+ case prototype_unspecified_array_size
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f[]);
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case call_mismatch_argument_array_size
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f[3]);
+ void func (vec3 f[3])
+ {
+ }
+
+ void main ()
+ {
+ vec3 array[4];
+ func(array);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_argument_const
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f);
+ void func (const vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_argument_array_const
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f[3]);
+ void func (const vec3 f[3])
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_array_inout
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (out vec3 f);
+ void func (inout vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ func (float f);
+ func (inout vec3 f[3])
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case call_before_definition
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void main ()
+ {
+ func(1.0);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ void func (float f)
+ {
+ }
+
+ ""
+ end
+
+ case return_array_in_struct
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ struct Foo
+ {
+ float f;
+ float arr[2];
+ };
+
+ Foo func ()
+ {
+ Foo f;
+ f.f = 1.0;
+ f.arr[0] = 2.0;
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_precision_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ float func (lowp float f)
+ {
+ return f;
+ }
+
+ float func (mediump float f)
+ {
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_in_out_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (in float f)
+ {
+ }
+
+ void func (out float f)
+ {
+ f = 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_in_inout_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (in float f)
+ {
+ }
+
+ void func (inout float f)
+ {
+ f = -f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_out_inout_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (out float f)
+ {
+ f = -1.0;
+ }
+
+ void func (inout float f)
+ {
+ f = -f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_type_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ float func (float f)
+ {
+ return f;
+ }
+
+ int func (float f)
+ {
+ return int(f);
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_type_precision_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ lowp float func (float f)
+ {
+ return f;
+ }
+
+ mediump float func (float f)
+ {
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_type_const_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ float func (float f)
+ {
+ return f;
+ }
+
+ const float func (float f)
+ {
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_without_value
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ float func (float f)
+ {
+ return;
+ return 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case local_function_prototype
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void main ()
+ {
+ float func (float f);
+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case local_function_definition
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void main ()
+ {
+ float func (float f)
+ {
+ return 1.0;
+ }
+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case name_type_conflict
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ struct foo { float a; }
+
+ float foo (float f)
+ {
+ return 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case const_overload
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f)
+ {
+ }
+
+ void func (const vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_local
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f)
+ {
+ uniform float u;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case varying_local
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f)
+ {
+ varying float v;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case attribute_local
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (vec3 f)
+ {
+ attribute float a;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_argument
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (uniform vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case varying_argument
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (varying vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case attribute_argument
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void func (attribute vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ uniform float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case varying_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ varying float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case attribute_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ attribute float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case main_invalid_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ float main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case main_has_arguments
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ void main (float f)
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case main_missing_return_type
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case write_const_arg
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ func (const float f)
+ {
+ f = 1.0;
+ }
+
+ main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case write_const_array_arg
+ expect compile_fail
+ both ""
+ precision mediump float;
+
+ func (const float f[3])
+ {
+ f[0] = 1.0;
+ }
+
+ main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case modify_const_arg
+ expect compile_fail
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(3));
+ }
+ ""
+ end
+
+ case init_const_local_from_const_arg
+ expect compile_fail
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ const int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(3));
+ }
+ ""
+ end
+
+ case array_size_from_const_arg
+ expect compile_fail
+ both ""
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ int arr[a];
+ arr[1] = 3;
+ return arr[1];
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(3));
+ }
+ ""
+ end
+
+ case double_declare
+ expect compile_fail
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+ float func (float f);
+
+ float func (float f)
+ {
+ return -f;
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+end # invalid
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.html
new file mode 100644
index 0000000000..2085a16a63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'invalid_texture_functions';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.test
new file mode 100644
index 0000000000..7641da2282
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/invalid_texture_functions.test
@@ -0,0 +1,90 @@
+
+case texture2d_bias_in_vertex
+ expect compile_fail
+ values {}
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ uniform lowp sampler2D s;
+
+ void main()
+ {
+ vec4 r = texture2D(s, vec2(1.0), 1.0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+case texturecube_bias_in_vertex
+ expect compile_fail
+ values {}
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ uniform lowp samplerCube s;
+
+ void main()
+ {
+ vec4 r = textureCube(s, vec3(1.0), 1.0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+case texture2dlod_in_fragment
+ expect compile_fail
+ values {}
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ uniform sampler2D s;
+
+ void main()
+ {
+ gl_FragColor = texture2DLod(s, vec2(0), 1.0);
+ }
+ ""
+end
+
+case texturecubelod_in_fragment
+ expect compile_fail
+ values {}
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ uniform samplerCube s;
+
+ void main()
+ {
+ gl_FragColor = textureCubeLod(s, vec3(0), 1.0);
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.html
new file mode 100644
index 0000000000..3c7b576ca4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'keywords';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.test
new file mode 100644
index 0000000000..16fc390654
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/keywords.test
@@ -0,0 +1,1613 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group keywords "Usage of keywords as identifiers."
+
+ case attribute
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float attribute = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case const
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float const = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uniform
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uniform = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case varying
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float varying = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case break
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float break = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case continue
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float continue = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case do
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float do = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case for
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float for = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case while
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float while = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case if
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float if = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case else
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float else = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case in
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float in = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case out
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float out = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case inout
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float inout = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case float
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float float = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case int
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float int = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case void
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float void = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bool
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bool = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case true
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float true = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case false
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float false = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case lowp
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float lowp = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mediump
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mediump = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case highp
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float highp = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float precision = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case invariant
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float invariant = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case discard
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float discard = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case return
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float return = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case vec2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float vec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case vec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float vec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case vec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float vec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case ivec2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float ivec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case ivec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float ivec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case ivec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float ivec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bvec2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2D
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case samplerCube
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float samplerCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case struct
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float struct = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # keywords
+group reserved_keywords "Usage of reserved keywords as identifiers."
+
+ case asm
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float asm = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case class
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float class = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case union
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float union = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case enum
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float enum = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case typedef
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float typedef = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case template
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float template = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case this
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float this = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case packed
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float packed = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case goto
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float goto = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case switch
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float switch = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case default
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float default = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case inline
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float inline = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case noinline
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float noinline = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case volatile
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float volatile = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case public
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float public = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case static
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float static = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case extern
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float extern = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case external
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float external = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case interface
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float interface = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case flat
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float flat = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case long
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float long = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case short
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float short = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case double
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float double = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case half
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float half = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fixed
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fixed = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case unsigned
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float unsigned = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case superp
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float superp = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case input
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float input = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case output
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float output = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case hvec2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float hvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case hvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float hvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case hvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float hvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case dvec2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float dvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case dvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float dvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case dvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float dvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fvec2
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fvec3
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fvec4
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler1D
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler3D
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler1DShadow
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler1DShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DShadow
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DRect
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DRect = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler3DRect
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler3DRect = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DRectShadow
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DRectShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sizeof
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sizeof = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case cast
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float cast = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case namespace
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float namespace = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case using
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float using = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # reserved_keywords
+group invalid_identifiers "Usage of invalid identifiers."
+
+ case gl_begin
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float gl_Invalid = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case digit
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float 0123 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case digit_begin
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float 0invalid = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # invalid_identifiers
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.html
new file mode 100644
index 0000000000..adf118b7da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'linkage';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.test
new file mode 100644
index 0000000000..319a85858b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/linkage.test
@@ -0,0 +1,1715 @@
+# not declared in vertex shader, declared in fragment shader
+case varying_1
+ desc "varying declared in fragment shader, no reference in vertex shader"
+ values { output float out0 = 1.0; }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ varying mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+# declared in vertex shader, no reference in frag shader
+case varying_2
+ desc "varying declared in vertex shader, no reference in fragment shader"
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# declared in vertex shader, declared in frag shader
+case varying_3
+ desc "varying declared in both vertex and fragment shader, but not used"
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump float var;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# declared in vertex shader, static use in frag shader
+case varying_4
+ desc "varying declared in both shaders, statically used in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump float var;
+ uniform bool u_false;
+ void main()
+ {
+ if (u_false)
+ gl_FragColor = vec4(var);
+ else
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# static use in vertex shader, no reference in fragment shader
+case varying_5
+ desc "varying declared and statically used in vertex shader, no reference in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# static use in vertex shader, declared in fragment shader
+case varying_6
+ desc "varying declared and statically used in vertex shader, only declared in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump float var;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# static use in vertex shader, used in fragment shader
+case varying_7
+ desc "varying statically used in both vertex and fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ if (u_false)
+ gl_FragColor = vec4(var);
+ else
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+case varying_type_float
+ desc "varying of type float"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_type_vec2
+ desc "varying of type vec2"
+ values
+ {
+ input vec2 in0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ output vec2 out0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump vec2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying vec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_type_vec3
+ desc "varying of type vec3"
+ values
+ {
+ input vec3 in0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump vec3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying vec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_type_vec4
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_type_mat2
+ desc "varying of type mat2"
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump mat2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying mat2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_type_mat3
+ desc "varying of type mat3"
+ values
+ {
+ input mat3 in0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ output mat3 out0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump mat3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying mat3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_type_mat4
+ desc "varying of type mat4"
+ values
+ {
+ input mat4 in0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ output mat4 out0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump mat4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying mat4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+# differing precision tests
+case varying_differing_precision_1
+ desc "varying declared as highp in vertex shader, but mediump in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.55 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.55 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying highp float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+# differing precision tests
+case varying_differing_precision_2
+ desc "varying declared as highp in vertex shader, but lowp in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.56 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.56 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying highp vec2 var;
+ void main()
+ {
+ var = vec2(in0, 2.0*in0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying lowp vec2 var;
+ void main()
+ {
+ out0 = var.y - var.x;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+# differing precision tests
+case varying_differing_precision_3
+ desc "varying declared as lowp in vertex shader, but mediump in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying lowp vec4 var;
+ void main()
+ {
+ var = vec4(in0, 2.0*in0, -in0, -in0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump vec4 var;
+ void main()
+ {
+ out0 = var.x + var.y + var.z + var.w;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+# mismatched type, static use but no runtime use in the fragment shader
+case varying_type_mismatch_1
+ desc "varying type mismatch (float vs. vec2), static use but no runtime use in the fragment shader"
+ expect link_fail
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ var = 2.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump vec2 var;
+ void main()
+ {
+ if (false)
+ {
+ gl_FragColor = vec4(var.y);
+ }
+ else
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ }
+ ""
+end
+
+# mismatched type, varyings used
+case varying_type_mismatch_2
+ desc "varying type mismatch (float vs. vec2)"
+ expect link_fail
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump float var;
+ void main()
+ {
+ var = 2.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump vec2 var;
+ void main()
+ {
+ gl_FragColor = var.xyyx;
+ }
+ ""
+end
+
+# no declaration in vertex shader, but static use in fragment
+case varying_illegal_usage_1
+ desc "varying not declared in vertex shader, but statically used in fragment shader"
+ expect link_fail
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump float var;
+ void main()
+ {
+ gl_FragColor = vec4(var);
+ }
+ ""
+end
+
+# integer varyings not allowed
+case invalid_varying_type_int
+ desc "integer varying used"
+ expect compile_fail
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying mediump int var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying mediump int var;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# bool varyings not allowed
+case invalid_varying_type_bool
+ desc "boolean varying used"
+ expect compile_fail
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying bool var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying bool var;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+# struct varyings not allowed
+case invalid_varying_type_struct
+ desc "struct varying used"
+ expect compile_fail
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ varying struct { mediump float foo; } var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ varying struct { mediump float foo; } var;
+ void main()
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
+
+case varying_readback_1
+ desc "read back (an already written) varying in the vertex shader"
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -2.0 | 10.0 ];
+ output float out0 = [ 3.0 | 0.0 | -6.0 | 30.0 ];
+ }
+ vertex ""
+ precision mediump float;
+ ${VERTEX_DECLARATIONS}
+ varying float var1;
+ varying float var2;
+
+ void main()
+ {
+ var1 = in0;
+ var2 = var1 + in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying float var1;
+ varying float var2;
+
+ void main()
+ {
+ out0 = var1 + var2;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case varying_writeback_1
+ desc "write back a varying in the fragment shader"
+ expect compile_fail
+ vertex ""
+ precision mediump float;
+ ${VERTEX_DECLARATIONS}
+ varying float var1;
+ varying float var2;
+
+ void main()
+ {
+ var1 = in0;
+ var2 = var1 + in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ varying float var1;
+ varying float var2;
+
+ void main()
+ {
+ var2 = var1;
+ out0 = var1;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+# Struct linkage handling
+case uniform_struct
+ desc "Same uniform struct in both shaders"
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ void main()
+ {
+ dummy = val.a + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.b + val.a;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vertex_only
+ desc "Uniform struct declared in both, used only in vertex."
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_fragment_only
+ desc "Uniform struct declared in both, used only in fragment."
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.a + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial
+ desc "Uniform struct declared in both, used partially in both."
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vec4
+ desc "Same uniform struct in both shaders. Datatype vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ void main()
+ {
+ dummy = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.b.y + val.a.x;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vertex_only_vec4
+ desc "Uniform struct declared in both, used only in vertex. Datatype vec4 "
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ varying mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_fragment_only_vec4
+ desc "Uniform struct declared in both, used only in fragment. Datatype vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.a.x + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_vec4
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vec4_vec3
+ desc "Same uniform struct in both shaders. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ void main()
+ {
+ dummy = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.b.y + val.a.x;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vertex_only_vec4_vec3
+ desc "Uniform struct declared in both, used only in vertex. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ varying mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_fragment_only_vec4_vec3
+ desc "Uniform struct declared in both, used only in fragment. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.a.x + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_vec4_vec3
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vec4_float
+ desc "Same uniform struct in both shaders. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ void main()
+ {
+ dummy = val.a.x + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ varying mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.b + val.a.x;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_vertex_only_vec4_float
+ desc "Uniform struct declared in both, used only in vertex. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_fragment_only_vec4_float
+ desc "Uniform struct declared in both, used only in fragment. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.a.x + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_vec4_float
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_vec4_struct
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and struct with vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b.c = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Inner {mediump vec4 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Inner {mediump vec4 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.c.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+
+
+case uniform_struct_partial_vec4_vec3_struct
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and struct with vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b.c = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Inner {mediump vec3 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Inner {mediump vec3 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.c.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_vec2_vec3
+ desc "Uniform struct declared in both, used partially in both. Datatype vec2 and vec3"
+ values {
+ uniform vec2 val.a = vec2(1.0, 2.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec2 a; mediump vec3 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec2 a; mediump vec3 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_vec2_int
+ desc "Uniform struct declared in both, used partially in both. Datatype vec2 and int"
+ values {
+ uniform vec2 val.a = vec2(1.0, 2.0);
+ uniform int val.b = 2;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec2 a; mediump int b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec2 a; mediump int b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + float(val.b);
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_int_float
+ desc "Uniform struct declared in both, used partially in both. Datatype int and float"
+ values {
+ uniform float val.a = 1.0;
+ uniform int val.b = 2;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump int b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a; mediump int b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + float(val.b);
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_bvec2_vec2
+ desc "Uniform struct declared in both, used partially in both. Datatype bvec2 and vec2"
+ values {
+ uniform bvec2 val.a = bvec2(true, true);
+ uniform vec2 val.b = vec2(1.0, 2.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {bvec2 a; mediump vec2 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = float(val.a.x);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {bvec2 a; mediump vec2 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_ivec2_vec2
+ desc "Uniform struct declared in both, used partially in both. Datatype ivec2 and vec2"
+ values {
+ uniform ivec2 val.a = ivec2(1, 2);
+ uniform vec2 val.b = vec2(1.0, 2.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump ivec2 a; mediump vec2 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = vec2(val.a).x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump ivec2 a; mediump vec2 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_partial_ivec2_ivec2
+ desc "Uniform struct declared in both, used partially in both. Datatype ivec2 and ivec2"
+ values {
+ uniform ivec2 val.a = ivec2(1, 2);
+ uniform ivec2 val.b = ivec2(1, 2);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump ivec2 a; mediump ivec2 b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = vec2(val.a).x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump ivec2 a; mediump ivec2 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + vec2(val.b).y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_type_conflict_1
+ desc "Fragment struct has one less member than fragment version"
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_type_conflict_2
+ desc "Vertex struct has int, fragment struct has float."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump int a;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = float(val.a);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_type_conflict_3
+ desc "Vertex struct has vec3, fragment struct has vec4."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec3 a;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = float(val.a.x);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump vec4 a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = val.a.x;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_precision_conflict_1
+ desc "Vertex side struct has highp, fragment side struct mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {highp float a;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_precision_conflict_2
+ desc "Vertex side struct has mediump, fragment side struct lowp."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {lowp float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_precision_conflict_3
+ desc "Vertex side struct has lowp, fragment side struct mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {lowp float a;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_precision_conflict_4
+ desc "Vertex side struct has lowp, fragment side struct implicit mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ ${VERTEX_DECLARATIONS}
+ struct Struct {lowp float a;};
+ uniform Struct val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Struct {float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_use_case_rip
+ desc "Complex Light struct from use case tests."
+ values {
+ uniform float val.constantAttenuation = 1.0;
+ uniform float val.quadraticAttenuation = 1.0;
+ output float out0 = 2.0;
+ }
+ vertex ""
+ struct Light
+ {
+ mediump vec3 color;
+ highp vec4 position;
+ highp vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ ${VERTEX_DECLARATIONS}
+ uniform Light val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.constantAttenuation;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Light
+ {
+ mediump vec3 color;
+ highp vec4 position;
+ highp vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ struct Struct {float a;};
+ uniform Light val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.quadraticAttenuation;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case uniform_struct_use_case_rip_sans_highp
+ desc "Complex Light struct from use case tests, without highp usage"
+ values {
+ uniform float val.constantAttenuation = 1.0;
+ uniform float val.quadraticAttenuation = 1.0;
+ output float out0 = 2.0;
+ }
+ vertex ""
+ struct Light
+ {
+ mediump vec3 color;
+ mediump vec4 position;
+ mediump vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ ${VERTEX_DECLARATIONS}
+ uniform Light val;
+ varying mediump float res;
+ void main()
+ {
+ res = val.constantAttenuation;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ precision mediump float;
+ struct Light
+ {
+ mediump vec3 color;
+ mediump vec4 position;
+ mediump vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ struct Struct {float a;};
+ uniform Light val;
+ ${FRAGMENT_DECLARATIONS}
+ varying mediump float res;
+ void main()
+ {
+ out0 = res + val.quadraticAttenuation;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.html
new file mode 100644
index 0000000000..ac91d22806
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'preprocessor';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.test
new file mode 100644
index 0000000000..7e3d251493
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/preprocessor.test
@@ -0,0 +1,4287 @@
+group basic "Basic Tests"
+
+ case correct_phases
+ expect compile_fail
+ both ""
+ #define e +1
+ void main()
+ {
+ mediump int n = 1e;
+ }
+ ""
+ end
+
+ case invalid_identifier
+ expect compile_fail
+ both ""
+ #define e +1
+
+ void main()
+ {
+ mediump int 1xyz = 1;
+ }
+ ""
+ end
+
+ case null_directive
+ values { output float out0 = 0.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ #
+ # // comment
+ /*sfd*/ # /* */
+
+ void main()
+ {
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_directive
+ expect compile_fail
+ both ""
+ #defin AAA
+
+ void main()
+ {
+ }
+ ""
+ end
+
+ case missing_identifier
+ expect compile_fail
+ both ""
+ #define
+
+ void main()
+ {
+ }
+ ""
+ end
+
+ case empty_object
+ values { output float out0 = -1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ # define VALUE
+
+ void main()
+ {
+ out0 = VALUE - 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case empty_function
+ values { output float out0 = -1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ # define VALUE(a)
+
+ void main()
+ {
+ out0 = VALUE(2.0) - 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case empty_directive
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ #
+
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case identifier_with_double_underscore
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ # define __VALUE__ 1
+
+ void main()
+ {
+ // __VALUE__ not used since it might be set by an "underlying software layer"
+ out0 = float(1.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+end # basic
+
+group definitions "Symbol Definition Tests"
+
+ case define_value_and_function
+ values { output float out0 = 6.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS:single-line}
+ # define VALUE (1.5 + 2.5)
+ # define FUNCTION(__LINE__, b) __LINE__+b
+
+ void main()
+ {
+ out0 = FUNCTION(VALUE, ((0.2) + 1.8) );
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case undefine_object_invalid_syntax
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define VAL 2.0
+ #undef VAL sdflkjfds
+ #define VAL 1.0
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VAL);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #undef __LINE__
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #undef __FILE__
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(__FILE__);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #undef __VERSION__
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(__VERSION__);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #undef GL_ES
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(GL_ES);
+ }
+ ""
+ end
+
+ case undefine_function
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define FUNCTION(a,b) a+b
+ #undef FUNCTION
+ #define FUNCTION(a,b) a-b
+
+ void main()
+ {
+ out0 = FUNCTION(3.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # definitions
+
+group invalid_definitions "Invalid Definition Tests"
+
+ case define_non_identifier
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define 123 321
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case undef_non_identifier_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #undef 123
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case undef_non_identifier_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #undef foo.bar
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+
+end # invalid_definitions
+
+group object_redefinitions "Object Redefinition Tests"
+
+ case invalid_object_ident
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2.0
+ # define AAAA 2.1
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAAA - 1.0)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_whitespace
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA- 1.0)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_op
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA + 1.0)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_floatval_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA - 1.1)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_floatval_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA - 1.0e-1)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_intval_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2
+ # define VALUE (AAA - 1)
+ # define VALUE (AAA - 2)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_intval_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA 2
+ # define VALUE (AAA - 1)
+ # define VALUE (AAA - 0x1)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case redefine_object_1
+ values { output float out0 = 6.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ # define VAL1 1.0
+ #define VAL2 2.0
+
+ #define RES2 (RES1 * VAL2)
+ #define RES1 (VAL2 / VAL1)
+ #define RES2 (RES1 * VAL2)
+ #define VALUE (RES2 + RES1)
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_ifdef
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #ifdef ADEFINE
+ #define VALUE 1.0
+ #else
+ #define VALUE 0.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_undef_ifdef
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+ #undef ADEFINE
+
+ #ifdef ADEFINE
+ #define VALUE 0.0
+ #else
+ #define VALUE 1.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_ifndef
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #ifndef ADEFINE
+ #define VALUE 0.0
+ #else
+ #define VALUE 1.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_defined_1
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #if defined(ADEFINE)
+ #define VALUE 1.0
+ #else
+ #define VALUE 0.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_defined_2
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #if defined ADEFINE
+ #define VALUE 1.0
+ #else
+ #define VALUE 0.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_comment
+ values { output float out0 = 6.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ # define VAL1 1.0
+ #define VAL2 2.0
+
+ #define RES2 /* fdsjklfdsjkl dsfjkhfdsjkh fdsjklhfdsjkh */ (RES1 * VAL2)
+ #define RES1 (VAL2 / VAL1)
+ #define RES2 /* ewrlkjhsadf */ (RES1 * VAL2)
+ #define VALUE (RES2 + RES1)
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_multiline_comment
+ values { output float out0 = 6.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ # define VAL1 1.0
+ #define VAL2 2.0
+
+ #define RES2 /* fdsjklfdsjkl
+ dsfjkhfdsjkh
+ fdsjklhfdsjkh */ (RES1 * VAL2)
+ #define RES1 (VAL2 / VAL1)
+ #define RES2 /* ewrlkjhsadf */ (RES1 * VAL2)
+ #define VALUE (RES2 + RES1)
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # object_redefinitions
+
+group invalid_redefinitions "Invalid Redefinitions Tests"
+
+ case invalid_identifier_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define GL_VALUE 1.0
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(GL_VALUE);
+ }
+ ""
+ end
+
+end # invalid_redefinitions
+
+group comments "Comment Tests"
+
+ case multiline_comment_define
+ values { output float out0 = 4.2; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define VALUE /* current
+ value */ 4.2
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_comment
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ /* /* */
+ out0 = 1.0;
+ // */
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case comment_trick_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ /*/
+ out0 = 0.0;
+ /*/
+ out0 = 1.0;
+ /**/
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case comment_trick_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ /**/
+ out0 = 1.0;
+ /*/
+ out0 = 0.0;
+ /**/
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_comment
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ /* /* */ */
+ ${POSITION_FRAG_COLOR} = 1.0;
+ }
+ ""
+ end
+
+ case unterminated_comment_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ /*
+ }
+ ""
+ end
+
+ case unterminated_comment_2
+ expect compile_fail
+ both ""
+ /*
+ precision mediump float;
+ void main()
+ {
+ }
+ ""
+ end
+
+end # comments
+
+group function_definitions "Function Definitions Tests"
+
+ case same_object_and_function_param
+ values { output float out0 = 1.0; }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define VALUE 1.0
+ #define FUNCTION(VALUE, B) (VALUE-B)
+
+ void main()
+ {
+ out0 = FUNCTION(3.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex_func
+ values { output float out0 = 518.5; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define AAA(a,b) a*(BBB(a,b))
+ #define BBB(a,b) a-b
+
+ void main()
+ {
+ out0 = BBB(AAA(8.0/4.0, 2.0)*BBB(2.0*2.0,0.75*2.0), AAA(40.0,10.0*BBB(5.0,3.0)));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_definition_with_comments
+ values { output float out0 = 3.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ /* sdfljk */ #/* sdfljk */define /* sdfljk */ FUNC( /* jklsfd*/a /*sfdjklh*/, /*sdfklj */b /*sdfklj*/) a+b
+
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # function_definitions
+
+group recursion "Recursions Tests"
+
+ case recursion_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA AAA
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA);
+ }
+ ""
+ end
+
+ case recursion_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA BBB
+ #define BBB AAA
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA);
+ }
+ ""
+ end
+
+ case recursion_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA (1.0+BBB)
+ #define BBB (2.0+AAA)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA);
+ }
+ ""
+ end
+
+ case recursion_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA(a) AAA(a)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA(1.0));
+ }
+ ""
+ end
+
+ case recursion_5
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define AAA(a, b) AAA(b, a)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA(1.0, 2.0));
+ }
+ ""
+ end
+
+end # recursion
+
+group function_redefinitions "Function Redefinition Tests"
+
+ case function_redefinition_1
+ values { output float out0 = 3.0; }
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC( a, b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_redefinition_2
+ values { output float out0 = 3.0; }
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) (a +b)
+ # define FUNC( a, b )(a +b)
+
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_redefinition_3
+ values { output float out0 = 3.0; }
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) (a +b)
+ # define FUNC(a,b)(a /* comment
+ */ +b)
+
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_function_redefinition_param_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC(A,b) A+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0));
+ }
+ ""
+ end
+
+ case invalid_function_redefinition_param_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC(a,b,c) a+b+c
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0, 3.0));
+ }
+ ""
+ end
+
+ case invalid_function_redefinition_param_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC(a,b) b+a
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0));
+ }
+ ""
+ end
+
+end # functions_redefinitions
+
+group invalid_function_definitions "Invalid Function Definition Tests"
+
+ case arguments_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC);
+ }
+ ""
+ end
+
+ case arguments_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC());
+ }
+ ""
+ end
+
+ case arguments_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC((();
+ }
+ ""
+ end
+
+ case arguments_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC));
+ }
+ ""
+ end
+
+ case arguments_5
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0));
+ }
+ ""
+ end
+
+ case arguments_6
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0);
+ }
+ ""
+ end
+
+ case arguments_7
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,));
+ }
+ ""
+ end
+
+ case arguments_8
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0, 3.0));
+ }
+ ""
+ end
+
+ case unique_param_name
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a,a) a+a
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case argument_list_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case argument_list_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(a + b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case argument_list_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(,a,b) a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(A a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(A,B,C a+b
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ # define FUNC(
+ ""
+ end
+
+end # invalid_function_definitions
+
+group semantic "Semantic Tests"
+
+ case ops_as_arguments
+ values { output float out0 = 20.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define FOO(a, b) (1 a 9) b 2
+
+ void main()
+ {
+ out0 = float(FOO(+, *));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case correct_order
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define FUNC(A) A
+ #define A 2.0
+
+ void main()
+ {
+ out0 = FUNC(A - 1.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # semantic
+
+group predefined_macros "Predefined Macros Tests"
+
+ case version
+ values { output float out0 = 100.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA __VERSION__
+ out0 = float(AAA);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case gl_es_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ out0 = float(GL_ES);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case gl_es_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define AAA(A) A
+
+ void main()
+ {
+ out0 = float(AAA(GL_ES));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_1
+ values { output float out0 = 1.0; }
+ both ""
+ const mediump int line = __LINE__;
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = float(line);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_2
+ # Note: Arguments are macro replaced in the first stage.
+ # Macro replacement list is expanded in the last stage.
+ values { output vec4 out0 = vec4(11.0, 11.0, 9.0, 10.0); }
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS:single-line}
+ #define BBB __LINE__, /*
+ */ __LINE__
+ #define AAA(a,b) BBB, a, b
+
+ void main()
+ {
+ out0 = vec4(AAA(__LINE__,
+ __LINE__
+ ));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case file
+ values { output float out0 = 0.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = float(__FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_gl_es
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if GL_ES
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_version
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if __VERSION__ == 100
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # predefined_macros
+
+group conditional_inclusion "Conditional Inclusion Tests"
+
+ case basic_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA asdf
+
+ #if defined AAA && !defined(BBB)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_2
+ values { output float out0 = 1.0; }
+ # Note: this is expected to fail contrary to native dEQP,
+ # see https://github.com/KhronosGroup/WebGL/pull/1523
+ expect compile_fail
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA defined(BBB)
+
+ #if !AAA
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_3
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ out0 = -1.0;
+ #elif 0
+ out0 = -2.0;
+ #elif 1
+ out0 = 1.0;
+ #else
+ out0 = -3.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_4
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ out0 = -1.0;
+ #elif 0
+ out0 = -2.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_5
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ out0 = 1.0;
+ #elif 0
+ out0 = -2.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case unary_ops_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !((~2 >> 1) & 1)
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case unary_ops_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !((~(- - - - - 1 + + + + + +1) >> 1) & 1)
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # conditional_inclusion
+
+group invalid_ops "Invalid Operations Tests"
+
+ case invalid_op_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if !((~(+ ++1 - - - -1) >> 1) & 1)
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_op_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if !((~(+ + +1 - -- -1) >> 1) & 1)
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define AAA 1
+
+ void main()
+ {
+ #if defined
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define AAA 1
+
+ void main()
+ {
+ #if defined()
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define AAA 1
+
+ void main()
+ {
+ #if defined(
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define AAA 1
+
+ void main()
+ {
+ #if defined)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_5
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define AAA 1
+
+ void main()
+ {
+ #if defined((AAA))
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_rparen
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #define AAA 1
+
+ void main()
+ {
+ #if defined(AAA
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case defined_define
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define define 1
+ #define AAA 1.0
+
+ void main()
+ {
+ out0 = AAA;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # invalid_ops
+
+group undefined_identifiers "Undefined Identifiers Tests"
+
+ case valid_undefined_identifier_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1 || AAA
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case valid_undefined_identifier_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0 && AAA
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case undefined_identifier_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1 - CCC + (-AAA || BBB)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if !A
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if -A
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if ~A
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_5
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_6
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #define A 1
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_7
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #define B 1
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_8
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #define B 1
+ #define A 2
+ #undef A
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_9
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_10
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #define A 0
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_11
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #define A 0
+ #define B 2
+ #undef B
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_12
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #define B 1
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+end # undefined_identifiers
+
+group invalid_conditionals "Invalid Conditionals Tests"
+
+ case empty_if
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_ifdef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifdef
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_ifndef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifndef
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_if_defined
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if defined
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_if_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_if_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 0
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_ifdef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifdef FOOBAR
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_ifndef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifndef GL_ES
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_else_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_else_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 0
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_elif_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 0
+ #elif 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_elif_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ #elif 0
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_elif_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 0
+ #elif 0
+ ${POSITION_FRAG_COLOR} = vec4(2.0);
+ }
+ ""
+ end
+
+ case elif_after_else
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 0
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #elif 1
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ #endif
+ }
+ ""
+ end
+
+ case else_without_if
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case elif_without_if
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #elif 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case endif_without_if
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case else_after_else
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if !GL_ES
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case nested_elif_without_if
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ # elif
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ # endif
+ #endif
+ }
+ ""
+ end
+
+ case if_float
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1.231
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ # elif
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ # endif
+ #endif
+ }
+ ""
+ end
+
+ case tokens_after_if
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1 foobar
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case tokens_after_elif
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 0
+ #elif foobar
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case tokens_after_else
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ #else foobar 1.231
+ #endif
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case tokens_after_endif
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ #else
+ #endif foobar
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case tokens_after_ifdef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifdef FOOBAR foobar
+ #else
+ #endif
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case tokens_after_ifndef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifndef FOOBAR ,, +- << barbar
+ #else
+ #endif
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_conditionals
+
+group conditionals "Conditionals Tests"
+
+ case unterminated_nested_blocks
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 1
+ # if 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case ifdef_1
+ values { output float out0 = 1.0; }
+ both ""
+ #define AAA
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef AAA
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifdef_2
+ values { output float out0 = 1.0; }
+ both ""
+ #define AAA
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined ( AAA)
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifdef_3
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef AAA
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_ifdef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifdef 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case ifndef_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef AAA
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifndef_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define AAA
+ void main()
+ {
+ #ifndef AAA
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_ifndef
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #ifndef 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case mixed_conditional_inclusion
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef AAA
+ out0 = 1.0;
+ #elif 1
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_if_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if GL_ES
+ # if __VERSION__ != 100
+ out0 = -1.0;
+ # else
+ out0 = 1.0;
+ # endif
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_if_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ # if 0
+ out0 = -1.0;
+ # else
+ # if 0
+ out0 = -1.0;
+ # elif 1
+ out0 = 1.0;
+ # else
+ out0 = -1.0;
+ # endif
+ # endif
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_if_3
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ # if 1
+ out0 = -1.0;
+ # endif
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # conditionals
+
+group directive "Directive Tests"
+
+ case version
+ values { output float out0 = 1.0; }
+ both ""
+ /* asdf */
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case version_is_less
+ expect compile_fail
+ both ""
+ #version 99
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_is_more
+ expect compile_fail
+ both ""
+ #version 101
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_missing
+ expect compile_fail
+ both ""
+ #version
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_not_first_statement_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ #version 100
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_not_first_statement_2
+ expect compile_fail
+ both ""
+ #define FOO BAR
+ #version 100
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_invalid_token_1
+ expect compile_fail
+ both ""
+ #version 100.0
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_invalid_token_2
+ expect compile_fail
+ both ""
+ #version foobar
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_version
+ expect compile_fail
+ both ""
+ #version AAA
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case additional_tokens
+ expect compile_fail
+ both ""
+ #version 100 foobar
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case error_with_no_tokens
+ expect compile_fail
+ both ""
+ #error
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case error
+ expect compile_fail
+ both ""
+ #define AAA asdf
+ #error 1 * AAA /* comment */
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # directive
+
+group builtin "Built-in Symbol Tests"
+
+ case line
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line 1
+ out0 = float(__LINE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_and_file
+ values { output vec4 out0 = vec4(234.0, 234.0, 10.0, 10.0); }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line 234 10
+ out0 = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_expression
+ values { output float out0 = 20.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line +20
+ out0 = float(__LINE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_and_file_expression
+ values { output vec4 out0 = vec4(243.0, 243.0, 10.0, 10.0); }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line (233 +10) (+10)
+ out0 = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_defined_1
+ values { output float out0 = 4.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 4
+ #line A
+ out0 = float(__LINE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_defined_2
+ values { output vec4 out0 = vec4(234.0, 234.0, 10.0, 10.0); }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 10
+ #line 234 A
+ out0 = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case empty_line
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #line
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_line_file_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #line 22 1.234
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ }
+ ""
+ end
+
+ case invalid_line_file_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #line 233 10 2
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ }
+ ""
+ end
+
+ case invalid_line_file_4
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #line foobar
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ }
+ ""
+ end
+
+end # builtin
+
+group pragmas "Pragma Tests"
+
+ # Note: pragma_vertex was removed compared to the native dEQP.
+ # This test was in the gles2-failures.txt skip list in the
+ # native dEQP. While it seemed theoretically correct, in
+ # practice, linking the program failed on Mac OS on all GPU
+ # types. Since this version of the dEQP is unlikely to be
+ # revisited, the test was removed here, rather than adding it
+ # to tcuSkipList.js.
+
+ # Note: pragma_fragment was removed compared to the native dEQP.
+ # This test was buggy; it required that a varying that was not
+ # invariant in the vertex shader, but invariant in the fragment
+ # shader, must link. The test was in the gles2-failures.txt skip
+ # list in the native test suite. To avoid confusion the test was
+ # removed here, rather than adding it to tcuSkipList.js.
+
+ case pragma_macro_exp
+ values { output float out0 = 1.0; }
+ both ""
+ #define off INVALID
+ /* pragma line not macro expanded */
+ #pragma debug(off)
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case pragma_unrecognized_debug
+ expect build_successful
+ both ""
+ #pragma debug(1.23)
+
+ // unrecognized preprocessor token
+
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case pragma_unrecognized_token
+ expect build_successful
+ both ""
+ #pragma **%
+
+ // trailing bytes form a valid but unrecognized preprocessor token
+
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # pragmas
+
+group extensions "Extension Tests"
+
+ case basic
+ values { output float out0 = 1.0; }
+ both ""
+ #extension all : warn
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case macro_exp
+ values { output float out0 = 1.0; }
+ both ""
+ #define warn enable
+
+ #extension all : warn
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case missing_extension_name
+ expect compile_fail
+ both ""
+ #extension
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_extension_name
+ expect compile_fail
+ both ""
+ #extension 2 : all
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_colon
+ expect compile_fail
+ both ""
+ #extension all
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case expected_colon
+ expect compile_fail
+ both ""
+ #extension all ;
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_behavior
+ expect compile_fail
+ both ""
+ #extension all :
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_behavior_1
+ expect compile_fail
+ both ""
+ #extension all : WARN
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_behavior_2
+ expect compile_fail
+ both ""
+ #extension all : require
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_char_in_name
+ expect compile_fail
+ both ""
+ #extension all* : warn
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_char_in_behavior
+ expect compile_fail
+ both ""
+ #extension all : war*n
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_comment
+ expect compile_fail
+ both ""
+ #extension all : warn /*asd
+ precision mediump float;
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+end # extensions
+
+group expressions "Expression Tests"
+
+ case shift_left
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if (VAL << 2) == 16
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case shift_right
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 5
+ out0 = 0.0;
+ #if (VAL >> 1) == 2
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case cmp_less_than
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 5
+ out0 = 0.0;
+ #if (VAL < 6) && (-VAL < -4)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_or_equal
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL <= 6) && (-VAL <= -6)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case or
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL | 5) == 7
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case and
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL & 5) == 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case xor
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL ^ 5) == 3
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mod
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 12
+ out0 = 0.0;
+ #if (VAL % 5) == 2
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_value
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL (( (4 ) ) )
+ out0 = 0.0;
+ #if VAL >= 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_tricky
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL (( (4 ) )
+ out0 = 0.0;
+ #if VAL) >= 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_if_no
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if VAL >= 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_if
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if (VAL >= 4)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_multi_if
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL (4)
+ out0 = 0.0;
+ #if (((VAL)) >= (4))
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_single_if
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if (VAL >= 4)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_ifelse_true
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ #if (VAL >= 4)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_ifelse_false
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ #if (VAL > 4)
+ out0 = 0.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_basic_0
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if -4 + 5 == 1
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_basic_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if (2 * 2) - 3 >= 0
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_simple_precedence_0
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 2 * 3 - 3 == 3
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_simple_precedence_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 2 - 2 / 2 == 1
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_1
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ void main()
+ {
+ #if defined(X)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_2
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ void main()
+ {
+ #if defined(X) == Y
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_3
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ void main()
+ {
+ #if defined(X) && defined(Y)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_4
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ #undef X
+ void main()
+ {
+ #if defined(X) && defined(Y)
+ out0 = 0.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_5
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ #undef X
+ void main()
+ {
+ #if defined(X) || defined(Y)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_6
+ values { output float out0 = 1.0; }
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ #undef Y
+ void main()
+ {
+ #if defined(X) && (defined(Y) || (X == 0))
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # expressions
+
+group invalid_expressions "Invalid Expression Tests"
+
+ case invalid_unary_expr
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if !
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_binary_expr
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 3+4+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_expr
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_expr_1
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 4 4
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_expr_2
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 4 * * 4
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_expr_3
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if (4)(4)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unopened_parenthesis
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if 4)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unclosed_parenthesis
+ expect compile_fail
+ both ""
+ precision mediump float;
+ void main()
+ {
+ #if ((4 + 7)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_expressions
+
+group operator_precedence "Operator precedence"
+
+
+ case modulo_vs_not
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 % ! 0 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_not
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 / ! 0 ) == 8
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_not
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 * ! 0 ) == 8
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case modulo_vs_bit_invert
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 % ~ 4 ) == 3
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case modulo_vs_minus
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 % - 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case modulo_vs_plus
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 % + 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_bit_invert
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 / ~ 2 ) == -2
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_minus
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 / - 2 ) == -4
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_plus
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 / + 2 ) == 4
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_bit_invert
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 * ~ 2 ) == -24
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_minus
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 * - 2 ) == -16
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_plus
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 * + 2 ) == 16
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sub_vs_modulo
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 - 3 % 2 ) == 7
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sub_vs_div
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 - 3 / 2 ) == 7
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sub_vs_mul
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 - 3 * 2 ) == 2
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case add_vs_modulo
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 + 3 % 2 ) == 9
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case add_vs_div
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 + 3 / 2 ) == 9
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case add_vs_mul
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 + 3 * 2 ) == 14
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case rshift_vs_sub
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 >> 3 - 2 ) == 4
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case rshift_vs_add
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 >> 3 + 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case lshift_vs_sub
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 << 3 - 2 ) == 16
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case lshift_vs_add
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 << 3 + 2 ) == 256
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_or_equal_vs_rshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 >= 3 >> 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_or_equal_vs_lshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 >= 3 << 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_or_equal_vs_rshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 <= 3 >> 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_or_equal_vs_lshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 <= 3 << 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_vs_rshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 > 3 >> 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_vs_lshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 > 3 << 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_vs_rshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 < 3 >> 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_vs_lshift
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 < 3 << 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_greater_or_equal
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 != 3 >= 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_less_or_equal
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 != 3 <= 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_greater
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 != 3 > 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_less
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 != 3 < 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_greater_or_equal
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 == 3 >= 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_less_or_equal
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 == 3 <= 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_greater
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 == 3 > 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_less
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 == 3 < 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise_and_vs_not_equal
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 & 3 != 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise_and_vs_equal
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 & 3 == 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case xor_vs_bitwise_and
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 ^ 3 & 2 ) == 10
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise_or_vs_xor
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 8 | 3 ^ 2 ) == 9
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical_and_vs_bitwise_or
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 0 && 3 | 2 )
+ #define VAL 0.0
+ #else
+ #define VAL 1.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical_and_vs_bitwise_and
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 0 && 4 & 2 )
+ #define VAL 0.0
+ #else
+ #define VAL 1.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical_or_vs_logical_and
+ values { output float out0 = 1.0; }
+ both ""
+
+ #if ( 0 || 4 && 0 )
+ #define VAL 0.0
+ #else
+ #define VAL 1.0
+ #endif
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # operator_precedence
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.html
new file mode 100644
index 0000000000..be660758b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'qualification_order';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.test
new file mode 100644
index 0000000000..4b20ad8ee8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/qualification_order.test
@@ -0,0 +1,785 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group variables "Order of qualification in variable declarations."
+
+ group valid "Valid orderings."
+
+ case invariant_storage_precision
+ expect pass
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ invariant varying lowp float x0;
+
+ uniform mediump float x1;
+
+ attribute mediump float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ invariant varying lowp float x0;
+
+ uniform mediump float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision
+ expect pass
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ varying lowp float x0;
+
+ uniform mediump float x1;
+
+ attribute mediump float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ varying lowp float x0;
+
+ uniform mediump float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage
+ expect pass
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ invariant varying float x0;
+
+ uniform float x1;
+
+ attribute float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ invariant varying float x0;
+
+ uniform float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+
+ end # valid
+ group invalid "Invalid orderings."
+
+ case invariant_precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ invariant lowp varying float x0;
+
+ mediump uniform float x1;
+
+ mediump attribute float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ invariant lowp varying float x0;
+
+ mediump uniform float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ varying invariant lowp float x0;
+
+ uniform mediump float x1;
+
+ attribute mediump float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ varying invariant lowp float x0;
+
+ uniform mediump float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ varying lowp invariant float x0;
+
+ uniform mediump float x1;
+
+ attribute mediump float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ varying lowp invariant float x0;
+
+ uniform mediump float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_invariant_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ lowp invariant varying float x0;
+
+ mediump uniform float x1;
+
+ mediump attribute float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ lowp invariant varying float x0;
+
+ mediump uniform float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ lowp varying invariant float x0;
+
+ mediump uniform float x1;
+
+ mediump attribute float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ lowp varying invariant float x0;
+
+ mediump uniform float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ lowp varying float x0;
+
+ mediump uniform float x1;
+
+ mediump attribute float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ lowp varying float x0;
+
+ mediump uniform float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ precision mediump float;
+ attribute highp vec4 dEQP_Position;
+
+ varying invariant float x0;
+
+ uniform float x1;
+
+ attribute float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ precision mediump float;
+
+ varying invariant float x0;
+
+ uniform float x1;
+
+ void main()
+ {
+ float result = x0 + x1;
+ gl_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+
+ end # invalid
+
+end # variables
+group parameters "Order of qualification in function parameters."
+
+ group valid "Valid orderings."
+
+ case storage_parameter_precision
+ expect pass
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const in lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( inout mediump float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case storage_parameter
+ expect pass
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case storage_precision
+ expect pass
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( mediump float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_precision
+ expect pass
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout mediump float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ end # valid
+ group invalid "Invalid orderings."
+
+ case storage_precision_parameter
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const lowp in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( mediump inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_storage_precision
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in const lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout mediump float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_precision_storage
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in lowp const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout mediump float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_storage_parameter
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp const in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (mediump inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_parameter_storage
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp in const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (mediump inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_storage
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_storage
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (mediump float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_parameter
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (mediump inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ end # invalid
+
+end # parameters
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.html
new file mode 100644
index 0000000000..b98b97b773
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'reserved_operators';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.test
new file mode 100644
index 0000000000..dda1f1aade
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/reserved_operators.test
@@ -0,0 +1,250 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+case operator_modulo
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value % 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_bitwise_not
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value = ~value;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_bitwise_shift_left
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value << 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_bitwise_shift_right
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value >> 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_bitwise_and
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value & 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_bitwise_xor
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value ^ 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_bitwise_or
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value | 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_assign_modulo
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value %= 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_assign_shift_left
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value <<= 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_assign_shift_right
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value >>= 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_assign_and
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value &= 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_assign_xor
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value ^= 1;
+ ${OUTPUT}
+ }
+ ""
+end
+case operator_assign_or
+ expect compile_fail
+ values {}
+
+ both ""
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int value = 100;
+ value |= 1;
+ ${OUTPUT}
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.html
new file mode 100644
index 0000000000..5d01ef844f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'scoping';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.test
new file mode 100644
index 0000000000..a387631af4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/scoping.test
@@ -0,0 +1,823 @@
+group valid "Valid scoping and name redeclaration cases"
+
+ case local_variable_hides_global_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case block_variable_hides_local_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ {
+ int a = -1;
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case block_variable_hides_global_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ void main()
+ {
+ ${SETUP}
+ {
+ int a = in0;
+
+ out0 = a;
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case for_init_statement_variable_hides_local_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ for (int a = 0; a < 10; a++)
+ {
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case for_init_statement_variable_hides_global_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 5;
+
+ void main()
+ {
+ ${SETUP}
+ for (int a = 0; a < 10; a++)
+ {
+ }
+ out0 = in0 + a - 5;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case variable_in_if_hides_global_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 1;
+
+ void main()
+ {
+ ${SETUP}
+ if (true)
+ int a = 42;
+ out0 = a*in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case variable_from_outer_scope_visible_in_initializer
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ {
+ int a = a+5, b = a-5;
+ out0 = b;
+ a = 42;
+ }
+ out0 = out0 + a - in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_int_variable_hides_struct_type
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int val; };
+
+ void main()
+ {
+ ${SETUP}
+ int S = S(in0).val;
+ out0 = S;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_struct_variable_hides_struct_type
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int val; };
+
+ void main()
+ {
+ ${SETUP}
+ S S = S(in0);
+ out0 = S.val;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_variable_hides_function
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int foo (int x) { return x; }
+
+ void main()
+ {
+ ${SETUP}
+ int foo = in0;
+ out0 = foo;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_global_variable
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ int func (int a) { return a; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_struct_type
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int x; };
+
+ int func (int S) { return S; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_function
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int func (int func) { return func; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_variable_in_inner_scope_hides_function_parameter
+ version 100 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+ int func (int inp, int x) { { int x = 5; return inp + x - 5; } }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0, 42);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end
+
+group invalid "Invalid scoping behavior"
+
+ case redeclare_global_variable
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a;
+ float a;
+
+ void main()
+ {
+ a = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case redeclare_local_variable
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ int a;
+ float a;
+ a = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case redeclare_for_init_statement_variable
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ int i = 11;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case redeclare_for_condition_variable
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ for (int i = 0; int a = (i < 10); i++)
+ {
+ int a = 0;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case redeclare_for_init_statement_variable_in_for_condition
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a;
+ for (int i = 0; int i = (i < 10); i++)
+ {
+ a = sin(i);
+ }
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case redeclare_while_condition_variable
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ int a = 0;
+ while (int i = (a < 5))
+ {
+ int i = 11;
+ a += i;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case redeclare_function
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func(float x);
+ float func(float x);
+
+ float func(float x) { return x + 1.0; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case redefine_function
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func(float x);
+
+ float func(float x) { return x + 1.0; }
+ float func(float x) { return x + 2.0; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case redeclare_builtin
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sin(float x);
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
+ }
+ ""
+ end
+
+ case redefine_builtin
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sin(float x) { return x + 1.0; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
+ }
+ ""
+ end
+
+ case conflict_function_struct
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void f(int x);
+ struct f { int x; };
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1);
+ }
+ ""
+ end
+
+ case conflict_function_variable
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void f(int x);
+ float f;
+
+ void main()
+ {
+ f = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(f);
+ }
+ ""
+ end
+
+ case use_global_variable_before_declaration
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func()
+ {
+ a = 2.0;
+ }
+
+ float a;
+
+ void main()
+ {
+ func();
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_local_variable_before_declaration
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a = 1.0;
+ a = b;
+ float b = 2.0;
+
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_struct_type_before_declaration
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float x) { return S(x).val; }
+ struct S { float val; };
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case use_function_before_declaration
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float x) { return bar(x); }
+ float bar (float x) { return x; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case use_variable_from_block_in_outer_scope
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ {
+ float a = 1.0;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_variable_from_if_in_outer_scope
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ if (true)
+ float a = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_variable_from_else_in_outer_scope
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ if (false)
+ float a = 1.0;
+ else
+ float b = 2.0;
+ ${POSITION_FRAG_COLOR} = vec4(b);
+ }
+ ""
+ end
+
+ case use_variable_from_if_in_else
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a = 1.0;
+ if (true)
+ {
+ float b = 2.0;
+ }
+ else
+ {
+ a = b;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_variable_from_for_init_statement_in_outer_scope
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float x = 0.0;
+ for (int i = 0; i < 10; i++)
+ {
+ x += sin(i);
+ }
+ ${POSITION_FRAG_COLOR} = vec4(float(i));
+ }
+ ""
+ end
+
+ case use_variable_from_while_condition_in_outer_scope
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ int a = 1;
+ while (bool b = (a == 1))
+ {
+ a++;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(float(b));
+ }
+ ""
+ end
+
+ case use_parameter_names_from_function_declaration
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func(float a, float b);
+
+ float func(float x, float y) { return a+b; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0, 2.0));
+ }
+ ""
+ end
+
+ case variable_not_visible_in_own_initializer
+ version 100 es
+ expect compile_fail
+ both ""
+ #version 100
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float x = x;
+ ${POSITION_FRAG_COLOR} = vec4(x);
+ }
+ ""
+ end
+
+end # invalid
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/shader-lib-test.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/shader-lib-test.html
new file mode 100644
index 0000000000..864ad80465
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/shader-lib-test.html
@@ -0,0 +1,462 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="shader-utils.js"></script>
+<script src="shader-library.js"></script>
+<script src="shader-library-case.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+
+ description("Testing the .test parser components.");
+
+ var wtu = WebGLTestUtils;
+ var successfullyParsed = false;
+ var parser = new shaderLibrary.Parser();
+
+
+ // this array of functions is processed sequentially.
+ // returning false will abort
+ var tests = [
+
+
+ function() {
+ var result = shaderLibrary.isWhitespace(" ");
+ test_result(
+ "Checking isWhitespace. Passing \" \". Expecting true",
+ result === true, result
+ );
+ return true;
+ },
+ function() {
+ var result = shaderLibrary.isWhitespace("q");
+ test_result(
+ "Checking isWhitespace. Passing \"q\". Expecting false",
+ result === false, result
+ );
+ return true;
+ },
+ function() {
+ var result = shaderLibrary.isWhitespace(" \r\n\t");
+ test_result(
+ "Checking isWhitespace. Passing \" \\r\\n\\t\". Expecting true",
+ result === true, result
+ );
+ return true;
+ },
+ function() {
+ var result = shaderLibrary.isWhitespace(" \r\n\tq");
+ test_result(
+ "Checking isWhitespace. Passing \" \\r\\n\\tq\". Expecting false",
+ result === false, result
+ );
+ return true;
+ },
+
+ function() {
+ try {
+ var result = shaderLibrary.removeExtraIndentation(
+ "\t\t\taaaa\n\t \t\tbbbb\n\t\t\tcccc\r\n\t\t\tdddd"
+ );
+ } catch (err) {
+ result = "aborted";
+ }
+
+ test_result(
+ "Checking removeExtraIndentation. \
+ Passing \"\t\t\taaaa\n\t \t\tbbbb\n\t\t\tcccc\r\n\t\t\tdddd\". \
+ Expecting \"aaaa\n\tbbbb\ncccc\ndddd\"",
+ result === "aaaa\n\tbbbb\ncccc\ndddd",
+ result
+ );
+ return true;
+ },
+
+
+ function() {
+ // looking for private access to the parser object
+ var result = (typeof parser.priv != 'undefined');
+ test_result("looking for private member access", result, result);
+ return result;
+ },
+
+ function() {
+ try {
+ var result = parser.priv.parseIntLiteral("42");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking int parser. Passing \"42\". Expecting 42",
+ result === 42, result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseIntLiteral("-5");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking int parser. Passing \"-5\". Expecting -5",
+ result === -5, result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseIntLiteral("42.9");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking int parser. Passing \"42.9\". Expecting 42",
+ result === 42, result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseFloatLiteral("42.9");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking float parser. Passing \"42.9\". Expecting 42.9",
+ result === 42.9, result
+ );
+ return true;
+ },
+
+
+ function() {
+ try {
+ var result = parser.priv.parseStringLiteral("\"hello world\"");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking string parser. Passing \"\"hello world\"\". Expecting \"hello world\"",
+ result == "hello world", result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseStringLiteral("\"hello world\"extra");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking string parser. Passing \"\"hello world\"extra\". Expecting \"hello world\"",
+ result == "hello world", result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseStringLiteral("\"\\\"\\\"\\\"\"\\\"\"");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking string parser. Passing \"\"\\\"\\\"\\\"\"\\\"\"\". Expecting \"\"\"\"\"",
+ result == "\"\"\"", result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseStringLiteral("\"newline test\\nnewline test\"");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking string parser. Passing \"\"newline test\\nnewline test\"\". Expecting \"newline test\nnewline test\"",
+ result == "newline test\nnewline test", result
+ );
+ return true;
+ },
+ function() {
+ try {
+ var result = parser.priv.parseStringLiteral("\"tab test\\ttab test\"");
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking string parser. Passing \"\"tab test\\ttab test\"\". Expecting \"tab test\ttab test\"",
+ result == "tab test\ttab test", result
+ );
+ return true;
+ },
+
+ function() {
+ try {
+ var result = parser.priv.parseShaderSource(
+ "\"\"\t\t\taaaa\n\t \t\tbbbb\n\t\t\tcccc\r\n\t\t\tdddd\"\""
+ );
+ } catch (err) {
+ result = "aborted";
+ }
+
+ test_result(
+ "Checking parseShaderSource. \
+ Passing \"\"\"\t\t\taaaa\n\t \t\tbbbb\n\t\t\tcccc\r\n\t\t\tdddd\"\"\". \
+ Expecting \"aaaa\n\tbbbb\ncccc\ndddd\"",
+ result === "aaaa\n\tbbbb\ncccc\ndddd",
+ result
+ );
+ return true;
+ },
+
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("bool value = true;", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"bool value = true;\", 0",
+ result.idType == parser.priv.Token.TOKEN_BOOL && result.value == "bool",
+ result.name + ": " + result.value
+ );
+ },
+
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("bool value = true;", 4);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"bool value = true;\", 4",
+ result.idType == parser.priv.Token.TOKEN_IDENTIFIER && result.value == "value",
+ result.name + ": " + result.value
+ );
+ },
+ //*
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("bool value = true;", 11);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"bool value = true;\", 11",
+ result.idType == parser.priv.Token.TOKEN_ASSIGN,
+ result.name + ": " + result.value
+ );
+ },
+ //*/
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("bool value = true;", 12);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"bool value = true;\", 12",
+ result.idType == parser.priv.Token.TOKEN_TRUE && result.value == "true",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("bool value = true;", 17);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"bool value = true;\", 17",
+ result.idType == parser.priv.Token.TOKEN_SEMI_COLON && result.value == ";",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("-7", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"-7\", 0",
+ result.idType == parser.priv.Token.TOKEN_MINUS && result.value == "-",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("-7", 1);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"-7\", 1",
+ result.idType == parser.priv.Token.TOKEN_INT_LITERAL && result.value == "7",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("3.145", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"3.145\", 0",
+ result.idType == parser.priv.Token.TOKEN_FLOAT_LITERAL && result.value == "3.145",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("1.0e+10", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"1.0e+10\", 0",
+ result.idType == parser.priv.Token.TOKEN_FLOAT_LITERAL && result.value == "1.0e+10",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("1.0e", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"1.0e\", 0",
+ result === "aborted",
+ result
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("\"\"shader source\"\";", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"\"\"shader source\"\";\", 0",
+ result.idType == parser.priv.Token.TOKEN_SHADER_SOURCE && result.value == "\"\"shader source\"\"",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("\"string\";", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"\"string\";\", 0",
+ result.idType == parser.priv.Token.TOKEN_STRING && result.value == "\"string\"",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("\'string\';", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"\'string\';\", 0",
+ result.idType == parser.priv.Token.TOKEN_STRING && result.value == "\'string\'",
+ result.name + ": " + result.value
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("\'string\";", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"\'string\";\", 0",
+ result === "aborted",
+ result
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.advanceTokenTester("\'string\\", 0);
+ } catch (err) {
+ result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing \"\'string\\\", 0",
+ result === "aborted",
+ result
+ );
+ },
+ function() {
+ try {
+ var result = parser.priv.mapDataTypeToken(parser.priv.Token.TOKEN_INT);
+ } catch (err) {
+ var result = "aborted";
+ }
+ test_result(
+ "Checking advanceToken. Passing parser.priv.Token.TOKEN_INT",
+ result === shaderUtils.DataType.TYPE_INT,
+ result
+ );
+ },
+
+ function() {
+ successfullyParsed = true;i
+ return true;
+ },
+
+ ];
+
+ var current = 0;
+
+ function test_result(description, result, additional) {
+ switch (typeof(additional)) {
+ case "undefined":
+ break;
+ case "string":
+ description += ": \"" + additional + "\"";
+ break;
+ default:
+ description += ": " + additional;
+ break;
+ }
+ if (result) {
+ testPassed(description);
+ } else {
+ testFailed(description);
+ }
+ }
+
+ function do_next() {
+ if (tests[current]() !== false && tests.length > ++current) {
+ setTimeout(do_next, 0);
+ } else {
+ on_complete();
+ }
+ }
+
+ function on_complete() {
+ var testPost = document.createElement('script');
+ testPost.src = "../../../../js/js-test-post.js";
+ document.body.appendChild(testPost);
+ }
+
+ do_next();
+
+//
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-conversions.js b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-conversions.js
new file mode 100644
index 0000000000..2322f0bf23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-conversions.js
@@ -0,0 +1,33 @@
+/*
+
+run with
+ node split-conversions.js
+
+notes:
+
+conversions.test is generated from the C++ based dEQP tests
+https://github.com/KhronosGroup/VK-GL-CTS/blob/main/modules/gles2/scripts/gen-conversions.py
+
+You need to manually add these tests to the 00_test_list.txt
+
+*/
+
+const fs = require('fs');
+
+process.chdir(__dirname);
+
+const testWarning = `\
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+`;
+
+const conversionsHTML = fs.readFileSync('conversions.template', {encoding: 'utf8'});
+const conversions = fs.readFileSync('conversions.test', {encoding: 'utf8'});
+const groupMatches = conversions.matchAll(/group ([a-zA-Z0-9_]+) [\s\S]+?end #.*?\n/g);
+for (const [str, groupName] of groupMatches) {
+ const baseName = `conversions_${groupName}`;
+ fs.writeFileSync(`${baseName}.test`, `${testWarning}${str}`);
+ fs.writeFileSync(`${baseName}.html`, `<!--\n${testWarning}-->\n${conversionsHTML.replace("'conversions'", `'${baseName}'`)}`);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-swizzles.js b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-swizzles.js
new file mode 100644
index 0000000000..4a67bfc7a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/split-swizzles.js
@@ -0,0 +1,47 @@
+/*
+
+run with
+ node split-swizzles.js
+
+notes:
+
+swizzles.test is generated from the C++ based dEQP tests
+https://github.com/KhronosGroup/VK-GL-CTS/blob/main/modules/gles2/scripts/gen-swizzles.py
+
+You need to manually add these tests to the 00_test_list.txt
+
+*/
+
+const fs = require('fs');
+
+process.chdir(__dirname);
+
+const testWarning = `\
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+`;
+
+const swizzlesHTML = fs.readFileSync('swizzles.template', {encoding: 'utf8'});
+const swizzles = fs.readFileSync('swizzles.test', {encoding: 'utf8'});
+const caseMatches = swizzles.matchAll(/\scase (\w+)_(\w+)_(\w+)\n[\s\S]+?end\n/g);
+
+// quick sanity check
+const numCases = swizzles.matchAll('\bcase\b').length;
+if (caseMatches.length !== numCases) {
+ throw Error(`numCases(${numCases}) does not match caseMatches.length(${caseMatches.length})`);
+}
+
+const byType = {}
+for (const [str, precision, type, swizzle] of caseMatches) {
+ byType[type] = byType[type] || [];
+ byType[type].push(str);
+}
+
+for (const [type, cases] of Object.entries(byType)) {
+ const baseName = `swizzles_${type}`;
+ const str = `group ${type}_swizzles "${type} swizzles"\n\n${cases.join('\n\n')}\n\nend # ${type}_swizzles`;
+ fs.writeFileSync(`${baseName}.test`, `${testWarning}${str}`);
+ fs.writeFileSync(`${baseName}.html`, `<!--\n${testWarning}-->\n${swizzlesHTML.replace("'swizzles'", `'${baseName}'`)}`);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.template b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.template
new file mode 100644
index 0000000000..542ca92d0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.template
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.test
new file mode 100644
index 0000000000..7e82c3e60d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles.test
@@ -0,0 +1,6811 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group vector_swizzles "Vector Swizzles"
+
+ case mediump_vec2_x
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xx
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xy
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yx
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yxy
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xyxx
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yyyy
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_s
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_ss
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_st
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_ts
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_tst
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_stss
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_tttt
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_r
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rr
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rg
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_gr
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_grg
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rgrr
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_gggg
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_x
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_z
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xyz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zyx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xxx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzy
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_yxy
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xzx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xyyx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzzz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_s
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_p
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_stp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pts
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sss
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_ppp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_ppt
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_tst
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sps
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_stts
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pppp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_r
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_b
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rgb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bgr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rrr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbg
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_grg
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rbr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rggr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbbb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_x
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_w
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wz
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_www
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_yyw
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzy
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xyzw
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzyx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xxxx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_yyyy
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wwww
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzzw
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wwwy
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xyxx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_zzwz
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_s
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_q
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qs
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qp
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ttq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qpt
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_stpq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qpts
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ssss
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_tttt
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqqq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qppq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqqt
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_stss
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ppqp
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_r
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_a
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ar
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ab
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaa
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_gga
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abg
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rgba
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abgr
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rrrr
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_gggg
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaaa
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abba
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaag
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rgrr
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_bbab
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_x
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xx
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xy
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yx
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yxy
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xyxx
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yyyy
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_s
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_ss
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_st
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_ts
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_tst
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_stss
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_tttt
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_r
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rr
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rg
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_gr
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_grg
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rgrr
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_gggg
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_x
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_z
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xyz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zyx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xxx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzy
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_yxy
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xzx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xyyx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzzz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_s
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_p
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_stp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pts
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sss
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_ppp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_ppt
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_tst
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sps
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_stts
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pppp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_r
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_b
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rgb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bgr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rrr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbg
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_grg
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rbr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rggr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbbb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_x
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_w
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wz
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_www
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_yyw
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzy
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xyzw
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzyx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xxxx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_yyyy
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wwww
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzzw
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wwwy
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xyxx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_zzwz
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_s
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_q
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qs
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qp
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ttq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qpt
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_stpq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qpts
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ssss
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_tttt
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqqq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qppq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqqt
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_stss
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ppqp
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_r
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_a
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ar
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ab
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaa
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_gga
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abg
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rgba
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abgr
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rrrr
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_gggg
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaaa
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abba
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaag
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rgrr
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_bbab
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_x
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xx
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xy
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yx
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yxy
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xyxx
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yyyy
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_s
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_ss
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_st
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_ts
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_tst
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_stss
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_tttt
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_r
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rr
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rg
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_gr
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_grg
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rgrr
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_gggg
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_x
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_z
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xyz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zyx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xxx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzy
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_yxy
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xzx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xyyx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzzz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_s
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_p
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_stp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pts
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sss
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_ppp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_ppt
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_tst
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sps
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_stts
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pppp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_r
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_b
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rgb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bgr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rrr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbg
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_grg
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rbr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rggr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbbb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_x
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_w
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wz
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_www
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_yyw
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzy
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xyzw
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzyx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xxxx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_yyyy
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wwww
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzzw
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wwwy
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xyxx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_zzwz
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_s
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_q
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qs
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qp
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ttq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qpt
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_stpq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qpts
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ssss
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_tttt
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqqq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qppq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqqt
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_stss
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ppqp
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_r
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_a
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ar
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ab
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaa
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_gga
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abg
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rgba
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abgr
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rrrr
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_gggg
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaaa
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abba
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaag
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rgrr
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_bbab
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_swizzles
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.html
new file mode 100644
index 0000000000..7a98a4562c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_bvec2';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.test
new file mode 100644
index 0000000000..1f74f6228a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec2.test
@@ -0,0 +1,469 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group bvec2_swizzles "bvec2 swizzles"
+
+ case mediump_bvec2_x
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_xx
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_xy
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_yx
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_yxy
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_xyxx
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_yyyy
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_s
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_ss
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_st
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_ts
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_tst
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_stss
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_tttt
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_r
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_rr
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_rg
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_gr
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_grg
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_rgrr
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_gggg
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # bvec2_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.html
new file mode 100644
index 0000000000..ae73ac5f54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_bvec3';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.test
new file mode 100644
index 0000000000..7e14baabee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec3.test
@@ -0,0 +1,865 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group bvec3_swizzles "bvec3 swizzles"
+
+ case mediump_bvec3_x
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_z
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xyz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zyx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xxx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zzz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zzy
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_yxy
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xzx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xyyx
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zzzz
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_s
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_p
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_sp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_pp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_stp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_pts
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_sss
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_ppp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_ppt
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_tst
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_sps
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_stts
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_pppp
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_r
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_b
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rgb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bgr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rrr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bbb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bbg
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_grg
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rbr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rggr
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bbbb
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # bvec3_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.html
new file mode 100644
index 0000000000..9a9c6e6552
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_bvec4';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.test
new file mode 100644
index 0000000000..b5cfcabb0d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_bvec4.test
@@ -0,0 +1,1063 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group bvec4_swizzles "bvec4 swizzles"
+
+ case mediump_bvec4_x
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_w
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wz
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_www
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_yyw
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wzy
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_xyzw
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wzyx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_xxxx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_yyyy
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wwww
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wzzw
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wwwy
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_xyxx
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_zzwz
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_s
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_q
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qs
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qp
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qqq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ttq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qpt
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_stpq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qpts
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ssss
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_tttt
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qqqq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qppq
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qqqt
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_stss
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ppqp
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_r
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_a
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ar
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ab
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_aaa
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_gga
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_abg
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_rgba
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_abgr
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_rrrr
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_gggg
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_aaaa
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_abba
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_aaag
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_rgrr
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_bbab
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # bvec4_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.html
new file mode 100644
index 0000000000..f48565709f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_ivec2';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.test
new file mode 100644
index 0000000000..6b4ca23c4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec2.test
@@ -0,0 +1,469 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group ivec2_swizzles "ivec2 swizzles"
+
+ case mediump_ivec2_x
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_xx
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_xy
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_yx
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_yxy
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_xyxx
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_yyyy
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_s
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_ss
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_st
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_ts
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_tst
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_stss
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_tttt
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_r
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_rr
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_rg
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_gr
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_grg
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_rgrr
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_gggg
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # ivec2_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.html
new file mode 100644
index 0000000000..a23797c0a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_ivec3';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.test
new file mode 100644
index 0000000000..11a06227fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec3.test
@@ -0,0 +1,865 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group ivec3_swizzles "ivec3 swizzles"
+
+ case mediump_ivec3_x
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_z
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xyz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zyx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xxx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zzz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zzy
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_yxy
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xzx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xyyx
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zzzz
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_s
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_p
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_sp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_pp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_stp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_pts
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_sss
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_ppp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_ppt
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_tst
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_sps
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_stts
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_pppp
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_r
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_b
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rgb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bgr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rrr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bbb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bbg
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_grg
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rbr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rggr
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bbbb
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # ivec3_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.html
new file mode 100644
index 0000000000..2b155d1f7a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_ivec4';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.test
new file mode 100644
index 0000000000..f9fe122449
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_ivec4.test
@@ -0,0 +1,1063 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group ivec4_swizzles "ivec4 swizzles"
+
+ case mediump_ivec4_x
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_w
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wz
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_www
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_yyw
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wzy
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_xyzw
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wzyx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_xxxx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_yyyy
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wwww
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wzzw
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wwwy
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_xyxx
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_zzwz
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_s
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_q
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qs
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qp
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qqq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ttq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qpt
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_stpq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qpts
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ssss
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_tttt
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qqqq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qppq
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qqqt
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_stss
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ppqp
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_r
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_a
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ar
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ab
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_aaa
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_gga
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_abg
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_rgba
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_abgr
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_rrrr
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_gggg
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_aaaa
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_abba
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_aaag
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_rgrr
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_bbab
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # ivec4_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.html
new file mode 100644
index 0000000000..bd16703c52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_vec2';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.test
new file mode 100644
index 0000000000..6a0eb1ddb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec2.test
@@ -0,0 +1,469 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group vec2_swizzles "vec2 swizzles"
+
+ case mediump_vec2_x
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_xx
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_xy
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_yx
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_yxy
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_xyxx
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_yyyy
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_s
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_ss
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_st
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_ts
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_tst
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_stss
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_tttt
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_r
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_rr
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_rg
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_gr
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_grg
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_rgrr
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_gggg
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vec2_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.html
new file mode 100644
index 0000000000..4caa0fc2a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_vec3';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.test
new file mode 100644
index 0000000000..f099dcfd2d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec3.test
@@ -0,0 +1,865 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group vec3_swizzles "vec3 swizzles"
+
+ case mediump_vec3_x
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_z
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xyz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zyx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xxx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zzz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zzy
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_yxy
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xzx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xyyx
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zzzz
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_s
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_p
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_sp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_pp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_stp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_pts
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_sss
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_ppp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_ppt
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_tst
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_sps
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_stts
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_pppp
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_r
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_b
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rgb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bgr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rrr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bbb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bbg
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_grg
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rbr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rggr
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bbbb
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vec3_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.html
new file mode 100644
index 0000000000..be64d18af1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_vec4';
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.test
new file mode 100644
index 0000000000..3fba360a42
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/swizzles_vec4.test
@@ -0,0 +1,1063 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group vec4_swizzles "vec4 swizzles"
+
+ case mediump_vec4_x
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_w
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wz
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_www
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_yyw
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wzy
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_xyzw
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wzyx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_xxxx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_yyyy
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wwww
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wzzw
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wwwy
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_xyxx
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_zzwz
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_s
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_q
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qs
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qp
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qqq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ttq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qpt
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_stpq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qpts
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ssss
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_tttt
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qqqq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qppq
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qqqt
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_stss
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ppqp
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_r
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_a
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ar
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ab
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_aaa
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_gga
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_abg
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_rgba
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_abgr
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_rrrr
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_gggg
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_aaaa
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_abba
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_aaag
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_rgrr
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_bbab
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vec4_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/template.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/template.html
new file mode 100644
index 0000000000..8d56d4dbe2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles2/shaders/template.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = ___TEST_NAME___;
+description("Shader test: " + testName + ".");
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/00_test_list.txt
new file mode 100644
index 0000000000..a556c4b7ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/00_test_list.txt
@@ -0,0 +1,33 @@
+arrays.html
+conditionals.html
+constants.html
+constant_expressions.html
+--min-version 2.0.1 conversions_matrix_combine.html
+--min-version 2.0.1 conversions_matrix_to_matrix.html
+--min-version 2.0.1 conversions_scalar_to_matrix.html
+--min-version 2.0.1 conversions_scalar_to_scalar.html
+--min-version 2.0.1 conversions_scalar_to_vector.html
+--min-version 2.0.1 conversions_vector_combine.html
+--min-version 2.0.1 conversions_vector_illegal.html
+--min-version 2.0.1 conversions_vector_to_scalar.html
+--min-version 2.0.1 conversions_vector_to_vector.html
+declarations.html
+fragdata.html
+functions.html
+invalid_texture_functions.html
+keywords.html
+linkage.html
+negative.html
+preprocessor.html
+qualification_order.html
+scoping.html
+switch.html
+--min-version 2.0.1 swizzles_bvec2.html
+--min-version 2.0.1 swizzles_bvec3.html
+--min-version 2.0.1 swizzles_bvec4.html
+--min-version 2.0.1 swizzles_ivec2.html
+--min-version 2.0.1 swizzles_ivec3.html
+--min-version 2.0.1 swizzles_ivec4.html
+--min-version 2.0.1 swizzles_vec2.html
+--min-version 2.0.1 swizzles_vec3.html
+--min-version 2.0.1 swizzles_vec4.html
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.html
new file mode 100644
index 0000000000..1a79102d02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'arrays';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.test
new file mode 100644
index 0000000000..f6276522b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/arrays.test
@@ -0,0 +1,1962 @@
+#X1. Type: float[5] // An array type with 5 elements
+#X2. Return value: float[5] func() { ... } // Function with a 5-element array return value
+#X3. Array constructor: float[3] (1.0, 2.0, 5.5) // 3-element array with given elements
+# // Fails with array of matrices!
+#X4. As unnamed parameter: void func(float[5]);
+#X5. Variable declaration: float[5] a; // Equivalent to float a[5]; (?)
+#X6. Empty brackets: float x[] = float[] (1.0, 2.0, 3.0); // Size of x is 3
+# float y[] = float[3] (1.0, 2.0, 3.0); // Size of y is 3 (equivalent)
+# float z[] = y; // Size of z is 3
+#X7. Testing that 2-dimensional arrays don't work: float a[5][3]; // Illegal
+# float[5] a[3]; // Illegal
+#X8. Testing that array declaration with dynamic variables as array size won't work.
+#X9. Testing length() operator: z.length(); // Returns 3 for z defined before
+#X10. Test C/C++ style {}-constructor
+#X11. Test struct arrays
+#X12. Test array element access at initialization with const/dynamic values
+
+group constructor "Array constructors"
+
+ case float3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, 0.5, 1.0) | vec3(2.0, 7.4, -1.0) | vec3(-2.0, 3.0, 1.6) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[3] x;
+ x = float[3] (in0.z, in0.x, in0.y);
+ out0 = vec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.5, 1.0, 2.0, 0.2) | vec4(7.4, -1.0, 2.0, -1.3) | vec4(3.0, 1.6, -2.0, 0.5) ];
+ output vec4 out0 = [ vec4(2.0, 0.5, 0.2, 1.0) | vec4(2.0, 7.4, -1.3, -1.0) | vec4(-2.0, 3.0, 0.5, 1.6) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[4] x;
+ x = float[4] (in0.z, in0.x, in0.w, in0.y);
+ out0 = vec4(x[0], x[1], x[2], x[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, 0, 1) | ivec3(2, 7, -1) | ivec3(-2, 3, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[3] x;
+ x = int[3] (in0.z, in0.x, in0.y);
+ out0 = ivec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, 0) | ivec4(7, -1, 2, -1) | ivec4(3, 1, -2, 0) ];
+ output ivec4 out0 = [ ivec4(2, 0, 0, 1) | ivec4(2, 7, -1, -1) | ivec4(-2, 3, 0, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[4] x;
+ x = int[4] (in0.z, in0.x, in0.w, in0.y);
+ out0 = ivec4(x[0], x[1], x[2], x[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, true, false) ];
+ output bvec3 out0 = [ bvec3(false, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[3] x;
+ x = bool[3] (in0.z, in0.x, in0.y);
+ out0 = bvec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, false) ];
+ output bvec4 out0 = [ bvec4(false, true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[4] x;
+ x = bool[4] (in0.z, in0.x, in0.y, in0.w);
+ out0 = bvec4(x[0], x[1], x[2], x[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(2.0, -0.5, -1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+
+
+ void main()
+ {
+ ${SETUP}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[3] x = test[3] (a, b, c);
+
+ out0 = vec3(x[0].f, x[1].v.y, x[2].v.x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.5, 1.0, 2.0, 1.5) ];
+ output vec4 out0 = [ vec4(2.0, -0.5, -1.0, -1.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+
+ void main()
+ {
+ ${SETUP}
+
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+ test d = test(-in0.w, vec3(-in0.w, -in0.x, -in0.z));
+
+ test[4] x = test[4] (a, b, c, d);
+
+ out0 = vec4(x[0].f, x[1].v.y, x[2].v.x, x[3].v.x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case float_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(0.5, -2.0, 1.0) | vec3(7.4, -2.0, -1.0) | vec3(3.0, 2.0, 1.6) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+
+ vec3[3] x;
+ x = vec3[3] ( vec3(in0.x, in0.y, in0.z) ,
+ vec3(-in0.y, -in0.z, -in0.x),
+ vec3(in0.z, in0.x, in0.y) );
+ out0 = vec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_vec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(5, -2, 1) | ivec3(7, -2, -1) | ivec3(3, 2, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+
+ ivec3[3] x;
+ x = ivec3[3] ( ivec3(in0.x, in0.y, in0.z) ,
+ ivec3(-in0.y, -in0.z, -in0.x),
+ ivec3(in0.z, in0.x, in0.y) );
+ out0 = ivec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_vec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+
+ bvec3[3] x;
+ x = bvec3[3] ( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x),
+ bvec3(in0.z, in0.x, in0.y) );
+ out0 = bvec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(0.5, -1.0, 1.0) | vec3(-1.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a = mat3[3] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_mat3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(0, -1, 1) | ivec3(-1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a = mat3[3] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_mat3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a = mat3[3] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y) ,
+ mat3( in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # type
+
+group return "Arrays as return value"
+
+ case float
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, -0.5, 1.0) | vec3(2.0, -7.4, -1.0) | vec3(-2.0, -3.0, 1.6) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float[3] func(vec3 a)
+ {
+ return float[3] (a.z, -a.x, a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float[3] x = func(in0);
+ out0 = vec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(4, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, -4, 1) | ivec3(2, -7, -1) | ivec3(-2, -3, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int[3] func(ivec3 a)
+ {
+ return int[3] (a.z, -a.x, a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int[3] x = func(in0);
+ out0 = ivec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, true) ];
+ output bvec3 out0 = [ bvec3(true, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool[3] func(bvec3 a)
+ {
+ return bool[3] (a.z, a.x, a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool[3] x = func(in0);
+ out0 = bvec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+
+ case float_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-0.5, 11.2, -1.0) ];
+ output vec3 out0 = [ vec3(1.0, 0.5, -2.0) | vec3(11.2, -0.5, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec3[3] func(vec3[3] a)
+ {
+ return vec3[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ vec3[3] x = vec3[3](vec3(in0.x, in0.y, -in0.z) ,
+ vec3(in0.y, -in0.z, in0.x) ,
+ vec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = vec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-1.0, 2.0, 0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test[3] func(test[3] a)
+ {
+ return test[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[3] t = test[3] (a, b, c);
+ test[3] x = func(t);
+
+ out0 = vec3(x[0].v.z, x[1].v.y, x[2].v.x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_vec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-5, 11, -1) ];
+ output ivec3 out0 = [ ivec3(1, 5, -2) | ivec3(11, -5, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ ivec3[3] func(ivec3[3] a)
+ {
+ return ivec3[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ ivec3[3] x = ivec3[3]( ivec3(in0.x, in0.y, -in0.z) ,
+ ivec3(in0.y, -in0.z, in0.x) ,
+ ivec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = ivec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_vec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bvec3[3] func(bvec3[3] a)
+ {
+ return bvec3[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bvec3[3] x = bvec3[3]( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x) ,
+ bvec3(in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = bvec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(2.0, -1.0, 2.0) | vec3(-2.3, 0.0, -2.3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_mat3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(2, -1, 2) | ivec3(-2, 0, -2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_mat3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) | bvec3(true, true, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y);
+ a[2] = mat3(in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # return
+
+group unnamed_parameter "Array type as unnamed parameter of a function prototype"
+
+ case float
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, 0.5, 1.0) | vec3(2.0, 7.4, -1.0) | vec3(-2.0, 3.0, 1.6) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float[3] func(float[3]);
+
+ void main()
+ {
+ ${SETUP}
+ float[3] a = float[3] (in0.x, in0.y, in0.z);
+ float[3] b = func(a);
+ out0 = vec3(b[0], b[1], b[2]);
+ ${OUTPUT}
+ }
+
+ float[3] func(float[3] a)
+ {
+ return float[3] (a[2], a[0], a[1]);
+ }
+
+ ""
+ end
+
+ case int
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, 0, 1) | ivec3(2, 7, -1) | ivec3(-2, 3, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int[3] func(int[3]);
+
+ void main()
+ {
+ ${SETUP}
+ int[3] a = int[3] (in0.x, in0.y, in0.z);
+ int[3] b = func(a);
+ out0 = ivec3(b[0], b[1], b[2]);
+ ${OUTPUT}
+ }
+
+ int[3] func(int[3] a)
+ {
+ return int[3] (a[2], a[0], a[1]);
+ }
+
+ ""
+ end
+
+ case bool
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, true) ];
+ output bvec3 out0 = [ bvec3(true, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool[3] func(bool[3]);
+
+ void main()
+ {
+ ${SETUP}
+ bool[3] a = bool[3] (in0.x, in0.y, in0.z);
+ bool[3] b = func(a);
+ out0 = bvec3(b[0], b[1], b[2]);
+ ${OUTPUT}
+ }
+
+ bool[3] func(bool[3] a)
+ {
+ return bool[3] (a[2], a[0], a[1]);
+ }
+
+ ""
+ end
+
+ case struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-1.0, 2.0, 0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test[3] func(test[3]);
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[3] t = test[3] (a, b, c);
+ test[3] x = func(t);
+ out0 = vec3(x[0].v.z, x[1].v.y, x[2].v.x);
+ ${OUTPUT}
+ }
+
+ test[3] func(test[3] a)
+ {
+ return test[3] (a[1], a[2], a[0]);
+ }
+
+ ""
+ end
+
+ case float_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-0.5, 11.2, -1.0) ];
+ output vec3 out0 = [ vec3(1.0, 0.5, -2.0) | vec3(11.2, -0.5, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec3[3] func(vec3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ vec3[3] x = vec3[3](vec3(in0.x, in0.y, -in0.z) ,
+ vec3(in0.y, -in0.z, in0.x) ,
+ vec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = vec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+
+ vec3[3] func(vec3[3] a)
+ {
+ return vec3[3] (a[1], a[2], a[0]);
+ }
+ ""
+ end
+
+ case int_vec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-5, 11, -1) ];
+ output ivec3 out0 = [ ivec3(1, 5, -2) | ivec3(11, -5, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ ivec3[3] func(ivec3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ ivec3[3] x = ivec3[3]( ivec3(in0.x, in0.y, -in0.z) ,
+ ivec3(in0.y, -in0.z, in0.x) ,
+ ivec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = ivec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+
+ ivec3[3] func(ivec3[3] a)
+ {
+ return ivec3[3] (a[1], a[2], a[0]);
+ }
+ ""
+ end
+
+ case bool_vec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bvec3[3] func(bvec3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ bvec3[3] x = bvec3[3]( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x) ,
+ bvec3(in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = bvec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+
+ bvec3[3] func(bvec3[3] a)
+ {
+ return bvec3[3] (a[1], a[2], a[0]);
+ }
+
+ ""
+ end
+
+ case float_mat3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(2.0, -1.0, 2.0) | vec3(-2.3, 0.0, -2.3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+ ""
+ end
+
+ case int_mat3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(2, -1, 2) | ivec3(-2, 0, -2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+ ""
+ end
+
+ case bool_mat3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) | bvec3(true, true, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3]);
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y);
+ a[2] = mat3(in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+ ""
+ end
+
+end # unnamed_parameter
+
+group declaration "Declaring arrays"
+
+ case implicit_size_float
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, 0.5, 1.0) | vec3(2.0, 7.4, -1.0) | vec3(-2.0, 3.0, 1.6) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[] x = float[] (in0.z, in0.x, in0.y);
+ float[] y = x;
+
+ out0 = vec3(y[0], y[1], y[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_int
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, 0, 1) | ivec3(2, 7, -1) | ivec3(-2, 3, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[] x = int[] (in0.z, in0.x, in0.y);
+ int[] y = x;
+
+ out0 = ivec3(y[0], y[1], y[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_bool
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, true) ];
+ output bvec3 out0 = [ bvec3(true, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[] x = bool[] (in0.z, in0.x, in0.y);
+ bool[] y = x;
+
+ out0 = bvec3(y[0], y[1], y[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-1.0, -0.5, 2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[] x = test[] (c, b, a);
+ test[] y = x;
+
+ out0 = vec3(y[0].v.x, y[1].v.y, y[2].v.z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_float_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-0.5, 11.2, -1.0) ];
+ output vec3 out0 = [ vec3(0.5, -2.0, 1.0) | vec3(-0.5, 1.0, 11.2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3[] x = vec3[] ( vec3(in0.x, in0.y, -in0.z) ,
+ vec3(in0.y, -in0.z, in0.x) ,
+ vec3(-in0.z, in0.x, in0.y) );
+ vec3[] y = x;
+ out0 = vec3(y[0].x, y[1].y, y[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_int_ivec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(5, 11, -1) ];
+ output ivec3 out0 = [ ivec3(0, -2, 1) | ivec3(5, 1, 11) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3[] x = ivec3[] ( ivec3(in0.x, in0.y, -in0.z) ,
+ ivec3(in0.y, -in0.z, in0.x) ,
+ ivec3(-in0.z, in0.x, in0.y) );
+ ivec3[] y = x;
+ out0 = ivec3(y[0].x, y[1].y, y[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_bool_bvec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3[] x = bvec3[] ( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x) ,
+ bvec3(in0.z, in0.x, in0.y) );
+ bvec3[] y = x;
+ out0 = bvec3(y[0].x, y[1].y, y[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_float_mat3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(0.5, -1.0, 1.0) | vec3(-1.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[] a = mat3[] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_int_mat3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(0, -1, 1) | ivec3(-1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[] a = mat3[] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_bool_mat3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[] a = mat3[] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y) ,
+ mat3( in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case constant_expression_array_size
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ const int a = 4;
+
+ void main ()
+ {
+ const int b = 5;
+ float[a] array1;
+ float[b] array2;
+ float[array1.length()] array3;
+ float[a+b] array4;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case constant_expression_array_access
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-2.0, -1.0, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ const int a = 3;
+
+ void main ()
+ {
+ ${SETUP}
+ const int b = 2;
+ float x = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [a];
+ float y = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [b+2];
+ float z = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [5];
+ out0 = vec3(x, y, z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case dynamic_expression_array_access
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ input ivec2 in1 = ivec2(3, 2);
+ output vec3 out0 = [ vec3(-2.0, -1.0, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ${SETUP}
+ float x = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [in1.x];
+ float y = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [in1.y+2];
+ float z = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [in1.x+in1.y];
+ out0 = vec3(x, y, z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multiple_declarations_single_statement_explicit
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(2.0, -1.0, 0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ${SETUP}
+ float[] x = float[6] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x),
+ y = float[2] (in0.x, -in0.y);
+ out0 = vec3(x[2], y[1], x[0]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multiple_declarations_single_statement_implicit
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) ];
+ output ivec3 out0 = [ ivec3(2, -1, 5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ${SETUP}
+ int[] x = int[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x),
+ y = int[] (in0.x, -in0.y);
+ out0 = ivec3(x[2], y[1], x[0]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # declaration
+
+group length "Array length method"
+
+ case float
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[] x = float[3] (in0.z, in0.x, in0.y);
+ float[] y = float[] (in0.z, in0.x, in0.y, in0.x, in0.y);
+ float[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[] x = int[3] (in0.z, in0.x, in0.y);
+ int[] y = int[] (in0.z, in0.x, in0.y, in0.x, in0.y);
+ int[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[] x = bool[3] (in0.z, in0.x, in0.y);
+ bool[] y = bool[] (in0.z, in0.x, in0.y, in0.x, in0.y);
+ bool[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[] x = test[3] (a, b, c);
+ test[] y = test[] (c, a, b, b, a);
+ test[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # length
+
+group invalid "Invalid Functions"
+
+ case multidimensional_array1
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float a[5][3];
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case multidimensional_array2
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float[5] a[3];
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case multidimensional_uniform_array
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform float a[3][2];
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case multidimensional_array_in_uniform_block
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform MyBlock
+ {
+ float a[3][2];
+ };
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case dynamic_expression_array_size
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ int a = 5;
+ float[a] array;
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_declaration_without_var_name
+ version 300 es
+ expect compile_or_link_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ int[];
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_declaration_with_var_name
+ version 300 es
+ expect compile_or_link_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ int[] a;
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case constructor_c-style1
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float a[];
+ a = float[3] { 1.0, 2.0, 3.0 };
+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case constructor_c-style2
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float a[5] = { 1.0, 2.0, 3.0 };
+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.html
new file mode 100644
index 0000000000..e786e14224
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conditionals';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.test
new file mode 100644
index 0000000000..a3a5b476fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conditionals.test
@@ -0,0 +1,381 @@
+group if "If Statements"
+
+ case single_statement
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ if (in0 >= 1.0)
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case compound_statement
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (in0 >= 1.0)
+ {
+ out0 = 1.0;
+ out1 = 0.0;
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sequence_statements
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (in0 >= 1.0)
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sequence_condition
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (false, in0 >= 1.0)
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex_condition
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (false || (in0 >= 1.0) && (in0 - 2.0*in0 < 0.0))
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_else
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 1.0)
+ out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_elseif
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ if (in0 >= 2.0)
+ out0 = 2.0;
+ else if (in0 >= 1.0)
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_elseif_else
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 2.0)
+ out0 = 2.0;
+ else if (in0 >= 1.0)
+ out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_if_elseif_else
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 2.0)
+ {
+ out0 = 2.0;
+ }
+ else if (in0 >= 1.0)
+ out0 = 2.0, out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # if
+
+group invalid_if "Invalid If Conditionals"
+
+ case missing_parenthesis
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if true
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unclosed_parenthesis
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (true
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (5)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_zero_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_one_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (1)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case int_uniform_condition
+ version 300 es
+ expect compile_fail
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ uniform int u0;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (u0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case float_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (5.0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case float_zero_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (0.0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case float_one_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (1.0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case sampler_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ uniform sampler2D s0;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (s0)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_if
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.html
new file mode 100644
index 0000000000..e74ca678f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'constant_expressions';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.test
new file mode 100644
index 0000000000..59c6cb6ffb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constant_expressions.test
@@ -0,0 +1,483 @@
+group trivial "Trivial expressions"
+
+ case float
+ version 300 es
+ values { output float out0 = 5.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = 5.0;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 300 es
+ values { output int out0 = 5; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = 5;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ version 300 es
+ values { output bool out0 = true; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = true;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case cast
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = float(int(bool(true)));
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # trivial
+
+group operators "Operators"
+
+ case math_float
+ version 300 es
+ values { output float out0 = 2.19; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = 6.0/3.5 + 1.8*2.6 - 4.2;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_vec
+ version 300 es
+ values { output float out0 = 15.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const vec3 a = (vec4(1.0, 2.0, 3.0, 4.0).zyx * vec3(1.0, 1.5, 3.0).xyz).xzy + (vec2(5.0)/vec2(2.5)).xxy;
+ out0 = a.x + a.y + a.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_int
+ version 300 es
+ values { output int out0 = 7; }
+ both ""
+ #version 300 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = 25%7 + 2*3 - 9/3;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_ivec
+ version 300 es
+ values { output int out0 = 21; }
+ both ""
+ #version 300 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const ivec3 a = ivec2(25%7, 4).xxy + ivec4(1*3, 9/3, 1+2, 8/4).xyz;
+ out0 = a.x + a.y + a.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_mat
+ version 300 es
+ values { output float out0 = 8.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const mat3 a = mat3(3.0) * mat3(4.0);
+ const mat4 b = mat4(a[1][1])*2.0;
+ const mat2 c = mat2(b[0][0]) / 3.0;
+ out0 = c[0][0]+c[1][0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise
+ version 300 es
+ values { output int out0 = 678332; }
+ both ""
+ #version 300 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = (((0xABBA<<4) ^ 0xCAFE) | (0xDCBA & (0xABCD>>2))) ^ (~0xDEAD & 0xBEEF);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical
+ version 300 es
+ values { output bool out0 = true; }
+ both ""
+ #version 300 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = (!false || false) && (true ^^ false);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case compare
+ version 300 es
+ values { output bool out0 = true; }
+ both ""
+ #version 300 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = (false == false) && (true != false) && (1 < 2) && (3 <= 3) && ((1 > 1) != (1 >= 1));
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case selection
+ version 300 es
+ values { output float out0 = 5.3; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = false ? 0.0 : (true ? 5.3 : 1.0);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # operators
+
+group complex_types "Arrays & Structs"
+
+ case struct
+ version 300 es
+ values { output float out0 = 260.922; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct S
+ {
+ vec4 a;
+ int b;
+ };
+
+ void main()
+ {
+ const S s = S(vec4(1.5), 123);
+ out0 = length(s.a.xy)*float(s.b);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_struct
+ version 300 es
+ values { output float out0 = 965.9; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct S
+ {
+ vec4 v;
+ int i;
+ };
+
+ struct T
+ {
+ S s;
+ bool b;
+ int i;
+ };
+
+ struct U
+ {
+ S s;
+ T t;
+ };
+
+ void main()
+ {
+ const S s = S(vec4(1.5), 123);
+ const T t = T(s, false, 3);
+ const U u = U(s, t);
+ const U v = U(S(vec4(1.3), 4), T(S(vec4(2.0), 5), true, 6));
+ out0 = float(u.s.i*v.t.i + v.t.s.i)*v.s.v.x; // float(123*6 + 5)*1.3
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_size
+ version 300 es
+ values { output int out0 = 1; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a[max(-1, 1)] = int[1](1);
+ out0 = a[0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_length
+ version 300 es
+ values { output int out0 = 2; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a[1] = int[1](1);
+ out0 = a.length() + a[0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array
+ version 300 es
+ values { output float out0 = 4.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a[1+2+5] = float[8](0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0);
+ const float f = a[1+2+4];
+ out0 = f + float(a.length()-8);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # complex_types
+
+group other "Other operations"
+
+ case switch_case
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 4 | 10];
+ }
+
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int _0 = 0;
+ const int _1 = 1;
+ const int _2 = 2;
+ const int _3 = 3;
+ const int _4 = 4;
+
+ switch(int(in0))
+ {
+ case _0:
+ out0 = 0;
+ break;
+ case _1:
+ out0 = 1;
+ break;
+ case _2:
+ out0 = 2;
+ break;
+ case _3:
+ out0 = 3;
+ break;
+ case _4:
+ out0 = 4;
+ break;
+ case 5:
+ out0 = 10;
+ break;
+ default:
+ out0 = 100;
+
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_builtin_funcs
+ version 300 es
+ values { output float out0 = 3.05; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = sqrt( atan(sin(1.5)/cos(1.5)) /*1.5*/ * log2(exp2(log(exp(6.2) + 0.1)) + 0.1) /*~6.2*/);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 4 | 10];
+ }
+
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct T
+ {
+ vec4 v;
+ };
+
+ struct S
+ {
+ T t;
+ int i;
+ bool b;
+ };
+
+ void main()
+ {
+ const T t = T(vec4(1.0));
+ const S s = S(t, 42, true);
+ const int _0 = int(sin(0.0));
+ const int _1 = int(1.0);
+ const int _2 = 2 + int(float(_0>_1));
+ const int _3 = min(gl_MaxVertexAttribs, 16)/4 - 1;
+ const int _4 = min(gl_MaxDrawBuffers, 4);
+ const ivec4 nums = ivec4(0, 1, 2, 3);
+
+ switch(int(in0))
+ {
+ case int(float(_0)):
+ out0 = ((true!=false) && (!false)) ? 0 : 25;
+ break;
+ case ivec3(_1).x:
+ out0 = 3*18/9-5;
+ break;
+ case nums[_2]:
+ out0 = int(length(vec4(1.0))+0.001);
+ break;
+ case _3:
+ out0 = 3;
+ break;
+ case clamp(_4, 1, 6):
+ out0 = (s.i-2)/10;
+ break;
+ case max(3, 5):
+ out0 = 10;
+ break;
+ default:
+ out0 = 100;
+
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.html
new file mode 100644
index 0000000000..891af46e5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'constants';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.test
new file mode 100644
index 0000000000..93e71b72b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/constants.test
@@ -0,0 +1,1153 @@
+case float_input
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ output float out0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ }
+ values
+ {
+ input float in0 = [ -1.123 | -0.75 | 512.0 | -72.13 | -199.91 ];
+ output float out0 = [ -1.123 | -0.75 | 512.0 | -72.13 | -199.91 ];
+ }
+
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = in0;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_uniform
+ version 300 es
+ values
+ {
+ uniform float uni0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ output float out0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ }
+
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ uniform float uni0;
+ void main()
+ {
+ out0 = uni0;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_0
+ version 300 es
+ values { output float out0 = 1.123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = +1.123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_1
+ version 300 es
+ values { output float out0 = -1.123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_2
+ version 300 es
+ values { output float out0 = 123.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 123.;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_3
+ version 300 es
+ values { output float out0 = 0.123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = .123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_4
+ version 300 es
+ values { output float out0 = 123.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.23e+2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_5
+ version 300 es
+ values { output float out0 = -123.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.23E+2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_6
+ version 300 es
+ values { output float out0 = -123.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.23e2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_7
+ version 300 es
+ values { output float out0 = 0.123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.23e-1;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_8
+ version 300 es
+ values { output float out0 = 1000.0; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1e3;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_f_suffix_0
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ float value = 1.0f;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_f_suffix_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ float value = 1.0F;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_0
+ version 300 es
+ values { output int out0 = 123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_1
+ version 300 es
+ values { output int out0 = -321; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -321;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_2
+ version 300 es
+ values { output int out0 = 123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0x7B;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_3
+ version 300 es
+ values { output int out0 = 123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0X7b;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_4
+ version 300 es
+ values { output int out0 = 123; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0173;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case bool_0
+ version 300 es
+ values { output bool out0 = true; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = true;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case bool_1
+ version 300 es
+ values { output bool out0 = false; }
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = false;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_global
+ version 300 es
+ values { output float out0 = 1000.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 1000.0;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_main
+ version 300 es
+ values { output float out0 = -1000.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant = -1000.0;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_function
+ version 300 es
+ values { output float out0 = -0.012; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ float func()
+ {
+ const float theConstant = -0.012;
+ return theConstant;
+ }
+ void main()
+ {
+ out0 = func();
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_1
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant = 100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_2
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ void main()
+ {
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_3
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_4
+ version 300 es
+ values { output float out0 = 2.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ float func()
+ {
+ const float theConstant = 2.0;
+ return theConstant;
+ }
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = func();
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_operations_with_const
+ version 300 es
+ values { output float out0 = 21.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theGlobalConstant = 10.0;
+ float func()
+ {
+ const float theConstant = 2.0;
+ return theConstant;
+ }
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = func() * theGlobalConstant + theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_1
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant1 = 10.0;
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_2
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant1 = 10.0;
+ {
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_3
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant1 = 10.0;
+ void main()
+ {
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_4
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant1 = 10.0;
+ float func()
+ {
+ const float theConstant2 = theConstant1;
+ return theConstant2;
+ }
+ void main()
+ {
+ out0 = func();
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_uniform
+ version 300 es
+ expect compile_fail
+ values { output float out0 = 10.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform float theUniform;
+ void main()
+ {
+ const float theConstant = theUniform;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_varying
+ version 300 es
+ expect compile_fail
+ values { output float out0 = 10.0; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out float theVarying;
+ void main()
+ {
+ theVarying = 1.0;
+ gl_Position = vec(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in float theVarying;
+ void main()
+ {
+ const float theConstant = theVarying;
+ out0 = theConstant;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+end
+
+case const_float_function_gotcha
+ version 300 es
+ desc "Function constant parameters are not really constants, so using them as constant expressions should fail."
+ expect compile_fail
+ values { output float out0 = 20.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ float func(const float gotcha)
+ {
+ const float theConstant2 = gotcha;
+ return theConstant2*2.0;
+ }
+ void main()
+ {
+ const float theConstant = 10.0;
+ out0 = func(theConstant);
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_int
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = float(10);
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec2
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec2(1.0, 10.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec3
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec3(1.0, 10.0, 20.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec4
+ version 300 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec4(1.0, 10.0, 20.0, -10.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_variable_1
+ version 300 es
+ expect compile_fail
+ values { output float out0 = 20.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ float theVariable = 20.0;
+ const float theConstant = theVariable;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_variable_2
+ version 300 es
+ expect compile_fail
+ values { output float out0 = 50.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ float theVariable = 20.0;
+ theVariable += 30.0;
+ const float theConstant = theVariable;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assign_user_func
+ version 300 es
+ expect compile_fail
+ values { output float out0 = 50.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ float func()
+ {
+ return 50.0;
+ }
+ void main()
+ {
+ const float theConstant = func();
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_decimal
+ version 300 es
+ values { output int out0 = 7; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 7;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_octal
+ version 300 es
+ values { output int out0 = 15; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 017;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_hexadecimal_0
+ version 300 es
+ values { output int out0 = 47; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 0x2f;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_hexadecimal_1
+ version 300 es
+ values { output int out0 = 47; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 0X2f;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_decimal_0
+ version 300 es
+ values { output uint out0 = 7; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 7u;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_decimal_1
+ version 300 es
+ values { output uint out0 = 7; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 7U;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_octal_0
+ version 300 es
+ values { output uint out0 = 15; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 017u;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_octal_1
+ version 300 es
+ values { output uint out0 = 15; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 017U;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_hexadecimal_0
+ version 300 es
+ values { output uint out0 = 47; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 0x2fU;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_hexadecimal_1
+ version 300 es
+ values { output uint out0 = 47; }
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 0X2fu;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_from_uint
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ int value = 7u;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case uint_from_int
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ uint value = 7;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case int_from_float
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ int value = 7.0;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case uint_from_float
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ uint value = 7.0;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case bool_from_int
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ bool value = 1;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case bool_from_uint
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ bool value = 1u;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case bool_from_float
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ bool value = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case float_int_f_suffix_0
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ float value = 1f;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case float_int_f_suffix_1
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ float value = 1F;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case int_l_suffix
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ int value = 1l;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case uint_ul_suffix
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ uint value = 1ul;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case invalid_octal_0
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ int value = 018;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case invalid_octal_1
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ uint value = 09U;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case invalid_hexadecimal_0
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ int value = 0x2g7;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
+
+case invalid_hexadecimal_1
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ uint value = 0X1h7u;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.template b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.template
new file mode 100644
index 0000000000..3a42d5c193
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.template
@@ -0,0 +1,25 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.test
new file mode 100644
index 0000000000..968c2d264f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions.test
@@ -0,0 +1,14246 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group scalar_to_scalar "Scalar to Scalar Conversions"
+
+ case float_to_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_int
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 0 | -8 | -20 | 36 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bool
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_float
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 5.0 | 8.0 | 11.0 | -12.0 | -66.0 | -192.0 | 255.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output int out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bool
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_float
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output float out0 = [ 0.0 | 2.0 | 3.0 | 8.0 | 9.0 | 12.0 | 10.0 | 45.0 | 193.0 | 255.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_int
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output int out0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bool
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_float
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output float out0 = [ 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_int
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output int out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uint
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uint out0 = [ 0 | 1 | 2 | 3 | 0 | 8 | 20 | 36 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uint
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uint out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uint
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uint out0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uint
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uint out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_scalar
+group scalar_to_vector "Scalar to Vector Conversions"
+
+ case float_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(3.5, 3.5) | vec2(-0.5, -0.5) | vec2(-8.25, -8.25) | vec2(-20.125, -20.125) | vec2(36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(3.5, 3.5, 3.5) | vec3(-0.5, -0.5, -0.5) | vec3(-8.25, -8.25, -8.25) | vec3(-20.125, -20.125, -20.125) | vec3(36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.5, 3.5, 3.5, 3.5) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-8.25, -8.25, -8.25, -8.25) | vec4(-20.125, -20.125, -20.125, -20.125) | vec4(36.8125, 36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(3, 3) | ivec2(0, 0) | ivec2(-8, -8) | ivec2(-20, -20) | ivec2(36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(0, 0, 0) | ivec3(-8, -8, -8) | ivec3(-20, -20, -20) | ivec3(36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(0, 0, 0, 0) | ivec4(-8, -8, -8, -8) | ivec4(-20, -20, -20, -20) | ivec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(5.0, 5.0) | vec2(8.0, 8.0) | vec2(11.0, 11.0) | vec2(-12.0, -12.0) | vec2(-66.0, -66.0) | vec2(-192.0, -192.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(5.0, 5.0, 5.0) | vec3(8.0, 8.0, 8.0) | vec3(11.0, 11.0, 11.0) | vec3(-12.0, -12.0, -12.0) | vec3(-66.0, -66.0, -66.0) | vec3(-192.0, -192.0, -192.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(5.0, 5.0, 5.0, 5.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(11.0, 11.0, 11.0, 11.0) | vec4(-12.0, -12.0, -12.0, -12.0) | vec4(-66.0, -66.0, -66.0, -66.0) | vec4(-192.0, -192.0, -192.0, -192.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(5, 5) | ivec2(8, 8) | ivec2(11, 11) | ivec2(-12, -12) | ivec2(-66, -66) | ivec2(-192, -192) | ivec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(5, 5, 5) | ivec3(8, 8, 8) | ivec3(11, 11, 11) | ivec3(-12, -12, -12) | ivec3(-66, -66, -66) | ivec3(-192, -192, -192) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(5, 5, 5, 5) | ivec4(8, 8, 8, 8) | ivec4(11, 11, 11, 11) | ivec4(-12, -12, -12, -12) | ivec4(-66, -66, -66, -66) | ivec4(-192, -192, -192, -192) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(2.0, 2.0) | vec2(3.0, 3.0) | vec2(8.0, 8.0) | vec2(9.0, 9.0) | vec2(12.0, 12.0) | vec2(10.0, 10.0) | vec2(45.0, 45.0) | vec2(193.0, 193.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(2.0, 2.0, 2.0) | vec3(3.0, 3.0, 3.0) | vec3(8.0, 8.0, 8.0) | vec3(9.0, 9.0, 9.0) | vec3(12.0, 12.0, 12.0) | vec3(10.0, 10.0, 10.0) | vec3(45.0, 45.0, 45.0) | vec3(193.0, 193.0, 193.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.0, 3.0, 3.0, 3.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(12.0, 12.0, 12.0, 12.0) | vec4(10.0, 10.0, 10.0, 10.0) | vec4(45.0, 45.0, 45.0, 45.0) | vec4(193.0, 193.0, 193.0, 193.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(2, 2) | ivec2(3, 3) | ivec2(8, 8) | ivec2(9, 9) | ivec2(12, 12) | ivec2(10, 10) | ivec2(45, 45) | ivec2(193, 193) | ivec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(8, 8, 8) | ivec3(9, 9, 9) | ivec3(12, 12, 12) | ivec3(10, 10, 10) | ivec3(45, 45, 45) | ivec3(193, 193, 193) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(8, 8, 8, 8) | ivec4(9, 9, 9, 9) | ivec4(12, 12, 12, 12) | ivec4(10, 10, 10, 10) | ivec4(45, 45, 45, 45) | ivec4(193, 193, 193, 193) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(2, 2) | uvec2(3, 3) | uvec2(0, 0) | uvec2(8, 8) | uvec2(20, 20) | uvec2(36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(2, 2, 2) | uvec3(3, 3, 3) | uvec3(0, 0, 0) | uvec3(8, 8, 8) | uvec3(20, 20, 20) | uvec3(36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(2, 2, 2, 2) | uvec4(3, 3, 3, 3) | uvec4(0, 0, 0, 0) | uvec4(8, 8, 8, 8) | uvec4(20, 20, 20, 20) | uvec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(2, 2) | uvec2(5, 5) | uvec2(8, 8) | uvec2(11, 11) | uvec2(12, 12) | uvec2(66, 66) | uvec2(192, 192) | uvec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(2, 2, 2) | uvec3(5, 5, 5) | uvec3(8, 8, 8) | uvec3(11, 11, 11) | uvec3(12, 12, 12) | uvec3(66, 66, 66) | uvec3(192, 192, 192) | uvec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(2, 2, 2, 2) | uvec4(5, 5, 5, 5) | uvec4(8, 8, 8, 8) | uvec4(11, 11, 11, 11) | uvec4(12, 12, 12, 12) | uvec4(66, 66, 66, 66) | uvec4(192, 192, 192, 192) | uvec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(2, 2) | uvec2(3, 3) | uvec2(8, 8) | uvec2(9, 9) | uvec2(12, 12) | uvec2(10, 10) | uvec2(45, 45) | uvec2(193, 193) | uvec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(2, 2, 2) | uvec3(3, 3, 3) | uvec3(8, 8, 8) | uvec3(9, 9, 9) | uvec3(12, 12, 12) | uvec3(10, 10, 10) | uvec3(45, 45, 45) | uvec3(193, 193, 193) | uvec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(2, 2, 2, 2) | uvec4(3, 3, 3, 3) | uvec4(8, 8, 8, 8) | uvec4(9, 9, 9, 9) | uvec4(12, 12, 12, 12) | uvec4(10, 10, 10, 10) | uvec4(45, 45, 45, 45) | uvec4(193, 193, 193, 193) | uvec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec3 out0 = [ uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec4 out0 = [ uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_vector
+group vector_to_scalar "Vector to Scalar Conversions"
+
+ case vec2_to_float
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_int
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bool
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_float
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_int
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bool
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_float
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_int
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bool
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_float
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_int
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bool
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_float
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_int
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bool
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_float
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_int
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bool
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_float
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_int
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bool
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_float
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_int
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bool
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_float
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_int
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bool
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_float
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_int
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bool
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_float
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_int
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bool
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_float
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_int
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bool
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uint
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.5, 2.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uint
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uint
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uint
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uint
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uint
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uint
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uint
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uint
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uint
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uint
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uint
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_scalar
+group vector_illegal "Illegal Vector Conversions"
+
+ case vec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_illegal
+group vector_to_vector "Vector to Vector Conversions"
+
+ case vec4_to_vec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec4 out0 = [ bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, -2.0, -4.0, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 2.0, 4.0, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 2.0, 4.0) | vec3(32.0, 64.0, 51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 1.0) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(0.0, 1.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 1, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec4 out0 = [ uvec4(1, 0, 0, 1) | uvec4(0, 0, 0, 1) | uvec4(0, 1, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 1, 0) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 2.0, 4.0) | vec3(32.0, 64.0, 51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 1, 0) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.5, 2.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_vector
+group scalar_to_matrix "Scalar to Matrix Conversions"
+
+ case float_to_mat4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25) | mat4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125) | mat4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat4x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0) | mat4x3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0) | mat4x3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0) | mat4x3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0) | mat4x3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat4x2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(3.5, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0) | mat4x2(-0.5, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0) | mat4x2(-8.25, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0) | mat4x2(-20.125, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0) | mat4x2(36.8125, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0) | mat3x4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0) | mat3x4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0) | mat3x4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0) | mat3x4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5) | mat3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5) | mat3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25) | mat3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125) | mat3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3x2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(3.5, 0.0, 0.0, 3.5, 0.0, 0.0) | mat3x2(-0.5, 0.0, 0.0, -0.5, 0.0, 0.0) | mat3x2(-8.25, 0.0, 0.0, -8.25, 0.0, 0.0) | mat3x2(-20.125, 0.0, 0.0, -20.125, 0.0, 0.0) | mat3x2(36.8125, 0.0, 0.0, 36.8125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0) | mat2x4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0) | mat2x4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0) | mat2x4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0) | mat2x4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0) | mat2x3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0) | mat2x3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0) | mat2x3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0) | mat2x3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.5, 0.0, 0.0, 3.5) | mat2(-0.5, 0.0, 0.0, -0.5) | mat2(-8.25, 0.0, 0.0, -8.25) | mat2(-20.125, 0.0, 0.0, -20.125) | mat2(36.8125, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0) | mat4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0) | mat4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0) | mat4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4x3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0) | mat4x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0) | mat4x3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0) | mat4x3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0) | mat4x3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0) | mat4x3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0) | mat4x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4x2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(5.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(11.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-12.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-66.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-192.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3x4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0) | mat3x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat3x4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0) | mat3x4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0) | mat3x4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0) | mat3x4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0) | mat3x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0) | mat3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0) | mat3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0) | mat3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3x2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(5.0, 0.0, 0.0, 5.0, 0.0, 0.0) | mat3x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat3x2(11.0, 0.0, 0.0, 11.0, 0.0, 0.0) | mat3x2(-12.0, 0.0, 0.0, -12.0, 0.0, 0.0) | mat3x2(-66.0, 0.0, 0.0, -66.0, 0.0, 0.0) | mat3x2(-192.0, 0.0, 0.0, -192.0, 0.0, 0.0) | mat3x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2x4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0) | mat2x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat2x4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0) | mat2x4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0) | mat2x4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0) | mat2x4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0) | mat2x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2x3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0) | mat2x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat2x3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0) | mat2x3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0) | mat2x3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0) | mat2x3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0) | mat2x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(5.0, 0.0, 0.0, 5.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(11.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, -12.0) | mat2(-66.0, 0.0, 0.0, -66.0) | mat2(-192.0, 0.0, 0.0, -192.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0) | mat4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0) | mat4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0) | mat4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0) | mat4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4x3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0) | mat4x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0) | mat4x3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0) | mat4x3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0) | mat4x3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0) | mat4x3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0) | mat4x3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0) | mat4x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4x2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(3.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(9.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(12.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(10.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(45.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(193.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3x4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0) | mat3x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat3x4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0) | mat3x4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0) | mat3x4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0) | mat3x4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0) | mat3x4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0) | mat3x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 9.0) | mat3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 12.0) | mat3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0) | mat3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 45.0) | mat3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 193.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3x2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(3.0, 0.0, 0.0, 3.0, 0.0, 0.0) | mat3x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat3x2(9.0, 0.0, 0.0, 9.0, 0.0, 0.0) | mat3x2(12.0, 0.0, 0.0, 12.0, 0.0, 0.0) | mat3x2(10.0, 0.0, 0.0, 10.0, 0.0, 0.0) | mat3x2(45.0, 0.0, 0.0, 45.0, 0.0, 0.0) | mat3x2(193.0, 0.0, 0.0, 193.0, 0.0, 0.0) | mat3x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2x4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0) | mat2x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat2x4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0) | mat2x4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0) | mat2x4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0) | mat2x4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0) | mat2x4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0) | mat2x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2x3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0) | mat2x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat2x3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0) | mat2x3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0) | mat2x3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0) | mat2x3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0) | mat2x3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0) | mat2x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.0, 0.0, 0.0, 3.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(9.0, 0.0, 0.0, 9.0) | mat2(12.0, 0.0, 0.0, 12.0) | mat2(10.0, 0.0, 0.0, 10.0) | mat2(45.0, 0.0, 0.0, 45.0) | mat2(193.0, 0.0, 0.0, 193.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_matrix
+group matrix_to_matrix "Matrix to Matrix Conversions"
+
+ case mat4_to_mat4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0, 9.975, -6.542, 0.015625, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0, 9.975, -6.542, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0, 9.975, -6.542, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, -24.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.125, 0.03125, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0) | mat4x2(-18.725, -0.0125, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0) | mat3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0) | mat3x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0) | mat3x2(8.0, -24.0, 16.0, -16.0, 0.0, 0.0) | mat3x2(0.125, 0.03125, 0.0625, 0.015625, 0.0, 0.0) | mat3x2(-18.725, -0.0125, -0.5, 19.975, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0) | mat2x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0) | mat2x4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0) | mat2x4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0) | mat2x4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0) | mat2x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0) | mat2x3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0) | mat2x3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0) | mat2x3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_to_matrix
+group vector_combine "Vector Combine Constructors"
+
+ case vec2_vec2_to_vec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, -32.0, 64.0) | vec4(-32.0, 64.0, 1.0, 1.25) | vec4(1.0, 1.25, 0.0, 0.5) | vec4(0.0, 0.5, -0.5, -2.25) | vec4(-0.75, -0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_ivec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output ivec4 out0 = [ ivec4(0, -2, -32, 64) | ivec4(-32, 64, 1, 1) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_bvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_vec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 1.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) | vec4(1.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_ivec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 1, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 1) | ivec4(0, 0, 1, 1) | ivec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_bvec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, false, false, false) | bvec4(false, true, false, true) | bvec4(false, false, true, true) | bvec4(true, true, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_vec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 3.5, 3.5) | vec4(0.0, 36.8125, 36.8125, 36.8125) | vec4(-0.5, -8.25, -8.25, 1.0) | vec4(-8.25, 2.0, 1.0, -8.25) | vec4(3.5, 3.5, 2.0, 2.0) | vec4(-20.125, 1.0, 0.0, 0.0) | vec4(36.8125, -20.125, -20.125, -0.5) | vec4(2.0, -0.5, -0.5, -20.125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_ivec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 3, 3) | ivec4(0, 36, 36, 36) | ivec4(0, -8, -8, 1) | ivec4(-8, 2, 1, -8) | ivec4(3, 3, 2, 2) | ivec4(-20, 1, 0, 0) | ivec4(36, -20, -20, 0) | ivec4(2, 0, 0, -20) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_bvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output vec4 out0 = [ vec4(-12.0, 2.0, 11.0, -192.0) | vec4(-66.0, 5.0, 255.0, -66.0) | vec4(2.0, -66.0, 5.0, 8.0) | vec4(5.0, 11.0, 8.0, -12.0) | vec4(8.0, -192.0, 2.0, 1.0) | vec4(-192.0, 8.0, -192.0, 2.0) | vec4(255.0, -12.0, -12.0, 0.0) | vec4(1.0, 1.0, -66.0, 255.0) | vec4(0.0, 255.0, 1.0, 5.0) | vec4(11.0, 0.0, 0.0, 11.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output ivec4 out0 = [ ivec4(-12, 2, 11, -192) | ivec4(-66, 5, 255, -66) | ivec4(2, -66, 5, 8) | ivec4(5, 11, 8, -12) | ivec4(8, -192, 2, 1) | ivec4(-192, 8, -192, 2) | ivec4(255, -12, -12, 0) | ivec4(1, 1, -66, 255) | ivec4(0, 255, 1, 5) | ivec4(11, 0, 0, 11) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_vec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output vec4 out0 = [ vec4(193.0, 12.0, 9.0, 3.0) | vec4(3.0, 45.0, 8.0, 9.0) | vec4(255.0, 193.0, 12.0, 12.0) | vec4(8.0, 2.0, 2.0, 2.0) | vec4(10.0, 8.0, 255.0, 255.0) | vec4(9.0, 255.0, 45.0, 193.0) | vec4(2.0, 0.0, 3.0, 0.0) | vec4(12.0, 3.0, 0.0, 10.0) | vec4(0.0, 9.0, 193.0, 45.0) | vec4(45.0, 10.0, 10.0, 8.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_ivec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output ivec4 out0 = [ ivec4(193, 12, 9, 3) | ivec4(3, 45, 8, 9) | ivec4(255, 193, 12, 12) | ivec4(8, 2, 2, 2) | ivec4(10, 8, 255, 255) | ivec4(9, 255, 45, 193) | ivec4(2, 0, 3, 0) | ivec4(12, 3, 0, 10) | ivec4(0, 9, 193, 45) | ivec4(45, 10, 10, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_bvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, true, false) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 0.0, 0.0) | vec4(0.0, 0.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output ivec4 out0 = [ ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(false, false, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output vec4 out0 = [ vec4(1.0, 36.8125, -66.0, 1.0) | vec4(1.0, 0.0, 2.0, 1.0) | vec4(0.0, -8.25, 255.0, 0.0) | vec4(0.0, 1.0, 11.0, 0.0) | vec4(0.0, -0.5, 1.0, 1.0) | vec4(1.0, 0.0, 8.0, 1.0) | vec4(0.0, 2.0, -192.0, 0.0) | vec4(0.0, -20.125, -12.0, 1.0) | vec4(1.0, 3.5, 0.0, 0.0) | vec4(1.0, 1.0, 5.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output ivec4 out0 = [ ivec4(1, 36, -66, 1) | ivec4(1, 0, 2, 1) | ivec4(0, -8, 255, 0) | ivec4(0, 1, 11, 0) | ivec4(0, 0, 1, 1) | ivec4(1, 0, 8, 1) | ivec4(0, 2, -192, 0) | ivec4(0, -20, -12, 1) | ivec4(1, 3, 0, 0) | ivec4(1, 1, 5, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(false, true, true, false) | bvec4(false, true, true, false) | bvec4(false, true, true, true) | bvec4(true, false, true, true) | bvec4(false, true, true, false) | bvec4(false, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_vec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(-0.75, -0.0322580645161, 0.0, -2.0) | vec4(-0.5, -2.25, 0.0, 0.0) | vec4(-32.0, 64.0, -32.0, 64.0) | vec4(1.0, 1.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_ivec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, 64) | ivec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_bvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(false, true, false, false) | bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_vec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output vec4 out0 = [ vec4(-0.75, -0.0322580645161, 0.0, 1.0) | vec4(-32.0, 64.0, 0.0, 0.0) | vec4(1.0, 1.25, 0.0, 0.0) | vec4(0.0, 0.5, 1.0, 1.0) | vec4(-0.5, -2.25, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_ivec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 1) | ivec4(-32, 64, 0, 0) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) | ivec4(0, -2, 1, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_bvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output bvec4 out0 = [ bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(true, true, false, false) | bvec4(false, true, true, true) | bvec4(true, true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_vec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, -0.5) | vec4(0.0, 0.0, 0.0, 3.5) | vec4(0.0, 1.0, 0.0, 2.0) | vec4(1.0, 1.0, 1.0, 0.0) | vec4(0.0, 0.0, 0.0, -8.25) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(1.0, 0.0, 0.0, 36.8125) | vec4(0.0, 1.0, 0.0, -20.125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_ivec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 0) | ivec4(0, 0, 0, 3) | ivec4(0, 1, 0, 2) | ivec4(1, 1, 1, 0) | ivec4(0, 0, 0, -8) | ivec4(0, 0, 0, 1) | ivec4(1, 0, 0, 36) | ivec4(0, 1, 0, -20) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_bvec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, true) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_vec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output vec4 out0 = [ vec4(-32.0, 64.0, -51.0, -0.5) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.0) | vec4(1.0, 1.25, 1.125, 3.5) | vec4(-0.5, -2.25, -4.875, -20.125) | vec4(0.0, 0.5, 0.75, 2.0) | vec4(-0.5, -2.25, -4.875, -8.25) | vec4(0.0, 0.5, 0.75, 1.0) | vec4(1.0, 1.25, 1.125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_ivec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(-32, 64, -51, 0) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 3) | ivec4(0, -2, -4, -20) | ivec4(0, 0, 0, 2) | ivec4(0, -2, -4, -8) | ivec4(0, 0, 0, 1) | ivec4(1, 1, 1, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_bvec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output vec4 out0 = [ vec4(-12.0, 0.0, -2.0, 1.0) | vec4(11.0, -32.0, 64.0, 11.0) | vec4(8.0, 0.0, 0.0, 2.0) | vec4(255.0, 0.0, -2.0, -66.0) | vec4(0.0, 1.0, 1.0, -192.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(-66.0, -32.0, 64.0, -12.0) | vec4(2.0, 1.0, 1.0, 255.0) | vec4(-192.0, 0.0, 0.0, 5.0) | vec4(5.0, 0.0, 0.0, 8.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output ivec4 out0 = [ ivec4(-12, 0, -2, 1) | ivec4(11, -32, 64, 11) | ivec4(8, 0, 0, 2) | ivec4(255, 0, -2, -66) | ivec4(0, 1, 1, -192) | ivec4(1, 0, 0, 0) | ivec4(-66, -32, 64, -12) | ivec4(2, 1, 1, 255) | ivec4(-192, 0, 0, 5) | ivec4(5, 0, 0, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, -32.0, 64.0) | vec4(0.0, 2.0, 0.0, 0.0) | vec4(0.0, 3.5, 0.0, 0.0) | vec4(1.0, -20.125, 0.0, -2.0) | vec4(1.0, -0.5, 0.0, -2.0) | vec4(1.0, 36.8125, 0.0, 0.0) | vec4(0.0, -8.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, -32, 64) | ivec4(0, 2, 0, 0) | ivec4(0, 3, 0, 0) | ivec4(1, -20, 0, -2) | ivec4(1, 0, 0, -2) | ivec4(1, 36, 0, 0) | ivec4(0, -8, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, true, true) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, true, false, true) | bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(false, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_vec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 0.0) | vec4(-20.125, 0.0, 0.0, 0.0) | vec4(-8.25, 1.0, 1.0, 1.0) | vec4(-0.5, 0.0, 2.0, 4.0) | vec4(0.0, 0.0, 0.0, 0.0) | vec4(2.0, 1.0, 1.0, 1.0) | vec4(3.5, 0.0, 2.0, 4.0) | vec4(36.8125, 32.0, 64.0, 51.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_ivec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 0) | ivec4(-20, 0, 0, 0) | ivec4(-8, 1, 1, 1) | ivec4(0, 0, 2, 4) | ivec4(0, 0, 0, 0) | ivec4(2, 1, 1, 1) | ivec4(3, 0, 2, 4) | ivec4(36, 32, 64, 51) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_bvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output bvec4 out0 = [ bvec4(true, false, false, false) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 2.0, 0.0) | vec4(-192.0, 1.0, 1.0, 0.0) | vec4(-66.0, 0.0, 0.0, 1.0) | vec4(-12.0, 0.0, 2.0, 1.0) | vec4(0.0, 32.0, 64.0, 1.0) | vec4(2.0, 0.0, 0.0, 1.0) | vec4(11.0, 32.0, 64.0, 1.0) | vec4(8.0, 0.0, 0.0, 0.0) | vec4(255.0, 1.0, 1.0, 0.0) | vec4(5.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output ivec4 out0 = [ ivec4(1, 0, 2, 0) | ivec4(-192, 1, 1, 0) | ivec4(-66, 0, 0, 1) | ivec4(-12, 0, 2, 1) | ivec4(0, 32, 64, 1) | ivec4(2, 0, 0, 1) | ivec4(11, 32, 64, 1) | ivec4(8, 0, 0, 0) | ivec4(255, 1, 1, 0) | ivec4(5, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output bvec4 out0 = [ bvec4(true, false, true, false) | bvec4(true, true, true, false) | bvec4(true, false, false, true) | bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, false, false, false) | bvec4(true, true, true, false) | bvec4(true, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_uvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.0, 0.5) | vec2(0.5, 2.25) | vec2(1.0, 1.25) ];
+ input vec2 in1 = [ vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(32.0, 64.0) | vec2(0.0, 0.5) | vec2(0.75, 0.0322580645161) ];
+ output uvec4 out0 = [ uvec4(32, 64, 0, 2) | uvec4(0, 0, 1, 1) | uvec4(0, 0, 32, 64) | uvec4(0, 2, 0, 0) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_uvec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) ];
+ output uvec4 out0 = [ uvec4(1, 0, 1, 1) | uvec4(0, 1, 0, 0) | uvec4(1, 1, 1, 0) | uvec4(0, 0, 0, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_uvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 36.8125 | 0.0 | 20.125 | 1.0 | 0.5 | 8.25 | 3.5 ];
+ input float in1 = [ 1.0 | 8.25 | 2.0 | 20.125 | 36.8125 | 0.0 | 0.5 | 3.5 ];
+ input float in2 = [ 0.0 | 8.25 | 2.0 | 1.0 | 36.8125 | 20.125 | 0.5 | 3.5 ];
+ input float in3 = [ 1.0 | 8.25 | 0.0 | 2.0 | 20.125 | 3.5 | 0.5 | 36.8125 ];
+ output uvec4 out0 = [ uvec4(2, 1, 0, 1) | uvec4(36, 8, 8, 8) | uvec4(0, 2, 2, 0) | uvec4(20, 20, 1, 2) | uvec4(1, 36, 36, 20) | uvec4(0, 0, 20, 3) | uvec4(8, 0, 0, 0) | uvec4(3, 3, 3, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 192 | 2 | 12 | 11 | 0 | 8 | 5 | 66 | 1 | 255 ];
+ input int in1 = [ 66 | 12 | 5 | 1 | 0 | 192 | 8 | 255 | 11 | 2 ];
+ input int in2 = [ 192 | 5 | 1 | 66 | 255 | 11 | 8 | 12 | 2 | 0 ];
+ input int in3 = [ 255 | 5 | 11 | 12 | 2 | 1 | 66 | 0 | 8 | 192 ];
+ output uvec4 out0 = [ uvec4(192, 66, 192, 255) | uvec4(2, 12, 5, 5) | uvec4(12, 5, 1, 11) | uvec4(11, 1, 66, 12) | uvec4(0, 0, 255, 2) | uvec4(8, 192, 11, 1) | uvec4(5, 8, 8, 66) | uvec4(66, 255, 12, 0) | uvec4(1, 11, 2, 8) | uvec4(255, 2, 0, 192) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_uvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 255 | 8 | 3 | 193 | 45 | 2 | 0 | 12 | 9 | 10 ];
+ input uint in1 = [ 255 | 45 | 0 | 12 | 2 | 10 | 8 | 9 | 193 | 3 ];
+ input uint in2 = [ 3 | 0 | 2 | 9 | 12 | 10 | 255 | 45 | 193 | 8 ];
+ input uint in3 = [ 2 | 255 | 10 | 193 | 8 | 12 | 3 | 9 | 0 | 45 ];
+ output uvec4 out0 = [ uvec4(255, 255, 3, 2) | uvec4(8, 45, 0, 255) | uvec4(3, 0, 2, 10) | uvec4(193, 12, 9, 193) | uvec4(45, 2, 12, 8) | uvec4(2, 10, 10, 12) | uvec4(0, 8, 255, 3) | uvec4(12, 9, 45, 9) | uvec4(9, 193, 193, 0) | uvec4(10, 3, 8, 45) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ true | false ];
+ output uvec4 out0 = [ uvec4(0, 0, 1, 1) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | true | false | true | true | true | false | false ];
+ input float in1 = [ 20.125 | 0.0 | 1.0 | 3.5 | 1.0 | 0.0 | 0.5 | 8.25 | 2.0 | 36.8125 ];
+ input int in2 = [ 66 | 192 | 1 | 2 | 5 | 11 | 8 | 12 | 255 | 0 ];
+ input bool in3 = [ true | true | true | true | false | true | false | false | false | false ];
+ output uvec4 out0 = [ uvec4(1, 20, 66, 1) | uvec4(0, 0, 192, 1) | uvec4(0, 1, 1, 1) | uvec4(1, 3, 2, 1) | uvec4(0, 1, 5, 0) | uvec4(1, 0, 11, 1) | uvec4(1, 0, 8, 0) | uvec4(1, 8, 12, 0) | uvec4(0, 2, 255, 0) | uvec4(0, 36, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_uvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.0, 0.5) ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) | ivec2(0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 2, 1, 1) | uvec4(1, 1, 0, 2) | uvec4(32, 64, 32, 64) | uvec4(0, 0, 0, 0) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_uvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.5, 2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(true, true) ];
+ output uvec4 out0 = [ uvec4(32, 64, 0, 0) | uvec4(0, 0, 0, 0) | uvec4(0, 2, 1, 0) | uvec4(0, 0, 0, 1) | uvec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_uvec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ 2.0 | 0.0 | 36.8125 | 0.5 | 1.0 | 8.25 | 3.5 | 20.125 ];
+ output uvec4 out0 = [ uvec4(1, 0, 0, 2) | uvec4(1, 1, 1, 0) | uvec4(0, 1, 0, 36) | uvec4(0, 0, 0, 0) | uvec4(0, 0, 0, 1) | uvec4(0, 1, 0, 8) | uvec4(1, 0, 0, 3) | uvec4(0, 0, 0, 20) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_uvec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 2.25, 4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(1.0, 1.25, 1.125) | vec3(0.75, 0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) ];
+ input float in1 = [ 8.25 | 1.0 | 0.0 | 36.8125 | 2.0 | 0.5 | 20.125 | 3.5 ];
+ output uvec4 out0 = [ uvec4(0, 2, 4, 8) | uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) | uvec4(0, 2, 4, 36) | uvec4(32, 64, 51, 2) | uvec4(1, 1, 1, 0) | uvec4(0, 0, 0, 20) | uvec4(0, 0, 0, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | 1 | 11 | 192 | 255 | 12 | 66 | 2 | 0 | 5 ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(32, 64) | ivec2(0, 2) | ivec2(0, 2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(32, 64) | ivec2(0, 0) ];
+ input int in2 = [ 2 | 192 | 12 | 0 | 8 | 1 | 66 | 255 | 11 | 5 ];
+ output uvec4 out0 = [ uvec4(8, 1, 1, 2) | uvec4(1, 0, 0, 192) | uvec4(11, 1, 1, 12) | uvec4(192, 32, 64, 0) | uvec4(255, 0, 2, 8) | uvec4(12, 0, 2, 1) | uvec4(66, 0, 0, 66) | uvec4(2, 0, 0, 255) | uvec4(0, 32, 64, 11) | uvec4(5, 0, 0, 5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | false | true ];
+ input float in1 = [ 8.25 | 0.5 | 2.0 | 20.125 | 0.0 | 36.8125 | 3.5 | 1.0 ];
+ input ivec2 in2 = [ ivec2(32, 64) | ivec2(1, 1) | ivec2(0, 2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output uvec4 out0 = [ uvec4(1, 8, 32, 64) | uvec4(1, 0, 1, 1) | uvec4(0, 2, 0, 2) | uvec4(0, 20, 0, 0) | uvec4(1, 0, 0, 0) | uvec4(0, 36, 0, 2) | uvec4(0, 3, 1, 1) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_uvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 20.125 | 1.0 | 0.5 | 3.5 | 2.0 | 36.8125 | 0.0 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 2, 4) | uvec3(1, 1, 1) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(8, 0, 0, 0) | uvec4(20, 0, 0, 0) | uvec4(1, 0, 2, 4) | uvec4(0, 32, 64, 51) | uvec4(3, 0, 2, 4) | uvec4(2, 1, 1, 1) | uvec4(36, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | 1 | 11 | 66 | 192 | 12 | 8 | 255 | 0 | 5 ];
+ input uvec2 in1 = [ uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(1, 1) | uvec2(32, 64) | uvec2(0, 0) ];
+ input bool in2 = [ true | false | false | false | false | true | true | true | false | true ];
+ output uvec4 out0 = [ uvec4(2, 1, 1, 1) | uvec4(1, 0, 0, 0) | uvec4(11, 0, 0, 0) | uvec4(66, 0, 2, 0) | uvec4(192, 0, 0, 0) | uvec4(12, 0, 2, 1) | uvec4(8, 32, 64, 1) | uvec4(255, 1, 1, 1) | uvec4(0, 32, 64, 0) | uvec4(5, 0, 0, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_vec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output vec3 out0 = [ vec3(-0.5, 2.0, 1.0) | vec3(1.0, -20.125, 3.5) | vec3(3.5, 3.5, 2.0) | vec3(-8.25, 36.8125, -8.25) | vec3(36.8125, -8.25, -20.125) | vec3(0.0, 1.0, -0.5) | vec3(2.0, -0.5, 36.8125) | vec3(-20.125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_ivec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output ivec3 out0 = [ ivec3(0, 2, 1) | ivec3(1, -20, 3) | ivec3(3, 3, 2) | ivec3(-8, 36, -8) | ivec3(36, -8, -20) | ivec3(0, 1, 0) | ivec3(2, 0, 36) | ivec3(-20, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_bvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_vec3
+ version 300 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output vec3 out0 = [ vec3(-192.0, 5.0, -192.0) | vec3(5.0, 1.0, 1.0) | vec3(-12.0, 8.0, 2.0) | vec3(0.0, 0.0, 5.0) | vec3(11.0, 2.0, -12.0) | vec3(8.0, -192.0, 8.0) | vec3(1.0, -12.0, 11.0) | vec3(-66.0, 255.0, 0.0) | vec3(255.0, -66.0, 255.0) | vec3(2.0, 11.0, -66.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_ivec3
+ version 300 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output ivec3 out0 = [ ivec3(-192, 5, -192) | ivec3(5, 1, 1) | ivec3(-12, 8, 2) | ivec3(0, 0, 5) | ivec3(11, 2, -12) | ivec3(8, -192, 8) | ivec3(1, -12, 11) | ivec3(-66, 255, 0) | ivec3(255, -66, 255) | ivec3(2, 11, -66) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_bvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_vec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output vec3 out0 = [ vec3(8.0, 193.0, 12.0) | vec3(45.0, 2.0, 2.0) | vec3(2.0, 9.0, 193.0) | vec3(3.0, 8.0, 255.0) | vec3(255.0, 0.0, 8.0) | vec3(193.0, 255.0, 10.0) | vec3(12.0, 45.0, 45.0) | vec3(0.0, 3.0, 0.0) | vec3(9.0, 10.0, 3.0) | vec3(10.0, 12.0, 9.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_ivec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output ivec3 out0 = [ ivec3(8, 193, 12) | ivec3(45, 2, 2) | ivec3(2, 9, 193) | ivec3(3, 8, 255) | ivec3(255, 0, 8) | ivec3(193, 255, 10) | ivec3(12, 45, 45) | ivec3(0, 3, 0) | ivec3(9, 10, 3) | ivec3(10, 12, 9) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_bvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 8.0) | vec3(1.0, 36.8125, -192.0) | vec3(0.0, 0.0, -66.0) | vec3(0.0, -8.25, 2.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 3.5, -12.0) | vec3(1.0, 1.0, 11.0) | vec3(0.0, -0.5, 255.0) | vec3(0.0, -20.125, 5.0) | vec3(1.0, 2.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output ivec3 out0 = [ ivec3(1, 0, 8) | ivec3(1, 36, -192) | ivec3(0, 0, -66) | ivec3(0, -8, 2) | ivec3(1, 1, 1) | ivec3(0, 3, -12) | ivec3(1, 1, 11) | ivec3(0, 0, 255) | ivec3(0, -20, 5) | ivec3(1, 2, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(false, true, true) | bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_vec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.25, 0.0) | vec3(-0.75, -0.0322580645161, 1.0) | vec3(-32.0, 64.0, 1.0) | vec3(-0.5, -2.25, 1.0) | vec3(0.0, 0.5, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_ivec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 0) | ivec3(0, 0, 1) | ivec3(-32, 64, 1) | ivec3(0, -2, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_bvec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_vec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, -20.125) | vec3(0.0, 1.0, 2.0) | vec3(0.0, 1.0, 36.8125) | vec3(1.0, 0.0, 1.0) | vec3(0.0, 0.0, 3.5) | vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, -8.25) | vec3(0.0, 0.0, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output ivec3 out0 = [ ivec3(1, 0, -20) | ivec3(0, 1, 2) | ivec3(0, 1, 36) | ivec3(1, 0, 1) | ivec3(0, 0, 3) | ivec3(0, 0, 0) | ivec3(1, 1, -8) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, true) | bvec3(false, true, true) | bvec3(true, false, true) | bvec3(false, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_vec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, -66.0) | vec3(0.0, 0.0, 255.0) | vec3(1.0, 0.0, 8.0) | vec3(0.0, 0.0, -192.0) | vec3(0.0, 1.0, 2.0) | vec3(1.0, 0.0, 5.0) | vec3(0.0, 1.0, 11.0) | vec3(0.0, 0.0, -12.0) | vec3(1.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, -66) | ivec3(0, 0, 255) | ivec3(1, 0, 8) | ivec3(0, 0, -192) | ivec3(0, 1, 2) | ivec3(1, 0, 5) | ivec3(0, 1, 11) | ivec3(0, 0, -12) | ivec3(1, 1, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, false, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(true, false, true) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, -2.0) | vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 1.0) | vec3(1.0, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output ivec3 out0 = [ ivec3(1, 0, -2) | ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 1) | ivec3(1, -32, 64) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_vec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output vec3 out0 = [ vec3(-20.125, 0.0, 0.0) | vec3(36.8125, 0.0, 2.0) | vec3(-8.25, 32.0, 64.0) | vec3(2.0, 0.0, 0.0) | vec3(-0.5, 0.0, 2.0) | vec3(0.0, 0.0, 0.0) | vec3(3.5, 1.0, 1.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_ivec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output ivec3 out0 = [ ivec3(-20, 0, 0) | ivec3(36, 0, 2) | ivec3(-8, 32, 64) | ivec3(2, 0, 0) | ivec3(0, 0, 2) | ivec3(0, 0, 0) | ivec3(3, 1, 1) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_bvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(true, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_uvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 20.125 | 2.0 | 3.5 | 0.5 | 36.8125 | 1.0 | 0.0 ];
+ input float in1 = [ 1.0 | 0.0 | 3.5 | 36.8125 | 8.25 | 2.0 | 0.5 | 20.125 ];
+ input float in2 = [ 20.125 | 0.5 | 8.25 | 36.8125 | 1.0 | 0.0 | 3.5 | 2.0 ];
+ output uvec3 out0 = [ uvec3(8, 1, 20) | uvec3(20, 0, 0) | uvec3(2, 3, 8) | uvec3(3, 36, 36) | uvec3(0, 8, 1) | uvec3(36, 2, 0) | uvec3(1, 0, 3) | uvec3(0, 20, 2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_uvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 255 | 192 | 2 | 5 | 12 | 0 | 11 | 8 | 66 ];
+ input int in1 = [ 192 | 66 | 5 | 8 | 11 | 1 | 0 | 255 | 12 | 2 ];
+ input int in2 = [ 192 | 5 | 1 | 11 | 66 | 8 | 12 | 0 | 2 | 255 ];
+ output uvec3 out0 = [ uvec3(1, 192, 192) | uvec3(255, 66, 5) | uvec3(192, 5, 1) | uvec3(2, 8, 11) | uvec3(5, 11, 66) | uvec3(12, 1, 8) | uvec3(0, 0, 12) | uvec3(11, 255, 0) | uvec3(8, 12, 2) | uvec3(66, 2, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_uvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 9 | 45 | 255 | 2 | 0 | 10 | 8 | 12 | 3 ];
+ input uint in1 = [ 3 | 45 | 2 | 9 | 10 | 0 | 8 | 12 | 255 | 193 ];
+ input uint in2 = [ 2 | 3 | 9 | 10 | 255 | 8 | 12 | 0 | 193 | 45 ];
+ output uvec3 out0 = [ uvec3(193, 3, 2) | uvec3(9, 45, 3) | uvec3(45, 2, 9) | uvec3(255, 9, 10) | uvec3(2, 10, 255) | uvec3(0, 0, 8) | uvec3(10, 8, 12) | uvec3(8, 12, 0) | uvec3(12, 255, 193) | uvec3(3, 193, 45) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ output uvec3 out0 = [ uvec3(0, 0, 1) | uvec3(1, 1, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | false | false | true | false | true | true | false ];
+ input float in1 = [ 36.8125 | 20.125 | 1.0 | 0.0 | 3.5 | 1.0 | 2.0 | 0.5 | 0.0 | 8.25 ];
+ input int in2 = [ 1 | 0 | 8 | 66 | 2 | 11 | 192 | 5 | 12 | 255 ];
+ output uvec3 out0 = [ uvec3(1, 36, 1) | uvec3(0, 20, 0) | uvec3(1, 1, 8) | uvec3(0, 0, 66) | uvec3(0, 3, 2) | uvec3(1, 1, 11) | uvec3(0, 2, 192) | uvec3(1, 0, 5) | uvec3(1, 0, 12) | uvec3(0, 8, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_uvec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(32.0, 64.0) | vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(0.75, 0.0322580645161) ];
+ input bool in1 = [ false | false | true | true | true ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(32, 64, 0) | uvec3(0, 2, 1) | uvec3(1, 1, 1) | uvec3(0, 0, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) ];
+ input float in1 = [ 8.25 | 36.8125 | 20.125 | 2.0 | 0.0 | 1.0 | 0.5 | 3.5 ];
+ output uvec3 out0 = [ uvec3(1, 1, 8) | uvec3(1, 0, 36) | uvec3(0, 1, 20) | uvec3(0, 0, 2) | uvec3(1, 0, 0) | uvec3(0, 1, 1) | uvec3(0, 0, 0) | uvec3(0, 0, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) ];
+ input int in1 = [ 255 | 1 | 2 | 5 | 0 | 11 | 192 | 12 | 8 | 66 ];
+ output uvec3 out0 = [ uvec3(1, 1, 255) | uvec3(0, 1, 1) | uvec3(0, 0, 2) | uvec3(1, 1, 5) | uvec3(0, 0, 0) | uvec3(1, 0, 11) | uvec3(0, 0, 192) | uvec3(0, 0, 12) | uvec3(0, 1, 8) | uvec3(1, 0, 66) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(32, 64) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 2) | uvec3(1, 1, 1) | uvec3(1, 0, 0) | uvec3(0, 32, 64) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_uvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 8.25 | 20.125 | 3.5 | 0.0 | 0.5 | 36.8125 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ output uvec3 out0 = [ uvec3(2, 0, 2) | uvec3(8, 1, 1) | uvec3(20, 32, 64) | uvec3(3, 0, 0) | uvec3(0, 0, 2) | uvec3(0, 0, 0) | uvec3(36, 1, 1) | uvec3(1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output vec2 out0 = [ vec2(-0.5, 1.0) | vec2(-20.125, -20.125) | vec2(1.0, 0.0) | vec2(2.0, 3.5) | vec2(3.5, -8.25) | vec2(36.8125, 36.8125) | vec2(-8.25, -0.5) | vec2(0.0, 2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output ivec2 out0 = [ ivec2(0, 1) | ivec2(-20, -20) | ivec2(1, 0) | ivec2(2, 3) | ivec2(3, -8) | ivec2(36, 36) | ivec2(-8, 0) | ivec2(0, 2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output vec2 out0 = [ vec2(2.0, -192.0) | vec2(-66.0, 8.0) | vec2(0.0, 1.0) | vec2(5.0, 0.0) | vec2(-12.0, 5.0) | vec2(8.0, -66.0) | vec2(-192.0, 2.0) | vec2(1.0, 255.0) | vec2(11.0, 11.0) | vec2(255.0, -12.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output ivec2 out0 = [ ivec2(2, -192) | ivec2(-66, 8) | ivec2(0, 1) | ivec2(5, 0) | ivec2(-12, 5) | ivec2(8, -66) | ivec2(-192, 2) | ivec2(1, 255) | ivec2(11, 11) | ivec2(255, -12) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_vec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output vec2 out0 = [ vec2(9.0, 8.0) | vec2(12.0, 9.0) | vec2(0.0, 45.0) | vec2(255.0, 2.0) | vec2(8.0, 12.0) | vec2(45.0, 193.0) | vec2(3.0, 255.0) | vec2(2.0, 0.0) | vec2(10.0, 3.0) | vec2(193.0, 10.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_ivec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output ivec2 out0 = [ ivec2(9, 8) | ivec2(12, 9) | ivec2(0, 45) | ivec2(255, 2) | ivec2(8, 12) | ivec2(45, 193) | ivec2(3, 255) | ivec2(2, 0) | ivec2(10, 3) | ivec2(193, 10) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_bvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_vec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_ivec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_bvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output vec2 out0 = [ vec2(0.0, -66.0) | vec2(3.5, 1.0) | vec2(0.0, 255.0) | vec2(2.0, -192.0) | vec2(-8.25, 8.0) | vec2(36.8125, 2.0) | vec2(-20.125, 0.0) | vec2(1.0, 5.0) | vec2(1.0, -12.0) | vec2(-0.5, 11.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output ivec2 out0 = [ ivec2(0, -66) | ivec2(3, 1) | ivec2(0, 255) | ivec2(2, -192) | ivec2(-8, 8) | ivec2(36, 2) | ivec2(-20, 0) | ivec2(1, 5) | ivec2(1, -12) | ivec2(0, 11) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output vec2 out0 = [ vec2(2.0, 0.0) | vec2(3.5, 1.0) | vec2(1.0, 1.0) | vec2(-20.125, 0.0) | vec2(-8.25, 0.0) | vec2(0.0, 1.0) | vec2(-0.5, 0.0) | vec2(36.8125, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output ivec2 out0 = [ ivec2(2, 0) | ivec2(3, 1) | ivec2(1, 1) | ivec2(-20, 0) | ivec2(-8, 0) | ivec2(0, 1) | ivec2(0, 0) | ivec2(36, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output vec2 out0 = [ vec2(255.0, 1.0) | vec2(2.0, 0.0) | vec2(-12.0, 0.0) | vec2(1.0, 0.0) | vec2(-192.0, 1.0) | vec2(5.0, 0.0) | vec2(8.0, 1.0) | vec2(0.0, 0.0) | vec2(-66.0, 1.0) | vec2(11.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output ivec2 out0 = [ ivec2(255, 1) | ivec2(2, 0) | ivec2(-12, 0) | ivec2(1, 0) | ivec2(-192, 1) | ivec2(5, 0) | ivec2(8, 1) | ivec2(0, 0) | ivec2(-66, 1) | ivec2(11, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output vec2 out0 = [ vec2(-66.0, 193.0) | vec2(1.0, 0.0) | vec2(-192.0, 2.0) | vec2(-12.0, 10.0) | vec2(5.0, 255.0) | vec2(255.0, 12.0) | vec2(11.0, 45.0) | vec2(0.0, 8.0) | vec2(2.0, 9.0) | vec2(8.0, 3.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output ivec2 out0 = [ ivec2(-66, 193) | ivec2(1, 0) | ivec2(-192, 2) | ivec2(-12, 10) | ivec2(5, 255) | ivec2(255, 12) | ivec2(11, 45) | ivec2(0, 8) | ivec2(2, 9) | ivec2(8, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_vec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output vec2 out0 = [ vec2(12.0, -20.125) | vec2(0.0, 0.0) | vec2(8.0, 3.5) | vec2(193.0, -8.25) | vec2(3.0, 0.0) | vec2(10.0, 1.0) | vec2(9.0, 2.0) | vec2(2.0, 36.8125) | vec2(45.0, -0.5) | vec2(255.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_ivec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output ivec2 out0 = [ ivec2(12, -20) | ivec2(0, 0) | ivec2(8, 3) | ivec2(193, -8) | ivec2(3, 0) | ivec2(10, 1) | ivec2(9, 2) | ivec2(2, 36) | ivec2(45, 0) | ivec2(255, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_bvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 36.8125 | 1.0 | 0.5 | 20.125 | 0.0 | 2.0 | 3.5 ];
+ input float in1 = [ 0.5 | 36.8125 | 0.0 | 2.0 | 8.25 | 20.125 | 1.0 | 3.5 ];
+ output uvec2 out0 = [ uvec2(8, 0) | uvec2(36, 36) | uvec2(1, 0) | uvec2(0, 2) | uvec2(20, 8) | uvec2(0, 20) | uvec2(2, 1) | uvec2(3, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 12 | 8 | 11 | 255 | 66 | 192 | 2 | 5 | 1 ];
+ input int in1 = [ 11 | 12 | 2 | 5 | 66 | 192 | 255 | 0 | 1 | 8 ];
+ output uvec2 out0 = [ uvec2(0, 11) | uvec2(12, 12) | uvec2(8, 2) | uvec2(11, 5) | uvec2(255, 66) | uvec2(66, 192) | uvec2(192, 255) | uvec2(2, 0) | uvec2(5, 1) | uvec2(1, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_uvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 3 | 9 | 10 | 193 | 8 | 0 | 255 | 45 | 2 | 12 ];
+ input uint in1 = [ 0 | 2 | 12 | 3 | 10 | 9 | 45 | 193 | 255 | 8 ];
+ output uvec2 out0 = [ uvec2(3, 0) | uvec2(9, 2) | uvec2(10, 12) | uvec2(193, 3) | uvec2(8, 10) | uvec2(0, 9) | uvec2(255, 45) | uvec2(45, 193) | uvec2(2, 255) | uvec2(12, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_uvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 1.0 | 0.5 | 3.5 | 2.0 | 0.0 | 36.8125 | 1.0 | 0.0 | 20.125 ];
+ input int in1 = [ 0 | 255 | 12 | 5 | 192 | 2 | 66 | 11 | 1 | 8 ];
+ output uvec2 out0 = [ uvec2(8, 0) | uvec2(1, 255) | uvec2(0, 12) | uvec2(3, 5) | uvec2(2, 192) | uvec2(0, 2) | uvec2(36, 66) | uvec2(1, 11) | uvec2(0, 1) | uvec2(20, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 3.5 | 1.0 | 8.25 | 0.5 | 2.0 | 36.8125 | 0.0 | 20.125 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true ];
+ output uvec2 out0 = [ uvec2(3, 1) | uvec2(1, 0) | uvec2(8, 1) | uvec2(0, 0) | uvec2(2, 1) | uvec2(36, 0) | uvec2(0, 0) | uvec2(20, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 12 | 11 | 0 | 5 | 8 | 255 | 2 | 1 | 66 | 192 ];
+ input bool in1 = [ true | true | false | false | false | true | false | false | true | true ];
+ output uvec2 out0 = [ uvec2(12, 1) | uvec2(11, 1) | uvec2(0, 0) | uvec2(5, 0) | uvec2(8, 0) | uvec2(255, 1) | uvec2(2, 0) | uvec2(1, 0) | uvec2(66, 1) | uvec2(192, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | 5 | 1 | 0 | 11 | 12 | 192 | 66 | 255 | 2 ];
+ input uint in1 = [ 8 | 10 | 45 | 255 | 9 | 193 | 2 | 3 | 0 | 12 ];
+ output uvec2 out0 = [ uvec2(8, 8) | uvec2(5, 10) | uvec2(1, 45) | uvec2(0, 255) | uvec2(11, 9) | uvec2(12, 193) | uvec2(192, 2) | uvec2(66, 3) | uvec2(255, 0) | uvec2(2, 12) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_uvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 45 | 8 | 3 | 10 | 2 | 193 | 12 | 255 | 0 ];
+ input float in1 = [ 3.5 | 20.125 | 2.0 | 0.0 | 1.0 | 36.8125 | 8.25 | 1.0 | 0.0 | 0.5 ];
+ output uvec2 out0 = [ uvec2(9, 3) | uvec2(45, 20) | uvec2(8, 2) | uvec2(3, 0) | uvec2(10, 1) | uvec2(2, 36) | uvec2(193, 8) | uvec2(12, 1) | uvec2(255, 0) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_combine
+group matrix_combine "Matrix Combine Constructors"
+
+ case vec2_vec2_to_mat2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input vec2 in1 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 0.0, 0.5) | mat2(-32.0, 64.0, 1.0, 1.25) | mat2(-0.5, -2.25, -0.75, -0.0322580645161) | mat2(-0.75, -0.0322580645161, -32.0, 64.0) | mat2(0.0, 0.5, -0.5, -2.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_mat2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, true) ];
+ output mat2 out0 = [ mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 1.0, 1.0, 0.0) | mat2(1.0, 0.0, 0.0, 0.0) | mat2(0.0, 0.0, 1.0, 1.0) | mat2(0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_mat2
+ version 300 es
+ values
+ {
+ input float in0 = [ -8.25 | 3.5 | 36.8125 | 2.0 | -20.125 | 1.0 | -0.5 | 0.0 ];
+ input float in1 = [ 3.5 | -20.125 | 1.0 | 0.0 | -8.25 | 2.0 | 36.8125 | -0.5 ];
+ input float in2 = [ 36.8125 | 3.5 | 0.0 | -20.125 | -0.5 | -8.25 | 1.0 | 2.0 ];
+ input float in3 = [ -0.5 | 0.0 | -8.25 | -20.125 | 2.0 | 3.5 | 1.0 | 36.8125 ];
+ output mat2 out0 = [ mat2(-8.25, 3.5, 36.8125, -0.5) | mat2(3.5, -20.125, 3.5, 0.0) | mat2(36.8125, 1.0, 0.0, -8.25) | mat2(2.0, 0.0, -20.125, -20.125) | mat2(-20.125, -8.25, -0.5, 2.0) | mat2(1.0, 2.0, -8.25, 3.5) | mat2(-0.5, 36.8125, 1.0, 1.0) | mat2(0.0, -0.5, 2.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | 1 | -192 | 11 | -66 | 255 | 0 | 8 | -12 | 5 ];
+ input int in1 = [ 11 | 255 | 5 | -66 | 8 | 2 | 0 | -12 | 1 | -192 ];
+ input int in2 = [ 11 | 1 | -12 | 255 | 5 | 0 | 8 | -192 | 2 | -66 ];
+ input int in3 = [ 2 | 1 | 0 | 8 | 255 | -66 | -192 | 11 | 5 | -12 ];
+ output mat2 out0 = [ mat2(2.0, 11.0, 11.0, 2.0) | mat2(1.0, 255.0, 1.0, 1.0) | mat2(-192.0, 5.0, -12.0, 0.0) | mat2(11.0, -66.0, 255.0, 8.0) | mat2(-66.0, 8.0, 5.0, 255.0) | mat2(255.0, 2.0, 0.0, -66.0) | mat2(0.0, 0.0, 8.0, -192.0) | mat2(8.0, -12.0, -192.0, 11.0) | mat2(-12.0, 1.0, 2.0, 5.0) | mat2(5.0, -192.0, -66.0, -12.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_mat2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 9 | 12 | 45 | 10 | 2 | 8 | 3 | 255 | 0 ];
+ input uint in1 = [ 0 | 255 | 12 | 193 | 3 | 2 | 45 | 9 | 8 | 10 ];
+ input uint in2 = [ 3 | 9 | 10 | 2 | 12 | 193 | 255 | 0 | 8 | 45 ];
+ input uint in3 = [ 45 | 12 | 9 | 3 | 2 | 255 | 10 | 8 | 193 | 0 ];
+ output mat2 out0 = [ mat2(193.0, 0.0, 3.0, 45.0) | mat2(9.0, 255.0, 9.0, 12.0) | mat2(12.0, 12.0, 10.0, 9.0) | mat2(45.0, 193.0, 2.0, 3.0) | mat2(10.0, 3.0, 12.0, 2.0) | mat2(2.0, 2.0, 193.0, 255.0) | mat2(8.0, 45.0, 255.0, 10.0) | mat2(3.0, 9.0, 0.0, 8.0) | mat2(255.0, 8.0, 8.0, 193.0) | mat2(0.0, 10.0, 45.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 0.0) | mat2(0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | true | false | true | true | false | false ];
+ input float in1 = [ 2.0 | -0.5 | 0.0 | 1.0 | 1.0 | 36.8125 | 3.5 | 0.0 | -8.25 | -20.125 ];
+ input int in2 = [ 0 | -12 | 8 | -192 | 1 | -66 | 5 | 11 | 2 | 255 ];
+ input bool in3 = [ true | false | true | false | true | false | false | true | true | false ];
+ output mat2 out0 = [ mat2(0.0, 2.0, 0.0, 1.0) | mat2(1.0, -0.5, -12.0, 0.0) | mat2(0.0, 0.0, 8.0, 1.0) | mat2(1.0, 1.0, -192.0, 0.0) | mat2(1.0, 1.0, 1.0, 1.0) | mat2(0.0, 36.8125, -66.0, 0.0) | mat2(1.0, 3.5, 5.0, 0.0) | mat2(1.0, 0.0, 11.0, 1.0) | mat2(0.0, -8.25, 2.0, 1.0) | mat2(0.0, -20.125, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_mat2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 0.0, -2.0) | mat2(-32.0, 64.0, 0.0, 0.0) | mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, -32.0, 64.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_mat2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) ];
+ output mat2 out0 = [ mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-32.0, 64.0, 1.0, 0.0) | mat2(1.0, 1.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, 0.0, 1.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_mat2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ 36.8125 | -8.25 | 1.0 | -0.5 | 2.0 | -20.125 | 0.0 | 3.5 ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 36.8125) | mat2(0.0, 1.0, 0.0, -8.25) | mat2(0.0, 0.0, 0.0, 1.0) | mat2(1.0, 1.0, 1.0, -0.5) | mat2(1.0, 0.0, 0.0, 2.0) | mat2(0.0, 1.0, 0.0, -20.125) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(0.0, 0.0, 0.0, 3.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_mat2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input float in1 = [ -0.5 | -20.125 | 0.0 | 36.8125 | 3.5 | -8.25 | 2.0 | 1.0 ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 1.125, -0.5) | mat2(-0.5, -2.25, -4.875, -20.125) | mat2(-0.5, -2.25, -4.875, 0.0) | mat2(1.0, 1.25, 1.125, 36.8125) | mat2(0.0, 0.5, 0.75, 3.5) | mat2(-32.0, 64.0, -51.0, -8.25) | mat2(0.0, 0.5, 0.75, 2.0) | mat2(-0.75, -0.0322580645161, 0.0526315789474, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | -192 | 2 | 0 | -66 | 255 | 5 | 1 | -12 | 11 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(1, 1) ];
+ input int in2 = [ 2 | 1 | -12 | 0 | 11 | 8 | 255 | -192 | 5 | -66 ];
+ output mat2 out0 = [ mat2(8.0, 0.0, -2.0, 2.0) | mat2(-192.0, 0.0, 0.0, 1.0) | mat2(2.0, -32.0, 64.0, -12.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(-66.0, 0.0, 0.0, 11.0) | mat2(255.0, -32.0, 64.0, 8.0) | mat2(5.0, 0.0, 0.0, 255.0) | mat2(1.0, 0.0, -2.0, -192.0) | mat2(-12.0, 1.0, 1.0, 5.0) | mat2(11.0, 1.0, 1.0, -66.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | true | false | false ];
+ input float in1 = [ 1.0 | -0.5 | -20.125 | 36.8125 | 2.0 | 0.0 | -8.25 | 3.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, -2) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 0.0, 0.0) | mat2(1.0, -0.5, 0.0, 0.0) | mat2(1.0, -20.125, 1.0, 1.0) | mat2(0.0, 36.8125, 0.0, 0.0) | mat2(0.0, 2.0, 1.0, 1.0) | mat2(1.0, 0.0, 0.0, -2.0) | mat2(0.0, -8.25, -32.0, 64.0) | mat2(0.0, 3.5, 0.0, -2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_mat2
+ version 300 es
+ values
+ {
+ input float in0 = [ 36.8125 | 2.0 | -0.5 | 0.0 | -20.125 | 1.0 | 3.5 | -8.25 ];
+ input uvec3 in1 = [ uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(32, 64, 51) | uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) ];
+ output mat2 out0 = [ mat2(36.8125, 1.0, 1.0, 1.0) | mat2(2.0, 0.0, 2.0, 4.0) | mat2(-0.5, 0.0, 2.0, 4.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(-20.125, 32.0, 64.0, 51.0) | mat2(1.0, 0.0, 0.0, 0.0) | mat2(3.5, 0.0, 0.0, 0.0) | mat2(-8.25, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -66 | 5 | -192 | 11 | 0 | 8 | 2 | -12 | 255 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(32, 64) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(0, 0) | uvec2(0, 0) | uvec2(32, 64) ];
+ input bool in2 = [ true | false | true | false | false | false | true | true | true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 2.0, 1.0) | mat2(-66.0, 32.0, 64.0, 0.0) | mat2(5.0, 1.0, 1.0, 1.0) | mat2(-192.0, 0.0, 0.0, 0.0) | mat2(11.0, 0.0, 0.0, 0.0) | mat2(0.0, 1.0, 1.0, 0.0) | mat2(8.0, 0.0, 2.0, 1.0) | mat2(2.0, 0.0, 0.0, 1.0) | mat2(-12.0, 0.0, 0.0, 1.0) | mat2(255.0, 32.0, 64.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in1 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 1.25, 1.125, -32.0, 64.0, -51.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25, -4.875) | mat2x3(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75) | mat2x3(-32.0, 64.0, -51.0, 1.0, 1.25, 1.125) | mat2x3(0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_bvec3_to_mat2x3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ input bvec3 in1 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(1.0, 1.0, 1.0, 1.0, 0.0, 0.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_float_float_to_mat2x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -8.25 | -20.125 | 36.8125 | -0.5 | 2.0 | 3.5 | 0.0 ];
+ input float in1 = [ -0.5 | -20.125 | 36.8125 | -8.25 | 2.0 | 1.0 | 3.5 | 0.0 ];
+ input float in2 = [ 3.5 | 1.0 | 36.8125 | -20.125 | -8.25 | -0.5 | 2.0 | 0.0 ];
+ input float in3 = [ 1.0 | -8.25 | 0.0 | -20.125 | 2.0 | 3.5 | -0.5 | 36.8125 ];
+ input float in4 = [ 1.0 | 0.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 ];
+ input float in5 = [ 2.0 | -20.125 | -8.25 | -0.5 | 3.5 | 1.0 | 36.8125 | 0.0 ];
+ output mat2x3 out0 = [ mat2x3(1.0, -0.5, 3.5, 1.0, 1.0, 2.0) | mat2x3(-8.25, -20.125, 1.0, -8.25, 0.0, -20.125) | mat2x3(-20.125, 36.8125, 36.8125, 0.0, 3.5, -8.25) | mat2x3(36.8125, -8.25, -20.125, -20.125, 2.0, -0.5) | mat2x3(-0.5, 2.0, -8.25, 2.0, -8.25, 3.5) | mat2x3(2.0, 1.0, -0.5, 3.5, -20.125, 1.0) | mat2x3(3.5, 3.5, 2.0, -0.5, -0.5, 36.8125) | mat2x3(0.0, 0.0, 0.0, 36.8125, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_int_int_to_mat2x3
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | 8 | -192 | 0 | 5 | -12 | 1 | 255 | -66 | 11 ];
+ input int in1 = [ 1 | -192 | 8 | 0 | -12 | 2 | 11 | 255 | -66 | 5 ];
+ input int in2 = [ -192 | 2 | -66 | 8 | 11 | 255 | 0 | 5 | -12 | 1 ];
+ input int in3 = [ 2 | 11 | 255 | 0 | -66 | -12 | 5 | -192 | 8 | 1 ];
+ input int in4 = [ 8 | 0 | -12 | -192 | 2 | -66 | 1 | 255 | 5 | 11 ];
+ input int in5 = [ 0 | 11 | 5 | 8 | -12 | 255 | -192 | 2 | 1 | -66 ];
+ output mat2x3 out0 = [ mat2x3(2.0, 1.0, -192.0, 2.0, 8.0, 0.0) | mat2x3(8.0, -192.0, 2.0, 11.0, 0.0, 11.0) | mat2x3(-192.0, 8.0, -66.0, 255.0, -12.0, 5.0) | mat2x3(0.0, 0.0, 8.0, 0.0, -192.0, 8.0) | mat2x3(5.0, -12.0, 11.0, -66.0, 2.0, -12.0) | mat2x3(-12.0, 2.0, 255.0, -12.0, -66.0, 255.0) | mat2x3(1.0, 11.0, 0.0, 5.0, 1.0, -192.0) | mat2x3(255.0, 255.0, 5.0, -192.0, 255.0, 2.0) | mat2x3(-66.0, -66.0, -12.0, 8.0, 5.0, 1.0) | mat2x3(11.0, 5.0, 1.0, 1.0, 11.0, -66.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_bool_bool_to_mat2x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ true | false ];
+ input bool in4 = [ true | false ];
+ input bool in5 = [ true | false ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(0.0, 1.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_float_int_to_mat2x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | true | false ];
+ input float in1 = [ 0.0 | -8.25 | 2.0 | -20.125 | 3.5 | 0.0 | -0.5 | 36.8125 | 1.0 | 1.0 ];
+ input int in2 = [ -66 | -12 | 2 | 8 | 255 | 11 | -192 | 1 | 5 | 0 ];
+ input bool in3 = [ true | false | true | false | false | true | true | false | true | false ];
+ input float in4 = [ 1.0 | 0.0 | -8.25 | 1.0 | 3.5 | -20.125 | -0.5 | 0.0 | 2.0 | 36.8125 ];
+ input int in5 = [ 255 | -192 | 1 | 2 | -12 | -66 | 8 | 0 | 11 | 5 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, -66.0, 1.0, 1.0, 255.0) | mat2x3(1.0, -8.25, -12.0, 0.0, 0.0, -192.0) | mat2x3(0.0, 2.0, 2.0, 1.0, -8.25, 1.0) | mat2x3(1.0, -20.125, 8.0, 0.0, 1.0, 2.0) | mat2x3(0.0, 3.5, 255.0, 0.0, 3.5, -12.0) | mat2x3(1.0, 0.0, 11.0, 1.0, -20.125, -66.0) | mat2x3(0.0, -0.5, -192.0, 1.0, -0.5, 8.0) | mat2x3(1.0, 36.8125, 1.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 1.0, 5.0, 1.0, 2.0, 11.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 36.8125, 5.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_ivec3_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, 0, 0) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 1.25, 1.125, 1.0, 1.0, 1.0) | mat2x3(-0.5, -2.25, -4.875, -32.0, 64.0, -51.0) | mat2x3(-32.0, 64.0, -51.0, 0.0, -2.0, -4.0) | mat2x3(0.0, 0.5, 0.75, 0.0, 0.0, 0.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec4_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output mat2x3 out0 = [ mat2x3(-32.0, 64.0, 1.0, 0.0, 0.0, 1.0) | mat2x3(0.0, 0.5, 0.0, 1.0, 0.0, 0.0) | mat2x3(-0.5, -2.25, 0.0, 0.0, 0.0, 1.0) | mat2x3(1.0, 1.25, 1.0, 1.0, 1.0, 1.0) | mat2x3(-0.75, -0.0322580645161, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_ivec2_to_mat2x3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ 1.0 | -8.25 | 36.8125 | 2.0 | 3.5 | -0.5 | -20.125 | 0.0 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(0.0, 0.0, 0.0, -8.25, 0.0, 0.0) | mat2x3(1.0, 1.0, 1.0, 36.8125, -32.0, 64.0) | mat2x3(1.0, 0.0, 0.0, 2.0, 0.0, -2.0) | mat2x3(0.0, 0.0, 0.0, 3.5, 1.0, 1.0) | mat2x3(0.0, 1.0, 0.0, -0.5, 0.0, -2.0) | mat2x3(1.0, 0.0, 0.0, -20.125, 0.0, 0.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_bvec2_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 36.8125 | 3.5 | -0.5 | -8.25 | 2.0 | 1.0 | -20.125 ];
+ input bvec2 in2 = [ bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.5, 0.75, 0.0, 0.0, 0.0) | mat2x3(-0.5, -2.25, -4.875, 36.8125, 0.0, 1.0) | mat2x3(0.0, 0.5, 0.75, 3.5, 1.0, 0.0) | mat2x3(1.0, 1.25, 1.125, -0.5, 0.0, 1.0) | mat2x3(-0.5, -2.25, -4.875, -8.25, 0.0, 0.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, 2.0, 1.0, 0.0) | mat2x3(-32.0, 64.0, -51.0, 1.0, 1.0, 1.0) | mat2x3(1.0, 1.25, 1.125, -20.125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec2_to_mat2x4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) ];
+ input vec3 in1 = [ vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec2 in2 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ output mat2x4 out0 = [ mat2x4(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75, -0.75, -0.0322580645161) | mat2x4(-0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25, -4.875, -32.0, 64.0) | mat2x4(0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25) | mat2x4(1.0, 1.25, 1.125, -32.0, 64.0, -51.0, 0.0, 0.5) | mat2x4(-32.0, 64.0, -51.0, 1.0, 1.25, 1.125, -0.5, -2.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec2_to_mat2x4
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) ];
+ output mat2x4 out0 = [ mat2x4(0.0, -2.0, -4.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -2.0) | mat2x4(1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 1.0, 1.0) | mat2x4(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 0.0, 0.0) | mat2x4(-32.0, 64.0, -51.0, 0.0, 0.0, 0.0, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_to_mat2x4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in2 = [ -8.25 | -0.5 | 3.5 | 36.8125 | 0.0 | 0.0 | 2.0 | -20.125 | 1.0 | 1.0 ];
+ input float in3 = [ 1.0 | 2.0 | -0.5 | 3.5 | 36.8125 | -8.25 | 1.0 | 0.0 | 0.0 | -20.125 ];
+ input int in4 = [ 255 | 8 | 11 | -12 | -192 | 0 | 2 | 1 | -66 | 5 ];
+ input bool in5 = [ true | false | false | true | false | true | true | false | true | false ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.5, 1.0, 1.0, -8.25, 1.0, 255.0, 1.0) | mat2x4(-32.0, 64.0, 0.0, -2.0, -0.5, 2.0, 8.0, 0.0) | mat2x4(-0.5, -2.25, -32.0, 64.0, 3.5, -0.5, 11.0, 0.0) | mat2x4(0.0, 0.5, 0.0, -2.0, 36.8125, 3.5, -12.0, 1.0) | mat2x4(-32.0, 64.0, 0.0, 0.0, 0.0, 36.8125, -192.0, 0.0) | mat2x4(1.0, 1.25, 0.0, 0.0, 0.0, -8.25, 0.0, 1.0) | mat2x4(-0.75, -0.0322580645161, -32.0, 64.0, 2.0, 1.0, 2.0, 1.0) | mat2x4(1.0, 1.25, 0.0, 0.0, -20.125, 0.0, 1.0, 0.0) | mat2x4(-0.5, -2.25, 0.0, 0.0, 1.0, 0.0, -66.0, 1.0) | mat2x4(-0.75, -0.0322580645161, 1.0, 1.0, 1.0, -20.125, 5.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_to_mat2x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | true | true | false | false | false | true ];
+ input float in1 = [ 0.0 | -0.5 | -20.125 | -8.25 | 0.0 | 2.0 | 3.5 | 1.0 | 1.0 | 36.8125 ];
+ input int in2 = [ 2 | 1 | 255 | 8 | -66 | 0 | -12 | 5 | -192 | 11 ];
+ input vec2 in3 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input bool in4 = [ true | false | false | true | false | false | true | true | true | false ];
+ input bvec2 in5 = [ bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 2.0, -32.0, 64.0, 1.0, 1.0, 0.0) | mat2x4(1.0, -0.5, 1.0, -0.5, -2.25, 0.0, 1.0, 1.0) | mat2x4(0.0, -20.125, 255.0, 1.0, 1.25, 0.0, 0.0, 1.0) | mat2x4(1.0, -8.25, 8.0, -0.75, -0.0322580645161, 1.0, 1.0, 1.0) | mat2x4(1.0, 0.0, -66.0, 0.0, 0.5, 0.0, 0.0, 0.0) | mat2x4(1.0, 2.0, 0.0, 1.0, 1.25, 0.0, 0.0, 1.0) | mat2x4(0.0, 3.5, -12.0, -32.0, 64.0, 1.0, 0.0, 0.0) | mat2x4(0.0, 1.0, 5.0, -0.5, -2.25, 1.0, 0.0, 0.0) | mat2x4(0.0, 1.0, -192.0, 0.0, 0.5, 1.0, 0.0, 0.0) | mat2x4(1.0, 36.8125, 11.0, -0.75, -0.0322580645161, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_to_mat2x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | false | false | true | true ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) ];
+ input int in2 = [ 8 | 1 | 5 | -66 | -192 | 11 | 255 | 0 | -12 | 2 ];
+ input vec4 in3 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 1.0, 1.0, 8.0, 0.0, 0.5, 0.75, 0.825) | mat2x4(1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.75, 0.825) | mat2x4(1.0, 1.0, 0.0, 5.0, -32.0, 64.0, -51.0, 24.0) | mat2x4(0.0, 0.0, 0.0, -66.0, 1.0, 1.25, 1.125, 1.75) | mat2x4(0.0, 1.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0) | mat2x4(0.0, 1.0, 0.0, 11.0, 1.0, 1.25, 1.125, 1.75) | mat2x4(0.0, 0.0, 1.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat2x4(0.0, 0.0, 0.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat2x4(1.0, 0.0, 1.0, -12.0, -0.5, -2.25, -4.875, 9.0) | mat2x4(1.0, 0.0, 0.0, 2.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_to_mat2x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 2.0 | -8.25 | -20.125 | 36.8125 | 1.0 | -0.5 ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) ];
+ input ivec2 in2 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) ];
+ input bool in3 = [ true | true | false | true | false | false | false | true ];
+ output mat2x4 out0 = [ mat2x4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0) | mat2x4(3.5, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, 1.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0) | mat2x4(-8.25, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x4(-20.125, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(36.8125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat2x4(-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec3 in1 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ output mat3x2 out0 = [ mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25, 1.125) | mat3x2(-0.5, -2.25, -4.875, -0.75, -0.0322580645161, 0.0526315789474) | mat3x2(0.0, 0.5, 0.75, -32.0, 64.0, -51.0) | mat3x2(-32.0, 64.0, -51.0, -0.5, -2.25, -4.875) | mat3x2(1.0, 1.25, 1.125, 0.0, 0.5, 0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_bvec3_to_mat3x2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ input bvec3 in1 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3x2(1.0, 1.0, 1.0, 0.0, 1.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_float_float_to_mat3x2
+ version 300 es
+ values
+ {
+ input float in0 = [ -8.25 | 36.8125 | -20.125 | -0.5 | 3.5 | 1.0 | 2.0 | 0.0 ];
+ input float in1 = [ 2.0 | 3.5 | -20.125 | 36.8125 | 1.0 | 0.0 | -8.25 | -0.5 ];
+ input float in2 = [ -0.5 | 2.0 | 1.0 | 0.0 | -8.25 | 36.8125 | -20.125 | 3.5 ];
+ input float in3 = [ 36.8125 | 0.0 | 1.0 | -0.5 | 2.0 | 3.5 | -20.125 | -8.25 ];
+ input float in4 = [ 36.8125 | 2.0 | 0.0 | -0.5 | 3.5 | -20.125 | -8.25 | 1.0 ];
+ input float in5 = [ 0.0 | 36.8125 | -20.125 | -0.5 | 3.5 | 2.0 | 1.0 | -8.25 ];
+ output mat3x2 out0 = [ mat3x2(-8.25, 2.0, -0.5, 36.8125, 36.8125, 0.0) | mat3x2(36.8125, 3.5, 2.0, 0.0, 2.0, 36.8125) | mat3x2(-20.125, -20.125, 1.0, 1.0, 0.0, -20.125) | mat3x2(-0.5, 36.8125, 0.0, -0.5, -0.5, -0.5) | mat3x2(3.5, 1.0, -8.25, 2.0, 3.5, 3.5) | mat3x2(1.0, 0.0, 36.8125, 3.5, -20.125, 2.0) | mat3x2(2.0, -8.25, -20.125, -20.125, -8.25, 1.0) | mat3x2(0.0, -0.5, 3.5, -8.25, 1.0, -8.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_int_int_to_mat3x2
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | -192 | 2 | 11 | 255 | -66 | 5 | -12 | 1 | 0 ];
+ input int in1 = [ 1 | 2 | -12 | 5 | 0 | 255 | 8 | 11 | -192 | -66 ];
+ input int in2 = [ -12 | 11 | 2 | 1 | 8 | -66 | -192 | 5 | 255 | 0 ];
+ input int in3 = [ -192 | 0 | -12 | 11 | 1 | -66 | 8 | 255 | 2 | 5 ];
+ input int in4 = [ -12 | 5 | 0 | -66 | 255 | 8 | -192 | 11 | 2 | 1 ];
+ input int in5 = [ -66 | -12 | 8 | 2 | 255 | 0 | -192 | 11 | 1 | 5 ];
+ output mat3x2 out0 = [ mat3x2(8.0, 1.0, -12.0, -192.0, -12.0, -66.0) | mat3x2(-192.0, 2.0, 11.0, 0.0, 5.0, -12.0) | mat3x2(2.0, -12.0, 2.0, -12.0, 0.0, 8.0) | mat3x2(11.0, 5.0, 1.0, 11.0, -66.0, 2.0) | mat3x2(255.0, 0.0, 8.0, 1.0, 255.0, 255.0) | mat3x2(-66.0, 255.0, -66.0, -66.0, 8.0, 0.0) | mat3x2(5.0, 8.0, -192.0, 8.0, -192.0, -192.0) | mat3x2(-12.0, 11.0, 5.0, 255.0, 11.0, 11.0) | mat3x2(1.0, -192.0, 255.0, 2.0, 2.0, 1.0) | mat3x2(0.0, -66.0, 0.0, 5.0, 1.0, 5.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_bool_bool_to_mat3x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ input bool in4 = [ false | true ];
+ input bool in5 = [ false | true ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 1.0, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_float_int_to_mat3x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false | true | false | true | false | false ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | 0.0 | 1.0 | -8.25 | 1.0 | 2.0 | 36.8125 | -0.5 ];
+ input int in2 = [ 255 | -66 | 8 | -192 | 5 | 11 | 1 | 2 | 0 | -12 ];
+ input bool in3 = [ true | false | false | true | false | true | true | false | false | true ];
+ input float in4 = [ 0.0 | -20.125 | 1.0 | -8.25 | 0.0 | -0.5 | 2.0 | 3.5 | 1.0 | 36.8125 ];
+ input int in5 = [ -192 | 8 | 2 | 255 | -66 | -12 | 11 | 0 | 5 | 1 ];
+ output mat3x2 out0 = [ mat3x2(1.0, -20.125, 255.0, 1.0, 0.0, -192.0) | mat3x2(0.0, 0.0, -66.0, 0.0, -20.125, 8.0) | mat3x2(1.0, 3.5, 8.0, 0.0, 1.0, 2.0) | mat3x2(1.0, 0.0, -192.0, 1.0, -8.25, 255.0) | mat3x2(0.0, 1.0, 5.0, 0.0, 0.0, -66.0) | mat3x2(1.0, -8.25, 11.0, 1.0, -0.5, -12.0) | mat3x2(0.0, 1.0, 1.0, 1.0, 2.0, 11.0) | mat3x2(1.0, 2.0, 2.0, 0.0, 3.5, 0.0) | mat3x2(0.0, 36.8125, 0.0, 0.0, 1.0, 5.0) | mat3x2(0.0, -0.5, -12.0, 1.0, 36.8125, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_ivec3_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.5, 0.75, 1.0, 1.0, 1.0) | mat3x2(1.0, 1.25, 1.125, 0.0, 0.0, 0.0) | mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 0.0, -2.0, -4.0) | mat3x2(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3x2(-0.5, -2.25, -4.875, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec4_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.5, 1.0, 1.0, 1.0, 1.0) | mat3x2(-0.75, -0.0322580645161, 0.0, 0.0, 0.0, 1.0) | mat3x2(-32.0, 64.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(-0.5, -2.25, 1.0, 0.0, 0.0, 1.0) | mat3x2(1.0, 1.25, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_ivec2_to_mat3x2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ input float in1 = [ -8.25 | 1.0 | 2.0 | -0.5 | -20.125 | 0.0 | 36.8125 | 3.5 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, -8.25, 1.0, 1.0) | mat3x2(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) | mat3x2(0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, -0.5, 0.0, -2.0) | mat3x2(0.0, 1.0, 0.0, -20.125, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 0.0, 36.8125, 0.0, -2.0) | mat3x2(1.0, 0.0, 0.0, 3.5, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_bvec2_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input float in1 = [ -8.25 | 36.8125 | -0.5 | 3.5 | 2.0 | -20.125 | 0.0 | 1.0 ];
+ input bvec2 in2 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 1.25, 1.125, -8.25, 1.0, 0.0) | mat3x2(1.0, 1.25, 1.125, 36.8125, 0.0, 0.0) | mat3x2(-0.5, -2.25, -4.875, -0.5, 1.0, 1.0) | mat3x2(-0.5, -2.25, -4.875, 3.5, 0.0, 0.0) | mat3x2(-32.0, 64.0, -51.0, 2.0, 0.0, 1.0) | mat3x2(0.0, 0.5, 0.75, -20.125, 0.0, 1.0) | mat3x2(0.0, 0.5, 0.75, 0.0, 1.0, 0.0) | mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec3_to_mat3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input vec3 in1 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in2 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 1.125, -0.75, -0.0322580645161, 0.0526315789474, -0.75, -0.0322580645161, 0.0526315789474) | mat3(-0.5, -2.25, -4.875, 1.0, 1.25, 1.125, -32.0, 64.0, -51.0) | mat3(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0, -0.5, -2.25, -4.875) | mat3(0.0, 0.5, 0.75, -0.5, -2.25, -4.875, 1.0, 1.25, 1.125) | mat3(-0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.5, 0.75, 0.0, 0.5, 0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec3_to_mat3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(1, 1, 1) ];
+ input ivec3 in2 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) | ivec3(0, 0, 0) ];
+ output mat3 out0 = [ mat3(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3(0.0, -2.0, -4.0, 0.0, -2.0, -4.0, 0.0, 0.0, 0.0) | mat3(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(-32.0, 64.0, -51.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0) | mat3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_bool_to_mat3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(-32, 64) ];
+ input float in2 = [ -0.5 | 3.5 | 0.0 | -20.125 | 1.0 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ input float in3 = [ 3.5 | 0.0 | -20.125 | 36.8125 | 2.0 | -8.25 | -0.5 | 1.0 | 0.0 | 1.0 ];
+ input int in4 = [ 0 | 11 | 5 | -192 | 8 | -66 | 1 | 2 | 255 | -12 ];
+ input bool in5 = [ true | true | true | false | true | false | false | false | true | false ];
+ input bool in6 = [ false | false | true | false | false | false | true | true | true | true ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 0.0, 0.0, -0.5, 3.5, 0.0, 1.0, 0.0) | mat3(-0.5, -2.25, 0.0, -2.0, 3.5, 0.0, 11.0, 1.0, 0.0) | mat3(0.0, 0.5, 1.0, 1.0, 0.0, -20.125, 5.0, 1.0, 1.0) | mat3(-0.75, -0.0322580645161, 0.0, -2.0, -20.125, 36.8125, -192.0, 0.0, 0.0) | mat3(-32.0, 64.0, 0.0, 0.0, 1.0, 2.0, 8.0, 1.0, 0.0) | mat3(-0.75, -0.0322580645161, 0.0, 0.0, -8.25, -8.25, -66.0, 0.0, 0.0) | mat3(-0.5, -2.25, 1.0, 1.0, 0.0, -0.5, 1.0, 0.0, 1.0) | mat3(1.0, 1.25, -32.0, 64.0, 1.0, 1.0, 2.0, 0.0, 1.0) | mat3(0.0, 0.5, 0.0, 0.0, 2.0, 0.0, 255.0, 1.0, 1.0) | mat3(-32.0, 64.0, -32.0, 64.0, 36.8125, 1.0, -12.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_float_to_mat3
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | true | true | true | true | false | false | false | false ];
+ input float in1 = [ -8.25 | 1.0 | -0.5 | 36.8125 | 0.0 | 3.5 | -20.125 | 1.0 | 0.0 | 2.0 ];
+ input int in2 = [ 8 | -66 | 5 | 1 | 0 | 2 | -12 | -192 | 11 | 255 ];
+ input vec2 in3 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input bool in4 = [ true | false | true | false | false | true | true | false | true | false ];
+ input bvec2 in5 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) ];
+ input float in6 = [ -0.5 | 1.0 | 1.0 | 0.0 | 36.8125 | 2.0 | 0.0 | 3.5 | -20.125 | -8.25 ];
+ output mat3 out0 = [ mat3(0.0, -8.25, 8.0, 0.0, 0.5, 1.0, 0.0, 1.0, -0.5) | mat3(1.0, 1.0, -66.0, -32.0, 64.0, 0.0, 0.0, 0.0, 1.0) | mat3(1.0, -0.5, 5.0, 1.0, 1.25, 1.0, 1.0, 0.0, 1.0) | mat3(1.0, 36.8125, 1.0, -32.0, 64.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, -0.5, -2.25, 0.0, 1.0, 1.0, 36.8125) | mat3(1.0, 3.5, 2.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0, 2.0) | mat3(0.0, -20.125, -12.0, -0.5, -2.25, 1.0, 1.0, 0.0, 0.0) | mat3(0.0, 1.0, -192.0, 0.0, 0.5, 0.0, 0.0, 0.0, 3.5) | mat3(0.0, 0.0, 11.0, 1.0, 1.25, 1.0, 0.0, 1.0, -20.125) | mat3(0.0, 2.0, 255.0, -0.75, -0.0322580645161, 0.0, 1.0, 1.0, -8.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_bool_to_mat3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false | false | true | false | false | true ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in2 = [ -192 | 2 | 0 | 5 | 1 | -66 | 11 | -12 | 8 | 255 ];
+ input vec4 in3 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ input bool in4 = [ false | true | false | true | false | false | false | true | true | true ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, -192.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(0.0, 0.0, 1.0, 2.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 1.0, 1.0, 5.0, -32.0, 64.0, -51.0, 24.0, 1.0) | mat3(0.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 0.0, 0.0, -66.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 0.0, 1.0, 11.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 1.0, 0.0, -12.0, -0.5, -2.25, -4.875, 9.0, 1.0) | mat3(0.0, 1.0, 0.0, 8.0, -0.5, -2.25, -4.875, 9.0, 1.0) | mat3(1.0, 0.0, 0.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_bool_to_mat3
+ version 300 es
+ values
+ {
+ input float in0 = [ -8.25 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -20.125 | 0.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, true) ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) ];
+ input bool in3 = [ false | true | false | true | true | false | true | false ];
+ input bool in4 = [ true | false | false | false | true | true | false | true ];
+ output mat3 out0 = [ mat3(-8.25, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat3(2.0, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, 1.0, 0.0) | mat3(36.8125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3(3.5, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, 1.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat3(-0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat3(-20.125, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0, 0.0) | mat3(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_to_mat3x4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat3x4 out0 = [ mat3x4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0) | mat3x4(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat3x4(-32.0, 64.0, -51.0, 24.0, 0.0, 0.5, 0.75, 0.825, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat3x4(-0.5, -2.25, -4.875, 9.0, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat3x4(0.0, 0.5, 0.75, 0.825, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_to_mat3x4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) ];
+ input ivec4 in1 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in2 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat3x4 out0 = [ mat3x4(0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(-32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_float_int_int_bool_bool_bool_to_mat3x4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-0.5, -2.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in2 = [ 1.0 | -8.25 | 2.0 | 3.5 | -20.125 | 36.8125 | 0.0 | 1.0 | -0.5 | 0.0 ];
+ input float in3 = [ -0.5 | 36.8125 | 1.0 | 1.0 | 0.0 | 3.5 | 2.0 | 0.0 | -8.25 | -20.125 ];
+ input float in4 = [ -8.25 | 1.0 | 1.0 | 0.0 | 2.0 | 36.8125 | 0.0 | -20.125 | 3.5 | -0.5 ];
+ input int in5 = [ 11 | 2 | 8 | 5 | 0 | -192 | 1 | -12 | 255 | -66 ];
+ input int in6 = [ -12 | 5 | 8 | 1 | 0 | 255 | 11 | -192 | -66 | 2 ];
+ input bool in7 = [ true | true | true | false | false | false | true | false | true | false ];
+ input bool in8 = [ true | true | true | false | true | false | true | false | false | false ];
+ input bool in9 = [ true | false | true | false | true | true | false | false | false | true ];
+ output mat3x4 out0 = [ mat3x4(1.0, 1.25, 0.0, 0.0, 1.0, -0.5, -8.25, 11.0, -12.0, 1.0, 1.0, 1.0) | mat3x4(0.0, 0.5, 0.0, 0.0, -8.25, 36.8125, 1.0, 2.0, 5.0, 1.0, 1.0, 0.0) | mat3x4(0.0, 0.5, -32.0, 64.0, 2.0, 1.0, 1.0, 8.0, 8.0, 1.0, 1.0, 1.0) | mat3x4(-32.0, 64.0, 1.0, 1.0, 3.5, 1.0, 0.0, 5.0, 1.0, 0.0, 0.0, 0.0) | mat3x4(-32.0, 64.0, 1.0, 1.0, -20.125, 0.0, 2.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat3x4(-0.75, -0.0322580645161, -32.0, 64.0, 36.8125, 3.5, 36.8125, -192.0, 255.0, 0.0, 0.0, 1.0) | mat3x4(1.0, 1.25, 0.0, 0.0, 0.0, 2.0, 0.0, 1.0, 11.0, 1.0, 1.0, 0.0) | mat3x4(-0.75, -0.0322580645161, 0.0, -2.0, 1.0, 0.0, -20.125, -12.0, -192.0, 0.0, 0.0, 0.0) | mat3x4(-0.5, -2.25, 0.0, 0.0, -0.5, -8.25, 3.5, 255.0, -66.0, 1.0, 0.0, 0.0) | mat3x4(-0.5, -2.25, 0.0, -2.0, 0.0, -20.125, -0.5, -66.0, 2.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec3_bool_bvec3_float_bool_to_mat3x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | false | true | true | true | true | false | false | false | true ];
+ input float in1 = [ 36.8125 | -8.25 | 1.0 | 0.0 | 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -20.125 ];
+ input int in2 = [ -66 | -192 | 255 | 8 | 0 | -12 | 5 | 2 | 11 | 1 ];
+ input vec3 in3 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) ];
+ input bool in4 = [ false | true | true | true | false | false | true | true | false | false ];
+ input bvec3 in5 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in6 = [ -8.25 | 1.0 | -0.5 | 36.8125 | 0.0 | 2.0 | -20.125 | 1.0 | 0.0 | 3.5 ];
+ input bool in7 = [ true | false | false | true | true | false | true | false | false | true ];
+ output mat3x4 out0 = [ mat3x4(0.0, 36.8125, -66.0, -0.75, -0.0322580645161, 0.0526315789474, 0.0, 1.0, 0.0, 0.0, -8.25, 1.0) | mat3x4(0.0, -8.25, -192.0, -32.0, 64.0, -51.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(1.0, 1.0, 255.0, 0.0, 0.5, 0.75, 1.0, 0.0, 1.0, 0.0, -0.5, 0.0) | mat3x4(1.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 36.8125, 1.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0) | mat3x4(1.0, 1.0, -12.0, -32.0, 64.0, -51.0, 0.0, 1.0, 1.0, 1.0, 2.0, 0.0) | mat3x4(0.0, 2.0, 5.0, 1.0, 1.25, 1.125, 1.0, 1.0, 1.0, 1.0, -20.125, 1.0) | mat3x4(0.0, 3.5, 2.0, 1.0, 1.25, 1.125, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.0, -0.5, 11.0, -0.5, -2.25, -4.875, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, -20.125, 1.0, -0.5, -2.25, -4.875, 0.0, 0.0, 0.0, 0.0, 3.5, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5, in6, in7);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4_int_vec4_bool_float_to_mat3x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | true | true | false | false | false | true | false | true ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) ];
+ input int in2 = [ 255 | 2 | -192 | -12 | 11 | 1 | 0 | -66 | 8 | 5 ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input bool in4 = [ true | true | true | false | false | false | true | true | false | false ];
+ input float in5 = [ 36.8125 | 2.0 | -8.25 | 0.0 | 1.0 | 1.0 | -0.5 | 3.5 | 0.0 | -20.125 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 255.0, -0.5, -2.25, -4.875, 9.0, 1.0, 36.8125) | mat3x4(1.0, 1.0, 0.0, 0.0, 1.0, 2.0, 1.0, 1.25, 1.125, 1.75, 1.0, 2.0) | mat3x4(1.0, 0.0, 1.0, 0.0, 0.0, -192.0, 1.0, 1.25, 1.125, 1.75, 1.0, -8.25) | mat3x4(1.0, 0.0, 0.0, 0.0, 1.0, -12.0, 0.0, 0.5, 0.75, 0.825, 0.0, 0.0) | mat3x4(0.0, 1.0, 1.0, 1.0, 1.0, 11.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 1.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 1.0) | mat3x4(0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, -0.5) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.5, 0.75, 0.825, 1.0, 3.5) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 0.0) | mat3x4(1.0, 1.0, 0.0, 0.0, 1.0, 5.0, -0.5, -2.25, -4.875, 9.0, 0.0, -20.125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec4_bool_bool_int_to_mat3x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 36.8125 | 1.0 | 0.0 | 3.5 | -8.25 | -20.125 | 2.0 | 0.0 | 1.0 | -0.5 ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(false, false, false, false) ];
+ input ivec4 in2 = [ ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) ];
+ input bool in3 = [ true | false | true | true | false | true | true | false | false | false ];
+ input bool in4 = [ true | false | false | true | true | false | false | false | true | true ];
+ input int in5 = [ 1 | 5 | -12 | 8 | -192 | 2 | -66 | 255 | 11 | 0 ];
+ output mat3x4 out0 = [ mat3x4(36.8125, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 5.0) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, 0.0, -12.0) | mat3x4(3.5, 0.0, 0.0, 0.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, 8.0) | mat3x4(-8.25, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -192.0) | mat3x4(-20.125, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 2.0) | mat3x4(2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -66.0) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 255.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 11.0) | mat3x4(-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec2_to_mat4x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input vec3 in1 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input vec2 in2 = [ vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 1.25, 1.125, -32.0, 64.0, -51.0, 1.0, 1.25) | mat4x2(-32.0, 64.0, -51.0, -0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25) | mat4x2(0.0, 0.5, 0.75, -0.5, -2.25, -4.875, -0.75, -0.0322580645161) | mat4x2(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75, -32.0, 64.0) | mat4x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25, 1.125, 0.0, 0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec2_to_mat4x2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec3 in1 = [ ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec2 in2 = [ ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, -2.0, -4.0, -32.0, 64.0) | mat4x2(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.0, -2.0, -4.0, 1.0, 1.0, 1.0, 0.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat4x2(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0, 0.0, -2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_to_mat4x2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in2 = [ 3.5 | -8.25 | 2.0 | 36.8125 | -0.5 | 1.0 | 1.0 | 0.0 | -20.125 | 0.0 ];
+ input float in3 = [ 0.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | 2.0 | 0.0 | -20.125 | 1.0 ];
+ input int in4 = [ -12 | -66 | 11 | 5 | 8 | 255 | -192 | 2 | 1 | 0 ];
+ input bool in5 = [ true | true | false | true | false | true | false | true | false | false ];
+ output mat4x2 out0 = [ mat4x2(-0.5, -2.25, 0.0, -2.0, 3.5, 0.0, -12.0, 1.0) | mat4x2(0.0, 0.5, 0.0, 0.0, -8.25, 36.8125, -66.0, 1.0) | mat4x2(1.0, 1.25, -32.0, 64.0, 2.0, 3.5, 11.0, 0.0) | mat4x2(0.0, 0.5, 1.0, 1.0, 36.8125, 1.0, 5.0, 1.0) | mat4x2(-32.0, 64.0, 1.0, 1.0, -0.5, -0.5, 8.0, 0.0) | mat4x2(-0.75, -0.0322580645161, 0.0, 0.0, 1.0, -8.25, 255.0, 1.0) | mat4x2(-0.75, -0.0322580645161, -32.0, 64.0, 1.0, 2.0, -192.0, 0.0) | mat4x2(-32.0, 64.0, 0.0, 0.0, 0.0, 0.0, 2.0, 1.0) | mat4x2(-0.5, -2.25, 0.0, 0.0, -20.125, -20.125, 1.0, 0.0) | mat4x2(1.0, 1.25, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_to_mat4x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | false | true | true | true | false | false | true | false | true ];
+ input float in1 = [ 36.8125 | -8.25 | 3.5 | 1.0 | 2.0 | -0.5 | 0.0 | 1.0 | -20.125 | 0.0 ];
+ input int in2 = [ -66 | 1 | -192 | 2 | 11 | 0 | 255 | 8 | 5 | -12 ];
+ input vec2 in3 = [ vec2(-0.75, -0.0322580645161) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bool in4 = [ true | false | false | false | false | true | true | true | false | true ];
+ input bvec2 in5 = [ bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 36.8125, -66.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0) | mat4x2(0.0, -8.25, 1.0, -0.75, -0.0322580645161, 0.0, 0.0, 1.0) | mat4x2(1.0, 3.5, -192.0, -32.0, 64.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 1.0, 2.0, 0.0, 0.5, 0.0, 1.0, 1.0) | mat4x2(1.0, 2.0, 11.0, 1.0, 1.25, 0.0, 1.0, 0.0) | mat4x2(0.0, -0.5, 0.0, 1.0, 1.25, 1.0, 0.0, 1.0) | mat4x2(0.0, 0.0, 255.0, -0.5, -2.25, 1.0, 0.0, 0.0) | mat4x2(1.0, 1.0, 8.0, -32.0, 64.0, 1.0, 1.0, 1.0) | mat4x2(0.0, -20.125, 5.0, 0.0, 0.5, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, -12.0, -0.5, -2.25, 1.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_to_mat4x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | false | true | false | true | false | true | true | true | false ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) ];
+ input int in2 = [ -12 | 8 | 2 | 255 | 5 | -192 | 0 | 11 | 1 | -66 ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 1.0, 0.0, -12.0, 1.0, 1.25, 1.125, 1.75) | mat4x2(0.0, 0.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4x2(1.0, 0.0, 0.0, 2.0, -32.0, 64.0, -51.0, 24.0) | mat4x2(0.0, 0.0, 0.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4x2(1.0, 1.0, 0.0, 5.0, -0.5, -2.25, -4.875, 9.0) | mat4x2(0.0, 0.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0) | mat4x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825) | mat4x2(1.0, 0.0, 1.0, 11.0, -32.0, 64.0, -51.0, 24.0) | mat4x2(1.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75) | mat4x2(0.0, 1.0, 1.0, -66.0, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_to_mat4x2
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -8.25 | -20.125 | 3.5 | -0.5 | 2.0 | 36.8125 | 0.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input ivec2 in2 = [ ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ input bool in3 = [ true | true | false | true | true | false | false | false ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 0.0, 1.0, -32.0, 64.0, 1.0) | mat4x2(-8.25, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0) | mat4x2(-20.125, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) | mat4x2(3.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4x2(-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat4x2(2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 0.0) | mat4x2(36.8125, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_to_mat4x3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) ];
+ input vec4 in1 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output mat4x3 out0 = [ mat4x3(-0.5, -2.25, -4.875, 9.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0) | mat4x3(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat4x3(0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat4x3(-0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) | mat4x3(-32.0, 64.0, -51.0, 24.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_to_mat4x3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) ];
+ input ivec4 in2 = [ ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) | mat4x3(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, -2.0, -4.0, 9.0) | mat4x3(0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4x3(-32.0, 64.0, -51.0, 24.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_float_int_int_bool_bool_bool_to_mat4x3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in2 = [ -20.125 | 3.5 | 2.0 | -0.5 | -8.25 | 0.0 | 1.0 | 0.0 | 1.0 | 36.8125 ];
+ input float in3 = [ 0.0 | -8.25 | 36.8125 | 1.0 | 0.0 | -20.125 | 3.5 | 2.0 | -0.5 | 1.0 ];
+ input float in4 = [ 0.0 | 1.0 | 3.5 | -20.125 | 0.0 | 36.8125 | 1.0 | -8.25 | 2.0 | -0.5 ];
+ input int in5 = [ 2 | 8 | 1 | -192 | 0 | -12 | 11 | 255 | 5 | -66 ];
+ input int in6 = [ 2 | -12 | 5 | 8 | 11 | 255 | 0 | -66 | 1 | -192 ];
+ input bool in7 = [ true | true | false | true | false | false | false | true | false | true ];
+ input bool in8 = [ true | false | false | true | true | false | true | true | false | false ];
+ input bool in9 = [ false | true | false | false | false | false | true | true | true | true ];
+ output mat4x3 out0 = [ mat4x3(-0.5, -2.25, 0.0, -2.0, -20.125, 0.0, 0.0, 2.0, 2.0, 1.0, 1.0, 0.0) | mat4x3(0.0, 0.5, -32.0, 64.0, 3.5, -8.25, 1.0, 8.0, -12.0, 1.0, 0.0, 1.0) | mat4x3(0.0, 0.5, 1.0, 1.0, 2.0, 36.8125, 3.5, 1.0, 5.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 1.25, -32.0, 64.0, -0.5, 1.0, -20.125, -192.0, 8.0, 1.0, 1.0, 0.0) | mat4x3(-0.75, -0.0322580645161, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 11.0, 0.0, 1.0, 0.0) | mat4x3(-0.5, -2.25, 0.0, 0.0, 0.0, -20.125, 36.8125, -12.0, 255.0, 0.0, 0.0, 0.0) | mat4x3(-32.0, 64.0, 0.0, 0.0, 1.0, 3.5, 1.0, 11.0, 0.0, 0.0, 1.0, 1.0) | mat4x3(1.0, 1.25, 0.0, -2.0, 0.0, 2.0, -8.25, 255.0, -66.0, 1.0, 1.0, 1.0) | mat4x3(-32.0, 64.0, 0.0, 0.0, 1.0, -0.5, 2.0, 5.0, 1.0, 0.0, 0.0, 1.0) | mat4x3(-0.75, -0.0322580645161, 1.0, 1.0, 36.8125, 1.0, -0.5, -66.0, -192.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec3_bool_bvec3_float_bool_to_mat4x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | true | true | false | false | false ];
+ input float in1 = [ -8.25 | 2.0 | 1.0 | -0.5 | 0.0 | 0.0 | 36.8125 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ 255 | 2 | 11 | 1 | 8 | -192 | 0 | -66 | -12 | 5 ];
+ input vec3 in3 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input bool in4 = [ true | true | false | false | true | false | false | false | true | true ];
+ input bvec3 in5 = [ bvec3(false, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(true, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in6 = [ 1.0 | 0.0 | -0.5 | 36.8125 | 1.0 | -20.125 | 2.0 | 0.0 | -8.25 | 3.5 ];
+ input bool in7 = [ true | true | false | false | false | false | true | true | false | true ];
+ output mat4x3 out0 = [ mat4x3(1.0, -8.25, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat4x3(1.0, 2.0, 2.0, 0.0, 0.5, 0.75, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0) | mat4x3(0.0, 1.0, 11.0, 0.0, 0.5, 0.75, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0) | mat4x3(0.0, -0.5, 1.0, -32.0, 64.0, -51.0, 0.0, 0.0, 1.0, 0.0, 36.8125, 0.0) | mat4x3(1.0, 0.0, 8.0, -0.5, -2.25, -4.875, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0) | mat4x3(1.0, 0.0, -192.0, 1.0, 1.25, 1.125, 0.0, 1.0, 0.0, 0.0, -20.125, 0.0) | mat4x3(1.0, 36.8125, 0.0, -32.0, 64.0, -51.0, 0.0, 1.0, 1.0, 1.0, 2.0, 1.0) | mat4x3(0.0, -20.125, -66.0, 1.0, 1.25, 1.125, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat4x3(0.0, 3.5, -12.0, -0.5, -2.25, -4.875, 1.0, 0.0, 0.0, 0.0, -8.25, 0.0) | mat4x3(0.0, 1.0, 5.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 3.5, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5, in6, in7);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4_int_vec4_bool_float_to_mat4x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | true | false | false | true | false | false ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, false, false, true) ];
+ input int in2 = [ 5 | 11 | 0 | -192 | -66 | 255 | 1 | -12 | 8 | 2 ];
+ input vec4 in3 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input bool in4 = [ false | true | true | false | true | false | true | true | false | false ];
+ input float in5 = [ -20.125 | 0.0 | 1.0 | -0.5 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 0.0, 5.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, -20.125) | mat4x3(1.0, 0.0, 1.0, 0.0, 0.0, 11.0, -32.0, 64.0, -51.0, 24.0, 1.0, 0.0) | mat4x3(1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0, 0.0, -0.5) | mat4x3(1.0, 1.0, 1.0, 1.0, 1.0, -66.0, 1.0, 1.25, 1.125, 1.75, 1.0, 3.5) | mat4x3(0.0, 1.0, 0.0, 0.0, 1.0, 255.0, -32.0, 64.0, -51.0, 24.0, 0.0, -8.25) | mat4x3(0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, -12.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.5, 0.75, 0.825, 0.0, 2.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 0.0, 0.5, 0.75, 0.825, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec4_bool_bool_int_to_mat4x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 36.8125 | -0.5 | 3.5 | 2.0 | 1.0 | -20.125 | 0.0 | 0.0 | -8.25 | 1.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input ivec4 in2 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, -2, -4, 9) ];
+ input bool in3 = [ false | true | false | true | false | false | false | true | true | true ];
+ input bool in4 = [ false | true | false | true | false | true | false | false | true | true ];
+ input int in5 = [ 2 | 1 | 8 | 11 | 255 | 5 | 0 | -66 | -192 | -12 ];
+ output mat4x3 out0 = [ mat4x3(36.8125, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 2.0) | mat4x3(-0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat4x3(3.5, 1.0, 0.0, 0.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 8.0) | mat4x3(2.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 11.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 255.0) | mat4x3(-20.125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 5.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, -66.0) | mat4x3(-8.25, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, -192.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, -12.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_vec4_to_mat4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in3 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ output mat4 out0 = [ mat4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0) | mat4(-32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4(-0.5, -2.25, -4.875, 9.0, -0.5, -2.25, -4.875, 9.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat4(1.0, 1.25, 1.125, 1.75, 1.0, 1.25, 1.125, 1.75, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) | mat4(0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, -0.5, -2.25, -4.875, 9.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_ivec4_to_mat4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in2 = [ ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in3 = [ ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat4 out0 = [ mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_bvec4_bvec4_bvec4_to_mat4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(true, false, false, true) ];
+ input bvec4 in1 = [ bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ input bvec4 in2 = [ bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) ];
+ input bvec4 in3 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_ivec3_bvec3_vec4_ivec2_float_vec2_to_mat4
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 1.0 | 3.5 | 0.0 | -20.125 | 36.8125 | -0.5 | -8.25 ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, -2, -4) ];
+ input bvec3 in2 = [ bvec3(true, false, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input ivec2 in4 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in5 = [ 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 | -20.125 | 1.0 | -0.5 ];
+ input vec2 in6 = [ vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(1.0, 1.25) ];
+ output mat4 out0 = [ mat4(2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, 0.0, 2.0, 0.0, 0.5) | mat4(1.0, -32.0, 64.0, -51.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0, 3.5, -0.5, -2.25) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, -2.0, 36.8125, -32.0, 64.0) | mat4(0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, 0.0, -8.25, 0.0, 0.5) | mat4(-20.125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0, 0.0, -0.75, -0.0322580645161) | mat4(36.8125, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -20.125, -0.5, -2.25) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 1.0, 1.0, 1.25) | mat4(-8.25, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, -2.0, -0.5, 1.0, 1.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_combine
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.html
new file mode 100644
index 0000000000..0f01ce529f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_matrix_combine';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.test
new file mode 100644
index 0000000000..ef74206d87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_combine.test
@@ -0,0 +1,1887 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group matrix_combine "Matrix Combine Constructors"
+
+ case vec2_vec2_to_mat2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input vec2 in1 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 0.0, 0.5) | mat2(-32.0, 64.0, 1.0, 1.25) | mat2(-0.5, -2.25, -0.75, -0.0322580645161) | mat2(-0.75, -0.0322580645161, -32.0, 64.0) | mat2(0.0, 0.5, -0.5, -2.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_mat2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, true) ];
+ output mat2 out0 = [ mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 1.0, 1.0, 0.0) | mat2(1.0, 0.0, 0.0, 0.0) | mat2(0.0, 0.0, 1.0, 1.0) | mat2(0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_mat2
+ version 300 es
+ values
+ {
+ input float in0 = [ -8.25 | 3.5 | 36.8125 | 2.0 | -20.125 | 1.0 | -0.5 | 0.0 ];
+ input float in1 = [ 3.5 | -20.125 | 1.0 | 0.0 | -8.25 | 2.0 | 36.8125 | -0.5 ];
+ input float in2 = [ 36.8125 | 3.5 | 0.0 | -20.125 | -0.5 | -8.25 | 1.0 | 2.0 ];
+ input float in3 = [ -0.5 | 0.0 | -8.25 | -20.125 | 2.0 | 3.5 | 1.0 | 36.8125 ];
+ output mat2 out0 = [ mat2(-8.25, 3.5, 36.8125, -0.5) | mat2(3.5, -20.125, 3.5, 0.0) | mat2(36.8125, 1.0, 0.0, -8.25) | mat2(2.0, 0.0, -20.125, -20.125) | mat2(-20.125, -8.25, -0.5, 2.0) | mat2(1.0, 2.0, -8.25, 3.5) | mat2(-0.5, 36.8125, 1.0, 1.0) | mat2(0.0, -0.5, 2.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | 1 | -192 | 11 | -66 | 255 | 0 | 8 | -12 | 5 ];
+ input int in1 = [ 11 | 255 | 5 | -66 | 8 | 2 | 0 | -12 | 1 | -192 ];
+ input int in2 = [ 11 | 1 | -12 | 255 | 5 | 0 | 8 | -192 | 2 | -66 ];
+ input int in3 = [ 2 | 1 | 0 | 8 | 255 | -66 | -192 | 11 | 5 | -12 ];
+ output mat2 out0 = [ mat2(2.0, 11.0, 11.0, 2.0) | mat2(1.0, 255.0, 1.0, 1.0) | mat2(-192.0, 5.0, -12.0, 0.0) | mat2(11.0, -66.0, 255.0, 8.0) | mat2(-66.0, 8.0, 5.0, 255.0) | mat2(255.0, 2.0, 0.0, -66.0) | mat2(0.0, 0.0, 8.0, -192.0) | mat2(8.0, -12.0, -192.0, 11.0) | mat2(-12.0, 1.0, 2.0, 5.0) | mat2(5.0, -192.0, -66.0, -12.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_mat2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 9 | 12 | 45 | 10 | 2 | 8 | 3 | 255 | 0 ];
+ input uint in1 = [ 0 | 255 | 12 | 193 | 3 | 2 | 45 | 9 | 8 | 10 ];
+ input uint in2 = [ 3 | 9 | 10 | 2 | 12 | 193 | 255 | 0 | 8 | 45 ];
+ input uint in3 = [ 45 | 12 | 9 | 3 | 2 | 255 | 10 | 8 | 193 | 0 ];
+ output mat2 out0 = [ mat2(193.0, 0.0, 3.0, 45.0) | mat2(9.0, 255.0, 9.0, 12.0) | mat2(12.0, 12.0, 10.0, 9.0) | mat2(45.0, 193.0, 2.0, 3.0) | mat2(10.0, 3.0, 12.0, 2.0) | mat2(2.0, 2.0, 193.0, 255.0) | mat2(8.0, 45.0, 255.0, 10.0) | mat2(3.0, 9.0, 0.0, 8.0) | mat2(255.0, 8.0, 8.0, 193.0) | mat2(0.0, 10.0, 45.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 0.0) | mat2(0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | true | false | true | true | false | false ];
+ input float in1 = [ 2.0 | -0.5 | 0.0 | 1.0 | 1.0 | 36.8125 | 3.5 | 0.0 | -8.25 | -20.125 ];
+ input int in2 = [ 0 | -12 | 8 | -192 | 1 | -66 | 5 | 11 | 2 | 255 ];
+ input bool in3 = [ true | false | true | false | true | false | false | true | true | false ];
+ output mat2 out0 = [ mat2(0.0, 2.0, 0.0, 1.0) | mat2(1.0, -0.5, -12.0, 0.0) | mat2(0.0, 0.0, 8.0, 1.0) | mat2(1.0, 1.0, -192.0, 0.0) | mat2(1.0, 1.0, 1.0, 1.0) | mat2(0.0, 36.8125, -66.0, 0.0) | mat2(1.0, 3.5, 5.0, 0.0) | mat2(1.0, 0.0, 11.0, 1.0) | mat2(0.0, -8.25, 2.0, 1.0) | mat2(0.0, -20.125, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_mat2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 0.0, -2.0) | mat2(-32.0, 64.0, 0.0, 0.0) | mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, -32.0, 64.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_mat2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) ];
+ output mat2 out0 = [ mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-32.0, 64.0, 1.0, 0.0) | mat2(1.0, 1.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, 0.0, 1.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_mat2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ 36.8125 | -8.25 | 1.0 | -0.5 | 2.0 | -20.125 | 0.0 | 3.5 ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 36.8125) | mat2(0.0, 1.0, 0.0, -8.25) | mat2(0.0, 0.0, 0.0, 1.0) | mat2(1.0, 1.0, 1.0, -0.5) | mat2(1.0, 0.0, 0.0, 2.0) | mat2(0.0, 1.0, 0.0, -20.125) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(0.0, 0.0, 0.0, 3.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_mat2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input float in1 = [ -0.5 | -20.125 | 0.0 | 36.8125 | 3.5 | -8.25 | 2.0 | 1.0 ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 1.125, -0.5) | mat2(-0.5, -2.25, -4.875, -20.125) | mat2(-0.5, -2.25, -4.875, 0.0) | mat2(1.0, 1.25, 1.125, 36.8125) | mat2(0.0, 0.5, 0.75, 3.5) | mat2(-32.0, 64.0, -51.0, -8.25) | mat2(0.0, 0.5, 0.75, 2.0) | mat2(-0.75, -0.0322580645161, 0.0526315789474, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | -192 | 2 | 0 | -66 | 255 | 5 | 1 | -12 | 11 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(1, 1) ];
+ input int in2 = [ 2 | 1 | -12 | 0 | 11 | 8 | 255 | -192 | 5 | -66 ];
+ output mat2 out0 = [ mat2(8.0, 0.0, -2.0, 2.0) | mat2(-192.0, 0.0, 0.0, 1.0) | mat2(2.0, -32.0, 64.0, -12.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(-66.0, 0.0, 0.0, 11.0) | mat2(255.0, -32.0, 64.0, 8.0) | mat2(5.0, 0.0, 0.0, 255.0) | mat2(1.0, 0.0, -2.0, -192.0) | mat2(-12.0, 1.0, 1.0, 5.0) | mat2(11.0, 1.0, 1.0, -66.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | true | false | false ];
+ input float in1 = [ 1.0 | -0.5 | -20.125 | 36.8125 | 2.0 | 0.0 | -8.25 | 3.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, -2) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 0.0, 0.0) | mat2(1.0, -0.5, 0.0, 0.0) | mat2(1.0, -20.125, 1.0, 1.0) | mat2(0.0, 36.8125, 0.0, 0.0) | mat2(0.0, 2.0, 1.0, 1.0) | mat2(1.0, 0.0, 0.0, -2.0) | mat2(0.0, -8.25, -32.0, 64.0) | mat2(0.0, 3.5, 0.0, -2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_mat2
+ version 300 es
+ values
+ {
+ input float in0 = [ 36.8125 | 2.0 | -0.5 | 0.0 | -20.125 | 1.0 | 3.5 | -8.25 ];
+ input uvec3 in1 = [ uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(32, 64, 51) | uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) ];
+ output mat2 out0 = [ mat2(36.8125, 1.0, 1.0, 1.0) | mat2(2.0, 0.0, 2.0, 4.0) | mat2(-0.5, 0.0, 2.0, 4.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(-20.125, 32.0, 64.0, 51.0) | mat2(1.0, 0.0, 0.0, 0.0) | mat2(3.5, 0.0, 0.0, 0.0) | mat2(-8.25, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -66 | 5 | -192 | 11 | 0 | 8 | 2 | -12 | 255 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(32, 64) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(0, 0) | uvec2(0, 0) | uvec2(32, 64) ];
+ input bool in2 = [ true | false | true | false | false | false | true | true | true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 2.0, 1.0) | mat2(-66.0, 32.0, 64.0, 0.0) | mat2(5.0, 1.0, 1.0, 1.0) | mat2(-192.0, 0.0, 0.0, 0.0) | mat2(11.0, 0.0, 0.0, 0.0) | mat2(0.0, 1.0, 1.0, 0.0) | mat2(8.0, 0.0, 2.0, 1.0) | mat2(2.0, 0.0, 0.0, 1.0) | mat2(-12.0, 0.0, 0.0, 1.0) | mat2(255.0, 32.0, 64.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in1 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 1.25, 1.125, -32.0, 64.0, -51.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25, -4.875) | mat2x3(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75) | mat2x3(-32.0, 64.0, -51.0, 1.0, 1.25, 1.125) | mat2x3(0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_bvec3_to_mat2x3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ input bvec3 in1 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(1.0, 1.0, 1.0, 1.0, 0.0, 0.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_float_float_to_mat2x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -8.25 | -20.125 | 36.8125 | -0.5 | 2.0 | 3.5 | 0.0 ];
+ input float in1 = [ -0.5 | -20.125 | 36.8125 | -8.25 | 2.0 | 1.0 | 3.5 | 0.0 ];
+ input float in2 = [ 3.5 | 1.0 | 36.8125 | -20.125 | -8.25 | -0.5 | 2.0 | 0.0 ];
+ input float in3 = [ 1.0 | -8.25 | 0.0 | -20.125 | 2.0 | 3.5 | -0.5 | 36.8125 ];
+ input float in4 = [ 1.0 | 0.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 ];
+ input float in5 = [ 2.0 | -20.125 | -8.25 | -0.5 | 3.5 | 1.0 | 36.8125 | 0.0 ];
+ output mat2x3 out0 = [ mat2x3(1.0, -0.5, 3.5, 1.0, 1.0, 2.0) | mat2x3(-8.25, -20.125, 1.0, -8.25, 0.0, -20.125) | mat2x3(-20.125, 36.8125, 36.8125, 0.0, 3.5, -8.25) | mat2x3(36.8125, -8.25, -20.125, -20.125, 2.0, -0.5) | mat2x3(-0.5, 2.0, -8.25, 2.0, -8.25, 3.5) | mat2x3(2.0, 1.0, -0.5, 3.5, -20.125, 1.0) | mat2x3(3.5, 3.5, 2.0, -0.5, -0.5, 36.8125) | mat2x3(0.0, 0.0, 0.0, 36.8125, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_int_int_to_mat2x3
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | 8 | -192 | 0 | 5 | -12 | 1 | 255 | -66 | 11 ];
+ input int in1 = [ 1 | -192 | 8 | 0 | -12 | 2 | 11 | 255 | -66 | 5 ];
+ input int in2 = [ -192 | 2 | -66 | 8 | 11 | 255 | 0 | 5 | -12 | 1 ];
+ input int in3 = [ 2 | 11 | 255 | 0 | -66 | -12 | 5 | -192 | 8 | 1 ];
+ input int in4 = [ 8 | 0 | -12 | -192 | 2 | -66 | 1 | 255 | 5 | 11 ];
+ input int in5 = [ 0 | 11 | 5 | 8 | -12 | 255 | -192 | 2 | 1 | -66 ];
+ output mat2x3 out0 = [ mat2x3(2.0, 1.0, -192.0, 2.0, 8.0, 0.0) | mat2x3(8.0, -192.0, 2.0, 11.0, 0.0, 11.0) | mat2x3(-192.0, 8.0, -66.0, 255.0, -12.0, 5.0) | mat2x3(0.0, 0.0, 8.0, 0.0, -192.0, 8.0) | mat2x3(5.0, -12.0, 11.0, -66.0, 2.0, -12.0) | mat2x3(-12.0, 2.0, 255.0, -12.0, -66.0, 255.0) | mat2x3(1.0, 11.0, 0.0, 5.0, 1.0, -192.0) | mat2x3(255.0, 255.0, 5.0, -192.0, 255.0, 2.0) | mat2x3(-66.0, -66.0, -12.0, 8.0, 5.0, 1.0) | mat2x3(11.0, 5.0, 1.0, 1.0, 11.0, -66.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_bool_bool_to_mat2x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ true | false ];
+ input bool in4 = [ true | false ];
+ input bool in5 = [ true | false ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(0.0, 1.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_float_int_to_mat2x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | true | false ];
+ input float in1 = [ 0.0 | -8.25 | 2.0 | -20.125 | 3.5 | 0.0 | -0.5 | 36.8125 | 1.0 | 1.0 ];
+ input int in2 = [ -66 | -12 | 2 | 8 | 255 | 11 | -192 | 1 | 5 | 0 ];
+ input bool in3 = [ true | false | true | false | false | true | true | false | true | false ];
+ input float in4 = [ 1.0 | 0.0 | -8.25 | 1.0 | 3.5 | -20.125 | -0.5 | 0.0 | 2.0 | 36.8125 ];
+ input int in5 = [ 255 | -192 | 1 | 2 | -12 | -66 | 8 | 0 | 11 | 5 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, -66.0, 1.0, 1.0, 255.0) | mat2x3(1.0, -8.25, -12.0, 0.0, 0.0, -192.0) | mat2x3(0.0, 2.0, 2.0, 1.0, -8.25, 1.0) | mat2x3(1.0, -20.125, 8.0, 0.0, 1.0, 2.0) | mat2x3(0.0, 3.5, 255.0, 0.0, 3.5, -12.0) | mat2x3(1.0, 0.0, 11.0, 1.0, -20.125, -66.0) | mat2x3(0.0, -0.5, -192.0, 1.0, -0.5, 8.0) | mat2x3(1.0, 36.8125, 1.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 1.0, 5.0, 1.0, 2.0, 11.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 36.8125, 5.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_ivec3_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, 0, 0) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 1.25, 1.125, 1.0, 1.0, 1.0) | mat2x3(-0.5, -2.25, -4.875, -32.0, 64.0, -51.0) | mat2x3(-32.0, 64.0, -51.0, 0.0, -2.0, -4.0) | mat2x3(0.0, 0.5, 0.75, 0.0, 0.0, 0.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec4_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output mat2x3 out0 = [ mat2x3(-32.0, 64.0, 1.0, 0.0, 0.0, 1.0) | mat2x3(0.0, 0.5, 0.0, 1.0, 0.0, 0.0) | mat2x3(-0.5, -2.25, 0.0, 0.0, 0.0, 1.0) | mat2x3(1.0, 1.25, 1.0, 1.0, 1.0, 1.0) | mat2x3(-0.75, -0.0322580645161, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_ivec2_to_mat2x3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ 1.0 | -8.25 | 36.8125 | 2.0 | 3.5 | -0.5 | -20.125 | 0.0 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(0.0, 0.0, 0.0, -8.25, 0.0, 0.0) | mat2x3(1.0, 1.0, 1.0, 36.8125, -32.0, 64.0) | mat2x3(1.0, 0.0, 0.0, 2.0, 0.0, -2.0) | mat2x3(0.0, 0.0, 0.0, 3.5, 1.0, 1.0) | mat2x3(0.0, 1.0, 0.0, -0.5, 0.0, -2.0) | mat2x3(1.0, 0.0, 0.0, -20.125, 0.0, 0.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_bvec2_to_mat2x3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 36.8125 | 3.5 | -0.5 | -8.25 | 2.0 | 1.0 | -20.125 ];
+ input bvec2 in2 = [ bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.5, 0.75, 0.0, 0.0, 0.0) | mat2x3(-0.5, -2.25, -4.875, 36.8125, 0.0, 1.0) | mat2x3(0.0, 0.5, 0.75, 3.5, 1.0, 0.0) | mat2x3(1.0, 1.25, 1.125, -0.5, 0.0, 1.0) | mat2x3(-0.5, -2.25, -4.875, -8.25, 0.0, 0.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, 2.0, 1.0, 0.0) | mat2x3(-32.0, 64.0, -51.0, 1.0, 1.0, 1.0) | mat2x3(1.0, 1.25, 1.125, -20.125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec2_to_mat2x4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) ];
+ input vec3 in1 = [ vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec2 in2 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ output mat2x4 out0 = [ mat2x4(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75, -0.75, -0.0322580645161) | mat2x4(-0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25, -4.875, -32.0, 64.0) | mat2x4(0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25) | mat2x4(1.0, 1.25, 1.125, -32.0, 64.0, -51.0, 0.0, 0.5) | mat2x4(-32.0, 64.0, -51.0, 1.0, 1.25, 1.125, -0.5, -2.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec2_to_mat2x4
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) ];
+ output mat2x4 out0 = [ mat2x4(0.0, -2.0, -4.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -2.0) | mat2x4(1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 1.0, 1.0) | mat2x4(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 0.0, 0.0) | mat2x4(-32.0, 64.0, -51.0, 0.0, 0.0, 0.0, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_to_mat2x4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in2 = [ -8.25 | -0.5 | 3.5 | 36.8125 | 0.0 | 0.0 | 2.0 | -20.125 | 1.0 | 1.0 ];
+ input float in3 = [ 1.0 | 2.0 | -0.5 | 3.5 | 36.8125 | -8.25 | 1.0 | 0.0 | 0.0 | -20.125 ];
+ input int in4 = [ 255 | 8 | 11 | -12 | -192 | 0 | 2 | 1 | -66 | 5 ];
+ input bool in5 = [ true | false | false | true | false | true | true | false | true | false ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.5, 1.0, 1.0, -8.25, 1.0, 255.0, 1.0) | mat2x4(-32.0, 64.0, 0.0, -2.0, -0.5, 2.0, 8.0, 0.0) | mat2x4(-0.5, -2.25, -32.0, 64.0, 3.5, -0.5, 11.0, 0.0) | mat2x4(0.0, 0.5, 0.0, -2.0, 36.8125, 3.5, -12.0, 1.0) | mat2x4(-32.0, 64.0, 0.0, 0.0, 0.0, 36.8125, -192.0, 0.0) | mat2x4(1.0, 1.25, 0.0, 0.0, 0.0, -8.25, 0.0, 1.0) | mat2x4(-0.75, -0.0322580645161, -32.0, 64.0, 2.0, 1.0, 2.0, 1.0) | mat2x4(1.0, 1.25, 0.0, 0.0, -20.125, 0.0, 1.0, 0.0) | mat2x4(-0.5, -2.25, 0.0, 0.0, 1.0, 0.0, -66.0, 1.0) | mat2x4(-0.75, -0.0322580645161, 1.0, 1.0, 1.0, -20.125, 5.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_to_mat2x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | true | true | false | false | false | true ];
+ input float in1 = [ 0.0 | -0.5 | -20.125 | -8.25 | 0.0 | 2.0 | 3.5 | 1.0 | 1.0 | 36.8125 ];
+ input int in2 = [ 2 | 1 | 255 | 8 | -66 | 0 | -12 | 5 | -192 | 11 ];
+ input vec2 in3 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input bool in4 = [ true | false | false | true | false | false | true | true | true | false ];
+ input bvec2 in5 = [ bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 2.0, -32.0, 64.0, 1.0, 1.0, 0.0) | mat2x4(1.0, -0.5, 1.0, -0.5, -2.25, 0.0, 1.0, 1.0) | mat2x4(0.0, -20.125, 255.0, 1.0, 1.25, 0.0, 0.0, 1.0) | mat2x4(1.0, -8.25, 8.0, -0.75, -0.0322580645161, 1.0, 1.0, 1.0) | mat2x4(1.0, 0.0, -66.0, 0.0, 0.5, 0.0, 0.0, 0.0) | mat2x4(1.0, 2.0, 0.0, 1.0, 1.25, 0.0, 0.0, 1.0) | mat2x4(0.0, 3.5, -12.0, -32.0, 64.0, 1.0, 0.0, 0.0) | mat2x4(0.0, 1.0, 5.0, -0.5, -2.25, 1.0, 0.0, 0.0) | mat2x4(0.0, 1.0, -192.0, 0.0, 0.5, 1.0, 0.0, 0.0) | mat2x4(1.0, 36.8125, 11.0, -0.75, -0.0322580645161, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_to_mat2x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | false | false | true | true ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) ];
+ input int in2 = [ 8 | 1 | 5 | -66 | -192 | 11 | 255 | 0 | -12 | 2 ];
+ input vec4 in3 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 1.0, 1.0, 8.0, 0.0, 0.5, 0.75, 0.825) | mat2x4(1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.75, 0.825) | mat2x4(1.0, 1.0, 0.0, 5.0, -32.0, 64.0, -51.0, 24.0) | mat2x4(0.0, 0.0, 0.0, -66.0, 1.0, 1.25, 1.125, 1.75) | mat2x4(0.0, 1.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0) | mat2x4(0.0, 1.0, 0.0, 11.0, 1.0, 1.25, 1.125, 1.75) | mat2x4(0.0, 0.0, 1.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat2x4(0.0, 0.0, 0.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat2x4(1.0, 0.0, 1.0, -12.0, -0.5, -2.25, -4.875, 9.0) | mat2x4(1.0, 0.0, 0.0, 2.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_to_mat2x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 2.0 | -8.25 | -20.125 | 36.8125 | 1.0 | -0.5 ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) ];
+ input ivec2 in2 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) ];
+ input bool in3 = [ true | true | false | true | false | false | false | true ];
+ output mat2x4 out0 = [ mat2x4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0) | mat2x4(3.5, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, 1.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0) | mat2x4(-8.25, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x4(-20.125, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(36.8125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat2x4(-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec3 in1 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ output mat3x2 out0 = [ mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25, 1.125) | mat3x2(-0.5, -2.25, -4.875, -0.75, -0.0322580645161, 0.0526315789474) | mat3x2(0.0, 0.5, 0.75, -32.0, 64.0, -51.0) | mat3x2(-32.0, 64.0, -51.0, -0.5, -2.25, -4.875) | mat3x2(1.0, 1.25, 1.125, 0.0, 0.5, 0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_bvec3_to_mat3x2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ input bvec3 in1 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3x2(1.0, 1.0, 1.0, 0.0, 1.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_float_float_to_mat3x2
+ version 300 es
+ values
+ {
+ input float in0 = [ -8.25 | 36.8125 | -20.125 | -0.5 | 3.5 | 1.0 | 2.0 | 0.0 ];
+ input float in1 = [ 2.0 | 3.5 | -20.125 | 36.8125 | 1.0 | 0.0 | -8.25 | -0.5 ];
+ input float in2 = [ -0.5 | 2.0 | 1.0 | 0.0 | -8.25 | 36.8125 | -20.125 | 3.5 ];
+ input float in3 = [ 36.8125 | 0.0 | 1.0 | -0.5 | 2.0 | 3.5 | -20.125 | -8.25 ];
+ input float in4 = [ 36.8125 | 2.0 | 0.0 | -0.5 | 3.5 | -20.125 | -8.25 | 1.0 ];
+ input float in5 = [ 0.0 | 36.8125 | -20.125 | -0.5 | 3.5 | 2.0 | 1.0 | -8.25 ];
+ output mat3x2 out0 = [ mat3x2(-8.25, 2.0, -0.5, 36.8125, 36.8125, 0.0) | mat3x2(36.8125, 3.5, 2.0, 0.0, 2.0, 36.8125) | mat3x2(-20.125, -20.125, 1.0, 1.0, 0.0, -20.125) | mat3x2(-0.5, 36.8125, 0.0, -0.5, -0.5, -0.5) | mat3x2(3.5, 1.0, -8.25, 2.0, 3.5, 3.5) | mat3x2(1.0, 0.0, 36.8125, 3.5, -20.125, 2.0) | mat3x2(2.0, -8.25, -20.125, -20.125, -8.25, 1.0) | mat3x2(0.0, -0.5, 3.5, -8.25, 1.0, -8.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_int_int_to_mat3x2
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | -192 | 2 | 11 | 255 | -66 | 5 | -12 | 1 | 0 ];
+ input int in1 = [ 1 | 2 | -12 | 5 | 0 | 255 | 8 | 11 | -192 | -66 ];
+ input int in2 = [ -12 | 11 | 2 | 1 | 8 | -66 | -192 | 5 | 255 | 0 ];
+ input int in3 = [ -192 | 0 | -12 | 11 | 1 | -66 | 8 | 255 | 2 | 5 ];
+ input int in4 = [ -12 | 5 | 0 | -66 | 255 | 8 | -192 | 11 | 2 | 1 ];
+ input int in5 = [ -66 | -12 | 8 | 2 | 255 | 0 | -192 | 11 | 1 | 5 ];
+ output mat3x2 out0 = [ mat3x2(8.0, 1.0, -12.0, -192.0, -12.0, -66.0) | mat3x2(-192.0, 2.0, 11.0, 0.0, 5.0, -12.0) | mat3x2(2.0, -12.0, 2.0, -12.0, 0.0, 8.0) | mat3x2(11.0, 5.0, 1.0, 11.0, -66.0, 2.0) | mat3x2(255.0, 0.0, 8.0, 1.0, 255.0, 255.0) | mat3x2(-66.0, 255.0, -66.0, -66.0, 8.0, 0.0) | mat3x2(5.0, 8.0, -192.0, 8.0, -192.0, -192.0) | mat3x2(-12.0, 11.0, 5.0, 255.0, 11.0, 11.0) | mat3x2(1.0, -192.0, 255.0, 2.0, 2.0, 1.0) | mat3x2(0.0, -66.0, 0.0, 5.0, 1.0, 5.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_bool_bool_to_mat3x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ input bool in4 = [ false | true ];
+ input bool in5 = [ false | true ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 1.0, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_float_int_to_mat3x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false | true | false | true | false | false ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | 0.0 | 1.0 | -8.25 | 1.0 | 2.0 | 36.8125 | -0.5 ];
+ input int in2 = [ 255 | -66 | 8 | -192 | 5 | 11 | 1 | 2 | 0 | -12 ];
+ input bool in3 = [ true | false | false | true | false | true | true | false | false | true ];
+ input float in4 = [ 0.0 | -20.125 | 1.0 | -8.25 | 0.0 | -0.5 | 2.0 | 3.5 | 1.0 | 36.8125 ];
+ input int in5 = [ -192 | 8 | 2 | 255 | -66 | -12 | 11 | 0 | 5 | 1 ];
+ output mat3x2 out0 = [ mat3x2(1.0, -20.125, 255.0, 1.0, 0.0, -192.0) | mat3x2(0.0, 0.0, -66.0, 0.0, -20.125, 8.0) | mat3x2(1.0, 3.5, 8.0, 0.0, 1.0, 2.0) | mat3x2(1.0, 0.0, -192.0, 1.0, -8.25, 255.0) | mat3x2(0.0, 1.0, 5.0, 0.0, 0.0, -66.0) | mat3x2(1.0, -8.25, 11.0, 1.0, -0.5, -12.0) | mat3x2(0.0, 1.0, 1.0, 1.0, 2.0, 11.0) | mat3x2(1.0, 2.0, 2.0, 0.0, 3.5, 0.0) | mat3x2(0.0, 36.8125, 0.0, 0.0, 1.0, 5.0) | mat3x2(0.0, -0.5, -12.0, 1.0, 36.8125, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_ivec3_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.5, 0.75, 1.0, 1.0, 1.0) | mat3x2(1.0, 1.25, 1.125, 0.0, 0.0, 0.0) | mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 0.0, -2.0, -4.0) | mat3x2(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3x2(-0.5, -2.25, -4.875, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec4_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.5, 1.0, 1.0, 1.0, 1.0) | mat3x2(-0.75, -0.0322580645161, 0.0, 0.0, 0.0, 1.0) | mat3x2(-32.0, 64.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(-0.5, -2.25, 1.0, 0.0, 0.0, 1.0) | mat3x2(1.0, 1.25, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_ivec2_to_mat3x2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ input float in1 = [ -8.25 | 1.0 | 2.0 | -0.5 | -20.125 | 0.0 | 36.8125 | 3.5 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, -8.25, 1.0, 1.0) | mat3x2(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) | mat3x2(0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, -0.5, 0.0, -2.0) | mat3x2(0.0, 1.0, 0.0, -20.125, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 0.0, 36.8125, 0.0, -2.0) | mat3x2(1.0, 0.0, 0.0, 3.5, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_bvec2_to_mat3x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input float in1 = [ -8.25 | 36.8125 | -0.5 | 3.5 | 2.0 | -20.125 | 0.0 | 1.0 ];
+ input bvec2 in2 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 1.25, 1.125, -8.25, 1.0, 0.0) | mat3x2(1.0, 1.25, 1.125, 36.8125, 0.0, 0.0) | mat3x2(-0.5, -2.25, -4.875, -0.5, 1.0, 1.0) | mat3x2(-0.5, -2.25, -4.875, 3.5, 0.0, 0.0) | mat3x2(-32.0, 64.0, -51.0, 2.0, 0.0, 1.0) | mat3x2(0.0, 0.5, 0.75, -20.125, 0.0, 1.0) | mat3x2(0.0, 0.5, 0.75, 0.0, 1.0, 0.0) | mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec3_to_mat3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input vec3 in1 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in2 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 1.125, -0.75, -0.0322580645161, 0.0526315789474, -0.75, -0.0322580645161, 0.0526315789474) | mat3(-0.5, -2.25, -4.875, 1.0, 1.25, 1.125, -32.0, 64.0, -51.0) | mat3(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0, -0.5, -2.25, -4.875) | mat3(0.0, 0.5, 0.75, -0.5, -2.25, -4.875, 1.0, 1.25, 1.125) | mat3(-0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.5, 0.75, 0.0, 0.5, 0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec3_to_mat3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(1, 1, 1) ];
+ input ivec3 in2 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) | ivec3(0, 0, 0) ];
+ output mat3 out0 = [ mat3(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3(0.0, -2.0, -4.0, 0.0, -2.0, -4.0, 0.0, 0.0, 0.0) | mat3(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(-32.0, 64.0, -51.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0) | mat3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_bool_to_mat3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(-32, 64) ];
+ input float in2 = [ -0.5 | 3.5 | 0.0 | -20.125 | 1.0 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ input float in3 = [ 3.5 | 0.0 | -20.125 | 36.8125 | 2.0 | -8.25 | -0.5 | 1.0 | 0.0 | 1.0 ];
+ input int in4 = [ 0 | 11 | 5 | -192 | 8 | -66 | 1 | 2 | 255 | -12 ];
+ input bool in5 = [ true | true | true | false | true | false | false | false | true | false ];
+ input bool in6 = [ false | false | true | false | false | false | true | true | true | true ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 0.0, 0.0, -0.5, 3.5, 0.0, 1.0, 0.0) | mat3(-0.5, -2.25, 0.0, -2.0, 3.5, 0.0, 11.0, 1.0, 0.0) | mat3(0.0, 0.5, 1.0, 1.0, 0.0, -20.125, 5.0, 1.0, 1.0) | mat3(-0.75, -0.0322580645161, 0.0, -2.0, -20.125, 36.8125, -192.0, 0.0, 0.0) | mat3(-32.0, 64.0, 0.0, 0.0, 1.0, 2.0, 8.0, 1.0, 0.0) | mat3(-0.75, -0.0322580645161, 0.0, 0.0, -8.25, -8.25, -66.0, 0.0, 0.0) | mat3(-0.5, -2.25, 1.0, 1.0, 0.0, -0.5, 1.0, 0.0, 1.0) | mat3(1.0, 1.25, -32.0, 64.0, 1.0, 1.0, 2.0, 0.0, 1.0) | mat3(0.0, 0.5, 0.0, 0.0, 2.0, 0.0, 255.0, 1.0, 1.0) | mat3(-32.0, 64.0, -32.0, 64.0, 36.8125, 1.0, -12.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_float_to_mat3
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | true | true | true | true | false | false | false | false ];
+ input float in1 = [ -8.25 | 1.0 | -0.5 | 36.8125 | 0.0 | 3.5 | -20.125 | 1.0 | 0.0 | 2.0 ];
+ input int in2 = [ 8 | -66 | 5 | 1 | 0 | 2 | -12 | -192 | 11 | 255 ];
+ input vec2 in3 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input bool in4 = [ true | false | true | false | false | true | true | false | true | false ];
+ input bvec2 in5 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) ];
+ input float in6 = [ -0.5 | 1.0 | 1.0 | 0.0 | 36.8125 | 2.0 | 0.0 | 3.5 | -20.125 | -8.25 ];
+ output mat3 out0 = [ mat3(0.0, -8.25, 8.0, 0.0, 0.5, 1.0, 0.0, 1.0, -0.5) | mat3(1.0, 1.0, -66.0, -32.0, 64.0, 0.0, 0.0, 0.0, 1.0) | mat3(1.0, -0.5, 5.0, 1.0, 1.25, 1.0, 1.0, 0.0, 1.0) | mat3(1.0, 36.8125, 1.0, -32.0, 64.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, -0.5, -2.25, 0.0, 1.0, 1.0, 36.8125) | mat3(1.0, 3.5, 2.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0, 2.0) | mat3(0.0, -20.125, -12.0, -0.5, -2.25, 1.0, 1.0, 0.0, 0.0) | mat3(0.0, 1.0, -192.0, 0.0, 0.5, 0.0, 0.0, 0.0, 3.5) | mat3(0.0, 0.0, 11.0, 1.0, 1.25, 1.0, 0.0, 1.0, -20.125) | mat3(0.0, 2.0, 255.0, -0.75, -0.0322580645161, 0.0, 1.0, 1.0, -8.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_bool_to_mat3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false | false | true | false | false | true ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in2 = [ -192 | 2 | 0 | 5 | 1 | -66 | 11 | -12 | 8 | 255 ];
+ input vec4 in3 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ input bool in4 = [ false | true | false | true | false | false | false | true | true | true ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, -192.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(0.0, 0.0, 1.0, 2.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 1.0, 1.0, 5.0, -32.0, 64.0, -51.0, 24.0, 1.0) | mat3(0.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 0.0, 0.0, -66.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 0.0, 1.0, 11.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 1.0, 0.0, -12.0, -0.5, -2.25, -4.875, 9.0, 1.0) | mat3(0.0, 1.0, 0.0, 8.0, -0.5, -2.25, -4.875, 9.0, 1.0) | mat3(1.0, 0.0, 0.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_bool_to_mat3
+ version 300 es
+ values
+ {
+ input float in0 = [ -8.25 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -20.125 | 0.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, true) ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) ];
+ input bool in3 = [ false | true | false | true | true | false | true | false ];
+ input bool in4 = [ true | false | false | false | true | true | false | true ];
+ output mat3 out0 = [ mat3(-8.25, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat3(2.0, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, 1.0, 0.0) | mat3(36.8125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3(3.5, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, 1.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat3(-0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat3(-20.125, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0, 0.0) | mat3(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_to_mat3x4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat3x4 out0 = [ mat3x4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0) | mat3x4(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat3x4(-32.0, 64.0, -51.0, 24.0, 0.0, 0.5, 0.75, 0.825, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat3x4(-0.5, -2.25, -4.875, 9.0, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat3x4(0.0, 0.5, 0.75, 0.825, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_to_mat3x4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) ];
+ input ivec4 in1 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in2 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat3x4 out0 = [ mat3x4(0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(-32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_float_int_int_bool_bool_bool_to_mat3x4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-0.5, -2.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in2 = [ 1.0 | -8.25 | 2.0 | 3.5 | -20.125 | 36.8125 | 0.0 | 1.0 | -0.5 | 0.0 ];
+ input float in3 = [ -0.5 | 36.8125 | 1.0 | 1.0 | 0.0 | 3.5 | 2.0 | 0.0 | -8.25 | -20.125 ];
+ input float in4 = [ -8.25 | 1.0 | 1.0 | 0.0 | 2.0 | 36.8125 | 0.0 | -20.125 | 3.5 | -0.5 ];
+ input int in5 = [ 11 | 2 | 8 | 5 | 0 | -192 | 1 | -12 | 255 | -66 ];
+ input int in6 = [ -12 | 5 | 8 | 1 | 0 | 255 | 11 | -192 | -66 | 2 ];
+ input bool in7 = [ true | true | true | false | false | false | true | false | true | false ];
+ input bool in8 = [ true | true | true | false | true | false | true | false | false | false ];
+ input bool in9 = [ true | false | true | false | true | true | false | false | false | true ];
+ output mat3x4 out0 = [ mat3x4(1.0, 1.25, 0.0, 0.0, 1.0, -0.5, -8.25, 11.0, -12.0, 1.0, 1.0, 1.0) | mat3x4(0.0, 0.5, 0.0, 0.0, -8.25, 36.8125, 1.0, 2.0, 5.0, 1.0, 1.0, 0.0) | mat3x4(0.0, 0.5, -32.0, 64.0, 2.0, 1.0, 1.0, 8.0, 8.0, 1.0, 1.0, 1.0) | mat3x4(-32.0, 64.0, 1.0, 1.0, 3.5, 1.0, 0.0, 5.0, 1.0, 0.0, 0.0, 0.0) | mat3x4(-32.0, 64.0, 1.0, 1.0, -20.125, 0.0, 2.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat3x4(-0.75, -0.0322580645161, -32.0, 64.0, 36.8125, 3.5, 36.8125, -192.0, 255.0, 0.0, 0.0, 1.0) | mat3x4(1.0, 1.25, 0.0, 0.0, 0.0, 2.0, 0.0, 1.0, 11.0, 1.0, 1.0, 0.0) | mat3x4(-0.75, -0.0322580645161, 0.0, -2.0, 1.0, 0.0, -20.125, -12.0, -192.0, 0.0, 0.0, 0.0) | mat3x4(-0.5, -2.25, 0.0, 0.0, -0.5, -8.25, 3.5, 255.0, -66.0, 1.0, 0.0, 0.0) | mat3x4(-0.5, -2.25, 0.0, -2.0, 0.0, -20.125, -0.5, -66.0, 2.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec3_bool_bvec3_float_bool_to_mat3x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | false | true | true | true | true | false | false | false | true ];
+ input float in1 = [ 36.8125 | -8.25 | 1.0 | 0.0 | 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -20.125 ];
+ input int in2 = [ -66 | -192 | 255 | 8 | 0 | -12 | 5 | 2 | 11 | 1 ];
+ input vec3 in3 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) ];
+ input bool in4 = [ false | true | true | true | false | false | true | true | false | false ];
+ input bvec3 in5 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in6 = [ -8.25 | 1.0 | -0.5 | 36.8125 | 0.0 | 2.0 | -20.125 | 1.0 | 0.0 | 3.5 ];
+ input bool in7 = [ true | false | false | true | true | false | true | false | false | true ];
+ output mat3x4 out0 = [ mat3x4(0.0, 36.8125, -66.0, -0.75, -0.0322580645161, 0.0526315789474, 0.0, 1.0, 0.0, 0.0, -8.25, 1.0) | mat3x4(0.0, -8.25, -192.0, -32.0, 64.0, -51.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(1.0, 1.0, 255.0, 0.0, 0.5, 0.75, 1.0, 0.0, 1.0, 0.0, -0.5, 0.0) | mat3x4(1.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 36.8125, 1.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0) | mat3x4(1.0, 1.0, -12.0, -32.0, 64.0, -51.0, 0.0, 1.0, 1.0, 1.0, 2.0, 0.0) | mat3x4(0.0, 2.0, 5.0, 1.0, 1.25, 1.125, 1.0, 1.0, 1.0, 1.0, -20.125, 1.0) | mat3x4(0.0, 3.5, 2.0, 1.0, 1.25, 1.125, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.0, -0.5, 11.0, -0.5, -2.25, -4.875, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, -20.125, 1.0, -0.5, -2.25, -4.875, 0.0, 0.0, 0.0, 0.0, 3.5, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5, in6, in7);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4_int_vec4_bool_float_to_mat3x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true | true | true | false | false | false | true | false | true ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) ];
+ input int in2 = [ 255 | 2 | -192 | -12 | 11 | 1 | 0 | -66 | 8 | 5 ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input bool in4 = [ true | true | true | false | false | false | true | true | false | false ];
+ input float in5 = [ 36.8125 | 2.0 | -8.25 | 0.0 | 1.0 | 1.0 | -0.5 | 3.5 | 0.0 | -20.125 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 255.0, -0.5, -2.25, -4.875, 9.0, 1.0, 36.8125) | mat3x4(1.0, 1.0, 0.0, 0.0, 1.0, 2.0, 1.0, 1.25, 1.125, 1.75, 1.0, 2.0) | mat3x4(1.0, 0.0, 1.0, 0.0, 0.0, -192.0, 1.0, 1.25, 1.125, 1.75, 1.0, -8.25) | mat3x4(1.0, 0.0, 0.0, 0.0, 1.0, -12.0, 0.0, 0.5, 0.75, 0.825, 0.0, 0.0) | mat3x4(0.0, 1.0, 1.0, 1.0, 1.0, 11.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 1.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 1.0) | mat3x4(0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, -0.5) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.5, 0.75, 0.825, 1.0, 3.5) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 0.0) | mat3x4(1.0, 1.0, 0.0, 0.0, 1.0, 5.0, -0.5, -2.25, -4.875, 9.0, 0.0, -20.125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec4_bool_bool_int_to_mat3x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 36.8125 | 1.0 | 0.0 | 3.5 | -8.25 | -20.125 | 2.0 | 0.0 | 1.0 | -0.5 ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(false, false, false, false) ];
+ input ivec4 in2 = [ ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) ];
+ input bool in3 = [ true | false | true | true | false | true | true | false | false | false ];
+ input bool in4 = [ true | false | false | true | true | false | false | false | true | true ];
+ input int in5 = [ 1 | 5 | -12 | 8 | -192 | 2 | -66 | 255 | 11 | 0 ];
+ output mat3x4 out0 = [ mat3x4(36.8125, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 5.0) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, 0.0, -12.0) | mat3x4(3.5, 0.0, 0.0, 0.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, 8.0) | mat3x4(-8.25, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -192.0) | mat3x4(-20.125, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 2.0) | mat3x4(2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -66.0) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 255.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 11.0) | mat3x4(-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec2_to_mat4x2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input vec3 in1 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input vec2 in2 = [ vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 1.25, 1.125, -32.0, 64.0, -51.0, 1.0, 1.25) | mat4x2(-32.0, 64.0, -51.0, -0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25) | mat4x2(0.0, 0.5, 0.75, -0.5, -2.25, -4.875, -0.75, -0.0322580645161) | mat4x2(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75, -32.0, 64.0) | mat4x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25, 1.125, 0.0, 0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec2_to_mat4x2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec3 in1 = [ ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec2 in2 = [ ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, -2.0, -4.0, -32.0, 64.0) | mat4x2(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.0, -2.0, -4.0, 1.0, 1.0, 1.0, 0.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat4x2(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0, 0.0, -2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_to_mat4x2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in2 = [ 3.5 | -8.25 | 2.0 | 36.8125 | -0.5 | 1.0 | 1.0 | 0.0 | -20.125 | 0.0 ];
+ input float in3 = [ 0.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | 2.0 | 0.0 | -20.125 | 1.0 ];
+ input int in4 = [ -12 | -66 | 11 | 5 | 8 | 255 | -192 | 2 | 1 | 0 ];
+ input bool in5 = [ true | true | false | true | false | true | false | true | false | false ];
+ output mat4x2 out0 = [ mat4x2(-0.5, -2.25, 0.0, -2.0, 3.5, 0.0, -12.0, 1.0) | mat4x2(0.0, 0.5, 0.0, 0.0, -8.25, 36.8125, -66.0, 1.0) | mat4x2(1.0, 1.25, -32.0, 64.0, 2.0, 3.5, 11.0, 0.0) | mat4x2(0.0, 0.5, 1.0, 1.0, 36.8125, 1.0, 5.0, 1.0) | mat4x2(-32.0, 64.0, 1.0, 1.0, -0.5, -0.5, 8.0, 0.0) | mat4x2(-0.75, -0.0322580645161, 0.0, 0.0, 1.0, -8.25, 255.0, 1.0) | mat4x2(-0.75, -0.0322580645161, -32.0, 64.0, 1.0, 2.0, -192.0, 0.0) | mat4x2(-32.0, 64.0, 0.0, 0.0, 0.0, 0.0, 2.0, 1.0) | mat4x2(-0.5, -2.25, 0.0, 0.0, -20.125, -20.125, 1.0, 0.0) | mat4x2(1.0, 1.25, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_to_mat4x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | false | true | true | true | false | false | true | false | true ];
+ input float in1 = [ 36.8125 | -8.25 | 3.5 | 1.0 | 2.0 | -0.5 | 0.0 | 1.0 | -20.125 | 0.0 ];
+ input int in2 = [ -66 | 1 | -192 | 2 | 11 | 0 | 255 | 8 | 5 | -12 ];
+ input vec2 in3 = [ vec2(-0.75, -0.0322580645161) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bool in4 = [ true | false | false | false | false | true | true | true | false | true ];
+ input bvec2 in5 = [ bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 36.8125, -66.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0) | mat4x2(0.0, -8.25, 1.0, -0.75, -0.0322580645161, 0.0, 0.0, 1.0) | mat4x2(1.0, 3.5, -192.0, -32.0, 64.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 1.0, 2.0, 0.0, 0.5, 0.0, 1.0, 1.0) | mat4x2(1.0, 2.0, 11.0, 1.0, 1.25, 0.0, 1.0, 0.0) | mat4x2(0.0, -0.5, 0.0, 1.0, 1.25, 1.0, 0.0, 1.0) | mat4x2(0.0, 0.0, 255.0, -0.5, -2.25, 1.0, 0.0, 0.0) | mat4x2(1.0, 1.0, 8.0, -32.0, 64.0, 1.0, 1.0, 1.0) | mat4x2(0.0, -20.125, 5.0, 0.0, 0.5, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, -12.0, -0.5, -2.25, 1.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_to_mat4x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | false | true | false | true | false | true | true | true | false ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) ];
+ input int in2 = [ -12 | 8 | 2 | 255 | 5 | -192 | 0 | 11 | 1 | -66 ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 1.0, 0.0, -12.0, 1.0, 1.25, 1.125, 1.75) | mat4x2(0.0, 0.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4x2(1.0, 0.0, 0.0, 2.0, -32.0, 64.0, -51.0, 24.0) | mat4x2(0.0, 0.0, 0.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4x2(1.0, 1.0, 0.0, 5.0, -0.5, -2.25, -4.875, 9.0) | mat4x2(0.0, 0.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0) | mat4x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825) | mat4x2(1.0, 0.0, 1.0, 11.0, -32.0, 64.0, -51.0, 24.0) | mat4x2(1.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75) | mat4x2(0.0, 1.0, 1.0, -66.0, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_to_mat4x2
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -8.25 | -20.125 | 3.5 | -0.5 | 2.0 | 36.8125 | 0.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input ivec2 in2 = [ ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ input bool in3 = [ true | true | false | true | true | false | false | false ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 0.0, 1.0, -32.0, 64.0, 1.0) | mat4x2(-8.25, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0) | mat4x2(-20.125, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) | mat4x2(3.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4x2(-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat4x2(2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 0.0) | mat4x2(36.8125, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_to_mat4x3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) ];
+ input vec4 in1 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output mat4x3 out0 = [ mat4x3(-0.5, -2.25, -4.875, 9.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0) | mat4x3(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat4x3(0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat4x3(-0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) | mat4x3(-32.0, 64.0, -51.0, 24.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_to_mat4x3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) ];
+ input ivec4 in2 = [ ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) | mat4x3(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, -2.0, -4.0, 9.0) | mat4x3(0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4x3(-32.0, 64.0, -51.0, 24.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_float_int_int_bool_bool_bool_to_mat4x3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in2 = [ -20.125 | 3.5 | 2.0 | -0.5 | -8.25 | 0.0 | 1.0 | 0.0 | 1.0 | 36.8125 ];
+ input float in3 = [ 0.0 | -8.25 | 36.8125 | 1.0 | 0.0 | -20.125 | 3.5 | 2.0 | -0.5 | 1.0 ];
+ input float in4 = [ 0.0 | 1.0 | 3.5 | -20.125 | 0.0 | 36.8125 | 1.0 | -8.25 | 2.0 | -0.5 ];
+ input int in5 = [ 2 | 8 | 1 | -192 | 0 | -12 | 11 | 255 | 5 | -66 ];
+ input int in6 = [ 2 | -12 | 5 | 8 | 11 | 255 | 0 | -66 | 1 | -192 ];
+ input bool in7 = [ true | true | false | true | false | false | false | true | false | true ];
+ input bool in8 = [ true | false | false | true | true | false | true | true | false | false ];
+ input bool in9 = [ false | true | false | false | false | false | true | true | true | true ];
+ output mat4x3 out0 = [ mat4x3(-0.5, -2.25, 0.0, -2.0, -20.125, 0.0, 0.0, 2.0, 2.0, 1.0, 1.0, 0.0) | mat4x3(0.0, 0.5, -32.0, 64.0, 3.5, -8.25, 1.0, 8.0, -12.0, 1.0, 0.0, 1.0) | mat4x3(0.0, 0.5, 1.0, 1.0, 2.0, 36.8125, 3.5, 1.0, 5.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 1.25, -32.0, 64.0, -0.5, 1.0, -20.125, -192.0, 8.0, 1.0, 1.0, 0.0) | mat4x3(-0.75, -0.0322580645161, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 11.0, 0.0, 1.0, 0.0) | mat4x3(-0.5, -2.25, 0.0, 0.0, 0.0, -20.125, 36.8125, -12.0, 255.0, 0.0, 0.0, 0.0) | mat4x3(-32.0, 64.0, 0.0, 0.0, 1.0, 3.5, 1.0, 11.0, 0.0, 0.0, 1.0, 1.0) | mat4x3(1.0, 1.25, 0.0, -2.0, 0.0, 2.0, -8.25, 255.0, -66.0, 1.0, 1.0, 1.0) | mat4x3(-32.0, 64.0, 0.0, 0.0, 1.0, -0.5, 2.0, 5.0, 1.0, 0.0, 0.0, 1.0) | mat4x3(-0.75, -0.0322580645161, 1.0, 1.0, 36.8125, 1.0, -0.5, -66.0, -192.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec3_bool_bvec3_float_bool_to_mat4x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | true | true | false | false | false ];
+ input float in1 = [ -8.25 | 2.0 | 1.0 | -0.5 | 0.0 | 0.0 | 36.8125 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ 255 | 2 | 11 | 1 | 8 | -192 | 0 | -66 | -12 | 5 ];
+ input vec3 in3 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input bool in4 = [ true | true | false | false | true | false | false | false | true | true ];
+ input bvec3 in5 = [ bvec3(false, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(true, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in6 = [ 1.0 | 0.0 | -0.5 | 36.8125 | 1.0 | -20.125 | 2.0 | 0.0 | -8.25 | 3.5 ];
+ input bool in7 = [ true | true | false | false | false | false | true | true | false | true ];
+ output mat4x3 out0 = [ mat4x3(1.0, -8.25, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat4x3(1.0, 2.0, 2.0, 0.0, 0.5, 0.75, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0) | mat4x3(0.0, 1.0, 11.0, 0.0, 0.5, 0.75, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0) | mat4x3(0.0, -0.5, 1.0, -32.0, 64.0, -51.0, 0.0, 0.0, 1.0, 0.0, 36.8125, 0.0) | mat4x3(1.0, 0.0, 8.0, -0.5, -2.25, -4.875, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0) | mat4x3(1.0, 0.0, -192.0, 1.0, 1.25, 1.125, 0.0, 1.0, 0.0, 0.0, -20.125, 0.0) | mat4x3(1.0, 36.8125, 0.0, -32.0, 64.0, -51.0, 0.0, 1.0, 1.0, 1.0, 2.0, 1.0) | mat4x3(0.0, -20.125, -66.0, 1.0, 1.25, 1.125, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat4x3(0.0, 3.5, -12.0, -0.5, -2.25, -4.875, 1.0, 0.0, 0.0, 0.0, -8.25, 0.0) | mat4x3(0.0, 1.0, 5.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 3.5, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5, in6, in7);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4_int_vec4_bool_float_to_mat4x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | true | false | false | true | false | false ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, false, false, true) ];
+ input int in2 = [ 5 | 11 | 0 | -192 | -66 | 255 | 1 | -12 | 8 | 2 ];
+ input vec4 in3 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input bool in4 = [ false | true | true | false | true | false | true | true | false | false ];
+ input float in5 = [ -20.125 | 0.0 | 1.0 | -0.5 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 0.0, 5.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, -20.125) | mat4x3(1.0, 0.0, 1.0, 0.0, 0.0, 11.0, -32.0, 64.0, -51.0, 24.0, 1.0, 0.0) | mat4x3(1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0, 0.0, -0.5) | mat4x3(1.0, 1.0, 1.0, 1.0, 1.0, -66.0, 1.0, 1.25, 1.125, 1.75, 1.0, 3.5) | mat4x3(0.0, 1.0, 0.0, 0.0, 1.0, 255.0, -32.0, 64.0, -51.0, 24.0, 0.0, -8.25) | mat4x3(0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, -12.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.5, 0.75, 0.825, 0.0, 2.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 0.0, 0.5, 0.75, 0.825, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec4_bool_bool_int_to_mat4x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 36.8125 | -0.5 | 3.5 | 2.0 | 1.0 | -20.125 | 0.0 | 0.0 | -8.25 | 1.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input ivec4 in2 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, -2, -4, 9) ];
+ input bool in3 = [ false | true | false | true | false | false | false | true | true | true ];
+ input bool in4 = [ false | true | false | true | false | true | false | false | true | true ];
+ input int in5 = [ 2 | 1 | 8 | 11 | 255 | 5 | 0 | -66 | -192 | -12 ];
+ output mat4x3 out0 = [ mat4x3(36.8125, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 2.0) | mat4x3(-0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat4x3(3.5, 1.0, 0.0, 0.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 8.0) | mat4x3(2.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 11.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 255.0) | mat4x3(-20.125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 5.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, -66.0) | mat4x3(-8.25, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, -192.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, -12.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_vec4_to_mat4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in3 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ output mat4 out0 = [ mat4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0) | mat4(-32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4(-0.5, -2.25, -4.875, 9.0, -0.5, -2.25, -4.875, 9.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat4(1.0, 1.25, 1.125, 1.75, 1.0, 1.25, 1.125, 1.75, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) | mat4(0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, -0.5, -2.25, -4.875, 9.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_ivec4_to_mat4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in2 = [ ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in3 = [ ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat4 out0 = [ mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_bvec4_bvec4_bvec4_to_mat4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(true, false, false, true) ];
+ input bvec4 in1 = [ bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ input bvec4 in2 = [ bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) ];
+ input bvec4 in3 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_ivec3_bvec3_vec4_ivec2_float_vec2_to_mat4
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 1.0 | 3.5 | 0.0 | -20.125 | 36.8125 | -0.5 | -8.25 ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, -2, -4) ];
+ input bvec3 in2 = [ bvec3(true, false, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input ivec2 in4 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in5 = [ 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 | -20.125 | 1.0 | -0.5 ];
+ input vec2 in6 = [ vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(1.0, 1.25) ];
+ output mat4 out0 = [ mat4(2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, 0.0, 2.0, 0.0, 0.5) | mat4(1.0, -32.0, 64.0, -51.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0, 3.5, -0.5, -2.25) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, -2.0, 36.8125, -32.0, 64.0) | mat4(0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, 0.0, -8.25, 0.0, 0.5) | mat4(-20.125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0, 0.0, -0.75, -0.0322580645161) | mat4(36.8125, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -20.125, -0.5, -2.25) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 1.0, 1.0, 1.25) | mat4(-8.25, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, -2.0, -0.5, 1.0, 1.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_combine
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.html
new file mode 100644
index 0000000000..35da4acd0d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_matrix_to_matrix';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.test
new file mode 100644
index 0000000000..bbf36658fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_matrix_to_matrix.test
@@ -0,0 +1,1952 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group matrix_to_matrix "Matrix to Matrix Conversions"
+
+ case mat4_to_mat4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0, 9.975, -6.542, 0.015625, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0, 9.975, -6.542, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0, 9.975, -6.542, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4x3
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4x2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, -24.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.125, 0.03125, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0) | mat4x2(-18.725, -0.0125, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3x4
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0) | mat3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3x2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0) | mat3x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0) | mat3x2(8.0, -24.0, 16.0, -16.0, 0.0, 0.0) | mat3x2(0.125, 0.03125, 0.0625, 0.015625, 0.0, 0.0) | mat3x2(-18.725, -0.0125, -0.5, 19.975, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2x4
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0) | mat2x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0) | mat2x4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0) | mat2x4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0) | mat2x4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2x3
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0) | mat2x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0) | mat2x3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0) | mat2x3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0) | mat2x3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_to_matrix
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.html
new file mode 100644
index 0000000000..34b523530e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_scalar_to_matrix';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.test
new file mode 100644
index 0000000000..f141323840
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_matrix.test
@@ -0,0 +1,872 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group scalar_to_matrix "Scalar to Matrix Conversions"
+
+ case float_to_mat4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25) | mat4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125) | mat4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat4x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0) | mat4x3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0) | mat4x3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0) | mat4x3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0) | mat4x3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat4x2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(3.5, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0) | mat4x2(-0.5, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0) | mat4x2(-8.25, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0) | mat4x2(-20.125, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0) | mat4x2(36.8125, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0) | mat3x4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0) | mat3x4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0) | mat3x4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0) | mat3x4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5) | mat3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5) | mat3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25) | mat3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125) | mat3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3x2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(3.5, 0.0, 0.0, 3.5, 0.0, 0.0) | mat3x2(-0.5, 0.0, 0.0, -0.5, 0.0, 0.0) | mat3x2(-8.25, 0.0, 0.0, -8.25, 0.0, 0.0) | mat3x2(-20.125, 0.0, 0.0, -20.125, 0.0, 0.0) | mat3x2(36.8125, 0.0, 0.0, 36.8125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2x4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0) | mat2x4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0) | mat2x4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0) | mat2x4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0) | mat2x4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2x3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0) | mat2x3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0) | mat2x3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0) | mat2x3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0) | mat2x3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.5, 0.0, 0.0, 3.5) | mat2(-0.5, 0.0, 0.0, -0.5) | mat2(-8.25, 0.0, 0.0, -8.25) | mat2(-20.125, 0.0, 0.0, -20.125) | mat2(36.8125, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0) | mat4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0) | mat4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0) | mat4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4x3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0) | mat4x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0) | mat4x3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0) | mat4x3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0) | mat4x3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0) | mat4x3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0) | mat4x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4x2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(5.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(11.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-12.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-66.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-192.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3x4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0) | mat3x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat3x4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0) | mat3x4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0) | mat3x4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0) | mat3x4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0) | mat3x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0) | mat3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0) | mat3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0) | mat3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3x2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(5.0, 0.0, 0.0, 5.0, 0.0, 0.0) | mat3x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat3x2(11.0, 0.0, 0.0, 11.0, 0.0, 0.0) | mat3x2(-12.0, 0.0, 0.0, -12.0, 0.0, 0.0) | mat3x2(-66.0, 0.0, 0.0, -66.0, 0.0, 0.0) | mat3x2(-192.0, 0.0, 0.0, -192.0, 0.0, 0.0) | mat3x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2x4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0) | mat2x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat2x4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0) | mat2x4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0) | mat2x4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0) | mat2x4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0) | mat2x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2x3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0) | mat2x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat2x3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0) | mat2x3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0) | mat2x3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0) | mat2x3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0) | mat2x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(5.0, 0.0, 0.0, 5.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(11.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, -12.0) | mat2(-66.0, 0.0, 0.0, -66.0) | mat2(-192.0, 0.0, 0.0, -192.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0) | mat4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0) | mat4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0) | mat4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0) | mat4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4x3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0) | mat4x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0) | mat4x3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0) | mat4x3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0) | mat4x3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0) | mat4x3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0) | mat4x3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0) | mat4x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4x2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(3.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(9.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(12.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(10.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(45.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(193.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3x4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0) | mat3x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat3x4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0) | mat3x4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0) | mat3x4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0) | mat3x4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0) | mat3x4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0) | mat3x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 9.0) | mat3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 12.0) | mat3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0) | mat3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 45.0) | mat3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 193.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3x2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(3.0, 0.0, 0.0, 3.0, 0.0, 0.0) | mat3x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat3x2(9.0, 0.0, 0.0, 9.0, 0.0, 0.0) | mat3x2(12.0, 0.0, 0.0, 12.0, 0.0, 0.0) | mat3x2(10.0, 0.0, 0.0, 10.0, 0.0, 0.0) | mat3x2(45.0, 0.0, 0.0, 45.0, 0.0, 0.0) | mat3x2(193.0, 0.0, 0.0, 193.0, 0.0, 0.0) | mat3x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2x4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0) | mat2x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat2x4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0) | mat2x4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0) | mat2x4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0) | mat2x4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0) | mat2x4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0) | mat2x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2x3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0) | mat2x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat2x3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0) | mat2x3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0) | mat2x3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0) | mat2x3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0) | mat2x3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0) | mat2x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.0, 0.0, 0.0, 3.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(9.0, 0.0, 0.0, 9.0) | mat2(12.0, 0.0, 0.0, 12.0) | mat2(10.0, 0.0, 0.0, 10.0) | mat2(45.0, 0.0, 0.0, 45.0) | mat2(193.0, 0.0, 0.0, 193.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3x2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2x4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2x3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_matrix
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.html
new file mode 100644
index 0000000000..bc29993f90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_scalar_to_scalar';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.test
new file mode 100644
index 0000000000..07b4112d54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_scalar.test
@@ -0,0 +1,392 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group scalar_to_scalar "Scalar to Scalar Conversions"
+
+ case float_to_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_int
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 0 | -8 | -20 | 36 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bool
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_float
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 5.0 | 8.0 | 11.0 | -12.0 | -66.0 | -192.0 | 255.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output int out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bool
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_float
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output float out0 = [ 0.0 | 2.0 | 3.0 | 8.0 | 9.0 | 12.0 | 10.0 | 45.0 | 193.0 | 255.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_int
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output int out0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bool
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_float
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output float out0 = [ 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_int
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output int out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uint
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uint out0 = [ 0 | 1 | 2 | 3 | 0 | 8 | 20 | 36 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uint
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uint out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uint
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uint out0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uint
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uint out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_scalar
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.html
new file mode 100644
index 0000000000..cf3838f8aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_scalar_to_vector';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.test
new file mode 100644
index 0000000000..ae9e8b53d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_scalar_to_vector.test
@@ -0,0 +1,1160 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group scalar_to_vector "Scalar to Vector Conversions"
+
+ case float_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(3.5, 3.5) | vec2(-0.5, -0.5) | vec2(-8.25, -8.25) | vec2(-20.125, -20.125) | vec2(36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(3.5, 3.5, 3.5) | vec3(-0.5, -0.5, -0.5) | vec3(-8.25, -8.25, -8.25) | vec3(-20.125, -20.125, -20.125) | vec3(36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.5, 3.5, 3.5, 3.5) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-8.25, -8.25, -8.25, -8.25) | vec4(-20.125, -20.125, -20.125, -20.125) | vec4(36.8125, 36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(3, 3) | ivec2(0, 0) | ivec2(-8, -8) | ivec2(-20, -20) | ivec2(36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(0, 0, 0) | ivec3(-8, -8, -8) | ivec3(-20, -20, -20) | ivec3(36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(0, 0, 0, 0) | ivec4(-8, -8, -8, -8) | ivec4(-20, -20, -20, -20) | ivec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(5.0, 5.0) | vec2(8.0, 8.0) | vec2(11.0, 11.0) | vec2(-12.0, -12.0) | vec2(-66.0, -66.0) | vec2(-192.0, -192.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(5.0, 5.0, 5.0) | vec3(8.0, 8.0, 8.0) | vec3(11.0, 11.0, 11.0) | vec3(-12.0, -12.0, -12.0) | vec3(-66.0, -66.0, -66.0) | vec3(-192.0, -192.0, -192.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(5.0, 5.0, 5.0, 5.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(11.0, 11.0, 11.0, 11.0) | vec4(-12.0, -12.0, -12.0, -12.0) | vec4(-66.0, -66.0, -66.0, -66.0) | vec4(-192.0, -192.0, -192.0, -192.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(5, 5) | ivec2(8, 8) | ivec2(11, 11) | ivec2(-12, -12) | ivec2(-66, -66) | ivec2(-192, -192) | ivec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(5, 5, 5) | ivec3(8, 8, 8) | ivec3(11, 11, 11) | ivec3(-12, -12, -12) | ivec3(-66, -66, -66) | ivec3(-192, -192, -192) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(5, 5, 5, 5) | ivec4(8, 8, 8, 8) | ivec4(11, 11, 11, 11) | ivec4(-12, -12, -12, -12) | ivec4(-66, -66, -66, -66) | ivec4(-192, -192, -192, -192) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(2.0, 2.0) | vec2(3.0, 3.0) | vec2(8.0, 8.0) | vec2(9.0, 9.0) | vec2(12.0, 12.0) | vec2(10.0, 10.0) | vec2(45.0, 45.0) | vec2(193.0, 193.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(2.0, 2.0, 2.0) | vec3(3.0, 3.0, 3.0) | vec3(8.0, 8.0, 8.0) | vec3(9.0, 9.0, 9.0) | vec3(12.0, 12.0, 12.0) | vec3(10.0, 10.0, 10.0) | vec3(45.0, 45.0, 45.0) | vec3(193.0, 193.0, 193.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.0, 3.0, 3.0, 3.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(12.0, 12.0, 12.0, 12.0) | vec4(10.0, 10.0, 10.0, 10.0) | vec4(45.0, 45.0, 45.0, 45.0) | vec4(193.0, 193.0, 193.0, 193.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(2, 2) | ivec2(3, 3) | ivec2(8, 8) | ivec2(9, 9) | ivec2(12, 12) | ivec2(10, 10) | ivec2(45, 45) | ivec2(193, 193) | ivec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(8, 8, 8) | ivec3(9, 9, 9) | ivec3(12, 12, 12) | ivec3(10, 10, 10) | ivec3(45, 45, 45) | ivec3(193, 193, 193) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(8, 8, 8, 8) | ivec4(9, 9, 9, 9) | ivec4(12, 12, 12, 12) | ivec4(10, 10, 10, 10) | ivec4(45, 45, 45, 45) | ivec4(193, 193, 193, 193) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(2, 2) | uvec2(3, 3) | uvec2(0, 0) | uvec2(8, 8) | uvec2(20, 20) | uvec2(36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(2, 2, 2) | uvec3(3, 3, 3) | uvec3(0, 0, 0) | uvec3(8, 8, 8) | uvec3(20, 20, 20) | uvec3(36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(2, 2, 2, 2) | uvec4(3, 3, 3, 3) | uvec4(0, 0, 0, 0) | uvec4(8, 8, 8, 8) | uvec4(20, 20, 20, 20) | uvec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(2, 2) | uvec2(5, 5) | uvec2(8, 8) | uvec2(11, 11) | uvec2(12, 12) | uvec2(66, 66) | uvec2(192, 192) | uvec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(2, 2, 2) | uvec3(5, 5, 5) | uvec3(8, 8, 8) | uvec3(11, 11, 11) | uvec3(12, 12, 12) | uvec3(66, 66, 66) | uvec3(192, 192, 192) | uvec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(2, 2, 2, 2) | uvec4(5, 5, 5, 5) | uvec4(8, 8, 8, 8) | uvec4(11, 11, 11, 11) | uvec4(12, 12, 12, 12) | uvec4(66, 66, 66, 66) | uvec4(192, 192, 192, 192) | uvec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(2, 2) | uvec2(3, 3) | uvec2(8, 8) | uvec2(9, 9) | uvec2(12, 12) | uvec2(10, 10) | uvec2(45, 45) | uvec2(193, 193) | uvec2(255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(2, 2, 2) | uvec3(3, 3, 3) | uvec3(8, 8, 8) | uvec3(9, 9, 9) | uvec3(12, 12, 12) | uvec3(10, 10, 10) | uvec3(45, 45, 45) | uvec3(193, 193, 193) | uvec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(2, 2, 2, 2) | uvec4(3, 3, 3, 3) | uvec4(8, 8, 8, 8) | uvec4(9, 9, 9, 9) | uvec4(12, 12, 12, 12) | uvec4(10, 10, 10, 10) | uvec4(45, 45, 45, 45) | uvec4(193, 193, 193, 193) | uvec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec3 out0 = [ uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec4 out0 = [ uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_vector
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.html
new file mode 100644
index 0000000000..d53c1ae55c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_combine';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.test
new file mode 100644
index 0000000000..900b5b70d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_combine.test
@@ -0,0 +1,3480 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_combine "Vector Combine Constructors"
+
+ case vec2_vec2_to_vec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, -32.0, 64.0) | vec4(-32.0, 64.0, 1.0, 1.25) | vec4(1.0, 1.25, 0.0, 0.5) | vec4(0.0, 0.5, -0.5, -2.25) | vec4(-0.75, -0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_ivec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output ivec4 out0 = [ ivec4(0, -2, -32, 64) | ivec4(-32, 64, 1, 1) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_bvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_vec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 1.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) | vec4(1.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_ivec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 1, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 1) | ivec4(0, 0, 1, 1) | ivec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_bvec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, false, false, false) | bvec4(false, true, false, true) | bvec4(false, false, true, true) | bvec4(true, true, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_vec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 3.5, 3.5) | vec4(0.0, 36.8125, 36.8125, 36.8125) | vec4(-0.5, -8.25, -8.25, 1.0) | vec4(-8.25, 2.0, 1.0, -8.25) | vec4(3.5, 3.5, 2.0, 2.0) | vec4(-20.125, 1.0, 0.0, 0.0) | vec4(36.8125, -20.125, -20.125, -0.5) | vec4(2.0, -0.5, -0.5, -20.125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_ivec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 3, 3) | ivec4(0, 36, 36, 36) | ivec4(0, -8, -8, 1) | ivec4(-8, 2, 1, -8) | ivec4(3, 3, 2, 2) | ivec4(-20, 1, 0, 0) | ivec4(36, -20, -20, 0) | ivec4(2, 0, 0, -20) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_bvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output vec4 out0 = [ vec4(-12.0, 2.0, 11.0, -192.0) | vec4(-66.0, 5.0, 255.0, -66.0) | vec4(2.0, -66.0, 5.0, 8.0) | vec4(5.0, 11.0, 8.0, -12.0) | vec4(8.0, -192.0, 2.0, 1.0) | vec4(-192.0, 8.0, -192.0, 2.0) | vec4(255.0, -12.0, -12.0, 0.0) | vec4(1.0, 1.0, -66.0, 255.0) | vec4(0.0, 255.0, 1.0, 5.0) | vec4(11.0, 0.0, 0.0, 11.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output ivec4 out0 = [ ivec4(-12, 2, 11, -192) | ivec4(-66, 5, 255, -66) | ivec4(2, -66, 5, 8) | ivec4(5, 11, 8, -12) | ivec4(8, -192, 2, 1) | ivec4(-192, 8, -192, 2) | ivec4(255, -12, -12, 0) | ivec4(1, 1, -66, 255) | ivec4(0, 255, 1, 5) | ivec4(11, 0, 0, 11) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_vec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output vec4 out0 = [ vec4(193.0, 12.0, 9.0, 3.0) | vec4(3.0, 45.0, 8.0, 9.0) | vec4(255.0, 193.0, 12.0, 12.0) | vec4(8.0, 2.0, 2.0, 2.0) | vec4(10.0, 8.0, 255.0, 255.0) | vec4(9.0, 255.0, 45.0, 193.0) | vec4(2.0, 0.0, 3.0, 0.0) | vec4(12.0, 3.0, 0.0, 10.0) | vec4(0.0, 9.0, 193.0, 45.0) | vec4(45.0, 10.0, 10.0, 8.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_ivec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output ivec4 out0 = [ ivec4(193, 12, 9, 3) | ivec4(3, 45, 8, 9) | ivec4(255, 193, 12, 12) | ivec4(8, 2, 2, 2) | ivec4(10, 8, 255, 255) | ivec4(9, 255, 45, 193) | ivec4(2, 0, 3, 0) | ivec4(12, 3, 0, 10) | ivec4(0, 9, 193, 45) | ivec4(45, 10, 10, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_bvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, true, false) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 0.0, 0.0) | vec4(0.0, 0.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output ivec4 out0 = [ ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(false, false, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output vec4 out0 = [ vec4(1.0, 36.8125, -66.0, 1.0) | vec4(1.0, 0.0, 2.0, 1.0) | vec4(0.0, -8.25, 255.0, 0.0) | vec4(0.0, 1.0, 11.0, 0.0) | vec4(0.0, -0.5, 1.0, 1.0) | vec4(1.0, 0.0, 8.0, 1.0) | vec4(0.0, 2.0, -192.0, 0.0) | vec4(0.0, -20.125, -12.0, 1.0) | vec4(1.0, 3.5, 0.0, 0.0) | vec4(1.0, 1.0, 5.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output ivec4 out0 = [ ivec4(1, 36, -66, 1) | ivec4(1, 0, 2, 1) | ivec4(0, -8, 255, 0) | ivec4(0, 1, 11, 0) | ivec4(0, 0, 1, 1) | ivec4(1, 0, 8, 1) | ivec4(0, 2, -192, 0) | ivec4(0, -20, -12, 1) | ivec4(1, 3, 0, 0) | ivec4(1, 1, 5, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(false, true, true, false) | bvec4(false, true, true, false) | bvec4(false, true, true, true) | bvec4(true, false, true, true) | bvec4(false, true, true, false) | bvec4(false, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_vec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(-0.75, -0.0322580645161, 0.0, -2.0) | vec4(-0.5, -2.25, 0.0, 0.0) | vec4(-32.0, 64.0, -32.0, 64.0) | vec4(1.0, 1.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_ivec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, 64) | ivec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_bvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(false, true, false, false) | bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_vec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output vec4 out0 = [ vec4(-0.75, -0.0322580645161, 0.0, 1.0) | vec4(-32.0, 64.0, 0.0, 0.0) | vec4(1.0, 1.25, 0.0, 0.0) | vec4(0.0, 0.5, 1.0, 1.0) | vec4(-0.5, -2.25, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_ivec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 1) | ivec4(-32, 64, 0, 0) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) | ivec4(0, -2, 1, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_bvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output bvec4 out0 = [ bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(true, true, false, false) | bvec4(false, true, true, true) | bvec4(true, true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_vec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, -0.5) | vec4(0.0, 0.0, 0.0, 3.5) | vec4(0.0, 1.0, 0.0, 2.0) | vec4(1.0, 1.0, 1.0, 0.0) | vec4(0.0, 0.0, 0.0, -8.25) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(1.0, 0.0, 0.0, 36.8125) | vec4(0.0, 1.0, 0.0, -20.125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_ivec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 0) | ivec4(0, 0, 0, 3) | ivec4(0, 1, 0, 2) | ivec4(1, 1, 1, 0) | ivec4(0, 0, 0, -8) | ivec4(0, 0, 0, 1) | ivec4(1, 0, 0, 36) | ivec4(0, 1, 0, -20) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_bvec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, true) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_vec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output vec4 out0 = [ vec4(-32.0, 64.0, -51.0, -0.5) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.0) | vec4(1.0, 1.25, 1.125, 3.5) | vec4(-0.5, -2.25, -4.875, -20.125) | vec4(0.0, 0.5, 0.75, 2.0) | vec4(-0.5, -2.25, -4.875, -8.25) | vec4(0.0, 0.5, 0.75, 1.0) | vec4(1.0, 1.25, 1.125, 36.8125) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_ivec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(-32, 64, -51, 0) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 3) | ivec4(0, -2, -4, -20) | ivec4(0, 0, 0, 2) | ivec4(0, -2, -4, -8) | ivec4(0, 0, 0, 1) | ivec4(1, 1, 1, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_bvec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output vec4 out0 = [ vec4(-12.0, 0.0, -2.0, 1.0) | vec4(11.0, -32.0, 64.0, 11.0) | vec4(8.0, 0.0, 0.0, 2.0) | vec4(255.0, 0.0, -2.0, -66.0) | vec4(0.0, 1.0, 1.0, -192.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(-66.0, -32.0, 64.0, -12.0) | vec4(2.0, 1.0, 1.0, 255.0) | vec4(-192.0, 0.0, 0.0, 5.0) | vec4(5.0, 0.0, 0.0, 8.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output ivec4 out0 = [ ivec4(-12, 0, -2, 1) | ivec4(11, -32, 64, 11) | ivec4(8, 0, 0, 2) | ivec4(255, 0, -2, -66) | ivec4(0, 1, 1, -192) | ivec4(1, 0, 0, 0) | ivec4(-66, -32, 64, -12) | ivec4(2, 1, 1, 255) | ivec4(-192, 0, 0, 5) | ivec4(5, 0, 0, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_vec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, -32.0, 64.0) | vec4(0.0, 2.0, 0.0, 0.0) | vec4(0.0, 3.5, 0.0, 0.0) | vec4(1.0, -20.125, 0.0, -2.0) | vec4(1.0, -0.5, 0.0, -2.0) | vec4(1.0, 36.8125, 0.0, 0.0) | vec4(0.0, -8.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_ivec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, -32, 64) | ivec4(0, 2, 0, 0) | ivec4(0, 3, 0, 0) | ivec4(1, -20, 0, -2) | ivec4(1, 0, 0, -2) | ivec4(1, 36, 0, 0) | ivec4(0, -8, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_bvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, true, true) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, true, false, true) | bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(false, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_vec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 0.0) | vec4(-20.125, 0.0, 0.0, 0.0) | vec4(-8.25, 1.0, 1.0, 1.0) | vec4(-0.5, 0.0, 2.0, 4.0) | vec4(0.0, 0.0, 0.0, 0.0) | vec4(2.0, 1.0, 1.0, 1.0) | vec4(3.5, 0.0, 2.0, 4.0) | vec4(36.8125, 32.0, 64.0, 51.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_ivec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 0) | ivec4(-20, 0, 0, 0) | ivec4(-8, 1, 1, 1) | ivec4(0, 0, 2, 4) | ivec4(0, 0, 0, 0) | ivec4(2, 1, 1, 1) | ivec4(3, 0, 2, 4) | ivec4(36, 32, 64, 51) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_bvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output bvec4 out0 = [ bvec4(true, false, false, false) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_vec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 2.0, 0.0) | vec4(-192.0, 1.0, 1.0, 0.0) | vec4(-66.0, 0.0, 0.0, 1.0) | vec4(-12.0, 0.0, 2.0, 1.0) | vec4(0.0, 32.0, 64.0, 1.0) | vec4(2.0, 0.0, 0.0, 1.0) | vec4(11.0, 32.0, 64.0, 1.0) | vec4(8.0, 0.0, 0.0, 0.0) | vec4(255.0, 1.0, 1.0, 0.0) | vec4(5.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_ivec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output ivec4 out0 = [ ivec4(1, 0, 2, 0) | ivec4(-192, 1, 1, 0) | ivec4(-66, 0, 0, 1) | ivec4(-12, 0, 2, 1) | ivec4(0, 32, 64, 1) | ivec4(2, 0, 0, 1) | ivec4(11, 32, 64, 1) | ivec4(8, 0, 0, 0) | ivec4(255, 1, 1, 0) | ivec4(5, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_bvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output bvec4 out0 = [ bvec4(true, false, true, false) | bvec4(true, true, true, false) | bvec4(true, false, false, true) | bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, false, false, false) | bvec4(true, true, true, false) | bvec4(true, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_uvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.0, 0.5) | vec2(0.5, 2.25) | vec2(1.0, 1.25) ];
+ input vec2 in1 = [ vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(32.0, 64.0) | vec2(0.0, 0.5) | vec2(0.75, 0.0322580645161) ];
+ output uvec4 out0 = [ uvec4(32, 64, 0, 2) | uvec4(0, 0, 1, 1) | uvec4(0, 0, 32, 64) | uvec4(0, 2, 0, 0) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_uvec4
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) ];
+ output uvec4 out0 = [ uvec4(1, 0, 1, 1) | uvec4(0, 1, 0, 0) | uvec4(1, 1, 1, 0) | uvec4(0, 0, 0, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_uvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 36.8125 | 0.0 | 20.125 | 1.0 | 0.5 | 8.25 | 3.5 ];
+ input float in1 = [ 1.0 | 8.25 | 2.0 | 20.125 | 36.8125 | 0.0 | 0.5 | 3.5 ];
+ input float in2 = [ 0.0 | 8.25 | 2.0 | 1.0 | 36.8125 | 20.125 | 0.5 | 3.5 ];
+ input float in3 = [ 1.0 | 8.25 | 0.0 | 2.0 | 20.125 | 3.5 | 0.5 | 36.8125 ];
+ output uvec4 out0 = [ uvec4(2, 1, 0, 1) | uvec4(36, 8, 8, 8) | uvec4(0, 2, 2, 0) | uvec4(20, 20, 1, 2) | uvec4(1, 36, 36, 20) | uvec4(0, 0, 20, 3) | uvec4(8, 0, 0, 0) | uvec4(3, 3, 3, 36) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 192 | 2 | 12 | 11 | 0 | 8 | 5 | 66 | 1 | 255 ];
+ input int in1 = [ 66 | 12 | 5 | 1 | 0 | 192 | 8 | 255 | 11 | 2 ];
+ input int in2 = [ 192 | 5 | 1 | 66 | 255 | 11 | 8 | 12 | 2 | 0 ];
+ input int in3 = [ 255 | 5 | 11 | 12 | 2 | 1 | 66 | 0 | 8 | 192 ];
+ output uvec4 out0 = [ uvec4(192, 66, 192, 255) | uvec4(2, 12, 5, 5) | uvec4(12, 5, 1, 11) | uvec4(11, 1, 66, 12) | uvec4(0, 0, 255, 2) | uvec4(8, 192, 11, 1) | uvec4(5, 8, 8, 66) | uvec4(66, 255, 12, 0) | uvec4(1, 11, 2, 8) | uvec4(255, 2, 0, 192) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_uvec4
+ version 300 es
+ values
+ {
+ input uint in0 = [ 255 | 8 | 3 | 193 | 45 | 2 | 0 | 12 | 9 | 10 ];
+ input uint in1 = [ 255 | 45 | 0 | 12 | 2 | 10 | 8 | 9 | 193 | 3 ];
+ input uint in2 = [ 3 | 0 | 2 | 9 | 12 | 10 | 255 | 45 | 193 | 8 ];
+ input uint in3 = [ 2 | 255 | 10 | 193 | 8 | 12 | 3 | 9 | 0 | 45 ];
+ output uvec4 out0 = [ uvec4(255, 255, 3, 2) | uvec4(8, 45, 0, 255) | uvec4(3, 0, 2, 10) | uvec4(193, 12, 9, 193) | uvec4(45, 2, 12, 8) | uvec4(2, 10, 10, 12) | uvec4(0, 8, 255, 3) | uvec4(12, 9, 45, 9) | uvec4(9, 193, 193, 0) | uvec4(10, 3, 8, 45) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ true | false ];
+ output uvec4 out0 = [ uvec4(0, 0, 1, 1) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | false | true | false | true | true | true | false | false ];
+ input float in1 = [ 20.125 | 0.0 | 1.0 | 3.5 | 1.0 | 0.0 | 0.5 | 8.25 | 2.0 | 36.8125 ];
+ input int in2 = [ 66 | 192 | 1 | 2 | 5 | 11 | 8 | 12 | 255 | 0 ];
+ input bool in3 = [ true | true | true | true | false | true | false | false | false | false ];
+ output uvec4 out0 = [ uvec4(1, 20, 66, 1) | uvec4(0, 0, 192, 1) | uvec4(0, 1, 1, 1) | uvec4(1, 3, 2, 1) | uvec4(0, 1, 5, 0) | uvec4(1, 0, 11, 1) | uvec4(1, 0, 8, 0) | uvec4(1, 8, 12, 0) | uvec4(0, 2, 255, 0) | uvec4(0, 36, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_uvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.0, 0.5) ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) | ivec2(0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 2, 1, 1) | uvec4(1, 1, 0, 2) | uvec4(32, 64, 32, 64) | uvec4(0, 0, 0, 0) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_uvec4
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.5, 2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(true, true) ];
+ output uvec4 out0 = [ uvec4(32, 64, 0, 0) | uvec4(0, 0, 0, 0) | uvec4(0, 2, 1, 0) | uvec4(0, 0, 0, 1) | uvec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_uvec4
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ 2.0 | 0.0 | 36.8125 | 0.5 | 1.0 | 8.25 | 3.5 | 20.125 ];
+ output uvec4 out0 = [ uvec4(1, 0, 0, 2) | uvec4(1, 1, 1, 0) | uvec4(0, 1, 0, 36) | uvec4(0, 0, 0, 0) | uvec4(0, 0, 0, 1) | uvec4(0, 1, 0, 8) | uvec4(1, 0, 0, 3) | uvec4(0, 0, 0, 20) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_uvec4
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 2.25, 4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(1.0, 1.25, 1.125) | vec3(0.75, 0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) ];
+ input float in1 = [ 8.25 | 1.0 | 0.0 | 36.8125 | 2.0 | 0.5 | 20.125 | 3.5 ];
+ output uvec4 out0 = [ uvec4(0, 2, 4, 8) | uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) | uvec4(0, 2, 4, 36) | uvec4(32, 64, 51, 2) | uvec4(1, 1, 1, 0) | uvec4(0, 0, 0, 20) | uvec4(0, 0, 0, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | 1 | 11 | 192 | 255 | 12 | 66 | 2 | 0 | 5 ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(32, 64) | ivec2(0, 2) | ivec2(0, 2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(32, 64) | ivec2(0, 0) ];
+ input int in2 = [ 2 | 192 | 12 | 0 | 8 | 1 | 66 | 255 | 11 | 5 ];
+ output uvec4 out0 = [ uvec4(8, 1, 1, 2) | uvec4(1, 0, 0, 192) | uvec4(11, 1, 1, 12) | uvec4(192, 32, 64, 0) | uvec4(255, 0, 2, 8) | uvec4(12, 0, 2, 1) | uvec4(66, 0, 0, 66) | uvec4(2, 0, 0, 255) | uvec4(0, 32, 64, 11) | uvec4(5, 0, 0, 5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_uvec4
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | false | true ];
+ input float in1 = [ 8.25 | 0.5 | 2.0 | 20.125 | 0.0 | 36.8125 | 3.5 | 1.0 ];
+ input ivec2 in2 = [ ivec2(32, 64) | ivec2(1, 1) | ivec2(0, 2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output uvec4 out0 = [ uvec4(1, 8, 32, 64) | uvec4(1, 0, 1, 1) | uvec4(0, 2, 0, 2) | uvec4(0, 20, 0, 0) | uvec4(1, 0, 0, 0) | uvec4(0, 36, 0, 2) | uvec4(0, 3, 1, 1) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_uvec4
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 20.125 | 1.0 | 0.5 | 3.5 | 2.0 | 36.8125 | 0.0 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 2, 4) | uvec3(1, 1, 1) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(8, 0, 0, 0) | uvec4(20, 0, 0, 0) | uvec4(1, 0, 2, 4) | uvec4(0, 32, 64, 51) | uvec4(3, 0, 2, 4) | uvec4(2, 1, 1, 1) | uvec4(36, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_uvec4
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | 1 | 11 | 66 | 192 | 12 | 8 | 255 | 0 | 5 ];
+ input uvec2 in1 = [ uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(1, 1) | uvec2(32, 64) | uvec2(0, 0) ];
+ input bool in2 = [ true | false | false | false | false | true | true | true | false | true ];
+ output uvec4 out0 = [ uvec4(2, 1, 1, 1) | uvec4(1, 0, 0, 0) | uvec4(11, 0, 0, 0) | uvec4(66, 0, 2, 0) | uvec4(192, 0, 0, 0) | uvec4(12, 0, 2, 1) | uvec4(8, 32, 64, 1) | uvec4(255, 1, 1, 1) | uvec4(0, 32, 64, 0) | uvec4(5, 0, 0, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_vec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output vec3 out0 = [ vec3(-0.5, 2.0, 1.0) | vec3(1.0, -20.125, 3.5) | vec3(3.5, 3.5, 2.0) | vec3(-8.25, 36.8125, -8.25) | vec3(36.8125, -8.25, -20.125) | vec3(0.0, 1.0, -0.5) | vec3(2.0, -0.5, 36.8125) | vec3(-20.125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_ivec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output ivec3 out0 = [ ivec3(0, 2, 1) | ivec3(1, -20, 3) | ivec3(3, 3, 2) | ivec3(-8, 36, -8) | ivec3(36, -8, -20) | ivec3(0, 1, 0) | ivec3(2, 0, 36) | ivec3(-20, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_bvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_vec3
+ version 300 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output vec3 out0 = [ vec3(-192.0, 5.0, -192.0) | vec3(5.0, 1.0, 1.0) | vec3(-12.0, 8.0, 2.0) | vec3(0.0, 0.0, 5.0) | vec3(11.0, 2.0, -12.0) | vec3(8.0, -192.0, 8.0) | vec3(1.0, -12.0, 11.0) | vec3(-66.0, 255.0, 0.0) | vec3(255.0, -66.0, 255.0) | vec3(2.0, 11.0, -66.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_ivec3
+ version 300 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output ivec3 out0 = [ ivec3(-192, 5, -192) | ivec3(5, 1, 1) | ivec3(-12, 8, 2) | ivec3(0, 0, 5) | ivec3(11, 2, -12) | ivec3(8, -192, 8) | ivec3(1, -12, 11) | ivec3(-66, 255, 0) | ivec3(255, -66, 255) | ivec3(2, 11, -66) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_bvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_vec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output vec3 out0 = [ vec3(8.0, 193.0, 12.0) | vec3(45.0, 2.0, 2.0) | vec3(2.0, 9.0, 193.0) | vec3(3.0, 8.0, 255.0) | vec3(255.0, 0.0, 8.0) | vec3(193.0, 255.0, 10.0) | vec3(12.0, 45.0, 45.0) | vec3(0.0, 3.0, 0.0) | vec3(9.0, 10.0, 3.0) | vec3(10.0, 12.0, 9.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_ivec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output ivec3 out0 = [ ivec3(8, 193, 12) | ivec3(45, 2, 2) | ivec3(2, 9, 193) | ivec3(3, 8, 255) | ivec3(255, 0, 8) | ivec3(193, 255, 10) | ivec3(12, 45, 45) | ivec3(0, 3, 0) | ivec3(9, 10, 3) | ivec3(10, 12, 9) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_bvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 8.0) | vec3(1.0, 36.8125, -192.0) | vec3(0.0, 0.0, -66.0) | vec3(0.0, -8.25, 2.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 3.5, -12.0) | vec3(1.0, 1.0, 11.0) | vec3(0.0, -0.5, 255.0) | vec3(0.0, -20.125, 5.0) | vec3(1.0, 2.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output ivec3 out0 = [ ivec3(1, 0, 8) | ivec3(1, 36, -192) | ivec3(0, 0, -66) | ivec3(0, -8, 2) | ivec3(1, 1, 1) | ivec3(0, 3, -12) | ivec3(1, 1, 11) | ivec3(0, 0, 255) | ivec3(0, -20, 5) | ivec3(1, 2, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(false, true, true) | bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_vec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.25, 0.0) | vec3(-0.75, -0.0322580645161, 1.0) | vec3(-32.0, 64.0, 1.0) | vec3(-0.5, -2.25, 1.0) | vec3(0.0, 0.5, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_ivec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 0) | ivec3(0, 0, 1) | ivec3(-32, 64, 1) | ivec3(0, -2, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_bvec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_vec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, -20.125) | vec3(0.0, 1.0, 2.0) | vec3(0.0, 1.0, 36.8125) | vec3(1.0, 0.0, 1.0) | vec3(0.0, 0.0, 3.5) | vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, -8.25) | vec3(0.0, 0.0, -0.5) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output ivec3 out0 = [ ivec3(1, 0, -20) | ivec3(0, 1, 2) | ivec3(0, 1, 36) | ivec3(1, 0, 1) | ivec3(0, 0, 3) | ivec3(0, 0, 0) | ivec3(1, 1, -8) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, true) | bvec3(false, true, true) | bvec3(true, false, true) | bvec3(false, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_vec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, -66.0) | vec3(0.0, 0.0, 255.0) | vec3(1.0, 0.0, 8.0) | vec3(0.0, 0.0, -192.0) | vec3(0.0, 1.0, 2.0) | vec3(1.0, 0.0, 5.0) | vec3(0.0, 1.0, 11.0) | vec3(0.0, 0.0, -12.0) | vec3(1.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, -66) | ivec3(0, 0, 255) | ivec3(1, 0, 8) | ivec3(0, 0, -192) | ivec3(0, 1, 2) | ivec3(1, 0, 5) | ivec3(0, 1, 11) | ivec3(0, 0, -12) | ivec3(1, 1, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, false, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(true, false, true) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_vec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, -2.0) | vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 1.0) | vec3(1.0, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_ivec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output ivec3 out0 = [ ivec3(1, 0, -2) | ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 1) | ivec3(1, -32, 64) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_bvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_vec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output vec3 out0 = [ vec3(-20.125, 0.0, 0.0) | vec3(36.8125, 0.0, 2.0) | vec3(-8.25, 32.0, 64.0) | vec3(2.0, 0.0, 0.0) | vec3(-0.5, 0.0, 2.0) | vec3(0.0, 0.0, 0.0) | vec3(3.5, 1.0, 1.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_ivec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output ivec3 out0 = [ ivec3(-20, 0, 0) | ivec3(36, 0, 2) | ivec3(-8, 32, 64) | ivec3(2, 0, 0) | ivec3(0, 0, 2) | ivec3(0, 0, 0) | ivec3(3, 1, 1) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_bvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(true, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_uvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 20.125 | 2.0 | 3.5 | 0.5 | 36.8125 | 1.0 | 0.0 ];
+ input float in1 = [ 1.0 | 0.0 | 3.5 | 36.8125 | 8.25 | 2.0 | 0.5 | 20.125 ];
+ input float in2 = [ 20.125 | 0.5 | 8.25 | 36.8125 | 1.0 | 0.0 | 3.5 | 2.0 ];
+ output uvec3 out0 = [ uvec3(8, 1, 20) | uvec3(20, 0, 0) | uvec3(2, 3, 8) | uvec3(3, 36, 36) | uvec3(0, 8, 1) | uvec3(36, 2, 0) | uvec3(1, 0, 3) | uvec3(0, 20, 2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_uvec3
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 255 | 192 | 2 | 5 | 12 | 0 | 11 | 8 | 66 ];
+ input int in1 = [ 192 | 66 | 5 | 8 | 11 | 1 | 0 | 255 | 12 | 2 ];
+ input int in2 = [ 192 | 5 | 1 | 11 | 66 | 8 | 12 | 0 | 2 | 255 ];
+ output uvec3 out0 = [ uvec3(1, 192, 192) | uvec3(255, 66, 5) | uvec3(192, 5, 1) | uvec3(2, 8, 11) | uvec3(5, 11, 66) | uvec3(12, 1, 8) | uvec3(0, 0, 12) | uvec3(11, 255, 0) | uvec3(8, 12, 2) | uvec3(66, 2, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_uvec3
+ version 300 es
+ values
+ {
+ input uint in0 = [ 193 | 9 | 45 | 255 | 2 | 0 | 10 | 8 | 12 | 3 ];
+ input uint in1 = [ 3 | 45 | 2 | 9 | 10 | 0 | 8 | 12 | 255 | 193 ];
+ input uint in2 = [ 2 | 3 | 9 | 10 | 255 | 8 | 12 | 0 | 193 | 45 ];
+ output uvec3 out0 = [ uvec3(193, 3, 2) | uvec3(9, 45, 3) | uvec3(45, 2, 9) | uvec3(255, 9, 10) | uvec3(2, 10, 255) | uvec3(0, 0, 8) | uvec3(10, 8, 12) | uvec3(8, 12, 0) | uvec3(12, 255, 193) | uvec3(3, 193, 45) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ output uvec3 out0 = [ uvec3(0, 0, 1) | uvec3(1, 1, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | false | false | true | false | true | true | false ];
+ input float in1 = [ 36.8125 | 20.125 | 1.0 | 0.0 | 3.5 | 1.0 | 2.0 | 0.5 | 0.0 | 8.25 ];
+ input int in2 = [ 1 | 0 | 8 | 66 | 2 | 11 | 192 | 5 | 12 | 255 ];
+ output uvec3 out0 = [ uvec3(1, 36, 1) | uvec3(0, 20, 0) | uvec3(1, 1, 8) | uvec3(0, 0, 66) | uvec3(0, 3, 2) | uvec3(1, 1, 11) | uvec3(0, 2, 192) | uvec3(1, 0, 5) | uvec3(1, 0, 12) | uvec3(0, 8, 255) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_uvec3
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(32.0, 64.0) | vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(0.75, 0.0322580645161) ];
+ input bool in1 = [ false | false | true | true | true ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(32, 64, 0) | uvec3(0, 2, 1) | uvec3(1, 1, 1) | uvec3(0, 0, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) ];
+ input float in1 = [ 8.25 | 36.8125 | 20.125 | 2.0 | 0.0 | 1.0 | 0.5 | 3.5 ];
+ output uvec3 out0 = [ uvec3(1, 1, 8) | uvec3(1, 0, 36) | uvec3(0, 1, 20) | uvec3(0, 0, 2) | uvec3(1, 0, 0) | uvec3(0, 1, 1) | uvec3(0, 0, 0) | uvec3(0, 0, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) ];
+ input int in1 = [ 255 | 1 | 2 | 5 | 0 | 11 | 192 | 12 | 8 | 66 ];
+ output uvec3 out0 = [ uvec3(1, 1, 255) | uvec3(0, 1, 1) | uvec3(0, 0, 2) | uvec3(1, 1, 5) | uvec3(0, 0, 0) | uvec3(1, 0, 11) | uvec3(0, 0, 192) | uvec3(0, 0, 12) | uvec3(0, 1, 8) | uvec3(1, 0, 66) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_uvec3
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(32, 64) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 2) | uvec3(1, 1, 1) | uvec3(1, 0, 0) | uvec3(0, 32, 64) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_uvec3
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 8.25 | 20.125 | 3.5 | 0.0 | 0.5 | 36.8125 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ output uvec3 out0 = [ uvec3(2, 0, 2) | uvec3(8, 1, 1) | uvec3(20, 32, 64) | uvec3(3, 0, 0) | uvec3(0, 0, 2) | uvec3(0, 0, 0) | uvec3(36, 1, 1) | uvec3(1, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output vec2 out0 = [ vec2(-0.5, 1.0) | vec2(-20.125, -20.125) | vec2(1.0, 0.0) | vec2(2.0, 3.5) | vec2(3.5, -8.25) | vec2(36.8125, 36.8125) | vec2(-8.25, -0.5) | vec2(0.0, 2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output ivec2 out0 = [ ivec2(0, 1) | ivec2(-20, -20) | ivec2(1, 0) | ivec2(2, 3) | ivec2(3, -8) | ivec2(36, 36) | ivec2(-8, 0) | ivec2(0, 2) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output vec2 out0 = [ vec2(2.0, -192.0) | vec2(-66.0, 8.0) | vec2(0.0, 1.0) | vec2(5.0, 0.0) | vec2(-12.0, 5.0) | vec2(8.0, -66.0) | vec2(-192.0, 2.0) | vec2(1.0, 255.0) | vec2(11.0, 11.0) | vec2(255.0, -12.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output ivec2 out0 = [ ivec2(2, -192) | ivec2(-66, 8) | ivec2(0, 1) | ivec2(5, 0) | ivec2(-12, 5) | ivec2(8, -66) | ivec2(-192, 2) | ivec2(1, 255) | ivec2(11, 11) | ivec2(255, -12) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_vec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output vec2 out0 = [ vec2(9.0, 8.0) | vec2(12.0, 9.0) | vec2(0.0, 45.0) | vec2(255.0, 2.0) | vec2(8.0, 12.0) | vec2(45.0, 193.0) | vec2(3.0, 255.0) | vec2(2.0, 0.0) | vec2(10.0, 3.0) | vec2(193.0, 10.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_ivec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output ivec2 out0 = [ ivec2(9, 8) | ivec2(12, 9) | ivec2(0, 45) | ivec2(255, 2) | ivec2(8, 12) | ivec2(45, 193) | ivec2(3, 255) | ivec2(2, 0) | ivec2(10, 3) | ivec2(193, 10) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_bvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_vec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_ivec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_bvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output vec2 out0 = [ vec2(0.0, -66.0) | vec2(3.5, 1.0) | vec2(0.0, 255.0) | vec2(2.0, -192.0) | vec2(-8.25, 8.0) | vec2(36.8125, 2.0) | vec2(-20.125, 0.0) | vec2(1.0, 5.0) | vec2(1.0, -12.0) | vec2(-0.5, 11.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output ivec2 out0 = [ ivec2(0, -66) | ivec2(3, 1) | ivec2(0, 255) | ivec2(2, -192) | ivec2(-8, 8) | ivec2(36, 2) | ivec2(-20, 0) | ivec2(1, 5) | ivec2(1, -12) | ivec2(0, 11) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_vec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output vec2 out0 = [ vec2(2.0, 0.0) | vec2(3.5, 1.0) | vec2(1.0, 1.0) | vec2(-20.125, 0.0) | vec2(-8.25, 0.0) | vec2(0.0, 1.0) | vec2(-0.5, 0.0) | vec2(36.8125, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_ivec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output ivec2 out0 = [ ivec2(2, 0) | ivec2(3, 1) | ivec2(1, 1) | ivec2(-20, 0) | ivec2(-8, 0) | ivec2(0, 1) | ivec2(0, 0) | ivec2(36, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_bvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output vec2 out0 = [ vec2(255.0, 1.0) | vec2(2.0, 0.0) | vec2(-12.0, 0.0) | vec2(1.0, 0.0) | vec2(-192.0, 1.0) | vec2(5.0, 0.0) | vec2(8.0, 1.0) | vec2(0.0, 0.0) | vec2(-66.0, 1.0) | vec2(11.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output ivec2 out0 = [ ivec2(255, 1) | ivec2(2, 0) | ivec2(-12, 0) | ivec2(1, 0) | ivec2(-192, 1) | ivec2(5, 0) | ivec2(8, 1) | ivec2(0, 0) | ivec2(-66, 1) | ivec2(11, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_vec2
+ version 300 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output vec2 out0 = [ vec2(-66.0, 193.0) | vec2(1.0, 0.0) | vec2(-192.0, 2.0) | vec2(-12.0, 10.0) | vec2(5.0, 255.0) | vec2(255.0, 12.0) | vec2(11.0, 45.0) | vec2(0.0, 8.0) | vec2(2.0, 9.0) | vec2(8.0, 3.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_ivec2
+ version 300 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output ivec2 out0 = [ ivec2(-66, 193) | ivec2(1, 0) | ivec2(-192, 2) | ivec2(-12, 10) | ivec2(5, 255) | ivec2(255, 12) | ivec2(11, 45) | ivec2(0, 8) | ivec2(2, 9) | ivec2(8, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_bvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_vec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output vec2 out0 = [ vec2(12.0, -20.125) | vec2(0.0, 0.0) | vec2(8.0, 3.5) | vec2(193.0, -8.25) | vec2(3.0, 0.0) | vec2(10.0, 1.0) | vec2(9.0, 2.0) | vec2(2.0, 36.8125) | vec2(45.0, -0.5) | vec2(255.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_ivec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output ivec2 out0 = [ ivec2(12, -20) | ivec2(0, 0) | ivec2(8, 3) | ivec2(193, -8) | ivec2(3, 0) | ivec2(10, 1) | ivec2(9, 2) | ivec2(2, 36) | ivec2(45, 0) | ivec2(255, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_bvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 36.8125 | 1.0 | 0.5 | 20.125 | 0.0 | 2.0 | 3.5 ];
+ input float in1 = [ 0.5 | 36.8125 | 0.0 | 2.0 | 8.25 | 20.125 | 1.0 | 3.5 ];
+ output uvec2 out0 = [ uvec2(8, 0) | uvec2(36, 36) | uvec2(1, 0) | uvec2(0, 2) | uvec2(20, 8) | uvec2(0, 20) | uvec2(2, 1) | uvec2(3, 3) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 12 | 8 | 11 | 255 | 66 | 192 | 2 | 5 | 1 ];
+ input int in1 = [ 11 | 12 | 2 | 5 | 66 | 192 | 255 | 0 | 1 | 8 ];
+ output uvec2 out0 = [ uvec2(0, 11) | uvec2(12, 12) | uvec2(8, 2) | uvec2(11, 5) | uvec2(255, 66) | uvec2(66, 192) | uvec2(192, 255) | uvec2(2, 0) | uvec2(5, 1) | uvec2(1, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_uvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 3 | 9 | 10 | 193 | 8 | 0 | 255 | 45 | 2 | 12 ];
+ input uint in1 = [ 0 | 2 | 12 | 3 | 10 | 9 | 45 | 193 | 255 | 8 ];
+ output uvec2 out0 = [ uvec2(3, 0) | uvec2(9, 2) | uvec2(10, 12) | uvec2(193, 3) | uvec2(8, 10) | uvec2(0, 9) | uvec2(255, 45) | uvec2(45, 193) | uvec2(2, 255) | uvec2(12, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_uvec2
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 8.25 | 1.0 | 0.5 | 3.5 | 2.0 | 0.0 | 36.8125 | 1.0 | 0.0 | 20.125 ];
+ input int in1 = [ 0 | 255 | 12 | 5 | 192 | 2 | 66 | 11 | 1 | 8 ];
+ output uvec2 out0 = [ uvec2(8, 0) | uvec2(1, 255) | uvec2(0, 12) | uvec2(3, 5) | uvec2(2, 192) | uvec2(0, 2) | uvec2(36, 66) | uvec2(1, 11) | uvec2(0, 1) | uvec2(20, 8) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_uvec2
+ version 300 es
+ values
+ {
+ input float in0 = [ 3.5 | 1.0 | 8.25 | 0.5 | 2.0 | 36.8125 | 0.0 | 20.125 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true ];
+ output uvec2 out0 = [ uvec2(3, 1) | uvec2(1, 0) | uvec2(8, 1) | uvec2(0, 0) | uvec2(2, 1) | uvec2(36, 0) | uvec2(0, 0) | uvec2(20, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 12 | 11 | 0 | 5 | 8 | 255 | 2 | 1 | 66 | 192 ];
+ input bool in1 = [ true | true | false | false | false | true | false | false | true | true ];
+ output uvec2 out0 = [ uvec2(12, 1) | uvec2(11, 1) | uvec2(0, 0) | uvec2(5, 0) | uvec2(8, 0) | uvec2(255, 1) | uvec2(2, 0) | uvec2(1, 0) | uvec2(66, 1) | uvec2(192, 1) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_uvec2
+ version 300 es
+ values
+ {
+ input int in0 = [ 8 | 5 | 1 | 0 | 11 | 12 | 192 | 66 | 255 | 2 ];
+ input uint in1 = [ 8 | 10 | 45 | 255 | 9 | 193 | 2 | 3 | 0 | 12 ];
+ output uvec2 out0 = [ uvec2(8, 8) | uvec2(5, 10) | uvec2(1, 45) | uvec2(0, 255) | uvec2(11, 9) | uvec2(12, 193) | uvec2(192, 2) | uvec2(66, 3) | uvec2(255, 0) | uvec2(2, 12) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_uvec2
+ version 300 es
+ values
+ {
+ input uint in0 = [ 9 | 45 | 8 | 3 | 10 | 2 | 193 | 12 | 255 | 0 ];
+ input float in1 = [ 3.5 | 20.125 | 2.0 | 0.0 | 1.0 | 36.8125 | 8.25 | 1.0 | 0.0 | 0.5 ];
+ output uvec2 out0 = [ uvec2(9, 3) | uvec2(45, 20) | uvec2(8, 2) | uvec2(3, 0) | uvec2(10, 1) | uvec2(2, 36) | uvec2(193, 8) | uvec2(12, 1) | uvec2(255, 0) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_combine
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.html
new file mode 100644
index 0000000000..73e3b7cbc1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_illegal';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.test
new file mode 100644
index 0000000000..b4be51604d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_illegal.test
@@ -0,0 +1,1064 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_illegal "Illegal Vector Conversions"
+
+ case vec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec2 in0 = vec2(0.0, 0.5);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec2 in0 = ivec2(0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec2 in0 = uvec2(0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec3 out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec3 out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ uvec3 out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec3
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec3 out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec2 in0 = bvec2(true, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3 in0 = vec3(0.0, 0.5, 0.75);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3 in0 = ivec3(0, 0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ uvec3 in0 = uvec3(0, 0, 0);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ vec4 out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ ivec4 out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ uvec4 out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec4
+ version 300 es
+ expect compile_fail
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3 in0 = bvec3(true, false, false);
+ bvec4 out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_illegal
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.html
new file mode 100644
index 0000000000..e9e1fa0ca2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_to_scalar';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.test
new file mode 100644
index 0000000000..7d1fe121ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_scalar.test
@@ -0,0 +1,1160 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_to_scalar "Vector to Scalar Conversions"
+
+ case vec2_to_float
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_int
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bool
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_float
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_int
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bool
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_float
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_int
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bool
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_float
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_int
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bool
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_float
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_int
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bool
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_float
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_int
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bool
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_float
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_int
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bool
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_float
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_int
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bool
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_float
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_int
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bool
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_float
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_int
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bool
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_float
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_int
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bool
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_float
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_int
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bool
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uint
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.5, 2.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uint
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uint
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uint
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uint
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uint
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uint
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uint
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uint
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uint
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uint
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uint
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_scalar
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.html
new file mode 100644
index 0000000000..c7452d81ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.html
@@ -0,0 +1,31 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'conversions_vector_to_vector';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+modules.shared.glsShaderLibrary.run(testName);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.test
new file mode 100644
index 0000000000..b112327284
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/conversions_vector_to_vector.test
@@ -0,0 +1,2312 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+group vector_to_vector "Vector to Vector Conversions"
+
+ case vec4_to_vec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec4 out0 = [ bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, -2.0, -4.0, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 2.0, 4.0, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 2.0, 4.0) | vec3(32.0, 64.0, 51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 1.0) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(0.0, 1.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 1, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec3
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec2
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec3
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec2
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec3
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec2
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec4 out0 = [ uvec4(1, 0, 0, 1) | uvec4(0, 0, 0, 1) | uvec4(0, 1, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 1, 0) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec2
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 2.0, 4.0) | vec3(32.0, 64.0, 51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec2
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec2
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec2
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 1, 0) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec2
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.5, 2.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_vector
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.html
new file mode 100644
index 0000000000..025d5933e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'declarations';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.test
new file mode 100644
index 0000000000..86f98d9832
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/declarations.test
@@ -0,0 +1,591 @@
+group invalid_declarations "Invalid declarations"
+ case in_in_vertex_main
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ in mediump float val;
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case out_in_vertex_main
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ out mediump float val;
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ in mediump float val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case in_in_fragment_main
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ out mediump float val;
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ in mediump float val;
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case out_in_fragment_main
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out mediump float val;
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_in_vertex_main
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ uniform mediump float val;
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_in_fragment_main
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ uniform mediump float val;
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_block_in_main
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main()
+ {
+ uniform Block { mediump float val; };
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invariant_attribute
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ invariant in mediump float val;
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invariant_uniform
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ invariant uniform mediump float val;
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invariant_uniform_block_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ invariant uniform Block { mediump float val; };
+ ${DECLARATIONS}
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invariant_uniform_block_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ uniform Block { invariant mediump float val; };
+ ${DECLARATIONS}
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_layout_qualifier
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ layout(foobar) uniform Block
+ {
+ mediump float val;
+ };
+ ${DECLARATIONS}
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_member_layout_qualifier
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ layout(foobar) uniform mediump float val;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_nested_struct_definition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ struct S
+ {
+ mediump float v;
+ struct T
+ {
+ highp int i;
+ } t;
+ } s;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_uniform_block
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ uniform Block2
+ {
+ mediump float v;
+ } block2;
+ } block;
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_sampler_2d
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ uniform sampler2D s;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_sampler_cube
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ uniform samplerCube s;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_missing_member_semicolon
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_missing_end_semicolon
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var;
+ }
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_member_name_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var;
+ mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_member_name_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var;
+ };
+ uniform Block2
+ {
+ mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_member_name_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform mediump float var;
+ uniform Block
+ {
+ mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_block_name
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var;
+ };
+ uniform Block
+ {
+ mediump float var2;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_instance_name_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var;
+ } block;
+ uniform Block2
+ {
+ mediump float var2;
+ } block;
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_instance_name_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform mediump float block;
+ uniform Block
+ {
+ mediump float var;
+ } block;
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_duplicate_instance_name_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float block;
+ };
+ uniform Block2
+ {
+ mediump float var2;
+ } block;
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_array_without_instance_name_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block[2]
+ {
+ mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_array_without_instance_name_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ mediump float var;
+ } [2];
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_in
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ in mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_out
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ out mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uniform_block_const
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ uniform Block
+ {
+ const mediump float var;
+ };
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # invalid_declarations
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.html
new file mode 100644
index 0000000000..3e531413ad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'fragdata';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.test
new file mode 100644
index 0000000000..f7ba4f2957
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/fragdata.test
@@ -0,0 +1,76 @@
+
+case invalid_assign_to_1
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main (void)
+ {
+ gl_FragData[1] = vec4(1.0);
+ }
+ ""
+end
+
+case write_fragcolor_and_fragdata_simple
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main (void)
+ {
+ gl_FragColor = vec4(1.0);
+ gl_FragData[0] = vec4(1.0);
+ }
+ ""
+end
+
+case write_fragcolor_and_fragdata_static_if
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void main (void)
+ {
+ if (false)
+ gl_FragColor = vec4(1.0);
+ else
+ gl_FragData[0] = vec4(1.0);
+ }
+ ""
+end
+
+case write_fragcolor_and_fragdata_unused_func
+ version 100 es
+ expect compile_fail
+ vertex ""
+ void main (void)
+ {
+ gl_Position = vec4(1.0);
+ }
+ ""
+ fragment ""
+ void unused (void)
+ {
+ gl_FragData[0] = vec4(1.0);
+ }
+ void main (void)
+ {
+ gl_FragColor = vec4(1.0);
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.html
new file mode 100644
index 0000000000..65ff88fbbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'functions';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.test
new file mode 100644
index 0000000000..767a03599e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/functions.test
@@ -0,0 +1,4345 @@
+# Tests todo:
+# - inout with varyings, attributes, uniforms (and arrays of 'em)
+# - inout with arrays, array elements
+# - inout with array elements
+# - inout by-value semantics (arrays & elements & structs)
+
+# Done:
+# - control flow: return, return in loop, etc.
+
+group datatypes "Function Parameter Data Types"
+
+ case float_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec2
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 1.0) | vec2(2.0, 2.5) ];
+ output float out0 = [ -1.0 | -4.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec2 a)
+ {
+ return -(a.x + a.y);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec3
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec3 a)
+ {
+ return -(a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec4
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, -2.0, 0.5) | vec4(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec4 a)
+ {
+ return -(a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(0.0, 1.0, -2.0, 0.5) | mat2(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat2 a)
+ {
+ return -(a[0][0] + a[0][1] + a[1][0] + a[1][1]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(0.0, 1.0, -2.0, 0.5, 1.0, -1.0, 2.0, 4.0, -1.0) | mat3(2.0, 2.5, 4.0, -7.0, 2.5, 3.0, 0.5, -3.5, 1.0) ];
+ output float out0 = [ -4.5 | -5.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat3 a)
+ {
+ return -(a[0][0] + a[0][1] + a[0][2] + a[1][0] + a[1][1] + a[1][2] + a[2][0] + a[2][1] + a[2][2]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(0.0, 1.0, -2.0, 0.5, 1.0, -1.0, 2.0, 4.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -2.0, -2.0) | mat4(2.0, 2.5, 4.0, -7.0, 2.5, 3.0, 0.5, -3.5, 1.0, 0.0, 2.0, -1.0, 1.0, 0.0, -1.0, 3.0) ];
+ output float out0 = [ -5.5 | -9.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat4 a)
+ {
+ return -(a[0][0] + a[0][1] + a[0][2] + a[0][3] + a[1][0] + a[1][1] + a[1][2] + a[1][3] + a[2][0] + a[2][1] + a[2][2] + a[2][3] + a[3][0] + a[3][1] + a[3][2] + a[3][3]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int
+ version 300 es
+ values
+ {
+ input int in0 = [ -1 | 0 | 1 | 4 ];
+ output int out0 = [ 1 | 0 | -1 | -4 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (int a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 0) | ivec2(1, 4) ];
+ output int out0 = [ 1 | -5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec2 a)
+ {
+ return -(a.x + a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec3
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 0, 2) | ivec3(1, 4, -8) ];
+ output int out0 = [ -1 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec3 a)
+ {
+ return -(a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec4
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 0, 2, 2) | ivec4(1, 4, -8, 2) ];
+ output int out0 = [ -3 | 1 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec4 a)
+ {
+ return -(a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint
+ version 300 es
+ values
+ {
+ input uint in0 = [ 1 | 0 | 2 | 4 ];
+ output uint out0 = [ 1 | 0 | 4 | 16 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uint a)
+ {
+ return a*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uvec2
+ version 300 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(1, 0) | uvec2(2, 4) ];
+ output uint out0 = [ 1 | 6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uvec2 a)
+ {
+ return (a.x + a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uvec3
+ version 300 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(1, 0, 2) | uvec3(1, 4, 8) ];
+ output uint out0 = [ 3 | 13 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uvec3 a)
+ {
+ return (a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uvec4
+ version 300 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(1, 0, 2, 2) | uvec4(1, 4, 8, 2) ];
+ output uint out0 = [ 5 | 15 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uvec4 a)
+ {
+ return (a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bool a)
+ {
+ return !a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, true) ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec2 a)
+ {
+ return !(a.x == a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec3
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, true, false) | bvec3(true, false, false) ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec3 a)
+ {
+ return (a.x == a.y) == a.z;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, true, false) | bvec4(false, false, true, true) | bvec4(true, false, false, true) ];
+ output bool out0 = [ false | true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec4 a)
+ {
+ return ((a.x == a.y) == (a.z == a.w));
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ version 300 es
+ values
+ {
+ input mat2 in0 = [ mat2(-2.0, 0.5, -1.0, 1.0) | mat2(1.0, -3.5, -3.5, 2.5) | mat2(-2.0, -2.0, 3.5, 0.0) ];
+ output mat2 out0 = [ mat2(4.0, -1.0, 2.0, -2.0) | mat2(-2.0, 7.0, 7.0, -5.0) | mat2(4.0, 4.0, -7.0, -0.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2 func (mat2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat2x3
+ version 300 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(2.5, 0.0, 1.0, -2.5, 1.0, 3.0) | mat2x3(0.0, 2.0, 1.5, -3.5, 2.0, 0.5) | mat2x3(-1.5, -3.5, 2.5, 0.0, 1.5, 3.0) ];
+ output mat2x3 out0 = [ mat2x3(-5.0, -0.0, -2.0, 5.0, -2.0, -6.0) | mat2x3(-0.0, -4.0, -3.0, 7.0, -4.0, -1.0) | mat2x3(3.0, 7.0, -5.0, -0.0, -3.0, -6.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2x3 func (mat2x3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat2x4
+ version 300 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.5, 3.0, -1.0, 2.5, -0.5, 3.5, 3.0, -3.0) | mat2x4(-2.5, -2.0, 3.5, -0.5, 1.0, -1.5, 0.0, -1.0) | mat2x4(-1.0, 0.5, 0.5, 3.0, 1.5, 3.0, 2.5, 3.5) ];
+ output mat2x4 out0 = [ mat2x4(-3.0, -6.0, 2.0, -5.0, 1.0, -7.0, -6.0, 6.0) | mat2x4(5.0, 4.0, -7.0, 1.0, -2.0, 3.0, -0.0, 2.0) | mat2x4(2.0, -1.0, -1.0, -6.0, -3.0, -6.0, -5.0, -7.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2x4 func (mat2x4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3x2
+ version 300 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.5, -2.5, 2.5, 3.5, 3.0, 0.5) | mat3x2(1.5, -2.0, 2.5, 0.5, -1.5, -3.5) | mat3x2(2.5, 3.5, -3.0, 2.5, -0.5, -2.5) ];
+ output mat3x2 out0 = [ mat3x2(-3.0, 5.0, -5.0, -7.0, -6.0, -1.0) | mat3x2(-3.0, 4.0, -5.0, -1.0, 3.0, 7.0) | mat3x2(-5.0, -7.0, 6.0, -5.0, 1.0, 5.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3x2 func (mat3x2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3
+ version 300 es
+ values
+ {
+ input mat3 in0 = [ mat3(-1.5, 2.0, 3.0, -3.5, 1.0, -3.5, 1.5, -1.5, 3.0) | mat3(3.5, 0.0, 3.5, -1.5, -3.0, 0.5, -3.5, -2.5, -0.5) | mat3(1.0, -2.5, -3.5, 3.0, -1.5, 3.5, 3.0, -1.0, -0.5) ];
+ output mat3 out0 = [ mat3(3.0, -4.0, -6.0, 7.0, -2.0, 7.0, -3.0, 3.0, -6.0) | mat3(-7.0, -0.0, -7.0, 3.0, 6.0, -1.0, 7.0, 5.0, 1.0) | mat3(-2.0, 5.0, 7.0, -6.0, 3.0, -7.0, -6.0, 2.0, 1.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3 func (mat3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3x4
+ version 300 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(0.0, 1.0, 0.5, 0.5, 1.0, 3.5, 0.0, -0.5, 1.5, -2.0, -1.5, 3.5) | mat3x4(0.0, 0.5, -3.5, -0.5, 0.5, -3.5, 1.0, 1.0, -3.5, 1.0, -0.5, 1.5) | mat3x4(-1.0, 1.5, 2.0, -3.5, -3.5, 1.5, 3.5, -2.0, -0.5, 0.5, -1.5, -1.0) ];
+ output mat3x4 out0 = [ mat3x4(-0.0, -2.0, -1.0, -1.0, -2.0, -7.0, -0.0, 1.0, -3.0, 4.0, 3.0, -7.0) | mat3x4(-0.0, -1.0, 7.0, 1.0, -1.0, 7.0, -2.0, -2.0, 7.0, -2.0, 1.0, -3.0) | mat3x4(2.0, -3.0, -4.0, 7.0, 7.0, -3.0, -7.0, 4.0, 1.0, -1.0, 3.0, 2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3x4 func (mat3x4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4x2
+ version 300 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(-1.5, -1.0, 0.5, -1.5, -1.0, 2.0, -3.5, 0.5) | mat4x2(2.0, -1.5, -2.0, 2.5, -2.0, -2.5, -0.5, 1.5) | mat4x2(-3.0, -1.5, -1.0, 2.5, -0.5, 2.5, -2.5, -1.0) ];
+ output mat4x2 out0 = [ mat4x2(3.0, 2.0, -1.0, 3.0, 2.0, -4.0, 7.0, -1.0) | mat4x2(-4.0, 3.0, 4.0, -5.0, 4.0, 5.0, 1.0, -3.0) | mat4x2(6.0, 3.0, 2.0, -5.0, 1.0, -5.0, 5.0, 2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4x2 func (mat4x2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4x3
+ version 300 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 3.0, -0.5, -2.0, -3.0, 0.0, -2.5, 2.5, 2.5, -2.5, -1.5, 2.5) | mat4x3(1.0, 2.5, -1.0, -3.0, -1.5, 2.0, -1.5, -1.0, -0.5, -0.5, -0.5, 3.0) | mat4x3(-2.5, -3.5, 3.5, 3.0, 3.5, -0.5, 3.5, 3.0, -2.0, 2.0, 2.5, 1.0) ];
+ output mat4x3 out0 = [ mat4x3(-2.0, -6.0, 1.0, 4.0, 6.0, -0.0, 5.0, -5.0, -5.0, 5.0, 3.0, -5.0) | mat4x3(-2.0, -5.0, 2.0, 6.0, 3.0, -4.0, 3.0, 2.0, 1.0, 1.0, 1.0, -6.0) | mat4x3(5.0, 7.0, -7.0, -6.0, -7.0, 1.0, -7.0, -6.0, 4.0, -4.0, -5.0, -2.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4x3 func (mat4x3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4
+ version 300 es
+ values
+ {
+ input mat4 in0 = [ mat4(0.0, -1.5, -1.0, -2.0, -3.0, 0.5, -1.5, 2.5, -3.5, 3.0, 1.5, 3.0, 3.0, 3.0, 0.5, -3.5) | mat4(2.0, -2.5, -1.5, 1.0, 0.0, -0.5, 3.5, 1.0, -1.0, -2.0, 2.5, 0.0, 2.0, -1.0, -2.5, 0.5) | mat4(2.5, -2.5, 2.0, 3.0, 2.5, 2.5, -3.5, 1.0, 2.5, -3.5, -1.5, -1.5, 0.0, -0.5, 0.0, 2.0) ];
+ output mat4 out0 = [ mat4(-0.0, 3.0, 2.0, 4.0, 6.0, -1.0, 3.0, -5.0, 7.0, -6.0, -3.0, -6.0, -6.0, -6.0, -1.0, 7.0) | mat4(-4.0, 5.0, 3.0, -2.0, -0.0, 1.0, -7.0, -2.0, 2.0, 4.0, -5.0, -0.0, -4.0, 2.0, 5.0, -1.0) | mat4(-5.0, 5.0, -4.0, -6.0, -5.0, -5.0, 7.0, -2.0, -5.0, 7.0, 3.0, 3.0, -0.0, 1.0, -0.0, -4.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4 func (mat4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+
+ float func (Pos p)
+ {
+ return -(p.a + p.b + p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ out0 = func(p);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct_struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+
+ Pos func (Pos p)
+ {
+ return Pos(-p.a, -p.b, -p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ p = func(p);
+ out0 = p.a + p.b + p.c;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct_nested_struct
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+ struct Line { Pos start, end; };
+
+ Line func (Pos p)
+ {
+ return Line(p, Pos(-p.a, -p.b, -p.c));
+ }
+
+ float sum (Pos p)
+ {
+ return (p.a + p.b + p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ Line line = func(p);
+ out0 = sum(line.start) + (2.0 * sum(line.end));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # datatypes
+
+group qualifiers "Function Parameter Qualifiers"
+
+ case in_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_lowp_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in lowp float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_lowp_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out lowp float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_lowp_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout lowp float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_highp_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in highp float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_highp_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out highp float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_highp_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout highp float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (const float a)
+ {
+ float b = -a;
+ return 2.0 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_in_float
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (const in float a)
+ {
+ float b = -a;
+ return 2.0 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_lowp_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in lowp int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_lowp_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out lowp int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_lowp_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout lowp int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_highp_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in highp int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_highp_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out highp int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_highp_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout highp int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_in_int
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const in int a)
+ {
+ int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a)
+ {
+ a = !a;
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = in0;
+ bool g = func(f);
+ out0 = (f != g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (out bool a)
+ {
+ a = false;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = true;
+ func(f);
+ out0 = (in0 == f);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (inout bool a)
+ {
+ a = !a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = true;
+ func(f);
+ out0 = (in0 == f);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_bool
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (const bool a)
+ {
+ bool b = !a;
+ return b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = in0;
+ bool g = func(f);
+ out0 = (f != g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # qualifiers
+
+group declarations "Function Declarations"
+
+ case basic
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void);
+
+ float func (void)
+ {
+ return -1.0;
+ }
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_arg
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ float func (float f)
+ {
+ return -f;
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case define_after_use
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void);
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+
+ float func (void)
+ {
+ return -1.0;
+ }
+ ""
+ end
+
+ case double_declare
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void);
+
+ float func (void);
+
+ float func (void)
+ {
+ return -1.0;
+ }
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case declare_after_define
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void)
+ {
+ return -1.0;
+ }
+
+ float func (void);
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case void_vs_no_void
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func ();
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+
+ float func (void)
+ {
+ return -1.0;
+ }
+ ""
+ end
+
+ case in_vs_no_in
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+
+ float func (in float f)
+ {
+ return -f;
+ }
+ ""
+ end
+
+ case default_vs_explicit_precision
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+
+ float func (mediump float f)
+ {
+ return -f;
+ }
+ ""
+ end
+
+
+end # declarations
+
+group overloading "Function Overloading"
+
+ case user_func_arg_type_simple
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ int func (int a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ out0 = func(in0) * float(func(-1));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_float_types
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a) { return -a; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+
+ void main()
+ {
+ out0 = func(func(func(func(vec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_int_types
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(func(func(func(ivec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_bool_types
+ version 300 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(func(func(func(bvec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_basic_types
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a) { return -a; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ if (func(func(bvec4(false)).x))
+ out0 = func(in0) * float(func(-1));
+ else
+ out0 = float(func(func(ivec4(func(func(func(vec4(0.5)).xyz).xy).xxxx)).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_complex_types
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+ struct Line { Pos start, end; };
+
+ float func (float a) { return -a; }
+ float func (float a[4]) { return a[0] + a[3]; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+ vec4 func (vec4 a[4]) { return a[1] + a[2]; }
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+ Pos func (Pos a) { return a; }
+ Line func (Line a) { return Line(a.end, a.start); }
+
+ void main()
+ {
+ ${SETUP}
+ float arr[4];
+ vec4 arr2[4];
+ out0 = func(arr) + func(arr2).x;
+ if (func(func(bvec4(false)).x))
+ out0 = func(in0) * float(func(-1));
+ else
+ out0 = float(func(func(ivec4(func(func(func(vec4(0.5)).xyz).xy).xxxx)).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arguments
+ version 300 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ float func (float a, float b)
+ {
+ return a * b;
+ }
+
+ void main()
+ {
+ out0 = func(in0) * func(-0.5, -2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_size
+ version 300 es
+ values
+ {
+ output float out0 = [ 1.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f[3])
+ {
+ return f[0];
+ }
+
+ float func (float f[4])
+ {
+ return f[1];
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ float[4] x = float[4] (-1.0, 1.0, 0.0, 0.0);
+ out0 = func(x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # overloading
+
+group array_arguments "Arrays as Arguments"
+
+ case local_in_float
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (in float a[4])
+ {
+ a[0] = -1.0;
+ a[2] = -4.0;
+ a[3] = -3.0 * a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ float arr[4];
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_float
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (in float a[4])
+ {
+ a[0] = -1.0;
+ a[2] = -4.0;
+ a[3] = -3.0 * a[1];
+ return a[0];
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_in_int
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, -4) | ivec4(-7, -11, 13, 19) ];
+ output ivec4 out0 = [ ivec4(0, -1, -2, 4) | ivec4(7, 11, -13, -19) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a[4])
+ {
+ a[0] = -1;
+ a[2] = -4;
+ a[3] = -3 * a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int arr[4];
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ int f = func(arr);
+ out0 = f * ivec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_int
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, 4) | ivec4(-7, -11, 13, 19) ];
+ output ivec4 out0 = [ ivec4(0, -1, -2, -4) | ivec4(7, 11, -13, -19) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a[4])
+ {
+ a[0] = -1;
+ a[2] = -4;
+ a[3] = -3 * a[1];
+ return a[0];
+ }
+
+ int arr[4];
+
+ void main()
+ {
+ ${SETUP}
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ int f = func(arr);
+ out0 = f * ivec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+
+ ""
+ end
+
+ case local_in_bool
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a[4])
+ {
+ a[0] = false;
+ a[2] = true;
+ a[3] = !a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool arr[4];
+ arr[0] = !in0.x;
+ arr[1] = !in0.y;
+ arr[2] = !in0.z;
+ arr[3] = !in0.w;
+ func(arr);
+ out0 = bvec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_bool
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a[4])
+ {
+ a[0] = false;
+ a[2] = true;
+ a[3] = !a[1];
+ return a[0];
+ }
+
+ bool arr[4];
+
+ void main()
+ {
+ ${SETUP}
+ arr[0] = !in0.x;
+ arr[1] = !in0.y;
+ arr[2] = !in0.z;
+ arr[3] = !in0.w;
+ func(arr);
+ out0 = bvec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case test_helpers
+ version 300 es
+ desc "Check that helper functions are supported properly."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output float out0 = [ 1.0 | 1.0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ negate(arr);
+ out0 = float(test(arr, -in0));
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_local_in_on_call
+ version 300 es
+ desc "Check that local 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ a[0] = 2.123;
+ a[2] = -4.123;
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ out0 = in0 * func(arr, arr);
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_global_in_on_call
+ version 300 es
+ desc "Check that global 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ a[0] = 2.123;
+ a[2] = -4.123;
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ set(arr, in0);
+ out0 = in0 * func(arr, arr);
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_local_inout_on_call
+ version 300 es
+ desc "Check that local 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (inout float a[4], inout float b[4])
+ {
+ negate(a);
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ float m = func(arr, arr); // returns -1.0
+ float n = float(test(arr, in0) || test(arr, -in0));
+ out0 = in0 * m * n;
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_global_inout_on_call
+ version 300 es
+ desc "Check that global 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ negate(a);
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ set(arr, in0);
+ float m = func(arr, arr); // returns -1.0
+ float n = float(test(arr, in0) || test(arr, -in0));
+ out0 = in0 * m * n;
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+# vec4 get (in float arr[4]);
+# void set (out float arr[4], vec4 val);
+# void negate (inout float arr[4]);
+# bool test (in float arr[4], vec4 ref);
+# bool isEqual (in float a[4], in float b[4]);
+
+# float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+# vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+# void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+# void negate (inout float arr[4]) { set(arr, -get(arr)); }
+# bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+# bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+
+end # array_arguments
+
+#group qualifiers "Function Parameter Qualifiers"
+#
+#end # qualifiers
+
+group control_flow "Control Flow In Functions"
+
+ case simple_return
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ a = a * -1.0;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_if
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ if (a != 0.0)
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_else
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ if (a == 0.0)
+ return 1.0;
+ else
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_loop
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ while (a < 100.0)
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_loop_if
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ while (a < 100.0)
+ {
+ a = -a;
+ if (a != 0.0)
+ return a;
+ else
+ return -1.0;
+ }
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_loop
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 5; i++)
+ a = -a;
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_break
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ a = -a;
+ if (i == 4)
+ break;
+ }
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_continue
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ if (i == 4)
+ continue;
+ a = -a;
+ }
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_nested_loop
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ a = -a;
+ for (int j = 0; j < 4; j++)
+ {
+ a = -a;
+ if (i == 1)
+ return a;
+ }
+ if (i == 4)
+ return 1.0;
+ }
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_loop_sequence
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ int i;
+ for (i = 0; i < 6; i++) // negate a
+ {
+ a = -a;
+ if (i == 4)
+ a = -a;
+ }
+
+ for (; i < 10; i++) // keep a
+ {
+ if (i == 8)
+ continue;
+ else if (i == 9)
+ break;
+ a = -a;
+ }
+
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_return_break_continue
+ version 300 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ int i;
+ for (i = 0; i < 6; i++)
+ {
+ if (i == 0)
+ continue;
+ else if (i == 1)
+ {
+ }
+ else if (i == 3)
+ break;
+ else
+ return a;
+ a = -a;
+ }
+
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # control_flow
+
+group misc "Miscellaneous"
+
+ case multi_arg_float
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, -2.0, 0.5) | vec4(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ]; # -sum(in0)
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sum(vec4 v) { return (v.x + v.y + v.z + v.w); }
+
+ float func (float a, vec3 b, vec2 c, vec2 d, vec4 e)
+ {
+ return -sum(vec4(a, b) + vec4(c, d)) + sum(e);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0.y, in0.xzw, in0.wz, in0.yx, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multi_arg_int
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 0, 2, 2) | ivec4(1, 4, -8, 2) ];
+ output int out0 = [ -3 | 1 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int sum(ivec4 v) { return (v.x + v.y + v.z + v.w); }
+
+ int func (int a, ivec3 b, ivec2 c, ivec2 d, ivec4 e)
+ {
+ return -sum(ivec4(a, b) + ivec4(c, d)) + sum(e);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0.y, in0.xzw, in0.wz, in0.yx, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case argument_eval_order_1
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 3 | 5 ];
+ output int out0 = [ -1 | 5 | 11 | 17 ];
+ }
+
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ int func (float a, int b, bool c, int d)
+ {
+ if (c)
+ return b + int(a) + d;
+ else
+ return -1;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ float v0 = float(in0);
+ int v1 = in0;
+ out0 = func((v0 += 1.0), v1++, (v0 > 1.5), v1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case argument_eval_order_2
+ version 300 es
+ values
+ {
+ input int in0 = [ 0 | -1 | 3 | 5 ];
+ output int out0 = [ 3 | -1 | 9 | 13 ];
+ }
+
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ int g;
+
+ int modG (int v)
+ {
+ g += v;
+ return v;
+ }
+
+ int func (float a, int b, bool c, int d)
+ {
+ if (c)
+ return b + int(a) + d;
+ else
+ return -1;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ out0 = func(float(g = in0), modG(2), --g > 0, g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # misc
+
+group invalid "Invalid Functions"
+ case break_in_body
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func ()
+ {
+ break;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case continue_in_body
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func ()
+ {
+ continue;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_value_from_void_function
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func ()
+ {
+ return 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case extra_arguments
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (float f)
+ {
+ }
+
+ void main ()
+ {
+ func(1.0, 2.0);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_arguments
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (float f)
+ {
+ }
+
+ void main ()
+ {
+ func();
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_argument_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (in f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_basetype_mismatch
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (float f)
+ {
+ }
+
+ void main ()
+ {
+ func(2);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_scalar_vector_mismatch
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec2 f)
+ {
+ }
+
+ void main ()
+ {
+ func(2.0);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_vector_size_mismatch
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ func(vec2(2.0));
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case duplicate_function
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f);
+
+ void func (vec3 f)
+ {
+ }
+
+ void func (vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f);
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ float func (vec3 f)
+ {
+ return f.x;
+ }
+ ""
+ end
+
+ case prototype_unspecified_array_size
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f[]);
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case call_mismatch_argument_array_size
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f[3]);
+ void func (vec3 f[3])
+ {
+ }
+
+ void main ()
+ {
+ vec3 array[4];
+ func(array);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_argument_const
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f);
+ void func (const vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_argument_array_const
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f[3]);
+ void func (const vec3 f[3])
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case prototype_mismatch_array_inout
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (out vec3 f);
+ void func (inout vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ func (float f);
+ func (inout vec3 f[3])
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case call_before_definition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ func(1.0);
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ void func (float f)
+ {
+ }
+
+ ""
+ end
+
+ case argument_precision_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (lowp float f)
+ {
+ return f;
+ }
+
+ float func (mediump float f)
+ {
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_in_out_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (in float f)
+ {
+ }
+
+ void func (out float f)
+ {
+ f = 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_in_inout_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (in float f)
+ {
+ }
+
+ void func (inout float f)
+ {
+ f = -f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case argument_out_inout_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (out float f)
+ {
+ f = -1.0;
+ }
+
+ void func (inout float f)
+ {
+ f = -f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_type_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f)
+ {
+ return f;
+ }
+
+ int func (float f)
+ {
+ return int(f);
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_type_precision_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ lowp float func (float f)
+ {
+ return f;
+ }
+
+ mediump float func (float f)
+ {
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_type_const_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f)
+ {
+ return f;
+ }
+
+ const float func (float f)
+ {
+ return f;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case return_without_value
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f)
+ {
+ return;
+ return 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case local_function_prototype
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float func (float f);
+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case local_function_definition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float func (float f)
+ {
+ return 1.0;
+ }
+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case name_type_conflict
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct foo { float a; }
+
+ float foo (float f)
+ {
+ return 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case const_overload
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f)
+ {
+ }
+
+ void func (const vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_local
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f)
+ {
+ uniform float u;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case in_local
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f)
+ {
+ in float v;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case out_local
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f)
+ {
+ in float a;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case inout_local
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (vec3 f)
+ {
+ inout float a;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_argument
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (uniform vec3 f)
+ {
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case uniform_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ uniform float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case in_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ in float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(vec3(1.0)));
+ }
+ ""
+ end
+
+ case out_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ out float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(vec3(1.0)));
+ }
+ ""
+ end
+
+ case inout_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ inout float func (vec3 f)
+ {
+ return f.x;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(vec3(1.0)));
+ }
+ ""
+ end
+
+ case main_invalid_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case main_has_arguments
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main (float f)
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case main_missing_return_type
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case write_const_arg
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (const float f)
+ {
+ f = 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case write_const_array_arg
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (const float f[3])
+ {
+ f[0] = 1.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case use_const_arg_in_const_expr
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (const int i)
+ {
+ const int z = i+1;
+ return float(z);
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1));
+ }
+ ""
+ end
+
+ case use_const_arg_as_array_size
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (const int i)
+ {
+ float f[i];
+ f[0] = 1.0;
+ return f[0];
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1));
+ }
+ ""
+ end
+
+ case overload_builtin_function
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int sin (int x)
+ {
+ return int(sin(float(x)));
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(sin(1));
+ }
+ ""
+ end
+
+ case redefine_builtin_function
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sin (float x)
+ {
+ return 0.0;
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
+ }
+ ""
+ end
+
+ case basic_recursion
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float fib (float x)
+ {
+ if (x <= 1.0)
+ return x;
+ else
+ return fib(x-2.0) + fib(x-1.0);
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(fib(5.0));
+ }
+ ""
+ end
+
+ case simple_tail_recursion
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float rec (float x)
+ {
+ if (x <= 0.0)
+ return 0.0;
+ else
+ return rec(x-1.0);
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(rec(5.0));
+ }
+ ""
+ end
+
+ case dynamic_conditional_recursion
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform float ua;
+ uniform float ub;
+
+ float funcA (float x);
+ float funcB (float x);
+
+ float funcA (float x)
+ {
+ if (ub+x > 0.0)
+ funcB(x*2.0);
+ else
+ return ub;
+ }
+
+ float funcB (float x)
+ {
+ return sqrt(funcA(x));
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(funcB(ua));
+ }
+ ""
+ end
+
+ case dynamic_loop_recursion
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform float ua;
+ uniform float ub;
+
+ float funcA (float x);
+ float funcB (float x);
+
+ float funcA (float x)
+ {
+ for (float z = 0.0; z < ub+x; z++)
+ {
+ if (z > 2.0)
+ funcB(z*2.0);
+ else
+ return z;
+ }
+ }
+
+ float funcB (float x)
+ {
+ return sqrt(funcA(x));
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(funcB(ua));
+ }
+ ""
+ end
+
+ case dynamic_switch_recursion
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform float ua;
+ uniform mediump int ub;
+
+ float funcA (float x);
+ float funcB (float x);
+
+ float funcA (float x)
+ {
+ switch (ub + int(x))
+ {
+ case 0: return ua-1.0;
+ case 1: return ua;
+ case 2: return funcB(x*2.0);
+ default: return 0.0;
+ }
+ }
+
+ float funcB (float x)
+ {
+ return sqrt(funcA(x));
+ }
+
+ void main ()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(funcB(ua));
+ }
+ ""
+ end
+
+ case modify_const_arg
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(3));
+ }
+ ""
+ end
+
+ case init_const_local_from_const_arg
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ const int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(3));
+ }
+ ""
+ end
+
+ case array_size_from_const_arg
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ int arr[a];
+ arr[1] = 3;
+ return arr[1];
+ }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(3));
+ }
+ ""
+ end
+
+end # invalid
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.html
new file mode 100644
index 0000000000..98c13381d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'invalid_texture_functions';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.test
new file mode 100644
index 0000000000..10d65b22ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/invalid_texture_functions.test
@@ -0,0 +1,1143 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+case texture_sampler3dshadow_vec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler3DShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texture(s, vec4(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texture_sampler2darrayshadow_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texture(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_samplercube_vec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_isamplercube_vec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump isamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_usamplercube_vec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump usamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_samplercube_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_isamplercube_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump isamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_usamplercube_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump usamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_sampler2darrayshadow_vec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureproj_sampler2darrayshadow_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProj(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelod_samplercubeshadow_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLod(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelod_sampler2darrayshadow_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLod(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_samplercube_vec3_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_isamplercube_vec3_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump isamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_usamplercube_vec3_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump usamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_samplercube_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_isamplercube_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump isamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_usamplercube_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump usamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_samplercube_vec3_ivec2_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec2(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_samplercube_vec3_ivec3_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec3(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_sampler2darray_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_sampler2darray_vec3_ivec3_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec3(0), ivec3(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_samplercubeshadow_vec4_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec4(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_samplercubeshadow_vec4_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec4(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_sampler2darrayshadow_vec4_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec4(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureoffset_sampler2darrayshadow_vec4_ivec2_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureOffset(s, vec4(0), ivec2(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_samplercube_ivec3_int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_isamplercube_ivec3_int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump isamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_usamplercube_ivec3_int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump usamplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_sampler2dshadow_ivec2_int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec2(0), int(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_samplercubeshadow_ivec3_int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_sampler2darrayshadow_ivec3_int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_samplercube_ivec3_int_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_sampler2dshadow_ivec2_int_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec2(0), int(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_samplercubeshadow_ivec3_int_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texelfetch_sampler2darrayshadow_ivec3_int_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(texelFetch(s, ivec3(0), int(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojoffset_samplercube_vec4_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjOffset(s, vec4(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojoffset_samplercube_vec4_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjOffset(s, vec4(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojoffset_samplercubeshadow_vec4_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjOffset(s, vec4(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojoffset_sampler2darrayshadow_vec4_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjOffset(s, vec4(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojoffset_sampler2darrayshadow_vec4_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjOffset(s, vec4(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelodoffset_samplercube_vec3_float_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLodOffset(s, vec3(0), float(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelodoffset_samplercube_vec3_float_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLodOffset(s, vec3(0), float(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelodoffset_samplercubeshadow_vec3_float_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLodOffset(s, vec3(0), float(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelodoffset_sampler2darrayshadow_vec3_float_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLodOffset(s, vec3(0), float(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturelodoffset_sampler2darrayshadow_vec3_float_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureLodOffset(s, vec3(0), float(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojlod_samplercube_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjLod(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojlod_sampler2darray_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjLod(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojlod_sampler2darrayshadow_vec4_float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArrayShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjLod(s, vec4(0), float(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturegrad_sampler2darray_vec3_vec3_vec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureGrad(s, vec3(0), vec3(0), vec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturegradoffset_samplercube_vec3_vec3_vec3_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureGradOffset(s, vec3(0), vec3(0), vec3(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturegradoffset_samplercube_vec3_vec3_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureGradOffset(s, vec3(0), vec3(0), vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturegradoffset_samplercubeshadow_vec4_vec3_vec3_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureGradOffset(s, vec4(0), vec3(0), vec3(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case texturegradoffset_samplercubeshadow_vec4_vec3_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCubeShadow s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureGradOffset(s, vec4(0), vec3(0), vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojgrad_samplercube_vec4_vec3_vec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjGrad(s, vec4(0), vec3(0), vec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojgrad_sampler2darray_vec4_vec2_vec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjGrad(s, vec4(0), vec2(0), vec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojgradoffset_samplercube_vec4_vec3_vec3_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjGradOffset(s, vec4(0), vec3(0), vec3(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojgradoffset_samplercube_vec4_vec3_vec3_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump samplerCube s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjGradOffset(s, vec4(0), vec3(0), vec3(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojgradoffset_sampler2darray_vec4_vec2_vec2_ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjGradOffset(s, vec4(0), vec2(0), vec2(0), ivec2(0)));
+ ${OUTPUT}
+ }
+ ""
+end
+case textureprojgradoffset_sampler2darray_vec4_vec2_vec2_ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ uniform mediump sampler2DArray s;
+
+ void main()
+ {
+ ${SETUP}
+ ${POSITION_FRAG_COLOR} = vec4(textureProjGradOffset(s, vec4(0), vec2(0), vec2(0), ivec3(0)));
+ ${OUTPUT}
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.html
new file mode 100644
index 0000000000..5899a9a279
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'keywords';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.test
new file mode 100644
index 0000000000..b588cd74e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/keywords.test
@@ -0,0 +1,3219 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group keywords "Usage of keywords as identifiers."
+
+ case const
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float const = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uniform
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uniform = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case layout
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float layout = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case centroid
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float centroid = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case flat
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float flat = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case smooth
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float smooth = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case break
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float break = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case continue
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float continue = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case do
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float do = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case for
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float for = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case while
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float while = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case switch
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float switch = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case case
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float case = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case default
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float default = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case if
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float if = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case else
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float else = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case in
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float in = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case out
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float out = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case inout
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float inout = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case float
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float float = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case int
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float int = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case void
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float void = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bool
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bool = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case true
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float true = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case false
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float false = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case invariant
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float invariant = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case discard
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float discard = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case return
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float return = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat2x2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat2x2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat2x3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat2x3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat2x4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat2x4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat3x2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat3x2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat3x3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat3x3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat3x4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat3x4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat4x2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat4x2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat4x3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat4x3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mat4x4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mat4x4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case vec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float vec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case vec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float vec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case vec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float vec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case ivec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float ivec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case ivec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float ivec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case ivec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float ivec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bvec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bvec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case bvec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float bvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uint
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uint = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uvec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uvec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uvec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case lowp
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float lowp = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case mediump
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float mediump = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case highp
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float highp = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float precision = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler3D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case samplerCube
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float samplerCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case samplerCubeShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float samplerCubeShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DArrayShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DArrayShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler2D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler3D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isamplerCube
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isamplerCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler2DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler2DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler2D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler3D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usamplerCube
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usamplerCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler2DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler2DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case struct
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float struct = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # keywords
+group reserved_keywords "Usage of reserved keywords as identifiers."
+
+ case attribute
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float attribute = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case varying
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float varying = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case coherent
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float coherent = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case restrict
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float restrict = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case readonly
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float readonly = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case writeonly
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float writeonly = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case resource
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float resource = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case atomic_uint
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float atomic_uint = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case noperspective
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float noperspective = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case patch
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float patch = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sample
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sample = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case subroutine
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float subroutine = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case common
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float common = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case partition
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float partition = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case active
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float active = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case asm
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float asm = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case class
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float class = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case union
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float union = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case enum
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float enum = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case typedef
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float typedef = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case template
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float template = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case this
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float this = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case goto
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float goto = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case inline
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float inline = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case noinline
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float noinline = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case volatile
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float volatile = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case public
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float public = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case static
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float static = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case extern
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float extern = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case external
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float external = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case interface
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float interface = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case long
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float long = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case short
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float short = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case double
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float double = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case half
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float half = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fixed
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fixed = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case unsigned
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float unsigned = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case superp
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float superp = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case input
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float input = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case output
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float output = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case hvec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float hvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case hvec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float hvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case hvec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float hvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case dvec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float dvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case dvec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float dvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case dvec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float dvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fvec2
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fvec2 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fvec3
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fvec3 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case fvec4
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float fvec4 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler3DRect
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler3DRect = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case filter
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float filter = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image1D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image2D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image3D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case imageCube
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float imageCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimage1D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimage1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimage2D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimage2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimage3D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimage3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimageCube
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimageCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimage1D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimage1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimage2D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimage2D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimage3D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimage3D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimageCube
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimageCube = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image1DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image1DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image2DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image2DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimage1DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimage1DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimage2DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimage2DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimage1DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimage1DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimage2DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimage2DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image1DShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image1DShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image2DShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image2DShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image1DArrayShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image1DArrayShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case image2DArrayShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float image2DArrayShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case imageBuffer
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float imageBuffer = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case iimageBuffer
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float iimageBuffer = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case uimageBuffer
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float uimageBuffer = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler1D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler1DShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler1DShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler1DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler1DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler1DArrayShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler1DArrayShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler1D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler1DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler1DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler1D
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler1D = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler1DArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler1DArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DRect
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DRect = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DRectShadow
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DRectShadow = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler2DRect
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler2DRect = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler2DRect
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler2DRect = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case samplerBuffer
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float samplerBuffer = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isamplerBuffer
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isamplerBuffer = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usamplerBuffer
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usamplerBuffer = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DMS
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DMS = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler2DMS
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler2DMS = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler2DMS
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler2DMS = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sampler2DMSArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sampler2DMSArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case isampler2DMSArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float isampler2DMSArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case usampler2DMSArray
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float usampler2DMSArray = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case sizeof
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float sizeof = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case cast
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float cast = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case namespace
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float namespace = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case using
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float using = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # reserved_keywords
+group invalid_identifiers "Usage of invalid identifiers."
+
+ case gl_begin
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float gl_Invalid = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case digit
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float 0123 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case digit_begin
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float 0invalid = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+ case max_length
+ expect compile_fail
+ values {}
+ version 300 es
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdX = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # invalid_identifiers
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.html
new file mode 100644
index 0000000000..c6ebbbc051
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'linkage';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.test
new file mode 100644
index 0000000000..4cdaa06180
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/linkage.test
@@ -0,0 +1,3833 @@
+
+# Varying tests
+group varying "Varying linkage"
+
+ # Linking rules
+ group rules "Varying linking rules"
+ # not declared in vertex shader, declared in fragment shader
+ case fragment_declare
+ version 300 es
+ desc "varying declared in fragment shader, no reference in vertex shader"
+ values { output float out0 = 1.0; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # declared in vertex shader, no reference in frag shader
+ case vertex_declare
+ version 300 es
+ desc "varying declared in vertex shader, no reference in fragment shader"
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # declared in vertex shader, declared in frag shader
+ case both_declare
+ version 300 es
+ desc "varying declared in both vertex and fragment shader, but not used"
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # declared in vertex shader, static use in frag shader
+ case vertex_declare_fragment_use
+ version 300 es
+ desc "varying declared in both shaders, statically used in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ if (u_false)
+ ${FRAG_COLOR} = vec4(var);
+ else
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # static use in vertex shader, no reference in fragment shader
+ case vertex_use_fragment_declare
+ version 300 es
+ desc "varying declared and statically used in vertex shader, no reference in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # static use in vertex shader, declared in fragment shader
+ case vertex_use_declare_fragment
+ version 300 es
+ desc "varying declared and statically used in vertex shader, only declared in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # static use in vertex shader, used in fragment shader
+ case vertex_use_fragment_use
+ version 300 es
+ desc "varying statically used in both vertex and fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var;
+ void main()
+ {
+ if (u_false)
+ ${FRAG_COLOR} = vec4(var);
+ else
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # differing precision tests
+ case differing_precision_1
+ version 300 es
+ desc "varying declared as highp in vertex shader, but mediump in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.55 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.55 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out highp float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # differing precision tests
+ case differing_precision_2
+ version 300 es
+ desc "varying declared as highp in vertex shader, but lowp in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.56 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.56 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out highp vec2 var;
+ void main()
+ {
+ var = vec2(in0, 2.0*in0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in lowp vec2 var;
+ void main()
+ {
+ out0 = var.y - var.x;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # differing precision tests
+ case differing_precision_3
+ version 300 es
+ desc "varying declared as lowp in vertex shader, but mediump in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out lowp vec4 var;
+ void main()
+ {
+ var = vec4(in0, 2.0*in0, -in0, -in0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump vec4 var;
+ void main()
+ {
+ out0 = var.x + var.y + var.z + var.w;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # mismatched type, static use but no runtime use in the fragment shader
+ case type_mismatch_1
+ version 300 es
+ desc "varying type mismatch (float vs. vec2), static use but no runtime use in the fragment shader"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ var = 2.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump vec2 var;
+ void main()
+ {
+ if (false)
+ {
+ ${FRAG_COLOR} = vec4(var.y);
+ }
+ else
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ }
+ ""
+ end
+
+ # mismatched type, varyings used
+ case type_mismatch_2
+ version 300 es
+ desc "varying type mismatch (float vs. vec2)"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ var = 2.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump vec2 var;
+ void main()
+ {
+ ${FRAG_COLOR} = var.xyyx;
+ }
+ ""
+ end
+
+ # mismatched type, varyings used
+ case type_mismatch_3
+ version 300 es
+ desc "varying type mismatch (int vs. uint)"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump int var;
+ void main()
+ {
+ var = 2;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in mediump uint var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(var);
+ }
+ ""
+ end
+
+ # mismatched type, varyings used
+ case struct_type_mismatch_1
+ version 300 es
+ desc "struct member mismatch"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { highp float a; highp vec2 b; };
+ out S var;
+ void main()
+ {
+ var.a = 2.0;
+ var.b = vec2(1.0, 0.0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { highp float a; highp vec3 b; };
+ in S var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(var.a, var.b);
+ }
+ ""
+ end
+
+ # mismatched type, varyings unused in fragment shader (runtime)
+ case struct_type_mismatch_2
+ version 300 es
+ desc "struct member mismatch"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { highp float a; highp vec2 b; };
+ out S var;
+ void main()
+ {
+ var.a = 2.0;
+ var.b = vec2(1.0, 0.0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { highp float a; highp vec3 b; };
+ in S var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(var.a);
+ if (false)
+ ${FRAG_COLOR}.yzw = var.b;
+ }
+ ""
+ end
+
+ # mismatched type, varyings unused in both (runtime)
+ case struct_type_mismatch_3
+ version 300 es
+ desc "struct member mismatch"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { highp float a; highp vec2 b; };
+ out S var;
+ void main()
+ {
+ var.a = 2.0;
+ if (false)
+ var.b = vec2(1.0, 0.0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { highp float a; highp vec3 b; };
+ in S var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(var.a);
+ if (false)
+ ${FRAG_COLOR}.yzw = var.b;
+ }
+ ""
+ end
+
+ # interpolation_mismatch
+ case interpolation_mismatch_1
+ version 300 es
+ desc "varying interpolation different (flat vs. smooth)"
+ expect link_fail
+
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ in highp float in0;
+ flat out mediump float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(var);
+ }
+ ""
+ end
+
+ # different interpolation
+ case differing_interpolation_2
+ version 300 es
+ desc "varying interpolation different (smooth vs. centroid)"
+ values
+ {
+ input float in0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ smooth out mediump float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ centroid in mediump float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # no declaration in vertex shader, but static use in fragment
+ case illegal_usage_1
+ version 300 es
+ desc "varying not declared in vertex shader, but statically used in fragment shader"
+ expect link_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(var);
+ }
+ ""
+ end
+
+ # non-flat integer varyings not allowed
+ case invalid_type_int
+ version 300 es
+ desc "integer varying used"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump int var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump int var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # non-flat integer varyings not allowed
+ case invalid_type_uint
+ version 300 es
+ desc "integer varying used"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump uint var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump uint var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # bool varyings not allowed
+ case invalid_type_bool
+ version 300 es
+ desc "boolean varying used"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out bool var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in bool var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_type_struct_array
+ version 300 es
+ desc "float array inside struct"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a[3]; };
+ out S var;
+ void main()
+ {
+ var.a[0] = 1.0;
+ var.a[1] = 1.0;
+ var.a[2] = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a[3]; };
+ in S var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_type_struct_struct
+ version 300 es
+ desc "struct inside struct"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; };
+ struct T { S s; };
+ out T var;
+ void main()
+ {
+ var.s.a = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; };
+ struct T { S s; };
+ in T var;
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_type_array_struct
+ version 300 es
+ desc "array of structs"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump int a; };
+ flat out S var[2];
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var[0].a = 1;
+ var[1].a = 1;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump int a; };
+ flat in S var[2];
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_type_array_array
+ version 300 es
+ desc "array of arrays"
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var[2][2];
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var[0][0] = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var[2][2];
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+ end
+
+ group basic_types "Basic varying types"
+ case float
+ version 300 es
+ desc "varying of type float"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec2
+ version 300 es
+ desc "varying of type vec2"
+ values
+ {
+ input vec2 in0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ output vec2 out0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump vec2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in vec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec3
+ version 300 es
+ desc "varying of type vec3"
+ values
+ {
+ input vec3 in0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump vec3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in vec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4
+ version 300 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ version 300 es
+ desc "varying of type mat2"
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3
+ version 300 es
+ desc "varying of type mat2x3"
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat2x3 out0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat2x3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat2x3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4
+ version 300 es
+ desc "varying of type mat2x4"
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat2x4 out0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat2x4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat2x4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2
+ version 300 es
+ desc "varying of type mat3x2"
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat3x2 out0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat3x2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat3x2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3
+ version 300 es
+ desc "varying of type mat3"
+ values
+ {
+ input mat3 in0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ output mat3 out0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4
+ version 300 es
+ desc "varying of type mat3x4"
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat3x4 out0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat3x4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat3x4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2
+ version 300 es
+ desc "varying of type mat4x2"
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat4x2 out0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat4x2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat4x2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3
+ version 300 es
+ desc "varying of type mat4x3"
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat4x3 out0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat4x3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat4x3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4
+ version 300 es
+ desc "varying of type mat4"
+ values
+ {
+ input mat4 in0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ output mat4 out0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 300 es
+ desc "varying of type int"
+ values
+ {
+ input int in0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ output int out0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump int var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in int var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2
+ version 300 es
+ desc "varying of type ivec2"
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ output ivec2 out0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump ivec2 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in ivec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3
+ version 300 es
+ desc "varying of type ivec3"
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ output ivec3 out0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump ivec3 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in ivec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4
+ version 300 es
+ desc "varying of type ivec4"
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ output ivec4 out0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump ivec4 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in ivec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uint
+ version 300 es
+ desc "varying of type int"
+ values
+ {
+ input uint in0 = [ 1 | 2 | 3 | 16 ];
+ output uint out0 = [ 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uint var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uint var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2
+ version 300 es
+ desc "varying of type uvec2"
+ values
+ {
+ input uvec2 in0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uvec2 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uvec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3
+ version 300 es
+ desc "varying of type uvec3"
+ values
+ {
+ input uvec3 in0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ output uvec3 out0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uvec3 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uvec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4
+ version 300 es
+ desc "varying of type uvec4"
+ values
+ {
+ input uvec4 in0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ output uvec4 out0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uvec4 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uvec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group struct "Structure varyings"
+ case float
+ version 300 es
+ desc "varying of type float inside struct"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec2
+ version 300 es
+ desc "varying of type vec2 inside struct"
+ values
+ {
+ input vec2 in0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ output vec2 out0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump vec2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump vec2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec3
+ version 300 es
+ desc "varying of type vec3 inside struct"
+ values
+ {
+ input vec3 in0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump vec3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump vec3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4
+ version 300 es
+ desc "varying of type vec4 inside struct"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump vec4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump vec4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ version 300 es
+ desc "varying of type mat2 inside struct"
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3
+ version 300 es
+ desc "varying of type mat2x3 inside struct"
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat2x3 out0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat2x3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat2x3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4
+ version 300 es
+ desc "varying of type mat2x4 inside struct"
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat2x4 out0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat2x4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat2x4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2
+ version 300 es
+ desc "varying of type mat3x2 inside struct"
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat3x2 out0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat3x2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat3x2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3
+ version 300 es
+ desc "varying of type mat3 inside struct"
+ values
+ {
+ input mat3 in0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ output mat3 out0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4
+ version 300 es
+ desc "varying of type mat3x4 inside struct"
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat3x4 out0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat3x4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat3x4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2
+ version 300 es
+ desc "varying of type mat4x2 inside struct"
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat4x2 out0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat4x2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat4x2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3
+ version 300 es
+ desc "varying of type mat4x3 inside struct"
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat4x3 out0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat4x3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat4x3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4
+ version 300 es
+ desc "varying of type mat4 inside struct"
+ values
+ {
+ input mat4 in0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ output mat4 out0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 300 es
+ desc "varying of type int inside struct"
+ values
+ {
+ input int in0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ output int out0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump int a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump int a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2
+ version 300 es
+ desc "varying of type ivec2 inside struct"
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ output ivec2 out0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump ivec2 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump ivec2 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3
+ version 300 es
+ desc "varying of type ivec3 inside struct"
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ output ivec3 out0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump ivec3 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump ivec3 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4
+ version 300 es
+ desc "varying of type ivec4 inside struct"
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ output ivec4 out0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump ivec4 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump ivec4 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uint
+ version 300 es
+ desc "varying of type uint in struct"
+ values
+ {
+ input uint in0 = [ 1 | 2 | 3 | 16 ];
+ output uint out0 = [ 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uint a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uint a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2
+ version 300 es
+ desc "varying of type uvec2 inside struct"
+ values
+ {
+ input uvec2 in0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uvec2 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uvec2 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3
+ version 300 es
+ desc "varying of type uvec3 inside struct"
+ values
+ {
+ input uvec3 in0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ output uvec3 out0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uvec3 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uvec3 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4
+ version 300 es
+ desc "varying of type uvec4 inside struct"
+ values
+ {
+ input uvec4 in0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ output uvec4 out0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uvec4 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uvec4 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec3
+ version 300 es
+ desc "varyings of type float and vec3 inside struct"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ input vec3 in1 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out1 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; highp vec3 b; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ var.b = in1;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; highp vec3 b; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ out1 = var.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_vec3
+ version 300 es
+ desc "varyings of type float and vec3 inside struct"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ input uvec2 in1 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) | uvec2(8, 7) ];
+ output uvec2 out1 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) | uvec2(8, 7) ];
+ input vec3 in2 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out2 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; highp uvec2 b; highp vec3 c; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ var.b = in1;
+ var.c = in2;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; highp uvec2 b; highp vec3 c; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ out1 = var.b;
+ out2 = var.c;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group interpolation "Varying interpolation modes"
+ case smooth
+ version 300 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ smooth out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ smooth in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case centroid
+ version 300 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ centroid out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ centroid in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case flat
+ version 300 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ flat in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group usage "Varying usage in shaders"
+ case readback_1
+ version 300 es
+ desc "read back (an already written) varying in the vertex shader"
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -2.0 | 10.0 ];
+ output float out0 = [ 3.0 | 0.0 | -6.0 | 30.0 ];
+ }
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ ${VERTEX_DECLARATIONS}
+ out float var1;
+ out float var2;
+
+ void main()
+ {
+ var1 = in0;
+ var2 = var1 + in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in float var1;
+ in float var2;
+
+ void main()
+ {
+ out0 = var1 + var2;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case writeback_1
+ version 300 es
+ desc "write back a varying in the fragment shader"
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -2.0 | 10.0 ];
+ }
+ expect compile_fail
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ ${VERTEX_DECLARATIONS}
+ out float var1;
+ out float var2;
+
+ void main()
+ {
+ var1 = in0;
+ var2 = var1 + in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in float var1;
+ in float var2;
+
+ void main()
+ {
+ var2 = var1;
+ out0 = var1;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+end
+
+group uniform "Uniform linkage"
+ group basic "Default block uniforms of scalar and vector types"
+ case precision_conflict_1
+ version 300 es
+ desc "Vertex side uniform has highp, fragment side uniform mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ uniform highp float u_val;
+ out mediump float res;
+ void main()
+ {
+ res = u_val;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ uniform float u_val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = u_val + res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ case precision_conflict_2
+ version 300 es
+ desc "Vertex side uniform has highp, fragment side uniform mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ uniform highp float u_val;
+ out mediump float res;
+ void main()
+ {
+ res = u_val;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision highp float;
+ uniform mediump float u_val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = u_val + res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ case precision_conflict_3
+ version 300 es
+ desc "Vertex side uniform has lowp, fragment side uniform highp."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ uniform lowp int u_val;
+ out mediump float res;
+ void main()
+ {
+ res = float(u_val);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision highp float;
+ uniform highp int u_val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = float(u_val) + res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ case precision_conflict_4
+ version 300 es
+ desc "Vertex side uniform has lowp, fragment side uniform mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ uniform lowp vec3 u_val;
+ out mediump float res;
+ void main()
+ {
+ res = u_val.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision highp float;
+ uniform mediump vec3 u_val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = u_val.z + res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group struct "Uniform structs"
+ # Struct linkage handling
+ case basic
+ version 300 es
+ desc "Same uniform struct in both shaders"
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ out mediump float dummy;
+ void main()
+ {
+ dummy = val.a + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ in mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.b + val.a;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vertex_only
+ version 300 es
+ desc "Uniform struct declared in both, used only in vertex."
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ in mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case fragment_only
+ version 300 es
+ desc "Uniform struct declared in both, used only in fragment."
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.a + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both."
+ values {
+ uniform float val.a = 1.0;
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = res + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4
+ version 300 es
+ desc "Same uniform struct in both shaders. Datatype vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ out mediump float dummy;
+ void main()
+ {
+ dummy = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ in mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = val.b.y + val.a.x;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vertex_only_vec4
+ version 300 es
+ desc "Uniform struct declared in both, used only in vertex. Datatype vec4 "
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ in mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case fragment_only_vec4
+ version 300 es
+ desc "Uniform struct declared in both, used only in fragment. Datatype vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = val.a.x + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec4
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec4 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec3
+ version 300 es
+ desc "Same uniform struct in both shaders. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ out mediump float dummy;
+ void main()
+ {
+ dummy = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ in mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = val.b.y + val.a.x;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vertex_only_vec4_vec3
+ version 300 es
+ desc "Uniform struct declared in both, used only in vertex. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x + val.b.y;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ in mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case fragment_only_vec4_vec3
+ version 300 es
+ desc "Uniform struct declared in both, used only in fragment. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = val.a.x + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec4_vec3
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump vec3 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_float
+ version 300 es
+ desc "Same uniform struct in both shaders. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ out mediump float dummy;
+ void main()
+ {
+ dummy = val.a.x + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ in mediump float dummy;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = val.b + val.a.x;
+ out0 = out0 + dummy;
+ out0 = out0 - dummy;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vertex_only_vec4_float
+ version 300 es
+ desc "Uniform struct declared in both, used only in vertex. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x + val.b;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ in mediump float res;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = res;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case fragment_only_vec4_float
+ version 300 es
+ desc "Uniform struct declared in both, used only in fragment. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ { out0 = val.a.x + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec4_float
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and float"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform float val.b = 2.0;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a; mediump float b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec4_struct
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and struct with vec4"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec4 val.b.c = vec4(1.0, 2.0, 3.0, 4.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Inner {mediump vec4 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Inner {mediump vec4 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.c.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec4_vec3_struct
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec4 and struct with vec3"
+ values {
+ uniform vec4 val.a = vec4(1.0, 2.0, 3.0, 4.0);
+ uniform vec3 val.b.c = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Inner {mediump vec3 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Inner {mediump vec3 c;};
+ struct Struct {mediump vec4 a; Inner b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.c.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec2_vec3
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec2 and vec3"
+ values {
+ uniform vec2 val.a = vec2(1.0, 2.0);
+ uniform vec3 val.b = vec3(1.0, 2.0, 3.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec2 a; mediump vec3 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec2 a; mediump vec3 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_vec2_int
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype vec2 and int"
+ values {
+ uniform vec2 val.a = vec2(1.0, 2.0);
+ uniform int val.b = 2;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec2 a; mediump int b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec2 a; mediump int b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + float(val.b);
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_int_float
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype int and float"
+ values {
+ uniform float val.a = 1.0;
+ uniform int val.b = 2;
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump int b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a; mediump int b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + float(val.b);
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_bvec2_vec2
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype bvec2 and vec2"
+ values {
+ uniform bvec2 val.a = bvec2(true, true);
+ uniform vec2 val.b = vec2(1.0, 2.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {bvec2 a; mediump vec2 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = float(val.a.x);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {bvec2 a; mediump vec2 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_ivec2_vec2
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype ivec2 and vec2"
+ values {
+ uniform ivec2 val.a = ivec2(1, 2);
+ uniform vec2 val.b = vec2(1.0, 2.0);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump ivec2 a; mediump vec2 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = vec2(val.a).x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump ivec2 a; mediump vec2 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.b.y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case partial_ivec2_ivec2
+ version 300 es
+ desc "Uniform struct declared in both, used partially in both. Datatype ivec2 and ivec2"
+ values {
+ uniform ivec2 val.a = ivec2(1, 2);
+ uniform ivec2 val.b = ivec2(1, 2);
+ output float out0 = 3.0;
+ }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump ivec2 a; mediump ivec2 b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = vec2(val.a).x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump ivec2 a; mediump ivec2 b;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + vec2(val.b).y;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case type_conflict_1
+ version 300 es
+ desc "Fragment struct has one less member than fragment version"
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a; mediump float b;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = res + val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case type_conflict_2
+ version 300 es
+ desc "Vertex struct has int, fragment struct has float."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump int a;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = float(val.a);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case type_conflict_3
+ version 300 es
+ desc "Vertex struct has vec3, fragment struct has vec4."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump vec3 a;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = float(val.a.x);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump vec4 a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = val.a.x;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case precision_conflict_1
+ version 300 es
+ desc "Vertex side struct has highp, fragment side struct mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {highp float a;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case precision_conflict_2
+ version 300 es
+ desc "Vertex side struct has mediump, fragment side struct lowp."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {lowp float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case precision_conflict_3
+ version 300 es
+ desc "Vertex side struct has lowp, fragment side struct mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {lowp float a;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {mediump float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case precision_conflict_4
+ version 300 es
+ desc "Vertex side struct has lowp, fragment side struct implicit mediump."
+ expect link_fail
+ values {output float out0 = 3.0;}
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ struct Struct {lowp float a;};
+ uniform Struct val;
+ out mediump float res;
+ void main()
+ {
+ res = val.a;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Struct {float a;};
+ uniform Struct val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ { out0 = val.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case light_struct_highp
+ version 300 es
+ desc "Complex Light struct from use case tests."
+ values {
+ uniform float val.constantAttenuation = 1.0;
+ uniform float val.quadraticAttenuation = 1.0;
+ output float out0 = 2.0;
+ }
+ vertex ""
+ #version 300 es
+ struct Light
+ {
+ mediump vec3 color;
+ highp vec4 position;
+ highp vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ ${VERTEX_DECLARATIONS}
+ uniform Light val;
+ out mediump float res;
+ void main()
+ {
+ res = val.constantAttenuation;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Light
+ {
+ mediump vec3 color;
+ highp vec4 position;
+ highp vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ struct Struct {float a;};
+ uniform Light val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = res + val.quadraticAttenuation;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case light_struct_mediump
+ version 300 es
+ desc "Complex Light struct from use case tests, without highp usage"
+ values {
+ uniform float val.constantAttenuation = 1.0;
+ uniform float val.quadraticAttenuation = 1.0;
+ output float out0 = 2.0;
+ }
+ vertex ""
+ #version 300 es
+ struct Light
+ {
+ mediump vec3 color;
+ mediump vec4 position;
+ mediump vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ ${VERTEX_DECLARATIONS}
+ uniform Light val;
+ out mediump float res;
+ void main()
+ {
+ res = val.constantAttenuation;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ struct Light
+ {
+ mediump vec3 color;
+ mediump vec4 position;
+ mediump vec3 direction;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+ };
+ struct Struct {float a;};
+ uniform Light val;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ out0 = res + val.quadraticAttenuation;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group block "Uniform blocks"
+ case type_mismatch
+ version 300 es
+ expect link_fail
+ vertex ""
+ #version 300 es
+
+ uniform Block
+ {
+ highp vec4 val;
+ };
+
+ ${VERTEX_DECLARATIONS}
+ out mediump float res;
+ void main()
+ {
+ res = val.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+
+ uniform Block
+ {
+ highp vec3 val;
+ };
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ dEQP_FragColor = vec4(val, 1.0);
+ }
+ ""
+ end
+
+ case members_mismatch
+ version 300 es
+ expect link_fail
+ vertex ""
+ #version 300 es
+
+ uniform Block
+ {
+ highp vec4 val;
+ };
+
+ ${VERTEX_DECLARATIONS}
+ out mediump float res;
+ void main()
+ {
+ res = val.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+
+ uniform Block
+ {
+ highp vec4 val;
+ lowp uint u;
+ };
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ dEQP_FragColor = vec4(val);
+ }
+ ""
+ end
+
+ case layout_qualifier_mismatch_2
+ version 300 es
+ expect compile_fail
+ vertex ""
+ #version 300 es
+
+ layout(shared) uniform Block
+ {
+ highp vec4 val;
+ };
+
+ ${VERTEX_DECLARATIONS}
+ out mediump float res;
+ void main()
+ {
+ res = val.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+
+ layout(packed) uniform Block
+ {
+ highp vec4 val;
+ };
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ dEQP_FragColor = vec4(val);
+ }
+ ""
+ end
+
+ case layout_qualifier_mismatch_3
+ version 300 es
+ expect link_fail
+ vertex ""
+ #version 300 es
+
+ layout(row_major) uniform Block
+ {
+ highp vec4 val;
+ };
+
+ ${VERTEX_DECLARATIONS}
+ out mediump float res;
+ void main()
+ {
+ res = val.x;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+
+ layout(column_major) uniform Block
+ {
+ highp vec4 val;
+ };
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ dEQP_FragColor = vec4(val);
+ }
+ ""
+ end
+
+ case layout_qualifier_mismatch_4
+ version 300 es
+ expect link_fail
+ vertex ""
+ #version 300 es
+
+ layout(row_major) uniform Block
+ {
+ highp mat3 val;
+ };
+
+ ${VERTEX_DECLARATIONS}
+ out mediump float res;
+ void main()
+ {
+ res = val[0][1];
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+
+ layout(column_major) uniform Block
+ {
+ highp mat3 val;
+ };
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ dEQP_FragColor = vec4(val[2], 1.0);
+ }
+ ""
+ end
+
+ case layout_qualifier_mismatch_5
+ version 300 es
+ expect link_fail
+ vertex ""
+ #version 300 es
+
+ uniform Block
+ {
+ layout(row_major) uniform highp mat3 val;
+ };
+
+ ${VERTEX_DECLARATIONS}
+ out mediump float res;
+ void main()
+ {
+ res = val[0][1];
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+
+ uniform Block
+ {
+ layout(column_major) uniform highp mat3 val;
+ };
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float res;
+ void main()
+ {
+ dEQP_FragColor = vec4(val[2], 1.0);
+ }
+ ""
+ end
+ end
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.html
new file mode 100644
index 0000000000..89236e542f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'negative';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.test
new file mode 100644
index 0000000000..c7b86eded4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/negative.test
@@ -0,0 +1,100 @@
+# Generic invalid cases that don't fall into other categories
+
+group c_cast "C-style casts"
+
+ case float_0
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ float a = 0.0;
+ float b = (float)a;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case float_1
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ int a = 0;
+ float b = (float)a;
+ ${POSITION_FRAG_COLOR} = vec4(b);
+ }
+ ""
+ end
+
+ case float_2
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ highp float a = 0.0;
+ mediump float b = (mediump float)a;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case int
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ float a = 0.0;
+ int b = (int)a;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case uint
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ float a = 0.0;
+ uint b = (uint)a;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case bool
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ int a = 1;
+ bool b = (bool)a;
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+end # casts
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.html
new file mode 100644
index 0000000000..f472cec46f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'preprocessor';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.test
new file mode 100644
index 0000000000..ebe3851965
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/preprocessor.test
@@ -0,0 +1,5256 @@
+group basic "Basic Tests"
+
+ case correct_phases
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #define e +1
+ ${DECLARATIONS}
+ void main()
+ {
+ mediump int n = 1e;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_identifier
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #define e +1
+ ${DECLARATIONS}
+ void main()
+ {
+ mediump int 1xyz = 1;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case null_directive
+ version 300 es
+ values { output float out0 = 0.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ #
+ # // comment
+ /*sfd*/ # /* */
+
+ void main()
+ {
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_directive
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #defin AAA
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case missing_identifier
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #define
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case empty_object
+ version 300 es
+ values { output float out0 = -1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ # define VALUE
+
+ void main()
+ {
+ out0 = VALUE - 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case empty_function
+ version 300 es
+ values { output float out0 = -1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ # define VALUE(a)
+
+ void main()
+ {
+ out0 = VALUE(2.0) - 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case empty_directive
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ #
+
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case identifier_with_double_underscore
+ values { output float out0 = 1.0; }
+ version 300 es
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define __VALUE__ 1
+
+ void main()
+ {
+ // __VALUE__ not used since it might be set by an "underlying software layer"
+ out0 = float(1.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+end # basic
+
+group definitions "Symbol Definition Tests"
+
+ case define_value_and_function
+ version 300 es
+ values { output float out0 = 6.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS:single-line}
+ # define VALUE (1.5 + 2.5)
+ # define FUNCTION(__LINE__, b) __LINE__+b
+
+ void main()
+ {
+ out0 = FUNCTION(VALUE, ((0.2) + 1.8) );
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case undefine_object_invalid_syntax
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define VAL 2.0
+ #undef VAL sdflkjfds
+ #define VAL 1.0
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VAL);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #undef __LINE__
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #undef __FILE__
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(__FILE__);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #undef __VERSION__
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(__VERSION__);
+ }
+ ""
+ end
+
+ case undefine_invalid_object_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #undef GL_ES
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(GL_ES);
+ }
+ ""
+ end
+
+ case undefine_function
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define FUNCTION(a,b) a+b
+ #undef FUNCTION
+ #define FUNCTION(a,b) a-b
+ ${DECLARATIONS}
+
+ void main()
+ {
+ out0 = FUNCTION(3.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # definitions
+
+group invalid_definitions "Invalid Definition Tests"
+
+ case define_non_identifier
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define 123 321
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case undef_non_identifier_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #undef 123
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case undef_non_identifier_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #undef foo.bar
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+
+end # invalid_definitions
+
+group object_redefinitions "Object Redefinition Tests"
+
+ case invalid_object_ident
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2.0
+ # define AAAA 2.1
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAAA - 1.0)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_whitespace
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA- 1.0)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_op
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA + 1.0)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_floatval_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA - 1.1)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_floatval_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2.0
+ # define VALUE (AAA - 1.0)
+ # define VALUE (AAA - 1.0e-1)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_intval_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2
+ # define VALUE (AAA - 1)
+ # define VALUE (AAA - 2)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case invalid_object_intval_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA 2
+ # define VALUE (AAA - 1)
+ # define VALUE (AAA - 0x1)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(VALUE);
+ }
+ ""
+ end
+
+ case redefine_object_1
+ version 300 es
+ values { output float out0 = 6.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define VAL1 1.0
+ #define VAL2 2.0
+
+ #define RES2 (RES1 * VAL2)
+ #define RES1 (VAL2 / VAL1)
+ #define RES2 (RES1 * VAL2)
+ #define VALUE (RES2 + RES1)
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_ifdef
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #ifdef ADEFINE
+ #define VALUE 1.0
+ #else
+ #define VALUE 0.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_undef_ifdef
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+ #undef ADEFINE
+
+ #ifdef ADEFINE
+ #define VALUE 0.0
+ #else
+ #define VALUE 1.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_ifndef
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #ifndef ADEFINE
+ #define VALUE 0.0
+ #else
+ #define VALUE 1.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_defined_1
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #if defined(ADEFINE)
+ #define VALUE 1.0
+ #else
+ #define VALUE 0.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_defined_2
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define ADEFINE 1
+ #define ADEFINE 1
+
+ #if defined ADEFINE
+ #define VALUE 1.0
+ #else
+ #define VALUE 0.0
+ #endif
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_comment
+ version 300 es
+ values { output float out0 = 6.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define VAL1 1.0
+ #define VAL2 2.0
+
+ #define RES2 /* fdsjklfdsjkl dsfjkhfdsjkh fdsjklhfdsjkh */ (RES1 * VAL2)
+ #define RES1 (VAL2 / VAL1)
+ #define RES2 /* ewrlkjhsadf */ (RES1 * VAL2)
+ #define VALUE (RES2 + RES1)
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redefine_object_multiline_comment
+ version 300 es
+ values { output float out0 = 6.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define VAL1 1.0
+ #define VAL2 2.0
+
+ #define RES2 /* fdsjklfdsjkl
+ dsfjkhfdsjkh
+ fdsjklhfdsjkh */ (RES1 * VAL2)
+ #define RES1 (VAL2 / VAL1)
+ #define RES2 /* ewrlkjhsadf */ (RES1 * VAL2)
+ #define VALUE (RES2 + RES1)
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # object_redefinitions
+
+group invalid_redefinitions "Invalid Redefinitions Tests"
+
+ case invalid_identifier_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define GL_VALUE 1.0
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(GL_VALUE);
+ }
+ ""
+ end
+
+end # invalid_redefinitions
+
+group comments "Comment Tests"
+
+ case multiline_comment_define
+ version 300 es
+ values { output float out0 = 4.2; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define VALUE /* current
+ value */ 4.2
+
+ void main()
+ {
+ out0 = VALUE;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_comment
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ /* /* */
+ out0 = 1.0;
+ // */
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case comment_trick_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ /*/
+ out0 = 0.0;
+ /*/
+ out0 = 1.0;
+ /**/
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case comment_trick_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ /**/
+ out0 = 1.0;
+ /*/
+ out0 = 0.0;
+ /**/
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_comment
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ /* /* */ */
+ ${POSITION_FRAG_COLOR} = 1.0;
+ }
+ ""
+ end
+
+ case unterminated_comment_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ /*
+ }
+ ""
+ end
+
+ case unterminated_comment_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ /*
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ }
+ ""
+ end
+
+ case backslash_in_a_comment_1
+ version 300 es
+ expect build_successful
+ both ""
+ #version 300 es
+ // \\note these are some declarations
+ precision mediump float;
+ ${DECLARATIONS}
+ // \\note this is the main function
+ void main()
+ {
+ // \\note this is a function body
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case backslash_in_a_comment_2
+ version 300 es
+ expect build_successful
+ both ""
+ #version 300 es
+ /* \\note these are some declarations */
+ precision mediump float;
+ ${DECLARATIONS}
+ /* \\note this is the main function */
+ void main()
+ {
+ /* \\note this is a function body */
+ ${OUTPUT}
+ }
+ ""
+ end
+end # comments
+
+group line_continuation "Line Continuation Tests"
+
+ case comment
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ out0 = 1.0;
+ // comment \\
+ out0 = -1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case define
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define A(X) \\
+ (-1.0*(X))
+
+ void main ()
+ {
+ out0 = A(-1.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case preprocessing_token
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #def\\
+ ine A(X) (-1.0*(X))
+
+ void main ()
+ {
+ out0 = A(-1.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case token
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f\\
+ oo = 1.0;
+ out0 = foo;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case middle_of_line
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define A a \\ b
+ #define B 1.0
+
+ void main ()
+ {
+ out0 = B;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # line_continuation
+
+group function_definitions "Function Definitions Tests"
+
+ case same_object_and_function_param
+ version 300 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define VALUE 1.0
+ #define FUNCTION(VALUE, B) (VALUE-B)
+
+ void main()
+ {
+ out0 = FUNCTION(3.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex_func
+ version 300 es
+ values { output float out0 = 518.5; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define AAA(a,b) a*(BBB(a,b))
+ #define BBB(a,b) a-b
+
+ void main()
+ {
+ out0 = BBB(AAA(8.0/4.0, 2.0)*BBB(2.0*2.0,0.75*2.0), AAA(40.0,10.0*BBB(5.0,3.0)));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_definition_with_comments
+ version 300 es
+ values { output float out0 = 3.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ /* sdfljk */ #/* sdfljk */define /* sdfljk */ FUNC( /* jklsfd*/a /*sfdjklh*/, /*sdfklj */b /*sdfklj*/) a+b
+
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # function_definitions
+
+group recursion "Recursions Tests"
+
+ case recursion_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA AAA
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA);
+ }
+ ""
+ end
+
+ case recursion_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA BBB
+ #define BBB AAA
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA);
+ }
+ ""
+ end
+
+ case recursion_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA (1.0+BBB)
+ #define BBB (2.0+AAA)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA);
+ }
+ ""
+ end
+
+ case recursion_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA(a) AAA(a)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA(1.0));
+ }
+ ""
+ end
+
+ case recursion_5
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ # define AAA(a, b) AAA(b, a)
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(AAA(1.0, 2.0));
+ }
+ ""
+ end
+
+end # recursion
+
+group function_redefinitions "Function Redefinition Tests"
+
+ case function_redefinition_1
+ version 300 es
+ values { output float out0 = 3.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC( a, b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_redefinition_2
+ version 300 es
+ values { output float out0 = 3.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) (a +b)
+ # define FUNC( a, b )(a +b)
+
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_redefinition_3
+ version 300 es
+ values { output float out0 = 3.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) (a +b)
+ # define FUNC(a,b)(a /* comment
+ */ +b)
+
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = FUNC(1.0, 2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_function_redefinition_param_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC(A,b) A+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0));
+ }
+ ""
+ end
+
+ case invalid_function_redefinition_param_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC(a,b,c) a+b+c
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0, 3.0));
+ }
+ ""
+ end
+
+ case invalid_function_redefinition_param_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+ # define FUNC(a,b) b+a
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0));
+ }
+ ""
+ end
+
+end # functions_redefinitions
+
+group invalid_function_definitions "Invalid Function Definition Tests"
+
+ case arguments_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC);
+ }
+ ""
+ end
+
+ case arguments_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC());
+ }
+ ""
+ end
+
+ case arguments_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC((();
+ }
+ ""
+ end
+
+ case arguments_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC));
+ }
+ ""
+ end
+
+ case arguments_5
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0));
+ }
+ ""
+ end
+
+ case arguments_6
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0);
+ }
+ ""
+ end
+
+ case arguments_7
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,));
+ }
+ ""
+ end
+
+ case arguments_8
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0, 2.0, 3.0));
+ }
+ ""
+ end
+
+ case unique_param_name
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a,a) a+a
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case argument_list_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case argument_list_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(a + b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case argument_list_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(,a,b) a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(A a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(A,B,C a+b
+
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0));
+ }
+ ""
+ end
+
+ case no_closing_parenthesis_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ # define FUNC(
+ ""
+ end
+
+end # invalid_function_definitions
+
+group semantic "Semantic Tests"
+
+ case ops_as_arguments
+ version 300 es
+ values { output float out0 = 20.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define FOO(a, b) (1 a 9) b 2
+
+ void main()
+ {
+ out0 = float(FOO(+, *));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case correct_order
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define FUNC(A) A
+ #define A 2.0
+
+ void main()
+ {
+ out0 = FUNC(A - 1.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # semantic
+
+group predefined_macros "Predefined Macros Tests"
+
+ case version
+ version 300 es
+ values { output float out0 = 300.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA __VERSION__
+ out0 = float(AAA);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case gl_es_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ out0 = float(GL_ES);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case gl_es_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define AAA(A) A
+
+ void main()
+ {
+ out0 = float(AAA(GL_ES));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_1
+ version 300 es
+ values { output float out0 = 2.0; }
+ both ""
+ #version 300 es
+ const mediump int line = __LINE__;
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = float(line);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_2
+ version 300 es
+ # Note: Arguments are macro replaced in the first stage.
+ # Macro replacement list is expanded in the last stage.
+ values { output vec4 out0 = vec4(12.0, 12.0, 10.0, 11.0); }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS:single-line}
+ #define BBB __LINE__, /*
+ */ __LINE__
+ #define AAA(a,b) BBB, a, b
+
+ void main()
+ {
+ out0 = vec4(AAA(__LINE__,
+ __LINE__
+ ));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case file
+ version 300 es
+ values { output float out0 = 0.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = float(__FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_gl_es
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if GL_ES
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_version
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if __VERSION__ == 300
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # predefined_macros
+
+group conditional_inclusion "Conditional Inclusion Tests"
+
+ case basic_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA asdf
+
+ #if defined AAA && !defined(BBB)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ # Note: this is expected to fail contrary to native dEQP,
+ # see https://github.com/KhronosGroup/WebGL/pull/1523
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA defined(BBB)
+
+ #if !AAA
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_macro_defined_test
+ version 300 es
+ values { output float out0 = 1.0; }
+ # Note: this is expected to fail contrary to native dEQP,
+ # see https://github.com/KhronosGroup/WebGL/pull/1523
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define AAA defined
+
+ #if AAA AAA
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_macro_undef
+ version 300 es
+ values { output float out0 = 1.0; }
+ # Note: this is expected to fail contrary to native dEQP,
+ # see https://github.com/KhronosGroup/WebGL/pull/1523
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define BBB 1
+ #define AAA defined(BBB)
+ #undef BBB
+
+ #if !AAA
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case define_defined
+ version 300 es
+ values { output float out0 = 1.0; }
+ # Note: this is expected to fail contrary to native dEQP,
+ # see https://github.com/KhronosGroup/WebGL/pull/1523
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define CCC 1
+ #define defined BBB
+ #define AAA defined
+
+ #if AAA CCC
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case define_defined_outside_if
+ version 300 es
+ values { output float out0 = 1.0; }
+ # Note: this is expected to fail contrary to native dEQP,
+ # see https://github.com/KhronosGroup/WebGL/pull/1523
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define CCC - 0.5
+ #define defined 0.5
+ #define AAA defined
+ out0 = 1.0 - (AAA CCC);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_invalid_before_all_macros_replaced
+ version 300 es
+ expect compile_fail
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define FOO 1
+ #define OPEN defined(
+ #define CLOSE FOO)
+
+ #if OPEN CLOSE
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_3
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ out0 = -1.0;
+ #elif 0
+ out0 = -2.0;
+ #elif 1
+ out0 = 1.0;
+ #else
+ out0 = -3.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_4
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ out0 = -1.0;
+ #elif 0
+ out0 = -2.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_5
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ out0 = 1.0;
+ #elif 0
+ out0 = -2.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case unary_ops_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !((~2 >> 1) & 1)
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case unary_ops_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !((~(- - - - - 1 + + + + + +1) >> 1) & 1)
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # conditional_inclusion
+
+group invalid_ops "Invalid Operations Tests"
+
+ case invalid_op_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !((~(+ ++1 - - - -1) >> 1) & 1)
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_op_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !((~(+ + +1 - -- -1) >> 1) & 1)
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define AAA 1
+
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define AAA 1
+
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined()
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define AAA 1
+
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined(
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define AAA 1
+
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_identifier_5
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define AAA 1
+
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined((AAA))
+ ${POSITION_FRAG_COLOR} = vec4(FUNC(1.0,2.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_defined_expected_rparen
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ #define AAA 1
+
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined(AAA
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case defined_define
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define define 1
+ #define AAA 1.0
+
+ void main()
+ {
+ out0 = AAA;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # invalid_ops
+
+group undefined_identifiers "Undefined Identifiers Tests"
+
+ case valid_undefined_identifier_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1 || AAA
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case valid_undefined_identifier_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0 && AAA
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case undefined_identifier_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1 - CCC + (-AAA || BBB)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !A
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if -A
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if ~A
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_5
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_6
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 1
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_7
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define B 1
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_8
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define B 1
+ #define A 2
+ #undef A
+ #if A && B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_9
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_10
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 0
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_11
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 0
+ #define B 2
+ #undef B
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case undefined_identifier_12
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define B 1
+ #if A || B
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+end # undefined_identifiers
+
+group invalid_conditionals "Invalid Conditionals Tests"
+
+ case empty_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_ifdef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case empty_ifndef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_ifdef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case invalid_ifndef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case empty_if_defined
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_if_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_if_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_ifdef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef FOOBAR
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_ifndef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef GL_ES
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_else_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_else_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_elif_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ #elif 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_elif_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ #elif 0
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_elif_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ #elif 0
+ ${POSITION_FRAG_COLOR} = vec4(2.0);
+ }
+ ""
+ end
+
+ case elif_after_else
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #elif 1
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ #endif
+ }
+ ""
+ end
+
+ case else_without_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case elif_without_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #elif 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case endif_without_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case else_after_else
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !GL_ES
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #else
+ ${POSITION_FRAG_COLOR} = vec4(-1.0);
+ #endif
+ }
+ ""
+ end
+
+ case nested_elif_without_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ # elif
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ # endif
+ #endif
+ }
+ ""
+ end
+
+ case if_float
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1.231
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ # elif
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ # endif
+ #endif
+ }
+ ""
+ end
+
+ case tokens_after_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1 foobar
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case tokens_after_elif
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ #elif foobar
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ #endif
+ }
+ ""
+ end
+
+ case tokens_after_else
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ #else foobar 1.231
+ #endif
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case tokens_after_endif
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ #else
+ #endif foobar
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case tokens_after_ifdef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef FOOBAR foobar
+ #else
+ #endif
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case tokens_after_ifndef
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef FOOBAR ,, +- << barbar
+ #else
+ #endif
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_nested_blocks
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ # if 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_conditionals
+
+group conditionals "Conditionals Tests"
+
+ case ifdef_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #define AAA
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef AAA
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifdef_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #define AAA
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if defined ( AAA)
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifdef_3
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifdef AAA
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifndef_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef AAA
+ out0 = 1.0;
+ #else
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ifndef_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define AAA
+ void main()
+ {
+ #ifndef AAA
+ out0 = -1.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_conditional_inclusion
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #ifndef AAA
+ out0 = 1.0;
+ #elif 1
+ out0 = -1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_if_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if GL_ES
+ # if __VERSION__ != 300
+ out0 = -1.0;
+ # else
+ out0 = 1.0;
+ # endif
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_if_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 1
+ # if 0
+ out0 = -1.0;
+ # else
+ # if 0
+ out0 = -1.0;
+ # elif 1
+ out0 = 1.0;
+ # else
+ out0 = -1.0;
+ # endif
+ # endif
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_if_3
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 0
+ # if 1
+ out0 = -1.0;
+ # endif
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # conditionals
+
+group directive "Directive Tests"
+
+ case version_is_less
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 299 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_is_more
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 301 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_missing_es
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_missing
+ expect compile_fail
+ version 300 es
+ both ""
+ #version
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_not_first_statement_1
+ expect compile_fail
+ version 300 es
+ both ""
+ precision mediump float;
+ #version 300 es
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_not_first_statement_2
+ expect compile_fail
+ version 300 es
+ both ""
+ #define FOO BAR
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_invalid_token_1
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es.0
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case version_invalid_token_2
+ expect compile_fail
+ version 300 es
+ both ""
+ #version foobar
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_version
+ expect compile_fail
+ version 300 es
+ both ""
+ #version AAA
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case additional_tokens
+ expect compile_fail
+ version 300 es
+ both ""
+ #version 300 es foobar
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case error_with_no_tokens
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #error
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case error
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #define AAA asdf
+ #error 1 * AAA /* comment */
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # directive
+
+group builtin "Built-in Symbol Tests"
+
+ case line
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line 1
+ out0 = float(__LINE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_and_file
+ version 300 es
+ values { output vec4 out0 = vec4(234.0, 234.0, 10.0, 10.0); }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line 234 10
+ out0 = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_expression
+ version 300 es
+ values { output float out0 = 20.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line +20
+ out0 = float(__LINE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_and_file_expression
+ version 300 es
+ values { output vec4 out0 = vec4(243.0, 243.0, 10.0, 10.0); }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line (233 +10) (+10)
+ out0 = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_defined_1
+ version 300 es
+ values { output float out0 = 4.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 4
+ #line A
+ out0 = float(__LINE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case line_defined_2
+ version 300 es
+ values { output vec4 out0 = vec4(234.0, 234.0, 10.0, 10.0); }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define A 10
+ #line 234 A
+ out0 = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case empty_line
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_line_file_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line 22 1.234
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ }
+ ""
+ end
+
+ case invalid_line_file_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line 233 10 2
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ }
+ ""
+ end
+
+ case invalid_line_file_4
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #line foobar
+ ${POSITION_FRAG_COLOR} = vec4(__LINE__, __LINE__, __FILE__, __FILE__);
+ }
+ ""
+ end
+
+end # builtin
+
+group pragmas "Pragma Tests"
+
+ case pragma_vertex
+ version 300 es
+ values { output float out0 = 1.0; }
+ vertex ""
+ #version 300 es
+ #pragma
+ #pragma STDGL invariant(all)
+ #pragma debug(off)
+ #pragma optimize(off)
+
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case pragma_fragment
+ version 300 es
+ values { output float out0 = 1.0; }
+ vertex ""
+ #version 300 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 300 es
+ #pragma
+ #pragma debug(off)
+ #pragma optimize(off)
+
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case pragma_macro_exp
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #define off INVALID
+ /* pragma line not macro expanded */
+ #pragma debug(off)
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case pragma_unrecognized_debug
+ version 300 es
+ expect build_successful
+ both ""
+ #version 300 es
+ #pragma debug(1.23)
+
+ // unrecognized preprocessor token
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case pragma_unrecognized_token
+ # Note: upstream dEQP uses unicode characters here but we can't test
+ # this in WebGL because it requires strings passed to glShaderSource
+ # to be ASCII. This would cause the test to fail at glShaderSource
+ # instead of glCompileShader, which is not what we want to test.
+ version 300 es
+ expect build_successful
+ both ""
+ #version 300 es
+ #pragma **%
+
+ // trailing bytes form a valid but unrecognized preprocessor token
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # pragmas
+
+group extensions "Extension Tests"
+
+ case basic
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #extension all : warn
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case macro_exp
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #define warn enable
+
+ #extension all : warn
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case missing_extension_name
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_extension_name
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension 2 : all
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_colon
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case expected_colon
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all ;
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_behavior
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all :
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_behavior_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all : WARN
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_behavior_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all : require
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_char_in_name
+ # Note: upstream dEQP uses unicode characters here but we can't test
+ # this in WebGL because it requires strings passed to glShaderSource
+ # to be ASCII. This would cause the test to fail at glShaderSource
+ # instead of glCompileShader, which is not what we want to test.
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all* : warn
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_char_in_behavior
+ # Note: upstream dEQP uses unicode characters here but we can't test
+ # this in WebGL because it requires strings passed to glShaderSource
+ # to be ASCII. This would cause the test to fail at glShaderSource
+ # instead of glCompileShader, which is not what we want to test.
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all : war*n
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unterminated_comment
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all : warn /*asd
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case after_non_preprocessing_tokens
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ #extension all : warn
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #extension all : disable
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+end # extensions
+
+group expressions "Expression Tests"
+
+ case shift_left
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if (VAL << 2) == 16
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case shift_right
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 5
+ out0 = 0.0;
+ #if (VAL >> 1) == 2
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case cmp_less_than
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 5
+ out0 = 0.0;
+ #if (VAL < 6) && (-VAL < -4)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_or_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL <= 6) && (-VAL <= -6)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case or
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL | 5) == 7
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case and
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL & 5) == 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case xor
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 6
+ out0 = 0.0;
+ #if (VAL ^ 5) == 3
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mod
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 12
+ out0 = 0.0;
+ #if (VAL % 5) == 2
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_value
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL (( (4 ) ) )
+ out0 = 0.0;
+ #if VAL >= 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_tricky
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL (( (4 ) )
+ out0 = 0.0;
+ #if VAL) >= 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_if_no
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if VAL >= 4
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_if
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if (VAL >= 4)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_multi_if
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL (4)
+ out0 = 0.0;
+ #if (((VAL)) >= (4))
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_single_if
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ out0 = 0.0;
+ #if (VAL >= 4)
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_ifelse_true
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ #if (VAL >= 4)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case parenthesis_ifelse_false
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #define VAL 4
+ #if (VAL > 4)
+ out0 = 0.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_basic_0
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if -4 + 5 == 1
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_basic_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if (2 * 2) - 3 >= 0
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_simple_precedence_0
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 2 * 3 - 3 == 3
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case eval_simple_precedence_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 2 - 2 / 2 == 1
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_1
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ void main()
+ {
+ #if defined(X)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_2
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ void main()
+ {
+ #if defined(X) == Y
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_3
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ void main()
+ {
+ #if defined(X) && defined(Y)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_4
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ #undef X
+ void main()
+ {
+ #if defined(X) && defined(Y)
+ out0 = 0.0;
+ #else
+ out0 = 1.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_5
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ #undef X
+ void main()
+ {
+ #if defined(X) || defined(Y)
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case defined_6
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ #define X 0
+ #define Y 1
+ #undef Y
+ void main()
+ {
+ #if defined(X) && (defined(Y) || (X == 0))
+ out0 = 1.0;
+ #else
+ out0 = 0.0;
+ #endif
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # expressions
+
+group invalid_expressions "Invalid Expression Tests"
+
+ case invalid_unary_expr
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if !
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_binary_expr
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 3+4+
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case missing_expr
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_expr_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 4 4
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_expr_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 4 * * 4
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case invalid_expr_3
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if (4)(4)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unopened_parenthesis
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if 4)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ case unclosed_parenthesis
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ #if ((4 + 7)
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+end # invalid_expressions
+
+group operator_precedence "Operator precedence"
+
+
+ case modulo_vs_not
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 % ! 0 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_not
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 / ! 0 ) == 8
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_not
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 * ! 0 ) == 8
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case modulo_vs_bit_invert
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 % ~ 4 ) == 3
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case modulo_vs_minus
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 % - 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case modulo_vs_plus
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 % + 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_bit_invert
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 / ~ 2 ) == -2
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_minus
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 / - 2 ) == -4
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case div_vs_plus
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 / + 2 ) == 4
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_bit_invert
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 * ~ 2 ) == -24
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_minus
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 * - 2 ) == -16
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mul_vs_plus
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 * + 2 ) == 16
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sub_vs_modulo
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 - 3 % 2 ) == 7
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sub_vs_div
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 - 3 / 2 ) == 7
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sub_vs_mul
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 - 3 * 2 ) == 2
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case add_vs_modulo
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 + 3 % 2 ) == 9
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case add_vs_div
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 + 3 / 2 ) == 9
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case add_vs_mul
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 + 3 * 2 ) == 14
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case rshift_vs_sub
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 >> 3 - 2 ) == 4
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case rshift_vs_add
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 >> 3 + 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case lshift_vs_sub
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 << 3 - 2 ) == 16
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case lshift_vs_add
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 << 3 + 2 ) == 256
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_or_equal_vs_rshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 >= 3 >> 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_or_equal_vs_lshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 >= 3 << 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_or_equal_vs_rshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 <= 3 >> 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_or_equal_vs_lshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 <= 3 << 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_vs_rshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 > 3 >> 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case greater_vs_lshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 > 3 << 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_vs_rshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 < 3 >> 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case less_vs_lshift
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 < 3 << 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_greater_or_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 != 3 >= 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_less_or_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 != 3 <= 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_greater
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 != 3 > 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case not_equal_vs_less
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 != 3 < 2 ) == 1
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_greater_or_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 == 3 >= 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_less_or_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 == 3 <= 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_greater
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 == 3 > 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case equal_vs_less
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 == 3 < 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise_and_vs_not_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 & 3 != 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise_and_vs_equal
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 & 3 == 2 ) == 0
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case xor_vs_bitwise_and
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 ^ 3 & 2 ) == 10
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise_or_vs_xor
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 8 | 3 ^ 2 ) == 9
+ #define VAL 1.0
+ #else
+ #define VAL 0.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical_and_vs_bitwise_or
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 0 && 3 | 2 )
+ #define VAL 0.0
+ #else
+ #define VAL 1.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical_and_vs_bitwise_and
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 0 && 4 & 2 )
+ #define VAL 0.0
+ #else
+ #define VAL 1.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical_or_vs_logical_and
+ version 300 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 300 es
+ #if ( 0 || 4 && 0 )
+ #define VAL 0.0
+ #else
+ #define VAL 1.0
+ #endif
+
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = VAL;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # operator_precedence
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.html
new file mode 100644
index 0000000000..d381f96f66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'qualification_order';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.test
new file mode 100644
index 0000000000..42c5b357f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/qualification_order.test
@@ -0,0 +1,2714 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group variables "Order of qualification in variable declarations."
+
+ group valid "Valid orderings."
+
+ case invariant_interp_storage_precision
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant smooth centroid out lowp float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage_precision
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out lowp float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_interp_storage
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant smooth centroid out float x0;
+
+ flat out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in float x0;
+
+ flat in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage_precision
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out lowp float x0;
+
+ out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp float x0;
+
+ in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out lowp float x0;
+
+ out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp float x0;
+
+ in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out float x0;
+
+ flat out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in float x0;
+
+ flat in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage
+ expect pass
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out float x0;
+
+ out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in float x0;
+
+ in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+
+ end # valid
+ group invalid "Invalid orderings."
+
+ case invariant_interp_precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant smooth lowp centroid out float x0;
+
+ flat mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth lowp centroid in float x0;
+
+ flat mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage_interp_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out smooth lowp float x0;
+
+ out flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth lowp float x0;
+
+ in flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage_precision_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out lowp smooth float x0;
+
+ out mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp smooth float x0;
+
+ in mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_precision_interp_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant lowp smooth centroid out float x0;
+
+ mediump flat out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp smooth centroid in float x0;
+
+ mediump flat in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_precision_storage_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant lowp centroid out smooth float x0;
+
+ mediump out flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in smooth float x0;
+
+ mediump in flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_invariant_storage_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth invariant centroid out lowp float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_invariant_precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth invariant lowp centroid out float x0;
+
+ flat mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth lowp centroid in float x0;
+
+ flat mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage_invariant_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out invariant lowp float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage_precision_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out lowp invariant float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_precision_invariant_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth lowp invariant centroid out float x0;
+
+ flat mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth lowp centroid in float x0;
+
+ flat mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_precision_storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth lowp centroid out invariant float x0;
+
+ flat mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth lowp centroid in float x0;
+
+ flat mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant_interp_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out invariant smooth lowp float x0;
+
+ out flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth lowp float x0;
+
+ in flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant_precision_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out invariant lowp smooth float x0;
+
+ out mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp smooth float x0;
+
+ in mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_interp_invariant_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out smooth invariant lowp float x0;
+
+ out flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth lowp float x0;
+
+ in flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_interp_precision_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out smooth lowp invariant float x0;
+
+ out flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth lowp float x0;
+
+ in flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision_invariant_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out lowp invariant smooth float x0;
+
+ out mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp smooth float x0;
+
+ in mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision_interp_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out lowp smooth invariant float x0;
+
+ out mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp smooth float x0;
+
+ in mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_invariant_interp_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp invariant smooth centroid out float x0;
+
+ mediump flat out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp smooth centroid in float x0;
+
+ mediump flat in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_invariant_storage_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp invariant centroid out smooth float x0;
+
+ mediump out flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in smooth float x0;
+
+ mediump in flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_interp_invariant_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp smooth invariant centroid out float x0;
+
+ mediump flat out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp smooth centroid in float x0;
+
+ mediump flat in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_interp_storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp smooth centroid out invariant float x0;
+
+ mediump flat out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp smooth centroid in float x0;
+
+ mediump flat in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage_invariant_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp centroid out invariant smooth float x0;
+
+ mediump out flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in smooth float x0;
+
+ mediump in flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage_interp_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp centroid out smooth invariant float x0;
+
+ mediump out flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in smooth float x0;
+
+ mediump in flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth lowp centroid out float x0;
+
+ flat mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth lowp centroid in float x0;
+
+ flat mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_interp_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out smooth lowp float x0;
+
+ out flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth lowp float x0;
+
+ in flat mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out lowp smooth float x0;
+
+ out mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp smooth float x0;
+
+ in mediump flat float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_interp_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp smooth centroid out float x0;
+
+ mediump flat out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp smooth centroid in float x0;
+
+ mediump flat in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp centroid out smooth float x0;
+
+ mediump out flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in smooth float x0;
+
+ mediump in flat float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out smooth float x0;
+
+ out flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth float x0;
+
+ in flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_invariant_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth invariant centroid out float x0;
+
+ flat out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in float x0;
+
+ flat in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out invariant float x0;
+
+ flat out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ smooth centroid in float x0;
+
+ flat in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out invariant smooth float x0;
+
+ out flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth float x0;
+
+ in flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_interp_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out smooth invariant float x0;
+
+ out flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth float x0;
+
+ in flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant lowp centroid out float x0;
+
+ mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in float x0;
+
+ mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant_precision
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out invariant lowp float x0;
+
+ out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp float x0;
+
+ in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out lowp invariant float x0;
+
+ out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in lowp float x0;
+
+ in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_invariant_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp invariant centroid out float x0;
+
+ mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in float x0;
+
+ mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp centroid out invariant float x0;
+
+ mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in float x0;
+
+ mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case precision_storage
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ lowp centroid out float x0;
+
+ mediump out float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ lowp centroid in float x0;
+
+ mediump in float x1;
+
+ highp uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_interp
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out smooth float x0;
+
+ out flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in smooth float x0;
+
+ in flat float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_invariant
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out invariant float x0;
+
+ out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ centroid in float x0;
+
+ in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_interp_storage_precision_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant smooth centroid out lowp float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage_precision_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out lowp float x0;
+
+ flat out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant smooth centroid in lowp float x0;
+
+ flat in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_interp_storage_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant smooth centroid out float x0;
+
+ flat out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant smooth centroid in float x0;
+
+ flat in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage_precision_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out lowp float x0;
+
+ out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant centroid in lowp float x0;
+
+ in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case storage_precision_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ centroid out lowp float x0;
+
+ out mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant centroid in lowp float x0;
+
+ in mediump float x1;
+
+ uniform highp float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case interp_storage_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ smooth centroid out float x0;
+
+ flat out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant smooth centroid in float x0;
+
+ flat in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+ case invariant_storage_invariant_input
+ expect compile_fail
+ values {}
+
+ vertex ""
+ #version 300 es
+ precision mediump float;
+ in highp vec4 dEQP_Position;
+
+ invariant centroid out float x0;
+
+ out float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ gl_Position = dEQP_Position;
+ }
+ ""
+
+ fragment ""
+ #version 300 es
+ precision mediump float;
+ layout(location = 0) out mediump vec4 dEQP_FragColor;
+
+ invariant centroid in float x0;
+
+ in float x1;
+
+ uniform float x2;
+
+ void main()
+ {
+ float result = (x0 + x1 + x2) / 3.0;
+ dEQP_FragColor = vec4(result, result, result, 1.0);
+ }
+ ""
+ end
+
+ end # invalid
+
+end # variables
+group parameters "Order of qualification in function parameters."
+
+ group valid "Valid orderings."
+
+ case storage_parameter_precision
+ expect pass
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const in lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( inout highp float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case storage_parameter
+ expect pass
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case storage_precision
+ expect pass
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( highp float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_precision
+ expect pass
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout highp float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ end # valid
+ group invalid "Invalid orderings."
+
+ case storage_precision_parameter
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (const lowp in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 ( mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 ( highp inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_storage_precision
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in const lowp float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout highp float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_precision_storage
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in lowp const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout highp float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_storage_parameter
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp const in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (highp inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_parameter_storage
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp in const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (highp inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case parameter_storage
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (in const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_storage
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp const float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (highp float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+ case precision_parameter
+ expect compile_fail
+ version 300 es
+ values {}
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float foo0 (lowp in float x)
+ {
+ return x + 1.0;
+ }
+
+ void foo1 (mediump out float x)
+ {
+ x = 1.0;
+ }
+
+ float foo2 (highp inout float x)
+ {
+ return x + 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float result;
+ foo1(result);
+ float x0 = foo0(1.0);
+ foo2(result);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ end # invalid
+
+end # parameters
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.html
new file mode 100644
index 0000000000..c525b32b68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'scoping';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.test
new file mode 100644
index 0000000000..4f195250f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/scoping.test
@@ -0,0 +1,901 @@
+group valid "Valid scoping and name redeclaration cases"
+
+ case local_variable_hides_global_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case block_variable_hides_local_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ {
+ int a = -1;
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case block_variable_hides_global_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ void main()
+ {
+ ${SETUP}
+ {
+ int a = in0;
+
+ out0 = a;
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case for_init_statement_variable_hides_local_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ for (int a = 0; a < 10; a++)
+ {
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case while_condition_variable_hides_local_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ int i = 0;
+ while (bool a = (i < 1))
+ {
+ i++;
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case for_init_statement_variable_hides_global_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 5;
+
+ void main()
+ {
+ ${SETUP}
+ for (int a = 0; a < 10; a++)
+ {
+ }
+ out0 = in0 + a - 5;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case while_condition_variable_hides_global_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 5;
+
+ void main()
+ {
+ ${SETUP}
+ int i = 0;
+ while (bool a = (i < 1))
+ {
+ i++;
+ }
+ out0 = in0 + a - 5;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case variable_in_if_hides_global_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 1;
+
+ void main()
+ {
+ ${SETUP}
+ if (true)
+ int a = 42;
+ out0 = a*in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case variable_from_outer_scope_visible_in_initializer
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ {
+ int a = a+5, b = a-5;
+ out0 = b;
+ a = 42;
+ }
+ out0 = out0 + a - in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_int_variable_hides_struct_type
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int val; };
+
+ void main()
+ {
+ ${SETUP}
+ int S = S(in0).val;
+ out0 = S;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_struct_variable_hides_struct_type
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int val; };
+
+ void main()
+ {
+ ${SETUP}
+ S S = S(in0);
+ out0 = S.val;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_variable_hides_function
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int foo (int x) { return x; }
+
+ void main()
+ {
+ ${SETUP}
+ int foo = in0;
+ out0 = foo;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_global_variable
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ int func (int a) { return a; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_struct_type
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int x; };
+
+ int func (int S) { return S; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_function
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int func (int func) { return func; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_variable_in_inner_scope_hides_function_parameter
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ int func (int inp, int x) { { int x = 5; return inp + x - 5; } }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0, 42);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redeclare_function
+ version 300 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int func (int x);
+ int func (int);
+ int func (int inp) { return inp; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end
+
+group invalid "Invalid scoping behavior"
+
+ case redeclare_global_variable
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a;
+ float a;
+
+ void main()
+ {
+ a = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case redeclare_local_variable
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ int a;
+ float a;
+ a = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case redeclare_for_init_statement_variable
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ int i = 11;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case redeclare_for_condition_variable
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ for (int i = 0; int a = (i < 10); i++)
+ {
+ int a = 0;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case redeclare_for_init_statement_variable_in_for_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a;
+ for (int i = 0; int i = (i < 10); i++)
+ {
+ a = sin(i);
+ }
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case redeclare_while_condition_variable
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ int a = 0;
+ while (int i = (a < 5))
+ {
+ int i = 11;
+ a += i;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+ ""
+ end
+
+ case redefine_function
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func(float x);
+
+ float func(float x) { return x + 1.0; }
+ float func(float x) { return x + 2.0; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case redeclare_builtin
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sin(float x);
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
+ }
+ ""
+ end
+
+ case redefine_builtin
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sin(float x) { return x + 1.0; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
+ }
+ ""
+ end
+
+ case conflict_function_struct
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void f(int x);
+ struct f { int x; };
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1);
+ }
+ ""
+ end
+
+ case conflict_function_variable
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void f(int x);
+ float f;
+
+ void main()
+ {
+ f = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(f);
+ }
+ ""
+ end
+
+ case use_global_variable_before_declaration
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func()
+ {
+ a = 2.0;
+ }
+
+ float a;
+
+ void main()
+ {
+ func();
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_local_variable_before_declaration
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a = 1.0;
+ a = b;
+ float b = 2.0;
+
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_struct_type_before_declaration
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float x) { return S(x).val; }
+ struct S { float val; };
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case use_function_before_declaration
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float x) { return bar(x); }
+ float bar (float x) { return x; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0));
+ }
+ ""
+ end
+
+ case use_variable_from_block_in_outer_scope
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ {
+ float a = 1.0;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_variable_from_if_in_outer_scope
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ if (true)
+ float a = 1.0;
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_variable_from_else_in_outer_scope
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ if (false)
+ float a = 1.0;
+ else
+ float b = 2.0;
+ ${POSITION_FRAG_COLOR} = vec4(b);
+ }
+ ""
+ end
+
+ case use_variable_from_if_in_else
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float a = 1.0;
+ if (true)
+ {
+ float b = 2.0;
+ }
+ else
+ {
+ a = b;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(a);
+ }
+ ""
+ end
+
+ case use_variable_from_for_init_statement_in_outer_scope
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float x = 0.0;
+ for (int i = 0; i < 10; i++)
+ {
+ x += sin(i);
+ }
+ ${POSITION_FRAG_COLOR} = vec4(float(i));
+ }
+ ""
+ end
+
+ case use_variable_from_while_condition_in_outer_scope
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ int a = 1;
+ while (bool b = (a == 1))
+ {
+ a++;
+ }
+ ${POSITION_FRAG_COLOR} = vec4(float(b));
+ }
+ ""
+ end
+
+ case use_parameter_names_from_function_declaration
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func(float a, float b);
+
+ float func(float x, float y) { return a+b; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0, 2.0));
+ }
+ ""
+ end
+
+ case variable_not_visible_in_own_initializer
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ float x = x;
+ ${POSITION_FRAG_COLOR} = vec4(x);
+ }
+ ""
+ end
+
+ case local_variable_hides_function_parameter
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+ float func (float inp, float x) { int x = 5.0; return inp + x - 5.0; }
+
+ void main()
+ {
+ ${POSITION_FRAG_COLOR} = vec4(func(1.0, 2.0));
+ }
+ ""
+ end
+
+end # invalid
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-conversions.js b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-conversions.js
new file mode 100644
index 0000000000..c3eeb7928f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-conversions.js
@@ -0,0 +1,33 @@
+/*
+
+run with
+ node split-conversions.js
+
+notes:
+
+conversions.test is generated from the C++ based dEQP tests
+https://github.com/KhronosGroup/VK-GL-CTS/blob/main/modules/gles3/scripts/gen-conversions.py
+
+You need to manually add these tests to the 00_test_list.txt
+
+*/
+
+const fs = require('fs');
+
+process.chdir(__dirname);
+
+const testWarning = `\
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-conversions.js
+
+`;
+
+const conversionsHTML = fs.readFileSync('conversions.template', {encoding: 'utf8'});
+const conversions = fs.readFileSync('conversions.test', {encoding: 'utf8'});
+const groupMatches = conversions.matchAll(/group ([a-zA-Z0-9_]+) [\s\S]+?end #.*?\n/g);
+for (const [str, groupName] of groupMatches) {
+ const baseName = `conversions_${groupName}`;
+ fs.writeFileSync(`${baseName}.test`, `${testWarning}${str}`);
+ fs.writeFileSync(`${baseName}.html`, `<!--\n${testWarning}-->\n${conversionsHTML.replace("'conversions'", `'${baseName}'`)}`);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-swizzles.js b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-swizzles.js
new file mode 100644
index 0000000000..7205d82afd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/split-swizzles.js
@@ -0,0 +1,47 @@
+/*
+
+run with
+ node split-swizzles.js
+
+notes:
+
+swizzles.test is generated from the C++ based dEQP tests
+https://github.com/KhronosGroup/VK-GL-CTS/blob/main/modules/gles3/scripts/gen-swizzles.py
+
+You need to manually add these tests to the 00_test_list.txt
+
+*/
+
+const fs = require('fs');
+
+process.chdir(__dirname);
+
+const testWarning = `\
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+`;
+
+const swizzlesHTML = fs.readFileSync('swizzles.template', {encoding: 'utf8'});
+const swizzles = fs.readFileSync('swizzles.test', {encoding: 'utf8'});
+const caseMatches = swizzles.matchAll(/\scase (\w+)_(\w+)_(\w+)\n[\s\S]+?end\n/g);
+
+// quick sanity check
+const numCases = swizzles.matchAll('\bcase\b').length;
+if (caseMatches.length !== numCases) {
+ throw Error(`numCases(${numCases}) does not match caseMatches.length(${caseMatches.length})`);
+}
+
+const byType = {}
+for (const [str, precision, type, swizzle] of caseMatches) {
+ byType[type] = byType[type] || [];
+ byType[type].push(str);
+}
+
+for (const [type, cases] of Object.entries(byType)) {
+ const baseName = `swizzles_${type}`;
+ const str = `group ${type}_swizzles "${type} swizzles"\n\n${cases.join('\n\n')}\n\nend # ${type}_swizzles`;
+ fs.writeFileSync(`${baseName}.test`, `${testWarning}${str}`);
+ fs.writeFileSync(`${baseName}.html`, `<!--\n${testWarning}-->\n${swizzlesHTML.replace("'swizzles'", `'${baseName}'`)}`);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.html
new file mode 100644
index 0000000000..9c9a5a0e1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'switch';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.test
new file mode 100644
index 0000000000..687eb7ebab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/switch.test
@@ -0,0 +1,633 @@
+
+case empty_condition
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch ()
+ {
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case condition_float
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float c = 1.0;
+ switch (c)
+ {
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case condition_bool
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ bool c = true;
+ switch (c)
+ {
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case condition_ivec2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ivec2 c = ivec2(1, 1);
+ switch (c)
+ {
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case condition_struct
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int m; };
+
+ void main ()
+ {
+ S c = S(1);
+ switch (c)
+ {
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case duplicate_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ int c = 1;
+ switch (c)
+ {
+ case 1:
+ case 1:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ int c = 1;
+ switch (c)
+ {
+ case 1.0:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case non_const_int_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ int c = 1;
+ int l = 2;
+ switch (c)
+ {
+ case l:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case statement_before_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case statement_before_default_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ default:
+ ${POSITION_FRAG_COLOR} = vec4(0.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case no_statement_after_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ case 0:
+ break;
+ case 1:
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case no_statement_after_default_label
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ case 0:
+ break;
+ default:
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case case_in_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ if (f > 0.0)
+ {
+ case 1:
+ f *= 2.0;
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case default_in_if
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ if (f > 0.0)
+ {
+ default:
+ f *= 2.0;
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case case_in_for_loop
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ for (int i = 0; i < 2; i++)
+ {
+ case 1:
+ f *= 2.0;
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case default_in_for_loop
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ for (int i = 0; i < 2; i++)
+ {
+ default:
+ f *= 2.0;
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case case_in_while_loop
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ while (f > 0.0)
+ {
+ case 1:
+ f *= 2.0;
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case default_in_while_loop
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ while (f > 0.0)
+ {
+ default:
+ f *= 2.0;
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case case_in_do_while_loop
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ do
+ {
+ case 1:
+ f *= 2.0;
+ } while (f > 0.0);
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case default_in_do_while_loop
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ float f = 1.0;
+ switch (1)
+ {
+ case 0:
+ f = 0.0;
+ do
+ {
+ default:
+ f *= 2.0;
+ } while (f > 0.0);
+ break;
+ case 2:
+ break;
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case missing_colon
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ case 1
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case missing_opening_brace
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case missing_closing_brace
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case double_case
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ case case 1:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case double_default_1
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ default:
+ break;
+ default:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
+
+case double_default_2
+ version 300 es
+ expect compile_fail
+ both ""
+ #version 300 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ switch (1)
+ {
+ default default:
+ ${POSITION_FRAG_COLOR} = vec4(1.0);
+ }
+
+ ${OUTPUT}
+ }
+ ""
+end
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.template b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.template
new file mode 100644
index 0000000000..6f633be636
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.template
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.test
new file mode 100644
index 0000000000..2477ebb064
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles.test
@@ -0,0 +1,7459 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group vector_swizzles "Vector Swizzles"
+
+ case mediump_vec2_x
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xx
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xy
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yx
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yxy
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xyxx
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yyyy
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_s
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_ss
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_st
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_ts
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_tst
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_stss
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_tttt
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_r
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rr
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rg
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_gr
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_grg
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rgrr
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_gggg
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_x
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_z
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xyz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zyx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xxx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzy
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_yxy
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xzx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xyyx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzzz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_s
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_p
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_stp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pts
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sss
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_ppp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_ppt
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_tst
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sps
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_stts
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pppp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_r
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_b
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rgb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bgr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rrr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbg
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_grg
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rbr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rggr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbbb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_x
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_w
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wz
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_www
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_yyw
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzy
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xyzw
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzyx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xxxx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_yyyy
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wwww
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzzw
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wwwy
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xyxx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_zzwz
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_s
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_q
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qs
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qp
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ttq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qpt
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_stpq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qpts
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ssss
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_tttt
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqqq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qppq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqqt
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_stss
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ppqp
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_r
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_a
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ar
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ab
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaa
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_gga
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abg
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rgba
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abgr
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rrrr
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_gggg
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaaa
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abba
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaag
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rgrr
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_bbab
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_x
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xx
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xy
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yx
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yxy
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xyxx
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yyyy
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_s
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_ss
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_st
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_ts
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_tst
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_stss
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_tttt
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_r
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rr
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rg
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_gr
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_grg
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rgrr
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_gggg
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_x
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_z
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xyz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zyx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xxx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzy
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_yxy
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xzx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xyyx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzzz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_s
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_p
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_stp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pts
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sss
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_ppp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_ppt
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_tst
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sps
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_stts
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pppp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_r
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_b
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rgb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bgr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rrr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbg
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_grg
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rbr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rggr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbbb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_x
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_w
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wz
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_www
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_yyw
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzy
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xyzw
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzyx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xxxx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_yyyy
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wwww
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzzw
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wwwy
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xyxx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_zzwz
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_s
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_q
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qs
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qp
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ttq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qpt
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_stpq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qpts
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ssss
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_tttt
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqqq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qppq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqqt
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_stss
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ppqp
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_r
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_a
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ar
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ab
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaa
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_gga
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abg
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rgba
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abgr
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rrrr
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_gggg
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaaa
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abba
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaag
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rgrr
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_bbab
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_x
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xx
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xy
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yx
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yxy
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xyxx
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yyyy
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_s
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_ss
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_st
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_ts
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_tst
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_stss
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_tttt
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_r
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rr
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rg
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_gr
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_grg
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rgrr
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_gggg
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_x
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_z
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xyz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zyx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xxx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzy
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_yxy
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xzx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xyyx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzzz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_s
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_p
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_stp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pts
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sss
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_ppp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_ppt
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_tst
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sps
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_stts
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pppp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_r
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_b
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rgb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bgr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rrr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbg
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_grg
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rbr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rggr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbbb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_x
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_w
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wz
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_www
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_yyw
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzy
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xyzw
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzyx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xxxx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_yyyy
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wwww
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzzw
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wwwy
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xyxx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_zzwz
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_s
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_q
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qs
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qp
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ttq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qpt
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_stpq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qpts
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ssss
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_tttt
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqqq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qppq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqqt
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_stss
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ppqp
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_r
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_a
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ar
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ab
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaa
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_gga
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abg
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rgba
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abgr
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rrrr
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_gggg
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaaa
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abba
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaag
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rgrr
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_bbab
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_swizzles
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.html
new file mode 100644
index 0000000000..b83b4d4644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_bvec2';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.test
new file mode 100644
index 0000000000..f1d20ef1ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec2.test
@@ -0,0 +1,511 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group bvec2_swizzles "bvec2 swizzles"
+
+ case mediump_bvec2_x
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_xx
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_xy
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_yx
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_yxy
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_xyxx
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_yyyy
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_s
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_ss
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_st
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_ts
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_tst
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_stss
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_tttt
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_r
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_rr
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_rg
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_gr
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_grg
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_rgrr
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec2_gggg
+ version 300 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # bvec2_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.html
new file mode 100644
index 0000000000..20ab741356
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_bvec3';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.test
new file mode 100644
index 0000000000..31a2ab07f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec3.test
@@ -0,0 +1,943 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group bvec3_swizzles "bvec3 swizzles"
+
+ case mediump_bvec3_x
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_z
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xyz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zyx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xxx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zzz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zzy
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_yxy
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xzx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_xyyx
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_zzzz
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_s
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_p
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_sp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_pp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_stp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_pts
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_sss
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_ppp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_ppt
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_tst
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_sps
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_stts
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_pppp
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_r
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_b
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rgb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bgr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rrr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bbb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bbg
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_grg
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rbr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_rggr
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec3_bbbb
+ version 300 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # bvec3_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.html
new file mode 100644
index 0000000000..39a59c3417
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_bvec4';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.test
new file mode 100644
index 0000000000..55b85c8b05
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_bvec4.test
@@ -0,0 +1,1159 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group bvec4_swizzles "bvec4 swizzles"
+
+ case mediump_bvec4_x
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_w
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wz
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_www
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_yyw
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wzy
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_xyzw
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wzyx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_xxxx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_yyyy
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wwww
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wzzw
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_wwwy
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_xyxx
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_zzwz
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_s
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_q
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qs
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qp
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qqq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ttq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qpt
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_stpq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qpts
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ssss
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_tttt
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qqqq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qppq
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_qqqt
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_stss
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ppqp
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_r
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_a
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ar
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_ab
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_aaa
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_gga
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_abg
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_rgba
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_abgr
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_rrrr
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_gggg
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_aaaa
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_abba
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_aaag
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_rgrr
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_bvec4_bbab
+ version 300 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # bvec4_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.html
new file mode 100644
index 0000000000..76f159b008
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_ivec2';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.test
new file mode 100644
index 0000000000..b26d29b41b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec2.test
@@ -0,0 +1,511 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group ivec2_swizzles "ivec2 swizzles"
+
+ case mediump_ivec2_x
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_xx
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_xy
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_yx
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_yxy
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_xyxx
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_yyyy
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_s
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_ss
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_st
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_ts
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_tst
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_stss
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_tttt
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_r
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_rr
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_rg
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_gr
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_grg
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_rgrr
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec2_gggg
+ version 300 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # ivec2_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.html
new file mode 100644
index 0000000000..ce29c8b8a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_ivec3';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.test
new file mode 100644
index 0000000000..277cbff7f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec3.test
@@ -0,0 +1,943 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group ivec3_swizzles "ivec3 swizzles"
+
+ case mediump_ivec3_x
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_z
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xyz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zyx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xxx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zzz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zzy
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_yxy
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xzx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_xyyx
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_zzzz
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_s
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_p
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_sp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_pp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_stp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_pts
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_sss
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_ppp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_ppt
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_tst
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_sps
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_stts
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_pppp
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_r
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_b
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rgb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bgr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rrr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bbb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bbg
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_grg
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rbr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_rggr
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec3_bbbb
+ version 300 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # ivec3_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.html
new file mode 100644
index 0000000000..3323b9fbb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_ivec4';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.test
new file mode 100644
index 0000000000..22d17df0ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_ivec4.test
@@ -0,0 +1,1159 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group ivec4_swizzles "ivec4 swizzles"
+
+ case mediump_ivec4_x
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_w
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wz
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_www
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_yyw
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wzy
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_xyzw
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wzyx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_xxxx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_yyyy
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wwww
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wzzw
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_wwwy
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_xyxx
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_zzwz
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_s
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_q
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qs
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qp
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qqq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ttq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qpt
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_stpq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qpts
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ssss
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_tttt
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qqqq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qppq
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_qqqt
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_stss
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ppqp
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_r
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_a
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ar
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_ab
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_aaa
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_gga
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_abg
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_rgba
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_abgr
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_rrrr
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_gggg
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_aaaa
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_abba
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_aaag
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_rgrr
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_ivec4_bbab
+ version 300 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # ivec4_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.html
new file mode 100644
index 0000000000..c70c9e24d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_vec2';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.test
new file mode 100644
index 0000000000..dba3acaf6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec2.test
@@ -0,0 +1,511 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group vec2_swizzles "vec2 swizzles"
+
+ case mediump_vec2_x
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_xx
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_xy
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_yx
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_yxy
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_xyxx
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_yyyy
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_s
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_ss
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_st
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_ts
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_tst
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_stss
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_tttt
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_r
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_rr
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_rg
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_gr
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_grg
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_rgrr
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec2_gggg
+ version 300 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vec2_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.html
new file mode 100644
index 0000000000..475d91f002
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_vec3';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.test
new file mode 100644
index 0000000000..d733347215
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec3.test
@@ -0,0 +1,943 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group vec3_swizzles "vec3 swizzles"
+
+ case mediump_vec3_x
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_z
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xyz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zyx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xxx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zzz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zzy
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_yxy
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xzx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_xyyx
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_zzzz
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_s
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_p
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_sp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_pp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_stp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_pts
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_sss
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_ppp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_ppt
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_tst
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_sps
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_stts
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_pppp
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_r
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_b
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rgb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bgr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rrr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bbb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bbg
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_grg
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rbr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_rggr
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec3_bbbb
+ version 300 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vec3_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.html
new file mode 100644
index 0000000000..1121c06fec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.html
@@ -0,0 +1,42 @@
+<!--
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = 'swizzles_vec4';
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.test b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.test
new file mode 100644
index 0000000000..df22f5b493
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/swizzles_vec4.test
@@ -0,0 +1,1159 @@
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+# See split-swizzles.js
+
+group vec4_swizzles "vec4 swizzles"
+
+ case mediump_vec4_x
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_w
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wz
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_www
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_yyw
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wzy
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_xyzw
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wzyx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_xxxx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_yyyy
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wwww
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wzzw
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_wwwy
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_xyxx
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_zzwz
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_s
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_q
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qs
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qp
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qqq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ttq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qpt
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_stpq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qpts
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ssss
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_tttt
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qqqq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qppq
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_qqqt
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_stss
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ppqp
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_r
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_a
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ar
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_ab
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_aaa
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_gga
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_abg
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_rgba
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_abgr
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_rrrr
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_gggg
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_aaaa
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_abba
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_aaag
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_rgrr
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mediump_vec4_bbab
+ version 300 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 300 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vec4_swizzles \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/template.html b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/template.html
new file mode 100644
index 0000000000..a1937f2ca7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/data/gles3/shaders/template.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('modules.shared.glsShaderLibrary');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+testName = ___TEST_NAME___;
+description("Shader test: " + testName + ".");
+WebGLTestUtils.setDefault3DContextVersion(2);
+
+var getFilter = function() {
+ var queryVars = window.location.search.substring(1).split('&');
+
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'filter')
+ return decodeURIComponent(value[1]);
+ }
+}
+
+modules.shared.glsShaderLibrary.run(testName, getFilter())
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuBilinearImageCompare.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuBilinearImageCompare.js
new file mode 100644
index 0000000000..bc23104c09
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuBilinearImageCompare.js
@@ -0,0 +1,272 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuBilinearImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+ var tcuBilinearImageCompare = framework.common.tcuBilinearImageCompare;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuRGBA = framework.common.tcuRGBA;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ // for bilinear interpolation
+ /** @const {number} */ tcuBilinearImageCompare.NUM_SUBPIXEL_BITS = 8;
+
+ // Algorithm assumes that colors are packed to 32-bit values as dictated by
+ // tcu::RGBA::*_SHIFT values.
+
+ function UintRGBA8_R(color) {
+ return (color >> 24) & 0xff;
+ }
+ function UintRGBA8_G(color) {
+ return (color >> 16) & 0xff;
+ }
+ function UintRGBA8_B(color) {
+ return (color >> 8) & 0xff;
+ }
+ function UintRGBA8_A(color) {
+ return color & 0xff;
+ }
+
+ /**
+ * @param {number} fx1 deUint32
+ * @param {number} fy1 deUint32
+ * @param {number} p00 deUint8
+ * @param {number} p01 deUint8
+ * @param {number} p10 deUint8
+ * @param {number} p11 deUint8
+ * @return {number} deUint8
+ */
+ tcuBilinearImageCompare.interpolateChannel = function(fx1, fy1, p00, p01, p10, p11) {
+ /** @const {number} */ var fx0 = (1 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) - fx1;
+ /** @const {number} */ var fy0 = (1 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) - fy1;
+ /** @const {number} */
+ var half = 1 << (tcuBilinearImageCompare.NUM_SUBPIXEL_BITS * 2 - 1);
+ /** @const {number} */ var sum =
+ (fx0 * fy0 * p00) +
+ (fx1 * fy0 * p10) +
+ (fx0 * fy1 * p01) +
+ (fx1 * fy1 * p11);
+ /** @const {number} */
+ var rounded = (sum + half) >> (tcuBilinearImageCompare.NUM_SUBPIXEL_BITS * 2);
+
+ DE_ASSERT(deMath.deInRange32(rounded, 0, 0xff));
+ return rounded;
+ };
+
+ tcuBilinearImageCompare.compareUintRGBA8Threshold = function(a, b, thr) {
+ if (a == b)
+ return true;
+
+ return (Math.abs(UintRGBA8_R(a) - UintRGBA8_R(b)) <= thr.getRed() &&
+ Math.abs(UintRGBA8_G(a) - UintRGBA8_G(b)) <= thr.getGreen() &&
+ Math.abs(UintRGBA8_B(a) - UintRGBA8_B(b)) <= thr.getBlue() &&
+ Math.abs(UintRGBA8_A(a) - UintRGBA8_A(b)) <= thr.getAlpha());
+ };
+
+ /**
+ * @param {tcuTexture.RGBA8View} view
+ * @param {number} u
+ * @param {number} v
+ * @return {number}
+ */
+ tcuBilinearImageCompare.bilinearSampleUintRGBA8 = function(view, u, v) {
+ /** @type {number} */ var x0 = u >> tcuBilinearImageCompare.NUM_SUBPIXEL_BITS;
+ /** @type {number} */ var y0 = v >> tcuBilinearImageCompare.NUM_SUBPIXEL_BITS;
+ /** @type {number} */ var x1 = x0 + 1;
+ /** @type {number} */ var y1 = y0 + 1;
+
+ DE_ASSERT(x1 < view.getWidth());
+ DE_ASSERT(y1 < view.getHeight());
+
+ /** @type {number} */ var fx1 = u - (x0 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS);
+ /** @type {number} */ var fy1 = v - (y0 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS);
+
+ /** @type {Array<number>} */ var channelsP00 = view.readUintRGBA8(x0, y0);
+ /** @type {Array<number>} */ var channelsP10 = view.readUintRGBA8(x1, y0);
+ /** @type {Array<number>} */ var channelsP01 = view.readUintRGBA8(x0, y1);
+ /** @type {Array<number>} */ var channelsP11 = view.readUintRGBA8(x1, y1);
+
+ /** @type {number} */ var res = 0;
+
+ res = (tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_R(channelsP00),
+ UintRGBA8_R(channelsP01), UintRGBA8_R(channelsP10), UintRGBA8_R(channelsP11)) & 0xff) << 24;
+ res += (tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_G(channelsP00),
+ UintRGBA8_G(channelsP01), UintRGBA8_G(channelsP10), UintRGBA8_G(channelsP11)) & 0xff) << 16;
+ res += (tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_B(channelsP00),
+ UintRGBA8_B(channelsP01), UintRGBA8_B(channelsP10), UintRGBA8_B(channelsP11)) & 0xff) << 8;
+ res += tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_A(channelsP00),
+ UintRGBA8_A(channelsP01), UintRGBA8_A(channelsP10), UintRGBA8_A(channelsP11)) & 0xff;
+
+ return res;
+ };
+
+ /**
+ * @param {tcuTexture.RGBA8View} reference
+ * @param {tcuTexture.RGBA8View} result
+ * @param {tcuRGBA.RGBA} threshold
+ * @param {number} x
+ * @param {number} y
+ * @return {boolean}
+ */
+ tcuBilinearImageCompare.comparePixelRGBA8 = function(reference, result, threshold, x, y) {
+ /** @const {tcuRGBA.RGBA} */ var resPix = result.readUintRGBA8(x, y);
+
+ // Step 1: Compare result pixel to 3x3 neighborhood pixels in reference.
+ /** @const {number} */ var x0 = Math.max(x - 1, 0);
+ /** @const {number} */ var x1 = x;
+ /** @const {number} */
+ var x2 = Math.min(x + 1, reference.getWidth() - 1);
+ /** @const {number} */ var y0 = Math.max(y - 1, 0);
+ /** @const {number} */ var y1 = y;
+ /** @const {number} */
+ var y2 = Math.min(y + 1, reference.getHeight() - 1);
+
+ //tcuBilinearImageCompare.readRGBA8List (reference, x0, y0, x2, y2);
+
+ if (tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x1, y1), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x0, y1), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x2, y1), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x0, y0), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x1, y0), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x2, y0), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x0, y2), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x1, y2), threshold) ||
+ tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x2, y2), threshold))
+ return true;
+
+ // Step 2: Compare using bilinear sampling.
+ // \todo [pyry] Optimize sample positions!
+ /** @const {Array<Array<number>>} */ var s_offsets = [
+ [226, 186],
+ [335, 235],
+ [279, 334],
+ [178, 272],
+ [112, 202],
+ [306, 117],
+ [396, 299],
+ [206, 382],
+ [146, 96],
+ [423, 155],
+ [361, 412],
+ [84, 339],
+ [48, 130],
+ [367, 43],
+ [455, 367],
+ [105, 439],
+ [83, 46],
+ [217, 24],
+ [461, 71],
+ [450, 459],
+ [239, 469],
+ [67, 267],
+ [459, 255],
+ [13, 416],
+ [10, 192],
+ [141, 502],
+ [503, 304],
+ [380, 506]
+ ];
+
+ for (var sampleNdx = 0; sampleNdx < s_offsets.length; sampleNdx++) {
+ /** @const {number} */
+ var u = ((x - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) + s_offsets[sampleNdx][0];
+ /** @const {number} */
+ var v = ((y - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) + s_offsets[sampleNdx][1];
+
+ if (!deMath.deInBounds32(u, 0, (reference.getWidth() - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) ||
+ !deMath.deInBounds32(v, 0, (reference.getHeight() - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS))
+ continue;
+
+ if (tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, tcuBilinearImageCompare.bilinearSampleUintRGBA8(reference, u, v), threshold))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.RGBA8View} reference
+ * @param {tcuTexture.RGBA8View} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuRGBA.RGBA} threshold
+ * @return {boolean}
+ */
+ tcuBilinearImageCompare.bilinearCompareRGBA8 = function(reference, result, errorMask, threshold) {
+ DE_ASSERT(reference.getFormat().isEqual(new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)));
+ DE_ASSERT(result.getFormat().isEqual(new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)));
+
+ // Clear error mask first to green (faster this way).
+ errorMask.clear([0.0, 1.0, 0.0, 1.0]);
+
+ /** @type {boolean} */ var allOk = true;
+
+ for (var y = 0; y < reference.getHeight(); y++) {
+ for (var x = 0; x < reference.getWidth(); x++) {
+ if (!tcuBilinearImageCompare.comparePixelRGBA8(reference, result, threshold, x, y) &&
+ !tcuBilinearImageCompare.comparePixelRGBA8(result, reference, threshold, x, y)) {
+ allOk = false;
+ errorMask.setPixel([1.0, 0.0, 0.0, 1.0], x, y);
+ }
+ }
+ }
+
+ return allOk;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuRGBA.RGBA} threshold
+ * @return {boolean}
+ */
+ tcuBilinearImageCompare.bilinearCompare = function(reference, result, errorMask, threshold) {
+ assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight() && result.getDepth() == reference.getDepth(),
+ 'Reference and result images have different dimensions', false, true);
+
+ assertMsgOptions(errorMask.getWidth() == reference.getWidth() && errorMask.getHeight() == reference.getHeight() && errorMask.getDepth() == reference.getDepth(),
+ 'Reference and error mask images have different dimensions', false, true);
+
+ /** @type {boolean} */ var isEqual = reference.getFormat().isEqual(
+ new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8));
+ if (isEqual) {
+ /** @type {tcuTexture.RGBA8View} */ var refView = new tcuTexture.RGBA8View(reference);
+ /** @type {tcuTexture.RGBA8View} */ var resView = new tcuTexture.RGBA8View(result);
+ return tcuBilinearImageCompare.bilinearCompareRGBA8(refView, resView, errorMask, threshold);
+ } else
+ throw new Error('Unsupported format for bilinear comparison');
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuCompressedTexture.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuCompressedTexture.js
new file mode 100644
index 0000000000..a309f81cfd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuCompressedTexture.js
@@ -0,0 +1,967 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Map tcu::TextureFormat to GL pixel transfer format.
+ *
+ * Maps generic texture format description to GL pixel transfer format.
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * \param texFormat Generic texture format.
+ * \return GL pixel transfer format.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('framework.common.tcuCompressedTexture');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuCompressedTexture = framework.common.tcuCompressedTexture;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+/**
+ * @enum
+ */
+tcuCompressedTexture.Format = {
+ ETC1_RGB8: 0,
+ EAC_R11: 1,
+ EAC_SIGNED_R11: 2,
+ EAC_RG11: 3,
+ EAC_SIGNED_RG11: 4,
+ ETC2_RGB8: 5,
+ ETC2_SRGB8: 6,
+ ETC2_RGB8_PUNCHTHROUGH_ALPHA1: 7,
+ ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: 8,
+ ETC2_EAC_RGBA8: 9,
+ ETC2_EAC_SRGB8_ALPHA8: 10,
+
+ ASTC_4x4_RGBA: 11,
+ ASTC_5x4_RGBA: 12,
+ ASTC_5x5_RGBA: 13,
+ ASTC_6x5_RGBA: 14,
+ ASTC_6x6_RGBA: 15,
+ ASTC_8x5_RGBA: 16,
+ ASTC_8x6_RGBA: 17,
+ ASTC_8x8_RGBA: 18,
+ ASTC_10x5_RGBA: 19,
+ ASTC_10x6_RGBA: 20,
+ ASTC_10x8_RGBA: 21,
+ ASTC_10x10_RGBA: 22,
+ ASTC_12x10_RGBA: 23,
+ ASTC_12x12_RGBA: 24,
+ ASTC_4x4_SRGB8_ALPHA8: 25,
+ ASTC_5x4_SRGB8_ALPHA8: 26,
+ ASTC_5x5_SRGB8_ALPHA8: 27,
+ ASTC_6x5_SRGB8_ALPHA8: 28,
+ ASTC_6x6_SRGB8_ALPHA8: 29,
+ ASTC_8x5_SRGB8_ALPHA8: 30,
+ ASTC_8x6_SRGB8_ALPHA8: 31,
+ ASTC_8x8_SRGB8_ALPHA8: 32,
+ ASTC_10x5_SRGB8_ALPHA8: 33,
+ ASTC_10x6_SRGB8_ALPHA8: 34,
+ ASTC_10x8_SRGB8_ALPHA8: 35,
+ ASTC_10x10_SRGB8_ALPHA8: 36,
+ ASTC_12x10_SRGB8_ALPHA8: 37,
+ ASTC_12x12_SRGB8_ALPHA8: 38
+};
+
+tcuCompressedTexture.divRoundUp = function(a, b) {
+ return Math.floor(a / b) + ((a % b) ? 1 : 0);
+};
+
+tcuCompressedTexture.isEtcFormat = function(fmt) {
+ // WebGL2 supports ETC2 and EAC formats
+ switch (fmt) {
+ // case tcuCompressedTexture.Format.ETC1_RGB8:
+ case tcuCompressedTexture.Format.EAC_R11:
+ case tcuCompressedTexture.Format.EAC_SIGNED_R11:
+ case tcuCompressedTexture.Format.EAC_RG11:
+ case tcuCompressedTexture.Format.EAC_SIGNED_RG11:
+ case tcuCompressedTexture.Format.ETC2_RGB8:
+ case tcuCompressedTexture.Format.ETC2_SRGB8:
+ case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
+ case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+ case tcuCompressedTexture.Format.ETC2_EAC_RGBA8:
+ case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8:
+ return true;
+
+ default:
+ return false;
+ }
+};
+
+tcuCompressedTexture.etcDecompressInternal = function() {
+
+var ETC2_BLOCK_WIDTH = 4;
+var ETC2_BLOCK_HEIGHT = 4;
+var ETC2_UNCOMPRESSED_PIXEL_SIZE_A8 = 1;
+var ETC2_UNCOMPRESSED_PIXEL_SIZE_R11 = 2;
+var ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11 = 4;
+var ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8 = 3;
+var ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 = 4;
+var ETC2_UNCOMPRESSED_BLOCK_SIZE_A8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
+var ETC2_UNCOMPRESSED_BLOCK_SIZE_R11 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
+var ETC2_UNCOMPRESSED_BLOCK_SIZE_RG11 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11;
+var ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+var ETC2_UNCOMPRESSED_BLOCK_SIZE_RGBA8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
+
+/**
+ * @param {ArrayBuffer} src Source ArrayBuffer
+ * @return {Uint8Array}
+ */
+var get64BitBlock = function(src, blockNdx) {
+ var block = new Uint8Array(src, blockNdx * 8, 8);
+ return block;
+};
+
+/**
+ * @param {ArrayBuffer} src Source ArrayBuffer
+ * Return the first 64 bits of a 128 bit block.
+ */
+var get128BitBlockStart = function(src, blockNdx) {
+ return get64BitBlock(src, 2 * blockNdx);
+};
+
+/**
+ * @param {ArrayBuffer} src Source ArrayBuffer
+ * Return the last 64 bits of a 128 bit block.
+ */
+var get128BitBlockEnd = function(src, blockNdx) {
+ return get64BitBlock(src, 2 * blockNdx + 1);
+};
+
+var mask8 = function(src, low, high) {
+ if (low > 7 || high < 0)
+ return {
+ value: 0,
+ bits: 0
+ };
+
+ var numBits = high - low + 1;
+ var mask = (1 << numBits) - 1;
+
+ return {
+ value: (src >> low) & mask,
+ bits: numBits
+ };
+};
+
+var getBits64 = function(src, low, high) {
+ var result = 0;
+ var bits = 0;
+ var lowIndex = low;
+ var highIndex = high;
+ for (var i = 7; i >= 0; i--) {
+ var v = mask8(src[i], Math.max(0, lowIndex), Math.min(7, highIndex));
+ lowIndex = lowIndex - 8;
+ highIndex = highIndex - 8;
+ result = result | (v.value << bits);
+ bits = v.bits;
+ }
+ return result;
+};
+
+var getBit64 = function(src, bit) {
+ return getBits64(src, bit, bit);
+};
+
+var extendSigned3To8 = function(src) {
+ var isNeg = (src & (1 << 2)) != 0;
+ var val = isNeg ? src - 8 : src;
+ return val;
+};
+
+var extend4To8 = function(src) {
+ return src * 255 / 15;
+};
+
+var extend5To8 = function(src) {
+ return src * 255 / 31;
+};
+
+var extend6To8 = function(src) {
+ return src * 255 / 63;
+};
+
+var extend7To8 = function(src) {
+ return src * 255 / 127;
+};
+
+var extend11To16 = function(src) {
+ return src * 32.015144;
+};
+
+var extend11To16WithSign = function(src) {
+ if (src < 0)
+ return -extend11To16(-src);
+ else
+ return extend11To16(src);
+};
+
+/**
+ * @param { (Uint16Array|Int16Array) } dst
+ * @param {Uint8Array} src
+ * @param {boolean} signedMode
+ */
+var decompressEAC11Block = function(dst, src, signedMode) {
+ var modifierTable = [
+ [-3, -6, -9, -15, 2, 5, 8, 14],
+ [-3, -7, -10, -13, 2, 6, 9, 12],
+ [-2, -5, -8, -13, 1, 4, 7, 12],
+ [-2, -4, -6, -13, 1, 3, 5, 12],
+ [-3, -6, -8, -12, 2, 5, 7, 11],
+ [-3, -7, -9, -11, 2, 6, 8, 10],
+ [-4, -7, -8, -11, 3, 6, 7, 10],
+ [-3, -5, -8, -11, 2, 4, 7, 10],
+ [-2, -6, -8, -10, 1, 5, 7, 9],
+ [-2, -5, -8, -10, 1, 4, 7, 9],
+ [-2, -4, -8, -10, 1, 3, 7, 9],
+ [-2, -5, -7, -10, 1, 4, 6, 9],
+ [-3, -4, -7, -10, 2, 3, 6, 9],
+ [-1, -2, -3, -10, 0, 1, 2, 9],
+ [-4, -6, -8, -9, 3, 5, 7, 8],
+ [-3, -5, -7, -9, 2, 4, 6, 8]
+ ];
+
+ var multiplier = getBits64(src, 52, 55);
+ var tableNdx = getBits64(src, 48, 51);
+ var baseCodeword = getBits64(src, 56, 63);
+
+ if (signedMode) {
+ if (baseCodeword > 127)
+ baseCodeword -= 256;
+ if (baseCodeword == -128)
+ baseCodeword = -127;
+ }
+
+ var pixelNdx = 0;
+ for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
+ for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++) {
+ var dstOffset = (y * ETC2_BLOCK_WIDTH + x);
+ var pixelBitNdx = 45 - 3 * pixelNdx;
+ var modifierNdx = (getBit64(src, pixelBitNdx + 2) << 2) | (getBit64(src, pixelBitNdx + 1) << 1) | getBit64(src, pixelBitNdx);
+ var modifier = modifierTable[tableNdx][modifierNdx];
+
+ if (signedMode) {
+ if (multiplier != 0)
+ dst[dstOffset] = deMath.clamp(baseCodeword * 8 + multiplier * modifier * 8, -1023, 1023);
+ else
+ dst[dstOffset] = deMath.clamp(baseCodeword * 8 + modifier, -1023, 1023);
+ } else {
+ if (multiplier != 0)
+ dst[dstOffset] = deMath.clamp(baseCodeword * 8 + 4 + multiplier * modifier * 8, 0, 2047);
+ else
+ dst[dstOffset] = deMath.clamp(baseCodeword * 8 + 4 + modifier, 0, 2047);
+ }
+ pixelNdx++;
+ }
+ }
+};
+
+var decompressEAC_R11 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src, signedMode) {
+ /** @const */ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
+ /** @const */ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
+ var dstPtr;
+ var dstRowPitch = dst.getRowPitch();
+ var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
+ var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_R11);
+ var uncompressedBlock16;
+ if (signedMode) {
+ dstPtr = new Int16Array(dst.m_data);
+ uncompressedBlock16 = new Int16Array(uncompressedBlockArray);
+ } else {
+ dstPtr = new Uint16Array(dst.m_data);
+ uncompressedBlock16 = new Uint16Array(uncompressedBlockArray);
+ }
+
+ for (var blockY = 0; blockY < numBlocksY; blockY++) {
+ for (var blockX = 0; blockX < numBlocksX; blockX++) {
+ /*const deUint64*/ var compressedBlock = get64BitBlock(src, blockY * numBlocksX + blockX);
+
+ // Decompress.
+ decompressEAC11Block(uncompressedBlock16, compressedBlock, signedMode);
+
+ // Write to dst.
+ var baseX = blockX * ETC2_BLOCK_WIDTH;
+ var baseY = blockY * ETC2_BLOCK_HEIGHT;
+ for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
+ for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
+ DE_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_R11 == 2);
+
+ if (signedMode) {
+ var srcIndex = y * ETC2_BLOCK_WIDTH + x;
+ var dstIndex = (baseY + y) * dstRowPitch / dstPixelSize + baseX + x;
+
+ dstPtr[dstIndex] = extend11To16WithSign(uncompressedBlock16[srcIndex]);
+ } else {
+ var srcIndex = y * ETC2_BLOCK_WIDTH + x;
+ var dstIndex = (baseY + y) * dstRowPitch / dstPixelSize + baseX + x;
+
+ dstPtr[dstIndex] = extend11To16(uncompressedBlock16[srcIndex]);
+ }
+ }
+ }
+ }
+ }
+};
+
+var decompressEAC_RG11 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src, signedMode) {
+ /** @const */ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
+ /** @const */ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
+ var dstPtr;
+ var dstRowPitch = dst.getRowPitch();
+ var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11;
+ var uncompressedBlockArrayR = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_R11);
+ var uncompressedBlockArrayG = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_R11);
+ var uncompressedBlockR16;
+ var uncompressedBlockG16;
+ if (signedMode) {
+ dstPtr = new Int16Array(dst.m_data);
+ uncompressedBlockR16 = new Int16Array(uncompressedBlockArrayR);
+ uncompressedBlockG16 = new Int16Array(uncompressedBlockArrayG);
+ } else {
+ dstPtr = new Uint16Array(dst.m_data);
+ uncompressedBlockR16 = new Uint16Array(uncompressedBlockArrayR);
+ uncompressedBlockG16 = new Uint16Array(uncompressedBlockArrayG);
+ }
+
+ for (var blockY = 0; blockY < numBlocksY; blockY++) {
+ for (var blockX = 0; blockX < numBlocksX; blockX++) {
+ /*const deUint64*/ var compressedBlockR = get128BitBlockStart(src, blockY * numBlocksX + blockX);
+ /*const deUint64*/ var compressedBlockG = get128BitBlockEnd(src, blockY * numBlocksX + blockX);
+
+ // Decompress.
+ decompressEAC11Block(uncompressedBlockR16, compressedBlockR, signedMode);
+ decompressEAC11Block(uncompressedBlockG16, compressedBlockG, signedMode);
+
+ // Write to dst.
+ var baseX = blockX * ETC2_BLOCK_WIDTH;
+ var baseY = blockY * ETC2_BLOCK_HEIGHT;
+ for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
+ for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
+ DE_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11 == 4);
+
+ if (signedMode) {
+ var srcIndex = y * ETC2_BLOCK_WIDTH + x;
+ var dstIndex = 2 * ((baseY + y) * dstRowPitch / dstPixelSize + baseX + x);
+
+ dstPtr[dstIndex] = extend11To16WithSign(uncompressedBlockR16[srcIndex]);
+ dstPtr[dstIndex + 1] = extend11To16WithSign(uncompressedBlockG16[srcIndex]);
+ } else {
+ var srcIndex = y * ETC2_BLOCK_WIDTH + x;
+ var dstIndex = 2 * ((baseY + y) * dstRowPitch / dstPixelSize + baseX + x);
+
+ dstPtr[dstIndex] = extend11To16(uncompressedBlockR16[srcIndex]);
+ dstPtr[dstIndex + 1] = extend11To16(uncompressedBlockG16[srcIndex]);
+ }
+ }
+ }
+ }
+ }
+};
+
+// if alphaMode is true, do PUNCHTHROUGH and store alpha to alphaDst; otherwise do ordinary ETC2 RGB8.
+/**
+ * @param {Uint8Array} dst Destination array
+ * @param {Uint8Array} src Source array
+ * @param {Uint8Array} alphaDst Optional Alpha output channel
+ */
+var decompressETC2Block = function(dst, src, alphaDst, alphaMode) {
+ /**
+ * enum
+ */
+ var Etc2Mode = {
+ MODE_INDIVIDUAL: 0,
+ MODE_DIFFERENTIAL: 1,
+ MODE_T: 2,
+ MODE_H: 3,
+ MODE_PLANAR: 4
+ };
+
+ var diffOpaqueBit = getBit64(src, 33);
+ var selBR = getBits64(src, 59, 63); // 5 bits.
+ var selBG = getBits64(src, 51, 55);
+ var selBB = getBits64(src, 43, 47);
+ var selDR = extendSigned3To8(getBits64(src, 56, 58)); // 3 bits.
+ var selDG = extendSigned3To8(getBits64(src, 48, 50));
+ var selDB = extendSigned3To8(getBits64(src, 40, 42));
+
+ var mode;
+
+ if (!alphaMode && diffOpaqueBit == 0)
+ mode = Etc2Mode.MODE_INDIVIDUAL;
+ else if (!deMath.deInRange32(selBR + selDR, 0, 31))
+ mode = Etc2Mode.MODE_T;
+ else if (!deMath.deInRange32(selBG + selDG, 0, 31))
+ mode = Etc2Mode.MODE_H;
+ else if (!deMath.deInRange32(selBB + selDB, 0, 31))
+ mode = Etc2Mode.MODE_PLANAR;
+ else
+ mode = Etc2Mode.MODE_DIFFERENTIAL;
+
+ if (mode == Etc2Mode.MODE_INDIVIDUAL || mode == Etc2Mode.MODE_DIFFERENTIAL) {
+ // Individual and differential modes have some steps in common, handle them here.
+ var modifierTable = [
+ // 00 01 10 11
+ [2, 8, -2, -8],
+ [5, 17, -5, -17],
+ [9, 29, -9, -29],
+ [13, 42, -13, -42],
+ [18, 60, -18, -60],
+ [24, 80, -24, -80],
+ [33, 106, -33, -106],
+ [47, 183, -47, -183]
+ ];
+
+ var flipBit = getBit64(src, 32);
+ var table = [getBits64(src, 37, 39), getBits64(src, 34, 36)];
+ var baseR = [];
+ var baseG = [];
+ var baseB = [];
+
+ if (mode == Etc2Mode.MODE_INDIVIDUAL) {
+ // Individual mode, initial values.
+ baseR[0] = extend4To8(getBits64(src, 60, 63));
+ baseR[1] = extend4To8(getBits64(src, 56, 59));
+ baseG[0] = extend4To8(getBits64(src, 52, 55));
+ baseG[1] = extend4To8(getBits64(src, 48, 51));
+ baseB[0] = extend4To8(getBits64(src, 44, 47));
+ baseB[1] = extend4To8(getBits64(src, 40, 43));
+ } else {
+ // Differential mode, initial values.
+ baseR[0] = extend5To8(selBR);
+ baseG[0] = extend5To8(selBG);
+ baseB[0] = extend5To8(selBB);
+
+ baseR[1] = extend5To8((selBR + selDR));
+ baseG[1] = extend5To8((selBG + selDG));
+ baseB[1] = extend5To8((selBB + selDB));
+ }
+
+ // Write final pixels for individual or differential mode.
+ var pixelNdx = 0;
+ for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
+ for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++, pixelNdx++) {
+ var dstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var subBlock = ((flipBit ? y : x) >= 2) ? 1 : 0;
+ var tableNdx = table[subBlock];
+ var modifierNdx = (getBit64(src, 16 + pixelNdx) << 1) | getBit64(src, pixelNdx);
+ var alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
+
+ // If doing PUNCHTHROUGH version (alphaMode), opaque bit may affect colors.
+ if (alphaMode && diffOpaqueBit == 0 && modifierNdx == 2) {
+ dst[dstOffset + 0] = 0;
+ dst[dstOffset + 1] = 0;
+ dst[dstOffset + 2] = 0;
+ alphaDst[alphaDstOffset] = 0;
+ } else {
+ var modifier;
+
+ // PUNCHTHROUGH version and opaque bit may also affect modifiers.
+ if (alphaMode && diffOpaqueBit == 0 && (modifierNdx == 0 || modifierNdx == 2))
+ modifier = 0;
+ else
+ modifier = modifierTable[tableNdx][modifierNdx];
+
+ dst[dstOffset + 0] = deMath.clamp(baseR[subBlock] + modifier, 0, 255);
+ dst[dstOffset + 1] = deMath.clamp(baseG[subBlock] + modifier, 0, 255);
+ dst[dstOffset + 2] = deMath.clamp(baseB[subBlock] + modifier, 0, 255);
+
+ if (alphaMode)
+ alphaDst[alphaDstOffset] = 255;
+ }
+ }
+ }
+ } else if (mode == Etc2Mode.MODE_T || mode == Etc2Mode.MODE_H) {
+ // T and H modes have some steps in common, handle them here.
+ var distTable = [3, 6, 11, 16, 23, 32, 41, 64];
+
+ var paintR = [];
+ var paintG = [];
+ var paintB = [];
+
+ if (mode == Etc2Mode.MODE_T) {
+ // T mode, calculate paint values.
+ var R1a = getBits64(src, 59, 60);
+ var R1b = getBits64(src, 56, 57);
+ var G1 = getBits64(src, 52, 55);
+ var B1 = getBits64(src, 48, 51);
+ var R2 = getBits64(src, 44, 47);
+ var G2 = getBits64(src, 40, 43);
+ var B2 = getBits64(src, 36, 39);
+ var distNdx = (getBits64(src, 34, 35) << 1) | getBit64(src, 32);
+ var dist = distTable[distNdx];
+
+ paintR[0] = extend4To8((R1a << 2) | R1b);
+ paintG[0] = extend4To8(G1);
+ paintB[0] = extend4To8(B1);
+ paintR[2] = extend4To8(R2);
+ paintG[2] = extend4To8(G2);
+ paintB[2] = extend4To8(B2);
+ paintR[1] = deMath.clamp(paintR[2] + dist, 0, 255);
+ paintG[1] = deMath.clamp(paintG[2] + dist, 0, 255);
+ paintB[1] = deMath.clamp(paintB[2] + dist, 0, 255);
+ paintR[3] = deMath.clamp(paintR[2] - dist, 0, 255);
+ paintG[3] = deMath.clamp(paintG[2] - dist, 0, 255);
+ paintB[3] = deMath.clamp(paintB[2] - dist, 0, 255);
+ } else {
+ // H mode, calculate paint values.
+ var R1 = getBits64(src, 59, 62);
+ var G1a = getBits64(src, 56, 58);
+ var G1b = getBit64(src, 52);
+ var B1a = getBit64(src, 51);
+ var B1b = getBits64(src, 47, 49);
+ var R2 = getBits64(src, 43, 46);
+ var G2 = getBits64(src, 39, 42);
+ var B2 = getBits64(src, 35, 38);
+ var baseR = [];
+ var baseG = [];
+ var baseB = [];
+ var baseValue = [];
+ var distNdx;
+ var dist;
+
+ baseR[0] = extend4To8(R1);
+ baseG[0] = extend4To8((G1a << 1) | G1b);
+ baseB[0] = extend4To8((B1a << 3) | B1b);
+ baseR[1] = extend4To8(R2);
+ baseG[1] = extend4To8(G2);
+ baseB[1] = extend4To8(B2);
+ baseValue[0] = ((baseR[0]) << 16) | ((baseG[0]) << 8) | baseB[0];
+ baseValue[1] = ((baseR[1]) << 16) | ((baseG[1]) << 8) | baseB[1];
+ distNdx = (getBit64(src, 34) << 2) | (getBit64(src, 32) << 1);
+ if (baseValue[0] >= baseValue[1])
+ distNdx += 1;
+ dist = distTable[distNdx];
+
+ paintR[0] = deMath.clamp(baseR[0] + dist, 0, 255);
+ paintG[0] = deMath.clamp(baseG[0] + dist, 0, 255);
+ paintB[0] = deMath.clamp(baseB[0] + dist, 0, 255);
+ paintR[1] = deMath.clamp(baseR[0] - dist, 0, 255);
+ paintG[1] = deMath.clamp(baseG[0] - dist, 0, 255);
+ paintB[1] = deMath.clamp(baseB[0] - dist, 0, 255);
+ paintR[2] = deMath.clamp(baseR[1] + dist, 0, 255);
+ paintG[2] = deMath.clamp(baseG[1] + dist, 0, 255);
+ paintB[2] = deMath.clamp(baseB[1] + dist, 0, 255);
+ paintR[3] = deMath.clamp(baseR[1] - dist, 0, 255);
+ paintG[3] = deMath.clamp(baseG[1] - dist, 0, 255);
+ paintB[3] = deMath.clamp(baseB[1] - dist, 0, 255);
+ }
+
+ // Write final pixels for T or H mode.
+ var pixelNdx = 0;
+ for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
+ for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++, pixelNdx++) {
+ var dstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var paintNdx = (getBit64(src, 16 + pixelNdx) << 1) | getBit64(src, pixelNdx);
+ var alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
+
+ if (alphaMode && diffOpaqueBit == 0 && paintNdx == 2) {
+ dst[dstOffset + 0] = 0;
+ dst[dstOffset + 1] = 0;
+ dst[dstOffset + 2] = 0;
+ alphaDst[alphaDstOffset] = 0;
+ } else {
+ dst[dstOffset + 0] = deMath.clamp(paintR[paintNdx], 0, 255);
+ dst[dstOffset + 1] = deMath.clamp(paintG[paintNdx], 0, 255);
+ dst[dstOffset + 2] = deMath.clamp(paintB[paintNdx], 0, 255);
+
+ if (alphaMode)
+ alphaDst[alphaDstOffset] = 255;
+ }
+ }
+ }
+ } else {
+ // Planar mode.
+ var GO1 = getBit64(src, 56);
+ var GO2 = getBits64(src, 49, 54);
+ var BO1 = getBit64(src, 48);
+ var BO2 = getBits64(src, 43, 44);
+ var BO3 = getBits64(src, 39, 41);
+ var RH1 = getBits64(src, 34, 38);
+ var RH2 = getBit64(src, 32);
+ var RO = extend6To8(getBits64(src, 57, 62));
+ var GO = extend7To8((GO1 << 6) | GO2);
+ var BO = extend6To8((BO1 << 5) | (BO2 << 3) | BO3);
+ var RH = extend6To8((RH1 << 1) | RH2);
+ var GH = extend7To8(getBits64(src, 25, 31));
+ var BH = extend6To8(getBits64(src, 19, 24));
+ var RV = extend6To8(getBits64(src, 13, 18));
+ var GV = extend7To8(getBits64(src, 6, 12));
+ var BV = extend6To8(getBits64(src, 0, 5));
+
+ // Write final pixels for planar mode.
+ for (var y = 0; y < 4; y++) {
+ for (var x = 0; x < 4; x++) {
+ var dstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var unclampedR = (x * (RH - RO) + y * (RV - RO) + 4 * RO + 2) / 4;
+ var unclampedG = (x * (GH - GO) + y * (GV - GO) + 4 * GO + 2) / 4;
+ var unclampedB = (x * (BH - BO) + y * (BV - BO) + 4 * BO + 2) / 4;
+ var alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
+
+ dst[dstOffset + 0] = deMath.clamp(unclampedR, 0, 255);
+ dst[dstOffset + 1] = deMath.clamp(unclampedG, 0, 255);
+ dst[dstOffset + 2] = deMath.clamp(unclampedB, 0, 255);
+
+ if (alphaMode)
+ alphaDst[alphaDstOffset] = 255;
+ }
+ }
+ }
+};
+
+var decompressEAC8Block = function(dst, src) {
+ var modifierTable = [
+ [-3, -6, -9, -15, 2, 5, 8, 14],
+ [-3, -7, -10, -13, 2, 6, 9, 12],
+ [-2, -5, -8, -13, 1, 4, 7, 12],
+ [-2, -4, -6, -13, 1, 3, 5, 12],
+ [-3, -6, -8, -12, 2, 5, 7, 11],
+ [-3, -7, -9, -11, 2, 6, 8, 10],
+ [-4, -7, -8, -11, 3, 6, 7, 10],
+ [-3, -5, -8, -11, 2, 4, 7, 10],
+ [-2, -6, -8, -10, 1, 5, 7, 9],
+ [-2, -5, -8, -10, 1, 4, 7, 9],
+ [-2, -4, -8, -10, 1, 3, 7, 9],
+ [-2, -5, -7, -10, 1, 4, 6, 9],
+ [-3, -4, -7, -10, 2, 3, 6, 9],
+ [-1, -2, -3, -10, 0, 1, 2, 9],
+ [-4, -6, -8, -9, 3, 5, 7, 8],
+ [-3, -5, -7, -9, 2, 4, 6, 8]
+ ];
+
+ var baseCodeword = getBits64(src, 56, 63);
+ var multiplier = getBits64(src, 52, 55);
+ var tableNdx = getBits64(src, 48, 51);
+
+ var pixelNdx = 0;
+ for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
+ for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++, pixelNdx++) {
+ var dstOffset = (y * ETC2_BLOCK_WIDTH + x);
+ var pixelBitNdx = 45 - 3 * pixelNdx;
+ var modifierNdx = (getBit64(src, pixelBitNdx + 2) << 2) | (getBit64(src, pixelBitNdx + 1) << 1) | getBit64(src, pixelBitNdx);
+ var modifier = modifierTable[tableNdx][modifierNdx];
+
+ dst[dstOffset] = deMath.clamp(baseCodeword + multiplier * modifier, 0, 255);
+ }
+ }
+};
+
+var decompressETC2 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src) {
+ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
+ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
+ var dstPtr = new Uint8Array(dst.m_data);
+ var dstRowPitch = dst.getRowPitch();
+ var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8);
+ var uncompressedBlock = new Uint8Array(uncompressedBlockArray);
+
+ for (var blockY = 0; blockY < numBlocksY; blockY++) {
+ for (var blockX = 0; blockX < numBlocksX; blockX++) {
+ var compressedBlock = get64BitBlock(src, blockY * numBlocksX + blockX);
+
+ // Decompress.
+ decompressETC2Block(uncompressedBlock, compressedBlock, null, false);
+
+ // Write to dst.
+ var baseX = blockX * ETC2_BLOCK_WIDTH;
+ var baseY = blockY * ETC2_BLOCK_HEIGHT;
+ for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
+ for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
+ var srcIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var dstIndex = (baseY + y) * dstRowPitch + (baseX + x) * dstPixelSize;
+
+ for (var i = 0; i < ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8; i++)
+ dstPtr[dstIndex + i] = uncompressedBlock[srcIndex + i];
+ }
+ }
+ }
+ }
+};
+
+var decompressETC2_EAC_RGBA8 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src) {
+ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
+ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
+ var dstPtr = new Uint8Array(dst.m_data);
+ var dstRowPitch = dst.getRowPitch();
+ var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
+ var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8);
+ var uncompressedBlock = new Uint8Array(uncompressedBlockArray);
+ var uncompressedBlockAlphaArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_A8);
+ var uncompressedBlockAlpha = new Uint8Array(uncompressedBlockAlphaArray);
+
+ for (var blockY = 0; blockY < numBlocksY; blockY++) {
+ for (var blockX = 0; blockX < numBlocksX; blockX++) {
+ var compressedBlockAlpha = get128BitBlockStart(src, blockY * numBlocksX + blockX);
+ var compressedBlockRGB = get128BitBlockEnd(src, blockY * numBlocksX + blockX);
+
+ // Decompress.
+ decompressETC2Block(uncompressedBlock, compressedBlockRGB, null, false);
+ decompressEAC8Block(uncompressedBlockAlpha, compressedBlockAlpha);
+
+ // Write to dst.
+ var baseX = blockX * ETC2_BLOCK_WIDTH;
+ var baseY = blockY * ETC2_BLOCK_HEIGHT;
+ for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
+ for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
+ var srcIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var srcAlphaIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
+ var dstIndex = (baseY + y) * dstRowPitch + (baseX + x) * dstPixelSize;
+
+ for (var i = 0; i < ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1; i++)
+ dstPtr[dstIndex + i] = uncompressedBlock[srcIndex + i];
+ dstPtr[dstIndex + ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1] = uncompressedBlockAlpha[srcAlphaIndex];
+
+ }
+ }
+ }
+ }
+};
+
+var decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src) {
+ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
+ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
+ var dstPtr = new Uint8Array(dst.m_data);
+ var dstRowPitch = dst.getRowPitch();
+ var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
+ var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8);
+ var uncompressedBlock = new Uint8Array(uncompressedBlockArray);
+ var uncompressedBlockAlphaArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_A8);
+ var uncompressedBlockAlpha = new Uint8Array(uncompressedBlockAlphaArray);
+
+ for (var blockY = 0; blockY < numBlocksY; blockY++) {
+ for (var blockX = 0; blockX < numBlocksX; blockX++) {
+ var compressedBlock = get64BitBlock(src, blockY * numBlocksX + blockX);
+
+ // Decompress.
+ decompressETC2Block(uncompressedBlock, compressedBlock, uncompressedBlockAlpha, true);
+
+ // Write to dst.
+ var baseX = blockX * ETC2_BLOCK_WIDTH;
+ var baseY = blockY * ETC2_BLOCK_HEIGHT;
+ for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
+ for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
+ var srcIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
+ var srcAlphaIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
+ var dstIndex = (baseY + y) * dstRowPitch + (baseX + x) * dstPixelSize;
+
+ for (var i = 0; i < ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1; i++)
+ dstPtr[dstIndex + i] = uncompressedBlock[srcIndex + i];
+ dstPtr[dstIndex + ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1] = uncompressedBlockAlpha[srcAlphaIndex];
+
+ }
+ }
+ }
+ }
+};
+
+return {
+ decompressEAC_R11: decompressEAC_R11,
+ decompressEAC_RG11: decompressEAC_RG11,
+ decompressETC2: decompressETC2,
+ decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1: decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1,
+ decompressETC2_EAC_RGBA8: decompressETC2_EAC_RGBA8
+};
+
+}();
+
+/**
+ * @constructor
+ * @param {tcuCompressedTexture.Format} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number=} depth
+ */
+tcuCompressedTexture.CompressedTexture = function(format, width, height, depth) {
+ depth = depth === undefined ? 1 : depth;
+ this.setStorage(format, width, height, depth);
+ /** @type {Uint8Array} */ this.m_data;
+};
+
+/**
+ * @return {number}
+ */
+tcuCompressedTexture.CompressedTexture.prototype.getDataSize = function() {
+ return this.m_data.length;
+};
+
+/**
+ * @return {Uint8Array}
+ */
+tcuCompressedTexture.CompressedTexture.prototype.getData = function() {
+ return this.m_data;
+};
+
+/**
+ * @return {number}
+ */
+tcuCompressedTexture.CompressedTexture.prototype.getWidth = function() {
+ return this.m_width;
+};
+
+/**
+ * @return {number}
+ */
+tcuCompressedTexture.CompressedTexture.prototype.getHeight = function() {
+ return this.m_height;
+};
+
+/**
+ * @return {tcuCompressedTexture.Format}
+ */
+tcuCompressedTexture.CompressedTexture.prototype.getFormat = function() {
+ return this.m_format;
+};
+
+tcuCompressedTexture.CompressedTexture.prototype.setStorage = function(format, width, height, depth) {
+ depth = depth === undefined ? 1 : depth;
+ this.m_format = format;
+ this.m_width = width;
+ this.m_height = height;
+ this.m_depth = depth;
+
+ if (tcuCompressedTexture.isEtcFormat(this.m_format)) {
+ DE_ASSERT(this.m_depth == 1);
+
+ var blockSizeMultiplier = 0; // How many 64-bit parts each compressed block contains.
+
+ switch (this.m_format) {
+ case tcuCompressedTexture.Format.ETC1_RGB8: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.EAC_R11: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.EAC_SIGNED_R11: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.EAC_RG11: blockSizeMultiplier = 2; break;
+ case tcuCompressedTexture.Format.EAC_SIGNED_RG11: blockSizeMultiplier = 2; break;
+ case tcuCompressedTexture.Format.ETC2_RGB8: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.ETC2_SRGB8: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: blockSizeMultiplier = 1; break;
+ case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: blockSizeMultiplier = 2; break;
+ case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: blockSizeMultiplier = 2; break;
+
+ default:
+ throw new Error('Unsupported format ' + format);
+ break;
+ }
+
+ this.m_array = new ArrayBuffer(blockSizeMultiplier * 8 * tcuCompressedTexture.divRoundUp(this.m_width, 4) * tcuCompressedTexture.divRoundUp(this.m_height, 4));
+ this.m_data = new Uint8Array(this.m_array);
+ }
+ // else if (isASTCFormat(this.m_format))
+ // {
+ // if (this.m_depth > 1)
+ // throw tcu::InternalError("3D ASTC textures not currently supported");
+
+ // const IVec3 blockSize = getASTCBlockSize(this.m_format);
+ // this.m_data.resize(ASTC_BLOCK_SIZE_BYTES * tcuCompressedTexture.divRoundUp(this.m_width, blockSize[0]) * tcuCompressedTexture.divRoundUp(this.m_height, blockSize[1]) * tcuCompressedTexture.divRoundUp(this.m_depth, blockSize[2]));
+ // }
+ // else
+ // {
+ // DE_ASSERT(this.m_format == FORMAT_LAST);
+ // DE_ASSERT(this.m_width == 0 && this.m_height == 0 && this.m_depth == 0);
+ // this.m_data.resize(0);
+ // }
+};
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Get uncompressed texture format
+ *//*--------------------------------------------------------------------*/
+tcuCompressedTexture.CompressedTexture.prototype.getUncompressedFormat = function() {
+ if (tcuCompressedTexture.isEtcFormat(this.m_format)) {
+ switch (this.m_format) {
+ case tcuCompressedTexture.Format.ETC1_RGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
+ case tcuCompressedTexture.Format.EAC_R11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNORM_INT16);
+ case tcuCompressedTexture.Format.EAC_SIGNED_R11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SNORM_INT16);
+ case tcuCompressedTexture.Format.EAC_RG11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNORM_INT16);
+ case tcuCompressedTexture.Format.EAC_SIGNED_RG11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT16);
+ case tcuCompressedTexture.Format.ETC2_RGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
+ case tcuCompressedTexture.Format.ETC2_SRGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGB, tcuTexture.ChannelType.UNORM_INT8);
+ case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+ case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
+ case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+ case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
+ default:
+ throw new Error('Unsupported format ' + this.m_format);
+ }
+ }
+ // else if (isASTCFormat(m_format))
+ // {
+ // if (isASTCSRGBFormat(m_format))
+ // return TextureFormat(tcuTexture.ChannelType.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
+ // else
+ // return TextureFormat(tcuTexture.ChannelType.RGBA, tcuTexture.ChannelType.HALF_FLOAT);
+ // }
+ // else
+ // {
+ // DE_ASSERT(false);
+ // return TextureFormat();
+ // }
+};
+
+/**
+ * Decode to uncompressed pixel data
+ * @param {tcuTexture.PixelBufferAccess} dst Destination buffer
+ */
+tcuCompressedTexture.CompressedTexture.prototype.decompress = function(dst) {
+ DE_ASSERT(dst.getWidth() == this.m_width && dst.getHeight() == this.m_height && dst.getDepth() == 1);
+ var format = this.getUncompressedFormat();
+ if (dst.getFormat().order != format.order || dst.getFormat().type != format.type)
+ throw new Error('Formats do not match.');
+
+ if (tcuCompressedTexture.isEtcFormat(this.m_format)) {
+ switch (this.m_format) {
+ // case tcuCompressedTexture.Format.ETC1_RGB8: decompressETC1 (dst, this.m_width, this.m_height, this.m_data); break;
+ case tcuCompressedTexture.Format.EAC_R11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_R11(dst, this.m_width, this.m_height, this.m_array, false); break;
+ case tcuCompressedTexture.Format.EAC_SIGNED_R11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_R11(dst, this.m_width, this.m_height, this.m_array, true); break;
+ case tcuCompressedTexture.Format.EAC_RG11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_RG11(dst, this.m_width, this.m_height, this.m_array, false); break;
+ case tcuCompressedTexture.Format.EAC_SIGNED_RG11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_RG11(dst, this.m_width, this.m_height, this.m_array, true); break;
+ case tcuCompressedTexture.Format.ETC2_RGB8: tcuCompressedTexture.etcDecompressInternal.decompressETC2(dst, this.m_width, this.m_height, this.m_array); break;
+ case tcuCompressedTexture.Format.ETC2_SRGB8: tcuCompressedTexture.etcDecompressInternal.decompressETC2(dst, this.m_width, this.m_height, this.m_array); break;
+ case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: tcuCompressedTexture.etcDecompressInternal.decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(dst, this.m_width, this.m_height, this.m_array); break;
+ case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: tcuCompressedTexture.etcDecompressInternal.decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(dst, this.m_width, this.m_height, this.m_array); break;
+ case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: tcuCompressedTexture.etcDecompressInternal.decompressETC2_EAC_RGBA8(dst, this.m_width, this.m_height, this.m_array); break;
+ case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: tcuCompressedTexture.etcDecompressInternal.decompressETC2_EAC_RGBA8(dst, this.m_width, this.m_height, this.m_array); break;
+
+ default:
+ throw new Error('Unsupported format ' + this.m_format);
+ break;
+ }
+ }
+ // else if (isASTCFormat(m_format))
+ // {
+ // const tcu::IVec3 blockSize = getASTCBlockSize(m_format);
+ // const bool isSRGBFormat = isASTCSRGBFormat(m_format);
+
+ // if (blockSize[2] > 1)
+ // throw tcu::InternalError("3D ASTC textures not currently supported");
+
+ // decompressASTC(dst, m_width, m_height, &m_data[0], blockSize[0], blockSize[1], isSRGBFormat, isSRGBFormat || params.isASTCModeLDR);
+ // } /**/
+ else
+ throw new Error('Unsupported format ' + this.m_format);
+};
+
+ });
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloat.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloat.js
new file mode 100644
index 0000000000..0cc74fe5a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloat.js
@@ -0,0 +1,862 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuFloat');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuFloat = framework.common.tcuFloat;
+var deMath = framework.delibs.debase.deMath;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+tcuFloat.FloatFlags = {
+ FLOAT_HAS_SIGN: (1 << 0),
+ FLOAT_SUPPORT_DENORM: (1 << 1)
+};
+
+/**
+ * Defines a tcuFloat.FloatDescription object, which is an essential part of the tcuFloat.deFloat type.
+ * Holds the information that shapes the tcuFloat.deFloat.
+ * @constructor
+ */
+tcuFloat.FloatDescription = function(exponentBits, mantissaBits, exponentBias, flags) {
+ this.ExponentBits = exponentBits;
+ this.MantissaBits = mantissaBits;
+ this.ExponentBias = exponentBias;
+ this.Flags = flags;
+
+ this.totalBitSize = 1 + this.ExponentBits + this.MantissaBits;
+ this.totalByteSize = Math.floor(this.totalBitSize / 8) + ((this.totalBitSize % 8) > 0 ? 1 : 0);
+};
+
+/**
+ * Builds a zero float of the current binary description.
+ * @param {number} sign
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.FloatDescription.prototype.zero = function(sign) {
+ return tcuFloat.newDeFloatFromParameters(this.zeroNumber(sign), this);
+};
+
+tcuFloat.FloatDescription.prototype.zeroNumber = function(sign) {
+ return deMath.shiftLeft((sign > 0 ? 0 : 1), (this.ExponentBits + this.MantissaBits));
+};
+
+/**
+ * Builds an infinity float representation of the current binary description.
+ * @param {number} sign
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.FloatDescription.prototype.inf = function(sign) {
+ return tcuFloat.newDeFloatFromParameters(this.infNumber(sign), this);
+};
+
+tcuFloat.FloatDescription.prototype.infNumber = function(sign) {
+ return ((sign > 0 ? 0 : 1) << (this.ExponentBits + this.MantissaBits)) |
+ deMath.shiftLeft(((1 << this.ExponentBits) - 1), this.MantissaBits); //Unless using very large exponent types, native shift is safe here, i guess.
+};
+
+/**
+ * Builds a NaN float representation of the current binary description.
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.FloatDescription.prototype.nan = function() {
+ return tcuFloat.newDeFloatFromParameters(this.nanNumber(), this);
+};
+
+tcuFloat.FloatDescription.prototype.nanNumber = function() {
+ return deMath.shiftLeft(1, (this.ExponentBits + this.MantissaBits)) - 1;
+};
+
+/**
+ * Builds a tcuFloat.deFloat number based on the description and the given
+ * sign, exponent and mantissa values.
+ * @param {number} sign
+ * @param {number} exponent
+ * @param {number} mantissa
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.FloatDescription.prototype.construct = function(sign, exponent, mantissa) {
+ // Repurpose this otherwise invalid input as a shorthand notation for zero (no need for caller to care about internal representation)
+ /** @type {boolean} */ var isShorthandZero = exponent == 0 && mantissa == 0;
+
+ // Handles the typical notation for zero (min exponent, mantissa 0). Note that the exponent usually used exponent (-ExponentBias) for zero/subnormals is not used.
+ // Instead zero/subnormals have the (normally implicit) leading mantissa bit set to zero.
+
+ /** @type {boolean} */ var isDenormOrZero = (exponent == 1 - this.ExponentBias) && (deMath.shiftRight(mantissa, this.MantissaBits) == 0);
+ /** @type {number} */ var s = deMath.shiftLeft((sign < 0 ? 1 : 0), (this.ExponentBits + this.MantissaBits));
+ /** @type {number} */ var exp = (isShorthandZero || isDenormOrZero) ? 0 : exponent + this.ExponentBias;
+
+ DE_ASSERT(sign == +1 || sign == -1);
+ DE_ASSERT(isShorthandZero || isDenormOrZero || deMath.shiftRight(mantissa, this.MantissaBits) == 1);
+ DE_ASSERT((exp >> this.ExponentBits) == 0); //Native shift is safe
+
+ return tcuFloat.newDeFloatFromParameters(
+ deMath.binaryOp(
+ deMath.binaryOp(
+ s,
+ deMath.shiftLeft(exp, this.MantissaBits),
+ deMath.BinaryOp.OR
+ ),
+ deMath.binaryOp(
+ mantissa,
+ deMath.shiftLeft(1, this.MantissaBits) - 1,
+ deMath.BinaryOp.AND
+ ),
+ deMath.BinaryOp.OR
+ ),
+ this
+ );
+};
+
+/**
+ * Builds a tcuFloat.deFloat number based on the description and the given
+ * sign, exponent and binary mantissa values.
+ * @param {number} sign
+ * @param {number} exponent
+ * @param {number} mantissaBits The raw binary representation.
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.FloatDescription.prototype.constructBits = function(sign, exponent, mantissaBits) {
+ /** @type {number} */ var signBit = sign < 0 ? 1 : 0;
+ /** @type {number} */ var exponentBits = exponent + this.ExponentBias;
+
+ DE_ASSERT(sign == +1 || sign == -1);
+ DE_ASSERT((exponentBits >> this.ExponentBits) == 0);
+ DE_ASSERT(deMath.shiftRight(mantissaBits, this.MantissaBits) == 0);
+
+ return tcuFloat.newDeFloatFromParameters(
+ deMath.binaryOp(
+ deMath.binaryOp(
+ deMath.shiftLeft(
+ signBit,
+ this.ExponentBits + this.MantissaBits
+ ),
+ deMath.shiftLeft(exponentBits, this.MantissaBits),
+ deMath.BinaryOp.OR
+ ),
+ mantissaBits,
+ deMath.BinaryOp.OR
+ ),
+ this
+ );
+};
+
+/**
+ * Converts a tcuFloat.deFloat from it's own format description into the format described
+ * by this description.
+ * @param {tcuFloat.deFloat} other Other float to convert to this format description.
+ * @return {tcuFloat.deFloat} converted tcuFloat.deFloat
+ */
+tcuFloat.FloatDescription.prototype.convert = function(other) {
+ /** @type {number} */ var otherExponentBits = other.description.ExponentBits;
+ /** @type {number} */ var otherMantissaBits = other.description.MantissaBits;
+ /** @type {number} */ var otherExponentBias = other.description.ExponentBias;
+ /** @type {number} */ var otherFlags = other.description.Flags;
+
+ /** @type {number} */ var bitDiff;
+ /** @type {number} */ var half;
+ /** @type {number} */ var bias;
+
+ if (!(this.Flags & tcuFloat.FloatFlags.FLOAT_HAS_SIGN) && other.sign() < 0) {
+ // Negative number, truncate to zero.
+ return this.zero(+1);
+ } else if (other.isInf()) {
+ return this.inf(other.sign());
+ } else if (other.isNaN()) {
+ return this.nan();
+ } else if (other.isZero()) {
+ return this.zero(other.sign());
+ } else {
+ /** @type {number} */ var eMin = 1 - this.ExponentBias;
+ /** @type {number} */ var eMax = ((1 << this.ExponentBits) - 2) - this.ExponentBias;
+
+ /** @type {number} */ var s = deMath.shiftLeft(other.signBit(), (this.ExponentBits + this.MantissaBits)); // \note Not sign, but sign bit.
+ /** @type {number} */ var e = other.exponent();
+ /** @type {number} */ var m = other.mantissa();
+
+ // Normalize denormalized values prior to conversion.
+ while (!deMath.binaryOp(m, deMath.shiftLeft(1, otherMantissaBits), deMath.BinaryOp.AND)) {
+ m = deMath.shiftLeft(m, 1);
+ e -= 1;
+ }
+
+ if (e < eMin) {
+ // Underflow.
+ if ((this.Flags & tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= this.MantissaBits)) {
+ // Shift and round (RTE).
+ bitDiff = (otherMantissaBits - this.MantissaBits) + (eMin - e);
+ half = deMath.shiftLeft(1, (bitDiff - 1)) - 1;
+ bias = deMath.binaryOp(deMath.shiftRight(m, bitDiff), 1, deMath.BinaryOp.AND);
+
+ return tcuFloat.newDeFloatFromParameters(
+ deMath.binaryOp(
+ s,
+ deMath.shiftRight(
+ m + half + bias,
+ bitDiff
+ ),
+ deMath.BinaryOp.OR
+ ),
+ this
+ );
+ } else
+ return this.zero(other.sign());
+ } else {
+ // Remove leading 1.
+ m = deMath.binaryOp(m, deMath.binaryNot(deMath.shiftLeft(1, otherMantissaBits)), deMath.BinaryOp.AND);
+
+ if (this.MantissaBits < otherMantissaBits) {
+ // Round mantissa (round to nearest even).
+ bitDiff = otherMantissaBits - this.MantissaBits;
+ half = deMath.shiftLeft(1, (bitDiff - 1)) - 1;
+ bias = deMath.binaryOp(deMath.shiftRight(m, bitDiff), 1, deMath.BinaryOp.AND);
+
+ m = deMath.shiftRight(m + half + bias, bitDiff);
+
+ if (deMath.binaryOp(m, deMath.shiftLeft(1, this.MantissaBits), deMath.BinaryOp.AND)) {
+ // Overflow in mantissa.
+ m = 0;
+ e += 1;
+ }
+ } else {
+ bitDiff = this.MantissaBits - otherMantissaBits;
+ m = deMath.shiftLeft(m, bitDiff);
+ }
+
+ if (e > eMax) {
+ // Overflow.
+ return this.inf(other.sign());
+ } else {
+ DE_ASSERT(deMath.deInRange32(e, eMin, eMax));
+ DE_ASSERT(deMath.binaryOp((e + this.ExponentBias), deMath.binaryNot(deMath.shiftLeft(1, this.ExponentBits) - 1), deMath.BinaryOp.AND) == 0);
+ DE_ASSERT(deMath.binaryOp(m, deMath.binaryNot(deMath.shiftLeft(1, this.MantissaBits) - 1), deMath.BinaryOp.AND) == 0);
+
+ return tcuFloat.newDeFloatFromParameters(
+ deMath.binaryOp(
+ deMath.binaryOp(
+ s,
+ deMath.shiftLeft(
+ e + this.ExponentBias,
+ this.MantissaBits
+ ),
+ deMath.BinaryOp.OR
+ ),
+ m,
+ deMath.BinaryOp.OR
+ ),
+ this
+ );
+ }
+ }
+ }
+};
+
+/**
+ * tcuFloat.deFloat class - Empty constructor, builds a 32 bit float by default
+ * @constructor
+ */
+tcuFloat.deFloat = function() {
+ this.description = tcuFloat.description32;
+
+ this.m_buffer = null;
+ this.m_array = null;
+ this.m_array32 = null;
+ this.bitValue = undefined;
+ this.signValue = undefined;
+ this.expValue = undefined;
+ this.mantissaValue = undefined;
+
+ this.m_value = 0;
+};
+
+/**
+ * buffer - Get the deFloat's existing ArrayBuffer or create one if none exists.
+ * @return {ArrayBuffer}
+ */
+tcuFloat.deFloat.prototype.buffer = function() {
+ if (!this.m_buffer)
+ this.m_buffer = new ArrayBuffer(this.description.totalByteSize);
+ return this.m_buffer;
+};
+
+/**
+ * array - Get the deFloat's existing Uint8Array or create one if none exists.
+ * @return {Uint8Array}
+ */
+tcuFloat.deFloat.prototype.array = function() {
+ if (!this.m_array)
+ this.m_array = new Uint8Array(this.buffer());
+ return this.m_array;
+};
+
+/**
+ * array32 - Get the deFloat's existing Uint32Array or create one if none exists.
+ * @return {Uint32Array}
+ */
+tcuFloat.deFloat.prototype.array32 = function() {
+ if (!this.m_array32)
+ this.m_array32 = new Uint32Array(this.buffer());
+ return this.m_array32;
+};
+
+/**
+ * deFloatNumber - To be used immediately after constructor
+ * Builds a 32-bit tcuFloat.deFloat based on a 64-bit JS number.
+ * @param {number} jsnumber
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.deFloatNumber = function(jsnumber) {
+ var view32 = new DataView(this.buffer());
+ view32.setFloat32(0, jsnumber, true); //little-endian
+ this.m_value = view32.getFloat32(0, true); //little-endian
+
+ // Clear cached values
+ this.bitValue = undefined;
+ this.signValue = undefined;
+ this.expValue = undefined;
+ this.mantissaValue = undefined;
+
+ return this;
+};
+
+/**
+ * deFloatNumber64 - To be used immediately after constructor
+ * Builds a 64-bit tcuFloat.deFloat based on a 64-bit JS number.
+ * @param {number} jsnumber
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.deFloatNumber64 = function(jsnumber) {
+ var view64 = new DataView(this.buffer());
+ view64.setFloat64(0, jsnumber, true); //little-endian
+ this.m_value = view64.getFloat64(0, true); //little-endian
+
+ // Clear cached values
+ this.bitValue = undefined;
+ this.signValue = undefined;
+ this.expValue = undefined;
+ this.mantissaValue = undefined;
+
+ return this;
+};
+
+/**
+ * Convenience function to build a 32-bit tcuFloat.deFloat based on a 64-bit JS number
+ * Builds a 32-bit tcuFloat.deFloat based on a 64-bit JS number.
+ * @param {number} jsnumber
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newDeFloatFromNumber = function(jsnumber) {
+ return new tcuFloat.deFloat().deFloatNumber(jsnumber);
+};
+
+/**
+ * deFloatBuffer - To be used immediately after constructor
+ * Builds a tcuFloat.deFloat based on a buffer and a format description.
+ * The buffer is assumed to contain data of the given description.
+ * @param {ArrayBuffer} buffer
+ * @param {tcuFloat.FloatDescription} description
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.deFloatBuffer = function(buffer, description) {
+ this.m_buffer = buffer;
+ this.m_array = new Uint8Array(this.m_buffer);
+ this.m_array32 = new Uint32Array(this.m_buffer);
+
+ this.m_value = deMath.arrayToNumber(this.m_array);
+
+ // Clear cached values
+ this.bitValue = undefined;
+ this.signValue = undefined;
+ this.expValue = undefined;
+ this.mantissaValue = undefined;
+
+ return this;
+};
+
+/**
+ * Convenience function to build a tcuFloat.deFloat based on a buffer and a format description
+ * The buffer is assumed to contain data of the given description.
+ * @param {ArrayBuffer} buffer
+ * @param {tcuFloat.FloatDescription} description
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newDeFloatFromBuffer = function(buffer, description) {
+ return new tcuFloat.deFloat().deFloatBuffer(buffer, description);
+};
+
+/**
+ * Set the tcuFloat.deFloat from the given bitwise representation.
+ *
+ * @param {number} jsnumber This is taken to be the bitwise representation of
+ * the floating point number represented by this deFloat. It must be an
+ * integer, less than 2^52, and compatible with the existing description.
+ * @return {tcuFloat.deFloat}
+ **/
+tcuFloat.deFloat.prototype.deFloatParametersNumber = function(jsnumber) {
+ /** @type {number} */ var jsnumberMax = -1 >>> (32 - this.description.totalBitSize);
+ DE_ASSERT(Number.isInteger(jsnumber) && jsnumber <= jsnumberMax);
+
+ this.m_value = jsnumber;
+ deMath.numberToArray(this.m_array, jsnumber);
+
+ // Clear cached values
+ this.bitValue = undefined;
+ this.signValue = undefined;
+ this.expValue = undefined;
+ this.mantissaValue = undefined;
+
+ return this;
+};
+
+/**
+ * Initializes a tcuFloat.deFloat from the given bitwise representation,
+ * with the specified format description.
+ *
+ * @param {number} jsnumber This is taken to be the bitwise representation of
+ * the floating point number represented by this deFloat. It must be an
+ * integer, less than 2^52, and compatible with the new description.
+ * @param {tcuFloat.FloatDescription} description
+ * @return {tcuFloat.deFloat}
+ **/
+tcuFloat.deFloat.prototype.deFloatParameters = function(jsnumber, description) {
+ /** @type {number} */ var maxUint52 = 0x10000000000000;
+ DE_ASSERT(Number.isInteger(jsnumber) && jsnumber < maxUint52);
+ if (description.totalBitSize > 52) {
+ // The jsnumber representation for this number can't possibly be valid.
+ // Make sure it has a sentinel 0 value.
+ DE_ASSERT(jsnumber === 0);
+ }
+
+ this.description = description;
+
+ this.m_buffer = new ArrayBuffer(this.description.totalByteSize);
+ this.m_array = new Uint8Array(this.m_buffer);
+
+ return this.deFloatParametersNumber(jsnumber);
+};
+
+/**
+ * Convenience function. Creates a tcuFloat.deFloat, then initializes it from
+ * the given bitwise representation, with the specified format description.
+ *
+ * @param {number} jsnumber This is taken to be the bitwise representation of
+ * the floating point number represented by this deFloat. It must be an
+ * integer, less than 2^52, and compatible with the new description.
+ * @param {tcuFloat.FloatDescription} description
+ * @return {tcuFloat.deFloat}
+ **/
+tcuFloat.newDeFloatFromParameters = function(jsnumber, description) {
+ return new tcuFloat.deFloat().deFloatParameters(jsnumber, description);
+};
+
+/**
+ * Returns bit range [begin, end)
+ * @param {number} begin
+ * @param {number} end
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.getBitRange = function(begin, end) {
+ if (this.description.totalBitSize <= 52) {
+ // this.bits() is invalid for more than 52 bits.
+ return deMath.getBitRange(this.bits(), begin, end);
+ } else {
+ return deMath.getArray32BitRange(this.array32(), begin, end);
+ }
+};
+
+/**
+ * Returns the raw binary representation value of the tcuFloat.deFloat
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.bits = function() {
+ if (typeof this.bitValue === 'undefined')
+ this.bitValue = deMath.arrayToNumber(this.array());
+ return this.bitValue;
+};
+
+/**
+ * Returns the raw binary sign bit
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.signBit = function() {
+ if (typeof this.signValue === 'undefined')
+ this.signValue = this.getBitRange(this.description.totalBitSize - 1, this.description.totalBitSize);
+ return this.signValue;
+};
+
+/**
+ * Returns the raw binary exponent bits
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.exponentBits = function() {
+ if (typeof this.expValue === 'undefined')
+ this.expValue = this.getBitRange(this.description.MantissaBits, this.description.MantissaBits + this.description.ExponentBits);
+ return this.expValue;
+};
+
+/**
+ * Returns the raw binary mantissa bits
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.mantissaBits = function() {
+ if (typeof this.mantissaValue === 'undefined')
+ this.mantissaValue = this.getBitRange(0, this.description.MantissaBits);
+ return this.mantissaValue;
+};
+
+/**
+ * Returns the sign as a factor (-1 or 1)
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.sign = function() {
+ var sign = this.signBit();
+ var signvalue = sign ? -1 : 1;
+ return signvalue;
+};
+
+/**
+ * Returns the real exponent, checking if it's a denorm or zero number or not
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.exponent = function() {return this.isDenorm() ? 1 - this.description.ExponentBias : this.exponentBits() - this.description.ExponentBias;};
+
+/**
+ * Returns the (still raw) mantissa, checking if it's a denorm or zero number or not
+ * Makes the normally implicit bit explicit.
+ * @return {number}
+ */
+tcuFloat.deFloat.prototype.mantissa = function() {return this.isZero() || this.isDenorm() ? this.mantissaBits() : deMath.binaryOp(this.mantissaBits(), deMath.shiftLeft(1, this.description.MantissaBits), deMath.BinaryOp.OR);};
+
+/**
+ * Returns if the number is infinity or not.
+ * @return {boolean}
+ */
+tcuFloat.deFloat.prototype.isInf = function() {return this.exponentBits() == ((1 << this.description.ExponentBits) - 1) && this.mantissaBits() == 0;};
+
+/**
+ * Returns if the number is NaN or not.
+ * @return {boolean}
+ */
+tcuFloat.deFloat.prototype.isNaN = function() {return this.exponentBits() == ((1 << this.description.ExponentBits) - 1) && this.mantissaBits() != 0;};
+
+/**
+ * Returns if the number is zero or not.
+ * @return {boolean}
+ */
+tcuFloat.deFloat.prototype.isZero = function() {return this.exponentBits() == 0 && this.mantissaBits() == 0;};
+
+/**
+ * Returns if the number is denormalized or not.
+ * @return {boolean}
+ */
+tcuFloat.deFloat.prototype.isDenorm = function() {return this.exponentBits() == 0 && this.mantissaBits() != 0;};
+
+/**
+ * Builds a zero float of the current binary description.
+ * @param {number} sign
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.zero = function(sign) {
+ return this.description.zero(sign);
+};
+
+/**
+ * Builds an infinity float representation of the current binary description.
+ * @param {number} sign
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.inf = function(sign) {
+ return this.description.inf(sign);
+};
+
+/**
+ * Builds a NaN float representation of the current binary description.
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.nan = function() {
+ return this.description.nan();
+};
+
+/**
+ * Builds a float of the current binary description.
+ * Given a sign, exponent and mantissa.
+ * @param {number} sign
+ * @param {number} exponent
+ * @param {number} mantissa
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.construct = function(sign, exponent, mantissa) {
+ return this.description.construct(sign, exponent, mantissa);
+};
+
+/**
+ * Builds a float of the current binary description.
+ * Given a sign, exponent and a raw binary mantissa.
+ * @param {number} sign
+ * @param {number} exponent
+ * @param {number} mantissaBits Raw binary mantissa.
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.deFloat.prototype.constructBits = function(sign, exponent, mantissaBits) {
+ return this.description.constructBits(sign, exponent, mantissaBits);
+};
+
+/**
+ * Calculates the JS float number from the internal representation.
+ * @return {number} The JS float value represented by this tcuFloat.deFloat.
+ */
+tcuFloat.deFloat.prototype.getValue = function() {
+ if ((this.description.Flags | tcuFloat.FloatFlags.FLOAT_HAS_SIGN) === 0 && this.sign() < 0)
+ return 0;
+ if (this.isInf())
+ return Number.Infinity;
+ if (this.isNaN())
+ return Number.NaN;
+ if (this.isZero())
+ return this.sign() * 0;
+ /**@type {number} */ var mymantissa = this.mantissa();
+ /**@type {number} */ var myexponent = this.exponent();
+ /**@type {number} */ var sign = this.sign();
+
+ /**@type {number} */ var value = mymantissa / Math.pow(2, this.description.MantissaBits) * Math.pow(2, myexponent);
+
+ if (this.description.Flags | tcuFloat.FloatFlags.FLOAT_HAS_SIGN != 0)
+ value = value * sign;
+
+ return value;
+};
+
+tcuFloat.description10 = new tcuFloat.FloatDescription(5, 5, 15, 0);
+tcuFloat.description11 = new tcuFloat.FloatDescription(5, 6, 15, 0);
+tcuFloat.description16 = new tcuFloat.FloatDescription(5, 10, 15, tcuFloat.FloatFlags.FLOAT_HAS_SIGN);
+tcuFloat.description32 = new tcuFloat.FloatDescription(8, 23, 127, tcuFloat.FloatFlags.FLOAT_HAS_SIGN | tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM);
+tcuFloat.description64 = new tcuFloat.FloatDescription(11, 52, 1023, tcuFloat.FloatFlags.FLOAT_HAS_SIGN | tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM);
+
+tcuFloat.convertFloat32Inline = (function() {
+ var float32View = new Float32Array(1);
+ var int32View = new Int32Array(float32View.buffer);
+
+ return function(fval, description) {
+ float32View[0] = fval;
+ var fbits = int32View[0];
+
+ var exponentBits = (fbits >> 23) & 0xff;
+ var mantissaBits = fbits & 0x7fffff;
+ var signBit = (fbits & 0x80000000) ? 1 : 0;
+ var sign = signBit ? -1 : 1;
+
+ var isZero = exponentBits == 0 && mantissaBits == 0;
+
+ var bitDiff;
+ var half;
+ var bias;
+
+ if (!(description.Flags & tcuFloat.FloatFlags.FLOAT_HAS_SIGN) && sign < 0) {
+ // Negative number, truncate to zero.
+ return description.zeroNumber(+1);
+ } else if (exponentBits == ((1 << tcuFloat.description32.ExponentBits) - 1) && mantissaBits == 0) { // isInf
+ return description.infNumber(sign);
+ } else if (exponentBits == ((1 << tcuFloat.description32.ExponentBits) - 1) && mantissaBits != 0) { // isNaN
+ return description.nanNumber();
+ } else if (isZero) {
+ return description.zeroNumber(sign);
+ } else {
+ var eMin = 1 - description.ExponentBias;
+ var eMax = ((1 << description.ExponentBits) - 2) - description.ExponentBias;
+
+ var isDenorm = exponentBits == 0 && mantissaBits != 0;
+
+ var s = signBit << (description.ExponentBits + description.MantissaBits); // \note Not sign, but sign bit.
+ var e = isDenorm ? 1 - tcuFloat.description32.ExponentBias : exponentBits - tcuFloat.description32.ExponentBias;// other.exponent();
+ var m = isZero || isDenorm ? mantissaBits : mantissaBits | (1 << tcuFloat.description32.MantissaBits); // other.mantissa();
+
+ // Normalize denormalized values prior to conversion.
+ while (!(m & (1 << tcuFloat.description32.MantissaBits))) {
+ m = deMath.shiftLeft(m, 1);
+ e -= 1;
+ }
+
+ if (e < eMin) {
+ // Underflow.
+ if ((description.Flags & tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= description.MantissaBits)) {
+ // Shift and round (RTE).
+ bitDiff = (tcuFloat.description32.MantissaBits - description.MantissaBits) + (eMin - e);
+ half = (1 << (bitDiff - 1)) - 1;
+ bias = ((m >> bitDiff) & 1);
+ return (s | ((m + half + bias) >> bitDiff));
+ } else
+ return description.zeroNumber(sign);
+ } else {
+ // Remove leading 1.
+ m = (m & ~(1 << tcuFloat.description32.MantissaBits));
+
+ if (description.MantissaBits < tcuFloat.description32.MantissaBits) {
+ // Round mantissa (round to nearest even).
+ bitDiff = tcuFloat.description32.MantissaBits - description.MantissaBits;
+ half = (1 << (bitDiff - 1)) - 1;
+ bias = ((m >> bitDiff) & 1);
+
+ m = (m + half + bias) >> bitDiff;
+
+ if ((m & (1 << description.MantissaBits))) {
+ // Overflow in mantissa.
+ m = 0;
+ e += 1;
+ }
+ } else {
+ bitDiff = description.MantissaBits - tcuFloat.description32.MantissaBits;
+ m = (m << bitDiff);
+ }
+
+ if (e > eMax) {
+ // Overflow.
+ return description.infNumber(sign);
+ } else {
+ DE_ASSERT(deMath.deInRange32(e, eMin, eMax));
+ DE_ASSERT(((e + description.ExponentBias) & ~((1 << description.ExponentBits) - 1)) == 0);
+ DE_ASSERT((m & ~((1 << description.MantissaBits) - 1)) == 0);
+
+ return (s | ((e + description.ExponentBias) << description.MantissaBits)) | m;
+ }
+ }
+ }
+ };
+})();
+
+/**
+ * Builds a 10 bit tcuFloat.deFloat
+ * @param {number} value (64-bit JS float)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat10 = function(value) {
+ DE_ASSERT(Number.isInteger(value) && value <= 0x3ff);
+ /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
+ return tcuFloat.description10.convert(other32);
+};
+
+/**
+ * Builds a 11 bit tcuFloat.deFloat
+ * @param {number} value (64-bit JS float)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat11 = function(value) {
+ /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
+ return tcuFloat.description11.convert(other32);
+};
+
+/**
+ * Builds a 16 bit tcuFloat.deFloat
+ * @param {number} value (64-bit JS float)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat16 = function(value) {
+ /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
+ return tcuFloat.description16.convert(other32);
+};
+
+/**
+ * Builds a 16 bit tcuFloat.deFloat from raw bits
+ * @param {number} value (16-bit value)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat32From16 = function(value) {
+ var other16 = tcuFloat.newDeFloatFromParameters(value, tcuFloat.description16);
+ return tcuFloat.description32.convert(other16);
+};
+
+/**
+ * Builds a 16 bit tcuFloat.deFloat with no denorm support
+ * @param {number} value (64-bit JS float)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat16NoDenorm = function(value) {
+ /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
+ return tcuFloat.description16.convert(other32);
+};
+
+/**
+ * Builds a 32 bit tcuFloat.deFloat
+ * @param {number} value (64-bit JS float)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat32 = function(value) {
+ return new tcuFloat.deFloat().deFloatNumber(value);
+};
+
+tcuFloat.numberToFloat11 = function(value) {
+ return tcuFloat.convertFloat32Inline(value, tcuFloat.description11);
+};
+
+tcuFloat.float11ToNumber = (function() {
+ var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description11);
+ return function(float11) {
+ x.deFloatParametersNumber(float11);
+ return x.getValue();
+ };
+})();
+
+tcuFloat.numberToFloat10 = function(value) {
+ return tcuFloat.convertFloat32Inline(value, tcuFloat.description10);
+};
+
+tcuFloat.float10ToNumber = (function() {
+ var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description10);
+ return function(float10) {
+ x.deFloatParametersNumber(float10);
+ return x.getValue();
+ };
+})();
+
+tcuFloat.numberToHalfFloat = function(value) {
+ return tcuFloat.convertFloat32Inline(value, tcuFloat.description16);
+};
+
+tcuFloat.numberToHalfFloatNoDenorm = function(value) {
+ return tcuFloat.newFloat16NoDenorm(value).bits();
+};
+
+tcuFloat.halfFloatToNumber = (function() {
+ var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description16);
+ return function(half) {
+ x.deFloatParametersNumber(half);
+ return x.getValue();
+ };
+})();
+
+tcuFloat.halfFloatToNumberNoDenorm = tcuFloat.halfFloatToNumber;
+
+/**
+ * Builds a 64 bit tcuFloat.deFloat
+ * @param {number} value (64-bit JS float)
+ * @return {tcuFloat.deFloat}
+ */
+tcuFloat.newFloat64 = function(value) {
+ return new tcuFloat.deFloat().deFloatParameters(0, tcuFloat.description64)
+ .deFloatNumber64(value);
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js
new file mode 100644
index 0000000000..a0b4dc82cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js
@@ -0,0 +1,349 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Adjustable-precision floating point operations.
+ *//*--------------------------------------------------------------------*/
+ 'use strict';
+ goog.provide('framework.common.tcuFloatFormat');
+
+ goog.require('framework.common.tcuInterval');
+goog.require('framework.delibs.debase.deMath');
+
+ goog.scope(function() {
+
+ var tcuFloatFormat = framework.common.tcuFloatFormat;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuInterval = framework.common.tcuInterval;
+
+ /**
+ * @param {tcuFloatFormat.YesNoMaybe} choice
+ * @param {tcuInterval.Interval} no
+ * @param {tcuInterval.Interval} yes
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.chooseInterval = function(choice, no, yes) {
+ switch (choice) {
+ case tcuFloatFormat.YesNoMaybe.NO: return no;
+ case tcuFloatFormat.YesNoMaybe.YES: return yes;
+ case tcuFloatFormat.YesNoMaybe.MAYBE: return no.operatorOrBinary(yes);
+ default: throw new Error('Impossible case');
+ }
+ };
+
+ /**
+ * @param {number} maxExp
+ * @param {number} fractionBits
+ * @return {number}
+ */
+ tcuFloatFormat.computeMaxValue = function(maxExp, fractionBits) {
+ return deMath.deLdExp(1, maxExp) + deMath.deLdExp(Math.pow(2, fractionBits) - 1, maxExp - fractionBits);
+ };
+
+ /**
+ * @enum {number}
+ */
+ tcuFloatFormat.YesNoMaybe = {
+ NO: 0,
+ MAYBE: 1,
+ YES: 2
+ };
+
+ /**
+ * @constructor
+ * @param {number} minExp
+ * @param {number} maxExp
+ * @param {number} fractionBits
+ * @param {boolean} exactPrecision
+ * @param {tcuFloatFormat.YesNoMaybe=} hasSubnormal
+ * @param {tcuFloatFormat.YesNoMaybe=} hasInf
+ * @param {tcuFloatFormat.YesNoMaybe=} hasNaN
+ */
+ tcuFloatFormat.FloatFormat = function(minExp, maxExp, fractionBits, exactPrecision, hasSubnormal, hasInf, hasNaN) {
+ // /** @type{number} */ var exponentShift (int exp) const;
+ // Interval clampValue (double d) const;
+
+ /** @type {number} */ this.m_minExp = minExp; // Minimum exponent, inclusive
+ /** @type {number} */ this.m_maxExp = maxExp; // Maximum exponent, inclusive
+ /** @type {number} */ this.m_fractionBits = fractionBits; // Number of fractional bits in significand
+ /** @type {tcuFloatFormat.YesNoMaybe} */ this.m_hasSubnormal = hasSubnormal === undefined ? tcuFloatFormat.YesNoMaybe.MAYBE : hasSubnormal; // Does the format support denormalized numbers?
+ /** @type {tcuFloatFormat.YesNoMaybe} */ this.m_hasInf = hasInf === undefined ? tcuFloatFormat.YesNoMaybe.MAYBE : hasInf; // Does the format support infinities?
+ /** @type {tcuFloatFormat.YesNoMaybe} */ this.m_hasNaN = hasNaN === undefined ? tcuFloatFormat.YesNoMaybe.MAYBE : hasNaN; // Does the format support NaNs?
+ /** @type {boolean} */ this.m_exactPrecision = exactPrecision; // Are larger precisions disallowed?
+ /** @type {number} */ this.m_maxValue = tcuFloatFormat.computeMaxValue(maxExp, fractionBits);
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getMinExp = function() {
+ return this.m_minExp;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getMaxExp = function() {
+ return this.m_maxExp;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getMaxValue = function() {
+ return this.m_maxValue;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getFractionBits = function() {
+ return this.m_fractionBits;
+ };
+
+ /**
+ * @return {tcuFloatFormat.YesNoMaybe}
+ */
+ tcuFloatFormat.FloatFormat.prototype.hasSubnormal = function() {
+ return this.m_hasSubnormal;
+ };
+
+ /**
+ * @return {tcuFloatFormat.YesNoMaybe}
+ */
+ tcuFloatFormat.FloatFormat.prototype.hasInf = function() {
+ return this.m_hasInf;
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} count
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.ulp = function(x, count) {
+ var breakdown = deMath.deFractExp(Math.abs(x));
+ /** @type {number} */ var exp = breakdown.exponent;
+ /** @type {number} */ var frac = breakdown.significand;
+
+ if (isNaN(frac))
+ return NaN;
+ else if (!isFinite(frac))
+ return deMath.deLdExp(1.0, this.m_maxExp - this.m_fractionBits);
+ else if (frac == 1.0) {
+ // Harrison's ULP: choose distance to closest (i.e. next lower) at binade
+ // boundary.
+ --exp;
+ } else if (frac == 0.0)
+ exp = this.m_minExp;
+
+ // ULP cannot be lower than the smallest quantum.
+ exp = Math.max(exp, this.m_minExp);
+
+ /** @type {number} */ var oneULP = deMath.deLdExp(1.0, exp - this.m_fractionBits);
+ // ScopedRoundingMode ctx (DE_ROUNDINGMODE_TO_POSITIVE_INF);
+
+ return oneULP * count;
+ };
+
+ /**
+ * Return the difference between the given nominal exponent and
+ * the exponent of the lowest significand bit of the
+ * representation of a number with this format.
+ * For normal numbers this is the number of significand bits, but
+ * for subnormals it is less and for values of exp where 2^exp is too
+ * small to represent it is <0
+ * @param {number} exp
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.exponentShift = function(exp) {
+ return this.m_fractionBits - Math.max(this.m_minExp - exp, 0);
+ };
+
+ /**
+ * @param {number} d
+ * @param {boolean} upward
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.round = function(d, upward) {
+ var breakdown = deMath.deFractExp(d);
+ /** @type {number} */ var exp = breakdown.exponent;
+ /** @type {number} */ var frac = breakdown.significand;
+
+ var shift = this.exponentShift(exp);
+ var shiftFrac = deMath.deLdExp(frac, shift);
+ var roundFrac = upward ? Math.ceil(shiftFrac) : Math.floor(shiftFrac);
+
+ return deMath.deLdExp(roundFrac, exp - shift);
+ };
+
+ /**
+ * Return the range of numbers that `d` might be converted to in the
+ * floatformat, given its limitations with infinities, subnormals and maximum
+ * exponent.
+ * @param {number} d
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.FloatFormat.prototype.clampValue = function(d) {
+ /** @type {number} */ var rSign = deMath.deSign(d);
+ /** @type {number} */ var rExp = 0;
+
+ // DE_ASSERT(!isNaN(d));
+
+ var breakdown = deMath.deFractExp(d);
+ rExp = breakdown.exponent;
+ if (rExp < this.m_minExp)
+ return tcuFloatFormat.chooseInterval(this.m_hasSubnormal, new tcuInterval.Interval(rSign * 0.0), new tcuInterval.Interval(d));
+ else if (!isFinite(d) || rExp > this.m_maxExp)
+ return tcuFloatFormat.chooseInterval(this.m_hasInf, new tcuInterval.Interval(rSign * this.getMaxValue()), new tcuInterval.Interval(rSign * Number.POSITIVE_INFINITY));
+
+ return new tcuInterval.Interval(d);
+ };
+
+ /**
+ * @param {number} d
+ * @param {boolean} upward
+ * @param {boolean} roundUnderOverflow
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.roundOutDir = function(d, upward, roundUnderOverflow) {
+ var breakdown = deMath.deFractExp(d);
+ var exp = breakdown.exponent;
+
+ if (roundUnderOverflow && exp > this.m_maxExp && (upward == (d < 0.0)))
+ return deMath.deSign(d) * this.getMaxValue();
+ else
+ return this.round(d, upward);
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @param {boolean} roundUnderOverflow
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.FloatFormat.prototype.roundOut = function(x, roundUnderOverflow) {
+ /** @type {tcuInterval.Interval} */ var ret = x.nan();
+
+ if (!x.empty()) {
+ var a = new tcuInterval.Interval(this.roundOutDir(x.lo(), false, roundUnderOverflow));
+ var b = new tcuInterval.Interval(this.roundOutDir(x.hi(), true, roundUnderOverflow));
+ ret.operatorOrAssignBinary(tcuInterval.withIntervals(a, b));
+ }
+ return ret;
+ };
+
+ //! Return the range of numbers that might be used with this format to
+ //! represent a number within `x`.
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.FloatFormat.prototype.convert = function(x) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+ /** @type {tcuInterval.Interval} */ var tmp = x;
+
+ if (x.hasNaN()) {
+ // If NaN might be supported, NaN is a legal return value
+ if (this.m_hasNaN != tcuFloatFormat.YesNoMaybe.NO)
+ ret.operatorOrAssignBinary(new tcuInterval.Interval(NaN));
+
+ // If NaN might not be supported, any (non-NaN) value is legal,
+ // _subject_ to clamping. Hence we modify tmp, not ret.
+ if (this.m_hasNaN != tcuFloatFormat.YesNoMaybe.YES)
+ tmp = tcuInterval.unbounded();
+ }
+
+ // Round both bounds _inwards_ to closest representable values.
+ if (!tmp.empty())
+ ret.operatorOrAssignBinary(
+ this.clampValue(this.round(tmp.lo(), true)).operatorOrBinary(
+ this.clampValue(this.round(tmp.hi(), false))));
+
+ // If this format's precision is not exact, the (possibly out-of-bounds)
+ // original value is also a possible result.
+ if (!this.m_exactPrecision)
+ ret.operatorOrAssignBinary(x);
+
+ return ret;
+ };
+
+ /**
+ * @param {number} x
+ * @return {string}
+ */
+ tcuFloatFormat.FloatFormat.prototype.floatToHex = function(x) {
+ if (isNaN(x))
+ return 'NaN';
+ else if (!isFinite(x))
+ return (x < 0.0 ? '-' : '+') + ('inf');
+ else if (x == 0.0) // \todo [2014-03-27 lauri] Negative zero
+ return '0.0';
+
+ return x.toString(10);
+ // TODO
+ // var breakdown = deMath.deFractExp(deAbs(x));
+ // /** @type{number} */ var exp = breakdown.exponent;
+ // /** @type{number} */ var frac = breakdown.significand;
+ // /** @type{number} */ var shift = this.exponentShift(exp);
+ // /** @type{number} */ var bits = deUint64(deLdExp(frac, shift));
+ // /** @type{number} */ var whole = bits >> m_fractionBits;
+ // /** @type{number} */ var fraction = bits & ((deUint64(1) << m_fractionBits) - 1);
+ // /** @type{number} */ var exponent = exp + m_fractionBits - shift;
+ // /** @type{number} */ var numDigits = (this.m_fractionBits + 3) / 4;
+ // /** @type{number} */ var aligned = fraction << (numDigits * 4 - m_fractionBits);
+ // /** @type{string} */ var oss = '';
+
+ // oss + (x < 0 ? '-' : '')
+ // + '0x' + whole + '.'
+ // + std::hex + std::setw(numDigits) + std::setfill('0') + aligned
+ // + 'p' + std::dec + std::setw(0) + exponent;
+ //return oss;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} interval
+ * @return {string}
+ */
+ tcuFloatFormat.FloatFormat.prototype.intervalToHex = function(interval) {
+ if (interval.empty())
+ return interval.hasNaN() ? '{ NaN }' : '{}';
+
+ else if (interval.lo() == interval.hi())
+ return ((interval.hasNaN() ? '{ NaN, ' : '{ ') +
+ this.floatToHex(interval.lo()) + ' }');
+ else if (interval == tcuInterval.unbounded(true))
+ return '<any>';
+
+ return ((interval.hasNaN() ? '{ NaN } | ' : '') +
+ '[' + this.floatToHex(interval.lo()) + ', ' + this.floatToHex(interval.hi()) + ']');
+ };
+
+ /**
+ * @return {tcuFloatFormat.FloatFormat}
+ */
+ tcuFloatFormat.nativeDouble = function() {
+ return new tcuFloatFormat.FloatFormat(-1021 - 1, // min_exponent
+ 1024 - 1, // max_exponent
+ 53 - 1, // digits
+ true, // has_denorm
+ tcuFloatFormat.YesNoMaybe.YES, // has_infinity
+ tcuFloatFormat.YesNoMaybe.YES, // has_quiet_nan
+ tcuFloatFormat.YesNoMaybe.YES); // has_denorm
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFuzzyImageCompare.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFuzzyImageCompare.js
new file mode 100644
index 0000000000..828d830100
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFuzzyImageCompare.js
@@ -0,0 +1,338 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuFuzzyImageCompare');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+
+goog.scope(function() {
+
+var tcuFuzzyImageCompare = framework.common.tcuFuzzyImageCompare;
+var deMath = framework.delibs.debase.deMath;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * tcuFuzzyImageCompare.FuzzyCompareParams struct
+ * @constructor
+ * @param {number=} maxSampleSkip_
+ * @param {number=} minErrThreshold_
+ * @param {number=} errExp_
+ */
+ tcuFuzzyImageCompare.FuzzyCompareParams = function(maxSampleSkip_, minErrThreshold_, errExp_) {
+ /** @type {number} */ this.maxSampleSkip = maxSampleSkip_ === undefined ? 8 : maxSampleSkip_;
+ /** @type {number} */ this.minErrThreshold = minErrThreshold_ === undefined ? 4 : minErrThreshold_;
+ /** @type {number} */ this.errExp = errExp_ === undefined ? 4.0 : errExp_;
+ };
+
+ /**
+ * @param {Array<number>} v
+ * @return {Array<number>}
+ */
+ tcuFuzzyImageCompare.roundArray4ToUint8Sat = function(v) {
+ return [
+ deMath.clamp(Math.trunc(v[0] + 0.5), 0, 255),
+ deMath.clamp(Math.trunc(v[1] + 0.5), 0, 255),
+ deMath.clamp(Math.trunc(v[2] + 0.5), 0, 255),
+ deMath.clamp(Math.trunc(v[3] + 0.5), 0, 255)
+ ];
+ };
+
+ /**
+ * @param {Array<number>} pa
+ * @param {Array<number>} pb
+ * @param {number} minErrThreshold
+ * @return {number}
+ */
+ tcuFuzzyImageCompare.compareColors = function(pa, pb, minErrThreshold) {
+ /** @type {number}*/ var r = Math.max(Math.abs(pa[0] - pb[0]) - minErrThreshold, 0);
+ /** @type {number}*/ var g = Math.max(Math.abs(pa[1] - pb[1]) - minErrThreshold, 0);
+ /** @type {number}*/ var b = Math.max(Math.abs(pa[2] - pb[2]) - minErrThreshold, 0);
+ /** @type {number}*/ var a = Math.max(Math.abs(pa[3] - pb[3]) - minErrThreshold, 0);
+
+ /** @type {number}*/ var scale = 1.0 / (255 - minErrThreshold);
+ /** @type {number}*/ var sqSum = (r * r + g * g + b * b + a * a) * (scale * scale);
+
+ return Math.sqrt(sqSum);
+ };
+
+ /**
+ * @param {tcuTexture.RGBA8View} src
+ * @param {number} u
+ * @param {number} v
+ * @param {number} NumChannels
+ * @return {Array<number>}
+ */
+ tcuFuzzyImageCompare.bilinearSample = function(src, u, v, NumChannels) {
+ /** @type {number}*/ var w = src.width;
+ /** @type {number}*/ var h = src.height;
+
+ /** @type {number}*/ var x0 = Math.floor(u - 0.5);
+ /** @type {number}*/ var x1 = x0 + 1;
+ /** @type {number}*/ var y0 = Math.floor(v - 0.5);
+ /** @type {number}*/ var y1 = y0 + 1;
+
+ /** @type {number}*/ var i0 = deMath.clamp(x0, 0, w - 1);
+ /** @type {number}*/ var i1 = deMath.clamp(x1, 0, w - 1);
+ /** @type {number}*/ var j0 = deMath.clamp(y0, 0, h - 1);
+ /** @type {number}*/ var j1 = deMath.clamp(y1, 0, h - 1);
+
+ /** @type {number}*/ var a = (u - 0.5) - Math.floor(u - 0.5);
+ /** @type {number}*/ var b = (v - 0.5) - Math.floor(v - 0.5);
+
+ /** @type {Array<number>} */ var p00 = src.read(i0, j0, NumChannels);
+ /** @type {Array<number>} */ var p10 = src.read(i1, j0, NumChannels);
+ /** @type {Array<number>} */ var p01 = src.read(i0, j1, NumChannels);
+ /** @type {Array<number>} */ var p11 = src.read(i1, j1, NumChannels);
+ /** @type {number} */ var dst = 0;
+
+ // Interpolate.
+ /** @type {Array<number>}*/ var f = [];
+ for (var c = 0; c < NumChannels; c++) {
+ f[c] = p00[c] * (1.0 - a) * (1.0 - b) +
+ (p10[c] * a * (1.0 - b)) +
+ (p01[c] * (1.0 - a) * b) +
+ (p11[c] * a * b);
+ }
+
+ return tcuFuzzyImageCompare.roundArray4ToUint8Sat(f);
+ };
+
+ /**
+ * @param {tcuTexture.RGBA8View} dst
+ * @param {tcuTexture.RGBA8View} src
+ * @param {number} shiftX
+ * @param {number} shiftY
+ * @param {Array<number>} kernelX
+ * @param {Array<number>} kernelY
+ * @param {number} DstChannels
+ * @param {number} SrcChannels
+ */
+ tcuFuzzyImageCompare.separableConvolve = function(dst, src, shiftX, shiftY, kernelX, kernelY, DstChannels, SrcChannels) {
+ DE_ASSERT(dst.width == src.width && dst.height == src.height);
+
+ /** @type {tcuTexture.TextureLevel} */ var tmp = new tcuTexture.TextureLevel(dst.getFormat(), dst.height, dst.width);
+ var tmpView = new tcuTexture.RGBA8View(tmp.getAccess());
+
+ /** @type {number} */ var kw = kernelX.length;
+ /** @type {number} */ var kh = kernelY.length;
+
+ /** @type {Array<number>} */ var sum = [];
+ /** @type {number} */ var f;
+ /** @type {Array<number>} */ var p;
+
+ // Horizontal pass
+ // \note Temporary surface is written in column-wise order
+ for (var j = 0; j < src.height; j++) {
+ for (var i = 0; i < src.width; i++) {
+ sum[0] = sum[1] = sum[2] = sum[3] = 0;
+ for (var kx = 0; kx < kw; kx++) {
+ f = kernelX[kw - kx - 1];
+ p = src.read(deMath.clamp(i + kx - shiftX, 0, src.width - 1), j, SrcChannels);
+ sum = deMath.add(sum, deMath.scale(p, f));
+ }
+
+ sum = tcuFuzzyImageCompare.roundArray4ToUint8Sat(sum);
+ tmpView.write(j, i, sum, DstChannels);
+ }
+ }
+
+ // Vertical pass
+ for (var j = 0; j < src.height; j++) {
+ for (var i = 0; i < src.width; i++) {
+ sum[0] = sum[1] = sum[2] = sum[3] = 0;
+ for (var ky = 0; ky < kh; ky++) {
+ f = kernelY[kh - ky - 1];
+ p = tmpView.read(deMath.clamp(j + ky - shiftY, 0, tmpView.width - 1), i, DstChannels);
+ sum = deMath.add(sum, deMath.scale(p, f));
+ }
+
+ sum = tcuFuzzyImageCompare.roundArray4ToUint8Sat(sum);
+ dst.write(i, j, sum, DstChannels);
+ }
+ }
+ };
+
+ /**
+ * @param {tcuFuzzyImageCompare.FuzzyCompareParams} params
+ * @param {deRandom.Random} rnd
+ * @param {Array<number>} pixel
+ * @param {tcuTexture.RGBA8View} surface
+ * @param {number} x
+ * @param {number} y
+ * @param {number} NumChannels
+ * @return {number}
+ */
+ tcuFuzzyImageCompare.compareToNeighbor = function(params, rnd, pixel, surface, x, y, NumChannels) {
+ /** @type {number} */ var minErr = 100;
+
+ // (x, y) + (0, 0)
+ minErr = Math.min(minErr, tcuFuzzyImageCompare.compareColors(pixel, surface.read(x, y, NumChannels), params.minErrThreshold));
+ if (minErr == 0.0)
+ return minErr;
+
+ // Area around (x, y)
+ /** @type {Array<Array.<number>>} */ var s_coords =
+ [
+ [-1, -1],
+ [0, -1],
+ [1, -1],
+ [-1, 0],
+ [1, 0],
+ [-1, 1],
+ [0, 1],
+ [1, 1]
+ ];
+
+ /** @type {number} */ var dx;
+ /** @type {number} */ var dy;
+
+ for (var d = 0; d < s_coords.length; d++) {
+ dx = x + s_coords[d][0];
+ dy = y + s_coords[d][1];
+
+ if (!deMath.deInBounds32(dx, 0, surface.width) || !deMath.deInBounds32(dy, 0, surface.height))
+ continue;
+
+ minErr = Math.min(minErr, tcuFuzzyImageCompare.compareColors(pixel, surface.read(dx, dy, NumChannels), params.minErrThreshold));
+ if (minErr == 0.0)
+ return minErr;
+ }
+
+ // Random bilinear-interpolated samples around (x, y)
+ for (var s = 0; s < 32; s++) {
+ dx = x + rnd.getFloat() * 2.0 - 0.5;
+ dy = y + rnd.getFloat() * 2.0 - 0.5;
+
+ /** @type {Array<number>} */ var sample = tcuFuzzyImageCompare.bilinearSample(surface, dx, dy, NumChannels);
+
+ minErr = Math.min(minErr, tcuFuzzyImageCompare.compareColors(pixel, sample, params.minErrThreshold));
+ if (minErr == 0.0)
+ return minErr;
+ }
+
+ return minErr;
+ };
+
+ /**
+ * @param {Array<number>} c
+ * @return {number}
+ */
+ tcuFuzzyImageCompare.toGrayscale = function(c) {
+ return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {boolean}
+ */
+ tcuFuzzyImageCompare.isFormatSupported = function(format) {
+ return format.type == tcuTexture.ChannelType.UNORM_INT8 && (format.order == tcuTexture.ChannelOrder.RGB || format.order == tcuTexture.ChannelOrder.RGBA);
+ };
+
+ /**
+ * @param {tcuFuzzyImageCompare.FuzzyCompareParams} params
+ * @param {tcuTexture.ConstPixelBufferAccess} ref
+ * @param {tcuTexture.ConstPixelBufferAccess} cmp
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @return {number}
+ */
+ tcuFuzzyImageCompare.fuzzyCompare = function(params, ref, cmp, errorMask) {
+ assertMsgOptions(ref.getWidth() == cmp.getWidth() && ref.getHeight() == cmp.getHeight(),
+ 'Reference and result images have different dimensions', false, true);
+
+ assertMsgOptions(ref.getWidth() == errorMask.getWidth() && ref.getHeight() == errorMask.getHeight(),
+ 'Reference and error mask images have different dimensions', false, true);
+
+ if (!tcuFuzzyImageCompare.isFormatSupported(ref.getFormat()) || !tcuFuzzyImageCompare.isFormatSupported(cmp.getFormat()))
+ throw new Error('Unsupported format in fuzzy comparison');
+
+ /** @type {number} */ var width = ref.getWidth();
+ /** @type {number} */ var height = ref.getHeight();
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(667);
+
+ // Filtered
+ /** @type {tcuTexture.TextureLevel} */ var refFiltered = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ /** @type {tcuTexture.TextureLevel} */ var cmpFiltered = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+
+ var refView = new tcuTexture.RGBA8View(ref);
+ var cmpView = new tcuTexture.RGBA8View(cmp);
+ var refFilteredView = new tcuTexture.RGBA8View(tcuTexture.PixelBufferAccess.newFromTextureLevel(refFiltered));
+ var cmpFilteredView = new tcuTexture.RGBA8View(tcuTexture.PixelBufferAccess.newFromTextureLevel(cmpFiltered));
+
+ // Kernel = {0.15, 0.7, 0.15}
+ /** @type {Array<number>} */ var kernel = [0.1, 0.8, 0.1];
+ /** @type {number} */ var shift = Math.floor((kernel.length - 1) / 2);
+
+ switch (ref.getFormat().order) {
+ case tcuTexture.ChannelOrder.RGBA: tcuFuzzyImageCompare.separableConvolve(refFilteredView, refView, shift, shift, kernel, kernel, 4, 4); break;
+ case tcuTexture.ChannelOrder.RGB: tcuFuzzyImageCompare.separableConvolve(refFilteredView, refView, shift, shift, kernel, kernel, 4, 3); break;
+ default:
+ throw new Error('tcuFuzzyImageCompare.fuzzyCompare - Invalid ChannelOrder');
+ }
+
+ switch (cmp.getFormat().order) {
+ case tcuTexture.ChannelOrder.RGBA: tcuFuzzyImageCompare.separableConvolve(cmpFilteredView, cmpView, shift, shift, kernel, kernel, 4, 4); break;
+ case tcuTexture.ChannelOrder.RGB: tcuFuzzyImageCompare.separableConvolve(cmpFilteredView, cmpView, shift, shift, kernel, kernel, 4, 3); break;
+ default:
+ throw new Error('tcuFuzzyImageCompare.fuzzyCompare - Invalid ChannelOrder');
+ }
+
+ /** @type {number} */ var numSamples = 0;
+ /** @type {number} */ var errSum = 0.0;
+
+ // Clear error mask to green.
+ errorMask.clear([0.0, 1.0, 0.0, 1.0]);
+
+ for (var y = 1; y < height - 1; y++) {
+ for (var x = 1; x < width - 1; x += params.maxSampleSkip > 0 ? rnd.getInt(0, params.maxSampleSkip) : 1) {
+ /** @type {number} */ var err = Math.min(tcuFuzzyImageCompare.compareToNeighbor(params, rnd, refFilteredView.read(x, y, 4), cmpFilteredView, x, y, 4),
+ tcuFuzzyImageCompare.compareToNeighbor(params, rnd, cmpFilteredView.read(x, y, 4), refFilteredView, x, y, 4));
+
+ err = Math.pow(err, params.errExp);
+
+ errSum += err;
+ numSamples += 1;
+
+ // Build error image.
+ /** @type {number} */ var red = err * 500.0;
+ /** @type {number} */ var luma = tcuFuzzyImageCompare.toGrayscale(cmp.getPixel(x, y));
+ /** @type {number} */ var rF = 0.7 + 0.3 * luma;
+ errorMask.setPixel([red * rF, (1.0 - red) * rF, 0.0, 1.0], x, y);
+
+ }
+ }
+
+ // Scale error sum based on number of samples taken
+ errSum *= ((width - 2) * (height - 2)) / numSamples;
+
+ return errSum;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js
new file mode 100644
index 0000000000..3a8138ef23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js
@@ -0,0 +1,757 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuBilinearImageCompare');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuFuzzyImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuSurface = framework.common.tcuSurface;
+var deMath = framework.delibs.debase.deMath;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuFloat = framework.common.tcuFloat;
+var tcuFuzzyImageCompare = framework.common.tcuFuzzyImageCompare;
+var tcuBilinearImageCompare = framework.common.tcuBilinearImageCompare;
+var tcuRGBA = framework.common.tcuRGBA;
+var tcuLogImage = framework.common.tcuLogImage;
+
+/**
+ * @enum
+ */
+tcuImageCompare.CompareLogMode = {
+ EVERYTHING: 0,
+ RESULT: 1,
+ ON_ERROR: 2
+};
+
+/**
+ * @param {framework.common.tcuTexture.ConstPixelBufferAccess} result
+ * @param {framework.common.tcuTexture.ConstPixelBufferAccess} reference
+ * @param {framework.common.tcuTexture.ConstPixelBufferAccess=} diff
+ */
+tcuImageCompare.displayImages = function(result, reference, diff) {
+ var limits = tcuImageCompare.computeScaleAndBias(reference, result);
+ tcuLogImage.logImage('Result', '', result, limits.scale, limits.bias);
+ tcuLogImage.logImage('Reference', '', reference, limits.scale, limits.bias);
+ if (diff)
+ tcuLogImage.logImage('Error', 'error mask', diff);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @return {{scale: Array<number>, bias: Array<number>}}
+ */
+tcuImageCompare.computeScaleAndBias = function(reference, result) {
+ var minVal = [];
+ var maxVal = [];
+ var scale = [];
+ var bias = [];
+
+ var eps = 0.0001;
+ var referenceRange = tcuTextureUtil.estimatePixelValueRange(reference);
+ var resultRange = tcuTextureUtil.estimatePixelValueRange(result);
+
+ minVal[0] = Math.min(referenceRange[0][0], resultRange[0][0]);
+ minVal[1] = Math.min(referenceRange[0][1], resultRange[0][1]);
+ minVal[2] = Math.min(referenceRange[0][2], resultRange[0][2]);
+ minVal[3] = Math.min(referenceRange[0][3], resultRange[0][3]);
+
+ maxVal[0] = Math.max(referenceRange[1][0], resultRange[1][0]);
+ maxVal[1] = Math.max(referenceRange[1][1], resultRange[1][1]);
+ maxVal[2] = Math.max(referenceRange[1][2], resultRange[1][2]);
+ maxVal[3] = Math.max(referenceRange[1][3], resultRange[1][3]);
+
+ for (var c = 0; c < 4; c++) {
+ if (maxVal[c] - minVal[c] < eps) {
+ scale[c] = (maxVal[c] < eps) ? 1 : (1 / maxVal[c]);
+ bias[c] = (c == 3) ? (1 - maxVal[c] * scale[c]) : (0 - minVal[c] * scale[c]);
+ } else {
+ scale[c] = 1 / (maxVal[c] - minVal[c]);
+ bias[c] = 0 - minVal[c] * scale[c];
+ }
+ }
+ return {
+ scale: scale,
+ bias: bias
+ };
+};
+
+/**
+ * \brief Per-pixel threshold-based comparison
+ *
+ * This compare computes per-pixel differences between result and reference
+ * image. Comparison fails if any pixels exceed the given threshold value.
+ *
+ * This comparison can be used for integer- and fixed-point texture formats.
+ * Difference is computed in integer space.
+ *
+ * On failure error image is generated that shows where the failing pixels
+ * are.
+ *
+ * @param {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
+ * @param {tcuTexture.ConstPixelBufferAccess} result Result image
+ * @param {Array<number>} threshold Maximum allowed difference
+ * @param {tcuImageCompare.CompareLogMode=} logMode
+ * @param {Array< Array<number> >} skipPixels pixels that are skipped comparison
+ * @return {boolean} true if comparison passes, false otherwise
+ */
+ tcuImageCompare.intThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode, skipPixels) {
+ var width = reference.getWidth();
+ var height = reference.getHeight();
+ var depth = reference.getDepth();
+ var errorMask = new tcuSurface.Surface(width, height);
+
+ var maxDiff = [0, 0, 0, 0];
+ // var pixelBias = [0, 0, 0, 0]; // Vec4 // TODO: check, only used in computeScaleAndBias, which is not included
+ // var pixelScale = [1, 1, 1, 1]; // Vec4 // TODO: check, only used in computeScaleAndBias
+
+ assertMsgOptions(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth,
+ 'Reference and result images have different dimensions', false, true);
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ if (skipPixels && skipPixels.length > 0) {
+ var skip = false;
+ for (var ii = 0; ii < skipPixels.length; ++ii) {
+ var refZ = (skipPixels[ii].length > 2 ? skipPixels[ii][2] : 0);
+ if (x == skipPixels[ii][0] && y == skipPixels[ii][1] && z == refZ) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+ }
+ var refPix = reference.getPixelInt(x, y, z);
+ var cmpPix = result.getPixelInt(x, y, z);
+
+ var diff = deMath.absDiff(refPix, cmpPix);
+ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ maxDiff = deMath.max(maxDiff, diff);
+ var color = [0, 255, 0, 255];
+ if (!isOk)
+ color = [255, 0, 0, 255];
+ errorMask.setPixel(x, y, color);
+ }
+ }
+ }
+
+ var compareOk = deMath.boolAll(deMath.lessThanEqual(maxDiff, threshold));
+
+ if (!compareOk) {
+ debug('Image comparison failed: max difference = ' + maxDiff + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ return compareOk;
+};
+
+/**
+ * \brief Per-pixel threshold-based deviation-ignoring comparison
+ *
+ * This compare computes per-pixel differences between result and reference
+ * image. Pixel fails the test if there is no pixel matching the given
+ * threshold value in the search volume. Comparison fails if the number of
+ * failing pixels exceeds the given limit.
+ *
+ * If the search volume contains out-of-bounds pixels, comparison can be set
+ * to either ignore these pixels in search or to accept any pixel that has
+ * out-of-bounds pixels in its search volume.
+ *
+ * This comparison can be used for integer- and fixed-point texture formats.
+ * Difference is computed in integer space.
+ *
+ * On failure error image is generated that shows where the failing pixels
+ * are.
+ *
+ * @param {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
+ * @param {tcuTexture.ConstPixelBufferAccess} result Result image
+ * @param {Array<number>} threshold Maximum allowed difference
+ * @param {Array<number>} maxPositionDeviation Maximum allowed distance in the search volume.
+ * @param {boolean} acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region
+ * @param {number} maxAllowedFailingPixels Maximum number of failing pixels
+ * @return {boolean} true if comparison passes, false otherwise
+ */
+tcuImageCompare.intThresholdPositionDeviationErrorThresholdCompare = function(
+ imageSetName, imageSetDesc, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue, maxAllowedFailingPixels) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+ /** @type {number} */ var numFailingPixels = tcuImageCompare.findNumPositionDeviationFailingPixels(errorMask.getAccess(), reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue);
+ var compareOk = numFailingPixels <= maxAllowedFailingPixels;
+ /** @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
+
+ if (!compareOk) {
+ debug('Position deviation error threshold image comparison failed: failed pixels = ' + numFailingPixels + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ } else
+ tcuLogImage.logImage('Result', '', result);
+
+ /*if (!compareOk) {
+ // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
+ if (tcuTexture.getTextureChannelClass(reference.getFormat().type) != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ||
+ tcuTexture.getTextureChannelClass(result.getFormat().type) != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) {
+ computeScaleAndBias(reference, result, pixelScale, pixelBias);
+ log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
+ }
+
+ if (!compareOk)
+ log << TestLog::Message
+ << "Image comparison failed:\n"
+ << "\tallowed position deviation = " << maxPositionDeviation << "\n"
+ << "\tcolor threshold = " << threshold
+ << TestLog::EndMessage;
+ log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage;
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
+ << TestLog::Image("ErrorMask", "Error mask", errorMask)
+ << TestLog::EndImageSet;
+ } else if (logMode == COMPARE_LOG_RESULT) {
+ if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ computePixelScaleBias(result, pixelScale, pixelBias);
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::EndImageSet;
+ }*/
+
+ return compareOk;
+};
+
+/**
+ * tcuImageCompare.floatUlpThresholdCompare
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {Array<number>} threshold - previously used as an Uint32Array
+ * @return {boolean}
+ */
+tcuImageCompare.floatUlpThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+
+ /** @type {Array<number>} */ var maxDiff = [0, 0, 0, 0]; // UVec4
+ // var pixelBias = [0, 0, 0, 0]; // Vec4
+ // var pixelScale = [1, 1, 1, 1]; // Vec4
+
+ assertMsgOptions(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth,
+ 'Reference and result images have different dimensions', false, true);
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ /** @type {ArrayBuffer} */ var arrayBufferRef = new ArrayBuffer(4 * 4);
+ /** @type {ArrayBuffer} */ var arrayBufferCmp = new ArrayBuffer(4 * 4);
+
+ /** @type {Array<number>} */ var refPix = reference.getPixel(x, y, z); // getPixel returns a Vec4 pixel color
+
+ /** @type {Array<number>} */ var cmpPix = result.getPixel(x, y, z); // getPixel returns a Vec4 pixel color
+
+ /** @type {Uint32Array} */ var refBits = new Uint32Array(arrayBufferRef); // UVec4
+ /** @type {Uint32Array} */ var cmpBits = new Uint32Array(arrayBufferCmp); // UVec4
+
+ // Instead of memcpy(), which is the way to do float->uint32 reinterpretation in C++
+ for (var i = 0; i < refPix.length; i++) {
+ refBits[i] = tcuFloat.convertFloat32Inline(refPix[i], tcuFloat.description32);
+ cmpBits[i] = tcuFloat.convertFloat32Inline(cmpPix[i], tcuFloat.description32);
+ }
+
+ /** @type {Array<number>} */ var diff = deMath.absDiff(refBits, cmpBits); // UVec4
+ /** @type {boolean} */ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ maxDiff = deMath.max(maxDiff, diff);
+
+ errorMask.setPixel(x, y, isOk ? [0, 255, 0, 255] : [255, 0, 0, 255]);
+ }
+ }
+ }
+
+ /** @type {boolean} */ var compareOk = deMath.boolAll(deMath.lessThanEqual(maxDiff, threshold));
+
+ if (!compareOk) {
+ debug('Image comparison failed: max difference = ' + maxDiff + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ /*if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) {
+ // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
+ if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
+ tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) {
+ computeScaleAndBias(reference, result, pixelScale, pixelBias);
+ log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
+ }
+
+ if (!compareOk)
+ log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
+ << TestLog::Image("ErrorMask", "Error mask", errorMask)
+ << TestLog::EndImageSet;
+ } else if (logMode == COMPARE_LOG_RESULT) {
+ if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ computePixelScaleBias(result, pixelScale, pixelBias);
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::EndImageSet;
+ }*/
+
+ return compareOk;
+};
+
+/**
+ * tcuImageCompare.floatThresholdCompare
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {Array<number>} threshold
+ * @return {boolean}
+ */
+tcuImageCompare.floatThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+
+ /** @type {Array<number>} */ var maxDiff = [0, 0, 0, 0]; // Vec4
+ // var pixelBias = [0, 0, 0, 0]; // Vec4
+ // var pixelScale = [1, 1, 1, 1]; // Vec4
+
+ assertMsgOptions(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth,
+ 'Reference and result images have different dimensions', false, true);
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ var refPix = reference.getPixel(x, y, z); // Vec4
+ var cmpPix = result.getPixel(x, y, z); // Vec4
+
+ /** @type {Array<number>} */ var diff = deMath.absDiff(refPix, cmpPix); // Vec4
+ /** @type {boolean} */ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ maxDiff = deMath.max(maxDiff, diff);
+
+ errorMask.setPixel(x, y, isOk ? [0, 255, 0, 255] : [255, 0, 0, 255]);
+ }
+ }
+ }
+
+ /** @type {boolean} */ var compareOk = deMath.boolAll(deMath.lessThanEqual(maxDiff, threshold));
+
+ if (!compareOk) {
+ debug('Image comparison failed: max difference = ' + maxDiff + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ /*if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) {
+ // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
+ if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
+ tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) {
+ computeScaleAndBias(reference, result, pixelScale, pixelBias);
+ log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
+ }
+
+ if (!compareOk)
+ log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
+ << TestLog::Image("ErrorMask", "Error mask", errorMask)
+ << TestLog::EndImageSet;
+ } else if (logMode == COMPARE_LOG_RESULT) {
+ if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ computePixelScaleBias(result, pixelScale, pixelBias);
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::EndImageSet;
+ }*/
+
+ return compareOk;
+};
+
+/**
+ * \brief Per-pixel threshold-based comparison
+ *
+ * This compare computes per-pixel differences between result and reference
+ * image. Comparison fails if any pixels exceed the given threshold value.
+ *
+ * On failure error image is generated that shows where the failing pixels
+ * are.
+ *
+ * @param {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuSurface.Surface} reference Reference image
+ * @param {tcuSurface.Surface} result Result image
+ * @param {Array<number>} threshold Maximum allowed difference
+ * @param {tcuImageCompare.CompareLogMode=} logMode
+ * @param {Array< Array<number> >} skipPixels pixels that are skipped comparison
+ * @return {boolean} true if comparison passes, false otherwise
+ */
+tcuImageCompare.pixelThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode, skipPixels) {
+ return tcuImageCompare.intThresholdCompare(imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold, logMode, skipPixels);
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {Array<number>} threshold
+ * @param {Array<number>} maxPositionDeviation
+ * @param {boolean} acceptOutOfBoundsAsAnyValue
+ * @return {number}
+ */
+tcuImageCompare.findNumPositionDeviationFailingPixels = function(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {number} */ var numFailingPixels = 0;
+
+ checkMessage(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth, 'Surfaces have different dimensions');
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ /** @type {Array<number>} */ var refPix = reference.getPixelInt(x, y, z);
+ /** @type {Array<number>} */ var cmpPix = result.getPixelInt(x, y, z);
+
+ // Exact match
+ /** @type {Array<number>} */ var diff = deMath.absDiff(refPix, cmpPix);
+ /** @type {boolean} */ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ if (isOk) {
+ errorMask.setPixel([0, 0xff, 0, 0xff], x, y, z);
+ continue;
+ }
+
+ // Accept over the image bounds pixels since they could be anything
+
+ if (acceptOutOfBoundsAsAnyValue &&
+ (x < maxPositionDeviation[0] || x + maxPositionDeviation[0] >= width ||
+ y < maxPositionDeviation[1] || y + maxPositionDeviation[1] >= height ||
+ z < maxPositionDeviation[2] || z + maxPositionDeviation[2] >= depth)) {
+ errorMask.setPixel([0, 0xff, 0, 0xff], x, y, z);
+ continue;
+ }
+
+ // Find matching pixels for both result and reference pixel
+
+ var pixelFoundForReference = false;
+ var pixelFoundForResult = false;
+
+ // Find deviated result pixel for reference
+
+ for (var sz = Math.max(0, z - maxPositionDeviation[2]); sz <= Math.min(depth - 1, z + maxPositionDeviation[2]) && !pixelFoundForReference; ++sz)
+ for (var sy = Math.max(0, y - maxPositionDeviation[1]); sy <= Math.min(height - 1, y + maxPositionDeviation[1]) && !pixelFoundForReference; ++sy)
+ for (var sx = Math.max(0, x - maxPositionDeviation[0]); sx <= Math.min(width - 1, x + maxPositionDeviation[0]) && !pixelFoundForReference; ++sx) {
+ /** @type {Array<number>} */ var deviatedCmpPix = result.getPixelInt(sx, sy, sz);
+ diff = deMath.absDiff(refPix, deviatedCmpPix);
+ isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ pixelFoundForReference |= isOk;
+ }
+
+ // Find deviated reference pixel for result
+
+ for (var sz = Math.max(0, z - maxPositionDeviation[2]); sz <= Math.min(depth - 1, z + maxPositionDeviation[2]) && !pixelFoundForResult; ++sz)
+ for (var sy = Math.max(0, y - maxPositionDeviation[1]); sy <= Math.min(height - 1, y + maxPositionDeviation[1]) && !pixelFoundForResult; ++sy)
+ for (var sx = Math.max(0, x - maxPositionDeviation[0]); sx <= Math.min(width - 1, x + maxPositionDeviation[0]) && !pixelFoundForResult; ++sx) {
+ /** @type {Array<number>} */ var deviatedRefPix = reference.getPixelInt(sx, sy, sz);
+ diff = deMath.absDiff(cmpPix, deviatedRefPix);
+ isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ pixelFoundForResult |= isOk;
+ }
+
+ if (pixelFoundForReference && pixelFoundForResult)
+ errorMask.setPixel([0, 0xff, 0, 0xff], x, y, z);
+ else {
+ errorMask.setPixel([0xff, 0, 0, 0xff], x, y, z);
+ ++numFailingPixels;
+ }
+ }
+ }
+ }
+
+ return numFailingPixels;
+};
+
+ /**
+ * tcuImageCompare.fuzzyCompare
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {number} threshold
+ * @param {tcuImageCompare.CompareLogMode=} logMode
+ * @return {boolean}
+ */
+tcuImageCompare.fuzzyCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode) {
+ /** @type {tcuFuzzyImageCompare.FuzzyCompareParams} */ var params = new tcuFuzzyImageCompare.FuzzyCompareParams(); // Use defaults.
+ /** @type {tcuTexture.TextureLevel} */ var errorMask = new tcuTexture.TextureLevel(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB,
+ tcuTexture.ChannelType.UNORM_INT8),
+ reference.getWidth(),
+ reference.getHeight()
+ );
+ /** @type {number} */ var difference = tcuFuzzyImageCompare.fuzzyCompare(
+ params,
+ reference,
+ result,
+ tcuTexture.PixelBufferAccess.newFromTextureLevel(errorMask)
+ );
+ /** @type {boolean} */ var isOk = difference <= threshold;
+ /** @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
+
+ if (!isOk) {
+ debug('Fuzzy image comparison failed: difference = ' + difference + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ /*
+ if (!isOk || logMode == COMPARE_LOG_EVERYTHING) {
+ // Generate more accurate error mask.
+ params.maxSampleSkip = 0;
+ tcuImageCompare.fuzzyCompare(params, reference, result, errorMask.getAccess());
+
+ if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ computeScaleAndBias(reference, result, pixelScale, pixelBias);
+
+ if (!isOk)
+ log << TestLog::Message << "Image comparison failed: difference = " << difference << ", threshold = " << threshold << TestLog::EndMessage;
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
+ << TestLog::Image("ErrorMask", "Error mask", errorMask)
+ << TestLog::EndImageSet;
+ } else if (logMode == COMPARE_LOG_RESULT) {
+ if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ computePixelScaleBias(result, pixelScale, pixelBias);
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::EndImageSet;
+ }
+ */
+ return isOk;
+};
+
+tcuImageCompare.unitTest = function() {
+ var width = 128;
+ var height = 128;
+
+ var weirdLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT32), width, height);
+ var access = weirdLevel.getAccess();
+ access.clear([0.1, 0.5, 0, 0]);
+ access.clear([0.11, 0.52, 0, 0], [0, width], [0, height / 2]);
+ access.clear([0.12, 0.52, 0, 0], [0, width], [height / 2, height / 2 + height / 8]);
+ var limits = tcuTextureUtil.computePixelScaleBias(access);
+ debug('Scale: ' + limits.scale);
+ debug('Bias: ' + limits.bias);
+ tcuLogImage.logImage('Weird', 'weird format without scaling', access);
+ tcuLogImage.logImage('Weird', 'weird format', access, limits.scale, limits.bias);
+
+ var srcLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var dstLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var src = srcLevel.getAccess();
+ var dst = dstLevel.getAccess();
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 1; i++) {
+ for (var j = 0; j < height - 1; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j, 90, 255], i + 1, j + 1);
+ }
+ }
+
+ debug('Src format: ' + src.getFormat());
+ debug('Destination: ' + dst);
+ debug(src);
+ tcuLogImage.logImage('Source', 'Source image', src);
+
+ if (!tcuImageCompare.fuzzyCompare('compare', 'compare similar images', src, dst, 0.05))
+ throw new Error('Compare should return true');
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 2; i++) {
+ for (var j = 0; j < height - 2; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j, 90, 255], i + 2, j + 2);
+ }
+ }
+
+ if (tcuImageCompare.fuzzyCompare('compare', 'compare different images', src, dst, 0.05))
+ throw new Error('Compare should return false');
+
+ debug('Passed');
+};
+
+tcuImageCompare.unitTest2 = function() {
+ var width = 128;
+ var height = 128;
+ var srcLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var dstLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var src = srcLevel.getAccess();
+ var dst = dstLevel.getAccess();
+ var threshold = tcuRGBA.newRGBAComponents(1, 1, 1, 1);
+ debug('Threshold: ' + threshold);
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 1; i++) {
+ for (var j = 0; j < height - 1; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j, 90, 255], i, j);
+ }
+ }
+ if (!tcuImageCompare.bilinearCompare('compare', 'compare similar images', src, dst, threshold))
+ throw new Error('Compare should return true');
+ debug('bilinear compare the same images passed');
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 1; i++) {
+ for (var j = 0; j < height - 1; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j + 1, 90, 255], i, j + 1);
+ }
+ }
+ if (!tcuImageCompare.bilinearCompare('compare', 'compare similar images', src, dst, threshold))
+ throw new Error('Compare should return true');
+ debug('bilinear compare very similar images passed');
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 2; i++) {
+ for (var j = 0; j < height - 2; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ // dst.setPixelInt([i, j, 90, 255], i + 2, j + 2);
+ }
+ }
+
+ if (tcuImageCompare.bilinearCompare('compare', 'compare different images', src, dst, threshold))
+ throw new Error('Compare should return false');
+
+ debug('bilinear compare very different images passed');
+};
+
+/**
+ * Bilinear image comparison
+ * On failure error image is generated that shows where the failing pixels
+ * are.
+ * Currently supports only RGBA, UNORM_INT8 formats
+ *
+ * @param {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
+ * @param {tcuTexture.ConstPixelBufferAccess} result Result image
+ * @param {tcuRGBA.RGBA} threshold Maximum local difference
+ * @param {tcuImageCompare.CompareLogMode=} logMode Logging mode
+ * @return {boolean} if comparison passes, false otherwise
+ */
+tcuImageCompare.bilinearCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode) {
+ /** @type {tcuTexture.TextureLevel} */
+ var errorMask = new tcuTexture.TextureLevel(
+ new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGB,
+ tcuTexture.ChannelType.UNORM_INT8),
+ reference.getWidth(),
+ reference.getHeight());
+
+ /** @type {boolean} */
+ var isOk = tcuBilinearImageCompare.bilinearCompare(
+ reference,
+ result,
+ tcuTexture.PixelBufferAccess.newFromTextureLevel(errorMask),
+ threshold);
+
+ if (!isOk) {
+ debug('Image comparison failed: threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ // /* @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
+ // /* @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
+ // if (!isOk || logMode == COMPARE_LOG_EVERYTHING)
+ // {
+ // if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ // computeScaleAndBias(reference, result, pixelScale, pixelBias);
+ //
+ // if (!isOk)
+ // log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage;
+ //
+ // log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ // << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ // << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
+ // << TestLog::Image("ErrorMask", "Error mask", errorMask)
+ // << TestLog::EndImageSet;
+ // }
+ // else if (logMode == COMPARE_LOG_RESULT)
+ // {
+ // if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
+ // computePixelScaleBias(result, pixelScale, pixelBias);
+ //
+ // log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ // << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ // << TestLog::EndImageSet;
+ // }
+
+ return isOk;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuInterval.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuInterval.js
new file mode 100644
index 0000000000..23296c1f3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuInterval.js
@@ -0,0 +1,609 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Interval arithmetic and floating point precisions.
+ *//*--------------------------------------------------------------------*/
+ 'use strict';
+ goog.provide('framework.common.tcuInterval');
+ goog.require('framework.delibs.debase.deMath');
+
+ goog.scope(function() {
+
+ var tcuInterval = framework.common.tcuInterval;
+ var deMath = framework.delibs.debase.deMath;
+
+ /**
+ * @typedef {function(number):number}
+ */
+ tcuInterval.DoubleFunc1;
+
+ /**
+ * @typedef {function(number, number):number}
+ */
+ tcuInterval.DoubleFunc2;
+
+ /**
+ * @typedef {function(number,number,number):number}
+ */
+ tcuInterval.DoubleFunc3;
+
+ /**
+ * @typedef {function(number):tcuInterval.Interval}
+ */
+ tcuInterval.DoubleIntervalFunc1;
+
+ /**
+ * @typedef {function(number,number):tcuInterval.Interval}
+ */
+ tcuInterval.DoubleIntervalFunc2;
+
+ /**
+ * @typedef {function(number,number,number):tcuInterval.Interval}
+ */
+ tcuInterval.DoubleIntervalFunc3;
+
+ /**
+ * @param {function(number): number} func
+ * @param {tcuInterval.Interval} arg0
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.applyMonotone1p = function(func, arg0) {
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {number}
+ */
+ var body = function(x, y) {
+ x = x || 0;
+ return func(x);
+ };
+ return tcuInterval.applyMonotone1(arg0,
+ function(x) { return tcuInterval.setInterval(body, x); });
+ };
+
+ /**
+ * @param {function(number): tcuInterval.Interval} func
+ * @param {tcuInterval.Interval} arg0
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.applyMonotone1i = function(func, arg0) {
+ return tcuInterval.withIntervals(func(arg0.lo()), func(arg0.hi()));
+ };
+
+ /**
+ * @param {function(number, number): number} func
+ * @param {tcuInterval.Interval} arg0
+ * @param {tcuInterval.Interval} arg1
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.applyMonotone2p = function(func, arg0, arg1) {
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {number}
+ */
+ var body = function(x, y) {
+ x = x || 0;
+ y = y || 0;
+ return func(x, y);
+ };
+ return tcuInterval.applyMonotone2(arg0, arg1,
+ function(x, y) { return tcuInterval.setInterval(body, x, y); });
+ };
+
+ /**
+ * @param {function(number, number): tcuInterval.Interval} func
+ * @param {tcuInterval.Interval} arg0
+ * @param {tcuInterval.Interval} arg1
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.applyMonotone2i = function(func, arg0, arg1) {
+ /** @type {number} */ var lo0 = arg0.lo();
+ /** @type {number} */ var hi0 = arg0.hi();
+ /** @type {number} */ var lo1 = arg1.lo();
+ /** @type {number} */ var hi1 = arg1.hi();
+ var a = tcuInterval.withIntervals(func(lo0, lo1), func(lo0, hi1));
+ var b = tcuInterval.withIntervals(func(hi0, lo1), func(hi0, hi1));
+ return tcuInterval.withIntervals(a, b);
+ };
+
+ /**
+ * @constructor
+ * @param {number=} val
+ */
+ tcuInterval.Interval = function(val) {
+ if (val === undefined) {
+ this.m_hasNaN = false;
+ this.m_lo = Number.POSITIVE_INFINITY;
+ this.m_hi = Number.NEGATIVE_INFINITY;
+ } else {
+ this.m_hasNaN = isNaN(val);
+ this.m_lo = this.m_hasNaN ? Number.POSITIVE_INFINITY : val;
+ this.m_hi = this.m_hasNaN ? Number.NEGATIVE_INFINITY : val;
+ }
+ };
+
+ tcuInterval.Interval.prototype.toString = function() {
+ var str = 'Interval(' + this.m_lo + ', ' + this.m_hi;
+ if (this.m_hasNaN)
+ str += ', hasNaN';
+ str += ')';
+ return str;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} a
+ * @param {tcuInterval.Interval} b
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.withIntervals = function(a, b) {
+ /** @type {tcuInterval.Interval} */ var interval = new tcuInterval.Interval();
+ interval.m_hasNaN = (a.m_hasNaN || b.m_hasNaN);
+ interval.m_lo = Math.min(a.m_lo, b.m_lo);
+ interval.m_hi = Math.max(a.m_hi, b.m_hi);
+ return interval;
+ };
+
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.withNumbers = function(a, b) {
+ var x = new tcuInterval.Interval(a);
+ var y = new tcuInterval.Interval(b);
+ return tcuInterval.withIntervals(x, y);
+ };
+
+ /**
+ * @param {boolean} hasNaN_
+ * @param {number} lo_
+ * @param {number} hi_
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.withParams = function(hasNaN_, lo_, hi_) {
+ /** @type {tcuInterval.Interval} */ var interval = new tcuInterval.Interval();
+ interval.m_hasNaN = hasNaN_;
+ interval.m_lo = lo_;
+ interval.m_hi = hi_;
+ return interval;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuInterval.Interval.prototype.length = function() {
+ return this.m_hi - this.m_lo;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuInterval.Interval.prototype.lo = function() {
+ return this.m_lo;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuInterval.Interval.prototype.hi = function() {
+ return this.m_hi;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.hasNaN = function() {
+ return this.m_hasNaN;
+ };
+
+ /**
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.prototype.nan = function() {
+ return this.m_hasNaN ? new tcuInterval.Interval(NaN) : new tcuInterval.Interval();
+ };
+
+ /**
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.empty = function() {
+ return this.m_lo > this.m_hi;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.isFinite = function() {
+ return isFinite(this.m_lo) && isFinite(this.m_hi);
+ };
+
+ /**
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.isOrdinary = function() {
+ return !this.hasNaN() && !this.empty() && this.isFinite();
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.prototype.operatorOrBinary = function(other) {
+ /** @type {tcuInterval.Interval} */ var temp = new tcuInterval.Interval();
+ temp.m_hasNaN = this.m_hasNaN || other.m_hasNaN;
+ temp.m_lo = Math.min(this.m_lo, other.m_lo);
+ temp.m_hi = Math.max(this.m_hi, other.m_hi);
+ return temp;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ */
+ tcuInterval.Interval.prototype.operatorOrAssignBinary = function(other) {
+ /** @type {tcuInterval.Interval} */ var temp = this.operatorOrBinary(other);
+ this.m_hasNaN = temp.m_hasNaN;
+ this.m_lo = temp.m_lo;
+ this.m_hi = temp.m_hi;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.prototype.operatorAndBinary = function(other) {
+ /** @type {tcuInterval.Interval} */ var temp = new tcuInterval.Interval();
+ temp.m_hasNaN = this.m_hasNaN && other.m_hasNaN;
+ temp.m_lo = Math.max(this.m_lo, other.m_lo);
+ temp.m_hi = Math.min(this.m_hi, other.m_hi);
+ return temp;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ */
+ tcuInterval.Interval.prototype.operatorAndAssignBinary = function(other) {
+ /** @type {tcuInterval.Interval} */ var temp = this.operatorAndBinary(other);
+ this.m_hasNaN = temp.m_hasNaN;
+ this.m_lo = temp.m_lo;
+ this.m_hi = temp.m_hi;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.contains = function(other) {
+ return (other.lo() >= this.lo() && other.hi() <= this.hi() &&
+ (!other.hasNaN() || this.hasNaN()));
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.intersects = function(other) {
+ return ((other.hi() >= this.lo() && other.lo() >= this.hi()) ||
+ (other.hasNaN() && this.hasNaN()));
+ };
+
+ /**
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.prototype.operatorNegative = function() {
+ /** @type {tcuInterval.Interval} */ var temp = new tcuInterval.Interval();
+ temp.m_hasNaN = this.m_hasNaN;
+ temp.m_lo = -this.m_hi;
+ temp.m_hi = -this.m_lo;
+ return temp;
+ };
+
+ /**
+ * @param {boolean=} nan
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.unbounded = function(nan) {
+ if (nan === undefined)
+ nan = false;
+ return tcuInterval.withParams(nan, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuInterval.Interval.prototype.midpoint = function() {
+ return 0.5 * (this.hi() + this.lo()); // returns NaN when not bounded
+ };
+
+ /**
+ * @param {tcuInterval.Interval} other
+ * @return {boolean}
+ */
+ tcuInterval.Interval.prototype.operatorCompare = function(other) {
+ return ((this.m_hasNaN == other.m_hasNaN) &&
+ ((this.empty() && other.empty()) ||
+ (this.m_lo == other.m_lo && this.m_hi == other.m_hi)));
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.operatorPositive = function(x) {
+ return x;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.exp2 = function(x) {
+ // std::pow
+ return tcuInterval.applyMonotone2p(Math.pow, new tcuInterval.Interval(2), x);
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.exp = function(x) {
+ // std::exp
+ return tcuInterval.applyMonotone1p(Math.exp, x);
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.sign = function(x) {
+ // TODO
+ throw new Error('Unimplemented');
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @param {tcuInterval.Interval} y
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.operatorSum = function(x, y) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+
+ if (!x.empty() && !y.empty())
+ ret = tcuInterval.setIntervalBounds(function(dummy) {return x.lo() + y.lo();}, function(dummy) {return x.hi() + y.hi();});
+ if (x.hasNaN() || y.hasNaN())
+ ret.operatorOrAssignBinary(new tcuInterval.Interval(NaN));
+
+ return ret;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @param {tcuInterval.Interval} y
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.operatorSub = function(x, y) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {tcuInterval.Interval}
+ */
+ var body = function(x, y) {
+ return new tcuInterval.Interval(x - y);
+ };
+
+ ret = tcuInterval.applyMonotone2(x, y, body);
+ return ret;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @param {tcuInterval.Interval} y
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.operatorMul = function(x, y) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {tcuInterval.Interval}
+ */
+ var body = function(x, y) {
+ return new tcuInterval.Interval(x * y);
+ };
+
+ ret = tcuInterval.applyMonotone2(x, y, body);
+
+ return ret;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} nom
+ * @param {tcuInterval.Interval} den
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.operatorDiv = function(nom, den) {
+ if (den.contains(new tcuInterval.Interval(0))) {
+ // \todo [2014-03-21 lauri] Non-inf endpoint when one den endpoint is
+ // zero and nom doesn't cross zero?
+ return tcuInterval.unbounded();
+ } else {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {tcuInterval.Interval}
+ */
+ var body = function(x, y) {
+ return new tcuInterval.Interval(x / y);
+ };
+
+ ret = tcuInterval.applyMonotone2(nom, den, body);
+
+ return ret;
+ }
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.prototype.abs = function(x) {
+ //std::abs
+ /** @type {tcuInterval.Interval} */ var mono = tcuInterval.applyMonotone1p(Math.abs, x);
+ var zero = new tcuInterval.Interval(0);
+ if (x.contains(zero))
+ return tcuInterval.withIntervals(zero, mono);
+
+ return mono;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.sqrt = function(x) {
+ return tcuInterval.applyMonotone1p(Math.sqrt, x);
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuInterval.Interval.inverseSqrt = function(x) {
+ var ret = new tcuInterval.Interval(1);
+ ret = tcuInterval.Interval.operatorDiv(ret, tcuInterval.Interval.sqrt(x));
+ return ret;
+ };
+
+/**
+ * @param {function(number=, number=): number} setLow
+ * @param {function(number=, number=): number} setHigh
+ * @param {number=} arg0
+ * @param {number=} arg1
+ * @return {tcuInterval.Interval}
+ */
+tcuInterval.setIntervalBounds = function(setLow, setHigh, arg0, arg1) {
+ // TODO: No support for rounding modes. Originally, setLow() was rounded down and setHigh() rounded up
+ var lo = new tcuInterval.Interval(setLow(arg0, arg1));
+ var hi = new tcuInterval.Interval(setHigh(arg0, arg1));
+ return lo.operatorOrBinary(hi);
+};
+
+/**
+ * @param {function(number=, number=): number} set
+ * @param {number=} arg0
+ * @param {number=} arg1
+ * @return {tcuInterval.Interval}
+ */
+tcuInterval.setInterval = function(set, arg0, arg1) {
+ return tcuInterval.setIntervalBounds(set, set, arg0, arg1);
+};
+
+/**
+ * @param {tcuInterval.Interval} arg
+ * @param {function(number): tcuInterval.Interval} body
+ * @return {tcuInterval.Interval}
+ */
+tcuInterval.applyMonotone1 = function(arg, body) {
+ var ret = new tcuInterval.Interval();
+
+ if (!arg.empty()) {
+ var lo = body(arg.lo());
+ var hi = body(arg.hi());
+ ret = lo.operatorOrBinary(hi);
+ }
+
+ if (arg.hasNaN()) {
+ ret = ret.operatorOrBinary(new tcuInterval.Interval(NaN));
+ }
+
+ return ret;
+};
+
+/**
+ * TODO: Check if this function works properly
+ * @param {tcuInterval.Interval} arg0
+ * @param {tcuInterval.Interval} arg1
+ * @param {function(number, number): tcuInterval.Interval} body
+ * @return {tcuInterval.Interval}
+ */
+tcuInterval.applyMonotone2 = function(arg0, arg1, body) {
+ var ret = new tcuInterval.Interval();
+
+ if (!arg0.empty() && !arg1.empty()) {
+ var lo0 = body(arg0.lo(), arg1.lo());
+ var lo1 = body(arg0.lo(), arg1.hi());
+ var hi0 = body(arg0.hi(), arg1.lo());
+ var hi1 = body(arg0.hi(), arg1.hi());
+ var a = lo0.operatorOrBinary(hi0);
+ var b = lo1.operatorOrBinary(hi1);
+ ret = a.operatorOrBinary(b);
+ }
+
+ if (arg0.hasNaN() || arg1.hasNaN()) {
+ ret = ret.operatorOrBinary(new tcuInterval.Interval(NaN));
+ }
+
+ return ret;
+};
+
+/**
+ * TODO: Check if this function works properly
+ * @param {tcuInterval.Interval} arg0
+ * @param {tcuInterval.Interval} arg1
+ * @param {tcuInterval.Interval} arg2
+ * @param {function(number, number, number): tcuInterval.Interval} body
+ * @return {tcuInterval.Interval}
+ */
+tcuInterval.applyMonotone3 = function(arg0, arg1, arg2, body) {
+ var ret = new tcuInterval.Interval();
+
+ if (!arg0.empty() && !arg1.empty() && !arg2.empty()) {
+ var i0 = body(arg0.lo(), arg1.lo(), arg2.lo());
+ var i1 = body(arg0.lo(), arg1.lo(), arg2.hi());
+ var i2 = body(arg0.lo(), arg1.hi(), arg2.lo());
+ var i3 = body(arg0.lo(), arg1.hi(), arg2.hi());
+ var i4 = body(arg0.hi(), arg1.lo(), arg2.lo());
+ var i5 = body(arg0.hi(), arg1.lo(), arg2.hi());
+ var i6 = body(arg0.hi(), arg1.hi(), arg2.lo());
+ var i7 = body(arg0.hi(), arg1.hi(), arg2.hi());
+
+ var low = Math.min(i0.lo(), i1.lo(), i2.lo(), i3.lo(), i4.lo(), i5.lo(), i6.lo(), i7.lo());
+ var high = Math.max(i0.hi(), i1.hi(), i2.hi(), i3.hi(), i4.hi(), i5.hi(), i6.hi(), i7.hi());
+ var hasNaN = i0.hasNaN() || i1.hasNaN() || i2.hasNaN() || i3.hasNaN() || i4.hasNaN() || i5.hasNaN() || i6.hasNaN() || i7.hasNaN();
+
+ ret = tcuInterval.withParams(hasNaN, low, high);
+ }
+
+ if (arg0.hasNaN() || arg1.hasNaN() || arg2.hasNaN()) {
+ ret = ret.operatorOrBinary(new tcuInterval.Interval(NaN));
+ }
+
+ return ret;
+};
+
+/** @const */ tcuInterval.POSITIVE_INFINITY = new tcuInterval.Interval(Infinity);
+/** @const */ tcuInterval.NEGATIVE_INFINITY = new tcuInterval.Interval(-Infinity);
+/** @const */ tcuInterval.ZERO = new tcuInterval.Interval(0);
+/** @const */ tcuInterval.NAN = new tcuInterval.Interval(NaN);
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuLogImage.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuLogImage.js
new file mode 100644
index 0000000000..2dabc9060b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuLogImage.js
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuLogImage');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuLogImage = framework.common.tcuLogImage;
+var tcuTexture = framework.common.tcuTexture;
+var tcuSurface = framework.common.tcuSurface;
+var deMath = framework.delibs.debase.deMath;
+
+/** @const */ var MAX_IMAGE_SIZE_2D = 4096;
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} src
+ */
+tcuLogImage.createImage = function(ctx, src) {
+ var w = src.getWidth();
+ var h = src.getHeight();
+ var pixelSize = src.getFormat().getPixelSize();
+ var imgData = ctx.createImageData(w, h);
+ var index = 0;
+ for (var y = 0; y < h; y++) {
+ for (var x = 0; x < w; x++) {
+ var pixel = src.getPixelInt(x, h - y - 1, 0);
+ for (var i = 0; i < pixelSize; i++) {
+ imgData.data[index] = pixel[i];
+ index = index + 1;
+ }
+ if (pixelSize < 4)
+ imgData.data[index++] = 255;
+ }
+ }
+ return imgData;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} image
+ * @param {string} info
+ */
+tcuLogImage.logImageWithInfo = function(image, info) {
+ var elem = document.getElementById('console');
+ var span = document.createElement('span');
+ tcuLogImage.logImage.counter = tcuLogImage.logImage.counter || 0;
+ var i = tcuLogImage.logImage.counter++;
+ var width = image.getWidth();
+ var height = image.getHeight();
+
+ elem.appendChild(span);
+ span.innerHTML = info + '<br> <canvas id="logImage' + i + '" width=' + width + ' height=' + height + '></canvas><br>';
+
+ var imageCanvas = document.getElementById('logImage' + i);
+ var ctx = imageCanvas.getContext('2d');
+ var data = tcuLogImage.createImage(ctx, image);
+ ctx.putImageData(data, 0, 0);
+};
+
+
+/**
+ * @param {Array<number>=} scale
+ * @param {Array<number>=} bias
+ * @return {string} HTML string to add to log.
+ */
+tcuLogImage.logScaleAndBias = function(scale, bias) {
+ if (scale && bias)
+ return '<br> Image normalized with formula p * (' + scale + ') + (' + bias + ')';
+ else if (scale)
+ return '<br> Image normalized with formula p * (' + scale + ')';
+ else if (bias)
+ return '<br> Image normalized with formula p + (' + bias + ')';
+ return '';
+};
+
+/**
+ * @param {string} name
+ * @param {string} description
+ * @param {tcuTexture.ConstPixelBufferAccess} image
+ * @param {Array<number>=} scale
+ * @param {Array<number>=} bias
+ */
+tcuLogImage.logImageRGB = function(name, description, image, scale, bias) {
+ var elem = document.getElementById('console');
+ var span = document.createElement('span');
+ var info = name + ' ' + description + '<br> ' + image;
+ if (scale || bias)
+ info += tcuLogImage.logScaleAndBias(scale, bias);
+ tcuLogImage.logImageWithInfo(image, info);
+};
+
+/**
+ * @param {string} name
+ * @param {string} description
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {Array<number>=} pixelScale
+ * @param {Array<number>=} pixelBias
+ */
+tcuLogImage.logImage = function(name, description, access, pixelScale, pixelBias) {
+ pixelScale = pixelScale || [1, 1, 1, 1];
+ pixelBias = pixelBias || [0, 0, 0, 0];
+ var format = access.getFormat();
+ var width = access.getWidth();
+ var height = access.getHeight();
+ var depth = access.getDepth();
+ var needScaling = pixelBias[0] != 0 || pixelBias[1] != 0 || pixelBias[2] != 0 || pixelBias[3] != 0 ||
+ pixelScale[0] != 1 || pixelScale[1] != 1 || pixelScale[2] != 1 || pixelScale[3] != 1;
+
+ if (depth == 1 && format.type == tcuTexture.ChannelType.UNORM_INT8 &&
+ width <= MAX_IMAGE_SIZE_2D && height <= MAX_IMAGE_SIZE_2D &&
+ (format.order == tcuTexture.ChannelOrder.RGB || tcuTexture.ChannelOrder.RGBA) &&
+ !needScaling)
+ // Fast-path.
+ tcuLogImage.logImageRGB(name, description, access);
+ else if (depth == 1) {
+ var sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.LINEAR, tcuTexture.FilterMode.NEAREST);
+ var logImageSize = [width, height]; /* TODO: Add scaling */
+ var logImageAccess = new tcuSurface.Surface(width, height).getAccess();
+
+ for (var y = 0; y < logImageAccess.getHeight(); y++) {
+ for (var x = 0; x < logImageAccess.getWidth(); x++) {
+ var yf = (y + 0.5) / logImageAccess.getHeight();
+ var xf = (x + 0.5) / logImageAccess.getWidth();
+ var s = access.sample2D(sampler, sampler.minFilter, xf, yf, 0);
+
+ if (needScaling)
+ s = deMath.add(deMath.multiply(s, pixelScale), pixelBias);
+
+ logImageAccess.setPixel(s, x, y);
+ }
+ }
+ var info = name + ' ' + description + '<br> ' + access;
+ if (needScaling) {
+ info += tcuLogImage.logScaleAndBias(pixelScale, pixelBias);
+ }
+
+ tcuLogImage.logImageWithInfo(logImageAccess, info);
+ } else {
+ /* TODO: Implement */
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrix.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrix.js
new file mode 100644
index 0000000000..e2959ecdc2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrix.js
@@ -0,0 +1,354 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('framework.common.tcuMatrix');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+ var tcuMatrix = framework.common.tcuMatrix;
+ var deMath = framework.delibs.debase.deMath;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * @constructor
+ * @param {number} rows
+ * @param {number} cols
+ * @param {*=} value
+ * Initialize to identity.
+ */
+ tcuMatrix.Matrix = function(rows, cols, value) {
+ value = value == undefined ? 1 : value;
+ this.rows = rows;
+ this.cols = cols;
+ this.matrix = [];
+ for (var i = 0; i < cols; i++)
+ this.matrix[i] = [];
+ for (var row = 0; row < rows; row++)
+ for (var col = 0; col < cols; col++)
+ this.set(row, col, (row == col) ? value : 0);
+ };
+
+ /**
+ * @param {number} rows
+ * @param {number} cols
+ * @param {Array<number>} vector
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.matrixFromVector = function(rows, cols, vector) {
+ var matrix = new tcuMatrix.Matrix(rows, cols);
+ for (var row = 0; row < vector.length; row++)
+ for (var col = 0; col < vector.length; col++)
+ matrix.matrix[col][row] = row == col ? vector[row] : 0;
+ return matrix;
+ };
+
+ /**
+ * @param {number} rows
+ * @param {number} cols
+ * @param {Array<number>} src
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.matrixFromDataArray = function(rows, cols, src) {
+ var matrix = new tcuMatrix.Matrix(rows, cols);
+ for (var row = 0; row < rows; row++) {
+ for (var col = 0; col < cols; col++) {
+ matrix.matrix[col][row] = src[row * cols + col];
+ }
+ }
+ return matrix;
+ };
+
+ /**
+ * Fill the Matrix with data from array
+ * @param {number} rows
+ * @param {number} cols
+ * @param {Array<number>} array
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.matrixFromArray = function(rows, cols, array) {
+ DE_ASSERT(array.length === rows * cols);
+ var matrix = new tcuMatrix.Matrix(rows, cols);
+ for (var row = 0; row < rows; row++)
+ for (var col = 0; col < cols; col++)
+ matrix.matrix[col][row] = array[row * cols + col];
+ return matrix;
+ };
+
+ tcuMatrix.Matrix.prototype.set = function(x, y, value) {
+ this.isRangeValid(x, y);
+ this.matrix[y][x] = value;
+ };
+
+ tcuMatrix.Matrix.prototype.setRow = function(row, values) {
+ if (!deMath.deInBounds32(row, 0, this.rows))
+ throw new Error('Rows out of range');
+ if (values.length > this.cols)
+ throw new Error('Too many columns');
+ for (var col = 0; col < values.length; col++)
+ this.matrix[col][row] = values[col];
+ };
+
+ tcuMatrix.Matrix.prototype.setCol = function(col, values) {
+ if (!deMath.deInBounds32(col, 0, this.cols))
+ throw new Error('Columns out of range');
+ if (values.length > this.rows)
+ throw new Error('Too many rows');
+ for (var row = 0; row < values.length; row++)
+ this.matrix[col][row] = values[row];
+ };
+
+ tcuMatrix.Matrix.prototype.get = function(x, y) {
+ this.isRangeValid(x, y);
+ return this.matrix[y][x];
+ };
+
+ tcuMatrix.Matrix.prototype.getColumn = function(y) {
+ return this.matrix[y];
+ };
+
+ tcuMatrix.Matrix.prototype.isRangeValid = function(x, y) {
+ if (!deMath.deInBounds32(x, 0, this.rows))
+ throw new Error('Rows out of range');
+ if (!deMath.deInBounds32(y, 0, this.cols))
+ throw new Error('Columns out of range');
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ tcuMatrix.Matrix.prototype.getColumnMajorData = function() {
+ /** @type {Array<number>} */ var a = [];
+ for (var col = 0; col < this.cols; col++)
+ for (var row = 0; row < this.rows; row++)
+ a.push(this.get(row, col));
+ return a;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} matrixA
+ * @param {tcuMatrix.Matrix} matrixB
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.add = function(matrixA, matrixB) {
+ var res = new tcuMatrix.Matrix(matrixA.rows, matrixB.cols);
+ for (var col = 0; col < matrixA.cols; col++)
+ for (var row = 0; row < matrixA.rows; row++)
+ res.set(row, col, matrixA.get(row, col) + matrixB.get(row, col));
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} matrixA
+ * @param {tcuMatrix.Matrix} matrixB
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.subtract = function(matrixA, matrixB) {
+ var res = new tcuMatrix.Matrix(matrixA.rows, matrixB.cols);
+ for (var col = 0; col < matrixA.cols; col++)
+ for (var row = 0; row < matrixA.rows; row++)
+ res.set(row, col, matrixA.get(row, col) - matrixB.get(row, col));
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} matrixA
+ * @param {tcuMatrix.Matrix} matrixB
+ * @return {tcuMatrix.Matrix}
+ * Multiplication of two matrices.
+ */
+ tcuMatrix.multiply = function(matrixA, matrixB) {
+ if (matrixA.cols != matrixB.rows)
+ throw new Error('Wrong matrices sizes');
+ var res = new tcuMatrix.Matrix(matrixA.rows, matrixB.cols);
+ for (var row = 0; row < matrixA.rows; row++)
+ for (var col = 0; col < matrixB.cols; col++) {
+ var v = 0;
+ for (var ndx = 0; ndx < matrixA.cols; ndx++)
+ v += matrixA.get(row, ndx) * matrixB.get(ndx, col);
+ res.set(row, col, v);
+ }
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} matrixA
+ * @param {tcuMatrix.Matrix} matrixB
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.divide = function(matrixA, matrixB) {
+ var res = new tcuMatrix.Matrix(matrixA.rows, matrixA.cols);
+ for (var col = 0; col < matrixA.cols; col++)
+ for (var row = 0; row < matrixA.rows; row++)
+ res.set(row, col, matrixA.get(row, col) / matrixB.get(row, col));
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mtx
+ * @param {Array<number>} vec
+ * @return {Array<number>}
+ */
+ tcuMatrix.multiplyMatVec = function(mtx, vec) {
+ /** @type {Array<number>} */ var res = [];
+ /** @type {number} */ var value;
+ for (var row = 0; row < mtx.rows; row++) {
+ value = 0;
+ for (var col = 0; col < mtx.cols; col++)
+ value += mtx.get(row, col) * vec[col];
+ res[row] = value;
+ }
+
+ return res;
+ };
+
+ /**
+ * @param {Array<number>} vec
+ * @param {tcuMatrix.Matrix} mtx
+ * @return {Array<number>}
+ */
+ tcuMatrix.multiplyVecMat = function(vec, mtx) {
+ /** @type {Array<number>} */ var res = [];
+ /** @type {number} */ var value;
+ for (var col = 0; col < mtx.cols; col++) {
+ value = 0;
+ for (var row = 0; row < mtx.rows; row++)
+ value += mtx.get(row, col) * vec[row];
+ res[col] = value;
+ }
+
+ return res;
+ };
+
+ tcuMatrix.Matrix.prototype.toString = function() {
+ var str = 'mat' + this.cols;
+ if (this.rows !== this.cols)
+ str += 'x' + this.rows;
+ str += '(';
+ for (var col = 0; col < this.cols; col++) {
+ str += '[';
+ for (var row = 0; row < this.rows; row++) {
+ str += this.matrix[col][row];
+ if (row != this.rows - 1)
+ str += ', ';
+ }
+ str += ']';
+
+ if (col != this.cols - 1)
+ str += ', ';
+ }
+ str += ')';
+ return str;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mtx
+ * @param {number} scalar
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.subtractMatScal = function(mtx, scalar) {
+ /** @type {tcuMatrix.Matrix} */ var res = new tcuMatrix.Matrix(mtx.rows, mtx.cols);
+ for (var col = 0; col < mtx.cols; col++)
+ for (var row = 0; row < mtx.rows; row++)
+ res.set(row, col, mtx.get(row, col) - scalar);
+
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mtx
+ * @param {number} scalar
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.addMatScal = function(mtx, scalar) {
+ /** @type {tcuMatrix.Matrix} */ var res = new tcuMatrix.Matrix(mtx.rows, mtx.cols);
+ for (var col = 0; col < mtx.cols; col++)
+ for (var row = 0; row < mtx.rows; row++)
+ res.set(row, col, mtx.get(row, col) + scalar);
+
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mtx
+ * @param {number} scalar
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.multiplyMatScal = function(mtx, scalar) {
+ /** @type {tcuMatrix.Matrix} */ var res = new tcuMatrix.Matrix(mtx.rows, mtx.cols);
+ for (var col = 0; col < mtx.cols; col++)
+ for (var row = 0; row < mtx.rows; row++)
+ res.set(row, col, mtx.get(row, col) * scalar);
+
+ return res;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mtx
+ * @param {number} scalar
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrix.divideMatScal = function(mtx, scalar) {
+ /** @type {tcuMatrix.Matrix} */ var res = new tcuMatrix.Matrix(mtx.rows, mtx.cols);
+ for (var col = 0; col < mtx.cols; col++)
+ for (var row = 0; row < mtx.rows; row++)
+ res.set(row, col, mtx.get(row, col) / scalar);
+
+ return res;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuMatrix.Matrix}
+ */
+ tcuMatrix.Mat2 = function() {
+ tcuMatrix.Matrix.call(this, 2, 2);
+ };
+
+ tcuMatrix.Mat2.prototype = Object.create(tcuMatrix.Matrix.prototype);
+ tcuMatrix.Mat2.prototype.constructor = tcuMatrix.Mat2;
+
+ /**
+ * @constructor
+ * @extends {tcuMatrix.Matrix}
+ */
+ tcuMatrix.Mat3 = function() {
+ tcuMatrix.Matrix.call(this, 3, 3);
+ };
+
+ tcuMatrix.Mat3.prototype = Object.create(tcuMatrix.Matrix.prototype);
+ tcuMatrix.Mat3.prototype.constructor = tcuMatrix.Mat3;
+
+ /**
+ * @constructor
+ * @extends {tcuMatrix.Matrix}
+ */
+ tcuMatrix.Mat4 = function() {
+ tcuMatrix.Matrix.call(this, 4, 4);
+ };
+
+ tcuMatrix.Mat4.prototype = Object.create(tcuMatrix.Matrix.prototype);
+ tcuMatrix.Mat4.prototype.constructor = tcuMatrix.Mat4;
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrixUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrixUtil.js
new file mode 100644
index 0000000000..63dcaba871
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuMatrixUtil.js
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('framework.common.tcuMatrixUtil');
+goog.require('framework.common.tcuMatrix');
+
+goog.scope(function() {
+
+ var tcuMatrixUtil = framework.common.tcuMatrixUtil;
+ var tcuMatrix = framework.common.tcuMatrix;
+
+ /**
+ * @param {Array<number>} translation
+ * @return {tcuMatrix.Matrix}
+ */
+ tcuMatrixUtil.translationMatrix = function(translation) {
+ var len = translation.length;
+ var res = new tcuMatrix.Matrix(len + 1, len + 1);
+ for (var row = 0; row < len; row++)
+ res.set(row, len, translation[row]);
+ return res;
+ };
+
+ /**
+ * Flatten an array of arrays or matrices
+ * @param {(Array<Array<number>> | Array<tcuMatrix.Matrix>)} a
+ * @return {Array<number>}
+ */
+ tcuMatrixUtil.flatten = function(a) {
+ if (a[0] instanceof Array) {
+ var merged = [];
+ return merged.concat.apply(merged, a);
+ }
+
+ if (a[0] instanceof tcuMatrix.Matrix) {
+ /** @type {tcuMatrix.Matrix} */ var m = a[0];
+ var rows = m.rows;
+ var cols = m.cols;
+ var size = a.length;
+ var result = [];
+ for (var col = 0; col < cols; col++)
+ for (var i = 0; i < size; i++)
+ result.push(a[i].getColumn(col));
+ return [].concat.apply([], result);
+ }
+
+ if (typeof(a[0]) === 'number')
+ return a;
+
+ throw new Error('Invalid input');
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuPixelFormat.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuPixelFormat.js
new file mode 100644
index 0000000000..daf3297a93
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuPixelFormat.js
@@ -0,0 +1,79 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuPixelFormat');
+
+goog.scope(function() {
+
+var tcuPixelFormat = framework.common.tcuPixelFormat;
+
+/**
+ * @constructor
+ * @param {number=} r
+ * @param {number=} g
+ * @param {number=} b
+ * @param {number=} a
+ */
+tcuPixelFormat.PixelFormat = function(r, g, b, a) {
+ this.redBits = r || 0;
+ this.greenBits = g || 0;
+ this.blueBits = b || 0;
+ this.alphaBits = a || 0;
+};
+
+/**
+ * @param {WebGL2RenderingContext} context
+ * @return {tcuPixelFormat.PixelFormat}
+ */
+tcuPixelFormat.PixelFormatFromContext = function(context) {
+ var r = /** @type {number} */ (context.getParameter(gl.RED_BITS));
+ var g = /** @type {number} */ (context.getParameter(gl.GREEN_BITS));
+ var b = /** @type {number} */ (context.getParameter(gl.BLUE_BITS));
+ var a = /** @type {number} */ (context.getParameter(gl.ALPHA_BITS));
+
+ return new tcuPixelFormat.PixelFormat(r, g, b, a);
+};
+
+/**
+ * @param {number} r
+ * @param {number} g
+ * @param {number} b
+ * @param {number} a
+ * @return {boolean}
+ */
+tcuPixelFormat.PixelFormat.prototype.equals = function(r, g, b, a) {
+ return this.redBits === r &&
+ this.greenBits === g &&
+ this.blueBits === b &&
+ this.alphaBits === a;
+};
+
+/**
+ * @return {Array<number>}
+ */
+tcuPixelFormat.PixelFormat.prototype.getColorThreshold = function() {
+ return [1 << (8 - this.redBits),
+ 1 << (8 - this.greenBits),
+ 1 << (8 - this.blueBits),
+ (this.alphaBits > 0) ? (1 << (8 - this.alphaBits)) : 0];
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuRGBA.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuRGBA.js
new file mode 100644
index 0000000000..0bab841d1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuRGBA.js
@@ -0,0 +1,279 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuRGBA');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuRGBA = framework.common.tcuRGBA;
+var deMath = framework.delibs.debase.deMath;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * class tcuRGBA.RGBA
+ * @constructor
+ * @struct
+ * @param {goog.NumberArray=} value
+ */
+ tcuRGBA.RGBA = function(value) {
+ /** @type {goog.NumberArray} */ this.m_value = value || null;
+
+ };
+
+ /**
+ * @enum
+ * In JS, these are not shift values, but positions in a typed array
+ */
+ tcuRGBA.RGBA.Shift = {
+ RED: 0,
+ GREEN: 1,
+ BLUE: 2,
+ ALPHA: 3
+ };
+
+ /**
+ * @enum
+ * Mask used as flags
+ * Hopefully will not use typed arrays
+ */
+ tcuRGBA.RGBA.Mask = function() {
+ return {
+ RED: false,
+ GREEN: false,
+ BLUE: false,
+ ALPHA: false
+ };
+ };
+
+ /**
+ * Builds an tcuRGBA.RGBA object from color components
+ * @param {number} r
+ * @param {number} g
+ * @param {number} b
+ * @param {number} a
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.newRGBAComponents = function(r, g, b, a) {
+ DE_ASSERT(deMath.deInRange32(r, 0, 255));
+ DE_ASSERT(deMath.deInRange32(g, 0, 255));
+ DE_ASSERT(deMath.deInRange32(b, 0, 255));
+ DE_ASSERT(deMath.deInRange32(a, 0, 255));
+
+ return new tcuRGBA.RGBA([r, g, b, a]);
+ };
+
+ /**
+ * Builds an tcuRGBA.RGBA object from a number array
+ * @param {goog.NumberArray} v
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.newRGBAFromArray = function(v) {
+ return new tcuRGBA.RGBA(v.slice(0, 4));
+ };
+
+ /**
+ * @param {number} value
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.newRGBAFromValue = function(value) {
+ var rgba = new tcuRGBA.RGBA();
+ var array32 = new Uint32Array([value]);
+ rgba.m_value = (new Uint8Array(array32.buffer));
+ return rgba;
+ };
+
+ /**
+ * @param {Array<number>} v
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.newRGBAFromVec = function (v) {
+ var r = deMath.clamp(v[0] * 255.0, 0, 255);
+ var g = deMath.clamp(v[1] * 255.0, 0, 255);
+ var b = deMath.clamp(v[2] * 255.0, 0, 255);
+ var a = deMath.clamp(v[3] * 255.0, 0, 255);
+
+ return new tcuRGBA.RGBA([r, g, b, a]);
+ };
+
+ /**
+ * @param {number} v
+ */
+ tcuRGBA.RGBA.prototype.setRed = function(v) { DE_ASSERT(deMath.deInRange32(v, 0, 255)); this.m_value[tcuRGBA.RGBA.Shift.RED] = v; };
+
+ /**
+ * @param {number} v
+ */
+ tcuRGBA.RGBA.prototype.setGreen = function(v) { DE_ASSERT(deMath.deInRange32(v, 0, 255)); this.m_value[tcuRGBA.RGBA.Shift.GREEN] = v; };
+
+ /**
+ * @param {number} v
+ */
+ tcuRGBA.RGBA.prototype.setBlue = function(v) { DE_ASSERT(deMath.deInRange32(v, 0, 255)); this.m_value[tcuRGBA.RGBA.Shift.BLUE] = v; };
+
+ /**
+ * @param {number} v
+ */
+ tcuRGBA.RGBA.prototype.setAlpha = function(v) { DE_ASSERT(deMath.deInRange32(v, 0, 255)); this.m_value[tcuRGBA.RGBA.Shift.ALPHA] = v; };
+
+ /**
+ * @return {number}
+ */
+ tcuRGBA.RGBA.prototype.getRed = function() { return this.m_value[tcuRGBA.RGBA.Shift.RED]; };
+
+ /**
+ * @return {number}
+ */
+ tcuRGBA.RGBA.prototype.getGreen = function() { return this.m_value[tcuRGBA.RGBA.Shift.GREEN]; };
+
+ /**
+ * @return {number}
+ */
+ tcuRGBA.RGBA.prototype.getBlue = function() { return this.m_value[tcuRGBA.RGBA.Shift.BLUE]; };
+
+ /**
+ * @return {number}
+ */
+ tcuRGBA.RGBA.prototype.getAlpha = function() { return this.m_value[tcuRGBA.RGBA.Shift.ALPHA]; };
+
+ /**
+ * @param {tcuRGBA.RGBA} thr
+ * @return {boolean}
+ */
+ tcuRGBA.RGBA.prototype.isBelowThreshold = function(thr) { return (this.getRed() <= thr.getRed()) && (this.getGreen() <= thr.getGreen()) && (this.getBlue() <= thr.getBlue()) && (this.getAlpha() <= thr.getAlpha()); };
+
+ /**
+ * @param {Uint8Array} bytes
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.RGBA.fromBytes = function(bytes) { return tcuRGBA.newRGBAFromArray(bytes); };
+
+ /**
+ * @param {Uint8Array} bytes
+ */
+ tcuRGBA.RGBA.prototype.toBytes = function(bytes) { var result = new Uint8Array(this.m_value); bytes[0] = result[0]; bytes[1] = result[1]; bytes[2] = result[2]; bytes[3] = result[3]; };
+
+ /**
+ * @return {Array<number>}
+ */
+ tcuRGBA.RGBA.prototype.toVec = function() {
+ return [
+ this.getRed() / 255.0,
+ this.getGreen() / 255.0,
+ this.getBlue() / 255.0,
+ this.getAlpha() / 255.0
+ ];
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ tcuRGBA.RGBA.prototype.toIVec = function() {
+ return [
+ this.getRed(),
+ this.getGreen(),
+ this.getBlue(),
+ this.getAlpha()
+ ];
+ };
+
+ /**
+ * @param {tcuRGBA.RGBA} v
+ * @return {boolean}
+ */
+ tcuRGBA.RGBA.prototype.equals = function(v) {
+ return (
+ this.m_value[0] == v.m_value[0] &&
+ this.m_value[1] == v.m_value[1] &&
+ this.m_value[2] == v.m_value[2] &&
+ this.m_value[3] == v.m_value[3]
+ );
+ };
+
+ /**
+ * @param {tcuRGBA.RGBA} a
+ * @param {tcuRGBA.RGBA} b
+ * @param {tcuRGBA.RGBA} threshold
+ * @return {boolean}
+ */
+ tcuRGBA.compareThreshold = function(a, b, threshold) {
+ if (a.equals(b)) return true; // Quick-accept
+ return tcuRGBA.computeAbsDiff(a, b).isBelowThreshold(threshold);
+ };
+
+ /**
+ * @param {tcuRGBA.RGBA} a
+ * @param {tcuRGBA.RGBA} b
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.computeAbsDiff = function(a, b) {
+ return tcuRGBA.newRGBAComponents(
+ Math.abs(a.getRed() - b.getRed()),
+ Math.abs(a.getGreen() - b.getGreen()),
+ Math.abs(a.getBlue() - b.getBlue()),
+ Math.abs(a.getAlpha() - b.getAlpha())
+ );
+ };
+
+ /**
+ * @param {tcuRGBA.RGBA} a
+ * @param {number} b
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.multiply = function(a, b) {
+ return tcuRGBA.newRGBAComponents(
+ deMath.clamp(a.getRed() * b, 0, 255),
+ deMath.clamp(a.getGreen() * b, 0, 255),
+ deMath.clamp(a.getBlue() * b, 0, 255),
+ deMath.clamp(a.getAlpha() * b, 0, 255));
+ };
+
+ /**
+ * @param {tcuRGBA.RGBA} a
+ * @param {tcuRGBA.RGBA} b
+ * @return {tcuRGBA.RGBA}
+ */
+ tcuRGBA.max = function(a, b) {
+ return tcuRGBA.newRGBAComponents(
+ Math.max(a.getRed(), b.getRed()),
+ Math.max(a.getGreen(), b.getGreen()),
+ Math.max(a.getBlue(), b.getBlue()),
+ Math.max(a.getAlpha(), b.getAlpha())
+ );
+ };
+
+ tcuRGBA.RGBA.prototype.toString = function() {
+ return '[' + this.m_value[0] + ',' + this.m_value[1] + ',' + this.m_value[2] + ',' + this.m_value[3] + ']';
+ };
+
+ // Color constants
+ tcuRGBA.RGBA.red = tcuRGBA.newRGBAComponents(0xFF, 0, 0, 0xFF);
+ tcuRGBA.RGBA.green = tcuRGBA.newRGBAComponents(0, 0xFF, 0, 0xFF);
+ tcuRGBA.RGBA.blue = tcuRGBA.newRGBAComponents(0, 0, 0xFF, 0xFF);
+ tcuRGBA.RGBA.gray = tcuRGBA.newRGBAComponents(0x80, 0x80, 0x80, 0xFF);
+ tcuRGBA.RGBA.white = tcuRGBA.newRGBAComponents(0xFF, 0xFF, 0xFF, 0xFF);
+ tcuRGBA.RGBA.black = tcuRGBA.newRGBAComponents(0, 0, 0, 0xFF);
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSkipList.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSkipList.js
new file mode 100644
index 0000000000..286b1956be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSkipList.js
@@ -0,0 +1,245 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+/**
+ * This class defines the individual tests which are skipped because
+ * of graphics driver bugs which simply can not be worked around in
+ * WebGL 2.0 implementations.
+ *
+ * The intent is that this list be kept as small as possible; and that
+ * bugs are filed with the respective GPU vendors for entries in this
+ * list.
+ *
+ * Pass the query argument "runSkippedTests" in the URL in order to
+ * force the skipped tests to be run. So, for example:
+ *
+ * http://localhost:8080/sdk/tests/deqp/functional/gles3/transformfeedback.html?filter=transform_feedback.basic_types.separate.points&runSkippedTests
+ */
+'use strict';
+goog.provide('framework.common.tcuSkipList');
+
+goog.scope(function() {
+
+ var tcuSkipList = framework.common.tcuSkipList;
+
+ var _skipEntries = {};
+ var _wildcardSkipEntries = {};
+ var _reason = "";
+
+ function _setReason(reason) {
+ _reason = reason;
+ }
+
+ function _skip(testName) {
+ if(testName.indexOf("*") >= 0){
+ testName = testName.split("*")[0];
+ _wildcardSkipEntries[testName] = _reason;
+ }else{
+ _skipEntries[testName] = _reason;
+ }
+ }
+
+ var runSkippedTests = false;
+ var queryVars = window.location.search.substring(1).split('&');
+ for (var i = 0; i < queryVars.length; i++) {
+ var value = queryVars[i].split('=');
+ if (decodeURIComponent(value[0]) === 'runSkippedTests') {
+ // Assume that presence of this query arg implies to run
+ // the skipped tests; the value is ignored.
+ runSkippedTests = true;
+ break;
+ }
+ }
+
+ if (!runSkippedTests) {
+ // Example usage:
+ //
+ // _setReason("Bugs in FooVendor 30.03 driver");
+ // _skip("transform_feedback.basic_types.separate.points.lowp_mat2");
+
+ // Please see https://android.googlesource.com/platform/external/deqp/+/7c5323116bb164d64bfecb68e8da1af634317b24
+ _setReason("Native dEQP also fails on these tests and suppresses them");
+ _skip("texture_functions.textureoffset.sampler3d_fixed_fragment");
+ _skip("texture_functions.textureoffset.isampler3d_fragment");
+ _skip("texture_functions.textureoffset.usampler3d_fragment");
+ _skip("texture_functions.textureprojoffset.sampler3d_fixed_fragment");
+ _skip("texture_functions.textureprojoffset.isampler3d_fragment");
+ _skip("texture_functions.textureprojoffset.usampler3d_fragment");
+ // Please see https://android.googlesource.com/platform/external/deqp/+/master/android/cts/master/src/gles3-hw-issues.txt
+ _skip("texture_functions.textureprojlod.isampler3d_vertex");
+ _skip("texture_functions.textureprojlod.usampler3d_vertex");
+ // Please see https://android.googlesource.com/platform/external/deqp/+/master/android/cts/master/src/gles3-test-issues.txt
+ _skip("texture_functions.textureprojlodoffset.usampler3d_vertex");
+ _skip("texture_functions.textureoffset.sampler3d_float_fragment");
+ _skip("texture_functions.textureprojoffset.sampler3d_float_fragment");
+ // Please see https://android.googlesource.com/platform/external/deqp/+/master/android/cts/master/src/gles3-driver-issues.txt
+ _skip("texture_functions.textureprojlodoffset.isampler3d_vertex");
+ _skip("texture_functions.texturegrad.samplercubeshadow*");
+ // Please see https://android.googlesource.com/platform/external/deqp/+/40ff528%5E%21/
+ // and https://bugs.chromium.org/p/angleproject/issues/detail?id=3094
+ _skip("texture_functions.texturelodoffset.sampler3d_float_vertex");
+
+ // https://android.googlesource.com/platform/external/deqp/+/0c1f83aee4709eef7ef2a3edd384f9c192f476fd/android/cts/master/src/gles3-hw-issues.txt#801
+ _setReason("Tricky blit rects can result in imperfect copies on some HW.");
+ _skip("blit.rect.nearest_consistency_mag");
+ _skip("blit.rect.nearest_consistency_mag_reverse_dst_x");
+ _skip("blit.rect.nearest_consistency_mag_reverse_src_dst_x");
+ _skip("blit.rect.nearest_consistency_mag_reverse_src_x");
+ _skip("blit.rect.nearest_consistency_mag_reverse_src_y");
+ _skip("blit.rect.nearest_consistency_min");
+ _skip("blit.rect.nearest_consistency_min_reverse_dst_x");
+ _skip("blit.rect.nearest_consistency_min_reverse_src_dst_x");
+ _skip("blit.rect.nearest_consistency_min_reverse_src_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag_reverse_dst_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag_reverse_src_dst_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag_reverse_src_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag_reverse_src_y");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_dst_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_src_dst_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_src_x");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_src_y");
+
+ // https://android.googlesource.com/platform/external/deqp/+/0c1f83aee4709eef7ef2a3edd384f9c192f476fd/android/cts/master/src/gles3-driver-issues.txt#381
+ _setReason("Tricky blit rects can result in imperfect copies on some drivers.");
+ _skip("blit.rect.out_of_bounds_linear");
+ _skip("blit.rect.out_of_bounds_reverse_src_x_linear");
+ _skip("blit.rect.out_of_bounds_reverse_src_y_linear");
+ _skip("blit.rect.out_of_bounds_reverse_dst_x_linear");
+ _skip("blit.rect.out_of_bounds_reverse_dst_y_linear");
+ _skip("blit.rect.out_of_bounds_reverse_src_dst_x_linear");
+ _skip("blit.rect.out_of_bounds_reverse_src_dst_y_linear");
+
+ // https://android.googlesource.com/platform/external/deqp/+/0c1f83aee4709eef7ef2a3edd384f9c192f476fd/android/cts/master/src/gles3-driver-issues.txt#368
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag_reverse_dst_y");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_mag_reverse_src_dst_y");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_dst_y");
+ _skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_src_dst_y");
+
+ _setReason("Missing shadow sampler functions in D3D11");
+ // https://github.com/KhronosGroup/WebGL/issues/1870
+ // deqp/functional/gles3/shadertexturefunction/texture.html
+ _skip("texture_functions.texture.sampler2darrayshadow_vertex");
+ // deqp/functional/gles3/shadertexturefunction/texturelod.html
+ _skip("texture_functions.texturelod.sampler2dshadow_vertex");
+ _skip("texture_functions.texturelod.sampler2dshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/texturelodoffset.html
+ _skip("texture_functions.texturelodoffset.sampler2dshadow_vertex");
+ _skip("texture_functions.texturelodoffset.sampler2dshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/textureprojlod.html
+ _skip("texture_functions.textureprojlod.sampler2dshadow_vertex");
+ _skip("texture_functions.textureprojlod.sampler2dshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/textureprojlodoffset.html
+ _skip("texture_functions.textureprojlodoffset.sampler2dshadow_vertex");
+ _skip("texture_functions.textureprojlodoffset.sampler2dshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/texturegrad.html
+ _skip("texture_functions.texturegrad.sampler2dshadow_vertex");
+ _skip("texture_functions.texturegrad.sampler2dshadow_fragment");
+ _skip("texture_functions.texturegrad.sampler2darrayshadow_vertex");
+ _skip("texture_functions.texturegrad.sampler2darrayshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/texturegradoffset.html
+ _skip("texture_functions.texturegradoffset.sampler2dshadow_vertex");
+ _skip("texture_functions.texturegradoffset.sampler2dshadow_fragment");
+ _skip("texture_functions.texturegradoffset.sampler2darrayshadow_vertex");
+ _skip("texture_functions.texturegradoffset.sampler2darrayshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/textureprojgrad.html
+ _skip("texture_functions.textureprojgrad.sampler2dshadow_vertex");
+ _skip("texture_functions.textureprojgrad.sampler2dshadow_fragment");
+ // deqp/functional/gles3/shadertexturefunction/textureprojgradoffset.html
+ _skip("texture_functions.textureprojgradoffset.sampler2dshadow_vertex");
+ _skip("texture_functions.textureprojgradoffset.sampler2dshadow_fragment");
+
+ _setReason("MacOSX drivers share namespaces where they should not");
+ // https://github.com/KhronosGroup/WebGL/issues/1890
+ // deqp/data/gles3/shaders/scoping.html
+ _skip("scoping.valid.local_int_variable_hides_struct_type_vertex");
+ _skip("scoping.valid.local_int_variable_hides_struct_type_fragment");
+ _skip("scoping.valid.local_struct_variable_hides_struct_type_vertex");
+ _skip("scoping.valid.local_struct_variable_hides_struct_type_fragment");
+ _skip("scoping.valid.function_parameter_hides_struct_type_vertex");
+ _skip("scoping.valid.function_parameter_hides_struct_type_fragment");
+
+ _setReason("NVidia Linux drivers does not clamp gl_FragDepth to [0.0, 1.0]");
+ // Standalone Test case:
+ // https://github.com/Kangz/GLDriverBugs/blob/master/frag_depth_clamp_32f_depth/Main.cpp
+ // deqp/functional/gles3/fbodepthbuffer.html
+ _skip("depth.depth_write_clamp.depth_component32f");
+ _skip("depth.depth_write_clamp.depth32f_stencil8");
+ _skip("depth.depth_test_clamp.depth_component32f");
+ _skip("depth.depth_test_clamp.depth32f_stencil8");
+
+ _setReason("NVidia Linux driver bug in nested uniform block location assignment");
+ // crbug.com/621178
+ // deqp/functional/gles3/uniformapi/random.html
+ _skip("uniform_api.random.64");
+
+ _setReason("Mac AMD / Linux AMD / older mesa handles clipping of wide points incorrectly");
+ // crbug.com/642822
+ // deqp/functional/gles3/clipping.html
+ _skip("clipping.wide_points_full_viewport");
+ _skip("clipping.wide_points_partial_viewport");
+
+ _setReason("Some Windows AMD D3D11 drivers have issues with blit and depth/stencil formats.");
+ // crbug.com/638323
+ // deqp/functional/gles3/framebufferblit/depth_stencil.html
+ // Also see conformance2/rendering/blitframebuffer-stencil-only.html for 2.0.1 test.
+ _skip("blit.depth_stencil.depth24_stencil8_scale");
+ _skip("blit.depth_stencil.depth24_stencil8_stencil_only");
+
+ _setReason("Removed from native dEQP mustpass. Not passable on Adreno.");
+ // These tests have been skipped in native dEQP since 2015:
+ // https://android.googlesource.com/platform/external/deqp/+/ea026b329e6bf73f109cda914c90f08d5f7a5b8d
+ // They do not pass on Android/Qualcomm (Google Pixel 1, Pixel 3).
+ // It's not clear if the tests or the hardware are out-of-spec, but there's nothing we can do about it right now.
+ // See also: crbug.com/695679
+ _skip("derivate.dfdy.fbo_float.float_highp");
+ _skip("derivate.dfdy.fbo_float.vec2_highp");
+ _skip("derivate.dfdy.fbo_float.vec3_highp");
+ _skip("derivate.dfdy.fbo_float.vec4_highp");
+ _skip("derivate.dfdy.nicest.fbo_float.float_highp");
+ _skip("derivate.dfdy.nicest.fbo_float.vec2_highp");
+ _skip("derivate.dfdy.nicest.fbo_float.vec3_highp");
+ _skip("derivate.dfdy.nicest.fbo_float.vec4_highp");
+ _skip("derivate.dfdy.fastest.fbo_float.float_highp");
+ _skip("derivate.dfdy.fastest.fbo_float.vec2_highp");
+ _skip("derivate.dfdy.fastest.fbo_float.vec3_highp");
+ _skip("derivate.dfdy.fastest.fbo_float.vec4_highp");
+ } // if (!runSkippedTests)
+
+ /*
+ * Gets the skip status of the given test. Returns an
+ * object with the properties "skip", a boolean, and "reason", a
+ * string.
+ */
+ tcuSkipList.getSkipStatus = function(testName) {
+ var skipEntry = _skipEntries[testName];
+ if (skipEntry === undefined) {
+ return this._getWildcardSkipStatus(testName);
+ } else {
+ return { 'skip': true, 'reason': skipEntry };
+ }
+ }
+
+ /*
+ * Gets the skip status of the given tests like testpath*
+ * object with the properties "skip", a boolean, and "reason", a
+ * string.
+ */
+ tcuSkipList._getWildcardSkipStatus = function(testName) {
+ var skipEntry;
+ for (var key in _wildcardSkipEntries) {
+ if (testName.indexOf(key) >=0 ) {
+ skipEntry = _wildcardSkipEntries[key];
+ if (skipEntry != undefined) {
+ return { 'skip': true, 'reason': skipEntry };
+ }
+ }
+ }
+ return { 'skip': false, 'reason': '' };
+ }
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuStringTemplate.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuStringTemplate.js
new file mode 100644
index 0000000000..d70056733b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuStringTemplate.js
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuStringTemplate');
+
+goog.scope(function() {
+
+var tcuStringTemplate = framework.common.tcuStringTemplate;
+
+tcuStringTemplate.escapeRegExp = function(string) {
+ return string.replace(/([.*+?^=!:$ {}()|\[\]\/\\])/g, '\\$1');
+};
+
+tcuStringTemplate.specialize = function(str, params) {
+ var dst = str;
+ for (var key in params) {
+ var value = params[key];
+ var re = new RegExp(tcuStringTemplate.escapeRegExp('\$\{' + key + '\}'), 'g');
+ dst = dst.replace(re, value);
+ }
+ return dst;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSurface.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSurface.js
new file mode 100644
index 0000000000..47d3634aad
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuSurface.js
@@ -0,0 +1,184 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var tcuSurface = framework.common.tcuSurface;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/**
+ * \brief RGBA8888 surface
+ *
+ * tcuSurface.Surface provides basic pixel storage functionality. Only single format
+ * (RGBA8888) is supported.
+ *
+ * PixelBufferAccess (see tcuTexture.h) provides much more flexible API
+ * for handling various pixel formats. This is mainly a convinience class.
+ * @constructor
+ * @param {number=} width
+ * @param {number=} height
+ */
+tcuSurface.Surface = function(width, height) {
+ width = width || 0;
+ height = height || 0;
+ this.setSize(width, height);
+};
+
+/**
+ * @param {number} width
+ * @param {number} height
+ */
+tcuSurface.Surface.prototype.setSize = function(width, height) {
+ this.m_width = width;
+ this.m_height = height;
+ if (width * height > 0) {
+ this.m_data = new ArrayBuffer(4 * width * height);
+ this.m_pixels = new Uint8Array(this.m_data);
+ } else {
+ this.m_data = null;
+ this.m_pixels = null;
+ }
+};
+
+/**
+ * @return {number}
+ */
+tcuSurface.Surface.prototype.getWidth = function() { return this.m_width; };
+
+/**
+ * @return {number}
+ */
+tcuSurface.Surface.prototype.getHeight = function() { return this.m_height; };
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {Array<number>} color Vec4 color
+ */
+tcuSurface.Surface.prototype.setPixel = function(x, y, color) {
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+
+ var offset = 4 * (x + y * this.m_width);
+ for (var i = 0; i < 4; i++)
+ this.m_pixels[offset + i] = color[i];
+};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {Array<number>}
+ */
+tcuSurface.Surface.prototype.getPixel = function(x, y) {
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+
+ var color = [];
+ color.length = 4;
+
+ var offset = 4 * (x + y * this.m_width);
+ for (var i = 0; i < 4; i++)
+ color[i] = this.m_pixels[offset + i];
+
+ return color;
+};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+tcuSurface.Surface.prototype.getPixelUintRGB8 = function(x, y) {
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+
+ var offset = 4 * (x + y * this.m_width);
+ return (this.m_pixels[offset] << 16) +
+ (this.m_pixels[offset + 1] << 8) +
+ this.m_pixels[offset + 2];
+};
+
+/**
+ * Read the viewport contents into this surface
+ * @param {*=} ctx WebGL or ref context
+ * @param {(Array<number>|{x: number, y: number, width: number, height: number})=} view
+ */
+tcuSurface.Surface.prototype.readViewport = function(ctx, view) {
+ ctx = ctx || gl;
+ var v = view || /** @type {Array<number>} */ (ctx.getParameter(gl.VIEWPORT));
+ /** @type {number} */ var x;
+ /** @type {number} */ var y;
+ /** @type {number} */ var width;
+ /** @type {number} */ var height;
+ if (v instanceof Array || ArrayBuffer.isView(v)) {
+ x = v[0];
+ y = v[1];
+ width = v[2];
+ height = v[3];
+ } else {
+ x = v.x;
+ y = v.y;
+ width = v.width;
+ height = v.height;
+ }
+ if (width != this.m_width || height != this.m_height)
+ this.setSize(width, height);
+ ctx.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, this.m_pixels);
+};
+
+/**
+ * @return {Uint8Array}
+ */
+tcuSurface.Surface.prototype.getPixels = function() { return this.m_pixels || null; };
+
+/**
+ * @return {tcuTexture.PixelBufferAccess} Pixel Buffer Access object
+ */
+tcuSurface.Surface.prototype.getAccess = function() {
+ return new tcuTexture.PixelBufferAccess({
+ format: new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8),
+ width: this.m_width,
+ height: this.m_height,
+ data: this.m_data
+ });
+
+};
+
+tcuSurface.Surface.prototype.getSubAccess = function(x, y, width, height) {
+ /* TODO: Implement. the deqp getSubAccess() looks broken. It will probably fail if
+ * x != 0 or width != m_width
+ */
+ throw new Error('Unimplemented');
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTestCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTestCase.js
new file mode 100644
index 0000000000..ec08eea5ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTestCase.js
@@ -0,0 +1,491 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This class allows one to create a hierarchy of tests and iterate over them.
+ * It replaces TestCase and TestCaseGroup classes.
+ */
+'use strict';
+goog.provide('framework.common.tcuTestCase');
+goog.require('framework.common.tcuSkipList');
+
+goog.scope(function() {
+
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSkipList = framework.common.tcuSkipList;
+
+ tcuTestCase.getQueryVal = function(key) {
+ const queryVars = window.location.search.substring(1).split('&');
+ for (let kv of queryVars) {
+ kv = kv.split('=');
+ if (decodeURIComponent(kv[0]) === key)
+ return decodeURIComponent(kv[1]);
+ }
+ return null;
+ };
+
+ tcuTestCase.isQuickMode = () => tcuTestCase.getQueryVal('quick') === '1';
+ tcuTestCase.isQuietMode = () => tcuTestCase.getQueryVal('quiet') === '1';
+
+ /**
+ * Reads the filter parameter from the URL to filter tests.
+ * @return {?string }
+ */
+ tcuTestCase.getFilter = () => tcuTestCase.getQueryVal('filter');
+
+ /**
+ * Indicates the state of an iteration operation.
+ * @enum {number}
+ */
+ tcuTestCase.IterateResult = {
+ STOP: 0,
+ CONTINUE: 1
+ };
+
+ /****************************************
+ * Runner
+ ***************************************/
+
+ /**
+ * A simple state machine.
+ * The purpose of this this object is to break
+ * long tests into small chunks that won't cause a timeout
+ * @constructor
+ */
+ tcuTestCase.Runner = function() {
+ /** @type {tcuTestCase.DeqpTest} */ this.currentTest = null;
+ /** @type {tcuTestCase.DeqpTest} */ this.nextTest = null;
+ /** @type {tcuTestCase.DeqpTest} */ this.testCases = null;
+ /** @type {?string } */ this.filter = tcuTestCase.getFilter();
+ };
+
+ /**
+ * @param {tcuTestCase.DeqpTest} root The root test of the test tree.
+ */
+ tcuTestCase.Runner.prototype.setRoot = function(root) {
+ this.currentTest = null;
+ this.testCases = root;
+ };
+
+ tcuTestCase.Runner.prototype.setRange = function(range) {
+ this.range = range;
+ };
+
+ /**
+ * Searches the test tree for the next executable test
+ * @return {?tcuTestCase.DeqpTest }
+ */
+ tcuTestCase.Runner.prototype.next = function() {
+
+ // First time? Use root test
+ if (!this.currentTest) {
+ this.currentTest = this.testCases;
+
+ // Root is executable? Use it
+ if (this.currentTest.isExecutable())
+ return this.currentTest;
+ }
+
+ // Should we proceed with the next test?
+ if (tcuTestCase.lastResult == tcuTestCase.IterateResult.STOP) {
+ // Look for next executable test
+ do {
+ if (this.range)
+ this.currentTest = this.currentTest.nextInRange(this.filter, this.range);
+ else
+ this.currentTest = this.currentTest.next(this.filter);
+ } while (this.currentTest && !this.currentTest.isExecutable());
+ }
+
+ return this.currentTest;
+ };
+
+ /**
+ * Schedule the callback to be run ASAP
+ * @param {function()} callback Callback to schedule
+ */
+ tcuTestCase.Runner.prototype.runCallback = function(callback) {
+ setTimeout(function() {
+ callback();
+ }.bind(this), 0);
+ };
+
+ /**
+ * Call this function at the end of the test
+ */
+ tcuTestCase.Runner.prototype.terminate = function() {
+ finishTest();
+ if (!tcuTestCase.isQuietMode()) {
+ console.log('finishTest() after (in ms):', performance.now());
+ }
+ };
+
+ tcuTestCase.runner = new tcuTestCase.Runner();
+
+ /** @type {tcuTestCase.IterateResult} */ tcuTestCase.lastResult = tcuTestCase.IterateResult.STOP;
+
+ /***************************************
+ * DeqpTest
+ ***************************************/
+
+ /**
+ * Assigns name, description and specification to test
+ * @constructor
+ * @param {?string} name
+ * @param {?string} description
+ * @param {Object=} spec
+ */
+ tcuTestCase.DeqpTest = function(name, description, spec) {
+ this.name = name || '';
+ this.description = description || '';
+ this.spec = spec;
+ this.currentTestNdx = 0;
+ this.parentTest = null;
+ this.childrenTests = [];
+ this.executeAlways = false;
+ };
+
+ /**
+ * Abstract init function(each particular test will implement it, or not)
+ */
+ tcuTestCase.DeqpTest.prototype.init = function() {};
+
+ /**
+ * Abstract deinit function(each particular test will implement it, or not)
+ */
+ tcuTestCase.DeqpTest.prototype.deinit = function() {};
+
+ /**
+ * Abstract iterate function(each particular test will implement it, or not)
+ * @return {tcuTestCase.IterateResult}
+ */
+ tcuTestCase.DeqpTest.prototype.iterate = function() { return tcuTestCase.IterateResult.STOP; };
+
+ /**
+ * Checks if the test is executable
+ * @return {boolean}
+ */
+ tcuTestCase.DeqpTest.prototype.isExecutable = function() {
+ return this.childrenTests.length == 0 || this.executeAlways;
+ };
+
+ /**
+ * Checks if the test is a leaf
+ */
+ tcuTestCase.DeqpTest.prototype.isLeaf = function() {
+ return this.childrenTests.length == 0;
+ };
+
+ /**
+ * Marks the test as always executable
+ */
+ tcuTestCase.DeqpTest.prototype.makeExecutable = function() {
+ this.executeAlways = true;
+ };
+
+ /**
+ * Adds a child test to the test's children
+ * @param {tcuTestCase.DeqpTest} test
+ */
+ tcuTestCase.DeqpTest.prototype.addChild = function(test) {
+ test.parentTest = this;
+ this.childrenTests.push(test);
+ };
+
+ /**
+ * Sets the whole children tests array
+ * @param {Array<tcuTestCase.DeqpTest>} tests
+ */
+ tcuTestCase.DeqpTest.prototype.setChildren = function(tests) {
+ for (var test in tests)
+ tests[test].parentTest = this;
+ this.childrenTests = tests;
+ };
+
+ /**
+ * Returns the next test in the hierarchy of tests
+ *
+ * @param {?string } pattern Optional pattern to search for
+ * @return {tcuTestCase.DeqpTest}
+ */
+ tcuTestCase.DeqpTest.prototype.next = function(pattern) {
+ return this._nextHonoringSkipList(pattern);
+ };
+
+ /**
+ * Returns the next test in the hierarchy of tests, honoring the
+ * skip list, and reporting skipped tests.
+ *
+ * @param {?string } pattern Optional pattern to search for
+ * @return {tcuTestCase.DeqpTest}
+ */
+ tcuTestCase.DeqpTest.prototype._nextHonoringSkipList = function(pattern) {
+ var tryAgain = false;
+ var test = null;
+ do {
+ tryAgain = false;
+ test = this._nextIgnoringSkipList(pattern);
+ if (test != null) {
+ // See whether the skip list vetoes the execution of
+ // this test.
+ var fullTestName = test.fullName();
+ var skipDisposition = tcuSkipList.getSkipStatus(fullTestName);
+ if (skipDisposition.skip) {
+ tryAgain = true;
+ setCurrentTestName(fullTestName);
+ checkMessage(false, 'Skipping test due to tcuSkipList: ' + fullTestName);
+ }
+ }
+ } while (tryAgain);
+ return test;
+ };
+
+
+ /**
+ * Returns the next test in the hierarchy of tests, ignoring the
+ * skip list.
+ *
+ * @param {?string } pattern Optional pattern to search for
+ * @return {tcuTestCase.DeqpTest}
+ */
+ tcuTestCase.DeqpTest.prototype._nextIgnoringSkipList = function(pattern) {
+ if (pattern)
+ return this._findIgnoringSkipList(pattern);
+
+ var test = null;
+
+ //Look for the next child
+ if (this.currentTestNdx < this.childrenTests.length) {
+ test = this.childrenTests[this.currentTestNdx];
+ this.currentTestNdx++;
+ }
+
+ // If no more children, get the next brother
+ if (test == null && this.parentTest != null) {
+ test = this.parentTest._nextIgnoringSkipList(null);
+ }
+
+ return test;
+ };
+
+ /**
+ * Returns the next test in the hierarchy of tests
+ * whose 1st level is in the given range
+ *
+ * @param {?string } pattern Optional pattern to search for
+ * @param {Array<number>} range
+ * @return {tcuTestCase.DeqpTest}
+ */
+ tcuTestCase.DeqpTest.prototype.nextInRange = function(pattern, range) {
+ while (true) {
+ var test = this._nextHonoringSkipList(pattern);
+ if (!test)
+ return null;
+ var topLevelId = tcuTestCase.runner.testCases.currentTestNdx - 1;
+ if (topLevelId >= range[0] && topLevelId < range[1])
+ return test;
+ }
+ };
+
+ /**
+ * Returns the full name of the test
+ *
+ * @return {string} Full test name.
+ */
+ tcuTestCase.DeqpTest.prototype.fullName = function() {
+ if (this.parentTest) {
+ var parentName = this.parentTest.fullName();
+ if (parentName)
+ return parentName + '.' + this.name;
+ }
+ return this.name;
+ };
+
+ /**
+ * Returns the description of the test
+ *
+ * @return {string} Test description.
+ */
+ tcuTestCase.DeqpTest.prototype.getDescription = function() {
+ return this.description;
+ };
+
+ /**
+ * Find a test with a matching name. Fast-forwards to a test whose
+ * full name matches the given pattern.
+ *
+ * @param {string} pattern Regular expression to search for
+ * @return {?tcuTestCase.DeqpTest } Found test or null.
+ */
+ tcuTestCase.DeqpTest.prototype.find = function(pattern) {
+ return this._findHonoringSkipList(pattern);
+ };
+
+ /**
+ * Find a test with a matching name. Fast-forwards to a test whose
+ * full name matches the given pattern, honoring the skip list, and
+ * reporting skipped tests.
+ *
+ * @param {string} pattern Regular expression to search for
+ * @return {?tcuTestCase.DeqpTest } Found test or null.
+ */
+ tcuTestCase.DeqpTest.prototype._findHonoringSkipList = function(pattern) {
+ var tryAgain = false;
+ var test = null;
+ do {
+ tryAgain = false;
+ test = this._findIgnoringSkipList(pattern);
+ if (test != null) {
+ // See whether the skip list vetoes the execution of
+ // this test.
+ var fullTestName = test.fullName();
+ var skipDisposition = tcuSkipList.getSkipStatus(fullTestName);
+ if (skipDisposition.skip) {
+ tryAgain = true;
+ checkMessage(false, 'Skipping test due to tcuSkipList: ' + fullTestName);
+ }
+ }
+ } while (tryAgain);
+ return test;
+ };
+
+ /**
+ * Find a test with a matching name. Fast-forwards to a test whose
+ * full name matches the given pattern.
+ *
+ * @param {string} pattern Regular expression to search for
+ * @return {?tcuTestCase.DeqpTest } Found test or null.
+ */
+ tcuTestCase.DeqpTest.prototype._findIgnoringSkipList = function(pattern) {
+ var test = this;
+ while (true) {
+ test = test._nextIgnoringSkipList(null);
+ if (!test)
+ break;
+ if (test.fullName().match(pattern) || test.executeAlways)
+ break;
+ }
+ return test;
+ };
+
+ /**
+ * Reset the iterator.
+ */
+ tcuTestCase.DeqpTest.prototype.reset = function() {
+ this.currentTestNdx = 0;
+
+ for (var i = 0; i < this.childrenTests.length; i++)
+ this.childrenTests[i].reset();
+ };
+
+ /**
+ * Defines a new test
+ *
+ * @param {?string} name Short test name
+ * @param {?string} description Description of the test
+ * @param {Object=} spec Test specification
+ *
+ * @return {tcuTestCase.DeqpTest} The new test
+ */
+ tcuTestCase.newTest = function(name, description, spec) {
+ var test = new tcuTestCase.DeqpTest(name, description, spec);
+
+ return test;
+ };
+
+ /**
+ * Defines a new executable test so it gets run even if it's not a leaf
+ *
+ * @param {string} name Short test name
+ * @param {string} description Description of the test
+ * @param {Object=} spec Test specification
+ *
+ * @return {tcuTestCase.DeqpTest} The new test
+ */
+ tcuTestCase.newExecutableTest = function(name, description, spec) {
+ var test = tcuTestCase.newTest(name, description, spec);
+ test.makeExecutable();
+
+ return test;
+ };
+
+ /**
+ * Run through the test cases giving time to system operation.
+ */
+ tcuTestCase.runTestCases = function() {
+ var state = tcuTestCase.runner;
+
+ if (state.next()) {
+ try {
+ // If proceeding with the next test, prepare it.
+ var fullTestName = state.currentTest.fullName();
+ var inited = true;
+ if (tcuTestCase.lastResult == tcuTestCase.IterateResult.STOP) {
+ // Update current test name
+ setCurrentTestName(fullTestName);
+ bufferedLogToConsole('Init testcase: ' + fullTestName); //Show also in console so we can see which test crashed the browser's tab
+
+ // Initialize particular test
+ inited = state.currentTest.init();
+ inited = inited === undefined ? true : inited;
+
+ //If it's a leaf test, notify of it's execution.
+ if (state.currentTest.isLeaf() && inited)
+ debug('<hr/><br/>Start testcase: ' + fullTestName);
+ }
+
+ if (inited) {
+ // Run the test, save the result.
+ tcuTestCase.lastResult = state.currentTest.iterate();
+ } else {
+ // Skip uninitialized test.
+ tcuTestCase.lastResult = tcuTestCase.IterateResult.STOP;
+ }
+
+ // Cleanup
+ if (tcuTestCase.lastResult == tcuTestCase.IterateResult.STOP)
+ state.currentTest.deinit();
+ }
+ catch (err) {
+ // If the exception was not thrown by a test check, log it, but don't throw it again
+ if (!(err instanceof TestFailedException)) {
+ //Stop execution of current test.
+ tcuTestCase.lastResult = tcuTestCase.IterateResult.STOP;
+ try {
+ // Cleanup
+ if (tcuTestCase.lastResult == tcuTestCase.IterateResult.STOP)
+ state.currentTest.deinit();
+ } catch (cerr) {
+ bufferedLogToConsole('Error while cleaning up test: ' + cerr);
+ }
+ var msg = err;
+ if (err.message)
+ msg = err.message;
+ testFailedOptions(msg, false);
+ }
+ bufferedLogToConsole(err);
+ }
+
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } else
+ tcuTestCase.runner.terminate();
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexCompareVerifier.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexCompareVerifier.js
new file mode 100644
index 0000000000..254963ae66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexCompareVerifier.js
@@ -0,0 +1,1356 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuTexCompareVerifier');
+goog.require('framework.common.tcuTexVerifierUtil');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuTexVerifierUtil = framework.common.tcuTexVerifierUtil;
+
+/**
+ * \brief Texture compare (shadow) lookup precision parameters.
+ * @constructor
+ * @struct
+ * @param {Array<number>=} coordBits
+ * @param {Array<number>=} uvwBits
+ * @param {number=} pcfBits
+ * @param {number=} referenceBits
+ * @param {number=} resultBits
+ */
+tcuTexCompareVerifier.TexComparePrecision = function(coordBits, uvwBits, pcfBits, referenceBits, resultBits) {
+ this.coordBits = coordBits === undefined ? [22, 22, 22] : coordBits;
+ this.uvwBits = uvwBits === undefined ? [22, 22, 22] : uvwBits;
+ this.pcfBits = pcfBits === undefined ? 16 : pcfBits;
+ this.referenceBits = referenceBits === undefined ? 16 : referenceBits;
+ this.resultBits = resultBits === undefined ? 16 : resultBits;
+};
+
+/**
+ * @constructor
+ * @struct
+ */
+tcuTexCompareVerifier.CmpResultSet = function() {
+ this.isTrue = false;
+ this.isFalse = false;
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {number} cmpValue_
+ * @param {number} cmpReference_
+ * @param {number} referenceBits
+ * @param {boolean} isFixedPoint
+ * @return {tcuTexCompareVerifier.CmpResultSet}
+ */
+tcuTexCompareVerifier.execCompare = function(compareMode,
+ cmpValue_,
+ cmpReference_,
+ referenceBits,
+ isFixedPoint) {
+ var clampValues = isFixedPoint; // if comparing against a floating point texture, ref (and value) is not clamped
+ var cmpValue = (clampValues) ? (deMath.clamp(cmpValue_, 0, 1)) : (cmpValue_);
+ var cmpReference = (clampValues) ? (deMath.clamp(cmpReference_, 0, 1)) : (cmpReference_);
+ var err = tcuTexVerifierUtil.computeFixedPointError(referenceBits);
+ var res = new tcuTexCompareVerifier.CmpResultSet();
+
+ switch (compareMode) {
+ case tcuTexture.CompareMode.COMPAREMODE_LESS:
+ res.isTrue = cmpReference - err < cmpValue;
+ res.isFalse = cmpReference + err >= cmpValue;
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_LESS_OR_EQUAL:
+ res.isTrue = cmpReference - err <= cmpValue;
+ res.isFalse = cmpReference + err > cmpValue;
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_GREATER:
+ res.isTrue = cmpReference + err > cmpValue;
+ res.isFalse = cmpReference - err <= cmpValue;
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_GREATER_OR_EQUAL:
+ res.isTrue = cmpReference + err >= cmpValue;
+ res.isFalse = cmpReference - err < cmpValue;
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_EQUAL:
+ res.isTrue = deMath.deInRange32(cmpValue, cmpReference - err, cmpReference + err);
+ res.isFalse = err != 0 || cmpValue != cmpReference;
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_NOT_EQUAL:
+ res.isTrue = err != 0 || cmpValue != cmpReference;
+ res.isFalse = deMath.deInRange32(cmpValue, cmpReference - err, cmpReference + err);
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_ALWAYS:
+ res.isTrue = true;
+ break;
+
+ case tcuTexture.CompareMode.COMPAREMODE_NEVER:
+ res.isFalse = true;
+ break;
+
+ default:
+ throw new Error('Invalid compare mode:' + compareMode);
+ }
+
+ assertMsgOptions(res.isTrue || res.isFalse, 'Both tests failed!', false, true);
+ return res;
+};
+
+/**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isFixedPointDepthTextureFormat = function(format) {
+ var channelClass = tcuTexture.getTextureChannelClass(format.type);
+
+ if (format.order == tcuTexture.ChannelOrder.D) {
+ // depth internal formats cannot be non-normalized integers
+ return channelClass != tcuTexture.TextureChannelClass.FLOATING_POINT;
+ } else if (format.order == tcuTexture.ChannelOrder.DS) {
+ // combined formats have no single channel class, detect format manually
+ switch (format.type) {
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return false;
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return true;
+
+ default:
+ throw new Error('Invalid texture format: ' + format);
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths
+ * @param {Array<number>} fBounds
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isLinearCompareValid = function(compareMode, prec, depths, fBounds, cmpReference, result, isFixedPointDepth) {
+ assertMsgOptions(fBounds[0] >= 0 && fBounds[0] <= fBounds[1] && fBounds[1] <= 1, 'Invalid fBounds', false, true);
+
+ var d0 = depths[0];
+ var d1 = depths[1];
+
+ var cmp0 = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp1 = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp = [cmp0, cmp1];
+
+ var isTrue = getMask(cmp, function(x) {return x.isTrue;});
+ var isFalse = getMask(cmp, function(x) {return x.isFalse;});
+
+ var f0 = fBounds[0];
+ var f1 = fBounds[1];
+
+ var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits);
+ var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
+ var totalErr = pcfErr + resErr;
+
+ for (var comb = 0; comb < 4; comb++) {
+ if (((comb & isTrue) | (~comb & isFalse )) != 3)
+ continue;
+
+ var cmp0True = ((comb >> 0) & 1) != 0;
+ var cmp1True = ((comb >> 1) & 1) != 0;
+
+ var ref0 = cmp0True ? 1 : 0;
+ var ref1 = cmp1True ? 1 : 0;
+
+ var v0 = ref0 * (1 - f0) + ref1 * f0;
+ var v1 = ref0 * (1 - f1) + ref1 * f1;
+ var minV = Math.min(v0, v1);
+ var maxV = Math.max(v0, v1);
+ var minR = minV - totalErr;
+ var maxR = maxV + totalErr;
+
+ if (deMath.deInRange32(result, minR, maxR))
+ return true;
+ }
+ return false;
+};
+
+/**
+ * @param {number} val
+ * @param {number} offset
+ * @return {Array<boolean>}
+ */
+tcuTexCompareVerifier.extractBVec4 = function(val, offset) {
+ return [
+ ((val >> (offset + 0)) & 1) != 0,
+ ((val >> (offset + 1)) & 1) != 0,
+ ((val >> (offset + 2)) & 1) != 0,
+ ((val >> (offset + 3)) & 1) != 0];
+};
+
+/**
+ * Values are in order (0,0), (1,0), (0,1), (1,1)
+ * @param {Array<number>} values
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+tcuTexCompareVerifier.bilinearInterpolate = function(values, x, y) {
+ var v00 = values[0];
+ var v10 = values[1];
+ var v01 = values[2];
+ var v11 = values[3];
+ var res = v00 * (1 - x) * (1 - y) + v10 * x * (1 - y) + v01 * (1 - x) * y + v11 * x * y;
+ return res;
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths vec4
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isBilinearAnyCompareValid = function(compareMode,
+ prec,
+ depths,
+ cmpReference,
+ result,
+ isFixedPointDepth) {
+ assertMsgOptions(prec.pcfBits === 0, 'PCF bits must be 0', false, true);
+
+ var d0 = depths[0];
+ var d1 = depths[1];
+ var d2 = depths[2];
+ var d3 = depths[3];
+
+ var cmp0 = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp1 = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp2 = tcuTexCompareVerifier.execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp3 = tcuTexCompareVerifier.execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);
+
+ var canBeTrue = cmp0.isTrue || cmp1.isTrue || cmp2.isTrue || cmp3.isTrue;
+ var canBeFalse = cmp0.isFalse || cmp1.isFalse || cmp2.isFalse || cmp3.isFalse;
+
+ var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
+
+ var minBound = canBeFalse ? 0 : 1;
+ var maxBound = canBeTrue ? 1 : 0;
+
+ return deMath.deInRange32(result, minBound - resErr, maxBound + resErr);
+};
+
+/**
+ * @param {Array<tcuTexCompareVerifier.CmpResultSet>} arr
+ * @param {function(tcuTexCompareVerifier.CmpResultSet): boolean} getValue
+ * @return {number}
+ */
+var getMask = function(arr, getValue) {
+ var mask = 0;
+ for (var i = 0; i < arr.length; i++) {
+ var val = getValue(arr[i]);
+ if (val)
+ mask |= 1 << i;
+ }
+ return mask;
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths vec4
+ * @param {Array<number>} xBounds vec2
+ * @param {Array<number>} yBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isBilinearPCFCompareValid = function(compareMode,
+ prec,
+ depths,
+ xBounds,
+ yBounds,
+ cmpReference,
+ result,
+ isFixedPointDepth) {
+ assertMsgOptions(0.0 <= xBounds[0] && xBounds[0] <= xBounds[1] && xBounds[1] <= 1.0, 'x coordinate out of bounds', false, true);
+ assertMsgOptions(0.0 <= yBounds[0] && yBounds[0] <= yBounds[1] && yBounds[1] <= 1.0, 'y coordinate out of bounds', false, true);
+ assertMsgOptions(prec.pcfBits > 0, 'PCF bits must be > 0', false, true);
+
+ var d0 = depths[0];
+ var d1 = depths[1];
+ var d2 = depths[2];
+ var d3 = depths[3];
+
+ /** @type {Array<tcuTexCompareVerifier.CmpResultSet>} */ var cmp = [];
+ cmp[0] = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
+ cmp[1] = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
+ cmp[2] = tcuTexCompareVerifier.execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
+ cmp[3] = tcuTexCompareVerifier.execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);
+
+ var isTrue = getMask(cmp, function(x) {return x.isTrue});
+ var isFalse = getMask(cmp, function(x) {return x.isFalse});
+
+ // Interpolation parameters
+ var x0 = xBounds[0];
+ var x1 = xBounds[1];
+ var y0 = yBounds[0];
+ var y1 = yBounds[1];
+
+ // Error parameters
+ var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits);
+ var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
+ var totalErr = pcfErr + resErr;
+
+ // Iterate over all valid combinations.
+ // \note It is not enough to compute minmax over all possible result sets, as ranges may
+ // not necessarily overlap, i.e. there are gaps between valid ranges.
+ for (var comb = 0; comb < (1 << 4); comb++) {
+ // Filter out invalid combinations:
+ // 1) True bit is set in comb but not in isTrue => sample can not be true
+ // 2) True bit is NOT set in comb and not in isFalse => sample can not be false
+ if (((comb & isTrue) | (~comb & isFalse)) != (1 << 4) - 1)
+ continue;
+
+ var cmpTrue = tcuTexCompareVerifier.extractBVec4(comb, 0);
+ var refVal = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue);
+
+ var v0 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x0, y0);
+ var v1 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x1, y0);
+ var v2 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x0, y1);
+ var v3 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x1, y1);
+ var minV = Math.min(v0, v1, v2, v3);
+ var maxV = Math.max(v0, v1, v2, v3);
+ var minR = minV - totalErr;
+ var maxR = maxV + totalErr;
+
+ if (deMath.deInRange32(result, minR, maxR))
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths vec4
+ * @param {Array<number>} xBounds vec2
+ * @param {Array<number>} yBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isBilinearCompareValid = function(compareMode,
+ prec,
+ depths,
+ xBounds,
+ yBounds,
+ cmpReference,
+ result,
+ isFixedPointDepth) {
+ if (prec.pcfBits > 0)
+ return tcuTexCompareVerifier.isBilinearPCFCompareValid(compareMode, prec, depths, xBounds, yBounds, cmpReference, result, isFixedPointDepth);
+ else
+ return tcuTexCompareVerifier.isBilinearAnyCompareValid(compareMode, prec, depths, cmpReference, result, isFixedPointDepth);
+};
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {number} coordZ
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isLinearCompareResultValid = function(level,
+ sampler,
+ prec,
+ coord,
+ coordZ,
+ cmpReference,
+ result) {
+ var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level.getFormat());
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinate bounds for (x0,y0) - without wrap mode
+ var minI = Math.floor(uBounds[0] - 0.5);
+ var maxI = Math.floor(uBounds[1] - 0.5);
+ var minJ = Math.floor(vBounds[0] - 0.5);
+ var maxJ = Math.floor(vBounds[1] - 0.5);
+
+ var w = level.getWidth();
+ var h = level.getHeight();
+
+ // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
+
+ for (var j = minJ; j <= maxJ; j++) {
+ for (var i = minI; i <= maxI; i++) {
+ // Wrapped coordinates
+ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w);
+ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w);
+ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h);
+ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h);
+
+ // Bounds for filtering factors
+ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
+ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
+ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
+ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
+
+ var depths = [
+ level.getPixDepth(x0, y0, coordZ),
+ level.getPixDepth(x1, y0, coordZ),
+ level.getPixDepth(x0, y1, coordZ),
+ level.getPixDepth(x1, y1, coordZ)
+ ];
+
+ if (tcuTexCompareVerifier.isBilinearCompareValid(sampler.compare, prec, depths, [minA, maxA], [minB, maxB], cmpReference, result, isFixedPointDepth))
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexCompareVerifier.CmpResultSet} resultSet
+ * @param {number} result
+ * @param {number} resultBits
+ */
+tcuTexCompareVerifier.isResultInSet = function(resultSet, result, resultBits) {
+ var err = tcuTexVerifierUtil.computeFixedPointError(resultBits);
+ var minR = result - err;
+ var maxR = result + err;
+
+ return (resultSet.isTrue && deMath.deInRange32(1, minR, maxR)) ||
+ (resultSet.isFalse && deMath.deInRange32(0, minR, maxR));
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {number} coordZ
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isNearestCompareResultValid = function(level,
+ sampler,
+ prec,
+ coord,
+ coordZ,
+ cmpReference,
+ result) {
+ var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level.getFormat());
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ var minI = Math.floor(uBounds[0]);
+ var maxI = Math.floor(uBounds[1]);
+ var minJ = Math.floor(vBounds[0]);
+ var maxJ = Math.floor(vBounds[1]);
+
+ for (var j = minJ; j <= maxJ; j++) {
+ for (var i = minI; i <= maxI; i++) {
+ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth());
+ var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight());
+ var depth = level.getPixDepth(x, y, coordZ);
+ var resSet = tcuTexCompareVerifier.execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);
+
+ if (tcuTexCompareVerifier.isResultInSet(resSet, result, prec.resultBits))
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filterMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {number} coordZ
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isLevelCompareResultValid = function(level,
+ sampler,
+ filterMode,
+ prec,
+ coord,
+ coordZ,
+ cmpReference,
+ result) {
+ if (filterMode == tcuTexture.FilterMode.LINEAR)
+ return tcuTexCompareVerifier.isLinearCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
+ else
+ return tcuTexCompareVerifier.isNearestCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths0 vec4
+ * @param {Array<number>} depths1 vec4
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isTrilinearAnyCompareValid = function(compareMode,
+ prec,
+ depths0,
+ depths1,
+ cmpReference,
+ result,
+ isFixedPointDepth) {
+ assertMsgOptions(prec.pcfBits === 0, 'PCF bits must be 0', false, true);
+
+ var cmp00 = tcuTexCompareVerifier.execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp01 = tcuTexCompareVerifier.execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp02 = tcuTexCompareVerifier.execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp03 = tcuTexCompareVerifier.execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp10 = tcuTexCompareVerifier.execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp11 = tcuTexCompareVerifier.execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp12 = tcuTexCompareVerifier.execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth);
+ var cmp13 = tcuTexCompareVerifier.execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth);
+
+ var canBeTrue = cmp00.isTrue ||
+ cmp01.isTrue ||
+ cmp02.isTrue ||
+ cmp03.isTrue ||
+ cmp10.isTrue ||
+ cmp11.isTrue ||
+ cmp12.isTrue ||
+ cmp13.isTrue;
+ var canBeFalse = cmp00.isFalse ||
+ cmp01.isFalse ||
+ cmp02.isFalse ||
+ cmp03.isFalse ||
+ cmp10.isFalse ||
+ cmp11.isFalse ||
+ cmp12.isFalse ||
+ cmp13.isFalse;
+
+ var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
+
+ var minBound = canBeFalse ? 0 : 1;
+ var maxBound = canBeTrue ? 1 : 0;
+
+ return deMath.deInRange32(result, minBound - resErr, maxBound + resErr);
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths0 vec4
+ * @param {Array<number>} depths1 vec4
+ * @param {Array<number>} xBounds0
+ * @param {Array<number>} yBounds0
+ * @param {Array<number>} xBounds1
+ * @param {Array<number>} yBounds1
+ * @param {Array<number>} fBounds
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isTrilinearPCFCompareValid = function(compareMode,
+ prec,
+ depths0,
+ depths1,
+ xBounds0,
+ yBounds0,
+ xBounds1,
+ yBounds1,
+ fBounds,
+ cmpReference,
+ result,
+ isFixedPointDepth) {
+ assertMsgOptions(0.0 <= xBounds0[0] && xBounds0[0] <= xBounds0[1] && xBounds0[1] <= 1.0, 'x0 coordinate out of bounds', false, true);
+ assertMsgOptions(0.0 <= yBounds0[0] && yBounds0[0] <= yBounds0[1] && yBounds0[1] <= 1.0, 'y0 coordinate out of bounds', false, true);
+ assertMsgOptions(0.0 <= xBounds1[0] && xBounds1[0] <= xBounds1[1] && xBounds1[1] <= 1.0, 'x1 coordinate out of bounds', false, true);
+ assertMsgOptions(0.0 <= yBounds1[0] && yBounds1[0] <= yBounds1[1] && yBounds1[1] <= 1.0, 'y1 coordinate out of bounds', false, true);
+ assertMsgOptions(0.0 <= fBounds[0] && fBounds[0] <= fBounds[1] && fBounds[1] <= 1.0, 'linear factor out of bounds', false, true);
+ assertMsgOptions(prec.pcfBits > 0, 'PCF bits must be > 0', false, true);
+
+ /** @type {Array<tcuTexCompareVerifier.CmpResultSet>} */ var cmp = [];
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth));
+ cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth));
+
+ var isTrue = getMask(cmp, function(x) {return x.isTrue});
+ var isFalse = getMask(cmp, function(x) {return x.isFalse});
+
+ // Error parameters
+ var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits);
+ var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
+ var totalErr = pcfErr + resErr;
+
+ // Iterate over all valid combinations.
+ for (var comb = 0; comb < (1 << 8); comb++) {
+ // Filter out invalid combinations.
+ if (((comb & isTrue) | (~comb & isFalse)) != (1 << 8) - 1)
+ continue;
+
+ var cmpTrue0 = tcuTexCompareVerifier.extractBVec4(comb, 0);
+ var cmpTrue1 = tcuTexCompareVerifier.extractBVec4(comb, 4);
+ var refVal0 = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue0);
+ var refVal1 = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue1);
+
+ // Bilinear interpolation within levels.
+ var v00 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[0], yBounds0[0]);
+ var v01 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[1], yBounds0[0]);
+ var v02 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[0], yBounds0[1]);
+ var v03 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[1], yBounds0[1]);
+ var minV0 = Math.min(v00, v01, v02, v03);
+ var maxV0 = Math.max(v00, v01, v02, v03);
+
+ var v10 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[0], yBounds1[0]);
+ var v11 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[1], yBounds1[0]);
+ var v12 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[0], yBounds1[1]);
+ var v13 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[1], yBounds1[1]);
+ var minV1 = Math.min(v10, v11, v12, v13);
+ var maxV1 = Math.max(v10, v11, v12, v13);
+
+ // Compute min-max bounds by filtering between minimum bounds and maximum bounds between levels.
+ // HW can end up choosing pretty much any of samples between levels, and thus interpolating
+ // between minimums should yield lower bound for range, and same for upper bound.
+ // \todo [2013-07-17 pyry] This seems separable? Can this be optimized? At least ranges could be pre-computed and later combined.
+ var minF0 = minV0 * (1 - fBounds[0]) + minV1 * fBounds[0];
+ var minF1 = minV0 * (1 - fBounds[1]) + minV1 * fBounds[1];
+ var maxF0 = maxV0 * (1 - fBounds[0]) + maxV1 * fBounds[0];
+ var maxF1 = maxV0 * (1 - fBounds[1]) + maxV1 * fBounds[1];
+
+ var minF = Math.min(minF0, minF1);
+ var maxF = Math.max(maxF0, maxF1);
+
+ var minR = minF - totalErr;
+ var maxR = maxF + totalErr;
+
+ if (deMath.deInRange32(result, minR, maxR))
+ return true;
+ }
+
+ return false;
+
+};
+
+/**
+ * @param {tcuTexture.CompareMode} compareMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} depths0 vec4
+ * @param {Array<number>} depths1 vec4
+ * @param {Array<number>} xBounds0
+ * @param {Array<number>} yBounds0
+ * @param {Array<number>} xBounds1
+ * @param {Array<number>} yBounds1
+ * @param {Array<number>} fBounds
+ * @param {number} cmpReference
+ * @param {number} result
+ * @param {boolean} isFixedPointDepth
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isTrilinearCompareValid = function(compareMode,
+ prec,
+ depths0,
+ depths1,
+ xBounds0,
+ yBounds0,
+ xBounds1,
+ yBounds1,
+ fBounds,
+ cmpReference,
+ result,
+ isFixedPointDepth) {
+ if (prec.pcfBits > 0)
+ return tcuTexCompareVerifier.isTrilinearPCFCompareValid(compareMode, prec, depths0, depths1, xBounds0, yBounds0, xBounds1, yBounds1, fBounds, cmpReference, result, isFixedPointDepth);
+ else
+ return tcuTexCompareVerifier.isTrilinearAnyCompareValid(compareMode, prec, depths0, depths1, cmpReference, result, isFixedPointDepth);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {number} coordZ
+ * @param {Array<number>} fBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid = function(level0,
+ level1,
+ sampler,
+ prec,
+ coord,
+ coordZ,
+ fBounds,
+ cmpReference,
+ result) {
+ var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level0.getFormat());
+
+ // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
+ // Right now this allows pairing any two valid bilinear quads.
+
+ var w0 = level0.getWidth();
+ var w1 = level1.getWidth();
+ var h0 = level0.getHeight();
+ var h1 = level1.getHeight();
+
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ var minI0 = Math.floor(uBounds0[0] - 0.5);
+ var maxI0 = Math.floor(uBounds0[1] - 0.5);
+ var minI1 = Math.floor(uBounds1[0] - 0.5);
+ var maxI1 = Math.floor(uBounds1[1] - 0.5);
+ var minJ0 = Math.floor(vBounds0[0] - 0.5);
+ var maxJ0 = Math.floor(vBounds0[1] - 0.5);
+ var minJ1 = Math.floor(vBounds1[0] - 0.5);
+ var maxJ1 = Math.floor(vBounds1[1] - 0.5);
+
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
+ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
+ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
+ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
+ var depths0 = [];
+
+ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0);
+ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0);
+ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0);
+ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0);
+
+ depths0[0] = level0.getPixDepth(x0, y0, coordZ);
+ depths0[1] = level0.getPixDepth(x1, y0, coordZ);
+ depths0[2] = level0.getPixDepth(x0, y1, coordZ);
+ depths0[3] = level0.getPixDepth(x1, y1, coordZ);
+
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
+ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
+ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
+ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
+ var depths1 = [];
+
+ x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1);
+ x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1);
+ y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1);
+ y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1);
+
+ depths1[0] = level1.getPixDepth(x0, y0, coordZ);
+ depths1[1] = level1.getPixDepth(x1, y0, coordZ);
+ depths1[2] = level1.getPixDepth(x0, y1, coordZ);
+ depths1[3] = level1.getPixDepth(x1, y1, coordZ);
+
+ if (tcuTexCompareVerifier.isTrilinearCompareValid(sampler.compare, prec, depths0, depths1,
+ [minA0, maxA0], [minB0, maxB0],
+ [minA1, maxA1], [minB1, maxB1],
+ fBounds, cmpReference, result, isFixedPointDepth))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {number} coordZ
+ * @param {Array<number>} fBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid = function(level0,
+ level1,
+ sampler,
+ prec,
+ coord,
+ coordZ,
+ fBounds,
+ cmpReference,
+ result) {
+ var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level0.getFormat());
+
+ var w0 = level0.getWidth();
+ var w1 = level1.getWidth();
+ var h0 = level0.getHeight();
+ var h1 = level1.getHeight();
+
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ var minI0 = Math.floor(uBounds0[0]);
+ var maxI0 = Math.floor(uBounds0[1]);
+ var minI1 = Math.floor(uBounds1[0]);
+ var maxI1 = Math.floor(uBounds1[1]);
+ var minJ0 = Math.floor(vBounds0[0]);
+ var maxJ0 = Math.floor(vBounds0[1]);
+ var minJ1 = Math.floor(vBounds1[0]);
+ var maxJ1 = Math.floor(vBounds1[1]);
+
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0);
+ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0);
+
+ // Derivated from C++ dEQP function lookupDepth()
+ // Since x0 and y0 are wrapped, here lookupDepth() returns the same result as getPixDepth()
+ assertMsgOptions(deMath.deInBounds32(x0, 0, level0.getWidth()) && deMath.deInBounds32(y0, 0, level0.getHeight()) && deMath.deInBounds32(coordZ, 0, level0.getDepth()), 'x0, y0 or coordZ out of bound.', false, true);
+ var depth0 = level0.getPixDepth(x0, y0, coordZ);
+
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1);
+ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1);
+
+ // Derivated from C++ dEQP function lookupDepth()
+ // Since x1 and y1 are wrapped, here lookupDepth() returns the same result as getPixDepth()
+ assertMsgOptions(deMath.deInBounds32(x1, 0, level1.getWidth()) && deMath.deInBounds32(y1, 0, level1.getHeight()), 'x1 or y1 out of bound.', false, true);
+ var depth1 = level1.getPixDepth(x1, y1, coordZ);
+
+ if (tcuTexCompareVerifier.isLinearCompareValid(sampler.compare, prec, [depth0, depth1], fBounds, cmpReference, result, isFixedPointDepth))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} levelFilter
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {number} coordZ
+ * @param {Array<number>} fBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isMipmapLinearCompareResultValid = function(level0,
+ level1,
+ sampler,
+ levelFilter,
+ prec,
+ coord,
+ coordZ,
+ fBounds,
+ cmpReference,
+ result) {
+ if (levelFilter == tcuTexture.FilterMode.LINEAR)
+ return tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result);
+ else
+ return tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result);
+};
+
+/**
+ * @param {tcuTexture.Texture2DView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {Array<number>} lodBounds vec2 level-of-detail bounds
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isTexCompareResultValid2D = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) {
+ var minLod = lodBounds[0];
+ var maxLod = lodBounds[1];
+ var canBeMagnified = minLod <= sampler.lodThreshold;
+ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ if (canBeMagnified) {
+ if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, cmpReference, result))
+ return true;
+ }
+
+ if (canBeMinified) {
+ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ var minTexLevel = 0;
+ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true);
+
+ if (isLinearMipmap) {
+ var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ var minF = deMath.clamp(minLod - level, 0, 1);
+ var maxF = deMath.clamp(maxLod - level, 0, 1);
+
+ if (tcuTexCompareVerifier.isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, [minF, maxF], cmpReference, result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, cmpReference, result))
+ return true;
+ }
+ } else {
+ if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, cmpReference, result))
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {number} baseLevelNdx
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {Array<number>} fBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isSeamplessLinearMipmapLinearCompareResultValid = function(texture,
+ baseLevelNdx,
+ sampler,
+ prec,
+ coords,
+ fBounds,
+ cmpReference,
+ result) {
+ var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(texture.getLevelFace(baseLevelNdx, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getFormat());
+ var size0 = texture.getLevelFace(baseLevelNdx, coords.face).getWidth();
+ var size1 = texture.getLevelFace(baseLevelNdx + 1, coords.face).getWidth();
+
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits[0], prec.uvwBits[0]);
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits[0], prec.uvwBits[0]);
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits[1], prec.uvwBits[1]);
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ var minI0 = Math.floor(uBounds0[0] - 0.5);
+ var maxI0 = Math.floor(uBounds0[1] - 0.5);
+ var minI1 = Math.floor(uBounds1[0] - 0.5);
+ var maxI1 = Math.floor(uBounds1[1] - 0.5);
+ var minJ0 = Math.floor(vBounds0[0] - 0.5);
+ var maxJ0 = Math.floor(vBounds0[1] - 0.5);
+ var minJ1 = Math.floor(vBounds1[0] - 0.5);
+ var maxJ1 = Math.floor(vBounds1[1] - 0.5);
+
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces0 = [];
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces1 = [];
+
+ for (var key in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[key];
+ faces0[face] = texture.getLevelFace(baseLevelNdx, face);
+ faces1[face] = texture.getLevelFace(baseLevelNdx + 1, face);
+ }
+
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
+ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
+ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
+ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
+ var depths0 = [];
+
+ var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 0]), size0);
+ var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 0]), size0);
+ var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 1]), size0);
+ var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 1]), size0);
+
+ // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
+ // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
+ if (c00 == null || c01 == null || c10 == null || c11 == null)
+ return true;
+
+ depths0[0] = faces0[c00.face].getPixDepth(c00.s, c00.t);
+ depths0[1] = faces0[c10.face].getPixDepth(c10.s, c10.t);
+ depths0[2] = faces0[c01.face].getPixDepth(c01.s, c01.t);
+ depths0[3] = faces0[c11.face].getPixDepth(c11.s, c11.t);
+
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
+ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
+ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
+ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
+ var depths1 = [];
+
+ c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 0]), size1);
+ c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 0]), size1);
+ c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 1]), size1);
+ c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 1]), size1);
+
+ if (c00 == null || c01 == null || c10 == null || c11 == null)
+ return true;
+
+ depths1[0] = faces1[c00.face].getPixDepth(c00.s, c00.t);
+ depths1[1] = faces1[c10.face].getPixDepth(c10.s, c10.t);
+ depths1[2] = faces1[c01.face].getPixDepth(c01.s, c01.t);
+ depths1[3] = faces1[c11.face].getPixDepth(c11.s, c11.t);
+
+ if (tcuTexCompareVerifier.isTrilinearCompareValid(sampler.compare, prec, depths0, depths1,
+ [minA0, maxA0], [minB0, maxB0],
+ [minA1, maxA1], [minB1, maxB1],
+ fBounds, cmpReference, result, isFixedPointDepth))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {number} levelNdx
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+
+tcuTexCompareVerifier.isSeamlessLinearCompareResultValid = function(texture,
+ levelNdx,
+ sampler,
+ prec,
+ coords,
+ cmpReference,
+ result) {
+ var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(texture.getLevelFace(levelNdx, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getFormat());
+ var size = texture.getLevelFace(levelNdx, coords.face).getWidth();
+
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits[0], prec.uvwBits[0]);
+ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinate bounds for (x0,y0) - without wrap mode
+ var minI = Math.floor(uBounds[0] - 0.5);
+ var maxI = Math.floor(uBounds[1] - 0.5);
+ var minJ = Math.floor(vBounds[0] - 0.5);
+ var maxJ = Math.floor(vBounds[1] - 0.5);
+
+ // Face accesses
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces = [];
+
+ for (var key in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[key];
+ faces[face] = texture.getLevelFace(levelNdx, face);
+ }
+
+ for (var j = minJ; j <= maxJ; j++) {
+ for (var i = minI; i <= maxI; i++) {
+ var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 0]), size);
+ var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 0]), size);
+ var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 1]), size);
+ var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 1]), size);
+
+ // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
+ // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
+ if (!c00 || !c01 || !c10 || !c11)
+ return true;
+
+ // Bounds for filtering factors
+ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
+ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
+ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
+ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
+
+ var depths = [];
+ depths[0] = faces[c00.face].getPixDepth(c00.s, c00.t);
+ depths[1] = faces[c10.face].getPixDepth(c10.s, c10.t);
+ depths[2] = faces[c01.face].getPixDepth(c01.s, c01.t);
+ depths[3] = faces[c11.face].getPixDepth(c11.s, c11.t);
+
+ if (tcuTexCompareVerifier.isBilinearCompareValid(sampler.compare, prec, depths, [minA, maxA], [minB, maxB], cmpReference, result, isFixedPointDepth))
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {number} levelNdx
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filterMode
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isCubeLevelCompareResultValid = function(texture,
+ levelNdx,
+ sampler,
+ filterMode,
+ prec,
+ coords,
+ cmpReference,
+ result) {
+ if (filterMode == tcuTexture.FilterMode.LINEAR) {
+ if (sampler.seamlessCubeMap)
+ return tcuTexCompareVerifier.isSeamlessLinearCompareResultValid(texture, levelNdx, sampler, prec, coords, cmpReference, result);
+ else
+ return tcuTexCompareVerifier.isLinearCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, [coords.s, coords.t], 0, cmpReference, result);
+ } else
+ return tcuTexCompareVerifier.isNearestCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, [coords.s, coords.t], 0, cmpReference, result);
+};
+
+/**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {number} baseLevelNdx
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} levelFilter
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {Array<number>} fBounds vec2
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isCubeMipmapLinearCompareResultValid = function(texture,
+ baseLevelNdx,
+ sampler,
+ levelFilter,
+ prec,
+ coords,
+ fBounds,
+ cmpReference,
+ result) {
+ if (levelFilter == tcuTexture.FilterMode.LINEAR) {
+ if (sampler.seamlessCubeMap)
+ return tcuTexCompareVerifier.isSeamplessLinearMipmapLinearCompareResultValid(texture, baseLevelNdx, sampler, prec, coords, fBounds, cmpReference, result);
+ else
+ return tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx, coords.face),
+ texture.getLevelFace(baseLevelNdx + 1, coords.face),
+ sampler, prec, [coords.s, coords.t], 0, fBounds, cmpReference, result);
+ } else
+ return tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx, coords.face),
+ texture.getLevelFace(baseLevelNdx + 1, coords.face),
+ sampler, prec, [coords.s, coords.t], 0, fBounds, cmpReference, result);
+};
+
+/**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec2 texture coordinates
+ * @param {Array<number>} lodBounds vec2 level-of-detail bounds
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isTexCompareResultValidCube = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) {
+ /** @type {Array<tcuTexture.CubeFace>} */var possibleFaces = tcuTexVerifierUtil.getPossibleCubeFaces(coord, prec.coordBits);
+
+ if (!possibleFaces)
+ return true; // Result is undefined.
+
+ for (var tryFaceNdx = 0; tryFaceNdx < possibleFaces.length; tryFaceNdx++) {
+ var face = possibleFaces[tryFaceNdx];
+ var faceCoords = new tcuTexture.CubeFaceCoords(face, tcuTexture.projectToFace(face, coord));
+ var minLod = lodBounds[0];
+ var maxLod = lodBounds[1];
+ var canBeMagnified = minLod <= sampler.lodThreshold;
+ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ if (canBeMagnified) {
+ if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, 0, sampler, sampler.magFilter, prec, faceCoords, cmpReference, result))
+ return true;
+ }
+
+ if (canBeMinified) {
+ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ var minTexLevel = 0;
+ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true);
+
+ if (isLinearMipmap) {
+ var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ var minF = deMath.clamp(minLod - level, 0, 1);
+ var maxF = deMath.clamp(maxLod - level, 0, 1);
+
+ if (tcuTexCompareVerifier.isCubeMipmapLinearCompareResultValid(texture, level, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, [minF, maxF], cmpReference, result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, level, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, cmpReference, result))
+ return true;
+ }
+ } else {
+ if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, 0, sampler, sampler.minFilter, prec, faceCoords, cmpReference, result))
+ return true;
+ }
+ }
+ }
+
+ return false;
+};
+
+/**
+ * @param {tcuTexture.Texture2DArrayView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexCompareVerifier.TexComparePrecision} prec
+ * @param {Array<number>} coord vec3 texture coordinates
+ * @param {Array<number>} lodBounds vec2 level-of-detail bounds
+ * @param {number} cmpReference
+ * @param {number} result
+ * @return {boolean}
+ */
+tcuTexCompareVerifier.isTexCompareResultValid2DArray = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) {
+ var depthErr = tcuTexVerifierUtil.computeFloatingPointError(coord[2], prec.coordBits[2]) + tcuTexVerifierUtil.computeFixedPointError(prec.uvwBits[2]);
+ var minZ = coord[2] - depthErr;
+ var maxZ = coord[2] + depthErr;
+ var minLayer = deMath.clamp(Math.floor(minZ + 0.5), 0, texture.getNumLayers() - 1);
+ var maxLayer = deMath.clamp(Math.floor(maxZ + 0.5), 0, texture.getNumLayers() - 1);
+
+ for (var layer = minLayer; layer <= maxLayer; layer++) {
+ var minLod = lodBounds[0];
+ var maxLod = lodBounds[1];
+ var canBeMagnified = minLod <= sampler.lodThreshold;
+ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ if (canBeMagnified) {
+ if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result))
+ return true;
+ }
+
+ if (canBeMinified) {
+ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ var minTexLevel = 0;
+ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true);
+
+ if (isLinearMipmap) {
+ var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ var minF = deMath.clamp(minLod - level, 0, 1);
+ var maxF = deMath.clamp(maxLod - level, 0, 1);
+
+ if (tcuTexCompareVerifier.isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, deMath.swizzle(coord, [0, 1]), layer, [minF, maxF], cmpReference, result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result))
+ return true;
+ }
+ } else {
+ if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result))
+ return true;
+ }
+ }
+ }
+
+ return false;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexLookupVerifier.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexLookupVerifier.js
new file mode 100644
index 0000000000..6b471998aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexLookupVerifier.js
@@ -0,0 +1,2225 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuTexLookupVerifier');
+goog.require('framework.common.tcuTexVerifierUtil');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+ var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var tcuTexVerifierUtil = framework.common.tcuTexVerifierUtil;
+ var deMath = framework.delibs.debase.deMath;
+
+ /** @typedef {(tcuTexLookupVerifier.LookupPrecision|{tcuTexLookupVerifier.LookupPrecision})} */
+ tcuTexLookupVerifier.PrecType;
+
+ /**
+ * Generic lookup precision parameters
+ * @constructor
+ * @struct
+ * @param {Array<number>=} coordBits
+ * @param {Array<number>=} uvwBits
+ * @param {Array<number>=} colorThreshold
+ * @param {Array<boolean>=} colorMask
+ */
+ tcuTexLookupVerifier.LookupPrecision = function(coordBits, uvwBits, colorThreshold, colorMask) {
+ /** @type {Array<number>} */ this.coordBits = coordBits || [22, 22, 22];
+ /** @type {Array<number>} */ this.uvwBits = uvwBits || [16, 16, 16];
+ /** @type {Array<number>} */ this.colorThreshold = colorThreshold || [0, 0, 0, 0];
+ /** @type {Array<boolean>} */ this.colorMask = colorMask || [true, true, true, true];
+ };
+
+ /**
+ * Lod computation precision parameters
+ * @constructor
+ * @struct
+ * @param {number=} derivateBits
+ * @param {number=} lodBits
+ */
+ tcuTexLookupVerifier.LodPrecision = function(derivateBits, lodBits) {
+ /** @type {number} */ this.derivateBits = derivateBits === undefined ? 22 : derivateBits;
+ /** @type {number} */ this.lodBits = lodBits === undefined ? 16 : lodBits;
+ };
+
+ /**
+ * @enum {number}
+ */
+ tcuTexLookupVerifier.TexLookupScaleMode = {
+ MINIFY: 0,
+ MAGNIFY: 1
+ };
+
+ // Generic utilities
+
+ /**
+ * @param {tcuTexture.Sampler} sampler
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isSamplerSupported = function(sampler) {
+ return sampler.compare == tcuTexture.CompareMode.COMPAREMODE_NONE &&
+ tcuTexVerifierUtil.isWrapModeSupported(sampler.wrapS) &&
+ tcuTexVerifierUtil.isWrapModeSupported(sampler.wrapT) &&
+ tcuTexVerifierUtil.isWrapModeSupported(sampler.wrapR);
+ };
+
+ // Color read & compare utilities
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.coordsInBounds = function(access, x, y, z) {
+ return deMath.deInBounds32(x, 0, access.getWidth()) && deMath.deInBounds32(y, 0, access.getHeight()) && deMath.deInBounds32(z, 0, access.getDepth());
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isSRGB = function(format) {
+ return format.order == tcuTexture.ChannelOrder.sRGB || format.order == tcuTexture.ChannelOrder.sRGBA;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} i
+ * @param {number} j
+ * @param {number} k
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.lookupScalar = function(access, sampler, i, j, k) {
+ if (tcuTexLookupVerifier.coordsInBounds(access, i, j, k))
+ return access.getPixel(i, j, k);
+ else
+ return deMath.toIVec(sampler.borderColor);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} i
+ * @param {number} j
+ * @param {number} k
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.lookupFloat = function(access, sampler, i, j, k) {
+ // Specialization for float lookups: sRGB conversion is performed as specified in format.
+ if (tcuTexLookupVerifier.coordsInBounds(access, i, j, k)) {
+ /** @type {Array<number>} */ var p = access.getPixel(i, j, k);
+ return tcuTexLookupVerifier.isSRGB(access.getFormat()) ? tcuTextureUtil.sRGBToLinear(p) : p;
+ } else
+ return sampler.borderColor;
+ };
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} ref
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isColorValid = function(prec, ref, result) {
+ return deMath.boolAll(
+ deMath.logicalOrBool(
+ deMath.lessThanEqual(deMath.absDiff(ref, result), prec.colorThreshold),
+ deMath.logicalNotBool(prec.colorMask)));
+ };
+
+ /**
+ * @constructor
+ * @struct
+ * @param {Array<number>=} p00
+ * @param {Array<number>=} p01
+ * @param {Array<number>=} p10
+ * @param {Array<number>=} p11
+ */
+ tcuTexLookupVerifier.ColorQuad = function(p00, p01, p10, p11) {
+ /** @type {Array<number>} */ this.p00 = p00 || null; //!< (0, 0)
+ /** @type {Array<number>} */ this.p01 = p01 || null; //!< (1, 0)
+ /** @type {Array<number>} */ this.p10 = p10 || null; //!< (0, 1)
+ /** @type {Array<number>} */ this.p11 = p11 || null; //!< (1, 1)
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} x0
+ * @param {number} x1
+ * @param {number} y0
+ * @param {number} y1
+ * @param {number} z
+ * @return {tcuTexLookupVerifier.ColorQuad}
+ */
+ tcuTexLookupVerifier.lookupQuad = function(level, sampler, x0, x1, y0, y1, z) {
+ var p00 = tcuTexLookupVerifier.lookupFloat(level, sampler, x0, y0, z);
+ var p10 = tcuTexLookupVerifier.lookupFloat(level, sampler, x1, y0, z);
+ var p01 = tcuTexLookupVerifier.lookupFloat(level, sampler, x0, y1, z);
+ var p11 = tcuTexLookupVerifier.lookupFloat(level, sampler, x1, y1, z);
+ return new tcuTexLookupVerifier.ColorQuad(p00, p01, p10, p11);
+ };
+
+ /**
+ * @constructor
+ * @struct
+ * @param {Array<number>=} p0
+ * @param {Array<number>=} p1
+ */
+ tcuTexLookupVerifier.ColorLine = function(p0, p1) {
+ /** @type {Array<number>} */ this.p0 = p0 || null; //!< 0
+ /** @type {Array<number>} */ this.p1 = p1 || null; //!< 1
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} x0
+ * @param {number} x1
+ * @param {number} y
+ * @return {tcuTexLookupVerifier.ColorLine}
+ */
+ tcuTexLookupVerifier.lookupLine = function(level, sampler, x0, x1, y) {
+ return new tcuTexLookupVerifier.ColorLine(
+ tcuTexLookupVerifier.lookupFloat(level, sampler, x0, y, 0),
+ tcuTexLookupVerifier.lookupFloat(level, sampler, x1, y, 0)
+ );
+ };
+
+ /**
+ * @param {Array<number>} vec
+ * @return {number}
+ */
+ tcuTexLookupVerifier.minComp = function(vec) {
+ /** @type {number} */ var minVal = vec[0];
+ for (var ndx = 1; ndx < vec.length; ndx++)
+ minVal = Math.min(minVal, vec[ndx]);
+ return minVal;
+ };
+
+ /**
+ * @param {Array<number>} vec
+ * @return {number}
+ */
+ tcuTexLookupVerifier.maxComp = function(vec) {
+ /** @type {number} */ var maxVal = vec[0];
+ for (var ndx = 1; ndx < vec.length; ndx++)
+ maxVal = Math.max(maxVal, vec[ndx]);
+ return maxVal;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorLine} line
+ * @return {number}
+ */
+ tcuTexLookupVerifier.computeBilinearSearchStepFromFloatLine = function(prec, line) {
+ assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true);
+
+ /** @type {number} */ var maxSteps = 1 << 16;
+ /** @type {Array<number>} */ var d = deMath.absDiff(line.p1, line.p0);
+ /** @type {Array<number>} */ var stepCount = deMath.divide([d, d, d, d], prec.colorThreshold);
+ /** @type {Array<number>} */
+ var minStep = deMath.divide([1, 1, 1, 1], deMath.add(stepCount, [1, 1, 1, 1]));
+ /** @type {number} */ var step = Math.max(tcuTexLookupVerifier.minComp(minStep), 1 / maxSteps);
+
+ return step;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad
+ * @return {number}
+ */
+ tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad = function(prec, quad) {
+ assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true);
+
+ /** @type {number} */ var maxSteps = 1 << 16;
+ /** @type {Array<number>} */ var d0 = deMath.absDiff(quad.p10, quad.p00);
+ /** @type {Array<number>} */ var d1 = deMath.absDiff(quad.p01, quad.p00);
+ /** @type {Array<number>} */ var d2 = deMath.absDiff(quad.p11, quad.p10);
+ /** @type {Array<number>} */ var d3 = deMath.absDiff(quad.p11, quad.p01);
+ /** @type {Array<number>} */ var maxD = deMath.max(d0, deMath.max(d1, deMath.max(d2, d3)));
+ /** @type {Array<number>} */ var stepCount = deMath.divide(maxD, prec.colorThreshold);
+ /** @type {Array<number>} */ var minStep = deMath.divide([1, 1, 1, 1], deMath.add(stepCount, [1, 1, 1, 1]));
+ /** @type {number} */ var step = Math.max(tcuTexLookupVerifier.minComp(minStep), 1 / maxSteps);
+
+ return step;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @return {number}
+ */
+ tcuTexLookupVerifier.computeBilinearSearchStepForUnorm = function(prec) {
+ assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true);
+
+ /** @type {Array<number>} */ var stepCount = deMath.divide([1, 1, 1, 1], prec.colorThreshold);
+ /** @type {Array<number>} */ var minStep = deMath.divide([1, 1, 1, 1], (deMath.add(stepCount, [1, 1, 1, 1])));
+ /** @type {number} */ var step = tcuTexLookupVerifier.minComp(minStep);
+
+ return step;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @return {number}
+ */
+ tcuTexLookupVerifier.computeBilinearSearchStepForSnorm = function(prec) {
+ assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true);
+
+ /** @type {Array<number>} */ var stepCount = deMath.divide([2.0, 2.0, 2.0, 2.0], prec.colorThreshold);
+ /** @type {Array<number>} */ var minStep = deMath.divide([1, 1, 1, 1], deMath.add(stepCount, [1, 1, 1, 1]));
+ /** @type {number} */ var step = tcuTexLookupVerifier.minComp(minStep);
+
+ return step;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.ColorLine} line
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.minLine = function(line) {
+ return deMath.min(line.p0, line.p1);
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.ColorLine} line
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.maxLine = function(line) {
+ var max = deMath.max;
+ return max(line.p0, line.p1);
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.ColorQuad} quad
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.minQuad = function(quad) {
+ var min = deMath.min;
+ return min(quad.p00, min(quad.p10, min(quad.p01, quad.p11)));
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.ColorQuad} quad
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.maxQuad = function(quad) {
+ var max = deMath.max;
+ return max(quad.p00, max(quad.p10, max(quad.p01, quad.p11)));
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isInColorBounds_1Quad = function(prec, quad, result) {
+ var quadMin = tcuTexLookupVerifier.minQuad;
+ var quadMax = tcuTexLookupVerifier.maxQuad;
+ /** @type {Array<number>} */ var minVal = deMath.subtract(quadMin(quad), prec.colorThreshold);
+ /** @type {Array<number>} */ var maxVal = deMath.add(quadMax(quad), prec.colorThreshold);
+ return deMath.boolAll(
+ deMath.logicalOrBool(
+ deMath.logicalAndBool(
+ deMath.greaterThanEqual(result, minVal),
+ deMath.lessThanEqual(result, maxVal)),
+ deMath.logicalNotBool(prec.colorMask)));
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad0
+ * @param {tcuTexLookupVerifier.ColorQuad} quad1
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isInColorBounds_2Quad = function(prec, quad0, quad1, result) {
+ var min = deMath.min;
+ var max = deMath.max;
+ var quadMin = tcuTexLookupVerifier.minQuad;
+ var quadMax = tcuTexLookupVerifier.maxQuad;
+ /** @type {Array<number>} */ var minVal = deMath.subtract(min(quadMin(quad0), quadMin(quad1)), prec.colorThreshold);
+ /** @type {Array<number>} */ var maxVal = deMath.add(max(quadMax(quad0), quadMax(quad1)), prec.colorThreshold);
+ return deMath.boolAll(
+ deMath.logicalOrBool(
+ deMath.logicalAndBool(
+ deMath.greaterThanEqual(result, minVal),
+ deMath.lessThanEqual(result, maxVal)),
+ deMath.logicalNotBool(prec.colorMask)));
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorLine} line0
+ * @param {tcuTexLookupVerifier.ColorLine} line1
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isInColorBounds_2Line = function(prec, line0, line1, result) {
+ var min = deMath.min;
+ var max = deMath.max;
+ var lineMin = tcuTexLookupVerifier.minLine;
+ var lineMax = tcuTexLookupVerifier.maxLine;
+ /** @type {Array<number>} */ var minVal = deMath.subtract(min(lineMin(line0), lineMin(line1)), prec.colorThreshold);
+ /** @type {Array<number>} */ var maxVal = deMath.add(max(lineMax(line0), lineMax(line1)), prec.colorThreshold);
+ return deMath.boolAll(
+ deMath.logicalOrBool(
+ deMath.logicalAndBool(
+ deMath.greaterThanEqual(result, minVal),
+ deMath.lessThanEqual(result, maxVal)),
+ deMath.logicalNotBool(prec.colorMask)));
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad00
+ * @param {tcuTexLookupVerifier.ColorQuad} quad01
+ * @param {tcuTexLookupVerifier.ColorQuad} quad10
+ * @param {tcuTexLookupVerifier.ColorQuad} quad11
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isInColorBounds_4Quad = function(prec, quad00, quad01, quad10, quad11, result) {
+ var min = deMath.min;
+ var max = deMath.max;
+ var quadMin = tcuTexLookupVerifier.minQuad;
+ var quadMax = tcuTexLookupVerifier.maxQuad;
+ /** @type {Array<number>} */ var minVal = deMath.subtract(min(quadMin(quad00), min(quadMin(quad01), min(quadMin(quad10), quadMin(quad11)))), prec.colorThreshold);
+ /** @type {Array<number>} */ var maxVal = deMath.add(max(quadMax(quad00), max(quadMax(quad01), max(quadMax(quad10), quadMax(quad11)))), prec.colorThreshold);
+ return deMath.boolAll(
+ deMath.logicalOrBool(
+ deMath.logicalAndBool(
+ deMath.greaterThanEqual(result, minVal),
+ deMath.lessThanEqual(result, maxVal)),
+ deMath.logicalNotBool(prec.colorMask)));
+ };
+
+ // Range search utilities
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} c0
+ * @param {Array<number>} c1
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLinearRangeValid = function(prec, c0, c1, fBounds, result) {
+ // This is basically line segment - AABB test. Valid interpolation line is checked
+ // against result AABB constructed by applying threshold.
+
+ /** @type {Array<number>} */ var rMin = deMath.subtract(result, prec.colorThreshold);
+ /** @type {Array<number>} */ var rMax = deMath.add(result, prec.colorThreshold);
+
+ // Algorithm: For each component check whether segment endpoints are inside, or intersect with slab.
+ // If all intersect or are inside, line segment intersects the whole 4D AABB.
+ for (var compNdx = 0; compNdx < 4; compNdx++) {
+ if (!prec.colorMask[compNdx])
+ continue;
+
+ /** @type {number} */ var i0 = c0[compNdx] * (1 - fBounds[0]) + c1[compNdx] * fBounds[0];
+ /** @type {number} */ var i1 = c0[compNdx] * (1 - fBounds[1]) + c1[compNdx] * fBounds[1];
+ if ((i0 > rMax[compNdx] && i1 > rMax[compNdx]) ||
+ (i0 < rMin[compNdx] && i1 < rMin[compNdx])) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad
+ * @param {Array<number>} xBounds
+ * @param {Array<number>} yBounds
+ * @param {number} searchStep
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isBilinearRangeValid = function(prec, quad, xBounds, yBounds, searchStep, result) {
+ assertMsgOptions(xBounds[0] <= xBounds[1], 'Out of bounds: X direction.', false, true);
+ assertMsgOptions(yBounds[0] <= yBounds[1], 'Out of bounds: Y direction.', false, true);
+
+ if (!tcuTexLookupVerifier.isInColorBounds_1Quad(prec, quad, result))
+ return false;
+
+ for (var x = xBounds[0]; x < xBounds[1] + searchStep; x += searchStep) {
+ /** @type {number} */ var a = Math.min(x, xBounds[1]);
+ /** @type {Array<number>} */ var c0 = deMath.add(deMath.scale(quad.p00, (1 - a)), deMath.scale(quad.p10, a));
+ /** @type {Array<number>} */ var c1 = deMath.add(deMath.scale(quad.p01, (1 - a)), deMath.scale(quad.p11, a));
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, yBounds, result))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad0
+ * @param {tcuTexLookupVerifier.ColorQuad} quad1
+ * @param {Array<number>} xBounds
+ * @param {Array<number>} yBounds
+ * @param {Array<number>} zBounds
+ * @param {number} searchStep
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isTrilinearRangeValid = function(prec, quad0, quad1, xBounds, yBounds, zBounds, searchStep, result) {
+ assertMsgOptions(xBounds[0] <= xBounds[1], 'Out of bounds: X direction.', false, true);
+ assertMsgOptions(yBounds[0] <= yBounds[1], 'Out of bounds: Y direction.', false, true);
+ assertMsgOptions(zBounds[0] <= zBounds[1], 'Out of bounds: Z direction.', false, true);
+
+ if (!tcuTexLookupVerifier.isInColorBounds_2Quad(prec, quad0, quad1, result))
+ return false;
+
+ for (var x = xBounds[0]; x < xBounds[1] + searchStep; x += searchStep) {
+ for (var y = yBounds[0]; y < yBounds[1] + searchStep; y += searchStep) {
+ /** @type {number} */ var a = Math.min(x, xBounds[1]);
+ /** @type {number} */ var b = Math.min(y, yBounds[1]);
+ /** @type {Array<number>} */
+ var c0 = deMath.add(
+ deMath.add(
+ deMath.add(
+ deMath.scale(quad0.p00, (1 - a) * (1 - b)),
+ deMath.scale(quad0.p10, a * (1 - b))),
+ deMath.scale(quad0.p01, (1 - a) * b)),
+ deMath.scale(quad0.p11, a * b));
+ /** @type {Array<number>} */
+ var c1 = deMath.add(
+ deMath.add(
+ deMath.add(
+ deMath.scale(quad1.p00, (1 - a) * (1 - b)),
+ deMath.scale(quad1.p10, a * (1 - b))),
+ deMath.scale(quad1.p01, (1 - a) * b)),
+ deMath.scale(quad1.p11, a * b));
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, zBounds, result))
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad0
+ * @param {tcuTexLookupVerifier.ColorQuad} quad1
+ * @param {Array<number>} xBounds0
+ * @param {Array<number>} yBounds0
+ * @param {Array<number>} xBounds1
+ * @param {Array<number>} yBounds1
+ * @param {Array<number>} zBounds
+ * @param {number} searchStep
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.is2DTrilinearFilterResultValid = function(prec, quad0, quad1, xBounds0, yBounds0, xBounds1, yBounds1, zBounds, searchStep, result) {
+ assertMsgOptions(xBounds0[0] <= xBounds0[1], 'Out of bounds: X direction.', false, true);
+ assertMsgOptions(yBounds0[0] <= yBounds0[1], 'Out of bounds: Y direction.', false, true);
+ assertMsgOptions(xBounds1[0] <= xBounds1[1], 'Out of bounds: X direction.', false, true);
+ assertMsgOptions(yBounds1[0] <= yBounds1[1], 'Out of bounds: Y direction.', false, true);
+
+ if (!tcuTexLookupVerifier.isInColorBounds_2Quad(prec, quad0, quad1, result))
+ return false;
+
+ for (var x0 = xBounds0[0]; x0 < xBounds0[1] + searchStep; x0 += searchStep) {
+ for (var y0 = yBounds0[0]; y0 < yBounds0[1] + searchStep; y0 += searchStep) {
+ /** @type {number} */ var a0 = Math.min(x0, xBounds0[1]);
+ /** @type {number} */ var b0 = Math.min(y0, yBounds0[1]);
+ /** @type {Array<number>} */
+ var c0 = deMath.add(
+ deMath.add(
+ deMath.add(
+ deMath.scale(quad0.p00, (1 - a0) * (1 - b0)),
+ deMath.scale(quad0.p10, a0 * (1 - b0))),
+ deMath.scale(quad0.p01, (1 - a0) * b0)),
+ deMath.scale(quad0.p11, a0 * b0));
+
+ for (var x1 = xBounds1[0]; x1 <= xBounds1[1]; x1 += searchStep) {
+ for (var y1 = yBounds1[0]; y1 <= yBounds1[1]; y1 += searchStep) {
+ /** @type {number} */ var a1 = Math.min(x1, xBounds1[1]);
+ /** @type {number} */ var b1 = Math.min(y1, yBounds1[1]);
+ /** @type {Array<number>} */
+ var c1 = deMath.add(
+ deMath.add(
+ deMath.add(
+ deMath.scale(quad1.p00, (1 - a1) * (1 - b1)),
+ deMath.scale(quad1.p10, a1 * (1 - b1))),
+ deMath.scale(quad1.p01, (1 - a1) * b1)),
+ deMath.scale(quad1.p11, a1 * b1));
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, zBounds, result))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexLookupVerifier.ColorQuad} quad00
+ * @param {tcuTexLookupVerifier.ColorQuad} quad01
+ * @param {tcuTexLookupVerifier.ColorQuad} quad10
+ * @param {tcuTexLookupVerifier.ColorQuad} quad11
+ * @param {Array<number>} xBounds0
+ * @param {Array<number>} yBounds0
+ * @param {Array<number>} zBounds0
+ * @param {Array<number>} xBounds1
+ * @param {Array<number>} yBounds1
+ * @param {Array<number>} zBounds1
+ * @param {Array<number>} wBounds
+ * @param {number} searchStep
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.is3DTrilinearFilterResultValid = function(prec, quad00, quad01, quad10, quad11, xBounds0, yBounds0, zBounds0, xBounds1, yBounds1, zBounds1, wBounds, searchStep, result) {
+ assertMsgOptions(xBounds0[0] <= xBounds0[1], 'Out of bounds: X direction.', false, true);
+ assertMsgOptions(yBounds0[0] <= yBounds0[1], 'Out of bounds: Y direction.', false, true);
+ assertMsgOptions(zBounds0[0] <= zBounds0[1], 'Out of bounds: Z direction.', false, true);
+ assertMsgOptions(xBounds1[0] <= xBounds1[1], 'Out of bounds: X direction.', false, true);
+ assertMsgOptions(yBounds1[0] <= yBounds1[1], 'Out of bounds: Y direction.', false, true);
+ assertMsgOptions(zBounds1[0] <= zBounds1[1], 'Out of bounds: Z direction.', false, true);
+
+ if (!tcuTexLookupVerifier.isInColorBounds_4Quad(prec, quad00, quad01, quad10, quad11, result))
+ return false;
+
+ function biInterp(result, p00, p01, p10, p11, s00, s01, s10, s11) {
+ for (var ii = 0; ii < 4; ++ii) {
+ result[ii] = p00[ii] * s00 + p10[ii] * s10 + p01[ii] * s01 + p11[ii] * s11;
+ }
+ }
+
+ function interp(result, p0, p1, s) {
+ for (var ii = 0; ii < 4; ++ii) {
+ result[ii] = p0[ii] * (1 - s) + p1[ii] * s;
+ }
+ }
+
+ /** @type {Array<number>} */ var c00 = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var c01 = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var c10 = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var c11 = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var cz0 = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var cz1 = [0, 0, 0, 0];
+
+ for (var x0 = xBounds0[0]; x0 < xBounds0[1] + searchStep; x0 += searchStep) {
+ for (var y0 = yBounds0[0]; y0 < yBounds0[1] + searchStep; y0 += searchStep) {
+ /** @type {number} */ var a0 = Math.min(x0, xBounds0[1]);
+ /** @type {number} */ var b0 = Math.min(y0, yBounds0[1]);
+
+ /** @type {number} */ var s00 = (1 - a0) * (1 - b0);
+ /** @type {number} */ var s01 = (1 - a0) * b0;
+ /** @type {number} */ var s10 = a0 * (1 - b0);
+ /** @type {number} */ var s11 = a0 * b0;
+
+ biInterp(c00, quad00.p00, quad00.p01, quad00.p10, quad00.p11, s00, s01, s10, s11);
+ biInterp(c01, quad01.p00, quad01.p01, quad01.p10, quad01.p11, s00, s01, s10, s11);
+
+ for (var z0 = zBounds0[0]; z0 < zBounds0[1] + searchStep; z0 += searchStep) {
+ /** @type {number} */ var c0 = Math.min(z0, zBounds0[1]);
+ interp(cz0, c00, c01, c0);
+
+ for (var x1 = xBounds1[0]; x1 < xBounds1[1] + searchStep; x1 += searchStep) {
+ for (var y1 = yBounds1[0]; y1 < yBounds1[1] + searchStep; y1 += searchStep) {
+ /** @type {number} */ var a1 = Math.min(x1, xBounds1[1]);
+ /** @type {number} */ var b1 = Math.min(y1, yBounds1[1]);
+
+ /** @type {number} */ var t00 = (1 - a1) * (1 - b1);
+ /** @type {number} */ var t01 = (1 - a1) * b1;
+ /** @type {number} */ var t10 = a1 * (1 - b1);
+ /** @type {number} */ var t11 = a1 * b1;
+
+ biInterp(c10, quad10.p00, quad10.p01, quad10.p10, quad10.p11, t00, t01, t10, t11);
+ biInterp(c11, quad11.p00, quad11.p01, quad11.p10, quad11.p11, t00, t01, t10, t11);
+
+ for (var z1 = zBounds1[0]; z1 < zBounds1[1] + searchStep; z1 += searchStep) {
+ /** @type {number} */ var c1 = Math.min(z1, zBounds1[1]);
+ interp(cz1, c10, c11, c1);
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, cz0, cz1, wBounds, result))
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {number} coordX
+ * @param {number} coordY
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isNearestSampleResultValid_CoordXYAsNumber = function(level, sampler, prec, coordX, coordY, result) {
+ assertMsgOptions(level.getDepth() == 1, 'Depth must be 1.', false, true);
+
+ /** @type {Array<number>} */
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getWidth(), coordX, prec.coordBits[0], prec.uvwBits[0]);
+
+ /** @type {number} */ var minI = Math.floor(uBounds[0]);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1]);
+
+ for (var i = minI; i <= maxI; i++) {
+ /** @type {number} */ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth());
+ /** @type {Array<number>} */ var color;
+ if (tcuTexLookupVerifier.isSRGB(level.getFormat())) {
+ color = tcuTexLookupVerifier.lookupFloat(level, sampler, x, coordY, 0);
+ } else {
+ color = tcuTexLookupVerifier.lookupScalar(level, sampler, x, coordY, 0);
+ }
+
+ if (tcuTexLookupVerifier.isColorValid(prec, color, result))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord vec2
+ * @param {number} coordZ int
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt = function(level, sampler, prec, coord, coordZ, result) {
+ /** @type {Array<number>} */
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI = Math.floor(uBounds[0]);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1]);
+ /** @type {number} */ var minJ = Math.floor(vBounds[0]);
+ /** @type {number} */ var maxJ = Math.floor(vBounds[1]);
+
+ // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
+
+ for (var j = minJ; j <= maxJ; j++)
+ for (var i = minI; i <= maxI; i++) {
+ /** @type {number} */ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth());
+ /** @type {number} */ var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight());
+ /** @type {Array<number>} */ var color;
+ if (tcuTexLookupVerifier.isSRGB(level.getFormat())) {
+ color = tcuTexLookupVerifier.lookupFloat(level, sampler, x, y, coordZ);
+ } else {
+ color = tcuTexLookupVerifier.lookupScalar(level, sampler, x, y, coordZ);
+ }
+
+ if (tcuTexLookupVerifier.isColorValid(prec, color, result))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord vec3
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec3 = function(level, sampler, prec, coord, result) {
+ /** @type {Array<number>} */
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var wBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getDepth(), coord[2], prec.coordBits[2], prec.uvwBits[2]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI = Math.floor(uBounds[0]);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1]);
+ /** @type {number} */ var minJ = Math.floor(vBounds[0]);
+ /** @type {number} */ var maxJ = Math.floor(vBounds[1]);
+ /** @type {number} */ var minK = Math.floor(wBounds[0]);
+ /** @type {number} */ var maxK = Math.floor(wBounds[1]);
+
+ // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
+
+ for (var k = minK; k <= maxK; k++) {
+ for (var j = minJ; j <= maxJ; j++) {
+ for (var i = minI; i <= maxI; i++) {
+ /** @type {number} */ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth());
+ /** @type {number} */ var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight());
+ /** @type {number} */ var z = tcuTexVerifierUtil.wrap(sampler.wrapR, k, level.getDepth());
+ /** @type {Array<number>} */ var color;
+ if (tcuTexLookupVerifier.isSRGB(level.getFormat())) {
+ color = tcuTexLookupVerifier.lookupFloat(level, sampler, x, y, z);
+ } else {
+ color = tcuTexLookupVerifier.lookupScalar(level, sampler, x, y, z);
+ }
+
+ if (tcuTexLookupVerifier.isColorValid(prec, color, result))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {number} coordX
+ * @param {number} coordY
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLinearSampleResultValid_CoordXYAsNumber = function(level, sampler, prec, coordX, coordY, result) {
+ /** @type {Array<number>} */ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coordX, prec.coordBits[0], prec.uvwBits[0]);
+
+ /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5);
+
+ /** @type {number} */ var w = level.getWidth();
+
+ for (var i = minI; i <= maxI; i++) {
+ // Wrapped coordinates
+ /** @type {number} */ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w);
+ /** @type {number} */ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w);
+
+ // Bounds for filtering factors
+ /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
+ /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
+
+ /** @type {Array<number>} */ var colorA = tcuTexLookupVerifier.lookupFloat(level, sampler, x0, coordY, 0);
+ /** @type {Array<number>} */ var colorB = tcuTexLookupVerifier.lookupFloat(level, sampler, x1, coordY, 0);
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, colorA, colorB, [minA, maxA], result))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord vec2
+ * @param {number} coordZ int
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec2AndInt = function(level, sampler, prec, coord, coordZ, result) {
+ /** @type {Array<number>} */ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinate bounds for (x0,y0) - without wrap mode
+ /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5);
+ /** @type {number} */ var minJ = Math.floor(vBounds[0] - 0.5);
+ /** @type {number} */ var maxJ = Math.floor(vBounds[1] - 0.5);
+
+ /** @type {number} */ var w = level.getWidth();
+ /** @type {number} */ var h = level.getHeight();
+
+ /** @type {tcuTexture.TextureChannelClass} */
+ var texClass = tcuTexture.getTextureChannelClass(level.getFormat().type);
+
+ /** @type {number} */
+ var searchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) :
+ (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) :
+ 0; // Step is computed for floating-point quads based on texel values.
+
+ // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
+
+ for (var j = minJ; j <= maxJ; j++)
+ for (var i = minI; i <= maxI; i++) {
+ // Wrapped coordinates
+ /** @type {number} */ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w);
+ /** @type {number} */ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w);
+ /** @type {number} */ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h);
+ /** @type {number} */ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h);
+
+ // Bounds for filtering factors
+ /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
+ /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
+ /** @type {number} */ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
+ /** @type {number} */ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
+
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad = tcuTexLookupVerifier.lookupQuad(level, sampler, x0, x1, y0, y1, coordZ);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad);
+
+ if (tcuTexLookupVerifier.isBilinearRangeValid(prec, quad, [minA, maxA], [minB, maxB], searchStep, result))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord vec3
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec3 = function(level, sampler, prec, coord, result) {
+ /** @type {Array<number>} */
+ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var wBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, level.getDepth(), coord[2], prec.coordBits[2], prec.uvwBits[2]);
+
+ // Integer coordinate bounds for (x0,y0) - without wrap mode
+ /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5);
+ /** @type {number} */ var minJ = Math.floor(vBounds[0] - 0.5);
+ /** @type {number} */ var maxJ = Math.floor(vBounds[1] - 0.5);
+ /** @type {number} */ var minK = Math.floor(wBounds[0] - 0.5);
+ /** @type {number} */ var maxK = Math.floor(wBounds[1] - 0.5);
+
+ /** @type {number} */ var w = level.getWidth();
+ /** @type {number} */ var h = level.getHeight();
+ /** @type {number} */ var d = level.getDepth();
+
+ /** @type {tcuTexture.TextureChannelClass} */
+ var texClass = tcuTexture.getTextureChannelClass(level.getFormat().type);
+ /** @type {number} */
+ var searchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) :
+ (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) :
+ 0; // Step is computed for floating-point quads based on texel values.
+
+ // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
+
+ for (var k = minK; k <= maxK; k++) {
+ for (var j = minJ; j <= maxJ; j++) {
+ for (var i = minI; i <= maxI; i++) {
+ // Wrapped coordinates
+ /** @type {number} */ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w);
+ /** @type {number} */ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w);
+ /** @type {number} */ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h);
+ /** @type {number} */ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h);
+ /** @type {number} */ var z0 = tcuTexVerifierUtil.wrap(sampler.wrapR, k, d);
+ /** @type {number} */ var z1 = tcuTexVerifierUtil.wrap(sampler.wrapR, k + 1, d);
+
+ // Bounds for filtering factors
+ /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
+ /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
+ /** @type {number} */ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
+ /** @type {number} */ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
+ /** @type {number} */ var minC = deMath.clamp((wBounds[0] - 0.5) - k, 0, 1);
+ /** @type {number} */ var maxC = deMath.clamp((wBounds[1] - 0.5) - k, 0, 1);
+
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad0 = tcuTexLookupVerifier.lookupQuad(level, sampler, x0, x1, y0, y1, z0);
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad1 = tcuTexLookupVerifier.lookupQuad(level, sampler, x0, x1, y0, y1, z1);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep = Math.min(tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad0), tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad1));
+
+ if (tcuTexLookupVerifier.isTrilinearRangeValid(prec, quad0, quad1, [minA, maxA], [minB, maxB], [minC, maxC], searchStep, result))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {number} coord
+ * @param {number} coordY
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordXYAsNumber = function(level0, level1, sampler, prec, coord, coordY, fBounds, result) {
+ /** @type {number} */ var w0 = level0.getWidth();
+ /** @type {number} */ var w1 = level1.getWidth();
+
+ /** @type {Array<number>} */
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w0, coord, prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w1, coord, prec.coordBits[0], prec.uvwBits[0]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI0 = Math.floor(uBounds0[0]);
+ /** @type {number} */ var maxI0 = Math.floor(uBounds0[1]);
+ /** @type {number} */ var minI1 = Math.floor(uBounds1[0]);
+ /** @type {number} */ var maxI1 = Math.floor(uBounds1[1]);
+
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ /** @type {Array<number>} */
+ var c0 = tcuTexLookupVerifier.lookupFloat(level0, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0), coordY, 0);
+ /** @type {Array<number>} */
+ var c1 = tcuTexLookupVerifier.lookupFloat(level1, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1), coordY, 0);
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, fBounds, result))
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {number} coordZ
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec2AndInt = function(level0, level1, sampler, prec, coord, coordZ, fBounds, result) {
+ /** @type {number} */ var w0 = level0.getWidth();
+ /** @type {number} */ var w1 = level1.getWidth();
+ /** @type {number} */ var h0 = level0.getHeight();
+ /** @type {number} */ var h1 = level1.getHeight();
+
+ /** @type {Array<number>} */
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI0 = Math.floor(uBounds0[0]);
+ /** @type {number} */ var maxI0 = Math.floor(uBounds0[1]);
+ /** @type {number} */ var minI1 = Math.floor(uBounds1[0]);
+ /** @type {number} */ var maxI1 = Math.floor(uBounds1[1]);
+ /** @type {number} */ var minJ0 = Math.floor(vBounds0[0]);
+ /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1]);
+ /** @type {number} */ var minJ1 = Math.floor(vBounds1[0]);
+ /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1]);
+
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ /** @type {Array<number>} */ var c0 = tcuTexLookupVerifier.lookupFloat(level0, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0), tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0), coordZ);
+ /** @type {Array<number>} */ var c1 = tcuTexLookupVerifier.lookupFloat(level1, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1), tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1), coordZ);
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, fBounds, result))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec3 = function(level0, level1, sampler, prec, coord, fBounds, result) {
+ /** @type {number} */ var w0 = level0.getWidth();
+ /** @type {number} */ var w1 = level1.getWidth();
+ /** @type {number} */ var h0 = level0.getHeight();
+ /** @type {number} */ var h1 = level1.getHeight();
+ /** @type {number} */ var d0 = level0.getDepth();
+ /** @type {number} */ var d1 = level1.getDepth();
+
+ /** @type {Array<number>} */
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var wBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, d0, coord[2], prec.coordBits[2], prec.uvwBits[2]);
+ /** @type {Array<number>} */
+ var wBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, d1, coord[2], prec.coordBits[2], prec.uvwBits[2]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI0 = Math.floor(uBounds0[0]);
+ /** @type {number} */ var maxI0 = Math.floor(uBounds0[1]);
+ /** @type {number} */ var minI1 = Math.floor(uBounds1[0]);
+ /** @type {number} */ var maxI1 = Math.floor(uBounds1[1]);
+ /** @type {number} */ var minJ0 = Math.floor(vBounds0[0]);
+ /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1]);
+ /** @type {number} */ var minJ1 = Math.floor(vBounds1[0]);
+ /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1]);
+ /** @type {number} */ var minK0 = Math.floor(wBounds0[0]);
+ /** @type {number} */ var maxK0 = Math.floor(wBounds0[1]);
+ /** @type {number} */ var minK1 = Math.floor(wBounds1[0]);
+ /** @type {number} */ var maxK1 = Math.floor(wBounds1[1]);
+
+ for (var k0 = minK0; k0 <= maxK0; k0++) {
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ for (var k1 = minK1; k1 <= maxK1; k1++) {
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ /** @type {Array<number>} */ var c0 = tcuTexLookupVerifier.lookupFloat(level0, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0), tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0), tcuTexVerifierUtil.wrap(sampler.wrapR, k0, d0));
+ /** @type {Array<number>} */ var c1 = tcuTexLookupVerifier.lookupFloat(level1, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1), tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1), tcuTexVerifierUtil.wrap(sampler.wrapR, k1, d1));
+
+ if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, fBounds, result))
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {number} coordZ
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec2AndInt = function(level0, level1, sampler, prec, coord, coordZ, fBounds, result) {
+ // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
+ // Right now this allows pairing any two valid bilinear quads.
+
+ /** @type {number} */ var w0 = level0.getWidth();
+ /** @type {number} */ var w1 = level1.getWidth();
+ /** @type {number} */ var h0 = level0.getHeight();
+ /** @type {number} */ var h1 = level1.getHeight();
+
+ /** @type {Array<number>} */
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI0 = Math.floor(uBounds0[0] - 0.5);
+ /** @type {number} */ var maxI0 = Math.floor(uBounds0[1] - 0.5);
+ /** @type {number} */ var minI1 = Math.floor(uBounds1[0] - 0.5);
+ /** @type {number} */ var maxI1 = Math.floor(uBounds1[1] - 0.5);
+ /** @type {number} */ var minJ0 = Math.floor(vBounds0[0] - 0.5);
+ /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1] - 0.5);
+ /** @type {number} */ var minJ1 = Math.floor(vBounds1[0] - 0.5);
+ /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1] - 0.5);
+
+ /** @type {tcuTexture.TextureChannelClass} */
+ var texClass = tcuTexture.getTextureChannelClass(level0.getFormat().type);
+ /** @type {number} */ var cSearchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) :
+ (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) :
+ 0; // Step is computed for floating-point quads based on texel values.
+
+ /** @type {number} */ var x0;
+ /** @type {number} */ var x1;
+ /** @type {number} */ var y0;
+ /** @type {number} */ var y1;
+
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ /** @type {number} */ var searchStep0;
+
+ x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0);
+ x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0);
+ y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0);
+ y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0);
+
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad0 = tcuTexLookupVerifier.lookupQuad(level0, sampler, x0, x1, y0, y1, coordZ);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep0 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad0);
+ else
+ searchStep0 = cSearchStep;
+
+ /** @type {number} */ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
+ /** @type {number} */ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
+ /** @type {number} */ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
+ /** @type {number} */ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
+
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ /** @type {number} */ var searchStep1;
+
+ x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1);
+ x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1);
+ y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1);
+ y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1);
+
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad1 = tcuTexLookupVerifier.lookupQuad(level1, sampler, x0, x1, y0, y1, coordZ);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep1 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad1);
+ else
+ searchStep1 = cSearchStep;
+
+ /** @type {number} */ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
+ /** @type {number} */ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
+ /** @type {number} */ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
+ /** @type {number} */ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
+
+ if (tcuTexLookupVerifier.is2DTrilinearFilterResultValid(prec, quad0, quad1, [minA0, maxA0], [minB0, maxB0], [minA1, maxA1], [minB1, maxB1],
+ fBounds, Math.min(searchStep0, searchStep1), result))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec3 = function(level0, level1, sampler, prec, coord, fBounds, result) {
+ // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
+ // Right now this allows pairing any two valid bilinear quads.
+
+ /** @type {number} */ var w0 = level0.getWidth();
+ /** @type {number} */ var w1 = level1.getWidth();
+ /** @type {number} */ var h0 = level0.getHeight();
+ /** @type {number} */ var h1 = level1.getHeight();
+ /** @type {number} */ var d0 = level0.getDepth();
+ /** @type {number} */ var d1 = level1.getDepth();
+
+ /** @type {Array<number>} */
+ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */
+ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */
+ var wBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, d0, coord[2], prec.coordBits[2], prec.uvwBits[2]);
+ /** @type {Array<number>} */
+ var wBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(
+ sampler.normalizedCoords, d1, coord[2], prec.coordBits[2], prec.uvwBits[2]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI0 = Math.floor(uBounds0[0] - 0.5);
+ /** @type {number} */ var maxI0 = Math.floor(uBounds0[1] - 0.5);
+ /** @type {number} */ var minI1 = Math.floor(uBounds1[0] - 0.5);
+ /** @type {number} */ var maxI1 = Math.floor(uBounds1[1] - 0.5);
+ /** @type {number} */ var minJ0 = Math.floor(vBounds0[0] - 0.5);
+ /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1] - 0.5);
+ /** @type {number} */ var minJ1 = Math.floor(vBounds1[0] - 0.5);
+ /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1] - 0.5);
+ /** @type {number} */ var minK0 = Math.floor(wBounds0[0] - 0.5);
+ /** @type {number} */ var maxK0 = Math.floor(wBounds0[1] - 0.5);
+ /** @type {number} */ var minK1 = Math.floor(wBounds1[0] - 0.5);
+ /** @type {number} */ var maxK1 = Math.floor(wBounds1[1] - 0.5);
+
+ /** @type {tcuTexture.TextureChannelClass} */
+ var texClass = tcuTexture.getTextureChannelClass(level0.getFormat().type);
+ /** @type {number} */ var cSearchStep = texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) :
+ texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) :
+ 0; // Step is computed for floating-point quads based on texel values.
+
+ /** @type {number} */ var x0;
+ /** @type {number} */ var x1;
+ /** @type {number} */ var y0;
+ /** @type {number} */ var y1;
+ /** @type {number} */ var z0;
+ /** @type {number} */ var z1;
+
+ for (var k0 = minK0; k0 <= maxK0; k0++) {
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ /** @type {number} */ var searchStep0;
+
+ x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0);
+ x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0);
+ y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0);
+ y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0);
+ z0 = tcuTexVerifierUtil.wrap(sampler.wrapR, k0, d0);
+ z1 = tcuTexVerifierUtil.wrap(sampler.wrapR, k0 + 1, d0);
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad00 = tcuTexLookupVerifier.lookupQuad(level0, sampler, x0, x1, y0, y1, z0);
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad01 = tcuTexLookupVerifier.lookupQuad(level0, sampler, x0, x1, y0, y1, z1);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep0 = Math.min(tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad00), tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad01));
+ else
+ searchStep0 = cSearchStep;
+
+ /** @type {number} */ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
+ /** @type {number} */ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
+ /** @type {number} */ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
+ /** @type {number} */ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
+ /** @type {number} */ var minC0 = deMath.clamp((wBounds0[0] - 0.5) - k0, 0, 1);
+ /** @type {number} */ var maxC0 = deMath.clamp((wBounds0[1] - 0.5) - k0, 0, 1);
+
+ for (var k1 = minK1; k1 <= maxK1; k1++) {
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+
+ /** @type {number} */ var searchStep1;
+
+ x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1);
+ x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1);
+ y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1);
+ y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1);
+ z0 = tcuTexVerifierUtil.wrap(sampler.wrapR, k1, d1);
+ z1 = tcuTexVerifierUtil.wrap(sampler.wrapR, k1 + 1, d1);
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad10 = tcuTexLookupVerifier.lookupQuad(level1, sampler, x0, x1, y0, y1, z0);
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad11 = tcuTexLookupVerifier.lookupQuad(level1, sampler, x0, x1, y0, y1, z1);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep1 = Math.min(tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad10), tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad11));
+ else
+ searchStep1 = cSearchStep;
+
+ /** @type {number} */ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
+ /** @type {number} */ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
+ /** @type {number} */ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
+ /** @type {number} */ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
+ /** @type {number} */ var minC1 = deMath.clamp((wBounds1[0] - 0.5) - k1, 0, 1);
+ /** @type {number} */ var maxC1 = deMath.clamp((wBounds1[1] - 0.5) - k1, 0, 1);
+
+ if (tcuTexLookupVerifier.is3DTrilinearFilterResultValid(
+ prec, quad00, quad01, quad10, quad11,
+ [minA0, maxA0], [minB0, maxB0], [minC0, maxC0],
+ [minA1, maxA1], [minB1, maxB1], [minC1, maxC1],
+ fBounds, Math.min(searchStep0, searchStep1), result))
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filterMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {number} coordX
+ * @param {number} coordY
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevelSampleResultValid_CoordXYAsNumber = function(level, sampler, filterMode, prec, coordX, coordY, result) {
+ if (filterMode == tcuTexture.FilterMode.LINEAR)
+ return tcuTexLookupVerifier.isLinearSampleResultValid_CoordXYAsNumber(level, sampler, prec, coordX, coordY, result);
+ else
+ return tcuTexLookupVerifier.isNearestSampleResultValid_CoordXYAsNumber(level, sampler, prec, coordX, coordY, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filterMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {number} coordZ
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt = function(level, sampler, filterMode, prec, coord, coordZ, result) {
+ if (filterMode == tcuTexture.FilterMode.LINEAR)
+ return tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec2AndInt(level, sampler, prec, coord, coordZ, result);
+ else
+ return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt(level, sampler, prec, coord, coordZ, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filterMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3 = function(level, sampler, filterMode, prec, coord, result) {
+ if (filterMode == tcuTexture.FilterMode.LINEAR)
+ return tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec3(level, sampler, prec, coord, result);
+ else
+ return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec3(level, sampler, prec, coord, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} levelFilter
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {number} coordZ
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec2AndInt = function(level0, level1, sampler, levelFilter, prec, coord, coordZ, fBounds, result) {
+ if (levelFilter == tcuTexture.FilterMode.LINEAR)
+ return tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec2AndInt(level0, level1, sampler, prec, coord, coordZ, fBounds, result);
+ else
+ return tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec2AndInt(level0, level1, sampler, prec, coord, coordZ, fBounds, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} level0
+ * @param {tcuTexture.ConstPixelBufferAccess} level1
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} levelFilter
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec3 = function(level0, level1, sampler, levelFilter, prec, coord, fBounds, result) {
+ if (levelFilter == tcuTexture.FilterMode.LINEAR)
+ return tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec3(level0, level1, sampler, prec, coord, fBounds, result);
+ else
+ return tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec3(level0, level1, sampler, prec, coord, fBounds, result);
+ };
+
+ /**
+ * @param {tcuTexture.Texture2DView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} lodBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLookupResultValid_Texture2DView = function(texture, sampler, prec, coord, lodBounds, result) {
+ /** @type {number} */ var minLod = lodBounds[0];
+ /** @type {number} */ var maxLod = lodBounds[1];
+ /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold;
+ /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true);
+
+ /** @type {number} */ var minLevel;
+ /** @type {number} */ var maxLevel;
+
+ if (canBeMagnified)
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, result))
+ return true;
+
+ if (canBeMinified) {
+ /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ /** @type {number} */ var minTexLevel = 0;
+ /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true);
+
+ if (isLinearMipmap && minTexLevel < maxTexLevel) {
+ minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ /** @type {number} */ var minF = deMath.clamp(minLod - level, 0, 1);
+ /** @type {number} */ var maxF = deMath.clamp(maxLod - level, 0, 1);
+
+ if (tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, [minF, maxF], result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, result))
+ return true;
+ }
+ } else {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, result))
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} lodBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLookupResultValid_TextureCubeView = function(texture, sampler, prec, coord, lodBounds, result) {
+ /** @type {number} */ var numPossibleFaces = 0;
+
+ assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true);
+
+ /** @type {Array<tcuTexture.CubeFace>} */ var possibleFaces = tcuTexVerifierUtil.getPossibleCubeFaces(coord, prec.coordBits);
+
+ /** @type {number} */ var minLevel;
+ /** @type {number} */ var maxLevel;
+
+ if (!possibleFaces)
+ return true; // Result is undefined.
+
+ for (var tryFaceNdx = 0; tryFaceNdx < possibleFaces.length; tryFaceNdx++) {
+ /** @type {tcuTexture.CubeFaceCoords} */
+ var faceCoords = new tcuTexture.CubeFaceCoords(possibleFaces[tryFaceNdx], tcuTexture.projectToFace(possibleFaces[tryFaceNdx], coord));
+ /** @type {number} */ var minLod = lodBounds[0];
+ /** @type {number} */ var maxLod = lodBounds[1];
+ /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold;
+ /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces = [];
+ if (canBeMagnified) {
+ tcuTexLookupVerifier.getCubeLevelFaces(texture, 0, faces);
+
+ if (tcuTexLookupVerifier.isCubeLevelSampleResultValid(faces, sampler, sampler.magFilter, prec, faceCoords, result))
+ return true;
+ }
+
+ if (canBeMinified) {
+ /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ /** @type {number} */ var minTexLevel = 0;
+ /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true);
+
+ if (isLinearMipmap && minTexLevel < maxTexLevel) {
+ minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++) {
+ /** @type {number} */ var minF = deMath.clamp(minLod - levelNdx, 0, 1);
+ /** @type {number} */ var maxF = deMath.clamp(maxLod - levelNdx, 0, 1);
+
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces0 = [];
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces1 = [];
+
+ tcuTexLookupVerifier.getCubeLevelFaces(texture, levelNdx, faces0);
+ tcuTexLookupVerifier.getCubeLevelFaces(texture, levelNdx + 1, faces1);
+
+ if (tcuTexLookupVerifier.isCubeMipmapLinearSampleResultValid(faces0, faces1, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, [minF, maxF], result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++) {
+ tcuTexLookupVerifier.getCubeLevelFaces(texture, levelNdx, faces);
+
+ if (tcuTexLookupVerifier.isCubeLevelSampleResultValid(faces, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, result))
+ return true;
+ }
+ } else {
+ tcuTexLookupVerifier.getCubeLevelFaces(texture, 0, faces);
+
+ if (tcuTexLookupVerifier.isCubeLevelSampleResultValid(faces, sampler, sampler.minFilter, prec, faceCoords, result))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.Texture2DArrayView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} lodBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLookupResultValid_Texture2DArrayView = function(texture, sampler, prec, coord, lodBounds, result) {
+ /** @type {Array<number>} */ var layerRange = tcuTexLookupVerifier.computeLayerRange(texture.getNumLayers(), prec.coordBits[2], coord[2]);
+ /** @type {Array<number>} */ var coordXY = deMath.swizzle(coord, [0, 1]);
+ /** @type {number} */ var minLod = lodBounds[0];
+ /** @type {number} */ var maxLod = lodBounds[1];
+ /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold;
+ /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true);
+ /** @type {number} */ var minLevel;
+ /** @type {number} */ var maxLevel;
+
+ for (var layer = layerRange[0]; layer <= layerRange[1]; layer++) {
+ if (canBeMagnified) {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.magFilter, prec, coordXY, layer, result))
+ return true;
+ }
+
+ if (canBeMinified) {
+ /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ /** @type {number} */ var minTexLevel = 0;
+ /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true);
+
+ if (isLinearMipmap && minTexLevel < maxTexLevel) {
+ minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ /** @type {number} */ var minF = deMath.clamp(minLod - level, 0, 1);
+ /** @type {number} */ var maxF = deMath.clamp(maxLod - level, 0, 1);
+
+ if (tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coordXY, layer, [minF, maxF], result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coordXY, layer, result))
+ return true;
+ }
+ } else {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.minFilter, prec, coordXY, layer, result))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {tcuTexture.Texture3DView} texture
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} lodBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLookupResultValid = function(texture, sampler, prec, coord, lodBounds, result) {
+ /** @type {number} */ var minLod = lodBounds[0];
+ /** @type {number} */ var maxLod = lodBounds[1];
+ /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold;
+ /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold;
+
+ assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true);
+
+ /** @type {number} */ var minLevel;
+ /** @type {number} */ var maxLevel;
+
+ if (canBeMagnified)
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, result))
+ return true;
+
+ if (canBeMinified) {
+ /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
+ /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
+ /** @type {number} */ var minTexLevel = 0;
+ /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1;
+
+ assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true);
+
+ if (isLinearMipmap && minTexLevel < maxTexLevel) {
+ minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
+ maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ /** @type {number} */ var minF = deMath.clamp(minLod - level, 0, 1);
+ /** @type {number} */ var maxF = deMath.clamp(maxLod - level, 0, 1);
+
+ if (tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec3(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, [minF, maxF], result))
+ return true;
+ }
+ } else if (isNearestMipmap) {
+ // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
+ // decision to allow floor(lod + 0.5) as well.
+ minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
+ maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
+
+ assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true);
+
+ for (var level = minLevel; level <= maxLevel; level++) {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, result))
+ return true;
+ }
+ } else {
+ if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, result))
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces (&faces)[CUBEFACE_LAST]
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isSeamlessLinearSampleResultValid = function(faces, sampler, prec, coords, result) {
+ /** @type {number} */ var size = faces[coords.face].getWidth();
+
+ /** @type {Array<number>} */ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinate bounds for (x0,y0) - without wrap mode
+ /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5);
+ /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5);
+ /** @type {number} */ var minJ = Math.floor(vBounds[0] - 0.5);
+ /** @type {number} */ var maxJ = Math.floor(vBounds[1] - 0.5);
+
+ /** @type {tcuTexture.TextureChannelClass} */ var texClass = tcuTexture.getTextureChannelClass(faces[coords.face].getFormat().type);
+ /** @type {number} */ var searchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) :
+ (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) :
+ 0; // Step is computed for floating-point quads based on texel values.
+
+ for (var j = minJ; j <= maxJ; j++) {
+ for (var i = minI; i <= maxI; i++) {
+ /** @type {tcuTexture.CubeFaceCoords} */ var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 0]), size);
+ /** @type {tcuTexture.CubeFaceCoords} */ var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 0]), size);
+ /** @type {tcuTexture.CubeFaceCoords} */ var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 1]), size);
+ /** @type {tcuTexture.CubeFaceCoords} */ var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 1]), size);
+
+ // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
+ // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
+ if (c00 == null || c01 == null || c10 == null || c11 == null ||
+ c00.face == null || c01.face == null || c10.face == null || c11.face == null)
+ return true;
+
+ // Bounds for filtering factors
+ /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
+ /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
+ /** @type {number} */ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
+ /** @type {number} */ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
+
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad = new tcuTexLookupVerifier.ColorQuad([], [], [], []);
+ quad.p00 = tcuTexLookupVerifier.lookupFloat(faces[c00.face], sampler, c00.s, c00.t, 0);
+ quad.p10 = tcuTexLookupVerifier.lookupFloat(faces[c10.face], sampler, c10.s, c10.t, 0);
+ quad.p01 = tcuTexLookupVerifier.lookupFloat(faces[c01.face], sampler, c01.s, c01.t, 0);
+ quad.p11 = tcuTexLookupVerifier.lookupFloat(faces[c11.face], sampler, c11.s, c11.t, 0);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad);
+
+ if (tcuTexLookupVerifier.isBilinearRangeValid(prec, quad, [minA, maxA], [minB, maxB], searchStep, result))
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces0 (&faces0)[CUBEFACE_LAST]
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces1 (&faces1)[CUBEFACE_LAST]
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isSeamplessLinearMipmapLinearSampleResultValid = function(faces0, faces1, sampler, prec, coords, fBounds, result) {
+ // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
+ // Right now this allows pairing any two valid bilinear quads.
+ /** @type {number} */ var size0 = faces0[coords.face].getWidth();
+ /** @type {number} */ var size1 = faces1[coords.face].getWidth();
+
+ /** @type {Array<number>} */ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits[0], prec.uvwBits[0]);
+ /** @type {Array<number>} */ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits[1], prec.uvwBits[1]);
+ /** @type {Array<number>} */ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits[1], prec.uvwBits[1]);
+
+ // Integer coordinates - without wrap mode
+ /** @type {number} */ var minI0 = Math.floor(uBounds0[0] - 0.5);
+ /** @type {number} */ var maxI0 = Math.floor(uBounds0[1] - 0.5);
+ /** @type {number} */ var minI1 = Math.floor(uBounds1[0] - 0.5);
+ /** @type {number} */ var maxI1 = Math.floor(uBounds1[1] - 0.5);
+ /** @type {number} */ var minJ0 = Math.floor(vBounds0[0] - 0.5);
+ /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1] - 0.5);
+ /** @type {number} */ var minJ1 = Math.floor(vBounds1[0] - 0.5);
+ /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1] - 0.5);
+
+ /** @type {tcuTexture.TextureChannelClass} */ var texClass = tcuTexture.getTextureChannelClass(faces0[coords.face].getFormat().type);
+ /** @type {number} */ var cSearchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) :
+ (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) :
+ 0; // Step is computed for floating-point quads based on texel values.
+
+ /** @type {tcuTexture.CubeFaceCoords} */ var c00;
+ /** @type {tcuTexture.CubeFaceCoords} */ var c10;
+ /** @type {tcuTexture.CubeFaceCoords} */ var c01;
+ /** @type {tcuTexture.CubeFaceCoords} */ var c11;
+
+ for (var j0 = minJ0; j0 <= maxJ0; j0++) {
+ for (var i0 = minI0; i0 <= maxI0; i0++) {
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad0 = new tcuTexLookupVerifier.ColorQuad([], [], [], []);
+ /** @type {number} */ var searchStep0;
+
+ c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 0]), size0);
+ c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 0]), size0);
+ c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 1]), size0);
+ c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 1]), size0);
+
+ // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
+ // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
+ if (c00 == null || c01 == null || c10 == null || c11 == null ||
+ c00.face == null || c01.face == null || c10.face == null || c11.face == null)
+ return true;
+
+ quad0.p00 = tcuTexLookupVerifier.lookupFloat(faces0[c00.face], sampler, c00.s, c00.t, 0);
+ quad0.p10 = tcuTexLookupVerifier.lookupFloat(faces0[c10.face], sampler, c10.s, c10.t, 0);
+ quad0.p01 = tcuTexLookupVerifier.lookupFloat(faces0[c01.face], sampler, c01.s, c01.t, 0);
+ quad0.p11 = tcuTexLookupVerifier.lookupFloat(faces0[c11.face], sampler, c11.s, c11.t, 0);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep0 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad0);
+ else
+ searchStep0 = cSearchStep;
+
+ /** @type {number} */ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
+ /** @type {number} */ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
+ /** @type {number} */ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
+ /** @type {number} */ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
+
+ for (var j1 = minJ1; j1 <= maxJ1; j1++) {
+ for (var i1 = minI1; i1 <= maxI1; i1++) {
+ /** @type {tcuTexLookupVerifier.ColorQuad} */
+ var quad1 = new tcuTexLookupVerifier.ColorQuad([], [], [], []);
+ /** @type {number} */ var searchStep1;
+
+ c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 0]), size1);
+ c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 0]), size1);
+ c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 1]), size1);
+ c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 1]), size1);
+
+ if (c00 == null || c01 == null || c10 == null || c11 == null ||
+ c00.face == null || c01.face == null || c10.face == null || c11.face == null)
+ return true;
+
+ quad1.p00 = tcuTexLookupVerifier.lookupFloat(faces1[c00.face], sampler, c00.s, c00.t, 0);
+ quad1.p10 = tcuTexLookupVerifier.lookupFloat(faces1[c10.face], sampler, c10.s, c10.t, 0);
+ quad1.p01 = tcuTexLookupVerifier.lookupFloat(faces1[c01.face], sampler, c01.s, c01.t, 0);
+ quad1.p11 = tcuTexLookupVerifier.lookupFloat(faces1[c11.face], sampler, c11.s, c11.t, 0);
+
+ if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ searchStep1 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad1);
+ else
+ searchStep1 = cSearchStep;
+
+ /** @type {number} */ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
+ /** @type {number} */ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
+ /** @type {number} */ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
+ /** @type {number} */ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
+
+ if (tcuTexLookupVerifier.is2DTrilinearFilterResultValid(prec, quad0, quad1, [minA0, maxA0], [minB0, maxB0], [minA1, maxA1], [minB1, maxB1],
+ fBounds, Math.min(searchStep0, searchStep1), result))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} level (&level)[CUBEFACE_LAST]
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filterMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isCubeLevelSampleResultValid = function(level, sampler, filterMode, prec, coords, result) {
+ if (filterMode == tcuTexture.FilterMode.LINEAR) {
+ if (sampler.seamlessCubeMap)
+ return tcuTexLookupVerifier.isSeamlessLinearSampleResultValid(level, sampler, prec, coords, result);
+ else
+ return tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec2AndInt(level[coords.face], sampler, prec, [coords.s, coords.t], 0, result);
+ } else
+ return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt(level[coords.face], sampler, prec, [coords.s, coords.t], 0, result);
+ };
+
+ /**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces0 (&faces0)[CUBEFACE_LAST]
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces1 (&faces1)[CUBEFACE_LAST]
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} levelFilter
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {tcuTexture.CubeFaceCoords} coords
+ * @param {Array<number>} fBounds
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isCubeMipmapLinearSampleResultValid = function(faces0, faces1, sampler, levelFilter, prec, coords, fBounds, result) {
+ if (levelFilter == tcuTexture.FilterMode.LINEAR) {
+ if (sampler.seamlessCubeMap)
+ return tcuTexLookupVerifier.isSeamplessLinearMipmapLinearSampleResultValid(faces0, faces1, sampler, prec, coords, fBounds, result);
+ else
+ return tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec2AndInt(faces0[coords.face], faces1[coords.face], sampler, prec, [coords.s, coords.t], 0, fBounds, result);
+ } else
+ return tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec2AndInt(faces0[coords.face], faces1[coords.face], sampler, prec, [coords.s, coords.t], 0, fBounds, result);
+ };
+
+ /**
+ * @param {tcuTexture.TextureCubeView} texture
+ * @param {number} levelNdx
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} out (&out)[CUBEFACE_LAST]
+ */
+ tcuTexLookupVerifier.getCubeLevelFaces = function(texture, levelNdx, out) {
+ for (var faceNdx = 0; faceNdx < 6; faceNdx++)
+ out[faceNdx] = texture.getLevelFace(levelNdx, /** @type {tcuTexture.CubeFace} */ (faceNdx));
+ };
+
+ /**
+ * @param {number} numLayers
+ * @param {number} numCoordBits
+ * @param {number} layerCoord
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeLayerRange = function(numLayers, numCoordBits, layerCoord) {
+ /** @type {number} */ var err = tcuTexVerifierUtil.computeFloatingPointError(layerCoord, numCoordBits);
+ /** @type {number} */ var minL = Math.floor(layerCoord - err + 0.5); // Round down
+ /** @type {number} */ var maxL = Math.ceil(layerCoord + err + 0.5) - 1; // Round up
+
+ assertMsgOptions(minL <= maxL, 'minL > maxL', false, true);
+
+ return [deMath.clamp(minL, 0, numLayers - 1), deMath.clamp(maxL, 0, numLayers - 1)];
+ };
+
+ /**
+ * @param {Array<number>} bits
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeFixedPointThreshold = function(bits) {
+ return tcuTexVerifierUtil.computeFixedPointError_Vector(bits);
+ };
+
+ /**
+ * @param {Array<number>} bits
+ * @param {Array<number>} value
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeFloatingPointThreshold = function(bits, value) {
+ return tcuTexVerifierUtil.computeFloatingPointError_Vector(value, bits);
+ };
+
+ /**
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dwdx
+ * @param {number} dudy
+ * @param {number} dvdy
+ * @param {number} dwdy
+ * @param {tcuTexLookupVerifier.LodPrecision} prec
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeLodBoundsFromDerivates = function(dudx, dvdx, dwdx, dudy, dvdy, dwdy, prec) {
+ /** @type {number} */ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
+ /** @type {number} */ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
+ /** @type {number} */ var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy));
+ /** @type {number} */ var minDBound = Math.max(Math.max(mu, mv), mw);
+ /** @type {number} */ var maxDBound = mu + mv + mw;
+ /** @type {number} */ var minDErr = tcuTexVerifierUtil.computeFloatingPointError(minDBound, prec.derivateBits);
+ /** @type {number} */ var maxDErr = tcuTexVerifierUtil.computeFloatingPointError(maxDBound, prec.derivateBits);
+ /** @type {number} */ var minLod = Math.log2(minDBound - minDErr);
+ /** @type {number} */ var maxLod = Math.log2(maxDBound + maxDErr);
+ /** @type {number} */ var lodErr = tcuTexVerifierUtil.computeFixedPointError(prec.lodBits);
+
+ assertMsgOptions(minLod <= maxLod, 'Error: minLod > maxLod', false, true);
+ return [minLod - lodErr, maxLod + lodErr];
+ };
+
+ /**
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dudy
+ * @param {number} dvdy
+ * @param {tcuTexLookupVerifier.LodPrecision} prec
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV = function(dudx, dvdx, dudy, dvdy, prec) {
+ return tcuTexLookupVerifier.computeLodBoundsFromDerivates(dudx, dvdx, 0, dudy, dvdy, 0, prec);
+ };
+
+ /**
+ * @param {number} dudx
+ * @param {number} dudy
+ * @param {tcuTexLookupVerifier.LodPrecision} prec
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeLodBoundsFromDerivatesU = function(dudx, dudy, prec) {
+ return tcuTexLookupVerifier.computeLodBoundsFromDerivates(dudx, 0, 0, dudy, 0, 0, prec);
+ };
+
+ /**
+ * @param {Array<number>} coord
+ * @param {Array<number>} coordDx
+ * @param {Array<number>} coordDy
+ * @param {number} faceSize
+ * @param {tcuTexLookupVerifier.LodPrecision} prec
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates = function(coord, coordDx, coordDy, faceSize, prec) {
+ /** @type {boolean} */ var allowBrokenEdgeDerivate = false;
+ /** @type {tcuTexture.CubeFace} */ var face = tcuTexture.selectCubeFace(coord);
+ /** @type {number} */ var maNdx = 0;
+ /** @type {number} */ var sNdx = 0;
+ /** @type {number} */ var tNdx = 0;
+
+ // \note Derivate signs don't matter when computing lod
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X:
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y:
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z:
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
+ default:
+ throw new Error('Invalid CubeFace.');
+ }
+
+ /** @type {number} */ var sc = coord[sNdx];
+ /** @type {number} */ var tc = coord[tNdx];
+ /** @type {number} */ var ma = Math.abs(coord[maNdx]);
+ /** @type {number} */ var scdx = coordDx[sNdx];
+ /** @type {number} */ var tcdx = coordDx[tNdx];
+ /** @type {number} */ var madx = Math.abs(coordDx[maNdx]);
+ /** @type {number} */ var scdy = coordDy[sNdx];
+ /** @type {number} */ var tcdy = coordDy[tNdx];
+ /** @type {number} */ var mady = Math.abs(coordDy[maNdx]);
+ /** @type {number} */ var dudx = faceSize * 0.5 * (scdx * ma - sc * madx) / (ma * ma);
+ /** @type {number} */ var dvdx = faceSize * 0.5 * (tcdx * ma - tc * madx) / (ma * ma);
+ /** @type {number} */ var dudy = faceSize * 0.5 * (scdy * ma - sc * mady) / (ma * ma);
+ /** @type {number} */ var dvdy = faceSize * 0.5 * (tcdy * ma - tc * mady) / (ma * ma);
+ /** @type {Array<number>} */ var bounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(dudx, dvdx, dudy, dvdy, prec);
+
+ // Implementations may compute derivate from projected (s, t) resulting in incorrect values at edges.
+ if (allowBrokenEdgeDerivate) {
+ /** @type {Array<number>} */ var dxErr = tcuTexVerifierUtil.computeFloatingPointError_Vector(coordDx, [prec.derivateBits, prec.derivateBits, prec.derivateBits]);
+ /** @type {Array<number>} */ var dyErr = tcuTexVerifierUtil.computeFloatingPointError_Vector(coordDy, [prec.derivateBits, prec.derivateBits, prec.derivateBits]);
+ /** @type {Array<number>} */ var xoffs = deMath.add(deMath.abs(coordDx), dxErr);
+ /** @type {Array<number>} */ var yoffs = deMath.add(deMath.abs(coordDy), dyErr);
+
+ if (tcuTexture.selectCubeFace(deMath.add(coord, xoffs)) != face ||
+ tcuTexture.selectCubeFace(deMath.subtract(coord, xoffs)) != face ||
+ tcuTexture.selectCubeFace(deMath.add(coord, yoffs)) != face ||
+ tcuTexture.selectCubeFace(deMath.subtract(coord, yoffs)) != face) {
+ return [bounds[0], 1000];
+ }
+ }
+
+ return bounds;
+ };
+
+ /**
+ * @param {Array<number>} lodBounds
+ * @param {Array<number>} lodMinMax
+ * @param {tcuTexLookupVerifier.LodPrecision} prec
+ * @return {Array<number>}
+ */
+ tcuTexLookupVerifier.clampLodBounds = function(lodBounds, lodMinMax, prec) {
+ /** @type {number} */ var lodErr = tcuTexVerifierUtil.computeFixedPointError(prec.lodBits);
+ /** @type {number} */ var a = lodMinMax[0];
+ /** @type {number} */ var b = lodMinMax[1];
+ return [deMath.clamp(lodBounds[0], a - lodErr, b - lodErr), deMath.clamp(lodBounds[1], a + lodErr, b + lodErr)];
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {number} coordZ
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevel2DLookupResultValid = function(access, sampler, scaleMode, prec, coord, coordZ, result) {
+ /** @type {tcuTexture.FilterMode} */
+ var filterMode = (scaleMode == tcuTexLookupVerifier.TexLookupScaleMode.MAGNIFY) ? sampler.magFilter : sampler.minFilter;
+ return tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(access, sampler, filterMode, prec, coord, coordZ, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {number} coordZ
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevel2DLookupResultValid_Int = function(access, sampler, scaleMode, prec, coord, coordZ, result) {
+ assertMsgOptions(sampler.minFilter == tcuTexture.FilterMode.NEAREST && sampler.magFilter == tcuTexture.FilterMode.NEAREST, 'minFilter and magFilter must be NEAREST', false, true);
+ return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt(access, sampler, prec, coord, coordZ, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevel3DLookupResultValid = function(access, sampler, scaleMode, prec, coord, result) {
+ /** @type {tcuTexture.FilterMode} */
+ var filterMode = (scaleMode == tcuTexLookupVerifier.TexLookupScaleMode.MAGNIFY) ? sampler.magFilter : sampler.minFilter;
+ return tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(access, sampler, filterMode, prec, coord, result);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode
+ * @param {tcuTexLookupVerifier.LookupPrecision} prec
+ * @param {Array<number>} coord
+ * @param {Array<number>} result
+ * @return {boolean}
+ */
+ tcuTexLookupVerifier.isLevel3DLookupResultValid_Int = function(access, sampler, scaleMode, prec, coord, result) {
+ assertMsgOptions(sampler.minFilter == tcuTexture.FilterMode.NEAREST && sampler.magFilter == tcuTexture.FilterMode.NEAREST, 'minFilter and magFilter must be NEAREST', false, true);
+ return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec3(access, sampler, prec, coord, result);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexVerifierUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexVerifierUtil.js
new file mode 100644
index 0000000000..4c88f44608
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexVerifierUtil.js
@@ -0,0 +1,265 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuTexVerifierUtil');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deUtil');
+
+goog.scope(function() {
+
+ var tcuTexVerifierUtil = framework.common.tcuTexVerifierUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var deUtil = framework.delibs.debase.deUtil;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuTexture = framework.common.tcuTexture;
+
+ /**
+ * @param {number} value
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ tcuTexVerifierUtil.computeFloatingPointError = function(value, numAccurateBits) {
+ /** @type {number} */ var numGarbageBits = 23 - numAccurateBits;
+ /** @type {number} */ var mask = (1 << numGarbageBits) - 1;
+ /** @type {number} */ var exp = tcuFloat.newFloat32(value).exponent();
+
+ /** @type {tcuFloat.deFloat} */ var v1 = new tcuFloat.deFloat();
+ /** @type {tcuFloat.deFloat} */ var v2 = new tcuFloat.deFloat();
+ return v1.construct(1, exp, 1 << 23 | mask).getValue() - v2.construct(1, exp, 1 << 23).getValue();
+ };
+
+ /**
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ tcuTexVerifierUtil.computeFixedPointError = function(numAccurateBits) {
+ return tcuTexVerifierUtil.computeFloatingPointError(1.0, numAccurateBits);
+ };
+
+ /**
+ * @param {Array<number>} numAccurateBits
+ * @return {Array<number>}
+ */
+ tcuTexVerifierUtil.computeFixedPointError_Vector = function(numAccurateBits) {
+ /** @type {Array<number>} */ var res = [];
+ for (var ndx = 0; ndx < numAccurateBits.length; ndx++)
+ res[ndx] = tcuTexVerifierUtil.computeFixedPointError(numAccurateBits[ndx]);
+ return res;
+ };
+
+ /**
+ * @param {Array<number>} value
+ * @param {Array<number>} numAccurateBits
+ * @return {Array<number>}
+ */
+ tcuTexVerifierUtil.computeFloatingPointError_Vector = function(value, numAccurateBits) {
+ assertMsgOptions(value.length === numAccurateBits.length, '', false, true);
+ /** @type {Array<number>} */ var res = [];
+ for (var ndx = 0; ndx < value.length; ndx++)
+ res[ndx] = tcuTexVerifierUtil.computeFloatingPointError(value[ndx], numAccurateBits[ndx]);
+ return res;
+ };
+
+ // Sampler introspection
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {boolean}
+ */
+ tcuTexVerifierUtil.isNearestMipmapFilter = function(mode) {
+ return mode == tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST || mode == tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST;
+ };
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {boolean}
+ */
+ tcuTexVerifierUtil.isLinearMipmapFilter = function(mode) {
+ return mode == tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR || mode == tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR;
+ };
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {boolean}
+ */
+ tcuTexVerifierUtil.isMipmapFilter = function(mode) {
+ return tcuTexVerifierUtil.isNearestMipmapFilter(mode) || tcuTexVerifierUtil.isLinearMipmapFilter(mode);
+ };
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {boolean}
+ */
+ tcuTexVerifierUtil.isLinearFilter = function(mode) {
+ return mode == tcuTexture.FilterMode.LINEAR || mode == tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST || mode == tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR;
+ };
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {boolean}
+ */
+ tcuTexVerifierUtil.isNearestFilter = function(mode) {
+ return !tcuTexVerifierUtil.isLinearFilter(mode);
+ };
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {tcuTexture.FilterMode}
+ */
+ tcuTexVerifierUtil.getLevelFilter = function(mode) {
+ return tcuTexVerifierUtil.isLinearFilter(mode) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ };
+
+ /**
+ * @param {tcuTexture.WrapMode} mode
+ * @return {boolean}
+ */
+ tcuTexVerifierUtil.isWrapModeSupported = function(mode) {
+ return mode != tcuTexture.WrapMode.MIRRORED_REPEAT_CL && mode != tcuTexture.WrapMode.REPEAT_CL;
+ };
+
+ /**
+ *
+ * @param {boolean} normalizedCoords
+ * @param {number} dim
+ * @param {number} coord
+ * @param {number} coordBits
+ * @param {number} uvBits
+ * @return {Array<number>}
+ */
+ tcuTexVerifierUtil.computeNonNormalizedCoordBounds = function(normalizedCoords, dim, coord, coordBits, uvBits) {
+ /** @type {number} */ var coordErr = tcuTexVerifierUtil.computeFloatingPointError(coord, coordBits);
+ /** @type {number} */ var minN = coord - coordErr;
+ /** @type {number} */ var maxN = coord + coordErr;
+ /** @type {number} */ var minA = normalizedCoords ? minN * dim : minN;
+ /** @type {number} */ var maxA = normalizedCoords ? maxN * dim : maxN;
+ /** @type {number} */ var minC = minA - tcuTexVerifierUtil.computeFixedPointError(uvBits);
+ /** @type {number} */ var maxC = maxA + tcuTexVerifierUtil.computeFixedPointError(uvBits);
+ assertMsgOptions(minC <= maxC, '', false, true);
+ return [minC, maxC];
+ };
+
+ /**
+ * @param {Array<number>} coord
+ * @param {Array<number>} bits
+ * @return {?Array<tcuTexture.CubeFace>}
+ */
+ tcuTexVerifierUtil.getPossibleCubeFaces = function(coord, bits) {
+
+ /** @type {Array<tcuTexture.CubeFace>} */ var faces = [];
+
+ /** @type {number} */ var x = coord[0];
+ /** @type {number} */ var y = coord[1];
+ /** @type {number} */ var z = coord[2];
+ /** @type {number} */ var ax = Math.abs(x);
+ /** @type {number} */ var ay = Math.abs(y);
+ /** @type {number} */ var az = Math.abs(z);
+ /** @type {number} */ var ex = tcuTexVerifierUtil.computeFloatingPointError(x, bits[0]);
+ /** @type {number} */ var ey = tcuTexVerifierUtil.computeFloatingPointError(y, bits[1]);
+ /** @type {number} */ var ez = tcuTexVerifierUtil.computeFloatingPointError(z, bits[2]);
+ /** @type {number} */ var numFaces = 0;
+
+ if (ay + ey < ax - ex && az + ez < ax - ex) {
+ if (x >= ex) faces.push(tcuTexture.CubeFace.CUBEFACE_POSITIVE_X);
+ if (x <= ex) faces.push(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X);
+ } else if (ax + ex < ay - ey && az + ez < ay - ey) {
+ if (y >= ey) faces.push(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y);
+ if (y <= ey) faces.push(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y);
+ } else if (ax + ex < az - ez && ay + ey < az - ez) {
+ if (z >= ez) faces.push(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z);
+ if (z <= ez) faces.push(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z);
+ } else {
+ // One or more components are equal (or within error bounds). Allow all faces where major axis is not zero.
+ if (ax > ex) {
+ faces.push(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X);
+ faces.push(tcuTexture.CubeFace.CUBEFACE_POSITIVE_X);
+ }
+
+ if (ay > ey) {
+ faces.push(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y);
+ faces.push(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y);
+ }
+
+ if (az > ez) {
+ faces.push(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z);
+ faces.push(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z);
+ }
+ }
+
+ return faces.length == 0 ? null : faces;
+ };
+
+ /**
+ * @param {tcuTexture.Sampler} sampler
+ * @return {tcuTexture.Sampler}
+ */
+ tcuTexVerifierUtil.getUnnormalizedCoordSampler = function(sampler) {
+ var copy = /** @type {tcuTexture.Sampler} */ (deUtil.clone(sampler));
+ copy.normalizedCoords = false;
+ return copy;
+ };
+
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+ tcuTexVerifierUtil.imod = function(a, b) {
+ return deMath.imod(a, b);
+ };
+
+ /**
+ * @param {number} a
+ * @return {number}
+ */
+ tcuTexVerifierUtil.mirror = function(a) {
+ return deMath.mirror(a);
+ };
+
+ /**
+ * @param {tcuTexture.WrapMode} mode
+ * @param {number} c
+ * @param {number} size
+ * @return {number}
+ */
+ tcuTexVerifierUtil.wrap = function(mode, c, size) {
+ switch (mode) {
+ // \note CL and GL modes are handled identically here, as verification process accounts for
+ // accuracy differences caused by different methods (wrapping vs. denormalizing first).
+ case tcuTexture.WrapMode.CLAMP_TO_EDGE:
+ return deMath.clamp(c, 0, size - 1);
+
+ case tcuTexture.WrapMode.REPEAT_GL:
+ case tcuTexture.WrapMode.REPEAT_CL:
+ return deMath.imod(c, size);
+
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_GL:
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_CL:
+ return (size - 1) - deMath.mirror(deMath.imod(c, 2 * size) - size);
+
+ default:
+ throw new Error('Wrap mode not supported.');
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexture.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexture.js
new file mode 100644
index 0000000000..8a3a2ed1d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTexture.js
@@ -0,0 +1,3636 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuTexture');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+
+goog.scope(function() {
+
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var tcuFloat = framework.common.tcuFloat;
+var deString = framework.delibs.debase.deString;
+var deUtil = framework.delibs.debase.deUtil;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/**
+ * Texture tcuTexture.channel order
+ * @enum
+ */
+tcuTexture.ChannelOrder = {
+ R: 0,
+ A: 1,
+ I: 2,
+ L: 3,
+ LA: 4,
+ RG: 5,
+ RA: 6,
+ RGB: 7,
+ RGBA: 8,
+ ARGB: 9,
+ BGRA: 10,
+
+ sRGB: 11,
+ sRGBA: 12,
+
+ D: 13,
+ S: 14,
+ DS: 15
+};
+
+/**
+ * Texture tcuTexture.channel type
+ * @enum
+ */
+tcuTexture.ChannelType = {
+ SNORM_INT8: 0,
+ SNORM_INT16: 1,
+ SNORM_INT32: 2,
+ UNORM_INT8: 3,
+ UNORM_INT16: 4,
+ UNORM_INT32: 5,
+ UNORM_SHORT_565: 6,
+ UNORM_SHORT_555: 7,
+ UNORM_SHORT_4444: 8,
+ UNORM_SHORT_5551: 9,
+ UNORM_INT_101010: 10,
+ UNORM_INT_1010102_REV: 11,
+ UNSIGNED_INT_1010102_REV: 12,
+ UNSIGNED_INT_11F_11F_10F_REV: 13,
+ UNSIGNED_INT_999_E5_REV: 14,
+ UNSIGNED_INT_24_8: 15,
+ SIGNED_INT8: 16,
+ SIGNED_INT16: 17,
+ SIGNED_INT32: 18,
+ UNSIGNED_INT8: 19,
+ UNSIGNED_INT16: 20,
+ UNSIGNED_INT32: 21,
+ HALF_FLOAT: 22,
+ FLOAT: 23,
+ FLOAT_UNSIGNED_INT_24_8_REV: 24
+};
+
+/**
+ * Enums for tcuTexture.TextureChannelClass
+ * @enum {number}
+ */
+tcuTexture.TextureChannelClass = {
+
+ SIGNED_FIXED_POINT: 0,
+ UNSIGNED_FIXED_POINT: 1,
+ SIGNED_INTEGER: 2,
+ UNSIGNED_INTEGER: 3,
+ FLOATING_POINT: 4
+};
+
+/**
+ * @param {?tcuTexture.ChannelType} channelType
+ * @return {tcuTexture.TextureChannelClass}
+ */
+tcuTexture.getTextureChannelClass = function(channelType) {
+
+ switch (channelType) {
+ case tcuTexture.ChannelType.SNORM_INT8: return tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.SNORM_INT16: return tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_INT8: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_INT16: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_SHORT_565: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_SHORT_555: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_INT_101010: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: return tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT;
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return tcuTexture.TextureChannelClass.UNSIGNED_INTEGER;
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return tcuTexture.TextureChannelClass.FLOATING_POINT;
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: return tcuTexture.TextureChannelClass.FLOATING_POINT;
+ case tcuTexture.ChannelType.SIGNED_INT8: return tcuTexture.TextureChannelClass.SIGNED_INTEGER;
+ case tcuTexture.ChannelType.SIGNED_INT16: return tcuTexture.TextureChannelClass.SIGNED_INTEGER;
+ case tcuTexture.ChannelType.SIGNED_INT32: return tcuTexture.TextureChannelClass.SIGNED_INTEGER;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return tcuTexture.TextureChannelClass.UNSIGNED_INTEGER;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return tcuTexture.TextureChannelClass.UNSIGNED_INTEGER;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return tcuTexture.TextureChannelClass.UNSIGNED_INTEGER;
+ case tcuTexture.ChannelType.HALF_FLOAT: return tcuTexture.TextureChannelClass.FLOATING_POINT;
+ case tcuTexture.ChannelType.FLOAT: return tcuTexture.TextureChannelClass.FLOATING_POINT;
+ default: return /** @type {tcuTexture.TextureChannelClass<number>} */ (Object.keys(tcuTexture.ChannelType).length);
+ }
+};
+
+/**
+ * @param {tcuTexture.TextureFormat} format
+ */
+tcuTexture.isFixedPointDepthTextureFormat = function(format) {
+ var channelClass = tcuTexture.getTextureChannelClass(format.type);
+
+ if (format.order == tcuTexture.ChannelOrder.D) {
+ // depth internal formats cannot be non-normalized integers
+ return channelClass != tcuTexture.TextureChannelClass.FLOATING_POINT;
+ } else if (format.order == tcuTexture.ChannelOrder.DS) {
+ // combined formats have no single channel class, detect format manually
+ switch (format.type) {
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return false;
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return true;
+
+ default:
+ // unknown format
+ DE_ASSERT(false);
+ return true;
+ }
+ }
+ return false;
+};
+
+/**
+ * @param {Array<number>} color
+ * @param {tcuTexture.CompareMode} compare
+ * @param {number} chanNdx
+ * @param {number} ref_
+ * @param {boolean} isFixedPoint
+ */
+tcuTexture.execCompare = function(color, compare, chanNdx, ref_, isFixedPoint) {
+ var clampValues = isFixedPoint;
+ var cmp = clampValues ? deMath.clamp(color[chanNdx], 0.0, 1.0) : color[chanNdx];
+ var ref = clampValues ? deMath.clamp(ref_, 0.0, 1.0) : ref_;
+ var res = false;
+
+ switch (compare) {
+ case tcuTexture.CompareMode.COMPAREMODE_LESS: res = ref < cmp; break;
+ case tcuTexture.CompareMode.COMPAREMODE_LESS_OR_EQUAL: res = ref <= cmp; break;
+ case tcuTexture.CompareMode.COMPAREMODE_GREATER: res = ref > cmp; break;
+ case tcuTexture.CompareMode.COMPAREMODE_GREATER_OR_EQUAL: res = ref >= cmp; break;
+ case tcuTexture.CompareMode.COMPAREMODE_EQUAL: res = ref == cmp; break;
+ case tcuTexture.CompareMode.COMPAREMODE_NOT_EQUAL: res = ref != cmp; break;
+ case tcuTexture.CompareMode.COMPAREMODE_ALWAYS: res = true; break;
+ case tcuTexture.CompareMode.COMPAREMODE_NEVER: res = false; break;
+ default:
+ DE_ASSERT(false);
+ }
+
+ return res ? 1.0 : 0.0;
+};
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ * @param {number} numLevels
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} lod
+ * @param {Array<number>} offset
+ */
+tcuTexture.sampleLevelArray2DCompare = function(levels, numLevels, sampler, ref, s, t, lod, offset) {
+ var magnified = lod <= sampler.lodThreshold;
+ var filterMode = magnified ? sampler.magFilter : sampler.minFilter;
+
+ switch (filterMode) {
+ case tcuTexture.FilterMode.NEAREST: return levels[0].sample2DCompare(sampler, filterMode, ref, s, t, offset);
+ case tcuTexture.FilterMode.LINEAR: return levels[0].sample2DCompare(sampler, filterMode, ref, s, t, offset);
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST: {
+ var maxLevel = numLevels - 1;
+ var level = deMath.clamp(Math.ceil(lod + 0.5) - 1, 0, maxLevel);
+ var levelFilter = filterMode == tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+
+ return levels[level].sample2DCompare(sampler, levelFilter, ref, s, t, offset);
+ }
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR: {
+ var maxLevel = numLevels - 1;
+ var level0 = deMath.clamp(Math.floor(lod), 0, maxLevel);
+ var level1 = Math.min(maxLevel, level0 + 1);
+ var levelFilter = filterMode == tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ var f = deMath.deFloatFrac(lod);
+ var t0 = levels[level0].sample2DCompare(sampler, levelFilter, ref, s, t, offset);
+ var t1 = levels[level1].sample2DCompare(sampler, levelFilter, ref, s, t, offset);
+
+ return t0 * (1.0 - f) + t1 * f;
+ }
+
+ default:
+ DE_ASSERT(false);
+ return 0.0;
+ }
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {number} u
+ * @param {number} v
+ * @param {Array<number>} offset
+ * @param {boolean} isFixedPointDepthFormat
+ * @return {number}
+ */
+tcuTexture.sampleLinear2DCompare = function(access, sampler, ref, u, v, offset, isFixedPointDepthFormat) {
+ var w = access.getWidth();
+ var h = access.getHeight();
+
+ var x0 = Math.floor(u - 0.5) + offset[0];
+ var x1 = x0 + 1;
+ var y0 = Math.floor(v - 0.5) + offset[1];
+ var y1 = y0 + 1;
+
+ var i0 = tcuTexture.wrap(sampler.wrapS, x0, w);
+ var i1 = tcuTexture.wrap(sampler.wrapS, x1, w);
+ var j0 = tcuTexture.wrap(sampler.wrapT, y0, h);
+ var j1 = tcuTexture.wrap(sampler.wrapT, y1, h);
+
+ var a = deMath.deFloatFrac(u - 0.5);
+ var b = deMath.deFloatFrac(v - 0.5);
+
+ var i0UseBorder = sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(i0, 0, w);
+ var i1UseBorder = sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(i1, 0, w);
+ var j0UseBorder = sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(j0, 0, h);
+ var j1UseBorder = sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(j1, 0, h);
+
+ // Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
+ var p00Clr = (i0UseBorder || j0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j0, offset[2]);
+ var p10Clr = (i1UseBorder || j0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j0, offset[2]);
+ var p01Clr = (i0UseBorder || j1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j1, offset[2]);
+ var p11Clr = (i1UseBorder || j1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j1, offset[2]);
+
+ // Execute comparisons.
+ var p00 = tcuTexture.execCompare(p00Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
+ var p10 = tcuTexture.execCompare(p10Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
+ var p01 = tcuTexture.execCompare(p01Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
+ var p11 = tcuTexture.execCompare(p11Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
+
+ // Interpolate.
+ return (p00 * (1.0 - a) * (1.0 - b)) +
+ (p10 * (a) * (1.0 - b)) +
+ (p01 * (1.0 - a) * (b)) +
+ (p11 * (a) * (b));
+};
+
+/**
+ * Construct texture format
+ * @param {?tcuTexture.ChannelOrder} order
+ * @param {?tcuTexture.ChannelType} type
+ *
+ * @constructor
+ */
+tcuTexture.TextureFormat = function(order, type) {
+ this.order = order;
+ this.type = type;
+};
+
+/**
+ * Compare two formats
+ * @param {tcuTexture.TextureFormat} format Format to compare with
+ * @return {boolean}
+ */
+tcuTexture.TextureFormat.prototype.isEqual = function(format) {
+ return this.order === format.order && this.type === format.type;
+};
+
+tcuTexture.TextureFormat.prototype.toString = function() {
+ return 'TextureFormat(' + deString.enumToString(tcuTexture.ChannelOrder, this.order) + ', ' +
+ deString.enumToString(tcuTexture.ChannelType, this.type) + ')';
+};
+
+/**
+ * Is format sRGB?
+ * @return {boolean}
+ */
+tcuTexture.TextureFormat.prototype.isSRGB = function() {
+ return this.order === tcuTexture.ChannelOrder.sRGB || this.order === tcuTexture.ChannelOrder.sRGBA;
+};
+
+tcuTexture.TextureFormat.prototype.getNumStencilBits = function() {
+ switch (this.order) {
+ case tcuTexture.ChannelOrder.S:
+ switch (this.type) {
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return 8;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return 16;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return 32;
+ default:
+ throw new Error('Wrong type: ' + this.type);
+ }
+
+ case tcuTexture.ChannelOrder.DS:
+ switch (this.type) {
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return 8;
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return 8;
+ default:
+ throw new Error('Wrong type: ' + this.type);
+ }
+
+ default:
+ throw new Error('Wrong order: ' + this.order);
+ }
+};
+
+/**
+ * Get TypedArray type that can be used to access texture.
+ * @param {?tcuTexture.ChannelType} type
+ * @return TypedArray that supports the tcuTexture.channel type.
+ */
+tcuTexture.getTypedArray = function(type) {
+ switch (type) {
+ case tcuTexture.ChannelType.SNORM_INT8: return Int8Array;
+ case tcuTexture.ChannelType.SNORM_INT16: return Int16Array;
+ case tcuTexture.ChannelType.SNORM_INT32: return Int32Array;
+ case tcuTexture.ChannelType.UNORM_INT8: return Uint8Array;
+ case tcuTexture.ChannelType.UNORM_INT16: return Uint16Array;
+ case tcuTexture.ChannelType.UNORM_INT32: return Uint32Array;
+ case tcuTexture.ChannelType.UNORM_SHORT_565: return Uint16Array;
+ case tcuTexture.ChannelType.UNORM_SHORT_555: return Uint16Array;
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: return Uint16Array;
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: return Uint16Array;
+ case tcuTexture.ChannelType.UNORM_INT_101010: return Uint32Array;
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: return Uint32Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return Uint32Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return Uint32Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: return Uint32Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return Uint32Array;
+ case tcuTexture.ChannelType.FLOAT: return Float32Array;
+ case tcuTexture.ChannelType.SIGNED_INT8: return Int8Array;
+ case tcuTexture.ChannelType.SIGNED_INT16: return Int16Array;
+ case tcuTexture.ChannelType.SIGNED_INT32: return Int32Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return Uint8Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return Uint16Array;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return Uint32Array;
+ case tcuTexture.ChannelType.HALF_FLOAT: return Uint16Array;
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return Float32Array; /* this type is a special case */
+ }
+
+ throw new Error('Unrecognized type ' + type);
+};
+
+/**
+ * @return {number} pixel size in bytes
+ */
+tcuTexture.TextureFormat.prototype.getPixelSize = function() {
+ if (this.type == null || this.order == null) {
+ // Invalid/empty format.
+ return 0;
+ } else if (this.type == tcuTexture.ChannelType.UNORM_SHORT_565 ||
+ this.type == tcuTexture.ChannelType.UNORM_SHORT_555 ||
+ this.type == tcuTexture.ChannelType.UNORM_SHORT_4444 ||
+ this.type == tcuTexture.ChannelType.UNORM_SHORT_5551) {
+ DE_ASSERT(this.order == tcuTexture.ChannelOrder.RGB || this.order == tcuTexture.ChannelOrder.RGBA);
+ return 2;
+ } else if (this.type == tcuTexture.ChannelType.UNORM_INT_101010 ||
+ this.type == tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV ||
+ this.type == tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV) {
+ DE_ASSERT(this.order == tcuTexture.ChannelOrder.RGB);
+ return 4;
+ } else if (this.type == tcuTexture.ChannelType.UNORM_INT_1010102_REV ||
+ this.type == tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV) {
+ DE_ASSERT(this.order == tcuTexture.ChannelOrder.RGBA);
+ return 4;
+ } else if (this.type == tcuTexture.ChannelType.UNSIGNED_INT_24_8) {
+ DE_ASSERT(this.order == tcuTexture.ChannelOrder.D || this.order == tcuTexture.ChannelOrder.DS);
+ return 4;
+ } else if (this.type == tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV) {
+ DE_ASSERT(this.order == tcuTexture.ChannelOrder.DS);
+ return 8;
+ } else {
+ var numChannels;
+ var channelSize;
+
+ switch (this.order) {
+ case tcuTexture.ChannelOrder.R: numChannels = 1; break;
+ case tcuTexture.ChannelOrder.A: numChannels = 1; break;
+ case tcuTexture.ChannelOrder.I: numChannels = 1; break;
+ case tcuTexture.ChannelOrder.L: numChannels = 1; break;
+ case tcuTexture.ChannelOrder.LA: numChannels = 2; break;
+ case tcuTexture.ChannelOrder.RG: numChannels = 2; break;
+ case tcuTexture.ChannelOrder.RA: numChannels = 2; break;
+ case tcuTexture.ChannelOrder.RGB: numChannels = 3; break;
+ case tcuTexture.ChannelOrder.RGBA: numChannels = 4; break;
+ case tcuTexture.ChannelOrder.ARGB: numChannels = 4; break;
+ case tcuTexture.ChannelOrder.BGRA: numChannels = 4; break;
+ case tcuTexture.ChannelOrder.sRGB: numChannels = 3; break;
+ case tcuTexture.ChannelOrder.sRGBA: numChannels = 4; break;
+ case tcuTexture.ChannelOrder.D: numChannels = 1; break;
+ case tcuTexture.ChannelOrder.S: numChannels = 1; break;
+ case tcuTexture.ChannelOrder.DS: numChannels = 2; break;
+ default: DE_ASSERT(false);
+ }
+
+ switch (this.type) {
+ case tcuTexture.ChannelType.SNORM_INT8: channelSize = 1; break;
+ case tcuTexture.ChannelType.SNORM_INT16: channelSize = 2; break;
+ case tcuTexture.ChannelType.SNORM_INT32: channelSize = 4; break;
+ case tcuTexture.ChannelType.UNORM_INT8: channelSize = 1; break;
+ case tcuTexture.ChannelType.UNORM_INT16: channelSize = 2; break;
+ case tcuTexture.ChannelType.UNORM_INT32: channelSize = 4; break;
+ case tcuTexture.ChannelType.SIGNED_INT8: channelSize = 1; break;
+ case tcuTexture.ChannelType.SIGNED_INT16: channelSize = 2; break;
+ case tcuTexture.ChannelType.SIGNED_INT32: channelSize = 4; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: channelSize = 1; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: channelSize = 2; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: channelSize = 4; break;
+ case tcuTexture.ChannelType.HALF_FLOAT: channelSize = 2; break;
+ case tcuTexture.ChannelType.FLOAT: channelSize = 4; break;
+ default: DE_ASSERT(false);
+ }
+
+ return numChannels * channelSize;
+ }
+};
+
+/**
+ * @enum
+ */
+tcuTexture.CubeFace = {
+ CUBEFACE_NEGATIVE_X: 0,
+ CUBEFACE_POSITIVE_X: 1,
+ CUBEFACE_NEGATIVE_Y: 2,
+ CUBEFACE_POSITIVE_Y: 3,
+ CUBEFACE_NEGATIVE_Z: 4,
+ CUBEFACE_POSITIVE_Z: 5
+};
+
+/**
+ * Renamed from ArrayBuffer due to name clash
+ * Wraps ArrayBuffer.
+ * @constructor
+ * @param {number=} numElements
+ */
+tcuTexture.DeqpArrayBuffer = function(numElements) {
+ if (numElements)
+ this.m_ptr = new ArrayBuffer(numElements);
+};
+
+/**
+ * Set array size
+ * @param {number} numElements Size in bytes
+ */
+tcuTexture.DeqpArrayBuffer.prototype.setStorage = function(numElements) {
+ this.m_ptr = new ArrayBuffer(numElements);
+};
+
+/**
+ * @return {number} Buffer size
+ */
+tcuTexture.DeqpArrayBuffer.prototype.size = function() {
+ if (this.m_ptr)
+ return this.m_ptr.byteLength;
+
+ return 0;
+};
+
+/**
+ * Is the buffer empty (zero size)?
+ * @return {boolean}
+ */
+tcuTexture.DeqpArrayBuffer.prototype.empty = function() {
+ if (!this.m_ptr)
+ return true;
+ return this.size() == 0;
+};
+
+/**
+ * @enum
+ * The values are negative to avoid conflict with channels 0 - 3
+ */
+tcuTexture.channel = {
+ ZERO: -1,
+ ONE: -2
+};
+
+/**
+ * @param {tcuTexture.ChannelOrder} order
+ * @return {Array<Number|tcuTexture.channel>}
+ */
+tcuTexture.getChannelReadMap = function(order) {
+ switch (order) {
+ /*static const Channel INV[] = { tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, tcuTexture.channel.ONE }; */
+
+ case tcuTexture.ChannelOrder.R: return [0, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, tcuTexture.channel.ONE];
+ case tcuTexture.ChannelOrder.A: return [tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, 0];
+ case tcuTexture.ChannelOrder.I: return [0, 0, 0, 0];
+ case tcuTexture.ChannelOrder.L: return [0, 0, 0, tcuTexture.channel.ONE];
+ case tcuTexture.ChannelOrder.LA: return [0, 0, 0, 1];
+ case tcuTexture.ChannelOrder.RG: return [0, 1, tcuTexture.channel.ZERO, tcuTexture.channel.ONE];
+ case tcuTexture.ChannelOrder.RA: return [0, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, 1];
+ case tcuTexture.ChannelOrder.RGB: return [0, 1, 2, tcuTexture.channel.ONE];
+ case tcuTexture.ChannelOrder.RGBA: return [0, 1, 2, 3];
+ case tcuTexture.ChannelOrder.BGRA: return [2, 1, 0, 3];
+ case tcuTexture.ChannelOrder.ARGB: return [1, 2, 3, 0];
+ case tcuTexture.ChannelOrder.sRGB: return [0, 1, 2, tcuTexture.channel.ONE];
+ case tcuTexture.ChannelOrder.sRGBA: return [0, 1, 2, 3];
+ case tcuTexture.ChannelOrder.D: return [0, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, tcuTexture.channel.ONE];
+ case tcuTexture.ChannelOrder.S: return [tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, 0];
+ case tcuTexture.ChannelOrder.DS: return [0, tcuTexture.channel.ZERO, tcuTexture.channel.ZERO, 1];
+ }
+
+ throw new Error('Unrecognized order ' + order);
+};
+
+/**
+ * @param {tcuTexture.ChannelOrder} order
+ * @return {Array<number>}
+ */
+tcuTexture.getChannelWriteMap = function(order) {
+ switch (order) {
+ case tcuTexture.ChannelOrder.R: return [0];
+ case tcuTexture.ChannelOrder.A: return [3];
+ case tcuTexture.ChannelOrder.I: return [0];
+ case tcuTexture.ChannelOrder.L: return [0];
+ case tcuTexture.ChannelOrder.LA: return [0, 3];
+ case tcuTexture.ChannelOrder.RG: return [0, 1];
+ case tcuTexture.ChannelOrder.RA: return [0, 3];
+ case tcuTexture.ChannelOrder.RGB: return [0, 1, 2];
+ case tcuTexture.ChannelOrder.RGBA: return [0, 1, 2, 3];
+ case tcuTexture.ChannelOrder.ARGB: return [3, 0, 1, 2];
+ case tcuTexture.ChannelOrder.BGRA: return [2, 1, 0, 3];
+ case tcuTexture.ChannelOrder.sRGB: return [0, 1, 2];
+ case tcuTexture.ChannelOrder.sRGBA: return [0, 1, 2, 3];
+ case tcuTexture.ChannelOrder.D: return [0];
+ case tcuTexture.ChannelOrder.S: return [3];
+ case tcuTexture.ChannelOrder.DS: return [0, 3];
+ }
+ throw new Error('Unrecognized order ' + order);
+};
+
+/**
+ * @param {tcuTexture.ChannelType} type
+ * @return {number}
+ */
+tcuTexture.getChannelSize = function(type) {
+ switch (type) {
+ case tcuTexture.ChannelType.SNORM_INT8: return 1;
+ case tcuTexture.ChannelType.SNORM_INT16: return 2;
+ case tcuTexture.ChannelType.SNORM_INT32: return 4;
+ case tcuTexture.ChannelType.UNORM_INT8: return 1;
+ case tcuTexture.ChannelType.UNORM_INT16: return 2;
+ case tcuTexture.ChannelType.UNORM_INT32: return 4;
+ case tcuTexture.ChannelType.SIGNED_INT8: return 1;
+ case tcuTexture.ChannelType.SIGNED_INT16: return 2;
+ case tcuTexture.ChannelType.SIGNED_INT32: return 4;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return 1;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return 2;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return 4;
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return 4;
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: return 4;
+ case tcuTexture.ChannelType.HALF_FLOAT: return 2;
+ case tcuTexture.ChannelType.FLOAT: return 4;
+
+ }
+ throw new Error('Unrecognized type ' + deString.enumToString(tcuTexture.ChannelType, type));
+};
+
+/**
+ * @param {number} src Source value
+ * @param {number} bits Source value size in bits
+ * @return {number} Normalized value
+ */
+tcuTexture.channelToNormFloat = function(src, bits) {
+ var maxVal = (1 << bits) - 1;
+ return src / maxVal;
+};
+
+/**
+ * @param {number} value Source value
+ * @param {tcuTexture.ChannelType} type
+ * @return {number} Source value converted to float
+ */
+tcuTexture.channelToFloat = function(value, type) {
+ switch (type) {
+ case tcuTexture.ChannelType.SNORM_INT8: return Math.max(-1, value / 127);
+ case tcuTexture.ChannelType.SNORM_INT16: return Math.max(-1, value / 32767);
+ case tcuTexture.ChannelType.SNORM_INT32: return Math.max(-1, value / 2147483647);
+ case tcuTexture.ChannelType.UNORM_INT8: return value / 255;
+ case tcuTexture.ChannelType.UNORM_INT16: return value / 65535;
+ case tcuTexture.ChannelType.UNORM_INT32: return value / 4294967295;
+ case tcuTexture.ChannelType.SIGNED_INT8: return value;
+ case tcuTexture.ChannelType.SIGNED_INT16: return value;
+ case tcuTexture.ChannelType.SIGNED_INT32: return value;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return value;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return value;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return value;
+ case tcuTexture.ChannelType.HALF_FLOAT: return tcuFloat.halfFloatToNumber(value);
+ case tcuTexture.ChannelType.FLOAT: return value;
+ }
+ throw new Error('Unrecognized tcuTexture.channel type ' + type);
+};
+
+/**
+ * @param {number} value Source value
+ * @param {tcuTexture.ChannelType} type
+ * @return {number} Source value converted to int
+ */
+tcuTexture.channelToInt = function(value, type) {
+ switch (type) {
+ case tcuTexture.ChannelType.HALF_FLOAT: return Math.round(tcuFloat.halfFloatToNumber(value));
+ case tcuTexture.ChannelType.FLOAT: return Math.round(value);
+ default:
+ return value;
+ }
+};
+
+/**
+ * @param {tcuTexture.ChannelOrder} order
+ * @return {number}
+ */
+tcuTexture.getNumUsedChannels = function(order) {
+ switch (order) {
+ case tcuTexture.ChannelOrder.R: return 1;
+ case tcuTexture.ChannelOrder.A: return 1;
+ case tcuTexture.ChannelOrder.I: return 1;
+ case tcuTexture.ChannelOrder.L: return 1;
+ case tcuTexture.ChannelOrder.LA: return 2;
+ case tcuTexture.ChannelOrder.RG: return 2;
+ case tcuTexture.ChannelOrder.RA: return 2;
+ case tcuTexture.ChannelOrder.RGB: return 3;
+ case tcuTexture.ChannelOrder.RGBA: return 4;
+ case tcuTexture.ChannelOrder.ARGB: return 4;
+ case tcuTexture.ChannelOrder.BGRA: return 4;
+ case tcuTexture.ChannelOrder.sRGB: return 3;
+ case tcuTexture.ChannelOrder.sRGBA: return 4;
+ case tcuTexture.ChannelOrder.D: return 1;
+ case tcuTexture.ChannelOrder.S: return 1;
+ case tcuTexture.ChannelOrder.DS: return 2;
+ }
+ throw new Error('Unrecognized tcuTexture.channel order ' + order);
+};
+
+/**
+ * @enum
+ */
+tcuTexture.WrapMode = {
+ CLAMP_TO_EDGE: 0, //! Clamp to edge
+ CLAMP_TO_BORDER: 1, //! Use border color at edge
+ REPEAT_GL: 2, //! Repeat with OpenGL semantics
+ REPEAT_CL: 3, //! Repeat with OpenCL semantics
+ MIRRORED_REPEAT_GL: 4, //! Mirrored repeat with OpenGL semantics
+ MIRRORED_REPEAT_CL: 5 //! Mirrored repeat with OpenCL semantics
+};
+
+/**
+ * @enum
+ */
+tcuTexture.FilterMode = {
+ NEAREST: 0,
+ LINEAR: 1,
+
+ NEAREST_MIPMAP_NEAREST: 2,
+ NEAREST_MIPMAP_LINEAR: 3,
+ LINEAR_MIPMAP_NEAREST: 4,
+ LINEAR_MIPMAP_LINEAR: 5
+};
+
+/**
+ * @enum
+ */
+tcuTexture.CompareMode = {
+ COMPAREMODE_NONE: 0,
+ COMPAREMODE_LESS: 1,
+ COMPAREMODE_LESS_OR_EQUAL: 2,
+ COMPAREMODE_GREATER: 3,
+ COMPAREMODE_GREATER_OR_EQUAL: 4,
+ COMPAREMODE_EQUAL: 5,
+ COMPAREMODE_NOT_EQUAL: 6,
+ COMPAREMODE_ALWAYS: 7,
+ COMPAREMODE_NEVER: 8
+};
+
+/**
+ * @constructor
+ * @param {!tcuTexture.WrapMode} wrapS
+ * @param {!tcuTexture.WrapMode} wrapT
+ * @param {!tcuTexture.WrapMode} wrapR
+ * @param {!tcuTexture.FilterMode} minFilter
+ * @param {!tcuTexture.FilterMode} magFilter
+ * @param {number=} lodThreshold
+ * @param {boolean=} normalizedCoords
+ * @param {tcuTexture.CompareMode=} compare
+ * @param {number=} compareChannel
+ * @param {Array<number>=} borderColor
+ * @param {boolean=} seamlessCubeMap
+ */
+tcuTexture.Sampler = function(wrapS, wrapT, wrapR, minFilter, magFilter, lodThreshold, normalizedCoords, compare, compareChannel, borderColor, seamlessCubeMap) {
+ /** @type {!tcuTexture.WrapMode} */ this.wrapS = wrapS;
+ /** @type {!tcuTexture.WrapMode} */ this.wrapT = wrapT;
+ /** @type {!tcuTexture.WrapMode} */ this.wrapR = wrapR;
+ /** @type {!tcuTexture.FilterMode} */ this.minFilter = minFilter;
+ /** @type {!tcuTexture.FilterMode} */ this.magFilter = magFilter;
+ this.lodThreshold = lodThreshold || 0;
+ this.normalizedCoords = normalizedCoords === undefined ? true : normalizedCoords;
+ /** @type {tcuTexture.CompareMode} */ this.compare = compare || tcuTexture.CompareMode.COMPAREMODE_NONE;
+ this.compareChannel = compareChannel || 0;
+ this.borderColor = borderColor || [0, 0, 0, 0];
+ this.seamlessCubeMap = seamlessCubeMap || false;
+};
+
+/**
+ * Special unnormalization for REPEAT_CL and MIRRORED_REPEAT_CL tcuTexture.wrap modes; otherwise ordinary unnormalization.
+ * @param {tcuTexture.WrapMode} mode
+ * @param {number} c Value to tcuTexture.unnormalize
+ * @param {number} size Unnormalized type size (integer)
+ * @return {number}
+ */
+tcuTexture.unnormalize = function(mode, c, size) {
+ switch (mode) {
+ case tcuTexture.WrapMode.CLAMP_TO_EDGE:
+ case tcuTexture.WrapMode.CLAMP_TO_BORDER:
+ case tcuTexture.WrapMode.REPEAT_GL:
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_GL: // Fall-through (ordinary case).
+ return size * c;
+
+ case tcuTexture.WrapMode.REPEAT_CL:
+ return size * (c - Math.floor(c));
+
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_CL:
+ return size * Math.abs(c - 2 * deMath.rint(0.5 * c));
+ }
+ throw new Error('Unrecognized tcuTexture.wrap mode ' + mode);
+};
+
+/**
+ * @param {tcuTexture.WrapMode} mode
+ * @param {number} c Source value (integer)
+ * @param {number} size Type size (integer)
+ * @return {number}
+ */
+tcuTexture.wrap = function(mode, c, size) {
+ switch (mode) {
+ case tcuTexture.WrapMode.CLAMP_TO_BORDER:
+ return deMath.clamp(c, -1, size);
+
+ case tcuTexture.WrapMode.CLAMP_TO_EDGE:
+ return deMath.clamp(c, 0, size - 1);
+
+ case tcuTexture.WrapMode.REPEAT_GL:
+ return deMath.imod(c, size);
+
+ case tcuTexture.WrapMode.REPEAT_CL:
+ return deMath.imod(c, size);
+
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_GL:
+ return (size - 1) - deMath.mirror(deMath.imod(c, 2 * size) - size);
+
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_CL:
+ return deMath.clamp(c, 0, size - 1); // \note Actual mirroring done already in unnormalization function.
+ }
+ throw new Error('Unrecognized tcuTexture.wrap mode ' + mode);
+};
+
+/**
+ * @param {number} cs
+ * @return {number}
+ */
+tcuTexture.sRGBChannelToLinear = function(cs) {
+ if (cs <= 0.04045)
+ return cs / 12.92;
+ else
+ return Math.pow((cs + 0.055) / 1.055, 2.4);
+};
+
+/**
+ * Convert sRGB to linear colorspace
+ * @param {Array<number>} cs Vec4
+ * @return {Array<number>} Vec4
+ */
+tcuTexture.sRGBToLinear = function(cs) {
+ return [
+ tcuTexture.sRGBChannelToLinear(cs[0]),
+ tcuTexture.sRGBChannelToLinear(cs[1]),
+ tcuTexture.sRGBChannelToLinear(cs[2]),
+ cs[3]
+ ];
+};
+
+/**
+ * Texel tcuTexture.lookup with color conversion.
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {number} i
+ * @param {number} j
+ * @param {number} k
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.lookup = function(access, i, j, k) {
+ var p = access.getPixel(i, j, k);
+ return access.getFormat().isSRGB() ? tcuTexture.sRGBToLinear(p) : p;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} u
+ * @param {number} v
+ * @param {(number|Array<number>)} depthOrOffset depth (int) or offset (ivec3)
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.sampleLinear2D = function(access, sampler, u, v, depthOrOffset) {
+ /** @type {number} */ var xOffset = 0;
+ /** @type {number} */ var yOffset = 0;
+ /** @type {number} */ var value;
+ if (Array.isArray(depthOrOffset)) {
+ xOffset = depthOrOffset[0];
+ yOffset = depthOrOffset[1];
+ value = depthOrOffset[2];
+ } else {
+ value = /** @type {number} */ (depthOrOffset);
+ }
+
+ /**
+ * @param {Array<number>} p00
+ * @param {Array<number>} p10
+ * @param {Array<number>} p01
+ * @param {Array<number>} p11
+ * @param {number} a
+ * @param {number} b
+ */
+ var interpolateQuad = function(p00, p10, p01, p11, a, b) {
+ var s00 = (1 - a) * (1 - b);
+ var s10 = a * (1 - b);
+ var s01 = (1 - a) * b;
+ var s11 = a * b;
+
+ return [
+ (p00[0] * s00) + (p10[0] * s10) + (p01[0] * s01) + (p11[0] * s11),
+ (p00[1] * s00) + (p10[1] * s10) + (p01[1] * s01) + (p11[1] * s11),
+ (p00[2] * s00) + (p10[2] * s10) + (p01[2] * s01) + (p11[2] * s11),
+ (p00[3] * s00) + (p10[3] * s10) + (p01[3] * s01) + (p11[3] * s11)
+ ];
+ };
+
+ var w = access.getWidth();
+ var h = access.getHeight();
+
+ var x0 = Math.floor(u - 0.5) + xOffset;
+ var x1 = x0 + 1;
+ var y0 = Math.floor(v - 0.5) + yOffset;
+ var y1 = y0 + 1;
+
+ var i0 = tcuTexture.wrap(sampler.wrapS, x0, w);
+ var i1 = tcuTexture.wrap(sampler.wrapS, x1, w);
+ var j0 = tcuTexture.wrap(sampler.wrapT, y0, h);
+ var j1 = tcuTexture.wrap(sampler.wrapT, y1, h);
+
+ var a = deMath.deFloatFrac(u - 0.5);
+ var b = deMath.deFloatFrac(v - 0.5);
+
+ var i0UseBorder = sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(i0, 0, w);
+ var i1UseBorder = sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(i1, 0, w);
+ var j0UseBorder = sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(j0, 0, h);
+ var j1UseBorder = sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(j1, 0, h);
+
+ // Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
+ var p00 = (i0UseBorder || j0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j0, value);
+ var p10 = (i1UseBorder || j0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j0, value);
+ var p01 = (i0UseBorder || j1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j1, value);
+ var p11 = (i1UseBorder || j1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j1, value);
+
+ // Interpolate.
+ return interpolateQuad(p00, p10, p01, p11, a, b);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} u
+ * @param {number} v
+ * @param {number} w
+ * @param {Array<number>=} offset
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.sampleLinear3D = function(access, sampler, u, v, w, offset) {
+ /**
+ * @param {Array<number>} p000
+ * @param {Array<number>} p100
+ * @param {Array<number>} p010
+ * @param {Array<number>} p110
+ * @param {Array<number>} p001
+ * @param {Array<number>} p101
+ * @param {Array<number>} p011
+ * @param {Array<number>} p111
+ * @param {number} a
+ * @param {number} b
+ * @param {number} c
+ */
+ var interpolateCube = function(p000, p100, p010, p110, p001, p101, p011, p111, a, b, c) {
+ var s000 = (1 - a) * (1 - b) * (1 - c);
+ var s100 = a * (1 - b) * (1 - c);
+ var s010 = (1 - a) * b * (1 - c);
+ var s110 = a * b * (1 - c);
+ var s001 = (1 - a) * (1 - b) * c;
+ var s101 = a * (1 - b) * c;
+ var s011 = (1 - a) * b * c;
+ var s111 = a * b * c;
+
+ return [
+ (p000[0] * s000) + (p100[0] * s100) + (p010[0] * s010) + (p110[0] * s110) + (p001[0] * s001) + (p101[0] * s101) + (p011[0] * s011) + (p111[0] * s111),
+ (p000[1] * s000) + (p100[1] * s100) + (p010[1] * s010) + (p110[1] * s110) + (p001[1] * s001) + (p101[1] * s101) + (p011[1] * s011) + (p111[1] * s111),
+ (p000[2] * s000) + (p100[2] * s100) + (p010[2] * s010) + (p110[2] * s110) + (p001[2] * s001) + (p101[2] * s101) + (p011[2] * s011) + (p111[2] * s111),
+ (p000[3] * s000) + (p100[3] * s100) + (p010[3] * s010) + (p110[3] * s110) + (p001[3] * s001) + (p101[3] * s101) + (p011[3] * s011) + (p111[3] * s111)
+ ];
+ };
+
+ var width = access.getWidth();
+ var height = access.getHeight();
+ var depth = access.getDepth();
+
+ /** @type {number} */ var xOffset = 0;
+ /** @type {number} */ var yOffset = 0;
+ /** @type {number} */ var zOffset = 0;
+
+ if (offset !== undefined && offset.length === 3) {
+ xOffset = offset[0];
+ yOffset = offset[1];
+ zOffset = offset[2];
+ }
+
+ var x0 = Math.floor(u - 0.5) + xOffset;
+ var x1 = x0 + 1;
+ var y0 = Math.floor(v - 0.5) + yOffset;
+ var y1 = y0 + 1;
+ var z0 = Math.floor(w - 0.5) + zOffset;
+ var z1 = z0 + 1;
+
+ var i0 = tcuTexture.wrap(sampler.wrapS, x0, width);
+ var i1 = tcuTexture.wrap(sampler.wrapS, x1, width);
+ var j0 = tcuTexture.wrap(sampler.wrapT, y0, height);
+ var j1 = tcuTexture.wrap(sampler.wrapT, y1, height);
+ var k0 = tcuTexture.wrap(sampler.wrapR, z0, depth);
+ var k1 = tcuTexture.wrap(sampler.wrapR, z1, depth);
+
+ var a = deMath.deFloatFrac(u - 0.5);
+ var b = deMath.deFloatFrac(v - 0.5);
+ var c = deMath.deFloatFrac(w - 0.5);
+
+ var i0UseBorder = sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(i0, 0, width);
+ var i1UseBorder = sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(i1, 0, width);
+ var j0UseBorder = sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(j0, 0, height);
+ var j1UseBorder = sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(j1, 0, height);
+ var k0UseBorder = sampler.wrapR == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(k0, 0, depth);
+ var k1UseBorder = sampler.wrapR == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(k1, 0, depth);
+
+ // Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
+ var p000 = (i0UseBorder || j0UseBorder || k0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j0, k0);
+ var p100 = (i1UseBorder || j0UseBorder || k0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j0, k0);
+ var p010 = (i0UseBorder || j1UseBorder || k0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j1, k0);
+ var p110 = (i1UseBorder || j1UseBorder || k0UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j1, k0);
+ var p001 = (i0UseBorder || j0UseBorder || k1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j0, k1);
+ var p101 = (i1UseBorder || j0UseBorder || k1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j0, k1);
+ var p011 = (i0UseBorder || j1UseBorder || k1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i0, j1, k1);
+ var p111 = (i1UseBorder || j1UseBorder || k1UseBorder) ? sampler.borderColor : tcuTexture.lookup(access, i1, j1, k1);
+
+ // Interpolate.
+ return interpolateCube(p000, p100, p010, p110, p001, p101, p011, p111, a, b, c);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} u
+ * @param {number} v
+ * @param {(number|Array<number>)} depthOrOffset depth (integer) or offset (ivec3)
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.sampleNearest2D = function(access, sampler, u, v, depthOrOffset) {
+ /** @type {number} */ var xOffset = 0;
+ /** @type {number} */ var yOffset = 0;
+ /** @type {number} */ var value;
+ if (Array.isArray(depthOrOffset)) {
+ xOffset = depthOrOffset[0];
+ yOffset = depthOrOffset[1];
+ value = depthOrOffset[2];
+ } else {
+ value = /** @type {number} */ (depthOrOffset);
+ }
+
+ var width = access.getWidth();
+ var height = access.getHeight();
+
+ var x = Math.floor(u) + xOffset;
+ var y = Math.floor(v) + yOffset;
+
+ // Check for CLAMP_TO_BORDER.
+ if ((sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(x, 0, width)) ||
+ (sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(y, 0, height)))
+ return sampler.borderColor;
+
+ var i = tcuTexture.wrap(sampler.wrapS, x, width);
+ var j = tcuTexture.wrap(sampler.wrapT, y, height);
+
+ return tcuTexture.lookup(access, i, j, value);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} u
+ * @param {number} v
+ * @param {number} w
+ * @param {Array<number>=} offset
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.sampleNearest3D = function(access, sampler, u, v, w, offset) {
+ var width = access.getWidth();
+ var height = access.getHeight();
+ var depth = access.getDepth();
+ /** @type {number} */ var xOffset = 0;
+ /** @type {number} */ var yOffset = 0;
+ /** @type {number} */ var zOffset = 0;
+
+ if (offset !== undefined && offset.length === 3) {
+ xOffset = offset[0];
+ yOffset = offset[1];
+ zOffset = offset[2];
+ }
+
+ var x = Math.floor(u) + xOffset;
+ var y = Math.floor(v) + yOffset;
+ var z = Math.floor(w) + zOffset;
+
+ // Check for CLAMP_TO_BORDER.
+ if ((sampler.wrapS == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(x, 0, width)) ||
+ (sampler.wrapT == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(y, 0, height)) ||
+ (sampler.wrapR == tcuTexture.WrapMode.CLAMP_TO_BORDER && !deMath.deInBounds32(z, 0, depth)))
+ return sampler.borderColor;
+
+ var i = tcuTexture.wrap(sampler.wrapS, x, width);
+ var j = tcuTexture.wrap(sampler.wrapT, y, height);
+ var k = tcuTexture.wrap(sampler.wrapR, z, depth);
+
+ return tcuTexture.lookup(access, i, j, k);
+};
+
+/**
+ * @param {Array<number>} color Vec4 color
+ * @return {number} The color in packed 32 bit format
+ */
+tcuTexture.packRGB999E5 = function(color) {
+ /** @const */ var mBits = 9;
+ /** @const */ var eBits = 5;
+ /** @const */ var eBias = 15;
+ /** @const */ var eMax = (1 << eBits) - 1;
+ /** @const */ var maxVal = (((1 << mBits) - 1) * (1 << (eMax - eBias))) / (1 << mBits);
+
+ var rc = deMath.clamp(color[0], 0, maxVal);
+ var gc = deMath.clamp(color[1], 0, maxVal);
+ var bc = deMath.clamp(color[2], 0, maxVal);
+ var maxc = Math.max(rc, gc, bc);
+ var expp = Math.max(-eBias - 1, Math.floor(Math.log2(maxc))) + 1 + eBias;
+ var e = Math.pow(2, expp - eBias - mBits);
+ var maxs = Math.floor(maxc / e + 0.5);
+
+ var exps = maxs == (1 << mBits) ? expp + 1 : expp;
+ var rs = deMath.clamp(Math.floor(rc / e + 0.5), 0, (1 << 9) - 1);
+ var gs = deMath.clamp(Math.floor(gc / e + 0.5), 0, (1 << 9) - 1);
+ var bs = deMath.clamp(Math.floor(bc / e + 0.5), 0, (1 << 9) - 1);
+
+ DE_ASSERT((exps & ~((1 << 5) - 1)) == 0);
+ DE_ASSERT((rs & ~((1 << 9) - 1)) == 0);
+ DE_ASSERT((gs & ~((1 << 9) - 1)) == 0);
+ DE_ASSERT((bs & ~((1 << 9) - 1)) == 0);
+
+ return rs | (gs << 9) | (bs << 18) | (exps << 27);
+};
+
+/**
+ * @param {number} color Color in packed 32 bit format
+ * @return {Array<number>} The color in unpacked format
+ */
+tcuTexture.unpackRGB999E5 = function(color) {
+ var mBits = 9;
+ var eBias = 15;
+
+ var exp = (color >> 27) & ((1 << 5) - 1);
+ var bs = (color >> 18) & ((1 << 9) - 1);
+ var gs = (color >> 9) & ((1 << 9) - 1);
+ var rs = color & ((1 << 9) - 1);
+
+ var e = Math.pow(2, (exp - eBias - mBits));
+ var r = rs * e;
+ var g = gs * e;
+ var b = bs * e;
+
+ return [r, g, b, 1];
+};
+
+/**
+ * \brief Read-only pixel data access
+ *
+ * tcuTexture.ConstPixelBufferAccess encapsulates pixel data pointer along with
+ * format and layout information. It can be used for read-only access
+ * to arbitrary pixel buffers.
+ *
+ * Access objects are like iterators or pointers. They can be passed around
+ * as values and are valid as long as the storage doesn't change.
+ * @constructor
+ */
+tcuTexture.ConstPixelBufferAccess = function(descriptor) {
+ if (descriptor) {
+ this.m_offset = descriptor.offset || 0;
+ this.m_format = descriptor.format || new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT);
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ if (descriptor.depth)
+ this.m_depth = descriptor.depth;
+ else
+ this.m_depth = 1;
+ this.m_data = descriptor.data;
+ if (descriptor.rowPitch)
+ this.m_rowPitch = descriptor.rowPitch;
+ else
+ this.m_rowPitch = this.m_width * this.m_format.getPixelSize();
+
+ if (descriptor.slicePitch)
+ this.m_slicePitch = descriptor.slicePitch;
+ else
+ this.m_slicePitch = this.m_rowPitch * this.m_height;
+
+ if (this.m_format.isEqual(new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)))
+ this.m_rgba8View = new tcuTexture.RGBA8View(this);
+ else if (this.m_format.isEqual(new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8)))
+ this.m_rgb8View = new tcuTexture.RGBA8View(this);
+
+ }
+
+ this.m_dataPtrType = null;
+ this.m_dataPtr = null;
+};
+
+tcuTexture.ConstPixelBufferAccess.prototype.toString = function() {
+ var str = 'BufferAccess(format: ' + this.m_format +
+ ', width: ' + this.m_width +
+ ', height: ' + this.m_height;
+ if (this.m_depth > 1)
+ str += ', depth: ' + this.m_depth;
+ if (this.m_rowPitch != this.m_width * this.m_format.getPixelSize())
+ str += ', row pitch: ' + this.m_rowPitch;
+ if (this.m_slicePitch != this.m_rowPitch * this.m_height)
+ str += ', slice pitch: ' + this.m_slicePitch;
+ if (this.m_offset > 0)
+ str += ', offset: ' + this.m_offset;
+ str += ')';
+ return str;
+};
+
+/** @return {number} */
+tcuTexture.ConstPixelBufferAccess.prototype.getDataSize = function() { return this.m_depth * this.m_slicePitch; };
+tcuTexture.ConstPixelBufferAccess.prototype.isEmpty = function() { return this.m_width == 0 || this.m_height == 0 || this.m_depth == 0; };
+/** @return {goog.TypedArray} */
+tcuTexture.ConstPixelBufferAccess.prototype.getDataPtr = function() {
+ if (this.m_dataPtrType != this.m_format.type) {
+ this.m_dataPtrType = this.m_format.type;
+ var arrayType = tcuTexture.getTypedArray(this.m_format.type);
+ this.m_dataPtr = new arrayType(this.m_data, this.m_offset);
+ }
+ return this.m_dataPtr;
+};
+/** @return {ArrayBuffer} */
+tcuTexture.ConstPixelBufferAccess.prototype.getBuffer = function() {
+ return this.m_data;
+};
+/** @return {number} */
+tcuTexture.ConstPixelBufferAccess.prototype.getRowPitch = function() { return this.m_rowPitch; };
+/** @return {number} */
+tcuTexture.ConstPixelBufferAccess.prototype.getWidth = function() { return this.m_width; };
+/** @return {number} */
+tcuTexture.ConstPixelBufferAccess.prototype.getHeight = function() { return this.m_height; };
+/** @return {number} */
+tcuTexture.ConstPixelBufferAccess.prototype.getDepth = function() { return this.m_depth; };
+/** @return {number} */
+tcuTexture.ConstPixelBufferAccess.prototype.getSlicePitch = function() { return this.m_slicePitch; };
+/** @return {tcuTexture.TextureFormat} */
+tcuTexture.ConstPixelBufferAccess.prototype.getFormat = function() { return this.m_format; };
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ * @return {number} stencil value
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.getPixStencil = function(x, y, z) {
+ z = z || 0;
+
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ x = Math.round(x);
+ y = Math.round(y);
+ z = Math.round(z);
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ case tcuTexture.ChannelOrder.S: return (pixelPtr[pixelPtrOffset] >> 8) & 0xff;
+ case tcuTexture.ChannelOrder.DS: return pixelPtr[pixelPtrOffset] & 0xff;
+
+ default:
+ DE_ASSERT(false);
+ return 0;
+ }
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV:
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ var u32array = new Uint32Array(this.m_data, offset + this.m_offset + 4, 1);
+ return u32array[0] & 0xff;
+
+ default: {
+ if (this.m_format.order == tcuTexture.ChannelOrder.S)
+ return tcuTexture.channelToInt(pixelPtr[pixelPtrOffset], this.m_format.type);
+ else {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ var stencilChannelIndex = 3;
+ return tcuTexture.channelToInt(pixelPtr[stencilChannelIndex + pixelPtrOffset], this.m_format.type);
+ }
+ }
+ }
+};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ * @return {number}
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.getPixDepth = function(x, y, z) {
+ if (z == null)
+ z = 0;
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ x = Math.round(x);
+ y = Math.round(y);
+ z = Math.round(z);
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ var ub = function(pixel, offset, count) {
+ return (pixel >> offset) & ((1 << count) - 1);
+ };
+ var nb = function(pixel, offset, count) {
+ return tcuTexture.channelToNormFloat(ub(pixel, offset, count), count);
+ };
+
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ case tcuTexture.ChannelOrder.D: // fall-through
+ case tcuTexture.ChannelOrder.DS:
+ return nb(pixelPtr[pixelPtrOffset], 8, 24);
+ default:
+ throw new Error('Unsupported tcuTexture.channel order ' + this.m_format.order);
+ }
+ break;
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ return pixelPtr[pixelPtrOffset];
+ break;
+ }
+
+ default: {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.D || this.m_format.order == tcuTexture.ChannelOrder.DS);
+ return tcuTexture.channelToFloat(pixelPtr[pixelPtrOffset], this.m_format.type);
+ }
+ }
+};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ * @return {Array<number>} Pixel value as Vec4
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.getPixel = function(x, y, z) {
+ z = z || 0;
+
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ return this._getPixelInternal(Math.round(x), Math.round(y), Math.round(z));
+};
+
+// NOTE: getPixel has been broken into getPixel, _getPixelInternal, and _getPixelPacked
+// because having them combined previously was causing V8 depots
+tcuTexture.ConstPixelBufferAccess.prototype._getPixelInternal = function(x, y, z) {
+ // Quick paths
+ if (z == 0) {
+ if (this.m_rgba8View) {
+ var color = this.m_rgba8View.read(x, y, 4);
+ color[0] /= 255;
+ color[1] /= 255;
+ color[2] /= 255;
+ color[3] /= 255;
+ return color;
+ } else if (this.m_rgb8View) {
+ var color = this.m_rgb8View.read(x, y, 3);
+ color[0] /= 255;
+ color[1] /= 255;
+ color[2] /= 255;
+ color[3] = 1;
+ return color;
+ }
+ }
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ return this._getPixelPacked(pixelPtr, pixelPtrOffset);
+};
+
+tcuTexture.ConstPixelBufferAccess.prototype._getPixelPacked = (function() {
+
+ var ub = function(pixel, offset, count) {
+ return (pixel >> offset) & ((1 << count) - 1);
+ };
+ var nb = function(pixel, offset, count) {
+ var maxVal = (1 << count) - 1;
+ return ((pixel >> offset) & ((1 << count) - 1)) / maxVal;
+ };
+ var f11 = tcuFloat.float11ToNumber;
+ var f10 = tcuFloat.float10ToNumber;
+
+ return function tcuTexture_ConstPixelBufferAccess_getPixelPacked(pixelPtr, pixelPtrOffset) {
+ var pixel = pixelPtr[pixelPtrOffset];
+
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNORM_SHORT_565: return [nb(pixel, 11, 5), nb(pixel, 5, 6), nb(pixel, 0, 5), 1];
+ case tcuTexture.ChannelType.UNORM_SHORT_555: return [nb(pixel, 10, 5), nb(pixel, 5, 5), nb(pixel, 0, 5), 1];
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: return [nb(pixel, 12, 4), nb(pixel, 8, 4), nb(pixel, 4, 4), nb(pixel, 0, 4)];
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: return [nb(pixel, 11, 5), nb(pixel, 6, 5), nb(pixel, 1, 5), nb(pixel, 0, 1)];
+ case tcuTexture.ChannelType.UNORM_INT_101010: return [nb(pixel, 22, 10), nb(pixel, 12, 10), nb(pixel, 2, 10), 1];
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: return [nb(pixel, 0, 10), nb(pixel, 10, 10), nb(pixel, 20, 10), nb(pixel, 30, 2)];
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return [ub(pixel, 0, 10), ub(pixel, 10, 10), ub(pixel, 20, 10), ub(pixel, 30, 2)];
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: return tcuTexture.unpackRGB999E5(pixel);
+
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ // \note Stencil is always ignored.
+ case tcuTexture.ChannelOrder.D: return [nb(pixel, 8, 24), 0, 0, 1];
+ case tcuTexture.ChannelOrder.DS: return [nb(pixel, 8, 24), 0, 0, 1 /* (float)ub(0, 8) */];
+ default:
+ DE_ASSERT(false);
+ }
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ // \note Stencil is ignored.
+ return [pixel, 0, 0, 1];
+ }
+
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: {
+ return [f11(ub(pixel, 0, 11)), f11(ub(pixel, 11, 11)), f10(ub(pixel, 22, 10)), 1];
+ }
+
+ default:
+ break;
+ }
+
+ // Generic path.
+ var result = [0, 0, 0, 0];
+ var channelMap = tcuTexture.getChannelReadMap(this.m_format.order);
+ var channelSize = tcuTexture.getChannelSize(this.m_format.type);
+
+ for (var c = 0; c < 4; c++) {
+ var map = channelMap[c];
+ if (map == tcuTexture.channel.ZERO)
+ result[c] = 0;
+ else if (map == tcuTexture.channel.ONE)
+ result[c] = 1;
+ else
+ result[c] = tcuTexture.channelToFloat(pixelPtr[map + pixelPtrOffset], this.m_format.type);
+ }
+
+ return result;
+ };
+})();
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ * @return {Array<number>} Pixel value as Vec4
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.getPixelInt = function(x, y, z) {
+ z = z || 0;
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ x = Math.round(x);
+ y = Math.round(y);
+ z = Math.round(z);
+
+ // Quick paths
+ if (z == 0) {
+ if (this.m_rgba8View)
+ return this.m_rgba8View.read(x, y, 4);
+ else if (this.m_rgb8View)
+ return this.m_rgb8View.read(x, y, 3);
+ }
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+ var pixel = pixelPtr[pixelPtrOffset];
+
+ var ub = function(pixel, offset, count) {
+ return (pixel >> offset) & ((1 << count) - 1);
+ };
+
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNORM_SHORT_565: return [ub(pixel, 11, 5), ub(pixel, 5, 6), ub(pixel, 0, 5), 1];
+ case tcuTexture.ChannelType.UNORM_SHORT_555: return [ub(pixel, 10, 5), ub(pixel, 5, 5), ub(pixel, 0, 5), 1];
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: return [ub(pixel, 12, 4), ub(pixel, 8, 4), ub(pixel, 4, 4), ub(pixel, 0, 4)];
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: return [ub(pixel, 11, 5), ub(pixel, 6, 5), ub(pixel, 1, 5), ub(pixel, 0, 1)];
+ case tcuTexture.ChannelType.UNORM_INT_101010: return [ub(pixel, 22, 10), ub(pixel, 12, 10), ub(pixel, 2, 10), 1];
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: return [ub(pixel, 0, 10), ub(pixel, 10, 10), ub(pixel, 20, 10), ub(pixel, 30, 2)];
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return [ub(pixel, 0, 10), ub(pixel, 10, 10), ub(pixel, 20, 10), ub(pixel, 30, 2)];
+
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ case tcuTexture.ChannelOrder.D: return [ub(pixel, 8, 24), 0, 0, 1];
+ case tcuTexture.ChannelOrder.S: return [0, 0, 0, ub(pixel, 8, 24)];
+ case tcuTexture.ChannelOrder.DS: return [ub(pixel, 8, 24), 0, 0, ub(pixel, 0, 8)];
+ default:
+ DE_ASSERT(false);
+ }
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ var u32array = new Uint32Array(this.m_data, this.m_offset + offset + 4, 1);
+ return [pixel, 0, 0, ub(u32array[0], 0, 8)];
+ }
+
+ default:
+ break;
+ }
+
+ // Generic path.
+ var result = [];
+ result.length = 4;
+ var channelMap = tcuTexture.getChannelReadMap(this.m_format.order);
+ var channelSize = tcuTexture.getChannelSize(this.m_format.type);
+
+ for (var c = 0; c < 4; c++) {
+ var map = channelMap[c];
+ if (map == tcuTexture.channel.ZERO)
+ result[c] = 0;
+ else if (map == tcuTexture.channel.ONE)
+ result[c] = 1;
+ else
+ result[c] = tcuTexture.channelToInt(pixelPtr[map + pixelPtrOffset], this.m_format.type);
+ }
+
+ return result;
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {?tcuTexture.FilterMode} filter
+ * @param {number} s
+ * @param {number} t
+ * @param {number} depth (integer)
+ * @return {Array<number>} Sample color
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.sample2D = function(sampler, filter, s, t, depth) {
+ DE_ASSERT(deMath.deInBounds32(depth, 0, this.m_depth));
+
+ // Non-normalized coordinates.
+ var u = s;
+ var v = t;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, this.m_width);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, this.m_height);
+ }
+
+ switch (filter) {
+ case tcuTexture.FilterMode.NEAREST: return tcuTexture.sampleNearest2D(this, sampler, u, v, depth);
+ case tcuTexture.FilterMode.LINEAR: return tcuTexture.sampleLinear2D(this, sampler, u, v, depth);
+ default:
+ throw new Error('Invalid filter:' + filter);
+ }
+ throw new Error('Unimplemented');
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {?tcuTexture.FilterMode} filter
+ * @param {number} s
+ * @param {number} t
+ * @param {Array<number>} offset
+ * @return {Array<number>} Sample color
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.sample2DOffset = function(sampler, filter, s, t, offset) {
+ DE_ASSERT(deMath.deInBounds32(offset[2], 0, this.m_depth));
+
+ // Non-normalized coordinates.
+ var u = s;
+ var v = t;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, this.m_width);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, this.m_height);
+ }
+
+ switch (filter) {
+ case tcuTexture.FilterMode.NEAREST: return tcuTexture.sampleNearest2D(this, sampler, u, v, offset);
+ case tcuTexture.FilterMode.LINEAR: return tcuTexture.sampleLinear2D(this, sampler, u, v, offset);
+ default:
+ throw new Error('Invalid filter:' + filter);
+ }
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {?tcuTexture.FilterMode} filter
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {Array<number>} offset
+ * @return {Array<number>} Sample color
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.sample3DOffset = function(sampler, filter, s, t, r, offset) {
+ // Non-normalized coordinates.
+ /** @type {number} */ var u = s;
+ /** @type {number} */ var v = t;
+ /** @type {number} */ var w = r;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, this.m_width);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, this.m_height);
+ w = tcuTexture.unnormalize(sampler.wrapR, r, this.m_depth);
+ }
+
+ switch (filter) {
+ case tcuTexture.FilterMode.NEAREST: return tcuTexture.sampleNearest3D(this, sampler, u, v, w, offset);
+ case tcuTexture.FilterMode.LINEAR: return tcuTexture.sampleLinear3D(this, sampler, u, v, w, offset);
+ default:
+ throw new Error('Invalid filter:' + filter);
+ }
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filter
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {Array<number>} offset
+ * @return {number}
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.sample2DCompare = function(sampler, filter, ref, s, t, offset) {
+ DE_ASSERT(deMath.deInBounds32(offset[2], 0, this.m_depth));
+
+ // Format information for comparison function
+ var isFixedPointDepth = tcuTexture.isFixedPointDepthTextureFormat(this.m_format);
+
+ // Non-normalized coordinates.
+ var u = s;
+ var v = t;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, this.m_width);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, this.m_height);
+ }
+
+ switch (filter) {
+ case tcuTexture.FilterMode.NEAREST: return tcuTexture.execCompare(tcuTexture.sampleNearest2D(this, sampler, u, v, offset), sampler.compare, sampler.compareChannel, ref, isFixedPointDepth);
+ case tcuTexture.FilterMode.LINEAR: return tcuTexture.sampleLinear2DCompare(this, sampler, ref, u, v, offset, isFixedPointDepth);
+ default:
+ DE_ASSERT(false);
+ return 0.0;
+ }
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {tcuTexture.FilterMode} filter
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @return {Array<number>} Sample color
+ */
+tcuTexture.ConstPixelBufferAccess.prototype.sample3D = function(sampler, filter, s, t, r) {
+ // Non-normalized coordinates.
+ var u = s;
+ var v = t;
+ var w = r;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, this.m_width);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, this.m_height);
+ w = tcuTexture.unnormalize(sampler.wrapR, r, this.m_depth);
+ }
+
+ switch (filter) {
+ case tcuTexture.FilterMode.NEAREST: return tcuTexture.sampleNearest3D(this, sampler, u, v, w);
+ case tcuTexture.FilterMode.LINEAR: return tcuTexture.sampleLinear3D(this, sampler, u, v, w);
+ default:
+ throw new Error('Invalid filter:' + filter);
+ }
+ throw new Error('Unimplemented');
+};
+
+ /* TODO: do we need any of these? */ {
+ // template<typename T>
+ // Vector<T, 4> getPixelT (int x, int y, int z = 0) const;
+
+ // Vec4 sample3D (const tcuTexture.Sampler& sampler, tcuTexture.tcuTexture.Sampler.tcuTexture.FilterMode filter, float s, float t, float r) const;
+
+ // Vec4 sample2DOffset (const tcuTexture.Sampler& sampler, tcuTexture.Sampler::tcuTexture.FilterMode filter, float s, float t, const IVec3& offset) const;
+ // Vec4 sample3DOffset (const tcuTexture.Sampler& sampler, tcuTexture.Sampler::tcuTexture.FilterMode filter, float s, float t, float r, const IVec3& offset) const;
+
+ // float sample2DCompare (const tcuTexture.Sampler& sampler, tcuTexture.Sampler::tcuTexture.FilterMode filter, float ref, float s, float t, const IVec3& offset) const;
+ };
+
+/** Common type limits
+ *
+ */
+tcuTexture.deTypes = {
+ deInt8: {min: -(1 << 7), max: (1 << 7) - 1},
+ deInt16: {min: -(1 << 15), max: (1 << 15) - 1},
+ deInt32: {min: -2147483648, max: 2147483647},
+ deUint8: {min: 0, max: (1 << 8) - 1},
+ deUint16: {min: 0, max: (1 << 16) - 1},
+ deUint32: {min: 0, max: 4294967295}
+};
+
+/**
+ * Round to even and saturate
+ * @param {{max: number, min: number}} deType from tcuTexture.deTypes
+ * @param {number} value
+ * @return {number}
+ */
+tcuTexture.convertSatRte = function(deType, value) {
+ var minVal = deType.min;
+ var maxVal = deType.max;
+ var floor = Math.floor(value);
+ var frac = value - floor;
+ if (frac == 0.5) {
+ if (floor % 2 != 0)
+ floor += 1;
+ } else if (frac > 0.5) {
+ floor += 1;
+ }
+
+ return Math.max(minVal, Math.min(maxVal, floor));
+};
+
+/**
+ * Saturate value to type range
+ * @param { {max: number, min: number}} deType from tcuTexture.deTypes
+ * @param {number} src
+ * @return {number}
+ */
+tcuTexture.convertSat = function(deType, src) {
+ var minVal = deType.min;
+ var maxVal = deType.max;
+ if (src < minVal)
+ return minVal;
+ else if (src > maxVal)
+ return maxVal;
+ else
+ return src;
+};
+
+/**
+ * @param {number} src Input integer value
+ * @param {tcuTexture.ChannelType} type
+ * @return {number}
+ */
+tcuTexture.intToChannel = function(src, type) {
+ var dst;
+ switch (type) {
+ case tcuTexture.ChannelType.SNORM_INT8: dst = tcuTexture.convertSat(tcuTexture.deTypes.deInt8, src); break;
+ case tcuTexture.ChannelType.SNORM_INT16: dst = tcuTexture.convertSat(tcuTexture.deTypes.deInt16, src); break;
+ case tcuTexture.ChannelType.UNORM_INT8: dst = tcuTexture.convertSat(tcuTexture.deTypes.deUint8, src); break;
+ case tcuTexture.ChannelType.UNORM_INT16: dst = tcuTexture.convertSat(tcuTexture.deTypes.deUint16, src); break;
+ case tcuTexture.ChannelType.SIGNED_INT8: dst = tcuTexture.convertSat(tcuTexture.deTypes.deInt8, src); break;
+ case tcuTexture.ChannelType.SIGNED_INT16: dst = tcuTexture.convertSat(tcuTexture.deTypes.deInt16, src); break;
+ case tcuTexture.ChannelType.SIGNED_INT32: dst = tcuTexture.convertSat(tcuTexture.deTypes.deInt32, src); break;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: dst = tcuTexture.convertSat(tcuTexture.deTypes.deUint8, src); break;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: dst = tcuTexture.convertSat(tcuTexture.deTypes.deUint16, src); break;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: dst = tcuTexture.convertSat(tcuTexture.deTypes.deUint32, src); break;
+ case tcuTexture.ChannelType.HALF_FLOAT: dst = tcuFloat.numberToHalfFloat(src); break;
+ case tcuTexture.ChannelType.FLOAT: dst = src; break;
+ default:
+ throw new Error('Unrecognized tcuTexture.channel type: ' + type);
+ }
+ return dst;
+};
+
+/**
+ * @param {number} src
+ * @param {number} bits
+ * @return {number}
+ */
+tcuTexture.normFloatToChannel = function(src, bits) {
+ var maxVal = (1 << bits) - 1;
+ var intVal = tcuTexture.convertSatRte(tcuTexture.deTypes.deUint32, src * maxVal);
+ return Math.min(maxVal, intVal);
+};
+
+/**
+ * @param {number} src
+ * @param {number} bits
+ * @return {number}
+ */
+tcuTexture.uintToChannel = function(src, bits) {
+ var maxVal = (1 << bits) - 1;
+ return Math.min(maxVal, src);
+};
+
+/**
+ * @param {number} src
+ * @param {tcuTexture.ChannelType} type
+ * @return {number} Converted src color value
+ */
+tcuTexture.floatToChannel = function(src, type) {
+ switch (type) {
+ case tcuTexture.ChannelType.SNORM_INT8: return tcuTexture.convertSatRte(tcuTexture.deTypes.deInt8, src * 127);
+ case tcuTexture.ChannelType.SNORM_INT16: return tcuTexture.convertSatRte(tcuTexture.deTypes.deInt16, src * 32767);
+ case tcuTexture.ChannelType.SNORM_INT32: return tcuTexture.convertSatRte(tcuTexture.deTypes.deInt32, src * 2147483647);
+ case tcuTexture.ChannelType.UNORM_INT8: return tcuTexture.convertSatRte(tcuTexture.deTypes.deUint8, src * 255);
+ case tcuTexture.ChannelType.UNORM_INT16: return tcuTexture.convertSatRte(tcuTexture.deTypes.deUint16, src * 65535);
+ case tcuTexture.ChannelType.UNORM_INT32: return tcuTexture.convertSatRte(tcuTexture.deTypes.deUint32, src * 4294967295);
+ case tcuTexture.ChannelType.SIGNED_INT8: return tcuTexture.convertSatRte(tcuTexture.deTypes.deInt8, src);
+ case tcuTexture.ChannelType.SIGNED_INT16: return tcuTexture.convertSatRte(tcuTexture.deTypes.deInt16, src);
+ case tcuTexture.ChannelType.SIGNED_INT32: return tcuTexture.convertSatRte(tcuTexture.deTypes.deInt32, src);
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return tcuTexture.convertSatRte(tcuTexture.deTypes.deUint8, src);
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return tcuTexture.convertSatRte(tcuTexture.deTypes.deUint16, src);
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return tcuTexture.convertSatRte(tcuTexture.deTypes.deUint32, src);
+ case tcuTexture.ChannelType.HALF_FLOAT: return tcuFloat.numberToHalfFloat(src);
+ case tcuTexture.ChannelType.FLOAT: return src;
+ }
+ throw new Error('Unrecognized type ' + type);
+};
+
+/**
+ * \brief Read-write pixel data access
+ *
+ * This class extends read-only access object by providing write functionality.
+ *
+ * \note tcuTexture.PixelBufferAccess may not have any data members nor add any
+ * virtual functions. It must be possible to reinterpret_cast<>
+ * tcuTexture.PixelBufferAccess to tcuTexture.ConstPixelBufferAccess.
+ * @constructor
+ * @extends {tcuTexture.ConstPixelBufferAccess}
+ *
+ */
+tcuTexture.PixelBufferAccess = function(descriptor) {
+ tcuTexture.ConstPixelBufferAccess.call(this, descriptor);
+};
+
+tcuTexture.PixelBufferAccess.prototype = Object.create(tcuTexture.ConstPixelBufferAccess.prototype);
+tcuTexture.PixelBufferAccess.prototype.constructor = tcuTexture.PixelBufferAccess;
+
+/**
+ * @param {Array<number>} color Vec4 color to set
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ */
+tcuTexture.PixelBufferAccess.prototype.setPixel = function(color, x, y, z) {
+ z = z || 0;
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ this._setPixelInternal(color, Math.round(x), Math.round(y), Math.round(z));
+};
+
+// NOTE: setPixel has been broken into setPixel, _setPixelInternal, and _setPixelPacked
+// because having them combined previously was causing V8 depots
+tcuTexture.PixelBufferAccess.prototype._setPixelInternal = function(color, x, y, z) {
+ // Quick paths
+ if (z == 0) {
+ if (this.m_rgba8View) {
+ color = deMath.toIVec(color);
+ this.m_rgba8View.write(x, y, color, 4);
+ return;
+ } else if (this.m_rgb8View) {
+ color = deMath.toIVec(color);
+ this.m_rgb8View.write(x, y, color, 3);
+ return;
+ }
+ }
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ return this._setPixelPacked(color, pixelPtr, pixelPtrOffset);
+};
+
+tcuTexture.PixelBufferAccess.prototype._setPixelPacked = (function () {
+ var pn = function(val, offs, bits) {
+ return tcuTexture.normFloatToChannel(val, bits) << offs;
+ };
+
+ var pu = function(val, offs, bits) {
+ return tcuTexture.uintToChannel(val, bits) << offs;
+ };
+
+ return function tcuTexture_PixelBufferAccess_setPixelPacked(color, pixelPtr, pixelPtrOffset) {
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNORM_SHORT_565: pixelPtr[pixelPtrOffset] = pn(color[0], 11, 5) | pn(color[1], 5, 6) | pn(color[2], 0, 5); break;
+ case tcuTexture.ChannelType.UNORM_SHORT_555: pixelPtr[pixelPtrOffset] = pn(color[0], 10, 5) | pn(color[1], 5, 5) | pn(color[2], 0, 5); break;
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: pixelPtr[pixelPtrOffset] = pn(color[0], 12, 4) | pn(color[1], 8, 4) | pn(color[2], 4, 4) | pn(color[3], 0, 4); break;
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: pixelPtr[pixelPtrOffset] = pn(color[0], 11, 5) | pn(color[1], 6, 5) | pn(color[2], 1, 5) | pn(color[3], 0, 1); break;
+ case tcuTexture.ChannelType.UNORM_INT_101010: pixelPtr[pixelPtrOffset] = pn(color[0], 22, 10) | pn(color[1], 12, 10) | pn(color[2], 2, 10); break;
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: pixelPtr[pixelPtrOffset] = pn(color[0], 0, 10) | pn(color[1], 10, 10) | pn(color[2], 20, 10) | pn(color[3], 30, 2); break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: pixelPtr[pixelPtrOffset] = pu(color[0], 0, 10) | pu(color[1], 10, 10) | pu(color[2], 20, 10) | pu(color[3], 30, 2); break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: pixelPtr[pixelPtrOffset] = tcuTexture.packRGB999E5(color); break;
+
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ // \note Stencil is always ignored.
+ case tcuTexture.ChannelOrder.D: pixelPtr[pixelPtrOffset] = pn(color[0], 8, 24); break;
+ case tcuTexture.ChannelOrder.S: pixelPtr[pixelPtrOffset] = pn(color[3], 8, 24); break;
+ case tcuTexture.ChannelOrder.DS: pixelPtr[pixelPtrOffset] = pn(color[0], 8, 24) | pu(color[3], 0, 8); break;
+ default:
+ throw new Error('Unsupported tcuTexture.channel order ' + this.m_format.order);
+ }
+ break;
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ pixelPtr[pixelPtrOffset] = color[0];
+ var u32array = new Uint32Array(this.m_data, (pixelPtrOffset * pixelPtr.BYTES_PER_ELEMENT) + this.m_offset + 4, 1);
+ u32array[0] = pu(color[3], 0, 8);
+ break;
+ }
+
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: {
+ var f11 = function(value) {
+ return tcuFloat.numberToFloat11(value);
+ };
+ var f10 = function(value) {
+ return tcuFloat.numberToFloat10(value);
+ };
+
+ pixelPtr[pixelPtrOffset] = f11(color[0]) | (f11(color[1]) << 11) | (f10(color[2]) << 22);
+ break;
+ }
+ case tcuTexture.ChannelType.FLOAT:
+ if (this.m_format.order == tcuTexture.ChannelOrder.D) {
+ pixelPtr[pixelPtrOffset] = color[0];
+ break;
+ }
+ // else fall-through to default case!
+
+ default: {
+ // Generic path.
+ var numChannels = tcuTexture.getNumUsedChannels(this.m_format.order);
+ var map = tcuTexture.getChannelWriteMap(this.m_format.order);
+
+ for (var c = 0; c < numChannels; c++)
+ pixelPtr[c + pixelPtrOffset] = tcuTexture.floatToChannel(color[map[c]], this.m_format.type);
+ }
+ }
+ };
+})();
+
+/**
+ * @param {Array<number>} color Vec4 color to set (unnormalized)
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ */
+tcuTexture.PixelBufferAccess.prototype.setPixelInt = function(color, x, y, z) {
+ z = z || 0;
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ x = Math.round(x);
+ y = Math.round(y);
+ z = Math.round(z);
+
+ // Quick paths
+ if (z == 0) {
+ if (this.m_rgba8View) {
+ this.m_rgba8View.write(x, y, color, 4);
+ return;
+ } else if (this.m_rgb8View) {
+ this.m_rgb8View.write(x, y, color, 3);
+ return;
+ }
+ }
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ var pu = function(val, offs, bits) {
+ return tcuTexture.uintToChannel(val, bits) << offs;
+ };
+
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNORM_SHORT_565: pixelPtr[pixelPtrOffset] = pu(color[0], 11, 5) | pu(color[1], 5, 6) | pu(color[2], 0, 5); break;
+ case tcuTexture.ChannelType.UNORM_SHORT_555: pixelPtr[pixelPtrOffset] = pu(color[0], 10, 5) | pu(color[1], 5, 5) | pu(color[2], 0, 5); break;
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: pixelPtr[pixelPtrOffset] = pu(color[0], 12, 4) | pu(color[1], 8, 4) | pu(color[2], 4, 4) | pu(color[3], 0, 4); break;
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: pixelPtr[pixelPtrOffset] = pu(color[0], 11, 5) | pu(color[1], 6, 5) | pu(color[2], 1, 5) | pu(color[3], 0, 1); break;
+ case tcuTexture.ChannelType.UNORM_INT_101010: pixelPtr[pixelPtrOffset] = pu(color[0], 22, 10) | pu(color[1], 12, 10) | pu(color[2], 2, 10); break;
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: pixelPtr[pixelPtrOffset] = pu(color[0], 0, 10) | pu(color[1], 10, 10) | pu(color[2], 20, 10) | pu(color[3], 30, 2); break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: pixelPtr[pixelPtrOffset] = pu(color[0], 0, 10) | pu(color[1], 10, 10) | pu(color[2], 20, 10) | pu(color[3], 30, 2); break;
+
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ // \note Stencil is always ignored.
+ case tcuTexture.ChannelOrder.D: pixelPtr[pixelPtrOffset] = pu(color[0], 8, 24); break;
+ case tcuTexture.ChannelOrder.S: pixelPtr[pixelPtrOffset] = pu(color[3], 8, 24); break;
+ case tcuTexture.ChannelOrder.DS: pixelPtr[pixelPtrOffset] = pu(color[0], 8, 24) | pu(color[3], 0, 8); break;
+ default:
+ throw new Error('Unsupported tcuTexture.channel order ' + this.m_format.order);
+ }
+ break;
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ pixelPtr[pixelPtrOffset] = color[0];
+ var u32array = new Uint32Array(this.m_data, offset + this.m_offset + 4, 1);
+ u32array[pixelPtrOffset] = pu(color[3], 0, 8);
+ break;
+ }
+
+ default: {
+ // Generic path.
+ var numChannels = tcuTexture.getNumUsedChannels(this.m_format.order);
+ var map = tcuTexture.getChannelWriteMap(this.m_format.order);
+
+ for (var c = 0; c < numChannels; c++)
+ pixelPtr[c + pixelPtrOffset] = tcuTexture.intToChannel(color[map[c]], this.m_format.type);
+ }
+ }
+};
+
+/**
+ * @param {Array<number>=} color Vec4 color to set, optional.
+ * @param {Array<number>=} x Range in x axis, optional.
+ * @param {Array<number>=} y Range in y axis, optional.
+ * @param {Array<number>=} z Range in z axis, optional.
+ */
+tcuTexture.PixelBufferAccess.prototype.clear = function(color, x, y, z) {
+ var c = color || [0, 0, 0, 0];
+ var arrayType = tcuTexture.getTypedArray(this.m_format.type);
+ var range_x = x || [0, this.m_width];
+ var range_y = y || [0, this.m_height];
+ var range_z = z || [0, this.m_depth];
+ var pixelSize = this.m_format.getPixelSize();
+ var numElements = pixelSize / arrayType.BYTES_PER_ELEMENT;
+ var width = range_x[1] - range_x[0];
+ var height = range_y[1] - range_y[0];
+ var depth = range_z[1] - range_z[0];
+ if (x === undefined && y === undefined && z === undefined &&
+ c[0] == 0 && c[1] == 0 && c[2] == 0 && c[3] == 0) {
+ var pixelPtr = new arrayType(this.m_data, this.m_offset);
+ pixelPtr.fill(0);
+ return;
+ }
+
+ //copy first pixel over other pixels in the row
+ var fillRow = function(pixelPtr, numElements, width) {
+ for (var i = 1; i < width; i++)
+ for (var c = 0; c < numElements; c++)
+ pixelPtr[i * numElements + c] = pixelPtr[c];
+ };
+ // copy first row to other rows in all planes
+ var fillPlanes = function(buffer, arrayType, src, offset, rowStride, planeStride, width, height, depth) {
+ for (var j = 0; j < depth; j++)
+ for (var i = (j == 0 ? 1 : 0); i < height; i++) {
+ var dst = new arrayType(buffer, offset + i * rowStride + j * planeStride, width);
+ dst.set(src);
+ }
+ };
+
+ this.setPixel(c, range_x[0], range_y[0], range_z[0]);
+
+ var offset = range_z[0] * this.m_slicePitch + range_y[0] * this.m_rowPitch + range_x[0] * pixelSize;
+ var pixelPtr = new arrayType(this.m_data, offset + this.m_offset, width * numElements);
+
+ fillRow(pixelPtr, numElements, width);
+ fillPlanes(this.m_data, arrayType, pixelPtr, offset + this.m_offset, this.m_rowPitch, this.m_slicePitch, width * numElements, height, depth);
+};
+
+/**
+ * @param {number} depth to set
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ */
+tcuTexture.PixelBufferAccess.prototype.setPixDepth = function(depth, x, y, z) {
+ if (z == null)
+ z = 0;
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ x = Math.round(x);
+ y = Math.round(y);
+ z = Math.round(z);
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ var pn = function(val, offs, bits) {
+ return tcuTexture.normFloatToChannel(val, bits) << offs;
+ };
+
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ case tcuTexture.ChannelOrder.D: pixelPtr[pixelPtrOffset] = pn(depth, 8, 24); break;
+ case tcuTexture.ChannelOrder.DS: pixelPtr[pixelPtrOffset] = pn(depth, 8, 24) | (pixelPtr[pixelPtrOffset] & 0xFF); break;
+ default:
+ throw new Error('Unsupported tcuTexture.channel order ' + this.m_format.order);
+ }
+ break;
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ pixelPtr[pixelPtrOffset] = depth;
+ break;
+ }
+
+ default: {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.D || this.m_format.order == tcuTexture.ChannelOrder.DS);
+ pixelPtr[pixelPtrOffset] = tcuTexture.floatToChannel(depth, this.m_format.type);
+ }
+ }
+};
+
+/**
+ * @param {number} stencil to set
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} z
+ */
+tcuTexture.PixelBufferAccess.prototype.setPixStencil = function(stencil, x, y, z) {
+ if (z == null)
+ z = 0;
+ DE_ASSERT(deMath.deInBounds32(x, 0, this.m_width));
+ DE_ASSERT(deMath.deInBounds32(y, 0, this.m_height));
+ DE_ASSERT(deMath.deInBounds32(z, 0, this.m_depth));
+
+ // Make sure that the position is 'integer'
+ x = Math.round(x);
+ y = Math.round(y);
+ z = Math.round(z);
+
+ var pixelSize = this.m_format.getPixelSize();
+ var offset = z * this.m_slicePitch + y * this.m_rowPitch + x * pixelSize;
+ var pixelPtr = this.getDataPtr();
+ var pixelPtrOffset = offset / pixelPtr.BYTES_PER_ELEMENT;
+
+ var pu = function(val, offs, bits) {
+ return tcuTexture.uintToChannel(val, bits) << offs;
+ };
+
+ // Packed formats.
+ switch (this.m_format.type) {
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ switch (this.m_format.order) {
+ case tcuTexture.ChannelOrder.S: pixelPtr[pixelPtrOffset] = pu(stencil, 8, 24); break;
+ case tcuTexture.ChannelOrder.DS: pixelPtr[pixelPtrOffset] = pu(stencil, 0, 8) | (pixelPtr[pixelPtrOffset] & 0xFFFFFF00); break;
+ default:
+ throw new Error('Unsupported tcuTexture.channel order ' + this.m_format.order);
+ }
+ break;
+
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: {
+ var u32array = new Uint32Array(this.m_data, this.m_offset + offset + 4, 1);
+ u32array[0] = pu(stencil, 0, 8);
+ break;
+ }
+
+ default: {
+ if (this.m_format.order == tcuTexture.ChannelOrder.S)
+ pixelPtr[pixelPtrOffset] = tcuTexture.floatToChannel(stencil, this.m_format.type);
+ else {
+ DE_ASSERT(this.m_format.order == tcuTexture.ChannelOrder.DS);
+ pixelPtr[3 + pixelPtrOffset] = tcuTexture.floatToChannel(stencil, this.m_format.type);
+ }
+ }
+ }
+};
+
+/**
+ * newFromTextureLevel
+ * @param {tcuTexture.TextureLevel} level
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+tcuTexture.PixelBufferAccess.newFromTextureLevel = function(level) {
+ var descriptor = new Object();
+ descriptor.format = level.getFormat();
+ descriptor.width = level.getWidth();
+ descriptor.height = level.getHeight();
+ descriptor.depth = level.m_depth;
+ descriptor.data = level.m_data.m_ptr;
+
+ return new tcuTexture.PixelBufferAccess(descriptor);
+};
+
+/**
+ * newFromTextureFormat
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} rowPitch
+ * @param {number} slicePitch
+ * @param {ArrayBuffer} data
+ */
+tcuTexture.PixelBufferAccess.newFromTextureFormat = function(format, width, height, depth, rowPitch, slicePitch, data) {
+ var descriptor = new Object();
+ descriptor.format = format;
+ descriptor.width = width;
+ descriptor.height = height;
+ descriptor.depth = depth;
+ descriptor.rowPitch = rowPitch;
+ descriptor.slicePitch = slicePitch;
+ descriptor.data = data;
+
+ return new tcuTexture.PixelBufferAccess(descriptor);
+};
+
+/* TODO: Port */
+// {
+// public:
+// tcuTexture.PixelBufferAccess (void) {}
+// tcuTexture.PixelBufferAccess (const tcuTexture.TextureFormat& format, int width, int height, int depth, void* data);
+
+// void* getDataPtr (void) const { return m_data; }
+
+// void setPixels (const void* buf, int bufSize) const;
+// void setPixel (const tcu::Vec4& color, int x, int y, int z = 0) const;
+// void setPixel (const tcu::IVec4& color, int x, int y, int z = 0) const;
+// void setPixel (const tcu::UVec4& color, int x, int y, int z = 0) const { setPixel(color.cast<int>(), x, y, z); }
+
+// void setPixDepth (float depth, int x, int y, int z = 0) const;
+// void setPixStencil (int stencil, int x, int y, int z = 0) const;
+// };
+
+/**
+ * @constructor
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} numLevels
+ */
+tcuTexture.TextureLevelPyramid = function(format, numLevels) {
+ /* tcuTexture.TextureFormat */this.m_format = format;
+ /* LevelData */ this.m_data = [];
+ for (var i = 0; i < numLevels; i++)
+ this.m_data.push(new tcuTexture.DeqpArrayBuffer());
+ /* {Array<tcuTexture.PixelBufferAccess>} */ this.m_access = [];
+ this.m_access.length = numLevels;
+};
+
+/** @return {boolean} */
+tcuTexture.TextureLevelPyramid.prototype.isLevelEmpty = function(levelNdx) { return this.m_data[levelNdx].empty(); };
+/** @return {tcuTexture.TextureFormat} */
+tcuTexture.TextureLevelPyramid.prototype.getFormat = function() { return this.m_format; };
+/** @return {number} */
+tcuTexture.TextureLevelPyramid.prototype.getNumLevels = function() { return this.m_access.length; };
+/** @return {tcuTexture.PixelBufferAccess} */
+tcuTexture.TextureLevelPyramid.prototype.getLevel = function(ndx) { return this.m_access[ndx]; };
+/** @return {Array<tcuTexture.PixelBufferAccess>} */
+tcuTexture.TextureLevelPyramid.prototype.getLevels = function() { return this.m_access; };
+
+/**
+ * @param {number} levelNdx
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+tcuTexture.TextureLevelPyramid.prototype.allocLevel = function(levelNdx, width, height, depth) {
+ var size = this.m_format.getPixelSize() * width * height * depth;
+
+ DE_ASSERT(this.isLevelEmpty(levelNdx));
+
+ this.m_data[levelNdx].setStorage(size);
+ this.m_access[levelNdx] = new tcuTexture.PixelBufferAccess({
+ format: this.m_format,
+ width: width,
+ height: height,
+ depth: depth,
+ data: this.m_data[levelNdx].m_ptr
+ });
+};
+
+tcuTexture.TextureLevelPyramid.prototype.clearLevel = function(levelNdx) {
+ /* TODO: Implement */
+ throw new Error('Not implemented');
+};
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ * @param {number} numLevels
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} s
+ * @param {number} t
+ * @param {number} depth (integer)
+ * @param {number=} lod
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.sampleLevelArray2D = function(levels, numLevels, sampler, s, t, depth, lod) {
+ // z-offset in 2D textures is layer selector
+ return tcuTexture.sampleLevelArray2DOffset(levels, numLevels, sampler, [s, t], lod, [0, 0, depth]);
+};
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ * @param {number} numLevels
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @return {Array<number>} Vec4 pixel color
+ */
+tcuTexture.sampleLevelArray3D = function(levels, numLevels, sampler, s, t, r, lod) {
+ return tcuTexture.sampleLevelArray3DOffset(levels, numLevels, sampler, s, t, r, lod, [0, 0, 0]);
+};
+
+/**
+ * @constructor
+ * @param {tcuTexture.CubeFace} face
+ * @param {Array<number>} coords
+ */
+tcuTexture.CubeFaceCoords = function(face, coords) {
+ this.face = face;
+ this.s = coords[0];
+ this.t = coords[1];
+};
+
+/**
+ * \brief 2D Texture View
+ * @constructor
+ * @param {number} numLevels
+ * @param {?Array<tcuTexture.ConstPixelBufferAccess>} levels
+ */
+tcuTexture.Texture2DView = function(numLevels, levels) {
+ this.m_numLevels = numLevels;
+ this.m_levels = levels;
+};
+
+/** @return {number} */
+tcuTexture.Texture2DView.prototype.getNumLevels = function() { return this.m_numLevels; };
+/** @return {number} */
+tcuTexture.Texture2DView.prototype.getWidth = function() { return this.m_numLevels > 0 ? this.m_levels[0].getWidth() : 0; };
+/** @return {number} */
+tcuTexture.Texture2DView.prototype.getHeight = function() { return this.m_numLevels > 0 ? this.m_levels[0].getHeight() : 0; };
+/**
+ * @param {number} ndx
+ * @return {tcuTexture.ConstPixelBufferAccess}
+ */
+tcuTexture.Texture2DView.prototype.getLevel = function(ndx) { DE_ASSERT(deMath.deInBounds32(ndx, 0, this.m_numLevels)); return this.m_levels[ndx]; };
+/** @return {Array<tcuTexture.ConstPixelBufferAccess>} */
+tcuTexture.Texture2DView.prototype.getLevels = function() { return this.m_levels; };
+
+/**
+ * @param {number} baseLevel
+ * @param {number} maxLevel
+ * return {tcuTexture.Texture2DView}
+ */
+tcuTexture.Texture2DView.prototype.getSubView = function(baseLevel, maxLevel) {
+ var clampedBase = deMath.clamp(baseLevel, 0, this.m_numLevels - 1);
+ var clampedMax = deMath.clamp(maxLevel, clampedBase, this.m_numLevels - 1);
+ var numLevels = clampedMax - clampedBase + 1;
+ return new tcuTexture.Texture2DView(numLevels, this.m_levels.slice(clampedBase, numLevels));
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number=} lod
+ * @return {Array<number>} Pixel color
+ */
+tcuTexture.Texture2DView.prototype.sample = function(sampler, texCoord, lod) {
+ return tcuTexture.sampleLevelArray2D(this.m_levels, this.m_numLevels, sampler, texCoord[0], texCoord[1], 0 /* depth */, lod);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>} Pixel color
+ */
+tcuTexture.Texture2DView.prototype.sampleOffset = function(sampler, texCoord, lod, offset) {
+ return tcuTexture.sampleLevelArray2DOffset(this.m_levels, this.m_numLevels, sampler, texCoord, lod, [offset[0], offset[1], 0]);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @return {number}
+ */
+tcuTexture.Texture2DView.prototype.sampleCompare = function(sampler, ref, texCoord, lod) {
+ return tcuTexture.sampleLevelArray2DCompare(this.m_levels, this.m_numLevels, sampler, ref, texCoord[0], texCoord[1], lod, [0, 0, 0]);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {number}
+ */
+tcuTexture.Texture2DView.prototype.sampleCompareOffset = function(sampler, ref, texCoord, lod, offset) {
+ return tcuTexture.sampleLevelArray2DCompare(this.m_levels, this.m_numLevels, sampler, ref, texCoord[0], texCoord[1], lod, [offset[0], offset[1], 0]);
+};
+
+ /* TODO: Port
+ Vec4 sample (const tcuTexture.Sampler& sampler, float s, float t, float lod) const;
+ Vec4 sampleOffset (const tcuTexture.Sampler& sampler, float s, float t, float lod, const IVec2& offset) const;
+ float sampleCompare (const tcuTexture.Sampler& sampler, float ref, float s, float t, float lod) const;
+ float sampleCompareOffset (const tcuTexture.Sampler& sampler, float ref, float s, float t, float lod, const IVec2& offset) const;
+
+ Vec4 gatherOffsets (const tcuTexture.Sampler& sampler, float s, float t, int componentNdx, const IVec2 (&offsets)[4]) const;
+ Vec4 gatherOffsetsCompare(const tcuTexture.Sampler& sampler, float ref, float s, float t, const IVec2 (&offsets)[4]) const;
+ */
+
+/**
+ * @constructor
+ * @param {number} numLevels
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ */
+tcuTexture.Texture2DArrayView = function(numLevels, levels) {
+ this.m_numLevels = numLevels;
+ this.m_levels = levels;
+};
+
+/** @return {number} */
+tcuTexture.Texture2DArrayView.prototype.getNumLevels = function() { return this.m_numLevels; };
+/** @return {number} */
+tcuTexture.Texture2DArrayView.prototype.getWidth = function() { return this.m_numLevels > 0 ? this.m_levels[0].getWidth() : 0; };
+/** @return {number} */
+tcuTexture.Texture2DArrayView.prototype.getHeight = function() { return this.m_numLevels > 0 ? this.m_levels[0].getHeight() : 0; };
+/** @return {number} */
+tcuTexture.Texture2DArrayView.prototype.getNumLayers = function() { return this.m_numLevels > 0 ? this.m_levels[0].getDepth() : 0; };
+/**
+ * @param {number} ndx
+ * @return {tcuTexture.ConstPixelBufferAccess}
+ */
+tcuTexture.Texture2DArrayView.prototype.getLevel = function(ndx) { DE_ASSERT(deMath.deInBounds32(ndx, 0, this.m_numLevels)); return this.m_levels[ndx]; };
+/** @return {Array<tcuTexture.ConstPixelBufferAccess>} */
+tcuTexture.Texture2DArrayView.prototype.getLevels = function() { return this.m_levels; };
+
+/**
+ * @param {number} r
+ * @return {number} layer corresponding to requested sampling 'r' coordinate
+ */
+tcuTexture.Texture2DArrayView.prototype.selectLayer = function(r) {
+ DE_ASSERT(this.m_numLevels > 0 && this.m_levels);
+ return deMath.clamp(Math.round(r), 0, this.m_levels[0].getDepth() - 1);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number=} lod
+ * @return {Array<number>} Pixel color
+ */
+tcuTexture.Texture2DArrayView.prototype.sample = function(sampler, texCoord, lod) {
+ lod = lod || 0;
+ return tcuTexture.sampleLevelArray2D(this.m_levels, this.m_numLevels, sampler, texCoord[0], texCoord[1], this.selectLayer(texCoord[2]), lod);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+tcuTexture.Texture2DArrayView.prototype.sampleOffset = function(sampler, texCoord, lod, offset) {
+ return tcuTexture.sampleLevelArray2DOffset(this.m_levels, this.m_numLevels, sampler, texCoord, lod, [offset[0], offset[1], this.selectLayer(texCoord[2])]);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {number}
+ */
+tcuTexture.Texture2DArrayView.prototype.sampleCompareOffset = function(sampler, ref, texCoord, lod, offset) {
+ return tcuTexture.sampleLevelArray2DCompare(this.m_levels, this.m_numLevels, sampler, ref, texCoord[0], texCoord[1], lod, [offset[0], offset[1], this.selectLayer(texCoord[2])]);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @return {number}
+ */
+tcuTexture.Texture2DArrayView.prototype.sampleCompare = function(sampler, ref, texCoord, lod) {
+ return tcuTexture.sampleLevelArray2DCompare(this.m_levels, this.m_numLevels, sampler, ref, texCoord[0], texCoord[1], lod, [0, 0, this.selectLayer(texCoord[2])]);
+};
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ * @param {number} numLevels
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+tcuTexture.sampleLevelArray2DOffset = function(levels, numLevels, sampler, texCoord, lod, offset) {
+ /** @type {boolean} */ var magnified = lod <= sampler.lodThreshold;
+ /** @type {tcuTexture.FilterMode} */ var filterMode = magnified ? sampler.magFilter : sampler.minFilter;
+ /** @type {number} */ var maxLevel;
+ /** @type {tcuTexture.FilterMode} */ var levelFilter;
+ switch (filterMode) {
+ case tcuTexture.FilterMode.NEAREST: return levels[0].sample2DOffset(sampler, filterMode, texCoord[0], texCoord[1], offset);
+ case tcuTexture.FilterMode.LINEAR: return levels[0].sample2DOffset(sampler, filterMode, texCoord[0], texCoord[1], offset);
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST:
+ maxLevel = numLevels - 1;
+ /** @type {number} */ var level = deMath.clamp(Math.ceil(lod + 0.5) - 1, 0, maxLevel);
+ levelFilter = (filterMode === tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+
+ return levels[level].sample2DOffset(sampler, levelFilter, texCoord[0], texCoord[1], offset);
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR:
+ maxLevel = numLevels - 1;
+ /** @type {number} */ var level0 = deMath.clamp(Math.floor(lod), 0, maxLevel);
+ /** @type {number} */ var level1 = Math.min(maxLevel, level0 + 1);
+ levelFilter = (filterMode === tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ /** @type {number} */ var f = deMath.deFloatFrac(lod);
+ /** @type {Array<number>} */ var t0 = levels[level0].sample2DOffset(sampler, levelFilter, texCoord[0], texCoord[1], offset);
+ /** @type {Array<number>} */ var t1 = levels[level1].sample2DOffset(sampler, levelFilter, texCoord[0], texCoord[1], offset);
+
+ return deMath.add(deMath.scale(t0, (1.0 - f)), deMath.scale(t1, f));
+
+ default:
+ return [0.0, 0.0, 0.0, 0.0];
+ }
+};
+
+/**
+ * @constructor
+ * @param {number} numLevels
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ */
+tcuTexture.Texture3DView = function(numLevels, levels) {
+ this.m_numLevels = numLevels;
+ this.m_levels = levels;
+};
+
+/** @return {number} */
+tcuTexture.Texture3DView.prototype.getNumLevels = function() { return this.m_numLevels; };
+/** @return {number} */
+tcuTexture.Texture3DView.prototype.getWidth = function() { return this.m_numLevels > 0 ? this.m_levels[0].getWidth() : 0; };
+/** @return {number} */
+tcuTexture.Texture3DView.prototype.getHeight = function() { return this.m_numLevels > 0 ? this.m_levels[0].getHeight() : 0; };
+/** @return {number} */
+tcuTexture.Texture3DView.prototype.getDepth = function() { return this.m_numLevels > 0 ? this.m_levels[0].getDepth() : 0; };
+/**
+ * @param {number} ndx
+ * @return {tcuTexture.ConstPixelBufferAccess}
+ */
+tcuTexture.Texture3DView.prototype.getLevel = function(ndx) { DE_ASSERT(deMath.deInBounds32(ndx, 0, this.m_numLevels)); return this.m_levels[ndx]; };
+/** @return {Array<tcuTexture.ConstPixelBufferAccess>} */
+tcuTexture.Texture3DView.prototype.getLevels = function() { return this.m_levels; };
+
+/**
+ * @param {number} baseLevel
+ * @param {number} maxLevel
+ * return {tcuTexture.Texture3DView}
+ */
+tcuTexture.Texture3DView.prototype.getSubView = function(baseLevel, maxLevel) {
+ var clampedBase = deMath.clamp(baseLevel, 0, this.m_numLevels - 1);
+ var clampedMax = deMath.clamp(maxLevel, clampedBase, this.m_numLevels - 1);
+ var numLevels = clampedMax - clampedBase + 1;
+ return new tcuTexture.Texture3DView(numLevels, this.m_levels.slice(clampedBase, numLevels));
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number=} lod
+ * @return {Array<number>} Pixel color
+ */
+tcuTexture.Texture3DView.prototype.sample = function(sampler, texCoord, lod) {
+ lod = lod || 0;
+ return tcuTexture.sampleLevelArray3D(this.m_levels, this.m_numLevels, sampler, texCoord[0], texCoord[1], texCoord[2], lod);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @return {number}
+ */
+tcuTexture.Texture3DView.prototype.sampleCompare = function(sampler, ref, texCoord, lod) {
+ throw new Error('Unimplemented');
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+tcuTexture.Texture3DView.prototype.sampleOffset = function(sampler, texCoord, lod, offset) {
+ return tcuTexture.sampleLevelArray3DOffset(this.m_levels, this.m_numLevels, sampler, texCoord[0], texCoord[1], texCoord[2], lod, offset);
+};
+
+/* TODO: All view classes are very similar. They should have a common base class */
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} levels
+ * @param {number} numLevels
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+tcuTexture.sampleLevelArray3DOffset = function(levels, numLevels, sampler, s, t, r, lod, offset) {
+ /** @type {boolean} */ var magnified = lod <= sampler.lodThreshold;
+ /** @type {tcuTexture.FilterMode} */ var filterMode = magnified ? sampler.magFilter : sampler.minFilter;
+ /** @type {number} */ var maxLevel;
+ /** @type {tcuTexture.FilterMode} */ var levelFilter;
+ switch (filterMode) {
+ case tcuTexture.FilterMode.NEAREST: return levels[0].sample3DOffset(sampler, filterMode, s, t, r, offset);
+ case tcuTexture.FilterMode.LINEAR: return levels[0].sample3DOffset(sampler, filterMode, s, t, r, offset);
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST:
+ maxLevel = numLevels - 1;
+ /** @type {number} */ var level = deMath.clamp(Math.ceil(lod + 0.5) - 1, 0, maxLevel);
+ levelFilter = (filterMode === tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+
+ return levels[level].sample3DOffset(sampler, levelFilter, s, t, r, offset);
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR:
+ maxLevel = numLevels - 1;
+ /** @type {number} */ var level0 = deMath.clamp(Math.floor(lod), 0, maxLevel);
+ /** @type {number} */ var level1 = Math.min(maxLevel, level0 + 1);
+ levelFilter = (filterMode === tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ /** @type {number} */ var f = deMath.deFloatFrac(lod);
+ /** @type {Array<number>} */ var t0 = levels[level0].sample3DOffset(sampler, levelFilter, s, t, r, offset);
+ /** @type {Array<number>} */ var t1 = levels[level1].sample3DOffset(sampler, levelFilter, s, t, r, offset);
+
+ return deMath.add(deMath.scale(t0, (1.0 - f)), deMath.scale(t1, f));
+
+ default:
+ throw new Error('Filter mode not supported');
+ }
+};
+
+/**
+ * @param {number} width
+ * @param {number=} height
+ * @param {number=} depth
+ * @return {number} Number of pyramid levels
+ */
+tcuTexture.computeMipPyramidLevels = function(width, height, depth) {
+ if (depth !== undefined)
+ return Math.floor(Math.log2(Math.max(width, Math.max(height, depth)))) + 1;
+ else if (height !== undefined)
+ return Math.floor(Math.log2(Math.max(width, height))) + 1;
+ else
+ return Math.floor(Math.log2(width)) + 1;
+};
+
+/**
+ * @param {number} baseLevelSize
+ * @param {number} levelNdx
+ */
+tcuTexture.getMipPyramidLevelSize = function(baseLevelSize, levelNdx) {
+ return Math.max(baseLevelSize >> levelNdx, 1);
+};
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faceAccesses
+ * @param {tcuTexture.CubeFace} baseFace
+ * @param {number} u
+ * @param {number} v
+ * @param {number} depth
+ * @return {Array<Array<number>>}
+ */
+tcuTexture.getCubeLinearSamples = function(faceAccesses, baseFace, u, v, depth) {
+ DE_ASSERT(faceAccesses[0].getWidth() == faceAccesses[0].getHeight());
+ /** @type {Array<Array<number>>} */ var dst = [];
+ var size = faceAccesses[0].getWidth();
+ var x0 = Math.floor(u - 0.5);
+ var x1 = x0 + 1;
+ var y0 = Math.floor(v - 0.5);
+ var y1 = y0 + 1;
+ var baseSampleCoords =
+ [
+ [x0, y0],
+ [x1, y0],
+ [x0, y1],
+ [x1, y1]
+ ];
+ /** @type {Array<Array<number>>} */ var sampleColors = [];
+ /** @type {Array<boolean>} */ var hasBothCoordsOutOfBounds = []; //!< Whether correctCubeFace() returns CUBEFACE_LAST, i.e. both u and v are out of bounds.
+
+ // Find correct faces and coordinates for out-of-bounds sample coordinates.
+
+ for (var i = 0; i < 4; i++) {
+ /** @type {tcuTexture.CubeFaceCoords} */ var coords = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(baseFace, baseSampleCoords[i]), size);
+ hasBothCoordsOutOfBounds[i] = coords == null;
+ if (!hasBothCoordsOutOfBounds[i])
+ sampleColors[i] = tcuTexture.lookup(faceAccesses[coords.face], coords.s, coords.t, depth);
+ }
+
+ // If a sample was out of bounds in both u and v, we get its color from the average of the three other samples.
+ // \note This averaging behavior is not required by the GLES3 spec (though it is recommended). GLES3 spec only
+ // requires that if the three other samples all have the same color, then the doubly-out-of-bounds sample
+ // must have this color as well.
+
+ var bothOutOfBoundsNdx = -1;
+ for (var i = 0; i < 4; i++) {
+ if (hasBothCoordsOutOfBounds[i]) {
+ DE_ASSERT(bothOutOfBoundsNdx < 0); // Only one sample can be out of bounds in both u and v.
+ bothOutOfBoundsNdx = i;
+ }
+ }
+ if (bothOutOfBoundsNdx != -1) {
+ sampleColors[bothOutOfBoundsNdx] = [0, 0, 0, 0];
+ for (var i = 0; i < 4; i++)
+ if (i != bothOutOfBoundsNdx)
+ sampleColors[bothOutOfBoundsNdx] = deMath.add(sampleColors[bothOutOfBoundsNdx], sampleColors[i]);
+
+ sampleColors[bothOutOfBoundsNdx] = deMath.scale(sampleColors[bothOutOfBoundsNdx], (1.0 / 3.0));
+ }
+
+ for (var i = 0; i < sampleColors.length; i++)
+ dst[i] = sampleColors[i];
+
+ return dst;
+};
+
+// \todo [2014-02-19 pyry] Optimize faceAccesses
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faceAccesses
+ * @param {tcuTexture.CubeFace} baseFace
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} s
+ * @param {number} t
+ * @param {number} depth
+ * @return {Array<number>}
+ */
+tcuTexture.sampleCubeSeamlessLinear = function(faceAccesses, baseFace, sampler, s, t, depth) {
+ DE_ASSERT(faceAccesses[0].getWidth() == faceAccesses[0].getHeight());
+
+ var size = faceAccesses[0].getWidth();
+ // Non-normalized coordinates.
+ var u = s;
+ var v = t;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, size);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, size);
+ }
+
+ // Get sample colors.
+
+ /** @type {Array<Array<number>>} */ var sampleColors = tcuTexture.getCubeLinearSamples(faceAccesses, baseFace, u, v, depth);
+
+ // Interpolate.
+
+ var a = deMath.deFloatFrac(u - 0.5);
+ var b = deMath.deFloatFrac(v - 0.5);
+
+ return deMath.add((deMath.scale(deMath.scale(sampleColors[0], (1.0 - a)), (1.0 - b))),
+ deMath.add((deMath.scale(deMath.scale(sampleColors[1], (a)), (1.0 - b))),
+ deMath.add((deMath.scale(deMath.scale(sampleColors[2], (1.0 - a)), (b))),
+ (deMath.scale(deMath.scale(sampleColors[3], (a)), (b))))));
+};
+
+/**
+ * @param {Array<Array<tcuTexture.ConstPixelBufferAccess>>} faces
+ * @param {number} numLevels
+ * @param {tcuTexture.CubeFace} face
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} s
+ * @param {number} t
+ * @param {number} depth
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+tcuTexture.sampleLevelArrayCubeSeamless = function(faces, numLevels, face, sampler, s, t, depth, lod) {
+ lod = lod || 0;
+ var magnified = lod <= sampler.lodThreshold;
+ /** @type {tcuTexture.FilterMode} */ var filterMode = magnified ? sampler.magFilter : sampler.minFilter;
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faceAccesses = [];
+ /** @type {tcuTexture.FilterMode}*/ var levelFilter;
+
+ switch (filterMode) {
+ case tcuTexture.FilterMode.NEAREST:
+ return tcuTexture.sampleCubeSeamlessNearest(faces[face][0], sampler, s, t, depth);
+
+ case tcuTexture.FilterMode.LINEAR: {
+ faceAccesses = [];
+ for (var i = 0; i < Object.keys(tcuTexture.CubeFace).length; i++)
+ faceAccesses[i] = faces[i][0];
+
+ return tcuTexture.sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, depth);
+ }
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST: {
+ var maxLevel = numLevels - 1;
+ var level = deMath.clamp(Math.ceil(lod + 0.5) - 1, 0, maxLevel);
+ levelFilter = (filterMode == tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+
+ if (levelFilter == tcuTexture.FilterMode.NEAREST)
+ return tcuTexture.sampleCubeSeamlessNearest(faces[face][level], sampler, s, t, depth);
+ else {
+ DE_ASSERT(levelFilter == tcuTexture.FilterMode.LINEAR);
+
+ faceAccesses = [];
+ for (var i = 0; i < Object.keys(tcuTexture.CubeFace).length; i++)
+ faceAccesses[i] = faces[i][level];
+
+ return tcuTexture.sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, depth);
+ }
+ }
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR: {
+ var maxLevel = numLevels - 1;
+ var level0 = deMath.clamp(Math.floor(lod), 0, maxLevel);
+ var level1 = Math.min(maxLevel, level0 + 1);
+ levelFilter = (filterMode == tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ var f = deMath.deFloatFrac(lod);
+ var t0 = [];
+ var t1 = [];
+
+ if (levelFilter == tcuTexture.FilterMode.NEAREST) {
+ t0 = tcuTexture.sampleCubeSeamlessNearest(faces[face][level0], sampler, s, t, depth);
+ t1 = tcuTexture.sampleCubeSeamlessNearest(faces[face][level1], sampler, s, t, depth);
+ } else {
+ DE_ASSERT(levelFilter == tcuTexture.FilterMode.LINEAR);
+
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>}*/ var faceAccesses0 = [];
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>}*/ var faceAccesses1 = [];
+ for (var i = 0; i < Object.keys(tcuTexture.CubeFace).length; i++) {
+ faceAccesses0[i] = faces[i][level0];
+ faceAccesses1[i] = faces[i][level1];
+ }
+
+ t0 = tcuTexture.sampleCubeSeamlessLinear(faceAccesses0, face, sampler, s, t, depth);
+ t1 = tcuTexture.sampleCubeSeamlessLinear(faceAccesses1, face, sampler, s, t, depth);
+ }
+
+ return deMath.add(deMath.scale(t0, (1.0 - f)), deMath.scale(t1, f));
+ }
+
+ default:
+ throw new Error('Unsupported filter mode');
+ }
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} faceAccess
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number=} depth
+ * @return {number}
+ */
+tcuTexture.sampleCubeSeamlessNearestCompare = function(faceAccess, sampler, ref, s, t, depth) {
+ depth = depth ? depth : 0;
+ /** @type {tcuTexture.Sampler} */ var clampingSampler = deUtil.clone(sampler);
+ clampingSampler.wrapS = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ clampingSampler.wrapT = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ return faceAccess.sample2DCompare(clampingSampler, tcuTexture.FilterMode.NEAREST, ref, s, t, [0, 0, depth]);
+};
+
+/**
+ * @param {Array<tcuTexture.ConstPixelBufferAccess>} faceAccesses
+ * @param {tcuTexture.CubeFace} baseFace
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @return {number}
+ */
+tcuTexture.sampleCubeSeamlessLinearCompare = function(faceAccesses, baseFace, sampler, ref, s, t) {
+ DE_ASSERT(faceAccesses[0].getWidth() == faceAccesses[0].getHeight());
+
+ var size = faceAccesses[0].getWidth();
+ // Non-normalized coordinates.
+ var u = s;
+ var v = t;
+
+ if (sampler.normalizedCoords) {
+ u = tcuTexture.unnormalize(sampler.wrapS, s, size);
+ v = tcuTexture.unnormalize(sampler.wrapT, t, size);
+ }
+
+ var x0 = Math.floor(u - 0.5);
+ var x1 = x0 + 1;
+ var y0 = Math.floor(v - 0.5);
+ var y1 = y0 + 1;
+ var baseSampleCoords = [
+ [x0, y0],
+ [x1, y0],
+ [x0, y1],
+ [x1, y1]
+ ];
+ var sampleRes = [];
+ var hasBothCoordsOutOfBounds = []; //!< Whether correctCubeFace() returns CUBEFACE_LAST, i.e. both u and v are out of bounds.
+
+ // Find correct faces and coordinates for out-of-bounds sample coordinates.
+
+ for (var i = 0; i < 4; i++) {
+ /** @type {tcuTexture.CubeFaceCoords} */ var coords = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(baseFace, baseSampleCoords[i]), size);
+ hasBothCoordsOutOfBounds[i] = coords == null;
+
+ if (!hasBothCoordsOutOfBounds[i]) {
+ var isFixedPointDepth = tcuTexture.isFixedPointDepthTextureFormat(faceAccesses[coords.face].getFormat());
+
+ sampleRes[i] = tcuTexture.execCompare(faceAccesses[coords.face].getPixel(coords.s, coords.t), sampler.compare, sampler.compareChannel, ref, isFixedPointDepth);
+ }
+ }
+
+ // If a sample was out of bounds in both u and v, we get its color from the average of the three other samples.
+ // \note This averaging behavior is not required by the GLES3 spec (though it is recommended). GLES3 spec only
+ // requires that if the three other samples all have the same color, then the doubly-out-of-bounds sample
+ // must have this color as well.
+
+ var bothOutOfBoundsNdx = -1;
+ for (var i = 0; i < 4; i++) {
+ if (hasBothCoordsOutOfBounds[i]) {
+ DE_ASSERT(bothOutOfBoundsNdx < 0); // Only one sample can be out of bounds in both u and v.
+ bothOutOfBoundsNdx = i;
+ }
+ }
+ if (bothOutOfBoundsNdx != -1) {
+ sampleRes[bothOutOfBoundsNdx] = 0.0;
+ for (var i = 0; i < 4; i++)
+ if (i != bothOutOfBoundsNdx)
+ sampleRes[bothOutOfBoundsNdx] += sampleRes[i];
+
+ sampleRes[bothOutOfBoundsNdx] = sampleRes[bothOutOfBoundsNdx] * (1.0 / 3.0);
+ }
+
+ // Interpolate.
+
+ var a = deMath.deFloatFrac(u - 0.5);
+ var b = deMath.deFloatFrac(v - 0.5);
+
+ return (sampleRes[0] * (1.0 - a) * (1.0 - b)) +
+ (sampleRes[1] * (a) * (1.0 - b)) +
+ (sampleRes[2] * (1.0 - a) * (b)) +
+ (sampleRes[3] * (a) * (b));
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} faceAccess
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} s
+ * @param {number} t
+ * @param {number} depth
+ * @return {Array<number>}
+ */
+tcuTexture.sampleCubeSeamlessNearest = function(faceAccess, sampler, s, t, depth) {
+ /** @type {tcuTexture.Sampler} */ var clampingSampler = sampler;
+ clampingSampler.wrapS = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ clampingSampler.wrapT = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ return faceAccess.sample2D(clampingSampler, tcuTexture.FilterMode.NEAREST, s, t, depth);
+};
+
+/**
+ * @param {Array<number>} coords Vec3 cube coordinates
+ * @return {tcuTexture.CubeFaceCoords}
+ */
+tcuTexture.getCubeFaceCoords = function(coords) {
+ var face = tcuTexture.selectCubeFace(coords);
+ return new tcuTexture.CubeFaceCoords(face, tcuTexture.projectToFace(face, coords));
+};
+
+/**
+ * @param {Array<Array<tcuTexture.ConstPixelBufferAccess>>} faces
+ * @param {number} numLevels
+ * @param {tcuTexture.CubeFace} face
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} lod
+ * @return {number}
+ */
+tcuTexture.sampleLevelArrayCubeSeamlessCompare = function(faces, numLevels, face, sampler, ref, s, t, lod) {
+ var magnified = lod <= sampler.lodThreshold;
+ /** @type {tcuTexture.FilterMode}*/ var filterMode = magnified ? sampler.magFilter : sampler.minFilter;
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faceAccesses = [];
+ /** @type {tcuTexture.FilterMode} */ var levelFilter;
+
+ switch (filterMode) {
+ case tcuTexture.FilterMode.NEAREST:
+ return tcuTexture.sampleCubeSeamlessNearestCompare(faces[face][0], sampler, ref, s, t);
+
+ case tcuTexture.FilterMode.LINEAR: {
+ faceAccesses = [];
+ for (var i = 0; i < Object.keys(tcuTexture.CubeFace).length; i++)
+ faceAccesses[i] = faces[i][0];
+
+ return tcuTexture.sampleCubeSeamlessLinearCompare(faceAccesses, face, sampler, ref, s, t);
+ }
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST: {
+ var maxLevel = numLevels - 1;
+ var level = deMath.clamp(Math.ceil(lod + 0.5) - 1, 0, maxLevel);
+ levelFilter = filterMode == tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+
+ if (levelFilter == tcuTexture.FilterMode.NEAREST)
+ return tcuTexture.sampleCubeSeamlessNearestCompare(faces[face][level], sampler, ref, s, t);
+ else {
+ DE_ASSERT(levelFilter == tcuTexture.FilterMode.LINEAR);
+
+ faceAccesses = [];
+ for (var i = 0; i < Object.keys(tcuTexture.CubeFace).length; i++)
+ faceAccesses[i] = faces[i][level];
+
+ return tcuTexture.sampleCubeSeamlessLinearCompare(faceAccesses, face, sampler, ref, s, t);
+ }
+ }
+
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR:
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR: {
+ var maxLevel = numLevels - 1;
+ var level0 = deMath.clamp(Math.floor(lod), 0, maxLevel);
+ var level1 = Math.min(maxLevel, level0 + 1);
+ levelFilter = (filterMode == tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ var f = deMath.deFloatFrac(lod);
+ var t0;
+ var t1;
+
+ if (levelFilter == tcuTexture.FilterMode.NEAREST) {
+ t0 = tcuTexture.sampleCubeSeamlessNearestCompare(faces[face][level0], sampler, ref, s, t);
+ t1 = tcuTexture.sampleCubeSeamlessNearestCompare(faces[face][level1], sampler, ref, s, t);
+ } else {
+ DE_ASSERT(levelFilter == tcuTexture.FilterMode.LINEAR);
+
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faceAccesses0 = [];
+ /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faceAccesses1 = [];
+ for (var i = 0; i < Object.keys(tcuTexture.CubeFace).length; i++) {
+ faceAccesses0[i] = faces[i][level0];
+ faceAccesses1[i] = faces[i][level1];
+ }
+
+ t0 = tcuTexture.sampleCubeSeamlessLinearCompare(faceAccesses0, face, sampler, ref, s, t);
+ t1 = tcuTexture.sampleCubeSeamlessLinearCompare(faceAccesses1, face, sampler, ref, s, t);
+ }
+
+ return t0 * (1.0 - f) + t1 * f;
+ }
+
+ default:
+ throw new Error('Unsupported filter mode');
+ }
+};
+
+/**
+ * @constructor
+ * @extends {tcuTexture.TextureLevelPyramid}
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ */
+tcuTexture.Texture2D = function(format, width, height) {
+ tcuTexture.TextureLevelPyramid.call(this, format, tcuTexture.computeMipPyramidLevels(width, height));
+ this.m_width = width;
+ this.m_height = height;
+ this.m_view = new tcuTexture.Texture2DView(this.getNumLevels(), this.getLevels());
+};
+
+tcuTexture.Texture2D.prototype = Object.create(tcuTexture.TextureLevelPyramid.prototype);
+tcuTexture.Texture2D.prototype.constructor = tcuTexture.Texture2D;
+
+tcuTexture.Texture2D.prototype.getWidth = function() { return this.m_width; };
+tcuTexture.Texture2D.prototype.getHeight = function() { return this.m_height; };
+/** @return {tcuTexture.Texture2DView} */
+tcuTexture.Texture2D.prototype.getView = function() { return this.m_view; };
+
+/**
+ * @param {number} baseLevel
+ * @param {number} maxLevel
+ * @return {tcuTexture.Texture2DView}
+ */
+tcuTexture.Texture2D.prototype.getSubView = function(baseLevel, maxLevel) { return this.m_view.getSubView(baseLevel, maxLevel); };
+
+/**
+ * @param {number} levelNdx
+ */
+tcuTexture.Texture2D.prototype.allocLevel = function(levelNdx) {
+ DE_ASSERT(deMath.deInBounds32(levelNdx, 0, this.getNumLevels()));
+
+ var width = tcuTexture.getMipPyramidLevelSize(this.m_width, levelNdx);
+ var height = tcuTexture.getMipPyramidLevelSize(this.m_height, levelNdx);
+
+ tcuTexture.TextureLevelPyramid.prototype.allocLevel.call(this, levelNdx, width, height, 1);
+};
+
+/**
+ * @constructor
+ * @extends {tcuTexture.TextureLevelPyramid}
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ */
+tcuTexture.Texture2DArray = function(format, width, height, numLayers) {
+ tcuTexture.TextureLevelPyramid.call(this, format, tcuTexture.computeMipPyramidLevels(width, height));
+ this.m_width = width;
+ this.m_height = height;
+ this.m_numLayers = numLayers;
+ this.m_view = new tcuTexture.Texture2DArrayView(this.getNumLevels(), this.getLevels());
+};
+
+tcuTexture.Texture2DArray.prototype = Object.create(tcuTexture.TextureLevelPyramid.prototype);
+tcuTexture.Texture2DArray.prototype.constructor = tcuTexture.Texture2DArray;
+/** @return {tcuTexture.Texture2DArrayView} */
+tcuTexture.Texture2DArray.prototype.getView = function() { return this.m_view; };
+
+/** @return {number} */
+tcuTexture.Texture2DArray.prototype.getWidth = function() { return this.m_width; };
+
+/** @return {number} */
+tcuTexture.Texture2DArray.prototype.getHeight = function() { return this.m_height; };
+
+/**
+ * @param {number} levelNdx
+ */
+tcuTexture.Texture2DArray.prototype.allocLevel = function(levelNdx) {
+ DE_ASSERT(deMath.deInBounds32(levelNdx, 0, this.getNumLevels()));
+
+ var width = tcuTexture.getMipPyramidLevelSize(this.m_width, levelNdx);
+ var height = tcuTexture.getMipPyramidLevelSize(this.m_height, levelNdx);
+
+ tcuTexture.TextureLevelPyramid.prototype.allocLevel.call(this, levelNdx, width, height, this.m_numLayers);
+};
+
+/**
+ * @constructor
+ * @extends {tcuTexture.TextureLevelPyramid}
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+tcuTexture.Texture3D = function(format, width, height, depth) {
+ tcuTexture.TextureLevelPyramid.call(this, format, tcuTexture.computeMipPyramidLevels(width, height, depth));
+ this.m_width = width;
+ this.m_height = height;
+ this.m_depth = depth;
+ this.m_view = new tcuTexture.Texture3DView(this.getNumLevels(), this.getLevels());
+};
+
+tcuTexture.Texture3D.prototype = Object.create(tcuTexture.TextureLevelPyramid.prototype);
+tcuTexture.Texture3D.prototype.constructor = tcuTexture.Texture3D;
+
+tcuTexture.Texture3D.prototype.getWidth = function() { return this.m_width; };
+tcuTexture.Texture3D.prototype.getHeight = function() { return this.m_height; };
+tcuTexture.Texture3D.prototype.getDepth = function() { return this.m_depth; };
+tcuTexture.Texture3D.prototype.getView = function() { return this.m_view; };
+/**
+ * @param {number} baseLevel
+ * @param {number} maxLevel
+ * @return {tcuTexture.Texture3DView}
+ */
+tcuTexture.Texture3D.prototype.getSubView = function(baseLevel, maxLevel) { return this.m_view.getSubView(baseLevel, maxLevel); };
+
+/**
+ * @param {number} levelNdx
+ */
+tcuTexture.Texture3D.prototype.allocLevel = function(levelNdx) {
+ DE_ASSERT(deMath.deInBounds32(levelNdx, 0, this.getNumLevels()));
+
+ var width = tcuTexture.getMipPyramidLevelSize(this.m_width, levelNdx);
+ var height = tcuTexture.getMipPyramidLevelSize(this.m_height, levelNdx);
+ var depth = tcuTexture.getMipPyramidLevelSize(this.m_depth, levelNdx);
+
+ tcuTexture.TextureLevelPyramid.prototype.allocLevel.call(this, levelNdx, width, height, depth);
+};
+
+/**
+ * @constructor
+ * @param {number} numLevels
+ * @param {Array<Array<tcuTexture.ConstPixelBufferAccess>>} levels
+ */
+tcuTexture.TextureCubeView = function(numLevels, levels) {
+ this.m_numLevels = numLevels;
+ this.m_levels = levels;
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number=} lod
+ * @return {Array<number>} Pixel color
+ */
+tcuTexture.TextureCubeView.prototype.sample = function(sampler, texCoord, lod) {
+ DE_ASSERT(sampler.compare == tcuTexture.CompareMode.COMPAREMODE_NONE);
+
+ // Computes (face, s, t).
+ var coords = tcuTexture.getCubeFaceCoords(texCoord);
+ if (sampler.seamlessCubeMap)
+ return tcuTexture.sampleLevelArrayCubeSeamless(this.m_levels, this.m_numLevels, coords.face, sampler, coords.s, coords.t, 0 /* depth */, lod);
+ else
+ return tcuTexture.sampleLevelArray2D(this.m_levels[coords.face], this.m_numLevels, sampler, coords.s, coords.t, 0 /* depth */, lod);
+};
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {number} ref
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @return {number}
+ */
+tcuTexture.TextureCubeView.prototype.sampleCompare = function(sampler, ref, texCoord, lod) {
+ DE_ASSERT(sampler.compare != tcuTexture.CompareMode.COMPAREMODE_NONE);
+
+ // Computes (face, s, t).
+ var coords = tcuTexture.getCubeFaceCoords(texCoord);
+ if (sampler.seamlessCubeMap)
+ return tcuTexture.sampleLevelArrayCubeSeamlessCompare(this.m_levels, this.m_numLevels, coords.face, sampler, ref, coords.s, coords.t, lod);
+ else
+ return tcuTexture.sampleLevelArray2DCompare(this.m_levels[coords.face], this.m_numLevels, sampler, ref, coords.s, coords.t, lod, [0, 0, 0]);
+};
+
+/**
+ * @param {tcuTexture.CubeFace} face
+ * @return {Array<tcuTexture.ConstPixelBufferAccess>}
+ */
+tcuTexture.TextureCubeView.prototype.getFaceLevels = function(face) { return this.m_levels[face]; };
+/** @return {number} */
+tcuTexture.TextureCubeView.prototype.getSize = function() { return this.m_numLevels > 0 ? this.m_levels[0][0].getWidth() : 0; };
+
+/** @return {number} */
+tcuTexture.TextureCubeView.prototype.getNumLevels = function() { return this.m_numLevels; };
+
+/**
+ * @param {number} ndx
+ * @param {tcuTexture.CubeFace} face
+ * @return {tcuTexture.ConstPixelBufferAccess}
+ */
+tcuTexture.TextureCubeView.prototype.getLevelFace = function(ndx, face) {
+ assertMsgOptions(0 <= ndx && ndx < this.m_numLevels, '', false, true);
+ return this.m_levels[face][ndx];
+};
+
+/**
+ * @param {number} baseLevel
+ * @param {number} maxLevel
+ * @return {tcuTexture.TextureCubeView}
+ */
+tcuTexture.TextureCubeView.prototype.getSubView = function(baseLevel, maxLevel) {
+ var clampedBase = deMath.clamp(baseLevel, 0, this.m_numLevels - 1);
+ var clampedMax = deMath.clamp(maxLevel, clampedBase, this.m_numLevels - 1);
+ var numLevels = clampedMax - clampedBase + 1;
+ var levels = [];
+ for (var face in tcuTexture.CubeFace)
+ levels.push(this.getFaceLevels(tcuTexture.CubeFace[face]).slice(clampedBase, numLevels));
+
+ return new tcuTexture.TextureCubeView(numLevels, levels);
+};
+
+/**
+ * @constructor
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} size
+ */
+tcuTexture.TextureCube = function(format, size) {
+ this.m_format = format;
+ this.m_size = size;
+ this.m_data = [];
+ this.m_data.length = Object.keys(tcuTexture.CubeFace).length;
+ this.m_access = [];
+ this.m_access.length = Object.keys(tcuTexture.CubeFace).length;
+
+ var numLevels = tcuTexture.computeMipPyramidLevels(this.m_size);
+ var levels = [];
+ levels.length = Object.keys(tcuTexture.CubeFace).length;
+
+ for (var face in tcuTexture.CubeFace) {
+ this.m_data[tcuTexture.CubeFace[face]] = [];
+ for (var i = 0; i < numLevels; i++)
+ this.m_data[tcuTexture.CubeFace[face]].push(new tcuTexture.DeqpArrayBuffer());
+ this.m_access[tcuTexture.CubeFace[face]] = [];
+ this.m_access[tcuTexture.CubeFace[face]].length = numLevels;
+ levels[tcuTexture.CubeFace[face]] = this.m_access[tcuTexture.CubeFace[face]];
+ }
+
+ this.m_view = new tcuTexture.TextureCubeView(numLevels, levels);
+};
+
+/** @return {tcuTexture.TextureFormat} */
+tcuTexture.TextureCube.prototype.getFormat = function() { return this.m_format; };
+/** @return {number} */
+tcuTexture.TextureCube.prototype.getSize = function() { return this.m_size; };
+/** @return {tcuTexture.TextureCubeView} */
+tcuTexture.TextureCube.prototype.getView = function() { return this.m_view; };
+/**
+ * @param {number} ndx Level index
+ * @param {tcuTexture.CubeFace} face
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+tcuTexture.TextureCube.prototype.getLevelFace = function(ndx, face) { return this.m_access[face][ndx]; };
+/** @return {number} */
+tcuTexture.TextureCube.prototype.getNumLevels = function() { return this.m_access[0].length; };
+
+/**
+ * @param {tcuTexture.Sampler} sampler
+ * @param {Array<number>} texCoord
+ * @param {number} lod
+ * @return {Array<number>} Pixel color
+ */
+tcuTexture.TextureCube.prototype.sample = function(sampler, texCoord, lod) {
+ return this.m_view.sample(sampler, texCoord, lod);
+};
+
+/**
+ * @param {number} baseLevel
+ * @param {number} maxLevel
+ * @return {tcuTexture.TextureCubeView}
+ */
+tcuTexture.TextureCube.prototype.getSubView = function(baseLevel, maxLevel) { return this.m_view.getSubView(baseLevel, maxLevel); };
+
+/**
+ * @param {tcuTexture.CubeFace} face
+ * @param {number} levelNdx
+ * @return {boolean}
+ */
+tcuTexture.TextureCube.prototype.isLevelEmpty = function(face, levelNdx) {
+ return this.m_data[face][levelNdx].empty();
+};
+
+/**
+ * @param {tcuTexture.CubeFace} face
+ * @param {number} levelNdx
+ */
+tcuTexture.TextureCube.prototype.allocLevel = function(face, levelNdx) {
+ /** @const */ var size = tcuTexture.getMipPyramidLevelSize(this.m_size, levelNdx);
+ /** @const*/ var dataSize = this.m_format.getPixelSize() * size * size;
+ DE_ASSERT(this.isLevelEmpty(face, levelNdx));
+
+ this.m_data[face][levelNdx].setStorage(dataSize);
+ this.m_access[face][levelNdx] = new tcuTexture.PixelBufferAccess({
+ format: this.m_format,
+ width: size,
+ height: size,
+ depth: 1,
+ data: this.m_data[face][levelNdx].m_ptr
+ });
+};
+
+/**
+ * @param {Array<number>} coords Cube coordinates
+ * @return {tcuTexture.CubeFace}
+ */
+tcuTexture.selectCubeFace = function(coords) {
+ var x = coords[0];
+ var y = coords[1];
+ var z = coords[2];
+ var ax = Math.abs(x);
+ var ay = Math.abs(y);
+ var az = Math.abs(z);
+
+ if (ay < ax && az < ax)
+ return x >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_X : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X;
+ else if (ax < ay && az < ay)
+ return y >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y;
+ else if (ax < az && ay < az)
+ return z >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z;
+ else {
+ // Some of the components are equal. Use tie-breaking rule.
+ if (ax == ay) {
+ if (ax < az)
+ return z >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z;
+ else
+ return x >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_X : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X;
+ } else if (ax == az) {
+ if (az < ay)
+ return y >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y;
+ else
+ return z >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z;
+ } else if (ay == az) {
+ if (ay < ax)
+ return x >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_X : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X;
+ else
+ return y >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y;
+ } else
+ return x >= 0 ? tcuTexture.CubeFace.CUBEFACE_POSITIVE_X : tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X;
+ }
+};
+
+/**
+ * @param {tcuTexture.CubeFace} face
+ * @param {Array<number>} coord Cube coordinates (Vec3)
+ * @return {Array<number>} face coordinates (Vec2)
+ */
+tcuTexture.projectToFace = function(face, coord) {
+ var rx = coord[0];
+ var ry = coord[1];
+ var rz = coord[2];
+ var sc = 0;
+ var tc = 0;
+ var ma = 0;
+
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: sc = +rz; tc = -ry; ma = -rx; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: sc = -rz; tc = -ry; ma = +rx; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: sc = +rx; tc = -rz; ma = -ry; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: sc = +rx; tc = +rz; ma = +ry; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: sc = -rx; tc = -ry; ma = -rz; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: sc = +rx; tc = -ry; ma = +rz; break;
+ default:
+ throw new Error('Unrecognized face ' + face);
+ }
+
+ // Compute s, t
+ var s = ((sc / ma) + 1) / 2;
+ var t = ((tc / ma) + 1) / 2;
+
+ return [s, t];
+};
+
+/**
+ * @constructor
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number=} width
+ * @param {number=} height
+ * @param {number=} depth
+ */
+tcuTexture.TextureLevel = function(format, width, height, depth) {
+ this.m_format = format;
+ this.m_width = width || 0;
+ this.m_height = height || 0;
+ this.m_depth = depth === undefined ? 1 : depth;
+ this.m_data = new tcuTexture.DeqpArrayBuffer();
+ this.setSize(this.m_width, this.m_height, this.m_depth);
+};
+
+tcuTexture.TextureLevel.prototype.constructor = tcuTexture.TextureLevel;
+
+/**
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number=} width
+ * @param {number=} height
+ * @param {number=} depth
+ */
+tcuTexture.TextureLevel.prototype.setStorage = function(format, width, height, depth) {
+ this.m_format = format;
+ this.setSize(width, height, depth);
+};
+
+/**
+ * @param {number=} width
+ * @param {number=} height
+ * @param {number=} depth
+ */
+tcuTexture.TextureLevel.prototype.setSize = function(width, height, depth) {
+ var pixelSize = this.m_format.getPixelSize();
+
+ this.m_width = width || 0;
+ this.m_height = height || 0;
+ this.m_depth = depth === undefined ? 1 : depth;
+
+ this.m_data.setStorage(this.m_width * this.m_height * this.m_depth * pixelSize);
+};
+
+/**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+tcuTexture.TextureLevel.prototype.getAccess = function() {
+ return new tcuTexture.PixelBufferAccess({
+ format: this.m_format,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_depth,
+ data: this.m_data.m_ptr
+ });
+
+};
+
+/**
+ * @return {number}
+ */
+tcuTexture.TextureLevel.prototype.getWidth = function() {
+ return this.m_width;
+};
+
+/**
+ * @return {number}
+ */
+tcuTexture.TextureLevel.prototype.getHeight = function() {
+ return this.m_height;
+};
+
+/**
+ * @return {number}
+ */
+tcuTexture.TextureLevel.prototype.getDepth = function() {
+ return this.m_depth;
+};
+
+/**
+ * @return {?tcuTexture.TextureFormat}
+ */
+tcuTexture.TextureLevel.prototype.getFormat = function() {
+ return this.m_format;
+};
+
+/**
+ * Checks if origCoords.coords is in bounds defined by size; if not, return a CubeFaceCoords with face set to the appropriate neighboring face and coords transformed accordingly.
+ * \note If both x and y in origCoords.coords are out of bounds, this returns with face CUBEFACE_LAST, signifying that there is no unique neighboring face.
+ * @param {tcuTexture.CubeFaceCoords} origCoords
+ * @param {number} size
+ * @return {tcuTexture.CubeFaceCoords}
+ */
+tcuTexture.remapCubeEdgeCoords = function(origCoords, size) {
+ var uInBounds = deMath.deInBounds32(origCoords.s, 0, size);
+ var vInBounds = deMath.deInBounds32(origCoords.t, 0, size);
+
+ if (uInBounds && vInBounds)
+ return origCoords;
+
+ if (!uInBounds && !vInBounds)
+ return null;
+
+ var coords = [
+ tcuTexture.wrap(tcuTexture.WrapMode.CLAMP_TO_BORDER, origCoords.s, size),
+ tcuTexture.wrap(tcuTexture.WrapMode.CLAMP_TO_BORDER, origCoords.t, size)];
+ var canonizedCoords = [];
+
+ // Map the uv coordinates to canonized 3d coordinates.
+
+ switch (origCoords.face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: canonizedCoords = [0, size - 1 - coords[1], coords[0]]; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: canonizedCoords = [size - 1, size - 1 - coords[1], size - 1 - coords[0]]; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: canonizedCoords = [coords[0], 0, size - 1 - coords[1]]; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: canonizedCoords = [coords[0], size - 1, coords[1]]; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: canonizedCoords = [size - 1 - coords[0], size - 1 - coords[1], 0]; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: canonizedCoords = [coords[0], size - 1 - coords[1], size - 1]; break;
+ default: throw new Error('Invalid cube face:' + origCoords.face);
+ }
+
+ // Find an appropriate face to re-map the coordinates to.
+
+ if (canonizedCoords[0] == -1)
+ return new tcuTexture.CubeFaceCoords(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X, [canonizedCoords[2], size - 1 - canonizedCoords[1]]);
+
+ if (canonizedCoords[0] == size)
+ return new tcuTexture.CubeFaceCoords(tcuTexture.CubeFace.CUBEFACE_POSITIVE_X, [size - 1 - canonizedCoords[2], size - 1 - canonizedCoords[1]]);
+
+ if (canonizedCoords[1] == -1)
+ return new tcuTexture.CubeFaceCoords(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y, [canonizedCoords[0], size - 1 - canonizedCoords[2]]);
+
+ if (canonizedCoords[1] == size)
+ return new tcuTexture.CubeFaceCoords(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y, [canonizedCoords[0], canonizedCoords[2]]);
+
+ if (canonizedCoords[2] == -1)
+ return new tcuTexture.CubeFaceCoords(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z, [size - 1 - canonizedCoords[0], size - 1 - canonizedCoords[1]]);
+
+ if (canonizedCoords[2] == size)
+ return new tcuTexture.CubeFaceCoords(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z, [canonizedCoords[0], size - 1 - canonizedCoords[1]]);
+
+ throw new Error('Cannot remap cube coordinates');
+};
+
+/**
+ * @constructor
+ * @param {tcuTexture.ConstPixelBufferAccess} src
+ */
+tcuTexture.RGBA8View = function(src) {
+ this.src = src;
+ this.data = new Uint8Array(src.getBuffer(), src.m_offset);
+ this.stride = src.getRowPitch();
+ this.width = src.getWidth();
+ this.height = src.getHeight();
+ this.pixelSize = src.getFormat().getPixelSize();
+};
+
+/**
+ * @return {tcuTexture.TextureFormat}
+ */
+tcuTexture.RGBA8View.prototype.getFormat = function() { return this.src.getFormat(); };
+
+/**
+ * Read a pixel
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} numChannels
+ * @return {Array<number>}
+ */
+tcuTexture.RGBA8View.prototype.read = function(x, y, numChannels) {
+ numChannels = numChannels || 4;
+ var offset = y * this.stride + x * this.pixelSize;
+ /* Always return a vec4 */
+ var result = [0, 0, 0, 255];
+ for (var i = 0; i < numChannels; i++)
+ result[i] = this.data[offset + i];
+ return result;
+};
+
+/**
+ * Read a pixel into a Uint32
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+tcuTexture.RGBA8View.prototype.readUintRGBA8 = function(x, y) {
+ var offset = y * this.stride + x * this.pixelSize;
+ return ((this.data[offset] & 0xff) << 24) +
+ ((this.data[offset + 1] & 0xff) << 16) +
+ ((this.data[offset + 2] & 0xff) << 8) +
+ (this.data[offset + 3] & 0xff);
+};
+
+/**
+ * Write a pixel
+ * @param {number} x
+ * @param {number} y
+ * @param {Array<number>} value
+ * @param {number=} numChannels
+ */
+tcuTexture.RGBA8View.prototype.write = function(x, y, value, numChannels) {
+ numChannels = numChannels || 4;
+ var offset = y * this.stride + x * this.pixelSize;
+ for (var i = 0; i < numChannels; i++)
+ this.data[offset + i] = value[i];
+};
+
+tcuTexture.RGBA8View.prototype.getWidth = function() { return this.width; };
+
+tcuTexture.RGBA8View.prototype.getHeight = function() { return this.height; };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTextureUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTextureUtil.js
new file mode 100644
index 0000000000..40450ab380
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuTextureUtil.js
@@ -0,0 +1,725 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a tcuTextureUtil.copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuTextureUtil');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+
+goog.scope(function() {
+
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var deRandom = framework.delibs.debase.deRandom;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/**
+ * @param {number} t
+ * @param {number} minVal
+ * @param {number} maxVal
+ * @return {number}
+ */
+tcuTextureUtil.linearInterpolate = function(t, minVal, maxVal) {
+ return minVal + (maxVal - minVal) * t;
+};
+
+/** tcuTextureUtil.linearChannelToSRGB
+ * @param {number} cl
+ * @return {number}
+ */
+tcuTextureUtil.linearChannelToSRGB = function(cl) {
+ if (cl <= 0.0)
+ return 0.0;
+ else if (cl < 0.0031308)
+ return 12.92 * cl;
+ else if (cl < 1.0)
+ return 1.055 * Math.pow(cl, 0.41666) - 0.055;
+ else
+ return 1.0;
+};
+
+/**
+ * Convert sRGB to linear colorspace
+ * @param {Array<number>} cs
+ * @return {Array<number>}
+ */
+tcuTextureUtil.sRGBToLinear = function(cs) {
+ return [tcuTextureUtil.sRGBChannelToLinear(cs[0]),
+ tcuTextureUtil.sRGBChannelToLinear(cs[1]),
+ tcuTextureUtil.sRGBChannelToLinear(cs[2]),
+ cs[3]];
+};
+
+/**
+ * @param {number} cs
+ * @return {number}
+ */
+ tcuTextureUtil.sRGBChannelToLinear = function(cs) {
+ if (cs <= 0.04045)
+ return cs / 12.92;
+ else
+ return Math.pow((cs + 0.055) / 1.055, 2.4);
+};
+
+/** tcuTextureUtil.linearToSRGB
+ * @param {Array<number>} cl
+ * @return {Array<number>}
+ */
+tcuTextureUtil.linearToSRGB = function(cl) {
+ return [tcuTextureUtil.linearChannelToSRGB(cl[0]),
+ tcuTextureUtil.linearChannelToSRGB(cl[1]),
+ tcuTextureUtil.linearChannelToSRGB(cl[2]),
+ cl[3]
+ ];
+};
+
+/**
+ * tcuTextureUtil.getSubregion
+ * @param {tcuTexture.PixelBufferAccess} access
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+tcuTextureUtil.getSubregion = function(access, x, y, z, width, height, depth) {
+
+ DE_ASSERT(deMath.deInBounds32(x, 0, access.getWidth()) && deMath.deInRange32(x + width, x, access.getWidth()));
+ DE_ASSERT(deMath.deInBounds32(y, 0, access.getHeight()) && deMath.deInRange32(y + height, y, access.getHeight()));
+ DE_ASSERT(deMath.deInBounds32(z, 0, access.getDepth()) && deMath.deInRange32(z + depth, z, access.getDepth()));
+
+ return new tcuTexture.PixelBufferAccess({
+ format: access.getFormat(),
+ width: width,
+ height: height,
+ depth: depth,
+ rowPitch: access.getRowPitch(),
+ slicePitch: access.getSlicePitch(),
+ offset: access.m_offset + access.getFormat().getPixelSize() * x + access.getRowPitch() * y + access.getSlicePitch() * z,
+ data: access.getBuffer()
+ });
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} access
+ * @param {Array<number>} minVal
+ * @param {Array<number>} maxVal
+ */
+tcuTextureUtil.fillWithComponentGradients1D = function(access, minVal, maxVal) {
+ DE_ASSERT(access.getHeight() == 1);
+ for (var x = 0; x < access.getWidth(); x++) {
+ var s = (x + 0.5) / access.getWidth();
+
+ var r = tcuTextureUtil.linearInterpolate(s, minVal[0], maxVal[0]);
+ var g = tcuTextureUtil.linearInterpolate(s, minVal[1], maxVal[1]);
+ var b = tcuTextureUtil.linearInterpolate(s, minVal[2], maxVal[2]);
+ var a = tcuTextureUtil.linearInterpolate(s, minVal[3], maxVal[3]);
+
+ access.setPixel([r, g, b, a], x, 0);
+ }
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} access
+ * @param {Array<number>} minVal
+ * @param {Array<number>} maxVal
+ */
+tcuTextureUtil.fillWithComponentGradients2D = function(access, minVal, maxVal) {
+ for (var y = 0; y < access.getHeight(); y++) {
+ var t = (y + 0.5) / access.getHeight();
+ for (var x = 0; x < access.getWidth(); x++) {
+ var s = (x + 0.5) / access.getWidth();
+
+ var r = tcuTextureUtil.linearInterpolate((s + t) * 0.5, minVal[0], maxVal[0]);
+ var g = tcuTextureUtil.linearInterpolate((s + (1 - t)) * 0.5, minVal[1], maxVal[1]);
+ var b = tcuTextureUtil.linearInterpolate(((1 - s) + t) * 0.5, minVal[2], maxVal[2]);
+ var a = tcuTextureUtil.linearInterpolate(((1 - s) + (1 - t)) * 0.5, minVal[3], maxVal[3]);
+
+ access.setPixel([r, g, b, a], x, y);
+ }
+ }
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {Array<number>} minVal
+ * @param {Array<number>} maxVal
+ */
+tcuTextureUtil.fillWithComponentGradients3D = function(dst, minVal, maxVal) {
+ for (var z = 0; z < dst.getDepth(); z++) {
+ var p = (z + 0.5) / dst.getDepth();
+ var b = tcuTextureUtil.linearInterpolate(p, minVal[2], maxVal[2]);
+ for (var y = 0; y < dst.getHeight(); y++) {
+ var t = (y + 0.5) / dst.getHeight();
+ var g = tcuTextureUtil.linearInterpolate(t, minVal[1], maxVal[1]);
+ for (var x = 0; x < dst.getWidth(); x++) {
+ var s = (x + 0.5) / dst.getWidth();
+ var r = tcuTextureUtil.linearInterpolate(s, minVal[0], maxVal[0]);
+ var a = tcuTextureUtil.linearInterpolate(1 - (s + t + p) / 3, minVal[3], maxVal[3]);
+ dst.setPixel([r, g, b, a], x, y, z);
+ }
+ }
+ }
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} access
+ * @param {Array<number>} minVal
+ * @param {Array<number>} maxVal
+ */
+tcuTextureUtil.fillWithComponentGradients = function(access, minVal, maxVal) {
+ if (access.getHeight() == 1 && access.getDepth() == 1)
+ tcuTextureUtil.fillWithComponentGradients1D(access, minVal, maxVal);
+ else if (access.getDepth() == 1)
+ tcuTextureUtil.fillWithComponentGradients2D(access, minVal, maxVal);
+ else
+ tcuTextureUtil.fillWithComponentGradients3D(access, minVal, maxVal);
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ */
+tcuTextureUtil.fillWithRGBAQuads = function(dst) {
+ checkMessage(dst.getDepth() == 1, 'Depth must be 1');
+ var width = dst.getWidth();
+ var height = dst.getHeight();
+ var left = width / 2;
+ var top = height / 2;
+
+ tcuTextureUtil.getSubregion(dst, 0, 0, 0, left, top, 1).clear([1.0, 0.0, 0.0, 1.0]);
+ tcuTextureUtil.getSubregion(dst, left, 0, 0, width - left, top, 1).clear([0.0, 1.0, 0.0, 1.0]);
+ tcuTextureUtil.getSubregion(dst, 0, top, 0, left, height - top, 1).clear([0.0, 0.0, 1.0, 0.0]);
+ tcuTextureUtil.getSubregion(dst, left, top, 0, width - left, height - top, 1).clear([0.5, 0.5, 0.5, 1.0]);
+};
+
+// \todo [2012-11-13 pyry] There is much better metaballs code in CL SIR value generators.
+/**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {number} numBalls
+ * @param {number} seed
+ */
+tcuTextureUtil.fillWithMetaballs = function(dst, numBalls, seed) {
+ checkMessage(dst.getDepth() == 1, 'Depth must be 1');
+ var points = [];
+ var rnd = new deRandom.Random(seed);
+
+ for (var i = 0; i < numBalls; i++) {
+ var x = rnd.getFloat();
+ var y = rnd.getFloat();
+ points[i] = [x, y];
+ }
+
+ for (var y = 0; y < dst.getHeight(); y++)
+ for (var x = 0; x < dst.getWidth(); x++) {
+ var p = [x / dst.getWidth(), y / dst.getHeight()];
+
+ var sum = 0.0;
+ for (var pointNdx = 0; pointNdx < points.length; pointNdx++) {
+ var d = deMath.subtract(p, points[pointNdx]);
+ var f = 0.01 / (d[0] * d[0] + d[1] * d[1]);
+
+ sum += f;
+ }
+
+ dst.setPixel([sum, sum, sum, sum], x, y);
+ }
+};
+
+/**
+ * Create tcuTextureUtil.TextureFormatInfo.
+ * @constructor
+ * @param {Array<number>} valueMin
+ * @param {Array<number>} valueMax
+ * @param {Array<number>} lookupScale
+ * @param {Array<number>} lookupBias
+ */
+tcuTextureUtil.TextureFormatInfo = function(valueMin, valueMax, lookupScale, lookupBias) {
+ /** @type {Array<number>} */ this.valueMin = valueMin;
+ /** @type {Array<number>} */ this.valueMax = valueMax;
+ /** @type {Array<number>} */ this.lookupScale = lookupScale;
+ /** @type {Array<number>} */ this.lookupBias = lookupBias;
+};
+
+/**
+ * @param {?tcuTexture.ChannelType} channelType
+ * @return {Array<number>}
+ */
+tcuTextureUtil.getChannelValueRange = function(channelType) {
+ var cMin = 0;
+ var cMax = 0;
+
+ switch (channelType) {
+ // Signed normalized formats.
+ case tcuTexture.ChannelType.SNORM_INT8:
+ case tcuTexture.ChannelType.SNORM_INT16: cMin = -1; cMax = 1; break;
+
+ // Unsigned normalized formats.
+ case tcuTexture.ChannelType.UNORM_INT8:
+ case tcuTexture.ChannelType.UNORM_INT16:
+ case tcuTexture.ChannelType.UNORM_SHORT_565:
+ case tcuTexture.ChannelType.UNORM_SHORT_4444:
+ case tcuTexture.ChannelType.UNORM_INT_101010:
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: cMin = 0; cMax = 1; break;
+
+ // Misc formats.
+ case tcuTexture.ChannelType.SIGNED_INT8: cMin = -128; cMax = 127; break;
+ case tcuTexture.ChannelType.SIGNED_INT16: cMin = -32768; cMax = 32767; break;
+ case tcuTexture.ChannelType.SIGNED_INT32: cMin = -2147483648; cMax = 2147483647; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: cMin = 0; cMax = 255; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: cMin = 0; cMax = 65535; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: cMin = 0; cMax = 4294967295; break;
+ case tcuTexture.ChannelType.HALF_FLOAT: cMin = -1e3; cMax = 1e3; break;
+ case tcuTexture.ChannelType.FLOAT: cMin = -1e5; cMax = 1e5; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: cMin = 0; cMax = 1e4; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: cMin = 0; cMax = 1e5; break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ return [cMin, cMax];
+};
+
+/**
+ * Creates an array by choosing between 'a' and 'b' based on 'cond' array.
+ * @param {Array | number} a
+ * @param {Array | number} b
+ * @param {Array<boolean>} cond Condtions
+ * @return {Array}
+ */
+tcuTextureUtil.select = function(a, b, cond) {
+
+ /*DE_ASSERT(!(a.length && !b.length)
+ || !(!a.length && b.length)
+ || !((a.length && b.length) && ((a.length != b.length) || (b.length != cond.length) || (a.length != cond.length))));*/
+
+ if (a.length && !b.length) throw new Error('second input parameter is not a vector');
+ if (!a.length && b.length) throw new Error('first input parameter is not a vector');
+ if ((a.length && b.length) && ((a.length != b.length) || (b.length != cond.length) || (a.length != cond.length))) throw new Error('different size vectors');
+
+ var dst = [];
+ for (var i = 0; i < cond.length; i++)
+ if (cond[i]) {
+ if (a.length) dst.push(a[i]);
+ else dst.push(a);
+ } else {
+ if (b.length) dst.push(b[i]);
+ else dst.push(b);
+ }
+ return dst;
+};
+
+/**
+ * Get standard parameters for testing texture format
+ *
+ * Returns tcuTextureUtil.TextureFormatInfo that describes good parameters for exercising
+ * given TextureFormat. Parameters include value ranges per channel and
+ * suitable lookup scaling and bias in order to reduce result back to
+ * 0..1 range.
+ *
+ * @param {tcuTexture.TextureFormat} format
+ * @return {tcuTextureUtil.TextureFormatInfo}
+ */
+tcuTextureUtil.getTextureFormatInfo = function(format) {
+ // Special cases.
+ if (format.isEqual(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV)))
+ return new tcuTextureUtil.TextureFormatInfo([0, 0, 0, 0],
+ [1023, 1023, 1023, 3],
+ [1 / 1023, 1 / 1023, 1 / 1023, 1 / 3],
+ [0, 0, 0, 0]);
+ else if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS)
+ return new tcuTextureUtil.TextureFormatInfo([0, 0, 0, 0],
+ [1, 1, 1, 0],
+ [1, 1, 1, 1],
+ [0, 0, 0, 0]); // Depth / stencil formats.
+ else if (format.isEqual(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_5551)))
+ return new tcuTextureUtil.TextureFormatInfo([0, 0, 0, 0.5],
+ [1, 1, 1, 1.5],
+ [1, 1, 1, 1],
+ [0, 0, 0, 0]);
+
+ var cRange = tcuTextureUtil.getChannelValueRange(format.type);
+ var chnMask = null;
+
+ switch (format.order) {
+ case tcuTexture.ChannelOrder.R: chnMask = [true, false, false, false]; break;
+ case tcuTexture.ChannelOrder.A: chnMask = [false, false, false, true]; break;
+ case tcuTexture.ChannelOrder.L: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.LA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.RG: chnMask = [true, true, false, false]; break;
+ case tcuTexture.ChannelOrder.RGB: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.RGBA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.sRGB: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.sRGBA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.D: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.DS: chnMask = [true, true, true, true]; break;
+ default:
+ DE_ASSERT(false);
+ }
+
+ var scale = 1 / (cRange[1] - cRange[0]);
+ var bias = -cRange[0] * scale;
+
+ return new tcuTextureUtil.TextureFormatInfo(tcuTextureUtil.select(cRange[0], 0, chnMask),
+ tcuTextureUtil.select(cRange[1], 0, chnMask),
+ tcuTextureUtil.select(scale, 1, chnMask),
+ tcuTextureUtil.select(bias, 0, chnMask));
+};
+
+/** tcuTextureUtil.getChannelBitDepth
+ * @param {?tcuTexture.ChannelType} channelType
+ * @return {Array<number>}
+ */
+tcuTextureUtil.getChannelBitDepth = function(channelType) {
+
+ switch (channelType) {
+ case tcuTexture.ChannelType.SNORM_INT8: return [8, 8, 8, 8];
+ case tcuTexture.ChannelType.SNORM_INT16: return [16, 16, 16, 16];
+ case tcuTexture.ChannelType.SNORM_INT32: return [32, 32, 32, 32];
+ case tcuTexture.ChannelType.UNORM_INT8: return [8, 8, 8, 8];
+ case tcuTexture.ChannelType.UNORM_INT16: return [16, 16, 16, 16];
+ case tcuTexture.ChannelType.UNORM_INT32: return [32, 32, 32, 32];
+ case tcuTexture.ChannelType.UNORM_SHORT_565: return [5, 6, 5, 0];
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: return [4, 4, 4, 4];
+ case tcuTexture.ChannelType.UNORM_SHORT_555: return [5, 5, 5, 0];
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: return [5, 5, 5, 1];
+ case tcuTexture.ChannelType.UNORM_INT_101010: return [10, 10, 10, 0];
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: return [10, 10, 10, 2];
+ case tcuTexture.ChannelType.SIGNED_INT8: return [8, 8, 8, 8];
+ case tcuTexture.ChannelType.SIGNED_INT16: return [16, 16, 16, 16];
+ case tcuTexture.ChannelType.SIGNED_INT32: return [32, 32, 32, 32];
+ case tcuTexture.ChannelType.UNSIGNED_INT8: return [8, 8, 8, 8];
+ case tcuTexture.ChannelType.UNSIGNED_INT16: return [16, 16, 16, 16];
+ case tcuTexture.ChannelType.UNSIGNED_INT32: return [32, 32, 32, 32];
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return [10, 10, 10, 2];
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return [24, 0, 0, 8];
+ case tcuTexture.ChannelType.HALF_FLOAT: return [16, 16, 16, 16];
+ case tcuTexture.ChannelType.FLOAT: return [32, 32, 32, 32];
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return [11, 11, 10, 0];
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: return [9, 9, 9, 0];
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return [32, 0, 0, 8];
+ default:
+ DE_ASSERT(false);
+ return [0, 0, 0, 0];
+ }
+};
+
+/** tcuTextureUtil.getTextureFormatBitDepth
+ * @param {tcuTexture.TextureFormat} format
+ * @return {Array<number>}
+ */
+tcuTextureUtil.getTextureFormatBitDepth = function(format) {
+
+ /** @type {Array<number>} */ var chnBits = tcuTextureUtil.getChannelBitDepth(format.type); // IVec4
+ /** @type {Array<boolean>} */ var chnMask = [false, false, false, false]; // BVec4
+ /** @type {Array<number>} */ var chnSwz = [0, 1, 2, 3]; // IVec4
+
+ switch (format.order) {
+ case tcuTexture.ChannelOrder.R: chnMask = [true, false, false, false]; break;
+ case tcuTexture.ChannelOrder.A: chnMask = [false, false, false, true]; break;
+ case tcuTexture.ChannelOrder.RA: chnMask = [true, false, false, true]; break;
+ case tcuTexture.ChannelOrder.L: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.I: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.LA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.RG: chnMask = [true, true, false, false]; break;
+ case tcuTexture.ChannelOrder.RGB: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.RGBA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.BGRA: chnMask = [true, true, true, true]; chnSwz = [2, 1, 0, 3]; break;
+ case tcuTexture.ChannelOrder.ARGB: chnMask = [true, true, true, true]; chnSwz = [1, 2, 3, 0]; break;
+ case tcuTexture.ChannelOrder.sRGB: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.sRGBA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.D: chnMask = [true, false, false, false]; break;
+ case tcuTexture.ChannelOrder.DS: chnMask = [true, false, false, true]; break;
+ case tcuTexture.ChannelOrder.S: chnMask = [false, false, false, true]; break;
+ default:
+ DE_ASSERT(false);
+ }
+
+ return tcuTextureUtil.select(deMath.swizzle(chnBits, [chnSwz[0], chnSwz[1], chnSwz[2], chnSwz[3]]), [0, 0, 0, 0], chnMask);
+
+};
+
+/** tcuTextureUtil.fillWithGrid
+ * @const @param {tcuTexture.PixelBufferAccess} access
+ * @param {number} cellSize
+ * @param {Array<number>} colorA
+ * @param {Array<number>} colorB
+ */
+tcuTextureUtil.fillWithGrid = function(access, cellSize, colorA, colorB) {
+ if (access.getHeight() == 1 && access.getDepth() == 1)
+ tcuTextureUtil.fillWithGrid1D(access, cellSize, colorA, colorB);
+ else if (access.getDepth() == 1)
+ tcuTextureUtil.fillWithGrid2D(access, cellSize, colorA, colorB);
+ else
+ tcuTextureUtil.fillWithGrid3D(access, cellSize, colorA, colorB);
+};
+
+/** tcuTextureUtil.fillWithGrid1D
+ * @const @param {tcuTexture.PixelBufferAccess} access
+ * @param {number} cellSize
+ * @param {Array<number>} colorA
+ * @param {Array<number>} colorB
+ */
+tcuTextureUtil.fillWithGrid1D = function(access, cellSize, colorA, colorB) {
+ for (var x = 0; x < access.getWidth(); x++) {
+ var mx = Math.floor(x / cellSize) % 2;
+
+ if (mx)
+ access.setPixel(colorB, x, 0);
+ else
+ access.setPixel(colorA, x, 0);
+ }
+};
+
+/** tcuTextureUtil.fillWithGrid2D
+ * @const @param {tcuTexture.PixelBufferAccess} access
+ * @param {number} cellSize
+ * @param {Array<number>} colorA
+ * @param {Array<number>} colorB
+ */
+tcuTextureUtil.fillWithGrid2D = function(access, cellSize, colorA, colorB) {
+ for (var y = 0; y < access.getHeight(); y++)
+ for (var x = 0; x < access.getWidth(); x++) {
+ var mx = Math.floor(x / cellSize) % 2;
+ var my = Math.floor(y / cellSize) % 2;
+
+ if (mx ^ my)
+ access.setPixel(colorB, x, y);
+ else
+ access.setPixel(colorA, x, y);
+ }
+};
+
+/** tcuTextureUtil.fillWithGrid3D
+ * @const @param {tcuTexture.PixelBufferAccess} access
+ * @param {number} cellSize
+ * @param {Array<number>} colorA
+ * @param {Array<number>} colorB
+ */
+tcuTextureUtil.fillWithGrid3D = function(access, cellSize, colorA, colorB) {
+ for (var z = 0; z < access.getDepth(); z++)
+ for (var y = 0; y < access.getHeight(); y++)
+ for (var x = 0; x < access.getWidth(); x++) {
+ var mx = Math.floor(x / cellSize) % 2;
+ var my = Math.floor(y / cellSize) % 2;
+ var mz = Math.floor(z / cellSize) % 2;
+
+ if (mx ^ my ^ mz)
+ access.setPixel(colorB, x, y, z);
+ else
+ access.setPixel(colorA, x, y, z);
+ }
+};
+
+/**
+ * @const @param {tcuTexture.TextureFormat} format
+ * @return {Array<number>}
+ */
+tcuTextureUtil.getTextureFormatMantissaBitDepth = function(format) {
+ /** @type {Array<number>} */ var chnBits = tcuTextureUtil.getChannelMantissaBitDepth(format.type);
+ /** @type {Array<boolean>} */ var chnMask = [false, false, false, false];
+ /** @type {Array<number>} */ var chnSwz = [0, 1, 2, 3];
+
+ switch (format.order) {
+ case tcuTexture.ChannelOrder.R: chnMask = [true, false, false, false]; break;
+ case tcuTexture.ChannelOrder.A: chnMask = [false, false, false, true]; break;
+ case tcuTexture.ChannelOrder.RA: chnMask = [true, false, false, true]; break;
+ case tcuTexture.ChannelOrder.L: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.I: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.LA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.RG: chnMask = [true, true, false, false]; break;
+ case tcuTexture.ChannelOrder.RGB: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.RGBA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.BGRA: chnMask = [true, true, true, true]; chnSwz = [2, 1, 0, 3]; break;
+ case tcuTexture.ChannelOrder.ARGB: chnMask = [true, true, true, true]; chnSwz = [1, 2, 3, 0]; break;
+ case tcuTexture.ChannelOrder.sRGB: chnMask = [true, true, true, false]; break;
+ case tcuTexture.ChannelOrder.sRGBA: chnMask = [true, true, true, true]; break;
+ case tcuTexture.ChannelOrder.D: chnMask = [true, false, false, false]; break;
+ case tcuTexture.ChannelOrder.DS: chnMask = [true, false, false, true]; break;
+ case tcuTexture.ChannelOrder.S: chnMask = [false, false, false, true]; break;
+ default:
+ DE_ASSERT(false);
+ }
+ return tcuTextureUtil.select(deMath.swizzle(chnBits, [chnSwz[0], chnSwz[1], chnSwz[2], chnSwz[3]]), [0, 0, 0, 0], chnMask);
+};
+
+/**
+ * @param {?tcuTexture.ChannelType} channelType
+ * @return {Array<number>}
+ */
+tcuTextureUtil.getChannelMantissaBitDepth = function(channelType) {
+ switch (channelType) {
+ case tcuTexture.ChannelType.SNORM_INT8:
+ case tcuTexture.ChannelType.SNORM_INT16:
+ case tcuTexture.ChannelType.SNORM_INT32:
+ case tcuTexture.ChannelType.UNORM_INT8:
+ case tcuTexture.ChannelType.UNORM_INT16:
+ case tcuTexture.ChannelType.UNORM_INT32:
+ case tcuTexture.ChannelType.UNORM_SHORT_565:
+ case tcuTexture.ChannelType.UNORM_SHORT_4444:
+ case tcuTexture.ChannelType.UNORM_SHORT_555:
+ case tcuTexture.ChannelType.UNORM_SHORT_5551:
+ case tcuTexture.ChannelType.UNORM_INT_101010:
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV:
+ case tcuTexture.ChannelType.SIGNED_INT8:
+ case tcuTexture.ChannelType.SIGNED_INT16:
+ case tcuTexture.ChannelType.SIGNED_INT32:
+ case tcuTexture.ChannelType.UNSIGNED_INT8:
+ case tcuTexture.ChannelType.UNSIGNED_INT16:
+ case tcuTexture.ChannelType.UNSIGNED_INT32:
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV:
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV:
+ return tcuTextureUtil.getChannelBitDepth(channelType);
+ case tcuTexture.ChannelType.HALF_FLOAT: return [10, 10, 10, 10];
+ case tcuTexture.ChannelType.FLOAT: return [23, 23, 23, 23];
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return [6, 6, 5, 0];
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return [23, 0, 0, 8];
+ default:
+ throw new Error('Invalid channelType: ' + channelType);
+ }
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {tcuTexture.ConstPixelBufferAccess} src
+ */
+tcuTextureUtil.copy = function(dst, src) {
+ var width = dst.getWidth();
+ var height = dst.getHeight();
+ var depth = dst.getDepth();
+
+ DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);
+
+ if (src.getFormat().isEqual(dst.getFormat())) {
+ var srcData = src.getDataPtr();
+ var dstData = dst.getDataPtr();
+
+ if (srcData.length == dstData.length) {
+ dstData.set(srcData);
+ return;
+ }
+ }
+ var srcClass = tcuTexture.getTextureChannelClass(src.getFormat().type);
+ var dstClass = tcuTexture.getTextureChannelClass(dst.getFormat().type);
+ var srcIsInt = srcClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER || srcClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER;
+ var dstIsInt = dstClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER || dstClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER;
+
+ if (srcIsInt && dstIsInt) {
+ for (var z = 0; z < depth; z++)
+ for (var y = 0; y < height; y++)
+ for (var x = 0; x < width; x++)
+ dst.setPixelInt(src.getPixelInt(x, y, z), x, y, z);
+ } else {
+ for (var z = 0; z < depth; z++)
+ for (var y = 0; y < height; y++)
+ for (var x = 0; x < width; x++)
+ dst.setPixel(src.getPixel(x, y, z), x, y, z);
+ }
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ */
+tcuTextureUtil.estimatePixelValueRange = function(access) {
+ var format = access.getFormat();
+
+ switch (format.type) {
+ case tcuTexture.ChannelType.UNORM_INT8:
+ case tcuTexture.ChannelType.UNORM_INT16:
+ // Normalized unsigned formats.
+ return [
+ [0, 0, 0, 0],
+ [1, 1, 1, 1]
+ ];
+
+ case tcuTexture.ChannelType.SNORM_INT8:
+ case tcuTexture.ChannelType.SNORM_INT16:
+ // Normalized signed formats.
+ return [
+ [-1, -1, -1, -1],
+ [1, 1, 1, 1]
+ ];
+
+ default:
+ // \note Samples every 4/8th pixel.
+ var minVal = [Infinity, Infinity, Infinity, Infinity];
+ var maxVal = [-Infinity, -Infinity, -Infinity, -Infinity];
+
+ for (var z = 0; z < access.getDepth(); z += 2) {
+ for (var y = 0; y < access.getHeight(); y += 2) {
+ for (var x = 0; x < access.getWidth(); x += 2) {
+ var p = access.getPixel(x, y, z);
+
+ minVal[0] = Math.min(minVal[0], p[0]);
+ minVal[1] = Math.min(minVal[1], p[1]);
+ minVal[2] = Math.min(minVal[2], p[2]);
+ minVal[3] = Math.min(minVal[3], p[3]);
+
+ maxVal[0] = Math.max(maxVal[0], p[0]);
+ maxVal[1] = Math.max(maxVal[1], p[1]);
+ maxVal[2] = Math.max(maxVal[2], p[2]);
+ maxVal[3] = Math.max(maxVal[3], p[3]);
+ }
+ }
+ }
+ return [minVal, maxVal];
+ }
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} access
+ * @return {{scale: Array<number>, bias: Array<number>}}
+ */
+tcuTextureUtil.computePixelScaleBias = function(access) {
+ var limits = tcuTextureUtil.estimatePixelValueRange(access);
+ var minVal = limits[0];
+ var maxVal = limits[1];
+
+ var scale = [1, 1, 1, 1];
+ var bias = [0, 0, 0, 0];
+
+ var eps = 0.0001;
+
+ for (var c = 0; c < 4; c++) {
+ if (maxVal[c] - minVal[c] < eps) {
+ scale[c] = (maxVal[c] < eps) ? 1 : (1 / maxVal[c]);
+ bias[c] = (c == 3) ? (1 - maxVal[c] * scale[c]) : (0 - minVal[c] * scale[c]);
+ } else {
+ scale[c] = 1 / (maxVal[c] - minVal[c]);
+ bias[c] = 0 - minVal[c] * scale[c];
+ }
+ }
+
+ return {
+ scale: scale,
+ bias: bias
+ };
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js
new file mode 100644
index 0000000000..fbb2a61fd7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js
@@ -0,0 +1,1143 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.delibs.debase.deMath');
+
+/** @typedef { (Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array) } */
+goog.TypedArray;
+
+/** @typedef { (Array<number>|Array<boolean>|goog.TypedArray) } */
+goog.NumberArray;
+
+goog.scope(function() {
+
+var deMath = framework.delibs.debase.deMath;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/** @const */ deMath.INT32_SIZE = 4;
+
+deMath.deInRange32 = function(a, mn, mx) {
+ return (a >= mn) && (a <= mx);
+};
+
+deMath.deInBounds32 = function(a, mn, mx) {
+ return (a >= mn) && (a < mx);
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+deMath.deFloatFrac = function(a) { return a - Math.floor(a); };
+
+/**
+ * Transform a 64-bit float number into a 32-bit float number.
+ * Native dEQP uses 32-bit numbers, so sometimes 64-bit floating numbers in JS should be transformed into 32-bit ones to ensure the correctness of the result.
+ * @param {number} a
+ * @return {number}
+ */
+deMath.toFloat32 = (function() {
+ var FLOAT32ARRAY1 = new Float32Array(1);
+ return function(a) {
+ FLOAT32ARRAY1[0] = a;
+ return FLOAT32ARRAY1[0];
+ };
+})();
+
+/** @const */ deMath.INV_LOG_2_FLOAT32 = deMath.toFloat32(1.44269504089); /** 1.0 / log_e(2.0) */
+
+/**
+ * Check if a value is a power-of-two.
+ * @param {number} a Input value.
+ * @return {boolean} return True if input is a power-of-two value, false otherwise.
+ * (Also returns true for zero).
+ */
+deMath.deIsPowerOfTwo32 = function(a) {
+ return ((a & (a - 1)) == 0);
+};
+
+/**
+ * Align an integer to given power-of-two size.
+ * @param {number} val The number to align.
+ * @param {number} align The size to align to.
+ * @return {number} The aligned value
+ */
+deMath.deAlign32 = function(val, align) {
+ if (!deMath.deIsPowerOfTwo32(align))
+ throw new Error('Not a power of 2: ' + align);
+ return ((val + align - 1) & ~(align - 1)) & 0xFFFFFFFF; //0xFFFFFFFF make sure it returns a 32 bit calculation in 64 bit browsers.
+};
+
+/**
+ * Compute the bit population count of an integer.
+ * @param {number} a
+ * @return {number} The number of one bits in
+ */
+deMath.dePop32 = function(a) {
+ /** @type {number} */ var mask0 = 0x55555555; /* 1-bit values. */
+ /** @type {number} */ var mask1 = 0x33333333; /* 2-bit values. */
+ /** @type {number} */ var mask2 = 0x0f0f0f0f; /* 4-bit values. */
+ /** @type {number} */ var mask3 = 0x00ff00ff; /* 8-bit values. */
+ /** @type {number} */ var mask4 = 0x0000ffff; /* 16-bit values. */
+ /** @type {number} */ var t = a & 0xFFFFFFFF; /* Crop to 32-bit value */
+ t = (t & mask0) + ((t >> 1) & mask0);
+ t = (t & mask1) + ((t >> 2) & mask1);
+ t = (t & mask2) + ((t >> 4) & mask2);
+ t = (t & mask3) + ((t >> 8) & mask3);
+ t = (t & mask4) + (t >> 16);
+ return t;
+};
+
+deMath.clamp = function(val, minParm, maxParm) {
+ return Math.min(Math.max(val, minParm), maxParm);
+};
+
+/**
+ * @param {Array<number>} values
+ * @param {number} minParm
+ * @param {number} maxParm
+ * @return {Array<number>}
+ */
+deMath.clampVector = function(values, minParm, maxParm) {
+ var result = [];
+ for (var i = 0; i < values.length; i++)
+ result.push(deMath.clamp(values[i], minParm, maxParm));
+ return result;
+};
+
+deMath.imod = function(a, b) {
+ var m = a % b;
+ return m < 0 ? m + b : m;
+};
+
+deMath.mirror = function(a) {
+ return a >= 0 ? a : -(1 + a);
+};
+
+/**
+ * @param {goog.NumberArray} a Source array
+ * @param {goog.NumberArray} indices
+ * @return {Array<number>} Swizzled array
+ */
+deMath.swizzle = function(a, indices) {
+ if (!indices.length)
+ throw new Error('Argument must be an array');
+ var dst = [];
+ for (var i = 0; i < indices.length; i++)
+ dst.push(a[indices[i]]);
+ return dst;
+};
+
+/**
+ * Shift left elements of array a by elements of array b
+ * dst[n] a[n] << b[n]
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>} Result array
+ */
+deMath.arrayShiftLeft = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] << b[i]);
+ return dst;
+};
+
+/**
+ * Multiply two vectors, element by element
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>} Result array
+ */
+
+deMath.multiply = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] * b[i]);
+ return dst;
+};
+
+/**
+ * Divide two vectors, element by element
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>} Result array
+ * @throws {Error}
+ */
+
+deMath.divide = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++) {
+ if (b[i] === 0)
+ throw new Error('Division by 0');
+ dst.push(a[i] / b[i]);
+ }
+ return dst;
+};
+
+/**
+ * Divide vector by a scalar
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>} Result array
+ */
+deMath.divideScale = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] / b);
+ return dst;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+deMath.mod = function(a, b) {
+ return a - b * Math.floor(a / b);
+};
+
+/**
+ * Modulus vector by a scalar
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>} Result array
+ */
+deMath.modScale = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(deMath.mod(a[i], b));
+ return dst;
+};
+
+/**
+ * Multiply vector by a scalar
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>} Result array
+ */
+deMath.scale = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] * b);
+ return dst;
+};
+
+/**
+ * Add vector and scalar, element by element
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>} Result array
+ */
+deMath.addScalar = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('First argument must be an array.');
+ if (typeof b !== 'number')
+ throw new Error('Second argument must be a number.');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] + b);
+ return dst;
+};
+
+/**
+ * Add two vectors, element by element
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>} Result array
+ */
+deMath.add = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] + b[i]);
+ return dst;
+};
+
+/**
+ * Subtract two vectors, element by element
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>} Result array
+ */
+
+deMath.subtract = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] - b[i]);
+ return dst;
+};
+
+/**
+ * Subtract vector and scalar, element by element
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>} Result array
+ */
+deMath.subScalar = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('First argument must be an array.');
+ if (typeof b !== 'number')
+ throw new Error('Second argument must be a number.');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] - b);
+ return dst;
+};
+
+/**
+ * Calculate absolute difference between two vectors
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>} abs(diff(a - b))
+ */
+deMath.absDiff = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(Math.abs(a[i] - b[i]));
+ return dst;
+};
+
+/**
+ * Calculate absolute value of a vector
+ * @param {goog.NumberArray} a
+ * @return {Array<number>} abs(a)
+ */
+deMath.abs = function(a) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(Math.abs(a[i]));
+ return dst;
+};
+
+/**
+ * Is a <= b (element by element)?
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<boolean>} Result array of booleans
+ */
+deMath.lessThanEqual = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i] <= b[i]);
+ return dst;
+};
+
+/**
+ * Is a === b (element by element)?
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {boolean} Result
+ */
+deMath.equal = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ for (var i = 0; i < a.length; i++) {
+ if (a[i] !== b[i])
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Are all values in the array true?
+ * @param {Array<boolean>} a
+ * @return {boolean}
+ */
+deMath.boolAll = function(a) {
+ for (var i = 0; i < a.length; i++)
+ if (a[i] == false)
+ return false;
+ return true;
+};
+
+/**
+ * deMath.assign(a, b) element by element
+ * @param {goog.NumberArray} a
+ * @return {Array<number>}
+ */
+deMath.assign = function(a) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(a[i]);
+ return dst;
+};
+
+/**
+ * deMath.max(a, b) element by element
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>}
+ */
+deMath.max = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(Math.max(a[i], b[i]));
+ return dst;
+};
+
+/**
+ * deMath.min(a, b) element by element
+ * @param {goog.NumberArray} a
+ * @param {goog.NumberArray} b
+ * @return {Array<number>}
+ */
+deMath.min = function(a, b) {
+ if (a.length != b.length)
+ throw new Error('Arrays must have the same size');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(Math.min(a[i], b[i]));
+ return dst;
+};
+
+// Nearest-even rounding in case of tie (fractional part 0.5), otherwise ordinary rounding.
+deMath.rint = function(a) {
+ var floorVal = Math.floor(a);
+ var fracVal = a - floorVal;
+
+ if (fracVal != 0.5)
+ return Math.round(a); // Ordinary case.
+
+ var roundUp = (floorVal % 2) != 0;
+
+ return floorVal + (roundUp ? 1 : 0);
+};
+
+/**
+ * wrap the number, so that it fits in the range [minValue, maxValue]
+ * @param {number} v
+ * @param {number} minValue
+ * @param {number} maxValue
+ * @return {number}
+ */
+deMath.wrap = function(v, minValue, maxValue) {
+ var range = maxValue - minValue + 1;
+
+ if (v < minValue) {
+ v += range * (Math.floor((minValue - v) / range) + 1);
+ }
+ return minValue + Math.floor((v - minValue) % range);
+};
+
+/**
+ * Round number to int by dropping fractional part
+ * it is equivalent of GLSL int() constructor
+ * @param {number} a
+ * @return {number}
+ */
+deMath.intCast = function(a) {
+ var v;
+ if (a >= 0)
+ v = Math.floor(a);
+ else
+ v = Math.ceil(a);
+ return deMath.wrap(v, -0x80000000, 0x7FFFFFFF);
+};
+
+/**
+ * Round number to uint by dropping fractional part
+ * it is equivalent of GLSL uint() constructor
+ * @param {number} a
+ * @return {number}
+ */
+deMath.uintCast = function(a) {
+ var v;
+ if (a >= 0)
+ v = Math.floor(a);
+ else
+ v = Math.ceil(a);
+ return deMath.wrap(v, 0, 0xFFFFFFFF);
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+deMath.logToFloor = function(a) {
+ assertMsgOptions(a > 0, 'Value is less or equal than zero', false, true);
+ return 31 - deMath.clz32(a);
+};
+
+/**
+ * Find intersection of two rectangles
+ * @param {goog.NumberArray} a Array [x, y, width, height]
+ * @param {goog.NumberArray} b Array [x, y, width, height]
+ * @return {Array<number>}
+ */
+deMath.intersect = function(a, b) {
+ if (a.length != 4)
+ throw new Error('Array "a" must have length 4 but has length: ' + a.length);
+ if (b.length != 4)
+ throw new Error('Array "b" must have length 4 but has length: ' + b.length);
+ var x0 = Math.max(a[0], b[0]);
+ var y0 = Math.max(a[1], b[1]);
+ var x1 = Math.min(a[0] + a[2], b[0] + b[2]);
+ var y1 = Math.min(a[1] + a[3], b[1] + b[3]);
+ var w = Math.max(0, x1 - x0);
+ var h = Math.max(0, y1 - y0);
+
+ return [x0, y0, w, h];
+};
+
+/** deMath.deMathHash
+ * @param {number} a
+ * @return {number}
+ */
+deMath.deMathHash = function(a) {
+ var key = a;
+ key = (key ^ 61) ^ (key >> 16);
+ key = key + (key << 3);
+ key = key ^ (key >> 4);
+ key = key * 0x27d4eb2d; /* prime/odd constant */
+ key = key ^ (key >> 15);
+ return key;
+};
+
+/**
+ * Converts a byte array to a number. Cannot convert numbers larger than 52 bits.
+ * @param {Uint8Array} array
+ * @return {number}
+ */
+deMath.arrayToNumber = function(array) {
+ DE_ASSERT(array.length <= 6 || (array.length == 6 && array[5] <= 127));
+ /** @type {number} */ var result = 0;
+
+ for (var ndx = 0; ndx < array.length; ndx++) {
+ result += array[ndx] * Math.pow(256, ndx);
+ }
+
+ return result;
+};
+
+/**
+ * Fills a byte array with a number
+ * @param {Uint8Array} array Output array (already resized)
+ * @param {number} number
+ */
+deMath.numberToArray = function(array, number) {
+ DE_ASSERT(Number.isInteger(number));
+ for (var byteNdx = 0; byteNdx < array.length; byteNdx++) {
+ /** @type {number} */ var acumzndx = !byteNdx ? number : Math.floor(number / Math.pow(256, byteNdx));
+ array[byteNdx] = acumzndx & 0xFF;
+ }
+};
+
+/**
+ * Obtains the bit fragment from a number
+ * @param {number} x
+ * @param {number} firstNdx
+ * @param {number} lastNdx
+ * @return {number}
+ */
+deMath.getBitRange = function(x, firstNdx, lastNdx) {
+ DE_ASSERT(lastNdx - firstNdx <= 52);
+ var shifted = deMath.shiftRight(x, firstNdx);
+ var bitSize = lastNdx - firstNdx;
+ var mask;
+ if (bitSize < 32)
+ mask = (1 << bitSize) - 1;
+ else
+ mask = Math.pow(2, bitSize) - 1;
+ var masked = deMath.binaryAnd(shifted, mask);
+ return masked;
+};
+
+/**
+ * Obtains the bit fragment from a Uint32Array representing a number.
+ * (ArrayBuffer representations are used in tcuFloat.)
+ *
+ * Cannot return more than 52 bits ((lastNdx - firstNdx) <= 52).
+ *
+ * @param {Uint32Array} array
+ * @param {number} firstNdx
+ * @param {number} lastNdx
+ * @return {number}
+ */
+deMath.getArray32BitRange = function(array, firstNdx, lastNdx) {
+ DE_ASSERT(0 <= firstNdx && firstNdx < (array.length * 32));
+ DE_ASSERT(0 < lastNdx && lastNdx <= (array.length * 32));
+ DE_ASSERT((lastNdx - firstNdx) <= 52);
+
+ // Example of how this works for a 64-bit number (Uint32Array of length 2).
+ //
+ // * Note that the shift operators in the code << and >>> are pointing in
+ // the opposite direction of this diagram, since LSB is shown on the left.
+ //
+ // [array[0], array[1] ]
+ // [00000011111111111111111111111111, 11111111111100000000000000000000]
+ // ^LSB MSB^ ^LSB MSB^
+ //
+ // [00000011111111111111111111111111, 11111111111100000000000000000000]
+ // \ \
+ // firstNdx = 6 (inclusive) lastNdx = 44 (exclusive)
+ // blockIndexA = 0 blockIndexB = 1
+ //
+ // [00000011111111111111111111111111, 11111111111100000000000000000000]
+ // \-----\ \-------------------\
+ // bitsToBeginningOfBlock = 6 bitsFromEndOfBlock = 20
+ //
+ // -------------blockA------------- -------------blockB-------------
+ // [00000011111111111111111111111111, 11111111111100000000000000000000]
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
+ // blockATruncated blockBTruncated
+ // \--blockATruncatedLength--\
+ //
+ // 11111111111111111111111111 111111111111
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^ return value (38 bits)
+
+ /** @type {number} */ var blockIndexA = Math.floor(firstNdx / 32);
+ /** @type {number} */ var bitsToBeginningOfBlock = firstNdx % 32;
+ /** @type {number} */ var blockIndexB = Math.floor((lastNdx - 1) / 32);
+ /** @type {number} */ var bitsFromEndOfBlock = 31 - ((lastNdx - 1) % 32);
+
+ /** @type {number} */ var blockB = array[blockIndexB];
+ // Chop off the most significant `bitsFromEndOfBlock` bits from blockB.
+ // Note: Initially this logic used a bitmask instead. But there are subtle
+ // corner cases in JS that caused results to sometimes come out negative.
+ // This truncation method is just used to avoid that complexity.
+ /** @type {number} */ var blockBTruncated = (blockB << bitsFromEndOfBlock) >>> bitsFromEndOfBlock;
+
+ if (blockIndexA == blockIndexB) {
+ // firstNdx and lastNdx are in the same block.
+ // Chop off the least significant `bitsToBeginningOfBlock` bits from blockBTruncated.
+ return blockBTruncated >>> bitsToBeginningOfBlock;
+ } else {
+ // firstNdx and lastNdx are in different blocks.
+ /** @type {number} */ var blockA = array[blockIndexA];
+ // Chop off the least significant `bitsToBeginningOfBlock` bits from blockA.
+ /** @type {number} */ var blockATruncated = blockA >>> bitsToBeginningOfBlock;
+ /** @type {number} */ var blockATruncatedLength = 32 - bitsToBeginningOfBlock;
+
+ // Concatenate blockATruncated and blockBTruncated.
+ // Conceptually equivalent to:
+ // blockATruncated | (blockBTruncated << blockATruncatedLength)
+ // except that wouldn't work for numbers larger than 32 bits.
+ return blockATruncated + (blockBTruncated * Math.pow(2, blockATruncatedLength));
+ }
+};
+
+/**
+ * Split a large signed number into low and high 32bit dwords.
+ * @param {number} x
+ * @return {Array<number>}
+ */
+deMath.split32 = function(x) {
+ var ret = [];
+ ret[1] = Math.floor(x / 0x100000000);
+ ret[0] = x - ret[1] * 0x100000000;
+ return ret;
+};
+
+/**
+ * Split a signed number's low 32bit dwords into low and high 16bit dwords.
+ * @param {number} x
+ * @return {Array<number>}
+ */
+deMath.split16 = function(x) {
+ var ret = [];
+ x = x & 0xffffffff;
+ ret[1] = Math.floor(x / 0x10000);
+ ret[0] = x - ret[1] * 0x10000;
+ return ret;
+};
+
+/**
+ * Recontruct a number from high and low 32 bit dwords
+ * @param {Array<number>} x
+ * @return {number}
+ */
+deMath.join32 = function(x) {
+ var v0 = x[0] >= 0 ? x[0] : 0x100000000 + x[0];
+ var v1 = x[1];
+ var val = v1 * 0x100000000 + v0;
+ return val;
+};
+
+//Bit operations with the help of arrays
+
+/**
+ * @enum
+ */
+deMath.BinaryOp = {
+ AND: 0,
+ OR: 1,
+ XOR: 2
+};
+
+/**
+ * Performs a normal (native) binary operation
+ * @param {number} valueA First operand
+ * @param {number} valueB Second operand
+ * @param {deMath.BinaryOp} operation The desired operation to perform
+ * @return {number}
+ */
+deMath.doNativeBinaryOp = function(valueA, valueB, operation) {
+ switch (operation) {
+ case deMath.BinaryOp.AND:
+ return valueA & valueB;
+ case deMath.BinaryOp.OR:
+ return valueA | valueB;
+ case deMath.BinaryOp.XOR:
+ return valueA ^ valueB;
+ default:
+ throw new Error('Unknown operation: ' + operation);
+ }
+};
+
+/**
+ * Performs a binary operation between two operands
+ * with the help of arrays to avoid losing the internal binary representation.
+ * @param {number} valueA First operand
+ * @param {number} valueB Second operand
+ * @param {deMath.BinaryOp} binaryOpParm The desired operation to perform
+ * @return {number}
+ */
+deMath.binaryOp = function(valueA, valueB, binaryOpParm) {
+ //quick path if values fit in signed 32 bit range
+ if (deMath.deInRange32(valueA, -0x80000000, 0x7FFFFFFF) && deMath.deInRange32(valueB, -0x80000000, 0x7FFFFFFF))
+ return deMath.doNativeBinaryOp(valueA, valueB, binaryOpParm);
+
+ var x = deMath.split32(valueA);
+ var y = deMath.split32(valueB);
+ var z = [];
+ for (var i = 0; i < 2; i++)
+ z[i] = deMath.doNativeBinaryOp(x[i], y[i], binaryOpParm);
+ var ret = deMath.join32(z);
+ return ret;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+deMath.binaryAnd = function(a, b) {
+ return deMath.binaryOp(a, b, deMath.BinaryOp.AND);
+};
+
+/**
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>}
+ */
+deMath.binaryAndVecScalar = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('First argument must be an array.');
+ if (typeof b !== 'number')
+ throw new Error('Second argument must be a number.');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(deMath.binaryOp(a[i], b, deMath.BinaryOp.AND));
+ return dst;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+deMath.binaryOr = function(a, b) {
+ return deMath.binaryOp(a, b, deMath.BinaryOp.OR);
+};
+
+/**
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>}
+ */
+deMath.binaryOrVecScalar = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('First argument must be an array.');
+ if (typeof b !== 'number')
+ throw new Error('Second argument must be a number.');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(deMath.binaryOp(a[i], b, deMath.BinaryOp.OR));
+ return dst;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+deMath.binaryXor = function(a, b) {
+ return deMath.binaryOp(a, b, deMath.BinaryOp.XOR);
+};
+
+/**
+ * @param {goog.NumberArray} a
+ * @param {number} b
+ * @return {Array<number>}
+ */
+deMath.binaryXorVecScalar = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('First argument must be an array.');
+ if (typeof b !== 'number')
+ throw new Error('Second argument must be a number.');
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(deMath.binaryOp(a[i], b, deMath.BinaryOp.XOR));
+ return dst;
+};
+
+/**
+ * Performs a binary NOT operation on an operand
+ * @param {number} value Operand
+ * @return {number}
+ */
+deMath.binaryNot = function(value) {
+ //quick path if value fits in signed 32 bit range
+ if (deMath.deInRange32(value, -0x80000000, 0x7FFFFFFF))
+ return ~value;
+
+ var x = deMath.split32(value);
+ x[0] = ~x[0];
+ x[1] = ~x[1];
+ var ret = deMath.join32(x);
+ return ret;
+};
+
+/**
+ * Shifts the given value 'steps' bits to the left. Replaces << operator
+ * This function should be used if the expected value will be wider than 32-bits.
+ * @param {number} value
+ * @param {number} steps
+ * @return {number}
+ */
+deMath.shiftLeft = function(value, steps) {
+ //quick path
+ if (steps < 31) {
+ var v = value * (1 << steps);
+ if (deMath.deInRange32(v, -0x80000000, 0x7FFFFFFF))
+ return v;
+ }
+
+ if (steps == 0)
+ return value;
+ else if (steps < 32) {
+ var mask = (1 << 32 - steps) - 1;
+ var x = deMath.split32(value);
+ var highBits = x[0] & (~mask);
+ var y = highBits >> (32 - steps);
+ if (highBits < 0) {
+ var m = (1 << steps) - 1;
+ y &= m;
+ }
+ var result = [];
+ result[0] = x[0] << steps;
+ result[1] = x[1] << steps;
+ result[1] |= y;
+
+ return deMath.join32(result);
+ } else {
+ var x = deMath.split32(value);
+ var result = [];
+ result[0] = 0;
+ result[1] = x[0] << steps - 32;
+ return deMath.join32(result);
+ }
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {number} b
+ */
+deMath.shiftLeftVecScalar = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(deMath.shiftLeft(a[i], b));
+ return dst;
+};
+
+/**
+ * Shifts the given value 'steps' bits to the right. Replaces >> operator
+ * This function should be used if the value is wider than 32-bits
+ * @param {number} value
+ * @param {number} steps
+ * @return {number}
+ */
+deMath.shiftRight = function(value, steps) {
+ //quick path
+ if (deMath.deInRange32(value, -0x80000000, 0x7FFFFFFF) && steps < 32)
+ return value >> steps;
+
+ if (steps == 0)
+ return value;
+ else if (steps < 32) {
+ if (steps == 0)
+ return value;
+ var mask = (1 << steps) - 1;
+ var x = deMath.split32(value);
+ var lowBits = x[1] & mask;
+ var result = [];
+ var m = (1 << 32 - steps) - 1;
+ result[0] = (x[0] >> steps) & m;
+ result[1] = x[1] >> steps;
+ result[0] |= lowBits << 32 - steps;
+ return deMath.join32(result);
+ } else {
+ var x = deMath.split32(value);
+ var result = [];
+ result[0] = x[1] >> steps - 32;
+ result[1] = value < 0 ? -1 : 0;
+ return deMath.join32(result);
+ }
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {number} b
+ */
+deMath.shiftRightVecScalar = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < a.length; i++)
+ dst.push(deMath.shiftRight(a[i], b));
+ return dst;
+};
+
+/** deMath.logicalAndBool over two arrays of booleans
+ * @param {Array<boolean>} a
+ * @param {Array<boolean>} b
+ * @return {Array<boolean>}
+ */
+deMath.logicalAndBool = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a);
+ if (!Array.isArray(b))
+ throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b);
+ if (a.length != b.length)
+ throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')');
+
+ /** @type {Array<boolean>} */ var result = [];
+ for (var i = 0; i < a.length; i++) {
+ if (a[i] & b[i])
+ result.push(true);
+ else
+ result.push(false);
+ }
+ return result;
+};
+
+/** deMath.logicalOrBool over two arrays of booleans
+ * @param {Array<boolean>} a
+ * @param {Array<boolean>} b
+ * @return {Array<boolean>}
+ */
+deMath.logicalOrBool = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a);
+ if (!Array.isArray(b))
+ throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b);
+ if (a.length != b.length)
+ throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')');
+
+ /** @type {Array<boolean>} */ var result = [];
+ for (var i = 0; i < a.length; i++) {
+ if (a[i] | b[i])
+ result.push(true);
+ else
+ result.push(false);
+ }
+ return result;
+};
+
+/** deMath.logicalNotBool over an array of booleans
+ * @param {Array<boolean>} a
+ * @return {Array<boolean>}
+ */
+deMath.logicalNotBool = function(a) {
+ if (!Array.isArray(a))
+ throw new Error('The passed value is not an array: (' + typeof(a) + ')' + a);
+
+ /** @type {Array<boolean>} */ var result = [];
+ for (var i = 0; i < a.length; i++)
+ result.push(!a[i]);
+ return result;
+};
+
+/** deMath.greaterThan over two arrays of booleans
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<boolean>}
+ */
+deMath.greaterThan = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a);
+ if (!Array.isArray(b))
+ throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b);
+ if (a.length != b.length)
+ throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')');
+
+ /** @type {Array<boolean>} */ var result = [];
+ for (var i = 0; i < a.length; i++)
+ result.push(a[i] > b[i]);
+ return result;
+};
+
+/** deMath.greaterThan over two arrays of booleans
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<boolean>}
+ */
+deMath.greaterThanEqual = function(a, b) {
+ if (!Array.isArray(a))
+ throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a);
+ if (!Array.isArray(b))
+ throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b);
+ if (a.length != b.length)
+ throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')');
+
+ /** @type {Array<boolean>} */ var result = [];
+ for (var i = 0; i < a.length; i++)
+ result.push(a[i] >= b[i]);
+ return result;
+};
+
+/**
+ * Array of float to array of int (0, 255)
+ * @param {Array<number>} a
+ * @return {Array<number>}
+ */
+
+deMath.toIVec = function(a) {
+ /** @type {Array<number>} */ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res.push(deMath.clamp(Math.floor(a[i] * 255), 0, 255));
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+ deMath.clz32 = function(a) {
+ /** @type {number} */ var maxValue = 2147483648; // max 32 bit number
+ /** @type {number} */ var leadingZeros = 0;
+ while (a < maxValue) {
+ maxValue = maxValue >>> 1;
+ leadingZeros++;
+ }
+ return leadingZeros;
+};
+
+/**
+ * @param {number} a
+ * @param {number} exponent
+ * @return {number}
+ */
+deMath.deLdExp = function(a, exponent) {
+ return deMath.ldexp(a, exponent);
+};
+
+/**
+ * @param {number} a
+ * @param {number} exponent
+ * @return {number}
+ */
+deMath.deFloatLdExp = function(a, exponent) {
+ return deMath.ldexp(a, exponent);
+};
+
+/**
+ * @param {number} value
+ * @return {Array<number>}
+ */
+deMath.frexp = (function() {
+ var data = new DataView(new ArrayBuffer(8));
+
+ return function(value) {
+ if (value === 0) return [value, 0];
+ data.setFloat64(0, value);
+ var bits = (data.getUint32(0) >>> 20) & 0x7FF;
+ if (bits === 0) {
+ data.setFloat64(0, value * Math.pow(2, 64));
+ bits = ((data.getUint32(0) >>> 20) & 0x7FF) - 64;
+ }
+ var exponent = bits - 1022,
+ mantissa = deMath.ldexp(value, -exponent);
+ return [mantissa, exponent];
+ }
+})();
+
+/**
+ * @param {number} mantissa
+ * @param {number} exponent
+ * @return {number}
+ */
+deMath.ldexp = function(mantissa, exponent) {
+ return exponent > 1023 ? // avoid multiplying by infinity
+ mantissa * Math.pow(2, 1023) * Math.pow(2, exponent - 1023) :
+ exponent < -1074 ? // avoid multiplying by zero
+ mantissa * Math.pow(2, -1074) * Math.pow(2, exponent + 1074) :
+ mantissa * Math.pow(2, exponent);
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+deMath.deCbrt = function(a) {
+ return deMath.deSign(a) * Math.pow(Math.abs(a), 1.0 / 3.0);
+};
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+deMath.deSign = function(x) {
+ return isNaN(x) ? x : ((x > 0.0) - (x < 0.0));
+};
+
+deMath.deFractExp = function(x) {
+ var result = {
+ significand: x,
+ exponent: 0
+ };
+
+ if (isFinite(x)) {
+ var r = deMath.frexp(x);
+ result.exponent = r[1] - 1;
+ result.significand = r[0] * 2;
+ }
+ return result;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js
new file mode 100644
index 0000000000..2246a2e9d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js
@@ -0,0 +1,260 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This class allows one to create a random integer, floating point number or boolean (TODO, deRandom.choose random items from a list and deRandom.shuffle an array)
+ */
+'use strict';
+goog.provide('framework.delibs.debase.deRandom');
+
+goog.scope(function() {
+
+var deRandom = framework.delibs.debase.deRandom;
+
+/**
+ * Array of pseudo random numbers based on seed
+ * @constructor
+ * @struct
+ */
+deRandom.deRandom = function() {
+ /** @type {number} */ this.x = 0;
+ /** @type {number} */ this.y = 0;
+ /** @type {number} */ this.z = 0;
+ /** @type {number} */ this.w = 0;
+};
+
+/**
+ * deRandom.Random number generator init
+ * @param {deRandom.deRandom} rnd Array to store random numbers
+ * @param {number} seed Number for seed
+ */
+deRandom.deRandom_init = function(rnd, seed) {
+ rnd.x = (-seed ^ 123456789);
+ rnd.y = (362436069 * seed);
+ rnd.z = (521288629 ^ (seed >> 7));
+ rnd.w = (88675123 ^ (seed << 3));
+};
+
+/**
+ * Function to get random int
+ * @param {deRandom.deRandom} rnd Initialised array of random numbers
+ * @param {Array<number>=} opts Min and max for range
+ * @return {number} deRandom.Random int
+ */
+deRandom.deRandom_getInt = function(rnd, opts) {
+ if (opts != undefined && opts[0] != undefined && opts[1] != undefined) {
+ if (opts[0] == 0x80000000 && opts[1] == 0x7fffffff) {
+ return deRandom.deRandom_getInt(rnd);
+ } else {
+ return opts[0] + (deRandom.deRandom_getInt(rnd) % (opts[1] - opts[0] + 1));
+ }
+ }
+ var w = rnd.w;
+ var t;
+
+ t = rnd.x ^ (rnd.x << 11);
+ rnd.x = rnd.y;
+ rnd.y = rnd.z;
+ rnd.z = w;
+ rnd.w = w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
+ return w;
+};
+
+/**
+ * Function to get random float
+ * @param {deRandom.deRandom} rnd Initialised array of random numbers
+ * @param {Array<number>=} opts Min and max for range
+ * @return {number} deRandom.Random float
+ */
+deRandom.deRandom_getFloat = function(rnd, opts) {
+ if (opts != undefined && opts[0] != undefined && opts[1] != undefined) {
+ if (opts[0] <= opts[1]) {
+ return opts[0] + (opts[1] - opts[0]) * deRandom.deRandom_getFloat(rnd);
+ }
+ } else {
+ return (deRandom.deRandom_getInt(rnd) & 0xFFFFFFF) / (0xFFFFFFF + 1);
+ }
+ throw new Error('Invalid arguments');
+};
+
+/**
+ * Function to get random boolean
+ * @param {deRandom.deRandom} rnd Initialised array of random numbers
+ * @return {boolean} deRandom.Random boolean
+ */
+deRandom.deRandom_getBool = function(rnd) {
+ var val;
+ val = deRandom.deRandom_getInt(rnd);
+ return ((val & 0xFFFFFF) < 0x800000);
+};
+
+/**
+ * Function to get a common base seed
+ * @return {number} constant
+ */
+deRandom.getBaseSeed = function() {
+ return 42;
+};
+
+/**
+ * TODO Function to deRandom.choose random items from a list
+ * @template T
+ * @param {deRandom.deRandom} rnd Initialised array of random numbers
+ * @param {Array<T>} elements Array segment already defined
+ * @param {Array<T>=} resultOut Array where to store the elements in. If undefined, default to array of (num) elements.
+ * @param {number=} num Number of items to store in resultOut. If undefined, default to 1.
+ * @return {Array<T>} Even though result is stored in resultOut, return it here as well.
+ */
+deRandom.choose = function(rnd, elements, resultOut, num) {
+ var items = num || 1;
+ var temp = elements.slice();
+ if (!resultOut)
+ resultOut = [];
+
+ while (items-- > 0) {
+ var index = deRandom.deRandom_getInt(rnd, [0, temp.length - 1]);
+ resultOut.push(temp[index]);
+ temp.splice(index, 1);
+ }
+ return resultOut;
+};
+
+/**
+ * TODO Function to deRandom.choose weighted random items from a list
+ * @param {deRandom.deRandom} rnd Initialised randomizer
+ * @param {Array<number>} array Array to choose items from
+ * @param {Array<number>} weights Weights array
+ * @return {number} Result output
+ */
+deRandom.chooseWeighted = function(rnd, array, weights) {
+ // Compute weight sum
+ /** @type {number} */ var weightSum = 0.0;
+ /** @type {number} */ var ndx;
+ for (ndx = 0; ndx < array.length; ndx++)
+ weightSum += weights[ndx];
+
+ // Random point in 0..weightSum
+ /** @type {number} */ var p = deRandom.deRandom_getFloat(rnd, [0.0, weightSum]);
+
+ // Find item in range
+ /** @type {number} */ var lastNonZero = array.length;
+ /** @type {number} */ var curWeight = 0.0;
+ for (ndx = 0; ndx != array.length; ndx++) {
+ /** @type {number} */ var w = weights[ndx];
+
+ curWeight += w;
+
+ if (p < curWeight)
+ return array[ndx];
+ else if (w > 0.0)
+ lastNonZero = ndx;
+ }
+
+ assertMsgOptions(lastNonZero != array.length, 'Index went out of bounds', false, true);
+ return array[lastNonZero];
+};
+
+/**
+ * TODO Function to deRandom.shuffle an array
+ * @param {deRandom.deRandom} rnd Initialised array of random numbers
+ * @param {Array} elements Array to deRandom.shuffle
+ * @return {Array} Shuffled array
+ */
+deRandom.shuffle = function(rnd, elements) {
+ var index = elements.length;
+
+ while (index > 0) {
+ var random = deRandom.deRandom_getInt(rnd, [0, index - 1]);
+ index -= 1;
+ var elem = elements[index];
+ elements[index] = elements[random];
+ elements[random] = elem;
+ }
+ return elements;
+};
+
+/**
+ * This function is used to create the deRandom.Random object and
+ * initialise the random number with a seed.
+ * It contains functions for generating random numbers in a variety of formats
+ * @constructor
+ * @param {number} seed Number to use as a seed
+ */
+deRandom.Random = function(seed) {
+ /**
+ * Instance of array of pseudo random numbers based on seeds
+ */
+ this.m_rnd = new deRandom.deRandom();
+
+ //initialise the random numbers based on seed
+ deRandom.deRandom_init(this.m_rnd, seed);
+};
+
+/**
+ * Function to get random boolean
+ * @return {boolean} deRandom.Random boolean
+ */
+deRandom.Random.prototype.getBool = function() { return deRandom.deRandom_getBool(this.m_rnd) == true; };
+/**
+ * Function to get random float
+ * @param {number=} min Min for range
+ * @param {number=} max Max for range
+ * @return {number} deRandom.Random float
+ */
+deRandom.Random.prototype.getFloat = function(min, max) { return deRandom.deRandom_getFloat(this.m_rnd, [min, max]) };
+/**
+ * Function to get random int
+ * @param {number=} min Min for range
+ * @param {number=} max Max for range
+ * @return {number} deRandom.Random int
+ */
+deRandom.Random.prototype.getInt = function(min, max) {return deRandom.deRandom_getInt(this.m_rnd, [min, max])};
+/**
+ * TODO Function to deRandom.choose random items from a list
+ * @template T
+ * @param {Array<T>} elements Array segment already defined
+ * @param {Array<T>=} resultOut Array where to store the elements in. If undefined, default to array of (num) elements.
+ * @param {number=} num Number of items to store in resultOut. If undefined, default to 1.
+ * @return {Array<T>} Even though result is stored in resultOut, return it here as well.
+ */
+deRandom.Random.prototype.choose = function(elements, resultOut, num) {return deRandom.choose(this.m_rnd, elements, resultOut, num)};
+/**
+ * choose weighted random items from a list
+ * @param {Array<number>} array Array to choose items from
+ * @param {Array<number>} weights Weights array
+ * @return {number} Result output
+ */
+deRandom.Random.prototype.chooseWeighted = function(array, weights) {return deRandom.chooseWeighted(this.m_rnd, array, weights)};
+/**
+ * TODO Function to deRandom.shuffle an array
+ * @param {Array} elements Array to deRandom.shuffle
+ * @return {Array} Shuffled array
+ */
+deRandom.Random.prototype.shuffle = function(elements) {return deRandom.shuffle(this.m_rnd, elements)};
+
+/**
+ * Function to get a common base seed
+ * @return {number} constant
+ */
+deRandom.Random.prototype.getBaseSeed = function() {
+ return deRandom.getBaseSeed();
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js
new file mode 100644
index 0000000000..fc84a72327
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js
@@ -0,0 +1,111 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This class allows one to create a random integer, floating point number or boolean (TODO, choose random items from a list and shuffle an array)
+ */
+'use strict';
+goog.provide('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var deString = framework.delibs.debase.deString;
+var deMath = framework.delibs.debase.deMath;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * Compute hash from string.
+ * @param {?string} str String to compute hash value for.
+ * @return {number} Computed hash value.
+ */
+ deString.deStringHash = function(str) {
+ /* \note [pyry] This hash is used in DT_GNU_HASH and is proven
+ to be robust for symbol hashing. */
+ /* \see http://sources.redhat.com/ml/binutils/2006-06/msg00418.html */
+ /** @type {number} */ var hash = 5381;
+ /** @type {number} */ var c;
+
+ DE_ASSERT(str != undefined);
+ if (str !== null) {
+ var i = 0;
+ while (i < str.length) { //(c = (unsigned int)*str++) != 0)
+ c = str.charCodeAt(i); //trunc to 8-bit
+ hash = (hash << 5) + hash + c;
+ i++;
+ }
+ }
+ return hash;
+ };
+
+ /**
+ * Checks if a JS string is either empty or undefined
+ * @param {string} str
+ * @return {boolean}
+ */
+ deString.deIsStringEmpty = function(str) {
+ if (str === undefined || str.length == 0)
+ return true;
+ return false;
+ };
+
+ /**
+ * @private
+ * @param {Object} enumType
+ * @param {?} value
+ * @return {string}
+ */
+ deString.getString = function(enumType, value) {
+ for (var p in enumType)
+ if (enumType[p] == value)
+ return p;
+
+ if (typeof value === 'undefined')
+ return 'undefined';
+
+ if (!value)
+ return 'null';
+
+ return value.toString(10);
+ };
+
+ /**
+ * @param {Object} enumType
+ * @param {?} value
+ * @return {string}
+ */
+ deString.enumToString = function(enumType, value) {
+ if (typeof deString.enumToString[enumType] === 'undefined')
+ deString.enumToString[enumType] = {};
+
+ var table = deString.enumToString[enumType];
+ if (typeof table[value] === 'undefined') {
+ var v = deString.getString(enumType, value);
+ table[value] = v;
+ }
+
+ return table[value];
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js
new file mode 100644
index 0000000000..56a90b6ff6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.delibs.debase.deUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+ var deUtil = framework.delibs.debase.deUtil;
+ var deMath = framework.delibs.debase.deMath;
+
+ //! Get an element of an array with a specified size.
+ /**
+ * @param {Array} array
+ * @param {number} offset
+ * @return {*}
+ */
+ deUtil.getArrayElement = function(array, offset) {
+ assertMsgOptions(deMath.deInBounds32(offset, 0, array.length), 'Array element out of bounds', false, true);
+ return array[offset];
+ };
+
+ /**
+ * clone - If you need to pass/assign an object by value, call this
+ * @param {*} obj
+ * @return {*}
+ */
+ deUtil.clone = function(obj) {
+ if (obj == null || typeof(obj) != 'object')
+ return obj;
+
+ var temp = {};
+ if (ArrayBuffer.isView(obj)) {
+ temp = new obj.constructor(obj);
+ } else if (obj instanceof Array) {
+ temp = new Array(obj.length);
+ for (var akey in obj)
+ temp[akey] = deUtil.clone(obj[akey]);
+ } else if (obj instanceof ArrayBuffer) {
+ temp = new ArrayBuffer(obj.byteLength);
+ var dst = new Uint8Array(temp);
+ var src = new Uint8Array(obj);
+ dst.set(src);
+ } else {
+ temp = Object.create(obj.constructor.prototype);
+ temp.constructor = obj.constructor;
+ for (var key in obj)
+ temp[key] = deUtil.clone(obj[key]);
+ }
+ return temp;
+ };
+
+ /**
+ * Add a push_unique function to Array. Will insert only if there is no equal element.
+ * @template T
+ * @param {Array<T>} array Any array
+ * @param {T} object Any object
+ */
+ deUtil.dePushUniqueToArray = function(array, object) {
+ //Simplest implementation
+ for (var i = 0; i < array.length; i++) {
+ if (object.equals !== undefined)
+ if (object.equals(array[i]))
+ return undefined;
+ else if (object === array[i])
+ return undefined;
+ }
+
+ array.push(object);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluDrawUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluDrawUtil.js
new file mode 100644
index 0000000000..baa05a9708
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluDrawUtil.js
@@ -0,0 +1,510 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+
+var gluDrawUtil = framework.opengl.gluDrawUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+/**
+ * Description of a vertex array binding
+ * @constructor
+ * @param {number} type GL gluDrawUtil.Type of data
+ * @param {(number|undefined)} location Binding location
+ * @param {number} components Number of components per vertex
+ * @param {number} elements Number of elements in the array
+ * @param {Array<number>} data Source data
+ * @param {number=} stride
+ * @param {number=} offset
+ */
+gluDrawUtil.VertexArrayBinding = function(type, location, components, elements, data, stride, offset) {
+ this.type = type;
+ this.location = location === undefined ? -1 : location;
+ this.components = components;
+ this.elements = elements;
+ this.data = data;
+ /** @type {?string} */ this.name = null;
+ this.stride = stride || 0;
+ this.offset = offset || 0;
+};
+
+/**
+ * Description of a vertex array binding
+ * @param {gluDrawUtil.BindingPoint} binding
+ * @param {gluDrawUtil.VertexArrayPointer} pointer
+ * @param {number=} dataType GL Data Type
+ * @return {gluDrawUtil.VertexArrayBinding}
+ */
+gluDrawUtil.vabFromBindingPointAndArrayPointer = function(binding, pointer, dataType) {
+ var type = dataType === undefined ? gl.FLOAT : dataType;
+ var location = binding.location;
+ var components = pointer.numComponents;
+ var elements = pointer.numElements;
+ var data = pointer.data;
+ var vaBinding = new gluDrawUtil.VertexArrayBinding(type, location, components, elements, data);
+ vaBinding.componentType = pointer.componentType;
+ vaBinding.name = binding.name;
+ vaBinding.convert = pointer.convert;
+ vaBinding.stride = pointer.stride;
+ return vaBinding;
+};
+
+/**
+ * ! Lower named bindings to locations and eliminate bindings that are not used by program.
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {WebGLProgram} program
+ * @param {Array} inputArray - Array with the named binding locations
+ * @param {Array=} outputArray - Array with the lowered locations
+ * @return {Array} outputArray
+ */
+gluDrawUtil.namedBindingsToProgramLocations = function(gl, program, inputArray, outputArray) {
+ outputArray = outputArray || [];
+
+ for (var i = 0; i < inputArray.length; i++) {
+ var cur = inputArray[i];
+ if (cur.name) {
+ //assert(binding.location >= 0);
+ var location = gl.getAttribLocation(program, cur.name);
+ if (location >= 0) {
+ if (cur.location >= 0)
+ location += cur.location;
+ // Add binding.location as an offset to accomodate matrices.
+ outputArray.push(new gluDrawUtil.VertexArrayBinding(cur.type, location, cur.components, cur.elements, cur.data, cur.stride, cur.offset));
+ }
+ } else {
+ outputArray.push(cur);
+ }
+ }
+
+ return outputArray;
+};
+
+/**
+ * Creates vertex buffer, binds it and draws elements
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {WebGLProgram} program ID, vertexProgramID
+ * @param {Array<gluDrawUtil.VertexArrayBinding>} vertexArrays
+ * @param {gluDrawUtil.PrimitiveList} primitives to gluDrawUtil.draw
+ * @param { {beforeDrawCall:function(), afterDrawCall:function()}=} callback
+ */
+gluDrawUtil.draw = function(gl, program, vertexArrays, primitives, callback) {
+ /** TODO: finish implementation */
+ /** @type {Array<WebGLBuffer>} */ var objects = [];
+
+ // Lower bindings to locations
+ vertexArrays = gluDrawUtil.namedBindingsToProgramLocations(gl, program, vertexArrays);
+
+ for (var i = 0; i < vertexArrays.length; i++) {
+ /** @type {WebGLBuffer} */ var buffer = gluDrawUtil.vertexBuffer(gl, vertexArrays[i]);
+ objects.push(buffer);
+ }
+
+ if (primitives.indices) {
+ /** @type {WebGLBuffer} */ var elemBuffer = gluDrawUtil.indexBuffer(gl, primitives);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elemBuffer);
+
+ if (callback)
+ callback.beforeDrawCall();
+
+ gluDrawUtil.drawIndexed(gl, primitives, 0);
+
+ if (callback)
+ callback.afterDrawCall();
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ } else {
+ if (callback)
+ callback.beforeDrawCall();
+
+ gl.drawArrays(gluDrawUtil.getPrimitiveGLType(gl, primitives.type), 0, primitives.numElements);
+
+ if (callback)
+ callback.afterDrawCall();
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'drawArrays', false, true);
+ for (var i = 0; i < vertexArrays.length; i++) {
+ gl.disableVertexAttribArray(vertexArrays[i].location);
+ }
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+};
+
+/**
+ * Creates vertex buffer, binds it and draws elements
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluDrawUtil.PrimitiveList} primitives Primitives to gluDrawUtil.draw
+ * @param {number} offset
+ */
+gluDrawUtil.drawIndexed = function(gl, primitives, offset) {
+/** @type {number} */ var mode = gluDrawUtil.getPrimitiveGLType(gl, primitives.type);
+ /** TODO: C++ implementation supports different index types, we use only int16.
+ Could it cause any issues?
+
+ deUint32 indexGLType = getIndexGLType(primitives.indexType);
+ */
+
+ gl.drawElements(mode, primitives.indices.length, gl.UNSIGNED_SHORT, offset);
+};
+
+/**
+ * Enums for primitive types
+ * @enum
+ */
+gluDrawUtil.primitiveType = {
+ TRIANGLES: 0,
+ TRIANGLE_STRIP: 1,
+ TRIANGLE_FAN: 2,
+
+ LINES: 3,
+ LINE_STRIP: 4,
+ LINE_LOOP: 5,
+
+ POINTS: 6,
+
+ PATCHES: 7
+};
+
+/**
+ * get GL type from primitive type
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluDrawUtil.primitiveType} type gluDrawUtil.primitiveType
+ * @return {number} GL primitive type
+ */
+gluDrawUtil.getPrimitiveGLType = function(gl, type) {
+ switch (type) {
+ case gluDrawUtil.primitiveType.TRIANGLES: return gl.TRIANGLES;
+ case gluDrawUtil.primitiveType.TRIANGLE_STRIP: return gl.TRIANGLE_STRIP;
+ case gluDrawUtil.primitiveType.TRIANGLE_FAN: return gl.TRIANGLE_FAN;
+ case gluDrawUtil.primitiveType.LINES: return gl.LINES;
+ case gluDrawUtil.primitiveType.LINE_STRIP: return gl.LINE_STRIP;
+ case gluDrawUtil.primitiveType.LINE_LOOP: return gl.LINE_LOOP;
+ case gluDrawUtil.primitiveType.POINTS: return gl.POINTS;
+// case gluDrawUtil.primitiveType.PATCHES: return gl.PATCHES;
+ default:
+ throw new Error('Unknown primitive type ' + type);
+ }
+};
+
+/**
+ * Calls gluDrawUtil.newPrimitiveListFromIndices() to create primitive list for Points
+ * @param {number} numElements
+ */
+gluDrawUtil.pointsFromElements = function(numElements) {
+ return new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.POINTS, numElements);
+};
+
+/**
+ * Calls gluDrawUtil.newPrimitiveListFromIndices() to create primitive list for Triangles
+ * @param {Array<number>} indices
+ */
+gluDrawUtil.triangles = function(indices) {
+ return gluDrawUtil.newPrimitiveListFromIndices(gluDrawUtil.primitiveType.TRIANGLES, indices);
+};
+
+/**
+ * Calls gluDrawUtil.newPrimitiveListFromIndices() to create primitive list for Patches
+ * @param {Array<number>} indices
+ */
+gluDrawUtil.patches = function(indices) {
+ return gluDrawUtil.newPrimitiveListFromIndices(gluDrawUtil.primitiveType.PATCHES, indices);
+};
+
+/**
+ * Creates primitive list for Triangles or Patches, depending on type
+ * @param {gluDrawUtil.primitiveType} type gluDrawUtil.primitiveType
+ * @param {number} numElements
+ * @constructor
+ */
+gluDrawUtil.PrimitiveList = function(type, numElements) {
+ this.type = type;
+ this.indices = 0;
+ this.numElements = numElements;
+};
+
+/**
+ * @param {gluDrawUtil.primitiveType} type
+ * @param {Array<number>} indices
+ * @return {gluDrawUtil.PrimitiveList}
+ */
+gluDrawUtil.newPrimitiveListFromIndices = function(type, indices) {
+ /** @type {gluDrawUtil.PrimitiveList} */ var primitiveList = new gluDrawUtil.PrimitiveList(type, 0);
+ primitiveList.indices = indices;
+ return primitiveList;
+};
+
+/**
+ * Create Element Array Buffer
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluDrawUtil.PrimitiveList} primitives to construct the buffer from
+ * @return {WebGLBuffer} indexObject buffer with elements
+ */
+gluDrawUtil.indexBuffer = function(gl, primitives) {
+ /** @type {WebGLBuffer} */ var indexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'bindBuffer', false, true);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(primitives.indices), gl.STATIC_DRAW);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'bufferData', false, true);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ return indexObject;
+};
+
+/**
+ * Create Array Buffer
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluDrawUtil.VertexArrayBinding} vertexArray primitives, Array buffer descriptor
+ * @return {WebGLBuffer} buffer of vertices
+ */
+gluDrawUtil.vertexBuffer = function(gl, vertexArray) {
+ /** @type {goog.TypedArray} */ var typedArray;
+ switch (vertexArray.type) {
+ case gl.BYTE: typedArray = new Int8Array(vertexArray.data); break;
+ case gl.UNSIGNED_BYTE: typedArray = new Uint8Array(vertexArray.data); break;
+ case gl.SHORT: typedArray = new Int16Array(vertexArray.data); break;
+ case gl.UNSIGNED_SHORT: typedArray = new Uint16Array(vertexArray.data); break;
+ case gl.INT: typedArray = new Int32Array(vertexArray.data); break;
+ case gl.UNSIGNED_INT: typedArray = new Uint32Array(vertexArray.data); break;
+ default: typedArray = new Float32Array(vertexArray.data); break;
+ }
+
+ /** @type {WebGLBuffer} */ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'bindBuffer', false, true);
+ gl.bufferData(gl.ARRAY_BUFFER, typedArray, gl.STATIC_DRAW);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'bufferData', false, true);
+ gl.enableVertexAttribArray(vertexArray.location);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'enableVertexAttribArray', false, true);
+ if (vertexArray.type === gl.FLOAT) {
+ gl.vertexAttribPointer(vertexArray.location, vertexArray.components, vertexArray.type, false, vertexArray.stride, vertexArray.offset);
+ } else {
+ gl.vertexAttribIPointer(vertexArray.location, vertexArray.components, vertexArray.type, vertexArray.stride, vertexArray.offset);
+ }
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'vertexAttribPointer', false, true);
+ return buffer;
+};
+
+/**
+ * @param {Array<number>} rgba
+ * @constructor
+ */
+gluDrawUtil.Pixel = function(rgba) {
+ this.rgba = rgba;
+};
+
+gluDrawUtil.Pixel.prototype.getRed = function() {
+ return this.rgba[0];
+};
+gluDrawUtil.Pixel.prototype.getGreen = function() {
+ return this.rgba[1];
+};
+gluDrawUtil.Pixel.prototype.getBlue = function() {
+ return this.rgba[2];
+};
+gluDrawUtil.Pixel.prototype.getAlpha = function() {
+ return this.rgba[3];
+};
+gluDrawUtil.Pixel.prototype.equals = function(otherPixel) {
+ return this.rgba[0] == otherPixel.rgba[0] &&
+ this.rgba[1] == otherPixel.rgba[1] &&
+ this.rgba[2] == otherPixel.rgba[2] &&
+ this.rgba[3] == otherPixel.rgba[3];
+};
+
+/**
+ * @constructor
+ */
+gluDrawUtil.Surface = function() {
+};
+
+gluDrawUtil.Surface.prototype.readSurface = function(gl, x, y, width, height) {
+ this.buffer = new Uint8Array(width * height * 4);
+ gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, this.buffer);
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ return this.buffer;
+};
+
+gluDrawUtil.Surface.prototype.getPixel = function(x, y) {
+ /** @type {number} */ var base = (x + y * this.width) * 4;
+ /** @type {Array<number>} */
+ var rgba = [
+ this.buffer[base],
+ this.buffer[base + 1],
+ this.buffer[base + 2],
+ this.buffer[base + 3]
+ ];
+ return new gluDrawUtil.Pixel(rgba);
+};
+
+gluDrawUtil.Surface.prototype.getPixelUintRGB8 = function(x, y) {
+ /** @type {number} */ var base = (x + y * this.width) * 4;
+ /** @type {number} */
+ return (this.buffer[base] << 16) +
+ (this.buffer[base + 1] << 8) +
+ this.buffer[base + 2];
+};
+
+/**
+ * @enum
+ */
+gluDrawUtil.VertexComponentType = {
+ // Standard types: all conversion types apply.
+ VTX_COMP_UNSIGNED_INT8: 0,
+ VTX_COMP_UNSIGNED_INT16: 1,
+ VTX_COMP_UNSIGNED_INT32: 2,
+ VTX_COMP_SIGNED_INT8: 3,
+ VTX_COMP_SIGNED_INT16: 4,
+ VTX_COMP_SIGNED_INT32: 5,
+
+ // Special types: only CONVERT_NONE is allowed.
+ VTX_COMP_FIXED: 6,
+ VTX_COMP_HALF_FLOAT: 7,
+ VTX_COMP_FLOAT: 8
+};
+
+/**
+ * @enum
+ */
+gluDrawUtil.VertexComponentConversion = {
+ VTX_COMP_CONVERT_NONE: 0, //!< No conversion: integer types, or floating-point values.
+ VTX_COMP_CONVERT_NORMALIZE_TO_FLOAT: 1, //!< Normalize integers to range [0,1] or [-1,1] depending on type.
+ VTX_COMP_CONVERT_CAST_TO_FLOAT: 2 //!< Convert to floating-point directly.
+};
+
+/**
+ * gluDrawUtil.VertexArrayPointer
+ * @constructor
+ * @param {gluDrawUtil.VertexComponentType} componentType_
+ * @param {gluDrawUtil.VertexComponentConversion} convert_
+ * @param {number} numComponents_
+ * @param {number} numElements_
+ * @param {number} stride_
+ * @const @param {Array<number>} data_
+ */
+gluDrawUtil.VertexArrayPointer = function(componentType_, convert_, numComponents_, numElements_, stride_, data_) {
+ this.componentType = componentType_;
+ this.convert = convert_;
+ this.numComponents = numComponents_;
+ this.numElements = numElements_;
+ this.stride = stride_;
+ this.data = data_;
+};
+
+/**
+ * gluDrawUtil.BindingPoint
+ * @constructor
+ * @param {string} name
+ * @param {number} location
+ * @param {number=} offset
+ */
+gluDrawUtil.BindingPoint = function(name, location, offset) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.location = location;
+ /** @type {number} */ this.offset = offset || 0;
+};
+
+/**
+ * bindingPointFromLocation
+ * @param {number} location
+ * return {gluDrawUtil.BindingPoint}
+ */
+gluDrawUtil.bindingPointFromLocation = function(location) {
+ return new gluDrawUtil.BindingPoint('', location);
+};
+
+/**
+ * bindingPointFromName
+ * @param {string} name
+ * @param {number=} location
+ * return {gluDrawUtil.BindingPoint}
+ */
+gluDrawUtil.bindingPointFromName = function(name, location) {
+ location = location === undefined ? -1 : location;
+ return new gluDrawUtil.BindingPoint(name, location);
+};
+
+/**
+ * @param {string} name
+ * @param {number} numComponents
+ * @param {number} numElements
+ * @param {number} stride
+ * @param {Array<number>} data
+ * @return {gluDrawUtil.VertexArrayBinding}
+ */
+gluDrawUtil.newInt32VertexArrayBinding = function(name, numComponents, numElements, stride, data) {
+ var bindingPoint = gluDrawUtil.bindingPointFromName(name);
+ var arrayPointer = new gluDrawUtil.VertexArrayPointer(gluDrawUtil.VertexComponentType.VTX_COMP_SIGNED_INT32,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE, numComponents, numElements, stride, data);
+ return gluDrawUtil.vabFromBindingPointAndArrayPointer(bindingPoint, arrayPointer, gl.INT);
+};
+
+/**
+ * @param {string} name
+ * @param {number} numComponents
+ * @param {number} numElements
+ * @param {number} stride
+ * @param {Array<number>} data
+ * @return {gluDrawUtil.VertexArrayBinding}
+ */
+gluDrawUtil.newUint32VertexArrayBinding = function(name, numComponents, numElements, stride, data) {
+ var bindingPoint = gluDrawUtil.bindingPointFromName(name);
+ var arrayPointer = new gluDrawUtil.VertexArrayPointer(gluDrawUtil.VertexComponentType.VTX_COMP_UNSIGNED_INT32,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE, numComponents, numElements, stride, data);
+ return gluDrawUtil.vabFromBindingPointAndArrayPointer(bindingPoint, arrayPointer, gl.UNSIGNED_INT);
+};
+
+/**
+ * @param {string} name
+ * @param {number} numComponents
+ * @param {number} numElements
+ * @param {number} stride
+ * @param {Array<number>} data
+ * @return {gluDrawUtil.VertexArrayBinding}
+ */
+gluDrawUtil.newFloatVertexArrayBinding = function(name, numComponents, numElements, stride, data) {
+ var bindingPoint = gluDrawUtil.bindingPointFromName(name);
+ var arrayPointer = new gluDrawUtil.VertexArrayPointer(gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE, numComponents, numElements, stride, data);
+ return gluDrawUtil.vabFromBindingPointAndArrayPointer(bindingPoint, arrayPointer);
+};
+
+/**
+ * @param {string} name
+ * @param {number} column
+ * @param {number} rows
+ * @param {number} numElements
+ * @param {number} stride
+ * @param {Array<number>} data
+ * @return {gluDrawUtil.VertexArrayBinding}
+ */
+gluDrawUtil.newFloatColumnVertexArrayBinding = function(name, column, rows, numElements, stride, data) {
+ var bindingPoint = gluDrawUtil.bindingPointFromName(name);
+ bindingPoint.location = column;
+ var arrayPointer = new gluDrawUtil.VertexArrayPointer(gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE, rows, numElements, stride, data);
+ return gluDrawUtil.vabFromBindingPointAndArrayPointer(bindingPoint, arrayPointer);
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluObjectWrapper.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluObjectWrapper.js
new file mode 100644
index 0000000000..38f8a28f9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluObjectWrapper.js
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+
+goog.provide('framework.opengl.gluObjectWrapper');
+
+goog.scope(function() {
+ var gluObjectWrapper = framework.opengl.gluObjectWrapper;
+
+ /**
+ * @typedef {function(this:WebGLRenderingContextBase): WebGLObject}
+ */
+ gluObjectWrapper.funcGenT;
+
+ /**
+ * @typedef {function(this:WebGLRenderingContextBase, WebGLObject)}
+ */
+ gluObjectWrapper.funcDelT;
+
+ /**
+ * @typedef {{name: string, funcGen: !gluObjectWrapper.funcGenT, funcDel: !gluObjectWrapper.funcDelT}}
+ */
+ gluObjectWrapper.traitsT;
+
+ /**
+ * Returns an object containing a configuration for an ObjectWrapper
+ * @param {string} name
+ * @param {gluObjectWrapper.funcGenT} funcGen
+ * @param {gluObjectWrapper.funcDelT} funcDel
+ * @return {gluObjectWrapper.traitsT}
+ */
+ gluObjectWrapper.traits = function(name, funcGen, funcDel) {
+ return {
+ name: name,
+ funcGen: funcGen,
+ funcDel: funcDel
+ };
+ };
+
+ /**
+ * @constructor
+ * @param {WebGLRenderingContextBase} gl
+ * @param {gluObjectWrapper.traitsT} traits
+ */
+ gluObjectWrapper.ObjectWrapper = function(gl, traits) {
+ /**
+ * @protected
+ * @type {WebGLRenderingContextBase}
+ */
+ this.m_gl = gl;
+
+ /**
+ * @protected
+ * @type {gluObjectWrapper.traitsT}
+ */
+ this.m_traits = traits;
+
+ /**
+ * @protected
+ * @type {WebGLObject}
+ */
+ this.m_object = this.m_traits.funcGen.call(gl);
+
+ };
+
+ /**
+ * Destorys the WebGLObject associated with this object.
+ */
+ gluObjectWrapper.ObjectWrapper.prototype.clear = function() {
+ this.m_traits.funcDel.call(this.m_gl, this.m_object);
+ };
+
+ /**
+ * Returns the WebGLObject associated with this object.
+ * @return {WebGLObject}
+ */
+ gluObjectWrapper.ObjectWrapper.prototype.get = function() {
+ return this.m_object;
+ };
+
+ /**
+ * @constructor
+ * @extends {gluObjectWrapper.ObjectWrapper}
+ * @param {WebGLRenderingContextBase} gl
+ */
+ gluObjectWrapper.Framebuffer = function(gl) {
+ gluObjectWrapper.ObjectWrapper.call(this, gl, gluObjectWrapper.traits(
+ 'framebuffer',
+ /** @type {gluObjectWrapper.funcGenT} */(gl.createFramebuffer),
+ /** @type {gluObjectWrapper.funcDelT} */(gl.deleteFramebuffer)
+ ));
+ };
+ gluObjectWrapper.Framebuffer.prototype = Object.create(gluObjectWrapper.ObjectWrapper.prototype);
+ gluObjectWrapper.Framebuffer.prototype.constructor = gluObjectWrapper.Framebuffer;
+
+ /**
+ * @return {WebGLFramebuffer}
+ */
+ gluObjectWrapper.Framebuffer.prototype.get;
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluPixelTransfer.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluPixelTransfer.js
new file mode 100644
index 0000000000..04b81a2a1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluPixelTransfer.js
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluPixelTransfer');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var gluPixelTransfer = framework.opengl.gluPixelTransfer;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+
+gluPixelTransfer.getTransferAlignment = function(format) {
+ var pixelSize = format.getPixelSize();
+ if (deMath.deIsPowerOfTwo32(pixelSize))
+ return Math.min(pixelSize, 8);
+ else
+ return 1;
+};
+
+gluPixelTransfer.readPixels = function(ctx, x, y, format, dst) {
+ var width = dst.getWidth();
+ var height = dst.getHeight();
+ var arrayType = tcuTexture.getTypedArray(format.type);
+ var transferFormat = gluTextureUtil.getTransferFormat(format);
+ ctx.pixelStorei(ctx.PACK_ALIGNMENT, gluPixelTransfer.getTransferAlignment(format));
+ var resultPixel = dst.getAccess().getDataPtr();
+ resultPixel = new arrayType(dst.getAccess().getBuffer());
+ ctx.readPixels(x, y, width, height, transferFormat.format, transferFormat.dataType, resultPixel);
+};
+
+/* TODO: implement other functions in C++ file */
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderProgram.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderProgram.js
new file mode 100644
index 0000000000..0c340ee380
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderProgram.js
@@ -0,0 +1,488 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality gluShaderProgram.Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+/**
+ * gluShaderProgram.Shader type enum
+ * @enum {number}
+ */
+gluShaderProgram.shaderType = {
+ VERTEX: 0,
+ FRAGMENT: 1
+};
+
+/**
+ * gluShaderProgram.Shader type enum name
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {string}
+ */
+gluShaderProgram.getShaderTypeName = function(shaderType) {
+ var s_names =
+ [
+ 'vertex',
+ 'fragment'
+ ];
+
+ return s_names[shaderType];
+};
+
+/**
+ * Get GL shader type from gluShaderProgram.shaderType
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluShaderProgram.shaderType} type gluShaderProgram.Shader Type
+ * @return {number} GL shader type
+ */
+gluShaderProgram.getGLShaderType = function(gl, type) {
+ var _glShaderType;
+ switch (type) {
+ case gluShaderProgram.shaderType.VERTEX: _glShaderType = gl.VERTEX_SHADER; break;
+ case gluShaderProgram.shaderType.FRAGMENT: _glShaderType = gl.FRAGMENT_SHADER; break;
+ default:
+ throw new Error('Unknown shader type ' + type);
+ }
+ return _glShaderType;
+};
+
+/**
+ * Declares shader information
+ * @constructor
+ * @param {gluShaderProgram.shaderType} type
+ * @param {string=} source
+ */
+gluShaderProgram.ShaderInfo = function(type, source) {
+ this.type = type; /** gluShaderProgram.Shader type. */
+ this.source = source; /** gluShaderProgram.Shader source. */
+ this.infoLog; /** Compile info log. */
+ this.compileOk = false; /** Did compilation succeed? */
+ this.compileTimeUs = 0; /** Compile time in microseconds (us). */
+};
+
+/**
+ * Generates vertex shader info from source
+ * @param {string} source
+ * @return {gluShaderProgram.ShaderInfo} vertex shader info
+ */
+gluShaderProgram.genVertexSource = function(source) {
+/** @type {gluShaderProgram.ShaderInfo} */ var shader = new gluShaderProgram.ShaderInfo(gluShaderProgram.shaderType.VERTEX, source);
+ return shader;
+};
+
+/**
+ * Generates fragment shader info from source
+ * @param {string} source
+ * @return {gluShaderProgram.ShaderInfo} fragment shader info
+ */
+gluShaderProgram.genFragmentSource = function(source) {
+/** @type {gluShaderProgram.ShaderInfo} */ var shader = new gluShaderProgram.ShaderInfo(gluShaderProgram.shaderType.FRAGMENT, source);
+ return shader;
+};
+
+/**
+ * Generates shader from WebGL context and type
+ * @constructor
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluShaderProgram.shaderType} type gluShaderProgram.Shader Type
+ */
+gluShaderProgram.Shader = function(gl, type) {
+ this.gl = gl;
+ this.info = new gluShaderProgram.ShaderInfo(type); /** Client-side clone of state for debug / perf reasons. */
+ this.shader = gl.createShader(gluShaderProgram.getGLShaderType(gl, type));
+ assertMsgOptions(gl.getError() == gl.NO_ERROR, 'gl.createShader()', false, true);
+
+ this.setSources = function(source) {
+ this.gl.shaderSource(this.shader, source);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'glshaderSource()', false, true);
+ this.info.source = source;
+ };
+
+ this.getCompileStatus = function() {
+ return this.info.compileOk;
+ };
+
+ this.compile = function() {
+ this.info.compileOk = false;
+ this.info.compileTimeUs = 0;
+ this.info.infoLog = '';
+
+ /** @type {Date} */ var compileStart = new Date();
+ this.gl.compileShader(this.shader);
+ /** @type {Date} */ var compileEnd = new Date();
+ this.info.compileTimeUs = 1000 * (compileEnd.getTime() - compileStart.getTime());
+
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.compileShader()', false, true);
+
+ var compileStatus = this.gl.getShaderParameter(this.shader, this.gl.COMPILE_STATUS);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'glGetShaderParameter()', false, true);
+
+ this.info.compileOk = compileStatus;
+ this.info.infoLog = this.gl.getShaderInfoLog(this.shader);
+ };
+
+ this.getShader = function() {
+ return this.shader;
+ };
+
+ this.destroy = function() {
+ this.gl.deleteShader(this.shader);
+ };
+
+};
+/**
+ * Creates gluShaderProgram.ProgramInfo
+ * @constructor
+ */
+gluShaderProgram.ProgramInfo = function() {
+ /** @type {string} */ this.infoLog = ''; /** Link info log. */
+ /** @type {boolean} */ this.linkOk = false; /** Did link succeed? */
+ /** @type {number} */ this.linkTimeUs = 0; /** Link time in microseconds (us). */
+};
+
+/**
+ * Creates program.
+ * Inner methods: attach shaders, bind attributes location, link program and transform Feedback Varyings
+ * @constructor
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {WebGLProgram=} programID
+ */
+gluShaderProgram.Program = function(gl, programID) {
+ this.gl = gl;
+ this.program = programID || null;
+ this.info = new gluShaderProgram.ProgramInfo();
+
+ if (!programID) {
+ this.program = gl.createProgram();
+ assertMsgOptions(gl.getError() == gl.NO_ERROR, 'gl.createProgram()', false, true);
+ }
+};
+
+/**
+ * @return {WebGLProgram}
+ */
+gluShaderProgram.Program.prototype.getProgram = function() { return this.program; };
+
+/**
+ * @return {gluShaderProgram.ProgramInfo}
+ */
+gluShaderProgram.Program.prototype.getInfo = function() { return this.info; };
+
+/**
+ * @param {WebGLShader} shader
+ */
+gluShaderProgram.Program.prototype.attachShader = function(shader) {
+ this.gl.attachShader(this.program, shader);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.attachShader()', false, true);
+};
+
+/**
+ * @param {WebGLShader} shader
+ */
+gluShaderProgram.Program.prototype.detachShader = function(shader) {
+ this.gl.detachShader(this.program, shader);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.detachShader()', false, true);
+};
+
+/**
+ * @param {number} location
+ * @param {string} name
+ */
+gluShaderProgram.Program.prototype.bindAttribLocation = function(location, name) {
+ this.gl.bindAttribLocation(this.program, location, name);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.bindAttribLocation()', false, true);
+};
+
+gluShaderProgram.Program.prototype.link = function() {
+ this.info.linkOk = false;
+ this.info.linkTimeUs = 0;
+ this.info.infoLog = '';
+
+ /** @type {Date} */ var linkStart = new Date();
+ this.gl.linkProgram(this.program);
+ /** @type {Date} */ var linkEnd = new Date();
+ this.info.linkTimeUs = 1000 * (linkEnd.getTime() - linkStart.getTime());
+
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.linkProgram()', false, true);
+
+ var linkStatus = this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.getProgramParameter()', false, true);
+ this.info.linkOk = linkStatus;
+ this.info.infoLog = this.gl.getProgramInfoLog(this.program);
+ if (!this.info.linkOk)
+ bufferedLogToConsole("program linking: " + this.info.infoLog);
+};
+
+/**
+ * return {boolean}
+ */
+gluShaderProgram.Program.prototype.getLinkStatus = function() {
+ return this.info.linkOk;
+};
+
+/**
+ * @param {Array<string>} varyings
+ * @param {number} bufferMode
+ */
+gluShaderProgram.Program.prototype.transformFeedbackVaryings = function(varyings, bufferMode) {
+ this.gl.transformFeedbackVaryings(this.program, varyings, bufferMode);
+ assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.transformFeedbackVaryings()', false, true);
+};
+
+/**
+ * Assigns gl WebGL context and programSources. Declares array of shaders and new program()
+ * @constructor
+ * @param {WebGL2RenderingContext} gl WebGL context
+ * @param {gluShaderProgram.ProgramSources} programSources
+ */
+gluShaderProgram.ShaderProgram = function(gl, programSources) {
+ this.gl = gl;
+ this.programSources = programSources;
+ this.shaders = [];
+ this.program = new gluShaderProgram.Program(gl);
+
+ /** @type {boolean} */ this.shadersOK = true;
+
+ for (var i = 0; i < programSources.sources.length; i++) {
+ /** @type {gluShaderProgram.Shader} */ var shader = new gluShaderProgram.Shader(gl, programSources.sources[i].type);
+ shader.setSources(programSources.sources[i].source);
+ shader.compile();
+ this.shaders.push(shader);
+ this.shadersOK = this.shadersOK && shader.getCompileStatus();
+ if (!shader.getCompileStatus()) {
+ bufferedLogToConsole('gluShaderProgram.Shader:\n' + programSources.sources[i].source);
+ bufferedLogToConsole('Compile status: ' + shader.getCompileStatus());
+ bufferedLogToConsole('Shader infoLog: ' + shader.info.infoLog);
+ }
+ }
+
+ if (this.shadersOK) {
+ for (var i = 0; i < this.shaders.length; i++)
+ this.program.attachShader(this.shaders[i].getShader());
+
+ for (var attrib in programSources.attribLocationBindings)
+ this.program.bindAttribLocation(programSources.attribLocationBindings[attrib], attrib);
+
+ if (programSources.transformFeedbackBufferMode)
+ if (programSources.transformFeedbackBufferMode === gl.NONE)
+ assertMsgOptions(programSources.transformFeedbackVaryings.length === 0, 'Transform feedback sanity check', false, true);
+ else
+ this.program.transformFeedbackVaryings(programSources.transformFeedbackVaryings, programSources.transformFeedbackBufferMode);
+
+ /* TODO: GLES 3.1: set separable flag */
+
+ this.program.link();
+
+ }
+};
+
+/**
+ * return {WebGLProgram}
+ */
+gluShaderProgram.ShaderProgram.prototype.getProgram = function() {
+ return this.program.program;
+ };
+
+/**
+ * @return {gluShaderProgram.ProgramInfo}
+ */
+gluShaderProgram.ShaderProgram.prototype.getProgramInfo = function() {
+ return this.program.info;
+};
+
+gluShaderProgram.ShaderProgram.prototype.isOk = function() {
+ return this.shadersOK && this.program.getLinkStatus();
+};
+
+gluShaderProgram.containerTypes = {
+ ATTRIB_LOCATION_BINDING: 0,
+ TRANSFORM_FEEDBACK_MODE: 1,
+ TRANSFORM_FEEDBACK_VARYING: 2,
+ TRANSFORM_FEEDBACK_VARYINGS: 3,
+ SHADER_SOURCE: 4,
+ PROGRAM_SEPARABLE: 5,
+ PROGRAM_SOURCES: 6,
+
+ CONTAINER_TYPE_LAST: 7,
+ ATTACHABLE_BEGIN: 0, // ATTRIB_LOCATION_BINDING
+ ATTACHABLE_END: 5 + 1 // PROGRAM_SEPARABLE + 1
+};
+
+/**
+ * @constructor
+ */
+gluShaderProgram.AttribLocationBinding = function(name, location) {
+ this.name = name;
+ this.location = location;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.ATTRIB_LOCATION_BINDING;
+ };
+};
+
+/**
+ * @constructor
+ */
+gluShaderProgram.TransformFeedbackMode = function(mode) {
+ this.mode = mode;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_MODE;
+ };
+};
+
+/**
+ * @constructor
+ * @param {string} name
+ */
+gluShaderProgram.TransformFeedbackVarying = function(name) {
+ /** @type {string} */ this.name = name;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYING;
+ };
+};
+
+/**
+ * @constructor
+ * @param {Array<string>} array
+ */
+gluShaderProgram.TransformFeedbackVaryings = function(array) {
+ /** @type {Array<string>} */ this.array = array;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYINGS;
+ };
+};
+
+/**
+ * @constructor
+ */
+gluShaderProgram.ProgramSeparable = function(separable) {
+ this.separable = separable;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.PROGRAM_SEPARABLE;
+ };
+};
+
+/**
+ * @constructor
+ */
+gluShaderProgram.VertexSource = function(str) {
+ this.shaderType = gluShaderProgram.shaderType.VERTEX;
+ this.source = str;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.SHADER_SOURCE;
+ };
+};
+
+/**
+ * @constructor
+ */
+gluShaderProgram.FragmentSource = function(str) {
+ this.shaderType = gluShaderProgram.shaderType.FRAGMENT;
+ this.source = str;
+
+ this.getContainerType = function() {
+ return gluShaderProgram.containerTypes.SHADER_SOURCE;
+ };
+};
+
+/**
+ * Create gluShaderProgram.ProgramSources.
+ * @constructor
+ */
+gluShaderProgram.ProgramSources = function() {
+ /** @type {Array<gluShaderProgram.ShaderInfo>} */ this.sources = [];
+ this.attribLocationBindings = [];
+ /** @type {Array<string>} */ this.transformFeedbackVaryings = [];
+ this.transformFeedbackBufferMode = 0;
+ this.separable = false;
+};
+
+gluShaderProgram.ProgramSources.prototype.getContainerType = function() {
+ return gluShaderProgram.containerTypes.PROGRAM_SOURCES;
+};
+
+gluShaderProgram.ProgramSources.prototype.add = function(item) {
+ var type = undefined;
+ if (typeof(item.getContainerType) == 'function') {
+ type = item.getContainerType();
+ if (
+ typeof(type) != 'number' ||
+ type < gluShaderProgram.containerTypes.ATTACHABLE_BEGIN ||
+ type >= gluShaderProgram.containerTypes.ATTACHABLE_END
+ ) {
+ type = undefined;
+ }
+ }
+
+ switch (type) {
+ case gluShaderProgram.containerTypes.ATTRIB_LOCATION_BINDING:
+ this.attribLocationBindings.push(item);
+ break;
+
+ case gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_MODE:
+ this.transformFeedbackBufferMode = item.mode;
+ break;
+
+ case gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYING:
+ this.transformFeedbackVaryings.push(item.name);
+ break;
+
+ case gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYINGS:
+ this.transformFeedbackVaryings = this.transformFeedbackVaryings.concat(item.array);
+ break;
+
+ case gluShaderProgram.containerTypes.SHADER_SOURCE:
+ this.sources.push(new gluShaderProgram.ShaderInfo(item.shaderType, item.source));
+ break;
+
+ case gluShaderProgram.containerTypes.PROGRAM_SEPARABLE:
+ this.separable = item.separable;
+ break;
+
+ default:
+ throw new Error('Type \"' + type + '\" cannot be added to gluShaderProgram.ProgramSources.');
+ break;
+ }
+
+ return this;
+};
+
+/**
+ * //! Helper for constructing vertex-fragment source pair.
+ * @param {string} vertexSrc
+ * @param {string} fragmentSrc
+ * @return {gluShaderProgram.ProgramSources}
+ */
+gluShaderProgram.makeVtxFragSources = function(vertexSrc, fragmentSrc) {
+ /** @type  {gluShaderProgram.ProgramSources} */ var sources = new gluShaderProgram.ProgramSources();
+ sources.sources.push(gluShaderProgram.genVertexSource(vertexSrc));
+ sources.sources.push(gluShaderProgram.genFragmentSource(fragmentSrc));
+ return sources;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderUtil.js
new file mode 100644
index 0000000000..1604dbc613
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluShaderUtil.js
@@ -0,0 +1,795 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluShaderUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var deMath = framework.delibs.debase.deMath;
+
+/**
+ * ShadingLanguageVersion
+ * @enum
+ */
+gluShaderUtil.GLSLVersion = {
+ V100_ES: 0, //!< GLSL ES 1.0
+ V300_ES: 1 //!< GLSL ES 3.0
+};
+
+/**
+ * gluShaderUtil.glslVersionUsesInOutQualifiers
+ * @param {gluShaderUtil.GLSLVersion} version
+ * @return {boolean}
+ */
+gluShaderUtil.glslVersionUsesInOutQualifiers = function(version) {
+ return version == gluShaderUtil.GLSLVersion.V300_ES;
+};
+
+/**
+ * gluShaderUtil.isGLSLVersionSupported
+ * @param {WebGL2RenderingContext|WebGLRenderingContextBase} ctx
+ * @param {gluShaderUtil.GLSLVersion} version
+ * @return {boolean}
+ */
+gluShaderUtil.isGLSLVersionSupported = function(ctx, version) {
+ return version <= gluShaderUtil.getGLSLVersion(ctx);
+};
+
+/**
+ * gluShaderUtil.getGLSLVersion - Returns a gluShaderUtil.GLSLVersion based on a given webgl context.
+ * @param {WebGL2RenderingContext|WebGLRenderingContextBase} gl
+ * @return {gluShaderUtil.GLSLVersion}
+ */
+gluShaderUtil.getGLSLVersion = function(gl) {
+ var glslversion = gl.getParameter(gl.SHADING_LANGUAGE_VERSION);
+
+ // TODO: Versions are not yet well implemented... Firefox returns GLSL ES 1.0 in some cases,
+ // and Chromium returns GLSL ES 2.0 in some cases. Returning the right version for
+ // testing.
+ // return gluShaderUtil.GLSLVersion.V300_ES;
+
+ if (glslversion.indexOf('WebGL GLSL ES 1.0') != -1) return gluShaderUtil.GLSLVersion.V100_ES;
+ if (glslversion.indexOf('WebGL GLSL ES 3.0') != -1) return gluShaderUtil.GLSLVersion.V300_ES;
+
+ throw new Error('Invalid WebGL version');
+};
+
+/**
+ * gluShaderUtil.getGLSLVersionDeclaration - Returns a string declaration for the glsl version in a shader.
+ * @param {gluShaderUtil.GLSLVersion} version
+ * @return {string}
+ */
+gluShaderUtil.getGLSLVersionDeclaration = function(version) {
+ /** @type {Array<string>} */ var s_decl =
+ [
+ '#version 100',
+ '#version 300 es'
+ ];
+
+ if (version > s_decl.length - 1)
+ throw new Error('Unsupported GLSL version.');
+
+ return s_decl[version];
+};
+
+/**
+ * gluShaderUtil.getGLSLVersionString - Returns the same thing as
+ * getGLSLVersionDeclaration() but without the substring '#version'
+ * @param {gluShaderUtil.GLSLVersion} version
+ * @return {string}
+ */
+gluShaderUtil.getGLSLVersionString = function(version) {
+ /** @type {Array<string>} */ var s_decl =
+ [
+ '100',
+ '300 es'
+ ];
+
+ if (version > s_decl.length - 1)
+ throw new Error('Unsupported GLSL version.');
+
+ return s_decl[version];
+};
+
+/**
+ * @enum
+ */
+gluShaderUtil.precision = {
+ PRECISION_LOWP: 0,
+ PRECISION_MEDIUMP: 1,
+ PRECISION_HIGHP: 2
+};
+
+gluShaderUtil.getPrecisionName = function(prec) {
+ var s_names = [
+ 'lowp',
+ 'mediump',
+ 'highp'
+ ];
+
+ return s_names[prec];
+};
+
+/**
+ * The Type constants
+ * @enum {number}
+ */
+gluShaderUtil.DataType = {
+ INVALID: 0,
+
+ FLOAT: 1,
+ FLOAT_VEC2: 2,
+ FLOAT_VEC3: 3,
+ FLOAT_VEC4: 4,
+ FLOAT_MAT2: 5,
+ FLOAT_MAT2X3: 6,
+ FLOAT_MAT2X4: 7,
+ FLOAT_MAT3X2: 8,
+ FLOAT_MAT3: 9,
+ FLOAT_MAT3X4: 10,
+ FLOAT_MAT4X2: 11,
+ FLOAT_MAT4X3: 12,
+ FLOAT_MAT4: 13,
+
+ INT: 14,
+ INT_VEC2: 15,
+ INT_VEC3: 16,
+ INT_VEC4: 17,
+
+ UINT: 18,
+ UINT_VEC2: 19,
+ UINT_VEC3: 20,
+ UINT_VEC4: 21,
+
+ BOOL: 22,
+ BOOL_VEC2: 23,
+ BOOL_VEC3: 24,
+ BOOL_VEC4: 25,
+
+ SAMPLER_2D: 26,
+ SAMPLER_CUBE: 27,
+ SAMPLER_2D_ARRAY: 28,
+ SAMPLER_3D: 29,
+
+ SAMPLER_2D_SHADOW: 30,
+ SAMPLER_CUBE_SHADOW: 31,
+ SAMPLER_2D_ARRAY_SHADOW: 32,
+
+ INT_SAMPLER_2D: 33,
+ INT_SAMPLER_CUBE: 34,
+ INT_SAMPLER_2D_ARRAY: 35,
+ INT_SAMPLER_3D: 36,
+
+ UINT_SAMPLER_2D: 37,
+ UINT_SAMPLER_CUBE: 38,
+ UINT_SAMPLER_2D_ARRAY: 39,
+ UINT_SAMPLER_3D: 40
+};
+
+/**
+ * Returns type of float scalars
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {string} type of float scalar
+ */
+gluShaderUtil.getDataTypeFloatScalars = function(dataType) {
+
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT: return 'float';
+ case gluShaderUtil.DataType.FLOAT_VEC2: return 'vec2';
+ case gluShaderUtil.DataType.FLOAT_VEC3: return 'vec3';
+ case gluShaderUtil.DataType.FLOAT_VEC4: return 'vec4';
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 'mat2';
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 'mat2x3';
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 'mat2x4';
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 'mat3x2';
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 'mat3';
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 'mat3x4';
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 'mat4x2';
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 'mat4x3';
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 'mat4';
+ case gluShaderUtil.DataType.INT: return 'float';
+ case gluShaderUtil.DataType.INT_VEC2: return 'vec2';
+ case gluShaderUtil.DataType.INT_VEC3: return 'vec3';
+ case gluShaderUtil.DataType.INT_VEC4: return 'vec4';
+ case gluShaderUtil.DataType.UINT: return 'float';
+ case gluShaderUtil.DataType.UINT_VEC2: return 'vec2';
+ case gluShaderUtil.DataType.UINT_VEC3: return 'vec3';
+ case gluShaderUtil.DataType.UINT_VEC4: return 'vec4';
+ case gluShaderUtil.DataType.BOOL: return 'float';
+ case gluShaderUtil.DataType.BOOL_VEC2: return 'vec2';
+ case gluShaderUtil.DataType.BOOL_VEC3: return 'vec3';
+ case gluShaderUtil.DataType.BOOL_VEC4: return 'vec4';
+ }
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * gluShaderUtil.getDataTypeVector
+ * @param {gluShaderUtil.DataType} scalarType
+ * @param {number} size
+ * @return {gluShaderUtil.DataType}
+ */
+gluShaderUtil.getDataTypeVector = function(scalarType, size) {
+ var floats = [gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4];
+ var ints = [gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4];
+ var uints = [gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4];
+ var bools = [gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL_VEC2,
+ gluShaderUtil.DataType.BOOL_VEC3,
+ gluShaderUtil.DataType.BOOL_VEC4];
+
+ switch (scalarType) {
+ case gluShaderUtil.DataType.FLOAT: return floats[size - 1];
+ case gluShaderUtil.DataType.INT: return ints[size - 1];
+ case gluShaderUtil.DataType.UINT: return uints[size - 1];
+ case gluShaderUtil.DataType.BOOL: return bools[size - 1];
+ default:
+ throw new Error('Scalar type is not a vectoe:' + scalarType);
+ }
+};
+
+/**
+ * gluShaderUtil.getDataTypeFloatVec
+ * @param {number} vecSize
+ * @return {gluShaderUtil.DataType}
+ */
+gluShaderUtil.getDataTypeFloatVec = function(vecSize) {
+ return gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.FLOAT, vecSize);
+};
+
+/**
+ * gluShaderUtil.isDataTypeBoolOrBVec
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {boolean}
+ */
+gluShaderUtil.isDataTypeBoolOrBVec = function(dataType) {
+ return (dataType >= gluShaderUtil.DataType.BOOL) && (dataType <= gluShaderUtil.DataType.BOOL_VEC4);
+};
+
+/**
+ * Returns type of scalar
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {string} type of scalar type
+ */
+gluShaderUtil.getDataTypeScalarType = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT: return 'float';
+ case gluShaderUtil.DataType.FLOAT_VEC2: return 'float';
+ case gluShaderUtil.DataType.FLOAT_VEC3: return 'float';
+ case gluShaderUtil.DataType.FLOAT_VEC4: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 'float';
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 'float';
+ case gluShaderUtil.DataType.INT: return 'int';
+ case gluShaderUtil.DataType.INT_VEC2: return 'int';
+ case gluShaderUtil.DataType.INT_VEC3: return 'int';
+ case gluShaderUtil.DataType.INT_VEC4: return 'int';
+ case gluShaderUtil.DataType.UINT: return 'uint';
+ case gluShaderUtil.DataType.UINT_VEC2: return 'uint';
+ case gluShaderUtil.DataType.UINT_VEC3: return 'uint';
+ case gluShaderUtil.DataType.UINT_VEC4: return 'uint';
+ case gluShaderUtil.DataType.BOOL: return 'bool';
+ case gluShaderUtil.DataType.BOOL_VEC2: return 'bool';
+ case gluShaderUtil.DataType.BOOL_VEC3: return 'bool';
+ case gluShaderUtil.DataType.BOOL_VEC4: return 'bool';
+ case gluShaderUtil.DataType.SAMPLER_2D: return 'sampler2D';
+ case gluShaderUtil.DataType.SAMPLER_CUBE: return 'samplerCube';
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY: return 'sampler2DArray';
+ case gluShaderUtil.DataType.SAMPLER_3D: return 'sampler3D';
+ case gluShaderUtil.DataType.SAMPLER_2D_SHADOW: return 'sampler2DShadow';
+ case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW: return 'samplerCubeShadow';
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW: return 'sampler2DArrayShadow';
+ case gluShaderUtil.DataType.INT_SAMPLER_2D: return 'isampler2D';
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE: return 'isamplerCube';
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY: return 'isampler2DArray';
+ case gluShaderUtil.DataType.INT_SAMPLER_3D: return 'isampler3D';
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D: return 'usampler2D';
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE: return 'usamplerCube';
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY: return 'usampler2DArray';
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D: return 'usampler3D';
+ }
+ throw new Error('Unrecognized datatype:' + dataType);
+};
+
+/**
+ * Returns type of scalar
+ * @param {?gluShaderUtil.DataType} dataType shader
+ * @return {gluShaderUtil.DataType} type of scalar type
+ */
+gluShaderUtil.getDataTypeScalarTypeAsDataType = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_VEC2: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_VEC3: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_VEC4: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT2: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT3: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.FLOAT_MAT4: return gluShaderUtil.DataType.FLOAT;
+ case gluShaderUtil.DataType.INT: return gluShaderUtil.DataType.INT;
+ case gluShaderUtil.DataType.INT_VEC2: return gluShaderUtil.DataType.INT;
+ case gluShaderUtil.DataType.INT_VEC3: return gluShaderUtil.DataType.INT;
+ case gluShaderUtil.DataType.INT_VEC4: return gluShaderUtil.DataType.INT;
+ case gluShaderUtil.DataType.UINT: return gluShaderUtil.DataType.UINT;
+ case gluShaderUtil.DataType.UINT_VEC2: return gluShaderUtil.DataType.UINT;
+ case gluShaderUtil.DataType.UINT_VEC3: return gluShaderUtil.DataType.UINT;
+ case gluShaderUtil.DataType.UINT_VEC4: return gluShaderUtil.DataType.UINT;
+ case gluShaderUtil.DataType.BOOL: return gluShaderUtil.DataType.BOOL;
+ case gluShaderUtil.DataType.BOOL_VEC2: return gluShaderUtil.DataType.BOOL;
+ case gluShaderUtil.DataType.BOOL_VEC3: return gluShaderUtil.DataType.BOOL;
+ case gluShaderUtil.DataType.BOOL_VEC4: return gluShaderUtil.DataType.BOOL;
+ case gluShaderUtil.DataType.SAMPLER_2D:
+ case gluShaderUtil.DataType.SAMPLER_CUBE:
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.SAMPLER_3D:
+ case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
+ case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D:
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.INT_SAMPLER_3D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D:
+ return dataType;
+ }
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * Checks if dataType is integer or vectors of integers
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType integer or integer vector
+ */
+gluShaderUtil.isDataTypeIntOrIVec = function(dataType) {
+ /** @type {boolean} */ var retVal = false;
+ switch (dataType) {
+ case gluShaderUtil.DataType.INT:
+ case gluShaderUtil.DataType.INT_VEC2:
+ case gluShaderUtil.DataType.INT_VEC3:
+ case gluShaderUtil.DataType.INT_VEC4:
+ retVal = true;
+ }
+
+ return retVal;
+};
+
+/**
+ * Checks if dataType is unsigned integer or vectors of unsigned integers
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType unsigned integer or unsigned integer vector
+ */
+gluShaderUtil.isDataTypeUintOrUVec = function(dataType) {
+ /** @type {boolean} */ var retVal = false;
+ switch (dataType) {
+ case gluShaderUtil.DataType.UINT:
+ case gluShaderUtil.DataType.UINT_VEC2:
+ case gluShaderUtil.DataType.UINT_VEC3:
+ case gluShaderUtil.DataType.UINT_VEC4:
+ retVal = true;
+ }
+
+ return retVal;
+};
+
+/**
+* Returns type of scalar size
+* @param {gluShaderUtil.DataType} dataType shader
+* @return {number} with size of the type of scalar
+*/
+gluShaderUtil.getDataTypeScalarSize = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT: return 1;
+ case gluShaderUtil.DataType.FLOAT_VEC2: return 2;
+ case gluShaderUtil.DataType.FLOAT_VEC3: return 3;
+ case gluShaderUtil.DataType.FLOAT_VEC4: return 4;
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 4;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 6;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 8;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 6;
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 9;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 12;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 8;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 12;
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 16;
+ case gluShaderUtil.DataType.INT: return 1;
+ case gluShaderUtil.DataType.INT_VEC2: return 2;
+ case gluShaderUtil.DataType.INT_VEC3: return 3;
+ case gluShaderUtil.DataType.INT_VEC4: return 4;
+ case gluShaderUtil.DataType.UINT: return 1;
+ case gluShaderUtil.DataType.UINT_VEC2: return 2;
+ case gluShaderUtil.DataType.UINT_VEC3: return 3;
+ case gluShaderUtil.DataType.UINT_VEC4: return 4;
+ case gluShaderUtil.DataType.BOOL: return 1;
+ case gluShaderUtil.DataType.BOOL_VEC2: return 2;
+ case gluShaderUtil.DataType.BOOL_VEC3: return 3;
+ case gluShaderUtil.DataType.BOOL_VEC4: return 4;
+ case gluShaderUtil.DataType.SAMPLER_2D: return 1;
+ case gluShaderUtil.DataType.SAMPLER_CUBE: return 1;
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY: return 1;
+ case gluShaderUtil.DataType.SAMPLER_3D: return 1;
+ case gluShaderUtil.DataType.SAMPLER_2D_SHADOW: return 1;
+ case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW: return 1;
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW: return 1;
+ case gluShaderUtil.DataType.INT_SAMPLER_2D: return 1;
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE: return 1;
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY: return 1;
+ case gluShaderUtil.DataType.INT_SAMPLER_3D: return 1;
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D: return 1;
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE: return 1;
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY: return 1;
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D: return 1;
+ }
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * Checks if dataType is float or vector
+ * @param {?gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType float or vector
+ */
+gluShaderUtil.isDataTypeFloatOrVec = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT:
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Checks if dataType is a matrix
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType matrix or not
+ */
+gluShaderUtil.isDataTypeMatrix = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT_MAT2:
+ case gluShaderUtil.DataType.FLOAT_MAT2X3:
+ case gluShaderUtil.DataType.FLOAT_MAT2X4:
+ case gluShaderUtil.DataType.FLOAT_MAT3X2:
+ case gluShaderUtil.DataType.FLOAT_MAT3:
+ case gluShaderUtil.DataType.FLOAT_MAT3X4:
+ case gluShaderUtil.DataType.FLOAT_MAT4X2:
+ case gluShaderUtil.DataType.FLOAT_MAT4X3:
+ case gluShaderUtil.DataType.FLOAT_MAT4:
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Checks if dataType is a vector
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType vector or not
+ */
+gluShaderUtil.isDataTypeScalar = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT:
+ case gluShaderUtil.DataType.INT:
+ case gluShaderUtil.DataType.UINT:
+ case gluShaderUtil.DataType.BOOL:
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Checks if dataType is a vector
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType vector or not
+ */
+gluShaderUtil.isDataTypeVector = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ case gluShaderUtil.DataType.INT_VEC2:
+ case gluShaderUtil.DataType.INT_VEC3:
+ case gluShaderUtil.DataType.INT_VEC4:
+ case gluShaderUtil.DataType.UINT_VEC2:
+ case gluShaderUtil.DataType.UINT_VEC3:
+ case gluShaderUtil.DataType.UINT_VEC4:
+ case gluShaderUtil.DataType.BOOL_VEC2:
+ case gluShaderUtil.DataType.BOOL_VEC3:
+ case gluShaderUtil.DataType.BOOL_VEC4:
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Checks if dataType is a vector or a scalar type
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType vector or scalar or not
+ */
+gluShaderUtil.isDataTypeScalarOrVector = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT:
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ case gluShaderUtil.DataType.INT:
+ case gluShaderUtil.DataType.INT_VEC2:
+ case gluShaderUtil.DataType.INT_VEC3:
+ case gluShaderUtil.DataType.INT_VEC4:
+ case gluShaderUtil.DataType.UINT:
+ case gluShaderUtil.DataType.UINT_VEC2:
+ case gluShaderUtil.DataType.UINT_VEC3:
+ case gluShaderUtil.DataType.UINT_VEC4:
+ case gluShaderUtil.DataType.BOOL:
+ case gluShaderUtil.DataType.BOOL_VEC2:
+ case gluShaderUtil.DataType.BOOL_VEC3:
+ case gluShaderUtil.DataType.BOOL_VEC4:
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Checks if dataType is a sampler
+ * @param {gluShaderUtil.DataType} dataType shader
+ * @return {boolean} Is dataType vector or scalar or not
+ */
+gluShaderUtil.isDataTypeSampler = function(dataType) {
+ return (dataType >= gluShaderUtil.DataType.SAMPLER_2D) && (dataType <= gluShaderUtil.DataType.UINT_SAMPLER_3D);
+};
+
+/**
+ * Returns a gluShaderUtil.DataType based on given rows and columns
+ * @param {number} numCols
+ * @param {number} numRows
+ * @return {gluShaderUtil.DataType}
+ */
+gluShaderUtil.getDataTypeMatrix = function(numCols, numRows) {
+ if (!(deMath.deInRange32(numCols, 2, 4) && deMath.deInRange32(numRows, 2, 4)))
+ throw new Error('Out of bounds: (' + numCols + ',' + numRows + ')');
+
+ var size = numCols.toString() + 'x' + numRows.toString();
+ var datatypes = {
+ '2x2': gluShaderUtil.DataType.FLOAT_MAT2,
+ '2x3': gluShaderUtil.DataType.FLOAT_MAT2X3,
+ '2x4': gluShaderUtil.DataType.FLOAT_MAT2X4,
+ '3x2': gluShaderUtil.DataType.FLOAT_MAT3X2,
+ '3x3': gluShaderUtil.DataType.FLOAT_MAT3,
+ '3x4': gluShaderUtil.DataType.FLOAT_MAT3X4,
+ '4x2': gluShaderUtil.DataType.FLOAT_MAT4X2,
+ '4x3': gluShaderUtil.DataType.FLOAT_MAT4X3,
+ '4x4': gluShaderUtil.DataType.FLOAT_MAT4
+ };
+ return datatypes[size];
+};
+
+/**
+* Returns number of rows of a gluShaderUtil.DataType Matrix
+* @param {gluShaderUtil.DataType} dataType shader
+* @return {number} with number of rows depending on gluShaderUtil.DataType Matrix
+*/
+gluShaderUtil.getDataTypeMatrixNumRows = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 2;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 3;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 4;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 2;
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 3;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 4;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 2;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 3;
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 4;
+ }
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+* Returns number of columns of a gluShaderUtil.DataType Matrix
+* @param {gluShaderUtil.DataType} dataType shader
+* @return {number} with number of columns depending on gluShaderUtil.DataType Matrix
+*/
+gluShaderUtil.getDataTypeMatrixNumColumns = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 2;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 2;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 2;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 3;
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 3;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 3;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 4;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 4;
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 4;
+ }
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {number}
+ */
+gluShaderUtil.getDataTypeNumLocations = function(dataType) {
+ if (gluShaderUtil.isDataTypeScalarOrVector(dataType))
+ return 1;
+ else if (gluShaderUtil.isDataTypeMatrix(dataType))
+ return gluShaderUtil.getDataTypeMatrixNumColumns(dataType);
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {number}
+ */
+gluShaderUtil.getDataTypeNumComponents = function(dataType) {
+ if (gluShaderUtil.isDataTypeScalarOrVector(dataType))
+ return gluShaderUtil.getDataTypeScalarSize(dataType);
+ else if (gluShaderUtil.isDataTypeMatrix(dataType))
+ return gluShaderUtil.getDataTypeMatrixNumRows(dataType);
+
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * Returns name of the dataType
+ * @param {?gluShaderUtil.DataType} dataType shader
+ * @return {string} dataType name
+ */
+gluShaderUtil.getDataTypeName = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.INVALID: return 'invalid';
+
+ case gluShaderUtil.DataType.FLOAT: return 'float';
+ case gluShaderUtil.DataType.FLOAT_VEC2: return 'vec2';
+ case gluShaderUtil.DataType.FLOAT_VEC3: return 'vec3';
+ case gluShaderUtil.DataType.FLOAT_VEC4: return 'vec4';
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 'mat2';
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 'mat2x3';
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 'mat2x4';
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 'mat3x2';
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 'mat3';
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 'mat3x4';
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 'mat4x2';
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 'mat4x3';
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 'mat4';
+
+ case gluShaderUtil.DataType.INT: return 'int';
+ case gluShaderUtil.DataType.INT_VEC2: return 'ivec2';
+ case gluShaderUtil.DataType.INT_VEC3: return 'ivec3';
+ case gluShaderUtil.DataType.INT_VEC4: return 'ivec4';
+
+ case gluShaderUtil.DataType.UINT: return 'uint';
+ case gluShaderUtil.DataType.UINT_VEC2: return 'uvec2';
+ case gluShaderUtil.DataType.UINT_VEC3: return 'uvec3';
+ case gluShaderUtil.DataType.UINT_VEC4: return 'uvec4';
+
+ case gluShaderUtil.DataType.BOOL: return 'bool';
+ case gluShaderUtil.DataType.BOOL_VEC2: return 'bvec2';
+ case gluShaderUtil.DataType.BOOL_VEC3: return 'bvec3';
+ case gluShaderUtil.DataType.BOOL_VEC4: return 'bvec4';
+
+ case gluShaderUtil.DataType.SAMPLER_2D: return 'sampler2D';
+ case gluShaderUtil.DataType.SAMPLER_CUBE: return 'samplerCube';
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY: return 'sampler2DArray';
+ case gluShaderUtil.DataType.SAMPLER_3D: return 'sampler3D';
+
+ case gluShaderUtil.DataType.SAMPLER_2D_SHADOW: return 'sampler2DShadow';
+ case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW: return 'samplerCubeShadow';
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW: return 'sampler2DArrayShadow';
+
+ case gluShaderUtil.DataType.INT_SAMPLER_2D: return 'isampler2D';
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE: return 'isamplerCube';
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY: return 'isampler2DArray';
+ case gluShaderUtil.DataType.INT_SAMPLER_3D: return 'isampler3D';
+
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D: return 'usampler2D';
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE: return 'usamplerCube';
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY: return 'usampler2DArray';
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D: return 'usampler3D';
+ }
+ throw Error('Unrecognized dataType ' + dataType);
+};
+
+/**
+ * Returns the gluShaderUtil.DataType from the GL type
+ * @param {number} glType
+ * @return {gluShaderUtil.DataType}
+ */
+gluShaderUtil.getDataTypeFromGLType = function(glType) {
+ switch (glType) {
+ case gl.FLOAT: return gluShaderUtil.DataType.FLOAT;
+ case gl.FLOAT_VEC2: return gluShaderUtil.DataType.FLOAT_VEC2;
+ case gl.FLOAT_VEC3: return gluShaderUtil.DataType.FLOAT_VEC3;
+ case gl.FLOAT_VEC4: return gluShaderUtil.DataType.FLOAT_VEC4;
+
+ case gl.FLOAT_MAT2: return gluShaderUtil.DataType.FLOAT_MAT2;
+ case gl.FLOAT_MAT2x3: return gluShaderUtil.DataType.FLOAT_MAT2X3;
+ case gl.FLOAT_MAT2x4: return gluShaderUtil.DataType.FLOAT_MAT2X4;
+
+ case gl.FLOAT_MAT3x2: return gluShaderUtil.DataType.FLOAT_MAT3X2;
+ case gl.FLOAT_MAT3: return gluShaderUtil.DataType.FLOAT_MAT3;
+ case gl.FLOAT_MAT3x4: return gluShaderUtil.DataType.FLOAT_MAT3X4;
+
+ case gl.FLOAT_MAT4x2: return gluShaderUtil.DataType.FLOAT_MAT4X2;
+ case gl.FLOAT_MAT4x3: return gluShaderUtil.DataType.FLOAT_MAT4X3;
+ case gl.FLOAT_MAT4: return gluShaderUtil.DataType.FLOAT_MAT4;
+
+ case gl.INT: return gluShaderUtil.DataType.INT;
+ case gl.INT_VEC2: return gluShaderUtil.DataType.INT_VEC2;
+ case gl.INT_VEC3: return gluShaderUtil.DataType.INT_VEC3;
+ case gl.INT_VEC4: return gluShaderUtil.DataType.INT_VEC4;
+
+ case gl.UNSIGNED_INT: return gluShaderUtil.DataType.UINT;
+ case gl.UNSIGNED_INT_VEC2: return gluShaderUtil.DataType.UINT_VEC2;
+ case gl.UNSIGNED_INT_VEC3: return gluShaderUtil.DataType.UINT_VEC3;
+ case gl.UNSIGNED_INT_VEC4: return gluShaderUtil.DataType.UINT_VEC4;
+
+ case gl.BOOL: return gluShaderUtil.DataType.BOOL;
+ case gl.BOOL_VEC2: return gluShaderUtil.DataType.BOOL_VEC2;
+ case gl.BOOL_VEC3: return gluShaderUtil.DataType.BOOL_VEC3;
+ case gl.BOOL_VEC4: return gluShaderUtil.DataType.BOOL_VEC4;
+
+ case gl.SAMPLER_2D: return gluShaderUtil.DataType.SAMPLER_2D;
+ case gl.SAMPLER_CUBE: return gluShaderUtil.DataType.SAMPLER_CUBE;
+ case gl.SAMPLER_2D_ARRAY: return gluShaderUtil.DataType.SAMPLER_2D_ARRAY;
+ case gl.SAMPLER_3D: return gluShaderUtil.DataType.SAMPLER_3D;
+
+ case gl.SAMPLER_2D_SHADOW: return gluShaderUtil.DataType.SAMPLER_2D_SHADOW;
+ case gl.SAMPLER_CUBE_SHADOW: return gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW;
+ case gl.SAMPLER_2D_ARRAY_SHADOW: return gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW;
+
+ case gl.INT_SAMPLER_2D: return gluShaderUtil.DataType.INT_SAMPLER_2D;
+ case gl.INT_SAMPLER_CUBE: return gluShaderUtil.DataType.INT_SAMPLER_CUBE;
+ case gl.INT_SAMPLER_2D_ARRAY: return gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY;
+ case gl.INT_SAMPLER_3D: return gluShaderUtil.DataType.INT_SAMPLER_3D;
+
+ case gl.UNSIGNED_INT_SAMPLER_2D: return gluShaderUtil.DataType.UINT_SAMPLER_2D;
+ case gl.UNSIGNED_INT_SAMPLER_CUBE: return gluShaderUtil.DataType.UINT_SAMPLER_CUBE;
+ case gl.UNSIGNED_INT_SAMPLER_2D_ARRAY: return gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY;
+ case gl.UNSIGNED_INT_SAMPLER_3D: return gluShaderUtil.DataType.UINT_SAMPLER_3D;
+
+ default:
+ throw new Error('Unrecognized GL type:' + glType);
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluStrUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluStrUtil.js
new file mode 100644
index 0000000000..b554db047a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluStrUtil.js
@@ -0,0 +1,166 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluStrUtil');
+
+goog.scope(function() {
+
+var gluStrUtil = framework.opengl.gluStrUtil;
+
+gluStrUtil.getPixelFormatName = function(value) {
+ switch (value) {
+ case gl.LUMINANCE: return 'gl.LUMINANCE';
+ case gl.LUMINANCE_ALPHA: return 'gl.LUMINANCE_ALPHA';
+ case gl.ALPHA: return 'gl.ALPHA';
+ case gl.RGB: return 'gl.RGB';
+ case gl.RGBA: return 'gl.RGBA';
+ case gl.RGBA4: return 'gl.RGBA4';
+ case gl.RGB5_A1: return 'gl.RGB5_A1';
+ case gl.RGB565: return 'gl.RGB565';
+ case gl.DEPTH_COMPONENT16: return 'gl.DEPTH_COMPONENT16';
+ case gl.STENCIL_INDEX8: return 'gl.STENCIL_INDEX8';
+ case gl.RG: return 'gl.RG';
+ case gl.RED: return 'gl.RED';
+ case gl.RGBA_INTEGER: return 'gl.RGBA_INTEGER';
+ case gl.RGB_INTEGER: return 'gl.RGB_INTEGER';
+ case gl.RG_INTEGER: return 'gl.RG_INTEGER';
+ case gl.RED_INTEGER: return 'gl.RED_INTEGER';
+ case gl.DEPTH_COMPONENT: return 'gl.DEPTH_COMPONENT';
+ case gl.DEPTH_STENCIL: return 'gl.DEPTH_STENCIL';
+ case gl.RGBA32F: return 'gl.RGBA32F';
+ case gl.RGBA32I: return 'gl.RGBA32I';
+ case gl.RGBA32UI: return 'gl.RGBA32UI';
+ // case gl.RGBA16: return 'gl.RGBA16';
+ // case gl.RGBA16_SNORM: return 'gl.RGBA16_SNORM';
+ case gl.RGBA16F: return 'gl.RGBA16F';
+ case gl.RGBA16I: return 'gl.RGBA16I';
+ case gl.RGBA16UI: return 'gl.RGBA16UI';
+ case gl.RGBA8: return 'gl.RGBA8';
+ case gl.RGBA8I: return 'gl.RGBA8I';
+ case gl.RGBA8UI: return 'gl.RGBA8UI';
+ case gl.SRGB8_ALPHA8: return 'gl.SRGB8_ALPHA8';
+ case gl.RGB10_A2: return 'gl.RGB10_A2';
+ case gl.RGB10_A2UI: return 'gl.RGB10_A2UI';
+ case gl.RGBA8_SNORM: return 'gl.RGBA8_SNORM';
+ case gl.RGB8: return 'gl.RGB8';
+ case gl.R11F_G11F_B10F: return 'gl.R11F_G11F_B10F';
+ case gl.RGB32F: return 'gl.RGB32F';
+ case gl.RGB32I: return 'gl.RGB32I';
+ case gl.RGB32UI: return 'gl.RGB32UI';
+ // case gl.RGB16: return 'gl.RGB16';
+ // case gl.RGB16_SNORM: return 'gl.RGB16_SNORM';
+ case gl.RGB16F: return 'gl.RGB16F';
+ case gl.RGB16I: return 'gl.RGB16I';
+ case gl.RGB16UI: return 'gl.RGB16UI';
+ case gl.RGB8_SNORM: return 'gl.RGB8_SNORM';
+ case gl.RGB8I: return 'gl.RGB8I';
+ case gl.RGB8UI: return 'gl.RGB8UI';
+ case gl.SRGB8: return 'gl.SRGB8';
+ case gl.RGB9_E5: return 'gl.RGB9_E5';
+ case gl.RG32F: return 'gl.RG32F';
+ case gl.RG32I: return 'gl.RG32I';
+ case gl.RG32UI: return 'gl.RG32UI';
+ // case gl.RG16: return 'gl.RG16';
+ // case gl.RG16_SNORM: return 'gl.RG16_SNORM';
+ case gl.RG16F: return 'gl.RG16F';
+ case gl.RG16I: return 'gl.RG16I';
+ case gl.RG16UI: return 'gl.RG16UI';
+ case gl.RG8: return 'gl.RG8';
+ case gl.RG8I: return 'gl.RG8I';
+ case gl.RG8UI: return 'gl.RG8UI';
+ case gl.RG8_SNORM: return 'gl.RG8_SNORM';
+ case gl.R32F: return 'gl.R32F';
+ case gl.R32I: return 'gl.R32I';
+ case gl.R32UI: return 'gl.R32UI';
+ // case gl.R16: return 'gl.R16';
+ // case gl.R16_SNORM: return 'gl.R16_SNORM';
+ case gl.R16F: return 'gl.R16F';
+ case gl.R16I: return 'gl.R16I';
+ case gl.R16UI: return 'gl.R16UI';
+ case gl.R8: return 'gl.R8';
+ case gl.R8I: return 'gl.R8I';
+ case gl.R8UI: return 'gl.R8UI';
+ case gl.R8_SNORM: return 'gl.R8_SNORM';
+ case gl.DEPTH_COMPONENT32F: return 'gl.DEPTH_COMPONENT32F';
+ case gl.DEPTH_COMPONENT24: return 'gl.DEPTH_COMPONENT24';
+ case gl.DEPTH32F_STENCIL8: return 'gl.DEPTH32F_STENCIL8';
+ case gl.DEPTH24_STENCIL8: return 'gl.DEPTH24_STENCIL8';
+ // case gl.RGB10: return 'gl.RGB10';
+ // case gl.DEPTH_COMPONENT32: return 'gl.DEPTH_COMPONENT32';
+ case gl.SRGB: return 'gl.SRGB';
+ // case gl.SRGB_ALPHA: return 'gl.SRGB_ALPHA';
+ default: return '';
+ }
+};
+
+gluStrUtil.getTypeName = function(value) {
+ switch (value) {
+ case gl.BYTE: return 'gl.BYTE';
+ case gl.UNSIGNED_BYTE: return 'gl.UNSIGNED_BYTE';
+ case gl.SHORT: return 'gl.SHORT';
+ case gl.UNSIGNED_SHORT: return 'gl.UNSIGNED_SHORT';
+ case gl.INT: return 'gl.INT';
+ case gl.UNSIGNED_INT: return 'gl.UNSIGNED_INT';
+ case gl.FLOAT: return 'gl.FLOAT';
+ // case gl.FIXED: return 'gl.FIXED';
+ case gl.UNSIGNED_SHORT_5_6_5: return 'gl.UNSIGNED_SHORT_5_6_5';
+ case gl.UNSIGNED_SHORT_4_4_4_4: return 'gl.UNSIGNED_SHORT_4_4_4_4';
+ case gl.UNSIGNED_SHORT_5_5_5_1: return 'gl.UNSIGNED_SHORT_5_5_5_1';
+ case gl.HALF_FLOAT: return 'gl.HALF_FLOAT';
+ case gl.INT_2_10_10_10_REV: return 'gl.INT_2_10_10_10_REV';
+ case gl.UNSIGNED_INT_2_10_10_10_REV: return 'gl.UNSIGNED_INT_2_10_10_10_REV';
+ case gl.UNSIGNED_INT_10F_11F_11F_REV: return 'gl.UNSIGNED_INT_10F_11F_11F_REV';
+ case gl.UNSIGNED_INT_5_9_9_9_REV: return 'gl.UNSIGNED_INT_5_9_9_9_REV';
+ case gl.UNSIGNED_INT_24_8: return 'gl.UNSIGNED_INT_24_8';
+ case gl.FLOAT_32_UNSIGNED_INT_24_8_REV: return 'gl.FLOAT_32_UNSIGNED_INT_24_8_REV';
+ case gl.SIGNED_NORMALIZED: return 'gl.SIGNED_NORMALIZED';
+ case gl.UNSIGNED_NORMALIZED: return 'gl.UNSIGNED_NORMALIZED';
+ // case gl.HALF_FLOAT_OES: return 'gl.HALF_FLOAT_OES';
+ default: return '';
+ }
+};
+
+gluStrUtil.getErrorName = function(value) {
+ switch (value) {
+ case gl.NO_ERROR: return 'gl.NO_ERROR';
+ case gl.INVALID_ENUM: return 'gl.INVALID_ENUM';
+ case gl.INVALID_VALUE: return 'gl.INVALID_VALUE';
+ case gl.INVALID_OPERATION: return 'gl.INVALID_OPERATION';
+ case gl.OUT_OF_MEMORY: return 'gl.OUT_OF_MEMORY';
+ // case gl.INVALID_FRAMEBUFFER_OPERATION: return 'gl.INVALID_FRAMEBUFFER_OPERATION';
+ default: return '';
+ }
+};
+
+gluStrUtil.getFramebufferStatusName = function(value) {
+ switch (value) {
+ case gl.FRAMEBUFFER_COMPLETE: return 'gl.FRAMEBUFFER_COMPLETE';
+ case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return 'gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT';
+ case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return 'gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT';
+ case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return 'gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS';
+ case gl.FRAMEBUFFER_UNSUPPORTED: return 'gl.FRAMEBUFFER_UNSUPPORTED';
+ case gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return 'gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE';
+ // case: gl.FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: return 'gl.FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS';
+ default: return '';
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTexture.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTexture.js
new file mode 100644
index 0000000000..fcc33588e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTexture.js
@@ -0,0 +1,380 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluTexture');
+goog.require('framework.common.tcuCompressedTexture');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var gluTexture = framework.opengl.gluTexture;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var tcuCompressedTexture = framework.common.tcuCompressedTexture;
+var deMath = framework.delibs.debase.deMath;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/** @enum {number} */
+gluTexture.Type = {
+ TYPE_NONE: 0,
+ TYPE_2D: 1,
+ TYPE_CUBE_MAP: 2,
+ TYPE_2D_ARRAY: 3,
+ TYPE_3D: 4
+};
+
+/**
+ * @constructor
+ */
+gluTexture.Texture2D = function(gl, format, isCompressed, refTexture) {
+ this.gl = gl;
+ this.m_glTexture = gl.createTexture();
+ this.m_isCompressed = isCompressed;
+ this.m_format = format; // Internal format
+ this.m_refTexture = refTexture;
+ this.m_type = gluTexture.Type.TYPE_2D;
+};
+
+gluTexture.Texture2D.prototype.getType = function() {
+ return this.m_type;
+};
+
+gluTexture.Texture2D.prototype.getRefTexture = function() {
+ return this.m_refTexture;
+};
+
+gluTexture.Texture2D.prototype.getGLTexture = function() {
+ return this.m_glTexture;
+};
+
+gluTexture.texture2DFromFormat = function(gl, format, dataType, width, height) {
+ var tex = new gluTexture.Texture2D(gl, format, false, new tcuTexture.Texture2D(gluTextureUtil.mapGLTransferFormat(format, dataType), width, height));
+ return tex;
+};
+
+gluTexture.texture2DFromInternalFormat = function(gl, internalFormat, width, height) {
+ var tex = new gluTexture.Texture2D(gl, internalFormat, false, new tcuTexture.Texture2D(gluTextureUtil.mapGLInternalFormat(internalFormat), width, height));
+ return tex;
+};
+
+/**
+ * @param {number} numLevels
+ * @param {Array<tcuCompressedTexture.CompressedTexture>} levels
+ * @return {gluTexture.Texture2D}
+ */
+gluTexture.texture2DFromCompressedTexture = function(gl, numLevels, levels) {
+ var level = levels[0];
+ var format = gluTextureUtil.getGLFormat(level.getFormat());
+ var refTex = new tcuTexture.Texture2D(level.getUncompressedFormat(), level.getWidth(), level.getHeight());
+ /** @type {gluTexture.Texture2D} */ var tex2d = new gluTexture.Texture2D(gl, format, true, refTex);
+
+ tex2d.loadCompressed(numLevels, levels);
+
+ return tex2d;
+};
+/**
+ * @param {number} numLevels
+ * @param {Array<tcuCompressedTexture.CompressedTexture>} levels
+ */
+gluTexture.Texture2D.prototype.loadCompressed = function(numLevels, levels) {
+ /** @type {number} */ var compressedFormat = gluTextureUtil.getGLFormat(levels[0].getFormat());
+
+ assertMsgOptions(this.m_glTexture, 'm_glTexture not defined', false, true);
+ gl.bindTexture(gl.TEXTURE_2D, this.m_glTexture);
+
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ /** @type {tcuCompressedTexture.CompressedTexture} */ var level = levels[levelNdx];
+
+ // Decompress to reference texture.
+ this.m_refTexture.allocLevel(levelNdx);
+ /** @type {tcuTexture.PixelBufferAccess} */ var refLevelAccess = this.m_refTexture.getLevel(levelNdx);
+ assertMsgOptions(level.getWidth() == refLevelAccess.getWidth() && level.getHeight() == refLevelAccess.getHeight(), 'level and reference sizes not equal', false, true);
+ level.decompress(refLevelAccess);
+
+ // Upload to GL texture in compressed form.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, levelNdx, compressedFormat,
+ level.getWidth(), level.getHeight(), 0, level.getData());
+ }
+};
+
+gluTexture.computePixelStore = function(/*const tcu::TextureFormat&*/ format) {
+ var pixelSize = format.getPixelSize();
+ if (deMath.deIsPowerOfTwo32(pixelSize))
+ return Math.min(pixelSize, 8);
+ else
+ return 1;
+};
+
+gluTexture.cubeFaceToGLFace = function(/*tcu::CubeFace*/ face) {
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return gl.TEXTURE_CUBE_MAP_NEGATIVE_X;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return gl.TEXTURE_CUBE_MAP_POSITIVE_X;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return gl.TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return gl.TEXTURE_CUBE_MAP_POSITIVE_Y;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return gl.TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return gl.TEXTURE_CUBE_MAP_POSITIVE_Z;
+ }
+ throw new Error('Unrecognized face: ' + face);
+};
+
+gluTexture.Texture2D.prototype.upload = function() {
+ DE_ASSERT(!this.m_isCompressed);
+
+ if (this.m_glTexture == null)
+ testFailedOptions('Failed to create GL texture', true);
+
+ gl.bindTexture(gl.TEXTURE_2D, this.m_glTexture);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat()));
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Setting pixel store failed', false, true);
+
+ var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat());
+
+ for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) {
+ if (this.m_refTexture.isLevelEmpty(levelNdx))
+ continue; // Don't upload.
+
+ var access = this.m_refTexture.getLevel(levelNdx);
+ DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
+ var data = access.getDataPtr();
+ gl.texImage2D(gl.TEXTURE_2D, levelNdx, this.m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+};
+
+/**
+ * @constructor
+ * @extends {gluTexture.Texture2D}
+ */
+gluTexture.TextureCube = function(gl, format, isCompressed, refTexture) {
+ gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture);
+ this.m_type = gluTexture.Type.TYPE_CUBE_MAP;
+};
+
+gluTexture.TextureCube.prototype = Object.create(gluTexture.Texture2D.prototype);
+gluTexture.TextureCube.prototype.constructor = gluTexture.TextureCube;
+
+gluTexture.TextureCube.prototype.upload = function() {
+ DE_ASSERT(!this.m_isCompressed);
+
+ if (this.m_glTexture == null)
+ testFailedOptions('Failed to create GL texture', true);
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.m_glTexture);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat()));
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Setting pixel store failed', false, true);
+
+ var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat());
+
+ for (var face in tcuTexture.CubeFace) {
+ for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) {
+ if (this.m_refTexture.isLevelEmpty(tcuTexture.CubeFace[face], levelNdx))
+ continue; // Don't upload.
+
+ /*tcu::ConstPixelBufferAccess*/ var access = this.m_refTexture.getLevelFace(levelNdx, tcuTexture.CubeFace[face]);
+ DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
+ gl.texImage2D(gluTexture.cubeFaceToGLFace(tcuTexture.CubeFace[face]), levelNdx, this.m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
+ }
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+};
+
+gluTexture.cubeFromFormat = function(gl, format, dataType, size) {
+ var tex = new gluTexture.TextureCube(gl, format, false, new tcuTexture.TextureCube(gluTextureUtil.mapGLTransferFormat(format, dataType), size));
+ return tex;
+};
+
+gluTexture.cubeFromInternalFormat = function(gl, internalFormat, size) {
+ var tex = new gluTexture.TextureCube(gl, internalFormat, false, new tcuTexture.TextureCube(gluTextureUtil.mapGLInternalFormat(internalFormat), size));
+ return tex;
+};
+
+/**
+ * @constructor
+ * @extends {gluTexture.Texture2D}
+ */
+gluTexture.Texture2DArray = function(gl, format, isCompressed, refTexture) {
+ gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture);
+ this.m_type = gluTexture.Type.TYPE_2D_ARRAY;
+};
+
+gluTexture.Texture2DArray.prototype = Object.create(gluTexture.Texture2D.prototype);
+gluTexture.Texture2DArray.prototype.constructor = gluTexture.Texture2DArray;
+
+gluTexture.Texture2DArray.prototype.upload = function() {
+ if (!gl.texImage3D)
+ throw new Error('gl.TexImage3D() is not supported');
+
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.m_glTexture);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat()));
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+
+ var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat());
+
+ for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) {
+ if (this.m_refTexture.isLevelEmpty(levelNdx))
+ continue; // Don't upload.
+
+ /*tcu::ConstPixelBufferAccess*/ var access = this.m_refTexture.getLevel(levelNdx);
+ DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
+ DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight());
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, levelNdx, this.m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+};
+
+gluTexture.texture2DArrayFromFormat = function(gl, format, dataType, width, height, numLayers) {
+ var tex = new gluTexture.Texture2DArray(gl, format, false, new tcuTexture.Texture2DArray(gluTextureUtil.mapGLTransferFormat(format, dataType), width, height, numLayers));
+ return tex;
+};
+
+gluTexture.texture2DArrayFromInternalFormat = function(gl, internalFormat, width, height, numLayers) {
+ var tex = new gluTexture.Texture2DArray(gl, internalFormat, false, new tcuTexture.Texture2DArray(gluTextureUtil.mapGLInternalFormat(internalFormat), width, height, numLayers));
+ return tex;
+};
+
+/**
+ * @constructor
+ * @extends {gluTexture.Texture2D}
+ */
+gluTexture.Texture3D = function(gl, format, isCompressed, refTexture) {
+ gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture);
+ this.m_type = gluTexture.Type.TYPE_3D;
+};
+
+gluTexture.Texture3D.prototype = Object.create(gluTexture.Texture2D.prototype);
+gluTexture.Texture3D.prototype.constructor = gluTexture.Texture3D;
+
+gluTexture.Texture3D.prototype.upload = function() {
+ if (!gl.texImage3D)
+ throw new Error('gl.TexImage3D() is not supported');
+
+ gl.bindTexture(gl.TEXTURE_3D, this.m_glTexture);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat()));
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+
+ var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat());
+
+ for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) {
+ if (this.m_refTexture.isLevelEmpty(levelNdx))
+ continue; // Don't upload.
+
+ /*tcu::ConstPixelBufferAccess*/ var access = this.m_refTexture.getLevel(levelNdx);
+ DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
+ DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight());
+ gl.texImage3D(gl.TEXTURE_3D, levelNdx, this.m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+};
+
+gluTexture.texture3DFromFormat = function(gl, format, dataType, width, height, depth) {
+ var tex = new gluTexture.Texture3D(gl, format, false, new tcuTexture.Texture3D(gluTextureUtil.mapGLTransferFormat(format, dataType), width, height, depth));
+ return tex;
+};
+
+gluTexture.texture3DFromInternalFormat = function(gl, internalFormat, width, height, depth) {
+ var tex = new gluTexture.Texture3D(gl, internalFormat, false, new tcuTexture.Texture3D(gluTextureUtil.mapGLInternalFormat(internalFormat), width, height, depth));
+ return tex;
+};
+
+/**
+ * @constructor
+ * @extends {gluTexture.Texture2D}
+ */
+gluTexture.Compressed2D = function(gl, format, isCompressed, refTexture) {
+ gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture);
+};
+
+gluTexture.Compressed2D.prototype = Object.create(gluTexture.Texture2D.prototype);
+gluTexture.Compressed2D.prototype.constructor = gluTexture.Compressed2D;
+
+gluTexture.Compressed2D.prototype.uploadLevel = function(level, source) {
+ DE_ASSERT(this.m_isCompressed);
+
+ if (this.m_glTexture == null)
+ testFailedOptions('Failed to create GL texture', true);
+
+ gl.bindTexture(gl.TEXTURE_2D, this.m_glTexture);
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, level, this.m_format, source.m_width, source.m_height, 0 /* border */, source.m_data);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+};
+
+/**
+ * @constructor
+ * @extends {gluTexture.Texture2D}
+ */
+gluTexture.CompressedCube = function(gl, format, isCompressed, refTexture) {
+ gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture);
+};
+
+gluTexture.CompressedCube.prototype = Object.create(gluTexture.Texture2D.prototype);
+gluTexture.CompressedCube.prototype.constructor = gluTexture.CompressedCube;
+
+gluTexture.CompressedCube.prototype.uploadLevel = function(level, source) {
+ DE_ASSERT(this.m_isCompressed);
+
+ if (this.m_glTexture == null)
+ testFailedOptions('Failed to create GL texture', true);
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.m_glTexture);
+
+ for (var face in tcuTexture.CubeFace) {
+
+ // Upload to GL texture in compressed form.
+ gl.compressedTexImage2D(gluTexture.cubeFaceToGLFace(tcuTexture.CubeFace[face]), 0, this.m_format,
+ source.m_width, source.m_height, 0 /* border */, source.m_data);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true);
+ }
+
+};
+
+gluTexture.compressed2DFromInternalFormat = function(gl, format, width, height, compressed) {
+ var tex = new gluTexture.Compressed2D(gl, gluTextureUtil.getGLFormat(format), true, new tcuTexture.Texture2D(compressed.getUncompressedFormat(), width, height));
+ tex.m_refTexture.allocLevel(0);
+ compressed.decompress(tex.m_refTexture.getLevel(0));
+ tex.uploadLevel(0, compressed);
+ return tex;
+};
+
+gluTexture.compressedCubeFromInternalFormat = function(gl, format, size, compressed) {
+ var tex = new gluTexture.CompressedCube(gl, gluTextureUtil.getGLFormat(format), true, new tcuTexture.TextureCube(compressed.getUncompressedFormat(), size));
+ for (var face in tcuTexture.CubeFace) {
+ tex.m_refTexture.allocLevel(tcuTexture.CubeFace[face], 0);
+
+ /*tcu::ConstPixelBufferAccess*/ var access = tex.m_refTexture.getLevelFace(0, tcuTexture.CubeFace[face]);
+ DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
+ compressed.decompress(access);
+ }
+ tex.uploadLevel(0, compressed);
+ return tex;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTextureUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTextureUtil.js
new file mode 100644
index 0000000000..06f3f5289d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluTextureUtil.js
@@ -0,0 +1,1025 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Map tcuTexture.TextureFormat to GL pixel transfer format.
+ *
+ * Maps generic texture format description to GL pixel transfer format.
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * \param texFormat Generic texture format.
+ * \return GL pixel transfer format.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('framework.opengl.gluTextureUtil');
+goog.require('framework.common.tcuCompressedTexture');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var deString = framework.delibs.debase.deString;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuCompressedTexture = framework.common.tcuCompressedTexture;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+/**
+ * @param {number} format
+ * @param {number} dataType
+ * @constructor
+ */
+gluTextureUtil.TransferFormat = function(format, dataType) {
+ this.format = format; //!< Pixel format.
+ this.dataType = dataType; //!< Data type.
+};
+
+/**
+ * Map tcuTexture.TextureFormat to GL pixel transfer format.
+ *
+ * Maps generic texture format description to GL pixel transfer format.
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * @param {tcuTexture.TextureFormat} texFormat Generic texture format.
+ * @return {gluTextureUtil.TransferFormat} GL pixel transfer format.
+ * @throws {Error}
+ */
+gluTextureUtil.getTransferFormat = function(/* tcuTexture.TextureFormat */ texFormat) {
+ var format = gl.NONE;
+ var type = gl.NONE;
+ /*boolean*/ var isInt = false;
+
+ switch (texFormat.type) {
+ case tcuTexture.ChannelType.SIGNED_INT8:
+ case tcuTexture.ChannelType.SIGNED_INT16:
+ case tcuTexture.ChannelType.SIGNED_INT32:
+ case tcuTexture.ChannelType.UNSIGNED_INT8:
+ case tcuTexture.ChannelType.UNSIGNED_INT16:
+ case tcuTexture.ChannelType.UNSIGNED_INT32:
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV:
+ isInt = true;
+ break;
+
+ default:
+ isInt = false;
+ break;
+ }
+
+ switch (texFormat.order) {
+ case tcuTexture.ChannelOrder.A: format = gl.ALPHA; break;
+ case tcuTexture.ChannelOrder.L: format = gl.LUMINANCE; break;
+ case tcuTexture.ChannelOrder.LA: format = gl.LUMINANCE_ALPHA; break;
+ case tcuTexture.ChannelOrder.R: format = isInt ? gl.RED_INTEGER : gl.RED; break;
+ case tcuTexture.ChannelOrder.RG: format = isInt ? gl.RG_INTEGER : gl.RG; break;
+ case tcuTexture.ChannelOrder.RGB: format = isInt ? gl.RGB_INTEGER : gl.RGB; break;
+ case tcuTexture.ChannelOrder.RGBA: format = isInt ? gl.RGBA_INTEGER : gl.RGBA; break;
+ case tcuTexture.ChannelOrder.sRGB: format = gl.RGB; break;
+ case tcuTexture.ChannelOrder.sRGBA: format = gl.RGBA; break;
+ case tcuTexture.ChannelOrder.D: format = gl.DEPTH_COMPONENT; break;
+ case tcuTexture.ChannelOrder.DS: format = gl.DEPTH_STENCIL; break;
+ case tcuTexture.ChannelOrder.S: format = gl.STENCIL_INDEX; break;
+
+ default:
+ throw new Error('Unknown ChannelOrder ' + texFormat.order);
+ }
+
+ switch (texFormat.type) {
+ case tcuTexture.ChannelType.SNORM_INT8: type = gl.BYTE; break;
+ case tcuTexture.ChannelType.SNORM_INT16: type = gl.SHORT; break;
+ case tcuTexture.ChannelType.UNORM_INT8: type = gl.UNSIGNED_BYTE; break;
+ case tcuTexture.ChannelType.UNORM_INT16: type = gl.UNSIGNED_SHORT; break;
+ case tcuTexture.ChannelType.UNORM_SHORT_565: type = gl.UNSIGNED_SHORT_5_6_5; break;
+ case tcuTexture.ChannelType.UNORM_SHORT_4444: type = gl.UNSIGNED_SHORT_4_4_4_4; break;
+ case tcuTexture.ChannelType.UNORM_SHORT_5551: type = gl.UNSIGNED_SHORT_5_5_5_1; break;
+ case tcuTexture.ChannelType.SIGNED_INT8: type = gl.BYTE; break;
+ case tcuTexture.ChannelType.SIGNED_INT16: type = gl.SHORT; break;
+ case tcuTexture.ChannelType.SIGNED_INT32: type = gl.INT; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT8: type = gl.UNSIGNED_BYTE; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT16: type = gl.UNSIGNED_SHORT; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT32: type = gl.UNSIGNED_INT; break;
+ case tcuTexture.ChannelType.FLOAT: type = gl.FLOAT; break;
+ case tcuTexture.ChannelType.UNORM_INT_101010: type = gl.UNSIGNED_INT_2_10_10_10_REV; break;
+ case tcuTexture.ChannelType.UNORM_INT_1010102_REV: type = gl.UNSIGNED_INT_2_10_10_10_REV; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: type = gl.UNSIGNED_INT_2_10_10_10_REV; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: type = gl.UNSIGNED_INT_10F_11F_11F_REV; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: type = gl.UNSIGNED_INT_5_9_9_9_REV; break;
+ case tcuTexture.ChannelType.HALF_FLOAT: type = gl.HALF_FLOAT; break;
+ case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: type = gl.FLOAT_32_UNSIGNED_INT_24_8_REV; break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8: type = texFormat.order == tcuTexture.ChannelOrder.D ?
+ gl.UNSIGNED_INT : gl.UNSIGNED_INT_24_8; break;
+
+ default:
+ throw new Error("Can't map texture format to GL transfer format " + texFormat.type);
+ }
+
+ return new gluTextureUtil.TransferFormat(format, type);
+};
+
+/**
+ * Map tcuTexture.TextureFormat to GL internal sized format.
+ *
+ * Maps generic texture format description to GL internal format.
+ * If no mapping is found, throws Error.
+ *
+ * @param {tcuTexture.TextureFormat} texFormat Generic texture format.
+ * @return {number} GL texture format.
+ * @throws {Error}
+ */
+gluTextureUtil.getInternalFormat = function(texFormat) {
+
+ var stringify = function(order, type) {
+ return '' + order + ' ' + type;
+ };
+
+ switch (stringify(texFormat.order, texFormat.type)) {
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_5551): return gl.RGB5_A1;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_4444): return gl.RGBA4;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_SHORT_565): return gl.RGB565;
+ case stringify(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNORM_INT16): return gl.DEPTH_COMPONENT16;
+ case stringify(tcuTexture.ChannelOrder.S, tcuTexture.ChannelType.UNSIGNED_INT8): return gl.STENCIL_INDEX8;
+
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT): return gl.RGBA32F;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT32): return gl.RGBA32I;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32): return gl.RGBA32UI;
+ // TODO: Check which ones are valid in WebGL 2 - case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT16): return gl.RGBA16;
+ //case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SNORM_INT16): return gl.RGBA16_SNORM;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.HALF_FLOAT): return gl.RGBA16F;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT16): return gl.RGBA16I;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT16): return gl.RGBA16UI;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8): return gl.RGBA8;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT8): return gl.RGBA8I;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT8): return gl.RGBA8UI;
+ case stringify(tcuTexture.ChannelOrder.sRGBA, tcuTexture.ChannelType.UNORM_INT8): return gl.SRGB8_ALPHA8;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT_1010102_REV): return gl.RGB10_A2;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV): return gl.RGB10_A2UI;
+ case stringify(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SNORM_INT8): return gl.RGBA8_SNORM;
+
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8): return gl.RGB8;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV): return gl.R11F_G11F_B10F;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.FLOAT): return gl.RGB32F;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SIGNED_INT32): return gl.RGB32I;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT32): return gl.RGB32UI;
+ //case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT16): return gl.RGB16;
+ //case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SNORM_INT16): return gl.RGB16_SNORM;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.HALF_FLOAT): return gl.RGB16F;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SIGNED_INT16): return gl.RGB16I;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT16): return gl.RGB16UI;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SNORM_INT8): return gl.RGB8_SNORM;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SIGNED_INT8): return gl.RGB8I;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT8): return gl.RGB8UI;
+ case stringify(tcuTexture.ChannelOrder.sRGB, tcuTexture.ChannelType.UNORM_INT8): return gl.SRGB8;
+ case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV): return gl.RGB9_E5;
+ //case stringify(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT_1010102_REV): return gl.RGB10;
+
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.FLOAT): return gl.RG32F;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SIGNED_INT32): return gl.RG32I;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNSIGNED_INT32): return gl.RG32UI;
+ //case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNORM_INT16): return gl.RG16;
+ //case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT16): return gl.RG16_SNORM;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.HALF_FLOAT): return gl.RG16F;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SIGNED_INT16): return gl.RG16I;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNSIGNED_INT16): return gl.RG16UI;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNORM_INT8): return gl.RG8;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SIGNED_INT8): return gl.RG8I;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNSIGNED_INT8): return gl.RG8UI;
+ case stringify(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT8): return gl.RG8_SNORM;
+
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.FLOAT): return gl.R32F;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SIGNED_INT32): return gl.R32I;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNSIGNED_INT32): return gl.R32UI;
+ //case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNORM_INT16): return gl.R16;
+ //case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SNORM_INT16): return gl.R16_SNORM;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.HALF_FLOAT): return gl.R16F;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SIGNED_INT16): return gl.R16I;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNSIGNED_INT16): return gl.R16UI;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNORM_INT8): return gl.R8;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SIGNED_INT8): return gl.R8I;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNSIGNED_INT8): return gl.R8UI;
+ case stringify(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SNORM_INT8): return gl.R8_SNORM;
+
+ case stringify(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.FLOAT): return gl.DEPTH_COMPONENT32F;
+ case stringify(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNSIGNED_INT_24_8): return gl.DEPTH_COMPONENT24;
+ //case stringify(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNSIGNED_INT32): return gl.DEPTH_COMPONENT32;
+ case stringify(tcuTexture.ChannelOrder.DS, tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV): return gl.DEPTH32F_STENCIL8;
+ case stringify(tcuTexture.ChannelOrder.DS, tcuTexture.ChannelType.UNSIGNED_INT_24_8): return gl.DEPTH24_STENCIL8;
+
+ default:
+ throw new Error("Can't map texture format to GL internal format");
+ }
+};
+
+/**
+ * Enable WEBGL_compressed_texture_etc support if available, by merging it
+ * into the WebGL2RenderingContext.
+ *
+ * This function may be called many times.
+ *
+ * @return {boolean} True if enabled.
+ */
+gluTextureUtil.enableCompressedTextureETC = (function() {
+ var enabled = undefined;
+ return function() {
+ if (enabled === undefined) {
+ enabled = false;
+
+ var WEBGL_compressed_texture_etc = gl.getExtension("WEBGL_compressed_texture_etc");
+ if (WEBGL_compressed_texture_etc) {
+ // Extend gl with enums from WEBGL_compressed_texture_etc
+ // (if it doesn't already have the etc texture formats).
+ var proto = Object.getPrototypeOf(WEBGL_compressed_texture_etc);
+ for (var prop in proto) {
+ if (proto.hasOwnProperty(prop)) {
+ gl[prop] = proto[prop];
+ }
+ }
+ enabled = true;
+ }
+ }
+ return enabled;
+ };
+})();
+
+/**
+ * Map generic compressed format to GL compressed format enum.
+ *
+ * Maps generic compressed format to GL compressed format enum value.
+ * If no mapping is found, throws Error.
+
+ * @param {tcuCompressedTexture.Format} format Generic compressed format.
+ * @return {number} GL compressed texture format.
+ * @throws {Error}
+ */
+gluTextureUtil.getGLFormat = function(/* tcuCompressedTexture.Format */ format) {
+ switch (format) {
+ // TODO: check which are available in WebGL 2 - case tcuCompressedTexture.Format.ETC1_RGB8: return gl.ETC1_RGB8_OES;
+ case tcuCompressedTexture.Format.EAC_R11: return gl.COMPRESSED_R11_EAC;
+ case tcuCompressedTexture.Format.EAC_SIGNED_R11: return gl.COMPRESSED_SIGNED_R11_EAC;
+ case tcuCompressedTexture.Format.EAC_RG11: return gl.COMPRESSED_RG11_EAC;
+ case tcuCompressedTexture.Format.EAC_SIGNED_RG11: return gl.COMPRESSED_SIGNED_RG11_EAC;
+ case tcuCompressedTexture.Format.ETC2_RGB8: return gl.COMPRESSED_RGB8_ETC2;
+ case tcuCompressedTexture.Format.ETC2_SRGB8: return gl.COMPRESSED_SRGB8_ETC2;
+ case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: return gl.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+ case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: return gl.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+ case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: return gl.COMPRESSED_RGBA8_ETC2_EAC;
+ case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
+
+ /*case tcuCompressedTexture.Format.ASTC_4x4_RGBA: return gl.COMPRESSED_RGBA_ASTC_4x4_KHR;
+ case tcuCompressedTexture.Format.ASTC_5x4_RGBA: return gl.COMPRESSED_RGBA_ASTC_5x4_KHR;
+ case tcuCompressedTexture.Format.ASTC_5x5_RGBA: return gl.COMPRESSED_RGBA_ASTC_5x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_6x5_RGBA: return gl.COMPRESSED_RGBA_ASTC_6x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_6x6_RGBA: return gl.COMPRESSED_RGBA_ASTC_6x6_KHR;
+ case tcuCompressedTexture.Format.ASTC_8x5_RGBA: return gl.COMPRESSED_RGBA_ASTC_8x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_8x6_RGBA: return gl.COMPRESSED_RGBA_ASTC_8x6_KHR;
+ case tcuCompressedTexture.Format.ASTC_8x8_RGBA: return gl.COMPRESSED_RGBA_ASTC_8x8_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x5_RGBA: return gl.COMPRESSED_RGBA_ASTC_10x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x6_RGBA: return gl.COMPRESSED_RGBA_ASTC_10x6_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x8_RGBA: return gl.COMPRESSED_RGBA_ASTC_10x8_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x10_RGBA: return gl.COMPRESSED_RGBA_ASTC_10x10_KHR;
+ case tcuCompressedTexture.Format.ASTC_12x10_RGBA: return gl.COMPRESSED_RGBA_ASTC_12x10_KHR;
+ case tcuCompressedTexture.Format.ASTC_12x12_RGBA: return gl.COMPRESSED_RGBA_ASTC_12x12_KHR;
+ case tcuCompressedTexture.Format.ASTC_4x4_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
+ case tcuCompressedTexture.Format.ASTC_5x4_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
+ case tcuCompressedTexture.Format.ASTC_5x5_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_6x5_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_6x6_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
+ case tcuCompressedTexture.Format.ASTC_8x5_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_8x6_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
+ case tcuCompressedTexture.Format.ASTC_8x8_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x5_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x6_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x8_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
+ case tcuCompressedTexture.Format.ASTC_10x10_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
+ case tcuCompressedTexture.Format.ASTC_12x10_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
+ case tcuCompressedTexture.Format.ASTC_12x12_SRGB8_ALPHA8: return gl.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;*/
+
+ default:
+ throw new Error("Can't map compressed format to GL format");
+ }
+};
+
+/**
+ * @param {number} dataType
+ * @param {boolean} normalized
+ * @return {tcuTexture.ChannelType}
+ * @throws {Error}
+ */
+gluTextureUtil.mapGLChannelType = function(/* deMath.deUint32 */ dataType, /*boolean*/ normalized) {
+ // \note Normalized bit is ignored where it doesn't apply.
+
+ switch (dataType) {
+ case gl.UNSIGNED_BYTE: return normalized ? tcuTexture.ChannelType.UNORM_INT8 : tcuTexture.ChannelType.UNSIGNED_INT8;
+ case gl.BYTE: return normalized ? tcuTexture.ChannelType.SNORM_INT8 : tcuTexture.ChannelType.SIGNED_INT8;
+ case gl.UNSIGNED_SHORT: return normalized ? tcuTexture.ChannelType.UNORM_INT16 : tcuTexture.ChannelType.UNSIGNED_INT16;
+ case gl.SHORT: return normalized ? tcuTexture.ChannelType.SNORM_INT16 : tcuTexture.ChannelType.SIGNED_INT16;
+ case gl.UNSIGNED_INT: return normalized ? tcuTexture.ChannelType.UNORM_INT32 : tcuTexture.ChannelType.UNSIGNED_INT32;
+ case gl.INT: return normalized ? tcuTexture.ChannelType.SNORM_INT32 : tcuTexture.ChannelType.SIGNED_INT32;
+ case gl.FLOAT: return tcuTexture.ChannelType.FLOAT;
+ case gl.UNSIGNED_SHORT_4_4_4_4: return tcuTexture.ChannelType.UNORM_SHORT_4444;
+ case gl.UNSIGNED_SHORT_5_5_5_1: return tcuTexture.ChannelType.UNORM_SHORT_5551;
+ case gl.UNSIGNED_SHORT_5_6_5: return tcuTexture.ChannelType.UNORM_SHORT_565;
+ case gl.HALF_FLOAT: return tcuTexture.ChannelType.HALF_FLOAT;
+ case gl.UNSIGNED_INT_2_10_10_10_REV: return normalized ? tcuTexture.ChannelType.UNORM_INT_1010102_REV : tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV;
+ case gl.UNSIGNED_INT_10F_11F_11F_REV: return tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV;
+ case gl.UNSIGNED_INT_24_8: return tcuTexture.ChannelType.UNSIGNED_INT_24_8;
+ case gl.FLOAT_32_UNSIGNED_INT_24_8_REV: return tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV;
+ case gl.UNSIGNED_INT_5_9_9_9_REV: return tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV;
+
+ default:
+ throw new Error('Unsupported dataType ' + dataType);
+ }
+};
+
+/**
+ * @param {number} format Generic compressed format.
+ * @param {number} dataType
+ * @return {tcuTexture.TextureFormat} GL texture format.
+ * @throws {Error}
+ */
+gluTextureUtil.mapGLTransferFormat = function(format, dataType) {
+ switch (format) {
+ case gl.ALPHA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.A, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.LUMINANCE: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.L, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.LUMINANCE_ALPHA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.LA, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.RGB: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.RGBA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, gluTextureUtil.mapGLChannelType(dataType, true));
+ //case gl.BGRA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.BGRA, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.RG: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.RED: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.RGBA_INTEGER: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, gluTextureUtil.mapGLChannelType(dataType, false));
+ case gl.RGB_INTEGER: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, gluTextureUtil.mapGLChannelType(dataType, false));
+ case gl.RG_INTEGER: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, gluTextureUtil.mapGLChannelType(dataType, false));
+ case gl.RED_INTEGER: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, gluTextureUtil.mapGLChannelType(dataType, false));
+
+ case gl.DEPTH_COMPONENT: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, gluTextureUtil.mapGLChannelType(dataType, true));
+ case gl.DEPTH_STENCIL: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.DS, gluTextureUtil.mapGLChannelType(dataType, true));
+
+ default:
+ throw new Error("Can't map GL pixel format (" + deString.enumToString(gl, format) + ', ' + deString.enumToString(gl, dataType) + ') to texture format');
+ }
+};
+
+ /**
+ * Map GL internal texture format to tcuTexture.TextureFormat.
+ *
+ * If no mapping is found, throws Error.
+ * @param {number} internalFormat
+ * @return {tcuTexture.TextureFormat} GL texture format.
+ * @throws {Error}
+ */
+gluTextureUtil.mapGLInternalFormat = function(/*deMath.deUint32*/ internalFormat) {
+ if (internalFormat === undefined)
+ throw new Error('internalformat is undefined');
+
+ switch (internalFormat) {
+ case gl.RGB5_A1: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_5551);
+ case gl.RGBA4: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_4444);
+ case gl.RGB565: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_SHORT_565);
+ case gl.DEPTH_COMPONENT16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNORM_INT16);
+ case gl.STENCIL_INDEX8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.S, tcuTexture.ChannelType.UNSIGNED_INT8);
+
+ case gl.RGBA32F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT);
+ case gl.RGBA32I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT32);
+ case gl.RGBA32UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32);
+ //TODO: Check which are available in WebGL 2 case gl.RGBA16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT16);
+ //case gl.RGBA16_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SNORM_INT16);
+ case gl.RGBA16F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.HALF_FLOAT);
+ case gl.RGBA16I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT16);
+ case gl.RGBA16UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT16);
+ case gl.RGBA8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.RGBA8I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT8);
+ case gl.RGBA8UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT8);
+ case gl.SRGB8_ALPHA8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.RGB10_A2: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT_1010102_REV);
+ case gl.RGB10_A2UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV);
+ case gl.RGBA8_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SNORM_INT8);
+
+ case gl.RGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.R11F_G11F_B10F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV);
+ case gl.RGB32F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.FLOAT);
+ case gl.RGB32I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SIGNED_INT32);
+ case gl.RGB32UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT32);
+ //case gl.RGB16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT16);
+ //case gl.RGB16_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SNORM_INT16);
+ case gl.RGB16F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.HALF_FLOAT);
+ case gl.RGB16I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SIGNED_INT16);
+ case gl.RGB16UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT16);
+ case gl.RGB8_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SNORM_INT8);
+ case gl.RGB8I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.SIGNED_INT8);
+ case gl.RGB8UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT8);
+ case gl.SRGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGB, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.RGB9_E5: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV);
+ //case gl.RGB10: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT_1010102_REV);
+
+ case gl.RG32F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.FLOAT);
+ case gl.RG32I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SIGNED_INT32);
+ case gl.RG32UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNSIGNED_INT32);
+ //case gl.RG16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNORM_INT16);
+ //case gl.RG16_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT16);
+ case gl.RG16F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.HALF_FLOAT);
+ case gl.RG16I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SIGNED_INT16);
+ case gl.RG16UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNSIGNED_INT16);
+ case gl.RG8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.RG8I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SIGNED_INT8);
+ case gl.RG8UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNSIGNED_INT8);
+ case gl.RG8_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT8);
+
+ case gl.R32F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.FLOAT);
+ case gl.R32I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SIGNED_INT32);
+ case gl.R32UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNSIGNED_INT32);
+ //case gl.R16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNORM_INT16);
+ //case gl.R16_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SNORM_INT16);
+ case gl.R16F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.HALF_FLOAT);
+ case gl.R16I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SIGNED_INT16);
+ case gl.R16UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNSIGNED_INT16);
+ case gl.R8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.R8I: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SIGNED_INT8);
+ case gl.R8UI: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNSIGNED_INT8);
+ case gl.R8_SNORM: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SNORM_INT8);
+
+ case gl.DEPTH_COMPONENT32F: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.FLOAT);
+ case gl.DEPTH_COMPONENT24: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNSIGNED_INT_24_8);
+ //case gl.DEPTH_COMPONENT32: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNSIGNED_INT32);
+ case gl.DEPTH32F_STENCIL8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.DS, tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV);
+ case gl.DEPTH24_STENCIL8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.DS, tcuTexture.ChannelType.UNSIGNED_INT_24_8);
+
+ default:
+ throw new Error("Can't map GL sized internal format (" + internalFormat.toString(16) + ') to texture format');
+ }
+};
+
+/**
+ * @param {number} format
+ * @return {boolean}
+ */
+gluTextureUtil.isGLInternalColorFormatFilterable = function(format) {
+ switch (format) {
+ case gl.R8:
+ case gl.R8_SNORM:
+ case gl.RG8:
+ case gl.RG8_SNORM:
+ case gl.RGB8:
+ case gl.RGB8_SNORM:
+ case gl.RGB565:
+ case gl.RGBA4:
+ case gl.RGB5_A1:
+ case gl.RGBA8:
+ case gl.RGBA8_SNORM:
+ case gl.RGB10_A2:
+ case gl.SRGB8:
+ case gl.SRGB8_ALPHA8:
+ case gl.R16F:
+ case gl.RG16F:
+ case gl.RGB16F:
+ case gl.RGBA16F:
+ case gl.R11F_G11F_B10F:
+ case gl.RGB9_E5:
+ return true;
+
+ case gl.RGB10_A2UI:
+ case gl.R32F:
+ case gl.RG32F:
+ case gl.RGB32F:
+ case gl.RGBA32F:
+ case gl.R8I:
+ case gl.R8UI:
+ case gl.R16I:
+ case gl.R16UI:
+ case gl.R32I:
+ case gl.R32UI:
+ case gl.RG8I:
+ case gl.RG8UI:
+ case gl.RG16I:
+ case gl.RG16UI:
+ case gl.RG32I:
+ case gl.RG32UI:
+ case gl.RGB8I:
+ case gl.RGB8UI:
+ case gl.RGB16I:
+ case gl.RGB16UI:
+ case gl.RGB32I:
+ case gl.RGB32UI:
+ case gl.RGBA8I:
+ case gl.RGBA8UI:
+ case gl.RGBA16I:
+ case gl.RGBA16UI:
+ case gl.RGBA32I:
+ case gl.RGBA32UI:
+ return false;
+
+ default:
+ throw new Error('Unrecognized format ' + format);
+ }
+};
+
+/**
+ * @param {number} wrapMode
+ * @return {tcuTexture.WrapMode}
+ */
+gluTextureUtil.mapGLWrapMode = function(wrapMode) {
+ switch (wrapMode) {
+ case gl.CLAMP_TO_EDGE: return tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ case gl.REPEAT: return tcuTexture.WrapMode.REPEAT_GL;
+ case gl.MIRRORED_REPEAT: return tcuTexture.WrapMode.MIRRORED_REPEAT_GL;
+ default:
+ throw new Error("Can't map GL wrap mode " + deString.enumToString(gl, wrapMode));
+ }
+};
+
+/**
+ * @param {number} filterMode
+ * @return {tcuTexture.FilterMode}
+ * @throws {Error}
+ */
+gluTextureUtil.mapGLFilterMode = function(filterMode) {
+ switch (filterMode) {
+ case gl.NEAREST: return tcuTexture.FilterMode.NEAREST;
+ case gl.LINEAR: return tcuTexture.FilterMode.LINEAR;
+ case gl.NEAREST_MIPMAP_NEAREST: return tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST;
+ case gl.NEAREST_MIPMAP_LINEAR: return tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR;
+ case gl.LINEAR_MIPMAP_NEAREST: return tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST;
+ case gl.LINEAR_MIPMAP_LINEAR: return tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR;
+ default:
+ throw new Error("Can't map GL filter mode" + filterMode);
+ }
+};
+
+/* TODO: Port the code below */
+// /*--------------------------------------------------------------------*//*!
+// * \brief Map GL sampler parameters to tcu::Sampler.
+// *
+// * If no mapping is found, throws tcu::InternalError.
+// *
+// * \param wrapS S-component wrap mode
+// * \param minFilter Minification filter mode
+// * \param magFilter Magnification filter mode
+// * \return Sampler description.
+// *//*--------------------------------------------------------------------*/
+// /*tcu::Sampler mapGLSamplerWrapS (deUint32 wrapS, deUint32 minFilter, deUint32 magFilter)
+// {
+// return mapGLSampler(wrapS, wrapS, wrapS, minFilter, magFilter);
+// }
+// */
+
+/**
+ * Map GL sampler parameters to tcu::Sampler.
+ *
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * @param {number} wrapS S-component wrap mode
+ * @param {number} wrapT T-component wrap mode
+ * @param {number} minFilter Minification filter mode
+ * @param {number} magFilter Magnification filter mode
+ * @return {tcuTexture.Sampler}
+ */
+gluTextureUtil.mapGLSamplerWrapST = function(wrapS, wrapT, minFilter, magFilter) {
+ return gluTextureUtil.mapGLSampler(wrapS, wrapT, wrapS, minFilter, magFilter);
+};
+
+/**
+ * Map GL sampler parameters to tcu::Sampler.
+ *
+ * If no mapping is found, throws tcu::InternalError.
+ * @param {number} wrapS S-component wrap mode
+ * @param {number} wrapT T-component wrap mode
+ * @param {number} wrapR R-component wrap mode
+ * @param {number} minFilter Minification filter mode
+ * @param {number} magFilter Magnification filter mode
+ * @return {tcuTexture.Sampler}
+ */
+gluTextureUtil.mapGLSampler = function(wrapS, wrapT, wrapR, minFilter, magFilter) {
+ return new tcuTexture.Sampler(
+ gluTextureUtil.mapGLWrapMode(wrapS),
+ gluTextureUtil.mapGLWrapMode(wrapT),
+ gluTextureUtil.mapGLWrapMode(wrapR),
+ gluTextureUtil.mapGLFilterMode(minFilter),
+ gluTextureUtil.mapGLFilterMode(magFilter),
+ 0.0,
+ true,
+ tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0,
+ [0.0, 0.0, 0.0, 0.0]);
+};
+
+// /*--------------------------------------------------------------------*//*!
+// * \brief Map GL compare function to tcu::Sampler::CompareMode.
+// *
+// * If no mapping is found, throws tcu::InternalError.
+// *
+// * \param mode GL compare mode
+// * \return Compare mode
+// *//*--------------------------------------------------------------------*/
+/**
+ * @param {number} mode
+ */
+gluTextureUtil.mapGLCompareFunc = function(mode) {
+ switch (mode) {
+ case gl.LESS: return tcuTexture.CompareMode.COMPAREMODE_LESS;
+ case gl.LEQUAL: return tcuTexture.CompareMode.COMPAREMODE_LESS_OR_EQUAL;
+ case gl.GREATER: return tcuTexture.CompareMode.COMPAREMODE_GREATER;
+ case gl.GEQUAL: return tcuTexture.CompareMode.COMPAREMODE_GREATER_OR_EQUAL;
+ case gl.EQUAL: return tcuTexture.CompareMode.COMPAREMODE_EQUAL;
+ case gl.NOTEQUAL: return tcuTexture.CompareMode.COMPAREMODE_NOT_EQUAL;
+ case gl.ALWAYS: return tcuTexture.CompareMode.COMPAREMODE_ALWAYS;
+ case gl.NEVER: return tcuTexture.CompareMode.COMPAREMODE_NEVER;
+ default:
+ throw new Error("Can't map GL compare mode " + mode);
+ }
+};
+
+/**
+ * Get GL wrap mode.
+ *
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * @param {tcuTexture.WrapMode} wrapMode
+ * @return {number} GL wrap mode
+ */
+gluTextureUtil.getGLWrapMode = function(wrapMode) {
+ switch (wrapMode) {
+ case tcuTexture.WrapMode.CLAMP_TO_EDGE: return gl.CLAMP_TO_EDGE;
+ case tcuTexture.WrapMode.REPEAT_GL: return gl.REPEAT;
+ case tcuTexture.WrapMode.MIRRORED_REPEAT_GL: return gl.MIRRORED_REPEAT;
+ default:
+ throw new Error("Can't map wrap mode");
+ }
+};
+
+/**
+ * Get GL filter mode.
+ *
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * @param {tcuTexture.FilterMode} filterMode Filter mode
+ * @return {number} GL filter mode
+ */
+gluTextureUtil.getGLFilterMode = function(filterMode) {
+ switch (filterMode) {
+ case tcuTexture.FilterMode.NEAREST: return gl.NEAREST;
+ case tcuTexture.FilterMode.LINEAR: return gl.LINEAR;
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST: return gl.NEAREST_MIPMAP_NEAREST;
+ case tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR: return gl.NEAREST_MIPMAP_LINEAR;
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST: return gl.LINEAR_MIPMAP_NEAREST;
+ case tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR: return gl.LINEAR_MIPMAP_LINEAR;
+ default:
+ throw new Error("Can't map filter mode");
+ }
+};
+
+/**
+ * Get GL compare mode.
+ *
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * @param {tcuTexture.CompareMode} compareMode Compare mode
+ * @return {number} GL compare mode
+ */
+gluTextureUtil.getGLCompareFunc = function(compareMode) {
+ switch (compareMode) {
+ case tcuTexture.CompareMode.COMPAREMODE_NONE: return gl.NONE;
+ case tcuTexture.CompareMode.COMPAREMODE_LESS: return gl.LESS;
+ case tcuTexture.CompareMode.COMPAREMODE_LESS_OR_EQUAL: return gl.LEQUAL;
+ case tcuTexture.CompareMode.COMPAREMODE_GREATER: return gl.GREATER;
+ case tcuTexture.CompareMode.COMPAREMODE_GREATER_OR_EQUAL: return gl.GEQUAL;
+ case tcuTexture.CompareMode.COMPAREMODE_EQUAL: return gl.EQUAL;
+ case tcuTexture.CompareMode.COMPAREMODE_NOT_EQUAL: return gl.NOTEQUAL;
+ case tcuTexture.CompareMode.COMPAREMODE_ALWAYS: return gl.ALWAYS;
+ case tcuTexture.CompareMode.COMPAREMODE_NEVER: return gl.NEVER;
+ default:
+ throw new Error("Can't map compare mode");
+ }
+};
+
+/**
+ * Get GL cube face.
+ *
+ * If no mapping is found, throws tcu::InternalError.
+ *
+ * @param {tcuTexture.CubeFace} face Cube face
+ * @return {number} GL cube face
+ */
+gluTextureUtil.getGLCubeFace = function(face) {
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X:
+ return gl.TEXTURE_CUBE_MAP_NEGATIVE_X;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X:
+ return gl.TEXTURE_CUBE_MAP_POSITIVE_X;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y:
+ return gl.TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y:
+ return gl.TEXTURE_CUBE_MAP_POSITIVE_Y;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z:
+ return gl.TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z:
+ return gl.TEXTURE_CUBE_MAP_POSITIVE_Z;
+ default:
+ throw Error("Can't map cube face");
+ }
+};
+
+// /*--------------------------------------------------------------------*//*!
+// * \brief Get GLSL sampler type for texture format.
+// *
+// * If no mapping is found, glu::TYPE_LAST is returned.
+// *
+// * \param format Texture format
+// * \return GLSL 1D sampler type for format
+// *//*--------------------------------------------------------------------*/
+// DataType getSampler1DType (tcu::TextureFormat format)
+// {
+// using tcu::TextureFormat;
+
+// if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS)
+// return TYPE_SAMPLER_1D;
+
+// if (format.order == tcuTexture.ChannelOrder.S)
+// return TYPE_LAST;
+
+// switch (tcu::getTextureChannelClass(format.type))
+// {
+// case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+// case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+// case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+// return glu::TYPE_SAMPLER_1D;
+
+// case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+// return glu::TYPE_INT_SAMPLER_1D;
+
+// case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+// return glu::TYPE_UINT_SAMPLER_1D;
+
+// default:
+// return glu::TYPE_LAST;
+// }
+// }
+
+/**
+ * Get GLSL sampler type for texture format.
+ * If no mapping is found, glu::TYPE_LAST is returned.
+ *
+ * @param {tcuTexture.TextureFormat} format
+ * @return {gluShaderUtil.DataType} GLSL 2D sampler type for format
+ */
+gluTextureUtil.getSampler2DType = function(format) {
+ if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS)
+ return gluShaderUtil.DataType.SAMPLER_2D;
+
+ if (format.order == tcuTexture.ChannelOrder.S)
+ return /** @type {gluShaderUtil.DataType} */ (Object.keys(gluShaderUtil.DataType).length);
+
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return gluShaderUtil.DataType.SAMPLER_2D;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return gluShaderUtil.DataType.INT_SAMPLER_2D;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return gluShaderUtil.DataType.UINT_SAMPLER_2D;
+
+ default:
+ return /** @type {gluShaderUtil.DataType} */ (Object.keys(gluShaderUtil.DataType).length);
+ }
+};
+
+/**
+ *
+ * @param {tcuTexture.TextureFormat} format
+ * @return {gluShaderUtil.DataType} GLSL 2D sampler type for format
+ */
+gluTextureUtil.getSampler3DType = function(format) {
+ if (format.order === tcuTexture.ChannelOrder.D || format.order === tcuTexture.ChannelOrder.DS)
+ return gluShaderUtil.DataType.SAMPLER_3D;
+
+ if (format.order === tcuTexture.ChannelOrder.S)
+ return /** @type {gluShaderUtil.DataType} */ (Object.keys(gluShaderUtil.DataType).length); // shouldn't we throw an error instead?
+
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return gluShaderUtil.DataType.SAMPLER_3D;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return gluShaderUtil.DataType.INT_SAMPLER_3D;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return gluShaderUtil.DataType.UINT_SAMPLER_3D;
+
+ default:
+ return /** @type {gluShaderUtil.DataType} */ (Object.keys(gluShaderUtil.DataType).length);
+ }
+};
+
+/**
+ * \brief Get GLSL sampler type for texture format.
+ *
+ * @param {tcuTexture.TextureFormat} format
+ * @return {gluShaderUtil.DataType} GLSL 2D sampler type for format
+ */
+gluTextureUtil.getSamplerCubeType = function(format) {
+ if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS)
+ return gluShaderUtil.DataType.SAMPLER_CUBE;
+
+ if (format.order == tcuTexture.ChannelOrder.S)
+ throw new Error('No cube sampler');
+
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return gluShaderUtil.DataType.SAMPLER_CUBE;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return gluShaderUtil.DataType.INT_SAMPLER_CUBE;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return gluShaderUtil.DataType.UINT_SAMPLER_CUBE;
+
+ default:
+ throw new Error('No cube sampler');
+ }
+};
+
+/**
+ * \brief Get GLSL sampler type for texture format.
+ *
+ * If no mapping is found, glu::TYPE_LAST is returned.
+ *
+ * @param {tcuTexture.TextureFormat} format
+ * @return {gluShaderUtil.DataType} GLSL 2D sampler type for format
+ */
+gluTextureUtil.getSampler2DArrayType = function(format) {
+
+ if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS)
+ return gluShaderUtil.DataType.SAMPLER_2D_ARRAY;
+
+ if (format.order == tcuTexture.ChannelOrder.S)
+ throw new Error('No 2d array sampler');
+
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return gluShaderUtil.DataType.SAMPLER_2D_ARRAY;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY;
+
+ default:
+ throw new Error('No 2d array sampler');
+ }
+};
+
+/**
+ * \brief Get GLSL sampler type for texture format.
+ *
+ * If no mapping is found, glu::TYPE_LAST is returned.
+ *
+ * @param {tcuTexture.TextureFormat} format
+ * @return {gluShaderUtil.DataType} GLSL 2D sampler type for format
+ */
+gluTextureUtil.getSampler3D = function(format) {
+ if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS)
+ return gluShaderUtil.DataType.SAMPLER_3D;
+
+ if (format.order == tcuTexture.ChannelOrder.S)
+ throw new Error('No 3d sampler');
+
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return gluShaderUtil.DataType.SAMPLER_3D;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return gluShaderUtil.DataType.INT_SAMPLER_3D;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return gluShaderUtil.DataType.UINT_SAMPLER_3D;
+
+ default:
+ throw new Error('No 3d sampler');
+ }
+};
+
+gluTextureUtil.RenderableType = {
+ RENDERABLE_COLOR: (1<<0),
+ RENDERABLE_DEPTH: (1<<1),
+ RENDERABLE_STENCIL: (1<<2)
+};
+
+/**
+ * \brief Get renderable bits.
+ * \note Works currently only on ES3 context.
+ *
+ * @param {number} internalFormat
+ * @return {gluTextureUtil.RenderableType}
+ */
+gluTextureUtil.getRenderableBitsES3 = function(internalFormat)
+{
+ switch (internalFormat)
+ {
+ // Color-renderable formats
+ case gl.RGBA32I:
+ case gl.RGBA32UI:
+ case gl.RGBA16I:
+ case gl.RGBA16UI:
+ case gl.RGBA8:
+ case gl.RGBA8I:
+ case gl.RGBA8UI:
+ case gl.SRGB8_ALPHA8:
+ case gl.RGB10_A2:
+ case gl.RGB10_A2UI:
+ case gl.RGBA4:
+ case gl.RGB5_A1:
+ case gl.RGB8:
+ case gl.RGB565:
+ case gl.RG32I:
+ case gl.RG32UI:
+ case gl.RG16I:
+ case gl.RG16UI:
+ case gl.RG8:
+ case gl.RG8I:
+ case gl.RG8UI:
+ case gl.R32I:
+ case gl.R32UI:
+ case gl.R16I:
+ case gl.R16UI:
+ case gl.R8:
+ case gl.R8I:
+ case gl.R8UI:
+ return gluTextureUtil.RenderableType.RENDERABLE_COLOR;
+
+ // EXT_color_buffer_float
+ case gl.RGBA32F:
+ case gl.R11F_G11F_B10F:
+ case gl.RG32F:
+ case gl.R32F:
+ case gl.RGBA16F:
+ case gl.RG16F:
+ case gl.R16F:
+ if (gl.getExtension("EXT_color_buffer_float"))
+ return gluTextureUtil.RenderableType.RENDERABLE_COLOR;
+ else
+ return 0;
+
+ // Depth formats
+ case gl.DEPTH_COMPONENT32F:
+ case gl.DEPTH_COMPONENT24:
+ case gl.DEPTH_COMPONENT16:
+ return gluTextureUtil.RenderableType.RENDERABLE_DEPTH;
+
+ // Depth+stencil formats
+ case gl.DEPTH32F_STENCIL8:
+ case gl.DEPTH24_STENCIL8:
+ return gluTextureUtil.RenderableType.RENDERABLE_DEPTH | gluTextureUtil.RenderableType.RENDERABLE_STENCIL;
+
+ // Stencil formats
+ case gl.STENCIL_INDEX8:
+ return gluTextureUtil.RenderableType.RENDERABLE_STENCIL;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ * \brief Check if sized internal format is color-renderable.
+ * \note Works currently only on ES3 context.
+ *
+ * @param {number} sizedFormat
+ * @return {boolean}
+ */
+gluTextureUtil.isSizedFormatColorRenderable = function(sizedFormat)
+{
+ var renderable = 0;
+ renderable = gluTextureUtil.getRenderableBitsES3(sizedFormat);
+ return (renderable & gluTextureUtil.RenderableType.RENDERABLE_COLOR) != 0;
+}
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarType.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarType.js
new file mode 100644
index 0000000000..a05f1c1e5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarType.js
@@ -0,0 +1,814 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluVarType');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+
+ var gluVarType = framework.opengl.gluVarType;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+ /**
+ * gluVarType.VarType types enum
+ * @enum {number}
+ */
+ gluVarType.Type = {
+ TYPE_BASIC: 0,
+ TYPE_ARRAY: 1,
+ TYPE_STRUCT: 2
+ };
+
+ /**
+ * gluVarType.TypeArray struct
+ * @param {gluVarType.VarType} elementType
+ * @param {number} arraySize
+ * @constructor
+ */
+ gluVarType.TypeArray = function(elementType, arraySize) {
+ /** @type {gluVarType.VarType} */ this.elementType = gluVarType.newClone(elementType);
+ /** @type {number} */ this.size = arraySize;
+ };
+
+ /**
+ * gluVarType.VarType class
+ * @constructor
+ */
+ gluVarType.VarType = function() {
+ /**
+ * @type {gluShaderUtil.precision}
+ * @private
+ */
+ this.m_flags;
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.m_type = -1;
+
+ /**
+ * m_data used to be a 'Data' union in C++. Using a var is enough here.
+ * it will contain any necessary value.
+ * case TYPE_BASIC: number
+ * case TYPE_ARRAY: gluVarType.TypeArray
+ * case TYPE_STRUCT: gluVarType.StructType
+ * @private
+ * @type {(number|gluVarType.TypeArray|gluVarType.StructType)}
+ */
+ this.m_data = null;
+ };
+
+ gluVarType.VarType.UNSIZED_ARRAY = -1;
+
+ /**
+ * Creates a basic type gluVarType.VarType. Use this after the constructor call.
+ * @param {number} basicType
+ * @param {gluShaderUtil.precision} flags
+ * @return {gluVarType.VarType} The currently modified object
+ */
+ gluVarType.VarType.prototype.VarTypeBasic = function(basicType, flags) {
+ this.m_type = gluVarType.Type.TYPE_BASIC;
+ this.m_flags = flags;
+ this.m_data = basicType;
+
+ return this;
+ };
+
+ /**
+ * Creates a basic type gluVarType.VarType with type boolean and undefined precision.
+ * @param {number} basicType
+ * @return {gluVarType.VarType} The currently modified object
+ */
+ gluVarType.VarType.prototype.VarTypeBoolean = function(basicType) {
+ this.m_type = gluVarType.Type.TYPE_BASIC;
+ this.m_data = basicType;
+
+ return this;
+ };
+
+ /**
+ * Creates an array type gluVarType.VarType. Use this after the constructor call.
+ * @param {gluVarType.VarType} elementType
+ * @param {number} arraySize
+ * @return {gluVarType.VarType} The currently modified object
+ */
+ gluVarType.VarType.prototype.VarTypeArray = function(elementType, arraySize) {
+ this.m_type = gluVarType.Type.TYPE_ARRAY;
+ if (!(arraySize >= 0 || arraySize == gluVarType.VarType.UNSIZED_ARRAY))
+ throw new Error('Illegal array size: ' + arraySize);
+ this.m_data = new gluVarType.TypeArray(elementType, arraySize);
+
+ return this;
+ };
+
+ /**
+ * Creates a struct type gluVarType.VarType. Use this after the constructor call.
+ * @param {gluVarType.StructType} structPtr
+ * @return {gluVarType.VarType} The currently modified object
+ */
+ gluVarType.VarType.prototype.VarTypeStruct = function(structPtr) {
+ this.m_type = gluVarType.Type.TYPE_STRUCT;
+ this.m_data = structPtr;
+
+ return this;
+ };
+
+ /**
+ * Creates a gluVarType.VarType, the same type as the passed in object.
+ * Use this after the constructor call.
+ * @param {gluVarType.VarType} object
+ * @return {gluVarType.VarType} The currently modified object
+ */
+ gluVarType.VarType.prototype.VarTypeClone = function(object) {
+
+ this.m_type = object.m_type;
+
+ switch (this.m_type) {
+ case gluVarType.Type.TYPE_BASIC:
+ this.m_flags = object.m_flags;
+ this.m_data = object.m_data;
+ break;
+ case gluVarType.Type.TYPE_BASIC:
+ this.m_data = new gluVarType.TypeArray(object.m_data.elementType, object.m_data.size);
+ break;
+ case gluVarType.Type.TYPE_STRUCT:
+ this.m_data = object.m_data;
+ break;
+ default:
+ throw new Error('unknown type: ' + this.m_type);
+ }
+
+ return this;
+ };
+
+ /** isBasicType
+ * @return {boolean} true if the gluVarType.VarType represents a basic type.
+ */
+ gluVarType.VarType.prototype.isBasicType = function() {
+ return this.m_type == gluVarType.Type.TYPE_BASIC;
+ };
+
+ /** isArrayType
+ * @return {boolean} true if the gluVarType.VarType represents an array.
+ */
+ gluVarType.VarType.prototype.isArrayType = function() {
+ return this.m_type == gluVarType.Type.TYPE_ARRAY;
+ };
+
+ /** isStructType
+ * @return {boolean} true if the gluVarType.VarType represents a struct.
+ */
+ gluVarType.VarType.prototype.isStructType = function() {
+ return this.m_type == gluVarType.Type.TYPE_STRUCT;
+ };
+
+ /** getFlags
+ * @return {number} returns the flags of the gluVarType.VarType.
+ */
+ gluVarType.VarType.prototype.getFlags = function() {
+ return this.m_flags;
+ };
+
+ /** getBasicType
+ * @return {gluShaderUtil.DataType<number>} returns the basic data type of the gluVarType.VarType.
+ */
+ gluVarType.VarType.prototype.getBasicType = function() {
+ if (!this.isBasicType())
+ throw new Error('VarType is not a basic type.');
+ return /** @type {gluShaderUtil.DataType<number>} */ (this.m_data);
+ };
+
+ /** getPrecision
+ * @return {gluShaderUtil.precision} returns the precision flag.
+ */
+ gluVarType.VarType.prototype.getPrecision = function() {
+ if (!this.isBasicType())
+ throw new Error('VarType is not a basic type.');
+ return this.m_flags;
+ };
+
+ /** getElementType
+ * @return {gluVarType.VarType} returns the gluVarType.VarType of the element in case of an Array.
+ */
+ gluVarType.VarType.prototype.getElementType = function() {
+ if (!this.isArrayType())
+ throw new Error('VarType is not an array type.');
+ return this.m_data.elementType;
+ };
+
+ /** getArraySize
+ * (not to be confused with a javascript array)
+ * @return {number} returns the size of the array in case it is an array.
+ */
+ gluVarType.VarType.prototype.getArraySize = function() {
+ if (!this.isArrayType())
+ throw new Error('VarType is not an array type.');
+ return this.m_data.size;
+ };
+
+ /** getStruct
+ * @return {gluVarType.StructType} returns the structure when it is a gluVarType.StructType.
+ */
+ gluVarType.VarType.prototype.getStruct = function() {
+ if (!this.isStructType())
+ throw new Error('VarType is not a struct type.');
+ return /** @type {gluVarType.StructType} */ (this.m_data);
+ };
+
+ /**
+ * getScalarSize
+ * @return {number} size of the scalar
+ */
+ gluVarType.VarType.prototype.getScalarSize = function() {
+ switch (this.m_type) {
+ case gluVarType.Type.TYPE_BASIC: {
+ return gluShaderUtil.getDataTypeScalarSize(/** @type {gluShaderUtil.DataType} */(this.getBasicType()));
+ }
+
+ // TODO: check implementation below: return m_data.array.elementType->getScalarSize()*m_data.array.size;
+ case gluVarType.Type.TYPE_ARRAY: {
+ var m_data = /** @type {gluVarType.TypeArray} */(this.m_data);
+ return m_data.elementType.getScalarSize() * m_data.size;
+ }
+
+ case gluVarType.Type.TYPE_STRUCT: {
+ var size = 0;
+
+ var struct = /** @type {gluVarType.StructType} */ (this.m_data);
+
+ // TODO: check loop conditions below
+ // for (gluVarType.StructType::ConstIterator iter = m_data.structPtr->begin(); iter != m_data.structPtr->end(); iter++)
+ for (var iter = 0; struct.m_members[iter] < struct.getSize(); iter++)
+ size += struct.getMember(iter).m_type.getScalarSize();
+ return size;
+ }
+
+ default:
+ // throw new Error('Unexpected type.');
+ return 0;
+ }
+ };
+
+ /**
+ * is
+ * @return {boolean} returns true if the current object is equivalent to other.
+ */
+ gluVarType.VarType.prototype.is = function(other) {
+ if (this.m_type != other.m_type)
+ return false;
+
+ switch (this.m_type) {
+ case gluVarType.Type.TYPE_BASIC:
+ return this.m_data == other.m_data &&
+ this.m_flags == other.m_flags;
+
+ case gluVarType.Type.TYPE_ARRAY:
+ return this.m_data.elementType == other.m_data.elementType &&
+ this.m_data.size == other.m_data.size;
+
+ case gluVarType.Type.TYPE_STRUCT:
+ return this.m_data === other.m_data;
+
+ default:
+ // throw new Error('Unexpected type.');
+ return false;
+ }
+ };
+
+ /**
+ * isnt
+ * @return {boolean} returns true if the current object is not equivalent to other.
+ */
+ gluVarType.VarType.prototype.isnt = function(other) {
+ return !(this.is(other));
+ };
+
+ /**
+ * Creates a basic type gluVarType.VarType.
+ * @param {gluShaderUtil.DataType} basicType
+ * @param {framework.opengl.gluShaderUtil.precision=} flags
+ * @return {gluVarType.VarType}
+ */
+ gluVarType.newTypeBasic = function(basicType, flags) {
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(basicType))
+ return new gluVarType.VarType().VarTypeBasic(basicType, /** @type {framework.opengl.gluShaderUtil.precision}*/ (flags));
+ else
+ return new gluVarType.VarType().VarTypeBoolean(basicType);
+ };
+
+ /**
+ * Creates an array type gluVarType.VarType.
+ * @param {gluVarType.VarType} elementType
+ * @param {number} arraySize
+ * @return {gluVarType.VarType}
+ */
+ gluVarType.newTypeArray = function(elementType, arraySize) {
+ return new gluVarType.VarType().VarTypeArray(elementType, arraySize);
+ };
+
+ /**
+ * Creates a struct type gluVarType.VarType.
+ * @param {gluVarType.StructType} structPtr
+ * @return {gluVarType.VarType}
+ */
+ gluVarType.newTypeStruct = function(structPtr) {
+ return new gluVarType.VarType().VarTypeStruct(structPtr);
+ };
+
+ /**
+ * Creates a struct type gluVarType.VarType.
+ * @param {gluVarType.VarType} object
+ * @return {gluVarType.VarType}
+ */
+ gluVarType.newClone = function(object) {
+ return new gluVarType.VarType().VarTypeClone(object);
+ };
+
+ /**
+ * gluVarType.StructMember class
+ * @constructor
+ */
+ gluVarType.StructMember = function() {
+ /** @type {string} */ this.m_name;
+ /** @type {gluVarType.VarType} */ this.m_type;
+ /** @type {number} */ // this.m_flags = 0; // only in glsUniformBlockCase
+ };
+
+ /**
+ * Creates a gluVarType.StructMember. Use this after the constructor call.
+ * @param {string} name
+ * @param {gluVarType.VarType} type
+ * @return {gluVarType.StructMember} The currently modified object
+ */
+ gluVarType.StructMember.prototype.Constructor = function(name, type) {
+ this.m_type = type;
+ this.m_name = name;
+
+ return this;
+ };
+
+ /** getName
+ * @return {string} name of the gluVarType.StructMember object.
+ */
+ gluVarType.StructMember.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /** getType
+ * @return {gluVarType.VarType} type of the gluVarType.StructMember object.
+ */
+ gluVarType.StructMember.prototype.getType = function() {
+ return this.m_type;
+ };
+
+ /**
+ * Creates a gluVarType.StructMember.
+ * @param {string} name
+ * @param {gluVarType.VarType} type
+ * @return {gluVarType.StructMember}
+ */
+ gluVarType.newStructMember = function(name, type) {
+ return new gluVarType.StructMember().Constructor(name, type);
+ };
+
+ /**
+ * gluVarType.StructType class
+ * @constructor
+ */
+ gluVarType.StructType = function() {
+ /** @type {string} */ this.m_typeName = '';
+ /** @type {Array<gluVarType.StructMember>} */ this.m_members = [];
+ };
+
+ /**
+ * Creates a gluVarType.StructType. Use this after the constructor call.
+ * @param {string} name
+ * @return {gluVarType.StructType} The currently modified object
+ */
+ gluVarType.StructType.prototype.Constructor = function(name) {
+ /** @type {string}*/ this.m_typeName = this.setTypeName(name);
+ return this;
+ };
+
+ /** hasTypeName
+ * Checks if the gluVarType.StructType m_typeName is defined
+ * @return {boolean}
+ */
+ gluVarType.StructType.prototype.hasTypeName = function() {
+ return (this.m_typeName !== 'undefined');
+ };
+
+ /** setTypeName
+ * @param {string} name
+ * @return {string} returns gluVarType.StructType.m_typeName
+ */
+ gluVarType.StructType.prototype.setTypeName = function(name) {
+ return this.m_typeName = name;
+ };
+
+ /** getTypeName
+ * @return {string}
+ */
+ gluVarType.StructType.prototype.getTypeName = function() {
+ return this.m_typeName;
+ };
+
+ /** getNumMembers
+ * @return {number}
+ */
+ gluVarType.StructType.prototype.getNumMembers = function() {
+ return this.m_members.length;
+ };
+
+ /** getMember
+ * @param {number} memberNdx The index of the member to retrieve.
+ * @return {gluVarType.StructMember}
+ */
+ gluVarType.StructType.prototype.getMember = function(memberNdx) {
+ if (memberNdx >= 0 && memberNdx < this.m_members.length)
+ return this.m_members[memberNdx];
+ else {
+ throw new Error('Invalid member index for StructTypes members');
+ }
+ };
+
+ /** getSize
+ * @return {number} The size of the m_members array.
+ */
+ gluVarType.StructType.prototype.getSize = function() {
+ return this.m_members.length;
+ };
+
+ /** addMember
+ * @param {string} name
+ * @param {gluVarType.VarType} type
+ */
+ gluVarType.StructType.prototype.addMember = function(name, type) {
+ var member = gluVarType.newStructMember(name, type);
+ this.m_members.push(member);
+ };
+
+ /**
+ * Creates a gluVarType.StructType.
+ * @param {string} name
+ * @return {gluVarType.StructType}
+ */
+ gluVarType.newStructType = function(name) {
+ return new gluVarType.StructType().Constructor(name);
+ };
+
+ /**
+ * @param {number} level
+ * @return {string}
+ */
+ gluVarType.indent = function(level) {
+ /** @type {string} */ var str = '';
+ for (var i = 0; i < level; i++)
+ str += '\t';
+ return str;
+ };
+
+ /**
+ * @param {gluVarType.VarType} varType
+ * @param {string} name
+ * @param {number=} level
+ * @return {string}
+ */
+ gluVarType.declareVariable = function(varType, name, level) {
+ /** @type {string} */ var str = '';
+ /** @type {gluVarType.VarType} */ var type = varType;
+ /** @type {gluVarType.VarType} */ var curType = type;
+ /** @type {Array<number>} */ var arraySizes = [];
+
+ // Handle arrays.
+ while (curType.isArrayType()) {
+ arraySizes.push(curType.getArraySize());
+ curType = curType.getElementType();
+ }
+
+ if (curType.isBasicType()) {
+ if (curType.getPrecision() !== undefined)
+ str += gluShaderUtil.getPrecisionName(curType.getPrecision()) + ' ';
+ str += gluShaderUtil.getDataTypeName(/** @type {gluShaderUtil.DataType} */(curType.getBasicType()));
+ } else if (curType.isStructType()) {
+ /** @type {gluVarType.StructType} */ var structPtr = curType.getStruct();
+
+ if (structPtr.hasTypeName())
+ str += structPtr.getTypeName();
+ else
+ str += gluVarType.declareStructType(structPtr, level); // Generate inline declaration.
+ } else
+ throw new Error('Unexpected Array typed VarType.');
+
+ str += ' ' + name;
+
+ // Print array sizes.
+ for (var size = 0; size < arraySizes.length; size++) { //std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++) {
+ /** @type {number} */ var arrSize = arraySizes[size];
+ if (arrSize == gluVarType.VarType.UNSIZED_ARRAY)
+ str += '[]';
+ else
+ str += '[' + arrSize + ']';
+ }
+
+ return str;
+ };
+
+ /**
+ * @param {gluVarType.StructType} structType
+ * @param {number=} level
+ * @return {string}
+ */
+ gluVarType.declareStructType = function(structType, level) {
+ /** @type {string} */ var str = 'struct';
+ level = level || 0;
+
+ // gluVarType.Type name is optional.
+ if (structType.hasTypeName())
+ str += ' ' + structType.getTypeName();
+
+ str += '\n' + gluVarType.indent(level) + ' {\n';
+
+ for (var memberNdx = 0; memberNdx < structType.getSize(); memberNdx++) { //gluVarType.StructType::ConstIterator memberIter = decl.structPtr->begin(); memberIter != decl.structPtr->end(); memberIter++) {
+ /** @type {gluVarType.StructMember} */ var memberIter = structType.getMember(memberNdx);
+ str += gluVarType.indent(level + 1);
+ str += gluVarType.declareVariable(memberIter.getType(), memberIter.getName(), level + 1) + ';\n';
+ }
+
+ str += gluVarType.indent(level) + '}';
+
+ return str;
+ };
+
+ /**
+ * @param {*} T
+ * @param {number=} size
+ * @param {gluShaderUtil.precision=} precision
+ * @return {gluVarType.VarType}
+ */
+ gluVarType.getVarTypeOf = function(T, size, precision) {
+ size = size || 1;
+ precision = precision || gluShaderUtil.precision.PRECISION_LOWP;
+ switch (size) {
+ case 4: return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, precision);
+ case 3: return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC3, precision);
+ case 2: return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision);
+ }
+ switch (T) {
+ case 'float' : return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT, precision);
+ case 'vec4': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, precision);
+ case 'vec3': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC3, precision);
+ case 'vec2': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision);
+ case 'mat2': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT2, precision);
+ case 'mat2x3': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT2X3, precision);
+ case 'mat2x4': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT2X4, precision);
+ case 'mat3x2': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3X2, precision);
+ case 'mat3': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, precision);
+ case 'mat3x4': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3X4, precision);
+ case 'mat4x2': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT4X2, precision);
+ case 'mat4x3': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT4X3, precision);
+ case 'mat4': return gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_MAT4, precision);
+ }
+ throw new Error('Invalid input type ' + T + ' or size ' + size);
+ };
+
+ /**
+ * @enum
+ */
+ gluVarType.Storage = {
+ STORAGE_IN: 0,
+ STORAGE_OUT: 1,
+ STORAGE_CONST: 2,
+ STORAGE_UNIFORM: 3,
+ STORAGE_BUFFER: 4
+ };
+
+ /**
+ * @param {gluVarType.Storage} storage
+ * @return {string}
+ */
+ gluVarType.getStorageName = function(storage) {
+ switch (storage) {
+ case gluVarType.Storage.STORAGE_IN: return 'in';
+ case gluVarType.Storage.STORAGE_OUT: return 'out';
+ case gluVarType.Storage.STORAGE_CONST: return 'const';
+ case gluVarType.Storage.STORAGE_UNIFORM: return 'uniform';
+ case gluVarType.Storage.STORAGE_BUFFER: return 'buffer';
+ default:
+ throw new Error('Unknown storage: ' + storage);
+ }
+ };
+
+ /**
+ * @enum
+ */
+ gluVarType.Interpolation = {
+ INTERPOLATION_SMOOTH: 0,
+ INTERPOLATION_FLAT: 1,
+ INTERPOLATION_CENTROID: 2
+ };
+
+ /**
+ * @param {gluVarType.Interpolation} interpolation
+ * @return {string}
+ */
+ gluVarType.getInterpolationName = function(interpolation) {
+ switch (interpolation) {
+ case gluVarType.Interpolation.INTERPOLATION_SMOOTH: return 'smooth';
+ case gluVarType.Interpolation.INTERPOLATION_FLAT: return 'flat';
+ case gluVarType.Interpolation.INTERPOLATION_CENTROID: return 'centrod';
+ default:
+ throw new Error('Unknown interpolation: ' + interpolation);
+ }
+ };
+
+ /**
+ * @enum
+ */
+ gluVarType.FormatLayout = {
+ FORMATLAYOUT_RGBA32F: 0,
+ FORMATLAYOUT_RGBA16F: 1,
+ FORMATLAYOUT_R32F: 2,
+ FORMATLAYOUT_RGBA8: 3,
+ FORMATLAYOUT_RGBA8_SNORM: 4,
+
+ FORMATLAYOUT_RGBA32I: 5,
+ FORMATLAYOUT_RGBA16I: 6,
+ FORMATLAYOUT_RGBA8I: 7,
+ FORMATLAYOUT_R32I: 8,
+
+ FORMATLAYOUT_RGBA32UI: 9,
+ FORMATLAYOUT_RGBA16UI: 10,
+ FORMATLAYOUT_RGBA8UI: 11,
+ FORMATLAYOUT_R32UI: 12
+ };
+
+ /**
+ * @param {gluVarType.FormatLayout} layout
+ * @return {string}
+ */
+ gluVarType.getFormatLayoutName = function(layout) {
+ switch (layout) {
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA32F: return 'rgba32f';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA16F: return 'rgba16f';
+ case gluVarType.FormatLayout.FORMATLAYOUT_R32F: return 'r32f';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA8: return 'rgba8';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA8_SNORM: return 'rgba8_snorm';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA32I: return 'rgba32i';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA16I: return 'rgba16i';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA8I: return 'rgba8i';
+ case gluVarType.FormatLayout.FORMATLAYOUT_R32I: return 'r32i';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA32UI: return 'rgba32ui';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA16UI: return 'rgba16ui';
+ case gluVarType.FormatLayout.FORMATLAYOUT_RGBA8UI: return 'rgba8ui';
+ case gluVarType.FormatLayout.FORMATLAYOUT_R32UI: return 'r32ui';
+ default:
+ throw new Error('Unknown layout: ' + layout);
+ }
+ };
+
+ /**
+ * @enum
+ */
+ gluVarType.MatrixOrder = {
+ MATRIXORDER_COLUMN_MAJOR: 0,
+ MATRIXORDER_ROW_MAJOR: 1
+ };
+
+ /**
+ * @param {gluVarType.MatrixOrder} qualifier
+ * @return {string}
+ */
+ gluVarType.getMatrixOrderName = function(qualifier) {
+ switch (qualifier) {
+ case gluVarType.MatrixOrder.MATRIXORDER_COLUMN_MAJOR: return 'column_major';
+ case gluVarType.MatrixOrder.MATRIXORDER_ROW_MAJOR: return 'row_major';
+ default:
+ throw new Error('Unknown qualifier: ' + qualifier);
+ }
+ };
+
+ gluVarType.MemoryAccessQualifier = {
+ MEMORYACCESSQUALIFIER_COHERENT_BIT: 0x01,
+ MEMORYACCESSQUALIFIER_VOLATILE_BIT: 0x02,
+ MEMORYACCESSQUALIFIER_RESTRICT_BIT: 0x04,
+ MEMORYACCESSQUALIFIER_READONLY_BIT: 0x08,
+ MEMORYACCESSQUALIFIER_WRITEONLY_BIT: 0x10
+ };
+ gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_MASK = (gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_WRITEONLY_BIT << 1) - 1;
+
+ /**
+ * @param {number} qualifier
+ * @return {string}
+ */
+ gluVarType.getMemoryAccessQualifierName = function(qualifier) {
+ switch (qualifier) {
+ case gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_COHERENT_BIT: return 'coherent';
+ case gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_VOLATILE_BIT: return 'volatile';
+ case gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_RESTRICT_BIT: return 'restrict';
+ case gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_READONLY_BIT: return 'readonly';
+ case gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_WRITEONLY_BIT: return 'writeonly';
+ default:
+ throw new Error('Unknown qualifier: ' + qualifier);
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {number=} location
+ * @param {number=} binding
+ * @param {number=} offset
+ * @param {gluVarType.FormatLayout=} format
+ * @param {gluVarType.MatrixOrder=} matrixOrder
+ */
+ gluVarType.Layout = function(location, binding, offset, format, matrixOrder) {
+ this.location = location;
+ this.binding = binding;
+ this.offset = offset;
+ this.format = format;
+ this.matrixOrder = matrixOrder;
+ };
+
+ gluVarType.Layout.prototype.toString = function() {
+ var strings = [];
+ var str = '';
+ if (typeof this.location !== 'undefined')
+ strings.push('location=' + this.location);
+ if (typeof this.binding !== 'undefined')
+ strings.push('binding=' + this.binding);
+ if (typeof this.offset !== 'undefined')
+ strings.push('offset=' + this.offset);
+ if (typeof this.format !== 'undefined')
+ strings.push(gluVarType.getFormatLayoutName(this.format));
+ if (typeof this.matrixOrder !== 'undefined')
+ strings.push(gluVarType.getMatrixOrderName(this.matrixOrder));
+
+ if (strings.length > 0) {
+ str += 'layout(' + strings[0];
+
+ for (var i = 1; i < strings.length; i++)
+ str += ', ' + strings[i];
+ str += ')';
+ }
+
+ return str;
+ };
+
+ /**
+ * @constructor
+ * @param {gluVarType.VarType} varType
+ * @param {string} name
+ * @param {gluVarType.Storage=} storage
+ * @param {gluVarType.Interpolation=} interpolation
+ * @param {gluVarType.Layout=} layout
+ * @param {number=} memoryAccessQualifierBits
+ */
+ gluVarType.VariableDeclaration = function(varType, name, storage, interpolation, layout, memoryAccessQualifierBits) {
+ this.varType = varType;
+ this.name = name;
+ this.storage = storage;
+ this.interpolation = interpolation;
+ this.layout = layout;
+ this.memoryAccessQualifierBits = memoryAccessQualifierBits || 0;
+ };
+
+ gluVarType.VariableDeclaration.prototype.toString = function() {
+ var str = '';
+ if (typeof this.layout !== 'undefined')
+ str += this.layout.toString() + ' ';
+
+ for (var bitNdx = 0; (1 << bitNdx) & gluVarType.MemoryAccessQualifier.MEMORYACCESSQUALIFIER_MASK; ++bitNdx)
+ if (this.memoryAccessQualifierBits & (1 << bitNdx))
+ str += gluVarType.getMemoryAccessQualifierName((1 << bitNdx)) + ' ';
+
+ if (typeof this.interpolation !== 'undefined')
+ str += gluVarType.getInterpolationName(this.interpolation) + ' ';
+
+ if (typeof this.storage !== 'undefined')
+ str += gluVarType.getStorageName(this.storage) + ' ';
+
+ str += gluVarType.declareVariable(this.varType, this.name);
+
+ return str;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarTypeUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarTypeUtil.js
new file mode 100644
index 0000000000..30e198a606
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/gluVarTypeUtil.js
@@ -0,0 +1,693 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.gluVarTypeUtil');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+
+goog.scope(function() {
+
+ var gluVarTypeUtil = framework.opengl.gluVarTypeUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+ gluVarTypeUtil.isNum = function(c) { return /^[0-9]$/.test(c); };
+ gluVarTypeUtil.isAlpha = function(c) { return /^[a-zA-Z]$/.test(c); };
+ gluVarTypeUtil.isIdentifierChar = function(c) { return /^[a-zA-Z0-9_]$/.test(c); };
+ gluVarTypeUtil.array_op_equivalent = function(arr1, arr2) {
+ if (arr1.length != arr2.length) return false;
+ for (var i = 0; i < arr1.length; ++i) {
+ if (arr1[i].isnt(arr2[1])) return false;
+ }
+ return true;
+ };
+
+ /**
+ * gluVarTypeUtil.VarTokenizer class.
+ * @param {string} str
+ * @constructor
+ */
+ gluVarTypeUtil.VarTokenizer = function(str) {
+
+ /** @private */
+ this.m_str = str;
+ /** @private */
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.length;
+ /** @private */
+ this.m_tokenStart = 0;
+ /** @private */
+ this.m_tokenLen = 0;
+
+ this.advance();
+
+ };
+ gluVarTypeUtil.VarTokenizer.s_Token = {
+ IDENTIFIER: 0,
+ LEFT_BRACKET: 1,
+ RIGHT_BRACKET: 2,
+ PERIOD: 3,
+ NUMBER: 4,
+ END: 5
+ };
+ gluVarTypeUtil.VarTokenizer.s_Token.length = Object.keys(gluVarTypeUtil.VarTokenizer.s_Token).length;
+
+ gluVarTypeUtil.VarTokenizer.prototype.getToken = function() {
+ return this.m_token;
+ };
+ gluVarTypeUtil.VarTokenizer.prototype.getIdentifier = function() {
+ return this.m_str.substr(this.m_tokenStart, this.m_tokenLen);
+ };
+ gluVarTypeUtil.VarTokenizer.prototype.getNumber = function() {
+ return parseInt(this.getIdentifier(), 10);
+ };
+ gluVarTypeUtil.VarTokenizer.prototype.getCurrentTokenStartLocation = function() {
+ return this.m_tokenStart;
+ };
+ gluVarTypeUtil.VarTokenizer.prototype.getCurrentTokenEndLocation = function() {
+ return this.m_tokenStart + this.m_tokenLen;
+ };
+
+ gluVarTypeUtil.VarTokenizer.prototype.advance = function() {
+
+ if (this.m_token == gluVarTypeUtil.VarTokenizer.s_Token.END) {
+ throw new Error('No more tokens.');
+ }
+
+ this.m_tokenStart += this.m_tokenLen;
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.length;
+ this.m_tokenLen = 1;
+
+ if (this.m_tokenStart >= this.m_str.length) {
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.END;
+
+ } else if (this.m_str[this.m_tokenStart] == '[') {
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.LEFT_BRACKET;
+
+ } else if (this.m_str[this.m_tokenStart] == ']') {
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.RIGHT_BRACKET;
+
+ } else if (this.m_str[this.m_tokenStart] == '.') {
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.PERIOD;
+
+ } else if (gluVarTypeUtil.isNum(this.m_str[this.m_tokenStart])) {
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.NUMBER;
+ while (gluVarTypeUtil.isNum(this.m_str[this.m_tokenStart + this.m_tokenLen])) {
+ this.m_tokenLen += 1;
+ }
+
+ } else if (gluVarTypeUtil.isIdentifierChar(this.m_str[this.m_tokenStart])) {
+ this.m_token = gluVarTypeUtil.VarTokenizer.s_Token.IDENTIFIER;
+ while (gluVarTypeUtil.isIdentifierChar(this.m_str[this.m_tokenStart + this.m_tokenLen])) {
+ this.m_tokenLen += 1;
+ }
+
+ } else {
+ throw new Error('Unexpected character');
+ }
+
+ };
+
+ /**
+ * VarType subtype path utilities class.
+ * @param {gluVarTypeUtil.VarTypeComponent.s_Type} type
+ * @param {number} index
+ * @constructor
+ */
+ gluVarTypeUtil.VarTypeComponent = function(type, index) {
+ /** @type {gluVarTypeUtil.VarTypeComponent.s_Type} */ this.type = type;
+ this.index = index || 0;
+ };
+
+ gluVarTypeUtil.VarTypeComponent.prototype.is = function(other) {
+ return this.type == other.type && this.index == other.index;
+ };
+ gluVarTypeUtil.VarTypeComponent.prototype.isnt = function(other) {
+ return this.type != other.type || this.index != other.index;
+ };
+
+ /**
+ * @enum
+ */
+ gluVarTypeUtil.VarTypeComponent.s_Type = {
+ STRUCT_MEMBER: 0,
+ ARRAY_ELEMENT: 1,
+ MATRIX_COLUMN: 2,
+ VECTOR_COMPONENT: 3
+ };
+
+ /**
+ * Type path formatter.
+ * @param {gluVarType.VarType} type_
+ * @param {Array<gluVarTypeUtil.VarTypeComponent>} path_
+ * @constructor
+ */
+ gluVarTypeUtil.TypeAccessFormat = function(type_, path_) {
+ this.type = type_;
+ this.path = path_;
+ };
+
+ gluVarTypeUtil.TypeAccessFormat.prototype.toString = function() {
+ var curType = this.type;
+ var str = '';
+
+ for (var i = 0; i < this.path.length; i++) {
+ var iter = this.path[i];
+ switch (iter.type) {
+ case gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT:
+ curType = curType.getElementType(); // Update current type.
+ // Fall-through.
+
+ case gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN:
+ case gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT:
+ str += '[' + iter.index + ']';
+ break;
+
+ case gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER: {
+ var member = curType.getStruct().getMember(i);
+ str += '.' + member.getName();
+ curType = member.getType();
+ break;
+ }
+
+ default:
+ throw new Error('Unrecognized type:' + iter.type);
+ }
+ }
+
+ return str;
+ };
+
+ /** gluVarTypeUtil.SubTypeAccess
+ * @param {gluVarType.VarType} type
+ * @constructor
+ */
+ gluVarTypeUtil.SubTypeAccess = function(type) {
+
+ this.m_type = null; // VarType
+ this.m_path = []; // TypeComponentVector
+
+ };
+
+ /** @private */
+ gluVarTypeUtil.SubTypeAccess.prototype.helper = function(type, ndx) {
+ this.m_path.push(new gluVarTypeUtil.VarTypeComponent(type, ndx));
+ if (!this.isValid()) {
+ throw new Error;
+ }
+ return this;
+ };
+
+ gluVarTypeUtil.SubTypeAccess.prototype.member = function(ndx) {
+ return this.helper(gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER, ndx);
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.element = function(ndx) {
+ return this.helper(gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT, ndx);
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.column = function(ndx) {
+ return this.helper(gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN, ndx);
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.component = function(ndx) {
+ return this.helper(gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT, ndx);
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.parent = function() {
+ if (!this.m_path.length) {
+ throw new Error;
+ }
+ this.m_path.pop();
+ return this;
+ };
+
+ gluVarTypeUtil.SubTypeAccess.prototype.isValid = function() {
+ return gluVarTypeUtil.isValidTypePath(this.m_type, this.m_path);
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.getType = function() {
+ return gluVarTypeUtil.getVarType(this.m_type, this.m_path);
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.getPath = function() {
+ return this.m_path;
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.empty = function() {
+ return !this.m_path.length;
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.is = function(other) {
+ return (
+ gluVarTypeUtil.array_op_equivalent(this.m_path, other.m_path) &&
+ this.m_type.is(other.m_type)
+ );
+ };
+ gluVarTypeUtil.SubTypeAccess.prototype.isnt = function(other) {
+ return (
+ !gluVarTypeUtil.array_op_equivalent(this.m_path, other.m_path) ||
+ this.m_type.isnt(other.m_type)
+ );
+ };
+
+ /**
+ * Subtype iterator parent class.
+ * basic usage for all child classes:
+ * for (var i = new gluVarTypeUtil.BasicTypeIterator(type) ; !i.end() ; i.next()) {
+ * var j = i.getType();
+ * }
+ * @constructor
+ */
+ gluVarTypeUtil.SubTypeIterator = function(type) {
+
+ /** @private */
+ this.m_type = null; // const VarType*
+ /** @private */
+ this.m_path = []; // TypeComponentVector
+
+ if (type) {
+ this.m_type = type;
+ this.findNext();
+ }
+
+ };
+
+ gluVarTypeUtil.SubTypeIterator.prototype.isExpanded = function(type) {
+ throw new Error('This function must be overriden in child class');
+ };
+
+ /** removeTraversed
+ * @private
+ */
+ gluVarTypeUtil.SubTypeIterator.prototype.removeTraversed = function() {
+
+ while (this.m_path.length) {
+ var curComp = this.m_path[this.m_path.length - 1]; // gluVarTypeUtil.VarTypeComponent&
+ var parentType = gluVarTypeUtil.getVarType(this.m_type, this.m_path, 0, this.m_path.length - 1); // VarType
+
+ if (curComp.type == gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN) {
+ if (!gluShaderUtil.isDataTypeMatrix(parentType.getBasicType())) {
+ throw new Error('Isn\'t a matrix.');
+ }
+ if (curComp.index + 1 < gluShaderUtil.getDataTypeMatrixNumColumns(parentType.getBasicType())) {
+ break;
+ }
+
+ } else if (curComp.type == gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT) {
+ if (!gluShaderUtil.isDataTypeVector(parentType.getBasicType())) {
+ throw new Error('Isn\'t a vector.');
+ }
+ if (curComp.index + 1 < gluShaderUtil.getDataTypeScalarSize(parentType.getBasicType())) {
+ break;
+ }
+
+ } else if (curComp.type == gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT) {
+ if (!parentType.isArrayType()) {
+ throw new Error('Isn\'t an array.');
+ }
+ if (curComp.index + 1 < parentType.getArraySize()) {
+ break;
+ }
+
+ } else if (curComp.type == gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER) {
+ if (!parentType.isStructType()) {
+ throw new Error('Isn\'t a struct.');
+ }
+ if (curComp.index + 1 < parentType.getStruct().getNumMembers()) {
+ break;
+ }
+
+ }
+
+ this.m_path.pop();
+ }
+ };
+ gluVarTypeUtil.SubTypeIterator.prototype.findNext = function() {
+
+ if (this.m_path.length > 0) {
+ // Increment child counter in current level.
+ var curComp = this.m_path[this.m_path.length - 1]; // gluVarTypeUtil.VarTypeComponent&
+ curComp.index += 1;
+ }
+
+ for (;;) {
+
+ var curType = gluVarTypeUtil.getVarType(this.m_type, this.m_path); // VarType
+
+ if (this.isExpanded(curType))
+ break;
+
+ // Recurse into child type.
+ if (curType.isBasicType()) {
+ var basicType = curType.getBasicType(); // DataType
+
+ if (gluShaderUtil.isDataTypeMatrix(basicType)) {
+ this.m_path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN, 0));
+
+ } else if (gluShaderUtil.isDataTypeVector(basicType)) {
+ this.m_path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT, 0));
+
+ } else {
+ throw new Error('Cant expand scalars - isExpanded() is buggy.');
+ }
+
+ } else if (curType.isArrayType()) {
+ this.m_path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT, 0));
+
+ } else if (curType.isStructType()) {
+ this.m_path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER, 0));
+
+ } else {
+ throw new Error();
+ }
+ }
+
+ };
+ gluVarTypeUtil.SubTypeIterator.prototype.end = function() {
+ return (this.m_type == null);
+ };
+ /** next
+ * equivelant to operator++(), doesnt return.
+ */
+ gluVarTypeUtil.SubTypeIterator.prototype.next = function() {
+ if (this.m_path.length > 0) {
+ // Remove traversed nodes.
+ this.removeTraversed();
+
+ if (this.m_path.length > 0)
+ this.findNext();
+ else
+ this.m_type = null; // Unset type to signal end.
+ } else {
+ if (!this.isExpanded(gluVarTypeUtil.getVarType(this.m_type, this.m_path))) {
+ throw new Error('First type was already expanded.');
+ }
+ this.m_type = null;
+ }
+ };
+ gluVarTypeUtil.SubTypeIterator.prototype.getType = function() {
+ return gluVarTypeUtil.getVarType(this.m_type, this.m_path);
+ };
+ gluVarTypeUtil.SubTypeIterator.prototype.getPath = function() {
+ return this.m_path;
+ };
+
+ gluVarTypeUtil.SubTypeIterator.prototype.toString = function() {
+ var x = new gluVarTypeUtil.TypeAccessFormat(this.m_type, this.m_path);
+ return x.toString();
+ };
+
+ /** gluVarTypeUtil.BasicTypeIterator
+ * @param {gluVarType.VarType} type
+ * @constructor
+ * @extends {gluVarTypeUtil.SubTypeIterator}
+ */
+ gluVarTypeUtil.BasicTypeIterator = function(type) {
+ gluVarTypeUtil.SubTypeIterator.call(this, type);
+ };
+ gluVarTypeUtil.BasicTypeIterator.prototype = Object.create(gluVarTypeUtil.SubTypeIterator.prototype);
+ gluVarTypeUtil.BasicTypeIterator.prototype.constructor = gluVarTypeUtil.BasicTypeIterator;
+
+ gluVarTypeUtil.BasicTypeIterator.prototype.isExpanded = function(type) {
+ return type.isBasicType();
+ };
+
+ /** gluVarTypeUtil.VectorTypeIterator
+ * @param {gluVarType.VarType} type
+ * @constructor
+ * @extends {gluVarTypeUtil.SubTypeIterator}
+ */
+ gluVarTypeUtil.VectorTypeIterator = function(type) {
+ gluVarTypeUtil.SubTypeIterator.call(this, type);
+ };
+ gluVarTypeUtil.VectorTypeIterator.prototype = Object.create(gluVarTypeUtil.SubTypeIterator.prototype);
+ gluVarTypeUtil.VectorTypeIterator.prototype.constructor = gluVarTypeUtil.VectorTypeIterator;
+
+ gluVarTypeUtil.VectorTypeIterator.prototype.isExpanded = function(type) {
+ return type.isBasicType() && gluShaderUtil.isDataTypeScalarOrVector(type.getBasicType());
+ };
+
+ /** gluVarTypeUtil.ScalarTypeIterator
+ * @param {gluVarType.VarType} type
+ * @constructor
+ * @extends {gluVarTypeUtil.SubTypeIterator}
+ */
+ gluVarTypeUtil.ScalarTypeIterator = function(type) {
+ gluVarTypeUtil.SubTypeIterator.call(this, type);
+ };
+ gluVarTypeUtil.ScalarTypeIterator.prototype = Object.create(gluVarTypeUtil.SubTypeIterator.prototype);
+ gluVarTypeUtil.ScalarTypeIterator.prototype.constructor = gluVarTypeUtil.ScalarTypeIterator;
+
+ gluVarTypeUtil.ScalarTypeIterator.prototype.isExpanded = function(type) {
+ return type.isBasicType() && gluShaderUtil.isDataTypeScalar(type.getBasicType());
+ };
+
+ gluVarTypeUtil.inBounds = (function(x, a, b) { return a <= x && x < b; });
+
+ /** gluVarTypeUtil.isValidTypePath
+ * @param {gluVarType.VarType} type
+ * @param {Array<gluVarTypeUtil.VarTypeComponent>} array
+ * @param {number=} begin
+ * @param {number=} end
+ * @return {boolean}
+ */
+ gluVarTypeUtil.isValidTypePath = function(type, array, begin, end) {
+
+ if (typeof(begin) == 'undefined') {begin = 0;}
+ if (typeof(end) == 'undefined') {begin = array.length;}
+
+ var curType = type; // const VarType*
+ var pathIter = begin; // Iterator
+
+ // Process struct member and array element parts of path.
+ while (pathIter != end) {
+ var element = array[pathIter];
+
+ if (element.type == gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER) {
+
+ if (!curType.isStructType() || !gluVarTypeUtil.inBounds(element.index, 0, curType.getStruct().getNumMembers())) {
+ return false;
+ }
+
+ curType = curType.getStruct().getMember(element.index).getType();
+
+ } else if (element.type == gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT) {
+ if (
+ !curType.isArrayType() ||
+ (
+ curType.getArraySize() != gluVarType.VarType.UNSIZED_ARRAY &&
+ !gluVarTypeUtil.inBounds(element.index, 0, curType.getArraySize())
+ )
+ ) {
+ return false;
+ }
+
+ curType = curType.getElementType();
+ } else {
+ break;
+ }
+
+ ++pathIter;
+ }
+
+ if (pathIter != end) {
+ if (!(
+ array[pathIter].type == gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN ||
+ array[pathIter].type == gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT
+ )) {
+ throw new Error('Not a matrix or a vector');
+ }
+
+ // Current type should be basic type.
+ if (!curType.isBasicType()) {
+ return false;
+ }
+
+ var basicType = curType.getBasicType(); // DataType
+
+ if (array[pathIter].type == gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN) {
+ if (!gluShaderUtil.isDataTypeMatrix(basicType)) {
+ return false;
+ }
+
+ basicType = gluShaderUtil.getDataTypeFloatVec(gluShaderUtil.getDataTypeMatrixNumRows(basicType));
+ ++pathIter;
+ }
+
+ if (pathIter != end && array[pathIter].type == gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT) {
+ if (!gluShaderUtil.isDataTypeVector(basicType))
+ return false;
+
+ basicType = gluShaderUtil.getDataTypeScalarType(basicType);
+ ++pathIter;
+ }
+ }
+
+ return pathIter == end;
+ };
+
+ /** gluVarTypeUtil.getVarType
+ * @param {gluVarType.VarType} type
+ * @param {Array<gluVarTypeUtil.VarTypeComponent>} array
+ * @param {number=} start
+ * @param {number=} end
+ * @return {gluVarType.VarType}
+ */
+ gluVarTypeUtil.getVarType = function(type, array, start, end) {
+
+ if (typeof(start) == 'undefined') start = 0;
+ if (typeof(end) == 'undefined') end = array.length;
+
+ if (!gluVarTypeUtil.isValidTypePath(type, array, start, end)) {
+ throw new Error('Type is invalid');
+ }
+
+ var curType = type; // const VarType*
+ var element = null; // Iterator
+ var pathIter = 0;
+
+ // Process struct member and array element parts of path.
+ for (pathIter = start; pathIter != end; ++pathIter) {
+ element = array[pathIter];
+
+ if (element.type == gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER) {
+ curType = curType.getStruct().getMember(element.index).getType();
+
+ } else if (element.type == gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT) {
+ curType = curType.getElementType();
+
+ } else {
+ break;
+
+ }
+ }
+
+ if (pathIter != end) {
+
+ var basicType = curType.getBasicType(); // DataType
+ var precision = curType.getPrecision(); // Precision
+
+ if (element.type == gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN) {
+ basicType = gluShaderUtil.getDataTypeFloatVec(gluShaderUtil.getDataTypeMatrixNumRows(basicType));
+ element = array[++pathIter];
+ }
+
+ if (pathIter != end && element.type == gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT) {
+ basicType = gluShaderUtil.getDataTypeScalarTypeAsDataType(basicType);
+ element = array[++pathIter];
+ }
+
+ if (pathIter != end) {
+ throw new Error();
+ }
+ return gluVarType.newTypeBasic(basicType, precision);
+ } else {
+ /* TODO: Original code created an object copy. We are returning reference to the same object */
+ return curType;
+ }
+ };
+
+ gluVarTypeUtil.parseVariableName = function(nameWithPath) {
+ var tokenizer = new gluVarTypeUtil.VarTokenizer(nameWithPath);
+ if (tokenizer.getToken() != gluVarTypeUtil.VarTokenizer.s_Token.IDENTIFIER) {
+ throw new Error('Not an identifier.');
+ }
+ return tokenizer.getIdentifier();
+ };
+
+ // returns an array (TypeComponentVector& path)
+ // params: const char*, const VarType&
+ gluVarTypeUtil.parseTypePath = function(nameWithPath, type) {
+
+ var tokenizer = new gluVarTypeUtil.VarTokenizer(nameWithPath);
+
+ if (tokenizer.getToken() == gluVarTypeUtil.VarTokenizer.s_Token.IDENTIFIER) {
+ tokenizer.advance();
+ }
+
+ var path = [];
+
+ while (tokenizer.getToken() != gluVarTypeUtil.VarTokenizer.s_Token.END) {
+
+ var curType = gluVarTypeUtil.getVarType(type, path);
+
+ if (tokenizer.getToken() == gluVarTypeUtil.VarTokenizer.s_Token.PERIOD) {
+
+ tokenizer.advance();
+ if (tokenizer.getToken() != gluVarTypeUtil.VarTokenizer.s_Token.IDENTIFIER) {
+ throw new Error();
+ }
+ if (!curType.isStructType()) {
+ throw new Error('Invalid field selector');
+ }
+
+ // Find member.
+ var memberName = tokenizer.getIdentifier();
+ var ndx = 0;
+ for (; ndx < curType.getStruct().getSize(); ++ndx) {
+
+ if (memberName == curType.getStruct().getMember(ndx).getName()) {
+ break;
+ }
+
+ }
+ if (ndx >= curType.getStruct().getSize()) {
+ throw new Error('Member not found in type: ' + memberName);
+ }
+
+ path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER, ndx));
+ tokenizer.advance();
+
+ } else if (tokenizer.getToken() == gluVarTypeUtil.VarTokenizer.s_Token.LEFT_BRACKET) {
+
+ tokenizer.advance();
+ if (tokenizer.getToken() != gluVarTypeUtil.VarTokenizer.s_Token.NUMBER) {
+ throw new Error();
+ }
+
+ var ndx = tokenizer.getNumber();
+
+ if (curType.isArrayType()) {
+ if (!gluVarTypeUtil.inBounds(ndx, 0, curType.getArraySize())) throw new Error;
+ path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT, ndx));
+
+ } else if (curType.isBasicType() && gluShaderUtil.isDataTypeMatrix(curType.getBasicType())) {
+ if (!gluVarTypeUtil.inBounds(ndx, 0, gluShaderUtil.getDataTypeMatrixNumColumns(curType.getBasicType()))) throw new Error;
+ path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN, ndx));
+
+ } else if (curType.isBasicType() && gluShaderUtil.isDataTypeVector(curType.getBasicType())) {
+ if (!gluVarTypeUtil.inBounds(ndx, 0, gluShaderUtil.getDataTypeScalarSize(curType.getBasicType()))) throw new Error;
+ path.push(new gluVarTypeUtil.VarTypeComponent(gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT, ndx));
+
+ } else {
+ //TCU_FAIL
+ throw new Error('Invalid subscript');
+ }
+
+ tokenizer.advance();
+ if (tokenizer.getToken() != gluVarTypeUtil.VarTokenizer.s_Token.RIGHT_BRACKET) {
+ throw new Error('Expected token RIGHT_BRACKET');
+ }
+ tokenizer.advance();
+
+ } else {
+ // TCU_FAIL
+ throw new Error('Unexpected token');
+ }
+ }
+
+ return path;
+
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/00_test_list.txt
new file mode 100644
index 0000000000..7db3d9d5c7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/00_test_list.txt
@@ -0,0 +1 @@
+referencecontext.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/referencecontext.html b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/referencecontext.html
new file mode 100644
index 0000000000..f3ba0ed262
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/referencecontext.html
@@ -0,0 +1,32 @@
+<html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>Reference context test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('framework.opengl.simplereference.sglrReferenceContextTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+ try {
+ framework.opengl.simplereference.sglrReferenceContextTest.run(gl);
+ }
+ catch(err)
+ {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrGLContext.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrGLContext.js
new file mode 100644
index 0000000000..13f75e8f5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrGLContext.js
@@ -0,0 +1,231 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.referencerenderer.rrRenderState');
+goog.require('framework.referencerenderer.rrRenderer');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+
+goog.scope(function() {
+
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var tcuTexture = framework.common.tcuTexture;
+ var deUtil = framework.delibs.debase.deUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var rrDefs = framework.referencerenderer.rrDefs;
+ var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+ var rrRenderer = framework.referencerenderer.rrRenderer;
+ var rrRenderState = framework.referencerenderer.rrRenderState;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * sglrGLContext.GLContext wraps the standard WebGL context to be able to be used interchangeably with the ReferenceContext
+ * @constructor
+ * @extends {WebGL2RenderingContext}
+ * @param {?WebGL2RenderingContext} context
+ * @param {Array<number>=} viewport
+ */
+ sglrGLContext.GLContext = function(context, viewport) {
+ DE_ASSERT(context);
+
+ var functionwrapper = function(context, fname) {
+ return function() {
+ return context[fname].apply(context, arguments);
+ };
+ };
+
+ var wrap = {};
+ for (var i in context) {
+ try {
+ if (typeof context[i] == 'function') {
+ wrap[i] = functionwrapper(context, i);
+ } else {
+ wrap[i] = context[i];
+ }
+ } catch (e) {
+ throw new Error('GLContext: Error accessing ' + i);
+ }
+ }
+ if (viewport)
+ context.viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+
+ /**
+ * createProgram
+ * @override
+ * @param {sglrShaderProgram.ShaderProgram=} shader
+ * @return {!WebGLProgram}
+ */
+ this.createProgram = function(shader) {
+ var program = new gluShaderProgram.ShaderProgram(
+ context,
+ gluShaderProgram.makeVtxFragSources(
+ shader.m_vertSrc,
+ shader.m_fragSrc
+ )
+ );
+
+ if (!program.isOk()) {
+ bufferedLogToConsole(program.toString());
+ testFailedOptions('Compile failed', true);
+ }
+ return program.getProgram();
+ };
+ wrap['createProgram'] = this.createProgram;
+
+ /**
+ * Draws quads from vertex arrays
+ * @param {number} primitive Primitive type
+ * @param {number} first First vertex to begin drawing with
+ * @param {number} count Number of vertices
+ */
+ var drawQuads = function(primitive, first, count) {
+ context.drawArrays(primitive, first, count);
+ };
+ wrap['drawQuads'] = drawQuads;
+
+ /**
+ * @return {number}
+ */
+ var getWidth = function() {
+ if(viewport)
+ return viewport[2];
+ else
+ return context.drawingBufferWidth;
+ };
+ wrap['getWidth'] = getWidth;
+
+ /**
+ * @return {number}
+ */
+ var getHeight = function() {
+ if(viewport)
+ return viewport[3];
+ else
+ return context.drawingBufferHeight;
+ };
+ wrap['getHeight'] = getHeight;
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {number} format
+ * @param {number} dataType
+ * @param {ArrayBuffer|ArrayBufferView} data
+ */
+ var readPixels = function(x, y, width, height, format, dataType, data) {
+ /** @type {?ArrayBufferView} */ var dataArr;
+ if (!ArrayBuffer.isView(data)) {
+ var type = gluTextureUtil.mapGLChannelType(dataType, true);
+ var dataArrType = tcuTexture.getTypedArray(type);
+ dataArr = new dataArrType(data);
+ } else {
+ dataArr = /** @type {?ArrayBufferView} */ (data);
+ }
+
+ context.readPixels(x, y, width, height, format, dataType, dataArr);
+ };
+ wrap['readPixels'] = readPixels;
+
+ /**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ */
+ var texImage2DDelegate = function(target, level, internalFormat, width, height) {
+ var format;
+ var dataType;
+
+ switch(internalFormat)
+ {
+ case gl.ALPHA:
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ case gl.RGB:
+ case gl.RGBA:
+ format = internalFormat;
+ dataType = gl.UNSIGNED_BYTE;
+ break;
+ default:
+ {
+ var transferFmt = gluTextureUtil.getTransferFormat(gluTextureUtil.mapGLInternalFormat(internalFormat));
+ format = transferFmt.format;
+ dataType = transferFmt.dataType;
+ break;
+ }
+ }
+ context.texImage2D(target, level, internalFormat, width, height, 0, format, dataType, null);
+ };
+ wrap['texImage2DDelegate'] = texImage2DDelegate;
+
+ return wrap;
+ };
+
+ /**
+ * createProgram - This had to be added here as dummy to remove a warning when the only context used is GLContext (no reference context)
+ * @override
+ * @param {sglrShaderProgram.ShaderProgram=} shader
+ * @return {!WebGLProgram}
+ */
+ sglrGLContext.GLContext.prototype.createProgram = function(shader) {return this.createProgram();};
+
+ /**
+ * @param ctx GL-like context
+ * @param {string} name
+ * @return {boolean}
+ */
+ sglrGLContext.isExtensionSupported = function(ctx, name) {
+ var extns = ctx.getSupportedExtensions();
+ var found = false;
+ if (extns) {
+ var index = extns.indexOf(name);
+ if (index != -1)
+ found = true;
+ }
+ return found;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContext.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContext.js
new file mode 100644
index 0000000000..523dbe607f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContext.js
@@ -0,0 +1,4986 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuMatrixUtil');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.simplereference.sglrReferenceUtils');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.referencerenderer.rrRenderState');
+goog.require('framework.referencerenderer.rrRenderer');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+
+goog.scope(function() {
+
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+ var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+ var tcuTexture = framework.common.tcuTexture;
+ var deMath = framework.delibs.debase.deMath;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var rrRenderer = framework.referencerenderer.rrRenderer;
+ var rrDefs = framework.referencerenderer.rrDefs;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrRenderState = framework.referencerenderer.rrRenderState;
+ var sglrReferenceUtils = framework.opengl.simplereference.sglrReferenceUtils;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var tcuMatrixUtil = framework.common.tcuMatrixUtil;
+
+ sglrReferenceContext.rrMPBA = rrMultisamplePixelBufferAccess;
+
+ //TODO: Implement automatic error checking in sglrReferenceContext, optional on creation.
+
+ /** @typedef {WebGLRenderbuffer|WebGLTexture|sglrReferenceContext.Renderbuffer|sglrReferenceContext.TextureContainer} */ sglrReferenceContext.AnyRenderbuffer;
+
+ /** @typedef {WebGLFramebuffer|sglrReferenceContext.Framebuffer} */ sglrReferenceContext.AnyFramebuffer;
+
+ /**
+ * @param {number} error
+ * @param {number} message
+ * @throws {Error}
+ */
+ sglrReferenceContext.GLU_EXPECT_NO_ERROR = function(error, message) {
+ if (error !== gl.NONE) {
+ bufferedLogToConsole('Assertion failed message:' + message);
+ }
+ };
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ // /* TODO: remove */
+ // /** @type {WebGL2RenderingContext} */ var gl;
+
+ sglrReferenceContext.MAX_TEXTURE_SIZE_LOG2 = 14;
+ sglrReferenceContext.MAX_TEXTURE_SIZE = 1 << sglrReferenceContext.MAX_TEXTURE_SIZE_LOG2;
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ * @return {number}
+ */
+ sglrReferenceContext.getNumMipLevels2D = function(width, height) {
+ return Math.floor(Math.log2(Math.max(width, height)) + 1);
+ };
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @return {number}
+ */
+ sglrReferenceContext.getNumMipLevels3D = function(width, height, depth) {
+ return Math.floor(Math.log2(Math.max(width, height, depth)) + 1);
+ };
+
+ /**
+ * @param {number} baseLevelSize
+ * @param {number} levelNdx
+ * @return {number}
+ */
+ sglrReferenceContext.getMipLevelSize = function(baseLevelSize, levelNdx) {
+ return Math.max(baseLevelSize >> levelNdx, 1);
+ };
+
+ sglrReferenceContext.mapGLCubeFace = function(face) {
+ switch (face) {
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_X: return tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X;
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_X: return tcuTexture.CubeFace.CUBEFACE_POSITIVE_X;
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: return tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y;
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_Y: return tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y;
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: return tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z;
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_Z: return tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z;
+ default: throw new Error('Invalid cube face: ' + face);
+ }
+ };
+
+ /**
+ * @param {tcuTexture.FilterMode} mode
+ * @return {boolean}
+ */
+ sglrReferenceContext.isMipmapFilter = function(/*const tcu::Sampler::FilterMode*/ mode) {
+ return mode != tcuTexture.FilterMode.NEAREST && mode != tcuTexture.FilterMode.LINEAR;
+ };
+
+ sglrReferenceContext.getNumMipLevels1D = function(size) {
+ return Math.floor(Math.log2(size)) + 1;
+ };
+
+ /**
+ * @param {?sglrReferenceContext.TextureType} type
+ * @return {sglrReferenceContext.TexTarget}
+ */
+ sglrReferenceContext.texLayeredTypeToTarget = function(type) {
+ switch (type) {
+ case sglrReferenceContext.TextureType.TYPE_2D_ARRAY: return sglrReferenceContext.TexTarget.TEXTARGET_2D_ARRAY;
+ case sglrReferenceContext.TextureType.TYPE_3D: return sglrReferenceContext.TexTarget.TEXTARGET_3D;
+ case sglrReferenceContext.TextureType.TYPE_CUBE_MAP_ARRAY: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_ARRAY;
+ default: throw new Error('Invalid texture type: ' + type);
+ }
+ };
+
+ /**
+ * @param {rrDefs.IndexType} indexType
+ * @return {number}
+ * @throws {Error}
+ */
+ sglrReferenceContext.getFixedRestartIndex = function(indexType) {
+ switch (indexType) {
+ case rrDefs.IndexType.INDEXTYPE_UINT8: return 0xFF;
+ case rrDefs.IndexType.INDEXTYPE_UINT16: return 0xFFFF;
+ case rrDefs.IndexType.INDEXTYPE_UINT32: return 0xFFFFFFFF;
+ default:
+ throw new Error('Unrecognized index type: ' + indexType);
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {sglrShaderProgram.ShaderProgram} program
+ */
+ sglrReferenceContext.ShaderProgramObjectContainer = function(program) {
+ this.m_program = program;
+ /** @type {boolean} */ this.m_deleteFlag = false;
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ * @constructor
+ */
+ sglrReferenceContext.ReferenceContextLimits = function(gl) {
+ /** @type {number} */ this.maxTextureImageUnits = 16;
+ /** @type {number} */ this.maxTexture2DSize = 2048;
+ /** @type {number} */ this.maxTextureCubeSize = 2048;
+ /** @type {number} */ this.maxTexture2DArrayLayers = 256;
+ /** @type {number} */ this.maxTexture3DSize = 256;
+ /** @type {number} */ this.maxRenderbufferSize = 2048;
+ /** @type {number} */ this.maxVertexAttribs = 16;
+
+ if (gl) {
+ this.maxTextureImageUnits = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
+ this.maxTexture2DSize = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_SIZE));
+ this.maxTextureCubeSize = /** @type {number} */ (gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE));
+ this.maxRenderbufferSize = /** @type {number} */ (gl.getParameter(gl.MAX_RENDERBUFFER_SIZE));
+ this.maxVertexAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ this.maxTexture2DArrayLayers = /** @type {number} */ (gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS));
+ this.maxTexture3DSize = /** @type {number} */ (gl.getParameter(gl.MAX_3D_TEXTURE_SIZE));
+
+ // Limit texture sizes to supported values
+ this.maxTexture2DSize = Math.min(this.maxTexture2DSize, sglrReferenceContext.MAX_TEXTURE_SIZE);
+ this.maxTextureCubeSize = Math.min(this.maxTextureCubeSize, sglrReferenceContext.MAX_TEXTURE_SIZE);
+ this.maxTexture3DSize = Math.min(this.maxTexture3DSize, sglrReferenceContext.MAX_TEXTURE_SIZE);
+
+ sglrReferenceContext.GLU_EXPECT_NO_ERROR(gl.getError(), gl.NO_ERROR);
+ }
+
+ /* TODO: Port
+ // \todo [pyry] Figure out following things:
+ // + supported fbo configurations
+ // ...
+
+ // \todo [2013-08-01 pyry] Do we want to make these conditional based on renderCtx?
+ addExtension("gl.EXT_color_buffer_half_float");
+ addExtension("gl.WEBGL_color_buffer_float");
+ */
+ };
+
+ /**
+ * @enum
+ */
+ sglrReferenceContext.TextureType = {
+ TYPE_2D: 0,
+ TYPE_CUBE_MAP: 1,
+ TYPE_2D_ARRAY: 2,
+ TYPE_3D: 3,
+ TYPE_CUBE_MAP_ARRAY: 4
+ };
+
+ /**
+ * @constructor
+ * @implements {rrDefs.Sampler}
+ * @param {sglrReferenceContext.TextureType} type
+ */
+ sglrReferenceContext.Texture = function(type) {
+ // NamedObject.call(this, name);
+ /** @type {sglrReferenceContext.TextureType} */ this.m_type = type;
+ /** @type {boolean} */ this.m_immutable = false;
+ /** @type {number} */ this.m_baseLevel = 0;
+ /** @type {number} */ this.m_maxLevel = 1000;
+ /** @type {tcuTexture.Sampler} */ this.m_sampler = new tcuTexture.Sampler(
+ tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR,
+ tcuTexture.FilterMode.LINEAR,
+ 0,
+ true,
+ tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0,
+ [0, 0, 0, 0],
+ true);
+ };
+
+ /**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @throws {Error}
+ */
+ sglrReferenceContext.Texture.prototype.sample = function(pos, lod) {throw new Error('Intentionally empty. Call method from child class instead'); };
+
+ /**
+ * @param {Array<Array<number>>} packetTexcoords
+ * @param {number} lodBias
+ * @throws {Error}
+ */
+ sglrReferenceContext.Texture.prototype.sample4 = function(packetTexcoords, lodBias) {throw new Error('Intentionally empty. Call method from child class instead'); };
+
+ // sglrReferenceContext.Texture.prototype = Object.create(NamedObject.prototype);
+ // sglrReferenceContext.Texture.prototype.constructor = sglrReferenceContext.Texture;
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.Texture.prototype.getType = function() { return this.m_type; };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.Texture.prototype.getBaseLevel = function() { return this.m_baseLevel; };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.Texture.prototype.getMaxLevel = function() { return this.m_maxLevel; };
+
+ /**
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture.prototype.isImmutable = function() { return this.m_immutable; };
+
+ /**
+ * @param {number} baseLevel
+ */
+ sglrReferenceContext.Texture.prototype.setBaseLevel = function(baseLevel) { this.m_baseLevel = baseLevel; };
+
+ /**
+ * @param {number} maxLevel
+ */
+ sglrReferenceContext.Texture.prototype.setMaxLevel = function(maxLevel) { this.m_maxLevel = maxLevel; };
+
+ /**
+ */
+ sglrReferenceContext.Texture.prototype.setImmutable = function() { this.m_immutable = true; };
+
+ /**
+ * @return {tcuTexture.Sampler}
+ */
+ sglrReferenceContext.Texture.prototype.getSampler = function() { return this.m_sampler; };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.TextureLevelArray = function() {
+ /** @type {Array<ArrayBuffer>} */ this.m_data = [];
+ /** @type {Array<tcuTexture.PixelBufferAccess>} */ this.m_access = [];
+ };
+
+ /**
+ * @param {number} level
+ * @return {boolean}
+ */
+ sglrReferenceContext.TextureLevelArray.prototype.hasLevel = function(level) { return this.m_data[level] != null; };
+
+ /**
+ * @param {number} level
+ * @return {tcuTexture.PixelBufferAccess}
+ * @throws {Error}
+ */
+ sglrReferenceContext.TextureLevelArray.prototype.getLevel = function(level) {
+ if (!this.hasLevel(level))
+ throw new Error('Level: ' + level + ' is not defined.');
+
+ return this.m_access[level];
+ };
+
+ /**
+ * @return {Array<tcuTexture.PixelBufferAccess>}
+ */
+ sglrReferenceContext.TextureLevelArray.prototype.getLevels = function() { return this.m_access; };
+
+ /**
+ * @param {number} level
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+ sglrReferenceContext.TextureLevelArray.prototype.allocLevel = function(level, format, width, height, depth) {
+ /** @type {number} */ var dataSize = format.getPixelSize() * width * height * depth;
+ if (this.hasLevel(level))
+ this.clearLevel(level);
+
+ this.m_data[level] = new ArrayBuffer(dataSize);
+ this.m_access[level] = new tcuTexture.PixelBufferAccess({
+ format: format,
+ width: width,
+ height: height,
+ depth: depth,
+ data: this.m_data[level]});
+ };
+
+ /**
+ * @param {number} level
+ */
+ sglrReferenceContext.TextureLevelArray.prototype.clearLevel = function(level) {
+ delete this.m_data[level];
+ delete this.m_access[level];
+ };
+
+ /**
+ */
+ sglrReferenceContext.TextureLevelArray.prototype.clear = function() {
+ for (var key in this.m_data)
+ delete this.m_data[key];
+
+ for (var key in this.m_access)
+ delete this.m_access[key];
+ };
+
+ /**
+ * @constructor
+ * @extends {sglrReferenceContext.Texture}
+ */
+ sglrReferenceContext.Texture2D = function() {
+ sglrReferenceContext.Texture.call(this, sglrReferenceContext.TextureType.TYPE_2D);
+ /** @type {tcuTexture.Texture2DView} */ this.m_view = new tcuTexture.Texture2DView(0, null);
+ /** @type {sglrReferenceContext.TextureLevelArray} */ this.m_levels = new sglrReferenceContext.TextureLevelArray();
+ };
+
+ /**
+ */
+ sglrReferenceContext.Texture2D.prototype = Object.create(sglrReferenceContext.Texture.prototype);
+ sglrReferenceContext.Texture2D.prototype.constructor = sglrReferenceContext.Texture2D;
+
+ sglrReferenceContext.Texture2D.prototype.clearLevels = function() { this.m_levels.clear(); };
+
+ /**
+ * @param {number} level
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture2D.prototype.hasLevel = function(level) { return this.m_levels.hasLevel(level); };
+
+ /**
+ * @param {number} level
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.Texture2D.prototype.getLevel = function(level) { return this.m_levels.getLevel(level); };
+
+ /**
+ * @param {number} level
+ * @param {?tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.Texture2D.prototype.allocLevel = function(level, format, width, height) { this.m_levels.allocLevel(level, format, width, height, 1); };
+
+ /**
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture2D.prototype.isComplete = function() {
+ /** @type {number} */ var baseLevel = this.getBaseLevel();
+
+ if (this.hasLevel(baseLevel)) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level0 = this.getLevel(baseLevel);
+ /** @type {boolean} */ var mipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+
+ if (mipmap) {
+ /** @type {tcuTexture.TextureFormat} */ var format = level0.getFormat();
+ /** @type {number} */ var w = level0.getWidth();
+ /** @type {number} */ var h = level0.getHeight();
+ /** @type {number} */ var numLevels = Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels2D(w, h));
+
+ for (var levelNdx = 1; levelNdx < numLevels; levelNdx++) {
+ if (this.hasLevel(baseLevel + levelNdx)) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level = this.getLevel(baseLevel + levelNdx);
+ /** @type {number} */ var expectedW = sglrReferenceContext.getMipLevelSize(w, levelNdx);
+ /** @type {number} */ var expectedH = sglrReferenceContext.getMipLevelSize(h, levelNdx);
+
+ if (level.getWidth() != expectedW ||
+ level.getHeight() != expectedH ||
+ !level.getFormat().isEqual(format))
+ return false;
+ } else
+ return false;
+ }
+ }
+
+ return true;
+ } else
+ return false;
+ };
+
+ /**
+ */
+ sglrReferenceContext.Texture2D.prototype.updateView = function() {
+ /** @type {number} */ var baseLevel = this.getBaseLevel();
+
+ if (this.hasLevel(baseLevel) && !this.getLevel(baseLevel).isEmpty()) {
+ // Update number of levels in mipmap pyramid.
+ /** @type {number} */ var width = this.getLevel(baseLevel).getWidth();
+ /** @type {number} */ var height = this.getLevel(baseLevel).getHeight();
+ /** @type {boolean} */ var isMipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+ /** @type {number} */ var numLevels = isMipmap ? Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels2D(width, height)) : 1;
+
+ this.m_view = new tcuTexture.Texture2DView(numLevels, this.m_levels.getLevels().slice(baseLevel));
+ } else
+ this.m_view = new tcuTexture.Texture2DView(0, null);
+ };
+
+ /**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+ sglrReferenceContext.Texture2D.prototype.sample = function(pos, lod) {
+ return this.m_view.sample(this.getSampler(), pos, lod);
+ };
+
+ /**
+ * @param {Array<Array<number>>} packetTexcoords 4 vec2 coordinates
+ * @param {number} lodBias_
+ * @return {Array<Array<number>>} 4 vec4 samples
+ */
+ sglrReferenceContext.Texture2D.prototype.sample4 = function(packetTexcoords, lodBias_) {
+ /** @type {number} */ var lodBias = lodBias_ || 0;
+ /** @type {number} */ var texWidth = this.m_view.getWidth();
+ /** @type {number} */ var texHeight = this.m_view.getHeight();
+ /** @type {Array<Array<number>>}*/ var output = [];
+
+ /** @type {Array<number>}*/ var dFdx0 = deMath.subtract(packetTexcoords[1], packetTexcoords[0]);
+ /** @type {Array<number>}*/ var dFdx1 = deMath.subtract(packetTexcoords[3], packetTexcoords[2]);
+ /** @type {Array<number>}*/ var dFdy0 = deMath.subtract(packetTexcoords[2], packetTexcoords[0]);
+ /** @type {Array<number>}*/ var dFdy1 = deMath.subtract(packetTexcoords[3], packetTexcoords[1]);
+
+ for (var fragNdx = 0; fragNdx < 4; ++fragNdx) {
+ /** @type {Array<number>}*/var dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
+ /** @type {Array<number>}*/var dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
+
+ /** @type {number} */ var mu = Math.max(Math.abs(dFdx[0]), Math.abs(dFdy[0]));
+ /** @type {number} */ var mv = Math.max(Math.abs(dFdx[1]), Math.abs(dFdy[1]));
+ /** @type {number} */ var p = Math.max(mu * texWidth, mv * texHeight);
+
+ /** @type {number} */ var lod = Math.log2(p) + lodBias;
+
+ output.push(this.sample([packetTexcoords[fragNdx][0], packetTexcoords[fragNdx][1]], lod));
+ }
+
+ return output;
+ };
+
+ /**
+ * @constructor
+ * @extends {sglrReferenceContext.Texture}
+ */
+ sglrReferenceContext.TextureCube = function() {
+ sglrReferenceContext.Texture.call(this, sglrReferenceContext.TextureType.TYPE_CUBE_MAP);
+ /** @type {tcuTexture.TextureCubeView} */ this.m_view = new tcuTexture.TextureCubeView(0, null);
+ /** @type {Array<sglrReferenceContext.TextureLevelArray>} */ this.m_levels = [];
+ for (var face in tcuTexture.CubeFace)
+ this.m_levels[tcuTexture.CubeFace[face]] = new sglrReferenceContext.TextureLevelArray();
+ };
+
+ /**
+ */
+ sglrReferenceContext.TextureCube.prototype = Object.create(sglrReferenceContext.Texture.prototype);
+ sglrReferenceContext.TextureCube.prototype.constructor = sglrReferenceContext.Texture2D;
+
+ sglrReferenceContext.TextureCube.prototype.clearLevels = function() {
+ for (var face in tcuTexture.CubeFace)
+ this.m_levels[tcuTexture.CubeFace[face]].clear();
+ };
+
+ /**
+ * @param {number} level
+ * @param {tcuTexture.CubeFace} face
+ * @return {boolean}
+ */
+ sglrReferenceContext.TextureCube.prototype.hasFace = function(level, face) { return this.m_levels[face].hasLevel(level); };
+
+ /**
+ * @param {number} level
+ * @param {tcuTexture.CubeFace} face
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.TextureCube.prototype.getFace = function(level, face) { return this.m_levels[face].getLevel(level); };
+
+ /**
+ * @param {number} level
+ * @param {tcuTexture.CubeFace} face
+ * @param {?tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.TextureCube.prototype.allocLevel = function(level, face, format, width, height) {
+ this.m_levels[face].allocLevel(level, format, width, height, 1);
+ };
+
+ sglrReferenceContext.TextureCube.prototype.isComplete = function() {
+ var baseLevel = this.getBaseLevel();
+
+ if (this.hasFace(baseLevel, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X)) {
+ var level = this.getFace(baseLevel, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X);
+ var width = level.getWidth();
+ var height = level.getHeight();
+ var format = level.getFormat();
+ var mipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+ var numLevels = mipmap ? Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels2D(width, height)) : 1;
+
+ if (width != height)
+ return false; // Non-square is not supported.
+
+ // \note Level 0 is always checked for consistency
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ var levelW = sglrReferenceContext.getMipLevelSize(width, levelNdx);
+ var levelH = sglrReferenceContext.getMipLevelSize(height, levelNdx);
+
+ for (var face in tcuTexture.CubeFace) {
+ if (this.hasFace(baseLevel + levelNdx, tcuTexture.CubeFace[face])) {
+ level = this.getFace(baseLevel + levelNdx, tcuTexture.CubeFace[face]);
+
+ if (level.getWidth() != levelW ||
+ level.getHeight() != levelH ||
+ !level.getFormat().isEqual(format))
+ return false;
+ } else
+ return false;
+ }
+ }
+
+ return true;
+ } else
+ return false;
+ };
+
+ sglrReferenceContext.TextureCube.prototype.updateView = function() {
+
+ var baseLevel = this.getBaseLevel();
+ var faces = [];
+
+ if (this.isComplete()) {
+ var size = this.getFace(baseLevel, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getWidth();
+ var isMipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+ var numLevels = isMipmap ? Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels1D(size)) : 1;
+
+ for (var face in tcuTexture.CubeFace)
+ faces[tcuTexture.CubeFace[face]] = this.m_levels[tcuTexture.CubeFace[face]].getLevels().slice(baseLevel);
+
+ this.m_view = new tcuTexture.TextureCubeView(numLevels, faces);
+ } else
+ this.m_view = new tcuTexture.TextureCubeView(0, null);
+ };
+
+ /**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+ sglrReferenceContext.TextureCube.prototype.sample = function(pos, lod) { return this.m_view.sample(this.getSampler(), pos, lod) };
+
+ /**
+ * @constructor
+ * @extends {sglrReferenceContext.Texture}
+ */
+ sglrReferenceContext.Texture2DArray = function() {
+ sglrReferenceContext.Texture.call(this, sglrReferenceContext.TextureType.TYPE_2D_ARRAY);
+ /** @type {tcuTexture.Texture2DArrayView} */ this.m_view = new tcuTexture.Texture2DArrayView(0, null);
+ /** @type {sglrReferenceContext.TextureLevelArray} */ this.m_levels = new sglrReferenceContext.TextureLevelArray();
+ };
+
+ /**
+ */
+ sglrReferenceContext.Texture2DArray.prototype = Object.create(sglrReferenceContext.Texture.prototype);
+ sglrReferenceContext.Texture2DArray.prototype.constructor = sglrReferenceContext.Texture2DArray;
+
+ sglrReferenceContext.Texture2DArray.prototype.clearLevels = function() { this.m_levels.clear(); };
+
+ /**
+ * @param {number} level
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture2DArray.prototype.hasLevel = function(level) { return this.m_levels.hasLevel(level); };
+
+ /**
+ * @param {number} level
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.Texture2DArray.prototype.getLevel = function(level) { return this.m_levels.getLevel(level); };
+
+ /**
+ * @param {number} level
+ * @param {?tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ */
+ sglrReferenceContext.Texture2DArray.prototype.allocLevel = function(level, format, width, height, numLayers) {
+ this.m_levels.allocLevel(level, format, width, height, numLayers);
+ };
+
+ /**
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture2DArray.prototype.isComplete = function() {
+ /** @type {number} */ var baseLevel = this.getBaseLevel();
+
+ if (this.hasLevel(baseLevel)) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level0 = this.getLevel(baseLevel);
+ /** @type {boolean} */ var mipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+
+ if (mipmap) {
+ /** @type {tcuTexture.TextureFormat} */ var format = level0.getFormat();
+ /** @type {number} */ var w = level0.getWidth();
+ /** @type {number} */ var h = level0.getHeight();
+ /** @type {number} */ var numLayers = level0.getDepth();
+ /** @type {number} */ var numLevels = Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels2D(w, h));
+
+ for (var levelNdx = 1; levelNdx < numLevels; levelNdx++) {
+ if (this.hasLevel(baseLevel + levelNdx)) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level = this.getLevel(baseLevel + levelNdx);
+ /** @type {number} */ var expectedW = sglrReferenceContext.getMipLevelSize(w, levelNdx);
+ /** @type {number} */ var expectedH = sglrReferenceContext.getMipLevelSize(h, levelNdx);
+
+ if (level.getWidth() != expectedW ||
+ level.getHeight() != expectedH ||
+ level.getDepth() != numLayers ||
+ !level.getFormat().isEqual(format))
+ return false;
+ } else
+ return false;
+ }
+ }
+
+ return true;
+ } else
+ return false;
+ };
+
+ /**
+ */
+ sglrReferenceContext.Texture2DArray.prototype.updateView = function() {
+ /** @type {number} */ var baseLevel = this.getBaseLevel();
+
+ if (this.hasLevel(baseLevel) && !this.getLevel(baseLevel).isEmpty()) {
+ // Update number of levels in mipmap pyramid.
+ /** @type {number} */ var width = this.getLevel(baseLevel).getWidth();
+ /** @type {number} */ var height = this.getLevel(baseLevel).getHeight();
+ /** @type {boolean} */ var isMipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+ /** @type {number} */ var numLevels = isMipmap ? Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels2D(width, height)) : 1;
+
+ this.m_view = new tcuTexture.Texture2DArrayView(numLevels, this.m_levels.getLevels().slice(baseLevel));
+ } else
+ this.m_view = new tcuTexture.Texture2DArrayView(0, null);
+ };
+
+ /**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+ sglrReferenceContext.Texture2DArray.prototype.sample = function(pos, lod) {
+ return this.m_view.sample(this.getSampler(), pos, lod);
+ };
+
+ /**
+ * @constructor
+ * @extends {sglrReferenceContext.Texture}
+ */
+ sglrReferenceContext.Texture3D = function() {
+ sglrReferenceContext.Texture.call(this, sglrReferenceContext.TextureType.TYPE_2D_ARRAY);
+ /** @type {tcuTexture.Texture3DView} */ this.m_view = new tcuTexture.Texture3DView(0, null);
+ /** @type {sglrReferenceContext.TextureLevelArray} */ this.m_levels = new sglrReferenceContext.TextureLevelArray();
+ };
+
+ /**
+ */
+ sglrReferenceContext.Texture3D.prototype = Object.create(sglrReferenceContext.Texture.prototype);
+ sglrReferenceContext.Texture3D.prototype.constructor = sglrReferenceContext.Texture3D;
+
+ sglrReferenceContext.Texture3D.prototype.clearLevels = function() { this.m_levels.clear(); };
+
+ /**
+ * @param {number} level
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture3D.prototype.hasLevel = function(level) { return this.m_levels.hasLevel(level); };
+
+ /**
+ * @param {number} level
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.Texture3D.prototype.getLevel = function(level) { return this.m_levels.getLevel(level); };
+
+ /**
+ * @param {number} level
+ * @param {?tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+ sglrReferenceContext.Texture3D.prototype.allocLevel = function(level, format, width, height, depth) {
+ this.m_levels.allocLevel(level, format, width, height, depth);
+ };
+
+ /**
+ * @return {boolean}
+ */
+ sglrReferenceContext.Texture3D.prototype.isComplete = function() {
+ /** @type {number} */ var baseLevel = this.getBaseLevel();
+
+ if (this.hasLevel(baseLevel)) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level0 = this.getLevel(baseLevel);
+ /** @type {boolean} */ var mipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+
+ if (mipmap) {
+ /** @type {tcuTexture.TextureFormat} */ var format = level0.getFormat();
+ /** @type {number} */ var w = level0.getWidth();
+ /** @type {number} */ var h = level0.getHeight();
+ /** @type {number} */ var d = level0.getDepth();
+ /** @type {number} */ var numLevels = Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels3D(w, h, d));
+
+ for (var levelNdx = 1; levelNdx < numLevels; levelNdx++) {
+ if (this.hasLevel(baseLevel + levelNdx)) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level = this.getLevel(baseLevel + levelNdx);
+ /** @type {number} */ var expectedW = sglrReferenceContext.getMipLevelSize(w, levelNdx);
+ /** @type {number} */ var expectedH = sglrReferenceContext.getMipLevelSize(h, levelNdx);
+ /** @type {number} */ var expectedD = sglrReferenceContext.getMipLevelSize(d, levelNdx);
+
+ if (level.getWidth() != expectedW ||
+ level.getHeight() != expectedH ||
+ level.getDepth() != expectedD ||
+ !level.getFormat().isEqual(format))
+ return false;
+ } else
+ return false;
+ }
+ }
+
+ return true;
+ } else
+ return false;
+ };
+
+ /**
+ */
+ sglrReferenceContext.Texture3D.prototype.updateView = function() {
+ /** @type {number} */ var baseLevel = this.getBaseLevel();
+
+ if (this.hasLevel(baseLevel) && !this.getLevel(baseLevel).isEmpty()) {
+ // Update number of levels in mipmap pyramid.
+ /** @type {number} */ var width = this.getLevel(baseLevel).getWidth();
+ /** @type {number} */ var height = this.getLevel(baseLevel).getHeight();
+ /** @type {boolean} */ var isMipmap = sglrReferenceContext.isMipmapFilter(this.getSampler().minFilter);
+ /** @type {number} */ var numLevels = isMipmap ? Math.min(this.getMaxLevel() - baseLevel + 1, sglrReferenceContext.getNumMipLevels2D(width, height)) : 1;
+
+ this.m_view = new tcuTexture.Texture3DView(numLevels, this.m_levels.getLevels().slice(baseLevel));
+ } else
+ this.m_view = new tcuTexture.Texture3DView(0, null);
+ };
+
+ /**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+ sglrReferenceContext.Texture3D.prototype.sample = function(pos, lod) { return this.m_view.sample(this.getSampler(), pos, lod) };
+
+ /**
+ * A container object for storing one of texture types;
+ * @constructor
+ */
+ sglrReferenceContext.TextureContainer = function() {
+ /** @type {sglrReferenceContext.Texture2D | sglrReferenceContext.TextureCube|sglrReferenceContext.Texture2DArray|sglrReferenceContext.Texture3D} */
+ this.texture = null;
+ /** @type {?sglrReferenceContext.TextureType} */ this.textureType = null;
+ };
+
+ /**
+ * @return {?sglrReferenceContext.TextureType}
+ */
+ sglrReferenceContext.TextureContainer.prototype.getType = function() { return this.textureType; };
+
+ /**
+ * @param {number} target
+ * @throws {Error}
+ */
+ sglrReferenceContext.TextureContainer.prototype.init = function(target) {
+ switch (target) {
+ case gl.TEXTURE_2D:
+ this.texture = new sglrReferenceContext.Texture2D();
+ this.textureType = sglrReferenceContext.TextureType.TYPE_2D;
+ break;
+ case gl.TEXTURE_CUBE_MAP:
+ this.texture = new sglrReferenceContext.TextureCube();
+ this.textureType = sglrReferenceContext.TextureType.TYPE_CUBE_MAP;
+ break;
+ case gl.TEXTURE_2D_ARRAY:
+ this.texture = new sglrReferenceContext.Texture2DArray();
+ this.textureType = sglrReferenceContext.TextureType.TYPE_2D_ARRAY;
+ break;
+ case gl.TEXTURE_3D:
+ this.texture = new sglrReferenceContext.Texture3D();
+ this.textureType = sglrReferenceContext.TextureType.TYPE_3D;
+ break;
+ /* TODO: Implement other types */
+ // case gl.TEXTURE_CUBE_MAP_ARRAY:
+ // this.textureType = sglrReferenceContext.TextureType.TYPE_CUBE_MAP_ARRAY;
+ // break;
+ default: throw new Error('Unrecognized target: ' + target);
+ }
+ };
+
+ /**
+ * @enum
+ */
+ sglrReferenceContext.AttachmentPoint = {
+ ATTACHMENTPOINT_COLOR0: 0,
+ ATTACHMENTPOINT_DEPTH: 1,
+ ATTACHMENTPOINT_STENCIL: 2
+ };
+
+ /**
+ * @param {number} attachment
+ * @return {sglrReferenceContext.AttachmentPoint}
+ * @throws {Error}
+ */
+ sglrReferenceContext.mapGLAttachmentPoint = function(attachment) {
+ switch (attachment) {
+ case gl.COLOR_ATTACHMENT0: return sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_COLOR0;
+ case gl.DEPTH_ATTACHMENT: return sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_DEPTH;
+ case gl.STENCIL_ATTACHMENT: return sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_STENCIL;
+ default: throw new Error('Wrong attachment point:' + attachment);
+ }
+ };
+
+ /**
+ * @enum
+ */
+ sglrReferenceContext.AttachmentType = {
+ ATTACHMENTTYPE_RENDERBUFFER: 0,
+ ATTACHMENTTYPE_TEXTURE: 1
+ };
+
+ /**
+ * @enum
+ */
+ sglrReferenceContext.TexTarget = {
+ TEXTARGET_2D: 0,
+ TEXTARGET_CUBE_MAP_POSITIVE_X: 1,
+ TEXTARGET_CUBE_MAP_POSITIVE_Y: 2,
+ TEXTARGET_CUBE_MAP_POSITIVE_Z: 3,
+ TEXTARGET_CUBE_MAP_NEGATIVE_X: 4,
+ TEXTARGET_CUBE_MAP_NEGATIVE_Y: 5,
+ TEXTARGET_CUBE_MAP_NEGATIVE_Z: 6,
+ TEXTARGET_2D_ARRAY: 7,
+ TEXTARGET_3D: 8,
+ TEXTARGET_CUBE_MAP_ARRAY: 9
+ };
+
+ /**
+ * @param {?sglrReferenceContext.TexTarget} target
+ * @return {tcuTexture.CubeFace}
+ */
+ sglrReferenceContext.texTargetToFace = function(target) {
+ switch (target) {
+ case sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_X: return tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X;
+ case sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_X: return tcuTexture.CubeFace.CUBEFACE_POSITIVE_X;
+ case sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_Y: return tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y;
+ case sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_Y: return tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y;
+ case sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_Z: return tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z;
+ case sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_Z: return tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z;
+ default: throw new Error('Invalid target ' + target);
+ }
+ };
+
+ /**
+ * @param {sglrReferenceContext.TexTarget} target
+ * @return {sglrReferenceContext.TexTarget}
+ * @throws {Error}
+ */
+ sglrReferenceContext.mapGLFboTexTarget = function(target) {
+ switch (target) {
+ case gl.TEXTURE_2D: return sglrReferenceContext.TexTarget.TEXTARGET_2D;
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_X: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_X;
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_Y: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_Y;
+ case gl.TEXTURE_CUBE_MAP_POSITIVE_Z: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_Z;
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_X: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_X;
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_Y;
+ case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: return sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_Z;
+ default: throw new Error('Wrong texture target:' + target);
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.Attachment = function() {
+ /** @type {?sglrReferenceContext.AttachmentType} */ this.type = null;
+ /** @type {sglrReferenceContext.TextureContainer|sglrReferenceContext.Renderbuffer} */ this.object = null; // TODO: fix reserved word
+ /** @type {?sglrReferenceContext.TexTarget} */ this.texTarget = null;
+ /** @type {number} */ this.level = 0;
+ /** @type {number} */ this.layer = 0;
+ };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.Framebuffer = function() {
+ /** @type {Array<sglrReferenceContext.Attachment>} */ this.m_attachments = [];
+ for (var key in sglrReferenceContext.AttachmentPoint)
+ this.m_attachments[sglrReferenceContext.AttachmentPoint[key]] = new sglrReferenceContext.Attachment();
+ };
+
+ /**
+ * @param {sglrReferenceContext.AttachmentPoint} point
+ * @return {sglrReferenceContext.Attachment}
+ */
+ sglrReferenceContext.Framebuffer.prototype.getAttachment = function(point) { return this.m_attachments[point]; };
+
+ /**
+ * @param {sglrReferenceContext.AttachmentPoint} point
+ * @param {sglrReferenceContext.Attachment} attachment
+ */
+ sglrReferenceContext.Framebuffer.prototype.setAttachment = function(point, attachment) { this.m_attachments[point] = attachment; };
+
+ // /**
+ // * @enum
+ // */
+ // var Format = {
+ // FORMAT_DEPTH_COMPONENT16: 0,
+ // FORMAT_RGBA4: 1,
+ // FORMAT_RGB5_A1: 2,
+ // FORMAT_RGB565: 3,
+ // FORMAT_STENCIL_INDEX8: 4
+ // };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.Renderbuffer = function() {
+ /** @type {tcuTexture.TextureLevel} */ this.m_data;
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.Renderbuffer.prototype.setStorage = function(format, width, height) {
+ this.m_data = new tcuTexture.TextureLevel(format, width, height);
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.Renderbuffer.prototype.getWidth = function() { return this.m_data.getWidth(); };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.Renderbuffer.prototype.getHeight = function() { return this.m_data.getHeight(); };
+
+ /**
+ * @return {?tcuTexture.TextureFormat}
+ */
+ sglrReferenceContext.Renderbuffer.prototype.getFormat = function() { return this.m_data.getFormat(); };
+
+ /**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.Renderbuffer.prototype.getAccess = function() { return this.m_data.getAccess(); };
+
+ /**
+ * @constructor
+ * @param {number} maxVertexAttribs
+ */
+ sglrReferenceContext.VertexArray = function(maxVertexAttribs) {
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_elementArrayBufferBinding = null;
+
+ /** @type {Array<sglrReferenceContext.VertexArray.VertexAttribArray>} */this.m_arrays = [];
+ for (var i = 0; i < maxVertexAttribs; i++)
+ this.m_arrays.push(new sglrReferenceContext.VertexArray.VertexAttribArray());
+ };
+
+ /** @constructor */
+ sglrReferenceContext.VertexArray.VertexAttribArray = function() {
+ this.enabled = false;
+ this.size = 4;
+ this.stride = 0;
+ this.type = gl.FLOAT;
+
+ this.normalized = false;
+ this.integer = false;
+ this.divisor = 0;
+ this.offset = 0;
+ this.bufferBinding = null;
+ };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.DataBuffer = function() {
+ /** @type {?ArrayBuffer} */ this.m_data = null;
+ };
+
+ /**
+ * @param {number} size
+ */
+ sglrReferenceContext.DataBuffer.prototype.setStorage = function(size) {this.m_data = new ArrayBuffer(size); };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.DataBuffer.prototype.getSize = function() {
+ /** @type {number} */ var size = 0;
+ if (this.m_data)
+ size = this.m_data.byteLength;
+ return size;
+ };
+
+ /**
+ * @return {?ArrayBuffer}
+ */
+ sglrReferenceContext.DataBuffer.prototype.getData = function() { return this.m_data; };
+
+ /**
+ * @param {ArrayBuffer|goog.NumberArray} data
+ */
+ sglrReferenceContext.DataBuffer.prototype.setData = function(data) {
+ /** @type {ArrayBuffer} */ var buffer;
+ /** @type {number} */ var offset = 0;
+ /** @type {number} */ var byteLength = data.byteLength;
+ if (data instanceof ArrayBuffer)
+ buffer = data;
+ else {
+ buffer = data.buffer;
+ offset = data.byteOffset;
+ }
+
+ if (!buffer)
+ throw new Error('Invalid buffer');
+
+ this.m_data = buffer.slice(offset, offset + byteLength);
+ };
+
+ /**
+ * @param {number} offset
+ * @param {goog.NumberArray} data
+ */
+ sglrReferenceContext.DataBuffer.prototype.setSubData = function(offset, data) {
+ /** @type {ArrayBuffer} */ var buffer;
+ /** @type {number} */ var srcOffset = 0;
+ /** @type {number} */ var byteLength = data.byteLength;
+ if (data instanceof ArrayBuffer)
+ buffer = data;
+ else {
+ buffer = data.buffer;
+ srcOffset = data.byteOffset;
+ }
+
+ if (!buffer)
+ throw new Error('Invalid buffer');
+
+ /** @type {goog.NumberArray} */ var src = new Uint8Array(buffer, srcOffset, byteLength);
+ /** @type {goog.NumberArray} */ var dst = new Uint8Array(this.m_data, offset, byteLength);
+ dst.set(src);
+ };
+
+ // /**
+ // * @constructor
+ // */
+ // var ObjectManager = function() {
+ // this.m_objects = {};
+ // };
+
+ // ObjectManager.prototype.insert = function(obj) {
+ // var name = obj.getName();
+ // if (!name)
+ // throw new Error("Cannot insert unnamed object");
+ // this.m_objects[name] = obj;
+ // };
+
+ // ObjectManager.prototype.find = function(name) { return this.m_objects[name]; };
+
+ // ObjectManager.prototype.acquireReference = function(obj) {
+ // if (this.find(obj.getName()) !== obj)
+ // throw new Error("Object is not in the object manager");
+ // obj.incRefCount();
+ // };
+
+ // ObjectManager.prototype.releaseReference = function(obj) {
+ // if (this.find(obj.getName()) !== obj)
+ // throw new Error("Object is not in the object manager");
+
+ // obj.decRefCount();
+
+ // if (obj.getRefCount() == 0)
+ // delete this.m_objects[obj.getName()];
+ // };
+
+ // ObjectManager.prototype.getAll = function() { return this.m_objects; };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.TextureUnit = function() {
+ /** @type {?sglrReferenceContext.TextureContainer} */ this.tex2DBinding = null;
+ /** @type {?sglrReferenceContext.TextureContainer} */ this.texCubeBinding = null;
+ /** @type {?sglrReferenceContext.TextureContainer} */ this.tex2DArrayBinding = null;
+ /** @type {?sglrReferenceContext.TextureContainer} */ this.tex3DBinding = null;
+ /** @type {?sglrReferenceContext.TextureContainer} */ this.texCubeArrayBinding = null;
+ };
+
+ /**
+ * @constructor
+ */
+ sglrReferenceContext.StencilState = function() {
+ /** @type {number} */ this.func = gl.ALWAYS;
+ /** @type {number} */ this.ref = 0;
+ /** @type {number} */ this.opMask = ~0;
+ /** @type {number} */ this.opStencilFail = gl.KEEP;
+ /** @type {number} */ this.opDepthFail = gl.KEEP;
+ /** @type {number} */ this.opDepthPass = gl.KEEP;
+ /** @type {number} */ this.writeMask = ~0;
+ };
+
+ /**
+ * @param {tcuPixelFormat.PixelFormat} pixelFmt
+ * @return {tcuTexture.TextureFormat}
+ * @throws {Error}
+ */
+ sglrReferenceContext.toTextureFormat = function(pixelFmt) {
+ if (pixelFmt.equals(8, 8, 8, 8))
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+ else if (pixelFmt.equals(8, 8, 8, 0))
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
+ else if (pixelFmt.equals(4, 4, 4, 4))
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_4444);
+ else if (pixelFmt.equals(5, 5, 5, 1))
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_5551);
+ else if (pixelFmt.equals(5, 6, 5, 0))
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_SHORT_565);
+
+ throw new Error('Could not map pixel format:' + pixelFmt);
+ };
+
+ /**
+ * @param {number} depthBits
+ * @return {tcuTexture.TextureFormat}
+ * @throws {Error}
+ */
+ sglrReferenceContext.getDepthFormat = function(depthBits) {
+ switch (depthBits) {
+ case 8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNORM_INT8);
+ case 16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNORM_INT16);
+ case 24: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.UNSIGNED_INT_24_8);
+ case 32: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.D, tcuTexture.ChannelType.FLOAT);
+ default:
+ throw new Error("Can't map depth buffer format, bits: " + depthBits);
+ }
+ };
+
+ /**
+ * @param {number} stencilBits
+ * @return {tcuTexture.TextureFormat}
+ * @throws {Error}
+ */
+ sglrReferenceContext.getStencilFormat = function(stencilBits) {
+ switch (stencilBits) {
+ case 8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.S, tcuTexture.ChannelType.UNSIGNED_INT8);
+ case 16: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.S, tcuTexture.ChannelType.UNSIGNED_INT16);
+ case 24: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.S, tcuTexture.ChannelType.UNSIGNED_INT_24_8);
+ case 32: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.S, tcuTexture.ChannelType.UNSIGNED_INT32);
+ default:
+ throw new Error("Can't map stencil buffer format, bits: " + stencilBits);
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {tcuPixelFormat.PixelFormat} colorBits
+ * @param {number} depthBits
+ * @param {number} stencilBits
+ * @param {number} width
+ * @param {number} height
+ * @param {number=} samples_
+ */
+ sglrReferenceContext.ReferenceContextBuffers = function(colorBits, depthBits, stencilBits, width, height, samples_) {
+ if (samples_ === undefined)
+ samples_ = 1;
+
+ /** @type {number} */ var samples = samples_;
+ /** @type {tcuTexture.TextureLevel} */ this.m_colorbuffer = new tcuTexture.TextureLevel(sglrReferenceContext.toTextureFormat(colorBits), samples, width, height);
+
+ if (depthBits > 0)
+ /** @type {tcuTexture.TextureLevel} */ this.m_depthbuffer = new tcuTexture.TextureLevel(sglrReferenceContext.getDepthFormat(depthBits), samples, width, height);
+
+ if (stencilBits > 0)
+ /** @type {tcuTexture.TextureLevel} */ this.m_stencilbuffer = new tcuTexture.TextureLevel(sglrReferenceContext.getStencilFormat(stencilBits), samples, width, height);
+ };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContextBuffers.prototype.getColorbuffer = function() { return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess(this.m_colorbuffer.getAccess()); };
+
+ /**
+ * @return {?rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContextBuffers.prototype.getDepthbuffer = function() { return this.m_depthbuffer !== undefined ? rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess(this.m_depthbuffer.getAccess()) : null; };
+
+ /**
+ * @return {?rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContextBuffers.prototype.getStencilbuffer = function() { return this.m_stencilbuffer !== undefined ? rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess(this.m_stencilbuffer.getAccess()) : null; };
+
+ /**
+ * @param {sglrReferenceContext.ReferenceContextLimits} limits
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} colorbuffer
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} depthbuffer
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} stencilbuffer
+ * @constructor
+ */
+ sglrReferenceContext.ReferenceContext = function(limits, colorbuffer, depthbuffer, stencilbuffer) {
+ /** @type {sglrReferenceContext.ReferenceContextLimits} */ this.m_limits = limits;
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ this.m_defaultColorbuffer = colorbuffer;
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ this.m_defaultDepthbuffer = depthbuffer;
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ this.m_defaultStencilbuffer = stencilbuffer;
+ /** @type {Array<number>} */ this.m_viewport = [0, 0, colorbuffer.raw().getHeight(), colorbuffer.raw().getDepth()];
+ /** @type {Array<sglrReferenceContext.TextureUnit>} */ this.m_textureUnits = [];
+ for (var i = 0; i < this.m_limits.maxTextureImageUnits; i++)
+ this.m_textureUnits.push(new sglrReferenceContext.TextureUnit());
+ /** @type {number} */ this.m_activeTexture = 0;
+ /** @type {number} */ this.m_lastError = gl.NO_ERROR;
+ // this.m_textures = new ObjectManager();
+ /** @type {number} */ this.m_pixelUnpackRowLength = 0;
+ /** @type {number} */ this.m_pixelUnpackSkipRows = 0;
+ /** @type {number} */ this.m_pixelUnpackSkipPixels = 0;
+ /** @type {number} */ this.m_pixelUnpackImageHeight = 0;
+ /** @type {number} */ this.m_pixelUnpackSkipImages = 0;
+ /** @type {number} */ this.m_pixelUnpackAlignment = 4;
+ /** @type {number} */ this.m_pixelPackAlignment = 4;
+ /** @type {Array<number>} */ this.m_clearColor = [0, 0, 0, 0];
+ /** @type {number} */ this.m_clearDepth = 1;
+ /** @type {number} */ this.m_clearStencil = 0;
+ /** @type {Array<number>} */ this.m_scissorBox = this.m_viewport;
+ /** @type {boolean} */ this.m_blendEnabled = false;
+ /** @type {boolean} */ this.m_scissorEnabled = false;
+ /** @type {boolean} */ this.m_depthTestEnabled = false;
+ /** @type {boolean} */ this.m_stencilTestEnabled = false;
+ /** @type {boolean} */ this.m_polygonOffsetFillEnabled = false;
+ /** @type {boolean} */ this.m_primitiveRestartFixedIndex = true; //always on
+ /** @type {boolean} */ this.m_primitiveRestartSettableIndex = true; //always on
+ /** @type {Array<sglrReferenceContext.StencilState>} */ this.m_stencil = [];
+ for (var type in rrDefs.FaceType)
+ this.m_stencil[rrDefs.FaceType[type]] = new sglrReferenceContext.StencilState();
+ /** @type {number} */ this.m_depthFunc = gl.LESS;
+ /** @type {number} */ this.m_depthRangeNear = 0;
+ /** @type {number} */ this.m_depthRangeFar = 1;
+ /** @type {number} */ this.m_polygonOffsetFactor = 0;
+ /** @type {number} */ this.m_polygonOffsetUnits = 0;
+ /** @type {number} */ this.m_blendModeRGB = gl.FUNC_ADD;
+ /** @type {number} */ this.m_blendModeAlpha = gl.FUNC_ADD;
+ /** @type {number} */ this.m_blendFactorSrcRGB = gl.ONE;
+ /** @type {number} */ this.m_blendFactorDstRGB = gl.ZERO;
+ /** @type {number} */ this.m_blendFactorSrcAlpha = gl.ONE;
+ /** @type {number} */ this.m_blendFactorDstAlpha = gl.ZERO;
+ /** @type {Array<number>} */ this.m_blendColor = [0, 0, 0, 0];
+ /** @type {boolean} */ this.m_sRGBUpdateEnabled = true;
+ /** @type {Array<boolean>} */ this.m_colorMask = [true, true, true, true];
+ /** @type {boolean} */ this.m_depthMask = true;
+ /** @type {sglrReferenceContext.VertexArray} */ this.m_defaultVAO = new sglrReferenceContext.VertexArray(this.m_limits.maxVertexAttribs);
+ /** @type {sglrReferenceContext.VertexArray} */ this.m_vertexArrayBinding = this.m_defaultVAO;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_arrayBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_copyReadBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_copyWriteBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_drawIndirectBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_pixelPackBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_pixelUnpackBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_transformFeedbackBufferBinding = null;
+ /** @type {sglrReferenceContext.DataBuffer} */ this.m_uniformBufferBinding = null;
+ /** @type {sglrReferenceContext.Framebuffer} */ this.m_readFramebufferBinding = null;
+ /** @type {sglrReferenceContext.Framebuffer} */ this.m_drawFramebufferBinding = null;
+ /** @type {sglrReferenceContext.Renderbuffer} */ this.m_renderbufferBinding = null;
+ /** @type {sglrShaderProgram.ShaderProgram} */ this.m_currentProgram = null;
+ /** @type {Array<rrGenericVector.GenericVec4>} */ this.m_currentAttribs = [];
+ for (var i = 0; i < this.m_limits.maxVertexAttribs; i++)
+ this.m_currentAttribs.push(new rrGenericVector.GenericVec4());
+ /** @type {number} */ this.m_lineWidth = 1;
+
+ /** @type {sglrReferenceContext.TextureContainer} */ this.m_emptyTex2D = new sglrReferenceContext.TextureContainer();
+ this.m_emptyTex2D.init(gl.TEXTURE_2D);
+ this.m_emptyTex2D.texture.getSampler().wrapS = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex2D.texture.getSampler().wrapT = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex2D.texture.getSampler().minFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTex2D.texture.getSampler().magFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTex2D.texture.allocLevel(0, new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), 1, 1);
+ this.m_emptyTex2D.texture.getLevel(0).setPixel([0, 0, 0, 1], 0, 0);
+ this.m_emptyTex2D.texture.updateView();
+
+ /** @type {sglrReferenceContext.TextureContainer} */ this.m_emptyTexCube = new sglrReferenceContext.TextureContainer();
+ this.m_emptyTexCube.init(gl.TEXTURE_CUBE_MAP);
+ this.m_emptyTexCube.texture.getSampler().wrapS = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTexCube.texture.getSampler().wrapT = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTexCube.texture.getSampler().minFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTexCube.texture.getSampler().magFilter = tcuTexture.FilterMode.NEAREST;
+
+ for (var face in tcuTexture.CubeFace) {
+ this.m_emptyTexCube.texture.allocLevel(0, tcuTexture.CubeFace[face],
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), 1, 1);
+ this.m_emptyTexCube.texture.getFace(0, tcuTexture.CubeFace[face]).setPixel([0, 0, 0, 1], 0, 0);
+ }
+ this.m_emptyTexCube.texture.updateView();
+
+ /** @type {sglrReferenceContext.TextureContainer} */ this.m_emptyTex2DArray = new sglrReferenceContext.TextureContainer();
+ this.m_emptyTex2DArray.init(gl.TEXTURE_2D_ARRAY);
+ this.m_emptyTex2DArray.texture.getSampler().wrapS = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex2DArray.texture.getSampler().wrapT = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex2DArray.texture.getSampler().wrapR = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex2DArray.texture.getSampler().minFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTex2DArray.texture.getSampler().magFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTex2DArray.texture.allocLevel(0, new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), 1, 1);
+ this.m_emptyTex2DArray.texture.getLevel(0).setPixel([0, 0, 0, 1], 0, 0);
+ this.m_emptyTex2DArray.texture.updateView();
+
+ /** @type {sglrReferenceContext.TextureContainer} */ this.m_emptyTex3D = new sglrReferenceContext.TextureContainer();
+ this.m_emptyTex3D.init(gl.TEXTURE_3D);
+ this.m_emptyTex3D.texture.getSampler().wrapS = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex3D.texture.getSampler().wrapT = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex3D.texture.getSampler().wrapR = tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ this.m_emptyTex3D.texture.getSampler().minFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTex3D.texture.getSampler().magFilter = tcuTexture.FilterMode.NEAREST;
+ this.m_emptyTex3D.texture.allocLevel(0, new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), 1, 1);
+ this.m_emptyTex3D.texture.getLevel(0).setPixel([0, 0, 0, 1], 0, 0);
+ this.m_emptyTex3D.texture.updateView();
+
+ /** @type {sglrReferenceContext.TextureType} */ this.m_type;
+
+ /** @type {boolean} */ this.m_immutable;
+
+ /** @type {tcuTexture.Sampler} */ this.m_sampler;
+ /** @type {number} */ this.m_baseLevel;
+ /** @type {number} */ this.m_maxLevel;
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getWidth = function() { return this.m_defaultColorbuffer.raw().getHeight(); };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getHeight = function() { return this.m_defaultColorbuffer.raw().getDepth(); };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.ReferenceContext.prototype.viewport = function(x, y, width, height) { this.m_viewport = [x, y, width, height]; };
+
+ /**
+ * @param {number} texture
+ */
+ sglrReferenceContext.ReferenceContext.prototype.activeTexture = function(texture) {
+ if (deMath.deInBounds32(texture, gl.TEXTURE0, gl.TEXTURE0 + this.m_textureUnits.length))
+ this.m_activeTexture = texture - gl.TEXTURE0;
+ else
+ this.setError(gl.INVALID_ENUM);
+ };
+
+ /**
+ * @param {number} error
+ */
+ sglrReferenceContext.ReferenceContext.prototype.setError = function(error) {
+ if (this.m_lastError == gl.NO_ERROR)
+ this.m_lastError = error;
+ };
+
+ /**
+ * @return {number} error
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getError = function() {
+ /** @type {number} */ var err = this.m_lastError;
+ this.m_lastError = gl.NO_ERROR;
+ return err;
+ };
+
+ /**
+ * @param {boolean} condition
+ * @param {number} error
+ */
+ sglrReferenceContext.ReferenceContext.prototype.conditionalSetError = function(condition, error) {
+ if (condition)
+ this.setError(error);
+ return condition;
+ };
+
+ /**
+ * @param {number} target
+ * @param {sglrReferenceContext.TextureContainer} texture
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bindTexture = function(target, texture) {
+ /** @type {number} */ var unitNdx = this.m_activeTexture;
+
+ if (this.conditionalSetError((target != gl.TEXTURE_2D &&
+ target != gl.TEXTURE_CUBE_MAP &&
+ target != gl.TEXTURE_2D_ARRAY &&
+ target != gl.TEXTURE_3D), // &&
+ // target != gl.TEXTURE_CUBE_MAP_ARRAY),
+ gl.INVALID_ENUM))
+ return;
+
+ if (!texture) {
+ // Clear binding.
+ switch (target) {
+ case gl.TEXTURE_2D: this.setTex2DBinding(unitNdx, null); break;
+ case gl.TEXTURE_CUBE_MAP: this.setTexCubeBinding(unitNdx, null); break;
+ case gl.TEXTURE_2D_ARRAY: this.setTex2DArrayBinding(unitNdx, null); break;
+ case gl.TEXTURE_3D: this.setTex3DBinding(unitNdx, null); break;
+ default:
+ throw new Error('Unrecognized target: ' + target);
+ }
+ } else {
+ if (texture.textureType == null) {
+ texture.init(target);
+ } else {
+ // Validate type.
+ /** @type {sglrReferenceContext.TextureType} */ var expectedType;
+ switch (target) {
+ case gl.TEXTURE_2D: expectedType = sglrReferenceContext.TextureType.TYPE_2D; break;
+ case gl.TEXTURE_CUBE_MAP: expectedType = sglrReferenceContext.TextureType.TYPE_CUBE_MAP; break;
+ case gl.TEXTURE_2D_ARRAY: expectedType = sglrReferenceContext.TextureType.TYPE_2D_ARRAY; break;
+ case gl.TEXTURE_3D: expectedType = sglrReferenceContext.TextureType.TYPE_3D; break;
+ default: throw new Error('Unrecognized target: ' + target);
+ }
+ if (this.conditionalSetError((texture.textureType != expectedType), gl.INVALID_OPERATION))
+ return;
+ }
+ switch (target) {
+ case gl.TEXTURE_2D: this.setTex2DBinding(unitNdx, texture); break;
+ case gl.TEXTURE_CUBE_MAP: this.setTexCubeBinding(unitNdx, texture); break;
+ case gl.TEXTURE_2D_ARRAY: this.setTex2DArrayBinding(unitNdx, texture); break;
+ case gl.TEXTURE_3D: this.setTex3DBinding(unitNdx, texture); break;
+ default:
+ throw new Error('Unrecognized target: ' + target);
+ }
+ }
+ };
+
+ /**
+ * @param {number} unitNdx
+ * @param {?sglrReferenceContext.TextureContainer} texture
+ */
+ sglrReferenceContext.ReferenceContext.prototype.setTexCubeBinding = function(unitNdx, texture) {
+ if (this.m_textureUnits[unitNdx].texCubeBinding) {
+ this.m_textureUnits[unitNdx].texCubeBinding = null;
+ }
+
+ if (texture) {
+ this.m_textureUnits[unitNdx].texCubeBinding = texture;
+ }
+ };
+
+ /**
+ * @param {number} unitNdx
+ * @param {?sglrReferenceContext.TextureContainer} texture
+ */
+ sglrReferenceContext.ReferenceContext.prototype.setTex2DBinding = function(unitNdx, texture) {
+ if (this.m_textureUnits[unitNdx].tex2DBinding) {
+ // this.m_textures.releaseReference(this.m_textureUnits[unitNdx].tex2DBinding);
+ this.m_textureUnits[unitNdx].tex2DBinding = null;
+ }
+
+ if (texture) {
+ // this.m_textures.acquireReference(texture);
+ this.m_textureUnits[unitNdx].tex2DBinding = texture;
+ }
+ };
+
+ /**
+ * @param {number} unitNdx
+ * @param {?sglrReferenceContext.TextureContainer} texture
+ */
+ sglrReferenceContext.ReferenceContext.prototype.setTex2DArrayBinding = function(unitNdx, texture) {
+ if (this.m_textureUnits[unitNdx].tex2DArrayBinding) {
+ // this.m_textures.releaseReference(this.m_textureUnits[unitNdx].tex2DArrayBinding);
+ this.m_textureUnits[unitNdx].tex2DArrayBinding = null;
+ }
+
+ if (texture) {
+ // this.m_textures.acquireReference(texture);
+ this.m_textureUnits[unitNdx].tex2DArrayBinding = texture;
+ }
+ };
+
+ /**
+ * @param {number} unitNdx
+ * @param {?sglrReferenceContext.TextureContainer} texture
+ */
+ sglrReferenceContext.ReferenceContext.prototype.setTex3DBinding = function(unitNdx, texture) {
+ if (this.m_textureUnits[unitNdx].tex3DBinding) {
+ // this.m_textures.releaseReference(this.m_textureUnits[unitNdx].tex3DBinding);
+ this.m_textureUnits[unitNdx].tex3DBinding = null;
+ }
+
+ if (texture) {
+ // this.m_textures.acquireReference(texture);
+ this.m_textureUnits[unitNdx].tex3DBinding = texture;
+ }
+ };
+
+ /**
+ * @return {sglrReferenceContext.TextureContainer}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.createTexture = function() { return new sglrReferenceContext.TextureContainer(); };
+
+ /**
+ * @param {sglrReferenceContext.Texture} texture
+ */
+ sglrReferenceContext.ReferenceContext.prototype.deleteTexture = function(texture) { /*empty*/ };
+
+ /**
+ * @param {number} target
+ * @param {framework.opengl.simplereference.sglrReferenceContext.Framebuffer} fbo
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bindFramebuffer = function(target, fbo) {
+ if (this.conditionalSetError((target != gl.FRAMEBUFFER &&
+ target != gl.DRAW_FRAMEBUFFER &&
+ target != gl.READ_FRAMEBUFFER), gl.INVALID_ENUM))
+ return;
+ for (var ndx = 0; ndx < 2; ndx++) {
+ /** @type {number} */ var bindingTarget = ndx ? gl.DRAW_FRAMEBUFFER : gl.READ_FRAMEBUFFER;
+
+ if (target != gl.FRAMEBUFFER && target != bindingTarget)
+ continue; // Doesn't match this target.
+
+ if (ndx)
+ this.m_drawFramebufferBinding = fbo;
+ else
+ this.m_readFramebufferBinding = fbo;
+ }
+ };
+
+ /**
+ * @return {sglrReferenceContext.Framebuffer}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.createFramebuffer = function() { return new sglrReferenceContext.Framebuffer(); };
+
+ /**
+ * @param {sglrReferenceContext.Framebuffer} fbo
+ */
+ sglrReferenceContext.ReferenceContext.prototype.deleteFramebuffer = function(fbo) { /*empty*/ };
+
+ /**
+ * @param {number} target
+ * @param {sglrReferenceContext.Renderbuffer} rbo
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bindRenderbuffer = function(target, rbo) {
+ if (this.conditionalSetError(target != gl.RENDERBUFFER, gl.INVALID_ENUM))
+ return;
+
+ this.m_renderbufferBinding = rbo;
+ };
+
+ /**
+ * @return {sglrReferenceContext.Renderbuffer}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.createRenderbuffer = function() { return new sglrReferenceContext.Renderbuffer(); };
+
+ /**
+ * @param {sglrReferenceContext.Renderbuffer} rbo
+ */
+ sglrReferenceContext.ReferenceContext.prototype.deleteRenderbuffer = function(rbo) { /*empty*/ };
+
+ /**
+ * @param {number} pname
+ * @param {number} param
+ */
+ sglrReferenceContext.ReferenceContext.prototype.pixelStorei = function(pname, param) {
+ switch (pname) {
+ case gl.UNPACK_ALIGNMENT:
+ if (this.conditionalSetError((param != 1 && param != 2 && param != 4 && param != 8), gl.INVALID_VALUE)) return;
+ this.m_pixelUnpackAlignment = param;
+ break;
+
+ case gl.PACK_ALIGNMENT:
+ if (this.conditionalSetError((param != 1 && param != 2 && param != 4 && param != 8), gl.INVALID_VALUE)) return;
+ this.m_pixelPackAlignment = param;
+ break;
+
+ case gl.UNPACK_ROW_LENGTH:
+ if (this.conditionalSetError(param < 0, gl.INVALID_VALUE)) return;
+ this.m_pixelUnpackRowLength = param;
+ break;
+
+ case gl.UNPACK_SKIP_ROWS:
+ if (this.conditionalSetError(param < 0, gl.INVALID_VALUE)) return;
+ this.m_pixelUnpackSkipRows = param;
+ break;
+
+ case gl.UNPACK_SKIP_PIXELS:
+ if (this.conditionalSetError(param < 0, gl.INVALID_VALUE)) return;
+ this.m_pixelUnpackSkipPixels = param;
+ break;
+
+ case gl.UNPACK_IMAGE_HEIGHT:
+ if (this.conditionalSetError(param < 0, gl.INVALID_VALUE)) return;
+ this.m_pixelUnpackImageHeight = param;
+ break;
+
+ case gl.UNPACK_SKIP_IMAGES:
+ if (this.conditionalSetError(param < 0, gl.INVALID_VALUE)) return;
+ this.m_pixelUnpackSkipImages = param;
+ break;
+
+ default:
+ this.setError(gl.INVALID_ENUM);
+ }
+ };
+
+ /**
+ * @param {number} red
+ * @param {number} green
+ * @param {number} blue
+ * @param {number} alpha
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearColor = function(red, green, blue, alpha) {
+ this.m_clearColor = [deMath.clamp(red, 0, 1),
+ deMath.clamp(green, 0, 1),
+ deMath.clamp(blue, 0, 1),
+ deMath.clamp(alpha, 0, 1)];
+ };
+
+ /**
+ * @param {number} depth
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearDepthf = function(depth) {
+ this.m_clearDepth = deMath.clamp(depth, 0, 1);
+ };
+
+ /**
+ * @param {number} stencil
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearStencil = function(stencil) {
+ this.m_clearStencil = stencil;
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.ReferenceContext.prototype.scissor = function(x, y, width, height) {
+ if (this.conditionalSetError(width < 0 || height < 0, gl.INVALID_VALUE))
+ return;
+ this.m_scissorBox = [x, y, width, height];
+ };
+
+ /**
+ * @param {number} cap
+ */
+ sglrReferenceContext.ReferenceContext.prototype.enable = function(cap) {
+ switch (cap) {
+ case gl.BLEND: this.m_blendEnabled = true; break;
+ case gl.SCISSOR_TEST: this.m_scissorEnabled = true; break;
+ case gl.DEPTH_TEST: this.m_depthTestEnabled = true; break;
+ case gl.STENCIL_TEST: this.m_stencilTestEnabled = true; break;
+ case gl.POLYGON_OFFSET_FILL: this.m_polygonOffsetFillEnabled = true; break;
+
+ case gl.DITHER:
+ // Not implemented - just ignored.
+ break;
+
+ default:
+ this.setError(gl.INVALID_ENUM);
+ break;
+ }
+ };
+
+ /**
+ * @param {number} cap
+ */
+ sglrReferenceContext.ReferenceContext.prototype.disable = function(cap) {
+ switch (cap) {
+ case gl.BLEND: this.m_blendEnabled = false; break;
+ case gl.SCISSOR_TEST: this.m_scissorEnabled = false; break;
+ case gl.DEPTH_TEST: this.m_depthTestEnabled = false; break;
+ case gl.STENCIL_TEST: this.m_stencilTestEnabled = false; break;
+ case gl.POLYGON_OFFSET_FILL: this.m_polygonOffsetFillEnabled = false; break;
+
+ case gl.DITHER:
+ // Not implemented - just ignored.
+ break;
+
+ default:
+ this.setError(gl.INVALID_ENUM);
+ break;
+ }
+ };
+
+ /**
+ * @param {number} func
+ * @param {number} ref
+ * @param {number} mask
+ */
+ sglrReferenceContext.ReferenceContext.prototype.stencilFunc = function(func, ref, mask) {
+ this.stencilFuncSeparate(gl.FRONT_AND_BACK, func, ref, mask);
+ };
+
+ /**
+ * @param {number} face
+ * @param {number} func
+ * @param {number} ref
+ * @param {number} mask
+ */
+ sglrReferenceContext.ReferenceContext.prototype.stencilFuncSeparate = function(face, func, ref, mask) {
+ /** @type {boolean} */ var setFront = face == gl.FRONT || face == gl.FRONT_AND_BACK;
+ /** @type {boolean} */ var setBack = face == gl.BACK || face == gl.FRONT_AND_BACK;
+
+ if (this.conditionalSetError(!sglrReferenceContext.isValidCompareFunc(func), gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(!setFront && !setBack, gl.INVALID_ENUM))
+ return;
+
+ for (var key in rrDefs.FaceType) {
+ /** @type {number} */ var type = rrDefs.FaceType[key];
+ if ((type == rrDefs.FaceType.FACETYPE_FRONT && setFront) ||
+ (type == rrDefs.FaceType.FACETYPE_BACK && setBack)) {
+ this.m_stencil[type].func = func;
+ this.m_stencil[type].ref = ref;
+ this.m_stencil[type].opMask = mask;
+ }
+ }
+ };
+
+ /**
+ * @param {number} func
+ * @return {boolean}
+ */
+ sglrReferenceContext.isValidCompareFunc = function(func) {
+ switch (func) {
+ case gl.NEVER:
+ case gl.LESS:
+ case gl.LEQUAL:
+ case gl.GREATER:
+ case gl.GEQUAL:
+ case gl.EQUAL:
+ case gl.NOTEQUAL:
+ case gl.ALWAYS:
+ return true;
+
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * @param {number} op
+ * @return {boolean}
+ */
+ sglrReferenceContext.isValidStencilOp = function(op) {
+ switch (op) {
+ case gl.KEEP:
+ case gl.ZERO:
+ case gl.REPLACE:
+ case gl.INCR:
+ case gl.INCR_WRAP:
+ case gl.DECR:
+ case gl.DECR_WRAP:
+ case gl.INVERT:
+ return true;
+
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * @param {number} sfail
+ * @param {number} dpfail
+ * @param {number} dppass
+ */
+ sglrReferenceContext.ReferenceContext.prototype.stencilOp = function(sfail, dpfail, dppass) {
+ this.stencilOpSeparate(gl.FRONT_AND_BACK, sfail, dpfail, dppass);
+ };
+
+ /**
+ * @param {number} face
+ * @param {number} sfail
+ * @param {number} dpfail
+ * @param {number} dppass
+ */
+ sglrReferenceContext.ReferenceContext.prototype.stencilOpSeparate = function(face, sfail, dpfail, dppass) {
+ /** @type {boolean} */ var setFront = face == gl.FRONT || face == gl.FRONT_AND_BACK;
+ /** @type {boolean} */ var setBack = face == gl.BACK || face == gl.FRONT_AND_BACK;
+
+ if (this.conditionalSetError((!sglrReferenceContext.isValidStencilOp(sfail) ||
+ !sglrReferenceContext.isValidStencilOp(dpfail) ||
+ !sglrReferenceContext.isValidStencilOp(dppass)),
+ gl.INVALID_ENUM))
+ return;
+
+ if (this.conditionalSetError(!setFront && !setBack, gl.INVALID_ENUM))
+ return;
+
+ for (var key in rrDefs.FaceType) {
+ /** @type {number} */ var type = rrDefs.FaceType[key];
+ if ((type == rrDefs.FaceType.FACETYPE_FRONT && setFront) ||
+ (type == rrDefs.FaceType.FACETYPE_BACK && setBack)) {
+ this.m_stencil[type].opStencilFail = sfail;
+ this.m_stencil[type].opDepthFail = dpfail;
+ this.m_stencil[type].opDepthPass = dppass;
+ }
+ }
+ };
+
+ /**
+ * @param {number} func
+ */
+ sglrReferenceContext.ReferenceContext.prototype.depthFunc = function(func) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidCompareFunc(func), gl.INVALID_ENUM))
+ return;
+ this.m_depthFunc = func;
+ };
+
+ /**
+ * @param {number} n
+ * @param {number} f
+ */
+ sglrReferenceContext.ReferenceContext.prototype.depthRange = function(n, f) {
+ this.m_depthRangeNear = deMath.clamp(n, 0, 1);
+ this.m_depthRangeFar = deMath.clamp(f, 0, 1);
+ };
+
+ /**
+ * @param {number} factor
+ * @param {number} units
+ */
+ sglrReferenceContext.ReferenceContext.prototype.polygonOffset = function(factor, units) {
+ this.m_polygonOffsetFactor = factor;
+ this.m_polygonOffsetUnits = units;
+ };
+
+ /**
+ * @param {number} mode
+ * @return {boolean}
+ */
+ sglrReferenceContext.isValidBlendEquation = function(mode) {
+ return mode == gl.FUNC_ADD ||
+ mode == gl.FUNC_SUBTRACT ||
+ mode == gl.FUNC_REVERSE_SUBTRACT ||
+ mode == gl.MIN ||
+ mode == gl.MAX;
+ };
+
+ /**
+ * @param {number} factor
+ * @return {boolean}
+ */
+ sglrReferenceContext.isValidBlendFactor = function(factor) {
+ switch (factor) {
+ case gl.ZERO:
+ case gl.ONE:
+ case gl.SRC_COLOR:
+ case gl.ONE_MINUS_SRC_COLOR:
+ case gl.DST_COLOR:
+ case gl.ONE_MINUS_DST_COLOR:
+ case gl.SRC_ALPHA:
+ case gl.ONE_MINUS_SRC_ALPHA:
+ case gl.DST_ALPHA:
+ case gl.ONE_MINUS_DST_ALPHA:
+ case gl.CONSTANT_COLOR:
+ case gl.ONE_MINUS_CONSTANT_COLOR:
+ case gl.CONSTANT_ALPHA:
+ case gl.ONE_MINUS_CONSTANT_ALPHA:
+ case gl.SRC_ALPHA_SATURATE:
+ return true;
+
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * @param {number} mode
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blendEquation = function(mode) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBlendEquation(mode), gl.INVALID_ENUM))
+ return;
+ this.m_blendModeRGB = mode;
+ this.m_blendModeAlpha = mode;
+ };
+
+ /**
+ * @param {number} modeRGB
+ * @param {number} modeAlpha
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blendEquationSeparate = function(modeRGB, modeAlpha) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBlendEquation(modeRGB) ||
+ !sglrReferenceContext.isValidBlendEquation(modeAlpha),
+ gl.INVALID_ENUM))
+ return;
+
+ this.m_blendModeRGB = modeRGB;
+ this.m_blendModeAlpha = modeAlpha;
+ };
+
+ /**
+ * @param {number} src
+ * @param {number} dst
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blendFunc = function(src, dst) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBlendFactor(src) ||
+ !sglrReferenceContext.isValidBlendFactor(dst),
+ gl.INVALID_ENUM))
+ return;
+
+ this.m_blendFactorSrcRGB = src;
+ this.m_blendFactorSrcAlpha = src;
+ this.m_blendFactorDstRGB = dst;
+ this.m_blendFactorDstAlpha = dst;
+ };
+
+ /**
+ * @param {number} srcRGB
+ * @param {number} dstRGB
+ * @param {number} srcAlpha
+ * @param {number} dstAlpha
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blendFuncSeparate = function(srcRGB, dstRGB, srcAlpha, dstAlpha) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBlendFactor(srcRGB) ||
+ !sglrReferenceContext.isValidBlendFactor(dstRGB) ||
+ !sglrReferenceContext.isValidBlendFactor(srcAlpha) ||
+ !sglrReferenceContext.isValidBlendFactor(dstAlpha),
+ gl.INVALID_ENUM))
+ return;
+
+ this.m_blendFactorSrcRGB = srcRGB;
+ this.m_blendFactorSrcAlpha = srcAlpha;
+ this.m_blendFactorDstRGB = dstRGB;
+ this.m_blendFactorDstAlpha = dstAlpha;
+ };
+
+ /**
+ * @param {number} red
+ * @param {number} green
+ * @param {number} blue
+ * @param {number} alpha
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blendColor = function(red, green, blue, alpha) {
+ this.m_blendColor = [deMath.clamp(red, 0, 1),
+ deMath.clamp(green, 0, 1),
+ deMath.clamp(blue, 0, 1),
+ deMath.clamp(alpha, 0, 1)];
+ };
+
+ /**
+ * @param {boolean} r
+ * @param {boolean} g
+ * @param {boolean} b
+ * @param {boolean} a
+ */
+ sglrReferenceContext.ReferenceContext.prototype.colorMask = function(r, g, b, a) {
+ this.m_colorMask = [r, g, b, a];
+ };
+
+ /**
+ * @param {boolean} mask
+ */
+ sglrReferenceContext.ReferenceContext.prototype.depthMask = function(mask) {
+ this.m_depthMask = mask;
+ };
+
+ /**
+ * @param {number} mask
+ */
+ sglrReferenceContext.ReferenceContext.prototype.stencilMask = function(mask) {
+ this.stencilMaskSeparate(gl.FRONT_AND_BACK, mask);
+ };
+
+ /**
+ * @param {number} face
+ * @param {number} mask
+ */
+ sglrReferenceContext.ReferenceContext.prototype.stencilMaskSeparate = function(face, mask) {
+ /** @type {boolean} */ var setFront = face == gl.FRONT || face == gl.FRONT_AND_BACK;
+ /** @type {boolean} */ var setBack = face == gl.BACK || face == gl.FRONT_AND_BACK;
+
+ if (this.conditionalSetError(!setFront && !setBack, gl.INVALID_ENUM))
+ return;
+
+ if (setFront) this.m_stencil[rrDefs.FaceType.FACETYPE_FRONT].writeMask = mask;
+ if (setBack) this.m_stencil[rrDefs.FaceType.FACETYPE_BACK].writeMask = mask;
+ };
+
+ /**
+ * @param {sglrReferenceContext.VertexArray} array
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bindVertexArray = function(array) {
+ if (array)
+ this.m_vertexArrayBinding = array;
+ else
+ this.m_vertexArrayBinding = this.m_defaultVAO;
+ };
+
+ /**
+ * @return {sglrReferenceContext.VertexArray}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.createVertexArray = function() { return new sglrReferenceContext.VertexArray(this.m_limits.maxVertexAttribs); };
+
+ /**
+ * @param {number} array
+ */
+ sglrReferenceContext.ReferenceContext.prototype.deleteVertexArray = function(array) {};
+
+ /**
+ * @param {number} index
+ * @param {number} rawSize
+ * @param {number} type
+ * @param {boolean} normalized
+ * @param {number} stride
+ * @param {number} offset
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttribPointer = function(index, rawSize, type, normalized, stride, offset) {
+ /** @type {boolean} */ var allowBGRA = false;
+ /** @type {number} */ var effectiveSize = rawSize;
+
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(effectiveSize <= 0 || effectiveSize > 4, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(type != gl.BYTE && type != gl.UNSIGNED_BYTE &&
+ type != gl.SHORT && type != gl.UNSIGNED_SHORT &&
+ type != gl.INT && type != gl.UNSIGNED_INT &&
+ type != gl.FLOAT && type != gl.HALF_FLOAT &&
+ type != gl.INT_2_10_10_10_REV && type != gl.UNSIGNED_INT_2_10_10_10_REV, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(normalized != true && normalized != false, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(stride < 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError((type == gl.INT_2_10_10_10_REV || type == gl.UNSIGNED_INT_2_10_10_10_REV) && effectiveSize != 4, gl.INVALID_OPERATION))
+ return;
+ if (this.conditionalSetError(this.m_vertexArrayBinding != null && this.m_arrayBufferBinding == null && offset != 0, gl.INVALID_OPERATION))
+ return;
+
+ /** @type {?(sglrReferenceContext.VertexArray.VertexAttribArray)} */ var array_ = this.m_vertexArrayBinding.m_arrays[index]; // TODO: fix type
+
+ array_.size = rawSize;
+ array_.stride = stride;
+ array_.type = type;
+ array_.normalized = normalized;
+ array_.integer = false;
+ array_.offset = offset;
+
+ array_.bufferBinding = this.m_arrayBufferBinding;
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} size
+ * @param {number} type
+ * @param {number} stride
+ * @param {number} offset
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttribIPointer = function(index, size, type, stride, offset) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(size <= 0 || size > 4, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(type != gl.BYTE && type != gl.UNSIGNED_BYTE &&
+ type != gl.SHORT && type != gl.UNSIGNED_SHORT &&
+ type != gl.INT && type != gl.UNSIGNED_INT, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(stride < 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(this.m_vertexArrayBinding != null && this.m_arrayBufferBinding == null && offset != 0, gl.INVALID_OPERATION))
+ return;
+
+ /** @type {?(sglrReferenceContext.VertexArray.VertexAttribArray)} */ var array_ = this.m_vertexArrayBinding.m_arrays[index]; // TODO: fix type
+
+ array_.size = size;
+ array_.stride = stride;
+ array_.type = type;
+ array_.normalized = false;
+ array_.integer = true;
+ array_.offset = offset;
+
+ array_.bufferBinding = this.m_arrayBufferBinding;
+ };
+
+ /**
+ * @param {number} index
+ */
+ sglrReferenceContext.ReferenceContext.prototype.enableVertexAttribArray = function(index) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_vertexArrayBinding.m_arrays[index].enabled = true;
+ };
+
+ /**
+ * @param {number} index
+ */
+ sglrReferenceContext.ReferenceContext.prototype.disableVertexAttribArray = function(index) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_vertexArrayBinding.m_arrays[index].enabled = false;
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} divisor
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttribDivisor = function(index, divisor) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_vertexArrayBinding.m_arrays[index].divisor = divisor;
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttrib1f = function(index, x) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_currentAttribs[index] = new rrGenericVector.GenericVec4(x, 0, 0, 1);
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttrib2f = function(index, x, y) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_currentAttribs[index] = new rrGenericVector.GenericVec4(x, y, 0, 1);
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttrib3f = function(index, x, y, z) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_currentAttribs[index] = new rrGenericVector.GenericVec4(x, y, z, 1);
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttrib4f = function(index, x, y, z, w) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_currentAttribs[index] = new rrGenericVector.GenericVec4(x, y, z, w);
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttribI4i = function(index, x, y, z, w) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_currentAttribs[index] = new rrGenericVector.GenericVec4(x, y, z, w);
+ };
+
+ /**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+ sglrReferenceContext.ReferenceContext.prototype.vertexAttribI4ui = function(index, x, y, z, w) {
+ if (this.conditionalSetError(index >= this.m_limits.maxVertexAttribs, gl.INVALID_VALUE))
+ return;
+
+ this.m_currentAttribs[index] = new rrGenericVector.GenericVec4(x, y, z, w);
+ };
+
+ /**
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {string} name
+ * @return {number}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getAttribLocation = function(program, name) {
+ if (this.conditionalSetError(!(program), gl.INVALID_OPERATION))
+ return -1;
+
+ for (var i = 0; i < program.m_attributeNames.length; i++)
+ if (program.m_attributeNames[i] === name)
+ return i;
+
+ return -1;
+ };
+
+ /**
+ * @param {number} pname
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getParameter = function(pname) {
+ switch (pname) {
+ case (gl.VIEWPORT): return new Int32Array(this.m_viewport);
+ case (gl.SCISSOR_BOX): return new Int32Array(this.m_scissorBox);
+ default:
+ throw new Error('Unimplemented');
+ }
+ };
+
+ /**
+ * @param {number} location
+ * @param {gluShaderUtil.DataType} type
+ * @param {Array<number>} value
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniformValue = function(location, type, value) {
+ if (this.conditionalSetError(!this.m_currentProgram, gl.INVALID_OPERATION))
+ return;
+
+ if (location === null)
+ return;
+
+ /** @type {sglrShaderProgram.Uniform} */ var uniform = this.m_currentProgram.m_uniforms[location];
+
+ if (this.conditionalSetError(!uniform, gl.INVALID_OPERATION))
+ return;
+
+ if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
+ if (this.conditionalSetError(type != gluShaderUtil.DataType.INT, gl.INVALID_OPERATION))
+ return;
+ } else if (this.conditionalSetError(uniform.type != type, gl.INVALID_OPERATION))
+ return;
+ /* TODO: Do we need to copy objects? */
+ uniform.value = value;
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform1f = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT, [x]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform1fv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform1i = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT, [x]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform1iv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ * @param {number} y
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform2f = function(location, x, y) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_VEC2, [x, y]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform2fv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_VEC2, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ * @param {number} y
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform2i = function(location, x, y) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT_VEC2, [x, y]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform2iv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT_VEC2, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform3f = function(location, x, y, z) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_VEC3, [x, y, z]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform3fv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_VEC3, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform3i = function(location, x, y, z) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT_VEC3, [x, y, z]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform3iv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT_VEC3, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform4f = function(location, x, y, z, w) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_VEC4, [x, y, z, w]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform4fv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_VEC4, x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform4i = function(location, x, y, z, w) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT_VEC4, [x, y, z, w]);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniform4iv = function(location, x) {
+ return this.uniformValue(location, gluShaderUtil.DataType.INT_VEC4, x);
+ };
+
+ /**
+ * @return {Array<string>}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getSupportedExtensions = function() {
+ var extensions = gl.getSupportedExtensions(); //TODO: Let's just return gl's supported extensions for now
+ return extensions;
+ };
+
+ /**
+ * @param {string} name
+ * @return {*}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getExtension = function(name) {
+ return gl.getExtension(name); //TODO: Let's just return gl's supported extensions for now
+ };
+
+ /** transpose matrix 'x' of 'size' columns and rows
+ * @param {number} size
+ * @param {Array<number>} x
+ * @return {Array<number>}
+ */
+ sglrReferenceContext.trans = function(size, x) {
+ /** @type {Array<number>} */ var result = [];
+ for (var row = 0; row < size; ++row)
+ for (var col = 0; col < size; ++col)
+ result[row * size + col] = x[col * size + row];
+
+ return result;
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniformMatrix2fv = function(location, transpose, x) {
+ /* change from column-major to internal row-major if transpose if FALSE */
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_MAT2, !transpose ? sglrReferenceContext.trans(2, x) : x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniformMatrix3fv = function(location, transpose, x) {
+ /* change from column-major to internal row-major if transpose if FALSE */
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_MAT3, !transpose ? sglrReferenceContext.trans(3, x) : x);
+ };
+
+ /**
+ * @param {number} location
+ * @param {Array<number>} x
+ */
+ sglrReferenceContext.ReferenceContext.prototype.uniformMatrix4fv = function(location, transpose, x) {
+ /* change from column-major to internal row-major if transpose if FALSE */
+ return this.uniformValue(location, gluShaderUtil.DataType.FLOAT_MAT4, !transpose ? sglrReferenceContext.trans(4, x) : x);
+ };
+
+ /**
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {string} name
+ * @return {number}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getUniformLocation = function(program, name) {
+ if (this.conditionalSetError(!program, gl.INVALID_OPERATION))
+ return -1;
+
+ for (var i = 0; i < program.m_uniforms.length; i++)
+ if (program.m_uniforms[i].name === name)
+ return i;
+
+ return -1;
+ };
+
+ /**
+ * @param {number} w
+ */
+ sglrReferenceContext.ReferenceContext.prototype.lineWidth = function(w) {
+ if (this.conditionalSetError(w < 0, gl.INVALID_VALUE))
+ return;
+ this.m_lineWidth = w;
+ };
+
+ /**
+ * @param {number} target
+ * @return {boolean}
+ */
+ sglrReferenceContext.isValidBufferTarget = function(target) {
+ switch (target) {
+ case gl.ARRAY_BUFFER:
+ case gl.COPY_READ_BUFFER:
+ case gl.COPY_WRITE_BUFFER:
+ case gl.ELEMENT_ARRAY_BUFFER:
+ case gl.PIXEL_PACK_BUFFER:
+ case gl.PIXEL_UNPACK_BUFFER:
+ case gl.TRANSFORM_FEEDBACK_BUFFER:
+ case gl.UNIFORM_BUFFER:
+ return true;
+
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {sglrReferenceContext.DataBuffer} buffer
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.setBufferBinding = function(target, buffer) {
+ switch (target) {
+ case gl.ARRAY_BUFFER: this.m_arrayBufferBinding = buffer; break;
+ case gl.COPY_READ_BUFFER: this.m_copyReadBufferBinding = buffer; break;
+ case gl.COPY_WRITE_BUFFER: this.m_copyWriteBufferBinding = buffer; break;
+ case gl.ELEMENT_ARRAY_BUFFER: this.m_vertexArrayBinding.m_elementArrayBufferBinding = buffer; break;
+ case gl.PIXEL_PACK_BUFFER: this.m_pixelPackBufferBinding = buffer; break;
+ case gl.PIXEL_UNPACK_BUFFER: this.m_pixelUnpackBufferBinding = buffer; break;
+ case gl.TRANSFORM_FEEDBACK_BUFFER: this.m_transformFeedbackBufferBinding = buffer; break;
+ case gl.UNIFORM_BUFFER: this.m_uniformBufferBinding = buffer; break;
+ default:
+ throw new Error('Unrecognized target: ' + target);
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @return {sglrReferenceContext.DataBuffer}
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getBufferBinding = function(target) {
+ switch (target) {
+ case gl.ARRAY_BUFFER: return this.m_arrayBufferBinding;
+ case gl.COPY_READ_BUFFER: return this.m_copyReadBufferBinding;
+ case gl.COPY_WRITE_BUFFER: return this.m_copyWriteBufferBinding;
+ case gl.ELEMENT_ARRAY_BUFFER: return this.m_vertexArrayBinding.m_elementArrayBufferBinding;
+ case gl.PIXEL_PACK_BUFFER: return this.m_pixelPackBufferBinding;
+ case gl.PIXEL_UNPACK_BUFFER: return this.m_pixelUnpackBufferBinding;
+ case gl.TRANSFORM_FEEDBACK_BUFFER: return this.m_transformFeedbackBufferBinding;
+ case gl.UNIFORM_BUFFER: return this.m_uniformBufferBinding;
+ default:
+ throw new Error('Unrecognized target: ' + target);
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {sglrReferenceContext.DataBuffer} buffer
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bindBuffer = function(target, buffer) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBufferTarget(target), gl.INVALID_ENUM))
+ return;
+
+ this.setBufferBinding(target, buffer);
+ };
+
+ /**
+ * @return {sglrReferenceContext.DataBuffer}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.createBuffer = function() { return new sglrReferenceContext.DataBuffer(); };
+
+ /**
+ * @param {number} buffer
+ */
+ sglrReferenceContext.ReferenceContext.prototype.deleteBuffer = function(buffer) {};
+
+ /**
+ * @param {number} target
+ * @param {number|goog.NumberArray} input
+ * @param {number} usage
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bufferData = function(target, input, usage) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBufferTarget(target), gl.INVALID_ENUM))
+ return;
+ /** @type {sglrReferenceContext.DataBuffer} */ var buffer = this.getBufferBinding(target);
+ if (this.conditionalSetError(!buffer, gl.INVALID_OPERATION))
+ return;
+
+ if (typeof input == 'number') {
+ if (this.conditionalSetError(input < 0, gl.INVALID_VALUE))
+ return;
+ buffer.setStorage(input);
+ } else {
+ buffer.setData(input);
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} offset
+ * @param {goog.NumberArray} data
+ */
+ sglrReferenceContext.ReferenceContext.prototype.bufferSubData = function(target, offset, data) {
+ if (this.conditionalSetError(!sglrReferenceContext.isValidBufferTarget(target), gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(offset < 0, gl.INVALID_VALUE))
+ return;
+ /** @type {sglrReferenceContext.DataBuffer} */ var buffer = this.getBufferBinding(target);
+ if (this.conditionalSetError(!buffer, gl.INVALID_OPERATION))
+ return;
+
+ if (this.conditionalSetError(offset + data.byteLength > buffer.getSize(), gl.INVALID_VALUE))
+ return;
+ buffer.setSubData(offset, data);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {number} format
+ * @param {number} type
+ * @param {goog.NumberArray} pixels
+ */
+ sglrReferenceContext.ReferenceContext.prototype.readPixels = function(x, y, width, height, format, type, pixels) {
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var src = this.getReadColorbuffer();
+
+ // Map transfer format.
+ /** @type {tcuTexture.TextureFormat} */ var transferFmt = gluTextureUtil.mapGLTransferFormat(format, type);
+
+ // Clamp input values
+ /** @type {number} */ var copyX = deMath.clamp(x, 0, src.raw().getHeight());
+ /** @type {number} */ var copyY = deMath.clamp(y, 0, src.raw().getDepth());
+ /** @type {number} */ var copyWidth = deMath.clamp(width, 0, src.raw().getHeight() - x);
+ /** @type {number} */ var copyHeight = deMath.clamp(height, 0, src.raw().getDepth() - y);
+
+ /** @type {?ArrayBuffer} */ var data;
+ /** @type {number} */ var offset;
+ if (this.m_pixelPackBufferBinding) {
+ if (this.conditionalSetError(typeof pixels !== 'number', gl.INVALID_VALUE))
+ return;
+ data = this.m_pixelPackBufferBinding.getData();
+ offset = pixels.byteOffset;
+ } else {
+ if (pixels instanceof ArrayBuffer) {
+ data = pixels;
+ offset = 0;
+ } else {
+ data = pixels.buffer;
+ offset = pixels.byteOffset;
+ }
+ }
+
+ /** @type {tcuTexture.PixelBufferAccess} */
+ var dst = new tcuTexture.PixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ depth: 1,
+ rowPitch: deMath.deAlign32(width * transferFmt.getPixelSize(), this.m_pixelPackAlignment),
+ slicePitch: 0,
+ data: data,
+ offset: offset});
+
+ src = src.getSubregion([copyX, copyY, copyWidth, copyHeight]);
+ src.resolveMultisampleColorBuffer(tcuTextureUtil.getSubregion(dst, 0, 0, 0, copyWidth, copyHeight, 1));
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getType = function() {
+ return this.m_type;
+ };
+
+ /**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.nullAccess = function() {
+ return new tcuTexture.PixelBufferAccess({
+ width: 0,
+ height: 0});
+ };
+
+ /**
+ * @param {sglrReferenceContext.Framebuffer} framebuffer
+ * @param {sglrReferenceContext.AttachmentPoint} point
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getFboAttachment = function(framebuffer, point) {
+ /** @type {sglrReferenceContext.Attachment} */ var attachment = framebuffer.getAttachment(point);
+
+ switch (attachment.type) {
+ case sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_TEXTURE: {
+ var container = /** @type {sglrReferenceContext.TextureContainer} */ (attachment.object);
+ /** @type {?sglrReferenceContext.TextureType} */ var type = container.getType();
+ var texture = container.texture;
+
+ if (type == sglrReferenceContext.TextureType.TYPE_2D)
+ return texture.getLevel(attachment.level);
+ else if (type == sglrReferenceContext.TextureType.TYPE_CUBE_MAP)
+ return texture.getFace(attachment.level, sglrReferenceContext.texTargetToFace(attachment.texTarget));
+ else if (type == sglrReferenceContext.TextureType.TYPE_2D_ARRAY ||
+ type == sglrReferenceContext.TextureType.TYPE_3D ||
+ type == sglrReferenceContext.TextureType.TYPE_CUBE_MAP_ARRAY) {
+ /** @type {tcuTexture.PixelBufferAccess} */ var level = texture.getLevel(attachment.level);
+
+ return new tcuTexture.PixelBufferAccess({
+ format: level.getFormat(),
+ width: level.getWidth(),
+ height: level.getHeight(),
+ depth: 1,
+ rowPitch: level.getRowPitch(),
+ slicePitch: 0,
+ data: level.getBuffer(),
+ offset: level.getSlicePitch() * attachment.layer});
+ } else
+ return sglrReferenceContext.nullAccess();
+ }
+
+ case sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_RENDERBUFFER: {
+ var rbo = /** @type {sglrReferenceContext.Renderbuffer} */ (attachment.object);
+ return rbo.getAccess();
+ }
+
+ default:
+ return sglrReferenceContext.nullAccess();
+ }
+ };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getReadColorbuffer = function() {
+ if (this.m_readFramebufferBinding)
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(this.getFboAttachment(this.m_readFramebufferBinding, sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_COLOR0));
+ else
+ return this.m_defaultColorbuffer;
+ };
+
+ // sglrReferenceContext.ReferenceContext.prototype.drawArrays = function(mode, first, count) {
+ // this.drawArraysInstanced(mode, first, count, 1);
+ // };
+
+ /**
+ * @param {number} target
+ * @return {number}
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.checkFramebufferStatus = function(target) {
+ if (this.conditionalSetError(target != gl.FRAMEBUFFER &&
+ target != gl.DRAW_FRAMEBUFFER &&
+ target != gl.READ_FRAMEBUFFER, gl.INVALID_ENUM))
+ return 0;
+
+ // Select binding point.
+ /** @type {sglrReferenceContext.Framebuffer} */ var framebufferBinding = (target == gl.FRAMEBUFFER || target == gl.DRAW_FRAMEBUFFER) ? this.m_drawFramebufferBinding : this.m_readFramebufferBinding;
+
+ // Default framebuffer is always complete.
+ if (!framebufferBinding)
+ return gl.FRAMEBUFFER_COMPLETE;
+
+ /** @type {number} */ var width = -1;
+ /** @type {number} */ var height = -1;
+ /** @type {boolean} */ var hasAttachment = false;
+ /** @type {boolean} */ var attachmentComplete = true;
+ /** @type {boolean} */ var dimensionsOk = true;
+
+ for (var key in sglrReferenceContext.AttachmentPoint) {
+ /** @type {sglrReferenceContext.AttachmentPoint} */ var point = sglrReferenceContext.AttachmentPoint[key];
+ /** @type {sglrReferenceContext.Attachment} */ var attachment = framebufferBinding.getAttachment(point);
+ /** @type {number} */ var attachmentWidth = 0;
+ /** @type {number} */ var attachmentHeight = 0;
+ /** @type {tcuTexture.TextureFormat} */ var attachmentFormat;
+
+ if (attachment.type == sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_TEXTURE) {
+ var container = /** @type {sglrReferenceContext.TextureContainer} */ (attachment.object);
+ /** @type {tcuTexture.ConstPixelBufferAccess} */ var level;
+
+ if (attachment.texTarget == sglrReferenceContext.TexTarget.TEXTARGET_2D) {
+ DE_ASSERT(container.textureType == sglrReferenceContext.TextureType.TYPE_2D);
+ /** @type {sglrReferenceContext.Texture2D} */ var tex2D = /** @type {sglrReferenceContext.Texture2D} */ (container.texture);
+
+ if (tex2D.hasLevel(attachment.level))
+ level = tex2D.getLevel(attachment.level);
+ // TODO: implement CUBE_MAP, 2D_ARRAY, 3D, CUBE_MAP_ARRAY
+ } else if (deMath.deInRange32(attachment.texTarget, sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_X,
+ sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_Z)) {
+ DE_ASSERT(container.textureType == sglrReferenceContext.TextureType.TYPE_CUBE_MAP);
+
+ var texCube = /** @type {sglrReferenceContext.TextureCube} */ (container.texture);
+ var face = sglrReferenceContext.texTargetToFace(attachment.texTarget);
+
+ if (texCube.hasFace(attachment.level, face))
+ level = texCube.getFace(attachment.level, face);
+ } else if (attachment.texTarget == sglrReferenceContext.TexTarget.TEXTARGET_2D_ARRAY) {
+ DE_ASSERT(container.textureType == sglrReferenceContext.TextureType.TYPE_2D_ARRAY);
+ var tex2DArr = /** @type {sglrReferenceContext.Texture2DArray} */ (container.texture);
+
+ if (tex2DArr.hasLevel(attachment.level))
+ level = tex2DArr.getLevel(attachment.level); // \note Slice doesn't matter here.
+ } else if (attachment.texTarget == sglrReferenceContext.TexTarget.TEXTARGET_3D) {
+ DE_ASSERT(container.textureType == sglrReferenceContext.TextureType.TYPE_3D);
+ var tex3D = /** @type {sglrReferenceContext.Texture3D} */ (container.texture);
+
+ if (tex3D.hasLevel(attachment.level))
+ level = tex3D.getLevel(attachment.level); // \note Slice doesn't matter here.
+ // } else if (attachment.texTarget == sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_ARRAY) {
+ // DE_ASSERT(container.textureType == sglrReferenceContext.TextureType.TYPE_CUBE_MAP_ARRAY);
+ // var texCubeArr = container.texture;
+ //
+ // if (texCubeArr.hasLevel(attachment.level))
+ // level = texCubeArr.getLevel(attachment.level); // \note Slice doesn't matter here.
+ } else
+ throw new Error('sglrReferenceContext.Framebuffer attached to a texture but no valid target specified.');
+
+ attachmentWidth = level.getWidth();
+ attachmentHeight = level.getHeight();
+ attachmentFormat = level.getFormat();
+ } else if (attachment.type == sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_RENDERBUFFER) {
+ var renderbuffer = attachment.object;
+
+ attachmentWidth = renderbuffer.getWidth();
+ attachmentHeight = renderbuffer.getHeight();
+ attachmentFormat = renderbuffer.getFormat();
+ } else
+ continue; // Skip rest of checks.
+
+ if (!hasAttachment && attachmentWidth > 0 && attachmentHeight > 0) {
+ width = attachmentWidth;
+ height = attachmentHeight;
+ hasAttachment = true;
+ } else if (attachmentWidth != width || attachmentHeight != height)
+ dimensionsOk = false;
+
+ // Validate attachment point compatibility.
+ switch (attachmentFormat.order) {
+ case tcuTexture.ChannelOrder.R:
+ case tcuTexture.ChannelOrder.RG:
+ case tcuTexture.ChannelOrder.RGB:
+ case tcuTexture.ChannelOrder.RGBA:
+ case tcuTexture.ChannelOrder.sRGB:
+ case tcuTexture.ChannelOrder.sRGBA:
+ if (point != sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_COLOR0)
+ attachmentComplete = false;
+ break;
+
+ case tcuTexture.ChannelOrder.D:
+ if (point != sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_DEPTH)
+ attachmentComplete = false;
+ break;
+
+ case tcuTexture.ChannelOrder.S:
+ if (point != sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_STENCIL)
+ attachmentComplete = false;
+ break;
+
+ case tcuTexture.ChannelOrder.DS:
+ if (point != sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_DEPTH &&
+ point != sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_STENCIL)
+ attachmentComplete = false;
+ break;
+
+ default:
+ throw new Error('Unsupported attachment channel order:' + attachmentFormat.order);
+ }
+ }
+
+ if (!attachmentComplete)
+ return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ else if (!hasAttachment)
+ return gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ else if (!dimensionsOk)
+ return gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ else
+ return gl.FRAMEBUFFER_COMPLETE;
+ };
+
+ /**
+ * @param {number} mode
+ * @return {boolean}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.predrawErrorChecks = function(mode) {
+ if (this.conditionalSetError(mode != gl.POINTS &&
+ mode != gl.LINE_STRIP && mode != gl.LINE_LOOP && mode != gl.LINES &&
+ mode != gl.TRIANGLE_STRIP && mode != gl.TRIANGLE_FAN && mode != gl.TRIANGLES,
+ gl.INVALID_ENUM))
+ return false;
+
+ // \todo [jarkko] Uncomment following code when the buffer mapping support is added
+ //for (size_t ndx = 0; ndx < vao.m_arrays.length; ++ndx)
+ // if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
+ // RC_ERROR_RET(gl.INVALID_OPERATION, RC_RET_VOID);
+
+ if (this.conditionalSetError(this.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE, gl.INVALID_FRAMEBUFFER_OPERATION))
+ return false;
+
+ return true;
+ };
+
+ /**
+ * Draws quads from vertex arrays
+ * @param {number} mode GL primitive type to draw with.
+ * @param {number} first First vertex to begin drawing with
+ * @param {number} count How many vertices to draw (not counting vertices before first)
+ * @param {number} instanceCount
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawArraysInstanced = function(mode, first, count, instanceCount) {
+ if (this.conditionalSetError(first < 0 || count < 0 || instanceCount < 0, gl.INVALID_VALUE))
+ return;
+
+ if (!this.predrawErrorChecks(mode))
+ return;
+
+ // All is ok
+ this.drawQuads(mode, first, count, instanceCount);
+ };
+
+ /**
+ * @param {number} mode GL primitive type to draw with.
+ * @param {number} start
+ * @param {number} end
+ * @param {number} count How many vertices to draw (not counting vertices before first)
+ * @param {number} type Data type
+ * @param {number} offset
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawRangeElements = function(mode, start, end, count, type, offset) {
+ if (this.conditionalSetError(end < start, gl.INVALID_VALUE))
+ return;
+
+ this.drawElements(mode, count, type, offset);
+ };
+
+ /**
+ * @param {number} mode GL primitive type to draw with.
+ * @param {number} count How many vertices to draw (not counting vertices before first)
+ * @param {number} type Data type
+ * @param {number} offset
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawElements = function(mode, count, type, offset) {
+ this.drawElementsInstanced(mode, count, type, offset, 1);
+ };
+
+ /**
+ * @param {number} mode GL primitive type to draw with.
+ * @param {number} count How many vertices to draw (not counting vertices before first)
+ * @param {number} type Data type
+ * @param {number} offset
+ * @param {number} instanceCount
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawElementsInstanced = function(mode, count, type, offset, instanceCount) {
+ this.drawElementsInstancedBaseVertex(mode, count, type, offset, instanceCount, 0);
+ };
+
+ /**
+ * @param {number} mode GL primitive type to draw with.
+ * @param {number} count How many vertices to draw (not counting vertices before first)
+ * @param {number} type Data type
+ * @param {number} offset
+ * @param {number} instanceCount
+ * @param {number} baseVertex
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawElementsInstancedBaseVertex = function(mode, count, type, offset, instanceCount, baseVertex) {
+ var vao = this.m_vertexArrayBinding;
+
+ if (this.conditionalSetError(type != gl.UNSIGNED_BYTE &&
+ type != gl.UNSIGNED_SHORT &&
+ type != gl.UNSIGNED_INT, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(count < 0 || instanceCount < 0, gl.INVALID_VALUE))
+ return;
+
+ if (!this.predrawErrorChecks(mode))
+ return;
+
+ if (this.conditionalSetError(count > 0 && !vao.m_elementArrayBufferBinding, gl.INVALID_OPERATION))
+ return;
+ // All is ok
+ var data = vao.m_elementArrayBufferBinding.getData();
+ var indices = new rrRenderer.DrawIndices(data, sglrReferenceUtils.mapGLIndexType(type), offset, baseVertex);
+
+ this.drawQuads(mode, indices, count, instanceCount);
+ };
+
+ /**
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} access
+ * @return {Array<number>}
+ */
+ sglrReferenceContext.getBufferRect = function(access) { return [0, 0, access.raw().getHeight(), access.raw().getDepth()]; };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getDrawColorbuffer = function() {
+ if (this.m_drawFramebufferBinding)
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(this.getFboAttachment(this.m_drawFramebufferBinding, sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_COLOR0));
+ return this.m_defaultColorbuffer;
+ };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getDrawDepthbuffer = function() {
+ if (this.m_drawFramebufferBinding)
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(this.getFboAttachment(this.m_drawFramebufferBinding, sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_DEPTH));
+ return this.m_defaultDepthbuffer;
+ };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getDrawStencilbuffer = function() {
+ if (this.m_drawFramebufferBinding)
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(this.getFboAttachment(this.m_drawFramebufferBinding, sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_STENCIL));
+ return this.m_defaultStencilbuffer;
+ };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getReadDepthbuffer = function() {
+ if (this.m_readFramebufferBinding)
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(this.getFboAttachment(this.m_readFramebufferBinding, sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_DEPTH));
+ return this.m_defaultDepthbuffer;
+ };
+
+ /**
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.getReadStencilbuffer = function() {
+ if (this.m_readFramebufferBinding)
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(this.getFboAttachment(this.m_readFramebufferBinding, sglrReferenceContext.AttachmentPoint.ATTACHMENTPOINT_STENCIL));
+ return this.m_defaultStencilbuffer;
+ };
+
+ /**
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} access
+ * @param {number} s
+ * @param {number} x
+ * @param {number} y
+ * @param {number} depth
+ */
+ sglrReferenceContext.writeDepthOnly = function(access, s, x, y, depth) { access.raw().setPixDepth(depth, s, x, y); };
+
+ /**
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} access
+ * @param {number} s
+ * @param {number} x
+ * @param {number} y
+ * @param {number} stencil
+ * @param {number} writeMask
+ */
+ sglrReferenceContext.writeStencilOnly = function(access, s, x, y, stencil, writeMask) {
+ /** @type {number} */ var oldVal = access.raw().getPixelInt(s, x, y)[3];
+ access.raw().setPixStencil((oldVal & ~writeMask) | (stencil & writeMask), s, x, y);
+ };
+
+ /**
+ * @param {number} bits
+ * @param {number} s
+ * @return {number}
+ */
+ sglrReferenceContext.maskStencil = function(bits, s) { return s & ((1 << bits) - 1); };
+
+ /**
+ * @param {number} buffers
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clear = function(buffers) {
+ if (this.conditionalSetError((buffers & ~(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) != 0, gl.INVALID_VALUE))
+ return;
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var colorBuf0 = this.getDrawColorbuffer();
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var depthBuf = this.getDrawDepthbuffer();
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var stencilBuf = this.getDrawStencilbuffer();
+ /** @type {boolean} */ var hasColor0 = /** @type {!boolean} */ (colorBuf0 && !colorBuf0.isEmpty());
+ /** @type {boolean} */ var hasDepth = /** @type {!boolean} */ (depthBuf && !depthBuf.isEmpty());
+ /** @type {boolean} */ var hasStencil = /** @type {!boolean} */ (stencilBuf && !stencilBuf.isEmpty());
+ /** @type {Array<number>} */ var baseArea = this.m_scissorEnabled ? this.m_scissorBox : [0, 0, 0x7fffffff, 0x7fffffff];
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var access;
+ /** @type {boolean} */ var isSharedDepthStencil;
+
+ if (hasColor0 && (buffers & gl.COLOR_BUFFER_BIT) != 0) {
+ /** @type {Array<number>} */ var colorArea = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(colorBuf0));
+ access = colorBuf0.getSubregion(colorArea);
+ /** @type {boolean} */ var isSRGB = colorBuf0.raw().getFormat().isSRGB();
+ /** @type {Array<number>} */ var c = (isSRGB && this.m_sRGBUpdateEnabled) ? tcuTextureUtil.linearToSRGB(this.m_clearColor) : this.m_clearColor;
+ /** @type {boolean} */ var maskUsed = !this.m_colorMask[0] || !this.m_colorMask[1] || !this.m_colorMask[2] || !this.m_colorMask[3];
+ /** @type {boolean} */ var maskZero = !this.m_colorMask[0] && !this.m_colorMask[1] && !this.m_colorMask[2] && !this.m_colorMask[3];
+
+ if (!maskUsed)
+ access.clear(c);
+ else if (!maskZero) {
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ access.raw().setPixel(tcuTextureUtil.select(c, access.raw().getPixel(s, x, y), this.m_colorMask), s, x, y);
+ }
+ // else all channels masked out
+ }
+
+ if (hasDepth && (buffers & gl.DEPTH_BUFFER_BIT) != 0 && this.m_depthMask) {
+ /** @type {Array<number>} */ var depthArea = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(depthBuf));
+ access = depthBuf.getSubregion(depthArea);
+ isSharedDepthStencil = depthBuf.raw().getFormat().order != tcuTexture.ChannelOrder.D;
+
+ if (isSharedDepthStencil) {
+ // Slow path where stencil is masked out in write.
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ sglrReferenceContext.writeDepthOnly(access, s, x, y, this.m_clearDepth);
+ } else
+ access.clear([this.m_clearDepth, 0, 0, 0]);
+ }
+
+ if (hasStencil && (buffers & gl.STENCIL_BUFFER_BIT) != 0) {
+ /** @type {Array<number>} */ var stencilArea = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(stencilBuf));
+ access = stencilBuf.getSubregion(stencilArea);
+ /** @type {number} */ var stencilBits = stencilBuf.raw().getFormat().getNumStencilBits();
+ /** @type {number} */ var stencil = sglrReferenceContext.maskStencil(stencilBits, this.m_clearStencil);
+ isSharedDepthStencil = stencilBuf.raw().getFormat().order != tcuTexture.ChannelOrder.S;
+
+ if (isSharedDepthStencil || ((this.m_stencil[rrDefs.FaceType.FACETYPE_FRONT].writeMask & ((1 << stencilBits) - 1)) != ((1 << stencilBits) - 1))) {
+ // Slow path where depth or stencil is masked out in write.
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ sglrReferenceContext.writeStencilOnly(access, s, x, y, stencil, this.m_stencil[rrDefs.FaceType.FACETYPE_FRONT].writeMask);
+ } else
+ access.clear([0, 0, 0, stencil]);
+ }
+ };
+
+ /**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {Array<number>} value
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearBufferiv = function(buffer, drawbuffer, value) {
+ if (this.conditionalSetError(buffer != gl.COLOR && buffer != gl.STENCIL, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(drawbuffer != 0, gl.INVALID_VALUE))
+ return;
+
+ /** @type {Array<number>} */ var baseArea = this.m_scissorEnabled ? this.m_scissorBox : [0, 0, 0x7fffffff, 0x7fffffff];
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var access;
+
+ if (buffer == gl.COLOR) {
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var colorBuf = this.getDrawColorbuffer();
+ /** @type {boolean} */ var maskUsed = !this.m_colorMask[0] || !this.m_colorMask[1] || !this.m_colorMask[2] || !this.m_colorMask[3];
+ /** @type {boolean} */ var maskZero = !this.m_colorMask[0] && !this.m_colorMask[1] && !this.m_colorMask[2] && !this.m_colorMask[3];
+
+ if (!colorBuf.isEmpty() && !maskZero) {
+ /** @type {Array<number>} */ var colorArea = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(colorBuf));
+ access = colorBuf.getSubregion(colorArea);
+
+ if (!maskUsed)
+ access.clear(value);
+ else {
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ access.raw().setPixel(tcuTextureUtil.select(value, access.raw().getPixel(s, x, y), this.m_colorMask), s, x, y);
+ }
+ }
+ } else {
+ if (buffer !== gl.STENCIL)
+ throw new Error('Unexpected buffer type: ' + buffer);
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var stencilBuf = this.getDrawStencilbuffer();
+
+ if (!stencilBuf.isEmpty() && this.m_stencil[rrDefs.FaceType.FACETYPE_FRONT].writeMask != 0) {
+ /** @type {Array<number>} */ var area = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(stencilBuf));
+ access = stencilBuf.getSubregion(area);
+ /** @type {number} */ var stencil = value[0];
+
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ sglrReferenceContext.writeStencilOnly(access, s, x, y, stencil, this.m_stencil[rrDefs.FaceType.FACETYPE_FRONT].writeMask);
+ }
+ }
+ };
+
+ /**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {Array<number>} value
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearBufferfv = function(buffer, drawbuffer, value) {
+ if (this.conditionalSetError(buffer != gl.COLOR && buffer != gl.DEPTH, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(drawbuffer != 0, gl.INVALID_VALUE))
+ return;
+
+ /** @type {Array<number>} */ var baseArea = this.m_scissorEnabled ? this.m_scissorBox : [0, 0, 0x7fffffff, 0x7fffffff];
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var access;
+ if (buffer == gl.COLOR) {
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var colorBuf = this.getDrawColorbuffer();
+ /** @type {boolean} */ var maskUsed = !this.m_colorMask[0] || !this.m_colorMask[1] || !this.m_colorMask[2] || !this.m_colorMask[3];
+ /** @type {boolean} */ var maskZero = !this.m_colorMask[0] && !this.m_colorMask[1] && !this.m_colorMask[2] && !this.m_colorMask[3];
+
+ if (!colorBuf.isEmpty() && !maskZero) {
+ /** @type {Array<number>} */ var colorArea = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(colorBuf));
+ access = colorBuf.getSubregion(colorArea);
+ var color = value;
+
+ if (this.m_sRGBUpdateEnabled && access.raw().getFormat().isSRGB())
+ color = tcuTextureUtil.linearToSRGB(color);
+
+ if (!maskUsed)
+ access.clear(color);
+ else {
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ access.raw().setPixel(tcuTextureUtil.select(color, access.raw().getPixel(s, x, y), this.m_colorMask), s, x, y);
+ }
+ }
+ } else {
+ if (buffer !== gl.DEPTH)
+ throw new Error('Unexpected buffer type: ' + buffer);
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var depthBuf = this.getDrawDepthbuffer();
+
+ if (!depthBuf.isEmpty() && this.m_depthMask) {
+ /** @type {Array<number>} */ var area = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(depthBuf));
+ access = depthBuf.getSubregion(area);
+ /** @type {number} */ var depth = value[0];
+
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ sglrReferenceContext.writeDepthOnly(access, s, x, y, depth);
+ }
+ }
+ };
+
+ /**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {Array<number>} value
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearBufferuiv = function(buffer, drawbuffer, value) {
+ if (this.conditionalSetError(buffer != gl.COLOR, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(drawbuffer != 0, gl.INVALID_VALUE))
+ return;
+
+ /** @type {Array<number>} */ var baseArea = this.m_scissorEnabled ? this.m_scissorBox : [0, 0, 0x7fffffff, 0x7fffffff];
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var colorBuf = this.getDrawColorbuffer();
+ /** @type {boolean} */ var maskUsed = !this.m_colorMask[0] || !this.m_colorMask[1] || !this.m_colorMask[2] || !this.m_colorMask[3];
+ /** @type {boolean} */ var maskZero = !this.m_colorMask[0] && !this.m_colorMask[1] && !this.m_colorMask[2] && !this.m_colorMask[3];
+
+ if (!colorBuf.isEmpty() && !maskZero) {
+ /** @type {Array<number>} */ var colorArea = deMath.intersect(baseArea, sglrReferenceContext.getBufferRect(colorBuf));
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var access = colorBuf.getSubregion(colorArea);
+
+ if (!maskUsed)
+ access.clear(value);
+ else {
+ for (var y = 0; y < access.raw().getDepth(); y++)
+ for (var x = 0; x < access.raw().getHeight(); x++)
+ for (var s = 0; s < access.getNumSamples(); s++)
+ access.raw().setPixel(tcuTextureUtil.select(value, access.raw().getPixel(s, x, y), this.m_colorMask), s, x, y);
+ }
+ }
+ };
+
+ /**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {number} depth
+ * @param {number} stencil
+ */
+ sglrReferenceContext.ReferenceContext.prototype.clearBufferfi = function(buffer, drawbuffer, depth, stencil) {
+ if (this.conditionalSetError(buffer != gl.DEPTH_STENCIL, gl.INVALID_ENUM))
+ return;
+ this.clearBufferfv(gl.DEPTH, drawbuffer, [depth]);
+ this.clearBufferiv(gl.STENCIL, drawbuffer, [stencil]);
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {sglrReferenceContext.TexTarget} textarget
+ * @param {sglrReferenceContext.TextureContainer} texture
+ * @param {number} level
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.framebufferTexture2D = function(target, attachment, textarget, texture, level) {
+ if (attachment == gl.DEPTH_STENCIL_ATTACHMENT) {
+ // Attach to both depth and stencil.
+ this.framebufferTexture2D(target, gl.DEPTH_ATTACHMENT, textarget, texture, level);
+ this.framebufferTexture2D(target, gl.STENCIL_ATTACHMENT, textarget, texture, level);
+ } else {
+ /** @type {sglrReferenceContext.AttachmentPoint} */ var point = sglrReferenceContext.mapGLAttachmentPoint(attachment);
+ /** @type {sglrReferenceContext.TexTarget} */ var fboTexTarget = sglrReferenceContext.mapGLFboTexTarget(textarget);
+
+ if (this.conditionalSetError(target != gl.FRAMEBUFFER &&
+ target != gl.DRAW_FRAMEBUFFER &&
+ target != gl.READ_FRAMEBUFFER, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(point == undefined, gl.INVALID_ENUM))
+ return;
+
+ // Select binding point.
+ /** @type {sglrReferenceContext.Framebuffer} */ var framebufferBinding = (target == gl.FRAMEBUFFER || target == gl.DRAW_FRAMEBUFFER) ? this.m_drawFramebufferBinding : this.m_readFramebufferBinding;
+ if (this.conditionalSetError(!framebufferBinding, gl.INVALID_OPERATION))
+ return;
+
+ if (texture) {
+ if (this.conditionalSetError(level != 0, gl.INVALID_VALUE))
+ return;
+
+ if (texture.getType() == sglrReferenceContext.TextureType.TYPE_2D) {
+ if (this.conditionalSetError(fboTexTarget != sglrReferenceContext.TexTarget.TEXTARGET_2D, gl.INVALID_OPERATION))
+ return;
+ } else {
+ if (!texture.getType() == sglrReferenceContext.TextureType.TYPE_CUBE_MAP)
+ throw new Error('Unsupported texture type');
+ if (this.conditionalSetError(!deMath.deInRange32(fboTexTarget, sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_POSITIVE_X, sglrReferenceContext.TexTarget.TEXTARGET_CUBE_MAP_NEGATIVE_Z), gl.INVALID_OPERATION))
+ return;
+ }
+ }
+
+ /** @type {sglrReferenceContext.Attachment} */ var fboAttachment = new sglrReferenceContext.Attachment();
+
+ if (texture) {
+ fboAttachment.type = sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_TEXTURE;
+ fboAttachment.object = texture;
+ fboAttachment.texTarget = fboTexTarget;
+ fboAttachment.level = level;
+ }
+ framebufferBinding.setAttachment(point, fboAttachment);
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {sglrReferenceContext.TextureContainer} texture
+ * @param {number} level
+ * @param {number} layer
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.framebufferTextureLayer = function(target, attachment, texture, level, layer) {
+ if (attachment == gl.DEPTH_STENCIL_ATTACHMENT) {
+ // Attach to both depth and stencil.
+ this.framebufferTextureLayer(target, gl.DEPTH_ATTACHMENT, texture, level, layer);
+ this.framebufferTextureLayer(target, gl.STENCIL_ATTACHMENT, texture, level, layer);
+ } else {
+ /** @type {sglrReferenceContext.AttachmentPoint} */ var point = sglrReferenceContext.mapGLAttachmentPoint(attachment);
+
+ if (this.conditionalSetError(target != gl.FRAMEBUFFER &&
+ target != gl.DRAW_FRAMEBUFFER &&
+ target != gl.READ_FRAMEBUFFER, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(point === undefined, gl.INVALID_ENUM))
+ return;
+
+ // Select binding point.
+ /** @type {sglrReferenceContext.Framebuffer} */ var framebufferBinding = (target == gl.FRAMEBUFFER || target == gl.DRAW_FRAMEBUFFER) ? this.m_drawFramebufferBinding : this.m_readFramebufferBinding;
+ if (this.conditionalSetError(!framebufferBinding, gl.INVALID_OPERATION))
+ return;
+
+ if (texture) {
+ if (this.conditionalSetError(level != 0, gl.INVALID_VALUE))
+ return;
+
+ if (this.conditionalSetError(texture.getType() != sglrReferenceContext.TextureType.TYPE_2D_ARRAY &&
+ texture.getType() != sglrReferenceContext.TextureType.TYPE_3D &&
+ texture.getType() != sglrReferenceContext.TextureType.TYPE_CUBE_MAP_ARRAY, gl.INVALID_OPERATION))
+ return;
+
+ if (texture.getType() == sglrReferenceContext.TextureType.TYPE_2D_ARRAY || texture.getType() == sglrReferenceContext.TextureType.TYPE_CUBE_MAP_ARRAY) {
+ if (this.conditionalSetError((layer < 0) || (layer >= gl.MAX_ARRAY_TEXTURE_LAYERS), gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError((level < 0) || (level > Math.floor(Math.log2(gl.MAX_TEXTURE_SIZE))), gl.INVALID_VALUE))
+ return;
+ } else if (texture.getType() == sglrReferenceContext.TextureType.TYPE_3D) {
+ if (this.conditionalSetError((layer < 0) || (layer >= gl.MAX_3D_TEXTURE_SIZE), gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError((level < 0) || (level > Math.floor(Math.log2(gl.MAX_3D_TEXTURE_SIZE))), gl.INVALID_VALUE))
+ return;
+ }
+ }
+
+ /** @type {sglrReferenceContext.Attachment} */ var fboAttachment = new sglrReferenceContext.Attachment();
+
+ if (texture) {
+ fboAttachment.type = sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_TEXTURE;
+ fboAttachment.object = texture;
+ fboAttachment.texTarget = sglrReferenceContext.texLayeredTypeToTarget(texture.getType());
+ fboAttachment.level = level;
+ fboAttachment.layer = layer;
+ }
+ framebufferBinding.setAttachment(point, fboAttachment);
+
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {number} renderbuffertarget
+ * @param {sglrReferenceContext.Renderbuffer} renderbuffer
+ */
+ sglrReferenceContext.ReferenceContext.prototype.framebufferRenderbuffer = function(target, attachment, renderbuffertarget, renderbuffer) {
+ if (attachment == gl.DEPTH_STENCIL_ATTACHMENT) {
+ // Attach both to depth and stencil.
+ this.framebufferRenderbuffer(target, gl.DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer);
+ this.framebufferRenderbuffer(target, gl.STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer);
+ } else {
+ /** @type {sglrReferenceContext.AttachmentPoint} */ var point = sglrReferenceContext.mapGLAttachmentPoint(attachment);
+
+ if (this.conditionalSetError(target != gl.FRAMEBUFFER &&
+ target != gl.DRAW_FRAMEBUFFER &&
+ target != gl.READ_FRAMEBUFFER, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(point == undefined, gl.INVALID_ENUM))
+ return;
+
+ // Select binding point.
+ /** @type {sglrReferenceContext.Framebuffer} */ var framebufferBinding = (target == gl.FRAMEBUFFER || target == gl.DRAW_FRAMEBUFFER) ? this.m_drawFramebufferBinding : this.m_readFramebufferBinding;
+ if (this.conditionalSetError(!framebufferBinding, gl.INVALID_OPERATION))
+ return;
+
+ if (renderbuffer) {
+ if (this.conditionalSetError(renderbuffertarget != gl.RENDERBUFFER, gl.INVALID_ENUM))
+ return;
+ }
+
+ /** @type {sglrReferenceContext.Attachment} */ var fboAttachment = new sglrReferenceContext.Attachment();
+
+ if (renderbuffer) {
+ fboAttachment.type = sglrReferenceContext.AttachmentType.ATTACHMENTTYPE_RENDERBUFFER;
+ fboAttachment.object = renderbuffer;
+ }
+ framebufferBinding.setAttachment(point, fboAttachment);
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.ReferenceContext.prototype.renderbufferStorage = function(target, internalformat, width, height) {
+ /** @type {tcuTexture.TextureFormat} */ var format = gluTextureUtil.mapGLInternalFormat(internalformat);
+
+ if (this.conditionalSetError(target != gl.RENDERBUFFER, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError(!this.m_renderbufferBinding, gl.INVALID_OPERATION))
+ return;
+ if (this.conditionalSetError(!deMath.deInRange32(width, 0, this.m_limits.maxRenderbufferSize) ||
+ !deMath.deInRange32(height, 0, this.m_limits.maxRenderbufferSize),
+ gl.INVALID_OPERATION))
+ return;
+ if (this.conditionalSetError(!format, gl.INVALID_ENUM))
+ return;
+
+ this.m_renderbufferBinding.setStorage(format, width, height);
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} samples
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.ReferenceContext.prototype.renderbufferStorageMultisample = function(target, samples, internalformat, width, height) {
+ this.renderbufferStorage(target, internalformat, width, height);
+ };
+
+ /**
+ * @param {rrRenderer.PrimitiveType} derivedType
+ * @return {rrRenderer.PrimitiveType}
+ * @throws {Error}
+ */
+ sglrReferenceContext.getPrimitiveBaseType = function(derivedType) {
+ switch (derivedType) {
+ case rrRenderer.PrimitiveType.TRIANGLES:
+ case rrRenderer.PrimitiveType.TRIANGLE_STRIP:
+ case rrRenderer.PrimitiveType.TRIANGLE_FAN:
+ return rrRenderer.PrimitiveType.TRIANGLES;
+
+ case rrRenderer.PrimitiveType.LINES:
+ case rrRenderer.PrimitiveType.LINE_STRIP:
+ case rrRenderer.PrimitiveType.LINE_LOOP:
+ return rrRenderer.PrimitiveType.LINES;
+
+ case rrRenderer.PrimitiveType.POINTS:
+ return rrRenderer.PrimitiveType.POINTS;
+
+ default:
+ throw new Error('Unrecognized primitive type:' + derivedType);
+ }
+ };
+
+ /**
+ * createProgram
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @return {sglrShaderProgram.ShaderProgram}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.createProgram = function(program) {
+ return program;
+ };
+
+ /**
+ * deleteProgram
+ * @param {sglrShaderProgram.ShaderProgram} program
+ */
+ sglrReferenceContext.ReferenceContext.prototype.deleteProgram = function(program) {};
+
+ /**
+ * @param {sglrShaderProgram.ShaderProgram} program
+ */
+ sglrReferenceContext.ReferenceContext.prototype.useProgram = function(program) {
+ this.m_currentProgram = program;
+ };
+
+ /**
+ * Draws quads from vertex arrays
+ * @param {number} primitive GL primitive type to draw with.
+ * @param {number} first First vertex to begin drawing with
+ * @param {number} count How many vertices to draw (not counting vertices before first)
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawArrays = function(primitive, first, count) {
+ this.drawQuads(primitive, first, count, 1);
+ };
+
+ /**
+ * Draws quads from vertex arrays
+ * @param {number} primitive GL primitive type to draw with.
+ * @param {(number|rrRenderer.DrawIndices)} first First vertex to begin drawing with
+ * @param {number} count Number of vertices
+ * @param {number=} instances Number of instances
+ */
+ sglrReferenceContext.ReferenceContext.prototype.drawQuads = function(primitive, first, count, instances) {
+ // undefined results
+ if (!this.m_currentProgram)
+ return;
+
+ if (typeof instances === 'undefined')
+ instances = 1;
+
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var colorBuf0 = this.getDrawColorbuffer();
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var depthBuf = this.getDrawDepthbuffer();
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var stencilBuf = this.getDrawStencilbuffer();
+ /** @type {boolean} */ var hasStencil = /** @type {!boolean} */ (stencilBuf && !stencilBuf.isEmpty());
+ /** @type {number} */ var stencilBits = (hasStencil) ? stencilBuf.raw().getFormat().getNumStencilBits() : 0;
+
+ /** @type {rrRenderer.RenderTarget} */ var renderTarget = new rrRenderer.RenderTarget(colorBuf0,
+ depthBuf,
+ stencilBuf);
+ /** @type {sglrShaderProgram.ShaderProgram} */ var program = this.m_currentProgram;
+
+ /*new rrRenderer.Program(
+ * this.m_currentProgram.getVertexShader(),
+ * this.m_currentProgram.getFragmentShader());*/
+
+ /** @type {rrRenderState.ViewportState} */ var viewportState = new rrRenderState.ViewportState(colorBuf0);
+ /** @type {rrRenderState.RenderState} */ var state = new rrRenderState.RenderState(viewportState);
+
+ /** @type {Array<rrVertexAttrib.VertexAttrib>} */ var vertexAttribs = [];
+
+ // Gen state
+ /** @type {rrRenderer.PrimitiveType} */ var baseType = rrRenderer.PrimitiveType.TRIANGLES;
+ /** @type {boolean} */ var polygonOffsetEnabled =
+ (baseType == rrRenderer.PrimitiveType.TRIANGLES) ?
+ (this.m_polygonOffsetFillEnabled) :
+ (false);
+
+ //state.cullMode = m_cullMode
+
+ state.fragOps.scissorTestEnabled = this.m_scissorEnabled;
+ state.fragOps.scissorRectangle = new rrRenderState.WindowRectangle(this.m_scissorBox);
+
+ state.fragOps.numStencilBits = stencilBits;
+ state.fragOps.stencilTestEnabled = this.m_stencilTestEnabled;
+
+ for (var key in rrDefs.FaceType) {
+ /** @type {number} */ var faceType = rrDefs.FaceType[key];
+ state.fragOps.stencilStates[faceType].compMask = this.m_stencil[faceType].opMask;
+ state.fragOps.stencilStates[faceType].writeMask = this.m_stencil[faceType].writeMask;
+ state.fragOps.stencilStates[faceType].ref = this.m_stencil[faceType].ref;
+ state.fragOps.stencilStates[faceType].func = sglrReferenceUtils.mapGLTestFunc(this.m_stencil[faceType].func);
+ state.fragOps.stencilStates[faceType].sFail = sglrReferenceUtils.mapGLStencilOp(this.m_stencil[faceType].opStencilFail);
+ state.fragOps.stencilStates[faceType].dpFail = sglrReferenceUtils.mapGLStencilOp(this.m_stencil[faceType].opDepthFail);
+ state.fragOps.stencilStates[faceType].dpPass = sglrReferenceUtils.mapGLStencilOp(this.m_stencil[faceType].opDepthPass);
+ }
+
+ state.fragOps.depthTestEnabled = this.m_depthTestEnabled;
+ state.fragOps.depthFunc = sglrReferenceUtils.mapGLTestFunc(this.m_depthFunc);
+ state.fragOps.depthMask = this.m_depthMask;
+
+ state.fragOps.blendMode = this.m_blendEnabled ? rrRenderState.BlendMode.STANDARD : rrRenderState.BlendMode.NONE;
+ state.fragOps.blendRGBState.equation = sglrReferenceUtils.mapGLBlendEquation(this.m_blendModeRGB);
+ state.fragOps.blendRGBState.srcFunc = sglrReferenceUtils.mapGLBlendFunc(this.m_blendFactorSrcRGB);
+ state.fragOps.blendRGBState.dstFunc = sglrReferenceUtils.mapGLBlendFunc(this.m_blendFactorDstRGB);
+ state.fragOps.blendAState.equation = sglrReferenceUtils.mapGLBlendEquation(this.m_blendModeAlpha);
+ state.fragOps.blendAState.srcFunc = sglrReferenceUtils.mapGLBlendFunc(this.m_blendFactorSrcAlpha);
+ state.fragOps.blendAState.dstFunc = sglrReferenceUtils.mapGLBlendFunc(this.m_blendFactorDstAlpha);
+ state.fragOps.blendColor = this.m_blendColor;
+
+ state.fragOps.colorMask = this.m_colorMask;
+
+ state.viewport.rect = new rrRenderState.WindowRectangle(this.m_viewport);
+ state.viewport.zn = this.m_depthRangeNear;
+ state.viewport.zf = this.m_depthRangeFar;
+
+ //state.point.pointSize = this.m_pointSize;
+ state.line.lineWidth = this.m_lineWidth;
+
+ state.fragOps.polygonOffsetEnabled = polygonOffsetEnabled;
+ state.fragOps.polygonOffsetFactor = this.m_polygonOffsetFactor;
+ state.fragOps.polygonOffsetUnits = this.m_polygonOffsetUnits;
+
+ state.provokingVertexConvention = (this.m_provokingFirstVertexConvention) ? (rrDefs.ProvokingVertex.PROVOKINGVERTEX_FIRST) : (rrDefs.ProvokingVertex.PROVOKINGVERTEX_LAST);
+
+ // gen attributes
+ /** @type {sglrReferenceContext.VertexArray} */ var vao = this.m_vertexArrayBinding;
+ for (var ndx = 0; ndx < vao.m_arrays.length; ++ndx) {
+ vertexAttribs[ndx] = new rrVertexAttrib.VertexAttrib();
+ if (!vao.m_arrays[ndx].enabled) {
+ vertexAttribs[ndx].type = rrVertexAttrib.VertexAttribType.DONT_CARE; // reading with wrong type is allowed, but results are undefined
+ vertexAttribs[ndx].generic = this.m_currentAttribs[ndx];
+ } else {
+ vertexAttribs[ndx].type = (vao.m_arrays[ndx].integer) ?
+ (sglrReferenceUtils.mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
+ (sglrReferenceUtils.mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size));
+ vertexAttribs[ndx].size = sglrReferenceUtils.mapGLSize(vao.m_arrays[ndx].size);
+ vertexAttribs[ndx].stride = vao.m_arrays[ndx].stride;
+ vertexAttribs[ndx].instanceDivisor = vao.m_arrays[ndx].divisor;
+ vertexAttribs[ndx].pointer = vao.m_arrays[ndx].bufferBinding.getData();
+ vertexAttribs[ndx].offset = vao.m_arrays[ndx].offset;
+ vertexAttribs[ndx].componentCount = vao.m_arrays[ndx].size;
+ }
+ }
+
+ // Set shader samplers
+ for (var uniformNdx = 0; uniformNdx < this.m_currentProgram.m_uniforms.length; ++uniformNdx) {
+ /** @type {number} */ var texNdx = this.m_currentProgram.m_uniforms[uniformNdx].value[0];
+
+ switch (this.m_currentProgram.m_uniforms[uniformNdx].type) {
+ case gluShaderUtil.DataType.SAMPLER_2D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D: {
+ /** @type {sglrReferenceContext.Texture2D} */ var tex;
+
+ if (texNdx >= 0 && texNdx < this.m_textureUnits.length)
+ tex = /** @type {sglrReferenceContext.Texture2D} */ (this.m_textureUnits[texNdx].tex2DBinding.texture);
+
+ if (tex && tex.isComplete()) {
+ tex.updateView();
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = tex;
+ } else
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = this.m_emptyTex2D.texture;
+
+ break;
+ }
+ case gluShaderUtil.DataType.SAMPLER_CUBE:
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE: {
+ /** @type {sglrReferenceContext.TextureCube} */ var texCube;
+
+ if (texNdx >= 0 && texNdx < this.m_textureUnits.length)
+ texCube = /** @type {sglrReferenceContext.TextureCube} */ (this.m_textureUnits[texNdx].texCubeBinding.texture);
+
+ if (texCube && texCube.isComplete()) {
+ texCube.updateView();
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = texCube;
+ } else
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = this.m_emptyTexCube.texture;
+
+ break;
+ }
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY: {
+ /** @type {sglrReferenceContext.Texture2DArray} */ var tex2DArray;
+
+ if (texNdx >= 0 && texNdx < this.m_textureUnits.length)
+ tex2DArray = /** @type {sglrReferenceContext.Texture2DArray} */ (this.m_textureUnits[texNdx].tex2DArrayBinding.texture);
+
+ if (tex2DArray && tex2DArray.isComplete()) {
+ tex2DArray.updateView();
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = tex2DArray;
+ } else
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = this.m_emptyTex2DArray.texture;
+
+ break;
+ }
+ case gluShaderUtil.DataType.SAMPLER_3D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D:
+ case gluShaderUtil.DataType.INT_SAMPLER_3D: {
+ /** @type {sglrReferenceContext.Texture3D} */ var tex3D;
+
+ if (texNdx >= 0 && texNdx < this.m_textureUnits.length)
+ tex3D = /** @type {sglrReferenceContext.Texture3D} */ (this.m_textureUnits[texNdx].tex3DBinding.texture);
+
+ if (tex3D && tex3D.isComplete()) {
+ tex3D.updateView();
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = tex3D;
+ } else
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler = this.m_emptyTex3D.texture;
+
+ break;
+ }
+ /* TODO: Port
+ case gluShaderUtil.DataType.SAMPLER_CUBE_ARRAY:
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE_ARRAY:
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE_ARRAY:{
+ rc::TextureCubeArray* tex = DE_NULL;
+
+ if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.length)
+ tex = (this.m_textureUnits[texNdx].texCubeArrayBinding) ? (this.m_textureUnits[texNdx].texCubeArrayBinding) : (&this.m_textureUnits[texNdx].defaultCubeArrayTex);
+
+ if (tex && tex.isComplete()) {
+ tex.updateView();
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler.texCubeArray = tex;
+ } else
+ this.m_currentProgram.m_uniforms[uniformNdx].sampler.texCubeArray = &this.m_emptyTexCubeArray;
+
+ break;
+ }
+ */
+ default:
+ // nothing
+ break;
+ }
+ }
+
+ var primitiveType = sglrReferenceUtils.mapGLPrimitiveType(primitive);
+
+ var renderFunction = rrRenderer.drawTriangles;
+ if (primitiveType == rrRenderer.PrimitiveType.LINES ||
+ primitiveType == rrRenderer.PrimitiveType.LINE_STRIP ||
+ primitiveType == rrRenderer.PrimitiveType.LINE_LOOP)
+ renderFunction = rrRenderer.drawLines;
+ else if (primitiveType == rrRenderer.PrimitiveType.POINTS)
+ renderFunction = rrRenderer.drawPoints;
+
+ for (var instanceID = 0; instanceID < instances; instanceID++)
+ renderFunction(state, renderTarget, program, vertexAttribs, primitiveType, first, count, instanceID);
+ };
+
+ /**
+ * @param {Array<number>} rect
+ * @return {boolean}
+ */
+ sglrReferenceContext.isEmpty = function(rect) { return rect[2] == 0 || rect[3] == 0; };
+
+ /**
+ * @param {number} mask
+ * @param {Array<number>} srcRect
+ * @param {Array<number>} dstRect
+ * @param {boolean} flipX
+ * @param {boolean} flipY
+ * @throws {Error}
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blitResolveMultisampleFramebuffer = function(mask, srcRect, dstRect, flipX, flipY) {
+ throw new Error('Unimplemented');
+ };
+
+ /**
+ * @param {number} srcX0
+ * @param {number} srcY0
+ * @param {number} srcX1
+ * @param {number} srcY1
+ * @param {number} dstX0
+ * @param {number} dstY0
+ * @param {number} dstX1
+ * @param {number} dstY1
+ * @param {number} mask
+ * @param {number} filter
+ */
+ sglrReferenceContext.ReferenceContext.prototype.blitFramebuffer = function(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter) {
+ // p0 in inclusive, p1 exclusive.
+ // Negative width/height means swap.
+ /** @type {boolean} */ var swapSrcX = srcX1 < srcX0;
+ /** @type {boolean} */ var swapSrcY = srcY1 < srcY0;
+ /** @type {boolean} */ var swapDstX = dstX1 < dstX0;
+ /** @type {boolean} */ var swapDstY = dstY1 < dstY0;
+ /** @type {number} */ var srcW = Math.abs(srcX1 - srcX0);
+ /** @type {number} */ var srcH = Math.abs(srcY1 - srcY0);
+ /** @type {number} */ var dstW = Math.abs(dstX1 - dstX0);
+ /** @type {number} */ var dstH = Math.abs(dstY1 - dstY0);
+ /** @type {boolean} */ var scale = srcW != dstW || srcH != dstH;
+ /** @type {number} */ var srcOriginX = swapSrcX ? srcX1 : srcX0;
+ /** @type {number} */ var srcOriginY = swapSrcY ? srcY1 : srcY0;
+ /** @type {number} */ var dstOriginX = swapDstX ? dstX1 : dstX0;
+ /** @type {number} */ var dstOriginY = swapDstY ? dstY1 : dstY0;
+ /** @type {Array<number>} */ var srcRect = [srcOriginX, srcOriginY, srcW, srcH];
+ /** @type {Array<number>} */ var dstRect = [dstOriginX, dstOriginY, dstW, dstH];
+
+ if (this.conditionalSetError(filter != gl.NEAREST && filter != gl.LINEAR, gl.INVALID_ENUM))
+ return;
+ if (this.conditionalSetError((mask & (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) != 0 && filter != gl.NEAREST, gl.INVALID_OPERATION))
+ return;
+
+ // Validate that both targets are complete.
+ if (this.conditionalSetError(this.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE ||
+ this.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE, gl.INVALID_OPERATION))
+ return;
+
+ // Check samples count is valid
+ if (this.conditionalSetError(this.getDrawColorbuffer().getNumSamples() != 1, gl.INVALID_OPERATION))
+ return;
+
+ // Check size restrictions of multisampled case
+ if (this.getReadColorbuffer().getNumSamples() != 1) {
+ // Src and Dst rect dimensions must be the same
+ if (this.conditionalSetError(srcW != dstW || srcH != dstH, gl.INVALID_OPERATION))
+ return;
+
+ // sglrReferenceContext.Framebuffer formats must match
+ if (mask & gl.COLOR_BUFFER_BIT)
+ if (this.conditionalSetError(this.getReadColorbuffer().raw().getFormat() != this.getDrawColorbuffer().raw().getFormat(), gl.INVALID_OPERATION))
+ return;
+ if (mask & gl.DEPTH_BUFFER_BIT)
+ if (this.conditionalSetError(this.getReadDepthbuffer().raw().getFormat() != this.getDrawDepthbuffer().raw().getFormat(), gl.INVALID_OPERATION))
+ return;
+ if (mask & gl.STENCIL_BUFFER_BIT)
+ if (this.conditionalSetError(this.getReadStencilbuffer().raw().getFormat() != this.getDrawStencilbuffer().raw().getFormat(), gl.INVALID_OPERATION))
+ return;
+ }
+
+ // Compute actual source rect.
+ srcRect = (mask & gl.COLOR_BUFFER_BIT) ? deMath.intersect(srcRect, sglrReferenceContext.getBufferRect(this.getReadColorbuffer())) : srcRect;
+ srcRect = (mask & gl.DEPTH_BUFFER_BIT) ? deMath.intersect(srcRect, sglrReferenceContext.getBufferRect(this.getReadDepthbuffer())) : srcRect;
+ srcRect = (mask & gl.STENCIL_BUFFER_BIT) ? deMath.intersect(srcRect, sglrReferenceContext.getBufferRect(this.getReadStencilbuffer())) : srcRect;
+
+ // Compute destination rect.
+ dstRect = (mask & gl.COLOR_BUFFER_BIT) ? deMath.intersect(dstRect, sglrReferenceContext.getBufferRect(this.getDrawColorbuffer())) : dstRect;
+ dstRect = (mask & gl.DEPTH_BUFFER_BIT) ? deMath.intersect(dstRect, sglrReferenceContext.getBufferRect(this.getDrawDepthbuffer())) : dstRect;
+ dstRect = (mask & gl.STENCIL_BUFFER_BIT) ? deMath.intersect(dstRect, sglrReferenceContext.getBufferRect(this.getDrawStencilbuffer())) : dstRect;
+ dstRect = this.m_scissorEnabled ? deMath.intersect(dstRect, this.m_scissorBox) : dstRect;
+
+ if (sglrReferenceContext.isEmpty(srcRect) || sglrReferenceContext.isEmpty(dstRect))
+ return; // Don't attempt copy.
+
+ // Multisampled read buffer is a special case
+ if (this.getReadColorbuffer().getNumSamples() != 1) {
+ /** @type {boolean} */ var swapX = swapSrcX ^ swapDstX ? true : false;
+ /** @type {boolean} */ var swapY = swapSrcY ^ swapDstY ? true : false;
+ var error = this.blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapX, swapY);
+
+ if (error != gl.NO_ERROR)
+ this.setError(error);
+
+ return;
+ }
+
+ // \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1
+
+ // Coordinate transformation:
+ // Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
+ /** @type {tcuMatrix.Matrix} */ var matrix = tcuMatrixUtil.translationMatrix([srcX0 - srcRect[0], srcY0 - srcRect[1]]);
+ matrix = tcuMatrix.multiply(matrix, tcuMatrix.matrixFromVector(3, 3, [(srcX1 - srcX0) / (dstX1 - dstX0), (srcY1 - srcY0) / (dstY1 - dstY0), 1]));
+ matrix = tcuMatrix.multiply(matrix, tcuMatrixUtil.translationMatrix([dstRect[0] - dstX0, dstRect[1] - dstY0]));
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ var transform = function(x, y) { return matrix.get(x, y); };
+
+ /** @type {number} */ var dX;
+ /** @type {number} */ var dY;
+ /** @type {number} */ var sX;
+ /** @type {number} */ var sY;
+ /** @type {tcuTexture.PixelBufferAccess|rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var src;
+ /** @type {tcuTexture.PixelBufferAccess|rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var dst;
+
+ if (mask & gl.COLOR_BUFFER_BIT) {
+ src = tcuTextureUtil.getSubregion(this.getReadColorbuffer().toSinglesampleAccess(), srcRect[0], srcRect[1], 0, srcRect[2], srcRect[3], 1);
+ dst = tcuTextureUtil.getSubregion(this.getDrawColorbuffer().toSinglesampleAccess(), dstRect[0], dstRect[1], 0, dstRect[2], dstRect[3], 1);
+ /** @type {tcuTexture.TextureChannelClass} */ var dstClass = tcuTexture.getTextureChannelClass(dst.getFormat().type);
+ /** @type {boolean} */ var dstIsFloat = dstClass == tcuTexture.TextureChannelClass.FLOATING_POINT ||
+ dstClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ||
+ dstClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT;
+ /** @type {tcuTexture.FilterMode} */ var sFilter = (scale && filter == gl.LINEAR) ? tcuTexture.FilterMode.LINEAR : tcuTexture.FilterMode.NEAREST;
+ /** @type {tcuTexture.Sampler} */ var sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ sFilter, sFilter, 0.0 /* lod threshold */, false /* non-normalized coords */);
+ /** @type {boolean} */ var srcIsSRGB = src.getFormat().order == tcuTexture.ChannelOrder.sRGB || src.getFormat().order == tcuTexture.ChannelOrder.sRGBA;
+ /** @type {boolean} */ var dstIsSRGB = dst.getFormat().order == tcuTexture.ChannelOrder.sRGB || dst.getFormat().order == tcuTexture.ChannelOrder.sRGBA;
+ /** @type {boolean} */ var convertSRGB = this.m_sRGBUpdateEnabled;
+
+ // \note We don't check for unsupported conversions, unlike spec requires.
+
+ for (var yo = 0; yo < dstRect[3]; yo++) {
+ for (var xo = 0; xo < dstRect[2]; xo++) {
+ dX = xo + 0.5;
+ dY = yo + 0.5;
+
+ // \note Only affine part is used.
+ sX = transform(0, 0) * dX + transform(0, 1) * dY + transform(0, 2);
+ sY = transform(1, 0) * dX + transform(1, 1) * dY + transform(1, 2);
+
+ // do not copy pixels outside the modified source region (modified by buffer intersection)
+ if (sX < 0.0 || sX >= srcRect[2] ||
+ sY < 0.0 || sY >= srcRect[3])
+ continue;
+
+ if (dstIsFloat || srcIsSRGB || filter == tcuTexture.FilterMode.LINEAR) {
+ /** @type {Array<number>} */ var p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
+ dst.setPixel((dstIsSRGB && convertSRGB) ? tcuTextureUtil.linearToSRGB(p) : p, xo, yo);
+ } else
+ dst.setPixelInt(src.getPixelInt(Math.floor(sX), Math.floor(sY)), xo, yo);
+ }
+ }
+ }
+
+ if ((mask & gl.DEPTH_BUFFER_BIT) && this.m_depthMask) {
+ src = this.getReadDepthbuffer().getSubregion(srcRect);
+ dst = this.getDrawDepthbuffer().getSubregion(dstRect);
+
+ for (var yo = 0; yo < dstRect[3]; yo++) {
+ for (var xo = 0; xo < dstRect[2]; xo++) {
+ var sampleNdx = 0; // multisample read buffer case is already handled
+
+ dX = xo + 0.5;
+ dY = yo + 0.5;
+ sX = transform(0, 0) * dX + transform(0, 1) * dY + transform(0, 2);
+ sY = transform(1, 0) * dX + transform(1, 1) * dY + transform(1, 2);
+
+ sglrReferenceContext.writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixel(sampleNdx, Math.floor(sX), Math.floor(sY))[0]);
+ }
+ }
+ }
+
+ if (mask & gl.STENCIL_BUFFER_BIT) {
+ src = this.getReadStencilbuffer().getSubregion(srcRect);
+ dst = this.getDrawStencilbuffer().getSubregion(dstRect);
+
+ for (var yo = 0; yo < dstRect[3]; yo++) {
+ for (var xo = 0; xo < dstRect[2]; xo++) {
+ var sampleNdx = 0; // multisample read buffer case is already handled
+
+ dX = xo + 0.5;
+ dY = yo + 0.5;
+ sX = transform(0, 0) * dX + transform(0, 1) * dY + transform(0, 2);
+ sY = transform(1, 0) * dX + transform(1, 1) * dY + transform(1, 2);
+
+ sglrReferenceContext.writeStencilOnly(dst, sampleNdx, xo, yo, src.raw().getPixelInt(sampleNdx, Math.floor(sX), Math.floor(sY))[3], this.m_stencil[rrDefs.FaceType.FACETYPE_FRONT].writeMask);
+ }
+ }
+ }
+ };
+
+ /**
+ * @param {number} internalFormat
+ * @return {tcuTexture.TextureFormat}
+ */
+ sglrReferenceContext.mapInternalFormat = function(internalFormat) {
+ switch (internalFormat) {
+ case gl.ALPHA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.A, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.LUMINANCE: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.L, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.LUMINANCE_ALPHA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.LA, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.RGB: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
+ case gl.RGBA: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+
+ default:
+ return gluTextureUtil.mapGLInternalFormat(internalFormat);
+ }
+ };
+
+ /**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {tcuTexture.ConstPixelBufferAccess} src
+ */
+ sglrReferenceContext.depthValueFloatClampCopy = function(dst, src) {
+ /** @type {number} */ var width = dst.getWidth();
+ /** @type {number} */ var height = dst.getHeight();
+ /** @type {number} */ var depth = dst.getDepth();
+
+ DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);
+
+ // clamping copy
+ for (var z = 0; z < depth; z++)
+ for (var y = 0; y < height; y++)
+ for (var x = 0; x < width; x++) {
+ /** @type {Array<number>} */ var data = src.getPixel(x, y, z);
+ dst.setPixel([deMath.clamp(data[0], 0.0, 1.0), data[1], data[2], data[3]], x, y, z);
+ }
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.ReferenceContext.prototype.texImage2DDelegate = function (target, level, internalFormat, width, height) {
+ var format;
+ var dataType;
+
+ switch (internalFormat)
+ {
+ case gl.ALPHA:
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ case gl.RGB:
+ case gl.RGBA:
+ format = internalFormat;
+ dataType = GL.UNSIGNED_BYTE;
+ break;
+ default:
+ {
+ var transferFmt = gluTextureUtil.getTransferFormat(gluTextureUtil.mapGLInternalFormat(internalFormat));
+ format = transferFmt.format;
+ dataType = transferFmt.dataType;
+ break;
+ }
+ }
+ this.texImage2D(target, level, internalFormat, width, height, 0, format, dataType, null);
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} border
+ * @param {number} format
+ * @param {number} type
+ * @param {number} pixels
+ */
+ sglrReferenceContext.ReferenceContext.prototype.texImage2D = function(target, level, internalFormat, width, height, border, format, type, pixels) {
+ this.texImage3D(target, level, internalFormat, width, height, 1, border, format, type, pixels);
+ };
+
+ sglrReferenceContext.ReferenceContext.prototype.texImage3D = function(target, level, internalFormat, width, height, depth, border, format, type, pixels) {
+ /** @type {sglrReferenceContext.TextureUnit} */var unit = this.m_textureUnits[this.m_activeTexture];
+ /** @type {ArrayBuffer} */ var data = null;
+ /** @type {number} */ var offset = 0;
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst;
+ /** @type {tcuTexture.ConstPixelBufferAccess} */ var src;
+ if (this.m_pixelUnpackBufferBinding) {
+ if (this.conditionalSetError(typeof pixels !== 'number', gl.INVALID_VALUE))
+ return;
+ data = this.m_pixelUnpackBufferBinding.getData();
+ offset = pixels;
+ } else if (pixels) {
+ if (pixels instanceof ArrayBuffer) {
+ data = pixels;
+ offset = 0;
+ } else {
+ data = pixels.buffer;
+ offset = pixels.byteOffset;
+ }
+ }
+ /** @type {boolean} */ var isDstFloatDepthFormat = (internalFormat == gl.DEPTH_COMPONENT32F || internalFormat == gl.DEPTH32F_STENCIL8); // depth components are limited to [0,1] range
+
+ if (this.conditionalSetError(border != 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(width < 0 || height < 0 || depth < 0 || level < 0, gl.INVALID_VALUE))
+ return;
+
+ // Map storage format.
+ /** @type {tcuTexture.TextureFormat} */ var storageFmt = sglrReferenceContext.mapInternalFormat(internalFormat);
+ if (this.conditionalSetError(!storageFmt, gl.INVALID_ENUM))
+ return;
+
+ // Map transfer format.
+ /** @type {tcuTexture.TextureFormat} */ var transferFmt = gluTextureUtil.mapGLTransferFormat(format, type);
+ if (this.conditionalSetError(!transferFmt, gl.INVALID_ENUM))
+ return;
+
+ if (target == gl.TEXTURE_2D) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize || height > this.m_limits.maxTexture2DSize || depth != 1, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.log2(this.m_limits.maxTexture2DSize), gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2D} */
+ var texture = /** @type {sglrReferenceContext.Texture2D} */ (unit.tex2DBinding.texture);
+
+ if (texture.isImmutable()) {
+ if (this.conditionalSetError(!texture.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ //NOTE: replaces this: var dst = tcuTexture.PixelBufferAccess.newFromTextureLevel(texture.getLevel(level));
+ dst = texture.getLevel(level);
+
+ if (this.conditionalSetError(!storageFmt.isEqual(dst.getFormat()) ||
+ width != dst.getWidth() ||
+ height != dst.getHeight(), gl.INVALID_OPERATION))
+ return;
+ } else
+ texture.allocLevel(level, storageFmt, width, height);
+
+ if (data) {
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var skip = this.m_pixelUnpackSkipRows * rowPitch + this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ rowPitch: rowPitch,
+ data: data,
+ offset: offset + skip});
+
+ //NOTE: replaces this: var dst = tcuTexture.PixelBufferAccess.newFromTextureLevel(texture.getLevel(level));
+ dst = texture.getLevel(level);
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(dst, src);
+ else
+ tcuTextureUtil.copy(dst, src);
+ } else {
+ // No data supplied, clear to black.
+
+ //NOTE: replaces this: var dst = tcuTexture.PixelBufferAccess.newFromTextureLevel(texture.getLevel(level));
+ dst = texture.getLevel(level);
+ dst.clear([0.0, 0.0, 0.0, 1.0]);
+ }
+ } else if (target == gl.TEXTURE_CUBE_MAP_NEGATIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Z) {
+ // Validate size and level.
+ if (this.conditionalSetError(width != height || width > this.m_limits.maxTextureCubeSize || depth != 1, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTextureCubeSize)), gl.INVALID_VALUE))
+ return;
+
+ var textureCube = /** @type {sglrReferenceContext.TextureCube} */ (unit.texCubeBinding.texture);
+
+ var face = sglrReferenceContext.mapGLCubeFace(target);
+
+ if (textureCube.isImmutable()) {
+ if (this.conditionalSetError(!textureCube.hasFace(level, face), gl.INVALID_OPERATION))
+ return;
+
+ dst = textureCube.getFace(level, face);
+
+ if (this.conditionalSetError(!storageFmt.isEqual(dst.getFormat()) ||
+ width != dst.getWidth() ||
+ height != dst.getHeight(), gl.INVALID_OPERATION))
+ return;
+ } else
+ textureCube.allocLevel(level, face, storageFmt, width, height);
+
+ if (data) {
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var skip = this.m_pixelUnpackSkipRows * rowPitch + this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ rowPitch: rowPitch,
+ data: data,
+ offset: offset + skip});
+
+ dst = textureCube.getFace(level, face);
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(dst, src);
+ else
+ tcuTextureUtil.copy(dst, src);
+ } else {
+ // No data supplied, clear to black.
+ dst = textureCube.getFace(level, face);
+ dst.clear([0.0, 0.0, 0.0, 1.0]);
+ }
+ } else if (target == gl.TEXTURE_2D_ARRAY) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize ||
+ height > this.m_limits.maxTexture2DSize ||
+ depth > this.m_limits.maxTexture2DArrayLayers, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTexture2DSize)), gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2DArray} */
+ var texture2DArray = /** @type {sglrReferenceContext.Texture2DArray} */ (unit.tex2DArrayBinding.texture);
+
+ if (texture2DArray.isImmutable()) {
+ if (this.conditionalSetError(!texture2DArray.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ dst = texture2DArray.getLevel(level);
+ if (this.conditionalSetError(!storageFmt.isEqual(dst.getFormat()) ||
+ width != dst.getWidth() ||
+ height != dst.getHeight() ||
+ depth != dst.getDepth(), gl.INVALID_OPERATION))
+ return;
+ } else
+ texture2DArray.allocLevel(level, storageFmt, width, height, depth);
+
+ if (data) {
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var imageHeight = this.m_pixelUnpackImageHeight > 0 ? this.m_pixelUnpackImageHeight : height;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var slicePitch = imageHeight * rowPitch;
+ var skip = this.m_pixelUnpackSkipImages * slicePitch + this.m_pixelUnpackSkipRows * rowPitch +
+ this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ depth: depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: offset + skip});
+
+ dst = texture2DArray.getLevel(level);
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(dst, src);
+ else
+ tcuTextureUtil.copy(dst, src);
+ } else {
+ // No data supplied, clear to black.
+ dst = texture2DArray.getLevel(level);
+ dst.clear([0.0, 0.0, 0.0, 1.0]);
+ }
+ } else if (target == gl.TEXTURE_3D) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture3DSize ||
+ height > this.m_limits.maxTexture3DSize ||
+ depth > this.m_limits.maxTexture3DSize, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTexture3DSize)), gl.INVALID_VALUE))
+ return;
+
+ var texture3D = /** @type {sglrReferenceContext.Texture3D} */ (unit.tex3DBinding.texture);
+
+ if (texture3D.isImmutable()) {
+ if (this.conditionalSetError(!texture3D.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ dst = texture3D.getLevel(level);
+ if (this.conditionalSetError(!storageFmt.isEqual(dst.getFormat()) ||
+ width != dst.getWidth() ||
+ height != dst.getHeight() ||
+ depth != dst.getDepth(), gl.INVALID_OPERATION))
+ return;
+ } else
+ texture3D.allocLevel(level, storageFmt, width, height, depth);
+
+ if (data) {
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var imageHeight = this.m_pixelUnpackImageHeight > 0 ? this.m_pixelUnpackImageHeight : height;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var slicePitch = imageHeight * rowPitch;
+ var skip = this.m_pixelUnpackSkipImages * slicePitch + this.m_pixelUnpackSkipRows * rowPitch +
+ this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ depth: depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: offset + skip});
+
+ dst = texture3D.getLevel(level);
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(dst, src);
+ else
+ tcuTextureUtil.copy(dst, src);
+
+ } else {
+ // No data supplied, clear to black.
+ dst = texture3D.getLevel(level);
+ dst.clear([0.0, 0.0, 0.0, 1.0]);
+ }
+ }
+ // else if (target == gl.TEXTURE_CUBE_MAP_ARRAY)
+ // {
+ // // Validate size and level.
+ // RC_IF_ERROR(width != height ||
+ // width > m_limits.maxTexture2DSize ||
+ // depth % 6 != 0 ||
+ // depth > m_limits.maxTexture2DArrayLayers, gl.INVALID_VALUE, RC_RET_VOID);
+ // RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), gl.INVALID_VALUE, RC_RET_VOID);
+
+ // TextureCubeArray* texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex;
+
+ // if (texture->isImmutable())
+ // {
+ // RC_IF_ERROR(!texture->hasLevel(level), gl.INVALID_OPERATION, RC_RET_VOID);
+
+ // ConstPixelBufferAccess dst(texture->getLevel(level));
+ // RC_IF_ERROR(storageFmt != dst.getFormat() ||
+ // width != dst.getWidth() ||
+ // height != dst.getHeight() ||
+ // depth != dst.getDepth(), gl.INVALID_OPERATION, RC_RET_VOID);
+ // }
+ // else
+ // texture->allocLevel(level, storageFmt, width, height, depth);
+
+ // if (unpackPtr)
+ // {
+ // ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
+ // PixelBufferAccess dst (texture->getLevel(level));
+
+ // if (isDstFloatDepthFormat)
+ // sglrReferenceContext.depthValueFloatClampCopy(dst, src);
+ // else
+ // tcu::copy(dst, src);
+ // }
+ // else
+ // {
+ // // No data supplied, clear to black.
+ // PixelBufferAccess dst = texture->getLevel(level);
+ // tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+ // }
+ // } /**/
+ else
+ this.setError(gl.INVALID_ENUM);
+ };
+
+ sglrReferenceContext.ReferenceContext.prototype.texSubImage2D = function(target, level, xoffset, yoffset, width, height, format, type, pixels) {
+ this.texSubImage3D(target, level, xoffset, yoffset, 0, width, height, 1, format, type, pixels);
+ };
+
+ sglrReferenceContext.ReferenceContext.prototype.texSubImage3D = function(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) {
+ /** @type {sglrReferenceContext.TextureUnit} */var unit = this.m_textureUnits[this.m_activeTexture];
+ /** @type {ArrayBuffer} */ var data = null;
+ /** @type {number} */ var offset = 0;
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst;
+ /** @type {tcuTexture.PixelBufferAccess} */ var sub;
+ /** @type {tcuTexture.ConstPixelBufferAccess} */ var src;
+ /** @type {boolean} */ var isDstFloatDepthFormat;
+ if (this.m_pixelUnpackBufferBinding) {
+ if (this.conditionalSetError(typeof pixels !== 'number', gl.INVALID_VALUE))
+ return;
+ data = this.m_pixelUnpackBufferBinding.getData();
+ offset = pixels;
+ } else if (pixels) {
+ if (pixels instanceof ArrayBuffer) {
+ data = pixels;
+ offset = 0;
+ } else {
+ data = pixels.buffer;
+ offset = pixels.byteOffset;
+ }
+ }
+
+ if (this.conditionalSetError(xoffset < 0 || yoffset < 0 || zoffset < 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(width < 0 || height < 0 || depth < 0 || level < 0, gl.INVALID_VALUE))
+ return;
+
+ // Map transfer format.
+ /** @type {tcuTexture.TextureFormat} */ var transferFmt = gluTextureUtil.mapGLTransferFormat(format, type);
+ if (this.conditionalSetError(!transferFmt, gl.INVALID_ENUM))
+ return;
+
+ if (target == gl.TEXTURE_2D) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize || height > this.m_limits.maxTexture2DSize || depth != 1, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.log2(this.m_limits.maxTexture2DSize), gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2D} */
+ var texture = /** @type {sglrReferenceContext.Texture2D} */ (unit.tex2DBinding.texture);
+
+ if (this.conditionalSetError(!texture.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ //NOTE: replaces this: var dst = tcuTexture.PixelBufferAccess.newFromTextureLevel(texture.getLevel(level));
+ dst = texture.getLevel(level);
+
+ if (this.conditionalSetError(xoffset + width > dst.getWidth() ||
+ yoffset + height > dst.getHeight() ||
+ zoffset + depth > dst.getDepth(),
+ gl.INVALID_VALUE))
+ return;
+
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var skip = this.m_pixelUnpackSkipRows * rowPitch + this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ rowPitch: rowPitch,
+ data: data,
+ offset: offset + skip});
+
+ sub = tcuTextureUtil.getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth);
+ isDstFloatDepthFormat = (dst.getFormat().order == tcuTexture.ChannelOrder.D || dst.getFormat().order == tcuTexture.ChannelOrder.DS); // depth components are limited to [0,1] range
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(sub, src);
+ else
+ tcuTextureUtil.copy(sub, src);
+ } else if (target == gl.TEXTURE_CUBE_MAP_NEGATIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Z) {
+ var textureCube = /** @type {sglrReferenceContext.TextureCube} */ (unit.texCubeBinding.texture);
+
+ var face = sglrReferenceContext.mapGLCubeFace(target);
+
+ if (this.conditionalSetError(!textureCube.hasFace(level, face), gl.INVALID_OPERATION))
+ return;
+
+ dst = textureCube.getFace(level, face);
+
+ if (this.conditionalSetError(xoffset + width > dst.getWidth() ||
+ yoffset + height > dst.getHeight() ||
+ zoffset + depth > dst.getDepth(),
+ gl.INVALID_VALUE))
+ return;
+
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var skip = this.m_pixelUnpackSkipRows * rowPitch + this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ rowPitch: rowPitch,
+ slicePitach: slicePitch,
+ data: data,
+ offset: offset + skip});
+
+ sub = tcuTextureUtil.getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth);
+ isDstFloatDepthFormat = (dst.getFormat().order == tcuTexture.ChannelOrder.D || dst.getFormat().order == tcuTexture.ChannelOrder.DS); // depth components are limited to [0,1] range
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(sub, src);
+ else
+ tcuTextureUtil.copy(sub, src);
+ } else if (target == gl.TEXTURE_2D_ARRAY) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize ||
+ height > this.m_limits.maxTexture2DSize ||
+ depth > this.m_limits.maxTexture2DArrayLayers, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTexture2DSize)), gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2DArray} */
+ var texture2DArray = /** @type {sglrReferenceContext.Texture2DArray} */ (unit.tex2DArrayBinding.texture);
+
+ if (this.conditionalSetError(!texture2DArray.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ dst = texture2DArray.getLevel(level);
+ if (this.conditionalSetError(xoffset + width > dst.getWidth() ||
+ yoffset + height > dst.getHeight() ||
+ zoffset + depth > dst.getDepth(),
+ gl.INVALID_VALUE))
+ return;
+
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var imageHeight = this.m_pixelUnpackImageHeight > 0 ? this.m_pixelUnpackImageHeight : height;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var slicePitch = imageHeight * rowPitch;
+ var skip = this.m_pixelUnpackSkipImages * slicePitch + this.m_pixelUnpackSkipRows * rowPitch +
+ this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ depth: depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: offset + skip});
+
+ sub = tcuTextureUtil.getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth);
+ isDstFloatDepthFormat = (dst.getFormat().order == tcuTexture.ChannelOrder.D || dst.getFormat().order == tcuTexture.ChannelOrder.DS); // depth components are limited to [0,1] range
+
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(sub, src);
+ else
+ tcuTextureUtil.copy(sub, src);
+ } else if (target == gl.TEXTURE_3D) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture3DSize ||
+ height > this.m_limits.maxTexture3DSize ||
+ depth > this.m_limits.maxTexture3DSize, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTexture3DSize)), gl.INVALID_VALUE))
+ return;
+
+ var texture3D = /** @type {sglrReferenceContext.Texture3D} */ (unit.tex3DBinding.texture);
+
+ if (this.conditionalSetError(!texture3D.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ dst = texture3D.getLevel(level);
+ if (this.conditionalSetError(xoffset + width > dst.getWidth() ||
+ yoffset + height > dst.getHeight() ||
+ zoffset + depth > dst.getDepth(),
+ gl.INVALID_VALUE))
+ return;
+
+ var rowLen = this.m_pixelUnpackRowLength > 0 ? this.m_pixelUnpackRowLength : width;
+ var imageHeight = this.m_pixelUnpackImageHeight > 0 ? this.m_pixelUnpackImageHeight : height;
+ var rowPitch = deMath.deAlign32(rowLen * transferFmt.getPixelSize(), this.m_pixelUnpackAlignment);
+ var slicePitch = imageHeight * rowPitch;
+ var skip = this.m_pixelUnpackSkipImages * slicePitch + this.m_pixelUnpackSkipRows * rowPitch +
+ this.m_pixelUnpackSkipPixels * transferFmt.getPixelSize();
+ src = new tcuTexture.ConstPixelBufferAccess({
+ format: transferFmt,
+ width: width,
+ height: height,
+ depth: depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: offset + skip});
+
+ sub = tcuTextureUtil.getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth);
+
+ isDstFloatDepthFormat = (dst.getFormat().order == tcuTexture.ChannelOrder.D || dst.getFormat().order == tcuTexture.ChannelOrder.DS); // depth components are limited to [0,1] range
+ if (isDstFloatDepthFormat)
+ sglrReferenceContext.depthValueFloatClampCopy(sub, src);
+ else
+ tcuTextureUtil.copy(sub, src);
+ } else
+ this.setError(gl.INVALID_ENUM);
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalFormat
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {number} border
+ */
+ sglrReferenceContext.ReferenceContext.prototype.copyTexImage2D = function(target, level, internalFormat, x, y, width, height, border) {
+ /** @type {sglrReferenceContext.TextureUnit} */var unit = this.m_textureUnits[this.m_activeTexture];
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var src = this.getReadColorbuffer();
+
+ if (this.conditionalSetError(border != 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(width < 0 || height < 0 || level < 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(src.isEmpty(), gl.INVALID_OPERATION))
+ return;
+
+ // Map storage format.
+ /** @type {tcuTexture.TextureFormat} */ var storageFmt = sglrReferenceContext.mapInternalFormat(internalFormat);
+ if (this.conditionalSetError(!storageFmt, gl.INVALID_ENUM))
+ return;
+
+ if (target == gl.TEXTURE_2D) {
+ // Validate size and level.
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize || height > this.m_limits.maxTexture2DSize, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTexture2DSize)), gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2D} */
+ var texture = /** @type {sglrReferenceContext.Texture2D} */ (unit.tex2DBinding.texture);
+
+ if (texture.isImmutable()) {
+ if (this.conditionalSetError(!texture.hasLevel(level), gl.INVALID_OPERATION))
+ return;
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst = texture.getLevel(level);
+ if (this.conditionalSetError(storageFmt != dst.getFormat() || width != dst.getWidth() || height != dst.getHeight(), gl.INVALID_OPERATION))
+ return;
+ } else {
+ texture.allocLevel(level, storageFmt, width, height);
+ }
+
+ // Copy from current framebuffer.
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst = texture.getLevel(level);
+ for (var yo = 0; yo < height; yo++) {
+ for (var xo = 0; xo < width; xo++) {
+ if (!deMath.deInBounds32(x+xo, 0, src.raw().getHeight()) || !deMath.deInBounds32(y+yo, 0, src.raw().getDepth()))
+ continue; // Undefined pixel.
+
+ dst.setPixel(src.resolveMultisamplePixel(x+xo, y+yo), xo, yo);
+ }
+ }
+ } else if (target == gl.TEXTURE_CUBE_MAP_NEGATIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Z) {
+ // Validate size and level.
+ if (this.conditionalSetError(width != height || width > this.m_limits.maxTextureCubeSize, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(level > Math.floor(Math.log2(this.m_limits.maxTextureCubeSize)), gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.TextureCube} */
+ var texture = /** @type {sglrReferenceContext.TextureCube} */ (unit.texCubeBinding.texture);
+ var face = sglrReferenceContext.mapGLCubeFace(target);
+
+ if (texture.isImmutable()) {
+ if (this.conditionalSetError(!texture.hasFace(level, face), gl.INVALID_OPERATION))
+ return;
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst = texture.getFace(level, face);
+ if (this.conditionalSetError(storageFmt != dst.getFormat() || width != dst.getWidth() || height != dst.getHeight(), gl.INVALID_OPERATION))
+ return;
+ } else {
+ texture.allocLevel(level, face, storageFmt, width, height);
+ }
+
+ // Copy from current framebuffer.
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst = texture.getFace(level, face);
+ for (var yo = 0; yo < height; yo++) {
+ for (var xo = 0; xo < width; xo++) {
+ if (!deMath.deInBounds32(x+xo, 0, src.raw().getHeight()) || !deMath.deInBounds32(y+yo, 0, src.raw().getDepth()))
+ continue; // Undefined pixel.
+
+ dst.setPixel(src.resolveMultisamplePixel(x+xo, y+yo), xo, yo);
+ }
+ }
+ } else {
+ this.setError(gl.INVALID_ENUM);
+ }
+ }
+
+ /**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+ sglrReferenceContext.ReferenceContext.prototype.copyTexSubImage2D = function(target, level, xoffset, yoffset, x, y, width, height) {
+ /** @type {sglrReferenceContext.TextureUnit} */var unit = this.m_textureUnits[this.m_activeTexture];
+ /** @type {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} */ var src = this.getReadColorbuffer();
+
+ if (this.conditionalSetError(xoffset < 0 || yoffset < 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(width < 0 || height < 0 || level < 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(src.isEmpty(), gl.INVALID_OPERATION))
+ return;
+
+ if (target == gl.TEXTURE_2D) {
+ /** @type {sglrReferenceContext.Texture2D} */
+ var texture = /** @type {sglrReferenceContext.Texture2D} */ (unit.tex2DBinding.texture);
+
+ if (this.conditionalSetError(!texture.hasLevel(level), gl.INVALID_VALUE))
+ return;
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst = texture.getLevel(level);
+
+ if (this.conditionalSetError(xoffset + width > dst.getWidth() || yoffset + height > dst.getHeight(), gl.INVALID_VALUE))
+ return;
+
+ for (var yo = 0; yo < height; yo++) {
+ for (var xo = 0; xo < width; xo++) {
+ if (!deMath.deInBounds32(x+xo, 0, src.raw().getHeight()) || !deMath.deInBounds32(y+yo, 0, src.raw().getDepth()))
+ continue;
+
+ dst.setPixel(src.resolveMultisamplePixel(x+xo, y+yo), xo+xoffset, yo+yoffset);
+ }
+ }
+ } else if (target == gl.TEXTURE_CUBE_MAP_NEGATIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_X ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Y ||
+ target == gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ||
+ target == gl.TEXTURE_CUBE_MAP_POSITIVE_Z) {
+ /** @type {sglrReferenceContext.TextureCube} */
+ var texture = /** @type {sglrReferenceContext.TextureCube} */ (unit.texCubeBinding.texture);
+ var face = sglrReferenceContext.mapGLCubeFace(target);
+
+ if (this.conditionalSetError(!texture.hasFace(level, face), gl.INVALID_VALUE))
+ return;
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var dst = texture.getFace(level, face);
+
+ if (this.conditionalSetError(xoffset + width > dst.getWidth() || yoffset + height > dst.getHeight(), gl.INVALID_VALUE))
+ return;
+
+ for (var yo = 0; yo < height; yo++) {
+ for (var xo = 0; xo < width; xo++) {
+ if (!deMath.deInBounds32(x+xo, 0, src.raw().getHeight()) || !deMath.deInBounds32(y+yo, 0, src.raw().getDepth()))
+ continue;
+
+ dst.setPixel(src.resolveMultisamplePixel(x+xo, y+yo), xo+xoffset, yo+yoffset);
+ }
+ }
+ } else {
+ this.setError(gl.INVALID_ENUM);
+ }
+ }
+
+ sglrReferenceContext.ReferenceContext.prototype.texStorage3D = function(target, levels, internalFormat, width, height, depth) {
+ /** @type {sglrReferenceContext.TextureUnit} */var unit = this.m_textureUnits[this.m_activeTexture];
+
+ if (this.conditionalSetError(width <= 0 || height <= 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(levels < 1 || levels > Math.floor(Math.log2(Math.max(width, height))) + 1, gl.INVALID_VALUE))
+ return;
+
+ // Map storage format.
+ /** @type {tcuTexture.TextureFormat} */ var storageFmt = sglrReferenceContext.mapInternalFormat(internalFormat);
+ if (this.conditionalSetError(!storageFmt, gl.INVALID_ENUM))
+ return;
+
+ if (target == gl.TEXTURE_2D_ARRAY) {
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize ||
+ height > this.m_limits.maxTexture2DSize ||
+ depth >= this.m_limits.maxTexture2DArrayLayers, gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2DArray} */
+ var textureArray = /** @type {sglrReferenceContext.Texture2DArray} */ (unit.tex2DArrayBinding.texture);
+ if (this.conditionalSetError(textureArray.isImmutable(), gl.INVALID_OPERATION))
+ return;
+
+ textureArray.clearLevels();
+ textureArray.setImmutable();
+
+ for (var level = 0; level < levels; level++) {
+ var levelW = Math.max(1, width >> level);
+ var levelH = Math.max(1, height >> level);
+
+ textureArray.allocLevel(level, storageFmt, levelW, levelH, depth);
+ }
+ } else if (target == gl.TEXTURE_3D) {
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize ||
+ height > this.m_limits.maxTexture2DSize ||
+ depth >= this.m_limits.maxTexture3DSize, gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture3D} */
+ var texture3D = /** @type {sglrReferenceContext.Texture3D} */ (unit.tex3DBinding.texture);
+ if (this.conditionalSetError(texture3D.isImmutable(), gl.INVALID_OPERATION))
+ return;
+
+ texture3D.clearLevels();
+ texture3D.setImmutable();
+
+ for (var level = 0; level < levels; level++) {
+ var levelW = Math.max(1, width >> level);
+ var levelH = Math.max(1, height >> level);
+ var levelD = Math.max(1, depth >> level);
+
+ texture3D.allocLevel(level, storageFmt, levelW, levelH, levelD);
+ }
+ } else
+ this.setError(gl.INVALID_ENUM);
+ };
+
+ sglrReferenceContext.ReferenceContext.prototype.texStorage2D = function(target, levels, internalFormat, width, height) {
+ /** @type {sglrReferenceContext.TextureUnit} */var unit = this.m_textureUnits[this.m_activeTexture];
+
+ if (this.conditionalSetError(width <= 0 || height <= 0, gl.INVALID_VALUE))
+ return;
+ if (this.conditionalSetError(levels < 1 || levels > Math.floor(Math.log2(Math.max(width, height))) + 1, gl.INVALID_VALUE))
+ return;
+
+ // Map storage format.
+ /** @type {tcuTexture.TextureFormat} */ var storageFmt = sglrReferenceContext.mapInternalFormat(internalFormat);
+ if (this.conditionalSetError(!storageFmt, gl.INVALID_ENUM))
+ return;
+
+ if (target == gl.TEXTURE_2D) {
+ if (this.conditionalSetError(width > this.m_limits.maxTexture2DSize || height > this.m_limits.maxTexture2DSize, gl.INVALID_VALUE))
+ return;
+
+ /** @type {sglrReferenceContext.Texture2D} */
+ var texture = /** @type {sglrReferenceContext.Texture2D} */ (unit.tex2DBinding.texture);
+ if (this.conditionalSetError(texture.isImmutable(), gl.INVALID_OPERATION))
+ return;
+
+ texture.clearLevels();
+ texture.setImmutable();
+
+ for (var level = 0; level < levels; level++) {
+ var levelW = Math.max(1, width >> level);
+ var levelH = Math.max(1, height >> level);
+
+ texture.allocLevel(level, storageFmt, levelW, levelH);
+ }
+ } else if (target == gl.TEXTURE_CUBE_MAP) {
+ if (this.conditionalSetError(width != height || width > this.m_limits.maxTextureCubeSize, gl.INVALID_VALUE))
+ return;
+ var textureCube = /** @type {sglrReferenceContext.TextureCube} */ (unit.texCubeBinding.texture);
+ if (this.conditionalSetError(textureCube.isImmutable(), gl.INVALID_OPERATION))
+ return;
+
+ textureCube.clearLevels();
+ textureCube.setImmutable();
+
+ for (var level = 0; level < levels; level++) {
+ var levelW = Math.max(1, width >> level);
+ var levelH = Math.max(1, height >> level);
+
+ for (var face in tcuTexture.CubeFace)
+ textureCube.allocLevel(level, tcuTexture.CubeFace[face], storageFmt, levelW, levelH);
+ }
+ } else
+ this.setError(gl.INVALID_ENUM);
+ };
+
+ /**
+ * @param {number} value
+ * @return {?tcuTexture.WrapMode}
+ */
+ sglrReferenceContext.mapGLWrapMode = function(value) {
+ switch (value) {
+ case gl.CLAMP_TO_EDGE: return tcuTexture.WrapMode.CLAMP_TO_EDGE;
+ case gl.REPEAT: return tcuTexture.WrapMode.REPEAT_GL;
+ case gl.MIRRORED_REPEAT: return tcuTexture.WrapMode.MIRRORED_REPEAT_GL;
+ }
+ return null;
+ };
+
+ /**
+ * @param {number} value
+ * @return {?tcuTexture.FilterMode}
+ */
+ sglrReferenceContext.mapGLFilterMode = function(value) {
+ switch (value) {
+ case gl.NEAREST: return tcuTexture.FilterMode.NEAREST;
+ case gl.LINEAR: return tcuTexture.FilterMode.LINEAR;
+ case gl.NEAREST_MIPMAP_NEAREST: return tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST;
+ case gl.NEAREST_MIPMAP_LINEAR: return tcuTexture.FilterMode.NEAREST_MIPMAP_LINEAR;
+ case gl.LINEAR_MIPMAP_NEAREST: return tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST;
+ case gl.LINEAR_MIPMAP_LINEAR: return tcuTexture.FilterMode.LINEAR_MIPMAP_LINEAR;
+ }
+ return null;
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} pname
+ * @param {number} value
+ */
+ sglrReferenceContext.ReferenceContext.prototype.texParameteri = function(target, pname, value) {
+ /** @type {sglrReferenceContext.TextureUnit} */ var unit = this.m_textureUnits[this.m_activeTexture];
+ /** @type {sglrReferenceContext.TextureContainer} */ var container = null;
+
+ switch (target) {
+ case gl.TEXTURE_2D: container = unit.tex2DBinding; break;
+ case gl.TEXTURE_CUBE_MAP: container = unit.texCubeBinding; break;
+ case gl.TEXTURE_2D_ARRAY: container = unit.tex2DArrayBinding; break;
+ case gl.TEXTURE_3D: container = unit.tex3DBinding; break;
+
+ default: this.setError(gl.INVALID_ENUM);
+ }
+
+ if (!container)
+ return;
+
+ /** @type {sglrReferenceContext.Texture} */
+ var texture = container.texture;
+
+ switch (pname) {
+ case gl.TEXTURE_WRAP_S: {
+ /** @type {?tcuTexture.WrapMode} */ var wrapS = sglrReferenceContext.mapGLWrapMode(value);
+ if (this.conditionalSetError(null == wrapS, gl.INVALID_VALUE))
+ return;
+ texture.getSampler().wrapS = /** @type {tcuTexture.WrapMode} */ (wrapS);
+ break;
+ }
+
+ case gl.TEXTURE_WRAP_T: {
+ /** @type {?tcuTexture.WrapMode} */ var wrapT = sglrReferenceContext.mapGLWrapMode(value);
+ if (this.conditionalSetError(null == wrapT, gl.INVALID_VALUE))
+ return;
+ texture.getSampler().wrapT = /** @type {tcuTexture.WrapMode} */ (wrapT);
+ break;
+ }
+
+ case gl.TEXTURE_WRAP_R: {
+ /** @type {?tcuTexture.WrapMode} */ var wrapR = sglrReferenceContext.mapGLWrapMode(value);
+ if (this.conditionalSetError(null == wrapR, gl.INVALID_VALUE))
+ return;
+ texture.getSampler().wrapR = /** @type {tcuTexture.WrapMode} */ (wrapR);
+ break;
+ }
+
+ case gl.TEXTURE_MIN_FILTER: {
+ /** @type {?tcuTexture.FilterMode} */ var minMode = sglrReferenceContext.mapGLFilterMode(value);
+ if (this.conditionalSetError(null == minMode, gl.INVALID_VALUE))
+ return;
+ texture.getSampler().minFilter = /** @type {tcuTexture.FilterMode} */ (minMode);
+ break;
+ }
+
+ case gl.TEXTURE_MAG_FILTER: {
+ /** @type {?tcuTexture.FilterMode} */ var magMode = sglrReferenceContext.mapGLFilterMode(value);
+ if (this.conditionalSetError(null == magMode, gl.INVALID_VALUE))
+ return;
+ texture.getSampler().magFilter = /** @type {tcuTexture.FilterMode} */ (magMode);
+ break;
+ }
+
+ case gl.TEXTURE_MAX_LEVEL: {
+ if (this.conditionalSetError(value < 0, gl.INVALID_VALUE))
+ return;
+ texture.setMaxLevel(value);
+ break;
+ }
+
+ default:
+ this.setError(gl.INVALID_ENUM);
+ return;
+ }
+ };
+
+ sglrReferenceContext.ReferenceContext.prototype.invalidateFramebuffer = function(target, attachments) {};
+ sglrReferenceContext.ReferenceContext.prototype.invalidateSubFramebuffer = function(target, attachments, x, y, width, height) {};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContextTest.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContextTest.js
new file mode 100644
index 0000000000..cc8abf5969
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceContextTest.js
@@ -0,0 +1,834 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('framework.opengl.simplereference.sglrReferenceContextTest');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+ var sglrReferenceContextTest = framework.opengl.simplereference.sglrReferenceContextTest;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var tcuRGBA = framework.common.tcuRGBA;
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ sglrReferenceContextTest.ClearContext = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ };
+
+ sglrReferenceContextTest.ClearContext.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ sglrReferenceContextTest.ClearContext.prototype.constructor = sglrReferenceContextTest.ClearContext;
+
+ sglrReferenceContextTest.ClearContext.prototype.init = function() {};
+
+ sglrReferenceContextTest.ClearContext.prototype.iterate = function() {
+
+ var width = 200;
+ var height = 188;
+ var samples = 1;
+ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ var format = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(format, 24, 8, width, height, samples);
+ var ctx = new sglrReferenceContext.ReferenceContext(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
+ ctx.clearColor(1, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ var pixels = new tcuSurface.Surface(width, height);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ var numFailedPixels = 0;
+ var redPixel = new gluDrawUtil.Pixel([255, 0, 0, 255]);
+ for (var x = 0; x < width; x++)
+ for (var y = 0; y < height; y++) {
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(x, y));
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+ }
+
+ var access = pixels.getAccess();
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ ctx.scissor(width / 4, height / 4, width / 2, height / 2);
+ ctx.enable(gl.SCISSOR_TEST);
+ ctx.clearColor(0, 1, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ numFailedPixels = 0;
+ var greenBluePixel = new gluDrawUtil.Pixel([0, 255, 255, 255]);
+ for (var x = 0; x < width; x++)
+ for (var y = 0; y < height; y++) {
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(x, y));
+ if ((x >= width / 4 && x < width - width / 4) && (y >= height / 4 && y < height - height / 4)) {
+ if (!pixel.equals(greenBluePixel))
+ numFailedPixels += 1;
+ } else
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+ }
+
+ access = pixels.getAccess();
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ sglrReferenceContextTest.Framebuffer = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ };
+
+ sglrReferenceContextTest.Framebuffer.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ sglrReferenceContextTest.Framebuffer.prototype.constructor = sglrReferenceContextTest.Framebuffer;
+
+ sglrReferenceContextTest.Framebuffer.prototype.init = function() {};
+
+ sglrReferenceContextTest.Framebuffer.prototype.iterate = function() {
+ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ var format = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var width = 200;
+ var height = 188;
+ var samples = 1;
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(format, 24, 8, width, height, samples);
+ var ctx = new sglrReferenceContext.ReferenceContext(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ var fbo = ctx.createFramebuffer();
+ var rbo = ctx.createRenderbuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, width, height);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+ bufferedLogToConsole('Framebuffer status: ' + (ctx.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE));
+ ctx.clearColor(1, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ var pixels = new tcuSurface.Surface(width, height);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+ var numFailedPixels = 0;
+ var redPixel = new gluDrawUtil.Pixel([255, 0, 0, 255]);
+ for (var x = 0; x < width; x++)
+ for (var y = 0; y < height; y++) {
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(x, y));
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+ }
+ var access = pixels.getAccess();
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ ctx.scissor(width / 4, height / 4, width / 2, height / 2);
+ ctx.enable(gl.SCISSOR_TEST);
+ ctx.clearColor(0, 1, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ numFailedPixels = 0;
+ var greenBluePixel = new gluDrawUtil.Pixel([0, 255, 255, 255]);
+ for (var x = 0; x < width; x++)
+ for (var y = 0; y < height; y++) {
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(x, y));
+ if ((x >= width / 4 && x < width - width / 4) && (y >= height / 4 && y < height - height / 4)) {
+ if (!pixel.equals(greenBluePixel))
+ numFailedPixels += 1;
+ } else
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+ }
+
+ access = pixels.getAccess();
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ var bluePixel = new gluDrawUtil.Pixel([0, 0, 255, 255]);
+ for (var x = 0; x < width; x++)
+ for (var y = 0; y < height; y++) {
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(x, y));
+ if (!pixel.equals(bluePixel))
+ numFailedPixels += 1;
+ }
+ access = pixels.getAccess();
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ sglrReferenceContextTest.Shader = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ };
+
+ sglrReferenceContextTest.Shader.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ sglrReferenceContextTest.Shader.prototype.constructor = sglrReferenceContextTest.Shader;
+
+ sglrReferenceContextTest.Shader.prototype.init = function() {};
+
+ sglrReferenceContextTest.Shader.prototype.iterate = function() {
+ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ var format = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var width = 200;
+ var height = 188;
+ var samples = 1;
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(format, 24, 8, width, height, samples);
+ var ctx = new sglrReferenceContext.ReferenceContext(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ var vertices = [
+ -0.5, 0.5,
+ 0.5, 0.5,
+ -0.5, -0.5,
+ 0.5, 0.5,
+ 0.5, -0.5,
+ -0.5, -0.5
+ ];
+
+ var vertices32 = new Float32Array(vertices);
+
+ var squareVerticesBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, vertices32, gl.STATIC_DRAW);
+
+ var colors = [
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1
+ ];
+
+ var colors32 = new Float32Array(colors);
+
+ var squareColorsBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, colors32, gl.STATIC_DRAW);
+
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var progDecl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexPosition', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexColor', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexSource(new sglrShaderProgram.VertexSource(''));
+
+ progDecl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushFragmentSource(new sglrShaderProgram.FragmentSource(''));
+
+ /** @type {sglrReferenceContextTest.ContextShaderProgram} */ var program = new sglrReferenceContextTest.ContextShaderProgram(progDecl);
+
+ //Create program
+ ctx.createProgram(program);
+
+ //Use program
+ ctx.useProgram(program);
+
+ var vertexPositionAttribute = ctx.getAttribLocation(program, 'aVertexPosition');
+ var vertexColorAttribute = ctx.getAttribLocation(program, 'aVertexColor');
+ ctx.enableVertexAttribArray(vertexPositionAttribute);
+ ctx.enableVertexAttribArray(vertexColorAttribute);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.vertexAttribPointer(vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.drawQuads(gl.TRIANGLES, 0, 6);
+
+ var pixels = new tcuSurface.Surface(width, height);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ var numFailedPixels = 0;
+
+ var redPixel = new gluDrawUtil.Pixel([255, 0, 0, 255]);
+ var bluePixel = new gluDrawUtil.Pixel([0, 0, 255, 255]);
+
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(0, 0));
+ if (!pixel.equals(bluePixel))
+ numFailedPixels += 1;
+
+ pixel = new gluDrawUtil.Pixel(pixels.getPixel(100, 94));
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+
+ var access = pixels.getAccess();
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ sglrReferenceContextTest.TriangleStrip = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ };
+
+ sglrReferenceContextTest.TriangleStrip.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ sglrReferenceContextTest.TriangleStrip.prototype.constructor = sglrReferenceContextTest.TriangleStrip;
+
+ sglrReferenceContextTest.TriangleStrip.prototype.init = function() {};
+
+ sglrReferenceContextTest.TriangleStrip.prototype.iterate = function() {
+ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ var format = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var width = 200;
+ var height = 188;
+ var samples = 1;
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(format, 24, 8, width, height, samples);
+ var ctx = new sglrReferenceContext.ReferenceContext(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ var vertices = [
+ -0.5, 0.5,
+ 0.5, 0.5,
+ -0.5, 0,
+ 0.5, 0,
+ -0.5, -0.5,
+ 0.5, -0.5
+ ];
+
+ var vertices32 = new Float32Array(vertices);
+
+ var squareVerticesBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, vertices32, gl.STATIC_DRAW);
+
+ var colors = [
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1
+ ];
+
+ var colors32 = new Float32Array(colors);
+
+ var squareColorsBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, colors32, gl.STATIC_DRAW);
+
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var progDecl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexPosition', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexColor', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexSource(new sglrShaderProgram.VertexSource(''));
+
+ progDecl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushFragmentSource(new sglrShaderProgram.FragmentSource(''));
+
+ /** @type {sglrReferenceContextTest.ContextShaderProgram} */ var program = new sglrReferenceContextTest.ContextShaderProgram(progDecl);
+
+ //Create program
+ ctx.createProgram(program);
+
+ //Use program
+ ctx.useProgram(program);
+
+ var vertexPositionAttribute = ctx.getAttribLocation(program, 'aVertexPosition');
+ var vertexColorAttribute = ctx.getAttribLocation(program, 'aVertexColor');
+ ctx.enableVertexAttribArray(vertexPositionAttribute);
+ ctx.enableVertexAttribArray(vertexColorAttribute);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.vertexAttribPointer(vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.drawQuads(gl.TRIANGLE_STRIP, 0, 6);
+
+ var pixels = new tcuSurface.Surface(width, height);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ var numFailedPixels = 0;
+
+ var redPixel = new gluDrawUtil.Pixel([255, 0, 0, 255]);
+ var bluePixel = new gluDrawUtil.Pixel([0, 0, 255, 255]);
+
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(0, 0));
+ if (!pixel.equals(bluePixel))
+ numFailedPixels += 1;
+
+ pixel = new gluDrawUtil.Pixel(pixels.getPixel(100, 94));
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+
+ var access = pixels.getAccess();
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ sglrReferenceContextTest.TriangleFan = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ };
+
+ sglrReferenceContextTest.TriangleFan.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ sglrReferenceContextTest.TriangleFan.prototype.constructor = sglrReferenceContextTest.TriangleFan;
+
+ sglrReferenceContextTest.TriangleFan.prototype.init = function() {};
+
+ sglrReferenceContextTest.TriangleFan.prototype.iterate = function() {
+ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ var format = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var width = 200;
+ var height = 188;
+ var samples = 1;
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(format, 24, 8, width, height, samples);
+ var ctx = new sglrReferenceContext.ReferenceContext(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ var vertices = [
+ -0.5, 0,
+ -0.5, 0.5,
+ 0.5, 0.5,
+ 0.5, 0,
+ 0.5, -0.5,
+ -0.5, -0.5
+ ];
+
+ var vertices32 = new Float32Array(vertices);
+
+ var squareVerticesBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, vertices32, gl.STATIC_DRAW);
+
+ var colors = [
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1,
+ 1, 0, 0, 1
+ ];
+
+ var colors32 = new Float32Array(colors);
+
+ var squareColorsBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, colors32, gl.STATIC_DRAW);
+
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var progDecl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexPosition', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexColor', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexSource(new sglrShaderProgram.VertexSource(''));
+
+ progDecl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushFragmentSource(new sglrShaderProgram.FragmentSource(''));
+
+ /** @type {sglrReferenceContextTest.ContextShaderProgram} */ var program = new sglrReferenceContextTest.ContextShaderProgram(progDecl);
+
+ //Create program
+ ctx.createProgram(program);
+
+ //Use program
+ ctx.useProgram(program);
+
+ var vertexPositionAttribute = ctx.getAttribLocation(program, 'aVertexPosition');
+ var vertexColorAttribute = ctx.getAttribLocation(program, 'aVertexColor');
+ ctx.enableVertexAttribArray(vertexPositionAttribute);
+ ctx.enableVertexAttribArray(vertexColorAttribute);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.vertexAttribPointer(vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.drawQuads(gl.TRIANGLE_FAN, 0, 6);
+
+ var pixels = new tcuSurface.Surface(width, height);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ var numFailedPixels = 0;
+
+ var redPixel = new gluDrawUtil.Pixel([255, 0, 0, 255]);
+ var bluePixel = new gluDrawUtil.Pixel([0, 0, 255, 255]);
+
+ var pixel = new gluDrawUtil.Pixel(pixels.getPixel(0, 0));
+ if (!pixel.equals(bluePixel))
+ numFailedPixels += 1;
+
+ pixel = new gluDrawUtil.Pixel(pixels.getPixel(100, 94));
+ if (!pixel.equals(redPixel))
+ numFailedPixels += 1;
+
+ var access = pixels.getAccess();
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ sglrReferenceContextTest.DrawElements = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ };
+
+ sglrReferenceContextTest.DrawElements.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ sglrReferenceContextTest.DrawElements.prototype.constructor = sglrReferenceContextTest.DrawElements;
+
+ sglrReferenceContextTest.DrawElements.prototype.init = function() {};
+
+ sglrReferenceContextTest.DrawElements.prototype.iterate = function() {
+ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ var format = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var width = 200;
+ var height = 188;
+ var samples = 1;
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(format, 24, 8, width, height, samples);
+ var ctx = new sglrReferenceContext.ReferenceContext(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ var vertices = [
+ -0.5, 0.5,
+ 0, 0.5,
+ 0.4, 0.5,
+
+ -0.5, 0.1,
+ 0, 0.1,
+ 0.4, 0.1,
+
+ -0.5, -0.7,
+ 0, -0.7,
+ 0.4, -0.7
+ ];
+
+ var vertices32 = new Float32Array(vertices);
+
+ var squareVerticesBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, vertices32, gl.STATIC_DRAW);
+
+ var indices = [
+ 0, 1, 3, 1, 3, 4,
+ 1, 2, 4, 2, 4, 5,
+ 3, 4, 6, 4, 6, 7,
+ 4, 5, 7, 5, 7, 8
+ ];
+ var indicesBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
+ ctx.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
+
+ var colors = [
+ 1, 0, 0, 1,
+ 0, 1, 0, 1,
+ 0, 0, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 0, 1,
+ 0, 1, 1, 1,
+ 1, 0, 1, 1,
+ 0.5, 0.5, 0.5, 1,
+ 0, 0, 0, 0
+ ];
+
+ var colors32 = new Float32Array(colors);
+
+ var squareColorsBuffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.bufferData(gl.ARRAY_BUFFER, colors32, gl.STATIC_DRAW);
+
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var progDecl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexPosition', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('aVertexColor', rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushVertexSource(new sglrShaderProgram.VertexSource(''));
+
+ progDecl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ progDecl.pushFragmentSource(new sglrShaderProgram.FragmentSource(''));
+
+ /** @type {sglrReferenceContextTest.ContextShaderProgram} */ var program = new sglrReferenceContextTest.ContextShaderProgram(progDecl);
+
+ //Create program
+ ctx.createProgram(program);
+
+ //Use program
+ ctx.useProgram(program);
+
+ var vertexPositionAttribute = ctx.getAttribLocation(program, 'aVertexPosition');
+ var vertexColorAttribute = ctx.getAttribLocation(program, 'aVertexColor');
+ ctx.enableVertexAttribArray(vertexPositionAttribute);
+ ctx.enableVertexAttribArray(vertexColorAttribute);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ ctx.vertexAttribPointer(vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, squareColorsBuffer);
+ ctx.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
+
+ var pixels = new tcuSurface.Surface(width, height);
+ ctx.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels.getAccess().getDataPtr());
+
+ var numFailedPixels = 0;
+
+ var access = pixels.getAccess();
+
+ var pixelsTotest = [
+ // location, color
+ [2, 1], [0, 0, 255, 255],
+ // The red vertex is between 140 and 141 so account for some blending with the white vertex
+ [50, 140], [255, 5, 5, 255],
+ [50, 28], [255, 0, 255, 255],
+ [139, 28], [0, 0, 0, 255],
+ [50, 102], [255, 255, 255, 255],
+ [139, 102], [0, 255, 255, 255]
+ ];
+
+ var threshold = new tcuRGBA.RGBA([5, 5, 5, 5]);
+
+ for (var i = 0; i < pixelsTotest.length; i += 2) {
+ var location = pixelsTotest[i];
+ var reference = new tcuRGBA.RGBA(pixelsTotest[i + 1]);
+ var color = access.getPixelInt(location[0], location[1]);
+ var pixel = new tcuRGBA.RGBA(color);
+ if (!tcuRGBA.compareThreshold(pixel, reference, threshold))
+ numFailedPixels++;
+ }
+
+ tcuLogImage.logImage('Result', '', access);
+
+ if (numFailedPixels > 0)
+ testFailedOptions('Image comparison failed, got ' + numFailedPixels + ' non-equal pixels.', false);
+ else
+ testPassedOptions('Image comparison succeed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {sglrShaderProgram.ShaderProgramDeclaration} progDecl
+ */
+ sglrReferenceContextTest.ContextShaderProgram = function(progDecl) {
+ sglrShaderProgram.ShaderProgram.call(this, progDecl);
+ };
+
+ sglrReferenceContextTest.ContextShaderProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ sglrReferenceContextTest.ContextShaderProgram.prototype.constructor = sglrReferenceContextTest.ContextShaderProgram;
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ sglrReferenceContextTest.ContextShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {number} */ var varyingLocColor = 0;
+
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ // Calc output color
+ /** @type {Array<number>} */ var coord = [1.0, 1.0];
+ /** @type {Array<number>} */ var color = [1.0, 1.0, 1.0];
+
+ for (var attribNdx = 0; attribNdx < this.getVertexShader().getInputs().length; attribNdx++) {
+ /** @type {number} */ var numComponents = inputs[attribNdx].componentCount;
+
+ var attribValue = rrVertexAttrib.readVertexAttrib(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx, this.getVertexShader().getInputs()[attribNdx].type);
+
+ if (attribNdx == 0) {
+ coord[0] = attribValue[0];
+ coord[1] = attribValue[1];
+ } else {
+ color[0] = attribValue[0] * attribValue[3];
+ color[1] = attribValue[1] * attribValue[3];
+ color[2] = attribValue[2] * attribValue[3];
+ }
+ }
+
+ // Transform position
+ packet.position = [coord[0], coord[1], 1.0, 1.0];
+
+ // Pass color to FS
+ packet.outputs[varyingLocColor] = [color[0], color[1], color[2], 1.0];
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packets
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ sglrReferenceContextTest.ContextShaderProgram.prototype.shadeFragments = function(packets, context) {
+ var varyingLocColor = 0;
+
+ // Normal shading
+ for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx)
+ packets[packetNdx].value = rrShadingContext.readTriangleVarying(packets[packetNdx], context, varyingLocColor);
+ };
+
+ sglrReferenceContextTest.init = function() {
+ var state = tcuTestCase.runner;
+ /** @type {tcuTestCase.DeqpTest} */ var testGroup = state.testCases;
+
+ /** @type {tcuTestCase.DeqpTest} */ var referenceContextGroup = tcuTestCase.newTest('reference_context', 'Test reference context');
+
+ referenceContextGroup.addChild(new sglrReferenceContextTest.ClearContext('clear_context', 'Clear Context Test'));
+ referenceContextGroup.addChild(new sglrReferenceContextTest.Framebuffer('Framebuffer', 'Framebuffer Test'));
+ referenceContextGroup.addChild(new sglrReferenceContextTest.Shader('Shaders', 'Drawing using TRIANGLES'));
+ referenceContextGroup.addChild(new sglrReferenceContextTest.TriangleStrip('TriangleStrip', 'Drawing using TRIANGLE_STRIP'));
+ referenceContextGroup.addChild(new sglrReferenceContextTest.TriangleFan('TriangleFan', 'Drawing using TRIANGLE_FAN'));
+ referenceContextGroup.addChild(new sglrReferenceContextTest.DrawElements('DrawElements', 'Drawing using DrawElements and TRIANGLES'));
+
+ testGroup.addChild(referenceContextGroup);
+
+ };
+
+ sglrReferenceContextTest.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'single_reference_context';
+ var testDescription = 'Single Reference Context Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ sglrReferenceContextTest.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceUtils.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceUtils.js
new file mode 100644
index 0000000000..3b93dd8f9f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrReferenceUtils.js
@@ -0,0 +1,317 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Reference context utils
+ *//*--------------------------------------------------------------------*/
+
+'use strict';
+goog.provide('framework.opengl.simplereference.sglrReferenceUtils');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrRenderState');
+goog.require('framework.referencerenderer.rrRenderer');
+goog.require('framework.referencerenderer.rrShaders');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+
+goog.scope(function() {
+
+ var sglrReferenceUtils = framework.opengl.simplereference.sglrReferenceUtils;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuFloat = framework.common.tcuFloat;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrRenderer = framework.referencerenderer.rrRenderer;
+ var rrDefs = framework.referencerenderer.rrDefs;
+ var rrShaders = framework.referencerenderer.rrShaders;
+ var rrRenderState = framework.referencerenderer.rrRenderState;
+
+ /**
+ * @param {number} type (32-bit, unsigend)
+ * @return {rrVertexAttrib.VertexAttribType}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLPureIntegerVertexAttributeType = function(type) {
+ switch (type) {
+ case gl.UNSIGNED_BYTE: return rrVertexAttrib.VertexAttribType.PURE_UINT8;
+ case gl.UNSIGNED_SHORT: return rrVertexAttrib.VertexAttribType.PURE_UINT16;
+ case gl.UNSIGNED_INT: return rrVertexAttrib.VertexAttribType.PURE_UINT32;
+ case gl.BYTE: return rrVertexAttrib.VertexAttribType.PURE_INT8;
+ case gl.SHORT: return rrVertexAttrib.VertexAttribType.PURE_INT16;
+ case gl.INT: return rrVertexAttrib.VertexAttribType.PURE_INT32;
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} type (32-bit, unsigend)
+ * @param {boolean} normalizedInteger
+ * @param {number} size
+ * @return {rrVertexAttrib.VertexAttribType} converted value from type to VertexAttribType
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLFloatVertexAttributeType = function(type, normalizedInteger, size) {
+
+ /** @type {boolean} */ var useClampingNormalization = true;
+
+ switch (type) {
+ case gl.FLOAT:
+ return rrVertexAttrib.VertexAttribType.FLOAT;
+ case gl.HALF_FLOAT:
+ return rrVertexAttrib.VertexAttribType.HALF;
+ /* Not supported in WebGL 1/2 case gl.FIXED:
+ return rrVertexAttrib.VertexAttribType.FIXED;
+ case gl.DOUBLE:
+ return rrVertexAttrib.VertexAttribType.DOUBLE; */
+ case gl.UNSIGNED_BYTE:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_UINT8;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_UNORM8;
+
+ case gl.UNSIGNED_SHORT:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_UINT16;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_UNORM16;
+
+ case gl.UNSIGNED_INT:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_UINT32;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_UNORM32;
+
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV;
+
+ case gl.BYTE:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_INT8;
+ else if (useClampingNormalization)
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_CLAMP;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_SCALE;
+
+ case gl.SHORT:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_INT16;
+ else if (useClampingNormalization)
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_CLAMP;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_SCALE;
+
+ case gl.INT:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_INT32;
+ else if (useClampingNormalization)
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_CLAMP;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_SCALE;
+
+ case gl.INT_2_10_10_10_REV:
+ if (!normalizedInteger)
+ return rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV;
+ else if (useClampingNormalization)
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP;
+ else
+ return rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE;
+
+ default:
+ throw new Error('Value to do mapping not compatible');
+
+ }
+
+ };
+
+ /**
+ * @param {number} size
+ * @return {number}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLSize = function(size) {
+ switch (size) {
+ case 1: return 1;
+ case 2: return 2;
+ case 3: return 3;
+ case 4: return 4;
+ /* NOT in GL
+ case gl.BGRA: return 4;
+ */
+
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} type (32-bit, unsigned)
+ * @return {rrRenderer.PrimitiveType}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLPrimitiveType = function(type) {
+ switch (type) {
+ case gl.TRIANGLES: return rrRenderer.PrimitiveType.TRIANGLES;
+ case gl.TRIANGLE_STRIP: return rrRenderer.PrimitiveType.TRIANGLE_STRIP;
+ case gl.TRIANGLE_FAN: return rrRenderer.PrimitiveType.TRIANGLE_FAN;
+ case gl.LINES: return rrRenderer.PrimitiveType.LINES;
+ case gl.LINE_STRIP: return rrRenderer.PrimitiveType.LINE_STRIP;
+ case gl.LINE_LOOP: return rrRenderer.PrimitiveType.LINE_LOOP;
+ case gl.POINTS: return rrRenderer.PrimitiveType.POINTS;
+
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} type (32-bit, unsigned)
+ * @return {rrDefs.IndexType}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLIndexType = function(type) {
+ switch (type) {
+ case gl.UNSIGNED_BYTE: return rrDefs.IndexType.INDEXTYPE_UINT8;
+ case gl.UNSIGNED_SHORT: return rrDefs.IndexType.INDEXTYPE_UINT16;
+ case gl.UNSIGNED_INT: return rrDefs.IndexType.INDEXTYPE_UINT32;
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} func (deUint32)
+ * @return {rrRenderState.TestFunc}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLTestFunc = function(func) {
+ switch (func) {
+ case gl.ALWAYS: return rrRenderState.TestFunc.ALWAYS;
+ case gl.EQUAL: return rrRenderState.TestFunc.EQUAL;
+ case gl.GEQUAL: return rrRenderState.TestFunc.GEQUAL;
+ case gl.GREATER: return rrRenderState.TestFunc.GREATER;
+ case gl.LEQUAL: return rrRenderState.TestFunc.LEQUAL;
+ case gl.LESS: return rrRenderState.TestFunc.LESS;
+ case gl.NEVER: return rrRenderState.TestFunc.NEVER;
+ case gl.NOTEQUAL: return rrRenderState.TestFunc.NOTEQUAL;
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} op (deUint32)
+ * @return {rrRenderState.StencilOp}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLStencilOp = function(op) {
+ switch (op) {
+ case gl.KEEP: return rrRenderState.StencilOp.KEEP;
+ case gl.ZERO: return rrRenderState.StencilOp.ZERO;
+ case gl.REPLACE: return rrRenderState.StencilOp.REPLACE;
+ case gl.INCR: return rrRenderState.StencilOp.INCR;
+ case gl.DECR: return rrRenderState.StencilOp.DECR;
+ case gl.INCR_WRAP: return rrRenderState.StencilOp.INCR_WRAP;
+ case gl.DECR_WRAP: return rrRenderState.StencilOp.DECR_WRAP;
+ case gl.INVERT: return rrRenderState.StencilOp.INVERT;
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} equation (deUint32)
+ * @return {rrRenderState.BlendEquation}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLBlendEquation = function(equation) {
+ switch (equation) {
+ case gl.FUNC_ADD: return rrRenderState.BlendEquation.ADD;
+ case gl.FUNC_SUBTRACT: return rrRenderState.BlendEquation.SUBTRACT;
+ case gl.FUNC_REVERSE_SUBTRACT: return rrRenderState.BlendEquation.REVERSE_SUBTRACT;
+ case gl.MIN: return rrRenderState.BlendEquation.MIN;
+ case gl.MAX: return rrRenderState.BlendEquation.MAX;
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+
+ /**
+ * @param {number} equation (deUint32)
+ * @return {rrRenderState.BlendEquationAdvanced}
+ * @throws {Error}
+ */
+ /*sglrReferenceUtils.mapGLBlendEquationAdvanced = function(equation) {
+ switch (equation) {
+ case gl.MULTIPLY_KHR: return rrRenderState.BlendEquationAdvanced.MULTIPLY;
+ case gl.SCREEN_KHR: return rrRenderState.BlendEquationAdvanced.SCREEN;
+ case gl.OVERLAY_KHR: return rrRenderState.BlendEquationAdvanced.OVERLAY;
+ case gl.DARKEN_KHR: return rrRenderState.BlendEquationAdvanced.DARKEN;
+ case gl.LIGHTEN_KHR: return rrRenderState.BlendEquationAdvanced.LIGHTEN;
+ case gl.COLORDODGE_KHR: return rrRenderState.BlendEquationAdvanced.COLORDODGE;
+ case gl.COLORBURN_KHR: return rrRenderState.BlendEquationAdvanced.COLORBURN;
+ case gl.HARDLIGHT_KHR: return rrRenderState.BlendEquationAdvanced.HARDLIGHT;
+ case gl.SOFTLIGHT_KHR: return rrRenderState.BlendEquationAdvanced.SOFTLIGHT;
+ case gl.DIFFERENCE_KHR: return rrRenderState.BlendEquationAdvanced.DIFFERENCE;
+ case gl.EXCLUSION_KHR: return rrRenderState.BlendEquationAdvanced.EXCLUSION;
+ case gl.HSL_HUE_KHR: return rrRenderState.BlendEquationAdvanced.HSL_HUE;
+ case gl.HSL_SATURATION_KHR: return rrRenderState.BlendEquationAdvanced.HSL_SATURATION;
+ case gl.HSL_COLOR_KHR: return rrRenderState.BlendEquationAdvanced.HSL_COLOR;
+ case gl.HSL_LUMINOSITY_KHR: return rrRenderState.BlendEquationAdvanced.HSL_LUMINOSITY;
+ default:
+ throw new Error("Value to do mapping not compatible");
+ }
+ };*/
+
+ /**
+ * @param {number} func (deUint32)
+ * @return {rrRenderState.BlendFunc}
+ * @throws {Error}
+ */
+ sglrReferenceUtils.mapGLBlendFunc = function(func) {
+ switch (func) {
+ case gl.ZERO: return rrRenderState.BlendFunc.ZERO;
+ case gl.ONE: return rrRenderState.BlendFunc.ONE;
+ case gl.SRC_COLOR: return rrRenderState.BlendFunc.SRC_COLOR;
+ case gl.ONE_MINUS_SRC_COLOR: return rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR;
+ case gl.DST_COLOR: return rrRenderState.BlendFunc.DST_COLOR;
+ case gl.ONE_MINUS_DST_COLOR: return rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR;
+ case gl.SRC_ALPHA: return rrRenderState.BlendFunc.SRC_ALPHA;
+ case gl.ONE_MINUS_SRC_ALPHA: return rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA;
+ case gl.DST_ALPHA: return rrRenderState.BlendFunc.DST_ALPHA;
+ case gl.ONE_MINUS_DST_ALPHA: return rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA;
+ case gl.CONSTANT_COLOR: return rrRenderState.BlendFunc.CONSTANT_COLOR;
+ case gl.ONE_MINUS_CONSTANT_COLOR: return rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR;
+ case gl.CONSTANT_ALPHA: return rrRenderState.BlendFunc.CONSTANT_ALPHA;
+ case gl.ONE_MINUS_CONSTANT_ALPHA: return rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA;
+ case gl.SRC_ALPHA_SATURATE: return rrRenderState.BlendFunc.SRC_ALPHA_SATURATE;
+ // case gl.SRC1_COLOR: return rrRenderState.BlendFunc.SRC1_COLOR;
+ // case gl.ONE_MINUS_SRC1_COLOR: return rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR;
+ // case gl.SRC1_ALPHA: return rrRenderState.BlendFunc.SRC1_ALPHA;
+ // case gl.ONE_MINUS_SRC1_ALPHA: return rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA;
+ default:
+ throw new Error('Value to do mapping not compatible');
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrShaderProgram.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrShaderProgram.js
new file mode 100644
index 0000000000..f5201a5315
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/opengl/simplereference/sglrShaderProgram.js
@@ -0,0 +1,336 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShaders');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var rrShaders = framework.referencerenderer.rrShaders;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var tcuTexture = framework.common.tcuTexture;
+ var deMath = framework.delibs.debase.deMath;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var rrDefs = framework.referencerenderer.rrDefs;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * sglrShaderProgram.VaryingFlags
+ * @constructor
+ * @struct
+ */
+ sglrShaderProgram.VaryingFlags = function() {
+ this.NONE = true; //TODO: is NONE necessary?
+ this.FLATSHADE = false;
+ };
+
+ /**
+ * sglrShaderProgram.VertexAttribute
+ * @constructor
+ * @param {string} name_
+ * @param {rrGenericVector.GenericVecType} type_
+ */
+ sglrShaderProgram.VertexAttribute = function(name_, type_) {
+ this.name = name_;
+ this.type = type_;
+ };
+
+ /**
+ * sglrShaderProgram.VertexToFragmentVarying
+ * @constructor
+ * @param {rrGenericVector.GenericVecType} type_
+ * @param {sglrShaderProgram.VaryingFlags=} flags
+ */
+ sglrShaderProgram.VertexToFragmentVarying = function(type_, flags) {
+ this.type = type_;
+ this.flatshade = flags === undefined ? new sglrShaderProgram.VaryingFlags().FLATSHADE : flags.FLATSHADE;
+ };
+
+ /**
+ * sglrShaderProgram.FragmentOutput
+ * @constructor
+ * @param {rrGenericVector.GenericVecType} type_
+ */
+ sglrShaderProgram.FragmentOutput = function(type_) {
+ /** @type {rrGenericVector.GenericVecType} */ this.type = type_;
+ };
+
+ /**
+ * sglrShaderProgram.Uniform
+ * @constructor
+ * @param {string} name_
+ * @param {gluShaderUtil.DataType} type_
+ */
+ sglrShaderProgram.Uniform = function(name_, type_) {
+ /** @type {string} */ this.name = name_;
+ /** @type {gluShaderUtil.DataType} */ this.type = type_;
+ /** @type {Array<number>} */ this.value;
+ /** @type {?rrDefs.Sampler} */ this.sampler = null;
+ };
+
+ /**
+ * sglrShaderProgram.VertexSource
+ * @constructor
+ * @param {string} str
+ */
+ sglrShaderProgram.VertexSource = function(str) {
+ /** @type {string} */ this.source = str;
+ };
+
+ /**
+ * sglrShaderProgram.FragmentSource
+ * @constructor
+ * @param {string} str
+ */
+ sglrShaderProgram.FragmentSource = function(str) {
+ /** @type {string} */ this.source = str;
+ };
+
+ /**
+ * sglrShaderProgram.ShaderProgramDeclaration
+ * @constructor
+ */
+ sglrShaderProgram.ShaderProgramDeclaration = function() {
+ /** @type {Array<sglrShaderProgram.VertexAttribute>} */ this.m_vertexAttributes = [];
+ /** @type {Array<sglrShaderProgram.VertexToFragmentVarying>} */ this.m_vertexToFragmentVaryings = [];
+ /** @type {Array<sglrShaderProgram.FragmentOutput>} */ this.m_fragmentOutputs = [];
+ /** @type {Array<sglrShaderProgram.Uniform>} */ this.m_uniforms = [];
+ /** @type {string} */ this.m_vertexSource;
+ /** @type {string} */ this.m_fragmentSource;
+
+ /** @type {boolean} */ this.m_vertexShaderSet = false;
+ /** @type {boolean} */ this.m_fragmentShaderSet = false;
+ };
+
+ /**
+ * Add a vertex attribute to the shader program declaration.
+ * @param {sglrShaderProgram.VertexAttribute} v
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.pushVertexAttribute = function(v) {
+ this.m_vertexAttributes.push(v);
+ return this;
+ };
+
+ /**
+ * Add a vertex to fragment varying to the shader program declaration.
+ * @param {sglrShaderProgram.VertexToFragmentVarying} v
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.pushVertexToFragmentVarying = function(v) {
+ this.m_vertexToFragmentVaryings.push(v);
+ return this;
+ };
+
+ /**
+ * Add a fragment output to the shader program declaration.
+ * @param {sglrShaderProgram.FragmentOutput} v
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.pushFragmentOutput = function(v) {
+ this.m_fragmentOutputs.push(v);
+ return this;
+ };
+
+ /**
+ * Add a uniform to the shader program declaration.
+ * @param {sglrShaderProgram.Uniform} v
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.pushUniform = function(v) {
+ this.m_uniforms.push(v);
+ return this;
+ };
+
+ /**
+ * @param {sglrShaderProgram.VertexSource} c
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.pushVertexSource = function(c) {
+ DE_ASSERT(!this.m_vertexShaderSet);
+ this.m_vertexSource = c.source;
+ this.m_vertexShaderSet = true;
+ return this;
+ };
+
+ /**
+ * @param {sglrShaderProgram.FragmentSource} c
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.pushFragmentSource = function(c) {
+ DE_ASSERT(!this.m_fragmentSource);
+ /** @type {sglrShaderProgram.FragmentSource} */ this.m_fragmentSource = c.source;
+ /** @type {boolean} */ this.m_fragmentShaderSet = true;
+ return this;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.valid = function() {
+ if (!this.m_vertexShaderSet || !this.m_fragmentShaderSet)
+ return false;
+
+ if (this.m_fragmentOutputs.length == 0)
+ return false;
+
+ return true;
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.getVertexInputCount = function() {
+ return this.m_vertexAttributes.length;
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.getVertexOutputCount = function() {
+ return this.m_vertexToFragmentVaryings.length;
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.getFragmentInputCount = function() {
+ return this.m_vertexToFragmentVaryings.length;
+ };
+
+ /**
+ * @return {number}
+ */
+ sglrShaderProgram.ShaderProgramDeclaration.prototype.getFragmentOutputCount = function() {
+ return this.m_fragmentOutputs.length;
+ };
+
+ /**
+ * @constructor
+ * @param {sglrShaderProgram.ShaderProgramDeclaration} decl
+ */
+ sglrShaderProgram.ShaderProgram = function(decl) {
+ /** @type {rrShaders.VertexShader} */ this.vertexShader = new rrShaders.VertexShader(decl.getVertexInputCount(), decl.getVertexOutputCount());
+ /** @type {rrShaders.FragmentShader} */ this.fragmentShader = new rrShaders.FragmentShader(decl.getFragmentInputCount(), decl.getFragmentOutputCount());
+
+ /** @type {Array<string>} */ this.m_attributeNames = [];
+ /** @type {Array<sglrShaderProgram.Uniform>} */ this.m_uniforms = [];
+ /** @type {string} */ this.m_vertSrc = decl.m_vertexSource;
+ /** @type {string} */ this.m_fragSrc = decl.m_fragmentSource;
+
+ DE_ASSERT(decl.valid());
+
+ // Set up shader IO
+
+ for (var ndx = 0; ndx < decl.m_vertexAttributes.length; ++ndx) {
+ this.vertexShader.m_inputs[ndx].type = decl.m_vertexAttributes[ndx].type;
+ this.m_attributeNames[ndx] = decl.m_vertexAttributes[ndx].name;
+ }
+
+ for (var ndx = 0; ndx < decl.m_vertexToFragmentVaryings.length; ++ndx) {
+ this.vertexShader.m_outputs[ndx].type = decl.m_vertexToFragmentVaryings[ndx].type;
+ this.vertexShader.m_outputs[ndx].flatshade = decl.m_vertexToFragmentVaryings[ndx].flatshade;
+
+ this.fragmentShader.m_inputs[ndx] = this.vertexShader.m_outputs[ndx];
+ }
+
+ for (var ndx = 0; ndx < decl.m_fragmentOutputs.length; ++ndx)
+ this.fragmentShader.m_outputs[ndx].type = decl.m_fragmentOutputs[ndx].type;
+
+ // Set up uniforms
+
+ for (var ndx = 0; ndx < decl.m_uniforms.length; ++ndx)
+ this.m_uniforms[ndx] = new sglrShaderProgram.Uniform(decl.m_uniforms[ndx].name, decl.m_uniforms[ndx].type);
+ };
+
+ /**
+ * @return {rrShaders.VertexShader}
+ */
+ sglrShaderProgram.ShaderProgram.prototype.getVertexShader = function() {
+ return this.vertexShader;
+ };
+
+ /**
+ * @return {rrShaders.FragmentShader}
+ */
+ sglrShaderProgram.ShaderProgram.prototype.getFragmentShader = function() {
+ return this.fragmentShader;
+ };
+
+ /**
+ * @param {string} name
+ * @return {sglrShaderProgram.Uniform}
+ * @throws {Error}
+ */
+ sglrShaderProgram.ShaderProgram.prototype.getUniformByName = function(name) {
+ DE_ASSERT(name);
+
+ for (var ndx = 0; ndx < this.m_uniforms.length; ++ndx)
+ if (this.m_uniforms[ndx].name == name)
+ return this.m_uniforms[ndx];
+
+ throw new Error('Invalid uniform name, uniform not found.');
+ };
+
+ /**
+ * shadeFragments - abstract function, to be implemented by children classes
+ * @param {Array<rrFragmentOperations.Fragment>} packets
+ * @param {rrShadingContext.FragmentShadingContext} context
+ * @throws {Error}
+ */
+ sglrShaderProgram.ShaderProgram.prototype.shadeFragments = function(packets, context) {
+ throw new Error('This function needs to be overwritten in a child class.');
+ };
+
+ /**
+ * shadeVertices - abstract function, to be implemented by children classes
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ * @throws {Error}
+ */
+ sglrShaderProgram.ShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ throw new Error('This function needs to be overwritten in a child class.');
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js
new file mode 100644
index 0000000000..c0400465e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrDefs');
+
+goog.scope(function() {
+
+var rrDefs = framework.referencerenderer.rrDefs;
+
+/**
+ * @enum
+ */
+rrDefs.FaceType = {
+ FACETYPE_FRONT: 0,
+ FACETYPE_BACK: 1
+};
+
+/**
+ * @enum
+ */
+rrDefs.IndexType = {
+ INDEXTYPE_UINT8: 0,
+ INDEXTYPE_UINT16: 1,
+ INDEXTYPE_UINT32: 2
+};
+
+/**
+ * @enum
+ */
+rrDefs.ProvokingVertex = {
+ PROVOKINGVERTEX_FIRST: 1,
+ PROVOKINGVERTEX_LAST: 2 // \note valid value, "last vertex", not last of enum
+};
+
+/**
+ * @interface
+ */
+rrDefs.Sampler = function() {};
+
+/**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+rrDefs.Sampler.prototype.sample = function(pos, lod) {};
+
+/**
+ * @param {Array<Array<number>>} packetTexcoords 4 coordinates
+ * @param {number} lodBias
+ * @return {Array<Array<number>>} 4 vec4 samples
+ */
+rrDefs.Sampler.prototype.sample4 = function(packetTexcoords, lodBias) {};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js
new file mode 100644
index 0000000000..62a92a4227
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrGenericVector');
+
+goog.scope(function() {
+
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * rrGenericVector.GenericVecType
+ * @enum
+ */
+ rrGenericVector.GenericVecType = {
+ FLOAT: 0,
+ UINT32: 1,
+ INT32: 2
+ };
+
+ /**
+ * @constructor
+ * @param {number=} a
+ * @param {number=} b
+ * @param {number=} c
+ * @param {number=} d
+ */
+ rrGenericVector.GenericVec4 = function(a, b, c, d) {
+ this.data = [a || 0, b || 0, c || 0, d || 0];
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js
new file mode 100644
index 0000000000..6de1ca2701
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js
@@ -0,0 +1,190 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/**
+ * \brief Read-write pixel data access to multisampled buffers.
+ *
+ * Multisampled data access follows the multisampled indexing convention.
+ *
+ * Prevents accidental usage of non-multisampled buffer as multisampled
+ * with PixelBufferAccess.
+ * @constructor
+ * @param {tcuTexture.PixelBufferAccess=} rawAccess
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess = function(rawAccess) {
+ this.m_access = rawAccess || new tcuTexture.PixelBufferAccess({
+ width: 0,
+ height: 0});
+};
+
+/**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.raw = function() { return this.m_access; };
+
+/**
+ * @return {boolean}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.isEmpty = function() { return this.m_access.isEmpty(); };
+
+/**
+ * @return {number}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.getNumSamples = function() { return this.raw().getWidth(); };
+
+/**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.toSinglesampleAccess = function() {
+ DE_ASSERT(this.getNumSamples() == 1);
+
+ return new tcuTexture.PixelBufferAccess({
+ format: this.m_access.getFormat(),
+ width: this.m_access.getHeight(),
+ height: this.m_access.getDepth(),
+ depth: 1,
+ rowPitch: this.m_access.getSlicePitch(),
+ slicePitch: this.m_access.getSlicePitch() * this.m_access.getDepth(),
+ data: this.m_access.m_data,
+ offset: this.m_access.m_offset});
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} original
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess = function(original) {
+ return new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess(
+ new tcuTexture.PixelBufferAccess({
+ format: original.getFormat(),
+ width: 1,
+ height: original.getWidth(),
+ depth: original.getHeight(),
+ rowPitch: original.getFormat().getPixelSize(),
+ slicePitch: original.getRowPitch(),
+ data: original.m_data,
+ offset: original.m_offset}));
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} multisampledAccess
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess = function(multisampledAccess) {
+ return new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess(multisampledAccess);
+};
+
+/**
+ * @param {Array<number>} region
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.getSubregion = function(region) {
+ var x = region[0];
+ var y = region[1];
+ var width = region[2];
+ var height = region[3];
+
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess(tcuTextureUtil.getSubregion(this.raw(), 0, x, y, this.getNumSamples(), width, height));
+};
+
+/**
+ * @return {Array<number>} [x, y, width, height]
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.getBufferSize = function() {
+ return [0, 0, this.raw().getHeight(), this.raw().getDepth()];
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.resolveMultisampleColorBuffer = function(dst) {
+ var src = this;
+ DE_ASSERT(dst.getWidth() == src.raw().getHeight());
+ DE_ASSERT(dst.getHeight() == src.raw().getDepth());
+
+ var numSamples = src.getNumSamples();
+ var sum = [0, 0, 0, 0];
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ sum[0] = 0;
+ sum[1] = 0;
+ sum[2] = 0;
+ sum[3] = 0;
+
+ for (var s = 0; s < src.raw().getWidth(); s++) {
+ var pixel = src.raw().getPixel(s, x, y);
+ sum[0] += pixel[0];
+ sum[1] += pixel[1];
+ sum[2] += pixel[2];
+ sum[3] += pixel[3];
+ }
+
+ sum[0] /= numSamples;
+ sum[1] /= numSamples;
+ sum[2] /= numSamples;
+ sum[3] /= numSamples;
+
+ dst.setPixel(sum, x, y);
+ }
+ }
+};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {Array<number>}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.resolveMultisamplePixel = function(x, y) {
+ var sum = [0, 0, 0, 0];
+ for (var s = 0; s < this.getNumSamples(); s++)
+ sum = deMath.add(sum, this.raw().getPixel(s, x, y));
+
+ for (var i = 0; i < sum.length; i++)
+ sum[i] = sum[i] / this.getNumSamples();
+
+ return sum;
+};
+
+/**
+ * @param {Array<number>} color
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.clear = function(color) {
+ this.raw().clear(color);
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js
new file mode 100644
index 0000000000..cac4dc56a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js
@@ -0,0 +1,323 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Reference Renderer
+ * -----------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Reference renderer render state.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('framework.referencerenderer.rrRenderState');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+
+goog.scope(function() {
+
+var rrRenderState = framework.referencerenderer.rrRenderState;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var rrDefs = framework.referencerenderer.rrDefs;
+
+/**
+ * Enum for rrRenderState.HorizontalFill values.
+ * @enum {number}
+ */
+rrRenderState.HorizontalFill = {
+ LEFT: 0,
+ RIGHT: 1
+};
+
+/**
+ * Enum for rrRenderState.VerticalFill values.
+ * @enum {number}
+ */
+rrRenderState.VerticalFill = {
+ TOP: 0,
+ BOTTOM: 1
+};
+
+/**
+ * Enum for rrRenderState.Winding values.
+ * @enum {number}
+ */
+rrRenderState.Winding = {
+ CCW: 0,
+ CC: 1
+};
+
+/**
+ * Enum for rrRenderState.CullMode values.
+ * @enum {number}
+ */
+rrRenderState.CullMode = {
+ NONE: 0,
+ BACK: 1,
+ FRONT: 2
+};
+
+/**rrRenderState.Winding : rrRenderState.Winding,
+
+ * @constructor
+ */
+rrRenderState.RasterizationState = function() {
+ /** @type {number} */ this.winding = rrRenderState.Winding.CCW;
+ /** @type {number} */ this.horizontalFill = rrRenderState.HorizontalFill.LEFT;
+ /** @type {number} */ this.verticalFill = rrRenderState.VerticalFill.BOTTOM;
+};
+
+/**
+ * Enum for rrRenderState.TestFunc values.
+ * @enum {number}
+ */
+rrRenderState.TestFunc = {
+ NEVER: 0,
+ ALWAYS: 1,
+ LESS: 2,
+ LEQUAL: 3,
+ GREATER: 4,
+ GEQUAL: 5,
+ EQUAL: 6,
+ NOTEQUAL: 7
+};
+
+/**
+ * Enum for rrRenderState.StencilOp values.
+ * @enum {number}
+ */
+rrRenderState.StencilOp = {
+ KEEP: 0,
+ ZERO: 1,
+ REPLACE: 2,
+ INCR: 3, //!< Increment with saturation.
+ DECR: 4, //!< Decrement with saturation.
+ INCR_WRAP: 5,
+ DECR_WRAP: 6,
+ INVERT: 7
+};
+
+/**
+ * Enum for rrRenderState.BlendMode values.
+ * @enum {number}
+ */
+rrRenderState.BlendMode = {
+ NONE: 0, //!< No blending.
+ STANDARD: 1 //!< Standard blending.
+// Advanced blending is not supported
+// ADVANCED : 2 //!< Advanced blending mode, as defined in gl.KHR_blend_equation_advanced.
+};
+
+/**
+ * Enum for rrRenderState.BlendEquation values.
+ * @enum {number}
+ */
+rrRenderState.BlendEquation = {
+ ADD: 0,
+ SUBTRACT: 1,
+ REVERSE_SUBTRACT: 2,
+ MIN: 3,
+ MAX: 4
+};
+
+// /**
+// * Enum for rrRenderState.BlendEquationAdvanced values.
+// * @enum {number}
+// */
+// rrRenderState.BlendEquationAdvanced = {
+// MULTIPLY : 0,
+// SCREEN : 1,
+// OVERLAY : 2,
+// DARKEN : 3,
+// LIGHTEN : 4,
+// COLORDODGE : 5,
+// COLORBURN : 6,
+// HARDLIGHT : 7,
+// SOFTLIGHT : 8,
+// DIFFERENCE : 9,
+// EXCLUSION : 10,
+// HSL_HUE : 11,
+// HSL_SATURATION : 12,
+// HSL_COLOR : 13,
+// HSL_LUMINOSITY : 14
+// };
+
+/**
+ * Enum for rrRenderState.BlendFunc values.
+ * @enum {number}
+ */
+rrRenderState.BlendFunc = {
+ ZERO: 0,
+ ONE: 1,
+ SRC_COLOR: 2,
+ ONE_MINUS_SRC_COLOR: 3,
+ DST_COLOR: 4,
+ ONE_MINUS_DST_COLOR: 5,
+ SRC_ALPHA: 6,
+ ONE_MINUS_SRC_ALPHA: 7,
+ DST_ALPHA: 8,
+ ONE_MINUS_DST_ALPHA: 9,
+ CONSTANT_COLOR: 10,
+ ONE_MINUS_CONSTANT_COLOR: 11,
+ CONSTANT_ALPHA: 12,
+ ONE_MINUS_CONSTANT_ALPHA: 13,
+ SRC_ALPHA_SATURATE: 14,
+ SRC1_COLOR: 15,
+ ONE_MINUS_SRC1_COLOR: 16,
+ SRC1_ALPHA: 17,
+ ONE_MINUS_SRC1_ALPHA: 18
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.StencilState = function() {
+ /** @type {number} */ this.func = rrRenderState.TestFunc.ALWAYS;
+ /** @type {number} */ this.ref = 0;
+ /** @type {number} */ this.compMask = ~0;
+ /** @type {number} */ this.sFail = rrRenderState.StencilOp.KEEP;
+ /** @type {number} */ this.dpFail = rrRenderState.StencilOp.KEEP;
+ /** @type {number} */ this.dpPass = rrRenderState.StencilOp.KEEP;
+ /** @type {number} */ this.writeMask = ~0;
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.BlendState = function() {
+ /** @type {number} */ this.equation = rrRenderState.BlendEquation.ADD;
+ /** @type {number} */ this.srcFunc = rrRenderState.BlendFunc.ONE;
+ /** @type {number} */ this.dstFunc = rrRenderState.BlendFunc.ZERO;
+};
+
+/**
+ * @param {(Array<number>|number)} left_
+ * @param {number=} bottom_
+ * @param {number=} width_
+ * @param {number=} height_
+ * @constructor
+ */
+rrRenderState.WindowRectangle = function(left_, bottom_, width_, height_) {
+ // Is first parameter an array? Use it
+ if (left_.length && left_.length == 4) {
+ this.left = left_[0];
+ this.bottom = left_[1];
+ this.width = left_[2];
+ this.height = left_[3];
+ } else {
+ this.left = left_;
+ this.bottom = bottom_;
+ this.width = width_;
+ this.height = height_;
+ }
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.FragmentOperationState = function() {
+ /** @type {boolean} */ this.scissorTestEnabled = false;
+ /** @type {rrRenderState.WindowRectangle} */ this.scissorRectangle = new rrRenderState.WindowRectangle(0, 0, 1, 1);
+
+ /** @type {boolean} */ this.stencilTestEnabled = false;
+
+ /** @type {Array<rrRenderState.StencilState>} */ this.stencilStates = [];
+ for (var type in rrDefs.FaceType)
+ this.stencilStates[rrDefs.FaceType[type]] = new rrRenderState.StencilState();
+
+ /** @type {boolean} */ this.depthTestEnabled = false;
+ /** @type {rrRenderState.TestFunc} */ this.depthFunc = rrRenderState.TestFunc.LESS;
+ /** @type {boolean} */ this.depthMask = true;
+
+ /** @type {rrRenderState.BlendMode} */ this.blendMode = rrRenderState.BlendMode.NONE;
+ /** @type {rrRenderState.BlendState} */ this.blendRGBState = new rrRenderState.BlendState();
+ /** @type {rrRenderState.BlendState} */ this.blendAState = new rrRenderState.BlendState();
+ /** @type {Array<number>} */ this.blendColor = [0.0, 0.0, 0.0, 0.0];
+// /** @type {rrRenderState.BlendEquationAdvanced} */ this.blendEquationAdvanced = null;
+
+ /** @type {boolean} */ this.sRGBEnabled = true;
+
+ /** @type {boolean} */ this.depthClampEnabled = false;
+
+ /** @type {boolean} */ this.polygonOffsetEnabled = false;
+ /** @type {number} */ this.polygonOffsetFactor = 0.0;
+ /** @type {number} */ this.polygonOffsetUnits = 0.0;
+
+ /** @type {Array<boolean>} */ this.colorMask = [true, true, true, true];
+
+ /** @type {number} */ this.numStencilBits = 8;
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.PointState = function() {
+ /** @type {number} */ this.pointSize = 1.0;
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.LineState = function() {
+ /** @type {number} */ this.lineWidth = 1.0;
+};
+
+/**
+ * Constructor checks if the parameter has a "raw" member to detect if the instance is
+ * of type rrRenderState.WindowRectangle or MultisamplePixelBufferAccess.
+ * @param {rrRenderState.WindowRectangle|rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} rect_
+ * @constructor
+ */
+rrRenderState.ViewportState = function(rect_) {
+ /** @type {number} */ this.zn = 0.0;
+ /** @type {number} */ this.zf = 1.0;
+ /** @type {rrRenderState.WindowRectangle} */ this.rect;
+
+ if (rect_.raw) {
+ this.rect = new rrRenderState.WindowRectangle(0, 0, rect_.raw().getHeight(),
+ rect_.raw().getDepth());
+ } else {
+ this.rect = /** @type {rrRenderState.WindowRectangle} */ (rect_);
+ }
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.RestartState = function() {
+ /** @type {boolean} */ this.enabled = false;
+ /** @type {number} */ this.restartIndex = 0xFFFFFFFF;
+};
+
+/**
+ * @constructor
+ * @param {rrRenderState.ViewportState} viewport_
+ */
+rrRenderState.RenderState = function(viewport_) {
+ /** @type {rrRenderState.CullMode} */ this.cullMode = rrRenderState.CullMode.NONE;
+ /** @type {number} */ this.provokingVertexConvention;
+ /** @type {rrRenderState.ViewportState} */ this.viewport = viewport_;
+
+ /** @type {rrRenderState.RasterizationState} */ this.rasterization = new rrRenderState.RasterizationState();
+ /** @type {rrRenderState.FragmentOperationState} */ this.fragOps = new rrRenderState.FragmentOperationState();
+ /** @type {rrRenderState.PointState} */ this.point = new rrRenderState.PointState();
+ /** @type {rrRenderState.LineState} */ this.line = new rrRenderState.LineState();
+ /** @type {rrRenderState.RestartState} */ this.restart = new rrRenderState.RestartState();
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js
new file mode 100644
index 0000000000..4d5752b2c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js
@@ -0,0 +1,1274 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrRenderer');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.referencerenderer.rrRenderState');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+var rrRenderer = framework.referencerenderer.rrRenderer;
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+var rrDefs = framework.referencerenderer.rrDefs;
+var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+var deMath = framework.delibs.debase.deMath;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var rrRenderState = framework.referencerenderer.rrRenderState;
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var rrShadingContext = framework.referencerenderer.rrShadingContext;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var deString = framework.delibs.debase.deString;
+var deUtil = framework.delibs.debase.deUtil;
+
+/**
+ * @enum
+ */
+rrRenderer.PrimitiveType = {
+ TRIANGLES: 0, //!< Separate rrRenderer.triangles
+ TRIANGLE_STRIP: 1, //!< rrRenderer.Triangle strip
+ TRIANGLE_FAN: 2, //!< rrRenderer.Triangle fan
+
+ LINES: 3, //!< Separate lines
+ LINE_STRIP: 4, //!< Line strip
+ LINE_LOOP: 5, //!< Line loop
+
+ POINTS: 6 //!< Points
+};
+
+// /**
+// * @constructor
+// * @param {boolean} depthEnabled Is depth buffer enabled
+// */
+// rrRenderer.RasterizationInternalBuffers = function(depthEnabled) {
+// /*std::vector<rrFragmentOperations.Fragment>*/ this.fragmentPackets = [];
+// /*std::vector<GenericVec4>*/ this.shaderOutputs = [];
+// /*std::vector<Fragment>*/ this.shadedFragments = [];
+// /*float**/ this.fragmentDepthBuffer = depthEnabled ? [] : null;
+// };
+
+/**
+ * @constructor
+ * @param {number=} id
+ */
+rrRenderer.DrawContext = function(id) {
+ this.primitiveID = id || 0;
+
+};
+
+/**
+ * Transform [x, y] to window (pixel) coordinates.
+ * z and w are unchanged
+ * @param {rrRenderState.RenderState} state
+ * @param {rrVertexPacket.VertexPacket} packet
+ * Wreturn {Array<number>}
+ */
+rrRenderer.transformGLToWindowCoords = function(state, packet) {
+ var transformed = [packet.position[0] / packet.position[3],
+ packet.position[1] / packet.position[3],
+ packet.position[2],
+ packet.position[3]];
+ var viewport = state.viewport.rect;
+ var halfW = viewport.width / 2;
+ var halfH = viewport.height / 2;
+ var oX = viewport.left + halfW;
+ var oY = viewport.bottom + halfH;
+
+ return [
+ transformed[0] * halfW + oX,
+ transformed[1] * halfH + oY,
+ transformed[2],
+ transformed[3]
+ ];
+};
+
+/**
+ * @constructor
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} colorMultisampleBuffer
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess=} depthMultisampleBuffer
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess=} stencilMultisampleBuffer
+ */
+rrRenderer.RenderTarget = function(colorMultisampleBuffer, depthMultisampleBuffer, stencilMultisampleBuffer) {
+ this.MAX_COLOR_BUFFERS = 4;
+ this.colorBuffers = [];
+ this.colorBuffers[0] = colorMultisampleBuffer;
+ this.depthBuffer = depthMultisampleBuffer || new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess();
+ this.stencilBuffer = stencilMultisampleBuffer || new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess();
+ this.numColorBuffers = 1;
+};
+
+// NOTE: Program object is useless. Let's just use the sglrShaderProgram
+// /**
+// * @constructor
+// * @param {rrShaders.VertexShader} vertexShader_
+// * @param {rrShaders.FragmentShader} fragmentShader_
+// */
+// var Program = function(vertexShader_, fragmentShader_) {
+// this.vertexShader = vertexShader_;
+// this.fragmentShader = fragmentShader_;
+// };
+
+/**
+ * @constructor
+ * @param {ArrayBuffer} data
+ * @param {rrDefs.IndexType} type
+ * @param {number} offset
+ * @param {number=} baseVertex_
+ */
+rrRenderer.DrawIndices = function(data, type, offset, baseVertex_) {
+ /** @type {ArrayBuffer} */ this.data = data;
+ /** @type {number} */ this.baseVertex = baseVertex_ || 0;
+ /** @type {rrDefs.IndexType} */ this.indexType = type;
+ /** @type {goog.NumberArray} */ this.access = null;
+ switch (type) {
+ case rrDefs.IndexType.INDEXTYPE_UINT8: this.access = new Uint8Array(data).subarray(offset); break;
+ case rrDefs.IndexType.INDEXTYPE_UINT16: this.access = new Uint16Array(data).subarray(offset / 2); break;
+ case rrDefs.IndexType.INDEXTYPE_UINT32: this.access = new Uint32Array(data).subarray(offset / 4); break;
+ default: throw new Error('Invalid type: ' + type);
+ }
+};
+
+/**
+ * @return {number}
+ */
+rrRenderer.DrawIndices.prototype.readIndexArray = function(index) { return this.access[index]; };
+
+/**
+ * @constructor
+ * @param {rrRenderer.PrimitiveType} primitiveType
+ * @param {number} numElements
+ * @param {(number|rrRenderer.DrawIndices)} indices
+ */
+rrRenderer.PrimitiveList = function(primitiveType, numElements, indices) {
+ /** @type {rrRenderer.PrimitiveType} */ this.m_primitiveType = primitiveType;
+ /** @type {number} */ this.m_numElements = numElements;
+ if (typeof indices == 'number') {
+ // !< primitive list for drawArrays-like call
+ this.m_indices = null;
+ this.m_indexType = null;
+ this.m_baseVertex = indices;
+ } else {
+ // !< primitive list for drawElements-like call
+ this.m_indices = indices;
+ this.m_indexType = indices.indexType;
+ this.m_baseVertex = indices.baseVertex;
+ }
+ this.m_iterator = 0;
+};
+
+/**
+ * @param {number} elementNdx
+ * @return {number}
+ */
+rrRenderer.PrimitiveList.prototype.getIndex = function(elementNdx) {
+ if (this.m_indices) {
+ var index = this.m_baseVertex + this.m_indices.readIndexArray(elementNdx);
+ if (index < 0)
+ throw new Error('Index must not be negative');
+
+ return index;
+ } else
+ return this.m_baseVertex + elementNdx;
+};
+
+/**
+ * @param {number} elementNdx
+ * @param {number} restartIndex
+ * @return {boolean}
+ */
+rrRenderer.PrimitiveList.prototype.isRestartIndex = function(elementNdx, restartIndex) {
+ // implicit index or explicit index (without base vertex) equals restart
+ if (this.m_indices)
+ return this.m_indices.readIndexArray(elementNdx) == restartIndex;
+ else
+ return elementNdx == restartIndex;
+};
+
+/**
+ * @return {number}
+ */
+rrRenderer.PrimitiveList.prototype.getNumElements = function() {return this.m_numElements;};
+
+/**
+ * @return {rrRenderer.PrimitiveType}
+ */
+rrRenderer.PrimitiveList.prototype.getPrimitiveType = function() {return this.m_primitiveType;};
+
+/**
+ * @return {?rrDefs.IndexType}
+ */
+rrRenderer.PrimitiveList.prototype.getIndexType = function() {return this.m_indexType;};
+
+/**
+ * Generate a primitive from indices
+ * @param {boolean=} reset Restart generating primitives. Default false
+ * @return {Array<number>}
+ */
+rrRenderer.PrimitiveList.prototype.getNextPrimitive = function(reset) {
+ if (reset)
+ this.m_iterator = 0;
+ var result = [];
+ var i = this.m_iterator;
+ switch (this.m_primitiveType) {
+ case rrRenderer.PrimitiveType.TRIANGLES:
+ if (this.m_iterator + 3 <= this.m_numElements) {
+ result = [i, i + 1, i + 2];
+ this.m_iterator += 3;
+ }
+ break;
+ case rrRenderer.PrimitiveType.TRIANGLE_STRIP:
+ if (this.m_iterator + 3 <= this.m_numElements) {
+ result = [i, i + 1, i + 2];
+ this.m_iterator += 1;
+ }
+ break;
+ case rrRenderer.PrimitiveType.TRIANGLE_FAN:
+ if (this.m_iterator + 3 <= this.m_numElements) {
+ result = [0, i + 1, i + 2];
+ this.m_iterator += 1;
+ }
+ break;
+ case rrRenderer.PrimitiveType.LINES:
+ if (this.m_iterator + 2 <= this.m_numElements) {
+ result = [i, i + 1];
+ this.m_iterator += 2;
+ }
+ break;
+ case rrRenderer.PrimitiveType.LINE_STRIP:
+ if (this.m_iterator + 2 <= this.m_numElements) {
+ result = [i, i + 1];
+ this.m_iterator += 1;
+ }
+ break;
+ case rrRenderer.PrimitiveType.LINE_LOOP:
+ if (this.m_iterator == this.m_numElements)
+ break;
+ if (this.m_iterator + 2 <= this.m_numElements)
+ result = [i, i + 1];
+ else
+ result = [i, 0];
+ this.m_iterator += 1;
+ break;
+ case rrRenderer.PrimitiveType.POINTS:
+ if (this.m_iterator == this.m_numElements)
+ break;
+ else
+ result = [i];
+ this.m_iterator += 1;
+ break;
+ default:
+ throw new Error('Unsupported primitive type: ' + deString.enumToString(rrRenderer.PrimitiveType, this.m_primitiveType));
+ }
+
+ return result;
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {Array<rrFragmentOperations.Fragment>} fragments Fragments to write
+*/
+rrRenderer.writeFragments = function(state, renderTarget, fragments) {
+ /* TODO: Add blending, depth, stencil ... */
+ var colorbuffer = renderTarget.colorBuffers[0].raw();
+ for (var i = 0; i < fragments.length; i++) {
+ var fragment = fragments[i];
+ colorbuffer.setPixel(fragment.value, 0, fragment.pixelCoord[0], fragment.pixelCoord[1]);
+ }
+
+};
+
+/**
+ * @param {rrRenderState.RenderState} renderState
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {Array<rrFragmentOperations.Fragment>} fragments Fragments to write
+*/
+rrRenderer.writeFragments2 = function(renderState, renderTarget, fragments) {
+ /*
+void FragmentProcessor::render (const rr::MultisamplePixelBufferAccess& msColorBuffer,
+ const rr::MultisamplePixelBufferAccess& msDepthBuffer,
+ const rr::MultisamplePixelBufferAccess& msStencilBuffer,
+ const Fragment* fragments,
+ int numFragments,
+ FaceType fragmentFacing,
+ const FragmentOperationState& state)
+*/
+
+ /** @const */ var fragmentFacing = rrDefs.FaceType.FACETYPE_FRONT;
+ var colorBuffer = renderTarget.colorBuffers[0].raw();
+ var depthBuffer = renderTarget.depthBuffer.raw();
+ var stencilBuffer = renderTarget.stencilBuffer.raw();
+ var state = renderState.fragOps;
+
+ var hasDepth = depthBuffer.getWidth() > 0 && depthBuffer.getHeight() > 0 && depthBuffer.getDepth() > 0;
+ var hasStencil = stencilBuffer.getWidth() > 0 && stencilBuffer.getHeight() > 0 && stencilBuffer.getDepth() > 0;
+ var doDepthTest = hasDepth && state.depthTestEnabled;
+ var doStencilTest = hasStencil && state.stencilTestEnabled;
+
+ var colorbufferClass = tcuTexture.getTextureChannelClass(colorBuffer.getFormat().type);
+ var fragmentDataType = rrGenericVector.GenericVecType.FLOAT;
+ switch (colorbufferClass) {
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ fragmentDataType = rrGenericVector.GenericVecType.INT32;
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ fragmentDataType = rrGenericVector.GenericVecType.UINT32;
+ break;
+ }
+
+ if (!((!hasDepth || colorBuffer.getWidth() == depthBuffer.getWidth()) && (!hasStencil || colorBuffer.getWidth() == stencilBuffer.getWidth())))
+ throw new Error('Attachment must have the same width');
+ if (!((!hasDepth || colorBuffer.getHeight() == depthBuffer.getHeight()) && (!hasStencil || colorBuffer.getHeight() == stencilBuffer.getHeight())))
+ throw new Error('Attachment must have the same height');
+ if (!((!hasDepth || colorBuffer.getDepth() == depthBuffer.getDepth()) && (!hasStencil || colorBuffer.getDepth() == stencilBuffer.getDepth())))
+ throw new Error('Attachment must have the same depth');
+
+ var stencilState = state.stencilStates[fragmentFacing];
+ var colorMaskFactor = [state.colorMask[0] ? 1 : 0, state.colorMask[1] ? 1 : 0, state.colorMask[2] ? 1 : 0, state.colorMask[3] ? 1 : 0];
+ var colorMaskNegationFactor = [state.colorMask[0] ? false : true, state.colorMask[1] ? false : true, state.colorMask[2] ? false : true, state.colorMask[3] ? false : true];
+ var sRGBTarget = state.sRGBEnabled && colorBuffer.getFormat().isSRGB();
+
+ // Scissor test.
+
+ if (state.scissorTestEnabled)
+ rrFragmentOperations.executeScissorTest(fragments, state.scissorRectangle);
+
+ // Stencil test.
+
+ if (doStencilTest) {
+ rrFragmentOperations.executeStencilCompare(fragments, stencilState, state.numStencilBits, stencilBuffer);
+ rrFragmentOperations.executeStencilSFail(fragments, stencilState, state.numStencilBits, stencilBuffer);
+ }
+
+ // Depth test.
+ // \note Current value of isAlive is needed for dpPass and dpFail, so it's only updated after them and not right after depth test.
+
+ if (doDepthTest) {
+ rrFragmentOperations.executeDepthCompare(fragments, state.depthFunc, depthBuffer);
+
+ if (state.depthMask)
+ rrFragmentOperations.executeDepthWrite(fragments, depthBuffer);
+ }
+
+ // Do dpFail and dpPass stencil writes.
+
+ if (doStencilTest)
+ rrFragmentOperations.executeStencilDpFailAndPass(fragments, stencilState, state.numStencilBits, stencilBuffer);
+
+ // Kill the samples that failed depth test.
+
+ if (doDepthTest) {
+ for (var i = 0; i < fragments.length; i++)
+ fragments[i].isAlive = fragments[i].isAlive && fragments[i].depthPassed;
+ }
+
+ // Paint fragments to target
+
+ switch (fragmentDataType) {
+ case rrGenericVector.GenericVecType.FLOAT:
+ // Blend calculation - only if using blend.
+ if (state.blendMode == rrRenderState.BlendMode.STANDARD) {
+ // Put dst color to register, doing srgb-to-linear conversion if needed.
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ var dstColor = colorBuffer.getPixel(0, frag.pixelCoord[0], frag.pixelCoord[1]);
+
+ /* TODO: Check frag.value and frag.value1 types */
+ frag.clampedBlendSrcColor = deMath.clampVector(frag.value, 0, 1);
+ frag.clampedBlendSrc1Color = deMath.clampVector(frag.value1, 0, 1);
+ frag.clampedBlendDstColor = deMath.clampVector(sRGBTarget ? tcuTexture.sRGBToLinear(dstColor) : dstColor, 0, 1);
+ }
+ }
+
+ // Calculate blend factors to register.
+ rrFragmentOperations.executeBlendFactorComputeRGB(fragments, state.blendColor, state.blendRGBState);
+ rrFragmentOperations.executeBlendFactorComputeA(fragments, state.blendColor, state.blendAState);
+
+ // Compute blended color.
+ rrFragmentOperations.executeBlend(fragments, state.blendRGBState, state.blendAState);
+ } else {
+ // Not using blend - just put values to register as-is.
+
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ frag.blendedRGB = deMath.swizzle(frag.value, [0, 1, 2]);
+ frag.blendedA = frag.value[3];
+ }
+ }
+ }
+
+ // Finally, write the colors to the color buffer.
+
+ if (state.colorMask[0] && state.colorMask[1] && state.colorMask[2] && state.colorMask[3]) {
+ /* TODO: Add quick path */
+ // if (colorBuffer.getFormat().isEqual(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)))
+ // executeRGBA8ColorWrite(fragments, colorBuffer);
+ // else
+ rrFragmentOperations.executeColorWrite(fragments, sRGBTarget, colorBuffer);
+ } else if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
+ rrFragmentOperations.executeMaskedColorWrite(fragments, colorMaskFactor, colorMaskNegationFactor, sRGBTarget, colorBuffer);
+ break;
+
+ case rrGenericVector.GenericVecType.INT32:
+ // Write fragments
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ frag.signedValue = frag.value;
+ }
+ }
+
+ if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
+ rrFragmentOperations.executeSignedValueWrite(fragments, state.colorMask, colorBuffer);
+ break;
+
+ case rrGenericVector.GenericVecType.UINT32:
+ // Write fragments
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ frag.unsignedValue = frag.value;
+ }
+ }
+
+ if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
+ rrFragmentOperations.executeUnsignedValueWrite(fragments, state.colorMask, colorBuffer);
+ break;
+
+ default:
+ throw new Error('Unrecognized fragment data type:' + fragmentDataType);
+ }
+};
+
+/**
+ * Determines the index of the corresponding vertex according to top/right conditions.
+ * @param {boolean} isTop
+ * @param {boolean} isRight
+ * @return {number}
+ */
+rrRenderer.getIndexOfCorner = function(isTop, isRight, vertexPackets) {
+ var x = null;
+ var y = null;
+
+ var xcriteria = isRight ? Math.max : Math.min;
+ var ycriteria = isTop ? Math.max : Math.min;
+
+ // Determine corner values
+ for (var i = 0; i < vertexPackets.length; i++) {
+ x = x != null ? xcriteria(vertexPackets[i].position[0], x) : vertexPackets[i].position[0];
+ y = y != null ? ycriteria(vertexPackets[i].position[1], y) : vertexPackets[i].position[1];
+ }
+
+ // Search for matching vertex
+ for (var v = 0; v < vertexPackets.length; v++)
+ if (vertexPackets[v].position[0] == x &&
+ vertexPackets[v].position[1] == y)
+ return v;
+
+ throw new Error('Corner not found');
+};
+
+/**
+ * Check that point is in the clipping volume
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {rrRenderState.WindowRectangle} rect
+ * @return {boolean}
+ */
+rrRenderer.clipTest = function(x, y, z, rect) {
+ x = Math.round(x);
+ y = Math.round(y);
+ if (!deMath.deInBounds32(x, rect.left, rect.left + rect.width))
+ return false;
+ if (!deMath.deInBounds32(y, rect.bottom, rect.bottom + rect.height))
+ return false;
+ if (z < 0 || z > 1)
+ return false;
+ return true;
+};
+
+// Rasterizer configuration
+rrRenderer.RASTERIZER_SUBPIXEL_BITS = 8;
+rrRenderer.RASTERIZER_MAX_SAMPLES_PER_FRAGMENT = 16;
+
+// Referenced from rrRasterizer.hpp
+
+/**
+ * Get coverage bit value
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @param {number} sampleNdx
+ * @return {number}
+ */
+rrRenderer.getCoverageBit = function(numSamples, x, y, sampleNdx) {
+ var maxSamples = 16;
+ assertMsgOptions(maxSamples >= rrRenderer.RASTERIZER_MAX_SAMPLES_PER_FRAGMENT, 'maxSamples should not greater than ' + rrRenderer.RASTERIZER_MAX_SAMPLES_PER_FRAGMENT, false, true);
+ assertMsgOptions(deMath.deInRange32(numSamples, 1, maxSamples) && deMath.deInBounds32(x, 0, 2) && deMath.deInBounds32(y, 0, 2), 'numSamples, x or y not in bound', false, true);
+ return 1 << ((x * 2 + y) * numSamples + sampleNdx);
+};
+
+/**
+ * Get all sample bits for fragment
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+rrRenderer.getCoverageFragmentSampleBits = function(numSamples, x, y) {
+ assertMsgOptions(deMath.deInBounds32(x, 0, 2) && deMath.deInBounds32(y, 0, 2), 'x or y is not in bound 0 to 2', false, true);
+ var fragMask = (1 << numSamples) - 1;
+ return fragMask << (x * 2 + y) * numSamples;
+};
+
+/**
+ * Set coverage bit in coverage mask
+ * @param {number} mask
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @param {number} sampleNdx
+ * @param {number} val
+ * @return {number}
+ */
+rrRenderer.setCoverageValue = function(mask, numSamples, x, y, sampleNdx, val) {
+ var bit = rrRenderer.getCoverageBit(numSamples, x, y, sampleNdx);
+ return val ? (mask | bit) : (mask & ~bit);
+};
+
+/**
+ * Test if any sample for fragment is live
+ * @param {number} mask
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+rrRenderer.getCoverageAnyFragmentSampleLive = function(mask, numSamples, x, y) {
+ return (mask & rrRenderer.getCoverageFragmentSampleBits(numSamples, x, y)) != 0;
+};
+
+// Referenced from rrRasterizer.cpp
+
+/**
+ * Pixel coord to sub pixel coord
+ * @param {number} v
+ * @return {number}
+ */
+rrRenderer.toSubpixelCoord = function(v) {
+ return Math.trunc(v * (1 << rrRenderer.RASTERIZER_SUBPIXEL_BITS) + (v < 0 ? -0.5 : 0.5));
+};
+
+/**
+ * Floor sub pixel coord to pixel coord
+ * @param {number} coord
+ * @param {boolean} fillEdge
+ * @return {number}
+ */
+rrRenderer.floorSubpixelToPixelCoord = function(coord, fillEdge) {
+ if (coord >= 0)
+ return Math.trunc((coord - (fillEdge ? 1 : 0)) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+ else
+ return Math.trunc((coord - ((1 << rrRenderer.RASTERIZER_SUBPIXEL_BITS) - (fillEdge ? 0 : 1))) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+};
+
+/**
+ * Ceil sub pixel coord to pixel coord
+ * @param {number} coord
+ * @param {boolean} fillEdge
+ * @return {number}
+ */
+rrRenderer.ceilSubpixelToPixelCoord = function(coord, fillEdge) {
+ if (coord >= 0)
+ return Math.trunc((coord + (1 << rrRenderer.RASTERIZER_SUBPIXEL_BITS) - (fillEdge ? 0 : 1)) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+ else
+ return Math.trunc((coord + (fillEdge ? 1 : 0)) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+};
+
+/**
+ * \brief Edge function - referenced from struct EdgeFunction in rrRasterizer.hpp
+ *
+ * Edge function can be evaluated for point P (in a fixed-point coordinates
+ * with RASTERIZER_SUBPIXEL_BITS fractional part) by computing
+ * D = a * Px + b * Py + c
+ *
+ * D will be fixed-point value where lower (RASTERIZER_SUBPIXEL_BITS * 2) bits
+ * will be fractional part.
+ *
+ * Member function evaluateEdge, reverseEdge and isInsideCCW are referenced from rrRasterizer.cpp.
+ *
+ * @param {number} a
+ * @param {number} b
+ * @param {number} c
+ * @param {boolean} inclusive
+ */
+rrRenderer.edgeFunction = function(a, b, c, inclusive) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.inclusive = inclusive; // True if edge is inclusive according to fill rules
+};
+
+/**
+ * Evaluate point (x,y)
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+rrRenderer.edgeFunction.prototype.evaluateEdge = function(x, y) {
+ return this.a * x + this.b * y + this.c;
+};
+
+/**
+ * Reverse edge (e.g. from CCW to CW)
+ */
+rrRenderer.edgeFunction.prototype.reverseEdge = function () {
+ this.a = -this.a;
+ this.b = -this.b;
+ this.c = -this.c;
+ this.inclusive = !this.inclusive;
+};
+
+/**
+ * Determine if a point with value edgeVal is inside the CCW region of the edge
+ * @param {number} edgeVal
+ * @return {boolean}
+ */
+rrRenderer.edgeFunction.prototype.isInsideCCW = function(edgeVal) {
+ return this.inclusive ? edgeVal >= 0 : edgeVal > 0;
+};
+
+/**
+ * Init an edge function in counter-clockwise (CCW) orientation
+ * @param {number} horizontalFill
+ * @param {number} verticalFill
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} x1
+ * @param {number} y1
+ * @return {rrRenderer.edgeFunction}
+ */
+rrRenderer.initEdgeCCW = function(horizontalFill, verticalFill, x0, y0, x1, y1) {
+ var xd = x1 - x0;
+ var yd = y1 - y0;
+ var inclusive = false;
+
+ if (yd == 0)
+ inclusive = verticalFill == rrRenderState.VerticalFill.BOTTOM ? xd >= 0 : xd <= 0;
+ else
+ inclusive = horizontalFill == rrRenderState.HorizontalFill.LEFT ? yd <= 0 : yd >=0;
+
+ return new rrRenderer.edgeFunction(y0 - y1, x1 - x0, x0 * y1 - y0 * x1, inclusive);
+};
+
+/**
+ * \brief Triangle rasterizer - referenced from class TriangleRasterizer in rrRasterizer.hpp
+ *
+ * Triangle rasterizer implements following features:
+ * - Rasterization using fixed-point coordinates
+ * - 1-sample rasterization (the value of numSamples always equals 1 in sglrReferenceContext)
+ * - Depth interpolation
+ * - Perspective-correct barycentric computation for interpolation
+ * - Visible face determination
+ * - Clipping - native dEQP does clipping before rasterization; see function drawBasicPrimitives
+ * in rrRenderer.cpp for more details
+ *
+ * It does not (and will not) implement following:
+ * - Triangle setup
+ * - Degenerate elimination
+ * - Coordinate transformation (inputs are in screen-space)
+ * - Culling - logic can be implemented outside by querying visible face
+ * - Scissoring - (this can be done by controlling viewport rectangle)
+ * - Any per-fragment operations
+ *
+ * @param {rrRenderState.RenderState} state
+ */
+rrRenderer.triangleRasterizer = function(state) {
+ this.m_viewport = state.viewport;
+ this.m_winding = state.rasterization.winding;
+ this.m_horizontalFill = state.rasterization.horizontalFill;
+ this.m_verticalFill = state.rasterization.verticalFill;
+};
+
+/**
+ * Initialize triangle rasterization
+ * @param {vec} v0 Screen-space coordinates (x, y, z) and 1/w for vertex 0
+ * @param {vec} v1 Screen-space coordinates (x, y, z) and 1/w for vertex 1
+ * @param {vec} v2 Screen-space coordinates (x, y, z) and 1/w for vertex 2
+ */
+rrRenderer.triangleRasterizer.prototype.init = function(v0, v1, v2) {
+ this.m_v0 = v0;
+ this.m_v1 = v1;
+ this.m_v2 = v2;
+
+ // Positions in fixed-point coordinates
+ var x0 = rrRenderer.toSubpixelCoord(v0[0]);
+ var y0 = rrRenderer.toSubpixelCoord(v0[1]);
+ var x1 = rrRenderer.toSubpixelCoord(v1[0]);
+ var y1 = rrRenderer.toSubpixelCoord(v1[1]);
+ var x2 = rrRenderer.toSubpixelCoord(v2[0]);
+ var y2 = rrRenderer.toSubpixelCoord(v2[1]);
+
+ // Initialize edge functions
+ if (this.m_winding == rrRenderState.Winding.CCW) {
+ this.m_edge01 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x0, y0, x1, y1);
+ this.m_edge12 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x1, y1, x2, y2);
+ this.m_edge20 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x2, y2, x0, y0);
+ } else {
+ // Reverse edges
+ this.m_edge01 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x1, y1, x0, y0);
+ this.m_edge12 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x2, y2, x1, y1);
+ this.m_edge20 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x0, y0, x2, y2);
+ }
+
+ // Determine face
+ var s = this.m_edge01.evaluateEdge(x2, y2);
+ var positiveArea = (this.m_winding == rrRenderState.Winding.CCW ) ? s > 0 : s < 0;
+ this.m_face = positiveArea ? rrDefs.FaceType.FACETYPE_FRONT : rrDefs.FaceType.FACETYPE_BACK;
+ if (!positiveArea) {
+ // Reverse edges so that we can use CCW area tests & interpolation
+ this.m_edge01.reverseEdge();
+ this.m_edge12.reverseEdge();
+ this.m_edge20.reverseEdge();
+ }
+
+ // Bounding box
+ var minX = Math.min(x0, x1, x2);
+ var maxX = Math.max(x0, x1, x2);
+ var minY = Math.min(y0, y1, y2);
+ var maxY = Math.max(y0, y1, y2);
+
+ this.m_bboxMin = [];
+ this.m_bboxMax = [];
+ this.m_bboxMin[0] = rrRenderer.floorSubpixelToPixelCoord(minX, this.m_horizontalFill == rrRenderState.HorizontalFill.LEFT);
+ this.m_bboxMin[1] = rrRenderer.floorSubpixelToPixelCoord(minY, this.m_verticalFill == rrRenderState.VerticalFill.BOTTOM);
+ this.m_bboxMax[0] = rrRenderer.ceilSubpixelToPixelCoord(maxX, this.m_horizontalFill == rrRenderState.HorizontalFill.RIGHT);
+ this.m_bboxMax[1] = rrRenderer.ceilSubpixelToPixelCoord(maxY, this.m_verticalFill == rrRenderState.VerticalFill.TOP);
+
+ // Clamp to viewport
+ var wX0 = this.m_viewport.rect.left;
+ var wY0 = this.m_viewport.rect.bottom;
+ var wX1 = wX0 + this.m_viewport.rect.width - 1;
+ var wY1 = wY0 + this.m_viewport.rect.height - 1;
+
+ this.m_bboxMin[0] = deMath.clamp(this.m_bboxMin[0], wX0, wX1);
+ this.m_bboxMin[1] = deMath.clamp(this.m_bboxMin[1], wY0, wY1);
+ this.m_bboxMax[0] = deMath.clamp(this.m_bboxMax[0], wX0, wX1);
+ this.m_bboxMax[1] = deMath.clamp(this.m_bboxMax[1], wY0, wY1);
+
+ this.m_curPos = [this.m_bboxMin[0], this.m_bboxMin[1]];
+};
+
+rrRenderer.triangleRasterizer.prototype.rasterize = function() {
+ var fragmentPackets = [];
+ var halfPixel = 1 << (rrRenderer.RASTERIZER_SUBPIXEL_BITS - 1);
+
+ // For depth interpolation; given barycentrics A, B, C = (1 - A -B)
+ // We can reformulate the usual z = z0 * A + z1 * B + z2 * C into more
+ // stable equation z = A * (z0 - z2) + B * (z1 - z2) + z2
+ var za = this.m_v0[2] - this.m_v2[2];
+ var zb = this.m_v1[2] - this.m_v2[2];
+ var zc = this.m_v2[2];
+
+ var zn = this.m_viewport.zn;
+ var zf = this.m_viewport.zf;
+ var depthScale = (zf - zn) / 2;
+ var depthBias = (zf + zn) / 2;
+
+ while (this.m_curPos[1] <= this.m_bboxMax[1]) {
+ var x0 = this.m_curPos[0];
+ var y0 = this.m_curPos[1];
+
+ // Subpixel coords of (x0, y0), (x0 + 1, y0), (x0, y0 + 1), (x0 + 1, y0 + 1)
+ var sx0 = rrRenderer.toSubpixelCoord(x0) + halfPixel;
+ var sx1 = rrRenderer.toSubpixelCoord(x0 + 1) + halfPixel;
+ var sy0 = rrRenderer.toSubpixelCoord(y0) + halfPixel;
+ var sy1 = rrRenderer.toSubpixelCoord(y0 + 1) + halfPixel;
+
+ var sx = [sx0, sx1, sx0, sx1];
+ var sy = [sy0, sy0, sy1, sy1];
+
+ // Viewport test
+ var outX1 = x0 + 1 == this.m_viewport.rect.left + this.m_viewport.rect.width;
+ var outY1 = y0 + 1 == this.m_viewport.rect.bottom + this.m_viewport.rect.height;
+
+ // Coverage
+ var coverage = 0;
+
+ // Evaluate edge values
+ var e01 = [];
+ var e12 = [];
+ var e20 = [];
+ for (var i = 0; i < 4; i++) {
+ e01.push(this.m_edge01.evaluateEdge(sx[i], sy[i]));
+ e12.push(this.m_edge12.evaluateEdge(sx[i], sy[i]));
+ e20.push(this.m_edge20.evaluateEdge(sx[i], sy[i]));
+ }
+
+ // Compute coverage mask
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 0, 0, 0, this.m_edge01.isInsideCCW(e01[0]) && this.m_edge12.isInsideCCW(e12[0]) && this.m_edge20.isInsideCCW(e20[0]));
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 1, 0, 0, !outX1 && this.m_edge01.isInsideCCW(e01[1]) && this.m_edge12.isInsideCCW(e12[1]) && this.m_edge20.isInsideCCW(e20[1]));
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 0, 1, 0, !outY1 && this.m_edge01.isInsideCCW(e01[2]) && this.m_edge12.isInsideCCW(e12[2]) && this.m_edge20.isInsideCCW(e20[2]));
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 1, 1, 0, !outX1 && !outY1 && this.m_edge01.isInsideCCW(e01[3]) && this.m_edge12.isInsideCCW(e12[3]) && this.m_edge20.isInsideCCW(e20[3]));
+
+ // Advance to next location
+ this.m_curPos[0] += 2;
+ if (this.m_curPos[0] > this.m_bboxMax[0]) {
+ this.m_curPos[0] = this.m_bboxMin[0];
+ this.m_curPos[1] += 2;
+ }
+
+ if (coverage == 0)
+ continue; // Discard
+
+ // Compute depth and barycentric coordinates
+ var edgeSum = deMath.add(deMath.add(e01, e12), e20);
+ var z0 = deMath.divide(e12, edgeSum);
+ var z1 = deMath.divide(e20, edgeSum);
+
+ var b0 = deMath.multiply(e12, [this.m_v0[3], this.m_v0[3], this.m_v0[3], this.m_v0[3]]);
+ var b1 = deMath.multiply(e20, [this.m_v1[3], this.m_v1[3], this.m_v1[3], this.m_v1[3]]);
+ var b2 = deMath.multiply(e01, [this.m_v2[3], this.m_v2[3], this.m_v2[3], this.m_v2[3]]);
+ var bSum = deMath.add(deMath.add(b0, b1), b2);
+ var barycentric0 = deMath.divide(b0, bSum);
+ var barycentric1 = deMath.divide(b1, bSum);
+ var barycentric2 = deMath.subtract(deMath.subtract([1, 1, 1, 1], barycentric0), barycentric1);
+
+ // In native dEQP, after rasterization, the pixel (x0, y0) actually represents four pixels:
+ // (x0, y0), (x0 + 1, y0), (x0, y0 + 1) and (x0 + 1, y0 + 1).
+ // The barycentrics and depths of these four pixels are to be computed after rasterization:
+ // barycentrics are computed in function shadeFragments in es3fFboTestUtil.cpp;
+ // depths are computed in function writeFragmentPackets in rrRenderer.cpp.
+
+ // In js, pixels are processed one after another, so their depths and barycentrics should be computed immediately.
+
+ // Determine if (x0, y0), (x0 + 1, y0), (x0, y0 + 1), (x0 + 1, y0 + 1) can be rendered
+ for (var fragNdx = 0; fragNdx < 4; fragNdx++) {
+ var xo = fragNdx % 2;
+ var yo = Math.trunc(fragNdx / 2);
+ var x = x0 + xo;
+ var y = y0 + yo;
+
+ // The value of numSamples always equals 1 in sglrReferenceContext.
+ if(rrRenderer.getCoverageAnyFragmentSampleLive(coverage, 1, xo, yo)) {
+ // Barycentric coordinates - referenced from function readTriangleVarying in rrShadingContext.hpp
+ var b = [barycentric0[fragNdx], barycentric1[fragNdx], barycentric2[fragNdx]];
+
+ // Depth - referenced from writeFragmentPackets in rrRenderer.cpp
+ var depth = z0[fragNdx] * za + z1[fragNdx] * zb + zc;
+ depth = depth * depthScale + depthBias;
+
+ // Clip test
+ // Native dEQP does clipping test before rasterization.
+ if (!rrRenderer.clipTest(x, y, depth, this.m_viewport.rect))
+ continue;
+
+ fragmentPackets.push(new rrFragmentOperations.Fragment(b, [x, y], depth));
+ }
+ }
+ }
+ return fragmentPackets;
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {Array<rrVertexAttrib.VertexAttrib>} vertexAttribs
+ * @param {rrRenderer.PrimitiveType} primitive
+ * @param {(number|rrRenderer.DrawIndices)} first Index of first quad vertex
+ * @param {number} count Number of indices
+ * @param {number} instanceID
+ */
+rrRenderer.drawTriangles = function(state, renderTarget, program, vertexAttribs, primitive, first, count, instanceID) {
+
+ /**
+ * @param {Array<rrVertexPacket.VertexPacket>} vertices
+ * @param {Array<number>} indices
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ var selectVertices = function(vertices, indices) {
+ var result = [];
+ for (var i = 0; i < indices.length; i++)
+ result.push(vertices[indices[i]]);
+ return result;
+ };
+
+ // Referenced from native dEQP Renderer::drawInstanced() in rrRenderer.cpp
+
+ var primitives = new rrRenderer.PrimitiveList(primitive, count, first);
+ // Do not draw if nothing to draw
+ if (primitives.getNumElements() == 0)
+ return;
+
+ // Prepare transformation
+ var numVaryings = program.vertexShader.getOutputs().length;
+ var vpalloc = new rrVertexPacket.VertexPacketAllocator(numVaryings);
+ var vertexPackets = vpalloc.allocArray(primitives.getNumElements());
+ var drawContext = new rrRenderer.DrawContext();
+ drawContext.primitiveID = 0;
+
+ var numberOfVertices = primitives.getNumElements();
+ var numVertexPackets = 0;
+ for (var elementNdx = 0; elementNdx < numberOfVertices; ++elementNdx) {
+
+ // input
+ vertexPackets[numVertexPackets].instanceNdx = instanceID;
+ vertexPackets[numVertexPackets].vertexNdx = primitives.getIndex(elementNdx);
+
+ // output
+ vertexPackets[numVertexPackets].pointSize = state.point.pointSize; // default value from the current state
+ vertexPackets[numVertexPackets].position = [0, 0, 0, 0]; // no undefined values
+
+ ++numVertexPackets;
+
+ }
+ program.shadeVertices(vertexAttribs, vertexPackets, numVertexPackets);
+
+ // Referenced from native dEQP Renderer::rasterizePrimitive() for triangle rasterization in rrRenderer.cpp
+
+ // In native dEQP, only maxFragmentPackets packets are processed per rasterize-shade-write loop;
+ // in js all packets are processed in one loop.
+
+ var rasterizer = new rrRenderer.triangleRasterizer(state);
+
+ for (var prim = primitives.getNextPrimitive(true); prim.length > 0; prim = primitives.getNextPrimitive()) {
+ var vertices = selectVertices(vertexPackets, prim);
+
+ var v0 = rrRenderer.transformGLToWindowCoords(state, vertices[0]);
+ var v1 = rrRenderer.transformGLToWindowCoords(state, vertices[1]);
+ var v2 = rrRenderer.transformGLToWindowCoords(state, vertices[2]);
+
+ rasterizer.init(v0, v1, v2);
+
+ // Culling
+ if ((state.cullMode == rrRenderState.CullMode.FRONT && rasterizer.m_face == rrDefs.FaceType.FACETYPE_FRONT) ||
+ (state.cullMode == rrRenderState.CullMode.BACK && rasterizer.m_face == rrDefs.FaceType.FACETYPE_BACK))
+ return;
+
+ /* TODO: Add Polygon Offset and Depth Clamp */
+
+ // Compute a conservative integer bounding box for the triangle
+ var minX = Math.floor(Math.min(v0[0], v1[0], v2[0]));
+ var maxX = Math.ceil(Math.max(v0[0], v1[0], v2[0]));
+ var minY = Math.floor(Math.min(v0[1], v1[1], v2[1]));
+ var maxY = Math.ceil(Math.max(v0[1], v1[1], v2[1]));
+
+ // Shading context
+ var shadingContext = new rrShadingContext.FragmentShadingContext(
+ vertices[0].outputs,
+ vertices[1].outputs,
+ vertices[2].outputs
+ );
+ shadingContext.setSize(maxX - minX, maxY - minY);
+
+ // Rasterize
+ var fragmentPackets = rasterizer.rasterize();
+
+ // Shade
+ program.shadeFragments(fragmentPackets, shadingContext);
+
+ // Handle fragment shader outputs
+ rrRenderer.writeFragments2(state, renderTarget, fragmentPackets);
+ }
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {Array<rrVertexAttrib.VertexAttrib>} vertexAttribs
+ * @param {rrRenderer.PrimitiveType} primitive
+ * @param {(number|rrRenderer.DrawIndices)} first Index of first quad vertex
+ * @param {number} count Number of indices
+ * @param {number} instanceID
+ */
+rrRenderer.drawLines = function(state, renderTarget, program, vertexAttribs, primitive, first, count, instanceID) {
+
+ /**
+ * @param {Array<rrVertexPacket.VertexPacket>} vertices
+ * @param {Array<number>} indices
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ var selectVertices = function(vertices, indices) {
+ var result = [];
+ for (var i = 0; i < indices.length; i++)
+ result.push(vertices[indices[i]]);
+ return result;
+ };
+
+ var lengthSquared = function(a) {
+ var sqSum = 0;
+ for (var i = 0; i < a.length; i++)
+ sqSum += a[i] * a[i];
+ return sqSum;
+ };
+
+ var dot = function(a, b) {
+ var res = 0;
+ for (var i = 0; i < a.length; i++)
+ res += a[i] * b[i];
+ return res;
+ };
+
+ var rasterizeLine = function(v0, v1) {
+ var d = [
+ Math.abs(v1[0] - v0[0]),
+ Math.abs(v1[1] - v0[1])];
+ var xstep = v0[0] < v1[0] ? 1 : -1;
+ var ystep = v0[1] < v1[1] ? 1 : -1;
+ var x = v0[0];
+ var y = v0[1];
+ var offset = d[0] - d[1];
+ var lenV = [v1[0] - v0[0], v1[1] - v0[1]];
+ var lenSq = lengthSquared(lenV);
+
+ var packets = [];
+
+ while (true) {
+ var t = dot([x - v0[0], y - v0[1]], lenV) / lenSq;
+ var depth = (1 - t) * v0[2] + t * v1[2];
+ var b = [0, 0, 0];
+ b[0] = 1 - t;
+ b[1] = t;
+
+ if (x == v1[0] && y == v1[1])
+ break;
+
+ depth = depth * depthScale + depthBias;
+ packets.push(new rrFragmentOperations.Fragment(b, [x, y], depth));
+
+ var offset2 = 2 * offset;
+ if (offset2 > -1 * d[1]) {
+ x += xstep;
+ offset -= d[1];
+ }
+
+ if (offset2 < d[0]) {
+ y += ystep;
+ offset += d[0];
+ }
+ }
+ return packets;
+ };
+
+ var primitives = new rrRenderer.PrimitiveList(primitive, count, first);
+ // Do not draw if nothing to draw
+ if (primitives.getNumElements() == 0)
+ return;
+
+ // Prepare transformation
+ var numVaryings = program.vertexShader.getOutputs().length;
+ var vpalloc = new rrVertexPacket.VertexPacketAllocator(numVaryings);
+ var vertexPackets = vpalloc.allocArray(primitives.getNumElements());
+ var drawContext = new rrRenderer.DrawContext();
+ drawContext.primitiveID = 0;
+
+ var numberOfVertices = primitives.getNumElements();
+ var numVertexPackets = 0;
+ for (var elementNdx = 0; elementNdx < numberOfVertices; ++elementNdx) {
+
+ // input
+ vertexPackets[numVertexPackets].instanceNdx = instanceID;
+ vertexPackets[numVertexPackets].vertexNdx = primitives.getIndex(elementNdx);
+
+ // output
+ vertexPackets[numVertexPackets].pointSize = state.point.pointSize; // default value from the current state
+ vertexPackets[numVertexPackets].position = [0, 0, 0, 0]; // no undefined values
+
+ ++numVertexPackets;
+
+ }
+ program.shadeVertices(vertexAttribs, vertexPackets, numVertexPackets);
+
+ var zn = state.viewport.zn;
+ var zf = state.viewport.zf;
+ var depthScale = (zf - zn) / 2;
+ var depthBias = (zf + zn) / 2;
+
+ // For each quad, we get a group of six vertex packets
+ for (var prim = primitives.getNextPrimitive(true); prim.length > 0; prim = primitives.getNextPrimitive()) {
+ var linePackets = selectVertices(vertexPackets, prim);
+
+ var v0 = rrRenderer.transformGLToWindowCoords(state, linePackets[0]);
+ var v1 = rrRenderer.transformGLToWindowCoords(state, linePackets[1]);
+ v0[2] = linePackets[0].position[2];
+ v1[2] = linePackets[1].position[2];
+
+ v0[0] = Math.floor(v0[0]);
+ v0[1] = Math.floor(v0[1]);
+ v1[0] = Math.floor(v1[0]);
+ v1[1] = Math.floor(v1[1]);
+
+ var lineWidth = state.line.lineWidth;
+
+ var shadingContext = new rrShadingContext.FragmentShadingContext(
+ linePackets[0].outputs,
+ linePackets[1].outputs,
+ null
+ );
+ var isXmajor = Math.abs(v1[0] - v0[0]) >= Math.abs(v1[1] - v0[1]);
+ var packets = [];
+ if (isXmajor)
+ packets = rasterizeLine([v0[0], v0[1] - (lineWidth - 1) / 2, v0[2]],
+ [v1[0], v1[1] - (lineWidth - 1) / 2, v1[2]]);
+ else
+ packets = rasterizeLine([v0[0] - (lineWidth - 1) / 2, v0[1], v0[2]],
+ [v1[0] - (lineWidth - 1) / 2, v1[1], v1[2]]);
+ var numPackets = packets.length;
+ if (lineWidth > 1)
+ for (var i = 0; i < numPackets; i++) {
+ var p = packets[i];
+ for (var j = 1; j < lineWidth; j++) {
+ var p2 = deUtil.clone(p);
+ if (isXmajor)
+ p2.pixelCoord[1] += j;
+ else
+ p2.pixelCoord[0] += j;
+ packets.push(p2);
+ }
+ }
+
+ var clipped = [];
+ for (var i = 0; i < packets.length; i++) {
+ var p = packets[i];
+ if (rrRenderer.clipTest(p.pixelCoord[0], p.pixelCoord[1], p.sampleDepths[0], state.viewport.rect))
+ clipped.push(p);
+ }
+ program.shadeFragments(clipped, shadingContext);
+
+ rrRenderer.writeFragments2(state, renderTarget, clipped);
+ }
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {Array<rrVertexAttrib.VertexAttrib>} vertexAttribs
+ * @param {rrRenderer.PrimitiveType} primitive
+ * @param {(number|rrRenderer.DrawIndices)} first Index of first quad vertex
+ * @param {number} count Number of indices
+ * @param {number} instanceID
+ */
+rrRenderer.drawPoints = function(state, renderTarget, program, vertexAttribs, primitive, first, count, instanceID) {
+ /**
+ * @param {Array<rrVertexPacket.VertexPacket>} vertices
+ * @param {Array<number>} indices
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ var selectVertices = function(vertices, indices) {
+ var result = [];
+ for (var i = 0; i < indices.length; i++)
+ result.push(vertices[indices[i]]);
+ return result;
+ };
+
+ var primitives = new rrRenderer.PrimitiveList(primitive, count, first);
+ // Do not draw if nothing to draw
+ if (primitives.getNumElements() == 0)
+ return;
+
+ // Prepare transformation
+ var numVaryings = program.vertexShader.getOutputs().length;
+ var vpalloc = new rrVertexPacket.VertexPacketAllocator(numVaryings);
+ var vertexPackets = vpalloc.allocArray(primitives.getNumElements());
+ var drawContext = new rrRenderer.DrawContext();
+ drawContext.primitiveID = 0;
+
+ var numberOfVertices = primitives.getNumElements();
+ var numVertexPackets = 0;
+ for (var elementNdx = 0; elementNdx < numberOfVertices; ++elementNdx) {
+
+ // input
+ vertexPackets[numVertexPackets].instanceNdx = instanceID;
+ vertexPackets[numVertexPackets].vertexNdx = primitives.getIndex(elementNdx);
+
+ // output
+ vertexPackets[numVertexPackets].pointSize = state.point.pointSize; // default value from the current state
+ vertexPackets[numVertexPackets].position = [0, 0, 0, 0]; // no undefined values
+
+ ++numVertexPackets;
+
+ }
+ program.shadeVertices(vertexAttribs, vertexPackets, numVertexPackets);
+
+ var zn = state.viewport.zn;
+ var zf = state.viewport.zf;
+ var depthScale = (zf - zn) / 2;
+ var depthBias = (zf + zn) / 2;
+
+ // For each primitive, we draw a point.
+ for (var prim = primitives.getNextPrimitive(true); prim.length > 0; prim = primitives.getNextPrimitive()) {
+ var pointPackets = selectVertices(vertexPackets, prim);
+
+ var v0 = rrRenderer.transformGLToWindowCoords(state, pointPackets[0]);
+ v0[2] = pointPackets[0].position[2];
+ var pointSize = pointPackets[0].pointSize;
+
+ var shadingContext = new rrShadingContext.FragmentShadingContext(
+ pointPackets[0].outputs,
+ null,
+ null
+ );
+ var packets = [];
+
+ var x = v0[0];
+ var y = v0[1];
+ var depth = v0[2];
+ var b = [1, 0, 0];
+ depth = depth * depthScale + depthBias;
+
+ for (var i = Math.floor(x - pointSize / 2); i < x + pointSize / 2; i++) {
+ for (var j = Math.floor(y - pointSize / 2); j < y + pointSize / 2; j++) {
+ var centerX = i + 0.5;
+ var centerY = j + 0.5;
+ if (Math.abs(centerX - x) <= pointSize / 2 &&
+ Math.abs(centerY - y) <= pointSize / 2 &&
+ rrRenderer.clipTest(i, j, depth, state.viewport.rect))
+ packets.push(new rrFragmentOperations.Fragment(b, [i, j], depth));
+ }
+ }
+
+ program.shadeFragments(packets, shadingContext);
+
+ rrRenderer.writeFragments2(state, renderTarget, packets);
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js
new file mode 100644
index 0000000000..143d9b7289
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrShaders');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+var rrShaders = framework.referencerenderer.rrShaders;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+var rrShadingContext = framework.referencerenderer.rrShadingContext;
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+
+ /**
+ * Vertex shader input information
+ * @constructor
+ */
+ rrShaders.VertexInputInfo = function() {
+ /** @type {rrGenericVector.GenericVecType} */ this.type;
+ };
+
+ /**
+ * Shader varying information
+ * @constructor
+ */
+ rrShaders.VertexVaryingInfo = function() {
+ /** @type {rrGenericVector.GenericVecType} */ this.type;
+ /** @type {boolean} */ var flatshade = false;
+ };
+
+ /**
+ * Fragment shader output information
+ * @constructor
+ */
+ rrShaders.FragmentOutputInfo = function() {
+ //Sensible defaults
+ /** @type {rrGenericVector.GenericVecType} */ this.type;
+ };
+
+ /**
+ * Vertex shader interface
+ *
+ * Vertex shaders execute shading for set of vertex packets. See VertexPacket
+ * documentation for more details on shading API.
+ * @constructor
+ * @param {number} numInputs
+ * @param {number} numOutputs
+ */
+ rrShaders.VertexShader = function(numInputs, numOutputs) {
+ /** @type {Array<rrShaders.VertexInputInfo>} */ this.m_inputs = [];
+ for (var ndx = 0; ndx < numInputs; ndx++) this.m_inputs[ndx] = new rrShaders.VertexInputInfo();
+ /** @type {Array<rrShaders.VertexVaryingInfo>} */ this.m_outputs = [];
+ for (var ndx = 0; ndx < numOutputs; ndx++) this.m_outputs[ndx] = new rrShaders.VertexVaryingInfo();
+ };
+
+ /**
+ * getInputs
+ * @return {Array<rrShaders.VertexInputInfo>}
+ */
+ rrShaders.VertexShader.prototype.getInputs = function() {return this.m_inputs;};
+
+ /**
+ * getOutputs
+ * @return {Array<rrShaders.VertexVaryingInfo>}
+ */
+ rrShaders.VertexShader.prototype.getOutputs = function() {return this.m_outputs;};
+
+ /**
+ * Fragment shader interface
+ *
+ * Fragment shader executes shading for list of fragment packets. See
+ * FragmentPacket documentation for more details on shading API.
+ * @constructor
+ * @param {number} numInputs
+ * @param {number} numOutputs
+ */
+ rrShaders.FragmentShader = function(numInputs, numOutputs) {
+ /** @type {Array<rrShaders.VertexVaryingInfo>} */ this.m_inputs = [];
+ for (var ndx = 0; ndx < numInputs; ndx++) this.m_inputs[ndx] = new rrShaders.VertexVaryingInfo();
+ /** @type {Array<rrShaders.FragmentOutputInfo>} */ this.m_outputs = [];
+ for (var ndx = 0; ndx < numOutputs; ndx++) this.m_outputs[ndx] = new rrShaders.FragmentOutputInfo();
+ /** @type {*} */ this.m_container; // owner object
+ };
+
+ /**
+ * getInputs
+ * @return {Array<rrShaders.VertexVaryingInfo>}
+ */
+ rrShaders.FragmentShader.prototype.getInputs = function() {return this.m_inputs;};
+
+ /**
+ * getOutputs
+ * @return {Array<rrShaders.FragmentOutputInfo>}
+ */
+ rrShaders.FragmentShader.prototype.getOutputs = function() {return this.m_outputs;};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js
new file mode 100644
index 0000000000..38b9d201f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js
@@ -0,0 +1,113 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+
+goog.scope(function() {
+
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var deMath = framework.delibs.debase.deMath;
+ var rrDefs = framework.referencerenderer.rrDefs;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * Fragment shading context
+ *
+ * Contains per-primitive information used in fragment shading
+ * @constructor
+ * @param {Array<Array<number>>} varying0 (GenericVec4*)
+ * @param {Array<Array<number>>} varying1 (GenericVec4*)
+ * @param {Array<Array<number>>} varying2 (GenericVec4*)
+ */
+ rrShadingContext.FragmentShadingContext = function(varying0, varying1, varying2) {
+ /** @type {Array<Array<Array<number>>>} */ this.varyings = [varying0, varying1, varying2]; //!< Vertex shader outputs. Pointer will be NULL if there is no such vertex.
+ this.m_width = 0xFFFFFFFF;
+ this.m_height = 0xFFFFFFFF;
+ };
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ */
+ rrShadingContext.FragmentShadingContext.prototype.setSize = function(width, height) {
+ this.m_width = width;
+ this.m_height = height;
+ };
+
+ rrShadingContext.FragmentShadingContext.prototype.getWidth = function() {
+ return this.m_width;
+ };
+
+ rrShadingContext.FragmentShadingContext.prototype.getHeight = function() {
+ return this.m_height;
+ };
+
+ // Read Varying
+
+ /**
+ * @param {rrFragmentOperations.Fragment} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ * @param {number} varyingLoc
+ * @return {Array<number>} (Vector<T, 4>)
+ */
+ rrShadingContext.readTriangleVarying = function(packet, context, varyingLoc) {
+ var result = deMath.scale(
+ context.varyings[0][varyingLoc],
+ packet.barycentric[0]
+ );
+
+ if (context.varyings[1])
+ result = deMath.add(result, deMath.scale(
+ context.varyings[1][varyingLoc],
+ packet.barycentric[1]
+ ));
+
+ if (context.varyings[2])
+ result = deMath.add(result, deMath.scale(
+ context.varyings[2][varyingLoc],
+ packet.barycentric[2]
+ ));
+
+ return result;
+ };
+
+ /**
+ * @param {rrFragmentOperations.Fragment} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ * @param {number} varyingLoc
+ * @return {Array<number>} (Vector<T, 4>)
+ */
+ rrShadingContext.readVarying = function(packet, context, varyingLoc) {
+ return rrShadingContext.readTriangleVarying(packet, context, varyingLoc);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js
new file mode 100644
index 0000000000..03a58168fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+
+goog.scope(function() {
+
+ var rrUtil = framework.referencerenderer.rrUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+
+ /**
+ * @param {sglrGLContext.GLContext | WebGL2RenderingContext | sglrReferenceContext.ReferenceContext} ctx
+ * @param {number|Object} program
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ */
+ rrUtil.drawQuad = function(ctx, program, p0, p1) {
+ // Vertex data.
+ var hz = (p0[2] + p1[2]) * 0.5;
+ /** @type {Array<number>} */ var position = [
+ p0[0], p0[1], p0[2], 1.0,
+ p0[0], p1[1], hz, 1.0,
+ p1[0], p0[1], hz, 1.0,
+ p1[0], p1[1], p1[2], 1.0
+ ];
+ /** @type {Array<number>} */ var coord = [
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 0.0,
+ 1.0, 1.0
+ ];
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+
+ var posLoc = ctx.getAttribLocation(program, 'a_position');
+ if (posLoc == -1)
+ throw new Error('a_position attribute is not defined.');
+
+ var coordLoc = ctx.getAttribLocation(program, 'a_coord');
+ var vaoID;
+ var bufIDs = [];
+
+ vaoID = ctx.createVertexArray();
+ ctx.bindVertexArray(vaoID);
+
+ bufIDs[0] = ctx.createBuffer();
+ bufIDs[1] = ctx.createBuffer();
+
+ ctx.useProgram(program);
+
+ if (posLoc >= 0) {
+ ctx.bindBuffer(gl.ARRAY_BUFFER, bufIDs[0]);
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(position), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(posLoc);
+ ctx.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, null);
+ }
+
+ if (coordLoc >= 0) {
+ ctx.bindBuffer(gl.ARRAY_BUFFER, bufIDs[1]);
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(coord), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(coordLoc);
+ ctx.vertexAttribPointer(coordLoc, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, null);
+ }
+
+ {
+ var ndxID = ctx.createBuffer();
+
+ ctx.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ndxID);
+ ctx.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
+
+ ctx.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+
+ ctx.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ ctx.deleteBuffer(ndxID);
+ }
+
+ ctx.bindVertexArray(null);
+ ctx.deleteBuffer(bufIDs[0]);
+ ctx.deleteBuffer(bufIDs[1]);
+ ctx.deleteVertexArray(vaoID);
+
+ if (posLoc >= 0)
+ ctx.disableVertexAttribArray(posLoc);
+
+ if (coordLoc >= 0)
+ ctx.disableVertexAttribArray(coordLoc);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js
new file mode 100644
index 0000000000..f6095e2cc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js
@@ -0,0 +1,641 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrGenericVector');
+
+goog.scope(function() {
+
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var deMath = framework.delibs.debase.deMath;
+var tcuFloat = framework.common.tcuFloat;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * rrVertexAttrib.NormalOrder
+ * @enum
+ */
+ rrVertexAttrib.NormalOrder = {
+ T0: 0,
+ T1: 1,
+ T2: 2,
+ T3: 3
+ };
+
+ /**
+ * rrVertexAttrib.BGRAOrder
+ * @enum
+ */
+ rrVertexAttrib.BGRAOrder = {
+ T0: 2,
+ T1: 1,
+ T2: 0,
+ T3: 3
+ };
+
+ /**
+ * rrVertexAttrib.VertexAttribType enum
+ * @enum
+ */
+ rrVertexAttrib.VertexAttribType = {
+ // Can only be rrVertexAttrib.read as floats
+ FLOAT: 0,
+ HALF: 1,
+ FIXED: 2,
+ DOUBLE: 3,
+
+ // Can only be rrVertexAttrib.read as floats, will be normalized
+ NONPURE_UNORM8: 4,
+ NONPURE_UNORM16: 5,
+ NONPURE_UNORM32: 6,
+ NONPURE_UNORM_2_10_10_10_REV: 7, //!< Packed format, only size = 4 is allowed
+
+ // Clamped formats, GLES3-style conversion: max{c / (2^(b-1) - 1), -1 }
+ NONPURE_SNORM8_CLAMP: 8,
+ NONPURE_SNORM16_CLAMP: 9,
+ NONPURE_SNORM32_CLAMP: 10,
+ NONPURE_SNORM_2_10_10_10_REV_CLAMP: 11, //!< Packed format, only size = 4 is allowed
+
+ // Scaled formats, GLES2-style conversion: (2c + 1) / (2^b - 1)
+ NONPURE_SNORM8_SCALE: 12,
+ NONPURE_SNORM16_SCALE: 13,
+ NONPURE_SNORM32_SCALE: 14,
+ NONPURE_SNORM_2_10_10_10_REV_SCALE: 15, //!< Packed format, only size = 4 is allowed
+
+ // can only be rrVertexAttrib.read as float, will not be normalized
+ NONPURE_UINT8: 16,
+ NONPURE_UINT16: 17,
+ NONPURE_UINT32: 18,
+
+ NONPURE_INT8: 19,
+ NONPURE_INT16: 20,
+ NONPURE_INT32: 21,
+
+ NONPURE_UINT_2_10_10_10_REV: 22, //!< Packed format, only size = 4 is allowed
+ NONPURE_INT_2_10_10_10_REV: 23, //!< Packed format, only size = 4 is allowed
+
+ // can only be rrVertexAttrib.read as integers
+ PURE_UINT8: 24,
+ PURE_UINT16: 25,
+ PURE_UINT32: 26,
+
+ PURE_INT8: 27,
+ PURE_INT16: 28,
+ PURE_INT32: 29,
+
+ // reordered formats of gl.ARB_vertex_array_bgra
+ NONPURE_UNORM8_BGRA: 30,
+ NONPURE_UNORM_2_10_10_10_REV_BGRA: 31,
+ NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA: 32,
+ NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA: 33,
+
+ // can be rrVertexAttrib.read as anything
+ DONT_CARE: 34 //!< Do not enforce type checking when reading GENERIC attribute. Used for current client side attributes.
+ };
+
+ /**
+ * rrVertexAttrib.VertexAttrib class
+ * @constructor
+ */
+ rrVertexAttrib.VertexAttrib = function() {
+ /** @type {rrVertexAttrib.VertexAttribType} */ this.type = rrVertexAttrib.VertexAttribType.FLOAT;
+ /** @type {number} */ this.size = 0;
+ /** @type {number} */ this.stride = 0;
+ /** @type {number} */ this.instanceDivisor = 0;
+ /** @type {number} */ this.offset = 0; //Added this property to compensate functionality (not in original dEQP).
+ /** @type {ArrayBuffer} */ this.pointer = null;
+ /** @type {Array<number>|rrGenericVector.GenericVec4} */ this.generic; //!< Generic attribute, used if pointer is null.
+ };
+
+ /**
+ * @param {rrVertexAttrib.VertexAttribType} type
+ * @return {number}
+ */
+ rrVertexAttrib.getComponentSize = function(type) {
+ switch (type) {
+ case rrVertexAttrib.VertexAttribType.FLOAT: return 4;
+ case rrVertexAttrib.VertexAttribType.HALF: return 2;
+ case rrVertexAttrib.VertexAttribType.FIXED: return 4;
+ case rrVertexAttrib.VertexAttribType.DOUBLE: return 8; //sizeof(double);
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM16: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_CLAMP: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_CLAMP: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_CLAMP: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_SCALE: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_SCALE: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_SCALE: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT8: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT16: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT8: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT16: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT8: return 1;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT16: return 2;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT32: return 4;
+ case rrVertexAttrib.VertexAttribType.PURE_INT8: return 1;
+ case rrVertexAttrib.VertexAttribType.PURE_INT16: return 2;
+ case rrVertexAttrib.VertexAttribType.PURE_INT32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8_BGRA: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV_BGRA: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA: return 1; //sizeof(deUint32)/4;
+ default:
+ throw new Error('rrVertexAttrib.getComponentSize - Invalid type');
+ }
+ };
+
+ /**
+ * rrVertexAttrib.isValidVertexAttrib function
+ * @param {rrVertexAttrib.VertexAttrib} vertexAttrib
+ * @return {boolean}
+ */
+ rrVertexAttrib.isValidVertexAttrib = function(vertexAttrib) {
+ // Trivial range checks.
+ if (!deMath.deInBounds32(vertexAttrib.type, 0, Object.keys(rrVertexAttrib.VertexAttribType).length) ||
+ !deMath.deInRange32(vertexAttrib.size, 0, 4) ||
+ vertexAttrib.instanceDivisor < 0)
+ return false;
+
+ // Generic attributes
+ if (!vertexAttrib.pointer && vertexAttrib.type != rrVertexAttrib.VertexAttribType.DONT_CARE)
+ return false;
+
+ // Packed formats
+ if ((vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV_BGRA ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA) &&
+ vertexAttrib.size != 4)
+ return false;
+
+ return true;
+ };
+
+ /**
+ * rrVertexAttrib.readVertexAttrib function
+ * @param {rrVertexAttrib.VertexAttrib} vertexAttrib
+ * @param {number} instanceNdx
+ * @param {number} vertexNdx
+ * @param {rrGenericVector.GenericVecType} genericType
+ * @return {goog.NumberArray}
+ */
+ rrVertexAttrib.readVertexAttrib = function(vertexAttrib, instanceNdx, vertexNdx, genericType) {
+ DE_ASSERT(rrVertexAttrib.isValidVertexAttrib(vertexAttrib));
+ /** @type {goog.NumberArray} */ var dst;
+
+ var arrayType = null;
+ switch (genericType) {
+ case rrGenericVector.GenericVecType.INT32:
+ arrayType = Int32Array;
+ break;
+ case rrGenericVector.GenericVecType.UINT32:
+ arrayType = Uint32Array;
+ break;
+ case rrGenericVector.GenericVecType.FLOAT:
+ arrayType = Float32Array;
+ break;
+ }
+
+ if (vertexAttrib.pointer) {
+ /** @type {number} */ var elementNdx = (vertexAttrib.instanceDivisor != 0) ? (instanceNdx / vertexAttrib.instanceDivisor) : vertexNdx;
+ /** @type {number} */ var compSize = rrVertexAttrib.getComponentSize(vertexAttrib.type);
+ /** @type {number} */ var stride = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size * compSize);
+ /** @type {number} */ var byteOffset = vertexAttrib.offset + (elementNdx * stride);
+
+ dst = [0, 0, 0, 1]; // defaults
+
+ if (arrayType != null) {
+ dst = new arrayType(dst);
+ }
+
+ rrVertexAttrib.read(dst, vertexAttrib.type, vertexAttrib.size, new Uint8Array(vertexAttrib.pointer, byteOffset));
+ } else {
+ dst = new arrayType(/** @type {Array<number>} */ vertexAttrib.generic.data);
+ }
+
+ return dst;
+ };
+
+ /**
+ * rrVertexAttrib.readHalf
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.readHalf = function(dst, size, ptr) {
+ var arraysize16 = 2; //2 bytes
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize16)); //Small buffer copy (max. 8 bytes)
+ var aligned = new Uint16Array(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = tcuFloat.newFloat32From16(aligned[0]).getValue();
+ if (size >= 2) dst[1] = tcuFloat.newFloat32From16(aligned[1]).getValue();
+ if (size >= 3) dst[2] = tcuFloat.newFloat32From16(aligned[2]).getValue();
+ if (size >= 4) dst[3] = tcuFloat.newFloat32From16(aligned[3]).getValue();
+ };
+
+ /**
+ * rrVertexAttrib.readFixed
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ /*rrVertexAttrib.readFixed = function(dst, size, ptr) {
+ var arraysize32 = 4; //4 bytes
+
+ //Reinterpret ptr as a uint16 array,
+ //assuming original ptr is 8-bits per element
+ var aligned = new Int32Array(ptr.buffer).subarray(
+ ptr.byteOffset / arraysize32,
+ (ptr.byteOffset + ptr.byteLength) / arraysize32);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = aligned[0] / (1 << 16);
+ if (size >= 2) dst[1] = aligned[1] / (1 << 16);
+ if (size >= 3) dst[2] = aligned[2] / (1 << 16);
+ if (size >= 4) dst[3] = aligned[3] / (1 << 16);
+ };*/
+
+ /**
+ * TODO: Check 64 bit numbers are handled ok
+ * rrVertexAttrib.readDouble
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ /*rrVertexAttrib.readDouble = function(dst, size, ptr) {
+ var arraysize64 = 8; //8 bytes
+
+ //Reinterpret 'ptr' into 'aligned' as a float64 array,
+ //assuming original ptr is 8-bits per element.
+ var aligned = new Float64Array(ptr.buffer).subarray(
+ ptr.byteOffset / arraysize64,
+ (ptr.byteOffset + ptr.byteLength) / arraysize64);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = aligned[0];
+ if (size >= 2) dst[1] = aligned[1];
+ if (size >= 3) dst[2] = aligned[2];
+ if (size >= 4) dst[3] = aligned[3];
+ };*/
+
+ /**
+ * extendSign
+ * @param {number} integerLen
+ * @param {number} integer_ (deUint32)
+ * @return {number} (deInt32)
+ */
+ rrVertexAttrib.extendSign = function(integerLen, integer_) {
+ return new Int32Array([
+ deMath.binaryOp(
+ 0 -
+ deMath.shiftLeft(
+ deMath.binaryOp(
+ integer_,
+ deMath.shiftLeft(
+ 1,
+ (integerLen - 1)
+ ),
+ deMath.BinaryOp.AND
+ ),
+ 1
+ ) ,
+
+integer_,
+ deMath.BinaryOp.OR
+ )
+ ])[0];
+ };
+
+ /**
+ * rrVertexAttrib.readUint2101010Rev
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.readUint2101010Rev = function(dst, size, ptr) {
+ var arraysize32 = 4; //4 bytes
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[0] = deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND);
+ if (size >= 2) dst[1] = deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND);
+ if (size >= 3) dst[2] = deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND);
+ if (size >= 4) dst[3] = deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND);
+ };
+
+ /**
+ * rrVertexAttrib.readInt2101010Rev
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.readInt2101010Rev = function(dst, size, ptr) {
+ var arraysize32 = 4; //4 bytes
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[0] = rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND));
+ if (size >= 2) dst[1] = rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND));
+ if (size >= 3) dst[2] = rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND));
+ if (size >= 4) dst[3] = rrVertexAttrib.extendSign(2, deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND));
+ };
+
+ /**
+ * rrVertexAttrib.readUnorm2101010RevOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ */
+ rrVertexAttrib.readUnorm2101010RevOrder = function(dst, size, ptr, order) {
+ var arraysize32 = 4; //4 bytes
+
+ //Left shift within 32-bit range as 32-bit int.
+ var range10 = new Uint32Array([deMath.shiftLeft(1, 10) - 1])[0];
+ var range2 = new Uint32Array([deMath.shiftLeft(1, 2) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[order.T0] = deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND) / range10;
+ if (size >= 2) dst[order.T1] = deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND) / range10;
+ if (size >= 3) dst[order.T2] = deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND) / range10;
+ if (size >= 4) dst[order.T3] = deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND) / range2;
+ };
+
+ /**
+ * rrVertexAttrib.readSnorm2101010RevClampOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ */
+ rrVertexAttrib.readSnorm2101010RevClampOrder = function(dst, size, ptr, order) {
+ var arraysize32 = 4; //4 bytes
+
+ //Left shift within 32-bit range as 32-bit int.
+ var range10 = new Uint32Array([deMath.shiftLeft(1, 10 - 1) - 1])[0];
+ var range2 = new Uint32Array([deMath.shiftLeft(1, 2 - 1) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[order.T0] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND))])[0] / range10);
+ if (size >= 2) dst[order.T1] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND))])[0] / range10);
+ if (size >= 3) dst[order.T2] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND))])[0] / range10);
+ if (size >= 4) dst[order.T3] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(2, deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND))])[0] / range2);
+ };
+
+ /**
+ * rrVertexAttrib.readSnorm2101010RevScaleOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ */
+ rrVertexAttrib.readSnorm2101010RevScaleOrder = function(dst, size, ptr, order) {
+ var arraysize32 = 4; //4 bytes
+
+ //Left shift within 32-bit range as 32-bit int.
+ var range10 = new Uint32Array([deMath.shiftLeft(1, 10) - 1])[0];
+ var range2 = new Uint32Array([deMath.shiftLeft(1, 2) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[order.T0] = new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range10;
+ if (size >= 2) dst[order.T1] = new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range10;
+ if (size >= 3) dst[order.T2] = new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range10;
+ if (size >= 4) dst[order.T3] = new Float32Array([rrVertexAttrib.extendSign(2, deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range2;
+ };
+
+ /**
+ * rrVertexAttrib.readUnormOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ * @param readAsTypeArray
+ */
+ rrVertexAttrib.readUnormOrder = function(dst, size, ptr, order, readAsTypeArray) {
+ var arrayelementsize = readAsTypeArray.BYTES_PER_ELEMENT;
+
+ //Left shift within 32-bit range as 32-bit float.
+ var range = new Float32Array([deMath.shiftLeft(1, arrayelementsize * 8) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arrayelementsize)); //Small buffer copy (max. 16 bytes)
+ var aligned = new readAsTypeArray(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[order.T0] = aligned[0] / range;
+ if (size >= 2) dst[order.T1] = aligned[1] / range;
+ if (size >= 3) dst[order.T2] = aligned[2] / range;
+ if (size >= 4) dst[order.T3] = aligned[3] / range;
+ };
+
+ /**
+ * rrVertexAttrib.readSnormClamp
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {function(new:ArrayBufferView,(Array<number>|ArrayBuffer|ArrayBufferView|null|number), number=, number=)} readAsTypeArray
+ */
+ rrVertexAttrib.readSnormClamp = function(dst, size, ptr, readAsTypeArray) {
+ var arrayelementsize = readAsTypeArray.BYTES_PER_ELEMENT;
+
+ //Left shift within 32-bit range as 32-bit float.
+ var range = new Float32Array([deMath.shiftLeft(1, arrayelementsize * 8 - 1) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arrayelementsize)); //Small buffer copy (max. 16 bytes)
+ var aligned = new readAsTypeArray(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = Math.max(-1, aligned[0] / range);
+ if (size >= 2) dst[1] = Math.max(-1, aligned[1] / range);
+ if (size >= 3) dst[2] = Math.max(-1, aligned[2] / range);
+ if (size >= 4) dst[3] = Math.max(-1, aligned[3] / range);
+ };
+
+ /**
+ * rrVertexAttrib.readOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order NormalOrder or BGRAOrder
+ * @param readAsTypeArray Typed Array type
+ */
+ rrVertexAttrib.readOrder = function(dst, size, ptr, order, readAsTypeArray) {
+ var arrayelementsize = readAsTypeArray.BYTES_PER_ELEMENT;
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arrayelementsize)); //Small buffer copy (max. 16 bytes)
+ var aligned = new readAsTypeArray(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ //(automatic in JS typed arrays).
+ dst[order.T0] = aligned[0];
+ if (size >= 2) dst[order.T1] = aligned[1];
+ if (size >= 3) dst[order.T2] = aligned[2];
+ if (size >= 4) dst[order.T3] = aligned[3];
+ };
+
+ /**
+ * TODO: Implement readSNormScale.
+ * @param {goog.NumberArray} dst
+ * @param {rrVertexAttrib.VertexAttribType} type
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.read = function(dst, type, size, ptr) {
+ var order;
+
+ switch (type) {
+ case rrVertexAttrib.VertexAttribType.FLOAT:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Float32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.HALF:
+ rrVertexAttrib.readHalf(dst, size, ptr);
+ break;
+ /*case rrVertexAttrib.VertexAttribType.FIXED:
+ rrVertexAttrib.readFixed(dst, size, ptr);
+ break;
+ case rrVertexAttrib.VertexAttribType.DOUBLE:
+ rrVertexAttrib.readDouble(dst, size, ptr);
+ break;*/
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM16:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM32:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV:
+ rrVertexAttrib.readUnorm2101010RevOrder(dst, size, ptr, rrVertexAttrib.NormalOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_CLAMP: //Int8
+ rrVertexAttrib.readSnormClamp(dst, size, ptr, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_CLAMP: //Int16
+ rrVertexAttrib.readSnormClamp(dst, size, ptr, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_CLAMP: //Int32
+ rrVertexAttrib.readSnormClamp(dst, size, ptr, Int32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP:
+ rrVertexAttrib.readSnorm2101010RevClampOrder(dst, size, ptr, rrVertexAttrib.NormalOrder);
+ break;
+ /*case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_SCALE: //Int8
+ rrVertexAttrib.readSnormScale(dst, size, ptr, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_SCALE: //Int16
+ rrVertexAttrib.readSnormScale(dst, size, ptr, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_SCALE: //Int32
+ rrVertexAttrib.readSnormScale(dst, size, ptr, Int32Array);
+ break;*/
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE:
+ rrVertexAttrib.readSnorm2101010RevScaleOrder(dst, size, ptr, rrVertexAttrib.NormalOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV:
+ rrVertexAttrib.readUint2101010Rev(dst, size, ptr);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV:
+ rrVertexAttrib.readInt2101010Rev(dst, size, ptr);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8_BGRA:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV_BGRA:
+ rrVertexAttrib.readUnorm2101010RevOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
+ rrVertexAttrib.readSnorm2101010RevClampOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
+ rrVertexAttrib.readSnorm2101010RevScaleOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_INT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_INT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_INT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int32Array);
+ break;
+
+ default:
+ throw new Error('rrVertexAttrib.read - Invalid type');
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js
new file mode 100644
index 0000000000..ec00e17d19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrVertexPacket');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+
+ /**
+ * rrVertexPacket.VertexPacket class. (Should only be created by rrVertexPacket.VertexPacketAllocator)
+ * @constructor
+ */
+ rrVertexPacket.VertexPacket = function() {
+ /** @type {number} */ this.instanceNdx;
+ /** @type {number} */ this.vertexNdx;
+ /** @type {goog.NumberArray} */ this.position; //!< Transformed position - must be written always.
+ /** @type {number} */ this.pointSize; //!< Point size, required when rendering points.
+ // /** @type {number} */ this.primitiveID; //!< Geometry shader output (Not used in webGL)
+ /** @type {Array<goog.NumberArray>} */ this.outputs = [[0, 0, 0, 0]];
+ };
+
+ /**
+ * rrVertexPacket.VertexPacketAllocator class
+ * @constructor
+ * @param {number} numberOfVertexOutputs
+ */
+ rrVertexPacket.VertexPacketAllocator = function(numberOfVertexOutputs) {
+ /** @type {number} */ this.m_numberOfVertexOutputs = numberOfVertexOutputs;
+ /** @type {Uint8Array} */ this.m_allocations;
+ /** @type {Array<rrVertexPacket.VertexPacket>} */ this.m_singleAllocPool = [];
+ };
+
+ /**
+ * @return {number}
+ */
+ rrVertexPacket.VertexPacketAllocator.prototype.getNumVertexOutputs = function() {
+ return this.m_numberOfVertexOutputs;
+ };
+
+ /**
+ * allocArray
+ * @param {number} count
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ rrVertexPacket.VertexPacketAllocator.prototype.allocArray = function(count) {
+ if (!count)
+ return [];
+
+ /** @type {number} */ var extraVaryings = (this.m_numberOfVertexOutputs == 0) ? (0) : (this.m_numberOfVertexOutputs - 1);
+ // /** @type {number} TODO: Check what this size is used for */ var packetSize = sizeof(rrVertexPacket.VertexPacket) + extraVaryings * sizeof(GenericVec4);
+
+ /** @type {Array<rrVertexPacket.VertexPacket>} */ var retVal = [];
+ // /** @type {Uint8Array} TODO: same as above */ var ptr = new deInt8[packetSize * count]; // throws bad_alloc => ok
+
+ //run ctors
+ for (var i = 0; i < count; ++i)
+ retVal.push(new rrVertexPacket.VertexPacket());
+
+ /** TODO: same as previous - this.m_allocations.push_back(ptr); */
+
+ return retVal;
+ };
+
+ /**
+ * @return {rrVertexPacket.VertexPacket}
+ */
+ rrVertexPacket.VertexPacketAllocator.prototype.alloc = function() {
+ /** @type {number} */ var poolSize = 8;
+
+ if (this.m_singleAllocPool.length == 0)
+ this.m_singleAllocPool = this.allocArray(poolSize);
+
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = this.m_singleAllocPool.pop();
+
+ return packet;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/00_test_list.txt
new file mode 100644
index 0000000000..5a6d768f62
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/00_test_list.txt
@@ -0,0 +1,80 @@
+# The builtinprecision tests are not correct. Errors were introduced when
+# porting the tests from C++ to JavaScript. Tests that fail here pass in
+# the C++ version of dEQP ported to WASM. The tests are disabled here until
+# they can be fixed.
+# --min-version 2.0.1 builtinprecision/00_test_list.txt
+draw/00_test_list.txt
+fbocolorbuffer/00_test_list.txt
+fboinvalidate/00_test_list.txt
+fborender/00_test_list.txt
+fragmentoutput/00_test_list.txt
+framebufferblit/00_test_list.txt
+multisample/00_test_list.txt
+primitiverestart/00_test_list.txt
+shaderindexing/00_test_list.txt
+shadermatrix/00_test_list.txt
+shaderoperator/00_test_list.txt
+shadertexturefunction/00_test_list.txt
+texturefiltering/00_test_list.txt
+textureformat/00_test_list.txt
+textureshadow/00_test_list.txt
+texturespecification/00_test_list.txt
+texturewrap/00_test_list.txt
+transformfeedback/00_test_list.txt
+uniformapi/00_test_list.txt
+uniformbuffers/00_test_list.txt
+vertexarrays/00_test_list.txt
+attriblocation.html
+booleanstatequery.html
+buffercopy.html
+bufferobjectquery.html
+clipping.html
+defaultvertexattribute.html
+fbocompleteness.html
+fbodepthbuffer.html
+fbomultisample.2_samples.html
+fbomultisample.4_samples.html
+fbomultisample.8_samples.html
+fbostatequery.html
+fbostencilbuffer.html
+floatstatequery.html
+fragdepth.html
+indexedstatequery.html
+instancedrendering.html
+integerstatequery.html
+internalformatquery.html
+lifetime.html
+negativebufferapi.html
+negativefragmentapi.html
+negativeshaderapi.html
+negativestateapi.html
+negativetextureapi.html
+negativevertexarrayapi.html
+occlusionquery_strict.html
+occlusionquery_conservative.html
+pixelbufferobject.html
+rasterizerdiscard.html
+rbostatequery.html
+readpixel.html
+samplerobject.html
+samplerstatequery.html
+shaderapi.html
+shaderbuiltinvar.html
+shadercommonfunction.html
+shaderderivate_dfdx.html
+shaderderivate_dfdy.html
+shaderderivate_fwidth.html
+shaderloop_for.html
+shaderloop_while.html
+shaderloop_do_while.html
+shaderpackingfunction.html
+shaderprecision_float.html
+shaderprecision_int.html
+shaderprecision_uint.html
+shaderstatequery.html
+shaderstruct.html
+shaderswitch.html
+stringquery.html
+sync.html
+texturestatequery.html
+vertexarrayobject.html
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/attriblocation.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/attriblocation.html
new file mode 100644
index 0000000000..5eb12e7782
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/attriblocation.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Attribute Location Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fAttribLocationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fAttribLocationTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/booleanstatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/booleanstatequery.html
new file mode 100644
index 0000000000..0423dd44f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/booleanstatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Boolean State Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBooleanStateQuery');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+
+functional.gles3.es3fBooleanStateQuery.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/buffercopy.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/buffercopy.html
new file mode 100644
index 0000000000..04c1d11bfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/buffercopy.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Buffer Copy Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBufferCopyTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBufferCopyTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/bufferobjectquery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/bufferobjectquery.html
new file mode 100644
index 0000000000..b0fa2f358c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/bufferobjectquery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Buffer Object Query Tests Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBufferObjectQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBufferObjectQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/00_test_list.txt
new file mode 100644
index 0000000000..6ac29a3862
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/00_test_list.txt
@@ -0,0 +1,55 @@
+add.html
+sub.html
+mul.html
+div.html
+radians.html
+degrees.html
+sin.html
+cos.html
+tan.html
+asin.html
+acos.html
+atan.html
+atan2.html
+sinh.html
+cosh.html
+tanh.html
+asinh.html
+acosh.html
+atanh.html
+pow.html
+exp.html
+exp2.html
+log.html
+log2.html
+sqrt.html
+inversesqrt.html
+abs.html
+sign.html
+floor.html
+trunc.html
+round.html
+roundeven.html
+ceil.html
+fract.html
+mod.html
+modf.html
+min.html
+max.html
+mix.html
+step.html
+smoothstep.html
+clamp.html
+length.html
+distance.html
+dot.html
+cross.html
+normalize.html
+faceforward.html
+reflect.html
+refract.html
+matrixcompmult.html
+outerproduct.html
+transpose.html
+determinant.html
+inverse.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/abs.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/abs.html
new file mode 100644
index 0000000000..1c395e94de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/abs.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 26);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acos.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acos.html
new file mode 100644
index 0000000000..3c27d4a350
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acos.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 10);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acosh.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acosh.html
new file mode 100644
index 0000000000..6931a60260
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/acosh.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 17);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/add.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/add.html
new file mode 100644
index 0000000000..5817299349
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/add.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 0);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asin.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asin.html
new file mode 100644
index 0000000000..7b8bd1a838
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asin.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 9);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asinh.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asinh.html
new file mode 100644
index 0000000000..ee84df94a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/asinh.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 16);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan.html
new file mode 100644
index 0000000000..00f50c03cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 11);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan2.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan2.html
new file mode 100644
index 0000000000..196de0060f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atan2.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 12);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atanh.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atanh.html
new file mode 100644
index 0000000000..d117666e8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/atanh.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 18);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/builtinprecision_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/builtinprecision_test_generator.py
new file mode 100644
index 0000000000..ba44b2fc48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/builtinprecision_test_generator.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for builtinprecision* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, %(index)s);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'add',
+ 'sub',
+ 'mul',
+ 'div',
+ 'radians',
+ 'degrees',
+ 'sin',
+ 'cos',
+ 'tan',
+ 'asin',
+ 'acos',
+ 'atan',
+ 'atan2',
+ 'sinh',
+ 'cosh',
+ 'tanh',
+ 'asinh',
+ 'acosh',
+ 'atanh',
+ 'pow',
+ 'exp',
+ 'exp2',
+ 'log',
+ 'log2',
+ 'sqrt',
+ 'inversesqrt',
+ 'abs',
+ 'sign',
+ 'floor',
+ 'trunc',
+ 'round',
+ 'roundeven',
+ 'ceil',
+ 'fract',
+ 'mod',
+ 'modf',
+ 'min',
+ 'max',
+ 'mix',
+ 'step',
+ 'smoothstep',
+ 'clamp',
+ 'length',
+ 'distance',
+ 'dot',
+ 'cross',
+ 'normalize',
+ 'faceforward',
+ 'reflect',
+ 'refract',
+ 'matrixcompmult',
+ 'outerproduct',
+ 'transpose',
+ 'determinant',
+ 'inverse'
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, index):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'index': index
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/ceil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/ceil.html
new file mode 100644
index 0000000000..e0d5924407
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/ceil.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 32);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/clamp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/clamp.html
new file mode 100644
index 0000000000..1a820652a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/clamp.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 41);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cos.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cos.html
new file mode 100644
index 0000000000..281419e897
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cos.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 7);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cosh.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cosh.html
new file mode 100644
index 0000000000..ec9c26b637
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cosh.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 14);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cross.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cross.html
new file mode 100644
index 0000000000..1cb96eada4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/cross.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 45);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/degrees.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/degrees.html
new file mode 100644
index 0000000000..a9ed0f80e6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/degrees.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 5);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/determinant.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/determinant.html
new file mode 100644
index 0000000000..56ad04eb41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/determinant.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 53);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/distance.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/distance.html
new file mode 100644
index 0000000000..1f9cfebaf6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/distance.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 43);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/div.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/div.html
new file mode 100644
index 0000000000..bc2c5ce723
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/div.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 3);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/dot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/dot.html
new file mode 100644
index 0000000000..e06fd395da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/dot.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 44);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp.html
new file mode 100644
index 0000000000..11cb6a826f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 20);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp2.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp2.html
new file mode 100644
index 0000000000..3f8755cd24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/exp2.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 21);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/faceforward.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/faceforward.html
new file mode 100644
index 0000000000..ecabe9cdf9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/faceforward.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 47);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/floor.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/floor.html
new file mode 100644
index 0000000000..1c060f13bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/floor.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 28);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/fract.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/fract.html
new file mode 100644
index 0000000000..de778f3ab6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/fract.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 33);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inverse.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inverse.html
new file mode 100644
index 0000000000..c0b2e5876b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inverse.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 54);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inversesqrt.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inversesqrt.html
new file mode 100644
index 0000000000..f34ec5569c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/inversesqrt.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 25);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/length.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/length.html
new file mode 100644
index 0000000000..949f716c79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/length.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 42);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log.html
new file mode 100644
index 0000000000..0528ceef25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 22);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log2.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log2.html
new file mode 100644
index 0000000000..6defd59a32
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/log2.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 23);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/matrixcompmult.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/matrixcompmult.html
new file mode 100644
index 0000000000..28c81e75f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/matrixcompmult.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 50);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/max.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/max.html
new file mode 100644
index 0000000000..95420abe1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/max.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 37);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/min.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/min.html
new file mode 100644
index 0000000000..0230351426
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/min.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 36);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mix.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mix.html
new file mode 100644
index 0000000000..183704370e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mix.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 38);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mod.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mod.html
new file mode 100644
index 0000000000..cbe10773d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mod.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 34);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/modf.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/modf.html
new file mode 100644
index 0000000000..a6e3df51a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/modf.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 35);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mul.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mul.html
new file mode 100644
index 0000000000..0473fd8c06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/mul.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 2);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/normalize.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/normalize.html
new file mode 100644
index 0000000000..82787d7a30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/normalize.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 46);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/outerproduct.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/outerproduct.html
new file mode 100644
index 0000000000..83e2b6d810
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/outerproduct.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 51);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/pow.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/pow.html
new file mode 100644
index 0000000000..7793d740d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/pow.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 19);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/radians.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/radians.html
new file mode 100644
index 0000000000..d808acba17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/radians.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 4);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/reflect.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/reflect.html
new file mode 100644
index 0000000000..87ba13d5e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/reflect.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 48);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/refract.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/refract.html
new file mode 100644
index 0000000000..68d967d557
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/refract.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 49);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/round.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/round.html
new file mode 100644
index 0000000000..0186d6795c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/round.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 30);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/roundeven.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/roundeven.html
new file mode 100644
index 0000000000..6e1f91eda7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/roundeven.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 31);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sign.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sign.html
new file mode 100644
index 0000000000..6c4cf28ac4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sign.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 27);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sin.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sin.html
new file mode 100644
index 0000000000..ee95d80af4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sin.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 6);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sinh.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sinh.html
new file mode 100644
index 0000000000..e805a703a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sinh.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 13);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/smoothstep.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/smoothstep.html
new file mode 100644
index 0000000000..4dd4d7c9b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/smoothstep.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 40);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sqrt.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sqrt.html
new file mode 100644
index 0000000000..707519237b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sqrt.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 24);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/step.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/step.html
new file mode 100644
index 0000000000..7dd143bb49
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/step.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 39);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sub.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sub.html
new file mode 100644
index 0000000000..8e22e94db0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/sub.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 1);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tan.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tan.html
new file mode 100644
index 0000000000..a442f83bfc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tan.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 8);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tanh.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tanh.html
new file mode 100644
index 0000000000..04013ed6d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/tanh.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 15);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/transpose.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/transpose.html
new file mode 100644
index 0000000000..48d55febf8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/transpose.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 52);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/trunc.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/trunc.html
new file mode 100644
index 0000000000..209656d9ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/builtinprecision/trunc.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from builtinprecision_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Builtin Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fBuiltinPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fBuiltinPrecisionTests.run(gl, 29);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/clipping.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/clipping.html
new file mode 100644
index 0000000000..ab2b2bd77f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/clipping.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Clipping tests Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fClippingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fClippingTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/defaultvertexattribute.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/defaultvertexattribute.html
new file mode 100644
index 0000000000..8bca99ad70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/defaultvertexattribute.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Default Vertex Attributes Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDefaultVertexAttributeTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDefaultVertexAttributeTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/00_test_list.txt
new file mode 100644
index 0000000000..ba28d1bb85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/00_test_list.txt
@@ -0,0 +1,7 @@
+draw_arrays.html
+draw_elements.html
+draw_arrays_instanced.html
+draw_elements_instanced.html
+draw_range_elements.html
+instancing.html
+random.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays.html
new file mode 100644
index 0000000000..ae9655df14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays_instanced.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays_instanced.html
new file mode 100644
index 0000000000..f8219ee073
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_arrays_instanced.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements.html
new file mode 100644
index 0000000000..1fb1a5c160
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements_instanced.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements_instanced.html
new file mode 100644
index 0000000000..e4c4b3b980
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_elements_instanced.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_range_elements.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_range_elements.html
new file mode 100644
index 0000000000..df2f7a92bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_range_elements.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_test_generator.py
new file mode 100644
index 0000000000..d96c767b4d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/draw_test_generator.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for draw* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'draw_arrays',
+ 'draw_elements',
+ 'draw_arrays_instanced',
+ 'draw_elements_instanced',
+ 'draw_range_elements',
+ 'instancing',
+ 'random',
+]
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = _GROUPS[ii] + '.html'
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/instancing.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/instancing.html
new file mode 100644
index 0000000000..df8d7910be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/instancing.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/random.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/random.html
new file mode 100644
index 0000000000..1c6f02f9c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/draw/random.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from draw_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Draw Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fDrawTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fDrawTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fApiCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fApiCase.js
new file mode 100644
index 0000000000..3238e6c2ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fApiCase.js
@@ -0,0 +1,161 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fApiCase');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluStrUtil');
+
+goog.scope(function() {
+
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var gluStrUtil = framework.opengl.gluStrUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+
+ // format numbers as they appear in gl.h
+ var getHexStr = function(num) {
+ var numstr = num.toString(16);
+ var prefix = '0x';
+ for (
+ var padding = (num < 0x10000 ? 4 : 8) - numstr.length;
+ padding-- > 0;
+ ) prefix += '0';
+ return prefix + numstr;
+ };
+
+ /**
+ * Base class for all the API tests.
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ */
+ es3fApiCase.ApiCase = function(name, desc, gl) {
+ gl = gl || window.gl;
+ if (this.test === undefined) {
+ throw new Error('Unimplemented virtual function: es3fApiCase.ApiCase.test');
+ }
+ tcuTestCase.DeqpTest.call(this, name, desc);
+
+ this.m_gl = gl;
+ this.m_pass = true;
+ this.m_comment = '';
+
+ };
+
+ es3fApiCase.ApiCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fApiCase.ApiCase.prototype.constructor = es3fApiCase.ApiCase;
+
+ /**
+ * @param {boolean} condition
+ * @param {string=} message
+ */
+ es3fApiCase.ApiCase.prototype.check = function(condition, message) {
+ if (this.m_pass && !condition) {
+ bufferedLogToConsole('Condition is false. Test failed.');
+ if (message)
+ this.m_comment += ' ' + message;
+ this.m_pass = condition;
+ }
+ return condition;
+ };
+
+ es3fApiCase.ApiCase.prototype.iterate = function() {
+
+ this.test();
+
+ if (this.m_pass)
+ testPassed(this.m_comment);
+ else
+ testFailedOptions(this.m_comment, true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {Array<number>|number} expected
+ * @return {boolean} returns true if gl.getError returns an expected error code and false otherwise.
+ */
+ es3fApiCase.ApiCase.prototype.expectError = function(expected) {
+ if (expected.constructor === Number)
+ expected = [expected];
+
+ var err = this.m_gl.getError();
+ var conformant = expected.indexOf(err) >= 0;
+
+ if (!conformant) {
+
+ var l = expected.length;
+ var msg = 'Expected ';
+
+ if (l > 1)
+ msg += (l == 2 ? 'either ' : 'one of ');
+
+ for (var i = 0; i < l; ++i) msg += (
+ (gluStrUtil.getErrorName(expected[i]) || getHexStr(expected[i])) +
+ (l - i == 2 ? ' or ' : ', ')
+ );
+
+ msg += 'but got ' + (gluStrUtil.getErrorName(err) || getHexStr(err)) + '.';
+
+ this.testFailed(msg);
+
+ }
+
+ return conformant;
+ };
+
+ es3fApiCase.ApiCase.prototype.testFailed = function(comment) {
+ bufferedLogToConsole(comment);
+ if (this.m_pass) {
+ this.m_comment = comment;
+ this.m_pass = false;
+ }
+ };
+
+ es3fApiCase.ApiCase.prototype.expectThrowNoError = function(f) {
+ try {
+ f();
+ this.testFailed("should have thrown exception");
+ } catch (e) {
+ this.expectError(this.m_gl.NO_ERROR);
+ }
+ }
+
+ /**
+ * Base class for all the API tests.
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {function(this:es3fApiCase.ApiCaseCallback)} callback
+ */
+ es3fApiCase.ApiCaseCallback = function(name, desc, gl, callback) {
+ this.test = callback;
+ es3fApiCase.ApiCase.call(this, name, desc, gl);
+ };
+ es3fApiCase.ApiCaseCallback.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fApiCase.ApiCaseCallback.prototype.constructor = es3fApiCase.ApiCaseCallback;
+
+/*
+ es3fApiCase.ApiCase.prototype.expectError // (error) or (error0, error1)
+ es3fApiCase.ApiCase.prototype.getSupportedExtensions // (number numSupportedValues, number extension, [number] values )
+ es3fApiCase.ApiCase.prototype.checkBooleans // (char value, char expected);
+//*/
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fAttribLocationTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fAttribLocationTests.js
new file mode 100644
index 0000000000..93f91eca1d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fAttribLocationTests.js
@@ -0,0 +1,267 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Attribute location test
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('functional.gles3.es3fAttribLocationTests');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('modules.shared.glsAttributeLocationTests');
+
+goog.scope(function() {
+
+ var es3fAttribLocationTests = functional.gles3.es3fAttribLocationTests;
+ var glsAttributeLocationTests = modules.shared.glsAttributeLocationTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+ es3fAttribLocationTests.createAttributeLocationTests = function() {
+
+ /** @type {Array<glsAttributeLocationTests.AttribType>} */
+ var types = [
+ new glsAttributeLocationTests.AttribType('float', 1, gl.FLOAT),
+ new glsAttributeLocationTests.AttribType('vec2', 1, gl.FLOAT_VEC2),
+ new glsAttributeLocationTests.AttribType('vec3', 1, gl.FLOAT_VEC3),
+ new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4),
+
+ new glsAttributeLocationTests.AttribType('mat2', 2, gl.FLOAT_MAT2),
+ new glsAttributeLocationTests.AttribType('mat3', 3, gl.FLOAT_MAT3),
+ new glsAttributeLocationTests.AttribType('mat4', 4, gl.FLOAT_MAT4),
+
+ new glsAttributeLocationTests.AttribType('int', 1, gl.INT),
+ new glsAttributeLocationTests.AttribType('ivec2', 1, gl.INT_VEC2),
+ new glsAttributeLocationTests.AttribType('ivec3', 1, gl.INT_VEC3),
+ new glsAttributeLocationTests.AttribType('ivec4', 1, gl.INT_VEC4),
+
+ new glsAttributeLocationTests.AttribType('uint', 1, gl.UNSIGNED_INT),
+ new glsAttributeLocationTests.AttribType('uvec2', 1, gl.UNSIGNED_INT_VEC2),
+ new glsAttributeLocationTests.AttribType('uvec3', 1, gl.UNSIGNED_INT_VEC3),
+ new glsAttributeLocationTests.AttribType('uvec4', 1, gl.UNSIGNED_INT_VEC4),
+
+ new glsAttributeLocationTests.AttribType('mat2x2', 2, gl.FLOAT_MAT2),
+ new glsAttributeLocationTests.AttribType('mat2x3', 2, gl.FLOAT_MAT2x3),
+ new glsAttributeLocationTests.AttribType('mat2x4', 2, gl.FLOAT_MAT2x4),
+
+ new glsAttributeLocationTests.AttribType('mat3x2', 3, gl.FLOAT_MAT3x2),
+ new glsAttributeLocationTests.AttribType('mat3x3', 3, gl.FLOAT_MAT3),
+ new glsAttributeLocationTests.AttribType('mat3x4', 3, gl.FLOAT_MAT3x4),
+
+ new glsAttributeLocationTests.AttribType('mat4x2', 4, gl.FLOAT_MAT4x2),
+ new glsAttributeLocationTests.AttribType('mat4x3', 4, gl.FLOAT_MAT4x3),
+ new glsAttributeLocationTests.AttribType('mat4x4', 4, gl.FLOAT_MAT4)
+ ];
+
+ /** @type {Array<glsAttributeLocationTests.AttribType>} */
+ var es2Types = [
+ new glsAttributeLocationTests.AttribType('float', 1, gl.FLOAT),
+ new glsAttributeLocationTests.AttribType('vec2', 1, gl.FLOAT_VEC2),
+ new glsAttributeLocationTests.AttribType('vec3', 1, gl.FLOAT_VEC3),
+ new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4),
+
+ new glsAttributeLocationTests.AttribType('mat2', 2, gl.FLOAT_MAT2),
+ new glsAttributeLocationTests.AttribType('mat3', 3, gl.FLOAT_MAT3),
+ new glsAttributeLocationTests.AttribType('mat4', 4, gl.FLOAT_MAT4)
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var root = tcuTestCase.newTest('attribute_location', 'Attribute location tests');
+
+ /** @type {number} */ var typeNdx;
+ /** @type {glsAttributeLocationTests.AttribType} */ var type;
+
+ // Basic bind attribute tests
+ /** @type {tcuTestCase.DeqpTest} */
+ var bindAttributeGroup = tcuTestCase.newTest('bind', 'Basic bind attribute location tests.');
+
+ root.addChild(bindAttributeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+ bindAttributeGroup.addChild(new glsAttributeLocationTests.BindAttributeTest(type));
+ }
+
+ // Bind max number of attributes
+ /** @type {tcuTestCase.DeqpTest} */
+ var bindMaxAttributeGroup = tcuTestCase.newTest('bind_max_attributes', 'Use bind with maximum number of attributes.');
+
+ root.addChild(bindMaxAttributeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+ bindMaxAttributeGroup.addChild(new glsAttributeLocationTests.BindMaxAttributesTest(type));
+ }
+
+ // Test filling holes in attribute location
+ /** @type {tcuTestCase.DeqpTest} */
+ var holeGroup = tcuTestCase.newTest('bind_hole', 'Bind all, but one attribute and leave hole in location space for it.');
+
+ root.addChild(holeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+
+ // Bind first location, leave hole size of type and fill rest of locations
+ holeGroup.addChild(new glsAttributeLocationTests.BindHoleAttributeTest(type));
+ }
+
+ // Test binding at different times
+ /** @type {tcuTestCase.DeqpTest} */
+ var bindTimeGroup = tcuTestCase.newTest('bind_time', 'Bind time tests. Test binding at different stages.');
+
+ root.addChild(bindTimeGroup);
+
+ bindTimeGroup.addChild(new glsAttributeLocationTests.PreAttachBindAttributeTest());
+ bindTimeGroup.addChild(new glsAttributeLocationTests.PreLinkBindAttributeTest());
+ bindTimeGroup.addChild(new glsAttributeLocationTests.PostLinkBindAttributeTest());
+ bindTimeGroup.addChild(new glsAttributeLocationTests.BindRelinkAttributeTest());
+ bindTimeGroup.addChild(new glsAttributeLocationTests.BindReattachAttributeTest());
+
+ // Basic layout location attribute tests
+ /** @type {tcuTestCase.DeqpTest} */
+ var layoutAttributeGroup = tcuTestCase.newTest('layout', 'Basic layout location tests.');
+
+ root.addChild(layoutAttributeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+ layoutAttributeGroup.addChild(new glsAttributeLocationTests.LocationAttributeTest(type));
+ }
+
+ // Test max attributes with layout locations
+ /** @type {tcuTestCase.DeqpTest} */
+ var layoutMaxAttributeGroup = tcuTestCase.newTest('layout_max_attributes', 'Maximum attributes used with layout location qualifiers.');
+
+ root.addChild(layoutMaxAttributeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+ layoutMaxAttributeGroup.addChild(new glsAttributeLocationTests.LocationMaxAttributesTest(type));
+ }
+
+ // Test filling holes in attribute location
+ holeGroup = tcuTestCase.newTest('layout_hole', 'Define layout location for all, but one attribute consuming max attribute locations.');
+
+ root.addChild(holeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+
+ // Location first location, leave hole size of type and fill rest of locations
+ holeGroup.addChild(new glsAttributeLocationTests.LocationHoleAttributeTest(type));
+ }
+
+ // Basic mixed mixed attribute tests
+ /** @type {tcuTestCase.DeqpTest} */
+ var mixedAttributeGroup = tcuTestCase.newTest('mixed', 'Basic mixed location tests.');
+
+ root.addChild(mixedAttributeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+ mixedAttributeGroup.addChild(new glsAttributeLocationTests.MixedAttributeTest(type));
+ }
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var mixedMaxAttributeGroup = tcuTestCase.newTest('mixed_max_attributes', 'Maximum attributes used with mixed binding and layout qualifiers.');
+
+ root.addChild(mixedMaxAttributeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+ mixedMaxAttributeGroup.addChild(new glsAttributeLocationTests.MixedMaxAttributesTest(type));
+ }
+
+ // Test mixed binding at different times
+ /** @type {tcuTestCase.DeqpTest} */
+ var mixedTimeGroup = tcuTestCase.newTest('mixed_time', 'Bind time tests. Test binding at different stages.');
+
+ root.addChild(mixedTimeGroup);
+
+ mixedTimeGroup.addChild(new glsAttributeLocationTests.PreAttachMixedAttributeTest());
+ mixedTimeGroup.addChild(new glsAttributeLocationTests.PreLinkMixedAttributeTest());
+ mixedTimeGroup.addChild(new glsAttributeLocationTests.PostLinkMixedAttributeTest());
+ mixedTimeGroup.addChild(new glsAttributeLocationTests.MixedRelinkAttributeTest());
+ mixedTimeGroup.addChild(new glsAttributeLocationTests.MixedReattachAttributeTest());
+
+ holeGroup = tcuTestCase.newTest('mixed_hole', 'Use layout location qualifiers and binding. Leave hole in location space for only free attribute.');
+
+ root.addChild(holeGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+
+ holeGroup.addChild(new glsAttributeLocationTests.MixedHoleAttributeTest(type));
+ }
+
+ // Test hole in location space that moves when relinking
+ /** @type {tcuTestCase.DeqpTest} */
+ var relinkBindHoleGroup = tcuTestCase.newTest('bind_relink_hole', 'Test relinking with moving hole in attribute location space.');
+
+ root.addChild(relinkBindHoleGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+
+ relinkBindHoleGroup.addChild(new glsAttributeLocationTests.BindRelinkHoleAttributeTest(type));
+ }
+
+ // Test hole in location space that moves when relinking
+ /** @type {tcuTestCase.DeqpTest} */
+ var relinkMixedHoleGroup = tcuTestCase.newTest('mixed_relink_hole', 'Test relinking with moving hole in attribute location space.');
+
+ root.addChild(relinkMixedHoleGroup);
+
+ for (typeNdx = 0; typeNdx < types.length; typeNdx++) {
+ type = types[typeNdx];
+
+ relinkMixedHoleGroup.addChild(new glsAttributeLocationTests.MixedRelinkHoleAttributeTest(type));
+ }
+
+ return root;
+ };
+
+ es3fAttribLocationTests.run = function(context) {
+ gl = context;
+ //Set up root Test
+ var state = tcuTestCase.runner;
+
+ var test = es3fAttribLocationTests.createAttributeLocationTests();
+ var testName = test.fullName();
+ var testDescription = test.getDescription() === undefined ? '' : test.getDescription();
+
+ state.testName = testName;
+ state.setRoot(test);
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ test.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ bufferedLogToConsole('Exception: ' + err);
+ testFailedOptions('Failed to es3fAttribLocationTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBooleanStateQuery.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBooleanStateQuery.js
new file mode 100644
index 0000000000..173dea0946
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBooleanStateQuery.js
@@ -0,0 +1,372 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fBooleanStateQuery');
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fBooleanStateQuery = functional.gles3.es3fBooleanStateQuery;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {boolean} value
+ */
+es3fBooleanStateQuery.IsEnabledStateTestCase = function(name, description, targetName, value) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_targetName = targetName;
+ this.m_initial = value;
+};
+
+setParentClass(es3fBooleanStateQuery.IsEnabledStateTestCase, es3fApiCase.ApiCase);
+
+es3fBooleanStateQuery.IsEnabledStateTestCase.prototype.test = function() {
+ // check inital value
+ this.m_pass &= glsStateQuery.verify(this.m_targetName, this.m_initial);
+
+ // check toggle
+
+ gl.enable(this.m_targetName);
+
+ this.m_pass &= glsStateQuery.verify(this.m_targetName, true);
+
+ gl.disable(this.m_targetName);
+
+ this.m_pass &= glsStateQuery.verify(this.m_targetName, false);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBooleanStateQuery.DepthWriteMaskTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fBooleanStateQuery.DepthWriteMaskTestCase, es3fApiCase.ApiCase);
+
+es3fBooleanStateQuery.DepthWriteMaskTestCase.prototype.test = function() {
+ this.m_pass &= glsStateQuery.verify(gl.DEPTH_WRITEMASK, true);
+
+ gl.depthMask(false);
+ this.m_pass &= glsStateQuery.verify(gl.DEPTH_WRITEMASK, false);
+
+ gl.depthMask(true);
+ this.m_pass &= glsStateQuery.verify(gl.DEPTH_WRITEMASK, true);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBooleanStateQuery.SampleCoverageInvertTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fBooleanStateQuery.SampleCoverageInvertTestCase, es3fApiCase.ApiCase);
+
+es3fBooleanStateQuery.SampleCoverageInvertTestCase.prototype.test = function() {
+ this.m_pass &= glsStateQuery.verify(gl.SAMPLE_COVERAGE_INVERT, false);
+
+ gl.sampleCoverage(1, true);
+ this.m_pass &= glsStateQuery.verify(gl.SAMPLE_COVERAGE_INVERT, true);
+
+ gl.sampleCoverage(1, false);
+ this.m_pass &= glsStateQuery.verify(gl.SAMPLE_COVERAGE_INVERT, false);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {boolean} value
+ */
+es3fBooleanStateQuery.InitialBooleanTestCase = function(name, description, targetName, value) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_targetName = targetName;
+ this.m_initial = value;
+};
+
+setParentClass(es3fBooleanStateQuery.InitialBooleanTestCase, es3fApiCase.ApiCase);
+
+es3fBooleanStateQuery.InitialBooleanTestCase.prototype.test = function() {
+ // check inital value
+ this.m_pass &= glsStateQuery.verify(this.m_targetName, this.m_initial);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBooleanStateQuery.ColorMaskTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fBooleanStateQuery.ColorMaskTestCase, es3fApiCase.ApiCase);
+
+es3fBooleanStateQuery.ColorMaskTestCase.prototype.test = function() {
+ this.m_pass &= glsStateQuery.verify(gl.COLOR_WRITEMASK, [true, true, true, true]);
+
+ var testMasks = [
+ [true, true, true, true],
+ [true, true, true, false],
+ [true, true, false, true],
+ [true, true, false, false],
+ [true, false, true, true],
+ [true, false, true, false],
+ [true, false, false, true],
+ [true, false, false, false],
+ [false, true, true, true],
+ [false, true, true, false],
+ [false, true, false, true],
+ [false, true, false, false],
+ [false, false, true, true],
+ [false, false, true, false],
+ [false, false, false, true],
+ [false, false, false, false]
+ ];
+
+ for (var ndx = 0; ndx < testMasks.length; ndx++) {
+ var mask = testMasks[ndx];
+ gl.colorMask(mask[0], mask[1], mask[2], mask[3]);
+ this.m_pass &= glsStateQuery.verify(gl.COLOR_WRITEMASK, mask);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBooleanStateQuery.TransformFeedbackTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {WebGLTransformFeedback} */ this.m_transformfeedback = null;
+};
+
+setParentClass(es3fBooleanStateQuery.TransformFeedbackTestCase, es3fApiCase.ApiCase);
+
+es3fBooleanStateQuery.TransformFeedbackTestCase.prototype.testTransformFeedback = function() {
+ throw new Error('Virtual function.');
+};
+
+es3fBooleanStateQuery.TransformFeedbackTestCase.prototype.test = function() {
+ var transformFeedbackTestVertSource = '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+ var transformFeedbackTestFragSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ this.m_transformfeedback = gl.createTransformFeedback();
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(shaderVert, transformFeedbackTestVertSource);
+ gl.compileShader(shaderVert);
+ this.m_pass &= glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true);
+
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(shaderFrag, transformFeedbackTestFragSource);
+ gl.compileShader(shaderFrag);
+ this.m_pass &= glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, true);
+
+ var shaderProg = gl.createProgram();
+ gl.attachShader(shaderProg, shaderVert);
+ gl.attachShader(shaderProg, shaderFrag);
+ var transform_feedback_outputs = ['gl_Position'];
+ gl.transformFeedbackVaryings(shaderProg, transform_feedback_outputs, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(shaderProg);
+ this.m_pass &= glsStateQuery.verifyProgram(shaderProg, gl.LINK_STATUS, true);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, this.m_transformfeedback);
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 16, gl.DYNAMIC_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
+
+ gl.useProgram(shaderProg);
+
+ this.testTransformFeedback();
+
+ gl.useProgram(null);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.deleteTransformFeedback(this.m_transformfeedback);
+ gl.deleteBuffer(buffer);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(shaderProg);
+};
+
+/**
+ * @constructor
+ * @extends {es3fBooleanStateQuery.TransformFeedbackTestCase}
+ * @param {string} name
+ */
+es3fBooleanStateQuery.TransformFeedbackBasicTestCase = function(name) {
+ es3fBooleanStateQuery.TransformFeedbackTestCase.call(this, name, 'Test TRANSFORM_FEEDBACK_ACTIVE and TRANSFORM_FEEDBACK_PAUSED');
+};
+
+setParentClass(es3fBooleanStateQuery.TransformFeedbackBasicTestCase, es3fBooleanStateQuery.TransformFeedbackTestCase);
+
+es3fBooleanStateQuery.TransformFeedbackBasicTestCase.prototype.testTransformFeedback = function() {
+ gl.beginTransformFeedback(gl.POINTS);
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, true);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, false);
+
+ gl.pauseTransformFeedback();
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, true);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, true);
+
+ gl.resumeTransformFeedback();
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, true);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, false);
+
+ gl.endTransformFeedback();
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, false);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, false);
+};
+
+/**
+ * @constructor
+ * @extends {es3fBooleanStateQuery.TransformFeedbackTestCase}
+ * @param {string} name
+ */
+es3fBooleanStateQuery.TransformFeedbackImplicitResumeTestCase = function(name) {
+ es3fBooleanStateQuery.TransformFeedbackTestCase.call(this, name, 'EndTransformFeedback performs an implicit ResumeTransformFeedback.');
+};
+
+setParentClass(es3fBooleanStateQuery.TransformFeedbackImplicitResumeTestCase, es3fBooleanStateQuery.TransformFeedbackTestCase);
+
+es3fBooleanStateQuery.TransformFeedbackImplicitResumeTestCase.prototype.testTransformFeedback = function() {
+ gl.beginTransformFeedback(gl.POINTS);
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, true);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, false);
+
+ gl.pauseTransformFeedback();
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, true);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, true);
+
+ gl.endTransformFeedback();
+
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_ACTIVE, false);
+ this.m_pass &= glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_PAUSED, false);
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fBooleanStateQuery.BooleanStateQuery = function() {
+ tcuTestCase.DeqpTest.call(this, 'boolean', 'Boolean State Query tests');
+};
+
+es3fBooleanStateQuery.BooleanStateQuery.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fBooleanStateQuery.BooleanStateQuery.prototype.constructor = es3fBooleanStateQuery.BooleanStateQuery;
+
+es3fBooleanStateQuery.BooleanStateQuery.prototype.init = function() {
+ var testRoot = this;
+ var isEnableds = [
+ ['rasterizer_discard', 'RASTERIZER_DISCARD', gl.RASTERIZER_DISCARD, false],
+ ['cull_face', 'CULL_FACE', gl.CULL_FACE, false],
+ ['polygon_offset_fill', 'POLYGON_OFFSET_FILL', gl.POLYGON_OFFSET_FILL, false],
+ ['sample_alpha_to_coverage', 'SAMPLE_ALPHA_TO_COVERAGE', gl.SAMPLE_ALPHA_TO_COVERAGE, false],
+ ['sample_coverage', 'SAMPLE_COVERAGE', gl.SAMPLE_COVERAGE, false],
+ ['scissor_test', 'SCISSOR_TEST', gl.SCISSOR_TEST, false],
+ ['stencil_test', 'STENCIL_TEST', gl.STENCIL_TEST, false],
+ ['depth_test', 'DEPTH_TEST', gl.DEPTH_TEST, false],
+ ['blend', 'BLEND', gl.BLEND, false],
+ ['dither', 'DITHER', gl.DITHER, true]
+ ];
+ isEnableds.forEach(function(elem) {
+ var name = elem[0];
+ var description = elem[1];
+ var targetName = elem[2];
+ var value = elem[3];
+ testRoot.addChild(new es3fBooleanStateQuery.IsEnabledStateTestCase(name, description, targetName, value));
+ });
+
+ testRoot.addChild(new es3fBooleanStateQuery.ColorMaskTestCase('color_writemask', 'COLOR_WRITEMASK'));
+ testRoot.addChild(new es3fBooleanStateQuery.DepthWriteMaskTestCase('depth_writemask', 'DEPTH_WRITEMASK'));
+ testRoot.addChild(new es3fBooleanStateQuery.SampleCoverageInvertTestCase('sample_coverage_invert', 'SAMPLE_COVERAGE_INVERT'));
+ testRoot.addChild(new es3fBooleanStateQuery.InitialBooleanTestCase('transform_feedback_active_initial', 'initial TRANSFORM_FEEDBACK_ACTIVE', gl.TRANSFORM_FEEDBACK_ACTIVE, false));
+ testRoot.addChild(new es3fBooleanStateQuery.InitialBooleanTestCase('transform_feedback_paused_initial', 'initial TRANSFORM_FEEDBACK_PAUSED', gl.TRANSFORM_FEEDBACK_PAUSED, false));
+ testRoot.addChild(new es3fBooleanStateQuery.TransformFeedbackBasicTestCase('transform_feedback'));
+ testRoot.addChild(new es3fBooleanStateQuery.TransformFeedbackImplicitResumeTestCase('transform_feedback_implicit_resume'));
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fBooleanStateQuery.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fBooleanStateQuery.BooleanStateQuery());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fBooleanStateQuery.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferCopyTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferCopyTests.js
new file mode 100644
index 0000000000..51186231a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferCopyTests.js
@@ -0,0 +1,355 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fBufferCopyTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('modules.shared.glsBufferTestUtil');
+
+goog.scope(function() {
+
+ var es3fBufferCopyTests = functional.gles3.es3fBufferCopyTests;
+ var glsBufferTestUtil = modules.shared.glsBufferTestUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ /**
+ * @constructor
+ * @extends {glsBufferTestUtil.BufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} srcTarget
+ * @param {number} srcSize
+ * @param {number} srcHint
+ * @param {number} dstTarget
+ * @param {number} dstSize
+ * @param {number} dstHint
+ * @param {number} copySrcOffset
+ * @param {number} copyDstOffset
+ * @param {number} copySize
+ * @param {glsBufferTestUtil.VerifyType} verifyType
+ */
+ es3fBufferCopyTests.BasicBufferCopyCase = function(name, desc, srcTarget, srcSize, srcHint, dstTarget, dstSize, dstHint, copySrcOffset, copyDstOffset, copySize, verifyType) {
+ glsBufferTestUtil.BufferCase.call(this, name, desc);
+
+ this.m_srcTarget = srcTarget;
+ this.m_srcSize = srcSize;
+ this.m_srcHint = srcHint;
+ this.m_dstTarget = dstTarget;
+ this.m_dstSize = dstSize;
+ this.m_dstHint = dstHint;
+ this.m_copySrcOffset = copySrcOffset;
+ this.m_copyDstOffset = copyDstOffset;
+ this.m_copySize = copySize;
+ this.m_verifyType = verifyType;
+
+ assertMsgOptions(deMath.deInBounds32(this.m_copySrcOffset, 0, this.m_srcSize) && deMath.deInRange32(this.m_copySrcOffset + this.m_copySize, this.m_copySrcOffset, this.m_srcSize), 'Copy parameters are out of buffer\'s range', false, true);
+ assertMsgOptions(deMath.deInBounds32(this.m_copyDstOffset, 0, this.m_dstSize) && deMath.deInRange32(this.m_copyDstOffset + this.m_copySize, this.m_copyDstOffset, this.m_dstSize), 'Copy parameters are out of buffer\'s range', false, true);
+ };
+
+ es3fBufferCopyTests.BasicBufferCopyCase.prototype = Object.create(glsBufferTestUtil.BufferCase.prototype);
+ es3fBufferCopyTests.BasicBufferCopyCase.prototype.constructor = es3fBufferCopyTests.BasicBufferCopyCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fBufferCopyTests.BasicBufferCopyCase.prototype.iterate = function() {
+ /** @type {glsBufferTestUtil.BufferVerifier} */ var verifier = new glsBufferTestUtil.BufferVerifier(this.m_verifyType);
+ var srcRef = new glsBufferTestUtil.ReferenceBuffer();
+ var dstRef = new glsBufferTestUtil.ReferenceBuffer();
+ var srcBuf = 0;
+ var dstBuf = 0;
+ var srcSeed = deMath.binaryOp(deString.deStringHash(this.fullName()), 0xabcd, deMath.BinaryOp.XOR);
+ var dstSeed = deMath.binaryOp(deString.deStringHash(this.fullName()), 0xef01, deMath.BinaryOp.XOR);
+ var isOk = true;
+
+ srcRef.setSize(this.m_srcSize);
+ glsBufferTestUtil.fillWithRandomBytes(srcRef.getPtr(), this.m_srcSize, srcSeed);
+
+ dstRef.setSize(this.m_dstSize);
+ glsBufferTestUtil.fillWithRandomBytes(dstRef.getPtr(), this.m_dstSize, dstSeed);
+
+ // Create source buffer and fill with data.
+ srcBuf = this.genBuffer();
+ gl.bindBuffer(this.m_srcTarget, srcBuf);
+ gl.bufferData(this.m_srcTarget, srcRef.getPtr(), this.m_srcHint);
+
+ // Create destination buffer and fill with data.
+ dstBuf = this.genBuffer();
+ gl.bindBuffer(this.m_dstTarget, dstBuf);
+ gl.bufferData(this.m_dstTarget, dstRef.getPtr(), this.m_dstHint);
+
+ // Verify both buffers before executing copy.
+ isOk = verifier.verify(srcBuf, srcRef.getPtr(), 0, this.m_srcSize, this.m_srcTarget) && isOk;
+ isOk = verifier.verify(dstBuf, dstRef.getPtr(), 0, this.m_dstSize, this.m_dstTarget) && isOk;
+
+ // Execute copy.
+ dstRef.getPtr().set(srcRef.getPtr().subarray(this.m_copySrcOffset, this.m_copySrcOffset + this.m_copySize), this.m_copyDstOffset);
+
+ gl.bindBuffer(this.m_srcTarget, srcBuf);
+ gl.bindBuffer(this.m_dstTarget, dstBuf);
+ gl.copyBufferSubData(this.m_srcTarget, this.m_dstTarget, this.m_copySrcOffset, this.m_copyDstOffset, this.m_copySize);
+
+ // Verify both buffers after copy.
+ isOk = verifier.verify(srcBuf, srcRef.getPtr(), 0, this.m_srcSize, this.m_srcTarget) && isOk;
+ isOk = verifier.verify(dstBuf, dstRef.getPtr(), 0, this.m_dstSize, this.m_dstTarget) && isOk;
+
+ if (isOk)
+ testPassed('');
+ else
+ testFailed('Buffer verification failed');
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ // Case B: same buffer, take range as parameter
+
+ /**
+ * @constructor
+ * @extends {glsBufferTestUtil.BufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} srcTarget
+ * @param {number} dstTarget
+ * @param {number} hint
+ * @param {glsBufferTestUtil.VerifyType} verifyType
+ */
+ es3fBufferCopyTests.SingleBufferCopyCase = function(name, desc, srcTarget, dstTarget, hint, verifyType) {
+ glsBufferTestUtil.BufferCase.call(this, name, desc);
+ this.m_srcTarget = srcTarget;
+ this.m_dstTarget = dstTarget;
+ this.m_hint = hint;
+ this.m_verifyType = verifyType;
+ };
+
+ es3fBufferCopyTests.SingleBufferCopyCase.prototype = Object.create(glsBufferTestUtil.BufferCase.prototype);
+ es3fBufferCopyTests.SingleBufferCopyCase.prototype.constructor = es3fBufferCopyTests.SingleBufferCopyCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fBufferCopyTests.SingleBufferCopyCase.prototype.iterate = function() {
+ var size = 1000;
+ /** @type {glsBufferTestUtil.BufferVerifier} */ var verifier = new glsBufferTestUtil.BufferVerifier(this.m_verifyType);
+ var ref = new glsBufferTestUtil.ReferenceBuffer();
+ var baseSeed = deString.deStringHash(this.fullName());
+ var isOk = true;
+
+ ref.setSize(size);
+
+ // Create buffer.
+ var buf = this.genBuffer();
+ gl.bindBuffer(this.m_srcTarget, buf);
+
+ /** @type {Array<{srcOffset: number, dstOffset: number, copySize: number}>} */
+ var copyRanges = [{
+ srcOffset: 57, dstOffset: 701, copySize: 101 // Non-adjecent, from low to high.
+ },{
+ srcOffset: 640, dstOffset: 101, copySize: 101 // Non-adjecent, from high to low.
+ },{
+ srcOffset: 0, dstOffset: 500, copySize: 500 // Lower half to upper half.
+ },{
+ srcOffset: 500, dstOffset: 0, copySize: 500 // Upper half to lower half.
+ }];
+
+ for (var ndx = 0; ndx < copyRanges.length && isOk; ndx++) {
+ var srcOffset = copyRanges[ndx].srcOffset;
+ var dstOffset = copyRanges[ndx].dstOffset;
+ var copySize = copyRanges[ndx].copySize;
+
+ glsBufferTestUtil.fillWithRandomBytes(ref.getPtr(), size, deMath.binaryOp(baseSeed, deMath.deMathHash(ndx), deMath.BinaryOp.XOR));
+
+ // Fill with data.
+ gl.bindBuffer(this.m_srcTarget, buf);
+ gl.bufferData(this.m_srcTarget, ref.getPtr(), this.m_hint);
+
+ // Execute copy.
+ ref.getPtr().set(ref.getPtr().subarray(srcOffset, srcOffset + copySize), dstOffset);
+
+ gl.bindBuffer(this.m_dstTarget, buf);
+ gl.copyBufferSubData(this.m_srcTarget, this.m_dstTarget, srcOffset, dstOffset, copySize);
+
+ // Verify buffer after copy.
+ isOk = verifier.verify(buf, ref.getPtr(), 0, size, this.m_dstTarget) && isOk;
+ }
+
+ if (isOk)
+ testPassed('');
+ else
+ testFailed('Buffer verification failed');
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fBufferCopyTests.BufferCopyTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'copy', 'Buffer copy tests');
+ this.makeExecutable();
+ };
+
+ es3fBufferCopyTests.BufferCopyTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fBufferCopyTests.BufferCopyTests.prototype.constructor = es3fBufferCopyTests.BufferCopyTests;
+
+ es3fBufferCopyTests.BufferCopyTests.prototype.init = function() {
+ /** @type {glsBufferTestUtil.VerifyType} */ var verify;
+
+ var bufferTargets = [
+ gl.ARRAY_BUFFER,
+ gl.COPY_READ_BUFFER,
+ gl.COPY_WRITE_BUFFER,
+ gl.ELEMENT_ARRAY_BUFFER,
+ gl.PIXEL_PACK_BUFFER,
+ gl.PIXEL_UNPACK_BUFFER,
+ gl.TRANSFORM_FEEDBACK_BUFFER,
+ gl.UNIFORM_BUFFER
+ ];
+
+ // .basic
+
+ var basicGroup = new tcuTestCase.DeqpTest('basic', 'Basic buffer copy cases');
+ this.addChild(basicGroup);
+
+ for (var srcTargetNdx = 0; srcTargetNdx < bufferTargets.length; srcTargetNdx++) {
+ for (var dstTargetNdx = 0; dstTargetNdx < bufferTargets.length; dstTargetNdx++) {
+ if (srcTargetNdx == dstTargetNdx)
+ continue;
+
+ // In WebGL 2, a copy between an ELEMENT_ARRAY_BUFFER and other data buffer
+ // (not COPY_WRITE_BUFFER nor COPY_READ_BUFFER nor ELEMENT_ARRAY_BUFFER)
+ // cannot be made, so let's skip those cases.
+ if (bufferTargets[srcTargetNdx] == gl.ELEMENT_ARRAY_BUFFER ||
+ bufferTargets[dstTargetNdx] == gl.ELEMENT_ARRAY_BUFFER)
+ continue;
+
+ var srcTarget = bufferTargets[srcTargetNdx];
+ var dstTarget = bufferTargets[dstTargetNdx];
+ var size = 1017;
+ var hint = gl.STATIC_DRAW;
+ verify = glsBufferTestUtil.VerifyType.AS_VERTEX_ARRAY;
+ var name = glsBufferTestUtil.getBufferTargetName(srcTarget) + '_' + glsBufferTestUtil.getBufferTargetName(dstTarget);
+
+ basicGroup.addChild(new es3fBufferCopyTests.BasicBufferCopyCase(name, '', srcTarget, size, hint, dstTarget, size, hint, 0, 0, size, verify));
+ }
+ }
+
+ // .subrange
+
+ var subrangeGroup = new tcuTestCase.DeqpTest('subrange', 'Buffer subrange copy tests');
+ this.addChild(subrangeGroup);
+
+ /**
+ * @type {Array<{name: string, srcSize: number, dstSize: number, srcOffset: number, dstOffset: number, copySize: number}>}
+ */
+ var cases = [{
+ name: 'middle', srcSize: 1000, dstSize: 1000, srcOffset: 250, dstOffset: 250, copySize: 500
+ },{
+ name: 'small_to_large', srcSize: 100, dstSize: 1000, srcOffset: 0, dstOffset: 409, copySize: 100
+ },{
+ name: 'large_to_small', srcSize: 1000, dstSize: 100, srcOffset: 409, dstOffset: 0, copySize: 100
+ },{
+ name: 'low_to_high_1', srcSize: 1000, dstSize: 1000, srcOffset: 0, dstOffset: 500, copySize: 500
+ },{
+ name: 'low_to_high_2', srcSize: 997, dstSize: 1027, srcOffset: 0, dstOffset: 701, copySize: 111
+ },{
+ name: 'high_to_low_1', srcSize: 1000, dstSize: 1000, srcOffset: 500, dstOffset: 0, copySize: 500
+ },{
+ name: 'high_to_low_2', srcSize: 1027, dstSize: 997, srcOffset: 701, dstOffset: 17, copySize: 111
+ }];
+
+ for (var ndx = 0; ndx < cases.length; ndx++) {
+ var srcTarget = gl.COPY_READ_BUFFER;
+ var dstTarget = gl.COPY_WRITE_BUFFER;
+ var hint = gl.STATIC_DRAW;
+ verify = glsBufferTestUtil.VerifyType.AS_VERTEX_ARRAY;
+
+ subrangeGroup.addChild(
+ new es3fBufferCopyTests.BasicBufferCopyCase(
+ cases[ndx].name, '',
+ srcTarget, cases[ndx].srcSize, hint,
+ dstTarget, cases[ndx].dstSize, hint,
+ cases[ndx].srcOffset, cases[ndx].dstOffset, cases[ndx].copySize,
+ verify
+ )
+ );
+ }
+
+ // .single_buffer
+
+ var singleBufGroup = new tcuTestCase.DeqpTest('single_buffer', 'Copies within single buffer');
+ this.addChild(singleBufGroup);
+
+ for (var srcTargetNdx = 0; srcTargetNdx < bufferTargets.length; srcTargetNdx++) {
+ for (var dstTargetNdx = 0; dstTargetNdx < bufferTargets.length; dstTargetNdx++) {
+ if (srcTargetNdx == dstTargetNdx)
+ continue;
+
+ // In WebGL 2, we can't rebind an ELEMENT_ARRAY_BUFFER or TRANSFORM_FEEDBACK_BUFFER as a
+ // different type of buffer, so we skip those cases.
+ if (bufferTargets[srcTargetNdx] == gl.ELEMENT_ARRAY_BUFFER || bufferTargets[srcTargetNdx] == gl.TRANSFORM_FEEDBACK_BUFFER ||
+ bufferTargets[dstTargetNdx] == gl.ELEMENT_ARRAY_BUFFER || bufferTargets[dstTargetNdx] == gl.TRANSFORM_FEEDBACK_BUFFER)
+ continue;
+
+ var srcTarget = bufferTargets[srcTargetNdx];
+ var dstTarget = bufferTargets[dstTargetNdx];
+ var hint = gl.STATIC_DRAW;
+ verify = glsBufferTestUtil.VerifyType.AS_VERTEX_ARRAY;
+ var name = glsBufferTestUtil.getBufferTargetName(srcTarget) + '_' + glsBufferTestUtil.getBufferTargetName(dstTarget);
+
+ singleBufGroup.addChild(new es3fBufferCopyTests.SingleBufferCopyCase(name, '', srcTarget, dstTarget, hint, verify));
+ }
+ }
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fBufferCopyTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+
+ state.setRoot(new es3fBufferCopyTests.BufferCopyTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferObjectQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferObjectQueryTests.js
new file mode 100644
index 0000000000..a4384d3ae7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBufferObjectQueryTests.js
@@ -0,0 +1,177 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fBufferObjectQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+var es3fBufferObjectQueryTests = functional.gles3.es3fBufferObjectQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var es3fApiCase = functional.gles3.es3fApiCase;
+var deRandom = framework.delibs.debase.deRandom;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBufferObjectQueryTests.BufferCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fBufferObjectQueryTests.BufferCase, es3fApiCase.ApiCase);
+
+es3fBufferObjectQueryTests.BufferCase.prototype.test = function() {
+ var bufferTargets = [
+ gl.ARRAY_BUFFER, gl.COPY_READ_BUFFER,
+ gl.TRANSFORM_FEEDBACK_BUFFER, gl.UNIFORM_BUFFER,
+
+ gl.COPY_WRITE_BUFFER, gl.ELEMENT_ARRAY_BUFFER,
+ gl.PIXEL_PACK_BUFFER, gl.PIXEL_UNPACK_BUFFER
+ ];
+
+ // most test need only to be run with a subset of targets
+ var targets = this.m_testAllTargets ? bufferTargets.length : 4;
+
+ for (var ndx = 0; ndx < targets; ++ndx) {
+ this.m_bufferTarget = bufferTargets[ndx];
+
+ var bufferId = gl.createBuffer();
+ gl.bindBuffer(this.m_bufferTarget, bufferId);
+
+ this.testBuffer();
+
+ gl.bindBuffer(this.m_bufferTarget, null);
+ gl.deleteBuffer(bufferId);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fBufferObjectQueryTests.BufferCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBufferObjectQueryTests.BufferSizeCase = function(name, description) {
+ es3fBufferObjectQueryTests.BufferCase.call(this, name, description);
+ this.m_testAllTargets = true;
+};
+
+setParentClass(es3fBufferObjectQueryTests.BufferSizeCase, es3fBufferObjectQueryTests.BufferCase);
+
+es3fBufferObjectQueryTests.BufferSizeCase.prototype.testBuffer = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ var size = /** type {number} */ (gl.getBufferParameter(this.m_bufferTarget, gl.BUFFER_SIZE));
+ this.check(size == 0, 'Initial size should be 0; got ' + size);
+
+ var numIterations = 16;
+ for (var i = 0; i < numIterations; ++i) {
+ var len = rnd.getInt(0, 1024);
+ gl.bufferData(this.m_bufferTarget, len, gl.STREAM_DRAW);
+
+ size = /** type {number} */ (gl.getBufferParameter(this.m_bufferTarget, gl.BUFFER_SIZE));
+ this.check(size == len, 'Buffer size should be ' + len + ' ; got ' + size);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fBufferObjectQueryTests.BufferCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fBufferObjectQueryTests.BufferUsageCase = function(name, description) {
+ es3fBufferObjectQueryTests.BufferCase.call(this, name, description);
+ this.m_testAllTargets = false;
+};
+
+setParentClass(es3fBufferObjectQueryTests.BufferUsageCase, es3fBufferObjectQueryTests.BufferCase);
+
+es3fBufferObjectQueryTests.BufferUsageCase.prototype.testBuffer = function() {
+ var usage = /** type {number} */ (gl.getBufferParameter(this.m_bufferTarget, gl.BUFFER_USAGE));
+ this.check(usage == gl.STATIC_DRAW, 'Initial usage should be STATIC_DRAW; got ' + wtu.glEnumToString(gl, usage));
+
+ var usages = [
+ gl.STREAM_DRAW, gl.STREAM_READ,
+ gl.STREAM_COPY, gl.STATIC_DRAW,
+ gl.STATIC_READ, gl.STATIC_COPY,
+ gl.DYNAMIC_DRAW, gl.DYNAMIC_READ,
+ gl.DYNAMIC_COPY
+ ];
+
+ for (var ndx = 0; ndx < usages.length; ++ndx) {
+ gl.bufferData(this.m_bufferTarget, 16, usages[ndx]);
+
+ usage = /** type {number} */ (gl.getBufferParameter(this.m_bufferTarget, gl.BUFFER_USAGE));
+ this.check(usage == usages[ndx], 'Buffer usage should be ' + wtu.glEnumToString(gl, usages[ndx]) + ' ; got ' + wtu.glEnumToString(gl, usage));
+ }
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fBufferObjectQueryTests.BufferObjectQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'buffer_object', 'Buffer Object Query tests');
+};
+
+es3fBufferObjectQueryTests.BufferObjectQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fBufferObjectQueryTests.BufferObjectQueryTests.prototype.constructor = es3fBufferObjectQueryTests.BufferObjectQueryTests;
+
+es3fBufferObjectQueryTests.BufferObjectQueryTests.prototype.init = function() {
+ this.addChild(new es3fBufferObjectQueryTests.BufferSizeCase('buffer_size' , 'BUFFER_SIZE'));
+ this.addChild(new es3fBufferObjectQueryTests.BufferUsageCase('buffer_usage' , 'BUFFER_USAGE'));
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fBufferObjectQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fBufferObjectQueryTests.BufferObjectQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fBufferObjectQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBuiltinPrecisionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBuiltinPrecisionTests.js
new file mode 100644
index 0000000000..d5786180b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fBuiltinPrecisionTests.js
@@ -0,0 +1,87 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Tests for precision and range of GLSL builtins and types.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('functional.gles3.es3fBuiltinPrecisionTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('modules.shared.glsBuiltinPrecisionTests');
+
+goog.scope(function() {
+
+ var es3fBuiltinPrecisionTests = functional.gles3.es3fBuiltinPrecisionTests;
+ var glsBuiltinPrecisionTests = modules.shared.glsBuiltinPrecisionTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+ /**
+ * @param {*} context
+ * @param {number} caseId test case Id
+ * @return {tcuTestCase.DeqpTest}
+ */
+ es3fBuiltinPrecisionTests.createBuiltinPrecisionTests = function(context, caseId) {
+ /** @type {tcuTestCase.DeqpTest} */
+ var group = tcuTestCase.newTest('precision', 'Builtin precision tests');
+
+ /** @type {Array<gluShaderProgram.shaderType>} */ var shaderTypes = [];
+ var es3Cases = glsBuiltinPrecisionTests.createES3BuiltinCases(caseId);
+
+ shaderTypes.push(gluShaderProgram.shaderType.VERTEX);
+ shaderTypes.push(gluShaderProgram.shaderType.FRAGMENT);
+
+ glsBuiltinPrecisionTests.addBuiltinPrecisionTests(es3Cases, shaderTypes, group);
+ return group;
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ * @param {number} caseId test case Id
+ */
+ es3fBuiltinPrecisionTests.run = function(context, caseId) {
+ gl = context;
+ // Set up root Test
+ var state = tcuTestCase.runner;
+
+ var test = es3fBuiltinPrecisionTests.createBuiltinPrecisionTests(context, caseId);
+ var testName = test.fullName();
+ var testDescription = test.getDescription() === undefined ? '' : test.getDescription();
+
+ state.testName = testName;
+ state.setRoot(test);
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ test.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ } catch (err) {
+ bufferedLogToConsole('Exception: ' + err);
+ testFailedOptions('Failed to es3fAttribLocationTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fClippingTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fClippingTests.js
new file mode 100644
index 0000000000..e261cdea63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fClippingTests.js
@@ -0,0 +1,406 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fClippingTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+var es3fClippingTests = functional.gles3.es3fClippingTests;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuTestCase = framework.common.tcuTestCase;
+var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var rrUtil = framework.referencerenderer.rrUtil;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var deRandom = framework.delibs.debase.deRandom;
+var deMath = framework.delibs.debase.deMath;
+var tcuRGBA = framework.common.tcuRGBA;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {Array<number>} viewport
+ * @param {Array<number>} rangeX
+ * @param {Array<number>} rangeY
+ * @param {Array<number>} rangeZ
+ */
+es3fClippingTests.TriangleCase = function(name, desc, viewport, rangeX, rangeY, rangeZ) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_viewport = viewport;
+ this.m_rangeX = rangeX;
+ this.m_rangeY = rangeY;
+ this.m_rangeZ = rangeZ;
+};
+
+setParentClass(es3fClippingTests.TriangleCase, es3fFboTestCase.FboTestCase);
+
+es3fClippingTests.TriangleCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var x = this.m_viewport[0];
+ var y = this.m_viewport[1];
+ var width = this.m_viewport[2];
+ var height = this.m_viewport[3];
+ ctx.viewport(x, y, width, height);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT);
+
+ var shader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var program = ctx.createProgram(shader);
+ shader.setGradient(ctx, program, [0, 0, 0, 0], [1, 1, 1, 1]);
+
+ rrUtil.drawQuad(ctx, program,
+ [this.m_rangeX[0], this.m_rangeY[0], this.m_rangeZ[0]],
+ [this.m_rangeX[1], this.m_rangeY[1], this.m_rangeZ[1]]);
+ dst.readViewport(ctx, this.m_viewport);
+};
+
+/**
+ * Move the vertex coordinate to pixel center
+ */
+var center = function(x, width) {
+ var half = width / 2;
+ var pos = half + x * half;
+ // almost to the center to avoid problems when rounding
+ // the position the pixel edge
+ pos = Math.round(pos) + 0.49;
+ return (pos - half) / half;
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {Array<number>} viewport
+ * @param {number} lineWidth
+ */
+es3fClippingTests.LinesCase = function(name, desc, viewport, lineWidth) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_viewport = viewport;
+ this.m_lineWidth = lineWidth;
+};
+
+setParentClass(es3fClippingTests.LinesCase, es3fFboTestCase.FboTestCase);
+
+es3fClippingTests.LinesCase.prototype.compare = function(reference, result) {
+ return tcuImageCompare.bilinearCompare('Result', 'Image comparison result',
+ reference.getAccess(),
+ result.getAccess(),
+ tcuRGBA.newRGBAComponents(3, 3, 3, 3));
+};
+
+es3fClippingTests.LinesCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var x = this.m_viewport[0];
+ var y = this.m_viewport[1];
+ var width = this.m_viewport[2];
+ var height = this.m_viewport[3];
+ ctx.viewport(x, y, width, height);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT);
+
+ var shader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var program = ctx.createProgram(shader);
+ shader.setGradient(ctx, program, [0, 0, 0, 0], [1, 1, 1, 1]);
+
+ // positions
+ var posLoc = ctx.getAttribLocation(program, 'a_position');
+ if (posLoc == -1)
+ throw new Error('a_position attribute is not defined.');
+
+ var buffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ ctx.lineWidth(this.m_lineWidth);
+
+ var y1 = center(-0.5, height);
+ var y2 = center(-0.2, height);
+ var y3 = center(0.2, height);
+ var y4 = center(0.5, height);
+ var y5 = center(0, height);
+ var x1 = center(-0.5, width);
+ var x2 = center(-0.2, width);
+ var x3 = center(0.2, width);
+ var x4 = center(0.5, width);
+ var positions = [
+ // horizontal check
+ // both ends outside viewport
+ -1 - 1 / width, y1, 0, 1,
+ 1 + 1 / width, y1, 0, 1,
+ // one end inside viewport
+ -1 + 1 / width, y2, 0, 1,
+ 1 + 1 / width, y2, 0, 1,
+
+ -1 - 1 / width, y3, 0, 1,
+ 1 - 1 / width, y3, 0, 1,
+ // both ends inside viewport
+
+ -1 + 1 / width, y4, 0, 1,
+ 1 - 1 / width, y4, 0, 1,
+
+ //vertical check
+ // both ends outside viewport
+ x1, -1 - 1 / height, 0, 1,
+ x1, 1 + 1 / height, 0, 1,
+
+ // one end inside viewport
+ x2, -1 + 1 / height, 0, 1,
+ x2, 1 + 1 / height, 0, 1,
+
+ x3, -1 - 1 / height, 0, 1,
+ x3, 1 - 1 / height, 0, 1,
+ //both ends inside viewport
+ x4, -1 + 1 / height, 0, 1,
+ x4, 1 - 1 / height, 0, 1,
+
+ //depth check
+ -1, y5, -1.5, 1,
+ 1, y5, 1.1, 1
+ ];
+ var numVertices = positions.length / 4;
+
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(posLoc);
+ ctx.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
+
+ //colors
+ var coordLoc = ctx.getAttribLocation(program, 'a_coord');
+ if (coordLoc == -1)
+ throw new Error('a_coord attribute is not defined.');
+
+ var buffer2 = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, buffer2);
+
+ var coords = [];
+ for (var i = 0; i < numVertices / 2; i++) {
+ coords.push(0, 0, 1, 1);
+ }
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(coordLoc);
+ ctx.vertexAttribPointer(coordLoc, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.drawArrays(gl.LINES, 0, numVertices);
+ ctx.disableVertexAttribArray(posLoc);
+ ctx.disableVertexAttribArray(coordLoc);
+ ctx.bindBuffer(gl.ARRAY_BUFFER, null);
+ ctx.deleteBuffer(buffer);
+ ctx.deleteBuffer(buffer2);
+ dst.readViewport(ctx, this.m_viewport);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {Array<number>} viewport
+ * @param {number} pointSize
+ */
+es3fClippingTests.PointsCase = function(name, desc, viewport, pointSize) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_viewport = viewport;
+ this.m_pointSize = pointSize;
+};
+
+setParentClass(es3fClippingTests.PointsCase, es3fFboTestCase.FboTestCase);
+
+es3fClippingTests.PointsCase.prototype.compare = function(reference, result) {
+ return tcuImageCompare.bilinearCompare('Result', 'Image comparison result',
+ reference.getAccess(),
+ result.getAccess(),
+ tcuRGBA.newRGBAComponents(3, 3, 3, 3));
+};
+
+es3fClippingTests.PointsCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var x = this.m_viewport[0];
+ var y = this.m_viewport[1];
+ var width = this.m_viewport[2];
+ var height = this.m_viewport[3];
+ ctx.viewport(x, y, width, height);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT);
+
+ var shader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4, this.m_pointSize);
+ var program = ctx.createProgram(shader);
+ shader.setColor(ctx, program, [0, 1, 0, 1]);
+
+ // positions
+ var posLoc = ctx.getAttribLocation(program, 'a_position');
+ if (posLoc == -1)
+ throw new Error('a_position attribute is not defined.');
+
+ var buffer = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ var positions = [
+ // clipping in X axis
+ -1 - 1 / width, -0.5, 0, 1,
+ -1, 0, 0, 1,
+ -1 + 1 / width, 0.5, 0, 1,
+ 1 + 1 / width, -0.5, 0, 1,
+ 1, 0, 0, 1,
+ 1 - 1 / width, 0.5, 0, 1,
+ // clipping in Y axis
+ -0.5, -1 - 1 / height, 0, 1,
+ 0, -1, 0, 1,
+ 0.5, -1 + 1 / height, 0, 1,
+ -0.5, 1 - 1 / height, 0, 1,
+ 0, 1, 0, 1,
+ 0.5, 1 + 1 / height, 0, 1,
+ // clipping in Z axis
+ -0.5, -0.5, -1.5, 1,
+ 0, 0, 0, 1,
+ 0.5, 0.5, 1.5, 1
+ ];
+ // move the vertices to pixel centers to avoid off-by-1 differences
+ for (var i = 0; i < positions.length; i += 4) {
+ positions[i + 0] = center(positions[i + 0], width);
+ positions[i + 1] = center(positions[i + 1], height);
+ }
+ // positions = [-1 + 3/width + 0.001, 1 + 1/height + 0.001, 0, 1];
+ // positions = [-1, -1, 0, 1];
+
+ var numVertices = positions.length / 4;
+
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(posLoc);
+ ctx.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.drawArrays(gl.POINTS, 0, numVertices);
+ ctx.disableVertexAttribArray(posLoc);
+ ctx.bindBuffer(gl.ARRAY_BUFFER, null);
+ ctx.deleteBuffer(buffer);
+ dst.readViewport(ctx, this.m_viewport);
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fClippingTests.ClippingTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'clipping', 'Clipping tests');
+};
+
+es3fClippingTests.ClippingTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fClippingTests.ClippingTests.prototype.constructor = es3fClippingTests.ClippingTests;
+
+es3fClippingTests.ClippingTests.prototype.init = function() {
+ var width = gl.drawingBufferWidth;
+ var height = gl.drawingBufferHeight;
+ /** @const */ var WIDE_POINT = 5;
+ /** @const */ var WIDE_LINE = 5;
+ var viewports = [{ name: 'full_viewport', v: [0, 0, width, height] }, {
+ name: 'partial_viewport', v: [width * 0.3 , height * 0.2 , width * 0.6, height * 0.5] }
+ ];
+ var pointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
+ var lineWidthRange = gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE);
+
+ for (var i = 0; i < viewports.length; i++) {
+ var v = viewports[i].v.map(Math.floor);
+ var vName = viewports[i].name;
+ this.addChild(new es3fClippingTests.LinesCase('narrow_lines_' + vName, 'lines', v, 1));
+ if (lineWidthRange[1] >= WIDE_LINE)
+ this.addChild(new es3fClippingTests.LinesCase('wide_lines_' + vName, 'lines', v, WIDE_LINE));
+ this.addChild(new es3fClippingTests.PointsCase('small_points_' + vName, 'points', v, 1));
+ if (pointSizeRange[1] >= WIDE_POINT)
+ this.addChild(new es3fClippingTests.PointsCase('wide_points_' + vName, 'points', v, WIDE_POINT));
+ }
+
+ var rangesX = [
+ [-1.2, 1.2],
+ [-1.2, 0.8],
+ [-0.8, 1.2]
+ ];
+ var rangesY = [
+ [-1.2, 1.2],
+ [-1.2, 0.8],
+ [-0.8, 1.2]
+ ];
+ var rangesZ = [
+ [-1.2, 1.2],
+ [1.2, -1.2]
+ ];
+ for (var i = 0; i < viewports.length; i++) {
+ var v = viewports[i].v.map(Math.floor);
+ var vName = viewports[i].name;
+ for (var x = 0; x < rangesX.length; x++)
+ for (var y = 0; y < rangesY.length; y++)
+ for (var z = 0; z < rangesZ.length; z++) {
+ var rangeX = rangesX[x];
+ var rangeY = rangesY[y];
+ var rangeZ = rangesZ[z];
+ var name = 'triangles_' + viewports[i].name + '_' +
+ '(' + rangeX[0] + ',' + rangeY[0] + ',' + rangeZ[0] + ')-' +
+ '(' + rangeX[1] + ',' + rangeY[1] + ',' + rangeZ[1] + ')';
+ this.addChild(new es3fClippingTests.TriangleCase(name, 'triangles', v,
+ rangeX,
+ rangeY,
+ rangeZ));
+ }
+ }
+};
+
+/**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+es3fClippingTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fClippingTests.ClippingTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fClippingTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fDrawTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fDrawTests.js
new file mode 100644
index 0000000000..df42ac8193
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fDrawTests.js
@@ -0,0 +1,1155 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fDrawTests');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluVarType');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+goog.require('modules.shared.glsDrawTests');
+
+goog.scope(function() {
+
+ var es3fDrawTests = functional.gles3.es3fDrawTests;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluVarType = framework.opengl.gluVarType;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deUtil = framework.delibs.debase.deUtil;
+ var glsDrawTests = modules.shared.glsDrawTests;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+
+ /** @type {WebGL2RenderingContext}*/ var gl;
+
+ /**
+ * @enum
+ */
+ es3fDrawTests.TestIterationType = {
+ DRAW_COUNT: 0, // !< test with 2, 6, and 26 primitives
+ INSTANCE_COUNT: 1, // !< test with 2, 4, and 12 instances
+ INDEX_RANGE: 2
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTest} test
+ * @param {glsDrawTests.DrawTestSpec} baseSpec
+ * @param {?es3fDrawTests.TestIterationType} type
+ */
+ es3fDrawTests.addTestIterations = function(test, baseSpec, type) {
+ var spec = /** @type {glsDrawTests.DrawTestSpec} */ (deUtil.clone(baseSpec));
+
+ if (type == es3fDrawTests.TestIterationType.DRAW_COUNT) {
+ spec.primitiveCount = 1;
+ test.addIteration(spec, 'draw count = ' + spec.primitiveCount);
+
+ spec.primitiveCount = 5;
+ test.addIteration(spec, 'draw count = ' + spec.primitiveCount);
+
+ spec.primitiveCount = 25;
+ test.addIteration(spec, 'draw count = ' + spec.primitiveCount);
+ } else if (type == es3fDrawTests.TestIterationType.INSTANCE_COUNT) {
+ spec.instanceCount = 1;
+ test.addIteration(spec, 'instance count = ' + spec.instanceCount);
+
+ spec.instanceCount = 4;
+ test.addIteration(spec, 'instance count = ' + spec.instanceCount);
+
+ spec.instanceCount = 11;
+ test.addIteration(spec, 'instance count = ' + spec.instanceCount);
+ } else if (type == es3fDrawTests.TestIterationType.INDEX_RANGE) {
+ spec.indexMin = 0;
+ spec.indexMax = 23;
+ test.addIteration(spec, 'index range = [' + spec.indexMin + ', ' + spec.indexMax + ']');
+
+ spec.indexMin = 23;
+ spec.indexMax = 40;
+ test.addIteration(spec, 'index range = [' + spec.indexMin + ', ' + spec.indexMax + ']');
+
+ // Only makes sense with points
+ if (spec.primitive == glsDrawTests.DrawTestSpec.Primitive.POINTS) {
+ spec.indexMin = 5;
+ spec.indexMax = 5;
+ test.addIteration(spec, 'index range = [' + spec.indexMin + ', ' + spec.indexMax + ']');
+ }
+ } else
+ throw new Error('Invalid test iteration type');
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec} spec
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method
+ */
+ es3fDrawTests.genBasicSpec = function(spec, method) {
+ //spec.apiType = glu::ApiType::es(3,0);
+ spec.primitive = glsDrawTests.DrawTestSpec.Primitive.TRIANGLES;
+ spec.primitiveCount = 6;
+ spec.drawMethod = method;
+ spec.indexType = null;
+ spec.indexPointerOffset = 0;
+ spec.indexStorage = null;
+ spec.first = 0;
+ spec.indexMin = 0;
+ spec.indexMax = 0;
+ spec.instanceCount = 1;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+
+ spec.attribs[0].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[0].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[0].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[0].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[0].componentCount = 4;
+ spec.attribs[0].offset = 0;
+ spec.attribs[0].stride = 0;
+ spec.attribs[0].normalize = false;
+ spec.attribs[0].instanceDivisor = 0;
+ spec.attribs[0].useDefaultAttribute = false;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+
+ spec.attribs[1].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[1].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[1].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[1].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[1].componentCount = 2;
+ spec.attribs[1].offset = 0;
+ spec.attribs[1].stride = 0;
+ spec.attribs[1].normalize = false;
+ spec.attribs[1].instanceDivisor = 0;
+ spec.attribs[1].useDefaultAttribute = false;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} descr
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
+ * @param {?glsDrawTests.DrawTestSpec.Storage} indexStorage
+ */
+ es3fDrawTests.AttributeGroup = function(name, descr, drawMethod, primitive, indexType, indexStorage) {
+ tcuTestCase.DeqpTest.call(this, name, descr);
+ this.m_method = drawMethod;
+ this.m_primitive = primitive;
+ this.m_indexType = indexType;
+ this.m_indexStorage = indexStorage;
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.AttributeGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.AttributeGroup.prototype.constructor = es3fDrawTests.AttributeGroup;
+
+ es3fDrawTests.AttributeGroup.prototype.init = function() {
+ // select test type
+ /** @type {boolean} */ var instanced = this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED ||
+ this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED;
+ /** @type {boolean} */ var ranged = this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED;
+ /** @type {es3fDrawTests.TestIterationType} */ var testType = instanced ? es3fDrawTests.TestIterationType.INSTANCE_COUNT :
+ (ranged ? es3fDrawTests.TestIterationType.INDEX_RANGE : es3fDrawTests.TestIterationType.DRAW_COUNT);
+
+ // Single attribute
+ /** @type {glsDrawTests.DrawTest} */ var test = new glsDrawTests.DrawTest(null, 'single_attribute', 'Single attribute array.');
+ /** @type {glsDrawTests.DrawTestSpec} */ var spec = new glsDrawTests.DrawTestSpec();
+
+ //spec.apiType = glu::ApiType::es(3,0);
+ spec.primitive = this.m_primitive;
+ spec.primitiveCount = 5;
+ spec.drawMethod = this.m_method;
+ spec.indexType = this.m_indexType;
+ spec.indexPointerOffset = 0;
+ spec.indexStorage = this.m_indexStorage;
+ spec.first = 0;
+ spec.indexMin = 0;
+ spec.indexMax = 0;
+ spec.instanceCount = 1;
+
+ spec.attribs.length = 0;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[0].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[0].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[0].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[0].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[0].componentCount = 2;
+ spec.attribs[0].offset = 0;
+ spec.attribs[0].stride = 0;
+ spec.attribs[0].normalize = false;
+ spec.attribs[0].instanceDivisor = 0;
+ spec.attribs[0].useDefaultAttribute = false;
+
+ es3fDrawTests.addTestIterations(test, spec, testType);
+
+ this.addChild(test);
+
+ // Multiple attribute
+
+ test = new glsDrawTests.DrawTest(null, 'multiple_attributes', 'Multiple attribute arrays.');
+ spec.primitive = this.m_primitive;
+ spec.primitiveCount = 5;
+ spec.drawMethod = this.m_method;
+ spec.indexType = this.m_indexType;
+ spec.indexPointerOffset = 0;
+ spec.indexStorage = this.m_indexStorage;
+ spec.first = 0;
+ spec.indexMin = 0;
+ spec.indexMax = 0;
+ spec.instanceCount = 1;
+
+ spec.attribs.length = 0;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[0].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[0].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[0].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[0].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[0].componentCount = 4;
+ spec.attribs[0].offset = 0;
+ spec.attribs[0].stride = 0;
+ spec.attribs[0].normalize = false;
+ spec.attribs[0].instanceDivisor = 0;
+ spec.attribs[0].useDefaultAttribute = false;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[1].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[1].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[1].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[1].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[1].componentCount = 2;
+ spec.attribs[1].offset = 0;
+ spec.attribs[1].stride = 0;
+ spec.attribs[1].normalize = false;
+ spec.attribs[1].instanceDivisor = 0;
+ spec.attribs[1].useDefaultAttribute = false;
+
+ es3fDrawTests.addTestIterations(test, spec, testType);
+
+ this.addChild(test);
+
+ // Multiple attribute, second one divided
+
+ test = new glsDrawTests.DrawTest(null, 'instanced_attributes', 'Instanced attribute array.');
+
+ //spec.apiType = glu::ApiType::es(3,0);
+ spec.primitive = this.m_primitive;
+ spec.primitiveCount = 5;
+ spec.drawMethod = this.m_method;
+ spec.indexType = this.m_indexType;
+ spec.indexPointerOffset = 0;
+ spec.indexStorage = this.m_indexStorage;
+ spec.first = 0;
+ spec.indexMin = 0;
+ spec.indexMax = 0;
+ spec.instanceCount = 1;
+
+ spec.attribs.length = 0;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[0].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[0].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[0].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[0].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[0].componentCount = 4;
+ spec.attribs[0].offset = 0;
+ spec.attribs[0].stride = 0;
+ spec.attribs[0].normalize = false;
+ spec.attribs[0].instanceDivisor = 0;
+ spec.attribs[0].useDefaultAttribute = false;
+
+ // Add another position component so the instances wont be drawn on each other
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[1].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[1].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[1].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[1].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[1].componentCount = 2;
+ spec.attribs[1].offset = 0;
+ spec.attribs[1].stride = 0;
+ spec.attribs[1].normalize = false;
+ spec.attribs[1].instanceDivisor = 1;
+ spec.attribs[1].useDefaultAttribute = false;
+ spec.attribs[1].additionalPositionAttribute = true;
+
+ // Instanced color
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[2].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[2].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[2].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[2].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[2].componentCount = 3;
+ spec.attribs[2].offset = 0;
+ spec.attribs[2].stride = 0;
+ spec.attribs[2].normalize = false;
+ spec.attribs[2].instanceDivisor = 1;
+ spec.attribs[2].useDefaultAttribute = false;
+
+ es3fDrawTests.addTestIterations(test, spec, testType);
+
+ this.addChild(test);
+
+ // Multiple attribute, second one default
+ test = new glsDrawTests.DrawTest(null, 'default_attribute', 'Attribute specified with glVertexAttrib*.');
+
+ //spec.apiType = glu::ApiType::es(3,0);
+ spec.primitive = this.m_primitive;
+ spec.primitiveCount = 5;
+ spec.drawMethod = this.m_method;
+ spec.indexType = this.m_indexType;
+ spec.indexPointerOffset = 0;
+ spec.indexStorage = this.m_indexStorage;
+ spec.first = 0;
+ spec.indexMin = 0;
+ spec.indexMax = 17; // \note addTestIterations is not called for the spec, so we must ensure [indexMin, indexMax] is a good range
+ spec.instanceCount = 1;
+
+ spec.attribs.length = 0;
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ spec.attribs[0].inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ spec.attribs[0].outputType = glsDrawTests.DrawTestSpec.OutputType.VEC2;
+ spec.attribs[0].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[0].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[0].componentCount = 2;
+ spec.attribs[0].offset = 0;
+ spec.attribs[0].stride = 0;
+ spec.attribs[0].normalize = false;
+ spec.attribs[0].instanceDivisor = 0;
+ spec.attribs[0].useDefaultAttribute = false;
+
+ /** @type {Array<{input:?glsDrawTests.DrawTestSpec.InputType, output:?glsDrawTests.DrawTestSpec.OutputType, componentCount:number}>} */ var iopairs = [
+ {input: glsDrawTests.DrawTestSpec.InputType.FLOAT, output: glsDrawTests.DrawTestSpec.OutputType.VEC2, componentCount: 4},
+ {input: glsDrawTests.DrawTestSpec.InputType.FLOAT, output: glsDrawTests.DrawTestSpec.OutputType.VEC4, componentCount: 2},
+ {input: glsDrawTests.DrawTestSpec.InputType.INT, output: glsDrawTests.DrawTestSpec.OutputType.IVEC3, componentCount: 4},
+ {input: glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT, output: glsDrawTests.DrawTestSpec.OutputType.UVEC2, componentCount: 4}
+ ];
+
+ spec.attribs.push(new glsDrawTests.DrawTestSpec.AttributeSpec());
+ for (var ioNdx = 0; ioNdx < iopairs.length; ++ioNdx) {
+ /** @type {string} */ var desc = glsDrawTests.DrawTestSpec.inputTypeToString(iopairs[ioNdx].input) + iopairs[ioNdx].componentCount + ' to ' + glsDrawTests.DrawTestSpec.outputTypeToString(iopairs[ioNdx].output);
+
+ spec.attribs[1].inputType = iopairs[ioNdx].input;
+ spec.attribs[1].outputType = iopairs[ioNdx].output;
+ spec.attribs[1].storage = glsDrawTests.DrawTestSpec.Storage.BUFFER;
+ spec.attribs[1].usage = glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW;
+ spec.attribs[1].componentCount = iopairs[ioNdx].componentCount;
+ spec.attribs[1].offset = 0;
+ spec.attribs[1].stride = 0;
+ spec.attribs[1].normalize = false;
+ spec.attribs[1].instanceDivisor = 0;
+ spec.attribs[1].useDefaultAttribute = true;
+
+ test.addIteration(spec, desc);
+ }
+
+ this.addChild(test);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} descr
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod
+ */
+ es3fDrawTests.IndexGroup = function(name, descr, drawMethod) {
+ tcuTestCase.DeqpTest.call(this, name, descr);
+ /** @type {?glsDrawTests.DrawTestSpec.DrawMethod} */ this.m_method = drawMethod;
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.IndexGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.IndexGroup.prototype.constructor = es3fDrawTests.IndexGroup;
+
+ es3fDrawTests.IndexGroup.prototype.init = function() {
+ /** @type {Array<{storage: ?glsDrawTests.DrawTestSpec.Storage, type: ?glsDrawTests.DrawTestSpec.IndexType, aligned: boolean, offsets: Array<number>}>} */ var tests = [
+ {storage: glsDrawTests.DrawTestSpec.Storage.BUFFER, type: glsDrawTests.DrawTestSpec.IndexType.BYTE, aligned: true, offsets: [0, 1, -1]},
+ {storage: glsDrawTests.DrawTestSpec.Storage.BUFFER, type: glsDrawTests.DrawTestSpec.IndexType.SHORT, aligned: true, offsets: [0, 2, -1]},
+ {storage: glsDrawTests.DrawTestSpec.Storage.BUFFER, type: glsDrawTests.DrawTestSpec.IndexType.INT, aligned: true, offsets: [0, 4, -1]},
+
+ {storage: glsDrawTests.DrawTestSpec.Storage.BUFFER, type: glsDrawTests.DrawTestSpec.IndexType.SHORT, aligned: false, offsets: [1, 3, -1]},
+ {storage: glsDrawTests.DrawTestSpec.Storage.BUFFER, type: glsDrawTests.DrawTestSpec.IndexType.INT, aligned: false, offsets: [2, 3, -1]}
+ ];
+
+ /** @type {glsDrawTests.DrawTestSpec} */ var spec = new glsDrawTests.DrawTestSpec();
+ es3fDrawTests.genBasicSpec(spec, this.m_method);
+
+ /** @type {tcuTestCase.DeqpTest} */ var bufferGroup = new tcuTestCase.DeqpTest('buffer', 'buffer');
+ /** @type {tcuTestCase.DeqpTest} */ var unalignedBufferGroup = new tcuTestCase.DeqpTest('unaligned_buffer', 'unaligned buffer');
+
+ this.addChild(bufferGroup);
+ this.addChild(unalignedBufferGroup);
+
+ for (var testNdx = 0; testNdx < tests.length; ++testNdx) {
+ /** @type {{storage: ?glsDrawTests.DrawTestSpec.Storage, type: ?glsDrawTests.DrawTestSpec.IndexType, aligned: boolean, offsets: Array<number>}} */
+ var indexTest = tests[testNdx];
+ /** @type {tcuTestCase.DeqpTest} */ var group = indexTest.aligned ? bufferGroup : unalignedBufferGroup;
+
+ /** @type {string} */ var name = 'index_' + glsDrawTests.DrawTestSpec.indexTypeToString(indexTest.type);
+ /** @type {string} */ var desc = 'index ' + glsDrawTests.DrawTestSpec.indexTypeToString(indexTest.type) + ' in ' + glsDrawTests.DrawTestSpec.storageToString(indexTest.storage);
+ /** @type {glsDrawTests.DrawTest} */ var test = new glsDrawTests.DrawTest(null, name, desc);
+
+ spec.indexType = indexTest.type;
+ spec.indexStorage = indexTest.storage;
+
+ for (var iterationNdx = 0; iterationNdx < indexTest.offsets.length && indexTest.offsets[iterationNdx] != -1; ++iterationNdx) {
+ /** @type {string} */ var iterationDesc = 'offset ' + indexTest.offsets[iterationNdx];
+ spec.indexPointerOffset = indexTest.offsets[iterationNdx];
+ test.addIteration(spec, iterationDesc);
+ }
+
+ if (spec.isCompatibilityTest() != glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET &&
+ spec.isCompatibilityTest() != glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE)
+ group.addChild(test);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} descr
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod
+ */
+ es3fDrawTests.FirstGroup = function(name, descr, drawMethod) {
+ tcuTestCase.DeqpTest.call(this, name, descr);
+ /** @type {?glsDrawTests.DrawTestSpec.DrawMethod} */ this.m_method = drawMethod;
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.FirstGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.FirstGroup.prototype.constructor = es3fDrawTests.FirstGroup;
+
+ /**
+ * init
+ */
+ es3fDrawTests.FirstGroup.prototype.init = function() {
+ var firsts =
+ [
+ 1, 3, 17
+ ];
+
+ /** @type {glsDrawTests.DrawTestSpec} */ var spec = new glsDrawTests.DrawTestSpec();
+ es3fDrawTests.genBasicSpec(spec, this.m_method);
+
+ for (var firstNdx = 0; firstNdx < firsts.length; ++firstNdx) {
+ var name = 'first_' + firsts[firstNdx];
+ var desc = 'first ' + firsts[firstNdx];
+ /** @type {glsDrawTests.DrawTest} */ var test = new glsDrawTests.DrawTest(null, name, desc);
+
+ spec.first = firsts[firstNdx];
+
+ es3fDrawTests.addTestIterations(test, spec, es3fDrawTests.TestIterationType.DRAW_COUNT);
+
+ this.addChild(test);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} descr
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod
+ */
+ es3fDrawTests.MethodGroup = function(name, descr, drawMethod) {
+ tcuTestCase.DeqpTest.call(this, name, descr);
+ /** @type {?glsDrawTests.DrawTestSpec.DrawMethod} */ this.m_method = drawMethod;
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.MethodGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.MethodGroup.prototype.constructor = es3fDrawTests.MethodGroup;
+
+ /**
+ * init
+ */
+ es3fDrawTests.MethodGroup.prototype.init = function() {
+ var indexed = (this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) || (this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) || (this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED);
+ var hasFirst = (this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) || (this.m_method == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED);
+
+ var primitive =
+ [
+ glsDrawTests.DrawTestSpec.Primitive.POINTS,
+ glsDrawTests.DrawTestSpec.Primitive.TRIANGLES,
+ glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN,
+ glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP,
+ glsDrawTests.DrawTestSpec.Primitive.LINES,
+ glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP,
+ glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP
+ ];
+
+ if (hasFirst) {
+ // First-tests
+ this.addChild(new es3fDrawTests.FirstGroup('first', 'First tests', this.m_method));
+ }
+
+ if (indexed) {
+ // Index-tests
+ if (this.m_method != glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED)
+ this.addChild(new es3fDrawTests.IndexGroup('indices', 'Index tests', this.m_method));
+ }
+
+ for (var ndx = 0; ndx < primitive.length; ++ndx) {
+ var name = glsDrawTests.DrawTestSpec.primitiveToString(primitive[ndx]);
+ var desc = glsDrawTests.DrawTestSpec.primitiveToString(primitive[ndx]);
+
+ this.addChild(new es3fDrawTests.AttributeGroup(name, desc, this.m_method, primitive[ndx], glsDrawTests.DrawTestSpec.IndexType.SHORT, glsDrawTests.DrawTestSpec.Storage.BUFFER));
+ }
+ };
+
+ /**
+ * es3fDrawTests.GridProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ */
+ es3fDrawTests.GridProgram = function() {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_offset', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_color', rrGenericVector.GenericVecType.FLOAT));
+
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_offset;\n' +
+ 'in highp vec4 a_color;\n' +
+ 'out mediump vec4 v_color;\n' +
+ 'void main(void)\n' +
+ '{\n' +
+ ' gl_Position = a_position + a_offset;\n' +
+ ' v_color = a_color;\n' +
+ '}\n'
+ ));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n' +
+ 'in mediump vec4 v_color;\n' +
+ 'void main(void)\n' +
+ '{\n' +
+ ' dEQP_FragColor = v_color;\n' +
+ '}\n'
+ ));
+
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ };
+
+ es3fDrawTests.GridProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fDrawTests.GridProgram.prototype.constructor = es3fDrawTests.GridProgram;
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fDrawTests.GridProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var ndx = 0; ndx < numPackets; ++ndx) {
+ packets[ndx].position = deMath.add(
+ rrVertexAttrib.readVertexAttrib(inputs[0], packets[ndx].instanceNdx, packets[ndx].vertexNdx, rrGenericVector.GenericVecType.FLOAT),
+ rrVertexAttrib.readVertexAttrib(inputs[1], packets[ndx].instanceNdx, packets[ndx].vertexNdx, rrGenericVector.GenericVecType.FLOAT)
+ );
+ packets[ndx].outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[2], packets[ndx].instanceNdx, packets[ndx].vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packets
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fDrawTests.GridProgram.prototype.shadeFragments = function(packets, context) {
+ for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx)
+ for (var fragNdx = 0; fragNdx < 4; ++fragNdx)
+ packets[packetNdx].value = rrShadingContext.readTriangleVarying(packets[packetNdx], context, fragNdx);
+ };
+
+ /**
+ * InstancedGridRenderTest
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} gridSide
+ * @param {boolean} useIndices
+ */
+ es3fDrawTests.InstancedGridRenderTest = function(name, desc, gridSide, useIndices) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_gridSide = gridSide;
+ this.m_useIndices = useIndices;
+ };
+
+ es3fDrawTests.InstancedGridRenderTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.InstancedGridRenderTest.prototype.constructor = es3fDrawTests.InstancedGridRenderTest;
+
+ /**
+ * iterate
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fDrawTests.InstancedGridRenderTest.prototype.iterate = function() {
+ var renderTargetWidth = Math.min(1024, gl.canvas.width);
+ var renderTargetHeight = Math.min(1024, gl.canvas.height);
+
+ /** @type {sglrGLContext.GLContext} */ var ctx = new sglrGLContext.GLContext(gl);
+ /** @type {tcuSurface.Surface} */ var surface = new tcuSurface.Surface(renderTargetWidth, renderTargetHeight);
+ /** @type {es3fDrawTests.GridProgram} */ var program = new es3fDrawTests.GridProgram();
+
+ // render
+
+ this.renderTo(ctx, program, surface);
+
+ // verify image
+
+ if (this.verifyImage(surface))
+ testPassed('');
+ else
+ testFailed('Incorrect rendering result');
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {sglrGLContext.GLContext} ctx
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fDrawTests.InstancedGridRenderTest.prototype.renderTo = function(ctx, program, dst) {
+ var green = [0, 1, 0, 1];
+ var yellow = [1, 1, 0, 1];
+
+ /** @type {WebGLBuffer} */ var positionBuf = null;
+ /** @type {WebGLBuffer} */ var offsetBuf = null;
+ /** @type {WebGLBuffer} */ var colorBuf = null;
+ /** @type {WebGLBuffer} */ var indexBuf = null;
+ /** @type {WebGLProgram} */ var programID = ctx.createProgram(program);
+ /** @type {number} */ var posLocation = ctx.getAttribLocation(/** @type {WebGLProgram} */ (programID), 'a_position');
+ /** @type {number} */ var offsetLocation = ctx.getAttribLocation(/** @type {WebGLProgram} */ (programID), 'a_offset');
+ /** @type {number} */ var colorLocation = ctx.getAttribLocation(/** @type {WebGLProgram} */ (programID), 'a_color');
+
+ var cellW = 2.0 / this.m_gridSide;
+ var cellH = 2.0 / this.m_gridSide;
+ var vertexPositions = new Float32Array([
+ 0, 0, 0, 1,
+ cellW, 0, 0, 1,
+ 0, cellH, 0, 1,
+
+ 0, cellH, 0, 1,
+ cellW, 0, 0, 1,
+ cellW, cellH, 0, 1
+ ]);
+
+ var indices = new Uint16Array([
+ 0, 4, 3,
+ 2, 1, 5
+ ]);
+
+ var offsets = [];
+ for (var x = 0; x < this.m_gridSide; ++x)
+ for (var y = 0; y < this.m_gridSide; ++y) {
+ offsets.push(x * cellW - 1.0);
+ offsets.push(y * cellW - 1.0);
+ offsets.push(0, 0);
+ }
+ offsets = new Float32Array(offsets);
+
+ var colors = [];
+ for (var x = 0; x < this.m_gridSide; ++x)
+ for (var y = 0; y < this.m_gridSide; ++y) {
+ var colorToPush = ((x + y) % 2 == 0) ? (green) : (yellow);
+ colors.push(colorToPush[0]);
+ colors.push(colorToPush[1]);
+ colors.push(colorToPush[2]);
+ colors.push(colorToPush[3]);
+ }
+ colors = new Float32Array(colors);
+
+ positionBuf = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, positionBuf);
+ ctx.bufferData(gl.ARRAY_BUFFER, vertexPositions, gl.STATIC_DRAW);
+ ctx.vertexAttribPointer(posLocation, 4, gl.FLOAT, false, 0, 0);
+ ctx.vertexAttribDivisor(posLocation, 0);
+ ctx.enableVertexAttribArray(posLocation);
+
+ offsetBuf = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, offsetBuf);
+ ctx.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
+ ctx.vertexAttribPointer(offsetLocation, 4, gl.FLOAT, false, 0, 0);
+ ctx.vertexAttribDivisor(offsetLocation, 1);
+ ctx.enableVertexAttribArray(offsetLocation);
+
+ colorBuf = ctx.createBuffer();
+ ctx.bindBuffer(gl.ARRAY_BUFFER, colorBuf);
+ ctx.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ ctx.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
+ ctx.vertexAttribDivisor(colorLocation, 1);
+ ctx.enableVertexAttribArray(colorLocation);
+
+ if (this.m_useIndices) {
+ indexBuf = ctx.createBuffer();
+ ctx.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ ctx.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+ }
+
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT);
+
+ ctx.viewport(0, 0, dst.getWidth(), dst.getHeight());
+
+ ctx.useProgram(programID);
+ if (this.m_useIndices)
+ ctx.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, this.m_gridSide * this.m_gridSide);
+ else
+ ctx.drawArraysInstanced(gl.TRIANGLES, 0, 6, this.m_gridSide * this.m_gridSide);
+ ctx.useProgram(null);
+
+ if (this.m_useIndices)
+ ctx.deleteBuffer(indexBuf);
+ ctx.deleteBuffer(colorBuf);
+ ctx.deleteBuffer(offsetBuf);
+ ctx.deleteBuffer(positionBuf);
+ ctx.deleteProgram(programID);
+
+ ctx.finish();
+ dst.readViewport(ctx, [0 , 0, dst.getWidth(), dst.getHeight()]);
+ };
+
+ /**
+ * @param {tcuSurface.Surface} image
+ * @return {boolean}
+ */
+ es3fDrawTests.InstancedGridRenderTest.prototype.verifyImage = function(image) {
+ // \note the green/yellow pattern is only for clarity. The test will only verify that all instances were drawn by looking for anything non-green/yellow.
+
+ var green = [0, 255, 0, 255];
+ var yellow = [255, 255, 0, 255];
+ var colorThreshold = 20;
+
+ /** @type {tcuSurface.Surface} */ var error = new tcuSurface.Surface(image.getWidth(), image.getHeight());
+ var isOk = true;
+
+ for (var y = 1; y < image.getHeight() - 1; y++)
+ for (var x = 1; x < image.getWidth() - 1; x++) {
+ /** @type {tcuRGBA.RGBA} */ var pixel = new tcuRGBA.RGBA(image.getPixel(x, y));
+ var pixelOk = true;
+
+ // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
+ if (Math.abs(pixel.getGreen() - 255) > colorThreshold)
+ pixelOk = false;
+
+ // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
+ if (Math.abs(pixel.getBlue() - 0) > colorThreshold)
+ pixelOk = false;
+
+ error.setPixel(x, y, pixelOk ? [0, 255, 0, 255] : [255, 0, 0, 255]);
+ isOk = isOk && pixelOk;
+ }
+
+ if (!isOk) {
+ bufferedLogToConsole('Image verification failed.');
+ debug('Verfication result');
+ tcuLogImage.logImageWithInfo(image.getAccess(), 'Result');
+ tcuLogImage.logImageWithInfo(error.getAccess(), 'Error mask');
+ } else {
+ debug('Verfication result');
+ }
+
+ return isOk;
+ };
+
+ /**
+ * InstancingGroup
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fDrawTests.InstancingGroup = function(name, descr) {
+ tcuTestCase.DeqpTest.call(this, name, descr);
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.InstancingGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.InstancingGroup.prototype.constructor = es3fDrawTests.InstancingGroup;
+
+ /**
+ * init
+ */
+ es3fDrawTests.InstancingGroup.prototype.init = function() {
+ var gridWidths = [
+ 2,
+ 5,
+ 10,
+ 32,
+ 100
+ ];
+
+ // drawArrays
+ for (var ndx = 0; ndx < gridWidths.length; ++ndx) {
+ var name = 'draw_arrays_instanced_grid_' + gridWidths[ndx] + 'x' + gridWidths[ndx];
+ var desc = 'DrawArraysInstanced, Grid size ' + gridWidths[ndx] + 'x' + gridWidths[ndx];
+
+ this.addChild(new es3fDrawTests.InstancedGridRenderTest(name, desc, gridWidths[ndx], false));
+ }
+
+ // drawElements
+ for (var ndx = 0; ndx < gridWidths.length; ++ndx) {
+ var name = 'draw_elements_instanced_grid_' + gridWidths[ndx] + 'x' + gridWidths[ndx];
+ var desc = 'DrawElementsInstanced, Grid size ' + gridWidths[ndx] + 'x' + gridWidths[ndx];
+
+ this.addChild(new es3fDrawTests.InstancedGridRenderTest(name, desc, gridWidths[ndx], true));
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ */
+ es3fDrawTests.UniformWeightArray = function(size) {
+ this.weights = [];
+
+ for (var i = 0; i < size; ++i)
+ this.weights[i] = 1.0;
+ };
+
+ /**
+ * RandomGroup
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} descr
+ */
+ es3fDrawTests.RandomGroup = function(name, descr) {
+ tcuTestCase.DeqpTest.call(this, name, descr);
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.RandomGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.RandomGroup.prototype.constructor = es3fDrawTests.RandomGroup;
+
+ /**
+ * init
+ */
+ es3fDrawTests.RandomGroup.prototype.init = function() {
+ /** @type {number} */ var numAttempts = 300;
+
+ /** @type {Array<number>} */ var attribCounts = [1, 2, 5];
+ /** @type {Array<number>} */ var attribWeights = [30, 10, 1];
+ /** @type {Array<number>} */ var primitiveCounts = [2, 6, 64];
+ /** @type {Array<number>} */ var primitiveCountWeights = [20, 10, 1];
+ /** @type {Array<number>} */ var indexOffsets = [0, 7, 13];
+ /** @type {Array<number>} */ var indexOffsetWeights = [20, 20, 1];
+ /** @type {Array<number>} */ var firsts = [0, 6, 12];
+ /** @type {Array<number>} */ var firstWeights = [20, 20, 1];
+ /** @type {Array<number>} */ var instanceCounts = [1, 2, 16, 17];
+ /** @type {Array<number>} */ var instanceWeights = [20, 10, 5, 1];
+ /** @type {Array<number>} */ var indexMins = [0, 1, 3, 9];
+ /** @type {Array<number>} */ var indexMaxs = [5, 9, 129, 257];
+ /** @type {Array<number>} */ var indexWeights = [50, 50, 50, 50];
+ /** @type {Array<number>} */ var offsets = [0, 1, 5, 12];
+ /** @type {Array<number>} */ var offsetWeights = [50, 10, 10, 10];
+ /** @type {Array<number>} */ var strides = [0, 7, 16, 17];
+ /** @type {Array<number>} */ var strideWeights = [50, 10, 10, 10];
+ /** @type {Array<number>} */ var instanceDivisors = [0, 1, 3, 129];
+ /** @type {Array<number>} */ var instanceDivisorWeights = [70, 30, 10, 10];
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.Primitive>} */ var primitives = [
+ glsDrawTests.DrawTestSpec.Primitive.POINTS,
+ glsDrawTests.DrawTestSpec.Primitive.TRIANGLES,
+ glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN,
+ glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP,
+ glsDrawTests.DrawTestSpec.Primitive.LINES,
+ glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP,
+ glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var primitiveWeights = new es3fDrawTests.UniformWeightArray(primitives.length);
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.DrawMethod>} */ var drawMethods = [
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var drawMethodWeights = new es3fDrawTests.UniformWeightArray(drawMethods.length);
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.IndexType>} */ var indexTypes = [
+ glsDrawTests.DrawTestSpec.IndexType.BYTE,
+ glsDrawTests.DrawTestSpec.IndexType.SHORT,
+ glsDrawTests.DrawTestSpec.IndexType.INT
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var indexTypeWeights = new es3fDrawTests.UniformWeightArray(indexTypes.length);
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.Storage>} */ var storages = [
+ //glsDrawTests.DrawTestSpec.Storage.USER,
+ glsDrawTests.DrawTestSpec.Storage.BUFFER
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var storageWeights = new es3fDrawTests.UniformWeightArray(storages.length);
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.InputType>} */ var inputTypes = [
+ glsDrawTests.DrawTestSpec.InputType.FLOAT,
+ //glsDrawTests.DrawTestSpec.InputType.FIXED,
+ glsDrawTests.DrawTestSpec.InputType.BYTE,
+ glsDrawTests.DrawTestSpec.InputType.SHORT,
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE,
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT,
+ glsDrawTests.DrawTestSpec.InputType.INT,
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT,
+ glsDrawTests.DrawTestSpec.InputType.HALF,
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10,
+ glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var inputTypeWeights = new es3fDrawTests.UniformWeightArray(inputTypes.length);
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.OutputType>} */ var outputTypes = [
+ glsDrawTests.DrawTestSpec.OutputType.FLOAT,
+ glsDrawTests.DrawTestSpec.OutputType.VEC2,
+ glsDrawTests.DrawTestSpec.OutputType.VEC3,
+ glsDrawTests.DrawTestSpec.OutputType.VEC4,
+ glsDrawTests.DrawTestSpec.OutputType.INT,
+ glsDrawTests.DrawTestSpec.OutputType.UINT,
+ glsDrawTests.DrawTestSpec.OutputType.IVEC2,
+ glsDrawTests.DrawTestSpec.OutputType.IVEC3,
+ glsDrawTests.DrawTestSpec.OutputType.IVEC4,
+ glsDrawTests.DrawTestSpec.OutputType.UVEC2,
+ glsDrawTests.DrawTestSpec.OutputType.UVEC3,
+ glsDrawTests.DrawTestSpec.OutputType.UVEC4
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var outputTypeWeights = new es3fDrawTests.UniformWeightArray(outputTypes.length);
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.Usage>} */ var usages = [
+ glsDrawTests.DrawTestSpec.Usage.DYNAMIC_DRAW,
+ glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW,
+ glsDrawTests.DrawTestSpec.Usage.STREAM_DRAW,
+ glsDrawTests.DrawTestSpec.Usage.STREAM_READ,
+ glsDrawTests.DrawTestSpec.Usage.STREAM_COPY,
+ glsDrawTests.DrawTestSpec.Usage.STATIC_READ,
+ glsDrawTests.DrawTestSpec.Usage.STATIC_COPY,
+ glsDrawTests.DrawTestSpec.Usage.DYNAMIC_READ,
+ glsDrawTests.DrawTestSpec.Usage.DYNAMIC_COPY
+ ];
+ /** @type {es3fDrawTests.UniformWeightArray} */ var usageWeights = new es3fDrawTests.UniformWeightArray(usages.length);
+
+ /** @type {Array<number>} */ var insertedHashes = []; //'set' structure
+ /** @type {number} */ var insertedCount = 0;
+
+ for (var ndx = 0; ndx < numAttempts; ++ndx) {
+ /** @type {deRandom.Random} */ var random = new deRandom.Random(0xc551393 + ndx); // random does not depend on previous cases
+
+ /** @type {number} */ var attributeCount = random.chooseWeighted(attribCounts, attribWeights);
+ /** @type {glsDrawTests.DrawTestSpec} */ var spec = new glsDrawTests.DrawTestSpec();
+
+ //spec.apiType = glu::ApiType::es(3,0);
+ spec.primitive = /** @type {glsDrawTests.DrawTestSpec.Primitive} */ (random.chooseWeighted(primitives, primitiveWeights.weights));
+ spec.primitiveCount = random.chooseWeighted(primitiveCounts, primitiveCountWeights);
+ spec.drawMethod = /** @type {glsDrawTests.DrawTestSpec.DrawMethod} */ (random.chooseWeighted(drawMethods, drawMethodWeights.weights));
+ spec.indexType = /** @type {glsDrawTests.DrawTestSpec.IndexType} */ (random.chooseWeighted(indexTypes, indexTypeWeights.weights));
+ spec.indexPointerOffset = random.chooseWeighted(indexOffsets, indexOffsetWeights);
+ spec.indexStorage = /** @type {glsDrawTests.DrawTestSpec.Storage} */ (random.chooseWeighted(storages, storageWeights.weights));
+ spec.first = random.chooseWeighted(firsts, firstWeights);
+ spec.indexMin = random.chooseWeighted(indexMins, indexWeights);
+ spec.indexMax = random.chooseWeighted(indexMaxs, indexWeights);
+ spec.instanceCount = random.chooseWeighted(instanceCounts, instanceWeights);
+
+ // check spec is legal
+ if (!spec.valid())
+ continue;
+
+ var hasZeroDivisor = false;
+ for (var attrNdx = 0; attrNdx < attributeCount;) {
+ /** @type {boolean} */ var valid;
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = new glsDrawTests.DrawTestSpec.AttributeSpec();
+
+ attribSpec.inputType = /** @type {glsDrawTests.DrawTestSpec.InputType} */ (random.chooseWeighted(inputTypes, inputTypeWeights.weights));
+ attribSpec.outputType = /** @type {glsDrawTests.DrawTestSpec.OutputType} */ (random.chooseWeighted(outputTypes, outputTypeWeights.weights));
+ attribSpec.storage = /** @type {glsDrawTests.DrawTestSpec.Storage} */ (random.chooseWeighted(storages, storageWeights.weights));
+ attribSpec.usage = /** @type {glsDrawTests.DrawTestSpec.Usage} */ (random.chooseWeighted(usages, usageWeights.weights));
+ attribSpec.componentCount = random.getInt(1, 4);
+ attribSpec.offset = random.chooseWeighted(offsets, offsetWeights);
+ attribSpec.stride = random.chooseWeighted(strides, strideWeights);
+ attribSpec.normalize = random.getBool();
+ attribSpec.instanceDivisor = random.chooseWeighted(instanceDivisors, instanceDivisorWeights);
+ attribSpec.useDefaultAttribute = random.getBool();
+
+ // check spec is legal
+ valid = attribSpec.valid(/*spec.apiType*/);
+
+ // we do not want interleaved elements. (Might result in some weird floating point values)
+ if (attribSpec.stride && attribSpec.componentCount * glsDrawTests.DrawTestSpec.inputTypeSize(attribSpec.inputType) > attribSpec.stride)
+ valid = false;
+
+ // try again if not valid
+ if (valid) {
+ spec.attribs.push(attribSpec);
+ ++attrNdx;
+ if (attribSpec.instanceDivisor == 0)
+ hasZeroDivisor = true;
+ }
+ }
+
+ // Do not collapse all vertex positions to a single positions
+ if (spec.primitive != glsDrawTests.DrawTestSpec.Primitive.POINTS) {
+ spec.attribs[0].instanceDivisor = 0;
+ hasZeroDivisor = true;
+ }
+
+ // There should be at least one enabled vertex attribute array that has a divisor of zero in WebGL.
+ // This limitation is added to keep compatible with D3D. It differs from the feature in gles.
+ // See the section <Enabled Attribute> in WebGL spec: https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.6
+ if (hasZeroDivisor == false)
+ continue;
+
+ // Is render result meaningful?
+ // Only one vertex
+ if (spec.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != glsDrawTests.DrawTestSpec.Primitive.POINTS)
+ continue;
+ if (spec.attribs[0].useDefaultAttribute && spec.primitive != glsDrawTests.DrawTestSpec.Primitive.POINTS)
+ continue;
+
+ // Triangle only on one axis
+ if (spec.primitive == glsDrawTests.DrawTestSpec.Primitive.TRIANGLES || spec.primitive == glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN || spec.primitive == glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP) {
+ if (spec.attribs[0].componentCount == 1)
+ continue;
+ if (spec.attribs[0].outputType == glsDrawTests.DrawTestSpec.OutputType.FLOAT || spec.attribs[0].outputType == glsDrawTests.DrawTestSpec.OutputType.INT || spec.attribs[0].outputType == glsDrawTests.DrawTestSpec.OutputType.UINT)
+ continue;
+ if (spec.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
+ continue;
+ }
+
+ // Add case
+ /** @type {number} */ var hash = spec.hash();
+ for (var attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
+ hash = deMath.binaryOp(deMath.shiftLeft(hash, 2), spec.attribs[attrNdx].hash(), deMath.BinaryOp.XOR);
+
+ if (insertedHashes.indexOf(hash) == -1) {
+ // Only properly aligned
+ if (spec.isCompatibilityTest() != glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET &&
+ spec.isCompatibilityTest() != glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE) {
+ this.addChild(new glsDrawTests.DrawTest(spec, insertedCount + '', spec.getDesc()));
+ }
+ deUtil.dePushUniqueToArray(insertedHashes, hash);
+
+ ++insertedCount;
+ }
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fDrawTests.DrawTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'draw', 'Drawing tests');
+ this.makeExecutable();
+ };
+
+ es3fDrawTests.DrawTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fDrawTests.DrawTest.prototype.constructor = es3fDrawTests.DrawTest;
+
+ /**
+ * init
+ */
+ es3fDrawTests.DrawTest.prototype.init = function() {
+ // Basic
+ /** @type {Array<glsDrawTests.DrawTestSpec.DrawMethod>} */ var basicMethods = [
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED,
+ glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED
+ ];
+
+ for (var ndx = 0; ndx < basicMethods.length; ++ndx) {
+ var name = glsDrawTests.DrawTestSpec.drawMethodToString(basicMethods[ndx]);
+ var desc = glsDrawTests.DrawTestSpec.drawMethodToString(basicMethods[ndx]);
+
+ this.addChild(new es3fDrawTests.MethodGroup(name, desc, basicMethods[ndx]));
+ }
+
+ // extreme instancing
+
+ this.addChild(new es3fDrawTests.InstancingGroup('instancing', 'draw tests with a large instance count.'));
+
+ // Random
+
+ this.addChild(new es3fDrawTests.RandomGroup('random', 'random draw commands.'));
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fDrawTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+
+ var rootTest = new es3fDrawTests.DrawTest();
+ state.setRoot(rootTest);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(rootTest.fullName());
+ description(rootTest.getDescription());
+
+ try {
+ if (range) {
+ state.setRange(range);
+ }
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to run draw tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboColorbufferTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboColorbufferTests.js
new file mode 100644
index 0000000000..deb692a7b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboColorbufferTests.js
@@ -0,0 +1,1049 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboColorbufferTests');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+var es3fFboColorbufferTests = functional.gles3.es3fFboColorbufferTests;
+var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuSurface = framework.common.tcuSurface;
+var tcuTexture = framework.common.tcuTexture;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuRGBA = framework.common.tcuRGBA;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var rrUtil = framework.referencerenderer.rrUtil;
+var deMath = framework.delibs.debase.deMath;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+/** @const*/ var MIN_THRESHOLD = new tcuRGBA.RGBA([12, 12, 12, 12]);
+
+let canvasWH = 256;
+let texPotSize = [128, 128, 5];
+let texNpotSizeA = [129, 117];
+let texNpotSizeB = [99, 128];
+if (tcuTestCase.isQuickMode()) {
+ canvasWH = 32;
+ texPotSize = [16, 16, 5];
+ texNpotSizeA = [12, 11];
+ texNpotSizeB = [9, 16];
+}
+const texW = texPotSize[0];
+const texH = texPotSize[1];
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @param {deRandom.Random} rnd
+ * @param {Array<number>} minVal
+ * @param {Array<number>} maxVal
+ * @return {Array<number>}
+ */
+es3fFboColorbufferTests.randomVector = function(rnd, minVal, maxVal) {
+ var res = [];
+ for (var ndx = 0; ndx < minVal.length; ndx++)
+ res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
+ return res;
+};
+
+/**
+ * @param {deRandom.Random} rnd
+ * @return {Array<number>}
+ */
+es3fFboColorbufferTests.generateRandomColor = function(rnd) {
+ var retVal = [];
+
+ for (var i = 0; i < 3; ++i)
+ retVal[i] = rnd.getFloat();
+ retVal[3] = 1;
+
+ return retVal;
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ */
+es3fFboColorbufferTests.FboColorbufferCase = function(name, desc, format) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_format = format;
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorbufferCase, es3fFboTestCase.FboTestCase);
+
+/**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @return {boolean}
+ */
+es3fFboColorbufferTests.FboColorbufferCase.prototype.compare = function(reference, result) {
+ /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.max(es3fFboTestUtil.getFormatThreshold(this.m_format), MIN_THRESHOLD);
+
+ bufferedLogToConsole('Comparing images, threshold: ' + threshold);
+
+ return tcuImageCompare.bilinearCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), threshold);
+ };
+
+/**
+ * Deinit. Clear some GL state variables
+ */
+es3fFboColorbufferTests.FboColorbufferCase.prototype.deinit = function() {
+ // Texture state
+ {
+ // Only TEXTURE0 and TEXTURE1 are used in this test
+ var numTexUnits = 2;
+
+ for (var ndx = 0; ndx < numTexUnits; ndx++) {
+ gl.activeTexture(gl.TEXTURE0 + ndx);
+
+ // Reset 2D texture
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ // Reset cube map texture
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+
+ // Reset 2D array texture
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
+
+ // Reset 3D texture
+ gl.bindTexture(gl.TEXTURE_3D, null);
+ }
+
+ gl.activeTexture(gl.TEXTURE0);
+ }
+
+ // Pixel operations
+ {
+ gl.disable(gl.SCISSOR_TEST);
+ gl.disable(gl.BLEND);
+ }
+
+ // Framebuffer control
+ {
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ }
+ };
+
+/**
+ * @constructor
+ * @extends {es3fFboColorbufferTests.FboColorbufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ */
+es3fFboColorbufferTests.FboColorClearCase = function(name, desc, format, width, height) {
+ es3fFboColorbufferTests.FboColorbufferCase.call(this, name, desc, format);
+ this.m_width = width;
+ this.m_height = height;
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorClearCase, es3fFboColorbufferTests.FboColorbufferCase);
+
+es3fFboColorbufferTests.FboColorClearCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+es3fFboColorbufferTests.FboColorClearCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var fboFormat = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ var fmtClass = tcuTexture.getTextureChannelClass(fboFormat.type);
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(fboFormat);
+ var rnd = new deRandom.Random(17);
+ var numClears = 16;
+
+ var fbo = ctx.createFramebuffer();
+ var rbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_width, this.m_height);
+ this.checkError();
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_width, this.m_height);
+
+ // Initialize to transparent black.
+ switch (fmtClass) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ ctx.clearBufferfv(gl.COLOR, 0, new Float32Array(4));
+ break;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ ctx.clearBufferuiv(gl.COLOR, 0, new Uint32Array(4));
+ break;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ ctx.clearBufferiv(gl.COLOR, 0, new Int32Array(4));
+ break;
+
+ default:
+ throw new Error('Invalid channelclass ' + fmtClass);
+ }
+
+ // Do random scissored clears.
+ ctx.enable(gl.SCISSOR_TEST);
+ for (var ndx = 0; ndx < numClears; ndx++) {
+ var x = rnd.getInt(0, this.m_width - 1);
+ var y = rnd.getInt(0, this.m_height - 1);
+ var w = rnd.getInt(1, this.m_width - x);
+ var h = rnd.getInt(1, this.m_height - y);
+ var color = es3fFboColorbufferTests.randomVector(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
+
+ ctx.scissor(x, y, w, h);
+
+ switch (fmtClass) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ ctx.clearBufferfv(gl.COLOR, 0, color);
+ break;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ ctx.clearBufferuiv(gl.COLOR, 0, color);
+ break;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ ctx.clearBufferiv(gl.COLOR, 0, color);
+ break;
+
+ default:
+ throw new Error('Invalid channelclass ' + fmtClass);
+ }
+ }
+
+ // Read results from renderbuffer.
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_width, this.m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
+ this.checkError();
+ };
+
+/**
+ * @constructor
+ * @extends {es3fFboColorbufferTests.FboColorbufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} tex0Fmt
+ * @param {Array<number>} tex0Size
+ * @param {number} tex1Fmt
+ * @param {Array<number>} tex1Size
+ */
+es3fFboColorbufferTests.FboColorMultiTex2DCase = function(name, desc, tex0Fmt, tex0Size, tex1Fmt, tex1Size) {
+ es3fFboColorbufferTests.FboColorbufferCase.call(this, name, desc, tex0Fmt);
+ this.m_tex0Fmt = tex0Fmt;
+ this.m_tex0Size = tex0Size;
+ this.m_tex1Fmt = tex1Fmt;
+ this.m_tex1Size = tex1Size;
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorMultiTex2DCase, es3fFboColorbufferTests.FboColorbufferCase);
+
+es3fFboColorbufferTests.FboColorMultiTex2DCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_tex0Fmt);
+ this.checkFormatSupport(this.m_tex1Fmt);
+ return true; // No exception thrown
+ };
+
+es3fFboColorbufferTests.FboColorMultiTex2DCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var texFmt0 = gluTextureUtil.mapGLInternalFormat(this.m_tex0Fmt);
+ var texFmt1 = gluTextureUtil.mapGLInternalFormat(this.m_tex1Fmt);
+ var fmtInfo0 = tcuTextureUtil.getTextureFormatInfo(texFmt0);
+ var fmtInfo1 = tcuTextureUtil.getTextureFormatInfo(texFmt1);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFbo0Shader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], es3fFboTestUtil.getFragmentOutputType(texFmt0),
+ deMath.subtract(fmtInfo0.valueMax, fmtInfo0.valueMin),
+ fmtInfo0.valueMin);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFbo1Shader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], es3fFboTestUtil.getFragmentOutputType(texFmt1),
+ deMath.subtract(fmtInfo1.valueMax, fmtInfo1.valueMin),
+ fmtInfo1.valueMin);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var multiTexShader = new es3fFboTestUtil.Texture2DShader(
+ [gluTextureUtil.getSampler2DType(texFmt0), gluTextureUtil.getSampler2DType(texFmt1)],
+ gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texToFbo0ShaderID = ctx.createProgram(texToFbo0Shader);
+ var texToFbo1ShaderID = ctx.createProgram(texToFbo1Shader);
+ var multiTexShaderID = ctx.createProgram(multiTexShader);
+
+ // Setup shaders
+ multiTexShader.setTexScaleBias(0, deMath.scale(fmtInfo0.lookupScale, 0.5), deMath.scale(fmtInfo0.lookupBias, 0.5));
+ multiTexShader.setTexScaleBias(1, deMath.scale(fmtInfo1.lookupScale, 0.5), deMath.scale(fmtInfo1.lookupBias, 0.5));
+ texToFbo0Shader.setUniforms(ctx, texToFbo0ShaderID);
+ texToFbo1Shader.setUniforms(ctx, texToFbo1ShaderID);
+ multiTexShader.setUniforms(ctx, multiTexShaderID);
+
+ var fbo0 = ctx.createFramebuffer();
+ var fbo1 = ctx.createFramebuffer();
+ var tex0 = ctx.createTexture();
+ var tex1 = ctx.createTexture();
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var transferFmt = gluTextureUtil.getTransferFormat(ndx ? texFmt1 : texFmt0);
+ var format = ndx ? this.m_tex1Fmt : this.m_tex0Fmt;
+ var isFilterable = gluTextureUtil.isGLInternalColorFormatFilterable(format);
+ var size = ndx ? this.m_tex1Size : this.m_tex0Size;
+ var fbo = ndx ? fbo1 : fbo0;
+ var tex = ndx ? tex1 : tex0;
+
+ ctx.bindTexture(gl.TEXTURE_2D, tex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, isFilterable ? gl.LINEAR : gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, isFilterable ? gl.LINEAR : gl.NEAREST);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, size[0], size[1], 0, transferFmt.format, transferFmt.dataType, null);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+ }
+
+ // Render textures to both framebuffers.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var format = gl.RGBA;
+ var dataType = gl.UNSIGNED_BYTE;
+ var tmpTex;
+ var fbo = ndx ? fbo1 : fbo0;
+ var viewport = ndx ? this.m_tex1Size : this.m_tex0Size;
+ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ if (ndx == 0)
+ tcuTextureUtil.fillWithComponentGradients(data.getAccess(), [0, 0, 0, 0], [1, 1, 1, 1]);
+ else
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, [0.2, 0.7, 0.1, 1.0], [0.7, 0.1, 0.5, 0.8]);
+
+ tmpTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, tmpTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.viewport(0, 0, viewport[0], viewport[1]);
+ rrUtil.drawQuad(ctx, ndx ? texToFbo1ShaderID : texToFbo0ShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ }
+
+ // Render to framebuffer.
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
+ ctx.activeTexture(gl.TEXTURE0);
+ ctx.bindTexture(gl.TEXTURE_2D, tex0);
+ ctx.activeTexture(gl.TEXTURE1);
+ ctx.bindTexture(gl.TEXTURE_2D, tex1);
+ rrUtil.drawQuad(ctx, multiTexShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+
+ this.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
+ };
+
+/**
+ * @constructor
+ * @extends {es3fFboColorbufferTests.FboColorbufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} texFmt
+ * @param {Array<number>} texSize
+ */
+es3fFboColorbufferTests.FboColorTexCubeCase = function(name, desc, texFmt, texSize) {
+ es3fFboColorbufferTests.FboColorbufferCase.call(this, name, desc, texFmt);
+ this.m_texSize = texSize;
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorTexCubeCase, es3fFboColorbufferTests.FboColorbufferCase);
+
+es3fFboColorbufferTests.FboColorTexCubeCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+es3fFboColorbufferTests.FboColorTexCubeCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+
+ var cubeGLFaces = [
+ gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
+ ];
+
+ var cubeTexFaces = [
+ tcuTexture.CubeFace.CUBEFACE_POSITIVE_X,
+ tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y,
+ tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z,
+ tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X,
+ tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y,
+ tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z
+ ];
+
+ var rnd = new deRandom.Random(21);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFboShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], es3fFboTestUtil.getFragmentOutputType(texFmt),
+ deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin),
+ fmtInfo.valueMin);
+
+ /** @type {es3fFboTestUtil.TextureCubeShader} */
+ var cubeTexShader = new es3fFboTestUtil.TextureCubeShader(
+ gluTextureUtil.getSamplerCubeType(texFmt),
+ gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texToFboShaderID = ctx.createProgram(texToFboShader);
+ var cubeTexShaderID = ctx.createProgram(cubeTexShader);
+
+ // Setup shaders
+ texToFboShader.setUniforms(ctx, texToFboShaderID);
+ cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
+
+ // Framebuffers.
+ var fbos = [];
+ var tex;
+
+ var transferFmt = gluTextureUtil.getTransferFormat(texFmt);
+ var isFilterable = gluTextureUtil.isGLInternalColorFormatFilterable(this.m_format);
+ var size = this.m_texSize;
+
+ tex = ctx.createTexture();
+
+ ctx.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ ctx.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, isFilterable ? gl.LINEAR : gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, isFilterable ? gl.LINEAR : gl.NEAREST);
+
+ // Generate an image and FBO for each cube face
+ for (var ndx = 0; ndx < cubeGLFaces.length; ndx++)
+ ctx.texImage2D(cubeGLFaces[ndx], 0, this.m_format, size[0], size[1], 0, transferFmt.format, transferFmt.dataType, null);
+ this.checkError();
+
+ for (var ndx = 0; ndx < cubeGLFaces.length; ndx++) {
+ var layerFbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, layerFbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ fbos.push(layerFbo);
+ }
+
+ // Render test images to random cube faces
+ var order = [];
+
+ for (var n = 0; n < fbos.length; n++)
+ order.push(n);
+ rnd.shuffle(order);
+
+ for (var ndx = 0; ndx < 4; ndx++) {
+ var face = order[ndx];
+ var format = gl.RGBA;
+ var dataType = gl.UNSIGNED_BYTE;
+ var tmpTex;
+ var fbo = fbos[face];
+ var viewport = this.m_texSize;
+ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, es3fFboColorbufferTests.generateRandomColor(rnd), [0, 0, 0, 0]);
+
+ tmpTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, tmpTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.viewport(0, 0, viewport[0], viewport[1]);
+ rrUtil.drawQuad(ctx, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ this.checkError();
+
+ // Render to framebuffer
+ var p0 = [(ndx % 2) - 1.0, Math.floor(ndx / 2) - 1.0, 0.0];
+ var p1 = deMath.add(p0, [1.0, 1.0, 0.0]);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
+
+ ctx.activeTexture(gl.TEXTURE0);
+ ctx.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+
+ cubeTexShader.setFace(cubeTexFaces[face]);
+ cubeTexShader.setUniforms(ctx, cubeTexShaderID);
+
+ rrUtil.drawQuad(ctx, cubeTexShaderID, p0, p1);
+ this.checkError();
+ }
+
+ this.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
+ };
+
+/**
+ * @constructor
+ * @extends {es3fFboColorbufferTests.FboColorbufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} texFmt
+ * @param {Array<number>} texSize
+ */
+es3fFboColorbufferTests.FboColorTex2DArrayCase = function(name, desc, texFmt, texSize) {
+ es3fFboColorbufferTests.FboColorbufferCase.call(this, name, desc, texFmt);
+ this.m_texSize = texSize;
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorTex2DArrayCase, es3fFboColorbufferTests.FboColorbufferCase);
+
+es3fFboColorbufferTests.FboColorTex2DArrayCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+ es3fFboColorbufferTests.FboColorTex2DArrayCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ var rnd = new deRandom.Random(100);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFboShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], es3fFboTestUtil.getFragmentOutputType(texFmt),
+ deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin),
+ fmtInfo.valueMin);
+
+ /** @type {es3fFboTestUtil.Texture2DArrayShader} */
+ var arrayTexShader = new es3fFboTestUtil.Texture2DArrayShader(
+ gluTextureUtil.getSampler2DArrayType(texFmt),
+ gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texToFboShaderID = ctx.createProgram(texToFboShader);
+ var arrayTexShaderID = ctx.createProgram(arrayTexShader);
+
+ // Setup textures
+ texToFboShader.setUniforms(ctx, texToFboShaderID);
+ arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
+
+ // Framebuffers.
+ var fbos = [];
+ var tex;
+
+ var transferFmt = gluTextureUtil.getTransferFormat(texFmt);
+ var isFilterable = gluTextureUtil.isGLInternalColorFormatFilterable(this.m_format);
+ var size = this.m_texSize;
+
+ tex = ctx.createTexture();
+
+ ctx.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ ctx.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, isFilterable ? gl.LINEAR : gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, isFilterable ? gl.LINEAR : gl.NEAREST);
+ ctx.texImage3D(gl.TEXTURE_2D_ARRAY, 0, this.m_format, size[0], size[1], size[2], 0, transferFmt.format, transferFmt.dataType, null);
+
+ // Generate an FBO for each layer
+ for (var ndx = 0; ndx < this.m_texSize[2]; ndx++) {
+ var layerFbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, layerFbo);
+ ctx.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, ndx);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ fbos.push(layerFbo);
+ }
+
+ // Render test images to random texture layers
+ var order = [];
+
+ for (var n = 0; n < fbos.length; n++)
+ order.push(n);
+ rnd.shuffle(order);
+
+ for (var ndx = 0; ndx < 4; ndx++) {
+ var layer = order[ndx];
+ var format = gl.RGBA;
+ var dataType = gl.UNSIGNED_BYTE;
+ var fbo = fbos[layer];
+ var viewport = this.m_texSize;
+ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, es3fFboColorbufferTests.generateRandomColor(rnd), [0, 0, 0, 0]);
+
+ var tmpTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, tmpTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.viewport(0, 0, viewport[0], viewport[1]);
+ rrUtil.drawQuad(ctx, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ this.checkError();
+
+ // Render to framebuffer
+ var p0 = [(ndx % 2) - 1.0, Math.floor(ndx / 2) - 1.0, 0.0];
+ var p1 = deMath.add(p0, [1.0, 1.0, 0.0]);
+ debug('Layer:' + layer + ' rectangle: ' + p0 + ' ' + p1);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
+
+ ctx.activeTexture(gl.TEXTURE0);
+ ctx.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+
+ arrayTexShader.setLayer(layer);
+ arrayTexShader.setUniforms(ctx, arrayTexShaderID);
+
+ rrUtil.drawQuad(ctx, arrayTexShaderID, p0, p1);
+ this.checkError();
+ }
+
+ this.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
+ };
+
+/**
+ * @constructor
+ * @extends {es3fFboColorbufferTests.FboColorbufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} texFmt
+ * @param {Array<number>} texSize
+ */
+es3fFboColorbufferTests.FboColorTex3DCase = function(name, desc, texFmt, texSize) {
+ es3fFboColorbufferTests.FboColorbufferCase.call(this, name, desc, texFmt);
+ this.m_texSize = texSize;
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorTex3DCase, es3fFboColorbufferTests.FboColorbufferCase);
+
+es3fFboColorbufferTests.FboColorTex3DCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+ es3fFboColorbufferTests.FboColorTex3DCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ var rnd = new deRandom.Random(100);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFboShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], es3fFboTestUtil.getFragmentOutputType(texFmt),
+ deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin),
+ fmtInfo.valueMin);
+
+ /** @type {es3fFboTestUtil.Texture3DShader} */
+ var tdTexShader = new es3fFboTestUtil.Texture3DShader(
+ gluTextureUtil.getSampler3D(texFmt),
+ gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texToFboShaderID = ctx.createProgram(texToFboShader);
+ var tdTexShaderID = ctx.createProgram(tdTexShader);
+
+ // Setup textures
+ texToFboShader.setUniforms(ctx, texToFboShaderID);
+ tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
+
+ // Framebuffers.
+ var fbos = [];
+ var tex;{
+ var transferFmt = gluTextureUtil.getTransferFormat(texFmt);
+ var size = this.m_texSize;
+
+ tex = ctx.createTexture();
+
+ ctx.bindTexture(gl.TEXTURE_3D, tex);
+ ctx.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ ctx.texImage3D(gl.TEXTURE_3D, 0, this.m_format, size[0], size[1], size[2], 0, transferFmt.format, transferFmt.dataType, null);
+
+ // Generate an FBO for each layer
+ for (var ndx = 0; ndx < this.m_texSize[2]; ndx++) {
+ var layerFbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, layerFbo);
+ ctx.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, ndx);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ fbos.push(layerFbo);
+ }
+ }
+
+ // Render test images to random texture layers
+ var order = [];
+
+ for (var n = 0; n < fbos.length; n++)
+ order.push(n);
+ rnd.shuffle(order);
+
+ for (var ndx = 0; ndx < 4; ndx++) {
+ var layer = order[ndx];
+ var format = gl.RGBA;
+ var dataType = gl.UNSIGNED_BYTE;
+ var fbo = fbos[layer];
+ var viewport = this.m_texSize;
+ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, es3fFboColorbufferTests.generateRandomColor(rnd), [0, 0, 0, 0]);
+
+ var tmpTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, tmpTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.viewport(0, 0, viewport[0], viewport[1]);
+ rrUtil.drawQuad(ctx, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ this.checkError();
+
+ // Render to framebuffer
+ var p0 = [(ndx % 2) - 1.0, Math.floor(ndx / 2) - 1.0, 0.0];
+ var p1 = deMath.add(p0, [1.0, 1.0, 0.0]);
+ debug('Layer:' + layer + ' rectangle: ' + p0 + ' ' + p1);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
+
+ ctx.activeTexture(gl.TEXTURE0);
+ ctx.bindTexture(gl.TEXTURE_3D, tex);
+
+ tdTexShader.setDepth(layer / (this.m_texSize[2] - 1));
+ tdTexShader.setUniforms(ctx, tdTexShaderID);
+
+ rrUtil.drawQuad(ctx, tdTexShaderID, p0, p1);
+ this.checkError();
+ }
+
+ this.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboColorbufferTests.FboColorbufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {Array<number>} size
+ * @param {number} funcRGB
+ * @param {number} funcAlpha
+ * @param {number} srcRGB
+ * @param {number} dstRGB
+ * @param {number} srcAlpha
+ * @param {number} dstAlpha
+ */
+es3fFboColorbufferTests.FboBlendCase = function(name, desc, format, size, funcRGB, funcAlpha, srcRGB, dstRGB, srcAlpha, dstAlpha) {
+ es3fFboColorbufferTests.FboColorbufferCase.call(this, name, desc, format);
+ this.m_size = size;
+ this.m_funcRGB = funcRGB;
+ this.m_funcAlpha = funcAlpha;
+ this.m_srcRGB = srcRGB;
+ this.m_dstRGB = dstRGB;
+ this.m_srcAlpha = srcAlpha;
+ this.m_dstAlpha = dstAlpha
+};
+
+setParentClass(es3fFboColorbufferTests.FboBlendCase, es3fFboColorbufferTests.FboColorbufferCase);
+
+es3fFboColorbufferTests.FboBlendCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ }
+
+ es3fFboColorbufferTests.FboBlendCase.prototype.render = function(dst) {
+ // \note Assumes floating-point or fixed-point format.
+ var ctx = this.getCurrentContext();
+ var fboFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(fboFmt);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], gluShaderUtil.DataType.FLOAT_VEC4);
+
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texShaderID = ctx.createProgram(texShader);
+ var gradShaderID = ctx.createProgram(gradShader);
+
+ // Setup shaders
+ texShader.setUniforms (ctx, texShaderID);
+ gradShader.setGradient(ctx, gradShaderID, [0, 0, 0, 0], [1, 1, 1, 1]);
+
+ var fbo = ctx.createFramebuffer();
+ var rbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_size[0], this.m_size[1]);
+ this.checkError();
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_size[0], this.m_size[1]);
+
+ // Fill framebuffer with grid pattern.
+ var format = gl.RGBA;
+ var dataType = gl.UNSIGNED_BYTE;
+ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, [0.2, 0.7, 0.1, 1.0], [0.7, 0.1, 0.5, 0.8]);
+
+ var gridTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, gridTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ rrUtil.drawQuad(ctx, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ this.checkError();
+
+ // Setup blend.
+ ctx.enable(gl.BLEND);
+ ctx.blendEquationSeparate(this.m_funcRGB, this.m_funcAlpha);
+ ctx.blendFuncSeparate(this.m_srcRGB, this.m_dstRGB, this.m_srcAlpha, this.m_dstAlpha);
+
+ // Render gradient with blend.
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+
+ es3fFboTestUtil.readPixels(ctx, dst, 0, 0, this.m_size[0], this.m_size[1], fboFmt, [1, 1, 1, 1], [0, 0, 0, 0]);
+ };
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fFboColorbufferTests.FboColorbufferTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'color', 'Colorbuffer tests');
+};
+
+setParentClass(es3fFboColorbufferTests.FboColorbufferTests, tcuTestCase.DeqpTest);
+
+es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
+ var colorFormats = [
+ // RGBA formats
+ gl.RGBA32I,
+ gl.RGBA32UI,
+ gl.RGBA16I,
+ gl.RGBA16UI,
+ gl.RGBA8,
+ gl.RGBA8I,
+ gl.RGBA8UI,
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGB10_A2UI,
+ gl.RGBA4,
+ gl.RGB5_A1,
+
+ // RGB formats
+ gl.RGB8,
+ gl.RGB565,
+
+ // RG formats
+ gl.RG32I,
+ gl.RG32UI,
+ gl.RG16I,
+ gl.RG16UI,
+ gl.RG8,
+ gl.RG8I,
+ gl.RG8UI,
+
+ // R formats
+ gl.R32I,
+ gl.R32UI,
+ gl.R16I,
+ gl.R16UI,
+ gl.R8,
+ gl.R8I,
+ gl.R8UI,
+
+ // gl.EXT_color_buffer_float
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F,
+
+ // gl.EXT_color_buffer_half_float is not exposed in WebGL 2.0.
+ // gl.RGB16F
+ ];
+
+ // .clear
+ var clearGroup = tcuTestCase.newTest("clear", "Color clears");
+ this.addChild(clearGroup);
+
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ clearGroup.addChild(new es3fFboColorbufferTests.FboColorClearCase(
+ es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texNpotSizeA[0], texNpotSizeA[1]));
+ }
+
+ var numGroups = 6;
+
+ // .tex2d
+ var tex2DGroup = [];
+ for (var ii = 0; ii < numGroups; ++ii) {
+ tex2DGroup[ii] = tcuTestCase.newTest("tex2d", "Texture 2D tests");
+ this.addChild(tex2DGroup[ii]);
+ }
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ tex2DGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorMultiTex2DCase(
+ es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texNpotSizeA, colorFormats[ndx], texNpotSizeB));
+ }
+
+ // .texcube
+ var texCubeGroup = [];
+ for (var ii = 0; ii < numGroups; ++ii) {
+ texCubeGroup[ii] = tcuTestCase.newTest("texcube", "Texture cube map tests");
+ this.addChild(texCubeGroup[ii]);
+ }
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ texCubeGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorTexCubeCase(
+ es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texPotSize));
+ }
+
+ // .tex2darray
+ var tex2DArrayGroup = [];
+ for (var ii = 0; ii < numGroups; ++ii) {
+ tex2DArrayGroup[ii] = tcuTestCase.newTest("tex2darray", "Texture 2D array tests");
+ this.addChild(tex2DArrayGroup[ii]);
+ }
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ tex2DArrayGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorTex2DArrayCase(
+ es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texPotSize));
+ }
+
+ // .tex3d
+ var tex3DGroup = [];
+ for (var ii = 0; ii < numGroups; ++ii) {
+ tex3DGroup[ii] = tcuTestCase.newTest("tex3d", "Texture 3D tests");
+ this.addChild(tex3DGroup[ii]);
+ }
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ tex3DGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorTex3DCase(
+ es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texPotSize));
+ }
+
+ // .blend
+ var blendGroup = tcuTestCase.newTest("blend", "Blending tests");
+ this.addChild(blendGroup);
+
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ var format = colorFormats[ndx];
+ var texFmt = gluTextureUtil.mapGLInternalFormat(format);
+ var fmtClass = tcuTexture.getTextureChannelClass(texFmt.type);
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+
+ if (texFmt.type == tcuTexture.ChannelType.FLOAT ||
+ fmtClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER ||
+ fmtClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER)
+ continue; // Blending is not supported.
+
+ blendGroup.addChild(new es3fFboColorbufferTests.FboBlendCase(fmtName + "_src_over", "", format,
+ texNpotSizeA, gl.FUNC_ADD, gl.FUNC_ADD, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE));
+ }
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fFboColorbufferTests.run = function(context, range) {
+ gl = context;
+
+ const canvas = gl.canvas;
+ canvas.width = canvasWH;
+ canvas.height = canvasWH;
+
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fFboColorbufferTests.FboColorbufferTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFboColorbufferTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboCompletenessTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboCompletenessTests.js
new file mode 100644
index 0000000000..1ae68fc8c7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboCompletenessTests.js
@@ -0,0 +1,567 @@
+
+// FboCompletenessTests
+'use strict';
+goog.provide('functional.gles3.es3fFboCompletenessTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('modules.shared.glsFboCompletenessTests');
+goog.require('modules.shared.glsFboUtil');
+
+goog.scope(function() {
+
+ var es3fFboCompletenessTests = functional.gles3.es3fFboCompletenessTests;
+ var glsFboUtil = modules.shared.glsFboUtil;
+ var glsFboCompletenessTests = modules.shared.glsFboCompletenessTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+
+ es3fFboCompletenessTests.initGlDependents = function(gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ /**
+ * @type {Array<number>}
+ */
+ es3fFboCompletenessTests.s_es3ColorRenderables = [
+ // GLES3, 4.4.4: "An internal format is color-renderable if it is one of
+ // the formats from table 3.12 noted as color-renderable..."
+ gl.R8, gl.RG8, gl.RGB8, gl.RGB565, gl.RGBA4, gl.RGB5_A1, gl.RGBA8,
+ gl.RGB10_A2, gl.RGB10_A2UI, gl.SRGB8_ALPHA8,
+ 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.RGBA81, gl.RGBA8UI, gl.RGB16I, gl.RGBA16UI, gl.RGBA32I, gl.RGBA32UI
+ ];
+
+ /**
+ * @type {Array<number>}
+ */
+ es3fFboCompletenessTests.s_es3UnsizedColorRenderables = [
+ // "...or if it is unsized format RGBA or RGB."
+ // See Table 3.3 in GLES3.
+ glsFboUtil.formatkey(gl.RGBA, gl.UNSIGNED_BYTE),
+ glsFboUtil.formatkey(gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4),
+ glsFboUtil.formatkey(gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1),
+ glsFboUtil.formatkey(gl.RGB, gl.UNSIGNED_BYTE),
+ glsFboUtil.formatkey(gl.RGB, gl.UNSIGNED_SHORT_5_6_5)
+ ];
+
+ /**
+ * @type {Array<number>}
+ */
+ es3fFboCompletenessTests.s_es3DepthRenderables = [
+ // GLES3, 4.4.4: "An internal format is depth-renderable if it is one of
+ // the formats from table 3.13."
+ gl.DEPTH_COMPONENT16, gl.DEPTH_COMPONENT24, gl.DEPTH_COMPONENT32F,
+ gl.DEPTH24_STENCIL8, gl.DEPTH32F_STENCIL8
+ ];
+
+ /**
+ * @type {Array<number>}
+ */
+ es3fFboCompletenessTests.s_es3StencilRboRenderables = [
+ // GLES3, 4.4.4: "An internal format is stencil-renderable if it is
+ // STENCIL_INDEX8..."
+ gl.STENCIL_INDEX8
+ ];
+
+ /**
+ * @type {Array<number>}
+ */
+ es3fFboCompletenessTests.s_es3StencilRenderables = [
+ // "...or one of the formats from table 3.13 whose base internal format is
+ // DEPTH_STENCIL."
+ gl.DEPTH24_STENCIL8, gl.DEPTH32F_STENCIL8
+ ];
+
+ /**
+ * @type {Array<number>}
+ */
+ es3fFboCompletenessTests.s_es3TextureFloatFormats = [
+ gl.RGBA32F, gl.RGBA16F, gl.R11F_G11F_B10F,
+ gl.RG32F, gl.RG16F, gl.R32F, gl.R16F,
+ gl.RGBA16F, gl.RGB16F, gl.RG16F, gl.R16F
+ ];
+
+ /**
+ * @type {Array<glsFboUtil.formatT>}
+ */
+ es3fFboCompletenessTests.s_es3Formats = [
+ [
+ (
+ glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.COLOR_RENDERABLE |
+ glsFboUtil.FormatFlags.TEXTURE_VALID
+ ),
+ glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3UnsizedColorRenderables)
+ ],
+ [
+ (
+ glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.COLOR_RENDERABLE |
+ glsFboUtil.FormatFlags.RENDERBUFFER_VALID |
+ glsFboUtil.FormatFlags.TEXTURE_VALID
+ ),
+ glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3ColorRenderables)
+ ], [
+ (
+ glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.DEPTH_RENDERABLE |
+ glsFboUtil.FormatFlags.RENDERBUFFER_VALID |
+ glsFboUtil.FormatFlags.TEXTURE_VALID
+ ),
+ glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3DepthRenderables)
+ ], [
+ (
+ glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.STENCIL_RENDERABLE |
+ glsFboUtil.FormatFlags.RENDERBUFFER_VALID
+ ),
+ glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3StencilRboRenderables)
+ ], [
+ (
+ glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.STENCIL_RENDERABLE |
+ glsFboUtil.FormatFlags.RENDERBUFFER_VALID |
+ glsFboUtil.FormatFlags.TEXTURE_VALID
+ ),
+ glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3StencilRenderables)
+ ],
+
+ // These are not color-renderable in vanilla ES3, but we need to mark them
+ // as valid for textures, since EXT_color_buffer_(half_)float brings in
+ // color-renderability and only renderbuffer-validity.
+ [
+ glsFboUtil.FormatFlags.TEXTURE_VALID,
+ glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3TextureFloatFormats)
+ ]
+ ];
+
+ // gl.EXT_color_buffer_float
+ es3fFboCompletenessTests.s_extColorBufferFloatFormats = [
+ gl.RGBA32F, gl.RGBA16F, gl.R11F_G11F_B10F, gl.RG32F, gl.RG16F, gl.R32F, gl.R16F
+ ];
+
+ // gl.OES_texture_stencil8
+ es3fFboCompletenessTests.s_extOESTextureStencil8 = [
+ gl.STENCIL_INDEX8
+ ];
+
+ es3fFboCompletenessTests.s_es3ExtFormats = [{
+ extensions: 'gl.EXT_color_buffer_float',
+ flags: glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.COLOR_RENDERABLE |
+ glsFboUtil.FormatFlags.RENDERBUFFER_VALID,
+ formats: new glsFboUtil.Range(es3fFboCompletenessTests.s_extColorBufferFloatFormats)
+ }, {
+ extensions: 'gl.OES_texture_stencil8',
+ flags: glsFboUtil.FormatFlags.REQUIRED_RENDERABLE |
+ glsFboUtil.FormatFlags.STENCIL_RENDERABLE |
+ glsFboUtil.FormatFlags.TEXTURE_VALID,
+ formats: new glsFboUtil.Range(es3fFboCompletenessTests.s_extOESTextureStencil8)
+ }
+ ];
+
+ glsFboCompletenessTests.initGlDependents(gl);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsFboUtil.Checker}
+ */
+ es3fFboCompletenessTests.ES3Checker = function() {
+ glsFboUtil.Checker.call(this, gl);
+ /** @type {number} */ this.m_numSamples = -1; // GLsizei
+ /** @type {number} */ this.m_depthStencilImage = 0; // GLuint
+ /** @type {number} */ this.m_depthStencilType = gl.NONE;
+ };
+ es3fFboCompletenessTests.ES3Checker.prototype = Object.create(glsFboUtil.Checker.prototype);
+ es3fFboCompletenessTests.ES3Checker.prototype.constructor = es3fFboCompletenessTests.ES3Checker;
+
+ es3fFboCompletenessTests.ES3Checker.prototype.check = function(attPoint, att, image) {
+
+ var imgSamples = glsFboUtil.imageNumSamples(image);
+
+ if (this.m_numSamples == -1) {
+ this.m_numSamples = imgSamples;
+ } else {
+ // GLES3: "The value of RENDERBUFFER_SAMPLES is the same for all attached
+ // renderbuffers and, if the attached images are a mix of renderbuffers
+ // and textures, the value of RENDERBUFFER_SAMPLES is zero."
+ //
+ // On creating a renderbuffer: "If _samples_ is zero, then
+ // RENDERBUFFER_SAMPLES is set to zero. Otherwise [...] the resulting
+ // value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or
+ // equal to _samples_ and no more than the next larger sample count
+ // supported by the implementation."
+
+ // Either all attachments are zero-sample renderbuffers and/or
+ // textures, or none of them are.
+ this.addFBOStatus(
+ (this.m_numSamples == 0) == (imgSamples == 0),
+ gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
+ );
+
+ // If the attachments requested a different number of samples, the
+ // implementation is allowed to report this as incomplete. However, it
+ // is also possible that despite the different requests, the
+ // implementation allocated the same number of samples to both. Hence
+ // reporting the framebuffer as complete is also legal.
+ this.addPotentialFBOStatus(
+ this.m_numSamples == imgSamples,
+ gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
+ );
+ }
+
+ // "Depth and stencil attachments, if present, are the same image."
+ if (attPoint == gl.DEPTH_ATTACHMENT || attPoint == gl.STENCIL_ATTACHMENT) {
+ if (this.m_depthStencilImage == 0) {
+ this.m_depthStencilImage = att.imageName;
+ this.m_depthStencilType = glsFboUtil.attachmentType(att);
+
+ } else {
+ this.addFBOStatus(
+ this.m_depthStencilImage == att.imageName && this.m_depthStencilType == glsFboUtil.attachmentType(att),
+ gl.FRAMEBUFFER_UNSUPPORTED
+ );
+ }
+ }
+
+ };
+
+ /**
+ * @typedef {{textureKind: number, numLayers: number, attachmentLayer: number}}
+ */
+ es3fFboCompletenessTests.numLayersParamsT;
+
+ /**
+ * @param {number} textureKind
+ * @param {number} numLayers
+ * @param {number} attachmentLayer
+ * @return {es3fFboCompletenessTests.numLayersParamsT}
+ */
+ es3fFboCompletenessTests.numLayersParams = function(textureKind, numLayers, attachmentLayer) {
+ if (typeof(attachmentLayer) == 'undefined') {
+ textureKind = 0;
+ numLayers = 0;
+ attachmentLayer = 0;
+ }
+ return {
+ textureKind: textureKind, //< gl.TEXTURE_3D or gl.TEXTURE_2D_ARRAY
+ numLayers: numLayers, //< Number of layers in texture
+ attachmentLayer: attachmentLayer //< Layer referenced by attachment
+ };
+ };
+
+ /**
+ * es3fFboCompletenessTests.numLayersParams.getName
+ * @param {es3fFboCompletenessTests.numLayersParamsT} params
+ * @return {string}
+ */
+ es3fFboCompletenessTests.numLayersParams.getName = function(params) {
+ return (
+ (params.textureKind == gl.TEXTURE_3D ? '3d' : '2darr') + '_' +
+ params.numLayers + '_' +
+ params.attachmentLayer
+ );
+ };
+ /**
+ * es3fFboCompletenessTests.numLayersParams.getDescription
+ * @param {es3fFboCompletenessTests.numLayersParamsT} params
+ * @return {string}
+ */
+ es3fFboCompletenessTests.numLayersParams.getDescription = function(params) {
+ return (
+ (params.textureKind == gl.TEXTURE_3D ? '3D Texture' : '2D Array Texture') + ', ' +
+ params.numLayers + ' layers, ' +
+ 'attached layer ' + params.attachmentLayer + '.'
+ );
+ };
+
+ // string, string, glsFboCompleteness::context, params.
+ /**
+ * @constructor
+ * @extends {glsFboCompletenessTests.TestBase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {glsFboCompletenessTests.Context} ctx
+ * @param {es3fFboCompletenessTests.numLayersParamsT} params
+ */
+ es3fFboCompletenessTests.NumLayersTest = function(name, desc, ctx, params) {
+ glsFboCompletenessTests.TestBase.call(this, name, desc, params);
+ this.m_ctx = ctx;
+ };
+
+ es3fFboCompletenessTests.NumLayersTest.prototype = Object.create(glsFboCompletenessTests.TestBase.prototype);
+ es3fFboCompletenessTests.NumLayersTest.prototype.constructor = es3fFboCompletenessTests.NumLayersTest;
+
+ es3fFboCompletenessTests.NumLayersTest.prototype.build = function(builder, gl) {
+
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ var target = gl.COLOR_ATTACHMENT0;
+ var texCfg = builder.makeConfig(
+ function(kind) {
+ switch (kind) {
+ case gl.TEXTURE_3D: return glsFboUtil.Texture3D;
+ case gl.TEXTURE_2D_ARRAY: return glsFboUtil.Texture2DArray;
+ default: throw new Error('Impossible case');
+ }
+ }(this.m_params.textureKind)
+ );
+
+ texCfg.internalFormat = this.getDefaultFormat(target, gl.TEXTURE, gl);
+ texCfg.width = 64;
+ texCfg.height = 64;
+ texCfg.numLayers = this.m_params.numLayers;
+ var tex = builder.glCreateTexture(texCfg);
+
+ var att = builder.makeConfig(glsFboUtil.TextureLayerAttachment);
+ att.layer = this.m_params.attachmentLayer;
+ att.imageName = tex;
+
+ builder.glAttach(target, att);
+
+ // return tcuTestCase.IterateResult.STOP;
+ };
+//es3fFboCompletenessTests.NumLayersTest.prototype.isExecutable = function() {
+// return false;
+//};
+
+ /**
+ * @enum
+ */
+ es3fFboCompletenessTests.e_samples = {
+ NONE: -2,
+ TEXTURE: -1
+ };
+
+ /**
+ * @typedef {{numSamples: Array<number>}}
+ */
+ es3fFboCompletenessTests.numSamplesParamsT;
+
+ /**
+ * @param {number} colour
+ * @param {number} depth
+ * @param {number} stencil
+ * @return {es3fFboCompletenessTests.numSamplesParamsT}
+ */
+ es3fFboCompletenessTests.numSamplesParams = function(colour, depth, stencil) {
+ var ret = {
+ numSamples: new Array(3)
+ };
+ if (colour !== undefined) {
+ ret.numSamples[0] = colour;
+ if (depth !== undefined) {
+ ret.numSamples[1] = depth;
+ if (stencil !== undefined) {
+ ret.numSamples[2] = stencil;
+ }
+ }
+ }
+ return ret;
+ };
+
+ /**
+ * @param {es3fFboCompletenessTests.numSamplesParamsT} params
+ * @return {string}
+ */
+ es3fFboCompletenessTests.numSamplesParams.getName = function(params) {
+ var out = '';
+
+ var first = true;
+ for (var i = 0; i < 3; ++i) {
+ if (first)
+ first = false;
+ else
+ out += '_';
+
+ switch (params.numSamples[i]) {
+ case es3fFboCompletenessTests.e_samples.NONE: out += 'none'; break;
+ case es3fFboCompletenessTests.e_samples.TEXTURE: out += 'tex'; break;
+ default: out += 'rbo'; break;
+ }
+ }
+ return out;
+ };
+ /**
+ * @param {es3fFboCompletenessTests.numSamplesParamsT} params
+ * @return {string}
+ */
+ es3fFboCompletenessTests.numSamplesParams.getDescription = function(params) {
+ var out = '';
+ var names = ['color', 'depth', 'stencil'];
+ var first = true;
+
+ for (var i = 0; i < 3; ++i) {
+ if (first)
+ first = false;
+ else
+ out += ', ';
+
+ if (params.numSamples[i] == es3fFboCompletenessTests.e_samples.TEXTURE) {
+ out += 'texture ' + names[i] + ' attachment';
+ } else {
+ out += params.numSamples[i] + '-sample renderbuffer ' + names[i] + ' attachment';
+ }
+ }
+ return out;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsFboCompletenessTests.TestBase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {glsFboCompletenessTests.Context} ctx
+ * @param {es3fFboCompletenessTests.numSamplesParamsT} params
+ */
+ es3fFboCompletenessTests.NumSamplesTest = function(name, desc, ctx, params) {
+ glsFboCompletenessTests.TestBase.call(this, name, desc, params);
+ this.m_ctx = ctx;
+ };
+ es3fFboCompletenessTests.NumSamplesTest.prototype = Object.create(glsFboCompletenessTests.TestBase.prototype);
+ es3fFboCompletenessTests.NumSamplesTest.prototype.constructor = es3fFboCompletenessTests.NumSamplesTest;
+
+ es3fFboCompletenessTests.NumSamplesTest.prototype.build = function(builder, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ var s_targets = [
+ gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.DEPTH_ATTACHMENT
+ ];
+ // Non-integer formats for each attachment type.
+ // \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so
+ // we can pick one smartly or maybe try several.
+ var s_formats = [
+ gl.RGBA8, gl.RGB565, gl.DEPTH_COMPONENT24
+ ];
+
+ var l = s_targets.length;
+ if (this.m_params.numSamples.length != l)
+ throw new Error('Wrong number of params.');
+
+ for (var i = 0; i < l; ++i) {
+ var target = s_targets[i];
+ var fmt = new glsFboUtil.ImageFormat(s_formats[i], gl.NONE);
+
+ var ns = this.m_params.numSamples[i];
+ if (ns == es3fFboCompletenessTests.e_samples.NONE)
+ continue;
+ if (ns == es3fFboCompletenessTests.e_samples.TEXTURE) {
+ this.attachTargetToNew(target, gl.TEXTURE, fmt, 64, 64, builder, gl);
+ } else {
+ var rboCfg = builder.makeConfig(glsFboUtil.Renderbuffer);
+ rboCfg.internalFormat = fmt;
+ rboCfg.width = rboCfg.height = 64;
+ rboCfg.numSamples = ns;
+
+ var rbo = builder.glCreateRbo(rboCfg);
+ // Implementations do not necessarily support sample sizes greater than 1.
+ if (builder.getError() == gl.INVALID_OPERATION) {
+ throw new Error('Unsupported number of samples.');
+ }
+ var att = builder.makeConfig(glsFboUtil.RenderbufferAttachment);
+ att.imageName = rbo;
+ builder.glAttach(target, att);
+ }
+ }
+
+ return true;
+ };
+
+ es3fFboCompletenessTests.init = function() {
+
+ //(testCtx, renderCtx, factory) {
+ var fboCtx = new glsFboCompletenessTests.Context(null, gl, function() {
+ return new es3fFboCompletenessTests.ES3Checker();
+ });
+
+ fboCtx.addFormats(glsFboUtil.rangeArray(es3fFboCompletenessTests.s_es3Formats));
+
+ /** @const @type {tcuTestCase.DeqpTest} */
+ var testGroup = tcuTestCase.runner.testCases;
+
+ testGroup.addChild(fboCtx.createRenderableTests(gl));
+ testGroup.addChild(fboCtx.createAttachmentTests(gl));
+ testGroup.addChild(fboCtx.createSizeTests(gl));
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var layerTests = tcuTestCase.newTest('layer', 'Tests for layer attachments');
+
+ /** @static */
+ var s_layersParams = [
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_2D_ARRAY, 1, 0),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_2D_ARRAY, 1, 3),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_2D_ARRAY, 4, 3),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_2D_ARRAY, 4, 15),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_3D, 1, 0),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_3D, 1, 15),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_3D, 4, 15),
+ es3fFboCompletenessTests.numLayersParams(gl.TEXTURE_3D, 64, 15)
+ ];
+
+ for (var i = 0; i < s_layersParams.length; ++i) {
+ var name = 'name';
+ var desc = 'desc';
+ layerTests.addChild(new es3fFboCompletenessTests.NumLayersTest(
+ es3fFboCompletenessTests.numLayersParams.getName(s_layersParams[i]),
+ es3fFboCompletenessTests.numLayersParams.getDescription(s_layersParams[i]),
+ fboCtx, s_layersParams[i]
+ ));
+ }
+ testGroup.addChild(layerTests);
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var sampleTests = tcuTestCase.newTest('sample', 'Tests for multisample attachments');
+ // some short hand
+ var samples = es3fFboCompletenessTests.e_samples;
+ // sample tests
+ /** @static */
+ var s_samplesParams = [
+ es3fFboCompletenessTests.numSamplesParams(0, samples.NONE, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(1, samples.NONE, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(2, samples.NONE, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(0, samples.TEXTURE, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(1, samples.TEXTURE, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(2, samples.TEXTURE, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(2, 1, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(2, 2, samples.NONE),
+ es3fFboCompletenessTests.numSamplesParams(0, 0, samples.TEXTURE),
+ es3fFboCompletenessTests.numSamplesParams(1, 2, 0),
+ es3fFboCompletenessTests.numSamplesParams(2, 2, 0),
+ es3fFboCompletenessTests.numSamplesParams(1, 1, 1),
+ es3fFboCompletenessTests.numSamplesParams(1, 2, 4)
+ ];
+
+ for (var i = 0; i < s_samplesParams.length; ++i) {
+ var name = 'name';
+ var desc = 'desc';
+ sampleTests.addChild(new es3fFboCompletenessTests.NumSamplesTest(
+ es3fFboCompletenessTests.numSamplesParams.getName(s_samplesParams[i]),
+ es3fFboCompletenessTests.numSamplesParams.getDescription(s_samplesParams[i]),
+ fboCtx, s_samplesParams[i]
+ ));
+ }
+ testGroup.addChild(sampleTests);
+
+ };
+
+ es3fFboCompletenessTests.run = function() {
+ var testName = 'completeness';
+ var testDescription = 'Completeness tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fFboCompletenessTests.init();
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboDepthbufferTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboDepthbufferTests.js
new file mode 100644
index 0000000000..c662a3764e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboDepthbufferTests.js
@@ -0,0 +1,385 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboDepthbufferTests');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+var es3fFboDepthbufferTests = functional.gles3.es3fFboDepthbufferTests;
+var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuSurface = framework.common.tcuSurface;
+var tcuTexture = framework.common.tcuTexture;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuRGBA = framework.common.tcuRGBA;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var rrUtil = framework.referencerenderer.rrUtil;
+var deMath = framework.delibs.debase.deMath;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ */
+es3fFboDepthbufferTests.BasicFboDepthCase = function(name, desc, format, width, height) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_format = format;
+ this.m_width = width;
+ this.m_height = height;
+};
+
+setParentClass(es3fFboDepthbufferTests.BasicFboDepthCase, es3fFboTestCase.FboTestCase);
+
+es3fFboDepthbufferTests.BasicFboDepthCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+es3fFboDepthbufferTests.BasicFboDepthCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFormat = gl.RGBA8;
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], gluShaderUtil.DataType.FLOAT_VEC4);
+ var texShaderID = ctx.createProgram(texShader);
+ var gradShaderID = ctx.createProgram(gradShader);
+ var clearDepth = 1;
+
+ // Setup shaders
+ gradShader.setGradient(ctx, gradShaderID, [0, 0, 0, 0], [1, 1, 1, 1]);
+ texShader.setUniforms(ctx, texShaderID);
+
+ // Setup FBO
+
+ var fbo = ctx.createFramebuffer();
+ var colorRbo = ctx.createRenderbuffer();
+ var depthRbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_width, this.m_height);
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_width, this.m_height);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_width, this.m_height);
+
+ // Clear depth to 1
+ ctx.clearBufferfv(gl.DEPTH, 0, [clearDepth]);
+
+ // Render gradient with depth = [-1..1]
+ ctx.enable(gl.DEPTH_TEST);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ // Render grid pattern with depth = 0
+ var format = gl.RGBA;
+ var dataType = gl.UNSIGNED_BYTE;
+ var texW = 128;
+ var texH = 128;
+ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, [0.2, 0.7, 0.1, 1.0], [0.7, 0.1, 0.5, 0.8]);
+
+ var gridTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, gridTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ rrUtil.drawQuad(ctx, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ this.checkError();
+
+ // Read results.
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_width, this.m_height,
+ gluTextureUtil.mapGLInternalFormat(colorFormat),
+ [1, 1, 1, 1], [0, 0, 0, 0]);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ */
+es3fFboDepthbufferTests.DepthWriteClampCase = function(name, desc, format, width, height) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_format = format;
+ this.m_width = width;
+ this.m_height = height;
+};
+
+setParentClass(es3fFboDepthbufferTests.DepthWriteClampCase, es3fFboTestCase.FboTestCase);
+
+es3fFboDepthbufferTests.DepthWriteClampCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+es3fFboDepthbufferTests.DepthWriteClampCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFormat = gl.RGBA8;
+ var transferFmt = gluTextureUtil.getTransferFormat(gluTextureUtil.mapGLInternalFormat(this.m_format));
+ /** @type {es3fFboTestUtil.DepthGradientShader} */
+ var gradShader = new es3fFboTestUtil.DepthGradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var gradShaderID = ctx.createProgram(gradShader);
+ var clearDepth = 1;
+ var red = [1, 0, 0, 1];
+ var green = [0, 1, 0, 1];
+
+ // Setup FBO
+
+ var fbo = ctx.createFramebuffer();
+ var colorRbo = ctx.createRenderbuffer();
+ var depthTexture = ctx.createTexture();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_width, this.m_height);
+
+ ctx.bindTexture(gl.TEXTURE_2D, depthTexture);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_format, this.m_width, this.m_height, 0, transferFmt.format, transferFmt.dataType, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture, 0);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_width, this.m_height);
+
+ // Clear depth to 1
+ ctx.clearBufferfv(gl.DEPTH, 0, [clearDepth]);
+
+ // Render gradient with depth = [-1..1]
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.depthFunc(gl.ALWAYS);
+ gradShader.setUniforms(ctx, gradShaderID, -1, 2, green);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+ ctx.depthMask(false);
+
+ // Test if any fragment has greater depth than 1; there should be none
+ ctx.depthFunc(gl.LESS); // (1 < depth) ?
+ gradShader.setUniforms(ctx, gradShaderID, 1, 1, red);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ // Test if any fragment has smaller depth than 0; there should be none
+ ctx.depthFunc(gl.GREATER); // (0 > depth) ?
+ gradShader.setUniforms(ctx, gradShaderID, 0, 0, red);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ // Read results.
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_width, this.m_height,
+ gluTextureUtil.mapGLInternalFormat(colorFormat),
+ [1, 1, 1, 1], [0, 0, 0, 0]);
+
+ ctx.depthMask(true);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ */
+es3fFboDepthbufferTests.DepthTestClampCase = function(name, desc, format, width, height) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_format = format;
+ this.m_width = width;
+ this.m_height = height;
+};
+
+setParentClass(es3fFboDepthbufferTests.DepthTestClampCase, es3fFboTestCase.FboTestCase);
+
+es3fFboDepthbufferTests.DepthTestClampCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+es3fFboDepthbufferTests.DepthTestClampCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFormat = gl.RGBA8;
+ var transferFmt = gluTextureUtil.getTransferFormat(gluTextureUtil.mapGLInternalFormat(this.m_format));
+ /** @type {es3fFboTestUtil.DepthGradientShader} */
+ var gradShader = new es3fFboTestUtil.DepthGradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var gradShaderID = ctx.createProgram(gradShader);
+ var clearDepth = 1;
+ var yellow = [1, 1, 0, 1];
+ var green = [0, 1, 0, 1];
+
+ // Setup FBO
+
+ var fbo = ctx.createFramebuffer();
+ var colorRbo = ctx.createRenderbuffer();
+ var depthTexture = ctx.createTexture();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_width, this.m_height);
+
+ ctx.bindTexture(gl.TEXTURE_2D, depthTexture);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_format, this.m_width, this.m_height, 0, transferFmt.format, transferFmt.dataType, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture, 0);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_width, this.m_height);
+
+ // Clear depth to 1
+ ctx.clearBufferfv(gl.DEPTH, 0, [clearDepth]);
+
+ // Test values used in depth test are clamped
+
+ // Render green quad, depth gradient = [-1..2]
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.depthFunc(gl.ALWAYS);
+
+ gradShader.setUniforms(ctx, gradShaderID, -1, 2, green);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ // Render yellow quad, depth gradient = [-0.5..3]. Gradients have equal values only outside [0, 1] range due to clamping
+ ctx.depthFunc(gl.EQUAL);
+
+ gradShader.setUniforms(ctx, gradShaderID, -0.5, 3, yellow);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ // Read results.
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_width, this.m_height,
+ gluTextureUtil.mapGLInternalFormat(colorFormat),
+ [1, 1, 1, 1], [0, 0, 0, 0]);
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fFboDepthbufferTests.FboDepthbufferTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'depth', 'depth tests');
+};
+
+setParentClass(es3fFboDepthbufferTests.FboDepthbufferTests, tcuTestCase.DeqpTest);
+
+es3fFboDepthbufferTests.FboDepthbufferTests.prototype.init = function() {
+ var depthFormats = [
+ gl.DEPTH_COMPONENT32F,
+ gl.DEPTH_COMPONENT24,
+ gl.DEPTH_COMPONENT16,
+ gl.DEPTH32F_STENCIL8,
+ gl.DEPTH24_STENCIL8
+ ];
+
+ // .basic
+ var basicGroup = tcuTestCase.newTest('basic', 'Basic depth tests');
+ this.addChild(basicGroup);
+
+ for (var ndx = 0; ndx < depthFormats.length; ndx++)
+ basicGroup.addChild(new es3fFboDepthbufferTests.BasicFboDepthCase(es3fFboTestUtil.getFormatName(depthFormats[ndx]), '', depthFormats[ndx], 119, 127));
+
+ // .depth_write_clamp
+ var depthClampGroup = tcuTestCase.newTest('depth_write_clamp', 'Depth write clamping tests');
+ this.addChild(depthClampGroup);
+
+ for (var ndx = 0; ndx < depthFormats.length; ndx++)
+ depthClampGroup.addChild(new es3fFboDepthbufferTests.DepthWriteClampCase(es3fFboTestUtil.getFormatName(depthFormats[ndx]), '', depthFormats[ndx], 119, 127));
+
+ // .depth_test_clamp
+ var depthTestGroup = tcuTestCase.newTest('depth_test_clamp', 'Depth test value clamping tests');
+ this.addChild(depthTestGroup);
+
+ for (var ndx = 0; ndx < depthFormats.length; ndx++)
+ depthTestGroup.addChild(new es3fFboDepthbufferTests.DepthTestClampCase(es3fFboTestUtil.getFormatName(depthFormats[ndx]), '', depthFormats[ndx], 119, 127));
+
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fFboDepthbufferTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fFboDepthbufferTests.FboDepthbufferTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFboDepthbufferTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboInvalidateTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboInvalidateTests.js
new file mode 100644
index 0000000000..3a90cceccd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboInvalidateTests.js
@@ -0,0 +1,1471 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboInvalidateTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+var es3fFboInvalidateTests = functional.gles3.es3fFboInvalidateTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var rrUtil = framework.referencerenderer.rrUtil;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var deMath = framework.delibs.debase.deMath;
+var tcuRGBA = framework.common.tcuRGBA;
+var tcuImageCompare = framework.common.tcuImageCompare;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+var getDefaultFBDiscardAttachments = function(discardBufferBits) {
+ var attachments = [];
+
+ if (discardBufferBits & gl.COLOR_BUFFER_BIT)
+ attachments.push(gl.COLOR);
+
+ if (discardBufferBits & gl.DEPTH_BUFFER_BIT)
+ attachments.push(gl.DEPTH);
+
+ if (discardBufferBits & gl.STENCIL_BUFFER_BIT)
+ attachments.push(gl.STENCIL);
+
+ return attachments;
+};
+
+var getFBODiscardAttachments = function(discardBufferBits) {
+ var attachments = [];
+
+ if (discardBufferBits & gl.COLOR_BUFFER_BIT)
+ attachments.push(gl.COLOR_ATTACHMENT0);
+
+ // \note DEPTH_STENCIL_ATTACHMENT is allowed when discarding FBO, but not with default FB
+ if ((discardBufferBits & (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) == (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT))
+ attachments.push(gl.DEPTH_STENCIL_ATTACHMENT);
+ else if (discardBufferBits & gl.DEPTH_BUFFER_BIT)
+ attachments.push(gl.DEPTH_ATTACHMENT);
+ else if (discardBufferBits & gl.STENCIL_BUFFER_BIT)
+ attachments.push(gl.STENCIL_ATTACHMENT);
+
+ return attachments;
+};
+
+var getCompatibleColorFormat = function() {
+ var redBits = gl.getParameter(gl.RED_BITS);
+ var greenBits = gl.getParameter(gl.GREEN_BITS);
+ var blueBits = gl.getParameter(gl.BLUE_BITS);
+ var alphaBits = gl.getParameter(gl.ALPHA_BITS);
+ switch ('' + redBits + greenBits + blueBits + alphaBits) {
+ case '8888' : return gl.RGBA8;
+ case '8880' : return gl.RGB8;
+ default:
+ throw new Error('Unexpected bit depth');
+ }
+};
+
+var getCompatibleDepthStencilFormat = function() {
+ var depthBits = /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS));
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+ var hasDepth = depthBits > 0;
+ var hasStencil = stencilBits > 0;
+
+ if (!hasDepth || !hasStencil || (stencilBits != 8))
+ return gl.NONE;
+
+ if (depthBits == 32)
+ return gl.DEPTH32F_STENCIL8;
+ else if (depthBits == 24)
+ return gl.DEPTH24_STENCIL8;
+ else
+ return gl.NONE;
+};
+
+var hasAttachment = function(attachments, attachment) {
+ return attachments.indexOf(attachment) >= 0;
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} buffers
+ * @param {number=} target
+ */
+es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase = function(name, desc, buffers, target) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_buffers = buffers;
+ this.m_fboTarget = target || gl.FRAMEBUFFER;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var attachments = getDefaultFBDiscardAttachments(this.m_buffers);
+
+ var shader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var program = ctx.createProgram(shader);
+ shader.setColor(ctx, program, [1, 0, 0, 1]);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ rrUtil.drawQuad(ctx, program, [-1, -1, -1], [1, 1, 1]);
+ ctx.invalidateFramebuffer(this.m_fboTarget, attachments);
+
+ if ((this.m_buffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Color was not preserved - fill with green.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ shader.setColor(ctx, program, [0, 1, 0, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, 0], [1, 1, 0]);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ }
+
+ if ((this.m_buffers & gl.DEPTH_BUFFER_BIT) != 0) {
+ // Depth was not preserved.
+ ctx.depthFunc(gl.ALWAYS);
+ }
+
+ if ((this.m_buffers & gl.STENCIL_BUFFER_BIT) == 0) {
+ // Stencil was preserved.
+ ctx.stencilFunc(gl.EQUAL, 1, 0xff);
+ }
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ shader.setColor(ctx, program, [0, 0, 1, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, 0], [1, 1, 0]);
+ dst.readViewport(ctx);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} buffers
+ */
+es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase = function(name, desc, buffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_buffers = buffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var attachments = getDefaultFBDiscardAttachments(this.m_buffers);
+
+ var shader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var program = ctx.createProgram(shader);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], gluShaderUtil.DataType.FLOAT_VEC4);
+
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texShaderID = ctx.createProgram(texShader);
+ var gradShaderID = ctx.createProgram(gradShader);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ // Create fbo.
+ var fbo = ctx.createFramebuffer();
+ var tex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, tex);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, this.getWidth(), this.getHeight(), 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ ctx.bindTexture(gl.TEXTURE_2D, null);
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ shader.setColor(ctx, program, [1, 0, 0, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, -1], [1, 1, 1]);
+
+ ctx.invalidateFramebuffer(gl.FRAMEBUFFER, attachments);
+
+ // Switch to fbo and render gradient into it.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ gradShader.setGradient(ctx, gradShaderID, [0, 0, 0, 0], [1, 1, 1, 1]);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, 0], [1, 1, 0]);
+ // Restore default fbo.
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ if ((this.m_buffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Color was not preserved - fill with green.
+ shader.setColor(ctx, program, [0, 1, 0, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, 0], [1, 1, 0]);
+ }
+
+ if ((this.m_buffers & gl.DEPTH_BUFFER_BIT) != 0) {
+ // Depth was not preserved.
+ ctx.depthFunc(gl.ALWAYS);
+ }
+
+ if ((this.m_buffers & gl.STENCIL_BUFFER_BIT) == 0) {
+ // Stencil was preserved.
+ ctx.stencilFunc(gl.EQUAL, 1, 0xff);
+ }
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+ ctx.bindTexture(gl.TEXTURE_2D, tex);
+
+ texShader.setUniforms(ctx, texShaderID);
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ dst.readViewport(ctx);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} buffers
+ * @param {number=} target
+ */
+es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase = function(name, desc, buffers, target) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_buffers = buffers;
+ this.m_fboTarget = target || gl.FRAMEBUFFER;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var invalidateX = this.getWidth() / 4;
+ var invalidateY = this.getHeight() / 4;
+ var invalidateW = this.getWidth() / 2;
+ var invalidateH = this.getHeight() / 2;
+ var attachments = getDefaultFBDiscardAttachments(this.m_buffers);
+
+ var shader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var program = ctx.createProgram(shader);
+ shader.setColor(ctx, program, [1, 0, 0, 1]);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ rrUtil.drawQuad(ctx, program, [-1, -1, -1], [1, 1, 1]);
+ ctx.invalidateSubFramebuffer(this.m_fboTarget, attachments, invalidateX, invalidateY, invalidateW, invalidateH);
+
+ // Clear invalidated buffers.
+ ctx.clearColor(0, 1, 0, 1);
+ ctx.clearStencil(1);
+ ctx.scissor(invalidateX, invalidateY, invalidateW, invalidateH);
+ ctx.enable(gl.SCISSOR_TEST);
+ ctx.clear(this.m_buffers);
+ ctx.disable(gl.SCISSOR_TEST);
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ shader.setColor(ctx, program, [0, 0, 1, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, 0], [1, 1, 0]);
+ dst.readViewport(ctx);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} buffers
+ */
+es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase = function(name, desc, buffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_buffers = buffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var attachments = getDefaultFBDiscardAttachments(this.m_buffers);
+ var invalidateX = this.getWidth() / 4;
+ var invalidateY = this.getHeight() / 4;
+ var invalidateW = this.getWidth() / 2;
+ var invalidateH = this.getHeight() / 2;
+
+ var shader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var program = ctx.createProgram(shader);
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], gluShaderUtil.DataType.FLOAT_VEC4);
+
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var texShaderID = ctx.createProgram(texShader);
+ var gradShaderID = ctx.createProgram(gradShader);
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ // Create fbo.
+ var fbo = ctx.createFramebuffer();
+ var tex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, tex);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, this.getWidth(), this.getHeight(), 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ ctx.bindTexture(gl.TEXTURE_2D, null);
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ shader.setColor(ctx, program, [1, 0, 0, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, -1], [1, 1, 1]);
+
+ ctx.invalidateSubFramebuffer(gl.FRAMEBUFFER, attachments, invalidateX, invalidateY, invalidateW, invalidateH);
+
+ // Switch to fbo and render gradient into it.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ gradShader.setGradient(ctx, gradShaderID, [0, 0, 0, 0], [1, 1, 1, 1]);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, 0], [1, 1, 0]);
+ // Restore default fbo.
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ if ((this.m_buffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Color was not preserved - fill with green.
+ shader.setColor(ctx, program, [0, 1, 0, 1]);
+ rrUtil.drawQuad(ctx, program, [-1, -1, 0], [1, 1, 0]);
+ }
+
+ // Clear invalidated buffers.
+ ctx.clearColor(0, 1, 0, 1);
+ ctx.clearStencil(1);
+ ctx.scissor(invalidateX, invalidateY, invalidateW, invalidateH);
+ ctx.enable(gl.SCISSOR_TEST);
+ ctx.clear(this.m_buffers);
+ ctx.disable(gl.SCISSOR_TEST);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+ ctx.bindTexture(gl.TEXTURE_2D, tex);
+
+ texShader.setUniforms(ctx, texShaderID);
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ dst.readViewport(ctx);
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+ ctx.disable(gl.BLEND);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} colorFmt
+ * @param {number} depthStencilFmt
+ * @param {number} invalidateBuffers
+ */
+es3fFboInvalidateTests.InvalidateFboRenderCase = function(name, desc, colorFmt, depthStencilFmt, invalidateBuffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_colorFmt = colorFmt;
+ this.m_depthStencilFmt = depthStencilFmt;
+ this.m_invalidateBuffers = invalidateBuffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateFboRenderCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateFboRenderCase.prototype.preCheck = function() {
+ if (this.m_colorFmt != gl.NONE) this.checkFormatSupport(this.m_colorFmt);
+ if (this.m_depthStencilFmt != gl.NONE) this.checkFormatSupport(this.m_depthStencilFmt);
+ return true; // No exception thrown
+};
+
+es3fFboInvalidateTests.InvalidateFboRenderCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFmt = gluTextureUtil.mapGLInternalFormat(this.m_colorFmt);
+ var depthStencilFmt = this.m_depthStencilFmt != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFmt) : new tcuTexture.TextureFormat(null, null);
+ var colorFmtInfo = tcuTextureUtil.getTextureFormatInfo(colorFmt);
+ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var cBias = colorFmtInfo.valueMin;
+ var cScale = deMath.subtract(colorFmtInfo.valueMax, colorFmtInfo.valueMin);
+ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var attachments = getFBODiscardAttachments(this.m_invalidateBuffers);
+ var flatShaderID = ctx.createProgram(flatShader);
+
+ // Create fbo.
+ var colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_colorFmt, this.getWidth(), this.getHeight());
+
+ if (this.m_depthStencilFmt != gl.NONE) {
+ var depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_depthStencilFmt, this.getWidth(), this.getHeight());
+ }
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+
+ if (depth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ if (stencil)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([1, 0, 0, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, -1], [1, 1, 1]);
+
+ ctx.invalidateFramebuffer(gl.FRAMEBUFFER, attachments);
+
+ if ((this.m_invalidateBuffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Color was not preserved - fill with green.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([0, 1, 0, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ }
+
+ if ((this.m_invalidateBuffers & gl.DEPTH_BUFFER_BIT) != 0) {
+ // Depth was not preserved.
+ ctx.depthFunc(gl.ALWAYS);
+ }
+
+ if ((this.m_invalidateBuffers & gl.STENCIL_BUFFER_BIT) == 0) {
+ // Stencil was preserved.
+ ctx.stencilFunc(gl.EQUAL, 1, 0xff);
+ }
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([0, 0, 1, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ es3fFboTestUtil.readPixels(ctx, dst, 0, 0, this.getWidth(), this.getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} colorFmt
+ * @param {number} depthStencilFmt
+ * @param {number} invalidateBuffers
+ */
+es3fFboInvalidateTests.InvalidateFboUnbindReadCase = function(name, desc, colorFmt, depthStencilFmt, invalidateBuffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_colorFmt = colorFmt;
+ this.m_depthStencilFmt = depthStencilFmt;
+ this.m_invalidateBuffers = invalidateBuffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateFboUnbindReadCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateFboUnbindReadCase.prototype.preCheck = function() {
+ if (this.m_colorFmt != gl.NONE) this.checkFormatSupport(this.m_colorFmt);
+ if (this.m_depthStencilFmt != gl.NONE) this.checkFormatSupport(this.m_depthStencilFmt);
+ return true; // No exception thrown
+};
+
+es3fFboInvalidateTests.InvalidateFboUnbindReadCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFmt = gluTextureUtil.mapGLInternalFormat(this.m_colorFmt);
+ var depthStencilFmt = this.m_depthStencilFmt != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFmt) : new tcuTexture.TextureFormat(null, null);
+ var colorFmtInfo = tcuTextureUtil.getTextureFormatInfo(colorFmt);
+ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var attachments = getFBODiscardAttachments(this.m_invalidateBuffers);
+ // Create fbo.
+ var transferFmt = gluTextureUtil.getTransferFormat(colorFmt);
+ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var gradShaderID = ctx.createProgram(gradShader);
+
+ var colorTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, colorTex);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_colorFmt, this.getWidth(), this.getHeight(), 0, transferFmt.format, transferFmt.dataType, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ if (this.m_depthStencilFmt != gl.NONE) {
+ transferFmt = gluTextureUtil.getTransferFormat(depthStencilFmt);
+
+ var depthStencilTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, depthStencilTex);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_depthStencilFmt, this.getWidth(), this.getHeight(), 0, transferFmt.format, transferFmt.dataType, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ }
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
+
+ if (depth)
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthStencilTex, 0);
+
+ if (stencil)
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, depthStencilTex, 0);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ gradShader.setGradient(ctx, gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, -1], [1, 1, 1]);
+
+ ctx.invalidateFramebuffer(gl.FRAMEBUFFER, attachments);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ if ((this.m_invalidateBuffers & gl.DEPTH_BUFFER_BIT) != 0) {
+ // Render color.
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluTextureUtil.getSampler2DType(colorFmt)], gluShaderUtil.DataType.FLOAT_VEC4);
+ var texShaderID = ctx.createProgram(texShader);
+
+ texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
+ texShader.setUniforms(ctx, texShaderID);
+
+ ctx.bindTexture(gl.TEXTURE_2D, colorTex);
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+ } else {
+ // Render depth.
+ texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluTextureUtil.getSampler2DType(depthStencilFmt)], gluShaderUtil.DataType.FLOAT_VEC4);
+ texShaderID = ctx.createProgram(texShader);
+
+ texShader.setUniforms(ctx, texShaderID);
+
+ ctx.bindTexture(gl.TEXTURE_2D, depthStencilTex);
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+ }
+
+ dst.readViewport(ctx);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} numSamples
+ * @param {number} invalidateBuffers
+ */
+es3fFboInvalidateTests.InvalidateFboUnbindBlitCase = function(name, desc, numSamples, invalidateBuffers) {
+// \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its
+// behing-the-scenes viewport position randomization, because with glBlitFramebuffer,
+// source and destination rectangles must match when multisampling.
+ es3fFboTestCase.FboTestCase.call(this, name, desc, numSamples > 0);
+ this.m_numSamples = numSamples;
+ this.m_colorFmt = getCompatibleColorFormat();
+ this.m_depthStencilFmt = getCompatibleDepthStencilFormat();
+ this.m_invalidateBuffers = invalidateBuffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateFboUnbindBlitCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateFboUnbindBlitCase.prototype.preCheck = function() {
+ if (this.m_colorFmt != gl.NONE) this.checkFormatSupport(this.m_colorFmt);
+ if (this.m_depthStencilFmt != gl.NONE) this.checkFormatSupport(this.m_depthStencilFmt);
+ return true; // No exception thrown
+};
+
+es3fFboInvalidateTests.InvalidateFboUnbindBlitCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var quadSizePixels = [this.m_numSamples == 0 ? this.getWidth() : Math.min(128, this.getWidth()),
+ this.m_numSamples == 0 ? this.getHeight() : Math.min(128, this.getHeight())];
+ var quadNDCLeftBottomXY = [-1, -1];
+ var quadNDCSize = [2 * quadSizePixels[0] / this.getWidth(), 2 * quadSizePixels[1] / this.getHeight()];
+ var quadNDCRightTopXY = deMath.add(quadNDCLeftBottomXY, quadNDCSize);
+ var depthStencilFmt = this.m_depthStencilFmt != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFmt) : new tcuTexture.TextureFormat(null, null);
+ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var attachments = getFBODiscardAttachments(this.m_invalidateBuffers);
+ var flatShaderID = ctx.createProgram(flatShader);
+
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Create fbo.
+ var colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, this.m_colorFmt, quadSizePixels[0], quadSizePixels[1]);
+
+ if (this.m_depthStencilFmt != gl.NONE) {
+ var depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, this.m_depthStencilFmt, quadSizePixels[0], quadSizePixels[1]);
+ }
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+
+ if (depth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ if (stencil)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ flatShader.setColor(ctx, flatShaderID, [1, 0, 0, 1]);
+ rrUtil.drawQuad(ctx, flatShaderID,
+ [quadNDCLeftBottomXY[0], quadNDCLeftBottomXY[1], -1],
+ [quadNDCRightTopXY[0], quadNDCRightTopXY[1], 1]);
+
+ ctx.invalidateFramebuffer(gl.FRAMEBUFFER, attachments);
+
+ // Set default framebuffer as draw framebuffer and blit preserved buffers.
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ ctx.blitFramebuffer(0, 0, quadSizePixels[0], quadSizePixels[1],
+ 0, 0, quadSizePixels[0], quadSizePixels[1],
+ (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) & ~this.m_invalidateBuffers, gl.NEAREST);
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+
+ if ((this.m_invalidateBuffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Color was not preserved - fill with green.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ flatShader.setColor(ctx, flatShaderID, [0, 1, 0, 1]);
+ rrUtil.drawQuad(ctx, flatShaderID,
+ [quadNDCLeftBottomXY[0], quadNDCLeftBottomXY[1], 0],
+ [quadNDCRightTopXY[0], quadNDCRightTopXY[1], 0]);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ }
+
+ if ((this.m_invalidateBuffers & gl.DEPTH_BUFFER_BIT) != 0) {
+ // Depth was not preserved.
+ ctx.depthFunc(gl.ALWAYS);
+ }
+
+ if ((this.m_invalidateBuffers & gl.STENCIL_BUFFER_BIT) == 0) {
+ // Stencil was preserved.
+ ctx.stencilFunc(gl.EQUAL, 1, 0xff);
+ }
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ flatShader.setColor(ctx, flatShaderID, [0, 0, 1, 1]);
+ rrUtil.drawQuad(ctx, flatShaderID,
+ [quadNDCLeftBottomXY[0], quadNDCLeftBottomXY[1], 0],
+ [quadNDCRightTopXY[0], quadNDCRightTopXY[1], 0]);
+
+ dst.readViewport(ctx, [0, 0, quadSizePixels[0], quadSizePixels[1]]);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} colorFmt
+ * @param {number} depthStencilFmt
+ * @param {number} invalidateBuffers
+ */
+es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase = function(name, desc, colorFmt, depthStencilFmt, invalidateBuffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_colorFmt = colorFmt;
+ this.m_depthStencilFmt = depthStencilFmt;
+ this.m_invalidateBuffers = invalidateBuffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase.prototype.preCheck = function() {
+ if (this.m_colorFmt != gl.NONE) this.checkFormatSupport(this.m_colorFmt);
+ if (this.m_depthStencilFmt != gl.NONE) this.checkFormatSupport(this.m_depthStencilFmt);
+ return true; // No exception thrown
+};
+
+es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase.prototype.compare = function(reference, result) {
+ var threshold = tcuRGBA.max(es3fFboTestUtil.getFormatThreshold(this.m_colorFmt), new tcuRGBA.RGBA([12, 12, 12, 12]));
+ return tcuImageCompare.bilinearCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), threshold);
+};
+
+es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFmt = gluTextureUtil.mapGLInternalFormat(this.m_colorFmt);
+ var depthStencilFmt = this.m_depthStencilFmt != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFmt) : new tcuTexture.TextureFormat(null, null);
+ var colorFmtInfo = tcuTextureUtil.getTextureFormatInfo(colorFmt);
+ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var attachments = getFBODiscardAttachments(this.m_invalidateBuffers);
+ // Create fbo.
+ var transferFmt = gluTextureUtil.getTransferFormat(colorFmt);
+ var gradShader = new es3fFboTestUtil.GradientShader(es3fFboTestUtil.getFragmentOutputType(colorFmt));
+ var gradShaderID = ctx.createProgram(gradShader);
+ var invalidateX = 0;
+ var invalidateY = 0;
+ var invalidateW = this.getWidth() / 2;
+ var invalidateH = this.getHeight();
+ var readX = invalidateW;
+ var readY = 0;
+ var readW = this.getWidth() / 2;
+ var readH = this.getHeight();
+
+ var colorTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, colorTex);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_colorFmt, this.getWidth(), this.getHeight(), 0, transferFmt.format, transferFmt.dataType, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ if (this.m_depthStencilFmt != gl.NONE) {
+ transferFmt = gluTextureUtil.getTransferFormat(depthStencilFmt);
+
+ var depthStencilTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, depthStencilTex);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_depthStencilFmt, this.getWidth(), this.getHeight(), 0, transferFmt.format, transferFmt.dataType, null);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ }
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
+
+ if (depth)
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthStencilTex, 0);
+
+ if (stencil)
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, depthStencilTex, 0);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ this.clearColorBuffer(colorFmt, [0.0, 0.0, 0.0, 1.0]);
+ ctx.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ gradShader.setGradient(ctx, gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, -1], [1, 1, 1]);
+
+ ctx.invalidateSubFramebuffer(gl.FRAMEBUFFER, attachments, invalidateX, invalidateY, invalidateW, invalidateH);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ ctx.clearColor(0.25, 0.5, 0.75, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Limit read area using scissor.
+ ctx.scissor(readX, readY, readW, readH);
+ ctx.enable(gl.SCISSOR_TEST);
+
+ if ((this.m_invalidateBuffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Render color.
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluTextureUtil.getSampler2DType(colorFmt)], gluShaderUtil.DataType.FLOAT_VEC4);
+ var texShaderID = ctx.createProgram(texShader);
+
+ texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
+ texShader.setUniforms(ctx, texShaderID);
+
+ ctx.bindTexture(gl.TEXTURE_2D, colorTex);
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+ } else {
+ // Render depth.
+ texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluTextureUtil.getSampler2DType(depthStencilFmt)], gluShaderUtil.DataType.FLOAT_VEC4);
+ texShaderID = ctx.createProgram(texShader);
+
+ texShader.setUniforms(ctx, texShaderID);
+
+ ctx.bindTexture(gl.TEXTURE_2D, depthStencilTex);
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+ }
+
+ dst.readViewport(ctx);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} colorFmt
+ * @param {number} depthStencilFmt
+ * @param {number} invalidateBuffers
+ */
+es3fFboInvalidateTests.InvalidateSubFboRenderCase = function(name, desc, colorFmt, depthStencilFmt, invalidateBuffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_colorFmt = colorFmt;
+ this.m_depthStencilFmt = depthStencilFmt;
+ this.m_invalidateBuffers = invalidateBuffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateSubFboRenderCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateSubFboRenderCase.prototype.preCheck = function() {
+ if (this.m_colorFmt != gl.NONE) this.checkFormatSupport(this.m_colorFmt);
+ if (this.m_depthStencilFmt != gl.NONE) this.checkFormatSupport(this.m_depthStencilFmt);
+ return true; // No exception thrown
+};
+
+es3fFboInvalidateTests.InvalidateSubFboRenderCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFmt = gluTextureUtil.mapGLInternalFormat(this.m_colorFmt);
+ var depthStencilFmt = this.m_depthStencilFmt != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFmt) : new tcuTexture.TextureFormat(null, null);
+ var colorFmtInfo = tcuTextureUtil.getTextureFormatInfo(colorFmt);
+ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var cBias = colorFmtInfo.valueMin;
+ var cScale = deMath.subtract(colorFmtInfo.valueMax, colorFmtInfo.valueMin);
+ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var attachments = getFBODiscardAttachments(this.m_invalidateBuffers);
+ var flatShaderID = ctx.createProgram(flatShader);
+ var invalidateX = this.getWidth() / 4;
+ var invalidateY = this.getHeight() / 4;
+ var invalidateW = this.getWidth() / 2;
+ var invalidateH = this.getHeight() / 2;
+
+ // Create fbo.
+ var colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_colorFmt, this.getWidth(), this.getHeight());
+
+ if (this.m_depthStencilFmt != gl.NONE) {
+ var depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_depthStencilFmt, this.getWidth(), this.getHeight());
+ }
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+
+ if (depth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ if (stencil)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.clearBufferfv(gl.COLOR, 0, deMath.add(deMath.multiply([0, 0, 0, 1], cScale), cBias));
+ ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1, 0);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([1, 0, 0, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, -1], [1, 1, 1]);
+
+ ctx.invalidateSubFramebuffer(gl.FRAMEBUFFER, attachments, invalidateX, invalidateY, invalidateW, invalidateH);
+
+ // Clear invalidated buffers.
+ ctx.scissor(invalidateX, invalidateY, invalidateW, invalidateH);
+ ctx.enable(gl.SCISSOR_TEST);
+
+ if (this.m_invalidateBuffers & gl.COLOR_BUFFER_BIT)
+ ctx.clearBufferfv(gl.COLOR, 0, deMath.add(deMath.multiply([0, 1, 0, 1], cScale), cBias));
+
+ ctx.clear(this.m_invalidateBuffers & ~gl.COLOR_BUFFER_BIT);
+ ctx.disable(gl.SCISSOR_TEST);
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([0, 0, 1, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ es3fFboTestUtil.readPixels(ctx, dst, 0, 0, this.getWidth(), this.getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} numSamples
+ * @param {number} invalidateBuffers
+ */
+es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase = function(name, desc, numSamples, invalidateBuffers) {
+// \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its
+// behing-the-scenes viewport position randomization, because with glBlitFramebuffer,
+// source and destination rectangles must match when multisampling.
+ es3fFboTestCase.FboTestCase.call(this, name, desc, numSamples > 0);
+ this.m_numSamples = numSamples;
+ this.m_colorFmt = getCompatibleColorFormat();
+ this.m_depthStencilFmt = getCompatibleDepthStencilFormat();
+ this.m_invalidateBuffers = invalidateBuffers;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase.prototype.preCheck = function() {
+ if (this.m_colorFmt != gl.NONE) this.checkFormatSupport(this.m_colorFmt);
+ if (this.m_depthStencilFmt != gl.NONE) this.checkFormatSupport(this.m_depthStencilFmt);
+ return true; // No exception thrown
+};
+
+es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var quadSizePixels = [this.m_numSamples == 0 ? this.getWidth() : Math.min(128, this.getWidth()),
+ this.m_numSamples == 0 ? this.getHeight() : Math.min(128, this.getHeight())];
+ var quadNDCLeftBottomXY = [-1, -1];
+ var quadNDCSize = [2 * quadSizePixels[0] / this.getWidth(), 2 * quadSizePixels[1] / this.getHeight()];
+ var quadNDCRightTopXY = deMath.add(quadNDCLeftBottomXY, quadNDCSize);
+ var depthStencilFmt = this.m_depthStencilFmt != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFmt) : new tcuTexture.TextureFormat(null, null);
+ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var attachments = getFBODiscardAttachments(this.m_invalidateBuffers);
+ var flatShaderID = ctx.createProgram(flatShader);
+ var invalidateX = 0;
+ var invalidateY = 0;
+ var invalidateW = quadSizePixels[0] / 2;
+ var invalidateH = quadSizePixels[1];
+ var blitX0 = invalidateW;
+ var blitY0 = 0;
+ var blitX1 = blitX0 + quadSizePixels[0] / 2;
+ var blitY1 = blitY0 + quadSizePixels[1];
+
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Create fbo.
+ var colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, this.m_colorFmt, quadSizePixels[0], quadSizePixels[1]);
+
+ if (this.m_depthStencilFmt != gl.NONE) {
+ var depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, this.m_depthStencilFmt, quadSizePixels[0], quadSizePixels[1]);
+ }
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+
+ if (depth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ if (stencil)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ flatShader.setColor(ctx, flatShaderID, [1, 0, 0, 1]);
+ rrUtil.drawQuad(ctx, flatShaderID,
+ [quadNDCLeftBottomXY[0], quadNDCLeftBottomXY[1], -1],
+ [quadNDCRightTopXY[0], quadNDCRightTopXY[1], 1]);
+
+ ctx.invalidateSubFramebuffer(gl.FRAMEBUFFER, attachments, invalidateX, invalidateY, invalidateW, invalidateH);
+
+ // Set default framebuffer as draw framebuffer and blit preserved buffers.
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ ctx.blitFramebuffer(blitX0, blitY0, blitX1, blitY1, blitX0, blitY0, blitX1, blitY1,
+ (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) & ~this.m_invalidateBuffers, gl.NEAREST);
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+
+ if ((this.m_invalidateBuffers & gl.COLOR_BUFFER_BIT) != 0) {
+ // Color was not preserved - fill with green.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ flatShader.setColor(ctx, flatShaderID, [0, 1, 0, 1]);
+ rrUtil.drawQuad(ctx, flatShaderID,
+ [quadNDCLeftBottomXY[0], quadNDCLeftBottomXY[1], 0],
+ [quadNDCRightTopXY[0], quadNDCRightTopXY[1], 0]);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ }
+
+ if ((this.m_invalidateBuffers & gl.DEPTH_BUFFER_BIT) != 0) {
+ // Depth was not preserved.
+ ctx.depthFunc(gl.ALWAYS);
+ }
+
+ if ((this.m_invalidateBuffers & gl.STENCIL_BUFFER_BIT) == 0) {
+ // Stencil was preserved.
+ ctx.stencilFunc(gl.EQUAL, 1, 0xff);
+ }
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ flatShader.setColor(ctx, flatShaderID, [0, 0, 1, 1]);
+ rrUtil.drawQuad(ctx, flatShaderID,
+ [quadNDCLeftBottomXY[0], quadNDCLeftBottomXY[1], 0],
+ [quadNDCRightTopXY[0], quadNDCRightTopXY[1], 0]);
+
+ dst.readViewport(ctx, [0, 0, quadSizePixels[0], quadSizePixels[1]]);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} boundTarget
+ * @param {number} invalidateTarget
+ * @param {Array<number>} invalidateAttachments
+ */
+es3fFboInvalidateTests.InvalidateFboTargetCase = function(name, desc, boundTarget, invalidateTarget, invalidateAttachments) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ this.m_boundTarget = boundTarget;
+ this.m_invalidateTarget = invalidateTarget;
+ this.m_invalidateAttachments = invalidateAttachments;
+};
+
+setParentClass(es3fFboInvalidateTests.InvalidateFboTargetCase, es3fFboTestCase.FboTestCase);
+
+es3fFboInvalidateTests.InvalidateFboTargetCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ var colorFormat = gl.RGBA8;
+ var depthStencilFormat = gl.DEPTH24_STENCIL8;
+ var colorFmt = gluTextureUtil.mapGLInternalFormat(colorFormat);
+ var colorFmtInfo = tcuTextureUtil.getTextureFormatInfo(colorFmt);
+ var cBias = colorFmtInfo.valueMin;
+ var cScale = deMath.subtract(colorFmtInfo.valueMax, colorFmtInfo.valueMin);
+ var isDiscarded = (this.m_boundTarget == gl.FRAMEBUFFER) ||
+ (this.m_invalidateTarget == gl.FRAMEBUFFER && this.m_boundTarget == gl.DRAW_FRAMEBUFFER) ||
+ (this.m_invalidateTarget == this.m_boundTarget);
+ var isColorDiscarded = isDiscarded && hasAttachment(this.m_invalidateAttachments, gl.COLOR_ATTACHMENT0);
+ var isDepthDiscarded = isDiscarded && (hasAttachment(this.m_invalidateAttachments, gl.DEPTH_ATTACHMENT) || hasAttachment(this.m_invalidateAttachments, gl.DEPTH_STENCIL_ATTACHMENT));
+ var isStencilDiscarded = isDiscarded && (hasAttachment(this.m_invalidateAttachments, gl.STENCIL_ATTACHMENT) || hasAttachment(this.m_invalidateAttachments, gl.DEPTH_STENCIL_ATTACHMENT));
+
+ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var flatShaderID = ctx.createProgram(flatShader);
+
+ // Create fbo.
+ var colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.getWidth(), this.getHeight());
+
+ var depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, this.getWidth(), this.getHeight());
+
+ var fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.clearColor(0, 0, 0, 1);
+ ctx.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([1, 0, 0, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, -1], [1, 1, 1]);
+
+ // Bound FBO to test target and default to other
+ if (this.m_boundTarget != gl.FRAMEBUFFER) {
+ // Dummy fbo is used as complemeting target (read when discarding draw for example).
+ // \note Framework takes care of deleting objects at the end of test case.
+ var dummyTarget = this.m_boundTarget == gl.DRAW_FRAMEBUFFER ? gl.READ_FRAMEBUFFER : gl.DRAW_FRAMEBUFFER;
+
+ var dummyColorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, dummyColorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 64, 64);
+ var dummyFbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(dummyTarget, dummyFbo);
+ ctx.framebufferRenderbuffer(dummyTarget, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dummyColorRbo);
+
+ ctx.bindFramebuffer(this.m_boundTarget, fbo);
+ }
+
+ ctx.invalidateFramebuffer(this.m_invalidateTarget, this.m_invalidateAttachments);
+
+ if (this.m_boundTarget != gl.FRAMEBUFFER)
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ if (isColorDiscarded) {
+ // Color was not preserved - fill with green.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([0, 1, 0, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ }
+
+ if (isDepthDiscarded) {
+ // Depth was not preserved.
+ ctx.depthFunc(gl.ALWAYS);
+ }
+
+ if (!isStencilDiscarded) {
+ // Stencil was preserved.
+ ctx.stencilFunc(gl.EQUAL, 1, 0xff);
+ }
+
+ ctx.enable(gl.BLEND);
+ ctx.blendFunc(gl.ONE, gl.ONE);
+ ctx.blendEquation(gl.FUNC_ADD);
+
+ flatShader.setColor(ctx, flatShaderID, deMath.add(deMath.multiply([0, 0, 1, 1], cScale), cBias));
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ es3fFboTestUtil.readPixels(ctx, dst, 0, 0, this.getWidth(), this.getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fFboInvalidateTests.FboInvalidateTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'invalidate', 'Framebuffer invalidate tests');
+};
+
+es3fFboInvalidateTests.FboInvalidateTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fFboInvalidateTests.FboInvalidateTests.prototype.constructor = es3fFboInvalidateTests.FboInvalidateTests;
+
+es3fFboInvalidateTests.FboInvalidateTests.prototype.init = function() {
+ var defaultFbGroup = new tcuTestCase.DeqpTest('default', 'Default framebuffer invalidate tests');
+ this.addChild(defaultFbGroup);
+
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('render_none', 'Invalidating no framebuffers (ref)', 0));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('render_color', 'Rendering after invalidating colorbuffer', gl.COLOR_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('render_depth', 'Rendering after invalidating depthbuffer', gl.DEPTH_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('render_stencil', 'Rendering after invalidating stencilbuffer', gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('render_depth_stencil', 'Rendering after invalidating depth- and stencilbuffers', gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('render_all', 'Rendering after invalidating all buffers', gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase('bind_color', 'Binding fbo after invalidating colorbuffer', gl.COLOR_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase('bind_depth', 'Binding fbo after invalidating depthbuffer', gl.DEPTH_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase('bind_stencil', 'Binding fbo after invalidating stencilbuffer', gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase('bind_depth_stencil', 'Binding fbo after invalidating depth- and stencilbuffers', gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferBindCase('bind_all', 'Binding fbo after invalidating all buffers', gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase('sub_render_color', 'Rendering after invalidating colorbuffer', gl.COLOR_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase('sub_render_depth', 'Rendering after invalidating depthbuffer', gl.DEPTH_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase('sub_render_stencil', 'Rendering after invalidating stencilbuffer', gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase('sub_render_depth_stencil', 'Rendering after invalidating depth- and stencilbuffers', gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferRenderCase('sub_render_all', 'Rendering after invalidating all buffers', gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase('sub_bind_color', 'Binding fbo after invalidating colorbuffer', gl.COLOR_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase('sub_bind_depth', 'Binding fbo after invalidating depthbuffer', gl.DEPTH_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase('sub_bind_stencil', 'Binding fbo after invalidating stencilbuffer', gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase('sub_bind_depth_stencil', 'Binding fbo after invalidating depth- and stencilbuffers', gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultSubFramebufferBindCase('sub_bind_all', 'Binding fbo after invalidating all buffers', gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('draw_framebuffer_color', 'Invalidating gl.COLOR in gl.DRAW_FRAMEBUFFER', gl.COLOR_BUFFER_BIT, gl.DRAW_FRAMEBUFFER));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('draw_framebuffer_all', 'Invalidating all in gl.DRAW_FRAMEBUFFER', gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, gl.DRAW_FRAMEBUFFER));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('read_framebuffer_color', 'Invalidating gl.COLOR in gl.READ_FRAMEBUFFER', gl.COLOR_BUFFER_BIT, gl.READ_FRAMEBUFFER));
+ defaultFbGroup.addChild(new es3fFboInvalidateTests.InvalidateDefaultFramebufferRenderCase('read_framebuffer_all', 'Invalidating all in gl.READ_FRAMEBUFFER', gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, gl.READ_FRAMEBUFFER));
+
+ // invalidate.whole.
+ var wholeFboGroup = new tcuTestCase.DeqpTest('whole', 'Invalidating whole framebuffer object');
+ this.addChild(wholeFboGroup);
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboRenderCase('render_none', '', gl.RGBA8, gl.DEPTH24_STENCIL8, 0));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboRenderCase('render_color', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboRenderCase('render_depth', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboRenderCase('render_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboRenderCase('render_depth_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboRenderCase('render_all', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindReadCase('unbind_read_color', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindReadCase('unbind_read_depth', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindReadCase('unbind_read_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindReadCase('unbind_read_depth_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindReadCase('unbind_read_color_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+
+ if (getCompatibleDepthStencilFormat() !== gl.NONE) {
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_color', '', 0, gl.COLOR_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_depth', '', 0, gl.DEPTH_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_stencil', '', 0, gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_depth_stencil', '', 0, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_msaa_color', '', 4, gl.COLOR_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_msaa_depth', '', 4, gl.DEPTH_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_msaa_stencil', '', 4, gl.STENCIL_BUFFER_BIT));
+ wholeFboGroup.addChild(new es3fFboInvalidateTests.InvalidateFboUnbindBlitCase('unbind_blit_msaa_depth_stencil', '', 4, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ }
+
+ // invalidate.sub.
+ var subFboGroup = new tcuTestCase.DeqpTest('sub', 'Invalidating subsection of framebuffer object');
+ this.addChild(subFboGroup);
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase('render_none', '', gl.RGBA8, gl.DEPTH24_STENCIL8, 0));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase('render_color', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase('render_depth', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase('render_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase('render_depth_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase('render_all', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase('unbind_read_color', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase('unbind_read_depth', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase('unbind_read_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase('unbind_read_depth_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase('unbind_read_color_stencil', '', gl.RGBA8, gl.DEPTH24_STENCIL8, gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+
+ if (getCompatibleDepthStencilFormat() !== gl.NONE) {
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_color', '', 0, gl.COLOR_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_depth', '', 0, gl.DEPTH_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_stencil', '', 0, gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_depth_stencil', '', 0, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_msaa_color', '', 4, gl.COLOR_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_msaa_depth', '', 4, gl.DEPTH_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_msaa_stencil', '', 4, gl.STENCIL_BUFFER_BIT));
+ subFboGroup.addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindBlitCase('unbind_blit_msaa_depth_stencil', '', 4, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ }
+ // invalidate.format.
+ var numFormatSubGroups = 3;
+ var formatGroup = [];
+ for (var ii = 0; ii < numFormatSubGroups; ++ii) {
+ formatGroup[ii] = new tcuTestCase.DeqpTest('format', 'Invalidating framebuffers with selected formats');
+ this.addChild(formatGroup[ii]);
+ }
+ // Color buffer formats.
+ var colorFormats = [
+ // RGBA formats
+ gl.RGBA32I,
+ gl.RGBA32UI,
+ gl.RGBA16I,
+ gl.RGBA16UI,
+ gl.RGBA8,
+ gl.RGBA8I,
+ gl.RGBA8UI,
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGB10_A2UI,
+ gl.RGBA4,
+ gl.RGB5_A1,
+
+ // RGB formats
+ gl.RGB8,
+ gl.RGB565,
+
+ // RG formats
+ gl.RG32I,
+ gl.RG32UI,
+ gl.RG16I,
+ gl.RG16UI,
+ gl.RG8,
+ gl.RG8I,
+ gl.RG8UI,
+
+ // R formats
+ gl.R32I,
+ gl.R32UI,
+ gl.R16I,
+ gl.R16UI,
+ gl.R8,
+ gl.R8I,
+ gl.R8UI,
+
+ // gl.EXT_color_buffer_float
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F
+ ];
+
+ // Depth/stencilbuffer formats.
+ var depthStencilFormats = [
+ gl.DEPTH_COMPONENT32F,
+ gl.DEPTH_COMPONENT24,
+ gl.DEPTH_COMPONENT16,
+ gl.DEPTH32F_STENCIL8,
+ gl.DEPTH24_STENCIL8,
+ gl.STENCIL_INDEX8
+ ];
+
+ // Colorbuffer tests use invalidate, unbind, read test.
+ for (var ndx = 0; ndx < colorFormats.length; ndx++)
+ formatGroup[ndx % numFormatSubGroups].addChild(new es3fFboInvalidateTests.InvalidateSubFboUnbindReadCase(es3fFboTestUtil.getFormatName(colorFormats[ndx]), '', colorFormats[ndx], gl.NONE, gl.COLOR_BUFFER_BIT));
+
+ // Depth/stencilbuffer tests use invalidate, render test.
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++)
+ formatGroup[ndx % numFormatSubGroups].addChild(new es3fFboInvalidateTests.InvalidateSubFboRenderCase(es3fFboTestUtil.getFormatName(depthStencilFormats[ndx]), '', gl.RGBA8, depthStencilFormats[ndx], gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+
+ // invalidate.target
+ var targetGroup = new tcuTestCase.DeqpTest('target', 'Invalidate target');
+ this.addChild(targetGroup);
+
+ var s_targetCases = [
+ ['framebuffer_framebuffer', gl.FRAMEBUFFER, gl.FRAMEBUFFER],
+ ['framebuffer_read_framebuffer', gl.FRAMEBUFFER, gl.READ_FRAMEBUFFER],
+ ['framebuffer_draw_framebuffer', gl.FRAMEBUFFER, gl.DRAW_FRAMEBUFFER],
+ ['read_framebuffer_framebuffer', gl.READ_FRAMEBUFFER, gl.FRAMEBUFFER],
+ ['read_framebuffer_read_framebuffer', gl.READ_FRAMEBUFFER, gl.READ_FRAMEBUFFER],
+ ['read_framebuffer_draw_framebuffer', gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER],
+ ['draw_framebuffer_framebuffer', gl.DRAW_FRAMEBUFFER, gl.FRAMEBUFFER],
+ ['draw_framebuffer_read_framebuffer', gl.DRAW_FRAMEBUFFER, gl.READ_FRAMEBUFFER],
+ ['draw_framebuffer_draw_framebuffer', gl.DRAW_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER]
+ ];
+
+ var colorAttachment = [gl.COLOR_ATTACHMENT0];
+ var depthStencilAttachment = [gl.DEPTH_STENCIL_ATTACHMENT];
+ var allAttachments = [gl.COLOR_ATTACHMENT0, gl.DEPTH_ATTACHMENT, gl.STENCIL_ATTACHMENT];
+
+ for (var caseNdx = 0; caseNdx < s_targetCases.length; caseNdx++) {
+ var baseName = s_targetCases[caseNdx][0];
+ var invalidateT = s_targetCases[caseNdx][1];
+ var boundT = s_targetCases[caseNdx][1];
+
+ targetGroup.addChild(new es3fFboInvalidateTests.InvalidateFboTargetCase(baseName + '_color', '', boundT, invalidateT, colorAttachment));
+ targetGroup.addChild(new es3fFboInvalidateTests.InvalidateFboTargetCase(baseName + '_depth_stencil', '', boundT, invalidateT, depthStencilAttachment));
+ targetGroup.addChild(new es3fFboInvalidateTests.InvalidateFboTargetCase(baseName + '_all', '', boundT, invalidateT, allAttachments));
+ }
+
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fFboInvalidateTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fFboInvalidateTests.FboInvalidateTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFboInvalidateTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboMultisampleTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboMultisampleTests.js
new file mode 100644
index 0000000000..261da00734
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboMultisampleTests.js
@@ -0,0 +1,377 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboMultisampleTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+
+var es3fFboMultisampleTests = functional.gles3.es3fFboMultisampleTests;
+var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuSurface = framework.common.tcuSurface;
+var tcuRGBA = framework.common.tcuRGBA;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var deRandom = framework.delibs.debase.deRandom;
+var deMath = framework.delibs.debase.deMath;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var rrUtil = framework.referencerenderer.rrUtil;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+ /**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} colorFormat
+ * @param {number} depthStencilFormat
+ * @param {Array<number>} size
+ * @param {number} numSamples
+ */
+ es3fFboMultisampleTests.BasicFboMultisampleCase = function(name, desc, colorFormat, depthStencilFormat, size, numSamples) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @type {number} */ this.m_colorFormat = colorFormat;
+ /** @type {number} */ this.m_depthStencilFormat = depthStencilFormat;
+ /** @type {Array<number>} */ this.m_size = size;
+ /** @type {number} */ this.m_numSamples = numSamples;
+ };
+
+ es3fFboMultisampleTests.BasicFboMultisampleCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFboMultisampleTests.BasicFboMultisampleCase.prototype.constructor = es3fFboMultisampleTests.BasicFboMultisampleCase;
+
+ es3fFboMultisampleTests.BasicFboMultisampleCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_colorFormat);
+ if (!this.checkSampleCount(this.m_colorFormat, this.m_numSamples))
+ return false;
+
+ if (this.m_depthStencilFormat != gl.NONE) {
+ this.checkFormatSupport(this.m_depthStencilFormat);
+ if (!this.checkSampleCount(this.m_depthStencilFormat, this.m_numSamples))
+ return false;
+ }
+ return true; // No exception thrown
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboMultisampleTests.BasicFboMultisampleCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ /** @type {tcuTexture.TextureFormat} */ var colorFmt = gluTextureUtil.mapGLInternalFormat(this.m_colorFormat);
+ /** @type {tcuTexture.TextureFormat} */ var depthStencilFmt = this.m_depthStencilFormat != gl.NONE ? gluTextureUtil.mapGLInternalFormat(this.m_depthStencilFormat) : new tcuTexture.TextureFormat(null, null);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var colorFmtInfo = tcuTextureUtil.getTextureFormatInfo(colorFmt);
+ /** @type {boolean} */ var depth = depthStencilFmt.order == tcuTexture.ChannelOrder.D || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ /** @type {boolean} */ var stencil = depthStencilFmt.order == tcuTexture.ChannelOrder.S || depthStencilFmt.order == tcuTexture.ChannelOrder.DS;
+ /** @type {es3fFboTestUtil.GradientShader} */ var gradShader = new es3fFboTestUtil.GradientShader(es3fFboTestUtil.getFragmentOutputType(colorFmt));
+ /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader(es3fFboTestUtil.getFragmentOutputType(colorFmt));
+ var gradShaderID = this.getCurrentContext().createProgram(gradShader);
+ var flatShaderID = this.getCurrentContext().createProgram(flatShader);
+ var msaaFbo = null;
+ var resolveFbo = null;
+ var msaaColorRbo = null;
+ var resolveColorRbo = null;
+ var msaaDepthStencilRbo = null;
+ var resolveDepthStencilRbo = null;
+
+ // Create framebuffers.
+ msaaColorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, msaaColorRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, this.m_colorFormat, this.m_size[0], this.m_size[1]);
+
+ if (depth || stencil) {
+ msaaDepthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, msaaDepthStencilRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, this.m_depthStencilFormat, this.m_size[0], this.m_size[1]);
+ }
+
+ msaaFbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, msaaFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msaaColorRbo);
+ if (depth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, msaaDepthStencilRbo);
+ if (stencil)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, msaaDepthStencilRbo);
+
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ resolveColorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, resolveColorRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, 0, this.m_colorFormat, this.m_size[0], this.m_size[1]);
+
+ if (depth || stencil) {
+ resolveDepthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, resolveDepthStencilRbo);
+ ctx.renderbufferStorageMultisample(gl.RENDERBUFFER, 0, this.m_depthStencilFormat, this.m_size[0], this.m_size[1]);
+ }
+
+ resolveFbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resolveColorRbo);
+ if (depth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, resolveDepthStencilRbo);
+ if (stencil)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, resolveDepthStencilRbo);
+
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, msaaFbo);
+ ctx.viewport(0, 0, this.m_size[0], this.m_size[1]);
+
+ // Clear depth and stencil buffers.
+ ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ // Fill MSAA fbo with gradient, depth = [-1..1]
+ ctx.enable(gl.DEPTH_TEST);
+ gradShader.setGradient(this.getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
+
+ rrUtil.drawQuad(this.getCurrentContext(), gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ // Render random-colored quads.
+ /** @const {number} */ var numQuads = 8;
+
+ // The choice of random seed affects the correctness of the tests,
+ // because there are some boundary conditions which aren't handled
+ // correctly even in the C++ dEQP tests.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(7);
+
+ ctx.depthFunc(gl.ALWAYS);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilFunc(gl.ALWAYS, 0, 0xff);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
+
+ for (var ndx = 0; ndx < numQuads; ndx++) {
+ /** @type {number} */ var r = rnd.getFloat();
+ /** @type {number} */ var g = rnd.getFloat();
+ /** @type {number} */ var b = rnd.getFloat();
+ /** @type {number} */ var a = rnd.getFloat();
+ /** @type {number} */ var x0 = rnd.getFloat(-1.0, 1.0);
+ /** @type {number} */ var y0 = rnd.getFloat(-1.0, 1.0);
+ /** @type {number} */ var z0 = rnd.getFloat(-1.0, 1.0);
+ /** @type {number} */ var x1 = rnd.getFloat(-1.0, 1.0);
+ /** @type {number} */ var y1 = rnd.getFloat(-1.0, 1.0);
+ /** @type {number} */ var z1 = rnd.getFloat(-1.0, 1.0);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, deMath.add(deMath.multiply([r, g, b, a], deMath.subtract(colorFmtInfo.valueMax, colorFmtInfo.valueMin)), colorFmtInfo.valueMin));
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [x0, y0, z0], [x1, y1, z1]);
+ }
+
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.disable(gl.STENCIL_TEST);
+ this.checkError();
+
+ // Resolve using glBlitFramebuffer().
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFbo);
+ ctx.blitFramebuffer(0, 0, this.m_size[0], this.m_size[1], 0, 0, this.m_size[0], this.m_size[1], gl.COLOR_BUFFER_BIT | (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0), gl.NEAREST);
+
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, resolveFbo);
+
+ /** @type {number} */ var numSteps;
+ /** @type {number} */ var step;
+ /** @type {number} */ var d;
+ /** @type {number} */ var c;
+ /** @type {number} */ var s;
+ if (depth) {
+ // Visualize depth.
+ numSteps = 8;
+ step = 2.0 / numSteps;
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.depthFunc(gl.LESS);
+ ctx.depthMask(false);
+ ctx.colorMask(false, false, true, false);
+
+ for (var ndx = 0; ndx < numSteps; ndx++) {
+ d = -1.0 + step * ndx;
+ c = ndx / (numSteps - 1);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, deMath.add(deMath.multiply([0.0, 0.0, c, 1.0], deMath.subtract(colorFmtInfo.valueMax, colorFmtInfo.valueMin)), colorFmtInfo.valueMin));
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-1.0, -1.0, d], [1.0, 1.0, d]);
+ }
+
+ ctx.disable(gl.DEPTH_TEST);
+ }
+
+ if (stencil) {
+ // Visualize stencil.
+ numSteps = 4;
+ step = 1;
+
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ ctx.colorMask(false, true, false, false);
+
+ for (var ndx = 0; ndx < numSteps; ndx++) {
+ s = step * ndx;
+ c = ndx / (numSteps - 1);
+
+ ctx.stencilFunc(gl.EQUAL, s, 0xff);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, deMath.add(deMath.multiply([0.0, c, 0.0, 1.0], deMath.subtract(colorFmtInfo.valueMax, colorFmtInfo.valueMin)), colorFmtInfo.valueMin));
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+ }
+
+ ctx.disable(gl.STENCIL_TEST);
+ }
+
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_size[0], this.m_size[1], colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
+ };
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @return {boolean}
+ */
+ es3fFboMultisampleTests.BasicFboMultisampleCase.prototype.colorCompare = function(reference, result) {
+ /** @const {tcuRGBA.RGBA} */ var threshold = tcuRGBA.max(es3fFboTestUtil.getFormatThreshold(this.m_colorFormat), tcuRGBA.newRGBAComponents(12, 12, 12, 12));
+ return tcuImageCompare.bilinearCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), threshold, tcuImageCompare.CompareLogMode.RESULT);
+ };
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @return {boolean}
+ */
+ es3fFboMultisampleTests.BasicFboMultisampleCase.prototype.compare = function(reference, result) {
+ if (this.m_depthStencilFormat != gl.NONE)
+ return es3fFboTestCase.FboTestCase.prototype.compare(reference, result); // FboTestCase.compare
+ else
+ return this.colorCompare(reference, result);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fFboMultisampleTests.FboMultisampleTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'msaa', 'Multisample FBO tests');
+ };
+
+ es3fFboMultisampleTests.FboMultisampleTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFboMultisampleTests.FboMultisampleTests.prototype.constructor = es3fFboMultisampleTests.FboMultisampleTests;
+
+ es3fFboMultisampleTests.FboMultisampleTests.prototype.init = function() {
+ /** @const {Array<number>} */ var colorFormats = [
+ // RGBA formats
+ gl.RGBA8,
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGBA4,
+ gl.RGB5_A1,
+
+ // RGB formats
+ gl.RGB8,
+ gl.RGB565,
+
+ // RG formats
+ gl.RG8,
+
+ // R formats
+ gl.R8,
+
+ // gl.EXT_color_buffer_float
+ // Multi-sample floating-point color buffers can be optional supported, see https://www.khronos.org/registry/webgl/extensions/EXT_color_buffer_float/
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F
+ ];
+
+ /** @const {Array<number>} */ var depthStencilFormats = [
+ gl.DEPTH_COMPONENT32F,
+ gl.DEPTH_COMPONENT24,
+ gl.DEPTH_COMPONENT16,
+ gl.DEPTH32F_STENCIL8,
+ gl.DEPTH24_STENCIL8,
+ gl.STENCIL_INDEX8
+ ];
+
+ /** @const {Array<number>} */ var sampleCounts = [2, 4, 8];
+
+ for (var sampleCntNdx in sampleCounts) {
+ /** @type {number} */ var samples = sampleCounts[sampleCntNdx];
+ /** @type {tcuTestCase.DeqpTest} */
+ var sampleCountGroup = tcuTestCase.newTest(samples + '_samples', '');
+ this.addChild(sampleCountGroup);
+
+ // Color formats.
+ for (var fmtNdx in colorFormats)
+ sampleCountGroup.addChild(new es3fFboMultisampleTests.BasicFboMultisampleCase(es3fFboTestUtil.getFormatName(colorFormats[fmtNdx]), '', colorFormats[fmtNdx], gl.NONE, [119, 131], samples));
+
+ // Depth/stencil formats.
+ for (var fmtNdx in depthStencilFormats)
+ sampleCountGroup.addChild(new es3fFboMultisampleTests.BasicFboMultisampleCase(es3fFboTestUtil.getFormatName(depthStencilFormats[fmtNdx]), '', gl.RGBA8, depthStencilFormats[fmtNdx], [119, 131], samples));
+ }
+ };
+
+ es3fFboMultisampleTests.run = function(context, range) {
+ gl = context;
+ //Set up root Test
+ var state = tcuTestCase.runner;
+
+ var test = new es3fFboMultisampleTests.FboMultisampleTests();
+ var testName = test.fullName();
+ var testDescription = test.getDescription();
+
+ state.testName = testName;
+ state.setRoot(test);
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ test.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFboMultisampleTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js
new file mode 100644
index 0000000000..78229de447
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js
@@ -0,0 +1,2389 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboRenderTest');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+
+ var es3fFboRenderTest = functional.gles3.es3fFboRenderTest;
+ var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var deUtil = framework.delibs.debase.deUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var sglrReferenceContext =
+ framework.opengl.simplereference.sglrReferenceContext;
+ var rrUtil = framework.referencerenderer.rrUtil;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ /**
+ * @constructor
+ * @param {number=} buffers_
+ * @param {number=} colorType_
+ * @param {number=} colorFormat_
+ * @param {number=} depthStencilType_
+ * @param {number=} depthStencilFormat_
+ * @param {number=} width_
+ * @param {number=} height_
+ * @param {number=} samples_
+ */
+ es3fFboRenderTest.FboConfig = function(
+ buffers_, colorType_, colorFormat_, depthStencilType_,
+ depthStencilFormat_, width_, height_, samples_
+ ) {
+ // Buffer bit mask (gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|...)
+ this.buffers = buffers_ ? buffers_ : 0;
+ // gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP, gl.RENDERBUFFER
+ this.colorType = colorType_ ? colorType_ : gl.NONE;
+ // Internal format for color buffer texture or renderbuffer
+ this.colorFormat = colorFormat_ ? colorFormat_ : gl.NONE;
+ this.depthStencilType = depthStencilType_?
+ depthStencilType_ : gl.NONE;
+ this.depthStencilFormat = depthStencilFormat_ ?
+ depthStencilFormat_ : gl.NONE;
+ this.width = width_ ? width_ : 0;
+ this.height = height_ ? height_ : 0;
+ this.samples = samples_? samples_ : 0;
+ };
+
+ /**
+ * @param {number} type
+ * @return {string}
+ */
+ es3fFboRenderTest.getTypeName = function(type) {
+ switch (type) {
+ case gl.TEXTURE_2D: return 'tex2d';
+ case gl.RENDERBUFFER: return 'rbo';
+ default:
+ testFailed('Unknown type');
+ }
+ return 'Should not get to this point';
+ };
+
+ /**
+ * @return {string}
+ */
+ es3fFboRenderTest.FboConfig.prototype.getName = function() {
+ var name = '';
+
+ assertMsgOptions((this.buffers & gl.COLOR_BUFFER_BIT) != 0,
+ 'Color buffer is not specified', false, true);
+
+ name += es3fFboRenderTest.getTypeName(this.colorType) + '_' +
+ es3fFboTestUtil.getFormatName(this.colorFormat);
+
+ if (this.buffers & gl.DEPTH_BUFFER_BIT)
+ name += '_depth';
+ if (this.buffers & gl.STENCIL_BUFFER_BIT)
+ name += '_stencil';
+
+ if (this.buffers & (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT))
+ name += '_' + es3fFboRenderTest.getTypeName(this.depthStencilType) +
+ '_' + es3fFboTestUtil.getFormatName(this.depthStencilFormat);
+
+ return name;
+ };
+
+ /**
+ * @param {number} format
+ * @return {Array<string>}
+ */
+ es3fFboRenderTest.getEnablingExtensions = function(format) {
+ /** @type {Array<string>} */ var out = [];
+
+ switch (format) {
+ case gl.RGB16F:
+ assertMsgOptions(false, "Not part of the tested formats", false, true);
+ break;
+
+ case gl.RGBA16F:
+ case gl.RG16F:
+ case gl.R16F:
+ case gl.RGBA32F:
+ case gl.RGB32F:
+ case gl.R11F_G11F_B10F:
+ case gl.RG32F:
+ case gl.R32F:
+ out.push('EXT_color_buffer_float');
+
+ default:
+ break;
+ }
+
+ return out;
+ };
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {string} name
+ * @return {*}
+ */
+ es3fFboRenderTest.isExtensionSupported = function(context, name) {
+ return context.getExtension(name);
+ };
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {Array<string>} requiredExts
+ * @return {boolean}
+ */
+ es3fFboRenderTest.isAnyExtensionSupported = function(
+ context, requiredExts) {
+
+ if (!requiredExts || requiredExts.length == 0)
+ return true;
+
+ for (var extNdx = 0; extNdx < requiredExts.length; extNdx++) {
+ var extension = requiredExts[extNdx];
+
+ if (es3fFboRenderTest.isExtensionSupported(context, extension))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {Array} list
+ * @param {string} sep
+ * @return {string}
+ */
+ es3fFboRenderTest.join = function(list, sep) {
+ var out = '';
+
+ for (var elemNdx = 0; elemNdx < list.length; elemNdx++) {
+ if (elemNdx != 0)
+ out += sep;
+ out += list[elemNdx];
+ }
+
+ return out;
+ };
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {number} sizedFormat
+ */
+ es3fFboRenderTest.checkColorFormatSupport = function(context, sizedFormat) {
+ /** @type {Array<string>} */ var requiredExts =
+ es3fFboRenderTest.getEnablingExtensions(sizedFormat);
+
+ if (!es3fFboRenderTest.isAnyExtensionSupported(context, requiredExts)) {
+ var errMsg = 'Format not supported, requires ' + (
+ (requiredExts.length == 1) ? requiredExts[0] :
+ ' one of the following: ' +
+ requiredExts.join(', ')
+ );
+ checkMessage(false, errMsg);
+
+ throw new TestFailedException(errMsg);
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {es3fFboRenderTest.FboConfig} config
+ * @param {number} width
+ * @param {number} height
+ * @param {sglrReferenceContext.AnyFramebuffer=} fbo
+ * @param {sglrReferenceContext.AnyRenderbuffer=} colorBufferName
+ * @param {sglrReferenceContext.AnyRenderbuffer=} depthStencilBufferName
+ */
+ es3fFboRenderTest.Framebuffer = function(
+ context, config, width, height, fbo,
+ colorBufferName, depthStencilBufferName) {
+
+ this.m_config = config;
+ this.m_context = context;
+ this.m_framebuffer = fbo ? fbo : null;
+ this.m_colorBuffer = colorBufferName ? colorBufferName : null;
+ this.m_depthStencilBuffer = depthStencilBufferName ?
+ depthStencilBufferName : null;
+
+ // Verify that color format is supported
+ es3fFboRenderTest.checkColorFormatSupport(context, config.colorFormat);
+
+ if (!this.m_framebuffer)
+ this.m_framebuffer = context.createFramebuffer();
+ context.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+
+ if (this.m_config.buffers & (gl.COLOR_BUFFER_BIT)) {
+ switch (this.m_config.colorType) {
+ case gl.TEXTURE_2D:
+ this.m_colorBuffer = this.createTex2D(
+ /** @type {WebGLTexture} */ (colorBufferName),
+ this.m_config.colorFormat, width, height
+ );
+
+ context.framebufferTexture2D(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, this.m_colorBuffer, 0
+ );
+
+ break;
+
+ case gl.RENDERBUFFER:
+ this.m_colorBuffer = this.createRbo(
+ /** @type {WebGLRenderbuffer} */ (colorBufferName),
+ this.m_config.colorFormat, width, height
+ );
+
+ context.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.RENDERBUFFER, this.m_colorBuffer
+ );
+
+ break;
+
+ default:
+ testFailed('Unsupported type');
+ }
+ }
+
+ if (this.m_config.buffers &
+ (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) {
+
+ switch (this.m_config.depthStencilType) {
+ case gl.TEXTURE_2D:
+ this.m_depthStencilBuffer = this.createTex2D(
+ /** @type {WebGLTexture} */
+ (depthStencilBufferName),
+ this.m_config.depthStencilFormat, width, height
+ );
+ break;
+ case gl.RENDERBUFFER:
+ this.m_depthStencilBuffer = this.createRbo(
+ /** @type {WebGLRenderbuffer} */
+ (depthStencilBufferName),
+ this.m_config.depthStencilFormat, width, height
+ );
+ break;
+
+ default:
+ testFailed('Unsupported type');
+ }
+ }
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var bit = ndx ? gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT;
+ var point = ndx ? gl.STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
+
+ if ((this.m_config.buffers & bit) == 0)
+ continue; /* Not used. */
+
+ switch (this.m_config.depthStencilType) {
+ case gl.TEXTURE_2D:
+ context.framebufferTexture2D(
+ gl.FRAMEBUFFER, point, gl.TEXTURE_2D,
+ this.m_depthStencilBuffer, 0
+ );
+ break;
+ case gl.RENDERBUFFER:
+ context.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, point,
+ gl.RENDERBUFFER, this.m_depthStencilBuffer
+ );
+ break;
+ default:
+ throw new Error('Invalid depth stencil type');
+ }
+ }
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ };
+
+ /**
+ * @return {es3fFboRenderTest.FboConfig}
+ */
+ es3fFboRenderTest.Framebuffer.prototype.getConfig = function() {
+ return this.m_config;
+ };
+
+ /**
+ * @return {?sglrReferenceContext.AnyFramebuffer}
+ */
+ es3fFboRenderTest.Framebuffer.prototype.getFramebuffer = function() {
+ return this.m_framebuffer;
+ };
+
+ /**
+ * @return {?sglrReferenceContext.AnyRenderbuffer}
+ */
+ es3fFboRenderTest.Framebuffer.prototype.getColorBuffer = function() {
+ return this.m_colorBuffer;
+ };
+
+ /**
+ * @return {?sglrReferenceContext.AnyRenderbuffer}
+ */
+ es3fFboRenderTest.Framebuffer.prototype.getDepthStencilBuffer = function() {
+ return this.m_depthStencilBuffer;
+ };
+
+ /**
+ * deinit
+ */
+ es3fFboRenderTest.Framebuffer.prototype.deinit = function() {
+ this.m_context.deleteFramebuffer(
+ /** @type {WebGLFramebuffer} */ (this.m_framebuffer)
+ );
+ this.destroyBuffer(this.m_colorBuffer, this.m_config.colorType);
+ this.destroyBuffer(
+ this.m_depthStencilBuffer, this.m_config.depthStencilType
+ );
+ };
+
+ /**
+ * checkCompleteness
+ */
+ es3fFboRenderTest.Framebuffer.prototype.checkCompleteness = function() {
+ this.m_context.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+ var status = this.m_context.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.m_context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ if (status != gl.FRAMEBUFFER_COMPLETE)
+ throw new es3fFboTestUtil.FboIncompleteException(status);
+ };
+
+ /**
+ * @param {?WebGLTexture|sglrReferenceContext.TextureContainer} name
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ * @return {?WebGLTexture|sglrReferenceContext.TextureContainer}
+ */
+ es3fFboRenderTest.Framebuffer.prototype.createTex2D = function(
+ name, format, width, height) {
+
+ if (!name)
+ name = this.m_context.createTexture();
+
+ this.m_context.bindTexture(gl.TEXTURE_2D, name);
+ this.m_context.texImage2DDelegate(
+ gl.TEXTURE_2D, 0, format, width, height
+ );
+
+ if (!deMath.deIsPowerOfTwo32(width) ||
+ !deMath.deIsPowerOfTwo32(height)) {
+
+ // Set wrap mode to clamp for NPOT FBOs
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE
+ );
+ }
+
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
+ );
+
+ return name;
+ };
+
+ /**
+ * @param {?WebGLRenderbuffer|sglrReferenceContext.Renderbuffer} name
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ * @return {?WebGLRenderbuffer|sglrReferenceContext.Renderbuffer}
+ */
+ es3fFboRenderTest.Framebuffer.prototype.createRbo = function(
+ name, format, width, height) {
+
+ if (!name)
+ name = this.m_context.createRenderbuffer();
+
+ this.m_context.bindRenderbuffer(gl.RENDERBUFFER, name);
+ this.m_context.renderbufferStorage(
+ gl.RENDERBUFFER, format, width, height
+ );
+
+ return name;
+ };
+
+ /**
+ * @param {?sglrReferenceContext.AnyRenderbuffer} name
+ * @param {number} type
+ */
+ es3fFboRenderTest.Framebuffer.prototype.destroyBuffer = function(
+ name, type) {
+
+ if (type == gl.TEXTURE_2D || type == gl.TEXTURE_CUBE_MAP)
+ this.m_context.deleteTexture(/** @type {?WebGLTexture} */ (name));
+ else if (type == gl.RENDERBUFFER)
+ this.m_context.deleteRenderbuffer(
+ /** @type {?WebGLRenderbuffer} */ (name)
+ );
+ else
+ assertMsgOptions(
+ type == gl.NONE, 'Invalid buffer type', false, true
+ );
+ };
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {WebGLTexture|sglrReferenceContext.TextureContainer} name
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fFboRenderTest.createMetaballsTex2D = function(
+ context, name, format, dataType, width, height) {
+
+ /** @type {tcuTexture.TextureFormat} */ var texFormat =
+ gluTextureUtil.mapGLTransferFormat(format, dataType);
+ /** @type {tcuTexture.TextureLevel} */ var level =
+ new tcuTexture.TextureLevel(texFormat, width, height);
+
+ tcuTextureUtil.fillWithMetaballs(
+ level.getAccess(), 5, /*name ^*/ width ^ height
+ );
+
+ context.bindTexture(gl.TEXTURE_2D, name);
+ context.texImage2D(
+ gl.TEXTURE_2D, 0, format, width, height, 0, format,
+ dataType, level.getAccess().getDataPtr()
+ );
+ context.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ };
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {WebGLTexture|sglrReferenceContext.TextureContainer} name
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fFboRenderTest.createQuadsTex2D = function(
+ context, name, format, dataType, width, height) {
+
+ /** @type {tcuTexture.TextureFormat} */
+ var texFormat = gluTextureUtil.mapGLTransferFormat(format, dataType);
+ /** @type {tcuTexture.TextureLevel} */
+ var level = new tcuTexture.TextureLevel(texFormat, width, height);
+
+ tcuTextureUtil.fillWithRGBAQuads(level.getAccess());
+
+ context.bindTexture(gl.TEXTURE_2D, name);
+ context.texImage2D(
+ gl.TEXTURE_2D, 0, format, width, height, 0,
+ format, dataType, level.getAccess().getDataPtr()
+ );
+ context.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fFboRenderTest.FboConfig} config
+ */
+ es3fFboRenderTest.FboRenderCase = function(name, description, config) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_config = config;
+ };
+
+ es3fFboRenderTest.FboRenderCase.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+
+ es3fFboRenderTest.FboRenderCase.prototype.constructor =
+ es3fFboRenderTest.FboRenderCase;
+
+ /**
+ * Must be overridden
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * fboContext
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.FboRenderCase.prototype.render = function(
+ fboContext, dst) {
+ throw new Error('Must override');
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fFboRenderTest.FboRenderCase.prototype.iterate = function() {
+ var clearColor = [0.125, 0.25, 0.5, 1.0];
+ /** @type {?string} */ var failReason = "";
+
+ // Position & size for context
+ var rnd = new deRandom.deRandom();
+ deRandom.deRandom_init(rnd, deString.deStringHash(this.fullName()));
+
+ var width = Math.min(gl.canvas.width, 128);
+ var height = Math.min(gl.canvas.height, 128);
+ var xMax = gl.canvas.width - width + 1;
+ var yMax = gl.canvas.height - height + 1;
+ var x = Math.abs(deRandom.deRandom_getInt(rnd)) % xMax;
+ var y = Math.abs(deRandom.deRandom_getInt(rnd)) % yMax;
+
+ /** @type {tcuSurface.Surface} */
+ var gles3Frame = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */
+ var refFrame = new tcuSurface.Surface(width, height);
+
+ /** @type {number} */ var gles3Error = 0;
+ /** @type {number} */ var refError = 0;
+
+ // Render using GLES3
+ /**
+ * @type {sglrGLContext.GLContext|
+ * sglrReferenceContext.ReferenceContext}
+ */
+ var context;
+
+ try {
+ context = new sglrGLContext.GLContext(gl, [x, y, width, height]);
+
+ context.clearColor(
+ clearColor[0], clearColor[1], clearColor[2], clearColor[3]
+ );
+
+ context.clear(
+ gl.COLOR_BUFFER_BIT |
+ gl.DEPTH_BUFFER_BIT |
+ gl.STENCIL_BUFFER_BIT
+ );
+
+ this.render(context, gles3Frame); // Call actual render func
+ gles3Error = context.getError();
+ }
+ catch (e) {
+ if (e instanceof es3fFboTestUtil.FboIncompleteException) {
+ e.message = WebGLTestUtils.glEnumToString(gl, e.getReason());
+ if(e.getReason() == gl.FRAMEBUFFER_UNSUPPORTED) {
+ // Mark test case as unsupported
+ bufferedLogToConsole(e + ': ' + e.message);
+ testFailed('Not supported');
+ return tcuTestCase.IterateResult.STOP;
+ }
+ }
+
+ // Propagate error
+ throw e;
+ }
+
+ // Render reference image
+
+ /** @type {sglrReferenceContext.ReferenceContextBuffers} */
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(
+ new tcuPixelFormat.PixelFormat(
+ 8, 8, 8,
+ gl.getParameter(gl.ALPHA_BITS) ? 8 : 0
+ ),
+ /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS)),
+ /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS)),
+ width,
+ height
+ );
+ context = new sglrReferenceContext.ReferenceContext(
+ new sglrReferenceContext.ReferenceContextLimits(gl),
+ buffers.getColorbuffer(),
+ buffers.getDepthbuffer(),
+ buffers.getStencilbuffer()
+ );
+
+ context.clearColor(
+ clearColor[0], clearColor[1], clearColor[2], clearColor[3]
+ );
+
+ context.clear(
+ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
+ );
+
+ this.render(context, refFrame);
+ refError = context.getError();
+
+ // Compare error codes
+ var errorCodesOk = (gles3Error == refError);
+
+ if (!errorCodesOk) {
+ bufferedLogToConsole (
+ 'Error code mismatch: got ' +
+ WebGLTestUtils.glEnumToString(gl, gles3Error) + ', expected ' +
+ WebGLTestUtils.glEnumToString(gl, refError)
+ );
+ failReason = 'Got unexpected error';
+ }
+
+ // Compare images
+ var imagesOk = this.compare(refFrame, gles3Frame);
+
+ if (!imagesOk && !failReason)
+ failReason = 'Image comparison failed';
+
+ // Store test result
+ var isOk = errorCodesOk && imagesOk;
+ assertMsgOptions(isOk, failReason, true, true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @return {boolean}
+ */
+ es3fFboRenderTest.FboRenderCase.prototype.compare = function(
+ reference, result) {
+
+ var threshold = new tcuRGBA.RGBA(
+ /* TODO: tcu::max(getFormatThreshold(this.m_config.colorFormat),*/
+ [12, 12, 12, 12]
+ );
+
+ return tcuImageCompare.bilinearCompare(
+ 'ComparisonResult', 'Image comparison result',
+ reference.getAccess(), result.getAccess(),
+ threshold, tcuImageCompare.CompareLogMode.RESULT
+ );
+ };
+
+ /**
+ * deinit
+ */
+ es3fFboRenderTest.FboRenderCase.prototype.deinit = function() {
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clearDepth(1.0);
+ gl.clearStencil(0);
+
+ gl.disable(gl.STENCIL_TEST);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ };
+
+ // FboCases
+
+ /**
+ * @constructor
+ * @extends {es3fFboRenderTest.FboRenderCase}
+ * @param {es3fFboRenderTest.FboConfig} config
+ */
+ es3fFboRenderTest.StencilClearsTest = function(config) {
+ es3fFboRenderTest.FboRenderCase.call(
+ this, config.getName(), 'Stencil clears', config
+ );
+ };
+
+ es3fFboRenderTest.StencilClearsTest.prototype =
+ Object.create(es3fFboRenderTest.FboRenderCase.prototype);
+
+ es3fFboRenderTest.StencilClearsTest.prototype.constructor =
+ es3fFboRenderTest.StencilClearsTest;
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.StencilClearsTest.prototype.render = function(
+ context, dst) {
+
+ /** @type {tcuTexture.TextureFormat} */
+ var colorFormat = gluTextureUtil.mapGLInternalFormat(
+ this.m_config.colorFormat
+ );
+
+ /** @type {gluShaderUtil.DataType} */
+ var fboSamplerType = /** @type {gluShaderUtil.DataType} */ (
+ gluTextureUtil.getSampler2DType(colorFormat)
+ );
+
+ /** @type {gluShaderUtil.DataType} */
+ var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat);
+
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat);
+
+ var fboOutScale = deMath.subtract(
+ fboRangeInfo.valueMax, fboRangeInfo.valueMin
+ );
+
+ var fboOutBias = fboRangeInfo.valueMin;
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFboShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType
+ );
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texFromFboShader = new es3fFboTestUtil.Texture2DShader(
+ [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4);
+
+ /** @type {number} */ var texToFboShaderID =
+ context.createProgram(texToFboShader);
+
+ /** @type {number} */ var texFromFboShaderID =
+ context.createProgram(texFromFboShader);
+
+ /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
+ var metaballsTex = context.createTexture();
+
+ /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
+ var quadsTex = context.createTexture();
+
+ /** @type {number} */ var width = 128;
+ /** @type {number} */ var height = 128;
+
+ texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
+ texFromFboShader.setTexScaleBias(
+ 0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
+ );
+
+ es3fFboRenderTest.createQuadsTex2D(
+ context, quadsTex, gl.RGBA, gl.UNSIGNED_BYTE, width, height
+ );
+
+ es3fFboRenderTest.createMetaballsTex2D(
+ context, metaballsTex, gl.RGBA, gl.UNSIGNED_BYTE, width, height
+ );
+
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fbo = new es3fFboRenderTest.Framebuffer(
+ context, this.m_config, width, height
+ );
+ fbo.checkCompleteness();
+
+ // Bind framebuffer and clear
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
+ context.viewport(0, 0, width, height);
+ context.clearColor(0.0, 0.0, 0.0, 1.0);
+ context.clear(
+ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
+ );
+
+ // Do stencil clears
+ context.enable(gl.SCISSOR_TEST);
+ context.scissor(10, 16, 32, 120);
+ context.clearStencil(1);
+ context.clear(gl.STENCIL_BUFFER_BIT);
+ context.scissor(16, 32, 100, 64);
+ context.clearStencil(2);
+ context.clear(gl.STENCIL_BUFFER_BIT);
+ context.disable(gl.SCISSOR_TEST);
+
+ // Draw 2 textures with stecil tests
+ context.enable(gl.STENCIL_TEST);
+
+ context.bindTexture(gl.TEXTURE_2D, quadsTex);
+ context.stencilFunc(gl.EQUAL, 1, 0xff);
+
+ texToFboShader.setUniforms(context, texToFboShaderID);
+ rrUtil.drawQuad(
+ context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ context.bindTexture(gl.TEXTURE_2D, metaballsTex);
+ context.stencilFunc(gl.EQUAL, 2, 0xff);
+
+ texToFboShader.setUniforms(context, texToFboShaderID);
+ rrUtil.drawQuad(
+ context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ context.disable(gl.STENCIL_TEST);
+
+ if (fbo.getConfig().colorType == gl.TEXTURE_2D) {
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
+ context.viewport(0, 0, context.getWidth(), context.getHeight());
+
+ texFromFboShader.setUniforms(context, texFromFboShaderID);
+ rrUtil.drawQuad(
+ context, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ dst.readViewport(
+ context, [0, 0, context.getWidth(), context.getHeight()]
+ );
+ } else
+ es3fFboTestUtil.readPixels(
+ context, dst, 0, 0, width, height, colorFormat,
+ fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
+ );
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboRenderTest.FboRenderCase}
+ * @param {es3fFboRenderTest.FboConfig} config
+ */
+ es3fFboRenderTest.SharedColorbufferTest = function(config) {
+ es3fFboRenderTest.FboRenderCase.call(
+ this, config.getName(), 'Shared colorbuffer', config
+ );
+ };
+
+ es3fFboRenderTest.SharedColorbufferTest.prototype =
+ Object.create(es3fFboRenderTest.FboRenderCase.prototype);
+
+ es3fFboRenderTest.SharedColorbufferTest.prototype.constructor =
+ es3fFboRenderTest.SharedColorbufferTest;
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.SharedColorbufferTest.prototype.render = function(
+ context, dst) {
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D],
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ /** @type {es3fFboTestUtil.FlatColorShader} */
+ var flatShader = new es3fFboTestUtil.FlatColorShader(
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ /** @type {number} */
+ var texShaderID = context.createProgram(texShader);
+ /** @type {number} */
+ var flatShaderID = context.createProgram(flatShader);
+
+ /** @type {number} */ var width = 128;
+ /** @type {number} */ var height = 128;
+
+ /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
+ var quadsTex = context.createTexture();
+
+ /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
+ var metaballsTex = context.createTexture();
+
+ /** @type {boolean} */ var stencil =
+ (this.m_config.buffers & gl.STENCIL_BUFFER_BIT) != 0;
+
+ context.disable(gl.DITHER);
+
+ // Textures
+ es3fFboRenderTest.createQuadsTex2D(
+ context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
+ );
+ es3fFboRenderTest.createMetaballsTex2D(
+ context, metaballsTex, gl.RGBA, gl.UNSIGNED_BYTE, 64, 64
+ );
+
+ context.viewport(0, 0, width, height);
+
+ // Fbo A
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fboA = new es3fFboRenderTest.Framebuffer(
+ context, this.m_config, width, height
+ );
+ fboA.checkCompleteness();
+
+ // Fbo B - don't create colorbuffer
+
+ /** @type {es3fFboRenderTest.FboConfig} */
+ var cfg = /** @type {es3fFboRenderTest.FboConfig} */
+ (deUtil.clone(this.m_config));
+
+ cfg.buffers = deMath.binaryOp(
+ cfg.buffers,
+ deMath.binaryNot(gl.COLOR_BUFFER_BIT),
+ deMath.BinaryOp.AND
+ );
+ cfg.colorType = gl.NONE;
+ cfg.colorFormat = gl.NONE;
+
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fboB = new es3fFboRenderTest.Framebuffer(
+ context, cfg, width, height
+ );
+
+ // Attach color buffer from fbo A
+ context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
+ switch (this.m_config.colorType) {
+ case gl.TEXTURE_2D:
+ context.framebufferTexture2D(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, fboA.getColorBuffer(), 0
+ );
+ break;
+
+ case gl.RENDERBUFFER:
+ context.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.RENDERBUFFER, fboA.getColorBuffer()
+ );
+ break;
+
+ default:
+ throw new Error('Invalid color type');
+ }
+
+ // Clear depth and stencil in fbo B
+ context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Render quads to fbo 1, with depth 0.0
+ context.bindFramebuffer(gl.FRAMEBUFFER, fboA.getFramebuffer());
+ context.bindTexture(gl.TEXTURE_2D, quadsTex);
+ context.clearColor(0.0, 0.0, 0.0, 1.0);
+ context.clear(
+ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
+ );
+
+ if (stencil) {
+ // Stencil to 1 in fbo A
+ context.clearStencil(1);
+ context.clear(gl.STENCIL_BUFFER_BIT);
+ }
+
+ texShader.setUniforms(context, texShaderID);
+
+ context.enable(gl.DEPTH_TEST);
+ rrUtil.drawQuad(
+ context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ context.disable(gl.DEPTH_TEST);
+
+ // Blend metaballs to fbo 2
+ context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
+ context.bindTexture(gl.TEXTURE_2D, metaballsTex);
+ context.enable(gl.BLEND);
+ context.blendFuncSeparate(
+ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE
+ );
+ rrUtil.drawQuad(
+ context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ // Render small quad that is only visible if depth buffer
+ // is not shared with fbo A - or there is no depth bits
+ context.bindTexture(gl.TEXTURE_2D, quadsTex);
+ context.enable(gl.DEPTH_TEST);
+ rrUtil.drawQuad(context, texShaderID, [0.5, 0.5, 0.5], [1.0, 1.0, 0.5]);
+ context.disable(gl.DEPTH_TEST);
+
+ if (stencil) {
+ flatShader.setColor(context, flatShaderID, [0.0, 1.0, 0.0, 1.0]);
+
+ // Clear subset of stencil buffer to 1
+ context.enable(gl.SCISSOR_TEST);
+ context.scissor(10, 10, 12, 25);
+ context.clearStencil(1);
+ context.clear(gl.STENCIL_BUFFER_BIT);
+ context.disable(gl.SCISSOR_TEST);
+
+ // Render quad with stencil mask == 1
+ context.enable(gl.STENCIL_TEST);
+ context.stencilFunc(gl.EQUAL, 1, 0xff);
+ rrUtil.drawQuad(
+ context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ context.disable(gl.STENCIL_TEST);
+ }
+
+ // Get results
+ if (fboA.getConfig().colorType == gl.TEXTURE_2D) {
+ texShader.setUniforms(context, texShaderID);
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ context.bindTexture(gl.TEXTURE_2D, fboA.getColorBuffer());
+ context.viewport(0, 0, context.getWidth(), context.getHeight());
+ rrUtil.drawQuad(
+ context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ dst.readViewport(
+ context, [0, 0, context.getWidth(), context.getHeight()]
+ );
+ } else
+ es3fFboTestUtil.readPixels(
+ context, dst, 0, 0, width, height,
+ gluTextureUtil.mapGLInternalFormat(
+ fboA.getConfig().colorFormat
+ ), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]
+ );
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboRenderTest.FboRenderCase}
+ * @param {es3fFboRenderTest.FboConfig} config
+ */
+ es3fFboRenderTest.SharedColorbufferClearsTest = function(config) {
+ es3fFboRenderTest.FboRenderCase.call(
+ this, config.getName(), 'Shared colorbuffer clears', config
+ );
+ };
+
+ es3fFboRenderTest.SharedColorbufferClearsTest.prototype =
+ Object.create(es3fFboRenderTest.FboRenderCase.prototype);
+
+ es3fFboRenderTest.SharedColorbufferClearsTest.prototype.constructor =
+ es3fFboRenderTest.SharedColorbufferClearsTest;
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.SharedColorbufferClearsTest.prototype.render = function(
+ context, dst) {
+
+ /** @type {tcuTexture.TextureFormat} */
+ var colorFormat = gluTextureUtil.mapGLInternalFormat(
+ this.m_config.colorFormat
+ );
+
+ /** @type {gluShaderUtil.DataType} */
+ var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat);
+
+ var width = 128;
+ var height = 128;
+ var colorbuffer = this.m_config.colorType == gl.TEXTURE_2D?
+ context.createTexture() :
+ context.createRenderbuffer();
+
+ // Check for format support.
+ es3fFboRenderTest.checkColorFormatSupport(
+ context, this.m_config.colorFormat
+ );
+
+ // Single colorbuffer
+ if (this.m_config.colorType == gl.TEXTURE_2D) {
+ context.bindTexture(gl.TEXTURE_2D, colorbuffer);
+ context.texImage2DDelegate(
+ gl.TEXTURE_2D, 0, this.m_config.colorFormat, width, height
+ );
+ context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
+ );
+ context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
+ );
+ } else {
+ assertMsgOptions(
+ this.m_config.colorType == gl.RENDERBUFFER,
+ 'Not a render buffer type', false, true
+ );
+ context.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
+ context.renderbufferStorage(
+ gl.RENDERBUFFER, this.m_config.colorFormat, width, height
+ );
+ }
+
+ // Multiple framebuffers sharing the colorbuffer
+ var fbo = [
+ context.createFramebuffer(),
+ context.createFramebuffer(),
+ context.createFramebuffer()
+ ];
+
+ for (var fboi = 0; fboi < fbo.length; fboi++) {
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo[fboi]);
+
+ if (this.m_config.colorType == gl.TEXTURE_2D)
+ context.framebufferTexture2D(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, colorbuffer, 0
+ );
+ else
+ context.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.RENDERBUFFER, colorbuffer
+ );
+ }
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]);
+
+ // Check completeness
+
+ var status = context.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE)
+ throw new es3fFboTestUtil.FboIncompleteException(status);
+
+ // Render to them
+ context.viewport(0, 0, width, height);
+ context.clearColor(0.0, 0.0, 1.0, 1.0);
+ context.clear(gl.COLOR_BUFFER_BIT);
+
+ context.enable(gl.SCISSOR_TEST);
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo[1]);
+ context.clearColor(0.6, 0.0, 0.0, 1.0);
+ context.scissor(10, 10, 64, 64);
+ context.clear(gl.COLOR_BUFFER_BIT);
+ context.clearColor(0.0, 0.6, 0.0, 1.0);
+ context.scissor(60, 60, 40, 20);
+ context.clear(gl.COLOR_BUFFER_BIT);
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo[2]);
+ context.clearColor(0.0, 0.0, 0.6, 1.0);
+ context.scissor(20, 20, 100, 10);
+ context.clear(gl.COLOR_BUFFER_BIT);
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]);
+ context.clearColor(0.6, 0.0, 0.6, 1.0);
+ context.scissor(20, 20, 5, 100);
+ context.clear(gl.COLOR_BUFFER_BIT);
+
+ context.disable(gl.SCISSOR_TEST);
+
+ if (this.m_config.colorType == gl.TEXTURE_2D) {
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var shader = new es3fFboTestUtil.Texture2DShader(
+ [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderID = context.createProgram(shader);
+
+ shader.setUniforms(context, shaderID);
+
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ context.viewport(0, 0, context.getWidth(), context.getHeight());
+ rrUtil.drawQuad(
+ context, shaderID, [-0.9, -0.9, 0.0], [0.9, 0.9, 0.0]
+ );
+ dst.readViewport(
+ context, [0, 0, context.getWidth(), context.getHeight()]
+ );
+ } else
+ es3fFboTestUtil.readPixels(
+ context, dst, 0, 0, width, height, colorFormat,
+ [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]
+ );
+
+ //delete FBOs
+ for (fboi = 0; fboi < fbo.length; fboi++)
+ context.deleteFramebuffer(fbo[fboi]);
+
+ //delete Texture/Renderbuffer
+ if (this.m_config.colorType == gl.TEXTURE_2D)
+ context.deleteTexture(colorbuffer);
+ else
+ context.deleteRenderbuffer(colorbuffer);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboRenderTest.FboRenderCase}
+ * @param {es3fFboRenderTest.FboConfig} config
+ */
+ es3fFboRenderTest.SharedDepthStencilTest = function(config) {
+ es3fFboRenderTest.FboRenderCase.call(
+ this, config.getName(), 'Shared depth/stencilbuffer', config
+ );
+ };
+
+ es3fFboRenderTest.SharedDepthStencilTest.prototype =
+ Object.create(es3fFboRenderTest.FboRenderCase.prototype);
+
+ es3fFboRenderTest.SharedDepthStencilTest.prototype.constructor =
+ es3fFboRenderTest.SharedDepthStencilTest;
+
+ /**
+ * @param {es3fFboRenderTest.FboConfig} config
+ * @return {boolean}
+ */
+ es3fFboRenderTest.SharedDepthStencilTest.prototype.isConfigSupported =
+ function(config) {
+ return deMath.binaryOp(
+ config.buffers,
+ deMath.binaryOp(
+ gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR
+ ), deMath.BinaryOp.AND
+ ) != 0;
+ };
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.SharedDepthStencilTest.prototype.render = function(
+ context, dst) {
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D],
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ /** @type {es3fFboTestUtil.FlatColorShader} */
+ var flatShader = new es3fFboTestUtil.FlatColorShader(
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ var texShaderID = context.createProgram(texShader);
+ var flatShaderID = context.createProgram(flatShader);
+ var width = 128;
+ var height = 128;
+ // bool depth = (this.m_config.buffers & gl.DEPTH_BUFFER_BIT) != 0;
+ /**@type {boolean} */ var stencil =
+ (this.m_config.buffers & gl.STENCIL_BUFFER_BIT) != 0;
+
+ // Textures
+ var metaballsTex = context.createTexture();
+ var quadsTex = context.createTexture();
+ es3fFboRenderTest.createMetaballsTex2D(
+ context, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
+ );
+ es3fFboRenderTest.createQuadsTex2D(
+ context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
+ );
+
+ context.viewport(0, 0, width, height);
+
+ // Fbo A
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fboA = new es3fFboRenderTest.Framebuffer(
+ context, this.m_config, width, height
+ );
+
+ fboA.checkCompleteness();
+
+ // Fbo B
+ /** @type {es3fFboRenderTest.FboConfig} */
+ var cfg = /** @type {es3fFboRenderTest.FboConfig} */
+ (deUtil.clone(this.m_config));
+
+ cfg.buffers = deMath.binaryOp(
+ cfg.buffers,
+ deMath.binaryNot(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT),
+ deMath.BinaryOp.AND
+ );
+ cfg.depthStencilType = gl.NONE;
+ cfg.depthStencilFormat = gl.NONE;
+
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fboB = new es3fFboRenderTest.Framebuffer(
+ context, cfg, width, height
+ );
+
+ // Bind depth/stencil buffers from fbo A to fbo B
+ context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var bit = ndx ? gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT;
+ var point = ndx ? gl.STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
+
+ if (
+ deMath.binaryOp(
+ this.m_config.buffers, bit, deMath.BinaryOp.AND
+ ) == 0
+ )
+ continue;
+
+ switch (this.m_config.depthStencilType) {
+ case gl.TEXTURE_2D:
+ context.framebufferTexture2D(
+ gl.FRAMEBUFFER, point, gl.TEXTURE_2D,
+ fboA.getDepthStencilBuffer(), 0
+ );
+ break;
+ case gl.RENDERBUFFER:
+ context.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, point, gl.RENDERBUFFER,
+ fboA.getDepthStencilBuffer()
+ );
+ break;
+ default:
+ testFailed('Not implemented');
+ }
+ }
+
+ // Setup uniforms
+ texShader.setUniforms(context, texShaderID);
+
+ // Clear color to red and stencil to 1 in fbo B.
+ context.clearColor(1.0, 0.0, 0.0, 1.0);
+ context.clearStencil(1);
+ context.clear(
+ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
+ );
+
+ context.enable(gl.DEPTH_TEST);
+
+ // Render quad to fbo A
+ context.bindFramebuffer(gl.FRAMEBUFFER, fboA.getFramebuffer());
+ context.bindTexture(gl.TEXTURE_2D, quadsTex);
+ rrUtil.drawQuad(
+ context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ if (stencil) {
+ // Clear subset of stencil buffer to 0 in fbo A
+ context.enable(gl.SCISSOR_TEST);
+ context.scissor(10, 10, 12, 25);
+ context.clearStencil(0);
+ context.clear(gl.STENCIL_BUFFER_BIT);
+ context.disable(gl.SCISSOR_TEST);
+ }
+
+ // Render metaballs to fbo B
+ context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
+ context.bindTexture(gl.TEXTURE_2D, metaballsTex);
+ rrUtil.drawQuad(
+ context, texShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]
+ );
+
+ context.disable(gl.DEPTH_TEST);
+
+ if (stencil) {
+ // Render quad with stencil mask == 0
+ context.enable(gl.STENCIL_TEST);
+ context.stencilFunc(gl.EQUAL, 0, 0xff);
+ context.useProgram(flatShaderID);
+ flatShader.setColor(context, flatShaderID, [0.0, 1.0, 0.0, 1.0]);
+ rrUtil.drawQuad(
+ context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ context.disable(gl.STENCIL_TEST);
+ }
+
+ if (this.m_config.colorType == gl.TEXTURE_2D) {
+ // Render both to screen
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ context.viewport(0, 0, context.getWidth(), context.getHeight());
+ context.bindTexture(gl.TEXTURE_2D, fboA.getColorBuffer());
+ rrUtil.drawQuad(
+ context, texShaderID, [-1.0, -1.0, 0.0], [0.0, 1.0, 0.0]
+ );
+ context.bindTexture(gl.TEXTURE_2D, fboB.getColorBuffer());
+ rrUtil.drawQuad(
+ context, texShaderID, [0.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ dst.readViewport(
+ context, [0, 0, context.getWidth(), context.getHeight()]
+ );
+ } else {
+ // Read results from fbo B
+ es3fFboTestUtil.readPixels(
+ context, dst, 0, 0, width, height,
+ gluTextureUtil.mapGLInternalFormat(this.m_config.colorFormat),
+ [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]
+ );
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboRenderTest.FboRenderCase}
+ * @param {es3fFboRenderTest.FboConfig} config
+ */
+ es3fFboRenderTest.ResizeTest = function(config) {
+ es3fFboRenderTest.FboRenderCase.call(
+ this, config.getName(), 'Resize framebuffer', config
+ );
+ };
+
+ es3fFboRenderTest.ResizeTest.prototype =
+ Object.create(es3fFboRenderTest.FboRenderCase.prototype);
+
+ es3fFboRenderTest.ResizeTest.prototype.constructor =
+ es3fFboRenderTest.ResizeTest;
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * context
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.ResizeTest.prototype.render = function(context, dst) {
+ /** @type {tcuTexture.TextureFormat} */
+ var colorFormat = gluTextureUtil.mapGLInternalFormat(
+ this.m_config.colorFormat
+ );
+ /** @type {gluShaderUtil.DataType} */
+ var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat);
+ /** @type {gluShaderUtil.DataType} */
+ var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat);
+ var fboOutScale = deMath.subtract(
+ fboRangeInfo.valueMax, fboRangeInfo.valueMin
+ );
+ var fboOutBias = fboRangeInfo.valueMin;
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFboShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType
+ );
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texFromFboShader = new es3fFboTestUtil.Texture2DShader(
+ [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ /** @type {es3fFboTestUtil.FlatColorShader} */
+ var flatShader = new es3fFboTestUtil.FlatColorShader(fboOutputType);
+ /** @type {WebGLProgram} */
+ var texToFboShaderID = context.createProgram(texToFboShader);
+ /** @type {WebGLProgram} */
+ var texFromFboShaderID = context.createProgram(texFromFboShader);
+ /** @type {WebGLProgram} */
+ var flatShaderID = context.createProgram(flatShader);
+
+ var quadsTex = context.createTexture();
+ var metaballsTex = context.createTexture();
+
+ var depth = deMath.binaryOp(
+ this.m_config.buffers, gl.DEPTH_BUFFER_BIT, deMath.BinaryOp.AND
+ ) != 0;
+ var stencil = deMath.binaryOp(
+ this.m_config.buffers, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.AND
+ ) != 0;
+
+ var initialWidth = 128;
+ var initialHeight = 128;
+ var newWidth = 64;
+ var newHeight = 32;
+
+ texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
+ texFromFboShader.setTexScaleBias(
+ 0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
+ );
+
+ es3fFboRenderTest.createQuadsTex2D(
+ context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
+ );
+ es3fFboRenderTest.createMetaballsTex2D(
+ context, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 32, 32
+ );
+
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fbo = new es3fFboRenderTest.Framebuffer(
+ context, this.m_config, initialWidth, initialHeight
+ );
+ fbo.checkCompleteness();
+
+ // Setup shaders
+ texToFboShader.setUniforms(context, texToFboShaderID);
+ texFromFboShader.setUniforms(context, texFromFboShaderID);
+ flatShader.setColor(
+ context, flatShaderID, deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], fboOutScale), fboOutBias
+ )
+ );
+
+ // Render quads
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
+ context.viewport(0, 0, initialWidth, initialHeight);
+ es3fFboTestUtil.clearColorBuffer(
+ context, colorFormat, [0.0, 0.0, 0.0, 1.0]
+ );
+ context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ context.bindTexture(gl.TEXTURE_2D, quadsTex);
+ rrUtil.drawQuad(
+ context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ if (fbo.getConfig().colorType == gl.TEXTURE_2D) {
+ // Render fbo to screen
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ context.viewport(0, 0, context.getWidth(), context.getHeight());
+ context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
+ rrUtil.drawQuad(
+ context, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ // Restore binding
+ context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
+ }
+
+ // Resize buffers
+ switch (fbo.getConfig().colorType) {
+ case gl.TEXTURE_2D:
+ context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
+ context.texImage2DDelegate(
+ gl.TEXTURE_2D, 0, fbo.getConfig().colorFormat,
+ newWidth, newHeight
+ );
+ break;
+
+ case gl.RENDERBUFFER:
+ context.bindRenderbuffer(gl.RENDERBUFFER, fbo.getColorBuffer());
+ context.renderbufferStorage(
+ gl.RENDERBUFFER, fbo.getConfig().colorFormat,
+ newWidth, newHeight
+ );
+ break;
+
+ default:
+ throw new Error('Color type unsupported');
+ }
+
+ if (depth || stencil) {
+ switch (fbo.getConfig().depthStencilType) {
+ case gl.TEXTURE_2D:
+ context.bindTexture(
+ gl.TEXTURE_2D, fbo.getDepthStencilBuffer()
+ );
+ context.texImage2DDelegate(
+ gl.TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat,
+ newWidth, newHeight
+ );
+ break;
+
+ case gl.RENDERBUFFER:
+ context.bindRenderbuffer(
+ gl.RENDERBUFFER, fbo.getDepthStencilBuffer()
+ );
+ context.renderbufferStorage(
+ gl.RENDERBUFFER, fbo.getConfig().depthStencilFormat,
+ newWidth, newHeight
+ );
+ break;
+
+ default:
+ throw new Error('Depth / stencil type unsupported');
+ }
+ }
+
+ // Render to resized fbo
+ context.viewport(0, 0, newWidth, newHeight);
+ es3fFboTestUtil.clearColorBuffer(
+ context, colorFormat, [1.0, 0.0, 0.0, 1.0]
+ );
+ context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ context.enable(gl.DEPTH_TEST);
+
+ context.bindTexture(gl.TEXTURE_2D, metaballsTex);
+ rrUtil.drawQuad(
+ context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ context.bindTexture(gl.TEXTURE_2D, quadsTex);
+ rrUtil.drawQuad(
+ context, texToFboShaderID, [0.0, 0.0, -1.0], [1.0, 1.0, 1.0]
+ );
+
+ context.disable(gl.DEPTH_TEST);
+
+ if (stencil) {
+ context.enable(gl.SCISSOR_TEST);
+ context.clearStencil(1);
+ context.scissor(10, 10, 5, 15);
+ context.clear(gl.STENCIL_BUFFER_BIT);
+ context.disable(gl.SCISSOR_TEST);
+
+ context.enable(gl.STENCIL_TEST);
+ context.stencilFunc(gl.EQUAL, 1, 0xff);
+ rrUtil.drawQuad(
+ context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ context.disable(gl.STENCIL_TEST);
+ }
+
+ if (this.m_config.colorType == gl.TEXTURE_2D) {
+ context.bindFramebuffer(gl.FRAMEBUFFER, null);
+ context.viewport(0, 0, context.getWidth(), context.getHeight());
+ context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
+ rrUtil.drawQuad(
+ context, texFromFboShaderID, [-0.5, -0.5, 0.0], [0.5, 0.5, 0.0]
+ );
+ dst.readViewport(
+ context, [0, 0, context.getWidth(), context.getHeight()]
+ );
+ } else
+ es3fFboTestUtil.readPixels(
+ context, dst, 0, 0, newWidth, newHeight, colorFormat,
+ fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
+ );
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboRenderTest.FboRenderCase}
+ * @param {es3fFboRenderTest.FboConfig} config
+ * @param {number} buffers
+ * @param {boolean} rebind
+ */
+ es3fFboRenderTest.RecreateBuffersTest = function(config, buffers, rebind) {
+ es3fFboRenderTest.FboRenderCase.call(
+ this, config.getName() +
+ (rebind ? '' : '_no_rebind'),
+ 'Recreate buffers', config
+ );
+ this.m_buffers = buffers;
+ this.m_rebind = rebind;
+ };
+
+ es3fFboRenderTest.RecreateBuffersTest.prototype =
+ Object.create(es3fFboRenderTest.FboRenderCase.prototype);
+
+ es3fFboRenderTest.RecreateBuffersTest.prototype.construtor =
+ es3fFboRenderTest.RecreateBuffersTest;
+
+ /**
+ * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
+ * ctx
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboRenderTest.RecreateBuffersTest.prototype.render = function(
+ ctx, dst) {
+
+ /** @type {tcuTexture.TextureFormat} */
+ var colorFormat = gluTextureUtil.mapGLInternalFormat(
+ this.m_config.colorFormat
+ );
+ /** @type {gluShaderUtil.DataType} */
+ var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat);
+ /** @type {gluShaderUtil.DataType} */
+ var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat);
+ var fboOutScale = deMath.subtract(
+ fboRangeInfo.valueMax, fboRangeInfo.valueMin
+ );
+ var fboOutBias = fboRangeInfo.valueMin;
+
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texToFboShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType
+ );
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texFromFboShader = new es3fFboTestUtil.Texture2DShader(
+ [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ /** @type {es3fFboTestUtil.FlatColorShader} */
+ var flatShader = new es3fFboTestUtil.FlatColorShader(fboOutputType);
+ /** @type {number} */
+ var texToFboShaderID = ctx.createProgram(texToFboShader);
+ /** @type {number} */
+ var texFromFboShaderID = ctx.createProgram(texFromFboShader);
+ /** @type {number} */
+ var flatShaderID = ctx.createProgram(flatShader);
+
+ var width = 128;
+ var height = 128;
+ var metaballsTex = ctx.createTexture();
+ var quadsTex = ctx.createTexture();
+ var stencil = deMath.binaryOp(
+ this.m_config.buffers, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.AND
+ ) != 0;
+
+ es3fFboRenderTest.createQuadsTex2D(
+ ctx, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
+ );
+ es3fFboRenderTest.createMetaballsTex2D(
+ ctx, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
+ );
+
+ /** @type {es3fFboRenderTest.Framebuffer} */
+ var fbo = new es3fFboRenderTest.Framebuffer(
+ ctx, this.m_config, width, height
+ );
+ fbo.checkCompleteness();
+
+ // Setup shaders
+ texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
+ texFromFboShader.setTexScaleBias(
+ 0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
+ );
+ texToFboShader.setUniforms(ctx, texToFboShaderID);
+ texFromFboShader.setUniforms(ctx, texFromFboShaderID);
+ flatShader.setColor(
+ ctx, flatShaderID, deMath.add(
+ deMath.multiply([0.0, 0.0, 1.0, 1.0], fboOutScale
+ ), fboOutBias)
+ );
+
+ // Draw scene
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
+ ctx.viewport(0, 0, width, height);
+ es3fFboTestUtil.clearColorBuffer(
+ ctx, colorFormat, [1.0, 0.0, 0.0, 1.0]
+ );
+ ctx.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ ctx.enable(gl.DEPTH_TEST);
+
+ ctx.bindTexture(gl.TEXTURE_2D, quadsTex);
+ rrUtil.drawQuad(
+ ctx, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ ctx.disable(gl.DEPTH_TEST);
+
+ if (stencil) {
+ ctx.enable(gl.SCISSOR_TEST);
+ ctx.scissor(
+ Math.floor(width / 4), Math.floor(height / 4),
+ Math.floor(width / 2), Math.floor(height / 2)
+ );
+ ctx.clearStencil(1);
+ ctx.clear(gl.STENCIL_BUFFER_BIT);
+ ctx.disable(gl.SCISSOR_TEST);
+ }
+
+ // Recreate buffers
+ if (!this.m_rebind)
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ assertMsgOptions(
+ deMath.binaryOp(
+ this.m_buffers, deMath.binaryOp(
+ gl.DEPTH_BUFFER_BIT,
+ gl.STENCIL_BUFFER_BIT,
+ deMath.BinaryOp.OR
+ ), deMath.BinaryOp.AND
+ ) == 0 || deMath.binaryOp(
+ this.m_buffers, deMath.binaryOp(
+ gl.DEPTH_BUFFER_BIT,
+ gl.STENCIL_BUFFER_BIT,
+ deMath.BinaryOp.OR
+ ), deMath.BinaryOp.AND
+ ) == deMath.binaryOp(
+ this.m_config.buffers, deMath.binaryOp(
+ gl.DEPTH_BUFFER_BIT,
+ gl.STENCIL_BUFFER_BIT,
+ deMath.BinaryOp.OR
+ ), deMath.BinaryOp.AND
+ ), 'Depth/stencil buffers are not disabled or not ' +
+ 'equal to the config\'s depth/stencil buffer state',
+ false, true
+ );
+
+ // Recreate.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var bit = ndx == 0 ? gl.COLOR_BUFFER_BIT :
+ (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ var type = ndx == 0 ? fbo.getConfig().colorType :
+ fbo.getConfig().depthStencilType;
+ var format = ndx == 0 ? fbo.getConfig().colorFormat :
+ fbo.getConfig().depthStencilFormat;
+ var buf = ndx == 0 ? fbo.getColorBuffer() :
+ fbo.getDepthStencilBuffer();
+
+ if (deMath.binaryOp(this.m_buffers, bit, deMath.BinaryOp.AND) == 0)
+ continue;
+
+ switch (type) {
+ case gl.TEXTURE_2D:
+ ctx.deleteTexture(/** @type {WebGLTexture} */ (buf));
+ buf = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, buf);
+ ctx.texImage2DDelegate(
+ gl.TEXTURE_2D, 0, format, width, height
+ );
+ ctx.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
+ );
+ ctx.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
+ );
+ break;
+
+ case gl.RENDERBUFFER:
+ ctx.deleteRenderbuffer(
+ /** @type {WebGLRenderbuffer} */ (buf)
+ );
+ buf = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, buf);
+ ctx.renderbufferStorage(
+ gl.RENDERBUFFER, format, width, height
+ );
+ break;
+
+ default:
+ throw new Error('Unsupported buffer type');
+ }
+
+ if (ndx == 0) {
+ fbo.m_colorBuffer = buf;
+ } else {
+ fbo.m_depthStencilBuffer = buf;
+ }
+ }
+
+ // Rebind.
+ if (this.m_rebind) {
+ for (var ndx = 0; ndx < 3; ndx++) {
+ var bit = ndx == 0 ? gl.COLOR_BUFFER_BIT :
+ ndx == 1 ? gl.DEPTH_BUFFER_BIT :
+ ndx == 2 ? gl.STENCIL_BUFFER_BIT : 0;
+ var point = ndx == 0 ? gl.COLOR_ATTACHMENT0 :
+ ndx == 1 ? gl.DEPTH_ATTACHMENT :
+ ndx == 2 ? gl.STENCIL_ATTACHMENT : 0;
+ var type = ndx == 0 ? fbo.getConfig().colorType :
+ fbo.getConfig().depthStencilType;
+ var buf = ndx == 0 ? fbo.getColorBuffer() :
+ fbo.getDepthStencilBuffer();
+
+ if (deMath.binaryOp(
+ this.m_buffers, bit, deMath.BinaryOp.AND) == 0)
+ continue;
+
+ switch (type) {
+ case gl.TEXTURE_2D:
+ ctx.framebufferTexture2D(
+ gl.FRAMEBUFFER, point, gl.TEXTURE_2D, buf, 0
+ );
+ break;
+
+ case gl.RENDERBUFFER:
+ ctx.framebufferRenderbuffer(
+ gl.FRAMEBUFFER, point, gl.RENDERBUFFER, buf
+ );
+ break;
+
+ default:
+ throw new Error('Invalid buffer type');
+ }
+ }
+ }
+
+ if (!this.m_rebind)
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
+
+ ctx.clearStencil(0);
+
+ // \note Clear only buffers that were re-created
+ ctx.clear(
+ deMath.binaryOp(
+ this.m_buffers,
+ deMath.binaryOp(
+ gl.DEPTH_BUFFER_BIT,
+ gl.STENCIL_BUFFER_BIT,
+ deMath.BinaryOp.OR
+ ), deMath.BinaryOp.AND
+ )
+ );
+
+ if (deMath.binaryOp(
+ this.m_buffers, gl.COLOR_BUFFER_BIT, deMath.BinaryOp.AND)) {
+ // Clearing of integer buffers is undefined
+ // so do clearing by rendering flat color.
+ rrUtil.drawQuad(
+ ctx, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+ }
+
+ ctx.enable(gl.DEPTH_TEST);
+
+ if (stencil) {
+ // \note Stencil test enabled only if we have stencil buffer
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilFunc(gl.EQUAL, 0, 0xff);
+ }
+ ctx.bindTexture(gl.TEXTURE_2D, metaballsTex);
+ rrUtil.drawQuad(
+ ctx, texToFboShaderID, [-1.0, -1.0, 1.0], [1.0, 1.0, -1.0]
+ );
+ if (stencil)
+ ctx.disable(gl.STENCIL_TEST);
+
+ ctx.disable(gl.DEPTH_TEST);
+
+ if (fbo.getConfig().colorType == gl.TEXTURE_2D) {
+ // Unbind fbo
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ // Draw to screen
+ ctx.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
+ ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
+ rrUtil.drawQuad(
+ ctx, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ // Read from screen
+ dst.readViewport(ctx, [0, 0, ctx.getWidth(), ctx.getHeight()]);
+ } else {
+ // Read from fbo
+ es3fFboTestUtil.readPixels(
+ ctx, dst, 0, 0, width, height, colorFormat,
+ fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
+ );
+ }
+ };
+
+ // FboGroups
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fFboRenderTest.FboRenderTestGroup = function() {
+ tcuTestCase.DeqpTest.call(this, 'render', 'Rendering Tests');
+ };
+
+ es3fFboRenderTest.FboRenderTestGroup.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+
+ es3fFboRenderTest.FboRenderTestGroup.prototype.constructor =
+ es3fFboRenderTest.FboRenderTestGroup;
+
+ /**
+ * @enum {number}
+ */
+ var FormatType = {
+ FLOAT: 0,
+ INT: 1,
+ UINT: 2
+ };
+
+ // Required by specification.
+ /**
+ * @typedef {{format: number, type: FormatType}}
+ */
+ var ColorFormatStruct;
+
+ /**
+ * @typedef {{format: number, depth: boolean, stencil: boolean}}
+ */
+ var DepthStencilFormatStruct;
+
+ /**
+ * init
+ */
+ es3fFboRenderTest.FboRenderTestGroup.prototype.init = function() {
+ var objectTypes = [
+ gl.TEXTURE_2D,
+ gl.RENDERBUFFER
+ ];
+
+ /** @type {Array<ColorFormatStruct>} */ var colorFormats = [{
+ format: gl.RGBA32F, type: FormatType.FLOAT
+ },{
+ format: gl.RGBA32I, type: FormatType.INT
+ },{
+ format: gl.RGBA32UI, type: FormatType.UINT
+ },{
+ format: gl.RGBA16F, type: FormatType.FLOAT
+ },{
+ format: gl.RGBA16I, type: FormatType.INT
+ },{
+ format: gl.RGBA16UI, type: FormatType.UINT
+ },/*{
+ // RGB16F isn't made color-renderable through WebGL's EXT_color_buffer_float
+ format: gl.RGB16F, type: FormatType.FLOAT
+ },*/{
+ format: gl.RGBA8I, type: FormatType.INT
+ },{
+ format: gl.RGBA8UI, type: FormatType.UINT
+ },{
+ format: gl.RGB10_A2UI, type: FormatType.UINT
+ },{
+ format: gl.R11F_G11F_B10F, type: FormatType.FLOAT
+ },{
+ format: gl.RG32F, type: FormatType.FLOAT
+ },{
+ format: gl.RG32I, type: FormatType.INT
+ },{
+ format: gl.RG32UI, type: FormatType.UINT
+ },{
+ format: gl.RG16F, type: FormatType.FLOAT
+ },{
+ format: gl.RG16I, type: FormatType.INT
+ },{
+ format: gl.RG16UI, type: FormatType.UINT
+ },{
+ format: gl.RG8, type: FormatType.FLOAT
+ },{
+ format: gl.RG8I, type: FormatType.INT
+ },{
+ format: gl.RG8UI, type: FormatType.UINT
+ },{
+ format: gl.R32F, type: FormatType.FLOAT
+ },{
+ format: gl.R32I, type: FormatType.INT
+ },{
+ format: gl.R32UI, type: FormatType.UINT
+ },{
+ format: gl.R16F, type: FormatType.FLOAT
+ },{
+ format: gl.R16I, type: FormatType.INT
+ },{
+ format: gl.R16UI, type: FormatType.UINT
+ },{
+ format: gl.R8, type: FormatType.FLOAT
+ },{
+ format: gl.R8I, type: FormatType.INT
+ },{
+ format: gl.R8UI, type: FormatType.UINT
+ }];
+
+ /** @type {Array<DepthStencilFormatStruct>} */
+ var depthStencilFormats = [{
+ format: gl.DEPTH_COMPONENT32F, depth: true, stencil: false
+ },{
+ format: gl.DEPTH_COMPONENT24, depth: true, stencil: false
+ },{
+ format: gl.DEPTH_COMPONENT16, depth: true, stencil: false
+ },{
+ format: gl.DEPTH32F_STENCIL8, depth: true, stencil: true
+ },{
+ format: gl.DEPTH24_STENCIL8, depth: true, stencil: true
+ },{
+ format: gl.STENCIL_INDEX8, depth: false, stencil: true
+ }];
+
+ /** @type {es3fFboRenderTest.FboConfig} */ var config;
+ var colorType;
+ var stencilType;
+ var colorFmt;
+ var depth;
+ var stencil;
+ var depthStencilType;
+ var depthStencilFormat;
+
+ // .stencil_clear
+ /** @type {tcuTestCase.DeqpTest} */
+ var stencilClearGroup = new tcuTestCase.DeqpTest(
+ 'stencil_clear', 'Stencil buffer clears'
+ );
+
+ this.addChild(stencilClearGroup);
+
+ for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
+ colorType = gl.TEXTURE_2D;
+ stencilType = gl.RENDERBUFFER;
+ colorFmt = gl.RGBA8;
+
+ if (!depthStencilFormats[fmtNdx].stencil)
+ continue;
+
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT,
+ colorType, colorFmt, stencilType,
+ depthStencilFormats[fmtNdx].format
+ );
+ stencilClearGroup.addChild(
+ new es3fFboRenderTest.StencilClearsTest(config)
+ );
+ }
+
+ // .shared_colorbuffer_clear
+ /** @type {tcuTestCase.DeqpTest} */
+ var sharedColorbufferClearGroup = new tcuTestCase.DeqpTest(
+ 'shared_colorbuffer_clear', 'Shader colorbuffer clears'
+ );
+
+ this.addChild(sharedColorbufferClearGroup);
+
+ for (var colorFmtNdx = 0;
+ colorFmtNdx < colorFormats.length;
+ colorFmtNdx++) {
+
+ // Clearing of integer buffers is undefined.
+ if (colorFormats[colorFmtNdx].type == FormatType.INT ||
+ colorFormats[colorFmtNdx].type == FormatType.UINT)
+ continue;
+
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT, objectTypes[typeNdx],
+ colorFormats[colorFmtNdx].format, gl.NONE, gl.NONE
+ );
+ sharedColorbufferClearGroup.addChild(
+ new es3fFboRenderTest.SharedColorbufferClearsTest(config)
+ );
+ }
+ }
+
+ // .shared_colorbuffer
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var sharedColorbufferGroup = [];
+ var numSharedColorbufferGroups = 3;
+ for (var ii = 0; ii < numSharedColorbufferGroups; ++ii) {
+ sharedColorbufferGroup[ii] = new tcuTestCase.DeqpTest(
+ 'shared_colorbuffer', 'Shared colorbuffer tests'
+ );
+ this.addChild(sharedColorbufferGroup[ii]);
+ }
+
+ for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) {
+
+ depthStencilType = gl.RENDERBUFFER;
+ depthStencilFormat = gl.DEPTH24_STENCIL8;
+
+ // Blending with integer buffers and fp32 targets is not supported.
+ if (colorFormats[colorFmtNdx].type == FormatType.INT ||
+ colorFormats[colorFmtNdx].type == FormatType.UINT ||
+ colorFormats[colorFmtNdx].format == gl.RGBA32F ||
+ colorFormats[colorFmtNdx].format == gl.RGB32F ||
+ colorFormats[colorFmtNdx].format == gl.RG32F ||
+ colorFormats[colorFmtNdx].format == gl.R32F)
+ continue;
+
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+ /** @type {es3fFboRenderTest.FboConfig} */
+ var colorOnlyConfig = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT, objectTypes[typeNdx],
+ colorFormats[colorFmtNdx].format, gl.NONE, gl.NONE
+ );
+ /** @type {es3fFboRenderTest.FboConfig} */
+ var colorDepthConfig = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT,
+ objectTypes[typeNdx], colorFormats[colorFmtNdx].format,
+ depthStencilType, depthStencilFormat
+ );
+ /** @type {es3fFboRenderTest.FboConfig} */
+ var colorDepthStencilConfig =
+ new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT |
+ gl.DEPTH_BUFFER_BIT |
+ gl.STENCIL_BUFFER_BIT,
+ objectTypes[typeNdx], colorFormats[colorFmtNdx].format,
+ depthStencilType, depthStencilFormat
+ );
+
+ sharedColorbufferGroup[0].addChild(
+ new es3fFboRenderTest.SharedColorbufferTest(colorOnlyConfig)
+ );
+
+ sharedColorbufferGroup[1].addChild(
+ new es3fFboRenderTest.SharedColorbufferTest(
+ colorDepthConfig
+ )
+ );
+
+ sharedColorbufferGroup[2].addChild(
+ new es3fFboRenderTest.SharedColorbufferTest(
+ colorDepthStencilConfig
+ )
+ );
+ }
+ }
+
+ // .shared_depth_stencil
+ /** @type {tcuTestCase.DeqpTest} */
+ var sharedDepthStencilGroup = new tcuTestCase.DeqpTest(
+ 'shared_depth_stencil', 'Shared depth and stencil buffers'
+ );
+
+ this.addChild(sharedDepthStencilGroup);
+
+ for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
+ colorType = gl.TEXTURE_2D;
+ colorFmt = gl.RGBA8;
+ depth = depthStencilFormats[fmtNdx].depth;
+ stencil = depthStencilFormats[fmtNdx].stencil;
+
+ if (!depth)
+ continue; // Not verified.
+
+ // Depth and stencil: both rbo and textures
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT |
+ (depth ? gl.DEPTH_BUFFER_BIT : 0) |
+ (stencil ? gl.STENCIL_BUFFER_BIT : 0),
+ colorType, colorFmt, objectTypes[typeNdx],
+ depthStencilFormats[fmtNdx].format
+ );
+
+ sharedDepthStencilGroup.addChild(
+ new es3fFboRenderTest.SharedDepthStencilTest(config)
+ );
+ }
+ }
+
+ // .resize
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var resizeGroup = [];
+ var numResizeGroups = 4;
+ for (var ii = 0; ii < numResizeGroups; ++ii) {
+ resizeGroup[ii] = new tcuTestCase.DeqpTest('resize', 'FBO resize tests');
+ this.addChild(resizeGroup[ii]);
+ }
+
+ for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) {
+
+ var colorFormat = colorFormats[colorFmtNdx].format;
+
+ // Color-only.
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT, objectTypes[typeNdx],
+ colorFormat, gl.NONE, gl.NONE
+ );
+ resizeGroup[colorFmtNdx % numResizeGroups].addChild(new es3fFboRenderTest.ResizeTest(config));
+ }
+
+ // For selected color formats tests depth & stencil variants.
+ if (colorFormat == gl.RGBA8 || colorFormat == gl.RGBA16F) {
+ for (var depthStencilFmtNdx = 0; depthStencilFmtNdx < depthStencilFormats.length; depthStencilFmtNdx++) {
+
+ colorType = gl.TEXTURE_2D;
+ depth = depthStencilFormats[depthStencilFmtNdx].depth;
+ stencil = depthStencilFormats[depthStencilFmtNdx].stencil;
+
+ // Depth and stencil: both rbo and textures
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+
+ if (!depth && objectTypes[typeNdx] != gl.RENDERBUFFER)
+ continue; // Not supported.
+
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT |
+ (depth ? gl.DEPTH_BUFFER_BIT : 0) |
+ (stencil ? gl.STENCIL_BUFFER_BIT : 0),
+ colorType, colorFormat, objectTypes[typeNdx],
+ depthStencilFormats[depthStencilFmtNdx].format
+ );
+
+ resizeGroup[colorFmtNdx % numResizeGroups].addChild(
+ new es3fFboRenderTest.ResizeTest(config)
+ );
+ }
+ }
+ }
+ }
+
+ // .recreate_color
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var recreateColorGroup = [];
+ var numRecreateColorGroups = 7;
+ for (var ii = 0; ii < numRecreateColorGroups; ++ii) {
+ recreateColorGroup[ii] = new tcuTestCase.DeqpTest('recreate_color', 'Recreate colorbuffer tests');
+ this.addChild(recreateColorGroup[ii]);
+ }
+
+ for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) {
+
+ colorFormat = colorFormats[colorFmtNdx].format;
+ depthStencilFormat = gl.DEPTH24_STENCIL8;
+ depthStencilType = gl.RENDERBUFFER;
+
+ // Color-only.
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT |
+ gl.DEPTH_BUFFER_BIT |
+ gl.STENCIL_BUFFER_BIT,
+ objectTypes[typeNdx], colorFormat,
+ depthStencilType, depthStencilFormat
+ );
+
+ recreateColorGroup[colorFmtNdx % numRecreateColorGroups].addChild(
+ new es3fFboRenderTest.RecreateBuffersTest(
+ config, gl.COLOR_BUFFER_BIT, true /* rebind */
+ )
+ );
+ }
+ }
+
+ // .recreate_depth_stencil
+ /** @type {tcuTestCase.DeqpTest} */
+ var recreateDepthStencilGroup = new tcuTestCase.DeqpTest(
+ 'recreate_depth_stencil', 'Recreate depth and stencil buffers'
+ );
+
+ this.addChild(recreateDepthStencilGroup);
+
+ for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
+ colorType = gl.TEXTURE_2D;
+ colorFmt = gl.RGBA8;
+ depth = depthStencilFormats[fmtNdx].depth;
+ stencil = depthStencilFormats[fmtNdx].stencil;
+
+ // Depth and stencil: both rbo and textures
+ for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
+ if (!depth && objectTypes[typeNdx] != gl.RENDERBUFFER)
+ continue;
+
+ config = new es3fFboRenderTest.FboConfig(
+ gl.COLOR_BUFFER_BIT |
+ (depth ? gl.DEPTH_BUFFER_BIT : 0) |
+ (stencil ? gl.STENCIL_BUFFER_BIT : 0),
+ colorType, colorFmt, objectTypes[typeNdx],
+ depthStencilFormats[fmtNdx].format
+ );
+
+ recreateDepthStencilGroup.addChild(
+ new es3fFboRenderTest.RecreateBuffersTest(
+ config,
+ (depth ? gl.DEPTH_BUFFER_BIT : 0) |
+ (stencil ? gl.STENCIL_BUFFER_BIT : 0),
+ true /* rebind */
+ )
+ );
+ }
+ }
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fFboRenderTest.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+
+ state.setRoot(new es3fFboRenderTest.FboRenderTestGroup());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStateQueryTests.js
new file mode 100644
index 0000000000..4795790ef4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStateQueryTests.js
@@ -0,0 +1,796 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboStateQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fFboStateQueryTests = functional.gles3.es3fFboStateQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+// WebGL bit depths
+es3fFboStateQueryTests.colorBits = [8, 8, 8, 8];
+es3fFboStateQueryTests.depthBits = 0;
+es3fFboStateQueryTests.stencilBits = 0;
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} framebufferTarget
+ */
+es3fFboStateQueryTests.DefaultFramebufferCase = function(name, description, framebufferTarget) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_framebufferTarget = framebufferTarget;
+};
+
+setParentClass(es3fFboStateQueryTests.DefaultFramebufferCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.DefaultFramebufferCase.prototype.test = function() {
+ var hasColorBuffer = es3fFboStateQueryTests.colorBits[0] > 0 ||
+ es3fFboStateQueryTests.colorBits[1] > 0 ||
+ es3fFboStateQueryTests.colorBits[2] > 0 ||
+ es3fFboStateQueryTests.colorBits[3] > 0;
+ var attachments = [
+ gl.BACK,
+ gl.DEPTH,
+ gl.STENCIL
+ ];
+ var attachmentExists = [
+ hasColorBuffer,
+ es3fFboStateQueryTests.depthBits > 0,
+ es3fFboStateQueryTests.stencilBits > 0
+ ];
+
+ for (var ndx = 0; ndx < attachments.length; ++ndx) {
+ var objType = gl.getFramebufferAttachmentParameter(this.m_framebufferTarget, attachments[ndx], gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ if (attachmentExists[ndx]) {
+ this.check(objType === gl.FRAMEBUFFER_DEFAULT);
+ } else {
+ // \note [jarkko] FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE "identifes the type of object which contains the attached image". However, it
+ // is unclear if an object of type FRAMEBUFFER_DEFAULT can contain a null image (or a 0-bits-per-pixel image). Accept both
+ // FRAMEBUFFER_DEFAULT and NONE as valid results in these cases.
+ this.check(objType === gl.FRAMEBUFFER_DEFAULT || objType === gl.NONE);
+ }
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentObjectCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentObjectCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentObjectCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+
+ // initial
+ this.check(glsStateQuery.verifyAttachment(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, gl.NONE));
+ this.check(glsStateQuery.verifyAttachment(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, null));
+
+ // texture
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 128, 128, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureID, 0);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, gl.TEXTURE));
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, textureID));
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+
+ // rb
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB8, 128, 128);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, gl.RENDERBUFFER));
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, renderbufferID));
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentTextureLevelCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentTextureLevelCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentTextureLevelCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ for (var mipmapLevel = 0; mipmapLevel < 7; ++mipmapLevel) {
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+ gl.texStorage2D(gl.TEXTURE_2D, 7, gl.RGB8, 128, 128);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureID, mipmapLevel);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, mipmapLevel));
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+ }
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentTextureCubeMapFaceCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentTextureCubeMapFaceCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentTextureCubeMapFaceCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, textureID);
+
+ gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGB8, 128, 128);
+
+ var faces = [
+ 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 ndx = 0; ndx < faces.length; ++ndx) {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, faces[ndx], textureID, 0);
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, faces[ndx]));
+ }
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentTextureLayerCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentTextureLayerCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentTextureLayerCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ // tex3d
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, textureID);
+ gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 16, 16, 16);
+
+ for (var layer = 0; layer < 16; ++layer) {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, textureID, 0, layer);
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, layer));
+ }
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+ // tex2d array
+ textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, textureID);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 16, 16, 16);
+
+ for (var layer = 0; layer < 16; ++layer) {
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, textureID, 0, layer);
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, layer));
+ }
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentTextureColorCodingCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentTextureColorCodingCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentTextureColorCodingCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ // rgb8 color
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB8, 128, 128);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, gl.LINEAR));
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+
+ // srgb8_alpha8 color
+ renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, 128, 128);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, gl.SRGB));
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+
+ // depth
+ renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 128, 128);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyAttachment(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, gl.LINEAR));
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentTextureComponentTypeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentTextureComponentTypeCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentTextureComponentTypeCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ // color-renderable required texture formats
+ var requiredColorformats = [
+ [gl.R8, gl.UNSIGNED_NORMALIZED],
+ [gl.RG8, gl.UNSIGNED_NORMALIZED],
+ [gl.RGB8, gl.UNSIGNED_NORMALIZED],
+ [gl.RGB565, gl.UNSIGNED_NORMALIZED],
+ [gl.RGBA4, gl.UNSIGNED_NORMALIZED],
+ [gl.RGB5_A1, gl.UNSIGNED_NORMALIZED],
+ [gl.RGBA8, gl.UNSIGNED_NORMALIZED],
+ [gl.RGB10_A2, gl.UNSIGNED_NORMALIZED],
+ [gl.RGB10_A2UI, gl.UNSIGNED_INT],
+ [gl.SRGB8_ALPHA8, gl.UNSIGNED_NORMALIZED],
+ [gl.R8I, gl.INT],
+ [gl.R8UI, gl.UNSIGNED_INT],
+ [gl.R16I, gl.INT],
+ [gl.R16UI, gl.UNSIGNED_INT],
+ [gl.R32I, gl.INT],
+ [gl.R32UI, gl.UNSIGNED_INT],
+ [gl.RG8I, gl.INT],
+ [gl.RG8UI, gl.UNSIGNED_INT],
+ [gl.RG16I, gl.INT],
+ [gl.RG16UI, gl.UNSIGNED_INT],
+ [gl.RG32I, gl.INT],
+ [gl.RG32UI, gl.UNSIGNED_INT],
+ [gl.RGBA8I, gl.INT],
+ [gl.RGBA8UI, gl.UNSIGNED_INT],
+ [gl.RGBA16I, gl.INT],
+ [gl.RGBA16UI, gl.UNSIGNED_INT],
+ [gl.RGBA32I, gl.INT],
+ [gl.RGBA32UI, gl.UNSIGNED_INT]
+ ];
+
+ for (var ndx = 0; ndx < requiredColorformats.length; ++ndx) {
+ var colorFormat = requiredColorformats[ndx][0];
+ var componentType = requiredColorformats[ndx][1];
+
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, colorFormat, 128, 128);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureID, 0);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, componentType));
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+ }
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentSizeInitialCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentSizeInitialCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentSizeInitialCase.prototype.attachmentExists = function(attachment) {
+ var objType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ return objType !== gl.NONE;
+};
+
+/**
+ * @this {es3fApiCase.ApiCase}
+ */
+var checkAttachmentComponentSizeAtLeast = function(target, attachment, r, g, b, a, d, s) {
+ var referenceSizes = [r, g, b, a, d, s];
+ var paramNames = [
+ 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
+ ];
+
+ for (var ndx = 0; ndx < referenceSizes.length; ++ndx) {
+ if (referenceSizes[ndx] == -1)
+ continue;
+
+ var value = /** @type {number} */ (gl.getFramebufferAttachmentParameter(target, attachment, paramNames[ndx]));
+
+ this.check(value >= referenceSizes[ndx], 'Expected greater or equal to ' + referenceSizes[ndx] + ' got ' + value);
+ }
+};
+
+/**
+ * @this {es3fApiCase.ApiCase}
+ */
+var checkAttachmentComponentSizeExactly = function(target, attachment, r, g, b, a, d, s) {
+ var referenceSizes = [r, g, b, a, d, s];
+ var paramNames = [
+ 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
+ ];
+
+ for (var ndx = 0; ndx < referenceSizes.length; ++ndx) {
+ if (referenceSizes[ndx] == -1)
+ continue;
+
+ var value = gl.getFramebufferAttachmentParameter(target, attachment, paramNames[ndx]);
+
+ this.check(value == referenceSizes[ndx], 'Expected equal to ' + referenceSizes[ndx] + ' got ' + value);
+ }
+};
+
+es3fFboStateQueryTests.AttachmentSizeInitialCase.prototype.test = function() {
+ // check default
+ if (this.attachmentExists(gl.BACK)) {
+ checkAttachmentComponentSizeAtLeast.bind(this,
+ gl.FRAMEBUFFER,
+ gl.BACK,
+ es3fFboStateQueryTests.colorBits[0],
+ es3fFboStateQueryTests.colorBits[1],
+ es3fFboStateQueryTests.colorBits[2],
+ es3fFboStateQueryTests.colorBits[3],
+ -1,
+ -1);
+ }
+
+ if (this.attachmentExists(gl.DEPTH)) {
+ checkAttachmentComponentSizeAtLeast.bind(this,
+ gl.FRAMEBUFFER,
+ gl.DEPTH,
+ -1,
+ -1,
+ -1,
+ -1,
+ es3fFboStateQueryTests.depthBits,
+ -1);
+ }
+
+ if (this.attachmentExists(gl.STENCIL)) {
+ checkAttachmentComponentSizeAtLeast.bind(this,
+ gl.FRAMEBUFFER,
+ gl.STENCIL,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ es3fFboStateQueryTests.stencilBits);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentSizeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentSizeCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.AttachmentSizeCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ // check some color targets
+
+ var colorAttachments = [
+ //format, red, green, blue, alpha
+ [gl.RGBA8, 8, 8, 8, 8],
+ [gl.RGB565, 5, 6, 5, 0],
+ [gl.RGBA4, 4, 4, 4, 4],
+ [gl.RGB5_A1, 5, 5, 5, 1],
+ [gl.RGBA8I, 8, 8, 8, 8],
+ [gl.RG32UI, 32, 32, 0, 0]
+ ];
+ for (var ndx = 0; ndx < colorAttachments.length; ++ndx)
+ this.testColorAttachment(colorAttachments[ndx][0], gl.COLOR_ATTACHMENT0, colorAttachments[ndx][1], colorAttachments[ndx][2], colorAttachments[ndx][3], colorAttachments[ndx][4]);
+
+ // check some depth targets
+
+ var depthAttachments = [
+ // format, attachment, depth, stencil
+ [gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT, 16, 0],
+ [gl.DEPTH_COMPONENT24, gl.DEPTH_ATTACHMENT, 24, 0],
+ [gl.DEPTH_COMPONENT32F, gl.DEPTH_ATTACHMENT, 32, 0],
+ [gl.DEPTH24_STENCIL8, gl.DEPTH_STENCIL_ATTACHMENT, 24, 8],
+ [gl.DEPTH32F_STENCIL8, gl.DEPTH_STENCIL_ATTACHMENT, 32, 8]
+ ];
+ for (var ndx = 0; ndx < depthAttachments.length; ++ndx)
+ this.testDepthAttachment(depthAttachments[ndx][0], depthAttachments[ndx][1], depthAttachments[ndx][2], depthAttachments[ndx][3]);
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboStateQueryTests.AttachmentSizeCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentSizeRboCase = function(name, description) {
+ es3fFboStateQueryTests.AttachmentSizeCase.call(this, name, description);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentSizeRboCase, es3fFboStateQueryTests.AttachmentSizeCase);
+
+es3fFboStateQueryTests.AttachmentSizeRboCase.prototype.testColorAttachment = function(internalFormat, attachment, r, g, b, a) {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, 128, 128);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbufferID);
+
+ checkAttachmentComponentSizeAtLeast.bind(this, gl.FRAMEBUFFER, attachment, r, g, b, a, -1, -1);
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, attachment, -1, -1, -1, -1, 0, 0);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+es3fFboStateQueryTests.AttachmentSizeRboCase.prototype.testDepthAttachment = function(internalFormat, attachment, depth, stencil) {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, 128, 128);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbufferID);
+
+ checkAttachmentComponentSizeAtLeast.bind(this, gl.FRAMEBUFFER, attachment, -1, -1, -1, -1, depth, stencil);
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, attachment, 0, 0, 0, 0, -1, -1);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboStateQueryTests.AttachmentSizeCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.AttachmentSizeTextureCase = function(name, description) {
+ es3fFboStateQueryTests.AttachmentSizeCase.call(this, name, description);
+};
+
+setParentClass(es3fFboStateQueryTests.AttachmentSizeTextureCase, es3fFboStateQueryTests.AttachmentSizeCase);
+
+es3fFboStateQueryTests.AttachmentSizeTextureCase.prototype.testColorAttachment = function(internalFormat, attachment, r, g, b, a) {
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, internalFormat, 128, 128);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureID, 0);
+
+ checkAttachmentComponentSizeAtLeast.bind(this, gl.FRAMEBUFFER, attachment, r, g, b, a, -1, -1);
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, attachment, -1, -1, -1, -1, 0, 0);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+};
+
+es3fFboStateQueryTests.AttachmentSizeTextureCase.prototype.testDepthAttachment = function(internalFormat, attachment, depth, stencil) {
+ // don't test stencil formats with textures
+ if (attachment == gl.DEPTH_STENCIL_ATTACHMENT)
+ return;
+
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+ gl.texStorage2D(gl.TEXTURE_2D, 1, internalFormat, 128, 128);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureID, 0);
+
+ checkAttachmentComponentSizeAtLeast.bind(this, gl.FRAMEBUFFER, attachment, -1, -1, -1, -1, depth, stencil);
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, attachment, 0, 0, 0, 0, -1, -1);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.UnspecifiedAttachmentTextureColorCodingCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.UnspecifiedAttachmentTextureColorCodingCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.UnspecifiedAttachmentTextureColorCodingCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ // color
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyColorAttachment(gl.FRAMEBUFFER, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, gl.LINEAR));
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+
+ // depth
+ renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyAttachment(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, gl.LINEAR));
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase.prototype.test = function() {
+ var framebufferID = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferID);
+ // check color target
+ this.testColorAttachment();
+
+ // check depth target
+ this.testDepthAttachment();
+ gl.deleteFramebuffer(framebufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeRboCase = function(name, description) {
+ es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase.call(this, name, description);
+};
+
+setParentClass(es3fFboStateQueryTests.UnspecifiedAttachmentSizeRboCase, es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase);
+
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeRboCase.prototype.testColorAttachment = function() {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbufferID);
+
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 0, 0, 0, 0, 0, 0);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeRboCase.prototype.testDepthAttachment = function() {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbufferID);
+
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, 0, 0, 0, 0, 0, 0);
+
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeTextureCase = function(name, description) {
+ es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase.call(this, name, description);
+};
+
+setParentClass(es3fFboStateQueryTests.UnspecifiedAttachmentSizeTextureCase, es3fFboStateQueryTests.UnspecifiedAttachmentSizeCase);
+
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeTextureCase.prototype.testColorAttachment = function() {
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureID, 0);
+
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 0, 0, 0, 0, 0, 0);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+};
+
+es3fFboStateQueryTests.UnspecifiedAttachmentSizeTextureCase.prototype.testDepthAttachment = function() {
+ var textureID = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, textureID);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureID, 0);
+
+ checkAttachmentComponentSizeExactly.bind(this, gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, 0, 0, 0, 0, 0, 0);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, null, 0);
+ gl.deleteTexture(textureID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fFboStateQueryTests.UnspecifiedAttachmentTextureComponentTypeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fFboStateQueryTests.UnspecifiedAttachmentTextureComponentTypeCase, es3fApiCase.ApiCase);
+
+es3fFboStateQueryTests.UnspecifiedAttachmentTextureComponentTypeCase.prototype.test = function() {
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fFboStateQueryTests.FboStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'fbo', 'Fbo State Query tests');
+};
+
+es3fFboStateQueryTests.FboStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fFboStateQueryTests.FboStateQueryTests.prototype.constructor = es3fFboStateQueryTests.FboStateQueryTests;
+
+es3fFboStateQueryTests.FboStateQueryTests.prototype.init = function() {
+ var red = /** @type {number} */ (gl.getParameter(gl.RED_BITS));
+ var green = /** @type {number} */ (gl.getParameter(gl.GREEN_BITS));
+ var blue = /** @type {number} */ (gl.getParameter(gl.BLUE_BITS));
+ var alpha = /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS));
+ es3fFboStateQueryTests.colorBits = [red, green, blue, alpha];
+ es3fFboStateQueryTests.depthBits = /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS));
+ es3fFboStateQueryTests.stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ this.addChild(new es3fFboStateQueryTests.DefaultFramebufferCase('draw_framebuffer_default_framebuffer', 'default framebuffer', gl.DRAW_FRAMEBUFFER));
+ this.addChild(new es3fFboStateQueryTests.DefaultFramebufferCase('read_framebuffer_default_framebuffer', 'default framebuffer', gl.READ_FRAMEBUFFER));
+ this.addChild(new es3fFboStateQueryTests.AttachmentObjectCase('framebuffer_attachment_object', 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE and FRAMEBUFFER_ATTACHMENT_OBJECT_NAME'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentTextureLevelCase('framebuffer_attachment_texture_level', 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentTextureCubeMapFaceCase('framebuffer_attachment_texture_cube_map_face', 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentTextureLayerCase('framebuffer_attachment_texture_layer', 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentTextureColorCodingCase('framebuffer_attachment_color_encoding', 'FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentTextureComponentTypeCase('framebuffer_attachment_component_type', 'FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentSizeInitialCase('framebuffer_attachment_x_size_initial', 'FRAMEBUFFER_ATTACHMENT_x_SIZE'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentSizeRboCase('framebuffer_attachment_x_size_rbo', 'FRAMEBUFFER_ATTACHMENT_x_SIZE'));
+ this.addChild(new es3fFboStateQueryTests.AttachmentSizeTextureCase('framebuffer_attachment_x_size_texture', 'FRAMEBUFFER_ATTACHMENT_x_SIZE'));
+ this.addChild(new es3fFboStateQueryTests.UnspecifiedAttachmentTextureColorCodingCase('framebuffer_unspecified_attachment_color_encoding', 'FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING'));
+ this.addChild(new es3fFboStateQueryTests.UnspecifiedAttachmentTextureComponentTypeCase('framebuffer_unspecified_attachment_component_type', 'FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE'));
+ this.addChild(new es3fFboStateQueryTests.UnspecifiedAttachmentSizeRboCase('framebuffer_unspecified_attachment_x_size_rbo', 'FRAMEBUFFER_ATTACHMENT_x_SIZE'));
+ this.addChild(new es3fFboStateQueryTests.UnspecifiedAttachmentSizeTextureCase('framebuffer_unspecified_attachment_x_size_texture', 'FRAMEBUFFER_ATTACHMENT_x_SIZE'));
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fFboStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fFboStateQueryTests.FboStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFboStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStencilbufferTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStencilbufferTests.js
new file mode 100644
index 0000000000..4cebe7e4a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboStencilbufferTests.js
@@ -0,0 +1,325 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fFboStencilbufferTests');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+
+ var es3fFboStencilbufferTests = functional.gles3.es3fFboStencilbufferTests;
+ var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+ var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var rrUtil = framework.referencerenderer.rrUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {Array<number>} size
+ * @param {boolean} useDepth
+ */
+ es3fFboStencilbufferTests.BasicFboStencilCase = function(name, desc, format, size, useDepth) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @type {number} */ this.m_format = format;
+ /** @type {Array<number>} */ this.m_size = size;
+ /** @type {boolean} */ this.m_useDepth = useDepth;
+ };
+
+ es3fFboStencilbufferTests.BasicFboStencilCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFboStencilbufferTests.BasicFboStencilCase.prototype.constructor = es3fFboStencilbufferTests.BasicFboStencilCase;
+
+ es3fFboStencilbufferTests.BasicFboStencilCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboStencilbufferTests.BasicFboStencilCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ /** @const {number} */ var colorFormat = gl.RGBA8;
+
+ /** @type {es3fFboTestUtil.GradientShader} */ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var flatShaderID = this.getCurrentContext().createProgram(flatShader);
+ var gradShaderID = this.getCurrentContext().createProgram(gradShader);
+
+ var fbo = 0;
+ var colorRbo = 0;
+ var depthStencilRbo = 0;
+
+ // Colorbuffer.
+ colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_size[0], this.m_size[1]);
+
+ // Stencil (and depth) buffer.
+ depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_size[0], this.m_size[1]);
+
+ // Framebuffer.
+ fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+ if (this.m_useDepth)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilRbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_size[0], this.m_size[1]);
+
+ // Clear framebuffer.
+ ctx.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 0.0]);
+ ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ // Render intersecting quads - increment stencil on depth pass
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilFunc(gl.ALWAYS, 0, 0xff);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [1.0, 0.0, 0.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+
+ gradShader.setGradient(this.getCurrentContext(), gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ ctx.disable(gl.DEPTH_TEST);
+
+ // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
+ ctx.stencilFunc(gl.EQUAL, this.m_useDepth ? 2 : 1, 0xff);
+ ctx.stencilOp(gl.DECR, gl.KEEP, gl.KEEP);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 1.0, 0.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-0.5, -0.5, 0.0], [0.5, 0.5, 0.0]);
+
+ // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer
+ ctx.stencilFunc(gl.GREATER, this.m_useDepth ? 1 : 2, 0xff);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 0.0, 1.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_size[0], this.m_size[1], gluTextureUtil.mapGLInternalFormat(colorFormat), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} attachDepth
+ */
+ es3fFboStencilbufferTests.DepthStencilAttachCase = function(name, desc, attachDepth, attachStencil) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @type {number} */ this.m_attachDepth = attachDepth;
+ /** @type {number} */ this.m_attachStencil = attachStencil;
+ DE_ASSERT(this.m_attachDepth == gl.DEPTH_ATTACHMENT || this.m_attachDepth == gl.DEPTH_STENCIL_ATTACHMENT || this.m_attachDepth == gl.NONE);
+ DE_ASSERT(this.m_attachStencil == gl.STENCIL_ATTACHMENT || this.m_attachStencil == gl.NONE);
+ DE_ASSERT(this.m_attachDepth != gl.DEPTH_STENCIL || this.m_attachStencil == gl.NONE);
+ };
+
+ es3fFboStencilbufferTests.DepthStencilAttachCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFboStencilbufferTests.DepthStencilAttachCase.prototype.constructor = es3fFboStencilbufferTests.DepthStencilAttachCase;
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFboStencilbufferTests.DepthStencilAttachCase.prototype.render = function(dst) {
+
+ var ctx = this.getCurrentContext();
+ /** @const {number} */ var colorFormat = gl.RGBA8;
+ /** @const {number} */ var depthStencilFormat = gl.DEPTH24_STENCIL8;
+ /** @const {number} */ var width = 128;
+ /** @const {number} */ var height = 128;
+ /** @const {boolean} */ var hasDepth = this.m_attachDepth == gl.DEPTH_STENCIL || this.m_attachDepth == gl.DEPTH_ATTACHMENT;
+ // /** @const {boolean} */ var hasStencil = this.m_attachDepth == gl.DEPTH_STENCIL || this.m_attachStencil == gl.DEPTH_STENCIL_ATTACHMENT); // commented out in original code
+
+ /** @type {es3fFboTestUtil.GradientShader} */ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var flatShaderID = this.getCurrentContext().createProgram(flatShader);
+ var gradShaderID = this.getCurrentContext().createProgram(gradShader);
+
+ var fbo = 0;
+ var colorRbo = 0;
+ var depthStencilRbo = 0;
+
+ // Colorbuffer.
+ colorRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, colorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, width, height);
+
+ // Depth-stencil buffer.
+ depthStencilRbo = ctx.createRenderbuffer();
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, width, height);
+
+ // Framebuffer.
+ fbo = ctx.createFramebuffer();
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRbo);
+
+ if (this.m_attachDepth != gl.NONE)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, this.m_attachDepth, gl.RENDERBUFFER, depthStencilRbo);
+ if (this.m_attachStencil != gl.NONE)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, this.m_attachStencil, gl.RENDERBUFFER, depthStencilRbo);
+
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, width, height);
+
+ // Clear framebuffer.
+ ctx.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 0.0]);
+ ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ // Render intersecting quads - increment stencil on depth pass
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilFunc(gl.ALWAYS, 0, 0xff);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [1.0, 0.0, 0.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+
+ gradShader.setGradient(this.getCurrentContext(), gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), gradShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]);
+
+ ctx.disable(gl.DEPTH_TEST);
+
+ // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
+ ctx.stencilFunc(gl.EQUAL, hasDepth ? 2 : 1, 0xff);
+ ctx.stencilOp(gl.DECR, gl.KEEP, gl.KEEP);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 1.0, 0.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-0.5, -0.5, 0.0], [0.5, 0.5, 0.0]);
+
+ // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer
+ ctx.stencilFunc(gl.GREATER, hasDepth ? 1 : 2, 0xff);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 0.0, 1.0, 1.0]);
+
+ rrUtil.drawQuad(this.getCurrentContext(), flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]);
+
+ this.readPixelsUsingFormat(dst, 0, 0, width, height, gluTextureUtil.mapGLInternalFormat(colorFormat), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fFboStencilbufferTests.FboStencilTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'stencil', 'FBO Stencilbuffer tests');
+ };
+
+ es3fFboStencilbufferTests.FboStencilTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFboStencilbufferTests.FboStencilTests.prototype.constructor = es3fFboStencilbufferTests.FboStencilTests;
+
+ es3fFboStencilbufferTests.FboStencilTests.prototype.init = function() {
+ /** @const {Array<number>} */ var stencilFormats = [
+ gl.DEPTH32F_STENCIL8,
+ gl.DEPTH24_STENCIL8,
+ gl.STENCIL_INDEX8
+ ];
+
+ // .basic
+ /** @type {tcuTestCase.DeqpTest} */
+ var basicGroup = tcuTestCase.newTest('basic', 'Basic stencil tests');
+ this.addChild(basicGroup);
+
+ for (var fmtNdx = 0; fmtNdx < stencilFormats.length; fmtNdx++) {
+ /** @type {number} */ var format = stencilFormats[fmtNdx];
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(format);
+
+ basicGroup.addChild(new es3fFboStencilbufferTests.BasicFboStencilCase(es3fFboTestUtil.getFormatName(format), '', format, [111, 132], false));
+
+ if (texFmt.order == tcuTexture.ChannelOrder.DS)
+ basicGroup.addChild(new es3fFboStencilbufferTests.BasicFboStencilCase(es3fFboTestUtil.getFormatName(format) + '_depth', '', format, [111, 132], true));
+ }
+
+ // .attach
+ /** @type {tcuTestCase.DeqpTest} */
+ var attachGroup = tcuTestCase.newTest('attach', 'Attaching depth stencil');
+ this.addChild(attachGroup);
+
+ attachGroup.addChild(new es3fFboStencilbufferTests.DepthStencilAttachCase('depth_only', 'Only depth part of depth-stencil RBO attached', gl.DEPTH_ATTACHMENT, gl.NONE));
+ attachGroup.addChild(new es3fFboStencilbufferTests.DepthStencilAttachCase('stencil_only', 'Only stencil part of depth-stencil RBO attached', gl.NONE, gl.STENCIL_ATTACHMENT));
+ attachGroup.addChild(new es3fFboStencilbufferTests.DepthStencilAttachCase('depth_stencil_separate', 'Depth and stencil attached separately', gl.DEPTH_ATTACHMENT, gl.STENCIL_ATTACHMENT));
+ attachGroup.addChild(new es3fFboStencilbufferTests.DepthStencilAttachCase('depth_stencil_attachment', 'Depth and stencil attached with DEPTH_STENCIL_ATTACHMENT', gl.DEPTH_STENCIL_ATTACHMENT, gl.NONE));
+ };
+
+ es3fFboStencilbufferTests.run = function(context) {
+ gl = context;
+ //Set up root Test
+ var state = tcuTestCase.runner;
+
+ var test = new es3fFboStencilbufferTests.FboStencilTests();
+ var testName = test.fullName();
+ var testDescription = test.getDescription();
+
+ state.testName = testName;
+ state.setRoot(test);
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ test.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFboStencilbufferTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestCase.js
new file mode 100644
index 0000000000..cdaa7d352f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestCase.js
@@ -0,0 +1,483 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboTestCase');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.referencerenderer.rrRenderer');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+
+var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+var tcuTestCase = framework.common.tcuTestCase;
+var deMath = framework.delibs.debase.deMath;
+var tcuSurface = framework.common.tcuSurface;
+var tcuTexture = framework.common.tcuTexture;
+var rrRenderer = framework.referencerenderer.rrRenderer;
+var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+var tcuPixelFormat = framework.common.tcuPixelFormat;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var deString = framework.delibs.debase.deString;
+var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var deRandom = framework.delibs.debase.deRandom;
+
+/** @typedef {(sglrGLContext.GLContext | WebGL2RenderingContext | sglrReferenceContext.ReferenceContext)} */
+es3fFboTestCase.Context;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+ /**
+ * es3fFboTestCase.FboTestCase class, inherits from TestCase and sglrContextWrapper
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean=} useScreenSizedViewport
+ */
+ es3fFboTestCase.FboTestCase = function(name, description, useScreenSizedViewport /*= false */) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {number} */ this.m_viewportWidth = useScreenSizedViewport === undefined ? gl.drawingBufferWidth : 128;
+ /** @type {number} */ this.m_viewportHeight = useScreenSizedViewport === undefined ? gl.drawingBufferHeight : 128;
+ /** @type {es3fFboTestCase.Context} */ this.m_curCtx = null;
+ };
+
+ es3fFboTestCase.FboTestCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFboTestCase.FboTestCase.prototype.constructor = es3fFboTestCase.FboTestCase;
+
+ es3fFboTestCase.FboTestCase.prototype.getWidth = function() {
+ return Math.min(gl.drawingBufferWidth, this.m_viewportWidth);
+ };
+
+ es3fFboTestCase.FboTestCase.prototype.getHeight = function() {
+ return Math.min(gl.drawingBufferHeight, this.m_viewportHeight);
+ };
+
+ /**
+ * Sets the current context (inherited from sglrContextWrapper)
+ * @param {es3fFboTestCase.Context} context
+ */
+ es3fFboTestCase.FboTestCase.prototype.setContext = function(context) {
+ this.m_curCtx = context;
+ };
+
+ /**
+ * Gets the current context (inherited from sglrContextWrapper)
+ * @return {es3fFboTestCase.Context}
+ */
+ es3fFboTestCase.FboTestCase.prototype.getCurrentContext = function() {
+ return this.m_curCtx;
+ };
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ */
+ es3fFboTestCase.FboTestCase.prototype.compare = function(reference, result) {
+ return tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), 0.05, tcuImageCompare.CompareLogMode.RESULT);
+ };
+
+ /**
+ * @param {number} sizedFormat
+ */
+ es3fFboTestCase.FboTestCase.prototype.checkFormatSupport = function(sizedFormat) {
+ /** @const @type {boolean} */ var isCoreFormat = es3fFboTestCase.isRequiredFormat(sizedFormat);
+ /** @const @type {Array<string>} */ var requiredExts = (!isCoreFormat) ? es3fFboTestCase.getEnablingExtensions(sizedFormat) : [];
+
+ // Check that we don't try to use invalid formats.
+ DE_ASSERT(isCoreFormat || requiredExts);
+ if (requiredExts.length > 0 && !es3fFboTestCase.isAnyExtensionSupported(gl, requiredExts)) {
+ var msg = 'SKIP: Format ' + WebGLTestUtils.glEnumToString(gl, sizedFormat) + ' not supported';
+ debug(msg);
+ throw new TestFailedException(msg);
+ }
+ };
+
+ /**
+ * @param {number} sizedFormat deUint32
+ * @param {number} numSamples
+ */
+ es3fFboTestCase.FboTestCase.prototype.checkSampleCount = function(sizedFormat, numSamples) {
+ /** @const @type {number} */ var minSampleCount = es3fFboTestCase.getMinimumSampleCount(sizedFormat);
+
+ if (numSamples > minSampleCount) {
+ // Exceeds spec-mandated minimum - need to check.
+ /** @const @type {goog.NumberArray} */ var supportedSampleCounts = es3fFboTestCase.querySampleCounts(sizedFormat);
+ var supported = Array.prototype.slice.call(supportedSampleCounts);
+ if (supported.indexOf(numSamples) == -1) {
+ if (minSampleCount == 0 || numSamples > gl.getParameter(gl.MAX_SAMPLES)) {
+ checkMessage(false, "Sample count not supported, but it is allowed.");
+ return false;
+ } else {
+ throw new Error('Sample count not supported');
+ }
+ }
+ return true;
+ }
+ return true;
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {tcuTexture.TextureFormat} format
+ * @param {Array<number>} scale Vec4
+ * @param {Array<number>} bias Vec4
+ */
+ es3fFboTestCase.FboTestCase.prototype.readPixelsUsingFormat = function(dst, x, y, width, height, format, scale, bias) {
+ dst.setSize(width, height);
+ es3fFboTestUtil.readPixels(this.getCurrentContext(), dst, x, y, width, height, format, scale, bias);
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fFboTestCase.FboTestCase.prototype.readPixels = function(dst, x, y, width, height) {
+ dst.readViewport(this.getCurrentContext(), [x, y, width, height]);
+ };
+
+ /**
+ * @param {number} target
+ */
+ es3fFboTestCase.FboTestCase.prototype.checkFramebufferStatus = function(target) {
+ /** @type {number} */ var status = this.getCurrentContext().checkFramebufferStatus(target);
+ if (status != gl.FRAMEBUFFER_COMPLETE)
+ throw new Error('Framebuffer Status: ' + WebGLTestUtils.glEnumToString(gl, status));
+ };
+
+ es3fFboTestCase.FboTestCase.prototype.checkError = function() {
+ /** @type {number} */ var err = this.getCurrentContext().getError();
+ if (err != gl.NO_ERROR)
+ throw new Error('glError: ' + WebGLTestUtils.glEnumToString(gl, err));
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @param {Array<number>=} value Vec4
+ */
+ es3fFboTestCase.FboTestCase.prototype.clearColorBuffer = function(format, value) {
+ if (value === undefined) value = [0.0, 0.0, 0.0, 0.0];
+ es3fFboTestUtil.clearColorBuffer(this.getCurrentContext(), format, value);
+ };
+
+ es3fFboTestCase.FboTestCase.prototype.iterate = function() {
+ // Viewport.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+ /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, this.m_viewportWidth);
+ /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, this.m_viewportHeight);
+ /** @type {number} */ var x = rnd.getInt(0, gl.drawingBufferWidth - width);
+ /** @type {number} */ var y = rnd.getInt(0, gl.drawingBufferHeight - height);
+
+ // Surface format and storage is choosen by render().
+ /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var result = new tcuSurface.Surface(width, height);
+
+ // Call preCheck() that can throw exception if some requirement is not met.
+ if (this.preCheck && !this.preCheck())
+ return tcuTestCase.IterateResult.STOP;
+
+ // Render using GLES3.
+ try {
+ /** @type {sglrGLContext.GLContext} */ var context = new sglrGLContext.GLContext(
+ gl,
+ [x, y, width, height]);
+
+ this.setContext(context);
+ this.render(result);
+
+ // Check error.
+ /** @type {number} */ var err = context.getError();
+ if (err != gl.NO_ERROR)
+ throw new Error('glError: ' + context);
+
+ this.setContext(null);
+ } catch (e) {
+ if (e instanceof es3fFboTestUtil.FboIncompleteException)
+ if (e.getReason() == gl.FRAMEBUFFER_UNSUPPORTED) {
+ // log << e;
+ // m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, 'Not supported');
+ assertMsgOptions(false, 'Not supported', true, false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ throw e;
+ }
+
+ // Render reference.
+ var alphaBits = /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS));
+ /** @type {sglrReferenceContext.ReferenceContextBuffers} */
+ var buffers = new sglrReferenceContext.ReferenceContextBuffers(new tcuPixelFormat.PixelFormat(
+ 8,
+ 8,
+ 8,
+ alphaBits > 0 ? 8 : 0),
+ /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS)),
+ /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS)),
+ width,
+ height);
+ /** @type {sglrReferenceContext.ReferenceContext} */
+ var refContext = new sglrReferenceContext.ReferenceContext(new sglrReferenceContext.ReferenceContextLimits(gl),
+ buffers.getColorbuffer(),
+ buffers.getDepthbuffer(),
+ buffers.getStencilbuffer());
+ refContext.getError();
+ this.setContext(refContext);
+ this.render(reference);
+ this.setContext(null);
+
+ /** @type {boolean} */ var isOk = this.compare(reference, result);
+
+ assertMsgOptions(isOk, '', true, false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * Deinit. Clear some GL state variables
+ */
+ es3fFboTestCase.FboTestCase.prototype.deinit = function () {
+ // Pixel operations
+ {
+ gl.disable(gl.SCISSOR_TEST);
+
+ gl.disable(gl.STENCIL_TEST);
+ gl.stencilFunc(gl.ALWAYS, 0, 0xffff);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LESS);
+
+ gl.disable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ZERO);
+ gl.blendEquation(gl.FUNC_ADD);
+ gl.blendColor(0.0, 0.0, 0.0, 0.0);
+
+ gl.enable(gl.DITHER);
+ }
+
+ // Framebuffer control
+ {
+ gl.colorMask(true, true, true, true);
+ gl.depthMask(true);
+ gl.stencilMask(0xffff);
+
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clearDepth(1.0);
+ gl.clearStencil(0.0);
+ // Do not call clear() here because it might generate an INVALID_OPERATION if
+ // some color buffers are of integer formats due to WebGL2 specific constraint.
+ // The tests do not rely on clear() here.
+ }
+ };
+
+ /**
+ * @param {number} format
+ * @return {boolean}
+ */
+ es3fFboTestCase.isRequiredFormat = function(format) {
+ switch (format) {
+ // Color-renderable formats
+ case gl.RGBA32I:
+ case gl.RGBA32UI:
+ case gl.RGBA16I:
+ case gl.RGBA16UI:
+ case gl.RGBA8:
+ case gl.RGBA8I:
+ case gl.RGBA8UI:
+ case gl.SRGB8_ALPHA8:
+ case gl.RGB10_A2:
+ case gl.RGB10_A2UI:
+ case gl.RGBA4:
+ case gl.RGB5_A1:
+ case gl.RGB8:
+ case gl.RGB565:
+ case gl.RG32I:
+ case gl.RG32UI:
+ case gl.RG16I:
+ case gl.RG16UI:
+ case gl.RG8:
+ case gl.RG8I:
+ case gl.RG8UI:
+ case gl.R32I:
+ case gl.R32UI:
+ case gl.R16I:
+ case gl.R16UI:
+ case gl.R8:
+ case gl.R8I:
+ case gl.R8UI:
+ return true;
+
+ // Depth formats
+ case gl.DEPTH_COMPONENT32F:
+ case gl.DEPTH_COMPONENT24:
+ case gl.DEPTH_COMPONENT16:
+ return true;
+
+ // Depth+stencil formats
+ case gl.DEPTH32F_STENCIL8:
+ case gl.DEPTH24_STENCIL8:
+ return true;
+
+ // Stencil formats
+ case gl.STENCIL_INDEX8:
+ return true;
+
+ default:
+ return false;
+ }
+ };
+
+ /**
+ * @param {number} format deUint32
+ * @return {Array<string>}
+ */
+ es3fFboTestCase.getEnablingExtensions = function(format) {
+ /** @return {Array<string>} */ var out = [];
+
+ DE_ASSERT(!es3fFboTestCase.isRequiredFormat(format));
+
+ switch (format) {
+ case gl.RGBA16F:
+ case gl.RG16F:
+ case gl.R16F:
+ case gl.RGBA32F:
+ case gl.RGB32F:
+ case gl.R11F_G11F_B10F:
+ case gl.RG32F:
+ case gl.R32F:
+ out.push('EXT_color_buffer_float');
+ break;
+ case gl.RGB16F:
+ // EXT_color_buffer_half_float is not exposed in WebGL 2.0.
+ break;
+ default:
+ break;
+ }
+
+ return out;
+ };
+
+ /**
+ * @param {es3fFboTestCase.Context} context
+ * @param {Array<string>} requiredExts
+ * @return {boolean}
+ */
+ es3fFboTestCase.isAnyExtensionSupported = function(context, requiredExts) {
+ for (var iter in requiredExts) {
+ /** @const @type {string} */ var extension = requiredExts[iter];
+
+ if (sglrGLContext.isExtensionSupported(gl, extension)) {
+ // enable the extension
+ gl.getExtension(extension);
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+/**
+ * @param {number} format GL format
+ * @return {number}
+ */
+es3fFboTestCase.getMinimumSampleCount = function(format) {
+ switch (format) {
+ // Core formats
+ case gl.RGBA32I:
+ case gl.RGBA32UI:
+ case gl.RGBA16I:
+ case gl.RGBA16UI:
+ case gl.RGBA8:
+ case gl.RGBA8I:
+ case gl.RGBA8UI:
+ case gl.SRGB8_ALPHA8:
+ case gl.RGB10_A2:
+ case gl.RGB10_A2UI:
+ case gl.RGBA4:
+ case gl.RGB5_A1:
+ case gl.RGB8:
+ case gl.RGB565:
+ case gl.RG32I:
+ case gl.RG32UI:
+ case gl.RG16I:
+ case gl.RG16UI:
+ case gl.RG8:
+ case gl.RG8I:
+ case gl.RG8UI:
+ case gl.R32I:
+ case gl.R32UI:
+ case gl.R16I:
+ case gl.R16UI:
+ case gl.R8:
+ case gl.R8I:
+ case gl.R8UI:
+ case gl.DEPTH_COMPONENT32F:
+ case gl.DEPTH_COMPONENT24:
+ case gl.DEPTH_COMPONENT16:
+ case gl.DEPTH32F_STENCIL8:
+ case gl.DEPTH24_STENCIL8:
+ case gl.STENCIL_INDEX8:
+ return 4;
+
+ // gl.EXT_color_buffer_float
+ case gl.R11F_G11F_B10F:
+ case gl.RG16F:
+ case gl.R16F:
+ return 4;
+
+ case gl.RGBA32F:
+ case gl.RGBA16F:
+ case gl.RG32F:
+ case gl.R32F:
+ return 0;
+
+ // gl.EXT_color_buffer_half_float
+ case gl.RGB16F:
+ return 0;
+
+ default:
+ throw new Error('Unknown format:' + format);
+ }
+};
+
+es3fFboTestCase.querySampleCounts = function(format) {
+ return gl.getInternalformatParameter(gl.RENDERBUFFER, format, gl.SAMPLES);
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestUtil.js
new file mode 100644
index 0000000000..ed152a43e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboTestUtil.js
@@ -0,0 +1,1324 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFboTestUtil');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuRGBA = framework.common.tcuRGBA;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var deMath = framework.delibs.debase.deMath;
+var rrShadingContext = framework.referencerenderer.rrShadingContext;
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+var tcuMatrix = framework.common.tcuMatrix;
+var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+var tcuSurface = framework.common.tcuSurface;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/**
+ * Defines the exception type for a test failure.
+ * @constructor
+ * @param {number} reason The error code.
+ */
+es3fFboTestUtil.FboIncompleteException = function(reason) {
+ this.reason = reason;
+ this.name = 'es3fFboTestUtil.FboIncompleteException';
+};
+
+/** @typedef { (WebGL2RenderingContext|sglrReferenceContext.ReferenceContext)} */
+es3fFboTestUtil.Context;
+
+es3fFboTestUtil.FboIncompleteException.prototype.getReason = function() {return this.reason; };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @return {rrGenericVector.GenericVecType}
+ */
+ es3fFboTestUtil.mapDataTypeToGenericVecType = function(type) {
+ switch (type) {
+ case gluShaderUtil.DataType.FLOAT_VEC4: return rrGenericVector.GenericVecType.FLOAT;
+ case gluShaderUtil.DataType.INT_VEC4: return rrGenericVector.GenericVecType.INT32;
+ case gluShaderUtil.DataType.UINT_VEC4: return rrGenericVector.GenericVecType.UINT32;
+ default:
+ throw new Error('Unrecognized type: ' + type);
+ }
+ };
+
+ /**
+ * @param {Array<number>} input
+ * @param {{max: number, min: number}} type min, max information
+ * @return {Array<number>}
+ */
+ es3fFboTestUtil.castVectorSaturate = function(input, type) {
+ return [
+ (input[0] + 0.5 >= type.max) ? (type.max) : ((input[0] - 0.5 <= type.min) ? (type.min) : Math.round(input[0])),
+ (input[1] + 0.5 >= type.max) ? (type.max) : ((input[1] - 0.5 <= type.min) ? (type.min) : Math.round(input[1])),
+ (input[2] + 0.5 >= type.max) ? (type.max) : ((input[2] - 0.5 <= type.min) ? (type.min) : Math.round(input[2])),
+ (input[3] + 0.5 >= type.max) ? (type.max) : ((input[3] - 0.5 <= type.min) ? (type.min) : Math.round(input[3]))
+ ];
+ };
+
+ /**
+ * es3fFboTestUtil.FlatColorShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {gluShaderUtil.DataType} outputType
+ * @param {number=} pointSize
+ */
+ es3fFboTestUtil.FlatColorShader = function(outputType, pointSize) {
+ pointSize = pointSize || 1;
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+ /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
+
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_color', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' gl_PointSize = ' + pointSize + '.0;\n' +
+ '}\n'));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(u_color);\n' +
+ '}\n'));
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ this.m_pointSize = pointSize;
+ };
+
+ es3fFboTestUtil.FlatColorShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.FlatColorShader.prototype.constructor = es3fFboTestUtil.FlatColorShader;
+
+ /**
+ * @param {(WebGL2RenderingContext|sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext)} context
+ * @param program GL program object
+ * @param {Array<number>} color
+ */
+ es3fFboTestUtil.FlatColorShader.prototype.setColor = function(context, program, color) {
+ /** @type {number} */ var location = context.getUniformLocation(program, 'u_color');
+
+ context.useProgram(program);
+ context.uniform4fv(location, color);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.FlatColorShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.pointSize = this.m_pointSize;
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.FlatColorShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @const {Array<number>} */ var color = this.m_uniforms[0].value;
+ /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx)
+ packet[packetNdx].value = color;
+ } else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx)
+ packet[packetNdx].value = icolor;
+ } else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx)
+ packet[packetNdx].value = uicolor;
+ } else
+ throw new Error('Invalid output type: ' + this.m_outputType);
+ };
+
+ /**
+ * es3fFboTestUtil.GradientShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {gluShaderUtil.DataType} outputType
+ */
+ es3fFboTestUtil.GradientShader = function(outputType) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+ /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_gradientMin', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_gradientMax', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coord;\n' +
+ 'out highp vec4 v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n'));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'in highp vec4 v_coord;\n' +
+ 'uniform highp vec4 u_gradientMin;\n' +
+ 'uniform highp vec4 u_gradientMax;\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' highp float x = v_coord.x;\n' +
+ ' highp float y = v_coord.y;\n' +
+ ' highp float f0 = (x + y) * 0.5;\n' +
+ ' highp float f1 = 0.5 + (x - y) * 0.5;\n' +
+ ' highp vec4 fv = vec4(f0, f1, 1.0f-f0, 1.0f-f1);\n' +
+ ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(u_gradientMin + (u_gradientMax-u_gradientMin)*fv);\n' +
+ '}\n'));
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ };
+
+ es3fFboTestUtil.GradientShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.GradientShader.prototype.constructor = es3fFboTestUtil.GradientShader;
+
+ /**
+ * @param {es3fFboTestUtil.Context} ctx GL-like context
+ * @param program GL program
+ * @param {Array<number>} gradientMin
+ * @param {Array<number>} gradientMax
+ */
+ es3fFboTestUtil.GradientShader.prototype.setGradient = function(ctx, program, gradientMin, gradientMax) {
+ ctx.useProgram(program);
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_gradientMin'), gradientMin);
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_gradientMax'), gradientMax);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.GradientShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.GradientShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @const {Array<number>} */ var gradientMin = this.m_uniforms[0].value;
+ /** @const {Array<number>} */ var gradientMax = this.m_uniforms[1].value;
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
+ /** @const {number} */ var x = coord[0];
+ /** @const {number} */ var y = coord[1];
+ /** @const {number} */ var f0 = (x + y) * 0.5;
+ /** @const {number} */ var f1 = 0.5 + (x - y) * 0.5;
+ /** @const {Array<number>} */ var fv = [f0, f1, 1.0 - f0, 1.0 - f1];
+
+ /** @const {Array<number>} */ var color = deMath.add(gradientMin, deMath.multiply(deMath.subtract(gradientMax, gradientMin), fv));
+ /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
+ packet[packetNdx].value = color;
+ else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
+ packet[packetNdx].value = icolor;
+ else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
+ packet[packetNdx].value = uicolor;
+ else
+ throw new Error('Invalid output type: ' + this.m_outputType);
+ }
+ };
+
+ /**
+ * @param {Array<gluShaderUtil.DataType>} samplerTypes
+ * @param {gluShaderUtil.DataType} outputType
+ * @return {string}
+ */
+ es3fFboTestUtil.genTexFragmentShader = function(samplerTypes, outputType) {
+ /** @type {string} */ var precision = 'highp';
+ /** @type {string} */ var src = '';
+
+ src = '#version 300 es\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color0;\n' +
+ 'in highp vec2 v_coord;\n';
+
+ for (var samplerNdx = 0; samplerNdx < samplerTypes.length; samplerNdx++) {
+ src += 'uniform ' + precision + ' ' + gluShaderUtil.getDataTypeName(samplerTypes[samplerNdx]) + ' u_sampler' + samplerNdx + ';\n' +
+ 'uniform ' + precision + ' vec4 u_texScale' + samplerNdx + ';\n' +
+ 'uniform ' + precision + ' vec4 u_texBias' + samplerNdx + ';\n';
+ }
+
+ // Output scale & bias
+ src += 'uniform ' + precision + ' vec4 u_outScale0;\n' +
+ 'uniform ' + precision + ' vec4 u_outBias0;\n';
+
+ src += '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ' + precision + ' vec4 out0 = vec4(0.0);\n';
+
+ // Texture input fetch and combine.
+ for (var inNdx = 0; inNdx < samplerTypes.length; inNdx++)
+ src += '\tout0 += vec4(' +
+ 'texture(u_sampler' + inNdx + ', v_coord)) * u_texScale' + inNdx + ' + u_texBias' + inNdx + ';\n';
+
+ // Write output.
+ src += ' o_color0 = ' + gluShaderUtil.getDataTypeName(outputType) + '(out0 * u_outScale0 + u_outBias0);\n' +
+ '}\n';
+
+ return src;
+ };
+
+ /**
+ * @param {Array<gluShaderUtil.DataType>} samplerTypes
+ * @param {gluShaderUtil.DataType} outputType
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ es3fFboTestUtil.genTexture2DShaderDecl = function(samplerTypes, outputType) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec2 a_coord;\n' +
+ 'out highp vec2 v_coord;\n' +
+ 'void main(void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n'));
+
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(es3fFboTestUtil.genTexFragmentShader(samplerTypes, outputType)));
+
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_outScale0', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_outBias0', gluShaderUtil.DataType.FLOAT_VEC4));
+
+ for (var ndx = 0; ndx < samplerTypes.length; ++ndx) {
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler' + ndx, samplerTypes[ndx]));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_texScale' + ndx, gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_texBias' + ndx, gluShaderUtil.DataType.FLOAT_VEC4));
+ }
+
+ return decl;
+ };
+
+ /**
+ * For use in es3fFboTestUtil.Texture2DShader
+ * @constructor
+ */
+ es3fFboTestUtil.Input = function() {
+ /** @type {number} */ this.unitNdx;
+ /** @type {Array<number>} */ this.scale;
+ /** @type {Array<number>} */ this.bias;
+ };
+
+ /**
+ * es3fFboTestUtil.Texture2DShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {Array<gluShaderUtil.DataType>} samplerTypes
+ * @param {gluShaderUtil.DataType} outputType
+ * @param {Array<number>=} outScale - default [1.0, 1.0, 1.0, 1.0]
+ * @param {Array<number>=} outBias - default [0.0, 0.0, 0.0, 0.0]
+ */
+ es3fFboTestUtil.Texture2DShader = function(samplerTypes, outputType, outScale, outBias) {
+ if (outScale === undefined) outScale = [1.0, 1.0, 1.0, 1.0];
+ if (outBias === undefined) outBias = [0.0, 0.0, 0.0, 0.0];
+ sglrShaderProgram.ShaderProgram.call(this, es3fFboTestUtil.genTexture2DShaderDecl(samplerTypes, outputType));
+ /** @type {Array<es3fFboTestUtil.Input>} */ this.m_inputs = [];
+ /** @type {Array<number>} */ this.m_outScale = outScale;
+ /** @type {Array<number>} */ this.m_outBias = outBias;
+ /** @const {gluShaderUtil.DataType} */ this.m_outputType = outputType;
+ for (var ndx = 0; ndx < samplerTypes.length; ndx++) {
+ var input = new es3fFboTestUtil.Input();
+ input.unitNdx = ndx;
+ input.scale = [1.0, 1.0, 1.0, 1.0];
+ input.bias = [0.0, 0.0, 0.0, 0.0];
+ this.m_inputs[ndx] = input;
+ }
+ };
+
+ es3fFboTestUtil.Texture2DShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.Texture2DShader.prototype.constructor = es3fFboTestUtil.Texture2DShader;
+
+ /**
+ * @param {number} inputNdx
+ * @param {number} unitNdx
+ */
+ es3fFboTestUtil.Texture2DShader.prototype.setUnit = function(inputNdx, unitNdx) {
+ this.m_inputs[inputNdx].unitNdx = unitNdx;
+ };
+
+ /**
+ * @param {number} inputNdx
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+ es3fFboTestUtil.Texture2DShader.prototype.setTexScaleBias = function(inputNdx, scale, bias) {
+ this.m_inputs[inputNdx].scale = scale;
+ this.m_inputs[inputNdx].bias = bias;
+ };
+
+ /**
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+ es3fFboTestUtil.Texture2DShader.prototype.setOutScaleBias = function(scale, bias) {
+ this.m_outScale = scale;
+ this.m_outBias = bias;
+ };
+
+ /**
+ * @param context GL-like context
+ * @param program
+ */
+ es3fFboTestUtil.Texture2DShader.prototype.setUniforms = function(context, program) {
+ context.useProgram(program);
+
+ for (var texNdx = 0; texNdx < this.m_inputs.length; texNdx++) {
+ /** @type {string} */ var samplerName = 'u_sampler' + texNdx;
+ /** @type {string} */ var scaleName = 'u_texScale' + texNdx;
+ /** @type {string} */ var biasName = 'u_texBias' + texNdx;
+
+ context.uniform1i(context.getUniformLocation(program, samplerName), this.m_inputs[texNdx].unitNdx);
+ context.uniform4fv(context.getUniformLocation(program, scaleName), this.m_inputs[texNdx].scale);
+ context.uniform4fv(context.getUniformLocation(program, biasName), this.m_inputs[texNdx].bias);
+ }
+
+ context.uniform4fv(context.getUniformLocation(program, 'u_outScale0'), this.m_outScale);
+ context.uniform4fv(context.getUniformLocation(program, 'u_outBias0'), this.m_outBias);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.Texture2DShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ // TODO: implement rrVertexAttrib.readVertexAttribFloat
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.Texture2DShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @type {Array<number>} */ var outScale = this.m_uniforms[0].value;
+ /** @type {Array<number>} */ var outBias = this.m_uniforms[1].value;
+ var texCoords = [];
+ var colors = [];
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ // setup tex coords
+ /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
+ texCoords = [coord[0], coord[1]];
+
+ // clear result
+ colors = [0.0, 0.0, 0.0, 0.0];
+
+ // sample each texture
+ for (var ndx = 0; ndx < this.m_inputs.length; ndx++) {
+ var tex = this.m_uniforms[2 + ndx * 3].sampler;
+ var ratioX = tex.m_view.getWidth() / context.getWidth();
+ var ratioY = tex.m_view.getHeight() / context.getHeight();
+ var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
+
+ /** @const {Array<number>} */ var scale = this.m_uniforms[2 + ndx * 3 + 1].value;
+ /** @const {Array<number>} */ var bias = this.m_uniforms[2 + ndx * 3 + 2].value;
+
+ var tmpColors = tex.sample(texCoords, lod);
+
+ colors = deMath.add(colors, deMath.add(deMath.multiply(tmpColors, scale), bias));
+ }
+
+ // write out
+ /** @const {Array<number>} */ var color = deMath.add(deMath.multiply(colors, outScale), outBias);
+ /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
+ packet[packetNdx].value = color;
+ else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
+ packet[packetNdx].value = icolor;
+ else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
+ packet[packetNdx].value = uicolor;
+ }
+ };
+
+ /**
+ * es3fFboTestUtil.TextureCubeShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {gluShaderUtil.DataType} samplerType
+ * @param {gluShaderUtil.DataType} outputType
+ */
+ es3fFboTestUtil.TextureCubeShader = function(samplerType, outputType) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_coordMat', gluShaderUtil.DataType.FLOAT_MAT3));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler0', samplerType));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_scale', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_bias', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in mediump vec2 a_coord;\n' +
+ 'uniform mat3 u_coordMat;\n' +
+ 'out mediump vec3 v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = u_coordMat * vec3(a_coord, 1.0);\n' +
+ '}\n'));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler0;\n' +
+ 'uniform highp vec4 u_scale;\n' +
+ 'uniform highp vec4 u_bias;\n' +
+ 'in mediump vec3 v_coord;\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(vec4(texture(u_sampler0, v_coord)) * u_scale + u_bias);\n' +
+ '}\n'));
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ /** @type {Array<number>} */ this.m_texScale = [1.0, 1.0, 1.0, 1.0];
+ /** @type {Array<number>} */ this.m_texBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {tcuMatrix.Mat3} */ this.m_coordMat;
+ /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
+ };
+
+ es3fFboTestUtil.TextureCubeShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.TextureCubeShader.prototype.constructor = es3fFboTestUtil.TextureCubeShader;
+
+ /**
+ * @param {tcuTexture.CubeFace} face
+ */
+ es3fFboTestUtil.TextureCubeShader.prototype.setFace = function(face) {
+ /** @const {Array<Array<number>>} */ var s_cubeTransforms = [
+ // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
+ [0, 0, -1,
+ 0, -2, 1,
+ 2, 0, -1],
+ // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
+ [0, 0, 1,
+ 0, -2, 1,
+ -2, 0, 1],
+ // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
+ [2, 0, -1,
+ 0, 0, -1,
+ 0, -2, 1],
+ // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
+ [2, 0, -1,
+ 0, 0, 1,
+ 0, 2, -1],
+ // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
+ [-2, 0, 1,
+ 0, -2, 1,
+ 0, 0, -1],
+ // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
+ [2, 0, -1,
+ 0, -2, 1,
+ 0, 0, 1]];
+ this.m_coordMat = /** @type {tcuMatrix.Mat3} */ (tcuMatrix.matrixFromArray(3, 3, s_cubeTransforms[face]));
+ };
+
+ /**
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+ es3fFboTestUtil.TextureCubeShader.prototype.setTexScaleBias = function(scale, bias) {
+ this.m_texScale = scale;
+ this.m_texBias = bias;
+ };
+
+ /**
+ * @param ctx GL-like context
+ * @param program
+ */
+ es3fFboTestUtil.TextureCubeShader.prototype.setUniforms = function(ctx, program) {
+ ctx.useProgram(program);
+
+ ctx.uniform1i(ctx.getUniformLocation(program, 'u_sampler0'), 0);
+ ctx.uniformMatrix3fv(ctx.getUniformLocation(program, 'u_coordMat'), false, this.m_coordMat.getColumnMajorData());
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_scale'), this.m_texScale);
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_bias'), this.m_texBias);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.TextureCubeShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ /** @type {tcuMatrix.Matrix} */ var texCoordMat = tcuMatrix.matrixFromArray(3, 3, this.m_uniforms[0].value);
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+ var x = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT)[0];
+ var y = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT)[1];
+ /** @type {Array<number>} */ var a_coord = [x, y];
+ /** @type {Array<number>} */ var v_coord = tcuMatrix.multiplyMatVec(texCoordMat, [a_coord[0], a_coord[1], 1.0]);
+
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.outputs[0] = [v_coord[0], v_coord[1], v_coord[2], 0.0];
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.TextureCubeShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @const {Array<number>} */ var texScale = this.m_uniforms[2].value;
+ /** @const {Array<number>} */ var texBias = this.m_uniforms[3].value;
+
+ var texCoords = [];
+ var colors = [];
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ var tex = this.m_uniforms[1].sampler;
+ var ratioX = tex.m_view.getSize() / context.getWidth();
+ var ratioY = tex.m_view.getSize() / context.getHeight();
+ var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
+
+ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
+ texCoords = [coord[0], coord[1], coord[2]];
+
+ colors = tex.sample(texCoords, lod);
+
+ var color = deMath.add(deMath.multiply(colors, texScale), texBias);
+ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
+ packet[packetNdx].value = color;
+ else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
+ packet[packetNdx].value = icolor;
+ else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
+ packet[packetNdx].value = uicolor;
+ }
+ };
+
+ /**
+ * es3fFboTestUtil.Texture2DArrayShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {gluShaderUtil.DataType} samplerType
+ * @param {gluShaderUtil.DataType} outputType
+ */
+ es3fFboTestUtil.Texture2DArrayShader = function(samplerType, outputType) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler0', samplerType));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_scale', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_bias', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_layer', gluShaderUtil.DataType.INT));
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec2 a_coord;\n' +
+ 'out highp vec2 v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n'));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler0;\n' +
+ 'uniform highp vec4 u_scale;\n' +
+ 'uniform highp vec4 u_bias;\n' +
+ 'uniform highp int u_layer;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(vec4(texture(u_sampler0, vec3(v_coord, u_layer))) * u_scale + u_bias);\n' +
+ '}\n'));
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ /** @type {Array<number>} */ this.m_texScale = [1.0, 1.0, 1.0, 1.0];
+ /** @type {Array<number>} */ this.m_texBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {number} */ this.m_layer = 0;
+ /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
+ };
+
+ es3fFboTestUtil.Texture2DArrayShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.Texture2DArrayShader.prototype.constructor = es3fFboTestUtil.Texture2DArrayShader;
+
+ /**
+ * @param {number} layer
+ */
+ es3fFboTestUtil.Texture2DArrayShader.prototype.setLayer = function(layer) {
+ this.m_layer = layer;
+ };
+ /**
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+ es3fFboTestUtil.Texture2DArrayShader.prototype.setTexScaleBias = function(scale, bias) {
+ this.m_texScale = scale;
+ this.m_texBias = bias;
+ };
+ /**
+ * @param {es3fFboTestUtil.Context} ctx GL-like context
+ * @param program
+ */
+ es3fFboTestUtil.Texture2DArrayShader.prototype.setUniforms = function(ctx, program) {
+ ctx.useProgram(program);
+
+ ctx.uniform1i(ctx.getUniformLocation(program, 'u_sampler0'), 0);
+ ctx.uniform1i(ctx.getUniformLocation(program, 'u_layer'), this.m_layer);
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_scale'), this.m_texScale);
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_bias'), this.m_texBias);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.Texture2DArrayShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.Texture2DArrayShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @const {Array<number>} */ var texScale = this.m_uniforms[1].value;
+ /** @const {Array<number>} */ var texBias = this.m_uniforms[2].value;
+ /** @const {number} */ var layer = this.m_uniforms[3].value[0];
+
+ var texCoords = [];
+ var colors = [];
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ var tex = this.m_uniforms[0].sampler;
+ var ratioX = tex.m_view.getWidth() / context.getWidth();
+ var ratioY = tex.m_view.getHeight() / context.getHeight();
+ var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
+
+ /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
+ texCoords = [coord[0], coord[1], layer];
+
+ colors = tex.sample(texCoords, lod);
+
+ /** @const {Array<number>} */ var color = deMath.add(deMath.multiply(colors, texScale), texBias);
+ /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
+ packet[packetNdx].value = color;
+ else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
+ packet[packetNdx].value = icolor;
+ else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
+ packet[packetNdx].value = uicolor;
+ }
+ };
+
+ /**
+ * es3fFboTestUtil.Texture3DShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {gluShaderUtil.DataType} samplerType
+ * @param {gluShaderUtil.DataType} outputType
+ */
+ es3fFboTestUtil.Texture3DShader = function(samplerType, outputType) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler0', samplerType));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_scale', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_bias', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_depth', gluShaderUtil.DataType.FLOAT));
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec2 a_coord;\n' +
+ 'out highp vec2 v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n'));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler0;\n' +
+ 'uniform highp vec4 u_scale;\n' +
+ 'uniform highp vec4 u_bias;\n' +
+ 'uniform highp float u_depth;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(vec4(texture(u_sampler0, vec3(v_coord, u_depth))) * u_scale + u_bias);\n' +
+ '}\n'));
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ /** @type {Array<number>} */ this.m_texScale = [1.0, 1.0, 1.0, 1.0];
+ /** @type {Array<number>} */ this.m_texBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {number} */ this.m_depth = 0.0;
+ /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
+ };
+
+ es3fFboTestUtil.Texture3DShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.Texture3DShader.prototype.constructor = es3fFboTestUtil.Texture3DShader;
+
+ /**
+ * @param {number} depth
+ */
+ es3fFboTestUtil.Texture3DShader.prototype.setDepth = function(depth) {
+ this.m_depth = depth;
+ };
+
+ /**
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+ es3fFboTestUtil.Texture3DShader.prototype.setTexScaleBias = function(scale, bias) {
+ this.m_texScale = scale;
+ this.m_texBias = bias;
+ };
+
+ /**
+ * @param context GL-like context
+ * @param program
+ */
+ es3fFboTestUtil.Texture3DShader.prototype.setUniforms = function(context, program) {
+ context.useProgram(program);
+ context.uniform1i(context.getUniformLocation(program, 'u_sampler0'), 0);
+ context.uniform1f(context.getUniformLocation(program, 'u_depth'), this.m_depth);
+ context.uniform4fv(context.getUniformLocation(program, 'u_scale'), this.m_texScale);
+ context.uniform4fv(context.getUniformLocation(program, 'u_bias'), this.m_texBias);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.Texture3DShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.Texture3DShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @const {Array<number>} */ var texScale = this.m_uniforms[1].value;
+ /** @const {Array<number>} */ var texBias = this.m_uniforms[2].value;
+ /** @const {number} */ var depth = this.m_uniforms[3].value[0];
+
+ var texCoords = [];
+ var colors = [];
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ var tex = this.m_uniforms[0].sampler;
+ var ratioX = tex.m_view.getWidth() / context.getWidth();
+ var ratioY = tex.m_view.getHeight() / context.getHeight();
+ // TODO: what to do with Z coordinate?
+ var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
+
+ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
+ texCoords = [coord[0], coord[1], depth];
+
+ colors = tex.sample(texCoords, lod);
+
+ /** @const {Array<number>} */ var color = deMath.add(deMath.multiply(colors, texScale), texBias);
+ /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
+ packet[packetNdx].value = color;
+ else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
+ packet[packetNdx].value = icolor;
+ else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
+ packet[packetNdx].value = uicolor;
+ }
+ };
+
+ /**
+ * es3fFboTestUtil.DepthGradientShader inherits from sglrShaderProgram
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {gluShaderUtil.DataType} outputType
+ */
+ es3fFboTestUtil.DepthGradientShader = function(outputType) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
+ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_maxGradient', gluShaderUtil.DataType.FLOAT));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_minGradient', gluShaderUtil.DataType.FLOAT));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_color', gluShaderUtil.DataType.FLOAT_VEC4));
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coord;\n' +
+ 'out highp vec4 v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n'));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
+ '#version 300 es\n' +
+ 'in highp vec4 v_coord;\n' +
+ 'uniform highp float u_minGradient;\n' +
+ 'uniform highp float u_maxGradient;\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' highp float x = v_coord.x;\n' +
+ ' highp float y = v_coord.y;\n' +
+ ' highp float f0 = (x + y) * 0.5;\n' +
+ ' gl_FragDepth = u_minGradient + (u_maxGradient-u_minGradient)*f0;\n' +
+ ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(u_color);\n' +
+ '}\n'));
+ this.m_outputType = outputType;
+ sglrShaderProgram.ShaderProgram.call(this, decl);
+ /** @const {sglrShaderProgram.Uniform} */ this.u_minGradient = this.getUniformByName('u_minGradient');
+ /** @const {sglrShaderProgram.Uniform} */ this.u_maxGradient = this.getUniformByName('u_maxGradient');
+ /** @const {sglrShaderProgram.Uniform} */ this.u_color = this.getUniformByName('u_color');
+ };
+
+ es3fFboTestUtil.DepthGradientShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fFboTestUtil.DepthGradientShader.prototype.constructor = es3fFboTestUtil.DepthGradientShader;
+
+ /**
+ * @param ctx GL-like context
+ * @param program
+ * @param {number} gradientMin
+ * @param {number} gradientMax
+ * @param {Array<number>} color
+ */
+ es3fFboTestUtil.DepthGradientShader.prototype.setUniforms = function(ctx, program, gradientMin, gradientMax, color) {
+ ctx.useProgram(program);
+ ctx.uniform1fv(ctx.getUniformLocation(program, 'u_minGradient'), [gradientMin]);
+ ctx.uniform1fv(ctx.getUniformLocation(program, 'u_maxGradient'), [gradientMax]);
+ ctx.uniform4fv(ctx.getUniformLocation(program, 'u_color'), color);
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ es3fFboTestUtil.DepthGradientShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fFboTestUtil.DepthGradientShader.prototype.shadeFragments = function(packet, context) {
+ var numPackets = packet.length;
+ /** @const {number} */ var gradientMin = this.u_minGradient.value[0];
+ /** @const {number} */ var gradientMax = this.u_maxGradient.value[0];
+ /** @type {Array<number>} */ var color = this.u_color.value;
+ /** @type {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
+ /** @type {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
+ /** @const {number} */ var x = coord[0];
+ /** @const {number} */ var y = coord[1];
+ /** @const {number} */ var f0 = (x + y) * 0.5;
+
+ packet[packetNdx].sampleDepths[0] = gradientMin + (gradientMax - gradientMin) * f0;
+
+ if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
+ packet[packetNdx].value = color;
+ else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
+ packet[packetNdx].value = icolor;
+ else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
+ packet[packetNdx].value = uicolor;
+ }
+ };
+
+ es3fFboTestUtil.getFormatName = function(format) {
+ switch (format) {
+ case gl.RGB565: return 'rgb565';
+ case gl.RGB5_A1: return 'rgb5_a1';
+ case gl.RGBA4: return 'rgba4';
+ case gl.DEPTH_COMPONENT16: return 'depth_component16';
+ case gl.STENCIL_INDEX8: return 'stencil_index8';
+ case gl.RGBA32F: return 'rgba32f';
+ case gl.RGBA32I: return 'rgba32i';
+ case gl.RGBA32UI: return 'rgba32ui';
+ case gl.RGBA16F: return 'rgba16f';
+ case gl.RGBA16I: return 'rgba16i';
+ case gl.RGBA16UI: return 'rgba16ui';
+ case gl.RGBA8: return 'rgba8';
+ case gl.RGBA8I: return 'rgba8i';
+ case gl.RGBA8UI: return 'rgba8ui';
+ case gl.SRGB8_ALPHA8: return 'srgb8_alpha8';
+ case gl.RGB10_A2: return 'rgb10_a2';
+ case gl.RGB10_A2UI: return 'rgb10_a2ui';
+ case gl.RGBA8_SNORM: return 'rgba8_snorm';
+ case gl.RGB8: return 'rgb8';
+ case gl.R11F_G11F_B10F: return 'r11f_g11f_b10f';
+ case gl.RGB32F: return 'rgb32f';
+ case gl.RGB32I: return 'rgb32i';
+ case gl.RGB32UI: return 'rgb32ui';
+ case gl.RGB16F: return 'rgb16f';
+ case gl.RGB16I: return 'rgb16i';
+ case gl.RGB16UI: return 'rgb16ui';
+ case gl.RGB8_SNORM: return 'rgb8_snorm';
+ case gl.RGB8I: return 'rgb8i';
+ case gl.RGB8UI: return 'rgb8ui';
+ case gl.SRGB8: return 'srgb8';
+ case gl.RGB9_E5: return 'rgb9_e5';
+ case gl.RG32F: return 'rg32f';
+ case gl.RG32I: return 'rg32i';
+ case gl.RG32UI: return 'rg32ui';
+ case gl.RG16F: return 'rg16f';
+ case gl.RG16I: return 'rg16i';
+ case gl.RG16UI: return 'rg16ui';
+ case gl.RG8: return 'rg8';
+ case gl.RG8I: return 'rg8i';
+ case gl.RG8UI: return 'rg8ui';
+ case gl.RG8_SNORM: return 'rg8_snorm';
+ case gl.R32F: return 'r32f';
+ case gl.R32I: return 'r32i';
+ case gl.R32UI: return 'r32ui';
+ case gl.R16F: return 'r16f';
+ case gl.R16I: return 'r16i';
+ case gl.R16UI: return 'r16ui';
+ case gl.R8: return 'r8';
+ case gl.R8I: return 'r8i';
+ case gl.R8UI: return 'r8ui';
+ case gl.R8_SNORM: return 'r8_snorm';
+ case gl.DEPTH_COMPONENT32F: return 'depth_component32f';
+ case gl.DEPTH_COMPONENT24: return 'depth_component24';
+ case gl.DEPTH32F_STENCIL8: return 'depth32f_stencil8';
+ case gl.DEPTH24_STENCIL8: return 'depth24_stencil8';
+
+ default:
+ throw new Error('Unknown format in getFromatName()');
+ }
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {gluShaderUtil.DataType}
+ */
+ es3fFboTestUtil.getFragmentOutputType = function(format) {
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return gluShaderUtil.DataType.FLOAT_VEC4;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return gluShaderUtil.DataType.UINT_VEC4;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return gluShaderUtil.DataType.INT_VEC4;
+
+ default:
+ throw new Error('Unknown format');
+ }
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {tcuTexture.TextureFormat}
+ */
+ es3fFboTestUtil.getFramebufferReadFormat = function(format) {
+ switch (tcuTexture.getTextureChannelClass(format.type)) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT);
+
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32);
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT32);
+
+ default:
+ throw new Error('Unknown format in es3fFboTestUtil.getFramebufferReadFormat()');
+ }
+ };
+
+ /**
+ * @param {es3fFboTestUtil.Context} ctx GL-like context
+ * @param {tcuTexture.TextureFormat} format
+ * @param {Array<number>} value
+ */
+ es3fFboTestUtil.clearColorBuffer = function(ctx, format, value) {
+ /** @const @type {tcuTexture.TextureChannelClass} */
+ var fmtClass = tcuTexture.getTextureChannelClass(format.type);
+
+ switch (fmtClass) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ ctx.clearBufferfv(gl.COLOR, 0, value);
+ break;
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ ctx.clearBufferuiv(gl.COLOR, 0, value);
+ break;
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ ctx.clearBufferiv(gl.COLOR, 0, value);
+ break;
+
+ default:
+ throw new Error('Invalid channel class: ' + fmtClass);
+ }
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {tcuRGBA.RGBA}
+ */
+ es3fFboTestUtil.getThresholdFromTextureFormat = function(format) {
+ /** @const @type {Array<number>} */ var bits = tcuTextureUtil.getTextureFormatMantissaBitDepth(format);
+ return tcuRGBA.newRGBAComponents(
+ es3fFboTestUtil.calculateU8ConversionError(bits[0]),
+ es3fFboTestUtil.calculateU8ConversionError(bits[1]),
+ es3fFboTestUtil.calculateU8ConversionError(bits[2]),
+ es3fFboTestUtil.calculateU8ConversionError(bits[3])
+ );
+ };
+
+ /**
+ * @param {number} glFormat
+ * @return {tcuRGBA.RGBA}
+ */
+ es3fFboTestUtil.getFormatThreshold = function(glFormat) {
+ /** @const @type {tcuTexture.TextureFormat} */ var format = gluTextureUtil.mapGLInternalFormat(glFormat);
+ return es3fFboTestUtil.getThresholdFromTextureFormat(format);
+ };
+
+ /**
+ * @param {number} srcBits
+ * @return {number}
+ */
+ es3fFboTestUtil.getToSRGB8ConversionError = function(srcBits) {
+ // \note These are pre-computed based on simulation results.
+ /** @const @type {Array<number>} */ var errors = [
+ 1, // 0 bits - rounding
+ 255, // 1 bits
+ 157, // 2 bits
+ 106, // 3 bits
+ 74, // 4 bits
+ 51, // 5 bits
+ 34, // 6 bits
+ 22, // 7 bits
+ 13, // 8 bits
+ 7, // 9 bits
+ 4, // 10 bits
+ 3, // 11 bits
+ 2 // 12 bits
+ // 1 from this on
+ ];
+
+ DE_ASSERT(srcBits >= 0);
+ if (srcBits < errors.length)
+ return errors[srcBits];
+ else
+ return 1;
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} src
+ * @param {tcuTexture.TextureFormat} dst
+ * @return {tcuRGBA.RGBA}
+ */
+ es3fFboTestUtil.getToSRGBConversionThreshold = function(src, dst) {
+ // Only SRGB8 and SRGB8_ALPHA8 formats are supported.
+ DE_ASSERT(dst.type == tcuTexture.ChannelType.UNORM_INT8);
+ DE_ASSERT(dst.order == tcuTexture.ChannelOrder.sRGB || dst.order == tcuTexture.ChannelOrder.sRGBA);
+
+ /** @const @type {Array<number>} */ var bits = tcuTextureUtil.getTextureFormatMantissaBitDepth(src);
+ /** @const @type {boolean} */ var dstHasAlpha = dst.order == tcuTexture.ChannelOrder.sRGBA;
+
+ return tcuRGBA.newRGBAComponents(
+ es3fFboTestUtil.getToSRGB8ConversionError(bits[0]),
+ es3fFboTestUtil.getToSRGB8ConversionError(bits[1]),
+ es3fFboTestUtil.getToSRGB8ConversionError(bits[2]),
+ dstHasAlpha ? es3fFboTestUtil.calculateU8ConversionError(bits[3]) : 0);
+ };
+
+ /**
+ * es3fFboTestUtil.readPixels()
+ * @param {(WebGL2RenderingContext|sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext)} ctx
+ * @param {tcuSurface.Surface} dst
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {tcuTexture.TextureFormat} format
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+ es3fFboTestUtil.readPixels = function(ctx, dst, x, y, width, height, format, scale, bias) {
+ /** @type {tcuTexture.TextureFormat} */ var readFormat = es3fFboTestUtil.getFramebufferReadFormat(format);
+ /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(readFormat);
+ /** @type {number} */ var alignment = 4; // \note gl.PACK_ALIGNMENT = 4 is assumed.
+ /** @type {number} */ var rowSize = deMath.deAlign32(readFormat.getPixelSize() * width, alignment);
+ var typedArrayType = tcuTexture.getTypedArray(readFormat.type);
+ var data = new typedArrayType(rowSize * height);
+ ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, data);
+
+ // Convert to surface.
+ var cpbaDescriptor = {
+ format: readFormat,
+ width: width,
+ height: height,
+ depth: 1,
+ rowPitch: rowSize,
+ slicePitch: 0,
+ data: data.buffer
+ };
+
+ /** @type {tcuTexture.ConstPixelBufferAccess} */
+ var src = new tcuTexture.ConstPixelBufferAccess(cpbaDescriptor);
+
+ dst.setSize(width, height);
+ /** @type {tcuTexture.PixelBufferAccess} */ var dstAccess = dst.getAccess();
+
+ for (var yo = 0; yo < height; yo++)
+ for (var xo = 0; xo < width; xo++)
+ dstAccess.setPixel(deMath.add(deMath.multiply(src.getPixel(xo, yo), scale), bias), xo, yo);
+ };
+
+ /**
+ * @param {number} srcBits
+ * @return {number}
+ */
+ es3fFboTestUtil.calculateU8ConversionError = function(srcBits) {
+ if (srcBits > 0) {
+ /** @const @type {number} */ var clampedBits = deMath.clamp(srcBits, 0, 8);
+ /** @const @type {number} */ var srcMaxValue = Math.max((1 << clampedBits) - 1, 1);
+ /** @const @type {number} */ var error = Math.floor(Math.ceil(255.0 * 2.0 / srcMaxValue));
+
+ return deMath.clamp(error, 0, 255);
+ } else
+ return 1;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFloatStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFloatStateQueryTests.js
new file mode 100644
index 0000000000..6b5431061e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFloatStateQueryTests.js
@@ -0,0 +1,431 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFloatStateQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+ var es3fFloatStateQueryTests = functional.gles3.es3fFloatStateQueryTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deMath = framework.delibs.debase.deMath;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var glsStateQuery = modules.shared.glsStateQuery;
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.DepthRangeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.DepthRangeCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.DepthRangeCase.prototype.constructor = es3fFloatStateQueryTests.DepthRangeCase;
+
+ es3fFloatStateQueryTests.DepthRangeCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.DEPTH_RANGE, new Float32Array([0.0, 1.0])));
+
+ /** @type {Array<Float32Array>} */ var fixedTests = [
+ new Float32Array([0.5, 1.0]),
+ new Float32Array([0.0, 0.5]),
+ new Float32Array([0.0, 0.0]),
+ new Float32Array([1.0, 1.0])
+ ];
+
+ for (var ndx = 0; ndx < fixedTests.length; ++ndx) {
+ gl.depthRange(fixedTests[ndx][0], fixedTests[ndx][1]);
+ this.check(glsStateQuery.verify(gl.DEPTH_RANGE, fixedTests[ndx]));
+ }
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ // [dag] sorting to keep zNear < zFar
+ /** @type {Array<number>} */ var values = [rnd.getFloat(0, 1), rnd.getFloat(0, 1)].sort();
+ /** @type {Float32Array} */ var depth = new Float32Array(values);
+ gl.depthRange(depth[0], depth[1]);
+ this.check(glsStateQuery.verify(gl.DEPTH_RANGE, depth));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.LineWidthCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.LineWidthCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.LineWidthCase.prototype.constructor = es3fFloatStateQueryTests.LineWidthCase;
+
+ es3fFloatStateQueryTests.LineWidthCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.LINE_WIDTH, 1.0));
+
+ /** @type {Float32Array} */ var range = /** @type {Float32Array} */ (gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE));
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var reference = rnd.getFloat(range[0], range[1]);
+
+ gl.lineWidth(reference);
+ this.check(glsStateQuery.verify(gl.LINE_WIDTH, reference));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.PolygonOffsetFactorCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.PolygonOffsetFactorCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.PolygonOffsetFactorCase.prototype.constructor = es3fFloatStateQueryTests.PolygonOffsetFactorCase;
+
+ es3fFloatStateQueryTests.PolygonOffsetFactorCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.POLYGON_OFFSET_FACTOR, 0.0));
+
+ /** @type {Array<number>} */ var fixedTests = [0.0, 0.5, -0.5, 1.5];
+
+ for (var ndx = 0; ndx < fixedTests.length; ++ndx) {
+ gl.polygonOffset(fixedTests[ndx], 0);
+ this.check(glsStateQuery.verify(gl.POLYGON_OFFSET_FACTOR, fixedTests[ndx]));
+ }
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var reference = rnd.getFloat(-64000, 64000);
+
+ gl.polygonOffset(reference, 0);
+ this.check(glsStateQuery.verify(gl.POLYGON_OFFSET_FACTOR, reference));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.PolygonOffsetUnitsCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.PolygonOffsetUnitsCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.PolygonOffsetUnitsCase.prototype.constructor = es3fFloatStateQueryTests.PolygonOffsetUnitsCase;
+
+ es3fFloatStateQueryTests.PolygonOffsetUnitsCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.POLYGON_OFFSET_UNITS, 0.0));
+
+ /** @type {Array<number>} */ var fixedTests = [0.0, 0.5, -0.5, 1.5];
+
+ for (var ndx = 0; ndx < fixedTests.length; ++ndx) {
+ gl.polygonOffset(0, fixedTests[ndx]);
+ this.check(glsStateQuery.verify(gl.POLYGON_OFFSET_UNITS, fixedTests[ndx]));
+ }
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var reference = rnd.getFloat(-64000, 64000);
+
+ gl.polygonOffset(0, reference);
+ this.check(glsStateQuery.verify(gl.POLYGON_OFFSET_UNITS, reference));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.SampleCoverageCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.SampleCoverageCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.SampleCoverageCase.prototype.constructor = es3fFloatStateQueryTests.SampleCoverageCase;
+
+ es3fFloatStateQueryTests.SampleCoverageCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.SAMPLE_COVERAGE_VALUE, 1.0));
+
+ /** @type {Array<number>} */ var fixedTests = [0.0, 0.5, 0.45, 0.55];
+
+ for (var ndx = 0; ndx < fixedTests.length; ++ndx) {
+ gl.sampleCoverage(fixedTests[ndx], false);
+ this.check(glsStateQuery.verify(gl.SAMPLE_COVERAGE_VALUE, fixedTests[ndx]));
+ }
+
+ /** @type {Array<number>} */ var clampTests = [-1.0, -1.5, 1.45, 3.55];
+
+ for (var ndx = 0; ndx < clampTests.length; ++ndx) {
+ gl.sampleCoverage(clampTests[ndx], false);
+ this.check(glsStateQuery.verify(gl.SAMPLE_COVERAGE_VALUE, deMath.clamp(clampTests[ndx], 0.0, 1.0)));
+ }
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var reference = rnd.getFloat(0, 1);
+ /** @type {boolean} */ var invert = rnd.getBool() ? true : false;
+
+ gl.sampleCoverage(reference, invert);
+ this.check(glsStateQuery.verify(gl.SAMPLE_COVERAGE_VALUE, reference));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.BlendColorCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.BlendColorCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.BlendColorCase.prototype.constructor = es3fFloatStateQueryTests.BlendColorCase;
+
+ es3fFloatStateQueryTests.BlendColorCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.BLEND_COLOR, new Float32Array([0, 0, 0, 0])));
+
+ /** @type {Array<Float32Array>} */ var fixedTests = [
+ new Float32Array([0.5, 1.0, 0.5, 1.0]),
+ new Float32Array([0.0, 0.5, 0.0, 0.5]),
+ new Float32Array([0.0, 0.0, 0.0, 0.0]),
+ new Float32Array([1.0, 1.0, 1.0, 1.0])
+ ];
+ for (var ndx = 0; ndx < fixedTests.length; ++ndx) {
+ gl.blendColor(fixedTests[ndx][0], fixedTests[ndx][1], fixedTests[ndx][2], fixedTests[ndx][3]);
+ this.check(glsStateQuery.verify(gl.BLEND_COLOR, fixedTests[ndx]));
+ }
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var r = rnd.getFloat(0, 1);
+ /** @type {number} */ var g = rnd.getFloat(0, 1);
+ /** @type {number} */ var b = rnd.getFloat(0, 1);
+ /** @type {number} */ var a = rnd.getFloat(0, 1);
+
+ gl.blendColor(r, g, b, a);
+ this.check(glsStateQuery.verify(gl.BLEND_COLOR, new Float32Array([r, g, b, a])));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.ColorClearCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.ColorClearCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.ColorClearCase.prototype.constructor = es3fFloatStateQueryTests.ColorClearCase;
+
+ es3fFloatStateQueryTests.ColorClearCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ // [dag] In the C++ dEQP code, initial color clear value check is temorarily removed. (until the framework does not alter it)
+ this.check(glsStateQuery.verify(gl.COLOR_CLEAR_VALUE, new Float32Array([0, 0, 0, 0])));
+
+ /** @type {Array<Float32Array>} */ var fixedTests = [
+ new Float32Array([0.5, 1.0, 0.5, 1.0]),
+ new Float32Array([0.0, 0.5, 0.0, 0.5]),
+ new Float32Array([0.0, 0.0, 0.0, 0.0]),
+ new Float32Array([1.0, 1.0, 1.0, 1.0])
+ ];
+ for (var ndx = 0; ndx < fixedTests.length; ++ndx) {
+ gl.clearColor(fixedTests[ndx][0], fixedTests[ndx][1], fixedTests[ndx][2], fixedTests[ndx][3]);
+ this.check(glsStateQuery.verify(gl.COLOR_CLEAR_VALUE, fixedTests[ndx]));
+ }
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var r = rnd.getFloat(0, 1);
+ /** @type {number} */ var g = rnd.getFloat(0, 1);
+ /** @type {number} */ var b = rnd.getFloat(0, 1);
+ /** @type {number} */ var a = rnd.getFloat(0, 1);
+
+ gl.clearColor(r, g, b, a);
+ this.check(glsStateQuery.verify(gl.COLOR_CLEAR_VALUE, new Float32Array([r, g, b, a])));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.DepthClearCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.DepthClearCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.DepthClearCase.prototype.constructor = es3fFloatStateQueryTests.DepthClearCase;
+
+ es3fFloatStateQueryTests.DepthClearCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(gl.DEPTH_CLEAR_VALUE, 1));
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var ref = rnd.getFloat(0, 1);
+
+ gl.clearDepth(ref);
+ this.check(glsStateQuery.verify(gl.DEPTH_CLEAR_VALUE, ref));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.MaxTextureLODBiasCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.MaxTextureLODBiasCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.MaxTextureLODBiasCase.prototype.constructor = es3fFloatStateQueryTests.MaxTextureLODBiasCase;
+
+ es3fFloatStateQueryTests.MaxTextureLODBiasCase.prototype.test = function() {
+ this.check(glsStateQuery.verifyGreaterOrEqual(gl.MAX_TEXTURE_LOD_BIAS, 2.0));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.AliasedPointSizeRangeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.AliasedPointSizeRangeCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.AliasedPointSizeRangeCase.prototype.constructor = es3fFloatStateQueryTests.AliasedPointSizeRangeCase;
+
+ es3fFloatStateQueryTests.AliasedPointSizeRangeCase.prototype.test = function() {
+ var pointSizeRange = /** @type {Float32Array} */ (gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE));
+ /** @type {Float32Array} */ var reference = new Float32Array([1, 1]);
+ this.check(pointSizeRange[0] <= reference[0] && pointSizeRange[1] >= reference[1]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fFloatStateQueryTests.AliasedLineWidthRangeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fFloatStateQueryTests.AliasedLineWidthRangeCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fFloatStateQueryTests.AliasedLineWidthRangeCase.prototype.constructor = es3fFloatStateQueryTests.AliasedLineWidthRangeCase;
+
+ es3fFloatStateQueryTests.AliasedLineWidthRangeCase.prototype.test = function() {
+ var lineWidthRange = /** @type {Float32Array} */ (gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE));
+ /** @type {Float32Array} */ var reference = new Float32Array([1, 1]);
+ this.check(lineWidthRange[0] <= reference[0] && lineWidthRange[1] >= reference[1]);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fFloatStateQueryTests.FloatStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'floats', 'Float Values');
+ };
+
+ es3fFloatStateQueryTests.FloatStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFloatStateQueryTests.FloatStateQueryTests.prototype.constructor = es3fFloatStateQueryTests.FloatStateQueryTests;
+
+ es3fFloatStateQueryTests.FloatStateQueryTests.prototype.init = function() {
+ this.addChild(new es3fFloatStateQueryTests.DepthRangeCase('depth_range', 'DEPTH_RANGE'));
+ this.addChild(new es3fFloatStateQueryTests.LineWidthCase('line_width', 'LINE_WIDTH'));
+ this.addChild(new es3fFloatStateQueryTests.PolygonOffsetFactorCase('polygon_offset_factor', 'POLYGON_OFFSET_FACTOR'));
+ this.addChild(new es3fFloatStateQueryTests.PolygonOffsetUnitsCase('polygon_offset_units', 'POLYGON_OFFSET_UNITS'));
+ this.addChild(new es3fFloatStateQueryTests.SampleCoverageCase('sample_coverage_value', 'SAMPLE_COVERAGE_VALUE'));
+ this.addChild(new es3fFloatStateQueryTests.BlendColorCase('blend_color', 'BLEND_COLOR'));
+ this.addChild(new es3fFloatStateQueryTests.ColorClearCase('color_clear_value', 'COLOR_CLEAR_VALUE'));
+ this.addChild(new es3fFloatStateQueryTests.DepthClearCase('depth_clear_value', 'DEPTH_CLEAR_VALUE'));
+ this.addChild(new es3fFloatStateQueryTests.MaxTextureLODBiasCase('max_texture_lod_bias', 'MAX_TEXTURE_LOD_BIAS'));
+ this.addChild(new es3fFloatStateQueryTests.AliasedPointSizeRangeCase('aliased_point_size_range', 'ALIASED_POINT_SIZE_RANGE'));
+ this.addChild(new es3fFloatStateQueryTests.AliasedLineWidthRangeCase('aliased_line_width_range', 'ALIASED_LINE_WIDTH_RANGE'));
+
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fFloatStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fFloatStateQueryTests.FloatStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFloatStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragDepthTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragDepthTests.js
new file mode 100644
index 0000000000..8a892a0926
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragDepthTests.js
@@ -0,0 +1,593 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFragDepthTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('modules.shared.glsShaderRenderCase');
+
+goog.scope(function() {
+ var es3fFragDepthTests = functional.gles3.es3fFragDepthTests;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTestCase = framework.common.tcuTestCase;
+ /** @typedef {function(Array<number>):number} */ es3fFragDepthTests.EvalFragDepthFunc;
+
+ /** @const {string} */ es3fFragDepthTests.s_vertexShaderSrc = '' +
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec2 a_coord;\n' +
+ 'out highp vec2 v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n';
+
+ /** @const {string} */ es3fFragDepthTests.s_defaultFragmentShaderSrc = '' +
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ '}\n';
+
+ /**
+ * @param {number} func
+ * @param {*} a
+ * @param {*} b
+ * @return {boolean}
+ */
+ es3fFragDepthTests.compare = function(func, a, b) {
+ switch (func) {
+ case gl.NEVER: return false;
+ case gl.ALWAYS: return true;
+ case gl.LESS: return a < b;
+ case gl.LEQUAL: return a <= b;
+ case gl.EQUAL: return a === b;
+ case gl.NOTEQUAL: return a !== b;
+ case gl.GEQUAL: return a >= b;
+ case gl.GREATER: return a > b;
+ }
+ bufferedLogToConsole('Compare function not supported.');
+ return false;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} fragSrc
+ * @param {?es3fFragDepthTests.EvalFragDepthFunc} evalFunc
+ * @param {number} compareFunc
+ */
+ es3fFragDepthTests.FragDepthCompareCase = function(name, desc, fragSrc, evalFunc, compareFunc) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /** @type {string} */ this.m_fragSrc = fragSrc;
+ /** @type {?es3fFragDepthTests.EvalFragDepthFunc} */ this.m_evalFunc = evalFunc;
+ /** @type {number} */ this.m_compareFunc = compareFunc;
+ };
+
+ es3fFragDepthTests.FragDepthCompareCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFragDepthTests.FragDepthCompareCase.prototype.constructor = es3fFragDepthTests.FragDepthCompareCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fFragDepthTests.FragDepthCompareCase.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+ /** @type {number} */ var viewportW = Math.min(128, gl.drawingBufferWidth);
+ /** @type {number} */ var viewportH = Math.min(128, gl.drawingBufferHeight);
+ /** @type {number} */ var viewportX = rnd.getInt(0, gl.drawingBufferWidth - viewportW);
+ /** @type {number} */ var viewportY = rnd.getInt(0, gl.drawingBufferHeight - viewportH);
+ /** @type {tcuSurface.Surface} */ var renderedFrame = new tcuSurface.Surface(viewportW, viewportH);
+ /** @type {tcuSurface.Surface} */ var referenceFrame = new tcuSurface.Surface(viewportW, viewportH);
+ /** @type {number} */ var constDepth = 0.1;
+ var depthBits = /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS));
+
+ /** @type {number} */ var xf;
+ /** @type {number} */ var d;
+ /** @type {boolean} */ var dpass;
+
+ if (depthBits == 0)
+ throw new Error('Depth buffer is required');
+
+ gl.depthMask(true);
+ gl.viewport(viewportX, viewportY, viewportW, viewportH);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ gl.enable(gl.DEPTH_TEST);
+
+ /** @type {Array<number>} */ var quadIndices = [0, 1, 2, 2, 1, 3];
+
+ // Fill viewport with 2 quads - one with constant depth and another with d = [-1..1]
+ /** @type {gluShaderProgram.ShaderProgram} */
+ var basicQuadProgram = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(es3fFragDepthTests.s_vertexShaderSrc, es3fFragDepthTests.s_defaultFragmentShaderSrc));
+
+ if (!basicQuadProgram.isOk()) {
+ bufferedLogToConsole(basicQuadProgram.getProgramInfo().infoLog);
+ throw new Error('Compile failed');
+ }
+
+ /** @type {Array<number>} */ var constDepthCoord = [
+ -1.0, -1.0, constDepth, 1.0,
+ -1.0, 1.0, constDepth, 1.0,
+ 0.0, -1.0, constDepth, 1.0,
+ 0.0, 1.0, constDepth, 1.0
+ ];
+
+ /** @type {Array<number>} */ var varyingDepthCoord = [
+ 0.0, -1.0, 1.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, -1.0, 1.0
+ ];
+
+ gl.useProgram(basicQuadProgram.getProgram());
+ gl.uniform4f(gl.getUniformLocation(basicQuadProgram.getProgram(), 'u_color'), 0.0, 0.0, 1.0, 1.0);
+ gl.depthFunc(gl.ALWAYS);
+
+ /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, constDepthCoord);
+ gluDrawUtil.draw(gl, basicQuadProgram.getProgram(), [posBinding], gluDrawUtil.triangles(quadIndices));
+
+ posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, varyingDepthCoord);
+ gluDrawUtil.draw(gl, basicQuadProgram.getProgram(), [posBinding], gluDrawUtil.triangles(quadIndices));
+
+ // Render with depth test.
+ /** @type {gluShaderProgram.ShaderProgram} */
+ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(es3fFragDepthTests.s_vertexShaderSrc, this.m_fragSrc));
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ throw new Error('Compile failed');
+
+ /** @type {Array<number>} */ var coord = [
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 0.0,
+ 1.0, 1.0
+ ];
+
+ /** @type {Array<number>} */ var position = [
+ -1.0, -1.0, 1.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, -1.0, 1.0
+ ];
+
+ gl.useProgram(program.getProgram());
+ gl.depthFunc(this.m_compareFunc);
+ gl.uniform4f(gl.getUniformLocation(program.getProgram(), 'u_color'), 0.0, 1.0, 0.0, 1.0);
+
+ // Setup default helper uniforms.
+ glsShaderRenderCase.setupDefaultUniforms(program.getProgram());
+
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [
+ gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, position),
+ gluDrawUtil.newFloatVertexArrayBinding('a_coord', 2, 4, 0, coord)
+ ];
+
+ gluDrawUtil.draw(gl, program.getProgram(), vertexArrays, gluDrawUtil.triangles(quadIndices));
+
+ renderedFrame.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
+
+ // Render reference.
+ for (var y = 0; y < referenceFrame.getHeight(); y++) {
+ /** @type {number} */ var yf = (y + 0.5) / referenceFrame.getHeight();
+ /** @type {number} */ var half = deMath.clamp(Math.floor(referenceFrame.getWidth() * 0.5 + 0.5), 0, referenceFrame.getWidth());
+
+ // Fill left half - comparison to constant 0.5
+ for (var x = 0; x < half; x++) {
+ xf = (x + 0.5) / referenceFrame.getWidth();
+ d = this.m_evalFunc([xf, yf]);
+ dpass = es3fFragDepthTests.compare(this.m_compareFunc, d, constDepth * 0.5 + 0.5);
+
+ referenceFrame.setPixel(x, y, dpass ? tcuRGBA.RGBA.green.toIVec() : tcuRGBA.RGBA.blue.toIVec());
+ }
+
+ // Fill right half - comparison to interpolated depth
+ for (var x = half; x < referenceFrame.getWidth(); x++) {
+ xf = (x + 0.5) / referenceFrame.getWidth();
+ /** @type {number} */ var xh = (x - half + 0.5) / (referenceFrame.getWidth() - half);
+ /** @type {number} */ var rd = 1.0 - (xh + yf) * 0.5;
+ d = this.m_evalFunc([xf, yf]);
+ dpass = es3fFragDepthTests.compare(this.m_compareFunc, d, rd);
+
+ referenceFrame.setPixel(x, y, dpass ? tcuRGBA.RGBA.green.toIVec() : tcuRGBA.RGBA.blue.toIVec());
+ }
+ }
+
+ /** @type {boolean} */ var isOk = tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', referenceFrame.getAccess(), renderedFrame.getAccess(), 0.05);
+
+ if (!isOk)
+ testFailedOptions('Fail', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} fragSrc
+ * @param {es3fFragDepthTests.EvalFragDepthFunc} evalFunc
+ */
+ es3fFragDepthTests.FragDepthWriteCase = function(name, desc, fragSrc, evalFunc) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /** @type {string} */ this.m_fragSrc = fragSrc;
+ /** @type {es3fFragDepthTests.EvalFragDepthFunc} */ this.m_evalFunc = evalFunc;
+ };
+
+ es3fFragDepthTests.FragDepthWriteCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFragDepthTests.FragDepthWriteCase.prototype.constructor = es3fFragDepthTests.FragDepthWriteCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fFragDepthTests.FragDepthWriteCase.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+ /** @type {number} */ var viewportW = Math.min(128, gl.drawingBufferWidth);
+ /** @type {number} */ var viewportH = Math.min(128, gl.drawingBufferHeight);
+ /** @type {number} */ var viewportX = rnd.getInt(0, gl.drawingBufferWidth - viewportW);
+ /** @type {number} */ var viewportY = rnd.getInt(0, gl.drawingBufferHeight - viewportH);
+ /** @type {tcuSurface.Surface} */ var renderedFrame = new tcuSurface.Surface(viewportW, viewportH);
+ /** @type {tcuSurface.Surface} */ var referenceFrame = new tcuSurface.Surface(viewportW, viewportH);
+ /** @type {number} */ var numDepthSteps = 16;
+ /** @type {number} */ var depthStep = 1.0 / (numDepthSteps - 1);
+ var depthBits = /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS));
+
+ if (depthBits === 0)
+ throw new Error('Depth buffer is required');
+
+ gl.depthMask(true);
+ gl.viewport(viewportX, viewportY, viewportW, viewportH);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LESS);
+
+ /** @type {Array<number>} */ var quadIndices = [0, 1, 2, 2, 1, 3];
+
+ // Render with given shader.
+ /** @type {gluShaderProgram.ShaderProgram} */
+ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(es3fFragDepthTests.s_vertexShaderSrc, this.m_fragSrc));
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ throw new Error('Compile failed');
+
+ /** @type {Array<number>} */ var coord = [
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 0.0,
+ 1.0, 1.0
+ ];
+
+ /** @type {Array<number>} */ var position = [
+ -1.0, -1.0, +1.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, -1.0, 1.0
+ ];
+
+ gl.useProgram(program.getProgram());
+ gl.uniform4f(gl.getUniformLocation(program.getProgram(), 'u_color'), 0.0, 1.0, 0.0, 1.0);
+
+ // Setup default helper uniforms.
+ glsShaderRenderCase.setupDefaultUniforms(program.getProgram());
+
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [
+ gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, position),
+ gluDrawUtil.newFloatVertexArrayBinding('a_coord', 2, 4, 0, coord)
+ ];
+ gluDrawUtil.draw(gl, program.getProgram(), vertexArrays, gluDrawUtil.triangles(quadIndices));
+
+ // Visualize by rendering full-screen quads with increasing depth and color.
+ program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(es3fFragDepthTests.s_vertexShaderSrc, es3fFragDepthTests.s_defaultFragmentShaderSrc));
+
+ if (!program.isOk()) {
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+ throw new Error('Compile failed');
+ }
+
+ /** @type {WebGLUniformLocation} */ var colorLoc = gl.getUniformLocation(program.getProgram(), 'u_color');
+
+ gl.useProgram(program.getProgram());
+ gl.depthMask(false);
+
+ for (var stepNdx = 0; stepNdx < numDepthSteps; stepNdx++) {
+ /** @type {number} */ var f = stepNdx * depthStep;
+ /** @type {number} */ var depth = f * 2.0 - 1.0;
+ /** @type {Array<number>} */ var color = [f, f, f, 1.0];
+
+ position = [
+ -1.0, -1.0, depth, 1.0,
+ -1.0, 1.0, depth, 1.0,
+ 1.0, -1.0, depth, 1.0,
+ 1.0, 1.0, depth, 1.0
+ ];
+
+ /** @type {gluDrawUtil.VertexArrayBinding} */
+ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, position);
+
+ gl.uniform4fv(colorLoc, color);
+ gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(quadIndices));
+ }
+
+ renderedFrame.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
+
+ // Render reference.
+ for (var y = 0; y < referenceFrame.getHeight(); y++)
+ for (var x = 0; x < referenceFrame.getWidth(); x++) {
+ /** @type {number} */ var xf = (x + 0.5) / referenceFrame.getWidth();
+ /** @type {number} */ var yf = (y + 0.5) / referenceFrame.getHeight();
+ /** @type {number} */ var d = this.m_evalFunc([xf, yf]);
+ /** @type {number} */ var step = Math.floor(d / depthStep);
+ /** @type {number} */ var col = deMath.clamp(Math.floor(step * depthStep * 255.0), 0, 255);
+
+ referenceFrame.setPixel(x, y, [col, col, col, 0xff]);
+ }
+
+ /** @type {boolean} */ var isOk = tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', referenceFrame.getAccess(), renderedFrame.getAccess(), 0.05);
+
+ if (!isOk)
+ testFailedOptions('Fail', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fFragDepthTests.FragDepthTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'fragdepth', 'gl_FragDepth tests');
+ };
+
+ es3fFragDepthTests.FragDepthTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFragDepthTests.FragDepthTests.prototype.constructor = es3fFragDepthTests.FragDepthTests;
+
+ /**
+ * @param {Array<number>} coord
+ * @return {number}
+ */
+ es3fFragDepthTests.evalConstDepth = function(coord) {
+ return 0.5;
+ };
+
+ /**
+ * @param {Array<number>} coord
+ * @return {number}
+ */
+ es3fFragDepthTests.evalDynamicDepth = function(coord) {
+ return (coord[0] + coord[1]) * 0.5;
+ };
+
+ /**
+ * @param {Array<number>} coord
+ * @return {number}
+ */
+ es3fFragDepthTests.evalNoWrite = function(coord) {
+ return 1.0 - (coord[0] + coord[1]) * 0.5;
+ };
+
+ /**
+ * @param {Array<number>} coord
+ * @return {number}
+ */
+ es3fFragDepthTests.evalDynamicConditionalDepth = function(coord) {
+ /** @type {number} */ var d = (coord[0] + coord[1]) * 0.5;
+ if (coord[1] < 0.5)
+ return d;
+ else
+ return 1.0 - d;
+ };
+
+ es3fFragDepthTests.FragDepthTests.prototype.init = function() {
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fFragDepthTests.EvalFragDepthFunc} evalFunc
+ * @param {string} fragSrc
+ */
+ var Case = function(name, desc, evalFunc, fragSrc) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.desc = desc;
+ /** @type {es3fFragDepthTests.EvalFragDepthFunc} */ this.evalFunc = evalFunc;
+ /** @type {string} */ this.fragSrc = fragSrc;
+ };
+
+ /** @type {Array<Case>} */ var cases = [
+ new Case('no_write', 'No gl_FragDepth write', es3fFragDepthTests.evalNoWrite,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ '}\n'
+ ),
+ new Case('const', 'Const depth write', es3fFragDepthTests.evalConstDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' gl_FragDepth = 0.5;\n' +
+ '}\n'
+ ),
+ new Case('uniform', 'Uniform depth write', es3fFragDepthTests.evalConstDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'uniform highp float uf_half;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' gl_FragDepth = uf_half;\n' +
+ '}\n'
+ ),
+ new Case('dynamic', 'Dynamic depth write', es3fFragDepthTests.evalDynamicDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n' +
+ '}\n'
+ ),
+ new Case('fragcoord_z', 'gl_FragDepth write from gl_FragCoord.z', es3fFragDepthTests.evalNoWrite,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' gl_FragDepth = gl_FragCoord.z;\n' +
+ '}\n'
+ ),
+ new Case('uniform_conditional_write', 'Uniform conditional write', es3fFragDepthTests.evalDynamicDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'uniform bool ub_true;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' if (ub_true)\n' +
+ ' gl_FragDepth = (v_coord.x+v_coord.y)*0.5;\n' +
+ '}\n'
+ ),
+ new Case('dynamic_conditional_write', 'Uniform conditional write', es3fFragDepthTests.evalDynamicConditionalDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'uniform bool ub_true;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' mediump float d = (v_coord.x+v_coord.y)*0.5f;\n' +
+ ' if (v_coord.y < 0.5)\n' +
+ ' gl_FragDepth = d;\n' +
+ ' else\n' +
+ ' gl_FragDepth = 1.0 - d;\n' +
+ '}\n'
+ ),
+ new Case('uniform_loop_write', 'Uniform loop write', es3fFragDepthTests.evalConstDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform highp float uf_fourth;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' gl_FragDepth = 0.0;\n' +
+ ' for (int i = 0; i < ui_two; i++)\n' +
+ ' gl_FragDepth += uf_fourth;\n' +
+ '}\n'
+ ),
+ new Case('write_in_function', 'Uniform loop write', es3fFragDepthTests.evalDynamicDepth,
+ '#version 300 es\n' +
+ 'uniform highp vec4 u_color;\n' +
+ 'uniform highp float uf_half;\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void myfunc (highp vec2 coord)\n' +
+ '{\n' +
+ ' gl_FragDepth = (coord.x+coord.y)*0.5;\n' +
+ '}\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = u_color;\n' +
+ ' myfunc(v_coord);\n' +
+ '}\n'
+ )
+ ];
+
+ var testGroup = tcuTestCase.runner.testCases;
+
+ // .write
+ /** @type {tcuTestCase.DeqpTest} */ var writeGroup = tcuTestCase.newTest('write', 'gl_FragDepth write tests');
+ testGroup.addChild(writeGroup);
+ for (var ndx = 0; ndx < cases.length; ndx++)
+ writeGroup.addChild(new es3fFragDepthTests.FragDepthWriteCase(cases[ndx].name, cases[ndx].desc, cases[ndx].fragSrc, cases[ndx].evalFunc));
+
+ // .compare
+ /** @type {tcuTestCase.DeqpTest} */ var compareGroup = tcuTestCase.newTest('compare', 'gl_FragDepth used with depth comparison');
+ testGroup.addChild(compareGroup);
+ for (var ndx = 0; ndx < cases.length; ndx++)
+ compareGroup.addChild(new es3fFragDepthTests.FragDepthCompareCase(cases[ndx].name, cases[ndx].desc, cases[ndx].fragSrc, cases[ndx].evalFunc, gl.LESS));
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fFragDepthTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fFragDepthTests.FragDepthTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fFragDepthTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragmentOutputTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragmentOutputTests.js
new file mode 100644
index 0000000000..b27eee7a6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFragmentOutputTests.js
@@ -0,0 +1,1398 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fFragmentOutputTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+
+var es3fFragmentOutputTests = functional.gles3.es3fFragmentOutputTests;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuTestCase = framework.common.tcuTestCase;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var deMath = framework.delibs.debase.deMath;
+var tcuImageCompare = framework.common.tcuImageCompare;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * es3fFragmentOutputTests.BufferSpec. Constructs the es3fFragmentOutputTests.BufferSpec object
+ * @constructor
+ * @param {WebGLRenderingContextBase.GLenum} format_
+ * @param {number} width_
+ * @param {number} height_
+ * @param {number} samples_
+ */
+ es3fFragmentOutputTests.BufferSpec = function(format_, width_, height_, samples_) {
+ this.format = format_;
+ this.width = width_;
+ this.height = height_;
+ this.samples = samples_;
+ };
+
+ /**
+ * es3fFragmentOutputTests.FragmentOutput. Constructs the es3fFragmentOutputTests.FragmentOutput object
+ * @constructor
+ * @param {gluShaderUtil.DataType} type_
+ * @param {gluShaderUtil.precision} precision_
+ * @param {number} location_
+ * @param {number=} arrayLength_
+ */
+ es3fFragmentOutputTests.FragmentOutput = function(type_, precision_, location_, arrayLength_) {
+ this.type = type_;
+ this.precision = precision_;
+ this.location = location_;
+ this.arrayLength = arrayLength_ || 0;
+ };
+
+ /**
+ * es3fFragmentOutputTests.FragmentOutputCase. Constructs the es3fFragmentOutputTests.FragmentOutputCase object
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {Array<es3fFragmentOutputTests.BufferSpec>} fboSpec
+ * @param {Array<es3fFragmentOutputTests.FragmentOutput>} outputs
+ * @return {Object} The currently modified object
+ */
+ es3fFragmentOutputTests.FragmentOutputCase = function(name, description, fboSpec, outputs) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {Array<es3fFragmentOutputTests.BufferSpec>} */ this.m_fboSpec = fboSpec;
+ /** @type {Array<es3fFragmentOutputTests.FragmentOutput>} */ this.m_outputs = outputs;
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {WebGLFramebuffer} */ this.m_framebuffer = null;
+
+ /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null;
+ };
+
+ es3fFragmentOutputTests.FragmentOutputCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFragmentOutputTests.FragmentOutputCase.prototype.constructor = es3fFragmentOutputTests.FragmentOutputCase;
+
+ /**
+ * es3fFragmentOutputTests.createProgram. Returns a ShaderProgram object
+ * @param {Array<es3fFragmentOutputTests.FragmentOutput>} outputs
+ * @return {gluShaderProgram.ShaderProgram} program
+ */
+ es3fFragmentOutputTests.createProgram = function(outputs) {
+
+ var vtx = '';
+ var frag = '';
+
+ vtx = '#version 300 es\n' + 'in highp vec4 a_position;\n';
+ frag = '#version 300 es\n';
+
+ /** @type {es3fFragmentOutputTests.FragmentOutput} */ var output = null;
+ /** @type {boolean} */ var isArray = false;
+ // Input-output declarations.
+ for (var outNdx = 0; outNdx < outputs.length; outNdx++) {
+ output = outputs[outNdx];
+ isArray = output.arrayLength > 0;
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(output.type);
+ /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(output.precision);
+ /** @type {boolean} */ var isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type);
+ /** @type {string} */ var interp = isFloat ? 'smooth' : 'flat';
+
+ if (isArray) {
+ for (var elemNdx = 0; elemNdx < output.arrayLength; elemNdx++) {
+ vtx += 'in ' + precName + ' ' + typeName + ' in' + outNdx + '_' + elemNdx + ';\n' +
+ interp + ' out ' + precName + ' ' + typeName + ' var' + outNdx + '_' + elemNdx + ';\n';
+ frag += interp + ' in ' + precName + ' ' + typeName + ' var' + outNdx + '_' + elemNdx + ';\n';
+ }
+ frag += 'layout(location = ' + output.location + ') out ' + precName + ' ' + typeName + ' out' + outNdx + '[' + output.arrayLength + '];\n';
+ } else {
+ vtx += 'in ' + precName + ' ' + typeName + ' in' + outNdx + ';\n' +
+ interp + ' out ' + precName + ' ' + typeName + ' var' + outNdx + ';\n';
+ frag += interp + ' in ' + precName + ' ' + typeName + ' var' + outNdx + ';\n' +
+ 'layout(location = ' + output.location + ') out ' + precName + ' ' + typeName + ' out' + outNdx + ';\n';
+ }
+ }
+
+ vtx += '\nvoid main()\n{\n';
+ frag += '\nvoid main()\n{\n';
+
+ vtx += ' gl_Position = a_position;\n';
+
+ // Copy body
+ for (var outNdx = 0; outNdx < outputs.length; outNdx++) {
+ output = outputs[outNdx];
+ isArray = output.arrayLength > 0;
+
+ if (isArray) {
+ for (var elemNdx = 0; elemNdx < output.arrayLength; elemNdx++) {
+ vtx += '\tvar' + outNdx + '_' + elemNdx + ' = in' + outNdx + '_' + elemNdx + ';\n';
+ frag += '\tout' + outNdx + '[' + elemNdx + '] = var' + outNdx + '_' + elemNdx + ';\n';
+ }
+ } else {
+ vtx += '\tvar' + outNdx + ' = in' + outNdx + ';\n';
+ frag += '\tout' + outNdx + ' = var' + outNdx + ';\n';
+ }
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ /** @type {gluShaderProgram.ShaderProgram} */
+ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag));
+ return program;
+ };
+
+ es3fFragmentOutputTests.FragmentOutputCase.prototype.init = function() {
+ // Check that all attachments are supported
+ for (var iter = 0; iter < this.m_fboSpec.length; ++iter) {
+ if (!gluTextureUtil.isSizedFormatColorRenderable(this.m_fboSpec[iter].format))
+ throw new Error('Unsupported attachment format');
+ }
+
+ DE_ASSERT(!this.m_program);
+ this.m_program = es3fFragmentOutputTests.createProgram(this.m_outputs);
+
+ // log << *m_program;
+ if (!this.m_program.isOk())
+ throw new Error('Compile failed. Program no created');
+
+ /*
+ // Print render target info to log.
+ log << TestLog::Section("Framebuffer", "Framebuffer configuration");
+
+ for (int ndx = 0; ndx < (int)m_fboSpec.size(); ndx++)
+ log << TestLog::Message << "COLOR_ATTACHMENT" << ndx << ": "
+ << glu::getPixelFormatStr(m_fboSpec[ndx].format) << ", "
+ << m_fboSpec[ndx].width << "x" << m_fboSpec[ndx].height << ", "
+ << m_fboSpec[ndx].samples << " samples"
+ << TestLog::EndMessage;
+
+ log << TestLog::EndSection;*/
+
+ // Create framebuffer.
+ this.m_framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+
+ for (var bufNdx = 0; bufNdx < /* m_renderbuffers.size() */ this.m_fboSpec.length; bufNdx++) {
+ this.m_renderbuffer = gl.createRenderbuffer();
+ /** @type {es3fFragmentOutputTests.BufferSpec} */ var bufSpec = this.m_fboSpec[bufNdx];
+ /** @type {number} */ var attachment = gl.COLOR_ATTACHMENT0 + bufNdx;
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
+
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, bufSpec.samples, bufSpec.format, bufSpec.width, bufSpec.height);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, this.m_renderbuffer);
+ }
+ /** @type {number} */ var fboStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ if (fboStatus == gl.FRAMEBUFFER_UNSUPPORTED)
+ throw new Error('Framebuffer not supported');
+ else if (fboStatus != gl.FRAMEBUFFER_COMPLETE)
+ throw new Error('Incomplete framebuffer');
+ // throw tcu::TestError((string("Incomplete framebuffer: ") + glu::getFramebufferStatusStr(fboStatus), "", __FILE__, __LINE__);
+
+ // gl.bindRenderbuffer(gl.RENDERBUFFER, null); // TODO: maybe needed?
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ };
+
+ es3fFragmentOutputTests.FragmentOutputCase.prototype.deinit = function() {
+ // TODO: implement?
+ };
+
+ /**
+ * es3fFragmentOutputTests.getMinSize.
+ * @param {Array<es3fFragmentOutputTests.BufferSpec>} fboSpec
+ * @return {Array<number>} minSize
+ */
+ es3fFragmentOutputTests.getMinSize = function(fboSpec) {
+ /** @type {Array<number>} */ var minSize = [0x7fffffff, 0x7fffffff];
+ for (var i = 0; i < fboSpec.length; i++) {
+ minSize[0] = Math.min(minSize[0], fboSpec[i].width);
+ minSize[1] = Math.min(minSize[1], fboSpec[i].height);
+ }
+ return minSize;
+ };
+
+ /**
+ * es3fFragmentOutputTests.getNumInputVectors. Returns the length of the array of all the outputs (es3fFragmentOutputTests.FragmentOutput object)
+ * @param {Array<es3fFragmentOutputTests.FragmentOutput>} outputs
+ * @return {number} numVecs
+ */
+ es3fFragmentOutputTests.getNumInputVectors = function(outputs) {
+ /** @type {number} */ var numVecs = 0;
+ for (var i = 0; i < outputs.length; i++)
+ numVecs += (outputs[i].arrayLength > 0 ? outputs[i].arrayLength : 1);
+ return numVecs;
+ };
+
+ /**
+ * es3fFragmentOutputTests.getFloatRange
+ * @param {gluShaderUtil.precision} precision
+ * @return {Array<number>} Vec2
+ */
+ es3fFragmentOutputTests.getFloatRange = function(precision) {
+ /** @type {Array<Array<number>>} */
+ var ranges = // Vec2
+ [
+ [-2.0, 2.0],
+ [-16000.0, 16000.0],
+ [-1e35, 1e35]
+ ];
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST);
+ // DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges)));
+ return ranges[precision];
+ };
+
+ /**
+ * es3fFragmentOutputTests.getIntRange
+ * @param {gluShaderUtil.precision} precision
+ * @return {Array<number>} IVec2
+ */
+ es3fFragmentOutputTests.getIntRange = function(precision) {
+ /** @type {Array<Array<number>>} */
+ var ranges = // IVec2
+ [
+ [-(1 << 7), (1 << 7) - 1],
+ [-(1 << 15), (1 << 15) - 1],
+ [-0x80000000, 0x7fffffff]
+ ];
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST);
+ // DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges)));
+ return ranges[precision];
+ };
+
+ /**
+ * es3fFragmentOutputTests.getUintRange
+ * @param {gluShaderUtil.precision} precision
+ * @return {Array<number>} UVec2
+ */
+ es3fFragmentOutputTests.getUintRange = function(precision) {
+ /** @type {Array<Array<number>>} */
+ var ranges = // UVec2
+ [
+ [0, (1 << 8) - 1],
+ [0, (1 << 16) - 1],
+ [0, 0xffffffff]
+ ];
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST);
+ // DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges)));
+ return ranges[precision];
+
+ };
+
+ /**
+ * es3fFragmentOutputTests.readVec4
+ * @param {Array<number>} ptr
+ * @param {number} index
+ * @param {number} numComponents
+ * @return {Array<number>} Vec4
+ */
+ es3fFragmentOutputTests.readVec4 = function(ptr, index, numComponents) {
+ DE_ASSERT(numComponents >= 1);
+ return [
+ ptr[index + 0],
+ numComponents >= 2 ? ptr[index + 1] : 0.0,
+ numComponents >= 3 ? ptr[index + 2] : 0.0,
+ numComponents >= 4 ? ptr[index + 3] : 0.0
+ ];
+ };
+
+ /**
+ * es3fFragmentOutputTests.readIVec4
+ * @param {Array<number>} ptr
+ * @param {number} numComponents
+ * @return {Array<number>} IVec4
+ */
+ es3fFragmentOutputTests.readIVec4 = function(ptr, index, numComponents) {
+ DE_ASSERT(numComponents >= 1);
+ return [
+ ptr[index + 0],
+ numComponents >= 2 ? ptr[index + 1] : 0,
+ numComponents >= 3 ? ptr[index + 2] : 0,
+ numComponents >= 4 ? ptr[index + 3] : 0
+ ];
+ };
+
+ /**
+ * es3fFragmentOutputTests.renderFloatReference
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {number} gridWidth
+ * @param {number} gridHeight
+ * @param {number} numComponents
+ * @param {Array<number>} vertices
+ */
+ es3fFragmentOutputTests.renderFloatReference = function(dst, gridWidth, gridHeight, numComponents, vertices) {
+
+ /** @type {boolean} */ var isSRGB = dst.getFormat().order == tcuTexture.ChannelOrder.sRGB || dst.getFormat().order == tcuTexture.ChannelOrder.sRGBA;
+ /** @type {number} */ var cellW = dst.getWidth() / (gridWidth - 1);
+ /** @type {number} */ var cellH = dst.getHeight() / (gridHeight - 1);
+
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ /** @type {number} */ var cellX = deMath.clamp(Math.floor(x / cellW), 0, gridWidth - 2);
+ /** @type {number} */ var cellY = deMath.clamp(Math.floor(y / cellH), 0, gridHeight - 2);
+ /** @type {number} */ var xf = (x - cellX * cellW + 0.5) / cellW;
+ /** @type {number} */ var yf = (y - cellY * cellH + 0.5) / cellH;
+
+ /** @type {Array<number>} */ var v00 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 0) * gridWidth + cellX + 0) * numComponents, numComponents); // Vec4
+ /** @type {Array<number>} */ var v01 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 1) * gridWidth + cellX + 0) * numComponents, numComponents); // Vec4
+ /** @type {Array<number>} */ var v10 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 0) * gridWidth + cellX + 1) * numComponents, numComponents); // Vec4
+ /** @type {Array<number>} */ var v11 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 1) * gridWidth + cellX + 1) * numComponents, numComponents); // Vec4
+
+ /** @type {boolean} */ var tri = xf + yf >= 1.0;
+ /** @type {Array<number>} */ var v0 = tri ? v11 : v00; // Vec4&
+ /** @type {Array<number>} */ var v1 = tri ? v01 : v10; // Vec4&
+ /** @type {Array<number>} */ var v2 = tri ? v10 : v01; // Vec4&
+ /** @type {number} */ var s = tri ? 1.0 - xf : xf;
+ /** @type {number} */ var t = tri ? 1.0 - yf : yf;
+ /** @type {Array<number>} */ var color = deMath.add(v0, deMath.add(deMath.multiply((deMath.subtract(v1, v0)), [s, s, s, s]), deMath.multiply((deMath.subtract(v2, v0)), [t, t, t, t]))); // Vec4
+
+ dst.setPixel(isSRGB ? tcuTextureUtil.linearToSRGB(color) : color, x, y);
+ }
+ }
+ };
+
+ /**
+ * es3fFragmentOutputTests.renderIntReference
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {number} gridWidth
+ * @param {number} gridHeight
+ * @param {number} numComponents
+ * @param {Array<number>} vertices
+ */
+ es3fFragmentOutputTests.renderIntReference = function(dst, gridWidth, gridHeight, numComponents, vertices) {
+
+ /** @type {number} */ var cellW = dst.getWidth() / (gridWidth - 1);
+ /** @type {number} */ var cellH = dst.getHeight() / (gridHeight - 1);
+
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ /** @type {number} */ var cellX = deMath.clamp(Math.floor(x / cellW), 0, gridWidth - 2);
+ /** @type {number} */ var cellY = deMath.clamp(Math.floor(y / cellH), 0, gridHeight - 2);
+ /** @type {Array<number>} */ var c = es3fFragmentOutputTests.readIVec4(vertices, (cellY * gridWidth + cellX + 1) * numComponents, numComponents); // IVec4
+
+ dst.setPixelInt(c, x, y);
+ }
+ }
+ };
+
+ /**
+ * es3fFragmentOutputTests.s_swizzles
+ * @return {Array<Array<number>>}
+ */
+ es3fFragmentOutputTests.s_swizzles = function() {
+ var mat_swizzles = [
+ [0, 1, 2, 3],
+ [1, 2, 3, 0],
+ [2, 3, 0, 1],
+ [3, 0, 1, 2],
+ [3, 2, 1, 0],
+ [2, 1, 0, 3],
+ [1, 0, 3, 2],
+ [0, 3, 2, 1]
+ ];
+
+ return mat_swizzles;
+ };
+
+ /**
+ * es3fFragmentOutputTests.swizzleVec. Returns an Array from a position contained in the Array es3fFragmentOutputTests.s_swizzles []
+ * @param {Array<number>} vec
+ * @param {number} swzNdx
+ * @return {Array<number>} Swizzled array
+ */
+ es3fFragmentOutputTests.swizzleVec = function(vec, swzNdx) {
+ /** @type {Array<number>} */ var swz = es3fFragmentOutputTests.s_swizzles()[swzNdx % es3fFragmentOutputTests.s_swizzles().length];
+
+ return deMath.swizzle(vec, swz);
+ };
+
+ /**
+ * es3fFragmentOutputTests.AttachmentData struct class
+ * @constructor
+ * @return {Object}
+ */
+ es3fFragmentOutputTests.AttachmentData = function() {
+ return {
+ /** @type {tcuTexture.TextureFormat} */ format: null, //!< Actual format of attachment.
+ /** @type {tcuTexture.TextureFormat} */ referenceFormat: null, //!< Used for reference rendering.
+ /** @type {tcuTexture.TextureFormat} */ readFormat: null,
+ /** @type {number} */ numWrittenChannels: 0,
+ /** @type {gluShaderUtil.precision} */ outPrecision: gluShaderUtil.precision.PRECISION_LOWP,
+ /** @type {ArrayBuffer} */ renderedData: null,
+ /** @type {ArrayBuffer} */ referenceData: null
+ };
+ };
+
+ es3fFragmentOutputTests.FragmentOutputCase.prototype.iterate = function() {
+ // Compute grid size & index list.
+ /** @type {number} */ var minCellSize = 8;
+ /** @type {Array<number>} */ var minBufSize = es3fFragmentOutputTests.getMinSize(this.m_fboSpec); // IVec2
+ /** @type {number} */ var gridWidth = deMath.clamp(Math.floor(minBufSize[0] / minCellSize), 1, 255) + 1;
+ /** @type {number} */ var gridHeight = deMath.clamp(Math.floor(minBufSize[1] / minCellSize), 1, 255) + 1;
+ /** @type {number} */ var numVertices = gridWidth * gridHeight;
+ /** @type {number} */ var numQuads = (gridWidth - 1) * (gridHeight - 1);
+ /** @type {number} */ var numIndices = numQuads * 6;
+
+ /** @type {number} */ var numInputVecs = es3fFragmentOutputTests.getNumInputVectors(this.m_outputs);
+ /** @type {Array<Array<number>>} */ var inputs = []; // originally vector<vector<deUint32>
+
+ for (var inputNdx = 0; inputNdx < numInputVecs; inputNdx++)
+ inputs[inputNdx] = []; // inputs.length = numInputVecs;
+
+ /** @type {Array<number>} */ var positions = []; // originally vector<float>
+ /** @type {Array<number>} */ var indices = []; // originally vector<deUint16>
+
+ /** @type {number} */ var readAlignment = 4;
+ /** @type {number} */ var viewportW = minBufSize[0];
+ /** @type {number} */ var viewportH = minBufSize[1];
+ /** @type {number} */ var numAttachments = this.m_fboSpec.length;
+
+ /** @type {Array<number>} */ var drawBuffers = []; // originally vector<deUint32>
+ /** @type {Array<es3fFragmentOutputTests.AttachmentData>} */ var attachments = [];
+ /** @type {number} */ var attachmentW;
+ /** @type {number} */ var attachmentH;
+
+ // Initialize attachment data.
+ for (var ndx = 0; ndx < numAttachments; ndx++) {
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_fboSpec[ndx].format);
+ /** @type {tcuTexture.TextureChannelClass} */ var chnClass = tcuTexture.getTextureChannelClass(texFmt.type);
+ /** @type {boolean} */ var isFixedPoint = (chnClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT ||
+ chnClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT);
+
+ // \note Fixed-point formats use float reference to enable more accurate result verification.
+ /** @type {tcuTexture.TextureFormat} */ var refFmt = isFixedPoint ? new tcuTexture.TextureFormat(texFmt.order, tcuTexture.ChannelType.FLOAT) : texFmt;
+ /** @type {tcuTexture.TextureFormat} */ var readFmt = es3fFboTestUtil.getFramebufferReadFormat(texFmt);
+ attachmentW = this.m_fboSpec[ndx].width;
+ attachmentH = this.m_fboSpec[ndx].height;
+
+ drawBuffers[ndx] = gl.COLOR_ATTACHMENT0 + ndx;
+ attachments[ndx] = new es3fFragmentOutputTests.AttachmentData();
+ attachments[ndx].format = texFmt;
+ attachments[ndx].readFormat = readFmt;
+ attachments[ndx].referenceFormat = refFmt;
+ attachments[ndx].renderedData = new ArrayBuffer(readFmt.getPixelSize() * attachmentW * attachmentH);
+ attachments[ndx].referenceData = new ArrayBuffer(refFmt.getPixelSize() * attachmentW * attachmentH);
+ }
+
+ // Initialize indices.
+ for (var quadNdx = 0; quadNdx < numQuads; quadNdx++) {
+ /** @type {number} */ var quadY = Math.floor(quadNdx / (gridWidth - 1));
+ /** @type {number} */ var quadX = quadNdx - quadY * (gridWidth - 1);
+
+ indices[quadNdx * 6 + 0] = quadX + quadY * gridWidth;
+ indices[quadNdx * 6 + 1] = quadX + (quadY + 1) * gridWidth;
+ indices[quadNdx * 6 + 2] = quadX + quadY * gridWidth + 1;
+ indices[quadNdx * 6 + 3] = indices[quadNdx * 6 + 1];
+ indices[quadNdx * 6 + 4] = quadX + (quadY + 1) * gridWidth + 1;
+ indices[quadNdx * 6 + 5] = indices[quadNdx * 6 + 2];
+ }
+
+ /** @type {number} */ var xf = 0;
+ /** @type {number} */ var yf = 0;
+ for (var y = 0; y < gridHeight; y++) {
+ for (var x = 0; x < gridWidth; x++) {
+ xf = x / (gridWidth - 1);
+ yf = y / (gridHeight - 1);
+
+ positions[(y * gridWidth + x) * 4 + 0] = 2.0 * xf - 1.0;
+ positions[(y * gridWidth + x) * 4 + 1] = 2.0 * yf - 1.0;
+ positions[(y * gridWidth + x) * 4 + 2] = 0.0;
+ positions[(y * gridWidth + x) * 4 + 3] = 1.0;
+ }
+ }
+ /** @type {es3fFragmentOutputTests.FragmentOutput} */ var output;
+ /** @type {boolean} */ var isArray;
+ /** @type {boolean} */ var isFloat;
+ /** @type {boolean} */ var isInt;
+ /** @type {boolean} */ var isUint;
+ /** @type {number} */ var numVecs;
+ /** @type {number} */ var numScalars;
+
+ var curInVec = 0;
+ for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) {
+ output = this.m_outputs[outputNdx];
+ isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type);
+ isInt = gluShaderUtil.isDataTypeIntOrIVec(output.type);
+ isUint = gluShaderUtil.isDataTypeUintOrUVec(output.type);
+ numVecs = output.arrayLength > 0 ? output.arrayLength : 1;
+ numScalars = gluShaderUtil.getDataTypeScalarSize(output.type);
+
+ for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) {
+ inputs[curInVec].length = numVertices * numScalars;
+
+ // Record how many outputs are written in attachment.
+ DE_ASSERT(output.location + vecNdx < attachments.length);
+ attachments[output.location + vecNdx].numWrittenChannels = numScalars;
+ attachments[output.location + vecNdx].outPrecision = output.precision;
+
+ /** @type {Array<number>} */ var range = null;
+ /** @type {Array<number>} */ var minVal = null;
+ /** @type {Array<number>} */ var maxVal = null;
+ /** @type {Array<number>} */ var fmtBits = null;
+ /** @type {Array<number>} */ var fmtMaxVal = [];
+ /** @type {Array<number>} */ var rangeDiv = null;
+ /** @type {Array<number>} */ var step = [];
+ /** @type {number} */ var ix = 0;
+ /** @type {number} */ var iy = 0;
+ /** @type {Array<number>} */ var c = null;
+ /** @type {number} */ var pos = 0;
+ if (isFloat) {
+ range = es3fFragmentOutputTests.getFloatRange(output.precision); // Vec2
+ minVal = [range[0], range[0], range[0], range[0]]; // Vec4
+ maxVal = [range[1], range[1], range[1], range[1]]; // Vec4
+
+ if (deMath.deInBounds32(output.location + vecNdx, 0, attachments.length)) {
+ // \note Floating-point precision conversion is not well-defined. For that reason we must
+ // limit value range to intersection of both data type and render target value ranges.
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(attachments[output.location + vecNdx].format);
+ minVal = deMath.max(minVal, fmtInfo.valueMin);
+ maxVal = deMath.min(maxVal, fmtInfo.valueMax);
+ }
+
+ bufferedLogToConsole('out ' + curInVec + ' value range: ' + minVal + ' -> ' + maxVal);
+
+ for (var y = 0; y < gridHeight; y++) {
+ for (var x = 0; x < gridWidth; x++) {
+ xf = x / (gridWidth - 1);
+ yf = y / (gridHeight - 1);
+ /** @type {number} */ var f0 = (xf + yf) * 0.5;
+ /** @type {number} */ var f1 = 0.5 + (xf - yf) * 0.5;
+
+ /** @type {Array<number>} */ var f = es3fFragmentOutputTests.swizzleVec([f0, f1, 1.0 - f0, 1.0 - f1], curInVec); // Vec4
+ c = deMath.add(minVal, deMath.multiply(deMath.subtract(maxVal, minVal), f)); // Vec4
+
+ pos = (y * gridWidth + x) * numScalars;
+
+ for (var ndx = 0; ndx < numScalars; ndx++)
+ inputs[curInVec][pos + ndx] = c[ndx];
+ }
+ }
+ } else if (isInt) {
+ range = es3fFragmentOutputTests.getIntRange(output.precision); // IVec2
+ minVal = [range[0], range[0], range[0], range[0]]; // IVec4
+ maxVal = [range[1], range[1], range[1], range[1]]; // IVec4
+
+ if (deMath.deInBounds32(output.location + vecNdx, 0, attachments.length)) {
+ // Limit to range of output format as conversion mode is not specified.
+ fmtBits = tcuTextureUtil.getTextureFormatBitDepth(attachments[output.location + vecNdx].format); // IVec4
+ /** @type {Array<boolean>} */ var isZero = deMath.lessThanEqual(fmtBits, [0, 0, 0, 0]); // BVec4, array of booleans, size = 4
+
+ /** @type {Array<number>} */ var fmtMinVal = []; // IVec4
+
+ for (var i = 0; i < 4; i++) {
+
+ // const IVec4 fmtMinVal = (-(tcu::Vector<deInt64, 4>(1) << (fmtBits - 1 ).cast<deInt64>())).asInt();
+ fmtMinVal[i] = -1 * Math.pow(2, fmtBits[i] - 1); // TODO: check implementation, original above
+ // const IVec4 fmtMaxVal = ((tcu::Vector<deInt64, 4>(1) << (fmtBits - 1 ).cast<deInt64>()) - deInt64(1)).asInt();
+ fmtMaxVal[i] = Math.pow(2, fmtBits[i] - 1) - 1; // TODO: check implementation, original above
+ }
+
+ minVal = tcuTextureUtil.select(minVal, deMath.max(minVal, fmtMinVal), isZero);
+ maxVal = tcuTextureUtil.select(maxVal, deMath.min(maxVal, fmtMaxVal), isZero);
+ }
+
+ bufferedLogToConsole('out ' + curInVec + ' value range: ' + minVal + ' -> ' + maxVal);
+
+ rangeDiv = es3fFragmentOutputTests.swizzleVec([gridWidth - 1, gridHeight - 1, gridWidth - 1, gridHeight - 1], curInVec); // IVec4
+ for (var i = 0; i < 4; i++) {
+ // const IVec4 step = ((maxVal.cast<deInt64>() - minVal.cast<deInt64>()) / (rangeDiv.cast<deInt64>())).asInt();
+ step[i] = Math.floor((maxVal[i] - minVal[i]) / rangeDiv[i]); // TODO: check with the above line of code
+ }
+
+ for (var y = 0; y < gridHeight; y++) {
+ for (var x = 0; x < gridWidth; x++) {
+ ix = gridWidth - x - 1;
+ iy = gridHeight - y - 1;
+ c = deMath.add(minVal, deMath.multiply(step, es3fFragmentOutputTests.swizzleVec([x, y, ix, iy], curInVec))); // IVec4
+
+ pos = (y * gridWidth + x) * numScalars;
+
+ for (var ndx = 0; ndx < numScalars; ndx++)
+ inputs[curInVec][pos + ndx] = c[ndx];
+ }
+ }
+ } else if (isUint) {
+ range = es3fFragmentOutputTests.getUintRange(output.precision); // UVec2
+ maxVal = [range[1], range[1], range[1], range[1]]; // UVec4
+
+ if (deMath.deInBounds32(output.location + vecNdx, 0, attachments.length)) {
+ // Limit to range of output format as conversion mode is not specified.
+ fmtBits = tcuTextureUtil.getTextureFormatBitDepth(attachments[output.location + vecNdx].format); // IVec4
+
+ for (var i = 0; i < 4; i++) {
+ fmtMaxVal[i] = Math.pow(2, fmtBits[i]) - 1;
+ }
+
+ maxVal = deMath.min(maxVal, fmtMaxVal);
+ }
+
+ bufferedLogToConsole('out ' + curInVec + ' value range: ' + minVal + ' -> ' + maxVal);
+
+ rangeDiv = es3fFragmentOutputTests.swizzleVec([gridWidth - 1, gridHeight - 1, gridWidth - 1, gridHeight - 1], curInVec); // IVec4
+
+ for (var stepPos = 0; stepPos < maxVal.length; stepPos++) {
+ step[stepPos] = Math.floor(maxVal[stepPos] / rangeDiv[stepPos]);
+ }
+
+ DE_ASSERT(range[0] == 0);
+
+ for (var y = 0; y < gridHeight; y++) {
+ for (var x = 0; x < gridWidth; x++) {
+ ix = gridWidth - x - 1;
+ iy = gridHeight - y - 1;
+ c = deMath.multiply(step, es3fFragmentOutputTests.swizzleVec([x, y, ix, iy], curInVec)); // UVec4
+ pos = (y * gridWidth + x) * numScalars;
+
+ DE_ASSERT(deMath.boolAll(deMath.lessThanEqual(c, maxVal))); // TODO: sometimes crashes here, condition not asserted
+
+ for (var ndx = 0; ndx < numScalars; ndx++)
+ inputs[curInVec][pos + ndx] = c[ndx];
+ }
+ }
+ } else
+ DE_ASSERT(false);
+
+ curInVec += 1;
+ }
+ }
+
+ // Render using gl.
+ gl.useProgram(this.m_program.getProgram());
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+ gl.viewport(0, 0, viewportW, viewportH);
+ gl.drawBuffers(drawBuffers);
+ gl.disable(gl.DITHER); // Dithering causes issues with unorm formats. Those issues could be worked around in threshold, but it makes validation less accurate.
+
+ /** @type {WebGLBuffer} */ var buffer = null;
+ /** @type {string} */ var name;
+ curInVec = 0;
+ for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) {
+ output = this.m_outputs[outputNdx];
+ isArray = output.arrayLength > 0;
+ isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type);
+ isInt = gluShaderUtil.isDataTypeIntOrIVec(output.type);
+ isUint = gluShaderUtil.isDataTypeUintOrUVec(output.type);
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(output.type);
+ /** @type {number} */ var glScalarType = isFloat ? /* gluShaderUtil.DataType.FLOAT */ gl.FLOAT :
+ isInt ? /* gluShaderUtil.DataType.INT */ gl.INT :
+ isUint ? /* gluShaderUtil.DataType.UINT */ gl.UNSIGNED_INT : /* gluShaderUtil.DataType.INVALID */ gl.NONE;
+ numVecs = isArray ? output.arrayLength : 1;
+
+ for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) {
+ name = 'in' + outputNdx + (isArray ? '_' + vecNdx : '');
+ /** @type {number} */ var loc = gl.getAttribLocation(this.m_program.getProgram(), name);
+
+ if (loc >= 0) {
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ gl.enableVertexAttribArray(loc);
+ if (isFloat) {
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(inputs[curInVec]), gl.STATIC_DRAW);
+ // KHRONOS WebGL 1.0 specification:
+ // void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+ gl.vertexAttribPointer(loc, scalarSize, glScalarType, false, 0, 0); // offset = 0
+ } else {
+ gl.bufferData(gl.ARRAY_BUFFER, new Int32Array(inputs[curInVec]), gl.STATIC_DRAW);
+ // KHRONOS WebGL 2.0 specification:
+ // void vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset)
+ gl.vertexAttribIPointer(loc, scalarSize, glScalarType, 0, 0); // offset = 0
+ }
+ } else
+ bufferedLogToConsole('Warning: No location for attribute "' + name + '" found.');
+
+ curInVec += 1;
+ }
+ }
+
+ /** @type {number} */ var posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ // TCU_CHECK(posLoc >= 0);
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(posLoc);
+ gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0); // offset = 0
+
+ /** @type {WebGLBuffer} */ var indexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
+
+ gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0); // offset = 0
+
+ // Render reference images.
+
+ var curInNdx = 0;
+ for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) {
+ output = this.m_outputs[outputNdx];
+ isArray = output.arrayLength > 0;
+ isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type);
+ isInt = gluShaderUtil.isDataTypeIntOrIVec(output.type);
+ isUint = gluShaderUtil.isDataTypeUintOrUVec(output.type);
+ scalarSize = gluShaderUtil.getDataTypeScalarSize(output.type);
+ numVecs = isArray ? output.arrayLength : 1;
+
+ for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) {
+ /** @type {number} */ var location = output.location + vecNdx;
+ /** @type {Array<number>} */ var inputData = inputs[curInNdx];
+
+ DE_ASSERT(deMath.deInBounds32(location, 0, this.m_fboSpec.length));
+
+ /** @type {number} */ var bufW = this.m_fboSpec[location].width;
+ /** @type {number} */ var bufH = this.m_fboSpec[location].height;
+ /** @type {Object} */ var descriptor = {
+ format: attachments[location].referenceFormat,
+ width: bufW,
+ height: bufH,
+ depth: 1,
+ data: attachments[location].referenceData // ArrayBuffer
+ };
+ /** @type {tcuTexture.PixelBufferAccess} */ var buf = new tcuTexture.PixelBufferAccess(descriptor);
+ /** @type {tcuTexture.PixelBufferAccess} */ var viewportBuf = tcuTextureUtil.getSubregion(buf, 0, 0, 0, viewportW, viewportH, 1);
+
+ if (isInt || isUint)
+ es3fFragmentOutputTests.renderIntReference(viewportBuf, gridWidth, gridHeight, scalarSize, inputData);
+ else if (isFloat)
+ es3fFragmentOutputTests.renderFloatReference(viewportBuf, gridWidth, gridHeight, scalarSize, inputData);
+ else
+ DE_ASSERT(false);
+
+ curInNdx += 1;
+ }
+ }
+
+ // Compare all images.
+ /** @type {boolean} */ var allLevelsOk = true;
+ for (var attachNdx = 0; attachNdx < numAttachments; attachNdx++) {
+ attachmentW = this.m_fboSpec[attachNdx].width;
+ attachmentH = this.m_fboSpec[attachNdx].height;
+ /** @type {number} */ var numValidChannels = attachments[attachNdx].numWrittenChannels;
+ /** @type {Array<boolean>} */ var cmpMask = [numValidChannels >= 1, numValidChannels >= 2, numValidChannels >= 3, numValidChannels >= 4];
+ /** @type {gluShaderUtil.precision} */ var outPrecision = attachments[attachNdx].outPrecision;
+ /** @type {tcuTexture.TextureFormat} */ var format = attachments[attachNdx].format;
+ /** @type {Object} */
+ var renderedDescriptor = {
+ format: attachments[attachNdx].readFormat,
+ width: attachmentW,
+ height: attachmentH,
+ depth: 1,
+ rowPitch: deMath.deAlign32(attachments[attachNdx].readFormat.getPixelSize() * attachmentW, readAlignment),
+ slicePitch: 0,
+ data: attachments[attachNdx].renderedData // ArrayBuffer
+ };
+ /** @type {tcuTexture.PixelBufferAccess} */ var rendered = new tcuTexture.PixelBufferAccess(renderedDescriptor);
+ /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(attachments[attachNdx].readFormat);
+ gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachNdx);
+ gl.readPixels(0, 0, attachmentW, attachmentH, transferFmt.format, transferFmt.dataType, rendered.getDataPtr());
+
+ /** @type {Object} */
+ var referenceDescriptor = {
+ format: attachments[attachNdx].referenceFormat,
+ width: attachmentW,
+ height: attachmentH,
+ depth: 1,
+ data: attachments[attachNdx].referenceData // ArrayBuffer
+ };
+ /** @type {tcuTexture.ConstPixelBufferAccess} */ var reference = new tcuTexture.ConstPixelBufferAccess(referenceDescriptor);
+ /** @type {tcuTexture.TextureChannelClass} */ var texClass = tcuTexture.getTextureChannelClass(format.type);
+ /** @type {boolean} */ var isOk = true;
+ name = 'Attachment ' + attachNdx;
+ /** @type {string} */ var desc = 'Color attachment ' + attachNdx;
+ /** @type {Array<number>} */ var threshold;
+
+ bufferedLogToConsole('Attachment ' + attachNdx + ': ' + numValidChannels + ' channels have defined values and used for comparison');
+
+ switch (texClass) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT: {
+ /** @type {Array<number>} */ var formatThreshold = []; // UVec4 //!< Threshold computed based on format.
+ formatThreshold.length = 4;
+ /** @type {number} */ var precThreshold = 0; // deUint32 //!< Threshold computed based on output type precision
+ /** @type {Array<number>} */ var finalThreshold = []; // UVec4
+ finalThreshold.length = 4;
+
+ switch (format.type) {
+ case tcuTexture.ChannelType.FLOAT:
+ formatThreshold = [4, 4, 4, 4]; // UVec4
+ break;
+ case tcuTexture.ChannelType.HALF_FLOAT:
+ formatThreshold = [(1 << 13) + 4, (1 << 13) + 4, (1 << 13) + 4, (1 << 13) + 4]; // UVec4
+ break;
+ case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV:
+ formatThreshold = [(1 << 17) + 4, (1 << 17) + 4, (1 << 18) + 4, 4]; // UVec4
+ break;
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ switch (outPrecision) {
+ case gluShaderUtil.precision.PRECISION_LOWP:
+ precThreshold = (1 << 21);
+ break;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP:
+ precThreshold = (1 << 13);
+ break;
+ case gluShaderUtil.precision.PRECISION_HIGHP:
+ precThreshold = 0;
+ break;
+ default:
+ DE_ASSERT(false);
+ }
+
+ finalThreshold = tcuTextureUtil.select(
+ deMath.max(formatThreshold, [precThreshold, precThreshold, precThreshold, precThreshold]),
+ [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff], // C++ version: UVec4(~0u) bitwise not, all bits in the integer will be flipped
+ cmpMask);
+
+ isOk = tcuImageCompare.floatUlpThresholdCompare(name, desc, reference, rendered, finalThreshold /*, tcu::COMPARE_LOG_RESULT*/);
+ break;
+ }
+
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT: {
+ // \note glReadPixels() allows only 8 bits to be read. This means that RGB10_A2 will loose some
+ // bits in the process and it must be taken into account when computing threshold.
+ /** @type {Array<number>} */ var bits = deMath.min([8, 8, 8, 8], tcuTextureUtil.getTextureFormatBitDepth(format)); // IVec4
+
+ /** @type {Array<number>} */ var baseThreshold = []; // Vec4
+ baseThreshold.length = 4;
+ for (var inc = 0; inc < baseThreshold.length; inc++) {
+ // TODO: check the operation below: baseThreshold = 1.0f / ((IVec4(1) << bits)-1).asFloat();
+ baseThreshold[inc] = 1.0 / ((1 << bits[inc]) - 1);
+ }
+
+ threshold = tcuTextureUtil.select(baseThreshold, [2.0, 2.0, 2.0, 2.0], cmpMask); // Vec4
+
+ isOk = tcuImageCompare.floatThresholdCompare(name, desc, reference, rendered, threshold/*, tcu::COMPARE_LOG_RESULT*/);
+ break;
+ }
+
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER: {
+ // The C++ dEQP code uses ~0u but ~0 is -1 in Javascript
+ var UINT_MAX = Math.pow(2.0, 32.0) - 1;
+ threshold = tcuTextureUtil.select(
+ [0, 0, 0, 0],
+ [UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX],
+ cmpMask
+ ); // UVec4
+ isOk = tcuImageCompare.intThresholdCompare(name, desc, reference, rendered, threshold/*, tcu::COMPARE_LOG_RESULT*/);
+ break;
+ }
+
+ default:
+ testFailedOptions('Unsupported comparison', true);
+ break;
+ }
+
+ if (!isOk)
+ allLevelsOk = false;
+ }
+
+ if (numAttachments > 1) {
+ if (allLevelsOk)
+ testPassed('Image comparison passed for ' + numAttachments + ' attachments');
+ else
+ testFailed('Image comparison failed for some of ' + numAttachments + ' attachments');
+ } else {
+ if (allLevelsOk)
+ testPassed('Image comparison passed');
+ else
+ testFailed('Image comparison failed');
+ }
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * es3fFragmentOutputTests.createRandomCase. Constructs the es3fFragmentOutputTests.createRandomCase, child class of es3fFragmentOutputTests.FragmentOutputCase
+ * @constructor
+ * @param {number} minRenderTargets
+ * @param {number} maxRenderTargets
+ * @param {number} seed
+ * @return {es3fFragmentOutputTests.FragmentOutputCase} The currently modified object
+ */
+ es3fFragmentOutputTests.createRandomCase = function(minRenderTargets, maxRenderTargets, seed, colorBufferFloatSupported) {
+
+ /** @type {Array<gluShaderUtil.DataType>} */
+ var outputTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4
+ ];
+
+ /** @type {Array<gluShaderUtil.precision>} */
+ var precisions = [
+ gluShaderUtil.precision.PRECISION_LOWP,
+ gluShaderUtil.precision.PRECISION_MEDIUMP,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ ];
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var floatFormats = [
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F,
+ gl.RGBA8,
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGBA4,
+ gl.RGB5_A1,
+ gl.RGB8,
+ gl.RGB565,
+ gl.RG8,
+ gl.R8
+ ];
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var colorBufferFloatFormats = [
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F
+ ];
+
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var intFormats = [
+ gl.RGBA32I,
+ gl.RGBA16I,
+ gl.RGBA8I,
+ gl.RG32I,
+ gl.RG16I,
+ gl.RG8I,
+ gl.R32I,
+ gl.R16I,
+ gl.R8I
+ ];
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var uintFormats = [
+ gl.RGBA32UI,
+ gl.RGBA16UI,
+ gl.RGBA8UI,
+ gl.RGB10_A2UI,
+ gl.RG32UI,
+ gl.RG16UI,
+ gl.RG8UI,
+ gl.R32UI,
+ gl.R16UI,
+ gl.R8UI
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
+ /** @type {Array<es3fFragmentOutputTests.FragmentOutput>} */ var outputs = [];
+ /** @type {Array<es3fFragmentOutputTests.BufferSpec>} */ var targets = [];
+ /** @type {Array<gluShaderUtil.DataType>} */ var outTypes = [];
+
+ /** @type {number} */ var numTargets = rnd.getInt(minRenderTargets, maxRenderTargets);
+ /** @type {number} */ var width = 128; // \todo [2012-04-10 pyry] Separate randomized sizes per target?
+ /** @type {number} */ var height = 64;
+ /** @type {number} */ var samples = 0;
+
+ // Compute outputs.
+ /** @type {number} */ var curLoc = 0;
+ while (curLoc < numTargets) {
+ /** @type {boolean} */ var useArray = rnd.getFloat() < 0.3;
+ /** @type {number} */ var maxArrayLen = numTargets - curLoc;
+ /** @type {number} */ var arrayLen = useArray ? rnd.getInt(1, maxArrayLen) : 0;
+ /** @type {Array<gluShaderUtil.DataType>} */ var basicTypeArray = rnd.choose(outputTypes, undefined, 1);
+ /** @type {gluShaderUtil.DataType} */ var basicType = basicTypeArray[0];
+ /** @type {Array<gluShaderUtil.precision>} */ var precisionArray = rnd.choose(precisions, undefined, 1);
+ /** @type {gluShaderUtil.precision} */ var precision = precisionArray[0];
+ /** @type {number} */ var numLocations = useArray ? arrayLen : 1;
+
+ outputs.push(new es3fFragmentOutputTests.FragmentOutput(basicType, precision, curLoc, arrayLen));
+
+ for (var ndx = 0; ndx < numLocations; ndx++)
+ outTypes.push(basicType);
+
+ curLoc += numLocations;
+ }
+ DE_ASSERT(curLoc == numTargets);
+ DE_ASSERT(outTypes.length == numTargets);
+
+ // Compute buffers.
+ while (targets.length < numTargets) {
+ /** @type {gluShaderUtil.DataType} */ var outType = outTypes[targets.length];
+ /** @type {boolean} */ var isFloat = gluShaderUtil.isDataTypeFloatOrVec(outType);
+ /** @type {boolean} */ var isInt = gluShaderUtil.isDataTypeIntOrIVec(outType);
+ /** @type {boolean} */ var isUint = gluShaderUtil.isDataTypeUintOrUVec(outType);
+ /** @type {Array} */ var formatArray = [];
+ /** @type {number} */ var format = 0;
+
+ if (isFloat) {
+ formatArray = rnd.choose(floatFormats, undefined, 1);
+ format = formatArray[0];
+ if (colorBufferFloatFormats.indexOf(format) >= 0 && !colorBufferFloatSupported)
+ return null;
+ } else if (isInt) {
+ formatArray = rnd.choose(intFormats, undefined, 1);
+ format = formatArray[0];
+ } else if (isUint) {
+ formatArray = rnd.choose(uintFormats, undefined, 1);
+ format = formatArray[0];
+ } else
+ DE_ASSERT(false);
+
+ targets.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+ }
+
+ return new es3fFragmentOutputTests.FragmentOutputCase(seed.toString(), '', targets, outputs);
+
+ };
+
+ es3fFragmentOutputTests.init = function(gl) {
+ var state = tcuTestCase.runner;
+ state.testCases = tcuTestCase.newTest('fragment_outputs', 'Top level');
+ /** @const @type {tcuTestCase.DeqpTest} */ var testGroup = state.testCases;
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var requiredFloatFormats = [
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F
+ ];
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var requiredFixedFormats = [
+ gl.RGBA8,
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGBA4,
+ gl.RGB5_A1,
+ gl.RGB8,
+ gl.RGB565,
+ gl.RG8,
+ gl.R8
+ ];
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var requiredIntFormats = [
+ gl.RGBA32I,
+ gl.RGBA16I,
+ gl.RGBA8I,
+ gl.RG32I,
+ gl.RG16I,
+ gl.RG8I,
+ gl.R32I,
+ gl.R16I,
+ gl.R8I
+ ];
+
+ /** @type {Array<WebGLRenderingContextBase.GLenum>} */
+ var requiredUintFormats = [
+ gl.RGBA32UI,
+ gl.RGBA16UI,
+ gl.RGBA8UI,
+ gl.RGB10_A2UI,
+ gl.RG32UI,
+ gl.RG16UI,
+ gl.RG8UI,
+ gl.R32UI,
+ gl.R16UI,
+ gl.R8UI
+ ];
+
+ /** @type {Array<gluShaderUtil.precision>} */
+ var precisions = [
+
+ gluShaderUtil.precision.PRECISION_LOWP,
+ gluShaderUtil.precision.PRECISION_MEDIUMP,
+ gluShaderUtil.precision.PRECISION_HIGHP
+
+ ];
+
+ // .basic.
+
+ /** @const @type {number} */ var width = 64;
+ /** @const @type {number} */ var height = 64;
+ /** @const @type {number} */ var samples = 0;
+ /** @type {Array<es3fFragmentOutputTests.BufferSpec>} */ var fboSpec = null;
+ /** @type {gluShaderUtil.precision} */ var prec;
+ /** @type {string} */ var precName;
+
+ // .float
+ if (gl.getExtension('EXT_color_buffer_float')) {
+ /** @type {tcuTestCase.DeqpTest} */ var floatGroup = tcuTestCase.newTest('basic.float', 'Floating-point output tests');
+ testGroup.addChild(floatGroup);
+
+ for (var fmtNdx = 0; fmtNdx < requiredFloatFormats.length; fmtNdx++) {
+ var format = requiredFloatFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ // NOTE: Eliminated original OutputVec and toVec(), as it only returned an element of the outputs array in OutputVec
+ floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0)]));
+ floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0)]));
+ floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0)]));
+ floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0)]));
+ }
+ }
+ }
+
+ // .fixed
+ /** @type {tcuTestCase.DeqpTest} */ var fixedGroup = tcuTestCase.newTest('basic.fixed', 'Fixed-point output tests');
+ testGroup.addChild(fixedGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredFixedFormats.length; fmtNdx++) {
+ var format = requiredFixedFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0)]));
+ fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0)]));
+ fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0)]));
+ fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0)]));
+ }
+ }
+
+ // .int
+ /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('basic.int', 'Integer output tests');
+ testGroup.addChild(intGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredIntFormats.length; fmtNdx++) {
+ var format = requiredIntFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_int', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT, prec, 0)]));
+ intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC2, prec, 0)]));
+ intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC3, prec, 0)]));
+ intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC4, prec, 0)]));
+ }
+ }
+
+ // .uint
+ /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('basic.uint', 'Usigned integer output tests');
+ testGroup.addChild(uintGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredUintFormats.length; fmtNdx++) {
+ var format = requiredUintFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uint', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT, prec, 0)]));
+ uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC2, prec, 0)]));
+ uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC3, prec, 0)]));
+ uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC4, prec, 0)]));
+
+ }
+ }
+
+ // .array
+
+ /** @type {number} */ var numTargets = 3;
+
+ // .float
+ if (gl.getExtension('EXT_color_buffer_float')) {
+ /** @type {tcuTestCase.DeqpTest} */ var arrayFloatGroup = tcuTestCase.newTest('array.float', 'Floating-point output tests');
+ testGroup.addChild(arrayFloatGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredFloatFormats.length; fmtNdx++) {
+ var format = requiredFloatFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ for (var ndx = 0; ndx < numTargets; ndx++)
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0, numTargets)]));
+ arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0, numTargets)]));
+ arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0, numTargets)]));
+ arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0, numTargets)]));
+ }
+ }
+ }
+
+ // .fixed
+ /** @type {tcuTestCase.DeqpTest} */ var arrayFixedGroup = tcuTestCase.newTest('array.fixed', 'Fixed-point output tests');
+ testGroup.addChild(arrayFixedGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredFixedFormats.length; fmtNdx++) {
+ var format = requiredFixedFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ for (var ndx = 0; ndx < numTargets; ndx++)
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0, numTargets)]));
+ arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0, numTargets)]));
+ arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0, numTargets)]));
+ arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0, numTargets)]));
+ }
+ }
+
+ // .int
+ /** @type {tcuTestCase.DeqpTest} */ var arrayIntGroup = tcuTestCase.newTest('array.int', 'Integer output tests');
+ testGroup.addChild(arrayIntGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredIntFormats.length; fmtNdx++) {
+ var format = requiredIntFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ for (var ndx = 0; ndx < numTargets; ndx++)
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_int', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT, prec, 0, numTargets)]));
+ arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC2, prec, 0, numTargets)]));
+ arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC3, prec, 0, numTargets)]));
+ arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC4, prec, 0, numTargets)]));
+ }
+ }
+
+ // .uint
+ /** @type {tcuTestCase.DeqpTest} */ var arrayUintGroup = tcuTestCase.newTest('array.uint', 'Usigned integer output tests');
+ testGroup.addChild(arrayUintGroup);
+ for (var fmtNdx = 0; fmtNdx < requiredUintFormats.length; fmtNdx++) {
+ var format = requiredUintFormats[fmtNdx];
+ var fmtName = es3fFboTestUtil.getFormatName(format);
+ fboSpec = [];
+
+ for (var ndx = 0; ndx < numTargets; ndx++)
+ fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples));
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ prec = precisions[precNdx];
+ precName = gluShaderUtil.getPrecisionName(prec);
+
+ arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uint', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT, prec, 0, numTargets)]));
+ arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC2, prec, 0, numTargets)]));
+ arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC3, prec, 0, numTargets)]));
+ arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC4, prec, 0, numTargets)]));
+ }
+ }
+
+ // .random
+
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var randomGroup = [];
+ var numRandomGroups = 3;
+ for (var ii = 0; ii < numRandomGroups; ++ii) {
+ randomGroup[ii] = tcuTestCase.newTest('random', 'Random fragment output cases');
+ testGroup.addChild(randomGroup[ii]);
+ }
+
+ /** @type {boolean} */ var colorBufferFloatSupported = (gl.getExtension('EXT_color_buffer_float') != null);
+ for (var seed = 0; seed < 100; seed++) {
+ var test = es3fFragmentOutputTests.createRandomCase(2, 4, seed, colorBufferFloatSupported);
+ if (test !== null) {
+ randomGroup[seed % numRandomGroups].addChild(test);
+ }
+ }
+
+ };
+
+ /**
+ * Create and execute the test cases
+ */
+ es3fFragmentOutputTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'fragment_output';
+ var testDescription = 'Fragment Output Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ es3fFragmentOutputTests.init(gl);
+ if (range)
+ state.setRange(range);
+ tcuTestCase.runTestCases();
+ } catch (err) {
+ testFailedOptions('Failed to es3fFragmentOutputTests.run tests', false);
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFramebufferBlitTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFramebufferBlitTests.js
new file mode 100644
index 0000000000..ffc6a0c68c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFramebufferBlitTests.js
@@ -0,0 +1,1261 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fFramebufferBlitTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestCase');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+
+ var es3fFramebufferBlitTests = functional.gles3.es3fFramebufferBlitTests;
+ var es3fFboTestCase = functional.gles3.es3fFboTestCase;
+ var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var rrUtil = framework.referencerenderer.rrUtil;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+ /**
+ * es3fFramebufferBlitTests.BlitRectCase class, inherits from FboTestCase
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} filter deUint32
+ * @param {Array<number>} srcSize
+ * @param {Array<number>} srcRect
+ * @param {Array<number>} dstSize
+ * @param {Array<number>} dstRect
+ * @param {number=} cellSize
+ */
+ es3fFramebufferBlitTests.BlitRectCase = function(name, desc, filter, srcSize, srcRect, dstSize, dstRect, cellSize) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @const {number} */ this.m_filter = filter;
+ /** @const {Array<number>} */ this.m_srcSize = srcSize;
+ /** @const {Array<number>} */ this.m_srcRect = srcRect;
+ /** @const {Array<number>} */ this.m_dstSize = dstSize;
+ /** @const {Array<number>} */ this.m_dstRect = dstRect;
+ /** @const {number} */ this.m_cellSize = cellSize === undefined ? 8 : cellSize;
+ /** @const {Array<number>} */ this.m_gridCellColorA = [0.2, 0.7, 0.1, 1.0];
+ /** @const {Array<number>} */ this.m_gridCellColorB = [0.7, 0.1, 0.5, 0.8];
+ };
+
+ es3fFramebufferBlitTests.BlitRectCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFramebufferBlitTests.BlitRectCase.prototype.constructor = es3fFramebufferBlitTests.BlitRectCase;
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFramebufferBlitTests.BlitRectCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ /** @type {number} */ var colorFormat = gl.RGBA8;
+
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradShader = new es3fFboTestUtil.GradientShader(
+ gluShaderUtil.DataType.FLOAT_VEC4);
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D],
+ gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var gradShaderID = ctx.createProgram(gradShader);
+ var texShaderID = ctx.createProgram(texShader);
+
+ var srcFbo;
+ var dstFbo;
+ var srcRbo;
+ var dstRbo;
+
+ // Setup shaders
+ gradShader.setGradient(ctx, gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ texShader.setUniforms(ctx, texShaderID);
+
+ // Create framebuffers.
+
+ /** @type {Array<number>} */ var size;
+
+ // source framebuffers
+ srcFbo = ctx.createFramebuffer();
+ srcRbo = ctx.createRenderbuffer();
+ size = this.m_srcSize;
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, srcRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, size[0], size[1]);
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, srcRbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // destination framebuffers
+ dstFbo = ctx.createFramebuffer();
+ dstRbo = ctx.createRenderbuffer();
+ size = this.m_dstSize;
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, dstRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, size[0], size[1]);
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dstRbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // Fill destination with gradient.
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
+ ctx.viewport(0, 0, this.m_dstSize[0], this.m_dstSize[1]);
+
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ // Fill source with grid pattern.
+ /** @const {number} */ var format = gl.RGBA;
+ /** @const {number} */ var dataType = gl.UNSIGNED_BYTE;
+ /** @const {number} */ var texW = this.m_srcSize[0];
+ /** @const {number} */ var texH = this.m_srcSize[1];
+ var gridTex;
+ /** @type {tcuTexture.TextureLevel} */ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), this.m_cellSize, this.m_gridCellColorA, this.m_gridCellColorB);
+
+ gridTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, gridTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
+ ctx.viewport(0, 0, this.m_srcSize[0], this.m_srcSize[1]);
+
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ // Perform copy.
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFbo);
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFbo);
+ ctx.blitFramebuffer(this.m_srcRect[0], this.m_srcRect[1], this.m_srcRect[2], this.m_srcRect[3],
+ this.m_dstRect[0], this.m_dstRect[1], this.m_dstRect[2], this.m_dstRect[3],
+ gl.COLOR_BUFFER_BIT, this.m_filter);
+
+ // Read back results.
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, dstFbo);
+
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_dstSize[0], this.m_dstSize[1],
+ gluTextureUtil.mapGLInternalFormat(colorFormat),
+ [1.0, 1.0, 1.0, 1.0],
+ [0.0, 0.0, 0.0, 0.0]);
+ };
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @return {boolean}
+ */
+ es3fFramebufferBlitTests.BlitRectCase.prototype.compare = function(reference, result) {
+ // Use pixel-threshold compare for rect cases since 1px off will mean failure.
+ var threshold = [7, 7, 7, 7];
+ return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, result, threshold);
+ };
+
+ /**
+ * es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase class
+ * @constructor
+ * @extends {es3fFramebufferBlitTests.BlitRectCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {Array<number>} srcSize
+ * @param {Array<number>} srcRect
+ * @param {Array<number>} dstSize
+ * @param {Array<number>} dstRect
+ */
+ es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase = function(name, desc, srcSize, srcRect, dstSize, dstRect) {
+ es3fFramebufferBlitTests.BlitRectCase.call(this, name, desc, gl.NEAREST, srcSize, srcRect, dstSize, dstRect, 1);
+ };
+
+ es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase.prototype = Object.create(es3fFramebufferBlitTests.BlitRectCase.prototype);
+ es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase.prototype.constructor = es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase;
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @return {boolean}
+ */
+ es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase.prototype.compare = function(reference, result) {
+ assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(),
+ 'Reference and result images have different dimensions', false, true);
+
+ // Image origin must be visible (for baseColor)
+ DE_ASSERT(Math.min(this.m_dstRect[0], this.m_dstRect[2]) >= 0);
+ DE_ASSERT(Math.min(this.m_dstRect[1], this.m_dstRect[3]) >= 0);
+ /** @const {tcuRGBA.RGBA} */ var cellColorA = tcuRGBA.newRGBAFromVec(this.m_gridCellColorA);
+ /** @const {tcuRGBA.RGBA} */ var cellColorB = tcuRGBA.newRGBAFromVec(this.m_gridCellColorB);
+ // TODO: implement
+ // const tcu::RGBA threshold = this.m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
+ /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.newRGBAComponents(7, 7, 7, 7);
+ /** @const {Array<number>} */ //IVec4.xyzw
+ var destinationArea = [
+ deMath.clamp(Math.min(this.m_dstRect[0], this.m_dstRect[2]), 0, result.getWidth()),
+ deMath.clamp(Math.min(this.m_dstRect[1], this.m_dstRect[3]), 0, result.getHeight()),
+ deMath.clamp(Math.max(this.m_dstRect[0], this.m_dstRect[2]), 0, result.getWidth()),
+ deMath.clamp(Math.max(this.m_dstRect[1], this.m_dstRect[3]), 0, result.getHeight())];
+
+ /** @const {tcuRGBA.RGBA} */ var baseColor = new tcuRGBA.RGBA(result.getPixel(destinationArea[0], destinationArea[1]));
+
+ /** @const {boolean} */ var signConfig = tcuRGBA.compareThreshold(baseColor, cellColorA, threshold);
+
+ /** @type {boolean} */ var error = false;
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ /** @type {Array<boolean>} */ var horisontalSign = [];
+ /** @type {Array<boolean>} */ var verticalSign = [];
+
+ errorMask.getAccess().clear([0.0, 1.0, 0.0, 1.0]);
+
+ // Checking only area in our destination rect
+
+ // m_testCtx.getLog()
+ // << tcu::TestLog::Message
+ // << 'Verifying consistency of NEAREST filtering. Verifying rect ' << m_dstRect << '.\n'
+ // << 'Rounding direction of the NEAREST filter at the horisontal texel edge (x = n + 0.5) should not depend on the y-coordinate.\n'
+ // << 'Rounding direction of the NEAREST filter at the vertical texel edge (y = n + 0.5) should not depend on the x-coordinate.\n'
+ // << 'Blitting a grid (with uniform sized cells) should result in a grid (with non-uniform sized cells).'
+ // << tcu::TestLog::EndMessage;
+
+ // Verify that destination only contains valid colors
+
+ /** @type {tcuRGBA.RGBA} */ var color;
+
+ for (var dy = 0; dy < destinationArea[3] - destinationArea[1]; ++dy) {
+ for (var dx = 0; dx < destinationArea[2] - destinationArea[0]; ++dx) {
+ color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0] + dx, destinationArea[1] + dy));
+
+ /** @const {boolean} */
+ var isValidColor =
+ tcuRGBA.compareThreshold(color, cellColorA, threshold) ||
+ tcuRGBA.compareThreshold(color, cellColorB, threshold);
+
+ if (!isValidColor) {
+ errorMask.setPixel(destinationArea[0] + dx, destinationArea[1] + dy, tcuRGBA.RGBA.red.toVec());
+ error = true;
+ }
+ }
+ }
+
+ if (error) {
+ // m_testCtx.getLog()
+ // << tcu::TestLog::Message
+ // << 'Image verification failed, destination rect contains unexpected values. '
+ // << 'Expected either ' << cellColorA << ' or ' << cellColorB << '.'
+ // << tcu::TestLog::EndMessage
+ // << tcu::TestLog::ImageSet('Result', 'Image verification result')
+ // << tcu::TestLog::Image('Result', 'Result', result)
+ // << tcu::TestLog::Image('ErrorMask', 'Error mask', errorMask)
+ // << tcu::TestLog::EndImageSet;
+ return false;
+ }
+
+ // Detect result edges by reading the first row and first column of the blitted area.
+ // Blitting a grid should result in a grid-like image. ('sign changes' should be consistent)
+
+ for (var dx = 0; dx < destinationArea[2] - destinationArea[0]; ++dx) {
+ color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0] + dx, destinationArea[1]));
+ if (tcuRGBA.compareThreshold(color, cellColorA, threshold))
+ horisontalSign[dx] = true;
+ else if (tcuRGBA.compareThreshold(color, cellColorB, threshold))
+ horisontalSign[dx] = false;
+ else
+ DE_ASSERT(false);
+ }
+ for (var dy = 0; dy < destinationArea[3] - destinationArea[1]; ++dy) {
+ color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0], destinationArea[1] + dy));
+
+ if (tcuRGBA.compareThreshold(color, cellColorA, threshold))
+ verticalSign[dy] = true;
+ else if (tcuRGBA.compareThreshold(color, cellColorB, threshold))
+ verticalSign[dy] = false;
+ else
+ DE_ASSERT(false);
+ }
+
+ // Verify grid-like image
+
+ for (var dy = 0; dy < destinationArea[3] - destinationArea[1]; ++dy) {
+ for (var dx = 0; dx < destinationArea[2] - destinationArea[0]; ++dx) {
+ color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0] + dx, destinationArea[1] + dy));
+ /** @const {boolean} */ var resultSign = tcuRGBA.compareThreshold(cellColorA, color, threshold);
+ /** @const {boolean} */ var correctSign = (horisontalSign[dx] == verticalSign[dy]) == signConfig;
+
+ if (resultSign != correctSign) {
+ errorMask.setPixel(destinationArea[0] + dx, destinationArea[1] + dy, tcuRGBA.RGBA.red.toVec());
+ error = true;
+ }
+ }
+ }
+ // Report result
+
+ // if (error)
+ // {
+ // m_testCtx.getLog()
+ // << tcu::TestLog::Message
+ // << 'Image verification failed, nearest filter is not consistent.'
+ // << tcu::TestLog::EndMessage
+ // << tcu::TestLog::ImageSet('Result', 'Image verification result')
+ // << tcu::TestLog::Image('Result', 'Result', result)
+ // << tcu::TestLog::Image('ErrorMask', 'Error mask', errorMask)
+ // << tcu::TestLog::EndImageSet;
+ // }
+ // else
+ // {
+ // m_testCtx.getLog()
+ // << tcu::TestLog::Message
+ // << 'Image verification passed.'
+ // << tcu::TestLog::EndMessage
+ // << tcu::TestLog::ImageSet('Result', 'Image verification result')
+ // << tcu::TestLog::Image('Result', 'Result', result)
+ // << tcu::TestLog::EndImageSet;
+ // }
+
+ return !error;
+ };
+
+ /**
+ * es3fFramebufferBlitTests.FramebufferBlitTests class, inherits from TestCase
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fFramebufferBlitTests.FramebufferBlitTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'blit', 'Framebuffer blit tests');
+ };
+
+ es3fFramebufferBlitTests.FramebufferBlitTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fFramebufferBlitTests.FramebufferBlitTests.prototype.constructor = es3fFramebufferBlitTests.FramebufferBlitTests;
+
+ es3fFramebufferBlitTests.FramebufferBlitTests.prototype.init = function() {
+ /** @const {Array<number>} */ var colorFormats = [
+ // RGBA formats
+ gl.RGBA32I,
+ gl.RGBA32UI,
+ gl.RGBA16I,
+ gl.RGBA16UI,
+ gl.RGBA8,
+ gl.RGBA8I,
+ gl.RGBA8UI,
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGB10_A2UI,
+ gl.RGBA4,
+ gl.RGB5_A1,
+
+ // RGB formats
+ gl.RGB8,
+ gl.RGB565,
+
+ // RG formats
+ gl.RG32I,
+ gl.RG32UI,
+ gl.RG16I,
+ gl.RG16UI,
+ gl.RG8,
+ gl.RG8I,
+ gl.RG8UI,
+
+ // R formats
+ gl.R32I,
+ gl.R32UI,
+ gl.R16I,
+ gl.R16UI,
+ gl.R8,
+ gl.R8I,
+ gl.R8UI,
+
+ // gl.EXT_color_buffer_float
+ gl.RGBA32F,
+ gl.RGBA16F,
+ gl.R11F_G11F_B10F,
+ gl.RG32F,
+ gl.RG16F,
+ gl.R32F,
+ gl.R16F
+ ];
+
+ /** @const {Array<number>} */ var depthStencilFormats = [
+ gl.DEPTH_COMPONENT32F,
+ gl.DEPTH_COMPONENT24,
+ gl.DEPTH_COMPONENT16,
+ gl.DEPTH32F_STENCIL8,
+ gl.DEPTH24_STENCIL8,
+ gl.STENCIL_INDEX8
+ ];
+
+ // .rect
+ /** @constructor
+ * @param {string} name
+ * @param {Array<number>} srcRect
+ * @param {Array<number>} dstRect
+ */
+ var CopyRect = function(name, srcRect, dstRect) {
+ /** @const {string} */ this.name = name;
+ /** @type {Array<number>} */ this.srcRect = srcRect;
+ /** @type {Array<number>} */ this.dstRect = dstRect;
+ };
+
+ /** @const {Array<CopyRect>} */ var copyRects = [
+ new CopyRect('basic', [10, 20, 65, 100], [45, 5, 100, 85]),
+ new CopyRect('scale', [10, 20, 65, 100], [25, 30, 125, 94]),
+ new CopyRect('out_of_bounds', [-10, -15, 100, 63], [50, 30, 136, 144])
+ ];
+
+ /** @const {Array<CopyRect>} */ var filterConsistencyRects = [
+
+ new CopyRect('mag', [20, 10, 74, 88], [10, 10, 91, 101]),
+ new CopyRect('min', [10, 20, 78, 100], [20, 20, 71, 80]),
+ new CopyRect('out_of_bounds_mag', [21, 10, 73, 82], [11, 43, 141, 151]),
+ new CopyRect('out_of_bounds_min', [11, 21, 77, 97], [80, 82, 135, 139])
+ ];
+
+ /** @constructor
+ * @param {?string} name
+ * @param {Array<number>} srcSwizzle
+ * @param {Array<number>} dstSwizzle
+ */
+ var Swizzle = function(name, srcSwizzle, dstSwizzle) {
+ /** @const {?string} */ this.name = name;
+ /** @type {Array<number>} */ this.srcSwizzle = srcSwizzle;
+ /** @type {Array<number>} */ this.dstSwizzle = dstSwizzle;
+ };
+
+ /** @const {Array<Swizzle>} */ var swizzles = [
+ new Swizzle(null, [0, 1, 2, 3], [0, 1, 2, 3]),
+ new Swizzle('reverse_src_x', [2, 1, 0, 3], [0, 1, 2, 3]),
+ new Swizzle('reverse_src_y', [0, 3, 2, 1], [0, 1, 2, 3]),
+ new Swizzle('reverse_dst_x', [0, 1, 2, 3], [2, 1, 0, 3]),
+ new Swizzle('reverse_dst_y', [0, 1, 2, 3], [0, 3, 2, 1]),
+ new Swizzle('reverse_src_dst_x', [2, 1, 0, 3], [2, 1, 0, 3]),
+ new Swizzle('reverse_src_dst_y', [0, 3, 2, 1], [0, 3, 2, 1])
+ ];
+
+ /** @const {Array<number>} */ var srcSize = [127, 119];
+ /** @const {Array<number>} */ var dstSize = [132, 128];
+
+ // Blit rectangle tests.
+ for (var rectNdx = 0; rectNdx < copyRects.length; rectNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var rectGroup = tcuTestCase.newTest('rect', 'Blit rectangle tests');
+ this.addChild(rectGroup);
+
+ for (var swzNdx = 0; swzNdx < swizzles.length; swzNdx++) {
+ /** @type {string} */ var name = copyRects[rectNdx].name + (swizzles[swzNdx].name ? ('_' + swizzles[swzNdx].name) : '');
+ /** @type {Array<number>} */ var srcSwz = swizzles[swzNdx].srcSwizzle;
+ /** @type {Array<number>} */ var dstSwz = swizzles[swzNdx].dstSwizzle;
+ /** @type {Array<number>} */ var srcRect = deMath.swizzle(copyRects[rectNdx].srcRect, srcSwz);
+ /** @type {Array<number>} */ var dstRect = deMath.swizzle(copyRects[rectNdx].dstRect, dstSwz);
+
+ rectGroup.addChild(new es3fFramebufferBlitTests.BlitRectCase((name + '_nearest'), '', gl.NEAREST, srcSize, srcRect, dstSize, dstRect));
+ rectGroup.addChild(new es3fFramebufferBlitTests.BlitRectCase((name + '_linear'), '', gl.LINEAR, srcSize, srcRect, dstSize, dstRect));
+ }
+ }
+
+ // Nearest filter tests
+ for (var rectNdx = 0; rectNdx < filterConsistencyRects.length; rectNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var rectGroup = tcuTestCase.newTest('rect', 'Blit rectangle tests');
+ this.addChild(rectGroup);
+ for (var swzNdx = 0; swzNdx < swizzles.length; swzNdx++) {
+ var name = 'nearest_consistency_' + filterConsistencyRects[rectNdx].name + (swizzles[swzNdx].name ? ('_' + swizzles[swzNdx].name) : '');
+ var srcSwz = swizzles[swzNdx].srcSwizzle;
+ var dstSwz = swizzles[swzNdx].dstSwizzle;
+ var srcRect = deMath.swizzle(filterConsistencyRects[rectNdx].srcRect, srcSwz);
+ var dstRect = deMath.swizzle(filterConsistencyRects[rectNdx].dstRect, dstSwz);
+
+ rectGroup.addChild(new es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase(name, 'Test consistency of the nearest filter', srcSize, srcRect, dstSize, dstRect));
+ }
+ }
+
+ // .conversion
+ for (var srcFmtNdx = 0; srcFmtNdx < colorFormats.length; srcFmtNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var conversionGroup = tcuTestCase.newTest('conversion', 'Color conversion tests');
+ this.addChild(conversionGroup);
+ for (var dstFmtNdx = 0; dstFmtNdx < colorFormats.length; dstFmtNdx++) {
+ /** @type {number} */ var srcFormat = colorFormats[srcFmtNdx];
+ /** @type {tcuTexture.TextureFormat} */ var srcTexFmt = gluTextureUtil.mapGLInternalFormat(srcFormat);
+ /** @type {tcuTexture.TextureChannelClass} */ var srcType = tcuTexture.getTextureChannelClass(srcTexFmt.type);
+ /** @type {number} */ var dstFormat = colorFormats[dstFmtNdx];
+ /** @type {tcuTexture.TextureFormat} */ var dstTexFmt = gluTextureUtil.mapGLInternalFormat(dstFormat);
+ /** @type {tcuTexture.TextureChannelClass} */ var dstType = tcuTexture.getTextureChannelClass(dstTexFmt.type);
+
+ if (((srcType == tcuTexture.TextureChannelClass.FLOATING_POINT || srcType == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) !=
+ (dstType == tcuTexture.TextureChannelClass.FLOATING_POINT || dstType == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT)) ||
+ ((srcType == tcuTexture.TextureChannelClass.SIGNED_INTEGER) != (dstType == tcuTexture.TextureChannelClass.SIGNED_INTEGER)) ||
+ ((srcType == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER) != (dstType == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER)))
+ continue; // Conversion not supported.
+
+ var name = es3fFboTestUtil.getFormatName(srcFormat) + '_to_' + es3fFboTestUtil.getFormatName(dstFormat);
+
+ conversionGroup.addChild(new es3fFramebufferBlitTests.BlitColorConversionCase(name, '', srcFormat, dstFormat, [127, 113]));
+ }
+ }
+
+ // .depth_stencil
+ /** @type {tcuTestCase.DeqpTest} */ var depthStencilGroup = tcuTestCase.newTest('depth_stencil', 'Depth and stencil blits');
+ this.addChild(depthStencilGroup);
+
+ for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
+ /** @type {number} */ var format = depthStencilFormats[fmtNdx];
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(format);
+ /** @type {string} */ var fmtName = es3fFboTestUtil.getFormatName(format);
+ /** @type {boolean} */ var depth = texFmt.order == tcuTexture.ChannelOrder.D || texFmt.order == tcuTexture.ChannelOrder.DS;
+ /** @type {boolean} */ var stencil = texFmt.order == tcuTexture.ChannelOrder.S || texFmt.order == tcuTexture.ChannelOrder.DS;
+ /** @type {number} */ var buffers = (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0);
+
+ depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_basic'), '', format, buffers, [128, 128], [0, 0, 128, 128], buffers, [128, 128], [0, 0, 128, 128], buffers));
+ depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_scale'), '', format, buffers, [127, 119], [10, 30, 100, 70], buffers, [111, 130], [20, 5, 80, 130], buffers));
+
+ if (depth && stencil) {
+ depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_depth_only'), '', format, buffers, [128, 128], [0, 0, 128, 128], buffers, [128, 128], [0, 0, 128, 128], gl.DEPTH_BUFFER_BIT));
+ depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_stencil_only'), '', format, buffers, [128, 128], [0, 0, 128, 128], buffers, [128, 128], [0, 0, 128, 128], gl.STENCIL_BUFFER_BIT));
+ }
+ }
+
+ // .default_framebuffer
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {es3fFramebufferBlitTests.BlitArea} area
+ */
+ var Area = function(name, area) {
+ /** @type {string} name */ this.name = name;
+ /** @type {es3fFramebufferBlitTests.BlitArea} area */ this.area = area;
+ };
+
+ /** @type {Array<Area>} */ var areas = [
+ new Area('scale', es3fFramebufferBlitTests.BlitArea.AREA_SCALE),
+ new Area('out_of_bounds', es3fFramebufferBlitTests.BlitArea.AREA_OUT_OF_BOUNDS)
+ ];
+
+ var numDefaultFbSubGroups = 7;
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var defaultFbGroup = [];
+ for (var ii = 0; ii < numDefaultFbSubGroups; ++ii) {
+ defaultFbGroup[ii] = tcuTestCase.newTest('default_framebuffer', 'Blits with default framebuffer');
+ this.addChild(defaultFbGroup[ii]);
+ }
+ for (var fmtNdx = 0; fmtNdx < colorFormats.length; fmtNdx++) {
+ var format = colorFormats[fmtNdx];
+ var texFmt = gluTextureUtil.mapGLInternalFormat(format);
+ var fmtClass = tcuTexture.getTextureChannelClass(texFmt.type);
+ var filter = gluTextureUtil.isGLInternalColorFormatFilterable(format) ? gl.LINEAR : gl.NEAREST;
+ var filterable = gluTextureUtil.isGLInternalColorFormatFilterable(format);
+
+ if (fmtClass != tcuTexture.TextureChannelClass.FLOATING_POINT &&
+ fmtClass != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT &&
+ fmtClass != tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT)
+ continue; // Conversion not supported.
+
+ defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.BlitDefaultFramebufferCase(es3fFboTestUtil.getFormatName(format), '', format, filter));
+
+ for (var areaNdx = 0; areaNdx < areas.length; areaNdx++) {
+ var name = areas[areaNdx].name;
+ var addLinear = filterable;
+ var addNearest = !addLinear || (areas[areaNdx].area != es3fFramebufferBlitTests.BlitArea.AREA_OUT_OF_BOUNDS); // No need to check out-of-bounds with different filtering
+
+ if (addNearest) {
+
+ defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_nearest_' + name + '_blit_from_default'), '', format, gl.NEAREST, es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area));
+ defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_nearest_' + name + '_blit_to_default'), '', format, gl.NEAREST, es3fFramebufferBlitTests.BlitDirection.BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area));
+ }
+
+ if (addLinear) {
+ defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_linear_' + name + '_blit_from_default'), '', format, gl.LINEAR, es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area));
+ defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_linear_' + name + '_blit_to_default'), '', format, gl.LINEAR, es3fFramebufferBlitTests.BlitDirection.BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area));
+ }
+ }
+ }
+ };
+
+ /**
+ * @param {?tcuTexture.ChannelOrder} order
+ * @return {Array<boolean>}
+ */
+ es3fFramebufferBlitTests.getChannelMask = function(order) {
+ switch (order) {
+ case tcuTexture.ChannelOrder.R: return [true, false, false, false];
+ case tcuTexture.ChannelOrder.RG: return [true, true, false, false];
+ case tcuTexture.ChannelOrder.RGB: return [true, true, true, false];
+ case tcuTexture.ChannelOrder.RGBA: return [true, true, true, true];
+ case tcuTexture.ChannelOrder.sRGB: return [true, true, true, false];
+ case tcuTexture.ChannelOrder.sRGBA: return [true, true, true, true];
+ default:
+ DE_ASSERT(false);
+ return [false, false, false, false];
+ }
+ };
+
+ /**
+ * es3fFramebufferBlitTests.BlitColorConversionCase class, inherits from FboTestCase
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} srcFormat
+ * @param {number} dstFormat
+ * @param {Array<number>} size
+ */
+ es3fFramebufferBlitTests.BlitColorConversionCase = function(name, desc, srcFormat, dstFormat, size) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @type {number} */ this.m_srcFormat = srcFormat;
+ /** @type {number} */ this.m_dstFormat = dstFormat;
+ /** @type {Array<number>} */ this.m_size = size;
+ };
+
+ es3fFramebufferBlitTests.BlitColorConversionCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFramebufferBlitTests.BlitColorConversionCase.prototype.constructor = es3fFramebufferBlitTests.BlitColorConversionCase;
+
+ es3fFramebufferBlitTests.BlitColorConversionCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_srcFormat);
+ this.checkFormatSupport(this.m_dstFormat);
+ return true; // No exception thrown
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFramebufferBlitTests.BlitColorConversionCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ /** @type {tcuTexture.TextureFormat} */ var srcFormat = gluTextureUtil.mapGLInternalFormat(this.m_srcFormat);
+ /** @type {tcuTexture.TextureFormat} */ var dstFormat = gluTextureUtil.mapGLInternalFormat(this.m_dstFormat);
+
+ /** @type {gluShaderUtil.DataType} */ var srcOutputType = es3fFboTestUtil.getFragmentOutputType(srcFormat);
+ /** @type {gluShaderUtil.DataType} */ var dstOutputType = es3fFboTestUtil.getFragmentOutputType(dstFormat);
+
+ // Compute ranges \note Doesn't handle case where src or dest is not subset of the another!
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var srcFmtRangeInfo = tcuTextureUtil.getTextureFormatInfo(srcFormat);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var dstFmtRangeInfo = tcuTextureUtil.getTextureFormatInfo(dstFormat);
+
+ /** @type {Array<boolean>} */ var copyMask = deMath.logicalAndBool(es3fFramebufferBlitTests.getChannelMask(srcFormat.order), es3fFramebufferBlitTests.getChannelMask(dstFormat.order));
+ /** @type {Array<boolean>} */ var srcIsGreater = deMath.greaterThan(deMath.subtract(srcFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMin), deMath.subtract(dstFmtRangeInfo.valueMax, dstFmtRangeInfo.valueMin));
+
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var srcRangeInfo = new tcuTextureUtil.TextureFormatInfo(
+ tcuTextureUtil.select(dstFmtRangeInfo.valueMin, srcFmtRangeInfo.valueMin, deMath.logicalAndBool(copyMask, srcIsGreater)),
+ tcuTextureUtil.select(dstFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMax, deMath.logicalAndBool(copyMask, srcIsGreater)),
+ tcuTextureUtil.select(dstFmtRangeInfo.lookupScale, srcFmtRangeInfo.lookupScale, deMath.logicalAndBool(copyMask, srcIsGreater)),
+ tcuTextureUtil.select(dstFmtRangeInfo.lookupBias, srcFmtRangeInfo.lookupBias, deMath.logicalAndBool(copyMask, srcIsGreater)));
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var dstRangeInfo = new tcuTextureUtil.TextureFormatInfo(
+ tcuTextureUtil.select(dstFmtRangeInfo.valueMin, srcFmtRangeInfo.valueMin, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)),
+ tcuTextureUtil.select(dstFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMax, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)),
+ tcuTextureUtil.select(dstFmtRangeInfo.lookupScale, srcFmtRangeInfo.lookupScale, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)),
+ tcuTextureUtil.select(dstFmtRangeInfo.lookupBias, srcFmtRangeInfo.lookupBias, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)));
+
+ // Shaders.
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradientToSrcShader = new es3fFboTestUtil.GradientShader(srcOutputType);
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var gradientToDstShader = new es3fFboTestUtil.GradientShader(dstOutputType);
+
+ var gradShaderSrcID = ctx.createProgram(gradientToSrcShader);
+ var gradShaderDstID = ctx.createProgram(gradientToDstShader);
+
+ var srcFbo;
+ var dstFbo;
+ var srcRbo;
+ var dstRbo;
+
+ // Create framebuffers.
+ // Source framebuffers
+ srcFbo = ctx.createFramebuffer();
+ srcRbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, srcRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_srcFormat, this.m_size[0], this.m_size[1]);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, srcRbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // Destination framebuffers
+ dstFbo = ctx.createFramebuffer();
+ dstRbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, dstRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_dstFormat, this.m_size[0], this.m_size[1]);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dstRbo);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ ctx.viewport(0, 0, this.m_size[0], this.m_size[1]);
+
+ // Render gradients.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, ndx ? dstFbo : srcFbo);
+ if (ndx) {
+ gradientToDstShader.setGradient(ctx, gradShaderDstID, dstRangeInfo.valueMax, dstRangeInfo.valueMin);
+ rrUtil.drawQuad(ctx, gradShaderDstID, [-1, -1, 0], [1, 1, 0]);
+ } else {
+ gradientToSrcShader.setGradient(ctx, gradShaderSrcID, srcRangeInfo.valueMin, srcRangeInfo.valueMax);
+ rrUtil.drawQuad(ctx, gradShaderSrcID, [-1, -1, 0], [1, 1, 0]);
+ }
+ }
+
+ // Execute copy.
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFbo);
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFbo);
+ ctx.blitFramebuffer(0, 0, this.m_size[0], this.m_size[1], 0, 0, this.m_size[0], this.m_size[1], gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.checkError();
+
+ // Read results.
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, dstFbo);
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_size[0], this.m_size[1], dstFormat, dstRangeInfo.lookupScale, dstRangeInfo.lookupBias);
+
+ };
+
+ /**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ */
+ es3fFramebufferBlitTests.BlitColorConversionCase.prototype.compare = function(reference, result) {
+ /** @const {tcuTexture.TextureFormat} */ var srcFormat = gluTextureUtil.mapGLInternalFormat(this.m_srcFormat);
+ /** @const {tcuTexture.TextureFormat} */ var dstFormat = gluTextureUtil.mapGLInternalFormat(this.m_dstFormat);
+ /** @const {boolean} */ var srcIsSRGB = (srcFormat.order == tcuTexture.ChannelOrder.sRGBA);
+ /** @const {boolean} */ var dstIsSRGB = (dstFormat.order == tcuTexture.ChannelOrder.sRGBA);
+ /** @type {tcuRGBA.RGBA} */ var threshold = new tcuRGBA.RGBA();
+
+ if (dstIsSRGB)
+ threshold = es3fFboTestUtil.getToSRGBConversionThreshold(srcFormat, dstFormat);
+ else {
+ /** @type {tcuRGBA.RGBA} */ var srcMaxDiff = es3fFboTestUtil.getThresholdFromTextureFormat(srcFormat);
+ /** @type {tcuRGBA.RGBA} */ var dstMaxDiff = es3fFboTestUtil.getThresholdFromTextureFormat(dstFormat);
+ if (srcIsSRGB)
+ srcMaxDiff = tcuRGBA.multiply(srcMaxDiff, 2);
+
+ threshold = tcuRGBA.max(srcMaxDiff, dstMaxDiff);
+ }
+
+ // m_testCtx.getLog() << tcu::TestLog::Message << 'threshold = ' << threshold << tcu::TestLog::EndMessage;
+ return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, result, threshold.toIVec());
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format deUint32
+ * @param {number} srcBuffers deUint32
+ * @param {Array<number>} srcSize IVec2
+ * @param {Array<number>} srcRect IVec4
+ * @param {number} dstBuffers deUint32
+ * @param {Array<number>} dstSize IVec2
+ * @param {Array<number>} dstRect IVec4
+ * @param {number} copyBuffers deUint32
+ */
+ es3fFramebufferBlitTests.BlitDepthStencilCase = function(name, desc, format, srcBuffers, srcSize, srcRect, dstBuffers, dstSize, dstRect, copyBuffers) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @type {number} */ this.m_format = format;
+ /** @type {number} */ this.m_srcBuffers = srcBuffers;
+ /** @type {Array<number>} */ this.m_srcSize = srcSize;
+ /** @type {Array<number>} */ this.m_srcRect = srcRect;
+ /** @type {number} */ this.m_dstBuffers = dstBuffers;
+ /** @type {Array<number>} */ this.m_dstSize = dstSize;
+ /** @type {Array<number>} */ this.m_dstRect = dstRect;
+ /** @type {number} */ this.m_copyBuffers = copyBuffers;
+ };
+
+ es3fFramebufferBlitTests.BlitDepthStencilCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFramebufferBlitTests.BlitDepthStencilCase.prototype.constructor = es3fFramebufferBlitTests.BlitDepthStencilCase;
+
+ /**
+ * @protected
+ */
+ es3fFramebufferBlitTests.BlitDepthStencilCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+ /**
+ * @protected
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFramebufferBlitTests.BlitDepthStencilCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ /** @const {number} */ var colorFormat = gl.RGBA8;
+ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D] ,
+ gluShaderUtil.DataType.FLOAT_VEC4);
+ var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var flatShaderID = ctx.createProgram(flatShader);
+ var texShaderID = ctx.createProgram(texShader);
+ var gradShaderID = ctx.createProgram(gradShader);
+
+ var srcFbo;
+ var dstFbo;
+ var srcColorRbo;
+ var dstColorRbo;
+ var srcDepthStencilRbo;
+ var dstDepthStencilRbo;
+
+ // setup shaders
+ gradShader.setGradient(ctx, gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ texShader.setUniforms(ctx, texShaderID);
+
+ // Create framebuffers
+ // Source framebuffers
+ srcFbo = ctx.createFramebuffer();
+ srcColorRbo = ctx.createRenderbuffer();
+ srcDepthStencilRbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, srcColorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_srcSize[0], this.m_srcSize[1]);
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, srcDepthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_srcSize[0], this.m_srcSize[1]);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, srcColorRbo);
+
+ if (this.m_srcBuffers & gl.DEPTH_BUFFER_BIT)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, srcDepthStencilRbo);
+ if (this.m_srcBuffers & gl.STENCIL_BUFFER_BIT)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, srcDepthStencilRbo);
+
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // Clear depth to 1 and stencil to 0.
+ ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ // Destination framebuffers
+ dstFbo = ctx.createFramebuffer();
+ dstColorRbo = ctx.createRenderbuffer();
+ dstDepthStencilRbo = ctx.createRenderbuffer();
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, dstColorRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_dstSize[0], this.m_dstSize[1]);
+
+ ctx.bindRenderbuffer(gl.RENDERBUFFER, dstDepthStencilRbo);
+ ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_dstSize[0], this.m_dstSize[1]);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dstColorRbo);
+
+ if (this.m_dstBuffers & gl.DEPTH_BUFFER_BIT)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, dstDepthStencilRbo);
+ if (this.m_dstBuffers & gl.STENCIL_BUFFER_BIT)
+ ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, dstDepthStencilRbo);
+
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // Clear depth to 1 and stencil to 0.
+ ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
+
+ // Fill source with gradient, depth = [-1..1], stencil = 7
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
+ ctx.viewport(0, 0, this.m_srcSize[0], this.m_srcSize[1]);
+ ctx.enable(gl.DEPTH_TEST);
+ ctx.enable(gl.STENCIL_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+ ctx.stencilFunc(gl.ALWAYS, 7, 0xff);
+
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, -1], [1, 1, 1]);
+
+ // Fill destination with grid pattern, depth = 0 and stencil = 1
+ /** @const {number} */ var format = gl.RGBA;
+ /** @const {number} */ var dataType = gl.UNSIGNED_BYTE;
+ /** @const {number} */ var texW = this.m_srcSize[0];
+ /** @const {number} */ var texH = this.m_srcSize[1];
+ /** @type {WebGLTexture|sglrReferenceContext.TextureContainer} */ var gridTex = null;
+ /** @type {tcuTexture.TextureLevel} */ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 8, [0.2, 0.7, 0.1, 1.0], [0.7, 0.1, 0.5, 0.8]);
+
+ gridTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, gridTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
+ ctx.viewport(0, 0, this.m_dstSize[0], this.m_dstSize[1]);
+ ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
+
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ // Perform copy.
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFbo);
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFbo);
+ ctx.blitFramebuffer(this.m_srcRect[0], this.m_srcRect[1], this.m_srcRect[2], this.m_srcRect[3], this.m_dstRect[0], this.m_dstRect[1], this.m_dstRect[2], this.m_dstRect[3], this.m_copyBuffers, gl.NEAREST);
+
+ // Render blue color where depth < 0, decrement on depth failure.
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
+ ctx.viewport(0, 0, this.m_dstSize[0], this.m_dstSize[1]);
+ ctx.stencilOp(gl.KEEP, gl.DECR, gl.KEEP);
+ ctx.stencilFunc(gl.ALWAYS, 0, 0xff);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 0.0, 1.0, 1.0]);
+
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ if (this.m_dstBuffers & gl.STENCIL_BUFFER_BIT) {
+ // Render green color where stencil == 6.
+ ctx.disable(gl.DEPTH_TEST);
+ ctx.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ ctx.stencilFunc(gl.EQUAL, 6, 0xff);
+
+ flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 1.0, 0.0, 1.0]);
+
+ rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ }
+ this.readPixelsUsingFormat(dst, 0, 0, this.m_dstSize[0], this.m_dstSize[1], gluTextureUtil.mapGLInternalFormat(colorFormat), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
+
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFboTestCase.FboTestCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} filter
+ */
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase = function(name, desc, format, filter) {
+ es3fFboTestCase.FboTestCase.call(this, name, desc);
+ /** @const {number} */ this.m_format = format;
+ /** @const {number} */ this.m_filter = filter;
+ };
+
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.constructor = es3fFramebufferBlitTests.BlitDefaultFramebufferCase;
+
+ /**
+ * @protected
+ */
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.preCheck = function() {
+ this.checkFormatSupport(this.m_format);
+ return true; // No exception thrown
+ };
+
+ /**
+ * @protected
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.render = function(dst) {
+ var ctx = this.getCurrentContext();
+ /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(colorFormat);
+
+ /** @type {es3fFboTestUtil.GradientShader} */ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
+ /** @type {es3fFboTestUtil.Texture2DShader} */ var texShader = new es3fFboTestUtil.Texture2DShader([gluTextureUtil.getSampler2DType(colorFormat)], gluShaderUtil.DataType.FLOAT_VEC4);
+
+ var gradShaderID = ctx.createProgram(gradShader);
+ var texShaderID = ctx.createProgram(texShader);
+ var fbo;
+ var tex;
+ /** @const {number} */ var texW = 128;
+ /** @const {number} */ var texH = 128;
+
+ // Setup shaders
+ gradShader.setGradient(ctx, gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ texShader.setUniforms(ctx, texShaderID);
+
+ // FBO
+ fbo = ctx.createFramebuffer();
+ tex = ctx.createTexture();
+
+ ctx.bindTexture(gl.TEXTURE_2D, tex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_filter);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_filter);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_format, texW, texH, 0, transferFmt.format, transferFmt.dataType, null);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ // Render gradient to screen.
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ // Blit gradient from screen to fbo.
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo);
+ ctx.blitFramebuffer(0, 0, ctx.getWidth(), ctx.getHeight(), 0, 0, texW, texH, gl.COLOR_BUFFER_BIT, this.m_filter);
+
+ // Fill left half of viewport with quad that uses texture.
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ ctx.clearBufferfv(gl.COLOR, 0, [1.0, 0.0, 0.0, 1.0]);
+
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ // Blit fbo to right half.
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo);
+ ctx.blitFramebuffer(0, 0, texW, texH, Math.floor(ctx.getWidth() / 2), 0, ctx.getWidth(), ctx.getHeight(), gl.COLOR_BUFFER_BIT, this.m_filter);
+
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
+ this.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
+
+ };
+
+ /**
+ * @protected
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ */
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.compare = function(reference, result) {
+ /** @const {tcuRGBA.RGBA} */
+ var threshold = tcuRGBA.max(es3fFboTestUtil.getFormatThreshold(this.m_format), tcuRGBA.newRGBAComponents(12, 12, 12, 12));
+
+ //m_testCtx.getLog() << TestLog::Message << 'Comparing images, threshold: ' << threshold << TestLog::EndMessage;
+
+ return tcuImageCompare.bilinearCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), threshold);
+ };
+
+ /** @enum */
+ es3fFramebufferBlitTests.BlitDirection = {
+ BLIT_DEFAULT_TO_TARGET: 0,
+ BLIT_TO_DEFAULT_FROM_TARGET: 1
+ };
+
+ /** @enum */
+ es3fFramebufferBlitTests.BlitArea = {
+ AREA_SCALE: 0,
+ AREA_OUT_OF_BOUNDS: 1
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fFramebufferBlitTests.BlitDefaultFramebufferCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} filter
+ * @param {es3fFramebufferBlitTests.BlitDirection} dir
+ * @param {es3fFramebufferBlitTests.BlitArea} area
+ */
+ es3fFramebufferBlitTests.DefaultFramebufferBlitCase = function(name, desc, format, filter, dir, area) {
+ es3fFramebufferBlitTests.BlitDefaultFramebufferCase.call(this, name, desc, format, filter);
+ /** @const {es3fFramebufferBlitTests.BlitDirection} */ this.m_blitDir = dir;
+ /** @const {es3fFramebufferBlitTests.BlitArea} */ this.m_blitArea = area;
+ /** @type {Array<number>} */ this.m_srcRect = [-1, -1, -1, -1];
+ /** @type {Array<number>} */ this.m_dstRect = [-1, -1, -1, -1];
+ /** @type {Array<number>} */ this.m_interestingArea = [-1, -1, -1, -1];
+ };
+
+ es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype = Object.create(es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype);
+ es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype.constructor = es3fFramebufferBlitTests.DefaultFramebufferBlitCase;
+
+ es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype.init = function() {
+ // requirements
+ /** @const {number} */ var minViewportSize = 128;
+ if (gl.drawingBufferWidth < minViewportSize ||
+ gl.drawingBufferHeight < minViewportSize)
+ throw new Error('Viewport size ' + minViewportSize + 'x' + minViewportSize + ' required');
+
+ // prevent viewport randoming
+ this.m_viewportWidth = gl.drawingBufferWidth;
+ this.m_viewportHeight = gl.drawingBufferHeight;
+
+ // set proper areas
+ if (this.m_blitArea == es3fFramebufferBlitTests.BlitArea.AREA_SCALE) {
+ this.m_srcRect = [10, 20, 65, 100];
+ this.m_dstRect = [25, 30, 125, 94];
+ this.m_interestingArea = [0, 0, 128, 128];
+ } else if (this.m_blitArea == es3fFramebufferBlitTests.BlitArea.AREA_OUT_OF_BOUNDS) {
+ /** @const {Array<number>} */
+ var ubound = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ?
+ ([128, 128]) :
+ ([gl.drawingBufferWidth, gl.drawingBufferHeight]);
+
+ this.m_srcRect = [-10, -15, 100, 63];
+ this.m_dstRect = deMath.add(deMath.swizzle(ubound, [0, 1, 0, 1]), [-75, -99, 8, 16]);
+ this.m_interestingArea = [ubound[0] - 128, ubound[1] - 128, ubound[0], ubound[1]];
+ }
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype.render = function(dst) {
+ /** @type {es3fFboTestCase.Context} */
+ var ctx = this.getCurrentContext();
+ // TOOD: implement
+ /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(colorFormat);
+ /** @const {tcuTexture.TextureChannelClass} */
+ var targetClass = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ?
+ (tcuTexture.getTextureChannelClass(colorFormat.type)) :
+ (tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT);
+
+ var fbo;
+ var fboTex;
+ /** @const {number} */ var fboTexW = 128;
+ /** @const {number} */ var fboTexH = 128;
+ /** @const {number} */ var sourceWidth = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (ctx.getWidth()) : (fboTexW);
+ /** @const {number} */ var sourceHeight = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (ctx.getHeight()) : (fboTexH);
+ /** @const {number} */ var gridRenderWidth = Math.min(256, sourceWidth);
+ /** @const {number} */ var gridRenderHeight = Math.min(256, sourceHeight);
+
+ var targetFbo;
+ var sourceFbo;
+
+ // FBO
+ fbo = ctx.createFramebuffer();
+ fboTex = ctx.createTexture();
+
+ ctx.bindTexture(gl.TEXTURE_2D, fboTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_filter);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_filter);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_format, fboTexW, fboTexH, 0, transferFmt.format, transferFmt.dataType, null);
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fboTex, 0);
+ this.checkError();
+ this.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ targetFbo = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (fbo) : (null);
+ sourceFbo = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (null) : (fbo);
+
+ // Render grid to source framebuffer
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var texShader = new es3fFboTestUtil.Texture2DShader(
+ [gluShaderUtil.DataType.SAMPLER_2D],
+ gluShaderUtil.DataType.FLOAT_VEC4);
+ var texShaderID = this.getCurrentContext().createProgram(texShader);
+ /** @const {number} */ var internalFormat = gl.RGBA8;
+ /** @const {number} */ var format = gl.RGBA;
+ /** @const {number} */ var dataType = gl.UNSIGNED_BYTE;
+ /** @const {number} */ var gridTexW = 128;
+ /** @const {number} */ var gridTexH = 128;
+ /** @type {WebGLTexture|framework.opengl.simplereference.sglrReferenceContext.TextureContainer|null} */
+ var gridTex = null;
+ /** @type {tcuTexture.TextureLevel} */ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), gridTexW, gridTexH, 1);
+
+ tcuTextureUtil.fillWithGrid(data.getAccess(), 9, [0.9, 0.5, 0.1, 0.9], [0.2, 0.8, 0.2, 0.7]);
+
+ gridTex = ctx.createTexture();
+ ctx.bindTexture(gl.TEXTURE_2D, gridTex);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ ctx.texImage2D(gl.TEXTURE_2D, 0, internalFormat, gridTexW, gridTexH, 0, format, dataType, data.getAccess().getDataPtr());
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, sourceFbo);
+ ctx.viewport(0, 0, gridRenderWidth, gridRenderHeight);
+ ctx.clearBufferfv(gl.COLOR, 0, [1.0, 0.0, 0.0, 1.0]);
+
+ texShader.setUniforms(this.getCurrentContext(), texShaderID);
+
+ rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
+
+ ctx.useProgram(null);
+
+ // Blit source framebuffer to destination
+
+ ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, sourceFbo);
+ ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, targetFbo);
+ this.checkError();
+
+ if (targetClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT ||
+ targetClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ||
+ targetClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
+ ctx.clearBufferfv(gl.COLOR, 0, [1.0, 1.0, 0.0, 1.0]);
+ else if (targetClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER)
+ ctx.clearBufferiv(gl.COLOR, 0, [0, 0, 0, 0]);
+ else if (targetClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER)
+ ctx.clearBufferuiv(gl.COLOR, 0, [0, 0, 0, 0]);
+ else
+ DE_ASSERT(false);
+
+ ctx.blitFramebuffer(this.m_srcRect[0], this.m_srcRect[1], this.m_srcRect[2], this.m_srcRect[3], this.m_dstRect[0], this.m_dstRect[1], this.m_dstRect[2], this.m_dstRect[3], gl.COLOR_BUFFER_BIT, this.m_filter);
+ this.checkError();
+
+ // Read target
+
+ ctx.bindFramebuffer(gl.FRAMEBUFFER, targetFbo);
+
+ if (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_TO_DEFAULT_FROM_TARGET)
+ this.readPixels(dst, this.m_interestingArea[0], this.m_interestingArea[1], this.m_interestingArea[2] - this.m_interestingArea[0], this.m_interestingArea[3] - this.m_interestingArea[1]);
+ else
+ this.readPixelsUsingFormat(dst, this.m_interestingArea[0], this.m_interestingArea[1], this.m_interestingArea[2] - this.m_interestingArea[0], this.m_interestingArea[3] - this.m_interestingArea[1], colorFormat, [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
+
+ this.checkError();
+ };
+
+ es3fFramebufferBlitTests.run = function(context, range) {
+ gl = context;
+ //Set up root Test
+ var state = tcuTestCase.runner;
+
+ var test = new es3fFramebufferBlitTests.FramebufferBlitTests();
+ var testName = test.fullName();
+ var testDescription = test.getDescription() || '';
+
+ state.testName = testName;
+ state.setRoot(test);
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ test.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ bufferedLogToConsole(err);
+ testFailedOptions('Failed to es3fFramebufferBlitTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIndexedStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIndexedStateQueryTests.js
new file mode 100644
index 0000000000..a18f6708b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIndexedStateQueryTests.js
@@ -0,0 +1,409 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fIndexedStateQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+ var es3fIndexedStateQueryTests = functional.gles3.es3fIndexedStateQueryTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIndexedStateQueryTests.TransformFeedbackCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIndexedStateQueryTests.TransformFeedbackCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIndexedStateQueryTests.TransformFeedbackCase.prototype.constructor = es3fIndexedStateQueryTests.TransformFeedbackCase;
+
+ es3fIndexedStateQueryTests.TransformFeedbackCase.prototype.testTransformFeedback = function() {
+ throw new Error('This method should be overriden.');
+ };
+
+ es3fIndexedStateQueryTests.TransformFeedbackCase.prototype.test = function() {
+ /** @type {string} */ var transformFeedbackTestVertSource = '' +
+ '#version 300 es\n' +
+ 'out highp vec4 anotherOutput;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ ' anotherOutput = vec4(0.0);\n' +
+ '}\n';
+ /** @type {string} */ var transformFeedbackTestFragSource = '' +
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ /** @type {WebGLShader} */ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {WebGLShader} */ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, transformFeedbackTestVertSource);
+ gl.shaderSource(shaderFrag, transformFeedbackTestFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ /** @type {WebGLProgram} */ var shaderProg = gl.createProgram();
+ gl.attachShader(shaderProg, shaderVert);
+ gl.attachShader(shaderProg, shaderFrag);
+
+ /** @type {Array<string>} */ var transformFeedbackOutputs = ['gl_Position', 'anotherOutput'];
+
+ gl.transformFeedbackVaryings(shaderProg, transformFeedbackOutputs, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(shaderProg);
+
+ /** @type {WebGLTransformFeedback} */ var transformFeedbackId = gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedbackId);
+
+ this.testTransformFeedback();
+
+ // cleanup
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+
+ gl.deleteTransformFeedback(transformFeedbackId);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(shaderProg);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIndexedStateQueryTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBindingCase = function(name, description) {
+ es3fIndexedStateQueryTests.TransformFeedbackCase.call(this, name, description);
+ };
+
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBindingCase.prototype = Object.create(es3fIndexedStateQueryTests.TransformFeedbackCase.prototype);
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBindingCase.prototype.constructor = es3fIndexedStateQueryTests.TransformFeedbackBufferBindingCase;
+
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBindingCase.prototype.testTransformFeedback = function() {
+ /** @type {number} */ var feedbackPositionIndex = 0;
+ /** @type {number} */ var feedbackOutputIndex = 1;
+ /** @type {Array<number>} */ var feedbackIndex = [feedbackPositionIndex, feedbackOutputIndex];
+
+ // bind buffers
+
+ /** @type {Array<WebGLBuffer>} */ var feedbackBuffers = [];
+ for (var ndx = 0; ndx < 2; ndx++)
+ feedbackBuffers[ndx] = gl.createBuffer();
+
+ for (var ndx = 0; ndx < feedbackBuffers.length; ndx++) {
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackBuffers[ndx]);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array(16), gl.DYNAMIC_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackIndex[ndx], feedbackBuffers[ndx]);
+ }
+
+ // test TRANSFORM_FEEDBACK_BUFFER_BINDING
+ for (var ndx = 0; ndx < feedbackBuffers.length; ndx++) {
+ var boundBuffer = /** @type {WebGLBuffer} */ (gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, ndx));
+ this.check(boundBuffer === feedbackBuffers[ndx], 'buffers do not match');
+ }
+
+ // cleanup
+ for (var ndx = 0; ndx < feedbackBuffers.length; ndx++)
+ gl.deleteBuffer(feedbackBuffers[ndx]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIndexedStateQueryTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBufferCase = function(name, description) {
+ es3fIndexedStateQueryTests.TransformFeedbackCase.call(this, name, description);
+ };
+
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBufferCase.prototype = Object.create(es3fIndexedStateQueryTests.TransformFeedbackCase.prototype);
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBufferCase.prototype.constructor = es3fIndexedStateQueryTests.TransformFeedbackBufferBufferCase;
+
+ es3fIndexedStateQueryTests.TransformFeedbackBufferBufferCase.prototype.testTransformFeedback = function() {
+ /** @type {number} */ var feedbackPositionIndex = 0;
+ /** @type {number} */ var feedbackOutputIndex = 1;
+
+ /** @type {number} */ var rangeBufferOffset = 4;
+ /** @type {number} */ var rangeBufferSize = 8;
+
+ // bind buffers
+
+ /** @type {Array<WebGLBuffer>} */ var feedbackBuffers = [];
+ for (var ndx = 0; ndx < 2; ndx++)
+ feedbackBuffers[ndx] = gl.createBuffer();
+
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackBuffers[0]);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array(16), gl.DYNAMIC_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackPositionIndex, feedbackBuffers[0]);
+
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackBuffers[1]);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array(16), gl.DYNAMIC_READ);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackOutputIndex, feedbackBuffers[1], rangeBufferOffset, rangeBufferSize);
+
+ /** @type {Array<{index: number, pname: number, value: number}>} */ var requirements = [
+ {index: feedbackPositionIndex, pname: gl.TRANSFORM_FEEDBACK_BUFFER_START, value: 0},
+ {index: feedbackPositionIndex, pname: gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, value: 0},
+ {index: feedbackOutputIndex, pname: gl.TRANSFORM_FEEDBACK_BUFFER_START, value: rangeBufferOffset},
+ {index: feedbackOutputIndex, pname: gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, value: rangeBufferSize}
+ ];
+
+ for (var ndx = 0; ndx < requirements.length; ndx++) {
+ var state = /** @type {number} */ (gl.getIndexedParameter(requirements[ndx].pname, requirements[ndx].index));
+ this.check(state === requirements[ndx].value, 'got ' + state + '; expected ' + requirements[ndx].value);
+ }
+
+ // cleanup
+ for (var ndx = 0; ndx < feedbackBuffers.length; ndx++)
+ gl.deleteBuffer(feedbackBuffers[ndx]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIndexedStateQueryTests.UniformBufferCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {?WebGLProgram} */ this.m_program = null;
+ };
+
+ es3fIndexedStateQueryTests.UniformBufferCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIndexedStateQueryTests.UniformBufferCase.prototype.constructor = es3fIndexedStateQueryTests.UniformBufferCase;
+
+ es3fIndexedStateQueryTests.UniformBufferCase.prototype.testUniformBuffers = function() {
+ throw new Error('This method should be overriden.');
+ };
+
+ es3fIndexedStateQueryTests.UniformBufferCase.prototype.test = function() {
+
+ /** @type {string} */ var testVertSource = '' +
+ '#version 300 es\n' +
+ 'uniform highp vec4 input1;\n' +
+ 'uniform highp vec4 input2;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = input1 + input2;\n' +
+ '}\n';
+ /** @type {string} */ var testFragSource = '' +
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ /** @type {WebGLShader} */ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {WebGLShader} */ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ this.m_program = gl.createProgram();
+ gl.attachShader(this.m_program, shaderVert);
+ gl.attachShader(this.m_program, shaderFrag);
+ gl.linkProgram(this.m_program);
+ gl.useProgram(this.m_program);
+
+ this.testUniformBuffers();
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(this.m_program);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIndexedStateQueryTests.UniformBufferCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIndexedStateQueryTests.UniformBufferBindingCase = function(name, description) {
+ es3fIndexedStateQueryTests.UniformBufferCase.call(this, name, description);
+ /** @type {?WebGLProgram} */ this.m_program = null;
+ };
+
+ es3fIndexedStateQueryTests.UniformBufferBindingCase.prototype = Object.create(es3fIndexedStateQueryTests.UniformBufferCase.prototype);
+ es3fIndexedStateQueryTests.UniformBufferBindingCase.prototype.constructor = es3fIndexedStateQueryTests.UniformBufferBindingCase;
+
+ es3fIndexedStateQueryTests.UniformBufferBindingCase.prototype.testUniformBuffers = function() {
+ /** @type {Array<string>} */ var uniformNames = ['input1', 'input2'];
+
+ /** @type {Array<number>} */ var uniformIndices = gl.getUniformIndices(this.m_program, uniformNames);
+
+ /** @type {Array<WebGLBuffer>} */ var buffers = [];
+ for (var ndx = 0; ndx < 2; ndx++)
+ buffers[ndx] = gl.createBuffer();
+
+ for (var ndx = 0; ndx < buffers.length; ++ndx) {
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffers[ndx]);
+ gl.bufferData(gl.UNIFORM_BUFFER, new Float32Array(32), gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, uniformIndices[ndx], buffers[ndx]);
+ }
+
+ /** @type {Array<WebGLBuffer>} */ var boundBuffer = [];
+ for (var ndx = 0; ndx < buffers.length; ndx++) {
+ boundBuffer[ndx] = /** @type {WebGLBuffer} */ (gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, uniformIndices[ndx]));
+ this.check(boundBuffer[ndx] === buffers[ndx], 'buffers do not match');
+ }
+
+ for (var ndx = 0; ndx < buffers.length; ndx++)
+ gl.deleteBuffer(buffers[ndx]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIndexedStateQueryTests.UniformBufferCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIndexedStateQueryTests.UniformBufferBufferCase = function(name, description) {
+ es3fIndexedStateQueryTests.UniformBufferCase.call(this, name, description);
+ /** @type {?WebGLProgram} */ this.m_program = null;
+ };
+
+ es3fIndexedStateQueryTests.UniformBufferBufferCase.prototype = Object.create(es3fIndexedStateQueryTests.UniformBufferCase.prototype);
+ es3fIndexedStateQueryTests.UniformBufferBufferCase.prototype.constructor = es3fIndexedStateQueryTests.UniformBufferBufferCase;
+
+ es3fIndexedStateQueryTests.UniformBufferBufferCase.prototype.testUniformBuffers = function() {
+ /** @type {Array<string>} */ var uniformNames = ['input1', 'input2'];
+
+ /** @type {Array<number>} */ var uniformIndices = gl.getUniformIndices(this.m_program, uniformNames);
+
+ /** @type {number} */ var alignment = this.getAlignment();
+ if (alignment === -1) // cannot continue without this
+ return;
+
+ bufferedLogToConsole('Alignment is ' + alignment);
+
+ /** @type {number} */ var rangeBufferOffset = alignment;
+ /** @type {number} */ var rangeBufferSize = alignment * 2;
+ /** @type {number} */ var rangeBufferTotalSize = rangeBufferOffset + rangeBufferSize + 8; // + 8 has no special meaning, just to make it != with the size of the range
+
+ /** @type {Array<WebGLBuffer>} */ var buffers = [];
+ for (var ndx = 0; ndx < 2; ndx++)
+ buffers[ndx] = gl.createBuffer();
+
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffers[0]);
+ gl.bufferData(gl.UNIFORM_BUFFER, new Float32Array(32), gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, uniformIndices[0], buffers[0]);
+
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffers[1]);
+ gl.bufferData(gl.UNIFORM_BUFFER, new Float32Array(32), gl.DYNAMIC_DRAW);
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformIndices[1], buffers[1], rangeBufferOffset, rangeBufferSize);
+
+ // test UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE
+
+ /** @type {Array<{index: number, pname: number, value: number}>} */ var requirements = [
+ {index: uniformIndices[0], pname: gl.UNIFORM_BUFFER_START, value: 0},
+ {index: uniformIndices[0], pname: gl.UNIFORM_BUFFER_SIZE, value: 0},
+ {index: uniformIndices[1], pname: gl.UNIFORM_BUFFER_START, value: rangeBufferOffset},
+ {index: uniformIndices[1], pname: gl.UNIFORM_BUFFER_SIZE, value: rangeBufferSize}
+ ];
+
+ for (var ndx = 0; ndx < requirements.length; ndx++) {
+ var state = /** @type {number} */ (gl.getIndexedParameter(requirements[ndx].pname, requirements[ndx].index));
+
+ this.check(state === requirements[ndx].value, 'got ' + state + '; expected ' + requirements[ndx].value);
+ }
+
+ for (var ndx = 0; ndx < buffers.length; ndx++)
+ gl.deleteBuffer(buffers[ndx]);
+
+ };
+
+ /**
+ * @return {number}
+ */
+ es3fIndexedStateQueryTests.UniformBufferBufferCase.prototype.getAlignment = function() {
+ var state = /** @type {number} */ (gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT));
+
+ if (state <= 256)
+ return state;
+
+ bufferedLogToConsole('ERROR: UNIFORM_BUFFER_OFFSET_ALIGNMENT has a maximum value of 256.');
+ testFailedOptions('invalid UNIFORM_BUFFER_OFFSET_ALIGNMENT value', false);
+
+ return -1;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fIndexedStateQueryTests.IndexedStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'indexed', 'Indexed Integer Values');
+ };
+
+ es3fIndexedStateQueryTests.IndexedStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fIndexedStateQueryTests.IndexedStateQueryTests.prototype.constructor = es3fIndexedStateQueryTests.IndexedStateQueryTests;
+
+ es3fIndexedStateQueryTests.IndexedStateQueryTests.prototype.init = function() {
+ // transform feedback
+ this.addChild(new es3fIndexedStateQueryTests.TransformFeedbackBufferBindingCase('transform_feedback_buffer_binding', 'TRANSFORM_FEEDBACK_BUFFER_BINDING'));
+ this.addChild(new es3fIndexedStateQueryTests.TransformFeedbackBufferBufferCase('transform_feedback_buffer_start_size', 'TRANSFORM_FEEDBACK_BUFFER_START and TRANSFORM_FEEDBACK_BUFFER_SIZE'));
+
+ // uniform buffers
+ this.addChild(new es3fIndexedStateQueryTests.UniformBufferBindingCase('uniform_buffer_binding', 'UNIFORM_BUFFER_BINDING'));
+ this.addChild(new es3fIndexedStateQueryTests.UniformBufferBufferCase('uniform_buffer_start_size', 'UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE'));
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fIndexedStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fIndexedStateQueryTests.IndexedStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fIndexedStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInstancedRenderingTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInstancedRenderingTests.js
new file mode 100644
index 0000000000..adc7e857ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInstancedRenderingTests.js
@@ -0,0 +1,711 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fInstancedRenderingTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var es3fInstancedRenderingTests = functional.gles3.es3fInstancedRenderingTests;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuSurface = framework.common.tcuSurface;
+var deString = framework.delibs.debase.deString;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var deMath = framework.delibs.debase.deMath;
+
+ /** @type {?WebGL2RenderingContext} */ var gl;
+
+ /** @const @type {number} */ es3fInstancedRenderingTests.MAX_RENDER_WIDTH = 128;
+ /** @const @type {number} */ es3fInstancedRenderingTests.MAX_RENDER_HEIGHT = 128;
+
+ /** @const @type {number} */ es3fInstancedRenderingTests.QUAD_GRID_SIZE = 127;
+
+ // Attribute divisors for the attributes defining the color's RGB components.
+ /** @const @type {number} */es3fInstancedRenderingTests.ATTRIB_DIVISOR_R = 3;
+ /** @const @type {number} */es3fInstancedRenderingTests.ATTRIB_DIVISOR_G = 2;
+ /** @const @type {number} */es3fInstancedRenderingTests.ATTRIB_DIVISOR_B = 1;
+
+ /** @const @type {number} */es3fInstancedRenderingTests.OFFSET_COMPONENTS = 3; // \note Affects whether a float or a vecN is used in shader, but only first component is non-zero.
+
+ // Scale and bias values when converting float to integer, when attribute is of integer type.
+ /** @const @type {number} */es3fInstancedRenderingTests.FLOAT_INT_SCALE = 100.0;
+ /** @const @type {number} */es3fInstancedRenderingTests.FLOAT_INT_BIAS = -50.0;
+ /** @const @type {number} */es3fInstancedRenderingTests.FLOAT_UINT_SCALE = 100.0;
+ /** @const @type {number} */es3fInstancedRenderingTests.FLOAT_UINT_BIAS = 0.0;
+
+ var DE_ASSERT = function(expression) {
+ if (!expression) throw new Error('Assert failed');
+ };
+
+ es3fInstancedRenderingTests.TCU_FAIL = function(message) {
+ throw new Error(message);
+ };
+
+ // es3fInstancedRenderingTests.InstancedRenderingCase
+
+ /**
+ * es3fInstancedRenderingTests.DrawFunction
+ * @enum {number}
+ */
+ es3fInstancedRenderingTests.DrawFunction = {
+ FUNCTION_DRAW_ARRAYS_INSTANCED: 0,
+ FUNCTION_DRAW_ELEMENTS_INSTANCED: 1
+ };
+
+ /**
+ * es3fInstancedRenderingTests.InstancingType
+ * @enum {number}
+ */
+ es3fInstancedRenderingTests.InstancingType = {
+ TYPE_INSTANCE_ID: 0,
+ TYPE_ATTRIB_DIVISOR: 1,
+ TYPE_MIXED: 2
+ };
+
+ /**
+ * es3fInstancedRenderingTests.InstancedRenderingCase class, inherits from TestCase class
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fInstancedRenderingTests.DrawFunction} drawFunction
+ * @param {es3fInstancedRenderingTests.InstancingType} instancingType
+ * @param {gluShaderUtil.DataType} rgbAttrType
+ * @param {number} numInstances
+ */
+ es3fInstancedRenderingTests.InstancedRenderingCase = function(name, description, drawFunction, instancingType, rgbAttrType, numInstances) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {es3fInstancedRenderingTests.DrawFunction} */ this.m_function = drawFunction;
+ /** @type {es3fInstancedRenderingTests.InstancingType} */ this.m_instancingType = instancingType;
+ /** @type {gluShaderUtil.DataType} */ this.m_rgbAttrType = rgbAttrType;
+ /** @type {number} */ this.m_numInstances = numInstances;
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {Array<number>} */ this.m_gridVertexPositions = [];
+ /** @type {Array<number>} */ this.m_gridIndices = [];
+ /** @type {Array<number>} */ this.m_instanceOffsets = [];
+ /** @type {Array<number>} */ this.m_instanceColorR = [];
+ /** @type {Array<number>} */ this.m_instanceColorG = [];
+ /** @type {Array<number>} */ this.m_instanceColorB = [];
+ };
+
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.constructor = es3fInstancedRenderingTests.InstancedRenderingCase;
+
+ /**
+ * Helper function that does biasing and scaling when converting float to integer.
+ * @param {Array<number>} vec
+ * @param {number} val
+ */
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.pushVarCompAttrib = function(vec, val) {
+ var isFloatCase = gluShaderUtil.isDataTypeFloatOrVec(this.m_rgbAttrType);
+ var isIntCase = gluShaderUtil.isDataTypeIntOrIVec(this.m_rgbAttrType);
+ var isUintCase = gluShaderUtil.isDataTypeUintOrUVec(this.m_rgbAttrType);
+ var isMatCase = gluShaderUtil.isDataTypeMatrix(this.m_rgbAttrType);
+ if (isFloatCase || isMatCase)
+ vec.push(val);
+ else if (isIntCase)
+ vec.push(val * es3fInstancedRenderingTests.FLOAT_INT_SCALE + es3fInstancedRenderingTests.FLOAT_INT_BIAS);
+ else if (isUintCase)
+ vec.push(val * es3fInstancedRenderingTests.FLOAT_UINT_SCALE + es3fInstancedRenderingTests.FLOAT_UINT_BIAS);
+ else
+ throw new Error('Invalid attribute type.');
+ };
+
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.init = function() {
+ // Clear errors from previous tests
+ gl.getError();
+
+ /** @type {boolean} */ var isFloatCase = gluShaderUtil.isDataTypeFloatOrVec(this.m_rgbAttrType);
+ /** @type {boolean} */ var isIntCase = gluShaderUtil.isDataTypeIntOrIVec(this.m_rgbAttrType);
+ /** @type {boolean} */ var isUintCase = gluShaderUtil.isDataTypeUintOrUVec(this.m_rgbAttrType);
+ /** @type {boolean} */ var isMatCase = gluShaderUtil.isDataTypeMatrix(this.m_rgbAttrType);
+ /** @type {number} */ var typeSize = gluShaderUtil.getDataTypeScalarSize(this.m_rgbAttrType);
+ /** @type {boolean} */ var isScalarCase = typeSize == 1;
+ /** @type {string} */ var swizzleFirst = isScalarCase ? '' : '.x';
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(this.m_rgbAttrType);
+
+ /** @type {string} */ var floatIntScaleStr = '(' + es3fInstancedRenderingTests.FLOAT_INT_SCALE.toFixed(3) + ')';
+ /** @type {string} */ var floatIntBiasStr = '(' + es3fInstancedRenderingTests.FLOAT_INT_BIAS.toFixed(3) + ')';
+ /** @type {string} */ var floatUintScaleStr = '(' + es3fInstancedRenderingTests.FLOAT_UINT_SCALE.toFixed(3) + ')';
+ /** @type {string} */ var floatUintBiasStr = '(' + es3fInstancedRenderingTests.FLOAT_UINT_BIAS.toFixed(3) + ')';
+
+ DE_ASSERT(isFloatCase || isIntCase || isUintCase || isMatCase);
+
+ // Generate shader.
+ // \note For case TYPE_MIXED, vertex position offset and color red component get their values from instance id, while green and blue get their values from instanced attributes.
+
+ /** @type {string} */ var numInstancesStr = this.m_numInstances.toString() + '.0';
+
+ /** @type {string} */ var instanceAttribs = '';
+ /** @type {string} */ var posExpression = '';
+ /** @type {string} */ var colorRExpression = '';
+ /** @type {string} */ var colorGExpression = '';
+ /** @type {string} */ var colorBExpression = '';
+
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_INSTANCE_ID || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED) {
+ posExpression = 'a_position + vec4(float(gl_InstanceID) * 2.0 / ' + numInstancesStr + ', 0.0, 0.0, 0.0)';
+ colorRExpression = 'float(gl_InstanceID)/' + numInstancesStr;
+
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_INSTANCE_ID) {
+ colorGExpression = 'float(gl_InstanceID)*2.0/' + numInstancesStr;
+ colorBExpression = '1.0 - float(gl_InstanceID)/' + numInstancesStr;
+ }
+ }
+
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED) {
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR) {
+ posExpression = 'a_position + vec4(a_instanceOffset';
+
+ DE_ASSERT(es3fInstancedRenderingTests.OFFSET_COMPONENTS >= 1 && es3fInstancedRenderingTests.OFFSET_COMPONENTS <= 4);
+
+ for (var i = 0; i < 4 - es3fInstancedRenderingTests.OFFSET_COMPONENTS; i++)
+ posExpression += ', 0.0';
+ posExpression += ')';
+
+ if (isFloatCase)
+ colorRExpression = 'a_instanceR' + swizzleFirst;
+ else if (isIntCase)
+ colorRExpression = '(float(a_instanceR' + swizzleFirst + ') - ' + floatIntBiasStr + ') / ' + floatIntScaleStr;
+ else if (isUintCase)
+ colorRExpression = '(float(a_instanceR' + swizzleFirst + ') - ' + floatUintBiasStr + ') / ' + floatUintScaleStr;
+ else if (isMatCase)
+ colorRExpression = 'a_instanceR[0][0]';
+ else
+ DE_ASSERT(false);
+
+ instanceAttribs += 'in highp ' + (es3fInstancedRenderingTests.OFFSET_COMPONENTS == 1 ? 'float' : 'vec' + es3fInstancedRenderingTests.OFFSET_COMPONENTS.toString()) + ' a_instanceOffset;\n';
+ instanceAttribs += 'in mediump ' + typeName + ' a_instanceR;\n';
+ }
+
+ if (isFloatCase) {
+ colorGExpression = 'a_instanceG' + swizzleFirst;
+ colorBExpression = 'a_instanceB' + swizzleFirst;
+ } else if (isIntCase) {
+ colorGExpression = '(float(a_instanceG' + swizzleFirst + ') - ' + floatIntBiasStr + ') / ' + floatIntScaleStr;
+ colorBExpression = '(float(a_instanceB' + swizzleFirst + ') - ' + floatIntBiasStr + ') / ' + floatIntScaleStr;
+ } else if (isUintCase) {
+ colorGExpression = '(float(a_instanceG' + swizzleFirst + ') - ' + floatUintBiasStr + ') / ' + floatUintScaleStr;
+ colorBExpression = '(float(a_instanceB' + swizzleFirst + ') - ' + floatUintBiasStr + ') / ' + floatUintScaleStr;
+ } else if (isMatCase) {
+ colorGExpression = 'a_instanceG[0][0]';
+ colorBExpression = 'a_instanceB[0][0]';
+ } else
+ DE_ASSERT(false);
+
+ instanceAttribs += 'in mediump ' + typeName + ' a_instanceG;\n';
+ instanceAttribs += 'in mediump ' + typeName + ' a_instanceB;\n';
+ }
+
+ DE_ASSERT(!(posExpression.length == 0));
+ DE_ASSERT(!(colorRExpression.length == 0));
+ DE_ASSERT(!(colorGExpression.length == 0));
+ DE_ASSERT(!(colorBExpression.length == 0));
+
+ /** @type {string} */ var vertShaderSourceStr =
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ instanceAttribs +
+ 'out mediump vec4 v_color;\n' +
+ '\n' +
+ 'void main()\n' +
+ ' {\n' +
+ ' gl_Position = ' + posExpression + ';\n' +
+ ' v_color.r = ' + colorRExpression + ';\n' +
+ ' v_color.g = ' + colorGExpression + ';\n' +
+ ' v_color.b = ' + colorBExpression + ';\n' +
+ ' v_color.a = 1.0;\n' +
+ '}\n';
+
+ /** @type {string} */ var fragShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'in mediump vec4 v_color;\n' +
+ '\n' +
+ 'void main()\n' +
+ ' {\n' +
+ ' o_color = v_color;\n' +
+ '}\n';
+
+ // Create shader program and log it.
+
+ DE_ASSERT(!this.m_program);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSourceStr, fragShaderSource));
+
+ //tcu::TestLog& log = this.m_testCtx.getLog();
+ //log << *m_program;
+ // TODO: bufferedLogToConsole?
+ //bufferedLogToConsole(this.m_program);
+
+ assertMsgOptions(this.m_program.isOk(), 'Failed to compile shader', false, true);
+
+ // Vertex shader attributes.
+
+ if (this.m_function == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED) {
+ // Vertex positions. Positions form a vertical bar of width <screen width>/<number of instances>.
+
+ for (var y = 0; y < es3fInstancedRenderingTests.QUAD_GRID_SIZE + 1; y++)
+ for (var x = 0; x < es3fInstancedRenderingTests.QUAD_GRID_SIZE + 1; x++) {
+ /** @type {number} */ var fx = -1.0 + x / es3fInstancedRenderingTests.QUAD_GRID_SIZE * 2.0 / this.m_numInstances;
+ /** @type {number} */ var fy = -1.0 + y / es3fInstancedRenderingTests.QUAD_GRID_SIZE * 2.0;
+
+ this.m_gridVertexPositions.push(fx);
+ this.m_gridVertexPositions.push(fy);
+ }
+
+ // Indices.
+
+ for (var y = 0; y < es3fInstancedRenderingTests.QUAD_GRID_SIZE; y++)
+ for (var x = 0; x < es3fInstancedRenderingTests.QUAD_GRID_SIZE; x++) {
+ /** @type {number} */ var ndx00 = y * (es3fInstancedRenderingTests.QUAD_GRID_SIZE + 1) + x;
+ /** @type {number} */ var ndx10 = y * (es3fInstancedRenderingTests.QUAD_GRID_SIZE + 1) + x + 1;
+ /** @type {number} */ var ndx01 = (y + 1) * (es3fInstancedRenderingTests.QUAD_GRID_SIZE + 1) + x;
+ /** @type {number} */ var ndx11 = (y + 1) * (es3fInstancedRenderingTests.QUAD_GRID_SIZE + 1) + x + 1;
+
+ // Lower-left triangle of a quad.
+ this.m_gridIndices.push(ndx00);
+ this.m_gridIndices.push(ndx10);
+ this.m_gridIndices.push(ndx01);
+
+ // Upper-right triangle of a quad.
+ this.m_gridIndices.push(ndx11);
+ this.m_gridIndices.push(ndx01);
+ this.m_gridIndices.push(ndx10);
+ }
+ } else {
+ DE_ASSERT(this.m_function == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ARRAYS_INSTANCED);
+
+ // Vertex positions. Positions form a vertical bar of width <screen width>/<number of instances>.
+
+ for (var y = 0; y < es3fInstancedRenderingTests.QUAD_GRID_SIZE; y++)
+ for (var x = 0; x < es3fInstancedRenderingTests.QUAD_GRID_SIZE; x++) {
+ /** @type {number} */ var fx0 = -1.0 + (x + 0) / es3fInstancedRenderingTests.QUAD_GRID_SIZE * 2.0 / this.m_numInstances;
+ /** @type {number} */ var fx1 = -1.0 + (x + 1) / es3fInstancedRenderingTests.QUAD_GRID_SIZE * 2.0 / this.m_numInstances;
+ /** @type {number} */ var fy0 = -1.0 + (y + 0) / es3fInstancedRenderingTests.QUAD_GRID_SIZE * 2.0;
+ /** @type {number} */ var fy1 = -1.0 + (y + 1) / es3fInstancedRenderingTests.QUAD_GRID_SIZE * 2.0;
+
+ // Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1)
+ this.m_gridVertexPositions.push(fx0);
+ this.m_gridVertexPositions.push(fy0);
+ this.m_gridVertexPositions.push(fx1);
+ this.m_gridVertexPositions.push(fy0);
+ this.m_gridVertexPositions.push(fx0);
+ this.m_gridVertexPositions.push(fy1);
+
+ // Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0)
+ this.m_gridVertexPositions.push(fx1);
+ this.m_gridVertexPositions.push(fy1);
+ this.m_gridVertexPositions.push(fx0);
+ this.m_gridVertexPositions.push(fy1);
+ this.m_gridVertexPositions.push(fx1);
+ this.m_gridVertexPositions.push(fy0);
+ }
+ }
+
+ // Instanced attributes: position offset and color RGB components.
+
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED) {
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR) {
+ // Offsets are such that the vertical bars are drawn next to each other.
+ for (var i = 0; i < this.m_numInstances; i++) {
+ this.m_instanceOffsets.push(i * 2.0 / this.m_numInstances);
+
+ DE_ASSERT(es3fInstancedRenderingTests.OFFSET_COMPONENTS >= 1 && es3fInstancedRenderingTests.OFFSET_COMPONENTS <= 4);
+
+ for (var j = 0; j < es3fInstancedRenderingTests.OFFSET_COMPONENTS - 1; j++)
+ this.m_instanceOffsets.push(0.0);
+ }
+
+ /** @type {number} */ var rInstances = Math.floor(this.m_numInstances / es3fInstancedRenderingTests.ATTRIB_DIVISOR_R) + (this.m_numInstances % es3fInstancedRenderingTests.ATTRIB_DIVISOR_R == 0 ? 0 : 1);
+ for (var i = 0; i < rInstances; i++) {
+ this.pushVarCompAttrib(this.m_instanceColorR, i / rInstances);
+
+ for (var j = 0; j < typeSize - 1; j++)
+ this.pushVarCompAttrib(this.m_instanceColorR, 0.0);
+ }
+ }
+
+ /** @type {number} */ var gInstances = Math.floor(this.m_numInstances / es3fInstancedRenderingTests.ATTRIB_DIVISOR_G) + (this.m_numInstances % es3fInstancedRenderingTests.ATTRIB_DIVISOR_G == 0 ? 0 : 1);
+ for (var i = 0; i < gInstances; i++) {
+ this.pushVarCompAttrib(this.m_instanceColorG, i * 2.0 / gInstances);
+
+ for (var j = 0; j < typeSize - 1; j++)
+ this.pushVarCompAttrib(this.m_instanceColorG, 0.0);
+ }
+
+ /** @type {number} */ var bInstances = Math.floor(this.m_numInstances / es3fInstancedRenderingTests.ATTRIB_DIVISOR_B) + (this.m_numInstances % es3fInstancedRenderingTests.ATTRIB_DIVISOR_B == 0 ? 0 : 1);
+ for (var i = 0; i < bInstances; i++) {
+ this.pushVarCompAttrib(this.m_instanceColorB, 1.0 - i / bInstances);
+
+ for (var j = 0; j < typeSize - 1; j++)
+ this.pushVarCompAttrib(this.m_instanceColorB, 0.0);
+ }
+ }
+ };
+
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.deinit = function() {
+ var numVertexAttribArrays = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ for (var idx = 0; idx < numVertexAttribArrays; idx++) {
+ gl.disableVertexAttribArray(idx);
+ gl.vertexAttribDivisor(idx, 0);
+ }
+ };
+
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.iterate = function() {
+ /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, es3fInstancedRenderingTests.MAX_RENDER_WIDTH);
+ /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, es3fInstancedRenderingTests.MAX_RENDER_HEIGHT);
+
+ /** @type {number} */ var xOffsetMax = gl.drawingBufferWidth - width;
+ /** @type {number} */ var yOffsetMax = gl.drawingBufferHeight - height;
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+
+ /** @type {number} */ var xOffset = rnd.getInt(0, xOffsetMax);
+ /** @type {number} */ var yOffset = rnd.getInt(0, yOffsetMax);
+
+ /** @type {tcuSurface.Surface} */ var referenceImg = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var resultImg = new tcuSurface.Surface(width, height);
+
+ // Draw result.
+
+ gl.viewport(xOffset, yOffset, width, height);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ this.setupAndRender();
+
+ var resImg = resultImg.getAccess();
+ var resImgTransferFormat = gluTextureUtil.getTransferFormat(resImg.getFormat());
+
+ gl.readPixels(xOffset, yOffset, resImg.m_width, resImg.m_height, resImgTransferFormat.format, resImgTransferFormat.dataType, resultImg.m_pixels);
+
+ // Compute reference.
+ this.computeReference(referenceImg);
+
+ // Compare.
+
+ // Passing referenceImg.getAccess() and resultImg.getAccess() instead of referenceImg and resultImg
+ /** @type {boolean} */ var testOk = tcuImageCompare.fuzzyCompare('ComparisonResult', 'Image comparison result', referenceImg.getAccess(), resultImg.getAccess(), 0.05 /*, gluShaderUtil.COMPARE_LOG_RESULT*/);
+
+ assertMsgOptions(testOk, '', true, false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {Array<number>} attrPtr
+ * @param {number} location
+ * @param {number} divisor
+ */
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.setupVarAttribPointer = function(attrPtr, location, divisor) {
+ /** @type {boolean} */ var isFloatCase = gluShaderUtil.isDataTypeFloatOrVec(this.m_rgbAttrType);
+ /** @type {boolean} */ var isIntCase = gluShaderUtil.isDataTypeIntOrIVec(this.m_rgbAttrType);
+ /** @type {boolean} */ var isUintCase = gluShaderUtil.isDataTypeUintOrUVec(this.m_rgbAttrType);
+ /** @type {boolean} */ var isMatCase = gluShaderUtil.isDataTypeMatrix(this.m_rgbAttrType);
+ /** @type {number} */ var typeSize = gluShaderUtil.getDataTypeScalarSize(this.m_rgbAttrType);
+ /** @type {number} */ var numSlots = isMatCase ? gluShaderUtil.getDataTypeMatrixNumColumns(this.m_rgbAttrType) : 1; // Matrix uses as many attribute slots as it has columns.
+
+ for (var slotNdx = 0; slotNdx < numSlots; slotNdx++) {
+ /** @type {number} */ var curLoc = location + slotNdx;
+
+ gl.enableVertexAttribArray(curLoc);
+ gl.vertexAttribDivisor(curLoc, divisor);
+ var curLocGlBuffer = gl.createBuffer();
+ if (isFloatCase) {
+ var bufferCurLoc = new Float32Array(attrPtr);
+ gl.bindBuffer(gl.ARRAY_BUFFER, curLocGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferCurLoc, gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(curLoc, typeSize, gl.FLOAT, false, 0, 0);
+ } else if (isIntCase) {
+ var bufferCurLoc = new Int32Array(attrPtr);
+ gl.bindBuffer(gl.ARRAY_BUFFER, curLocGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferCurLoc, gl.STATIC_DRAW);
+
+ gl.vertexAttribIPointer(curLoc, typeSize, gl.INT, 0, 0);
+ } else if (isUintCase) {
+ var bufferCurLoc = new Uint32Array(attrPtr);
+ gl.bindBuffer(gl.ARRAY_BUFFER, curLocGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferCurLoc, gl.STATIC_DRAW);
+
+ gl.vertexAttribIPointer(curLoc, typeSize, gl.UNSIGNED_INT, 0, 0);
+ } else if (isMatCase) {
+ /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(this.m_rgbAttrType);
+ /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(this.m_rgbAttrType);
+
+ var bufferCurLoc = new Float32Array(attrPtr);
+ gl.bindBuffer(gl.ARRAY_BUFFER, curLocGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferCurLoc, gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(curLoc, numRows, gl.FLOAT, false, numCols * numRows * 4, 0);
+ } else
+ DE_ASSERT(false);
+ }
+ };
+
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.setupAndRender = function() {
+ /** @type {WebGLProgram} */ var program = this.m_program.getProgram();
+
+ gl.useProgram(program);
+ // Setup attributes.
+
+ // Position attribute is non-instanced.
+ /** @type {number} */ var positionLoc = gl.getAttribLocation(program, 'a_position');
+ gl.enableVertexAttribArray(positionLoc);
+ var positionBuffer = gl.createBuffer();
+ var bufferGridVertexPosition = new Float32Array(this.m_gridVertexPositions);
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferGridVertexPosition, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
+
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED) {
+ if (this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR) {
+ // Position offset attribute is instanced with separate offset for every instance.
+ /** @type {number} */ var offsetLoc = gl.getAttribLocation(program, 'a_instanceOffset');
+ gl.enableVertexAttribArray(offsetLoc);
+ gl.vertexAttribDivisor(offsetLoc, 1);
+
+ var offsetLocGlBuffer = gl.createBuffer();
+ var bufferOffsetLoc = new Float32Array(this.m_instanceOffsets);
+ gl.bindBuffer(gl.ARRAY_BUFFER, offsetLocGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferOffsetLoc, gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(offsetLoc, es3fInstancedRenderingTests.OFFSET_COMPONENTS, gl.FLOAT, false, 0, 0);
+
+ /** @type {number} */ var rLoc = gl.getAttribLocation(program, 'a_instanceR');
+ this.setupVarAttribPointer(this.m_instanceColorR, rLoc, es3fInstancedRenderingTests.ATTRIB_DIVISOR_R);
+ }
+
+ /** @type {number} */ var gLoc = gl.getAttribLocation(program, 'a_instanceG');
+ this.setupVarAttribPointer(this.m_instanceColorG, gLoc, es3fInstancedRenderingTests.ATTRIB_DIVISOR_G);
+
+ /** @type {number} */ var bLoc = gl.getAttribLocation(program, 'a_instanceB');
+ this.setupVarAttribPointer(this.m_instanceColorB, bLoc, es3fInstancedRenderingTests.ATTRIB_DIVISOR_B);
+ }
+
+ // Draw using appropriate function.
+
+ if (this.m_function == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ARRAYS_INSTANCED) {
+ /** @type {number} */ var numPositionComponents = 2;
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, Math.floor(this.m_gridVertexPositions.length / numPositionComponents), this.m_numInstances);
+ } else {
+ var gridIndicesGLBuffer = gl.createBuffer();
+ var bufferGridIndices = new Uint16Array(this.m_gridIndices);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gridIndicesGLBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferGridIndices, gl.STATIC_DRAW);
+
+ gl.drawElementsInstanced(gl.TRIANGLES, this.m_gridIndices.length, gl.UNSIGNED_SHORT, 0, this.m_numInstances);
+ }
+ gl.useProgram(null);
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ */
+ es3fInstancedRenderingTests.InstancedRenderingCase.prototype.computeReference = function(dst) {
+ /** @type {number} */ var wid = dst.getWidth();
+ /** @type {number} */ var hei = dst.getHeight();
+
+ // Draw a rectangle (vertical bar) for each instance.
+
+ for (var instanceNdx = 0; instanceNdx < this.m_numInstances; instanceNdx++) {
+ /** @type {number} */ var xStart = Math.floor(instanceNdx * wid / this.m_numInstances);
+ /** @type {number} */ var xEnd = Math.floor((instanceNdx + 1) * wid / this.m_numInstances);
+
+ // Emulate attribute divisors if that is the case.
+
+ /** @type {number} */ var clrNdxR = this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR ? Math.floor(instanceNdx / es3fInstancedRenderingTests.ATTRIB_DIVISOR_R) : instanceNdx;
+ /** @type {number} */ var clrNdxG = this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED ? Math.floor(instanceNdx / es3fInstancedRenderingTests.ATTRIB_DIVISOR_G) : instanceNdx;
+ /** @type {number} */ var clrNdxB = this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED ? Math.floor(instanceNdx / es3fInstancedRenderingTests.ATTRIB_DIVISOR_B) : instanceNdx;
+
+ /** @type {number} */ var rInstances = this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR ? Math.floor(this.m_numInstances / es3fInstancedRenderingTests.ATTRIB_DIVISOR_R) + (this.m_numInstances % es3fInstancedRenderingTests.ATTRIB_DIVISOR_R == 0 ? 0 : 1) : this.m_numInstances;
+ /** @type {number} */ var gInstances = this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED ? Math.floor(this.m_numInstances / es3fInstancedRenderingTests.ATTRIB_DIVISOR_G) + (this.m_numInstances % es3fInstancedRenderingTests.ATTRIB_DIVISOR_G == 0 ? 0 : 1) : this.m_numInstances;
+ /** @type {number} */ var bInstances = this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR || this.m_instancingType == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED ? Math.floor(this.m_numInstances / es3fInstancedRenderingTests.ATTRIB_DIVISOR_B) + (this.m_numInstances % es3fInstancedRenderingTests.ATTRIB_DIVISOR_B == 0 ? 0 : 1) : this.m_numInstances;
+
+ // Calculate colors.
+
+ /** @type {number} */ var r = clrNdxR / rInstances;
+ /** @type {number} */ var g = clrNdxG * 2.0 / gInstances;
+ /** @type {number} */ var b = 1.0 - clrNdxB / bInstances;
+
+ // Convert to integer and back if shader inputs are integers.
+
+ if (gluShaderUtil.isDataTypeIntOrIVec(this.m_rgbAttrType)) {
+ /** @type {number} */var intR = (r * es3fInstancedRenderingTests.FLOAT_INT_SCALE + es3fInstancedRenderingTests.FLOAT_INT_BIAS);
+ /** @type {number} */var intG = (g * es3fInstancedRenderingTests.FLOAT_INT_SCALE + es3fInstancedRenderingTests.FLOAT_INT_BIAS);
+ /** @type {number} */var intB = (b * es3fInstancedRenderingTests.FLOAT_INT_SCALE + es3fInstancedRenderingTests.FLOAT_INT_BIAS);
+ r = (intR - es3fInstancedRenderingTests.FLOAT_INT_BIAS) / es3fInstancedRenderingTests.FLOAT_INT_SCALE;
+ g = (intG - es3fInstancedRenderingTests.FLOAT_INT_BIAS) / es3fInstancedRenderingTests.FLOAT_INT_SCALE;
+ b = (intB - es3fInstancedRenderingTests.FLOAT_INT_BIAS) / es3fInstancedRenderingTests.FLOAT_INT_SCALE;
+ } else if (gluShaderUtil.isDataTypeUintOrUVec(this.m_rgbAttrType)) {
+ /** @type {number} */var uintR = (r * es3fInstancedRenderingTests.FLOAT_UINT_SCALE + es3fInstancedRenderingTests.FLOAT_UINT_BIAS);
+ /** @type {number} */var uintG = (g * es3fInstancedRenderingTests.FLOAT_UINT_SCALE + es3fInstancedRenderingTests.FLOAT_UINT_BIAS);
+ /** @type {number} */var uintB = (b * es3fInstancedRenderingTests.FLOAT_UINT_SCALE + es3fInstancedRenderingTests.FLOAT_UINT_BIAS);
+ r = (uintR - es3fInstancedRenderingTests.FLOAT_UINT_BIAS) / es3fInstancedRenderingTests.FLOAT_UINT_SCALE;
+ g = (uintG - es3fInstancedRenderingTests.FLOAT_UINT_BIAS) / es3fInstancedRenderingTests.FLOAT_UINT_SCALE;
+ b = (uintB - es3fInstancedRenderingTests.FLOAT_UINT_BIAS) / es3fInstancedRenderingTests.FLOAT_UINT_SCALE;
+ }
+
+ // Convert from float to unorm8.
+ var color = deMath.add(deMath.scale([r, g, b, 1.0], 255), [0.5, 0.5, 0.5, 0.5]);
+ color = deMath.clampVector(color, 0, 255);
+
+ // Draw rectangle.
+ for (var y = 0; y < hei; y++)
+ for (var x = xStart; x < xEnd; x++)
+ dst.setPixel(x, y, color);
+ }
+ };
+
+ es3fInstancedRenderingTests.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ /** @type {Array<number>} */ var instanceCounts = [1, 2, 4, 20];
+
+ for (var _function in es3fInstancedRenderingTests.DrawFunction) {
+ /** @type {?string} */ var functionName =
+ es3fInstancedRenderingTests.DrawFunction[_function] == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ARRAYS_INSTANCED ? 'draw_arrays_instanced' :
+ es3fInstancedRenderingTests.DrawFunction[_function] == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED ? 'draw_elements_instanced' :
+ null;
+
+ /** @type {?string} */ var functionDesc =
+ es3fInstancedRenderingTests.DrawFunction[_function] == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ARRAYS_INSTANCED ? 'Use glDrawArraysInstanced()' :
+ es3fInstancedRenderingTests.DrawFunction[_function] == es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED ? 'Use glDrawElementsInstanced()' :
+ null;
+
+ DE_ASSERT(functionName != null);
+ DE_ASSERT(functionDesc != null);
+
+ /** @type {tcuTestCase.DeqpTest} */ var functionGroup = tcuTestCase.newTest(functionName, functionDesc);
+ testGroup.addChild(functionGroup);
+
+ for (var instancingType in es3fInstancedRenderingTests.InstancingType) {
+ /** @type {?string} */ var instancingTypeName =
+ es3fInstancedRenderingTests.InstancingType[instancingType] == es3fInstancedRenderingTests.InstancingType.TYPE_INSTANCE_ID ? 'instance_id' :
+ es3fInstancedRenderingTests.InstancingType[instancingType] == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR ? 'attribute_divisor' :
+ es3fInstancedRenderingTests.InstancingType[instancingType] == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED ? 'mixed' :
+ null;
+
+ /** @type {?string} */ var instancingTypeDesc =
+ es3fInstancedRenderingTests.InstancingType[instancingType] == es3fInstancedRenderingTests.InstancingType.TYPE_INSTANCE_ID ? 'Use gl_InstanceID for instancing' :
+ es3fInstancedRenderingTests.InstancingType[instancingType] == es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR ? 'Use vertex attribute divisors for instancing' :
+ es3fInstancedRenderingTests.InstancingType[instancingType] == es3fInstancedRenderingTests.InstancingType.TYPE_MIXED ? 'Use both gl_InstanceID and vertex attribute divisors for instancing' :
+ null;
+
+ DE_ASSERT(instancingTypeName != null);
+ DE_ASSERT(instancingTypeDesc != null);
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var instancingTypeGroup = tcuTestCase.newTest(instancingTypeName, instancingTypeDesc);
+
+ functionGroup.addChild(instancingTypeGroup);
+
+ for (var countNdx in instanceCounts) {
+ /** @type {string} */ var countName = instanceCounts[countNdx].toString() + '_instances';
+ instancingTypeGroup.addChild(new es3fInstancedRenderingTests.InstancedRenderingCase(countName,
+ '',
+ es3fInstancedRenderingTests.DrawFunction[_function],
+ es3fInstancedRenderingTests.InstancingType[instancingType],
+ gluShaderUtil.DataType.FLOAT,
+ instanceCounts[countNdx]));
+ }
+ }
+ }
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var s_testTypes =
+ [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3,
+ gluShaderUtil.DataType.FLOAT_MAT4,
+
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4
+ ];
+
+ /** @type {number} */ var typeTestNumInstances = 4;
+
+ /** @type {tcuTestCase.DeqpTest} */ var typesGroup = tcuTestCase.newTest('types', 'Tests for instanced attributes of particular data types');
+
+ testGroup.addChild(typesGroup);
+
+ for (var typeNdx in s_testTypes) {
+ /** @type {gluShaderUtil.DataType} */ var type = s_testTypes[typeNdx];
+ typesGroup.addChild(new es3fInstancedRenderingTests.InstancedRenderingCase(gluShaderUtil.getDataTypeName(type), '',
+ es3fInstancedRenderingTests.DrawFunction.FUNCTION_DRAW_ARRAYS_INSTANCED,
+ es3fInstancedRenderingTests.InstancingType.TYPE_ATTRIB_DIVISOR,
+ type,
+ typeTestNumInstances));
+ }
+ };
+
+ es3fInstancedRenderingTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'instanced_rendering';
+ var testDescription = 'Instanced Rendering Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.setRoot(tcuTestCase.newTest(testName, testDescription, null));
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fInstancedRenderingTests.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fInstancedRenderingTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIntegerStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIntegerStateQueryTests.js
new file mode 100644
index 0000000000..ec5048e4f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fIntegerStateQueryTests.js
@@ -0,0 +1,2049 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fIntegerStateQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+ var es3fIntegerStateQueryTests = functional.gles3.es3fIntegerStateQueryTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deRandom = framework.delibs.debase.deRandom;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var glsStateQuery = modules.shared.glsStateQuery;
+
+ /** @type {string} */ var transformFeedbackTestVertSource = '' +
+ '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+
+ /** @type {string} */ var transformFeedbackTestFragSource = '' +
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ /** @type {string} */ var testVertSource = '' +
+ '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+
+ /** @type {string} */ var testFragSource = '' +
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.TransformFeedbackTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {WebGLTransformFeedback} */ this.m_transformfeedback;
+ };
+
+ es3fIntegerStateQueryTests.TransformFeedbackTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.TransformFeedbackTestCase.prototype.constructor = es3fIntegerStateQueryTests.TransformFeedbackTestCase;
+
+ es3fIntegerStateQueryTests.TransformFeedbackTestCase.prototype.testTransformFeedback = function() {
+ throw new Error('This method should be implemented by child classes.');
+ };
+
+ es3fIntegerStateQueryTests.TransformFeedbackTestCase.prototype.test = function() {
+ this.beforeTransformFeedbackTest(); // [dag] added this as there is no other way this method would be called.
+
+ this.m_transformfeedback = gl.createTransformFeedback();
+
+ /** @type {WebGLShader} */ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(shaderVert, transformFeedbackTestVertSource);
+ gl.compileShader(shaderVert);
+
+ var compileStatus = /** @type {boolean} */ (gl.getShaderParameter(shaderVert, gl.COMPILE_STATUS));
+ glsStateQuery.compare(compileStatus, true);
+
+ /** @type {WebGLShader} */ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(shaderFrag, transformFeedbackTestFragSource);
+ gl.compileShader(shaderFrag);
+
+ compileStatus = /** @type {boolean} */ (gl.getShaderParameter(shaderFrag, gl.COMPILE_STATUS));
+ glsStateQuery.compare(compileStatus, true);
+
+ /** @type {WebGLProgram} */ var shaderProg = gl.createProgram();
+ gl.attachShader(shaderProg, shaderVert);
+ gl.attachShader(shaderProg, shaderFrag);
+ /** @type {Array<string>} */ var transform_feedback_outputs = ['gl_Position'];
+ gl.transformFeedbackVaryings(shaderProg, transform_feedback_outputs, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(shaderProg);
+
+ var linkStatus = /** @type {boolean} */ (gl.getProgramParameter(shaderProg, gl.LINK_STATUS));
+ glsStateQuery.compare(linkStatus, true);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, this.m_transformfeedback);
+
+
+ /** @type {WebGLBuffer} */ var feedbackBufferId = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, feedbackBufferId);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array(16), gl.DYNAMIC_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, feedbackBufferId);
+
+ gl.useProgram(shaderProg);
+
+ this.testTransformFeedback();
+
+ gl.useProgram(null);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.deleteTransformFeedback(this.m_transformfeedback);
+ gl.deleteBuffer(feedbackBufferId);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(shaderProg);
+
+ this.afterTransformFeedbackTest(); // [dag] added this as there is no other way this method would be called.
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIntegerStateQueryTests.TransformFeedbackTestCase}
+ * @param {string} name
+ */
+ es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase = function(name) {
+ es3fIntegerStateQueryTests.TransformFeedbackTestCase.call(this, name, 'GL_TRANSFORM_FEEDBACK_BINDING');
+ };
+
+ es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase.prototype = Object.create(es3fIntegerStateQueryTests.TransformFeedbackTestCase.prototype);
+ es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase;
+
+
+ es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase.prototype.beforeTransformFeedbackTest = function() {
+ this.check(glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_BINDING, null), 'beforeTransformFeedbackTest');
+ };
+
+ es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase.prototype.testTransformFeedback = function() {
+ this.check(glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_BINDING, this.m_transformfeedback), 'testTransformFeedback');
+ };
+
+ es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase.prototype.afterTransformFeedbackTest = function() {
+ this.check(glsStateQuery.verify(gl.TRANSFORM_FEEDBACK_BINDING, null), 'afterTransformFeedbackTest');
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {number} minValue
+ */
+ es3fIntegerStateQueryTests.ConstantMinimumValueTestCase = function(name, description, targetName, minValue) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_targetName = targetName;
+ /** @type {number} */ this.m_minValue = minValue;
+ };
+
+ es3fIntegerStateQueryTests.ConstantMinimumValueTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ConstantMinimumValueTestCase.prototype.constructor = es3fIntegerStateQueryTests.ConstantMinimumValueTestCase;
+
+ es3fIntegerStateQueryTests.ConstantMinimumValueTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verifyGreaterOrEqual(this.m_targetName, this.m_minValue), 'Fail');
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {number} minValue
+ */
+ es3fIntegerStateQueryTests.ConstantMaximumValueTestCase = function(name, description, targetName, minValue) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_targetName = targetName;
+ /** @type {number} */ this.m_minValue = minValue;
+ };
+
+ es3fIntegerStateQueryTests.ConstantMaximumValueTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ConstantMaximumValueTestCase.prototype.constructor = es3fIntegerStateQueryTests.ConstantMaximumValueTestCase;
+
+ es3fIntegerStateQueryTests.ConstantMaximumValueTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verifyLessOrEqual(this.m_targetName, this.m_minValue), 'Fail');
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.SampleBuffersTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.SampleBuffersTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.SampleBuffersTestCase.prototype.constructor = es3fIntegerStateQueryTests.SampleBuffersTestCase;
+
+ es3fIntegerStateQueryTests.SampleBuffersTestCase.prototype.test = function() {
+ /** @type {number} */ var expectedSampleBuffers = (/** @type {number} */ (gl.getParameter(gl.SAMPLES)) > 1) ? 1 : 0;
+
+ bufferedLogToConsole('Sample count is ' + expectedSampleBuffers + ', expecting GL_SAMPLE_BUFFERS to be ' + expectedSampleBuffers);
+
+ this.check(glsStateQuery.verify(gl.SAMPLE_BUFFERS, expectedSampleBuffers));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.SamplesTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.SamplesTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.SamplesTestCase.prototype.constructor = es3fIntegerStateQueryTests.SamplesTestCase;
+
+ es3fIntegerStateQueryTests.SamplesTestCase.prototype.test = function() {
+ var numSamples = /** @type {number} */ (gl.getParameter(gl.SAMPLES));
+ // MSAA?
+ if (numSamples > 1) {
+ bufferedLogToConsole('Sample count is ' + numSamples);
+
+ this.check(glsStateQuery.verify(gl.SAMPLES, numSamples));
+ } else {
+ /** @type {Array<number>} */ var validSamples = [0, 1];
+
+ bufferedLogToConsole('Expecting GL_SAMPLES to be 0 or 1');
+
+ this.check(glsStateQuery.verifyAnyOf(gl.SAMPLES, validSamples));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ */
+ es3fIntegerStateQueryTests.HintTestCase = function(name, description, targetName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_targetName = targetName;
+ };
+
+ es3fIntegerStateQueryTests.HintTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.HintTestCase.prototype.constructor = es3fIntegerStateQueryTests.HintTestCase;
+
+ es3fIntegerStateQueryTests.HintTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_targetName, gl.DONT_CARE));
+
+ gl.hint(this.m_targetName, gl.NICEST);
+ this.check(glsStateQuery.verify(this.m_targetName, gl.NICEST));
+
+ gl.hint(this.m_targetName, gl.FASTEST);
+ this.check(glsStateQuery.verify(this.m_targetName, gl.FASTEST));
+
+ gl.hint(this.m_targetName, gl.DONT_CARE);
+ this.check(glsStateQuery.verify(this.m_targetName, gl.DONT_CARE));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.DepthFuncTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.DepthFuncTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.DepthFuncTestCase.prototype.constructor = es3fIntegerStateQueryTests.DepthFuncTestCase;
+
+ es3fIntegerStateQueryTests.DepthFuncTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.DEPTH_FUNC, gl.LESS));
+
+ /** @type {Array<number>} */ var depthFunctions = [gl.NEVER, gl.ALWAYS, gl.LESS, gl.LEQUAL, gl.EQUAL, gl.GREATER, gl.GEQUAL, gl.NOTEQUAL];
+ for (var ndx = 0; ndx < depthFunctions.length; ndx++) {
+ gl.depthFunc(depthFunctions[ndx]);
+
+ this.check(glsStateQuery.verify(gl.DEPTH_FUNC, depthFunctions[ndx]));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.CullFaceTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.CullFaceTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.CullFaceTestCase.prototype.constructor = es3fIntegerStateQueryTests.CullFaceTestCase;
+
+ es3fIntegerStateQueryTests.CullFaceTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.CULL_FACE_MODE, gl.BACK));
+
+ /** @type {Array<number>} */ var cullFaces = [gl.FRONT, gl.BACK, gl.FRONT_AND_BACK];
+ for (var ndx = 0; ndx < cullFaces.length; ndx++) {
+ gl.cullFace(cullFaces[ndx]);
+
+ this.check(glsStateQuery.verify(gl.CULL_FACE_MODE, cullFaces[ndx]));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.FrontFaceTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.FrontFaceTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.FrontFaceTestCase.prototype.constructor = es3fIntegerStateQueryTests.FrontFaceTestCase;
+
+ es3fIntegerStateQueryTests.FrontFaceTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.FRONT_FACE, gl.CCW));
+
+ /** @type {Array<number>} */ var frontFaces = [gl.CW, gl.CCW];
+ for (var ndx = 0; ndx < frontFaces.length; ndx++) {
+ gl.frontFace(frontFaces[ndx]);
+
+ this.check(glsStateQuery.verify(gl.FRONT_FACE, frontFaces[ndx]));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.ViewPortTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.ViewPortTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ViewPortTestCase.prototype.constructor = es3fIntegerStateQueryTests.ViewPortTestCase;
+
+ es3fIntegerStateQueryTests.ViewPortTestCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ var maxViewportDimensions = /** @type {Array<number>} */ (gl.getParameter(gl.MAX_VIEWPORT_DIMS));
+
+ // verify initial value of first two values
+ this.check(glsStateQuery.verify(gl.VIEWPORT, new Int32Array([0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight])));
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var x = rnd.getInt(-64000, 64000);
+ /** @type {number} */ var y = rnd.getInt(-64000, 64000);
+ /** @type {number} */ var width = rnd.getInt(0, maxViewportDimensions[0]);
+ /** @type {number} */ var height = rnd.getInt(0, maxViewportDimensions[1]);
+
+ gl.viewport(x, y, width, height);
+ this.check(glsStateQuery.verify(gl.VIEWPORT, new Int32Array([x, y, width, height])));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.ScissorBoxTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.ScissorBoxTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ScissorBoxTestCase.prototype.constructor = es3fIntegerStateQueryTests.ScissorBoxTestCase;
+
+ es3fIntegerStateQueryTests.ScissorBoxTestCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ // verify initial value of first two values
+ this.check(glsStateQuery.verifyMask(gl.SCISSOR_BOX, [0, 0, 0, 0], [true, true, false, false]));
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var left = rnd.getInt(-64000, 64000);
+ /** @type {number} */ var bottom = rnd.getInt(-64000, 64000);
+ /** @type {number} */ var width = rnd.getInt(0, 64000);
+ /** @type {number} */ var height = rnd.getInt(0, 64000);
+
+ gl.scissor(left, bottom, width, height);
+ this.check(glsStateQuery.verify(gl.SCISSOR_BOX, new Int32Array([left, bottom, width, height])));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.MaxViewportDimsTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.MaxViewportDimsTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.MaxViewportDimsTestCase.prototype.constructor = es3fIntegerStateQueryTests.MaxViewportDimsTestCase;
+
+ es3fIntegerStateQueryTests.MaxViewportDimsTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verifyGreaterOrEqual(gl.MAX_VIEWPORT_DIMS, [gl.drawingBufferWidth, gl.drawingBufferHeight]));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ */
+ es3fIntegerStateQueryTests.StencilRefTestCase = function(name, description, testTargetName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ };
+
+ es3fIntegerStateQueryTests.StencilRefTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilRefTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilRefTestCase;
+
+ es3fIntegerStateQueryTests.StencilRefTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_testTargetName, 0));
+
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var ref = 1 << stencilBit;
+
+ gl.stencilFunc(gl.ALWAYS, ref, 0); // mask should not affect the REF
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, ref));
+
+ gl.stencilFunc(gl.ALWAYS, ref, ref);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, ref));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} stencilFuncTargetFace
+ */
+ es3fIntegerStateQueryTests.StencilRefSeparateTestCase = function(name, description, testTargetName, stencilFuncTargetFace) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_stencilFuncTargetFace = stencilFuncTargetFace;
+ };
+
+ es3fIntegerStateQueryTests.StencilRefSeparateTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilRefSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilRefSeparateTestCase;
+
+ es3fIntegerStateQueryTests.StencilRefSeparateTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_testTargetName, 0));
+
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var ref = 1 << stencilBit;
+
+ gl.stencilFuncSeparate(this.m_stencilFuncTargetFace, gl.ALWAYS, ref, 0);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, ref));
+
+ gl.stencilFuncSeparate(this.m_stencilFuncTargetFace, gl.ALWAYS, ref, ref);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, ref));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} stencilOpName
+ */
+ es3fIntegerStateQueryTests.StencilOpTestCase = function(name, description, stencilOpName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_stencilOpName = stencilOpName;
+ };
+
+ es3fIntegerStateQueryTests.StencilOpTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilOpTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilOpTestCase;
+
+ es3fIntegerStateQueryTests.StencilOpTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_stencilOpName, gl.KEEP));
+
+ /** @type {Array<number>} */ var stencilOpValues = [gl.KEEP, gl.ZERO, gl.REPLACE, gl.INCR, gl.DECR, gl.INVERT, gl.INCR_WRAP, gl.DECR_WRAP];
+ for (var ndx = 0; ndx < stencilOpValues.length; ++ndx) {
+ this.setStencilOp(stencilOpValues[ndx]);
+
+ this.check(glsStateQuery.verify(this.m_stencilOpName, stencilOpValues[ndx]));
+ }
+ };
+
+ es3fIntegerStateQueryTests.StencilOpTestCase.prototype.deinit = function() {
+ // [dag] need to reset everything once the test is done, otherwise related tests fail
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ };
+
+ /**
+ * @param {number} stencilOpValue
+ */
+ es3fIntegerStateQueryTests.StencilOpTestCase.prototype.setStencilOp = function(stencilOpValue) {
+ switch (this.m_stencilOpName) {
+ case gl.STENCIL_FAIL:
+ case gl.STENCIL_BACK_FAIL:
+ gl.stencilOp(stencilOpValue, gl.KEEP, gl.KEEP);
+ break;
+
+ case gl.STENCIL_PASS_DEPTH_FAIL:
+ case gl.STENCIL_BACK_PASS_DEPTH_FAIL:
+ gl.stencilOp(gl.KEEP, stencilOpValue, gl.KEEP);
+ break;
+
+ case gl.STENCIL_PASS_DEPTH_PASS:
+ case gl.STENCIL_BACK_PASS_DEPTH_PASS:
+ gl.stencilOp(gl.KEEP, gl.KEEP, stencilOpValue);
+ break;
+
+ default:
+ throw new Error('should not happen');
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIntegerStateQueryTests.StencilOpTestCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} stencilOpName
+ * @param {number} stencilOpFace
+ */
+ es3fIntegerStateQueryTests.StencilOpSeparateTestCase = function(name, description, stencilOpName, stencilOpFace) {
+ es3fIntegerStateQueryTests.StencilOpTestCase.call(this, name, description, stencilOpName);
+ /** @type {number} */ this.m_stencilOpName = stencilOpName;
+ /** @type {number} */ this.m_stencilOpFace = stencilOpFace;
+ };
+
+ es3fIntegerStateQueryTests.StencilOpSeparateTestCase.prototype = Object.create(es3fIntegerStateQueryTests.StencilOpTestCase.prototype);
+ es3fIntegerStateQueryTests.StencilOpSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilOpSeparateTestCase;
+
+ es3fIntegerStateQueryTests.StencilOpSeparateTestCase.prototype.test = function() {};
+
+ /**
+ * @param {number} stencilOpValue
+ */
+ es3fIntegerStateQueryTests.StencilOpSeparateTestCase.prototype.setStencilOp = function(stencilOpValue) {
+ switch (this.m_stencilOpName) {
+ case gl.STENCIL_FAIL:
+ case gl.STENCIL_BACK_FAIL:
+ gl.stencilOpSeparate(this.m_stencilOpFace, stencilOpValue, gl.KEEP, gl.KEEP);
+ break;
+
+ case gl.STENCIL_PASS_DEPTH_FAIL:
+ case gl.STENCIL_BACK_PASS_DEPTH_FAIL:
+ gl.stencilOpSeparate(this.m_stencilOpFace, gl.KEEP, stencilOpValue, gl.KEEP);
+ break;
+
+ case gl.STENCIL_PASS_DEPTH_PASS:
+ case gl.STENCIL_BACK_PASS_DEPTH_PASS:
+ gl.stencilOpSeparate(this.m_stencilOpFace, gl.KEEP, gl.KEEP, stencilOpValue);
+ break;
+
+ default:
+ throw new Error('should not happen');
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.StencilFuncTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.StencilFuncTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilFuncTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilFuncTestCase;
+
+ es3fIntegerStateQueryTests.StencilFuncTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.STENCIL_FUNC, gl.ALWAYS));
+
+ /** @type {Array<number>} */ var stencilfuncValues = [gl.NEVER, gl.ALWAYS, gl.LESS, gl.LEQUAL, gl.EQUAL, gl.GEQUAL, gl.GREATER, gl.NOTEQUAL];
+
+ for (var ndx = 0; ndx < stencilfuncValues.length; ++ndx) {
+ gl.stencilFunc(stencilfuncValues[ndx], 0, 0);
+
+ this.check(glsStateQuery.verify(gl.STENCIL_FUNC, stencilfuncValues[ndx]));
+
+ this.check(glsStateQuery.verify(gl.STENCIL_BACK_FUNC, stencilfuncValues[ndx]));
+ }
+ };
+
+ es3fIntegerStateQueryTests.StencilFuncTestCase.prototype.deinit = function() {
+ // [dag] reset stencilFunc to ALWAYS
+ gl.stencilFunc(gl.ALWAYS, 0, 0);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} stencilFuncName
+ * @param {number} stencilFuncFace
+ */
+ es3fIntegerStateQueryTests.StencilFuncSeparateTestCase = function(name, description, stencilFuncName, stencilFuncFace) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_stencilFuncName = stencilFuncName;
+ /** @type {number} */ this.m_stencilFuncFace = stencilFuncFace;
+ };
+
+ es3fIntegerStateQueryTests.StencilFuncSeparateTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilFuncSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilFuncSeparateTestCase;
+
+ es3fIntegerStateQueryTests.StencilFuncSeparateTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_stencilFuncName, gl.ALWAYS));
+
+ /** @type {Array<number>} */ var stencilfuncValues = [gl.NEVER, gl.ALWAYS, gl.LESS, gl.LEQUAL, gl.EQUAL, gl.GEQUAL, gl.GREATER, gl.NOTEQUAL];
+
+ for (var ndx = 0; ndx < stencilfuncValues.length; ++ndx) {
+ gl.stencilFuncSeparate(this.m_stencilFuncFace, stencilfuncValues[ndx], 0, 0);
+
+ this.check(glsStateQuery.verify(this.m_stencilFuncName, stencilfuncValues[ndx]));
+ }
+ };
+
+ es3fIntegerStateQueryTests.StencilFuncSeparateTestCase.prototype.deinit = function() {
+ // [dag] reset the stencil func
+ gl.stencilFuncSeparate(this.m_stencilFuncFace, gl.ALWAYS, 0, 0);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ */
+ es3fIntegerStateQueryTests.StencilMaskTestCase = function(name, description, testTargetName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ };
+
+ es3fIntegerStateQueryTests.StencilMaskTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilMaskTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilMaskTestCase;
+
+ es3fIntegerStateQueryTests.StencilMaskTestCase.prototype.test = function() {
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, stencilBits));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var mask = 1 << stencilBit;
+
+ gl.stencilFunc(gl.ALWAYS, 0, mask);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, mask));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} stencilFuncTargetFace
+ */
+ es3fIntegerStateQueryTests.StencilMaskSeparateTestCase = function(name, description, testTargetName, stencilFuncTargetFace) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_stencilFuncTargetFace = stencilFuncTargetFace;
+ };
+
+ es3fIntegerStateQueryTests.StencilMaskSeparateTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilMaskSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilMaskSeparateTestCase;
+
+ es3fIntegerStateQueryTests.StencilMaskSeparateTestCase.prototype.test = function() {
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, stencilBits));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var mask = 1 << stencilBit;
+
+ gl.stencilFuncSeparate(this.m_stencilFuncTargetFace, gl.ALWAYS, 0, mask);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, mask));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ */
+ es3fIntegerStateQueryTests.StencilWriteMaskTestCase = function(name, description, testTargetName) {
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.StencilWriteMaskTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilWriteMaskTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilWriteMaskTestCase;
+
+ es3fIntegerStateQueryTests.StencilWriteMaskTestCase.prototype.test = function() {
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var mask = 1 << stencilBit;
+
+ gl.stencilMask(mask);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, mask));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} stencilTargetFace
+ */
+ es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase = function(name, description, testTargetName, stencilTargetFace) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_stencilTargetFace = stencilTargetFace;
+ };
+
+ es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase;
+
+ es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase.prototype.test = function() {
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var mask = 1 << stencilBit;
+
+ gl.stencilMaskSeparate(this.m_stencilTargetFace, mask);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, mask));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} initialValue
+ */
+ es3fIntegerStateQueryTests.PixelStoreTestCase = function(name, description, testTargetName, initialValue) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_initialValue = initialValue;
+ };
+
+ es3fIntegerStateQueryTests.PixelStoreTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.PixelStoreTestCase.prototype.constructor = es3fIntegerStateQueryTests.PixelStoreTestCase;
+
+ es3fIntegerStateQueryTests.PixelStoreTestCase.prototype.test = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, this.m_initialValue));
+
+ /** @type {number} */ var numIterations = 120;
+ for (var i = 0; i < numIterations; ++i) {
+ /** @type {number} */ var referenceValue = rnd.getInt(0, 64000);
+
+ gl.pixelStorei(this.m_testTargetName, referenceValue);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, referenceValue));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ */
+ es3fIntegerStateQueryTests.PixelStoreAlignTestCase = function(name, description, testTargetName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ };
+
+ es3fIntegerStateQueryTests.PixelStoreAlignTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.PixelStoreAlignTestCase.prototype.constructor = es3fIntegerStateQueryTests.PixelStoreAlignTestCase;
+
+ es3fIntegerStateQueryTests.PixelStoreAlignTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_testTargetName, 4));
+
+ /** @type {Array<number>} */ var alignments = [1, 2, 4, 8];
+
+ for (var ndx = 0; ndx < alignments.length; ++ndx) {
+ /** @type {number} */ var referenceValue = alignments[ndx];
+
+ gl.pixelStorei(this.m_testTargetName, referenceValue);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, referenceValue));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} initialValue
+ */
+ es3fIntegerStateQueryTests.BlendFuncTestCase = function(name, description, testTargetName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ };
+
+ es3fIntegerStateQueryTests.BlendFuncTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.BlendFuncTestCase.prototype.constructor = es3fIntegerStateQueryTests.BlendFuncTestCase;
+
+ es3fIntegerStateQueryTests.BlendFuncTestCase.prototype.test = function() {
+ /** @type {Array<number>} */ var blendFuncValues = [
+ gl.ZERO, gl.ONE, gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR, gl.DST_COLOR, gl.ONE_MINUS_DST_COLOR,
+ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.DST_ALPHA, gl.ONE_MINUS_DST_ALPHA, gl.CONSTANT_COLOR,
+ gl.ONE_MINUS_CONSTANT_COLOR, gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_ALPHA,
+ gl.SRC_ALPHA_SATURATE
+ ];
+
+ for (var ndx = 0; ndx < blendFuncValues.length; ++ndx) {
+ /** @type {number} */ var referenceValue = blendFuncValues[ndx];
+
+ this.setBlendFunc(referenceValue);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, referenceValue));
+ }};
+
+ /**
+ * @param {number} func
+ */
+ es3fIntegerStateQueryTests.BlendFuncTestCase.prototype.setBlendFunc = function(func) {
+ switch (this.m_testTargetName) {
+ case gl.BLEND_SRC_RGB:
+ case gl.BLEND_SRC_ALPHA:
+ gl.blendFunc(func, gl.ZERO);
+ break;
+
+ case gl.BLEND_DST_RGB:
+ case gl.BLEND_DST_ALPHA:
+ gl.blendFunc(gl.ZERO, func);
+ break;
+
+ default:
+ throw new Error('should not happen');
+ }
+ };
+
+ es3fIntegerStateQueryTests.BlendFuncTestCase.prototype.deinit = function() {
+ gl.blendFunc(gl.ONE, gl.ZERO);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIntegerStateQueryTests.BlendFuncTestCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} initialValue
+ */
+ es3fIntegerStateQueryTests.BlendFuncSeparateTestCase = function(name, description, testTargetName) {
+ es3fIntegerStateQueryTests.BlendFuncTestCase.call(this, name, description, testTargetName);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ };
+
+ es3fIntegerStateQueryTests.BlendFuncSeparateTestCase.prototype = Object.create(es3fIntegerStateQueryTests.BlendFuncTestCase.prototype);
+ es3fIntegerStateQueryTests.BlendFuncSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.BlendFuncSeparateTestCase;
+
+ /**
+ * @param {number} func
+ */
+ es3fIntegerStateQueryTests.BlendFuncSeparateTestCase.prototype.setBlendFunc = function(func) {
+ switch (this.m_testTargetName) {
+ case gl.BLEND_SRC_RGB:
+ gl.blendFuncSeparate(func, gl.ZERO, gl.ZERO, gl.ZERO);
+ break;
+
+ case gl.BLEND_DST_RGB:
+ gl.blendFuncSeparate(gl.ZERO, func, gl.ZERO, gl.ZERO);
+ break;
+
+ case gl.BLEND_SRC_ALPHA:
+ gl.blendFuncSeparate(gl.ZERO, gl.ZERO, func, gl.ZERO);
+ break;
+
+ case gl.BLEND_DST_ALPHA:
+ gl.blendFuncSeparate(gl.ZERO, gl.ZERO, gl.ZERO, func);
+ break;
+
+ default:
+ throw new Error('should not happen');
+ }
+ };
+
+ es3fIntegerStateQueryTests.BlendFuncSeparateTestCase.prototype.deinit = function() {
+ gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ZERO);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} initialValue
+ */
+ es3fIntegerStateQueryTests.BlendEquationTestCase = function(name, description, testTargetName, initialValue) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_initialValue = initialValue;
+ };
+
+ es3fIntegerStateQueryTests.BlendEquationTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.BlendEquationTestCase.prototype.constructor = es3fIntegerStateQueryTests.BlendEquationTestCase;
+
+ es3fIntegerStateQueryTests.BlendEquationTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_testTargetName, this.m_initialValue));
+
+ /** @type {Array<number>} */ var blendFuncValues = [gl.FUNC_ADD, gl.FUNC_SUBTRACT, gl.FUNC_REVERSE_SUBTRACT, gl.MIN, gl.MAX];
+
+ for (var ndx = 0; ndx < blendFuncValues.length; ++ndx) {
+ /** @type {number} */ var referenceValue = blendFuncValues[ndx];
+
+ this.setBlendEquation(referenceValue);
+
+ this.check(glsStateQuery.verify(this.m_testTargetName, referenceValue));
+ }
+ };
+
+ /**
+ * @param {number} equation
+ */
+ es3fIntegerStateQueryTests.BlendEquationTestCase.prototype.setBlendEquation = function(equation) {
+ gl.blendEquation(equation);
+ };
+
+ es3fIntegerStateQueryTests.BlendEquationTestCase.prototype.deinit = function() {
+ gl.blendEquation(this.m_initialValue);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fIntegerStateQueryTests.BlendEquationTestCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} initialValue
+ */
+ es3fIntegerStateQueryTests.BlendEquationSeparateTestCase = function(name, description, testTargetName, initialValue) {
+ es3fIntegerStateQueryTests.BlendEquationTestCase.call(this, name, description, testTargetName, initialValue);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_initialValue = initialValue;
+ };
+
+ es3fIntegerStateQueryTests.BlendEquationSeparateTestCase.prototype = Object.create(es3fIntegerStateQueryTests.BlendEquationTestCase.prototype);
+ es3fIntegerStateQueryTests.BlendEquationSeparateTestCase.prototype.constructor = es3fIntegerStateQueryTests.BlendEquationSeparateTestCase;
+
+ /**
+ * @param {number} equation
+ */
+ es3fIntegerStateQueryTests.BlendEquationSeparateTestCase.prototype.setBlendEquation = function(equation) {
+ switch (this.m_testTargetName) {
+ case gl.BLEND_EQUATION_RGB:
+ gl.blendEquationSeparate(equation, gl.FUNC_ADD);
+ break;
+
+ case gl.BLEND_EQUATION_ALPHA:
+ gl.blendEquationSeparate(gl.FUNC_ADD, equation);
+ break;
+
+ default:
+ throw new Error('should not happen');
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testTargetName
+ * @param {number} minValue
+ */
+ es3fIntegerStateQueryTests.ImplementationArrayTestCase = function(name, description, testTargetName, minValue) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testTargetName = testTargetName;
+ /** @type {number} */ this.m_minValue = minValue;
+ };
+
+ es3fIntegerStateQueryTests.ImplementationArrayTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ImplementationArrayTestCase.prototype.constructor = es3fIntegerStateQueryTests.ImplementationArrayTestCase;
+
+ es3fIntegerStateQueryTests.ImplementationArrayTestCase.prototype.test = function() {
+ if (!framework.opengl.gluTextureUtil.enableCompressedTextureETC()) {
+ debug('Skipping ETC2 texture format tests: no support for WEBGL_compressed_texture_etc');
+ return;
+ }
+
+ var queryResult = /** @type {Array<number>} */ (gl.getParameter(this.m_testTargetName));
+ this.check(glsStateQuery.compare(queryResult.length, this.m_minValue));
+
+ /** @type {Array<number>} */ var textureFormats = [
+ gl.COMPRESSED_R11_EAC, gl.COMPRESSED_SIGNED_R11_EAC, gl.COMPRESSED_RG11_EAC, gl.COMPRESSED_SIGNED_RG11_EAC, gl.COMPRESSED_RGB8_ETC2, gl.COMPRESSED_SRGB8_ETC2,
+ gl.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, gl.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, gl.COMPRESSED_RGBA8_ETC2_EAC, gl.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ ];
+
+ for (var ndx = 0; ndx < textureFormats.length; ndx++) {
+ /** @type {number} */ var format = textureFormats[ndx];
+ /** @type {boolean} */ var isInArray = queryResult.indexOf(format) !== -1;
+ this.check(glsStateQuery.compare(isInArray, true));
+ }
+
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.CurrentProgramBindingTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.CurrentProgramBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.CurrentProgramBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.CurrentProgramBindingTestCase;
+
+ es3fIntegerStateQueryTests.CurrentProgramBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.CURRENT_PROGRAM, null));
+
+ /** @type {WebGLShader} */ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.compileShader(shaderVert);
+ var compileStatus = /** @type {boolean} */ (gl.getShaderParameter(shaderVert, gl.COMPILE_STATUS));
+ this.check(glsStateQuery.compare(compileStatus, true));
+
+ /** @type {WebGLShader} */ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(shaderFrag, testFragSource);
+ gl.compileShader(shaderFrag);
+ compileStatus = /** @type {boolean} */ (gl.getShaderParameter(shaderFrag, gl.COMPILE_STATUS));
+ this.check(glsStateQuery.compare(compileStatus, true));
+
+ /** @type {WebGLProgram} */ var shaderProg = gl.createProgram();
+ gl.attachShader(shaderProg, shaderVert);
+ gl.attachShader(shaderProg, shaderFrag);
+ gl.linkProgram(shaderProg);
+ var linkStatus = /** @type {boolean} */ (gl.getProgramParameter(shaderProg, gl.LINK_STATUS));
+ this.check(glsStateQuery.compare(linkStatus, true));
+
+ gl.useProgram(shaderProg);
+
+ this.check(glsStateQuery.verify(gl.CURRENT_PROGRAM, shaderProg));
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(shaderProg);
+
+ this.check(glsStateQuery.verify(gl.CURRENT_PROGRAM, shaderProg));
+
+ gl.useProgram(null);
+ this.check(glsStateQuery.verify(gl.CURRENT_PROGRAM, null));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.VertexArrayBindingTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.VertexArrayBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.VertexArrayBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.VertexArrayBindingTestCase;
+
+ es3fIntegerStateQueryTests.VertexArrayBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.VERTEX_ARRAY_BINDING, null));
+
+ /** @type {WebGLVertexArrayObject} */ var vertexArrayObject = gl.createVertexArray();
+
+ gl.bindVertexArray(vertexArrayObject);
+ this.check(glsStateQuery.verify(gl.VERTEX_ARRAY_BINDING, vertexArrayObject));
+
+ gl.deleteVertexArray(vertexArrayObject);
+ this.check(glsStateQuery.verify(gl.VERTEX_ARRAY_BINDING, null));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} bufferBindingName
+ * @param {number} bufferType
+ */
+ es3fIntegerStateQueryTests.BufferBindingTestCase = function(name, description, bufferBindingName, bufferType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_bufferBindingName = bufferBindingName;
+ /** @type {number} */ this.m_bufferType = bufferType;
+ };
+
+ es3fIntegerStateQueryTests.BufferBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.BufferBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.BufferBindingTestCase;
+
+ es3fIntegerStateQueryTests.BufferBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_bufferBindingName, null));
+
+ /** @type {WebGLBuffer} */ var bufferObject = gl.createBuffer();
+
+ gl.bindBuffer(this.m_bufferType, bufferObject);
+ this.check(glsStateQuery.verify(this.m_bufferBindingName, bufferObject));
+
+ gl.deleteBuffer(bufferObject);
+ this.check(glsStateQuery.verify(this.m_bufferBindingName, null));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ */
+ es3fIntegerStateQueryTests.ElementArrayBufferBindingTestCase = function(name) {
+ es3fApiCase.ApiCase.call(this, name, 'GL_ELEMENT_ARRAY_BUFFER_BINDING', gl);
+ };
+
+ es3fIntegerStateQueryTests.ElementArrayBufferBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ElementArrayBufferBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.ElementArrayBufferBindingTestCase;
+
+ es3fIntegerStateQueryTests.ElementArrayBufferBindingTestCase.prototype.test = function() {
+ // Test with default VAO
+ bufferedLogToConsole('DefaultVAO: Test with default VAO');
+
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, null));
+
+ /** @type {WebGLBuffer} */ var bufferObject = gl.createBuffer();
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferObject);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, bufferObject));
+
+ gl.deleteBuffer(bufferObject);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, null));
+
+ // Test with multiple VAOs
+ bufferedLogToConsole('WithVAO: Test with VAO');
+
+ /** @type {Array<WebGLVertexArrayObject>} */ var vaos = [];
+ /** @type {Array<WebGLBuffer>} */ var buffers = [];
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ vaos[ndx] = gl.createVertexArray();
+ buffers[ndx] = gl.createBuffer();
+ }
+
+ // initial
+ gl.bindVertexArray(vaos[0]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, null));
+
+ // after setting
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers[0]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, buffers[0]));
+
+ // initial of vao 2
+ gl.bindVertexArray(vaos[1]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, null));
+
+ // after setting to 2
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers[1]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, buffers[1]));
+
+ // vao 1 still has buffer 1 bound?
+ gl.bindVertexArray(vaos[0]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, buffers[0]));
+
+ // deleting clears from bound vaos ...
+ for (var ndx = 0; ndx < 2; ndx++)
+ gl.deleteBuffer(buffers[ndx]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, null));
+
+ // ... but does not from non-bound vaos?
+ gl.bindVertexArray(vaos[1]);
+ this.check(glsStateQuery.verify(gl.ELEMENT_ARRAY_BUFFER_BINDING, buffers[1]));
+
+ for (var ndx = 0; ndx < 2; ndx++)
+ gl.deleteVertexArray(vaos[ndx]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.StencilClearValueTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.StencilClearValueTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.StencilClearValueTestCase.prototype.constructor = es3fIntegerStateQueryTests.StencilClearValueTestCase;
+
+ es3fIntegerStateQueryTests.StencilClearValueTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.STENCIL_CLEAR_VALUE, 0));
+
+ var stencilBits = /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS));
+
+ for (var stencilBit = 0; stencilBit < stencilBits; ++stencilBit) {
+ /** @type {number} */ var ref = 1 << stencilBit;
+
+ gl.clearStencil(ref); // mask should not affect the REF
+
+ this.check(glsStateQuery.verify(gl.STENCIL_CLEAR_VALUE, ref));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.ActiveTextureTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.ActiveTextureTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ActiveTextureTestCase.prototype.constructor = es3fIntegerStateQueryTests.ActiveTextureTestCase;
+
+ es3fIntegerStateQueryTests.ActiveTextureTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.ACTIVE_TEXTURE, gl.TEXTURE0));
+
+ var textureUnits = /** @type {number} */ (gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
+
+ for (var ndx = 0; ndx < textureUnits; ++ndx) {
+ gl.activeTexture(gl.TEXTURE0 + ndx);
+
+ this.check(glsStateQuery.verify(gl.ACTIVE_TEXTURE, gl.TEXTURE0 + ndx));
+ }
+ };
+
+ es3fIntegerStateQueryTests.ActiveTextureTestCase.prototype.deinit = function() {
+ // [dag] reset the state of the context
+ gl.activeTexture(gl.TEXTURE0);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.RenderbufferBindingTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.RenderbufferBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.RenderbufferBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.RenderbufferBindingTestCase;
+
+ es3fIntegerStateQueryTests.RenderbufferBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.RENDERBUFFER_BINDING, null));
+
+ /** @type {WebGLRenderbuffer} */ var renderBuffer = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderBuffer);
+
+ this.check(glsStateQuery.verify(gl.RENDERBUFFER_BINDING, renderBuffer));
+
+ gl.deleteRenderbuffer(renderBuffer);
+ this.check(glsStateQuery.verify(gl.RENDERBUFFER_BINDING, null));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.SamplerObjectBindingTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.SamplerObjectBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.SamplerObjectBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.SamplerObjectBindingTestCase;
+
+ es3fIntegerStateQueryTests.SamplerObjectBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.SAMPLER_BINDING, null));
+
+ bufferedLogToConsole('SingleUnit: Single unit');
+ /** @type {WebGLSampler} */ var sampler = gl.createSampler();
+
+ gl.bindSampler(0, sampler);
+
+ this.check(glsStateQuery.verify(gl.SAMPLER_BINDING, sampler));
+
+ gl.deleteSampler(sampler);
+ this.check(glsStateQuery.verify(gl.SAMPLER_BINDING, null));
+
+ bufferedLogToConsole('MultipleUnits: Multiple units');
+
+ /** @type {WebGLSampler} */ var samplerA = gl.createSampler();
+ /** @type {WebGLSampler} */ var samplerB = gl.createSampler();
+
+ gl.bindSampler(1, samplerA);
+ gl.bindSampler(2, samplerB);
+
+ this.check(glsStateQuery.verify(gl.SAMPLER_BINDING, null));
+
+ gl.activeTexture(gl.TEXTURE1);
+ this.check(glsStateQuery.verify(gl.SAMPLER_BINDING, samplerA));
+
+ gl.activeTexture(gl.TEXTURE2);
+ this.check(glsStateQuery.verify(gl.SAMPLER_BINDING, samplerB));
+
+ gl.deleteSampler(samplerB);
+ gl.deleteSampler(samplerA);
+ };
+
+ es3fIntegerStateQueryTests.SamplerObjectBindingTestCase.prototype.deinit = function() {
+ gl.activeTexture(gl.TEXTURE0);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} testBindingName
+ * @param {number} textureType
+ */
+ es3fIntegerStateQueryTests.TextureBindingTestCase = function(name, description, testBindingName, textureType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_testBindingName = testBindingName;
+ /** @type {number} */ this.m_textureType = textureType;
+ };
+
+ es3fIntegerStateQueryTests.TextureBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.TextureBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.TextureBindingTestCase;
+
+ es3fIntegerStateQueryTests.TextureBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(this.m_testBindingName, null));
+
+ /** @type {WebGLTexture} */ var texture = gl.createTexture();
+
+ gl.bindTexture(this.m_textureType, texture);
+ this.check(glsStateQuery.verify(this.m_testBindingName, texture));
+
+ gl.deleteTexture(texture);
+
+ this.check(glsStateQuery.verify(this.m_testBindingName, null));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.FrameBufferBindingTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.FrameBufferBindingTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.FrameBufferBindingTestCase.prototype.constructor = es3fIntegerStateQueryTests.FrameBufferBindingTestCase;
+
+ es3fIntegerStateQueryTests.FrameBufferBindingTestCase.prototype.test = function() {
+ this.check(glsStateQuery.verify(gl.DRAW_FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.READ_FRAMEBUFFER_BINDING, null));
+
+ /** @type {WebGLFramebuffer} */ var framebufferId = gl.createFramebuffer();
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferId);
+
+ this.check(glsStateQuery.verify(gl.DRAW_FRAMEBUFFER_BINDING, framebufferId));
+ this.check(glsStateQuery.verify(gl.FRAMEBUFFER_BINDING, framebufferId));
+ this.check(glsStateQuery.verify(gl.READ_FRAMEBUFFER_BINDING, framebufferId));
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.check(glsStateQuery.verify(gl.DRAW_FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.READ_FRAMEBUFFER_BINDING, null));
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, framebufferId);
+
+ this.check(glsStateQuery.verify(gl.DRAW_FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.READ_FRAMEBUFFER_BINDING, framebufferId));
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebufferId);
+
+ this.check(glsStateQuery.verify(gl.DRAW_FRAMEBUFFER_BINDING, framebufferId));
+ this.check(glsStateQuery.verify(gl.FRAMEBUFFER_BINDING, framebufferId));
+ this.check(glsStateQuery.verify(gl.READ_FRAMEBUFFER_BINDING, framebufferId));
+
+ gl.deleteFramebuffer(framebufferId);
+
+ this.check(glsStateQuery.verify(gl.DRAW_FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.FRAMEBUFFER_BINDING, null));
+ this.check(glsStateQuery.verify(gl.READ_FRAMEBUFFER_BINDING, null));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.ImplementationColorReadTestCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.ImplementationColorReadTestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ImplementationColorReadTestCase.prototype.constructor = es3fIntegerStateQueryTests.ImplementationColorReadTestCase;
+
+ es3fIntegerStateQueryTests.ImplementationColorReadTestCase.prototype.test = function() {
+ /** @type {Array<number>} */ var defaultColorTypes = [
+ gl.UNSIGNED_BYTE, gl.BYTE, gl.UNSIGNED_SHORT, gl.SHORT,
+ gl.UNSIGNED_INT, gl.INT, gl.HALF_FLOAT, gl.FLOAT, gl.UNSIGNED_SHORT_5_6_5,
+ gl.UNSIGNED_SHORT_4_4_4_4, gl.UNSIGNED_SHORT_5_5_5_1,
+ gl.UNSIGNED_INT_2_10_10_10_REV, gl.UNSIGNED_INT_10F_11F_11F_REV
+ ];
+
+ /** @type {Array<number>} */ var defaultColorFormats = [
+ gl.RGBA, gl.RGBA_INTEGER, gl.RGB, gl.RGB_INTEGER,
+ gl.RG, gl.RG_INTEGER, gl.RED, gl.RED_INTEGER
+ ];
+
+ /** @type {Array<number>} */ var validColorTypes = [];
+ /** @type {Array<number>} */ var validColorFormats = [];
+
+ // Defined by the spec
+
+ for (var ndx = 0; ndx < defaultColorTypes.length; ++ndx)
+ validColorTypes.push(defaultColorTypes[ndx]);
+ for (var ndx = 0; ndx < defaultColorFormats.length; ++ndx)
+ validColorFormats.push(defaultColorFormats[ndx]);
+
+ // Extensions
+
+ // if (this.m_context.getContextInfo().isExtensionSupported("gl.EXT_texture_format_BGRA8888") ||
+ // this.m_context.getContextInfo().isExtensionSupported("gl.APPLE_texture_format_BGRA8888"))
+ // validColorFormats.push(gl.BGRA);
+ //
+ // if (this.m_context.getContextInfo().isExtensionSupported("gl.EXT_read_format_bgra")) {
+ // validColorFormats.push(gl.BGRA);
+ // validColorTypes.push(gl.UNSIGNED_SHORT_4_4_4_4_REV);
+ // validColorTypes.push(gl.UNSIGNED_SHORT_1_5_5_5_REV);
+ // }
+ //
+ // if (this.m_context.getContextInfo().isExtensionSupported("gl.IMG_read_format")) {
+ // validColorFormats.push(gl.BGRA);
+ // validColorTypes.push(gl.UNSIGNED_SHORT_4_4_4_4_REV);
+ // }
+ //
+ // if (this.m_context.getContextInfo().isExtensionSupported("gl.NV_sRGB_formats")) {
+ // validColorFormats.push(gl.SLUMINANCE_NV);
+ // validColorFormats.push(gl.SLUMINANCE_ALPHA_NV);
+ // }
+ //
+ // if (this.m_context.getContextInfo().isExtensionSupported("gl.NV_bgr")) {
+ // validColorFormats.push(gl.BGR_NV);
+ // }
+
+ this.check(glsStateQuery.verifyAnyOf(gl.IMPLEMENTATION_COLOR_READ_TYPE, validColorTypes));
+ this.check(glsStateQuery.verifyAnyOf(gl.IMPLEMENTATION_COLOR_READ_FORMAT, validColorFormats));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.ReadBufferCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.ReadBufferCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ReadBufferCase.prototype.constructor = es3fIntegerStateQueryTests.ReadBufferCase;
+
+ es3fIntegerStateQueryTests.ReadBufferCase.prototype.test = function() {
+ /** @type {Array<number>} */ var validInitialValues = [gl.BACK, gl.NONE];
+ this.check(glsStateQuery.verifyAnyOf(gl.READ_BUFFER, validInitialValues));
+
+ gl.readBuffer(gl.NONE);
+ this.check(glsStateQuery.verify(gl.READ_BUFFER, gl.NONE));
+
+ gl.readBuffer(gl.BACK);
+ this.check(glsStateQuery.verify(gl.READ_BUFFER, gl.BACK));
+
+ // test gl.READ_BUFFER with framebuffers
+
+ /** @type {WebGLFramebuffer} */ var framebufferId = gl.createFramebuffer();
+
+ /** @type {WebGLRenderbuffer} */ var renderbuffer_id = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer_id);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 128, 128);
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, framebufferId);
+
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer_id);
+
+ this.check(glsStateQuery.verify(gl.READ_BUFFER, gl.COLOR_ATTACHMENT0));
+
+ gl.deleteFramebuffer(framebufferId);
+ gl.deleteRenderbuffer(renderbuffer_id);
+
+ this.check(glsStateQuery.verify(gl.READ_BUFFER, gl.BACK));
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fIntegerStateQueryTests.DrawBufferCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ };
+
+ es3fIntegerStateQueryTests.DrawBufferCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.DrawBufferCase.prototype.constructor = es3fIntegerStateQueryTests.DrawBufferCase;
+
+ es3fIntegerStateQueryTests.DrawBufferCase.prototype.test = function() {
+ /** @type {Array<number>} */ var validInitialValues = [gl.BACK, gl.NONE];
+ this.check(glsStateQuery.verifyAnyOf(gl.DRAW_BUFFER0, validInitialValues));
+
+ /** @type {number} */ var bufs = gl.NONE;
+ gl.drawBuffers([bufs]);
+ this.check(glsStateQuery.verify(gl.DRAW_BUFFER0, gl.NONE));
+
+ bufs = gl.BACK;
+ gl.drawBuffers([bufs]);
+ this.check(glsStateQuery.verify(gl.DRAW_BUFFER0, gl.BACK));
+
+ // test gl.DRAW_BUFFER with framebuffers
+
+ /** @type {WebGLFramebuffer} */ var framebufferId = gl.createFramebuffer();
+
+ /** @type {Array<WebGLRenderbuffer>} */ var renderbuffer_ids = [];
+
+ for (var ndx = 0; ndx < 2; ndx++)
+ renderbuffer_ids[ndx] = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer_ids[0]);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 128, 128);
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer_ids[1]);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 128, 128);
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebufferId);
+
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer_ids[0]);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, renderbuffer_ids[1]);
+
+ // only the initial state the draw buffer for fragment color zero is defined
+ this.check(glsStateQuery.verify(gl.DRAW_BUFFER0, gl.COLOR_ATTACHMENT0));
+
+ /** @type {Array<number>} */ var bufTargets = [gl.NONE, gl.COLOR_ATTACHMENT1];
+ gl.drawBuffers(bufTargets);
+ this.check(glsStateQuery.verify(gl.DRAW_BUFFER0, gl.NONE));
+ this.check(glsStateQuery.verify(gl.DRAW_BUFFER1, gl.COLOR_ATTACHMENT1));
+
+ gl.deleteFramebuffer(framebufferId);
+ gl.deleteRenderbuffer(renderbuffer_ids[0]);
+ gl.deleteRenderbuffer(renderbuffer_ids[1]);
+
+ this.check(glsStateQuery.verify(gl.DRAW_BUFFER0, gl.BACK));
+ };
+
+ // Integer64
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {number} minValue
+ */
+ es3fIntegerStateQueryTests.ConstantMinimumValue64TestCase = function(name, description, targetName, minValue) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_targetName = targetName;
+ /** @type {number} */ this.m_minValue = minValue;
+ };
+
+ es3fIntegerStateQueryTests.ConstantMinimumValue64TestCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.ConstantMinimumValue64TestCase.prototype.constructor = es3fIntegerStateQueryTests.ConstantMinimumValue64TestCase;
+
+ es3fIntegerStateQueryTests.ConstantMinimumValue64TestCase.prototype.test = function() {
+ this.check(glsStateQuery.verifyGreaterOrEqual(this.m_targetName, this.m_minValue), 'Fail');
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {number} targetMaxUniformBlocksName
+ * @param {number} targetMaxUniformComponentsName
+ */
+ es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase = function(name, description, targetName, targetMaxUniformBlocksName, targetMaxUniformComponentsName) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {number} */ this.m_targetName = targetName;
+ /** @type {number} */ this.m_targetMaxUniformBlocksName = targetMaxUniformBlocksName;
+ /** @type {number} */ this.m_targetMaxUniformComponentsName = targetMaxUniformComponentsName;
+ };
+
+ es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase.prototype = Object.create(es3fApiCase.ApiCase.prototype);
+ es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase.prototype.constructor = es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase;
+
+ es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase.prototype.test = function() {
+ var uniformBlockSize = /** @type {number} */ (gl.getParameter(gl.MAX_UNIFORM_BLOCK_SIZE));
+ var maxUniformBlocks = /** @type {number} */ (gl.getParameter(this.m_targetMaxUniformBlocksName));
+ var maxUniformComponents = /** @type {number} */ (gl.getParameter(this.m_targetMaxUniformComponentsName));
+
+ // MAX_stage_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE / 4 + MAX_stage_UNIFORM_COMPONENTS
+ /** @type {number} */ var minCombinedUniformComponents = maxUniformBlocks * uniformBlockSize / 4 + maxUniformComponents;
+
+ this.check(glsStateQuery.verifyGreaterOrEqual(this.m_targetName, minCombinedUniformComponents));
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fIntegerStateQueryTests.IntegerStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'integers', 'Integer Values');
+ };
+
+ es3fIntegerStateQueryTests.IntegerStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fIntegerStateQueryTests.IntegerStateQueryTests.prototype.constructor = es3fIntegerStateQueryTests.IntegerStateQueryTests;
+
+ es3fIntegerStateQueryTests.IntegerStateQueryTests.prototype.init = function() {
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {number} value
+ */
+ var LimitedStateInteger = function(name, description, targetName, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.targetName = targetName;
+ /** @type {number} */ this.value = value;
+ };
+
+ /** @type {Array<LimitedStateInteger>} */ var implementationMinLimits = [
+ new LimitedStateInteger('subpixel_bits', 'SUBPIXEL_BITS has minimum value of 4', gl.SUBPIXEL_BITS, 4),
+ new LimitedStateInteger('max_3d_texture_size', 'MAX_3D_TEXTURE_SIZE has minimum value of 256', gl.MAX_3D_TEXTURE_SIZE, 256),
+ new LimitedStateInteger('max_texture_size', 'MAX_TEXTURE_SIZE has minimum value of 2048', gl.MAX_TEXTURE_SIZE, 2048),
+ new LimitedStateInteger('max_array_texture_layers', 'MAX_ARRAY_TEXTURE_LAYERS has minimum value of 256', gl.MAX_ARRAY_TEXTURE_LAYERS, 256),
+ new LimitedStateInteger('max_cube_map_texture_size', 'MAX_CUBE_MAP_TEXTURE_SIZE has minimum value of 2048', gl.MAX_CUBE_MAP_TEXTURE_SIZE, 2048),
+ new LimitedStateInteger('max_renderbuffer_size', 'MAX_RENDERBUFFER_SIZE has minimum value of 2048', gl.MAX_RENDERBUFFER_SIZE, 2048),
+ new LimitedStateInteger('max_draw_buffers', 'MAX_DRAW_BUFFERS has minimum value of 4', gl.MAX_DRAW_BUFFERS, 4),
+ new LimitedStateInteger('max_color_attachments', 'MAX_COLOR_ATTACHMENTS has minimum value of 4', gl.MAX_COLOR_ATTACHMENTS, 4),
+ new LimitedStateInteger('max_elements_indices', 'MAX_ELEMENTS_INDICES has minimum value of 0', gl.MAX_ELEMENTS_INDICES, 0),
+ new LimitedStateInteger('max_elements_vertices', 'MAX_ELEMENTS_VERTICES has minimum value of 0', gl.MAX_ELEMENTS_VERTICES, 0),
+ new LimitedStateInteger('max_vertex_attribs', 'MAX_VERTEX_ATTRIBS has minimum value of 16', gl.MAX_VERTEX_ATTRIBS, 16),
+ new LimitedStateInteger('max_vertex_uniform_components', 'MAX_VERTEX_UNIFORM_COMPONENTS has minimum value of 1024', gl.MAX_VERTEX_UNIFORM_COMPONENTS, 1024),
+ new LimitedStateInteger('max_vertex_uniform_vectors', 'MAX_VERTEX_UNIFORM_VECTORS has minimum value of 256', gl.MAX_VERTEX_UNIFORM_VECTORS, 256),
+ new LimitedStateInteger('max_vertex_uniform_blocks', 'MAX_VERTEX_UNIFORM_BLOCKS has minimum value of 12', gl.MAX_VERTEX_UNIFORM_BLOCKS, 12),
+ new LimitedStateInteger('max_vertex_output_components', 'MAX_VERTEX_OUTPUT_COMPONENTS has minimum value of 64', gl.MAX_VERTEX_OUTPUT_COMPONENTS, 64),
+ new LimitedStateInteger('max_vertex_texture_image_units', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS has minimum value of 16', gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS, 16),
+ new LimitedStateInteger('max_fragment_uniform_components', 'MAX_FRAGMENT_UNIFORM_COMPONENTS has minimum value of 896', gl.MAX_FRAGMENT_UNIFORM_COMPONENTS, 896),
+ new LimitedStateInteger('max_fragment_uniform_vectors', 'MAX_FRAGMENT_UNIFORM_VECTORS has minimum value of 224', gl.MAX_FRAGMENT_UNIFORM_VECTORS, 224),
+ new LimitedStateInteger('max_fragment_uniform_blocks', 'MAX_FRAGMENT_UNIFORM_BLOCKS has minimum value of 12', gl.MAX_FRAGMENT_UNIFORM_BLOCKS, 12),
+ new LimitedStateInteger('max_fragment_input_components', 'MAX_FRAGMENT_INPUT_COMPONENTS has minimum value of 60', gl.MAX_FRAGMENT_INPUT_COMPONENTS, 60),
+ new LimitedStateInteger('max_texture_image_units', 'MAX_TEXTURE_IMAGE_UNITS has minimum value of 16', gl.MAX_TEXTURE_IMAGE_UNITS, 16),
+ new LimitedStateInteger('max_program_texel_offset', 'MAX_PROGRAM_TEXEL_OFFSET has minimum value of 7', gl.MAX_PROGRAM_TEXEL_OFFSET, 7),
+ new LimitedStateInteger('max_uniform_buffer_bindings', 'MAX_UNIFORM_BUFFER_BINDINGS has minimum value of 24', gl.MAX_UNIFORM_BUFFER_BINDINGS, 24),
+ new LimitedStateInteger('max_combined_uniform_blocks', 'MAX_COMBINED_UNIFORM_BLOCKS has minimum value of 24', gl.MAX_COMBINED_UNIFORM_BLOCKS, 24),
+ new LimitedStateInteger('max_varying_components', 'MAX_VARYING_COMPONENTS has minimum value of 60', gl.MAX_VARYING_COMPONENTS, 60),
+ new LimitedStateInteger('max_varying_vectors', 'MAX_VARYING_VECTORS has minimum value of 15', gl.MAX_VARYING_VECTORS, 15),
+ new LimitedStateInteger('max_combined_texture_image_units', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS has minimum value of 32', gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS, 32),
+ new LimitedStateInteger('max_transform_feedback_interleaved_components', 'MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS has minimum value of 64', gl.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, 64),
+ new LimitedStateInteger('max_transform_feedback_separate_attribs', 'MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS has minimum value of 4', gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, 4),
+ new LimitedStateInteger('max_transform_feedback_separate_components', 'MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS has minimum value of 4', gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, 4),
+ new LimitedStateInteger('max_samples', 'MAX_SAMPLES has minimum value of 4', gl.MAX_SAMPLES, 4),
+ new LimitedStateInteger('red_bits', 'RED_BITS has minimum value of 0', gl.RED_BITS, 0),
+ new LimitedStateInteger('green_bits', 'GREEN_BITS has minimum value of 0', gl.GREEN_BITS, 0),
+ new LimitedStateInteger('blue_bits', 'BLUE_BITS has minimum value of 0', gl.BLUE_BITS, 0),
+ new LimitedStateInteger('alpha_bits', 'ALPHA_BITS has minimum value of 0', gl.ALPHA_BITS, 0),
+ new LimitedStateInteger('depth_bits', 'DEPTH_BITS has minimum value of 0', gl.DEPTH_BITS, 0),
+ new LimitedStateInteger('stencil_bits', 'STENCIL_BITS has minimum value of 0', gl.STENCIL_BITS, 0)
+ ];
+
+ /** @type {Array<LimitedStateInteger>} */ var implementationMaxLimits = [
+ new LimitedStateInteger('min_program_texel_offset', 'MIN_PROGRAM_TEXEL_OFFSET has maximum value of -8', gl.MIN_PROGRAM_TEXEL_OFFSET, -8),
+ new LimitedStateInteger('uniform_buffer_offset_alignment', 'UNIFORM_BUFFER_OFFSET_ALIGNMENT has minimum value of 1', gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT, 256)
+ ];
+
+ var testCtx = this;
+
+ for (var testNdx = 0; testNdx < implementationMinLimits.length; testNdx++)
+ testCtx.addChild(new es3fIntegerStateQueryTests.ConstantMinimumValueTestCase(implementationMinLimits[testNdx].name, implementationMinLimits[testNdx].description, implementationMinLimits[testNdx].targetName, implementationMinLimits[testNdx].value));
+
+ for (var testNdx = 0; testNdx < implementationMaxLimits.length; testNdx++)
+ testCtx.addChild(new es3fIntegerStateQueryTests.ConstantMaximumValueTestCase(implementationMaxLimits[testNdx].name, implementationMaxLimits[testNdx].description, implementationMaxLimits[testNdx].targetName, implementationMaxLimits[testNdx].value));
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.SampleBuffersTestCase('sample_buffers', 'SAMPLE_BUFFERS'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.SamplesTestCase('samples' , 'SAMPLES'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.HintTestCase('generate_mipmap_hint', 'GENERATE_MIPMAP_HINT', gl.GENERATE_MIPMAP_HINT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.HintTestCase('fragment_shader_derivative_hint', 'FRAGMENT_SHADER_DERIVATIVE_HINT', gl.FRAGMENT_SHADER_DERIVATIVE_HINT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.DepthFuncTestCase('depth_func', 'DEPTH_FUNC'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.CullFaceTestCase('cull_face_mode', 'CULL_FACE_MODE'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.FrontFaceTestCase('front_face_mode', 'FRONT_FACE'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.ViewPortTestCase('viewport', 'VIEWPORT'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.ScissorBoxTestCase('scissor_box', 'SCISSOR_BOX'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.MaxViewportDimsTestCase('max_viewport_dims', 'MAX_VIEWPORT_DIMS'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilRefTestCase('stencil_ref', 'STENCIL_REF', gl.STENCIL_REF));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilRefTestCase('stencil_back_ref', 'STENCIL_BACK_REF', gl.STENCIL_BACK_REF));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilRefSeparateTestCase('stencil_ref_separate', 'STENCIL_REF (separate)', gl.STENCIL_REF, gl.FRONT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilRefSeparateTestCase('stencil_ref_separate_both', 'STENCIL_REF (separate)', gl.STENCIL_REF, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilRefSeparateTestCase('stencil_back_ref_separate', 'STENCIL_BACK_REF (separate)', gl.STENCIL_BACK_REF, gl.BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilRefSeparateTestCase('stencil_back_ref_separate_both', 'STENCIL_BACK_REF (separate)', gl.STENCIL_BACK_REF, gl.FRONT_AND_BACK));
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} frontDescription
+ * @param {number} frontTarget
+ * @param {string} backDescription
+ * @param {number} backTarget
+ */
+ var NamedStencilOp = function(name, frontDescription, frontTarget, backDescription, backTarget) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.frontDescription = frontDescription;
+ /** @type {number} */ this.frontTarget = frontTarget;
+ /** @type {string} */ this.backDescription = backDescription;
+ /** @type {number} */ this.backTarget = backTarget;
+ };
+
+ /** @type {Array<NamedStencilOp>} */ var stencilOps = [
+ new NamedStencilOp('fail', 'STENCIL_FAIL', gl.STENCIL_FAIL, 'STENCIL_BACK_FAIL', gl.STENCIL_BACK_FAIL),
+ new NamedStencilOp('depth_fail', 'STENCIL_PASS_DEPTH_FAIL', gl.STENCIL_PASS_DEPTH_FAIL, 'STENCIL_BACK_PASS_DEPTH_FAIL', gl.STENCIL_BACK_PASS_DEPTH_FAIL),
+ new NamedStencilOp('depth_pass', 'STENCIL_PASS_DEPTH_PASS', gl.STENCIL_PASS_DEPTH_PASS, 'STENCIL_BACK_PASS_DEPTH_PASS', gl.STENCIL_BACK_PASS_DEPTH_PASS)
+ ];
+
+ for (var testNdx = 0; testNdx < stencilOps.length; testNdx++) {
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilOpTestCase('stencil_' + stencilOps[testNdx].name, stencilOps[testNdx].frontDescription, stencilOps[testNdx].frontTarget));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilOpTestCase('stencil_back_' + stencilOps[testNdx].name, stencilOps[testNdx].backDescription, stencilOps[testNdx].backTarget));
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilOpSeparateTestCase('stencil_' + stencilOps[testNdx].name + '_separate_both', stencilOps[testNdx].frontDescription, stencilOps[testNdx].frontTarget, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilOpSeparateTestCase('stencil_back_' + stencilOps[testNdx].name + '_separate_both', stencilOps[testNdx].backDescription, stencilOps[testNdx].backTarget, gl.FRONT_AND_BACK));
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilOpSeparateTestCase('stencil_' + stencilOps[testNdx].name + '_separate', stencilOps[testNdx].frontDescription, stencilOps[testNdx].frontTarget, gl.FRONT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilOpSeparateTestCase('stencil_back_' + stencilOps[testNdx].name + '_separate', stencilOps[testNdx].backDescription, stencilOps[testNdx].backTarget, gl.BACK));
+ }
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilFuncTestCase('stencil_func', 'STENCIL_FUNC'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilFuncSeparateTestCase('stencil_func_separate', 'STENCIL_FUNC (separate)', gl.STENCIL_FUNC, gl.FRONT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilFuncSeparateTestCase('stencil_func_separate_both', 'STENCIL_FUNC (separate)', gl.STENCIL_FUNC, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilFuncSeparateTestCase('stencil_back_func_separate', 'STENCIL_FUNC (separate)', gl.STENCIL_BACK_FUNC, gl.BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilFuncSeparateTestCase('stencil_back_func_separate_both', 'STENCIL_FUNC (separate)', gl.STENCIL_BACK_FUNC, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilMaskTestCase('stencil_value_mask', 'STENCIL_VALUE_MASK', gl.STENCIL_VALUE_MASK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilMaskTestCase('stencil_back_value_mask', 'STENCIL_BACK_VALUE_MASK', gl.STENCIL_BACK_VALUE_MASK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilMaskSeparateTestCase('stencil_value_mask_separate', 'STENCIL_VALUE_MASK (separate)', gl.STENCIL_VALUE_MASK, gl.FRONT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilMaskSeparateTestCase('stencil_value_mask_separate_both', 'STENCIL_VALUE_MASK (separate)', gl.STENCIL_VALUE_MASK, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilMaskSeparateTestCase('stencil_back_value_mask_separate', 'STENCIL_BACK_VALUE_MASK (separate)', gl.STENCIL_BACK_VALUE_MASK, gl.BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilMaskSeparateTestCase('stencil_back_value_mask_separate_both', 'STENCIL_BACK_VALUE_MASK (separate)', gl.STENCIL_BACK_VALUE_MASK, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilWriteMaskTestCase('stencil_writemask', 'STENCIL_WRITEMASK', gl.STENCIL_WRITEMASK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilWriteMaskTestCase('stencil_back_writemask', 'STENCIL_BACK_WRITEMASK', gl.STENCIL_BACK_WRITEMASK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase('stencil_writemask_separate', 'STENCIL_WRITEMASK (separate)', gl.STENCIL_WRITEMASK, gl.FRONT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase('stencil_writemask_separate_both', 'STENCIL_WRITEMASK (separate)', gl.STENCIL_WRITEMASK, gl.FRONT_AND_BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase('stencil_back_writemask_separate', 'STENCIL_BACK_WRITEMASK (separate)', gl.STENCIL_BACK_WRITEMASK, gl.BACK));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilWriteMaskSeparateTestCase('stencil_back_writemask_separate_both', 'STENCIL_BACK_WRITEMASK (separate)', gl.STENCIL_BACK_WRITEMASK, gl.FRONT_AND_BACK));
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} target
+ * @param {number} initialValue
+ */
+ var PixelStoreState = function(name, description, target, initialValue) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.target = target;
+ /** @type {number} */ this.initialValue = initialValue;
+ };
+
+ /** @type {Array<PixelStoreState>} */ var pixelStoreStates = [
+ new PixelStoreState('unpack_image_height', 'UNPACK_IMAGE_HEIGHT', gl.UNPACK_IMAGE_HEIGHT, 0),
+ new PixelStoreState('unpack_skip_images', 'UNPACK_SKIP_IMAGES', gl.UNPACK_SKIP_IMAGES, 0),
+ new PixelStoreState('unpack_row_length', 'UNPACK_ROW_LENGTH', gl.UNPACK_ROW_LENGTH, 0),
+ new PixelStoreState('unpack_skip_rows', 'UNPACK_SKIP_ROWS', gl.UNPACK_SKIP_ROWS, 0),
+ new PixelStoreState('unpack_skip_pixels', 'UNPACK_SKIP_PIXELS', gl.UNPACK_SKIP_PIXELS, 0),
+ new PixelStoreState('pack_row_length', 'PACK_ROW_LENGTH', gl.PACK_ROW_LENGTH, 0),
+ new PixelStoreState('pack_skip_rows', 'PACK_SKIP_ROWS', gl.PACK_SKIP_ROWS, 0),
+ new PixelStoreState('pack_skip_pixels', 'PACK_SKIP_PIXELS', gl.PACK_SKIP_PIXELS, 0)
+ ];
+
+ for (var testNdx = 0; testNdx < pixelStoreStates.length; testNdx++)
+ testCtx.addChild(new es3fIntegerStateQueryTests.PixelStoreTestCase(pixelStoreStates[testNdx].name, pixelStoreStates[testNdx].description, pixelStoreStates[testNdx].target, pixelStoreStates[testNdx].initialValue));
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.PixelStoreAlignTestCase('unpack_alignment', 'UNPACK_ALIGNMENT', gl.UNPACK_ALIGNMENT));
+ testCtx.addChild(new es3fIntegerStateQueryTests.PixelStoreAlignTestCase('pack_alignment', 'PACK_ALIGNMENT', gl.PACK_ALIGNMENT));
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} target
+ * @param {number} initialValue
+ */
+ var BlendColorState = function(name, description, target, initialValue) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.target = target;
+ /** @type {number} */ this.initialValue = initialValue;
+ };
+
+ /** @type {Array<PixelStoreState>} */ var blendColorStates = [
+ new BlendColorState('blend_src_rgb', 'BLEND_SRC_RGB', gl.BLEND_SRC_RGB),
+ new BlendColorState('blend_src_alpha', 'BLEND_SRC_ALPHA', gl.BLEND_SRC_ALPHA),
+ new BlendColorState('blend_dst_rgb', 'BLEND_DST_RGB', gl.BLEND_DST_RGB),
+ new BlendColorState('blend_dst_alpha', 'BLEND_DST_ALPHA', gl.BLEND_DST_ALPHA)
+ ];
+
+ for (var testNdx = 0; testNdx < blendColorStates.length; testNdx++) {
+ testCtx.addChild(new es3fIntegerStateQueryTests.BlendFuncTestCase(blendColorStates[testNdx].name, blendColorStates[testNdx].description, blendColorStates[testNdx].target));
+ testCtx.addChild(new es3fIntegerStateQueryTests.BlendFuncSeparateTestCase(blendColorStates[testNdx].name + '_separate', blendColorStates[testNdx].description, blendColorStates[testNdx].target));
+ }
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} target
+ * @param {number} initialValue
+ */
+ var BlendEquationState = function(name, description, target, initialValue) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.target = target;
+ /** @type {number} */ this.initialValue = initialValue;
+ };
+
+ /** @type {Array<PixelStoreState>} */ var blendEquationStates = [
+ new BlendEquationState('blend_equation_rgb', 'BLEND_EQUATION_RGB', gl.BLEND_EQUATION_RGB, gl.FUNC_ADD),
+ new BlendEquationState('blend_equation_alpha', 'BLEND_EQUATION_ALPHA', gl.BLEND_EQUATION_ALPHA, gl.FUNC_ADD)
+ ];
+
+ for (var testNdx = 0; testNdx < blendEquationStates.length; testNdx++) {
+ testCtx.addChild(new es3fIntegerStateQueryTests.BlendEquationTestCase(blendEquationStates[testNdx].name, blendEquationStates[testNdx].description, blendEquationStates[testNdx].target, blendEquationStates[testNdx].initialValue));
+ testCtx.addChild(new es3fIntegerStateQueryTests.BlendEquationSeparateTestCase(blendEquationStates[testNdx].name + '_separate', blendEquationStates[testNdx].description, blendEquationStates[testNdx].target, blendEquationStates[testNdx].initialValue));
+ }
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} target
+ * @param {number} minValue
+ */
+ var ImplementationArrayReturningState = function(name, description, target, minValue) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.target = target;
+ /** @type {number} */ this.minValue = minValue;
+ };
+
+ /** @type {ImplementationArrayReturningState} */ var implementationArrayReturningStates = new ImplementationArrayReturningState('compressed_texture_formats', 'COMPRESSED_TEXTURE_FORMATS', gl.COMPRESSED_TEXTURE_FORMATS, 10);
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.ImplementationArrayTestCase(implementationArrayReturningStates.name, implementationArrayReturningStates.description, implementationArrayReturningStates.target, implementationArrayReturningStates.minValue));
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} target
+ * @param {number} type
+ */
+ var BufferBindingState = function(name, description, target, type) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.target = target;
+ /** @type {number} */ this.type = type;
+ };
+
+ /** @type {Array<BufferBindingState>} */ var bufferBindingStates = [
+ new BufferBindingState('array_buffer_binding', 'ARRAY_BUFFER_BINDING', gl.ARRAY_BUFFER_BINDING, gl.ARRAY_BUFFER),
+ new BufferBindingState('uniform_buffer_binding', 'UNIFORM_BUFFER_BINDING', gl.UNIFORM_BUFFER_BINDING, gl.UNIFORM_BUFFER),
+ new BufferBindingState('pixel_pack_buffer_binding', 'PIXEL_PACK_BUFFER_BINDING', gl.PIXEL_PACK_BUFFER_BINDING, gl.PIXEL_PACK_BUFFER),
+ new BufferBindingState('pixel_unpack_buffer_binding', 'PIXEL_UNPACK_BUFFER_BINDING', gl.PIXEL_UNPACK_BUFFER_BINDING, gl.PIXEL_UNPACK_BUFFER),
+ new BufferBindingState('transform_feedback_buffer_binding', 'TRANSFORM_FEEDBACK_BUFFER_BINDING', gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, gl.TRANSFORM_FEEDBACK_BUFFER),
+ new BufferBindingState('copy_read_buffer_binding', 'COPY_READ_BUFFER_BINDING', gl.COPY_READ_BUFFER_BINDING, gl.COPY_READ_BUFFER),
+ new BufferBindingState('copy_write_buffer_binding', 'COPY_WRITE_BUFFER_BINDING', gl.COPY_WRITE_BUFFER_BINDING, gl.COPY_WRITE_BUFFER)
+ ];
+
+ for (var testNdx = 0; testNdx < bufferBindingStates.length; testNdx++)
+ testCtx.addChild(new es3fIntegerStateQueryTests.BufferBindingTestCase(bufferBindingStates[testNdx].name, bufferBindingStates[testNdx].description, bufferBindingStates[testNdx].target, bufferBindingStates[testNdx].type));
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.ElementArrayBufferBindingTestCase('element_array_buffer_binding'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase('transform_feedback_binding'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.TransformFeedbackBindingTestCase('transform_feedback_binding'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.CurrentProgramBindingTestCase('current_program_binding', 'CURRENT_PROGRAM'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.VertexArrayBindingTestCase('vertex_array_binding', 'VERTEX_ARRAY_BINDING'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.StencilClearValueTestCase('stencil_clear_value', 'STENCIL_CLEAR_VALUE'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.ActiveTextureTestCase('active_texture', 'ACTIVE_TEXTURE'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.RenderbufferBindingTestCase('renderbuffer_binding', 'RENDERBUFFER_BINDING'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.SamplerObjectBindingTestCase('sampler_binding', 'SAMPLER_BINDING'));
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} target
+ * @param {number} type
+ */
+ var TextureBinding = function(name, description, target, type) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.target = target;
+ /** @type {number} */ this.type = type;
+ };
+
+ /** @type {Array<TextureBinding>} */ var textureBindings = [
+ new TextureBinding('texture_binding_2d', 'TEXTURE_BINDING_2D', gl.TEXTURE_BINDING_2D, gl.TEXTURE_2D),
+ new TextureBinding('texture_binding_3d', 'TEXTURE_BINDING_3D', gl.TEXTURE_BINDING_3D, gl.TEXTURE_3D),
+ new TextureBinding('texture_binding_2d_array', 'TEXTURE_BINDING_2D_ARRAY', gl.TEXTURE_BINDING_2D_ARRAY, gl.TEXTURE_2D_ARRAY),
+ new TextureBinding('texture_binding_cube_map', 'TEXTURE_BINDING_CUBE_MAP', gl.TEXTURE_BINDING_CUBE_MAP, gl.TEXTURE_CUBE_MAP)
+ ];
+
+ for (var testNdx = 0; testNdx < textureBindings.length; testNdx++)
+ testCtx.addChild(new es3fIntegerStateQueryTests.TextureBindingTestCase(textureBindings[testNdx].name, textureBindings[testNdx].description, textureBindings[testNdx].target, textureBindings[testNdx].type));
+
+ testCtx.addChild(new es3fIntegerStateQueryTests.FrameBufferBindingTestCase('framebuffer_binding', 'DRAW_FRAMEBUFFER_BINDING and READ_FRAMEBUFFER_BINDING'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.ImplementationColorReadTestCase('implementation_color_read', 'IMPLEMENTATION_COLOR_READ_TYPE and IMPLEMENTATION_COLOR_READ_FORMAT'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.ReadBufferCase('read_buffer', 'READ_BUFFER'));
+ testCtx.addChild(new es3fIntegerStateQueryTests.DrawBufferCase('draw_buffer', 'DRAW_BUFFER'));
+
+
+ // Integer64
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} targetName
+ * @param {number} minValue
+ */
+ var LimitedStateInteger64 = function(name, description, targetName, minValue) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {number} */ this.targetName = targetName;
+ /** @type {number} */ this.minValue = minValue;
+
+ };
+
+ /** @type {Array<LimitedStateInteger64>} */ var implementationLimits = [
+ new LimitedStateInteger64('max_element_index', 'MAX_ELEMENT_INDEX', gl.MAX_ELEMENT_INDEX, 0x00FFFFFF),
+ new LimitedStateInteger64('max_server_wait_timeout', 'MAX_SERVER_WAIT_TIMEOUT', gl.MAX_SERVER_WAIT_TIMEOUT, 0),
+ new LimitedStateInteger64('max_uniform_block_size', 'MAX_UNIFORM_BLOCK_SIZE', gl.MAX_UNIFORM_BLOCK_SIZE, 16384)
+ ];
+
+ for (var testNdx = 0; testNdx < implementationLimits.length; testNdx++)
+ this.addChild(new es3fIntegerStateQueryTests.ConstantMinimumValue64TestCase(implementationLimits[testNdx].name, implementationLimits[testNdx].description, implementationLimits[testNdx].targetName, implementationLimits[testNdx].minValue));
+
+ this.addChild(new es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase('max_combined_vertex_uniform_components', 'MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS', gl.MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, gl.MAX_VERTEX_UNIFORM_BLOCKS, gl.MAX_VERTEX_UNIFORM_COMPONENTS));
+ this.addChild(new es3fIntegerStateQueryTests.MaxCombinedStageUniformComponentsCase('max_combined_fragment_uniform_components', 'MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS', gl.MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, gl.MAX_FRAGMENT_UNIFORM_BLOCKS, gl.MAX_FRAGMENT_UNIFORM_COMPONENTS));
+
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fIntegerStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fIntegerStateQueryTests.IntegerStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fIntegerStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInternalFormatQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInternalFormatQueryTests.js
new file mode 100644
index 0000000000..8eb1b0e2c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fInternalFormatQueryTests.js
@@ -0,0 +1,173 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fInternalFormatQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fInternalFormatQueryTests = functional.gles3.es3fInternalFormatQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} internalFormat
+ * @param {boolean} isIntegerInternalFormat
+ */
+es3fInternalFormatQueryTests.SamplesCase = function(name, description, internalFormat, isIntegerInternalFormat) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_internalFormat = internalFormat;
+ this.m_isIntegerInternalFormat = isIntegerInternalFormat;
+};
+
+setParentClass(es3fInternalFormatQueryTests.SamplesCase, es3fApiCase.ApiCase);
+
+es3fInternalFormatQueryTests.SamplesCase.prototype.test = function() {
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, this.m_internalFormat, gl.SAMPLES);
+
+ this.check(!this.m_isIntegerInternalFormat || samples.length == 0, 'integer internal format should have 0 samples, got ' + samples.length);
+
+ if (samples.length == 0)
+ return;
+
+ var prevSampleCount = 0;
+ var sampleCount = 0;
+ for (var ndx = 0; ndx < samples.length; ++ndx, prevSampleCount = sampleCount) {
+ sampleCount = samples[ndx];
+
+ // sample count must be > 0
+ this.check(sampleCount > 0, 'Expected sample count to be at least one; got ' + sampleCount);
+
+ // samples must be ordered descending
+ this.check(ndx == 0 || sampleCount < prevSampleCount, 'Expected sample count to be ordered in descending order; got ' + prevSampleCount + ' at index ' + (ndx - 1) + ', and ' + sampleCount + ' at index ' + ndx);
+ }
+
+ // the maximum value in SAMPLES is guaranteed to be at least the value of MAX_SAMPLES
+ var maxSamples = /** @type {number} */ (gl.getParameter(gl.MAX_SAMPLES));
+ var maximumFormatSampleCount = samples[0];
+ this.check(maximumFormatSampleCount >= maxSamples, 'Expected maximum value in SAMPLES (' + maximumFormatSampleCount + ') to be at least the value of MAX_SAMPLES (' + maxSamples + ')');
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fInternalFormatQueryTests.InternalFormatQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'internal_format', 'Internal Format Query tests');
+};
+
+es3fInternalFormatQueryTests.InternalFormatQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fInternalFormatQueryTests.InternalFormatQueryTests.prototype.constructor = es3fInternalFormatQueryTests.InternalFormatQueryTests;
+
+es3fInternalFormatQueryTests.InternalFormatQueryTests.prototype.init = function() {
+ var internalFormats = [
+ //name, format, is_integer
+ // color renderable and unsized
+ // \note These unsized formats seem to allowed by the spec, but they are not useful in any way. (You can't create a renderbuffer with such internalFormat)
+ ['rgba', gl.RGBA, false],
+ ['rgb', gl.RGB, false],
+
+ // color renderable
+ ['r8', gl.R8, false],
+ ['rg8', gl.RG8, false],
+ ['rgb8', gl.RGB8, false],
+ ['rgb565', gl.RGB565, false],
+ ['rgba4', gl.RGBA4, false],
+ ['rgb5_a1', gl.RGB5_A1, false],
+ ['rgba8', gl.RGBA8, false],
+ ['rgb10_a2', gl.RGB10_A2, false],
+ ['rgb10_a2ui', gl.RGB10_A2UI, true],
+ ['srgb8_alpha8', gl.SRGB8_ALPHA8, false],
+ ['r8i', gl.R8I, true],
+ ['r8ui', gl.R8UI, true],
+ ['r16i', gl.R16I, true],
+ ['r16ui', gl.R16UI, true],
+ ['r32i', gl.R32I, true],
+ ['r32ui', gl.R32UI, true],
+ ['rg8i', gl.RG8I, true],
+ ['rg8ui', gl.RG8UI, true],
+ ['rg16i', gl.RG16I, true],
+ ['rg16ui', gl.RG16UI, true],
+ ['rg32i', gl.RG32I, true],
+ ['rg32ui', gl.RG32UI, true],
+ ['rgba8i', gl.RGBA8I, true],
+ ['rgba8ui', gl.RGBA8UI, true],
+ ['rgba16i', gl.RGBA16I, true],
+ ['rgba16ui', gl.RGBA16UI, true],
+ ['rgba32i', gl.RGBA32I, true],
+ ['rgba32ui', gl.RGBA32UI, true],
+
+ // depth renderable
+ ['depth_component16', gl.DEPTH_COMPONENT16, false],
+ ['depth_component24', gl.DEPTH_COMPONENT24, false],
+ ['depth_component32f', gl.DEPTH_COMPONENT32F, false],
+ ['depth24_stencil8', gl.DEPTH24_STENCIL8, false],
+ ['depth32f_stencil8', gl.DEPTH32F_STENCIL8, false],
+
+ // stencil renderable
+ ['stencil_index8', gl.STENCIL_INDEX8, false]
+ // DEPTH24_STENCIL8, duplicate
+ // DEPTH32F_STENCIL8 duplicate
+ ];
+
+ for (var ndx = 0; ndx < internalFormats.length; ++ndx) {
+ var internalFormat = internalFormats[ndx];
+
+ this.addChild(new es3fInternalFormatQueryTests.SamplesCase(internalFormat[0] + '_samples', 'SAMPLES and NUM_SAMPLE_COUNTS', internalFormat[1], internalFormat[2]));
+ }
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fInternalFormatQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fInternalFormatQueryTests.InternalFormatQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fInternalFormatQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fLifetimeTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fLifetimeTests.js
new file mode 100644
index 0000000000..b179022bfd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fLifetimeTests.js
@@ -0,0 +1,471 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fLifetimeTests');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('modules.shared.glsLifetimeTests');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+var es3fLifetimeTests = functional.gles3.es3fLifetimeTests;
+var glsLifetimeTests = modules.shared.glsLifetimeTests;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuSurface = framework.common.tcuSurface;
+var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+var tcuTestCase = framework.common.tcuTestCase;
+
+/** @const */ var VIEWPORT_SIZE = 128;
+/** @const */ var NUM_COMPONENTS = 4;
+/** @const */ var NUM_VERTICES = 3;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {gluShaderProgram.ShaderProgram}
+ */
+es3fLifetimeTests.ScaleProgram = function() {
+ gluShaderProgram.ShaderProgram.call(this, gl, this.getSources());
+ assertMsgOptions(this.isOk(), 'Program creation failed', false, true);
+ this.m_scaleLoc = gl.getUniformLocation(this.getProgram(), 'scale');
+ this.m_posLoc = gl.getAttribLocation(this.getProgram(), 'pos');
+};
+
+setParentClass(es3fLifetimeTests.ScaleProgram, gluShaderProgram.ShaderProgram);
+
+/**
+ * @param {WebGLVertexArrayObject} vao
+ * @param {number} scale
+ * @param {boolean} tf
+ * @param {tcuSurface.Surface} dst
+ */
+es3fLifetimeTests.ScaleProgram.prototype.draw = function(vao, scale, tf, dst) {
+ es3fLifetimeTests.ScaleProgram.seed = es3fLifetimeTests.ScaleProgram.seed || 0;
+ ++es3fLifetimeTests.ScaleProgram.seed;
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_SIZE, VIEWPORT_SIZE, es3fLifetimeTests.ScaleProgram.seed);
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.bindVertexArray(vao);
+ gl.enableVertexAttribArray(this.m_posLoc);
+ gl.useProgram(this.getProgram());
+
+ gl.uniform1f(this.m_scaleLoc, scale);
+
+ if (tf)
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ if (tf)
+ gl.endTransformFeedback();
+
+ if (dst)
+ glsLifetimeTests.readRectangle(viewport, dst);
+
+ gl.bindVertexArray(null);
+
+};
+
+/**
+ * @param {WebGLBuffer} buffer
+ * @param {WebGLVertexArrayObject} vao
+ */
+es3fLifetimeTests.ScaleProgram.prototype.setPos = function(buffer, vao) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bindVertexArray(vao);
+ gl.vertexAttribPointer(this.m_posLoc, NUM_COMPONENTS, gl.FLOAT, false, 0, 0);
+ gl.bindVertexArray(null);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+};
+
+/**
+ * @private
+ */
+es3fLifetimeTests.ScaleProgram.prototype.getSources = function() {
+/** @const */ var s_vertexShaderSrc =
+ '#version 100\n' +
+ 'attribute vec4 pos;\n' +
+ 'uniform float scale;\n' +
+ 'void main ()\n' +
+ '{\n' +
+ ' gl_Position = vec4(scale * pos.xy, pos.zw);\n' +
+ '}';
+
+/** @const */ var s_fragmentShaderSrc =
+ '#version 100\n' +
+ 'void main ()\n' +
+ '{\n' +
+ ' gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\n' +
+ '}';
+ var sources = new gluShaderProgram.ProgramSources();
+ sources.add(new gluShaderProgram.VertexSource(s_vertexShaderSrc));
+ sources.add(new gluShaderProgram.FragmentSource(s_fragmentShaderSrc));
+ sources.add(new gluShaderProgram.TransformFeedbackMode(gl.INTERLEAVED_ATTRIBS));
+ sources.add(new gluShaderProgram.TransformFeedbackVarying('gl_Position'));
+ return sources;
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.SimpleBinder}
+ */
+es3fLifetimeTests.VertexArrayBinder = function() {
+ glsLifetimeTests.SimpleBinder.call(this, null, gl.NONE, gl.VERTEX_ARRAY_BINDING);
+};
+
+setParentClass(es3fLifetimeTests.VertexArrayBinder, glsLifetimeTests.SimpleBinder);
+
+es3fLifetimeTests.VertexArrayBinder.prototype.bind = function(obj) {
+ var vao = /** @type {WebGLVertexArrayObject} */ (obj);
+ gl.bindVertexArray(vao);
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Binder}
+ */
+es3fLifetimeTests.SamplerBinder = function() {
+ glsLifetimeTests.Binder.call(this);
+};
+
+setParentClass(es3fLifetimeTests.SamplerBinder, glsLifetimeTests.Binder);
+
+es3fLifetimeTests.SamplerBinder.prototype.bind = function(obj) {
+ var sampler = /** @type {WebGLSampler} */ (obj);
+ gl.bindSampler(0, sampler);
+};
+es3fLifetimeTests.SamplerBinder.prototype.getBinding = function() { return /** @type {WebGLSampler} */ (gl.getParameter(gl.SAMPLER_BINDING)); };
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Binder}
+ */
+es3fLifetimeTests.QueryBinder = function() {
+ glsLifetimeTests.Binder.call(this);
+};
+
+setParentClass(es3fLifetimeTests.QueryBinder, glsLifetimeTests.Binder);
+
+es3fLifetimeTests.QueryBinder.prototype.bind = function(obj) {
+ var query = /** @type {WebGLQuery} */ (obj);
+ if (query)
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, query);
+ else
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+};
+
+es3fLifetimeTests.QueryBinder.prototype.getBinding = function() { return null; };
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Attacher}
+ * @param {glsLifetimeTests.Type} elementType
+ * @param {glsLifetimeTests.Type} varrType
+ * @param {es3fLifetimeTests.ScaleProgram} program
+ */
+es3fLifetimeTests.BufferVAOAttacher = function(elementType, varrType, program) {
+ glsLifetimeTests.Attacher.call(this, elementType, varrType);
+ this.m_program = program;
+};
+
+setParentClass(es3fLifetimeTests.BufferVAOAttacher, glsLifetimeTests.Attacher);
+
+/**
+ * @return {es3fLifetimeTests.ScaleProgram}
+ */
+es3fLifetimeTests.BufferVAOAttacher.prototype.getProgram = function() { return this.m_program; };
+
+/**
+ * @param {number} seed
+ * @param {number} usage
+ * @param {WebGLBuffer} buffer
+ */
+es3fLifetimeTests.initBuffer = function(seed, usage, buffer) {
+ /** @const */ var s_varrData = [
+ -1.0, 0.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 0.0, -1.0, 0.0, 1.0
+ ];
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ if (seed == 0)
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(s_varrData), usage);
+ else {
+ var rnd = new deRandom.Random(seed);
+ var data = [];
+
+ for (var ndx = 0; ndx < NUM_VERTICES; ndx++) {
+ data.push(2 * (rnd.getFloat() - 0.5));
+ data.push(2 * (rnd.getFloat() - 0.5));
+ data.push(0);
+ data.push(1);
+ }
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), usage);
+ }
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+};
+
+es3fLifetimeTests.BufferVAOAttacher.prototype.initAttachment = function(seed, obj) {
+ var buffer = /** @type {WebGLBuffer} */ (obj);
+ es3fLifetimeTests.initBuffer(seed, gl.STATIC_DRAW, buffer);
+ bufferedLogToConsole('Initialized buffer ' + buffer + ' from seed ' + seed);
+};
+
+es3fLifetimeTests.BufferVAOAttacher.prototype.attach = function(element, target) {
+ var buffer = /** @type {WebGLBuffer} */ (element);
+ var vao = /** @type {WebGLVertexArrayObject} */ (target);
+
+ this.m_program.setPos(buffer, vao);
+ bufferedLogToConsole('Set the `pos` attribute in VAO ' + vao + ' to buffer ' + buffer);
+};
+
+es3fLifetimeTests.BufferVAOAttacher.prototype.detach = function(element, target) {
+ var vao = /** @type {WebGLVertexArrayObject} */ (target);
+ this.attach(null, vao);
+};
+
+es3fLifetimeTests.BufferVAOAttacher.prototype.getAttachment = function(target) {
+ var vao = /** @type {WebGLVertexArrayObject} */ (target);
+ gl.bindVertexArray(vao);
+ var name = gl.getVertexAttrib(this.m_posLoc, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ gl.bindVertexArray(null);
+ return name;
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.InputAttacher}
+ * @param {es3fLifetimeTests.BufferVAOAttacher} attacher
+ */
+es3fLifetimeTests.BufferVAOInputAttacher = function(attacher) {
+ glsLifetimeTests.InputAttacher.call(this, attacher);
+ this.m_program = attacher.getProgram();
+};
+
+setParentClass(es3fLifetimeTests.BufferVAOInputAttacher, glsLifetimeTests.InputAttacher);
+
+es3fLifetimeTests.BufferVAOInputAttacher.prototype.drawContainer = function(obj, dst) {
+ var vao = /** @type {WebGLVertexArrayObject} */ (obj);
+ this.m_program.draw(vao, 1.0, false, dst);
+ bufferedLogToConsole('Drew an output image with VAO ' + vao);
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Attacher}
+ * @param {glsLifetimeTests.Type} elementType
+ * @param {glsLifetimeTests.Type} tfType
+*/
+es3fLifetimeTests.BufferTfAttacher = function(elementType, tfType) {
+ glsLifetimeTests.Attacher.call(this, elementType, tfType);
+};
+
+setParentClass(es3fLifetimeTests.BufferTfAttacher, glsLifetimeTests.Attacher);
+
+es3fLifetimeTests.BufferTfAttacher.prototype.initAttachment = function(seed, obj) {
+ var buffer = /** @type {WebGLBuffer} */ (obj);
+ es3fLifetimeTests.initBuffer(seed, gl.DYNAMIC_READ, buffer);
+ bufferedLogToConsole('Initialized buffer ' + buffer + ' from seed ' + seed);
+};
+
+es3fLifetimeTests.BufferTfAttacher.prototype.attach = function(element, target) {
+ var buffer = /** @type {WebGLBuffer} */ (element);
+ var tf = /** @type {WebGLTransformFeedback} */ (target);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+};
+
+es3fLifetimeTests.BufferTfAttacher.prototype.detach = function(element, target) {
+ var buffer = /** @type {WebGLBuffer} */ (element);
+ var tf = /** @type {WebGLTransformFeedback} */ (target);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+
+};
+
+es3fLifetimeTests.BufferTfAttacher.prototype.getAttachment = function(target) {
+ var tf = /** @type {WebGLTransformFeedback} */ (target);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ var name = gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ return name;
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.OutputAttacher}
+ */
+es3fLifetimeTests.BufferTfOutputAttacher = function(attacher, program) {
+ glsLifetimeTests.OutputAttacher.call(this, attacher);
+ this.m_program = program;
+};
+
+setParentClass(es3fLifetimeTests.BufferTfOutputAttacher, glsLifetimeTests.OutputAttacher);
+
+es3fLifetimeTests.BufferTfOutputAttacher.prototype.setupContainer = function(seed, obj) {
+ var tf = /** @type {WebGLTransformFeedback} */ (obj);
+ var posBuf = gl.createBuffer();
+ var vao = gl.createVertexArray();
+
+ es3fLifetimeTests.initBuffer(seed, gl.STATIC_DRAW, posBuf);
+ this.m_program.setPos(posBuf, vao);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ this.m_program.draw(vao, -1.0, true, null);
+ bufferedLogToConsole('Drew an image with seed ' + seed + ' with transform feedback to ' + tf);
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.deleteVertexArray(vao);
+ gl.deleteBuffer(posBuf);
+};
+
+es3fLifetimeTests.BufferTfOutputAttacher.prototype.drawAttachment = function(buffer, dst) {
+ var vao = gl.createVertexArray();
+
+ this.m_program.setPos(buffer, vao);
+ this.m_program.draw(vao, 1.0, false, dst);
+ bufferedLogToConsole('Drew output image with vertices from buffer ' + buffer);
+ gl.deleteVertexArray(vao);
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.ES2Types}
+ */
+es3fLifetimeTests.ES3Types = function() {
+ glsLifetimeTests.ES2Types.call(this);
+ this.m_program = new es3fLifetimeTests.ScaleProgram();
+ this.m_queryBind = new es3fLifetimeTests.QueryBinder();
+ this.m_queryType = new glsLifetimeTests.SimpleType('query', gl.createQuery, gl.deleteQuery, gl.isQuery, this.m_queryBind);
+ this.m_tfBind = new glsLifetimeTests.SimpleBinder(gl.bindTransformFeedback, gl.TRANSFORM_FEEDBACK,
+ gl.TRANSFORM_FEEDBACK_BINDING);
+ this.m_tfType = new glsLifetimeTests.SimpleType('transform_feedback', gl.createTransformFeedback, gl.deleteTransformFeedback, gl.isTransformFeedback, this.m_tfBind);
+ this.m_varrBind = new es3fLifetimeTests.VertexArrayBinder();
+ this.m_varrType = new glsLifetimeTests.SimpleType('vertex_array', gl.createVertexArray, gl.deleteVertexArray, gl.isVertexArray, this.m_varrBind);
+ this.m_samplerBind = new es3fLifetimeTests.SamplerBinder();
+ this.m_samplerType = new glsLifetimeTests.SimpleType('sampler', gl.createSampler, gl.deleteSampler, gl.isSampler, this.m_samplerBind, true);
+ this.m_bufVarrAtt = new es3fLifetimeTests.BufferVAOAttacher(this.m_bufferType, this.m_varrType, this.m_program);
+ this.m_bufVarrInAtt = new es3fLifetimeTests.BufferVAOInputAttacher(this.m_bufVarrAtt);
+ this.m_bufTfAtt = new es3fLifetimeTests.BufferTfAttacher(this.m_bufferType, this.m_tfType);
+ this.m_bufTfOutAtt = new es3fLifetimeTests.BufferTfOutputAttacher(this.m_bufTfAtt, this.m_program);
+
+ this.m_types.push(this.m_queryType, this.m_tfType, this.m_varrType, this.m_samplerType);
+ this.m_attachers.push(this.m_bufVarrAtt, this.m_bufTfAtt);
+ this.m_inAttachers.push(this.m_bufVarrInAtt);
+ this.m_outAttachers.push(this.m_bufTfOutAtt);
+};
+
+setParentClass(es3fLifetimeTests.ES3Types, glsLifetimeTests.ES2Types);
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fLifetimeTests.TfDeleteActiveTest = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+};
+
+setParentClass(es3fLifetimeTests.TfDeleteActiveTest, tcuTestCase.DeqpTest);
+
+es3fLifetimeTests.TfDeleteActiveTest.prototype.iterate = function() {
+/** @const */ var s_xfbVertexSource =
+ '#version 300 es\n' +
+ 'void main ()\n' +
+ '{\n' +
+ ' gl_Position = vec4(float(gl_VertexID) / 2.0, float(gl_VertexID % 2) / 2.0, 0.0, 1.0);\n' +
+ '}\n';
+
+/** @const */ var s_xfbFragmentSource =
+ '#version 300 es\n' +
+ 'layout(location=0) out mediump vec4 dEQP_FragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' dEQP_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n' +
+ '}\n';
+ var buf = gl.createBuffer();
+
+ var sources = new gluShaderProgram.ProgramSources();
+ sources.add(new gluShaderProgram.VertexSource(s_xfbVertexSource));
+ sources.add(new gluShaderProgram.FragmentSource(s_xfbFragmentSource));
+ sources.add(new gluShaderProgram.TransformFeedbackMode(gl.SEPARATE_ATTRIBS));
+ sources.add(new gluShaderProgram.TransformFeedbackVarying('gl_Position'));
+ var program = new gluShaderProgram.ShaderProgram(gl, sources);
+ if (!program.isOk()) {
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+ testFailedOptions('failed to build program', true);
+ }
+ gl.useProgram(program.getProgram());
+
+ var tf = gl.createTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 48, gl.STATIC_DRAW);
+
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ var errCode = gl.NONE;
+ gl.deleteTransformFeedback(tf);
+ errCode = gl.getError();
+ assertMsgOptions(errCode == gl.INVALID_OPERATION,
+ 'Deleting active transform feedback must produce INVALID_OPERATION', false, true);
+ gl.endTransformFeedback();
+ gl.deleteTransformFeedback(tf);
+ testPassed();
+ return tcuTestCase.IterateResult.STOP;
+};
+
+es3fLifetimeTests.genTestCases = function() {
+ var state = tcuTestCase.runner;
+ state.setRoot(tcuTestCase.newTest('lifetime', 'Top level'));
+
+ var types = new es3fLifetimeTests.ES3Types();
+ glsLifetimeTests.addTestCases(state.testCases, types);
+ /* TODO: Add TfDeleteActiveTest test */
+ var deleteActiveGroup = tcuTestCase.newTest('delete_active', 'Delete active object');
+ state.testCases.addChild(deleteActiveGroup);
+ deleteActiveGroup.addChild(
+ new es3fLifetimeTests.TfDeleteActiveTest('transform_feedback', 'Transform Feedback'));
+};
+
+/**
+ * Create and execute the test cases
+ */
+es3fLifetimeTests.run = function(context) {
+ gl = context;
+ try {
+ es3fLifetimeTests.genTestCases();
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fMultisampleTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fMultisampleTests.js
new file mode 100644
index 0000000000..47e6267d35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fMultisampleTests.js
@@ -0,0 +1,1744 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fMultisampleTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluStrUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+ /** @type {?WebGL2RenderingContext} */ var gl;
+ var es3fMultisampleTests = functional.gles3.es3fMultisampleTests;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuTexture = framework.common.tcuTexture;
+ var gluStrUtil = framework.opengl.gluStrUtil;
+ var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var tcuLogImage = framework.common.tcuLogImage;
+
+ /**
+ * @constructor
+ * @struct
+ * @param {Array<number>} p0_
+ * @param {Array<number>} p1_
+ * @param {Array<number>} p2_
+ * @param {Array<number>} p3_
+ */
+ es3fMultisampleTests.QuadCorners = function(p0_, p1_, p2_, p3_) {
+ /** @type {Array<number>} */ this.p0 = p0_;
+ /** @type {Array<number>} */ this.p1 = p1_;
+ /** @type {Array<number>} */ this.p2 = p2_;
+ /** @type {Array<number>} */ this.p3 = p3_;
+ };
+
+ /**
+ * @param {number} defaultCount
+ * @return {number}
+ */
+ es3fMultisampleTests.getIterationCount = function(defaultCount) {
+ // The C++ test takes an argument from the command line.
+ // Leaving this function in case we want to be able to take an argument from the URL
+ return defaultCount;
+ };
+
+ /**
+ * @param {Array<number>} point
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} p3
+ * @return {boolean}
+ */
+ es3fMultisampleTests.isInsideQuad = function(point, p0, p1, p2, p3) {
+ /** @type {number} */ var dot0 = (point[0] - p0[0]) * (p1[1] - p0[1]) + (point[1] - p0[1]) * (p0[0] - p1[0]);
+ /** @type {number} */ var dot1 = (point[0] - p1[0]) * (p2[1] - p1[1]) + (point[1] - p1[1]) * (p1[0] - p2[0]);
+ /** @type {number} */ var dot2 = (point[0] - p2[0]) * (p3[1] - p2[1]) + (point[1] - p2[1]) * (p2[0] - p3[0]);
+ /** @type {number} */ var dot3 = (point[0] - p3[0]) * (p0[1] - p3[1]) + (point[1] - p3[1]) * (p3[0] - p0[0]);
+
+ return (dot0 > 0) == (dot1 > 0) && (dot1 > 0) == (dot2 > 0) && (dot2 > 0) == (dot3 > 0);
+ };
+
+ /**
+ * Check if a region in an image is unicolored.
+ *
+ * Checks if the pixels in img inside the convex quadilateral defined by
+ * p0, p1, p2 and p3 are all (approximately) of the same color.
+ *
+ * @param {tcuSurface.Surface} img
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} p3
+ * @return {boolean}
+ */
+ es3fMultisampleTests.isPixelRegionUnicolored = function(img, p0, p1, p2, p3) {
+ /** @type {number} */ var xMin = deMath.clamp(Math.min(p0[0], p1[0], p2[0], p3[0]), 0, img.getWidth() - 1);
+ /** @type {number} */ var yMin = deMath.clamp(Math.min(p0[1], p1[1], p2[1], p3[1]), 0, img.getHeight() - 1);
+ /** @type {number} */ var xMax = deMath.clamp(Math.max(p0[0], p1[0], p2[0], p3[0]), 0, img.getWidth() - 1);
+ /** @type {number} */ var yMax = deMath.clamp(Math.max(p0[1], p1[1], p2[1], p3[1]), 0, img.getHeight() - 1);
+ /** @type {boolean} */ var insideEncountered = false; //!< Whether we have already seen at least one pixel inside the region.
+ /** @type {tcuRGBA.RGBA} */ var insideColor; //!< Color of the first pixel inside the region.
+ /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.newRGBAComponents(3, 3, 3, 3);
+ for (var y = yMin; y <= yMax; y++)
+ for (var x = xMin; x <= xMax; x++)
+ if (es3fMultisampleTests.isInsideQuad([x, y], p0, p1, p2, p3)) {
+ /** @type {tcuRGBA.RGBA} */ var pixColor = new tcuRGBA.RGBA(img.getPixel(x, y));
+
+ if (insideEncountered)
+ if (!tcuRGBA.compareThreshold(pixColor, insideColor, threshold)) // Pixel color differs from already-detected color inside same region - region not unicolored.
+ return false;
+ else {
+ insideEncountered = true;
+ insideColor = pixColor;
+ }
+ }
+ return true;
+ };
+
+ /**
+ * [drawUnicolorTestErrors description]
+ * @param {tcuSurface.Surface} img
+ * @param {tcuTexture.PixelBufferAccess} errorImg
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} p3
+ * @return {boolean}
+ */
+ es3fMultisampleTests.drawUnicolorTestErrors = function(img, errorImg, p0, p1, p2, p3) {
+ /** @type {number} */ var xMin = deMath.clamp(Math.min(p0[0], p1[0], p2[0], p3[0]), 0, img.getWidth() - 1);
+ /** @type {number} */ var yMin = deMath.clamp(Math.min(p0[1], p1[1], p2[1], p3[1]), 0, img.getHeight() - 1);
+ /** @type {number} */ var xMax = deMath.clamp(Math.max(p0[0], p1[0], p2[0], p3[0]), 0, img.getWidth() - 1);
+ /** @type {number} */ var yMax = deMath.clamp(Math.max(p0[1], p1[1], p2[1], p3[1]), 0, img.getHeight() - 1);
+ /** @type {tcuRGBA.RGBA} */ var refColor = new tcuRGBA.RGBA(img.getPixel(Math.floor((xMin + xMax) / 2), Math.floor((yMin + yMax) / 2)));
+ /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.newRGBAComponents(3, 3, 3, 3);
+ for (var y = yMin; y <= yMax; y++)
+ for (var x = xMin; x <= xMax; x++)
+ if (es3fMultisampleTests.isInsideQuad([x, y], p0, p1, p2, p3)) {
+ if (!tcuRGBA.compareThreshold(new tcuRGBA.RGBA(img.getPixel(x, y)), refColor, threshold)) {
+ img.setPixel(x, y, tcuRGBA.RGBA.red.toVec()); // TODO: this might also be toIVec()
+ errorImg.setPixel([1.0, 0.0, 0.0, 1.0], x, y);
+ }
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @struct
+ * @param {number=} numSamples_
+ * @param {boolean=} useDepth_
+ * @param {boolean=} useStencil_
+ */
+ es3fMultisampleTests.FboParams = function(numSamples_, useDepth_, useStencil_) {
+ /** @type {boolean} */ var useFbo_ = true;
+ if (numSamples_ === undefined && useDepth_ === undefined && useStencil_ === undefined)
+ useFbo_ = false;
+ /** @type {boolean} */ this.useFbo = useFbo_;
+ /** @type {number} */ this.numSamples = numSamples_ === undefined ? -1 : numSamples_;
+ /** @type {boolean} */ this.useDepth = useDepth_ === undefined ? false : useDepth_;
+ /** @type {boolean} */ this.useStencil = useStencil_ === undefined ? false : useStencil_;
+
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} desiredViewportSize
+ * @param {es3fMultisampleTests.FboParams} fboParams
+ */
+ es3fMultisampleTests.MultisampleCase = function(name, desc, desiredViewportSize, fboParams) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /** @type {number} */ this.m_numSamples = 0;
+ /** @type {number} */ this.m_viewportSize = 0;
+ /** @type {number} */ this.m_desiredViewportSize = desiredViewportSize;
+ /** @type {es3fMultisampleTests.FboParams} */ this.m_fboParams = fboParams;
+ /** @type {WebGLRenderbuffer} */ this.m_msColorRbo = null;
+ /** @type {WebGLRenderbuffer} */ this.m_msDepthStencilRbo = null;
+ /** @type {WebGLRenderbuffer} */ this.m_resolveColorRbo = null;
+ /** @type {WebGLFramebuffer} */ this.m_msFbo = null;
+ /** @type {WebGLFramebuffer} */ this.m_resolveFbo = null;
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {number} */ this.m_attrPositionLoc = -1;
+ /** @type {number} */ this.m_attrColorLoc = -1;
+ /** @type {number} */ this.m_renderWidth = fboParams.useFbo ? 2 * desiredViewportSize : gl.drawingBufferWidth;
+ /** @type {number} */ this.m_renderHeight = fboParams.useFbo ? 2 * desiredViewportSize : gl.drawingBufferHeight;
+ /** @type {number} */ this.m_viewportX = 0;
+ /** @type {number} */ this.m_viewportY = 0;
+ /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
+ if (this.m_fboParams.useFbo)
+ assertMsgOptions(this.m_fboParams.numSamples >= 0, 'fboParams.numSamples < 0', false, true);
+ };
+
+ es3fMultisampleTests.MultisampleCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.MultisampleCase.prototype.constructor = es3fMultisampleTests.MultisampleCase;
+
+ /* Rest states */
+ es3fMultisampleTests.MultisampleCase.prototype.deinit = function() {
+ gl.colorMask(true, true, true, true);
+ gl.depthMask(true);
+
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clearDepth(1.0);
+ gl.clearStencil(0);
+
+ gl.disable(gl.STENCIL_TEST);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND)
+ gl.disable(gl.SAMPLE_COVERAGE);
+ gl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);
+
+ if (this.m_program) {
+ gl.deleteProgram(this.m_program.getProgram());
+ this.m_program = null;
+ }
+ if (this.m_msColorRbo) {
+ gl.deleteRenderbuffer(this.m_msColorRbo);
+ this.m_msColorRbo = null;
+ }
+ if (this.m_msDepthStencilRbo) {
+ gl.deleteRenderbuffer(this.m_msDepthStencilRbo);
+ this.m_msDepthStencilRbo = null;
+ }
+ if (this.m_resolveColorRbo) {
+ gl.deleteRenderbuffer(this.m_resolveColorRbo);
+ this.m_resolveColorRbo = null;
+ }
+
+ if (this.m_msFbo) {
+ gl.deleteFramebuffer(this.m_msFbo);
+ this.m_msFbo = null;
+ }
+ if (this.m_resolveFbo) {
+ gl.deleteFramebuffer(this.m_resolveFbo);
+ this.m_resolveFbo = null;
+ }
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ }
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} c0
+ * @param {Array<number>} c1
+ * @param {Array<number>} c2
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderTriangle_pAsVec3cAsVec4 = function(p0, p1, p2, c0, c1, c2) {
+ /** @type {Array<number>} */ var vertexPositions = [
+ p0[0], p0[1], p0[2], 1.0,
+ p1[0], p1[1], p1[2], 1.0,
+ p2[0], p2[1], p2[2], 1.0
+ ];
+ /** @type {Array<number>} */ var vertexColors = [
+ c0[0], c0[1], c0[2], c0[3],
+ c1[0], c1[1], c1[2], c1[3],
+ c2[0], c2[1], c2[2], c2[3]
+ ];
+
+ var posGLBuffer = gl.createBuffer();
+ /** @type {ArrayBufferView} */ var posBuffer = new Float32Array(vertexPositions);
+ gl.bindBuffer(gl.ARRAY_BUFFER, posGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, posBuffer, gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(this.m_attrPositionLoc);
+ gl.vertexAttribPointer(this.m_attrPositionLoc, 4, gl.FLOAT, false, 0, 0);
+
+ var colGLBuffer = gl.createBuffer();
+ /** @type {ArrayBufferView} */ var colBuffer = new Float32Array(vertexColors);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colBuffer, gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(this.m_attrColorLoc);
+ gl.vertexAttribPointer(this.m_attrColorLoc, 4, gl.FLOAT, false, 0, 0);
+
+ gl.useProgram(this.m_program.getProgram());
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(colGLBuffer);
+ gl.deleteBuffer(posGLBuffer);
+ };
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} color
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderTriangle_pAsVec3WithColor = function(p0, p1, p2, color) {
+ this.renderTriangle_pAsVec3cAsVec4(p0, p1, p2, color, color, color);
+ };
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} c0
+ * @param {Array<number>} c1
+ * @param {Array<number>} c2
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderTriangle_pAsVec2 = function(p0, p1, p2, c0, c1, c2) {
+ this.renderTriangle_pAsVec3cAsVec4(
+ [p0[0], p0[1], 0.0],
+ [p1[0], p1[1], 0.0],
+ [p2[0], p2[1], 0.0],
+ c0, c1, c2);
+ };
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} color
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderTriangle_pAsVec2WithColor = function(p0, p1, p2, color) {
+ this.renderTriangle_pAsVec2(p0, p1, p2, color, color, color);
+ };
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} p3
+ * @param {Array<number>} c0
+ * @param {Array<number>} c1
+ * @param {Array<number>} c2
+ * @param {Array<number>} c3
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderQuad = function(p0, p1, p2, p3, c0, c1, c2, c3) {
+ this.renderTriangle_pAsVec2(p0, p1, p2, c0, c1, c2);
+ this.renderTriangle_pAsVec2(p2, p1, p3, c2, c1, c3);
+ };
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} p2
+ * @param {Array<number>} p3
+ * @param {Array<number>} color
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderQuad_WithColor = function(p0, p1, p2, p3, color) {
+ this.renderQuad(p0, p1, p2, p3, color, color, color, color);
+ };
+
+ /**
+ * @protected
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} color
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.renderLine = function(p0, p1, color) {
+ /** @type {Array<number>} */ var vertexPositions = [
+ p0[0], p0[1], 0.0, 1.0,
+ p1[0], p1[1], 0.0, 1.0
+ ];
+ /** @type {Array<number>} */ var vertexColors = [
+ color[0], color[1], color[2], color[3],
+ color[0], color[1], color[2], color[3]
+ ];
+
+ var posGLBuffer = gl.createBuffer();
+ /** @type {ArrayBufferView} */ var posBuffer = new Float32Array(vertexPositions);
+ gl.bindBuffer(gl.ARRAY_BUFFER, posGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, posBuffer, gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(this.m_attrPositionLoc);
+ gl.vertexAttribPointer(this.m_attrPositionLoc, 4, gl.FLOAT, false, 0, 0);
+
+ var colGLBuffer = gl.createBuffer();
+ /** @type {ArrayBufferView} */ var colBuffer = new Float32Array(vertexColors);
+ gl.bindBuffer(gl.ARRAY_BUFFER, colGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colBuffer, gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(this.m_attrColorLoc);
+ gl.vertexAttribPointer(this.m_attrColorLoc, 4, gl.FLOAT, false, 0, 0);
+
+ gl.useProgram(this.m_program.getProgram());
+ gl.drawArrays(gl.LINES, 0, 2);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(colGLBuffer);
+ gl.deleteBuffer(posGLBuffer);
+ };
+
+ /**
+ * @protected
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.randomizeViewport = function() {
+ this.m_viewportX = this.m_rnd.getInt(0, this.m_renderWidth - this.m_viewportSize);
+ this.m_viewportY = this.m_rnd.getInt(0, this.m_renderHeight - this.m_viewportSize);
+
+ gl.viewport(this.m_viewportX, this.m_viewportY, this.m_viewportSize, this.m_viewportSize);
+ };
+
+ /**
+ * @protected
+ * @return {tcuSurface.Surface}
+ */
+ es3fMultisampleTests.MultisampleCase.prototype.readImage = function() {
+ /** @type {tcuSurface.Surface} */
+ var dst = new tcuSurface.Surface(this.m_viewportSize, this.m_viewportSize);
+ /** @type {number} */ var pixelSize = dst.getAccess().getFormat().getPixelSize();
+ /** @type {number} */ var param = deMath.deIsPowerOfTwo32(pixelSize) ? Math.min(pixelSize, 8) : 1;
+ /** @type {gluTextureUtil.TransferFormat} */ var format = gluTextureUtil.getTransferFormat(dst.getAccess().getFormat());
+ /** @type {number} */ var width = dst.getAccess().getWidth();
+ /** @type {number} */ var height = dst.getAccess().getHeight();
+ if (this.m_fboParams.useFbo) {
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this.m_resolveFbo);
+ gl.blitFramebuffer(0, 0, this.m_renderWidth, this.m_renderHeight, 0, 0, this.m_renderWidth, this.m_renderHeight, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.m_resolveFbo);
+
+ gl.pixelStorei(gl.PACK_ALIGNMENT, param);
+ gl.readPixels(this.m_viewportX, this.m_viewportY, width, height, format.format, format.dataType, dst.getAccess().getDataPtr());
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_msFbo);
+ }
+ else {
+ gl.pixelStorei(gl.PACK_ALIGNMENT, param);
+ gl.readPixels(this.m_viewportX, this.m_viewportY, width, height, format.format, format.dataType, dst.getAccess().getDataPtr());
+ }
+ return dst;
+ };
+
+ es3fMultisampleTests.MultisampleCase.prototype.init = function() {
+ /** @type {string} */ var vertShaderSource = '' +
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in mediump vec4 a_color;\n' +
+ 'out mediump vec4 v_color;\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_color = a_color;\n' +
+ '}\n';
+
+ /** @type {string} */ var fragShaderSource = '' +
+ '#version 300 es\n' +
+ 'in mediump vec4 v_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' o_color = v_color;\n' +
+ '}\n';
+
+ var numSamples = /** @type {number} */ (gl.getParameter(gl.SAMPLES));
+ if (!this.m_fboParams.useFbo && numSamples <= 1) {
+ var msg = 'No multisample buffers';
+ checkMessage(false, msg);
+ return false;
+ }
+
+ if (this.m_fboParams.useFbo) {
+ if (this.m_fboParams.numSamples > 0)
+ this.m_numSamples = this.m_fboParams.numSamples;
+ else {
+ bufferedLogToConsole('Querying maximum number of samples for ' + gluStrUtil.getPixelFormatName(gl.RGBA8) + ' with gl.getInternalformatParameter()');
+ var supportedSampleCountArray = /** @type {Int32Array} */ (gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES));
+ if (supportedSampleCountArray.length == 0) {
+ var msg = 'No supported sample counts';
+ checkMessage(false, msg);
+ return false;
+ }
+ this.m_numSamples = supportedSampleCountArray[0];
+ }
+
+ bufferedLogToConsole('Using FBO of size (' + this.m_renderWidth + ', ' + this.m_renderHeight + ') with ' + this.m_numSamples + ' samples');
+ }
+ else {
+ // Query and log number of samples per pixel.
+ this.m_numSamples = numSamples;
+ bufferedLogToConsole('gl.SAMPLES =' + this.m_numSamples);
+ }
+
+ // Prepare program.
+
+ assertMsgOptions(!this.m_program, 'Program loaded when it should not be.', false, true);
+
+ this.m_program = new gluShaderProgram.ShaderProgram(
+ gl,
+ gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource));
+
+ if (!this.m_program.isOk())
+ throw new Error('Failed to compile program');
+
+ this.m_attrPositionLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ this.m_attrColorLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_color');
+
+ if (this.m_attrPositionLoc < 0 || this.m_attrColorLoc < 0) {
+ this.m_program = null;
+ throw new Error('Invalid attribute locations');
+ }
+
+ if (this.m_fboParams.useFbo) {
+ // Setup ms color RBO.
+ this.m_msColorRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_msColorRbo);
+
+ /** @type {Int32Array} */ var supportedSampleCountArray = /** @type {Int32Array} */ (gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES));
+ var maxSampleCount = supportedSampleCountArray[0];
+ if (maxSampleCount < this.m_numSamples) {
+ bufferedLogToConsole('skipping test: ' + this.m_numSamples + ' samples not supported; max is ' + maxSampleCount);
+ return false;
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'should be no GL error before renderbufferStorageMultisample');
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, gl.RGBA8, this.m_renderWidth, this.m_renderHeight);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'should be no GL error after renderbufferStorageMultisample');
+
+
+ if (this.m_fboParams.useDepth || this.m_fboParams.useStencil) {
+ // Setup ms depth & stencil RBO.
+ this.m_msDepthStencilRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_msDepthStencilRbo);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, gl.DEPTH24_STENCIL8, this.m_renderWidth, this.m_renderHeight);
+ }
+
+ // Setup ms FBO.
+ this.m_msFbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_msFbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_msColorRbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.m_msDepthStencilRbo);
+
+ // Setup resolve color RBO.
+ this.m_resolveColorRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_resolveColorRbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, this.m_renderWidth, this.m_renderHeight);
+
+ // Setup resolve FBO.
+ this.m_resolveFbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_resolveFbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_resolveColorRbo);
+
+ // Use ms FBO.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_msFbo);
+ }
+
+ // Get suitable viewport size.
+
+ this.m_viewportSize = Math.min(this.m_desiredViewportSize, this.m_renderWidth, this.m_renderHeight);
+ this.randomizeViewport();
+ return true;
+ };
+
+ /**
+ * Base class for cases testing the value of sample count.
+ *
+ * Draws a test pattern (defined by renderPattern() of an inheriting class)
+ * and counts the number of distinct colors in the resulting image. That
+ * number should be at least the value of sample count plus one. This is
+ * repeated with increased values of m_currentIteration until this correct
+ * number of colors is detected or m_currentIteration reaches
+ * m_maxNumIterations.
+ *
+ * @extends {es3fMultisampleTests.MultisampleCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fMultisampleTests.FboParams} fboParams
+ */
+ es3fMultisampleTests.NumSamplesCase = function(name, desc, fboParams) {
+ es3fMultisampleTests.MultisampleCase.call(this, name, desc, 256, fboParams);
+ /** @type {number} */ var DEFAULT_MAX_NUM_ITERATIONS = 16;
+ /** @type {number} */ this.m_currentIteration = 0;
+ /** @type {number} */ this.m_maxNumIterations = es3fMultisampleTests.getIterationCount(DEFAULT_MAX_NUM_ITERATIONS);
+ /** @type {Array<tcuRGBA.RGBA>} */ this.m_detectedColors = [];
+ };
+
+ es3fMultisampleTests.NumSamplesCase.prototype = Object.create(es3fMultisampleTests.MultisampleCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.NumSamplesCase.prototype.constructor = es3fMultisampleTests.NumSamplesCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fMultisampleTests.NumSamplesCase.prototype.iterate = function() {
+ this.randomizeViewport();
+
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ this.renderPattern();
+
+ // Read and log rendered image.
+
+ /** @type {tcuSurface.Surface} */ var renderedImg = this.readImage();
+ tcuLogImage.logImage('RenderedImage', 'Rendered image', renderedImg.getAccess());
+
+ // Detect new, previously unseen colors from image.
+
+ /** @type {number} */ var requiredNumDistinctColors = this.m_numSamples + 1;
+
+ // If the number of samples is high (64 or more), we need to lower the threshold for detecting unique colors, otherwise two expected unique colors would be treated as the same color.
+ var threshold = Math.min(3, Math.floor(255 / this.m_numSamples) - 1);
+ var thresholdRGBA = tcuRGBA.newRGBAComponents(threshold, threshold, threshold, threshold);
+
+ for (var y = 0; y < renderedImg.getHeight() && this.m_detectedColors.length < requiredNumDistinctColors; y++)
+ for (var x = 0; x < renderedImg.getWidth() && this.m_detectedColors.length < requiredNumDistinctColors; x++) {
+ /** @type {tcuRGBA.RGBA} */ var color = new tcuRGBA.RGBA(renderedImg.getPixel(x, y));
+
+ /** @type {number} */ var i;
+ for (i = 0; i < this.m_detectedColors.length; i++) {
+ if (tcuRGBA.compareThreshold(color, this.m_detectedColors[i], thresholdRGBA))
+ break;
+ }
+
+ if (i === this.m_detectedColors.length)
+ this.m_detectedColors.push(color); // Color not previously detected.
+ }
+
+ // Log results.
+
+ bufferedLogToConsole('Number of distinct colors detected so far: ' + (this.m_detectedColors.length >= requiredNumDistinctColors ? 'at least ' : '') + this.m_detectedColors.length);
+
+
+ if (this.m_detectedColors.length < requiredNumDistinctColors) {
+ // Haven't detected enough different colors yet.
+
+ this.m_currentIteration++;
+
+ if (this.m_currentIteration >= this.m_maxNumIterations) {
+ testFailedOptions('Failure: Number of distinct colors detected is lower than sample count+1', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ else {
+ bufferedLogToConsole('The number of distinct colors detected is lower than sample count+1 - trying again with a slightly altered pattern');
+ return tcuTestCase.IterateResult.CONTINUE;
+ }
+ }
+ else {
+ testPassedOptions('Success: The number of distinct colors detected is at least sample count+1', true);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ };
+
+ /**
+ * @extends {es3fMultisampleTests.NumSamplesCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.PolygonNumSamplesCase = function(name, desc, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, false) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.NumSamplesCase.call(this, name, desc, params);
+ };
+
+ es3fMultisampleTests.PolygonNumSamplesCase.prototype = Object.create(es3fMultisampleTests.NumSamplesCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.PolygonNumSamplesCase.prototype.constructor = es3fMultisampleTests.PolygonNumSamplesCase;
+
+ es3fMultisampleTests.PolygonNumSamplesCase.prototype.renderPattern = function() {
+ // The test pattern consists of several triangles with edges at different angles.
+
+ /** @type {number} */ var numTriangles = 25;
+ for (var i = 0; i < numTriangles; i++) {
+ /** @type {number} */ var angle0 = 2.0 * Math.PI * i / numTriangles + 0.001 * this.m_currentIteration;
+ /** @type {number} */ var angle1 = 2.0 * Math.PI * (i + 0.5) / numTriangles + 0.001 * this.m_currentIteration;
+
+ this.renderTriangle_pAsVec2WithColor(
+ [0.0, 0.0],
+ [Math.cos(angle0) * 0.95, Math.sin(angle0) * 0.95],
+ [Math.cos(angle1) * 0.95, Math.sin(angle1) * 0.95],
+ [1.0, 1.0, 1.0, 1.0]);
+ }
+ };
+
+ /**
+ * @extends {es3fMultisampleTests.NumSamplesCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.LineNumSamplesCase = function(name, desc, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, false) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.NumSamplesCase.call(this, name, desc, params);
+ };
+
+ es3fMultisampleTests.LineNumSamplesCase.prototype = Object.create(es3fMultisampleTests.NumSamplesCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.LineNumSamplesCase.prototype.constructor = es3fMultisampleTests.LineNumSamplesCase;
+
+ es3fMultisampleTests.LineNumSamplesCase.prototype.renderPattern = function() {
+ // The test pattern consists of several lines at different angles.
+
+ // We scale the number of lines based on the viewport size. This is because a gl line's thickness is
+ // constant in pixel units, i.e. they get relatively thicker as viewport size decreases. Thus we must
+ // decrease the number of lines in order to decrease the extent of overlap among the lines in the
+ // center of the pattern.
+ /** @type {number} */ var numLines = Math.floor(100.0 * Math.sqrt(this.m_viewportSize / 256.0));
+
+ for (var i = 0; i < numLines; i++) {
+ /** @type {number} */ var angle = 2.0 * Math.PI * i / numLines + 0.001 * this.m_currentIteration;
+ this.renderLine([0.0, 0.0], [Math.cos(angle) * 0.95, Math.sin(angle) * 0.95], [1.0, 1.0, 1.0, 1.0]);
+ }
+ };
+
+ /**
+ * Case testing behaviour of common edges when multisampling.
+ *
+ * Draws a number of test patterns, each with a number of quads, each made
+ * of two triangles, rotated at different angles. The inner edge inside the
+ * quad (i.e. the common edge of the two triangles) still should not be
+ * visible, despite multisampling - i.e. the two triangles forming the quad
+ * should never get any common coverage bits in any pixel.
+ *
+ * @extends {es3fMultisampleTests.MultisampleCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fMultisampleTests.CommonEdgeCase.CaseType} caseType
+ * @param {number} numFboSamples
+ */
+ es3fMultisampleTests.CommonEdgeCase = function(name, desc, caseType, numFboSamples) {
+ /** @type {number} */ var cases = caseType === es3fMultisampleTests.CommonEdgeCase.CaseType.SMALL_QUADS ? 128 : 32;
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, false) : new es3fMultisampleTests.FboParams();
+
+ es3fMultisampleTests.MultisampleCase.call(this, name, desc, cases, params);
+ /** @type {number} */ var DEFAULT_SMALL_QUADS_ITERATIONS = 16;
+ /** @type {number} */ var DEFAULT_BIGGER_THAN_VIEWPORT_QUAD_ITERATIONS = 64; // 8*8
+ /** @type {es3fMultisampleTests.CommonEdgeCase.CaseType} */ this.m_caseType = caseType;
+ /** @type {number} */ this.m_currentIteration = 0;
+ /** @type {number} */
+ this.m_numIterations = caseType === es3fMultisampleTests.CommonEdgeCase.CaseType.SMALL_QUADS ? es3fMultisampleTests.getIterationCount(DEFAULT_SMALL_QUADS_ITERATIONS) :
+ caseType === es3fMultisampleTests.CommonEdgeCase.CaseType.BIGGER_THAN_VIEWPORT_QUAD ? es3fMultisampleTests.getIterationCount(DEFAULT_BIGGER_THAN_VIEWPORT_QUAD_ITERATIONS) :
+ 8;
+ };
+
+ es3fMultisampleTests.CommonEdgeCase.prototype = Object.create(es3fMultisampleTests.MultisampleCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.CommonEdgeCase.prototype.constructor = es3fMultisampleTests.CommonEdgeCase;
+
+ /**
+ * @enum {number}
+ */
+ es3fMultisampleTests.CommonEdgeCase.CaseType = {
+ SMALL_QUADS: 0, //!< Draw several small quads per iteration.
+ BIGGER_THAN_VIEWPORT_QUAD: 1, //!< Draw one bigger-than-viewport quad per iteration.
+ FIT_VIEWPORT_QUAD: 2 //!< Draw one exactly viewport-sized, axis aligned quad per iteration.
+ };
+
+ es3fMultisampleTests.CommonEdgeCase.prototype.init = function() {
+ var inited = es3fMultisampleTests.MultisampleCase.prototype.init.call(this);
+ if (!inited) {
+ return false;
+ }
+
+ if (this.m_caseType === es3fMultisampleTests.CommonEdgeCase.CaseType.SMALL_QUADS) {
+ // Check for a big enough viewport. With too small viewports the test case can't analyze the resulting image well enough.
+
+ /** @type {number} */ var minViewportSize = 32;
+
+ if (this.m_viewportSize < minViewportSize)
+ throw new Error('Render target width or height too low (is ' + this.m_viewportSize + ', should be at least ' + minViewportSize + ')');
+ }
+
+ gl.enable(gl.BLEND);
+ gl.blendEquation(gl.FUNC_ADD);
+ gl.blendFunc(gl.ONE, gl.ONE);
+ bufferedLogToConsole('Additive blending enabled in order to detect (erroneously) overlapping samples');
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fMultisampleTests.CommonEdgeCase.prototype.iterate = function() {
+ /** @type {tcuSurface.Surface} */ var errorImg = new tcuSurface.Surface(this.m_viewportSize, this.m_viewportSize);
+
+ this.randomizeViewport();
+
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw test pattern. Test patterns consist of quads formed with two triangles.
+ // After drawing the pattern, we check that the interior pixels of each quad are
+ // all the same color - this is meant to verify that there are no artifacts on the inner edge.
+
+ /** @type {Array<es3fMultisampleTests.QuadCorners>} */ var unicoloredRegions = [];
+
+ /** @type {Array<Array<number>>} */ var corners;
+ /** @type {number} */ var angleCos;
+ /** @type {number} */ var angleSin;
+ /** @type {number} */ var angle;
+ /** @type {number} */ var quadDiagLen;
+ /** @type {number} */ var unicolorRegionScale;
+ /** @type {number} */ var quadBaseAngleNdx
+ /** @type {number} */ var quadSubAngleNdx;
+
+ if (this.m_caseType == es3fMultisampleTests.CommonEdgeCase.CaseType.SMALL_QUADS) {
+ // Draw several quads, rotated at different angles.
+
+ quadDiagLen = 2.0 / 3.0 * 0.9; // \note Fit 3 quads in both x and y directions.
+
+
+ // \note First and second iteration get exact 0 (and 90, 180, 270) and 45 (and 135, 225, 315) angle quads, as they are kind of a special case.
+
+ if (this.m_currentIteration === 0) {
+ angleCos = 1.0;
+ angleSin = 0.0;
+ }
+ else if (this.m_currentIteration === 1) {
+ angleCos = Math.SQRT1_2;
+ angleSin = Math.SQRT1_2;
+ }
+ else {
+ angle = 0.5 * Math.PI * (this.m_currentIteration - 1) / (this.m_numIterations - 1);
+ angleCos = Math.cos(angle);
+ angleSin = Math.sin(angle);
+ }
+
+ corners = [
+ deMath.scale([angleCos, angleSin], 0.5 * quadDiagLen),
+ deMath.scale([-angleSin, angleCos], 0.5 * quadDiagLen),
+ deMath.scale([-angleCos, -angleSin], 0.5 * quadDiagLen),
+ deMath.scale([angleSin, -angleCos], 0.5 * quadDiagLen)
+ ];
+
+ // Draw 8 quads.
+ // First four are rotated at angles angle+0, angle+90, angle+180 and angle+270.
+ // Last four are rotated the same angles as the first four, but the ordering of the last triangle's vertices is reversed.
+
+ for (var quadNdx = 0; quadNdx < 8; quadNdx++) {
+ /** @type {Array<number>} */
+ var center = deMath.addScalar(
+ deMath.scale([quadNdx % 3, quadNdx / 3], (2.0 - quadDiagLen)/ 2.0),
+ (-0.5 * (2.0 - quadDiagLen)));
+
+ this.renderTriangle_pAsVec2WithColor(
+ deMath.add(corners[(0 + quadNdx) % 4], center),
+ deMath.add(corners[(1 + quadNdx) % 4], center),
+ deMath.add(corners[(2 + quadNdx) % 4], center),
+ [0.5, 0.5, 0.5, 1.0]);
+
+ if (quadNdx >= 4) {
+ this.renderTriangle_pAsVec2WithColor(
+ deMath.add(corners[(3 + quadNdx) % 4], center),
+ deMath.add(corners[(2 + quadNdx) % 4], center),
+ deMath.add(corners[(0 + quadNdx) % 4], center),
+ [0.5, 0.5, 0.5, 1.0]);
+ }
+ else {
+ this.renderTriangle_pAsVec2WithColor(
+ deMath.add(corners[(0 + quadNdx) % 4], center),
+ deMath.add(corners[(2 + quadNdx) % 4], center),
+ deMath.add(corners[(3 + quadNdx) % 4], center),
+ [0.5, 0.5, 0.5, 1.0]);
+ }
+
+ // The size of the 'interior' of a quad is assumed to be approximately unicolorRegionScale*<actual size of quad>.
+ // By 'interior' we here mean the region of non-boundary pixels of the rendered quad for which we can safely assume
+ // that it has all coverage bits set to 1, for every pixel.
+ unicolorRegionScale = 1.0 - 6.0 * 2.0 / this.m_viewportSize / quadDiagLen;
+ unicoloredRegions.push(
+ new es3fMultisampleTests.QuadCorners(
+ deMath.add(center, deMath.scale(corners[0], unicolorRegionScale)),
+ deMath.add(center, deMath.scale(corners[1], unicolorRegionScale)),
+ deMath.add(center, deMath.scale(corners[2], unicolorRegionScale)),
+ deMath.add(center, deMath.scale(corners[3], unicolorRegionScale))));
+ }
+ }
+ else if (this.m_caseType === es3fMultisampleTests.CommonEdgeCase.CaseType.BIGGER_THAN_VIEWPORT_QUAD) {
+ // Draw a bigger-than-viewport quad, rotated at an angle depending on m_currentIteration.
+
+ quadBaseAngleNdx = Math.floor(this.m_currentIteration / 8);
+ quadSubAngleNdx = this.m_currentIteration % 8;
+
+ if (quadBaseAngleNdx === 0) {
+ angleCos = 1.0;
+ angleSin = 0.0;
+ }
+ else if (quadBaseAngleNdx === 1) {
+ angleCos = Math.SQRT1_2;
+ angleSin = Math.SQRT1_2;
+ }
+ else {
+ angle = 0.5 * Math.PI * (this.m_currentIteration - 1) / (this.m_numIterations - 1);
+ angleCos = Math.cos(angle);
+ angleSin = Math.sin(angle);
+ }
+
+ quadDiagLen = 2.5 / Math.max(angleCos, angleSin);
+
+ corners = [
+ deMath.scale([angleCos, angleSin], 0.5 * quadDiagLen),
+ deMath.scale([-angleSin, angleCos], 0.5 * quadDiagLen),
+ deMath.scale([-angleCos, -angleSin], 0.5 * quadDiagLen),
+ deMath.scale([angleSin, -angleCos], 0.5 * quadDiagLen)
+ ];
+
+ this.renderTriangle_pAsVec2WithColor(
+ corners[(0 + quadSubAngleNdx) % 4],
+ corners[(1 + quadSubAngleNdx) % 4],
+ corners[(2 + quadSubAngleNdx) % 4],
+ [0.5, 0.5, 0.5, 1.0]);
+
+ if (quadSubAngleNdx >= 4) {
+ this.renderTriangle_pAsVec2WithColor(
+ corners[(3 + quadSubAngleNdx) % 4],
+ corners[(2 + quadSubAngleNdx) % 4],
+ corners[(0 + quadSubAngleNdx) % 4],
+ [0.5, 0.5, 0.5, 1.0]);
+ }
+ else {
+ this.renderTriangle_pAsVec2WithColor(
+ corners[(0 + quadSubAngleNdx) % 4],
+ corners[(2 + quadSubAngleNdx) % 4],
+ corners[(3 + quadSubAngleNdx) % 4],
+ [0.5, 0.5, 0.5, 1.0]);
+ }
+
+ unicolorRegionScale = 1.0 - 6.0 * 2.0 / this.m_viewportSize / quadDiagLen;
+ unicoloredRegions.push(
+ new es3fMultisampleTests.QuadCorners(
+ deMath.scale(corners[0], unicolorRegionScale),
+ deMath.scale(corners[1], unicolorRegionScale),
+ deMath.scale(corners[2], unicolorRegionScale),
+ deMath.scale(corners[3], unicolorRegionScale)));
+ }
+ else if (this.m_caseType === es3fMultisampleTests.CommonEdgeCase.CaseType.FIT_VIEWPORT_QUAD) {
+ // Draw an exactly viewport-sized quad, rotated by multiples of 90 degrees angle depending on m_currentIteration.
+
+ quadSubAngleNdx = this.m_currentIteration % 8;
+
+ corners = [
+ [1.0, 1.0],
+ [-1.0, 1.0],
+ [-1.0, -1.0],
+ [1.0, -1.0]
+ ];
+
+ this.renderTriangle_pAsVec2WithColor(
+ corners[(0 + quadSubAngleNdx) % 4],
+ corners[(1 + quadSubAngleNdx) % 4],
+ corners[(2 + quadSubAngleNdx) % 4],
+ [0.5, 0.5, 0.5, 1.0]);
+
+ if (quadSubAngleNdx >= 4) {
+ this.renderTriangle_pAsVec2WithColor(
+ corners[(3 + quadSubAngleNdx) % 4],
+ corners[(2 + quadSubAngleNdx) % 4],
+ corners[(0 + quadSubAngleNdx) % 4],
+ [0.5, 0.5, 0.5, 1.0]);
+ }
+ else {
+ this.renderTriangle_pAsVec2WithColor(
+ corners[(0 + quadSubAngleNdx) % 4],
+ corners[(2 + quadSubAngleNdx) % 4],
+ corners[(3 + quadSubAngleNdx) % 4],
+ [0.5, 0.5, 0.5, 1.0]);
+ }
+
+ unicoloredRegions.push(new es3fMultisampleTests.QuadCorners(corners[0], corners[1], corners[2], corners[3]));
+ }
+ else
+ throw new Error('CaseType not supported.');
+
+ // Read pixels and check unicolored regions.
+
+ /** @type {tcuSurface.Surface} */ var renderedImg = this.readImage();
+
+ errorImg.getAccess().clear([0.0, 1.0, 0.0, 1.0]);
+ tcuLogImage.logImage('RenderedImage', 'Rendered image', renderedImg.getAccess());
+
+ /** @type {boolean} */ var errorsDetected = false;
+ for (var i = 0; i < unicoloredRegions.length; i++) {
+ /** @type {es3fMultisampleTests.QuadCorners} */ var region = unicoloredRegions[i];
+ /** @type {Array<number>} */ var p0Win = deMath.scale(deMath.addScalar(region.p0, 1.0), 0.5 * (this.m_viewportSize - 1) + 0.5);
+ /** @type {Array<number>} */ var p1Win = deMath.scale(deMath.addScalar(region.p1, 1.0), 0.5 * (this.m_viewportSize - 1) + 0.5);
+ /** @type {Array<number>} */ var p2Win = deMath.scale(deMath.addScalar(region.p2, 1.0), 0.5 * (this.m_viewportSize - 1) + 0.5);
+ /** @type {Array<number>} */ var p3Win = deMath.scale(deMath.addScalar(region.p3, 1.0), 0.5 * (this.m_viewportSize - 1) + 0.5);
+ /** @type {boolean} */ var errorsInCurrentRegion = !es3fMultisampleTests.isPixelRegionUnicolored(renderedImg, p0Win, p1Win, p2Win, p3Win);
+
+ if (errorsInCurrentRegion)
+ es3fMultisampleTests.drawUnicolorTestErrors(renderedImg, errorImg.getAccess(), p0Win, p1Win, p2Win, p3Win);
+
+ errorsDetected = errorsDetected || errorsInCurrentRegion;
+ }
+
+ this.m_currentIteration++;
+
+ if (errorsDetected) {
+ bufferedLogToConsole('Failure: Not all quad interiors seem unicolored - common-edge artifacts?');
+ bufferedLogToConsole('Erroneous pixels are drawn red in the following image');
+ tcuLogImage.logImage('RenderedImageWithErrors', 'Rendered image with errors marked', renderedImg.getAccess());
+ tcuLogImage.logImage('ErrorsOnly', 'Image with error pixels only', errorImg.getAccess());
+ testFailedOptions('Failed: iteration ' + (this.m_currentIteration - 1), false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ else if (this.m_currentIteration < this.m_numIterations) {
+ bufferedLogToConsole('Quads seem OK - moving on to next pattern');
+ return tcuTestCase.IterateResult.CONTINUE;
+ }
+ else {
+ bufferedLogToConsole('Success: All quad interiors seem unicolored (no common-edge artifacts)');
+ testPassedOptions('Passed: iteration ' + (this.m_currentIteration - 1), true);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ };
+
+ /**
+ * Test that depth values are per-sample.
+ *
+ * Draws intersecting, differently-colored polygons and checks that there
+ * are at least sample count+1 distinct colors present, due to some of the
+ * samples at the intersection line belonging to one and some to another
+ * polygon.
+ *
+ * @extends {es3fMultisampleTests.NumSamplesCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.SampleDepthCase = function(name, desc, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, true, false) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.NumSamplesCase.call(this, name, desc, params);
+ };
+
+ es3fMultisampleTests.SampleDepthCase.prototype = Object.create(es3fMultisampleTests.NumSamplesCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.SampleDepthCase.prototype.constructor = es3fMultisampleTests.SampleDepthCase;
+
+ es3fMultisampleTests.SampleDepthCase.prototype.init = function() {
+ var inited = es3fMultisampleTests.MultisampleCase.prototype.init.call(this);
+ if (!inited) {
+ return false;
+ }
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LESS);
+
+ bufferedLogToConsole('Depth test enabled, depth func is gl.LESS');
+ bufferedLogToConsole('Drawing several bigger-than-viewport black or white polygons intersecting each other');
+ };
+
+ es3fMultisampleTests.SampleDepthCase.prototype.renderPattern = function() {
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clearDepth(1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ /** @type {number} */ var numPolygons = 50;
+
+ for (var i = 0; i < numPolygons; i++) {
+ /** @type {Array<number>} */ var color = i % 2 == 0 ? [1.0, 1.0, 1.0, 1.0] : [0.0, 0.0, 0.0, 1.0];
+ /** @type {number} */ var angle = 2.0 * Math.PI * i / numPolygons + 0.001 * this.m_currentIteration;
+ /** @type {Array<number>} */ var pt0 = [3.0 * Math.cos(angle + 2.0 * Math.PI * 0.0 / 3.0), 3.0 * Math.sin(angle + 2.0 * Math.PI * 0.0 / 3.0), 1.0];
+ /** @type {Array<number>} */ var pt1 = [3.0 * Math.cos(angle + 2.0 * Math.PI * 1.0 / 3.0), 3.0 * Math.sin(angle + 2.0 * Math.PI * 1.0 / 3.0), 0.0];
+ /** @type {Array<number>} */ var pt2 = [3.0 * Math.cos(angle + 2.0 * Math.PI * 2.0 / 3.0), 3.0 * Math.sin(angle + 2.0 * Math.PI * 2.0 / 3.0), 0.0];
+
+ this.renderTriangle_pAsVec3WithColor(pt0, pt1, pt2, color);
+ }
+ };
+
+ /**
+ * Test that stencil buffer values are per-sample.
+ *
+ * Draws a unicolored pattern and marks drawn samples in stencil buffer;
+ * then clears and draws a viewport-size quad with that color and with
+ * proper stencil test such that the resulting image should be exactly the
+ * same as after the pattern was first drawn.
+ *
+ * @extends {es3fMultisampleTests.MultisampleCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.SampleStencilCase = function(name, desc, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, true) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.MultisampleCase.call(this, name, desc, 256, params);
+ };
+
+ es3fMultisampleTests.SampleStencilCase.prototype = Object.create(es3fMultisampleTests.MultisampleCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.SampleStencilCase.prototype.constructor = es3fMultisampleTests.SampleStencilCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fMultisampleTests.SampleStencilCase.prototype.iterate = function() {
+ this.randomizeViewport();
+
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clearStencil(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ gl.enable(gl.STENCIL_TEST);
+ gl.stencilFunc(gl.ALWAYS, 1, 1);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+
+ bufferedLogToConsole('Drawing a pattern with gl.stencilFunc(gl.ALWAYS, 1, 1) and gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE)');
+
+ /** @type {number} */ var numTriangles = 25;
+ for (var i = 0; i < numTriangles; i++) {
+ /** @type {number} */ var angle0 = 2.0 * Math.PI * i / numTriangles;
+ /** @type {number} */ var angle1 = 2.0 * Math.PI * (i + 0.5) / numTriangles;
+
+ this.renderTriangle_pAsVec2WithColor(
+ [0.0, 0.0],
+ [Math.cos(angle0) * 0.95, Math.sin(angle0) * 0.95],
+ [Math.cos(angle1) * 0.95, Math.sin(angle1) * 0.95],
+ [1.0, 1.0, 1.0, 1.0]);
+ }
+
+ /** @type {tcuSurface.Surface} */ var renderedImgFirst = this.readImage();
+ tcuLogImage.logImage('RenderedImgFirst', 'First image rendered', renderedImgFirst.getAccess());
+ bufferedLogToConsole('Clearing color buffer to black');
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.stencilFunc(gl.EQUAL, 1, 1);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+
+ bufferedLogToConsole('Checking that color buffer was actually cleared to black');
+
+ /** @type {tcuSurface.Surface} */ var clearedImg = this.readImage();
+
+ for (var y = 0; y < clearedImg.getHeight(); y++)
+ for (var x = 0; x < clearedImg.getWidth(); x++) {
+ /** @type {tcuRGBA.RGBA} */ var clr = new tcuRGBA.RGBA(clearedImg.getPixel(x, y));
+ if (!clr.equals(tcuRGBA.RGBA.black)) {
+ bufferedLogToConsole('Failure: first non-black pixel, color ' + clr.toString() + ', detected at coordinates (' + x + ', ' + y + ')');
+ tcuLogImage.logImage('ClearedImg', 'Image after clearing, erroneously non-black', clearedImg.getAccess());
+ testFailedOptions('Failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ }
+
+ bufferedLogToConsole('Drawing a viewport-sized quad with gl.stencilFunc(gl.EQUAL, 1, 1) and gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP) - should result in same image as the first');
+
+ this.renderQuad_WithColor(
+ [-1.0, -1.0],
+ [1.0, -1.0],
+ [-1.0, 1.0],
+ [1.0, 1.0],
+ [1.0, 1.0, 1.0, 1.0]);
+
+ /** @type {tcuSurface.Surface} */ var renderedImgSecond = this.readImage();
+ tcuLogImage.logImage('RenderedImgSecond', 'Second image rendered', renderedImgSecond.getAccess());
+ /** @type {boolean} */
+ var passed = tcuImageCompare.pixelThresholdCompare(
+ 'ImageCompare',
+ 'Image comparison',
+ renderedImgFirst,
+ renderedImgSecond,
+ [0,0,0,0]);
+
+ if (passed) {
+ bufferedLogToConsole('Success: The two images rendered are identical');
+ testPassedOptions('Passed', true);
+ }
+ else
+ testFailedOptions('Failed', false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * Tests coverage mask generation proportionality property.
+ *
+ * Tests that the number of coverage bits in a coverage mask created by
+ * gl.SAMPLE_ALPHA_TO_COVERAGE or gl.SAMPLE_COVERAGE is, on average,
+ * proportional to the alpha or coverage value, respectively. Draws
+ * multiple frames, each time increasing the alpha or coverage value used,
+ * and checks that the average color is changing appropriately.
+ *
+ * @extends {es3fMultisampleTests.MultisampleCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fMultisampleTests.MaskProportionalityCase.CaseType} type
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.MaskProportionalityCase = function(name, desc, type, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, false) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.MultisampleCase.call(this, name, desc, 32, params);
+ /** @type {es3fMultisampleTests.MaskProportionalityCase.CaseType} */ this.m_type = type;
+ /** @type {number} */ this.m_numIterations;
+ /** @type {number} */ this.m_currentIteration = 0;
+ /** @type {number} */ this.m_previousIterationColorSum = -1;
+ };
+
+ es3fMultisampleTests.MaskProportionalityCase.prototype = Object.create(es3fMultisampleTests.MultisampleCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.MaskProportionalityCase.prototype.constructor = es3fMultisampleTests.MaskProportionalityCase;
+
+ /**
+ * @enum {number}
+ */
+ es3fMultisampleTests.MaskProportionalityCase.CaseType = {
+ ALPHA_TO_COVERAGE: 0,
+ SAMPLE_COVERAGE: 1,
+ SAMPLE_COVERAGE_INVERTED: 2
+ };
+
+ es3fMultisampleTests.MaskProportionalityCase.prototype.init = function() {
+ var inited = es3fMultisampleTests.MultisampleCase.prototype.init.call(this);
+ if (!inited) {
+ return false;
+ }
+
+ if (this.m_type == es3fMultisampleTests.MaskProportionalityCase.CaseType.ALPHA_TO_COVERAGE) {
+ gl.enable(gl.SAMPLE_ALPHA_TO_COVERAGE);
+ bufferedLogToConsole('gl.SAMPLE_ALPHA_TO_COVERAGE is enabled');
+ }
+ else {
+ assertMsgOptions(
+ this.m_type == es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE ||
+ this.m_type == es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE_INVERTED,
+ 'CaseType should be SAMPLE_COVERAGE or SAMPLE_COVERAGE_INVERTED', false, true);
+
+ gl.enable(gl.SAMPLE_COVERAGE);
+ bufferedLogToConsole('gl.SAMPLE_COVERAGE is enabled');
+ }
+
+ this.m_numIterations = Math.max(2, es3fMultisampleTests.getIterationCount(this.m_numSamples * 5));
+
+ this.randomizeViewport(); // \note Using the same viewport for every iteration since coverage mask may depend on window-relative pixel coordinate.
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fMultisampleTests.MaskProportionalityCase.prototype.iterate = function() {
+ bufferedLogToConsole('Clearing color to black');
+ gl.colorMask(true, true, true, true);
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ if (this.m_type === es3fMultisampleTests.MaskProportionalityCase.CaseType.ALPHA_TO_COVERAGE) {
+ gl.colorMask(true, true, true, false);
+ bufferedLogToConsole('Using color mask TRUE, TRUE, TRUE, FALSE');
+ }
+
+ // Draw quad.
+
+ /** @type {Array<number>} */ var pt0 = [-1.0, -1.0];
+ /** @type {Array<number>} */ var pt1 = [1.0, -1.0];
+ /** @type {Array<number>} */ var pt2 = [-1.0, 1.0];
+ /** @type {Array<number>} */ var pt3 = [1.0, 1.0];
+ /** @type {Array<number>} */ var quadColor = [1.0, 0.0, 0.0, 1.0];
+ /** @type {number} */ var alphaOrCoverageValue = this.m_currentIteration / (this.m_numIterations-1);
+
+ if (this.m_type === es3fMultisampleTests.MaskProportionalityCase.CaseType.ALPHA_TO_COVERAGE) {
+ bufferedLogToConsole('Drawing a red quad using alpha value ' + alphaOrCoverageValue);
+ quadColor[3] = alphaOrCoverageValue;
+ }
+ else {
+ assertMsgOptions(
+ this.m_type === es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE ||
+ this.m_type === es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE_INVERTED,
+ 'CaseType should be SAMPLE_COVERAGE or SAMPLE_COVERAGE_INVERTED', false, true);
+
+ /** @type {boolean} */ var isInverted = (this.m_type === es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE_INVERTED);
+ /** @type {number} */ var coverageValue = isInverted ? 1.0 - alphaOrCoverageValue : alphaOrCoverageValue;
+ bufferedLogToConsole('Drawing a red quad using sample coverage value ' + coverageValue + (isInverted ? ' (inverted)' : ''));
+ gl.sampleCoverage(coverageValue, isInverted ? true : false);
+ }
+
+ this.renderQuad_WithColor(pt0, pt1, pt2, pt3, quadColor);
+
+ // Read and log image.
+ /** @type {tcuSurface.Surface} */ var renderedImg = this.readImage();
+ /** @type {number} */ var numPixels = renderedImg.getWidth() * renderedImg.getHeight();
+
+ tcuLogImage.logImage('RenderedImage', 'Rendered image', renderedImg.getAccess());
+ // Compute average red component in rendered image.
+
+ /** @type {number} */ var sumRed = 0;
+
+ for (var y = 0; y < renderedImg.getHeight(); y++)
+ for (var x = 0; x < renderedImg.getWidth(); x++)
+ sumRed += new tcuRGBA.RGBA(renderedImg.getPixel(x, y)).getRed();
+
+ bufferedLogToConsole('Average red color component: ' + (sumRed / 255.0 / numPixels));
+
+ // Check if average color has decreased from previous frame's color.
+
+ if (sumRed < this.m_previousIterationColorSum) {
+ bufferedLogToConsole('Failure: Current average red color component is lower than previous');
+ testFailedOptions('Failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ // Check if coverage mask is not all-zeros if alpha or coverage value is 0 (or 1, if inverted).
+
+ if (this.m_currentIteration == 0 && sumRed != 0)
+ {
+ bufferedLogToConsole('Failure: Image should be completely black');
+ testFailedOptions('Failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ if (this.m_currentIteration == this.m_numIterations-1 && sumRed != 0xff*numPixels)
+ {
+ bufferedLogToConsole('Failure: Image should be completely red');
+
+ testFailedOptions('Failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ this.m_previousIterationColorSum = sumRed;
+
+ this.m_currentIteration++;
+
+ if (this.m_currentIteration >= this.m_numIterations)
+ {
+ bufferedLogToConsole('Success: Number of coverage mask bits set appears to be, on average, proportional to ' +
+ (this.m_type == es3fMultisampleTests.MaskProportionalityCase.CaseType.ALPHA_TO_COVERAGE ? 'alpha' :
+ this.m_type == es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE ? 'sample coverage value' :
+ 'inverted sample coverage value'));
+
+ testPassedOptions('Passed', true);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ else
+ return tcuTestCase.IterateResult.CONTINUE;
+ };
+
+ /**
+ * Tests coverage mask generation constancy property.
+ *
+ * Tests that the coverage mask created by gl.SAMPLE_ALPHA_TO_COVERAGE or
+ * gl.SAMPLE_COVERAGE is constant at given pixel coordinates, with a given
+ * alpha component or coverage value, respectively. Draws two quads, with
+ * the second one fully overlapping the first one such that at any given
+ * pixel, both quads have the same alpha or coverage value. This way, if
+ * the constancy property is fulfilled, only the second quad should be
+ * visible.
+ * @extends {es3fMultisampleTests.MultisampleCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fMultisampleTests.MaskConstancyCase.CaseType} type
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.MaskConstancyCase = function(name, desc, type, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, false) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.MultisampleCase.call(this, name, desc, 256, params);
+ var CaseType = es3fMultisampleTests.MaskConstancyCase.CaseType;
+ /** @type {boolean} */ this.m_isAlphaToCoverageCase = (type === CaseType.ALPHA_TO_COVERAGE || type === CaseType.BOTH || type === CaseType.BOTH_INVERTED);
+ /** @type {boolean} */ this.m_isSampleCoverageCase = (type === CaseType.SAMPLE_COVERAGE || type === CaseType.SAMPLE_COVERAGE_INVERTED || type === CaseType.BOTH || type === CaseType.BOTH_INVERTED);
+ /** @type {boolean} */ this.m_isInvertedSampleCoverageCase = (type === CaseType.SAMPLE_COVERAGE_INVERTED || type === CaseType.BOTH_INVERTED);
+ };
+
+ es3fMultisampleTests.MaskConstancyCase.prototype = Object.create(es3fMultisampleTests.MultisampleCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.MaskConstancyCase.prototype.constructor = es3fMultisampleTests.MaskConstancyCase;
+
+ /**
+ * @enum {number}
+ */
+ es3fMultisampleTests.MaskConstancyCase.CaseType = {
+ ALPHA_TO_COVERAGE: 0, //!< Use only alpha-to-coverage.
+ SAMPLE_COVERAGE: 1, //!< Use only sample coverage.
+ SAMPLE_COVERAGE_INVERTED: 2, //!< Use only inverted sample coverage.
+ BOTH: 3, //!< Use both alpha-to-coverage and sample coverage.
+ BOTH_INVERTED: 4 //!< Use both alpha-to-coverage and inverted sample coverage.
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fMultisampleTests.MaskConstancyCase.prototype.iterate = function() {
+ this.randomizeViewport();
+
+ bufferedLogToConsole('Clearing color to black');
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ if (this.m_isAlphaToCoverageCase) {
+ gl.enable(gl.SAMPLE_ALPHA_TO_COVERAGE);
+ gl.colorMask(true, true, true, false);
+ bufferedLogToConsole('gl.SAMPLE_ALPHA_TO_COVERAGE is enabled');
+ bufferedLogToConsole('Color mask is TRUE, TRUE, TRUE, FALSE');
+ }
+
+ if (this.m_isSampleCoverageCase) {
+ gl.enable(gl.SAMPLE_COVERAGE);
+ bufferedLogToConsole('gl.SAMPLE_COVERAGE is enabled');
+ }
+
+ bufferedLogToConsole('Drawing several green quads, each fully overlapped by a red quad with the same ' +
+ (this.m_isAlphaToCoverageCase ? 'alpha' : '') +
+ (this.m_isAlphaToCoverageCase && this.m_isSampleCoverageCase ? ' and ' : '') +
+ (this.m_isInvertedSampleCoverageCase ? 'inverted ' : '') +
+ (this.m_isSampleCoverageCase ? 'sample coverage' : '') +
+ ' values');
+
+ /** @type {number} */ var numQuadRowsCols = this.m_numSamples * 4;
+
+ for (var row = 0; row < numQuadRowsCols; row++) {
+ for (var col = 0; col < numQuadRowsCols; col++) {
+ /** @type {number} */ var x0 = (col + 0) / numQuadRowsCols * 2.0 - 1.0;
+ /** @type {number} */ var x1 = (col + 1) / numQuadRowsCols * 2.0 - 1.0;
+ /** @type {number} */ var y0 = (row + 0) / numQuadRowsCols * 2.0 - 1.0;
+ /** @type {number} */ var y1 = (row + 1) / numQuadRowsCols * 2.0 - 1.0;
+ /** @type {Array<number>} */ var baseGreen = [0.0, 1.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var baseRed = [1.0, 0.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var alpha0 = [0.0, 0.0, 0.0, this.m_isAlphaToCoverageCase ? col / (numQuadRowsCols - 1) : 1.0];
+ /** @type {Array<number>} */ var alpha1 = [0.0, 0.0, 0.0, this.m_isAlphaToCoverageCase ? row / (numQuadRowsCols - 1) : 1.0];
+
+ if (this.m_isSampleCoverageCase) {
+ /** @type {number} */ var value = (row*numQuadRowsCols + col) / (numQuadRowsCols*numQuadRowsCols - 1);
+ gl.sampleCoverage(this.m_isInvertedSampleCoverageCase ? 1.0 - value : value, this.m_isInvertedSampleCoverageCase ? true : false);
+ }
+
+ this.renderQuad([x0, y0], [x1, y0], [x0, y1], [x1, y1],
+ deMath.add(baseGreen, alpha0), deMath.add(baseGreen, alpha1),
+ deMath.add(baseGreen, alpha0), deMath.add(baseGreen, alpha1));
+ this.renderQuad([x0, y0], [x1, y0], [x0, y1], [x1, y1],
+ deMath.add(baseRed, alpha0), deMath.add(baseRed, alpha1),
+ deMath.add(baseRed, alpha0), deMath.add(baseRed, alpha1));
+ }
+ }
+
+ /** @type {tcuSurface.Surface} */ var renderedImg = this.readImage();
+
+ tcuLogImage.logImage('RenderedImage', 'Rendered image', renderedImg.getAccess());
+ for (var y = 0; y < renderedImg.getHeight(); y++)
+ for (var x = 0; x < renderedImg.getWidth(); x++) {
+ if (new tcuRGBA.RGBA(renderedImg.getPixel(x, y)).getGreen() > 0) {
+ bufferedLogToConsole('Failure: Non-zero green color component detected - should have been completely overwritten by red quad');
+ testFailedOptions('Failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ }
+
+ bufferedLogToConsole('Success: Coverage mask appears to be constant at a given pixel coordinate with a given ' +
+ (this.m_isAlphaToCoverageCase ? 'alpha' : '') +
+ (this.m_isAlphaToCoverageCase && this.m_isSampleCoverageCase ? ' and ' : '') +
+ (this.m_isSampleCoverageCase ? 'coverage value' : ''));
+
+ testPassedOptions('Passed', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+
+ /**
+ * Tests coverage mask inversion validity.
+ *
+ * Tests that the coverage masks obtained by glSampleCoverage(..., true)
+ * and glSampleCoverage(..., false) are indeed each others' inverses.
+ * This is done by drawing a pattern, with varying coverage values,
+ * overlapped by a pattern that has inverted masks and is otherwise
+ * identical. The resulting image is compared to one obtained by drawing
+ * the same pattern but with all-ones coverage masks.
+ * @extends {es3fMultisampleTests.MultisampleCase}
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number=} numFboSamples
+ */
+ es3fMultisampleTests.CoverageMaskInvertCase = function(name, desc, numFboSamples) {
+ numFboSamples = numFboSamples === undefined ? 0 : numFboSamples;
+ /** @type {es3fMultisampleTests.FboParams} */
+ var params = numFboSamples >= 0 ? new es3fMultisampleTests.FboParams(numFboSamples, false, false) : new es3fMultisampleTests.FboParams();
+ es3fMultisampleTests.MultisampleCase.call(this, name, desc, 256, params);
+ };
+
+ es3fMultisampleTests.CoverageMaskInvertCase.prototype = Object.create(es3fMultisampleTests.MultisampleCase.prototype);
+
+ /** Copy the constructor */
+ es3fMultisampleTests.CoverageMaskInvertCase.prototype.constructor = es3fMultisampleTests.CoverageMaskInvertCase;
+
+ /**
+ * @param {boolean} invertSampleCoverage
+ */
+ es3fMultisampleTests.CoverageMaskInvertCase.prototype.drawPattern = function(invertSampleCoverage) {
+ /** @type {number} */ var numTriangles = 25;
+ for (var i = 0; i < numTriangles; i++) {
+ gl.sampleCoverage(i / (numTriangles - 1), invertSampleCoverage ? true : false);
+
+ /** @type {number} */ var angle0 = 2.0 * Math.PI * i / numTriangles;
+ /** @type {number} */ var angle1 = 2.0 * Math.PI * (i + 0.5) / numTriangles;
+
+ this.renderTriangle_pAsVec2WithColor(
+ [0.0, 0.0],
+ [Math.cos(angle0) * 0.95, Math.sin(angle0) * 0.95],
+ [Math.cos(angle1) * 0.95, Math.sin(angle1) * 0.95],
+ [0.4 + i / numTriangles * 0.6,
+ 0.5 + i / numTriangles * 0.3,
+ 0.6 - i / numTriangles * 0.5,
+ 0.7 - i / numTriangles * 0.7]);
+ }
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fMultisampleTests.CoverageMaskInvertCase.prototype.iterate = function() {
+ this.randomizeViewport();
+
+ gl.enable(gl.BLEND);
+ gl.blendEquation(gl.FUNC_ADD);
+ gl.blendFunc(gl.ONE, gl.ONE);
+ bufferedLogToConsole('Additive blending enabled in order to detect (erroneously) overlapping samples');
+
+ bufferedLogToConsole('Clearing color to all-zeros');
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ bufferedLogToConsole('Drawing the pattern with gl.SAMPLE_COVERAGE disabled');
+ this.drawPattern(false);
+ /** @type {tcuSurface.Surface} */ var renderedImgNoSampleCoverage = this.readImage();
+
+ tcuLogImage.logImage('RenderedImageNoSampleCoverage', 'Rendered image with gl.SAMPLE_COVERAGE disabled', renderedImgNoSampleCoverage.getAccess());
+ bufferedLogToConsole('Clearing color to all-zeros');
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.enable(gl.SAMPLE_COVERAGE);
+ bufferedLogToConsole('Drawing the pattern with gl.SAMPLE_COVERAGE enabled, using non-inverted masks');
+ this.drawPattern(false);
+ bufferedLogToConsole('Drawing the pattern with gl.SAMPLE_COVERAGE enabled, using same sample coverage values but inverted masks');
+ this.drawPattern(true);
+ /** @type {tcuSurface.Surface} */ var renderedImgSampleCoverage = this.readImage();
+
+ tcuLogImage.logImage('RenderedImageSampleCoverage', 'Rendered image with gl.SAMPLE_COVERAGE enabled', renderedImgSampleCoverage.getAccess());
+ /** @type {boolean} */ var passed = tcuImageCompare.pixelThresholdCompare(
+ 'CoverageVsNoCoverage',
+ 'Comparison of same pattern with gl.SAMPLE_COVERAGE disabled and enabled',
+ renderedImgNoSampleCoverage,
+ renderedImgSampleCoverage,
+ [0, 0, 0, 0]);
+
+ if (passed) {
+ bufferedLogToConsole('Success: The two images rendered are identical');
+ testPassedOptions('Passed', true);
+ }
+ else {
+ testFailedOptions('Failed', false);
+ }
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ es3fMultisampleTests.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ /**
+ * @enum {number}
+ */
+ var CaseType = {
+ DEFAULT_FRAMEBUFFER: 0,
+ FBO_4_SAMPLES: 1,
+ FBO_8_SAMPLES: 2,
+ FBO_MAX_SAMPLES: 3
+ };
+
+ for (var caseTypeI in CaseType) {
+ /** @type {CaseType} */ var caseType = CaseType[caseTypeI];
+ /** @type {number} */
+ var numFboSamples = caseType === CaseType.DEFAULT_FRAMEBUFFER ? -1 :
+ caseType === CaseType.FBO_4_SAMPLES ? 4 :
+ caseType === CaseType.FBO_8_SAMPLES ? 8 :
+ caseType === CaseType.FBO_MAX_SAMPLES ? 0 :
+ -2;
+
+ /** @type {?string} */
+ var name = caseType === CaseType.DEFAULT_FRAMEBUFFER ? 'default_framebuffer' :
+ caseType === CaseType.FBO_4_SAMPLES ? 'fbo_4_samples' :
+ caseType === CaseType.FBO_8_SAMPLES ? 'fbo_8_samples' :
+ caseType === CaseType.FBO_MAX_SAMPLES ? 'fbo_max_samples' :
+ null;
+ /** @type {?string} */
+ var desc = caseType === CaseType.DEFAULT_FRAMEBUFFER ? 'Render into default framebuffer' :
+ caseType === CaseType.FBO_4_SAMPLES ? 'Render into a framebuffer object with 4 samples' :
+ caseType === CaseType.FBO_8_SAMPLES ? 'Render into a framebuffer object with 8 samples' :
+ caseType === CaseType.FBO_MAX_SAMPLES ? 'Render into a framebuffer object with the maximum number of samples' :
+ null;
+
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(name, desc);
+
+ assertMsgOptions(group.name != null, 'Error: No Test Name', false, true);
+ assertMsgOptions(group.description != null, 'Error: No Test Description', false, true);
+ assertMsgOptions(numFboSamples >= -1, 'Assert Failed: numFboSamples >= -1', false, true);
+ testGroup.addChild(group);
+
+ group.addChild(new es3fMultisampleTests.PolygonNumSamplesCase(
+ 'num_samples_polygon',
+ 'Test sanity of the sample count, with polygons',
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.LineNumSamplesCase(
+ 'num_samples_line',
+ 'Test sanity of the sample count, with lines',
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.CommonEdgeCase(
+ 'common_edge_small_quads',
+ 'Test polygons\'s common edges with small quads',
+ es3fMultisampleTests.CommonEdgeCase.CaseType.SMALL_QUADS,
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.CommonEdgeCase(
+ 'common_edge_big_quad',
+ 'Test polygon\'s common edges with bigger-than-viewport quads',
+ es3fMultisampleTests.CommonEdgeCase.CaseType.BIGGER_THAN_VIEWPORT_QUAD,
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.CommonEdgeCase(
+ 'common_edge_viewport_quad',
+ 'Test polygons\' common edges with exactly viewport-sized quads',
+ es3fMultisampleTests.CommonEdgeCase.CaseType.FIT_VIEWPORT_QUAD,
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.SampleDepthCase(
+ 'depth',
+ 'Test that depth values are per-sample',
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.SampleStencilCase(
+ 'stencil',
+ 'Test that stencil values are per-sample',
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.CoverageMaskInvertCase(
+ 'sample_coverage_invert',
+ 'Test that non-inverted and inverted sample coverage masks are each other\'s negations',
+ numFboSamples));
+
+
+ group.addChild(new es3fMultisampleTests.MaskProportionalityCase(
+ 'proportionality_alpha_to_coverage',
+ 'Test the proportionality property of GL_SAMPLE_ALPHA_TO_COVERAGE',
+ es3fMultisampleTests.MaskProportionalityCase.CaseType.ALPHA_TO_COVERAGE,
+ numFboSamples));
+ group.addChild(new es3fMultisampleTests.MaskProportionalityCase(
+ 'proportionality_sample_coverage',
+ 'Test the proportionality property of GL_SAMPLE_COVERAGE',
+ es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE,
+ numFboSamples));
+ group.addChild(new es3fMultisampleTests.MaskProportionalityCase(
+ 'proportionality_sample_coverage_inverted',
+ 'Test the proportionality property of inverted-mask GL_SAMPLE_COVERAGE',
+ es3fMultisampleTests.MaskProportionalityCase.CaseType.SAMPLE_COVERAGE_INVERTED,
+ numFboSamples));
+
+ group.addChild(new es3fMultisampleTests.MaskConstancyCase(
+ 'constancy_alpha_to_coverage',
+ 'Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE',
+ es3fMultisampleTests.MaskConstancyCase.CaseType.ALPHA_TO_COVERAGE,
+ numFboSamples));
+ group.addChild(new es3fMultisampleTests.MaskConstancyCase(
+ 'constancy_sample_coverage',
+ 'Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_COVERAGE',
+ es3fMultisampleTests.MaskConstancyCase.CaseType.SAMPLE_COVERAGE,
+ numFboSamples));
+ group.addChild(new es3fMultisampleTests.MaskConstancyCase(
+ 'constancy_sample_coverage_inverted',
+ 'Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using inverted-mask GL_SAMPLE_COVERAGE',
+ es3fMultisampleTests.MaskConstancyCase.CaseType.SAMPLE_COVERAGE_INVERTED,
+ numFboSamples));
+ group.addChild(new es3fMultisampleTests.MaskConstancyCase(
+ 'constancy_both',
+ 'Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE and GL_SAMPLE_COVERAGE',
+ es3fMultisampleTests.MaskConstancyCase.CaseType.BOTH,
+ numFboSamples));
+ group.addChild(new es3fMultisampleTests.MaskConstancyCase(
+ 'constancy_both_inverted',
+ 'Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE and inverted-mask GL_SAMPLE_COVERAGE',
+ es3fMultisampleTests.MaskConstancyCase.CaseType.BOTH_INVERTED,
+ numFboSamples));
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fMultisampleTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'multisample';
+ var testDescription = 'Multisample Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.setRoot(tcuTestCase.newTest(testName, testDescription, null));
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fMultisampleTests.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fMultisampleTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeBufferApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeBufferApiTests.js
new file mode 100644
index 0000000000..2a8910eb0d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeBufferApiTests.js
@@ -0,0 +1,1104 @@
+'use strict';
+goog.provide('functional.gles3.es3fNegativeBufferApiTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluStrUtil');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+
+ var es3fNegativeBufferApiTests = functional.gles3.es3fNegativeBufferApiTests;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var gluStrUtil = framework.opengl.gluStrUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeBufferApiTests.init = function(gl) {
+
+ var testGroup = tcuTestCase.runner.testCases;
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'bind_buffer', 'Invalid gl.bindBuffer() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the allowable values.');
+ gl.bindBuffer(-1, null);
+ this.expectError(gl.INVALID_ENUM);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'buffer_data', 'Invalid gl.bufferData() usage', gl,
+ function() {
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER.');
+ gl.bufferData(-1, 0, gl.STREAM_DRAW);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if usage is not gl.STREAM_DRAW, gl.STATIC_DRAW, or gl.DYNAMIC_DRAW.');
+ gl.bufferData(gl.ARRAY_BUFFER, 0, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if size is negative.');
+ gl.bufferData(gl.ARRAY_BUFFER, -1, gl.STREAM_DRAW);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.');
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STREAM_DRAW);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(buffer);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'buffer_sub_data', 'Invalid gl.bufferSubData() usage', gl,
+ function() {
+ var buffer = gl.createBuffer();
+ var data = new ArrayBuffer(5);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, 10, gl.STREAM_DRAW);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER.');
+ gl.bufferSubData(-1, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.');
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(buffer);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'buffer_sub_data_size_offset', 'Invalid gl.bufferSubData() usage', gl,
+ function() {
+ var buffer = gl.createBuffer();
+ var data = new ArrayBuffer(5);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, 10, gl.STREAM_DRAW);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if offset is negative');
+ gl.bufferSubData(gl.ARRAY_BUFFER, -1, data);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if the data would be written past the end of the buffer.');
+ gl.bufferSubData(gl.ARRAY_BUFFER, 7, data);
+ this.expectError(gl.INVALID_VALUE);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 15, data);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('An exception is thrown if data is null.');
+ this.expectThrowNoError(function() {
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, null);
+ });
+
+ gl.deleteBuffer(buffer);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'clear', 'Invalid gl.clear() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if any bit other than the three defined bits is set in mask.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ this.expectError(gl.NO_ERROR);
+ gl.clear(0x0200);
+ this.expectError(gl.INVALID_VALUE);
+ gl.clear(0x1000);
+ this.expectError(gl.INVALID_VALUE);
+ gl.clear(0x0010);
+ this.expectError(gl.INVALID_VALUE);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'read_pixels', 'Invalid gl.readPixels() usage', gl,
+ function() {
+ var buffer = new ArrayBuffer(8);
+ var ubyteData = new Uint8Array(buffer);
+ var ushortData = new Uint16Array(buffer);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the combination of format and type is unsupported.');
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the ArrayBuffer type does not match the type parameter.');
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if either width or height is negative.');
+ gl.readPixels(0, 0, -1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ubyteData);
+ this.expectError(gl.INVALID_VALUE);
+ gl.readPixels(0, 0, 1, -1, gl.RGBA, gl.UNSIGNED_BYTE, ubyteData);
+ this.expectError(gl.INVALID_VALUE);
+ gl.readPixels(0, 0, -1, -1, gl.RGBA, gl.UNSIGNED_BYTE, ubyteData);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ubyteData);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'read_pixels_format_mismatch', 'Invalid glReadPixels() usage', gl,
+ function() {
+ var buffer = new ArrayBuffer(8);
+ var ubyteData = new Uint8Array(buffer);
+ var ushortData = new Uint16Array(buffer);
+
+ bufferedLogToConsole('Unsupported combinations of format and type will generate a gl.INVALID_OPERATION error.');
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_SHORT_5_6_5, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.readPixels(0, 0, 1, 1, gl.ALPHA, gl.UNSIGNED_SHORT_5_6_5, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.readPixels(0, 0, 1, 1, gl.RGB, gl.UNSIGNED_SHORT_4_4_4_4, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.readPixels(0, 0, 1, 1, gl.ALPHA, gl.UNSIGNED_SHORT_4_4_4_4, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.readPixels(0, 0, 1, 1, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.readPixels(0, 0, 1, 1, gl.ALPHA, gl.UNSIGNED_SHORT_5_5_5_1, ushortData);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.RGBA/gl.UNSIGNED_BYTE is always accepted and the other acceptable pair can be discovered by querying gl.IMPLEMENTATION_COLOR_READ_FORMAT and gl.IMPLEMENTATION_COLOR_READ_TYPE.');
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ubyteData);
+ this.expectError(gl.NO_ERROR);
+ var readFormat = /** @type {number} */ (gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT));
+ var readType = /** @type {number} */ (gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE));
+ gl.readPixels(0, 0, 1, 1, readFormat, readType, ubyteData);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'read_pixels_fbo_format_mismatch', 'Invalid gl.readPixels() usage', gl,
+ function() {
+ var ubyteData = new Uint8Array(4);
+ var floatData = new Float32Array(4);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if currently bound framebuffer format is incompatible with format and type.');
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, floatData);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32I, 32, 32, 0, gl.RGBA_INTEGER, gl.INT, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, floatData);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, 32, 32, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, floatData);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.READ_FRAMEBUFFER_BINDING is non-zero, the read framebuffer is complete, and the value of gl.SAMPLE_BUFFERS for the read framebuffer is greater than zero.');
+
+ var rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 32, 32);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+
+ var binding = /** @type {WebGLFramebuffer} */ (gl.getParameter(gl.READ_FRAMEBUFFER_BINDING));
+ bufferedLogToConsole('gl.READ_FRAMEBUFFER_BINDING: ' + binding);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ var sampleBuffers = /** @type {number} */ (gl.getParameter(gl.SAMPLE_BUFFERS));
+ bufferedLogToConsole('gl.SAMPLE_BUFFERS: ' + sampleBuffers);
+ this.expectError(gl.NO_ERROR);
+
+ if (binding == null || sampleBuffers <= 0) {
+ this.testFailed('expected gl.READ_FRAMEBUFFER_BINDING to be non-zero and gl.SAMPLE_BUFFERS to be greater than zero');
+ } else {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ubyteData);
+ this.expectError(gl.INVALID_OPERATION);
+ }
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(rbo);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(texture);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'bind_buffer_range', 'Invalid glBindBufferRange() usage', gl,
+ function() {
+ var bufEmpty = new ArrayBuffer(16);
+
+ var bufUniform = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, bufUniform);
+ gl.bufferData(gl.UNIFORM_BUFFER, bufEmpty, gl.STREAM_DRAW);
+
+ var bufTF = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, bufTF);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, bufEmpty, gl.STREAM_DRAW);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.TRANSFORM_FEEDBACK_BUFFER or gl.UNIFORM_BUFFER.');
+ gl.bindBufferRange(gl.ARRAY_BUFFER, 0, bufUniform, 0, 4);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is gl.TRANSFORM_FEEDBACK_BUFFER and index is greater than or equal to gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.');
+ var maxTFSize = /** @type {number} */ (gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS));
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, maxTFSize, bufTF, 0, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is gl.UNIFORM_BUFFER and index is greater than or equal to gl.MAX_UNIFORM_BUFFER_BINDINGS.');
+ var maxUSize = /** @type {number} */ (gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS));
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, maxUSize, bufUniform, 0, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if size is less than or equal to zero.');
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufUniform, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufUniform, 0, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is gl.TRANSFORM_FEEDBACK_BUFFER and size or offset are not multiples of 4.');
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufTF, 4, 5);
+ this.expectError(gl.INVALID_VALUE);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufTF, 5, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufTF, 5, 7);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is gl.UNIFORM_BUFFER and offset is not a multiple of gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT.');
+ var alignment = /** @type {number} */ (gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT));
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufUniform, alignment + 1, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteBuffer(bufUniform);
+ gl.deleteBuffer(bufTF);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'bind_buffer_base', 'Invalid glBindBufferBase() usage', gl,
+ function() {
+ var bufEmpty = new ArrayBuffer(16);
+
+ var bufUniform = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, bufUniform);
+ gl.bufferData(gl.UNIFORM_BUFFER, bufEmpty, gl.STREAM_DRAW);
+
+ var bufTF = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, bufTF);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, bufEmpty, gl.STREAM_DRAW);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.TRANSFORM_FEEDBACK_BUFFER or gl.UNIFORM_BUFFER.');
+ gl.bindBufferBase(-1, 0, bufUniform);
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindBufferBase(gl.ARRAY_BUFFER, 0, bufUniform);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is gl.UNIFORM_BUFFER and index is greater than or equal to gl.MAX_UNIFORM_BUFFER_BINDINGS.');
+ var maxUSize = /** @type {number} */ (gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS));
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, maxUSize, bufUniform);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is gl.TRANSFORM_FEEDBACK_BUFFER andindex is greater than or equal to gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.');
+ var maxTFSize = /** @type {number} */ (gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS));
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, maxTFSize, bufTF);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteBuffer(bufUniform);
+ gl.deleteBuffer(bufTF);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'clear_bufferiv', 'Invalid gl.clearBufferiv() usage', gl,
+ function() {
+ var data = new Int32Array(32 * 32);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32I, 32, 32, 0, gl.RGBA_INTEGER, gl.INT, null);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is not an accepted value.');
+ gl.clearBufferiv(-1, 0, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferiv(gl.FRAMEBUFFER, 0, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if buffer is gl.COLOR, gl.FRONT, gl.BACK, gl.LEFT, gl.RIGHT, or gl.FRONT_AND_BACK and drawBuffer is greater than or equal to gl.MAX_DRAW_BUFFERS.');
+ var maxDrawBuffers = /** @type {number} */ (gl.getParameter(gl.MAX_DRAW_BUFFERS));
+ gl.clearBufferiv(gl.COLOR, maxDrawBuffers, data);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is gl.DEPTH or gl.DEPTH_STENCIL.');
+ gl.clearBufferiv(gl.DEPTH, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferiv(gl.DEPTH_STENCIL, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if buffer is gl.STENCIL and drawBuffer is not zero.');
+ gl.clearBufferiv(gl.STENCIL, 1, data);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'clear_bufferuiv', 'Invalid gl.clearBufferuiv() usage', gl,
+ function() {
+ var data = new Uint32Array(32 * 32);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, 32, 32, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, null);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is not an accepted value.');
+ gl.clearBufferuiv(-1, 0, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferuiv(gl.FRAMEBUFFER, 0, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if buffer is gl.COLOR, gl.FRONT, gl.BACK, gl.LEFT, gl.RIGHT, or gl.FRONT_AND_BACK and drawBuffer is greater than or equal to gl.MAX_DRAW_BUFFERS.');
+ var maxDrawBuffers = /** @type {number} */ (gl.getParameter(gl.MAX_DRAW_BUFFERS));
+ gl.clearBufferuiv(gl.COLOR, maxDrawBuffers, data);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is gl.DEPTH, gl.STENCIL or gl.DEPTH_STENCIL.');
+ gl.clearBufferuiv(gl.DEPTH, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferuiv(gl.STENCIL, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferuiv(gl.DEPTH_STENCIL, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'clear_bufferfv', 'Invalid gl.clearBufferfv() usage', gl,
+ function() {
+ var data = new Float32Array(32 * 32);
+
+ var texture = gl.createTexture();
+ // Float type texture isn't color-renderable without EXT_color_buffer_float extension.
+ if (gl.getExtension('EXT_color_buffer_float')) {
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 32, 32, 0, gl.RGBA, gl.FLOAT, null);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is not an accepted value.');
+ gl.clearBufferfv(-1, 0, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferfv(gl.FRAMEBUFFER, 0, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if buffer is gl.COLOR, gl.FRONT, gl.BACK, gl.LEFT, gl.RIGHT, or gl.FRONT_AND_BACK and drawBuffer is greater than or equal to gl.MAX_DRAW_BUFFERS.');
+ var maxDrawBuffers = /** @type {number} */ (gl.getParameter(gl.MAX_DRAW_BUFFERS));
+ gl.clearBufferfv(gl.COLOR, maxDrawBuffers, data);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is gl.STENCIL or gl.DEPTH_STENCIL.');
+ gl.clearBufferfv(gl.STENCIL, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferfv(gl.DEPTH_STENCIL, 1, data);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if buffer is gl.DEPTH and drawBuffer is not zero.');
+ gl.clearBufferfv(gl.DEPTH, 1, data);
+ this.expectError(gl.INVALID_VALUE);
+ }
+
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'clear_bufferfi', 'Invalid gl.clearBufferfi() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is not an accepted value.');
+ gl.clearBufferfi(-1, 0, 1.0, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferfi(gl.FRAMEBUFFER, 0, 1.0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if buffer is not gl.DEPTH_STENCIL.');
+ gl.clearBufferfi(gl.DEPTH, 0, 1.0, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferfi(gl.STENCIL, 0, 1.0, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.clearBufferfi(gl.COLOR, 0, 1.0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if buffer is gl.DEPTH_STENCIL and drawBuffer is not zero.');
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 1, 1.0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'copy_buffer_sub_data', 'Invalid gl.copyBufferSubData() usage', gl,
+ function() {
+ var buf = {
+ r: gl.createBuffer(),
+ w: gl.createBuffer()
+ };
+
+ gl.bindBuffer(gl.COPY_READ_BUFFER, buf.r);
+ gl.bufferData(gl.COPY_READ_BUFFER, 32, gl.DYNAMIC_COPY);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, buf.w);
+ gl.bufferData(gl.COPY_WRITE_BUFFER, 32, gl.DYNAMIC_COPY);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if any of readoffset, writeoffset or size is negative.');
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, -4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, -1, 0, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, -1, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if readoffset + size exceeds the size of the buffer object bound to readtarget.');
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 36);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 24, 0, 16);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 36, 0, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if writeoffset + size exceeds the size of the buffer object bound to writetarget.');
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 36);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 24, 16);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 36, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if the same buffer object is bound to both readtarget and writetarget and the ranges [readoffset, readoffset + size) and [writeoffset, writeoffset + size) overlap.');
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, buf.r);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 16, 4);
+ this.expectError(gl.NO_ERROR);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 16, 18);
+ this.expectError(gl.INVALID_VALUE);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, buf.w);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if null is bound to readtarget or writetarget.');
+ gl.bindBuffer(gl.COPY_READ_BUFFER, null);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 16);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindBuffer(gl.COPY_READ_BUFFER, buf.r);
+
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 16);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, buf.w);
+
+ gl.deleteBuffer(buf.w);
+ gl.deleteBuffer(buf.r);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'draw_buffers', 'Invalid glDrawBuffers() usage', gl,
+ function() {
+ var maxDrawBuffers = /** @type {number} */ (gl.getParameter(gl.MAX_DRAW_BUFFERS));
+ var values = [
+ gl.NONE,
+ gl.BACK,
+ gl.COLOR_ATTACHMENT0,
+ gl.DEPTH_ATTACHMENT
+ ];
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if one of the values in bufs is not an accepted value.');
+ gl.drawBuffers(values.slice(2, 4));
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the GL is bound to the default framebuffer and the number of queried buffers is not 1.');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.drawBuffers(values.slice(0, 2));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the GL is bound to the default framebuffer and the value in bufs is one of the gl.COLOR_ATTACHMENTn tokens.');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.drawBuffers(values.slice(2, 3));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the GL is bound to a framebuffer object and the ith buffer listed in bufs is anything other than gl.NONE or gl.COLOR_ATTACHMENTSi.');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.drawBuffers(values.slice(1, 2));
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ // Framebuffer Objects
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'bind_framebuffer', 'Invalid glBindFramebuffer() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.FRAMEBUFFER.');
+ gl.bindFramebuffer(-1, null);
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindFramebuffer(gl.RENDERBUFFER, null);
+ this.expectError(gl.INVALID_ENUM);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'bind_renderbuffer', 'Invalid glBindRenderbuffer() usage', gl,
+ function() {
+ bufferedLogToConsole('glINVALID_ENUM is generated if target is not gl.RENDERBUFFER.');
+ gl.bindRenderbuffer(-1, null);
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindRenderbuffer(gl.FRAMEBUFFER, null);
+ this.expectError(gl.INVALID_ENUM);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'check_framebuffer_status', 'Invalid glCheckFramebufferStatus() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.FRAMEBUFFER.');
+ gl.checkFramebufferStatus(-1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.checkFramebufferStatus(gl.RENDERBUFFER);
+ this.expectError(gl.INVALID_ENUM);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'framebuffer_renderbuffer', 'Invalid glFramebufferRenderbuffer() usage', gl,
+ function() {
+ var rbo = gl.createRenderbuffer();
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted tokens.');
+ gl.framebufferRenderbuffer(-1, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if renderbuffertarget is not gl.RENDERBUFFER.');
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, -1, rbo);
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if zero is bound to target.');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteRenderbuffer(rbo);
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'framebuffer_texture2d', 'Invalid glFramebufferTexture2D() usage', gl,
+ function() {
+
+ var fbo = gl.createFramebuffer();
+ var tex2D = gl.createTexture();
+ var texCube = gl.createTexture();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.bindTexture(gl.TEXTURE_2D, tex2D);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted tokens.');
+ gl.framebufferTexture2D(-1, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if textarget is not an accepted texture target.');
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, -1, tex2D, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0 or larger than log_2 of maximum texture size.');
+ var maxTexSize = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_SIZE));
+ var maxCubeTexSize = /** @type {number} */ (gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE));
+ var maxSizePlane = Math.floor(Math.log2(maxTexSize)) + 1;
+ var maxSizeCube = Math.floor(Math.log2(maxCubeTexSize)) + 1;
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2D, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2D, maxSizePlane);
+ this.expectError(gl.INVALID_VALUE);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, texCube, maxSizeCube);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if textarget and texture are not compatible.');
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex2D, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.deleteTexture(tex2D);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texCube, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.deleteTexture(texCube);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if zero is bound to target.');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'renderbuffer_storage', 'Invalid glRenderbufferStorage() usage', gl,
+ function() {
+ var rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.RENDERBUFFER.');
+ gl.renderbufferStorage(-1, gl.RGBA4, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.renderbufferStorage(gl.FRAMEBUFFER, gl.RGBA4, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if internalformat is not a color-renderable, depth-renderable, or stencil-renderable format.');
+ gl.renderbufferStorage(gl.RENDERBUFFER, -1, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ // EXT_color_buffer_half_float disables error
+ if (gl.getExtension('EXT_color_buffer_half_float') === null) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB16F, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+ }
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8_SNORM, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than zero.');
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, -1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 1, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, -1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is greater than gl.MAX_RENDERBUFFER_SIZE.');
+ var maxSize = /** @type {number} */ (gl.getParameter(gl.MAX_RENDERBUFFER_SIZE));
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 1, maxSize + 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, maxSize + 1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, maxSize + 1, maxSize + 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.deleteRenderbuffer(rbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'blit_framebuffer', 'Invalid glBlitFramebuffer() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */
+ var texture = [
+ gl.createTexture(), gl.createTexture()
+ ];
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+
+ /** @type {Array<WebGLRenderbuffer>} */
+ var rbo = [
+ gl.createRenderbuffer(), gl.createRenderbuffer()
+ ];
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo[0]);
+
+ /** @type {Array<WebGLFramebuffer>} */
+ var fbo = [
+ gl.createFramebuffer(), gl.createFramebuffer()
+ ];
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo[0]);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, 32, 32);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo[0]);
+ gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER);
+ gl.bindTexture(gl.TEXTURE_2D, texture[1]);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo[1]);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo[1]);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, 32, 32);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[1], 0);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo[1]);
+ gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if mask contains any of the gl.DEPTH_BUFFER_BIT or gl.STENCIL_BUFFER_BIT and filter is not gl.NEAREST.');
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, gl.LINEAR);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.LINEAR);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, gl.LINEAR);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if mask contains gl.COLOR_BUFFER_BIT and read buffer format is incompatible with draw buffer format.');
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, 32, 32, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, null);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ bufferedLogToConsole('// Read buffer: gl.RGBA32UI, draw buffer: gl.RGBA');
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32I, 32, 32, 0, gl.RGBA_INTEGER, gl.INT, null);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ bufferedLogToConsole('// Read buffer: gl.RGBA32I, draw buffer: gl.RGBA');
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ gl.bindTexture(gl.TEXTURE_2D, texture[1]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32I, 32, 32, 0, gl.RGBA_INTEGER, gl.INT, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[1], 0);
+ bufferedLogToConsole('// Read buffer: gl.RGBA8, draw buffer: gl.RGBA32I');
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if filter is gl.LINEAR and the read buffer contains integer data.');
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, 32, 32, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, null);
+ gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0);
+ gl.bindTexture(gl.TEXTURE_2D, texture[1]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, 32, 32, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, null);
+ gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[1], 0);
+ bufferedLogToConsole('// Read buffer: gl.RGBA32UI, filter: gl.LINEAR');
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT, gl.LINEAR);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if mask contains gl.DEPTH_BUFFER_BIT or gl.STENCIL_BUFFER_BIT and the source and destination depth and stencil formats do not match.');
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo[0]);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH32F_STENCIL8, 32, 32);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo[0]);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.DEPTH_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.STENCIL_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo[1]);
+ gl.deleteFramebuffer(fbo[0]);
+ gl.deleteTexture(texture[1]);
+ gl.deleteTexture(texture[0]);
+ gl.deleteRenderbuffer(rbo[1]);
+ gl.deleteRenderbuffer(rbo[0]);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'blit_framebuffer_multisample', 'Invalid glBlitFramebuffer() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLRenderbuffer>} */
+ var rbo = [
+ gl.createRenderbuffer(), gl.createRenderbuffer()
+ ];
+ /** @type {Array<WebGLFramebuffer>} */
+ var fbo = [
+ gl.createFramebuffer(), gl.createFramebuffer()
+ ];
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo[0]);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo[0]);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 32, 32);
+ gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo[0]);
+ gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER);
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo[1]);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo[1]);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the value of gl.SAMPLE_BUFFERS for the draw buffer is greater than zero.');
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 32, 32);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo[1]);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.SAMPLE_BUFFERS for the read buffer is greater than zero and the formats of draw and read buffers are not identical.');
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 32, 32);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo[1]);
+ gl.blitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.SAMPLE_BUFFERS for the read buffer is greater than zero and the source and destination rectangles are not defined with the same (X0, Y0) and (X1, Y1) bounds.');
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 32, 32);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo[1]);
+ gl.blitFramebuffer(0, 0, 16, 16, 2, 2, 18, 18, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteRenderbuffer(rbo[0]);
+ gl.deleteRenderbuffer(rbo[1]);
+ gl.deleteFramebuffer(fbo[0]);
+ gl.deleteFramebuffer(fbo[1]);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'framebuffer_texture_layer', 'Invalid glFramebufferTextureLayer() usage', gl,
+ function() {
+
+ var fbo = gl.createFramebuffer();
+ var tex3D = gl.createTexture();
+ var tex2DArray = gl.createTexture();
+ var tex2D = gl.createTexture();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ gl.bindTexture(gl.TEXTURE_3D, tex3D);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex2DArray);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_2D, tex2D);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted tokens.');
+ gl.framebufferTextureLayer(-1, gl.COLOR_ATTACHMENT0, tex3D, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.framebufferTextureLayer(gl.RENDERBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if attachment is not one of the accepted tokens.');
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, -1, tex3D, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.BACK, tex3D, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if texture is non-zero and not the name of a 3D texture or 2D array texture.');
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if texture is not zero and layer is negative.');
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if texture is not zero and layer is greater than gl.MAX_3D_TEXTURE_SIZE-1 for a 3D texture.');
+ var max3DTexSize = /** @type {number} */ (gl.getParameter(gl.MAX_3D_TEXTURE_SIZE));
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, max3DTexSize);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if texture is not zero and layer is greater than gl.MAX_ARRAY_TEXTURE_LAYERS-1 for a 2D array texture.');
+ var maxArrayTexLayers = /** @type {number} */ (gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS));
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2DArray, 0, maxArrayTexLayers);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if zero is bound to target.');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(tex3D);
+ gl.deleteTexture(tex2DArray);
+ gl.deleteTexture(tex2D);
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'invalidate_framebuffer', 'Invalid gl.invalidateFramebuffer() usage', gl,
+ function() {
+ var maxColorAttachments = /** @type {number} */ (gl.getParameter(gl.MAX_COLOR_ATTACHMENTS));
+ var attachments = [
+ gl.COLOR_ATTACHMENT0
+ ];
+
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.FRAMEBUFFER, gl.READ_FRAMEBUFFER or gl.DRAW_FRAMEBUFFER.');
+ gl.invalidateFramebuffer(-1, attachments);
+ this.expectError(gl.INVALID_ENUM);
+ gl.invalidateFramebuffer(gl.BACK, attachments);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if attachments contains gl.COLOR_ATTACHMENTm and m is greater than or equal to the value of gl.MAX_COLOR_ATTACHMENTS.');
+ gl.invalidateFramebuffer(gl.FRAMEBUFFER, [gl.COLOR_ATTACHMENT0 + maxColorAttachments]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'invalidate_sub_framebuffer', 'Invalid gl.invalidateSubFramebuffer() usage', gl,
+ function() {
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ var maxColorAttachments = /** @type {number} */ (gl.getParameter(gl.MAX_COLOR_ATTACHMENTS));
+ var att0 = [gl.COLOR_ATTACHMENT0];
+ var attm = [gl.COLOR_ATTACHMENT0 + maxColorAttachments];
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.FRAMEBUFFER, gl.READ_FRAMEBUFFER or gl.DRAW_FRAMEBUFFER.');
+ gl.invalidateSubFramebuffer(-1, att0, 0, 0, 16, 16);
+ this.expectError(gl.INVALID_ENUM);
+ gl.invalidateSubFramebuffer(gl.BACK, att0, 0, 0, 16, 16);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if attachments contains gl.COLOR_ATTACHMENTm and m is greater than or equal to the value of gl.MAX_COLOR_ATTACHMENTS.');
+ gl.invalidateSubFramebuffer(gl.FRAMEBUFFER, attm, 0, 0, 16, 16);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteFramebuffer(fbo);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'renderbuffer_storage_multisample', 'Invalid glRenderbufferStorageMultisample() usage', gl,
+ function() {
+
+ var rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ /** @type {Int32Array} */ var samplesSupportedRGBA4 = /** @type {Int32Array} */ gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA4, gl.SAMPLES);
+ // supported samples are written in descending numeric order, so the first one is the max samples
+ var maxSamplesSupportedRGBA4 = samplesSupportedRGBA4[0];
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.RENDERBUFFER.');
+ gl.renderbufferStorageMultisample(-1, 2, gl.RGBA4, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.renderbufferStorageMultisample(gl.FRAMEBUFFER, 2, gl.RGBA4, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if samples is greater than the maximum number of samples supported for internalformat.');
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, maxSamplesSupportedRGBA4 + 1, gl.RGBA4, 1, 1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if internalformat is not a color-renderable, depth-renderable, or stencil-renderable format.');
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, -1, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ // EXT_color_buffer_half_float disables error
+ if (gl.getExtension('EXT_color_buffer_half_float') === null) {
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, gl.RGB16F, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+ }
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, gl.RGBA8_SNORM, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than zero.');
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, gl.RGBA4, -1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, gl.RGBA4, 1, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 2, gl.RGBA4, -1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is greater than gl.MAX_RENDERBUFFER_SIZE.');
+ var maxSize = /** @type {number} */ (gl.getParameter(gl.MAX_RENDERBUFFER_SIZE));
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA4, 1, maxSize + 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA4, maxSize + 1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA4, maxSize + 1, maxSize + 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteRenderbuffer(rbo);
+ }
+ ));
+
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeBufferApiTests.run = function(gl) {
+ var testName = 'negativeBufferApi';
+ var testDescription = 'Negative Buffer API tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fNegativeBufferApiTests.init(gl);
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeFragmentApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeFragmentApiTests.js
new file mode 100644
index 0000000000..c3675d436f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeFragmentApiTests.js
@@ -0,0 +1,339 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative Fragment Pipe API tests.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('functional.gles3.es3fNegativeFragmentApiTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+
+ var es3fNegativeFragmentApiTests = functional.gles3.es3fNegativeFragmentApiTests;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeFragmentApiTests.init = function(gl) {
+
+ var testGroup = tcuTestCase.runner.testCases;
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('scissor', 'Invalid gl.scissor() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if either width or height is negative.');
+ gl.scissor(0, 0, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.scissor(0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.scissor(0, 0, -1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('depth_func', 'Invalid gl.depthFunc() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if func is not an accepted value.');
+ gl.depthFunc(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('viewport', 'Invalid gl.viewport() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if either width or height is negative.');
+ gl.viewport(0, 0, -1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.viewport(0, 0, 1, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.viewport(0, 0, -1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ // Stencil functions
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('stencil_func', 'Invalid gl.stencilFunc() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if func is not one of the eight accepted values.');
+ gl.stencilFunc(-1, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('stencil_func_separate', 'Invalid gl.stencilFuncSeparate() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if face is not gl.FRONT, gl.BACK, or gl.FRONT_AND_BACK.');
+ gl.stencilFuncSeparate(-1, gl.NEVER, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if func is not one of the eight accepted values.');
+ gl.stencilFuncSeparate(gl.FRONT, -1, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('stencil_op', 'Invalid gl.stencilOp() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if sfail, dpfail, or dppass is any value other than the defined symbolic constant values.');
+ gl.stencilOp(-1, gl.ZERO, gl.REPLACE);
+ this.expectError(gl.INVALID_ENUM);
+ gl.stencilOp(gl.KEEP, -1, gl.REPLACE);
+ this.expectError(gl.INVALID_ENUM);
+ gl.stencilOp(gl.KEEP, gl.ZERO, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('stencil_op_separate', 'Invalid gl.stencilOpSeparate() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if face is any value other than gl.FRONT, gl.BACK, or gl.FRONT_AND_BACK.');
+ gl.stencilOpSeparate(-1, gl.KEEP, gl.ZERO, gl.REPLACE);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if sfail, dpfail, or dppass is any value other than the eight defined symbolic constant values.');
+ gl.stencilOpSeparate(gl.FRONT, -1, gl.ZERO, gl.REPLACE);
+ this.expectError(gl.INVALID_ENUM);
+ gl.stencilOpSeparate(gl.FRONT, gl.KEEP, -1, gl.REPLACE);
+ this.expectError(gl.INVALID_ENUM);
+ gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.ZERO, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('stencil_mask_separate', 'Invalid gl.stencilMaskSeparate() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if face is not gl.FRONT, gl.BACK, or gl.FRONT_AND_BACK.');
+ gl.stencilMaskSeparate(-1, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ // Blend functions
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('blend_equation', 'Invalid gl.blendEquation() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not gl.FUNC_ADD, gl.FUNC_SUBTRACT, gl.FUNC_REVERSE_SUBTRACT, gl.MAX or gl.MIN.');
+ gl.blendEquation(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('blend_equation_separate', 'Invalid gl.blendEquationSeparate() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if modeRGB is not gl.FUNC_ADD, gl.FUNC_SUBTRACT, gl.FUNC_REVERSE_SUBTRACT, gl.MAX or gl.MIN.');
+ gl.blendEquationSeparate(-1, gl.FUNC_ADD);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if modeAlpha is not gl.FUNC_ADD, gl.FUNC_SUBTRACT, gl.FUNC_REVERSE_SUBTRACT, gl.MAX or gl.MIN.');
+ gl.blendEquationSeparate(gl.FUNC_ADD, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('blend_func', 'Invalid gl.blendFunc() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if either sfactor or dfactor is not an accepted value.');
+ gl.blendFunc(-1, gl.ONE);
+ this.expectError(gl.INVALID_ENUM);
+ gl.blendFunc(gl.ONE, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('blend_func_separate', 'Invalid gl.blendFuncSeparate() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if srcRGB, dstRGB, srcAlpha, or dstAlpha is not an accepted value.');
+ gl.blendFuncSeparate(-1, gl.ONE, gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.blendFuncSeparate(gl.ZERO, -1, gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.blendFuncSeparate(gl.ZERO, gl.ONE, -1, gl.ONE_MINUS_SRC_COLOR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.blendFuncSeparate(gl.ZERO, gl.ONE, gl.SRC_COLOR, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ // Rasterization API functions
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('cull_face', 'Invalid gl.cullFace() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.cullFace(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('front_face', 'Invalid gl.frontFace() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.frontFace(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('line_width', 'Invalid gl.lineWidth() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width is less than or equal to 0.');
+ gl.lineWidth(0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.lineWidth(-1);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('begin_query', 'Invalid gl.beginQuery() usage', gl, function() {
+ /** @type{Array<WebGLQuery>} */ var ids = [];
+ ids[0] = gl.createQuery();
+ ids[1] = gl.createQuery();
+ ids[2] = gl.createQuery();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted tokens.');
+ gl.beginQuery(-1, ids[0]);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.beginQuery is executed while a query object of the same target is already active.');
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, ids[0]);
+ this.expectError(gl.NO_ERROR);
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, ids[1]);
+ this.expectError(gl.INVALID_OPERATION);
+ // \note gl.ANY_SAMPLES_PASSED and gl.ANY_SAMPLES_PASSED_CONSERVATIVE alias to the same target for the purposes of this error.
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED_CONSERVATIVE, ids[1]);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[1]);
+ this.expectError(gl.NO_ERROR);
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[2]);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('An exception is thrown if the name is null.');
+ this.expectThrowNoError(function() {
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, null);
+ });
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the name has since been deleted with gl.deleteQuery.');
+ gl.deleteQuery(ids[2]);
+ this.expectError(gl.NO_ERROR);
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, ids[2]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if id is the name of an already active query object.');
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, ids[0]);
+ this.expectError(gl.NO_ERROR);
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[0]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if id refers to an existing query object whose type does not does not match target.');
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ this.expectError(gl.NO_ERROR);
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[0]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteQuery(ids[0]);
+ gl.deleteQuery(ids[1]);
+ gl.deleteQuery(ids[2]);
+ this.expectError(gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('end_query', 'Invalid gl.endQuery() usage', gl, function() {
+ /** @type{WebGLQuery} */ var id;
+ id = gl.createQuery();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted tokens.');
+ gl.endQuery(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.endQuery is executed when a query object of the same target is not active.');
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, id);
+ this.expectError(gl.NO_ERROR);
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ this.expectError(gl.NO_ERROR);
+
+ gl.deleteQuery(id);
+ this.expectError(gl.NO_ERROR);
+ }));
+
+ // Sync objects
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('fence_sync', 'Invalid gl.fenceSync() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if condition is not gl.SYNC_GPU_COMMANDS_COMPLETE.');
+ gl.fenceSync(-1, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if flags is not zero.');
+ gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0x0010);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('wait_sync', 'Invalid gl.waitSync() usage', gl, function() {
+ /** @type{WebGLSync} */ var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ bufferedLogToConsole('An exception is thrown if sync is null.');
+ this.expectThrowNoError(function() {
+ gl.waitSync(null, 0, gl.TIMEOUT_IGNORED);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if flags is not zero.');
+ gl.waitSync(sync, 0x0010, gl.TIMEOUT_IGNORED);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if timeout is not gl.TIMEOUT_IGNORED.');
+ gl.waitSync(sync, 0, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteSync(sync);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('client_wait_sync', 'Invalid gl.clientWaitSync() usage', gl, function() {
+ /** @type{WebGLSync} */ var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ bufferedLogToConsole('An exception is thrown if sync is null.');
+ this.expectThrowNoError(function() {
+ gl.clientWaitSync (null, 0, 0);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if flags contains any unsupported flag.');
+ gl.clientWaitSync(sync, 0x00000004, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteSync(sync);
+ }));
+
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeFragmentApiTests.run = function(gl) {
+ var testName = 'negativeFragmentApi';
+ var testDescription = 'Negative Fragment API tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fNegativeFragmentApiTests.init(gl);
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeShaderApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeShaderApiTests.js
new file mode 100644
index 0000000000..6e48dab60d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeShaderApiTests.js
@@ -0,0 +1,1195 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fNegativeShaderApiTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+
+ var es3fNegativeShaderApiTests = functional.gles3.es3fNegativeShaderApiTests;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var vertexShaderSource = '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var fragmentShaderSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var uniformTestVertSource = '#version 300 es\n' +
+ 'uniform mediump vec4 vec4_v;\n' +
+ 'uniform mediump mat4 mat4_v;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = mat4_v * vec4_v;\n' +
+ '}\n';
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var uniformTestFragSource = '#version 300 es\n' +
+ 'uniform mediump ivec4 ivec4_f;\n' +
+ 'uniform mediump uvec4 uvec4_f;\n' +
+ 'uniform sampler2D sampler_f;\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor.xy = (vec4(uvec4_f) + vec4(ivec4_f)).xy;\n' +
+ ' fragColor.zw = texture(sampler_f, vec2(0.0, 0.0)).zw;\n' +
+ '}\n';
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var uniformBlockVertSource = '#version 300 es\n' +
+ 'layout(std140) uniform Block { lowp float var; };\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(var);\n' +
+ '}\n';
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeShaderApiTests.init = function(gl) {
+ var testGroup = tcuTestCase.runner.testCases;
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'create_shader', 'Invalid gl.createShader() usage', gl,
+ function() {
+ bufferedLogToConsole('INVALID_ENUM is generated if shaderType is not an accepted value.');
+ gl.createShader(-1);
+ this.expectError(gl.INVALID_ENUM);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('attach_shader', 'Invalid gl.attachShader() usage', gl,
+ function() {
+ /** @type {WebGLShader} */ var shader1 = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {WebGLShader} */ var shader2 = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {WebGLProgram} */ var program = gl.createProgram();
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if shader is already attached to program.');
+ gl.attachShader(program, shader1);
+ this.expectError(gl.NO_ERROR);
+ gl.attachShader(program, shader1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if a shader of the same type as shader is already attached to program.');
+ gl.attachShader(program, shader2);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteProgram(program);
+ gl.deleteShader(shader1);
+ gl.deleteShader(shader2);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('detach_shader', 'Invalid gl.detachShader() usage', gl,
+ function() {
+ /** @type {WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {WebGLProgram} */ var program = gl.createProgram();
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if shader is not attached to program.');
+ gl.detachShader(program, shader);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteProgram(program);
+ gl.deleteShader(shader);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('link_program', 'Invalid gl.linkProgram() usage', gl,
+ function() {
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if program is the currently active program object and transform feedback mode is active.');
+
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {WebGLTransformFeedback} */ var tfID;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ tfID = gl.createTransformFeedback();
+ buf = gl.createBuffer();
+
+ gl.useProgram(program.getProgram());
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+
+ this.expectError(gl.NO_ERROR);
+
+ gl.linkProgram(program.getProgram());
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.endTransformFeedback();
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(buf);
+ this.expectError(gl.NO_ERROR);
+
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('use_program', 'Invalid gl.useProgram() usage', gl,
+ function() {
+
+ /** @type {WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback mode is active and not paused.');
+ /** @type {gluShaderProgram.ShaderProgram} */ var program1 = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {gluShaderProgram.ShaderProgram} */ var program2 = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {WebGLTransformFeedback} */ var tfID;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ tfID = gl.createTransformFeedback();
+ buf = gl.createBuffer();
+
+ gl.useProgram(program1.getProgram());
+ gl.transformFeedbackVaryings(program1.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program1.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ this.expectError(gl.NO_ERROR);
+
+ gl.useProgram(program2.getProgram());
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.pauseTransformFeedback();
+ gl.useProgram(program2.getProgram());
+ this.expectError(gl.NO_ERROR);
+
+ gl.endTransformFeedback();
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(buf);
+ this.expectError(gl.NO_ERROR);
+
+ gl.useProgram(null);
+ gl.deleteShader(shader);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('bind_sampler', 'Invalid gl.bindSampler() usage', gl,
+ function() {
+ /** @type {number} */ var maxTexImageUnits;
+ /** @type {WebGLSampler} */ var sampler;
+ /** @type {WebGLSampler} */ var buf;
+ maxTexImageUnits = /** @type {number} */ (gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
+ sampler = gl.createSampler();
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if unit is greater than or equal to the value of gl.MAX_COMBIED_TEXTURE_IMAGE_UNITS.');
+ gl.bindSampler(maxTexImageUnits, sampler);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if sampler has been deleted by a call to glDeleteSamplers.');
+ gl.deleteSampler(sampler);
+ gl.bindSampler(1, sampler);
+ this.expectError(gl.INVALID_OPERATION);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_sampler_parameteriv', 'Invalid gl.getSamplerParameter() usage', gl,
+ function() {
+ /** @type {number} */ var params;
+ /** @type {WebGLSampler} */ var sampler;
+ sampler = gl.createSampler();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ params = /** @type {number} */ (gl.getSamplerParameter(sampler, -1));
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteSampler(sampler);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_sampler_parameterfv', 'Invalid gl.getSamplerParameter() usage', gl,
+ function() {
+ /** @type {number} */ var params;
+ /** @type {WebGLSampler} */ var sampler;
+ sampler = gl.createSampler();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ params = /** @type {number} */ (gl.getSamplerParameter(sampler, -1));
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteSampler(sampler);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('sampler_parameteri', 'Invalid gl.samplerParameteri() usage', gl,
+ function() {
+ /** @type {WebGLSampler} */ var sampler;
+ sampler = gl.createSampler();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.');
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteSampler(sampler);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'sampler_parameteriv', 'Invalid gl.samplerParameteri() usage', gl,
+ function() {
+ /** @type {number} */ var params;
+ /** @type {WebGLSampler} */ var sampler;
+ sampler = gl.createSampler();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.');
+ params = -1;
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, params);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteSampler(sampler);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'sampler_parameterf', 'Invalid glSamplerParameterf() usage', gl,
+ function() {
+ /** @type {WebGLSampler} */ var sampler;
+ sampler = gl.createSampler();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.');
+ gl.samplerParameterf(sampler, gl.TEXTURE_WRAP_S, -1.0);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteSampler(sampler);
+ }
+ ));
+
+ // Shader data commands
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'get_attrib_location', 'Invalid gl.getAttribLocation() usage', gl,
+ function() {
+ /** @type {WebGLProgram} */ var programEmpty = gl.createProgram();
+ /** @type {WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if program has not been successfully linked.');
+ gl.bindAttribLocation(programEmpty, 0, 'test');
+ gl.getAttribLocation(programEmpty, 'test');
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ gl.deleteShader(shader);
+ gl.deleteProgram(programEmpty);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'get_uniform_location', 'Invalid gl.getUniformLocation() usage', gl,
+ function() {
+ /** @type {WebGLProgram} */ var programEmpty = gl.createProgram();
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if program has not been successfully linked.');
+ gl.getUniformLocation(programEmpty, 'test');
+ this.expectError(gl.INVALID_OPERATION);
+ gl.deleteProgram(programEmpty);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback(
+ 'bind_attrib_location', 'Invalid gl.bindAttribLocation() usage', gl,
+ function() {
+ /** @type {WebGLProgram} */ var program = gl.createProgram();
+ var maxIndex = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ gl.bindAttribLocation(program, maxIndex, 'test');
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if name starts with the reserved prefix \'gl.\'.');
+ gl.bindAttribLocation(program, maxIndex-1, 'gl_test');
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteProgram(program);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniform_block_binding', 'Invalid gl.uniformBlockBinding() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformBlockVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+
+ /** @type {number} */ var maxUniformBufferBindings;
+ /** @type {number} */ var numActiveUniforms = -1;
+ /** @type {number} */ var numActiveBlocks = -1;
+ maxUniformBufferBindings = /** @type {number} */ (gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS));
+ numActiveUniforms = /** @type {number} */ (gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORMS));
+ numActiveBlocks = /** @type {number} */ (gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORM_BLOCKS));
+ bufferedLogToConsole('// gl.MAX_UNIFORM_BUFFER_BINDINGS = ' + maxUniformBufferBindings);
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORMS = ' + numActiveUniforms);
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORM_BLOCKS = ' + numActiveBlocks);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if uniformBlockIndex is not an active uniform block index of program.');
+ gl.uniformBlockBinding(program.getProgram(), -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.uniformBlockBinding(program.getProgram(), 5, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if uniformBlockBinding is greater than or equal to the value of gl.MAX_UNIFORM_BUFFER_BINDINGS.');
+ gl.uniformBlockBinding(program.getProgram(), maxUniformBufferBindings, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.uniformBlockBinding(null, 0, 0);
+ });
+ }
+ ));
+
+ // glUniform*f
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformf_incompatible_type', 'Invalid glUniform{1234}f() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null || ivec4_f == null || uvec4_f == null || sampler_f == null) {
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+ }
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1f(vec4_v, 0.0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2f(vec4_v, 0.0, 0.0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3f(vec4_v, 0.0, 0.0, 0.0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4f(vec4_v, 0.0, 0.0, 0.0, 0.0);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}f is used to load a uniform variable of type int, ivec2, ivec3, ivec4, unsigned int, uvec2, uvec3, uvec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform4f(ivec4_f, 0.0, 0.0, 0.0, 0.0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4f(uvec4_f, 0.0, 0.0, 0.0, 0.0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1f(sampler_f, 0.0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformfv_incompatible_type', 'Invalid glUniform{1234}fv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null || ivec4_f == null || uvec4_f == null || sampler_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Float32Array} */ var data = new Float32Array(4);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1fv(vec4_v, new Float32Array(1));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2fv(vec4_v, new Float32Array(2));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3fv(vec4_v, new Float32Array(3));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4fv(vec4_v, new Float32Array(4));
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}fv is used to load a uniform variable of type /** @type {number} */ var , ivec2, ivec3, ivec4, unsigned /** @type {number} */ var , uvec2, uvec3, uvec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform4fv(ivec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4fv(uvec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1fv(sampler_f, new Float32Array(1));
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformfv_invalid_count', 'Invalid glUniform{1234}fv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Float32Array} */ var data = new Float32Array(12);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1fv(vec4_v, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2fv(vec4_v, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3fv(vec4_v, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4fv(vec4_v, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformi_incompatible_type', 'Invalid glUniform{1234}i() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null || ivec4_f == null || uvec4_f == null || sampler_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1i(ivec4_f, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2i(ivec4_f, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3i(ivec4_f, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4i(ivec4_f, 0, 0, 0, 0);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type unsigned /** @type {number} */ var , uvec2, uvec3, uvec4, or an array of these.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1i(uvec4_f, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2i(uvec4_f, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3i(uvec4_f, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4i(uvec4_f, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type /** @type {number} */ var , vec2, vec3, or vec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1i(vec4_v, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2i(vec4_v, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3i(vec4_v, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4i(vec4_v, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformiv_incompatible_type', 'Invalid glUniform{1234}iv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null || ivec4_f == null || uvec4_f == null || sampler_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Int32Array} */ var data1 = new Int32Array(1);
+ /** @type {Int32Array} */ var data2 = new Int32Array(2);
+ /** @type {Int32Array} */ var data3 = new Int32Array(3);
+ /** @type {Int32Array} */ var data4 = new Int32Array(4);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1iv(ivec4_f, data1);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2iv(ivec4_f, data2);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3iv(ivec4_f, data3);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4iv(ivec4_f, data4);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}iv is used to load a uniform variable of type /** @type {number} */ var , vec2, vec3, or vec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1iv(vec4_v, data1);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2iv(vec4_v, data2);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3iv(vec4_v, data3);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4iv(vec4_v, data4);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}iv is used to load a uniform variable of type unsigned /** @type {number} */ var , uvec2, uvec3 or uvec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1iv(uvec4_f, data1);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2iv(uvec4_f, data2);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3iv(uvec4_f, data3);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4iv(uvec4_f, data4);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformiv_invalid_count', 'Invalid glUniform{1234}iv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ this.expectError(gl.NO_ERROR);
+
+ if (ivec4_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Int32Array} */ var data = new Int32Array(12);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1iv(ivec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2iv(ivec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3iv(ivec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4iv(ivec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformui_incompatible_type', 'Invalid glUniform{1234}ui() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null || ivec4_f == null || uvec4_f == null || sampler_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1ui(uvec4_f, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2ui(uvec4_f, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3ui(uvec4_f, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4ui(uvec4_f, 0, 0, 0, 0);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type /** @type {number} */ var , ivec2, ivec3, ivec4, or an array of these.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1ui(ivec4_f, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2ui(ivec4_f, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3ui(ivec4_f, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4ui(ivec4_f, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type /** @type {number} */ var , vec2, vec3, or vec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1ui(vec4_v, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2ui(vec4_v, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3ui(vec4_v, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4ui(vec4_v, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1ui(sampler_f, 0);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformuiv_incompatible_type', 'Invalid glUniform{1234}uiv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var vec4_v = gl.getUniformLocation(program.getProgram(), 'vec4_v'); // vec4
+ /** @type {WebGLUniformLocation} */ var ivec4_f = gl.getUniformLocation(program.getProgram(), 'ivec4_f'); // ivec4
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (vec4_v == null || ivec4_f == null || uvec4_f == null || sampler_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Uint32Array} */ var data1 = new Uint32Array(1);
+ /** @type {Uint32Array} */ var data2 = new Uint32Array(2);
+ /** @type {Uint32Array} */ var data3 = new Uint32Array(3);
+ /** @type {Uint32Array} */ var data4 = new Uint32Array(4);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1uiv(uvec4_f, data1);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2uiv(uvec4_f, data2);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3uiv(uvec4_f, data3);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4uiv(uvec4_f, data4);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}uiv is used to load a uniform variable of type /** @type {number} */ var , vec2, vec3, or vec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1uiv(vec4_v, data1);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2uiv(vec4_v, data2);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3uiv(vec4_v, data3);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4uiv(vec4_v, data4);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if glUniform{1234}uiv is used to load a uniform variable of type /** @type {number} */ var , ivec2, ivec3 or ivec4.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1uiv(ivec4_f, data1);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2uiv(ivec4_f, data2);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3uiv(ivec4_f, data3);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4uiv(ivec4_f, data4);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1uiv(sampler_f, data1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniformuiv_invalid_count', 'Invalid glUniform{1234}uiv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var uvec4_f = gl.getUniformLocation(program.getProgram(), 'uvec4_f'); // uvec4
+ this.expectError(gl.NO_ERROR);
+
+ if (uvec4_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Uint32Array} */ var data = new Uint32Array(12);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.');
+ gl.useProgram(program.getProgram());
+ gl.uniform1uiv(uvec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform2uiv(uvec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform3uiv(uvec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniform4uiv(uvec4_f, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniform_matrixfv_incompatible_type', 'Invalid glUniformMatrix{234}fv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var mat4_v = gl.getUniformLocation(program.getProgram(), 'mat4_v'); // mat4
+ /** @type {WebGLUniformLocation} */ var sampler_f = gl.getUniformLocation(program.getProgram(), 'sampler_f'); // sampler2D
+ this.expectError(gl.NO_ERROR);
+
+ if (mat4_v == null || sampler_f == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Float32Array} */ var data4 = new Float32Array(4);
+ /** @type {Float32Array} */ var data9 = new Float32Array(9);
+ /** @type {Float32Array} */ var data16 = new Float32Array(16);
+ /** @type {Float32Array} */ var data6 = new Float32Array(6);
+ /** @type {Float32Array} */ var data8 = new Float32Array(8);
+ /** @type {Float32Array} */ var data12 = new Float32Array(12);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.');
+ gl.useProgram(program.getProgram());
+ gl.uniformMatrix2fv(mat4_v, false, data4);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3fv(mat4_v, false, data9);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4fv(mat4_v, false, data16);
+ this.expectError(gl.NO_ERROR);
+
+ gl.uniformMatrix2x3fv(mat4_v, false, data6);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3x2fv(mat4_v, false, data6);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix2x4fv(mat4_v, false, data8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4x2fv(mat4_v, false, data8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3x4fv(mat4_v, false, data12);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4x3fv(mat4_v, false, data12);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.');
+ gl.useProgram(program.getProgram());
+ gl.uniformMatrix2fv(sampler_f, false, data4);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3fv(sampler_f, false, data9);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4fv(sampler_f, false, data16);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.uniformMatrix2x3fv(sampler_f, false, data6);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3x2fv(sampler_f, false, data6);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix2x4fv(sampler_f, false, data8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4x2fv(sampler_f, false, data8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3x4fv(sampler_f, false, data12);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4x3fv(sampler_f, false, data12);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('uniform_matrixfv_invalid_count', 'Invalid glUniformMatrix{234}fv() usage', gl,
+ function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+
+ gl.useProgram(program.getProgram());
+ /** @type {WebGLUniformLocation} */ var mat4_v = gl.getUniformLocation(program.getProgram(), 'mat4_v'); // mat4
+ this.expectError(gl.NO_ERROR);
+
+ if (mat4_v == null)
+ assertMsgOptions(false, 'Failed to retrieve uniform location', false, true);
+
+ /** @type {Float32Array} */ var data = new Float32Array(144);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.');
+ gl.useProgram(program.getProgram());
+ gl.uniformMatrix2fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.uniformMatrix2x3fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3x2fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix2x4fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4x2fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix3x4fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.uniformMatrix4x3fv(mat4_v, false, data);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.useProgram(null);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('bind_transform_feedback', 'Invalid gl.bindTransformFeedback() usage', gl,
+ function() {
+ /** @type {Array<WebGLTransformFeedback>} */ var tfID = [];
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID[0] = gl.createTransformFeedback();
+ tfID[1] = gl.createTransformFeedback();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.TRANSFORM_FEEDBACK.');
+ gl.bindTransformFeedback(-1, tfID[0]);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the transform feedback operation is active on the currently bound transform feedback object, and is not paused.');
+ gl.useProgram(program.getProgram());
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID[0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ this.expectError(gl.NO_ERROR);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID[1]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.endTransformFeedback();
+ this.expectError(gl.NO_ERROR);
+
+ gl.useProgram(null);
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID[0]);
+ gl.deleteTransformFeedback(tfID[1]);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('begin_transform_feedback', 'Invalid gl.beginTransformFeedback() usage', gl,
+ function() {
+ /** @type {Array<WebGLTransformFeedback>} */ var tfID = [];
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID[0] = gl.createTransformFeedback();
+ tfID[1] = gl.createTransformFeedback();
+
+ gl.useProgram(program.getProgram());
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID[0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if primitiveMode is not one of gl.POINTS, gl.LINES, or gl.TRIANGLES.');
+ gl.beginTransformFeedback(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is already active.');
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ this.expectError(gl.NO_ERROR);
+ gl.beginTransformFeedback(gl.POINTS);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if any binding point used in transform feedback mode does not have a buffer object bound.');
+ /** @type{WebGLBuffer} */ var dummyBuf = gl.createBuffer()
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, dummyBuf);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if no binding points would be used because no program object is active.');
+ gl.useProgram(null);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.useProgram(program.getProgram());
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if no binding points would be used because the active program object has specified no varying variables to record.');
+ gl.transformFeedbackVaryings(program.getProgram(), [], gl.INTERLEAVED_ATTRIBS);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.endTransformFeedback();
+ gl.deleteBuffer(buf);
+ gl.deleteBuffer(dummyBuf);
+ gl.deleteTransformFeedback(tfID[0]);
+ gl.deleteTransformFeedback(tfID[1]);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('pause_transform_feedback', 'Invalid gl.pauseTransformFeedback() usage', gl,
+ function() {
+ /** @type {Array<WebGLTransformFeedback>} */ var tfID = [];
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID[0] = gl.createTransformFeedback();
+ tfID[1] = gl.createTransformFeedback();
+
+ gl.useProgram(program.getProgram());
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID[0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the currently bound transform feedback object is not active or is paused.');
+ gl.pauseTransformFeedback();
+ this.expectError(gl.INVALID_OPERATION);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ gl.pauseTransformFeedback();
+ this.expectError(gl.NO_ERROR);
+ gl.pauseTransformFeedback();
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.endTransformFeedback();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID[0]);
+ gl.deleteTransformFeedback(tfID[1]);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('resume_transform_feedback', 'Invalid gl.resumeTransformFeedback() usage', gl,
+ function() {
+ /** @type {Array<WebGLTransformFeedback>} */ var tfID = [];
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID[0] = gl.createTransformFeedback();
+ tfID[1] = gl.createTransformFeedback();
+
+ gl.useProgram(program.getProgram());
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID[0]);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the currently bound transform feedback object is not active or is not paused.');
+ gl.resumeTransformFeedback();
+ this.expectError(gl.INVALID_OPERATION);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ gl.resumeTransformFeedback();
+ this.expectError(gl.INVALID_OPERATION);
+ gl.pauseTransformFeedback();
+ gl.resumeTransformFeedback();
+ this.expectError(gl.NO_ERROR);
+
+ gl.endTransformFeedback();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID[0]);
+ gl.deleteTransformFeedback(tfID[1]);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('end_transform_feedback', 'Invalid gl.endTransformFeedback() usage', gl,
+ function() {
+ /** @type {WebGLTransformFeedback} */ var tfID;
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {WebGLBuffer} */ var buf;
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram(program.getProgram());
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(program.getProgram());
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is not active.');
+ gl.endTransformFeedback();
+ this.expectError(gl.INVALID_OPERATION);
+ gl.beginTransformFeedback(gl.TRIANGLES);
+ gl.endTransformFeedback();
+ this.expectError(gl.NO_ERROR);
+
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_transform_feedback_varying', 'Invalid glGetTransformFeedbackVarying() usage', gl,
+ function() {
+ /** @type {WebGLTransformFeedback} */ var tfID;
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {gluShaderProgram.ShaderProgram} */ var programInvalid = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, ''));
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+ /** @type {number} */ var maxTransformFeedbackVaryings = 0;
+
+ /** @type {number} */ var length;
+ /** @type {number} */ var size;
+ /** @type {number} */ var type;
+ /** @type {WebGLActiveInfo} */ var name;
+
+ tfID = gl.createTransformFeedback();
+
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ this.expectError(gl.NO_ERROR);
+ gl.linkProgram(program.getProgram());
+ this.expectError(gl.NO_ERROR);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tfID);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getTransformFeedbackVarying(null, 0);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater or equal to the value of gl.TRANSFORM_FEEDBACK_VARYINGS.');
+ maxTransformFeedbackVaryings = /** @type {number} */ (gl.getProgramParameter(program.getProgram(), gl.TRANSFORM_FEEDBACK_VARYINGS));
+ name = gl.getTransformFeedbackVarying(program.getProgram(), maxTransformFeedbackVaryings);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION or gl.INVALID_VALUE is generated program has not been linked.');
+ name = gl.getTransformFeedbackVarying(programInvalid.getProgram(), 0);
+ this.expectError([gl.INVALID_OPERATION, gl.INVALID_VALUE]);
+
+ gl.deleteTransformFeedback(tfID);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('transform_feedback_varyings', 'Invalid gl.transformFeedbackVaryings() usage', gl,
+ function() {
+ /** @type {WebGLTransformFeedback} */ var tfID;
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ /** @type {Array<string>} */ var tfVarying = ['gl_Position'];
+ /** @type {number} */ var maxTransformFeedbackSeparateAttribs = 0;
+
+ tfID = gl.createTransformFeedback();
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.transformFeedbackVaryings(null, tfVarying, gl.INTERLEAVED_ATTRIBS);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if bufferMode is gl.SEPARATE_ATTRIBS and count is greater than gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.');
+ maxTransformFeedbackSeparateAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS));
+ for (var count = 0; count < maxTransformFeedbackSeparateAttribs; ++count) {
+ tfVarying = tfVarying.concat(['gl_Position']);
+ }
+ gl.transformFeedbackVaryings(program.getProgram(), tfVarying, gl.SEPARATE_ATTRIBS);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTransformFeedback(tfID);
+ this.expectError(gl.NO_ERROR);
+ }
+ ));
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeShaderApiTests.run = function(gl) {
+ //Set up Test Root parameters
+ var testName = 'negative_shader_api';
+ var testDescription = 'Negative Shader Api Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fNegativeShaderApiTests.init(gl);
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeStateApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeStateApiTests.js
new file mode 100644
index 0000000000..40d6384edc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeStateApiTests.js
@@ -0,0 +1,927 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative GL State API tests.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('functional.gles3.es3fNegativeStateApiTests');
+
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+
+ var es3fNegativeStateApiTests = functional.gles3.es3fNegativeStateApiTests;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var uniformTestVertSource = '#version 300 es\n' +
+ 'uniform mediump vec4 vUnif_vec4;\n' +
+ 'in mediump vec4 attr;\n' +
+ 'layout(std140) uniform Block { mediump vec4 blockVar; };\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vUnif_vec4 + blockVar + attr;\n' +
+ '}\n';
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var uniformTestFragSource = '#version 300 es\n' +
+ 'uniform mediump ivec4 fUnif_ivec4;\n' +
+ 'uniform mediump uvec4 fUnif_uvec4;\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(vec4(fUnif_ivec4) + vec4(fUnif_uvec4));\n' +
+ '}\n';
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeStateApiTests.init = function(gl) {
+
+ var testGroup = tcuTestCase.runner.testCases;
+
+ // Enabling & disabling states
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('enable', 'Invalid gl.enable() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if cap is not one of the allowed values.');
+ gl.enable(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('disable', 'Invalid gl.disable() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if cap is not one of the allowed values.');
+ gl.disable(-1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ // Simple state queries
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_parameter', 'Invalid gl.getParameter() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not one of the allowed values.');
+ /** @type{boolean} */ var params = false;
+ //glGetBooleanv(-1, params);
+ params = /** @type{boolean} */ (gl.getParameter(-1));
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_indexed_parameter', 'Invalid gl.getIndexedParameter() usage', gl, function() {
+ /** @type{number} */ var data = -1;
+ /** @type{number} */ var maxUniformBufferBindings;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if name is not an accepted value.');
+ data = /** @type{number} */ (gl.getIndexedParameter(-1, 0));
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.');
+ maxUniformBufferBindings = /** @type{number} */ (gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS));
+ this.expectError(gl.NO_ERROR);
+ data = /** @type{number} */ (gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, maxUniformBufferBindings));
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ // Enumerated state queries: Shaders
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_attached_shaders', 'Invalid gl.getAttachedShaders() usage', gl, function() {
+ /** @type{WebGLShader} */ var shaderObject = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getAttachedShaders(null);
+ });
+
+ gl.deleteShader(shaderObject);
+ gl.deleteProgram(program);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_shader_parameter', 'Invalid gl.getShaderParameter() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+ /** @type{number} */ var param = -1;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ param = /** @type{number} */ (gl.getShaderParameter(shader, -1));
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('An exception is thrown if shader is null.');
+ this.expectThrowNoError(function() {
+ gl.getShaderParameter(null, gl.SHADER_TYPE);
+ });
+
+ gl.deleteShader(shader);
+ gl.deleteProgram(program);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_shader_info_log', 'Invalid gl.getShaderInfoLog() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+
+ bufferedLogToConsole('An exception is thrown if shader is null.');
+ this.expectThrowNoError(function() {
+ gl.getShaderInfoLog(null);
+ });
+
+ gl.deleteShader(shader);
+ gl.deleteProgram(program);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_shader_precision_format', 'Invalid gl.getShaderPrecisionFormat() usage', gl, function() {
+ /** @type{WebGLShaderPrecisionFormat } */ var precision;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if shaderType or precisionType is not an accepted value.');
+ precision = gl.getShaderPrecisionFormat (-1, gl.MEDIUM_FLOAT);
+ this.expectError(gl.INVALID_ENUM);
+ precision = gl.getShaderPrecisionFormat (gl.VERTEX_SHADER, -1);
+ this.expectError(gl.INVALID_ENUM);
+ precision = gl.getShaderPrecisionFormat (-1, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_shader_source', 'Invalid gl.getShaderSource() usage', gl, function() {
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+
+ bufferedLogToConsole('An exception is thrown if shader is null.');
+ this.expectThrowNoError(function() {
+ gl.getShaderSource(null);
+ });
+
+ gl.deleteProgram(program);
+ gl.deleteShader(shader);
+ }));
+
+ // Enumerated state queries: Programs
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_program_parameter', 'Invalid gl.getProgramParameter() usage', gl, function() {
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{boolean} */ var params;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ params = /** @type{boolean} */ (gl.getProgramParameter(program, -1));
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getProgramParameter(null, gl.LINK_STATUS);
+ });
+
+ gl.deleteProgram(program);
+ gl.deleteShader(shader);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_program_info_log', 'Invalid gl.getProgramInfoLog() usage', gl, function() {
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getProgramInfoLog (null);
+ });
+
+ gl.deleteProgram(program);
+ gl.deleteShader(shader);
+ }));
+
+ // Enumerated state queries: Shader variables
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_tex_parameter', 'Invalid gl.getTexParameter() usage', gl, function() {
+ /** @type{WebGLTexture} */ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or pname is not an accepted value.');
+ gl.getTexParameter (-1, gl.TEXTURE_MAG_FILTER);
+ this.expectError(gl.INVALID_ENUM);
+ gl.getTexParameter (gl.TEXTURE_2D, -1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.getTexParameter (-1, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_uniform', 'Invalid gl.getUniform() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ gl.useProgram(program.getProgram());
+
+ /** @type{WebGLUniformLocation} */ var unif = gl.getUniformLocation(program.getProgram(), 'vUnif_vec4'); // vec4
+ assertMsgOptions(unif != null, 'Failed to retrieve uniform location', false, true);
+
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{WebGLProgram} */ var programEmpty = gl.createProgram();
+ /** @type{*} */ var params;
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getUniform (null, unif);
+ });
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if program has not been successfully linked.');
+ params = gl.getUniform (programEmpty, unif);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('An exception is thrown if location is null.');
+ this.expectThrowNoError(function() {
+ gl.getUniform (program.getProgram(), null);
+ });
+
+ gl.deleteShader(shader);
+ gl.deleteProgram(programEmpty);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_active_uniform', 'Invalid gl.getActiveUniform() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ /** @type{number} */ var numActiveUniforms = -1;
+
+ numActiveUniforms = /** @type{number} */ (gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORMS));
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORMS = ' + numActiveUniforms + ' (expected 4).');
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getActiveUniform(null, 0);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to the number of active uniform variables in program.');
+ gl.useProgram(program.getProgram());
+ gl.getActiveUniform(program.getProgram(), numActiveUniforms);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.useProgram(null);
+ gl.deleteShader(shader);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_active_uniforms', 'Invalid gl.getActiveUniforms() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ /** @type{Array<number>} */ var dummyUniformIndex = [1];
+ /** @type{Array<number>} */ var dummyParamDst;
+ /** @type{number} */ var numActiveUniforms = -1;
+
+ gl.useProgram(program.getProgram());
+
+ numActiveUniforms = /** @type{number} */ (gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORMS));
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORMS = ' + numActiveUniforms + ' (expected 4).');
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getActiveUniforms(null, dummyUniformIndex, gl.UNIFORM_TYPE);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if any value in uniformIndices is greater than or equal to the value of gl.ACTIVE_UNIFORMS for program.');
+ /** @type{Array<number>} */ var invalidUniformIndices;
+ /** @type{Array<number>} */ var dummyParamsDst;
+ for (var excess = 0; excess <= 2; excess++) {
+ invalidUniformIndices = [1, numActiveUniforms - 1 + excess, 1];
+ dummyParamsDst = gl.getActiveUniforms(program.getProgram(), invalidUniformIndices, gl.UNIFORM_TYPE);
+ this.expectError(excess == 0 ? gl.NO_ERROR : gl.INVALID_VALUE);
+ }
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted token.');
+ dummyParamDst = gl.getActiveUniforms(program.getProgram(), dummyUniformIndex, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.useProgram(null);
+ gl.deleteShader(shader);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_active_uniform_block_parameter', 'Invalid gl.getActiveUniformBlockParameter() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ /** @type{*} */ var params;
+ /** @type{number} */ var numActiveBlocks = -1;
+
+ numActiveBlocks = /** @type{number} */ (gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORM_BLOCKS));
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORM_BLOCKS = ' + numActiveBlocks + ' (expected 1).');
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if uniformBlockIndex is greater than or equal to the value of gl.ACTIVE_UNIFORM_BLOCKS or is not the index of an active uniform block in program.');
+ gl.useProgram(program.getProgram());
+ this.expectError(gl.NO_ERROR);
+ params = gl.getActiveUniformBlockParameter(program.getProgram(), numActiveBlocks, gl.UNIFORM_BLOCK_BINDING);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not one of the accepted tokens.');
+ params = gl.getActiveUniformBlockParameter(program.getProgram(), 0, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_active_uniform_block_name', 'Invalid gl.getActiveUniformBlockName() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ /** @type{number} */ var length = -1;
+ /** @type{number} */ var numActiveBlocks = -1;
+ /** @type{string} */ var uniformBlockName;
+
+ numActiveBlocks = /** @type{number} */ (gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORM_BLOCKS));
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORM_BLOCKS = ' + numActiveBlocks + ' (expected 1).');
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if uniformBlockIndex is greater than or equal to the value of gl.ACTIVE_UNIFORM_BLOCKS or is not the index of an active uniform block in program.');
+ gl.useProgram(program.getProgram());
+ this.expectError(gl.NO_ERROR);
+ uniformBlockName = gl.getActiveUniformBlockName(program.getProgram(), numActiveBlocks);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_active_attrib', 'Invalid gl.getActiveAttrib() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ /** @type{number} */ var numActiveAttributes = -1;
+
+ /** @type{WebGLActiveInfo} */ var activeInfo;
+ /** @type{number} */ var size = -1;
+ /** @type{number} */ var type = -1;
+ /** @type{string} */ var name;
+
+ numActiveAttributes = /** @type{number} */(gl.getProgramParameter(program.getProgram(), gl.ACTIVE_ATTRIBUTES));
+ bufferedLogToConsole('// gl.ACTIVE_ATTRIBUTES = ' + numActiveAttributes + ' (expected 1).');
+
+ gl.useProgram(program.getProgram());
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getActiveAttrib(null, 0);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.ACTIVE_ATTRIBUTES.');
+ activeInfo = gl.getActiveAttrib(program.getProgram(), numActiveAttributes);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.useProgram(null);
+ gl.deleteShader(shader);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_uniform_indices', 'Invalid gl.getUniformIndices() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
+ gl.useProgram(program.getProgram());
+ /** @type{number} */ var numActiveBlocks = -1;
+ /** @type{Array<string>} */ var uniformName = ['Block.blockVar'];
+ /** @type{Array<number>} */ var uniformIndices = [-1];
+
+ numActiveBlocks = /** @type{number} */(gl.getProgramParameter(program.getProgram(), gl.ACTIVE_UNIFORM_BLOCKS));
+ bufferedLogToConsole('// gl.ACTIVE_UNIFORM_BLOCKS = ' + numActiveBlocks);
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('An exception is thrown if program is null.');
+ this.expectThrowNoError(function() {
+ gl.getUniformIndices(null, uniformName);
+ });
+
+ gl.useProgram(null);
+ gl.deleteShader(shader);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_vertex_attrib', 'Invalid gl.getVertexAttrib() usage', gl, function() {
+ /** @type{*} */ var params;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ params = gl.getVertexAttrib(0, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ /** @type{number} */ var maxVertexAttribs;
+ maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ params = gl.getVertexAttrib(maxVertexAttribs, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_vertex_attrib_offset', 'Invalid gl.getVertexAttribOffset() usage', gl, function() {
+ /** @type{number} */ var ptr;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ ptr = gl.getVertexAttribOffset(0, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ /** @type{number} */ var maxVertexAttribs;
+ maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ ptr = gl.getVertexAttribOffset(maxVertexAttribs, gl.VERTEX_ATTRIB_ARRAY_POINTER);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_frag_data_location', 'Invalid gl.getFragDataLocation() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type{WebGLProgram} */ var program = gl.createProgram();
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if program has not been linked.');
+ gl.getFragDataLocation(program, 'gl_FragColor');
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteProgram(program);
+ gl.deleteShader(shader);
+ }));
+
+ // Enumerated state queries: Buffers
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_buffer_parameter', 'Invalid gl.getBufferParameter() usage', gl, function() {
+ /** @type{number} */ var params = -1;
+ /** @type{WebGLBuffer} */ var buf;
+ buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or value is not an accepted value.');
+ params = /** @type{number} */ (gl.getBufferParameter(-1, gl.BUFFER_SIZE));
+ this.expectError(gl.INVALID_ENUM);
+ params = /** @type{number} */ (gl.getBufferParameter(gl.ARRAY_BUFFER, -1));
+ this.expectError(gl.INVALID_ENUM);
+ params = /** @type{number} */ (gl.getBufferParameter(-1, -1));
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.');
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ params = /** @type{number} */ (gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE));
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(buf);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_framebuffer_attachment_parameter', 'Invalid gl.getFramebufferAttachmentParameter() usage', gl, function() {
+ /** @type{*} */ var params;
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{Array<WebGLRenderbuffer>} */ var rbo = [];
+
+ fbo = gl.createFramebuffer();
+ rbo[0] = gl.createRenderbuffer();
+ rbo[1] = gl.createRenderbuffer();
+
+ gl.bindFramebuffer (gl.FRAMEBUFFER, fbo);
+ gl.bindRenderbuffer (gl.RENDERBUFFER, rbo[0]);
+ gl.renderbufferStorage (gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16);
+ gl.framebufferRenderbuffer (gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rbo[0]);
+ gl.bindRenderbuffer (gl.RENDERBUFFER, rbo[1]);
+ gl.renderbufferStorage (gl.RENDERBUFFER, gl.STENCIL_INDEX8, 16, 16);
+ gl.framebufferRenderbuffer (gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo[1]);
+ gl.checkFramebufferStatus (gl.FRAMEBUFFER);
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted tokens.');
+ gl.getFramebufferAttachmentParameter(-1, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); // TYPE is gl.RENDERBUFFER
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not valid for the value of gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE.');
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL); // TYPE is gl.RENDERBUFFER
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); // TYPE is gl.FRAMEBUFFER_DEFAULT
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if attachment is gl.DEPTH_STENCIL_ATTACHMENT and different objects are bound to the depth and stencil attachment points of target.');
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the value of gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is gl.NONE and pname is not gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME.');
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); // TYPE is gl.NONE
+ this.expectError(gl.NO_ERROR);
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE); // TYPE is gl.NONE
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION or gl.INVALID_ENUM is generated if attachment is not one of the accepted values for the current binding of target.');
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); // A FBO is bound so gl.BACK is invalid
+ this.expectError([gl.INVALID_OPERATION, gl.INVALID_ENUM]);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); // Default framebuffer is bound so gl.COLOR_ATTACHMENT0 is invalid
+ this.expectError([gl.INVALID_OPERATION, gl.INVALID_ENUM]);
+
+ gl.deleteFramebuffer(fbo);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_renderbuffer_parameter', 'Invalid gl.getRenderbufferParameter() usage', gl, function() {
+ /** @type{number} */ var params = -1;
+ /** @type{WebGLRenderbuffer} */ var rbo;
+ rbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.RENDERBUFFER.');
+ gl.getRenderbufferParameter(-1, gl.RENDERBUFFER_WIDTH);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not one of the accepted tokens.');
+ gl.getRenderbufferParameter(gl.RENDERBUFFER, -1);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteRenderbuffer(rbo);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_internalformat_parameter', 'Invalid gl.getInternalformatParameter() usage', gl, function() {
+ /** @type{WebGLRenderbuffer} */ var rbo = gl.createRenderbuffer();
+ /** @type{WebGLFramebuffer} */ var fbo = gl.createFramebuffer();
+ /** @type{WebGLTexture} */ var tex = gl.createTexture();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not gl.SAMPLES or gl.NUM_SAMPLE_COUNTS.');
+ gl.getInternalformatParameter (gl.RENDERBUFFER, gl.RGBA8, -1);
+ this.expectError (gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if internalformat is not color-, depth-, or stencil-renderable.');
+ gl.getInternalformatParameter (gl.RENDERBUFFER, gl.RG8_SNORM, gl.NUM_SAMPLE_COUNTS);
+ this.expectError (gl.INVALID_ENUM);
+ gl.getInternalformatParameter (gl.RENDERBUFFER, gl.COMPRESSED_RGB8_ETC2, gl.NUM_SAMPLE_COUNTS);
+ this.expectError (gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.RENDERBUFFER.');
+ gl.getInternalformatParameter (-1, gl.RGBA8, gl.NUM_SAMPLE_COUNTS);
+ this.expectError (gl.INVALID_ENUM);
+ gl.getInternalformatParameter (gl.FRAMEBUFFER, gl.RGBA8, gl.NUM_SAMPLE_COUNTS);
+ this.expectError (gl.INVALID_ENUM);
+ gl.getInternalformatParameter (gl.TEXTURE_2D, gl.RGBA8, gl.NUM_SAMPLE_COUNTS);
+ this.expectError (gl.INVALID_ENUM);
+
+ gl.deleteRenderbuffer(rbo);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(tex);
+
+ }));
+
+ // Query object queries
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_query', 'Invalid gl.getQuery() usage', gl, function() {
+ /** @type{number} */ var params = -1;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or pname is not an accepted value.');
+ gl.getQuery (gl.ANY_SAMPLES_PASSED, -1);
+ this.expectError (gl.INVALID_ENUM);
+ gl.getQuery (-1, gl.CURRENT_QUERY);
+ this.expectError (gl.INVALID_ENUM);
+ gl.getQuery (-1, -1);
+ this.expectError (gl.INVALID_ENUM);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_query_parameter', 'Invalid gl.getQueryParameter() usage', gl, function() {
+
+ /** @type{WebGLQuery} */ var id;
+ id = gl.createQuery();
+
+ bufferedLogToConsole('An exception is thrown if the query object is null.');
+ this.expectThrowNoError(function() {
+ gl.getQueryParameter (null, gl.QUERY_RESULT_AVAILABLE);
+ });
+
+ bufferedLogToConsole('// Note: ' + id + ' is not a query object yet, since it hasn\'t been used by gl.beginQuery');
+ gl.getQueryParameter (id, gl.QUERY_RESULT_AVAILABLE);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.beginQuery (gl.ANY_SAMPLES_PASSED, id);
+ gl.endQuery (gl.ANY_SAMPLES_PASSED);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ gl.getQueryParameter (id, -1);
+ this.expectError (gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if id is the name of a currently active query object.');
+ gl.beginQuery (gl.ANY_SAMPLES_PASSED, id);
+ this.expectError (gl.NO_ERROR);
+ gl.getQueryParameter (id, gl.QUERY_RESULT_AVAILABLE);
+ this.expectError (gl.INVALID_OPERATION);
+ gl.endQuery (gl.ANY_SAMPLES_PASSED);
+ this.expectError (gl.NO_ERROR);
+
+ gl.deleteQuery(id);
+ }));
+
+ // Sync object queries
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('get_sync_parameter', 'Invalid gl.getSyncParameter() usage', gl, function() {
+ /** @type{WebGLSync} */ var sync;
+
+ bufferedLogToConsole('An exception is thrown if sync is null.');
+ this.expectThrowNoError(function() {
+ gl.getSyncParameter (null, gl.OBJECT_TYPE);
+ });
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not one of the accepted tokens.');
+ sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ this.expectError (gl.NO_ERROR);
+ gl.getSyncParameter (sync, -1);
+ this.expectError (gl.INVALID_ENUM);
+
+ }));
+
+ // Enumerated boolean state queries
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_enabled', 'Invalid gl.isEnabled() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if cap is not an accepted value.');
+ gl.isEnabled(-1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.isEnabled(gl.TRIANGLES);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ // Named Object Usage
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_buffer', 'Invalid gl.isBuffer() usage', gl, function() {
+ /** @type{WebGLBuffer} */ var buffer;
+ /** @type{boolean} */ var isBuffer;
+
+ bufferedLogToConsole('A name returned by glGenBuffers, but not yet associated with a buffer object by calling glBindBuffer, is not the name of a buffer object.');
+ isBuffer = gl.isBuffer(buffer);
+ assertMsgOptions(!isBuffer, 'Got invalid boolean value', false, true);
+
+ buffer = gl.createBuffer();
+ isBuffer = gl.isBuffer(buffer);
+ assertMsgOptions(!isBuffer, 'Got invalid boolean value', false, true);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ isBuffer = gl.isBuffer(buffer);
+ assertMsgOptions(isBuffer, 'Got invalid boolean value', false, true);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.deleteBuffer(buffer);
+ isBuffer = gl.isBuffer(buffer);
+ assertMsgOptions(!isBuffer, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_framebuffer', 'Invalid gl.isFramebuffer() usage', gl, function() {
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{boolean} */ var isFbo;
+
+ bufferedLogToConsole('A name returned by glGenFramebuffers, but not yet bound through a call to gl.bindFramebuffer is not the name of a framebuffer object.');
+ isFbo = gl.isFramebuffer(fbo);
+ assertMsgOptions(!isFbo, 'Got invalid boolean value', false, true);
+
+ fbo = gl.createFramebuffer();
+ isFbo = gl.isFramebuffer(fbo);
+ assertMsgOptions(!isFbo, 'Got invalid boolean value', false, true);
+
+ gl.bindFramebuffer (gl.FRAMEBUFFER, fbo);
+ isFbo = gl.isFramebuffer(fbo);
+ assertMsgOptions(isFbo, 'Got invalid boolean value', false, true);
+
+ gl.bindFramebuffer (gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ isFbo = gl.isFramebuffer(fbo);
+ assertMsgOptions(!isFbo, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_program', 'Invalid gl.isProgram() usage', gl, function() {
+ /** @type{WebGLProgram} */ var program;
+ /** @type{boolean} */ var isProgram;
+
+ bufferedLogToConsole('A name created with gl.createProgram, and not yet deleted with glDeleteProgram is a name of a program object.');
+ isProgram = gl.isProgram(program);
+ assertMsgOptions(!isProgram, 'Got invalid boolean value', false, true);
+
+ program = gl.createProgram();
+ isProgram = gl.isProgram(program);
+ assertMsgOptions(isProgram, 'Got invalid boolean value', false, true);
+
+ gl.deleteProgram(program);
+ isProgram = gl.isProgram(program);
+ assertMsgOptions(!isProgram, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_renderbuffer', 'Invalid gl.isRenderbuffer() usage', gl, function() {
+ /** @type{WebGLRenderbuffer} */ var rbo;
+ /** @type{boolean} */ var isRbo;
+
+ bufferedLogToConsole('A name returned by glGenRenderbuffers, but not yet bound through a call to gl.bindRenderbuffer or gl.framebufferRenderbuffer is not the name of a renderbuffer object.');
+ isRbo = gl.isRenderbuffer(rbo);
+ assertMsgOptions(!isRbo, 'Got invalid boolean value', false, true);
+
+ rbo = gl.createRenderbuffer();
+ isRbo = gl.isRenderbuffer(rbo);
+ assertMsgOptions(!isRbo, 'Got invalid boolean value', false, true);
+
+ gl.bindRenderbuffer (gl.RENDERBUFFER, rbo);
+ isRbo = gl.isRenderbuffer(rbo);
+ assertMsgOptions(isRbo, 'Got invalid boolean value', false, true);
+
+ gl.bindRenderbuffer (gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(rbo);
+ isRbo = gl.isRenderbuffer(rbo);
+ assertMsgOptions(!isRbo, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_shader', 'Invalid gl.isShader() usage', gl, function() {
+ /** @type{WebGLShader} */ var shader;
+ /** @type{boolean} */ var isShader;
+
+ bufferedLogToConsole('A name created with glCreateShader, and not yet deleted with glDeleteShader is a name of a shader object.');
+ isShader = gl.isProgram(shader);
+ assertMsgOptions(!isShader, 'Got invalid boolean value', false, true);
+
+ shader = gl.createShader(gl.VERTEX_SHADER);
+ isShader = gl.isShader(shader);
+ assertMsgOptions(isShader, 'Got invalid boolean value', false, true);
+
+ gl.deleteShader (shader);
+ isShader = gl.isShader(shader);
+ assertMsgOptions(!isShader, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_texture', 'Invalid gl.isTexture() usage', gl, function() {
+ /** @type{WebGLTexture} */ var texture;
+ /** @type{boolean} */ var isTexture;
+
+ bufferedLogToConsole('A name returned by glGenTextures, but not yet bound through a call to glBindTexture is not the name of a texture.');
+ isTexture = gl.isTexture(texture);
+ assertMsgOptions(!isTexture, 'Got invalid boolean value', false, true);
+
+ texture = gl.createTexture();
+ isTexture = gl.isTexture(texture);
+ assertMsgOptions(!isTexture, 'Got invalid boolean value', false, true);
+
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+ isTexture = gl.isTexture(texture);
+ assertMsgOptions(isTexture, 'Got invalid boolean value', false, true);
+
+ gl.bindTexture (gl.TEXTURE_2D, null);
+ gl.deleteTexture(texture);
+ isTexture = gl.isTexture(texture);
+ assertMsgOptions(!isTexture, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_query', 'Invalid gl.isQuery() usage', gl, function() {
+ /** @type{WebGLQuery} */ var query;
+ /** @type{boolean} */ var isQuery;
+
+ bufferedLogToConsole('A name returned by glGenQueries, but not yet associated with a query object by calling gl.beginQuery, is not the name of a query object.');
+ isQuery = gl.isQuery(query);
+ assertMsgOptions(!isQuery, 'Got invalid boolean value', false, true);
+
+ query = gl.createQuery();
+ isQuery = gl.isQuery(query);
+ assertMsgOptions(!isQuery, 'Got invalid boolean value', false, true);
+
+ gl.beginQuery (gl.ANY_SAMPLES_PASSED, query);
+ isQuery = gl.isQuery(query);
+ assertMsgOptions(isQuery, 'Got invalid boolean value', false, true);
+
+ gl.endQuery (gl.ANY_SAMPLES_PASSED);
+ gl.deleteQuery (query);
+ isQuery = gl.isQuery(query);
+ assertMsgOptions(!isQuery, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_sampler', 'Invalid gl.isSampler() usage', gl, function() {
+ /** @type{WebGLSampler} */ var sampler;
+ /** @type{boolean} */ var isSampler;
+
+ bufferedLogToConsole('A name returned by glGenSamplers is the name of a sampler object.');
+ isSampler = gl.isSampler(sampler);
+ assertMsgOptions(!isSampler, 'Got invalid boolean value', false, true);
+
+ sampler = gl.createSampler();
+ isSampler = gl.isSampler(sampler);
+ assertMsgOptions(isSampler, 'Got invalid boolean value', false, true);
+
+ gl.bindSampler(0, sampler);
+ isSampler = gl.isSampler(sampler);
+ assertMsgOptions(isSampler, 'Got invalid boolean value', false, true);
+
+ gl.deleteSampler(sampler);
+ isSampler = gl.isSampler(sampler);
+ assertMsgOptions(!isSampler, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_sync', 'Invalid gl.isSync() usage', gl, function() {
+ /** @type{WebGLSync} */ var sync;
+ /** @type{boolean} */ var isSync;
+
+ bufferedLogToConsole('A name returned by gl.fenceSync is the name of a sync object.');
+ isSync = gl.isSync(sync);
+ assertMsgOptions(!isSync, 'Got invalid boolean value', false, true);
+
+ sync = gl.fenceSync (gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ isSync = gl.isSync(sync);
+ assertMsgOptions(isSync, 'Got invalid boolean value', false, true);
+
+ gl.deleteSync (sync);
+ isSync = gl.isSync(sync);
+ assertMsgOptions(!isSync, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_transform_feedback', 'Invalid gl.isTransformFeedback() usage', gl, function() {
+ /** @type{WebGLTransformFeedback} */ var tf;
+ /** @type{boolean} */ var isTF;
+
+ bufferedLogToConsole('A name returned by glGenTransformFeedbacks, but not yet bound using glBindTransformFeedback, is not the name of a transform feedback object.');
+ isTF = gl.isTransformFeedback(tf);
+ assertMsgOptions(!isTF, 'Got invalid boolean value', false, true);
+
+ tf = gl.createTransformFeedback();
+ isTF = gl.isTransformFeedback(tf);
+ assertMsgOptions(!isTF, 'Got invalid boolean value', false, true);
+
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tf);
+ isTF = gl.isTransformFeedback(tf);
+ assertMsgOptions(isTF, 'Got invalid boolean value', false, true);
+
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, null);
+ gl.deleteTransformFeedback (tf);
+ isTF = gl.isTransformFeedback(tf);
+ assertMsgOptions(!isTF, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('is_vertex_array', 'Invalid gl.isVertexArray() usage', gl, function() {
+ /** @type{WebGLVertexArrayObject} */ var vao;
+ /** @type{boolean} */ var isVao;
+
+ bufferedLogToConsole('A name returned by glGenVertexArrays, but not yet bound using glBindVertexArray, is not the name of a vertex array object.');
+ isVao = gl.isVertexArray(vao);
+ assertMsgOptions(!isVao, 'Got invalid boolean value', false, true);
+
+ vao = gl.createVertexArray();
+ isVao = gl.isVertexArray(vao);
+ assertMsgOptions(!isVao, 'Got invalid boolean value', false, true);
+
+ gl.bindVertexArray (vao);
+ isVao = gl.isVertexArray(vao);
+ assertMsgOptions(isVao, 'Got invalid boolean value', false, true);
+
+ gl.bindVertexArray (null);
+ gl.deleteVertexArray (vao);
+ isVao = gl.isVertexArray(vao);
+ assertMsgOptions(!isVao, 'Got invalid boolean value', false, true);
+
+ this.expectError (gl.NO_ERROR);
+ }));
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeStateApiTests.run = function(gl) {
+ var testName = 'state';
+ var testDescription = 'Negative GL State API Cases';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fNegativeStateApiTests.init(gl);
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeTextureApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeTextureApiTests.js
new file mode 100644
index 0000000000..8bccf1bb37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeTextureApiTests.js
@@ -0,0 +1,3002 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative Texture API tests.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('functional.gles3.es3fNegativeTextureApiTests');
+
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+ var es3fNegativeTextureApiTests = functional.gles3.es3fNegativeTextureApiTests;
+ var tcuTexture = framework.common.tcuTexture;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+
+ function etc2Unsupported() {
+ debug("Skipping test: no support for WEBGL_compressed_texture_etc");
+ }
+
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ * @return {number}
+ */
+ es3fNegativeTextureApiTests.etc2DataSize = function(width, height) {
+ return Math.ceil(width / 4) * Math.ceil(height / 4) * 8;
+ };
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ * @return {number}
+ */
+ es3fNegativeTextureApiTests.etc2EacDataSize = function(width, height) {
+ return 2 * es3fNegativeTextureApiTests.etc2DataSize(width, height);
+ };
+
+ /**
+ * @param {function(number)} func
+ */
+ es3fNegativeTextureApiTests.forCubeFaces = function(func) {
+ var faceGLVar;
+ for (var faceIterTcu in tcuTexture.CubeFace) {
+ faceGLVar = gluTexture.cubeFaceToGLFace(tcuTexture.CubeFace[faceIterTcu]);
+ func(faceGLVar);
+ }
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeTextureApiTests.init = function(gl) {
+
+ var haveCompressedTextureETC = gluTextureUtil.enableCompressedTextureETC();
+
+ var testGroup = tcuTestCase.runner.testCases;
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('activetexture', 'Invalid gl.ActiveTexture() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if texture is not one of gl.TEXTUREi, where i ranges from 0 to (gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1).');
+ gl.activeTexture(-1);
+ this.expectError(gl.INVALID_ENUM);
+ var numMaxTextureUnits = /** @type {number} */(gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
+ gl.activeTexture(gl.TEXTURE0 + numMaxTextureUnits);
+ this.expectError(gl.INVALID_ENUM);
+
+ }));
+
+ // gl.bindTexture
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('bindTexture', 'Invalid gl.bindTexture() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the allowable values.');
+ gl.bindTexture(0, texture[0]);
+ this.expectError(gl.INVALID_ENUM);
+ gl.bindTexture(gl.FRAMEBUFFER, texture[0]);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if texture was previously created with a target that doesn\'t match that of target.');
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ this.expectError(gl.NO_ERROR);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[0]);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindTexture(gl.TEXTURE_3D, texture[0]);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, texture[0]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ this.expectError(gl.NO_ERROR);
+ gl.bindTexture(gl.TEXTURE_2D, texture[1]);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindTexture(gl.TEXTURE_3D, texture[1]);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, texture[1]);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ // gl.compressedTexImage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_invalid_target', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(0);
+ gl.compressedTexImage2D(0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_invalid_format', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if internalformat is not a supported format returned in gl.COMPRESSED_TEXTURE_FORMATS.');
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(0);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_neg_level', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(0);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_max_level', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE) for a 2d texture target.');
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16));
+
+ /** @type {number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type {number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.compressedTexImage2D(gl.TEXTURE_2D, log2MaxTextureSize, gl.COMPRESSED_RGB8_ETC2, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_CUBE_MAP_TEXTURE_SIZE) for a cubemap target.');
+ /** @type {number} */ var log2MaxCubemapSize = Math.floor(Math.log2(/** @type {number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)))) + 1;
+
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, log2MaxCubemapSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, log2MaxCubemapSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, log2MaxCubemapSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, log2MaxCubemapSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, log2MaxCubemapSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, log2MaxCubemapSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_neg_width_height', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than 0.');
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(0);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, 0, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_max_width_height', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+ var maxTextureSize = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_SIZE)) + 1;
+ var maxCubemapSize = /** @type {number} */ (gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)) + 1;
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is greater than gl.MAX_TEXTURE_SIZE.');
+
+ var maxSideSize = Math.max(maxCubemapSize, maxTextureSize);
+ var scratchBuffer = new ArrayBuffer(
+ Math.max(es3fNegativeTextureApiTests.etc2EacDataSize(maxSideSize, 1),
+ es3fNegativeTextureApiTests.etc2EacDataSize(1, maxSideSize)));
+ function getUint8ArrayEtc2EacDataSize(w, h) {
+ return new Uint8Array(scratchBuffer, 0, es3fNegativeTextureApiTests.etc2EacDataSize(w, h));
+ }
+
+ var dataTextureMaxByOne = getUint8ArrayEtc2EacDataSize(maxTextureSize, 1);
+ var dataTextureOneByMax = getUint8ArrayEtc2EacDataSize(1, maxTextureSize);
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxTextureSize, 1, 0, dataTextureMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxTextureSize, 0, dataTextureOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+ var dataCubemapMaxByOne = getUint8ArrayEtc2EacDataSize(maxCubemapSize, 1);
+ var dataCubemapOneByMax = getUint8ArrayEtc2EacDataSize(1, maxCubemapSize);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxCubemapSize, 1, 0, dataCubemapMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxCubemapSize, 0, dataCubemapOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxCubemapSize, 1, 0, dataCubemapMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxCubemapSize, 0, dataCubemapOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxCubemapSize, 1, 0, dataCubemapMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxCubemapSize, 0, dataCubemapOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxCubemapSize, 1, 0, dataCubemapMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxCubemapSize, 0, dataCubemapOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxCubemapSize, 1, 0, dataCubemapMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxCubemapSize, 0, dataCubemapOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxCubemapSize, 1, 0, dataCubemapMaxByOne);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 1, maxCubemapSize, 0, dataCubemapOneByMax);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_invalid_border', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(0);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if border is not 0.');
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage2d_invalid_size', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+
+ /** @type {WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if imageSize is not consistent with the format, dimensions, and contents of the specified compressed image data.');
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, new Uint8Array(1));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, new Uint8Array(4 * 4 * 8));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGB8_ETC2, 16, 16, 0, new Uint8Array(4 * 4 * 16));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_SIGNED_R11_EAC, 16, 16, 0, new Uint8Array(4 * 4 * 16));
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture);
+
+
+ }));
+
+ // gl.copyTexImage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_invalid_target', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.copyTexImage2D(0, 0, gl.RGB, 0, 0, 64, 64, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+
+ gl.deleteTexture(texture);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_invalid_format', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_ENUM or gl.INVALID_VALUE is generated if internalformat is not an accepted format.');
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 64, 64, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 0, 16, 16, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, 0, 16, 16, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, 0, 16, 16, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, 0, 16, 16, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, 0, 16, 16, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, 0, 16, 16, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_inequal_width_height_cube', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is one of the six cube map 2D image targets and the width and height parameters are not equal.');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, 16, 17, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, 16, 17, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, 16, 17, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, 16, 17, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, 16, 17, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, 16, 17, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_neg_level', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.copyTexImage2D(gl.TEXTURE_2D, -1, gl.RGB, 0, 0, 64, 64, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, -1, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, -1, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, -1, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, -1, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, -1, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, -1, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_max_level', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type {number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type {number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.copyTexImage2D(gl.TEXTURE_2D, log2MaxTextureSize, gl.RGB, 0, 0, 64, 64, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_CUBE_MAP_TEXTURE_SIZE).');
+ /** @type {number} */ var log2MaxCubemapSize = Math.floor(Math.log2(/** @type {number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)))) + 1;
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, log2MaxCubemapSize, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, log2MaxCubemapSize, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, log2MaxCubemapSize, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, log2MaxCubemapSize, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, log2MaxCubemapSize, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, log2MaxCubemapSize, gl.RGB, 0, 0, 16, 16, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_neg_width_height', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than 0.');
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, -1, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, 1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, -1, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_max_width_height', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ var maxTextureSize = /** @type {number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)) + 1;
+ var maxCubemapSize = /** @type {number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)) + 1;
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is greater than gl.MAX_TEXTURE_SIZE.');
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, maxTextureSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, 1, maxTextureSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, maxTextureSize, maxTextureSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, 1, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, maxCubemapSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, maxCubemapSize, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, 1, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, maxCubemapSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, maxCubemapSize, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, 1, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, maxCubemapSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, maxCubemapSize, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, 1, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, maxCubemapSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, maxCubemapSize, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, 1, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, maxCubemapSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, maxCubemapSize, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, 1, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, maxCubemapSize, 1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, maxCubemapSize, maxCubemapSize, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_invalid_border', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if border is not 0.');
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 0, 0, 0, 0, 1);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copyteximage2d_incomplete_framebuffer', 'Invalid gl.copyTexImage2D() usage', gl,
+ function() {
+
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ /** @type {WebGLFramebuffer} */ var fbo;
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA8, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ // gl.copyTexSubImage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_invalid_target', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+
+ /** @type {WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.copyTexSubImage2D(0, 0, 0, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_neg_level', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.texImage2D(faceGL, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, -1, 0, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ var local = this;
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.copyTexSubImage2D(faceGL, -1, 0, 0, 0, 0, 4, 4);
+ local.expectError(gl.INVALID_VALUE);
+ });
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_max_level', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.texImage2D(faceGL, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ });
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE) for 2D texture targets.');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, log2MaxTextureSize, 0, 0, 0, 0, 4, 4);
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_CUBE_MAP_SIZE) for cubemap targets.');
+ /** @type{number} */ var log2MaxCubemapSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)))) + 1;
+ var local = this;
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.copyTexSubImage2D(faceGL, log2MaxCubemapSize, 0, 0, 0, 0, 4, 4);
+ local.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ });
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_neg_offset', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset < 0 or yoffset < 0.');
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, -1, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, -1, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, -1, -1, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_invalid_offset', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset + width > texture_width or yoffset + height > texture_height.');
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 14, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 14, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 14, 14, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_neg_width_height', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than 0.');
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, -1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage2d_incomplete_framebuffer', 'Invalid gl.copyTexSubImage2D() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ /** @type{WebGLFramebuffer} */ var fbo;
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, 0, 0, 0, 0);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ // glDeleteTextures
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('deletetextures', 'glDeleteTextures() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+
+ bufferedLogToConsole('gl.NO_ERROR is generated if texture is null.');
+ gl.deleteTexture(null);
+ this.expectError(gl.NO_ERROR);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.deleteTexture(null);
+ this.expectError(gl.NO_ERROR);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.generateMipmap
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('generatemipmap', 'Invalid gl.generateMipmap() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ /** @type{WebGLFramebuffer} */ var fbo;
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not gl.TEXTURE_2D or gl.TEXTURE_CUBE_MAP.');
+ gl.generateMipmap(0);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('INVALID_OPERATION is generated if the texture bound to target is not cube complete.');
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[0]);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.REPEAT);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[0]);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 32, 32, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ this.expectError(gl.INVALID_OPERATION);
+
+ if (haveCompressedTextureETC) {
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the zero level array is stored in a compressed internal format.');
+ gl.bindTexture(gl.TEXTURE_2D, texture[1]);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, new Uint8Array(0));
+ gl.generateMipmap(gl.TEXTURE_2D);
+ this.expectError(gl.INVALID_OPERATION);
+ } else {
+ etc2Unsupported();
+ }
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the level base array was not specified with an unsized internal format or a sized internal format that is both color-renderable and texture-filterable.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8_SNORM, 0, 0, 0, gl.RGB, gl.BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8I, 0, 0, 0, gl.RED_INTEGER, gl.BYTE, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 0, 0, 0, gl.RGBA, gl.FLOAT, null);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ // gl.pixelStorei
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('pixelstorei', 'Invalid gl.pixelStorei() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if pname is not an accepted value.');
+ gl.pixelStorei(0,1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if a negative row length, pixel skip, or row skip value is specified, or if alignment is specified as other than 1, 2, 4, or 8.');
+ gl.pixelStorei(gl.PACK_ROW_LENGTH, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.PACK_SKIP_ROWS, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.PACK_SKIP_PIXELS, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, -1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.PACK_ALIGNMENT, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.PACK_ALIGNMENT, 16);
+ this.expectError(gl.INVALID_VALUE);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 16);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ // gl.texImage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+
+ /** @type {WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.texImage2D(0, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not a type constant.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, 0, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if format is not an accepted format constant.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, 0, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if internalFormat is not one of the accepted resolution and format symbolic constants.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, 0, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the combination of internalFormat, format and type is invalid.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGB, gl.UNSIGNED_SHORT_4_4_4_4, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB5_A1, 1, 1, 0, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2, 1, 1, 0, gl.RGB, gl.UNSIGNED_INT_2_10_10_10_REV, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, 1, 1, 0, gl.RGBA_INTEGER, gl.INT, null);
+ this.expectError(gl.INVALID_OPERATION);
+
+
+ gl.deleteTexture(texture);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d_inequal_width_height_cube', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+ /** @type {WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if target is one of the six cube map 2D image targets and the width and height parameters are not equal.');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 1, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 1, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 1, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 1, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 1, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 1, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d_neg_level', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.texImage2D(gl.TEXTURE_2D, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, -1, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d_max_level', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.texImage2D(gl.TEXTURE_2D, log2MaxTextureSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_CUBE_MAP_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxCubemapSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)))) + 1;
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, log2MaxCubemapSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, log2MaxCubemapSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, log2MaxCubemapSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, log2MaxCubemapSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, log2MaxCubemapSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, log2MaxCubemapSize, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d_neg_width_height', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than 0.');
+
+ bufferedLogToConsole('gl.TEXTURE_2D target');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, -1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, -1, -1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d_max_width_height', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ var maxTextureSize = /** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)) + 1;
+ var maxCubemapSize = /** @type{number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)) + 1;
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is greater than gl.MAX_TEXTURE_SIZE.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, maxTextureSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, maxTextureSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, maxTextureSize, maxTextureSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is greater than gl.MAX_CUBE_MAP_TEXTURE_SIZE.');
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_X target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, maxCubemapSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 1, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, maxCubemapSize, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Y target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, maxCubemapSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 1, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, maxCubemapSize, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_POSITIVE_Z target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, maxCubemapSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 1, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, maxCubemapSize, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_X target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, maxCubemapSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 1, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, maxCubemapSize, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Y target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, maxCubemapSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 1, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, maxCubemapSize, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.TEXTURE_CUBE_MAP_NEGATIVE_Z target');
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, maxCubemapSize, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 1, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, maxCubemapSize, maxCubemapSize, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage2d_invalid_border', 'Invalid gl.texImage2D() usage', gl,
+ function() {
+
+ /** @type {Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if border is not 0.');
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, -1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, 1, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ // gl.texSubImage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage2d', 'Invalid gl.texSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(64);
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.texSubImage2D(0, 0, 0, 0, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if format is not an accepted format constant.');
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 4, 4, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not a type constant.');
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGB, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the combination of internalFormat of the previously specified texture array, format and type is not valid.');
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGBA, gl.UNSIGNED_SHORT_5_6_5, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGB, gl.UNSIGNED_SHORT_4_4_4_4, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGBA_INTEGER, gl.UNSIGNED_INT, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.RGB, gl.FLOAT, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage2d_neg_level', 'Invalid gl.texSubImage2D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 32, 32, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.texImage2D(faceGL, 0, gl.RGB, 32, 32, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ });
+ this.expectError(gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.texSubImage2D(gl.TEXTURE_2D, -1, 0, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ var local = this;
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.texSubImage2D(faceGL, -1, 0, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ local.expectError(gl.INVALID_VALUE);
+ });
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage2d_max_level', 'Invalid gl.texSubImage2D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture[0]);
+ gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGB, 32, 32, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture (gl.TEXTURE_CUBE_MAP, texture[1]);
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.texImage2D(faceGL, 0, gl.RGB, 32, 32, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ });
+
+ this.expectError (gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.texSubImage2D(gl.TEXTURE_2D, log2MaxTextureSize, 0, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_CUBE_MAP_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxCubemapSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)))) + 1;
+ var local = this;
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.texSubImage2D(faceGL, log2MaxCubemapSize, 0, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ local.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ });
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage2d_neg_offset', 'Invalid gl.texSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 32, 32, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset or yoffset are negative.');
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, -1, 0, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, -1, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, -1, -1, 0, 0, gl.RGB, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage2d_invalid_offset', 'Invalid gl.texSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(64);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset + width > texture_width or yoffset + height > texture_height.');
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 30, 0, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 30, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 30, 30, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage2d_neg_width_height', 'Invalid gl.texSubImage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than 0.');
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, -1, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, -1, -1, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.texParameteri
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texparameteri', 'Invalid gl.texParameteri() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or pname is not one of the accepted defined values.');
+ gl.texParameteri(0, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameteri(gl.TEXTURE_2D, 0, gl.LINEAR);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameteri(0, 0, gl.LINEAR);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined symbolic constant value (based on the value of pname) and does not.');
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.REPEAT);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.NEAREST);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or pname is not one of the accepted defined values.');
+ gl.texParameteri(0, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameteri(gl.TEXTURE_2D, 0, gl.LINEAR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameteri(0, 0, gl.LINEAR);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined symbolic constant value (based on the value of pname) and does not.');
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, 0);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.REPEAT);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, 0);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.NEAREST);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.texParameterf
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texparameterf', 'Invalid gl.texParameterf() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or pname is not one of the accepted defined values.');
+ gl.texParameterf(0, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameterf(gl.TEXTURE_2D, 0, gl.LINEAR);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameterf(0, 0, gl.LINEAR);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined symbolic constant value (based on the value of pname) and does not.');
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.REPEAT);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, 0);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.NEAREST);
+ this.expectError([gl.INVALID_ENUM, gl.INVALID_OPERATION]);
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target or pname is not one of the accepted defined values.');
+ gl.texParameterf(0, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameterf(gl.TEXTURE_2D, 0, gl.LINEAR);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameterf(0, 0, gl.LINEAR);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if params should have a defined symbolic constant value (based on the value of pname) and does not.');
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, 0);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.REPEAT);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, 0);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.NEAREST);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.compressedTexSubImage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d', 'Invalid gl.compressedTexSubImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.compressedTexSubImage2D(0, 0, 0, 0, 0, 0, gl.COMPRESSED_RGB8_ETC2, new Uint8Array(0));
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.compressedTexImage2D (gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 18, 18, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if format does not match the internal format of the texture image being modified.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.COMPRESSED_RGB8_ETC2, new Uint8Array(0));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('For ETC2/EAC images gl.INVALID_OPERATION is generated if width is not a multiple of four, and width + xoffset is not equal to the width of the texture level.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 4, 0, 10, 4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(10, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('For ETC2/EAC images gl.INVALID_OPERATION is generated if height is not a multiple of four, and height + yoffset is not equal to the height of the texture level.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 4, 4, 10, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 10)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('For ETC2/EAC images gl.INVALID_OPERATION is generated if xoffset or yoffset is not a multiple of four.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 1, 4, 4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d_neg_level', 'Invalid gl.compressedTexSubImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.compressedTexImage2D (gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 18, 18, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.compressedTexImage2D(faceGL, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 18, 18, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ });
+
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, -1, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ var local = this;
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.compressedTexSubImage2D(faceGL, -1, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ local.expectError(gl.INVALID_VALUE);
+ });
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d_max_level', 'Invalid gl.compressedTexSubImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture[0]);
+ gl.compressedTexImage2D (gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 18, 18, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture[1]);
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.compressedTexImage2D(faceGL, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 18, 18, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ });
+
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, log2MaxTextureSize, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_CUBE_MAP_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxCubemapSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)))) + 1;
+ var local = this;
+ es3fNegativeTextureApiTests.forCubeFaces(function(faceGL) {
+ gl.compressedTexSubImage2D(faceGL, log2MaxCubemapSize, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ local.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ });
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d_neg_offset', 'Invalid gl.compressedTexSubImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 8, 8, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(8, 8)));
+
+ // \note Both gl.INVALID_VALUE and gl.INVALID_OPERATION are valid here since implementation may
+ // first check if offsets are valid for certain format and only after that check that they
+ // are not negative.
+ bufferedLogToConsole('gl.INVALID_VALUE or gl.INVALID_OPERATION is generated if xoffset or yoffset are negative.');
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, -4, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, -4, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, -4, -4, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d_invalid_offset', 'Invalid gl.compressedTexSubImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+ gl.compressedTexImage2D (gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE or gl.INVALID_OPERATION is generated if xoffset + width > texture_width or yoffset + height > texture_height.');
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 12, 0, 8, 4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(8, 4)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 12, 4, 8, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 8)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 12, 12, 8, 8, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(8, 8)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d_neg_width_height', 'Invalid gl.compressedTexSubImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+ gl.compressedTexImage2D (gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE or gl.INVALID_OPERATION is generated if width or height is less than 0.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, -4, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, -4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, -4, -4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage2d_invalid_size', 'Invalid gl.compressedTexImage2D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+ gl.compressedTexImage2D (gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if imageSize is not consistent with the format, dimensions, and contents of the specified compressed image data.');
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(1));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 16, 16, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(4*4*16-1));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.texImage3D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage3d', 'Invalid gl.texImage3D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture[0]);
+ gl.bindTexture (gl.TEXTURE_3D, texture[1]);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.texImage3D(0, 0, gl.RGBA, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texImage3D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not a type constant.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, gl.RGBA, 0, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if format is not an accepted format constant.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, 0, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if internalFormat is not one of the accepted resolution and format symbolic constants.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, 0, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if target is gl.TEXTURE_3D and format is gl.DEPTH_COMPONENT, or gl.DEPTH_STENCIL.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the combination of internalFormat, format and type is invalid.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_SHORT_4_4_4_4, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB5_A1, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB10_A2, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_INT_2_10_10_10_REV, null);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA32UI, 1, 1, 1, 0, gl.RGBA_INTEGER, gl.INT, null);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage3d_neg_level', 'Invalid gl.texImage3D() usage', gl,
+ function() {
+ // NOTE: this method hangs the browser if the textures are binded.
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.texImage3D(gl.TEXTURE_3D, -1, gl.RGB, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, -1, gl.RGB, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage3d_max_level', 'Invalid gl.texImage3D() usage', gl,
+ function() {
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_3D_TEXTURE_SIZE).');
+ /** @type{number} */ var log2Max3DTextureSize = Math.floor(Math.log2(/** @type{number} */ (gl.getParameter(gl.MAX_3D_TEXTURE_SIZE)))) + 1;
+ gl.texImage3D(gl.TEXTURE_3D, log2Max3DTextureSize, gl.RGB, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */ (gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, log2MaxTextureSize, gl.RGB, 1, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage3d_neg_width_height_depth', 'Invalid gl.texImage3D() usage', gl,
+ function() {
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height is less than 0.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, -1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, -1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, -1, -1, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, -1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 1, -1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 1, 1, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, -1, -1, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage3d_max_width_height_depth', 'Invalid gl.texImage3D() usage', gl,
+ function() {
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+
+ var max3DTextureSize = /** @type{number} */ (gl.getParameter(gl.MAX_3D_TEXTURE_SIZE)) + 1;
+ var maxTextureSize = /** @type{number} */ (gl.getParameter(gl.MAX_TEXTURE_SIZE)) + 1;
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width, height or depth is greater than gl.MAX_3D_TEXTURE_SIZE.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, max3DTextureSize, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, max3DTextureSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, max3DTextureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, max3DTextureSize, max3DTextureSize, max3DTextureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width, height or depth is greater than gl.MAX_TEXTURE_SIZE.');
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, maxTextureSize, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 1, maxTextureSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 1, 1, maxTextureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, maxTextureSize, maxTextureSize, maxTextureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('teximage3d_invalid_border', 'Invalid gl.texImage3D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if border is not 0 or 1.');
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB, 1, 1, 1, -1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB, 1, 1, 1, 2, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGB, 1, 1, 1, -1, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGB, 1, 1, 1, 2, gl.RGB, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ // gl.texSubImage3D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage3d', 'Invalid gl.texSubImage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(256);
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.texSubImage3D(0, 0, 0, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_ENUM);
+ gl.texSubImage3D(gl.TEXTURE_2D, 0, 0, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if format is not an accepted format constant.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 4, 4, 4, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not a type constant.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, gl.RGB, 0, uint8);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the combination of internalFormat of the previously specified texture array, format and type is not valid.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, gl.RGB, gl.UNSIGNED_SHORT_4_4_4_4, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, gl.RGB, gl.UNSIGNED_SHORT_5_5_5_1, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, gl.RGBA_INTEGER, gl.UNSIGNED_INT, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, gl.RGB, gl.FLOAT, uint8);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage3d_neg_level', 'Invalid gl.texSubImage3D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+ gl.texImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.texSubImage3D(gl.TEXTURE_3D, -1, 0, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, -1, 0, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage3d_max_level', 'Invalid gl.texSubImage3D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+ gl.texImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ /** @type{number} */ var log2Max3DTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_3D_TEXTURE_SIZE)))) + 1;
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_3D_TEXTURE_SIZE).');
+ gl.texSubImage3D(gl.TEXTURE_3D, log2Max3DTextureSize, 0, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, log2MaxTextureSize, 0, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage3d_neg_offset', 'Invalid gl.texSubImage3D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+ gl.texImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset, yoffset or zoffset are negative.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, -1, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, -1, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, -1, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, -1, -1, -1, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, -1, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, -1, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, -1, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, -1, -1, -1, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage3d_invalid_offset', 'Invalid gl.texSubImage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(256);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset + width > texture_width.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 2, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if yoffset + height > texture_height.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 2, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if zoffset + depth > texture_depth.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 2, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texsubimage3d_neg_width_height', 'Invalid gl.texSubImage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ /** @type {ArrayBufferView} */ var uint8 = new Uint8Array(4);
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width, height or depth is less than 0.');
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, -1, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, -1, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, -1, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+ gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, -1, -1, -1, gl.RGBA, gl.UNSIGNED_BYTE, uint8);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.copyTexSubImage3D(0, 0, 0, 0, 0, 0, 0, 4, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteTexture(texture);
+ }));
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d_neg_level', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+ gl.texImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, -1, 0, 0, 0, 0, 0, 4, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, -1, 0, 0, 0, 0, 0, 4, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d_max_level', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ /** @type{number} */ var log2Max3DTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_3D_TEXTURE_SIZE)))) + 1;
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture[0]);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+ gl.texImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_3D_TEXTURE_SIZE).');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, log2Max3DTextureSize, 0, 0, 0, 0, 0, 4, 0);
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ gl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, log2MaxTextureSize, 0, 0, 0, 0, 0, 4, 0);
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d_neg_offset', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset, yoffset or zoffset is negative.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, -1, 0, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, -1, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, -1, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, -1, -1, -1, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d_invalid_offset', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if xoffset + width > texture_width.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 1, 0, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if yoffset + height > texture_height.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 1, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if zoffset + 1 > texture_depth.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 4, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d_neg_width_height', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+ gl.texImage3D (gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width < 0.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, -4, 4);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if height < 0.');
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, 4, -4);
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('copytexsubimage3d_incomplete_framebuffer', 'Invalid gl.copyTexSubImage3D() usage', gl,
+ function() {
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+ /** @type{WebGLFramebuffer} */ var fbo;
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_3D, texture[0]);
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, texture[1]);
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ this.expectError(gl.NO_ERROR);
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER);
+ this.expectError(gl.NO_ERROR);
+
+ gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 4, 4);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ // gl.compressedTexImage3D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{Array<WebGLTexture>} */ var texture = [];
+
+ // We have to create and bind textures to each target for the test because default textures are not supported by WebGL.
+ texture[0] = gl.createTexture();
+ texture[1] = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_CUBE_MAP, texture[0]);
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture[1]);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ gl.compressedTexImage3D(0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage3D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if internalformat is not one of the specific compressed internal formats.');
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_ENUM);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, 0, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.deleteTexture(texture[0]);
+ gl.deleteTexture(texture[1]);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d_neg_level', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, -1, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d_max_level', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, log2MaxTextureSize, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, 0, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d_neg_width_height_depth', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width, height or depth is less than 0.');
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, -1, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, -1, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, -1, -1, -1, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d_max_width_height_depth', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+
+ var maxTextureSize = /** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)) + 1;
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width, height or depth is greater than gl.MAX_TEXTURE_SIZE.');
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxTextureSize, 0, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, maxTextureSize, 0, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, maxTextureSize, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, maxTextureSize, maxTextureSize, maxTextureSize, 0, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d_invalid_border', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if border is not 0.');
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, -1, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, 1, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedteximage3d_invalid_size', 'Invalid gl.compressedTexImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{ WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if imageSize is not consistent with the format, dimensions, and contents of the specified compressed image data.');
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 0, 0, 0, 0, new Uint8Array(1));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 1, 0, new Uint8Array(4*4*8));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGB8_ETC2, 16, 16, 1, 0, new Uint8Array(4*4*16));
+ this.expectError(gl.INVALID_VALUE);
+ gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_SIGNED_R11_EAC, 16, 16, 1, 0, new Uint8Array(4*4*16));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+
+ }));
+
+ // gl.compressedTexSubImage3D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is invalid.');
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.compressedTexSubImage3D(0, 0, 0, 0, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError(gl.INVALID_ENUM);
+
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 18, 18, 1, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if format does not match the internal format of the texture image being modified.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, gl.COMPRESSED_RGB8_ETC2, new Uint8Array(0));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if internalformat is an ETC2/EAC format and target is not gl.TEXTURE_2D_ARRAY.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 18, 18, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(18, 18)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('For ETC2/EAC images gl.INVALID_OPERATION is generated if width is not a multiple of four, and width + xoffset is not equal to the width of the texture level.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 4, 0, 0, 10, 4, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(10, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('For ETC2/EAC images gl.INVALID_OPERATION is generated if height is not a multiple of four, and height + yoffset is not equal to the height of the texture level.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 4, 0, 4, 10, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 10)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ bufferedLogToConsole('For ETC2/EAC images gl.INVALID_OPERATION is generated if xoffset or yoffset is not a multiple of four.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 1, 0, 0, 4, 4, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 1, 0, 4, 4, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 1, 1, 0, 4, 4, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d_neg_level', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 1, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is less than 0.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, -1, 0, 0, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d_max_level', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 1, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if level is greater than log_2(gl.MAX_TEXTURE_SIZE).');
+ /** @type{number} */ var log2MaxTextureSize = Math.floor(Math.log2(/** @type{number} */(gl.getParameter(gl.MAX_TEXTURE_SIZE)))) + 1;
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, log2MaxTextureSize, 0, 0, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d_neg_offset', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 1, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE or gl.INVALID_OPERATION is generated if xoffset, yoffset or zoffset are negative.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, -4, 0, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, -4, 0, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, -4, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, -4, -4, -4, 0, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d_invalid_offset', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 1, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE or gl.INVALID_OPERATION is generated if xoffset + width > texture_width or yoffset + height > texture_height.');
+
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 12, 0, 0, 8, 4, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(8, 4)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 12, 0, 4, 8, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 8)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 12, 4, 4, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(4, 4)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 12, 12, 12, 8, 8, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(8, 8)));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d_neg_width_height_depth', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 1, 0, new Uint8Array(es3fNegativeTextureApiTests.etc2EacDataSize(16, 16)));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE or gl.INVALID_OPERATION is generated if width, height or depth are negative.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, -4, 0, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, -4, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, -4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, -4, -4, -4, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError([gl.INVALID_VALUE, gl.INVALID_OPERATION]);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('compressedtexsubimage3d_invalid_size', 'Invalid gl.compressedTexSubImage3D() usage', gl,
+ function() {
+ if (!haveCompressedTextureETC) { etc2Unsupported(); return; }
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D_ARRAY, texture);
+ gl.compressedTexImage3D (gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 16, 16, 1, 0, new Uint8Array(4*4*16));
+ this.expectError (gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if imageSize is not consistent with the format, dimensions, and contents of the specified compressed image data.');
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(0));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, gl.COMPRESSED_RGBA8_ETC2_EAC, new Uint8Array(4*4*16-1));
+ this.expectError(gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.texStorage2D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texstorage2d', 'Invalid gl.texStorage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_ENUM or gl.INVALID_VALUE is generated if internalformat is not a valid sized internal format.');
+ gl.texStorage2D (gl.TEXTURE_2D, 1, 0, 16, 16);
+ this.expectError ([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA_INTEGER, 16, 16);
+ this.expectError ([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted target enumerants.');
+ gl.texStorage2D (0, 1, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_ENUM);
+ gl.texStorage2D (gl.TEXTURE_3D, 1, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_ENUM);
+ gl.texStorage2D (gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width or height are less than 1.');
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA8, 0, 16);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA8, 16, 0);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA8, 0, 0);
+ this.expectError (gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texstorage2d_invalid_binding', 'Invalid gl.texStorage2D() usage', gl,
+ function() {
+ gl.bindTexture (gl.TEXTURE_2D, null);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if there is no texture object curently bound to target.');
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_OPERATION);
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the texture object currently bound to target already has gl.TEXTURE_IMMUTABLE_FORMAT set to true.');
+ /** @type{number} */ var immutable;
+ immutable = /** @type{number} */(gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_IMMUTABLE_FORMAT));
+ bufferedLogToConsole('// gl.TEXTURE_IMMUTABLE_FORMAT = ' + ((immutable != 0) ? 'true' : 'false'));
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA8, 16, 16);
+ this.expectError (gl.NO_ERROR);
+ immutable = /** @type{number} */(gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_IMMUTABLE_FORMAT));
+ bufferedLogToConsole('// gl.TEXTURE_IMMUTABLE_FORMAT = ' + ((immutable != 0) ? 'true' : 'false'));
+ gl.texStorage2D (gl.TEXTURE_2D, 1, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texstorage2d_invalid_levels', 'Invalid gl.texStorage2D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_2D, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if levels is less than 1.');
+ gl.texStorage2D (gl.TEXTURE_2D, 0, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage2D (gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0);
+ this.expectError (gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if levels is greater than floor(log_2(max(width, height))) + 1');
+ /** @type{number} */ var log2MaxSize = Math.floor(Math.log2(Math.max(16, 4))) + 1 + 1;
+ gl.texStorage2D (gl.TEXTURE_2D, log2MaxSize, gl.RGBA8, 16, 4);
+ this.expectError (gl.INVALID_OPERATION);
+ gl.texStorage2D (gl.TEXTURE_2D, log2MaxSize, gl.RGBA8, 4, 16);
+ this.expectError (gl.INVALID_OPERATION);
+ gl.texStorage2D (gl.TEXTURE_2D, log2MaxSize, gl.RGBA8, 16, 16);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // gl.texStorage3D
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texstorage3d', 'Invalid gl.texStorage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+
+ bufferedLogToConsole('gl.INVALID_ENUM or gl.INVALID_VALUE is generated if internalformat is not a valid sized internal format.');
+ gl.texStorage3D (gl.TEXTURE_3D, 1, 0, 4, 4, 4);
+ this.expectError ([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA_INTEGER, 4, 4, 4);
+ this.expectError ([gl.INVALID_ENUM, gl.INVALID_VALUE]);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if target is not one of the accepted target enumerants.');
+ gl.texStorage3D (0, 1, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.INVALID_ENUM);
+ gl.texStorage3D (gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.INVALID_ENUM);
+ gl.texStorage3D (gl.TEXTURE_2D, 1, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if width, height or depth are less than 1.');
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 0, 4, 4);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 4, 0, 4);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 4, 4, 0);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 0, 0, 0);
+ this.expectError (gl.INVALID_VALUE);
+
+ gl.deleteTexture(texture);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texstorage3d_invalid_binding', 'Invalid gl.texStorage3D() usage', gl,
+ function() {
+ gl.bindTexture (gl.TEXTURE_3D, null);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if there is no texture object curently bound to target.');
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.INVALID_OPERATION);
+
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if the texture object currently bound to target already has gl.TEXTURE_IMMUTABLE_FORMAT set to true.');
+ /** @type{number} */ var immutable;
+ immutable = /** @type{number} */(gl.getTexParameter(gl.TEXTURE_3D, gl.TEXTURE_IMMUTABLE_FORMAT));
+ bufferedLogToConsole('// gl.TEXTURE_IMMUTABLE_FORMAT = ' + ((immutable != 0) ? 'true' : 'false'));
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.NO_ERROR);
+ immutable = /** @type{number} */(gl.getTexParameter(gl.TEXTURE_3D, gl.TEXTURE_IMMUTABLE_FORMAT));
+ bufferedLogToConsole('// gl.TEXTURE_IMMUTABLE_FORMAT = ' + ((immutable != 0) ? 'true' : 'false'));
+ gl.texStorage3D (gl.TEXTURE_3D, 1, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+
+ // NOTE: the test doesn't cause glError using the parameters defined in the original test of C code
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('texstorage3d_invalid_levels', 'Invalid gl.texStorage3D() usage', gl,
+ function() {
+ /** @type{WebGLTexture} */ var texture;
+ texture = gl.createTexture();
+ gl.bindTexture (gl.TEXTURE_3D, texture);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if levels is less than 1.');
+ gl.texStorage3D (gl.TEXTURE_3D, 0, gl.RGBA8, 4, 4, 4);
+ this.expectError (gl.INVALID_VALUE);
+ gl.texStorage3D (gl.TEXTURE_3D, 0, gl.RGBA8, 0, 0, 0);
+ this.expectError (gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if levels is greater than floor(log_2(max(width, height, depth))) + 1');
+ /** @type{number} */ var log2MaxSize = Math.floor(Math.log2(8)) + 1 + 1;
+ gl.texStorage3D (gl.TEXTURE_3D, log2MaxSize, gl.RGBA8, 8, 2, 2);
+ this.expectError (gl.INVALID_OPERATION);
+ gl.texStorage3D (gl.TEXTURE_3D, log2MaxSize, gl.RGBA8, 2, 8, 2);
+ this.expectError (gl.INVALID_OPERATION);
+ gl.texStorage3D (gl.TEXTURE_3D, log2MaxSize, gl.RGBA8, 2, 2, 8);
+ this.expectError (gl.INVALID_OPERATION);
+ gl.texStorage3D (gl.TEXTURE_3D, log2MaxSize, gl.RGBA8, 8, 8, 8);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.deleteTexture(texture);
+ }));
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeTextureApiTests.run = function(gl) {
+ var testName = 'negativeTextureApi';
+ var testDescription = 'Negative Texture API tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fNegativeTextureApiTests.init(gl);
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeVertexArrayApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeVertexArrayApiTests.js
new file mode 100644
index 0000000000..d921a6f52b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fNegativeVertexArrayApiTests.js
@@ -0,0 +1,906 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative Vertex Array API tests.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('functional.gles3.es3fNegativeVertexArrayApiTests');
+
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+
+goog.scope(function() {
+
+ var es3fNegativeVertexArrayApiTests = functional.gles3.es3fNegativeVertexArrayApiTests;
+ var tcuTexture = framework.common.tcuTexture;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var vertexShaderSource = '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+
+ /**
+ * @type {string}
+ * @const
+ */
+ var fragmentShaderSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeVertexArrayApiTests.init = function(gl) {
+
+ var testGroup = tcuTestCase.runner.testCases;
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attribf', 'Invalid glVertexAttrib{1234}f() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ gl.vertexAttrib1f(maxVertexAttribs, 0.0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttrib2f(maxVertexAttribs, 0.0, 0.0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttrib3f(maxVertexAttribs, 0.0, 0.0, 0.0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttrib4f(maxVertexAttribs, 0.0, 0.0, 0.0, 0.0);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attribfv', 'Invalid glVertexAttrib{1234}fv() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ /** @type{Array<number>} */ var v = [0.0];
+ gl.vertexAttrib1fv(maxVertexAttribs, v);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttrib2fv(maxVertexAttribs, v);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttrib3fv(maxVertexAttribs, v);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttrib4fv(maxVertexAttribs, v);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attribi4', 'Invalid glVertexAttribI4{i|ui}f() usage', gl, function() {
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ /** @type{number} */ var valInt = 0;
+ /** @type{number} */ var valUint = 0;
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ gl.vertexAttribI4i(maxVertexAttribs, valInt, valInt, valInt, valInt);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttribI4ui(maxVertexAttribs, valUint, valUint, valUint, valUint);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attribi4v', 'Invalid glVertexAttribI4{i|ui}fv() usage', gl, function() {
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ /** @type{Array<number>} */ var valInt = [0];
+ /** @type{Array<number>} */ var valUint = [0];
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ gl.vertexAttribI4iv(maxVertexAttribs, valInt);
+ this.expectError(gl.INVALID_VALUE);
+ gl.vertexAttribI4uiv(maxVertexAttribs, valUint);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attrib_pointer', 'Invalid gl.vertexAttribPointer() usage', gl, function() {
+ /** @type{WebGLBuffer} */ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not an accepted value.');
+ gl.vertexAttribPointer(0, 1, 0, true, 0, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ gl.vertexAttribPointer(maxVertexAttribs, 1, gl.BYTE, true, 0, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if size is not 1, 2, 3, or 4.');
+ gl.vertexAttribPointer(0, 0, gl.BYTE, true, 0, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if stride is negative.');
+ gl.vertexAttribPointer(0, 1, gl.BYTE, true, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if type is gl.INT_2_10_10_10_REV or gl.UNSIGNED_INT_2_10_10_10_REV and size is not 4.');
+ gl.vertexAttribPointer(0, 2, gl.INT_2_10_10_10_REV, true, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.vertexAttribPointer(0, 2, gl.UNSIGNED_INT_2_10_10_10_REV, true, 0, 0);
+ this.expectError(gl.INVALID_OPERATION);
+ gl.vertexAttribPointer(0, 4, gl.INT_2_10_10_10_REV, true, 0, 0);
+ this.expectError(gl.NO_ERROR);
+ gl.vertexAttribPointer(0, 4, gl.UNSIGNED_INT_2_10_10_10_REV, true, 0, 0);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated a non-zero vertex array object is bound, zero is bound to the gl.ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.');
+ /** @type{WebGLVertexArrayObject} */ var vao;
+ /** @type{number} */ var offset = 1;
+ vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ this.expectError(gl.NO_ERROR);
+
+ gl.vertexAttribPointer(0, 1, gl.BYTE, true, 0, offset);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.bindVertexArray(null);
+ gl.deleteVertexArray(vao);
+ this.expectError(gl.NO_ERROR);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attrib_i_pointer', 'Invalid gl.vertexAttribIPointer() usage', gl, function() {
+ /** @type{WebGLBuffer} */ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not an accepted value.');
+ gl.vertexAttribIPointer(0, 1, 0, 0, 0);
+ this.expectError(gl.INVALID_ENUM);
+ gl.vertexAttribIPointer(0, 4, gl.INT_2_10_10_10_REV, 0, 0);
+ this.expectError(gl.INVALID_ENUM);
+ gl.vertexAttribIPointer(0, 4, gl.UNSIGNED_INT_2_10_10_10_REV, 0, 0);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ gl.vertexAttribIPointer(maxVertexAttribs, 1, gl.BYTE, 0, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if size is not 1, 2, 3, or 4.');
+ gl.vertexAttribIPointer(0, 0, gl.BYTE, 0, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if stride is negative.');
+ gl.vertexAttribIPointer(0, 1, gl.BYTE, -1, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated a non-zero vertex array object is bound, zero is bound to the gl.ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.');
+ /** @type{WebGLVertexArrayObject} */ var vao;
+ /** @type{number} */ var offset = 1;
+ vao = gl.createVertexArray();
+ gl.bindVertexArray(vao);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ this.expectError(gl.NO_ERROR);
+
+ gl.vertexAttribIPointer(0, 1, gl.BYTE, 0, offset);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.bindVertexArray(null);
+ gl.deleteVertexArray(vao);
+ this.expectError(gl.NO_ERROR);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('enable_vertex_attrib_array', 'Invalid gl.enableVertexAttribArray() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ gl.enableVertexAttribArray(maxVertexAttribs);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('disable_vertex_attrib_array', 'Invalid gl.disableVertexAttribArray() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ gl.disableVertexAttribArray(maxVertexAttribs);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('vertex_attrib_divisor', 'Invalid gl.vertexAttribDivisor() usage', gl, function() {
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if index is greater than or equal to gl.MAX_VERTEX_ATTRIBS.');
+ var maxVertexAttribs = /** @type{number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ gl.vertexAttribDivisor(maxVertexAttribs, 0);
+ this.expectError(gl.INVALID_VALUE);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_arrays', 'Invalid gl.drawArrays() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawArrays(-1, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
+ gl.drawArrays(gl.POINTS, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_arrays_invalid_program', 'Invalid gl.drawArrays() usage', gl, function() {
+ gl.useProgram(null);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) is used.');
+ gl.drawArrays(gl.POINTS, 0, 1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_arrays_incomplete_primitive', 'Invalid gl.drawArrays() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawArrays(-1, 0, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
+ gl.drawArrays(gl.TRIANGLES, 0, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawArrays(gl.TRIANGLES, 0, 1);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_elements', 'Invalid gl.drawElements() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{WebGLBuffer} */ var buf;
+ /** @type{WebGLTransformFeedback} */ var tfID;
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawElements(-1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not one of the accepted values.');
+ gl.drawElements(gl.POINTS, 0, -1, vertices);
+ this.expectError(gl.INVALID_ENUM);
+ gl.drawElements(gl.POINTS, 0, gl.FLOAT, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
+ gl.drawElements(gl.POINTS, -1, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ if (!sglrGLContext.isExtensionSupported(gl, 'EXT_geometry_shader')) { // gl.EXT_geometry_shader removes error
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is active and not paused.');
+ /** @type{Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram (program.getProgram());
+ gl.transformFeedbackVaryings (program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram (program.getProgram());
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer (gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData (gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase (gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback (gl.POINTS);
+ this.expectError (gl.NO_ERROR);
+
+ gl.drawElements (gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ gl.pauseTransformFeedback();
+ gl.drawElements (gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.NO_ERROR);
+
+ gl.endTransformFeedback ();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(bufElements);
+ this.expectError (gl.NO_ERROR);
+
+ }
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_elements_invalid_program', 'Invalid gl.drawElements() usage', gl, function() {
+ gl.useProgram(null);
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) was set.');
+ gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(bufElements);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_elements_incomplete_primitive', 'Invalid gl.drawElements() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{WebGLBuffer} */ var buf;
+ /** @type{WebGLTransformFeedback} */ var tfID;
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawElements(-1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not one of the accepted values.');
+ gl.drawElements(gl.TRIANGLES, 0, -1, vertices);
+ this.expectError(gl.INVALID_ENUM);
+ gl.drawElements(gl.TRIANGLES, 0, gl.FLOAT, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
+ gl.drawElements(gl.TRIANGLES, -1, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawElements(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ if (!sglrGLContext.isExtensionSupported(gl, 'EXT_geometry_shader')) {// gl.EXT_geometry_shader removes error
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is active and not paused.');
+ /** @type{Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram (program.getProgram());
+ gl.transformFeedbackVaryings (program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram (program.getProgram());
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer (gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData (gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase (gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback (gl.TRIANGLES);
+ this.expectError (gl.NO_ERROR);
+
+ gl.drawElements (gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ gl.pauseTransformFeedback();
+ gl.drawElements (gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.NO_ERROR);
+
+ gl.endTransformFeedback ();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(bufElements);
+ this.expectError (gl.NO_ERROR);
+
+ }
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_arrays_instanced', 'Invalid gl.drawArraysInstanced() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufElements);
+
+ gl.vertexAttribDivisor(0, 1);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawArraysInstanced(-1, 0, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count or primcount are negative.');
+ gl.drawArraysInstanced(gl.POINTS, 0, -1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.drawArraysInstanced(gl.POINTS, 0, 1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawArraysInstanced(gl.POINTS, 0, 1, 1);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ gl.deleteBuffer(bufElements);
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_arrays_instanced_invalid_program', 'Invalid gl.drawArraysInstanced() usage', gl, function() {
+ gl.useProgram(null);
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufElements);
+
+ gl.vertexAttribDivisor(0, 1);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) is set.');
+ gl.drawArraysInstanced(gl.POINTS, 0, 1, 1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(bufElements);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_arrays_instanced_incomplete_primitive', 'Invalid gl.drawArraysInstanced() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufElements);
+
+ gl.vertexAttribDivisor(0, 1);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawArraysInstanced(-1, 0, 1, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count or primcount are negative.');
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, -1, 1);
+ this.expectError(gl.INVALID_VALUE);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 1, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 1, 1);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ gl.deleteBuffer(bufElements);
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_elements_instanced', 'Invalid gl.drawElementsInstanced() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{WebGLBuffer} */ var buf;
+ /** @type{WebGLTransformFeedback} */ var tfID;
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ gl.vertexAttribDivisor(0, 1);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawElementsInstanced(-1, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not one of the accepted values.');
+ gl.drawElementsInstanced(gl.POINTS, 0, -1, vertices, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.drawElementsInstanced(gl.POINTS, 0, gl.FLOAT, vertices, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count or primcount are negative.');
+ gl.drawElementsInstanced(gl.POINTS, -1, gl.UNSIGNED_BYTE, vertices, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.drawElementsInstanced(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawElementsInstanced(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ if (!sglrGLContext.isExtensionSupported(gl, 'EXT_geometry_shader')) {// gl.EXT_geometry_shader removes error
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is active and not paused.');
+ /** @type{Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram (program.getProgram());
+ gl.transformFeedbackVaryings (program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram (program.getProgram());
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer (gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData (gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase (gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback (gl.POINTS);
+ this.expectError (gl.NO_ERROR);
+
+ gl.drawElementsInstanced (gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ gl.pauseTransformFeedback();
+ gl.drawElementsInstanced (gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError (gl.NO_ERROR);
+
+ gl.endTransformFeedback ();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(bufElements);
+ this.expectError (gl.NO_ERROR);
+
+ }
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_elements_instanced_invalid_program', 'Invalid gl.drawElementsInstanced() usage', gl, function() {
+ gl.useProgram(null);
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements;
+ bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ gl.vertexAttribDivisor(0, 1);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) is set.');
+ gl.drawElementsInstanced(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(bufElements);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_elements_instanced_incomplete_primitive', 'Invalid gl.drawElementsInstanced() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{WebGLBuffer} */ var buf;
+ /** @type{WebGLTransformFeedback} */ var tfID;
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements;
+ bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ gl.vertexAttribDivisor(0, 1);
+ this.expectError(gl.NO_ERROR);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawElementsInstanced(-1, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not one of the accepted values.');
+ gl.drawElementsInstanced(gl.TRIANGLES, 0, -1, vertices, 1);
+ this.expectError(gl.INVALID_ENUM);
+ gl.drawElementsInstanced(gl.TRIANGLES, 0, gl.FLOAT, vertices, 1);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count or primcount are negative.');
+ gl.drawElementsInstanced(gl.TRIANGLES, -1, gl.UNSIGNED_BYTE, vertices, 0);
+ this.expectError(gl.INVALID_VALUE);
+ gl.drawElementsInstanced(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices, -1);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawElementsInstanced(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ if (!sglrGLContext.isExtensionSupported(gl, 'EXT_geometry_shader')) {// gl.EXT_geometry_shader removes error
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is active and not paused.');
+ /** @type{Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram (program.getProgram());
+ gl.transformFeedbackVaryings (program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram (program.getProgram());
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer (gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData (gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase (gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback (gl.TRIANGLES);
+ this.expectError (gl.NO_ERROR);
+
+ gl.drawElementsInstanced (gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ gl.pauseTransformFeedback();
+ gl.drawElementsInstanced (gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices, 1);
+ this.expectError (gl.NO_ERROR);
+
+ gl.endTransformFeedback ();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(bufElements);
+ this.expectError (gl.NO_ERROR);
+
+ }
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_range_elements', 'Invalid gl.drawRangeElements() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{WebGLBuffer} */ var buf;
+ /** @type{WebGLTransformFeedback} */ var tfID;
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements;
+ bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawRangeElements(-1, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not one of the accepted values.');
+ gl.drawRangeElements(gl.POINTS, 0, 1, 0, -1, vertices);
+ this.expectError(gl.INVALID_ENUM);
+ gl.drawRangeElements(gl.POINTS, 0, 1, 0, gl.FLOAT, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
+ gl.drawRangeElements(gl.POINTS, 0, 1, -1, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if end < start.');
+ gl.drawRangeElements(gl.POINTS, 1, 0, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawRangeElements(gl.POINTS, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ if (!sglrGLContext.isExtensionSupported(gl, 'EXT_geometry_shader')) {// gl.EXT_geometry_shader removes error
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is active and not paused.');
+ /** @type{Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram (program.getProgram());
+ gl.transformFeedbackVaryings (program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram (program.getProgram());
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer (gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData (gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase (gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback (gl.POINTS);
+ this.expectError (gl.NO_ERROR);
+
+ gl.drawRangeElements (gl.POINTS, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ gl.pauseTransformFeedback();
+ gl.drawRangeElements (gl.POINTS, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.NO_ERROR);
+
+ gl.endTransformFeedback ();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(bufElements);
+ this.expectError (gl.NO_ERROR);
+
+ }
+
+ gl.useProgram(null);
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_range_elements_invalid_program', 'Invalid gl.drawRangeElements() usage', gl, function() {
+ gl.useProgram(null);
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements;
+ bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) is set.');
+ gl.drawRangeElements(gl.POINTS, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_OPERATION);
+
+ gl.deleteBuffer(bufElements);
+
+ }));
+
+ testGroup.addChild(new es3fApiCase.ApiCaseCallback('draw_range_elements_incomplete_primitive', 'Invalid gl.drawRangeElements() usage', gl, function() {
+ /** @type{gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl,gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+ gl.useProgram(program.getProgram());
+ /** @type{WebGLFramebuffer} */ var fbo;
+ /** @type{WebGLBuffer} */ var buf;
+ /** @type{WebGLTransformFeedback} */ var tfID;
+ /** @type{number} */ var vertices = 0;
+
+ /** @type{WebGLBuffer} */ var bufElements;
+ bufElements = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
+ gl.drawRangeElements(-1, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_ENUM is generated if type is not one of the accepted values.');
+ gl.drawRangeElements(gl.TRIANGLES, 0, 1, 0, -1, vertices);
+ this.expectError(gl.INVALID_ENUM);
+ gl.drawRangeElements(gl.TRIANGLES, 0, 1, 0, gl.FLOAT, vertices);
+ this.expectError(gl.INVALID_ENUM);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
+ gl.drawRangeElements(gl.TRIANGLES, 0, 1, -1, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_VALUE is generated if end < start.');
+ gl.drawRangeElements(gl.TRIANGLES, 1, 0, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_VALUE);
+
+ bufferedLogToConsole('gl.INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.');
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ gl.drawRangeElements(gl.TRIANGLES, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+
+ if (!sglrGLContext.isExtensionSupported(gl, 'EXT_geometry_shader')) {// gl.EXT_geometry_shader removes error
+ bufferedLogToConsole('gl.INVALID_OPERATION is generated if transform feedback is active and not paused.');
+ /** @type{Array<string>} */ var tfVarying = ['gl_Position'];
+
+ buf = gl.createBuffer();
+ tfID = gl.createTransformFeedback();
+
+ gl.useProgram (program.getProgram());
+ gl.transformFeedbackVaryings (program.getProgram(), tfVarying, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram (program.getProgram());
+ gl.bindTransformFeedback (gl.TRANSFORM_FEEDBACK, tfID);
+ gl.bindBuffer (gl.TRANSFORM_FEEDBACK_BUFFER, buf);
+ gl.bufferData (gl.TRANSFORM_FEEDBACK_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bindBufferBase (gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+ gl.beginTransformFeedback (gl.TRIANGLES);
+ this.expectError (gl.NO_ERROR);
+
+ gl.drawRangeElements (gl.TRIANGLES, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.INVALID_OPERATION);
+
+ gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
+
+ gl.pauseTransformFeedback();
+ gl.drawRangeElements (gl.TRIANGLES, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
+ this.expectError (gl.NO_ERROR);
+
+ gl.endTransformFeedback ();
+ gl.deleteBuffer(buf);
+ gl.deleteTransformFeedback(tfID);
+ gl.deleteBuffer(bufElements);
+ this.expectError (gl.NO_ERROR);
+
+ }
+
+ gl.useProgram(null);
+ }));
+ };
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ es3fNegativeVertexArrayApiTests.run = function(gl) {
+ var testName = 'vertex_array';
+ var testDescription = 'Negative Vertex Array API Cases';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fNegativeVertexArrayApiTests.init(gl);
+ tcuTestCase.runner.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fOcclusionQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fOcclusionQueryTests.js
new file mode 100644
index 0000000000..8549d657bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fOcclusionQueryTests.js
@@ -0,0 +1,511 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fOcclusionQueryTests');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+var es3fOcclusionQueryTests = functional.gles3.es3fOcclusionQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuLogImage = framework.common.tcuLogImage;
+var tcuSurface = framework.common.tcuSurface;
+var deRandom = framework.delibs.debase.deRandom;
+var deString = framework.delibs.debase.deString;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/** @const */ var DEPTH_WRITE_COLOR = [0, 0, 1, 1];
+/** @const */ var DEPTH_CLEAR_COLOR = [0, 0.5, 0.8, 1];
+/** @const */ var STENCIL_WRITE_COLOR = [0, 1, 0, 1];
+/** @const */ var STENCIL_CLEAR_COLOR = [0, 0.8, 0.5, 1];
+/** @const */ var TARGET_COLOR = [1, 0, 0, 1];
+/** @const */ var ELEMENTS_PER_VERTEX = 4;
+/** @const */ var NUM_CASE_ITERATIONS = 10;
+
+// Constants to tweak visible/invisible case probability balance.
+
+/** @const */ var DEPTH_CLEAR_OFFSET = 100;
+/** @const */ var STENCIL_CLEAR_OFFSET = 100;
+/** @const */ var SCISSOR_OFFSET = 100;
+/** @const */ var SCISSOR_MINSIZE = 250;
+
+/** @const */ var OCCLUDER_SCISSOR = (1 << 0);
+/** @const */ var OCCLUDER_DEPTH_WRITE = (1 << 1);
+/** @const */ var OCCLUDER_DEPTH_CLEAR = (1 << 2);
+/** @const */ var OCCLUDER_STENCIL_WRITE = (1 << 3);
+/** @const */ var OCCLUDER_STENCIL_CLEAR = (1 << 4);
+
+/**
+ * @enum
+ */
+es3fOcclusionQueryTests.State = {
+ DRAW: 0,
+ VERIFY: 1,
+ FINISH: 2
+};
+
+/* Maximum time to wait for query result (in seconds) */
+/** @const */ var MAX_VERIFY_WAIT = 5;
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fOcclusionQueryTests.OcclusionQueryCase = function(name, description, numOccluderDraws, numOccludersPerDraw, occluderSize, numTargetDraws, numTargetsPerDraw, targetSize, queryMode, occluderTypes) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_numOccluderDraws = numOccluderDraws;
+ this.m_numOccludersPerDraw = numOccludersPerDraw;
+ this.m_occluderSize = occluderSize;
+ this.m_numTargetDraws = numTargetDraws;
+ this.m_numTargetsPerDraw = numTargetsPerDraw;
+ this.m_targetSize = targetSize;
+ this.m_queryMode = queryMode;
+ this.m_occluderTypes = occluderTypes;
+ this.m_program = null;
+ this.m_iterNdx = 0;
+ this.m_rnd = new deRandom.Random(deString.deStringHash(name));
+ this.m_state = es3fOcclusionQueryTests.State.DRAW;
+ /** @type {WebGLQuery} */ this.m_query;
+};
+
+setParentClass(es3fOcclusionQueryTests.OcclusionQueryCase, tcuTestCase.DeqpTest);
+
+es3fOcclusionQueryTests.OcclusionQueryCase.prototype.generateVertices = function(width, height, primitiveCount, verticesPerPrimitive, rnd, primitiveSize, minZ, maxZ) {
+ var dst = [];
+ var w = width / 2;
+ var h = height / 2;
+ var s = primitiveSize / 2;
+
+ var vertexCount = verticesPerPrimitive * primitiveCount;
+
+ // First loop gets a random point inside unit square
+ for (var i = 0; i < vertexCount; i += 3) {
+ var rndX = rnd.getFloat(-w, w);
+ var rndY = rnd.getFloat(-h, h);
+
+ // Second loop gets 3 random points within given distance s from (rndX, rndY)
+ for (var j = 0; j < verticesPerPrimitive; j++) {
+ var offset = (i + j) * ELEMENTS_PER_VERTEX;
+ dst[offset] = rndX + rnd.getFloat(-s, s); // x
+ dst[offset + 1] = rndY + rnd.getFloat(-s, s); // y
+ dst[offset + 2] = rnd.getFloat(minZ, maxZ); // z
+ dst[offset + 3] = 1; // w
+ }
+ }
+ return dst;
+};
+
+es3fOcclusionQueryTests.OcclusionQueryCase.prototype.init = function() {
+ var vertShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) in mediump vec4 a_position;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+
+ var fragShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n' +
+ 'uniform mediump vec4 u_color;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float depth_gradient = gl_FragCoord.z;\n' +
+ ' mediump float bias = 0.1;\n' +
+ ' dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1);\n' +
+ '}\n';
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource));
+
+ if (!this.m_program.isOk())
+ testFailedOptions('Failed to compile program', true);
+
+ this.m_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_buffer);
+ gl.vertexAttribPointer(0, ELEMENTS_PER_VERTEX, gl.FLOAT, false, 0, 0);
+};
+
+es3fOcclusionQueryTests.OcclusionQueryCase.prototype.draw = function() {
+ var colorUnif = gl.getUniformLocation(this.m_program.getProgram(), 'u_color');
+
+ var targetW = gl.drawingBufferWidth;
+ var targetH = gl.drawingBufferHeight;
+
+ bufferedLogToConsole('Case iteration ' + (this.m_iterNdx + 1) + ' / ' + NUM_CASE_ITERATIONS);
+ bufferedLogToConsole('Parameters:\n' +
+ '- ' + this.m_numOccluderDraws + ' occluder draws, ' + this.m_numOccludersPerDraw + ' primitive writes per draw,\n' +
+ '- ' + this.m_numTargetDraws + ' target draws, ' + this.m_numTargetsPerDraw + ' targets per draw\n');
+
+ gl.clearColor(0, 0, 0, 1);
+ gl.clearDepth(1);
+ gl.clearStencil(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ gl.useProgram(this.m_program.getProgram());
+ gl.enableVertexAttribArray(0);
+
+ // Draw occluders
+
+ var occOptions = [];
+ if (this.m_occluderTypes & OCCLUDER_DEPTH_WRITE) occOptions.push(OCCLUDER_DEPTH_WRITE);
+ if (this.m_occluderTypes & OCCLUDER_DEPTH_CLEAR) occOptions.push(OCCLUDER_DEPTH_CLEAR);
+ if (this.m_occluderTypes & OCCLUDER_STENCIL_WRITE) occOptions.push(OCCLUDER_STENCIL_WRITE);
+ if (this.m_occluderTypes & OCCLUDER_STENCIL_CLEAR) occOptions.push(OCCLUDER_STENCIL_CLEAR);
+
+ for (var i = 0; i < this.m_numOccluderDraws; i++) {
+ if (occOptions.length == 0)
+ break;
+
+ var type = occOptions[this.m_rnd.getInt(0, occOptions.length - 1)]; // Choosing a random occluder type from available options
+
+ switch (type) {
+ case OCCLUDER_DEPTH_WRITE:
+ bufferedLogToConsole('Occluder draw ' + (i + 1) + ' / ' + this.m_numOccluderDraws + ' : ' + 'Depth write');
+
+ var occluderVertices = this.generateVertices(2, 2, this.m_numOccludersPerDraw, 3, this.m_rnd, this.m_occluderSize, 0, 0.6); // Generate vertices for occluding primitives
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.uniform4f(colorUnif, DEPTH_WRITE_COLOR[0], DEPTH_WRITE_COLOR[1], DEPTH_WRITE_COLOR[2], DEPTH_WRITE_COLOR[3]);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(occluderVertices), gl.STATIC_DRAW);
+ gl.drawArrays(gl.TRIANGLES, 0, 3 * this.m_numOccludersPerDraw);
+ gl.disable(gl.DEPTH_TEST);
+
+ break;
+
+ case OCCLUDER_DEPTH_CLEAR: {
+ var scissorBoxX = this.m_rnd.getInt(-DEPTH_CLEAR_OFFSET, targetW);
+ var scissorBoxY = this.m_rnd.getInt(-DEPTH_CLEAR_OFFSET, targetH);
+ var scissorBoxW = this.m_rnd.getInt(DEPTH_CLEAR_OFFSET, targetW + DEPTH_CLEAR_OFFSET);
+ var scissorBoxH = this.m_rnd.getInt(DEPTH_CLEAR_OFFSET, targetH + DEPTH_CLEAR_OFFSET);
+
+ bufferedLogToConsole('Occluder draw ' + (i + 1) + ' / ' + this.m_numOccluderDraws + ' : ' + 'Depth clear');
+ bufferedLogToConsole('Depth-clearing box drawn at ' +
+ '(' + scissorBoxX + ', ' + scissorBoxY + ')' +
+ ', width = ' + scissorBoxW + ', height = ' + scissorBoxH + '.');
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(scissorBoxX, scissorBoxY, scissorBoxW, scissorBoxH);
+ gl.clearDepth(0);
+ gl.clearColor(DEPTH_CLEAR_COLOR[0], DEPTH_CLEAR_COLOR[1], DEPTH_CLEAR_COLOR[2], DEPTH_CLEAR_COLOR[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.disable(gl.SCISSOR_TEST);
+
+ break;
+ }
+
+ case OCCLUDER_STENCIL_WRITE:
+ bufferedLogToConsole('Occluder draw ' + (i + 1) + ' / ' + this.m_numOccluderDraws + ' : ' + 'Stencil write');
+
+ occluderVertices = this.generateVertices(2, 2, this.m_numOccludersPerDraw, 3, this.m_rnd, this.m_occluderSize, 0, 0.6);
+
+ gl.stencilFunc(gl.ALWAYS, 1, 0xFF);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
+
+ gl.enable(gl.STENCIL_TEST);
+ gl.uniform4f(colorUnif, STENCIL_WRITE_COLOR[0], STENCIL_WRITE_COLOR[1], STENCIL_WRITE_COLOR[2], STENCIL_WRITE_COLOR[3]);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(occluderVertices), gl.STATIC_DRAW);
+ gl.drawArrays(gl.TRIANGLES, 0, 3 * this.m_numOccludersPerDraw);
+ gl.disable(gl.STENCIL_TEST);
+
+ break;
+
+ case OCCLUDER_STENCIL_CLEAR: {
+ var scissorBoxX = this.m_rnd.getInt(-STENCIL_CLEAR_OFFSET, targetW);
+ var scissorBoxY = this.m_rnd.getInt(-STENCIL_CLEAR_OFFSET, targetH);
+ var scissorBoxW = this.m_rnd.getInt(STENCIL_CLEAR_OFFSET, targetW + STENCIL_CLEAR_OFFSET);
+ var scissorBoxH = this.m_rnd.getInt(STENCIL_CLEAR_OFFSET, targetH + STENCIL_CLEAR_OFFSET);
+
+ bufferedLogToConsole('Occluder draw ' + (i + 1) + ' / ' + this.m_numOccluderDraws + ' : ' + 'Stencil clear');
+ bufferedLogToConsole('Stencil-clearing box drawn at ' +
+ '(' + scissorBoxX + ', ' + scissorBoxY + ')' +
+ ', width = ' + scissorBoxW + ', height = ' + scissorBoxH + '.');
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(scissorBoxX, scissorBoxY, scissorBoxW, scissorBoxH);
+ gl.clearStencil(1);
+ gl.clearColor(STENCIL_CLEAR_COLOR[0], STENCIL_CLEAR_COLOR[1], STENCIL_CLEAR_COLOR[2], STENCIL_CLEAR_COLOR[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ gl.disable(gl.SCISSOR_TEST);
+
+ break;
+ }
+
+ default:
+ throw new Error('Invalid occluder type: ' + type);
+ }
+ }
+
+ if (this.m_occluderTypes & OCCLUDER_SCISSOR) {
+ var scissorBoxX = this.m_rnd.getInt(-SCISSOR_OFFSET, targetW - SCISSOR_OFFSET);
+ var scissorBoxY = this.m_rnd.getInt(-SCISSOR_OFFSET, targetH - SCISSOR_OFFSET);
+ var scissorBoxW = this.m_rnd.getInt(SCISSOR_MINSIZE, targetW + SCISSOR_OFFSET);
+ var scissorBoxH = this.m_rnd.getInt(SCISSOR_MINSIZE, targetH + SCISSOR_OFFSET);
+
+ bufferedLogToConsole('Scissor box drawn at ' +
+ '(' + scissorBoxX + ', ' + scissorBoxY + ')' +
+ ', width = ' + scissorBoxW + ', height = ' + scissorBoxH + '.');
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(scissorBoxX, scissorBoxY, scissorBoxW, scissorBoxH);
+ }
+
+ this.m_query = gl.createQuery();
+ gl.beginQuery(this.m_queryMode, this.m_query);
+
+ // Draw target primitives
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.enable(gl.STENCIL_TEST);
+ gl.stencilFunc(gl.EQUAL, 0, 0xFF);
+
+ for (var i = 0; i < this.m_numTargetDraws; i++) {
+ var targetVertices = this.generateVertices(2, 2, this.m_numTargetsPerDraw, 3, this.m_rnd, this.m_targetSize, 0.4, 1); // Generate vertices for target primitives
+
+ if (targetVertices.length > 0) {
+ gl.uniform4f(colorUnif, TARGET_COLOR[0], TARGET_COLOR[1], TARGET_COLOR[2], TARGET_COLOR[3]);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(targetVertices), gl.STATIC_DRAW);
+ gl.drawArrays(gl.TRIANGLES, 0, 3 * this.m_numTargetsPerDraw);
+ }
+ }
+
+ gl.endQuery(this.m_queryMode);
+ gl.disable(gl.SCISSOR_TEST);
+ gl.disable(gl.STENCIL_TEST);
+ gl.disable(gl.DEPTH_TEST);
+ this.m_state = es3fOcclusionQueryTests.State.VERIFY;
+};
+
+es3fOcclusionQueryTests.OcclusionQueryCase.prototype.verify = function() {
+ // Check that query result is available.
+ var resultAvailable = /** @type {boolean} */ (gl.getQueryParameter(this.m_query, gl.QUERY_RESULT_AVAILABLE));
+ if (!resultAvailable) {
+ if (!this.m_verifyStart)
+ this.m_verifyStart = new Date();
+ else {
+ var current = new Date();
+ var elapsedTime = 0.001 * (current.getTime() - this.m_verifyStart.getTime());
+ if (elapsedTime > MAX_VERIFY_WAIT) {
+ testFailed('Query result not available after ' + elapsedTime + ' seconds.');
+ this.m_state = es3fOcclusionQueryTests.State.FINISH;
+ }
+ }
+ return;
+ }
+
+ // Read query result.
+ var result = /** @type {number} */ (gl.getQueryParameter(this.m_query, gl.QUERY_RESULT));
+ var queryResult = (result > 0);
+
+ gl.deleteQuery(this.m_query);
+
+ // Read pixel data
+
+ var pixels = new tcuSurface.Surface();
+ pixels.readViewport(gl);
+ var colorReadResult = false;
+ var width = pixels.getWidth();
+ var height = pixels.getHeight();
+
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ if (pixels.getPixel(x, y)[0] != 0) {
+ colorReadResult = true;
+ break;
+ }
+ }
+ if (colorReadResult) break;
+ }
+
+ var message = 'Occlusion query result: Target ' + (queryResult ? 'visible' : 'invisible') + '. ' +
+ 'Framebuffer read result: Target ' + (colorReadResult ? 'visible' : 'invisible');
+
+ var testOk = false;
+ if (this.m_queryMode == gl.ANY_SAMPLES_PASSED_CONSERVATIVE) {
+ if (queryResult || colorReadResult)
+ testOk = queryResult; // Allow conservative occlusion query to return false positives.
+ else
+ testOk = queryResult == colorReadResult;
+ } else
+ testOk = (queryResult == colorReadResult);
+
+ if (!testOk) {
+ tcuLogImage.logImage('Result image', 'Result image', pixels.getAccess());
+ testFailed(message);
+ this.m_state = es3fOcclusionQueryTests.State.FINISH;
+ return;
+ }
+
+ bufferedLogToConsole(message);
+ bufferedLogToConsole('Case passed!');
+
+ if (++this.m_iterNdx < NUM_CASE_ITERATIONS) {
+ this.m_state = es3fOcclusionQueryTests.State.DRAW
+ } else {
+ this.m_state = es3fOcclusionQueryTests.State.FINISH;
+ testPassed();
+ }
+};
+
+
+es3fOcclusionQueryTests.OcclusionQueryCase.prototype.iterate = function() {
+ switch(this.m_state) {
+ case es3fOcclusionQueryTests.State.DRAW:
+ this.draw();
+ break;
+ case es3fOcclusionQueryTests.State.VERIFY:
+ this.verify();
+ break;
+ case es3fOcclusionQueryTests.State.FINISH:
+ return tcuTestCase.IterateResult.STOP;
+ default:
+ throw new Error('Invalid state: ' + this.m_state);
+ }
+
+ return tcuTestCase.IterateResult.CONTINUE;
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fOcclusionQueryTests.OcclusionQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'occlusion_query', 'Occlusion Query Tests');
+};
+
+es3fOcclusionQueryTests.OcclusionQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fOcclusionQueryTests.OcclusionQueryTests.prototype.constructor = es3fOcclusionQueryTests.OcclusionQueryTests;
+
+es3fOcclusionQueryTests.OcclusionQueryTests.prototype.init = function() {
+ // Strict occlusion query cases
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor', 'scissor', 1, 10, 1.6, 1, 1, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write', 'depth_write', 8, 10, 1.6, 1, 7, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_clear', 'depth_clear', 5, 10, 1.6, 1, 5, 0.2, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('stencil_write', 'stencil_write', 8, 10, 2.0, 1, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('stencil_clear', 'stencil_clear', 5, 10, 2.0, 1, 3, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write', 'scissor_depth_write', 5, 10, 1.6, 2, 5, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_clear', 'scissor_depth_clear', 7, 10, 1.6, 2, 5, 1.0, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_stencil_write', 'scissor_stencil_write', 4, 10, 1.6, 2, 5, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_stencil_clear', 'scissor_stencil_clear', 4, 10, 1.6, 2, 5, 1.0, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_depth_clear', 'depth_write_depth_clear', 7, 10, 1.6, 1, 5, 0.2, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_stencil_write', 'depth_write_stencil_write', 8, 10, 1.6, 1, 5, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_stencil_clear', 'depth_write_stencil_clear', 8, 10, 1.6, 1, 5, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_clear_stencil_write', 'depth_clear_stencil_write', 8, 10, 1.6, 1, 5, 0.3, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_clear_stencil_clear', 'depth_clear_stencil_clear', 12, 10, 1.6, 1, 5, 0.2, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('stencil_write_stencil_clear', 'stencil_write_stencil_clear', 5, 10, 2.0, 1, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write_depth_clear', 'scissor_depth_write_depth_clear', 5, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write_stencil_write', 'scissor_depth_write_stencil_write', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write_stencil_clear', 'scissor_depth_write_stencil_clear', 6, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_clear_stencil_write', 'scissor_depth_clear_stencil_write', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_clear_stencil_clear', 'scissor_depth_clear_stencil_clear', 5, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_stencil_write_stencil_clear', 'scissor_stencil_write_stencil_clear', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_depth_clear_stencil_write', 'depth_write_depth_clear_stencil_write', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_depth_clear_stencil_clear', 'depth_write_depth_clear_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_stencil_write_stencil_clear', 'depth_write_stencil_write_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_clear_stencil_write_stencil_clear', 'depth_clear_stencil_write_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write_depth_clear_stencil_write', 'scissor_depth_write_depth_clear_stencil_write', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write_depth_clear_stencil_clear', 'scissor_depth_write_depth_clear_stencil_clear', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_write_stencil_write_stencil_clear', 'scissor_depth_write_stencil_write_stencil_clear', 5, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('scissor_depth_clear_stencil_write_stencil_clear', 'scissor_depth_clear_stencil_write_stencil_clear', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('depth_write_depth_clear_stencil_write_stencil_clear', 'depth_write_depth_clear_stencil_write_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('all_occluders', 'all_occluders', 7, 10, 1.6, 3, 5, 0.6, gl.ANY_SAMPLES_PASSED, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ // Conservative occlusion query cases
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor', 'conservative_scissor', 1, 10, 1.6, 1, 1, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write', 'conservative_depth_write', 8, 10, 1.6, 1, 7, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_clear', 'conservative_depth_clear', 5, 10, 1.6, 1, 5, 0.2, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_stencil_write', 'conservative_stencil_write', 8, 10, 2.0, 1, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_stencil_clear', 'conservative_stencil_clear', 5, 10, 2.0, 1, 3, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write', 'conservative_scissor_depth_write', 5, 10, 1.6, 2, 5, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_clear', 'conservative_scissor_depth_clear', 7, 10, 1.6, 2, 5, 1.0, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_stencil_write', 'conservative_scissor_stencil_write', 4, 10, 1.6, 2, 5, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_stencil_clear', 'conservative_scissor_stencil_clear', 4, 10, 1.6, 2, 5, 1.0, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_depth_clear', 'conservative_depth_write_depth_clear', 7, 10, 1.6, 1, 5, 0.2, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_stencil_write', 'conservative_depth_write_stencil_write', 8, 10, 1.6, 1, 5, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_stencil_clear', 'conservative_depth_write_stencil_clear', 8, 10, 1.6, 1, 5, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_clear_stencil_write', 'conservative_depth_clear_stencil_write', 8, 10, 1.6, 1, 5, 0.3, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_clear_stencil_clear', 'conservative_depth_clear_stencil_clear', 12, 10, 1.6, 1, 5, 0.2, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_stencil_write_stencil_clear', 'conservative_stencil_write_stencil_clear', 5, 10, 2.0, 1, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write_depth_clear', 'conservative_scissor_depth_write_depth_clear', 5, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write_stencil_write', 'conservative_scissor_depth_write_stencil_write', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write_stencil_clear', 'conservative_scissor_depth_write_stencil_clear', 6, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_clear_stencil_write', 'conservative_scissor_depth_clear_stencil_write', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_clear_stencil_clear', 'conservative_scissor_depth_clear_stencil_clear', 5, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_stencil_write_stencil_clear', 'conservative_scissor_stencil_write_stencil_clear', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_depth_clear_stencil_write', 'conservative_depth_write_depth_clear_stencil_write', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_depth_clear_stencil_clear', 'conservative_depth_write_depth_clear_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_stencil_write_stencil_clear', 'conservative_depth_write_stencil_write_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_clear_stencil_write_stencil_clear', 'conservative_depth_clear_stencil_write_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write_depth_clear_stencil_write', 'conservative_scissor_depth_write_depth_clear_stencil_write', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write_depth_clear_stencil_clear', 'conservative_scissor_depth_write_depth_clear_stencil_clear', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_write_stencil_write_stencil_clear', 'conservative_scissor_depth_write_stencil_write_stencil_clear', 5, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_scissor_depth_clear_stencil_write_stencil_clear', 'conservative_scissor_depth_clear_stencil_write_stencil_clear', 4, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_depth_write_depth_clear_stencil_write_stencil_clear', 'conservative_depth_write_depth_clear_stencil_write_stencil_clear', 7, 10, 1.6, 2, 5, 0.4, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+ this.addChild(new es3fOcclusionQueryTests.OcclusionQueryCase('conservative_all_occluders', 'conservative_all_occluders', 7, 10, 1.6, 3, 5, 0.6, gl.ANY_SAMPLES_PASSED_CONSERVATIVE, OCCLUDER_SCISSOR | OCCLUDER_DEPTH_WRITE | OCCLUDER_DEPTH_CLEAR | OCCLUDER_STENCIL_WRITE | OCCLUDER_STENCIL_CLEAR));
+
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fOcclusionQueryTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fOcclusionQueryTests.OcclusionQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fOcclusionQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPixelBufferObjectTest.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPixelBufferObjectTest.js
new file mode 100644
index 0000000000..ac577193aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPixelBufferObjectTest.js
@@ -0,0 +1,585 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fPixelBufferObjectTest');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var es3fPixelBufferObjectTest = functional.gles3.es3fPixelBufferObjectTest;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuTestCase = framework.common.tcuTestCase;
+var deRandom = framework.delibs.debase.deRandom;
+var deString = framework.delibs.debase.deString;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuImageCompare = framework.common.tcuImageCompare;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ es3fPixelBufferObjectTest.DE_STATIC_ASSERT = function(expression) {
+ if (!expression) throw new Error('Assert failed');
+ };
+
+ /** @enum */
+ es3fPixelBufferObjectTest.FramebufferType = {
+ FRAMEBUFFERTYPE_NATIVE: 0,
+ FRAMEBUFFERTYPE_RENDERBUFFER: 1
+ };
+
+ /**
+ * @constructor
+ * @struct
+ */
+ es3fPixelBufferObjectTest.TestSpec = function() { // This is originaly a struct
+ this.name = '';
+ this.description = '';
+ this.useColorClear = false;
+ this.renderTriangles = false;
+ /** @type {es3fPixelBufferObjectTest.FramebufferType} */ this.framebufferType;
+ /** @type {number} */ this.renderbufferFormat;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {es3fPixelBufferObjectTest.TestSpec} spec
+ */
+ es3fPixelBufferObjectTest.ReadPixelsTest = function(spec) {
+ tcuTestCase.DeqpTest.call(this, spec.name, spec.description);
+ this.m_random = new deRandom.Random(deString.deStringHash(spec.name));
+ this.m_program = null;
+ this.m_framebuffeType = spec.framebufferType;
+ this.m_renderbufferFormat = spec.renderbufferFormat;
+ this.m_texChannelClass = undefined;
+ this.m_useColorClears = spec.useColorClear;
+ this.m_renderTriangles = spec.renderTriangles;
+ this.m_colorScale = 1.0;
+
+ if (this.m_framebuffeType === es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE) {
+ this.m_colorScale = 1.0;
+ } else if (this.m_framebuffeType === es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_RENDERBUFFER) {
+ this.m_texChannelClass = tcuTexture.getTextureChannelClass(gluTextureUtil.mapGLInternalFormat(spec.renderbufferFormat).type);
+ switch (this.m_texChannelClass) {
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ this.m_colorScale = 1.0;
+ break;
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ this.m_colorScale = 100.0;
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ this.m_colorScale = 100.0;
+ break;
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ this.m_colorScale = 100.0;
+ break;
+ default:
+ DE_ASSERT(false);
+ }
+ } else {
+ DE_ASSERT(false);
+ }
+ };
+
+ es3fPixelBufferObjectTest.ReadPixelsTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fPixelBufferObjectTest.ReadPixelsTest.prototype.constructor = es3fPixelBufferObjectTest.ReadPixelsTest;
+
+ es3fPixelBufferObjectTest.ReadPixelsTest.prototype.init = function() {
+ var outtype = '';
+
+ if (this.m_framebuffeType === es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE)
+ outtype = 'vec4';
+ else if (this.m_framebuffeType === es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_RENDERBUFFER) {
+ switch (this.m_texChannelClass) {
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ outtype = 'vec4';
+ break;
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ outtype = 'ivec4';
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ outtype = 'uvec4';
+ break;
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ outtype = 'vec4';
+ break;
+ default:
+ DE_ASSERT(false);
+ }
+ } else
+ DE_ASSERT(false);
+
+ /** @type {string} */ var vertexShaderSource =
+ '#version 300 es\n' +
+ 'in mediump vec3 a_position;\n' +
+ 'in mediump vec4 a_color;\n' +
+ 'uniform mediump float u_colorScale;\n' +
+ 'out mediump vec4 v_color;\n' +
+ 'void main(void)\n' +
+ ' {\n' +
+ '\tgl_Position = vec4(a_position, 1.0);\n' +
+ '\tv_color = u_colorScale * a_color;\n' +
+ '}';
+
+ /** @type {string} */ var fragmentShaderSource =
+ '#version 300 es\n' +
+ 'in mediump vec4 v_color;\n' +
+ 'layout (location = 0) out mediump ' +
+ outtype +
+ ' o_color;\n' +
+ 'void main(void)\n' +
+ ' {\n' +
+ '\to_color = ' +
+ outtype +
+ '(v_color);\n' +
+ '}';
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+
+ if (!this.m_program.isOk())
+ throw new Error('Compile failed. Program not created');
+
+ };
+
+ /**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @param {Array<number>} c
+ */
+ es3fPixelBufferObjectTest.ReadPixelsTest.prototype.renderTriangle = function(a, b, c) {
+
+ var positions = new Float32Array(36);
+
+ positions[0] = a[0];
+ positions[1] = a[1];
+ positions[2] = a[2];
+
+ positions[3] = b[0];
+ positions[4] = b[1];
+ positions[5] = b[2];
+
+ positions[6] = c[0];
+ positions[7] = c[1];
+ positions[8] = c[2];
+
+ var colors = new Float32Array([
+ 1.0, 0.0, 0.0, 1.0,
+ 0.0, 1.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0, 1.0]);
+
+ gl.useProgram(this.m_program.getProgram());
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'useProgram failed ', false, true);
+
+ /** @type {WebGLUniformLocation} */ var colorScaleLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_colorScale');
+ assertMsgOptions(colorScaleLoc != -1, 'Could not find u_colorScale ', false, true);
+
+ gl.uniform1f(colorScaleLoc, this.m_colorScale);
+
+ /** @type {number} */ var coordLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ assertMsgOptions(coordLoc != -1, 'Could not find a_position ', false, true);
+
+ /** @type {number} */ var colorLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_color');
+ assertMsgOptions(colorLoc != -1, 'Could not find a_color ', false, true);
+
+ gl.enableVertexAttribArray(colorLoc);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'enableVertexAttribArray failed ', false, true);
+ gl.enableVertexAttribArray(coordLoc);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'enableVertexAttribArray failed ', false, true);
+
+ var pos = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, pos);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(coordLoc, 3, gl.FLOAT, false, 0, 0);
+
+ var c = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, c);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ gl.disableVertexAttribArray(colorLoc);
+ gl.disableVertexAttribArray(coordLoc);
+ };
+
+ /**
+ * @param {number} r
+ * @param {number} g
+ * @param {number} b
+ * @param {number} a
+ */
+
+ es3fPixelBufferObjectTest.ReadPixelsTest.prototype.clearColor = function(r, g, b, a) {
+ if (this.m_framebuffeType == es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE) {
+ gl.clearColor(r, g, b, a);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ } else if (this.m_framebuffeType == es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_RENDERBUFFER) {
+ switch (this.m_texChannelClass) {
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ gl.clearColor(r, g, b, a);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ break;
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ gl.clearBufferiv(gl.COLOR, 0, new Int32Array([r, g, b, a]));
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ gl.clearBufferuiv(gl.COLOR, 0, new Uint32Array([r, g, b, a]));
+ break;
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ gl.clearBufferfv(gl.COLOR, 0, new Float32Array([r, g, b, a]));
+ break;
+ default:
+ DE_ASSERT(false);
+ }
+ } else
+ DE_ASSERT(false);
+
+ };
+
+ es3fPixelBufferObjectTest.ReadPixelsTest.prototype.iterate = function() {
+ var width = gl.drawingBufferWidth;
+ var height = gl.drawingBufferHeight;
+
+ var framebuffer = null;
+ var renderbuffer = null;
+
+ switch (this.m_framebuffeType) {
+ case es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE:
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ break;
+ case es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_RENDERBUFFER:
+ framebuffer = gl.createFramebuffer();
+ renderbuffer = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, this.m_renderbufferFormat, width, height);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer);
+ break;
+ }
+
+ this.clearColor(this.m_colorScale * 0.4, this.m_colorScale * 1.0, this.m_colorScale * 0.5, this.m_colorScale * 1.0);
+
+ if (this.m_useColorClears) {
+ /** @type {number} */ var maxClearCount = 10;
+ /** @type {number} */ var minClearCount = 6;
+ /** @type {number} */ var minClearSize = 15;
+
+ /** @type {number} */ var clearCount = this.m_random.getInt(minClearCount, maxClearCount);
+
+ for (var clearNdx = 0; clearNdx < clearCount; clearNdx++) {
+ /** @type {number} */ var clearX = this.m_random.getInt(0, width - minClearSize);
+ /** @type {number} */ var clearY = this.m_random.getInt(0, height - minClearSize);
+
+ /** @type {number} */ var clearWidth = this.m_random.getInt(minClearSize, width - clearX);
+ /** @type {number} */ var clearHeight = this.m_random.getInt(minClearSize, height - clearY);
+
+ /** @type {number} */ var clearRed = this.m_colorScale * this.m_random.getFloat();
+ /** @type {number} */ var clearGreen = this.m_colorScale * this.m_random.getFloat();
+ /** @type {number} */ var clearBlue = this.m_colorScale * this.m_random.getFloat();
+ /** @type {number} */ var clearAlpha = this.m_colorScale * (0.5 + 0.5 * this.m_random.getFloat());
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(clearX, clearY, clearWidth, clearHeight);
+
+ this.clearColor(clearRed, clearGreen, clearBlue, clearAlpha);
+ }
+
+ gl.disable(gl.SCISSOR_TEST);
+
+ }
+
+ if (this.m_renderTriangles) {
+ /** @type {number} */ var minTriangleCount = 4;
+ /** @type {number} */ var maxTriangleCount = 10;
+
+ /** @type {number} */ var triangleCount = this.m_random.getInt(minTriangleCount, maxTriangleCount);
+
+ for (var triangleNdx = 0; triangleNdx < triangleCount; triangleNdx++) {
+ /** @type {number} */ var x1 = 2.0 * this.m_random.getFloat() - 1.0;
+ /** @type {number} */ var y1 = 2.0 * this.m_random.getFloat() - 1.0;
+ /** @type {number} */ var z1 = 2.0 * this.m_random.getFloat() - 1.0;
+
+ /** @type {number} */ var x2 = 2.0 * this.m_random.getFloat() - 1.0;
+ /** @type {number} */ var y2 = 2.0 * this.m_random.getFloat() - 1.0;
+ /** @type {number} */ var z2 = 2.0 * this.m_random.getFloat() - 1.0;
+
+ /** @type {number} */ var x3 = 2.0 * this.m_random.getFloat() - 1.0;
+ /** @type {number} */ var y3 = 2.0 * this.m_random.getFloat() - 1.0;
+ /** @type {number} */ var z3 = 2.0 * this.m_random.getFloat() - 1.0;
+
+ this.renderTriangle([x1, y1, z1], [x2, y2, z2], [x3, y3, z3]);
+ }
+ }
+
+ /** @type {tcuTexture.TextureFormat} */ var readFormat;
+ /** @type {number} */ var readPixelsFormat;
+ /** @type {number} */ var readPixelsType;
+ /** @type {boolean} */ var floatCompare;
+
+ if (this.m_framebuffeType == es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE) {
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA, gl.UNSIGNED_BYTE);
+ readPixelsFormat = gl.RGBA;
+ readPixelsType = gl.UNSIGNED_BYTE;
+ floatCompare = false;
+ } else if (this.m_framebuffeType == es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_RENDERBUFFER) {
+ switch (this.m_texChannelClass) {
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA, gl.UNSIGNED_BYTE);
+ readPixelsFormat = gl.RGBA;
+ readPixelsType = gl.UNSIGNED_BYTE;
+ floatCompare = true;
+ break;
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA_INTEGER, gl.INT);
+ readPixelsFormat = gl.RGBA_INTEGER;
+ readPixelsType = gl.INT;
+ floatCompare = false;
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA_INTEGER, gl.UNSIGNED_INT);
+ readPixelsFormat = gl.RGBA_INTEGER;
+ readPixelsType = gl.UNSIGNED_INT;
+ floatCompare = false;
+ break;
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA, gl.FLOAT);
+ readPixelsFormat = gl.RGBA;
+ readPixelsType = gl.FLOAT;
+ floatCompare = true;
+ break;
+ default:
+ DE_ASSERT(false);
+ // Silence warning
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA, gl.FLOAT);
+ readPixelsFormat = gl.RGBA;
+ readPixelsType = gl.FLOAT;
+ floatCompare = true;
+ }
+ } else {
+ // Silence warnings
+ readFormat = gluTextureUtil.mapGLTransferFormat(gl.RGBA, gl.FLOAT);
+ readPixelsFormat = gl.RGBA;
+ readPixelsType = gl.FLOAT;
+ floatCompare = true;
+ DE_ASSERT(false);
+ }
+
+ var readReference = new tcuTexture.Texture2D(readFormat, width, height);
+ readReference.allocLevel(0);
+
+ var pixelBuffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pixelBuffer);
+ gl.bufferData(gl.PIXEL_PACK_BUFFER, readReference.getLevel(0).getDataSize(), gl.STREAM_READ);
+ gl.readPixels(0, 0, width, height, readPixelsFormat, readPixelsType, 0);
+
+ var bufferData = new Uint8Array(readReference.getLevel(0).getDataSize());
+
+ gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, bufferData);
+
+ var readResult = new tcuTexture.ConstPixelBufferAccess({
+ width: width,
+ height: height,
+ format: readFormat,
+ data: bufferData.buffer});
+
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
+
+ gl.readPixels(0, 0, width, height, readPixelsFormat, readPixelsType, readReference.getLevel(0).getDataPtr());
+
+ if (framebuffer)
+ gl.deleteFramebuffer(framebuffer);
+
+ if (renderbuffer)
+ gl.deleteRenderbuffer(renderbuffer);
+
+ var isOk = false;
+
+ if (floatCompare) {
+ // When converting between integers and floats, certain GPUs might have different behaviors
+ // from javascript in rounding (up vs down). Increase tolerance to allow both behaviors.
+ // Detailed discussion in Mesa upstream can be found at:
+ // https://bugs.freedesktop.org/show_bug.cgi?id=89314.
+ var threshold;
+ switch (this.m_renderbufferFormat) {
+ case gl.RGB10_A2:
+ case gl.RGB5_A1:
+ case gl.RGB565:
+ threshold = [0.004, 0.004, 0.004, 0.0];
+ break;
+ default:
+ threshold = [0.0, 0.0, 0.0, 0.0];
+ break;
+ }
+ isOk = tcuImageCompare.floatThresholdCompare('Result comparison', 'Result of read pixels to memory compared with result of read pixels to buffer', readReference.getLevel(0), readResult, threshold);
+ }
+ else
+ isOk = tcuImageCompare.intThresholdCompare('Result comparison', 'Result of read pixels to memory compared with result of read pixels to buffer', readReference.getLevel(0), readResult, [0, 0, 0, 0]);
+
+ gl.deleteBuffer(pixelBuffer);
+
+ assertMsgOptions(isOk, this.getDescription(), true, true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ es3fPixelBufferObjectTest.init = function() {
+ var state = tcuTestCase.runner;
+ /** @type {tcuTestCase.DeqpTest} */ var testGroup = state.testCases;
+
+ /** @type {tcuTestCase.DeqpTest} */ var nativeFramebufferGroup = tcuTestCase.newTest('native', 'Tests with reading from native framebuffer');
+
+ var nativeFramebufferTests = [{
+ name: 'clears',
+ description: 'Simple read pixels test with color clears',
+ useColorClear: true,
+ renderTriangles: false,
+ framebufferType: es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE,
+ renderbufferFormat: gl.NONE
+ }, {
+ name: 'triangles',
+ description: 'Simple read pixels test rendering triangles',
+ useColorClear: false,
+ renderTriangles: true,
+ framebufferType: es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_NATIVE,
+ renderbufferFormat: gl.NONE
+ }
+ ];
+
+ for (var testNdx = 0; testNdx < nativeFramebufferTests.length; testNdx++)
+ nativeFramebufferGroup.addChild(new es3fPixelBufferObjectTest.ReadPixelsTest(nativeFramebufferTests[testNdx]));
+
+ testGroup.addChild(nativeFramebufferGroup);
+
+ /** @type {tcuTestCase.DeqpTest} */ var renderbufferGroup = tcuTestCase.newTest('renderbuffer', 'Tests with reading from renderbuffer');
+
+ var renderbufferFormats = [
+ gl.RGBA8,
+ gl.RGBA8I,
+ gl.RGBA8UI,
+ gl.RGBA16I,
+ gl.RGBA16UI,
+ gl.RGBA32I,
+ gl.RGBA32UI,
+
+ gl.SRGB8_ALPHA8,
+ gl.RGB10_A2,
+ gl.RGB10_A2UI,
+ gl.RGBA4,
+ gl.RGB5_A1,
+
+ gl.RGB8,
+ gl.RGB565,
+
+ gl.RG8,
+ gl.RG8I,
+ gl.RG8UI,
+ gl.RG16I,
+ gl.RG16UI,
+ gl.RG32I,
+ gl.RG32UI
+ ];
+
+ var renderbufferFormatsStr = [
+ 'rgba8',
+ 'rgba8i',
+ 'rgba8ui',
+ 'rgba16i',
+ 'rgba16ui',
+ 'rgba32i',
+ 'rgba32ui',
+
+ 'srgb8_alpha8',
+ 'rgb10_a2',
+ 'rgb10_a2ui',
+ 'rgba4',
+ 'rgb5_a1',
+
+ 'rgb8',
+ 'rgb565',
+
+ 'rg8',
+ 'rg8i',
+ 'rg8ui',
+ 'rg16i',
+ 'rg16ui',
+ 'rg32i',
+ 'rg32ui'
+ ];
+ es3fPixelBufferObjectTest.DE_STATIC_ASSERT(renderbufferFormatsStr.length == renderbufferFormats.length);
+
+ for (var formatNdx = 0; formatNdx < renderbufferFormats.length; formatNdx++) {
+ for (var trianglesClears = 0; trianglesClears < 2; trianglesClears++) {
+ var nameDescription = renderbufferFormatsStr[formatNdx] + '_' + (trianglesClears == 0 ? 'triangles' : 'clears');
+ var testSpec = new es3fPixelBufferObjectTest.TestSpec();
+ testSpec.name = nameDescription;
+ testSpec.description = nameDescription;
+ testSpec.useColorClear = trianglesClears == 1;
+ testSpec.renderTriangles = trianglesClears == 0;
+ testSpec.framebufferType = es3fPixelBufferObjectTest.FramebufferType.FRAMEBUFFERTYPE_RENDERBUFFER;
+ testSpec.renderbufferFormat = renderbufferFormats[formatNdx];
+
+ renderbufferGroup.addChild(new es3fPixelBufferObjectTest.ReadPixelsTest(testSpec));
+ }
+ }
+
+ testGroup.addChild(renderbufferGroup);
+ };
+
+ es3fPixelBufferObjectTest.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'pixel_buffer_object';
+ var testDescription = 'Pixel Buffer Object Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fPixelBufferObjectTest.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPrimitiveRestartTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPrimitiveRestartTests.js
new file mode 100644
index 0000000000..ac0da2fe66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fPrimitiveRestartTests.js
@@ -0,0 +1,709 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fPrimitiveRestartTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var es3fPrimitiveRestartTests = functional.gles3.es3fPrimitiveRestartTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuSurface = framework.common.tcuSurface;
+var deMath = framework.delibs.debase.deMath;
+var deRandom = framework.delibs.debase.deRandom;
+var deString = framework.delibs.debase.deString;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+ /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_RENDER_WIDTH = 256;
+ /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_RENDER_HEIGHT = 256;
+
+ /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_UNSIGNED_BYTE = 255;
+ /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_UNSIGNED_SHORT = 65535;
+ /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_UNSIGNED_INT = 4294967295;
+
+ /** @const @type {number} */ es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE = es3fPrimitiveRestartTests.MAX_UNSIGNED_BYTE;
+ /** @const @type {number} */ es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT = es3fPrimitiveRestartTests.MAX_UNSIGNED_SHORT;
+ /** @const @type {number} */ es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT = es3fPrimitiveRestartTests.MAX_UNSIGNED_INT;
+
+ var DE_ASSERT = function(expression) {
+ if (!expression) throw new Error('Assert failed');
+ };
+
+ /**
+ * @enum
+ */
+ es3fPrimitiveRestartTests.PrimitiveType = {
+ PRIMITIVE_POINTS: 0,
+ PRIMITIVE_LINE_STRIP: 1,
+ PRIMITIVE_LINE_LOOP: 2,
+ PRIMITIVE_LINES: 3,
+ PRIMITIVE_TRIANGLE_STRIP: 4,
+ PRIMITIVE_TRIANGLE_FAN: 5,
+ PRIMITIVE_TRIANGLES: 6
+ };
+
+ /**
+ * @enum
+ */
+ es3fPrimitiveRestartTests.IndexType = {
+ INDEX_UNSIGNED_BYTE: 0,
+ INDEX_UNSIGNED_SHORT: 1,
+ INDEX_UNSIGNED_INT: 2
+ };
+
+ /**
+ * @enum
+ */
+ es3fPrimitiveRestartTests.DrawFunction = {
+ FUNCTION_DRAW_ELEMENTS: 0,
+ FUNCTION_DRAW_ELEMENTS_INSTANCED: 1,
+ FUNCTION_DRAW_RANGE_ELEMENTS: 2
+ };
+
+ /**
+ * es3fPrimitiveRestartTests.PrimitiveRestartCase class, inherits from TestCase class
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {?string} name
+ * @param {string} description
+ * @param {es3fPrimitiveRestartTests.PrimitiveType} primType
+ * @param {es3fPrimitiveRestartTests.IndexType} indexType
+ * @param {es3fPrimitiveRestartTests.DrawFunction} _function
+ * @param {boolean} beginWithRestart
+ * @param {boolean} endWithRestart
+ * @param {boolean} duplicateRestarts
+ */
+ es3fPrimitiveRestartTests.PrimitiveRestartCase = function(name, description, primType, indexType, _function, beginWithRestart, endWithRestart, duplicateRestarts) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {es3fPrimitiveRestartTests.PrimitiveType} */ this.m_primType = primType;
+ /** @type {es3fPrimitiveRestartTests.IndexType} */ this.m_indexType = indexType;
+ /** @type {es3fPrimitiveRestartTests.DrawFunction} */ this.m_function = _function;
+ /** @type {boolean} */ this.m_beginWithRestart = beginWithRestart; // Whether there will be restart indices at the beginning of the index array.
+ /** @type {boolean} */ this.m_endWithRestart = endWithRestart; // Whether there will be restart indices at the end of the index array.
+ /** @type {boolean} */ this.m_duplicateRestarts = duplicateRestarts; // Whether two consecutive restarts are used instead of one.
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+
+ // \note Only one of the following index vectors is used (according to m_indexType).
+ /** @type {Array<number>} */ this.m_indicesUB = []; //deUint8
+ /** @type {Array<number>} */ this.m_indicesUS = []; //deUint16
+ /** @type {Array<number>} */ this.m_indicesUI = []; //deUint32
+
+ /** @type {Array<number>} */ this.m_positions = [];
+ };
+
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.constructor = es3fPrimitiveRestartTests.PrimitiveRestartCase;
+
+ /**
+ * Draw with the appropriate GLES3 draw function.
+ * @param {number} startNdx
+ * @param {number} count
+ */
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.draw = function(startNdx, count) {
+ /** @type {number} */ var primTypeGL;
+
+ switch (this.m_primType) {
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS:
+ primTypeGL = gl.POINTS;
+ break;
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_STRIP:
+ primTypeGL = gl.LINE_STRIP;
+ break;
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_LOOP:
+ primTypeGL = gl.LINE_LOOP;
+ break;
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINES:
+ primTypeGL = gl.LINES;
+ break;
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_STRIP:
+ primTypeGL = gl.TRIANGLE_STRIP;
+ break;
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_FAN:
+ primTypeGL = gl.TRIANGLE_FAN;
+ break;
+ case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLES:
+ primTypeGL = gl.TRIANGLES;
+ break;
+ default:
+ DE_ASSERT(false);
+ primTypeGL = 0;
+ }
+
+ /** @type {number} */ var indexTypeGL;
+
+ switch (this.m_indexType) {
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE:
+ indexTypeGL = gl.UNSIGNED_BYTE;
+ break;
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT:
+ indexTypeGL = gl.UNSIGNED_SHORT;
+ break;
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT:
+ indexTypeGL = gl.UNSIGNED_INT;
+ break;
+ default:
+ DE_ASSERT(false);
+ indexTypeGL = 0;
+ }
+
+ /** @type {number} */ var restartIndex = this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE :
+ this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT :
+ this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT :
+ 0;
+
+ DE_ASSERT(restartIndex != 0);
+
+ var indexGLBuffer = gl.createBuffer();
+ var bufferIndex = this.getIndexPtr(startNdx);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexGLBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferIndex, gl.STATIC_DRAW);
+
+ if (this.m_function == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS) {
+ gl.drawElements(primTypeGL, count, indexTypeGL, 0);
+ } else if (this.m_function == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED) {
+ gl.drawElementsInstanced(primTypeGL, count, indexTypeGL, 0, 1);
+ } else {
+ DE_ASSERT(this.m_function == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_RANGE_ELEMENTS);
+
+ // Find the largest non-restart index in the index array (for glDrawRangeElements() end parameter).
+
+ /** @type {number} */ var max = 0;
+
+ /** @type {number} */ var numIndices = this.getNumIndices();
+ for (var i = 0; i < numIndices; i++) {
+ /** @type {number} */ var index = this.getIndex(i);
+ if (index != restartIndex && index > max)
+ max = index;
+ }
+ //TODO: drawRangeElements -> check getIndexPtr usage
+ gl.drawRangeElements(primTypeGL, 0, max, count, indexTypeGL, 0);
+ }
+ };
+
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.renderWithRestart = function() {
+ // Primitive Restart is always on in WebGL2
+ //gl.enable(gl.PRIMITIVE_RESTART_FIXED_INDEX);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ this.draw(0, this.getNumIndices());
+ };
+
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.renderWithoutRestart = function() {
+ /** @type {number} */ var restartIndex = this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE :
+ this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT :
+ this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT :
+ 0;
+
+ DE_ASSERT(restartIndex != 0);
+ // Primitive Restart is always on in WebGL2
+ //gl.disable(gl.PRIMITIVE_RESTART_FIXED_INDEX);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Draw, emulating primitive restart.
+
+ /** @type {number} */ var numIndices = this.getNumIndices();
+
+ DE_ASSERT(numIndices >= 0);
+
+ /** @type {number} */ var indexArrayStartNdx = 0; // Keep track of the draw start index - first index after a primitive restart, or initially the first index altogether.
+
+ for (var indexArrayNdx = 0; indexArrayNdx <= numIndices; indexArrayNdx++) { // \note Goes one "too far" in order to detect end of array as well.
+ if (indexArrayNdx >= numIndices || this.getIndex(indexArrayNdx) == restartIndex) {// \note Handle end of array the same way as a restart index encounter.
+ if (indexArrayStartNdx < numIndices) {
+ // Draw from index indexArrayStartNdx to index indexArrayNdx-1 .
+
+ this.draw(indexArrayStartNdx, indexArrayNdx - indexArrayStartNdx);
+ }
+
+ indexArrayStartNdx = indexArrayNdx + 1; // Next draw starts just after this restart index.
+ }
+ }
+ };
+
+ /**
+ * @param {number} index
+ */
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.addIndex = function(index) {
+ if (this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE) {
+ DE_ASSERT(deMath.deInRange32(index, 0, es3fPrimitiveRestartTests.MAX_UNSIGNED_BYTE));
+ this.m_indicesUB.push(index); // deUint8
+ } else if (this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT) {
+ DE_ASSERT(deMath.deInRange32(index, 0, es3fPrimitiveRestartTests.MAX_UNSIGNED_SHORT));
+ this.m_indicesUS.push(index); // deUint16
+ } else if (this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT) {
+ DE_ASSERT(deMath.deInRange32(index, 0, es3fPrimitiveRestartTests.MAX_UNSIGNED_INT));
+ this.m_indicesUI.push(index); // // deUint32
+ } else
+ DE_ASSERT(false);
+ };
+
+ /**
+ * @param {number} indexNdx
+ * @return {number}
+ */
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.getIndex = function(indexNdx) {
+ switch (this.m_indexType) {
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE:
+ return this.m_indicesUB[indexNdx]; //deUint32
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT:
+ return this.m_indicesUS[indexNdx]; //deUint32
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT:
+ return this.m_indicesUI[indexNdx];
+ default:
+ DE_ASSERT(false);
+ return 0;
+ }
+ };
+
+ /**
+ * @return {number}
+ */
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.getNumIndices = function() {
+ switch (this.m_indexType) {
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE:
+ return this.m_indicesUB.length;
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT:
+ return this.m_indicesUS.length;
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT:
+ return this.m_indicesUI.length;
+ default:
+ DE_ASSERT(false);
+ return 0;
+ }
+ };
+
+ /**
+ * Pointer to the index value at index indexNdx.
+ * @param {number} indexNdx
+ * @return {Uint8Array|Uint16Array|Uint32Array}
+ */
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.getIndexPtr = function(indexNdx) {
+ //TODO: implement
+ switch (this.m_indexType) {
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE:
+ return new Uint8Array(this.m_indicesUB).subarray(indexNdx);
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT:
+ return new Uint16Array(this.m_indicesUS).subarray(indexNdx);
+ case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT:
+ return new Uint32Array(this.m_indicesUI).subarray(indexNdx);
+ default:
+ DE_ASSERT(false);
+ return null;
+ }
+ };
+
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.init = function() {
+ // Clear errors from previous tests
+ gl.getError();
+
+ // Create shader program.
+
+ /** @type {string} */ var vertShaderSource =
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ '\n' +
+ 'void main()\n' +
+ ' {\n' +
+ ' gl_Position = a_position;\n';
+
+ if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS) {
+ vertShaderSource += ' gl_PointSize = 1.0;\n';
+ }
+
+ vertShaderSource += '}\n';
+
+ /** @type {string} */ var fragShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ '\n' +
+ 'void main()\n' +
+ ' {\n' +
+ ' o_color = vec4(1.0f);\n' +
+ '}\n';
+
+ DE_ASSERT(!this.m_program);
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource));
+
+ if (!this.m_program.isOk()) {
+ //m_testCtx.getLog() << *this.m_program;
+ testFailedOptions('Failed to compile shader', true);
+ }
+
+ /** @type {number} */ var restartIndex = this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE :
+ this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT :
+ this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT :
+ 0;
+
+ DE_ASSERT(restartIndex != 0);
+
+ DE_ASSERT(this.getNumIndices() == 0);
+
+ // If testing a case with restart at beginning, add it there.
+ if (this.m_beginWithRestart) {
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+
+ // Generate vertex positions and indices depending on primitive type.
+ // \note At this point, restarts shall not be added to the start or the end of the index vector. Those are special cases, and are done above and after the following if-else chain, respectively.
+ /** @type {number} */ var curIndex;
+ /** @type {number} */ var numRows;
+ /** @type {number} */ var numCols;
+ /** @type {number} */ var fx;
+ /** @type {number} */ var fy;
+ /** @type {number} */ var centerY;
+ /** @type {number} */ var centerX;
+ /** @type {number} */ var numVertices;
+ /** @type {number} */ var numArcVertices;
+ /** @type {number} */ var numStrips;
+
+ if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS) {
+ // Generate rows with different numbers of points.
+
+ curIndex = 0;
+ numRows = 20;
+
+ for (var row = 0; row < numRows; row++) {
+ for (var col = 0; col < row + 1; col++) {
+ fx = -1.0 + 2.0 * (col + 0.5) / numRows;
+ fy = -1.0 + 2.0 * (row + 0.5) / numRows;
+
+ this.m_positions.push(fx);
+ this.m_positions.push(fy);
+
+ this.addIndex(curIndex++);
+ }
+
+ if (row < numRows - 1) { // Add a restart after all but last row.
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+ }
+ } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_STRIP || this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_LOOP || this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINES) {
+ // Generate a numRows x numCols arrangement of line polygons of different vertex counts.
+
+ curIndex = 0;
+ numRows = 4;
+ numCols = 4;
+
+ for (var row = 0; row < numRows; row++) {
+ centerY = -1.0 + 2.0 * (row + 0.5) / numRows;
+
+ for (var col = 0; col < numCols; col++) {
+ centerX = -1.0 + 2.0 * (col + 0.5) / numCols;
+ numVertices = row * numCols + col + 1;
+
+ for (var i = 0; i < numVertices; i++) {
+ fx = centerX + 0.9 * Math.cos(i * 2.0 * Math.PI / numVertices) / numCols;
+ fy = centerY + 0.9 * Math.sin(i * 2.0 * Math.PI / numVertices) / numRows;
+
+ this.m_positions.push(fx);
+ this.m_positions.push(fy);
+
+ this.addIndex(curIndex++);
+ }
+
+ if (col < numCols - 1 || row < numRows - 1) {// Add a restart after all but last polygon.
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+ }
+ }
+ } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_STRIP) {
+ // Generate a number of horizontal triangle strips of different lengths.
+
+ curIndex = 0;
+ numStrips = 20;
+
+ for (var stripNdx = 0; stripNdx < numStrips; stripNdx++) {
+ numVertices = stripNdx + 1;
+
+ for (var i = 0; i < numVertices; i++) {
+ fx = -0.9 + 1.8 * (i / 2 * 2) / numStrips;
+ fy = -0.9 + 1.8 * (stripNdx + (i % 2 == 0 ? 0.0 : 0.8)) / numStrips;
+
+ this.m_positions.push(fx);
+ this.m_positions.push(fy);
+
+ this.addIndex(curIndex++);
+ }
+
+ if (stripNdx < numStrips - 1) { // Add a restart after all but last strip.
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+ }
+ } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_FAN) {
+ // Generate a numRows x numCols arrangement of triangle fan polygons of different vertex counts.
+
+ curIndex = 0;
+ numRows = 4;
+ numCols = 4;
+
+ for (var row = 0; row < numRows; row++) {
+ centerY = -1.0 + 2.0 * (row + 0.5) / numRows;
+
+ for (var col = 0; col < numCols; col++) {
+ centerX = -1.0 + 2.0 * (col + 0.5) / numCols;
+ numArcVertices = row * numCols + col;
+
+ this.m_positions.push(centerX);
+ this.m_positions.push(centerY);
+
+ this.addIndex(curIndex++);
+
+ for (var i = 0; i < numArcVertices; i++) {
+ fx = centerX + 0.9 * Math.cos(i * 2.0 * Math.PI / numArcVertices) / numCols;
+ fy = centerY + 0.9 * Math.sin(i * 2.0 * Math.PI / numArcVertices) / numRows;
+
+ this.m_positions.push(fx);
+ this.m_positions.push(fy);
+
+ this.addIndex(curIndex++);
+ }
+
+ if (col < numCols - 1 || row < numRows - 1) { // Add a restart after all but last polygon.
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+ }
+ }
+ } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLES) {
+ // Generate a number of rows with (potentially incomplete) triangles.
+
+ curIndex = 0;
+ numRows = 3 * 7;
+
+ for (var rowNdx = 0; rowNdx < numRows; rowNdx++) {
+ numVertices = rowNdx + 1;
+
+ for (var i = 0; i < numVertices; i++) {
+ fx = -0.9 + 1.8 * ((i / 3) + (i % 3 == 2 ? 0.8 : 0.0)) * 3 / numRows;
+ fy = -0.9 + 1.8 * (rowNdx + (i % 3 == 0 ? 0.0 : 0.8)) / numRows;
+
+ this.m_positions.push(fx);
+ this.m_positions.push(fy);
+
+ this.addIndex(curIndex++);
+ }
+
+ if (rowNdx < numRows - 1) { // Add a restart after all but last row.
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+ }
+ } else
+ DE_ASSERT(false);
+
+ // If testing a case with restart at end, add it there.
+ if (this.m_endWithRestart) {
+ this.addIndex(restartIndex);
+ if (this.m_duplicateRestarts)
+ this.addIndex(restartIndex);
+ }
+
+ // Special case assertions.
+
+ /** @type {number} */ var numIndices = this.getNumIndices();
+
+ DE_ASSERT(numIndices > 0);
+ DE_ASSERT(this.m_beginWithRestart || this.getIndex(0) != restartIndex); // We don't want restarts at beginning unless the case is a special case.
+ DE_ASSERT(this.m_endWithRestart || this.getIndex(numIndices - 1) != restartIndex); // We don't want restarts at end unless the case is a special case.
+
+ if (!this.m_duplicateRestarts)
+ for (var i = 1; i < numIndices; i++)
+ DE_ASSERT(this.getIndex(i) != restartIndex || this.getIndex(i - 1) != restartIndex); // We don't want duplicate restarts unless the case is a special case.
+
+ };
+
+ es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.iterate = function() {
+ /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, es3fPrimitiveRestartTests.MAX_RENDER_WIDTH);
+ /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, es3fPrimitiveRestartTests.MAX_RENDER_HEIGHT);
+
+ /** @type {number} */ var xOffsetMax = gl.drawingBufferWidth - width;
+ /** @type {number} */ var yOffsetMax = gl.drawingBufferHeight - height;
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+
+ /** @type {number} */ var xOffset = rnd.getInt(0, xOffsetMax);
+ /** @type {number} */ var yOffset = rnd.getInt(0, yOffsetMax);
+ /** @type {tcuSurface.Surface} */ var referenceImg = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var resultImg = new tcuSurface.Surface(width, height);
+
+ gl.viewport(xOffset, yOffset, width, height);
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+
+ var program = this.m_program.getProgram();
+ gl.useProgram(program);
+
+ // Setup position attribute.
+
+ /** @type {number} */ var loc = gl.getAttribLocation(program, 'a_position');
+ gl.enableVertexAttribArray(loc);
+
+ var locGlBuffer = gl.createBuffer();
+ var bufferLoc = new Float32Array(this.m_positions);
+ gl.bindBuffer(gl.ARRAY_BUFFER, locGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, bufferLoc, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
+
+ // Render result.
+ this.renderWithRestart();
+ var resImg = resultImg.getAccess();
+ var resImgTransferFormat = gluTextureUtil.getTransferFormat(resImg.getFormat());
+ gl.readPixels(xOffset, yOffset, resImg.m_width, resImg.m_height, resImgTransferFormat.format, resImgTransferFormat.dataType, resultImg.m_pixels);
+
+ // Render reference (same scene as the real deal, but emulate primitive restart without actually using it).
+ this.renderWithoutRestart();
+
+ var refImg = referenceImg.getAccess();
+ var refImgTransferFormat = gluTextureUtil.getTransferFormat(refImg.getFormat());
+
+ gl.readPixels(xOffset, yOffset, refImg.m_width, refImg.m_height, refImgTransferFormat.format, refImgTransferFormat.dataType, referenceImg.m_pixels);
+
+ // Compare.
+ /** @type {boolean} */ var testOk = tcuImageCompare.pixelThresholdCompare('ComparisonResult', 'Image comparison result', referenceImg, resultImg, [0, 0, 0, 0]);
+
+ assertMsgOptions(testOk, '', true, false);
+ gl.useProgram(null);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ es3fPrimitiveRestartTests.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ for (var isRestartBeginCaseI = 0; isRestartBeginCaseI <= 1; isRestartBeginCaseI++) {
+ for (var isRestartEndCaseI = 0; isRestartEndCaseI <= 1; isRestartEndCaseI++) {
+ for (var isDuplicateRestartCaseI = 0; isDuplicateRestartCaseI <= 1; isDuplicateRestartCaseI++) {
+ /** @type {boolean} */ var isRestartBeginCase = isRestartBeginCaseI != 0;
+ /** @type {boolean} */ var isRestartEndCase = isRestartEndCaseI != 0;
+ /** @type {boolean} */ var isDuplicateRestartCase = isDuplicateRestartCaseI != 0;
+
+ /** @type {string} */ var specialCaseGroupName = '';
+
+ if (isRestartBeginCase) specialCaseGroupName = 'begin_restart';
+ if (isRestartEndCase) specialCaseGroupName += (deString.deIsStringEmpty(specialCaseGroupName) ? '' : '_') + 'end_restart';
+ if (isDuplicateRestartCase) specialCaseGroupName += (deString.deIsStringEmpty(specialCaseGroupName) ? '' : '_') + 'duplicate_restarts';
+
+ if (deString.deIsStringEmpty(specialCaseGroupName))
+ specialCaseGroupName = 'basic';
+
+ /** @type {tcuTestCase.DeqpTest} */ var specialCaseGroup = tcuTestCase.newTest(specialCaseGroupName, '');
+ testGroup.addChild(specialCaseGroup);
+
+ for (var primType in es3fPrimitiveRestartTests.PrimitiveType) {
+ /** @type {string} */ var primTypeName = es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS ? 'points' :
+ es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_STRIP ? 'line_strip' :
+ es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_LOOP ? 'line_loop' :
+ es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINES ? 'lines' :
+ es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_STRIP ? 'triangle_strip' :
+ es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_FAN ? 'triangle_fan' :
+ es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLES ? 'triangles' :
+ '';
+
+ DE_ASSERT(primTypeName != null);
+
+ /** @type {tcuTestCase.DeqpTest} */ var primTypeGroup = tcuTestCase.newTest(primTypeName, '');
+ specialCaseGroup.addChild(primTypeGroup);
+
+ for (var indexType in es3fPrimitiveRestartTests.IndexType) {
+ /** @type {string} */ var indexTypeName = es3fPrimitiveRestartTests.IndexType[indexType] == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? 'unsigned_byte' :
+ es3fPrimitiveRestartTests.IndexType[indexType] == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? 'unsigned_short' :
+ es3fPrimitiveRestartTests.IndexType[indexType] == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? 'unsigned_int' :
+ '';
+
+ DE_ASSERT(indexTypeName != null);
+
+ /** @type {tcuTestCase.DeqpTest} */ var indexTypeGroup = tcuTestCase.newTest(indexTypeName, '');
+ primTypeGroup.addChild(indexTypeGroup);
+
+ for (var _function in es3fPrimitiveRestartTests.DrawFunction) {
+ /** @type {?string} */ var functionName = es3fPrimitiveRestartTests.DrawFunction[_function] == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS ? 'draw_elements' :
+ es3fPrimitiveRestartTests.DrawFunction[_function] == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED ? 'draw_elements_instanced' :
+ es3fPrimitiveRestartTests.DrawFunction[_function] == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_RANGE_ELEMENTS ? 'draw_range_elements' :
+ null;
+
+ DE_ASSERT(functionName != null);
+
+ indexTypeGroup.addChild(new es3fPrimitiveRestartTests.PrimitiveRestartCase(functionName,
+ '',
+ es3fPrimitiveRestartTests.PrimitiveType[primType],
+ es3fPrimitiveRestartTests.IndexType[indexType],
+ es3fPrimitiveRestartTests.DrawFunction[_function],
+ isRestartBeginCase,
+ isRestartEndCase,
+ isDuplicateRestartCase));
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ es3fPrimitiveRestartTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'primitive_restart';
+ var testDescription = 'Primitive Restart Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.setRoot(tcuTestCase.newTest(testName, testDescription, null));
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fPrimitiveRestartTests.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fPrimitiveRestartTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRasterizerDiscardTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRasterizerDiscardTests.js
new file mode 100644
index 0000000000..ce74648569
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRasterizerDiscardTests.js
@@ -0,0 +1,485 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Rasterizer discard tests.
+ *//*--------------------------------------------------------------------*/
+
+goog.provide('functional.gles3.es3fRasterizerDiscardTests');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+var es3fRasterizerDiscardTests = functional.gles3.es3fRasterizerDiscardTests;
+var deString = framework.delibs.debase.deString;
+var tcuTestCase = framework.common.tcuTestCase;
+var deRandom = framework.delibs.debase.deRandom;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuSurface = framework.common.tcuSurface;
+var gluDrawUtil = framework.opengl.gluDrawUtil;
+var tcuLogImage = framework.common.tcuLogImage;
+
+/** @const */ var NUM_CASE_ITERATIONS = 1;
+/** @const */ var FAIL_COLOR_RED = [1, 0, 0.0, 1];
+/** @const */ var PASS_COLOR_BLUE = [0, 0, 0.5, 1];
+/** @const */ var BLACK_COLOR = [0, 0, 0.0, 1];
+/** @const */ var FAIL_DEPTH = 0;
+/** @const */ var FAIL_STENCIL = 1;
+/** @const */ var UNIT_SQUARE = [
+ 1, 1, 0.05, 1,
+ 1, -1, 0.05, 1,
+ -1, 1, 0.05, 1,
+ -1, -1, 0.05, 1
+];
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+/**
+ * @enum
+ */
+es3fRasterizerDiscardTests.CaseType = {
+ WRITE_DEPTH: 0,
+ WRITE_STENCIL: 1,
+ CLEAR_COLOR: 2,
+ CLEAR_DEPTH: 3,
+ CLEAR_STENCIL: 4
+};
+
+/**
+ * @enum {{useFBO: boolean, useScissor: boolean}}
+ */
+es3fRasterizerDiscardTests.CaseOptions = {
+ FBO: {useFBO: true, useScissor: false},
+ SCISSOR: {useFBO: false, useScissor: true}
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} numPrimitives
+ * @param {es3fRasterizerDiscardTests.CaseType} caseType
+ * @param {?es3fRasterizerDiscardTests.CaseOptions} caseOptions
+ * @param {gluDrawUtil.primitiveType=} drawMode
+ */
+es3fRasterizerDiscardTests.RasterizerDiscardCase = function(name, description, numPrimitives, caseType, caseOptions, drawMode) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_numPrimitives = numPrimitives;
+ this.m_caseType = caseType;
+ this.m_caseOptions = caseOptions || {useFBO: false, useScissor: false};
+ this.m_drawMode = drawMode || gluDrawUtil.primitiveType.TRIANGLES;
+ this.m_program = null;
+ this.m_fbo = null;
+ this.m_colorBuf = null;
+ this.m_depthStencilBuf = null;
+ this.m_iterNdx = 0;
+ this.m_rnd = new deRandom.Random(deString.deStringHash(name));
+};
+
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype.constructor = es3fRasterizerDiscardTests.RasterizerDiscardCase;
+
+/**
+ * @param {number} numPrimitives
+ * @param {deRandom.Random} rnd
+ * @param {gluDrawUtil.primitiveType} drawMode
+ * @return {Array<number>}
+ */
+es3fRasterizerDiscardTests.generateVertices = function(numPrimitives, rnd, drawMode) {
+ var dst = [];
+ var numVertices;
+
+ switch (drawMode) {
+ case gl.POINTS: numVertices = numPrimitives; break;
+ case gl.LINES: numVertices = 2 * numPrimitives; break;
+ case gl.LINE_STRIP: numVertices = numPrimitives + 1; break;
+ case gl.LINE_LOOP: numVertices = numPrimitives + 2; break;
+ case gl.TRIANGLES: numVertices = 3 * numPrimitives; break;
+ case gl.TRIANGLE_STRIP: numVertices = numPrimitives + 2; break;
+ case gl.TRIANGLE_FAN: numVertices = numPrimitives + 2; break;
+ default:
+ throw new Error('Invalid drawMode: ' + drawMode);
+ }
+
+ for (var i = 0; i < numVertices; i++) {
+ dst[i * 4] = rnd.getFloat(-1.0, 1.0); // x
+ dst[i * 4 + 1] = rnd.getFloat(-1.0, 1.0); // y
+ dst[i * 4 + 2] = rnd.getFloat(0.1, 0.9); // z
+ dst[i * 4 + 3] = 1.0; // w
+ }
+
+ return dst;
+};
+
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype.setupFramebufferObject = function() {
+ var width = gl.drawingBufferWidth;
+ var height = gl.drawingBufferHeight;
+
+ // Create framebuffer object
+
+ this.m_fbo = gl.createFramebuffer();
+ this.m_colorBuf = gl.createTexture();
+ this.m_depthStencilBuf = gl.createRenderbuffer();
+
+ // Create color texture
+
+ gl.bindTexture(gl.TEXTURE_2D, this.m_colorBuf);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ // Create depth and stencil buffers
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_depthStencilBuf);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, width, height);
+
+ // Attach texture and buffers to FBO
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.m_colorBuf, 0);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.m_depthStencilBuf);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.m_depthStencilBuf);
+
+ var fboStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+ if (fboStatus == gl.FRAMEBUFFER_UNSUPPORTED)
+ throw new Error('Framebuffer unsupported');
+ else if (fboStatus != gl.FRAMEBUFFER_COMPLETE)
+ throw new Error('Failed to create framebuffer object: ' + deString.enumToString(gl, fboStatus));
+};
+
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype.deleteFramebufferObject = function() {
+ gl.deleteTexture(this.m_colorBuf);
+ gl.deleteRenderbuffer(this.m_depthStencilBuf);
+ gl.deleteFramebuffer(this.m_fbo);
+};
+
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype.init = function() {
+ var vertShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) in mediump vec4 a_position;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+
+ var fragShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n' +
+ 'uniform mediump vec4 u_color;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float depth_gradient = gl_FragCoord.z;\n' +
+ ' mediump float bias = 0.1;\n' +
+ ' dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1.0);\n' +
+ '}\n';
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource));
+
+ if (!this.m_program.isOk()) {
+ bufferedLogToConsole(this.m_program);
+ testFailedOptions('Failed to compile shader program', true);
+ }
+};
+
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype.deinit = function() {
+ this.deleteFramebufferObject();
+ this.m_program = null;
+};
+
+es3fRasterizerDiscardTests.RasterizerDiscardCase.prototype.iterate = function() {
+ var program = this.m_program.getProgram();
+ var colorUnif = gl.getUniformLocation(program, 'u_color');
+ var failColorFound = false;
+ var passColorFound = false;
+ var vertices;
+
+ bufferedLogToConsole('Case iteration ' + (this.m_iterNdx + 1) + ' / ' + NUM_CASE_ITERATIONS);
+
+ // Create and bind FBO if needed
+
+ if (this.m_caseOptions.useFBO) {
+ this.setupFramebufferObject();
+ }
+
+ if (this.m_caseOptions.useScissor) {
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+ bufferedLogToConsole('Scissor test enabled: glScissor(0, 0, ' + gl.drawingBufferWidth + ', ' + gl.drawingBufferHeight + ')');
+ }
+
+ gl.useProgram(this.m_program.getProgram());
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthRange(0, 1);
+ gl.depthFunc(gl.LEQUAL);
+
+ gl.enable(gl.STENCIL_TEST);
+ gl.stencilFunc(gl.NOTEQUAL, 1, 0xFF);
+ gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
+
+ gl.clearColor(PASS_COLOR_BLUE[0], PASS_COLOR_BLUE[1], PASS_COLOR_BLUE[2], PASS_COLOR_BLUE[3]);
+ gl.clearDepth(1);
+ gl.clearStencil(0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ // Generate vertices
+ vertices = es3fRasterizerDiscardTests.generateVertices(this.m_numPrimitives, this.m_rnd, this.m_drawMode);
+ var posLoc = gl.getAttribLocation(program, 'a_position');
+ var vertexArrays = [];
+ vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, vertices.length / 4, vertices));
+ // Clear color to black for depth and stencil clear cases
+
+ if (this.m_caseType == es3fRasterizerDiscardTests.CaseType.CLEAR_DEPTH || this.m_caseType == es3fRasterizerDiscardTests.CaseType.CLEAR_STENCIL) {
+ gl.clearColor(BLACK_COLOR[0], BLACK_COLOR[1], BLACK_COLOR[2], BLACK_COLOR[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+
+ // Set fail values for color, depth and stencil
+
+ gl.uniform4fv(colorUnif, FAIL_COLOR_RED);
+ gl.clearColor(FAIL_COLOR_RED[0], FAIL_COLOR_RED[1], FAIL_COLOR_RED[2], FAIL_COLOR_RED[3]);
+ gl.clearDepth(FAIL_DEPTH);
+ gl.clearStencil(FAIL_STENCIL);
+
+ // Enable rasterizer discard
+
+ gl.enable(gl.RASTERIZER_DISCARD);
+ bufferedLogToConsole('Rasterizer discard enabled');
+
+ // Do to-be-discarded primitive draws and buffer clears
+
+ switch (this.m_caseType) {
+ case es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH:
+ gluDrawUtil.draw(gl, program, vertexArrays, new gluDrawUtil.PrimitiveList(this.m_drawMode, vertices.length / 4));
+ break;
+ case es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL:
+ gluDrawUtil.draw(gl, program, vertexArrays, new gluDrawUtil.PrimitiveList(this.m_drawMode, vertices.length / 4));
+ break;
+ case es3fRasterizerDiscardTests.CaseType.CLEAR_COLOR:
+ if (this.m_caseOptions.useFBO)
+ gl.clearBufferfv(gl.COLOR, 0, FAIL_COLOR_RED);
+ else
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ break;
+ case es3fRasterizerDiscardTests.CaseType.CLEAR_DEPTH:
+ if (this.m_caseOptions.useFBO)
+ gl.clearBufferfv(gl.DEPTH, 0, [FAIL_DEPTH]);
+ else
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ break;
+ case es3fRasterizerDiscardTests.CaseType.CLEAR_STENCIL:
+ if (this.m_caseOptions.useFBO)
+ gl.clearBufferiv(gl.STENCIL, 0, [FAIL_STENCIL]);
+ else
+ gl.clear(gl.STENCIL_BUFFER_BIT);
+ break;
+ default:
+ throw new Error('Invalid case type ' + this.m_caseType);
+ }
+
+ // Disable rasterizer discard
+
+ gl.disable(gl.RASTERIZER_DISCARD);
+ bufferedLogToConsole('Rasterizer discard disabled');
+
+ if (this.m_caseType == es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL) {
+ if (this.m_caseOptions.useFBO || gl.getContextAttributes().stencil) {
+ // Draw a full-screen square that colors all pixels red if they have stencil value 1.
+ var square = [new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, UNIT_SQUARE.length / 4, UNIT_SQUARE)];
+
+ gl.stencilFunc(gl.EQUAL, 1, 0xFF);
+ gluDrawUtil.draw(gl, program, square,
+ new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLE_STRIP, UNIT_SQUARE.length / 4));
+ }
+ // \note If no stencil buffers are present and test is rendering to default framebuffer, test will always pass.
+ } else if (this.m_caseType == es3fRasterizerDiscardTests.CaseType.CLEAR_DEPTH || this.m_caseType == es3fRasterizerDiscardTests.CaseType.CLEAR_STENCIL) {
+ // Draw pass-indicating primitives for depth and stencil clear cases
+
+ gl.uniform4fv(colorUnif, PASS_COLOR_BLUE);
+ gluDrawUtil.draw(gl, program, vertexArrays, new gluDrawUtil.PrimitiveList(this.m_drawMode, vertices.length / 4));
+ }
+
+ gl.finish();
+ gl.disable(gl.STENCIL_TEST);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.SCISSOR_TEST);
+
+ // Read and check pixel data
+
+ var pixels = new tcuSurface.Surface();
+ pixels.readViewport(gl);
+
+ var width = pixels.getWidth();
+ var height = pixels.getHeight();
+
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ var pixel = pixels.getPixel(x, y);
+ if (pixel[2] != 0)
+ passColorFound = true;
+
+ if (pixel[0] != 0) {
+ failColorFound = true;
+ break;
+ }
+ }
+ if (failColorFound) break;
+ }
+
+ // Delete FBO if created
+
+ if (this.m_caseOptions.useFBO)
+ this.deleteFramebufferObject();
+
+ // Evaluate test result
+
+ var testOk = passColorFound && !failColorFound;
+
+ if (!testOk) {
+ tcuLogImage.logImage('Result image', '', pixels.getAccess());
+ testFailed('Primitive or buffer clear was not discarded.');
+ return tcuTestCase.IterateResult.STOP;
+ }
+ bufferedLogToConsole('Primitive or buffer clear was discarded correctly.');
+
+ if (++this.m_iterNdx < NUM_CASE_ITERATIONS)
+ return tcuTestCase.IterateResult.CONTINUE;
+
+ testPassed();
+ return tcuTestCase.IterateResult.STOP;
+};
+
+es3fRasterizerDiscardTests.init = function() {
+ var state = tcuTestCase.runner;
+ var testGroup = state.testCases;
+
+ var basic = tcuTestCase.newTest('basic', 'Rasterizer discard test for default framebuffer');
+ var scissor = tcuTestCase.newTest('scissor', 'Rasterizer discard test for default framebuffer with scissor test enabled');
+ var fbo = tcuTestCase.newTest('fbo', 'Rasterizer discard test for framebuffer object');
+
+ testGroup.addChild(basic);
+ testGroup.addChild(scissor);
+ testGroup.addChild(fbo);
+
+ // Default framebuffer cases
+
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_points', 'points', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.POINTS));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_lines', 'lines', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.LINES));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_line_strip', 'line_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.LINE_STRIP));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_line_loop', 'line_loop', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.LINE_LOOP));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangles', 'triangles', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.TRIANGLES));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangle_strip', 'triangle_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.TRIANGLE_STRIP));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangle_fan', 'triangle_fan', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, null, gluDrawUtil.primitiveType.TRIANGLE_FAN));
+
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_points', 'points', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.POINTS));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_lines', 'lines', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.LINES));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_line_strip', 'line_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.LINE_STRIP));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_line_loop', 'line_loop', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.LINE_LOOP));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangles', 'triangles', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.TRIANGLES));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangle_strip', 'triangle_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.TRIANGLE_STRIP));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangle_fan', 'triangle_fan', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, null, gluDrawUtil.primitiveType.TRIANGLE_FAN));
+
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_color', 'clear_color', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_COLOR, null));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_depth', 'clear_depth', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_DEPTH, null));
+ basic.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_stencil', 'clear_stencil', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_STENCIL, null));
+
+ // Default framebuffer cases with scissor test enabled
+
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_points', 'points', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.POINTS));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_lines', 'lines', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.LINES));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_line_strip', 'line_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.LINE_STRIP));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_line_loop', 'line_loop', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.LINE_LOOP));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangles', 'triangles', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.TRIANGLES));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangle_strip', 'triangle_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.TRIANGLE_STRIP));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangle_fan', 'triangle_fan', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.TRIANGLE_FAN));
+
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_points', 'points', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.POINTS));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_lines', 'lines', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.LINES));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_line_strip', 'line_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.LINE_STRIP));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_line_loop', 'line_loop', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.LINE_LOOP));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangles', 'triangles', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.TRIANGLES));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangle_strip', 'triangle_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.TRIANGLE_STRIP));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangle_fan', 'triangle_fan', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR, gluDrawUtil.primitiveType.TRIANGLE_FAN));
+
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_color', 'clear_color', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_COLOR, es3fRasterizerDiscardTests.CaseOptions.SCISSOR));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_depth', 'clear_depth', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_DEPTH, es3fRasterizerDiscardTests.CaseOptions.SCISSOR));
+ scissor.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_stencil', 'clear_stencil', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_STENCIL, es3fRasterizerDiscardTests.CaseOptions.SCISSOR));
+
+ // FBO cases
+
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_points', 'points', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.POINTS));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_lines', 'lines', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.LINES));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_line_strip', 'line_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.LINE_STRIP));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_line_loop', 'line_loop', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.LINE_LOOP));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangles', 'triangles', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.TRIANGLES));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangle_strip', 'triangle_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.TRIANGLE_STRIP));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_depth_triangle_fan', 'triangle_fan', 4, es3fRasterizerDiscardTests.CaseType.WRITE_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.TRIANGLE_FAN));
+
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_points', 'points', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.POINTS));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_lines', 'lines', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.LINES));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_line_strip', 'line_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.LINE_STRIP));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_line_loop', 'line_loop', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.LINE_LOOP));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangles', 'triangles', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.TRIANGLES));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangle_strip', 'triangle_strip', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.TRIANGLE_STRIP));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('write_stencil_triangle_fan', 'triangle_fan', 4, es3fRasterizerDiscardTests.CaseType.WRITE_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO, gluDrawUtil.primitiveType.TRIANGLE_FAN));
+
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_color', 'clear_color', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_COLOR, es3fRasterizerDiscardTests.CaseOptions.FBO));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_depth', 'clear_depth', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_DEPTH, es3fRasterizerDiscardTests.CaseOptions.FBO));
+ fbo.addChild(new es3fRasterizerDiscardTests.RasterizerDiscardCase('clear_stencil', 'clear_stencil', 4, es3fRasterizerDiscardTests.CaseType.CLEAR_STENCIL, es3fRasterizerDiscardTests.CaseOptions.FBO));
+};
+
+/**
+ * Create and execute the test cases
+ */
+es3fRasterizerDiscardTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'rasterizer_discard';
+ var testDescription = 'Rasterizer Discard Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ es3fRasterizerDiscardTests.init();
+ tcuTestCase.runTestCases();
+ } catch (err) {
+ testFailedOptions('Failed to run tests', false);
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRboStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRboStateQueryTests.js
new file mode 100644
index 0000000000..9903102990
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fRboStateQueryTests.js
@@ -0,0 +1,308 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fRboStateQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fRboStateQueryTests = functional.gles3.es3fRboStateQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+var deRandom = framework.delibs.debase.deRandom;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @this {es3fApiCase.ApiCase}
+ */
+var checkRenderbufferComponentSize = function(r, g, b, a, d, s) {
+ var referenceSizes = [r, g, b, a, d, s];
+ var paramNames = [
+ gl.RENDERBUFFER_RED_SIZE,
+ gl.RENDERBUFFER_GREEN_SIZE,
+ gl.RENDERBUFFER_BLUE_SIZE,
+ gl.RENDERBUFFER_ALPHA_SIZE,
+ gl.RENDERBUFFER_DEPTH_SIZE,
+ gl.RENDERBUFFER_STENCIL_SIZE
+ ];
+
+ for (var ndx = 0; ndx < referenceSizes.length; ++ndx) {
+ if (referenceSizes[ndx] == -1)
+ continue;
+ var value = /** @type {number} */ (gl.getRenderbufferParameter(gl.RENDERBUFFER, paramNames[ndx]));
+
+ this.check(value >= referenceSizes[ndx], 'Expected greater or equal to ' + referenceSizes[ndx] + ' got ' + value);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fRboStateQueryTests.RboSizeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fRboStateQueryTests.RboSizeCase, es3fApiCase.ApiCase);
+
+es3fRboStateQueryTests.RboSizeCase.prototype.test = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_WIDTH, 0));
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_HEIGHT, 0));
+
+ var numIterations = 60;
+ for (var i = 0; i < numIterations; ++i) {
+ var w = rnd.getInt(0, 128);
+ var h = rnd.getInt(0, 128);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB8, w, h);
+
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_WIDTH, w));
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_HEIGHT, h));
+ }
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fRboStateQueryTests.RboInternalFormatCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fRboStateQueryTests.RboInternalFormatCase, es3fApiCase.ApiCase);
+
+es3fRboStateQueryTests.RboInternalFormatCase.prototype.test = function() {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_INTERNAL_FORMAT, gl.RGBA4));
+
+ var requiredColorformats = [
+ gl.R8, gl.RG8, gl.RGB8, gl.RGB565, gl.RGBA4, gl.RGB5_A1, gl.RGBA8, gl.RGB10_A2,
+ gl.RGB10_A2UI, gl.SRGB8_ALPHA8, 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.RGBA8I, gl.RGBA8UI,
+ gl.RGBA16I, gl.RGBA16UI, gl.RGBA32I, gl.RGBA32UI
+ ];
+
+ for (var ndx = 0; ndx < requiredColorformats.length; ++ndx) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, requiredColorformats[ndx], 128, 128);
+
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_INTERNAL_FORMAT, requiredColorformats[ndx]));
+ }
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fRboStateQueryTests.RboComponentSizeColorCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fRboStateQueryTests.RboComponentSizeColorCase, es3fApiCase.ApiCase);
+
+es3fRboStateQueryTests.RboComponentSizeColorCase.prototype.test = function() {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ checkRenderbufferComponentSize.bind(this, 0, 0, 0, 0, 0, 0);
+
+ var requiredColorFormats = [
+ // format, r, g, b, a
+ [gl.R8, 8, 0, 0, 0],
+ [gl.RG8, 8, 8, 0, 0],
+ [gl.RGB8, 8, 8, 8, 0],
+ [gl.RGB565, 5, 6, 5, 0],
+ [gl.RGBA4, 4, 4, 4, 4],
+ [gl.RGB5_A1, 5, 5, 5, 1],
+ [gl.RGBA8, 8, 8, 8, 8],
+ [gl.RGB10_A2, 10, 10, 10, 2],
+ [gl.RGB10_A2UI, 10, 10, 10, 2],
+ [gl.SRGB8_ALPHA8, 8, 8, 8, 8],
+ [gl.R8I, 8, 0, 0, 0],
+ [gl.R8UI, 8, 0, 0, 0],
+ [gl.R16I, 16, 0, 0, 0],
+ [gl.R16UI, 16, 0, 0, 0],
+ [gl.R32I, 32, 0, 0, 0],
+ [gl.R32UI, 32, 0, 0, 0],
+ [gl.RG8I, 8, 8, 0, 0],
+ [gl.RG8UI, 8, 8, 0, 0],
+ [gl.RG16I, 16, 16, 0, 0],
+ [gl.RG16UI, 16, 16, 0, 0],
+ [gl.RG32I, 32, 32, 0, 0],
+ [gl.RG32UI, 32, 32, 0, 0],
+ [gl.RGBA8I, 8, 8, 8, 8],
+ [gl.RGBA8UI, 8, 8, 8, 8],
+ [gl.RGBA16I, 16, 16, 16, 16],
+ [gl.RGBA16UI, 16, 16, 16, 16],
+ [gl.RGBA32I, 32, 32, 32, 32],
+ [gl.RGBA32UI, 32, 32, 32, 32]
+ ];
+
+ for (var ndx = 0; ndx < requiredColorFormats.length; ++ndx) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, requiredColorFormats[ndx][0], 128, 128);
+
+ checkRenderbufferComponentSize.bind(this, requiredColorFormats[ndx][1], requiredColorFormats[ndx][2], requiredColorFormats[ndx][3], requiredColorFormats[ndx][4], -1, -1);
+ }
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fRboStateQueryTests.RboComponentSizeDepthCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fRboStateQueryTests.RboComponentSizeDepthCase, es3fApiCase.ApiCase);
+
+es3fRboStateQueryTests.RboComponentSizeDepthCase.prototype.test = function() {
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ var requiredDepthFormats = [
+ // format, depth, stencil
+ [gl.DEPTH_COMPONENT16, 16, 0],
+ [gl.DEPTH_COMPONENT24, 24, 0],
+ [gl.DEPTH_COMPONENT32F, 32, 0],
+ [gl.DEPTH24_STENCIL8, 24, 8],
+ [gl.DEPTH32F_STENCIL8, 32, 8]
+ ];
+
+ for (var ndx = 0; ndx < requiredDepthFormats.length; ++ndx) {
+ gl.renderbufferStorage(gl.RENDERBUFFER, requiredDepthFormats[ndx][0], 128, 128);
+
+ checkRenderbufferComponentSize.bind(this, -1, -1, -1, -1, requiredDepthFormats[ndx][1], requiredDepthFormats[ndx][2]);
+ }
+
+ // STENCIL_INDEX8 is required, in that case sBits >= 8
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 128, 128);
+
+ var value = /** @type {number} */ (gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_STENCIL_SIZE));
+ this.check(value >= 8, 'Expected greater or equal to 8; got ' + value);
+
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fRboStateQueryTests.RboSamplesCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fRboStateQueryTests.RboSamplesCase, es3fApiCase.ApiCase);
+
+es3fRboStateQueryTests.RboSamplesCase.prototype.test = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ var renderbufferID = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbufferID);
+
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_SAMPLES, 0));
+
+ var max_samples = /** @type {number} */ (gl.getParameter(gl.MAX_SAMPLES));
+
+ // 0 samples is a special case
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 0, gl.RGBA8, 128, 128);
+
+ this.check(glsStateQuery.verifyRenderbuffer(gl.RENDERBUFFER_SAMPLES, 0));
+
+ // test [1, n] samples
+ for (var samples = 1; samples <= max_samples; ++samples) {
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.RGBA8, 128, 128);
+ var value = /** @type {number} */ (gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES));
+ this.check(value >= samples, 'Expected greater or equal to ' + samples + ' got ' + value);
+ }
+
+ gl.deleteRenderbuffer(renderbufferID);
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fRboStateQueryTests.RboStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'rbo', 'Rbo State Query tests');
+};
+
+es3fRboStateQueryTests.RboStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fRboStateQueryTests.RboStateQueryTests.prototype.constructor = es3fRboStateQueryTests.RboStateQueryTests;
+
+es3fRboStateQueryTests.RboStateQueryTests.prototype.init = function() {
+ this.addChild(new es3fRboStateQueryTests.RboSizeCase('renderbuffer_size', 'RENDERBUFFER_WIDTH and RENDERBUFFER_HEIGHT'));
+ this.addChild(new es3fRboStateQueryTests.RboInternalFormatCase('renderbuffer_internal_format', 'RENDERBUFFER_INTERNAL_FORMAT'));
+ this.addChild(new es3fRboStateQueryTests.RboComponentSizeColorCase('renderbuffer_component_size_color', 'RENDERBUFFER_x_SIZE'));
+ this.addChild(new es3fRboStateQueryTests.RboComponentSizeDepthCase('renderbuffer_component_size_depth', 'RENDERBUFFER_x_SIZE'));
+ this.addChild(new es3fRboStateQueryTests.RboSamplesCase('renderbuffer_samples', 'RENDERBUFFER_SAMPLES'));
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fRboStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fRboStateQueryTests.RboStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fRboStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fReadPixelTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fReadPixelTests.js
new file mode 100644
index 0000000000..7996c9196c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fReadPixelTests.js
@@ -0,0 +1,517 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fReadPixelTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+ var es3fReadPixelTests = functional.gles3.es3fReadPixelTests;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} chooseFormat
+ * @param {number} alignment
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number=} format
+ * @param {number=} type
+ */
+ es3fReadPixelTests.ReadPixelsTest = function(name, description, chooseFormat, alignment, rowLength, skipRows, skipPixels, format, type) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+
+ /** @type {number} */ this.m_seed = deString.deStringHash(name);
+ /** @type {boolean} */ this.m_chooseFormat = chooseFormat;
+ /** @type {number} */ this.m_alignment = alignment;
+ /** @type {number} */ this.m_rowLength = rowLength;
+ /** @type {number} */ this.m_skipRows = skipRows;
+ /** @type {number} */ this.m_skipPixels = skipPixels;
+ /** @type {number} */ this.m_format = format !== undefined ? format : gl.RGBA;
+ /** @type {number} */ this.m_type = type !== undefined ? type : gl.UNSIGNED_BYTE;
+
+ /** @const {number} */ this.m_width = 13;
+ /** @const {number} */ this.m_height = 13;
+ };
+
+ es3fReadPixelTests.ReadPixelsTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fReadPixelTests.ReadPixelsTest.prototype.constructor = es3fReadPixelTests.ReadPixelsTest;
+
+ /**
+ * @param {tcuTexture.Texture2D} reference
+ */
+ es3fReadPixelTests.ReadPixelsTest.prototype.render = function(reference) {
+ var refType = /** @type {tcuTexture.ChannelType} */ (reference.getFormat().type);
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @return {tcuTexture.PixelBufferAccess} */ var level0 = reference.getLevel(0);
+
+ // Create program
+ /** @type {string} */ var vertexSource = '#version 300 es\n' +
+ 'in mediump vec2 i_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ '\tgl_Position = vec4(i_coord, 0.0, 1.0);\n' +
+ '}\n';
+
+ /** @type {string} */ var fragmentSource = '#version 300 es\n';
+
+ if (refType === tcuTexture.ChannelType.SIGNED_INT32)
+ fragmentSource += 'layout(location = 0) out mediump ivec4 o_color;\n';
+ else if (refType === tcuTexture.ChannelType.UNSIGNED_INT32)
+ fragmentSource += 'layout(location = 0) out mediump uvec4 o_color;\n';
+ else
+ fragmentSource += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ fragmentSource += 'void main (void)\n' +
+ '{\n';
+
+ if (refType === tcuTexture.ChannelType.UNSIGNED_INT32)
+ fragmentSource += '\to_color = uvec4(0, 0, 0, 1000);\n';
+ else if (refType === tcuTexture.ChannelType.SIGNED_INT32)
+ fragmentSource += '\to_color = ivec4(0, 0, 0, 1000);\n';
+ else
+ fragmentSource += '\to_color = vec4(0.0, 0.0, 0.0, 1.0);\n';
+
+ fragmentSource += '}\n';
+
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexSource, fragmentSource));
+
+ assertMsgOptions(program.isOk(), 'Program failed', false, true);
+
+ gl.useProgram(program.getProgram());
+
+ // Render
+ /** @type {Array<number>} */ var coords = [
+ -0.5, -0.5,
+ 0.5, -0.5,
+ 0.5, 0.5,
+
+ 0.5, 0.5,
+ -0.5, 0.5,
+ -0.5, -0.5
+ ];
+ /** @type {number} */ var coordLoc;
+
+ coordLoc = gl.getAttribLocation(program.getProgram(), 'i_coord');
+
+ gl.enableVertexAttribArray(coordLoc);
+
+ /** @type {WebGLBuffer} */ var coordsGLBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, coordsGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(coordLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.disableVertexAttribArray(coordLoc);
+
+ // Render reference
+
+ /** @type {number} */ var coordX1 = Math.floor((-0.5 * width / 2.0) + width / 2.0);
+ /** @type {number} */ var coordY1 = Math.floor((-0.5 * height / 2.0) + height / 2.0);
+ /** @type {number} */ var coordX2 = Math.floor((0.5 * width / 2.0) + width / 2.0);
+ /** @type {number} */ var coordY2 = Math.floor((0.5 * height / 2.0) + height / 2.0);
+
+ for (var x = 0; x < width; x++) {
+ if (x < coordX1 || x > coordX2)
+ continue;
+
+ for (var y = 0; y < height; y++) {
+ if (y >= coordY1 && y <= coordY2) {
+ if (refType === tcuTexture.ChannelType.SIGNED_INT32)
+ level0.setPixelInt([0, 0, 0, 1000], x, y);
+ else if (refType === tcuTexture.ChannelType.UNSIGNED_INT32)
+ level0.setPixelInt([0, 0, 0, 1000], x, y);
+ else
+ level0.setPixel([0.0, 0.0, 0.0, 1.0], x, y);
+ }
+ }
+ }
+ };
+
+ /**
+ * @return {{format: tcuTexture.TextureFormat, pixelSize: number, align: boolean}}
+ */
+ es3fReadPixelTests.ReadPixelsTest.prototype.getFormatInfo = function() {
+ if (this.m_chooseFormat) {
+ this.m_format = /** @type {number} */ (gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT));
+ this.m_type = /** @type {number} */ (gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE));
+ }
+
+ /** @type {tcuTexture.TextureFormat} */ var fmt = gluTextureUtil.mapGLTransferFormat(this.m_format, this.m_type);
+ /** @type {boolean} */ var align_;
+ switch (this.m_type) {
+ case gl.BYTE:
+ case gl.UNSIGNED_BYTE:
+ case gl.SHORT:
+ case gl.UNSIGNED_SHORT:
+ case gl.INT:
+ case gl.UNSIGNED_INT:
+ case gl.FLOAT:
+ case gl.HALF_FLOAT:
+ align_ = true;
+ break;
+
+ case gl.UNSIGNED_SHORT_5_6_5:
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ case gl.UNSIGNED_INT_24_8:
+ case gl.FLOAT_32_UNSIGNED_INT_24_8_REV:
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ align_ = false;
+ break;
+
+ default:
+ throw new Error('Unsupported format');
+ }
+
+ /** @type {number} */ var pxSize = fmt.getPixelSize();
+
+ return {format: fmt, pixelSize: pxSize, align: align_};
+ };
+
+ /**
+ * @param {tcuTexture.Texture2D} reference
+ * @param {boolean} align
+ * @param {number} pixelSize
+ * @return {goog.TypedArray}
+ */
+ es3fReadPixelTests.ReadPixelsTest.prototype.clearColor = function(reference, align, pixelSize) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @return {tcuTexture.PixelBufferAccess} */ var level0 = reference.getLevel(0);
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(this.m_seed);
+ /** @type {WebGLFramebuffer} */ var framebuffer;
+ /** @type {WebGLRenderbuffer} */ var renderbuffer;
+ /** @type {number} */ var red;
+ /** @type {number} */ var green;
+ /** @type {number} */ var blue;
+ /** @type {number} */ var alpha;
+ /** @type {Array<number>} */ var color;
+
+ if (this.m_format === gl.RGBA_INTEGER) {
+ if (this.m_type === gl.UNSIGNED_INT) {
+ renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA32UI, this.m_width, this.m_height);
+ } else if (this.m_type === gl.INT) {
+ renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA32I, this.m_width, this.m_height);
+ } else
+ throw new Error('Type not supported');
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer);
+ } else if (this.m_format === gl.RGBA || /*this.m_format === gl.BGRA ||*/ this.m_format === gl.RGB) {
+ // Empty
+ } else
+ throw new Error('Format not supported');
+
+ gl.viewport(0, 0, width, height);
+
+ // Clear color
+ if (this.m_format === gl.RGBA || this.m_format === gl.RGB) {
+ red = rnd.getFloat();
+ green = rnd.getFloat();
+ blue = rnd.getFloat();
+ alpha = rnd.getFloat();
+
+ color = [red, green, blue, alpha];
+ // Clear target
+ gl.clearColor(red, green, blue, alpha);
+ bufferedLogToConsole('ClearColor: (' + red + ', ' + green + ', ' + blue + ')');
+
+ gl.clearBufferfv(gl.COLOR, 0, color);
+
+ // Clear reference
+ level0.clear(color);
+ } else if (this.m_format === gl.RGBA_INTEGER) {
+ if (this.m_type === gl.INT) {
+ red = Math.abs(rnd.getInt());
+ green = Math.abs(rnd.getInt());
+ blue = Math.abs(rnd.getInt());
+ alpha = Math.abs(rnd.getInt());
+
+ color = [red, green, blue, alpha];
+ bufferedLogToConsole('ClearColor: (' + red + ', ' + green + ', ' + blue + ')');
+
+ gl.clearBufferiv(gl.COLOR, 0, color);
+
+ // Clear reference
+ level0.clear([red, green, blue, alpha]);
+ } else if (this.m_type === gl.UNSIGNED_INT) {
+ red = Math.abs(rnd.getInt());
+ green = Math.abs(rnd.getInt());
+ blue = Math.abs(rnd.getInt());
+ alpha = Math.abs(rnd.getInt());
+
+ color = [red, green, blue, alpha];
+ bufferedLogToConsole('ClearColor: (' + red + ', ' + green + ', ' + blue + ')');
+
+ gl.clearBufferuiv(gl.COLOR, 0, color);
+
+ // Clear reference
+ level0.clear(color);
+ } else
+ throw new Error('Type not supported.');
+ } else
+ throw new Error('Format not supported.');
+
+ this.render(reference);
+
+ /** @type {number} */ var rowWidth = (this.m_rowLength === 0 ? this.m_width : this.m_rowLength) + this.m_skipPixels;
+ /** @type {number} */ var rowPitch = (align ? this.m_alignment * Math.ceil(pixelSize * rowWidth / this.m_alignment) : rowWidth * pixelSize);
+
+ var arrayType = tcuTexture.getTypedArray(reference.getFormat().type);
+ /** @type {goog.TypedArray} */ var pixelData = new arrayType(rowPitch * (this.m_height + this.m_skipRows));
+ gl.readPixels(0, 0, this.m_width, this.m_height, this.m_format, this.m_type, pixelData);
+
+ if (framebuffer)
+ gl.deleteFramebuffer(framebuffer);
+
+ if (renderbuffer)
+ gl.deleteRenderbuffer(renderbuffer);
+
+ return pixelData;
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fReadPixelTests.ReadPixelsTest.prototype.iterate = function() {
+ /** @type {tcuTexture.TextureFormat} */ var format = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+ /** @type {number} */ var pixelSize;
+ /** @type {boolean} */ var align;
+
+ /** @type {{format: tcuTexture.TextureFormat, pixelSize: number, align: boolean}} */ var formatInfo = this.getFormatInfo();
+ format = formatInfo.format;
+ align = formatInfo.align;
+ pixelSize = formatInfo.pixelSize;
+
+ bufferedLogToConsole('Format: ' + this.m_format + ', Type: ' + this.m_type);
+
+ /** @type {tcuTexture.Texture2D} */ var reference = new tcuTexture.Texture2D(format, this.m_width, this.m_height);
+ reference.allocLevel(0);
+ /** @return {tcuTexture.PixelBufferAccess} */ var level0 = reference.getLevel(0);
+
+ this.m_alignment = /** @type {number} */ (gl.getParameter(gl.PACK_ALIGNMENT));
+ bufferedLogToConsole('gl.PACK_ALIGNMENT: ' + this.m_alignment);
+
+ this.m_rowLength = /** @type {number} */ (gl.getParameter(gl.PACK_ROW_LENGTH));
+ bufferedLogToConsole('gl.PACK_ROW_LENGTH: ' + this.m_rowLength);
+
+ this.m_skipRows = /** @type {number} */ (gl.getParameter(gl.PACK_SKIP_ROWS));
+ bufferedLogToConsole('gl.PACK_SKIP_ROWS: ' + this.m_skipRows);
+
+ this.m_skipPixels = /** @type {number} */ (gl.getParameter(gl.PACK_SKIP_PIXELS));
+ bufferedLogToConsole('gl.PACK_SKIP_PIXELS: ' + this.m_skipPixels);
+
+ gl.viewport(0, 0, this.m_width, this.m_height);
+
+ /** @type {goog.TypedArray} */ var pixelData = this.clearColor(reference, align, pixelSize);
+
+ /** @type {number} */ var rowWidth = (this.m_rowLength === 0 ? this.m_width : this.m_rowLength);
+ /** @type {number} */ var rowPitch = (align ? this.m_alignment * Math.ceil(pixelSize * rowWidth / this.m_alignment) : rowWidth * pixelSize);
+ /** @type {Array<number>} */ var formatBitDepths = [];
+ /** @type {number} */ var redThreshold;
+ /** @type {number} */ var greenThreshold;
+ /** @type {number} */ var blueThreshold;
+ /** @type {number} */ var alphaThreshold;
+ var redBits = /** @type {number} */ (gl.getParameter(gl.RED_BITS));
+ var blueBits = /** @type {number} */ (gl.getParameter(gl.BLUE_BITS));
+ var greenBits = /** @type {number} */ (gl.getParameter(gl.GREEN_BITS));
+ var alphaBits = /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS));
+ /** @type {(tcuRGBA.RGBA|Array<number>)} */ var threshold;
+ /** @type {tcuTexture.PixelBufferAccess} */ var result;
+ // \note gl.RGBA_INTEGER uses always renderbuffers that are never multisampled. Otherwise default framebuffer is used.
+ if (this.m_format !== gl.RGBA_INTEGER && /** @type {number} */ (gl.getParameter(gl.SAMPLES)) > 1) {
+ formatBitDepths = tcuTextureUtil.getTextureFormatBitDepth(format);
+ redThreshold = Math.ceil(256.0 * (2.0 / (1 << Math.min(redBits, formatBitDepths[0]))));
+ greenThreshold = Math.ceil(256.0 * (2.0 / (1 << Math.min(greenBits, formatBitDepths[1]))));
+ blueThreshold = Math.ceil(256.0 * (2.0 / (1 << Math.min(blueBits, formatBitDepths[2]))));
+ alphaThreshold = Math.ceil(256.0 * (2.0 / (1 << Math.min(alphaBits, formatBitDepths[3]))));
+
+ result = tcuTexture.PixelBufferAccess.newFromTextureFormat(format, this.m_width, this.m_height, 1, rowPitch, 0, pixelData.buffer);
+ threshold = new tcuRGBA.RGBA([redThreshold, greenThreshold, blueThreshold, alphaThreshold]);
+ if (tcuImageCompare.bilinearCompare('Result', 'Result', level0, result, threshold))
+ testPassedOptions('Pass', true);
+ else
+ testFailedOptions('Fail', false);
+ } else {
+ formatBitDepths = tcuTextureUtil.getTextureFormatBitDepth(format);
+ redThreshold = 2.0 / (1 << Math.min(redBits, formatBitDepths[0]));
+ greenThreshold = 2.0 / (1 << Math.min(greenBits, formatBitDepths[1]));
+ blueThreshold = 2.0 / (1 << Math.min(blueBits, formatBitDepths[2]));
+ alphaThreshold = 2.0 / (1 << Math.min(alphaBits, formatBitDepths[3]));
+
+ // Compare
+ result = new tcuTexture.PixelBufferAccess({
+ format: format,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: rowPitch,
+ data: pixelData.buffer,
+ offset: pixelSize * this.m_skipPixels + this.m_skipRows * rowPitch
+ });
+
+ threshold = [redThreshold, greenThreshold, blueThreshold, alphaThreshold];
+ if (tcuImageCompare.floatThresholdCompare('Result', 'Result', level0, result, threshold))
+ testPassedOptions('Pass', true);
+ else
+ testFailedOptions('Fail', false);
+ }
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fReadPixelTests.ReadPixelTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'read_pixels', 'ReadPixel tests');
+ };
+
+ es3fReadPixelTests.ReadPixelTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fReadPixelTests.ReadPixelTests.prototype.constructor = es3fReadPixelTests.ReadPixelTests;
+
+ es3fReadPixelTests.ReadPixelTests.prototype.init = function() {
+ /** @type {tcuTestCase.DeqpTest} */ var groupAlignment = tcuTestCase.newTest('alignment', 'Read pixels pack alignment parameter tests');
+
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_1', '', false, 1, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_2', '', false, 2, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_4', '', false, 4, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_8', '', false, 8, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_1', '', false, 1, 0, 0, 0, gl.RGBA_INTEGER, gl.INT));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_2', '', false, 2, 0, 0, 0, gl.RGBA_INTEGER, gl.INT));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_4', '', false, 4, 0, 0, 0, gl.RGBA_INTEGER, gl.INT));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_8', '', false, 8, 0, 0, 0, gl.RGBA_INTEGER, gl.INT));
+
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_1', '', false, 1, 0, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_2', '', false, 2, 0, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_4', '', false, 4, 0, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_8', '', false, 8, 0, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_1', '', true, 1, 0, 0, 0));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_2', '', true, 2, 0, 0, 0));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_4', '', true, 4, 0, 0, 0));
+ groupAlignment.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_8', '', true, 8, 0, 0, 0));
+
+ this.addChild(groupAlignment);
+
+ /** @type {tcuTestCase.DeqpTest} */ var groupRowLength = tcuTestCase.newTest('rowlength', 'Read pixels rowlength test');
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_17', '', false, 4, 17, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_19', '', false, 4, 19, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_23', '', false, 4, 23, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_29', '', false, 4, 29, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_17', '', false, 4, 17, 0, 0, gl.RGBA_INTEGER, gl.INT));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_19', '', false, 4, 19, 0, 0, gl.RGBA_INTEGER, gl.INT));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_23', '', false, 4, 23, 0, 0, gl.RGBA_INTEGER, gl.INT));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_29', '', false, 4, 29, 0, 0, gl.RGBA_INTEGER, gl.INT));
+
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_17', '', false, 4, 17, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_19', '', false, 4, 19, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_23', '', false, 4, 23, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_29', '', false, 4, 29, 0, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_17', '', true, 4, 17, 0, 0));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_19', '', true, 4, 19, 0, 0));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_23', '', true, 4, 23, 0, 0));
+ groupRowLength.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_29', '', true, 4, 29, 0, 0));
+
+ this.addChild(groupRowLength);
+
+ /** @type {tcuTestCase.DeqpTest} */ var groupSkip = tcuTestCase.newTest('skip', 'Read pixels skip pixels and rows test');
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_0_3', '', false, 4, 17, 0, 3, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_3_0', '', false, 4, 17, 3, 0, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_3_3', '', false, 4, 17, 3, 3, gl.RGBA, gl.UNSIGNED_BYTE));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_ubyte_3_5', '', false, 4, 17, 3, 5, gl.RGBA, gl.UNSIGNED_BYTE));
+
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_0_3', '', false, 4, 17, 0, 3, gl.RGBA_INTEGER, gl.INT));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_3_0', '', false, 4, 17, 3, 0, gl.RGBA_INTEGER, gl.INT));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_3_3', '', false, 4, 17, 3, 3, gl.RGBA_INTEGER, gl.INT));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_int_3_5', '', false, 4, 17, 3, 5, gl.RGBA_INTEGER, gl.INT));
+
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_0_3', '', false, 4, 17, 0, 3, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_3_0', '', false, 4, 17, 3, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_3_3', '', false, 4, 17, 3, 3, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('rgba_uint_3_5', '', false, 4, 17, 3, 5, gl.RGBA_INTEGER, gl.UNSIGNED_INT));
+
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_0_3', '', true, 4, 17, 0, 3));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_3_0', '', true, 4, 17, 3, 0));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_3_3', '', true, 4, 17, 3, 3));
+ groupSkip.addChild(new es3fReadPixelTests.ReadPixelsTest('choose_3_5', '', true, 4, 17, 3, 5));
+
+ this.addChild(groupSkip);
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fReadPixelTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fReadPixelTests.ReadPixelTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fReadPixelTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerObjectTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerObjectTests.js
new file mode 100644
index 0000000000..271a2186ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerObjectTests.js
@@ -0,0 +1,313 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fSamplerObjectTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('modules.shared.glsSamplerObjectTest');
+
+goog.scope(function() {
+
+var es3fSamplerObjectTests = functional.gles3.es3fSamplerObjectTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsSamplerObjectTest = modules.shared.glsSamplerObjectTest;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ // TODO: implement glsSamplerObjectTest and validate constructors
+ es3fSamplerObjectTests.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ /** @type {Array<glsSamplerObjectTest.TestSpec>} */ var simpleTestCases = [
+ new glsSamplerObjectTest.TestSpec('diff_wrap_t', 'Different gl.TEXTURE_WRAP_T', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_s', 'Different gl.TEXTURE_WRAP_S', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_r', 'Different gl.TEXTURE_WRAP_R', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_filter', 'Different gl.TEXTURE_MIN_FILTER', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_mag_filter', 'Different gl.TEXTURE_MAG_FILTER', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_max_lod', 'Different gl.TEXTURE_MAX_LOD', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, -999.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_lod', 'Different gl.TEXTURE_MIN_LOD', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 100.0, 1000.0)
+ )
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var simpleTexture2D = tcuTestCase.newTest('single_tex_2d', 'Simple 2D texture with sampler');
+
+ for (var testNdx = 0; testNdx < simpleTestCases.length; testNdx++)
+ simpleTexture2D.addChild(new glsSamplerObjectTest.TextureSamplerTest(simpleTestCases[testNdx]));
+
+ testGroup.addChild(simpleTexture2D);
+
+ /** @type {Array<glsSamplerObjectTest.TestSpec>} */ var multiTestCases = [
+ new glsSamplerObjectTest.TestSpec('diff_wrap_t', 'Different gl.TEXTURE_WRAP_T', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_s', 'Different gl.TEXTURE_WRAP_S', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_r', 'Different gl.TEXTURE_WRAP_R', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_filter', 'Different gl.TEXTURE_MIN_FILTER', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_mag_filter', 'Different gl.TEXTURE_MAG_FILTER', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_max_lod', 'Different gl.TEXTURE_MAX_LOD', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, -999.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_lod', 'Different gl.TEXTURE_MIN_LOD', gl.TEXTURE_2D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 100.0, 1000.0)
+ )
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var multiTexture2D = tcuTestCase.newTest('multi_tex_2d', 'Multiple texture units 2D texture with sampler');
+
+ for (var testNdx = 0; testNdx < multiTestCases.length; testNdx++)
+ multiTexture2D.addChild(new glsSamplerObjectTest.MultiTextureSamplerTest(multiTestCases[testNdx]));
+
+ testGroup.addChild(multiTexture2D);
+
+ /** @type {Array<glsSamplerObjectTest.TestSpec>} */ var simpleTestCases3D = [
+ new glsSamplerObjectTest.TestSpec('diff_wrap_t', 'Different gl.TEXTURE_WRAP_T', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_s', 'Different gl.TEXTURE_WRAP_S', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_r', 'Different gl.TEXTURE_WRAP_R', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_filter', 'Different gl.TEXTURE_MIN_FILTER', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_mag_filter', 'Different gl.TEXTURE_MAG_FILTER', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_max_lod', 'Different gl.TEXTURE_MAX_LOD', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, -999.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_lod', 'Different gl.TEXTURE_MIN_LOD', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 100.0, 1000.0)
+ )
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var simpleTexture3D = tcuTestCase.newTest('single_tex_3d', 'Simple 3D texture with sampler');
+
+ for (var testNdx = 0; testNdx < simpleTestCases3D.length; testNdx++)
+ simpleTexture3D.addChild(new glsSamplerObjectTest.TextureSamplerTest(simpleTestCases3D[testNdx]));
+
+ testGroup.addChild(simpleTexture3D);
+
+ /** @type {Array<glsSamplerObjectTest.TestSpec>} */ var multiTestCases3D = [
+ new glsSamplerObjectTest.TestSpec('diff_wrap_t', 'Different gl.TEXTURE_WRAP_T', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_s', 'Different gl.TEXTURE_WRAP_S', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_r', 'Different gl.TEXTURE_WRAP_R', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_filter', 'Different gl.TEXTURE_MIN_FILTER', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_mag_filter', 'Different gl.TEXTURE_MAG_FILTER', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_max_lod', 'Different gl.TEXTURE_MAX_LOD', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, -999.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_lod', 'Different gl.TEXTURE_MIN_LOD', gl.TEXTURE_3D,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 100.0, 1000.0)
+ )
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var multiTexture3D = tcuTestCase.newTest('multi_tex_3d', 'Multiple texture units 3D texture with sampler');
+
+ for (var testNdx = 0; testNdx < multiTestCases3D.length; testNdx++)
+ multiTexture3D.addChild(new glsSamplerObjectTest.MultiTextureSamplerTest(multiTestCases3D[testNdx]));
+
+ testGroup.addChild(multiTexture3D);
+
+ /** @type {Array<glsSamplerObjectTest.TestSpec>} */ var simpleTestCasesCube = [
+ new glsSamplerObjectTest.TestSpec('diff_wrap_t', 'Different gl.TEXTURE_WRAP_T', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_s', 'Different gl.TEXTURE_WRAP_S', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_r', 'Different gl.TEXTURE_WRAP_R', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_filter', 'Different gl.TEXTURE_MIN_FILTER', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_mag_filter', 'Different gl.TEXTURE_MAG_FILTER', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_max_lod', 'Different gl.TEXTURE_MAX_LOD', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, -999.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_lod', 'Different gl.TEXTURE_MIN_LOD', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 100.0, 1000.0)
+ )
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var simpleTextureCube = tcuTestCase.newTest('single_cubemap', 'Simple cubemap texture with sampler');
+
+ for (var testNdx = 0; testNdx < simpleTestCasesCube.length; testNdx++)
+ simpleTextureCube.addChild(new glsSamplerObjectTest.TextureSamplerTest(simpleTestCasesCube[testNdx]));
+
+ testGroup.addChild(simpleTextureCube);
+
+ /** @type {Array<glsSamplerObjectTest.TestSpec>} */ var multiTestCasesCube = [
+ new glsSamplerObjectTest.TestSpec('diff_wrap_t', 'Different gl.TEXTURE_WRAP_T', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.MIRRORED_REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_s', 'Different gl.TEXTURE_WRAP_S', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.MIRRORED_REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_wrap_r', 'Different gl.TEXTURE_WRAP_R', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.MIRRORED_REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_filter', 'Different gl.TEXTURE_MIN_FILTER', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.LINEAR, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_mag_filter', 'Different gl.TEXTURE_MAG_FILTER', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.LINEAR, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_max_lod', 'Different gl.TEXTURE_MAX_LOD', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, -1000.0, -999.0)
+ ),
+ new glsSamplerObjectTest.TestSpec('diff_min_lod', 'Different gl.TEXTURE_MIN_LOD', gl.TEXTURE_CUBE_MAP,
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 0.0, 1000.0),
+ new glsSamplerObjectTest.SamplingState(gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST, gl.REPEAT, gl.REPEAT, gl.REPEAT, 100.0, 1000.0)
+ )
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var multiTextureCube = tcuTestCase.newTest('multi_cubemap', 'Multiple texture units cubemap textures with sampler');
+
+ for (var testNdx = 0; testNdx < multiTestCasesCube.length; testNdx++)
+ multiTextureCube.addChild(new glsSamplerObjectTest.MultiTextureSamplerTest(multiTestCasesCube[testNdx]));
+
+ testGroup.addChild(multiTextureCube);
+ };
+
+ es3fSamplerObjectTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'sampler_object';
+ var testDescription = 'Sampler Object Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.setRoot(tcuTestCase.newTest(testName, testDescription, null));
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fSamplerObjectTests.init();
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fSamplerObjectTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerStateQueryTests.js
new file mode 100644
index 0000000000..22cfde12aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSamplerStateQueryTests.js
@@ -0,0 +1,205 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fSamplerStateQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fSamplerStateQueryTests = functional.gles3.es3fSamplerStateQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+var deRandom = framework.delibs.debase.deRandom;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fSamplerStateQueryTests.SamplerCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {WebGLSampler} */ this.m_sampler;
+};
+
+setParentClass(es3fSamplerStateQueryTests.SamplerCase, es3fApiCase.ApiCase);
+
+es3fSamplerStateQueryTests.SamplerCase.prototype.testSampler = function() {
+ throw new Error('Virtual function. Please override.');
+};
+
+es3fSamplerStateQueryTests.SamplerCase.prototype.test = function() {
+ this.m_sampler = gl.createSampler();
+
+ this.testSampler();
+
+ gl.deleteSampler(this.m_sampler);
+};
+
+/**
+ * @constructor
+ * @extends {es3fSamplerStateQueryTests.SamplerCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} valueName
+ * @param {number} initialValue
+ * @param {Array<number>} valueRange
+ */
+es3fSamplerStateQueryTests.SamplerModeCase = function(name, description, valueName, initialValue, valueRange) {
+ es3fSamplerStateQueryTests.SamplerCase.call(this, name, description);
+ this.m_valueName = valueName;
+ this.m_initialValue = initialValue;
+ this.m_valueRange = valueRange;
+};
+
+setParentClass(es3fSamplerStateQueryTests.SamplerModeCase, es3fSamplerStateQueryTests.SamplerCase);
+
+es3fSamplerStateQueryTests.SamplerModeCase.prototype.testSampler = function() {
+ this.check(glsStateQuery.verifySampler(this.m_sampler, this.m_valueName, this.m_initialValue));
+
+ for (var ndx = 0; ndx < this.m_valueRange.length; ++ndx) {
+ gl.samplerParameteri(this.m_sampler, this.m_valueName, this.m_valueRange[ndx]);
+
+ this.check(glsStateQuery.verifySampler(this.m_sampler, this.m_valueName, this.m_valueRange[ndx]));
+ }
+
+ //check unit conversions with float
+
+ for (var ndx = 0; ndx < this.m_valueRange.length; ++ndx) {
+ gl.samplerParameterf(this.m_sampler, this.m_valueName, this.m_valueRange[ndx]);
+
+ this.check(glsStateQuery.verifySampler(this.m_sampler, this.m_valueName, this.m_valueRange[ndx]));
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fSamplerStateQueryTests.SamplerCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} lodTarget
+ * @param {number} initialValue
+ */
+es3fSamplerStateQueryTests.SamplerLODCase = function(name, description, lodTarget, initialValue) {
+ es3fSamplerStateQueryTests.SamplerCase.call(this, name, description);
+ this.m_lodTarget = lodTarget;
+ this.m_initialValue = initialValue;
+};
+
+setParentClass(es3fSamplerStateQueryTests.SamplerLODCase, es3fSamplerStateQueryTests.SamplerCase);
+
+es3fSamplerStateQueryTests.SamplerLODCase.prototype.testSampler = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verifySampler(this.m_sampler, this.m_lodTarget, this.m_initialValue));
+ var numIterations = 60;
+ for (var ndx = 0; ndx < numIterations; ++ndx) {
+ var ref = rnd.getFloat(-64000, 64000);
+
+ gl.samplerParameterf(this.m_sampler, this.m_lodTarget, ref);
+
+ this.check(glsStateQuery.verifySampler(this.m_sampler, this.m_lodTarget, ref));
+ }
+
+ // check unit conversions with int
+
+ for (var ndx = 0; ndx < numIterations; ++ndx) {
+ var ref = rnd.getInt(-64000, 64000);
+
+ gl.samplerParameteri(this.m_sampler, this.m_lodTarget, ref);
+
+ this.check(glsStateQuery.verifySampler(this.m_sampler, this.m_lodTarget, ref));
+ }
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fSamplerStateQueryTests.SamplerStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'sampler', 'Sampler State Query tests');
+};
+
+es3fSamplerStateQueryTests.SamplerStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fSamplerStateQueryTests.SamplerStateQueryTests.prototype.constructor = es3fSamplerStateQueryTests.SamplerStateQueryTests;
+
+es3fSamplerStateQueryTests.SamplerStateQueryTests.prototype.init = function() {
+ var wrapValues = [gl.CLAMP_TO_EDGE, gl.REPEAT, gl.MIRRORED_REPEAT];
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_wrap_s' , 'TEXTURE_WRAP_S',
+ gl.TEXTURE_WRAP_S, gl.REPEAT, wrapValues));
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_wrap_t' , 'TEXTURE_WRAP_T',
+ gl.TEXTURE_WRAP_T, gl.REPEAT, wrapValues));
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_wrap_r' , 'TEXTURE_WRAP_R',
+ gl.TEXTURE_WRAP_R, gl.REPEAT, wrapValues));
+
+ var magValues = [gl.NEAREST, gl.LINEAR];
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_mag_filter' , 'TEXTURE_MAG_FILTER',
+ gl.TEXTURE_MAG_FILTER, gl.LINEAR, magValues));
+
+ var minValues = [gl.NEAREST, gl.LINEAR, gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST_MIPMAP_LINEAR, gl.LINEAR_MIPMAP_NEAREST, gl.LINEAR_MIPMAP_LINEAR];
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_min_filter' , 'TEXTURE_MIN_FILTER',
+ gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR, minValues));
+
+ this.addChild(new es3fSamplerStateQueryTests.SamplerLODCase('sampler_texture_min_lod' , 'TEXTURE_MIN_LOD', gl.TEXTURE_MIN_LOD, -1000));
+ this.addChild(new es3fSamplerStateQueryTests.SamplerLODCase('sampler_texture_max_lod' , 'TEXTURE_MAX_LOD', gl.TEXTURE_MAX_LOD, 1000));
+
+ var modes = [gl.COMPARE_REF_TO_TEXTURE, gl.NONE];
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_compare_mode' , 'TEXTURE_COMPARE_MODE',
+ gl.TEXTURE_COMPARE_MODE, gl.NONE, modes));
+
+ var compareFuncs = [gl.LEQUAL, gl.GEQUAL, gl.LESS, gl.GREATER, gl.EQUAL, gl.NOTEQUAL, gl.ALWAYS, gl.NEVER];
+ this.addChild(new es3fSamplerStateQueryTests.SamplerModeCase('sampler_texture_compare_func' , 'TEXTURE_COMPARE_FUNC',
+ gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL, compareFuncs));
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fSamplerStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fSamplerStateQueryTests.SamplerStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fSamplerStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderApiTests.js
new file mode 100644
index 0000000000..2768f0325b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderApiTests.js
@@ -0,0 +1,650 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderApiTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+var es3fShaderApiTests = functional.gles3.es3fShaderApiTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var es3fApiCase = functional.gles3.es3fApiCase;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var deRandom = framework.delibs.debase.deRandom;
+var deString = framework.delibs.debase.deString;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+var getSimpleShaderSource = function(shaderType) {
+ var simpleVertexShaderSource =
+ '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+
+ var simpleFragmentShaderSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ switch (shaderType) {
+ case gluShaderProgram.shaderType.VERTEX:
+ return simpleVertexShaderSource;
+ case gluShaderProgram.shaderType.FRAGMENT:
+ return simpleFragmentShaderSource;
+ default:
+ throw new Error('Invalid shader type');
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.CreateShaderCase = function(name, description, shaderType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_shaderType = shaderType;
+};
+
+setParentClass(es3fShaderApiTests.CreateShaderCase, es3fApiCase.ApiCase);
+
+es3fShaderApiTests.CreateShaderCase.prototype.test = function() {
+ var shaderObject = gl.createShader(gluShaderProgram.getGLShaderType(gl, this.m_shaderType));
+ this.check(shaderObject != null);
+ gl.deleteShader(shaderObject);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.CompileShaderCase = function(name, description, shaderType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_shaderType = shaderType;
+};
+
+setParentClass(es3fShaderApiTests.CompileShaderCase, es3fApiCase.ApiCase);
+
+es3fShaderApiTests.CompileShaderCase.prototype.checkCompileStatus = function(shader) {
+ var status = /** @type {boolean} */ (gl.getShaderParameter(shader, gl.COMPILE_STATUS));
+ return status;
+};
+
+es3fShaderApiTests.CompileShaderCase.prototype.test = function() {
+ var shaderObject = gl.createShader(gluShaderProgram.getGLShaderType(gl, this.m_shaderType));
+ var shaderSource = getSimpleShaderSource(this.m_shaderType);
+
+ this.check(shaderObject != null);
+
+ gl.shaderSource(shaderObject, shaderSource);
+ gl.compileShader(shaderObject);
+
+ this.check(this.checkCompileStatus(shaderObject));
+
+ gl.deleteShader(shaderObject);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ShaderSourceReplaceCase = function(name, description, shaderType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_shaderType = shaderType;
+};
+
+setParentClass(es3fShaderApiTests.ShaderSourceReplaceCase, es3fApiCase.ApiCase);
+
+es3fShaderApiTests.ShaderSourceReplaceCase.prototype.generateFirstSource = function() {
+ return getSimpleShaderSource(this.m_shaderType);
+};
+
+es3fShaderApiTests.ShaderSourceReplaceCase.prototype.generateSecondSource = function() {
+ var source = '#version 300 es\n' +
+ 'precision mediump float;\n';
+
+ if (this.m_shaderType == gluShaderProgram.shaderType.FRAGMENT)
+ source += 'layout(location = 0) out mediump vec4 o_fragColor;\n';
+
+ source += 'void main()\n'+
+ '{\n'+
+ ' float variable = 1.0f;\n';
+
+ if (this.m_shaderType == gluShaderProgram.shaderType.VERTEX) source += ' gl_Position = vec4(variable);\n';
+ else if (this.m_shaderType == gluShaderProgram.shaderType.FRAGMENT) source += ' o_fragColor = vec4(variable);\n';
+
+ source += '}\n';
+
+ return source;
+};
+
+es3fShaderApiTests.ShaderSourceReplaceCase.prototype.test = function() {
+ var shaderObject = gl.createShader(gluShaderProgram.getGLShaderType(gl, this.m_shaderType));
+ var firstSource = this.generateFirstSource();
+ var secondSource = this.generateSecondSource();
+
+ this.check(shaderObject != null);
+
+ gl.shaderSource(shaderObject, firstSource);
+ this.check(firstSource == gl.getShaderSource(shaderObject));
+
+ gl.shaderSource(shaderObject, secondSource);
+ this.check(secondSource == gl.getShaderSource(shaderObject));
+
+ gl.deleteShader(shaderObject);
+};
+
+/**
+ * @constructor
+ */
+es3fShaderApiTests.SourceGenerator = function() {};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {string}
+ */
+es3fShaderApiTests.SourceGenerator.prototype.next = function(shaderType) {
+ throw new Error('Virtual function. Please override');
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {boolean}
+ */
+es3fShaderApiTests.SourceGenerator.prototype.finished = function(shaderType) {
+ throw new Error('Virtual function. Please override');
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.SourceGenerator}
+ */
+es3fShaderApiTests.ConstantShaderGenerator = function(rnd) {
+ es3fShaderApiTests.SourceGenerator.call(this);
+ this.m_rnd = rnd;
+};
+
+setParentClass(es3fShaderApiTests.ConstantShaderGenerator, es3fShaderApiTests.SourceGenerator);
+
+es3fShaderApiTests.SourceGenerator.prototype.next = function(shaderType) {
+ var value = this.m_rnd.getFloat(0.0, 1.0);
+ var outputName = (shaderType == gluShaderProgram.shaderType.VERTEX) ? 'gl_Position' : 'o_fragColor';
+
+ var out = '#version 300 es\n';
+
+ if (shaderType == gluShaderProgram.shaderType.FRAGMENT)
+ out += 'layout(location = 0) out mediump vec4 o_fragColor;\n';
+
+ out += 'void main (void)\n';
+ out += '{\n';
+ out += ' ' + outputName + ' = vec4(' + value + ');\n';
+ out += '}\n';
+
+ return out;
+};
+
+es3fShaderApiTests.SourceGenerator.prototype.finished = function(shaderType) {
+ return false;
+};
+
+// Shader allocation utility
+
+/**
+ * @constructor
+ * @param {es3fShaderApiTests.SourceGenerator} generator
+ */
+es3fShaderApiTests.ShaderAllocator = function(generator) {
+ this.m_srcGen = generator;
+ this.m_shaders = {};
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ShaderAllocator.prototype.createShader = function(shaderType) {
+ var shader = new gluShaderProgram.Shader(gl, shaderType);
+ this.m_shaders[shaderType] = shader;
+ this.setSource(shaderType);
+ return shader;
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ShaderAllocator.prototype.deleteShader = function(shaderType) {
+ this.m_shaders[shaderType].destroy();
+ this.m_shaders[shaderType] = null;
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ShaderAllocator.prototype.setSource = function(shaderType) {
+ var source = this.m_srcGen.next(shaderType);
+ this.m_shaders[shaderType].setSources(source);
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ShaderAllocator.prototype.get = function(shaderType) {
+ return this.m_shaders[shaderType];
+};
+
+// Base class for simple program API tests
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderApiTests.SimpleProgramCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_vertShader = null;
+ this.m_fragShader = null;
+ this.m_program = null;
+};
+
+setParentClass(es3fShaderApiTests.SimpleProgramCase, es3fApiCase.ApiCase);
+
+es3fShaderApiTests.SimpleProgramCase.prototype.compileShaders = function() {
+ var vertSource = getSimpleShaderSource(gluShaderProgram.shaderType.VERTEX);
+ var fragSource = getSimpleShaderSource(gluShaderProgram.shaderType.FRAGMENT);
+
+ var vertShader = gl.createShader(gl.VERTEX_SHADER);
+ var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
+
+ this.check(vertShader != null);
+ this.check(fragShader != null);
+
+ gl.shaderSource(vertShader, vertSource);
+ gl.compileShader(vertShader);
+
+ gl.shaderSource(fragShader, fragSource);
+ gl.compileShader(fragShader);
+
+ this.m_vertShader = vertShader;
+ this.m_fragShader = fragShader;
+};
+
+es3fShaderApiTests.SimpleProgramCase.prototype.linkProgram = function() {
+ var program = gl.createProgram();
+
+ this.check(program != null);
+
+ gl.attachShader(program, this.m_vertShader);
+ gl.attachShader(program, this.m_fragShader);
+
+ gl.linkProgram(program);
+
+ this.m_program = program;
+};
+
+es3fShaderApiTests.SimpleProgramCase.prototype.cleanup = function() {
+ gl.deleteShader(this.m_vertShader);
+ gl.deleteShader(this.m_fragShader);
+ gl.deleteProgram(this.m_program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.SimpleProgramCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderApiTests.DeleteShaderCase = function(name, description) {
+ es3fShaderApiTests.SimpleProgramCase.call(this, name, description);
+};
+
+setParentClass(es3fShaderApiTests.DeleteShaderCase, es3fShaderApiTests.SimpleProgramCase);
+
+es3fShaderApiTests.DeleteShaderCase.prototype.checkDeleteStatus = function(shader) {
+ var status = /** @type {boolean} */ (gl.getShaderParameter(shader, gl.DELETE_STATUS));
+ return status;
+};
+
+es3fShaderApiTests.DeleteShaderCase.prototype.deleteShaders = function() {
+ gl.deleteShader(this.m_vertShader);
+ gl.deleteShader(this.m_fragShader);
+};
+
+es3fShaderApiTests.DeleteShaderCase.prototype.test = function() {
+ this.compileShaders();
+ this.linkProgram();
+
+ this.deleteShaders();
+
+ this.check(this.checkDeleteStatus(this.m_vertShader) && this.checkDeleteStatus(this.m_fragShader));
+
+ gl.deleteProgram(this.m_program);
+
+ this.check(!(gl.isShader(this.m_vertShader) || gl.isShader(this.m_fragShader)));
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.SimpleProgramCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderApiTests.LinkVertexFragmentCase = function(name, description) {
+ es3fShaderApiTests.SimpleProgramCase.call(this, name, description);
+};
+
+setParentClass(es3fShaderApiTests.LinkVertexFragmentCase, es3fShaderApiTests.SimpleProgramCase);
+
+es3fShaderApiTests.LinkVertexFragmentCase.prototype.checkLinkStatus = function(program) {
+ var status = /** @type {boolean} */ (gl.getProgramParameter(program, gl.LINK_STATUS));
+ return status;
+};
+
+es3fShaderApiTests.LinkVertexFragmentCase.prototype.test = function() {
+ this.compileShaders();
+ this.linkProgram();
+
+ this.check(this.checkLinkStatus(this.m_program), 'Fail, expected LINK_STATUS to be TRUE.');
+
+ this.cleanup();
+};
+
+// Base class for program state persistence cases
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateCase = function(name, description, shaderType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_shaderType = shaderType;
+ this.m_rnd = new deRandom.Random(deString.deStringHash(name) ^ 0x713de0ca);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateCase, es3fApiCase.ApiCase);
+
+/**
+ * @param {gluShaderProgram.Program} program
+ * @param {es3fShaderApiTests.ShaderAllocator} shaders
+ */
+es3fShaderApiTests.ProgramStateCase.prototype.buildProgram = function(program, shaders) {
+ var vertShader = shaders.createShader(gluShaderProgram.shaderType.VERTEX);
+ var fragShader = shaders.createShader(gluShaderProgram.shaderType.FRAGMENT);
+
+ vertShader.compile();
+ fragShader.compile();
+
+ program.attachShader(vertShader.getShader());
+ program.attachShader(fragShader.getShader());
+ program.link();
+};
+
+/**
+ * @param {gluShaderProgram.Program} program
+ * @param {gluShaderProgram.ProgramInfo} reference
+ */
+es3fShaderApiTests.ProgramStateCase.prototype.verify = function(program, reference) {
+ var programInfo = program.getInfo();
+ this.check(programInfo.linkOk, 'Fail, link status may only change as a result of linking');
+
+ this.check(programInfo.linkTimeUs == reference.linkTimeUs, 'Fail, reported link time changed.');
+
+ this.check(programInfo.infoLog == reference.infoLog, 'Fail, program infolog changed.');
+};
+
+es3fShaderApiTests.ProgramStateCase.prototype.test = function() {
+ var sourceGen = new es3fShaderApiTests.ConstantShaderGenerator(this.m_rnd);
+
+ var shaders = new es3fShaderApiTests.ShaderAllocator(sourceGen);
+ var program = new gluShaderProgram.Program(gl);
+
+ this.buildProgram(program, shaders);
+
+ if (program.getLinkStatus()) {
+ var programInfo = program.getInfo();
+
+ this.executeForProgram(program, shaders);
+
+ this.verify(program, programInfo);
+
+ } else{
+ this.check(false, "Fail, couldn't link program.");
+ }
+
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.ProgramStateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateDetachShaderCase = function(name, description, shaderType) {
+ es3fShaderApiTests.ProgramStateCase.call(this, name, description, shaderType);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateDetachShaderCase, es3fShaderApiTests.ProgramStateCase);
+
+es3fShaderApiTests.ProgramStateDetachShaderCase.prototype.executeForProgram = function(program, shaders) {
+ var caseShader = shaders.get(this.m_shaderType);
+ program.detachShader(caseShader.getShader());
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.ProgramStateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateReattachShaderCase = function(name, description, shaderType) {
+ es3fShaderApiTests.ProgramStateCase.call(this, name, description, shaderType);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateReattachShaderCase, es3fShaderApiTests.ProgramStateCase);
+
+es3fShaderApiTests.ProgramStateReattachShaderCase.prototype.executeForProgram = function(program, shaders) {
+ var caseShader = shaders.get(this.m_shaderType);
+ program.detachShader(caseShader.getShader());
+ program.attachShader(caseShader.getShader());
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.ProgramStateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateDeleteShaderCase = function(name, description, shaderType) {
+ es3fShaderApiTests.ProgramStateCase.call(this, name, description, shaderType);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateDeleteShaderCase, es3fShaderApiTests.ProgramStateCase);
+
+es3fShaderApiTests.ProgramStateDeleteShaderCase.prototype.executeForProgram = function(program, shaders) {
+ var caseShader = shaders.get(this.m_shaderType);
+ program.detachShader(caseShader.getShader());
+ shaders.deleteShader(this.m_shaderType);
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.ProgramStateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateReplaceShaderCase = function(name, description, shaderType) {
+ es3fShaderApiTests.ProgramStateCase.call(this, name, description, shaderType);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateReplaceShaderCase, es3fShaderApiTests.ProgramStateCase);
+
+es3fShaderApiTests.ProgramStateReplaceShaderCase.prototype.executeForProgram = function(program, shaders) {
+ var caseShader = shaders.get(this.m_shaderType);
+ program.detachShader(caseShader.getShader());
+ shaders.deleteShader(this.m_shaderType);
+ program.attachShader(shaders.createShader(this.m_shaderType).getShader());
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.ProgramStateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateRecompileShaderCase = function(name, description, shaderType) {
+ es3fShaderApiTests.ProgramStateCase.call(this, name, description, shaderType);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateRecompileShaderCase, es3fShaderApiTests.ProgramStateCase);
+
+es3fShaderApiTests.ProgramStateRecompileShaderCase.prototype.executeForProgram = function(program, shaders) {
+ var caseShader = shaders.get(this.m_shaderType);
+ caseShader.compile();
+};
+
+/**
+ * @constructor
+ * @extends {es3fShaderApiTests.ProgramStateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+es3fShaderApiTests.ProgramStateReplaceSourceCase = function(name, description, shaderType) {
+ es3fShaderApiTests.ProgramStateCase.call(this, name, description, shaderType);
+};
+
+setParentClass(es3fShaderApiTests.ProgramStateReplaceSourceCase, es3fShaderApiTests.ProgramStateCase);
+
+es3fShaderApiTests.ProgramStateReplaceSourceCase.prototype.executeForProgram = function(program, shaders) {
+ var caseShader = shaders.get(this.m_shaderType);
+ shaders.setSource(this.m_shaderType);
+ caseShader.compile();
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fShaderApiTests.ShaderApiTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'shader_api', 'Shader API Cases');
+};
+
+es3fShaderApiTests.ShaderApiTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fShaderApiTests.ShaderApiTests.prototype.constructor = es3fShaderApiTests.ShaderApiTests;
+
+es3fShaderApiTests.ShaderApiTests.prototype.init = function() {
+ // create and delete shaders
+ var createDeleteGroup = new tcuTestCase.DeqpTest('create_delete', 'glCreateShader() tests');
+ this.addChild(createDeleteGroup);
+
+ createDeleteGroup.addChild(new es3fShaderApiTests.CreateShaderCase('create_vertex_shader', 'Create vertex shader object', gluShaderProgram.shaderType.VERTEX));
+ createDeleteGroup.addChild(new es3fShaderApiTests.CreateShaderCase('create_fragment_shader', 'Create fragment shader object', gluShaderProgram.shaderType.FRAGMENT));
+
+ createDeleteGroup.addChild(new es3fShaderApiTests.DeleteShaderCase('delete_vertex_fragment', 'Delete vertex shader and fragment shader'));
+
+ // compile and link
+ var compileLinkGroup = new tcuTestCase.DeqpTest('compile_link', 'Compile and link tests');
+ this.addChild(compileLinkGroup);
+
+ compileLinkGroup.addChild(new es3fShaderApiTests.CompileShaderCase('compile_vertex_shader', 'Compile vertex shader', gluShaderProgram.shaderType.VERTEX));
+ compileLinkGroup.addChild(new es3fShaderApiTests.CompileShaderCase('compile_fragment_shader', 'Compile fragment shader', gluShaderProgram.shaderType.FRAGMENT));
+
+ compileLinkGroup.addChild(new es3fShaderApiTests.LinkVertexFragmentCase('link_vertex_fragment', 'Link vertex and fragment shaders'));
+
+ // shader source
+ var shaderSourceGroup = new tcuTestCase.DeqpTest('shader_source', 'glShaderSource() tests');
+ this.addChild(shaderSourceGroup);
+ shaderSourceGroup.addChild(new es3fShaderApiTests.ShaderSourceReplaceCase('replace_source_vertex', 'Replace source code of vertex shader', gluShaderProgram.shaderType.VERTEX));
+ shaderSourceGroup.addChild(new es3fShaderApiTests.ShaderSourceReplaceCase('replace_source_fragment', 'Replace source code of fragment shader', gluShaderProgram.shaderType.FRAGMENT));
+
+ // link status and infolog
+ var linkStatusGroup = new tcuTestCase.DeqpTest('program_state', 'Program state persistence tests');
+ this.addChild(linkStatusGroup);
+
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateDetachShaderCase('detach_shader_vertex', 'detach vertex shader', gluShaderProgram.shaderType.VERTEX));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateReattachShaderCase('reattach_shader_vertex', 'reattach vertex shader', gluShaderProgram.shaderType.VERTEX));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateDeleteShaderCase('delete_shader_vertex', 'delete vertex shader', gluShaderProgram.shaderType.VERTEX));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateReplaceShaderCase('replace_shader_vertex', 'replace vertex shader object', gluShaderProgram.shaderType.VERTEX));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateRecompileShaderCase('recompile_shader_vertex', 'recompile vertex shader', gluShaderProgram.shaderType.VERTEX));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateReplaceSourceCase('replace_source_vertex', 'replace vertex shader source', gluShaderProgram.shaderType.VERTEX));
+
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateDetachShaderCase('detach_shader_fragment', 'detach fragment shader', gluShaderProgram.shaderType.FRAGMENT));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateReattachShaderCase('reattach_shader_fragment', 'reattach fragment shader', gluShaderProgram.shaderType.FRAGMENT));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateDeleteShaderCase('delete_shader_fragment', 'delete fragment shader', gluShaderProgram.shaderType.FRAGMENT));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateReplaceShaderCase('replace_shader_fragment', 'replace fragment shader object', gluShaderProgram.shaderType.FRAGMENT));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateRecompileShaderCase('recompile_shader_fragment', 'recompile fragment shader', gluShaderProgram.shaderType.FRAGMENT));
+ linkStatusGroup.addChild(new es3fShaderApiTests.ProgramStateReplaceSourceCase('replace_source_fragment', 'replace fragment shader source', gluShaderProgram.shaderType.FRAGMENT));
+
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fShaderApiTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderApiTests.ShaderApiTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderApiTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderBuiltinVarTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderBuiltinVarTests.js
new file mode 100644
index 0000000000..c696c6c12e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderBuiltinVarTests.js
@@ -0,0 +1,1109 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderBuiltinVarTests');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.referencerenderer.rrRenderer');
+goog.require('framework.referencerenderer.rrRenderState');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+goog.require('modules.shared.glsShaderRenderCase');
+goog.require('modules.shared.glsShaderExecUtil');
+
+goog.scope(function() {
+ var es3fShaderBuiltinVarTests = functional.gles3.es3fShaderBuiltinVarTests;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+ var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+ var rrRenderer = framework.referencerenderer.rrRenderer;
+ var rrRenderState = framework.referencerenderer.rrRenderState;
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+
+ /** @typedef {function():number} */ es3fShaderBuiltinVarTests.GetConstantValueFunc;
+
+ /**
+ * @param {number} pname
+ * @return {number} getParameter returns values of any kind
+ */
+ es3fShaderBuiltinVarTests.getInteger = function(pname) {
+ return /** @type {number} */ (gl.getParameter(pname));
+ };
+
+ /**
+ * @param {number} pname
+ * @return {number} forcing number
+ */
+ es3fShaderBuiltinVarTests.getVectorsFromComps = function(pname) {
+ var value = /** @type {number} */ (gl.getParameter(pname));
+ assertMsgOptions(value%4 === 0, 'Expected value to be divisible by 4.', false, true);
+ return value / 4;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} varName
+ * @param {es3fShaderBuiltinVarTests.GetConstantValueFunc} getValue
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase = function(name, desc, varName, getValue, shaderType) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /** @type {string} */ this.m_varName = varName;
+ /** @type {es3fShaderBuiltinVarTests.GetConstantValueFunc} */ this.m_getValue = getValue;
+ /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
+ };
+
+ es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.constructor = es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase;
+
+ es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.deinit = function() {
+ // an attempt to cleanup the GL state when the test fails
+ bufferedLogToConsole('ShaderBuildInConstantCase.deinit()');
+ gl.useProgram(null);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ };
+
+ /**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {string} varName
+ * @return {glsShaderExecUtil.ShaderExecutor}
+ */
+ es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.createGetConstantExecutor = function(shaderType, varName) {
+ /** @type {glsShaderExecUtil.ShaderSpec} */ var shaderSpec = new glsShaderExecUtil.ShaderSpec();
+ shaderSpec.version = gluShaderUtil.GLSLVersion.V300_ES;
+ shaderSpec.source = 'result = ' + varName + ';\n';
+ shaderSpec.outputs.push(new glsShaderExecUtil.Symbol('result',
+ gluVarType.newTypeBasic(gluShaderUtil.DataType.INT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ return glsShaderExecUtil.createExecutor(shaderType, shaderSpec);
+
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.iterate = function() {
+ /** @type {glsShaderExecUtil.ShaderExecutor} */
+ var shaderExecutor = this.createGetConstantExecutor(this.m_shaderType, this.m_varName);
+ /** @type {number} */ var reference = this.m_getValue();
+ /** @type {goog.NumberArray} */ var shaderExecutorResult;
+ /** @type {number} */ var result;
+
+ if (!shaderExecutor.isOk())
+ assertMsgOptions(false, 'Compile failed', false, true);
+
+ shaderExecutor.useProgram();
+
+ shaderExecutorResult = shaderExecutor.execute(1, null);
+ result = new Int32Array(shaderExecutorResult[0].buffer)[0];
+
+ bufferedLogToConsole(this.m_varName + ' = ' + result);
+
+ if (result != reference) {
+ bufferedLogToConsole('ERROR: Expected ' + this.m_varName + ' = ' + reference + '\n' +
+ 'Test shader:' + shaderExecutor.m_program.getProgramInfo().infoLog);
+ testFailedOptions('Invalid builtin constant value', false);
+ } else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @struct
+ * @constructor
+ * @param {number=} near
+ * @param {number=} far
+ */
+ es3fShaderBuiltinVarTests.DepthRangeParams = function(near, far) {
+ /** @type {number} */ this.zNear = near === undefined ? 0.0 : near;
+ /** @type {number} */ this.zFar = far === undefined ? 1.0 : far;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderEvaluator}
+ * @param {es3fShaderBuiltinVarTests.DepthRangeParams} params
+ */
+ es3fShaderBuiltinVarTests.DepthRangeEvaluator = function(params) {
+ /** @type {es3fShaderBuiltinVarTests.DepthRangeParams} */ this.m_params = params;
+ };
+
+ es3fShaderBuiltinVarTests.DepthRangeEvaluator.prototype = Object.create(glsShaderRenderCase.ShaderEvaluator.prototype);
+ es3fShaderBuiltinVarTests.DepthRangeEvaluator.prototype.constructor = es3fShaderBuiltinVarTests.DepthRangeEvaluator;
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+ es3fShaderBuiltinVarTests.DepthRangeEvaluator.prototype.evaluate = function(c) {
+ /** @type {number} */ var zNear = deMath.clamp(this.m_params.zNear, 0.0, 1.0);
+ /** @type {number} */ var zFar = deMath.clamp(this.m_params.zFar, 0.0, 1.0);
+ /** @type {number} */ var diff = zFar - zNear;
+ c.color[0] = zNear;
+ c.color[1] = zFar;
+ c.color[2] = diff * 0.5 + 0.5;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {boolean} isVertexCase
+ */
+ es3fShaderBuiltinVarTests.ShaderDepthRangeTest = function(name, desc, isVertexCase) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, desc, isVertexCase);
+ /** @type {es3fShaderBuiltinVarTests.DepthRangeParams} */ this.m_depthRange = new es3fShaderBuiltinVarTests.DepthRangeParams();
+ /** @type {es3fShaderBuiltinVarTests.DepthRangeEvaluator} */ this.m_evaluator = new es3fShaderBuiltinVarTests.DepthRangeEvaluator(this.m_depthRange);
+ /** @type {number} */ this.m_iterNdx = 0;
+ };
+
+ es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+ es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype.constructor = es3fShaderBuiltinVarTests.ShaderDepthRangeTest;
+
+ es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype.init = function() {
+ /** @type {string} */ var defaultVertSrc = '' +
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+ /** @type {string} */ var defaultFragSrc = '' +
+ '#version 300 es\n' +
+ 'in mediump vec4 v_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = v_color;\n' +
+ '}\n';
+
+ // Construct shader.
+ /** @type {string} */ var src = '#version 300 es\n';
+ if (this.m_isVertexCase)
+ src += 'in highp vec4 a_position;\n' +
+ 'out mediump vec4 v_color;\n';
+ else
+ src += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ src += 'void main (void)\n{\n' +
+ '\t' + (this.m_isVertexCase ? 'v_color' : 'o_color') + ' = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff*0.5 + 0.5, 1.0);\n';
+
+ if (this.m_isVertexCase)
+ src += '\tgl_Position = a_position;\n';
+
+ src += '}\n';
+
+ this.m_vertShaderSource = this.m_isVertexCase ? src : defaultVertSrc;
+ this.m_fragShaderSource = this.m_isVertexCase ? defaultFragSrc : src;
+
+ this.postinit();
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype.iterate = function() {
+ /** @type {Array<es3fShaderBuiltinVarTests.DepthRangeParams>} */ var cases = [
+ new es3fShaderBuiltinVarTests.DepthRangeParams(0.0, 1.0)
+ ];
+
+ this.m_depthRange = cases[this.m_iterNdx];
+ bufferedLogToConsole('gl.depthRange(' + this.m_depthRange.zNear + ', ' + this.m_depthRange.zFar + ')');
+ gl.depthRange(this.m_depthRange.zNear, this.m_depthRange.zFar);
+
+ this.postiterate();
+ this.m_iterNdx += 1;
+
+ if (this.m_iterNdx == cases.length)
+ return tcuTestCase.IterateResult.STOP;
+ else
+ return tcuTestCase.IterateResult.CONTINUE;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderBuiltinVarTests.FragCoordXYZCase = function() {
+ tcuTestCase.DeqpTest.call(this, 'fragcoord_xyz', 'gl_FragCoord.xyz Test');
+ };
+
+ es3fShaderBuiltinVarTests.FragCoordXYZCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.FragCoordXYZCase.prototype.constructor = es3fShaderBuiltinVarTests.FragCoordXYZCase;
+
+ es3fShaderBuiltinVarTests.FragCoordXYZCase.prototype.iterate = function() {
+ /** @type {number} */ var width = gl.drawingBufferWidth;
+ /** @type {number} */ var height = gl.drawingBufferHeight;
+ /** @type {Array<number>} */ var threshold = deMath.add([1, 1, 1, 1], tcuPixelFormat.PixelFormatFromContext(gl).getColorThreshold());
+ /** @type {Array<number>} */ var scale = [1. / width, 1. / height, 1.0];
+
+ /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
+
+ /** @type {string} */ var vtxSource = '' +
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+ /** @type {string} */ var fragSource = '' +
+ '#version 300 es\n' +
+ 'uniform highp vec3 u_scale;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = vec4(gl_FragCoord.xyz*u_scale, 1.0);\n' +
+ '}\n';
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
+
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ throw new Error('Compile failed');
+
+ // Draw with GL.
+ /** @type {Array<number>} */ var positions = [
+ -1.0, 1.0, -1.0, 1.0,
+ -1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 1.0, 1.0
+ ];
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+
+ /** @type {WebGLUniformLocation} */ var scaleLoc = gl.getUniformLocation(program.getProgram(), 'u_scale');
+ /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions);
+
+ gl.useProgram(program.getProgram());
+ gl.uniform3fv(scaleLoc, scale);
+
+ gl.viewport(0, 0, width, height);
+ gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indices));
+
+ testImg.readViewport(gl, [0, 0, width, height]);
+
+ // Draw reference
+ for (var y = 0; y < refImg.getHeight(); y++) {
+ for (var x = 0; x < refImg.getWidth(); x++) {
+ /** @type {number} */ var xf = (x + .5) / refImg.getWidth();
+ /** @type {number} */ var yf = (refImg.getHeight() - y - 1 + .5) / refImg.getHeight();
+ /** @type {number} */ var z = (xf + yf) / 2.0;
+ /** @type {Array<number>} */ var fragCoord = [x + .5, y + .5, z];
+ /** @type {Array<number>} */ var scaledFC = deMath.multiply(fragCoord, scale);
+ /** @type {Array<number>} */
+ var color = [
+ deMath.clamp(Math.floor(scaledFC[0] * 255 + 0.5), 0, 255),
+ deMath.clamp(Math.floor(scaledFC[1] * 255 + 0.5), 0, 255),
+ deMath.clamp(Math.floor(scaledFC[2] * 255 + 0.5), 0, 255),
+ 255];
+ refImg.setPixel(x, y, color);
+ }
+ }
+
+ // Compare
+ /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', refImg, testImg, threshold);
+
+ if (!isOk)
+ testFailedOptions('Image comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {Array<number>} s
+ * @param {Array<number>} w
+ * @param {number} nx
+ * @param {number} ny
+ * @return {number}
+ */
+ es3fShaderBuiltinVarTests.projectedTriInterpolate = function(s, w, nx, ny) {
+ return (s[0] * (1.0 - nx - ny)/w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) / ((1.0 - nx - ny) / w[0] + ny / w[1] + nx / w[2]);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderBuiltinVarTests.FragCoordWCase = function() {
+ tcuTestCase.DeqpTest.call(this, 'fragcoord_w', 'gl_FragCoord.w Test');
+ };
+
+ es3fShaderBuiltinVarTests.FragCoordWCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.FragCoordWCase.prototype.constructor = es3fShaderBuiltinVarTests.FragCoordWCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderBuiltinVarTests.FragCoordWCase.prototype.iterate = function() {
+ /** @type {number} */ var width = gl.drawingBufferWidth;
+ /** @type {number} */ var height = gl.drawingBufferHeight;
+ /** @type {Array<number>} */ var threshold = deMath.add([1, 1, 1, 1], tcuPixelFormat.PixelFormatFromContext(gl).getColorThreshold());
+
+ /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
+
+ /** @type {Array<number>} */ var w = [1.7, 2.0, 1.2, 1.0];
+
+ /** @type {string} */ var vtxSource = '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+
+ /** @type {string} */ var fragSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = vec4(0.0, 1.0/gl_FragCoord.w - 1.0, 0.0, 1.0);\n' +
+ '}\n';
+
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ throw new Error('Compile failed');
+
+ // Draw with GL.
+ /** @type {Array<number>} */ var positions = [
+ -w[0], w[0], 0.0, w[0],
+ -w[1], -w[1], 0.0, w[1],
+ w[2], w[2], 0.0, w[2],
+ w[3], -w[3], 0.0, w[3]
+ ];
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+
+ /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions);
+ gl.useProgram(program.getProgram());
+
+ gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indices));
+ testImg.readViewport(gl, [0, 0, width, height]);
+
+ // Draw reference
+ for (var y = 0; y < refImg.getHeight(); y++) {
+ for (var x = 0; x < refImg.getWidth(); x++) {
+ /** @type {number} */ var xf = (x + 0.5) / refImg.getWidth();
+ /** @type {number} */ var yf = (refImg.getHeight() - y - 1 + 0.5) / refImg.getHeight();
+ /** @type {number} */ var oow = ((xf + yf) < 1.0) ?
+ es3fShaderBuiltinVarTests.projectedTriInterpolate([w[0], w[1], w[2]], [w[0], w[1], w[2]], xf, yf) :
+ es3fShaderBuiltinVarTests.projectedTriInterpolate([w[3], w[2], w[1]], [w[3], w[2], w[1]], 1.0 - xf, 1.0 - yf);
+ /** @type {Array<number>} */
+ var color = [
+ 0,
+ deMath.clamp(Math.floor((oow - 1.0) * 255 + 0.5), 0, 255),
+ 0,
+ 255];
+ refImg.setPixel(x, y, color);
+ }
+ }
+
+ // Compare
+ /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', refImg, testImg, threshold);
+
+ if (!isOk) {
+ testFailedOptions('Image comparison failed', false);
+ } else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderBuiltinVarTests.PointCoordCase = function() {
+ tcuTestCase.DeqpTest.call(this, 'pointcoord', 'gl_PointCoord Test');
+ };
+
+ es3fShaderBuiltinVarTests.PointCoordCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.PointCoordCase.prototype.constructor = es3fShaderBuiltinVarTests.PointCoordCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderBuiltinVarTests.PointCoordCase.prototype.iterate = function() {
+ /** @type {number} */ var width = Math.min(256, gl.drawingBufferWidth);
+ /** @type {number} */ var height = Math.min(256, gl.drawingBufferHeight);
+ /** @type {number} */ var threshold = 0.02;
+
+ /** @type {number} */ var numPoints = 8;
+
+ /** @type {Array<number>} */ var coords = [];
+ /** @type {Array<number>} */ var pointSizeRange = [0.0, 0.0];
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0x145fa);
+ /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
+
+ pointSizeRange = /** @type {Array<number>} */ (gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE));
+
+ if (pointSizeRange[0] <= 0.0 || pointSizeRange[1] <= 0.0 || pointSizeRange[1] < pointSizeRange[0])
+ throw new Error('Invalid gl.ALIASED_POINT_SIZE_RANGE');
+
+ // Compute coordinates.
+ for (var i = 0; i < numPoints; i++)
+ coords.push([
+ rnd.getFloat(-0.9, 0.9),
+ rnd.getFloat(-0.9, 0.9),
+ rnd.getFloat(pointSizeRange[0], pointSizeRange[1])
+ ]);
+
+ /** @type {string} */ var vtxSource = '#version 300 es\n' +
+ 'in highp vec3 a_positionSize;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(a_positionSize.xy, 0.0, 1.0);\n' +
+ ' gl_PointSize = a_positionSize.z;\n' +
+ '}\n';
+
+ /** @type {string} */ var fragSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = vec4(gl_PointCoord, 0.0, 1.0);\n' +
+ '}\n';
+
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ throw new Error('Compile failed');
+
+ // Draw with GL.
+ var newCoords = [].concat.apply([], coords);
+
+ // /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_positionSize', 3, coords.length, 0, coords);
+ /** @type {gluDrawUtil.VertexArrayBinding} */
+ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_positionSize', 3, coords.length, 12, newCoords);
+ /** @type {number} */ var viewportX = rnd.getInt(0, gl.drawingBufferWidth - width);
+ /** @type {number} */ var viewportY = rnd.getInt(0, gl.drawingBufferHeight - height);
+
+ gl.viewport(viewportX, viewportY, width, height);
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.useProgram(program.getProgram());
+
+ gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.pointsFromElements(coords.length));
+ testImg.readViewport(gl, [viewportX, viewportY, width, height]);
+
+ // Draw reference
+ refImg.getAccess().clear([0.0, 0.0, 0.0, 1.0]);
+ for (var i = 0; i < coords.length; i++) {
+ /** @type {number} */ var x0 = Math.round(width * (coords[i][0] * 0.5 + 0.5) - coords[i][2] * 0.5);
+ /** @type {number} */ var y0 = Math.round(height* (coords[i][1] * 0.5 + 0.5) - coords[i][2] * 0.5);
+ /** @type {number} */ var x1 = Math.round(width * (coords[i][0] * 0.5 + 0.5) + coords[i][2] * 0.5);
+ /** @type {number} */ var y1 = Math.round(height * (coords[i][1] * 0.5 + 0.5) + coords[i][2] * 0.5);
+ /** @type {number} */ var w = x1 - x0;
+ /** @type {number} */ var h = y1 - y0;
+
+ for (var yo = 0; yo < h; yo++) {
+ for (var xo = 0; xo < w; xo++) {
+ /** @type {number} */ var xf = (xo + 0.5) / w;
+ /** @type {number} */ var yf = ((h - yo - 1) + 0.5) / h;
+ /** @type {number} */ var dx = x0 + xo;
+ /** @type {number} */ var dy = y0 + yo;
+ /** @type {Array<number>} */
+ var color = [
+ deMath.clamp(Math.floor(xf * 255 + 0.5), 0, 255),
+ deMath.clamp(Math.floor(yf * 255 + 0.5), 0, 255),
+ 0,
+ 255];
+ if (deMath.deInBounds32(dx, 0, refImg.getWidth()) && deMath.deInBounds32(dy, 0, refImg.getHeight()))
+ refImg.setPixel(dx, dy, color);
+ }
+ }
+ }
+
+ // Compare
+ /** @type {boolean} */ var isOk = tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', refImg.getAccess(), testImg.getAccess(), threshold);
+
+ if (!isOk) {
+ testFailedOptions('Image comparison failed', false);
+ } else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderBuiltinVarTests.FrontFacingCase = function() {
+ tcuTestCase.DeqpTest.call(this, 'frontfacing', 'gl_FrontFacing Test');
+ };
+
+ es3fShaderBuiltinVarTests.FrontFacingCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.FrontFacingCase.prototype.constructor = es3fShaderBuiltinVarTests.FrontFacingCase;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderBuiltinVarTests.FrontFacingCase.prototype.iterate = function() {
+ // Test case renders two adjecent quads, where left is has front-facing
+ // triagles and right back-facing. Color is selected based on gl_FrontFacing
+ // value.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0x89f2c);
+ /** @type {number} */ var width = Math.min(64, gl.drawingBufferWidth);
+ /** @type {number} */ var height = Math.min(64, gl.drawingBufferHeight);
+ /** @type {number} */ var viewportX = rnd.getInt(0, gl.drawingBufferWidth - width);
+ /** @type {number} */ var viewportY = rnd.getInt(0, gl.drawingBufferHeight - height);
+ /** @type {Array<number>} */ var threshold = deMath.add([1, 1, 1, 1], tcuPixelFormat.PixelFormatFromContext(gl).getColorThreshold());
+
+ /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
+ /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
+
+ /** @type {string} */ var vtxSource = '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+
+ /** @type {string} */ var fragSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' if (gl_FrontFacing)\n' +
+ ' o_color = vec4(0.0, 1.0, 0.0, 1.0);\n' +
+ ' else\n' +
+ ' o_color = vec4(0.0, 0.0, 1.0, 1.0);\n' +
+ '}\n';
+
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
+
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ throw new Error('Compile failed');
+
+ // Draw with GL.
+ /** @type {Array<number>} */ var positions = [
+ -1.0, 1.0, 0.0, 1.0,
+ -1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0
+ ];
+
+ /** @type {Array<number>} */ var indicesCCW = [0, 1, 2, 2, 1, 3];
+ /** @type {Array<number>} */ var indicesCW = [2, 1, 0, 3, 1, 2];
+
+ /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions);
+
+ gl.useProgram(program.getProgram());
+
+ gl.viewport(viewportX, viewportY, Math.floor(width / 2), height);
+
+ gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indicesCCW));
+
+ gl.viewport(viewportX + Math.floor(width / 2), viewportY, width - Math.floor(width / 2), height);
+ gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indicesCW));
+ testImg.readViewport(gl, [viewportX, viewportY, width, height]);
+ // Draw reference
+ for (var y = 0; y < refImg.getHeight(); y++) {
+ for (var x = 0; x < Math.floor(refImg.getWidth() / 2); x++)
+ refImg.setPixel(x, y, tcuRGBA.RGBA.green.toIVec());
+
+ for (var x = Math.floor(refImg.getWidth() / 2); x < refImg.getWidth(); x++)
+ refImg.setPixel(x, y, tcuRGBA.RGBA.blue.toIVec());
+ }
+
+ // Compare
+ /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', refImg, testImg, threshold);
+
+ if (!isOk) {
+ testFailedOptions('Image comparison failed', false);
+ } else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderBuiltinVarTests.VertexIDCase = function() {
+ tcuTestCase.DeqpTest.call(this, 'vertex_id', 'gl_VertexID Test');
+ /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {WebGLBuffer} */ this.m_positionBuffer = null;
+ /** @type {WebGLBuffer} */ this.m_elementBuffer = null;
+ /** @type {number} */ this.m_viewportW = 0;
+ /** @type {number} */ this.m_viewportH = 0;
+ /** @type {number} */ this.m_iterNdx = 0;
+ /** @type {Array<Array<number>>} */ this.m_positions = [];
+ /** @type {Array<Array<number>>} */ this.m_colors = [];
+ };
+
+ es3fShaderBuiltinVarTests.VertexIDCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.VertexIDCase.prototype.constructor = es3fShaderBuiltinVarTests.VertexIDCase;
+
+ es3fShaderBuiltinVarTests.VertexIDCase.MAX_VERTICES = 24; //!< 8 triangles, totals 24 vertices
+
+ es3fShaderBuiltinVarTests.VertexIDCase.prototype.init = function() {
+ /** @type {number} */ var width = gl.drawingBufferWidth;
+ /** @type {number} */ var height = gl.drawingBufferHeight;
+
+ /** @type {number} */ var quadWidth = 32;
+ /** @type {number} */ var quadHeight = 32;
+
+ if (width < quadWidth)
+ throw new Error('Too small render target');
+
+ /** @type {number} */ var maxQuadsX = Math.floor(width / quadWidth);
+ /** @type {number} */ var numVertices = es3fShaderBuiltinVarTests.VertexIDCase.MAX_VERTICES;
+
+ /** @type {number} */ var numQuads = Math.floor(numVertices / 6) + (numVertices % 6 != 0 ? 1 : 0);
+ /** @type {number} */ var viewportW = Math.min(numQuads, maxQuadsX)*quadWidth;
+ /** @type {number} */ var viewportH = (Math.floor(numQuads/maxQuadsX) + (numQuads % maxQuadsX != 0 ? 1 : 0)) * quadHeight;
+
+ if (viewportH > height)
+ throw new Error('Too small render target');
+
+ assertMsgOptions(viewportW <= width && viewportH <= height, 'Unexpected viewport dimensions.', false, true);
+
+ assertMsgOptions(!this.m_program, 'Program should not be defined at this point.', false, true);
+
+ /** @type {string} */ var vtxSource = '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'out mediump vec4 v_color;\n' +
+ 'uniform highp vec4 u_colors[24];\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_color = u_colors[gl_VertexID];\n' +
+ '}\n';
+
+ /** @type {string} */ var fragSource = '#version 300 es\n' +
+ 'in mediump vec4 v_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = v_color;\n' +
+ '}\n';
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
+ bufferedLogToConsole(this.m_program.getProgramInfo().infoLog);
+
+ if (!this.m_program.isOk()) {
+ this.m_program = null;
+ throw new Error('Compile failed');
+ }
+
+ this.m_positionBuffer = gl.createBuffer();
+ this.m_elementBuffer = gl.createBuffer();
+
+ // Set colors (in dynamic memory to save static data space).
+ this.m_colors[0] = [0.0, 0.0, 0.0, 1.0];
+ this.m_colors[1] = [0.5, 1.0, 0.5, 1.0];
+ this.m_colors[2] = [0.0, 0.5, 1.0, 1.0];
+ this.m_colors[3] = [0.0, 1.0, 0.0, 1.0];
+ this.m_colors[4] = [0.0, 1.0, 1.0, 1.0];
+ this.m_colors[5] = [0.5, 0.0, 0.0, 1.0];
+ this.m_colors[6] = [0.5, 0.0, 1.0, 1.0];
+ this.m_colors[7] = [0.5, 0.0, 0.5, 1.0];
+ this.m_colors[8] = [1.0, 0.0, 0.0, 1.0];
+ this.m_colors[9] = [0.5, 1.0, 0.0, 1.0];
+ this.m_colors[10] = [0.0, 0.5, 0.0, 1.0];
+ this.m_colors[11] = [0.5, 1.0, 1.0, 1.0];
+ this.m_colors[12] = [0.0, 0.0, 1.0, 1.0];
+ this.m_colors[13] = [1.0, 0.0, 0.5, 1.0];
+ this.m_colors[14] = [0.0, 0.5, 0.5, 1.0];
+ this.m_colors[15] = [1.0, 1.0, 0.5, 1.0];
+ this.m_colors[16] = [1.0, 0.0, 1.0, 1.0];
+ this.m_colors[17] = [1.0, 0.5, 0.0, 1.0];
+ this.m_colors[18] = [0.0, 1.0, 0.5, 1.0];
+ this.m_colors[19] = [1.0, 0.5, 1.0, 1.0];
+ this.m_colors[20] = [1.0, 1.0, 0.0, 1.0];
+ this.m_colors[21] = [1.0, 0.5, 0.5, 1.0];
+ this.m_colors[22] = [0.0, 0.0, 0.5, 1.0];
+ this.m_colors[23] = [1.0, 1.0, 1.0, 1.0];
+
+ // Compute positions.
+ assertMsgOptions(numVertices % 3 == 0, 'Number of vertices should be multiple of 3.', false, true);
+
+ for (var vtxNdx = 0; vtxNdx < numVertices; vtxNdx += 3) {
+ /** @type {number} */ var h = 2.0 * quadHeight / viewportH;
+ /** @type {number} */ var w = 2.0 * quadWidth / viewportW;
+
+ /** @type {number} */ var triNdx = Math.floor(vtxNdx / 3);
+ /** @type {number} */ var quadNdx = Math.floor(triNdx / 2);
+ /** @type {number} */ var quadY = Math.floor(quadNdx / maxQuadsX);
+ /** @type {number} */ var quadX = quadNdx % maxQuadsX;
+
+ /** @type {number} */ var x0 = -1.0 + quadX * w;
+ /** @type {number} */ var y0 = -1.0 + quadY * h;
+
+ if (triNdx % 2 === 0) {
+ this.m_positions[vtxNdx + 0] = [x0, y0, 0.0, 1.0];
+ this.m_positions[vtxNdx + 1] = [x0+w, y0+h, 0.0, 1.0];
+ this.m_positions[vtxNdx + 2] = [x0, y0+h, 0.0, 1.0];
+ } else {
+ this.m_positions[vtxNdx + 0] = [x0 + w, y0 + h, 0.0, 1.0];
+ this.m_positions[vtxNdx + 1] = [x0, y0, 0.0, 1.0];
+ this.m_positions[vtxNdx + 2] = [x0+w, y0, 0.0, 1.0];
+ }
+ }
+
+ this.m_viewportW = viewportW;
+ this.m_viewportH = viewportH;
+ this.m_iterNdx = 0;
+
+ };
+
+ es3fShaderBuiltinVarTests.VertexIDCase.prototype.deinit = function() {
+ this.m_program = null;
+
+ if (this.m_positionBuffer) {
+ gl.deleteBuffer(this.m_positionBuffer);
+ this.m_positionBuffer = null;
+ }
+
+ if (this.m_elementBuffer) {
+ gl.deleteBuffer(this.m_elementBuffer);
+ this.m_elementBuffer = null;
+ }
+
+ this.m_positions = [];
+ this.m_colors = [];
+ };
+
+ /**
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ */
+ es3fShaderBuiltinVarTests.VertexIDReferenceShader = function() {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var declaration = new sglrShaderProgram.ShaderProgramDeclaration();
+ declaration.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('', rrGenericVector.GenericVecType.FLOAT));
+ declaration.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('', rrGenericVector.GenericVecType.FLOAT));
+ declaration.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT, new sglrShaderProgram.VaryingFlags()));
+ declaration.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+ declaration.pushVertexSource(new sglrShaderProgram.VertexSource('')); // ShaderProgram fails if we don't push a source, even though GLSL source is not used
+ declaration.pushFragmentSource(new sglrShaderProgram.FragmentSource(''));
+ sglrShaderProgram.ShaderProgram.call(this, declaration);
+ };
+
+ es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype.constructor = es3fShaderBuiltinVarTests.VertexIDReferenceShader;
+
+ /** @const {number} */ es3fShaderBuiltinVarTests.VertexIDReferenceShader.VARYINGLOC_COLOR = 0;
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ */
+ es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype.shadeVertices = function(inputs, packets) {
+ for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) {
+ /** @type {number} */ var positionAttrLoc = 0;
+ /** @type {number} */ var colorAttrLoc = 1;
+
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ // Transform to position
+ packet.position = rrVertexAttrib.readVertexAttrib(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+
+ // Pass color to FS
+ packet.outputs[es3fShaderBuiltinVarTests.VertexIDReferenceShader.VARYINGLOC_COLOR] = rrVertexAttrib.readVertexAttrib(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packets
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype.shadeFragments = function(packets, context) {
+ for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) {
+ /** @type {rrFragmentOperations.Fragment} */ var packet = packets[packetNdx];
+ packet.value = rrShadingContext.readVarying(packet, context, es3fShaderBuiltinVarTests.VertexIDReferenceShader.VARYINGLOC_COLOR);
+ }
+ };
+
+ /**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ * @param {Array<number>} indices
+ * @param {goog.NumberArray} positions
+ * @param {goog.NumberArray} colors
+ */
+ es3fShaderBuiltinVarTests.VertexIDCase.prototype.renderReference = function(dst, indices, positions, colors) {
+ /** @type {rrRenderState.RenderState} */
+ var referenceState = new rrRenderState.RenderState(
+ new rrRenderState.ViewportState(rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(dst))
+ );
+
+ /** @type {rrRenderer.RenderTarget} */
+ var referenceTarget = new rrRenderer.RenderTarget(
+ rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(dst)
+ );
+
+ /** @type {es3fShaderBuiltinVarTests.VertexIDReferenceShader} */
+ var referenceShaderProgram = new es3fShaderBuiltinVarTests.VertexIDReferenceShader();
+
+ /** @type {Array<rrVertexAttrib.VertexAttrib>} */ var attribs = [];
+ attribs[0] = new rrVertexAttrib.VertexAttrib();
+ attribs[0].type = rrVertexAttrib.VertexAttribType.FLOAT;
+ attribs[0].size = 4;
+ attribs[0].stride = 0;
+ attribs[0].instanceDivisor = 0;
+ attribs[0].pointer = positions.buffer;
+
+ attribs[1] = new rrVertexAttrib.VertexAttrib();
+ attribs[1].type = rrVertexAttrib.VertexAttribType.FLOAT;
+ attribs[1].size = 4;
+ attribs[1].stride = 0;
+ attribs[1].instanceDivisor = 0;
+ attribs[1].pointer = colors.buffer;
+ rrRenderer.drawTriangles(referenceState, referenceTarget, referenceShaderProgram,
+ attribs, rrRenderer.PrimitiveType.TRIANGLES, 0, indices.length, /*instanceID = */ 0);
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderBuiltinVarTests.VertexIDCase.prototype.iterate = function() {
+ /** @type {number} */ var width = gl.drawingBufferWidth;
+ /** @type {number} */ var height = gl.drawingBufferHeight;
+ /** @type {number} */ var viewportW = this.m_viewportW;
+ /** @type {number} */ var viewportH = this.m_viewportH;
+
+ /** @type {number} */ var threshold = 0.02;
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xcf23ab1 ^ deString.deStringHash(this.m_iterNdx.toString()));
+ /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(viewportW, viewportH);
+ /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(viewportW, viewportH);
+
+ /** @type {number} */ var viewportX = rnd.getInt(0, width - viewportW);
+ /** @type {number} */ var viewportY = rnd.getInt(0, height - viewportH);
+
+ /** @type {number} */ var posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ /** @type {WebGLUniformLocation} */ var colorsLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_colors[0]');
+ /** @type {Array<number>} */ var clearColor = [0.0, 0.0, 0.0, 1.0];
+ /** @type {Array<number>} */ var indices = [];
+ /** @type {Array<Array<number>>} */ var mappedPos = [];
+ /** @type {goog.NumberArray} */ var flatColorArray;
+ /** @type {goog.NumberArray} */ var flatPosArray;
+ // Setup common state.
+ gl.viewport(viewportX, viewportY, viewportW, viewportH);
+ gl.useProgram(this.m_program.getProgram());
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuffer);
+ gl.enableVertexAttribArray(posLoc);
+ gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
+ gl.uniform4fv(colorsLoc, [].concat.apply([], this.m_colors));
+
+ // Clear render target to black.
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ refImg.getAccess().clear(clearColor);
+
+ if (this.m_iterNdx === 0) {
+ bufferedLogToConsole('Iter0: glDrawArrays()');
+
+ flatPosArray = new Float32Array([].concat.apply([], this.m_positions));
+ flatColorArray = new Float32Array([].concat.apply([], this.m_colors));
+ gl.bufferData(gl.ARRAY_BUFFER, flatPosArray.buffer, gl.DYNAMIC_DRAW);
+ gl.drawArrays(gl.TRIANGLES, 0, Math.floor(flatPosArray.length / 4));
+
+ //glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
+ testImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
+ // Reference indices
+ for (var ndx = 0; ndx < this.m_positions.length; ndx++)
+ indices.push(ndx);
+
+ this.renderReference(refImg.getAccess(), indices, flatPosArray, flatColorArray);
+ } else if (this.m_iterNdx === 1) {
+ bufferedLogToConsole('Iter1: glDrawElements(), indices in buffer');
+
+ // Compute initial indices and suffle
+ for (var ndx = 0; ndx < this.m_positions.length; ndx++)
+ indices.push(ndx);
+ // deRandom.shuffle(rnd, indices);
+ // \note [2015-08-05 dag] The original test shuffles the indices array but the reference renderer cannot handle triangles with sides not parallel to the axes.
+
+ // Use indices to re-map positions.
+ for (var ndx = 0; ndx < indices.length; ndx++)
+ mappedPos[indices[ndx]] = this.m_positions[ndx];
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_elementBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, (new Uint16Array(indices)).buffer, gl.DYNAMIC_DRAW);
+
+ flatPosArray = new Float32Array([].concat.apply([], mappedPos));
+ flatColorArray = new Float32Array([].concat.apply([], this.m_colors));
+ gl.bufferData(gl.ARRAY_BUFFER, flatPosArray.buffer, gl.DYNAMIC_DRAW);
+ gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
+
+ //glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
+ testImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
+ refImg.getAccess().clear(clearColor);
+ this.renderReference(refImg.getAccess(), indices, flatPosArray, flatColorArray);
+ } else
+ throw new Error('Iteration count exceeded.');
+
+ if (!tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', refImg.getAccess(), testImg.getAccess(), threshold))
+ testFailedOptions('Image comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ this.m_iterNdx += 1;
+ return (this.m_iterNdx < 2) ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderBuiltinVarTests.ShaderBuiltinVarTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'builtin_variable', 'Built-in Variable Tests');
+ };
+
+ es3fShaderBuiltinVarTests.ShaderBuiltinVarTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderBuiltinVarTests.ShaderBuiltinVarTests.prototype.constructor = es3fShaderBuiltinVarTests.ShaderBuiltinVarTests;
+
+ es3fShaderBuiltinVarTests.ShaderBuiltinVarTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ // Builtin constants.
+ /**
+ * @struct
+ * @constructor
+ * @param {string} caseName
+ * @param {string} varName
+ * @param {es3fShaderBuiltinVarTests.GetConstantValueFunc} getValue
+ */
+ var BuiltinConstant = function(caseName, varName, getValue) {
+ /** @type {string} */ this.caseName = caseName;
+ /** @type {string} */ this.varName = varName;
+ /** @type {es3fShaderBuiltinVarTests.GetConstantValueFunc} */ this.getValue = getValue;
+
+ };
+
+ /** @type {Array<BuiltinConstant>} */ var builtinConstants = [
+ // GLES 2.
+
+ new BuiltinConstant('max_vertex_attribs', 'gl_MaxVertexAttribs', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_VERTEX_ATTRIBS); }),
+ new BuiltinConstant('max_vertex_uniform_vectors', 'gl_MaxVertexUniformVectors', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_VERTEX_UNIFORM_VECTORS); }),
+ new BuiltinConstant('max_fragment_uniform_vectors', 'gl_MaxFragmentUniformVectors', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_FRAGMENT_UNIFORM_VECTORS); }),
+ new BuiltinConstant('max_texture_image_units', 'gl_MaxTextureImageUnits', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_TEXTURE_IMAGE_UNITS); }),
+ new BuiltinConstant('max_vertex_texture_image_units', 'gl_MaxVertexTextureImageUnits', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); }),
+ new BuiltinConstant('max_combined_texture_image_units', 'gl_MaxCombinedTextureImageUnits', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS); }),
+ new BuiltinConstant('max_draw_buffers', 'gl_MaxDrawBuffers', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_DRAW_BUFFERS); }),
+
+ // GLES 3.
+
+ new BuiltinConstant('max_vertex_output_vectors', 'gl_MaxVertexOutputVectors', function() { return es3fShaderBuiltinVarTests.getVectorsFromComps(gl.MAX_VERTEX_OUTPUT_COMPONENTS); }),
+ new BuiltinConstant('max_fragment_input_vectors', 'gl_MaxFragmentInputVectors', function() { return es3fShaderBuiltinVarTests.getVectorsFromComps(gl.MAX_FRAGMENT_INPUT_COMPONENTS); }),
+ new BuiltinConstant('min_program_texel_offset', 'gl_MinProgramTexelOffset', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MIN_PROGRAM_TEXEL_OFFSET); }),
+ new BuiltinConstant('max_program_texel_offset', 'gl_MaxProgramTexelOffset', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_PROGRAM_TEXEL_OFFSET); })
+ ];
+
+ for (var ndx = 0; ndx < builtinConstants.length; ndx++) {
+ /** @type {string} */ var caseName = builtinConstants[ndx].caseName;
+ /** @type {string} */ var varName = builtinConstants[ndx].varName;
+ /** @type {es3fShaderBuiltinVarTests.GetConstantValueFunc} */ var getValue = builtinConstants[ndx].getValue;
+
+ testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase(caseName + '_vertex', varName, varName, getValue, gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase(caseName + '_fragment', varName, varName, getValue, gluShaderProgram.shaderType.FRAGMENT));
+ }
+
+ testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderDepthRangeTest('depth_range_vertex', 'gl_DepthRange', true));
+ testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderDepthRangeTest('depth_range_fragment', 'gl_DepthRange', false));
+
+ // Vertex shader builtin variables.
+ testGroup.addChild(new es3fShaderBuiltinVarTests.VertexIDCase());
+ // \todo [2013-03-20 pyry] gl_InstanceID -- tested in instancing tests quite thoroughly.
+
+ // Fragment shader builtin variables.
+ testGroup.addChild(new es3fShaderBuiltinVarTests.FragCoordXYZCase());
+ testGroup.addChild(new es3fShaderBuiltinVarTests.FragCoordWCase());
+ testGroup.addChild(new es3fShaderBuiltinVarTests.PointCoordCase());
+ testGroup.addChild(new es3fShaderBuiltinVarTests.FrontFacingCase());
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderBuiltinVarTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderBuiltinVarTests.ShaderBuiltinVarTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderBuiltinVarTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderCommonFunctionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderCommonFunctionTests.js
new file mode 100644
index 0000000000..5c24c73f90
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderCommonFunctionTests.js
@@ -0,0 +1,1973 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderCommonFunctionTests');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+goog.require('modules.shared.glsShaderExecUtil');
+goog.scope(function() {
+ var es3fShaderCommonFunctionTests = functional.gles3.es3fShaderCommonFunctionTests;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
+
+ /** @typedef {function(new: es3fShaderCommonFunctionTests.CommonFunctionCase, gluShaderUtil.DataType, gluShaderUtil.precision, gluShaderProgram.shaderType)} */ es3fShaderCommonFunctionTests.TestClass;
+
+ /**
+ * @enum
+ */
+ es3fShaderCommonFunctionTests.Types = {
+ FLOAT: 0,
+ INT: 1,
+ UINT: 2
+ };
+
+ /**
+ * @param {Array<number>} values
+ */
+ es3fShaderCommonFunctionTests.vecToFloat16 = function(values) {
+ for (var ndx = 0; ndx < values.length; ndx++)
+ values[ndx] = tcuFloat.newFloat16(values[ndx]).getValue();
+ };
+
+ /**
+ * @param {es3fShaderCommonFunctionTests.Types} type
+ * @param {deRandom.Random} rnd
+ * @param {number} minValue
+ * @param {number} maxValue
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.randomScalar = function(type, rnd, minValue, maxValue) {
+ switch (type) {
+ case es3fShaderCommonFunctionTests.Types.FLOAT: return rnd.getFloat(minValue, maxValue);
+ case es3fShaderCommonFunctionTests.Types.INT: return rnd.getInt(minValue, maxValue);
+ case es3fShaderCommonFunctionTests.Types.UINT: return Math.abs(rnd.getInt(minValue, maxValue));
+ default: throw new Error('Only FLOAT, INT, and UINT are supported.');
+ }
+ };
+
+ /**
+ * @param {es3fShaderCommonFunctionTests.Types} type
+ * @param {Array<number>} size
+ * @param {deRandom.Random} rnd
+ * @param {Array<number>} minValue
+ * @param {Array<number>} maxValue
+ * @return {Array<number>}
+ */
+ es3fShaderCommonFunctionTests.randomVector = function(type, size, rnd, minValue, maxValue) {
+ /** @type {Array<number>} */ var res = [];
+ for (var ndx = 0; ndx < size; ndx++)
+ res.push(es3fShaderCommonFunctionTests.randomScalar(type, rnd, minValue[ndx], maxValue[ndx]));
+ return res;
+ };
+
+ /**
+ * @param {es3fShaderCommonFunctionTests.Types} type
+ * @param {Array<number>} size
+ * @param {deRandom.Random} rnd
+ * @param {Array<number>} minValue
+ * @param {Array<number>} maxValue
+ * @param {number} numValues
+ * @param {number=} offset
+ * @return {Array<Array<number>>}
+ */
+ es3fShaderCommonFunctionTests.fillRandomVectors = function(type, size, rnd, minValue, maxValue, numValues, offset) {
+ offset = offset === undefined ? 0 : offset;
+ /** @type {Array<Array<number>>} */ var access;
+ for (var ndx = 0; ndx < numValues; ndx++)
+ access[offset + ndx] = es3fShaderCommonFunctionTests.randomVector(type, size, rnd, minValue, maxValue);
+ return access;
+ };
+
+ /**
+ * @param {es3fShaderCommonFunctionTests.Types} type
+ * @param {deRandom.Random} rnd
+ * @param {number} minValue
+ * @param {number} maxValue
+ * @param {number} numValues
+ * @param {number=} offset
+ * @return {Array<number>}
+ */
+ es3fShaderCommonFunctionTests.fillRandomScalars = function(type, rnd, minValue, maxValue, numValues, offset) {
+ offset = offset === undefined ? 0 : offset;
+ /** @type {Array<number>} */ var access = [];
+ for (var ndx = 0; ndx < numValues; ndx++)
+ access[offset + ndx] = es3fShaderCommonFunctionTests.randomScalar(type, rnd, minValue, maxValue);
+ return access;
+ };
+
+ /**
+ * @param {number} input
+ * @param {number} output
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.numBitsLostInOp = function(input, output) {
+ /** @type {number} */ var inExp = tcuFloat.newFloat32(input).exponent();
+ /** @type {number} */ var outExp = tcuFloat.newFloat32(output).exponent();
+ return Math.max(0, inExp - outExp); // Lost due to mantissa shift.
+ };
+
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.getUlpDiff = function(a, b) {
+ /** @type {number} */ var aBits = tcuFloat.newFloat32(a).bits();
+ /** @type {number} */ var bBits = tcuFloat.newFloat32(b).bits();
+ return aBits > bBits ? aBits - bBits : bBits - aBits;
+ };
+
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign = function(a, b) {
+ if (tcuFloat.newFloat32(a).isZero())
+ return es3fShaderCommonFunctionTests.getUlpDiff(new tcuFloat.deFloat().construct(tcuFloat.newFloat32(b).sign(), 0, 0).getValue(), b);
+ else if (tcuFloat.newFloat32(b).isZero())
+ return es3fShaderCommonFunctionTests.getUlpDiff(a, new tcuFloat.deFloat().construct(tcuFloat.newFloat32(a).sign(), 0, 0).getValue());
+ else
+ return es3fShaderCommonFunctionTests.getUlpDiff(a, b);
+ };
+
+ /**
+ * @param {gluShaderUtil.precision} precision
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.supportsSignedZero = function(precision) {
+ // \note GLSL ES 3.0 doesn't really require support for -0, but we require it for highp
+ // as it is very widely supported.
+ return precision == gluShaderUtil.precision.PRECISION_HIGHP;
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} ulpDiff
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.getEpsFromMaxUlpDiff = function(value, ulpDiff) {
+ /** @type {number} */ var exp = tcuFloat.newFloat32(value).exponent();
+ return new tcuFloat.deFloat().construct(+1, exp, (1 << 23) | ulpDiff).getValue() - new tcuFloat.deFloat().construct(+1, exp, 1 << 23).getValue();
+ };
+
+ /**
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits = function(numAccurateBits) {
+ /** @type {number} */ var numGarbageBits = 23 - numAccurateBits;
+ /** @type {number} */ var mask = (1 << numGarbageBits) - 1;
+
+ return mask;
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.getEpsFromBits = function(value, numAccurateBits) {
+ return es3fShaderCommonFunctionTests.getEpsFromMaxUlpDiff(value, es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(numAccurateBits));
+ };
+
+ /**
+ * @param {gluShaderUtil.precision} precision
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.getMinMantissaBits = function(precision) {
+ /** @type {Array<number>} */ var bits = [
+ 7, // lowp
+ 10, // mediump
+ 23 // highp
+ ];
+
+ assertMsgOptions(deMath.deInBounds32(precision, 0, bits.length), 'Unexpected precision option.', false, true);
+ return bits[precision];
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.CommonFunctionCase = function(name, description, shaderType) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
+ /** @type {number} */ this.m_numValues = 100;
+ /** @type {glsShaderExecUtil.ShaderExecutor} */ this.m_executor = null;
+ /** @type {glsShaderExecUtil.ShaderSpec} */ this.m_spec = new glsShaderExecUtil.ShaderSpec();
+ this.m_spec.version = gluShaderUtil.GLSLVersion.V300_ES;
+ /** @type {string} */ this.m_failMsg; //!< Comparison failure help message.
+ };
+
+ es3fShaderCommonFunctionTests.CommonFunctionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.constructor = es3fShaderCommonFunctionTests.CommonFunctionCase;
+
+ es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.init = function() {
+ assertMsgOptions(!this.m_executor, 'Shader executor should be null at this point', false, true);
+ this.m_executor = glsShaderExecUtil.createExecutor(this.m_shaderType, this.m_spec);
+ if (!this.m_executor.isOk())
+ throw new Error('Compile failed');
+ };
+
+ es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.deinit = function() {
+ this.m_executor = null;
+ };
+
+ /**
+ * @param {Array<glsShaderExecUtil.Symbol>} symbols
+ * @return {Array<number>}
+ */
+ es3fShaderCommonFunctionTests.getScalarSizes = function(symbols) {
+ /** @type {Array<number>} */ var sizes = [];
+ for (var ndx = 0; ndx < symbols.length; ++ndx)
+ sizes.push(symbols[ndx].varType.getScalarSize());
+ return sizes;
+ };
+
+ /**
+ * @param {Array<glsShaderExecUtil.Symbol>} symbols
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.computeTotalScalarSize = function(symbols) {
+ /** @type {number} */ var totalSize = 0;
+ for (var sym in symbols)
+ totalSize += symbols[sym].varType.getScalarSize();
+ return totalSize;
+ };
+
+ /**
+ * @param {boolean} value
+ * @return {string}
+ */
+ es3fShaderCommonFunctionTests.ToBoolString = function(value) {
+ return value ? "true" : "false";
+ };
+
+ /**
+ * @param {gluVarType.VarType} varType
+ * @param {Array<*>} values
+ * @return {string}
+ */
+ es3fShaderCommonFunctionTests.VarValue = function(varType, values) {
+ /** @type {gluShaderUtil.DataType} */ var basicType = varType.getBasicType();
+ /** @type {gluShaderUtil.DataType} */ var scalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(basicType);
+ /** @type {number} */ var numComponents = gluShaderUtil.getDataTypeScalarSize(basicType);
+ /** @type {string} */ var outputStr = "";
+
+ if (numComponents > 1) {
+ outputStr += gluShaderUtil.getDataTypeName(basicType) + "(";
+ }
+
+ for (var compNdx = 0; compNdx < numComponents; ++compNdx) {
+ if (compNdx != 0) {
+ outputStr += ", ";
+ }
+
+ // tcu::toHex() is all commented out in this project.
+ // e.g. Line 199 of es3fShaderPackingFunctionTests.js
+ switch (scalarType) {
+ case gluShaderUtil.DataType.FLOAT:
+ case gluShaderUtil.DataType.INT:
+ case gluShaderUtil.DataType.UINT:
+ outputStr += values[compNdx];
+ break;
+ case gluShaderUtil.DataType.BOOL:
+ outputStr += es3fShaderCommonFunctionTests.ToBoolString(values[compNdx]);
+ break;
+
+ default:
+ throw Error('Unrecognized dataType ' + scalarType);
+ }
+ }
+
+ if (numComponents > 1) {
+ outputStr += ")";
+ }
+
+ return outputStr;
+ }
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.iterate = function() {
+ /** @type {number} */ var numInputScalars = es3fShaderCommonFunctionTests.computeTotalScalarSize(this.m_spec.inputs);
+ /** @type {number} */ var numOutputScalars = es3fShaderCommonFunctionTests.computeTotalScalarSize(this.m_spec.outputs);
+ /** @type {Array<goog.TypedArray>} */ var inputData = [];
+ /** @type {Array<goog.TypedArray>} */ var outputData = [];
+ /** @type {gluShaderUtil.DataType} */ var inputType = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.DataType} */ var outputType = this.m_spec.outputs[0].varType.getBasicType();
+ /** @type {Array<Array<number>>} */ var inputValues;
+ /** @type {ArrayBuffer} */ var outputValues;
+ inputValues = this.getInputValues(this.m_numValues);
+
+ for (var inNdx = 0; inNdx < inputValues.length; inNdx++) {
+ var data = inputType >= gluShaderUtil.DataType.FLOAT && inputType <= gluShaderUtil.DataType.FLOAT_VEC4 ? new Float32Array(inputValues[inNdx]) :
+ inputType >= gluShaderUtil.DataType.INT && inputType <= gluShaderUtil.DataType.INT_VEC4 ? new Int32Array(inputValues[inNdx]) :
+ inputType >= gluShaderUtil.DataType.UINT && inputType <= gluShaderUtil.DataType.UINT_VEC4 ? new Uint32Array(inputValues[inNdx]) :
+ null;
+ inputData.push(data);
+ }
+
+ // Execute shader.
+ this.m_executor.useProgram();
+ outputValues = this.m_executor.execute(this.m_numValues, inputData);
+ for (var outNdx = 0; outNdx < outputValues.length; outNdx++) {
+ var data = outputType >= gluShaderUtil.DataType.FLOAT && outputType <= gluShaderUtil.DataType.FLOAT_VEC4 ? new Float32Array(outputValues[outNdx].buffer) :
+ outputType >= gluShaderUtil.DataType.INT && outputType <= gluShaderUtil.DataType.INT_VEC4 ? new Int32Array(outputValues[outNdx].buffer) :
+ outputType >= gluShaderUtil.DataType.UINT && outputType <= gluShaderUtil.DataType.UINT_VEC4 ? new Uint32Array(outputValues[outNdx].buffer) :
+ outputType >= gluShaderUtil.DataType.BOOL && outputType <= gluShaderUtil.DataType.BOOL_VEC4 ? new Int32Array(outputValues[outNdx].buffer) :
+ null;
+ outputData.push(data);
+ }
+
+ // TODO: verify proper TypedArray for BOOL types; defaulting to Int32Array in the mean time (outputValues returns 400 bytes, we need 100 elements)
+ // Compare results.
+ /** @type {Array<number>} */ var inScalarSizes = es3fShaderCommonFunctionTests.getScalarSizes(this.m_spec.inputs);
+ /** @type {Array<number>} */ var outScalarSizes = es3fShaderCommonFunctionTests.getScalarSizes(this.m_spec.outputs);
+ /** @type {Array<*>} */ var curInputPtr = [];
+ /** @type {Array<*>} */ var curOutputPtr = [];
+ /** @type {number} */ var numFailed = 0;
+
+ for (var inNdx = 0; inNdx < inputData.length; inNdx++) {
+ curInputPtr[inNdx] = [];
+ for (var valNdx = 0; valNdx < inputData[inNdx].length; valNdx += inScalarSizes[inNdx])
+ curInputPtr[inNdx].push(inputData[inNdx].slice(valNdx, valNdx + inScalarSizes[inNdx]));
+ }
+
+ for (var outNdx = 0; outNdx < outputData.length; outNdx++) {
+ curOutputPtr[outNdx] = [];
+ for (var valNdx = 0; valNdx < outputData[outNdx].length; valNdx += outScalarSizes[outNdx])
+ curOutputPtr[outNdx].push(outputData[outNdx].slice(valNdx, valNdx + outScalarSizes[outNdx]));
+ }
+
+ this.m_failMsg = '';
+ for (var valNdx = 0; valNdx < this.m_numValues; valNdx++) {
+ var curInputValues = [];
+ var curOutputValues = [];
+ for (var inNdx = 0; inNdx < inputData.length; inNdx++) {
+ curInputValues.push(curInputPtr[inNdx][valNdx]);
+ }
+ for (var outNdx = 0; outNdx < outputData.length; outNdx++) {
+ curOutputValues.push(curOutputPtr[outNdx][valNdx]);
+ }
+ if (!this.compare(curInputValues, curOutputValues)) {
+ // \todo [2013-08-08 pyry] We probably want to log reference value as well?
+
+ bufferedLogToConsole('ERROR: comparison failed for value ' + valNdx + ':\n ' + this.m_failMsg);
+ bufferedLogToConsole(' inputs:');
+ for (var inNdx = 0; inNdx < inputData.length; ++inNdx) {
+ var varValue = es3fShaderCommonFunctionTests.VarValue(this.m_spec.inputs[0].varType, curInputValues[inNdx]);
+ bufferedLogToConsole(' ' + this.m_spec.inputs[inNdx].name + ' = ' + varValue);
+ }
+
+ bufferedLogToConsole(' outputs:');
+ for (var outNdx = 0; outNdx < outputData.length; ++outNdx) {
+ var varValue = es3fShaderCommonFunctionTests.VarValue(this.m_spec.inputs[0].varType, curOutputValues[outNdx]);
+ bufferedLogToConsole(' ' + this.m_spec.outputs[outNdx].name + ' = ' + varValue);
+ }
+
+ this.m_failMsg = '';
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((this.m_numValues - numFailed) + ' / ' + this.m_numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {gluShaderUtil.precision} precision
+ * @return {string}
+ */
+ es3fShaderCommonFunctionTests.getPrecisionPostfix = function(precision) {
+ /** @type {Array<string>} */ var s_postfix = [
+ '_lowp',
+ '_mediump',
+ '_highp'
+ ];
+ assertMsgOptions(0 <= precision && precision < s_postfix.length, 'Error: Out of range', false, true);
+ return s_postfix[precision];
+ };
+
+ /**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {string}
+ */
+ es3fShaderCommonFunctionTests.getShaderTypePostfix = function(shaderType) {
+ /** @type {Array<string>} */ var s_postfix = [
+ '_vertex',
+ '_fragment'
+ ];
+ assertMsgOptions(0 <= shaderType && shaderType < s_postfix.length, 'Error Out of range', false, true);
+ return s_postfix[shaderType];
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {string}
+ */
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName = function(baseType, precision, shaderType) {
+ return gluShaderUtil.getDataTypeName(baseType) +
+ es3fShaderCommonFunctionTests.getPrecisionPostfix(precision) +
+ es3fShaderCommonFunctionTests.getShaderTypePostfix(shaderType);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.AbsCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'abs', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = abs(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.AbsCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.AbsCase.prototype.constructor = es3fShaderCommonFunctionTests.AbsCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.AbsCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var floatRanges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {Array<Array<number>>} */ var intRanges = [
+ [-(1 << 7) + 1, (1 << 7) - 1],
+ [-(1 << 15) + 1, (1 << 15) - 1],
+ [-0x80000000 + 1, 0x7fffffff]
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x235fac);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(type))
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, floatRanges[precision][0], floatRanges[precision][1], numValues * scalarSize);
+ else
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.INT, rnd, intRanges[precision][0], intRanges[precision][1], numValues * scalarSize);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.AbsCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref0;
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(type)) {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = (1 << (23 - mantissaBits)) - 1;
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref0 = Math.abs(in0);
+ /** @type {number} */ var ulpDiff0 = es3fShaderCommonFunctionTests.getUlpDiff(out0, ref0);
+
+ if (ulpDiff0 > maxUlpDiff) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0 /*HexFloat(ref0)*/ + ' with ULP threshold ' + maxUlpDiff + ', got ULP diff ' + ulpDiff0;
+ return false;
+ }
+ }
+ } else
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref0 = Math.abs(in0);
+
+ if (out0 != ref0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0;
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.SignCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'sign', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = sign(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.SignCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.SignCase.prototype.constructor = es3fShaderCommonFunctionTests.SignCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.SignCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var floatRanges = [
+ [-2.0, 2.0], // lowp
+ [-1e4, 1e4], // mediump
+ [-1e8, 1e8] // highp
+ ];
+
+ /** @type {Array<Array<number>>} */ var intRanges = [
+ [-(1 << 7), (1 << 7) - 1],
+ [-(1 << 15), (1 << 15) - 1],
+ [0x80000000, 0x7fffffff]
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x324);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(type)) {
+ // Special cases.
+ // [dag] The special cases are 1, -1, and 0
+ var specialCases = [1.0, -1.0, 0.0];
+ for (var caseNdx = 0; caseNdx < specialCases.length; caseNdx++)
+ for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
+ values[0].push(specialCases[caseNdx]);
+ }
+ values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, floatRanges[precision][0], floatRanges[precision][1], (numValues - 3) * scalarSize));
+ } else {
+ var specialCases = [1, -1, 0];
+ for (var caseNdx = 0; caseNdx < specialCases.length; caseNdx++)
+ for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
+ values[0].push(specialCases[caseNdx]);
+ }
+ values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.INT, rnd, intRanges[precision][0], intRanges[precision][1], (numValues - 3) * scalarSize));
+ }
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.SignCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref0;
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(type)) {
+ // Both highp and mediump should be able to represent -1, 0, and +1 exactly
+ /** @type {number} */ var maxUlpDiff = precision === gluShaderUtil.precision.PRECISION_LOWP ?
+ es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(es3fShaderCommonFunctionTests.getMinMantissaBits(precision)) :
+ 0;
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref0 = in0 < 0.0 ? -1.0 :
+ in0 > 0.0 ? 1.0 : 0.0;
+ /** @type {number} */ var ulpDiff0 = es3fShaderCommonFunctionTests.getUlpDiff(out0, ref0);
+
+ if (ulpDiff0 > maxUlpDiff) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0 /*HexFloat(ref0)*/ + ' with ULP threshold ' + maxUlpDiff + ', got ULP diff ' + ulpDiff0;
+ return false;
+ }
+ }
+ } else {
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref0 = in0 < 0 ? -1 :
+ in0 > 0 ? 1 : 0;
+
+ if (out0 != ref0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @param {number} v
+ * @return {number}
+ */
+ es3fShaderCommonFunctionTests.roundEven = function(v) {
+ /** @type {number} */ var q = deMath.deFloatFrac(v);
+ /** @type {number} */ var truncated = Math.trunc(v - q);
+ /** @type {number} */ var rounded = (q > 0.5) ? (truncated + 1) : // Rounded up
+ (q == 0.5 && (truncated % 2 != 0)) ? (truncated + 1) : // Round to nearest even at 0.5
+ truncated; // Rounded down
+ return rounded;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.RoundEvenCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'roundEven', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = roundEven(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.RoundEvenCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.RoundEvenCase.prototype.constructor = es3fShaderCommonFunctionTests.RoundEvenCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.RoundEvenCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var numSpecialCases = 0;
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+ // Special cases.
+ if (precision !== gluShaderUtil.precision.PRECISION_LOWP) {
+ assertMsgOptions(numValues >= 20, 'numValues should be greater or equal than 20', false, true);
+ for (var ndx = 0; ndx < 20; ndx++) {
+ /** @type {number} */ var v = deMath.clamp(ndx - 10.5, ranges[precision][0], ranges[precision][1]);
+ for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
+ values[0].push(v);
+ }
+ numSpecialCases += 1;
+ }
+ }
+
+ // Random cases.
+ values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - numSpecialCases) * scalarSize));
+
+ // If precision is mediump, make sure values can be represented in fp16 exactly
+ if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
+ es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.RoundEvenCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+
+ if (precision == gluShaderUtil.precision.PRECISION_HIGHP || precision == gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ // Require exact rounding result.
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {number} */ var ref = es3fShaderCommonFunctionTests.roundEven(in0);
+
+ /** @type {number} */ var ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
+
+ if (ulpDiff > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ } else {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
+ /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {number} */ var minRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 - eps));
+ /** @type {number} */ var maxRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 + eps));
+ /** @type {boolean} */ var anyOk = false;
+
+ for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
+
+ if (ulpDiff <= maxUlpDiff) {
+ anyOk = true;
+ break;
+ }
+ }
+
+ if (!anyOk) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.ModfCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'modf', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out1', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = modf(in0, out1);';
+ };
+
+ es3fShaderCommonFunctionTests.ModfCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.ModfCase.prototype.constructor = es3fShaderCommonFunctionTests.ModfCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.ModfCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.ModfCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var out1;
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ out1 = outputs[1][compNdx];
+
+ /** @type {number} */ var refOut1 = Math.floor(in0);
+ /** @type {number} */ var refOut0 = in0 - refOut1;
+
+ /** @type {number} */ var bitsLost = precision != gluShaderUtil.precision.PRECISION_HIGHP ? es3fShaderCommonFunctionTests.numBitsLostInOp(in0, refOut0) : 0;
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(Math.max(mantissaBits - bitsLost, 0));
+
+ /** @type {number} */ var resSum = out0 + out1;
+
+ /** @type {number} */ var ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(resSum, in0) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(resSum, in0);
+
+ if (ulpDiff > maxUlpDiff) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = (' + refOut0 + ') + (' + refOut1 + ') = ' + in0 + ' with ULP threshold ' +
+ maxUlpDiff + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.IsnanCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'isnan', shaderType);
+ assertMsgOptions(gluShaderUtil.isDataTypeFloatOrVec(baseType), 'Assert error.', false, true);
+
+ /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
+ /** @type {gluShaderUtil.DataType} */ var boolType = vecSize > 1 ?
+ gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.BOOL, vecSize) :
+ gluShaderUtil.DataType.BOOL;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(boolType)));
+ this.m_spec.source = 'out0 = isnan(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.IsnanCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.IsnanCase.prototype.constructor = es3fShaderCommonFunctionTests.IsnanCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.IsnanCase.prototype.getInputValues = function(numValues) {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xc2a39f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var mantissaMask = (~es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits)) & ((1 << 23) - 1);
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+
+ for (var valNdx = 0; valNdx < numValues * scalarSize; valNdx++) {
+ /** @type {boolean} */ var isNan = rnd.getFloat() > 0.3;
+ /** @type {boolean} */ var isInf = !isNan && rnd.getFloat() > 0.4;
+ /** @type {number} */ var mantissa = !isInf ? ((1 << 22) | (Math.abs(rnd.getInt()) & mantissaMask)) : 0;
+ /** @type {number} */ var exp = !isNan && !isInf ? (Math.abs(rnd.getInt()) & 0x7f) : 0xff;
+ /** @type {number} */ var sign = Math.abs(rnd.getInt()) & 0x1;
+ /** @type {number} */ var value = (sign << 31) | (exp << 23) | mantissa;
+
+ // Convert int to float.
+ var view = new DataView(new ArrayBuffer(4));
+ view.setInt32(0, value, true);
+ value = view.getFloat32(0, true);
+
+ assertMsgOptions(tcuFloat.newFloat32(value).isInf() === isInf && tcuFloat.newFloat32(value).isNaN() === isNan, 'Assert error.', false, true);
+
+ values[0].push(value);
+ }
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.IsnanCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP) {
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref = tcuFloat.newFloat32(in0).isNaN() ? 1 : 0;
+
+ if (out0 !== ref) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref;
+ return false;
+ }
+ }
+ } else {
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ out0 = outputs[0][compNdx];
+
+ if (out0 !== 0 && out0 !== 1) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = 0 / 1';
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.IsinfCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'isinf', shaderType);
+ assertMsgOptions(gluShaderUtil.isDataTypeFloatOrVec(baseType), 'Assert error.', false, true);
+
+ /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
+ /** @type {gluShaderUtil.DataType} */ var boolType = vecSize > 1 ?
+ gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.BOOL, vecSize) :
+ gluShaderUtil.DataType.BOOL;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(boolType)));
+ this.m_spec.source = 'out0 = isinf(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.IsinfCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.IsinfCase.prototype.constructor = es3fShaderCommonFunctionTests.IsinfCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.IsinfCase.prototype.getInputValues = function(numValues) {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xc2a39f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var mantissaMask = (~es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits)) & ((1 << 23) - 1);
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+
+ for (var valNdx = 0; valNdx < numValues * scalarSize; valNdx++) {
+ /** @type {boolean} */ var isInf = rnd.getFloat() > 0.3;
+ /** @type {boolean} */ var isNan = !isInf && rnd.getFloat() > 0.4;
+ /** @type {number} */ var mantissa = !isInf ? ((1 << 22) | (Math.abs(rnd.getInt()) & mantissaMask)) : 0;
+ /** @type {number} */ var exp = !isNan && !isInf ? (Math.abs(rnd.getInt()) & 0x7f) : 0xff;
+ /** @type {number} */ var sign = Math.abs(rnd.getInt()) & 0x1;
+ /** @type {number} */ var value = (sign << 31) | (exp << 23) | mantissa;
+
+ // Convert int to float.
+ var view = new DataView(new ArrayBuffer(4));
+ view.setInt32(0, value, true);
+ value = view.getFloat32(0, true);
+
+ assertMsgOptions(tcuFloat.newFloat32(value).isInf() === isInf && tcuFloat.newFloat32(value).isNaN() === isNan, 'Assert error.', false, true);
+
+ values[0].push(value);
+ }
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.IsinfCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP) {
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref = tcuFloat.newFloat32(in0).isInf() ? 1 : 0;
+
+ if (out0 !== ref) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref;
+ return false;
+ }
+ }
+ } else {
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ out0 = outputs[0][compNdx];
+
+ if (out0 !== 0 && out0 !== 1) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = 0 / 1';
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {boolean} outIsSigned
+ */
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase = function(baseType, precision, shaderType, outIsSigned) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ outIsSigned ? 'floatBitsToInt' : 'floatBitsToUint', shaderType);
+
+ /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
+ /** @type {gluShaderUtil.DataType} */ var intType = outIsSigned ?
+ (vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) : gluShaderUtil.DataType.INT) :
+ (vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.UINT, vecSize) : gluShaderUtil.DataType.UINT);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(intType, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = outIsSigned ? 'out0 = floatBitsToInt(in0);' : 'out0 = floatBitsToUint(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype.constructor = es3fShaderCommonFunctionTests.FloatBitsToUintIntCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype.getInputValues = function(numValues) {
+
+ /** @type {Array<number>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x2790a);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {Array<Array<number>>} */ var values = [];
+
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var refOut0;
+ /** @type {number} */ var ulpDiff;
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+
+ // Convert int to uint because ref out is in uint format.
+ var view = new DataView(new ArrayBuffer(4));
+ view.setInt32(0, out0, true);
+ out0 = view.getUint32(0, true);
+
+ refOut0 = tcuFloat.newFloat32(in0).bits();
+ ulpDiff = Math.abs(out0 - refOut0);
+ if (ulpDiff > maxUlpDiff) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + refOut0 + ' with threshold ' +
+ maxUlpDiff + ', got diff ' + ulpDiff;
+ return false;
+ }
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.FloatBitsToUintIntCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.FloatBitsToIntCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.call(this, baseType, precision, shaderType, true);
+ };
+
+ es3fShaderCommonFunctionTests.FloatBitsToIntCase.prototype = Object.create(es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype);
+ es3fShaderCommonFunctionTests.FloatBitsToIntCase.prototype.constructor = es3fShaderCommonFunctionTests.FloatBitsToIntCase;
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.FloatBitsToUintIntCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.FloatBitsToUintCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.call(this, baseType, precision, shaderType, false);
+ };
+
+ es3fShaderCommonFunctionTests.FloatBitsToUintCase.prototype = Object.create(es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype);
+ es3fShaderCommonFunctionTests.FloatBitsToUintCase.prototype.constructor = es3fShaderCommonFunctionTests.FloatBitsToUintCase;
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.BitsToFloatCase = function(baseType, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, gluShaderUtil.precision.PRECISION_HIGHP, shaderType),
+ gluShaderUtil.isDataTypeIntOrIVec(baseType) ? 'intBitsToFloat' : 'uintBitsToFloat', shaderType);
+ /** @type {boolean} */ var inIsSigned = gluShaderUtil.isDataTypeIntOrIVec(baseType);
+ /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
+ /** @type {gluShaderUtil.DataType} */ var floatType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(floatType, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = inIsSigned ? 'out0 = intBitsToFloat(in0);' : 'out0 = uintBitsToFloat(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.BitsToFloatCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.BitsToFloatCase.prototype.constructor = es3fShaderCommonFunctionTests.BitsToFloatCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.BitsToFloatCase.prototype.getInputValues = function(numValues) {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xbbb225);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {Array<number>} */ var range = [-1e8, 1e8];
+ /** @type {Array<Array<number>>} */ var values = [];
+
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, range[0], range[1], numValues * scalarSize);
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.BitsToFloatCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var maxUlpDiff = 0;
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ulpDiff;
+ /** @type {number} */ var refOut0;
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+
+ // Convert int to float
+ var view = new DataView(new ArrayBuffer(4));
+ view.setInt32(0, in0, true);
+ in0 = view.getFloat32(0, true);
+
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiff(in0, out0);
+ if (ulpDiff > maxUlpDiff) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + in0 + ' with ULP threshold ' +
+ maxUlpDiff + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.FloorCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'floor', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = floor(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.FloorCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.FloorCase.prototype.constructor = es3fShaderCommonFunctionTests.FloorCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.FloorCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {Array<Array<number>>} */ var values = [];
+ // Random cases.
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
+
+ // If precision is mediump, make sure values can be represented in fp16 exactly
+ if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
+ es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.FloorCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref;
+ /** @type {number} */ var ulpDiff;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ // Require exact result.
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref = Math.floor(in0);
+
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiff(out0, ref);
+
+ if (ulpDiff > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ } else {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
+ /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {number} */ var minRes = Math.floor(in0 - eps);
+ /** @type {number} */ var maxRes = Math.floor(in0 + eps);
+ /** @type {boolean} */ var anyOk = false;
+
+ for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiff(out0, roundedVal);
+
+ if (ulpDiff <= maxUlpDiff) {
+ anyOk = true;
+ break;
+ }
+ }
+
+ if (!anyOk) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.TruncCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'trunc', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = trunc(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.TruncCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.TruncCase.prototype.constructor = es3fShaderCommonFunctionTests.TruncCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.TruncCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {Array<number>} */ var specialCases = [0.0, -0.0, -0.9, 0.9, 1.0, -1.0];
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+
+ // Special cases
+ for (var caseNdx = 0; caseNdx < specialCases.length; caseNdx++)
+ for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
+ values[0].push(specialCases[caseNdx]);
+
+ // Random cases.
+ values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - specialCases.length) * scalarSize));
+
+ // If precision is mediump, make sure values can be represented in fp16 exactly
+ if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
+ es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.TruncCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref;
+ /** @type {number} */ var ulpDiff;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ // Require exact result.
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {boolean} */ var isNeg = tcuFloat.newFloat32(in0).sign() < 0;
+ ref = isNeg ? (-Math.floor(-in0)) : Math.floor(in0);
+
+ // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
+
+ if (ulpDiff > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ } else {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
+ /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {number} */ var minRes = Math.trunc(in0 - eps);
+ /** @type {number} */ var maxRes = Math.trunc(in0 + eps);
+ /** @type {boolean} */ var anyOk = false;
+
+ for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
+
+ if (ulpDiff <= maxUlpDiff) {
+ anyOk = true;
+ break;
+ }
+ }
+
+ if (!anyOk) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.RoundCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'round', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = round(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.RoundCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.RoundCase.prototype.constructor = es3fShaderCommonFunctionTests.RoundCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.RoundCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var numSpecialCases = 0;
+
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = []
+
+ // Special cases.
+ if (precision === gluShaderUtil.precision.PRECISION_LOWP) {
+ assertMsgOptions(numValues >= 10, 'Sample too small.', false, true);
+ for (var ndx = 0; ndx < 10; ndx++) {
+ /** @type {number} */ var v = deMath.clamp(ndx - 5.5, ranges[precision][0], ranges[precision][1]);
+ for (var iter = 1; iter <= scalarSize; iter++)
+ values[0].push(v);
+ numSpecialCases += 1;
+ }
+ }
+
+ // Random cases.
+ values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - numSpecialCases) * scalarSize));
+
+ // If precision is mediump, make sure values can be represented in fp16 exactly
+ if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
+ es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.RoundCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ulpDiff;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ // Require exact result.
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+
+ if ((in0 - Math.floor(in0)) === 0.5) {
+ /** @type {number} */ var ref0 = Math.floor(in0);
+ /** @type {number} */ var ref1 = Math.ceil(in0);
+ /** @type {number} */ var ulpDiff0 = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref0) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref0);
+ /** @type {number} */ var ulpDiff1 = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref1) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref1);
+ if (ulpDiff0 > 0 && ulpDiff1 > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0 + ' or ' + ref1 + ', got ULP diff ' + Math.min(ulpDiff0, ulpDiff1);
+ return false;
+ }
+ } else {
+ // Require exact result
+ /** @type {number} */ var ref = es3fShaderCommonFunctionTests.roundEven(in0);
+ ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
+
+ if (ulpDiff > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ }
+ } else {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
+ /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {number} */ var minRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 - eps));
+ /** @type {number} */ var maxRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 + eps));
+ /** @type {boolean} */ var anyOk = false;
+
+ for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
+
+ if (ulpDiff <= maxUlpDiff) {
+ anyOk = true;
+ break;
+ }
+ }
+
+ if (!anyOk) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.CeilCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'ceil', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = ceil(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.CeilCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.CeilCase.prototype.constructor = es3fShaderCommonFunctionTests.CeilCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.CeilCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {Array<Array<number>>} */ var values = [];
+
+ // Random cases.
+ values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
+
+ // If precision is mediump, make sure values can be represented in fp16 exactly
+ if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
+ es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.CeilCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref;
+ /** @type {number} */ var ulpDiff;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ // Require exact result.
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref = Math.ceil(in0);
+ ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
+
+ if (ulpDiff > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ } else {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
+ /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ /** @type {number} */ var minRes = Math.ceil(in0 - eps);
+ /** @type {number} */ var maxRes = Math.ceil(in0 + eps);
+ /** @type {boolean} */ var anyOk = false;
+
+ for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
+
+ if (ulpDiff <= maxUlpDiff) {
+ anyOk = true;
+ break;
+ }
+ }
+
+ if (!anyOk & deMath.deInRange32(0, minRes, maxRes)) {
+ ulpDiff = Math.abs(Math.floor(tcuFloat.newFloat32(out0).bits()) - 0x80000000);
+ anyOk = ulpDiff <= maxUlpDiff;
+ }
+
+ if (!anyOk) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
+ * @param {gluShaderUtil.DataType} baseType
+ * @param {gluShaderUtil.precision} precision
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderCommonFunctionTests.FractCase = function(baseType, precision, shaderType) {
+ es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
+ es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
+ 'fract', shaderType);
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
+ this.m_spec.source = 'out0 = fract(in0);';
+ };
+
+ es3fShaderCommonFunctionTests.FractCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
+ es3fShaderCommonFunctionTests.FractCase.prototype.constructor = es3fShaderCommonFunctionTests.FractCase;
+
+ /**
+ * @param {number} numValues
+ * @return {*}
+ */
+ es3fShaderCommonFunctionTests.FractCase.prototype.getInputValues = function(numValues) {
+ /** @type {Array<Array<number>>} */ var ranges = [
+ [-2.0, 2.0], // lowp
+ [-1e3, 1e3], // mediump
+ [-1e7, 1e7] // highp
+ ];
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
+
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */ var numSpecialCases = 0;
+
+ /** @type {Array<Array<number>>} */ var values = [];
+ values[0] = [];
+
+ // Special cases.
+ if (precision !== gluShaderUtil.precision.PRECISION_LOWP) {
+ assertMsgOptions(numValues >= 10, 'Sample too small.', false, true);
+ for (var ndx = 0; ndx < 10; ndx++) {
+ /** @type {number} */ var v = deMath.clamp(ndx - 5.5, ranges[precision][0], ranges[precision][1]);
+ for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
+ values[0].push(v);
+ }
+ numSpecialCases += 1;
+ }
+ }
+
+ // Random cases.
+ values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - numSpecialCases) * scalarSize));
+
+ // If precision is mediump, make sure values can be represented in fp16 exactly
+ if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
+ es3fShaderCommonFunctionTests.vecToFloat16(values[0])
+
+ return values;
+ };
+
+ /**
+ * @param {*} inputs
+ * @param {*} outputs
+ * @return {boolean}
+ */
+ es3fShaderCommonFunctionTests.FractCase.prototype.compare = function(inputs, outputs) {
+ /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
+ /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
+ /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {number} */ var in0;
+ /** @type {number} */ var out0;
+ /** @type {number} */ var ref;
+ /** @type {number} */ var ulpDiff;
+
+ if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ // Require exact result.
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+ ref = in0 - Math.floor(in0);
+ ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
+
+ if (ulpDiff > 0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
+ return false;
+ }
+ }
+ } else {
+ /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
+ /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
+
+ for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
+ in0 = inputs[0][compNdx];
+ out0 = outputs[0][compNdx];
+
+ if (Math.floor(in0 - eps) == Math.floor(in0 + eps)) {
+ ref = in0 - Math.floor(in0);
+ /** @type {number} */ var bitsLost = es3fShaderCommonFunctionTests.numBitsLostInOp(in0, ref);
+ /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(Math.max(0, mantissaBits - bitsLost)); // ULP diff for rounded integer value.
+ ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
+ if (ulpDiff > maxUlpDiff) {
+ this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ' with ULP threshold ' + maxUlpDiff + ', got diff ' + ulpDiff;
+ return false;
+ }
+ } else {
+ if (out0 >= 1.0) {
+ this.m_failMsg += 'Expected [' + compNdx + '] < 1.0';
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderCommonFunctionTests.ShaderCommonFunctionTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'common', 'Common function tests');
+ };
+
+ es3fShaderCommonFunctionTests.ShaderCommonFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderCommonFunctionTests.ShaderCommonFunctionTests.prototype.constructor = es3fShaderCommonFunctionTests.ShaderCommonFunctionTests;
+
+ /**
+ * @param {tcuTestCase.DeqpTest} parent
+ * @param {es3fShaderCommonFunctionTests.TestClass} testClass
+ * @param {string} functionName
+ * @param {boolean} floatTypes
+ * @param {boolean} intTypes
+ * @param {boolean} uintTypes
+ */
+ es3fShaderCommonFunctionTests.addFunctionCases = function(parent, testClass, functionName, floatTypes, intTypes, uintTypes) {
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(functionName, functionName);
+ parent.addChild(group);
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var scalarTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.UINT
+ ];
+
+ for (var scalarTypeNdx = 0; scalarTypeNdx < scalarTypes.length; scalarTypeNdx++) {
+ /** @type {gluShaderUtil.DataType} */ var scalarType = scalarTypes[scalarTypeNdx];
+
+ if ((!floatTypes && scalarType == gluShaderUtil.DataType.FLOAT) ||
+ (!intTypes && scalarType == gluShaderUtil.DataType.INT) ||
+ (!uintTypes && scalarType == gluShaderUtil.DataType.UINT))
+ continue;
+
+ for (var vecSize = 1; vecSize <= 4; vecSize++)
+ for (var prec = gluShaderUtil.precision.PRECISION_LOWP; prec <= gluShaderUtil.precision.PRECISION_HIGHP; prec++)
+ for (var shaderType = gluShaderProgram.shaderType.VERTEX; shaderType <= gluShaderProgram.shaderType.FRAGMENT; shaderType++)
+ group.addChild(new testClass(/** @type {gluShaderUtil.DataType} */ (scalarType + vecSize - 1), prec, shaderType));
+ }
+ };
+
+ es3fShaderCommonFunctionTests.ShaderCommonFunctionTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.AbsCase, 'abs', true, true, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.SignCase, 'sign', true, true, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FloorCase, 'floor', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.TruncCase, 'trunc', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.RoundCase, 'round', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.RoundEvenCase, 'roundeven', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.CeilCase, 'ceil', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FractCase, 'fract', true, false, false);
+ // mod
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.ModfCase, 'modf', true, false, false);
+ // min, max, clamp, mix, step, smoothstep
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.IsnanCase, 'isnan', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.IsinfCase, 'isinf', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FloatBitsToIntCase, 'floatbitstoint', true, false, false);
+ es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FloatBitsToUintCase, 'floatbitstouint', true, false, false);
+
+ // (u)intBitsToFloat()
+ /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('intbitstofloat', 'intBitsToFloat() Tests');
+ /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('uintbitstofloat', 'uintBitsToFloat() Tests');
+
+ testGroup.addChild(intGroup);
+ testGroup.addChild(uintGroup);
+
+ /** @type {Array<gluShaderProgram.shaderType>} */ var shaderTypes = [
+ gluShaderProgram.shaderType.VERTEX,
+ gluShaderProgram.shaderType.FRAGMENT
+ ];
+
+ for (var vecSize = 1; vecSize < 4; vecSize++) {
+ /** @type {gluShaderUtil.DataType} */ var intType = vecSize > 1 ?
+ gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) :
+ gluShaderUtil.DataType.INT;
+
+ /** @type {gluShaderUtil.DataType} */ var uintType = vecSize > 1 ?
+ gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.UINT, vecSize) :
+ gluShaderUtil.DataType.UINT;
+
+ for (var shaderType in shaderTypes) {
+ intGroup.addChild(new es3fShaderCommonFunctionTests.BitsToFloatCase(intType, shaderTypes[shaderType]));
+ uintGroup.addChild(new es3fShaderCommonFunctionTests.BitsToFloatCase(uintType, shaderTypes[shaderType]));
+ }
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderCommonFunctionTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderCommonFunctionTests.ShaderCommonFunctionTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderCommonFunctionTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderDerivateTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderDerivateTests.js
new file mode 100644
index 0000000000..9c859c296f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderDerivateTests.js
@@ -0,0 +1,1696 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderDerivateTests');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluPixelTransfer');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.common.tcuInterval');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.common.tcuTestCase');
+goog.require('modules.shared.glsShaderRenderCase');
+
+goog.scope(function() {
+ var es3fShaderDerivateTests = functional.gles3.es3fShaderDerivateTests;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluPixelTransfer = framework.opengl.gluPixelTransfer;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var tcuInterval = framework.common.tcuInterval;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuStringTemplate = framework.common.tcuStringTemplate;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+
+ /** @const {number} */ es3fShaderDerivateTests.VIEWPORT_WIDTH = 167;
+ /** @const {number} */ es3fShaderDerivateTests.VIEWPORT_HEIGHT = 103;
+ /** @const {number} */ es3fShaderDerivateTests.FBO_WIDTH = 99;
+ /** @const {number} */ es3fShaderDerivateTests.FBO_HEIGHT = 133;
+ /** @const {number} */ es3fShaderDerivateTests.MAX_FAILED_MESSAGES = 10;
+ /** @const {number} */ es3fShaderDerivateTests.INTERPOLATION_LOST_BITS = 3; // number mantissa of bits allowed to be lost in varying interpolation
+ /**
+ * @enum {number}
+ */
+ es3fShaderDerivateTests.DerivateFunc = {
+ DFDX: 0,
+ DFDY: 1,
+ FWIDTH: 2
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fShaderDerivateTests.SurfaceType = {
+ DEFAULT_FRAMEBUFFER: 0,
+ UNORM_FBO: 1,
+ FLOAT_FBO: 2 // \note Uses RGBA32UI fbo actually, since FP rendertargets are not in core spec.
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fShaderDerivateTests.VerificationLogging = {
+ LOG_ALL: 0,
+ LOG_NOTHING: 1
+ };
+
+ /**
+ * @param {es3fShaderDerivateTests.DerivateFunc} func
+ * @return {string}
+ */
+ es3fShaderDerivateTests.getDerivateFuncName = function(func) {
+ switch (func) {
+ case es3fShaderDerivateTests.DerivateFunc.DFDX: return 'dFdx';
+ case es3fShaderDerivateTests.DerivateFunc.DFDY: return 'dFdy';
+ case es3fShaderDerivateTests.DerivateFunc.FWIDTH: return 'fwidth';
+ default: throw new Error('Derivate Func not supported.');
+ }
+ };
+
+ /**
+ * @param {es3fShaderDerivateTests.DerivateFunc} func
+ * @return {string}
+ */
+ es3fShaderDerivateTests.getDerivateFuncCaseName = function(func) {
+ switch (func) {
+ case es3fShaderDerivateTests.DerivateFunc.DFDX: return 'dfdx';
+ case es3fShaderDerivateTests.DerivateFunc.DFDY: return 'dfdy';
+ case es3fShaderDerivateTests.DerivateFunc.FWIDTH: return 'fwidth';
+ default: throw new Error('Derivate Func not supported.');
+ }
+ };
+
+ /**
+ * @param {?gluShaderUtil.DataType} type
+ * @return {Array<boolean>}
+ */
+ es3fShaderDerivateTests.getDerivateMask = function(type) {
+ switch (type) {
+ case gluShaderUtil.DataType.FLOAT: return [true, false, false, false];
+ case gluShaderUtil.DataType.FLOAT_VEC2: return [true, true, false, false];
+ case gluShaderUtil.DataType.FLOAT_VEC3: return [true, true, true, false];
+ case gluShaderUtil.DataType.FLOAT_VEC4: return [true, true, true, true];
+ default: throw new Error('Data Type not supported.');
+ }
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} surface
+ * @param {Array<number>} derivScale
+ * @param {Array<number>} derivBias
+ * @param {number} x
+ * @param {number} y
+ * @return {Array<number>}
+ */
+ es3fShaderDerivateTests.readDerivate = function(surface, derivScale, derivBias, x, y) {
+ return deMath.divide(deMath.subtract(surface.getPixel(x, y), derivBias), derivScale);
+ };
+
+ /**
+ * @param {Array<number>} v
+ * @return {Array<number>}
+ */
+ es3fShaderDerivateTests.getCompExpBits = function(v) {
+ return [tcuFloat.newFloat32(v[0]).exponentBits(),
+ tcuFloat.newFloat32(v[1]).exponentBits(),
+ tcuFloat.newFloat32(v[2]).exponentBits(),
+ tcuFloat.newFloat32(v[3]).exponentBits()];
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ es3fShaderDerivateTests.computeFloatingPointError = function(value, numAccurateBits) {
+ /** @type {number} */ var numGarbageBits = 23 - numAccurateBits;
+ /** @type {number} */ var mask = (1 << numGarbageBits) - 1 ;
+ /** @type {number} */ var exp = tcuFloat.newFloat32(value).exponent();
+
+ return (new tcuFloat.deFloat()).construct(1, exp, (1 << 23) | mask).getValue() - (new tcuFloat.deFloat()).construct(1, exp, 1 << 23).getValue();
+ };
+
+ /**
+ * @param {?gluShaderUtil.precision} precision
+ * @return {number}
+ */
+ es3fShaderDerivateTests.getNumMantissaBits = function(precision) {
+ switch (precision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP: return 23;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: return 10;
+ case gluShaderUtil.precision.PRECISION_LOWP: return 6;
+ default:
+ throw new Error('Precision not supported: ' + precision);
+ }
+ };
+
+ /**
+ * @param {?gluShaderUtil.precision} precision
+ * @return {number}
+ */
+ es3fShaderDerivateTests.getMinExponent = function(precision) {
+ switch (precision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP: return -126;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: return -14;
+ case gluShaderUtil.precision.PRECISION_LOWP: return -8;
+ default:
+ throw new Error('Precision not supported: ' + precision);
+ }
+ };
+
+ /**
+ * @param {number} exp
+ * @param {number} numMantissaBits
+ * @return {number}
+ */
+ es3fShaderDerivateTests.getSingleULPForExponent = function(exp, numMantissaBits) {
+ if (numMantissaBits > 0) {
+ assertMsgOptions(numMantissaBits <= 23, 'numMantissaBits must be less or equal than 23.', false, true);
+
+ /** @type {number} */ var ulpBitNdx = 23 - numMantissaBits;
+
+ return (new tcuFloat.deFloat()).construct(1, exp, (1 << 23) | (1 << ulpBitNdx)).getValue() - (new tcuFloat.deFloat()).construct(1, exp, 1 << 23).getValue();
+ } else {
+ assertMsgOptions(numMantissaBits === 0, 'numMantissaBits must equal to 0.', false, true);
+ return (new tcuFloat.deFloat()).construct(1, exp, (1 << 23)).getValue()
+ }
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} numMantissaBits
+ * @return {number}
+ */
+ es3fShaderDerivateTests.getSingleULPForValue = function(value, numMantissaBits) {
+ /** @type {number} */ var exp = (new tcuFloat.deFloat().deFloatNumber(value)).exponent();
+ return es3fShaderDerivateTests.getSingleULPForExponent(exp, numMantissaBits);
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} minExponent
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ es3fShaderDerivateTests.convertFloorFlushToZero = function(value, minExponent, numAccurateBits) {
+ if (value === 0.0) {
+ return 0.0;
+ } else {
+ /** @type {tcuFloat.deFloat} */ var inputFloat = new tcuFloat.deFloat().deFloatNumber(value);
+ /** @type {number} */ var numTruncatedBits = 23 - numAccurateBits;
+ /** @type {number} */ var truncMask = (1 << numTruncatedBits) - 1;
+
+ if (value > 0.0) {
+ if (value > 0.0 && (new tcuFloat.deFloat().deFloatNumber(value)).exponent() < minExponent) {
+ // flush to zero if possible
+ return 0.0;
+ } else {
+ // just mask away non-representable bits
+ return (new tcuFloat.deFloat()).construct(1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).getValue();
+ }
+ } else {
+ if (inputFloat.mantissa() & truncMask) {
+ // decrement one ulp if truncated bits are non-zero (i.e. if value is not representable)
+ return (new tcuFloat.deFloat()).construct(-1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).getValue() - es3fShaderDerivateTests.getSingleULPForExponent(inputFloat.exponent(), numAccurateBits);
+ } else {
+ // value is representable, no need to do anything
+ return value;
+ }
+ }
+ }
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} minExponent
+ * @param {number} numAccurateBits
+ * @return {number}
+ */
+ es3fShaderDerivateTests.convertCeilFlushToZero = function(value, minExponent, numAccurateBits) {
+ return -es3fShaderDerivateTests.convertFloorFlushToZero(-value, minExponent, numAccurateBits);
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} numUlps
+ * @param {number} numMantissaBits
+ * @return {number}
+ */
+ es3fShaderDerivateTests.addErrorUlp = function(value, numUlps, numMantissaBits) {
+ return value + numUlps * es3fShaderDerivateTests.getSingleULPForValue(value, numMantissaBits);
+ };
+
+ /**
+ * @param {?gluShaderUtil.precision} precision
+ * @param {Array<number>} valueMin
+ * @param {Array<number>} valueMax
+ * @param {Array<number>} expectedDerivate
+ * @return {Array<number>}
+ */
+ es3fShaderDerivateTests.getDerivateThreshold = function(precision, valueMin, valueMax, expectedDerivate) {
+ /** @type {number} */ var baseBits = es3fShaderDerivateTests.getNumMantissaBits(precision);
+ /** @type {Array<number>} */ var derivExp = es3fShaderDerivateTests.getCompExpBits(expectedDerivate);
+ /** @type {Array<number>} */ var maxValueExp = deMath.max(es3fShaderDerivateTests.getCompExpBits(valueMin), es3fShaderDerivateTests.getCompExpBits(valueMax));
+ /** @type {Array<number>} */ var numBitsLost = deMath.subtract(maxValueExp, deMath.min(maxValueExp, derivExp));
+ /** @type {Array<number>} */
+ var numAccurateBits = deMath.max(
+ deMath.addScalar(
+ deMath.subtract(
+ [baseBits, baseBits, baseBits, baseBits],
+ numBitsLost),
+ -es3fShaderDerivateTests.INTERPOLATION_LOST_BITS),
+ [0, 0, 0, 0]);
+
+ return [es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]),
+ es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]),
+ es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]),
+ es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[3], numAccurateBits[3])];
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {?gluShaderUtil.DataType} dataType
+ * @param {Array<number>} reference
+ * @param {Array<number>} threshold
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ * @param {es3fShaderDerivateTests.VerificationLogging=} logPolicy
+ * @return {boolean}
+ */
+ es3fShaderDerivateTests.verifyConstantDerivate = function(result, errorMask, dataType, reference, threshold, scale, bias, logPolicy) {
+ logPolicy = logPolicy === undefined ? es3fShaderDerivateTests.VerificationLogging.LOG_ALL : logPolicy;
+ /** @type {Array<boolean>} */ var mask = deMath.logicalNotBool(es3fShaderDerivateTests.getDerivateMask(dataType));
+ /** @type {number} */ var numFailedPixels = 0;
+
+ if (logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL)
+ bufferedLogToConsole('Expecting ' + reference + ' with threshold ' + threshold);
+
+ for (var y = 0; y < result.getHeight(); y++) {
+ for (var x = 0; x < result.getWidth(); x++) {
+ /** @type {Array<number>} */ var resDerivate = es3fShaderDerivateTests.readDerivate(result, scale, bias, x, y);
+ /** @type {boolean} */
+ var isOk = deMath.boolAll(
+ deMath.logicalOrBool(
+ deMath.lessThanEqual(
+ deMath.abs(deMath.subtract(reference, resDerivate)),
+ threshold),
+ mask));
+
+ if (!isOk) {
+ if (numFailedPixels < es3fShaderDerivateTests.MAX_FAILED_MESSAGES && logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL)
+ bufferedLogToConsole('FAIL: got ' + resDerivate + ', diff = ' + deMath.abs(deMath.subtract(reference, resDerivate)) + ', at x = ' + x + ', y = ' + y);
+ numFailedPixels += 1;
+ errorMask.setPixel(tcuRGBA.RGBA.red.toVec(), x, y);
+ }
+ }
+ }
+
+ if (numFailedPixels >= es3fShaderDerivateTests.MAX_FAILED_MESSAGES && logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL)
+ bufferedLogToConsole('...');
+
+ if (numFailedPixels > 0 && logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL)
+ bufferedLogToConsole('FAIL: found ' + numFailedPixels + ' failed pixels');
+
+ return numFailedPixels === 0;
+ };
+
+ /**
+ * .-----.
+ * | s_x |
+ * M x | s_y |
+ * | 1.0 |
+ * '-----'
+ * @struct
+ * @constructor
+ */
+ es3fShaderDerivateTests.Linear2DFunctionEvaluator = function() {
+ /** @type {tcuMatrix.Matrix} */ this.matrix = new tcuMatrix.Matrix(4, 3);
+ };
+
+ es3fShaderDerivateTests.Linear2DFunctionEvaluator.prototype.evaluateAt = function(screenX, screenY) {
+ /** @type {Array<number>} */ var position = [screenX, screenY, 1.0];
+ return tcuMatrix.multiplyMatVec(this.matrix, position);
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {?gluShaderUtil.DataType} dataType
+ * @param {?gluShaderUtil.precision} precision
+ * @param {Array<number>} derivScale
+ * @param {Array<number>} derivBias
+ * @param {Array<number>} surfaceThreshold
+ * @param {es3fShaderDerivateTests.DerivateFunc} derivateFunc
+ * @param {es3fShaderDerivateTests.Linear2DFunctionEvaluator} func
+ * @return {boolean}
+ */
+ es3fShaderDerivateTests.reverifyConstantDerivateWithFlushRelaxations = function(result, errorMask, dataType, precision, derivScale, derivBias, surfaceThreshold, derivateFunc, func) {
+ assertMsgOptions(result.getWidth() === errorMask.getWidth(), 'Dimensions of result and errorMask inconsistent.', false, true);
+ assertMsgOptions(result.getHeight() === errorMask.getHeight(), 'Dimensions of result and errorMask inconsistent.', false, true);
+ assertMsgOptions(derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX || derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDY, 'Derivate Function should be DFDX or DFDY.', false, true);
+
+ /** @type {Array<number>} */ var red = [255, 0, 0, 255];
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ /** @type {number} */ var divisionErrorUlps = 2.5;
+
+ /** @type {number} */ var numComponents = gluShaderUtil.getDataTypeScalarTypeAsDataType(dataType);
+ /** @type {number} */ var numBits = es3fShaderDerivateTests.getNumMantissaBits(precision);
+ /** @type {number} */ var minExponent = es3fShaderDerivateTests.getMinExponent(precision);
+
+ /** @type {number} */ var numVaryingSampleBits = numBits - es3fShaderDerivateTests.INTERPOLATION_LOST_BITS;
+ /** @type {number} */ var numFailedPixels = 0;
+
+ errorMask.clear(green);
+
+ // search for failed pixels
+ for (var y = 0; y < result.getHeight(); ++y)
+ for (var x = 0; x < result.getWidth(); ++x) {
+ // flushToZero?(f2z?(functionValueCurrent) - f2z?(functionValueBefore))
+ // flushToZero? ( ------------------------------------------------------------------------ +- 2.5 ULP )
+ // dx
+
+ /** @type {Array<number>} */ var resultDerivative = es3fShaderDerivateTests.readDerivate(result, derivScale, derivBias, x, y);
+
+ // sample at the front of the back pixel and the back of the front pixel to cover the whole area of
+ // legal sample positions. In general case this is NOT OK, but we know that the target funtion is
+ // (mostly*) linear which allows us to take the sample points at arbitrary points. This gets us the
+ // maximum difference possible in exponents which are used in error bound calculations.
+ // * non-linearity may happen around zero or with very high function values due to subnorms not
+ // behaving well.
+ /** @type {Array<number>} */ var functionValueForward = (derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX) ?
+ (func.evaluateAt(x + 2.0, y + 0.5)) :
+ (func.evaluateAt(x + 0.5, y + 2.0));
+ /** @type {Array<number>} */ var functionValueBackward = (derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX) ?
+ (func.evaluateAt(x - 1.0, y + 0.5)) :
+ (func.evaluateAt(x + 0.5, y - 1.0));
+
+ /** @type {boolean} */ var anyComponentFailed = false;
+
+ // check components separately
+ for (var c = 0; c < numComponents; ++c) {
+ // interpolation value range
+ /** @type {tcuInterval.Interval} */ var forwardComponent = tcuInterval.withIntervals(
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero(
+ es3fShaderDerivateTests.addErrorUlp(functionValueForward[c], -0.5, numVaryingSampleBits), minExponent, numBits)),
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero(
+ es3fShaderDerivateTests.addErrorUlp(functionValueForward[c], +0.5, numVaryingSampleBits), minExponent, numBits))
+ );
+
+ /** @type {tcuInterval.Interval} */ var backwardComponent = tcuInterval.withIntervals(
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero(
+ es3fShaderDerivateTests.addErrorUlp(functionValueBackward[c], -0.5, numVaryingSampleBits), minExponent, numBits)),
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero(
+ es3fShaderDerivateTests.addErrorUlp(functionValueBackward[c], +0.5, numVaryingSampleBits), minExponent, numBits))
+ );
+
+ /** @type {number} */
+ var maxValueExp = Math.max(
+ (new tcuFloat.deFloat().deFloatNumber(forwardComponent.lo())).exponent(),
+ (new tcuFloat.deFloat().deFloatNumber(forwardComponent.hi())).exponent(),
+ (new tcuFloat.deFloat().deFloatNumber(backwardComponent.lo())).exponent(),
+ (new tcuFloat.deFloat().deFloatNumber(backwardComponent.hi())).exponent());
+
+ // subtraction in nominator will likely cause a cancellation of the most
+ // significant bits. Apply error bounds.
+ /** @type {tcuInterval.Interval} */ var nominator = tcuInterval.Interval.operatorSub(forwardComponent, backwardComponent);
+ /** @type {number} */ var nominatorLoExp = (new tcuFloat.deFloat().deFloatNumber(nominator.lo())).exponent();
+ /** @type {number} */ var nominatorHiExp = (new tcuFloat.deFloat().deFloatNumber(nominator.hi())).exponent();
+ /** @type {number} */ var nominatorLoBitsLost = maxValueExp - nominatorLoExp;
+ /** @type {number} */ var nominatorHiBitsLost = maxValueExp - nominatorHiExp;
+ /** @type {number} */ var nominatorLoBits = Math.max(0, numBits - nominatorLoBitsLost);
+ /** @type {number} */ var nominatorHiBits = Math.max(0, numBits - nominatorHiBitsLost);
+
+ /** @type {tcuInterval.Interval} */ var nominatorRange = tcuInterval.withIntervals(
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero(nominator.lo(), minExponent, nominatorLoBits)),
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero(nominator.hi(), minExponent, nominatorHiBits)));
+ //
+ /** @type {tcuInterval.Interval} */ var divisionRange = tcuInterval.Interval.operatorDiv(nominatorRange, new tcuInterval.Interval(3.0)); // legal sample area is anywhere within this and neighboring pixels (i.e. size = 3)
+ /** @type {tcuInterval.Interval} */ var divisionResultRange = tcuInterval.withIntervals(
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero(es3fShaderDerivateTests.addErrorUlp(divisionRange.lo(), -divisionErrorUlps, numBits), minExponent, numBits)),
+ new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero(es3fShaderDerivateTests.addErrorUlp(divisionRange.hi(), divisionErrorUlps, numBits), minExponent, numBits)));
+ /** @type {tcuInterval.Interval} */ var finalResultRange = tcuInterval.withIntervals(
+ new tcuInterval.Interval(divisionResultRange.lo() - surfaceThreshold[c]),
+ new tcuInterval.Interval(divisionResultRange.hi() + surfaceThreshold[c]));
+
+ if (resultDerivative[c] >= finalResultRange.lo() && resultDerivative[c] <= finalResultRange.hi()) {
+ // value ok
+ } else {
+ if (numFailedPixels < es3fShaderDerivateTests.MAX_FAILED_MESSAGES)
+ bufferedLogToConsole('Error in pixel at ' + x + ', ' + y + ' with component ' + c + ' (channel ' + ('rgba'[c]) + ')\n' +
+ '\tGot pixel value ' + result.getPixelInt(x, y) + '\n' +
+ '\t\tdFd' + ((derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX) ? 'x' : 'y') + ' ~= ' + resultDerivative[c] + '\n' +
+ '\t\tdifference to a valid range: ' +
+ ((resultDerivative[c] < finalResultRange.lo()) ? '-' : '+') +
+ ((resultDerivative[c] < finalResultRange.lo()) ? (finalResultRange.lo() - resultDerivative[c]) : (resultDerivative[c] - finalResultRange.hi())) +
+ '\n' +
+ '\tDerivative value range:\n' +
+ '\t\tMin: ' + finalResultRange.lo() + '\n' +
+ '\t\tMax: ' + finalResultRange.hi() + '\n');
+
+ ++numFailedPixels;
+ anyComponentFailed = true;
+ }
+ }
+
+ if (anyComponentFailed)
+ errorMask.setPixel(red, x, y);
+ }
+
+ if (numFailedPixels >= es3fShaderDerivateTests.MAX_FAILED_MESSAGES)
+ bufferedLogToConsole('...');
+
+ if (numFailedPixels > 0)
+ bufferedLogToConsole('FAIL: found ' + numFailedPixels + ' failed pixels');
+
+ return numFailedPixels === 0;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ es3fShaderDerivateTests.TriangleDerivateCase = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {?gluShaderUtil.DataType} */ this.m_dataType = null;
+ /** @type {?gluShaderUtil.precision} */ this.m_precision = null;
+
+ /** @type {?gluShaderUtil.DataType} */ this.m_coordDataType = null;
+ /** @type {?gluShaderUtil.precision} */ this.m_coordPrecision = null;
+
+ /** @type {string} */ this.m_fragmentSrc;
+
+ /** @type {Array<number>} */ this.m_coordMin = [];
+ /** @type {Array<number>} */ this.m_coordMax = [];
+ /** @type {Array<number>} */ this.m_derivScale = [];
+ /** @type {Array<number>} */ this.m_derivBias = [];
+
+ /** @type {es3fShaderDerivateTests.SurfaceType} */ this.m_surfaceType = es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER;
+ /** @type {number} */ this.m_numSamples = 0;
+ /** @type {number} */ this.m_hint = gl.DONT_CARE;
+
+ assertMsgOptions(this.m_surfaceType !== es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER || this.m_numSamples === 0, 'Did not expect surfaceType = DEFAULT_FRAMEBUFFER or numSamples = 0', false, true);
+ };
+
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype.constructor = es3fShaderDerivateTests.TriangleDerivateCase;
+
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype.deinit = function() {};
+
+ /** @param {WebGLProgram} program */
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype.setupRenderState = function(program) {};
+
+ /**
+ * @param {?gluShaderUtil.DataType} coordType
+ * @param {?gluShaderUtil.precision} precision
+ * @return {string}
+ */
+ es3fShaderDerivateTests.genVertexSource = function(coordType, precision) {
+ assertMsgOptions(gluShaderUtil.isDataTypeFloatOrVec(coordType), 'Coord Type not supported', false, true);
+
+ /** @type {string} */ var vertexTmpl = '' +
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in ${PRECISION} ${DATATYPE} a_coord;\n' +
+ 'out ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_coord = a_coord;\n' +
+ '}\n';
+
+ /** @type {Object} */ var vertexParams = {};
+
+ vertexParams['PRECISION'] = gluShaderUtil.getPrecisionName(precision);
+ vertexParams['DATATYPE'] = gluShaderUtil.getDataTypeName(coordType);
+
+ return tcuStringTemplate.specialize(vertexTmpl, vertexParams);
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype.getViewportSize = function() {
+ if (this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER) {
+ /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, es3fShaderDerivateTests.VIEWPORT_WIDTH);
+ /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, es3fShaderDerivateTests.VIEWPORT_HEIGHT);
+ return [width, height];
+ } else
+ return [es3fShaderDerivateTests.FBO_WIDTH, es3fShaderDerivateTests.FBO_HEIGHT];
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype.iterate = function() {
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(es3fShaderDerivateTests.genVertexSource(this.m_coordDataType, this.m_coordPrecision), this.m_fragmentSrc));
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xbbc24);
+ /** @type {boolean} */ var useFbo = this.m_surfaceType != es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER;
+ /** @type {number} */ var fboFormat = this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO ? gl.RGBA32UI : gl.RGBA8;
+ /** @type {Array<number>} */ var viewportSize = this.getViewportSize();
+ /** @type {number} */ var viewportX = useFbo ? 0 : rnd.getInt(0, gl.drawingBufferWidth - viewportSize[0]);
+ /** @type {number} */ var viewportY = useFbo ? 0 : rnd.getInt(0, gl.drawingBufferHeight - viewportSize[1]);
+ /** @type {?WebGLFramebuffer} */ var fbo = null;
+ /** @type {?WebGLRenderbuffer} */ var rbo = null;
+ /** @type {tcuTexture.TextureLevel} */ var result = null;
+
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk())
+ assertMsgOptions(false, 'Compile failed', false, true);
+
+ if (useFbo) {
+ bufferedLogToConsole('Rendering to FBO, format = ' + wtu.glEnumToString(gl, fboFormat) + ', samples = ' + this.m_numSamples);
+
+ fbo = gl.createFramebuffer();
+ rbo = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, fboFormat, viewportSize[0], viewportSize[1]);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+ } else {
+ /** @type {tcuPixelFormat.PixelFormat} */ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+
+ bufferedLogToConsole('Rendering to default framebuffer\n' +
+ '\tColor depth: R=' + pixelFormat.redBits + ', G=' + pixelFormat.greenBits + ', B=' + pixelFormat.blueBits + ', A=' + pixelFormat.alphaBits);
+ }
+
+ bufferedLogToConsole('in: ' + this.m_coordMin + ' ' + this.m_coordMax + '\n' +
+ 'v_coord.x = in.x * x\n' +
+ 'v_coord.y = in.y * y\n' +
+ 'v_coord.z = in.z * (x+y)/2\n' +
+ 'v_coord.w = in.w * (1 - (x+y)/2)\n' +
+ '\n' +
+ 'u_scale: ' + this.m_derivScale + ', u_bias: ' + this.m_derivBias + ' (displayed values have scale/bias removed)' +
+ 'Viewport: ' + viewportSize[0] + 'x' + viewportSize[1] +
+ 'gl.FRAGMENT_SHADER_DERIVATE_HINT: ' + wtu.glEnumToString(gl, this.m_hint));
+ // Draw
+ /** @type {Array<number>} */ var positions = [
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0
+ ];
+
+ /** @type {Array<number>} */ var coords =[
+ this.m_coordMin[0], this.m_coordMin[1], this.m_coordMin[2], this.m_coordMax[3],
+ this.m_coordMin[0], this.m_coordMax[1], (this.m_coordMin[2] + this.m_coordMax[2]) * 0.5, (this.m_coordMin[3]+this.m_coordMax[3]) * 0.5,
+ this.m_coordMax[0], this.m_coordMin[1], (this.m_coordMin[2] + this.m_coordMax[2]) * 0.5, (this.m_coordMin[3]+this.m_coordMax[3]) * 0.5,
+ this.m_coordMax[0], this.m_coordMax[1], this.m_coordMax[2], this.m_coordMin[3]
+ ];
+
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [
+ gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions),
+ gluDrawUtil.newFloatVertexArrayBinding('a_coord', 4, 4, 0, coords)
+ ];
+
+ /** @type {Array<number>} */ var indices = [0, 2, 1, 2, 3, 1];
+
+ gl.clearColor(0.125, 0.25, 0.5, 1.0);
+ // We can't really call clear() on gl.COLOR_BUFFER_BIT here as in c++ deqp.
+ // The fbo format might be of integer type and WebGL2 requires an INVALID_OPERATION to be generated.
+ var formatObj = gluTextureUtil.mapGLInternalFormat(fboFormat);
+ var fmtClass = tcuTexture.getTextureChannelClass(formatObj.type);
+ switch (fmtClass) {
+ case tcuTexture.TextureChannelClass.FLOATING_POINT:
+ case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
+ case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ gl.clearBufferuiv(gl.COLOR, 0, new Uint32Array([31, 63, 127, 255]));
+ gl.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ break;
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ gl.clearBufferiv(gl.COLOR, 0, new Int32Array([31, 63, 127, 255]));
+ gl.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+ break;
+ default:
+ throw new Error('Invalid channelclass ' + fmtClass);
+ }
+ gl.disable(gl.DITHER);
+
+ gl.useProgram(program.getProgram());
+
+ /** @type {WebGLUniformLocation} */ var scaleLoc = gl.getUniformLocation(program.getProgram(), 'u_scale');
+ /** @type {WebGLUniformLocation} */ var biasLoc = gl.getUniformLocation(program.getProgram(), 'u_bias');
+
+ switch (this.m_dataType) {
+ case gluShaderUtil.DataType.FLOAT:
+ gl.uniform1f(scaleLoc, this.m_derivScale[0]);
+ gl.uniform1f(biasLoc, this.m_derivBias[0]);
+ break;
+
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ gl.uniform2fv(scaleLoc, this.m_derivScale.slice(0,2));
+ gl.uniform2fv(biasLoc, this.m_derivBias.slice(0,2));
+ break;
+
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ gl.uniform3fv(scaleLoc, this.m_derivScale.slice(0,3));
+ gl.uniform3fv(biasLoc, this.m_derivBias.slice(0,3));
+ break;
+
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ gl.uniform4fv(scaleLoc, this.m_derivScale);
+ gl.uniform4fv(biasLoc, this.m_derivBias);
+ break;
+
+ default:
+ throw new Error('Data Type not supported: ' + this.m_dataType);
+ }
+
+ glsShaderRenderCase.setupDefaultUniforms(program.getProgram());
+ this.setupRenderState(program.getProgram());
+
+ gl.hint(gl.FRAGMENT_SHADER_DERIVATIVE_HINT, this.m_hint);
+
+ gl.viewport(viewportX, viewportY, viewportSize[0], viewportSize[1]);
+ gluDrawUtil.draw(gl, program.getProgram(), vertexArrays, gluDrawUtil.triangles(indices));
+
+ // Read back results
+
+ /** @type {boolean} */ var isMSAA = useFbo && this.m_numSamples > 0;
+ /** @type {?WebGLFramebuffer} */ var resFbo = null;
+ /** @type {?WebGLRenderbuffer} */ var resRbo = null;
+
+ // Resolve if necessary
+ if (isMSAA) {
+ resFbo = gl.createFramebuffer();
+ resRbo = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, resRbo);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 0, fboFormat, viewportSize[0], viewportSize[1]);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resFbo);
+ gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resRbo);
+
+ gl.blitFramebuffer(0, 0, viewportSize[0], viewportSize[1], 0, 0, viewportSize[0], viewportSize[1], gl.COLOR_BUFFER_BIT, gl.NEAREST);
+
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, resFbo);
+ }
+ switch (this.m_surfaceType) {
+ case es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER:
+ case es3fShaderDerivateTests.SurfaceType.UNORM_FBO:
+ var dataFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
+ result = new tcuTexture.TextureLevel(dataFormat, viewportSize[0], viewportSize[1]);
+ gluPixelTransfer.readPixels(gl, viewportX, viewportY, dataFormat, result);
+ break;
+
+ case es3fShaderDerivateTests.SurfaceType.FLOAT_FBO:
+ var dataFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT);
+ var transferFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32);
+ result = new tcuTexture.TextureLevel(dataFormat, viewportSize[0], viewportSize[1]);
+ gluPixelTransfer.readPixels(gl, viewportX, viewportY, transferFormat, result);
+ break;
+
+ default:
+ throw new Error('Surface Type not supported: ' + this.m_surfaceType);
+ }
+
+ // Verify
+ /** @type {tcuSurface.Surface} */
+ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+
+ errorMask.getAccess().clear(tcuRGBA.RGBA.green.toVec());
+
+ /** @type {boolean} */ var isOk = this.verify(result.getAccess(), errorMask.getAccess());
+
+ if (!isOk) {
+ tcuLogImage.logImage('Rendered', 'Rendered image', result.getAccess());
+ tcuLogImage.logImage('ErrorMask', 'Error mask', errorMask.getAccess());
+ testFailedOptions('Fail', false);
+ } else
+ testPassedOptions('Pass', true);
+
+ // Cleaning up buffers
+ gl.deleteFramebuffer(fbo);
+ gl.deleteRenderbuffer(rbo);
+ gl.deleteFramebuffer(resFbo);
+ gl.deleteRenderbuffer(resRbo);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ es3fShaderDerivateTests.TriangleDerivateCase.prototype.getSurfaceThreshold = function() {
+ switch (this.m_surfaceType) {
+ case es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER:
+ /** @type {tcuPixelFormat.PixelFormat} */ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ /** @type {Array<number>} */ var channelBits = [pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits];
+ /** @type {Array<number>} */ var intThreshold = deMath.arrayShiftLeft([1, 1, 1, 1], deMath.subtract([8, 8, 8, 8], channelBits));
+ /** @type {Array<number>} */ var normThreshold = deMath.scale(intThreshold, 1.0/255.0);
+
+ return normThreshold;
+
+ case es3fShaderDerivateTests.SurfaceType.UNORM_FBO: return deMath.scale([1, 1, 1, 1], 1.0/255.0);
+ case es3fShaderDerivateTests.SurfaceType.FLOAT_FBO: return [0.0, 0.0, 0.0, 0.0];
+ default:
+ assertMsgOptions(false, 'Surface Type not supported. Falling back to default retun value [0.0, 0.0, 0.0, 0.0]', false, false);
+ return [0.0, 0.0, 0.0, 0.0];
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderDerivateTests.TriangleDerivateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fShaderDerivateTests.DerivateFunc} func
+ * @param {gluShaderUtil.DataType} type
+ */
+ es3fShaderDerivateTests.ConstantDerivateCase = function(name, description, func, type) {
+ es3fShaderDerivateTests.TriangleDerivateCase.call(this, name, description);
+ /** @type {es3fShaderDerivateTests.DerivateFunc} */ this.m_func = func;
+ this.m_dataType = type;
+ this.m_precision = gluShaderUtil.precision.PRECISION_HIGHP;
+ this.m_coordDataType = this.m_dataType;
+ this.m_coordPrecision = this.m_precision;
+ };
+
+ es3fShaderDerivateTests.ConstantDerivateCase.prototype = Object.create(es3fShaderDerivateTests.TriangleDerivateCase.prototype);
+ es3fShaderDerivateTests.ConstantDerivateCase.prototype.constructor = es3fShaderDerivateTests.ConstantDerivateCase;
+
+ es3fShaderDerivateTests.ConstantDerivateCase.prototype.init = function() {
+ /** @type {string} */ var fragmentTmpl = '' +
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res = ${FUNC}(${VALUE}) * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n';
+
+ /** @type {Object} */ var fragmentParams = {};
+ fragmentParams['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_precision);
+ fragmentParams['DATATYPE'] = gluShaderUtil.getDataTypeName(this.m_dataType);
+ fragmentParams['FUNC'] = es3fShaderDerivateTests.getDerivateFuncName(this.m_func);
+ fragmentParams['VALUE'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'vec4(1.0, 7.2, -1e5, 0.0)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec3(1e2, 8.0, 0.01)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec2(-0.0, 2.7)' :
+ '7.7';
+ fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'res' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec4(res, 1.0)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec4(res, 0.0, 1.0)' :
+ 'vec4(res, 0.0, 0.0, 1.0)';
+
+ this.m_fragmentSrc = tcuStringTemplate.specialize(fragmentTmpl, fragmentParams);
+
+ this.m_derivScale = [1e3, 1e3, 1e3, 1e3];
+ this.m_derivBias = [0.5, 0.5, 0.5, 0.5];
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @return {boolean}
+ */
+ es3fShaderDerivateTests.ConstantDerivateCase.prototype.verify = function(result, errorMask) {
+ /** @type {Array<number>} */ var reference = [0.0, 0.0, 0.0, 0.0]; // Derivate of constant argument should always be 0
+ /** @type {Array<number>} */ var threshold = deMath.divide(this.getSurfaceThreshold(), deMath.abs(this.m_derivScale));
+ return es3fShaderDerivateTests.verifyConstantDerivate(result, errorMask, this.m_dataType,
+ reference, threshold, this.m_derivScale, this.m_derivBias);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderDerivateTests.TriangleDerivateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fShaderDerivateTests.DerivateFunc} func
+ * @param {gluShaderUtil.DataType} type
+ * @param {gluShaderUtil.precision} precision
+ * @param {number} hint
+ * @param {es3fShaderDerivateTests.SurfaceType} surfaceType
+ * @param {number} numSamples
+ * @param {string} fragmentSrcTmpl
+ */
+ es3fShaderDerivateTests.LinearDerivateCase = function(name, description, func, type, precision, hint, surfaceType, numSamples, fragmentSrcTmpl) {
+ es3fShaderDerivateTests.TriangleDerivateCase.call(this, name, description);
+ /** @type {es3fShaderDerivateTests.DerivateFunc} */ this.m_func = func;
+ /** @type {string} */ this.m_fragmentTmpl = fragmentSrcTmpl;
+ this.m_dataType = type;
+ this.m_precision = precision;
+ this.m_coordDataType = this.m_dataType;
+ this.m_coordPrecision = this.m_precision;
+ this.m_hint = hint;
+ this.m_surfaceType = surfaceType;
+ this.m_numSamples = numSamples;
+ };
+
+ es3fShaderDerivateTests.LinearDerivateCase.prototype = Object.create(es3fShaderDerivateTests.TriangleDerivateCase.prototype);
+ es3fShaderDerivateTests.LinearDerivateCase.prototype.constructor = es3fShaderDerivateTests.LinearDerivateCase;
+
+ es3fShaderDerivateTests.LinearDerivateCase.prototype.init = function() {
+ /** @type {Array<number>} */ var viewportSize = this.getViewportSize();
+ /** @type {number} */ var w = viewportSize[0];
+ /** @type {number} */ var h = viewportSize[1];
+ /** @type {boolean} */ var packToInt = this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO;
+
+ /** @type {Object} */ var fragmentParams = {};
+ fragmentParams['OUTPUT_TYPE'] = gluShaderUtil.getDataTypeName(packToInt ? gluShaderUtil.DataType.UINT_VEC4 : gluShaderUtil.DataType.FLOAT_VEC4);
+ fragmentParams['OUTPUT_PREC'] = gluShaderUtil.getPrecisionName(packToInt ? gluShaderUtil.precision.PRECISION_HIGHP : this.m_precision);
+ fragmentParams['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_precision);
+ fragmentParams['DATATYPE'] = gluShaderUtil.getDataTypeName(this.m_dataType);
+ fragmentParams['FUNC'] = es3fShaderDerivateTests.getDerivateFuncName(this.m_func);
+
+ if (packToInt) {
+ fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'floatBitsToUint(res)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'floatBitsToUint(vec4(res, 1.0))' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'floatBitsToUint(vec4(res, 0.0, 1.0))' :
+ 'floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))';
+ } else {
+ fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'res' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec4(res, 1.0)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec4(res, 0.0, 1.0)' :
+ 'vec4(res, 0.0, 0.0, 1.0)';
+ }
+
+ this.m_fragmentSrc = tcuStringTemplate.specialize(this.m_fragmentTmpl, fragmentParams);
+
+ switch (this.m_precision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP:
+ this.m_coordMin = [-97., 0.2, 71., 74.];
+ this.m_coordMax = [-13.2, -77., 44., 76.];
+ break;
+
+ case gluShaderUtil.precision.PRECISION_MEDIUMP:
+ this.m_coordMin = [-37.0, 47., -7., 0.0];
+ this.m_coordMax = [-1.0, 12., 7., 19.];
+ break;
+
+ case gluShaderUtil.precision.PRECISION_LOWP:
+ this.m_coordMin = [0.0, -1.0, 0.0, 1.0];
+ this.m_coordMax = [1.0, 1.0, -1.0, -1.0];
+ break;
+
+ default:
+ throw new Error('Precision not supported: ' + this.m_precision);
+ }
+
+ if (this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO) {
+ // No scale or bias used for accuracy.
+ this.m_derivScale = [1.0, 1.0, 1.0, 1.0];
+ this.m_derivBias = [0.0, 0.0, 0.0, 0.0];
+ } else {
+ // Compute scale - bias that normalizes to 0..1 range.
+ /** @type {Array<number>} */ var dx = deMath.divide(deMath.subtract(this.m_coordMax, this.m_coordMin), [w, w, w * 0.5, -w * 0.5]);
+ /** @type {Array<number>} */ var dy = deMath.divide(deMath.subtract(this.m_coordMax, this.m_coordMin), [h, h, h * 0.5, -h * 0.5]);
+
+ switch (this.m_func) {
+ case es3fShaderDerivateTests.DerivateFunc.DFDX:
+ this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dx);
+ break;
+
+ case es3fShaderDerivateTests.DerivateFunc.DFDY:
+ this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dy);
+ break;
+
+ case es3fShaderDerivateTests.DerivateFunc.FWIDTH:
+ this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], deMath.add(deMath.abs(dx), deMath.abs(dy)));
+ break;
+
+ default:
+ throw new Error('Derivate Function not supported: ' + this.m_func);
+ }
+
+ this.m_derivBias = [0.0, 0.0, 0.0, 0.0];
+ }
+ };
+
+ /**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @return {boolean}
+ */
+ es3fShaderDerivateTests.LinearDerivateCase.prototype.verify = function(result, errorMask) {
+ /** @type {Array<number>} */ var xScale = [1.0, 0.0, 0.5, -0.5];
+ /** @type {Array<number>} */ var yScale = [0.0, 1.0, 0.5, -0.5];
+ /** @type {Array<number>} */ var surfaceThreshold = deMath.divide(this.getSurfaceThreshold(), deMath.abs(this.m_derivScale));
+
+ /** @type {number} */ var w;
+ /** @type {number} */ var h;
+ /** @type {Array<number>} */ var reference;
+ /** @type {Array<number>} */ var threshold;
+
+ if (this.m_func === es3fShaderDerivateTests.DerivateFunc.DFDX || this.m_func === es3fShaderDerivateTests.DerivateFunc.DFDY) {
+ /** @type {boolean} */ var isX = this.m_func === es3fShaderDerivateTests.DerivateFunc.DFDX;
+ /** @type {number} */ var div = isX ? result.getWidth() : result.getHeight();
+ /** @type {Array<number>} */ var scale = isX ? xScale : yScale;
+ reference = deMath.multiply(deMath.scale(deMath.subtract(this.m_coordMax, this.m_coordMin), 1/div), scale);
+ /** @type {Array<number>} */ var opThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_coordMin, scale), deMath.multiply(this.m_coordMax, scale), reference);
+ threshold = deMath.max(surfaceThreshold, opThreshold);
+ bufferedLogToConsole('Verifying result image.\n' +
+ '\tValid derivative is ' + reference + ' with threshold ' + threshold);
+
+ // short circuit if result is strictly within the normal value error bounds.
+ // This improves performance significantly.
+ if (es3fShaderDerivateTests.verifyConstantDerivate(result, errorMask,
+ this.m_dataType, reference, threshold, this.m_derivScale,
+ this.m_derivBias, es3fShaderDerivateTests.VerificationLogging.LOG_NOTHING)) {
+ bufferedLogToConsole('No incorrect derivatives found, result valid.');
+ return true;
+ }
+
+ // some pixels exceed error bounds calculated for normal values. Verify that these
+ // potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
+
+ bufferedLogToConsole('Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n' +
+ '\tVerifying each result derivative is within its range of legal result values.');
+
+ /** @type {Array<number>} */ var viewportSize = this.getViewportSize();
+ /** @type {Array<number>} */ var valueRamp = deMath.subtract(this.m_coordMax, this.m_coordMin);
+ /** @type {es3fShaderDerivateTests.Linear2DFunctionEvaluator} */ var function_ = new es3fShaderDerivateTests.Linear2DFunctionEvaluator();
+ w = viewportSize[0];
+ h = viewportSize[1];
+
+ function_.matrix.setRow(0, [valueRamp[0] / w, 0.0, this.m_coordMin[0]]);
+ function_.matrix.setRow(1, [0.0, valueRamp[1] / h, this.m_coordMin[1]]);
+ function_.matrix.setRow(2, deMath.scale([valueRamp[2] / w, valueRamp[2] / h, this.m_coordMin[2] + this.m_coordMin[2]], 1 / 2.0));
+ function_.matrix.setRow(3, deMath.scale([-valueRamp[3] / w, -valueRamp[3] / h, this.m_coordMax[3] + this.m_coordMax[3]], 1 / 2.0));
+
+ return es3fShaderDerivateTests.reverifyConstantDerivateWithFlushRelaxations(
+ result, errorMask, this.m_dataType, this.m_precision, this.m_derivScale,
+ this.m_derivBias, surfaceThreshold, this.m_func, function_);
+ } else {
+ assertMsgOptions(this.m_func === es3fShaderDerivateTests.DerivateFunc.FWIDTH, 'Expected DerivateFunc.FWIDTH', false, true);
+ w = result.getWidth();
+ h = result.getHeight();
+
+ /** @type {Array<number>} */ var dx = deMath.multiply(deMath.scale(deMath.subtract(this.m_coordMax, this.m_coordMin), 1 / w), xScale);
+ /** @type {Array<number>} */ var dy = deMath.multiply(deMath.scale(deMath.subtract(this.m_coordMax, this.m_coordMin), 1 / h), yScale);
+ reference = deMath.add(deMath.abs(dx), deMath.abs(dy));
+ /** @type {Array<number>} */ var dxThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_coordMin, xScale), deMath.multiply(this.m_coordMax, xScale), dx);
+ /** @type {Array<number>} */ var dyThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_coordMin, yScale), deMath.multiply(this.m_coordMax, yScale), dy);
+ threshold = deMath.max(surfaceThreshold, deMath.max(dxThreshold, dyThreshold));
+
+ return es3fShaderDerivateTests.verifyConstantDerivate(result, errorMask, this.m_dataType,
+ reference, threshold, this.m_derivScale, this.m_derivBias);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderDerivateTests.TriangleDerivateCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fShaderDerivateTests.DerivateFunc} func
+ * @param {gluShaderUtil.DataType} type
+ * @param {gluShaderUtil.precision} precision
+ * @param {number} hint
+ * @param {es3fShaderDerivateTests.SurfaceType} surfaceType
+ * @param {number} numSamples
+ */
+ es3fShaderDerivateTests.TextureDerivateCase = function(name, description, func, type, precision, hint, surfaceType, numSamples) {
+ es3fShaderDerivateTests.TriangleDerivateCase.call(this, name, description);
+ /** @type {es3fShaderDerivateTests.DerivateFunc} */ this.m_func = func;
+ /** @type {gluTexture.Texture2D} */ this.m_texture = null;
+ /** @type {Array<number>} */ this.m_texValueMin = [];
+ /** @type {Array<number>} */ this.m_texValueMax = [];
+ this.m_dataType = type;
+ this.m_precision = precision;
+ this.m_coordDataType = gluShaderUtil.DataType.FLOAT_VEC2;
+ this.m_coordPrecision = gluShaderUtil.precision.PRECISION_HIGHP;
+ this.m_hint = hint;
+ this.m_surfaceType = surfaceType;
+ this.m_numSamples = numSamples;
+ };
+
+ es3fShaderDerivateTests.TextureDerivateCase.prototype = Object.create(es3fShaderDerivateTests.TriangleDerivateCase.prototype);
+ es3fShaderDerivateTests.TextureDerivateCase.prototype.constructor = es3fShaderDerivateTests.TextureDerivateCase;
+
+ es3fShaderDerivateTests.TextureDerivateCase.prototype.deinit = function() {
+ this.m_texture = null;
+ };
+
+ es3fShaderDerivateTests.TextureDerivateCase.prototype.init = function() {
+ // Generate shader
+ /** @type {string} */ var fragmentTmpl = '' +
+ '#version 300 es\n' +
+ 'in highp vec2 v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} sampler2D u_sampler;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} vec4 tex = texture(u_sampler, v_coord);\n' +
+ ' ${PRECISION} ${DATATYPE} res = ${FUNC}(tex${SWIZZLE}) * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n';
+
+ /** @type {boolean} */ var packToInt = this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO;
+ /** @type {Object} */ var fragmentParams = {};
+ /** @type {Array<number>} */ var viewportSize;
+ fragmentParams['OUTPUT_TYPE'] = gluShaderUtil.getDataTypeName(packToInt ? gluShaderUtil.DataType.UINT_VEC4 : gluShaderUtil.DataType.FLOAT_VEC4);
+ fragmentParams['OUTPUT_PREC'] = gluShaderUtil.getPrecisionName(packToInt ? gluShaderUtil.precision.PRECISION_HIGHP : this.m_precision);
+ fragmentParams['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_precision);
+ fragmentParams['DATATYPE'] = gluShaderUtil.getDataTypeName(this.m_dataType);
+ fragmentParams['FUNC'] = es3fShaderDerivateTests.getDerivateFuncName(this.m_func);
+ fragmentParams['SWIZZLE'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? '' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? '.xyz' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? '.xy' :
+ '.x';
+
+ if (packToInt) {
+ fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'floatBitsToUint(res)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'floatBitsToUint(vec4(res, 1.0))' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'floatBitsToUint(vec4(res, 0.0, 1.0))' :
+ 'floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))';
+ } else {
+ fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'res' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec4(res, 1.0)' :
+ this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec4(res, 0.0, 1.0)' :
+ 'vec4(res, 0.0, 0.0, 1.0)';
+ }
+
+ this.m_fragmentSrc = tcuStringTemplate.specialize(fragmentTmpl, fragmentParams);
+
+ // Texture size matches viewport and nearest sampling is used. Thus texture sampling
+ // is equal to just interpolating the texture value range.
+
+ // Determine value range for texture.
+
+ switch (this.m_precision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP:
+ this.m_texValueMin = [-97., 0.2, 71., 74.];
+ this.m_texValueMax = [-13.2, -77., 44., 76.];
+ break;
+
+ case gluShaderUtil.precision.PRECISION_MEDIUMP:
+ this.m_texValueMin = [-37.0, 47., -7., 0.0];
+ this.m_texValueMax = [-1.0, 12., 7., 19.];
+ break;
+
+ case gluShaderUtil.precision.PRECISION_LOWP:
+ this.m_texValueMin = [0.0, -1.0, 0.0, 1.0];
+ this.m_texValueMax = [1.0, 1.0, -1.0, -1.0];
+ break;
+
+ default:
+ throw new Error(false, 'Precision not supported:' + this.m_precision);
+ }
+
+ // Lowp and mediump cases use RGBA16F format, while highp uses RGBA32F.
+ viewportSize = this.getViewportSize();
+ assertMsgOptions(!this.m_texture, 'Texture not null', false, true);
+ this.m_texture = gluTexture.texture2DFromInternalFormat(gl, this.m_precision === gluShaderUtil.precision.PRECISION_HIGHP ? gl.RGBA32F : gl.RGBA16F, viewportSize[0], viewportSize[1]);
+ this.m_texture.getRefTexture().allocLevel(0);
+
+ // Texture coordinates
+ this.m_coordMin = [0.0, 0.0, 0.0, 0.0];
+ this.m_coordMax = [1.0, 1.0, 1.0, 1.0];
+
+ // Fill with gradients.
+ /** @type {tcuTexture.PixelBufferAccess} */ var level0 = this.m_texture.getRefTexture().getLevel(0);
+ for (var y = 0; y < level0.getHeight(); y++) {
+ for (var x = 0; x < level0.getWidth(); x++) {
+ /** @type {number} */ var xf = (x + 0.5) / level0.getWidth();
+ /** @type {number} */ var yf = (y + 0.5) / level0.getHeight();
+ /** @type {Array<number>} */ var s = [xf, yf, (xf + yf) / 2.0, 1.0 - (xf + yf) / 2.0];
+
+ level0.setPixel(deMath.add(this.m_texValueMin, deMath.multiply(deMath.subtract(this.m_texValueMax, this.m_texValueMin), s)), x, y);
+ }
+ }
+
+ this.m_texture.upload();
+
+ if (this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO) {
+ // No scale or bias used for accuracy.
+ this.m_derivScale = [1.0, 1.0, 1.0, 1.0];
+ this.m_derivBias = [0.0, 0.0, 0.0, 0.0];
+ } else {
+ // Compute scale - bias that normalizes to 0..1 range.
+ viewportSize = this.getViewportSize();
+ /** @type {number} */ var w = viewportSize[0];
+ /** @type {number} */ var h = viewportSize[1];
+ /** @type {Array<number>} */ var dx = deMath.divide(deMath.subtract(this.m_texValueMax, this.m_texValueMin), [w, w, w * 0.5, -w * 0.5]);
+ /** @type {Array<number>} */ var dy = deMath.divide(deMath.subtract(this.m_texValueMax, this.m_texValueMin), [h, h, h * 0.5, -h * 0.5]);
+
+ switch (this.m_func) {
+ case es3fShaderDerivateTests.DerivateFunc.DFDX:
+ this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dx);
+ break;
+
+ case es3fShaderDerivateTests.DerivateFunc.DFDY:
+ this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dy);
+ break;
+
+ case es3fShaderDerivateTests.DerivateFunc.FWIDTH:
+ this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], deMath.add(deMath.abs(dx), deMath.abs(dy)));
+ break;
+
+ default:
+ throw new Error('Derivate Function not supported: ' + this.m_func);
+ }
+
+ this.m_derivBias = [0.0, 0.0, 0.0, 0.0];
+ }
+ };
+
+ /**
+ * @param {WebGLProgram} program
+ */
+ es3fShaderDerivateTests.TextureDerivateCase.prototype.setupRenderState = function(program) {
+ /** @type {number} */ var texUnit = 1;
+
+ gl.activeTexture(gl.TEXTURE0 + texUnit);
+ gl.bindTexture(gl.TEXTURE_2D, this.m_texture.getGLTexture());
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ gl.uniform1i(gl.getUniformLocation(program, 'u_sampler'), texUnit);
+ };
+
+ /**
+ * @param {tcuTexture.PixelBufferAccess} result
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @return {boolean}
+ */
+ es3fShaderDerivateTests.TextureDerivateCase.prototype.verify = function(result, errorMask) {
+ // \note Edges are ignored in comparison
+ if (result.getWidth() < 2 || result.getHeight() < 2)
+ throw new Error('Too small viewport');
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var compareArea = tcuTextureUtil.getSubregion(result, 1, 1, 0, result.getWidth() - 2, result.getHeight() - 2, 1);
+ /** @type {tcuTexture.PixelBufferAccess} */ var maskArea = tcuTextureUtil.getSubregion(errorMask, 1, 1, 0, errorMask.getWidth() - 2, errorMask.getHeight() - 2, 1);
+ /** @type {Array<number>} */ var xScale = [1.0, 0.0, 0.5, -0.5];
+ /** @type {Array<number>} */ var yScale = [0.0, 1.0, 0.5, -0.5];
+ /** @type {number} */ var w = result.getWidth();
+ /** @type {number} */ var h = result.getHeight();
+
+ /** @type {Array<number>} */ var surfaceThreshold = deMath.divide(this.getSurfaceThreshold(), deMath.abs(this.m_derivScale));
+ /** @type {Array<number>} */ var reference;
+ /** @type {Array<number>} */ var threshold;
+ if (this.m_func == es3fShaderDerivateTests.DerivateFunc.DFDX || this.m_func == es3fShaderDerivateTests.DerivateFunc.DFDY) {
+ /** @type {boolean} */ var isX = this.m_func == es3fShaderDerivateTests.DerivateFunc.DFDX;
+ /** @type {number} */ var div = isX ? w : h;
+ /** @type {Array<number>} */ var scale = isX ? xScale : yScale;
+ reference = deMath.multiply(deMath.scale(deMath.subtract(this.m_texValueMax, this.m_texValueMin), 1 / div), scale);
+ /** @type {Array<number>} */ var opThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_texValueMin, scale), deMath.multiply(this.m_texValueMax, scale), reference);
+ threshold = deMath.max(surfaceThreshold, opThreshold);
+
+ bufferedLogToConsole('Verifying result image.\n'+
+ '\tValid derivative is ' + reference + ' with threshold ' + threshold);
+
+ // short circuit if result is strictly within the normal value error bounds.
+ // This improves performance significantly.
+ if (es3fShaderDerivateTests.verifyConstantDerivate(compareArea, maskArea, this.m_dataType,
+ reference, threshold, this.m_derivScale, this.m_derivBias,
+ es3fShaderDerivateTests.VerificationLogging.LOG_NOTHING)) {
+ bufferedLogToConsole('No incorrect derivatives found, result valid.');
+ return true;
+ }
+ // some pixels exceed error bounds calculated for normal values. Verify that these
+ // potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
+
+ bufferedLogToConsole('Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n' +
+ '\tVerifying each result derivative is within its range of legal result values.');
+
+ /** @type {Array<number>} */ var valueRamp = deMath.subtract(this.m_texValueMax, this.m_texValueMin);
+ /** @type {es3fShaderDerivateTests.Linear2DFunctionEvaluator} */ var function_ = new es3fShaderDerivateTests.Linear2DFunctionEvaluator();
+
+ function_.matrix.setRow(0, [valueRamp[0] / w, 0.0, this.m_texValueMin[0]]);
+ function_.matrix.setRow(1, [0.0, valueRamp[1] / h, this.m_texValueMin[1]]);
+ function_.matrix.setRow(2, deMath.scale([valueRamp[2] / w, valueRamp[2] / h, this.m_texValueMin[2] + this.m_texValueMin[2]], 1 / 2.0));
+ function_.matrix.setRow(3, deMath.scale([-valueRamp[3] / w, -valueRamp[3] / h, this.m_texValueMax[3] + this.m_texValueMax[3]], 1 / 2.0));
+
+ return es3fShaderDerivateTests.reverifyConstantDerivateWithFlushRelaxations(compareArea, maskArea, this.m_dataType, this.m_precision,
+ this.m_derivScale, this.m_derivBias, surfaceThreshold, this.m_func, function_);
+ } else {
+ assertMsgOptions(this.m_func == es3fShaderDerivateTests.DerivateFunc.FWIDTH, 'Expected Derivate Function FWIDTH', false, true);
+ /** @type {Array<number>} */ var dx = deMath.multiply(deMath.scale(deMath.subtract(this.m_texValueMax, this.m_texValueMin), 1 / w), xScale);
+ /** @type {Array<number>} */ var dy = deMath.multiply(deMath.scale(deMath.subtract(this.m_texValueMax, this.m_texValueMin), 1 / h), yScale);
+ reference = deMath.add(deMath.abs(dx), deMath.abs(dy));
+ /** @type {Array<number>} */ var dxThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_texValueMin, xScale), deMath.multiply(this.m_texValueMax, xScale), dx);
+ /** @type {Array<number>} */ var dyThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_texValueMin, yScale), deMath.multiply(this.m_texValueMax, yScale), dy);
+ threshold = deMath.max(surfaceThreshold, deMath.max(dxThreshold, dyThreshold));
+
+ return es3fShaderDerivateTests.verifyConstantDerivate(compareArea, maskArea, this.m_dataType,
+ reference, threshold, this.m_derivScale, this.m_derivBias);
+ };
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderDerivateTests.ShaderDerivateTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'derivate', 'Derivate Function Tests');
+ };
+
+ es3fShaderDerivateTests.ShaderDerivateTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderDerivateTests.ShaderDerivateTests.prototype.constructor = es3fShaderDerivateTests.ShaderDerivateTests
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {es3fShaderDerivateTests.DerivateFunc} func
+ * @param {gluShaderUtil.DataType} dataType_
+ * @param {gluShaderUtil.precision} precision_
+ */
+ es3fShaderDerivateTests.FunctionSpec = function(name, func, dataType_, precision_) {
+ this.name = name;
+ this.function_ = func;
+ this.dataType = dataType_;
+ this.precision = precision_;
+ };
+
+ es3fShaderDerivateTests.ShaderDerivateTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {string} source
+ */
+ var LinearDerivateCase = function(name, description, source) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.description = description;
+ /** @type {string} */ this.source = source;
+ };
+
+ /** @type {Array<LinearDerivateCase>} */
+ var s_linearDerivateCases = [
+ new LinearDerivateCase(
+ 'linear',
+ 'Basic derivate of linearly interpolated argument',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res = ${FUNC}(v_coord) * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'in_function',
+ 'Derivate of linear function argument',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ '\n' +
+ '${PRECISION} ${DATATYPE} computeRes (${PRECISION} ${DATATYPE} value)\n' +
+ '{\n' +
+ ' return ${FUNC}(v_coord) * u_scale + u_bias;\n' +
+ '}\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res = computeRes(v_coord);\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'static_if',
+ 'Derivate of linearly interpolated value in static if',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res;\n' +
+ ' if (false)\n' +
+ ' res = ${FUNC}(-v_coord) * u_scale + u_bias;\n' +
+ ' else\n' +
+ ' res = ${FUNC}(v_coord) * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'static_loop',
+ 'Derivate of linearly interpolated value in static loop',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n' +
+ ' for (int i = 0; i < 2; i++)\n' +
+ ' res += ${FUNC}(v_coord * float(i));\n' +
+ ' res = res * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'static_switch',
+ 'Derivate of linearly interpolated value in static switch',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res;\n' +
+ ' switch (1)\n' +
+ ' {\n' +
+ ' case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias; break;\n' +
+ ' case 1: res = ${FUNC}(v_coord) * u_scale + u_bias; break;\n' +
+ ' }\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'uniform_if',
+ 'Derivate of linearly interpolated value in uniform if',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'uniform bool ub_true;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res;\n' +
+ ' if (ub_true)\n' +
+ ' res = ${FUNC}(v_coord) * u_scale + u_bias;\n' +
+ ' else\n' +
+ ' res = ${FUNC}(-v_coord) * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'uniform_loop',
+ 'Derivate of linearly interpolated value in uniform loop',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'uniform int ui_two;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n' +
+ ' for (int i = 0; i < ui_two; i++)\n' +
+ ' res += ${FUNC}(v_coord * float(i));\n' +
+ ' res = res * u_scale + u_bias;\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n'),
+ new LinearDerivateCase(
+ 'uniform_switch',
+ 'Derivate of linearly interpolated value in uniform switch',
+ '#version 300 es\n' +
+ 'in ${PRECISION} ${DATATYPE} v_coord;\n' +
+ 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' +
+ 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' +
+ 'uniform int ui_one;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${PRECISION} ${DATATYPE} res;\n' +
+ ' switch (ui_one)\n' +
+ ' {\n' +
+ ' case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias; break;\n' +
+ ' case 1: res = ${FUNC}(v_coord) * u_scale + u_bias; break;\n' +
+ ' }\n' +
+ ' o_color = ${CAST_TO_OUTPUT};\n' +
+ '}\n')
+ ];
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {es3fShaderDerivateTests.SurfaceType} surfaceType
+ * @param {number} numSamples
+ */
+ var FboConfig = function(name, surfaceType, numSamples) {
+ /** @type {string} */ this.name = name;
+ /** @type {es3fShaderDerivateTests.SurfaceType} */ this.surfaceType = surfaceType;
+ /** @type {number} */ this.numSamples = numSamples;
+ };
+
+ /** @type {Array<FboConfig>} */ var s_fboConfigs = [
+ new FboConfig('fbo', es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER, 0),
+ new FboConfig('fbo_msaa2', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 2),
+ new FboConfig('fbo_msaa4', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 4),
+ new FboConfig('fbo_float', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0)
+ ];
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {number} hint
+ */
+ var Hint = function(name, hint) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.hint = hint;
+ };
+
+ /** @type {Array<Hint>} */ var s_hints = [
+ new Hint('fastest', gl.FASTEST),
+ new Hint('nicest', gl.NICEST)
+ ];
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {es3fShaderDerivateTests.SurfaceType} surfaceType
+ * @param {number} numSamples
+ */
+ var HintFboConfig = function(name, surfaceType, numSamples) {
+ /** @type {string} */ this.name = name;
+ /** @type {es3fShaderDerivateTests.SurfaceType} */ this.surfaceType = surfaceType;
+ /** @type {number} */ this.numSamples = numSamples;
+ };
+
+ /** @type {Array<HintFboConfig>} */ var s_hintFboConfigs = [
+ new HintFboConfig('default', es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER, 0),
+ new HintFboConfig('fbo_msaa4', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 4),
+ new HintFboConfig('fbo_float', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0)
+ ];
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {es3fShaderDerivateTests.SurfaceType} surfaceType
+ * @param {number} numSamples
+ * @param {number} hint
+ */
+ var TextureConfig = function(name, surfaceType, numSamples, hint) {
+ /** @type {string} */ this.name = name;
+ /** @type {es3fShaderDerivateTests.SurfaceType} */ this.surfaceType = surfaceType;
+ /** @type {number} */ this.numSamples = numSamples;
+ /** @type {number} */ this.hint = hint;
+ };
+
+ /** @type {Array<TextureConfig>} */ var s_textureConfigs = [
+ new TextureConfig('basic', es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER, 0, gl.DONT_CARE),
+ new TextureConfig('msaa4', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 4, gl.DONT_CARE),
+ new TextureConfig('float_fastest', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0, gl.FASTEST),
+ new TextureConfig('float_nicest', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0, gl.NICEST)
+ ];
+
+ /** @type {gluShaderUtil.DataType} */ var dataType;
+ /** @type {string} */ var source;
+ /** @type {gluShaderUtil.precision} */ var precision;
+ /** @type {es3fShaderDerivateTests.SurfaceType} */ var surfaceType;
+ /** @type {number} */ var numSamples;
+ /** @type {number} */ var hint;
+ /** @type {string} */ var caseName;
+ /** @type {tcuTestCase.DeqpTest} */ var fboGroup;
+
+ // .dfdx, .dfdy, .fwidth
+ for (var funcNdx in es3fShaderDerivateTests.DerivateFunc) {
+ /** @type {es3fShaderDerivateTests.DerivateFunc} */ var function_ = es3fShaderDerivateTests.DerivateFunc[funcNdx];
+ /** @type {tcuTestCase.DeqpTest} */ var functionGroup = tcuTestCase.newTest(es3fShaderDerivateTests.getDerivateFuncCaseName(function_), es3fShaderDerivateTests.getDerivateFuncName(function_));
+ testGroup.addChild(functionGroup);
+
+ // .constant - no precision variants, checks that derivate of constant arguments is 0
+ /** @type {tcuTestCase.DeqpTest} */ var constantGroup = tcuTestCase.newTest('constant', 'Derivate of constant argument');
+ functionGroup.addChild(constantGroup);
+
+ for (var vecSize = 1; vecSize <= 4; vecSize++) {
+ dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
+ constantGroup.addChild(new es3fShaderDerivateTests.ConstantDerivateCase(gluShaderUtil.getDataTypeName(dataType), '', function_, dataType));
+ }
+
+ // Cases based on LinearDerivateCase
+ for (var caseNdx = 0; caseNdx < s_linearDerivateCases.length; caseNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var linearCaseGroup = tcuTestCase.newTest(s_linearDerivateCases[caseNdx].name, s_linearDerivateCases[caseNdx].description);
+ source = s_linearDerivateCases[caseNdx].source;
+ functionGroup.addChild(linearCaseGroup);
+
+ for (var vecSize = 1; vecSize <= 4; vecSize++)
+ for (var precNdx in gluShaderUtil.precision) {
+ dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
+ precision = gluShaderUtil.precision[precNdx];
+ surfaceType = es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER;
+ numSamples = 0;
+ hint = gl.DONT_CARE;
+
+ if (caseNdx !== 0 && precision === gluShaderUtil.precision.PRECISION_LOWP)
+ continue; // Skip as lowp doesn't actually produce any bits when rendered to default FB.
+
+ caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision);
+
+ linearCaseGroup.addChild(new es3fShaderDerivateTests.LinearDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples, source));
+ }
+ }
+
+ // Fbo cases
+ for (var caseNdx = 0; caseNdx < s_fboConfigs.length; caseNdx++) {
+ fboGroup = tcuTestCase.newTest(s_fboConfigs[caseNdx].name, 'Derivate usage when rendering into FBO');
+ source = s_linearDerivateCases[0].source; // use source from .linear group
+ surfaceType = s_fboConfigs[caseNdx].surfaceType;
+ numSamples = s_fboConfigs[caseNdx].numSamples;
+ functionGroup.addChild(fboGroup);
+
+ for (var vecSize = 1; vecSize <= 4; vecSize++)
+ for (var precNdx in gluShaderUtil.precision) {
+ dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
+ precision = gluShaderUtil.precision[precNdx];
+ hint = gl.DONT_CARE;
+
+ if (surfaceType !== es3fShaderDerivateTests.SurfaceType.FLOAT_FBO && precision === gluShaderUtil.precision.PRECISION_LOWP)
+ continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
+
+ caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision);
+
+ fboGroup.addChild(new es3fShaderDerivateTests.LinearDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples, source));
+ }
+ }
+
+ // .fastest, .nicest
+ for (var hintCaseNdx = 0; hintCaseNdx < s_hints.length; hintCaseNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var hintGroup = tcuTestCase.newTest(s_hints[hintCaseNdx].name, 'Shader derivate hints');
+ source = s_linearDerivateCases[0].source; // use source from .linear group
+ hint = s_hints[hintCaseNdx].hint;
+ functionGroup.addChild(hintGroup);
+
+ for (var fboCaseNdx = 0; fboCaseNdx < s_hintFboConfigs.length; fboCaseNdx++) {
+ fboGroup = tcuTestCase.newTest(s_hintFboConfigs[fboCaseNdx].name, '');
+ surfaceType = s_hintFboConfigs[fboCaseNdx].surfaceType;
+ numSamples = s_hintFboConfigs[fboCaseNdx].numSamples;
+ hintGroup.addChild(fboGroup);
+
+ for (var vecSize = 1; vecSize <= 4; vecSize++)
+ for (var precNdx in gluShaderUtil.precision) {
+ dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
+ precision = gluShaderUtil.precision[precNdx];
+
+ if (surfaceType !== es3fShaderDerivateTests.SurfaceType.FLOAT_FBO && precision === gluShaderUtil.precision.PRECISION_LOWP)
+ continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
+
+ caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision);
+
+ fboGroup.addChild(new es3fShaderDerivateTests.LinearDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples, source));
+ }
+ }
+ }
+
+ // .texture
+ /** @type {tcuTestCase.DeqpTest} */ var textureGroup = tcuTestCase.newTest('texture', 'Derivate of texture lookup result');
+ functionGroup.addChild(textureGroup);
+
+ for (var texCaseNdx = 0; texCaseNdx < s_textureConfigs.length; texCaseNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var caseGroup = tcuTestCase.newTest(s_textureConfigs[texCaseNdx].name, '');
+ surfaceType = s_textureConfigs[texCaseNdx].surfaceType;
+ numSamples = s_textureConfigs[texCaseNdx].numSamples;
+ hint = s_textureConfigs[texCaseNdx].hint;
+ textureGroup.addChild(caseGroup);
+
+ for (var vecSize = 1; vecSize <= 4; vecSize++)
+ for (var precNdx in gluShaderUtil.precision) {
+ dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
+ precision = gluShaderUtil.precision[precNdx];
+
+ if (surfaceType !== es3fShaderDerivateTests.SurfaceType.FLOAT_FBO && precision === gluShaderUtil.precision.PRECISION_LOWP)
+ continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
+
+ caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision);
+
+ caseGroup.addChild(new es3fShaderDerivateTests.TextureDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples));
+ }
+ }
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderDerivateTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderDerivateTests.ShaderDerivateTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderDerivateTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderIndexingTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderIndexingTests.js
new file mode 100644
index 0000000000..c08db90758
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderIndexingTests.js
@@ -0,0 +1,1278 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderIndexingTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluTexture');
+goog.require('modules.shared.glsShaderRenderCase');
+
+goog.scope(function() {
+ /** @type {?WebGL2RenderingContext} */ var gl;
+ var es3fShaderIndexingTests = functional.gles3.es3fShaderIndexingTests;
+ var deMath = framework.delibs.debase.deMath;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuStringTemplate = framework.common.tcuStringTemplate;
+ /**
+ * @enum {number}
+ */
+ es3fShaderIndexingTests.IndexAccessType = {
+ STATIC: 0,
+ DYNAMIC: 1,
+ STATIC_LOOP: 2,
+ DYNAMIC_LOOP: 3
+ };
+
+ /**
+ * @param {es3fShaderIndexingTests.IndexAccessType} accessType
+ * @return {string}
+ */
+ es3fShaderIndexingTests.getIndexAccessTypeName = function(accessType) {
+ /** @type {Array<string>} */ var s_names = [
+ 'static',
+ 'dynamic',
+ 'static_loop',
+ 'dynamic_loop'
+ ];
+ return s_names[accessType];
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fShaderIndexingTests.VectorAccessType = {
+ DIRECT: 0,
+ COMPONENT: 1,
+ SUBSCRIPT_STATIC: 2,
+ SUBSCRIPT_DYNAMIC: 3,
+ SUBSCRIPT_STATIC_LOOP: 4,
+ SUBSCRIPT_DYNAMIC_LOOP: 5
+ };
+
+ /**
+ * @param {es3fShaderIndexingTests.VectorAccessType} accessType
+ * @return {string}
+ */
+ es3fShaderIndexingTests.getVectorAccessTypeName = function(accessType) {
+ /** @type {Array<string>} */ var s_names = [
+ 'direct',
+ 'component',
+ 'static_subscript',
+ 'dynamic_subscript',
+ 'static_loop_subscript',
+ 'dynamic_loop_subscript'
+ ];
+ assertMsgOptions(deMath.deInBounds32(accessType, 0, s_names.length), 'Index out of bounds', false, true);
+ return s_names[accessType];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayCoordsFloat = function(c) {
+ c.color[0] = 1.875 * c.coords[0];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayCoordsVec2 = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [0, 1]);
+ c.color[0] = 1.875 * swizzled[0];
+ c.color[1] = 1.875 * swizzled[1];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayCoordsVec3 = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [0, 1, 2]);
+ c.color[0] = 1.875 * swizzled[0];
+ c.color[1] = 1.875 * swizzled[1];
+ c.color[2] = 1.875 * swizzled[2];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayCoordsVec4 = function(c) {
+ c.color = deMath.scale(c.coords, 1.875);
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {function(glsShaderRenderCase.ShaderEvalContext)}
+ */
+ es3fShaderIndexingTests.getArrayCoordsEvalFunc = function(dataType) {
+ if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayCoordsFloat;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayCoordsVec2;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayCoordsVec3;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayCoordsVec4;
+ else throw new Error('Invalid data type.');
+ };
+
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayUniformFloat = function(c) {
+ c.color[0] = 1.875 * c.constCoords[0];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayUniformVec2 = function(c) {
+ var swizzled = deMath.swizzle(c.constCoords, [0, 1]);
+ c.color[0] = 1.875 * swizzled[0];
+ c.color[1] = 1.875 * swizzled[1];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayUniformVec3 = function(c) {
+ var swizzled = deMath.swizzle(c.constCoords, [0, 1, 2]);
+ c.color[0] = 1.875 * swizzled[0];
+ c.color[1] = 1.875 * swizzled[1];
+ c.color[2] = 1.875 * swizzled[2];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalArrayUniformVec4 = function(c) {
+ c.color = deMath.scale(c.constCoords, 1.875);
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {function(glsShaderRenderCase.ShaderEvalContext)}
+ */
+ es3fShaderIndexingTests.getArrayUniformEvalFunc = function(dataType) {
+ if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayUniformFloat;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayUniformVec2;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayUniformVec3;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayUniformVec4;
+ else throw new Error('Invalid data type.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {gluShaderUtil.DataType} varType
+ * @param {function(glsShaderRenderCase.ShaderEvalContext)} evalFunc
+ * @param {string} vertShaderSource
+ * @param {string} fragShaderSource
+ */
+ es3fShaderIndexingTests.ShaderIndexingCase = function(name, description, isVertexCase, varType, evalFunc, vertShaderSource, fragShaderSource) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
+ /** @type {gluShaderUtil.DataType} */ this.m_varType = varType;
+ /** @type {string} */ this.m_vertShaderSource = vertShaderSource;
+ /** @type {string} */ this.m_fragShaderSource = fragShaderSource;
+ };
+
+ es3fShaderIndexingTests.ShaderIndexingCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+ es3fShaderIndexingTests.ShaderIndexingCase.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingCase;
+
+ /**
+ * @param {?WebGLProgram} programID
+ * @param {Array<number>} constCoords
+ */
+ es3fShaderIndexingTests.ShaderIndexingCase.prototype.setupUniforms = function(programID, constCoords) {
+ /** @type {(Array<number>|Float32Array)} */ var arr = [];
+ /** @type {Array<number>} */ var array1d = [];
+ /** @type {?WebGLUniformLocation} */ var arrLoc = gl.getUniformLocation(programID, 'u_arr');
+ if (arrLoc != null) {
+ if (this.m_varType === gluShaderUtil.DataType.FLOAT) {
+ arr[0] = constCoords[0];
+ arr[1] = constCoords[0] * 0.5;
+ arr[2] = constCoords[0] * 0.25;
+ arr[3] = constCoords[0] * 0.125;
+ gl.uniform1fv(arrLoc, arr);
+ }
+ else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC2) {
+ arr[0] = deMath.swizzle(constCoords, [0, 1]);
+ arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.5);
+ arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.25);
+ arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.125);
+ for (var i = 0; i < arr.length; i++)
+ array1d = array1d.concat(arr[i]);
+ gl.uniform2fv(arrLoc, array1d);
+ }
+ else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC3) {
+ arr[0] = deMath.swizzle(constCoords, [0, 1, 2]);
+ arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.5);
+ arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.25);
+ arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.125);
+ for (var i = 0; i < arr.length; i++)
+ array1d = array1d.concat(arr[i]);
+ gl.uniform3fv(arrLoc, array1d);
+ }
+ else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC4) {
+ arr[0] = deMath.swizzle(constCoords, [0,1,2,3]);
+ arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.5);
+ arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.25);
+ arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.125);
+ for (var i = 0; i < arr.length; i++)
+ array1d = array1d.concat(arr[i]);
+ gl.uniform4fv(arrLoc, array1d);
+ }
+ else
+ throw new Error('u_arr should not have location assigned in this test case');
+ }
+ };
+
+ /**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {gluShaderUtil.DataType} varType
+ * @param {es3fShaderIndexingTests.IndexAccessType} vertAccess
+ * @param {es3fShaderIndexingTests.IndexAccessType} fragAccess
+ * @return {es3fShaderIndexingTests.ShaderIndexingCase}
+ */
+ es3fShaderIndexingTests.createVaryingArrayCase = function(caseName, description, varType, vertAccess, fragAccess) {
+ /** @type {string} */ var vtx = '';
+ vtx += '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coords;\n';
+
+ if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
+ vtx += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
+ else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
+ vtx += 'uniform mediump int ui_four;\n';
+
+ vtx += 'out ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' +
+ '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n';
+
+ if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ vtx += ' var[0] = ${VAR_TYPE}(a_coords);\n' +
+ ' var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n' +
+ ' var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n' +
+ ' var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n';
+ }
+ else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ vtx += ' var[ui_zero] = ${VAR_TYPE}(a_coords);\n' +
+ ' var[ui_one] = ${VAR_TYPE}(a_coords) * 0.5;\n' +
+ ' var[ui_two] = ${VAR_TYPE}(a_coords) * 0.25;\n' +
+ ' var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n';
+ }
+ else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ vtx += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' +
+ ' for (int i = 0; i < 4; i++)\n' +
+ ' {\n' +
+ ' var[i] = ${VAR_TYPE}(coords);\n' +
+ ' coords = coords * 0.5;\n' +
+ ' }\n';
+ }
+ else {
+ assertMsgOptions(vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true);
+ vtx += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' +
+ ' for (int i = 0; i < ui_four; i++)\n' +
+ ' {\n' +
+ ' var[i] = ${VAR_TYPE}(coords);\n' +
+ ' coords = coords * 0.5;\n' +
+ ' }\n';
+ }
+ vtx += '}\n';
+
+ /** @type {string} */ var frag = '';
+ frag += '#version 300 es\n' +
+ 'precision mediump int;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
+ frag += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
+ else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
+ frag += 'uniform int ui_four;\n';
+
+ frag += 'in ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' +
+ '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n';
+
+ if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ frag += ' res += var[0];\n' +
+ ' res += var[1];\n' +
+ ' res += var[2];\n' +
+ ' res += var[3];\n';
+ }
+ else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ frag += ' res += var[ui_zero];\n' +
+ ' res += var[ui_one];\n' +
+ ' res += var[ui_two];\n' +
+ ' res += var[ui_three];\n';
+ }
+ else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ frag += ' for (int i = 0; i < 4; i++)\n' +
+ ' res += var[i];\n';
+ }
+ else {
+ assertMsgOptions(fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true);
+ frag += ' for (int i = 0; i < ui_four; i++)\n' +
+ ' res += var[i];\n';
+ }
+ frag += ' o_color = vec4(res${PADDING});\n' +
+ '}\n';
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType);
+ params['ARRAY_LEN'] = '4';
+ params['PRECISION'] = 'mediump';
+
+ if (varType === gluShaderUtil.DataType.FLOAT)
+ params['PADDING'] = ', 0.0, 0.0, 1.0';
+ else if (varType === gluShaderUtil.DataType.FLOAT_VEC2)
+ params['PADDING'] = ', 0.0, 1.0';
+ else if (varType === gluShaderUtil.DataType.FLOAT_VEC3)
+ params['PADDING'] = ', 1.0';
+ else
+ params['PADDING'] = '';
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
+ var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType);
+ return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, true, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
+ };
+
+ /**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {gluShaderUtil.DataType} varType
+ * @param {es3fShaderIndexingTests.IndexAccessType} readAccess
+ * @return {es3fShaderIndexingTests.ShaderIndexingCase}
+ */
+ es3fShaderIndexingTests.createUniformArrayCase = function(caseName, description, isVertexCase, varType, readAccess) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n';
+ vtx += 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (isVertexCase) {
+ vtx += 'out mediump vec4 v_color;\n';
+ frag += 'in mediump vec4 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+ }
+
+ if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
+ op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
+ op += 'uniform mediump int ui_four;\n';
+
+ op += 'uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ vtx += '\n';
+ vtx += 'void main()\n';
+ vtx += '{\n';
+ vtx += ' gl_Position = a_position;\n';
+
+ frag += '\n';
+ frag += 'void main()\n';
+ frag += '{\n';
+
+ // Read array.
+ op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n';
+ if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ op += ' res += u_arr[0];\n';
+ op += ' res += u_arr[1];\n';
+ op += ' res += u_arr[2];\n';
+ op += ' res += u_arr[3];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ op += ' res += u_arr[ui_zero];\n';
+ op += ' res += u_arr[ui_one];\n';
+ op += ' res += u_arr[ui_two];\n';
+ op += ' res += u_arr[ui_three];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ op += ' for (int i = 0; i < 4; i++)\n';
+ op += ' res += u_arr[i];\n';
+ }
+ else {
+ assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true);
+ op += ' for (int i = 0; i < ui_four; i++)\n';
+ op += ' res += u_arr[i];\n';
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ vtx += ' v_color = vec4(res${PADDING});\n';
+ frag += ' o_color = v_color;\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res${PADDING});\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType);
+ params['ARRAY_LEN'] = '4';
+ params['PRECISION'] = 'mediump';
+
+ if (varType === gluShaderUtil.DataType.FLOAT)
+ params['PADDING'] = ', 0.0, 0.0, 1.0';
+ else if (varType === gluShaderUtil.DataType.FLOAT_VEC2)
+ params['PADDING'] = ', 0.0, 1.0';
+ else if (varType === gluShaderUtil.DataType.FLOAT_VEC3)
+ params['PADDING'] = ', 1.0';
+ else
+ params['PADDING'] = '';
+
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
+ var evalFunc = es3fShaderIndexingTests.getArrayUniformEvalFunc(varType);
+ return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
+ };
+
+ /**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {gluShaderUtil.DataType} varType
+ * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess
+ * @param {es3fShaderIndexingTests.IndexAccessType} readAccess
+ * @return {es3fShaderIndexingTests.ShaderIndexingCase}
+ */
+ es3fShaderIndexingTests.createTmpArrayCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (isVertexCase) {
+ vtx += 'out mediump vec4 v_color;\n';
+ frag += 'in mediump vec4 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+ }
+
+ if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
+ op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
+
+ if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
+ op += 'uniform mediump int ui_four;\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ vtx += '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n';
+
+ frag += '\n' +
+ 'void main()\n' +
+ '{\n';
+
+ // Write array.
+ if (isVertexCase)
+ op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n';
+ else
+ op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n';
+
+ op += ' ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n';
+ if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ op += ' arr[0] = ${VAR_TYPE}(coords);\n' +
+ ' arr[1] = ${VAR_TYPE}(coords) * 0.5;\n' +
+ ' arr[2] = ${VAR_TYPE}(coords) * 0.25;\n' +
+ ' arr[3] = ${VAR_TYPE}(coords) * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ op += ' arr[ui_zero] = ${VAR_TYPE}(coords);\n' +
+ ' arr[ui_one] = ${VAR_TYPE}(coords) * 0.5;\n' +
+ ' arr[ui_two] = ${VAR_TYPE}(coords) * 0.25;\n' +
+ ' arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ op += ' for (int i = 0; i < 4; i++)\n' +
+ ' {\n' +
+ ' arr[i] = ${VAR_TYPE}(coords);\n' +
+ ' coords = coords * 0.5;\n' +
+ ' }\n';
+ }
+ else {
+ assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true);
+ op += ' for (int i = 0; i < ui_four; i++)\n' +
+ ' {\n' +
+ ' arr[i] = ${VAR_TYPE}(coords);\n' +
+ ' coords = coords * 0.5;\n' +
+ ' }\n';
+ }
+
+ // Read array.
+ op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n';
+ if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ op += ' res += arr[0];\n' +
+ ' res += arr[1];\n' +
+ ' res += arr[2];\n' +
+ ' res += arr[3];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ op += ' res += arr[ui_zero];\n' +
+ ' res += arr[ui_one];\n' +
+ ' res += arr[ui_two];\n' +
+ ' res += arr[ui_three];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ op += ' for (int i = 0; i < 4; i++)\n' +
+ ' res += arr[i];\n';
+ }
+ else {
+ assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true);
+ op += ' for (int i = 0; i < ui_four; i++)\n' +
+ ' res += arr[i];\n';
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ vtx += ' v_color = vec4(res${PADDING});\n';
+ frag += ' o_color = v_color;\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res${PADDING});\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType);
+ params["ARRAY_LEN"] = "4";
+ params["PRECISION"] = "mediump";
+
+ if (varType === gluShaderUtil.DataType.FLOAT)
+ params['PADDING'] = ', 0.0, 0.0, 1.0';
+ else if (varType === gluShaderUtil.DataType.FLOAT_VEC2)
+ params['PADDING'] = ', 0.0, 1.0';
+ else if (varType === gluShaderUtil.DataType.FLOAT_VEC3)
+ params['PADDING'] = ', 1.0';
+ else
+ params['PADDING'] = '';
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
+ var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType);
+ return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
+ };
+
+ // VECTOR SUBSCRIPT.
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptVec2 = function(c) {
+ c.color[0] = c.coords[0] + 0.5 * c.coords[1];
+ c.color[1] = c.coords[0] + 0.5 * c.coords[1];
+ c.color[2] = c.coords[0] + 0.5 * c.coords[1];
+ };
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptVec3 = function(c) {
+ c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2];
+ c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2];
+ c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2];
+ };
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptVec4 = function(c) {
+ c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3];
+ c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3];
+ c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3];
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {function(glsShaderRenderCase.ShaderEvalContext)}
+ */
+ es3fShaderIndexingTests.getVectorSubscriptEvalFunc = function(dataType) {
+ if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalSubscriptVec2;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalSubscriptVec3;
+ else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalSubscriptVec4;
+ else throw new Error('Invalid data type.');
+ };
+
+ /**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {gluShaderUtil.DataType} varType
+ * @param {es3fShaderIndexingTests.VectorAccessType} writeAccess
+ * @param {es3fShaderIndexingTests.VectorAccessType} readAccess
+ * @return {es3fShaderIndexingTests.ShaderIndexingCase}
+ */
+ es3fShaderIndexingTests.createVectorSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '' ;
+
+ /** @type {number} */ var vecLen = gluShaderUtil.getDataTypeScalarSize(varType);
+ /** @type {string} */ var vecLenName = glsShaderRenderCase.getIntUniformName(vecLen);
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (isVertexCase) {
+ vtx += 'out mediump vec3 v_color;\n';
+ frag += 'in mediump vec3 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+ }
+
+ if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC ||
+ readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC){
+ op += 'uniform mediump int ui_zero';
+ if (vecLen >= 2) op += ', ui_one';
+ if (vecLen >= 3) op += ', ui_two';
+ if (vecLen >= 4) op += ', ui_three';
+ op += ';\n';
+ }
+
+ if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP ||
+ readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP)
+ op += 'uniform mediump int ' + vecLenName + ';\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ vtx += '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n';
+
+ frag += '\n' +
+ 'void main()\n' +
+ '{\n';
+
+ // Write vector.
+ if (isVertexCase)
+ op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n';
+ else
+ op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n';
+
+ op += ' ${PRECISION} ${VAR_TYPE} tmp;\n';
+ if (writeAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT)
+ op += ' tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n';
+ else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) {
+ op += ' tmp.x = coords.x;\n';
+ if (vecLen >= 2) op += ' tmp.y = coords.y * 0.5;\n';
+ if (vecLen >= 3) op += ' tmp.z = coords.z * 0.25;\n';
+ if (vecLen >= 4) op += ' tmp.w = coords.w * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) {
+ op += ' tmp[0] = coords.x;\n';
+ if (vecLen >= 2) op += ' tmp[1] = coords.y * 0.5;\n';
+ if (vecLen >= 3) op += ' tmp[2] = coords.z * 0.25;\n';
+ if (vecLen >= 4) op += ' tmp[3] = coords.w * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) {
+ op += ' tmp[ui_zero] = coords.x;\n';
+ if (vecLen >= 2) op += ' tmp[ui_one] = coords.y * 0.5;\n';
+ if (vecLen >= 3) op += ' tmp[ui_two] = coords.z * 0.25;\n';
+ if (vecLen >= 4) op += ' tmp[ui_three] = coords.w * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) {
+ op += ' for (int i = 0; i < ' + vecLen + '; i++)\n';
+ op += ' {\n';
+ op += ' tmp[i] = coords.x;\n';
+ op += ' coords = coords.${ROT_SWIZZLE} * 0.5;\n';
+ op += ' }\n';
+ }
+ else {
+ assertMsgOptions(writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'writeAccess not supported.', false, true);
+ op += ' for (int i = 0; i < ' + vecLenName + '; i++)\n';
+ op += ' {\n';
+ op += ' tmp[i] = coords.x;\n';
+ op += ' coords = coords.${ROT_SWIZZLE} * 0.5;\n';
+ op += ' }\n';
+ }
+
+ // Read vector.
+ op += ' ${PRECISION} float res = 0.0;\n';
+ if (readAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT)
+ op += ' res = dot(tmp, ${VAR_TYPE}(1.0));\n';
+ else if (readAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) {
+ op += ' res += tmp.x;\n';
+ if (vecLen >= 2) op += ' res += tmp.y;\n';
+ if (vecLen >= 3) op += ' res += tmp.z;\n';
+ if (vecLen >= 4) op += ' res += tmp.w;\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) {
+ op += ' res += tmp[0];\n';
+ if (vecLen >= 2) op += ' res += tmp[1];\n';
+ if (vecLen >= 3) op += ' res += tmp[2];\n';
+ if (vecLen >= 4) op += ' res += tmp[3];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) {
+ op += ' res += tmp[ui_zero];\n';
+ if (vecLen >= 2) op += ' res += tmp[ui_one];\n';
+ if (vecLen >= 3) op += ' res += tmp[ui_two];\n';
+ if (vecLen >= 4) op += ' res += tmp[ui_three];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) {
+ op += ' for (int i = 0; i < ' + vecLen + '; i++)\n';
+ op += ' res += tmp[i];\n';
+ }
+ else {
+ assertMsgOptions(readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'readAccess not supported', false, true);
+ op += ' for (int i = 0; i < ' + vecLenName + '; i++)\n';
+ op += ' res += tmp[i];\n';
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ vtx += ' v_color = vec3(res);\n';
+ frag += ' o_color = vec4(v_color.rgb, 1.0);\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(vec3(res), 1.0);\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Fill in shader templates.
+ /** @type {Array<string>} */ var s_swizzles = ['', 'x', 'xy', 'xyz', 'xyzw'];
+ /** @type {Array<string>} */ var s_rotSwizzles = ['', 'x', 'yx', 'yzx', 'yzwx'];
+
+ /** @type {Object} */ var params = {};
+ params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType);
+ params["PRECISION"] = "mediump";
+ params["SWIZZLE"] = s_swizzles[vecLen];
+ params["ROT_SWIZZLE"] = s_rotSwizzles[vecLen];
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
+ var evalFunc = es3fShaderIndexingTests.getVectorSubscriptEvalFunc(varType);
+ return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
+ };
+
+ // MATRIX SUBSCRIPT.
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat2 = function(c) {
+ var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
+ var swizzle12 = deMath.swizzle(c.coords, [1, 2]);
+ c.color[0] = swizzle01[0] + 0.5 * swizzle12[0];
+ c.color[1] = swizzle01[1] + 0.5 * swizzle12[1];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat2x3 = function(c) {
+ var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
+ var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]);
+ c.color[0] = swizzle012[0] + 0.5 * swizzle123[0];
+ c.color[1] = swizzle012[1] + 0.5 * swizzle123[1];
+ c.color[2] = swizzle012[2] + 0.5 * swizzle123[2];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat2x4 = function(c) {
+ c.color = deMath.add(
+ deMath.swizzle(c.coords, [0,1,2,3]),
+ deMath.scale(deMath.swizzle(c.coords, [1,2,3,0]), 0.5));
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat3x2 = function(c) {
+ var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
+ var swizzle12 = deMath.swizzle(c.coords, [1, 2]);
+ var swizzle23 = deMath.swizzle(c.coords, [2, 3]);
+ c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0];
+ c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat3 = function(c) {
+ var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
+ var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]);
+ var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]);
+ c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0];
+ c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1];
+ c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat3x4 = function(c) {
+ var swizzle0123 = deMath.swizzle(c.coords, [0, 1, 2, 3]);
+ var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]);
+ var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]);
+ c.color = deMath.add(
+ swizzle0123,
+ deMath.add(
+ deMath.scale(swizzle1230, 0.5),
+ deMath.scale(swizzle2301, 0.25)));
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat4x2 = function(c) {
+ var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
+ var swizzle12 = deMath.swizzle(c.coords, [1, 2]);
+ var swizzle23 = deMath.swizzle(c.coords, [2, 3]);
+ var swizzle30 = deMath.swizzle(c.coords, [3, 0]);
+ c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0] + 0.125 * swizzle30[0];
+ c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1] + 0.125 * swizzle30[1];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat4x3 = function(c) {
+ var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
+ var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]);
+ var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]);
+ var swizzle301 = deMath.swizzle(c.coords, [3, 0, 1]);
+ c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0] + 0.125 * swizzle301[0];
+ c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1] + 0.125 * swizzle301[1];
+ c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2] + 0.125 * swizzle301[2];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ es3fShaderIndexingTests.evalSubscriptMat4 = function(c) {
+ var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]);
+ var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]);
+ var swizzle3012 = deMath.swizzle(c.coords, [3, 0, 1, 2]);
+ c.color = deMath.add(
+ c.coords,
+ deMath.add(
+ deMath.scale(swizzle1230, 0.5),
+ deMath.add(
+ deMath.scale(swizzle2301, 0.25),
+ deMath.scale(swizzle3012, 0.125))));
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} dataType
+ * @return {function(glsShaderRenderCase.ShaderEvalContext)}
+ */
+ es3fShaderIndexingTests.getMatrixSubscriptEvalFunc = function(dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.FLOAT_MAT2: return es3fShaderIndexingTests.evalSubscriptMat2;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return es3fShaderIndexingTests.evalSubscriptMat2x3;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return es3fShaderIndexingTests.evalSubscriptMat2x4;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return es3fShaderIndexingTests.evalSubscriptMat3x2;
+ case gluShaderUtil.DataType.FLOAT_MAT3: return es3fShaderIndexingTests.evalSubscriptMat3;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return es3fShaderIndexingTests.evalSubscriptMat3x4;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return es3fShaderIndexingTests.evalSubscriptMat4x2;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return es3fShaderIndexingTests.evalSubscriptMat4x3;
+ case gluShaderUtil.DataType.FLOAT_MAT4: return es3fShaderIndexingTests.evalSubscriptMat4;
+ default:
+ throw new Error('Invalid data type.');
+ }
+ };
+
+ /**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {gluShaderUtil.DataType} varType
+ * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess
+ * @param {es3fShaderIndexingTests.IndexAccessType} readAccess
+ * @return {es3fShaderIndexingTests.ShaderIndexingCase}
+ */
+ es3fShaderIndexingTests.createMatrixSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(varType);
+ /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(varType);
+ /** @type {string} */ var matSizeName = glsShaderRenderCase.getIntUniformName(numCols);
+ /** @type {gluShaderUtil.DataType} */ var vecType = gluShaderUtil.getDataTypeFloatVec(numRows);
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (isVertexCase) {
+ vtx += 'out mediump vec4 v_color;\n';
+ frag += 'in mediump vec4 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+ }
+
+ if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ op += 'uniform mediump int ui_zero';
+ if (numCols >= 2) op += ', ui_one';
+ if (numCols >= 3) op += ', ui_two';
+ if (numCols >= 4) op += ', ui_three';
+ op += ';\n';
+ }
+
+ if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
+ op += 'uniform mediump int ' + matSizeName + ';\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ vtx += '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n';
+
+ frag += '\n' +
+ 'void main()\n' +
+ '{\n';
+
+ // Write matrix.
+ if (isVertexCase)
+ op += ' ${PRECISION} vec4 coords = a_coords;\n';
+ else
+ op += ' ${PRECISION} vec4 coords = v_coords;\n';
+
+ op += ' ${PRECISION} ${MAT_TYPE} tmp;\n';
+ if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ op += ' tmp[0] = ${VEC_TYPE}(coords);\n';
+ if (numCols >= 2) op += ' tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n';
+ if (numCols >= 3) op += ' tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n';
+ if (numCols >= 4) op += ' tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ op += ' tmp[ui_zero] = ${VEC_TYPE}(coords);\n';
+ if (numCols >= 2) op += ' tmp[ui_one] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n';
+ if (numCols >= 3) op += ' tmp[ui_two] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n';
+ if (numCols >= 4) op += ' tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n';
+ }
+ else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ op += ' for (int i = 0; i < ' + numCols + '; i++)\n';
+ op += ' {\n';
+ op += ' tmp[i] = ${VEC_TYPE}(coords);\n';
+ op += ' coords = coords.yzwx * 0.5;\n';
+ op += ' }\n';
+ }
+ else {
+ assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true);
+ op += ' for (int i = 0; i < ' + matSizeName + '; i++)\n';
+ op += ' {\n';
+ op += ' tmp[i] = ${VEC_TYPE}(coords);\n';
+ op += ' coords = coords.yzwx * 0.5;\n';
+ op += ' }\n';
+ }
+
+ // Read matrix.
+ op += ' ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n';
+ if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
+ op += ' res += tmp[0];\n';
+ if (numCols >= 2) op += ' res += tmp[1];\n';
+ if (numCols >= 3) op += ' res += tmp[2];\n';
+ if (numCols >= 4) op += ' res += tmp[3];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
+ op += ' res += tmp[ui_zero];\n';
+ if (numCols >= 2) op += ' res += tmp[ui_one];\n';
+ if (numCols >= 3) op += ' res += tmp[ui_two];\n';
+ if (numCols >= 4) op += ' res += tmp[ui_three];\n';
+ }
+ else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
+ op += ' for (int i = 0; i < ' + numCols + '; i++)\n';
+ op += ' res += tmp[i];\n';
+ }
+ else {
+ assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported', false, true);
+ op += ' for (int i = 0; i < ' + matSizeName + '; i++)\n';
+ op += ' res += tmp[i];\n';
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ vtx += ' v_color = vec4(res${PADDING});\n';
+ frag += ' o_color = v_color;\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res${PADDING});\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Fill in shader templates.
+
+ /** @type {Object} */ var params = {};
+ params['MAT_TYPE'] = gluShaderUtil.getDataTypeName(varType);
+ params['VEC_TYPE'] = gluShaderUtil.getDataTypeName(vecType);
+ params['PRECISION'] = "mediump";
+
+
+ if (numRows === 2)
+ params['PADDING'] = ', 0.0, 1.0';
+ else if (numRows === 3)
+ params['PADDING'] = ', 1.0';
+ else
+ params['PADDING'] = '';
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
+ var evalFunc = es3fShaderIndexingTests.getMatrixSubscriptEvalFunc(varType);
+ return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderIndexingTests.ShaderIndexingTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'indexing', 'Indexing Tests');
+ };
+
+ es3fShaderIndexingTests.ShaderIndexingTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderIndexingTests.ShaderIndexingTests.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingTests;
+
+ es3fShaderIndexingTests.ShaderIndexingTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [
+ gluShaderProgram.shaderType.VERTEX,
+ gluShaderProgram.shaderType.FRAGMENT
+ ];
+ /** @type {Array<gluShaderUtil.DataType>} */ var s_floatAndVecTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4
+ ];
+ /** @type {string} */ var name;
+ /** @type {string} */ var desc;
+ /** @type {string} */ var shaderTypeName;
+ /** @type {boolean} */ var isVertexCase;
+ /** @type {gluShaderProgram.shaderType} */ var shaderType;
+ /** @type {string} */ var writeAccessName;
+ /** @type {string} */ var readAccessName;
+ // Varying array access cases.
+ /** @type {tcuTestCase.DeqpTest} */ var varyingGroup = tcuTestCase.newTest('varying_array', 'Varying array access tests.');
+ testGroup.addChild(varyingGroup);
+ /** @type {gluShaderUtil.DataType} */ var varType;
+ for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) {
+ varType = s_floatAndVecTypes[typeNdx];
+ for (var vertAccessStr in es3fShaderIndexingTests.IndexAccessType) {
+ for (var fragAccessStr in es3fShaderIndexingTests.IndexAccessType) {
+ var vertAccess = es3fShaderIndexingTests.IndexAccessType[vertAccessStr];
+ var fragAccess = es3fShaderIndexingTests.IndexAccessType[fragAccessStr];
+ /** @type {string} */ var vertAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(vertAccess);
+ /** @type {string} */ var fragAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(fragAccess);
+ name = gluShaderUtil.getDataTypeName(varType) + '_' + vertAccessName + '_write_' + fragAccessName + '_read';
+ desc = 'Varying array with ' + vertAccessName + ' write in vertex shader and ' + fragAccessName + ' read in fragment shader.';
+ varyingGroup.addChild(es3fShaderIndexingTests.createVaryingArrayCase(name, desc, varType, vertAccess, fragAccess));
+ }
+ }
+ }
+
+ // Uniform array access cases.
+ /** @type {tcuTestCase.DeqpTest} */ var uniformGroup = tcuTestCase.newTest("uniform_array", "Uniform array access tests.");
+ testGroup.addChild(uniformGroup);
+
+ for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) {
+ varType = s_floatAndVecTypes[typeNdx];
+ for (var readAccessStr in es3fShaderIndexingTests.IndexAccessType) {
+ var readAccess = es3fShaderIndexingTests.IndexAccessType[readAccessStr];
+ readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(readAccess);
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ name = gluShaderUtil.getDataTypeName(varType) + "_" + readAccessName + "_read_" + shaderTypeName;
+ desc = "Uniform array with " + readAccessName + " read in " + shaderTypeName + " shader.";
+ isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
+ uniformGroup.addChild(es3fShaderIndexingTests.createUniformArrayCase(name, desc, isVertexCase, varType, readAccess));
+ }
+ }
+ }
+
+ // Temporary array access cases.
+ /** @type {tcuTestCase.DeqpTest} */ var tmpGroup = tcuTestCase.newTest("tmp_array", "Temporary array access tests.");
+ testGroup.addChild(tmpGroup);
+
+ for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) {
+ varType = s_floatAndVecTypes[typeNdx];
+ for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) {
+ for (var readAccess in es3fShaderIndexingTests.IndexAccessType) {
+ writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]);
+ readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]);
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
+ desc = "Temporary array with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
+ isVertexCase = (shaderType === gluShaderProgram.shaderType.VERTEX);
+ tmpGroup.addChild(es3fShaderIndexingTests.createTmpArrayCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess]));
+ }
+ }
+ }
+ }
+
+ // Vector indexing with subscripts.
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var s_vectorTypes = [
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4
+ ];
+
+ for (var typeNdx = 0; typeNdx < s_vectorTypes.length; typeNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */ var vecGroup = tcuTestCase.newTest("vector_subscript", "Vector subscript indexing.");
+ testGroup.addChild(vecGroup);
+
+ varType = s_vectorTypes[typeNdx];
+ for (var writeAccess in es3fShaderIndexingTests.VectorAccessType) {
+ for (var readAccess in es3fShaderIndexingTests.VectorAccessType) {
+ writeAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[writeAccess]);
+ readAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[readAccess]);
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
+ desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
+ isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
+ vecGroup.addChild(es3fShaderIndexingTests.createVectorSubscriptCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.VectorAccessType[writeAccess], es3fShaderIndexingTests.VectorAccessType[readAccess]));
+ }
+ }
+ }
+ }
+
+ // Matrix indexing with subscripts.
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var matGroup = [
+ tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."),
+ tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."),
+ tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."),
+ ];
+ for (var ii = 0; ii < matGroup.length; ++ii) {
+ testGroup.addChild(matGroup[ii]);
+ }
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var s_matrixTypes = [
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3,
+ gluShaderUtil.DataType.FLOAT_MAT4
+ ];
+
+ for (var typeNdx = 0; typeNdx < s_matrixTypes.length; typeNdx++) {
+ varType = s_matrixTypes[typeNdx];
+ for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) {
+ for (var readAccess in es3fShaderIndexingTests.IndexAccessType) {
+ writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]);
+ readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]);
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
+ desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
+ isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
+ matGroup[typeNdx % matGroup.length].addChild(es3fShaderIndexingTests.createMatrixSubscriptCase(
+ name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess]));
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderIndexingTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderIndexingTests.ShaderIndexingTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderIndexingTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js
new file mode 100644
index 0000000000..822b121bda
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js
@@ -0,0 +1,1251 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderLoopTests');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('modules.shared.glsShaderRenderCase');
+
+goog.scope(function() {
+var es3fShaderLoopTests = functional.gles3.es3fShaderLoopTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var deMath = framework.delibs.debase.deMath;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+var tcuStringTemplate = framework.common.tcuStringTemplate;
+// Repeated with for, while, do-while. Examples given as 'for' loops.
+// Repeated for const, uniform, dynamic loops.
+
+/**
+ * @enum {number}
+ */
+es3fShaderLoopTests.LoopCase = {
+ LOOPCASE_EMPTY_BODY: 0, // for (...) { }
+ LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST: 1, // for (...) { break; <body>; }
+ LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST: 2, // for (...) { <body>; break; }
+ LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK: 3, // for (...) { <body>; if (cond) break; }
+ LOOPCASE_SINGLE_STATEMENT: 4, // for (...) statement;
+ LOOPCASE_COMPOUND_STATEMENT: 5, // for (...) { statement; statement; }
+ LOOPCASE_SEQUENCE_STATEMENT: 6, // for (...) statement, statement;
+ LOOPCASE_NO_ITERATIONS: 7, // for (i=0; i<0; i++) ...
+ LOOPCASE_SINGLE_ITERATION: 8, // for (i=0; i<1; i++) ...
+ LOOPCASE_SELECT_ITERATION_COUNT: 9, // for (i=0; i<a?b:c; i++) ...
+ LOOPCASE_CONDITIONAL_CONTINUE: 10, // for (...) { if (cond) continue; }
+ LOOPCASE_UNCONDITIONAL_CONTINUE: 11, // for (...) { <body>; continue; }
+ LOOPCASE_ONLY_CONTINUE: 12, // for (...) { continue; }
+ LOOPCASE_DOUBLE_CONTINUE: 13, // for (...) { if (cond) continue; <body>; continue; }
+ LOOPCASE_CONDITIONAL_BREAK: 14, // for (...) { if (cond) break; }
+ LOOPCASE_UNCONDITIONAL_BREAK: 15, // for (...) { <body>; break; }
+ LOOPCASE_PRE_INCREMENT: 16, // for (...; ++i) { <body>; }
+ LOOPCASE_POST_INCREMENT: 17, // for (...; i++) { <body>; }
+ LOOPCASE_MIXED_BREAK_CONTINUE: 18,
+ LOOPCASE_VECTOR_COUNTER: 19, // for (ivec3 ndx = ...; ndx.x < ndx.y; ndx.x += ndx.z) { ... }
+ LOOPCASE_101_ITERATIONS: 20, // loop for 101 iterations
+ LOOPCASE_SEQUENCE: 21, // two loops in sequence
+ LOOPCASE_NESTED: 22, // two nested loops
+ LOOPCASE_NESTED_SEQUENCE: 23, // two loops in sequence nested inside a third
+ LOOPCASE_NESTED_TRICKY_DATAFLOW_1: 24, // nested loops with tricky data flow
+ LOOPCASE_NESTED_TRICKY_DATAFLOW_2: 25 // nested loops with tricky data flow
+};
+
+/**
+ * @param {es3fShaderLoopTests.LoopCase} loopCase
+ * @return {string}
+ */
+es3fShaderLoopTests.getLoopCaseName = function(loopCase) {
+ /** @type {Array<string>} */ var s_names = [
+ 'empty_body',
+ 'infinite_with_unconditional_break_first',
+ 'infinite_with_unconditional_break_last',
+ 'infinite_with_conditional_break',
+ 'single_statement',
+ 'compound_statement',
+ 'sequence_statement',
+ 'no_iterations',
+ 'single_iteration',
+ 'select_iteration_count',
+ 'conditional_continue',
+ 'unconditional_continue',
+ 'only_continue',
+ 'double_continue',
+ 'conditional_break',
+ 'unconditional_break',
+ 'pre_increment',
+ 'post_increment',
+ 'mixed_break_continue',
+ 'vector_counter',
+ '101_iterations',
+ 'sequence',
+ 'nested',
+ 'nested_sequence',
+ 'nested_tricky_dataflow_1',
+ 'nested_tricky_dataflow_2'
+ ];
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == es3fShaderLoopTests.LoopCase.LOOPCASE_LAST);
+ // DE_ASSERT(deInBounds32((int)loopCase, 0, LOOPCASE_LAST));
+ return s_names[loopCase];
+};
+
+// Complex loop cases.
+
+/*enum LoopBody
+{
+ LOOPBODY_READ_UNIFORM = 0,
+ LOOPBODY_READ_UNIFORM_ARRAY,
+ LOOPBODY_READ_
+};*/
+
+/**
+ * @enum {number}
+ */
+es3fShaderLoopTests.LoopType = {
+ LOOPTYPE_FOR: 0,
+ LOOPTYPE_WHILE: 1,
+ LOOPTYPE_DO_WHILE: 2
+};
+
+/**
+ * @param {es3fShaderLoopTests.LoopType} loopType
+ * @return {string}
+ */
+es3fShaderLoopTests.getLoopTypeName = function(loopType) {
+ /** @type {Array<string>} */ var s_names = [
+ 'for',
+ 'while',
+ 'do_while'
+ ];
+
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) === es3fShaderLoopTests.LoopType.LOOPTYPE_LAST);
+ // DE_ASSERT(deInBounds32((int)loopType, 0, LOOPTYPE_LAST));
+ return s_names[loopType];
+};
+
+/**
+ * @enum {number}
+ */
+es3fShaderLoopTests.LoopCountType = {
+ LOOPCOUNT_CONSTANT: 0,
+ LOOPCOUNT_UNIFORM: 1,
+ LOOPCOUNT_DYNAMIC: 2
+};
+
+/**
+ * @param {es3fShaderLoopTests.LoopCountType} countType
+ * @return {string}
+ */
+es3fShaderLoopTests.getLoopCountTypeName = function(countType) {
+ /** @type {Array<string>} */ var s_names = [
+ 'constant',
+ 'uniform',
+ 'dynamic'
+ ];
+
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == es3fShaderLoopTests.LoopCountType.LOOPCOUNT_LAST);
+ // DE_ASSERT(deInBounds32((int)countType, 0, es3fShaderLoopTests.LoopCountType.LOOPCOUNT_LAST));
+ return s_names[countType];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop0Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [0, 1, 2]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop1Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [1, 2, 3]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop2Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [2, 3, 0]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop3Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [3, 0, 1]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {number} numIters
+ * @return {glsShaderRenderCase.ShaderEvalFunc}
+ */
+es3fShaderLoopTests.getLoopEvalFunc = function(numIters) {
+ switch (numIters % 4) {
+ case 0: return es3fShaderLoopTests.evalLoop0Iters;
+ case 1: return es3fShaderLoopTests.evalLoop1Iters;
+ case 2: return es3fShaderLoopTests.evalLoop2Iters;
+ case 3: return es3fShaderLoopTests.evalLoop3Iters;
+ }
+
+ throw new Error('Invalid loop iteration count.');
+};
+
+// ShaderLoopCase
+
+/**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ * @param {string} vertShaderSource
+ * @param {string} fragShaderSource
+ */
+es3fShaderLoopTests.ShaderLoopCase = function(name, description, isVertexCase, evalFunc, vertShaderSource, fragShaderSource) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
+ /** @type {string} */ this.m_vertShaderSource = vertShaderSource;
+ /** @type {string} */ this.m_fragShaderSource = fragShaderSource;
+};
+
+es3fShaderLoopTests.ShaderLoopCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+es3fShaderLoopTests.ShaderLoopCase.prototype.constructor = es3fShaderLoopTests.ShaderLoopCase;
+
+// Test case creation.
+
+/**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {es3fShaderLoopTests.LoopType} loopType
+ * @param {es3fShaderLoopTests.LoopCountType} loopCountType
+ * @param {gluShaderUtil.precision} loopCountPrecision
+ * @param {gluShaderUtil.DataType} loopCountDataType
+ * @return {es3fShaderLoopTests.ShaderLoopCase}
+ */
+es3fShaderLoopTests.createGenericLoopCase = function(caseName, description, isVertexCase, loopType, loopCountType, loopCountPrecision, loopCountDataType) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n';
+ vtx += 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += 'in mediump float a_one;\n';
+
+ if (isVertexCase) {
+ vtx += 'out mediump vec3 v_color;\n';
+ frag += 'in mediump vec3 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ vtx += 'out mediump float v_one;\n';
+ frag += 'in mediump float v_one;\n';
+ }
+ }
+
+ // \todo [petri] Pass numLoopIters from outside?
+ /** @type {number} */ var numLoopIters = 3;
+ /** @type {boolean} */ var isIntCounter = gluShaderUtil.isDataTypeIntOrIVec(loopCountDataType);
+
+ if (isIntCounter) {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM || loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ op += 'uniform ${COUNTER_PRECISION} int ' + glsShaderRenderCase.getIntUniformName(numLoopIters) + ';\n';
+ }
+ else {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM || loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ op += 'uniform ${COUNTER_PRECISION} float ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters) + ';\n';
+
+ if (numLoopIters != 1)
+ op += 'uniform ${COUNTER_PRECISION} float uf_one;\n';
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ vtx += "\n" +
+ "void main()\n" +
+ "{\n" +
+ " gl_Position = a_position;\n";
+
+ frag += "\n" +
+ "void main()\n" +
+ "{\n";
+
+ if (isVertexCase)
+ vtx += ' ${PRECISION} vec4 coords = a_coords;\n';
+ else
+ frag += ' ${PRECISION} vec4 coords = v_coords;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ if (isIntCounter) {
+ if (isVertexCase)
+ vtx += ' ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n';
+ else
+ frag += ' ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n';
+ }
+ else {
+ if (isVertexCase)
+ vtx += ' ${COUNTER_PRECISION} float one = a_one;\n';
+ else
+ frag += ' ${COUNTER_PRECISION} float one = v_one;\n';
+ }
+ }
+
+ // Read array.
+ op += ' ${PRECISION} vec4 res = coords;\n';
+
+ // Loop iteration count.
+ /** @type {string} */ var iterMaxStr;
+
+ if (isIntCounter) {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ iterMaxStr = numLoopIters.toString();
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ iterMaxStr = glsShaderRenderCase.getIntUniformName(numLoopIters);
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ iterMaxStr = glsShaderRenderCase.getIntUniformName(numLoopIters) + '*one';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+ else {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ iterMaxStr = '1.0';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ iterMaxStr = 'uf_one';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ iterMaxStr = 'uf_one*one';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+
+ // Loop operations.
+ /** @type {string} */ var initValue = isIntCounter ? '0' : '0.05';
+ /** @type {string} */ var loopCountDeclStr = '' + gluShaderUtil.getPrecisionName(loopCountPrecision) + ' ' + gluShaderUtil.getDataTypeName(loopCountDataType) + ' ndx = ' + initValue;
+ /** @type {string} */ var loopCmpStr = 'ndx < ' + iterMaxStr;
+ /** @type {string} */ var incrementStr;
+
+ if (isIntCounter)
+ incrementStr = 'ndx++';
+ else {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ incrementStr = 'ndx += ' + (1.0 / numLoopIters);
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ incrementStr = 'ndx += ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters);
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ incrementStr = 'ndx += ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters) + '*one';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+
+ // Loop body.
+ /** @type {string} */ var loopBody = ' res = res.yzwx;\n';;
+
+ if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_FOR) {
+ op += ' for (' + loopCountDeclStr + '; ' + loopCmpStr + '; ' + incrementStr + ')\n' +
+ ' {\n' +
+ loopBody +
+ ' }\n';
+ }
+ else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_WHILE) {
+ op += '\t' + loopCountDeclStr + ';\n' +
+ ' while (' + loopCmpStr + ')\n' +
+ ' {\n' +
+ loopBody +
+ '\t\t' + incrementStr + ';\n' +
+ ' }\n';
+ }
+ else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE)
+ {
+ op += '\t' + loopCountDeclStr + ';\n' +
+ ' do\n' +
+ ' {\n' +
+ loopBody +
+ '\t\t' + incrementStr + ';\n' +
+ ' } while (' + loopCmpStr + ');\n';
+ }
+ else
+ throw new Error('Loop Type not supported: ' + loopType);
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ vtx += ' v_color = res.rgb;\n';
+ frag += ' o_color = vec4(v_color.rgb, 1.0);\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res.rgb, 1.0);\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += ' v_one = a_one;\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params['LOOP_VAR_TYPE'] = gluShaderUtil.getDataTypeName(loopCountDataType);
+ params['PRECISION'] = 'mediump';
+ params['COUNTER_PRECISION'] = gluShaderUtil.getPrecisionName(loopCountPrecision);
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ // Create the case.
+ /** @type {glsShaderRenderCase.ShaderEvalFunc} */
+ var evalFunc = es3fShaderLoopTests.getLoopEvalFunc(numLoopIters);
+ return new es3fShaderLoopTests.ShaderLoopCase(caseName, description, isVertexCase, evalFunc, vertexShaderSource, fragmentShaderSource);
+};
+
+// \todo [petri] Generalize to float as well?
+
+/**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {es3fShaderLoopTests.LoopCase} loopCase
+ * @param {es3fShaderLoopTests.LoopType} loopType
+ * @param {es3fShaderLoopTests.LoopCountType} loopCountType
+ * @return {es3fShaderLoopTests.ShaderLoopCase}
+ */
+es3fShaderLoopTests.createSpecialLoopCase = function(caseName, description, isVertexCase, loopCase, loopType, loopCountType) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n';
+ vtx += 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += 'in mediump float a_one;\n';
+
+ // Attribute and varyings.
+ if (isVertexCase) {
+ vtx += 'out mediump vec3 v_color;\n';
+ frag += 'in mediump vec3 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ vtx += 'out mediump float v_one;\n';
+ frag += 'in mediump float v_one;\n';
+ }
+ }
+
+ if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT)
+ op += 'uniform bool ub_true;\n';
+
+ op += 'uniform ${COUNTER_PRECISION} int ui_zero, ui_one, ui_two, ui_three, ui_four, ui_five, ui_six;\n';
+ if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS)
+ op += 'uniform ${COUNTER_PRECISION} int ui_oneHundredOne;\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ /** @type {number} */ var iterCount = 3; // value to use in loop
+ /** @type {number} */ var numIters = 3; // actual number of iterations
+
+ vtx += '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n';
+
+ frag += '\n' +
+ 'void main()\n' +
+ '{\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ if (isVertexCase)
+ vtx += ' ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n';
+ else
+ frag += ' ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n';
+ }
+
+ if (isVertexCase)
+ vtx += ' ${PRECISION} vec4 coords = a_coords;\n';
+ else
+ frag += ' ${PRECISION} vec4 coords = v_coords;\n';
+
+ // Read array.
+ op += ' ${PRECISION} vec4 res = coords;\n';
+
+ // Handle all loop types.
+ /** @type {string} */ var counterPrecisionStr = 'mediump';
+ /** @type {string} */ var forLoopStr = '';
+ /** @type {string} */ var whileLoopStr = '';
+ /** @type {string} */ var doWhileLoopPreStr = '';
+ /** @type {string} */ var doWhileLoopPostStr = '';
+
+ if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_FOR) {
+ switch (loopCase) {
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
+ numIters = 0;
+ op += ' ${FOR_LOOP} {}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
+ numIters = 0;
+ op += ' for (;;) { break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
+ numIters = 1;
+ op += ' for (;;) { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' for (;;) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${FOR_LOOP} { res = res.yzwx; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${FOR_LOOP} res = res.yzwx, res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
+ iterCount = 0;
+ numIters = 0;
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
+ iterCount = 1;
+ numIters = 1;
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
+ op += ' for (int i = 0; i < (ub_true ? ${ITER_COUNT} : 0); i++) res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
+ op += ' ${FOR_LOOP} { res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
+ numIters = 0;
+ op += ' ${FOR_LOOP} { continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
+ numIters = 1;
+ op += ' ${FOR_LOOP} { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
+ op += ' for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
+ op += ' ${FOR_LOOP} { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
+ numIters = 2;
+ iterCount = 5;
+ op += ' ${FOR_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
+ op += ' for (${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0); i.x < i.z; i.x += i.y) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
+ numIters = iterCount = 101;
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
+ iterCount = 5;
+ numIters = 5;
+ op += ' ${COUNTER_PRECISION} int i;\n' +
+ ' for (i = 0; i < ${TWO}; i++) { res = res.yzwx; }\n' +
+ ' for (; i < ${ITER_COUNT}; i++) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
+ numIters = 2 * iterCount;
+ op += ' for (${COUNTER_PRECISION} int i = 0; i < ${TWO}; i++)\n' +
+ ' {\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${ITER_COUNT}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
+ numIters = 3 * iterCount;
+ op += ' for (${COUNTER_PRECISION} int i = 0; i < ${ITER_COUNT}; i++)\n' +
+ ' {\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${ONE}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
+ numIters = 2;
+ op += ' ${FOR_LOOP}\n' +
+ ' {\n' +
+ ' res = coords; // ignore outer loop effect \n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
+ numIters = iterCount;
+ op += ' ${FOR_LOOP}\n' +
+ ' {\n' +
+ ' res = coords.wxyz;\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' coords = res;\n' +
+ ' }\n';
+ break;
+
+ default:
+ throw new Error('Case not supported: ' + loopCase);
+ }
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < ' + iterCount + '; i++)';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < ' + glsShaderRenderCase.getIntUniformName(iterCount) + '; i++)';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + '; i++)';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+ else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_WHILE) {
+ switch (loopCase) {
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
+ numIters = 0;
+ op += ' ${WHILE_LOOP} {}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
+ numIters = 0;
+ op += ' while (true) { break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
+ numIters = 1;
+ op += ' while (true) { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (true) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${WHILE_LOOP} { res = res.yzwx; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${WHILE_LOOP} res = res.yzwx, res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
+ iterCount = 0;
+ numIters = 0;
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
+ iterCount = 1;
+ numIters = 1;
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i < (ub_true ? ${ITER_COUNT} : 0)) { res = res.yzwx; i++; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${WHILE_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
+ op += ' ${WHILE_LOOP} { res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
+ numIters = 0;
+ op += ' ${WHILE_LOOP} { continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${WHILE_LOOP} { if (i == ${ONE}) continue; res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
+ numIters = 1;
+ op += ' ${WHILE_LOOP} { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
+ numIters = iterCount - 1;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (++i < ${ITER_COUNT}) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
+ numIters = 2;
+ iterCount = 5;
+ op += ' ${WHILE_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
+ op += ' ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n' +
+ ' while (i.x < i.z) { res = res.yzwx; i.x += i.y; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
+ numIters = iterCount = 101;
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
+ iterCount = 6;
+ numIters = iterCount - 1;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${TWO}) { res = res.yzwx; }\n' +
+ ' while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n'; // \note skips one iteration
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
+ numIters = 2 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${TWO})\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${ITER_COUNT})\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
+ numIters = 2 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${ITER_COUNT})\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${ONE})\n' +
+ ' res = res.yzwx;\n' +
+ ' while (j++ < ${THREE})\n' + // \note skips one iteration
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
+ numIters = 2;
+ op += ' ${WHILE_LOOP}\n' +
+ ' {\n' +
+ ' res = coords; // ignore outer loop effect \n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${TWO})\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
+ numIters = iterCount;
+ op += ' ${WHILE_LOOP}\n' +
+ ' {\n' +
+ ' res = coords.wxyz;\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${TWO})\n' +
+ ' res = res.yzwx;\n' +
+ ' coords = res;\n' +
+ ' }\n';
+ break;
+
+ default:
+ throw new Error('Loop Case not supported: ' + loopCase);
+ }
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + ' while(i++ < ' + iterCount + ')';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + ' while(i++ < ' + glsShaderRenderCase.getIntUniformName(iterCount) + ')';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + ' while(i++ < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + ')';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+ else {
+ assertMsgOptions(loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE, 'Expected LOOPTYPE_DO_WHILE', false, true);
+
+ switch (loopCase) {
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
+ numIters = 0;
+ op += ' ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
+ numIters = 0;
+ op += ' do { break; res = res.yzwx; } while (true);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
+ numIters = 1;
+ op += ' do { res = res.yzwx; break; } while (true);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; if (i == ${ONE}) break; i++; } while (true);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
+ op += ' ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; res = res.yzwx; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${DO_WHILE_PRE} res = res.yzwx, res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
+ //assertMsgOptions(false, 'LOOPCASE_NO_ITERATIONS', false, false);
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
+ iterCount = 1;
+ numIters = 1;
+ op += ' ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (++i < (ub_true ? ${ITER_COUNT} : 0));\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
+ numIters = 0;
+ op += ' ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; if (i == ${ONE}) break; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
+ numIters = 1;
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; break; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
+ numIters = iterCount + 1;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (i++ < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
+ numIters = 2;
+ iterCount = 5;
+ op += ' ${DO_WHILE_PRE} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
+ op += ' ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n' +
+ ' do { res = res.yzwx; } while ((i.x += i.y) < i.z);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
+ numIters = iterCount = 101;
+ op += ' ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
+ iterCount = 5;
+ numIters = 5;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (++i < ${TWO});\n' +
+ ' do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
+ numIters = 2 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${ITER_COUNT});\n' +
+ ' } while (++i < ${TWO});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
+ numIters = 3 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${TWO});\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${THREE});\n' +
+ ' } while (++i < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
+ numIters = 2;
+ op += ' ${DO_WHILE_PRE}\n' +
+ ' {\n' +
+ ' res = coords; // ignore outer loop effect \n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${TWO});\n' +
+ ' } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
+ numIters = iterCount;
+ op += ' ${DO_WHILE_PRE}\n' +
+ ' {\n' +
+ ' res = coords.wxyz;\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${TWO})\n' +
+ ' res = res.yzwx;\n' +
+ ' coords = res;\n' +
+ ' } ${DO_WHILE_POST}\n';
+ break;
+
+ default:
+ throw new Error('Loop Case not supported: ' + loopCase);
+ }
+
+ doWhileLoopPreStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + '\tdo ';
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ doWhileLoopPostStr = ' while (++i < ' + iterCount + ');\n';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ doWhileLoopPostStr = ' while (++i < ' + glsShaderRenderCase.getIntUniformName(iterCount) + ');\n';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ doWhileLoopPostStr = ' while (++i < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + ');\n';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ // Shader footers.
+ if (isVertexCase) {
+ vtx += ' v_color = res.rgb;\n';
+ frag += ' o_color = vec4(v_color.rgb, 1.0);\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res.rgb, 1.0);\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += ' v_one = a_one;\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Constants.
+ /** @type {string} */ var oneStr = '';
+ /** @type {string} */ var twoStr = '';
+ /** @type {string} */ var threeStr = '';
+ /** @type {string} */ var iterCountStr = '';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT) {
+ oneStr = '1';
+ twoStr = '2';
+ threeStr = '3';
+ iterCountStr = iterCount.toString();
+ }
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM) {
+ oneStr = 'ui_one';
+ twoStr = 'ui_two';
+ threeStr = 'ui_three';
+ iterCountStr = glsShaderRenderCase.getIntUniformName(iterCount);
+ }
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ oneStr = 'one*ui_one';
+ twoStr = 'one*ui_two';
+ threeStr = 'one*ui_three';
+ iterCountStr = 'one*' + glsShaderRenderCase.getIntUniformName(iterCount);
+ }
+ else throw new Error('Loop Count Type not supported: ' + loopCountType);
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params["PRECISION"] = "mediump";
+ params["ITER_COUNT"] = iterCountStr;
+ params["COUNTER_PRECISION"] = counterPrecisionStr;
+ params["FOR_LOOP"] = forLoopStr;
+ params["WHILE_LOOP"] = whileLoopStr;
+ params["DO_WHILE_PRE"] = doWhileLoopPreStr;
+ params["DO_WHILE_POST"] = doWhileLoopPostStr;
+ params["ONE"] = oneStr;
+ params["TWO"] = twoStr;
+ params["THREE"] = threeStr;
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ // Create the case.
+ /** @type {glsShaderRenderCase.ShaderEvalFunc} */
+ var evalFunc = es3fShaderLoopTests.getLoopEvalFunc(numIters);
+ return new es3fShaderLoopTests.ShaderLoopCase(caseName, description, isVertexCase, evalFunc, vertexShaderSource, fragmentShaderSource);
+};
+
+// ShaderLoopTests.
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fShaderLoopTests.ShaderLoopTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'loops', 'Loop Tests');
+};
+
+es3fShaderLoopTests.ShaderLoopTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fShaderLoopTests.ShaderLoopTests.prototype.constructor = es3fShaderLoopTests.ShaderLoopTests;
+
+es3fShaderLoopTests.ShaderLoopTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ // Loop cases.
+
+ /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [
+ gluShaderProgram.shaderType.VERTEX,
+ gluShaderProgram.shaderType.FRAGMENT
+ ];
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var s_countDataType = [
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.FLOAT
+ ];
+
+ /** @type {gluShaderProgram.shaderType} */ var shaderType;
+ /** @type {string} */ var shaderTypeName;
+ /** @type {boolean} */ var isVertexCase;
+ /** @type {string} */ var name;
+ /** @type {string} */ var desc;
+
+ for (var loopType in es3fShaderLoopTests.LoopType) {
+ /** @type {string} */ var loopTypeName = es3fShaderLoopTests.getLoopTypeName(es3fShaderLoopTests.LoopType[loopType]);
+ /** @type {tcuTestCase.DeqpTest} */ var loopTypeGroup = tcuTestCase.newTest(loopTypeName, 'Loop tests with ' + loopTypeName + ' loop type');
+ testGroup.addChild(loopTypeGroup);
+
+ for (var loopCountType in es3fShaderLoopTests.LoopCountType) {
+ /** @type {string} */ var loopCountName = es3fShaderLoopTests.getLoopCountTypeName(es3fShaderLoopTests.LoopCountType[loopCountType]);
+
+ /** @type {string} */ var groupName = loopCountName + '_iterations';
+ /** @type {string} */ var groupDesc = 'Loop tests with ' + loopCountName + ' loop counter.';
+
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(groupName, groupDesc);
+ loopTypeGroup.addChild(group);
+
+ // Generic cases.
+
+ for (var precision in gluShaderUtil.precision) {
+ /** @type {string} */ var precisionName = gluShaderUtil.getPrecisionName(gluShaderUtil.precision[precision]);
+
+ for (var dataTypeNdx = 0; dataTypeNdx < s_countDataType.length; dataTypeNdx++) {
+ /** @type {gluShaderUtil.DataType} */ var loopDataType = s_countDataType[dataTypeNdx];
+ /** @type {string} */ var dataTypeName = gluShaderUtil.getDataTypeName(loopDataType);
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ isVertexCase = (shaderType == gluShaderProgram.shaderType.VERTEX);
+
+
+ name = 'basic_' + precisionName + '_' + dataTypeName + '_' + shaderTypeName;
+ desc = loopTypeName + ' loop with ' + precisionName + dataTypeName + ' ' + loopCountName + ' iteration count in ' + shaderTypeName + ' shader.';
+ group.addChild(es3fShaderLoopTests.createGenericLoopCase(name, desc, isVertexCase, es3fShaderLoopTests.LoopType[loopType], es3fShaderLoopTests.LoopCountType[loopCountType], gluShaderUtil.precision[precision], loopDataType));
+ }
+ }
+ }
+
+ // Special cases.
+
+ for (var loopCase in es3fShaderLoopTests.LoopCase) {
+ /** @type {string} */ var loopCaseName = es3fShaderLoopTests.getLoopCaseName(es3fShaderLoopTests.LoopCase[loopCase]);
+
+ // no-iterations not possible with do-while.
+ if ((es3fShaderLoopTests.LoopCase[loopCase] == es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS) && (es3fShaderLoopTests.LoopType[loopType] == es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE))
+ continue;
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ isVertexCase = (shaderType == gluShaderProgram.shaderType.VERTEX);
+
+ name = loopCaseName + '_' + shaderTypeName;
+ desc = loopCaseName + ' loop with ' + loopTypeName + ' iteration count in ' + shaderTypeName + ' shader.';
+ group.addChild(es3fShaderLoopTests.createSpecialLoopCase(name, desc, isVertexCase, es3fShaderLoopTests.LoopCase[loopCase], es3fShaderLoopTests.LoopType[loopType], es3fShaderLoopTests.LoopCountType[loopCountType]));
+ }
+ }
+ }
+ }
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fShaderLoopTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderLoopTests.ShaderLoopTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderLoopTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderMatrixTest.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderMatrixTest.js
new file mode 100644
index 0000000000..5af21863f5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderMatrixTest.js
@@ -0,0 +1,1852 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fShaderMatrixTest');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('modules.shared.glsShaderRenderCase');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.common.tcuTestCase');
+
+goog.scope(function() {
+
+ var es3fShaderMatrixTest= functional.gles3.es3fShaderMatrixTest;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuTestCase = framework.common.tcuTestCase;
+
+
+ /** @const {Array<number>}*/ var s_constInFloat = [0.5, -0.2];
+ /** @const {Array<Array<number>>}*/ var s_constInVec2 = [[1.2, 0.5], [0.5, 1.0]];
+ /** @const {Array<Array<number>>}*/ var s_constInVec3 = [[1.1, 0.1, 0.5], [-0.2, 0.5, 0.8]];
+ /** @const {Array<Array<number>>}*/ var s_constInVec4 = [[1.4, 0.2, -0.5, 0.7], [0.2, -1.0, 0.5, 0.8]];
+
+ /** @typedef {function(glsShaderRenderCase.ShaderEvalContext)} */ es3fShaderMatrixTest.MatrixShaderEvalFunc;
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat2x2 = [
+ [-0.1, 1.0, -0.2, 0.0],
+ [0.8, 0.1, 0.5, -0.9]
+ ];
+ /** @const {Array<Array<number>>}*/ var s_constInMat3x2 = [
+ [0.8, -0.3, 0.3, 1.0, 1.2, -1.2],
+ [1.2, -1.0, 0.5, -0.8, 1.1, 0.3]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat4x2 = [
+ [-0.2, 0.5, 0.0, -1.0, 1.2, -0.5, 0.3, -0.9],
+ [1.0, 0.1, -1.1, 0.6, 0.8, -1.2, -1.1, 0.7]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat2x3 = [
+ [-0.6, -0.1, -0.7, -1.2, -0.2, 0.0],
+ [1.1, 0.6, 0.8, 1.0, 0.7, 0.1]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat3x3 = [
+ [-0.2, 1.1, 1.2, -1.0, 1.2, 0.5, 0.7, -0.2, 1.0],
+ [-0.1, -0.1, 0.1, -0.1, -0.2, 1.0, -0.5, 0.1, -0.4]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat4x3 = [
+ [-0.9, 0.0, 0.6, 0.2, 0.9, -0.1, -0.3, -0.7, -0.1, 0.1, 1.0, 0.0],
+ [0.5, 0.7, 0.7, 1.2, 1.1, 0.1, 1.0, -1.0, -0.2, -0.2, -0.3, -0.5]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat2x4 = [
+ [-0.6, -1.1, -0.6, -0.6, -0.2, -0.6, -0.1, -0.1],
+ [-1.2, -1.0, 0.7, -1.0, 0.7, 0.7, -0.4, -0.3]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat3x4 = [
+ [0.6, -0.4, 1.2, 0.9, 0.8, 0.4, 1.1, 0.3, 0.5, -0.2, 0.0, 1.1],
+ [-0.8, 1.2, -0.2, -1.1, -0.9, -0.5, -1.2, 1.0, 1.2, 0.1, -0.7, -0.5]
+ ];
+
+ /** @const {Array<Array<number>>}*/ var s_constInMat4x4 = [
+ [0.3, 0.9, -0.2, 1.0, -0.4, -0.6, 0.6, -1.0, -0.9, -0.1, 0.3, -0.2, -0.3, -0.9, 1.0, 0.1],
+ [0.4, -0.7, -0.8, 0.7, -0.4, -0.8, 0.6, -0.3, 0.7, -1.0, 0.1, -0.3, 0.2, 0.6, 0.4, -1.0]
+ ];
+
+ // Operation info
+
+ /**
+ * @enum
+ */
+ es3fShaderMatrixTest.OperationType = {
+ OPERATIONTYPE_BINARY_OPERATOR: 0,
+ OPERATIONTYPE_BINARY_FUNCTION: 1,
+ OPERATIONTYPE_UNARY_PREFIX_OPERATOR: 2,
+ OPERATIONTYPE_UNARY_POSTFIX_OPERATOR: 3,
+ OPERATIONTYPE_UNARY_FUNCTION: 4,
+ OPERATIONTYPE_ASSIGNMENT: 5
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {string}
+ */
+ es3fShaderMatrixTest.getOperationName = function(op) {
+ switch (op) {
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD: return '+';
+ case es3fShaderMatrixTest.MatrixOp.OP_SUB: return '-';
+ case es3fShaderMatrixTest.MatrixOp.OP_MUL: return '*';
+ case es3fShaderMatrixTest.MatrixOp.OP_DIV: return '/';
+ case es3fShaderMatrixTest.MatrixOp.OP_COMP_MUL: return 'matrixCompMult';
+ case es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT: return 'outerProduct';
+ case es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE: return 'transpose';
+ case es3fShaderMatrixTest.MatrixOp.OP_INVERSE: return 'inverse';
+ case es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT: return 'determinant';
+ case es3fShaderMatrixTest.MatrixOp.OP_UNARY_PLUS: return '+';
+ case es3fShaderMatrixTest.MatrixOp.OP_NEGATION: return '-';
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT: return '++';
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT: return '--';
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT: return '++';
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT: return '--';
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO: return '+=';
+ case es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM: return '-=';
+ case es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO: return '*=';
+ case es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO: return '/=';
+ default:
+ throw new Error('Error invalid Matrix Operation');
+ }
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {es3fShaderMatrixTest.OperationType}
+ */
+ es3fShaderMatrixTest.getOperationType = function (op) {
+ switch (op)
+ {
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_SUB: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_MUL: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_DIV: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_COMP_MUL: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_FUNCTION;
+ case es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_FUNCTION;
+ case es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_FUNCTION;
+ case es3fShaderMatrixTest.MatrixOp.OP_INVERSE: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_FUNCTION;
+ case es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_FUNCTION;
+ case es3fShaderMatrixTest.MatrixOp.OP_UNARY_PLUS: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_NEGATION: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT;
+ case es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT;
+ case es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT;
+ case es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO: return es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT;
+ default:
+ throw new Error('Error invalid Matrix Operation');
+ }
+ };
+
+ /**
+ * @enum
+ */
+ es3fShaderMatrixTest.MatrixType = {
+ TESTMATRIXTYPE_DEFAULT: 0,
+ TESTMATRIXTYPE_NEGATED: 1,
+ TESTMATRIXTYPE_INCREMENTED: 2,
+ TESTMATRIXTYPE_DECREMENTED: 3,
+ TESTMATRIXTYPE_NEGATED_INCREMENTED: 4,
+ TESTMATRIXTYPE_INCREMENTED_LESS: 5
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {es3fShaderMatrixTest.MatrixType}
+ */
+ es3fShaderMatrixTest.getOperationTestMatrixType = function (op) {
+ switch(op) {
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_SUB: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_MUL: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_DIV: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_COMP_MUL: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_INVERSE: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_UNARY_PLUS: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DECREMENTED;
+ case es3fShaderMatrixTest.MatrixOp.OP_NEGATION: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_NEGATED_INCREMENTED;
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_NEGATED;
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_INCREMENTED;
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_NEGATED;
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT;
+ case es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_INCREMENTED_LESS;
+ case es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_NEGATED;
+ case es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO: return es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DECREMENTED;
+ default:
+ throw new Error('Error invalid Matrix Operation');
+ }
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationBinary = function (op) {
+ return es3fShaderMatrixTest.getOperationType(op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_OPERATOR ||
+ es3fShaderMatrixTest.getOperationType(op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_FUNCTION ||
+ es3fShaderMatrixTest.getOperationType(op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationMatrixScalar = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_ADD ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_SUB ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_MUL ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_DIV;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationMatrixVector = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_MUL;
+ };
+
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationArithmeticMatrixMatrix = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_MUL;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationComponentwiseMatrixMatrix = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_ADD ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_SUB ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_MUL ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_DIV ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_COMP_MUL;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationVectorVector = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationUnaryAnyMatrix = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_UNARY_PLUS ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_NEGATION ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationUnarySymmetricMatrix = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_INVERSE ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationValueModifying = function (op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationAssignment = function(op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationAssignmentAnyMatrix = function(op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM ||
+ op == es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {boolean}
+ */
+ es3fShaderMatrixTest.isOperationAssignmentSymmetricMatrix = function(op) {
+ return op == es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO;
+ };
+
+ // Operation nature
+
+ /**
+ * @enum
+ */
+ es3fShaderMatrixTest.OperationNature = {
+ OPERATIONNATURE_PURE: 0,
+ OPERATIONNATURE_MUTATING: 1,
+ OPERATIONNATURE_ASSIGNMENT: 2
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @return {es3fShaderMatrixTest.OperationNature}
+ */
+ es3fShaderMatrixTest.getOperationNature = function (op) {
+ if (es3fShaderMatrixTest.isOperationAssignment(op))
+ return es3fShaderMatrixTest.OperationNature.OPERATIONNATURE_ASSIGNMENT;
+ if (es3fShaderMatrixTest.isOperationValueModifying(op))
+ return es3fShaderMatrixTest.OperationNature.OPERATIONNATURE_MUTATING;
+ return es3fShaderMatrixTest.OperationNature.OPERATIONNATURE_PURE;
+ };
+
+ // Input value loader.
+ /**
+ * @param {es3fShaderMatrixTest.InputType} inputType
+ * @param {gluShaderUtil.DataType} typeFormat
+ * @param {glsShaderRenderCase.ShaderEvalContext} evalCtx
+ * @param {number} inputNdx
+ * @return {Array<number>|tcuMatrix.Matrix|number}
+ */
+ es3fShaderMatrixTest.getInputValue = function (inputType, typeFormat, evalCtx, inputNdx) {
+ if (inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_CONST) {
+ switch (typeFormat) {
+ case gluShaderUtil.DataType.FLOAT:
+ return s_constInFloat[inputNdx];
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ return s_constInVec2[inputNdx];
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ return s_constInVec3[inputNdx];
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ return s_constInVec4[inputNdx];
+ case gluShaderUtil.DataType.FLOAT_MAT2:
+ return tcuMatrix.matrixFromDataArray(2, 2, s_constInMat2x2[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT2X3:
+ return tcuMatrix.matrixFromDataArray(3, 2, s_constInMat2x3[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT2X4:
+ return tcuMatrix.matrixFromDataArray(4, 2, s_constInMat2x4[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT3X2:
+ return tcuMatrix.matrixFromDataArray(2, 3, s_constInMat3x2[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT3:
+ return tcuMatrix.matrixFromDataArray(3, 3, s_constInMat3x3[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT3X4:
+ return tcuMatrix.matrixFromDataArray(4, 3, s_constInMat3x4[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT4X2:
+ return tcuMatrix.matrixFromDataArray(2, 4, s_constInMat4x2[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT4X3:
+ return tcuMatrix.matrixFromDataArray(3, 4, s_constInMat4x3[inputNdx]);
+ case gluShaderUtil.DataType.FLOAT_MAT4:
+ return tcuMatrix.matrixFromDataArray(4, 4, s_constInMat4x4[inputNdx]);
+ }
+ } else if (inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC) {
+ switch (typeFormat) {
+ case gluShaderUtil.DataType.FLOAT:
+ return evalCtx.coords[0];
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ return deMath.swizzle(evalCtx.coords, [0, 1]);
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ return deMath.swizzle(evalCtx.coords, [0, 1, 2]);
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ return deMath.swizzle(evalCtx.coords, [0, 1, 2, 3]);
+ case gluShaderUtil.DataType.FLOAT_MAT2:
+ var m = new tcuMatrix.Matrix(2, 2);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3:
+ var m = new tcuMatrix.Matrix(3, 2);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1, 2]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1, 2]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4:
+ var m = new tcuMatrix.Matrix(4, 2);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1, 2, 3]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1, 2, 3]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2:
+ var m = new tcuMatrix.Matrix(2, 3);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1]));
+ m.setCol(2, deMath.swizzle(evalCtx.in_[2], [0, 1]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT3:
+ var m = new tcuMatrix.Matrix(3, 3);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1, 2]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1, 2]));
+ m.setCol(2, deMath.swizzle(evalCtx.in_[2], [0, 1, 2]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4:
+ var m = new tcuMatrix.Matrix(4, 3);
+ m.setCol(0, evalCtx.in_[0]);
+ m.setCol(1, evalCtx.in_[1]);
+ m.setCol(2, evalCtx.in_[2]);
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2:
+ var m = new tcuMatrix.Matrix(2, 4);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1]));
+ m.setCol(2, deMath.swizzle(evalCtx.in_[2], [0, 1]));
+ m.setCol(3, deMath.swizzle(evalCtx.in_[3], [0, 1]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3:
+ var m = new tcuMatrix.Matrix(3, 4);
+ m.setCol(0, deMath.swizzle(evalCtx.in_[0], [0, 1, 2]));
+ m.setCol(1, deMath.swizzle(evalCtx.in_[1], [0, 1, 2]));
+ m.setCol(2, deMath.swizzle(evalCtx.in_[2], [0, 1, 2]));
+ m.setCol(3, deMath.swizzle(evalCtx.in_[3], [0, 1, 2]));
+ return m;
+ case gluShaderUtil.DataType.FLOAT_MAT4:
+ var m = new tcuMatrix.Matrix(4, 4);
+ m.setCol(0, evalCtx.in_[0]);
+ m.setCol(1, evalCtx.in_[1]);
+ m.setCol(2, evalCtx.in_[2]);
+ m.setCol(3, evalCtx.in_[3]);
+ return m;
+ }
+ }
+ throw new Error('Invalid input type');
+ };
+
+ /**
+ * @param {Array<number>} value
+ * @return {Array<number>}
+ */
+ es3fShaderMatrixTest.reduceVecToVec3 = function (value) {
+ if (value.length == 3) {
+ return value;
+ } else if (value.length == 2) {
+ return deMath.swizzle(value, [0, 1, 0])
+ } else {
+ return [value[0], value[1], value[2] + value[3]];
+ }
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} value
+ * @return {Array<number>}
+ */
+ es3fShaderMatrixTest.reduceMatToVec3 = function (value) {
+ if (value.cols == 2) {
+ if (value.rows == 2) {
+ // mat2
+ return [value.get(0, 0), value.get(0, 1), value.get(1, 0) + value.get(1, 1)];
+ } else if (value.rows == 3){
+ //mat2x3
+ return deMath.add(value.getColumn(0), value.getColumn(1));
+ } else {
+ //mat2x4
+ return deMath.add(deMath.swizzle(value.getColumn(0), [0, 1, 2]), deMath.swizzle(value.getColumn(1), [1, 2, 3]));
+ }
+ } else if (value.cols == 3) {
+ if (value.rows == 2) {
+ return [value.get(0, 0) + value.get(1, 0), value.get(0, 1) + value.get(1, 1), value.get(0, 2) + value.get(1, 2)];
+ } else if (value.rows == 3) {
+ return deMath.add(deMath.add(value.getColumn(0), value.getColumn(1)), value.getColumn(2));
+ } else {
+ return deMath.add(deMath.add(deMath.swizzle(value.getColumn(0), [0, 1, 2]), deMath.swizzle(value.getColumn(1), [1, 2, 3])), deMath.swizzle(value.getColumn(2), [2, 3, 0]))
+ }
+ } else {
+ if (value.rows == 2) {
+ return [value.get(0, 0) + value.get(1, 0) + value.get(0, 3), value.get(0, 1) + value.get(1, 1) + value.get(1, 3), value.get(0, 2) + value.get(1, 2)];
+ } else if (value.rows == 3) {
+ return deMath.add(deMath.add(deMath.add(value.getColumn(0), value.getColumn(1)), value.getColumn(2)), value.getColumn(3));
+ } else {
+ return deMath.add(deMath.add(deMath.add(deMath.swizzle(value.getColumn(0), [0, 1, 2]), deMath.swizzle(value.getColumn(1), [1, 2, 3])), deMath.swizzle(value.getColumn(2), [2, 3, 0])), deMath.swizzle(value.getColumn(3), [3, 0, 1]));
+ }
+ }
+ };
+
+ /**
+ * @param {Array<number>|tcuMatrix.Matrix|number} value
+ * @return {Array<number>}
+ */
+ es3fShaderMatrixTest.reduceToVec3 = function (value) {
+ if (value instanceof tcuMatrix.Matrix)
+ return es3fShaderMatrixTest.reduceMatToVec3(value);
+ else if (value instanceof Array)
+ return es3fShaderMatrixTest.reduceVecToVec3(value);
+ else
+ throw new Error('Impossible case');
+ };
+
+ es3fShaderMatrixTest.add = function (a, b) {
+ if (a instanceof tcuMatrix.Matrix) {
+ if (b instanceof tcuMatrix.Matrix)
+ return tcuMatrix.add(a, b);
+ else if (b instanceof Array)
+ throw new Error('Unimplemented');
+ else
+ return tcuMatrix.addMatScal(a, b);
+ }
+ else {
+ if (b instanceof tcuMatrix.Matrix)
+ throw new Error('Unimplemented');
+ else
+ return deMath.add(a, b);
+ }
+ };
+
+ es3fShaderMatrixTest.subtract = function (a, b) {
+ if (a instanceof tcuMatrix.Matrix) {
+ if (b instanceof tcuMatrix.Matrix)
+ return tcuMatrix.subtract(a, b);
+ else if (b instanceof Array)
+ throw new Error('Unimplemented');
+ else
+ return tcuMatrix.subtractMatScal(a, b);
+ }
+ else {
+ if (b instanceof tcuMatrix.Matrix)
+ throw new Error('Unimplemented');
+ else
+ return deMath.subtract(a, b);
+ }
+ };
+
+ es3fShaderMatrixTest.multiply = function (a, b) {
+ if (a instanceof tcuMatrix.Matrix) {
+ if (b instanceof tcuMatrix.Matrix)
+ return tcuMatrix.multiply(a, b);
+ else if (b instanceof Array)
+ return tcuMatrix.multiplyMatVec(a, b);
+ else
+ return tcuMatrix.multiplyMatScal(a, b);
+ } else {
+ if (b instanceof tcuMatrix.Matrix)
+ return tcuMatrix.multiplyVecMat(a, b);
+ else
+ return deMath.multiply(a, b);
+ }
+ };
+
+ es3fShaderMatrixTest.divide = function (a, b) {
+ if (a instanceof tcuMatrix.Matrix) {
+ if (b instanceof tcuMatrix.Matrix)
+ return tcuMatrix.divide(a, b);
+ else if (b instanceof Array)
+ throw new Error('Unimplemented');
+ else
+ return tcuMatrix.divideMatScal(a, b);
+ }
+ else {
+ if (b instanceof tcuMatrix.Matrix)
+ throw new Error('Unimplemented');
+ else
+ return deMath.divide(a, b);
+ }
+ };
+
+
+ /**
+ * @param {tcuMatrix.Matrix} a
+ * @param {tcuMatrix.Matrix} b
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.matrixCompMult = function (a, b) {
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Matrix(a.rows, a.cols);
+
+ for (var r = 0; r < a.rows; ++r) {
+ for (var c = 0; c < a.cols; ++c) {
+ retVal.set(r, c, a.get(r, c) * b.get(r, c));
+ }
+ }
+ return retVal;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.transpose = function (mat) {
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Matrix(mat.cols, mat.rows);
+
+ for (var r = 0; r < mat.rows; ++r) {
+ for (var c = 0; c < mat.cols; ++c) {
+ retVal.set(c, r, mat.get(r, c));
+ }
+ }
+
+ return retVal;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {number}
+ */
+ es3fShaderMatrixTest.determinantMat2 = function (mat) {
+ return mat.get(0, 0) * mat.get(1, 1) - mat.get(1, 0) * mat.get(0,1);
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {number}
+ */
+ es3fShaderMatrixTest.determinantMat3 = function (mat) {
+ return + mat.get(0, 0) * mat.get(1, 1) * mat.get(2, 2)
+ + mat.get(0, 1) * mat.get(1, 2) * mat.get(2, 0)
+ + mat.get(0, 2) * mat.get(1, 0) * mat.get(2, 1)
+ - mat.get(0, 0) * mat.get(1, 2) * mat.get(2, 1)
+ - mat.get(0, 1) * mat.get(1, 0) * mat.get(2, 2)
+ - mat.get(0, 2) * mat.get(1, 1) * mat.get(2, 0);
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {number}
+ */
+ es3fShaderMatrixTest.determinantMat4 = function (mat) {
+ /** @type {Array<Array<number>>} */ var minorMatrices = [
+ [
+ mat.get(1, 1), mat.get(2, 1), mat.get(3, 1),
+ mat.get(1, 2), mat.get(2, 2), mat.get(3, 2),
+ mat.get(1, 3), mat.get(2, 3), mat.get(3, 3)
+ ],
+ [
+ mat.get(1, 0), mat.get(2, 0), mat.get(3, 0),
+ mat.get(1, 2), mat.get(2, 2), mat.get(3, 2),
+ mat.get(1, 3), mat.get(2, 3), mat.get(3, 3)
+ ],
+ [
+ mat.get(1, 0), mat.get(2, 0), mat.get(3, 0),
+ mat.get(1, 1), mat.get(2, 1), mat.get(3, 1),
+ mat.get(1, 3), mat.get(2, 3), mat.get(3, 3)
+ ],
+ [
+ mat.get(1, 0), mat.get(2, 0), mat.get(3, 0),
+ mat.get(1, 1), mat.get(2, 1), mat.get(3, 1),
+ mat.get(1, 2), mat.get(2, 2), mat.get(3, 2)
+ ]
+ ];
+
+ return + mat.get(0, 0) * es3fShaderMatrixTest.determinant(tcuMatrix.matrixFromDataArray(3, 3, minorMatrices[0]))
+ - mat.get(0, 1) * es3fShaderMatrixTest.determinant(tcuMatrix.matrixFromDataArray(3, 3, minorMatrices[1]))
+ + mat.get(0, 2) * es3fShaderMatrixTest.determinant(tcuMatrix.matrixFromDataArray(3, 3, minorMatrices[2]))
+ - mat.get(0, 3) * es3fShaderMatrixTest.determinant(tcuMatrix.matrixFromDataArray(3, 3, minorMatrices[3]));
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {number}
+ */
+ es3fShaderMatrixTest.determinant = function (mat) {
+ if (mat.rows == 2) {
+ return es3fShaderMatrixTest.determinantMat2(mat);
+ } else if (mat.rows == 3) {
+ return es3fShaderMatrixTest.determinantMat3(mat);
+ } else {
+ return es3fShaderMatrixTest.determinantMat4(mat);
+ }
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.inverseMat2 = function (mat) {
+ /** @type {number} */ var det = es3fShaderMatrixTest.determinant(mat);
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Mat2();
+
+ if (det == 0.0) {
+ throw new Error('Wrong determinant')
+ }
+
+ retVal.set(0, 0, mat.get(1, 1) / det);
+ retVal.set(0, 1, -mat.get(0, 1) / det);
+ retVal.set(1, 0, -mat.get(1, 0) / det);
+ retVal.set(1, 1, mat.get(0, 0) / det);
+
+ return retVal;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.inverseMat3 = function (mat) {
+ if (es3fShaderMatrixTest.determinant(mat) == 0.0) {
+ throw new Error('Wrong determinant')
+ }
+
+ /** @type {Array<number>} */ var areaA = [mat.get(0, 0), mat.get(0, 1), mat.get(1, 0), mat.get(1,1)];
+ /** @type {Array<number>} */ var areaB = [mat.get(0, 2), mat.get(1, 2)];
+ /** @type {Array<number>} */ var areaC = [mat.get(2, 0), mat.get(2, 1)];
+ /** @type {Array<number>} */ var areaD = [mat.get(2,2)];
+
+ /** @type {tcuMatrix.Matrix} */ var invA = es3fShaderMatrixTest.inverse(tcuMatrix.matrixFromDataArray(2, 2, areaA));
+ /** @type {tcuMatrix.Matrix} */ var matB = tcuMatrix.matrixFromDataArray(2, 1, areaB);
+ /** @type {tcuMatrix.Matrix} */ var matC = tcuMatrix.matrixFromDataArray(1, 2, areaC);
+ /** @type {tcuMatrix.Matrix} */ var matD = tcuMatrix.matrixFromDataArray(1, 1, areaD);
+
+ /** @type {tcuMatrix.Matrix} */ var tmp = tcuMatrix.subtract(matD, tcuMatrix.multiply(matC, tcuMatrix.multiply(invA, matB)));
+ /** @type {number} */ var schurComplement = 1.0 / tmp.get(0, 0);
+ /** @type {tcuMatrix.Matrix} */ var zeroMat = new tcuMatrix.Matrix(2, 2, 0);
+
+ /** @type {tcuMatrix.Matrix} */ var blockA = tcuMatrix.add(invA, tcuMatrix.multiply(tcuMatrix.multiply(invA, tcuMatrix.multiply(tcuMatrix.multiplyMatScal(matB, schurComplement), matC)), invA));
+ /** @type {tcuMatrix.Matrix} */ var blockB = tcuMatrix.multiplyMatScal(tcuMatrix.multiply(tcuMatrix.subtract(zeroMat, invA), matB), schurComplement);
+ /** @type {tcuMatrix.Matrix} */ var blockC = tcuMatrix.multiply(matC, tcuMatrix.multiplyMatScal(invA, - schurComplement));
+ /** @type {number} */ var blockD = schurComplement;
+
+ /** @type {Array<number>} */ var result = [
+ blockA.get(0, 0), blockA.get(0, 1), blockB.get(0, 0),
+ blockA.get(1, 0), blockA.get(1, 1), blockB.get(1, 0),
+ blockC.get(0, 0), blockC.get(0, 1), blockD
+ ];
+
+ return tcuMatrix.matrixFromDataArray(3, 3, result);
+ }
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.inverseMat4 = function (mat) {
+ // Blockwise inversion
+ if (es3fShaderMatrixTest.determinant(mat) == 0.0) {
+ throw new Error('Wrong determinant')
+ }
+
+ /** @type {Array<number>} */ var areaA = [
+ mat.get(0, 0), mat.get(0, 1),
+ mat.get(1, 0), mat.get(1, 1)
+ ];
+ /** @type {Array<number>} */ var areaB = [
+ mat.get(0, 2), mat.get(0, 3),
+ mat.get(1, 2), mat.get(1, 3)
+ ];
+ /** @type {Array<number>} */ var areaC = [
+ mat.get(2, 0), mat.get(2, 1),
+ mat.get(3, 0), mat.get(3, 1)
+ ];
+ /** @type {Array<number>} */ var areaD = [
+ mat.get(2, 2), mat.get(2, 3),
+ mat.get(3, 2), mat.get(3, 3)
+ ];
+
+ /** @type {tcuMatrix.Matrix} */ var invA = es3fShaderMatrixTest.inverse(tcuMatrix.matrixFromDataArray(2, 2, areaA));
+ /** @type {tcuMatrix.Matrix} */ var matB = tcuMatrix.matrixFromDataArray(2, 2, areaB);
+ /** @type {tcuMatrix.Matrix} */ var matC = tcuMatrix.matrixFromDataArray(2, 2, areaC);
+ /** @type {tcuMatrix.Matrix} */ var matD = tcuMatrix.matrixFromDataArray(2, 2, areaD);
+
+ /** @type {tcuMatrix.Matrix} */ var schurComplement = es3fShaderMatrixTest.inverse(tcuMatrix.subtract(matD, (tcuMatrix.multiply(matC, tcuMatrix.multiply(invA, matB)))));
+ /** @type {tcuMatrix.Matrix} */ var zeroMat = new tcuMatrix.Matrix(2, 2, 0);
+
+ /** @type {tcuMatrix.Matrix} */ var blockA = tcuMatrix.add(invA, tcuMatrix.multiply(tcuMatrix.multiply(tcuMatrix.multiply(tcuMatrix.multiply(invA, matB), schurComplement), matC), invA));
+ /** @type {tcuMatrix.Matrix} */ var blockB = tcuMatrix.multiply(tcuMatrix.multiply(tcuMatrix.subtract(zeroMat, invA), matB), schurComplement);
+ /** @type {tcuMatrix.Matrix} */ var blockC = tcuMatrix.multiply(tcuMatrix.multiply(tcuMatrix.subtract(zeroMat, schurComplement),matC), invA);
+ /** @type {tcuMatrix.Matrix} */ var blockD = schurComplement;
+
+ /** @type {Array<number>} */ var result = [
+ blockA.get(0, 0), blockA.get(0, 1), blockB.get(0, 0), blockB.get(0, 1),
+ blockA.get(1, 0), blockA.get(1, 1), blockB.get(1, 0), blockB.get(1, 1),
+ blockC.get(0, 0), blockC.get(0, 1), blockD.get(0, 0), blockD.get(0, 1),
+ blockC.get(1, 0), blockC.get(1, 1), blockD.get(1, 0), blockD.get(1, 1)
+ ];
+
+ return tcuMatrix.matrixFromDataArray(4, 4, result);
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.inverse = function (mat) {
+ if (mat.cols == 2) {
+ return es3fShaderMatrixTest.inverseMat2(mat)
+ } else if (mat.cols == 3) {
+ return es3fShaderMatrixTest.inverseMat3(mat)
+ } else {
+ return es3fShaderMatrixTest.inverseMat4(mat)
+ }
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.negate = function (mat) {
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Matrix(mat.rows, mat.cols);
+
+ for (var r = 0; r < mat.rows; ++r)
+ for (var c = 0; c < mat.cols; ++c)
+ retVal.set(r,c, -mat.get(r, c));
+
+ return retVal;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.increment = function (mat) {
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Matrix(mat.rows, mat.cols);
+
+ for (var r = 0; r < mat.rows; ++r)
+ for (var c = 0; c < mat.cols; ++c)
+ retVal.set(r,c, mat.get(r, c) + 1.0);
+
+ return retVal;
+ };
+
+ /**
+ * @param {tcuMatrix.Matrix} mat
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.decrement = function (mat) {
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Matrix(mat.rows, mat.cols);
+
+ for (var r = 0; r < mat.rows; ++r)
+ for (var c = 0; c < mat.cols; ++c)
+ retVal.set(r,c, mat.get(r, c) - 1.0);
+
+ return retVal;
+ };
+
+ /**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {tcuMatrix.Matrix}
+ */
+ es3fShaderMatrixTest.outerProduct = function (a, b) {
+ /** @type {tcuMatrix.Matrix} */ var retVal = new tcuMatrix.Matrix(b.length, a.length);
+
+ for (var r = 0; r < b.length; ++r) {
+ for (var c = 0; c < a.length; ++c) {
+ retVal.set(r, c, a[c] * b[r]);
+ }
+ }
+
+ return es3fShaderMatrixTest.transpose(retVal);
+ };
+
+ /**
+ * @enum
+ */
+ es3fShaderMatrixTest.InputType = {
+ INPUTTYPE_CONST: 0,
+ INPUTTYPE_UNIFORM: 1,
+ INPUTTYPE_DYNAMIC: 2
+ };
+
+ /**
+ * @enum
+ */
+ es3fShaderMatrixTest.MatrixOp = {
+ OP_ADD: 0,
+ OP_SUB: 1,
+ OP_MUL: 2,
+ OP_DIV: 3,
+ OP_COMP_MUL: 4,
+ OP_OUTER_PRODUCT: 5,
+ OP_TRANSPOSE: 6,
+ OP_INVERSE: 7,
+ OP_DETERMINANT: 8,
+ OP_UNARY_PLUS: 9,
+ OP_NEGATION: 10,
+ OP_PRE_INCREMENT: 11,
+ OP_PRE_DECREMENT: 12,
+ OP_POST_INCREMENT: 13,
+ OP_POST_DECREMENT: 14,
+ OP_ADD_INTO: 15,
+ OP_SUBTRACT_FROM: 16,
+ OP_MULTIPLY_INTO: 17,
+ OP_DIVIDE_INTO: 18,
+ OP_LAST: 19
+ };
+
+ /**
+ * @constructor
+ * @param {es3fShaderMatrixTest.InputType=} inputType_
+ * @param {gluShaderUtil.DataType=} dataType_
+ * @param {gluShaderUtil.precision=} precision_
+ * @struct
+ */
+ es3fShaderMatrixTest.ShaderInput = function (inputType_, dataType_, precision_){
+ this.inputType = inputType_ || es3fShaderMatrixTest.InputType.INPUTTYPE_CONST;
+ this.dataType = dataType_ || gluShaderUtil.DataType.INVALID;
+ this.precision = precision_ || gluShaderUtil.precision.PRECISION_LOWP;
+ };
+
+ /**
+ * @param {es3fShaderMatrixTest.ShaderInput} in0
+ * @param {es3fShaderMatrixTest.ShaderInput} in1
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ */
+ es3fShaderMatrixTest.getEvalFunc = function (in0, in1, op) {
+ var setColor = function(evalCtx, src) {
+ for (var i = 0; i < 3; i++)
+ evalCtx.color[i] = src[i];
+ };
+ switch(op){
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.add(in0_, in1_)));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_SUB:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.subtract(in0_, in1_)));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_MUL:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.multiply(in0_, in1_)));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_DIV:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.divide(in0_, in1_)));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_COMP_MUL:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.matrixCompMult(/** @type {tcuMatrix.Matrix} */(in0_), /** @type {tcuMatrix.Matrix} */(in1_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.outerProduct(/** @type {Array<number>} */(in0_), /** @type {Array<number>} */(in1_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.transpose(/** @type {tcuMatrix.Matrix} */(in0_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_INVERSE:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.inverse(/** @type {tcuMatrix.Matrix} */(in0_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ var det = es3fShaderMatrixTest.determinant(/** @type {tcuMatrix.Matrix} */(in0_));
+ setColor(evalCtx, [det, det, det]);
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_UNARY_PLUS:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(/** @type {tcuMatrix.Matrix} */(in0_)));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_NEGATION:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.negate(/** @type {tcuMatrix.Matrix} */(in0_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ var val0 = es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.increment(/** @type {tcuMatrix.Matrix} */(in0_)));
+ var val1 = es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.increment(/** @type {tcuMatrix.Matrix} */(in0_)));
+ setColor(evalCtx, deMath.add(val0, val1));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ var val0 = es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.decrement(/** @type {tcuMatrix.Matrix} */(in0_)));
+ var val1 = es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.decrement(/** @type {tcuMatrix.Matrix} */(in0_)));
+ setColor(evalCtx, deMath.add(val0, val1));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ var val0 = es3fShaderMatrixTest.reduceToVec3((in0_));
+ var val1 = es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.increment(/** @type {tcuMatrix.Matrix} */(in0_)));
+ setColor(evalCtx, deMath.add(val0, val1));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+
+ var val0 = es3fShaderMatrixTest.reduceToVec3((in0_));
+ var val1 = es3fShaderMatrixTest.reduceToVec3(es3fShaderMatrixTest.decrement(/** @type {tcuMatrix.Matrix} */(in0_)));
+ setColor(evalCtx, deMath.add(val0, val1));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in0.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(tcuMatrix.add(/** @type {tcuMatrix.Matrix} */(in0_), /** @type {tcuMatrix.Matrix} */(in1_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in0.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(tcuMatrix.subtract(/** @type {tcuMatrix.Matrix} */(in0_), /** @type {tcuMatrix.Matrix} */(in1_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in0.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(tcuMatrix.multiply(/** @type {tcuMatrix.Matrix} */(in0_), /** @type {tcuMatrix.Matrix} */(in1_))));
+ };
+ case es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO:
+ return function (evalCtx) {
+ var in0_ = in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in0.inputType, in0.dataType, evalCtx, 0)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in0.dataType, evalCtx, 0);
+ var in1_ = in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ?
+ es3fShaderMatrixTest.getInputValue(in1.inputType, in1.dataType, evalCtx, 1)
+ : es3fShaderMatrixTest.getInputValue(es3fShaderMatrixTest.InputType.INPUTTYPE_CONST, in1.dataType, evalCtx, 1);
+
+ setColor(evalCtx, es3fShaderMatrixTest.reduceToVec3(tcuMatrix.divide(/** @type {tcuMatrix.Matrix} */(in0_), /** @type {tcuMatrix.Matrix} */(in1_))));
+ };
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {es3fShaderMatrixTest.MatrixShaderEvalFunc} evalFunc
+ * @param {es3fShaderMatrixTest.InputType} inType0
+ * @param {es3fShaderMatrixTest.InputType} inType1
+ * @extends {glsShaderRenderCase.ShaderEvaluator}
+ */
+ es3fShaderMatrixTest.MatrixShaderEvaluator = function(evalFunc, inType0, inType1) {
+ glsShaderRenderCase.ShaderEvaluator.call(this);
+ this.m_matEvalFunc = evalFunc;
+ this.m_inType0 = inType0;
+ this.m_inType1 = inType1;
+ };
+
+ es3fShaderMatrixTest.MatrixShaderEvaluator.prototype = Object.create(glsShaderRenderCase.ShaderEvaluator);
+ es3fShaderMatrixTest.MatrixShaderEvaluator.prototype.constructor = es3fShaderMatrixTest.MatrixShaderEvaluator;
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} evalCtx
+ */
+ es3fShaderMatrixTest.MatrixShaderEvaluator.prototype.evaluate = function (evalCtx) {
+ this.m_matEvalFunc(evalCtx);
+ }
+
+ /**
+ * @param {Array<number>} v
+ * @param {number} size
+ */
+ es3fShaderMatrixTest.writeVectorConstructor = function (v, size) {
+ var str = 'vec' + size + '';
+ for (var ndx = 0; ndx < size; ndx++) {
+ if (ndx != 0)
+ str += ', ';
+ str += v[ndx].toString;
+ }
+ str += ')';
+ return str;
+ }
+
+ /**
+ * @param {tcuMatrix.Matrix} m
+ */
+ es3fShaderMatrixTest.writeMatrixConstructor = function (m) {
+ var str = '';
+ if (m.rows == m.cols)
+ str += 'mat' + m.cols;
+ else
+ str += 'mat' + m.cols + 'x' + m.rows;
+
+ str += '(';
+ for (var colNdx = 0; colNdx < m.cols; colNdx++) {
+ for (var rowNdx = 0; rowNdx < m.rows; rowNdx++) {
+ if (rowNdx > 0 || colNdx > 0)
+ str += ', ';
+ str += m.get(rowNdx, colNdx).toString();
+ }
+ }
+ str += ')';
+ return str;
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fShaderMatrixTest.ShaderInput} in0
+ * @param {es3fShaderMatrixTest.ShaderInput} in1
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @param {boolean} isVertexCase
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ */
+ es3fShaderMatrixTest.ShaderMatrixCase = function(name, desc, in0, in1, op, isVertexCase) {
+ var evalFunc = es3fShaderMatrixTest.getEvalFunc(in0, in1, op);
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, desc, isVertexCase, evalFunc);
+ this.m_in0 = in0;
+ this.m_in1 = in1;
+ this.m_op = op;
+ this.m_evaluator = new es3fShaderMatrixTest.MatrixShaderEvaluator(evalFunc, in0.inputType, in1.inputType);
+ };
+
+ es3fShaderMatrixTest.ShaderMatrixCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+ es3fShaderMatrixTest.ShaderMatrixCase.prototype.constructor = es3fShaderMatrixTest.ShaderMatrixCase;
+
+
+ es3fShaderMatrixTest.ShaderMatrixCase.prototype.init = function () {
+ var shaderSources = [ '', '' ];
+ var vtx = 0;
+ var frag = 1;
+ var op = this.m_isVertexCase ? vtx : frag;
+
+ /** @type {boolean} */ var isInDynMat0 = gluShaderUtil.isDataTypeMatrix(this.m_in0.dataType) && this.m_in0.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC;
+ /** @type {boolean} */ var isInDynMat1 = gluShaderUtil.isDataTypeMatrix(this.m_in1.dataType) && this.m_in1.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC;
+ /** @type {Array<string>} */ var inValues = [];
+ /** @type {gluShaderUtil.DataType} */ var resultType;
+ /** @type {gluShaderUtil.precision} */ var resultPrec = this.m_in0.precision;
+ /** @type {Array<string>} */ var passVars = [];
+ /** @type {number} */ var numInputs = (es3fShaderMatrixTest.isOperationBinary(this.m_op)) ? (2) : (1);
+
+ /** @type {string} */ var operationValue0 = '';
+ /** @type {string} */ var operationValue1 = '';
+
+ if (isInDynMat0 && isInDynMat1) {
+ throw new Error ('Only single dynamic matrix input is allowed.');
+ }
+
+ if (this.m_op == es3fShaderMatrixTest.MatrixOp.OP_MUL && gluShaderUtil.isDataTypeMatrix(this.m_in0.dataType) && gluShaderUtil.isDataTypeMatrix(this.m_in1.dataType)) {
+ resultType = gluShaderUtil.getDataTypeMatrix(gluShaderUtil.getDataTypeMatrixNumColumns(this.m_in1.dataType), gluShaderUtil.getDataTypeMatrixNumRows(this.m_in0.dataType));
+ } else if (this.m_op == es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT) {
+ resultType = gluShaderUtil.getDataTypeMatrix(gluShaderUtil.getDataTypeScalarSize(this.m_in1.dataType), gluShaderUtil.getDataTypeScalarSize(this.m_in0.dataType));
+ } else if (this.m_op == es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE) {
+ resultType = gluShaderUtil.getDataTypeMatrix(gluShaderUtil.getDataTypeMatrixNumRows(this.m_in0.dataType), gluShaderUtil.getDataTypeMatrixNumColumns(this.m_in0.dataType));
+ } else if (this.m_op == es3fShaderMatrixTest.MatrixOp.OP_INVERSE) {
+ resultType = this.m_in0.dataType;
+ } else if (this.m_op == es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT) {
+ resultType = gluShaderUtil.DataType.FLOAT;
+ } else if (es3fShaderMatrixTest.getOperationType(this.m_op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
+ es3fShaderMatrixTest.getOperationType(this.m_op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_POSTFIX_OPERATOR) {
+ resultType = this.m_in0.dataType;
+ } else if (gluShaderUtil.isDataTypeMatrix(this.m_in0.dataType) && gluShaderUtil.isDataTypeMatrix(this.m_in1.dataType)) {
+ if (this.m_in0.dataType !== this.m_in1.dataType) {
+ throw new Error ('Incompatible data types');
+ }
+ resultType = this.m_in0.dataType;
+ } else if (gluShaderUtil.isDataTypeMatrix(this.m_in0.dataType) || gluShaderUtil.isDataTypeMatrix(this.m_in1.dataType)) {
+ /** @type {number} */ var matNdx = gluShaderUtil.isDataTypeMatrix(this.m_in0.dataType) ? 0 : 1;
+ /** @type {gluShaderUtil.DataType} */ var matrixType = matNdx == 0 ? this.m_in0.dataType : this.m_in1.dataType;
+ /** @type {gluShaderUtil.DataType} */ var otherType = matNdx == 0 ? this.m_in1.dataType : this.m_in0.dataType;
+
+ if (otherType == gluShaderUtil.DataType.FLOAT)
+ resultType = matrixType;
+ else {
+ if (!gluShaderUtil.isDataTypeVector(otherType)) {
+ throw new Error ('Is not data type vector');
+ }
+ resultType = gluShaderUtil.getDataTypeFloatVec(matNdx == 0 ? gluShaderUtil.getDataTypeMatrixNumRows(matrixType) : gluShaderUtil.getDataTypeMatrixNumColumns(matrixType));
+ }
+ } else {
+ throw new Error ('Error');
+ }
+
+ shaderSources[vtx] += '#version 300 es\n';
+ shaderSources[frag] += '#version 300 es\n';
+
+ shaderSources[vtx] += 'in highp vec4 a_position;\n';
+ shaderSources[frag] += 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+ if (this.m_isVertexCase) {
+ shaderSources[vtx] += 'out mediump vec4 v_color;\n';
+ shaderSources[frag] += 'in mediump vec4 v_color;\n';
+ }
+
+ // Input declarations.
+ for (var inNdx = 0; inNdx < numInputs; inNdx++) {
+ /** @type {es3fShaderMatrixTest.ShaderInput} */ var ind = inNdx > 0 ? this.m_in1 : this.m_in0;
+ /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(ind.precision);
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(ind.dataType);
+ /** @type {number} */ var inValueNdx = inNdx > 0 ? 1 : 0;
+
+ if (ind.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC) {
+ shaderSources[vtx] += 'in ' + precName + ' ' + typeName + ' a_';
+
+ if (gluShaderUtil.isDataTypeMatrix(ind.dataType)) {
+ // a_matN, v_matN
+ shaderSources[vtx] += typeName + ';\n';
+ if (!this.m_isVertexCase) {
+ shaderSources[vtx] += 'out ' + precName + ' ' + typeName + ' v_' + typeName + ';\n';
+ shaderSources[frag] += 'in ' + precName + ' ' + typeName + ' v_' + typeName + ';\n';
+ passVars.push(typeName);
+ }
+
+ inValues[inValueNdx] = (this.m_isVertexCase ? 'a_' : 'v_') + gluShaderUtil.getDataTypeName(ind.dataType);
+ } else {
+ // a_coords, v_coords
+ shaderSources[vtx] += 'coords;\n';
+ if (!this.m_isVertexCase) {
+ shaderSources[vtx] += 'out ' + precName + ' ' + typeName + ' v_coords;\n';
+ shaderSources[frag] += 'in ' + precName + ' ' + typeName + ' v_coords;\n';
+ passVars.push('coords');
+ }
+
+ inValues[inValueNdx] = this.m_isVertexCase ? 'a_coords' : 'v_coords';
+ }
+ } else if (ind.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM) {
+ shaderSources[op] += 'uniform ' + precName + ' ' + typeName + ' u_in' + inNdx + ';\n';
+ inValues[inValueNdx] = 'u_in' + inNdx.toString();
+ } else if (ind.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_CONST) {
+ shaderSources[op] += 'const ' + precName + ' ' + typeName + ' in' + inNdx + ' = ';
+
+ // Generate declaration.
+ switch (ind.dataType) {
+ case gluShaderUtil.DataType.FLOAT:
+ shaderSources[op] += s_constInFloat[inNdx].toString();
+ break;
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ shaderSources[op] += es3fShaderMatrixTest.writeVectorConstructor( s_constInVec2[inNdx], 2);
+ break;
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ shaderSources[op] += es3fShaderMatrixTest.writeVectorConstructor( s_constInVec3[inNdx], 3);
+ break;
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ shaderSources[op] += es3fShaderMatrixTest.writeVectorConstructor( s_constInVec4[inNdx], 4);
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT2:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(2, 2, s_constInMat2x2[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(3, 2, s_constInMat2x3[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(4, 2, s_constInMat2x4[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(2, 3, s_constInMat3x2[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT3:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(3, 3, s_constInMat3x3[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(4, 3, s_constInMat3x4[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(2, 4, s_constInMat4x2[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(3, 4, s_constInMat4x3[inNdx]));
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT4:
+ shaderSources[op] += es3fShaderMatrixTest.writeMatrixConstructor( tcuMatrix.matrixFromDataArray(4, 4, s_constInMat4x4[inNdx]));
+ break;
+
+ default:
+ throw new Error('Data type error');
+ }
+
+ shaderSources[op] += ';\n';
+
+ inValues[inValueNdx] = 'in' + inNdx.toString();
+ }
+ }
+
+ shaderSources[vtx] += '\n'
+ + 'void main (void)\n'
+ + '{\n'
+ + ' gl_Position = a_position;\n';
+ shaderSources[frag] += '\n'
+ + 'void main (void)\n'
+ + '{\n';
+
+ if (this.m_isVertexCase)
+ shaderSources[frag] += ' dEQP_FragColor = v_color;\n';
+ else {
+ for (var i = 0; i != passVars.length; i++)
+ shaderSources[vtx] += ' v_' + passVars[i] + ' = ' + 'a_' + passVars[i] + ';\n';
+ }
+
+ // Operation.
+
+ switch (es3fShaderMatrixTest.getOperationNature(this.m_op)) {
+ case es3fShaderMatrixTest.OperationNature.OPERATIONNATURE_PURE:
+ if (es3fShaderMatrixTest.getOperationType(this.m_op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT)
+ throw new Error('Wrong operation type');
+
+ operationValue0 = inValues[0];
+ operationValue1 = inValues[1];
+ break;
+
+ case es3fShaderMatrixTest.OperationNature.OPERATIONNATURE_MUTATING:
+ if (es3fShaderMatrixTest.getOperationType(this.m_op) == es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT)
+ throw new Error('Wrong operation type');
+
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec) + ' ' + gluShaderUtil.getDataTypeName(resultType) + ' tmpValue = ' + inValues[0] + ';\n';
+
+ operationValue0 = 'tmpValue';
+ operationValue1 = inValues[1];
+ break;
+
+ case es3fShaderMatrixTest.OperationNature.OPERATIONNATURE_ASSIGNMENT:
+ if (es3fShaderMatrixTest.getOperationType(this.m_op) != es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT)
+ throw new Error('Wrong operation type');
+
+ operationValue0 = inValues[0];
+ operationValue1 = inValues[1];
+ break;
+
+ default:
+ throw new Error('Wrong operation nature');
+ }
+
+ switch (es3fShaderMatrixTest.getOperationType(this.m_op)) {
+ case es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_OPERATOR:
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec) + ' '
+ + gluShaderUtil.getDataTypeName(resultType)
+ + ' res = ' + operationValue0 + ' '
+ + es3fShaderMatrixTest.getOperationName(this.m_op) + ' '
+ + operationValue1 + ';\n';
+ break;
+ case es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec) + ' '
+ + gluShaderUtil.getDataTypeName(resultType)
+ + ' res = ' + es3fShaderMatrixTest.getOperationName(this.m_op)
+ + operationValue0 + ';\n';
+ break;
+ case es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec) + ' '
+ + gluShaderUtil.getDataTypeName(resultType)
+ + ' res = ' + operationValue0
+ + es3fShaderMatrixTest.getOperationName(this.m_op) + ';\n';
+ break;
+ case es3fShaderMatrixTest.OperationType.OPERATIONTYPE_BINARY_FUNCTION:
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec)
+ + ' ' + gluShaderUtil.getDataTypeName(resultType)
+ + ' res = ' + es3fShaderMatrixTest.getOperationName(this.m_op)
+ + '(' + operationValue0
+ + ', ' + operationValue1 + ');\n';
+ break;
+ case es3fShaderMatrixTest.OperationType.OPERATIONTYPE_UNARY_FUNCTION:
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec)
+ + ' ' + gluShaderUtil.getDataTypeName(resultType)
+ + ' res = ' + es3fShaderMatrixTest.getOperationName(this.m_op)
+ + '(' + operationValue0 + ');\n';
+ break;
+ case es3fShaderMatrixTest.OperationType.OPERATIONTYPE_ASSIGNMENT:
+ shaderSources[op] += ' ' + gluShaderUtil.getPrecisionName(resultPrec)
+ + ' ' + gluShaderUtil.getDataTypeName(resultType)
+ + ' res = ' + operationValue0 + ';\n';
+ shaderSources[op] += ' res ' + es3fShaderMatrixTest.getOperationName(this.m_op)
+ + ' ' + operationValue1 + ';\n';
+ break;
+ default:
+ throw new Error('Wrong operation type');
+ }
+
+ // Reduction to vec3 (rgb). Check the used value too if it was modified
+ shaderSources[op] += ' ' + (this.m_isVertexCase ? 'v_color' : 'dEQP_FragColor') + ' = ';
+
+ if (es3fShaderMatrixTest.isOperationValueModifying(this.m_op))
+ shaderSources[op] += 'vec4(' + this.genGLSLMatToVec3Reduction(resultType, 'res')
+ + ', 1.0) + vec4(' + this.genGLSLMatToVec3Reduction(resultType, 'tmpValue')
+ + ', 0.0);\n';
+ else
+ shaderSources[op] += 'vec4(' + this.genGLSLMatToVec3Reduction(resultType, 'res')
+ + ', 1.0);\n';
+
+ shaderSources[vtx] += '}\n';
+ shaderSources[frag] += '}\n';
+
+ this.m_vertShaderSource = shaderSources[vtx];
+ this.m_fragShaderSource = shaderSources[frag];
+
+ // \todo [2012-02-14 pyry] Compute better values for matrix tests.
+ for (var attribNdx = 0; attribNdx < 4; attribNdx++) {
+ this.m_userAttribTransforms[attribNdx] = new tcuMatrix.Matrix(4, 4, 0);
+ this.m_userAttribTransforms[attribNdx].set(0, 3, 0.2);// !< prevent matrix*vec from going into zero (assuming vec.w != 0)
+ this.m_userAttribTransforms[attribNdx].set(1, 3, 0.1);// !<
+ this.m_userAttribTransforms[attribNdx].set(2, 3, 0.4 + 0.15 * attribNdx);// !<
+ this.m_userAttribTransforms[attribNdx].set(3, 3, 0.7);// !<
+ this.m_userAttribTransforms[attribNdx].set((0 + attribNdx) % 4, 0, 1.0);
+ this.m_userAttribTransforms[attribNdx].set((1 + attribNdx) % 4, 1, 1.0);
+ this.m_userAttribTransforms[attribNdx].set((2 + attribNdx) % 4, 2, 1.0);
+ this.m_userAttribTransforms[attribNdx].set((3 + attribNdx) % 4, 3, 1.0);
+ }
+
+ // prevent bad reference cases such as black result images by fine-tuning used matrices
+ if (es3fShaderMatrixTest.getOperationTestMatrixType(this.m_op) != es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DEFAULT) {
+ for (var attribNdx = 0; attribNdx < 4; attribNdx++) {
+ for (var row = 0; row < 4; row++)
+ for (var col = 0; col < 4; col++) {
+ switch (es3fShaderMatrixTest.getOperationTestMatrixType(this.m_op)) {
+ case es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_NEGATED:
+ this.m_userAttribTransforms[attribNdx].set(row, col, -this.m_userAttribTransforms[attribNdx].get(row, col));
+ break;
+ case es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_INCREMENTED:
+ this.m_userAttribTransforms[attribNdx].set(row, col, this.m_userAttribTransforms[attribNdx].get(row, col) + 0.3);
+ break;
+ case es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_DECREMENTED:
+ this.m_userAttribTransforms[attribNdx].set(row, col, this.m_userAttribTransforms[attribNdx].get(row, col) - 0.3);
+ break;
+ case es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_NEGATED_INCREMENTED:
+ this.m_userAttribTransforms[attribNdx].set(row, col, -(this.m_userAttribTransforms[attribNdx].get(row, col) + 0.3));
+ break;
+ case es3fShaderMatrixTest.MatrixType.TESTMATRIXTYPE_INCREMENTED_LESS:
+ this.m_userAttribTransforms[attribNdx].set(row, col, this.m_userAttribTransforms[attribNdx].get(row, col) - 0.1);
+ break;
+ default:
+ throw new Error('Wrong Matrix type');
+ }
+ }
+ }
+ }
+
+ glsShaderRenderCase.ShaderRenderCase.prototype.init.call(this);
+ };
+
+
+ es3fShaderMatrixTest.ShaderMatrixCase.prototype.setupUniforms = function(programId, constCoords) {
+ for (var inNdx = 0; inNdx < 2; inNdx++)
+ {
+ var input = inNdx > 0 ? this.m_in1 : this.m_in0;
+
+ if (input.inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM)
+ {
+ var loc = gl.getUniformLocation(programId, "u_in" + inNdx);
+
+ if (!loc)
+ continue;
+
+ switch (input.dataType)
+ {
+ case gluShaderUtil.DataType.FLOAT: gl.uniform1f(loc, s_constInFloat[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_VEC2: gl.uniform2fv(loc, s_constInVec2[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_VEC3: gl.uniform3fv(loc, s_constInVec3[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_VEC4: gl.uniform4fv(loc, s_constInVec4[inNdx]); break;
+ // \note GLES3 supports transpose in matrix upload.
+ case gluShaderUtil.DataType.FLOAT_MAT2: gl.uniformMatrix2fv (loc, true, s_constInMat2x2[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: gl.uniformMatrix2x3fv(loc, true, s_constInMat2x3[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: gl.uniformMatrix2x4fv(loc, true, s_constInMat2x4[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: gl.uniformMatrix3x2fv(loc, true, s_constInMat3x2[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3: gl.uniformMatrix3fv (loc, true, s_constInMat3x3[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: gl.uniformMatrix3x4fv(loc, true, s_constInMat3x4[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: gl.uniformMatrix4x2fv(loc, true, s_constInMat4x2[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: gl.uniformMatrix4x3fv(loc, true, s_constInMat4x3[inNdx]); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4: gl.uniformMatrix4fv (loc, true, s_constInMat4x4[inNdx]); break;
+ default:
+ throw new Error('Invalid datatype' + input.dataType);
+ }
+ }
+ }
+ };
+
+
+
+ /**
+ * @param {gluShaderUtil.DataType} matType
+ * @param {string} varName
+ * @return {string}
+ */
+ es3fShaderMatrixTest.ShaderMatrixCase.prototype.genGLSLMatToVec3Reduction = function (matType, varName) {
+ /** @type {string} */ var op = '';
+
+ switch (matType) {
+ case gluShaderUtil.DataType.FLOAT:
+ op += varName + ', '
+ + varName + ', '
+ + varName + '';
+ break;
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ op += varName + '.x, '
+ + varName + '.y, '
+ + varName + '.x';
+ break;
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ op += varName + '';
+ break;
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ op += varName + '.x, '
+ + varName + '.y, '
+ + varName + '.z+'
+ + varName + '.w';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT2:
+ op += varName + '[0][0], '
+ + varName + '[1][0], '
+ + varName + '[0][1]+'
+ + varName + '[1][1]';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3:
+ op += varName + '[0] + '
+ + varName + '[1]';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4:
+ op += varName + '[0].xyz + '
+ + varName + '[1].yzw';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2:
+ op += varName + '[0][0]+'
+ + varName + '[0][1], '
+ + varName + '[1][0]+'
+ + varName + '[1][1], '
+ + varName + '[2][0]+'
+ + varName + '[2][1]';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT3:
+ op += varName + '[0] + '
+ + varName + '[1] + '
+ + varName + '[2]';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4:
+ op += varName + '[0].xyz + '
+ + varName + '[1].yzw + '
+ + varName + '[2].zwx';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2:
+ op += varName + '[0][0]+'
+ + varName + '[0][1]+'
+ + varName + '[3][0], '
+ + varName + '[1][0]+'
+ + varName + '[1][1]+'
+ + varName + '[3][1], '
+ + varName + '[2][0]+'
+ + varName + '[2][1]';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3:
+ op += varName + '[0] + '
+ + varName + '[1] + '
+ + varName + '[2] + '
+ + varName + '[3]';
+ break;
+ case gluShaderUtil.DataType.FLOAT_MAT4:
+ op += varName + '[0].xyz+'
+ + varName + '[1].yzw+'
+ + varName + '[2].zwx+'
+ + varName + '[3].wxy';
+ break;
+
+ default:
+ throw new Error('Wrong data type');
+ }
+
+ return op;
+ }
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fShaderMatrixTest.MatrixOp} op
+ * @param {boolean} extendedInputTypeCases
+ * @param {boolean} createInputTypeGroup
+ */
+ es3fShaderMatrixTest.ops = function (name, desc, op, extendedInputTypeCases, createInputTypeGroup) {
+ this.name = name;
+ this.desc = desc;
+ this.op = op;
+ this.extendedInputTypeCases = extendedInputTypeCases;
+ this.createInputTypeGroup = createInputTypeGroup;
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fShaderMatrixTest.InputType} type
+ */
+ es3fShaderMatrixTest.InputTypeSpec = function (name, desc, type) {
+ this.name = name;
+ this.desc = desc;
+ this.type = type;
+ };
+
+ es3fShaderMatrixTest.init = function () {
+ var state = tcuTestCase.runner;
+
+ var ops = [
+ new es3fShaderMatrixTest.ops('add', 'Matrix addition tests', es3fShaderMatrixTest.MatrixOp.OP_ADD, true, true),
+ new es3fShaderMatrixTest.ops('sub', 'Matrix subtraction tests', es3fShaderMatrixTest.MatrixOp.OP_SUB, true, true),
+ new es3fShaderMatrixTest.ops('mul', 'Matrix multiplication tests', es3fShaderMatrixTest.MatrixOp.OP_MUL, true, true),
+ new es3fShaderMatrixTest.ops('div', 'Matrix division tests', es3fShaderMatrixTest.MatrixOp.OP_DIV, true, true),
+ new es3fShaderMatrixTest.ops('matrixcompmult', 'Matrix component-wise multiplication tests', es3fShaderMatrixTest.MatrixOp.OP_COMP_MUL, false, true),
+ new es3fShaderMatrixTest.ops('outerproduct', 'Matrix outerProduct() tests', es3fShaderMatrixTest.MatrixOp.OP_OUTER_PRODUCT, false, true),
+ new es3fShaderMatrixTest.ops('transpose', 'Matrix transpose() tests', es3fShaderMatrixTest.MatrixOp.OP_TRANSPOSE, false, true),
+ new es3fShaderMatrixTest.ops('determinant', 'Matrix determinant() tests', es3fShaderMatrixTest.MatrixOp.OP_DETERMINANT, false, true),
+ new es3fShaderMatrixTest.ops('inverse', 'Matrix inverse() tests', es3fShaderMatrixTest.MatrixOp.OP_INVERSE, false, true),
+ new es3fShaderMatrixTest.ops('unary_addition', 'Matrix unary addition tests', es3fShaderMatrixTest.MatrixOp.OP_UNARY_PLUS, false, false),
+ new es3fShaderMatrixTest.ops('negation', 'Matrix negation tests', es3fShaderMatrixTest.MatrixOp.OP_NEGATION, false, false),
+ new es3fShaderMatrixTest.ops('pre_increment', 'Matrix prefix increment tests', es3fShaderMatrixTest.MatrixOp.OP_PRE_INCREMENT, false, false),
+ new es3fShaderMatrixTest.ops('pre_decrement', 'Matrix prefix decrement tests', es3fShaderMatrixTest.MatrixOp.OP_PRE_DECREMENT, false, false),
+ new es3fShaderMatrixTest.ops('post_increment', 'Matrix postfix increment tests', es3fShaderMatrixTest.MatrixOp.OP_POST_INCREMENT, false, false),
+ new es3fShaderMatrixTest.ops('post_decrement', 'Matrix postfix decrement tests', es3fShaderMatrixTest.MatrixOp.OP_POST_DECREMENT, false, false),
+ new es3fShaderMatrixTest.ops('add_assign', 'Matrix add into tests', es3fShaderMatrixTest.MatrixOp.OP_ADD_INTO, false, false),
+ new es3fShaderMatrixTest.ops('sub_assign', 'Matrix subtract from tests', es3fShaderMatrixTest.MatrixOp.OP_SUBTRACT_FROM,false, false),
+ new es3fShaderMatrixTest.ops('mul_assign', 'Matrix multiply into tests', es3fShaderMatrixTest.MatrixOp.OP_MULTIPLY_INTO,false, false),
+ new es3fShaderMatrixTest.ops('div_assign', 'Matrix divide into tests', es3fShaderMatrixTest.MatrixOp.OP_DIVIDE_INTO,false, false)
+ ];
+
+ var extendedInputTypes = [
+ new es3fShaderMatrixTest.InputTypeSpec('const', 'Constant matrix input', es3fShaderMatrixTest.InputType.INPUTTYPE_CONST),
+ new es3fShaderMatrixTest.InputTypeSpec('uniform', 'Uniform matrix input', es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM),
+ new es3fShaderMatrixTest.InputTypeSpec('dynamic', 'Dynamic matrix input', es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC)
+ ];
+
+ var reducedInputTypes = [
+ new es3fShaderMatrixTest.InputTypeSpec('dynamic', 'Dynamic matrix input', es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC)
+ ];
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var matrixTypes = [
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3,
+ gluShaderUtil.DataType.FLOAT_MAT4
+ ];
+
+ /** @type {Array<gluShaderUtil.precision>} */ var precisions = [
+ gluShaderUtil.precision.PRECISION_LOWP,
+ gluShaderUtil.precision.PRECISION_MEDIUMP,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ ];
+
+ for (var opNdx = 0; opNdx < ops.length; opNdx++) {
+ var inTypeList = ops[opNdx].extendedInputTypeCases ? extendedInputTypes : reducedInputTypes;
+ var inTypeListSize = ops[opNdx].extendedInputTypeCases ? extendedInputTypes.length : reducedInputTypes.length;
+ var op = ops[opNdx].op;
+
+ for (var inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++) {
+ var inputType = inTypeList[inTypeNdx].type;
+ var group = [];
+
+ if (ops[opNdx].name != 'mul') {
+ if (ops[opNdx].createInputTypeGroup) {
+ group[0] = tcuTestCase.newTest(ops[opNdx].name + '.' + inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
+ } else {
+ group[0] = tcuTestCase.newTest(ops[opNdx].name, ops[opNdx].desc);
+ }
+ state.testCases.addChild(group[0]);
+ } else {
+ for (var ii = 0; ii < precisions.length; ++ii) {
+ group[ii] = tcuTestCase.newTest(ops[opNdx].name + '.' + inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
+ state.testCases.addChild(group[ii]);
+ }
+ }
+
+ for (var matTypeNdx = 0; matTypeNdx < matrixTypes.length; matTypeNdx++) {
+ var matType = matrixTypes[matTypeNdx];
+ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(matType);
+ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(matType);
+ var matTypeName = gluShaderUtil.getDataTypeName(matType);
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ var inGroup;
+ if (ops[opNdx].name != 'mul') {
+ inGroup = group[0];
+ } else {
+ inGroup = group[precNdx];
+ }
+
+ var precision = precisions[precNdx];
+ var precName = gluShaderUtil.getPrecisionName(precision);
+ var baseName = precName + '_' + matTypeName + '_';
+ var matIn = new es3fShaderMatrixTest.ShaderInput(inputType, matType, precision);
+
+ if (es3fShaderMatrixTest.isOperationMatrixScalar(op)) {
+ // Matrix-scalar \note For div cases we use uniform input.
+ var scalarIn = new es3fShaderMatrixTest.ShaderInput(op == es3fShaderMatrixTest.MatrixOp.OP_DIV ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC, gluShaderUtil.DataType.FLOAT, precision);
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_vertex', 'Matrix-scalar case', matIn, scalarIn, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_fragment', 'Matrix-scalar case', matIn, scalarIn, op, false));
+ }
+
+ if (es3fShaderMatrixTest.isOperationMatrixVector(op)) {
+ // Matrix-vector.
+ var colVecType = gluShaderUtil.getDataTypeFloatVec(numCols);
+ var colVecIn = new es3fShaderMatrixTest.ShaderInput(op == es3fShaderMatrixTest.MatrixOp.OP_DIV ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC, colVecType, precision);
+
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + gluShaderUtil.getDataTypeName(colVecType) + '_vertex', 'Matrix-vector case', matIn, colVecIn, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + gluShaderUtil.getDataTypeName(colVecType) + '_fragment', 'Matrix-vector case', matIn, colVecIn, op, false));
+
+ // Vector-matrix.
+ var rowVecType = gluShaderUtil.getDataTypeFloatVec(numRows);
+ var rowVecIn = new es3fShaderMatrixTest.ShaderInput(op == es3fShaderMatrixTest.MatrixOp.OP_DIV ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC, rowVecType, precision);
+ var vecMatName = precName + '_' + gluShaderUtil.getDataTypeName(rowVecType) + '_' + matTypeName;
+
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(vecMatName + '_vertex', 'Vector-matrix case', rowVecIn, matIn, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(vecMatName + '_fragment', 'Vector-matrix case', rowVecIn, matIn, op, false));
+ }
+
+ if (es3fShaderMatrixTest.isOperationArithmeticMatrixMatrix(op)) {
+ // Arithmetic matrix-matrix multiplication.
+ for (var otherCols = 2; otherCols <= 4; otherCols++) {
+ var otherMatIn = new es3fShaderMatrixTest.ShaderInput(inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : inputType, gluShaderUtil.getDataTypeMatrix(otherCols, numCols), precision);
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + gluShaderUtil.getDataTypeName(otherMatIn.dataType) + '_vertex', 'Matrix-matrix case', matIn, otherMatIn, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + gluShaderUtil.getDataTypeName(otherMatIn.dataType) + '_fragment', 'Matrix-matrix case', matIn, otherMatIn, op, false));
+ }
+ } else if (es3fShaderMatrixTest.isOperationComponentwiseMatrixMatrix(op)) {
+ // Component-wise.
+ var otherMatIn = new es3fShaderMatrixTest.ShaderInput(inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : inputType, matType, precision);
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + matTypeName + '_vertex', 'Matrix-matrix case', matIn, otherMatIn, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + matTypeName + '_fragment', 'Matrix-matrix case', matIn, otherMatIn, op, false));
+ }
+
+ if (es3fShaderMatrixTest.isOperationVectorVector(op)) {
+ var vec1In = new es3fShaderMatrixTest.ShaderInput(inputType, gluShaderUtil.getDataTypeFloatVec(numRows), precision);
+ var vec2In = new es3fShaderMatrixTest.ShaderInput((inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC) ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : inputType, gluShaderUtil.getDataTypeFloatVec(numCols), precision);
+
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_vertex', 'Vector-vector case', vec1In, vec2In, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_fragment', 'Vector-vector case', vec1In, vec2In, op, false));
+ }
+
+ if (es3fShaderMatrixTest.isOperationUnaryAnyMatrix(op) || (es3fShaderMatrixTest.isOperationUnarySymmetricMatrix(op) && numCols == numRows)) {
+ var voidInput = new es3fShaderMatrixTest.ShaderInput();
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_vertex', 'Matrix case', matIn, voidInput, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_fragment', 'Matrix case', matIn, voidInput, op, false));
+ }
+
+ if (es3fShaderMatrixTest.isOperationAssignmentAnyMatrix(op) || (es3fShaderMatrixTest.isOperationAssignmentSymmetricMatrix(op) && numCols == numRows)) {
+ var otherMatIn = new es3fShaderMatrixTest.ShaderInput(inputType == es3fShaderMatrixTest.InputType.INPUTTYPE_DYNAMIC ? es3fShaderMatrixTest.InputType.INPUTTYPE_UNIFORM : inputType, matType, precision);
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_vertex', 'Matrix assignment case', matIn, otherMatIn, op, true));
+ inGroup.addChild(new es3fShaderMatrixTest.ShaderMatrixCase(baseName + 'float_fragment', 'Matrix assignment case', matIn, otherMatIn, op, false));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ es3fShaderMatrixTest.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'shader_matrix';
+ var testDescription = 'Shader Matrix Test';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fShaderMatrixTest.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderOperatorTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderOperatorTests.js
new file mode 100644
index 0000000000..5dfd0311d3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderOperatorTests.js
@@ -0,0 +1,3252 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderOperatorTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.delibs.debase.deMath');
+goog.require('modules.shared.glsShaderRenderCase');
+goog.require('framework.common.tcuMatrix');
+
+goog.scope(function() {
+var es3fShaderOperatorTests = functional.gles3.es3fShaderOperatorTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var deMath = framework.delibs.debase.deMath;
+var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+var tcuMatrix = framework.common.tcuMatrix;
+
+/** @const */ es3fShaderOperatorTests.MAX_INPUTS = 3;
+
+let canvasWH = 256;
+if (tcuTestCase.isQuickMode()) {
+ canvasWH = 32;
+}
+
+es3fShaderOperatorTests.stringJoin = function(elems, delim) {
+ var result = '';
+ for (var i = 0; i < elems.length; i++)
+ result += (i > 0 ? delim : '') + elems[i];
+ return result;
+};
+
+es3fShaderOperatorTests.twoValuedVec4 = function(first, second, firstMask) {
+ var elems = [];
+ for (var i = 0; i < 4; i++)
+ elems[i] = firstMask[i] ? first : second;
+
+ return 'vec4(' + es3fShaderOperatorTests.stringJoin(elems, ', ') + ')';
+};
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+var negate = function(x) {
+ return -x;
+};
+
+var addOne = function(x) {
+ return x + 1;
+};
+
+var subOne = function(x) {
+ return x - 1;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var add = function(a, b) {
+ return a + b;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var sub = function(a, b) {
+ return a - b;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var mul = function(a, b) {
+ return a * b;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var div = function(a, b) {
+ return a / b;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+var lessThan = function(a, b) {
+ return a < b ? 1 : 0;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var lessThanVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = a[i] < b[i];
+ return res
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+var lessThanEqual = function(a, b) {
+ return a <= b ? 1 : 0;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var lessThanEqualVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = a[i] <= b[i];
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var greaterThan = function(a, b) {
+ return a > b ? 1 : 0;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var greaterThanVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = a[i] > b[i];
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var greaterThanEqual = function(a, b) {
+ return a >= b ? 1 : 0;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var greaterThanEqualVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = a[i] >= b[i];
+ return res;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {number}
+ */
+var allEqual = function(a, b) {
+ return deMath.equal(a, b) ? 1 : 0;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var allEqualVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = a[i] == b[i];
+ return res;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {number}
+ */
+var anyNotEqual = function(a, b) {
+ return !deMath.equal(a, b) ? 1 : 0;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var anyNotEqualVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = a[i] != b[i];
+ return res;
+};
+
+/**
+ * @param {Array<number>} a
+ * @return {Array<number>}
+ */
+var boolNotVec = function(a) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = !a[i];
+ return res;
+}
+
+/**
+ * @param {Array<number>} a
+ * @return {boolean}
+ */
+var boolAny = function(a) {
+ for (var i = 0; i < a.length; i++)
+ if (a[i] == true)
+ return true;
+ return false;
+}
+
+/**
+ * @param {Array<number>} a
+ * @return {boolean}
+ */
+var boolAll = function(a) {
+ for (var i = 0; i < a.length; i++)
+ if (a[i] == false)
+ return false;
+ return true;
+}
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var logicalAnd = function(a, b) {
+ return a && b ? 1 : 0;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var logicalOr = function(a, b) {
+ return a || b ? 1 : 0;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ */
+var logicalXor = function(a, b) {
+ return a != b ? 1 : 0;
+};
+
+/**
+ * @param {number} a
+ */
+var exp2 = function(a) {
+ return deFloatExp2(a);
+};
+
+/**
+ * @param {number} a
+ */
+var inverseSqrt = function(a) {
+ return deFloatRsq(a);
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {number} b
+ * @return {Array<number>}
+ */
+var minVecScalar = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = Math.min(a[i], b);
+ return res;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {number} b
+ * @return {Array<number>}
+ */
+var maxVecScalar = function(a, b) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = Math.max(a[i], b);
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @param {number} c
+ * @return {number}
+ */
+var mix = function(a, b, c) {
+ return a * (1.0 - c) + b * c;
+};
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @param {number} c
+ * @return {Array<number>}
+ */
+var mixVecVecScalar = function(a, b, c) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = mix(a[i], b[i], c);
+ return res;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {number} b
+ * @param {number} c
+ * @return {Array<number>}
+ */
+var clampVecScalarScalar = function(a, b, c) {
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = deMath.clamp(a[i], b, c);
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+var step = function(a, b) {
+ return b < a ? 0.0 : 1.0;
+};
+
+/**
+ * @param {number} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var stepScalarVec = function(a, b) {
+ var res = [];
+ for (var i = 0; i < b.length; i++)
+ res[i] = step(a, b[i]);
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @param {number} c
+ * @return {number}
+ */
+var smoothStep = function(a, b, c) {
+ if (c <= a) return 0.0;
+ if (c >= b) return 1.0;
+ var t = deMath.clamp((c - a) / (b - a), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+};
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @param {Array<number>} c
+ * @return {Array<number>}
+ */
+var smoothStepScalarScalarVec = function(a, b, c) {
+ var res = [];
+ for (var i = 0; i < c.length; i++)
+ res[i] = smoothStep(a, b, c[i]);
+ return res;
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+var roundToEven = function(a) {
+ var q = deMath.deFloatFrac(a);
+ var r = a - q;
+
+ if (q > 0.5)
+ r += 1.0;
+ else if (q == 0.5 && r % 2 != 0)
+ r += 1.0;
+
+ return r;
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+var fract = function(a) {
+ return a - Math.floor(a);
+};
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+var radians = function(a) {
+ return deFloatRadians(a);
+}
+
+/**
+ * @param {number} a
+ * @return {number}
+ */
+var degrees = function(a) {
+ return deFloatDegrees(a);
+}
+
+/**
+ * @param {number} a
+ * @param {Array<number>} b
+ */
+var addScalarVec = function(a, b) {
+ return deMath.addScalar(b, a);
+};
+
+/**
+ * @param {number} a
+ * @param {Array<number>} b
+ */
+var subScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(a - b[i]);
+ return dst;
+};
+
+/**
+ * @param {number} a
+ * @param {Array<number>} b
+ */
+var mulScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(a * b[i]);
+ return dst;
+};
+
+/**
+ * @param {number} a
+ * @param {Array<number>} b
+ */
+var divScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(a / b[i]);
+ return dst;
+};
+
+/**
+ * @param {number} a
+ * @param {Array<number>} b
+ */
+var modScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(a % b[i]);
+ return dst;
+};
+
+var bitwiseAndScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(deMath.binaryOp(a, b[i], deMath.BinaryOp.AND));
+ return dst;
+};
+
+var bitwiseOrScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(deMath.binaryOp(a, b[i], deMath.BinaryOp.OR));
+ return dst;
+};
+
+var bitwiseXorScalarVec = function(a, b) {
+ var dst = [];
+ for (var i = 0; i < b.length; i++)
+ dst.push(deMath.binaryOp(a, b[i], deMath.BinaryOp.XOR));
+ return dst;
+};
+
+/**
+ * @param {Array<number>} a
+ * @return {number}
+ */
+var length = function(a) {
+ var squareSum = 0;
+ for (var i = 0; i < a.length; i++)
+ squareSum += a[i] * a[i];
+ return Math.sqrt(squareSum);
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {number}
+ */
+var distance = function(a, b) {
+ var res = deMath.subtract(a, b)
+ return length(res);
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {number}
+ */
+var dot = function(a, b) {
+ var res = deMath.multiply(a, b);
+ var sum = 0;
+ for (var i = 0; i < res.length; i++)
+ sum += res[i];
+ return sum;
+};
+
+/**
+ * @param {Array<number>} a
+ * @return {Array<number>}
+ */
+var normalize = function(a) {
+ var ooLen = 1 / length(a);
+ var res = [];
+ for (var i = 0; i < a.length; i++)
+ res[i] = ooLen * a[i];
+ return res;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @param {Array<number>} c
+ * @return {Array<number>}
+ */
+var faceforward = function(a, b, c) {
+ return dot(c, b) < 0 ? a : deMath.scale(a, -1);
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var reflect = function(a, b) {
+ return deMath.subtract(a, deMath.scale(deMath.scale(b, dot(b, a)), 2));
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @param {number} c
+ * @return {Array<number>}
+ */
+var refract = function(a, b, c) {
+ var cosAngle = dot(b, a);
+ var k = 1 - c * c * (1 - cosAngle * cosAngle);
+ if (k < 0) {
+ var res = new Array(a.length);
+ return res.fill(0)
+ } else
+ return deMath.subtract(deMath.scale(a, c), deMath.scale(b, c * cosAngle + Math.sqrt(k)));
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @return {Array<number>}
+ */
+var cross = function(a, b) {
+ if (a.length != 3 || b.length != 3)
+ throw new Error('Arrays must have the size of 3');
+ return [
+ a[1] * b[2] - b[1] * a[2],
+ a[2] * b[0] - b[2] * a[0],
+ a[0] * b[1] - b[0] * a[1]];
+};
+
+var nop = function(v) {
+ return v;
+};
+
+var selection = function(cond, a, b) {
+ return cond ? a : b;
+};
+
+var boolNot = function(a) {
+ return !a;
+};
+
+var bitwiseNot = function(a) {
+ return ~a;
+};
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+var deFloatRadians = function(x) {
+ return x * (Math.PI / 180.0);
+};
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+var deFloatDegrees = function(x) {
+ return x * (180.0 / Math.PI);
+};
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+var deFloatExp2 = function(x) {
+ return Math.exp(x * Math.LN2);
+};
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+var deFloatLog2 = function(x) {
+ return Math.log(x) * Math.LOG2E;
+};
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+var deFloatRsq = function(x) {
+ var s = Math.sqrt(x);
+ return s == 0.0 ? 0.0 : (1.0 / s);
+};
+
+/**
+ * @constructor
+ * @param {boolean} low
+ * @param {boolean} medium
+ * @param {boolean} high
+ */
+es3fShaderOperatorTests.Precision = function(low, medium, high) {
+ this.low = low;
+ this.medium = medium;
+ this.high = high;
+};
+
+/** @const */ es3fShaderOperatorTests.Precision.Low = new es3fShaderOperatorTests.Precision(true, false, false);
+/** @const */ es3fShaderOperatorTests.Precision.Medium = new es3fShaderOperatorTests.Precision(false, true, false);
+/** @const */ es3fShaderOperatorTests.Precision.High = new es3fShaderOperatorTests.Precision(false, false, true);
+/** @const */ es3fShaderOperatorTests.Precision.LowMedium = new es3fShaderOperatorTests.Precision(true, true, false);
+/** @const */ es3fShaderOperatorTests.Precision.MediumHigh = new es3fShaderOperatorTests.Precision(false, true, true);
+/** @const */ es3fShaderOperatorTests.Precision.All = new es3fShaderOperatorTests.Precision(true, true, true);
+/** @const */ es3fShaderOperatorTests.Precision.None = new es3fShaderOperatorTests.Precision(false, false, false);
+
+/**
+ * @enum
+ */
+es3fShaderOperatorTests.ValueType = {
+ NONE: 0,
+ FLOAT: (1 << 0), // float scalar
+ FLOAT_VEC: (1 << 1), // float vector
+ FLOAT_GENTYPE: (1 << 2), // float scalar/vector
+ VEC3: (1 << 3), // vec3 only
+ MATRIX: (1 << 4), // matrix
+ BOOL: (1 << 5), // boolean scalar
+ BOOL_VEC: (1 << 6), // boolean vector
+ BOOL_GENTYPE: (1 << 7), // boolean scalar/vector
+ INT: (1 << 8), // int scalar
+ INT_VEC: (1 << 9), // int vector
+ INT_GENTYPE: (1 << 10), // int scalar/vector
+ UINT: (1 << 11), // uint scalar
+ UINT_VEC: (1 << 12), // uint vector
+ UINT_GENTYPE: (1 << 13) // uint scalar/vector
+};
+
+/**
+ * @param {es3fShaderOperatorTests.ValueType} type
+ * @return {boolean}
+ */
+es3fShaderOperatorTests.isBoolType = function(type) {
+ return (type & (es3fShaderOperatorTests.ValueType.BOOL | es3fShaderOperatorTests.ValueType.BOOL_VEC | es3fShaderOperatorTests.ValueType.BOOL_GENTYPE)) != 0;
+};
+
+/**
+ * @param {es3fShaderOperatorTests.ValueType} type
+ * @return {boolean}
+ */
+es3fShaderOperatorTests.isIntType = function(type) {
+ return (type & (es3fShaderOperatorTests.ValueType.INT | es3fShaderOperatorTests.ValueType.INT_VEC | es3fShaderOperatorTests.ValueType.INT_GENTYPE)) != 0;
+};
+
+/**
+ * @param {es3fShaderOperatorTests.ValueType} type
+ * @return {boolean}
+ */
+es3fShaderOperatorTests.isUintType = function(type) {
+ return (type & (es3fShaderOperatorTests.ValueType.UINT | es3fShaderOperatorTests.ValueType.UINT_VEC | es3fShaderOperatorTests.ValueType.UINT_GENTYPE)) != 0;
+};
+
+/**
+ * @param {es3fShaderOperatorTests.ValueType} type
+ * @return {boolean}
+ */
+es3fShaderOperatorTests.isScalarType = function(type) {
+ return type == es3fShaderOperatorTests.ValueType.FLOAT || type == es3fShaderOperatorTests.ValueType.BOOL || type == es3fShaderOperatorTests.ValueType.INT || type == es3fShaderOperatorTests.ValueType.UINT;
+};
+
+/**
+ * @param {es3fShaderOperatorTests.ValueType} type
+ * @return {boolean}
+ */
+es3fShaderOperatorTests.isFloatType = function(type) {
+ return (type & (es3fShaderOperatorTests.ValueType.FLOAT | es3fShaderOperatorTests.ValueType.FLOAT_VEC | es3fShaderOperatorTests.ValueType.FLOAT_GENTYPE)) != 0;
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {gluShaderUtil.precision} uintPrecision
+ * @return {number}
+ */
+es3fShaderOperatorTests.getGLSLUintMaxAsFloat = function(shaderType, uintPrecision) {
+ switch (uintPrecision) {
+ case gluShaderUtil.precision.PRECISION_LOWP:
+ var intPrecisionGL = gl.LOW_INT;
+ break;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP:
+ var intPrecisionGL = gl.MEDIUM_INT;
+ break;
+ case gluShaderUtil.precision.PRECISION_HIGHP:
+ var intPrecisionGL = gl.HIGH_INT;
+ break;
+ default:
+ assertMsgOptions(false, 'Invalid shader type', false, false);
+ var intPrecisionGL = 0;
+ }
+
+ switch (shaderType) {
+ case gluShaderProgram.shaderType.VERTEX:
+ var shaderTypeGL = gl.VERTEX_SHADER;
+ break;
+ case gluShaderProgram.shaderType.FRAGMENT:
+ var shaderTypeGL = gl.FRAGMENT_SHADER;
+ break;
+ default:
+ assertMsgOptions(false, 'Invalid shader type', false, false);
+ var shaderTypeGL = 0;
+ }
+
+ /** @type {WebGLShaderPrecisionFormat } */ var sPrecision = gl.getShaderPrecisionFormat(shaderTypeGL, intPrecisionGL);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'glGetShaderPrecisionFormat failed', false, true);
+
+ if (!deMath.deInBounds32(sPrecision.rangeMin, 8, 32))
+ throw new Error('Out of range');
+
+ var numBitsInType = sPrecision.rangeMin + 1;
+ return Math.pow(2, numBitsInType) - 1;
+};
+
+/**
+ * @enum
+ */
+es3fShaderOperatorTests.OperationType = {
+ FUNCTION: 0,
+ OPERATOR: 1,
+ SIDE_EFFECT_OPERATOR: 2 // Test the side-effect (as opposed to the result) of a side-effect operator.
+};
+
+/**
+ * swizzling indices for assigning the tested function output to the correct color channel
+ */
+es3fShaderOperatorTests.outIndices = [];
+es3fShaderOperatorTests.outIndices[1] = [0];
+es3fShaderOperatorTests.outIndices[2] = [1, 2];
+es3fShaderOperatorTests.outIndices[3] = [0, 1, 2];
+es3fShaderOperatorTests.outIndices[4] = [0, 1, 2, 3];
+
+var convert = function(input, dataType) {
+ switch (dataType) {
+ case gluShaderUtil.DataType.INT:
+ if (input instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < input.length; i++)
+ ret[i] = deMath.intCast(input[i]);
+ return ret;
+ }
+ return deMath.intCast(input);
+ case gluShaderUtil.DataType.UINT:
+ if (input instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < input.length; i++)
+ ret[i] = deMath.uintCast(input[i]);
+ return ret;
+ }
+ return deMath.uintCast(input);
+ case gluShaderUtil.DataType.BOOL:
+ if (input instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < input.length; i++)
+ ret[i] = input[i] > 0 ? 1 : 0;
+ return ret;
+ }
+ return input > 0 ? 1 : 0;
+
+ }
+ return input;
+};
+
+/**
+ * Generate unary functions which have the same input and return type
+ * @param {function(number): number} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.unaryGenTypeFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input) {
+ if (input instanceof Array) {
+ var len = input.length;
+ var indices = es3fShaderOperatorTests.outIndices[len];
+ for (var i = 0; i < input.length; i++)
+ output[indices[i]] = convert(func(convert(input[i], dataTypeIn)), dataTypeOut);
+ } else
+ output[0] = convert(func(convert(input, dataTypeIn)), dataTypeOut);
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, c.in_[0][2]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0])); };
+ return functions;
+};
+
+/**
+ * Generate unary functions which have the same input and return type
+ * @param {function(Array<number>): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.unaryArrayFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input) {
+ var len = input.length;
+ var indices = es3fShaderOperatorTests.outIndices[len];
+ var value = convert(func(convert(input, dataTypeIn)), dataTypeOut);
+ for (var i = 0; i < input.length; i++)
+ output[indices[i]] = value[i];
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, [c.in_[0][2]]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0])); };
+ return functions;
+};
+
+/**
+ * Generate unary functions which always have scalar return type
+ * @param {function(Array<number>): number} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.unaryScalarGenTypeFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input) {
+ output[0] = convert(func(convert(input, dataTypeIn)), dataTypeOut);
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, [c.in_[0][2]]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0])); };
+ return functions;
+};
+
+/**
+ * Generate unary functions which always have bolean return type
+ * @param {function(Array<number>): boolean} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.unaryBooleanGenTypeFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input) {
+ output[0] = convert(func(convert(input, dataTypeIn)), dataTypeOut);
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, [c.in_[0][2] > 0.0]); };
+ functions.vec2 = function(c) { run(c.color, func, greaterThanVec(deMath.swizzle(c.in_[0], [3, 1]), [0, 0])); };
+ functions.vec3 = function(c) { run(c.color, func, greaterThanVec(deMath.swizzle(c.in_[0], [2, 0, 1]), [0, 0, 0])); };
+ functions.vec4 = function(c) { run(c.color, func, greaterThanVec(deMath.swizzle(c.in_[0], [1, 2, 3, 0]), [0, 0, 0, 0])); };
+ return functions;
+};
+
+/**
+ * Generate binary functions which have the same input and return type
+ * @param {function(number, number): number} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.binaryGenTypeFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input1, input2) {
+ if (input1 instanceof Array) {
+ var len = input1.length;
+ var indices = es3fShaderOperatorTests.outIndices[len];
+ for (var i = 0; i < input1.length; i++)
+ output[indices[i]] = convert(func(convert(input1[i], dataTypeIn), convert(input2[i], dataTypeIn)), dataTypeOut);
+ } else {
+ var value = convert(func(convert(input1, dataTypeIn), convert(input2, dataTypeIn)), dataTypeOut);
+ output[0] = value;
+ }
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, c.in_[0][2], c.in_[1][0]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), deMath.swizzle(c.in_[1], [1, 0])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), deMath.swizzle(c.in_[1], [1, 2, 0])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), deMath.swizzle(c.in_[1], [3, 2, 1, 0])); };
+ return functions;
+};
+
+/**
+ * Generate binary functions which have the same input and return type
+ * @param {function(number, number, number): number} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.ternaryGenTypeFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input1, input2, input3) {
+ if (input1 instanceof Array) {
+ var len = input1.length;
+ var indices = es3fShaderOperatorTests.outIndices[len];
+ for (var i = 0; i < input1.length; i++)
+ output[indices[i]] = convert(func(convert(input1[i], dataTypeIn), convert(input2[i], dataTypeIn), convert(input3[i], dataTypeIn)), dataTypeOut);
+ } else {
+ var value = convert(func(convert(input1, dataTypeIn), convert(input2, dataTypeIn), convert(input3, dataTypeIn)), dataTypeOut);
+ output[0] = value;
+ }
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, c.in_[0][2], c.in_[1][0], c.in_[2][1]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), deMath.swizzle(c.in_[1], [1, 0]), deMath.swizzle(c.in_[2], [2, 1])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), deMath.swizzle(c.in_[1], [1, 2, 0]), deMath.swizzle(c.in_[2], [3, 1, 2])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), deMath.swizzle(c.in_[1], [3, 2, 1, 0]), deMath.swizzle(c.in_[2], [0, 3, 2, 1])); };
+ return functions;
+};
+
+/**
+ * Generate binary functions which have the same input and return type
+ * @param {function(Array<number>, Array<number>): number} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.binaryScalarGenTypeFuncs = function(func, dataTypeOut, dataTypeIn) {
+ var run = function(output, func, input1, input2) {
+ var value = convert(func(convert(input1, dataTypeIn), convert(input2, dataTypeIn)), dataTypeOut);
+ output[0] = value;
+ };
+
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, [c.in_[0][2]], [c.in_[1][0]]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), deMath.swizzle(c.in_[1], [1, 0])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), deMath.swizzle(c.in_[1], [1, 2, 0])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), deMath.swizzle(c.in_[1], [3, 2, 1, 0])); };
+ return functions;
+};
+
+/**
+ * Generate (cond ? a : b) functions
+ * @param {gluShaderUtil.DataType} dataType
+ * Returns an array of functions, indexed by datatype size
+ */
+es3fShaderOperatorTests.selectionFuncs = function(dataType) {
+ var run = function(output, input0, input1, input2) {
+ var value = selection(input0, input1, input2);
+ value = convert(value, dataType);
+ if (value instanceof Array) {
+ var len = value.length;
+ var indices = es3fShaderOperatorTests.outIndices[len];
+ for (var i = 0; i < len; i++)
+ output[indices[i]] = value[i];
+ } else
+ output[0] = value;
+ };
+
+ var functions = [];
+ functions[1] = function(c) { run(c.color, c.in_[0][2] > 0, c.in_[1][0], c.in_[2][1]); };
+ functions[2] = function(c) { run(c.color, c.in_[0][2] > 0, deMath.swizzle(c.in_[1], [1, 0]), deMath.swizzle(c.in_[2], [2, 1])); };
+ functions[3] = function(c) { run(c.color, c.in_[0][2] > 0, deMath.swizzle(c.in_[1], [1, 2, 0]), deMath.swizzle(c.in_[2], [3, 1, 2])); };
+ functions[4] = function(c) { run(c.color, c.in_[0][2] > 0, deMath.swizzle(c.in_[1], [3, 2, 1, 0]), deMath.swizzle(c.in_[2], [0, 3, 2, 1])); };
+ return functions;
+};
+
+var cp = function(dst, src) {
+ var len = src.length;
+ var indices = es3fShaderOperatorTests.outIndices[len];
+ for (var i = 0; i < len; i++)
+ dst[indices[i]] = src[i];
+};
+
+/**
+ * Generate binary functions of form: vec = func(scalar, vec)
+ * @param {function(number, Array<number>): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.binaryScalarVecFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(number, Array<number>): Array<number>} func
+ * @param {number} input1
+ * @param {Array<number>} input2
+ */
+ var run = function(output, func, input1, input2) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var value = func(in1, in2);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.vec2 = function(c) { run(c.color, func, c.in_[0][2], deMath.swizzle(c.in_[1], [1, 0])); };
+ functions.vec3 = function(c) { run(c.color, func, c.in_[0][2], deMath.swizzle(c.in_[1], [1, 2, 0])); };
+ functions.vec4 = function(c) { run(c.color, func, c.in_[0][2], deMath.swizzle(c.in_[1], [3, 2, 1, 0])); };
+ return functions;
+};
+
+/**
+ * Generate binary functions of form: vec = func(vec, scalar)
+ * @param {function(Array<number>, number): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.binaryVecScalarFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(Array<number>, number): Array<number>} func
+ * @param {Array<number>} input1
+ * @param {number} input2
+ */
+ var run = function(output, func, input1, input2) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var value = func(in1, in2);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), c.in_[1][0]); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), c.in_[1][0]); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), c.in_[1][0]); };
+ return functions;
+};
+
+/**
+ * Generate binary functions of form: vec = func(vec, vec, scalar)
+ * @param {function(Array<number>, Array<number>, number): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.ternaryVecVecScalarFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(Array<number>, Array<number>, number): Array<number>} func
+ * @param {Array<number>} input1
+ * @param {Array<number>} input2
+ * @param {number} input3
+ */
+ var run = function(output, func, input1, input2, input3) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var in3 = convert(input3, dataTypeIn);
+ var value = func(in1, in2, in3);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.scalar = function(c) { run(c.color, func, [c.in_[0][2]], [c.in_[1][0]], c.in_[2][1]); };
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), deMath.swizzle(c.in_[1], [1, 0]), c.in_[2][1]); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), deMath.swizzle(c.in_[1], [1, 2, 0]), c.in_[2][1]); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), deMath.swizzle(c.in_[1], [3, 2, 1, 0]), c.in_[2][1]); };
+ return functions;
+};
+
+/**
+ * Generate binary functions of form: vec = func(vec, scalar, scalar)
+ * @param {function(Array<number>, number, number): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.ternaryVecScalarScalarFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(Array<number>, number, number): Array<number>} func
+ * @param {Array<number>} input1
+ * @param {number} input2
+ * @param {number} input3
+ */
+ var run = function(output, func, input1, input2, input3) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var in3 = convert(input3, dataTypeIn);
+ var value = func(in1, in2, in3);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), c.in_[1][0], c.in_[2][1]); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), c.in_[1][0], c.in_[2][1]); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), c.in_[1][0], c.in_[2][1]); };
+ return functions;
+};
+
+/**
+ * Generate binary functions of form: vec = func(scalar, scalar, vec)
+ * @param {function(number, number, Array<number>): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.ternaryScalarScalarVecFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(number, number, Array<number>): Array<number>} func
+ * @param {number} input1
+ * @param {number} input2
+ * @param {Array<number>} input3
+ */
+ var run = function(output, func, input1, input2, input3) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var in3 = convert(input3, dataTypeIn);
+ var value = func(in1, in2, in3);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.vec2 = function(c) { run(c.color, func, c.in_[0][2], c.in_[1][0], deMath.swizzle(c.in_[2], [2, 1])); };
+ functions.vec3 = function(c) { run(c.color, func, c.in_[0][2], c.in_[1][0], deMath.swizzle(c.in_[2], [3, 1, 2])); };
+ functions.vec4 = function(c) { run(c.color, func, c.in_[0][2], c.in_[1][0], deMath.swizzle(c.in_[2], [0, 3, 2, 1])); };
+ return functions;
+};
+
+/**
+ * Generate binary functions of form: vec = func(vec, vec, vec)
+ * @param {function(Array<number>, Array<number>, Array<number>): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.ternaryVecVecVecFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(Array<number>, Array<number>, Array<number>): Array<number>} func
+ * @param {Array<number>} input1
+ * @param {Array<number>} input2
+ * @param {Array<number>} input3
+ */
+ var run = function(output, func, input1, input2, input3) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var in3 = convert(input3, dataTypeIn);
+ var value = func(in1, in2, in3);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), deMath.swizzle(c.in_[1], [1, 0]), deMath.swizzle(c.in_[2], [2, 1])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), deMath.swizzle(c.in_[1], [1, 2, 0]), deMath.swizzle(c.in_[2], [3, 1, 2])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), deMath.swizzle(c.in_[1], [3, 2, 1, 0]), deMath.swizzle(c.in_[2], [0, 3, 2, 1])); };
+ return functions;
+};
+
+/**
+ * Generate binary functions of form: vec = func(vec, vec)
+ * @param {function(Array<number>, Array<number>): Array<number>} func
+ * @param {gluShaderUtil.DataType=} dataTypeIn
+ * @param {gluShaderUtil.DataType=} dataTypeOut
+ */
+es3fShaderOperatorTests.binaryVecVecFuncs = function(func, dataTypeOut, dataTypeIn) {
+ /**
+ * @param {function(Array<number>, Array<number>): Array<number>} func
+ * @param {Array<number>} input1
+ * @param {Array<number>} input2
+ */
+ var run = function(output, func, input1, input2) {
+ var in1 = convert(input1, dataTypeIn);
+ var in2 = convert(input2, dataTypeIn);
+ var value = func(in1, in2);
+ value = convert(value, dataTypeOut);
+ cp(output, value);
+ };
+ var functions = {};
+ functions.vec2 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [3, 1]), deMath.swizzle(c.in_[1], [1, 0])); };
+ functions.vec3 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [2, 0, 1]), deMath.swizzle(c.in_[1], [1, 2, 0])); };
+ functions.vec4 = function(c) { run(c.color, func, deMath.swizzle(c.in_[0], [1, 2, 3, 0]), deMath.swizzle(c.in_[1], [3, 2, 1, 0])); };
+ return functions;
+};
+
+/**
+ * @constructor
+ * @param {es3fShaderOperatorTests.ValueType} valueType
+ * @param {es3fShaderOperatorTests.FloatScalar} rangeMin
+ * @param {es3fShaderOperatorTests.FloatScalar} rangeMax
+ */
+es3fShaderOperatorTests.Value = function(valueType, rangeMin, rangeMax) {
+ this.valueType = valueType;
+ this.rangeMin = rangeMin;
+ this.rangeMax = rangeMax;
+};
+
+/**
+ * @enum
+ */
+es3fShaderOperatorTests.Symbol = {
+ SYMBOL_LOWP_UINT_MAX: 0,
+ SYMBOL_MEDIUMP_UINT_MAX: 1,
+
+ SYMBOL_LOWP_UINT_MAX_RECIPROCAL: 2,
+ SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL: 3,
+
+ SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX: 4,
+ SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX: 5
+
+};
+
+/**
+ * @constructor
+ * @param {number|es3fShaderOperatorTests.Symbol} value
+ * @param {boolean=} isSymbol
+ */
+es3fShaderOperatorTests.FloatScalar = function(value, isSymbol) {
+ if (isSymbol)
+ this.symbol = /** @type {es3fShaderOperatorTests.Symbol} */ (value);
+ else
+ this.constant = /** @type {number} */ (value);
+};
+
+/**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {number}
+ */
+es3fShaderOperatorTests.FloatScalar.prototype.getValue = function(shaderType) {
+ if (this.constant !== undefined)
+ return this.constant;
+ else
+ switch (this.symbol) {
+ case es3fShaderOperatorTests.Symbol.SYMBOL_LOWP_UINT_MAX:
+ return es3fShaderOperatorTests.getGLSLUintMaxAsFloat(shaderType, gluShaderUtil.precision.PRECISION_LOWP);
+ case es3fShaderOperatorTests.Symbol.SYMBOL_MEDIUMP_UINT_MAX:
+ return es3fShaderOperatorTests.getGLSLUintMaxAsFloat(shaderType, gluShaderUtil.precision.PRECISION_MEDIUMP);
+
+ case es3fShaderOperatorTests.Symbol.SYMBOL_LOWP_UINT_MAX_RECIPROCAL:
+ return 1.0 / es3fShaderOperatorTests.getGLSLUintMaxAsFloat(shaderType, gluShaderUtil.precision.PRECISION_LOWP);
+ case es3fShaderOperatorTests.Symbol.SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL:
+ return 1.0 / es3fShaderOperatorTests.getGLSLUintMaxAsFloat(shaderType, gluShaderUtil.precision.PRECISION_MEDIUMP);
+
+ case es3fShaderOperatorTests.Symbol.SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX:
+ return 1.0 - 0xFFFFFFFF / es3fShaderOperatorTests.getGLSLUintMaxAsFloat(shaderType, gluShaderUtil.precision.PRECISION_LOWP);
+ case es3fShaderOperatorTests.Symbol.SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX:
+ return 1.0 - 0xFFFFFFFF / es3fShaderOperatorTests.getGLSLUintMaxAsFloat(shaderType, gluShaderUtil.precision.PRECISION_MEDIUMP);
+
+ default:
+ assertMsgOptions(false, 'Invalid shader type', false, false);
+ return 0.0;
+ }
+};
+
+/**
+ * @constructor
+ * @param {gluShaderUtil.DataType=} type
+ * @param {es3fShaderOperatorTests.FloatScalar=} rangeMin
+ * @param {es3fShaderOperatorTests.FloatScalar=} rangeMax
+ */
+es3fShaderOperatorTests.ShaderValue = function(type, rangeMin, rangeMax) {
+ this.type = type || gluShaderUtil.DataType.INVALID;
+ this.rangeMin = rangeMin || new es3fShaderOperatorTests.FloatScalar(0);
+ this.rangeMax = rangeMax || new es3fShaderOperatorTests.FloatScalar(0);
+};
+
+/**
+ * @constructor
+ */
+es3fShaderOperatorTests.ShaderDataSpec = function() {
+ /** @type {es3fShaderOperatorTests.FloatScalar} */ this.resultScale = new es3fShaderOperatorTests.FloatScalar(1);
+ /** @type {es3fShaderOperatorTests.FloatScalar} */ this.resultBias = new es3fShaderOperatorTests.FloatScalar(0);
+ /** @type {es3fShaderOperatorTests.FloatScalar} */ this.referenceScale = new es3fShaderOperatorTests.FloatScalar(1);
+ /** @type {es3fShaderOperatorTests.FloatScalar} */ this.referenceBias = new es3fShaderOperatorTests.FloatScalar(0);
+ /** @type {es3fShaderOperatorTests.Precision} */ this.precision = es3fShaderOperatorTests.Precision.None;
+ /** @type {gluShaderUtil.DataType} */ this.output;
+ /** @type {number} */ this.numInputs = 0;
+ /** @type {Array<es3fShaderOperatorTests.ShaderValue>}*/ this.inputs = [];
+ for (var i = 0; i < es3fShaderOperatorTests.MAX_INPUTS; i++)
+ this.inputs[i] = new es3fShaderOperatorTests.ShaderValue();
+};
+
+/**
+ * @constructor
+ * @struct
+ * @param {string} caseName
+ * @param {string} shaderFuncName
+ * @param {es3fShaderOperatorTests.ValueType} outValue
+ * @param {Array<es3fShaderOperatorTests.Value>} inputs
+ * @param {es3fShaderOperatorTests.FloatScalar} resultScale
+ * @param {es3fShaderOperatorTests.FloatScalar} resultBias
+ * @param {es3fShaderOperatorTests.FloatScalar} referenceScale
+ * @param {es3fShaderOperatorTests.FloatScalar} referenceBias
+ * @param {gluShaderUtil.precision} precision
+ * @param {*} functions
+ * @param {es3fShaderOperatorTests.OperationType=} type
+ * @param {boolean=} isUnaryPrefix
+ */
+es3fShaderOperatorTests.BuiltinFuncInfo = function(caseName, shaderFuncName, outValue, inputs, resultScale, resultBias, referenceScale, referenceBias, precision, functions, type, isUnaryPrefix) {
+ this.caseName = caseName;
+ this.shaderFuncName = shaderFuncName;
+ this.outValue = outValue;
+ this.inputs = inputs;
+ this.resultScale = resultScale;
+ this.resultBias = resultBias;
+ this.referenceScale = referenceScale;
+ this.referenceBias = referenceBias;
+ this.precision = precision;
+ this.evalFunctions = functions;
+ this.type = type || es3fShaderOperatorTests.OperationType.FUNCTION;
+ this.isUnaryPrefix = isUnaryPrefix === undefined ? true : isUnaryPrefix;
+};
+
+es3fShaderOperatorTests.builtinOperInfo = function(caseName, shaderFuncName, outValue, inputs, scale, bias, precision, functions) {
+ return new es3fShaderOperatorTests.BuiltinFuncInfo(caseName,
+ shaderFuncName,
+ outValue,
+ inputs,
+ scale,
+ bias,
+ scale,
+ bias,
+ precision,
+ functions,
+ es3fShaderOperatorTests.OperationType.OPERATOR);
+};
+
+es3fShaderOperatorTests.builtinFunctionInfo = function(caseName, shaderFuncName, outValue, inputs, scale, bias, precision, functions) {
+ return new es3fShaderOperatorTests.BuiltinFuncInfo(caseName,
+ shaderFuncName,
+ outValue,
+ inputs,
+ scale,
+ bias,
+ scale,
+ bias,
+ precision,
+ functions,
+ es3fShaderOperatorTests.OperationType.FUNCTION);
+};
+
+es3fShaderOperatorTests.builtinSideEffOperInfo = function(caseName, shaderFuncName, outValue, inputs, scale, bias, precision, functions) {
+ return new es3fShaderOperatorTests.BuiltinFuncInfo(caseName,
+ shaderFuncName,
+ outValue,
+ inputs,
+ scale,
+ bias,
+ scale,
+ bias,
+ precision,
+ functions,
+ es3fShaderOperatorTests.OperationType.SIDE_EFFECT_OPERATOR);
+};
+
+es3fShaderOperatorTests.builtinOperInfoSeparateRefScaleBias = function(caseName, shaderFuncName, outValue, inputs, scale, bias, precision, functions, referenceScale, referenceBias) {
+ return new es3fShaderOperatorTests.BuiltinFuncInfo(caseName,
+ shaderFuncName,
+ outValue,
+ inputs,
+ scale,
+ bias,
+ referenceScale,
+ referenceBias,
+ precision,
+ functions,
+ es3fShaderOperatorTests.OperationType.OPERATOR);
+};
+
+es3fShaderOperatorTests.BuiltinPostSideEffOperInfo = function(caseName, shaderFuncName, outValue, inputs, scale, bias, precision, functions) {
+ return new es3fShaderOperatorTests.BuiltinFuncInfo(caseName,
+ shaderFuncName,
+ outValue,
+ inputs,
+ scale,
+ bias,
+ scale,
+ bias,
+ precision,
+ functions,
+ es3fShaderOperatorTests.OperationType.SIDE_EFFECT_OPERATOR,
+ false);
+};
+es3fShaderOperatorTests.BuiltinPostOperInfo = function(caseName, shaderFuncName, outValue, inputs, scale, bias, precision, functions) {
+ return new es3fShaderOperatorTests.BuiltinFuncInfo(caseName,
+ shaderFuncName,
+ outValue,
+ inputs,
+ scale,
+ bias,
+ scale,
+ bias,
+ precision,
+ functions,
+ es3fShaderOperatorTests.OperationType.OPERATOR,
+ false);
+};
+
+/**
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderOperatorTests.BuiltinFuncGroup = function(name, description) {
+ this.name = name;
+ this.description = description;
+ this.funcInfos = [];
+};
+
+es3fShaderOperatorTests.BuiltinFuncGroup.prototype.push = function(a) { this.funcInfos.push(a); };
+
+var s_inSwizzles = [
+
+ ['z', 'wy', 'zxy', 'yzwx'],
+ ['x', 'yx', 'yzx', 'wzyx'],
+ ['y', 'zy', 'wyz', 'xwzy']
+];
+
+var s_outSwizzles = ['x', 'yz', 'xyz', 'xyzw'];
+
+var s_outSwizzleChannelMasks = [
+ [true, false, false, false],
+ [false, true, true, false],
+ [true, true, true, false],
+ [true, true, true, true]
+];
+
+/**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderEvaluator}
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ * @param {es3fShaderOperatorTests.FloatScalar} scale
+ * @param {es3fShaderOperatorTests.FloatScalar} bias
+ * @param {number} resultScalarSize
+ */
+es3fShaderOperatorTests.OperatorShaderEvaluator = function(shaderType, evalFunc, scale, bias, resultScalarSize) {
+ glsShaderRenderCase.ShaderEvaluator.call(this, evalFunc);
+ this.m_shaderType = shaderType;
+ this.m_scale = scale;
+ this.m_bias = bias;
+ this.m_resultScalarSize = resultScalarSize;
+ this.m_areScaleAndBiasEvaluated = false;
+};
+
+setParentClass(es3fShaderOperatorTests.OperatorShaderEvaluator, glsShaderRenderCase.ShaderEvaluator);
+
+es3fShaderOperatorTests.OperatorShaderEvaluator.prototype.evaluate = function(ctx) {
+ this.m_evalFunc(ctx);
+
+ if (!this.m_areScaleAndBiasEvaluated) {
+ this.m_evaluatedScale = this.m_scale.getValue(this.m_shaderType);
+ this.m_evaluatedBias = this.m_bias.getValue(this.m_shaderType);
+ this.m_areScaleAndBiasEvaluated = true;
+ }
+
+ for (var i = 0; i < 4; i++)
+ if (s_outSwizzleChannelMasks[this.m_resultScalarSize - 1][i])
+ ctx.color[i] = ctx.color[i] * this.m_evaluatedScale + this.m_evaluatedBias;
+};
+
+/**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ * @param {string} shaderOp
+ * @param {es3fShaderOperatorTests.ShaderDataSpec} spec
+ */
+es3fShaderOperatorTests.ShaderOperatorCase = function(caseName, description, isVertexCase, evalFunc, shaderOp, spec) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, caseName, description, isVertexCase, evalFunc);
+ this.m_spec = spec;
+ this.m_shaderOp = shaderOp;
+ var shaderType = isVertexCase ? gluShaderProgram.shaderType.VERTEX : gluShaderProgram.shaderType.FRAGMENT;
+ this.m_evaluator = new es3fShaderOperatorTests.OperatorShaderEvaluator(shaderType,
+ evalFunc,
+ spec.referenceScale,
+ spec.referenceBias,
+ gluShaderUtil.getDataTypeScalarSize(spec.output));
+};
+
+setParentClass(es3fShaderOperatorTests.ShaderOperatorCase, glsShaderRenderCase.ShaderRenderCase);
+
+es3fShaderOperatorTests.ShaderOperatorCase.prototype.setupShaderData = function() {
+ var shaderType = this.m_isVertexCase ? gluShaderProgram.shaderType.VERTEX : gluShaderProgram.shaderType.FRAGMENT;
+ var precision = this.m_spec.precision !== undefined ? gluShaderUtil.getPrecisionName(this.m_spec.precision) : null;
+ var inputPrecision = [];
+ var sources = [];
+ sources[0] = ''; //vertex
+ sources[1] = ''; //fragment
+ var vtx = 0;
+ var frag = 1;
+ var op = this.m_isVertexCase ? vtx : frag;
+
+ sources[vtx] += '#version 300 es\n';
+ sources[frag] += '#version 300 es\n';
+
+ // Compute precision for inputs.
+ for (var i = 0; i < this.m_spec.numInputs; i++) {
+ var isBoolVal = gluShaderUtil.isDataTypeBoolOrBVec(this.m_spec.inputs[i].type);
+ var isIntVal = gluShaderUtil.isDataTypeIntOrIVec(this.m_spec.inputs[i].type);
+ var isUintVal = gluShaderUtil.isDataTypeUintOrUVec(this.m_spec.inputs[i].type);
+ // \note Mediump interpolators are used for booleans, and highp for integers.
+ var prec = isBoolVal ? gluShaderUtil.precision.PRECISION_MEDIUMP :
+ isIntVal || isUintVal ? gluShaderUtil.precision.PRECISION_HIGHP :
+ this.m_spec.precision;
+ inputPrecision[i] = gluShaderUtil.getPrecisionName(prec);
+ }
+
+ // Attributes.
+ sources[vtx] += 'in highp vec4 a_position;\n';
+ for (var i = 0; i < this.m_spec.numInputs; i++)
+ sources[vtx] += 'in ' + inputPrecision[i] + ' vec4 a_in' + i + ';\n';
+
+ // Color output.
+ sources[frag] += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (this.m_isVertexCase) {
+ sources[vtx] += 'out mediump vec4 v_color;\n';
+ sources[frag] += 'in mediump vec4 v_color;\n';
+ } else{
+ for (var i = 0; i < this.m_spec.numInputs; i++) {
+ sources[vtx] += 'out ' + inputPrecision[i] + ' vec4 v_in' + i + ';\n';
+ sources[frag] += 'in ' + inputPrecision[i] + ' vec4 v_in' + i + ';\n';
+ }
+ }
+
+ sources[vtx] += '\n';
+ sources[vtx] += 'void main()\n';
+ sources[vtx] += '{\n';
+ sources[vtx] += ' gl_Position = a_position;\n';
+
+ sources[frag] += '\n';
+ sources[frag] += 'void main()\n';
+ sources[frag] += '{\n';
+
+ // Expression inputs.
+ var prefix = this.m_isVertexCase ? 'a_' : 'v_';
+ for (var i = 0; i < this.m_spec.numInputs; i++) {
+ var inType = this.m_spec.inputs[i].type;
+ var inSize = gluShaderUtil.getDataTypeScalarSize(inType);
+ var isInt = gluShaderUtil.isDataTypeIntOrIVec(inType);
+ var isUint = gluShaderUtil.isDataTypeUintOrUVec(inType);
+ var isBool = gluShaderUtil.isDataTypeBoolOrBVec(inType);
+ var typeName = gluShaderUtil.getDataTypeName(inType);
+ var swizzle = s_inSwizzles[i][inSize - 1];
+
+ sources[op] += '\t';
+ if (precision && !isBool) sources[op] += precision + ' ';
+
+ sources[op] += typeName + ' in' + i + ' = ';
+
+ if (isBool) {
+ if (inSize == 1) sources[op] += '(';
+ else sources[op] += 'greaterThan(';
+ } else if (isInt || isUint)
+ sources[op] += typeName + '(';
+
+ sources[op] += prefix + 'in' + i + '.' + swizzle;
+
+ if (isBool) {
+ if (inSize == 1) sources[op] += ' > 0.0)';
+ else sources[op] += ', vec' + inSize + '(0.0))';
+ } else if (isInt || isUint)
+ sources[op] += ')';
+
+ sources[op] += ';\n';
+ }
+
+ // Result variable.
+ var outTypeName = gluShaderUtil.getDataTypeName(this.m_spec.output);
+ var isBoolOut = gluShaderUtil.isDataTypeBoolOrBVec(this.m_spec.output);
+
+ sources[op] += '\t';
+ if (precision && !isBoolOut) sources[op] += precision + ' ';
+ sources[op] += outTypeName + ' res = ' + outTypeName + '(0.0);\n\n';
+
+
+ // Expression.
+ sources[op] += '\t' + this.m_shaderOp + '\n\n';
+
+ // Convert to color.
+ var isResFloatVec = gluShaderUtil.isDataTypeFloatOrVec(this.m_spec.output);
+ var outScalarSize = gluShaderUtil.getDataTypeScalarSize(this.m_spec.output);
+
+ sources[op] += '\thighp vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n';
+ sources[op] += '\tcolor.' + s_outSwizzles[outScalarSize - 1] + ' = ';
+
+ if (!isResFloatVec && outScalarSize == 1)
+ sources[op] += 'float(res)';
+ else if (!isResFloatVec)
+ sources[op] += 'vec' + outScalarSize + '(res)';
+ else
+ sources[op] += 'res';
+
+ sources[op] += ';\n';
+
+ // Scale & bias.
+ var resultScale = this.m_spec.resultScale.getValue(shaderType);
+ var resultBias = this.m_spec.resultBias.getValue(shaderType);
+ if ((resultScale != 1.0) || (resultBias != 0.0)) {
+ sources[op] += '\tcolor = color';
+ if (resultScale != 1.0) sources[op] += ' * ' + es3fShaderOperatorTests.twoValuedVec4(resultScale.toString(10), '1.0', s_outSwizzleChannelMasks[outScalarSize - 1]);
+ if (resultBias != 0.0) sources[op] += ' + ' + es3fShaderOperatorTests.twoValuedVec4(resultBias.toString(10), '0.0', s_outSwizzleChannelMasks[outScalarSize - 1]);
+ sources[op] += ';\n';
+ }
+
+ // ..
+ if (this.m_isVertexCase) {
+ sources[vtx] += ' v_color = color;\n';
+ sources[frag] += ' o_color = v_color;\n';
+ } else{
+ for (var i = 0; i < this.m_spec.numInputs; i++)
+ sources[vtx] += ' v_in' + i + ' = a_in' + i + ';\n';
+ sources[frag] += ' o_color = color;\n';
+ }
+
+ sources[vtx] += '}\n';
+ sources[frag] += '}\n';
+
+ this.m_vertShaderSource = sources[vtx];
+ this.m_fragShaderSource = sources[frag];
+
+ // Setup the user attributes.
+ this.m_userAttribTransforms = [];
+ for (var inputNdx = 0; inputNdx < this.m_spec.numInputs; inputNdx++) {
+ var v = this.m_spec.inputs[inputNdx];
+
+ var rangeMin = v.rangeMin.getValue(shaderType);
+ var rangeMax = v.rangeMax.getValue(shaderType);
+ var scale = rangeMax - rangeMin;
+ var minBias = rangeMin;
+ var maxBias = rangeMax;
+ var attribMatrix = new tcuMatrix.Matrix(4, 4);
+
+ for (var rowNdx = 0; rowNdx < 4; rowNdx++) {
+ var row;
+
+ switch ((rowNdx + inputNdx) % 4) {
+ case 0: row = [scale, 0.0, 0.0, minBias]; break;
+ case 1: row = [0.0, scale, 0.0, minBias]; break;
+ case 2: row = [-scale, 0.0, 0.0, maxBias]; break;
+ case 3: row = [0.0, -scale, 0.0, maxBias]; break;
+ default: throw new Error('Invalid row index');
+ }
+
+ attribMatrix.setRow(rowNdx, row);
+ }
+
+ this.m_userAttribTransforms[inputNdx] = attribMatrix;
+ }
+
+};
+
+// Reference functions for specific sequence operations for the sequence operator tests.
+/**
+ * Reference for expression "in0, in2 + in1, in1 + in0"
+ * @param {Array<number>} in0 Vec4
+ * @param {Array<number>} in1 Vec4
+ * @param {Array<number>} in2 Vec4
+ * @return {Array<number>} Vec4
+ */
+es3fShaderOperatorTests.sequenceNoSideEffCase0 = function(in0, in1, in2) {
+ return deMath.add(in1, in0);
+};
+
+/**
+ * Reference for expression "in0, in2 + in1, in1 + in0"
+ * @param {number} in0 float
+ * @param {number} in1 deUint32
+ * @param {number} in2 float
+ * @return {number} deUint32
+ */
+es3fShaderOperatorTests.sequenceNoSideEffCase1 = function(in0, in1, in2) {
+ in1 = convert(in1, gluShaderUtil.DataType.UINT);
+ return convert(in1 + in1, gluShaderUtil.DataType.UINT);
+};
+
+/**
+ * Reference for expression "in0 && in1, in0, ivec2(vec2(in0) + in2)"
+ * @param {boolean} in0
+ * @param {boolean} in1
+ * @param {Array<number>} in2 Vec2
+ * @return {Array<number>} IVec2
+ */
+es3fShaderOperatorTests.sequenceNoSideEffCase2 = function(in0, in1, in2) {
+ in0 = convert(in0, gluShaderUtil.DataType.BOOL);
+ return convert([in0 + in2[0], in0 + in2[1]], gluShaderUtil.DataType.INT);
+};
+
+/**
+ * Reference for expression "in0 + vec4(in1), in2, in1"
+ * @param {Array<number>} in0 Vec4
+ * @param {Array<number>} in1 IVec4
+ * @param {Array<boolean>} in2 BVec4
+ * @return {Array<number>} IVec4
+ */
+es3fShaderOperatorTests.sequenceNoSideEffCase3 = function(in0, in1, in2) {
+ return convert(in1, gluShaderUtil.DataType.INT);
+};
+
+/**
+ * Reference for expression "in0++, in1 = in0 + in2, in2 = in1"
+ * @param {Array<number>} in0 Vec4
+ * @param {Array<number>} in1 Vec4
+ * @param {Array<number>} in2 Vec4
+ * @return {Array<number>} Vec4
+ */
+es3fShaderOperatorTests.sequenceSideEffCase0 = function(in0, in1, in2) {
+ return deMath.add(deMath.add(in0, [1.0, 1.0, 1.0, 1.0]), in2);
+};
+
+/**
+ * Reference for expression "in1++, in0 = float(in1), in1 = uint(in0 + in2)"
+ * @param {number} in0 float
+ * @param {number} in1 deUint32
+ * @param {number} in2 float
+ * @return {number} deUint32
+ */
+es3fShaderOperatorTests.sequenceSideEffCase1 = function(in0, in1, in2) {
+ in1 = convert(in1, gluShaderUtil.DataType.UINT);
+ return convert(in1 + 1.0 + in2, gluShaderUtil.DataType.UINT);
+};
+
+/**
+ * Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
+ * @param {boolean} in0
+ * @param {boolean} in1
+ * @param {Array<number>} in2 Vec2
+ * @return {Array<number>} IVec2
+ */
+es3fShaderOperatorTests.sequenceSideEffCase2 = function(in0, in1, in2) {
+ in0 = convert(in0, gluShaderUtil.DataType.BOOL);
+ return convert(deMath.add(deMath.add(in2, [1.0, 1.0]), [in0, in0]), gluShaderUtil.DataType.INT);
+};
+
+/**
+ * Reference for expression "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++"
+ * @param {Array<number>} in0 Vec4
+ * @param {Array<number>} in1 IVec4
+ * @param {Array<boolean>} in2 BVec4
+ * @return {Array<number>} IVec4
+ */
+es3fShaderOperatorTests.sequenceSideEffCase3 = function(in0, in1, in2) {
+ in1 = convert(in1, gluShaderUtil.DataType.INT);
+ in2 = convert(in2, gluShaderUtil.DataType.BOOL);
+ in0 = deMath.add(in0, in2);
+ in1 = deMath.add(in1, convert(in0, gluShaderUtil.DataType.INT));
+ return in1;
+};
+
+// ShaderEvalFunc-type wrappers for the above functions.
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceNoSideEffCase0 = function(ctx) {
+ ctx.color = es3fShaderOperatorTests.sequenceNoSideEffCase0(
+ deMath.swizzle(ctx.in_[0], [1, 2, 3, 0]),
+ deMath.swizzle(ctx.in_[1], [3, 2, 1, 0]),
+ deMath.swizzle(ctx.in_[2], [0, 3, 2, 1])
+ );
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceNoSideEffCase1 = function(ctx) {
+ ctx.color[0] = es3fShaderOperatorTests.sequenceNoSideEffCase1(
+ ctx.in_[0][2],
+ ctx.in_[1][0],
+ ctx.in_[2][1]
+ );
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceNoSideEffCase2 = function(ctx) {
+ /** @type {Array<number>} */ var result = es3fShaderOperatorTests.sequenceNoSideEffCase2(
+ ctx.in_[0][2] > 0.0,
+ ctx.in_[1][0] > 0.0,
+ deMath.swizzle(ctx.in_[2], [2, 1])
+ );
+ ctx.color[1] = result[0];
+ ctx.color[2] = result[1];
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceNoSideEffCase3 = function(ctx) {
+ ctx.color = es3fShaderOperatorTests.sequenceNoSideEffCase3(
+ deMath.swizzle(ctx.in_[0], [1, 2, 3, 0]),
+ deMath.swizzle(ctx.in_[1], [3, 2, 1, 0]),
+ deMath.greaterThan(deMath.swizzle(ctx.in_[2], [0, 3, 2, 1]), [0.0, 0.0, 0.0, 0.0])
+ );
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceSideEffCase0 = function(ctx) {
+ ctx.color = es3fShaderOperatorTests.sequenceSideEffCase0(
+ deMath.swizzle(ctx.in_[0], [1, 2, 3, 0]),
+ deMath.swizzle(ctx.in_[1], [3, 2, 1, 0]),
+ deMath.swizzle(ctx.in_[2], [0, 3, 2, 1])
+ );
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceSideEffCase1 = function(ctx) {
+ ctx.color[0] = es3fShaderOperatorTests.sequenceSideEffCase1(
+ ctx.in_[0][2],
+ ctx.in_[1][0],
+ ctx.in_[2][1]
+ );
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceSideEffCase2 = function(ctx) {
+ /** @type {Array<number>} */ var result = es3fShaderOperatorTests.sequenceSideEffCase2(
+ ctx.in_[0][2] > 0.0,
+ ctx.in_[1][0] > 0.0,
+ deMath.swizzle(ctx.in_[2], [2, 1])
+ );
+ ctx.color[1] = result[0];
+ ctx.color[2] = result[1];
+};
+
+/** @param {glsShaderRenderCase.ShaderEvalContext} ctx */
+es3fShaderOperatorTests.evalSequenceSideEffCase3 = function(ctx) {
+ ctx.color = es3fShaderOperatorTests.sequenceSideEffCase3(
+ deMath.swizzle(ctx.in_[0], [1, 2, 3, 0]),
+ deMath.swizzle(ctx.in_[1], [3, 2, 1, 0]),
+ deMath.greaterThan(deMath.swizzle(ctx.in_[2], [0, 3, 2, 1]), [0.0, 0.0, 0.0, 0.0])
+ );
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fShaderOperatorTests.ShaderOperatorTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'shaderop', 'Shader operators tests');
+};
+
+setParentClass(es3fShaderOperatorTests.ShaderOperatorTests, tcuTestCase.DeqpTest);
+
+es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
+ var op = es3fShaderOperatorTests.builtinOperInfo;
+ var side = es3fShaderOperatorTests.builtinSideEffOperInfo;
+ var separate = es3fShaderOperatorTests.builtinOperInfoSeparateRefScaleBias;
+ var postSide = es3fShaderOperatorTests.BuiltinPostSideEffOperInfo;
+ var postOp = es3fShaderOperatorTests.BuiltinPostOperInfo;
+ var all = es3fShaderOperatorTests.Precision.All;
+ var highp = es3fShaderOperatorTests.Precision.High;
+ var mediump = es3fShaderOperatorTests.Precision.Medium;
+ var mediumhighp = es3fShaderOperatorTests.Precision.MediumHigh;
+ var lowp = es3fShaderOperatorTests.Precision.Low;
+ var na = es3fShaderOperatorTests.Precision.None;
+ var GT = es3fShaderOperatorTests.ValueType.FLOAT_GENTYPE;
+ var UGT = es3fShaderOperatorTests.ValueType.UINT_GENTYPE;
+ var IGT = es3fShaderOperatorTests.ValueType.INT_GENTYPE;
+ var BGT = es3fShaderOperatorTests.ValueType.BOOL_GENTYPE;
+ var F = es3fShaderOperatorTests.ValueType.FLOAT;
+ var I = es3fShaderOperatorTests.ValueType.INT;
+ var U = es3fShaderOperatorTests.ValueType.UINT;
+ var BV = es3fShaderOperatorTests.ValueType.BOOL_VEC;
+ var FV = es3fShaderOperatorTests.ValueType.FLOAT_VEC;
+ var IV = es3fShaderOperatorTests.ValueType.INT_VEC;
+ var UV = es3fShaderOperatorTests.ValueType.UINT_VEC;
+ var B = es3fShaderOperatorTests.ValueType.BOOL;
+ var V3 = es3fShaderOperatorTests.ValueType.VEC3;
+ var lUMax = es3fShaderOperatorTests.Symbol.SYMBOL_LOWP_UINT_MAX;
+ var mUMax = es3fShaderOperatorTests.Symbol.SYMBOL_MEDIUMP_UINT_MAX;
+ var lUMaxR = es3fShaderOperatorTests.Symbol.SYMBOL_LOWP_UINT_MAX_RECIPROCAL;
+ var mUMaxR = es3fShaderOperatorTests.Symbol.SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL;
+ var f = function(value) {
+ return new es3fShaderOperatorTests.FloatScalar(value);
+ };
+ var s = function(value) {
+ return new es3fShaderOperatorTests.FloatScalar(value, true);
+ };
+ var v = function(type, a, b) {
+ return new es3fShaderOperatorTests.Value(type, f(a), f(b));
+ };
+ var v2 = function(type, a, b) {
+ return new es3fShaderOperatorTests.Value(type, f(a), s(b));
+ };
+ var funcInfoGroups = [];
+ var unary = new es3fShaderOperatorTests.BuiltinFuncGroup('unary_operator', 'Unary operator tests');
+ funcInfoGroups.push(unary);
+
+ unary.push(op('plus', '+', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop)));
+ unary.push(op('plus', '+', IGT, [v(IGT, -5.0, 5.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(op('plus', '+', UGT, [v(UGT, 0.0, 2e2)], f(5e-3), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(op('minus', '-', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(negate)));
+ unary.push(op('minus', '-', IGT, [v(IGT, -5.0, 5.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(negate, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(separate('minus', '-', UGT, [v2(UGT, 0.0, lUMax)], s(lUMaxR), f(0.0), lowp,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(negate, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT), s(lUMaxR),
+ s(es3fShaderOperatorTests.Symbol.SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX)));
+ unary.push(separate('minus', '-', UGT, [v2(UGT, 0.0, mUMax)], s(mUMaxR), f(0.0), mediump,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(negate, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT), s(mUMaxR),
+ s(es3fShaderOperatorTests.Symbol.SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX)));
+ unary.push(op('minus', '-', UGT, [v(UGT, 0.0, 4e9)], f(2e-10), f(0.0), highp,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(negate, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(op('not', '!', B, [v(B, -1.0, 1.0)], f(1.0), f(0.0), na,{'scalar': es3fShaderOperatorTests.unaryGenTypeFuncs(boolNot, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL).scalar}));
+ unary.push(op('bitwise_not', '~', IGT, [v(IGT, -1e5, 1e5)], f(5e-5), f(0.5), highp,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(bitwiseNot, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(op('bitwise_not', '~', UGT, [v(UGT, 0.0, 2e9)], f(2e-10), f(0.0), highp,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(bitwiseNot, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ // Pre/post incr/decr side effect cases.
+ unary = new es3fShaderOperatorTests.BuiltinFuncGroup('unary_operator', 'Unary operator tests');
+ funcInfoGroups.push(unary);
+
+ unary.push(side('pre_increment_effect', '++', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne)));
+ unary.push(side('pre_increment_effect', '++', IGT, [v(IGT, -6.0, 4.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(side('pre_increment_effect', '++', UGT, [v(UGT, 0.0, 9.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(side('pre_decrement_effect', '--', GT, [v(GT, -1.0, 1.0)], f(0.5), f(1.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne)));
+ unary.push(side('pre_decrement_effect', '--', IGT, [v(IGT, -4.0, 6.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(side('pre_decrement_effect', '--', UGT, [v(UGT, 0.0, 10.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(postSide('post_increment_result', '++', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne)));
+ unary.push(postSide('post_increment_result', '++', IGT, [v(IGT, -6.0, 4.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(postSide('post_increment_result', '++', UGT, [v(UGT, 0.0, 9.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(postSide('post_decrement_result', '--', GT, [v(GT, -1.0, 1.0)], f(0.5), f(1.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne)));
+ unary.push(postSide('post_decrement_result', '--', IGT, [v(IGT, -4.0, 6.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(postSide('post_decrement_result', '--', UGT, [v(UGT, 1.0, 10.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ // Pre/post incr/decr result cases.
+ unary = new es3fShaderOperatorTests.BuiltinFuncGroup('unary_operator', 'Unary operator tests');
+ funcInfoGroups.push(unary);
+
+ unary.push(op('pre_increment_result', '++', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne)));
+ unary.push(op('pre_increment_result', '++', IGT, [v(IGT, -6.0, 4.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(op('pre_increment_result', '++', UGT, [v(UGT, 0.0, 9.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(addOne, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(op('pre_dencrement_result', '--', GT, [v(GT, -1.0, 1.0)], f(0.5), f(1.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne)));
+ unary.push(op('pre_decrement_result', '--', IGT, [v(IGT, -4.0, 6.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(op('pre_decrement_result', '--', UGT, [v(UGT, 0.0, 10.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(subOne, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(postOp('post_increment_result', '++', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop)));
+ unary.push(postOp('post_increment_result', '++', IGT, [v(IGT, -5.0, 5.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(postOp('post_increment_result', '++', UGT, [v(UGT, 0.0, 9.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ unary.push(postOp('post_decrement_result', '--', GT, [v(GT, -1.0, 1.0)], f(0.5), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop)));
+ unary.push(postOp('post_decrement_result', '--', IGT, [v(IGT, -5.0, 5.0)], f(0.1), f(0.5), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ unary.push(postOp('post_decrement_result', '--', UGT, [v(UGT, 1.0, 10.0)], f(0.1), f(0.0), all,
+ es3fShaderOperatorTests.unaryGenTypeFuncs(nop, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ var binary;
+
+ // Normal binary operations and their corresponding assignment operations have lots in common; generate both in the following loop.
+ // 0: normal op test, 1: assignment op side-effect test, 2: assignment op result test
+ for (var binaryOperatorType = 0; binaryOperatorType <= 2; binaryOperatorType++) {
+ var isNormalOp = binaryOperatorType == 0;
+ var isAssignEff = binaryOperatorType == 1;
+ var isAssignRes = binaryOperatorType == 2;
+
+ var addName = isNormalOp ? 'add' : isAssignEff ? 'add_assign_effect' : 'add_assign_result';
+ var subName = isNormalOp ? 'sub' : isAssignEff ? 'sub_assign_effect' : 'sub_assign_result';
+ var mulName = isNormalOp ? 'mul' : isAssignEff ? 'mul_assign_effect' : 'mul_assign_result';
+ var divName = isNormalOp ? 'div' : isAssignEff ? 'div_assign_effect' : 'div_assign_result';
+ var modName = isNormalOp ? 'mod' : isAssignEff ? 'mod_assign_effect' : 'mod_assign_result';
+ var andName = isNormalOp ? 'bitwise_and' : isAssignEff ? 'bitwise_and_assign_effect' : 'bitwise_and_assign_result';
+ var orName = isNormalOp ? 'bitwise_or' : isAssignEff ? 'bitwise_or_assign_effect' : 'bitwise_or_assign_result';
+ var xorName = isNormalOp ? 'bitwise_xor' : isAssignEff ? 'bitwise_xor_assign_effect' : 'bitwise_xor_assign_result';
+ var leftShiftName = isNormalOp ? 'left_shift' : isAssignEff ? 'left_shift_assign_effect' : 'left_shift_assign_result';
+ var rightShiftName = isNormalOp ? 'right_shift' : isAssignEff ? 'right_shift_assign_effect' : 'right_shift_assign_result';
+ var addOp = isNormalOp ? '+' : '+=';
+ var subOp = isNormalOp ? '-' : '-=';
+ var mulOp = isNormalOp ? '*' : '*=';
+ var divOp = isNormalOp ? '/' : '/=';
+ var modOp = isNormalOp ? '%' : '%=';
+ var andOp = isNormalOp ? '&' : '&=';
+ var orOp = isNormalOp ? '|' : '|=';
+ var xorOp = isNormalOp ? '^' : '^=';
+ var leftShiftOp = isNormalOp ? '<<' : '<<=';
+ var rightShiftOp = isNormalOp ? '>>' : '>>=';
+
+ op = isAssignEff ? es3fShaderOperatorTests.builtinSideEffOperInfo : es3fShaderOperatorTests.builtinOperInfo;
+
+ binary = new es3fShaderOperatorTests.BuiltinFuncGroup('binary_operator', 'Binary operator tests');
+ funcInfoGroups.push(binary);
+
+ // The add operator.
+
+ binary.push(op(addName, addOp, GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(add)));
+ binary.push(op(addName, addOp, IGT, [v(IGT, -4.0, 6.0), v(IGT, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(add, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(addName, addOp, IGT, [v(IGT, -2e9, 2e9), v(IGT, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(add, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(addName, addOp, UGT, [v(UGT, 0.0, 1e2), v(UGT, 0.0, 1e2)], f(5e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(add, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(addName, addOp, UGT, [v(UGT, 0.0, 4e9), v(UGT, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(add, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ binary.push(op(addName, addOp, FV, [v(FV, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.addScalar)));
+ binary.push(op(addName, addOp, IV, [v(IV, -4.0, 6.0), v(I, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.addScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(addName, addOp, IV, [v(IV, -2e9, 2e9), v(I, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.addScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(addName, addOp, UV, [v(UV, 0.0, 1e2), v(U, 0.0, 1e2)], f(5e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.addScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(addName, addOp, UV, [v(UV, 0.0, 4e9), v(U, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.addScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(addName, addOp, FV, [v(F, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarVecFuncs(addScalarVec)));
+ binary.push(op(addName, addOp, IV, [v(I, -4.0, 6.0), v(IV, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(addScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(addName, addOp, IV, [v(I, -2e9, 2e9), v(IV, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(addScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(addName, addOp, UV, [v(U, 0.0, 1e2), v(UV, 0.0, 1e2)], f(5e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(addScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(addName, addOp, UV, [v(U, 0.0, 4e9), v(UV, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(addScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ // The subtract operator.
+
+ binary.push(op(subName, subOp, GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(sub)));
+ binary.push(op(subName, subOp, IGT, [v(IGT, -4.0, 6.0), v(IGT, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(sub, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(subName, subOp, IGT, [v(IGT, -2e9, 2e9), v(IGT, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(sub, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(subName, subOp, UGT, [v(UGT, 1e2, 2e2), v(UGT, 0.0, 1e2)], f(5e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(sub, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(subName, subOp, UGT, [v(UGT, .5e9, 3.7e9), v(UGT, 0.0, 3.9e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(sub, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(subName, subOp, FV, [v(FV, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.subScalar)));
+ binary.push(op(subName, subOp, IV, [v(IV, -4.0, 6.0), v(I, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.subScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(subName, subOp, IV, [v(IV, -2e9, 2e9), v(I, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.subScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(subName, subOp, UV, [v(UV, 1e2, 2e2), v(U, 0.0, 1e2)], f(5e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.subScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(subName, subOp, UV, [v(UV, 0.0, 4e9), v(U, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.subScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(subName, subOp, FV, [v(F, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarVecFuncs(subScalarVec)));
+ binary.push(op(subName, subOp, IV, [v(I, -4.0, 6.0), v(IV, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(subScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(subName, subOp, IV, [v(I, -2e9, 2e9), v(IV, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(subScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(subName, subOp, UV, [v(U, 1e2, 2e2), v(UV, 0.0, 1e2)], f(5e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(subScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(subName, subOp, UV, [v(U, 0.0, 4e9), v(UV, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(subScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ binary = new es3fShaderOperatorTests.BuiltinFuncGroup('binary_operator', 'Binary operator tests');
+ funcInfoGroups.push(binary);
+
+ // The multiply operator.
+
+ binary.push(op(mulName, mulOp, GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(mul)));
+ binary.push(op(mulName, mulOp, IGT, [v(IGT, -4.0, 6.0), v(IGT, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(mul, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(mulName, mulOp, IGT, [v(IGT, -3e5, 3e5), v(IGT, -3e4, 3e4)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(mul, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(mulName, mulOp, UGT, [v(UGT, 0.0, 16.0), v(UGT, 0.0, 16.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(mul, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(mulName, mulOp, UGT, [v(UGT, 0.0, 6e5), v(UGT, 0.0, 6e4)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(mul, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(mulName, mulOp, FV, [v(FV, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.scale)));
+ binary.push(op(mulName, mulOp, IV, [v(IV, -4.0, 6.0), v(I, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.scale, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(mulName, mulOp, IV, [v(IV, -3e5, 3e5), v(I, -3e4, 3e4)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.scale, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(mulName, mulOp, UV, [v(UV, 0.0, 16.0), v(U, 0.0, 16.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.scale, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(mulName, mulOp, UV, [v(UV, 0.0, 6e5), v(U, 0.0, 6e4)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.scale, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(mulName, mulOp, FV, [v(F, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarVecFuncs(mulScalarVec)));
+ binary.push(op(mulName, mulOp, IV, [v(I, -4.0, 6.0), v(IV, -6.0, 5.0)], f(0.1), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(mulScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(mulName, mulOp, IV, [v(I, -3e5, 3e5), v(IV, -3e4, 3e4)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(mulScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(mulName, mulOp, UV, [v(U, 0.0, 16.0), v(UV, 0.0, 16.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(mulScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(mulName, mulOp, UV, [v(U, 0.0, 6e5), v(UV, 0.0, 6e4)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(mulScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ // The divide operator.
+
+ binary.push(op(divName, divOp, GT, [v(GT, -1.0, 1.0), v(GT, -2.0, -0.5)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(div)));
+ binary.push(op(divName, divOp, IGT, [v(IGT, 24.0, 24.0), v(IGT, -4.0, -1.0)], f(0.04), f(1.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(div, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(divName, divOp, IGT, [v(IGT, 40320.0, 40320.0), v(IGT, -8.0, -1.0)], f(1e-5), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(div, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(divName, divOp, UGT, [v(UGT, 0.0, 24.0), v(UGT, 1.0, 4.0)], f(0.04), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(div, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(divName, divOp, UGT, [v(UGT, 0.0, 40320.0), v(UGT, 1.0, 8.0)], f(1e-5), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(div, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(divName, divOp, FV, [v(FV, -1.0, 1.0), v(F, -2.0, -0.5)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.divideScale)));
+ binary.push(op(divName, divOp, IV, [v(IV, 24.0, 24.0), v(I, -4.0, -1.0)], f(0.04), f(1.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.divideScale, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(divName, divOp, IV, [v(IV, 40320.0, 40320.0), v(I, -8.0, -1.0)], f(1e-5), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.divideScale, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(divName, divOp, UV, [v(UV, 0.0, 24.0), v(U, 1.0, 4.0)], f(0.04), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.divideScale, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(divName, divOp, UV, [v(UV, 0.0, 40320.0), v(U, 1.0, 8.0)], f(1e-5), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.divideScale, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(divName, divOp, FV, [v(F, -1.0, 1.0), v(FV, -2.0, -0.5)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarVecFuncs(divScalarVec)));
+ binary.push(op(divName, divOp, IV, [v(I, 24.0, 24.0), v(IV, -4.0, -1.0)], f(0.04), f(1.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(divScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(divName, divOp, IV, [v(I, 40320.0, 40320.0), v(IV, -8.0, -1.0)], f(1e-5), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(divScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(divName, divOp, UV, [v(U, 0.0, 24.0), v(UV, 1.0, 4.0)], f(0.04), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(divScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(divName, divOp, UV, [v(U, 0.0, 40320.0), v(UV, 1.0, 8.0)], f(1e-5), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(divScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ binary = new es3fShaderOperatorTests.BuiltinFuncGroup('binary_operator', 'Binary operator tests');
+ funcInfoGroups.push(binary);
+
+ // The modulus operator.
+
+ binary.push(op(modName, modOp, IGT, [v(IGT, 0.0, 6.0), v(IGT, 1.1, 6.1)], f(0.25), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.mod, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, IGT, [v(IGT, 0.0, 14.0), v(IGT, 1.1, 11.1)], f(0.1), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.mod, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, UGT, [v(UGT, 0.0, 6.0), v(UGT, 1.1, 6.1)], f(0.25), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.mod, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, UGT, [v(UGT, 0.0, 24.0), v(UGT, 1.1, 11.1)], f(0.1), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.mod, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(modName, modOp, IV, [v(IV, 0.0, 6.0), v(I, 1.1, 6.1)], f(0.25), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.modScale, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, IV, [v(IV, 0.0, 6.0), v(I, 1.1, 11.1)], f(0.1), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.modScale, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, UV, [v(UV, 0.0, 6.0), v(U, 1.1, 6.1)], f(0.25), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.modScale, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(modName, modOp, UV, [v(UV, 0.0, 24.0), v(U, 1.1, 11.1)], f(0.1), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.modScale, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(modName, modOp, IV, [v(I, 0.0, 6.0), v(IV, 1.1, 6.1)], f(0.25), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(modScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, IV, [v(I, 0.0, 6.0), v(IV, 1.1, 11.1)], f(0.1), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(modScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(modName, modOp, UV, [v(U, 0.0, 6.0), v(UV, 1.1, 6.1)], f(0.25), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(modScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(modName, modOp, UV, [v(U, 0.0, 24.0), v(UV, 1.1, 11.1)], f(0.1), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(modScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ // The bitwise and operator.
+
+ binary.push(op(andName, andOp, IGT, [v(IGT, -16.0, 16.0), v(IGT, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryAnd, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(andName, andOp, IGT, [v(IGT, -2e9, 2e9), v(IGT, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryAnd, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(andName, andOp, UGT, [v(UGT, 0.0, 32.0), v(UGT, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryAnd, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(andName, andOp, UGT, [v(UGT, 0.0, 4e9), v(UGT, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryAnd, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(andName, andOp, IV, [v(IV, -16.0, 16.0), v(I, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryAndVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(andName, andOp, IV, [v(IV, -2e9, 2e9), v(I, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryAndVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(andName, andOp, UV, [v(UV, 0.0, 32.0), v(U, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryAndVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(andName, andOp, UV, [v(UV, 0.0, 4e9), v(U, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryAndVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(andName, andOp, IV, [v(I, -16.0, 16.0), v(IV, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseAndScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(andName, andOp, IV, [v(I, -2e9, 2e9), v(IV, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseAndScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(andName, andOp, UV, [v(U, 0.0, 32.0), v(UV, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseAndScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(andName, andOp, UV, [v(U, 0.0, 4e9), v(UV, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseAndScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ binary = new es3fShaderOperatorTests.BuiltinFuncGroup('binary_operator', 'Binary operator tests');
+ funcInfoGroups.push(binary);
+
+ // The bitwise or operator.
+
+ binary.push(op(orName, orOp, IGT, [v(IGT, -16.0, 16.0), v(IGT, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryOr, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(orName, orOp, IGT, [v(IGT, -2e9, 2e9), v(IGT, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryOr, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(orName, orOp, UGT, [v(UGT, 0.0, 32.0), v(UGT, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryOr, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(orName, orOp, UGT, [v(UGT, 0.0, 4e9), v(UGT, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryOr, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(orName, orOp, IV, [v(IV, -16.0, 16.0), v(I, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryOrVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(orName, orOp, IV, [v(IV, -2e9, 2e9), v(I, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryOrVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(orName, orOp, UV, [v(UV, 0.0, 32.0), v(U, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryOrVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(orName, orOp, UV, [v(UV, 0.0, 4e9), v(U, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryOrVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(orName, orOp, IV, [v(I, -16.0, 16.0), v(IV, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseOrScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(orName, orOp, IV, [v(I, -2e9, 2e9), v(IV, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseOrScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(orName, orOp, UV, [v(U, 0.0, 32.0), v(UV, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseOrScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(orName, orOp, UV, [v(U, 0.0, 4e9), v(UV, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseOrScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ // The bitwise xor operator.
+
+ binary.push(op(xorName, xorOp, IGT, [v(IGT, -16.0, 16.0), v(IGT, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryXor, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(xorName, xorOp, IGT, [v(IGT, -2e9, 2e9), v(IGT, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryXor, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(xorName, xorOp, UGT, [v(UGT, 0.0, 32.0), v(UGT, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryXor, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(xorName, xorOp, UGT, [v(UGT, 0.0, 4e9), v(UGT, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.binaryXor, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(xorName, xorOp, IV, [v(IV, -16.0, 16.0), v(I, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryXorVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(xorName, xorOp, IV, [v(IV, -2e9, 2e9), v(I, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryXorVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(xorName, xorOp, UV, [v(UV, 0.0, 32.0), v(U, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryXorVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(xorName, xorOp, UV, [v(UV, 0.0, 4e9), v(U, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.binaryXorVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+
+ if (isNormalOp) {
+ binary.push(op(xorName, xorOp, IV, [v(I, -16.0, 16.0), v(IV, -16.0, 16.0)], f(0.03), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseXorScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(xorName, xorOp, IV, [v(I, -2e9, 2e9), v(IV, -2e9, 2e9)], f(4e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseXorScalarVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(xorName, xorOp, UV, [v(U, 0.0, 32.0), v(UV, 0.0, 32.0)], f(0.03), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseXorScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(xorName, xorOp, UV, [v(U, 0.0, 4e9), v(UV, 0.0, 4e9)], f(2e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryScalarVecFuncs(bitwiseXorScalarVec, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ binary = new es3fShaderOperatorTests.BuiltinFuncGroup('binary_operator', 'Binary operator tests');
+ funcInfoGroups.push(binary);
+
+ // The left shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
+ for (var isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++) {
+ var gType = isSignedAmount == 0 ? UGT : IGT;
+ var sType = isSignedAmount == 0 ? U : I;
+ binary.push(op(leftShiftName, leftShiftOp, IGT, [v(IGT, -7.0, 7.0), v(gType, 0.0, 4.0)], f(4e-3), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftLeft, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(leftShiftName, leftShiftOp, IGT, [v(IGT, -7.0, 7.0), v(gType, 0.0, 27.0)], f(5e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftLeft, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(leftShiftName, leftShiftOp, UGT, [v(UGT, 0.0, 7.0), v(gType, 0.0, 5.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftLeft, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(leftShiftName, leftShiftOp, UGT, [v(UGT, 0.0, 7.0), v(gType, 0.0, 28.0)], f(5e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftLeft, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(leftShiftName, leftShiftOp, IV, [v(IV, -7.0, 7.0), v(sType, 0.0, 4.0)], f(4e-3), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftLeftVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(leftShiftName, leftShiftOp, IV, [v(IV, -7.0, 7.0), v(sType, 0.0, 27.0)], f(5e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftLeftVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(leftShiftName, leftShiftOp, UV, [v(UV, 0.0, 7.0), v(sType, 0.0, 5.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftLeftVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(leftShiftName, leftShiftOp, UV, [v(UV, 0.0, 7.0), v(sType, 0.0, 28.0)], f(5e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftLeftVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+
+ // The right shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
+
+ for (var isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++) {
+ gType = isSignedAmount == 0 ? UGT : IGT;
+ sType = isSignedAmount == 0 ? U : I;
+ binary.push(op(rightShiftName, rightShiftOp, IGT, [v(IGT, -127.0, 127.0), v(gType, 0.0, 8.0)], f(4e-3), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftRight, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(rightShiftName, rightShiftOp, IGT, [v(IGT, -2e9, 2e9), v(gType, 0.0, 31.0)], f(5e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftRight, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(rightShiftName, rightShiftOp, UGT, [v(UGT, 0.0, 255.0), v(gType, 0.0, 8.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftRight, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(rightShiftName, rightShiftOp, UGT, [v(UGT, 0.0, 4e9), v(gType, 0.0, 31.0)], f(5e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.shiftRight, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(rightShiftName, rightShiftOp, IV, [v(IV, -127.0, 127.0), v(sType, 0.0, 8.0)], f(4e-3), f(0.5),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftRightVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(rightShiftName, rightShiftOp, IV, [v(IV, -2e9, 2e9), v(sType, 0.0, 31.0)], f(5e-10), f(0.5),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftRightVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op(rightShiftName, rightShiftOp, UV, [v(UV, 0.0, 255.0), v(sType, 0.0, 8.0)], f(4e-3), f(0.0),
+ mediump, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftRightVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op(rightShiftName, rightShiftOp, UV, [v(UV, 0.0, 4e9), v(sType, 0.0, 31.0)], f(5e-10), f(0.0),
+ highp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.shiftRightVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ }
+ }
+
+ // Rest of binary operators.
+ // Scalar relational operators.
+ binary = new es3fShaderOperatorTests.BuiltinFuncGroup('binary_operator', 'Binary operator tests');
+ funcInfoGroups.push(binary);
+
+ binary.push(op('less', '<', B, [v(F, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(lessThan).scalar}));
+ binary.push(op('less', '<', B, [v(I, -5.0, 5.0), v(I, -5.0, 5.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(lessThan, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT).scalar}));
+ binary.push(op('less', '<', B, [v(U, 0.0, 16.0), v(U, 0.0, 16.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(lessThan, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT).scalar}));
+ binary.push(op('less_or_equal', '<=', B, [v(F, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(lessThanEqual).scalar}));
+ binary.push(op('less_or_equal', '<=', B, [v(I, -5.0, 5.0), v(I, -5.0, 5.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(lessThanEqual, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT).scalar}));
+ binary.push(op('less_or_equal', '<=', B, [v(U, 0.0, 16.0), v(U, 0.0, 16.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(lessThanEqual, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT).scalar}));
+ binary.push(op('greater', '>', B, [v(F, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(greaterThan).scalar}));
+ binary.push(op('greater', '>', B, [v(I, -5.0, 5.0), v(I, -5.0, 5.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(greaterThan, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT).scalar}));
+ binary.push(op('greater', '>', B, [v(U, 0.0, 16.0), v(U, 0.0, 16.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(greaterThan, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT).scalar}));
+ binary.push(op('greater_or_equal', '>=', B, [v(F, -1.0, 1.0), v(F, -1.0, 1.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(greaterThanEqual).scalar}));
+ binary.push(op('greater_or_equal', '>=', B, [v(I, -5.0, 5.0), v(I, -5.0, 5.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(greaterThanEqual, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT).scalar}));
+ binary.push(op('greater_or_equal', '>=', B, [v(U, 0.0, 16.0), v(U, 0.0, 16.0)], f(1.0), f(0.0),
+ all, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(greaterThanEqual, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT).scalar}));
+
+ binary.push(op('equal', '==', B, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(allEqual)));
+ binary.push(op('equal', '==', B, [v(IGT, -5.5, 4.7), v(IGT, -2.1, 0.1)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(allEqual, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op('equal', '==', B, [v(UGT, 0.0, 8.0), v(UGT, 3.5, 4.5)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(allEqual, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op('equal', '==', B, [v(BGT, -2.1, 2.1), v(BGT, -1.1, 3.0)], f(1.0), f(0.0),
+ na, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(allEqual, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL)));
+ binary.push(op('not_equal', '!=', B, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(anyNotEqual)));
+ binary.push(op('not_equal', '!=', B, [v(IGT, -5.5, 4.7), v(IGT, -2.1, 0.1)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(anyNotEqual, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ binary.push(op('not_equal', '!=', B, [v(UGT, 0.0, 8.0), v(UGT, 3.5, 4.5)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(anyNotEqual, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ binary.push(op('not_equal', '!=', B, [v(BGT, -2.1, 2.1), v(BGT, -1.1, 3.0)], f(1.0), f(0.0),
+ na, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(anyNotEqual, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL)));
+
+ // Logical operators.
+ binary.push(op('logical_and', '&&', B, [v(B, -1.0, 1.0), v(B, -1.0, 1.0)], f(1.0), f(0.0),
+ na, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(logicalAnd, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL).scalar}));
+ binary.push(op('logical_or', '||', B, [v(B, -1.0, 1.0), v(B, -1.0, 1.0)], f(1.0), f(0.0),
+ na, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(logicalOr, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL).scalar}));
+ binary.push(op('logical_xor', '^^', B, [v(B, -1.0, 1.0), v(B, -1.0, 1.0)], f(1.0), f(0.0),
+ na, {scalar: es3fShaderOperatorTests.binaryGenTypeFuncs(logicalXor, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL).scalar}));
+
+ // 8.1 Angle and Trigonometry Functions.
+ var trig = new es3fShaderOperatorTests.BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.");
+ funcInfoGroups.push(trig);
+ op = es3fShaderOperatorTests.builtinFunctionInfo;
+ trig.push(op("radians", "radians", GT, [v(GT, -1.0, 1.0)], f(25.0), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(radians)));
+ trig.push(op("degrees", "degrees", GT, [v(GT, -1.0, 1.0)], f(0.04), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(degrees)));
+ trig.push(op("sin", "sin", GT, [v(GT, -5.0, 5.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.sin)));
+ trig.push(op("sin", "sin", GT, [v(GT, -1.5, 1.5)], f(0.5), f(0.5),
+ lowp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.sin)));
+ trig.push(op("cos", "cos", GT, [v(GT, -5.0, 5.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.cos)));
+ trig.push(op("cos", "cos", GT, [v(GT, -1.5, 1.5)], f(0.5), f(0.5),
+ lowp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.cos)));
+ trig.push(op("tan", "tan", GT, [v(GT, -5.0, 5.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.tan)));
+ trig.push(op("tan", "tan", GT, [v(GT, -1.5, 5.5)], f(0.5), f(0.5),
+ lowp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.tan)));
+
+ trig = new es3fShaderOperatorTests.BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.");
+ funcInfoGroups.push(trig);
+ trig.push(op("asin", "asin", GT, [v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.asin)));
+ trig.push(op("acos", "acos", GT, [v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.acos)));
+ trig.push(op("atan", "atan", GT, [v(GT, -4.0, 4.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.atan)));
+ trig.push(op("atan2", "atan", GT, [v(GT, -4.0, 4.0), v(GT, 0.5, 2.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.atan2)));
+
+ trig = new es3fShaderOperatorTests.BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.");
+ funcInfoGroups.push(trig);
+ trig.push(op("sinh", "sinh", GT, [v(GT, -5.0, 5.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.sinh)));
+ trig.push(op("sinh", "sinh", GT, [v(GT, -1.5, 1.5)], f(0.5), f(0.5),
+ lowp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.sinh)));
+ trig.push(op("cosh", "cosh", GT, [v(GT, -5.0, 5.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.cosh)));
+ trig.push(op("cosh", "cosh", GT, [v(GT, -1.5, 1.5)], f(0.5), f(0.5),
+ lowp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.cosh)));
+ trig.push(op("tanh", "tanh", GT, [v(GT, -5.0, 5.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.tanh)));
+ trig.push(op("tanh", "tanh", GT, [v(GT, -1.5, 5.5)], f(0.5), f(0.5),
+ lowp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.tanh)));
+
+ trig = new es3fShaderOperatorTests.BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.");
+ funcInfoGroups.push(trig);
+ trig.push(op("asinh", "asinh", GT, [v(GT, -1.0, 1.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.asinh)));
+ trig.push(op("acosh", "acosh", GT, [v(GT, 1.0, 2.2)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.acosh)));
+ // Results are undefined if |x| >= 1, so it diverses from C++ version here.
+ trig.push(op("atanh", "atanh", GT, [v(GT, -0.99, 0.99)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.atanh)));
+
+ // 8.2 Exponential Functions.
+ var exps = new es3fShaderOperatorTests.BuiltinFuncGroup("exponential", "Exponential function tests");
+ exps.push(op("pow", "pow", GT, [v(GT, 0.1, 8.0), v(GT, -4.0, 2.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.pow)));
+ exps.push(op("exp", "exp", GT, [v(GT, -6.0, 3.0)], f(0.5), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.exp)));
+ exps.push(op("log", "log", GT, [v(GT, 0.1, 10.0)], f(0.5), f(0.3),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.log)));
+ exps.push(op("exp2", "exp2", GT, [v(GT, -7.0, 2.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(exp2)));
+ exps.push(op("log2", "log2", GT, [v(GT, 0.1, 10.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.log2)));
+ exps.push(op("sqrt", "sqrt", GT, [v(GT, 0.0, 10.0)], f(0.3), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.sqrt)));
+ exps.push(op("inversesqrt", "inversesqrt", GT, [v(GT, 0.5, 10.0)], f(1.0), f(0.0),
+ mediumhighp, es3fShaderOperatorTests.unaryGenTypeFuncs(inverseSqrt)));
+
+ funcInfoGroups.push(exps);
+
+ // 8.3 Common Functions.
+ var comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+ comm.push(op("abs", "abs", GT, [v(GT, -2.0, 2.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.abs)));
+ comm.push(op("sign", "sign", GT, [v(GT, -1.5, 1.5)], f(0.3), f(0.5),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.sign)));
+ comm.push(op("floor", "floor", GT, [v(GT, 2.5, 2.5)], f(0.2), f(0.7),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.floor)));
+ comm.push(op("trunc", "trunc", GT, [v(GT, 2.5, 2.5)], f(0.2), f(0.7),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.trunc)));
+ comm.push(op("round", "round", GT, [v(GT, 2.5, 2.5)], f(0.2), f(0.7),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(roundToEven)));
+
+ comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+
+ comm.push(op("roundEven", "roundEven", GT, [v(GT, 2.5, 2.5)], f(0.2), f(0.7),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(roundToEven)));
+ comm.push(op("ceil", "ceil", GT, [v(GT, 2.5, 2.5)], f(0.2), f(0.5),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(Math.ceil)));
+ comm.push(op("fract", "fract", GT, [v(GT, -1.5, 1.5)], f(0.8), f(0.1),
+ all, es3fShaderOperatorTests.unaryGenTypeFuncs(fract)));
+ comm.push(op("mod", "mod", GT, [v(GT, -2.0, 2.0), v(GT, 0.9, 6.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.binaryGenTypeFuncs(deMath.mod)));
+ comm.push(op("mod", "mod", GT, [v(FV, -2.0, 2.0), v(F, 0.9, 6.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.binaryVecScalarFuncs(deMath.modScale)));
+
+ comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+
+ comm.push(op("min", "min", GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.min)));
+ comm.push(op("min", "min", GT, [v(FV, -1.0, 1.0), v(F, -1.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(minVecScalar)));
+ comm.push(op("min", "min", IGT, [v(IGT, -4.0, 4.0), v(IGT, -4.0, 4.0)], f(0.125), f(0.5),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.min, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ comm.push(op("min", "min", IGT, [v(IV, -4.0, 4.0), v(I, -4.0, 4.0)], f(0.125), f(0.5),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(minVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ comm.push(op("min", "min", UGT, [v(UGT, 0.0, 8.0), v(UGT, 0.0, 8.0)], f(0.125), f(0.0),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.min, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+
+ comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+
+ comm.push(op("min", "min", UGT, [v(UV, 0.0, 8.0), v(U, 0.0, 8.0)], f(0.125), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(minVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ comm.push(op("max", "max", GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.max)));
+ comm.push(op("max", "max", GT, [v(FV, -1.0, 1.0), v(F, -1.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(maxVecScalar)));
+ comm.push(op("max", "max", IGT, [v(IGT, -4.0, 4.0), v(IGT, -4.0, 4.0)], f(0.125), f(0.5),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.max, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ comm.push(op("max", "max", IGT, [v(IV, -4.0, 4.0), v(I, -4.0, 4.0)], f(0.125), f(0.5),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(maxVecScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+
+ comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+
+ comm.push(op("max", "max", UGT, [v(UGT, 0.0, 8.0), v(UGT, 0.0, 8.0)], f(0.125), f(0.0),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(Math.max, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ comm.push(op("max", "max", UGT, [v(UV, 0.0, 8.0), v(U, 0.0, 8.0)], f(0.125), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecScalarFuncs(maxVecScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ comm.push(op("clamp", "clamp", GT, [v(GT, -1.0, 1.0), v(GT, -0.5, 0.5), v(GT, 0.5, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.ternaryGenTypeFuncs(deMath.clamp)));
+ comm.push(op("clamp", "clamp", GT, [v(FV, -1.0, 1.0), v(F, -0.5, 0.5), v(F, 0.5, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.ternaryVecScalarScalarFuncs(clampVecScalarScalar)));
+ comm.push(op("clamp", "clamp", IGT, [v(IGT, -4.0, 4.0), v(IGT, -2.0, 2.0), v(IGT, 2.0, 4.0)], f(0.125), f(0.5),
+ all, es3fShaderOperatorTests.ternaryGenTypeFuncs(deMath.clamp, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+
+ comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+
+ comm.push(op("clamp", "clamp", IGT, [v(IGT, -4.0, 4.0), v(I, -2.0, 2.0), v(I, 2.0, 4.0)], f(0.125), f(0.5),
+ all, es3fShaderOperatorTests.ternaryVecScalarScalarFuncs(clampVecScalarScalar, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ comm.push(op("clamp", "clamp", UGT, [v(UGT, 0.0, 8.0), v(UGT, 2.0, 6.0), v(UGT, 6.0, 8.0)], f(0.125), f(0.0),
+ all, es3fShaderOperatorTests.ternaryGenTypeFuncs(deMath.clamp, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ comm.push(op("clamp", "clamp", UGT, [v(UV, 0.0, 8.0), v(U, 2.0, 6.0), v(U, 6.0, 8.0)], f(0.125), f(0.0),
+ all, es3fShaderOperatorTests.ternaryVecScalarScalarFuncs(clampVecScalarScalar, gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT)));
+ comm.push(op("mix", "mix", GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 1.0), v(GT, 0.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.ternaryGenTypeFuncs(mix)));
+ comm.push(op("mix", "mix", GT, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0), v(F, 0.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.ternaryVecVecScalarFuncs(mixVecVecScalar)));
+
+ comm = new es3fShaderOperatorTests.BuiltinFuncGroup("common_functions", "Common function tests.");
+ funcInfoGroups.push(comm);
+
+ comm.push(op("step", "step", GT, [v(GT, -1.0, 1.0), v(GT, -1.0, 0.0)], f(0.5), f(0.25),
+ all, es3fShaderOperatorTests.binaryGenTypeFuncs(step)));
+ comm.push(op("step", "step", GT, [v(F, -1.0, 1.0), v(FV, -1.0, 0.0)], f(0.5), f(0.25),
+ all, es3fShaderOperatorTests.binaryScalarVecFuncs(stepScalarVec)));
+ comm.push(op("smoothstep", "smoothstep", GT, [v(GT, -0.5, 0.0), v(GT, 0.1, 1.0), v(GT, -1.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.ternaryGenTypeFuncs(smoothStep)));
+ comm.push(op("smoothstep", "smoothstep", GT, [v(F, -0.5, 0.0), v(F, 0.1, 1.0), v(FV, -1.0, 1.0)], f(0.5), f(0.5),
+ all, es3fShaderOperatorTests.ternaryScalarScalarVecFuncs(smoothStepScalarScalarVec)));
+
+ // 8.4 Geometric Functions.
+ var geom = new es3fShaderOperatorTests.BuiltinFuncGroup("geometric", "Geometric function tests.");
+ geom.push(op("length", "length", F, [v(GT, -5.0, 5.0)], f(0.1), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryScalarGenTypeFuncs(length)));
+ geom.push(op("distance", "distance", F, [v(GT, -5.0, 5.0), v(GT, -5.0, 5.0)], f(0.1), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(distance)));
+ geom.push(op("dot", "dot", F, [v(GT, -5.0, 5.0), v(GT, -5.0, 5.0)], f(0.1), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.binaryScalarGenTypeFuncs(dot)));
+ geom.push(op("cross", "cross", V3, [v(GT, -5.0, 5.0), v(GT, -5.0, 5.0)], f(0.1), f(0.5),
+ mediumhighp, {vec3: es3fShaderOperatorTests.binaryVecVecFuncs(cross).vec3}));
+ geom.push(op("normalize", "normalize", GT, [v(GT, 0.1, 4.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.unaryArrayFuncs(normalize)));
+ geom.push(op("faceforward", "faceforward", GT, [v(GT, -5.0, 5.0), v(GT, -5.0, 5.0), v(GT, -1.0, 1.0)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.ternaryVecVecVecFuncs(faceforward)));
+ geom.push(op("reflect", "reflect", GT, [v(GT, -0.8, -0.5), v(GT, 0.5, 0.8)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.binaryVecVecFuncs(reflect)));
+ geom.push(op("refract", "refract", GT, [v(GT, -0.8, 1.2), v(GT, -1.1, 0.5), v(F, 0.2, 1.5)], f(0.5), f(0.5),
+ mediumhighp, es3fShaderOperatorTests.ternaryVecVecScalarFuncs(refract)));
+
+ funcInfoGroups.push(geom);
+
+ // 8.6 Vector Relational Functions.
+ var floatComp = new es3fShaderOperatorTests.BuiltinFuncGroup("float_compare", "Floating point comparison tests.");
+ floatComp.push(op("lessThan", "lessThan", BV, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(lessThanVec)));
+ floatComp.push(op("lessThanEqual", "lessThanEqual", BV, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(lessThanEqualVec)));
+ floatComp.push(op("greaterThan", "greaterThan", BV, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(greaterThanVec)));
+ floatComp.push(op("greaterThanEqual", "greaterThanEqual", BV, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(greaterThanEqualVec)));
+ floatComp.push(op("equal", "equal", BV, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(allEqualVec)));
+ floatComp.push(op("notEqual", "notEqual", BV, [v(FV, -1.0, 1.0), v(FV, -1.0, 1.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(anyNotEqualVec)));
+
+ funcInfoGroups.push(floatComp);
+
+ var intComp = new es3fShaderOperatorTests.BuiltinFuncGroup("int_compare", "Integer comparison tests.");
+ intComp.push(op("lessThan", "lessThan", BV, [v(IV, 5.2, 4.9), v(IV, -5.0, 5.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(lessThanVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ intComp.push(op("lessThanEqual", "lessThanEqual", BV, [v(IV, -5.2, 4.9), v(IV, -5.0, 5.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(lessThanEqualVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ intComp.push(op("greaterThan", "greaterThan", BV, [v(IV, -5.2, 4.9), v(IV, -5.0, 5.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(greaterThanVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ intComp.push(op("greaterThanEqual", "greaterThanEqual", BV, [v(IV, -5.2, 4.9), v(IV, -5.0, 5.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(greaterThanEqualVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ intComp.push(op("equal", "equal", BV, [v(IV, -5.2, 4.9), v(IV, -5.0, 5.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(allEqualVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+ intComp.push(op("notEqual", "notEqual", BV, [v(IV, -5.2, 4.9), v(IV, -5.0, 5.0)], f(1.0), f(0.0),
+ all, es3fShaderOperatorTests.binaryVecVecFuncs(anyNotEqualVec, gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT)));
+
+ funcInfoGroups.push(intComp);
+
+ var boolComp = new es3fShaderOperatorTests.BuiltinFuncGroup("bool_compare", "Boolean comparison tests.");
+ var evalBoolEqual = es3fShaderOperatorTests.binaryVecVecFuncs(allEqualVec, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL);
+ var evalBoolNotEqual = es3fShaderOperatorTests.binaryVecVecFuncs(anyNotEqualVec, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL);
+ var evalBoolAny = es3fShaderOperatorTests.unaryBooleanGenTypeFuncs(boolAny, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL);
+ evalBoolAny.scalar = null;
+ var evalBoolAll = es3fShaderOperatorTests.unaryBooleanGenTypeFuncs(boolAll, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL);
+ evalBoolAll.scalar = null;
+ var evalBoolNot = es3fShaderOperatorTests.unaryArrayFuncs(boolNotVec, gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL);
+ evalBoolNot.scalar = null;
+
+ boolComp.push(op("equal", "equal", BV, [v(BV, -5.2, 4.9), v(BV, -5.0, 5.0)], f(1.0), f(0.0),
+ na, evalBoolEqual));
+ boolComp.push(op("notEqual", "notEqual", BV, [v(BV, -5.2, 4.9), v(BV, -5.0, 5.0)], f(1.0), f(0.0),
+ na, evalBoolNotEqual));
+ boolComp.push(op("any", "any", B, [v(BV, -1.0, 0.3)], f(1.0), f(0.0),
+ na, evalBoolAny));
+ boolComp.push(op("all", "all", B, [v(BV, -0.3, 1.0)], f(1.0), f(0.0),
+ na, evalBoolAll));
+ boolComp.push(op("not", "not", BV, [v(BV, -1.0, 1.0)], f(1.0), f(0.0),
+ na, evalBoolNot));
+
+ funcInfoGroups.push(boolComp);
+
+ var s_shaderTypes = [
+ gluShaderProgram.shaderType.VERTEX,
+ gluShaderProgram.shaderType.FRAGMENT
+ ];
+
+ var s_floatTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4
+ ];
+
+ var s_intTypes = [
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4
+ ];
+
+ var s_uintTypes = [
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4
+ ];
+
+ var s_boolTypes = [
+ gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL_VEC2,
+ gluShaderUtil.DataType.BOOL_VEC3,
+ gluShaderUtil.DataType.BOOL_VEC4
+ ];
+
+ for (var outerGroupNdx = 0; outerGroupNdx < funcInfoGroups.length; outerGroupNdx++) {
+ // Create outer group.
+ var outerGroupInfo = funcInfoGroups[outerGroupNdx];
+ var outerGroup = new tcuTestCase.DeqpTest(outerGroupInfo.name, outerGroupInfo.description);
+ this.addChild(outerGroup);
+
+ // Only create new group if name differs from previous one.
+ var innerGroup = null;
+
+ for (var funcInfoNdx = 0; funcInfoNdx < outerGroupInfo.funcInfos.length; funcInfoNdx++) {
+ var funcInfo = outerGroupInfo.funcInfos[funcInfoNdx];
+ var shaderFuncName = funcInfo.shaderFuncName;
+ var isBoolCase = (funcInfo.precision == es3fShaderOperatorTests.Precision.None);
+ var isBoolOut = es3fShaderOperatorTests.isBoolType(funcInfo.outValue);
+ var isIntOut = es3fShaderOperatorTests.isIntType(funcInfo.outValue);
+ var isUintOut = es3fShaderOperatorTests.isUintType(funcInfo.outValue);
+ var isFloatOut = !isBoolOut && !isIntOut && !isUintOut;
+
+ if (!innerGroup || (innerGroup.name != funcInfo.caseName)) {
+ var groupDesc = 'Built-in function ' + shaderFuncName + '() tests.';
+ innerGroup = new tcuTestCase.DeqpTest(funcInfo.caseName, groupDesc);
+ outerGroup.addChild(innerGroup);
+ }
+
+ for (var inScalarSize = 1; inScalarSize <= 4; inScalarSize++) {
+ var outScalarSize = ((funcInfo.outValue == es3fShaderOperatorTests.ValueType.FLOAT) || (funcInfo.outValue == es3fShaderOperatorTests.ValueType.BOOL)) ? 1 : inScalarSize; // \todo [petri] Int.
+ var outDataType = isFloatOut ? s_floatTypes[outScalarSize - 1] :
+ isIntOut ? s_intTypes[outScalarSize - 1] :
+ isUintOut ? s_uintTypes[outScalarSize - 1] :
+ isBoolOut ? s_boolTypes[outScalarSize - 1] :
+ undefined;
+
+ var evalFunc = null;
+ if (inScalarSize == 1) evalFunc = funcInfo.evalFunctions.scalar;
+ else if (inScalarSize == 2) evalFunc = funcInfo.evalFunctions.vec2;
+ else if (inScalarSize == 3) evalFunc = funcInfo.evalFunctions.vec3;
+ else if (inScalarSize == 4) evalFunc = funcInfo.evalFunctions.vec4;
+ else throw new Error('Invalid scalar size ' + inScalarSize);
+
+ // Skip if no valid eval func.
+ // \todo [petri] Better check for V3 only etc. cases?
+ if (evalFunc == null)
+ continue;
+
+ var precisions = ['low', 'medium', 'high'];
+ for (var precId = 0; precId < precisions.length; precId++) {
+ var precision = precisions[precId];
+ if ((funcInfo.precision[precision]) ||
+ (funcInfo.precision == es3fShaderOperatorTests.Precision.None && precision === 'medium')) { // use mediump interpolators for booleans
+ var precisionPrefix = isBoolCase ? '' : precision + 'p_';
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ var shaderType = s_shaderTypes[shaderTypeNdx];
+ var shaderSpec = new es3fShaderOperatorTests.ShaderDataSpec();
+ var shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ var isVertexCase = shaderType == gluShaderProgram.shaderType.VERTEX;
+ var isUnaryOp = (funcInfo.inputs.length == 1);
+
+ // \note Data type names will be added to description and name in a following loop.
+ var desc = 'Built-in function ' + shaderFuncName + '(';
+ var name = precisionPrefix;
+
+ // Generate shader op.
+ var shaderOp = 'res = ';
+
+ var precNames = [gluShaderUtil.precision.PRECISION_LOWP,
+ gluShaderUtil.precision.PRECISION_MEDIUMP,
+ gluShaderUtil.precision.PRECISION_HIGHP];
+ // Setup shader data info.
+ shaderSpec.numInputs = 0;
+ shaderSpec.precision = isBoolCase ? undefined : precNames[precId];
+ shaderSpec.output = outDataType;
+ shaderSpec.resultScale = funcInfo.resultScale;
+ shaderSpec.resultBias = funcInfo.resultBias;
+ shaderSpec.referenceScale = funcInfo.referenceScale;
+ shaderSpec.referenceBias = funcInfo.referenceBias;
+
+ if (funcInfo.type == es3fShaderOperatorTests.OperationType.OPERATOR) {
+ if (isUnaryOp && funcInfo.isUnaryPrefix)
+ shaderOp += shaderFuncName;
+ } else if (funcInfo.type == es3fShaderOperatorTests.OperationType.FUNCTION)
+ shaderOp += shaderFuncName + '(';
+ else // SIDE_EFFECT_OPERATOR
+ shaderOp += 'in0;\n\t';
+
+ for (var inputNdx = 0; inputNdx < funcInfo.inputs.length; inputNdx++) {
+ var prevNdx = inputNdx > 0 ? inputNdx - 1 : funcInfo.inputs.length - 1;
+ var prevValue = funcInfo.inputs[prevNdx];
+ var value = funcInfo.inputs[inputNdx];
+
+ if (value.valueType == es3fShaderOperatorTests.ValueType.NONE)
+ continue; // Skip unused input.
+
+ var prevInScalarSize = es3fShaderOperatorTests.isScalarType(prevValue.valueType) ? 1 : inScalarSize;
+ var prevInDataType = es3fShaderOperatorTests.isFloatType(prevValue.valueType) ? s_floatTypes[prevInScalarSize - 1] :
+ es3fShaderOperatorTests.isIntType(prevValue.valueType) ? s_intTypes[prevInScalarSize - 1] :
+ es3fShaderOperatorTests.isUintType(prevValue.valueType) ? s_uintTypes[prevInScalarSize - 1] :
+ es3fShaderOperatorTests.isBoolType(prevValue.valueType) ? s_boolTypes[prevInScalarSize - 1] :
+ undefined;
+
+ var curInScalarSize = es3fShaderOperatorTests.isScalarType(value.valueType) ? 1 : inScalarSize;
+ var curInDataType = es3fShaderOperatorTests.isFloatType(value.valueType) ? s_floatTypes[curInScalarSize - 1] :
+ es3fShaderOperatorTests.isIntType(value.valueType) ? s_intTypes[curInScalarSize - 1] :
+ es3fShaderOperatorTests.isUintType(value.valueType) ? s_uintTypes[curInScalarSize - 1] :
+ es3fShaderOperatorTests.isBoolType(value.valueType) ? s_boolTypes[curInScalarSize - 1] :
+ undefined;
+
+ // Write input type(s) to case description and name.
+
+ if (inputNdx > 0)
+ desc += ', ';
+
+ desc += gluShaderUtil.getDataTypeName(curInDataType);
+
+ if (inputNdx == 0 || prevInDataType != curInDataType) // \note Only write input type to case name if different from previous input type (avoid overly long names).
+ name += gluShaderUtil.getDataTypeName(curInDataType) + '_';
+
+ // Generate op input source.
+
+ if (funcInfo.type == es3fShaderOperatorTests.OperationType.OPERATOR || funcInfo.type == es3fShaderOperatorTests.OperationType.FUNCTION) {
+ if (inputNdx != 0) {
+ if (funcInfo.type == es3fShaderOperatorTests.OperationType.OPERATOR && !isUnaryOp)
+ shaderOp += ' ' + shaderFuncName + ' ';
+ else
+ shaderOp += ', ';
+ }
+
+ shaderOp += 'in' + inputNdx.toString(10);
+
+ if (funcInfo.type == es3fShaderOperatorTests.OperationType.OPERATOR && isUnaryOp && !funcInfo.isUnaryPrefix)
+ shaderOp += shaderFuncName;
+ } else{
+ if (inputNdx != 0 || (isUnaryOp && funcInfo.isUnaryPrefix))
+ shaderOp += (isUnaryOp ? '' : ' ') + shaderFuncName + (isUnaryOp ? '' : ' ');
+
+ shaderOp += inputNdx == 0 ? 'res' : 'in' + inputNdx.toString(10); // \note in0 has already been assigned to res, so start from in1.
+
+ if (isUnaryOp && !funcInfo.isUnaryPrefix)
+ shaderOp += shaderFuncName;
+ }
+
+ // Fill in shader info.
+ shaderSpec.inputs[shaderSpec.numInputs++] = new es3fShaderOperatorTests.ShaderValue(curInDataType, value.rangeMin, value.rangeMax);
+ }
+
+ if (funcInfo.type == es3fShaderOperatorTests.OperationType.FUNCTION)
+ shaderOp += ')';
+
+ shaderOp += ';';
+
+ desc += ').';
+ name += shaderTypeName;
+
+ // Create the test case.
+ innerGroup.addChild(new es3fShaderOperatorTests.ShaderOperatorCase(name, desc, isVertexCase, evalFunc, shaderOp, shaderSpec));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // The ?: selection operator.
+
+ var s_selectionInfo = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4,
+ gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL_VEC2,
+ gluShaderUtil.DataType.BOOL_VEC3,
+ gluShaderUtil.DataType.BOOL_VEC4
+ ];
+
+ var selectionEvalFuncsFloat = es3fShaderOperatorTests.selectionFuncs(gluShaderUtil.DataType.FLOAT);
+ var selectionEvalFuncsInt = es3fShaderOperatorTests.selectionFuncs(gluShaderUtil.DataType.INT);
+ var selectionEvalFuncsUint = es3fShaderOperatorTests.selectionFuncs(gluShaderUtil.DataType.UINT);
+ var selectionEvalFuncsBool = es3fShaderOperatorTests.selectionFuncs(gluShaderUtil.DataType.BOOL);
+
+ var selectionGroup = new tcuTestCase.DeqpTest('selection', 'Selection operator tests');
+ this.addChild(selectionGroup);
+
+ for (var typeNdx = 0; typeNdx < s_selectionInfo.length; typeNdx++) {
+ var curType = s_selectionInfo[typeNdx];
+ var scalarSize = gluShaderUtil.getDataTypeScalarSize(curType);
+ var isBoolCase = gluShaderUtil.isDataTypeBoolOrBVec(curType);
+ var isFloatCase = gluShaderUtil.isDataTypeFloatOrVec(curType);
+ var isIntCase = gluShaderUtil.isDataTypeIntOrIVec(curType);
+ var isUintCase = gluShaderUtil.isDataTypeUintOrUVec(curType);
+ var dataTypeStr = gluShaderUtil.getDataTypeName(curType);
+
+ var evalFuncs = selectionEvalFuncsFloat;
+ if (isBoolCase)
+ evalFuncs = selectionEvalFuncsBool;
+ else if (isIntCase)
+ evalFuncs = selectionEvalFuncsInt;
+ else if (isUintCase)
+ evalFuncs = selectionEvalFuncsUint;
+
+ var evalFunc = evalFuncs[scalarSize];
+
+ for (var prec in gluShaderUtil.precision) {
+ var precision = gluShaderUtil.precision[prec];
+ if (isBoolCase && precision != gluShaderUtil.precision.PRECISION_MEDIUMP) // Use mediump interpolators for booleans.
+ continue;
+
+ var precisionStr = gluShaderUtil.getPrecisionName(precision);
+ var precisionPrefix = isBoolCase ? '' : (precisionStr + '_');
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ var shaderType = s_shaderTypes[shaderTypeNdx];
+ var shaderSpec = new es3fShaderOperatorTests.ShaderDataSpec();
+ var shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ var isVertexCase = shaderType == gluShaderProgram.shaderType.VERTEX;
+
+ var name = precisionPrefix + dataTypeStr + '_' + shaderTypeName;
+
+ shaderSpec.numInputs = 3;
+ shaderSpec.precision = isBoolCase ? undefined : precision;
+ shaderSpec.output = curType;
+ shaderSpec.resultScale = isBoolCase ? f(1.0) : isFloatCase ? f(0.5) : isUintCase ? f(0.5) : f(0.1);
+ shaderSpec.resultBias = isBoolCase ? f(0.0) : isFloatCase ? f(0.5) : isUintCase ? f(0.0) : f(0.5);
+ shaderSpec.referenceScale = shaderSpec.resultScale;
+ shaderSpec.referenceBias = shaderSpec.resultBias;
+
+ var rangeMin = isBoolCase ? -1.0 : isFloatCase ? -1.0 : isUintCase ? 0.0 : -5.0;
+ var rangeMax = isBoolCase ? 1.0 : isFloatCase ? 1.0 : isUintCase ? 2.0 : 5.0;
+
+ shaderSpec.inputs[0] = new es3fShaderOperatorTests.ShaderValue(gluShaderUtil.DataType.BOOL, f(-1.0), f(1.0));
+ shaderSpec.inputs[1] = new es3fShaderOperatorTests.ShaderValue(curType, f(rangeMin), f(rangeMax));
+ shaderSpec.inputs[2] = new es3fShaderOperatorTests.ShaderValue(curType, f(rangeMin), f(rangeMax));
+
+ selectionGroup.addChild(new es3fShaderOperatorTests.ShaderOperatorCase(name, '', isVertexCase, evalFunc, 'res = in0 ? in1 : in2;', shaderSpec));
+ }
+ }
+ }
+
+ // The sequence operator (comma).
+ /** @type {tcuTestCase.DeqpTest} */ var sequenceGroup = new tcuTestCase.DeqpTest('sequence', 'sequence');
+ this.addChild(sequenceGroup);
+
+ /** @type {tcuTestCase.DeqpTest} */ var sequenceNoSideEffGroup = new tcuTestCase.DeqpTest('no_side_effects', 'Sequence tests without side-effects');
+ /** @type {tcuTestCase.DeqpTest} */ var sequenceSideEffGroup = new tcuTestCase.DeqpTest('side_effects', 'Sequence tests with side-effects');
+ sequenceGroup.addChild(sequenceNoSideEffGroup);
+ sequenceGroup.addChild(sequenceSideEffGroup);
+
+ /**
+ * @struct
+ * @constructor
+ * @param {boolean} containsSideEffects
+ * @param {string} caseName
+ * @param {string} expressionStr
+ * @param {number} numInputs
+ * @param {Array<gluShaderUtil.DataType>} inputTypes
+ * @param {gluShaderUtil.DataType} resultType
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ */
+ var SequenceCase = function(containsSideEffects, caseName, expressionStr, numInputs, inputTypes, resultType, evalFunc) {
+ /** @type {boolean} */ this.containsSideEffects = containsSideEffects;
+ /** @type {string} */ this.caseName = caseName;
+ /** @type {string} */ this.expressionStr = expressionStr;
+ /** @type {number} */ this.numInputs = numInputs;
+ /** @type {Array<gluShaderUtil.DataType>} */ this.inputTypes = inputTypes;
+ /** @type {gluShaderUtil.DataType} */ this.resultType = resultType;
+ /** @type {glsShaderRenderCase.ShaderEvalFunc} */ this.evalFunc = evalFunc;
+ };
+
+ /** @type {Array<SequenceCase>} */ var s_sequenceCases = [
+ new SequenceCase(false, 'vec4', 'in0, in2 + in1, in1 + in0', 3, [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.FLOAT_VEC4], gluShaderUtil.DataType.FLOAT_VEC4, es3fShaderOperatorTests.evalSequenceNoSideEffCase0),
+ new SequenceCase(false, 'float_uint', 'in0 + in2, in1 + in1', 3, [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.UINT, gluShaderUtil.DataType.FLOAT], gluShaderUtil.DataType.UINT, es3fShaderOperatorTests.evalSequenceNoSideEffCase1),
+ new SequenceCase(false, 'bool_vec2', 'in0 && in1, in0, ivec2(vec2(in0) + in2)', 3, [gluShaderUtil.DataType.BOOL, gluShaderUtil.DataType.BOOL, gluShaderUtil.DataType.FLOAT_VEC2], gluShaderUtil.DataType.INT_VEC2, es3fShaderOperatorTests.evalSequenceNoSideEffCase2),
+ new SequenceCase(false, 'vec4_ivec4_bvec4', 'in0 + vec4(in1), in2, in1', 3, [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.INT_VEC4, gluShaderUtil.DataType.BOOL_VEC4], gluShaderUtil.DataType.INT_VEC4, es3fShaderOperatorTests.evalSequenceNoSideEffCase3),
+
+ new SequenceCase(true, 'vec4', 'in0++, in1 = in0 + in2, in2 = in1', 3, [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.FLOAT_VEC4], gluShaderUtil.DataType.FLOAT_VEC4, es3fShaderOperatorTests.evalSequenceSideEffCase0),
+ new SequenceCase(true, 'float_uint', 'in1++, in0 = float(in1), in1 = uint(in0 + in2)', 3, [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.UINT, gluShaderUtil.DataType.FLOAT], gluShaderUtil.DataType.UINT, es3fShaderOperatorTests.evalSequenceSideEffCase1),
+ new SequenceCase(true, 'bool_vec2', 'in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)', 3, [gluShaderUtil.DataType.BOOL, gluShaderUtil.DataType.BOOL, gluShaderUtil.DataType.FLOAT_VEC2], gluShaderUtil.DataType.INT_VEC2, es3fShaderOperatorTests.evalSequenceSideEffCase2),
+ new SequenceCase(true, 'vec4_ivec4_bvec4', 'in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++', 3, [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.INT_VEC4, gluShaderUtil.DataType.BOOL_VEC4], gluShaderUtil.DataType.INT_VEC4, es3fShaderOperatorTests.evalSequenceSideEffCase3)
+ ];
+
+ for (var caseNdx = 0; caseNdx < s_sequenceCases.length; caseNdx++) {
+ for (var precision in gluShaderUtil.precision) {
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ /** @type {gluShaderProgram.shaderType} */ var shaderType = s_shaderTypes[shaderTypeNdx];
+ /** @type {es3fShaderOperatorTests.ShaderDataSpec} */ var shaderSpec = new es3fShaderOperatorTests.ShaderDataSpec();
+ /** @type {string} */ var shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ /** @type {boolean} */ var isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
+
+ /** @type {string} */ var name = gluShaderUtil.getPrecisionName(gluShaderUtil.precision[precision]) + '_' + s_sequenceCases[caseNdx].caseName + '_' + shaderTypeName;
+
+ shaderSpec.numInputs = s_sequenceCases[caseNdx].numInputs;
+ shaderSpec.precision = gluShaderUtil.precision[precision];
+ shaderSpec.output = s_sequenceCases[caseNdx].resultType;
+ shaderSpec.resultScale = f(0.5);
+ shaderSpec.resultBias = f(0.0);
+ shaderSpec.referenceScale = shaderSpec.resultScale;
+ shaderSpec.referenceBias = shaderSpec.resultBias;
+
+ for (var inputNdx = 0; inputNdx < s_sequenceCases[caseNdx].numInputs; inputNdx++) {
+ /** @type {gluShaderUtil.DataType} */ var type = s_sequenceCases[caseNdx].inputTypes[inputNdx];
+ /** @type {es3fShaderOperatorTests.FloatScalar} */ var rangeMin = gluShaderUtil.isDataTypeFloatOrVec(type) ?
+ f(-0.5) : gluShaderUtil.isDataTypeIntOrIVec(type) ?
+ f(-2.0) : gluShaderUtil.isDataTypeUintOrUVec(type) ?
+ f(0.0) : f(-1.0);
+
+ /** @type {es3fShaderOperatorTests.FloatScalar} */ var rangeMax = gluShaderUtil.isDataTypeFloatOrVec(type) ?
+ f(0.5) : gluShaderUtil.isDataTypeIntOrIVec(type) ?
+ f(2.0) : gluShaderUtil.isDataTypeUintOrUVec(type) ?
+ f(2.0) : f(1.0);
+
+ shaderSpec.inputs[inputNdx] = new es3fShaderOperatorTests.ShaderValue(type, rangeMin, rangeMax);
+ }
+
+ /** @type {string} */ var expression = 'res = (' + s_sequenceCases[caseNdx].expressionStr + ');';
+
+ if (s_sequenceCases[caseNdx].containsSideEffects)
+ sequenceSideEffGroup.addChild(new es3fShaderOperatorTests.ShaderOperatorCase(name, '', isVertexCase, s_sequenceCases[caseNdx].evalFunc, expression, shaderSpec));
+ else
+ sequenceNoSideEffGroup.addChild(new es3fShaderOperatorTests.ShaderOperatorCase(name, '', isVertexCase, s_sequenceCases[caseNdx].evalFunc, expression, shaderSpec));
+ }
+ }
+ }
+
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fShaderOperatorTests.run = function(context, range) {
+ gl = context;
+
+ const canvas = gl.canvas;
+ canvas.width = canvasWH;
+ canvas.height = canvasWH;
+
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderOperatorTests.ShaderOperatorTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderOperatorTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js
new file mode 100644
index 0000000000..3e4233db4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js
@@ -0,0 +1,791 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderPackingFunctionTests');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuMatrixUtil');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+goog.require('modules.shared.glsShaderExecUtil');
+
+
+
+goog.scope(function() {
+ var es3fShaderPackingFunctionTests = functional.gles3.es3fShaderPackingFunctionTests;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
+ var tcuMatrixUtil = framework.common.tcuMatrixUtil;
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+ es3fShaderPackingFunctionTests.getUlpDiff = function(a, b) {
+ /** @type {number} */ var aBits = tcuFloat.newFloat32(a).bits();
+ /** @type {number} */ var bBits = tcuFloat.newFloat32(b).bits();
+ return aBits > bBits ? aBits - bBits : bBits - aBits;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase = function(name, description, shaderType) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
+ /** @type {?glsShaderExecUtil.ShaderSpec} */ this.m_spec = new glsShaderExecUtil.ShaderSpec();
+ /** @type {?glsShaderExecUtil.ShaderExecutor} */ this.m_executor = null;
+ };
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionCase;
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.init = function() {
+ assertMsgOptions(!this.m_executor, 'Error: Executor is not null.', false, true);
+ this.m_executor = glsShaderExecUtil.createExecutor(this.m_shaderType, this.m_spec);
+ if (!this.m_executor.isOk())
+ throw new Error('Compile failed');
+ };
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.deinit = function() {
+ this.m_executor = null;
+ };
+
+ /**
+ * @param {gluShaderUtil.precision} precision
+ * @return {string}
+ */
+ es3fShaderPackingFunctionTests.getPrecisionPostfix = function(precision) {
+ /** @type {Array<string>} */ var s_postfix = [
+ '_lowp',
+ '_mediump',
+ '_highp'
+ ];
+ assertMsgOptions(0 <= precision && precision < s_postfix.length, 'Error: Out of range', false, true);
+ return s_postfix[precision];
+ };
+
+ /**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {string}
+ */
+ es3fShaderPackingFunctionTests.getShaderTypePostfix = function(shaderType) {
+ /** @type {Array<string>} */ var s_postfix = [
+ '_vertex',
+ '_fragment'
+ ];
+ assertMsgOptions(0 <= shaderType && shaderType < s_postfix.length, 'Error Out of range', false, true);
+ return s_postfix[shaderType];
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {gluShaderUtil.precision} precision
+ */
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case = function(shaderType, precision) {
+ /** @const {string} */ var name = 'packsnorm2x16' +
+ es3fShaderPackingFunctionTests.getPrecisionPostfix(precision) +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packSnorm2x16', shaderType);
+ this.m_precision = precision;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = packSnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackSnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<Array<number>>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var outputs; // deUint32
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {number} */ var maxDiff = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : // Rounding only.
+ this.m_precision == gluShaderUtil.precision.PRECISION_MEDIUMP ? 33 : // (2^-10) * (2^15) + 1
+ this.m_precision == gluShaderUtil.precision.PRECISION_LOWP ? 129 : 0; // (2^-8) * (2^15) + 1
+ /** @type {number} */ var x;
+ /** @type {number} */ var y;
+ // Special values to check.
+ inputs.push([0.0, 0.0]);
+ inputs.push([-1.0, 1.0]);
+ inputs.push([0.5, -0.5]);
+ inputs.push([-1.5, 1.5]);
+ inputs.push([0.25, -0.75]);
+
+ // Random values, mostly in range.
+ for (var ndx = 0; ndx < 15; ndx++) {
+ x = rnd.getFloat() * 2.5 - 1.25;
+ y = rnd.getFloat() * 2.5 - 1.25;
+ inputs.push([x, y]);
+ }
+
+ // Large random values.
+ for (var ndx = 0; ndx < 80; ndx++) {
+ x = rnd.getFloat() * 1e6 - 0.5e6;
+ y = rnd.getFloat() * 1e6 - 0.5e6;
+ inputs.push([x, y]);
+ }
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Uint32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < numValues; valNdx++) {
+ /** @type {number} */ var ref0 = (deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][0], -1.0, 1.0) * 32767.0), -(1 << 15), (1 << 15) - 1)) & 0xFFFF;
+ /** @type {number} */ var ref1 = (deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][1], -1.0, 1.0) * 32767.0), -(1 << 15), (1 << 15) - 1)) & 0xFFFF;
+ /** @type {number} */ var ref = (ref1 << 16) | ref0;
+ /** @type {number} */ var res = outputs[valNdx];
+ /** @type {number} */ var res0 = (res & 0xffff);
+ /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
+ /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
+ /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints) {
+ bufferedLogToConsole(
+ 'ERROR: Mismatch in value ' + valNdx +
+ ', expected packSnorm2x16(' + inputs[valNdx] + ') = ' + ref + //tcu::toHex(ref)
+ ', got ' + res + // tcu::toHex(res)
+ '\n diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ }
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'unpacksnorm2x16' + es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackSnorm2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = unpackSnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackSnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 1; // Rounding error.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<number>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput; //vector<vec2<float>>
+ /** @type {goog.TypedArray} */ var outputs; //vector<vec2<float>>
+
+ inputs.push(0x00000000);
+ inputs.push(0x7fff8000);
+ inputs.push(0x80007fff);
+ inputs.push(0xffffffff);
+ inputs.push(0x0001fffe);
+
+ // Random values.
+ for (var ndx = 0; ndx < 95; ndx++)
+ inputs.push(rnd.getInt());
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0]; // This test case only has one output
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Float32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var in0 = Math.floor(inputs[valNdx] & 0xffff);
+ // Convert 16-bit uint to 16-bit int
+ var view = new DataView(new ArrayBuffer(4));
+ view.setUint16(0, in0, true);
+ in0 = view.getInt16(0, true);
+ /** @type {number} */ var in1 = Math.floor(deMath.shiftRight(inputs[valNdx], 16));
+ // Convert 16-bit uint to 16-bit int
+ var view = new DataView(new ArrayBuffer(4));
+ view.setUint16(0, in1, true);
+ in1 = view.getInt16(0, true);
+ /** @type {number} */ var ref0 = deMath.clamp(in0 / 32767., -1.0, 1.0);
+ /** @type {number} */ var ref1 = deMath.clamp(in1 / 32767., -1.0, 1.0);
+ /** @type {number} */ var res0 = outputs[2 * valNdx];
+ /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
+
+ /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0);
+ /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
+ ' expected unpackSnorm2x16(' + inputs[valNdx].toString(16) + ') = ' +
+ 'vec2(' + ref0.toString(16) + ', ' + ref1.toString(16) + ')' +
+ ', got vec2(' + res0.toString(16) + ', ' + res1.toString(16) + ')' +
+ '\n ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {gluShaderUtil.precision} precision
+ */
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case = function(shaderType, precision) {
+ /** @const {string} */ var name = 'packunorm2x16' +
+ es3fShaderPackingFunctionTests.getPrecisionPostfix(precision) +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packUnorm2x16', shaderType);
+ this.m_precision = precision;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = packUnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackUnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<Array<number>>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {goog.TypedArray} */ var outputs; // deUint32
+ /** @type {number} */ var maxDiff = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : // Rounding only.
+ this.m_precision == gluShaderUtil.precision.PRECISION_MEDIUMP ? 65 : // (2^-10) * (2^16) + 1
+ this.m_precision == gluShaderUtil.precision.PRECISION_LOWP ? 257 : 0; // (2^-8) * (2^16) + 1
+ /** @type {number} */ var x;
+ /** @type {number} */ var y;
+ // Special values to check.
+ inputs.push([0.0, 0.0]);
+ inputs.push([0.5, 1.0]);
+ inputs.push([1.0, 0.5]);
+ inputs.push([-0.5, 1.5]);
+ inputs.push([0.25, 0.75]);
+
+ // Random values, mostly in range.
+ for (var ndx = 0; ndx < 15; ndx++) {
+ x = rnd.getFloat() * 1.25;
+ y = rnd.getFloat() * 1.25;
+ inputs.push([x, y]);
+ }
+
+ // Large random values.
+ for (var ndx = 0; ndx < 80; ndx++) {
+ x = rnd.getFloat() * 1e6 - 1e5;
+ y = rnd.getFloat() * 1e6 - 1e5;
+ inputs.push([x, y]);
+ }
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Uint32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var ref0 = deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][0], 0.0, 1.0) * 65535.0), 0, (1 << 16) - 1) & 0xFFFF;
+ /** @type {number} */ var ref1 = deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][1], 0.0, 1.0) * 65535.0), 0, (1 << 16) - 1) & 0xFFFF;
+ /** @type {number} */ var ref = (ref1 << 16) | ref0;
+ /** @type {number} */ var res = outputs[valNdx];
+ /** @type {number} */ var res0 = (res & 0xffff);
+ /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
+ /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
+ /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx +
+ ', expected packUnorm2x16(' + inputs[valNdx] + ') = ' + ref /*tcu::toHex(ref)*/ +
+ ', got ' + res /*tcu::toHex(res)*/ +
+ '\n diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed === maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'unpackunorm2x16' +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackUnorm2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = unpackUnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackUnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 1; // Rounding error.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<number>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {goog.TypedArray} */ var outputs; //vector<vec2>
+
+ inputs.push(0x00000000);
+ inputs.push(0x7fff8000);
+ inputs.push(0x80007fff);
+ inputs.push(0xffffffff);
+ inputs.push(0x0001fffe);
+
+ // Random values.
+ for (var ndx = 0; ndx < 95; ndx++)
+ inputs.push(rnd.getInt());
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Float32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var in0 = Math.floor(inputs[valNdx] & 0xffff);
+ /** @type {number} */ var in1 = Math.floor(deMath.shiftRight(inputs[valNdx], 16));
+ /** @type {number} */ var ref0 = in0 / 65535.0;
+ /** @type {number} */ var ref1 = in1 / 65535.0;
+ /** @type {number} */ var res0 = outputs[2 * valNdx];
+ /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
+
+ /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0);
+ /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
+ ' expected unpackUnorm2x16(' + inputs[valNdx].toString(16) + ') = ' +
+ 'vec2(' + ref0.toString(16) + ', ' + ref1.toString(16) + ')' +
+ ', got vec2(' + res0.toString(16) + ', ' + res1.toString(16) + ')' +
+ '\n ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed === maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.PackHalf2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'packhalf2x16' +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packHalf2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = packHalf2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackHalf2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 0; // Values can be represented exactly in mediump.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<Array<number>>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {goog.TypedArray} */ var outputs; // deUint32
+
+ // Special values to check.
+ inputs.push([0.0, 0.0]);
+ inputs.push([0.5, 1.0]);
+ inputs.push([1.0, 0.5]);
+ inputs.push([-0.5, 1.5]);
+ inputs.push([0.25, 0.75]);
+
+ // Random values.
+ /** @type {number} */ var minExp = -14;
+ /** @type {number} */ var maxExp = 15;
+
+ /** @type {Array<number>} */ var v = [];
+ for (var ndx = 0; ndx < 95; ndx++) {
+ for (var c = 0; c < 2; c++) {
+ /** @type {number} */ var s = rnd.getBool() ? 1 : -1;
+ /** @type {number} */ var exp = rnd.getInt(minExp, maxExp);
+ /** @type {number} */ var mantissa = rnd.getInt(0) & ((1 << 23) - 1);
+
+ v[c] = (new tcuFloat.deFloat()).construct(s, exp ? exp : 1 /* avoid denormals */, (1 << 23) | mantissa).getValue();
+ }
+ inputs.push(v);
+ }
+
+ // Convert input values to fp16 and back to make sure they can be represented exactly in mediump.
+ for (var inVal in inputs)
+ inputs[inVal] = [tcuFloat.newFloat16(inputs[inVal][0]).getValue(), tcuFloat.newFloat16(inputs[inVal][1]).getValue()];
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Uint32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var ref0 = tcuFloat.newFloat16(inputs[valNdx][0]).bits();
+ /** @type {number} */ var ref1 = tcuFloat.newFloat16(inputs[valNdx][1]).bits();
+ /** @type {number} */ var ref = (ref1 << 16) | ref0;
+ /** @type {number} */ var res = outputs[valNdx];
+ /** @type {number} */ var res0 = (res & 0xffff);
+ /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
+ /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
+ /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx +
+ ', expected packHalf2x16(' + inputs[valNdx] + ') = ' + ref /*tcu::toHex(ref)*/ +
+ ', got ' + res /*tcu::toHex(res)*/ +
+ '\n diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'unpackhalf2x16' +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackHalf2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_MEDIUMP)));
+ this.m_spec.source = 'out0 = unpackHalf2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackHalf2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 0; // All bits must be accurate.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<number>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var outputs; // vector<vec2<float>>
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+
+ // Special values.
+ inputs.push((tcuFloat.newFloat16(0.0).bits() << 16) | tcuFloat.newFloat16(1.0).bits());
+ inputs.push((tcuFloat.newFloat16(1.0).bits() << 16) | tcuFloat.newFloat16(0.0).bits());
+ inputs.push((tcuFloat.newFloat16(-1.0).bits() << 16) | tcuFloat.newFloat16(0.5).bits());
+ inputs.push((tcuFloat.newFloat16(0.5).bits() << 16) | tcuFloat.newFloat16(-0.5).bits());
+
+ // Construct random values.
+ /** @type {number} */ var minExp = -14;
+ /** @type {number} */ var maxExp = 15;
+ /** @type {number} */ var mantBits = 10;
+
+ /** @type {number} */ var inVal = 0;
+ for (var ndx = 0; ndx < 96; ndx++) {
+ for (var c = 0; c < 2; c++) {
+ /** @type {number} */ var s = rnd.getBool() ? 1 : -1;
+ /** @type {number} */ var exp = rnd.getInt(minExp, maxExp);
+ /** @type {number} */ var mantissa = rnd.getInt(0) & ((1 << mantBits) - 1);
+ /** @type {number} */ var value = tcuFloat.newFloat16(0).construct(s, exp ? exp : 1 /* avoid denorm */, (1 << 10) | mantissa).bits();
+
+ inVal |= value << (16 * c);
+ }
+ inputs.push(inVal);
+ }
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Float32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var in0 = (inputs[valNdx] & 0xffff);
+ /** @type {number} */ var in1 = deMath.shiftRight(inputs[valNdx], 16);
+ /** @type {number} */ var ref0 = tcuFloat.halfFloatToNumber(in0);
+ /** @type {number} */ var ref1 = tcuFloat.halfFloatToNumber(in1);
+ /** @type {number} */ var res0 = outputs[2 * valNdx];
+ /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
+ /** @type {number} */ var refBits0 = tcuFloat.newFloat32(ref0).bits();
+ /** @type {number} */ var refBits1 = tcuFloat.newFloat32(ref1).bits();
+ /** @type {number} */ var resBits0 = tcuFloat.newFloat32(res0).bits();
+ /** @type {number} */ var resBits1 = tcuFloat.newFloat32(res1).bits();
+
+ /** @type {number} */ var diff0 = Math.abs(refBits0 - resBits0);
+ /** @type {number} */ var diff1 = Math.abs(refBits1 - resBits1);
+
+ if (isNaN(ref0) && isNaN(res0))
+ diff0 = 0;
+ if (isNaN(ref1) && isNaN(res1))
+ diff1 = 0;
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
+ ' expected unpackHalf2x16(' + inputs[valNdx] /*tcu::toHex(inputs[valNdx])*/ + ') = ' +
+ 'vec2(' + ref0 + ' / ' + refBits0 /*tcu::toHex(refBits0)*/ + ', ' + ref1 + ' / ' + refBits1 /*tcu::toHex(refBits1)*/ + ')' +
+ ', got vec2(' + res0 + ' / ' + resBits0 /*tcu::toHex(resBits0)*/ + ', ' + res1 + ' / ' + resBits1 /*tcu::toHex(resBits1)*/ + ')' +
+ '\n ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'pack_unpack', 'Floating-point pack and unpack function tests');
+ };
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionTests;
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_HIGHP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_HIGHP));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_HIGHP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_HIGHP));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderPackingFunctionTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderPackingFunctionTests.ShaderPackingFunctionTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderPackingFunctionTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPrecisionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPrecisionTests.js
new file mode 100644
index 0000000000..28a697397c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPrecisionTests.js
@@ -0,0 +1,947 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderPrecisionTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+ var es3fShaderPrecisionTests = functional.gles3.es3fShaderPrecisionTests;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+ /** @const {number} */ es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH = 32;
+ /** @const {number} */ es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT = 32;
+
+ es3fShaderPrecisionTests.add = function(a, b) { return a + b; };
+ es3fShaderPrecisionTests.sub = function(a, b) { return a - b; };
+ es3fShaderPrecisionTests.mul = function(a, b) { return a * b; };
+ // a * b = (a1 * 2^16 + a0) * (b1 * 2^16 + b0) = a1 * b1 * 2^32 + (a0 * b1 + a1 * b0) * 2^16 + a0 * b0
+ // 32bit integer multiplication may overflow in JavaScript. Only return low 32bit of the result.
+ es3fShaderPrecisionTests.mul32 = function(a, b) {
+ var sign = Math.sign(a) * Math.sign(b);
+ a = Math.abs(a);
+ b = Math.abs(b);
+ var a1 = deMath.split16(a)[1];
+ var a0 = deMath.split16(a)[0];
+ var b1 = deMath.split16(b)[1];
+ var b0 = deMath.split16(b)[0];
+ return sign * ((a0 * b1 + a1 * b0) * 0x10000 + a0 * b0);
+ }
+ es3fShaderPrecisionTests.div = function(a, b) { if (b !== 0) return a / b; else throw new Error('division by zero.')};
+
+ /**
+ * @param {gluShaderUtil.precision} precision
+ * @param {string} evalOp
+ * @param {boolean} isVertexCase
+ * @return {gluShaderProgram.ShaderProgram}
+ */
+ es3fShaderPrecisionTests.createFloatPrecisionEvalProgram = function(precision, evalOp, isVertexCase) {
+ /** @type {gluShaderUtil.DataType} */ var type = gluShaderUtil.DataType.FLOAT;
+ /** @type {gluShaderUtil.DataType} */ var outType = gluShaderUtil.DataType.UINT;
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(type);
+ /** @type {string} */ var outTypeName = gluShaderUtil.getDataTypeName(outType);
+ /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision);
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in ' + precName + ' ' + typeName + ' a_in0;\n' +
+ 'in ' + precName + ' ' + typeName + ' a_in1;\n';
+ frag += '#version 300 es\n' +
+ 'layout(location = 0) out highp ' + outTypeName + ' o_out;\n';
+
+ if (isVertexCase) {
+ vtx += 'flat out ' + precName + ' ' + typeName + ' v_out;\n';
+ frag += 'flat in ' + precName + ' ' + typeName + ' v_out;\n';
+ } else {
+ vtx += 'flat out ' + precName + ' ' + typeName + ' v_in0;\n' +
+ 'flat out ' + precName + ' ' + typeName + ' v_in1;\n';
+ frag += 'flat in ' + precName + ' ' + typeName + ' v_in0;\n' +
+ 'flat in ' + precName + ' ' + typeName + ' v_in1;\n';
+ }
+
+ vtx += '\nvoid main (void)\n{\n' +
+ ' gl_Position = a_position;\n';
+ frag += '\nvoid main (void)\n{\n';
+
+ op += '\t' + precName + ' ' + typeName + ' in0 = ' + (isVertexCase ? 'a_' : 'v_') + 'in0;\n' +
+ '\t' + precName + ' ' + typeName + ' in1 = ' + (isVertexCase ? 'a_' : 'v_') + 'in1;\n';
+
+ if (!isVertexCase)
+ op += '\t' + precName + ' ' + typeName + ' res;\n';
+
+ op += '\t' + (isVertexCase ? 'v_out' : 'res') + ' = ' + evalOp + ';\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ frag += ' o_out = floatBitsToUint(v_out);\n';
+ } else {
+ vtx += ' v_in0 = a_in0;\n' +
+ ' v_in1 = a_in1;\n';
+ frag += ' o_out = floatBitsToUint(res);\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag));
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @param {gluShaderUtil.precision} precision
+ * @param {string} evalOp
+ * @param {boolean} isVertexCase
+ * @return {gluShaderProgram.ShaderProgram}
+ */
+ es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram = function(type, precision, evalOp, isVertexCase) {
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(type);
+ /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision);
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in ' + precName + ' ' + typeName + ' a_in0;\n' +
+ 'in ' + precName + ' ' + typeName + ' a_in1;\n';
+ frag += '#version 300 es\n' +
+ 'layout(location = 0) out ' + precName + ' ' + typeName + ' o_out;\n';
+
+ if (isVertexCase) {
+ vtx += 'flat out ' + precName + ' ' + typeName + ' v_out;\n';
+ frag += 'flat in ' + precName + ' ' + typeName + ' v_out;\n';
+ } else {
+ vtx += 'flat out ' + precName + ' ' + typeName + ' v_in0;\n' +
+ 'flat out ' + precName + ' ' + typeName + ' v_in1;\n';
+ frag += 'flat in ' + precName + ' ' + typeName + ' v_in0;\n' +
+ 'flat in ' + precName + ' ' + typeName + ' v_in1;\n';
+ }
+
+ vtx += '\nvoid main (void)\n{\n'+
+ ' gl_Position = a_position;\n';
+ frag += '\nvoid main (void)\n{\n';
+
+ op += '\t' + precName + ' ' + typeName + ' in0 = ' + (isVertexCase ? 'a_' : 'v_') + 'in0;\n' +
+ '\t' + precName + ' ' + typeName + ' in1 = ' + (isVertexCase ? 'a_' : 'v_') + 'in1;\n';
+
+ op += '\t' + (isVertexCase ? 'v_' : 'o_') + 'out = ' + evalOp + ';\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ frag += ' o_out = v_out;\n';
+ } else {
+ vtx += ' v_in0 = a_in0;\n' +
+ ' v_in1 = a_in1;\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag));
+ };
+
+ /** @typedef {function(number, number)} */ es3fShaderPrecisionTests.EvalFunc;
+
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} op
+ * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
+ * @param {gluShaderUtil.precision} precision
+ * @param {Array<number>} rangeA
+ * @param {Array<number>} rangeB
+ * @param {boolean} isVertexCase
+ */
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase = function(name, desc, op, evalFunc, precision, rangeA, rangeB, isVertexCase) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ // Case parameters.
+ /** @type {string} */ this.m_op = op;
+ /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc;
+ /** @type {gluShaderUtil.precision} */ this.m_precision = precision;
+ /** @type {Array<number>} */ this.m_rangeA = rangeA;
+ /** @type {Array<number>} */ this.m_rangeB = rangeB;
+ /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
+
+ /** @type {number} */ this.m_numTestsPerIter = 32;
+ /** @type {number} */ this.m_numIters = 4;
+ /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
+
+ // Iteration state.
+ /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {?WebGLFramebuffer} */ this.m_framebuffer = null;
+ /** @type {?WebGLRenderbuffer} */ this.m_renderbuffer = null;
+ /** @type {number} */ this.m_iterNdx = 0;
+ /** @type {Array<boolean>} */ this.m_iterPass = [];
+ };
+
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderFloatPrecisionCase;
+
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.init = function() {
+ assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true);
+
+ // Create program.
+ this.m_program = es3fShaderPrecisionTests.createFloatPrecisionEvalProgram(this.m_precision, this.m_op, this.m_isVertexCase);
+
+ if (!this.m_program.isOk())
+ assertMsgOptions(false, 'Compile failed', false, true);
+
+ // Create framebuffer.
+ this.m_framebuffer = gl.createFramebuffer();
+ this.m_renderbuffer = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32UI, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer);
+
+ assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.m_iterNdx = 0;
+ };
+
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.deinit = function() {
+ if(this.m_framebuffer)
+ gl.deleteFramebuffer(this.m_framebuffer);
+ if(this.m_renderbuffer)
+ gl.deleteRenderbuffer(this.m_renderbuffer);
+ this.m_program = null;
+ this.m_framebuffer = null;
+ this.m_renderbuffer = null;
+ };
+
+ /**
+ * @param {number} in0
+ * @param {number} in1
+ * @param {number} reference
+ * @param {number} result
+ */
+
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.compare = function(in0, in1, reference, result) {
+ // Comparison is done using 64-bit reference value to accurately evaluate rounding mode error.
+ // If 32-bit reference value is used, 2 bits of rounding error must be allowed.
+
+ // For mediump and lowp types the comparison currently allows 3 bits of rounding error:
+ // two bits from conversions and one from actual operation.
+
+ // \todo [2013-09-30 pyry] Make this more strict: determine if rounding can actually happen.
+
+ /** @type {number} */ var mantissaBits = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 23 : 10;
+ /** @type {number} */ var numPrecBits = 52 - mantissaBits;
+
+ /** @type {number} */ var in0Exp = tcuFloat.newFloat32(in0).exponent();
+ /** @type {number} */ var in1Exp = tcuFloat.newFloat32(in1).exponent();
+ /** @type {number} */ var resExp = tcuFloat.newFloat32(result).exponent();
+ /** @type {number} */ var numLostBits = Math.max(in0Exp - resExp, in1Exp - resExp, 0); // Lost due to mantissa shift.
+
+ /** @type {number} */ var roundingUlpError = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : 3;
+ /** @type {number} */ var maskBits = numLostBits + numPrecBits;
+
+ bufferedLogToConsole("Assuming " + mantissaBits + " mantissa bits, " + numLostBits + " bits lost in operation, and " + roundingUlpError + " ULP rounding error.")
+
+ // These numbers should never be larger than 52 bits. An assertion in getBitRange verifies this.
+ /** @type {number} */ var accurateRefBits = tcuFloat.newFloat64(reference).getBitRange(maskBits, 64);
+ /** @type {number} */ var accurateResBits = tcuFloat.newFloat64(result).getBitRange(maskBits, 64);
+ /** @type {number} */ var ulpDiff = Math.abs(accurateRefBits - accurateResBits);
+
+ if (ulpDiff > roundingUlpError) {
+ bufferedLogToConsole("ERROR: comparison failed! ULP diff (ignoring lost/undefined bits) = " + ulpDiff );
+ return false;
+ }
+ else
+ return true;
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.iterate = function() {
+ var testPassed = true;
+ var testPassedMsg = 'Pass';
+
+ // Constant data.
+ /** @type {Array<number>} */ var position =[
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0
+ ];
+
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+ /** @type {number} */ var numVertices = 4;
+ /** @type {Array<number>} */ var in0Arr = [0.0, 0.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var in1Arr = [0.0, 0.0, 0.0, 0.0];
+
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
+
+ // Image read from GL.
+ /** @type {goog.TypedArray} */ var pixels_uint = new Uint32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4);
+
+ // \todo [2012-05-03 pyry] Could be cached.
+ /** @type {WebGLProgram} */ var prog = this.m_program.getProgram();
+
+ gl.useProgram(prog);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+
+ vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position);
+
+
+ // Compute values and reference.
+ for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) {
+ /** @type {number} */ var in0 = this.m_rnd.getFloat(this.m_rangeA[0], this.m_rangeA[1]);
+ /** @type {number} */ var in1 = this.m_rnd.getFloat(this.m_rangeB[0], this.m_rangeB[1]);
+
+ // These random numbers are used in the reference computation. But
+ // highp is only 32 bits, so these float64s must be rounded to
+ // float32 first for correctness. This is needed for highp_mul_* on
+ // one Linux/NVIDIA machine.
+ in0 = tcuFloat.newFloat32(in0).getValue();
+ in1 = tcuFloat.newFloat32(in1).getValue();
+
+ /** @type {number} */ var refD = this.m_evalFunc(in0, in1);
+
+ bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": "+
+ "in0 = " + in0 + " / " + tcuFloat.newFloat32(in0).bits() +
+ ", in1 = " + in1 + " / " + tcuFloat.newFloat32(in1).bits() +
+ " reference = " + refD + " / " + tcuFloat.newFloat32(refD).bits());
+
+ in0Arr = [in0, in0, in0, in0];
+ in1Arr = [in1, in1, in1, in1];
+ vertexArrays[1] = gluDrawUtil.newFloatVertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr);
+ vertexArrays[2] = gluDrawUtil.newFloatVertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr);
+
+ gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
+
+ gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH,
+ es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixels_uint);
+
+ var pixels = new Float32Array(pixels_uint.buffer);
+ bufferedLogToConsole(" result = " + pixels[0] + " / " + tcuFloat.newFloat32(pixels[0]).bits());
+
+ // Verify results
+ /** @type {boolean} */ var firstPixelOk = this.compare(in0, in1, refD, pixels[0]);
+
+ if (firstPixelOk) {
+ // Check that rest of pixels match to first one.
+ /** @type {number} */ var firstPixelBits = tcuFloat.newFloat32(pixels[0]).bits();
+ /** @type {boolean} */ var allPixelsOk = true;
+
+ for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) {
+ for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) {
+ /** @type {number} */ var pixelBits = tcuFloat.newFloat32(pixels[(y * es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4]).bits();
+
+ if (pixelBits != firstPixelBits) {
+ bufferedLogToConsole("ERROR: Inconsistent results, got " + pixelBits + " at (" + x + ", " + y + ")")
+ allPixelsOk = false;
+ }
+ }
+
+ if (!allPixelsOk)
+ break;
+ }
+
+ if (!allPixelsOk){
+ bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + "Inconsistent values in framebuffer");
+ testPassed = false;
+ testPassedMsg = 'Inconsistent values in framebuffer';
+ }
+ }
+ else{
+ bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + "Result comparison failed");
+ testPassed = false;
+ testPassedMsg = 'Result comparison failed'
+ }
+ }
+
+ // [dag] Aggregating test results to make the test less verbose.
+ this.m_iterPass[this.m_iterNdx] = testPassed;
+
+ // [dag] Show test results after the last iteration is done.
+ if (this.m_iterPass.length === this.m_numIters) {
+ if (!deMath.boolAll(this.m_iterPass))
+ testFailedOptions(testPassedMsg, false);
+ else
+ testPassedOptions(testPassedMsg, true);
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.m_iterNdx += 1;
+ return (this.m_iterNdx < this.m_numIters) ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} op
+ * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
+ * @param {gluShaderUtil.precision} precision
+ * @param {number} bits
+ * @param {Array<number>} rangeA
+ * @param {Array<number>} rangeB
+ * @param {boolean} isVertexCase
+ */
+ es3fShaderPrecisionTests.ShaderIntPrecisionCase = function(name, desc, op, evalFunc, precision, bits, rangeA, rangeB, isVertexCase) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ // Case parameters.
+ /** @type {string} */ this.m_op = op;
+ /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc;
+ /** @type {gluShaderUtil.precision} */ this.m_precision = precision;
+ /** @type {number} */ this.m_bits = bits;
+ /** @type {Array<number>} */ this.m_rangeA = rangeA;
+ /** @type {Array<number>} */ this.m_rangeB = rangeB;
+ /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
+
+ /** @type {number} */ this.m_numTestsPerIter = 32;
+ /** @type {number} */ this.m_numIters = 4;
+ /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
+
+ // Iteration state.
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {WebGLFramebuffer} */ this.m_framebuffer = null;
+ /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null;
+ /** @type {number} */ this.m_iterNdx = 0;
+ };
+
+ es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderIntPrecisionCase;
+
+ es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.init = function() {
+ assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true);
+ // Create program.
+ this.m_program = es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram(gluShaderUtil.DataType.INT, this.m_precision, this.m_op, this.m_isVertexCase);
+
+ if (!this.m_program.isOk())
+ assertMsgOptions(false, 'Compile failed', false, true);
+
+ // Create framebuffer.
+ this.m_framebuffer = gl.createFramebuffer();
+ this.m_renderbuffer = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32I, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer);
+
+ assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.m_iterNdx = 0;
+
+ bufferedLogToConsole("Number of accurate bits assumed = " + this.m_bits);
+ };
+
+ es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.deinit = function() {
+ if(this.m_framebuffer)
+ gl.deleteFramebuffer(this.m_framebuffer);
+ if(this.m_renderbuffer)
+ gl.deleteRenderbuffer(this.m_renderbuffer);
+ this.m_program = null;
+ this.m_framebuffer = null;
+ this.m_renderbuffer = null;
+ };
+
+ /**
+ * @param {number} value
+ * @param {number} bits
+ * @return {number}
+ */
+
+ es3fShaderPrecisionTests.extendTo32Bit = function(value, bits) {
+ return (value & ((1 << (bits - 1)) - 1)) | ((value & (1 << (bits - 1))) << (32 - bits)) >> (32 - bits);
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.iterate = function() {
+ var testPassed = true;
+ var testPassedMsg = 'Pass';
+ // Constant data.
+ /** @type {Array<number>} */ var position = [
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0
+ ]
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+
+ /** @type {number} */ var numVertices = 4;
+ /** @type {Array<number>} */ var in0Arr = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var in1Arr = [0, 0, 0, 0];
+
+ /** @type {number} */ var mask = this.m_bits === 32 ? 0xffffffff : ((1 << this.m_bits) - 1);
+ /** @type {goog.TypedArray} */ var pixels = new Int32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4);
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
+
+ /** @type {WebGLProgram} */ var prog = this.m_program.getProgram();
+
+ // \todo [2012-05-03 pyry] A bit hacky. getInt() should work fine with ranges like this.
+ /** @type {boolean} */ var isMaxRangeA = this.m_rangeA[0] === 0x80000000 && this.m_rangeA[1] === 0x7fffffff;
+ /** @type {boolean} */ var isMaxRangeB = this.m_rangeB[0] === 0x80000000 && this.m_rangeB[1] === 0x7fffffff;
+
+ gl.useProgram(prog);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+
+ vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position);
+
+ // Compute values and reference.
+ for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) {
+ /** @type {number} */ var in0 = this.m_rnd.getInt(this.m_rangeA[0], this.m_rangeA[1]); //es3fShaderPrecisionTests.extendTo32Bit(((isMaxRangeA ? Math.abs(this.m_rnd.getInt()) : this.m_rnd.getInt(this.m_rangeA[0], this.m_rangeA[1])) & mask), this.m_bits);
+ /** @type {number} */ var in1 = this.m_rnd.getInt(this.m_rangeB[0], this.m_rangeB[1]); //es3fShaderPrecisionTests.extendTo32Bit(((isMaxRangeB ? Math.abs(this.m_rnd.getInt()) : this.m_rnd.getInt(this.m_rangeB[0], this.m_rangeB[1])) & mask), this.m_bits);
+ /** @type {number} */ var refMasked = this.m_evalFunc(in0, in1) & mask;
+ /** @type {number} */ var refOut = es3fShaderPrecisionTests.extendTo32Bit(refMasked, this.m_bits);
+
+ bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": " +
+ "in0 = " + in0 + ", in1 = " + in1 + ", ref out = " + refOut + " / " + refMasked);
+
+ in0Arr = [in0, in0, in0, in0];
+ in1Arr = [in1, in1, in1, in1];
+
+ vertexArrays[1] = gluDrawUtil.newInt32VertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr);
+ vertexArrays[2] = gluDrawUtil.newInt32VertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr);
+
+ gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
+
+ gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH,
+ es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT,
+ gl.RGBA_INTEGER, gl.INT, pixels);
+
+ // Compare pixels.
+ for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) {
+ for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) {
+ /** @type {number} */ var cmpOut = pixels[(y * es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4];
+ /** @type {number} */ var cmpMasked = cmpOut & mask;
+
+ if (cmpMasked != refMasked) {
+ bufferedLogToConsole("Comparison failed (at " + x + ", " + y + "): " +
+ + "got " + cmpOut + " / " + cmpOut);
+ testPassed = false;
+ testPassedMsg = 'Comparison failed';
+ }
+ }
+ }
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.m_iterNdx += 1;
+ if (!testPassed) {
+ testFailedOptions(testPassedMsg, false);
+ return tcuTestCase.IterateResult.STOP;
+ } else if (testPassed && this.m_iterNdx < this.m_numIters) {
+ return tcuTestCase.IterateResult.CONTINUE;
+ } else {
+ testPassedOptions(testPassedMsg, true);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} op
+ * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
+ * @param {gluShaderUtil.precision} precision
+ * @param {number} bits
+ * @param {Array<number>} rangeA
+ * @param {Array<number>} rangeB
+ * @param {boolean} isVertexCase
+ */
+ es3fShaderPrecisionTests.ShaderUintPrecisionCase = function(name, desc, op, evalFunc, precision, bits, rangeA, rangeB, isVertexCase) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ // Case parameters.
+ /** @type {string} */ this.m_op = op;
+ /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc;
+ /** @type {gluShaderUtil.precision} */ this.m_precision = precision;
+ /** @type {number} */ this.m_bits = bits;
+ /** @type {Array<number>} */ this.m_rangeA = rangeA;
+ /** @type {Array<number>} */ this.m_rangeB = rangeB;
+ /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
+
+ /** @type {number} */ this.m_numTestsPerIter = 32;
+ /** @type {number} */ this.m_numIters = 4;
+ /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
+
+ // Iteration state.
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {WebGLFramebuffer} */ this.m_framebuffer = null;
+ /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null;
+ /** @type {number} */ this.m_iterNdx = 0;
+ };
+
+ es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderUintPrecisionCase;
+
+ es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.init = function() {
+ assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true);
+ // Create program.
+ this.m_program = es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram(gluShaderUtil.DataType.UINT, this.m_precision, this.m_op, this.m_isVertexCase);
+
+ if (!this.m_program.isOk())
+ assertMsgOptions(false, 'Compile failed', false, true);
+
+ // Create framebuffer.
+ this.m_framebuffer = gl.createFramebuffer();
+ this.m_renderbuffer = gl.createRenderbuffer();
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32UI, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer);
+
+ assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.m_iterNdx = 0;
+
+ bufferedLogToConsole("Number of accurate bits assumed = " + this.m_bits);
+ };
+
+ es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.deinit = function() {
+ if(this.m_framebuffer)
+ gl.deleteFramebuffer(this.m_framebuffer);
+ if(this.m_renderbuffer)
+ gl.deleteRenderbuffer(this.m_renderbuffer);
+ this.m_program = null;
+ this.m_framebuffer = null;
+ this.m_renderbuffer = null;
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.iterate = function() {
+ var testPassed = true;
+ var testPassedMsg = 'Pass';
+
+ // Constant data.
+ /** @type {Array<number>} */ var position = [
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0
+ ];
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+
+ /** @type {number} */ var numVertices = 4;
+ /** @type {Array<number>} */ var in0Arr = [0, 0, 0, 0];
+ /** @type {Array<number>} */ var in1Arr = [0, 0, 0, 0];
+
+ /** @type {number} */ var mask = this.m_bits === 32 ? 0xffffffff : ((1 << this.m_bits) - 1);
+ /** @type {goog.TypedArray} */ var pixels = new Uint32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4);
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
+
+ /** @type {WebGLProgram} */ var prog = this.m_program.getProgram();
+
+ // \todo [2012-05-03 pyry] A bit hacky.
+ /** @type {boolean} */ var isMaxRangeA = this.m_rangeA[0] === 0 && this.m_rangeA[1] === 0xffffffff;
+ /** @type {boolean} */ var isMaxRangeB = this.m_rangeB[0] === 0 && this.m_rangeB[1] === 0xffffffff;
+
+ gl.useProgram(prog);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
+
+ vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position);
+
+ // Compute values and reference.
+ for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) {
+ /** @type {number} */ var in0 = (isMaxRangeA ? Math.abs(this.m_rnd.getInt()) : (this.m_rangeA[0] + Math.abs(this.m_rnd.getInt()) % (this.m_rangeA[1] - this.m_rangeA[0] + 1))) & mask;
+ /** @type {number} */ var in1 = (isMaxRangeB ? Math.abs(this.m_rnd.getInt()) : (this.m_rangeB[0] + Math.abs(this.m_rnd.getInt()) % (this.m_rangeB[1] - this.m_rangeB[0] + 1))) & mask;
+ /** @type {number} */ var refOut = this.m_evalFunc(in0, in1) & mask;
+
+ bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": " +
+ + "in0 = " + in0 + ", in1 = " + in1 + ", ref out = " + refOut)
+
+ in0Arr = [in0, in0, in0, in0];
+ in1Arr = [in1, in1, in1, in1];
+ vertexArrays[1] = gluDrawUtil.newUint32VertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr);
+ vertexArrays[2] = gluDrawUtil.newUint32VertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr);
+
+ gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
+
+ gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH,
+ es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixels);
+
+ // Compare pixels.
+ for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) {
+ for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) {
+ /** @type {number} */ var cmpOut = pixels[(y*es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4];
+ /** @type {number} */ var cmpMasked = cmpOut & mask;
+
+ if (cmpMasked != refOut) {
+ bufferedLogToConsole("Comparison failed (at " + x + ", " + y + "): " + "got " + cmpOut)
+ testPassed = false;
+ testPassedMsg = 'Comparison failed';
+ }
+ }
+ }
+ }
+
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ this.m_iterNdx += 1;
+ if (!testPassed) {
+ testFailedOptions(testPassedMsg, false);
+ return tcuTestCase.IterateResult.STOP;
+ } else if (testPassed && this.m_iterNdx < this.m_numIters) {
+ return tcuTestCase.IterateResult.CONTINUE;
+ } else {
+ testPassedOptions(testPassedMsg, true);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderPrecisionTests.ShaderPrecisionTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'precision', 'Shader precision requirements validation tests');
+ };
+
+ es3fShaderPrecisionTests.ShaderPrecisionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPrecisionTests.ShaderPrecisionTests.prototype.constructor = es3fShaderPrecisionTests.ShaderPrecisionTests;
+
+ es3fShaderPrecisionTests.ShaderPrecisionTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ // Exp = Emax-2, Mantissa = 0
+ // /** @type {number} */ var minF32 = tcuFloat.newFloat32((1 << 31) | (0xfd << 23) | 0x0).getValue();
+ // /** @type {number} */ var maxF32 = tcuFloat.newFloat32((0 << 31) | (0xfd << 23) | 0x0).getValue();
+ // [dag] Workaround for float32 numbers
+ /** @type {number} */ var minF32 = new Float32Array(new Uint32Array([1<<31|0xfd<<23|0x0]).buffer)[0];
+ /** @type {number} */ var maxF32 = new Float32Array(new Uint32Array([0<<31|0xfd<<23|0x0]).buffer)[0];
+
+ // /** @type {number} */ var minF16 = tcuFloat.newFloat16(((1 << 15) | (0x1d << 10) | 0x0)).getValue();
+ // /** @type {number} */ var maxF16 = tcuFloat.newFloat16(((0 << 15) | (0x1d << 10) | 0x0)).getValue();
+ /** @type {number} */ var minF16 = -16384; //-1 << 14; // 1 << 15 | 0x1d | 0x0 == 0b1111010000000000; -1 * (2**(29-15)) * 1
+ /** @type {number} */ var maxF16 = 16384; //1 << 14; // 0 << 15 | 0x1d | 0x0 == 0b0111010000000000; +1 * (2**(29-15)) * 1
+
+ /** @type {Array<number>} */ var fullRange32F = [minF32, maxF32];
+ /** @type {Array<number>} */ var fullRange16F = [minF16, maxF16];
+ /** @type {Array<number>} */ var fullRange32I = [-2147483648, 2147483647]; // [0x80000000|0, 0x7fffffff|0]; // |0 to force the number as a 32-bit integer
+ /** @type {Array<number>} */ var fullRange16I = [minF16, maxF16 - 1]; //[-(1 << 15), (1 << 15) - 1]; // Added the negative sign to index 0
+ /** @type {Array<number>} */ var fullRange8I = [-128, 127]; //[-(1 << 7), (1 << 7) - 1]; // Added the negative sign to index 0
+ /** @type {Array<number>} */ var fullRange32U = [0, 0xffffffff];
+ /** @type {Array<number>} */ var fullRange16U = [0, 0xffff];
+ /** @type {Array<number>} */ var fullRange8U = [0, 0xff];
+
+ // \note Right now it is not programmatically verified that the results shouldn't end up being inf/nan but
+ // actual values used are ok.
+
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {string} op
+ * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
+ * @param {gluShaderUtil.precision} precision
+ * @param {Array<number>} rangeA
+ * @param {Array<number>} rangeB
+ */
+ var FloatCase = function(name, op, evalFunc, precision, rangeA, rangeB) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.op = op;
+ /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc;
+ /** @type {gluShaderUtil.precision} */ this.precision = precision;
+ /** @type {Array<number>} */ this.rangeA = rangeA;
+ /** @type {Array<number>} */ this.rangeB = rangeB;
+ };
+
+ /** @type {Array<FloatCase>} */ var floatCases = [
+ new FloatCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, fullRange32F, fullRange32F),
+ new FloatCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, fullRange32F, fullRange32F),
+ new FloatCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_HIGHP, [-1e5, 1e5], [-1e5, 1e5]),
+ new FloatCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, [-1e5, 1e5], [-1e5, 1e5]),
+ new FloatCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, fullRange16F, fullRange16F),
+ new FloatCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, fullRange16F, fullRange16F),
+ new FloatCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, [-1e2, 1e2], [-1e2, 1e2]),
+ new FloatCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, [-1e2, 1e2], [-1e2, 1e2])
+ ];
+
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {string} op
+ * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
+ * @param {gluShaderUtil.precision} precision
+ * @param {number} bits
+ * @param {Array<number>} rangeA
+ * @param {Array<number>} rangeB
+ */
+ var IntCase = function(name, op, evalFunc, precision, bits, rangeA, rangeB) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.op = op;
+ /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc;
+ /** @type {gluShaderUtil.precision} */ this.precision = precision;
+ /** @type {number} */ this.bits = bits;
+ /** @type {Array<number>} */ this.rangeA = rangeA;
+ /** @type {Array<number>} */ this.rangeB = rangeB;
+ };
+
+ /** @type {Array<IntCase>} */ var intCases = [
+ new IntCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I),
+ new IntCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I),
+ new IntCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul32, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I),
+ new IntCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, [-10000, -1]),
+ new IntCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I),
+ new IntCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I),
+ new IntCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I),
+ new IntCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, [1, 1000]),
+ new IntCase('lowp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I),
+ new IntCase('lowp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I),
+ new IntCase('lowp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I),
+ new IntCase('lowp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, [-50, -1])
+ ];
+
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {string} op
+ * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
+ * @param {gluShaderUtil.precision} precision
+ * @param {number} bits
+ * @param {Array<number>} rangeA
+ * @param {Array<number>} rangeB
+ */
+ var UintCase = function(name, op, evalFunc, precision, bits, rangeA, rangeB) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.op = op;
+ /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc;
+ /** @type {gluShaderUtil.precision} */ this.precision = precision;
+ /** @type {number} */ this.bits = bits;
+ /** @type {Array<number>} */ this.rangeA = rangeA;
+ /** @type {Array<number>} */ this.rangeB = rangeB;
+ };
+
+ /** @type {Array<UintCase>} */ var uintCases = [
+ new UintCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U),
+ new UintCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U),
+ new UintCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul32, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U),
+ new UintCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, [1, 10000]),
+ new UintCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U),
+ new UintCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U),
+ new UintCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U),
+ new UintCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, [1, 1000]),
+ new UintCase('lowp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U),
+ new UintCase('lowp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U),
+ new UintCase('lowp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U),
+ new UintCase('lowp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, [1, 50])
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var floatGroup = tcuTestCase.newTest('float', 'Floating-point precision tests');
+ testGroup.addChild(floatGroup);
+ for (var ndx = 0; ndx < floatCases.length; ndx++) {
+ floatGroup.addChild(new es3fShaderPrecisionTests.ShaderFloatPrecisionCase(
+ floatCases[ndx].name + '_vertex', '', floatCases[ndx].op, floatCases[ndx].evalFunc,
+ floatCases[ndx].precision, floatCases[ndx].rangeA, floatCases[ndx].rangeB, true));
+ floatGroup.addChild(new es3fShaderPrecisionTests.ShaderFloatPrecisionCase(
+ floatCases[ndx].name + '_fragment', '', floatCases[ndx].op, floatCases[ndx].evalFunc,
+ floatCases[ndx].precision, floatCases[ndx].rangeA, floatCases[ndx].rangeB, false));
+ }
+
+ /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('int', 'Integer precision tests');
+ testGroup.addChild(intGroup);
+ for (var ndx = 0; ndx < intCases.length; ndx++) {
+ intGroup.addChild(new es3fShaderPrecisionTests.ShaderIntPrecisionCase(
+ intCases[ndx].name + '_vertex', '', intCases[ndx].op, intCases[ndx].evalFunc,
+ intCases[ndx].precision, intCases[ndx].bits, intCases[ndx].rangeA, intCases[ndx].rangeB, true));
+ intGroup.addChild(new es3fShaderPrecisionTests.ShaderIntPrecisionCase(
+ intCases[ndx].name + '_fragment', '', intCases[ndx].op, intCases[ndx].evalFunc,
+ intCases[ndx].precision, intCases[ndx].bits, intCases[ndx].rangeA, intCases[ndx].rangeB, false));
+ }
+
+ /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('uint', 'Unsigned integer precision tests');
+ testGroup.addChild(uintGroup);
+ for (var ndx = 0; ndx < uintCases.length; ndx++) {
+ uintGroup.addChild(new es3fShaderPrecisionTests.ShaderUintPrecisionCase(
+ uintCases[ndx].name + '_vertex', '', uintCases[ndx].op, uintCases[ndx].evalFunc,
+ uintCases[ndx].precision, uintCases[ndx].bits, uintCases[ndx].rangeA, uintCases[ndx].rangeB, true));
+ uintGroup.addChild(new es3fShaderPrecisionTests.ShaderUintPrecisionCase(
+ uintCases[ndx].name + '_fragment', '', uintCases[ndx].op, uintCases[ndx].evalFunc,
+ uintCases[ndx].precision, uintCases[ndx].bits, uintCases[ndx].rangeA, uintCases[ndx].rangeB, false));
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderPrecisionTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderPrecisionTests.ShaderPrecisionTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderPrecisionTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStateQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStateQueryTests.js
new file mode 100644
index 0000000000..1a2859f249
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStateQueryTests.js
@@ -0,0 +1,2205 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderStateQueryTests');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fShaderStateQueryTests = functional.gles3.es3fShaderStateQueryTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuMatrix = framework.common.tcuMatrix;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+var commonTestVertSource = '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+var commonTestFragSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+var brokenShader = '#version 300 es\n' +
+ 'broken, this should not compile!\n' +
+ '\n';
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ShaderTypeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ShaderTypeCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ShaderTypeCase.prototype.test = function() {
+ var shaderTypes = [gl.VERTEX_SHADER, gl.FRAGMENT_SHADER];
+ for (var ndx = 0; ndx < shaderTypes.length; ++ndx) {
+ var shader = gl.createShader(shaderTypes[ndx]);
+ var result = glsStateQuery.verifyShader(shader, gl.SHADER_TYPE, shaderTypes[ndx]);
+ this.check(result, 'Incorrect shader type');
+ gl.deleteShader(shader);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ShaderCompileStatusCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ShaderCompileStatusCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ShaderCompileStatusCase.prototype.test = function() {
+ var result;
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ result = glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, false);
+ this.check(result, 'Vertex shader compilation status should be false');
+ result = glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, false);
+ this.check(result, 'Fragment shader compilation status should be false');
+
+ gl.shaderSource(shaderVert, commonTestVertSource);
+ gl.shaderSource(shaderFrag, commonTestFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ result = glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true);
+ this.check(result, 'Vertex shader compilation status should be true');
+ result = glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, true);
+ this.check(result, 'Fragment shader compilation status should be true');
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ShaderInfoLogCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ShaderInfoLogCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ShaderInfoLogCase.prototype.test = function() {
+ var shader = gl.createShader(gl.VERTEX_SHADER);
+ var log = gl.getShaderInfoLog(shader);
+ this.check(log === '');
+
+ gl.shaderSource(shader, brokenShader);
+ gl.compileShader(shader);
+
+ log = gl.getShaderInfoLog(shader);
+ this.check(log === null || typeof log === 'string');
+
+ gl.deleteShader(shader);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ShaderSourceCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ShaderSourceCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ShaderSourceCase.prototype.test = function() {
+ var shader = gl.createShader(gl.VERTEX_SHADER);
+ this.check(gl.getShaderSource(shader) === '');
+
+ gl.shaderSource(shader, brokenShader);
+ this.check(gl.getShaderSource(shader) === brokenShader);
+
+ gl.deleteShader(shader);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.DeleteStatusCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.DeleteStatusCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.DeleteStatusCase.prototype.test = function() {
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, commonTestVertSource);
+ gl.shaderSource(shaderFrag, commonTestFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, true));
+
+ var shaderProg = gl.createProgram();
+ gl.attachShader(shaderProg, shaderVert);
+ gl.attachShader(shaderProg, shaderFrag);
+ gl.linkProgram(shaderProg);
+
+ this.check(glsStateQuery.verifyProgram(shaderProg, gl.LINK_STATUS, true));
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.DELETE_STATUS, false));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.DELETE_STATUS, false));
+ this.check(glsStateQuery.verifyProgram(shaderProg, gl.DELETE_STATUS, false));
+
+ gl.useProgram(shaderProg);
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(shaderProg);
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.DELETE_STATUS, true));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.DELETE_STATUS, true));
+ this.check(glsStateQuery.verifyProgram(shaderProg, gl.DELETE_STATUS, true));
+
+ gl.useProgram(null);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.CurrentVertexAttribInitialCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.CurrentVertexAttribInitialCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.CurrentVertexAttribInitialCase.prototype.test = function() {
+ var attribute_count = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ var initial = new Float32Array([0, 0, 0, 1]);
+ // initial
+
+ for (var index = 0; index < attribute_count; ++index) {
+ var attrib = gl.getVertexAttrib(index, gl.CURRENT_VERTEX_ATTRIB);
+ this.check(glsStateQuery.compare(attrib, initial), 'Initial attrib value should be [0, 0, 0, 1]');
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.CurrentVertexAttribFloatCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.CurrentVertexAttribFloatCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.CurrentVertexAttribFloatCase.prototype.test = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ var attribute_count = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+
+ // test write float/read float
+
+ for (var index = 0; index < attribute_count; ++index) {
+ var x = rnd.getFloat(-64000, 64000);
+ var y = rnd.getFloat(-64000, 64000);
+ var z = rnd.getFloat(-64000, 64000);
+ var w = rnd.getFloat(-64000, 64000);
+
+ gl.vertexAttrib4f(index, x, y, z, w);
+ this.check(glsStateQuery.verifyCurrentVertexAttrib(index, new Float32Array([x, y, z, w])));
+ }
+ for (var index = 0; index < attribute_count; ++index) {
+ var x = rnd.getFloat(-64000, 64000);
+ var y = rnd.getFloat(-64000, 64000);
+ var z = rnd.getFloat(-64000, 64000);
+ var w = 1.0;
+
+ gl.vertexAttrib3f(index, x, y, z);
+ this.check(glsStateQuery.verifyCurrentVertexAttrib(index, new Float32Array([x, y, z, w])));
+ }
+ for (var index = 0; index < attribute_count; ++index) {
+ var x = rnd.getFloat(-64000, 64000);
+ var y = rnd.getFloat(-64000, 64000);
+ var z = 0.0;
+ var w = 1.0;
+
+ gl.vertexAttrib2f(index, x, y);
+ this.check(glsStateQuery.verifyCurrentVertexAttrib(index, new Float32Array([x, y, z, w])));
+ }
+ for (var index = 0; index < attribute_count; ++index) {
+ var x = rnd.getFloat(-64000, 64000);
+ var y = 0.0;
+ var z = 0.0;
+ var w = 1.0;
+
+ gl.vertexAttrib1f(index, x);
+ this.check(glsStateQuery.verifyCurrentVertexAttrib(index, new Float32Array([x, y, z, w])));
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.CurrentVertexAttribIntCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.CurrentVertexAttribIntCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.CurrentVertexAttribIntCase.prototype.test = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ var attribute_count = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+
+ // test write float/read float
+
+ for (var index = 0; index < attribute_count; ++index) {
+ var x = rnd.getInt(-64000, 64000);
+ var y = rnd.getInt(-64000, 64000);
+ var z = rnd.getInt(-64000, 64000);
+ var w = rnd.getInt(-64000, 64000);
+
+ gl.vertexAttribI4i(index, x, y, z, w);
+ this.check(glsStateQuery.verifyCurrentVertexAttrib(index, new Int32Array([x, y, z, w])));
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.CurrentVertexAttribUintCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.CurrentVertexAttribUintCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.CurrentVertexAttribUintCase.prototype.test = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ var attribute_count = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+
+ // test write float/read float
+
+ for (var index = 0; index < attribute_count; ++index) {
+ var x = rnd.getInt(0, 64000);
+ var y = rnd.getInt(0, 64000);
+ var z = rnd.getInt(0, 64000);
+ var w = rnd.getInt(0, 64000);
+
+ gl.vertexAttribI4ui(index, x, y, z, w);
+ this.check(glsStateQuery.verifyCurrentVertexAttrib(index, new Uint32Array([x, y, z, w])));
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ProgramInfoLogCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ProgramInfoLogCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ProgramInfoLogCase.prototype.test = function() {
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, brokenShader);
+ gl.compileShader(shaderVert);
+ gl.shaderSource(shaderFrag, brokenShader);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+
+ var log = gl.getProgramInfoLog(program);
+ this.check(log === null || typeof log === 'string');
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ProgramValidateStatusCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ProgramValidateStatusCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ProgramValidateStatusCase.prototype.test = function() {
+ // test validate ok
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, commonTestVertSource);
+ gl.shaderSource(shaderFrag, commonTestFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyProgram(program, gl.LINK_STATUS, true));
+
+ gl.validateProgram(program);
+ this.check(glsStateQuery.verifyProgram(program, gl.VALIDATE_STATUS, true));
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+
+ // test with broken shader
+ shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, commonTestVertSource);
+ gl.shaderSource(shaderFrag, brokenShader);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, false));
+ this.check(glsStateQuery.verifyProgram(program, gl.LINK_STATUS, false));
+
+ gl.validateProgram(program);
+ this.check(glsStateQuery.verifyProgram(program, gl.VALIDATE_STATUS, false));
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ProgramAttachedShadersCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ProgramAttachedShadersCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ProgramAttachedShadersCase.prototype.test = function() {
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, commonTestVertSource);
+ gl.shaderSource(shaderFrag, commonTestFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ // check ATTACHED_SHADERS
+
+ var program = gl.createProgram();
+ this.check(glsStateQuery.verifyProgram(program, gl.ATTACHED_SHADERS, 0));
+
+ gl.attachShader(program, shaderVert);
+ this.check(glsStateQuery.verifyProgram(program, gl.ATTACHED_SHADERS, 1));
+
+ gl.attachShader(program, shaderFrag);
+ this.check(glsStateQuery.verifyProgram(program, gl.ATTACHED_SHADERS, 2));
+
+ // check GetAttachedShaders
+ var shaders = gl.getAttachedShaders(program);
+ this.check(glsStateQuery.compare(shaders, [shaderVert, shaderFrag]));
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ProgramActiveUniformNameCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ProgramActiveUniformNameCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ProgramActiveUniformNameCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform highp float uniformNameWithLength23;\n' +
+ 'uniform highp vec2 uniformVec2;\n' +
+ 'uniform highp mat4 uniformMat4;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+
+ this.check(glsStateQuery.verifyProgram(program, gl.ACTIVE_UNIFORMS, 3));
+
+ var uniformNames = [
+ 'uniformNameWithLength23',
+ 'uniformVec2',
+ 'uniformMat4'
+ ];
+
+ var indices = gl.getUniformIndices(program, uniformNames);
+
+ // check names
+ for (var ndx = 0; ndx < uniformNames.length; ++ndx) {
+ var index = indices[ndx];
+ var uniform = gl.getActiveUniform(program, index);
+
+ this.check(glsStateQuery.compare(uniform.name, uniformNames[ndx]));
+ }
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ProgramUniformCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ProgramUniformCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ProgramUniformCase.prototype.test = function() {
+ var uniformTypes = [
+ ['float', '', 'highp', '', 'uniformValue', gl.FLOAT, 1, false],
+ ['float[2]', '', 'highp', '', 'uniformValue[1]', gl.FLOAT, 2, false],
+ ['vec2', '', 'highp', '', 'uniformValue.x', gl.FLOAT_VEC2, 1, false],
+ ['vec3', '', 'highp', '', 'uniformValue.x', gl.FLOAT_VEC3, 1, false],
+ ['vec4', '', 'highp', '', 'uniformValue.x', gl.FLOAT_VEC4, 1, false],
+ ['int', '', 'highp', '', 'float(uniformValue)', gl.INT, 1, false],
+ ['ivec2', '', 'highp', '', 'float(uniformValue.x)', gl.INT_VEC2, 1, false],
+ ['ivec3', '', 'highp', '', 'float(uniformValue.x)', gl.INT_VEC3, 1, false],
+ ['ivec4', '', 'highp', '', 'float(uniformValue.x)', gl.INT_VEC4, 1, false],
+ ['uint', '', 'highp', '', 'float(uniformValue)', gl.UNSIGNED_INT, 1, false],
+ ['uvec2', '', 'highp', '', 'float(uniformValue.x)', gl.UNSIGNED_INT_VEC2, 1, false],
+ ['uvec3', '', 'highp', '', 'float(uniformValue.x)', gl.UNSIGNED_INT_VEC3, 1, false],
+ ['uvec4', '', 'highp', '', 'float(uniformValue.x)', gl.UNSIGNED_INT_VEC4, 1, false],
+ ['bool', '', '', '', 'float(uniformValue)', gl.BOOL, 1, false],
+ ['bvec2', '', '', '', 'float(uniformValue.x)', gl.BOOL_VEC2, 1, false],
+ ['bvec3', '', '', '', 'float(uniformValue.x)', gl.BOOL_VEC3, 1, false],
+ ['bvec4', '', '', '', 'float(uniformValue.x)', gl.BOOL_VEC4, 1, false],
+ ['mat2', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT2, 1, false],
+ ['mat3', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT3, 1, false],
+ ['mat4', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT4, 1, false],
+ ['mat2x3', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT2x3, 1, false],
+ ['mat2x4', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT2x4, 1, false],
+ ['mat3x2', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT3x2, 1, false],
+ ['mat3x4', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT3x4, 1, false],
+ ['mat4x2', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT4x2, 1, false],
+ ['mat4x3', '', 'highp', '', 'float(uniformValue[0][0])', gl.FLOAT_MAT4x3, 1, false],
+ ['sampler2D', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_2D, 1, false],
+ ['sampler3D', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_3D, 1, false],
+ ['samplerCube', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_CUBE, 1, false],
+ ['sampler2DShadow', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_2D_SHADOW, 1, false],
+ ['sampler2DArray', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_2D_ARRAY, 1, false],
+ ['sampler2DArrayShadow', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_2D_ARRAY_SHADOW, 1, false],
+ ['samplerCubeShadow', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.SAMPLER_CUBE_SHADOW, 1, false],
+ ['isampler2D', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.INT_SAMPLER_2D, 1, false],
+ ['isampler3D', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.INT_SAMPLER_3D, 1, false],
+ ['isamplerCube', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.INT_SAMPLER_CUBE, 1, false],
+ ['isampler2DArray', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.INT_SAMPLER_2D_ARRAY, 1, false],
+ ['usampler2D', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.UNSIGNED_INT_SAMPLER_2D, 1, false],
+ ['usampler3D', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.UNSIGNED_INT_SAMPLER_3D, 1, false],
+ ['usamplerCube', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.UNSIGNED_INT_SAMPLER_CUBE, 1, false],
+ ['usampler2DArray', '', 'highp', '', 'float(textureSize(uniformValue,0).r)', gl.UNSIGNED_INT_SAMPLER_2D_ARRAY, 1, false]
+ ];
+
+ var vertSource =
+ '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+ var program = gl.createProgram();
+
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+
+ gl.shaderSource(shaderVert, vertSource);
+ gl.compileShader(shaderVert);
+
+ for (var ndx = 0; ndx < uniformTypes.length; ++ndx) {
+ var declaration = uniformTypes[ndx][0];
+ var postDeclaration = uniformTypes[ndx][1];
+ var precision = uniformTypes[ndx][2];
+ var layout = uniformTypes[ndx][3];
+ var getter = uniformTypes[ndx][4];
+ var type = uniformTypes[ndx][5];
+ var size = uniformTypes[ndx][6];
+ var isRowMajor = uniformTypes[ndx][7];
+ bufferedLogToConsole('Verify type of ' + declaration + ' variable' + postDeclaration);
+
+ // gen fragment shader
+
+ var frag = '';
+ frag += '#version 300 es\n';
+ frag += layout + 'uniform ' + precision + ' ' + declaration + ' uniformValue' + postDeclaration + ';\n';
+ frag += 'layout(location = 0) out mediump vec4 fragColor;\n';
+ frag += 'void main (void)\n';
+ frag += '{\n';
+ frag += ' fragColor = vec4(' + getter + ');\n';
+ frag += '}\n';
+
+ gl.shaderSource(shaderFrag, frag);
+
+ // compile & link
+
+ gl.compileShader(shaderFrag);
+ gl.linkProgram(program);
+
+ // test
+ if (this.check(glsStateQuery.verifyProgram(program, gl.LINK_STATUS, true), 'Program link fail' + gl.getProgramInfoLog(program))) {
+ var indices = gl.getUniformIndices(program, ['uniformValue']);
+ var info_type = gl.getActiveUniforms(program, indices, gl.UNIFORM_TYPE)[0];
+ var info_size = gl.getActiveUniforms(program, indices, gl.UNIFORM_SIZE)[0];
+ var info_is_row_major = gl.getActiveUniforms(program, indices, gl.UNIFORM_IS_ROW_MAJOR)[0];
+ this.check(glsStateQuery.compare(info_size, size));
+ this.check(glsStateQuery.compare(info_type, type));
+ this.check(glsStateQuery.compare(info_is_row_major, isRowMajor));
+ }
+ }
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ProgramActiveUniformBlocksCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ProgramActiveUniformBlocksCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ProgramActiveUniformBlocksCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n' +
+ 'uniform shortUniformBlockName {highp vec2 vector2;highp vec4 vector4;} shortUniformInstanceName;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = shortUniformInstanceName.vector4 + vec4(longlongUniformInstanceName.vector2.x) + vec4(shortUniformInstanceName.vector2.x);\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(longlongUniformInstanceName.vector2.y);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyProgram(program, gl.LINK_STATUS, true));
+
+ this.check(glsStateQuery.verifyProgram(program, gl.ACTIVE_UNIFORM_BLOCKS, 2));
+
+ var longlongUniformBlockIndex = gl.getUniformBlockIndex(program, 'longlongUniformBlockName');
+ var shortUniformBlockIndex = gl.getUniformBlockIndex(program, 'shortUniformBlockName');
+
+ var uniformNames = [
+ 'longlongUniformBlockName.vector2',
+ 'shortUniformBlockName.vector2',
+ 'shortUniformBlockName.vector4'
+ ];
+
+ // test UNIFORM_BLOCK_INDEX
+
+ var uniformIndices = gl.getUniformIndices(program, uniformNames);
+
+ var uniformsBlockIndices = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_BLOCK_INDEX);
+ this.check(uniformsBlockIndices[0] == longlongUniformBlockIndex &&
+ uniformsBlockIndices[1] == shortUniformBlockIndex &&
+ uniformsBlockIndices[2] == shortUniformBlockIndex,
+ 'Expected [' + longlongUniformBlockIndex + ", " + shortUniformBlockIndex + ", " + shortUniformBlockIndex + ']; got ' +
+ uniformsBlockIndices[0] + ", " + uniformsBlockIndices[1] + ", " + uniformsBlockIndices[2] + "]");
+
+ // test UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER & UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
+
+ this.check(glsStateQuery.verifyActiveUniformBlock(program, longlongUniformBlockIndex, gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, true));
+ this.check(glsStateQuery.verifyActiveUniformBlock(program, longlongUniformBlockIndex, gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, true));
+ this.check(glsStateQuery.verifyActiveUniformBlock(program, shortUniformBlockIndex, gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, true));
+ this.check(glsStateQuery.verifyActiveUniformBlock(program, shortUniformBlockIndex, gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, false));
+
+ // test UNIFORM_BLOCK_ACTIVE_UNIFORMS
+
+ this.check(glsStateQuery.verifyActiveUniformBlock(program, longlongUniformBlockIndex, gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS, 1));
+ this.check(glsStateQuery.verifyActiveUniformBlock(program, shortUniformBlockIndex, gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS, 2));
+
+ // test UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
+
+ var shortUniformBlockIndices = gl.getActiveUniformBlockParameter(program, shortUniformBlockIndex, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
+ this.check(shortUniformBlockIndices.length == 2, 'Expected 2 indices; got ' + shortUniformBlockIndices.length);
+
+ this.check(glsStateQuery.compare(shortUniformBlockIndices, new Uint32Array([uniformIndices[1], uniformIndices[2]])) ||
+ glsStateQuery.compare(shortUniformBlockIndices, new Uint32Array([uniformIndices[2], uniformIndices[1]])),
+ 'Expected { ' + uniformIndices[1] +', ' + uniformIndices[2] +
+ '}; got {' + shortUniformBlockIndices[0] + ', ' + shortUniformBlockIndices[1] + '}');
+
+ // check block names
+
+ var name = gl.getActiveUniformBlockName(program, longlongUniformBlockIndex);
+ this.check(name == "longlongUniformBlockName", 'Wrong uniform block name, expected longlongUniformBlockName; got ' + name);
+ name = gl.getActiveUniformBlockName(program, shortUniformBlockIndex)
+ this.check(name == "shortUniformBlockName", 'Wrong uniform block name, expected shortUniformBlockName; got ' + name);
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.TransformFeedbackCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.TransformFeedbackCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.TransformFeedbackCase.prototype.test = function() {
+ var transformFeedbackTestVertSource =
+ '#version 300 es\n' +
+ 'out highp vec4 tfOutput2withLongName;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ ' tfOutput2withLongName = vec4(0.0);\n' +
+ '}\n';
+ var transformFeedbackTestFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out highp vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+ var shaderProg = gl.createProgram();
+
+ this.check(glsStateQuery.verifyProgram(shaderProg, gl.TRANSFORM_FEEDBACK_BUFFER_MODE, gl.INTERLEAVED_ATTRIBS));
+
+ gl.shaderSource(shaderVert, transformFeedbackTestVertSource);
+ gl.shaderSource(shaderFrag, transformFeedbackTestFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ this.check(glsStateQuery.verifyShader(shaderVert, gl.COMPILE_STATUS, true));
+ this.check(glsStateQuery.verifyShader(shaderFrag, gl.COMPILE_STATUS, true));
+
+ gl.attachShader(shaderProg, shaderVert);
+ gl.attachShader(shaderProg, shaderFrag);
+
+ // check TRANSFORM_FEEDBACK_BUFFER_MODE
+
+ var transform_feedback_outputs = ['gl_Position', 'tfOutput2withLongName'];
+ var bufferModes = [gl.SEPARATE_ATTRIBS, gl.INTERLEAVED_ATTRIBS];
+
+ for (var ndx = 0; ndx < bufferModes.length; ++ndx) {
+ gl.transformFeedbackVaryings(shaderProg, transform_feedback_outputs, bufferModes[ndx]);
+ gl.linkProgram(shaderProg);
+
+ this.check(glsStateQuery.verifyProgram(shaderProg, gl.LINK_STATUS, true));
+ this.check(glsStateQuery.verifyProgram(shaderProg, gl.TRANSFORM_FEEDBACK_BUFFER_MODE, bufferModes[ndx]));
+ }
+
+ // check varyings
+ var varyings = /** @type {number} */ (gl.getProgramParameter(shaderProg, gl.TRANSFORM_FEEDBACK_VARYINGS));
+ this.check(varyings === 2);
+
+ for (var index = 0; index < varyings; ++index) {
+ var info = gl.getTransformFeedbackVarying(shaderProg, index);
+ this.check(glsStateQuery.compare(info.type, gl.FLOAT_VEC4));
+ this.check(glsStateQuery.compare(info.size, 1));
+ this.check(glsStateQuery.compare(info.name, transform_feedback_outputs[index]));
+ }
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(shaderProg);
+
+ // TODO(kbr): this test is failing and leaving an error in the GL
+ // state, causing later tests to fail. Clear the error state for
+ // the time being.
+ while (gl.getError() != gl.NO_ERROR) {}
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.ActiveAttributesCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.ActiveAttributesCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.ActiveAttributesCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'in highp vec2 longInputAttributeName;\n' +
+ 'in highp vec2 shortName;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+
+ this.check(glsStateQuery.verifyProgram(program, gl.ACTIVE_ATTRIBUTES, 2));
+
+ var attribNames = [
+ 'longInputAttributeName',
+ 'shortName'
+ ];
+ // check names
+ for (var attributeNdx = 0; attributeNdx < 2; ++attributeNdx) {
+ var info = gl.getActiveAttrib(program, attributeNdx);
+ this.check(glsStateQuery.compare(info.name, attribNames[0]) || glsStateQuery.compare(info.name, attribNames[1]));
+ }
+
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeSizeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeSizeCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeSizeCase.prototype.test = function() {
+ var pointers = [
+ // size test
+ [4, gl.FLOAT, 0, false, 0],
+ [3, gl.FLOAT, 0, false, 0],
+ [2, gl.FLOAT, 0, false, 0],
+ [1, gl.FLOAT, 0, false, 0],
+ [4, gl.INT, 0, false, 0],
+ [3, gl.INT, 0, false, 0],
+ [2, gl.INT, 0, false, 0],
+ [1, gl.INT, 0, false, 0]
+ ];
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ // Test with default VAO
+
+ for (var ndx = 0; ndx < pointers.length; ++ndx) {
+ gl.vertexAttribPointer(0, pointers[ndx][0], pointers[ndx][1], pointers[ndx][3], pointers[ndx][2], pointers[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx][0]));
+ }
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE, 4));
+
+ // set vao 0 to some value
+ gl.vertexAttribPointer(0, pointers[0][0], pointers[0][1], pointers[0][3], pointers[0][2], 0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribPointer(0, pointers[1][0], pointers[1][1], pointers[1][3], pointers[1][2], 0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE, pointers[1][0]));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE, pointers[0][0]));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buf);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeTypeCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeTypeCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeTypeCase.prototype.test = function() {
+ var pointers = [
+ // type test
+ [1, gl.BYTE, 0, false, 0],
+ [1, gl.SHORT, 0, false, 0],
+ [1, gl.INT, 0, false, 0],
+ [1, gl.FLOAT, 0, false, 0],
+ [1, gl.HALF_FLOAT, 0, false, 0],
+ [1, gl.UNSIGNED_BYTE, 0, false, 0],
+ [1, gl.UNSIGNED_SHORT, 0, false, 0],
+ [1, gl.UNSIGNED_INT, 0, false, 0],
+ [4, gl.INT_2_10_10_10_REV, 0, false, 0],
+ [4, gl.UNSIGNED_INT_2_10_10_10_REV, 0, false, 0]
+ ];
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ // Test with default VAO
+
+ for (var ndx = 0; ndx < pointers.length; ++ndx) {
+ gl.vertexAttribPointer(0, pointers[ndx][0], pointers[ndx][1], pointers[ndx][3], pointers[ndx][2], pointers[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx][1]));
+ }
+
+ var pointersI = [
+ [1, gl.BYTE, 0, false, 0],
+ [1, gl.SHORT, 0, false, 0],
+ [1, gl.INT, 0, false, 0],
+ [1, gl.UNSIGNED_BYTE, 0, false, 0],
+ [1, gl.UNSIGNED_SHORT, 0, false, 0],
+ [1, gl.UNSIGNED_INT, 0, false, 0]
+ ];
+
+ for (var ndx = 0; ndx < pointersI.length; ++ndx) {
+ gl.vertexAttribIPointer(0, pointersI[ndx][0], pointersI[ndx][1], pointersI[ndx][2], pointersI[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE, pointersI[ndx][1]));
+ }
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE, gl.FLOAT));
+
+ // set vao 0 to some value
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribPointer(0, 1, gl.SHORT, false, 0, 0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE, gl.SHORT));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE, gl.FLOAT));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buf);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeStrideCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeStrideCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeStrideCase.prototype.test = function() {
+ var pointers = [
+ [1, gl.FLOAT, 0, 0, gl.NO_ERROR],
+ [1, gl.FLOAT, 1, 0, gl.INVALID_OPERATION],
+ [1, gl.FLOAT, 4, 0, gl.NO_ERROR],
+ [1, gl.HALF_FLOAT, 0, 0, gl.NO_ERROR],
+ [1, gl.HALF_FLOAT, 1, 0, gl.INVALID_OPERATION],
+ [1, gl.HALF_FLOAT, 4, 0, gl.NO_ERROR]
+ ];
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ // Test with default VAO
+
+ for (var ndx = 0; ndx < pointers.length; ++ndx) {
+ gl.vertexAttribPointer(0, pointers[ndx][0], pointers[ndx][1], false, pointers[ndx][2], pointers[ndx][3]);
+ this.expectError(pointers[ndx][4]);
+ if (pointers[ndx][4] == gl.NO_ERROR) {
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx][2]));
+ }
+ }
+
+ var pointersI = [
+ [1, gl.INT, 0, 0, gl.NO_ERROR],
+ [1, gl.INT, 1, 0, gl.INVALID_OPERATION],
+ [1, gl.INT, 4, 0, gl.NO_ERROR],
+ [4, gl.UNSIGNED_BYTE, 0, 0, gl.NO_ERROR],
+ [4, gl.UNSIGNED_BYTE, 1, 0, gl.NO_ERROR],
+ [4, gl.UNSIGNED_BYTE, 4, 0, gl.NO_ERROR],
+ [2, gl.SHORT, 0, 0, gl.NO_ERROR],
+ [2, gl.SHORT, 1, 0, gl.INVALID_OPERATION],
+ [2, gl.SHORT, 4, 0, gl.NO_ERROR]
+ ];
+
+ for (var ndx = 0; ndx < pointersI.length; ++ndx) {
+ gl.vertexAttribIPointer(0, pointersI[ndx][0], pointersI[ndx][1], pointersI[ndx][2], pointersI[ndx][3]);
+ this.expectError(pointersI[ndx][4]);
+ if (pointersI[ndx][4] == gl.NO_ERROR) {
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE, pointersI[ndx][2]));
+ }
+ }
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE, 0));
+
+ // set vao 0 to some value
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 4, 0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribPointer(0, 1, gl.SHORT, false, 8, 0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE, 8));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE, 4));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buf);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeNormalizedCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeNormalizedCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeNormalizedCase.prototype.test = function() {
+ var pointers = [
+ // type test
+ [1, gl.BYTE, 0, false, 0],
+ [1, gl.SHORT, 0, false, 0],
+ [1, gl.INT, 0, false, 0],
+ [1, gl.FLOAT, 0, false, 0],
+ [1, gl.HALF_FLOAT, 0, false, 0],
+ [1, gl.UNSIGNED_BYTE, 0, false, 0],
+ [1, gl.UNSIGNED_SHORT, 0, false, 0],
+ [1, gl.UNSIGNED_INT, 0, false, 0],
+ [4, gl.INT_2_10_10_10_REV, 0, false, 0],
+ [4, gl.UNSIGNED_INT_2_10_10_10_REV, 0, false, 0],
+ [1, gl.BYTE, 0, true, 0],
+ [1, gl.SHORT, 0, true, 0],
+ [1, gl.INT, 0, true, 0],
+ [1, gl.FLOAT, 0, true, 0],
+ [1, gl.HALF_FLOAT, 0, true, 0],
+ [1, gl.UNSIGNED_BYTE, 0, true, 0],
+ [1, gl.UNSIGNED_SHORT, 0, true, 0],
+ [1, gl.UNSIGNED_INT, 0, true, 0],
+ [4, gl.INT_2_10_10_10_REV, 0, true, 0],
+ [4, gl.UNSIGNED_INT_2_10_10_10_REV, 0, true, 0]
+ ];
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ // Test with default VAO
+
+ for (var ndx = 0; ndx < pointers.length; ++ndx) {
+ gl.vertexAttribPointer(0, pointers[ndx][0], pointers[ndx][1], pointers[ndx][3], pointers[ndx][2], pointers[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx][3]));
+ }
+
+ var pointersI = [
+ [1, gl.BYTE, 0, false, 0],
+ [1, gl.SHORT, 0, false, 0],
+ [1, gl.INT, 0, false, 0],
+ [1, gl.UNSIGNED_BYTE, 0, false, 0],
+ [1, gl.UNSIGNED_SHORT, 0, false, 0],
+ [1, gl.UNSIGNED_INT, 0, false, 0]
+ ];
+
+ for (var ndx = 0; ndx < pointersI.length; ++ndx) {
+ gl.vertexAttribIPointer(0, pointersI[ndx][0], pointersI[ndx][1], pointersI[ndx][2], pointersI[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, false));
+ }
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, false));
+
+ // set vao 0 to some value
+ gl.vertexAttribPointer(0, 1, gl.INT, true, 0, 0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribPointer(0, 1, gl.INT, false, 0, 0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, false));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, true));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buf);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeIntegerCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeIntegerCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeIntegerCase.prototype.test = function() {
+ var pointers = [
+ // type test
+ [1, gl.BYTE, 0, false, 0],
+ [1, gl.SHORT, 0, false, 0],
+ [1, gl.INT, 0, false, 0],
+ [1, gl.FLOAT, 0, false, 0],
+ [1, gl.HALF_FLOAT, 0, false, 0],
+ [1, gl.UNSIGNED_BYTE, 0, false, 0],
+ [1, gl.UNSIGNED_SHORT, 0, false, 0],
+ [1, gl.UNSIGNED_INT, 0, false, 0],
+ [4, gl.INT_2_10_10_10_REV, 0, false, 0],
+ [4, gl.UNSIGNED_INT_2_10_10_10_REV, 0, false, 0]
+ ];
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ // Test with default VAO
+
+ for (var ndx = 0; ndx < pointers.length; ++ndx) {
+ gl.vertexAttribPointer(0, pointers[ndx][0], pointers[ndx][1], pointers[ndx][3], pointers[ndx][2], pointers[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_INTEGER, false));
+ }
+
+ var pointersI = [
+ [1, gl.BYTE, 0, false, 0],
+ [1, gl.SHORT, 0, false, 0],
+ [1, gl.INT, 0, false, 0],
+ [1, gl.UNSIGNED_BYTE, 0, false, 0],
+ [1, gl.UNSIGNED_SHORT, 0, false, 0],
+ [1, gl.UNSIGNED_INT, 0, false, 0]
+ ];
+
+ for (var ndx = 0; ndx < pointersI.length; ++ndx) {
+ gl.vertexAttribIPointer(0, pointersI[ndx][0], pointersI[ndx][1], pointersI[ndx][2], pointersI[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_INTEGER, true));
+ }
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_INTEGER, false));
+
+ // set vao 0 to some value
+ gl.vertexAttribIPointer(0, 1, gl.INT, 0, 0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_INTEGER, false));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_INTEGER, true));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buf);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeEnabledCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeEnabledCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeEnabledCase.prototype.test = function() {
+ // Test with default VAO
+
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_ENABLED, false));
+ gl.enableVertexAttribArray(0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_ENABLED, true));
+ gl.disableVertexAttribArray(0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_ENABLED, false));
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ // set vao 0 to some value
+ gl.enableVertexAttribArray(0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.disableVertexAttribArray(0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_ENABLED, false));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_ENABLED, true));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeDivisorCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeDivisorCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeDivisorCase.prototype.test = function() {
+ // Test with default VAO
+
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_DIVISOR, 0));
+ gl.vertexAttribDivisor(0, 1);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_DIVISOR, 1));
+ gl.vertexAttribDivisor(0, 5);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_DIVISOR, 5));
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ // set vao 0 to some value
+ gl.vertexAttribDivisor(0, 1);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribDivisor(0, 5);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_DIVISOR, 5));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_DIVISOR, 1));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeBufferBindingCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeBufferBindingCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeBufferBindingCase.prototype.test = function() {
+ // Test with default VAO
+
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, buffer));
+
+ gl.deleteBuffer(buffer);
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+ var buffer0 = gl.createBuffer();
+ var buffer1 = gl.createBuffer();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ // set vao 0 to some value
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer0);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer1);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, buffer1));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, buffer0));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buffer0);
+ gl.deleteBuffer(buffer1);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.VertexAttributeOffsetCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.VertexAttributeOffsetCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.VertexAttributeOffsetCase.prototype.test = function() {
+ var pointers = [
+ [1, gl.BYTE, 0, false, 2 * 4],
+ [1, gl.SHORT, 0, false, 1 * 4],
+ [1, gl.INT, 0, false, 2 * 4],
+ [1, gl.FLOAT, 0, false, 0 * 4],
+ [1, gl.FLOAT, 0, false, 3 * 4],
+ [1, gl.FLOAT, 0, false, 2 * 4],
+ [1, gl.HALF_FLOAT, 0, false, 0 * 4],
+ [4, gl.HALF_FLOAT, 0, false, 1 * 4],
+ [4, gl.HALF_FLOAT, 0, false, 2 * 4]
+ ];
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+
+ // Test with default VAO
+
+ for (var ndx = 0; ndx < pointers.length; ++ndx) {
+ gl.vertexAttribPointer(0, pointers[ndx][0], pointers[ndx][1], pointers[ndx][3], pointers[ndx][2], pointers[ndx][4]);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_POINTER, pointers[ndx][4]));
+ }
+
+ // Test with multiple VAOs
+ var vao0 = gl.createVertexArray();
+ var vao1 = gl.createVertexArray();
+
+ // initial
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_POINTER, 0));
+
+ // set vao 0 to some value
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 8);
+
+ // set vao 1 to some other value
+ gl.bindVertexArray(vao1);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 4);
+
+ // verify vao 1 state
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_POINTER, 4));
+
+ // verify vao 0 state
+ gl.bindVertexArray(vao0);
+ this.check(glsStateQuery.verifyVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_POINTER, 8));
+
+ gl.deleteVertexArray(vao0);
+ gl.deleteVertexArray(vao1);
+ gl.deleteBuffer(buf);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueFloatCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueFloatCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueFloatCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform highp float floatUniform;\n' +
+ 'uniform highp vec2 float2Uniform;\n' +
+ 'uniform highp vec3 float3Uniform;\n' +
+ 'uniform highp vec4 float4Uniform;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ location = gl.getUniformLocation(program, 'floatUniform');
+ gl.uniform1f(location, 1);
+ this.check(glsStateQuery.verifyUniform(program, location, 1));
+
+ location = gl.getUniformLocation(program, 'float2Uniform');
+ gl.uniform2f(location, 1, 2);
+ this.check(glsStateQuery.verifyUniform(program, location, new Float32Array([1, 2])));
+
+ location = gl.getUniformLocation(program, 'float3Uniform');
+ gl.uniform3f(location, 1, 2, 3);
+ this.check(glsStateQuery.verifyUniform(program, location, new Float32Array([1, 2, 3])));
+
+ location = gl.getUniformLocation(program, 'float4Uniform');
+ gl.uniform4f(location, 1, 2, 3, 4);
+ this.check(glsStateQuery.verifyUniform(program, location, new Float32Array([1, 2, 3, 4])));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueIntCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueIntCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueIntCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform highp int intUniform;\n' +
+ 'uniform highp ivec2 int2Uniform;\n' +
+ 'uniform highp ivec3 int3Uniform;\n' +
+ 'uniform highp ivec4 int4Uniform;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ location = gl.getUniformLocation(program, 'intUniform');
+ gl.uniform1i(location, 1);
+ this.check(glsStateQuery.verifyUniform(program, location, 1));
+
+ location = gl.getUniformLocation(program, 'int2Uniform');
+ gl.uniform2i(location, 1, 2);
+ this.check(glsStateQuery.verifyUniform(program, location, new Int32Array([1, 2])));
+
+ location = gl.getUniformLocation(program, 'int3Uniform');
+ gl.uniform3i(location, 1, 2, 3);
+ this.check(glsStateQuery.verifyUniform(program, location, new Int32Array([1, 2, 3])));
+
+ location = gl.getUniformLocation(program, 'int4Uniform');
+ gl.uniform4i(location, 1, 2, 3, 4);
+ this.check(glsStateQuery.verifyUniform(program, location, new Int32Array([1, 2, 3, 4])));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueUintCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueUintCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueUintCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform highp uint uintUniform;\n' +
+ 'uniform highp uvec2 uint2Uniform;\n' +
+ 'uniform highp uvec3 uint3Uniform;\n' +
+ 'uniform highp uvec4 uint4Uniform;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(float(uintUniform + uint2Uniform.x + uint3Uniform.x + uint4Uniform.x));\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ location = gl.getUniformLocation(program, 'uintUniform');
+ gl.uniform1ui(location, 1);
+ this.check(glsStateQuery.verifyUniform(program, location, 1));
+
+ location = gl.getUniformLocation(program, 'uint2Uniform');
+ gl.uniform2ui(location, 1, 2);
+ this.check(glsStateQuery.verifyUniform(program, location, new Uint32Array([1, 2])));
+
+ location = gl.getUniformLocation(program, 'uint3Uniform');
+ gl.uniform3ui(location, 1, 2, 3);
+ this.check(glsStateQuery.verifyUniform(program, location, new Uint32Array([1, 2, 3])));
+
+ location = gl.getUniformLocation(program, 'uint4Uniform');
+ gl.uniform4ui(location, 1, 2, 3, 4);
+ this.check(glsStateQuery.verifyUniform(program, location, new Uint32Array([1, 2, 3, 4])));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueBooleanCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueBooleanCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueBooleanCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform bool boolUniform;\n' +
+ 'uniform bvec2 bool2Uniform;\n' +
+ 'uniform bvec3 bool3Uniform;\n' +
+ 'uniform bvec4 bool4Uniform;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + float(bool3Uniform.x) + float(bool4Uniform.x));\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ location = gl.getUniformLocation(program, 'boolUniform');
+ gl.uniform1i(location, 1);
+ this.check(glsStateQuery.verifyUniform(program, location, true));
+
+ location = gl.getUniformLocation(program, 'bool2Uniform');
+ gl.uniform2i(location, 1, 0);
+ this.check(glsStateQuery.verifyUniform(program, location, [true, false]));
+
+ location = gl.getUniformLocation(program, 'bool3Uniform');
+ gl.uniform3i(location, 1, 0, 1);
+ this.check(glsStateQuery.verifyUniform(program, location, [true, false, true]));
+
+ location = gl.getUniformLocation(program, 'bool4Uniform');
+ gl.uniform4i(location, 1, 0, 1, 0);
+ this.check(glsStateQuery.verifyUniform(program, location, [true, false, true, false]));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueSamplerCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueSamplerCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueSamplerCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'uniform highp sampler2D uniformSampler;\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(textureSize(uniformSampler, 0).x);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ location = gl.getUniformLocation(program, 'uniformSampler');
+ gl.uniform1i(location, 1);
+ this.check(glsStateQuery.verifyUniform(program, location, 1));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueArrayCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueArrayCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueArrayCase.prototype.test = function() {
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform highp float arrayUniform[5];' +
+ 'uniform highp vec2 array2Uniform[5];' +
+ 'uniform highp vec3 array3Uniform[5];' +
+ 'uniform highp vec4 array4Uniform[5];' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = \n' +
+ ' + vec4(arrayUniform[0] + arrayUniform[1] + arrayUniform[2] + arrayUniform[3] + arrayUniform[4])\n' +
+ ' + vec4(array2Uniform[0].x + array2Uniform[1].x + array2Uniform[2].x + array2Uniform[3].x + array2Uniform[4].x)\n' +
+ ' + vec4(array3Uniform[0].x + array3Uniform[1].x + array3Uniform[2].x + array3Uniform[3].x + array3Uniform[4].x)\n' +
+ ' + vec4(array4Uniform[0].x + array4Uniform[1].x + array4Uniform[2].x + array4Uniform[3].x + array4Uniform[4].x);\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ var uniformValue = [
+ -1.0, 0.1, 4.0, 800.0,
+ 13.0, 55.0, 12.0, 91.0,
+ -55.1, 1.1, 98.0, 19.0,
+ 41.0, 65.0, 4.0, 12.2,
+ 95.0, 77.0, 32.0, 48.0
+ ];
+
+ location = gl.getUniformLocation(program, 'arrayUniform');
+ gl.uniform1fv(location, new Float32Array(uniformValue.slice(0, 5)));
+
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'arrayUniform[0]'), uniformValue[0]));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'arrayUniform[1]'), uniformValue[1]));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'arrayUniform[2]'), uniformValue[2]));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'arrayUniform[3]'), uniformValue[3]));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'arrayUniform[4]'), uniformValue[4]));
+
+ location = gl.getUniformLocation(program, 'array2Uniform');
+ gl.uniform2fv(location, new Float32Array(uniformValue.slice(0, 10)));
+
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array2Uniform[0]'), new Float32Array([uniformValue[2 * 0], uniformValue[(2 * 0) + 1]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array2Uniform[1]'), new Float32Array([uniformValue[2 * 1], uniformValue[(2 * 1) + 1]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array2Uniform[2]'), new Float32Array([uniformValue[2 * 2], uniformValue[(2 * 2) + 1]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array2Uniform[3]'), new Float32Array([uniformValue[2 * 3], uniformValue[(2 * 3) + 1]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array2Uniform[4]'), new Float32Array([uniformValue[2 * 4], uniformValue[(2 * 4) + 1]])));
+
+ location = gl.getUniformLocation(program, 'array3Uniform');
+ gl.uniform3fv(location, new Float32Array(uniformValue.slice(0, 15)));
+
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array3Uniform[0]'), new Float32Array([uniformValue[3 * 0], uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array3Uniform[1]'), new Float32Array([uniformValue[3 * 1], uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array3Uniform[2]'), new Float32Array([uniformValue[3 * 2], uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array3Uniform[3]'), new Float32Array([uniformValue[3 * 3], uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array3Uniform[4]'), new Float32Array([uniformValue[3 * 4], uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]])));
+
+ location = gl.getUniformLocation(program, 'array4Uniform');
+ gl.uniform4fv(location, new Float32Array(uniformValue));
+
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array4Uniform[0]'), new Float32Array([uniformValue[4 * 0], uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array4Uniform[1]'), new Float32Array([uniformValue[4 * 1], uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array4Uniform[2]'), new Float32Array([uniformValue[4 * 2], uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array4Uniform[3]'), new Float32Array([uniformValue[4 * 3], uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]])));
+ this.check(glsStateQuery.verifyUniform(program, gl.getUniformLocation(program, 'array4Uniform[4]'), new Float32Array([uniformValue[4 * 4], uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]])));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ */
+es3fShaderStateQueryTests.UniformValueMatrixCase = function(name, description) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+};
+
+setParentClass(es3fShaderStateQueryTests.UniformValueMatrixCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.UniformValueMatrixCase.prototype.test = function() {
+ var transpose = function(rows, cols, data) {
+ var matrix = tcuMatrix.matrixFromDataArray(rows, cols, data);
+ var result = [];
+ for (var col = 0; col < cols; col++)
+ result.push(matrix.getColumn(col));
+ return new Float32Array([].concat.apply([], result));
+ };
+
+ var testVertSource =
+ '#version 300 es\n' +
+ 'uniform highp mat2 mat2Uniform;' +
+ 'uniform highp mat3 mat3Uniform;' +
+ 'uniform highp mat4 mat4Uniform;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n' +
+ '}\n';
+ var testFragSource =
+ '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = vec4(0.0);\n' +
+ '}\n';
+
+ var shaderVert = gl.createShader(gl.VERTEX_SHADER);
+ var shaderFrag = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(shaderVert, testVertSource);
+ gl.shaderSource(shaderFrag, testFragSource);
+
+ gl.compileShader(shaderVert);
+ gl.compileShader(shaderFrag);
+
+ var program = gl.createProgram();
+ gl.attachShader(program, shaderVert);
+ gl.attachShader(program, shaderFrag);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ var location;
+
+ var matrixValues = [
+ -1.0, 0.1, 4.0, 800.0,
+ 13.0, 55.0, 12.0, 91.0,
+ -55.1, 1.1, 98.0, 19.0,
+ 41.0, 65.0, 4.0, 12.0
+ ];
+
+ // the values of the matrix are returned in column major order but they can be given in either order
+
+ location = gl.getUniformLocation(program, 'mat2Uniform');
+ var m2 = new Float32Array(matrixValues.slice(0, 2 * 2));
+ gl.uniformMatrix2fv(location, false, m2);
+ this.check(glsStateQuery.verifyUniform(program, location, m2));
+ gl.uniformMatrix2fv(location, true, m2);
+ this.check(glsStateQuery.verifyUniform(program, location, transpose(2, 2, m2)));
+
+ location = gl.getUniformLocation(program, 'mat3Uniform');
+ var m3 = new Float32Array(matrixValues.slice(0, 3 * 3));
+ gl.uniformMatrix3fv(location, false, m3);
+ this.check(glsStateQuery.verifyUniform(program, location, m3));
+ gl.uniformMatrix3fv(location, true, m3);
+ this.check(glsStateQuery.verifyUniform(program, location, transpose(3, 3, m3)));
+
+ location = gl.getUniformLocation(program, 'mat4Uniform');
+ var m4 = new Float32Array(matrixValues.slice(0, 4 * 4));
+ gl.uniformMatrix4fv(location, false, m4);
+ this.check(glsStateQuery.verifyUniform(program, location, m4));
+ gl.uniformMatrix4fv(location, true, m4);
+ this.check(glsStateQuery.verifyUniform(program, location, transpose(4, 4, m4)));
+
+ gl.useProgram(null);
+ gl.deleteShader(shaderVert);
+ gl.deleteShader(shaderFrag);
+ gl.deleteProgram(program);
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} shaderType
+ * @param {number} precisionType
+ */
+es3fShaderStateQueryTests.PrecisionFormatCase = function(name, description, shaderType, precisionType) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ this.m_shaderType = shaderType;
+ this.m_precisionType = precisionType;
+};
+
+setParentClass(es3fShaderStateQueryTests.PrecisionFormatCase, es3fApiCase.ApiCase);
+
+es3fShaderStateQueryTests.PrecisionFormatCase.prototype.test = function() {
+ var requirements = {};
+ requirements[gl.LOW_FLOAT] = [0, 0, 8];
+ requirements[gl.MEDIUM_FLOAT] = [13, 13, 10];
+ requirements[gl.HIGH_FLOAT] = [127, 127, 23];
+ requirements[gl.LOW_INT] = [8, 7, 0];
+ requirements[gl.MEDIUM_INT] = [15, 14, 0];
+ requirements[gl.HIGH_INT] = [31, 30, 0];
+
+
+ var expected = requirements[this.m_precisionType];
+ var result = gl.getShaderPrecisionFormat(this.m_shaderType, this.m_precisionType);
+
+ bufferedLogToConsole('Precision:' +
+ ' range min = ' + result.rangeMin +
+ ' range max = ' + result.rangeMax +
+ ' precision = ' + result.precision);
+
+ if (this.m_precisionType == gl.HIGH_FLOAT) {
+ // highp float must be IEEE 754 single
+
+ this.check(result.rangeMin == expected[0] ||
+ result.rangeMax == expected[1] ||
+ result.precision == expected[2],
+ 'Invalid precision format, expected:' +
+ ' range min = ' + expected[0] +
+ ' range max = ' + expected[1] +
+ ' precision = ' + expected[2]);
+ } else{
+ this.check(result.rangeMin >= expected[0] ||
+ result.rangeMax >= expected[1] ||
+ result.precision >= expected[2],
+ 'Invalid precision format, expected:' +
+ ' range min >= ' + expected[0] +
+ ' range max >= ' + expected[1] +
+ ' precision >= ' + expected[2]);
+ }
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fShaderStateQueryTests.ShaderStateQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'shader', 'Shader State Query tests');
+};
+
+es3fShaderStateQueryTests.ShaderStateQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fShaderStateQueryTests.ShaderStateQueryTests.prototype.constructor = es3fShaderStateQueryTests.ShaderStateQueryTests;
+
+es3fShaderStateQueryTests.ShaderStateQueryTests.prototype.init = function() {
+ // shader
+ this.addChild(new es3fShaderStateQueryTests.ShaderTypeCase('shader_type', 'SHADER_TYPE'));
+ this.addChild(new es3fShaderStateQueryTests.ShaderCompileStatusCase('shader_compile_status', 'COMPILE_STATUS'));
+ this.addChild(new es3fShaderStateQueryTests.ShaderInfoLogCase('shader_info_log', 'INFO_LOG'));
+ this.addChild(new es3fShaderStateQueryTests.ShaderSourceCase('shader_source', 'SHADER_SOURCE'));
+
+ // shader and program
+ this.addChild(new es3fShaderStateQueryTests.DeleteStatusCase('delete_status', 'DELETE_STATUS'));
+
+ // // vertex-attrib
+ this.addChild(new es3fShaderStateQueryTests.CurrentVertexAttribInitialCase('current_vertex_attrib_initial', 'CURRENT_VERTEX_ATTRIB'));
+ this.addChild(new es3fShaderStateQueryTests.CurrentVertexAttribFloatCase('current_vertex_attrib_float', 'CURRENT_VERTEX_ATTRIB'));
+ this.addChild(new es3fShaderStateQueryTests.CurrentVertexAttribIntCase('current_vertex_attrib_int', 'CURRENT_VERTEX_ATTRIB'));
+ this.addChild(new es3fShaderStateQueryTests.CurrentVertexAttribUintCase('current_vertex_attrib_uint', 'CURRENT_VERTEX_ATTRIB'));
+
+ // // program
+ this.addChild(new es3fShaderStateQueryTests.ProgramInfoLogCase('program_info_log', 'INFO_LOG'));
+ this.addChild(new es3fShaderStateQueryTests.ProgramValidateStatusCase('program_validate_status', 'VALIDATE_STATUS'));
+ this.addChild(new es3fShaderStateQueryTests.ProgramAttachedShadersCase('program_attached_shaders', 'ATTACHED_SHADERS'));
+
+ this.addChild(new es3fShaderStateQueryTests.ProgramActiveUniformNameCase('program_active_uniform_name', 'ACTIVE_UNIFORMS'));
+ this.addChild(new es3fShaderStateQueryTests.ProgramUniformCase('program_active_uniform_types', 'UNIFORM_TYPE, UNIFORM_SIZE, and UNIFORM_IS_ROW_MAJOR'));
+ this.addChild(new es3fShaderStateQueryTests.ProgramActiveUniformBlocksCase ("program_active_uniform_blocks", "ACTIVE_UNIFORM_BLOCK_x"));
+
+ // transform feedback
+ this.addChild(new es3fShaderStateQueryTests.TransformFeedbackCase('transform_feedback', 'TRANSFORM_FEEDBACK_BUFFER_MODE, TRANSFORM_FEEDBACK_VARYINGS, TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH'));
+
+ // attribute related
+ this.addChild(new es3fShaderStateQueryTests.ActiveAttributesCase('active_attributes', 'ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeSizeCase('vertex_attrib_size', 'VERTEX_ATTRIB_ARRAY_SIZE'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeTypeCase('vertex_attrib_type', 'VERTEX_ATTRIB_ARRAY_TYPE'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeStrideCase('vertex_attrib_stride', 'VERTEX_ATTRIB_ARRAY_STRIDE'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeNormalizedCase('vertex_attrib_normalized', 'VERTEX_ATTRIB_ARRAY_NORMALIZED'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeIntegerCase('vertex_attrib_integer', 'VERTEX_ATTRIB_ARRAY_INTEGER'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeEnabledCase('vertex_attrib_array_enabled', 'VERTEX_ATTRIB_ARRAY_ENABLED'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeDivisorCase('vertex_attrib_array_divisor', 'VERTEX_ATTRIB_ARRAY_DIVISOR'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeBufferBindingCase('vertex_attrib_array_buffer_binding', 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING'));
+ this.addChild(new es3fShaderStateQueryTests.VertexAttributeOffsetCase('vertex_attrib_offset', 'VERTEX_ATTRIB_ARRAY_POINTER'));
+
+ // uniform values
+ this.addChild(new es3fShaderStateQueryTests.UniformValueFloatCase('uniform_value_float', 'GetUniform*'));
+ this.addChild(new es3fShaderStateQueryTests.UniformValueIntCase('uniform_value_int', 'GetUniform*'));
+ this.addChild(new es3fShaderStateQueryTests.UniformValueUintCase('uniform_value_uint', 'GetUniform*'));
+ this.addChild(new es3fShaderStateQueryTests.UniformValueBooleanCase('uniform_value_boolean', 'GetUniform*'));
+ this.addChild(new es3fShaderStateQueryTests.UniformValueSamplerCase('uniform_value_sampler', 'GetUniform*'));
+ this.addChild(new es3fShaderStateQueryTests.UniformValueArrayCase('uniform_value_array', 'GetUniform*'));
+ this.addChild(new es3fShaderStateQueryTests.UniformValueMatrixCase('uniform_value_matrix', 'GetUniform*'));
+
+ // precision format query
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_vertex_lowp_float', 'GetShaderPrecisionFormat', gl.VERTEX_SHADER, gl.LOW_FLOAT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_vertex_mediump_float', 'GetShaderPrecisionFormat', gl.VERTEX_SHADER, gl.MEDIUM_FLOAT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_vertex_highp_float', 'GetShaderPrecisionFormat', gl.VERTEX_SHADER, gl.HIGH_FLOAT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_vertex_lowp_int', 'GetShaderPrecisionFormat', gl.VERTEX_SHADER, gl.LOW_INT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_vertex_mediump_int', 'GetShaderPrecisionFormat', gl.VERTEX_SHADER, gl.MEDIUM_INT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_vertex_highp_int', 'GetShaderPrecisionFormat', gl.VERTEX_SHADER, gl.HIGH_INT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_fragment_lowp_float', 'GetShaderPrecisionFormat', gl.FRAGMENT_SHADER, gl.LOW_FLOAT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_fragment_mediump_float', 'GetShaderPrecisionFormat', gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_fragment_highp_float', 'GetShaderPrecisionFormat', gl.FRAGMENT_SHADER, gl.HIGH_FLOAT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_fragment_lowp_int', 'GetShaderPrecisionFormat', gl.FRAGMENT_SHADER, gl.LOW_INT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_fragment_mediump_int', 'GetShaderPrecisionFormat', gl.FRAGMENT_SHADER, gl.MEDIUM_INT));
+ this.addChild(new es3fShaderStateQueryTests.PrecisionFormatCase('precision_fragment_highp_int', 'GetShaderPrecisionFormat', gl.FRAGMENT_SHADER, gl.HIGH_INT));
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fShaderStateQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderStateQueryTests.ShaderStateQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderStateQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStructTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStructTests.js
new file mode 100644
index 0000000000..3c23545d75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderStructTests.js
@@ -0,0 +1,1957 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderStructTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+// goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('modules.shared.glsShaderRenderCase');
+goog.require('framework.common.tcuStringTemplate');
+
+goog.scope(function() {
+ var es3fShaderStructTests = functional.gles3.es3fShaderStructTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deMath = framework.delibs.debase.deMath;
+ // var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+ var gluTexture = framework.opengl.gluTexture;
+ var tcuStringTemplate = framework.common.tcuStringTemplate;
+
+ /** @typedef {function(WebGLProgram, Array<number>)} */
+ es3fShaderStructTests.SetupUniformsFunc;
+
+ /** @const {number} */ es3fShaderStructTests.TEXTURE_BRICK = 0;
+
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {boolean} usesTextures
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ * @param {?es3fShaderStructTests.SetupUniformsFunc} setupUniformsFunc
+ * @param {string} vertShaderSource
+ * @param {string} fragShaderSource
+ */
+ es3fShaderStructTests.ShaderStructCase = function(name, description, isVertexCase, usesTextures, evalFunc, setupUniformsFunc, vertShaderSource, fragShaderSource) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
+ /** @type {?es3fShaderStructTests.SetupUniformsFunc} */ this.m_setupUniforms = setupUniformsFunc;
+ /** @type {boolean} */ this.m_usesTexture = usesTextures;
+ /** @type {gluTexture.Texture2D} */ this.m_brickTexture = null;
+ /** @type {string} */ this.m_vertShaderSource = vertShaderSource;
+ /** @type {string} */ this.m_fragShaderSource = fragShaderSource;
+ };
+
+ es3fShaderStructTests.ShaderStructCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+ es3fShaderStructTests.ShaderStructCase.prototype.constructor = es3fShaderStructTests.ShaderStructCase;
+
+ es3fShaderStructTests.ShaderStructCase.prototype.init = function() {
+ if (this.m_usesTexture) {
+ this.m_brickTexture = gluTexture.texture2DFromInternalFormat(gl, gl.RGBA8, 256, 256);
+ var ref = this.m_brickTexture.getRefTexture();
+ for (var i = 0 ; i < ref.getNumLevels(); i++) {
+ ref.allocLevel(i);
+ tcuTextureUtil.fillWithGrid(ref.getLevel(i), 8, [0.2, 0.7, 0.1, 1.0], [0.7, 0.1, 0.5, 0.8]);
+ }
+ this.m_brickTexture.upload();
+
+ this.m_textures.push(new glsShaderRenderCase.TextureBinding(
+ this.m_brickTexture,
+ new tcuTexture.Sampler(
+ tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.LINEAR,
+ tcuTexture.FilterMode.LINEAR)));
+
+ assertMsgOptions(this.m_textures.length === 1, 'Only one texture required', false, true);
+ }
+ this.postinit();
+ };
+
+ es3fShaderStructTests.ShaderStructCase.prototype.deinit = function() {
+ glsShaderRenderCase.ShaderRenderCase.prototype.deinit.call(this);
+ this.m_brickTexture = null;
+ };
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {Array<number>} constCoords
+ */
+ es3fShaderStructTests.ShaderStructCase.prototype.setupUniforms = function(programID, constCoords) {
+ glsShaderRenderCase.ShaderRenderCase.prototype.setupUniforms.call(this, programID, constCoords);
+ if (this.m_setupUniforms)
+ this.m_setupUniforms(programID, constCoords);
+ };
+
+ /**
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {boolean} usesTextures
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ * @param {?es3fShaderStructTests.SetupUniformsFunc} setupUniforms
+ * @param {string} shaderSrc
+ */
+ es3fShaderStructTests.ShaderStructCase.createStructCase = function(name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, shaderSrc) {
+ /** @type {string} */ var defaultVertSrc =
+ '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in highp vec4 a_coords;\n' +
+ 'out mediump vec4 v_coords;\n\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' v_coords = a_coords;\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+ /** @type {string} */ var defaultFragSrc =
+ '#version 300 es\n' +
+ 'in mediump vec4 v_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = v_color;\n' +
+ '}\n';
+
+ // Fill in specialization parameters.
+ var spParams = {};
+ if (isVertexCase) {
+ spParams["HEADER"] =
+ "#version 300 es\n" +
+ "in highp vec4 a_position;\n" +
+ "in highp vec4 a_coords;\n" +
+ "out mediump vec4 v_color;";
+ spParams["COORDS"] = "a_coords";
+ spParams["DST"] = "v_color";
+ spParams["ASSIGN_POS"] = "gl_Position = a_position;";
+ }
+ else {
+ spParams["HEADER"] =
+ "#version 300 es\n" +
+ "in mediump vec4 v_coords;\n" +
+ "layout(location = 0) out mediump vec4 o_color;";
+ spParams["COORDS"] = "v_coords";
+ spParams["DST"] = "o_color";
+ spParams["ASSIGN_POS"] = "";
+ }
+
+ if (isVertexCase)
+ return new es3fShaderStructTests.ShaderStructCase(name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, tcuStringTemplate.specialize(shaderSrc, spParams), defaultFragSrc);
+ else
+ return new es3fShaderStructTests.ShaderStructCase(name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, defaultVertSrc, tcuStringTemplate.specialize(shaderSrc, spParams));
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderStructTests.LocalStructTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'local', 'Local structs');
+ this.makeExecutable();
+ };
+
+ es3fShaderStructTests.LocalStructTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderStructTests.LocalStructTests.prototype.constructor = es3fShaderStructTests.LocalStructTests;
+
+ es3fShaderStructTests.LocalStructTests.prototype.init = function() {
+ var currentCtx = this;
+ function LocalStructCase(name, description, shaderSource, evalFunction) {
+ currentCtx.addChild(es3fShaderStructTests.ShaderStructCase.createStructCase(name + "_vertex", description, true, false, evalFunction, null, shaderSource));
+ currentCtx.addChild(es3fShaderStructTests.ShaderStructCase.createStructCase(name + "_fragment", description, false, false, evalFunction, null, shaderSource));
+ };
+
+ LocalStructCase('basic', 'Basic struct usage',
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, vec3(0.0), ui_one);\n' +
+ ' s.b = ${COORDS}.yzw;\n' +
+ ' ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[2];
+ });
+
+ LocalStructCase('nested', "Nested struct",
+ '${HEADER}\n' +
+ "uniform int ui_zero;\n" +
+ "uniform int ui_one;\n" +
+ "\n" +
+ "struct T {\n" +
+ " int a;\n" +
+ " mediump vec2 b;\n" +
+ "};\n" +
+ "struct S {\n" +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);\n' +
+ ' s.b = T(ui_zero, ${COORDS}.yz);\n' +
+ ' ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[2];
+ });
+
+ LocalStructCase('array_member', "Struct with array member",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump float b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s;\n' +
+ ' s.a = ${COORDS}.w;\n' +
+ ' s.c = ui_one;\n' +
+ ' s.b[0] = ${COORDS}.z;\n' +
+ ' s.b[1] = ${COORDS}.y;\n' +
+ ' s.b[2] = ${COORDS}.x;\n' +
+ ' ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[3];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[1];
+ });
+
+ LocalStructCase('array_member_dynamic_index', "Struct with array member, dynamic indexing",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump float b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s;\n' +
+ ' s.a = ${COORDS}.w;\n' +
+ ' s.c = ui_one;\n' +
+ ' s.b[0] = ${COORDS}.z;\n' +
+ ' s.b[1] = ${COORDS}.y;\n' +
+ ' s.b[2] = ${COORDS}.x;\n' +
+ ' ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[1];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[0];
+ });
+
+ LocalStructCase('struct_array', "Struct array",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[3];\n' +
+ ' s[0] = S(${COORDS}.x, ui_zero);\n' +
+ ' s[1].a = ${COORDS}.y;\n' +
+ ' s[1].b = ui_one;\n' +
+ ' s[2] = S(${COORDS}.z, ui_two);\n' +
+ ' ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[2];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[0];
+ });
+
+ LocalStructCase('struct_array_dynamic_index', "Struct array with dynamic indexing",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[3];\n' +
+ ' s[0] = S(${COORDS}.x, ui_zero);\n' +
+ ' s[1].a = ${COORDS}.y;\n' +
+ ' s[1].b = ui_one;\n' +
+ ' s[2] = S(${COORDS}.z, ui_two);\n' +
+ ' ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[2];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[0];
+ });
+
+ LocalStructCase('nested_struct_array', "Nested struct array",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform mediump float uf_two;\n' +
+ 'uniform mediump float uf_three;\n' +
+ 'uniform mediump float uf_four;\n' +
+ 'uniform mediump float uf_half;\n' +
+ 'uniform mediump float uf_third;\n' +
+ 'uniform mediump float uf_fourth;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[2];\n' +
+ '\n' +
+ ' // S[0]\n' +
+ ' s[0].a = ${COORDS}.x;\n' +
+ ' s[0].b[0].a = uf_half;\n' +
+ ' s[0].b[0].b[0] = ${COORDS}.xy;\n' +
+ ' s[0].b[0].b[1] = ${COORDS}.zw;\n' +
+ ' s[0].b[1].a = uf_third;\n' +
+ ' s[0].b[1].b[0] = ${COORDS}.zw;\n' +
+ ' s[0].b[1].b[1] = ${COORDS}.xy;\n' +
+ ' s[0].b[2].a = uf_fourth;\n' +
+ ' s[0].b[2].b[0] = ${COORDS}.xz;\n' +
+ ' s[0].b[2].b[1] = ${COORDS}.yw;\n' +
+ ' s[0].c = ui_zero;\n' +
+ '\n' +
+ ' // S[1]\n' +
+ ' s[1].a = ${COORDS}.w;\n' +
+ ' s[1].b[0].a = uf_two;\n' +
+ ' s[1].b[0].b[0] = ${COORDS}.xx;\n' +
+ ' s[1].b[0].b[1] = ${COORDS}.yy;\n' +
+ ' s[1].b[1].a = uf_three;\n' +
+ ' s[1].b[1].b[0] = ${COORDS}.zz;\n' +
+ ' s[1].b[1].b[1] = ${COORDS}.ww;\n' +
+ ' s[1].b[2].a = uf_four;\n' +
+ ' s[1].b[2].b[0] = ${COORDS}.yx;\n' +
+ ' s[1].b[2].b[1] = ${COORDS}.wz;\n' +
+ ' s[1].c = ui_one;\n' +
+ '\n' +
+ ' mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5\n' +
+ ' mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4\n' +
+ ' mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w + w) * 0.333\n' +
+ ' mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0\n' +
+ ' ${DST} = vec4(r, g, b, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[2];
+ c.color[1] = c.coords[0];
+ c.color[2] = c.coords[3];
+ });
+
+ LocalStructCase('nested_struct_array_dynamic_index', "Nested struct array with dynamic indexing",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform mediump float uf_two;\n' +
+ 'uniform mediump float uf_three;\n' +
+ 'uniform mediump float uf_four;\n' +
+ 'uniform mediump float uf_half;\n' +
+ 'uniform mediump float uf_third;\n' +
+ 'uniform mediump float uf_fourth;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[2];\n' +
+ '\n' +
+ ' // S[0]\n' +
+ ' s[0].a = ${COORDS}.x;\n' +
+ ' s[0].b[0].a = uf_half;\n' +
+ ' s[0].b[0].b[0] = ${COORDS}.xy;\n' +
+ ' s[0].b[0].b[1] = ${COORDS}.zw;\n' +
+ ' s[0].b[1].a = uf_third;\n' +
+ ' s[0].b[1].b[0] = ${COORDS}.zw;\n' +
+ ' s[0].b[1].b[1] = ${COORDS}.xy;\n' +
+ ' s[0].b[2].a = uf_fourth;\n' +
+ ' s[0].b[2].b[0] = ${COORDS}.xz;\n' +
+ ' s[0].b[2].b[1] = ${COORDS}.yw;\n' +
+ ' s[0].c = ui_zero;\n' +
+ '\n' +
+ ' // S[1]\n' +
+ ' s[1].a = ${COORDS}.w;\n' +
+ ' s[1].b[0].a = uf_two;\n' +
+ ' s[1].b[0].b[0] = ${COORDS}.xx;\n' +
+ ' s[1].b[0].b[1] = ${COORDS}.yy;\n' +
+ ' s[1].b[1].a = uf_three;\n' +
+ ' s[1].b[1].b[0] = ${COORDS}.zz;\n' +
+ ' s[1].b[1].b[1] = ${COORDS}.ww;\n' +
+ ' s[1].b[2].a = uf_four;\n' +
+ ' s[1].b[2].b[0] = ${COORDS}.yx;\n' +
+ ' s[1].b[2].b[1] = ${COORDS}.wz;\n' +
+ ' s[1].c = ui_one;\n' +
+ '\n' +
+ ' mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5\n' +
+ ' mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * s[ui_one].b[2].a; // x * 0.25 * 4\n' +
+ ' mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333\n' +
+ ' mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0\n' +
+ ' ${DST} = vec4(r, g, b, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[2];
+ c.color[1] = c.coords[0];
+ c.color[2] = c.coords[3];
+ });
+
+ LocalStructCase('parameter', "Struct as a function parameter",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'mediump vec4 myFunc (S s)\n' +
+ '{\n' +
+ ' return vec4(s.a, s.b.x, s.b.y, s.c);\n' +
+ '}\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, vec3(0.0), ui_one);\n' +
+ ' s.b = ${COORDS}.yzw;\n' +
+ ' ${DST} = myFunc(s);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[2];
+ });
+
+ LocalStructCase('parameter_nested', "Nested struct as a function parameter",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' int a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'mediump vec4 myFunc (S s)\n' +
+ '{\n' +
+ ' return vec4(s.a, s.b.b, s.b.a + s.c);\n' +
+ '}\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);\n' +
+ ' s.b = T(ui_zero, ${COORDS}.yz);\n' +
+ ' ${DST} = myFunc(s);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[2];
+ });
+
+ LocalStructCase('return', "Struct as a return value",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'S myFunc (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, vec3(0.0), ui_one);\n' +
+ ' s.b = ${COORDS}.yzw;\n' +
+ ' return s;\n' +
+ '}\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = myFunc();\n' +
+ ' ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[2];
+ });
+
+ LocalStructCase('return_nested', "Nested struct",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' int a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'S myFunc (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);\n' +
+ ' s.b = T(ui_zero, ${COORDS}.yz);\n' +
+ ' return s;\n' +
+ '}\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = myFunc();\n' +
+ ' ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[2];
+ });
+
+ LocalStructCase('conditional_assignment', "Conditional struct assignment",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform mediump float uf_one;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);\n' +
+ ' if (uf_one > 0.0)\n' +
+ ' s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);\n' +
+ ' ${DST} = vec4(s.a, s.b.xy, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[3];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[1];
+ });
+
+ LocalStructCase('loop_assignment', "Struct assignment in loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);\n' +
+ ' for (int i = 0; i < 3; i++)\n' +
+ ' {\n' +
+ ' if (i == 1)\n' +
+ ' s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);\n' +
+ ' }\n' +
+ ' ${DST} = vec4(s.a, s.b.xy, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[3];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[1];
+ });
+
+ LocalStructCase('dynamic_loop_assignment', "Struct assignment in loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_three;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);\n' +
+ ' for (int i = 0; i < ui_three; i++)\n' +
+ ' {\n' +
+ ' if (i == ui_one)\n' +
+ ' s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);\n' +
+ ' }\n' +
+ ' ${DST} = vec4(s.a, s.b.xy, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[3];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[1];
+ });
+
+ LocalStructCase('nested_conditional_assignment', "Conditional assignment of nested struct",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform mediump float uf_one;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' int a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);\n' +
+ ' if (uf_one > 0.0)\n' +
+ ' s.b = T(ui_zero, ${COORDS}.zw);\n' +
+ ' ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[3];
+ });
+
+ LocalStructCase('nested_loop_assignment', "Nested struct assignment in loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform mediump float uf_one;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' int a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);\n' +
+ ' for (int i = 0; i < 3; i++)\n' +
+ ' {\n' +
+ ' if (i == 1)\n' +
+ ' s.b = T(ui_zero, ${COORDS}.zw);\n' +
+ ' }\n' +
+ ' ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[3];
+ });
+
+ LocalStructCase('nested_dynamic_loop_assignment', "Nested struct assignment in dynamic loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_three;\n' +
+ 'uniform mediump float uf_one;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' int a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);\n' +
+ ' for (int i = 0; i < ui_three; i++)\n' +
+ ' {\n' +
+ ' if (i == ui_one)\n' +
+ ' s.b = T(ui_zero, ${COORDS}.zw);\n' +
+ ' }\n' +
+ ' ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[0];
+ c.color[1] = c.coords[2];
+ c.color[2] = c.coords[3];
+ });
+
+ LocalStructCase('loop_struct_array', "Struct array usage in loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[3];\n' +
+ ' s[0] = S(${COORDS}.x, ui_zero);\n' +
+ ' s[1].a = ${COORDS}.y;\n' +
+ ' s[1].b = -ui_one;\n' +
+ ' s[2] = S(${COORDS}.z, ui_two);\n' +
+ '\n' +
+ ' mediump float rgb[3];\n' +
+ ' int alpha = 0;\n' +
+ ' for (int i = 0; i < 3; i++)\n' +
+ ' {\n' +
+ ' rgb[i] = s[2-i].a;\n' +
+ ' alpha += s[i].b;\n' +
+ ' }\n' +
+ ' ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[2];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[0];
+ });
+
+ LocalStructCase('loop_nested_struct_array', "Nested struct array usage in loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform mediump float uf_two;\n' +
+ 'uniform mediump float uf_three;\n' +
+ 'uniform mediump float uf_four;\n' +
+ 'uniform mediump float uf_half;\n' +
+ 'uniform mediump float uf_third;\n' +
+ 'uniform mediump float uf_fourth;\n' +
+ 'uniform mediump float uf_sixth;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[2];\n' +
+ '\n' +
+ ' // S[0]\n' +
+ ' s[0].a = ${COORDS}.x;\n' +
+ ' s[0].b[0].a = uf_half;\n' +
+ ' s[0].b[0].b[0] = ${COORDS}.yx;\n' +
+ ' s[0].b[0].b[1] = ${COORDS}.zx;\n' +
+ ' s[0].b[1].a = uf_third;\n' +
+ ' s[0].b[1].b[0] = ${COORDS}.yy;\n' +
+ ' s[0].b[1].b[1] = ${COORDS}.wy;\n' +
+ ' s[0].b[2].a = uf_fourth;\n' +
+ ' s[0].b[2].b[0] = ${COORDS}.zx;\n' +
+ ' s[0].b[2].b[1] = ${COORDS}.zy;\n' +
+ ' s[0].c = ui_zero;\n' +
+ '\n' +
+ ' // S[1]\n' +
+ ' s[1].a = ${COORDS}.w;\n' +
+ ' s[1].b[0].a = uf_two;\n' +
+ ' s[1].b[0].b[0] = ${COORDS}.zx;\n' +
+ ' s[1].b[0].b[1] = ${COORDS}.zy;\n' +
+ ' s[1].b[1].a = uf_three;\n' +
+ ' s[1].b[1].b[0] = ${COORDS}.zz;\n' +
+ ' s[1].b[1].b[1] = ${COORDS}.ww;\n' +
+ ' s[1].b[2].a = uf_four;\n' +
+ ' s[1].b[2].b[0] = ${COORDS}.yx;\n' +
+ ' s[1].b[2].b[1] = ${COORDS}.wz;\n' +
+ ' s[1].c = ui_one;\n' +
+ '\n' +
+ ' mediump float r = 0.0; // (x*3 + y*3) / 6.0\n' +
+ ' mediump float g = 0.0; // (y*3 + z*3) / 6.0\n' +
+ ' mediump float b = 0.0; // (z*3 + w*3) / 6.0\n' +
+ ' mediump float a = 1.0;\n' +
+ ' for (int i = 0; i < 2; i++)\n' +
+ ' {\n' +
+ ' for (int j = 0; j < 3; j++)\n' +
+ ' {\n' +
+ ' r += s[0].b[j].b[i].y;\n' +
+ ' g += s[i].b[j].b[0].x;\n' +
+ ' b += s[i].b[j].b[1].x;\n' +
+ ' a *= s[i].b[j].a;\n' +
+ ' }\n' +
+ ' }\n' +
+ ' ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = (c.coords[0] + c.coords[1]) * 0.5;
+ c.color[1] = (c.coords[1] + c.coords[2]) * 0.5;
+ c.color[2] = (c.coords[2] + c.coords[3]) * 0.5;
+ });
+
+ LocalStructCase('dynamic_loop_struct_array', "Struct array usage in dynamic loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform int ui_three;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[3];\n' +
+ ' s[0] = S(${COORDS}.x, ui_zero);\n' +
+ ' s[1].a = ${COORDS}.y;\n' +
+ ' s[1].b = -ui_one;\n' +
+ ' s[2] = S(${COORDS}.z, ui_two);\n' +
+ '\n' +
+ ' mediump float rgb[3];\n' +
+ ' int alpha = 0;\n' +
+ ' for (int i = 0; i < ui_three; i++)\n' +
+ ' {\n' +
+ ' rgb[i] = s[2-i].a;\n' +
+ ' alpha += s[i].b;\n' +
+ ' }\n' +
+ ' ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = c.coords[2];
+ c.color[1] = c.coords[1];
+ c.color[2] = c.coords[0];
+ });
+
+ LocalStructCase('dynamic_loop_nested_struct_array', "Nested struct array usage in dynamic loop",
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform int ui_three;\n' +
+ 'uniform mediump float uf_two;\n' +
+ 'uniform mediump float uf_three;\n' +
+ 'uniform mediump float uf_four;\n' +
+ 'uniform mediump float uf_half;\n' +
+ 'uniform mediump float uf_third;\n' +
+ 'uniform mediump float uf_fourth;\n' +
+ 'uniform mediump float uf_sixth;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S s[2];\n' +
+ '\n' +
+ ' // S[0]\n' +
+ ' s[0].a = ${COORDS}.x;\n' +
+ ' s[0].b[0].a = uf_half;\n' +
+ ' s[0].b[0].b[0] = ${COORDS}.yx;\n' +
+ ' s[0].b[0].b[1] = ${COORDS}.zx;\n' +
+ ' s[0].b[1].a = uf_third;\n' +
+ ' s[0].b[1].b[0] = ${COORDS}.yy;\n' +
+ ' s[0].b[1].b[1] = ${COORDS}.wy;\n' +
+ ' s[0].b[2].a = uf_fourth;\n' +
+ ' s[0].b[2].b[0] = ${COORDS}.zx;\n' +
+ ' s[0].b[2].b[1] = ${COORDS}.zy;\n' +
+ ' s[0].c = ui_zero;\n' +
+ '\n' +
+ ' // S[1]\n' +
+ ' s[1].a = ${COORDS}.w;\n' +
+ ' s[1].b[0].a = uf_two;\n' +
+ ' s[1].b[0].b[0] = ${COORDS}.zx;\n' +
+ ' s[1].b[0].b[1] = ${COORDS}.zy;\n' +
+ ' s[1].b[1].a = uf_three;\n' +
+ ' s[1].b[1].b[0] = ${COORDS}.zz;\n' +
+ ' s[1].b[1].b[1] = ${COORDS}.ww;\n' +
+ ' s[1].b[2].a = uf_four;\n' +
+ ' s[1].b[2].b[0] = ${COORDS}.yx;\n' +
+ ' s[1].b[2].b[1] = ${COORDS}.wz;\n' +
+ ' s[1].c = ui_one;\n' +
+ '\n' +
+ ' mediump float r = 0.0; // (x*3 + y*3) / 6.0\n' +
+ ' mediump float g = 0.0; // (y*3 + z*3) / 6.0\n' +
+ ' mediump float b = 0.0; // (z*3 + w*3) / 6.0\n' +
+ ' mediump float a = 1.0;\n' +
+ ' for (int i = 0; i < ui_two; i++)\n' +
+ ' {\n' +
+ ' for (int j = 0; j < ui_three; j++)\n' +
+ ' {\n' +
+ ' r += s[0].b[j].b[i].y;\n' +
+ ' g += s[i].b[j].b[0].x;\n' +
+ ' b += s[i].b[j].b[1].x;\n' +
+ ' a *= s[i].b[j].a;\n' +
+ ' }\n' +
+ ' }\n' +
+ ' ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ c.color[0] = (c.coords[0] + c.coords[1]) * 0.5;
+ c.color[1] = (c.coords[1] + c.coords[2]) * 0.5;
+ c.color[2] = (c.coords[2] + c.coords[3]) * 0.5;
+ });
+
+ LocalStructCase('basic_equal', "Basic struct equality",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);\n' +
+ ' S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);\n' +
+ ' S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);\n' +
+ ' S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);\n' +
+ ' ${DST} = vec4(0.0, 0.0, 0.0, 1.0);\n' +
+ ' if (a == b) ${DST}.x = 1.0;\n' +
+ ' if (a == c) ${DST}.y = 1.0;\n' +
+ ' if (a == d) ${DST}.z = 1.0;\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ if (Math.floor(c.coords[0]) === Math.floor(c.coords[0] + 0.5))
+ c.color[0] = 1.0;
+ if (Math.floor(c.coords[1]) === Math.floor(c.coords[1] + 0.5))
+ c.color[1] = 1.0;
+ });
+
+ LocalStructCase('basic_not_equal', "Basic struct equality",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);\n' +
+ ' S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);\n' +
+ ' S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);\n' +
+ ' S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);\n' +
+ ' ${DST} = vec4(0.0, 0.0, 0.0, 1.0);\n' +
+ ' if (a != b) ${DST}.x = 1.0;\n' +
+ ' if (a != c) ${DST}.y = 1.0;\n' +
+ ' if (a != d) ${DST}.z = 1.0;\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ if (Math.floor(c.coords[0]) != Math.floor(c.coords[0] + 0.5))
+ c.color[0] = 1.0;
+ if (Math.floor(c.coords[1]) != Math.floor(c.coords[1] + 0.5))
+ c.color[1] = 1.0;
+ c.color[2] = 1.0;
+ });
+
+ LocalStructCase('nested_equal', "Nested struct struct equality",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' mediump vec3 a;\n' +
+ ' int b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);\n' +
+ ' S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);\n' +
+ ' S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);\n' +
+ ' S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);\n' +
+ ' ${DST} = vec4(0.0, 0.0, 0.0, 1.0);\n' +
+ ' if (a == b) ${DST}.x = 1.0;\n' +
+ ' if (a == c) ${DST}.y = 1.0;\n' +
+ ' if (a == d) ${DST}.z = 1.0;\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ if (Math.floor(c.coords[0]) == Math.floor(c.coords[0] + 0.5))
+ c.color[0] = 1.0;
+ if (Math.floor(c.coords[1]) == Math.floor(c.coords[1] + 0.5))
+ c.color[1] = 1.0;
+ });
+
+ LocalStructCase('nested_not_equal', "Nested struct struct equality",
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '\n' +
+ 'struct T {\n' +
+ ' mediump vec3 a;\n' +
+ ' int b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);\n' +
+ ' S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);\n' +
+ ' S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);\n' +
+ ' S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);\n' +
+ ' ${DST} = vec4(0.0, 0.0, 0.0, 1.0);\n' +
+ ' if (a != b) ${DST}.x = 1.0;\n' +
+ ' if (a != c) ${DST}.y = 1.0;\n' +
+ ' if (a != d) ${DST}.z = 1.0;\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}\n',
+ function(c) {
+ if (Math.floor(c.coords[0]) != Math.floor(c.coords[0] + 0.5))
+ c.color[0] = 1.0;
+ if (Math.floor(c.coords[1]) != Math.floor(c.coords[1] + 0.5))
+ c.color[1] = 1.0;
+ c.color[2] = 1.0;
+ });
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderStructTests.UniformStructTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'uniform', 'Uniform structs');
+ this.makeExecutable();
+ };
+
+ es3fShaderStructTests.UniformStructTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderStructTests.UniformStructTests.prototype.constructor = es3fShaderStructTests.UniformStructTests;
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {string} name
+ * @param {Array<number>} vec
+ */
+ es3fShaderStructTests.setUniform2fv = function(programID, name, vec) {
+ /** @type {WebGLUniformLocation} */ var loc = gl.getUniformLocation(programID, name);
+ gl.uniform2fv(loc, vec);
+ };
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {string} name
+ * @param {Array<number>} vec
+ */
+ es3fShaderStructTests.setUniform3fv = function(programID, name, vec) {
+ /** @type {WebGLUniformLocation} */ var loc = gl.getUniformLocation(programID, name);
+ gl.uniform3fv(loc, vec);
+ };
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {string} name
+ * @param {number} value
+ */
+ es3fShaderStructTests.setUniform1i = function(programID, name, value) {
+ /** @type {WebGLUniformLocation} */ var loc = gl.getUniformLocation(programID, name);
+ gl.uniform1i(loc, value);
+ };
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {string} name
+ * @param {number} value
+ */
+ es3fShaderStructTests.setUniform1f = function(programID, name, value) {
+ /** @type {WebGLUniformLocation} */ var loc = gl.getUniformLocation(programID, name);
+ gl.uniform1f(loc, value);
+ };
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {string} name
+ * @param {Array<number>} vec
+ */
+ es3fShaderStructTests.setUniform1fv = function(programID, name, vec) {
+ /** @type {WebGLUniformLocation} */ var loc = gl.getUniformLocation(programID, name);
+ gl.uniform1fv(loc, vec);
+ };
+
+ es3fShaderStructTests.UniformStructTests.prototype.init = function() {
+ var currentCtx = this;
+ function UniformStructCase(name, description, textures, shaderSrc, setUniformsFunc, evalFunc) {
+ currentCtx.addChild(es3fShaderStructTests.ShaderStructCase.createStructCase(name + "_vertex", description, true, textures, evalFunc, setUniformsFunc, shaderSrc));
+ currentCtx.addChild(es3fShaderStructTests.ShaderStructCase.createStructCase(name + "_fragment", description, false, textures, evalFunc, setUniformsFunc, shaderSrc));
+ }
+
+ UniformStructCase('basic', "Basic struct usage", false,
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s.a", constCoords[0]);
+ es3fShaderStructTests.setUniform3fv(programID, "s.b", deMath.swizzle(constCoords, [1, 2, 3]));
+ es3fShaderStructTests.setUniform1i(programID, "s.c", 1);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[0];
+ c.color[1] = c.constCoords[1];
+ c.color[2] = c.constCoords[2];
+ });
+
+ UniformStructCase('nested', "Nested struct", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ '' +
+ 'struct T {\n' +
+ ' int a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s.a", constCoords[0]);
+ es3fShaderStructTests.setUniform1i(programID, "s.b.a", 0);
+ es3fShaderStructTests.setUniform2fv(programID, "s.b.b", deMath.swizzle(constCoords, [1,2]));
+ es3fShaderStructTests.setUniform1i(programID, "s.c", 1);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[0];
+ c.color[1] = c.constCoords[1];
+ c.color[2] = c.constCoords[2];
+ });
+
+ UniformStructCase('array_member', "Struct with array member", false,
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump float b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords){
+ es3fShaderStructTests.setUniform1f(programID, "s.a", constCoords[3]);
+ es3fShaderStructTests.setUniform1i(programID, "s.c", 1);
+
+ /** @type {Array<number>} */ var b = [];
+ b[0] = constCoords[2];
+ b[1] = constCoords[1];
+ b[2] = constCoords[0];
+ es3fShaderStructTests.setUniform1fv(programID, "s.b", b);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[3];
+ c.color[1] = c.constCoords[2];
+ c.color[2] = c.constCoords[1];
+ });
+
+ UniformStructCase('array_member_dynamic_index', "Struct with array member, dynamic indexing", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump float b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s.a", constCoords[3]);
+ es3fShaderStructTests.setUniform1i(programID, "s.c", 1);
+
+ /** @type {Array<number>} */ var b = [];
+ b[0] = constCoords[2];
+ b[1] = constCoords[1];
+ b[2] = constCoords[0];
+ es3fShaderStructTests.setUniform1fv(programID, "s.b", b);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[1];
+ c.color[1] = c.constCoords[2];
+ c.color[2] = c.constCoords[0];
+ });
+
+ UniformStructCase('struct_array', "Struct array", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ 'uniform S s[3];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].b", 0);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[1]);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].b", 1);
+ es3fShaderStructTests.setUniform1f(programID, "s[2].a", constCoords[2]);
+ es3fShaderStructTests.setUniform1i(programID, "s[2].b", 2);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[2];
+ c.color[1] = c.constCoords[1];
+ c.color[2] = c.constCoords[0];
+ });
+
+ UniformStructCase('struct_array_dynamic_index', "Struct array with dynamic indexing", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ 'uniform S s[3];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].b", 0);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[1]);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].b", 1);
+ es3fShaderStructTests.setUniform1f(programID, "s[2].a", constCoords[2]);
+ es3fShaderStructTests.setUniform1i(programID, "s[2].b", 2);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[2];
+ c.color[1] = c.constCoords[1];
+ c.color[2] = c.constCoords[0];
+ });
+
+ UniformStructCase('nested_struct_array', "Nested struct array", false,
+ '${HEADER}\n' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s[2];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5\n' +
+ ' mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4\n' +
+ ' mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w + w) * 0.333\n' +
+ ' mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0\n' +
+ ' ${DST} = vec4(r, g, b, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ /** @type {Array<number>} */ var arr = [];
+
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ arr = deMath.swizzle(constCoords, [0,1,2,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[0].a", 0.5);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [2,3,0,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[1].a", 1.0/3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [0,2,1,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[2].a", 1.0/4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].c", 0);
+
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[3]);
+ arr = deMath.swizzle(constCoords, [0,0,1,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[0].a", 2.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [2,2,3,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[1].a", 3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [1,0,3,2]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[2].a", 4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].c", 1);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[2];
+ c.color[1] = c.constCoords[0];
+ c.color[2] = c.constCoords[3];
+ });
+
+ UniformStructCase('nested_struct_array_dynamic_index', "Nested struct array with dynamic indexing", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s[2];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5\n' +
+ ' mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * s[ui_one].b[2].a; // x * 0.25 * 4\n' +
+ ' mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333\n' +
+ ' mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0\n' +
+ ' ${DST} = vec4(r, g, b, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords){
+ /** @type {Array<number>} */ var arr = [];
+
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ arr = constCoords;
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[0].a", 0.5);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [2,3,0,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[1].a", 1.0/3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [0,2,1,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[2].a", 1.0/4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].c", 0);
+
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[3]);
+ arr = deMath.swizzle(constCoords, [0,0,1,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[0].a", 2.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [2,2,3,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[1].a", 3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [1,0,3,2]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[2].a", 4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].c", 1);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[2];
+ c.color[1] = c.constCoords[0];
+ c.color[2] = c.constCoords[3];
+ });
+
+ UniformStructCase('loop_struct_array', "Struct array usage in loop", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ 'uniform S s[3];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float rgb[3];\n' +
+ ' int alpha = 0;\n' +
+ ' for (int i = 0; i < 3; i++)\n' +
+ ' {\n' +
+ ' rgb[i] = s[2-i].a;\n' +
+ ' alpha += s[i].b;\n' +
+ ' }\n' +
+ ' ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].b", 0);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[1]);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].b", -1);
+ es3fShaderStructTests.setUniform1f(programID, "s[2].a", constCoords[2]);
+ es3fShaderStructTests.setUniform1i(programID, "s[2].b", 2);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[2];
+ c.color[1] = c.constCoords[1];
+ c.color[2] = c.constCoords[0];
+ });
+
+ UniformStructCase('loop_nested_struct_array', "Nested struct array usage in loop", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform mediump float uf_two;\n' +
+ 'uniform mediump float uf_three;\n' +
+ 'uniform mediump float uf_four;\n' +
+ 'uniform mediump float uf_half;\n' +
+ 'uniform mediump float uf_third;\n' +
+ 'uniform mediump float uf_fourth;\n' +
+ 'uniform mediump float uf_sixth;\n' +
+ '' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s[2];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float r = 0.0; // (x*3 + y*3) / 6.0\n' +
+ ' mediump float g = 0.0; // (y*3 + z*3) / 6.0\n' +
+ ' mediump float b = 0.0; // (z*3 + w*3) / 6.0\n' +
+ ' mediump float a = 1.0;\n' +
+ ' for (int i = 0; i < 2; i++)\n' +
+ ' {\n' +
+ ' for (int j = 0; j < 3; j++)\n' +
+ ' {\n' +
+ ' r += s[0].b[j].b[i].y;\n' +
+ ' g += s[i].b[j].b[0].x;\n' +
+ ' b += s[i].b[j].b[1].x;\n' +
+ ' a *= s[i].b[j].a;\n' +
+ ' }\n' +
+ ' }\n' +
+ ' ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ /** @type {Array<number>} */ var arr = [];
+
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ arr = deMath.swizzle(constCoords, [1,0,2,0]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[0].a", 0.5);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [1,1,3,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[1].a", 1.0/3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [2,1,2,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[2].a", 1.0/4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].c", 0);
+
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[3]);
+ arr = deMath.swizzle(constCoords, [2,0,2,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[0].a", 2.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [2,2,3,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[1].a", 3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [1,0,3,2]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[2].a", 4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].c", 1);
+ },
+ function(c) {
+ c.color[0] = (c.constCoords[0] + c.constCoords[1]) * 0.5;
+ c.color[1] = (c.constCoords[1] + c.constCoords[2]) * 0.5;
+ c.color[2] = (c.constCoords[2] + c.constCoords[3]) * 0.5;
+ });
+
+ UniformStructCase('dynamic_loop_struct_array', "Struct array usage in dynamic loop", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform int ui_three;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump int b;\n' +
+ '};\n' +
+ 'uniform S s[3];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float rgb[3];\n' +
+ ' int alpha = 0;\n' +
+ ' for (int i = 0; i < ui_three; i++)\n' +
+ ' {\n' +
+ ' rgb[i] = s[2-i].a;\n' +
+ ' alpha += s[i].b;\n' +
+ ' }\n' +
+ ' ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].b", 0);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[1]);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].b", -1);
+ es3fShaderStructTests.setUniform1f(programID, "s[2].a", constCoords[2]);
+ es3fShaderStructTests.setUniform1i(programID, "s[2].b", 2);
+ },
+ function(c) {
+ c.color[0] = c.constCoords[2];
+ c.color[1] = c.constCoords[1];
+ c.color[2] = c.constCoords[0];
+ });
+
+ UniformStructCase('dynamic_loop_nested_struct_array', "Nested struct array usage in dynamic loop", false,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ 'uniform int ui_two;\n' +
+ 'uniform int ui_three;\n' +
+ 'uniform mediump float uf_two;\n' +
+ 'uniform mediump float uf_three;\n' +
+ 'uniform mediump float uf_four;\n' +
+ 'uniform mediump float uf_half;\n' +
+ 'uniform mediump float uf_third;\n' +
+ 'uniform mediump float uf_fourth;\n' +
+ 'uniform mediump float uf_sixth;\n' +
+ '' +
+ 'struct T {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec2 b[2];\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b[3];\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s[2];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' mediump float r = 0.0; // (x*3 + y*3) / 6.0\n' +
+ ' mediump float g = 0.0; // (y*3 + z*3) / 6.0\n' +
+ ' mediump float b = 0.0; // (z*3 + w*3) / 6.0\n' +
+ ' mediump float a = 1.0;\n' +
+ ' for (int i = 0; i < ui_two; i++)\n' +
+ ' {\n' +
+ ' for (int j = 0; j < ui_three; j++)\n' +
+ ' {\n' +
+ ' r += s[0].b[j].b[i].y;\n' +
+ ' g += s[i].b[j].b[0].x;\n' +
+ ' b += s[i].b[j].b[1].x;\n' +
+ ' a *= s[i].b[j].a;\n' +
+ ' }\n' +
+ ' }\n' +
+ ' ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ /** @type {Array<number>} */ var arr = [];
+
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", constCoords[0]);
+ arr = deMath.swizzle(constCoords, [1,0,2,0]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[0].a", 0.5);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [1,1,3,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[1].a", 1.0/3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [2,1,2,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[0].b[2].a", 1.0/4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[0].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].c", 0);
+
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", constCoords[3]);
+ arr = deMath.swizzle(constCoords, [2,0,2,1]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[0].a", 2.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[0].b", arr);
+ arr = deMath.swizzle(constCoords, [2,2,3,3]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[1].a", 3.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[1].b", arr);
+ arr = deMath.swizzle(constCoords, [1,0,3,2]);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].b[2].a", 4.0);
+ es3fShaderStructTests.setUniform2fv(programID, "s[1].b[2].b", arr);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].c", 1);
+ },
+ function(c) {
+ c.color[0] = (c.constCoords[0] + c.constCoords[1]) * 0.5;
+ c.color[1] = (c.constCoords[1] + c.constCoords[2]) * 0.5;
+ c.color[2] = (c.constCoords[2] + c.constCoords[3]) * 0.5;
+ });
+
+ UniformStructCase('sampler', "Sampler in struct", true,
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' sampler2D c;\n' +
+ '};\n' +
+ 'uniform S s;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "s.b", [0.25, 0.25, 0.5]);
+ es3fShaderStructTests.setUniform1i(programID, "s.c", 0);
+ },
+ function(c) {
+ var tex2d = c.texture2D(es3fShaderStructTests.TEXTURE_BRICK, deMath.addScalar(deMath.scale(deMath.swizzle(c.coords, [0,1]), 0.25), 0.5))
+
+ c.color[0] = tex2d[0];
+ c.color[1] = tex2d[1];
+ c.color[2] = tex2d[2];
+ });
+
+ UniformStructCase('sampler_nested', "Sampler in nested struct", true,
+ '${HEADER}\n' +
+ 'uniform int ui_zero;\n' +
+ 'uniform int ui_one;\n' +
+ '' +
+ 'struct T {\n' +
+ ' sampler2D a;\n' +
+ ' mediump vec2 b;\n' +
+ '};\n' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' T b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S s;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s.a", 0.5);
+ es3fShaderStructTests.setUniform1i(programID, "s.b.a", 0);
+ es3fShaderStructTests.setUniform2fv(programID, "s.b.b", [0.25, 0.25]);
+ es3fShaderStructTests.setUniform1i(programID, "s.c", 1);
+ },
+ function(c) {
+ var tex2d = c.texture2D(es3fShaderStructTests.TEXTURE_BRICK, deMath.addScalar(deMath.scale(deMath.swizzle(c.coords, [0,1]), 0.25), 0.5));
+ c.color[0] = tex2d[0];
+ c.color[1] = tex2d[1];
+ c.color[2] = tex2d[2];
+ });
+
+ UniformStructCase('sampler_array', "Sampler in struct array", true,
+ '${HEADER}\n' +
+ 'uniform int ui_one;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' sampler2D c;\n' +
+ '};\n' +
+ 'uniform S s[2];\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "s[0].a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "s[0].b", [0.25, 0.25, 0.25]);
+ es3fShaderStructTests.setUniform1i(programID, "s[0].c", 1);
+ es3fShaderStructTests.setUniform1f(programID, "s[1].a", 0.0);
+ es3fShaderStructTests.setUniform3fv(programID, "s[1].b", [0.5, 0.5, 0.5]);
+ es3fShaderStructTests.setUniform1i(programID, "s[1].c", 0);
+ },
+ function(c) {
+ var tex2d = c.texture2D(es3fShaderStructTests.TEXTURE_BRICK, deMath.addScalar(deMath.scale(deMath.swizzle(c.coords, [0,1]), 0.25), 0.5));
+ c.color[0] = tex2d[0];
+ c.color[1] = tex2d[1];
+ c.color[2] = tex2d[2];
+ });
+
+ UniformStructCase('equal', "Struct equality", false,
+ '${HEADER}\n' +
+ 'uniform mediump float uf_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S a;\n' +
+ 'uniform S b;\n' +
+ 'uniform S c;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);\n' +
+ ' ${DST} = vec4(0.0, 0.0, 0.0, 1.0);\n' +
+ ' if (a == b) ${DST}.x = 1.0;\n' +
+ ' if (a == c) ${DST}.y = 1.0;\n' +
+ ' if (a == d) ${DST}.z = 1.0;\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "a.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "a.b", [0.0, 1.0, 2.0]);
+ es3fShaderStructTests.setUniform1i(programID, "a.c", 2);
+ es3fShaderStructTests.setUniform1f(programID, "b.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "b.b", [0.0, 1.0, 2.0]);
+ es3fShaderStructTests.setUniform1i(programID, "b.c", 2);
+ es3fShaderStructTests.setUniform1f(programID, "c.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "c.b", [0.0, 1.1, 2.0]);
+ es3fShaderStructTests.setUniform1i(programID, "c.c", 2);
+ },
+ function(c) {
+ c.color[0] = 1.0;
+ c.color[1] = 0.0;
+ if (Math.floor(c.coords[1] + 1.0) == Math.floor(1.1))
+ c.color[2] = 1.0;
+ });
+
+ UniformStructCase('not_equal', "Struct equality", false,
+ '${HEADER}\n' +
+ 'uniform mediump float uf_one;\n' +
+ 'uniform int ui_two;\n' +
+ '' +
+ 'struct S {\n' +
+ ' mediump float a;\n' +
+ ' mediump vec3 b;\n' +
+ ' int c;\n' +
+ '};\n' +
+ 'uniform S a;\n' +
+ 'uniform S b;\n' +
+ 'uniform S c;\n' +
+ '' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);\n' +
+ ' ${DST} = vec4(0.0, 0.0, 0.0, 1.0);\n' +
+ ' if (a != b) ${DST}.x = 1.0;\n' +
+ ' if (a != c) ${DST}.y = 1.0;\n' +
+ ' if (a != d) ${DST}.z = 1.0;\n' +
+ ' ${ASSIGN_POS}\n' +
+ '}',
+ function(programID, constCoords) {
+ es3fShaderStructTests.setUniform1f(programID, "a.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "a.b", [0.0, 1.0, 2.0]);
+ es3fShaderStructTests.setUniform1i(programID, "a.c", 2);
+ es3fShaderStructTests.setUniform1f(programID, "b.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "b.b", [0.0, 1.0, 2.0]);
+ es3fShaderStructTests.setUniform1i(programID, "b.c", 2);
+ es3fShaderStructTests.setUniform1f(programID, "c.a", 1.0);
+ es3fShaderStructTests.setUniform3fv(programID, "c.b", [0.0, 1.1, 2.0]);
+ es3fShaderStructTests.setUniform1i(programID, "c.c", 2);
+ },
+ function(c) {
+ c.color[0] = 0.0;
+ c.color[1] = 1.0;
+ if (Math.floor(c.coords[1] + 1.0) != Math.floor(1.1))
+ c.color[2] = 1.0;
+ });
+
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderStructTests.ShaderStructTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'struct', 'Struct Tests');
+ };
+
+ es3fShaderStructTests.ShaderStructTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderStructTests.ShaderStructTests.prototype.constructor = es3fShaderStructTests.ShaderStructTests;
+
+ es3fShaderStructTests.ShaderStructTests.prototype.init = function() {
+ this.addChild(new es3fShaderStructTests.LocalStructTests());
+ this.addChild(new es3fShaderStructTests.UniformStructTests());
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderStructTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderStructTests.ShaderStructTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderStructTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderSwitchTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderSwitchTests.js
new file mode 100644
index 0000000000..27670f9d64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderSwitchTests.js
@@ -0,0 +1,492 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderSwitchTests');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuTestCase');
+goog.require('modules.shared.glsShaderRenderCase');
+
+
+goog.scope(function() {
+ var es3fShaderSwitchTests = functional.gles3.es3fShaderSwitchTests;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuStringTemplate = framework.common.tcuStringTemplate;
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {string} vtxSource
+ * @param {string} fragSource
+ * @param {glsShaderRenderCase.ShaderEvalFunc=} evalFunc
+ */
+ es3fShaderSwitchTests.ShaderSwitchCase = function(name, description, isVertexCase, vtxSource, fragSource, evalFunc) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
+ /** @type {string} */ this.m_vertShaderSource = vtxSource;
+ /** @type {string} */ this.m_fragShaderSource = fragSource;
+ };
+
+ es3fShaderSwitchTests.ShaderSwitchCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+ es3fShaderSwitchTests.ShaderSwitchCase.prototype.constructor = es3fShaderSwitchTests.ShaderSwitchCase;
+
+ /**
+ * @enum {number}
+ */
+ es3fShaderSwitchTests.SwitchType = {
+ STATIC: 0,
+ UNIFORM: 1,
+ DYNAMIC: 2
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */
+ es3fShaderSwitchTests.evalSwitchStatic = function(evalCtx) {
+ evalCtx.color[0] = evalCtx.coords[1];
+ evalCtx.color[1] = evalCtx.coords[2];
+ evalCtx.color[2] = evalCtx.coords[3];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */
+ es3fShaderSwitchTests.evalSwitchUniform = function(evalCtx) {
+ evalCtx.color[0] = evalCtx.coords[1];
+ evalCtx.color[1] = evalCtx.coords[2];
+ evalCtx.color[2] = evalCtx.coords[3];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */
+ es3fShaderSwitchTests.evalSwitchDynamic = function(evalCtx) {
+ switch (Math.floor(evalCtx.coords[2]*1.5 + 2.0)) {
+ case 0:
+ evalCtx.color[0] = evalCtx.coords[0];
+ evalCtx.color[1] = evalCtx.coords[1];
+ evalCtx.color[2] = evalCtx.coords[2];
+ break;
+ case 1:
+ evalCtx.color[0] = evalCtx.coords[3];
+ evalCtx.color[1] = evalCtx.coords[2];
+ evalCtx.color[2] = evalCtx.coords[1];
+ break;
+ case 2:
+ evalCtx.color[0] = evalCtx.coords[1];
+ evalCtx.color[1] = evalCtx.coords[2];
+ evalCtx.color[2] = evalCtx.coords[3];
+ break;
+ case 3:
+ evalCtx.color[0] = evalCtx.coords[2];
+ evalCtx.color[1] = evalCtx.coords[1];
+ evalCtx.color[2] = evalCtx.coords[0];
+ break;
+ default:
+ evalCtx.color[0] = evalCtx.coords[0];
+ evalCtx.color[1] = evalCtx.coords[0];
+ evalCtx.color[2] = evalCtx.coords[0];
+ break;
+ }
+ };
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fShaderSwitchTests.SwitchType} type
+ * @param {boolean} isVertex
+ * @param {string} switchBody
+ * @return {es3fShaderSwitchTests.ShaderSwitchCase}
+ */
+ es3fShaderSwitchTests.makeSwitchCase = function(name, desc, type, isVertex, switchBody) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += "#version 300 es\n" +
+ "in highp vec4 a_position;\n" +
+ "in highp vec4 a_coords;\n";
+ frag += "#version 300 es\n" +
+ "layout(location = 0) out mediump vec4 o_color;\n";
+
+ if (isVertex) {
+ vtx += "out mediump vec4 v_color;\n";
+ frag += "in mediump vec4 v_color;\n";
+ } else {
+ vtx += "out highp vec4 v_coords;\n";
+ frag += "in highp vec4 v_coords;\n";
+ }
+
+ if (type === es3fShaderSwitchTests.SwitchType.UNIFORM)
+ op += "uniform highp int ui_two;\n";
+
+ vtx += isVertex ? op : '';
+ frag += isVertex ? '' : op;
+ op = '';
+
+ vtx += "\n" +
+ "void main (void)\n" +
+ "{\n" +
+ " gl_Position = a_position;\n";
+ frag += "\n" +
+ "void main (void)\n" +
+ "{\n";
+
+ // Setup.
+ op += " highp vec4 coords = " + (isVertex ? "a_coords" : "v_coords") + ";\n";
+ op += " mediump vec3 res = vec3(0.0);\n\n";
+ vtx += isVertex ? op : '';
+ frag += isVertex ? '' : op;
+ op = '';
+
+ // Switch body.
+ var params = {};
+ params["CONDITION"] = type == es3fShaderSwitchTests.SwitchType.STATIC ? "2" :
+ type == es3fShaderSwitchTests.SwitchType.UNIFORM ? "ui_two" :
+ type == es3fShaderSwitchTests.SwitchType.DYNAMIC ? "int(floor(coords.z*1.5 + 2.0))" : "???";
+
+ op += tcuStringTemplate.specialize(switchBody, params);
+ op += "\n";
+
+ vtx += isVertex ? op : '';
+ frag += isVertex ? '' : op;
+ op = '';
+
+ if (isVertex) {
+ vtx += " v_color = vec4(res, 1.0);\n";
+ frag += " o_color = v_color;\n";
+ } else {
+ vtx += " v_coords = a_coords;\n";
+ frag += " o_color = vec4(res, 1.0);\n";
+ }
+
+ vtx += "}\n";
+ frag += "}\n";
+
+ return new es3fShaderSwitchTests.ShaderSwitchCase(name, desc, isVertex, vtx, frag,
+ type === es3fShaderSwitchTests.SwitchType.STATIC ? es3fShaderSwitchTests.evalSwitchStatic :
+ type === es3fShaderSwitchTests.SwitchType.UNIFORM ? es3fShaderSwitchTests.evalSwitchUniform :
+ type === es3fShaderSwitchTests.SwitchType.DYNAMIC ? es3fShaderSwitchTests.evalSwitchDynamic : undefined);
+ };
+
+ /**
+ * @param {tcuTestCase.DeqpTest} group
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} switchBody
+ */
+ es3fShaderSwitchTests.makeSwitchCases = function(group, name, desc, switchBody) {
+ /** @type {Array<string>} */ var switchTypeNames = ["static", "uniform", "dynamic"];
+ for (var type in es3fShaderSwitchTests.SwitchType) {
+ group.addChild(es3fShaderSwitchTests.makeSwitchCase(name + "_" + switchTypeNames[es3fShaderSwitchTests.SwitchType[type]] + "_vertex", desc, es3fShaderSwitchTests.SwitchType[type], true, switchBody));
+ group.addChild(es3fShaderSwitchTests.makeSwitchCase(name + "_" + switchTypeNames[es3fShaderSwitchTests.SwitchType[type]] + "_fragment", desc, es3fShaderSwitchTests.SwitchType[type], false, switchBody));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderSwitchTests.ShaderSwitchTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'switch', 'Switch statement tests');
+ };
+
+ es3fShaderSwitchTests.ShaderSwitchTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderSwitchTests.ShaderSwitchTests.prototype.constructor = es3fShaderSwitchTests.ShaderSwitchTests;
+
+ es3fShaderSwitchTests.ShaderSwitchTests.prototype.init = function() {
+ // Expected swizzles:
+ // 0: xyz
+ // 1: wzy
+ // 2: yzw
+ // 3: zyx
+ es3fShaderSwitchTests.makeSwitchCases(this, "basic", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2: res = coords.yzw; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "const_expr_in_label", "Constant expression in label",
+ ' const int t = 2;\n' +
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case int(0.0): res = coords.xyz; break;\n' +
+ ' case 2-1: res = coords.wzy; break;\n' +
+ ' case 3&(1<<1): res = coords.yzw; break;\n' +
+ ' case t+1: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "default_label", "Default label usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' default: res = coords.yzw;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "default_not_last", "Default label usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' default: res = coords.yzw; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "no_default_label", "No match in switch without default label",
+ ' res = coords.yzw;\n\n' +
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "fall_through", "Fall-through",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2: coords = coords.yzwx;\n' +
+ ' case 4: res = vec3(coords); break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "fall_through_default", "Fall-through",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' case 2: coords = coords.yzwx;\n' +
+ ' default: res = vec3(coords);\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "conditional_fall_through", "Fall-through",
+ ' highp vec4 tmp = coords;\n' +
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2:\n' +
+ ' tmp = coords.yzwx;\n' +
+ ' case 3:\n' +
+ ' res = vec3(tmp);\n' +
+ ' if (${CONDITION} != 3)\n' +
+ ' break;\n' +
+ ' default: res = tmp.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "conditional_fall_through_2", "Fall-through",
+ ' highp vec4 tmp = coords;\n' +
+ ' mediump int c = ${CONDITION};\n' +
+ ' switch (c)\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2:\n' +
+ ' c += ${CONDITION};\n' +
+ ' tmp = coords.yzwx;\n' +
+ ' case 3:\n' +
+ ' res = vec3(tmp);\n' +
+ ' if (c == 4)\n' +
+ ' break;\n' +
+ ' default: res = tmp.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "scope", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2:\n' +
+ ' {\n' +
+ ' mediump vec3 t = coords.yzw;\n' +
+ ' res = t;\n' +
+ ' break;\n' +
+ ' }\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_if", "Switch in for loop",
+ ' if (${CONDITION} >= 0)\n' +
+ ' {\n' +
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2: res = coords.yzw; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_for_loop", "Switch in for loop",
+ ' for (int i = 0; i <= ${CONDITION}; i++)\n' +
+ ' {\n' +
+ ' switch (i)\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2: res = coords.yzw; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_while_loop", "Switch in while loop",
+ ' int i = 0;\n' +
+ ' while (i <= ${CONDITION})\n' +
+ ' {\n' +
+ ' switch (i)\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2: res = coords.yzw; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n' +
+ ' i += 1;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_do_while_loop", "Switch in do-while loop",
+ ' int i = 0;\n' +
+ ' do\n' +
+ ' {\n' +
+ ' switch (i)\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' case 2: res = coords.yzw; break;\n' +
+ ' case 3: res = coords.zyx; break;\n' +
+ ' }\n' +
+ ' i += 1;\n' +
+ ' } while (i <= ${CONDITION});\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "if_in_switch", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1: res = coords.wzy; break;\n' +
+ ' default:\n' +
+ ' if (${CONDITION} == 2)\n' +
+ ' res = coords.yzw;\n' +
+ ' else\n' +
+ ' res = coords.zyx;\n' +
+ ' break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "for_loop_in_switch", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1:\n' +
+ ' case 2:\n' +
+ ' {\n' +
+ ' highp vec3 t = coords.yzw;\n' +
+ ' for (int i = 0; i < ${CONDITION}; i++)\n' +
+ ' t = t.zyx;\n' +
+ ' res = t;\n' +
+ ' break;\n' +
+ ' }\n' +
+ ' default: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "while_loop_in_switch", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1:\n' +
+ ' case 2:\n' +
+ ' {\n' +
+ ' highp vec3 t = coords.yzw;\n' +
+ ' int i = 0;\n' +
+ ' while (i < ${CONDITION})\n' +
+ ' {\n' +
+ ' t = t.zyx;\n' +
+ ' i += 1;\n' +
+ ' }\n' +
+ ' res = t;\n' +
+ ' break;\n' +
+ ' }\n' +
+ ' default: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "do_while_loop_in_switch", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1:\n' +
+ ' case 2:\n' +
+ ' {\n' +
+ ' highp vec3 t = coords.yzw;\n' +
+ ' int i = 0;\n' +
+ ' do\n' +
+ ' {\n' +
+ ' t = t.zyx;\n' +
+ ' i += 1;\n' +
+ ' } while (i < ${CONDITION});\n' +
+ ' res = t;\n' +
+ ' break;\n' +
+ ' }\n' +
+ ' default: res = coords.zyx; break;\n' +
+ ' }\n');
+
+ es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_switch", "Basic switch statement usage",
+ ' switch (${CONDITION})\n' +
+ ' {\n' +
+ ' case 0: res = coords.xyz; break;\n' +
+ ' case 1:\n' +
+ ' case 2:\n' +
+ ' switch (${CONDITION} - 1)\n' +
+ ' {\n' +
+ ' case 0: res = coords.wzy; break;\n' +
+ ' case 1: res = coords.yzw; break;\n' +
+ ' }\n' +
+ ' break;\n' +
+ ' default: res = coords.zyx; break;\n' +
+ '}\n');
+
+ // Negative cases.
+ // This is being tested somwhere else: data/gles3/shaders/switch.html
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderSwitchTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderSwitchTests.ShaderSwitchTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderSwitchTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderTextureFunctionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderTextureFunctionTests.js
new file mode 100644
index 0000000000..b6386c96ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderTextureFunctionTests.js
@@ -0,0 +1,2709 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderTextureFunctionTests');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('modules.shared.glsShaderRenderCase');
+
+goog.scope(function() {
+ var es3fShaderTextureFunctionTests = functional.gles3.es3fShaderTextureFunctionTests;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+
+ let canvasWH = 256;
+ if (tcuTestCase.isQuickMode()) {
+ canvasWH = 32;
+ }
+
+ /**
+ * @enum
+ */
+ es3fShaderTextureFunctionTests.TexFunction = {
+ TEXTURE: 0, //!< texture(), textureOffset()
+ TEXTUREPROJ: 1, //!< textureProj(), textureProjOffset()
+ TEXTUREPROJ3: 2, //!< textureProj(sampler2D, vec3)
+ TEXTURELOD: 3, // ...
+ TEXTUREPROJLOD: 4,
+ TEXTUREPROJLOD3: 5, //!< textureProjLod(sampler2D, vec3)
+ TEXTUREGRAD: 6,
+ TEXTUREPROJGRAD: 7,
+ TEXTUREPROJGRAD3: 8, //!< textureProjGrad(sampler2D, vec3)
+ TEXELFETCH: 9
+ };
+
+ /**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {es3fShaderTextureFunctionTests.TexFunction} function_
+ * @return {boolean}
+ */
+ es3fShaderTextureFunctionTests.functionHasAutoLod = function(shaderType, function_) {
+ return shaderType === gluShaderProgram.shaderType.FRAGMENT &&
+ (function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTURE ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3);
+ };
+
+ /**
+ * @param {es3fShaderTextureFunctionTests.TexFunction} function_
+ * @return {boolean}
+ */
+ es3fShaderTextureFunctionTests.functionHasProj = function(function_) {
+ return function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3 ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3 ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3;
+ };
+
+ /**
+ * @param {es3fShaderTextureFunctionTests.TexFunction} function_
+ * @return {boolean}
+ */
+ es3fShaderTextureFunctionTests.functionHasGrad = function(function_) {
+ return function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3;
+ };
+
+ /**
+ * @param {es3fShaderTextureFunctionTests.TexFunction} function_
+ * @return {boolean}
+ */
+ es3fShaderTextureFunctionTests.functionHasLod = function(function_) {
+ return function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3 ||
+ function_ === es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH;
+ };
+
+ /**
+ * @struct
+ * @constructor
+ * @param {es3fShaderTextureFunctionTests.TexFunction} func
+ * @param {Array<number>} minCoord
+ * @param {Array<number>} maxCoord
+ * @param {boolean} useBias
+ * @param {number} minLodBias
+ * @param {number} maxLodBias
+ * @param {Array<number>} minDX For *Grad* functions
+ * @param {Array<number>} maxDX For *Grad* functions
+ * @param {Array<number>} minDY For *Grad* functions
+ * @param {Array<number>} maxDY For *Grad* functions
+ * @param {boolean} useOffset
+ * @param {Array<number>} offset
+ */
+ es3fShaderTextureFunctionTests.TextureLookupSpec = function(func, minCoord, maxCoord, useBias, minLodBias, maxLodBias, minDX, maxDX, minDY, maxDY, useOffset, offset) {
+ /** @type {es3fShaderTextureFunctionTests.TexFunction} */ this.func = func;
+ /** @type {Array<number>} */ this.minCoord = minCoord;
+ /** @type {Array<number>} */ this.maxCoord = maxCoord;
+ // Bias
+ /** @type {boolean} */ this.useBias = useBias;
+ // Bias or Lod for *Lod* functions
+ /** @type {number} */ this.minLodBias = minLodBias;
+ /** @type {number} */ this.maxLodBias = maxLodBias;
+ // For *Grad* functions
+ /** @type {Array<number>} */ this.minDX = minDX;
+ /** @type {Array<number>} */ this.maxDX = maxDX;
+ /** @type {Array<number>} */ this.minDY = minDY;
+ /** @type {Array<number>} */ this.maxDY = maxDY;
+ /** @type {boolean} */ this.useOffset = useOffset;
+ /** @type {Array<number>} */ this.offset = offset;
+ };
+
+ /**
+ * @enum
+ */
+ es3fShaderTextureFunctionTests.TextureType = {
+ TEXTURETYPE_2D: 0,
+ TEXTURETYPE_CUBE_MAP: 1,
+ TEXTURETYPE_2D_ARRAY: 2,
+ TEXTURETYPE_3D: 3
+ };
+
+ /**
+ * @struct
+ * @constructor
+ * @param {?es3fShaderTextureFunctionTests.TextureType} type
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} numLevels
+ * @param {?tcuTexture.Sampler} sampler
+ */
+ es3fShaderTextureFunctionTests.TextureSpec = function(type, format, width, height, depth, numLevels, sampler) {
+ /** @type {?es3fShaderTextureFunctionTests.TextureType} */ this.type = type; //!< Texture type (2D, cubemap, ...)
+ /** @type {number} */ this.format = format; //!< Internal format.
+ /** @type {number} */ this.width = width;
+ /** @type {number} */ this.height = height;
+ /** @type {number} */ this.depth = depth;
+ /** @type {number} */ this.numLevels = numLevels;
+ /** @type {?tcuTexture.Sampler} */ this.sampler = sampler;
+ };
+
+ /**
+ * @struct
+ * @constructor
+ */
+ es3fShaderTextureFunctionTests.TexLookupParams = function() {
+ /** @type {number} */ this.lod = 0;
+ /** @type {Array<number>} */ this.offset = [0, 0, 0];
+ /** @type {Array<number>} */ this.scale = [1.0, 1.0, 1.0, 1.0];
+ /** @type {Array<number>} */ this.bias = [0.0, 0.0, 0.0, 0.0];
+ };
+
+ /**
+ * @enum
+ */
+ es3fShaderTextureFunctionTests.LodMode = {
+ EXACT: 0,
+ MIN_BOUND: 1,
+ MAX_BOUND: 2
+ };
+
+ /** @const {es3fShaderTextureFunctionTests.LodMode} */ es3fShaderTextureFunctionTests.DEFAULT_LOD_MODE = es3fShaderTextureFunctionTests.LodMode.EXACT;
+
+ /**
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dudy
+ * @param {number} dvdy
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromDerivates_UV = function(dudx, dvdx, dudy, dvdy) {
+ /** @type {es3fShaderTextureFunctionTests.LodMode} */ var mode = es3fShaderTextureFunctionTests.DEFAULT_LOD_MODE;
+ /** @type {number} */ var p;
+
+ switch (mode) {
+ case es3fShaderTextureFunctionTests.LodMode.EXACT:
+ p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx), Math.sqrt(dudy * dudy + dvdy * dvdy));
+ break;
+
+ case es3fShaderTextureFunctionTests.LodMode.MIN_BOUND:
+ case es3fShaderTextureFunctionTests.LodMode.MAX_BOUND:
+ /** @type {number} */ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
+ /** @type {number} */ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
+
+ p = mode === es3fShaderTextureFunctionTests.LodMode.MIN_BOUND ? Math.max(mu, mv) : mu + mv;
+ break;
+
+ default:
+ throw new Error('LOD_MODE not supported.');
+ }
+
+ return Math.log2(p);
+ };
+
+ /**
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dwdx
+ * @param {number} dudy
+ * @param {number} dvdy
+ * @param {number} dwdy
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromDerivates_UVW = function(dudx, dvdx, dwdx, dudy, dvdy, dwdy) {
+ /** @type {es3fShaderTextureFunctionTests.LodMode} */ var mode = es3fShaderTextureFunctionTests.DEFAULT_LOD_MODE;
+ /** @type {number} */ var p;
+
+ switch (mode) {
+ case es3fShaderTextureFunctionTests.LodMode.EXACT:
+ p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx + dwdx * dwdx), Math.sqrt(dudy * dudy + dvdy * dvdy + dwdy * dwdy));
+ break;
+
+ case es3fShaderTextureFunctionTests.LodMode.MIN_BOUND:
+ case es3fShaderTextureFunctionTests.LodMode.MAX_BOUND:
+ /** @type {number} */ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
+ /** @type {number} */ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
+ /** @type {number} */ var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy));
+
+ p = mode === es3fShaderTextureFunctionTests.LodMode.MIN_BOUND ? Math.max(mu, mv, mw) : (mu + mv + mw);
+ break;
+
+ default:
+ throw new Error('LOD_MODE not supported.');
+ }
+
+ return Math.log2(p);
+ };
+
+ /**
+ * [dag] Wrapper function for computeLodFromDerivates_UV or computeLodFromDerivates_UVW
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dwdxOrdudy
+ * @param {number} dudyOrdvdy
+ * @param {number=} dvdy
+ * @param {number=} dwdy
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromDerivates = function(dudx, dvdx, dwdxOrdudy, dudyOrdvdy, dvdy, dwdy) {
+ if (arguments.length === 4)
+ return es3fShaderTextureFunctionTests.computeLodFromDerivates_UV(dudx, dvdx, dwdxOrdudy, dudyOrdvdy);
+ else
+ return es3fShaderTextureFunctionTests.computeLodFromDerivates_UVW(dudx, dvdx, dwdxOrdudy, dudyOrdvdy, /** @type {number} */ (dvdy), /** @type {number} */ (dwdy));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromGrad2D = function(c) {
+ /** @type {number} */ var w = c.textures[0].tex2D.getWidth();
+ /** @type {number} */ var h = c.textures[0].tex2D.getHeight();
+ return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * w, c.in_[1][1] * h, c.in_[2][0] * w, c.in_[2][1] * h);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromGrad2DArray = function(c) {
+ /** @type {number} */ var w = c.textures[0].tex2DArray.getWidth();
+ /** @type {number} */ var h = c.textures[0].tex2DArray.getHeight();
+ return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * w, c.in_[1][1] * h, c.in_[2][0] * w, c.in_[2][1] * h);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromGrad3D = function(c) {
+ /** @type {number} */ var w = c.textures[0].tex3D.getWidth();
+ /** @type {number} */ var h = c.textures[0].tex3D.getHeight();
+ /** @type {number} */ var d = c.textures[0].tex3D.getDepth();
+ return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * w, c.in_[1][1] * h, c.in_[1][2] * d, c.in_[2][0] * w, c.in_[2][1] * h, c.in_[2][2] * d);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.computeLodFromGradCube = function(c) {
+ // \note Major axis is always -Z or +Z
+ /** @type {number} */ var m = Math.abs(c.in_[0][2]);
+ /** @type {number} */ var d = c.textures[0].texCube.getSize();
+ /** @type {number} */ var s = d / (2.0 * m);
+ /** @type {number} */ var t = d / (2.0 * m);
+ return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * s, c.in_[1][1] * t, c.in_[2][0] * s, c.in_[2][1] * t);
+ };
+
+ /** @typedef {function(glsShaderRenderCase.ShaderEvalContext, es3fShaderTextureFunctionTests.TexLookupParams)} */ es3fShaderTextureFunctionTests.TexEvalFunc;
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} lod
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.texture2D = function(c, s, t, lod) {
+ return c.textures[0].tex2D.getView().sample(c.textures[0].sampler, [s, t], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.textureCube = function(c, s, t, r, lod) {
+ return c.textures[0].texCube.getView().sample(c.textures[0].sampler, [s, t, r], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.texture2DArray = function(c, s, t, r, lod) {
+ return c.textures[0].tex2DArray.getView().sample(c.textures[0].sampler, [s, t, r], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.texture3D = function(c, s, t, r, lod) {
+ return c.textures[0].tex3D.getView().sample(c.textures[0].sampler, [s, t, r], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} lod
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.texture2DShadow = function(c, ref, s, t, lod) {
+ return c.textures[0].tex2D.getView().sampleCompare(c.textures[0].sampler, ref, [s, t], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.textureCubeShadow = function(c, ref, s, t, r, lod) {
+ return c.textures[0].texCube.getView().sampleCompare(c.textures[0].sampler, ref, [s, t, r], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.texture2DArrayShadow = function(c, ref, s, t, r, lod) {
+ return c.textures[0].tex2DArray.getView().sampleCompare(c.textures[0].sampler, ref, [s, t, r], lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.texture2DOffset = function(c, s, t, lod, offset) {
+ return c.textures[0].tex2D.getView().sampleOffset(c.textures[0].sampler, [s, t], lod, offset);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.texture2DArrayOffset = function(c, s, t, r, lod, offset) {
+ return c.textures[0].tex2DArray.getView().sampleOffset(c.textures[0].sampler, [s, t, r], lod, offset);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {Array<number>}
+ */
+ es3fShaderTextureFunctionTests.texture3DOffset = function(c, s, t, r, lod, offset) {
+ return c.textures[0].tex3D.getView().sampleOffset(c.textures[0].sampler, [s, t, r], lod, offset);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.texture2DShadowOffset = function(c, ref, s, t, lod, offset) {
+ return c.textures[0].tex2D.getView().sampleCompareOffset(c.textures[0].sampler, ref, [s, t], lod, offset);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {number} ref
+ * @param {number} s
+ * @param {number} t
+ * @param {number} r
+ * @param {number} lod
+ * @param {Array<number>} offset
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.texture2DArrayShadowOffset = function(c, ref, s, t, r, lod, offset) {
+ return c.textures[0].tex2DArray.getView().sampleCompareOffset(c.textures[0].sampler, ref, [s, t, r], lod, offset);
+ };
+
+ // Eval functions.
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2D = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], p.lod), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCube = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArray = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3D = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCubeBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProj3 = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProj3Bias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProj = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProj = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod+c.in_[1][0]), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DLod = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCubeLod = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayLod = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DLod = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjLod3 = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjLod = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0]), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjLod = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], c.in_[1][0]), p.scale), p.bias);
+ };
+
+ // Offset variants
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod, p.offset), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DOffsetBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DOffsetBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0], p.offset), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DLodOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DLodOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0], p.offset), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProj3Offset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod, p.offset), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod+c.in_[1][0], p.offset), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], c.in_[1][0], p.offset), p.scale), p.bias);
+ };
+
+ // Shadow variants
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadow = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod);
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowBias = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0]);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCubeShadow = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.textureCubeShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod);
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCubeShadowBias = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.textureCubeShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayShadow = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DArrayShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowLod = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], c.in_[1][0]);
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowLodOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProj = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod);
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjBias = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0]);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjLod = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0]);
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjLodOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod, deMath.swizzle(p.offset, [0,1]));
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowOffsetBias = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod, deMath.swizzle(p.offset, [0,1]));
+ };
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffsetBias = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
+ };
+
+ // Gradient variarts
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DGrad = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c)), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCubeGrad = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGradCube(c)), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayGrad = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c)), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DGrad = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c)), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowGrad = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTextureCubeShadowGrad = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.textureCubeShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGradCube(c));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGrad = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DArrayShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c));
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DGradOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DGradOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c), p.offset), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowGradOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1]));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGradOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DArrayShadowOffset(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c), deMath.swizzle(p.offset, [0,1]));
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjGrad = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c));
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DShadowProjGradOffset = function(c, p) {
+ c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1]));
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjGrad3 = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c)), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjGrad = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c)), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjGrad = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c)), p.scale), p.bias);
+ };
+
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset = function(c, p) {
+ c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c), p.offset), p.scale), p.bias);
+ };
+
+ // Texel fetch variants
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexelFetch2D = function(c, p) {
+ /** @type {number} */ var x = Math.trunc(c.in_[0][0]) + p.offset[0];
+ /** @type {number} */ var y = Math.trunc(c.in_[0][1]) + p.offset[1];
+ /** @type {number} */ var lod = Math.trunc(c.in_[1][0]);
+ c.color = deMath.add(deMath.multiply(c.textures[0].tex2D.getLevel(lod).getPixel(x, y), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexelFetch2DArray = function(c, p) {
+ /** @type {number} */ var x = Math.trunc(c.in_[0][0]) + p.offset[0];
+ /** @type {number} */ var y = Math.trunc(c.in_[0][1]) + p.offset[1];
+ /** @type {number} */ var l = Math.trunc(c.in_[0][2]);
+ /** @type {number} */ var lod = Math.trunc(c.in_[1][0]);
+ c.color = deMath.add(deMath.multiply(c.textures[0].tex2DArray.getLevel(lod).getPixel(x, y, l), p.scale), p.bias);
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
+ */
+ es3fShaderTextureFunctionTests.evalTexelFetch3D = function(c, p) {
+ /** @type {number} */ var x = Math.trunc(c.in_[0][0]) + p.offset[0];
+ /** @type {number} */ var y = Math.trunc(c.in_[0][1]) + p.offset[1];
+ /** @type {number} */ var z = Math.trunc(c.in_[0][2]) + p.offset[2];
+ /** @type {number} */ var lod = Math.trunc(c.in_[1][0]);
+ c.color = deMath.add(deMath.multiply(c.textures[0].tex3D.getLevel(lod).getPixel(x, y, z), p.scale), p.bias);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderEvaluator}
+ * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
+ * @param {es3fShaderTextureFunctionTests.TexLookupParams} lookupParams
+ */
+ es3fShaderTextureFunctionTests.TexLookupEvaluator = function(evalFunc, lookupParams) {
+ /** @type {es3fShaderTextureFunctionTests.TexEvalFunc} */ this.m_evalFunc = evalFunc;
+ /** @type {es3fShaderTextureFunctionTests.TexLookupParams} */ this.m_lookupParams = lookupParams;
+ };
+
+ es3fShaderTextureFunctionTests.TexLookupEvaluator.prototype = Object.create(glsShaderRenderCase.ShaderEvaluator.prototype);
+ es3fShaderTextureFunctionTests.TexLookupEvaluator.prototype.constructor = es3fShaderTextureFunctionTests.TexLookupEvaluator;
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} ctx
+ */
+ es3fShaderTextureFunctionTests.TexLookupEvaluator.prototype.evaluate = function(ctx) {
+ this.m_evalFunc(ctx, this.m_lookupParams);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {es3fShaderTextureFunctionTests.TextureLookupSpec} lookup
+ * @param {es3fShaderTextureFunctionTests.TextureSpec} texture
+ * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
+ * @param {boolean} isVertexCase
+ */
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase = function(name, desc, lookup, texture, evalFunc, isVertexCase) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, desc, isVertexCase);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureLookupSpec} */ this.m_lookupSpec = lookup;
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.m_textureSpec = texture;
+ /** @type {es3fShaderTextureFunctionTests.TexLookupParams} */ this.m_lookupParams = new es3fShaderTextureFunctionTests.TexLookupParams();
+ /** @type {es3fShaderTextureFunctionTests.TexLookupEvaluator} */ this.m_evaluator = new es3fShaderTextureFunctionTests.TexLookupEvaluator(evalFunc, this.m_lookupParams);
+
+ /** @type {gluTexture.Texture2D} */ this.m_texture2D = null;
+ /** @type {gluTexture.TextureCube} */ this.m_textureCube = null;
+ /** @type {gluTexture.Texture2DArray} */ this.m_texture2DArray = null;
+ /** @type {gluTexture.Texture3D} */ this.m_texture3D = null;
+ };
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.constructor = es3fShaderTextureFunctionTests.ShaderTextureFunctionCase;
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.init = function() {
+
+ // Base coord scale & bias
+ /** @type {(Array<number>|number)} */ var s = deMath.subtract(this.m_lookupSpec.maxCoord, this.m_lookupSpec.minCoord);
+ /** @type {(Array<number>|number)} */ var b = this.m_lookupSpec.minCoord;
+
+ /** @type {Array<number>} */ var baseCoordTrans = [
+ s[0], 0.0, 0.0, b[0],
+ 0.0, s[1], 0., b[1],
+ s[2]/2.0, -s[2]/2.0, 0.0, s[2]/2.0 + b[2],
+ -s[3]/2.0, s[3]/2.0, 0.0, s[3]/2.0 + b[3]
+ ];
+ this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, baseCoordTrans));
+
+ /** @type {boolean} */ var hasLodBias = es3fShaderTextureFunctionTests.functionHasLod(this.m_lookupSpec.func) || this.m_lookupSpec.useBias;
+ /** @type {boolean} */ var isGrad = es3fShaderTextureFunctionTests.functionHasGrad(this.m_lookupSpec.func);
+ assertMsgOptions(!isGrad || !hasLodBias, 'Assert Error. expected: isGrad || hasLodBias === false', false, true);
+
+ if (hasLodBias) {
+ s = this.m_lookupSpec.maxLodBias - this.m_lookupSpec.minLodBias;
+ b = this.m_lookupSpec.minLodBias;
+ /** @type {Array<number>} */ var lodCoordTrans = [
+ s/2.0, s/2.0, 0.0, b,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0
+ ];
+
+ this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, lodCoordTrans));
+ }
+ else if (isGrad) {
+ /** @type {Array<number>} */ var sx = deMath.subtract(this.m_lookupSpec.maxDX, this.m_lookupSpec.minDX);
+ /** @type {Array<number>} */ var sy = deMath.subtract(this.m_lookupSpec.maxDY, this.m_lookupSpec.minDY);
+ /** @type {Array<number>} */ var gradDxTrans = [
+ sx[0]/2.0, sx[0]/2.0, 0.0, this.m_lookupSpec.minDX[0],
+ sx[1]/2.0, sx[1]/2.0, 0.0, this.m_lookupSpec.minDX[1],
+ sx[2]/2.0, sx[2]/2.0, 0.0, this.m_lookupSpec.minDX[2],
+ 0.0, 0.0, 0.0, 0.0
+ ];
+ /** @type {Array<number>} */ var gradDyTrans = [
+ -sy[0]/2.0, -sy[0]/2.0, 0.0, this.m_lookupSpec.maxDY[0],
+ -sy[1]/2.0, -sy[1]/2.0, 0.0, this.m_lookupSpec.maxDY[1],
+ -sy[2]/2.0, -sy[2]/2.0, 0.0, this.m_lookupSpec.maxDY[2],
+ 0.0, 0.0, 0.0, 0.0
+ ];
+
+ this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, gradDxTrans));
+ this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, gradDyTrans));
+ }
+
+ this.initShaderSources();
+ this.initTexture();
+
+ this.postinit();
+
+ };
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.initTexture = function() {
+ /** @type {Array<Array<number>>} */ var texCubeSwz = [
+ [0, 0, 1, 1],
+ [1, 1, 0, 0],
+ [0, 1, 0, 1],
+ [1, 0, 1, 0],
+ [0, 1, 1, 0],
+ [1, 0, 0, 1]
+ ];
+
+ assertMsgOptions(texCubeSwz.length === 6, 'Cube should have 6 faces.', false, true);
+
+ /** @type {number} */ var levelStep;
+ /** @type {Array<number>} */ var cScale;
+ /** @type {Array<number>} */ var cBias;
+ /** @type {number} */ var baseCellSize;
+
+ /** @type {number} */ var fA;
+ /** @type {number} */ var fB;
+ /** @type {Array<number>} */ var colorA;
+ /** @type {Array<number>} */ var colorB;
+
+ /** @type {number} */ var dudx;
+ /** @type {number} */ var dvdy;
+
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_textureSpec.format);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ /** @type {Array<number>} */ var viewportSize = this.getViewportSize();
+ /** @type {boolean} */ var isProj = es3fShaderTextureFunctionTests.functionHasProj(this.m_lookupSpec.func);
+ /** @type {boolean} */ var isAutoLod = es3fShaderTextureFunctionTests.functionHasAutoLod(
+ this.m_isVertexCase ? gluShaderProgram.shaderType.VERTEX : gluShaderProgram.shaderType.FRAGMENT,
+ this.m_lookupSpec.func); // LOD can vary significantly
+ /** @type {number} */ var proj = isProj ?
+ 1.0 / this.m_lookupSpec.minCoord[this.m_lookupSpec.func === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3 ? 2 : 3] :
+ 1.0;
+
+ switch (this.m_textureSpec.type) {
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
+ levelStep = isAutoLod ? 0.0 : 1.0 / Math.max(1, this.m_textureSpec.numLevels - 1);
+ cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
+ cBias = fmtInfo.valueMin;
+ baseCellSize = Math.min(this.m_textureSpec.width / 4, this.m_textureSpec.height / 4);
+
+ this.m_texture2D = gluTexture.texture2DFromInternalFormat(gl, this.m_textureSpec.format, this.m_textureSpec.width, this.m_textureSpec.height);
+ for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
+ fA = level * levelStep;
+ fB = 1.0 - fA;
+ colorA = deMath.add(cBias, deMath.multiply(cScale, [fA, fB, fA, fB]));
+ colorB = deMath.add(cBias, deMath.multiply(cScale, [fB, fA, fB, fA]));
+
+ this.m_texture2D.getRefTexture().allocLevel(level);
+ tcuTextureUtil.fillWithGrid(this.m_texture2D.getRefTexture().getLevel(level), Math.max(1, baseCellSize >> level), colorA, colorB);
+ }
+ this.m_texture2D.upload();
+
+ // Compute LOD.
+ dudx = (this.m_lookupSpec.maxCoord[0] - this.m_lookupSpec.minCoord[0]) * proj * this.m_textureSpec.width / viewportSize[0];
+ dvdy = (this.m_lookupSpec.maxCoord[1] - this.m_lookupSpec.minCoord[1]) * proj * this.m_textureSpec.height / viewportSize[1];
+ this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, 0.0, dvdy);
+
+ // Append to texture list.
+ this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_texture2D, this.m_textureSpec.sampler));
+ break;
+
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
+ levelStep = isAutoLod ? 0.0 : 1.0 / Math.max(1, this.m_textureSpec.numLevels - 1);
+ cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
+ cBias = fmtInfo.valueMin;
+ /** @type {Array<number>} */ var cCorner = deMath.add(cBias, deMath.scale(cScale, 0.5));
+ baseCellSize = Math.min(this.m_textureSpec.width / 4, this.m_textureSpec.height / 4);
+
+ assertMsgOptions(this.m_textureSpec.width === this.m_textureSpec.height, 'Expected width === height', false, true);
+ this.m_textureCube = gluTexture.cubeFromInternalFormat(gl, this.m_textureSpec.format, this.m_textureSpec.width);
+ for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
+ fA = level * levelStep;
+ fB = 1.0 - fA;
+ /** @type {Array<number>} */ var f = [fA, fB];
+
+ for (var face = 0; face < 6; face++) {
+ /** @type {Array<number>} */ var swzA = texCubeSwz[face];
+ /** @type {Array<number>} */ var swzB = deMath.subtract([1, 1, 1, 1], swzA);
+ colorA = deMath.add(cBias, deMath.multiply(cScale, deMath.swizzle(f, [swzA[0], swzA[1], swzA[2], swzA[3]])));
+ colorB = deMath.add(cBias, deMath.multiply(cScale, deMath.swizzle(f, [swzB[0], swzB[1], swzB[2], swzB[3]])));
+
+ this.m_textureCube.getRefTexture().allocLevel(face, level);
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var access = this.m_textureCube.getRefTexture().getLevelFace(level, face);
+ /** @type {number} */ var lastPix = access.getWidth() - 1;
+
+ tcuTextureUtil.fillWithGrid(access, Math.max(1, baseCellSize >> level), colorA, colorB);
+
+ // Ensure all corners have identical colors in order to avoid dealing with ambiguous corner texel filtering
+ access.setPixel(cCorner, 0, 0);
+ access.setPixel(cCorner, 0, lastPix);
+ access.setPixel(cCorner, lastPix, 0);
+ access.setPixel(cCorner, lastPix, lastPix);
+ }
+ }
+ this.m_textureCube.upload();
+
+ // Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
+ assertMsgOptions(Math.abs(this.m_lookupSpec.minCoord[2] - this.m_lookupSpec.maxCoord[2]) < 0.005, 'Expected abs(minCoord-maxCoord) < 0.005', false, true);
+ assertMsgOptions(Math.abs(this.m_lookupSpec.minCoord[0]) < Math.abs(this.m_lookupSpec.minCoord[2]) && Math.abs(this.m_lookupSpec.maxCoord[0]) < Math.abs(this.m_lookupSpec.minCoord[2]), 'Assert error: minCoord, maxCoord', false, true);
+ assertMsgOptions(Math.abs(this.m_lookupSpec.minCoord[1]) < Math.abs(this.m_lookupSpec.minCoord[2]) && Math.abs(this.m_lookupSpec.maxCoord[1]) < Math.abs(this.m_lookupSpec.minCoord[2]), 'Assert error: minCoord, maxCoord', false, true);
+
+ /** @type {tcuTexture.CubeFaceCoords} */ var c00 = tcuTexture.getCubeFaceCoords([this.m_lookupSpec.minCoord[0] * proj, this.m_lookupSpec.minCoord[1] * proj, this.m_lookupSpec.minCoord[2] * proj]);
+ /** @type {tcuTexture.CubeFaceCoords} */ var c10 = tcuTexture.getCubeFaceCoords([this.m_lookupSpec.maxCoord[0] * proj, this.m_lookupSpec.minCoord[1] * proj, this.m_lookupSpec.minCoord[2] * proj]);
+ /** @type {tcuTexture.CubeFaceCoords} */ var c01 = tcuTexture.getCubeFaceCoords([this.m_lookupSpec.minCoord[0] * proj, this.m_lookupSpec.maxCoord[1] * proj, this.m_lookupSpec.minCoord[2] * proj]);
+ dudx = (c10.s - c00.s) * this.m_textureSpec.width / viewportSize[0];
+ dvdy = (c01.t - c00.t) * this.m_textureSpec.height / viewportSize[1];
+
+ this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, 0.0, dvdy);
+
+ this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_textureCube, this.m_textureSpec.sampler));
+ break;
+
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
+ /** @type {number} */ var layerStep = 1.0 / this.m_textureSpec.depth;
+ levelStep = isAutoLod ? 0.0 : 1.0 / (Math.max(1, this.m_textureSpec.numLevels - 1) * this.m_textureSpec.depth);
+ cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
+ cBias = fmtInfo.valueMin;
+ baseCellSize = Math.min(this.m_textureSpec.width / 4, this.m_textureSpec.height / 4);
+
+ this.m_texture2DArray = gluTexture.texture2DArrayFromInternalFormat(gl,
+ this.m_textureSpec.format,
+ this.m_textureSpec.width,
+ this.m_textureSpec.height,
+ this.m_textureSpec.depth);
+
+ for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
+ this.m_texture2DArray.getRefTexture().allocLevel(level);
+ /** @type {tcuTexture.PixelBufferAccess} */ var levelAccess = this.m_texture2DArray.getRefTexture().getLevel(level);
+
+ for (var layer = 0; layer < levelAccess.getDepth(); layer++) {
+ fA = layer * layerStep + level * levelStep;
+ fB = 1.0 - fA;
+ colorA = deMath.add(cBias, deMath.multiply(cScale, [fA, fB, fA, fB]));
+ colorB = deMath.add(cBias, deMath.multiply(cScale, [fB, fA, fB, fA]));
+
+ tcuTextureUtil.fillWithGrid(tcuTextureUtil.getSubregion(levelAccess, 0, 0, layer, levelAccess.getWidth(), levelAccess.getHeight(), 1), Math.max(1, baseCellSize >> level), colorA, colorB);
+ }
+ }
+ this.m_texture2DArray.upload();
+
+ // Compute LOD.
+ dudx = (this.m_lookupSpec.maxCoord[0] - this.m_lookupSpec.minCoord[0]) * proj * this.m_textureSpec.width / viewportSize[0];
+ dvdy = (this.m_lookupSpec.maxCoord[1] - this.m_lookupSpec.minCoord[1]) * proj * this.m_textureSpec.height / viewportSize[1];
+ this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, 0.0, dvdy);
+
+ // Append to texture list.
+ this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_texture2DArray, this.m_textureSpec.sampler));
+ break;
+
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
+ levelStep = isAutoLod ? 0.0 : 1.0 / Math.max(1, this.m_textureSpec.numLevels - 1);
+ cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
+ cBias = fmtInfo.valueMin;
+ baseCellSize = Math.min(this.m_textureSpec.width / 2, this.m_textureSpec.height / 2, this.m_textureSpec.depth / 2);
+
+ this.m_texture3D = gluTexture.texture3DFromInternalFormat(gl, this.m_textureSpec.format, this.m_textureSpec.width, this.m_textureSpec.height, this.m_textureSpec.depth);
+ for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
+ fA = level * levelStep;
+ fB = 1.0 - fA;
+ colorA = deMath.add(cBias, deMath.multiply(cScale, [fA, fB, fA, fB]));
+ colorB = deMath.add(cBias, deMath.multiply(cScale, [fB, fA, fB, fA]));
+
+ this.m_texture3D.getRefTexture().allocLevel(level);
+ tcuTextureUtil.fillWithGrid(this.m_texture3D.getRefTexture().getLevel(level), Math.max(1, baseCellSize >> level), colorA, colorB);
+ }
+ this.m_texture3D.upload();
+
+ // Compute LOD.
+ dudx = (this.m_lookupSpec.maxCoord[0] - this.m_lookupSpec.minCoord[0]) * proj * this.m_textureSpec.width / viewportSize[0];
+ dvdy = (this.m_lookupSpec.maxCoord[1] - this.m_lookupSpec.minCoord[1]) * proj * this.m_textureSpec.height / viewportSize[1];
+ /** @type {number} */ var dwdx = (this.m_lookupSpec.maxCoord[2] - this.m_lookupSpec.minCoord[2]) * 0.5 * proj * this.m_textureSpec.depth / viewportSize[0];
+ /** @type {number} */ var dwdy = (this.m_lookupSpec.maxCoord[2] - this.m_lookupSpec.minCoord[2]) * 0.5 * proj * this.m_textureSpec.depth / viewportSize[1];
+ this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, dwdx, 0.0, dvdy, dwdy);
+
+ // Append to texture list.
+ this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_texture3D, this.m_textureSpec.sampler));
+ break;
+
+ default:
+ throw new Error('Texture type not supported.');
+ }
+
+ // Set lookup scale & bias
+ this.m_lookupParams.scale = fmtInfo.lookupScale;
+ this.m_lookupParams.bias = fmtInfo.lookupBias;
+ this.m_lookupParams.offset = this.m_lookupSpec.offset;
+ };
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.initShaderSources = function() {
+ /** @type {es3fShaderTextureFunctionTests.TexFunction} */ var function_ = this.m_lookupSpec.func;
+ /** @type {boolean} */ var isVtxCase = this.m_isVertexCase;
+ /** @type {boolean} */ var isProj = es3fShaderTextureFunctionTests.functionHasProj(function_);
+ /** @type {boolean} */ var isGrad = es3fShaderTextureFunctionTests.functionHasGrad(function_);
+ /** @type {boolean} */ var isShadow = this.m_textureSpec.sampler.compare !== tcuTexture.CompareMode.COMPAREMODE_NONE;
+ /** @type {boolean} */ var is2DProj4 = !isShadow && this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D && (function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ || function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD || function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD);
+ /** @type {boolean} */ var isIntCoord = function_ === es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH;
+ /** @type {boolean} */ var hasLodBias = es3fShaderTextureFunctionTests.functionHasLod(this.m_lookupSpec.func) || this.m_lookupSpec.useBias;
+ /** @type {number} */ var texCoordComps = this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D ? 2 : 3;
+ /** @type {number} */ var extraCoordComps = (isProj ? (is2DProj4 ? 2 : 1) : 0) + (isShadow ? 1 : 0);
+ /** @type {gluShaderUtil.DataType} */ var coordType = gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.FLOAT, texCoordComps+extraCoordComps);
+ /** @type {gluShaderUtil.precision} */ var coordPrec = gluShaderUtil.precision.PRECISION_HIGHP;
+ /** @type {string} */ var coordTypeName = gluShaderUtil.getDataTypeName(coordType);
+ /** @type {string} */ var coordPrecName = gluShaderUtil.getPrecisionName(coordPrec);
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_textureSpec.format);
+ /** @type {?gluShaderUtil.DataType} */ var samplerType = null;
+ /** @type {gluShaderUtil.DataType} */ var gradType = (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP || this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D) ? gluShaderUtil.DataType.FLOAT_VEC3 : gluShaderUtil.DataType.FLOAT_VEC2;
+ /** @type {string} */ var gradTypeName = gluShaderUtil.getDataTypeName(gradType);
+ /** @type {string} */ var baseFuncName = '';
+
+ assertMsgOptions(!isGrad || !hasLodBias, 'Expected !isGrad || !hasLodBias', false, true);
+
+ switch (this.m_textureSpec.type) {
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
+ samplerType = isShadow ? gluShaderUtil.DataType.SAMPLER_2D_SHADOW : gluTextureUtil.getSampler2DType(texFmt);
+ break;
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
+ samplerType = isShadow ? gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW : gluTextureUtil.getSamplerCubeType(texFmt);
+ break;
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
+ samplerType = isShadow ? gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW : gluTextureUtil.getSampler2DArrayType(texFmt);
+ break;
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
+ assertMsgOptions(!isShadow, 'Expected !isShadow', false, true);
+ samplerType = gluTextureUtil.getSampler3DType(texFmt);
+ break;
+ default:
+ throw new Error('Unexpected type.');
+ }
+
+ switch (this.m_lookupSpec.func) {
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTURE: baseFuncName = 'texture'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ: baseFuncName = 'textureProj'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3: baseFuncName = 'textureProj'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD: baseFuncName = 'textureLod'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD: baseFuncName = 'textureProjLod'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3: baseFuncName = 'textureProjLod'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD: baseFuncName = 'textureGrad'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD: baseFuncName = 'textureProjGrad'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3: baseFuncName = 'textureProjGrad'; break;
+ case es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH: baseFuncName = 'texelFetch'; break;
+ default:
+ throw new Error('Unexpected function.');
+ }
+
+ /** @type {string} */ var vert = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vert += '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'in ' + coordPrecName + ' ' + coordTypeName + ' a_in0;\n';
+
+ if (isGrad) {
+ vert += 'in ' + coordPrecName + ' ' + gradTypeName + ' a_in1;\n';
+ vert += 'in ' + coordPrecName + ' ' + gradTypeName + ' a_in2;\n';
+ }
+ else if (hasLodBias)
+ vert += 'in ' + coordPrecName + ' float a_in1;\n';
+
+ frag += '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (isVtxCase) {
+ vert += 'out mediump vec4 v_color;\n';
+ frag += 'in mediump vec4 v_color;\n';
+ }
+ else
+ {
+ vert += 'out ' + coordPrecName + ' ' + coordTypeName + ' v_texCoord;\n';
+ frag += 'in ' + coordPrecName + ' ' + coordTypeName + ' v_texCoord;\n';
+
+ if (isGrad) {
+ vert += 'out ' + coordPrecName + ' ' + gradTypeName + ' v_gradX;\n';
+ vert += 'out ' + coordPrecName + ' ' + gradTypeName + ' v_gradY;\n';
+ frag += 'in ' + coordPrecName + ' ' + gradTypeName + ' v_gradX;\n';
+ frag += 'in ' + coordPrecName + ' ' + gradTypeName + ' v_gradY;\n';
+ }
+
+ if (hasLodBias) {
+ vert += 'out ' + coordPrecName + ' float v_lodBias;\n';
+ frag += 'in ' + coordPrecName + ' float v_lodBias;\n';
+ }
+ }
+
+ // Uniforms
+ op += 'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler;\n' +
+ 'uniform highp vec4 u_scale;\n' +
+ 'uniform highp vec4 u_bias;\n';
+
+ vert += isVtxCase ? op : '';
+ frag += isVtxCase ? '' : op;
+ op = '';
+
+ vert += '\nvoid main()\n{\n' +
+ '\tgl_Position = a_position;\n';
+ frag += '\nvoid main()\n{\n';
+
+ if (isVtxCase)
+ vert += '\tv_color = ';
+ else
+ frag += '\to_color = ';
+
+ // Op.
+ /** @type {string} */ var texCoord = isVtxCase ? 'a_in0' : 'v_texCoord';
+ /** @type {string} */ var gradX = isVtxCase ? 'a_in1' : 'v_gradX';
+ /** @type {string} */ var gradY = isVtxCase ? 'a_in2' : 'v_gradY';
+ /** @type {string} */ var lodBias = isVtxCase ? 'a_in1' : 'v_lodBias';
+
+ op += 'vec4(' + baseFuncName;
+ if (this.m_lookupSpec.useOffset)
+ op += 'Offset';
+ op += '(u_sampler, ';
+
+ if (isIntCoord)
+ op += 'ivec' + (texCoordComps+extraCoordComps) + '(';
+
+ op += texCoord;
+
+ if (isIntCoord)
+ op += ')';
+
+ if (isGrad)
+ op += ', ' + gradX + ', ' + gradY;
+
+ if (es3fShaderTextureFunctionTests.functionHasLod(function_)) {
+ if (isIntCoord)
+ op += ', int(' + lodBias + ')';
+ else
+ op += ', ' + lodBias;
+ }
+
+ if (this.m_lookupSpec.useOffset) {
+ /** @type {number} */ var offsetComps = this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D ? 3 : 2;
+
+ op += ', ivec' + offsetComps + '(';
+ for (var ndx = 0; ndx < offsetComps; ndx++) {
+ if (ndx !== 0)
+ op += ', ';
+ op += this.m_lookupSpec.offset[ndx];
+ }
+ op += ')';
+ }
+
+ if (this.m_lookupSpec.useBias)
+ op += ', ' + lodBias;
+
+ op += ')';
+
+ if (isShadow)
+ op += ', 0.0, 0.0, 1.0)';
+ else
+ op += ')*u_scale + u_bias';
+
+ op += ';\n';
+
+ vert += isVtxCase ? op : '';
+ frag += isVtxCase ? '' : op;
+ op = '';
+
+ if (isVtxCase)
+ frag += '\to_color = v_color;\n';
+ else {
+ vert += '\tv_texCoord = a_in0;\n';
+
+ if (isGrad) {
+ vert += '\tv_gradX = a_in1;\n';
+ vert += '\tv_gradY = a_in2;\n';
+ }
+ else if (hasLodBias)
+ vert += '\tv_lodBias = a_in1;\n';
+ }
+
+ vert += '}\n';
+ frag += '}\n';
+
+ this.m_vertShaderSource = vert;
+ this.m_fragShaderSource = frag;
+ };
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.deinit = function() {
+ this.m_program = null;
+ this.m_texture2D = null;
+ this.m_textureCube = null;
+ this.m_texture2DArray = null;
+ this.m_texture3D = null;
+ };
+
+ /**
+ * @param {WebGLProgram} programID
+ * @param {Array<number>} constCoords
+ */
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.setupUniforms = function(programID, constCoords) {
+ gl.uniform1i(gl.getUniformLocation(programID, 'u_sampler'), 0);
+ gl.uniform4fv(gl.getUniformLocation(programID, 'u_scale'), this.m_lookupParams.scale);
+ gl.uniform4fv(gl.getUniformLocation(programID, 'u_bias'), this.m_lookupParams.bias);
+ };
+
+
+ /**
+ * @struct
+ * @constructor
+ * @param {Array<number>} textureSize
+ * @param {number} lod
+ * @param {number} lodBase
+ * @param {Array<number>} expectedSize
+ */
+ es3fShaderTextureFunctionTests.TestSize = function(textureSize, lod, lodBase, expectedSize) {
+ /** @type {Array<number>} */ this.textureSize = textureSize;
+ /** @type {number} */ this.lod = lod;
+ /** @type {number} */ this.lodBase = lodBase;
+ /** @type {Array<number>} */ this.expectedSize = expectedSize;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {string} samplerType
+ * @param {es3fShaderTextureFunctionTests.TextureSpec} texture
+ * @param {boolean} isVertexCase
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase = function(name, desc, samplerType, texture, isVertexCase) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /** @type {string} */ this.m_samplerTypeStr = samplerType;
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.m_textureSpec = texture;
+ /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
+ /** @type {boolean} */ this.m_has3DSize = texture.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D || texture.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY;
+ /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {number} */ this.m_iterationCounter = 0;
+ };
+
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.constructor = es3fShaderTextureFunctionTests.TextureSizeCase;
+
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.deinit = function() {
+ this.freeShader();
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.iterate = function() {
+ /** @type {number} */ var currentIteration = this.m_iterationCounter++;
+ /** @type {Array<es3fShaderTextureFunctionTests.TestSize>} */ var testSizes = [
+ new es3fShaderTextureFunctionTests.TestSize([1, 2, 1], 1, 0, [1, 1, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([1, 2, 1], 0, 0, [1, 2, 1]),
+
+ new es3fShaderTextureFunctionTests.TestSize([1, 3, 2], 0, 0, [1, 3, 2]),
+ new es3fShaderTextureFunctionTests.TestSize([1, 3, 2], 1, 0, [1, 1, 1]),
+
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 0, 0, [100, 31, 18]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 1, 0, [50, 15, 9]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 2, 0, [25, 7, 4]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 3, 0, [12, 3, 2]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 4, 0, [6, 1, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 5, 0, [3, 1, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 6, 0, [1, 1, 1]),
+
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 0, 0, [100, 128, 32]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 1, 0, [50, 64, 16]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 2, 0, [25, 32, 8]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 3, 0, [12, 16, 4]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 4, 0, [6, 8, 2]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 5, 0, [3, 4, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 6, 0, [1, 2, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 7, 0, [1, 1, 1]),
+
+ // pow 2
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 0, 0, [128, 64, 32]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 1, 0, [64, 32, 16]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 2, 0, [32, 16, 8]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 3, 0, [16, 8, 4]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 4, 0, [8, 4, 2]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 5, 0, [4, 2, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 6, 0, [2, 1, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 7, 0, [1, 1, 1]),
+
+ // w === h
+ new es3fShaderTextureFunctionTests.TestSize([1, 1, 1], 0, 0, [1, 1, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 0, 0, [64, 64, 64]),
+ new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 1, 0, [32, 32, 32]),
+ new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 2, 0, [16, 16, 16]),
+ new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 3, 0, [8, 8, 8]),
+ new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 4, 0, [4, 4, 4]),
+
+ // with lod base
+ new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 3, 1, [6, 1, 1]),
+ new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 3, 1, [8, 4, 2]),
+ new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 1, 1, [16, 16, 16])
+
+ ];
+ /** @type {number} */ var lastIterationIndex = testSizes.length + 1;
+
+ if (currentIteration === 0) {
+ return this.initShader() ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ }
+ else if (currentIteration === lastIterationIndex) {
+ this.freeShader();
+ return tcuTestCase.IterateResult.STOP;
+ }
+ else {
+ if (!this.testTextureSize(testSizes[currentIteration - 1]))
+ testFailedOptions('Fail: Case ' + (currentIteration - 1) + ' Got unexpected texture size', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.CONTINUE;
+ }
+ };
+
+ /**
+ * @return {boolean}
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.initShader = function() {
+ /** @type {string} */ var vertSrc = this.genVertexShader();
+ /** @type {string} */ var fragSrc = this.genFragmentShader();
+
+ assertMsgOptions(this.m_program === null, 'Program should be null', false, true);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertSrc, fragSrc));
+
+ if (!this.m_program.isOk()) {
+ testFailedOptions('Fail: Shader failed', false);
+ return false;
+ }
+
+ return true;
+ };
+
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.freeShader = function() {
+ this.m_program = null;
+ };
+
+ /**
+ * @param {es3fShaderTextureFunctionTests.TestSize} testSize
+ * @return {boolean}
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.testTextureSize = function(testSize) {
+ /** @type {Array<number>} */ var triangle = [ // covers entire viewport
+ -1, -1, 0, 1, // was a 3x4 matrix
+ 4, -1, 0, 1,
+ -1, 4, 0, 1
+ ];
+
+ /** @type {number} */ var positionLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ /** @type {WebGLUniformLocation} */ var samplerLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_sampler');
+ /** @type {WebGLUniformLocation} */ var sizeLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_texSize');
+ /** @type {WebGLUniformLocation} */ var lodLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_lod');
+ /** @type {number} */ var textureTarget = this.getGLTextureTarget();
+ /** @type {boolean} */ var isSquare = testSize.textureSize[0] === testSize.textureSize[1];
+ /** @type {boolean} */ var is2DLodValid = (testSize.textureSize[0] >> (testSize.lod + testSize.lodBase)) !== 0 || (testSize.textureSize[1] >> (testSize.lod + testSize.lodBase)) !== 0;
+ /** @type {boolean} */ var success = true;
+ /** @type {number} */ var errorValue;
+
+ // Skip incompatible cases
+ if (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP && !isSquare)
+ return true;
+ if (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D && !is2DLodValid)
+ return true;
+ if (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY && !is2DLodValid)
+ return true;
+
+ // setup rendering
+ gl.useProgram(this.m_program.getProgram());
+ gl.uniform1i(samplerLoc, 0);
+ gl.clearColor(0.5, 0.5, 0.5, 1.0);
+ gl.viewport(0, 0, 1, 1);
+
+ /** @type {WebGLBuffer} */ var triangleGlBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, triangleGlBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangle), gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(positionLoc);
+
+ // setup texture
+ /** @type {number} */ var maxLevel = testSize.lod + testSize.lodBase;
+ /** @type {number} */ var levels = maxLevel + 1;
+ /** @type {?WebGLTexture} */ var texId = null;
+
+ // gen texture
+ texId = gl.createTexture();
+ gl.bindTexture(textureTarget, texId);
+ gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(textureTarget, gl.TEXTURE_BASE_LEVEL, testSize.lodBase);
+ gl.texParameteri(textureTarget, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+
+ // set up texture
+
+ switch (this.m_textureSpec.type) {
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
+ // bufferedLogToConsole('Testing image size ' + testSize.textureSize[0] + 'x' + testSize.textureSize[1] + 'x' + testSize.textureSize[2]);
+ // bufferedLogToConsole('Lod: ' + testSize.lod + ', base level: ' + testSize.lodBase);
+ // bufferedLogToConsole('Expecting: ' + testSize.expectedSize[0] + 'x' + testSize.expectedSize[1] + 'x' + testSize.expectedSize[2]);
+
+ gl.uniform3iv(sizeLoc, testSize.expectedSize);
+ gl.uniform1iv(lodLoc, [testSize.lod]);
+
+ gl.texStorage3D(textureTarget, levels, this.m_textureSpec.format, testSize.textureSize[0], testSize.textureSize[1], testSize.textureSize[2]);
+ break;
+
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
+ // bufferedLogToConsole('Testing image size ' + testSize.textureSize[0] + 'x' + testSize.textureSize[1]);
+ // bufferedLogToConsole('Lod: ' + testSize.lod + ', base level: ' + testSize.lodBase);
+ // bufferedLogToConsole('Expecting: ' + testSize.expectedSize[0] + 'x' + testSize.expectedSize[1]);
+
+ gl.uniform2iv(sizeLoc, testSize.expectedSize.slice(0,2));
+ gl.uniform1iv(lodLoc, [testSize.lod]);
+
+ gl.texStorage2D(textureTarget, levels, this.m_textureSpec.format, testSize.textureSize[0], testSize.textureSize[1]);
+ break;
+
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
+ /** @type {Array<number>} */ var expectedSize = [testSize.expectedSize[0], testSize.expectedSize[1], testSize.textureSize[2]];
+
+ // bufferedLogToConsole('Testing image size ' + testSize.textureSize[0] + 'x' + testSize.textureSize[1] + ' with ' + testSize.textureSize[2] + ' layer(s)');
+ // bufferedLogToConsole('Lod: ' + testSize.lod + ', base level: ' + testSize.lodBase);
+ // bufferedLogToConsole('Expecting: ' + testSize.expectedSize[0] + 'x' + testSize.expectedSize[1] + ' and ' + testSize.textureSize[2] + ' layer(s)');
+
+ gl.uniform3iv(sizeLoc, expectedSize);
+ gl.uniform1iv(lodLoc, [testSize.lod]);
+
+ gl.texStorage3D(textureTarget, levels, this.m_textureSpec.format, testSize.textureSize[0], testSize.textureSize[1], testSize.textureSize[2]);
+ break;
+
+ default:
+ throw new Error('Type not supported');
+ }
+
+ // test
+ /** @type {number} */ var colorTolerance = 0.1;
+ /** @type {tcuSurface.Surface} */ var sample = new tcuSurface.Surface(1, 1);
+ /** @type {Array<number>} */ var outputColor;
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ gl.finish();
+
+ sample.readViewport(gl, [0, 0, 1, 1]);
+
+ outputColor = sample.getAccess().getPixel(0, 0);
+
+ if (outputColor[0] >= 1.0 - colorTolerance &&
+ outputColor[1] >= 1.0 - colorTolerance &&
+ outputColor[2] >= 1.0 - colorTolerance)
+ bufferedLogToConsole('Passed');
+ else {
+ // failure
+ bufferedLogToConsole('Failed');
+ success = false;
+ }
+
+ // free
+ gl.bindTexture(textureTarget, null);
+ gl.deleteTexture(texId);
+
+ gl.useProgram(null);
+
+ return success;
+ };
+
+ /**
+ * @return {string}
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.genVertexShader = function() {
+ /** @type {string} */ var vert = '';
+ vert += '#version 300 es\n' +
+ 'in highp vec4 a_position;\n';
+
+ if (this.m_isVertexCase) {
+ vert += 'out mediump vec4 v_color;\n' +
+ 'uniform highp ' + this.m_samplerTypeStr + ' u_sampler;\n' +
+ 'uniform highp ivec' + (this.m_has3DSize ? 3 : 2) + ' u_texSize;\n' +
+ 'uniform highp int u_lod;\n';
+ }
+
+ vert += 'void main()\n{\n';
+
+ if (this.m_isVertexCase)
+ vert += ' v_color = (textureSize(u_sampler, u_lod) == u_texSize ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n';
+
+ vert += ' gl_Position = a_position;\n' +
+ '}\n';
+
+ return vert;
+ };
+
+ /**
+ * @return {string}
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.genFragmentShader = function() {
+ /** @type {string} */ var frag = '';
+
+ frag += '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (this.m_isVertexCase)
+ frag += 'in mediump vec4 v_color;\n';
+
+ if (!this.m_isVertexCase) {
+ frag += 'uniform highp ' + this.m_samplerTypeStr + ' u_sampler;\n' +
+ 'uniform highp ivec' + (this.m_has3DSize ? 3 : 2) + ' u_texSize;\n' +
+ 'uniform highp int u_lod;\n';
+ }
+
+ frag += 'void main()\n{\n';
+
+ if (!this.m_isVertexCase)
+ frag += ' o_color = (textureSize(u_sampler, u_lod) == u_texSize ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n';
+ else
+ frag += ' o_color = v_color;\n';
+
+ frag += '}\n';
+
+ return frag;
+ };
+
+ /**
+ * @return {number}
+ */
+ es3fShaderTextureFunctionTests.TextureSizeCase.prototype.getGLTextureTarget = function() {
+ switch (this.m_textureSpec.type) {
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
+ return gl.TEXTURE_2D;
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
+ return gl.TEXTURE_CUBE_MAP;
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
+ return gl.TEXTURE_2D_ARRAY;
+ case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
+ return gl.TEXTURE_3D;
+ default:
+ throw new Error('Texture Type not supported.');
+ }
+ };
+
+ /** @typedef {Array<string, es3fShaderTextureFunctionTests.TextureLookupSpec, es3fShaderTextureFunctionTests.TextureSpec, es3fShaderTextureFunctionTests.EvalFunc, es3fShaderTextureFunctionTests.CaseFlags>} */ es3fShaderTextureFunctionTests.TestSpec;
+
+ /**
+ * @param {string} name
+ * @param {es3fShaderTextureFunctionTests.TexFunction} func
+ * @param {Array<number>} minCoord
+ * @param {Array<number>} maxCoord
+ * @param {boolean} useBias
+ * @param {number} minLodBias
+ * @param {number} maxLodBias
+ * @param {boolean} useOffset
+ * @param {Array<number>} offset
+ * @param {es3fShaderTextureFunctionTests.TextureSpec} texSpec
+ * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
+ * @param {es3fShaderTextureFunctionTests.CaseFlags} flags
+ * @return {es3fShaderTextureFunctionTests.TexFuncCaseSpec}
+ */
+ es3fShaderTextureFunctionTests.getCaseSpec = function(name, func, minCoord, maxCoord, useBias, minLodBias, maxLodBias, useOffset, offset, texSpec, evalFunc, flags) {
+ return new es3fShaderTextureFunctionTests.TexFuncCaseSpec(name,
+ new es3fShaderTextureFunctionTests.TextureLookupSpec(func, minCoord, maxCoord, useBias, minLodBias, maxLodBias, [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], useOffset, offset),
+ texSpec,
+ evalFunc,
+ flags);
+ };
+
+ /**
+ * @param {string} name
+ * @param {es3fShaderTextureFunctionTests.TexFunction} func
+ * @param {Array<number>} minCoord
+ * @param {Array<number>} maxCoord
+ * @param {Array<number>} mindx
+ * @param {Array<number>} maxdx
+ * @param {Array<number>} mindy
+ * @param {Array<number>} maxdy
+ * @param {boolean} useOffset
+ * @param {Array<number>} offset
+ * @param {es3fShaderTextureFunctionTests.TextureSpec} texSpec
+ * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
+ * @param {es3fShaderTextureFunctionTests.CaseFlags} flags
+ * @return {es3fShaderTextureFunctionTests.TexFuncCaseSpec}
+ */
+ es3fShaderTextureFunctionTests.getGradCaseSpec = function(name, func, minCoord, maxCoord, mindx, maxdx, mindy, maxdy, useOffset, offset, texSpec, evalFunc, flags) {
+ return new es3fShaderTextureFunctionTests.TexFuncCaseSpec(name,
+ new es3fShaderTextureFunctionTests.TextureLookupSpec(func, minCoord, maxCoord, false, 0.0, 0.0, mindx, maxdx, mindy, maxdy, useOffset, offset),
+ texSpec,
+ evalFunc,
+ flags);
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fShaderTextureFunctionTests.CaseFlags = {
+ VERTEX: 1,
+ FRAGMENT: 2,
+ BOTH: 3
+ };
+
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {es3fShaderTextureFunctionTests.TextureLookupSpec} lookupSpec
+ * @param {es3fShaderTextureFunctionTests.TextureSpec} texSpec
+ * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
+ * @param {number} flags
+ */
+ es3fShaderTextureFunctionTests.TexFuncCaseSpec = function(name, lookupSpec, texSpec, evalFunc, flags) {
+ /** @type {string} */ this.name = name;
+ /** @type {es3fShaderTextureFunctionTests.TextureLookupSpec} */ this.lookupSpec = lookupSpec;
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.texSpec = texSpec;
+ /** @type {es3fShaderTextureFunctionTests.TexEvalFunc} */ this.evalFunc = evalFunc;
+ /** @type {number} */ this.flags = flags;
+ };
+
+ /**
+ * @param {tcuTestCase.DeqpTest} parent
+ * @param {string} groupName
+ * @param {string} groupDesc
+ * @param {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} cases
+ */
+ es3fShaderTextureFunctionTests.createCaseGroup = function(parent, groupName, groupDesc, cases) {
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(groupName, groupDesc);
+ parent.addChild(group);
+
+ for (var ndx = 0; ndx < cases.length; ndx++) {
+ /** @type {string} */ var name = cases[ndx].name;
+ if (cases[ndx].flags & es3fShaderTextureFunctionTests.CaseFlags.VERTEX)
+ group.addChild(new es3fShaderTextureFunctionTests.ShaderTextureFunctionCase(name + '_vertex', '', cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, true));
+ if (cases[ndx].flags & es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ group.addChild(new es3fShaderTextureFunctionTests.ShaderTextureFunctionCase(name + '_fragment', '', cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, false));
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'texture_functions', 'Texture Access Function Tests');
+ };
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionTests.prototype.constructor = es3fShaderTextureFunctionTests.ShaderTextureFunctionTests;
+
+ es3fShaderTextureFunctionTests.ShaderTextureFunctionTests.prototype.init = function() {
+ // Samplers
+ /** @type {tcuTexture.Sampler} */ var samplerNearestNoMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST,
+ 0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+ /** @type {tcuTexture.Sampler} */ var samplerLinearNoMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.LINEAR, tcuTexture.FilterMode.LINEAR,
+ 0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+ /** @type {tcuTexture.Sampler} */ var samplerNearestMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST, tcuTexture.FilterMode.NEAREST,
+ 0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+ /** @type {tcuTexture.Sampler} */ var samplerLinearMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST, tcuTexture.FilterMode.LINEAR,
+ 0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+
+ /** @type {tcuTexture.Sampler} */ var samplerShadowNoMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST,
+ 0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_LESS,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+ /** @type {tcuTexture.Sampler} */ var samplerShadowMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST, tcuTexture.FilterMode.NEAREST,
+ 0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_LESS,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+
+ /** @type {tcuTexture.Sampler} */ var samplerTexelFetch = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
+ tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST, tcuTexture.FilterMode.NEAREST,
+ 0.0 /* LOD threshold */, false /* non-normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
+ 0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
+
+ // Default textures.
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8, 256, 256, 1, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA16F, 256, 256, 1, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8I, 256, 256, 1, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8UI, 256, 256, 1, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8, 256, 256, 1, 9, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA16F, 256, 256, 1, 9, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8I, 256, 256, 1, 9, samplerNearestMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8UI, 256, 256, 1, 9, samplerNearestMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8, 256, 256, 1, 9, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA16F, 256, 256, 1, 9, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8I, 256, 256, 1, 9, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8UI, 256, 256, 1, 9, samplerTexelFetch);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8, 256, 256, 1, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA16F, 256, 256, 1, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8I, 256, 256, 1, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8UI, 256, 256, 1, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8, 256, 256, 1, 9, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA16F, 128, 128, 1, 8, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8I, 256, 256, 1, 9, samplerNearestMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8UI, 256, 256, 1, 9, samplerNearestMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.DEPTH_COMPONENT16, 256, 256, 1, 1, samplerShadowNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8, 128, 128, 4, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA16F, 128, 128, 4, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8I, 128, 128, 4, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8UI, 128, 128, 4, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8, 128, 128, 4, 8, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA16F, 128, 128, 4, 8, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8I, 128, 128, 4, 8, samplerNearestMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8UI, 128, 128, 4, 8, samplerNearestMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.DEPTH_COMPONENT16, 128, 128, 4, 1, samplerShadowNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.DEPTH_COMPONENT16, 128, 128, 4, 8, samplerShadowMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8, 128, 128, 4, 8, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA16F, 128, 128, 4, 8, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8I, 128, 128, 4, 8, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8UI, 128, 128, 4, 8, samplerTexelFetch);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8, 64, 32, 32, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA16F, 64, 32, 32, 1, samplerLinearNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8I, 64, 32, 32, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8UI, 64, 32, 32, 1, samplerNearestNoMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8, 64, 32, 32, 7, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA16F, 64, 32, 32, 7, samplerLinearMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8I, 64, 32, 32, 7, samplerNearestMipmap);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8UI, 64, 32, 32, 7, samplerNearestMipmap);
+
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8, 64, 32, 32, 7, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA16F, 64, 32, 32, 7, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8I, 64, 32, 32, 7, samplerTexelFetch);
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8UI, 64, 32, 32, 7, samplerTexelFetch);
+
+ var testGroup = tcuTestCase.runner.testCases;
+ // texture() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeFixed, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeFloat, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeInt, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeUint, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], true, -2.0, 2.0, false, [0, 0, 0], texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], true, -2.0, 2.0, false, [0, 0, 0], texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isamplercube_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], true, -2.0, 2.0, false, [0, 0, 0], texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usamplercube_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], true, -2.0, 2.0, false, [0, 0, 0], texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayFixed, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayFloat, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayInt, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayUint, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DInt, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DUint, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 1.0, false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 1.0, false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadow, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadow, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercubeshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadow, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercubeshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0], false, 0.0, 0.0, false, [0, 0, 0], texCubeMipmapShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadow, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercubeshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0], true, -2.0, 2.0, false, [0, 0, 0], texCubeMipmapShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadowBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadow, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadow, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+
+ // Not in spec.
+ // es3fShaderTextureFunctionTests.getCaseSpec('sampler2darrayshadow_bias', (es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], true, -2.0, 2.0, Vec2(0.0), Vec2(0.0), false, [0, 0, 0]), tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowBias, FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texture', 'texture() Tests', textureCases);
+
+ // textureOffset() cases
+ // \note _bias variants are not using mipmap thanks to wide allowed range for LOD computation
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureOffsetCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, true, [7, -8, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], true, -2.0, 2.0, true, [7, -8, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DArrayFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DArrayFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DArrayInt, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DArrayUint, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DArrayFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, true, [7, -8, 0], tex2DArrayFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DArrayInt, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], true, -2.0, 2.0, true, [7, -8, 0], tex2DArrayUint, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [-8, 7, 3], tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [7, 3, -8], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [3, -8, 7], tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [-8, 7, 3], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [7, 3, -8], tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [3, -8, 7], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [-8, 7, 3], tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, 0.0, 0.0, true, [7, 3, -8], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 1.0, true, [-8, 7, 3], tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 1.0, true, [7, 3, -8], tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 2.0, true, [3, -8, 7], tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], true, -2.0, 2.0, true, [-8, 7, 3], tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureoffset', 'textureOffset() Tests', textureOffsetCases);
+
+ // textureProj() cases
+ // \note Currently uses constant divider!
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 1.0, false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 1.0, false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 2.0, false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 2.0, false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], false, 0.0, 0.0, false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], true, -2.0, 2.0, false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureproj', 'textureProj() Tests', textureProjCases);
+
+ // textureProjOffset() cases
+ // \note Currently uses constant divider!
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjOffsetCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, true, [7, -8, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, true, [-8, 7, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], true, -2.0, 2.0, true, [7, -8, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [-8, 7, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [-8, 7, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [-8, 7, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [-8, 7, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, true, [-8, 7, 0], tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, true, [7, -8, 0], tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, true, [-8, 7, 0], tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], true, -2.0, 2.0, true, [7, -8, 0], tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [-8, 7, 3], tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [7, 3, -8], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [3, -8, 7], tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [-8, 7, 3], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [7, 3, -8], tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [3, -8, 7], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [-8, 7, 3], tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, 0.0, 0.0, true, [7, 3, -8], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 2.0, true, [-8, 7, 3], tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 2.0, true, [7, 3, -8], tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 2.0, true, [3, -8, 7], tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], true, -2.0, 2.0, true, [-8, 7, 3], tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ // NOTE: offset changed from [-8, 7, 0] in native dEQP to [7, -8, 0] per https://github.com/KhronosGroup/WebGL/issues/2033
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], false, 0.0, 0.0, true, [7, -8, 0], tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], false, 0.0, 0.0, true, [7, -8, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], true, -2.0, 2.0, true, [-8, 7, 0], tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojoffset', 'textureOffsetProj() Tests', textureProjOffsetCases);
+
+ // textureLod() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureLodCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], false, -1.0, 9.0, false, [0, 0, 0], texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], false, -1.0, 9.0, false, [0, 0, 0], texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], false, -1.0, 9.0, false, [0, 0, 0], texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], false, -1.0, 9.0, false, [0, 0, 0], texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, false, [0, 0, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, false, [0, 0, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, false, [0, 0, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, false, [0, 0, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturelod', 'textureLod() Tests', textureLodCases);
+
+ // textureLodOffset() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureLodOffsetCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], false, -1.0, 9.0, true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, true, [-8, 7, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, true, [7, -8, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, true, [-8, 7, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], false, -1.0, 8.0, true, [7, -8, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, true, [-8, 7, 3], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, true, [7, 3, -8], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, true, [3, -8, 7], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], false, -1.0, 7.0, true, [-8, 7, 3], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturelodoffset', 'textureLodOffset() Tests', textureLodOffsetCases);
+
+ // textureProjLod() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjLodCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], false, -1.0, 9.0, false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojlod', 'textureProjLod() Tests', textureProjLodCases);
+
+ // textureProjLodOffset() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjLodOffsetCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], false, -1.0, 9.0, true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], false, -1.0, 9.0, true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, true, [-8, 7, 3], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, true, [7, 3, -8], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, true, [3, -8, 7], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], false, -1.0, 7.0, true, [-8, 7, 3], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5], false, -1.0, 9.0, true, [-8, 7, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojlodoffset', 'textureProjLodOffset() Tests', textureProjLodOffsetCases);
+
+ // textureGrad() cases
+ // \note Only one of dudx, dudy, dvdx, dvdy is non-zero since spec allows approximating p from derivates by various methods.
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureGradCases = [
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2], false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('samplercubeshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], texCubeMipmapShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], false, [0, 0, 0], tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], false, [0, 0, 0], tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturegrad', 'textureGrad() Tests', textureGradCases);
+
+ // textureGradOffset() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureGradOffsetCases = [
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 0], tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, -8, 0], tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], true, [-8, 7, 0], tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], true, [7, -8, 0], tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 3], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, 3, -8], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [3, -8, 7], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], true, [-8, 7, 3], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], true, [7, 3, -8], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2], true, [3, -8, 7], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, -8, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], true, [-8, 7, 0], tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], true, [7, -8, 0], tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturegradoffset', 'textureGradOffset() Tests', textureGradOffsetCases);
+
+ // textureProjGrad() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjGradCases = [
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], false, [0, 0, 0], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2], false, [0, 0, 0], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], false, [0, 0, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojgrad', 'textureProjGrad() Tests', textureProjGradCases);
+
+ // textureProjGradOffset() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjGradOffsetCases = [
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, -8, 0], tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], true, [7, -8, 0], tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 3], tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [7, 3, -8], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [3, -8, 7], tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0], true, [-8, 7, 3], tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], true, [7, 3, -8], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2], true, [3, -8, 7], tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
+
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], true, [-8, 7, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
+ es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], true, [7, -8, 0], tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojgradoffset', 'textureProjGradOffset() Tests', textureProjGradOffsetCases);
+
+ // texelFetch() cases
+ // \note Level is constant across quad
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var texelFetchCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [255.9, 255.9, 0.0, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [127.9, 127.9, 0.0, 0.0], false, 1.0, 1.0, false, [0, 0, 0], tex2DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 63.9, 0.0, 0.0], false, 2.0, 2.0, false, [0, 0, 0], tex2DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [15.9, 15.9, 0.0, 0.0], false, 4.0, 4.0, false, [0, 0, 0], tex2DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [127.9, 127.9, 3.9, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex2DArrayTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 63.9, 3.9, 0.0], false, 1.0, 1.0, false, [0, 0, 0], tex2DArrayTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [31.9, 31.9, 3.9, 0.0], false, 2.0, 2.0, false, [0, 0, 0], tex2DArrayTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [15.9, 15.9, 3.9, 0.0], false, 3.0, 3.0, false, [0, 0, 0], tex2DArrayTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 31.9, 31.9, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [31.9, 15.9, 15.9, 0.0], false, 1.0, 1.0, false, [0, 0, 0], tex3DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [15.9, 7.9, 7.9, 0.0], false, 2.0, 2.0, false, [0, 0, 0], tex3DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 31.9, 31.9, 0.0], false, 0.0, 0.0, false, [0, 0, 0], tex3DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texelfetch', 'texelFetch() Tests', texelFetchCases);
+
+ // texelFetchOffset() cases
+ /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var texelFetchOffsetCases = [
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [263.9, 248.9, 0.0, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [120.9, 135.9, 0.0, 0.0], false, 1.0, 1.0, true, [7, -8, 0], tex2DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [71.9, 56.9, 0.0, 0.0], false, 2.0, 2.0, true, [-8, 7, 0], tex2DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [8.9, 23.9, 0.0, 0.0], false, 4.0, 4.0, true, [7, -8, 0], tex2DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [135.9, 120.9, 3.9, 0.0], false, 0.0, 0.0, true, [-8, 7, 0], tex2DArrayTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [56.9, 71.9, 3.9, 0.0], false, 1.0, 1.0, true, [7, -8, 0], tex2DArrayTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [39.9, 24.9, 3.9, 0.0], false, 2.0, 2.0, true, [-8, 7, 0], tex2DArrayTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [8.9, 23.9, 3.9, 0.0], false, 3.0, 3.0, true, [7, -8, 0], tex2DArrayTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, -3.0, 0.0], [71.9, 24.9, 28.9, 0.0], false, 0.0, 0.0, true, [-8, 7, 3], tex3DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, -3.0, 8.0, 0.0], [24.9, 12.9, 23.9, 0.0], false, 1.0, 1.0, true, [7, 3, -8], tex3DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-3.0, 8.0, -7.0, 0.0], [12.9, 15.9, 0.9, 0.0], false, 2.0, 2.0, true, [3, -8, 7], tex3DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
+ es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, -3.0, 0.0], [71.9, 24.9, 28.9, 0.0], false, 0.0, 0.0, true, [-8, 7, 3], tex3DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH)
+ ];
+ es3fShaderTextureFunctionTests.createCaseGroup(this, 'texelfetchoffset', 'texelFetchOffset() Tests', texelFetchOffsetCases);
+
+ // textureSize() cases
+ /**
+ * @struct
+ * @constructor
+ * @param {string} name
+ * @param {string} samplerName
+ * @param {es3fShaderTextureFunctionTests.TextureSpec} textureSpec
+ */
+ var TextureSizeCaseSpec = function(name, samplerName, textureSpec) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.samplerName = samplerName;
+ /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.textureSpec = textureSpec;
+ };
+
+ /** @type {Array<TextureSizeCaseSpec>} */ var textureSizeCases = [
+ new TextureSizeCaseSpec('sampler2d_fixed', 'sampler2D', tex2DFixed),
+ new TextureSizeCaseSpec('sampler2d_float', 'sampler2D', tex2DFloat),
+ new TextureSizeCaseSpec('isampler2d', 'isampler2D', tex2DInt),
+ new TextureSizeCaseSpec('usampler2d', 'usampler2D', tex2DUint),
+ new TextureSizeCaseSpec('sampler2dshadow', 'sampler2DShadow', tex2DShadow),
+ new TextureSizeCaseSpec('sampler3d_fixed', 'sampler3D', tex3DFixed),
+ new TextureSizeCaseSpec('sampler3d_float', 'sampler3D', tex3DFloat),
+ new TextureSizeCaseSpec('isampler3d', 'isampler3D', tex3DInt),
+ new TextureSizeCaseSpec('usampler3d', 'usampler3D', tex3DUint),
+ new TextureSizeCaseSpec('samplercube_fixed', 'samplerCube', texCubeFixed),
+ new TextureSizeCaseSpec('samplercube_float', 'samplerCube', texCubeFloat),
+ new TextureSizeCaseSpec('isamplercube', 'isamplerCube', texCubeInt),
+ new TextureSizeCaseSpec('usamplercube', 'usamplerCube', texCubeUint),
+ new TextureSizeCaseSpec('samplercubeshadow', 'samplerCubeShadow', texCubeShadow),
+ new TextureSizeCaseSpec('sampler2darray_fixed', 'sampler2DArray', tex2DArrayFixed),
+ new TextureSizeCaseSpec('sampler2darray_float', 'sampler2DArray', tex2DArrayFloat),
+ new TextureSizeCaseSpec('isampler2darray', 'isampler2DArray', tex2DArrayInt),
+ new TextureSizeCaseSpec('usampler2darray', 'usampler2DArray', tex2DArrayUint),
+ new TextureSizeCaseSpec('sampler2darrayshadow', 'sampler2DArrayShadow', tex2DArrayShadow)
+ ];
+
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest('texturesize', 'textureSize() Tests');
+ testGroup.addChild(group);
+
+ for (var ndx = 0; ndx < textureSizeCases.length; ++ndx) {
+ group.addChild(new es3fShaderTextureFunctionTests.TextureSizeCase(textureSizeCases[ndx].name + '_vertex', '', textureSizeCases[ndx].samplerName, textureSizeCases[ndx].textureSpec, true));
+ group.addChild(new es3fShaderTextureFunctionTests.TextureSizeCase(textureSizeCases[ndx].name + '_fragment', '', textureSizeCases[ndx].samplerName, textureSizeCases[ndx].textureSpec, false));
+ }
+
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ * @param {Array<number>=} range Test range
+ */
+ es3fShaderTextureFunctionTests.run = function(context, range) {
+ gl = context;
+
+ const canvas = gl.canvas;
+ canvas.width = canvasWH;
+ canvas.height = canvasWH;
+
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderTextureFunctionTests.ShaderTextureFunctionTests());
+ if (range)
+ state.setRange(range);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderTextureFunctionTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fStringQueryTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fStringQueryTests.js
new file mode 100644
index 0000000000..8e90ff576b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fStringQueryTests.js
@@ -0,0 +1,111 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fStringQueryTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('functional.gles3.es3fApiCase');
+
+goog.scope(function() {
+ var es3fStringQueryTests = functional.gles3.es3fStringQueryTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var es3fApiCase = functional.gles3.es3fApiCase;
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fStringQueryTests.StringQueryTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'string', 'String Query tests');
+ };
+
+ es3fStringQueryTests.StringQueryTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fStringQueryTests.StringQueryTests.prototype.constructor = es3fStringQueryTests.StringQueryTests;
+
+ es3fStringQueryTests.StringQueryTests.prototype.init = function() {
+ this.addChild(new es3fApiCase.ApiCaseCallback('renderer', 'RENDERER', gl, function() {
+ var string = /** @type {string} */ (gl.getParameter(gl.RENDERER));
+ this.check(string !== null,
+ 'Got invalid string: ' + string);
+ }));
+
+ this.addChild(new es3fApiCase.ApiCaseCallback('vendor', 'VENDOR', gl, function() {
+ var string = /** @type {string} */ (gl.getParameter(gl.VENDOR));
+ this.check(string !== null,
+ 'Got invalid string: ' + string);
+ }));
+
+ this.addChild(new es3fApiCase.ApiCaseCallback('version', 'VERSION', gl, function() {
+ var string = /** @type {string} */ (gl.getParameter(gl.VERSION));
+ /** @type {string} */ var referenceString = 'WebGL 2.0';
+
+ this.check(string !== null && string.indexOf(referenceString) === 0,
+ 'Got invalid string prefix: ' + string + ' expected: ' + referenceString);
+ }));
+
+ this.addChild(new es3fApiCase.ApiCaseCallback('shading_language_version', 'SHADING_LANGUAGE_VERSION', gl, function() {
+ var string = /** @type {string} */ (gl.getParameter(gl.SHADING_LANGUAGE_VERSION));
+ /** @type {string} */ var referenceString = 'WebGL GLSL ES 3.00';
+
+ this.check(string !== null, 'Got invalid string');
+ this.check(string.indexOf(referenceString) === 0, 'Got invalid string prefix');
+ }));
+
+ this.addChild(new es3fApiCase.ApiCaseCallback('extensions', 'EXTENSIONS', gl, function() {
+ /** @type {Array<string>} */ var extensions = gl.getSupportedExtensions();
+ this.check(extensions !== null, 'Got invalid string');
+
+ // [dag] check that all extensions from gl.getSupportedExtensions() are found using gl.getExtension()
+ for (var i in extensions) {
+ /** @type {Object} */ var extension = gl.getExtension(extensions[i]);
+ this.check(extension !== null, 'Advertised extension ' + extensions[i] + ' not found');
+ }
+
+ // [dag] check that gl.getExtension() returns null for items not in gl.getSupportedExtensions()
+ this.check(gl.getExtension('Random_String') === null, 'Extension query methods are not consistent.');
+ }));
+
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fStringQueryTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fStringQueryTests.StringQueryTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fStringQueryTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSyncTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSyncTests.js
new file mode 100644
index 0000000000..bd18845d9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fSyncTests.js
@@ -0,0 +1,330 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fSyncTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+ var es3fSyncTests = functional.gles3.es3fSyncTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deRandom = framework.delibs.debase.deRandom;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var deString = framework.delibs.debase.deString;
+
+ /** @const {number} */ es3fSyncTests.NUM_CASE_ITERATIONS = 5;
+ /** @const {number} */ es3fSyncTests.MAX_VERIFY_WAIT = 5;
+
+ /**
+ * @enum
+ */
+ es3fSyncTests.WaitCommand = {
+ WAIT_SYNC: 1,
+ CLIENT_WAIT_SYNC: 2
+ };
+
+ /** @enum
+ */
+ es3fSyncTests.CaseOptions = {
+ FLUSH_BEFORE_WAIT: 1,
+ FINISH_BEFORE_WAIT: 2
+ };
+
+ /** @enum
+ */
+ es3fSyncTests.State = {
+ DRAW: 0,
+ VERIFY: 1,
+ FINISH: 2
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} numPrimitives
+ * @param {number} waitCommand
+ * @param {number} waitFlags
+ * @param {number} timeout
+ * @param {number} options
+ */
+ es3fSyncTests.FenceSyncCase = function(name, description, numPrimitives, waitCommand, waitFlags, timeout, options) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {number} */ this.m_numPrimitives = numPrimitives;
+ /** @type {number} */ this.m_waitCommand = waitCommand;
+ /** @type {number} */ this.m_waitFlags = waitFlags;
+ /** @type {number} */ this.m_timeout = timeout;
+ /** @type {number} */ this.m_caseOptions = options;
+
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {WebGLSync} */ this.m_syncObject = null;
+ /** @type {number} */ this.m_iterNdx = 0;
+ /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
+ /** @type {es3fSyncTests.State} */ this.m_state = es3fSyncTests.State.DRAW;
+ };
+
+ es3fSyncTests.FenceSyncCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fSyncTests.FenceSyncCase.prototype.constructor = es3fSyncTests.FenceSyncCase;
+
+ /**
+ * @param {number} numPrimitives
+ * @param {deRandom.Random} rnd
+ * @return {Array<number>}
+ */
+ es3fSyncTests.generateVertices = function(numPrimitives, rnd) {
+ /** @type {Array<number>} */ var dst = [];
+ /** @type {number} */ var numVertices = 3 * numPrimitives;
+
+ for (var i = 0; i < numVertices; i++) {
+ dst.push(rnd.getFloat(-1.0, 1.0)); // x
+ dst.push(rnd.getFloat(-1.0, 1.0)); // y
+ dst.push(rnd.getFloat(0.0, 1.0)); // z
+ dst.push(1.0); // w
+ }
+ return dst;
+ };
+
+ es3fSyncTests.FenceSyncCase.prototype.init = function() {
+ /** @type {string} */ var vertShaderSource = '#version 300 es\n' +
+ 'layout(location = 0) in mediump vec4 a_position;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n' +
+ '}\n';
+
+ /** @type {string} */ var fragShaderSource = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = vec4(0.25, 0.5, 0.75, 1.0);\n' +
+ '}\n';
+
+ assertMsgOptions(!this.m_program, 'Program should be null.', false, true);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource));
+
+ if (!this.m_program.isOk())
+ throw new Error('Failed to compile shader program');
+ };
+
+ es3fSyncTests.FenceSyncCase.prototype.deinit = function() {
+ if (this.m_program)
+ this.m_program = null;
+
+ if (this.m_syncObject) {
+ gl.deleteSync(this.m_syncObject);
+ this.m_syncObject = null;
+ }
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fSyncTests.FenceSyncCase.prototype.draw = function() {
+ /** @type {Array<number>} */ var vertices = [];
+
+ /** @type {string} */ var header = 'Case iteration ' + (this.m_iterNdx + 1) + ' / ' + es3fSyncTests.NUM_CASE_ITERATIONS;
+ bufferedLogToConsole(header);
+
+ assertMsgOptions(this.m_program !== null, 'Expected program', false, true);
+ gl.useProgram(this.m_program.getProgram());
+ gl.enable(gl.DEPTH_TEST);
+ gl.clearColor(0.3, 0.3, 0.3, 1.0);
+ gl.clearDepth(1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // Generate vertices
+
+ gl.enableVertexAttribArray(0);
+ vertices = es3fSyncTests.generateVertices(this.m_numPrimitives, this.m_rnd);
+
+ /** @type {WebGLBuffer} */ var vertexGLBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+
+ // Draw
+
+ gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 4);
+ bufferedLogToConsole('Primitives drawn.');
+
+ // Create sync object
+
+ this.m_syncObject = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ bufferedLogToConsole('Sync object created');
+
+ if (this.m_caseOptions & es3fSyncTests.CaseOptions.FLUSH_BEFORE_WAIT)
+ gl.flush();
+ if (this.m_caseOptions & es3fSyncTests.CaseOptions.FINISH_BEFORE_WAIT)
+ gl.finish();
+ this.m_state = es3fSyncTests.State.VERIFY;
+ };
+
+
+ es3fSyncTests.FenceSyncCase.prototype.verify = function() {
+ /** @type {number} */ var waitValue = 0;
+ /** @type {boolean} */ var testOk = true;
+
+ // Wait for sync object
+ if (this.m_waitCommand & es3fSyncTests.WaitCommand.WAIT_SYNC) {
+ assertMsgOptions(this.m_timeout === gl.TIMEOUT_IGNORED, 'Expected TIMEOUT_IGNORED', false, true);
+ assertMsgOptions(this.m_waitFlags === 0, 'Expected waitFlags = 0', false, true);
+ gl.waitSync(this.m_syncObject, this.m_waitFlags, this.m_timeout);
+ bufferedLogToConsole('Wait command glWaitSync called with GL_TIMEOUT_IGNORED.');
+ }
+
+ if (this.m_waitCommand & es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC) {
+ waitValue = gl.clientWaitSync(this.m_syncObject, this.m_waitFlags, this.m_timeout);
+ bufferedLogToConsole('glClientWaitSync return value:');
+ switch (waitValue) {
+ case gl.ALREADY_SIGNALED:
+ bufferedLogToConsole('gl.ALREADY_SIGNALED');
+ break;
+ case gl.TIMEOUT_EXPIRED:
+ bufferedLogToConsole('gl.TIMEOUT_EXPIRED');
+ break;
+ case gl.CONDITION_SATISFIED:
+ bufferedLogToConsole('gl.CONDITION_SATISFIED');
+ break;
+ case gl.WAIT_FAILED:
+ bufferedLogToConsole('gl.WAIT_FAILED');
+ testOk = false;
+ break;
+ default:
+ bufferedLogToConsole('Illegal return value!');
+ }
+ }
+
+ gl.finish();
+
+ // Delete sync object
+
+ if (this.m_syncObject && testOk) {
+ gl.deleteSync(this.m_syncObject);
+ this.m_syncObject = null;
+ bufferedLogToConsole('Sync object deleted.');
+ }
+
+ // Evaluate test result
+
+ bufferedLogToConsole('Test result: ' + (testOk ? 'Passed!' : 'Failed!'));
+
+ if (!testOk) {
+ if (!this.m_verifyStart)
+ this.m_verifyStart = new Date();
+ else {
+ var current = new Date();
+ var elapsedTime = 0.001 * (current.getTime() - this.m_verifyStart.getTime());
+ if (elapsedTime > es3fSyncTests.MAX_VERIFY_WAIT) {
+ testFailedOptions('Fail', false);
+ this.m_state = es3fSyncTests.State.FINISH;
+ if (this.m_syncObject) {
+ gl.deleteSync(this.m_syncObject);
+ this.m_syncObject = null;
+ bufferedLogToConsole('Sync object deleted.');
+ }
+ }
+ }
+ } else {
+ bufferedLogToConsole('Sync objects created and deleted successfully.');
+ testPassedOptions('Pass', true);
+ this.m_state = (++this.m_iterNdx < es3fSyncTests.NUM_CASE_ITERATIONS) ? es3fSyncTests.State.DRAW : es3fSyncTests.State.FINISH;
+ }
+ };
+
+ es3fSyncTests.FenceSyncCase.prototype.iterate = function() {
+ switch (this.m_state) {
+ case es3fSyncTests.State.DRAW:
+ this.draw();
+ break;
+ case es3fSyncTests.State.VERIFY:
+ this.verify();
+ break;
+ case es3fSyncTests.State.FINISH:
+ return tcuTestCase.IterateResult.STOP;
+ default:
+ throw new Error('Invalid state: ' + this.m_state);
+ }
+
+ return tcuTestCase.IterateResult.CONTINUE;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fSyncTests.SyncTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'fence_sync', 'Fence Sync Tests');
+ };
+
+ es3fSyncTests.SyncTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fSyncTests.SyncTests.prototype.constructor = es3fSyncTests.SyncTests;
+
+ es3fSyncTests.SyncTests.prototype.init = function() {
+ // Fence sync tests.
+
+ this.addChild(new es3fSyncTests.FenceSyncCase('wait_sync_smalldraw', '', 10, es3fSyncTests.WaitCommand.WAIT_SYNC, 0, gl.TIMEOUT_IGNORED, 0));
+ this.addChild(new es3fSyncTests.FenceSyncCase('wait_sync_largedraw', '', 100000, es3fSyncTests.WaitCommand.WAIT_SYNC, 0, gl.TIMEOUT_IGNORED, 0));
+
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_smalldraw', '', 10, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, 0));
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_largedraw', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, 0));
+
+ // Originally the next two test cases' timeout is 10, but in WebGL2 that could be illegal.
+ var max = gl.getParameter(gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL) || 0;
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_timeout_smalldraw', '', 10, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, max, 0));
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_timeout_largedraw', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, max, 0));
+
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_flush_auto', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, gl.SYNC_FLUSH_COMMANDS_BIT, 0, 0));
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_flush_manual', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, es3fSyncTests.CaseOptions.FLUSH_BEFORE_WAIT));
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_noflush', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, 0));
+ this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_finish', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, es3fSyncTests.CaseOptions.FINISH_BEFORE_WAIT));
+
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fSyncTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fSyncTests.SyncTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fSyncTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js
new file mode 100644
index 0000000000..45ff09a11c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js
@@ -0,0 +1,2282 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fTextureFilteringTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexLookupVerifier');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('functional.gles3.es3fFboTestUtil');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+
+ var es3fTextureFilteringTests = functional.gles3.es3fTextureFilteringTests;
+ var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+ var gluTexture = framework.opengl.gluTexture;
+ var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ es3fTextureFilteringTests.version =
+ gluShaderUtil.getGLSLVersionString(gluShaderUtil.GLSLVersion.V300_ES);
+
+ let canvasWH = 256;
+ let viewportWH = 64;
+
+ if (tcuTestCase.isQuickMode()) {
+ canvasWH = 64;
+ viewportWH = 32;
+ }
+
+ const TEX2D_VIEWPORT_WIDTH = viewportWH;
+ const TEX2D_VIEWPORT_HEIGHT = viewportWH;
+ const TEX2D_MIN_VIEWPORT_WIDTH = viewportWH;
+ const TEX2D_MIN_VIEWPORT_HEIGHT = viewportWH;
+
+ const TEX3D_VIEWPORT_WIDTH = viewportWH;
+ const TEX3D_VIEWPORT_HEIGHT = viewportWH;
+ const TEX3D_MIN_VIEWPORT_WIDTH = viewportWH;
+ const TEX3D_MIN_VIEWPORT_HEIGHT = viewportWH;
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fTextureFilteringTests.TextureFilteringTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'filtering', 'Texture Filtering Tests');
+ };
+
+ es3fTextureFilteringTests.TextureFilteringTests.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+
+ es3fTextureFilteringTests.TextureFilteringTests.prototype.constructor =
+ es3fTextureFilteringTests.TextureFilteringTests;
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureFilteringTests.Texture2DFilteringCase = function(
+ name, desc, minFilter, magFilter, wrapS, wrapT,
+ internalFormat, width, height
+ ) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_minFilter = minFilter;
+ this.m_magFilter = magFilter;
+ this.m_wrapS = wrapS;
+ this.m_wrapT = wrapT;
+ this.m_internalFormat = internalFormat;
+ this.m_width = width;
+ this.m_height = height;
+ /** @type {glsTextureTestUtil.TextureRenderer} */
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(
+ es3fTextureFilteringTests.version,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ );
+ this.m_caseNdx = 0;
+ /** @type {Array<gluTexture.Texture2D>} */ this.m_textures = [];
+ this.m_cases = [];
+ };
+
+ es3fTextureFilteringTests.Texture2DFilteringCase.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fTextureFilteringTests.Texture2DFilteringCase.prototype.constructor =
+ es3fTextureFilteringTests.Texture2DFilteringCase;
+
+ /**
+ * @constructor
+ * @param {gluTexture.Texture2D} tex_
+ * @param {Array<number>} minCoord_
+ * @param {Array<number>} maxCoord_
+ */
+ es3fTextureFilteringTests.Texture2DFilteringCase.FilterCase = function(
+ tex_, minCoord_, maxCoord_
+ ) {
+ this.texture = tex_;
+ this.minCoord = minCoord_;
+ this.maxCoord = maxCoord_;
+ };
+
+ /** @typedef {{texNdx: number, lodX: number,
+ * lodY: number, oX: number, oY: number}} */
+ es3fTextureFilteringTests.Cases;
+
+ /**
+ * init
+ */
+ es3fTextureFilteringTests.Texture2DFilteringCase.prototype.init =
+ function() {
+ try {
+ // Create 2 textures.
+ for (var ndx = 0; ndx < 2; ndx++)
+ this.m_textures.push(
+ gluTexture.texture2DFromInternalFormat(
+ gl, this.m_internalFormat,
+ this.m_width, this.m_height
+ )
+ );
+
+ var mipmaps = true;
+ var numLevels = mipmaps ? deMath.logToFloor(
+ Math.max(this.m_width, this.m_height)
+ ) + 1 : 1;
+
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(
+ this.m_textures[0].getRefTexture().getFormat()
+ );
+ /** @type {Array<number>} */ var cBias = fmtInfo.valueMin;
+ /** @type {Array<number>} */
+ var cScale = deMath.subtract(
+ fmtInfo.valueMax, fmtInfo.valueMin
+ );
+
+ // Fill first gradient texture.
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ /** @type {Array<number>} */ var gMin = deMath.add(
+ deMath.multiply([0.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ /** @type {Array<number>} */ var gMax = deMath.add(
+ deMath.multiply([1.0, 1.0, 1.0, 0.0], cScale), cBias
+ );
+
+ this.m_textures[0].getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithComponentGradients(
+ this.m_textures[0].getRefTexture().getLevel(levelNdx),
+ gMin, gMax
+ );
+ }
+
+ // Fill second with grid texture.
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ /** @type {number} */ var step = 0x00ffffff / numLevels;
+ /** @type {number} */ var rgb = step * levelNdx;
+ /** @type {number} */ var colorA = deMath.binaryOp(
+ 0xff000000, rgb, deMath.BinaryOp.OR
+ );
+ /** @type {number} */ var colorB = deMath.binaryOp(
+ 0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR
+ );
+
+ this.m_textures[1].getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithGrid(
+ this.m_textures[1].getRefTexture().getLevel(levelNdx),
+ 4,
+ deMath.add(deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorA).toVec(), cScale),
+ cBias
+ ),
+ deMath.add(deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorB).toVec(), cScale),
+ cBias
+ )
+ );
+ }
+
+ // Upload.
+ for (var i = 0; i < this.m_textures.length; i++)
+ this.m_textures[i].upload();
+
+ // Compute cases.
+
+ /** @type {Array<es3fTextureFilteringTests.Cases>} */
+ var cases = [{
+ texNdx: 0, lodX: 1.6, lodY: 2.9, oX: -1.0, oY: -2.7
+ }, {
+ texNdx: 0, lodX: -2.0, lodY: -1.35, oX: -0.2, oY: 0.7
+ }, {
+ texNdx: 1, lodX: 0.14, lodY: 0.275, oX: -1.5, oY: -1.1
+ }, {
+ texNdx: 1, lodX: -0.92, lodY: -2.64, oX: 0.4, oY: -0.1
+ }
+ ];
+
+ var viewportW = Math.min(
+ TEX2D_VIEWPORT_WIDTH, gl.canvas.width
+ );
+ var viewportH = Math.min(
+ TEX2D_VIEWPORT_HEIGHT, gl.canvas.height
+ );
+
+ for (var caseNdx = 0; caseNdx < cases.length; caseNdx++) {
+ /** @type {number} */ var texNdx = deMath.clamp(
+ cases[caseNdx].texNdx, 0, this.m_textures.length - 1
+ );
+ /** @type {number} */ var lodX = cases[caseNdx].lodX;
+ /** @type {number} */ var lodY = cases[caseNdx].lodY;
+ /** @type {number} */ var oX = cases[caseNdx].oX;
+ /** @type {number} */ var oY = cases[caseNdx].oY;
+ /** @type {number} */ var sX = Math.exp(lodX * Math.log(2)) * viewportW /
+ this.m_textures[texNdx].getRefTexture().getWidth();
+ /** @type {number} */ var sY = Math.exp(lodY * Math.log(2)) * viewportH /
+ this.m_textures[texNdx].getRefTexture().getHeight();
+
+ this.m_cases.push(
+ new
+ es3fTextureFilteringTests.Texture2DFilteringCase.FilterCase(
+ this.m_textures[texNdx], [oX, oY], [oX + sX, oY + sY]
+ )
+ );
+ }
+
+ this.m_caseNdx = 0;
+ }
+ catch (e) {
+ // Clean up to save memory.
+ this.deinit();
+ throw e;
+ }
+ };
+
+ /**
+ * deinit
+ */
+ es3fTextureFilteringTests.Texture2DFilteringCase.prototype.deinit =
+ function() {
+ while (this.m_textures.length > 0) {
+ gl.deleteTexture(this.m_textures[0].getGLTexture());
+ this.m_textures.splice(0, 1);
+ }
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureFilteringTests.Texture2DFilteringCase.prototype.iterate =
+ function() {
+ /** @type {glsTextureTestUtil.RandomViewport} */
+ var viewport = new glsTextureTestUtil.RandomViewport(
+ gl.canvas, TEX2D_VIEWPORT_WIDTH,
+ TEX2D_VIEWPORT_HEIGHT, deMath.binaryOp(
+ deString.deStringHash(this.fullName()),
+ deMath.deMathHash(this.m_caseNdx),
+ deMath.BinaryOp.XOR
+ )
+ );
+ /** @type {tcuTexture.TextureFormat} */
+ var texFmt = this.m_textures[0].getRefTexture().getFormat();
+
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ var curCase = this.m_cases[this.m_caseNdx];
+ bufferedLogToConsole('Test ' + this.m_caseNdx);
+ var refParams = new glsTextureTestUtil.ReferenceParams(
+ glsTextureTestUtil.textureType.TEXTURETYPE_2D
+ );
+ var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
+ var texCoord = [0, 0];
+
+ if (viewport.width < TEX2D_MIN_VIEWPORT_WIDTH ||
+ viewport.height < TEX2D_MIN_VIEWPORT_HEIGHT)
+ throw new Error('Too small render target');
+
+ // Setup params for reference.
+ refParams.sampler = gluTextureUtil.mapGLSamplerWrapST(
+ this.m_wrapS, this.m_wrapT, this.m_minFilter, this.m_magFilter
+ );
+ refParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt);
+ refParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ refParams.colorBias = fmtInfo.lookupBias;
+ refParams.colorScale = fmtInfo.lookupScale;
+
+ // Compute texture coordinates.
+ bufferedLogToConsole(
+ 'Texture coordinates: ' + curCase.minCoord +
+ ' -> ' + curCase.maxCoord
+ );
+ texCoord = glsTextureTestUtil.computeQuadTexCoord2D(
+ curCase.minCoord, curCase.maxCoord
+ );
+
+ gl.bindTexture(gl.TEXTURE_2D, curCase.texture.getGLTexture());
+ gl.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_minFilter
+ );
+ gl.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_magFilter
+ );
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.m_wrapT);
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ this.m_renderer.renderQuad(0, texCoord, refParams);
+ rendered.readViewport(
+ gl, [viewport.x, viewport.y, viewport.width, viewport.height]
+ );
+
+ /** @type {boolean} */ var isNearestOnly =
+ this.m_minFilter == gl.NEAREST && this.m_magFilter == gl.NEAREST;
+ /** @type {tcuPixelFormat.PixelFormat} */
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+
+ //(iVec4)
+ var colorBits = deMath.max(
+ deMath.addScalar(
+ glsTextureTestUtil.getBitsVec(pixelFormat),
+ // 1 inaccurate bit if nearest only, 2 otherwise
+ -1 * (isNearestOnly ? 1 : 2)
+ ),
+ [0, 0, 0, 0]
+ );
+
+ /** @type {tcuTexLookupVerifier.LodPrecision} */
+ var lodPrecision = new tcuTexLookupVerifier.LodPrecision();
+ /** @type {tcuTexLookupVerifier.LookupPrecision} */
+ var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision();
+
+ lodPrecision.derivateBits = 18;
+ lodPrecision.lodBits = 6;
+ lookupPrecision.colorThreshold = deMath.divide(
+ tcuTexLookupVerifier.computeFixedPointThreshold(colorBits),
+ refParams.colorScale
+ );
+ lookupPrecision.coordBits = [20, 20, 0];
+ lookupPrecision.uvwBits = [7, 7, 0];
+ lookupPrecision.colorMask =
+ glsTextureTestUtil.getCompareMask(pixelFormat);
+
+ var isHighQuality = glsTextureTestUtil.verifyTexture2DResult(
+ rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat
+ );
+
+ if (!isHighQuality) {
+ // Evaluate against lower precision requirements.
+ lodPrecision.lodBits = 4;
+ lookupPrecision.uvwBits = [4, 4, 0];
+
+ bufferedLogToConsole('Warning: Verification against high ' +
+ 'precision requirements failed, trying with lower ' +
+ 'requirements.'
+ );
+
+ var isOk = glsTextureTestUtil.verifyTexture2DResult(
+ rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, refParams, lookupPrecision, lodPrecision,
+ pixelFormat
+ );
+
+ if (!isOk) {
+ bufferedLogToConsole(
+ 'ERROR: Verification against low ' +
+ 'precision requirements failed, failing test case.'
+ );
+ testFailedOptions('Image verification failed', false);
+ //In JS version, one mistake and you're out
+ return tcuTestCase.IterateResult.STOP;
+ } else
+ checkMessage(
+ false,
+ 'Low-quality filtering result in iteration no. ' +
+ this.m_caseNdx
+ );
+ }
+
+ this.m_caseNdx += 1;
+ if (this.m_caseNdx < this.m_cases.length)
+ return tcuTestCase.IterateResult.CONTINUE;
+
+ testPassed('Verified');
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {boolean} onlySampleFaceInterior
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureFilteringTests.TextureCubeFilteringCase = function(
+ name, desc, minFilter, magFilter, wrapS, wrapT, onlySampleFaceInterior,
+ internalFormat, width, height
+ ) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_minFilter = minFilter;
+ this.m_magFilter = magFilter;
+ this.m_wrapS = wrapS;
+ this.m_wrapT = wrapT;
+ /** @type {boolean}*/
+ this.m_onlySampleFaceInterior = onlySampleFaceInterior;
+ this.m_internalFormat = internalFormat;
+ this.m_width = width;
+ this.m_height = height;
+ /** @type {glsTextureTestUtil.TextureRenderer} */
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(
+ es3fTextureFilteringTests.version,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ );
+ this.m_caseNdx = 0;
+ /** @type {Array<gluTexture.TextureCube>} */ this.m_textures = [];
+ /** @type {Array<es3fTextureFilteringTests.
+ * TextureCubeFilteringCase.FilterCase>}
+ */
+ this.m_cases = [];
+ };
+
+ /**
+ * @constructor
+ * @param {gluTexture.TextureCube} tex_
+ * @param {Array<number>} bottomLeft_
+ * @param {Array<number>} topRight_
+ */
+ es3fTextureFilteringTests.TextureCubeFilteringCase.FilterCase = function(
+ tex_, bottomLeft_, topRight_
+ ) {
+ this.texture = tex_;
+ this.bottomLeft = bottomLeft_;
+ this.topRight = topRight_;
+ };
+
+ es3fTextureFilteringTests.TextureCubeFilteringCase.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+
+ es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.constructor =
+ es3fTextureFilteringTests.TextureCubeFilteringCase;
+
+ /**
+ * init
+ */
+ es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.init =
+ function() {
+ try {
+ assertMsgOptions(
+ this.m_width == this.m_height, 'Texture has to be squared',
+ false, true
+ );
+ for (var ndx = 0; ndx < 2; ndx++)
+ this.m_textures.push(gluTexture.cubeFromInternalFormat(
+ gl, this.m_internalFormat, this.m_width
+ ));
+
+ var numLevels = deMath.logToFloor(
+ Math.max(this.m_width, this.m_height)
+ ) + 1;
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(
+ this.m_textures[0].getRefTexture().getFormat()
+ );
+ /** @type {Array<number>} */
+ var cBias = fmtInfo.valueMin;
+ /** @type {Array<number>} */
+ var cScale = deMath.subtract(
+ fmtInfo.valueMax, fmtInfo.valueMin
+ );
+
+ // Fill first with gradient texture.
+ /** @type {Array<Array<Array<number>>>}
+ * (array of 4 component vectors)
+ */
+ var gradients = [
+ [ // negative x
+ [0.0, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0]
+ ], [ // positive x
+ [0.5, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0]
+ ], [ // negative y
+ [0.0, 0.5, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0]
+ ], [ // positive y
+ [0.0, 0.0, 0.5, 1.0], [1.0, 1.0, 1.0, 0.0]
+ ], [ // negative z
+ [0.0, 0.0, 0.0, 0.5], [1.0, 1.0, 1.0, 1.0]
+ ], [ // positive z
+ [0.5, 0.5, 0.5, 1.0], [1.0, 1.0, 1.0, 0.0]
+ ]
+ ];
+ for (var face = 0;
+ face < Object.keys(tcuTexture.CubeFace).length;
+ face++) {
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ this.m_textures[0].getRefTexture().allocLevel(
+ face, levelNdx
+ );
+ tcuTextureUtil.fillWithComponentGradients(
+ this.m_textures[0].getRefTexture().getLevelFace(
+ levelNdx, face
+ ),
+ deMath.add(deMath.multiply(
+ gradients[face][0], cScale
+ ), cBias),
+ deMath.add(deMath.multiply(
+ gradients[face][1], cScale
+ ), cBias)
+ );
+ }
+ }
+
+ // Fill second with grid texture.
+ for (var face = 0;
+ face < Object.keys(tcuTexture.CubeFace).length;
+ face++) {
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ var step = 0x00ffffff / (
+ numLevels * Object.keys(tcuTexture.CubeFace).length
+ );
+ var rgb = step * levelNdx * face;
+ /** @type {number} */ var colorA = deMath.binaryOp(
+ 0xff000000, rgb, deMath.BinaryOp.OR
+ );
+ /** @type {number} */ var colorB = deMath.binaryOp(
+ 0xff000000, deMath.binaryNot(rgb),
+ deMath.BinaryOp.OR
+ );
+
+ this.m_textures[1].getRefTexture().allocLevel(
+ face, levelNdx
+ );
+ tcuTextureUtil.fillWithGrid(
+ this.m_textures[1].getRefTexture().getLevelFace(
+ levelNdx, face
+ ), 4, deMath.add(
+ deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorA).toVec(),
+ cScale
+ ), cBias
+ ), deMath.add(
+ deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorB).toVec(),
+ cScale
+ ), cBias
+ )
+ );
+ }
+ }
+
+ // Upload.
+ for (var i = 0; i < this.m_textures.length; i++)
+ this.m_textures[i].upload();
+
+ // Compute cases
+ /** @type {gluTexture.TextureCube} */
+ var tex0 = this.m_textures[0];
+ /** @type {gluTexture.TextureCube} */
+ var tex1 = this.m_textures.length > 1 ? this.m_textures[1] : tex0;
+
+ if (this.m_onlySampleFaceInterior) {
+ // minification
+ this.m_cases.push(new es3fTextureFilteringTests.
+ TextureCubeFilteringCase.FilterCase(
+ tex0, [-0.8, -0.8], [0.8, 0.8]
+ ));
+ // magnification
+ this.m_cases.push(new es3fTextureFilteringTests.
+ TextureCubeFilteringCase.FilterCase(
+ tex0, [0.5, 0.65], [0.8, 0.8]
+ ));
+ // minification
+ this.m_cases.push(new es3fTextureFilteringTests.
+ TextureCubeFilteringCase.FilterCase(
+ tex1, [-0.8, -0.8], [0.8, 0.8]
+ ));
+ // magnification
+ this.m_cases.push(new es3fTextureFilteringTests.
+ TextureCubeFilteringCase.FilterCase(
+ tex1, [0.2, 0.2], [0.6, 0.5]
+ ));
+ } else {
+ // minification
+ if (gl.getParameter(gl.SAMPLES) == 0)
+ this.m_cases.push(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase.
+ FilterCase(
+ tex0, [-1.25, -1.2], [1.2, 1.25]
+ )
+ );
+ // minification - w/ tweak to avoid hitting triangle
+ // edges with face switchpoint.
+ else
+ this.m_cases.push(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase.
+ FilterCase(
+ tex0, [-1.19, -1.3], [1.1, 1.35]
+ )
+ );
+
+ // magnification
+ this.m_cases.push(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase.
+ FilterCase(
+ tex0, [0.8, 0.8], [1.25, 1.20]
+ )
+ );
+ // minification
+ this.m_cases.push(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase.
+ FilterCase(
+ tex1, [-1.19, -1.3], [1.1, 1.35]
+ )
+ );
+ // magnification
+ this.m_cases.push(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase.
+ FilterCase(
+ tex1, [-1.2, -1.1], [-0.8, -0.8]
+ )
+ );
+ }
+
+ this.m_caseNdx = 0;
+ }
+ catch (e) {
+ // Clean up to save memory.
+ this.deinit();
+ throw e;
+ }
+ };
+
+ /**
+ * deinit
+ */
+ es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.deinit =
+ function() {
+ while (this.m_textures.length > 0) {
+ gl.deleteTexture(this.m_textures[0].getGLTexture());
+ this.m_textures.splice(0, 1);
+ }
+ };
+
+ /**
+ * @param {tcuTexture.CubeFace} face
+ * @return {string}
+ */
+ es3fTextureFilteringTests.getFaceDesc = function(face) {
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return '-X';
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return '+X';
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return '-Y';
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return '+Y';
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return '-Z';
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return '+Z';
+ default:
+ throw new Error('Invalid cube face specified');
+ }
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.iterate =
+ function() {
+ var viewportSize = 28;
+ /** @type {glsTextureTestUtil.RandomViewport} */
+ var viewport = new glsTextureTestUtil.RandomViewport(
+ gl.canvas, viewportSize,
+ viewportSize, deMath.binaryOp(
+ deString.deStringHash(this.fullName()),
+ deMath.deMathHash(this.m_caseNdx),
+ deMath.BinaryOp.XOR
+ )
+ );
+ bufferedLogToConsole('Test' + this.m_caseNdx);
+ /** @type {es3fTextureFilteringTests.
+ * TextureCubeFilteringCase.FilterCase}
+ */
+ var curCase = this.m_cases[this.m_caseNdx];
+ /** @type {tcuTexture.TextureFormat} */
+ var texFmt = curCase.texture.getRefTexture().getFormat();
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ /** @type {glsTextureTestUtil.ReferenceParams} */
+ var sampleParams = new glsTextureTestUtil.ReferenceParams(
+ glsTextureTestUtil.textureType.TEXTURETYPE_CUBE
+ );
+
+ if (viewport.width < viewportSize || viewport.height < viewportSize)
+ throw new Error('Too small render target');
+
+ // Setup texture
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, curCase.texture.getGLTexture());
+ gl.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, this.m_minFilter
+ );
+ gl.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, this.m_magFilter
+ );
+ gl.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this.m_wrapS
+ );
+ gl.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this.m_wrapT
+ );
+
+ // Other state
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ // Params for reference computation.
+ sampleParams.sampler = gluTextureUtil.mapGLSamplerWrapST(
+ gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE,
+ this.m_minFilter, this.m_magFilter
+ );
+ sampleParams.sampler.seamlessCubeMap = true;
+ sampleParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt);
+ sampleParams.colorBias = fmtInfo.lookupBias;
+ sampleParams.colorScale = fmtInfo.lookupScale;
+ sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+
+ bufferedLogToConsole(
+ 'Coordinates: ' + curCase.bottomLeft + ' -> ' + curCase.topRight
+ );
+
+ for (var faceNdx = 0;
+ faceNdx < Object.keys(tcuTexture.CubeFace).length;
+ faceNdx++) {
+ var face = /** @type {tcuTexture.CubeFace} */ (faceNdx);
+ /** @type {tcuSurface.Surface} */
+ var result = new tcuSurface.Surface(
+ viewport.width, viewport.height
+ );
+ /** @type {Array<number>} */ var texCoord;
+
+ texCoord = glsTextureTestUtil.computeQuadTexCoordCubeFace(
+ face, curCase.bottomLeft, curCase.topRight
+ );
+
+ bufferedLogToConsole(
+ 'Face ' + es3fTextureFilteringTests.getFaceDesc(face)
+ );
+
+ // \todo Log texture coordinates.
+
+ this.m_renderer.renderQuad(0, texCoord, sampleParams);
+
+ result.readViewport(
+ gl, [viewport.x, viewport.y, viewport.width, viewport.height]
+ );
+
+ /** @type {boolean} */
+ var isNearestOnly = this.m_minFilter == gl.NEAREST &&
+ this.m_magFilter == gl.NEAREST;
+ /** @type {tcuPixelFormat.PixelFormat} */
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+
+ //(iVec4)
+ var colorBits = deMath.max(
+ deMath.addScalar(
+ glsTextureTestUtil.getBitsVec(pixelFormat),
+ // 1 inaccurate bit if nearest only, 2 otherwise
+ -1 * (isNearestOnly ? 1 : 2)
+ ),
+ [0, 0, 0, 0]
+ );
+ /** @type {tcuTexLookupVerifier.LodPrecision} */
+ var lodPrecision = new tcuTexLookupVerifier.LodPrecision();
+ /** @type {tcuTexLookupVerifier.LookupPrecision} */
+ var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision();
+
+ lodPrecision.derivateBits = 10;
+ lodPrecision.lodBits = 5;
+ lookupPrecision.colorThreshold = deMath.divide(
+ tcuTexLookupVerifier.computeFixedPointThreshold(colorBits),
+ sampleParams.colorScale
+ );
+ lookupPrecision.coordBits = [10, 10, 10];
+ lookupPrecision.uvwBits = [6, 6, 0];
+ lookupPrecision.colorMask =
+ glsTextureTestUtil.getCompareMask(pixelFormat);
+
+ var isHighQuality = glsTextureTestUtil.verifyTextureCubeResult(
+ result.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, lookupPrecision, lodPrecision,
+ pixelFormat
+ );
+
+
+ if (!isHighQuality) {
+ // Evaluate against lower precision requirements.
+ lodPrecision.lodBits = 2;
+ lookupPrecision.uvwBits = [3, 3, 0];
+
+ bufferedLogToConsole('Warning: Verification against high ' +
+ 'precision requirements failed, trying with lower ' +
+ 'requirements.');
+
+ var isOk = glsTextureTestUtil.verifyTextureCubeResult(
+ result.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, lookupPrecision, lodPrecision,
+ pixelFormat
+ );
+
+ if (!isOk) {
+ bufferedLogToConsole('ERROR: Verification against low' +
+ 'precision requirements failed, failing test case.');
+ testFailedOptions('Image verification failed', false);
+ //In JS version, one mistake and you're out
+ return tcuTestCase.IterateResult.STOP;
+ } else
+ checkMessage(
+ false,
+ 'Low-quality filtering result in iteration no. ' +
+ this.m_caseNdx
+ );
+ }
+ }
+
+ this.m_caseNdx += 1;
+ if (this.m_caseNdx < this.m_cases.length)
+ return tcuTestCase.IterateResult.CONTINUE;
+
+ testPassed('Verified');
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ // 2D array filtering
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ */
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase = function(
+ name, desc, minFilter, magFilter, wrapS, wrapT,
+ internalFormat, width, height, numLayers
+ ) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_minFilter = minFilter;
+ this.m_magFilter = magFilter;
+ this.m_wrapS = wrapS;
+ this.m_wrapT = wrapT;
+ this.m_internalFormat = internalFormat;
+ this.m_width = width;
+ this.m_height = height;
+ this.m_numLayers = numLayers;
+ this.m_gradientTex = null;
+ this.m_gridTex = null;
+ /** @type {glsTextureTestUtil.TextureRenderer} */
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(
+ es3fTextureFilteringTests.version,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ );
+ this.m_textures = [];
+ this.m_caseNdx = 0;
+ this.m_cases = [];
+ };
+
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.
+ constructor = es3fTextureFilteringTests.Texture2DArrayFilteringCase;
+
+ /**
+ * @constructor
+ * @param {gluTexture.Texture2DArray} tex_
+ * @param {Array<number>} lod_
+ * @param {Array<number>} offset_
+ * @param {Array<number>} layerRange_
+ */
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase.FilterCase =
+ function(
+ tex_, lod_, offset_, layerRange_
+ ) {
+ this.texture = tex_;
+ this.lod = lod_;
+ this.offset = offset_;
+ this.layerRange = layerRange_;
+ };
+
+ /*
+ * init
+ */
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.init =
+ function() {
+ try {
+ /** @type {tcuTexture.TextureFormat} */
+ var texFmt = gluTextureUtil.mapGLInternalFormat(
+ this.m_internalFormat
+ );
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ var cScale = deMath.subtract(
+ fmtInfo.valueMax, fmtInfo.valueMin
+ );
+ var cBias = fmtInfo.valueMin;
+ var numLevels = deMath.logToFloor(
+ Math.max(this.m_width, this.m_height)
+ ) + 1;
+
+ // Create textures.
+ this.m_gradientTex = gluTexture.texture2DArrayFromInternalFormat(
+ gl,
+ this.m_internalFormat, this.m_width,
+ this.m_height, this.m_numLayers
+ );
+
+ this.m_gridTex = gluTexture.texture2DArrayFromInternalFormat(
+ gl,
+ this.m_internalFormat, this.m_width,
+ this.m_height, this.m_numLayers
+ );
+
+ var levelSwz = [
+ [0, 1, 2, 3],
+ [2, 1, 3, 0],
+ [3, 0, 1, 2],
+ [1, 3, 2, 0]
+ ];
+
+ // Fill first gradient texture
+ // (gradient direction varies between layers).
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ this.m_gradientTex.getRefTexture().allocLevel(levelNdx);
+
+ var levelBuf =
+ this.m_gradientTex.getRefTexture().getLevel(levelNdx);
+
+ for (var layerNdx = 0;
+ layerNdx < this.m_numLayers;
+ layerNdx++) {
+ var swz = levelSwz[layerNdx % levelSwz.length];
+ var gMin = deMath.add(deMath.multiply(deMath.swizzle(
+ [0.0, 0.0, 0.0, 1.0], [swz[0], swz[1], swz[2], swz[3]]
+ ), cScale), cBias);
+ var gMax = deMath.add(deMath.multiply(deMath.swizzle(
+ [1.0, 1.0, 1.0, 0.0], [swz[0], swz[1], swz[2], swz[3]]
+ ), cScale), cBias);
+
+ tcuTextureUtil.fillWithComponentGradients2D(
+ tcuTextureUtil.getSubregion(
+ levelBuf, 0, 0, layerNdx, levelBuf.getWidth(),
+ levelBuf.getHeight(), 1
+ ), gMin, gMax
+ );
+ }
+ }
+
+ // Fill second with grid texture (each layer has unique colors).
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ this.m_gridTex.getRefTexture().allocLevel(levelNdx);
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var levelBuf =
+ this.m_gridTex.getRefTexture().getLevel(levelNdx);
+
+ for (
+ var layerNdx = 0;
+ layerNdx < this.m_numLayers;
+ layerNdx++) {
+ var step = 0x00ffffff / (numLevels * this.m_numLayers - 1);
+ var rgb = step * (levelNdx + layerNdx * numLevels);
+ /** @type {number} */ var colorA = deMath.binaryOp(
+ 0xff000000, rgb, deMath.BinaryOp.OR
+ );
+ /** @type {number} */ var colorB = deMath.binaryOp(
+ 0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR
+ );
+
+ tcuTextureUtil.fillWithGrid(
+ tcuTextureUtil.getSubregion(
+ levelBuf, 0, 0, layerNdx, levelBuf.getWidth(),
+ levelBuf.getHeight(), 1
+ ), 4,
+ deMath.add(
+ deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorA).toVec(),
+ cScale
+ ), cBias
+ ),
+ deMath.add(
+ deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorB).toVec(),
+ cScale
+ ), cBias
+ )
+ );
+ }
+ }
+
+ // Upload.
+ this.m_gradientTex.upload();
+ this.m_gridTex.upload();
+
+ // Test cases
+ this.m_cases.push(
+ new es3fTextureFilteringTests.
+ Texture2DArrayFilteringCase.FilterCase(
+ this.m_gradientTex, [1.5, 2.8], [-1.0, -2.7],
+ [-0.5, this.m_numLayers + 0.5]
+ )
+ );
+ this.m_cases.push(
+ new es3fTextureFilteringTests.
+ Texture2DArrayFilteringCase.FilterCase(
+ this.m_gridTex, [0.2, 0.175], [-2.0, -3.7],
+ [-0.5, this.m_numLayers + 0.5]
+ )
+ );
+ this.m_cases.push(
+ new es3fTextureFilteringTests.
+ Texture2DArrayFilteringCase.FilterCase(
+ this.m_gridTex, [-0.8, -2.3], [0.2, -0.1],
+ [this.m_numLayers + 0.5, -0.5]
+ )
+ );
+
+ // Level rounding - only in single-sample configs as
+ // multisample configs may produce smooth transition at the middle.
+ if (gl.getParameter(gl.SAMPLES) == 0)
+ this.m_cases.push(
+ new es3fTextureFilteringTests.
+ Texture2DArrayFilteringCase.FilterCase(
+ this.m_gradientTex, [-2.0, -1.5], [-0.1, 0.9],
+ [1.50001, 1.49999]
+ )
+ );
+
+ this.m_caseNdx = 0;
+ }
+ catch (e) {
+ // Clean up to save memory.
+ this.deinit();
+ throw e;
+ }
+ };
+
+ /**
+ * deinit
+ */
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.deinit =
+ function() {
+ if (this.m_gradientTex)
+ gl.deleteTexture(this.m_gradientTex.getGLTexture());
+ if (this.m_gridTex)
+ gl.deleteTexture(this.m_gridTex.getGLTexture());
+
+ this.m_gradientTex = null;
+ this.m_gridTex = null;
+ };
+
+ /**
+ * iterate
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.iterate =
+ function() {
+ /** @type {glsTextureTestUtil.RandomViewport} */
+ var viewport = new glsTextureTestUtil.RandomViewport(
+ gl.canvas, TEX3D_VIEWPORT_WIDTH,
+ TEX3D_VIEWPORT_HEIGHT, deMath.binaryOp(
+ deString.deStringHash(this.fullName()),
+ deMath.deMathHash(this.m_caseNdx),
+ deMath.BinaryOp.XOR
+ )
+ );
+
+ /** @type {es3fTextureFilteringTests.Texture2DArrayFilteringCase.
+ * FilterCase} */ var curCase = this.m_cases[this.m_caseNdx];
+
+ /** @type {tcuTexture.TextureFormat} */
+ var texFmt = curCase.texture.getRefTexture().getFormat();
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+
+ bufferedLogToConsole('Test' + this.m_caseNdx);
+
+ /** @type {glsTextureTestUtil.ReferenceParams} */
+ var refParams = new glsTextureTestUtil.ReferenceParams(
+ glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY
+ );
+
+ /** @type {tcuSurface.Surface} */
+ var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
+
+ if (viewport.width < TEX3D_MIN_VIEWPORT_WIDTH ||
+ viewport.height < TEX3D_MIN_VIEWPORT_HEIGHT)
+ throw new Error('Too small render target');
+
+ // Setup params for reference.
+ refParams.sampler = gluTextureUtil.mapGLSampler(
+ this.m_wrapS, this.m_wrapT, this.m_wrapT,
+ this.m_minFilter, this.m_magFilter
+ );
+ refParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt);
+ refParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ refParams.colorBias = fmtInfo.lookupBias;
+ refParams.colorScale = fmtInfo.lookupScale;
+
+ // Compute texture coordinates.
+ bufferedLogToConsole(
+ 'Approximate lod per axis = ' + curCase.lod +
+ ', offset = ' + curCase.offset
+ );
+
+ /** @type {number} */ var lodX = curCase.lod[0];
+ /** @type {number} */ var lodY = curCase.lod[1];
+ /** @type {number} */ var oX = curCase.offset[0];
+ /** @type {number} */ var oY = curCase.offset[1];
+ /** @type {number} */ var sX = Math.pow(2, lodX) * viewport.width /
+ this.m_gradientTex.getRefTexture().getWidth();
+ /** @type {number} */ var sY = Math.pow(2, lodY) * viewport.height /
+ this.m_gradientTex.getRefTexture().getHeight();
+ /** @type {number} */ var l0 = curCase.layerRange[0];
+ /** @type {number} */ var l1 = curCase.layerRange[1];
+
+ /** @type {Array<number>}*/
+ var texCoord = [
+ oX, oY, l0,
+ oX, oY + sY, l0 * 0.5 + l1 * 0.5,
+ oX + sX, oY, l0 * 0.5 + l1 * 0.5,
+ oX + sX, oY + sY, l1
+ ];
+
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, curCase.texture.getGLTexture());
+ gl.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, this.m_minFilter
+ );
+ gl.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, this.m_magFilter
+ );
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, this.m_wrapT);
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+ this.m_renderer.renderQuad(
+ 0, texCoord,
+ refParams
+ );
+ rendered.readViewport(
+ gl, [viewport.x, viewport.y, viewport.width, viewport.height]
+ );
+
+ /** @type {boolean} */
+ var isNearestOnly = this.m_minFilter == gl.NEAREST &&
+ this.m_magFilter == gl.NEAREST;
+ /** @type {tcuPixelFormat.PixelFormat} */
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ //(iVec4)
+ var colorBits = deMath.max(
+ deMath.addScalar(
+ glsTextureTestUtil.getBitsVec(pixelFormat),
+ // 1 inaccurate bit if nearest only, 2 otherwise
+ -1 * (isNearestOnly ? 1 : 2)
+ ),
+ [0, 0, 0, 0]
+ );
+ /** @type {tcuTexLookupVerifier.LodPrecision} */
+ var lodPrecision = new tcuTexLookupVerifier.LodPrecision();
+ /** @type {tcuTexLookupVerifier.LookupPrecision} */
+ var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision();
+
+ lodPrecision.derivateBits = 18;
+ lodPrecision.lodBits = 6;
+ lookupPrecision.colorThreshold = deMath.divide(
+ tcuTexLookupVerifier.computeFixedPointThreshold(colorBits),
+ refParams.colorScale
+ );
+ lookupPrecision.coordBits = [20, 20, 20];
+ lookupPrecision.uvwBits = [7, 7, 0];
+ lookupPrecision.colorMask =
+ glsTextureTestUtil.getCompareMask(pixelFormat);
+
+ var isHighQuality = glsTextureTestUtil.verifyTexture2DArrayResult(
+ rendered.getAccess(), curCase.texture.getRefTexture().getView(),
+ texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat);
+
+ if (!isHighQuality) {
+ // Evaluate against lower precision requirements.
+ lodPrecision.lodBits = 3;
+ lookupPrecision.uvwBits = [3, 3, 0];
+
+ bufferedLogToConsole(
+ 'Warning: Verification against high ' +
+ 'precision requirements failed, ' +
+ 'trying with lower requirements.'
+ );
+
+ var isOk = glsTextureTestUtil.verifyTexture2DArrayResult(
+ rendered.getAccess(), curCase.texture.getRefTexture().getView(),
+ texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat
+ );
+
+ if (!isOk) {
+ bufferedLogToConsole(
+ 'ERROR: Verification against low precision requirements ' +
+ 'failed, failing test case.'
+ );
+ testFailedOptions('Image verification failed', false);
+ //In JS version, one mistake and you're out
+ return tcuTestCase.IterateResult.STOP;
+ } else
+ checkMessage(
+ false,
+ 'Low-quality filtering result in iteration no. ' +
+ this.m_caseNdx
+ );
+ }
+
+ this.m_caseNdx += 1;
+ if (this.m_caseNdx < this.m_cases.length)
+ return tcuTestCase.IterateResult.CONTINUE;
+
+ testPassed('Verified');
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ // 3D filtering
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} wrapR
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+ es3fTextureFilteringTests.Texture3DFilteringCase = function(
+ name, desc, minFilter, magFilter, wrapS, wrapT, wrapR, internalFormat,
+ width, height, depth
+ ) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_minFilter = minFilter;
+ this.m_magFilter = magFilter;
+ this.m_wrapS = wrapS;
+ this.m_wrapT = wrapT;
+ this.m_wrapR = wrapR;
+ this.m_internalFormat = internalFormat;
+ this.m_width = width;
+ this.m_height = height;
+ this.m_depth = depth;
+ this.m_gradientTex = null;
+ this.m_gridTex = null;
+ /** @type {glsTextureTestUtil.TextureRenderer} */
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(
+ es3fTextureFilteringTests.version,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ );
+ this.m_caseNdx = 0;
+ this.m_cases = [];
+ };
+
+ es3fTextureFilteringTests.Texture3DFilteringCase.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+
+ es3fTextureFilteringTests.Texture3DFilteringCase.prototype.constructor =
+ es3fTextureFilteringTests.Texture3DFilteringCase;
+
+ /**
+ * @constructor
+ * @param {gluTexture.Texture3D} tex_
+ * @param {Array<number>} lod_
+ * @param {Array<number>} offset_
+ */
+ es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase = function(
+ tex_, lod_, offset_
+ ) {
+ this.texture = tex_;
+ this.lod = lod_;
+ this.offset = offset_;
+ };
+
+ /**
+ * init
+ */
+ es3fTextureFilteringTests.Texture3DFilteringCase.prototype.init = function(
+ ) {
+ try {
+ /** @type {tcuTexture.TextureFormat} */
+ var texFmt =
+ gluTextureUtil.mapGLInternalFormat(this.m_internalFormat);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ var cScale = deMath.subtract(
+ fmtInfo.valueMax, fmtInfo.valueMin
+ );
+ var cBias = fmtInfo.valueMin;
+ var numLevels = deMath.logToFloor(
+ Math.max(Math.max(this.m_width, this.m_height), this.m_depth)
+ ) + 1;
+
+ // Create textures.
+ this.m_gradientTex = gluTexture.texture3DFromInternalFormat(
+ gl, this.m_internalFormat,
+ this.m_width, this.m_height, this.m_depth
+ );
+
+ this.m_gridTex = gluTexture.texture3DFromInternalFormat(
+ gl, this.m_internalFormat,
+ this.m_width, this.m_height, this.m_depth
+ );
+
+ // Fill first gradient texture.
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ var gMin = deMath.add(
+ deMath.multiply([0.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+
+ var gMax = deMath.add(
+ deMath.multiply([1.0, 1.0, 1.0, 0.0], cScale), cBias
+ );
+
+ this.m_gradientTex.getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithComponentGradients(
+ this.m_gradientTex.getRefTexture().getLevel(levelNdx),
+ gMin, gMax
+ );
+ }
+
+ // Fill second with grid texture.
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ /** @type {number} */ var step = 0x00ffffff / numLevels;
+ /** @type {number} */ var rgb = step * levelNdx;
+ /** @type {number} */ var colorA = deMath.binaryOp(
+ 0xff000000, rgb, deMath.BinaryOp.OR
+ );
+ /** @type {number} */ var colorB = deMath.binaryOp(
+ 0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR
+ );
+
+ this.m_gridTex.getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithGrid(
+ this.m_gridTex.getRefTexture().getLevel(levelNdx), 4,
+ deMath.add(
+ deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorA).toVec(),
+ cScale
+ ),
+ cBias
+ ),
+ deMath.add(
+ deMath.multiply(
+ tcuRGBA.newRGBAFromValue(colorB).toVec(),
+ cScale
+ ),
+ cBias
+ )
+ );
+ }
+
+ // Upload.
+ this.m_gradientTex.upload();
+ this.m_gridTex.upload();
+
+ // Test cases
+ this.m_cases.push(
+ new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase(
+ this.m_gradientTex, [1.5, 2.8, 1.0], [-1.0, -2.7, -2.275]
+ )
+ );
+ this.m_cases.push(
+ new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase(
+ this.m_gradientTex, [-2.0, -1.5, -1.8], [-0.1, 0.9, -0.25]
+ )
+ );
+ this.m_cases.push(
+ new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase(
+ this.m_gridTex, [0.2, 0.175, 0.3], [-2.0, -3.7, -1.825]
+ )
+ );
+ this.m_cases.push(
+ new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase(
+ this.m_gridTex, [-0.8, -2.3, -2.5], [0.2, -0.1, 1.325]
+ )
+ );
+
+ this.m_caseNdx = 0;
+ }
+ catch (e) {
+ // Clean up to save memory.
+ this.deinit();
+ throw e;
+ }
+ };
+
+ /**
+ * deinit
+ */
+ es3fTextureFilteringTests.Texture3DFilteringCase.prototype.deinit =
+ function() {
+ if (this.m_gradientTex)
+ gl.deleteTexture(this.m_gradientTex.getGLTexture());
+ if (this.m_gridTex)
+ gl.deleteTexture(this.m_gridTex.getGLTexture());
+
+ this.m_gradientTex = null;
+ this.m_gridTex = null;
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureFilteringTests.Texture3DFilteringCase.prototype.iterate =
+ function() {
+ /** @type {glsTextureTestUtil.RandomViewport} */
+ var viewport = new glsTextureTestUtil.RandomViewport(
+ gl.canvas, TEX3D_VIEWPORT_WIDTH,
+ TEX3D_VIEWPORT_HEIGHT, deMath.binaryOp(
+ deString.deStringHash(this.fullName()),
+ deMath.deMathHash(this.m_caseNdx),
+ deMath.BinaryOp.XOR
+ )
+ );
+
+ /** @type {es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase}
+ */ var curCase = this.m_cases[this.m_caseNdx];
+
+ /** @type {tcuTexture.TextureFormat} */
+ var texFmt = curCase.texture.getRefTexture().getFormat();
+ /** @type {tcuTextureUtil.TextureFormatInfo} */
+ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+
+ bufferedLogToConsole('Test' + this.m_caseNdx);
+ /** @type {glsTextureTestUtil.ReferenceParams} */
+ var refParams = new glsTextureTestUtil.ReferenceParams(
+ glsTextureTestUtil.textureType.TEXTURETYPE_3D
+ );
+
+ /** @type {tcuSurface.Surface} */
+ var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
+ /** @type {Array<number>}*/
+ var texCoord = [];
+
+ if (viewport.width < TEX3D_MIN_VIEWPORT_WIDTH ||
+ viewport.height < TEX3D_MIN_VIEWPORT_HEIGHT)
+ throw new Error('Too small render target');
+
+ // Setup params for reference.
+ refParams.sampler = gluTextureUtil.mapGLSampler(
+ this.m_wrapS, this.m_wrapT, this.m_wrapR,
+ this.m_minFilter, this.m_magFilter
+ );
+
+ // Setup params for reference.
+ refParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt);
+ refParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ refParams.colorBias = fmtInfo.lookupBias;
+ refParams.colorScale = fmtInfo.lookupScale;
+
+ // Compute texture coordinates.
+ bufferedLogToConsole('Approximate lod per axis = ' + curCase.lod +
+ ', offset = ' + curCase.offset);
+
+ /** @type {number} */ var lodX = curCase.lod[0];
+ /** @type {number} */ var lodY = curCase.lod[1];
+ /** @type {number} */ var lodZ = curCase.lod[2];
+ /** @type {number} */ var oX = curCase.offset[0];
+ /** @type {number} */ var oY = curCase.offset[1];
+ /** @type {number} */ var oZ = curCase.offset[2];
+ /** @type {number} */ var sX = Math.pow(2, lodX) * viewport.width /
+ this.m_gradientTex.getRefTexture().getWidth();
+ /** @type {number} */ var sY = Math.pow(2, lodY) * viewport.height /
+ this.m_gradientTex.getRefTexture().getHeight();
+ /** @type {number} */ var sZ = Math.pow(2, lodZ) *
+ Math.max(viewport.width, viewport.height) /
+ this.m_gradientTex.getRefTexture().getDepth();
+
+ texCoord[0] = oX; texCoord[1] = oY; texCoord[2] = oZ;
+ texCoord[3] = oX; texCoord[4] = oY + sY; texCoord[5] = oZ + sZ * 0.5;
+ texCoord[6] = oX + sX; texCoord[7] = oY; texCoord[8] = oZ + sZ * 0.5;
+ texCoord[9] = oX + sX; texCoord[10] = oY + sY; texCoord[11] = oZ + sZ;
+
+ gl.bindTexture(gl.TEXTURE_3D, curCase.texture.getGLTexture());
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, this.m_minFilter
+ );
+ gl.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, this.m_magFilter
+ );
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, this.m_wrapT);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, this.m_wrapR);
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+ this.m_renderer.renderQuad(0, texCoord, refParams);
+ rendered.readViewport(
+ gl, [viewport.x, viewport.y, viewport.width, viewport.height]
+ );
+
+ var isNearestOnly = this.m_minFilter == gl.NEAREST &&
+ this.m_magFilter == gl.NEAREST;
+ /** @type {tcuPixelFormat.PixelFormat} */
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ //(iVec4)
+ var colorBits = deMath.max(
+ deMath.addScalar(
+ glsTextureTestUtil.getBitsVec(pixelFormat),
+ // 1 inaccurate bit if nearest only, 2 otherwise
+ -1 * (isNearestOnly ? 1 : 2)
+ ),
+ [0, 0, 0, 0]
+ );
+ /** @type {tcuTexLookupVerifier.LodPrecision} */
+ var lodPrecision = new tcuTexLookupVerifier.LodPrecision();
+ /** @type {tcuTexLookupVerifier.LookupPrecision} */
+ var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision();
+
+ lodPrecision.derivateBits = 18;
+ lodPrecision.lodBits = 6;
+ lookupPrecision.colorThreshold = deMath.divide(
+ tcuTexLookupVerifier.computeFixedPointThreshold(colorBits),
+ refParams.colorScale
+ );
+ lookupPrecision.coordBits = [20, 20, 20];
+ lookupPrecision.uvwBits = [7, 7, 7];
+ lookupPrecision.colorMask =
+ glsTextureTestUtil.getCompareMask(pixelFormat);
+
+ var isHighQuality = glsTextureTestUtil.verifyTexture3DResult(
+ rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat
+ );
+
+ if (!isHighQuality) {
+ // Evaluate against lower precision requirements.
+ lodPrecision.lodBits = 4;
+ lookupPrecision.uvwBits = [4, 4, 4];
+
+ bufferedLogToConsole(
+ 'Warning: Verification against high precision ' +
+ 'requirements failed, trying with lower requirements.'
+ );
+
+ var isOk = glsTextureTestUtil.verifyTexture3DResult(
+ rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat
+ );
+
+ if (!isOk) {
+ bufferedLogToConsole('ERROR: Verification against low ' +
+ 'precision requirements failed, failing test case.'
+ );
+ testFailedOptions('Image verification failed', false);
+ //In JS version, one mistake and you're out
+ return tcuTestCase.IterateResult.STOP;
+ } else
+ checkMessage(
+ false,
+ 'Low-quality filtering result in iteration no. ' +
+ this.m_caseNdx
+ );
+ }
+
+ this.m_caseNdx += 1;
+ if (this.m_caseNdx < this.m_cases.length)
+ return tcuTestCase.IterateResult.CONTINUE;
+
+ testPassed('Verified');
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /** @typedef {{name: string, mode: number}} */
+ es3fTextureFilteringTests.WrapMode;
+
+ /** @typedef {{name: string, mode: number}} */
+ es3fTextureFilteringTests.MinFilterMode;
+
+ /** @typedef {{name: string, mode: number}} */
+ es3fTextureFilteringTests.MagFilterModes;
+
+ /** @typedef {{width: number, height: number}} */
+ es3fTextureFilteringTests.Sizes2D;
+
+ /** @typedef {{width: number, height: number}} */
+ es3fTextureFilteringTests.SizesCube;
+
+ /** @typedef {{width: number, height: number, numLayers: number}} */
+ es3fTextureFilteringTests.Sizes2DArray;
+
+ /** @typedef {{width: number, height: number, depth: number}} */
+ es3fTextureFilteringTests.Sizes3D;
+
+ /** @typedef {{name: string, format: number}} */
+ es3fTextureFilteringTests.FilterableFormatsByType;
+
+ /**
+ * init
+ */
+ es3fTextureFilteringTests.TextureFilteringTests.prototype.init =
+ function() {
+ /** @type {Array<es3fTextureFilteringTests.WrapMode>} */
+ var wrapModes = [{
+ name: 'clamp', mode: gl.CLAMP_TO_EDGE
+ }, {
+ name: 'repeat', mode: gl.REPEAT
+ }, {
+ name: 'mirror', mode: gl.MIRRORED_REPEAT
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.MinFilterMode>} */
+ var minFilterModes = [{
+ name: 'nearest', mode: gl.NEAREST
+ }, {
+ name: 'linear', mode: gl.LINEAR
+ }, {
+ name: 'nearest_mipmap_nearest', mode: gl.NEAREST_MIPMAP_NEAREST
+ }, {
+ name: 'linear_mipmap_nearest', mode: gl.LINEAR_MIPMAP_NEAREST
+ }, {
+ name: 'nearest_mipmap_linear', mode: gl.NEAREST_MIPMAP_LINEAR
+ }, {
+ name: 'linear_mipmap_linear', mode: gl.LINEAR_MIPMAP_LINEAR
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.MagFilterModes>} */
+ var magFilterModes = [{
+ name: 'nearest', mode: gl.NEAREST
+ }, {
+ name: 'linear', mode: gl.LINEAR
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.Sizes2D>} */
+ var sizes2D = [{
+ width: 4, height: 8
+ }, {
+ width: 32, height: 64
+ }, {
+ width: 128, height: 128
+ }, {
+ width: 3, height: 7
+ }, {
+ width: 31, height: 55
+ }, {
+ width: 127, height: 99
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.SizesCube>} */
+ var sizesCube = [{
+ width: 8, height: 8
+ }, {
+ width: 64, height: 64
+ }, {
+ width: 128, height: 128
+ }, {
+ width: 7, height: 7
+ }, {
+ width: 63, height: 63
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.Sizes2DArray>} */
+ var sizes2DArray = [{
+ width: 4, height: 8, numLayers: 8
+ }, {
+ width: 32, height: 64, numLayers: 16
+ }, {
+ width: 128, height: 32, numLayers: 64
+ }, {
+ width: 3, height: 7, numLayers: 5
+ }, {
+ width: 63, height: 63, numLayers: 63
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.Sizes3D>} */
+ var sizes3D = [{
+ width: 4, height: 8, depth: 8
+ }, {
+ width: 32, height: 64, depth: 16
+ }, {
+ width: 128, height: 32, depth: 64
+ }, {
+ width: 3, height: 7, depth: 5
+ }, {
+ width: 63, height: 63, depth: 63
+ }
+ ];
+
+ /** @type {Array<es3fTextureFilteringTests.FilterableFormatsByType>} */
+ var filterableFormatsByType = [{
+ name: 'rgba16f', format: gl.RGBA16F
+ }, {
+ name: 'r11f_g11f_b10f', format: gl.R11F_G11F_B10F
+ }, {
+ name: 'rgb9_e5', format: gl.RGB9_E5
+ }, {
+ name: 'rgba8', format: gl.RGBA8
+ }, {
+ name: 'rgba8_snorm', format: gl.RGBA8_SNORM
+ }, {
+ name: 'rgb565', format: gl.RGB565
+ }, {
+ name: 'rgba4', format: gl.RGBA4
+ }, {
+ name: 'rgb5_a1', format: gl.RGB5_A1
+ }, {
+ name: 'srgb8_alpha8', format: gl.SRGB8_ALPHA8
+ }, {
+ name: 'rgb10_a2', format: gl.RGB10_A2
+ }
+ ];
+
+ // 2D texture filtering.
+
+ // Formats.
+ /** @type {tcuTestCase.DeqpTest} */
+ var formatsGroup;
+ for (var fmtNdx = 0;
+ fmtNdx < filterableFormatsByType.length;
+ fmtNdx++) {
+ formatsGroup = new tcuTestCase.DeqpTest(
+ '2d_formats', '2D Texture Formats');
+ this.addChild(formatsGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ /** @type {number} */
+ var minFilter = minFilterModes[filterNdx].mode;
+ /** @type {string} */
+ var filterName = minFilterModes[filterNdx].name;
+ /** @type {number} */
+ var format = filterableFormatsByType[fmtNdx].format;
+ /** @type {string} */
+ var formatName = filterableFormatsByType[fmtNdx].name;
+ var isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ /** @type {number} */
+ var magFilter = isMipmap ? gl.LINEAR : minFilter;
+ /** @type {string} */
+ var name = formatName + '_' + filterName;
+ /** @type {number} */
+ var wrapS = gl.REPEAT;
+ /** @type {number} */
+ var wrapT = gl.REPEAT;
+ /** @type {number} */ var width = 64;
+ /** @type {number} */ var height = 64;
+
+ formatsGroup.addChild(
+ new es3fTextureFilteringTests.Texture2DFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ format, width, height
+ )
+ );
+ }
+ }
+
+ // Sizes.
+ /** @type {tcuTestCase.DeqpTest} */
+ var sizesGroup;
+ for (var sizeNdx = 0; sizeNdx < sizes2D.length; sizeNdx++) {
+ sizesGroup = new tcuTestCase.DeqpTest(
+ '2d_sizes', '2D Texture Sizes');
+ this.addChild(sizesGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ format = gl.RGBA8;
+ isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ magFilter = isMipmap ? gl.LINEAR : minFilter;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ width = sizes2D[sizeNdx].width;
+ height = sizes2D[sizeNdx].height;
+ name = '' + width + 'x' + height + '_' + filterName;
+
+ sizesGroup.addChild(
+ new es3fTextureFilteringTests.Texture2DFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ format, width, height
+ )
+ );
+ }
+ }
+
+ // Wrap modes.
+ /** @type {tcuTestCase.DeqpTest} */
+ var combinationsGroup;
+ for (var minFilterNdx = 0;
+ minFilterNdx < minFilterModes.length;
+ minFilterNdx++) {
+ combinationsGroup = new tcuTestCase.DeqpTest(
+ '2d_combinations', '2D Filter and wrap mode combinations');
+ this.addChild(combinationsGroup);
+ for (var magFilterNdx = 0;
+ magFilterNdx < magFilterModes.length;
+ magFilterNdx++) {
+ for (var wrapSNdx = 0;
+ wrapSNdx < wrapModes.length;
+ wrapSNdx++) {
+ for (var wrapTNdx = 0;
+ wrapTNdx < wrapModes.length;
+ wrapTNdx++) {
+ minFilter = minFilterModes[minFilterNdx].mode;
+ magFilter = magFilterModes[magFilterNdx].mode;
+ format = gl.RGBA8;
+ wrapS = wrapModes[wrapSNdx].mode;
+ wrapT = wrapModes[wrapTNdx].mode;
+ width = 63;
+ height = 57;
+ name = minFilterModes[minFilterNdx].name + '_' +
+ magFilterModes[magFilterNdx].name + '_' +
+ wrapModes[wrapSNdx].name + '_' +
+ wrapModes[wrapTNdx].name;
+
+ combinationsGroup.addChild(
+ new
+ es3fTextureFilteringTests.Texture2DFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ format, width, height
+ )
+ );
+ }
+ }
+ }
+ }
+
+ // Cube map texture filtering.
+
+ // Formats.
+ for (var fmtNdx = 0;
+ fmtNdx < filterableFormatsByType.length;
+ fmtNdx++) {
+ formatsGroup = new tcuTestCase.DeqpTest(
+ 'cube_formats', 'Cube Texture Formats');
+ this.addChild(formatsGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ format = filterableFormatsByType[fmtNdx].format;
+ formatName = filterableFormatsByType[fmtNdx].name;
+ isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ magFilter = isMipmap ? gl.LINEAR : minFilter;
+ name = formatName + '_' + filterName;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ width = 64;
+ height = 64;
+
+ formatsGroup.addChild(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ false /* always sample exterior as well */,
+ format, width, height
+ )
+ );
+ }
+ }
+
+ // Sizes.
+ for (var sizeNdx = 0; sizeNdx < sizesCube.length; sizeNdx++) {
+ sizesGroup = new tcuTestCase.DeqpTest(
+ 'cube_sizes', 'Cube Texture Sizes');
+ this.addChild(sizesGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ var format = gl.RGBA8;
+ isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ magFilter = isMipmap ? gl.LINEAR : minFilter;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ width = sizesCube[sizeNdx].width;
+ height = sizesCube[sizeNdx].height;
+ name = '' + width + 'x' + height + '_' + filterName;
+
+ sizesGroup.addChild(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ false, format, width, height
+ )
+ );
+ }
+ }
+
+ // Filter/wrap mode combinations.
+ for (var minFilterNdx = 0;
+ minFilterNdx < minFilterModes.length;
+ minFilterNdx++) {
+ combinationsGroup = new tcuTestCase.DeqpTest(
+ 'cube_combinations', 'Cube Filter and wrap mode combinations'
+ );
+ this.addChild(combinationsGroup);
+ for (var magFilterNdx = 0;
+ magFilterNdx < magFilterModes.length;
+ magFilterNdx++) {
+ for (var wrapSNdx = 0;
+ wrapSNdx < wrapModes.length;
+ wrapSNdx++) {
+ for (var wrapTNdx = 0;
+ wrapTNdx < wrapModes.length;
+ wrapTNdx++) {
+ minFilter = minFilterModes[minFilterNdx].mode;
+ magFilter = magFilterModes[magFilterNdx].mode;
+ format = gl.RGBA8;
+ wrapS = wrapModes[wrapSNdx].mode;
+ wrapT = wrapModes[wrapTNdx].mode;
+ width = 63;
+ height = 63;
+ name = minFilterModes[minFilterNdx].name + '_' +
+ magFilterModes[magFilterNdx].name + '_' +
+ wrapModes[wrapSNdx].name + '_' +
+ wrapModes[wrapTNdx].name;
+
+ combinationsGroup.addChild(
+ new es3fTextureFilteringTests.
+ TextureCubeFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ false, format, width, height
+ )
+ );
+ }
+ }
+ }
+ }
+
+ // Cases with no visible cube edges.
+ /** @type {tcuTestCase.DeqpTest} */
+ var onlyFaceInteriorGroup = new tcuTestCase.DeqpTest(
+ 'cube_no_edges_visible', "Don't sample anywhere near a face's edges"
+ );
+ this.addChild(onlyFaceInteriorGroup);
+
+ for (var isLinearI = 0; isLinearI <= 1; isLinearI++) {
+ var isLinear = isLinearI != 0;
+ var filter = isLinear ? gl.LINEAR : gl.NEAREST;
+
+ onlyFaceInteriorGroup.addChild(
+ new es3fTextureFilteringTests.TextureCubeFilteringCase(
+ isLinear ? 'linear' : 'nearest', '',
+ filter, filter, gl.REPEAT, gl.REPEAT,
+ true, gl.RGBA8, 63, 63
+ )
+ );
+ }
+
+ // Formats.
+ for (var fmtNdx = 0;
+ fmtNdx < filterableFormatsByType.length;
+ fmtNdx++) {
+ formatsGroup = new tcuTestCase.DeqpTest(
+ '2d_array_formats', '2D Array Texture Formats');
+ this.addChild(formatsGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ format = filterableFormatsByType[fmtNdx].format;
+ var formatName = filterableFormatsByType[fmtNdx].name;
+ isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ magFilter = isMipmap ? gl.LINEAR : minFilter;
+ name = formatName + '_' + filterName;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ width = 128;
+ height = 128;
+ /** @type {number} */ var numLayers = 8;
+
+ formatsGroup.addChild(
+ new es3fTextureFilteringTests.Texture2DArrayFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ format, width, height, numLayers
+ )
+ );
+ }
+ }
+
+ // Sizes.
+ for (var sizeNdx = 0; sizeNdx < sizes2DArray.length; sizeNdx++) {
+ sizesGroup = new tcuTestCase.DeqpTest(
+ '2d_array_sizes', '2D Array Texture Sizes');
+ this.addChild(sizesGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ format = gl.RGBA8;
+ isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ magFilter = isMipmap ? gl.LINEAR : minFilter;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ width = sizes2DArray[sizeNdx].width;
+ height = sizes2DArray[sizeNdx].height;
+ numLayers = sizes2DArray[sizeNdx].numLayers;
+ name = '' + width + 'x' + height + 'x' +
+ numLayers + '_' + filterName;
+
+ sizesGroup.addChild(
+ new es3fTextureFilteringTests.Texture2DArrayFilteringCase(
+ name, '', minFilter, magFilter, wrapS, wrapT,
+ format, width, height, numLayers
+ )
+ );
+ }
+ }
+
+ // Wrap modes.
+ for (var minFilterNdx = 0;
+ minFilterNdx < minFilterModes.length;
+ minFilterNdx++) {
+ combinationsGroup = new tcuTestCase.DeqpTest(
+ '2d_array_combinations',
+ '2D Array Filter and wrap mode combinations');
+ this.addChild(combinationsGroup);
+ for (var magFilterNdx = 0;
+ magFilterNdx < magFilterModes.length;
+ magFilterNdx++) {
+ for (var wrapSNdx = 0;
+ wrapSNdx < wrapModes.length;
+ wrapSNdx++) {
+ for (var wrapTNdx = 0;
+ wrapTNdx < wrapModes.length;
+ wrapTNdx++) {
+ minFilter = minFilterModes[minFilterNdx].mode;
+ magFilter = magFilterModes[magFilterNdx].mode;
+ format = gl.RGBA8;
+ wrapS = wrapModes[wrapSNdx].mode;
+ wrapT = wrapModes[wrapTNdx].mode;
+ width = 123;
+ height = 107;
+ numLayers = 7;
+ name = minFilterModes[minFilterNdx].name + '_' +
+ magFilterModes[magFilterNdx].name + '_' +
+ wrapModes[wrapSNdx].name + '_' +
+ wrapModes[wrapTNdx].name;
+
+ combinationsGroup.addChild(
+ new es3fTextureFilteringTests.
+ Texture2DArrayFilteringCase(
+ name, '', minFilter, magFilter,
+ wrapS, wrapT, format,
+ width, height, numLayers
+ )
+ );
+ }
+ }
+ }
+ }
+
+ // 3D texture filtering.
+
+ // Formats.
+ /** @type {number} */ var depth = 64;
+ for (var fmtNdx = 0;
+ fmtNdx < filterableFormatsByType.length;
+ fmtNdx++) {
+ formatsGroup = new tcuTestCase.DeqpTest(
+ '3d_formats', '3D Texture Formats');
+ this.addChild(formatsGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ format = filterableFormatsByType[fmtNdx].format;
+ formatName = filterableFormatsByType[fmtNdx].name;
+ isMipmap = minFilter != gl.NEAREST &&
+ minFilter != gl.LINEAR;
+ magFilter = isMipmap ? gl.LINEAR : minFilter;
+ name = formatName + '_' + filterName;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ /** @type {number} */ var wrapR = gl.REPEAT;
+ width = 64;
+ height = 64;
+ depth = 64;
+
+ formatsGroup.addChild(
+ new es3fTextureFilteringTests.Texture3DFilteringCase(
+ name, '', minFilter, magFilter,
+ wrapS, wrapT, wrapR, format,
+ width, height, depth
+ )
+ );
+ }
+ }
+
+ // Sizes.
+ for (var sizeNdx = 0; sizeNdx < sizes3D.length; sizeNdx++) {
+ sizesGroup = new tcuTestCase.DeqpTest(
+ '3d_sizes', '3D Texture Sizes');
+ this.addChild(sizesGroup);
+ for (var filterNdx = 0;
+ filterNdx < minFilterModes.length;
+ filterNdx++) {
+ minFilter = minFilterModes[filterNdx].mode;
+ filterName = minFilterModes[filterNdx].name;
+ format = gl.RGBA8;
+ isMipmap =
+ minFilter != gl.NEAREST && minFilter != gl.LINEAR;
+ magFilter =
+ isMipmap ? gl.LINEAR : minFilter;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ wrapR = gl.REPEAT;
+ width = sizes3D[sizeNdx].width;
+ height = sizes3D[sizeNdx].height;
+ depth = sizes3D[sizeNdx].depth;
+ name = '' + width + 'x' + height + 'x' + depth +
+ '_' + filterName;
+
+ sizesGroup.addChild(
+ new es3fTextureFilteringTests.Texture3DFilteringCase(
+ name, '', minFilter, magFilter,
+ wrapS, wrapT, wrapR, format,
+ width, height, depth
+ )
+ );
+ }
+ }
+
+ // Wrap modes.
+ for (var minFilterNdx = 0;
+ minFilterNdx < minFilterModes.length;
+ minFilterNdx++) {
+ for (var magFilterNdx = 0;
+ magFilterNdx < magFilterModes.length;
+ magFilterNdx++) {
+ for (var wrapSNdx = 0;
+ wrapSNdx < wrapModes.length;
+ wrapSNdx++) {
+ combinationsGroup = new tcuTestCase.DeqpTest(
+ '3d_combinations',
+ '3D Filter and wrap mode combinations');
+ this.addChild(combinationsGroup);
+ for (var wrapTNdx = 0;
+ wrapTNdx < wrapModes.length;
+ wrapTNdx++) {
+ for (var wrapRNdx = 0;
+ wrapRNdx < wrapModes.length;
+ wrapRNdx++) {
+ minFilter = minFilterModes[minFilterNdx].mode;
+ magFilter = magFilterModes[magFilterNdx].mode;
+ format = gl.RGBA8;
+ wrapS = wrapModes[wrapSNdx].mode;
+ wrapT = wrapModes[wrapTNdx].mode;
+ wrapR = wrapModes[wrapRNdx].mode;
+ width = 63;
+ height = 57;
+ depth = 67;
+ name = minFilterModes[minFilterNdx].name + '_' +
+ magFilterModes[magFilterNdx].name + '_' +
+ wrapModes[wrapSNdx].name + '_' +
+ wrapModes[wrapTNdx].name + '_' +
+ wrapModes[wrapRNdx].name;
+
+ combinationsGroup.addChild(
+ new
+ es3fTextureFilteringTests.
+ Texture3DFilteringCase(
+ name, '', minFilter, magFilter,
+ wrapS, wrapT, wrapR, format,
+ width, height, depth
+ )
+ );
+ }
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ * @param {Array<number>=} range Test range
+ */
+ es3fTextureFilteringTests.run = function(context, range) {
+ gl = context;
+
+ const canvas = gl.canvas;
+ canvas.width = canvasWH;
+ canvas.height = canvasWH;
+
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+
+ state.setRoot(new es3fTextureFilteringTests.TextureFilteringTests());
+ if (range)
+ state.setRange(range);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFormatTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFormatTests.js
new file mode 100644
index 0000000000..7300225a8d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFormatTests.js
@@ -0,0 +1,1185 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fTextureFormatTests');
+goog.require('framework.common.tcuCompressedTexture');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluStrUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+
+var es3fTextureFormatTests = functional.gles3.es3fTextureFormatTests;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var deRandom = framework.delibs.debase.deRandom;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuSurface = framework.common.tcuSurface;
+var gluTexture = framework.opengl.gluTexture;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var gluStrUtil = framework.opengl.gluStrUtil;
+var deMath = framework.delibs.debase.deMath;
+var tcuCompressedTexture = framework.common.tcuCompressedTexture;
+
+/** @type {WebGL2RenderingContext} */ var gl;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+es3fTextureFormatTests.version = '300 es';
+
+es3fTextureFormatTests.testDescription = function() {
+ var test = tcuTestCase.runner.currentTest;
+ return test.description;
+};
+
+es3fTextureFormatTests.setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fTextureFormatTests.Texture2DFormatCase = function(descriptor) {
+ tcuTestCase.DeqpTest.call(this, descriptor.name, descriptor.description);
+ this.m_format = descriptor.format;
+ this.m_dataType = descriptor.dataType;
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureFormatTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+};
+
+es3fTextureFormatTests.setParentClass(es3fTextureFormatTests.Texture2DFormatCase, tcuTestCase.DeqpTest);
+
+es3fTextureFormatTests.Texture2DFormatCase.prototype.init = function() {
+ /*tcu::TextureFormat*/ var fmt = this.m_dataType ? gluTextureUtil.mapGLTransferFormat(this.m_format, this.m_dataType) : gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /*tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(fmt);
+ /* TODO : Port
+
+ std::ostringstream fmtName;
+
+ if (m_dataType)
+ fmtName << glu::getPixelFormatStr(m_format) << ", " << glu::getTypeStr(m_dataType);
+ else
+ fmtName << glu::getPixelFormatStr(m_format);
+
+ log << TestLog::Message << "2D texture, " << fmtName.str() << ", " << m_width << "x" << m_height
+ << ",\n fill with " << formatGradient(&spec.valueMin, &spec.valueMax) << " gradient"
+ << TestLog::EndMessage;
+ */
+
+ this.m_texture = this.m_dataType ?
+ gluTexture.texture2DFromFormat(gl, this.m_format, this.m_dataType, this.m_width, this.m_height) : // Implicit internal format.
+ gluTexture.texture2DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height); // Explicit internal format.
+
+ // Fill level 0.
+ this.m_texture.getRefTexture().allocLevel(0);
+ tcuTextureUtil.fillWithComponentGradients(this.m_texture.getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
+};
+
+es3fTextureFormatTests.Texture2DFormatCase.prototype.deinit = function() {
+ /* TODO: Implement */
+};
+
+es3fTextureFormatTests.Texture2DFormatCase.prototype.iterate = function() {
+ /* TODO: Implement */
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), this.m_width, this.m_height/*, deStringHash(getName())*/);
+
+ /* tcu::Surface */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* tcu::Surface */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* TODO: Implement
+ // tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ */
+ var threshold = [3, 3, 3, 3];
+ var renderParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D);
+
+ /* tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(this.m_texture.getRefTexture().getFormat());
+ /** @const */ var wrapS = gl.CLAMP_TO_EDGE;
+ /** @const */ var wrapT = gl.CLAMP_TO_EDGE;
+ /** @const */ var minFilter = gl.NEAREST;
+ /** @const */ var magFilter = gl.NEAREST;
+
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+
+ renderParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ renderParams.sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST);
+ renderParams.colorScale = spec.lookupScale;
+ renderParams.colorBias = spec.lookupBias;
+
+ var texCoord = glsTextureTestUtil.computeQuadTexCoord2D([0, 0], [1, 1]);
+
+ // log << TestLog::Message << "Texture parameters:"
+ // << "\n WRAP_S = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_S, wrapS)
+ // << "\n WRAP_T = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_T, wrapT)
+ // << "\n MIN_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MIN_FILTER, minFilter)
+ // << "\n MAG_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MAG_FILTER, magFilter)
+ // << TestLog::EndMessage;
+
+ // Setup base viewport.
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ // Upload texture data to GL.
+ this.m_texture.upload();
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, this.m_texture.getGLTexture());
+
+ // Setup nearest neighbor filtering and clamp-to-edge.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
+
+ // // Draw.
+ this.m_renderer.renderQuad(0, texCoord, renderParams);
+ renderedFrame.readViewport(gl, viewport);
+
+ // // Compute reference.
+ glsTextureTestUtil.sampleTexture2D(new glsTextureTestUtil.SurfaceAccess(referenceFrame, undefined /*m_renderCtx.getRenderTarget().getPixelFormat()*/),
+ this.m_texture.getRefTexture(), texCoord, renderParams);
+
+ // Compare and log.
+ var isOk = glsTextureTestUtil.compareImages(referenceFrame, renderedFrame, threshold);
+
+ assertMsgOptions(isOk, es3fTextureFormatTests.testDescription(), true, false);
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fTextureFormatTests.TextureCubeFormatCase = function(descriptor) {
+ tcuTestCase.DeqpTest.call(this, descriptor.name, descriptor.description);
+ this.m_format = descriptor.format;
+ this.m_dataType = descriptor.dataType;
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureFormatTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+ DE_ASSERT(this.m_width == this.m_height);
+};
+
+es3fTextureFormatTests.setParentClass(es3fTextureFormatTests.TextureCubeFormatCase, tcuTestCase.DeqpTest);
+
+es3fTextureFormatTests.TextureCubeFormatCase.prototype.init = function() {
+ /*tcu::TextureFormat*/ var fmt = this.m_dataType ? gluTextureUtil.mapGLTransferFormat(this.m_format, this.m_dataType) : gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /*tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(fmt);
+ /* TODO : Port
+
+ std::ostringstream fmtName;
+
+ if (m_dataType)
+ fmtName << glu::getPixelFormatStr(m_format) << ", " << glu::getTypeStr(m_dataType);
+ else
+ fmtName << glu::getPixelFormatStr(m_format);
+
+ log << TestLog::Message << "2D texture, " << fmtName.str() << ", " << m_width << "x" << m_height
+ << ",\n fill with " << formatGradient(&spec.valueMin, &spec.valueMax) << " gradient"
+ << TestLog::EndMessage;
+ */
+
+ this.m_texture = this.m_dataType ?
+ gluTexture.cubeFromFormat(gl, this.m_format, this.m_dataType, this.m_width) : // Implicit internal format.
+ gluTexture.cubeFromInternalFormat(gl, this.m_format, this.m_width); // Explicit internal format.
+
+ // Fill level 0.
+ for (var face in tcuTexture.CubeFace) {
+ var gMin = null;
+ var gMax = null;
+
+ switch (tcuTexture.CubeFace[face]) {
+ case 0: gMin = deMath.swizzle(spec.valueMin, [0, 1, 2, 3]); gMax = deMath.swizzle(spec.valueMax, [0, 1, 2, 3]); break;
+ case 1: gMin = deMath.swizzle(spec.valueMin, [2, 1, 0, 3]); gMax = deMath.swizzle(spec.valueMax, [2, 1, 0, 3]); break;
+ case 2: gMin = deMath.swizzle(spec.valueMin, [1, 2, 0, 3]); gMax = deMath.swizzle(spec.valueMax, [1, 2, 0, 3]); break;
+ case 3: gMin = deMath.swizzle(spec.valueMax, [0, 1, 2, 3]); gMax = deMath.swizzle(spec.valueMin, [0, 1, 2, 3]); break;
+ case 4: gMin = deMath.swizzle(spec.valueMax, [2, 1, 0, 3]); gMax = deMath.swizzle(spec.valueMin, [2, 1, 0, 3]); break;
+ case 5: gMin = deMath.swizzle(spec.valueMax, [1, 2, 0, 3]); gMax = deMath.swizzle(spec.valueMin, [1, 2, 0, 3]); break;
+ default:
+ DE_ASSERT(false);
+ }
+
+ this.m_texture.getRefTexture().allocLevel(tcuTexture.CubeFace[face], 0);
+ tcuTextureUtil.fillWithComponentGradients(this.m_texture.getRefTexture().getLevelFace(0, tcuTexture.CubeFace[face]), gMin, gMax);
+ }
+
+ this.m_texture.upload();
+ this.m_curFace = 0;
+ this.m_isOk = true;
+};
+
+es3fTextureFormatTests.TextureCubeFormatCase.prototype.testFace = function(face) {
+ /* TODO: Implement */
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), this.m_width, this.m_height/*, deStringHash(getName())*/);
+
+ /* tcu::Surface */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* tcu::Surface */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* TODO: Implement
+ // tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ */
+ var threshold = [3, 3, 3, 3];
+ var renderParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_CUBE);
+
+ /* tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(this.m_texture.getRefTexture().getFormat());
+ /** @const */ var wrapS = gl.CLAMP_TO_EDGE;
+ /** @const */ var wrapT = gl.CLAMP_TO_EDGE;
+ /** @const */ var minFilter = gl.NEAREST;
+ /** @const */ var magFilter = gl.NEAREST;
+
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+
+ renderParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ renderParams.sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST);
+ renderParams.colorScale = spec.lookupScale;
+ renderParams.colorBias = spec.lookupBias;
+
+ // Log render info on first face.
+ if (face === tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X) {
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+ }
+
+ var texCoord = glsTextureTestUtil.computeQuadTexCoordCube(face);
+
+ // log << TestLog::Message << "Texture parameters:"
+ // << "\n WRAP_S = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_S, wrapS)
+ // << "\n WRAP_T = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_T, wrapT)
+ // << "\n MIN_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MIN_FILTER, minFilter)
+ // << "\n MAG_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MAG_FILTER, magFilter)
+ // << TestLog::EndMessage;
+
+ // Setup base viewport.
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.m_texture.getGLTexture());
+
+ // Setup nearest neighbor filtering and clamp-to-edge.
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, wrapS);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, wrapT);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, magFilter);
+
+ // // Draw.
+ this.m_renderer.renderQuad(0, texCoord, renderParams);
+ renderedFrame.readViewport(gl, viewport);
+
+ // // Compute reference.
+ glsTextureTestUtil.sampleTextureCube(new glsTextureTestUtil.SurfaceAccess(referenceFrame, undefined /*m_renderCtx.getRenderTarget().getPixelFormat()*/),
+ this.m_texture.getRefTexture(), texCoord, renderParams);
+
+ // Compare and log.
+ var skipPixels = null;
+ if (renderParams.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_INT ||
+ renderParams.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT) {
+ // Skip top right pixel due to Mac Intel driver bug.
+ // https://github.com/KhronosGroup/WebGL/issues/1819
+ skipPixels = [
+ [this.m_width - 1, this.m_height - 1]
+ ];
+ }
+ var isOk = glsTextureTestUtil.compareImages(referenceFrame, renderedFrame, threshold, skipPixels);
+
+ assertMsgOptions(isOk, 'Face: ' + this.m_curFace + ' ' + es3fTextureFormatTests.testDescription(), true, false);
+ return isOk;
+};
+
+es3fTextureFormatTests.TextureCubeFormatCase.prototype.iterate = function() {
+ debug('Testing face ' + this.m_curFace);
+ // Execute test for all faces.
+ if (!this.testFace(this.m_curFace))
+ this.m_isOk = false;
+
+ this.m_curFace += 1;
+
+ if (this.m_curFace < Object.keys(tcuTexture.CubeFace).length)
+ return tcuTestCase.IterateResult.CONTINUE;
+ else
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fTextureFormatTests.Texture2DArrayFormatCase = function(descriptor) {
+ tcuTestCase.DeqpTest.call(this, descriptor.name, descriptor.description);
+ this.m_format = descriptor.format;
+ this.m_dataType = descriptor.dataType;
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ this.m_numLayers = descriptor.numLayers;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureFormatTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+};
+
+es3fTextureFormatTests.setParentClass(es3fTextureFormatTests.Texture2DArrayFormatCase, tcuTestCase.DeqpTest);
+
+es3fTextureFormatTests.Texture2DArrayFormatCase.prototype.init = function() {
+ /*tcu::TextureFormat*/ var fmt = this.m_dataType ? gluTextureUtil.mapGLTransferFormat(this.m_format, this.m_dataType) : gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /*tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(fmt);
+ /* TODO : Port
+
+ std::ostringstream fmtName;
+
+ if (m_dataType)
+ fmtName << glu::getPixelFormatStr(m_format) << ", " << glu::getTypeStr(m_dataType);
+ else
+ fmtName << glu::getPixelFormatStr(m_format);
+
+ log << TestLog::Message << "2D texture, " << fmtName.str() << ", " << m_width << "x" << m_height
+ << ",\n fill with " << formatGradient(&spec.valueMin, &spec.valueMax) << " gradient"
+ << TestLog::EndMessage;
+ */
+
+ this.m_texture = this.m_dataType ?
+ gluTexture.texture2DArrayFromFormat(gl, this.m_format, this.m_dataType, this.m_width, this.m_height, this.m_numLayers) : // Implicit internal format.
+ gluTexture.texture2DArrayFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, this.m_numLayers); // Explicit internal format.
+
+ this.m_texture.getRefTexture().allocLevel(0);
+ tcuTextureUtil.fillWithComponentGradients(this.m_texture.getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
+
+ this.m_curLayer = 0;
+ this.m_isOk = true;
+};
+
+es3fTextureFormatTests.Texture2DArrayFormatCase.prototype.testLayer = function(layerNdx) {
+ /* TODO: Implement */
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), this.m_width, this.m_height/*, deStringHash(getName())*/);
+
+ /* tcu::Surface */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* tcu::Surface */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* TODO: Implement
+ // tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ */
+ var threshold = [3, 3, 3, 3];
+ var renderParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY);
+
+ /* tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(this.m_texture.getRefTexture().getFormat());
+ /** @const */ var wrapS = gl.CLAMP_TO_EDGE;
+ /** @const */ var wrapT = gl.CLAMP_TO_EDGE;
+ /** @const */ var minFilter = gl.NEAREST;
+ /** @const */ var magFilter = gl.NEAREST;
+
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+
+ renderParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ renderParams.sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST);
+ renderParams.colorScale = spec.lookupScale;
+ renderParams.colorBias = spec.lookupBias;
+
+ var texCoord = glsTextureTestUtil.computeQuadTexCoord2DArray(layerNdx, [0, 0], [1, 1]);
+
+ // log << TestLog::Message << "Texture parameters:"
+ // << "\n WRAP_S = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_S, wrapS)
+ // << "\n WRAP_T = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_T, wrapT)
+ // << "\n MIN_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MIN_FILTER, minFilter)
+ // << "\n MAG_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MAG_FILTER, magFilter)
+ // << TestLog::EndMessage;
+
+ // Setup base viewport.
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ this.m_texture.upload();
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.m_texture.getGLTexture());
+
+ // Setup nearest neighbor filtering and clamp-to-edge.
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, wrapS);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, wrapT);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, magFilter);
+
+ // // Draw.
+ this.m_renderer.renderQuad(0, texCoord, renderParams);
+ renderedFrame.readViewport(gl, viewport);
+
+ // // Compute reference.
+ glsTextureTestUtil.sampleTexture2DArray(new glsTextureTestUtil.SurfaceAccess(referenceFrame, undefined /*m_renderCtx.getRenderTarget().getPixelFormat()*/),
+ this.m_texture.getRefTexture().getView(), texCoord, renderParams);
+
+ // Compare and log.
+ var isOk = glsTextureTestUtil.compareImages(referenceFrame, renderedFrame, threshold);
+
+ assertMsgOptions(isOk, 'Layer: ' + this.m_curLayer + ' ' + es3fTextureFormatTests.testDescription(), true, false);
+ return isOk;
+};
+
+es3fTextureFormatTests.Texture2DArrayFormatCase.prototype.iterate = function() {
+ debug('Testing layer ' + this.m_curLayer);
+ // Execute test for all layers.
+ if (!this.testLayer(this.m_curLayer))
+ this.m_isOk = false;
+
+ this.m_curLayer += 1;
+
+ if (this.m_curLayer == this.m_numLayers)
+ return tcuTestCase.IterateResult.STOP;
+ else
+ return tcuTestCase.IterateResult.CONTINUE;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fTextureFormatTests.Texture3DFormatCase = function(descriptor) {
+ tcuTestCase.DeqpTest.call(this, descriptor.name, descriptor.description);
+ this.m_format = descriptor.format;
+ this.m_dataType = descriptor.dataType;
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ this.m_depth = descriptor.depth;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureFormatTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+};
+
+es3fTextureFormatTests.setParentClass(es3fTextureFormatTests.Texture3DFormatCase, tcuTestCase.DeqpTest);
+
+es3fTextureFormatTests.Texture3DFormatCase.prototype.init = function() {
+ /*tcu::TextureFormat*/ var fmt = this.m_dataType ? gluTextureUtil.mapGLTransferFormat(this.m_format, this.m_dataType) : gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /*tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(fmt);
+ /* TODO : Port
+
+ std::ostringstream fmtName;
+
+ if (m_dataType)
+ fmtName << glu::getPixelFormatStr(m_format) << ", " << glu::getTypeStr(m_dataType);
+ else
+ fmtName << glu::getPixelFormatStr(m_format);
+
+ log << TestLog::Message << "2D texture, " << fmtName.str() << ", " << m_width << "x" << m_height
+ << ",\n fill with " << formatGradient(&spec.valueMin, &spec.valueMax) << " gradient"
+ << TestLog::EndMessage;
+ */
+
+ this.m_texture = this.m_dataType ?
+ gluTexture.texture3DFromFormat(gl, this.m_format, this.m_dataType, this.m_width, this.m_height, this.m_depth) : // Implicit internal format.
+ gluTexture.texture3DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, this.m_depth); // Explicit internal format.
+
+ this.m_texture.getRefTexture().allocLevel(0);
+ tcuTextureUtil.fillWithComponentGradients(this.m_texture.getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
+
+ this.m_curSlice = 0;
+ this.m_isOk = true;
+};
+
+es3fTextureFormatTests.Texture3DFormatCase.prototype.testSlice = function(sliceNdx) {
+ /* TODO: Implement */
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), this.m_width, this.m_height/*, deStringHash(getName())*/);
+
+ /* tcu::Surface */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* tcu::Surface */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* TODO: Implement
+ // tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ */
+ var threshold = [3, 3, 3, 3];
+ var renderParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_3D);
+
+ /* tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(this.m_texture.getRefTexture().getFormat());
+ var r = (sliceNdx + 0.5) / this.m_depth;
+ /** @const */ var wrapS = gl.CLAMP_TO_EDGE;
+ /** @const */ var wrapT = gl.CLAMP_TO_EDGE;
+ /** @const */ var minFilter = gl.NEAREST;
+ /** @const */ var magFilter = gl.NEAREST;
+
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+
+ renderParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ renderParams.sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST);
+ renderParams.colorScale = spec.lookupScale;
+ renderParams.colorBias = spec.lookupBias;
+
+ var texCoord = glsTextureTestUtil.computeQuadTexCoord3D([0, 0, r], [1, 1, r], [0, 1, 2]);
+
+ // log << TestLog::Message << "Texture parameters:"
+ // << "\n WRAP_S = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_S, wrapS)
+ // << "\n WRAP_T = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_T, wrapT)
+ // << "\n MIN_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MIN_FILTER, minFilter)
+ // << "\n MAG_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MAG_FILTER, magFilter)
+ // << TestLog::EndMessage;
+
+ // Setup base viewport.
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ this.m_texture.upload();
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_3D, this.m_texture.getGLTexture());
+
+ // Setup nearest neighbor filtering and clamp-to-edge.
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, wrapS);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, wrapT);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, magFilter);
+
+ // // Draw.
+ this.m_renderer.renderQuad(0, texCoord, renderParams);
+ renderedFrame.readViewport(gl, viewport);
+
+ // // Compute reference.
+ glsTextureTestUtil.sampleTexture3D(new glsTextureTestUtil.SurfaceAccess(referenceFrame, undefined /*m_renderCtx.getRenderTarget().getPixelFormat()*/),
+ this.m_texture.getRefTexture(), texCoord, renderParams);
+
+ // Compare and log.
+ var isOk = glsTextureTestUtil.compareImages(referenceFrame, renderedFrame, threshold);
+
+ assertMsgOptions(isOk, 'Slice: ' + this.m_curSlice + ' ' + es3fTextureFormatTests.testDescription(), true, false);
+ return isOk;
+};
+
+es3fTextureFormatTests.Texture3DFormatCase.prototype.iterate = function() {
+ debug('Testing slice ' + this.m_curSlice);
+ // Execute test for all layers.
+ if (!this.testSlice(this.m_curSlice))
+ this.m_isOk = false;
+
+ this.m_curSlice += 1;
+
+ if (this.m_curSlice >= this.m_depth)
+ return tcuTestCase.IterateResult.STOP;
+ else
+ return tcuTestCase.IterateResult.CONTINUE;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fTextureFormatTests.Compressed2DFormatCase = function(descriptor) {
+ tcuTestCase.DeqpTest.call(this, descriptor.name, descriptor.description);
+ this.m_format = descriptor.format;
+ this.m_dataType = descriptor.dataType;
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureFormatTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+};
+
+es3fTextureFormatTests.setParentClass(es3fTextureFormatTests.Compressed2DFormatCase, tcuTestCase.DeqpTest);
+
+es3fTextureFormatTests.Compressed2DFormatCase.prototype.init = function() {
+ var compressed = new tcuCompressedTexture.CompressedTexture(this.m_format, this.m_width, this.m_height);
+ var rand = new deRandom.Random(0);
+ for (var i = 0; i < compressed.m_data.length; i++) {
+ compressed.m_data[i] = rand.getInt(0, 255);
+ }
+ this.m_texture = gluTexture.compressed2DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, compressed);
+};
+
+es3fTextureFormatTests.Compressed2DFormatCase.prototype.deinit = function() {
+ /* TODO: Implement */
+};
+
+es3fTextureFormatTests.Compressed2DFormatCase.prototype.iterate = function() {
+ /* TODO: Implement */
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), this.m_width, this.m_height/*, deStringHash(getName())*/);
+
+ /* tcu::Surface */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* tcu::Surface */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* TODO: Implement
+ // tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ */
+ var threshold = [3, 3, 3, 3];
+ var renderParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D);
+
+ /* tcu::TextureFormatInfo*/ var spec = tcuTextureUtil.getTextureFormatInfo(this.m_texture.getRefTexture().getFormat());
+ /** @const */ var wrapS = gl.CLAMP_TO_EDGE;
+ /** @const */ var wrapT = gl.CLAMP_TO_EDGE;
+ /** @const */ var minFilter = gl.NEAREST;
+ /** @const */ var magFilter = gl.NEAREST;
+
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+
+ renderParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ renderParams.sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST);
+ renderParams.colorScale = spec.lookupScale;
+ renderParams.colorBias = spec.lookupBias;
+
+ var texCoord = glsTextureTestUtil.computeQuadTexCoord2D([0, 0], [1, 1]);
+
+ // log << TestLog::Message << "Texture parameters:"
+ // << "\n WRAP_S = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_S, wrapS)
+ // << "\n WRAP_T = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_T, wrapT)
+ // << "\n MIN_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MIN_FILTER, minFilter)
+ // << "\n MAG_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MAG_FILTER, magFilter)
+ // << TestLog::EndMessage;
+
+ // Setup base viewport.
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, this.m_texture.getGLTexture());
+
+ // Setup nearest neighbor filtering and clamp-to-edge.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
+
+ // // Draw.
+ this.m_renderer.renderQuad(0, texCoord, renderParams);
+ renderedFrame.readViewport(gl, viewport);
+
+ // // Compute reference.
+ glsTextureTestUtil.sampleTexture2D(new glsTextureTestUtil.SurfaceAccess(referenceFrame, undefined /*m_renderCtx.getRenderTarget().getPixelFormat()*/),
+ this.m_texture.getRefTexture(), texCoord, renderParams);
+
+ // Compare and log.
+ var isOk = glsTextureTestUtil.compareImages(referenceFrame, renderedFrame, threshold);
+
+ assertMsgOptions(isOk, es3fTextureFormatTests.testDescription(), true, false);
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fTextureFormatTests.CompressedCubeFormatCase = function(descriptor) {
+ tcuTestCase.DeqpTest.call(this, descriptor.name, descriptor.description);
+ this.m_format = descriptor.format;
+ this.m_dataType = descriptor.dataType;
+ this.m_width = descriptor.width;
+ this.m_height = descriptor.height;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureFormatTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+ this.m_curFace = 0;
+ this.m_isOk = true;
+ DE_ASSERT(this.m_width == this.m_height);
+};
+
+es3fTextureFormatTests.setParentClass(es3fTextureFormatTests.CompressedCubeFormatCase, tcuTestCase.DeqpTest);
+
+es3fTextureFormatTests.CompressedCubeFormatCase.prototype.init = function() {
+ var compressed = new tcuCompressedTexture.CompressedTexture(this.m_format, this.m_width, this.m_height);
+ var rand = new deRandom.Random(0);
+ for (var i = 0; i < compressed.m_data.length; i++) {
+ compressed.m_data[i] = rand.getInt(0, 255);
+ }
+ this.m_texture = gluTexture.compressedCubeFromInternalFormat(gl, this.m_format, this.m_width, compressed);
+};
+
+es3fTextureFormatTests.CompressedCubeFormatCase.prototype.testFace = function(face) {
+ /* TODO: Implement */
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), this.m_width, this.m_height/*, deStringHash(getName())*/);
+
+ /* tcu::Surface */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* tcu::Surface */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /* TODO: Implement
+ // tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ */
+ // Threshold high enough to cover numerical errors in software decoders on Windows and Mac. Threshold is 17 in native dEQP.
+ var threshold = [6, 6, 6, 6];
+ var renderParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_CUBE);
+
+ /** @const */ var wrapS = gl.CLAMP_TO_EDGE;
+ /** @const */ var wrapT = gl.CLAMP_TO_EDGE;
+ /** @const */ var minFilter = gl.NEAREST;
+ /** @const */ var magFilter = gl.NEAREST;
+
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+
+ renderParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ renderParams.sampler = new tcuTexture.Sampler(tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE, tcuTexture.WrapMode.CLAMP_TO_EDGE,
+ tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST);
+
+ // Log render info on first face.
+ if (face === tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X) {
+ renderParams.flags.log_programs = true;
+ renderParams.flags.log_uniforms = true;
+ }
+
+ var texCoord = glsTextureTestUtil.computeQuadTexCoordCube(face);
+
+ // log << TestLog::Message << "Texture parameters:"
+ // << "\n WRAP_S = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_S, wrapS)
+ // << "\n WRAP_T = " << glu::getTextureParameterValueStr(gl.TEXTURE_WRAP_T, wrapT)
+ // << "\n MIN_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MIN_FILTER, minFilter)
+ // << "\n MAG_FILTER = " << glu::getTextureParameterValueStr(gl.TEXTURE_MAG_FILTER, magFilter)
+ // << TestLog::EndMessage;
+
+ // Setup base viewport.
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.m_texture.getGLTexture());
+
+ // Setup nearest neighbor filtering and clamp-to-edge.
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, wrapS);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, wrapT);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, magFilter);
+
+ // // Draw.
+ this.m_renderer.renderQuad(0, texCoord, renderParams);
+ renderedFrame.readViewport(gl, viewport);
+
+ // // Compute reference.
+ glsTextureTestUtil.sampleTextureCube(new glsTextureTestUtil.SurfaceAccess(referenceFrame, undefined /*m_renderCtx.getRenderTarget().getPixelFormat()*/),
+ this.m_texture.getRefTexture(), texCoord, renderParams);
+
+ // Compare and log.
+ var isOk = glsTextureTestUtil.compareImages(referenceFrame, renderedFrame, threshold);
+
+ assertMsgOptions(isOk, 'Face: ' + this.m_curFace + ' ' + es3fTextureFormatTests.testDescription(), true, false);
+ return isOk;
+};
+
+es3fTextureFormatTests.CompressedCubeFormatCase.prototype.iterate = function() {
+ debug('Testing face ' + this.m_curFace);
+ // Execute test for all faces.
+ if (!this.testFace(this.m_curFace))
+ this.m_isOk = false;
+
+ this.m_curFace += 1;
+
+ if (this.m_curFace < Object.keys(tcuTexture.CubeFace).length)
+ return tcuTestCase.IterateResult.CONTINUE;
+ else
+ return tcuTestCase.IterateResult.STOP;
+};
+
+es3fTextureFormatTests.genTestCases = function() {
+ var state = tcuTestCase.runner;
+ state.setRoot(tcuTestCase.newTest('texture_format', 'Top level'));
+
+ var texFormats = [
+ ['alpha', gl.ALPHA, gl.UNSIGNED_BYTE],
+ ['luminance', gl.LUMINANCE, gl.UNSIGNED_BYTE],
+ ['luminance_alpha', gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE],
+ ['rgb_unsigned_short_5_6_5', gl.RGB, gl.UNSIGNED_SHORT_5_6_5],
+ ['rgb_unsigned_byte', gl.RGB, gl.UNSIGNED_BYTE],
+ ['rgba_unsigned_short_4_4_4_4', gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4],
+ ['rgba_unsigned_short_5_5_5_1', gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1],
+ ['rgba_unsigned_byte', gl.RGBA, gl.UNSIGNED_BYTE]
+ ];
+
+ var unsized2DGroup = tcuTestCase.newTest('unsized', 'Unsized formats (2D, Cubemap)');
+ state.testCases.addChild(unsized2DGroup);
+ var unsized2DArrayGroup = tcuTestCase.newTest('unsized', 'Unsized formats (2D Array)');
+ state.testCases.addChild(unsized2DArrayGroup);
+ var unsized3DGroup = tcuTestCase.newTest('unsized', 'Unsized formats (3D)');
+ state.testCases.addChild(unsized3DGroup);
+
+ texFormats.forEach(function(elem) {
+ var format = elem[1];
+ var dataType = elem[2];
+ var nameBase = elem[0];
+ var descriptionBase = gluStrUtil.getPixelFormatName(format) + ', ' + gluStrUtil.getTypeName(dataType);
+ unsized2DGroup.addChild(new es3fTextureFormatTests.Texture2DFormatCase({
+ name: nameBase + '_2d_pot',
+ description: descriptionBase + ' gl.TEXTURE_2D',
+ format: format,
+ dataType: dataType,
+ width: 128,
+ height: 128
+ }));
+ unsized2DGroup.addChild(new es3fTextureFormatTests.Texture2DFormatCase({
+ name: nameBase + '_2d_npot',
+ description: descriptionBase + ' gl.TEXTURE_2D',
+ format: format,
+ dataType: dataType,
+ width: 63,
+ height: 112
+ }));
+ unsized2DGroup.addChild(new es3fTextureFormatTests.TextureCubeFormatCase({
+ name: nameBase + '_cube_pot',
+ description: descriptionBase + ' gl.TEXTURE_CUBE_MAP',
+ format: format,
+ dataType: dataType,
+ width: 64,
+ height: 64
+ }));
+ unsized2DGroup.addChild(new es3fTextureFormatTests.TextureCubeFormatCase({
+ name: nameBase + '_cube_npot',
+ description: descriptionBase + ' gl.TEXTURE_CUBE_MAP',
+ format: format,
+ dataType: dataType,
+ width: 57,
+ height: 57
+ }));
+ unsized2DArrayGroup.addChild(new es3fTextureFormatTests.Texture2DArrayFormatCase({
+ name: nameBase + '_2d_array_pot',
+ description: descriptionBase + ' gl.TEXTURE_2D_ARRAY',
+ format: format,
+ dataType: dataType,
+ width: 64,
+ height: 64,
+ numLayers: 8
+ }));
+ unsized2DArrayGroup.addChild(new es3fTextureFormatTests.Texture2DArrayFormatCase({
+ name: nameBase + '_2d_array_npot',
+ description: descriptionBase + ' gl.TEXTURE_2D_ARRAY',
+ format: format,
+ dataType: dataType,
+ width: 63,
+ height: 57,
+ numLayers: 7
+ }));
+ unsized3DGroup.addChild(new es3fTextureFormatTests.Texture3DFormatCase({
+ name: nameBase + '_3d_pot',
+ description: descriptionBase + ' gl.TEXTURE_3D',
+ format: format,
+ dataType: dataType,
+ width: 8,
+ height: 32,
+ depth: 16
+ }));
+ unsized3DGroup.addChild(new es3fTextureFormatTests.Texture3DFormatCase({
+ name: nameBase + '_3d_npot',
+ description: descriptionBase + ' gl.TEXTURE_3D',
+ format: format,
+ dataType: dataType,
+ width: 11,
+ height: 31,
+ depth: 7
+ }));
+ });
+
+ var sizedColorFormats = [
+ ['rgba32f', gl.RGBA32F],
+ ['rgba32i', gl.RGBA32I],
+ ['rgba32ui', gl.RGBA32UI],
+ ['rgba16f', gl.RGBA16F],
+ ['rgba16i', gl.RGBA16I],
+ ['rgba16ui', gl.RGBA16UI],
+ ['rgba8', gl.RGBA8],
+ ['rgba8i', gl.RGBA8I],
+ ['rgba8ui', gl.RGBA8UI],
+ ['srgb8_alpha8', gl.SRGB8_ALPHA8],
+ ['rgb10_a2', gl.RGB10_A2],
+ ['rgb10_a2ui', gl.RGB10_A2UI],
+ ['rgba4', gl.RGBA4],
+ ['rgb5_a1', gl.RGB5_A1],
+ ['rgba8_snorm', gl.RGBA8_SNORM],
+ ['rgb8', gl.RGB8],
+ ['rgb565', gl.RGB565],
+ ['r11f_g11f_b10f', gl.R11F_G11F_B10F],
+ ['rgb32f', gl.RGB32F],
+ ['rgb32i', gl.RGB32I],
+ ['rgb32ui', gl.RGB32UI],
+ ['rgb16f', gl.RGB16F],
+ ['rgb16i', gl.RGB16I],
+ ['rgb16ui', gl.RGB16UI],
+ ['rgb8_snorm', gl.RGB8_SNORM],
+ ['rgb8i', gl.RGB8I],
+ ['rgb8ui', gl.RGB8UI],
+ ['srgb8', gl.SRGB8],
+ ['rgb9_e5', gl.RGB9_E5],
+ ['rg32f', gl.RG32F],
+ ['rg32i', gl.RG32I],
+ ['rg32ui', gl.RG32UI],
+ ['rg16f', gl.RG16F],
+ ['rg16i', gl.RG16I],
+ ['rg16ui', gl.RG16UI],
+ ['rg8', gl.RG8],
+ ['rg8i', gl.RG8I],
+ ['rg8ui', gl.RG8UI],
+ ['rg8_snorm', gl.RG8_SNORM],
+ ['r32f', gl.R32F],
+ ['r32i', gl.R32I],
+ ['r32ui', gl.R32UI],
+ ['r16f', gl.R16F],
+ ['r16i', gl.R16I],
+ ['r16ui', gl.R16UI],
+ ['r8', gl.R8],
+ ['r8i', gl.R8I],
+ ['r8ui', gl.R8UI],
+ ['r8_snorm', gl.R8_SNORM]
+ ];
+
+ var splitSizedColorTests = 4;
+ var sizedColor2DPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColor2DPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (2D POT)'));
+ state.testCases.addChild(sizedColor2DPOTGroup[ii]);
+ }
+ var sizedColor2DNPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColor2DNPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (2D NPOT)'));
+ state.testCases.addChild(sizedColor2DNPOTGroup[ii]);
+ }
+ var sizedColorCubePOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColorCubePOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (Cubemap POT)'));
+ state.testCases.addChild(sizedColorCubePOTGroup[ii]);
+ }
+ var sizedColorCubeNPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColorCubeNPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (Cubemap NPOT)'));
+ state.testCases.addChild(sizedColorCubeNPOTGroup[ii]);
+ }
+ var sizedColor2DArrayPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColor2DArrayPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (2D Array POT)'));
+ state.testCases.addChild(sizedColor2DArrayPOTGroup[ii]);
+ }
+ var sizedColor2DArrayNPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColor2DArrayNPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (2D Array NPOT)'));
+ state.testCases.addChild(sizedColor2DArrayNPOTGroup[ii]);
+ }
+ var sizedColor3DPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColor3DPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (3D POT)'));
+ state.testCases.addChild(sizedColor3DPOTGroup[ii]);
+ }
+ var sizedColor3DNPOTGroup = [];
+ for (var ii = 0; ii < splitSizedColorTests; ++ii) {
+ sizedColor3DNPOTGroup.push(tcuTestCase.newTest('sized', 'Sized formats (3D NPOT)'));
+ state.testCases.addChild(sizedColor3DNPOTGroup[ii]);
+ }
+
+ for (var ii = 0; ii < sizedColorFormats.length; ++ii) {
+ var internalFormat = sizedColorFormats[ii][1];
+ var nameBase = sizedColorFormats[ii][0];
+ var descriptionBase = gluStrUtil.getPixelFormatName(internalFormat);
+ sizedColor2DPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.Texture2DFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_2D',
+ format: internalFormat,
+ width: 128,
+ height: 128
+ }));
+ sizedColor2DNPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.Texture2DFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_2D',
+ format: internalFormat,
+ width: 63,
+ height: 112
+ }));
+ sizedColorCubePOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.TextureCubeFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_CUBE_MAP',
+ format: internalFormat,
+ width: 64,
+ height: 64
+ }));
+ sizedColorCubeNPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.TextureCubeFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_CUBE_MAP',
+ format: internalFormat,
+ width: 57,
+ height: 57
+ }));
+ sizedColor2DArrayPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.Texture2DArrayFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_2D_ARRAY',
+ format: internalFormat,
+ width: 64,
+ height: 64,
+ numLayers: 8
+
+ }));
+ sizedColor2DArrayNPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.Texture2DArrayFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_2D_ARRAY',
+ format: internalFormat,
+ width: 63,
+ height: 57,
+ numLayers: 7
+ }));
+ sizedColor3DPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.Texture3DFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_3D',
+ format: internalFormat,
+ width: 8,
+ height: 32,
+ depth: 16
+ }));
+ sizedColor3DNPOTGroup[ii % splitSizedColorTests].addChild(new es3fTextureFormatTests.Texture3DFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_3D',
+ format: internalFormat,
+ width: 11,
+ height: 31,
+ depth: 7
+ }));
+ }
+
+ var sizedDepthStencilFormats = [
+ // Depth and stencil formats
+ ['depth_component32f', gl.DEPTH_COMPONENT32F],
+ ['depth_component24', gl.DEPTH_COMPONENT24],
+ ['depth_component16', gl.DEPTH_COMPONENT16],
+ // The following format is restricted in WebGL2.
+ // ['depth32f_stencil8', gl.DEPTH32F_STENCIL8],
+ ['depth24_stencil8', gl.DEPTH24_STENCIL8]
+ ];
+ var sizedDepthStencilGroup = tcuTestCase.newTest('sized', 'Sized formats (Depth Stencil)');
+ state.testCases.addChild(sizedDepthStencilGroup);
+ sizedDepthStencilFormats.forEach(function(elem) {
+ var internalFormat = elem[1];
+ var nameBase = elem[0];
+ var descriptionBase = gluStrUtil.getPixelFormatName(internalFormat);
+ sizedDepthStencilGroup.addChild(new es3fTextureFormatTests.Texture2DFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_2D',
+ format: internalFormat,
+ width: 128,
+ height: 128
+ }));
+ sizedDepthStencilGroup.addChild(new es3fTextureFormatTests.Texture2DFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_2D',
+ format: internalFormat,
+ width: 63,
+ height: 112
+ }));
+ sizedDepthStencilGroup.addChild(new es3fTextureFormatTests.TextureCubeFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_CUBE_MAP',
+ format: internalFormat,
+ width: 64,
+ height: 64
+ }));
+ sizedDepthStencilGroup.addChild(new es3fTextureFormatTests.TextureCubeFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_CUBE_MAP',
+ format: internalFormat,
+ width: 57,
+ height: 57
+ }));
+ sizedDepthStencilGroup.addChild(new es3fTextureFormatTests.Texture2DArrayFormatCase({
+ name: nameBase + '_pot',
+ description: descriptionBase + ' gl.TEXTURE_2D_ARRAY',
+ format: internalFormat,
+ width: 64,
+ height: 64,
+ numLayers: 8
+ }));
+ sizedDepthStencilGroup.addChild(new es3fTextureFormatTests.Texture2DArrayFormatCase({
+ name: nameBase + '_npot',
+ description: descriptionBase + ' gl.TEXTURE_2D_ARRAY',
+ format: internalFormat,
+ width: 63,
+ height: 57,
+ numLayers: 7
+ }));
+ });
+
+ var compressed2DGroup = tcuTestCase.newTest('compressed', 'Compressed formats (2D)');
+ state.testCases.addChild(compressed2DGroup);
+ var compressedCubeGroup = tcuTestCase.newTest('compressed', 'Compressed formats (Cubemap)');
+ state.testCases.addChild(compressedCubeGroup);
+ var etc2Formats = [
+ ['gl.COMPRESSED_R11_EAC', 'eac_r11', tcuCompressedTexture.Format.EAC_R11],
+ ['gl.COMPRESSED_SIGNED_R11_EAC', 'eac_signed_r11', tcuCompressedTexture.Format.EAC_SIGNED_R11],
+ ['gl.COMPRESSED_RG11_EAC', 'eac_rg11', tcuCompressedTexture.Format.EAC_RG11],
+ ['gl.COMPRESSED_SIGNED_RG11_EAC', 'eac_signed_rg11', tcuCompressedTexture.Format.EAC_SIGNED_RG11],
+ ['gl.COMPRESSED_RGB8_ETC2', 'etc2_rgb8', tcuCompressedTexture.Format.ETC2_RGB8],
+ ['gl.COMPRESSED_SRGB8_ETC2', 'etc2_srgb8', tcuCompressedTexture.Format.ETC2_SRGB8],
+ ['gl.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2', 'etc2_rgb8_punchthrough_alpha1', tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1],
+ ['gl.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2', 'etc2_srgb8_punchthrough_alpha1', tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1],
+ ['gl.COMPRESSED_RGBA8_ETC2_EAC', 'etc2_eac_rgba8', tcuCompressedTexture.Format.ETC2_EAC_RGBA8],
+ ['gl.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC', 'etc2_eac_srgb8_alpha8', tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8]
+ ];
+ if (!gluTextureUtil.enableCompressedTextureETC()) {
+ debug('Skipping ETC2/EAC texture format tests: no support for WEBGL_compressed_texture_etc');
+ etc2Formats = [];
+ }
+ etc2Formats.forEach(function(elem) {
+ var nameBase = elem[1];
+ var descriptionBase = elem[0];
+ var format = elem[2];
+ compressed2DGroup.addChild(new es3fTextureFormatTests.Compressed2DFormatCase({
+ name: nameBase + '_2d_pot',
+ description: descriptionBase + ', gl.TEXTURE_2D',
+ format: format,
+ width: 128,
+ height: 64
+ }));
+ compressedCubeGroup.addChild(new es3fTextureFormatTests.CompressedCubeFormatCase({
+ name: nameBase + '_cube_pot',
+ description: descriptionBase + ', gl.TEXTURE_CUBE_MAP',
+ format: format,
+ width: 64,
+ height: 64
+ }));
+ compressed2DGroup.addChild(new es3fTextureFormatTests.Compressed2DFormatCase({
+ name: nameBase + '_2d_pot',
+ description: descriptionBase + ', gl.TEXTURE_2D',
+ format: format,
+ width: 128,
+ height: 64
+ }));
+ compressedCubeGroup.addChild(new es3fTextureFormatTests.CompressedCubeFormatCase({
+ name: nameBase + '_cube_npot',
+ description: descriptionBase + ', gl.TEXTURE_CUBE_MAP',
+ format: format,
+ width: 51,
+ height: 51
+ }));
+ });
+};
+
+/**
+ * Create and execute the test cases
+ */
+es3fTextureFormatTests.run = function(context, range) {
+ gl = context;
+ var state = tcuTestCase.runner;
+ try {
+ es3fTextureFormatTests.genTestCases();
+ if (range)
+ state.setRange(range);
+ state.runCallback(tcuTestCase.runTestCases);
+ } catch (err) {
+ bufferedLogToConsole(err);
+ state.terminate();
+ }
+
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureShadowTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureShadowTests.js
new file mode 100644
index 0000000000..c878228b23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureShadowTests.js
@@ -0,0 +1,898 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('functional.gles3.es3fTextureShadowTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexCompareVerifier');
+goog.require('framework.common.tcuTexLookupVerifier');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+
+var es3fTextureShadowTests = functional.gles3.es3fTextureShadowTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluTexture = framework.opengl.gluTexture;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuLogImage = framework.common.tcuLogImage;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuRGBA = framework.common.tcuRGBA;
+var deMath = framework.delibs.debase.deMath;
+var tcuPixelFormat = framework.common.tcuPixelFormat;
+var tcuSurface = framework.common.tcuSurface;
+var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier;
+var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var deString = framework.delibs.debase.deString;
+var deUtil = framework.delibs.debase.deUtil;
+
+ es3fTextureShadowTests.version = '300 es';
+
+ /** @const */ var VIEWPORT_WIDTH = 64;
+ /** @const */ var VIEWPORT_HEIGHT = 64;
+ /** @const */ var MIN_VIEWPORT_WIDTH = 64;
+ /** @const */ var MIN_VIEWPORT_HEIGHT = 64;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {boolean}
+ */
+ es3fTextureShadowTests.isFloatingPointDepthFormat = function(format) {
+ // Only two depth and depth-stencil formats are floating point
+ return (format.order == tcuTexture.ChannelOrder.D && format.type == tcuTexture.ChannelType.FLOAT) || (format.order == tcuTexture.ChannelOrder.DS && format.type == tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV);
+ };
+
+ /**
+ * @param {tcuTexture.PixelBufferAccess} access
+ */
+ es3fTextureShadowTests.clampFloatingPointTexture = function(access) {
+ DE_ASSERT(es3fTextureShadowTests.isFloatingPointDepthFormat(access.getFormat()));
+ for (var z = 0; z < access.getDepth(); ++z)
+ for (var y = 0; y < access.getHeight(); ++y)
+ for (var x = 0; x < access.getWidth(); ++x)
+ access.setPixDepth(deMath.clamp(access.getPixDepth(x, y, z), 0.0, 1.0), x, y, z);
+ };
+
+ /**
+ * @param {tcuTexture.Texture2D|tcuTexture.Texture2DArray} target
+ */
+ es3fTextureShadowTests.clampFloatingPointTexture2D = function(target) {
+ for (var level = 0; level < target.getNumLevels(); ++level)
+ if (!target.isLevelEmpty(level))
+ es3fTextureShadowTests.clampFloatingPointTexture(target.getLevel(level));
+ };
+
+ /**
+ * @param {tcuTexture.TextureCube} target
+ */
+ es3fTextureShadowTests.clampFloatingPointTextureCube = function(target) {
+ for (var level = 0; level < target.getNumLevels(); ++level)
+ for (var face = tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X; face < Object.keys(tcuTexture.CubeFace).length; face++)
+ es3fTextureShadowTests.clampFloatingPointTexture(target.getLevelFace(level, face));
+ };
+
+ /**
+ * @param {?} textureType
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.Texture2D|tcuTexture.Texture2DArray|tcuTexture.TextureCube} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrecision
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ */
+ es3fTextureShadowTests.verifyTexCompareResult = function(textureType, result, src, texCoord, sampleParams, comparePrec, lodPrecision, pixelFormat) {
+ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ var nonShadowThreshold = deMath.swizzle(tcuTexLookupVerifier.computeFixedPointThreshold(deMath.subtract(glsTextureTestUtil.getBitsVec(pixelFormat), [1, 1, 1, 1])), [1, 2, 3]);
+ var numFailedPixels;
+
+ if (es3fTextureShadowTests.isFloatingPointDepthFormat(src.getFormat())) {
+ var clampedSource = /*deUtil.clone(*/src/*)*/;
+
+ if (textureType == tcuTexture.Texture2D) {
+ es3fTextureShadowTests.clampFloatingPointTexture2D(/** @type {tcuTexture.Texture2D} */(clampedSource));
+ glsTextureTestUtil.sampleTexture2D(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DView} */ (clampedSource.getView()), texCoord, sampleParams);
+ // sample clamped values
+ numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2D(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DView} */ (clampedSource.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
+ } else if (textureType == tcuTexture.Texture2DArray) {
+ es3fTextureShadowTests.clampFloatingPointTexture2D(/** @type {tcuTexture.Texture2DArray} */(clampedSource));
+ glsTextureTestUtil.sampleTexture2DArray(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DArrayView} */ (clampedSource.getView()), texCoord, sampleParams);
+ // sample clamped values
+ numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DArrayView} */ (clampedSource.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
+ } else if (textureType == tcuTexture.TextureCube) {
+ es3fTextureShadowTests.clampFloatingPointTextureCube(/** @type {tcuTexture.TextureCube} */(clampedSource));
+ glsTextureTestUtil.sampleTextureCube(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.TextureCubeView} */ (clampedSource.getView()), texCoord, sampleParams);
+ // sample clamped values
+ numFailedPixels = glsTextureTestUtil.computeTextureCompareDiffCube(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.TextureCubeView} */ (clampedSource.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
+ } else
+ throw new Error('Invalid texture type');
+
+ } else {
+ if (textureType == tcuTexture.Texture2D) {
+ glsTextureTestUtil.sampleTexture2D(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DView} */ (src.getView()), texCoord, sampleParams);
+ // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
+ numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2D(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DView} */ (src.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
+ } else if (textureType == tcuTexture.Texture2DArray) {
+ glsTextureTestUtil.sampleTexture2DArray(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DArrayView} */ (src.getView()), texCoord, sampleParams);
+ // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
+ numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DArrayView} */ (src.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
+ } else if (textureType == tcuTexture.TextureCube) {
+ glsTextureTestUtil.sampleTextureCube(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.TextureCubeView} */ (src.getView()), texCoord, sampleParams);
+ // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
+ numFailedPixels = glsTextureTestUtil.computeTextureCompareDiffCube(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.TextureCubeView} */ (src.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
+ } else
+ throw new Error('Invalid texture type');
+ }
+
+ if (numFailedPixels > 0)
+ bufferedLogToConsole('ERROR: Result verification failed, got ' + numFailedPixels + ' invalid pixels!');
+
+ if (numFailedPixels > 0)
+ tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
+ else
+ tcuLogImage.logImageWithInfo(result, 'Result');
+
+ return numFailedPixels == 0;
+
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {number} format
+ * @struct
+ */
+ es3fTextureShadowTests.Format = function(name, format) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.format = format;
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @struct
+ */
+ es3fTextureShadowTests.Filter = function(name, minFilter, magFilter) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.minFilter = minFilter;
+ /** @type {number} */ this.magFilter = magFilter;
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {number} func
+ * @struct
+ */
+ es3fTextureShadowTests.CompareFunc = function(name, func) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.func = func;
+ };
+
+ /**
+ * @constructor
+ * @param {number} texNdx
+ * @param {number} ref
+ * @param {number} lodX
+ * @param {number} lodY
+ * @param {number} oX
+ * @param {number} oY
+ * @struct
+ */
+ es3fTextureShadowTests.TestCase = function(texNdx, ref, lodX, lodY, oX, oY) {
+ /** @type {number} */ this.texNdx = texNdx;
+ /** @type {number} */ this.ref = ref;
+ /** @type {number} */ this.lodX = lodX;
+ /** @type {number} */ this.lodY = lodY;
+ /** @type {number} */ this.oX = oX
+ /** @type {number} */ this.oY = oY;
+ };
+
+ /**
+ * @constructor
+ * @param {?gluTexture.Texture2D|?gluTexture.TextureCube|?gluTexture.Texture2DArray} tex
+ * @param {number} ref
+ * @param {Array<number>} minCoord
+ * @param {Array<number>} maxCoord
+ * @struct
+ */
+ es3fTextureShadowTests.FilterCase = function(tex, ref, minCoord, maxCoord) {
+ /** @type {?gluTexture.Texture2D|?gluTexture.TextureCube|?gluTexture.Texture2DArray} */ this.texture = tex;
+ /** @type {Array<number>} */ this.minCoord = minCoord;
+ /** @type {Array<number>} */ this.maxCoord = maxCoord;
+ /** @type {number} */ this.ref = ref;
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} compareFunc
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fTextureShadowTests.Texture2DShadowCase = function(name, desc, minFilter, magFilter, wrapS, wrapT, format, width, height, compareFunc) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_minFilter = minFilter;
+ this.m_magFilter = magFilter;
+ this.m_wrapS = wrapS;
+ this.m_wrapT = wrapT;
+ this.m_format = format;
+ this.m_width = width;
+ this.m_height = height;
+ this.m_compareFunc = compareFunc;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureShadowTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+ this.m_caseNdx = 0;
+ this.m_cases = [];
+ };
+
+ es3fTextureShadowTests.Texture2DShadowCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fTextureShadowTests.Texture2DShadowCase.prototype.constructor = es3fTextureShadowTests.Texture2DShadowCase;
+
+ es3fTextureShadowTests.Texture2DShadowCase.prototype.init = function() {
+
+ // Create 2 textures.
+ this.m_textures = [];
+ this.m_textures[0] = gluTexture.texture2DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height);
+ this.m_textures[1] = gluTexture.texture2DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height);
+
+ var numLevels = this.m_textures[0].getRefTexture().getNumLevels();
+
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ this.m_textures[0].getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithComponentGradients(this.m_textures[0].getRefTexture().getLevel(levelNdx), [-0.5, -0.5, -0.5, 2.0], [1, 1, 1, 0]);
+ }
+
+ for (levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ var step = 0x00ffffff / numLevels;
+ var rgb = step * levelNdx;
+ var colorA = 0xff000000 | rgb;
+ var colorB = 0xff000000 | ~rgb;
+
+ this.m_textures[1].getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithGrid(this.m_textures[1].getRefTexture().getLevel(levelNdx), 4, tcuRGBA.newRGBAFromValue(colorA).toVec(), tcuRGBA.newRGBAFromValue(colorB).toVec());
+ }
+
+ for (var i = 0; i < this.m_textures.length; i++)
+ this.m_textures[i].upload();
+
+ var refInRangeUpper = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 1.0 : 0.5;
+ var refInRangeLower = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 0.0 : 0.5;
+
+ var refOutOfBoundsUpper = 1.1;
+ var refOutOfBoundsLower = -0.1;
+
+ numLevels = this.m_textures[0].getRefTexture().getNumLevels();
+
+ var cases = [];
+ cases.push(new es3fTextureShadowTests.TestCase(0, refInRangeUpper, 1.6, 2.9, -1.0, -2.7));
+ cases.push(new es3fTextureShadowTests.TestCase(0, refInRangeLower, -2.0, -1.35, -0.2, 0.7));
+ cases.push(new es3fTextureShadowTests.TestCase(1, refInRangeUpper, 0.14, 0.275, -1.5, -1.1));
+ cases.push(new es3fTextureShadowTests.TestCase(1, refInRangeLower, -0.92, -2.64, 0.4, -0.1));
+ cases.push(new es3fTextureShadowTests.TestCase(1, refOutOfBoundsUpper, -0.39, -0.52, 0.65, 0.87));
+ cases.push(new es3fTextureShadowTests.TestCase(1, refOutOfBoundsLower, -1.55, 0.65, 0.35, 0.91));
+
+ var viewportW = Math.min(VIEWPORT_WIDTH, gl.canvas.width);
+ var viewportH = Math.min(VIEWPORT_HEIGHT, gl.canvas.height);
+
+ for (var caseNdx = 0; caseNdx < cases.length; caseNdx++) {
+ var texNdx = deMath.clamp(cases[caseNdx].texNdx, 0, this.m_textures.length - 1);
+ var ref = cases[caseNdx].ref;
+ var lodX = cases[caseNdx].lodX;
+ var lodY = cases[caseNdx].lodY;
+ var oX = cases[caseNdx].oX;
+ var oY = cases[caseNdx].oY;
+ var sX = Math.exp(lodX * Math.log(2)) * viewportW / this.m_textures[texNdx].getRefTexture().getWidth();
+ var sY = Math.exp(lodY * Math.log(2)) * viewportH / this.m_textures[texNdx].getRefTexture().getHeight();
+
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_textures[texNdx], ref, [oX, oY], [oX + sX, oY + sY]));
+ }
+
+ this.m_caseNdx = 0;
+ };
+
+ es3fTextureShadowTests.Texture2DShadowCase.prototype.iterate = function() {
+
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+ var curCase = this.m_cases[this.m_caseNdx];
+ var sampleParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D);
+ var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
+ var texCoord = [];
+
+ if (viewport.width < MIN_VIEWPORT_WIDTH || viewport.height < MIN_VIEWPORT_HEIGHT)
+ throw new Error('Too small render target');
+
+ // Setup params for reference.
+ sampleParams.sampler = gluTextureUtil.mapGLSampler(this.m_wrapS, this.m_wrapT, gl.CLAMP_TO_EDGE, this.m_minFilter, this.m_magFilter);
+ sampleParams.sampler.compare = gluTextureUtil.mapGLCompareFunc(this.m_compareFunc);
+ sampleParams.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW;
+ sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ sampleParams.ref = curCase.ref;
+
+ bufferedLogToConsole('Compare reference value = ' + sampleParams.ref);
+
+ // Compute texture coordinates.
+ bufferedLogToConsole('Texture coordinates: ' + curCase.minCoord + ' -> ' + curCase.maxCoord);
+
+ texCoord = glsTextureTestUtil.computeQuadTexCoord2D(curCase.minCoord, curCase.maxCoord);
+
+ gl.bindTexture(gl.TEXTURE_2D, curCase.texture.getGLTexture());
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.m_wrapT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, this.m_compareFunc);
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+ this.m_renderer.renderQuad(0, texCoord, sampleParams);
+ rendered.readViewport(gl, viewport);
+
+
+ var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ var lodPrecision = new tcuTexLookupVerifier.LodPrecision(18, 6);
+ var texComparePrecision = new tcuTexCompareVerifier.TexComparePrecision([20, 20, 0], [7, 7, 0], 5, 16, pixelFormat.redBits - 1);
+
+ var isHighQuality = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2D, rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
+
+ if (!isHighQuality) {
+ bufferedLogToConsole('Warning: Verification assuming high-quality PCF filtering failed.');
+
+ lodPrecision.lodBits = 4;
+ texComparePrecision.uvwBits = [4, 4, 0];
+ texComparePrecision.pcfBits = 0;
+
+ var isOk = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2D, rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
+
+ if (!isOk) {
+ bufferedLogToConsole('ERROR: Verification against low precision requirements failed, failing test case.');
+ testFailedOptions('Image verification failed', false);
+ } else
+ testPassedOptions('Low-quality result', true);
+ } else
+ testPassedOptions('High-quality result', true);
+
+ this.m_caseNdx += 1;
+ return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} format
+ * @param {number} size
+ * @param {number} compareFunc
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fTextureShadowTests.TextureCubeShadowCase = function(name, desc, minFilter, magFilter, wrapS, wrapT, format, size, compareFunc) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_minFilter = minFilter;
+ this.m_magFilter = magFilter;
+ this.m_wrapS = wrapS;
+ this.m_wrapT = wrapT;
+ this.m_format = format;
+ this.m_size = size;
+ this.m_compareFunc = compareFunc;
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureShadowTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+ this.m_caseNdx = 0;
+ this.m_cases = [];
+ };
+
+ es3fTextureShadowTests.TextureCubeShadowCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fTextureShadowTests.TextureCubeShadowCase.prototype.constructor = es3fTextureShadowTests.TextureCubeShadowCase;
+
+ es3fTextureShadowTests.TextureCubeShadowCase.prototype.init = function() {
+ DE_ASSERT(!this.m_gradientTex && !this.m_gridTex);
+
+ var numLevels = Math.floor(Math.log2(this.m_size)) + 1;
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ /** @type {Array<number>} */ var cBias = fmtInfo.valueMin;
+ /** @type {Array<number>} */ var cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
+
+ // Create textures.
+ this.m_gradientTex = gluTexture.cubeFromInternalFormat(gl, this.m_format, this.m_size);
+ this.m_gridTex = gluTexture.cubeFromInternalFormat(gl, this.m_format, this.m_size);
+
+ // Fill first with gradient texture.
+ var gradients = [[[-1.0, -1.0, -1.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // negative x
+ [[0.0, -1.0, -1.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // positive x
+ [[-1.0, 0.0, -1.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // negative y
+ [[-1.0, -1.0, 0.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // positive y
+ [[-1.0, -1.0, -1.0, 0.0], [1.0, 1.0, 1.0, 1.0]], // negative z
+ [[0.0, 0.0, 0.0, 2.0], [1.0, 1.0, 1.0, 0.0]]]; // positive z
+
+ for (var face in tcuTexture.CubeFace) {
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ this.m_gradientTex.getRefTexture().allocLevel(tcuTexture.CubeFace[face], levelNdx);
+ tcuTextureUtil.fillWithComponentGradients(this.m_gradientTex.getRefTexture().getLevelFace(levelNdx, tcuTexture.CubeFace[face]), deMath.add(deMath.multiply(gradients[tcuTexture.CubeFace[face]][0], cScale), cBias), deMath.add(deMath.multiply(gradients[tcuTexture.CubeFace[face]][1], cScale), cBias));
+ }
+ }
+
+ // Fill second with grid texture.
+ for (var face in tcuTexture.CubeFace) {
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ var step = 0x00ffffff / (numLevels * Object.keys(tcuTexture.CubeFace).length);
+ var rgb = step * levelNdx * face;
+ var colorA = 0xff000000 | rgb;
+ var colorB = 0xff000000 | ~rgb;
+
+ this.m_gridTex.getRefTexture().allocLevel(tcuTexture.CubeFace[face], levelNdx);
+ tcuTextureUtil.fillWithGrid(this.m_gridTex.getRefTexture().getLevelFace(levelNdx, tcuTexture.CubeFace[face]), 4, deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorA).toVec(), cScale), cBias), deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorB).toVec(), cScale), cBias));
+ }
+ }
+
+ // Upload.
+ this.m_gradientTex.upload();
+ this.m_gridTex.upload();
+
+ var refInRangeUpper = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 1.0 : 0.5;
+ var refInRangeLower = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 0.0 : 0.5;
+ var refOutOfBoundsUpper = 1.1;
+ var refOutOfBoundsLower = -0.1;
+ var singleSample = new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess().getNumSamples() == 0;
+ //var singleSample = this.m_context.getRenderTarget().getNumSamples() == 0;
+
+ if (singleSample)
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gradientTex, refInRangeUpper, [-1.25, -1.2], [1.2, 1.25])); // minification
+ else
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gradientTex, refInRangeUpper, [-1.19, -1.3], [1.1, 1.35])); // minification - w/ tuned coordinates to avoid hitting triangle edges
+
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gradientTex, refInRangeLower, [0.8, 0.8], [1.25, 1.20])); // magnification
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refInRangeUpper, [-1.19, -1.3], [1.1, 1.35])); // minification
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refInRangeLower, [-1.2, -1.1], [-0.8, -0.8])); // magnification
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refOutOfBoundsUpper, [-0.61, -0.1], [0.9, 1.18])); // reference value clamp, upper
+
+ if (singleSample)
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refOutOfBoundsLower, [-0.75, 1.0], [0.05, 0.75])); // reference value clamp, lower
+ else
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refOutOfBoundsLower, [-0.75, 1.0], [0.25, 0.75])); // reference value clamp, lower
+
+ this.m_caseNdx = 0;
+ };
+
+ es3fTextureShadowTests.TextureCubeShadowCase.prototype.iterate = function() {
+ var viewportSize = 28;
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), viewportSize, viewportSize, deString.deStringHash(this.fullName()) ^ deMath.deMathHash(this.m_caseNdx));
+ var curCase = this.m_cases[this.m_caseNdx];
+ var sampleParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_CUBE);
+
+ if (viewport.width < viewportSize || viewport.height < viewportSize)
+ throw new Error('Too small render target');
+
+ // Setup texture
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, curCase.texture.getGLTexture());
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this.m_wrapT);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, this.m_compareFunc);
+
+ // Other state
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ // Params for reference computation.
+ sampleParams.sampler = gluTextureUtil.mapGLSampler(gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, this.m_minFilter, this.m_magFilter);
+ sampleParams.sampler.seamlessCubeMap = true;
+ sampleParams.sampler.compare = gluTextureUtil.mapGLCompareFunc(this.m_compareFunc);
+ sampleParams.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW;
+ sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ sampleParams.ref = curCase.ref;
+
+ bufferedLogToConsole(
+ 'Compare reference value = ' + sampleParams.ref + '\n' +
+ 'Coordinates: ' + curCase.minCoord + ' -> ' + curCase.maxCoord);
+
+ for (var faceNdx in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[faceNdx];
+ var result = new tcuSurface.Surface(viewport.width, viewport.height);
+ var texCoord = [];
+
+ texCoord = glsTextureTestUtil.computeQuadTexCoordCubeFace(face, curCase.minCoord, curCase.maxCoord);
+
+ this.m_renderer.renderQuad(0, texCoord, sampleParams);
+
+ result.readViewport(gl, viewport);
+
+ var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ /** @type {tcuTexLookupVerifier.LodPrecision} */ var lodPrecision = new tcuTexLookupVerifier.LodPrecision(10, 5);
+ /** @type {tcuTexCompareVerifier.TexComparePrecision} */ var texComparePrecision = new tcuTexCompareVerifier.TexComparePrecision(
+ [10, 10, 10],
+ [6, 6, 0],
+ 5,
+ 16,
+ pixelFormat.redBits - 1
+ );
+
+ var isHighQuality = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.TextureCube, result.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
+
+ if (!isHighQuality) {
+ bufferedLogToConsole('Warning: Verification assuming high-quality PCF filtering failed.');
+
+ lodPrecision.lodBits = 4;
+ texComparePrecision.uvwBits = [4, 4, 0];
+ texComparePrecision.pcfBits = 0;
+
+ var isOk = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.TextureCube, result.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
+ if (!isOk) {
+ bufferedLogToConsole('ERROR: Verification against low precision requirements failed, failing test case.');
+ testFailedOptions('Image verification failed', false);
+ } else
+ testPassedOptions('Low-quality result', true);
+ }
+ else
+ testPassedOptions('High-quality result', true);
+ }
+
+ this.m_caseNdx += 1;
+ return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * Testure2DArrayShadowCase
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ * @param {number} compareFunc
+ */
+ es3fTextureShadowTests.Texture2DArrayShadowCase = function(name, desc, minFilter, magFilter, wrapS, wrapT, format, width, height, numLayers, compareFunc) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /** @type {number} */ this.m_minFilter = minFilter;
+ /** @type {number} */ this.m_magFilter = magFilter;
+ /** @type {number} */ this.m_wrapS = wrapS;
+ /** @type {number} */ this.m_wrapT = wrapT;
+ /** @type {number} */ this.m_format = format;
+ /** @type {number} */ this.m_width = width;
+ /** @type {number} */ this.m_height = height;
+ /** @type {number} */ this.m_numLayers = numLayers;
+ /** @type {number} */ this.m_compareFunc = compareFunc;
+ /** @type {?gluTexture.Texture2DArray} */ this.m_gradientTex = null;
+ /** @type {?gluTexture.Texture2DArray} */ this.m_gridTex = null;
+ /** @type {glsTextureTestUtil.TextureRenderer} */ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureShadowTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
+ /** @type {Array<es3fTextureShadowTests.FilterCase>} */ this.m_cases = [];
+ /** @type {number} */ this.m_caseNdx = 0;
+ };
+
+ es3fTextureShadowTests.Texture2DArrayShadowCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fTextureShadowTests.Texture2DArrayShadowCase.prototype.constructor = es3fTextureShadowTests.Texture2DArrayShadowCase;
+
+ /**
+ * init
+ */
+ es3fTextureShadowTests.Texture2DArrayShadowCase.prototype.init = function() {
+ /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
+ /** @type {Array<number>}*/ var cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
+ /** @type {Array<number>}*/ var cBias = fmtInfo.valueMin;
+ /** @type {number}*/ var numLevels = deMath.logToFloor(Math.max(this.m_width, this.m_height)) + 1;
+
+ // Create textures.
+ this.m_gradientTex = gluTexture.texture2DArrayFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, this.m_numLayers);
+ this.m_gridTex = gluTexture.texture2DArrayFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, this.m_numLayers);
+
+ // Fill first gradient texture.
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ /** @type {Array<number>}*/ var gMin = deMath.add(deMath.multiply([-0.5, -0.5, -0.5, 2.0], cScale), cBias);
+ /** @type {Array<number>}*/ var gMax = deMath.add(deMath.multiply([1.0, 1.0, 1.0, 0.0], cScale), cBias);
+
+ this.m_gradientTex.getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithComponentGradients(
+ /** @type {tcuTexture.PixelBufferAccess} */ (this.m_gradientTex.getRefTexture().getLevel(levelNdx)), gMin, gMax);
+ }
+
+ // Fill second with grid texture.
+ for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
+ /** @type {number}*/ var step = Math.floor(0x00ffffff / numLevels);
+ /** @type {number}*/ var rgb = step * levelNdx;
+ /** @type {number}*/ var colorA = deMath.binaryOp(0xff000000, rgb, deMath.BinaryOp.OR);
+ /** @type {number}*/ var colorB = deMath.binaryOp(0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR);
+
+ this.m_gridTex.getRefTexture().allocLevel(levelNdx);
+ tcuTextureUtil.fillWithGrid(
+ /** @type {tcuTexture.PixelBufferAccess} */ (this.m_gridTex.getRefTexture().getLevel(levelNdx)), 4,
+ deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorA).toVec(), cScale), cBias),
+ deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorB).toVec(), cScale), cBias)
+ );
+ }
+
+ // Upload.
+ this.m_gradientTex.upload();
+ this.m_gridTex.upload();
+
+ // Compute cases.
+ /** @type {number} */ var refInRangeUpper = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 1.0 : 0.5;
+ /** @type {number} */ var refInRangeLower = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 0.0 : 0.5;
+ /** @type {number} */ var refOutOfBoundsUpper = 1.1; // !< lookup function should clamp values to [0, 1] range
+ /** @type {number} */ var refOutOfBoundsLower = -0.1;
+
+ /** @type {Array<{texNdx: number, ref: number, lodX: number, lodY: number, oX: number, oY: number}>} */
+ var cases = [{ texNdx: 0, ref: refInRangeUpper, lodX: 1.6, lodY: 2.9, oX: -1.0, oY: -2.7 },{ texNdx: 0, ref: refInRangeLower, lodX: -2.0, lodY: -1.35, oX: -0.2, oY: 0.7 },{ texNdx: 1, ref: refInRangeUpper, lodX: 0.14, lodY: 0.275, oX: -1.5, oY: -1.1 },{ texNdx: 1, ref: refInRangeLower, lodX: -0.92, lodY: -2.64, oX: 0.4, oY: -0.1 },{ texNdx: 1, ref: refOutOfBoundsUpper, lodX: -0.49, lodY: -0.22, oX: 0.45, oY: 0.97 },{ texNdx: 1, ref: refOutOfBoundsLower, lodX: -0.85, lodY: 0.75, oX: 0.25, oY: 0.61 }
+ ];
+
+ var viewportW = Math.min(VIEWPORT_WIDTH, gl.canvas.width);
+ var viewportH = Math.min(VIEWPORT_HEIGHT, gl.canvas.height);
+
+ /** @type {number} */ var minLayer = -0.5;
+ /** @type {number} */ var maxLayer = this.m_numLayers;
+
+ for (var caseNdx = 0; caseNdx < cases.length; caseNdx++) {
+ var tex = cases[caseNdx].texNdx > 0 ? this.m_gridTex : this.m_gradientTex;
+ /** @type {number} */ var ref = cases[caseNdx].ref;
+ /** @type {number} */ var lodX = cases[caseNdx].lodX;
+ /** @type {number} */ var lodY = cases[caseNdx].lodY;
+ /** @type {number} */ var oX = cases[caseNdx].oX;
+ /** @type {number} */ var oY = cases[caseNdx].oY;
+ /** @type {number} */ var sX = Math.exp(lodX * Math.LN2) * viewportW / tex.getRefTexture().getWidth();
+ /** @type {number} */ var sY = Math.exp(lodY * Math.LN2) * viewportH / tex.getRefTexture().getHeight();
+
+ this.m_cases.push(new es3fTextureShadowTests.FilterCase(tex, ref, [oX, oY, minLayer], [oX + sX, oY + sY, maxLayer]));
+ }
+
+ this.m_caseNdx = 0;
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureShadowTests.Texture2DArrayShadowCase.prototype.iterate = function() {
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, deString.deStringHash(this.fullName()) ^ deMath.deMathHash(this.m_caseNdx));
+ var curCase = this.m_cases[this.m_caseNdx];
+ var sampleParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY);
+ var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
+ var texCoord = [];
+
+ texCoord = [curCase.minCoord[0], curCase.minCoord[1], curCase.minCoord[2],
+ curCase.minCoord[0], curCase.maxCoord[1], (curCase.minCoord[2] + curCase.maxCoord[2]) / 2.0,
+ curCase.maxCoord[0], curCase.minCoord[1], (curCase.minCoord[2] + curCase.maxCoord[2]) / 2.0,
+ curCase.maxCoord[0], curCase.maxCoord[1], curCase.maxCoord[2]];
+
+ if (viewport.width < MIN_VIEWPORT_WIDTH || viewport.height < MIN_VIEWPORT_HEIGHT)
+ throw new Error('Too small render target');
+
+ sampleParams.sampler = gluTextureUtil.mapGLSamplerWrapST(this.m_wrapS, this.m_wrapT, this.m_minFilter, this.m_magFilter);
+ sampleParams.sampler.compare = gluTextureUtil.mapGLCompareFunc(this.m_compareFunc);
+ sampleParams.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW;
+ sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ sampleParams.ref = curCase.ref;
+
+ bufferedLogToConsole(
+ 'Compare reference value = ' + sampleParams.ref + '\n' +
+ 'Texture Coordinates: ' + curCase.minCoord + ' -> ' + curCase.maxCoord
+ );
+
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, curCase.texture.getGLTexture());
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, this.m_wrapT);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_COMPARE_FUNC, this.m_compareFunc);
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+ this.m_renderer.renderQuad(0, texCoord, sampleParams);
+ rendered.readViewport(gl, viewport);
+
+ var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ /** @type {tcuTexLookupVerifier.LodPrecision} */ var lodPrecision = new tcuTexLookupVerifier.LodPrecision(18, 6);
+ /** @type {tcuTexCompareVerifier.TexComparePrecision} */ var texComparePrecision = new tcuTexCompareVerifier.TexComparePrecision(
+ [20, 20, 20],
+ [7, 7, 7],
+ 5,
+ 16,
+ pixelFormat.redBits - 1
+ );
+
+ var isHighQuality = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2DArray, rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
+
+ if (!isHighQuality) {
+ bufferedLogToConsole('Warning: Verification assuming high-quality PCF filtering failed');
+
+ lodPrecision.lodBits = 4;
+ texComparePrecision.uvwBits = [4, 4, 4];
+ texComparePrecision.pcfBits = 0;
+
+ var isOk = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2DArray, rendered.getAccess(), curCase.texture.getRefTexture(),
+ texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
+
+ if (!isOk) {
+ bufferedLogToConsole('ERROR: Verification against low precision requirements failed, failing test case.');
+ testFailedOptions('Image verification failed', false);
+ } else
+ testPassedOptions('Low-quality result', true);
+ } else
+ testPassedOptions('High-quality result', true);
+
+ this.m_caseNdx += 1;
+ return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ };
+
+ es3fTextureShadowTests.init = function() {
+ /** @type {Array<es3fTextureShadowTests.Format>} */ var formats = [];
+ formats.push(new es3fTextureShadowTests.Format('depth_component16', gl.DEPTH_COMPONENT16));
+ formats.push(new es3fTextureShadowTests.Format('depth_component32f', gl.DEPTH_COMPONENT32F));
+ formats.push(new es3fTextureShadowTests.Format('depth24_stencil8', gl.DEPTH24_STENCIL8));
+
+ /** @type {Array<es3fTextureShadowTests.Filter>} */ var filters = [];
+ filters.push(new es3fTextureShadowTests.Filter('nearest', gl.NEAREST, gl.NEAREST));
+ filters.push(new es3fTextureShadowTests.Filter('linear', gl.LINEAR, gl.LINEAR));
+ filters.push(new es3fTextureShadowTests.Filter('nearest_mipmap_nearest', gl.NEAREST_MIPMAP_NEAREST, gl.LINEAR));
+ filters.push(new es3fTextureShadowTests.Filter('linear_mipmap_nearest', gl.LINEAR_MIPMAP_NEAREST, gl.LINEAR));
+ filters.push(new es3fTextureShadowTests.Filter('nearest_mipmap_linear', gl.NEAREST_MIPMAP_LINEAR, gl.LINEAR));
+ filters.push(new es3fTextureShadowTests.Filter('linear_mipmap_linear', gl.LINEAR_MIPMAP_LINEAR, gl.LINEAR));
+
+ /** @type {Array<es3fTextureShadowTests.CompareFunc>} */ var compareFuncs = [];
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('less_or_equal', gl.LEQUAL));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('greater_or_equal', gl.GEQUAL));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('less', gl.LESS));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('greater', gl.GREATER));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('equal', gl.EQUAL));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('not_equal', gl.NOTEQUAL));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('always', gl.ALWAYS));
+ compareFuncs.push(new es3fTextureShadowTests.CompareFunc('never', gl.NEVER));
+
+ var state = tcuTestCase.runner;
+ /** @type {tcuTestCase.DeqpTest} */ var testGroup = state.testCases;
+
+ for (var filterNdx = 0; filterNdx < filters.length; filterNdx++) {
+ for (var compareNdx = 0; compareNdx < compareFuncs.length; compareNdx++) {
+ var filterGroup = tcuTestCase.newTest(
+ '2d.' + filters[filterNdx].name, '2D texture shadow lookup tests');
+ testGroup.addChild(filterGroup);
+
+ for (var formatNdx = 0; formatNdx < formats.length; formatNdx++) {
+ /** @type {number} */ var minFilter = filters[filterNdx].minFilter;
+ /** @type {number} */ var magFilter = filters[filterNdx].magFilter;
+ /** @type {number} */ var format = formats[formatNdx].format;
+ /** @type {number} */ var compareFunc = compareFuncs[compareNdx].func;
+ /** @type {number} */ var wrapS = gl.REPEAT;
+ /** @type {number} */ var wrapT = gl.REPEAT;
+ /** @type {number} */ var width = 32;
+ /** @type {number} */ var height = 64;
+ /** @type {string} */ var name = compareFuncs[compareNdx].name + '_' + formats[formatNdx].name;
+
+ filterGroup.addChild(new es3fTextureShadowTests.Texture2DShadowCase(name, '', minFilter, magFilter, wrapS, wrapT, format, width, height, compareFunc));
+ }
+ }
+ }
+
+ for (filterNdx = 0; filterNdx < filters.length; filterNdx++) {
+ for (compareNdx = 0; compareNdx < compareFuncs.length; compareNdx++) {
+ filterGroup = tcuTestCase.newTest(
+ 'cube.' + filters[filterNdx].name, 'Cube map texture shadow lookup tests');
+ testGroup.addChild(filterGroup);
+
+ for (formatNdx = 0; formatNdx < formats.length; formatNdx++) {
+ minFilter = filters[filterNdx].minFilter;
+ magFilter = filters[filterNdx].magFilter;
+ format = formats[formatNdx].format;
+ compareFunc = compareFuncs[compareNdx].func;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ var size = 32;
+ name = compareFuncs[compareNdx].name + '_' + formats[formatNdx].name;
+
+ filterGroup.addChild(new es3fTextureShadowTests.TextureCubeShadowCase(name, '', minFilter, magFilter, wrapS, wrapT, format, size, compareFunc));
+ }
+ }
+ }
+
+ for (var filterNdx = 0; filterNdx < filters.length; filterNdx++) {
+ for (var compareNdx = 0; compareNdx < compareFuncs.length; compareNdx++) {
+ filterGroup = tcuTestCase.newTest(
+ '2d_array.' + filters[filterNdx].name, '2D texture array shadow lookup tests');
+ testGroup.addChild(filterGroup);
+
+ for (var formatNdx = 0; formatNdx < formats.length; formatNdx++) {
+ minFilter = filters[filterNdx].minFilter;
+ magFilter = filters[filterNdx].magFilter;
+ format = formats[formatNdx].format;
+ compareFunc = compareFuncs[compareNdx].func;
+ wrapS = gl.REPEAT;
+ wrapT = gl.REPEAT;
+ width = 32;
+ height = 64;
+ var numLayers = 8;
+ name = compareFuncs[compareNdx].name + '_' + formats[formatNdx].name;
+
+ filterGroup.addChild(new es3fTextureShadowTests.Texture2DArrayShadowCase(name, '', minFilter, magFilter, wrapS, wrapT, format, width, height, numLayers, compareFunc));
+ }
+ }
+ }
+ };
+
+ es3fTextureShadowTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'texture_shadow';
+ var testDescription = 'Texture Shadow Test';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fTextureShadowTests.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureSpecificationTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureSpecificationTests.js
new file mode 100644
index 0000000000..5ff5edc550
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureSpecificationTests.js
@@ -0,0 +1,7456 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fTextureSpecificationTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.referencerenderer.rrUtil');
+goog.require('functional.gles3.es3fFboTestUtil');
+
+goog.scope(function() {
+ var es3fTextureSpecificationTests =
+ functional.gles3.es3fTextureSpecificationTests;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var sglrReferenceContext =
+ framework.opengl.simplereference.sglrReferenceContext;
+ var rrUtil = framework.referencerenderer.rrUtil;
+ var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
+ var tcuLogImage = framework.common.tcuLogImage;
+
+ /**
+ * @param {number} internalFormat
+ * @return {tcuTexture.TextureFormat}
+ */
+ es3fTextureSpecificationTests.mapGLUnsizedInternalFormat = function(
+ internalFormat
+ ) {
+ switch (internalFormat) {
+ case gl.ALPHA:
+ return new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.A,
+ tcuTexture.ChannelType.UNORM_INT8
+ );
+ case gl.LUMINANCE:
+ return new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.L,
+ tcuTexture.ChannelType.UNORM_INT8
+ );
+ case gl.LUMINANCE_ALPHA:
+ return new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.LA,
+ tcuTexture.ChannelType.UNORM_INT8
+ );
+ case gl.RGB:
+ return new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGB,
+ tcuTexture.ChannelType.UNORM_INT8
+ );
+ case gl.RGBA:
+ return new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8
+ );
+ default:
+ throw new Error(
+ 'Can\'t map GL unsized internal format (' +
+ internalFormat.toString(16) + ') to texture format'
+ );
+ }
+ };
+
+ var VIEWPORT_WIDTH = 256;
+ var VIEWPORT_HEIGHT = 256;
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ * @param {number=} depth
+ * @return {number}
+ */
+ es3fTextureSpecificationTests.maxLevelCount = function(
+ width, height, depth
+ ) {
+ depth = depth || 0;
+ return deMath.logToFloor(Math.max(width, Math.max(height, depth))) + 1;
+ };
+
+ /**
+ * @param {deRandom.Random} rnd
+ * @param {Array<number>} minVal
+ * @param {Array<number>} maxVal
+ * @param {number} size
+ * @return {Array<number>}
+ */
+ es3fTextureSpecificationTests.randomVector = function(
+ rnd, minVal, maxVal, size
+ ) {
+ var res = [];
+ for (var ndx = 0; ndx < size; ndx++)
+ res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
+ return res;
+ };
+
+ /**
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ * @param {tcuTexture.TextureFormat} textureFormat
+ * @return {Array<number>} (ivec4)
+ */
+ es3fTextureSpecificationTests.getPixelFormatCompareDepth = function(
+ pixelFormat, textureFormat
+ ) {
+ switch (textureFormat.order) {
+ case tcuTexture.ChannelOrder.L:
+ case tcuTexture.ChannelOrder.LA:
+ return [
+ pixelFormat.redBits, pixelFormat.redBits,
+ pixelFormat.redBits, pixelFormat.alphaBits
+ ];
+ default:
+ return [
+ pixelFormat.redBits, pixelFormat.greenBits,
+ pixelFormat.blueBits, pixelFormat.alphaBits
+ ];
+ }
+ };
+
+ /**
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ * @param {tcuTexture.TextureFormat} textureFormat
+ * @return {Array<number>} (uvec4)
+ */
+ es3fTextureSpecificationTests.computeCompareThreshold = function(
+ pixelFormat, textureFormat
+ ) {
+ /** @type {Array<number>} */
+ var texFormatBits = tcuTextureUtil.getTextureFormatBitDepth(
+ textureFormat
+ );
+ /** @type {Array<number>} */
+ var pixelFormatBits =
+ es3fTextureSpecificationTests.getPixelFormatCompareDepth(
+ pixelFormat, textureFormat
+ );
+ /** @type {Array<number>} */
+ var accurateFmtBits = deMath.min(pixelFormatBits, texFormatBits);
+ /** @type {Array<number>} */
+ var compareBits = deMath.addScalar(
+ tcuTextureUtil.select(
+ accurateFmtBits, [8, 8, 8, 8],
+ deMath.greaterThan(accurateFmtBits, [0, 0, 0, 0])
+ ), - 1
+ );
+
+ var result = [];
+ for (var i = 0; i < compareBits.length; i++)
+ result.push(1 << compareBits[i]);
+ return result;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * context
+ */
+ es3fTextureSpecificationTests.TextureSpecCase = function(name, desc) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ /**
+ * @type {
+ * ?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext
+ * }
+ */
+ this.m_context = null;
+ };
+
+ es3fTextureSpecificationTests.TextureSpecCase.prototype = Object.create(
+ tcuTestCase.DeqpTest.prototype
+ );
+
+ es3fTextureSpecificationTests.TextureSpecCase.prototype.constructor =
+ es3fTextureSpecificationTests.TextureSpecCase;
+
+ /**
+ * deinit
+ */
+ es3fTextureSpecificationTests.TextureSpecCase.prototype.deinit =
+ function() {
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0);
+
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ }
+
+ /**
+ * createTexture - Needs to be overridden
+ */
+ es3fTextureSpecificationTests.TextureSpecCase.prototype.createTexture =
+ function() {
+ throw new Error('Must override');
+ };
+
+ /**
+ * verifyTexture - Needs to be overridden
+ * @param {sglrGLContext.GLContext} webgl2Context
+ * @param {sglrReferenceContext.ReferenceContext} refContext
+ * @return {boolean}
+ */
+ es3fTextureSpecificationTests.TextureSpecCase.prototype.verifyTexture =
+ function(
+ webgl2Context, refContext
+ ) {
+ throw new Error('Must override');
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureSpecificationTests.TextureSpecCase.prototype.iterate = function() {
+ if (gl.canvas.width < VIEWPORT_WIDTH ||
+ gl.canvas.height < VIEWPORT_HEIGHT)
+ throw new Error('Too small viewport', '');
+
+ // Context size, and viewport for GLES3
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var width = Math.min(gl.canvas.width, VIEWPORT_WIDTH);
+ var height = Math.min(gl.canvas.height, VIEWPORT_HEIGHT);
+ var x = rnd.getInt(0, gl.canvas.width - width);
+ var y = rnd.getInt(0, gl.canvas.height - height);
+
+ // Contexts.
+ /** @type {sglrGLContext.GLContext} */
+ var webgl2Context = new sglrGLContext.GLContext(
+ gl, [x, y, width, height]
+ );
+
+ /** @type {sglrReferenceContext.ReferenceContextBuffers} */
+ var refBuffers = new sglrReferenceContext.ReferenceContextBuffers(
+ new tcuPixelFormat.PixelFormat(
+ 8, 8, 8, gl.getParameter(gl.ALPHA_BITS) ? 8 : 0
+ ), 0 /* depth */, 0 /* stencil */, width, height
+ );
+
+ /** @type {sglrReferenceContext.ReferenceContext} */
+ var refContext = new sglrReferenceContext.ReferenceContext(
+ new sglrReferenceContext.ReferenceContextLimits(gl),
+ refBuffers.getColorbuffer(), refBuffers.getDepthbuffer(),
+ refBuffers.getStencilbuffer()
+ );
+
+ // Clear color buffer.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ this.m_context = ndx ? refContext : webgl2Context;
+ // C++ port uses (0.125, 0.25, 0.5, 1.0), but here we use (0, 0, 0, 0)
+ // in order to optimize the `clear' op in ReferenceContext.
+ this.m_context.clearColor(0, 0, 0, 0);
+ this.m_context.clear(
+ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT |
+ gl.STENCIL_BUFFER_BIT
+ );
+ }
+
+ // Construct texture using both GLES3 and reference contexts.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ this.m_context = ndx ? refContext : webgl2Context;
+ this.createTexture();
+ checkMessage(
+ this.m_context.getError() == gl.NO_ERROR,
+ 'Problem creating texture.'
+ );
+ }
+
+ // Verify results.
+ if (this.verifyTexture(webgl2Context, refContext))
+ testPassed();
+ else
+ testFailed('Verification failed');
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ * @param {
+ * ?WebGLProgram|
+ * framework.opengl.simplereference.sglrShaderProgram.ShaderProgram
+ * } program
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.TextureSpecCase.prototype.renderTex =
+ function(dst, program, width, height) {
+ var targetW = this.m_context.getWidth();
+ var targetH = this.m_context.getHeight();
+
+ var w = width / targetW;
+ var h = height / targetH;
+
+ rrUtil.drawQuad(
+ this.m_context, program, [-1.0, -1.0, 0.0],
+ [-1.0 + w * 2.0, -1.0 + h * 2.0, 0.0]
+ );
+
+ // Read pixels back.
+ dst.readViewport(this.m_context, [0, 0, width, height]);
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.Texture2DSpecCase = function(
+ name, desc, format, width, height, numLevels
+ ) {
+ es3fTextureSpecificationTests.TextureSpecCase.call(this, name, desc);
+
+ this.m_texFormat = format;
+ this.m_texFormatInfo = tcuTextureUtil.getTextureFormatInfo(format);
+ this.m_width = width;
+ this.m_height = height;
+ this.m_numLevels = numLevels;
+ };
+
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype = Object.create(
+ es3fTextureSpecificationTests.TextureSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype.constructor =
+ es3fTextureSpecificationTests.Texture2DSpecCase;
+
+ /**
+ * @param {sglrGLContext.GLContext} webgl2Context
+ * @param {sglrReferenceContext.ReferenceContext} refContext
+ */
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype.verifyTexture =
+ function(
+ webgl2Context, refContext
+ ) {
+ /** @type {es3fFboTestUtil.Texture2DShader} */
+ var shader = new es3fFboTestUtil.Texture2DShader(
+ [gluTextureUtil.getSampler2DType(this.m_texFormat)],
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+
+ var shaderIDgles = webgl2Context.createProgram(shader);
+ var shaderIDRef = refContext.createProgram(shader);
+
+ shader.setTexScaleBias(
+ 0, this.m_texFormatInfo.lookupScale,
+ this.m_texFormatInfo.lookupBias
+ );
+
+ // Set state.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var ctx = ndx ? refContext : webgl2Context;
+
+ this.m_context = ctx;
+
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, this.m_numLevels - 1
+ );
+ }
+
+ for (var levelNdx = 0; levelNdx < this.m_numLevels; levelNdx++) {
+ var levelW = Math.max(1, this.m_width >> levelNdx);
+ var levelH = Math.max(1, this.m_height >> levelNdx);
+ /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface();
+ /** @type {tcuSurface.Surface} */ var result = new tcuSurface.Surface();
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ /** @type {tcuSurface.Surface} */
+ var dst = ndx ? reference : result;
+ var ctx = ndx ? refContext : webgl2Context;
+ var shaderID = ndx ? shaderIDRef : shaderIDgles;
+
+ this.m_context = ctx;
+ shader.setUniforms(ctx, shaderID);
+ this.renderTex(dst, shaderID, levelW, levelH);
+ }
+
+ var threshold =
+ es3fTextureSpecificationTests.computeCompareThreshold(
+ tcuPixelFormat.PixelFormatFromContext(gl), this.m_texFormat
+ );
+ var levelStr = levelNdx.toString();
+ var name = 'Level' + levelStr;
+ var desc = 'Level ' + levelStr;
+ var isOk = tcuImageCompare.intThresholdCompare(
+ name, desc, reference.getAccess(), result.getAccess(),
+ threshold, levelNdx == 0 ?
+ tcuImageCompare.CompareLogMode.RESULT :
+ tcuImageCompare.CompareLogMode.ON_ERROR
+ );
+
+ if (!isOk) {
+ testFailed('Image comparison failed');
+ return false;
+ } else {
+ // tcuLogImage.logImageWithInfo(result.getAccess(),'Comparison OK on level: ' + levelNdx);
+ }
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} size
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.TextureCubeSpecCase = function(
+ name, desc, format, size, numLevels
+ ) {
+ es3fTextureSpecificationTests.TextureSpecCase.call(
+ this, name, desc
+ );
+ this.m_texFormat = format;
+ this.m_texFormatInfo = tcuTextureUtil.getTextureFormatInfo(format);
+ this.m_size = size;
+ this.m_numLevels = numLevels;
+ };
+
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype =
+ Object.create(es3fTextureSpecificationTests.TextureSpecCase.prototype);
+
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype.constructor =
+ es3fTextureSpecificationTests.TextureCubeSpecCase;
+
+ /**
+ * @param {sglrGLContext.GLContext} webgl2Context
+ * @param {sglrReferenceContext.ReferenceContext} refContext
+ */
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype.verifyTexture =
+ function(
+ webgl2Context, refContext
+ ) {
+ /** @type {es3fFboTestUtil.TextureCubeShader} */
+ var shader = new es3fFboTestUtil.TextureCubeShader(
+ gluTextureUtil.getSamplerCubeType(this.m_texFormat),
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderIDgles = webgl2Context.createProgram(shader);
+ var shaderIDRef = refContext.createProgram(shader);
+
+ shader.setTexScaleBias(
+ this.m_texFormatInfo.lookupScale, this.m_texFormatInfo.lookupBias
+ );
+
+ // Set state.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var ctx = ndx ? refContext : webgl2Context;
+
+ this.m_context = ctx;
+
+ this.m_context.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER,
+ gl.NEAREST_MIPMAP_NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER,
+ gl.NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAX_LEVEL,
+ this.m_numLevels - 1
+ );
+ }
+
+ for (var levelNdx = 0; levelNdx < this.m_numLevels; levelNdx++) {
+ var levelSize = Math.max(1, this.m_size >> levelNdx);
+ var isOk = true;
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ /** @type {tcuSurface.Surface} */
+ var reference = new tcuSurface.Surface();
+ /** @type {tcuSurface.Surface} */
+ var result = new tcuSurface.Surface();
+
+ if (levelSize <= 2)
+ continue; // Fuzzy compare doesn't work for images this small.
+
+ shader.setFace(face);
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ /** @type {tcuSurface.Surface} */
+ var dst = ndx ? reference : result;
+ ctx = ndx ? refContext : webgl2Context;
+ var shaderID = ndx ? shaderIDRef : shaderIDgles;
+
+ this.m_context = ctx;
+ shader.setUniforms(ctx, shaderID);
+ this.renderTex(dst, shaderID, levelSize, levelSize);
+ }
+
+ var threshold = 0.02;
+ var faceStr = face.toString();
+ var levelStr = levelNdx.toString();
+ var name = 'Level' + levelStr;
+ var desc = 'Level ' + levelStr + ', face ' + faceStr;
+ var isFaceOk = tcuImageCompare.fuzzyCompare(
+ name, desc, reference.getAccess(), result.getAccess(),
+ threshold, levelNdx == 0 ?
+ tcuImageCompare.CompareLogMode.RESULT :
+ tcuImageCompare.CompareLogMode.ON_ERROR
+ );
+
+ if (!isFaceOk) {
+ testFailed('Image comparison failed');
+ return false;
+ }
+ }
+
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.Texture2DArraySpecCase = function(
+ name, desc, format, width, height, numLayers, numLevels
+ ) {
+ es3fTextureSpecificationTests.TextureSpecCase.call(
+ this, name, desc
+ );
+ this.m_texFormat = format;
+ this.m_texFormatInfo = tcuTextureUtil.getTextureFormatInfo(format);
+ this.m_width = width;
+ this.m_height = height;
+ this.m_numLayers = numLayers;
+ this.m_numLevels = numLevels;
+ };
+
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype =
+ Object.create(es3fTextureSpecificationTests.TextureSpecCase.prototype);
+
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype.constructor =
+ es3fTextureSpecificationTests.Texture2DArraySpecCase;
+
+ /**
+ * @param {sglrGLContext.GLContext} webgl2Context
+ * @param {sglrReferenceContext.ReferenceContext} refContext
+ */
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype.verifyTexture =
+ function(
+ webgl2Context, refContext
+ ) {
+ /** @type {es3fFboTestUtil.Texture2DArrayShader} */
+ var shader = new es3fFboTestUtil.Texture2DArrayShader(
+ gluTextureUtil.getSampler2DArrayType(this.m_texFormat),
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderIDgles = webgl2Context.createProgram(shader);
+ var shaderIDRef = refContext.createProgram(shader);
+
+ shader.setTexScaleBias(
+ this.m_texFormatInfo.lookupScale, this.m_texFormatInfo.lookupBias
+ );
+
+ // Set state.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var ctx = ndx ? refContext : webgl2Context;
+
+ this.m_context = ctx;
+
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER,
+ gl.NEAREST_MIPMAP_NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER,
+ gl.NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_R,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAX_LEVEL,
+ this.m_numLevels - 1
+ );
+ }
+
+ for (var layerNdx = 0; layerNdx < this.m_numLayers; layerNdx++) {
+ var layerOk = true;
+
+ shader.setLayer(layerNdx);
+ for (var levelNdx = 0; levelNdx < this.m_numLevels; levelNdx++) {
+ var levelW = Math.max(1, this.m_width >> levelNdx);
+ var levelH = Math.max(1, this.m_height >> levelNdx);
+
+ if (levelW == 1 || levelH == 1) {
+ // Rendering to texture of size x1 is problematic in referencerenderer
+ // due to its deviation from c++ code: crbug.com/613206
+ continue;
+ }
+ /** @type {tcuSurface.Surface} */
+ var reference = new tcuSurface.Surface();
+ /** @type {tcuSurface.Surface} */
+ var result = new tcuSurface.Surface();
+
+ var isOk = true;
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ /** @type {tcuSurface.Surface} */
+ var dst = ndx ? reference : result;
+ ctx = ndx ? refContext : webgl2Context;
+ var shaderID = ndx ? shaderIDRef : shaderIDgles;
+
+ this.m_context = ctx;
+ shader.setUniforms(ctx, shaderID);
+ this.renderTex(dst, shaderID, levelW, levelH);
+ }
+
+ var threshold =
+ es3fTextureSpecificationTests.computeCompareThreshold(
+ tcuPixelFormat.PixelFormatFromContext(gl), this.m_texFormat
+ );
+ var levelStr = levelNdx.toString();
+ var layerStr = layerNdx.toString();
+ var name = 'Layer' + layerStr + 'Level' + levelStr;
+ var desc = 'Layer ' + layerStr + ', Level ' + levelStr;
+ var depthOk = tcuImageCompare.intThresholdCompare(
+ name, desc, reference.getAccess(), result.getAccess(),
+ threshold, (levelNdx == 0 && layerNdx == 0) ?
+ tcuImageCompare.CompareLogMode.RESULT :
+ tcuImageCompare.CompareLogMode.ON_ERROR
+ );
+
+ if (!depthOk) {
+ testFailed('Image comparison failed');
+ return false;
+ }
+ }
+
+ }
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {tcuTexture.TextureFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.Texture3DSpecCase = function(
+ name, desc, format, width, height, depth, numLevels
+ ) {
+ es3fTextureSpecificationTests.TextureSpecCase.call(
+ this, name, desc
+ );
+ this.m_texFormat = format;
+ this.m_texFormatInfo = tcuTextureUtil.getTextureFormatInfo(format);
+ this.m_width = width;
+ this.m_height = height;
+ this.m_depth = depth;
+ this.m_numLevels = numLevels;
+ };
+
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype =
+ Object.create(es3fTextureSpecificationTests.TextureSpecCase.prototype);
+
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype.constructor =
+ es3fTextureSpecificationTests.Texture3DSpecCase;
+
+ /**
+ * @param {sglrGLContext.GLContext} webgl2Context
+ * @param {sglrReferenceContext.ReferenceContext} refContext
+ */
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype.verifyTexture =
+ function(
+ webgl2Context, refContext
+ ) {
+ /** @type {es3fFboTestUtil.Texture3DShader} */
+ var shader = new es3fFboTestUtil.Texture3DShader(
+ gluTextureUtil.getSampler3D(this.m_texFormat),
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderIDgles = webgl2Context.createProgram(shader);
+ var shaderIDRef = refContext.createProgram(shader);
+
+ shader.setTexScaleBias(
+ this.m_texFormatInfo.lookupScale, this.m_texFormatInfo.lookupBias
+ );
+
+ // Set state.
+ for (var ndx = 0; ndx < 2; ndx++) {
+ var ctx = ndx ? refContext : webgl2Context;
+
+ this.m_context = ctx;
+
+ this.m_context.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER,
+ gl.NEAREST_MIPMAP_NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER,
+ gl.NEAREST
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_WRAP_S,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_WRAP_T,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_WRAP_R,
+ gl.CLAMP_TO_EDGE
+ );
+ this.m_context.texParameteri(
+ gl.TEXTURE_3D, gl.TEXTURE_MAX_LEVEL,
+ this.m_numLevels - 1
+ );
+ }
+
+ for (var levelNdx = 0; levelNdx < this.m_numLevels; levelNdx++) {
+ var levelW = Math.max(1, this.m_width >> levelNdx);
+ var levelH = Math.max(1, this.m_height >> levelNdx);
+ var levelD = Math.max(1, this.m_depth >> levelNdx);
+ var levelOk = true;
+
+ if (levelW == 1 || levelH == 1) {
+ // Rendering to texture of size x1 is problematic in referencerenderer
+ // due to its deviation from c++ code: crbug.com/613206
+ continue;
+ }
+
+ for (var depth = 0; depth < levelD; depth++) {
+ /** @type {tcuSurface.Surface} */
+ var reference = new tcuSurface.Surface();
+ /** @type {tcuSurface.Surface} */
+ var result = new tcuSurface.Surface();
+
+ shader.setDepth((depth + 0.5) / levelD);
+
+ for (var ndx = 0; ndx < 2; ndx++) {
+ /** @type {tcuSurface.Surface} */
+ var dst = ndx ? reference : result;
+ ctx = ndx ? refContext : webgl2Context;
+ var shaderID = ndx ? shaderIDRef : shaderIDgles;
+
+ this.m_context = ctx;
+ shader.setUniforms(ctx, shaderID);
+ this.renderTex(dst, shaderID, levelW, levelH);
+ }
+
+ var threshold =
+ es3fTextureSpecificationTests.computeCompareThreshold(
+ tcuPixelFormat.PixelFormatFromContext(gl), this.m_texFormat
+ );
+ var levelStr = levelNdx.toString();
+ var sliceStr = depth.toString();
+ var name = 'Layer' + levelStr + 'Slice' + sliceStr;
+ var desc = 'Layer ' + levelStr + ', Slice ' + sliceStr;
+ var depthOk = tcuImageCompare.intThresholdCompare(
+ name, desc, reference.getAccess(), result.getAccess(),
+ threshold, (levelNdx == 0 && depth == 0) ?
+ tcuImageCompare.CompareLogMode.RESULT :
+ tcuImageCompare.CompareLogMode.ON_ERROR
+ );
+
+ if (!depthOk) {
+ testFailed('Image comparison failed');
+ return false;
+ }
+ }
+
+ }
+ return true;
+ };
+
+ // Basic TexImage2D() with 2D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.BasicTexImage2DCase = function(
+ name, desc, format, dataType, width, height
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height,
+ es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.BasicTexImage2DCase.prototype = Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.BasicTexImage2DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexImage2DCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @return {es3fTextureSpecificationTests.BasicTexImage2DCase}
+ */
+ es3fTextureSpecificationTests.newBasicTexImage2DCaseInternal = function(
+ name, desc, internalFormat, width, height
+ ) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.BasicTexImage2DCase(
+ name, desc, fmt.format, fmt.dataType, width, height
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.BasicTexImage2DCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, levelW, levelH, 0,
+ this.m_format, this.m_dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Basic TexImage2D() with cubemap usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.BasicTexImageCubeCase = function(
+ name, desc, format, dataType, size
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, deMath.logToFloor(size) + 1
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.BasicTexImageCubeCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicTexImageCubeCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexImageCubeCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @return {es3fTextureSpecificationTests.BasicTexImageCubeCase}
+ */
+ es3fTextureSpecificationTests.newBasicTexImageCubeCaseInternal = function(
+ name, desc, internalFormat, size
+ ) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.BasicTexImageCubeCase(
+ name, desc, fmt.format, fmt.dataType, size
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexImageCubeCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_size, this.m_size
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ levelData.setSize(levelSize, levelSize);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, this.m_internalFormat, levelSize, levelSize, 0,
+ this.m_format, this.m_dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ }
+ };
+
+ // Basic TexImage3D() with 2D array texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ */
+ es3fTextureSpecificationTests.BasicTexImage2DArrayCase = function(
+ name, desc, internalFormat, width, height, numLayers
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat), width, height,
+ numLayers, es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexImage2DArrayCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicTexImage2DArrayCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexImage2DArrayCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexImage2DArrayCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH, this.m_numLayers);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage3D(
+ gl.TEXTURE_2D_ARRAY, ndx, this.m_internalFormat, levelW, levelH,
+ this.m_numLayers, 0, transferFmt.format,
+ transferFmt.dataType, levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Basic TexImage3D() with 3D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+ es3fTextureSpecificationTests.BasicTexImage3DCase = function(
+ name, desc, internalFormat, width, height, depth
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat), width, height,
+ depth, es3fTextureSpecificationTests.maxLevelCount(
+ width, height, depth
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexImage3DCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicTexImage3DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexImage3DCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexImage3DCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var levelD = Math.max(1, this.m_depth >> ndx);
+
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH, levelD);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage3D(
+ gl.TEXTURE_3D, ndx, this.m_internalFormat, levelW, levelH,
+ levelD, 0, transferFmt.format, transferFmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Randomized 2D texture specification using TexImage2D
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.RandomOrderTexImage2DCase = function(
+ name, desc, format, dataType, width, height
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height,
+ es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.RandomOrderTexImage2DCase.prototype = Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ RandomOrderTexImage2DCase.prototype.constructor =
+ es3fTextureSpecificationTests.RandomOrderTexImage2DCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @return {es3fTextureSpecificationTests.RandomOrderTexImage2DCase}
+ */
+ es3fTextureSpecificationTests.newRandomOrderTexImage2DCaseInternal =
+ function(name, desc, internalFormat, width, height) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.RandomOrderTexImage2DCase(
+ name, desc, fmt.format, fmt.dataType, width, height
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ RandomOrderTexImage2DCase.prototype.createTexture = function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ var levels = [];
+ for (var i = 0; i < this.m_numLevels; i++)
+ levels[i] = i;
+ levels = rnd.shuffle(levels);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelNdx = levels[ndx];
+ var levelW = Math.max(1, this.m_width >> levelNdx);
+ var levelH = Math.max(1, this.m_height >> levelNdx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, levelNdx, this.m_internalFormat, levelW, levelH, 0,
+ this.m_format, this.m_dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Randomized cubemap texture specification using TexImage2D
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.RandomOrderTexImageCubeCase = function(
+ name, desc, format, dataType, size
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, deMath.logToFloor(size) + 1
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.RandomOrderTexImageCubeCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ RandomOrderTexImageCubeCase.prototype.constructor =
+ es3fTextureSpecificationTests.RandomOrderTexImageCubeCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @return {es3fTextureSpecificationTests.RandomOrderTexImageCubeCase}
+ */
+ es3fTextureSpecificationTests.newRandomOrderTexImageCubeCaseInternal =
+ function(name, desc, internalFormat, size) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.RandomOrderTexImageCubeCase(
+ name, desc, fmt.format, fmt.dataType, size
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ RandomOrderTexImageCubeCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_size, this.m_size
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // Level-face pairs.
+ var images = [];
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++)
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ images[ndx * 6 + face] = {ndx: ndx, face: face};
+ }
+
+ images = rnd.shuffle(images);
+
+ for (var ndx = 0; ndx < images.length; ndx++) {
+ var levelNdx = images[ndx].ndx;
+ /** @type {framework.common.tcuTexture.CubeFace} */
+ var face = images[ndx].face;
+ var levelSize = Math.max(1, this.m_size >> levelNdx);
+
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelSize, levelSize);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ levelNdx, this.m_internalFormat, levelSize, levelSize, 0,
+ this.m_format, this.m_dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexImage2D() unpack alignment case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLevels
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexImage2DAlignCase = function(
+ name, desc, format, dataType, width, height, numLevels, alignment
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height, numLevels
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexImage2DAlignCase.prototype = Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DAlignCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DAlignCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLevels
+ * @param {number} alignment
+ * @return {es3fTextureSpecificationTests.TexImage2DAlignCase}
+ */
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal = function(
+ name, desc, internalFormat, width, height, numLevels, alignment
+ ) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.TexImage2DAlignCase(
+ name, desc, fmt.format, fmt.dataType,
+ width, height, numLevels, alignment
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.TexImage2DAlignCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var colorA = deMath.add(
+ deMath.multiply(
+ [1.0, 0.0, 0.0, 1.0],
+ deMath.subtract(
+ this.m_texFormatInfo.valueMax,
+ this.m_texFormatInfo.valueMin
+ )
+ ), this.m_texFormatInfo.valueMin
+ );
+ var colorB = deMath.add(
+ deMath.multiply(
+ [0.0, 1.0, 0.0, 1.0],
+ deMath.subtract(
+ this.m_texFormatInfo.valueMax,
+ this.m_texFormatInfo.valueMin
+ )
+ ), this.m_texFormatInfo.valueMin
+ );
+
+ var rowPitch = deMath.deAlign32(
+ levelW * this.m_texFormat.getPixelSize(), this.m_alignment
+ );
+ var cellSize = Math.max(1, Math.min(levelW >> 2, levelH >> 2));
+ data = new ArrayBuffer(rowPitch * levelH);
+ var access = new tcuTexture.PixelBufferAccess({format: this.m_texFormat, width: levelW,
+ height: levelH, rowPitch: rowPitch, data: data}
+ );
+ tcuTextureUtil.fillWithGrid(access, cellSize, colorA, colorB
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, levelW, levelH, 0,
+ this.m_format, this.m_dataType,
+ access.getDataPtr()
+ );
+ }
+ };
+
+ // TexImageCube unpack alignment case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ * @param {number} numLevels
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexImageCubeAlignCase = function(
+ name, desc, format, dataType, size, numLevels, alignment
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, numLevels
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexImageCubeAlignCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImageCubeAlignCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImageCubeAlignCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @param {number} numLevels
+ * @param {number} alignment
+ * @return {es3fTextureSpecificationTests.TexImageCubeAlignCase}
+ */
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal =
+ function(name, desc, internalFormat, size, numLevels, alignment) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.TexImageCubeAlignCase(
+ name, desc, fmt.format, fmt.dataType, size, numLevels, alignment
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImageCubeAlignCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ /** @type {ArrayBuffer} */ var data;
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+ var cellSize = Math.max(1, levelSize >> 2);
+ var rowPitch = deMath.deAlign32(
+ this.m_texFormat.getPixelSize() * levelSize, this.m_alignment
+ );
+ var colorA = deMath.add(deMath.multiply(
+ [1.0, 0.0, 0.0, 1.0], deMath.subtract(
+ this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin
+ )), this.m_texFormatInfo.valueMin
+ );
+ var colorB = deMath.add(deMath.multiply(
+ [0.0, 1.0, 0.0, 1.0], deMath.subtract(
+ this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin
+ )), this.m_texFormatInfo.valueMin
+ );
+
+ data = new ArrayBuffer(rowPitch * levelSize);
+ var access = new tcuTexture.PixelBufferAccess({format: this.m_texFormat, width: levelSize,
+ height: levelSize, rowPitch: rowPitch, data: data}
+ );
+ tcuTextureUtil.fillWithGrid(access, cellSize, colorA, colorB
+ );
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, this.m_internalFormat, levelSize, levelSize, 0,
+ this.m_format, this.m_dataType,
+ access.getDataPtr()
+ );
+ }
+ }
+ };
+
+ // TexImage2D() unpack parameters case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexImage2DParamsCase = function(
+ name, desc, internalFormat, width, height, rowLength, skipRows,
+ skipPixels, alignment
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat),
+ width, height, 1
+ );
+ this.m_internalFormat = internalFormat;
+ this.m_rowLength = rowLength;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexImage2DParamsCase.prototype =
+ Object.create(es3fTextureSpecificationTests.Texture2DSpecCase.prototype);
+
+ es3fTextureSpecificationTests.TexImage2DParamsCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DParamsCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.TexImage2DParamsCase.prototype.createTexture =
+ function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_width;
+ var rowPitch = deMath.deAlign32(rowLength * pixelSize, this.m_alignment);
+ var height = this.m_height + this.m_skipRows;
+ var tex = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels different to 1',
+ false, true
+ );
+
+ // Fill data with grid.
+ data = new ArrayBuffer(rowPitch * height + this.m_skipPixels * pixelSize);
+
+ var cScale = deMath.subtract(
+ this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin
+ );
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply(
+ [1.0, 0.0, 0.0, 1.0], cScale
+ ), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply(
+ [0.0, 1.0, 0.0, 1.0], cScale
+ ), cBias
+ );
+
+ var accessWithOffset = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: rowPitch,
+ data: data,
+ offset: this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize
+ });
+ tcuTextureUtil.fillWithGrid(accessWithOffset, 4, colorA, colorB
+ );
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: rowPitch,
+ data: data,
+ });
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, 0, this.m_internalFormat,
+ this.m_width, this.m_height, 0,
+ transferFmt.format, transferFmt.dataType, access.getDataPtr()
+ );
+ };
+
+ // TexImage3D() unpack parameters case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} imageHeight
+ * @param {number} rowLength
+ * @param {number} skipImages
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexImage3DParamsCase = function(
+ name, desc, internalFormat, width, height, depth, imageHeight,
+ rowLength, skipImages, skipRows, skipPixels, alignment
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat),
+ width, height, depth, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_imageHeight = imageHeight;
+ this.m_rowLength = rowLength;
+ this.m_skipImages = skipImages;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexImage3DParamsCase.prototype =
+ Object.create(es3fTextureSpecificationTests.Texture3DSpecCase.prototype);
+
+ es3fTextureSpecificationTests.TexImage3DParamsCase.prototype.constructor =
+ es3fTextureSpecificationTests.Texture3DSpecCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.TexImage3DParamsCase.prototype.createTexture =
+ function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_width;
+ var rowPitch = deMath.deAlign32(rowLength * pixelSize, this.m_alignment);
+ var imageHeight = this.m_imageHeight > 0 ?
+ this.m_imageHeight : this.m_height;
+ var slicePitch = imageHeight * rowPitch;
+
+ var tex = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels different to 1',
+ false, true
+ );
+
+ // Fill data with grid.
+ data = new ArrayBuffer(slicePitch * (this.m_depth + this.m_skipImages) +
+ this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize);
+
+ var cScale = deMath.subtract(
+ this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin
+ );
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply(
+ [1.0, 0.0, 0.0, 1.0], cScale
+ ), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply(
+ [0.0, 1.0, 0.0, 1.0], cScale
+ ), cBias
+ );
+
+ var accessWithOffset = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: this.m_skipImages * slicePitch + this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize
+ });
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithGrid(
+ accessWithOffset, 4, colorA, colorB
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, this.m_imageHeight);
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_IMAGES, this.m_skipImages);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+ this.m_context.texImage3D(
+ gl.TEXTURE_3D, 0, this.m_internalFormat,
+ this.m_width, this.m_height, this.m_depth, 0,
+ transferFmt.format, transferFmt.dataType, access.getDataPtr()
+ );
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.BasicTexSubImage2DCase = function(
+ name, desc, format, dataType, width, height
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height, es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_format = format;
+ this.m_internalFormat = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.BasicTexSubImage2DCase.prototype =
+ Object.create(es3fTextureSpecificationTests.Texture2DSpecCase.prototype);
+
+ es3fTextureSpecificationTests.BasicTexSubImage2DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexSubImage2DCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @return {es3fTextureSpecificationTests.BasicTexSubImage2DCase}
+ */
+ es3fTextureSpecificationTests.newBasicTexSubImage2DCaseInternal =
+ function(name, desc, internalFormat, width, height) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.BasicTexSubImage2DCase(
+ name, desc, fmt.format, fmt.dataType, width, height
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ */
+ es3fTextureSpecificationTests.
+ BasicTexSubImage2DCase.prototype.createTexture = function() {
+ var tex = null;
+ var data = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ data.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ data.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, levelW, levelH, 0,
+ this.m_format, this.m_dataType,
+ data.getAccess().getDataPtr()
+ );
+ }
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ var w = rnd.getInt(1, levelW);
+ var h = rnd.getInt(1, levelH);
+ var x = rnd.getInt(0, levelW - w);
+ var y = rnd.getInt(0, levelH - h);
+
+ var colorA = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var colorB = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var cellSize = rnd.getInt(2, 16);
+
+ data.setSize(w, h);
+ tcuTextureUtil.fillWithGrid(
+ data.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, ndx, x, y, w, h, this.m_format, this.m_dataType,
+ data.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.BasicTexSubImageCubeCase = function(
+ name, desc, format, dataType, size
+ ) {
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, deMath.logToFloor(size) + 1
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.BasicTexSubImageCubeCase.prototype =
+ Object.create(es3fTextureSpecificationTests.TextureCubeSpecCase.prototype);
+
+ es3fTextureSpecificationTests.
+ BasicTexSubImageCubeCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexSubImageCubeCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.newBasicTexSubImageCubeCaseInternal =
+ function(name, desc, internalFormat, size) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase =
+ new es3fTextureSpecificationTests.BasicTexSubImageCubeCase(
+ name, desc, fmt.format, fmt.dataType,
+ size);
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexSubImageCubeCase.prototype.createTexture = function() {
+ var tex = null;
+ var data = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_size, this.m_size
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+ data.setSize(levelSize, levelSize);
+
+ for (var face = /** @type {tcuTexture.CubeFace} */ (0);
+ face < es3fTextureSpecificationTests.s_cubeMapFaces.length;
+ face++) {
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ tcuTextureUtil.fillWithComponentGradients(
+ data.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face], ndx,
+ this.m_internalFormat, levelSize, levelSize, 0,
+ this.m_format, this.m_dataType,
+ data.getAccess().getDataPtr()
+ );
+ }
+ }
+
+ // Re-specify parts of each face and level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+
+ var w = rnd.getInt(1, levelSize);
+ var h = rnd.getInt(1, levelSize);
+ var x = rnd.getInt(0, levelSize - w);
+ var y = rnd.getInt(0, levelSize - h);
+
+ var colorA = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var colorB = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var cellSize = rnd.getInt(2, 16);
+
+ data.setSize(w, h);
+ tcuTextureUtil.fillWithGrid(
+ data.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texSubImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, x, y, w, h, this.m_format,
+ this.m_dataType, data.getAccess().getDataPtr()
+ );
+ }
+ }
+ };
+
+ // TexSubImage2D() unpack parameters case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexSubImage2DParamsCase = function(
+ name, desc, internalFormat, width, height, subX, subY, subW, subH,
+ rowLength, skipRows, skipPixels, alignment
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat),
+ width, height, 1
+ );
+ this.m_internalFormat = internalFormat;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_rowLength = rowLength;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DParamsCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DParamsCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DParamsCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DParamsCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var tex = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels different to 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+
+ // First fill texture with gradient.
+ data = new ArrayBuffer(
+ deMath.deAlign32(this.m_width * pixelSize, 4) * this.m_height
+ );
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: deMath.deAlign32(this.m_width * pixelSize, 4),
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, this.m_texFormatInfo.valueMin, this.m_texFormatInfo.valueMax
+ );
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, 0, this.m_internalFormat, this.m_width,
+ this.m_height, 0, transferFmt.format, transferFmt.dataType,
+ access.getDataPtr()
+ );
+
+ // Fill data with grid.
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_subW;
+ var rowPitch = deMath.deAlign32(rowLength * pixelSize, this.m_alignment);
+ var height = this.m_subH + this.m_skipRows;
+ var cScale = deMath.subtract(
+ this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin
+ );
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply(
+ [1.0, 0.0, 0.0, 1.0], cScale
+ ), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply(
+ [0.0, 1.0, 0.0, 1.0], cScale
+ ), cBias
+ );
+
+ data = new ArrayBuffer(rowPitch * height + this.m_skipPixels * pixelSize);
+ tcuTextureUtil.fillWithGrid(
+ new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: data,
+ offset: this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize
+ }) ,
+ 4, colorA, colorB
+ );
+
+ access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: data
+ });
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, 0, this.m_subX, this.m_subY,
+ this.m_subW, this.m_subH,
+ transferFmt.format, transferFmt.dataType,
+ access.getDataPtr()
+ );
+ };
+
+ // Basic TexSubImage3D() with 3D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+ es3fTextureSpecificationTests.BasicTexSubImage3DCase = function(
+ name, desc, internalFormat, width, height, depth
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat),
+ width, height, depth, es3fTextureSpecificationTests.maxLevelCount(
+ width, height, depth
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexSubImage3DCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.BasicTexSubImage3DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexSubImage3DCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexSubImage3DCase.prototype.createTexture = function() {
+ var tex = null;
+ var data = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // First specify full texture.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var levelD = Math.max(1, this.m_depth >> ndx);
+
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ data.setSize(levelW, levelH, levelD);
+ tcuTextureUtil.fillWithComponentGradients(
+ data.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage3D(
+ gl.TEXTURE_3D, ndx, this.m_internalFormat, levelW, levelH,
+ levelD, 0, transferFmt.format, transferFmt.dataType,
+ data.getAccess().getDataPtr()
+ );
+ }
+
+ // Re-specify parts of each level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var levelD = Math.max(1, this.m_depth >> ndx);
+
+ var w = rnd.getInt(1, levelW);
+ var h = rnd.getInt(1, levelH);
+ var d = rnd.getInt(1, levelD);
+ var x = rnd.getInt(0, levelW - w);
+ var y = rnd.getInt(0, levelH - h);
+ var z = rnd.getInt(0, levelD - d);
+
+ var colorA = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var colorB = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var cellSize = rnd.getInt(2, 16);
+
+ data.setSize(w, h, d);
+ tcuTextureUtil.fillWithGrid(
+ data.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texSubImage3D(
+ gl.TEXTURE_3D, ndx, x, y, z, w, h, d,
+ transferFmt.format, transferFmt.dataType,
+ data.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexSubImage2D() to texture initialized with empty data
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.TexSubImage2DEmptyTexCase = function(
+ name, desc, format, dataType, width, height
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height, es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_format = format;
+ this.m_internalFormat = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DEmptyTexCase.prototype =
+ Object.create(es3fTextureSpecificationTests.Texture2DSpecCase.prototype);
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DEmptyTexCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DEmptyTexCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.newTexSubImage2DEmptyTexCaseInternal =
+ function(name, desc, internalFormat, width, height) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase =
+ new es3fTextureSpecificationTests.TexSubImage2DEmptyTexCase(
+ name, desc, fmt.format, fmt.dataType, width, height
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DEmptyTexCase.prototype.createTexture = function() {
+ var tex = null;
+ var data = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // First allocate storage for each level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, levelW, levelH, 0,
+ this.m_format, this.m_dataType,
+ null
+ );
+ }
+
+ // Specify pixel data to all levels using glTexSubImage2D()
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ data.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ data.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, ndx, 0, 0, levelW, levelH,
+ this.m_format, this.m_dataType,
+ data.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexSubImage2D() to empty cubemap texture
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.TexSubImageCubeEmptyTexCase = function(
+ name, desc, format, dataType, size
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, deMath.logToFloor(size) + 1
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.TexSubImageCubeEmptyTexCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImageCubeEmptyTexCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImageCubeEmptyTexCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @return {es3fTextureSpecificationTests.TexSubImageCubeEmptyTexCase}
+ */
+ es3fTextureSpecificationTests.newTexSubImageCubeEmptyTexCaseInternal =
+ function(name, desc, internalFormat, size) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase =
+ new es3fTextureSpecificationTests.TexSubImageCubeEmptyTexCase(
+ name, desc, fmt.format, fmt.dataType, size
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImageCubeEmptyTexCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ var data = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_size, this.m_size
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // Specify storage for each level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, this.m_internalFormat, levelSize, levelSize, 0,
+ this.m_format, this.m_dataType,
+ null
+ );
+ }
+ }
+
+ // Specify data using glTexSubImage2D()
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ data.setSize(levelSize, levelSize);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ tcuTextureUtil.fillWithComponentGradients(
+ data.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texSubImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, 0, 0, levelSize, levelSize, this.m_format,
+ this.m_dataType, data.getAccess().getDataPtr()
+ );
+ }
+ }
+ };
+
+ // TexSubImage2D() unpack alignment with 2D texture
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexSubImage2DAlignCase = function(
+ name, desc, format, dataType, width, height, subX, subY, subW, subH,
+ alignment
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height, 1
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DAlignCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DAlignCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DAlignCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} alignment
+ * @return {es3fTextureSpecificationTests.TexSubImage2DAlignCase}
+ */
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal = function(
+ name, desc, internalFormat, width, height, subX, subY, subW, subH,
+ alignment
+ ) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase = new es3fTextureSpecificationTests.TexSubImage2DAlignCase(
+ name, desc, fmt.format, fmt.dataType,
+ width, height, subX, subY, subW, subH, alignment
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DAlignCase.prototype.createTexture = function() {
+ var tex = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+
+ // Specify base level.
+ data = new ArrayBuffer(this.m_texFormat.getPixelSize() *
+ this.m_width * this.m_height
+ );
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, [0, 0, 0, 0], [1, 1, 1, 1]);
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+ this.m_context.texImage2D(gl.TEXTURE_2D, 0, this.m_internalFormat,
+ this.m_width, this.m_height, 0, this.m_format, this.m_dataType,
+ access.getDataPtr()
+ );
+
+ // Re-specify subrectangle.
+ var rowPitch = deMath.deAlign32(
+ this.m_texFormat.getPixelSize() * this.m_subW, this.m_alignment
+ );
+ data = new ArrayBuffer(rowPitch * this.m_subH);
+ access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithGrid(access, 4, [1, 0, 0, 1], [0, 1, 0, 1]
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, 0, this.m_subX, this.m_subY, this.m_subW,
+ this.m_subH, this.m_format, this.m_dataType, access.getDataPtr()
+ );
+ };
+
+ // TexSubImage2D() unpack alignment with cubemap texture
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexSubImageCubeAlignCase = function(
+ name, desc, format, dataType, size, subX, subY, subW, subH, alignment
+ ) {
+ // Unsized internal format.
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, 1
+ );
+
+ this.m_internalFormat = format;
+ this.m_format = format;
+ this.m_dataType = dataType;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexSubImageCubeAlignCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImageCubeAlignCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImageCubeAlignCase;
+
+ /**
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} alignment
+ * @return {es3fTextureSpecificationTests.TexSubImageCubeAlignCase}
+ */
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal =
+ function(
+ name, desc, internalFormat, size,
+ subX, subY, subW, subH, alignment
+ ) {
+ // Sized internal format.
+ var fmt = gluTextureUtil.getTransferFormat(
+ gluTextureUtil.mapGLInternalFormat(internalFormat)
+ );
+ var testcase =
+ new es3fTextureSpecificationTests.TexSubImageCubeAlignCase(
+ name, desc, fmt.format, fmt.dataType, size,
+ subX, subY, subW, subH, alignment
+ );
+ testcase.m_internalFormat = internalFormat;
+ return testcase;
+ };
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImageCubeAlignCase.prototype.createTexture =
+ function() {
+ var tex = null;
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+
+ var data = new ArrayBuffer(this.m_texFormat.getPixelSize() * this.m_size * this.m_size);
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_size,
+ height: this.m_size,
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, [0, 0, 0, 0], [1, 1, 1, 1]
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ 0, this.m_internalFormat, this.m_size, this.m_size, 0,
+ this.m_format, this.m_dataType,
+ access.getDataPtr()
+ );
+ }
+
+ // Re-specify subrectangle.
+ var rowPitch = deMath.deAlign32(
+ this.m_texFormat.getPixelSize() * this.m_subW, this.m_alignment
+ );
+ data = new ArrayBuffer(rowPitch * this.m_subH);
+ access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithGrid(access, 4, [1, 0, 0, 1], [0, 1, 0, 1]
+ );
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ this.m_context.texSubImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ 0, this.m_subX, this.m_subY, this.m_subW, this.m_subH,
+ this.m_format, this.m_dataType, access.getDataPtr()
+ );
+ }
+ };
+
+ // TexSubImage3D() unpack parameters case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} subX ,
+ * @param {number} subY ,
+ * @param {number} subZ ,
+ * @param {number} subW ,
+ * @param {number} subH ,
+ * @param {number} subD ,
+ * @param {number} imageHeight ,
+ * @param {number} rowLength ,
+ * @param {number} skipImages ,
+ * @param {number} skipRows ,
+ * @param {number} skipPixels ,
+ * @param {number} alignment
+ */
+ es3fTextureSpecificationTests.TexSubImage3DParamsCase = function(
+ name, desc, internalFormat, width, height, depth,
+ subX, subY, subZ, subW, subH, subD,
+ imageHeight, rowLength, skipImages, skipRows, skipPixels, alignment
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc,
+ gluTextureUtil.mapGLInternalFormat(internalFormat),
+ width, height, depth, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subZ = subZ;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_subD = subD;
+ this.m_imageHeight = imageHeight;
+ this.m_rowLength = rowLength;
+ this.m_skipImages = skipImages;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage3DParamsCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage3DParamsCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage3DParamsCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage3DParamsCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var tex = null;
+ var rowPitch = deMath.deAlign32(pixelSize * this.m_width, 4);
+ var slicePitch = rowPitch * this.m_height;
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Numbel of levels different than 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+
+ // Fill with gradient.
+
+ var data = new ArrayBuffer(slicePitch * this.m_depth);
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, this.m_texFormatInfo.valueMin, this.m_texFormatInfo.valueMax);
+
+ this.m_context.texImage3D(
+ gl.TEXTURE_3D, 0, this.m_internalFormat, this.m_width,
+ this.m_height, this.m_depth, 0, transferFmt.format,
+ transferFmt.dataType, access.getDataPtr()
+ );
+
+ // Fill data with grid.
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_subW;
+ rowPitch = deMath.deAlign32(rowLength * pixelSize, this.m_alignment);
+ var imageHeight = this.m_imageHeight > 0 ? this.m_imageHeight : this.m_subH;
+ slicePitch = imageHeight * rowPitch;
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ data = new ArrayBuffer(slicePitch * (this.m_depth + this.m_skipImages) +
+ this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize);
+ var accessWithOffset = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ depth: this.m_subD,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: this.m_skipImages * slicePitch + this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize
+ });
+ access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ depth: this.m_subD,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithGrid(accessWithOffset, 4, colorA, colorB);
+
+ this.m_context.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, this.m_imageHeight);
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_IMAGES, this.m_skipImages);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+ this.m_context.texSubImage3D(
+ gl.TEXTURE_3D, 0, this.m_subX, this.m_subY, this.m_subZ,
+ this.m_subW, this.m_subH, this.m_subD,
+ transferFmt.format, transferFmt.dataType, access.getDataPtr()
+ );
+ };
+
+ // Basic CopyTexImage2D() with 2D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.BasicCopyTexImage2DCase = function(
+ name, desc, internalFormat, width, height
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ internalFormat, gl.UNSIGNED_BYTE
+ ), width, height, es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicCopyTexImage2DCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicCopyTexImage2DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicCopyTexImage2DCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicCopyTexImage2DCase.prototype.createTexture = function() {
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ var targetHasRGB = pixelFormat.redBits > 0 &&
+ pixelFormat.greenBits > 0 &&
+ pixelFormat.blueBits > 0;
+ var targetHasAlpha = pixelFormat.alphaBits > 0;
+ var fmt = es3fTextureSpecificationTests.mapGLUnsizedInternalFormat(
+ this.m_internalFormat
+ );
+ var texHasRGB = fmt.order != tcuTexture.ChannelOrder.A;
+ var texHasAlpha = fmt.order == tcuTexture.ChannelOrder.RGBA ||
+ fmt.order == tcuTexture.ChannelOrder.LA ||
+ fmt.order == tcuTexture.ChannelOrder.A;
+ var tex = null;
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var shader = new es3fFboTestUtil.GradientShader(
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderID = this.m_context.createProgram(shader);
+
+ if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
+ throw new Error(
+ 'Copying from current framebuffer is not supported'
+ );
+
+ // Fill render target with gradient.
+ shader.setGradient(
+ this.m_context, shaderID, [0, 0, 0, 0], [1, 1, 1, 1]
+ );
+ rrUtil.drawQuad(
+ this.m_context, shaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var x = rnd.getInt(0, this.m_width - levelW);
+ var y = rnd.getInt(0, this.m_height - levelH);
+
+ this.m_context.copyTexImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, x, y,
+ levelW, levelH, 0
+ );
+ }
+ };
+
+ // Basic CopyTexImage2D() with cubemap usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.BasicCopyTexImageCubeCase = function(
+ name, desc, internalFormat, size
+ ) {
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ internalFormat, gl.UNSIGNED_BYTE
+ ), size, deMath.logToFloor(size) + 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicCopyTexImageCubeCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicCopyTexImageCubeCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicCopyTexImageCubeCase;
+
+ es3fTextureSpecificationTests.
+ BasicCopyTexImageCubeCase.prototype.createTexture = function() {
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ var targetHasRGB = pixelFormat.redBits > 0 &&
+ pixelFormat.greenBits > 0 &&
+ pixelFormat.blueBits > 0;
+ var targetHasAlpha = pixelFormat.alphaBits > 0;
+ var fmt = es3fTextureSpecificationTests.mapGLUnsizedInternalFormat(
+ this.m_internalFormat
+ );
+ var texHasRGB = fmt.order != tcuTexture.ChannelOrder.A;
+ var texHasAlpha = fmt.order == tcuTexture.ChannelOrder.RGBA ||
+ fmt.order == tcuTexture.ChannelOrder.LA ||
+ fmt.order == tcuTexture.ChannelOrder.A;
+ var tex = null;
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var shader = new es3fFboTestUtil.GradientShader(
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderID = this.m_context.createProgram(shader);
+
+ if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
+ throw new Error(
+ 'Copying from current framebuffer is not supported'
+ );
+
+ // Fill render target with gradient.
+ shader.setGradient(
+ this.m_context, shaderID, [0, 0, 0, 0], [1, 1, 1, 1]
+ );
+ rrUtil.drawQuad(
+ this.m_context, shaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var x = rnd.getInt(0, this.m_size - levelSize);
+ var y = rnd.getInt(0, this.m_size - levelSize);
+
+ this.m_context.copyTexImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face], ndx,
+ this.m_internalFormat, x, y, levelSize, levelSize, 0
+ );
+ }
+ }
+ };
+
+ // Basic CopyTexSubImage2D() with 2D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase = function(
+ name, desc, format, dataType, width, height
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), width, height, es3fTextureSpecificationTests.maxLevelCount(
+ width, height
+ )
+ );
+
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicCopyTexSubImage2DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicCopyTexSubImage2DCase.prototype.createTexture = function() {
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ var targetHasRGB = pixelFormat.redBits > 0 &&
+ pixelFormat.greenBits > 0 &&
+ pixelFormat.blueBits > 0;
+ var targetHasAlpha = pixelFormat.alphaBits > 0;
+ var fmt = gluTextureUtil.mapGLTransferFormat(
+ this.m_format, this.m_dataType
+ );
+ var texHasRGB = fmt.order != tcuTexture.ChannelOrder.A;
+ var texHasAlpha = fmt.order == tcuTexture.ChannelOrder.RGBA ||
+ fmt.order == tcuTexture.ChannelOrder.LA ||
+ fmt.order == tcuTexture.ChannelOrder.A;
+ var tex = null;
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var shader = new es3fFboTestUtil.GradientShader(
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderID = this.m_context.createProgram(shader);
+
+ if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
+ throw new Error(
+ 'Copying from current framebuffer is not supported'
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // First specify full texture.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ var colorA = es3fTextureSpecificationTests.randomVector(
+ rnd, [0, 0, 0, 0], [1, 1, 1, 1], 4
+ );
+ var colorB = es3fTextureSpecificationTests.randomVector(
+ rnd, [0, 0, 0, 0], [1, 1, 1, 1], 4
+ );
+ var cellSize = rnd.getInt(2, 16);
+
+ var data = new tcuTexture.TextureLevel(fmt, levelW, levelH);
+ tcuTextureUtil.fillWithGrid(
+ data.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_format, levelW, levelH, 0, this.m_format, this.m_dataType, data.getAccess().getDataPtr()
+ );
+ }
+
+ // Fill render target with gradient.
+ shader.setGradient(
+ this.m_context, shaderID, [0, 0, 0, 0], [1, 1, 1, 1]
+ );
+ rrUtil.drawQuad(
+ this.m_context, shaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ // Re-specify parts of each level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ var w = rnd.getInt(1, levelW);
+ var h = rnd.getInt(1, levelH);
+ var xo = rnd.getInt(0, levelW - w);
+ var yo = rnd.getInt(0, levelH - h);
+
+ var x = rnd.getInt(0, this.m_width - w);
+ var y = rnd.getInt(0, this.m_height - h);
+
+ this.m_context.copyTexSubImage2D(
+ gl.TEXTURE_2D, ndx, xo, yo, x, y, w, h
+ );
+ }
+ };
+
+ // Basic CopyTexSubImage2D() with cubemap usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} size
+ */
+ es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase = function(
+ name, desc, format, dataType, size
+ ) {
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLTransferFormat(
+ format, dataType
+ ), size, deMath.logToFloor(size) + 1
+ );
+
+ this.m_format = format;
+ this.m_dataType = dataType;
+ };
+
+ es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicCopyTexSubImageCubeCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase;
+
+ es3fTextureSpecificationTests.
+ BasicCopyTexSubImageCubeCase.prototype.createTexture = function() {
+ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl);
+ var targetHasRGB = pixelFormat.redBits > 0 &&
+ pixelFormat.greenBits > 0 &&
+ pixelFormat.blueBits > 0;
+ var targetHasAlpha = pixelFormat.alphaBits > 0;
+ var fmt = gluTextureUtil.mapGLTransferFormat(this.m_format, this.m_dataType);
+ var texHasRGB = fmt.order != tcuTexture.ChannelOrder.A;
+ var texHasAlpha = fmt.order == tcuTexture.ChannelOrder.RGBA ||
+ fmt.order == tcuTexture.ChannelOrder.LA ||
+ fmt.order == tcuTexture.ChannelOrder.A;
+ var tex = null;
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ /** @type {es3fFboTestUtil.GradientShader} */
+ var shader = new es3fFboTestUtil.GradientShader(
+ gluShaderUtil.DataType.FLOAT_VEC4
+ );
+ var shaderID = this.m_context.createProgram(shader);
+
+ if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
+ throw new Error(
+ 'Copying from current framebuffer is not supported'
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ var data = new tcuTexture.TextureLevel(fmt);
+
+ // First specify full texture.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ data.setSize(levelSize, levelSize);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var colorA = es3fTextureSpecificationTests.randomVector(
+ rnd, [0, 0, 0, 0], [1, 1, 1, 1], 4
+ );
+ var colorB = es3fTextureSpecificationTests.randomVector(
+ rnd, [0, 0, 0, 0], [1, 1, 1, 1], 4
+ );
+ var cellSize = rnd.getInt(2, 16);
+
+ tcuTextureUtil.fillWithGrid(
+ data.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, this.m_format, levelSize, levelSize, 0, this.m_format,
+ this.m_dataType, data.getAccess().getDataPtr()
+ );
+ }
+ }
+
+ // Fill render target with gradient.
+ shader.setGradient(
+ this.m_context, shaderID, [0, 0, 0, 0], [1, 1, 1, 1]
+ );
+ rrUtil.drawQuad(
+ this.m_context, shaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
+ );
+
+ // Re-specify parts of each face and level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ for (var f in es3fTextureSpecificationTests.s_cubeMapFaces) {
+ var w = rnd.getInt(1, levelSize);
+ var h = rnd.getInt(1, levelSize);
+ var xo = rnd.getInt(0, levelSize - w);
+ var yo = rnd.getInt(0, levelSize - h);
+
+ var x = rnd.getInt(0, this.m_size - w);
+ var y = rnd.getInt(0, this.m_size - h);
+
+ this.m_context.copyTexSubImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[f],
+ ndx, xo, yo, x, y, w, h
+ );
+ }
+ }
+ };
+
+ // Basic glTexStorage2D() with 2D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.BasicTexStorage2DCase = function(
+ name, desc, internalFormat, width, height, numLevels
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, numLevels
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexStorage2DCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.BasicTexStorage2DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexStorage2DCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexStorage2DCase.prototype.createTexture = function() {
+ var fmt = gluTextureUtil.mapGLInternalFormat(this.m_internalFormat);
+ var transferFmt = gluTextureUtil.getTransferFormat(fmt);
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ fmt, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.texStorage2D(
+ gl.TEXTURE_2D, this.m_numLevels, this.m_internalFormat,
+ this.m_width, this.m_height
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, ndx, 0, 0, levelW, levelH,
+ transferFmt.format, transferFmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Basic glTexStorage2D() with cubemap usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.BasicTexStorageCubeCase = function(
+ name, desc, internalFormat, size, numLevels
+ ) {
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), size, numLevels
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexStorageCubeCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.BasicTexStorageCubeCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexStorageCubeCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.BasicTexStorageCubeCase.prototype.createTexture = function() {
+ var fmt = gluTextureUtil.mapGLInternalFormat(this.m_internalFormat);
+ var transferFmt = gluTextureUtil.getTransferFormat(fmt);
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ fmt, this.m_size, this.m_size
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.texStorage2D(
+ gl.TEXTURE_CUBE_MAP, this.m_numLevels, this.m_internalFormat,
+ this.m_size, this.m_size
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelSize = Math.max(1, this.m_size >> ndx);
+
+ levelData.setSize(levelSize, levelSize);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texSubImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face],
+ ndx, 0, 0, levelSize, levelSize,
+ transferFmt.format, transferFmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ }
+ };
+
+ // Basic glTexStorage3D() with 2D array texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} numLayers
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.BasicTexStorage2DArrayCase = function(
+ name, desc, internalFormat, width, height, numLayers, numLevels
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, numLayers, numLevels
+ );
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexStorage2DArrayCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicTexStorage2DArrayCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexStorage2DArrayCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.BasicTexStorage2DArrayCase.prototype.createTexture = function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ this.m_context.texStorage3D(
+ gl.TEXTURE_2D_ARRAY, this.m_numLevels, this.m_internalFormat,
+ this.m_width, this.m_height, this.m_numLayers
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH, this.m_numLayers);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texSubImage3D(
+ gl.TEXTURE_2D_ARRAY, ndx, 0, 0, 0, levelW, levelH,
+ this.m_numLayers, transferFmt.format, transferFmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Basic TexStorage3D() with 3D texture usage
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} numLevels
+ */
+ es3fTextureSpecificationTests.BasicTexStorage3DCase = function(
+ name, desc, internalFormat, width, height, depth, numLevels
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, depth, numLevels
+ );
+
+ this.m_internalFormat = internalFormat;
+ };
+
+ es3fTextureSpecificationTests.BasicTexStorage3DCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ BasicTexStorage3DCase.prototype.constructor =
+ es3fTextureSpecificationTests.BasicTexStorage3DCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ BasicTexStorage3DCase.prototype.createTexture = function() {
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+ this.m_context.texStorage3D(
+ gl.TEXTURE_3D, this.m_numLevels, this.m_internalFormat,
+ this.m_width, this.m_height, this.m_depth
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var levelD = Math.max(1, this.m_depth >> ndx);
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ levelData.setSize(levelW, levelH, levelD);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texSubImage3D(
+ gl.TEXTURE_3D, ndx, 0, 0, 0, levelW, levelH,
+ levelD, transferFmt.format, transferFmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // Pixel buffer object cases.
+
+ // TexImage2D() from pixel buffer object.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexImage2DBufferCase = function(
+ name, desc, internalFormat, width, height, rowLength,
+ skipRows, skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_rowLength = rowLength;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexImage2DBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.TexImage2DBufferCase.prototype.createTexture =
+ function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_rowLength > 0 ?
+ this.m_rowLength :
+ this.m_width + this.m_skipPixels;
+ var rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var height = this.m_height + this.m_skipRows;
+ var buf = null;
+ var tex = null;
+ var data = new ArrayBuffer(rowPitch * height + this.m_skipPixels * pixelSize + this.m_offset);
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels different than 1',
+ false, true
+ );
+
+ // Fill data with grid.
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: rowPitch,
+ data: data,
+ offset: this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize + this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(access, 4, colorA, colorB);
+
+ // Create buffer and upload.
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.texImage2D(gl.TEXTURE_2D, 0, this.m_internalFormat,
+ this.m_width, this.m_height, 0, transferFmt.format, transferFmt.dataType,
+ this.m_offset
+ );
+ };
+
+ // TexImage2D() cubemap from pixel buffer object case
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexImageCubeBufferCase = function(
+ name, desc, internalFormat, size, rowLength, skipRows, skipPixels,
+ alignment, offset
+ ) {
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), size, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_rowLength = rowLength;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexImageCubeBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImageCubeBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImageCubeBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImageCubeBufferCase.prototype.createTexture = function() {
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var tex = null;
+ var fmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_rowLength > 0 ?
+ this.m_rowLength : this.m_size + this.m_skipPixels;
+ var rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var height = this.m_size + this.m_skipRows;
+
+ var data = new ArrayBuffer(rowPitch * height + this.m_skipPixels * pixelSize + this.m_offset);
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_size,
+ height: this.m_size,
+ rowPitch: rowPitch,
+ data: data,
+ offset: this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize + this.m_offset
+ });
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var buf = null;
+
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ tcuTextureUtil.fillWithComponentGradients(access, gMin, gMax);
+
+ // Create buffer and upload.
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW);
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face], 0,
+ this.m_internalFormat, this.m_size, this.m_size, 0, fmt.format,
+ fmt.dataType, this.m_offset);
+ }
+ };
+
+ // TexImage3D() 2D array from pixel buffer object.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} imageHeight
+ * @param {number} rowLength
+ * @param {number} skipImages
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexImage2DArrayBufferCase = function(
+ name, desc, internalFormat, width, height, depth, imageHeight,
+ rowLength, skipImages, skipRows, skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, depth, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_imageHeight = imageHeight;
+ this.m_rowLength = rowLength;
+ this.m_skipImages = skipImages;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexImage2DArrayBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DArrayBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DArrayBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImage2DArrayBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_width;
+ var rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var imageHeight = this.m_imageHeight > 0 ?
+ this.m_imageHeight : this.m_height;
+ var slicePitch = imageHeight * rowPitch;
+ var tex = null;
+ var buf = null;
+ var data = new ArrayBuffer(
+ slicePitch * (this.m_numLayers + this.m_skipImages) +
+ this.m_skipRows * rowPitch + this.m_skipPixels * pixelSize + this.m_offset
+ );
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ // Fill data with grid.
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_numLayers,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: this.m_skipImages * slicePitch +
+ this.m_skipRows * rowPitch +
+ this.m_skipPixels * pixelSize +
+ this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(access, 4, colorA, colorB);
+
+ // Create buffer and upload.
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW);
+
+ this.m_context.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, this.m_imageHeight);
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_IMAGES, this.m_skipImages);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ this.m_context.texImage3D(
+ gl.TEXTURE_2D_ARRAY, 0, this.m_internalFormat, this.m_width,
+ this.m_height, this.m_numLayers, 0, transferFmt.format,
+ transferFmt.dataType, this.m_offset
+ );
+ };
+
+ // TexImage3D() from pixel buffer object.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} imageHeight
+ * @param {number} rowLength
+ * @param {number} skipImages
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexImage3DBufferCase = function(
+ name, desc, internalFormat, width, height, depth, imageHeight,
+ rowLength, skipImages, skipRows, skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, depth, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_imageHeight = imageHeight;
+ this.m_rowLength = rowLength;
+ this.m_skipImages = skipImages;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexImage3DBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage3DBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage3DBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImage3DBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_width;
+ var rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var imageHeight = this.m_imageHeight > 0 ?
+ this.m_imageHeight : this.m_height;
+ var slicePitch = imageHeight * rowPitch;
+ var tex = null;
+ var buf = null;
+ var data = new ArrayBuffer(
+ slicePitch * (this.m_depth + this.m_skipImages) +
+ rowPitch * this.m_skipRows + pixelSize * this.m_skipPixels + this.m_offset
+ );
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ // Fill data with grid.
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: this.m_skipImages * slicePitch +
+ this.m_skipRows * rowPitch +
+ this.m_skipPixels * pixelSize +
+ this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(access, 4, colorA, colorB);
+
+ // Create buffer and upload.
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW);
+
+ this.m_context.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, this.m_imageHeight);
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_IMAGES, this.m_skipImages);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+ this.m_context.texImage3D(
+ gl.TEXTURE_3D, 0, this.m_internalFormat, this.m_width,
+ this.m_height, this.m_depth, 0, transferFmt.format,
+ transferFmt.dataType, this.m_offset
+ );
+ };
+
+ // TexSubImage2D() PBO case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexSubImage2DBufferCase = function(
+ name, desc, internalFormat, width, height, subX, subY, subW, subH,
+ rowLength, skipRows, skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, 1
+ );
+ this.m_internalFormat = internalFormat;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_rowLength = rowLength;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var tex = null;
+ var buf = null;
+ var data = new ArrayBuffer(
+ deMath.deAlign32(this.m_width * pixelSize, 4) * this.m_height
+ );
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: deMath.deAlign32(this.m_width * pixelSize, 4),
+ data: data
+ });
+ // First fill texture with gradient.
+ tcuTextureUtil.fillWithComponentGradients(access, this.m_texFormatInfo.valueMin, this.m_texFormatInfo.valueMax);
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, 0, this.m_internalFormat,
+ this.m_width, this.m_height, 0, transferFmt.format,
+ transferFmt.dataType, access.getDataPtr()
+ );
+
+ // Fill data with grid.
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_subW;
+ var rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var height = this.m_subH + this.m_skipRows;
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: new ArrayBuffer(rowPitch * height + this.m_offset),
+ offset: this.m_skipRows * rowPitch +
+ this.m_skipPixels * pixelSize +
+ this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(access, 4, colorA, colorB);
+
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(gl.PIXEL_UNPACK_BUFFER, access.getBuffer(), gl.STATIC_DRAW);
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, 0, this.m_subX, this.m_subY,
+ this.m_subW, this.m_subH, transferFmt.format,
+ transferFmt.dataType, this.m_offset
+ );
+ };
+
+ // TexSubImage2D() cubemap PBO case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.TextureCubeSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} size
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} rowLength
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexSubImageCubeBufferCase = function(
+ name, desc, internalFormat, size, subX, subY, subW, subH, rowLength,
+ skipRows, skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.TextureCubeSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), size, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_rowLength = rowLength;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexSubImageCubeBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.TextureCubeSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImageCubeBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImageCubeBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImageCubeBufferCase.prototype.createTexture = function() {
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var tex = null;
+ var buf = null;
+ var data = new ArrayBuffer(
+ deMath.deAlign32(this.m_size * pixelSize, 4) * this.m_size
+ );
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_size,
+ height: this.m_size,
+ rowPitch: deMath.deAlign32(this.m_size * pixelSize, 4),
+ data: data
+ });
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+
+ // Fill faces with different gradients.
+
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ var gMin = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+ var gMax = es3fTextureSpecificationTests.randomVector(
+ rnd, this.m_texFormatInfo.valueMin,
+ this.m_texFormatInfo.valueMax, 4
+ );
+
+ tcuTextureUtil.fillWithComponentGradients(access, gMin, gMax);
+
+ this.m_context.texImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face], 0,
+ this.m_internalFormat, this.m_size, this.m_size, 0,
+ transferFmt.format, transferFmt.dataType,
+ access.getDataPtr()
+ );
+ }
+
+ // Fill data with grid.
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_subW;
+ var rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var height = this.m_subH + this.m_skipRows;
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ data = new ArrayBuffer(rowPitch * height + this.m_skipPixels * pixelSize + this.m_offset);
+ var accessSub = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: data,
+ offset: this.m_skipRows * rowPitch +
+ this.m_skipPixels * pixelSize +
+ this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(accessSub, 4, colorA, colorB);
+
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(
+ gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+
+ for (var f in tcuTexture.CubeFace) {
+ var face = tcuTexture.CubeFace[f];
+ this.m_context.texSubImage2D(
+ es3fTextureSpecificationTests.s_cubeMapFaces[face], 0,
+ this.m_subX, this.m_subY, this.m_subW, this.m_subH,
+ transferFmt.format, transferFmt.dataType, this.m_offset
+ );
+ }
+ };
+
+ // TexSubImage3D() 2D array PBO case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subZ
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} subD
+ * @param {number} imageHeight
+ * @param {number} rowLength
+ * @param {number} skipImages
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexSubImage2DArrayBufferCase = function(
+ name, desc, internalFormat, width, height, depth, subX, subY, subZ,
+ subW, subH, subD, imageHeight, rowLength, skipImages, skipRows,
+ skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, depth, 1
+ );
+ this.m_internalFormat = internalFormat;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subZ = subZ;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_subD = subD;
+ this.m_imageHeight = imageHeight;
+ this.m_rowLength = rowLength;
+ this.m_skipImages = skipImages;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DArrayBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DArrayBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DArrayBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DArrayBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var tex = null;
+ var buf = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+
+ // Fill with gradient.
+ var rowPitch = deMath.deAlign32(pixelSize * this.m_width, 4);
+ var slicePitch = rowPitch * this.m_height;
+
+ data = new ArrayBuffer(slicePitch * this.m_numLayers);
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_numLayers,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, this.m_texFormatInfo.valueMin, this.m_texFormatInfo.valueMax
+ );
+
+ this.m_context.texImage3D(gl.TEXTURE_2D_ARRAY, 0, this.m_internalFormat, this.m_width, this.m_height,
+ this.m_numLayers, 0, transferFmt.format, transferFmt.dataType, access.getDataPtr());
+
+ // Fill data with grid.
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_subW;
+ rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var height = this.m_subH + this.m_skipRows;
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ var accessSub = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ rowPitch: rowPitch,
+ data: new ArrayBuffer(rowPitch * height + this.m_offset),
+ offset: this.m_skipRows * rowPitch +
+ this.m_skipPixels * pixelSize +
+ this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(accessSub, 4, colorA, colorB);
+
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(
+ gl.PIXEL_UNPACK_BUFFER, accessSub.getBuffer(), gl.STATIC_DRAW
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+ };
+
+ // TexSubImage3D() PBO case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture3DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} subX
+ * @param {number} subY
+ * @param {number} subZ
+ * @param {number} subW
+ * @param {number} subH
+ * @param {number} subD
+ * @param {number} imageHeight
+ * @param {number} rowLength
+ * @param {number} skipImages
+ * @param {number} skipRows
+ * @param {number} skipPixels
+ * @param {number} alignment
+ * @param {number} offset
+ */
+ es3fTextureSpecificationTests.TexSubImage3DBufferCase = function(
+ name, desc, internalFormat, width, height, depth, subX, subY, subZ,
+ subW, subH, subD, imageHeight, rowLength, skipImages, skipRows,
+ skipPixels, alignment, offset
+ ) {
+ es3fTextureSpecificationTests.Texture3DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), width, height, depth, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ this.m_subX = subX;
+ this.m_subY = subY;
+ this.m_subZ = subZ;
+ this.m_subW = subW;
+ this.m_subH = subH;
+ this.m_subD = subD;
+ this.m_imageHeight = imageHeight;
+ this.m_rowLength = rowLength;
+ this.m_skipImages = skipImages;
+ this.m_skipRows = skipRows;
+ this.m_skipPixels = skipPixels;
+ this.m_alignment = alignment;
+ this.m_offset = offset;
+ };
+
+ es3fTextureSpecificationTests.TexSubImage3DBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture3DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage3DBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage3DBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage3DBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(
+ this.m_texFormat
+ );
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var tex = null;
+ var buf = null;
+ /** @type {ArrayBuffer} */ var data;
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_3D, tex);
+
+ // Fill with gradient.
+ var rowPitch = deMath.deAlign32(pixelSize * this.m_width, 4);
+ var slicePitch = rowPitch * this.m_height;
+
+ data = new ArrayBuffer(slicePitch * this.m_depth);
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_depth,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data});
+ tcuTextureUtil.fillWithComponentGradients(access, this.m_texFormatInfo.valueMin, this.m_texFormatInfo.valueMax
+ );
+
+ this.m_context.texImage3D(
+ gl.TEXTURE_3D, 0, this.m_internalFormat, this.m_width,
+ this.m_height, this.m_depth, 0, transferFmt.format,
+ transferFmt.dataType, access.getDataPtr()
+ );
+
+ // Fill data with grid.
+ var rowLength = this.m_rowLength > 0 ? this.m_rowLength : this.m_subW;
+ rowPitch = deMath.deAlign32(
+ rowLength * pixelSize, this.m_alignment
+ );
+ var imageHeight = this.m_imageHeight > 0 ?
+ this.m_imageHeight : this.m_subH;
+ slicePitch = imageHeight * rowPitch;
+ var cScale = deMath.subtract(this.m_texFormatInfo.valueMax, this.m_texFormatInfo.valueMin);
+ var cBias = this.m_texFormatInfo.valueMin;
+ var colorA = deMath.add(
+ deMath.multiply([1.0, 0.0, 0.0, 1.0], cScale), cBias
+ );
+ var colorB = deMath.add(
+ deMath.multiply([0.0, 1.0, 0.0, 1.0], cScale), cBias
+ );
+
+ data = new ArrayBuffer(slicePitch * (this.m_subD + this.m_skipImages) +
+ rowPitch * this.m_skipRows + pixelSize * this.m_skipPixels + this.m_offset);
+ var accessSub = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_subW,
+ height: this.m_subH,
+ depth: this.m_subD,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data,
+ offset: this.m_skipImages * slicePitch +
+ this.m_skipRows * rowPitch +
+ this.m_skipPixels * pixelSize +
+ this.m_offset
+ });
+ tcuTextureUtil.fillWithGrid(accessSub, 4, colorA, colorB
+ );
+
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(
+ gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, this.m_imageHeight);
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, this.m_rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_IMAGES, this.m_skipImages);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, this.m_skipRows);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, this.m_skipPixels);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, this.m_alignment);
+ this.m_context.texSubImage3D(
+ gl.TEXTURE_3D, 0, this.m_subX, this.m_subY, this.m_subZ,
+ this.m_subW, this.m_subH, this.m_subD, transferFmt.format,
+ transferFmt.dataType, this.m_offset
+ );
+ };
+
+ // TexImage2D() depth case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} imageWidth
+ * @param {number} imageHeight
+ */
+ es3fTextureSpecificationTests.TexImage2DDepthCase = function(
+ name, desc, internalFormat, imageWidth, imageHeight
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), imageWidth, imageHeight,
+ es3fTextureSpecificationTests.maxLevelCount(
+ imageWidth, imageHeight
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
+ this.m_texFormatInfo.lookupBias = [0.25, 0.0, 0.0, 1.0];
+ this.m_texFormatInfo.lookupScale = [0.5, 1.0, 1.0, 0.0];
+ };
+
+ es3fTextureSpecificationTests.TexImage2DDepthCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DDepthCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DDepthCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.TexImage2DDepthCase.prototype.createTexture =
+ function() {
+ var fmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = [-1.5, -2.0, 1.7, -1.5];
+ var gMax = [2.0, 1.5, -1.0, 2.0];
+
+ levelData.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, levelW, levelH, 0,
+ fmt.format, fmt.dataType, levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexImage3D() depth case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} imageWidth
+ * @param {number} imageHeight
+ * @param {number} numLayers
+ */
+ es3fTextureSpecificationTests.TexImage2DArrayDepthCase = function(
+ name, desc, internalFormat, imageWidth, imageHeight, numLayers
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), imageWidth, imageHeight, numLayers,
+ es3fTextureSpecificationTests.maxLevelCount(
+ imageWidth, imageHeight
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
+ this.m_texFormatInfo.lookupBias = [0.25, 0.0, 0.0, 1.0];
+ this.m_texFormatInfo.lookupScale = [0.5, 1.0, 1.0, 0.0];
+ };
+
+ es3fTextureSpecificationTests.TexImage2DArrayDepthCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DArrayDepthCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DArrayDepthCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImage2DArrayDepthCase.prototype.createTexture = function() {
+ var fmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = [-1.5, -2.0, 1.7, -1.5];
+ var gMax = [2.0, 1.5, -1.0, 2.0];
+
+ levelData.setSize(levelW, levelH, this.m_numLayers);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage3D(
+ gl.TEXTURE_2D_ARRAY, ndx, this.m_internalFormat, levelW, levelH,
+ this.m_numLayers, 0, fmt.format, fmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexSubImage2D() depth case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} imageWidth
+ * @param {number} imageHeight
+ */
+ es3fTextureSpecificationTests.TexSubImage2DDepthCase = function(
+ name, desc, internalFormat, imageWidth, imageHeight
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), imageWidth, imageHeight,
+ es3fTextureSpecificationTests.maxLevelCount(
+ imageWidth, imageHeight
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
+ this.m_texFormatInfo.lookupBias = [0.25, 0.0, 0.0, 1.0];
+ this.m_texFormatInfo.lookupScale = [0.5, 1.0, 1.0, 0.0];
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DDepthCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DDepthCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DDepthCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DDepthCase.prototype.createTexture = function() {
+ var fmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // First specify full texture.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = [-1.5, -2.0, 1.7, -1.5];
+ var gMax = [2.0, 1.5, -1.0, 2.0];
+
+ levelData.setSize(levelW, levelH);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, ndx, this.m_internalFormat, levelW, levelH, 0,
+ fmt.format, fmt.dataType, levelData.getAccess().getDataPtr()
+ );
+ }
+
+ // Re-specify parts of each level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ var w = rnd.getInt(1, levelW);
+ var h = rnd.getInt(1, levelH);
+ var x = rnd.getInt(0, levelW - w);
+ var y = rnd.getInt(0, levelH - h);
+
+ var colorA = [2.0, 1.5, -1.0, 2.0];
+ var colorB = [-1.5, -2.0, 1.7, -1.5];
+ var cellSize = rnd.getInt(2, 16);
+
+ levelData.setSize(w, h);
+ tcuTextureUtil.fillWithGrid(
+ levelData.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texSubImage2D(
+ gl.TEXTURE_2D, ndx, x, y, w, h, fmt.format, fmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexSubImage3D() depth case.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} imageWidth
+ * @param {number} imageHeight
+ * @param {number} numLayers
+ */
+ es3fTextureSpecificationTests.TexSubImage2DArrayDepthCase = function(
+ name, desc, internalFormat, imageWidth, imageHeight, numLayers
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), imageWidth, imageHeight, numLayers,
+ es3fTextureSpecificationTests.maxLevelCount(
+ imageWidth, imageHeight
+ )
+ );
+
+ this.m_internalFormat = internalFormat;
+ // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
+ this.m_texFormatInfo.lookupBias = [0.25, 0.0, 0.0, 1.0];
+ this.m_texFormatInfo.lookupScale = [0.5, 1.0, 1.0, 0.0];
+ };
+
+ es3fTextureSpecificationTests.TexSubImage2DArrayDepthCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexSubImage2DArrayDepthCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexSubImage2DArrayDepthCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexSubImage2DArrayDepthCase.prototype.createTexture = function() {
+ var fmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var rnd = new deRandom.Random(deString.deStringHash(this.fullName()));
+ var tex = null;
+ var levelData = new tcuTexture.TextureLevel(
+ this.m_texFormat, this.m_width, this.m_height
+ );
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ // First specify full texture.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+ var gMin = [-1.5, -2.0, 1.7, -1.5];
+ var gMax = [2.0, 1.5, -1.0, 2.0];
+
+ levelData.setSize(levelW, levelH, this.m_numLayers);
+ tcuTextureUtil.fillWithComponentGradients(
+ levelData.getAccess(), gMin, gMax
+ );
+ this.m_context.texImage3D(
+ gl.TEXTURE_2D_ARRAY, ndx, this.m_internalFormat, levelW, levelH,
+ this.m_numLayers, 0, fmt.format, fmt.dataType,
+ levelData.getAccess().getDataPtr()
+ );
+ }
+
+ // Re-specify parts of each level.
+ for (var ndx = 0; ndx < this.m_numLevels; ndx++) {
+ var levelW = Math.max(1, this.m_width >> ndx);
+ var levelH = Math.max(1, this.m_height >> ndx);
+
+ var w = rnd.getInt(1, levelW);
+ var h = rnd.getInt(1, levelH);
+ var d = rnd.getInt(1, this.m_numLayers);
+ var x = rnd.getInt(0, levelW - w);
+ var y = rnd.getInt(0, levelH - h);
+ var z = rnd.getInt(0, this.m_numLayers - d);
+
+ var colorA = [2.0, 1.5, -1.0, 2.0];
+ var colorB = [-1.5, -2.0, 1.7, -1.5];
+ var cellSize = rnd.getInt(2, 16);
+
+ levelData.setSize(w, h, d);
+ tcuTextureUtil.fillWithGrid(
+ levelData.getAccess(), cellSize, colorA, colorB
+ );
+
+ this.m_context.texSubImage3D(
+ gl.TEXTURE_2D_ARRAY, ndx, x, y, z, w, h, d, fmt.format,
+ fmt.dataType, levelData.getAccess().getDataPtr()
+ );
+ }
+ };
+
+ // TexImage2D() depth case with pbo.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DSpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} imageWidth
+ * @param {number} imageHeight
+ */
+ es3fTextureSpecificationTests.TexImage2DDepthBufferCase = function(
+ name, desc, internalFormat, imageWidth, imageHeight
+ ) {
+ es3fTextureSpecificationTests.Texture2DSpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), imageWidth, imageHeight, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
+ this.m_texFormatInfo.lookupBias = [0.25, 0.0, 0.0, 1.0];
+ this.m_texFormatInfo.lookupScale = [0.5, 1.0, 1.0, 0.0];
+ };
+
+ es3fTextureSpecificationTests.TexImage2DDepthBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DSpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DDepthBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DDepthBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImage2DDepthBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_width;
+ var alignment = 4;
+ var rowPitch = deMath.deAlign32(rowLength * pixelSize, alignment);
+ var height = this.m_height;
+ var buf = null;
+ var tex = null;
+ var data = new ArrayBuffer(rowPitch * height);
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ // Fill data with gradient
+ var gMin = [-1.5, -2.0, 1.7, -1.5];
+ var gMax = [2.0, 1.5, -1.0, 2.0];
+
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ rowPitch: rowPitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, gMin, gMax);
+
+ // Create buffer and upload.
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(
+ gl.PIXEL_UNPACK_BUFFER, access.getBuffer(), gl.STATIC_DRAW
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D, tex);
+ this.m_context.texImage2D(
+ gl.TEXTURE_2D, 0, this.m_internalFormat, this.m_width,
+ this.m_height, 0, transferFmt.format, transferFmt.dataType, 0
+ );
+ this.m_context.deleteBuffer(buf);
+ };
+
+ // TexImage3D() depth case with pbo.
+ /**
+ * @constructor
+ * @extends {es3fTextureSpecificationTests.Texture2DArraySpecCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} internalFormat
+ * @param {number} imageWidth
+ * @param {number} imageHeight
+ */
+ es3fTextureSpecificationTests.TexImage2DArrayDepthBufferCase = function(
+ name, desc, internalFormat, imageWidth, imageHeight, numLayers
+ ) {
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.call(
+ this, name, desc, gluTextureUtil.mapGLInternalFormat(
+ internalFormat
+ ), imageWidth, imageHeight, numLayers, 1
+ );
+
+ this.m_internalFormat = internalFormat;
+ // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
+ this.m_texFormatInfo.lookupBias = [0.25, 0.0, 0.0, 1.0];
+ this.m_texFormatInfo.lookupScale = [0.5, 1.0, 1.0, 0.0];
+ };
+
+ es3fTextureSpecificationTests.TexImage2DArrayDepthBufferCase.prototype =
+ Object.create(
+ es3fTextureSpecificationTests.Texture2DArraySpecCase.prototype
+ );
+
+ es3fTextureSpecificationTests.
+ TexImage2DArrayDepthBufferCase.prototype.constructor =
+ es3fTextureSpecificationTests.TexImage2DArrayDepthBufferCase;
+
+ /**
+ * createTexture
+ */
+ es3fTextureSpecificationTests.
+ TexImage2DArrayDepthBufferCase.prototype.createTexture = function() {
+ var transferFmt = gluTextureUtil.getTransferFormat(this.m_texFormat);
+ var pixelSize = this.m_texFormat.getPixelSize();
+ var rowLength = this.m_width;
+ var alignment = 4;
+ var rowPitch = deMath.deAlign32(rowLength * pixelSize, alignment);
+ var imageHeight = this.m_height;
+ var slicePitch = imageHeight * rowPitch;
+ var tex = null;
+ var buf = null;
+ var data = new ArrayBuffer(slicePitch * this.m_numLayers);
+
+ assertMsgOptions(
+ this.m_numLevels == 1, 'Number of levels is different than 1',
+ false, true
+ );
+
+ // Fill data with gradient
+ var gMin = [-1.5, -2.0, 1.7, -1.5];
+ var gMax = [2.0, 1.5, -1.0, 2.0];
+
+ var access = new tcuTexture.PixelBufferAccess({
+ format: this.m_texFormat,
+ width: this.m_width,
+ height: this.m_height,
+ depth: this.m_numLayers,
+ rowPitch: rowPitch,
+ slicePitch: slicePitch,
+ data: data
+ });
+ tcuTextureUtil.fillWithComponentGradients(access, gMin, gMax);
+
+ buf = this.m_context.createBuffer();
+ this.m_context.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
+ this.m_context.bufferData(
+ gl.PIXEL_UNPACK_BUFFER, access.getBuffer(), gl.STATIC_DRAW
+ );
+
+ this.m_context.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_ROW_LENGTH, rowLength);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ this.m_context.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ this.m_context.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);
+
+ tex = this.m_context.createTexture();
+ this.m_context.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
+ this.m_context.texImage3D(
+ gl.TEXTURE_2D_ARRAY, 0, this.m_internalFormat, this.m_width,
+ this.m_height, this.m_numLayers, 0, transferFmt.format,
+ transferFmt.dataType, 0
+ );
+ this.m_context.deleteBuffer(buf);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fTextureSpecificationTests.TextureSpecificationTests = function() {
+ tcuTestCase.DeqpTest.call(
+ this, 'specification', 'Texture Specification Tests'
+ );
+ };
+
+ es3fTextureSpecificationTests.TextureSpecificationTests.prototype =
+ Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fTextureSpecificationTests.TextureSpecificationTests.prototype.constructor =
+ es3fTextureSpecificationTests.TextureSpecificationTests;
+
+ es3fTextureSpecificationTests.TextureSpecificationTests.prototype.init = function() {
+ /**
+ * @type {Array<number>}
+ */
+ es3fTextureSpecificationTests.s_cubeMapFaces = [
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z
+ ];
+
+ /** @type {Array<{name: string, format: number, dataType: number}>} */
+ var unsizedFormats = [{
+ name: 'alpha_unsigned_byte',
+ format: gl.ALPHA,
+ dataType: gl.UNSIGNED_BYTE
+ }, {
+ name: 'luminance_unsigned_byte',
+ format: gl.LUMINANCE,
+ dataType: gl.UNSIGNED_BYTE
+ }, {
+ name: 'luminance_alpha_unsigned_byte',
+ format: gl.LUMINANCE_ALPHA,
+ dataType: gl.UNSIGNED_BYTE
+ }, {
+ name: 'rgb_unsigned_short_5_6_5',
+ format: gl.RGB,
+ dataType: gl.UNSIGNED_SHORT_5_6_5
+ }, {
+ name: 'rgb_unsigned_byte',
+ format: gl.RGB,
+ dataType: gl.UNSIGNED_BYTE
+ }, {
+ name: 'rgba_unsigned_short_4_4_4_4',
+ format: gl.RGBA,
+ dataType: gl.UNSIGNED_SHORT_4_4_4_4
+ }, {
+ name: 'rgba_unsigned_short_5_5_5_1',
+ format: gl.RGBA,
+ dataType: gl.UNSIGNED_SHORT_5_5_5_1
+ }, {
+ name: 'rgba_unsigned_byte',
+ format: gl.RGBA,
+ dataType: gl.UNSIGNED_BYTE
+ }
+ ];
+
+ /** @type {Array<{name: string, internalFormat: number}>} */
+ var colorFormats = [{
+ name: 'rgba32f', internalFormat: gl.RGBA32F
+ }, {
+ name: 'rgba32i', internalFormat: gl.RGBA32I
+ }, {
+ name: 'rgba32ui', internalFormat: gl.RGBA32UI
+ }, {
+ name: 'rgba16f', internalFormat: gl.RGBA16F
+ }, {
+ name: 'rgba16i', internalFormat: gl.RGBA16I
+ }, {
+ name: 'rgba16ui', internalFormat: gl.RGBA16UI
+ }, {
+ name: 'rgba8', internalFormat: gl.RGBA8
+ }, {
+ name: 'rgba8i', internalFormat: gl.RGBA8I
+ }, {
+ name: 'rgba8ui', internalFormat: gl.RGBA8UI
+ }, {
+ name: 'srgb8_alpha8', internalFormat: gl.SRGB8_ALPHA8
+ }, {
+ name: 'rgb10_a2', internalFormat: gl.RGB10_A2
+ }, {
+ name: 'rgb10_a2ui', internalFormat: gl.RGB10_A2UI
+ }, {
+ name: 'rgba4', internalFormat: gl.RGBA4
+ }, {
+ name: 'rgb5_a1', internalFormat: gl.RGB5_A1
+ }, {
+ name: 'rgba8_snorm', internalFormat: gl.RGBA8_SNORM
+ }, {
+ name: 'rgb8', internalFormat: gl.RGB8
+ }, {
+ name: 'rgb565', internalFormat: gl.RGB565
+ }, {
+ name: 'r11f_g11f_b10f', internalFormat: gl.R11F_G11F_B10F
+ }, {
+ name: 'rgb32f', internalFormat: gl.RGB32F
+ }, {
+ name: 'rgb32i', internalFormat: gl.RGB32I
+ }, {
+ name: 'rgb32ui', internalFormat: gl.RGB32UI
+ }, {
+ name: 'rgb16f', internalFormat: gl.RGB16F
+ }, {
+ name: 'rgb16i', internalFormat: gl.RGB16I
+ }, {
+ name: 'rgb16ui', internalFormat: gl.RGB16UI
+ }, {
+ name: 'rgb8_snorm', internalFormat: gl.RGB8_SNORM
+ }, {
+ name: 'rgb8i', internalFormat: gl.RGB8I
+ }, {
+ name: 'rgb8ui', internalFormat: gl.RGB8UI
+ }, {
+ name: 'srgb8', internalFormat: gl.SRGB8
+ }, {
+ name: 'rgb9_e5', internalFormat: gl.RGB9_E5
+ }, {
+ name: 'rg32f', internalFormat: gl.RG32F
+ }, {
+ name: 'rg32i', internalFormat: gl.RG32I
+ }, {
+ name: 'rg32ui', internalFormat: gl.RG32UI
+ }, {
+ name: 'rg16f', internalFormat: gl.RG16F
+ }, {
+ name: 'rg16i', internalFormat: gl.RG16I
+ }, {
+ name: 'rg16ui', internalFormat: gl.RG16UI
+ }, {
+ name: 'rg8', internalFormat: gl.RG8
+ }, {
+ name: 'rg8i', internalFormat: gl.RG8I
+ }, {
+ name: 'rg8ui', internalFormat: gl.RG8UI
+ }, {
+ name: 'rg8_snorm', internalFormat: gl.RG8_SNORM
+ }, {
+ name: 'r32f', internalFormat: gl.R32F
+ }, {
+ name: 'r32i', internalFormat: gl.R32I
+ }, {
+ name: 'r32ui', internalFormat: gl.R32UI
+ }, {
+ name: 'r16f', internalFormat: gl.R16F
+ }, {
+ name: 'r16i', internalFormat: gl.R16I
+ }, {
+ name: 'r16ui', internalFormat: gl.R16UI
+ }, {
+ name: 'r8', internalFormat: gl.R8
+ }, {
+ name: 'r8i', internalFormat: gl.R8I
+ }, {
+ name: 'r8ui', internalFormat: gl.R8UI
+ }, {
+ name: 'r8_snorm', internalFormat: gl.R8_SNORM
+ }
+ ];
+
+ // Depth and stencil formats
+ /** @type {Array<{name: string, internalFormat: number}>} */
+ var depthStencilFormats = [{
+ name: 'depth_component32f',
+ internalFormat: gl.DEPTH_COMPONENT32F
+ }, {
+ name: 'depth_component24',
+ internalFormat: gl.DEPTH_COMPONENT24
+ }, {
+ name: 'depth_component16',
+ internalFormat: gl.DEPTH_COMPONENT16
+ }, {
+ name: 'depth32f_stencil8',
+ internalFormat: gl.DEPTH32F_STENCIL8
+ }, {
+ name: 'depth24_stencil8',
+ internalFormat: gl.DEPTH24_STENCIL8
+ }
+ ];
+
+ // Basic TexImage2D usage.
+ var splitBasicTex2D = 2, splitBasicTexCube = 5;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */
+ var basicTexImageGroup2D = [];
+ for (var ii = 0; ii < splitBasicTex2D; ++ii) {
+ basicTexImageGroup2D.push(
+ new tcuTestCase.DeqpTest('basic_teximage2d', 'Basic glTexImage2D() usage')
+ );
+ this.addChild(basicTexImageGroup2D[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */
+ var basicTexImageGroupCube = [];
+ for (var ii = 0; ii < splitBasicTexCube; ++ii) {
+ basicTexImageGroupCube.push(
+ new tcuTestCase.DeqpTest('basic_teximage2d', 'Basic glTexImage2D() usage')
+ );
+ this.addChild(basicTexImageGroupCube[ii]);
+ }
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ /** @type {string} */
+ var fmtName = colorFormats[formatNdx].name;
+ /** @type {number} */
+ var format = colorFormats[formatNdx].internalFormat;
+ /** @type {number} */
+ var tex2DWidth = 64;
+ /** @type {number} */
+ var tex2DHeight = 128;
+ /** @type {number} */
+ var texCubeSize = 64;
+
+ basicTexImageGroup2D[formatNdx % splitBasicTex2D].addChild(
+ es3fTextureSpecificationTests.newBasicTexImage2DCaseInternal(
+ fmtName + '_2d', '', format, tex2DWidth, tex2DHeight
+ )
+ );
+ basicTexImageGroupCube[formatNdx % splitBasicTexCube].addChild(
+ es3fTextureSpecificationTests.newBasicTexImageCubeCaseInternal(
+ fmtName + '_cube', '', format, texCubeSize
+ )
+ );
+ }
+
+ // Randomized TexImage2D order.
+ /** @type {tcuTestCase.DeqpTest} */
+ var randomTexImageGroup = new tcuTestCase.DeqpTest(
+ 'random_teximage2d', 'Randomized glTexImage2D() usage'
+ );
+ this.addChild(randomTexImageGroup);
+ var rnd = new deRandom.Random(9);
+
+ // 2D cases.
+ for (var ndx = 0; ndx < 10; ndx++) {
+ var formatNdx = rnd.getInt(0, colorFormats.length - 1);
+ var width = 1 << rnd.getInt(2, 8);
+ var height = 1 << rnd.getInt(2, 8);
+
+ randomTexImageGroup.addChild(
+ es3fTextureSpecificationTests.newRandomOrderTexImage2DCaseInternal(
+ '2d.' + colorFormats[formatNdx].name, '',
+ colorFormats[formatNdx].internalFormat, width, height
+ )
+ );
+ }
+
+ // Cubemap cases.
+ randomTexImageGroup = new tcuTestCase.DeqpTest(
+ 'random_teximage2d', 'Randomized glTexImage2D() usage'
+ );
+ this.addChild(randomTexImageGroup);
+
+ for (var ndx = 0; ndx < 10; ndx++) {
+ formatNdx = rnd.getInt(0, colorFormats.length - 1);
+ /** @type {number} */ var size = 1 << rnd.getInt(2, 8);
+
+ randomTexImageGroup.addChild(
+ es3fTextureSpecificationTests.newRandomOrderTexImageCubeCaseInternal(
+ 'cube.' + colorFormats[formatNdx].name, '',
+ colorFormats[formatNdx].internalFormat, size
+ )
+ );
+ }
+
+ // TexImage2D unpack alignment.
+ /** @type {tcuTestCase.DeqpTest} */
+ var alignGroup = new tcuTestCase.DeqpTest(
+ 'teximage2d_align', 'glTexImage2D() unpack alignment tests'
+ );
+ this.addChild(alignGroup);
+
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_r8_4_8', '', gl.R8, 4, 8, 4, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_r8_63_1', '', gl.R8, 63, 30, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_r8_63_2', '', gl.R8, 63, 30, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_r8_63_4', '', gl.R8, 63, 30, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_r8_63_8', '', gl.R8, 63, 30, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba4_51_1', '', gl.RGBA4, 51, 30, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba4_51_2', '', gl.RGBA4, 51, 30, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba4_51_4', '', gl.RGBA4, 51, 30, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba4_51_8', '', gl.RGBA4, 51, 30, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgb8_39_1', '', gl.RGB8, 39, 43, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgb8_39_2', '', gl.RGB8, 39, 43, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgb8_39_4', '', gl.RGB8, 39, 43, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgb8_39_8', '', gl.RGB8, 39, 43, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba8_47_1', '', gl.RGBA8, 47, 27, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba8_47_2', '', gl.RGBA8, 47, 27, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba8_47_4', '', gl.RGBA8, 47, 27, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImage2DAlignCaseInternal(
+ '2d_rgba8_47_8', '', gl.RGBA8, 47, 27, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_r8_4_8', '', gl.R8, 4, 3, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_r8_63_1', '', gl.R8, 63, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_r8_63_2', '', gl.R8, 63, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_r8_63_4', '', gl.R8, 63, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_r8_63_8', '', gl.R8, 63, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_1', '', gl.RGBA4, 51, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_2', '', gl.RGBA4, 51, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_4', '', gl.RGBA4, 51, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_8', '', gl.RGBA4, 51, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_1', '', gl.RGB8, 39, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_2', '', gl.RGB8, 39, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_4', '', gl.RGB8, 39, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_8', '', gl.RGB8, 39, 1, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_1', '', gl.RGBA8, 47, 1, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_2', '', gl.RGBA8, 47, 1, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_4', '', gl.RGBA8, 47, 1, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_8', '', gl.RGBA8, 47, 1, 8
+ )
+ );
+
+ // glTexImage2D() unpack parameter cases.
+ /** @type {tcuTestCase.DeqpTest} */
+ var paramGroup = new tcuTestCase.DeqpTest(
+ 'teximage2d_unpack_params',
+ 'glTexImage2D() pixel transfer mode cases'
+ );
+ this.addChild(paramGroup);
+
+ var cases = [{
+ name: 'rgb8_alignment', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 0, skipRows: 0, skipPixels: 0,
+ alignment: 2
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 50, skipRows: 0, skipPixels: 0,
+ alignment: 4
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 0, skipRows: 3, skipPixels: 0,
+ alignment: 4
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 36, skipRows: 0, skipPixels: 5,
+ alignment: 4
+ }, {
+ name: 'r8_complex1', format: gl.R8, width: 31,
+ height: 30, rowLength: 64, skipRows: 1, skipPixels: 3,
+ alignment: 1
+ }, {
+ name: 'r8_complex2', format: gl.R8, width: 31,
+ height: 30, rowLength: 64, skipRows: 1, skipPixels: 3,
+ alignment: 2
+ }, {
+ name: 'r8_complex3', format: gl.R8, width: 31,
+ height: 30, rowLength: 64, skipRows: 1, skipPixels: 3,
+ alignment: 4
+ }, {
+ name: 'r8_complex4', format: gl.R8, width: 31,
+ height: 30, rowLength: 64, skipRows: 1, skipPixels: 3,
+ alignment: 8
+ }, {
+ name: 'rgba8_complex1', format: gl.RGBA8, width: 56,
+ height: 61, rowLength: 69, skipRows: 0, skipPixels: 0,
+ alignment: 8
+ }, {
+ name: 'rgba8_complex2', format: gl.RGBA8, width: 56,
+ height: 61, rowLength: 69, skipRows: 0, skipPixels: 7,
+ alignment: 8
+ }, {
+ name: 'rgba8_complex3', format: gl.RGBA8, width: 56,
+ height: 61, rowLength: 69, skipRows: 3, skipPixels: 0,
+ alignment: 8
+ }, {
+ name: 'rgba8_complex4', format: gl.RGBA8, width: 56,
+ height: 61, rowLength: 69, skipRows: 3, skipPixels: 7,
+ alignment: 8
+ }, {
+ name: 'rgba32f_complex', format: gl.RGBA32F, width: 19,
+ height: 10, rowLength: 27, skipRows: 1, skipPixels: 7,
+ alignment: 8
+ }
+ ];
+
+ for (var ndx = 0; ndx < cases.length; ndx++)
+ paramGroup.addChild(
+ new es3fTextureSpecificationTests.TexImage2DParamsCase(
+ cases[ndx].name, '', cases[ndx].format, cases[ndx].width,
+ cases[ndx].height, cases[ndx].rowLength,
+ cases[ndx].skipRows, cases[ndx].skipPixels,
+ cases[ndx].alignment
+ )
+ );
+
+ // glTexImage2D() pbo cases.
+ var splitPboTex2D = 2, splitPboTexCube = 5;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var pboGroup2D = [];
+ for (var ii = 0; ii < splitPboTex2D; ++ii) {
+ pboGroup2D.push(new tcuTestCase.DeqpTest('teximage2d_pbo', 'glTexImage2D() from PBO'));
+ this.addChild(pboGroup2D[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var pboGroupCube = [];
+ for (var ii = 0; ii < splitPboTexCube; ++ii) {
+ pboGroupCube.push(new tcuTestCase.DeqpTest('teximage2d_pbo', 'glTexImage2D() from PBO'));
+ this.addChild(pboGroupCube[ii]);
+ }
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ format = colorFormats[formatNdx].internalFormat;
+ tex2DWidth = 65;
+ tex2DHeight = 37;
+ texCubeSize = 64;
+
+ pboGroup2D[formatNdx % splitPboTex2D].addChild(
+ new es3fTextureSpecificationTests.TexImage2DBufferCase(
+ fmtName + '_2d', '', format,
+ tex2DWidth, tex2DHeight, 0, 0, 0, 4, 0
+ )
+ );
+ pboGroupCube[formatNdx % splitPboTexCube].addChild(
+ new es3fTextureSpecificationTests.TexImageCubeBufferCase(
+ fmtName + '_cube', '', format,
+ texCubeSize, 0, 0, 0, 4, 0
+ )
+ );
+ }
+
+ // Parameter cases
+ var pboGroupParams = new tcuTestCase.DeqpTest(
+ 'teximage2d_pbo', 'glTexImage2D() from PBO'
+ );
+ this.addChild(pboGroupParams);
+ /**
+ * @type {Array<{name: string, format: number, width: number,
+ * height: number, rowLength: number, skipRows: number,
+ * skipPixels: number, alignment: number, offset: number}>}
+ */
+ var parameterCases = [{
+ name: 'rgb8_offset', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 0, skipRows: 0, skipPixels: 0,
+ alignment: 4, offset: 67
+ }, {
+ name: 'rgb8_alignment', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 0, skipRows: 0, skipPixels: 0,
+ alignment: 2, offset: 0
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 50, skipRows: 0, skipPixels: 0,
+ alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 0, skipRows: 3, skipPixels: 0,
+ alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 31,
+ height: 30, rowLength: 36, skipRows: 0, skipPixels: 5,
+ alignment: 4, offset: 0
+ }
+ ];
+ for (var ndx = 0; ndx < parameterCases.length; ndx++) {
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexImage2DBufferCase(
+ parameterCases[ndx].name + '_2d', '',
+ parameterCases[ndx].format, parameterCases[ndx].width,
+ parameterCases[ndx].height, parameterCases[ndx].rowLength,
+ parameterCases[ndx].skipRows,
+ parameterCases[ndx].skipPixels,
+ parameterCases[ndx].alignment,
+ parameterCases[ndx].offset
+ )
+ );
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexImageCubeBufferCase(
+ parameterCases[ndx].name + '_cube', '',
+ parameterCases[ndx].format, parameterCases[ndx].width,
+ parameterCases[ndx].rowLength, parameterCases[ndx].skipRows,
+ parameterCases[ndx].skipPixels,
+ parameterCases[ndx].alignment, parameterCases[ndx].offset
+ )
+ );
+ }
+
+ // glTexImage2D() depth cases.
+ /** @type {tcuTestCase.DeqpTest} */
+ var shadow2dGroup = new tcuTestCase.DeqpTest(
+ 'teximage2d_depth',
+ 'glTexImage2D() with depth or depth/stencil format'
+ );
+ this.addChild(shadow2dGroup);
+
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++) {
+ // WebGL 2 specific constraint.
+ if (depthStencilFormats[ndx].internalFormat == gl.DEPTH32F_STENCIL8)
+ continue;
+ var tex2DWidth = 64;
+ var tex2DHeight = 128;
+
+ shadow2dGroup.addChild(
+ new es3fTextureSpecificationTests.TexImage2DDepthCase(
+ depthStencilFormats[ndx].name, '',
+ depthStencilFormats[ndx].internalFormat,
+ tex2DWidth, tex2DHeight
+ )
+ );
+ }
+
+ // glTexImage2D() depth cases with pbo.
+ shadow2dGroup = new tcuTestCase.DeqpTest(
+ 'teximage2d_depth_pbo',
+ 'glTexImage2D() with depth or depth/stencil format with pbo'
+ );
+ this.addChild(shadow2dGroup);
+
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++) {
+ tex2DWidth = 64;
+ tex2DHeight = 128;
+
+ shadow2dGroup.addChild(
+ new es3fTextureSpecificationTests.TexImage2DDepthBufferCase(
+ depthStencilFormats[ndx].name, '',
+ depthStencilFormats[ndx].internalFormat,
+ tex2DWidth, tex2DHeight
+ )
+ );
+ }
+
+ // Basic TexSubImage2D usage.
+ splitBasicTex2D = 3;
+ splitBasicTexCube = 5;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */
+ var basicTexSubImageGroup2D = [];
+ for (var ii = 0; ii < splitBasicTex2D; ++ii) {
+ basicTexSubImageGroup2D.push(
+ new tcuTestCase.DeqpTest('basic_texsubimage2d', 'Basic glTexSubImage2D() usage')
+ );
+ this.addChild(basicTexSubImageGroup2D[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */
+ var basicTexSubImageGroupCube = [];
+ for (var ii = 0; ii < splitBasicTexCube; ++ii) {
+ basicTexSubImageGroupCube.push(
+ new tcuTestCase.DeqpTest('basic_texsubimage2d', 'Basic glTexSubImage2D() usage')
+ );
+ this.addChild(basicTexSubImageGroupCube[ii]);
+ }
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ format = colorFormats[formatNdx].internalFormat;
+ tex2DWidth = 64;
+ tex2DHeight = 128;
+ texCubeSize = 64;
+
+ basicTexSubImageGroup2D[formatNdx % splitBasicTex2D].addChild(
+ es3fTextureSpecificationTests.newBasicTexSubImage2DCaseInternal(
+ fmtName + '_2d', '', format, tex2DWidth, tex2DHeight
+ )
+ );
+ basicTexSubImageGroupCube[formatNdx % splitBasicTexCube].addChild(
+ es3fTextureSpecificationTests.newBasicTexImageCubeCaseInternal(
+ fmtName + '_cube', '', format, texCubeSize
+ )
+ );
+ }
+
+ // TexSubImage2D to empty texture.
+ /** @type {tcuTestCase.DeqpTest} */
+ var texSubImageEmptyTexGroup = new tcuTestCase.DeqpTest(
+ 'texsubimage2d_empty_tex',
+ 'glTexSubImage2D() to texture that has storage but no data'
+ );
+ this.addChild(texSubImageEmptyTexGroup);
+ for (var formatNdx = 0; formatNdx < unsizedFormats.length; formatNdx++) {
+ fmtName = unsizedFormats[formatNdx].name;
+ format = unsizedFormats[formatNdx].format;
+ /** @type {number} */
+ var dataType = unsizedFormats[formatNdx].dataType;
+ tex2DWidth = 64;
+ tex2DHeight = 32;
+ texCubeSize = 32;
+
+ texSubImageEmptyTexGroup.addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DEmptyTexCase(
+ fmtName + '_2d', '', format, dataType, tex2DWidth, tex2DHeight
+ )
+ );
+ texSubImageEmptyTexGroup.addChild(
+ new es3fTextureSpecificationTests.TexSubImageCubeEmptyTexCase(
+ fmtName + '_cube', '', format, dataType, texCubeSize
+ )
+ );
+ }
+
+ // TexSubImage2D alignment cases.
+ alignGroup = new tcuTestCase.DeqpTest(
+ 'texsubimage2d_align', 'glTexSubImage2D() unpack alignment tests'
+ );
+ this.addChild(alignGroup);
+
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_1_1', '', gl.R8, 64, 64, 13, 17, 1, 6, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_1_2', '', gl.R8, 64, 64, 13, 17, 1, 6, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_1_4', '', gl.R8, 64, 64, 13, 17, 1, 6, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_1_8', '', gl.R8, 64, 64, 13, 17, 1, 6, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_63_1', '', gl.R8, 64, 64, 1, 9, 63, 30, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_63_2', '', gl.R8, 64, 64, 1, 9, 63, 30, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_63_4', '', gl.R8, 64, 64, 1, 9, 63, 30, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_r8_63_8', '', gl.R8, 64, 64, 1, 9, 63, 30, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba4_51_1', '', gl.RGBA4, 64, 64, 7, 29, 51, 30, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba4_51_2', '', gl.RGBA4, 64, 64, 7, 29, 51, 30, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba4_51_4', '', gl.RGBA4, 64, 64, 7, 29, 51, 30, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba4_51_8', '', gl.RGBA4, 64, 64, 7, 29, 51, 30, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgb8_39_1', '', gl.RGB8, 64, 64, 11, 8, 39, 43, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgb8_39_2', '', gl.RGB8, 64, 64, 11, 8, 39, 43, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgb8_39_4', '', gl.RGB8, 64, 64, 11, 8, 39, 43, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgb8_39_8', '', gl.RGB8, 64, 64, 11, 8, 39, 43, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba8_47_1', '', gl.RGBA8, 64, 64, 10, 1, 47, 27, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba8_47_2', '', gl.RGBA8, 64, 64, 10, 1, 47, 27, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba8_47_4', '', gl.RGBA8, 64, 64, 10, 1, 47, 27, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImage2DAlignCaseInternal(
+ '2d_rgba8_47_8', '', gl.RGBA8, 64, 64, 10, 1, 47, 27, 8
+ )
+ );
+
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_1_1', '', gl.R8, 64, 13, 17, 1, 6, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_1_2', '', gl.R8, 64, 13, 17, 1, 6, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_1_4', '', gl.R8, 64, 13, 17, 1, 6, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_1_8', '', gl.R8, 64, 13, 17, 1, 6, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_63_1', '', gl.R8, 64, 1, 9, 63, 30, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_63_2', '', gl.R8, 64, 1, 9, 63, 30, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_63_4', '', gl.R8, 64, 1, 9, 63, 30, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_r8_63_8', '', gl.R8, 64, 1, 9, 63, 30, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_1', '', gl.RGBA4, 64, 7, 29, 51, 30, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_2', '', gl.RGBA4, 64, 7, 29, 51, 30, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_4', '', gl.RGBA4, 64, 7, 29, 51, 30, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba4_51_8', '', gl.RGBA4, 64, 7, 29, 51, 30, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_1', '', gl.RGB8, 64, 11, 8, 39, 43, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_2', '', gl.RGB8, 64, 11, 8, 39, 43, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_4', '', gl.RGB8, 64, 11, 8, 39, 43, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgb8_39_8', '', gl.RGB8, 64, 11, 8, 39, 43, 8
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_1', '', gl.RGBA8, 64, 10, 1, 47, 27, 1
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_2', '', gl.RGBA8, 64, 10, 1, 47, 27, 2
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_4', '', gl.RGBA8, 64, 10, 1, 47, 27, 4
+ )
+ );
+ alignGroup.addChild(
+ es3fTextureSpecificationTests.newTexSubImageCubeAlignCaseInternal(
+ 'cube_rgba8_47_8', '', gl.RGBA8, 64, 10, 1, 47, 27, 8
+ )
+ );
+
+ // glTexSubImage2D() pixel transfer mode cases.
+ paramGroup = new tcuTestCase.DeqpTest(
+ 'texsubimage2d_unpack_params',
+ 'glTexSubImage2D() pixel transfer mode cases'
+ );
+ this.addChild(paramGroup);
+
+ cases = [{
+ name: 'rgb8_alignment', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 0, skipRows: 0, skipPixels: 0, alignment: 2
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 50, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 0, skipRows: 3, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 36, skipRows: 0, skipPixels: 5, alignment: 4
+ }, {
+ name: 'r8_complex1', format: gl.R8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 64, skipRows: 1, skipPixels: 3, alignment: 1
+ }, {
+ name: 'r8_complex2', format: gl.R8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 64, skipRows: 1, skipPixels: 3, alignment: 2
+ }, {
+ name: 'r8_complex3', format: gl.R8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 64, skipRows: 1, skipPixels: 3, alignment: 4
+ }, {
+ name: 'r8_complex4', format: gl.R8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 64, skipRows: 1, skipPixels: 3, alignment: 8
+ }, {
+ name: 'rgba8_complex1', format: gl.RGBA8, width: 92,
+ height: 84, subX: 13, subY: 19, subW: 56, subH: 61,
+ rowLength: 69, skipRows: 0, skipPixels: 0, alignment: 8
+ }, {
+ name: 'rgba8_complex2', format: gl.RGBA8, width: 92,
+ height: 84, subX: 13, subY: 19, subW: 56, subH: 61,
+ rowLength: 69, skipRows: 0, skipPixels: 7, alignment: 8
+ }, {
+ name: 'rgba8_complex3', format: gl.RGBA8, width: 92,
+ height: 84, subX: 13, subY: 19, subW: 56, subH: 61,
+ rowLength: 69, skipRows: 3, skipPixels: 0, alignment: 8
+ }, {
+ name: 'rgba8_complex4', format: gl.RGBA8, width: 92,
+ height: 84, subX: 13, subY: 19, subW: 56, subH: 61,
+ rowLength: 69, skipRows: 3, skipPixels: 7, alignment: 8
+ }, {
+ name: 'rgba32f_complex', format: gl.RGBA32F, width: 92,
+ height: 84, subX: 13, subY: 19, subW: 56, subH: 61,
+ rowLength: 69, skipRows: 3, skipPixels: 7, alignment: 8
+ }
+ ];
+
+ for (var ndx = 0; ndx < cases.length; ndx++)
+ paramGroup.addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DParamsCase(
+ cases[ndx].name, '', cases[ndx].format, cases[ndx].width,
+ cases[ndx].height, cases[ndx].subX, cases[ndx].subY,
+ cases[ndx].subW, cases[ndx].subH, cases[ndx].rowLength,
+ cases[ndx].skipRows, cases[ndx].skipPixels,
+ cases[ndx].alignment
+ )
+ );
+
+ // glTexSubImage2D() PBO cases.
+ splitPboTex2D = 2;
+ splitPboTexCube = 5;
+ pboGroup2D = [];
+ for (var ii = 0; ii < splitPboTex2D; ++ii) {
+ pboGroup2D.push(new tcuTestCase.DeqpTest(
+ 'texsubimage2d_pbo',
+ 'glTexSubImage2D() pixel buffer object tests'
+ ));
+ this.addChild(pboGroup2D[ii]);
+ }
+ pboGroupCube = [];
+ for (var ii = 0; ii < splitPboTexCube; ++ii) {
+ pboGroupCube.push(new tcuTestCase.DeqpTest(
+ 'texsubimage2d_pbo',
+ 'glTexSubImage2D() pixel buffer object tests'
+ ));
+ this.addChild(pboGroupCube[ii]);
+ }
+
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ pboGroup2D[ndx % splitPboTex2D].addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DBufferCase(
+ colorFormats[ndx].name + '_2d', '',
+ colorFormats[ndx].internalFormat,
+ 54, // Width
+ 60, // Height
+ 11, // Sub X
+ 7, // Sub Y
+ 31, // Sub W
+ 30, // Sub H
+ 0, // Row len
+ 0, // Skip rows
+ 0, // Skip pixels
+ 4, // Alignment
+ 0 /* offset */
+ )
+ );
+ pboGroupCube[ndx % splitPboTexCube].addChild(
+ new es3fTextureSpecificationTests.TexSubImageCubeBufferCase(
+ colorFormats[ndx].name + '_cube', '',
+ colorFormats[ndx].internalFormat,
+ 64, // Size
+ 11, // Sub X
+ 7, // Sub Y
+ 31, // Sub W
+ 30, // Sub H
+ 0, // Row len
+ 0, // Skip rows
+ 0, // Skip pixels
+ 4, // Alignment
+ 0 /* offset */
+ )
+ );
+ }
+
+ pboGroupParams = new tcuTestCase.DeqpTest(
+ 'texsubimage2d_pbo',
+ 'glTexSubImage2D() pixel buffer object tests'
+ );
+ this.addChild(pboGroupParams);
+ /** @type {Array<{name: string, format: number, width: number,
+ * height: number, subX: number, subY: number,
+ * subW: number, subH: number, rowLength: number, skipRows: number,
+ * skipPixels: number, alignment: number, offset: number}>}
+ */
+ var paramCases = [{
+ name: 'rgb8_offset', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 0, skipRows: 0, skipPixels: 0,
+ alignment: 4, offset: 67
+ }, {
+ name: 'rgb8_alignment', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 0, skipRows: 0, skipPixels: 0,
+ alignment: 2, offset: 0
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 50, skipRows: 0, skipPixels: 0,
+ alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 0, skipRows: 3, skipPixels: 0,
+ alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 54,
+ height: 60, subX: 11, subY: 7, subW: 31, subH: 30,
+ rowLength: 36, skipRows: 0, skipPixels: 5,
+ alignment: 4, offset: 0
+ }
+ ];
+
+ for (var ndx = 0; ndx < paramCases.length; ndx++) {
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DBufferCase(
+ paramCases[ndx].name + '_2d', '',
+ paramCases[ndx].format,
+ paramCases[ndx].width,
+ paramCases[ndx].height,
+ paramCases[ndx].subX,
+ paramCases[ndx].subY,
+ paramCases[ndx].subW,
+ paramCases[ndx].subH,
+ paramCases[ndx].rowLength,
+ paramCases[ndx].skipRows,
+ paramCases[ndx].skipPixels,
+ paramCases[ndx].alignment,
+ paramCases[ndx].offset));
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexSubImageCubeBufferCase(
+ paramCases[ndx].name + '_cube', '',
+ paramCases[ndx].format,
+ paramCases[ndx].width,
+ paramCases[ndx].subX,
+ paramCases[ndx].subY,
+ paramCases[ndx].subW,
+ paramCases[ndx].subH,
+ paramCases[ndx].rowLength,
+ paramCases[ndx].skipRows,
+ paramCases[ndx].skipPixels,
+ paramCases[ndx].alignment,
+ paramCases[ndx].offset
+ )
+ );
+ }
+
+ // glTexSubImage2D() depth cases.
+ shadow2dGroup = new tcuTestCase.DeqpTest(
+ 'texsubimage2d_depth',
+ 'glTexSubImage2D() with depth or depth/stencil format'
+ );
+ this.addChild(shadow2dGroup);
+
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++) {
+ // WebGL 2 specific constraint.
+ if (depthStencilFormats[ndx].internalFormat == gl.DEPTH32F_STENCIL8)
+ continue;
+ tex2DWidth = 64;
+ tex2DHeight = 32;
+
+ shadow2dGroup.addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DDepthCase(
+ depthStencilFormats[ndx].name, '',
+ depthStencilFormats[ndx].internalFormat,
+ tex2DWidth, tex2DHeight
+ )
+ );
+ }
+
+ // Basic glCopyTexImage2D() cases
+ /** @type {tcuTestCase.DeqpTest} */
+ var copyTexImageGroup = new tcuTestCase.DeqpTest(
+ 'basic_copyteximage2d', 'Basic glCopyTexImage2D() usage'
+ );
+ this.addChild(copyTexImageGroup);
+
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImage2DCase(
+ '2d_alpha', '', gl.ALPHA, 128, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImage2DCase(
+ '2d_luminance', '', gl.LUMINANCE, 128, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImage2DCase(
+ '2d_luminance_alpha', '', gl.LUMINANCE_ALPHA, 128, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImage2DCase(
+ '2d_rgb', '', gl.RGB, 128, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImage2DCase(
+ '2d_rgba', '', gl.RGBA, 128, 64
+ )
+ );
+
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImageCubeCase(
+ 'cube_alpha', '', gl.ALPHA, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImageCubeCase(
+ 'cube_luminance', '', gl.LUMINANCE, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImageCubeCase(
+ 'cube_luminance_alpha', '', gl.LUMINANCE_ALPHA, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImageCubeCase(
+ 'cube_rgb', '', gl.RGB, 64
+ )
+ );
+ copyTexImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexImageCubeCase(
+ 'cube_rgba', '', gl.RGBA, 64
+ )
+ );
+
+ // Basic glCopyTexSubImage2D() cases
+ /** @type {tcuTestCase.DeqpTest} */
+ var copyTexSubImageGroup = new tcuTestCase.DeqpTest(
+ 'basic_copytexsubimage2d', 'Basic glCopyTexSubImage2D() usage'
+ );
+ this.addChild(copyTexSubImageGroup);
+
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase(
+ '2d_alpha', '', gl.ALPHA, gl.UNSIGNED_BYTE, 128, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase(
+ '2d_luminance', '', gl.LUMINANCE, gl.UNSIGNED_BYTE, 128, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase(
+ '2d_luminance_alpha', '', gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, 128, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase(
+ '2d_rgb', '', gl.RGB, gl.UNSIGNED_BYTE, 128, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImage2DCase(
+ '2d_rgba', '', gl.RGBA, gl.UNSIGNED_BYTE, 128, 64
+ )
+ );
+
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase(
+ 'cube_alpha', '', gl.ALPHA, gl.UNSIGNED_BYTE, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase(
+ 'cube_luminance', '', gl.LUMINANCE, gl.UNSIGNED_BYTE, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase(
+ 'cube_luminance_alpha', '', gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase(
+ 'cube_rgb', '', gl.RGB, gl.UNSIGNED_BYTE, 64
+ )
+ );
+ copyTexSubImageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicCopyTexSubImageCubeCase(
+ 'cube_rgba', '', gl.RGBA, gl.UNSIGNED_BYTE, 64
+ )
+ );
+
+ // Basic TexImage3D usage.
+ var splitBasicTex2DArray = 3, splitBasicTex3D = 5;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */
+ var basicTexImageGroup2DArray = [];
+ for (var ii = 0; ii < splitBasicTex2DArray; ++ii) {
+ basicTexImageGroup2DArray.push(
+ new tcuTestCase.DeqpTest('basic_teximage3d', 'Basic glTexImage3D() usage')
+ );
+ this.addChild(basicTexImageGroup2DArray[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */
+ var basicTexImageGroup3D = [];
+ for (var ii = 0; ii < splitBasicTex3D; ++ii) {
+ basicTexImageGroup3D.push(
+ new tcuTestCase.DeqpTest('basic_teximage3d', 'Basic glTexImage3D() usage')
+ );
+ this.addChild(basicTexImageGroup3D[ii]);
+ }
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ format = colorFormats[formatNdx].internalFormat;
+ /** @type {number} */ var tex2DArrayWidth = 57;
+ /** @type {number} */ var tex2DArrayHeight = 44;
+ /** @type {number} */ var tex2DArrayLevels = 5;
+ /** @type {number} */ var tex3DWidth = 63;
+ /** @type {number} */ var tex3DHeight = 29;
+ /** @type {number} */ var tex3DDepth = 11;
+
+ basicTexImageGroup2DArray[formatNdx % splitBasicTex2DArray].addChild(
+ new es3fTextureSpecificationTests.BasicTexImage2DArrayCase(
+ fmtName + '_2d_array', '', format,
+ tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLevels
+ )
+ );
+ basicTexImageGroup3D[formatNdx % splitBasicTex3D].addChild(
+ new es3fTextureSpecificationTests.BasicTexImage3DCase(
+ fmtName + '_3d', '', format,
+ tex3DWidth, tex3DHeight, tex3DDepth
+ )
+ );
+ }
+
+ // glTexImage3D() unpack params cases.
+ paramGroup = new tcuTestCase.DeqpTest(
+ 'teximage3d_unpack_params', 'glTexImage3D() unpack parameters'
+ );
+ this.addChild(paramGroup);
+
+ cases = [{
+ name: 'rgb8_image_height', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 26, rowLength: 0,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 27,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_images', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 0,
+ skipImages: 3, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 22, rowLength: 0,
+ skipImages: 0, skipRows: 3, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 25,
+ skipImages: 0, skipRows: 0, skipPixels: 2, alignment: 4
+ }, {
+ name: 'r8_complex1', format: gl.R8, width: 13,
+ height: 17, depth: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 1
+ }, {
+ name: 'r8_complex2', format: gl.R8, width: 13,
+ height: 17, depth: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 2
+ }, {
+ name: 'r8_complex3', format: gl.R8, width: 13,
+ height: 17, depth: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 4
+ }, {
+ name: 'r8_complex4', format: gl.R8, width: 13,
+ height: 17, depth: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 8
+ }, {
+ name: 'rgba8_complex1', format: gl.RGBA8, width: 11,
+ height: 20, depth: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 8
+ }, {
+ name: 'rgba8_complex2', format: gl.RGBA8, width: 11,
+ height: 20, depth: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 2, skipPixels: 0, alignment: 8
+ }, {
+ name: 'rgba8_complex3', format: gl.RGBA8, width: 11,
+ height: 20, depth: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 0, skipPixels: 3, alignment: 8
+ }, {
+ name: 'rgba8_complex4', format: gl.RGBA8, width: 11,
+ height: 20, depth: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 2, skipPixels: 3, alignment: 8
+ }, {
+ name: 'rgba32f_complex', format: gl.RGBA32F, width: 11,
+ height: 20, depth: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 2, skipPixels: 3, alignment: 8
+ }
+ ];
+
+ for (var ndx = 0; ndx < cases.length; ndx++)
+ paramGroup.addChild(
+ new es3fTextureSpecificationTests.TexImage3DParamsCase(
+ cases[ndx].name, '', cases[ndx].format, cases[ndx].width,
+ cases[ndx].height, cases[ndx].depth, cases[ndx].imageHeight,
+ cases[ndx].rowLength, cases[ndx].skipImages,
+ cases[ndx].skipRows, cases[ndx].skipPixels,
+ cases[ndx].alignment
+ )
+ );
+
+ // glTexImage3D() pbo cases.
+ var splitTex2DArray = 2, splitTex3D = 2;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var pboGroup2DArray = [];
+ for (var ii = 0; ii < splitTex2DArray; ++ii) {
+ pboGroup2DArray.push(
+ new tcuTestCase.DeqpTest('teximage3d_pbo', 'glTexImage3D() from PBO')
+ );
+ this.addChild(pboGroup2DArray[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var pboGroup3D = [];
+ for (var ii = 0; ii < splitTex3D; ++ii) {
+ pboGroup3D.push(
+ new tcuTestCase.DeqpTest('teximage3d_pbo', 'glTexImage3D() from PBO')
+ );
+ this.addChild(pboGroup3D[ii]);
+ }
+
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ format = colorFormats[formatNdx].internalFormat;
+ tex3DWidth = 11;
+ tex3DHeight = 20;
+ tex3DDepth = 8;
+
+ pboGroup2DArray[formatNdx % splitTex2DArray].addChild(
+ new es3fTextureSpecificationTests.TexImage2DArrayBufferCase(
+ fmtName + '_2d_array', '', format, tex3DWidth, tex3DHeight,
+ tex3DDepth, 0, 0, 0, 0, 0, 4, 0
+ )
+ );
+ pboGroup3D[formatNdx % splitTex3D].addChild(
+ new es3fTextureSpecificationTests.TexImage3DBufferCase(
+ fmtName + '_3d', '', format, tex3DWidth, tex3DHeight,
+ tex3DDepth, 0, 0, 0, 0, 0, 4, 0
+ )
+ );
+ }
+
+ // Parameter cases
+ parameterCases = [{
+ name: 'rgb8_offset', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 0,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 1,
+ offset: 67
+ }, {
+ name: 'rgb8_alignment', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 0,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 2,
+ offset: 0
+ }, {
+ name: 'rgb8_image_height', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 26, rowLength: 0,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 4,
+ offset: 0
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 27,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 4,
+ offset: 0
+ }, {
+ name: 'rgb8_skip_images', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 0,
+ skipImages: 3, skipRows: 0, skipPixels: 0, alignment: 4,
+ offset: 0
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 22, rowLength: 0,
+ skipImages: 0, skipRows: 3, skipPixels: 0, alignment: 4,
+ offset: 0
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 23,
+ height: 19, depth: 8, imageHeight: 0, rowLength: 25,
+ skipImages: 0, skipRows: 0, skipPixels: 2, alignment: 4,
+ offset: 0
+ }
+ ];
+
+ pboGroupParams = new tcuTestCase.DeqpTest('teximage3d_pbo', 'glTexImage3D() from PBO');
+ this.addChild(pboGroupParams);
+ for (var ndx = 0; ndx < parameterCases.length; ndx++) {
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexImage2DArrayBufferCase(
+ parameterCases[ndx].name + '_2d_array', '',
+ parameterCases[ndx].format, parameterCases[ndx].width,
+ parameterCases[ndx].height, parameterCases[ndx].depth,
+ parameterCases[ndx].imageHeight,
+ parameterCases[ndx].rowLength,
+ parameterCases[ndx].skipImages,
+ parameterCases[ndx].skipRows,
+ parameterCases[ndx].skipPixels,
+ parameterCases[ndx].alignment, parameterCases[ndx].offset
+ )
+ );
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexImage3DBufferCase(
+ parameterCases[ndx].name + '_3d', '',
+ parameterCases[ndx].format, parameterCases[ndx].width,
+ parameterCases[ndx].height, parameterCases[ndx].depth,
+ parameterCases[ndx].imageHeight,
+ parameterCases[ndx].rowLength,
+ parameterCases[ndx].skipImages,
+ parameterCases[ndx].skipRows,
+ parameterCases[ndx].skipPixels,
+ parameterCases[ndx].alignment, parameterCases[ndx].offset
+ )
+ );
+ }
+
+ // glTexImage3D() depth cases.
+ /** @type {tcuTestCase.DeqpTest} */
+ var shadow3dGroup = new tcuTestCase.DeqpTest(
+ 'teximage3d_depth',
+ 'glTexImage3D() with depth or depth/stencil format'
+ );
+ this.addChild(shadow3dGroup);
+
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++) {
+ // WebGL 2 specific constraint.
+ if (depthStencilFormats[ndx].internalFormat == gl.DEPTH32F_STENCIL8)
+ continue;
+ tex3DWidth = 32;
+ tex3DHeight = 64;
+ tex3DDepth = 8;
+
+ shadow3dGroup.addChild(
+ new es3fTextureSpecificationTests.TexImage2DArrayDepthCase(
+ depthStencilFormats[ndx].name + '_2d_array', '',
+ depthStencilFormats[ndx].internalFormat,
+ tex3DWidth, tex3DHeight, tex3DDepth
+ )
+ );
+ }
+
+ // glTexImage3D() depth cases with pbo.
+ shadow3dGroup = new tcuTestCase.DeqpTest(
+ 'teximage3d_depth_pbo',
+ 'glTexImage3D() with depth or depth/stencil format with pbo'
+ );
+ this.addChild(shadow3dGroup);
+
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++) {
+ tex3DWidth = 32;
+ tex3DHeight = 64;
+ tex3DDepth = 8;
+
+ shadow3dGroup.addChild(
+ new es3fTextureSpecificationTests.TexImage2DArrayDepthBufferCase(
+ depthStencilFormats[ndx].name + '_2d_array', '',
+ depthStencilFormats[ndx].internalFormat,
+ tex3DWidth, tex3DHeight, tex3DDepth
+ )
+ );
+ }
+
+ // Basic TexSubImage3D usage.
+ splitTex3D = 5;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var basicTexSubImageGroup = [];
+ for (var ii = 0; ii < splitTex3D; ++ii) {
+ basicTexSubImageGroup.push(
+ new tcuTestCase.DeqpTest('basic_texsubimage3d', 'Basic glTexSubImage3D() usage')
+ );
+ this.addChild(basicTexSubImageGroup[ii]);
+ }
+
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ format = colorFormats[formatNdx].internalFormat;
+ tex3DWidth = 32;
+ tex3DHeight = 64;
+ tex3DDepth = 8;
+
+ basicTexSubImageGroup[formatNdx % splitTex3D].addChild(
+ new es3fTextureSpecificationTests.BasicTexSubImage3DCase(
+ fmtName + '_3d', '', format,
+ tex3DWidth, tex3DHeight, tex3DDepth
+ )
+ );
+ }
+
+ // glTexSubImage3D() unpack params cases.
+ paramGroup = new tcuTestCase.DeqpTest(
+ 'texsubimage3d_unpack_params', 'glTexSubImage3D() unpack parameters'
+ );
+ this.addChild(paramGroup);
+
+ /** @type {Array<{name: string, format: number, width: number,
+ * height: number, depth: number, subX: number, subY: number,
+ * subZ: number, subW: number, subH: number, subD: number,
+ * imageHeight: number, rowLength: number, skipImages: number,
+ * skipRows: number, skipPixels: number, alignment: number}>}
+ */
+ var casesSubImage3D = [{
+ name: 'rgb8_image_height', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 26, rowLength: 0,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 27,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_images', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 0,
+ skipImages: 3, skipRows: 0, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 22, rowLength: 0,
+ skipImages: 0, skipRows: 3, skipPixels: 0, alignment: 4
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 25,
+ skipImages: 0, skipRows: 0, skipPixels: 2, alignment: 4
+ }, {
+ name: 'r8_complex1', format: gl.R8, width: 15,
+ height: 20, depth: 11, subX: 1, subY: 1, subZ: 0, subW: 13,
+ subH: 17, subD: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 1
+ }, {
+ name: 'r8_complex2', format: gl.R8, width: 15,
+ height: 20, depth: 11, subX: 1, subY: 1, subZ: 0, subW: 13,
+ subH: 17, subD: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 2
+ }, {
+ name: 'r8_complex3', format: gl.R8, width: 15,
+ height: 20, depth: 11, subX: 1, subY: 1, subZ: 0, subW: 13,
+ subH: 17, subD: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 4
+ }, {
+ name: 'r8_complex4', format: gl.R8, width: 15,
+ height: 20, depth: 11, subX: 1, subY: 1, subZ: 0, subW: 13,
+ subH: 17, subD: 11, imageHeight: 23, rowLength: 15,
+ skipImages: 2, skipRows: 3, skipPixels: 1, alignment: 8
+ }, {
+ name: 'rgba8_complex1', format: gl.RGBA8, width: 15,
+ height: 25, depth: 10, subX: 0, subY: 5, subZ: 1, subW: 11,
+ subH: 20, subD: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 0, skipPixels: 0, alignment: 8
+ }, {
+ name: 'rgba8_complex2', format: gl.RGBA8, width: 15,
+ height: 25, depth: 10, subX: 0, subY: 5, subZ: 1, subW: 11,
+ subH: 20, subD: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 2, skipPixels: 0, alignment: 8
+ }, {
+ name: 'rgba8_complex3', format: gl.RGBA8, width: 15,
+ height: 25, depth: 10, subX: 0, subY: 5, subZ: 1, subW: 11,
+ subH: 20, subD: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 0, skipPixels: 3, alignment: 8
+ }, {
+ name: 'rgba8_complex4', format: gl.RGBA8, width: 15,
+ height: 25, depth: 10, subX: 0, subY: 5, subZ: 1, subW: 11,
+ subH: 20, subD: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 2, skipPixels: 3, alignment: 8
+ }, {
+ name: 'rgba32f_complex', format: gl.RGBA32F, width: 15,
+ height: 25, depth: 10, subX: 0, subY: 5, subZ: 1, subW: 11,
+ subH: 20, subD: 8, imageHeight: 25, rowLength: 14,
+ skipImages: 0, skipRows: 2, skipPixels: 3, alignment: 8
+ }
+ ];
+
+ for (var ndx = 0; ndx < casesSubImage3D.length; ndx++)
+ paramGroup.addChild(
+ new es3fTextureSpecificationTests.TexSubImage3DParamsCase(
+ casesSubImage3D[ndx].name, '', casesSubImage3D[ndx].format,
+ casesSubImage3D[ndx].width, casesSubImage3D[ndx].height, casesSubImage3D[ndx].depth,
+ casesSubImage3D[ndx].subX, casesSubImage3D[ndx].subY, casesSubImage3D[ndx].subZ,
+ casesSubImage3D[ndx].subW, casesSubImage3D[ndx].subH, casesSubImage3D[ndx].subD,
+ casesSubImage3D[ndx].imageHeight, casesSubImage3D[ndx].rowLength,
+ casesSubImage3D[ndx].skipImages, casesSubImage3D[ndx].skipRows,
+ casesSubImage3D[ndx].skipPixels, casesSubImage3D[ndx].alignment
+ )
+ );
+
+ // glTexSubImage3D() PBO cases.
+ splitTex2DArray = 2;
+ pboGroup2DArray = [];
+ for (var ii = 0; ii < splitTex2DArray; ++ii) {
+ pboGroup2DArray.push(
+ new tcuTestCase.DeqpTest('texsubimage3d_pbo', 'glTexSubImage3D() pixel buffer object tests')
+ );
+ this.addChild(pboGroup2DArray[ii]);
+ }
+
+ splitTex3D = 2;
+ pboGroup3D = [];
+ for (var ii = 0; ii < splitTex3D; ++ii) {
+ pboGroup3D.push(
+ new tcuTestCase.DeqpTest('texsubimage3d_pbo', 'glTexSubImage3D() pixel buffer object tests')
+ );
+ this.addChild(pboGroup3D[ii]);
+ }
+
+ for (var ndx = 0; ndx < colorFormats.length; ndx++) {
+ pboGroup2DArray[ndx % splitTex2DArray].addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DArrayBufferCase(
+ colorFormats[ndx].name + '_2d_array', '',
+ colorFormats[ndx].internalFormat,
+ 26, // Width
+ 25, // Height
+ 10, // Depth
+ 1, // Sub X
+ 2, // Sub Y
+ 0, // Sub Z
+ 23, // Sub W
+ 19, // Sub H
+ 8, // Sub D
+ 0, // Image height
+ 0, // Row length
+ 0, // Skip images
+ 0, // Skip rows
+ 0, // Skip pixels
+ 4, // Alignment
+ 0 // offset
+ )
+ );
+ pboGroup3D[ndx % splitTex3D].addChild(
+ new es3fTextureSpecificationTests.TexSubImage3DBufferCase(
+ colorFormats[ndx].name + '_3d', '',
+ colorFormats[ndx].internalFormat,
+ 26, // Width
+ 25, // Height
+ 10, // Depth
+ 1, // Sub X
+ 2, // Sub Y
+ 0, // Sub Z
+ 23, // Sub W
+ 19, // Sub H
+ 8, // Sub D
+ 0, // Image height
+ 0, // Row length
+ 0, // Skip images
+ 0, // Skip rows
+ 0, // Skip pixels
+ 4, // Alignment
+ 0 // offset
+ )
+ );
+ }
+
+ paramCases = [{
+ name: 'rgb8_offset', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 0, skipImages: 0,
+ skipRows: 0, skipPixels: 0, alignment: 4, offset: 67
+ }, {
+ name: 'rgb8_image_height', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 26, rowLength: 0, skipImages: 0,
+ skipRows: 0, skipPixels: 0, alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_row_length', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 27, skipImages: 0,
+ skipRows: 0, skipPixels: 0, alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_images', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 0, skipImages: 3,
+ skipRows: 0, skipPixels: 0, alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_rows', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 22, rowLength: 0, skipImages: 0,
+ skipRows: 3, skipPixels: 0, alignment: 4, offset: 0
+ }, {
+ name: 'rgb8_skip_pixels', format: gl.RGB8, width: 26,
+ height: 25, depth: 10, subX: 1, subY: 2, subZ: 1, subW: 23,
+ subH: 19, subD: 8, imageHeight: 0, rowLength: 25, skipImages: 0,
+ skipRows: 0, skipPixels: 2, alignment: 4, offset: 0
+ }
+ ];
+
+ pboGroupParams = new tcuTestCase.DeqpTest(
+ 'texsubimage3d_pbo', 'glTexSubImage3D() pixel buffer object tests'
+ );
+ this.addChild(pboGroupParams);
+
+ for (var ndx = 0; ndx < paramCases.length; ndx++) {
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DArrayBufferCase(
+ paramCases[ndx].name + '_2d_array', '',
+ paramCases[ndx].format, paramCases[ndx].width,
+ paramCases[ndx].height, paramCases[ndx].depth,
+ paramCases[ndx].subX, paramCases[ndx].subY,
+ paramCases[ndx].subZ, paramCases[ndx].subW,
+ paramCases[ndx].subH, paramCases[ndx].subD,
+ paramCases[ndx].imageHeight, paramCases[ndx].rowLength,
+ paramCases[ndx].skipImages, paramCases[ndx].skipRows,
+ paramCases[ndx].skipPixels, paramCases[ndx].alignment,
+ paramCases[ndx].offset
+ )
+ );
+ pboGroupParams.addChild(
+ new es3fTextureSpecificationTests.TexSubImage3DBufferCase(
+ paramCases[ndx].name + '_3d', '',
+ paramCases[ndx].format, paramCases[ndx].width,
+ paramCases[ndx].height, paramCases[ndx].depth,
+ paramCases[ndx].subX, paramCases[ndx].subY,
+ paramCases[ndx].subZ, paramCases[ndx].subW,
+ paramCases[ndx].subH, paramCases[ndx].subD,
+ paramCases[ndx].imageHeight, paramCases[ndx].rowLength,
+ paramCases[ndx].skipImages, paramCases[ndx].skipRows,
+ paramCases[ndx].skipPixels, paramCases[ndx].alignment,
+ paramCases[ndx].offset
+ )
+ );
+ }
+
+ // glTexSubImage3D() depth cases.
+ shadow3dGroup = new tcuTestCase.DeqpTest(
+ 'texsubimage3d_depth',
+ 'glTexSubImage3D() with depth or depth/stencil format'
+ );
+ this.addChild(shadow3dGroup);
+
+ for (var ndx = 0; ndx < depthStencilFormats.length; ndx++) {
+ // WebGL 2 specific constraint.
+ if (depthStencilFormats[ndx].internalFormat == gl.DEPTH32F_STENCIL8)
+ continue;
+ tex2DArrayWidth = 57;
+ tex2DArrayHeight = 44;
+ tex2DArrayLevels = 5;
+
+ shadow3dGroup.addChild(
+ new es3fTextureSpecificationTests.TexSubImage2DArrayDepthCase(
+ depthStencilFormats[ndx].name + '_2d_array', '',
+ depthStencilFormats[ndx].internalFormat, tex2DArrayWidth,
+ tex2DArrayHeight, tex2DArrayLevels
+ )
+ );
+ }
+
+ // glTexStorage2D() cases.
+
+ // Color formats
+ var splitStorage2D = 3, splitStorageCube = 5;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var colorFormatGroup2D = [];
+ for (var ii = 0; ii < splitStorage2D; ++ii) {
+ colorFormatGroup2D.push(
+ new tcuTestCase.DeqpTest('texstorage2d.format', 'glTexStorage2D() with all formats')
+ );
+ this.addChild(colorFormatGroup2D[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var colorFormatGroupCube = [];
+ for (var ii = 0; ii < splitStorageCube; ++ii) {
+ colorFormatGroupCube.push(
+ new tcuTestCase.DeqpTest('texstorage2d.format', 'glTexStorage2D() with all formats')
+ );
+ this.addChild(colorFormatGroupCube[ii]);
+ }
+
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ /** @type {number} */ var internalFormat = colorFormats[formatNdx].internalFormat;
+ var tex2DWidth = 117;
+ var tex2DHeight = 97;
+ var tex2DLevels = es3fTextureSpecificationTests.maxLevelCount(tex2DWidth, tex2DHeight);
+ /** @type {number} */ var cubeSize = 57;
+ /** @type {number} */
+ var cubeLevels = es3fTextureSpecificationTests.maxLevelCount(
+ cubeSize, cubeSize
+ );
+
+ colorFormatGroup2D[formatNdx % splitStorage2D].addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage2DCase(
+ fmtName + '_2d', '', internalFormat,
+ tex2DWidth, tex2DHeight, tex2DLevels
+ )
+ );
+ colorFormatGroupCube[formatNdx % splitStorageCube].addChild(
+ new es3fTextureSpecificationTests.BasicTexStorageCubeCase(
+ fmtName + '_cube', '', internalFormat, cubeSize, cubeLevels
+ )
+ );
+ }
+
+ // Depth / stencil formats.
+ /** @type {tcuTestCase.DeqpTest} */
+ var storageGroup = new tcuTestCase.DeqpTest(
+ 'texstorage2d.format',
+ 'glTexStorage2D() with all formats'
+ );
+ this.addChild(storageGroup);
+
+ for (var formatNdx = 0; formatNdx < depthStencilFormats.length; formatNdx++) {
+ fmtName = depthStencilFormats[formatNdx].name;
+ internalFormat = depthStencilFormats[formatNdx].internalFormat;
+ // WebGL 2 specific constraint.
+ if (internalFormat == gl.DEPTH32F_STENCIL8)
+ continue;
+
+ tex2DWidth = 117;
+ tex2DHeight = 97;
+ tex2DLevels = es3fTextureSpecificationTests.maxLevelCount(
+ tex2DWidth, tex2DHeight
+ );
+ cubeSize = 57;
+ cubeLevels = es3fTextureSpecificationTests.maxLevelCount(
+ cubeSize, cubeSize
+ );
+
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage2DCase(
+ fmtName + '_2d', '', internalFormat,
+ tex2DWidth, tex2DHeight, tex2DLevels
+ )
+ );
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorageCubeCase(
+ fmtName + '_cube', '', internalFormat, cubeSize, cubeLevels
+ )
+ );
+ }
+
+ // Sizes.
+ storageGroup = new tcuTestCase.DeqpTest(
+ 'texstorage2d.size',
+ 'glTexStorage2D() with various sizes'
+ );
+ this.addChild(storageGroup);
+
+ // W H L
+ /** @type {Array<{width: number, height: number, levels: number}>} */
+ var tex2DSizes = [{
+ width: 1, height: 1, levels: 1
+ }, {
+ width: 2, height: 2, levels: 2
+ }, {
+ width: 64, height: 32, levels: 7
+ }, {
+ width: 32, height: 64, levels: 4
+ }, {
+ width: 57, height: 63, levels: 1
+ }, {
+ width: 57, height: 63, levels: 2
+ }, {
+ width: 57, height: 63, levels: 6
+ }
+ ];
+
+ // S L
+ /** @type {Array<{sizes: number, levels: number}>} */
+ var cubeSizes = [{
+ sizes: 1, levels: 1
+ }, {
+ sizes: 2, levels: 2
+ }, {
+ sizes: 57, levels: 1
+ }, {
+ sizes: 57, levels: 2
+ }, {
+ sizes: 57, levels: 6
+ }, {
+ sizes: 64, levels: 4
+ }, {
+ sizes: 64, levels: 7
+ }
+ ];
+
+ for (var ndx = 0; ndx < tex2DSizes.length; ndx++) {
+ format = gl.RGBA8;
+ /** @type {number} */ var width = tex2DSizes[ndx].width;
+ /** @type {number} */ var height = tex2DSizes[ndx].height;
+ /** @type {number} */ var levels = tex2DSizes[ndx].levels;
+ /** @type {string} */
+ var name = '2d_' + width + 'x' + height + '_' + levels + '_levels';
+
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage2DCase(
+ name, '', format, width, height, levels
+ )
+ );
+ }
+
+ for (var ndx = 0; ndx < cubeSizes.length; ndx++) {
+ format = gl.RGBA8;
+ size = cubeSizes[ndx].sizes;
+ levels = cubeSizes[ndx].levels;
+ name = 'cube_' + size + 'x' + size + '_' + levels + '_levels';
+
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorageCubeCase(
+ name, '', format, size, levels
+ )
+ );
+ }
+
+ // glTexStorage3D() cases.
+
+ // Color formats.
+ var splitStorage2DArray = 3, splitStorage3D = 4;
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var colorFormatGroup2DArray = [];
+ for (var ii = 0; ii < splitStorage2DArray; ++ii) {
+ colorFormatGroup2DArray.push(
+ new tcuTestCase.DeqpTest('texstorage3d.format', 'glTexStorage3D() with all formats')
+ );
+ this.addChild(colorFormatGroup2DArray[ii]);
+ }
+ /** @type {Array<{tcuTestCase.DeqpTest}>} */ var colorFormatGroup3D = [];
+ for (var ii = 0; ii < splitStorage3D; ++ii) {
+ colorFormatGroup3D.push(
+ new tcuTestCase.DeqpTest('texstorage3d.format', 'glTexStorage3D() with all formats')
+ );
+ this.addChild(colorFormatGroup3D[ii]);
+ }
+
+ // Color formats.
+ for (var formatNdx = 0; formatNdx < colorFormats.length; formatNdx++) {
+ fmtName = colorFormats[formatNdx].name;
+ internalFormat = colorFormats[formatNdx].internalFormat;
+ tex2DArrayWidth = 57;
+ tex2DArrayHeight = 13;
+ var tex2DArrayLayers = 7;
+ tex2DArrayLevels = es3fTextureSpecificationTests.maxLevelCount(
+ tex2DArrayWidth, tex2DArrayHeight
+ );
+ tex3DWidth = 59;
+ tex3DHeight = 37;
+ tex3DDepth = 11;
+ var tex3DLevels = es3fTextureSpecificationTests.maxLevelCount(
+ tex3DWidth, tex3DHeight, tex3DDepth
+ );
+
+ colorFormatGroup2DArray[formatNdx % splitStorage2DArray].addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage2DArrayCase(
+ fmtName + '_2d_array', '', internalFormat, tex2DArrayWidth,
+ tex2DArrayHeight, tex2DArrayLayers, tex2DArrayLevels
+ )
+ );
+ colorFormatGroup3D[formatNdx % splitStorage3D].addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage3DCase(
+ fmtName + '_3d', '', internalFormat, tex3DWidth,
+ tex3DHeight, tex3DDepth, tex3DLevels
+ )
+ );
+ }
+
+ storageGroup = new tcuTestCase.DeqpTest(
+ 'texstorage3d.format',
+ 'glTexStorage3D() with all formats'
+ );
+ this.addChild(storageGroup);
+
+ // Depth/stencil formats (only 2D texture array is supported).
+ for (var formatNdx = 0;
+ formatNdx < depthStencilFormats.length;
+ formatNdx++) {
+ fmtName = depthStencilFormats[formatNdx].name;
+ internalFormat = depthStencilFormats[formatNdx].internalFormat;
+ // WebGL 2 specific constraint.
+ if (internalFormat == gl.DEPTH32F_STENCIL8)
+ continue;
+
+ tex2DArrayWidth = 57;
+ tex2DArrayHeight = 13;
+ tex2DArrayLayers = 7;
+ tex2DArrayLevels = es3fTextureSpecificationTests.maxLevelCount(
+ tex2DArrayWidth, tex2DArrayHeight
+ );
+
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage2DArrayCase(
+ fmtName + '_2d_array', '', internalFormat, tex2DArrayWidth,
+ tex2DArrayHeight, tex2DArrayLayers, tex2DArrayLevels
+ )
+ );
+ }
+
+ // Sizes.
+ // W H La Le
+ /**
+ * @type {Array<{width: number, height: number,
+ * layers: number, levels: number}>}
+ */
+ var tex2DArraySizes = [{
+ width: 1, height: 1, layers: 1, levels: 1
+ }, {
+ width: 2, height: 2, layers: 2, levels: 2
+ }, {
+ width: 64, height: 32, layers: 3, levels: 7
+ }, {
+ width: 32, height: 64, layers: 3, levels: 4
+ }, {
+ width: 57, height: 63, layers: 5, levels: 1
+ }, {
+ width: 57, height: 63, layers: 5, levels: 2
+ }, {
+ width: 57, height: 63, layers: 5, levels: 6
+ }
+ ];
+
+ // W H D L
+ /**
+ * @type {Array<{width: number, height: number,
+ * depth: number, levels: number}>}
+ */
+ var tex3DSizes = [{
+ width: 1, height: 1, depth: 1, levels: 1
+ }, {
+ width: 2, height: 2, depth: 2, levels: 2
+ }, {
+ width: 64, height: 32, depth: 16, levels: 7
+ }, {
+ width: 32, height: 64, depth: 16, levels: 4
+ }, {
+ width: 32, height: 16, depth: 64, levels: 4
+ }, {
+ width: 57, height: 63, depth: 11, levels: 1
+ }, {
+ width: 57, height: 63, depth: 11, levels: 2
+ }, {
+ width: 57, height: 63, depth: 11, levels: 6
+ }
+ ];
+
+ storageGroup = new tcuTestCase.DeqpTest(
+ 'texstorage3d.size', 'glTexStorage3D() with various sizes'
+ );
+ this.addChild(storageGroup);
+
+ for (var ndx = 0; ndx < tex2DArraySizes.length; ndx++) {
+ format = gl.RGBA8;
+ width = tex2DArraySizes[ndx].width;
+ height = tex2DArraySizes[ndx].height;
+ /** @type {number} */ var layers = tex2DArraySizes[ndx].layers;
+ levels = tex2DArraySizes[ndx].levels;
+ name = '2d_array_' + width + 'x' + height + 'x' +
+ layers + '_' + levels + '_levels';
+
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage2DArrayCase(
+ name, '', format, width, height, layers, levels
+ )
+ );
+ }
+
+ for (var ndx = 0; ndx < tex3DSizes.length; ndx++) {
+ format = gl.RGBA8;
+ width = tex3DSizes[ndx].width;
+ height = tex3DSizes[ndx].height;
+ var depth = tex3DSizes[ndx].depth;
+ levels = tex3DSizes[ndx].levels;
+ name = '3d_' + width + 'x' + height + 'x' +
+ depth + '_' + levels + '_levels';
+
+ storageGroup.addChild(
+ new es3fTextureSpecificationTests.BasicTexStorage3DCase(
+ name, '', format, width, height, depth, levels
+ )
+ );
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ * @param {Array<number>=} range Test range
+ */
+ es3fTextureSpecificationTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fTextureSpecificationTests.TextureSpecificationTests());
+ if (range)
+ state.setRange(range);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fTextureSpecificationTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureStateQuery.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureStateQuery.js
new file mode 100644
index 0000000000..ab1f4d6bb9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureStateQuery.js
@@ -0,0 +1,376 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fTextureStateQuery');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('functional.gles3.es3fApiCase');
+goog.require('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var es3fTextureStateQuery = functional.gles3.es3fTextureStateQuery;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsStateQuery = modules.shared.glsStateQuery;
+var es3fApiCase = functional.gles3.es3fApiCase;
+var deRandom = framework.delibs.debase.deRandom;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/**
+ * @constructor
+ * @extends {es3fApiCase.ApiCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ */
+es3fTextureStateQuery.TextureCase = function(name, description, textureTarget) {
+ es3fApiCase.ApiCase.call(this, name, description, gl);
+ /** @type {WebGLTexture} */ this.m_texture;
+ this.m_textureTarget = textureTarget;
+};
+
+setParentClass(es3fTextureStateQuery.TextureCase, es3fApiCase.ApiCase);
+
+es3fTextureStateQuery.TextureCase.prototype.testTexture = function() {
+ throw new Error('Virtual function. Please override.');
+};
+
+es3fTextureStateQuery.TextureCase.prototype.test = function() {
+ this.m_texture = gl.createTexture();
+ gl.bindTexture(this.m_textureTarget, this.m_texture);
+
+ this.testTexture();
+
+ gl.bindTexture(this.m_textureTarget, null);
+ gl.deleteTexture(this.m_texture);
+};
+
+/**
+ * @constructor
+ * @extends {es3fTextureStateQuery.TextureCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ */
+es3fTextureStateQuery.IsTextureCase = function(name, description, textureTarget) {
+ es3fTextureStateQuery.TextureCase.call(this, name, description, textureTarget);
+};
+
+setParentClass(es3fTextureStateQuery.IsTextureCase, es3fTextureStateQuery.TextureCase);
+
+es3fTextureStateQuery.IsTextureCase.prototype.testTexture = function() {
+ this.check(glsStateQuery.compare(gl.isTexture(this.m_texture), true), 'gl.isTexture() should have returned true');
+};
+
+/**
+ * @constructor
+ * @extends {es3fTextureStateQuery.TextureCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ * @param {number} valueName
+ * @param {number} initialValue
+ * @param {Array<number>} valueRange
+ */
+es3fTextureStateQuery.TextureParamCase = function(name, description, textureTarget, valueName, initialValue, valueRange) {
+ es3fTextureStateQuery.TextureCase.call(this, name, description, textureTarget);
+ this.m_valueName = valueName;
+ this.m_initialValue = initialValue;
+ this.m_valueRange = valueRange;
+};
+
+setParentClass(es3fTextureStateQuery.TextureParamCase, es3fTextureStateQuery.TextureCase);
+
+es3fTextureStateQuery.TextureParamCase.prototype.testTexture = function() {
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_valueName, this.m_initialValue));
+
+ for (var ndx = 0; ndx < this.m_valueRange.length; ++ndx) {
+ gl.texParameteri(this.m_textureTarget, this.m_valueName, this.m_valueRange[ndx]);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_valueName, this.m_valueRange[ndx]));
+ }
+
+ //check unit conversions with float
+
+ for (var ndx = 0; ndx < this.m_valueRange.length; ++ndx) {
+ gl.texParameterf(this.m_textureTarget, this.m_valueName, this.m_valueRange[ndx]);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_valueName, this.m_valueRange[ndx]));
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fTextureStateQuery.TextureCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ * @param {number} lodTarget
+ * @param {number} initialValue
+ */
+es3fTextureStateQuery.TextureLODCase = function(name, description, textureTarget, lodTarget, initialValue) {
+ es3fTextureStateQuery.TextureCase.call(this, name, description, textureTarget);
+ this.m_lodTarget = lodTarget;
+ this.m_initialValue = initialValue;
+};
+
+setParentClass(es3fTextureStateQuery.TextureLODCase, es3fTextureStateQuery.TextureCase);
+
+es3fTextureStateQuery.TextureLODCase.prototype.testTexture = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_lodTarget, this.m_initialValue));
+
+ var numIterations = 60;
+ for (var ndx = 0; ndx < numIterations; ++ndx) {
+ var ref = rnd.getFloat(-64000, 64000);
+
+ gl.texParameterf(this.m_textureTarget, this.m_lodTarget, ref);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_lodTarget, ref));
+ }
+
+ // check unit conversions with int
+
+ for (var ndx = 0; ndx < numIterations; ++ndx) {
+ var ref = rnd.getInt(-64000, 64000);
+
+ gl.texParameteri(this.m_textureTarget, this.m_lodTarget, ref);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_lodTarget, ref));
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fTextureStateQuery.TextureCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ * @param {number} levelTarget
+ * @param {number} initialValue
+ */
+es3fTextureStateQuery.TextureLevelCase = function(name, description, textureTarget, levelTarget, initialValue) {
+ es3fTextureStateQuery.TextureCase.call(this, name, description, textureTarget);
+ this.m_levelTarget = levelTarget;
+ this.m_initialValue = initialValue;
+};
+
+setParentClass(es3fTextureStateQuery.TextureLevelCase, es3fTextureStateQuery.TextureCase);
+
+es3fTextureStateQuery.TextureLevelCase.prototype.testTexture = function() {
+ var rnd = new deRandom.Random(0xabcdef);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_levelTarget, this.m_initialValue));
+
+ var numIterations = 60;
+ for (var ndx = 0; ndx < numIterations; ++ndx) {
+ var ref = rnd.getInt(0, 64000);
+
+ gl.texParameteri(this.m_textureTarget, this.m_levelTarget, ref);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_levelTarget, ref));
+ }
+
+ // check unit conversions with float
+ var nonSignificantOffsets = [-0.45, -0.25, 0, 0.45]; // offsets O so that for any integers z in Z, o in O roundToClosestInt(z+o)==z
+
+ for (var ndx = 0; ndx < numIterations; ++ndx) {
+ var ref = rnd.getInt(0, 64000);
+
+ for (var i = 0; i < nonSignificantOffsets.length; i++) {
+ gl.texParameterf(this.m_textureTarget, this.m_levelTarget, ref + nonSignificantOffsets[i]);
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, this.m_levelTarget, ref));
+ }
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fTextureStateQuery.TextureCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ */
+es3fTextureStateQuery.TextureImmutableLevelsCase = function(name, description, textureTarget) {
+ es3fTextureStateQuery.TextureCase.call(this, name, description, textureTarget);
+};
+
+setParentClass(es3fTextureStateQuery.TextureImmutableLevelsCase, es3fTextureStateQuery.TextureCase);
+
+es3fTextureStateQuery.TextureImmutableLevelsCase.prototype.testTexture = function() {
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, gl.TEXTURE_IMMUTABLE_LEVELS, 0));
+ for (var level = 1; level <= 8; ++level) {
+ var textureID = gl.createTexture();
+ gl.bindTexture(this.m_textureTarget, textureID);
+
+ if (this.m_textureTarget == gl.TEXTURE_2D_ARRAY || this.m_textureTarget == gl.TEXTURE_3D)
+ gl.texStorage3D(this.m_textureTarget, level, gl.RGB8, 256, 256, 256);
+ else
+ gl.texStorage2D(this.m_textureTarget, level, gl.RGB8, 256, 256);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, gl.TEXTURE_IMMUTABLE_LEVELS, level));
+ gl.deleteTexture(textureID);
+ }
+};
+
+/**
+ * @constructor
+ * @extends {es3fTextureStateQuery.TextureCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {number} textureTarget
+ */
+es3fTextureStateQuery.TextureImmutableFormatCase = function(name, description, textureTarget) {
+ es3fTextureStateQuery.TextureCase.call(this, name, description, textureTarget);
+};
+
+setParentClass(es3fTextureStateQuery.TextureImmutableFormatCase, es3fTextureStateQuery.TextureCase);
+
+es3fTextureStateQuery.TextureImmutableFormatCase.prototype.testTexture = function() {
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, gl.TEXTURE_IMMUTABLE_LEVELS, 0));
+ var testSingleFormat = function(format) {
+ var textureID = gl.createTexture();
+ gl.bindTexture(this.m_textureTarget, textureID);
+
+ if (this.m_textureTarget == gl.TEXTURE_2D_ARRAY || this.m_textureTarget == gl.TEXTURE_3D)
+ gl.texStorage3D(this.m_textureTarget, 1, format, 32, 32, 32);
+ else
+ gl.texStorage2D(this.m_textureTarget, 1, format, 32, 32);
+
+ this.check(glsStateQuery.verifyTexture(this.m_textureTarget, gl.TEXTURE_IMMUTABLE_FORMAT, 1));
+ gl.deleteTexture(textureID);
+ };
+
+ var formats = [
+ gl.RGBA32I, gl.RGBA32UI, gl.RGBA16I, gl.RGBA16UI, gl.RGBA8, gl.RGBA8I,
+ gl.RGBA8UI, gl.SRGB8_ALPHA8, gl.RGB10_A2, gl.RGB10_A2UI, gl.RGBA4,
+ gl.RGB5_A1, gl.RGB8, gl.RGB565, gl.RG32I, gl.RG32UI, gl.RG16I, gl.RG16UI,
+ gl.RG8, gl.RG8I, gl.RG8UI, gl.R32I, gl.R32UI, gl.R16I, gl.R16UI, gl.R8,
+ gl.R8I, gl.R8UI,
+
+ gl.RGBA32F, gl.RGBA16F, gl.RGBA8_SNORM, gl.RGB32F,
+ gl.RGB32I, gl.RGB32UI, gl.RGB16F, gl.RGB16I, gl.RGB16UI, gl.RGB8_SNORM,
+ gl.RGB8I, gl.RGB8UI, gl.SRGB8, gl.R11F_G11F_B10F, gl.RGB9_E5, gl.RG32F,
+ gl.RG16F, gl.RG8_SNORM, gl.R32F, gl.R16F, gl.R8_SNORM
+ ];
+
+ var non3dFormats = [
+ gl.DEPTH_COMPONENT32F, gl.DEPTH_COMPONENT24, gl.DEPTH_COMPONENT16,
+ gl.DEPTH32F_STENCIL8, gl.DEPTH24_STENCIL8
+ ];
+
+ for (var formatNdx = 0; formatNdx < formats.length; ++formatNdx)
+ testSingleFormat.bind(this, formats[formatNdx]);
+
+ if (this.m_textureTarget != gl.TEXTURE_3D)
+ for (var formatNdx = 0; formatNdx < non3dFormats.length; ++formatNdx)
+ testSingleFormat.bind(this, non3dFormats[formatNdx]);
+};
+
+/**
+* @constructor
+* @extends {tcuTestCase.DeqpTest}
+*/
+es3fTextureStateQuery.TextureStateQuery = function() {
+ tcuTestCase.DeqpTest.call(this, 'texture', 'Texture State Query tests');
+};
+
+es3fTextureStateQuery.TextureStateQuery.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fTextureStateQuery.TextureStateQuery.prototype.constructor = es3fTextureStateQuery.TextureStateQuery;
+
+es3fTextureStateQuery.TextureStateQuery.prototype.init = function() {
+ var textureTargets = [
+ ['texture_2d', gl.TEXTURE_2D],
+ ['texture_3d', gl.TEXTURE_3D],
+ ['texture_2d_array', gl.TEXTURE_2D_ARRAY],
+ ['texture_cube_map', gl.TEXTURE_CUBE_MAP]
+ ];
+
+ var state = this;
+ var wrapValues = [gl.CLAMP_TO_EDGE, gl.REPEAT, gl.MIRRORED_REPEAT];
+ var magValues = [gl.NEAREST, gl.LINEAR];
+ var minValues = [gl.NEAREST, gl.LINEAR, gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST_MIPMAP_LINEAR, gl.LINEAR_MIPMAP_NEAREST, gl.LINEAR_MIPMAP_LINEAR];
+ var modes = [gl.COMPARE_REF_TO_TEXTURE, gl.NONE];
+ var compareFuncs = [gl.LEQUAL, gl.GEQUAL, gl.LESS, gl.GREATER, gl.EQUAL, gl.NOTEQUAL, gl.ALWAYS, gl.NEVER];
+ textureTargets.forEach(function(elem) {
+ var name = elem[0];
+ var target = elem[1];
+ state.addChild(new es3fTextureStateQuery.IsTextureCase(name + '_is_texture', 'IsTexture', target));
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_wrap_s' , 'TEXTURE_WRAP_S',
+ target, gl.TEXTURE_WRAP_S, gl.REPEAT, wrapValues));
+ if (target == gl.TEXTURE_2D ||
+ target == gl.TEXTURE_3D ||
+ target == gl.TEXTURE_CUBE_MAP)
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_wrap_t' , 'TEXTURE_WRAP_T',
+ target, gl.TEXTURE_WRAP_T, gl.REPEAT, wrapValues));
+
+ if (target == gl.TEXTURE_3D)
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_wrap_r' , 'TEXTURE_WRAP_R',
+ target, gl.TEXTURE_WRAP_R, gl.REPEAT, wrapValues));
+
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_mag_filter' , 'TEXTURE_MAG_FILTER',
+ target, gl.TEXTURE_MAG_FILTER, gl.LINEAR, magValues));
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_min_filter' , 'TEXTURE_MIN_FILTER',
+ target, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR, minValues));
+ state.addChild(new es3fTextureStateQuery.TextureLODCase(name + '_texture_min_lod' , 'TEXTURE_MIN_LOD', target, gl.TEXTURE_MIN_LOD, -1000));
+ state.addChild(new es3fTextureStateQuery.TextureLODCase(name + '_texture_max_lod' , 'TEXTURE_MAX_LOD', target, gl.TEXTURE_MAX_LOD, 1000));
+ state.addChild(new es3fTextureStateQuery.TextureLevelCase(name + '_texture_base_level' , 'TEXTURE_BASE_LEVEL', target, gl.TEXTURE_BASE_LEVEL, 0));
+ state.addChild(new es3fTextureStateQuery.TextureLevelCase(name + '_texture_max_level' , 'TEXTURE_MAX_LEVEL', target, gl.TEXTURE_MAX_LEVEL, 1000));
+
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_compare_mode' , 'TEXTURE_COMPARE_MODE',
+ target, gl.TEXTURE_COMPARE_MODE, gl.NONE, modes));
+ state.addChild(new es3fTextureStateQuery.TextureParamCase(name + '_texture_compare_func' , 'TEXTURE_COMPARE_FUNC',
+ target, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL, compareFuncs));
+
+ state.addChild(new es3fTextureStateQuery.TextureImmutableLevelsCase(name + '_texture_immutable_levels', 'TEXTURE_IMMUTABLE_LEVELS', target));
+ state.addChild(new es3fTextureStateQuery.TextureImmutableFormatCase(name + '_texture_immutable_format', 'TEXTURE_IMMUTABLE_FORMAT', target));
+ });
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fTextureStateQuery.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fTextureStateQuery.TextureStateQuery());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fTextureStateQuery.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureWrapTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureWrapTests.js
new file mode 100644
index 0000000000..a6d6e96d14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureWrapTests.js
@@ -0,0 +1,434 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fTextureWrapTests');
+goog.require('framework.common.tcuCompressedTexture');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexLookupVerifier');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+ /** @type {?WebGL2RenderingContext} */ var gl;
+
+ var es3fTextureWrapTests = functional.gles3.es3fTextureWrapTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+ var tcuCompressedTexture = framework.common.tcuCompressedTexture;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var deString = framework.delibs.debase.deString;
+
+ /**
+ * @enum {number}
+ */
+ var Viewport = {
+ WIDTH: 256,
+ HEIGHT: 256
+ };
+
+ /**
+ * @constructor
+ * @param {Array<number>=} bl
+ * @param {Array<number>=} tr
+ */
+ es3fTextureWrapTests.Case = function(bl, tr) {
+ /** @type {?Array<number>} */ this.bottomLeft = bl || null;
+ /** @type {?Array<number>} */ this.topRight = tr || null;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {?tcuCompressedTexture.Format} compressedFormat
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} width
+ * @param {number} height
+ */
+ es3fTextureWrapTests.TextureWrapCase = function(name, description, compressedFormat, wrapS, wrapT, minFilter, magFilter, width, height) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {number} */ this.m_format = gl.NONE;
+ /** @type {number} */ this.m_dataType = gl.NONE;
+ /** @type {?tcuCompressedTexture.Format} */ this.m_compressedFormat = compressedFormat;
+ /** @type {number} */ this.m_wrapS = wrapS;
+ /** @type {number} */ this.m_wrapT = wrapT;
+ /** @type {number} */ this.m_minFilter = minFilter;
+ /** @type {number} */ this.m_magFilter = magFilter;
+ /** @type {number} */ this.m_width = width;
+ /** @type {number} */ this.m_height = height;
+ /** @type {Array<es3fTextureWrapTests.Case>} */ this.m_cases = [];
+ /** @type {number} */ this.m_caseNdx = 0;
+ /** @type {gluTexture.Texture2D} */ this.m_texture = null;
+ /** @type {glsTextureTestUtil.TextureRenderer} */
+ this.m_renderer = new glsTextureTestUtil.TextureRenderer(gluShaderUtil.getGLSLVersionString(gluShaderUtil.GLSLVersion.V300_ES), gluShaderUtil.precision.PRECISION_MEDIUMP);
+ };
+
+ es3fTextureWrapTests.TextureWrapCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+
+ /** Copy the constructor */
+ es3fTextureWrapTests.TextureWrapCase.prototype.constructor = es3fTextureWrapTests.TextureWrapCase;
+
+ /**
+ * @param {string} name
+ * @param {string} description
+ * @param {number} format
+ * @param {number} dataType
+ * @param {number} wrapS
+ * @param {number} wrapT
+ * @param {number} minFilter
+ * @param {number} magFilter
+ * @param {number} width
+ * @param {number} height
+ * @return {es3fTextureWrapTests.TextureWrapCase}
+ */
+ es3fTextureWrapTests.textureWrapCaseFromFormat = function(name, description, format, dataType, wrapS, wrapT, minFilter, magFilter, width, height) {
+ var texWrapCase = new es3fTextureWrapTests.TextureWrapCase(name, description, null, wrapS, wrapT, minFilter, magFilter, width, height);
+ texWrapCase.m_format = gl.RGBA;
+ texWrapCase.m_dataType = gl.UNSIGNED_BYTE;
+ return texWrapCase;
+ };
+
+ /**
+ */
+ es3fTextureWrapTests.TextureWrapCase.prototype.init = function() {
+ if (this.m_compressedFormat !== null) {
+ // Generate compressed texture.
+
+ assertMsgOptions(this.m_format == gl.NONE && this.m_dataType == gl.NONE, 'init/compressedFormat', false, true);
+ if (tcuCompressedTexture.isEtcFormat(this.m_compressedFormat)) {
+ // Create ETC texture. Any content is valid.
+
+ /** @type {tcuCompressedTexture.CompressedTexture}*/
+ var compressedTexture = new tcuCompressedTexture.CompressedTexture(this.m_compressedFormat, this.m_width, this.m_height);
+ /** @type {number} */ var dataSize = compressedTexture.getDataSize();
+ /** @type {goog.NumberArray} */ var data = compressedTexture.getData();
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+
+ for (var i = 0; i < dataSize; i++)
+ data[i] = rnd.getFloat() & 0xff;
+
+ this.m_texture = gluTexture.texture2DFromCompressedTexture(gl, 1, [compressedTexture]);
+ } else
+ throw new Error('Only ETC2 and EAC are supported.');
+ } else{
+ this.m_texture = gluTexture.texture2DFromFormat(gl, this.m_format, this.m_dataType, this.m_width, this.m_height);
+
+ // Fill level 0.
+ this.m_texture.getRefTexture().allocLevel(0);
+ tcuTextureUtil.fillWithComponentGradients(this.m_texture.getRefTexture().getLevel(0), [-0.5, -0.5, -0.5, 2.0], [1.0, 1.0, 1.0, 0.0]);
+
+ this.m_texture.upload();
+ }
+
+ // Sub-cases.
+
+ this.m_cases.push(new es3fTextureWrapTests.Case([-1.5, -3.0], [1.5, 2.5]));
+ this.m_cases.push(new es3fTextureWrapTests.Case([-0.5, 0.75], [0.25, 1.25]));
+ assertMsgOptions(this.m_caseNdx == 0, 'm_caseNdx != 0', false, true);
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fTextureWrapTests.TextureWrapCase.prototype.iterate = function() {
+ /** @type {glsTextureTestUtil.RandomViewport} */ var viewport = new glsTextureTestUtil.RandomViewport(gl.canvas, Viewport.WIDTH, Viewport.HEIGHT, deString.deStringHash(this.name) + this.m_caseNdx);
+ /** @type {tcuSurface.Surface} */ var renderedFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /** @type {tcuSurface.Surface} */ var referenceFrame = new tcuSurface.Surface(viewport.width, viewport.height);
+ /** @type {glsTextureTestUtil.ReferenceParams} */ var refParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D);
+ /** @type {tcuTexture.TextureFormat} */ var texFormat = this.m_texture.getRefTexture().getFormat();
+ /** @type {Array<number>} */ var texCoord;
+ /** @type {tcuTextureUtil.TextureFormatInfo} */ var texFormatInfo = tcuTextureUtil.getTextureFormatInfo(texFormat);
+ /** @type {boolean} */ var useDefaultColorScaleAndBias = true;
+
+ // Bind to unit 0.
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, this.m_texture.getGLTexture());
+
+ // Setup filtering and wrap modes.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.m_wrapS);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.m_wrapT);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
+
+ // Parameters for reference images.
+ refParams.sampler = gluTextureUtil.mapGLSamplerWrapST(this.m_wrapS, this.m_wrapT, this.m_minFilter, this.m_magFilter);
+ refParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ refParams.samplerType = glsTextureTestUtil.getSamplerType(this.m_texture.getRefTexture().getFormat());
+ refParams.colorScale = useDefaultColorScaleAndBias ? texFormatInfo.lookupScale : [1.0, 1.0, 1.0, 1.0];
+ refParams.colorBias = useDefaultColorScaleAndBias ? texFormatInfo.lookupBias : [0, 0, 0, 0];
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+ texCoord = glsTextureTestUtil.computeQuadTexCoord2D(this.m_cases[this.m_caseNdx].bottomLeft, this.m_cases[this.m_caseNdx].topRight);
+ this.m_renderer.renderQuad(0, texCoord, refParams);
+
+ // gluPixelTransfer.readPixels(viewport.x, viewport.y, renderedFrame.getAccess());
+ /** @type {number} */ var pixelSize = renderedFrame.getAccess().getFormat().getPixelSize();
+ /** @type {number} */ var param = deMath.deIsPowerOfTwo32(pixelSize) ? Math.min(pixelSize, 8) : 1;
+
+ gl.pixelStorei(gl.PACK_ALIGNMENT, param);
+ /** @type {gluTextureUtil.TransferFormat} */ var format = gluTextureUtil.getTransferFormat(renderedFrame.getAccess().getFormat());
+
+ renderedFrame.readViewport(gl, viewport);
+
+ // const tcu::ScopedLogSection section (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
+ /** @type {boolean} */ var isNearestOnly = this.m_minFilter == gl.NEAREST && this.m_magFilter == gl.NEAREST;
+ /** @type {boolean} */ var isSRGB = texFormat.order == tcuTexture.ChannelOrder.sRGB || texFormat.order == tcuTexture.ChannelOrder.sRGBA;
+ /** @type {tcuPixelFormat.PixelFormat} */ var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
+ /** @type {Array<number>} */ var colorBits = deMath.max(deMath.subtract(glsTextureTestUtil.getBitsVec(pixelFormat), (isNearestOnly && !isSRGB ? [1, 1, 1, 1] : [2, 2, 2, 2])), [0, 0, 0, 0]);
+ /** @type {tcuTexLookupVerifier.LodPrecision} */ var lodPrecision = new tcuTexLookupVerifier.LodPrecision(18, 5);
+ /** @type {tcuTexLookupVerifier.LookupPrecision} */
+ var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision(
+ [20, 20, 0],
+ [5, 5, 0],
+ deMath.divide(tcuTexLookupVerifier.computeFixedPointThreshold(colorBits), refParams.colorScale),
+ glsTextureTestUtil.getCompareMask(pixelFormat)
+ );
+
+ // log << TestLog::Message << "Note: lookup coordinates: bottom-left " << m_cases[m_caseNdx].bottomLeft << ", top-right " << m_cases[m_caseNdx].topRight << TestLog::EndMessage;
+
+ /** @type {boolean} */ var isOk = glsTextureTestUtil.verifyTexture2DResult(renderedFrame.getAccess(), this.m_texture.getRefTexture(), texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat);
+
+ if (!isOk)
+ testFailedOptions('Case ' + this.m_caseNdx + ': verifyTexture2DResult is false', false);
+ else
+ testPassedOptions('Case ' + this.m_caseNdx + ': OK', true);
+
+ this.m_caseNdx++;
+
+ return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * Initialize test
+ */
+ es3fTextureWrapTests.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ /** @type {string} */ var name;
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {number} mode
+ */
+ var WrapMode = function(name, mode) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.mode = mode;
+ };
+
+ /** @type {Array<WrapMode>} */ var wrapModes = [
+ new WrapMode('clamp', gl.CLAMP_TO_EDGE),
+ new WrapMode('repeat', gl.REPEAT),
+ new WrapMode('mirror', gl.MIRRORED_REPEAT)
+ ];
+
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {number} mode
+ */
+ var FilteringMode = function(name, mode) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.mode = mode;
+ };
+
+ /** @type {Array<FilteringMode>} */ var filteringModes = [
+ new FilteringMode('nearest', gl.NEAREST),
+ new FilteringMode('linear', gl.LINEAR)
+ ];
+
+ /* Begin RGBA8 Cases */
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {number} width
+ * @param {number} height
+ */
+ var Rgba8Size = function(name, width, height) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.width = width;
+ /** @type {number} */ this.height = height;
+ };
+
+ /** @type {Array<Rgba8Size>} */ var rgba8Sizes = [
+ new Rgba8Size('pot', 64, 128),
+ new Rgba8Size('npot', 63, 112)
+ ];
+
+ for (var size = 0; size < rgba8Sizes.length; size++) {
+ /** @type {tcuTestCase.DeqpTest} */ var rgba8Group = tcuTestCase.newTest('rgba8', '');
+ testGroup.addChild(rgba8Group);
+ for (var wrapS = 0; wrapS < wrapModes.length; wrapS++) {
+ for (var wrapT = 0; wrapT < wrapModes.length; wrapT++) {
+ for (var filter = 0; filter < filteringModes.length; filter++) {
+ name = [
+ wrapModes[wrapS].name,
+ wrapModes[wrapT].name,
+ filteringModes[filter].name,
+ rgba8Sizes[size].name
+ ].join('_');
+
+ rgba8Group.addChild(es3fTextureWrapTests.textureWrapCaseFromFormat(
+ name, '',
+ gl.RGBA, gl.UNSIGNED_BYTE,
+ wrapModes[wrapS].mode,
+ wrapModes[wrapT].mode,
+ filteringModes[filter].mode, filteringModes[filter].mode,
+ rgba8Sizes[size].width, rgba8Sizes[size].height
+ ));
+ }
+ }
+ }
+ }
+ /* End RGBA8 Cases */
+
+ /* Begin ETC-2 (and EAC) cases */
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {tcuCompressedTexture.Format} format
+ */
+ var Etc2Format = function(name, format) {
+ /** @type {string} */ this.name = name;
+ /** @type {tcuCompressedTexture.Format} */ this.format = format;
+ };
+
+ var etc2Formats = [
+ new Etc2Format('eac_r11', tcuCompressedTexture.Format.EAC_R11),
+ new Etc2Format('eac_signed_r11', tcuCompressedTexture.Format.EAC_SIGNED_R11),
+ new Etc2Format('eac_rg11', tcuCompressedTexture.Format.EAC_RG11),
+ new Etc2Format('eac_signed_rg11', tcuCompressedTexture.Format.EAC_SIGNED_RG11),
+ new Etc2Format('etc2_rgb8', tcuCompressedTexture.Format.ETC2_RGB8),
+ new Etc2Format('etc2_srgb8', tcuCompressedTexture.Format.ETC2_SRGB8),
+ new Etc2Format('etc2_rgb8_punchthrough_alpha1', tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1),
+ new Etc2Format('etc2_srgb8_punchthrough_alpha1', tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1),
+ new Etc2Format('etc2_eac_rgba8', tcuCompressedTexture.Format.ETC2_EAC_RGBA8),
+ new Etc2Format('etc2_eac_srgb8_alpha8', tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8)
+ ];
+ if (!gluTextureUtil.enableCompressedTextureETC()) {
+ debug('Skipping ETC2/EAC texture format tests: no support for WEBGL_compressed_texture_etc');
+ etc2Formats = [];
+ }
+
+ /**
+ * @constructor
+ * @struct
+ * @param {string} name
+ * @param {number} width
+ * @param {number} height
+ */
+ var Etc2Size = function(name, width, height) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.width = width;
+ /** @type {number} */ this.height = height;
+ };
+
+ /** @type {Array<Etc2Size>} */ var etc2Sizes = [
+ new Etc2Size('pot', 64, 128),
+ new Etc2Size('npot', 123, 107)
+ ];
+
+ for (var formatNdx = 0; formatNdx < etc2Formats.length; formatNdx++) {
+ for (var size = 0; size < etc2Sizes.length; size++) {
+ /** @type {tcuTestCase.DeqpTest} */ var formatGroup = tcuTestCase.newTest(etc2Formats[formatNdx].name, '');
+ testGroup.addChild(formatGroup);
+ for (var wrapS = 0; wrapS < wrapModes.length; wrapS++) {
+ for (var wrapT = 0; wrapT < wrapModes.length; wrapT++) {
+ for (var filter = 0; filter < filteringModes.length; filter++) {
+ name = [
+ wrapModes[wrapS].name,
+ wrapModes[wrapT].name,
+ filteringModes[filter].name,
+ etc2Sizes[size].name
+ ].join('_');
+
+ formatGroup.addChild(new es3fTextureWrapTests.TextureWrapCase(
+ name, '',
+ etc2Formats[formatNdx].format,
+ wrapModes[wrapS].mode,
+ wrapModes[wrapT].mode,
+ filteringModes[filter].mode, filteringModes[filter].mode,
+ etc2Sizes[size].width, etc2Sizes[size].height
+ ));
+ }
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fTextureWrapTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'texture_wrap';
+ var testDescription = 'Texture Wrap Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.setRoot(tcuTestCase.newTest(testName, testDescription, null));
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fTextureWrapTests.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fTextureWrapTests.run tests', false);
+ state.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTransformFeedbackTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTransformFeedbackTests.js
new file mode 100644
index 0000000000..5beae6985d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTransformFeedbackTests.js
@@ -0,0 +1,1914 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fTransformFeedbackTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+goog.require('framework.opengl.gluVarTypeUtil');
+
+goog.scope(function() {
+
+ var es3fTransformFeedbackTests = functional.gles3.es3fTransformFeedbackTests;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var gluVarTypeUtil = framework.opengl.gluVarTypeUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+ };
+
+ /**
+ * @enum
+ */
+ es3fTransformFeedbackTests.State = {
+ DRAW: 0,
+ VERIFY: 1,
+ FINISH: 2
+ };
+
+ /* Maximum time to wait for query result (in seconds) */
+ /** @const */ es3fTransformFeedbackTests.MAX_VERIFY_WAIT = 5;
+
+ /** @const @type {number} */ es3fTransformFeedbackTests.VIEWPORT_WIDTH = 128;
+ /** @const @type {number} */ es3fTransformFeedbackTests.VIEWPORT_HEIGHT = 128;
+ /** @const @type {number} */ es3fTransformFeedbackTests.BUFFER_GUARD_MULTIPLIER = 2;
+
+ /**
+ * Enums for es3fTransformFeedbackTests.interpolation
+ * @enum {number}
+ */
+ es3fTransformFeedbackTests.interpolation = {
+ SMOOTH: 0,
+ FLAT: 1,
+ CENTROID: 2
+
+ };
+
+ /**
+ * Returns es3fTransformFeedbackTests.interpolation name: smooth, flat or centroid
+ * @param {number} interpol es3fTransformFeedbackTests.interpolation enum value
+ * @return {string}
+ */
+ es3fTransformFeedbackTests.getInterpolationName = function(interpol) {
+
+ switch (interpol) {
+ case es3fTransformFeedbackTests.interpolation.SMOOTH: return 'smooth';
+ case es3fTransformFeedbackTests.interpolation.FLAT: return 'flat';
+ case es3fTransformFeedbackTests.interpolation.CENTROID: return 'centroid';
+ default:
+ throw new Error('Unrecognized es3fTransformFeedbackTests.interpolation name ' + interpol);
+ }
+
+ };
+
+ /**
+ * @struct
+ * @param {string} name
+ * @param {gluVarType.VarType} type
+ * @param {number} interpolation
+ * @constructor
+ */
+ es3fTransformFeedbackTests.Varying = function(name, type, interpolation) {
+ this.name = name;
+ this.type = type;
+ this.interpolation = interpolation;
+ };
+
+ /** es3fTransformFeedbackTests.findAttributeNameEquals
+ * Replaces original implementation of "VaryingNameEquals" and "AttributeNameEquals" in the C++ version
+ * Returns an es3fTransformFeedbackTests.Attribute or es3fTransformFeedbackTests.Varying object which matches its name with the passed string value in the function
+ * @param {(Array<es3fTransformFeedbackTests.Attribute> | Array<es3fTransformFeedbackTests.Varying>)} array
+ * @param {string} name
+ * @return { (es3fTransformFeedbackTests.Attribute | es3fTransformFeedbackTests.Varying | null)}
+ */
+ es3fTransformFeedbackTests.findAttributeNameEquals = function(array, name) {
+ for (var pos = 0; pos < array.length; pos++) {
+ if (array[pos].name === name) {
+ return array[pos];
+ }
+ }
+ return null;
+ };
+
+ /**
+ * @struct
+ * @param {string} name
+ * @param {gluVarType.VarType} type
+ * @param {number} offset
+ * @constructor
+ */
+ es3fTransformFeedbackTests.Attribute = function(name, type, offset) {
+ this.name = name;
+ this.type = type;
+ this.offset = offset;
+ };
+
+ /**
+ * Constructs an es3fTransformFeedbackTests.Output object
+ * @constructor
+ */
+ es3fTransformFeedbackTests.Output = function() {
+ /** @type {number} */ this.bufferNdx = 0;
+ /** @type {number} */ this.offset = 0;
+ /** @type {string} */ this.name;
+ /** @type {gluVarType.VarType} */ this.type = null;
+ /** @type {Array<es3fTransformFeedbackTests.Attribute>} */ this.inputs = [];
+ };
+
+ /**
+ * Constructs an object type es3fTransformFeedbackTests.DrawCall.
+ * Contains the number of elements as well as whether the Transform Feedback is enabled or not.
+ * @struct
+ * @param {number} numElements
+ * @param {boolean} tfEnabled is Transform Feedback enabled or not
+ * @constructor
+ */
+ es3fTransformFeedbackTests.DrawCall = function(numElements, tfEnabled) {
+ this.numElements = numElements;
+ this.transformFeedbackEnabled = tfEnabled;
+ };
+
+ /**
+ * @constructor
+ */
+ es3fTransformFeedbackTests.ProgramSpec = function() {
+
+ /** @type {Array<gluVarType.StructType>} */ var m_structs = [];
+ /** @type {Array<es3fTransformFeedbackTests.Varying>} */ var m_varyings = [];
+ /** @type {Array<string>} */ var m_transformFeedbackVaryings = [];
+
+ this.createStruct = function(name) {
+ var struct = gluVarType.newStructType(name);
+ m_structs.push(struct);
+ return struct;
+ };
+
+ this.addVarying = function(name, type, interp) {
+ m_varyings.push(new es3fTransformFeedbackTests.Varying(name, type, interp));
+ };
+
+ this.addTransformFeedbackVarying = function(name) {
+ m_transformFeedbackVaryings.push(name);
+ };
+
+ this.getStructs = function() {
+ return m_structs;
+ };
+ this.getVaryings = function() {
+ return m_varyings;
+ };
+ this.getTransformFeedbackVaryings = function() {
+ return m_transformFeedbackVaryings;
+ };
+
+ this.isPointSizeUsed = function() {
+ for (var i = 0; i < m_transformFeedbackVaryings.length; ++i) {
+ if (m_transformFeedbackVaryings[i] == 'gl_PointSize') return true;
+ }
+ return false;
+ };
+
+ };
+
+ /** Returns if the program is supported or not
+ * @param {es3fTransformFeedbackTests.ProgramSpec} spec
+ * @param {number} tfMode
+ * @return {boolean}
+ */
+ es3fTransformFeedbackTests.isProgramSupported = function(spec, tfMode) {
+ var maxVertexAttribs = Number(gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ var maxTfInterleavedComponents = Number(gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS));
+ var maxTfSeparateAttribs = Number(gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS));
+ var maxTfSeparateComponents = Number(gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS));
+
+ // Check vertex attribs.
+ /** @type {number} */ var totalVertexAttribs = (
+ 1 /* a_position */ + (spec.isPointSizeUsed() ? 1 : 0)
+ );
+
+ for (var i = 0; i < spec.getVaryings().length; ++i) {
+ for (var v_iter = new gluVarTypeUtil.VectorTypeIterator(spec.getVaryings()[i].type); !v_iter.end(); v_iter.next()) {
+ totalVertexAttribs += 1;
+ }
+ }
+
+ if (totalVertexAttribs > maxVertexAttribs)
+ return false; // Vertex attribute es3fTransformFeedbackTests.count exceeded.
+
+ // check varyings
+ /** @type {number} */ var totalTfComponents = 0;
+ /** @type {number} */ var totalTfAttribs = 0;
+ /** @type {Object.<number, number>} */ var presetNumComponents = {
+ gl_Position: 4,
+ gl_PointSize: 1
+ };
+ for (var i = 0; i < spec.getTransformFeedbackVaryings().length; ++i) {
+ var name = spec.getTransformFeedbackVaryings()[i];
+ var numComponents = 0;
+
+ if (typeof(presetNumComponents[name]) != 'undefined') {
+ numComponents = presetNumComponents[name];
+ } else {
+ var varName = gluVarTypeUtil.parseVariableName(name);
+ // find the varying called varName
+ /** @type {es3fTransformFeedbackTests.Varying} */ var varying = (function(varyings) {
+ for (var i = 0; i < varyings.length; ++i) {
+ if (varyings[i].name == varName) {
+ return varyings[i];
+ }
+ }
+ return null;
+ }(spec.getVaryings()));
+
+ // glu::TypeComponentVector
+ var varPath = gluVarTypeUtil.parseTypePath(name, varying.type);
+ numComponents = gluVarTypeUtil.getVarType(varying.type, varPath).getScalarSize();
+ }
+
+ if (tfMode == gl.SEPARATE_ATTRIBS && numComponents > maxTfSeparateComponents)
+ return false; // Per-attribute component es3fTransformFeedbackTests.count exceeded.
+
+ totalTfComponents += numComponents;
+ totalTfAttribs += 1;
+ }
+
+ if (tfMode == gl.SEPARATE_ATTRIBS && totalTfAttribs > maxTfSeparateAttribs)
+ return false;
+
+ if (tfMode == gl.INTERLEAVED_ATTRIBS && totalTfComponents > maxTfInterleavedComponents)
+ return false;
+
+ return true;
+
+ };
+
+ /**
+ * @param {string} varyingName
+ * @param {Array<gluVarTypeUtil.VarTypeComponent>} path
+ * @return {string}
+ */
+ es3fTransformFeedbackTests.getAttributeName = function(varyingName, path) {
+ /** @type {string} */ var str = 'a_' + varyingName.substr(/^v_/.test(varyingName) ? 2 : 0);
+
+ for (var i = 0; i < path.length; ++i) {
+ /** @type {string} */ var prefix;
+
+ switch (path[i].type) {
+ case gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER: prefix = '_m'; break;
+ case gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT: prefix = '_e'; break;
+ case gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN: prefix = '_c'; break;
+ case gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT: prefix = '_s'; break;
+ default:
+ throw new Error('invalid type in the component path.');
+ }
+ str += prefix + path[i].index;
+ }
+ return str;
+ };
+
+ /**
+ * original definition:
+ * static void es3fTransformFeedbackTests.genShaderSources (const es3fTransformFeedbackTests.ProgramSpec& spec, std::string& vertSource, std::string& fragSource, bool pointSizeRequired)
+ * in place of the std::string references, this function returns those params in an object
+ *
+ * @param {es3fTransformFeedbackTests.ProgramSpec} spec
+ * @param {boolean} pointSizeRequired
+ * @return {Object.<string, string>}
+ */
+ es3fTransformFeedbackTests.genShaderSources = function(spec, pointSizeRequired) {
+
+ var vtx = { str: null };
+ var frag = { str: null };
+ var addPointSize = spec.isPointSizeUsed();
+
+ vtx.str = '#version 300 es\n' +
+ 'in highp vec4 a_position;\n';
+ frag.str = '#version 300 es\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform highp vec4 u_scale;\n' +
+ 'uniform highp vec4 u_bias;\n';
+ //vtx.str = 'attribute highp vec4 a_position;\n';
+ //frag.str = 'uniform highp vec4 u_scale;\n' +
+ // 'uniform highp vec4 u_bias;\n';
+
+ if (addPointSize) {
+ vtx.str += 'in highp float a_pointSize;\n';
+ //vtx.str += 'attribute highp float a_pointSize;\n';
+ }
+
+ // Declare attributes.
+ for (var i = 0; i < spec.getVaryings().length; ++i) {
+
+ /** @type {string} */ var name = spec.getVaryings()[i].name;
+ /** @type {gluVarType.VarType} */ var type = spec.getVaryings()[i].type;
+
+ for (var vecIter = new gluVarTypeUtil.VectorTypeIterator(type); !vecIter.end(); vecIter.next()) {
+
+ /** @type {gluVarType.VarType} */
+ var attribType = gluVarTypeUtil.getVarType(type, vecIter.getPath());
+
+ /** @type {string} */
+ var attribName = es3fTransformFeedbackTests.getAttributeName(name, vecIter.getPath());
+ vtx.str += 'in ' + gluVarType.declareVariable(attribType, attribName) + ';\n';
+
+ }
+ }
+
+ // Declare varyings.
+ for (var ndx = 0; ndx < 2; ++ndx) {
+ var inout = ndx ? 'in' : 'out';
+ var shader = ndx ? frag : vtx;
+
+ for (var i = 0; i < spec.getStructs().length; ++i) {
+ var struct = spec.getStructs()[i];
+ if (struct.hasTypeName()) {
+ shader.str += gluVarType.declareStructType(struct) + ';\n';
+ }
+ }
+
+ /** @type {Array<es3fTransformFeedbackTests.Varying>} */ var varyings = spec.getVaryings();
+ for (var i = 0; i < varyings.length; ++i) {
+ var varying = varyings[i];
+ shader.str += es3fTransformFeedbackTests.getInterpolationName(varying.interpolation) +
+ ' ' + inout + ' ' +
+ gluVarType.declareVariable(varying.type, varying.name) +
+ ';\n';
+ }
+ }
+
+ vtx.str += '\nvoid main (void)\n {\n' +
+ '\tgl_Position = a_position;\n';
+ frag.str += '\nvoid main (void)\n {\n' +
+ '\thighp vec4 res = vec4(0.0);\n';
+
+ if (addPointSize) {
+ vtx.str += '\tgl_PointSize = a_pointSize;\n';
+ } else if (pointSizeRequired) {
+ vtx.str += '\tgl_PointSize = 1.0;\n';
+ }
+
+ for (var i = 0; i < spec.getVaryings().length; ++i) {
+ var name = spec.getVaryings()[i].name;
+ var type = spec.getVaryings()[i].type;
+
+ for (var vecIter = new gluVarTypeUtil.VectorTypeIterator(type); !vecIter.end(); vecIter.next()) {
+ /** @type {gluVarType.VarType} */var subType = gluVarTypeUtil.getVarType(type, vecIter.getPath());
+ var attribName = es3fTransformFeedbackTests.getAttributeName(name, vecIter.getPath());
+
+ if (!(
+ subType.isBasicType() &&
+ gluShaderUtil.isDataTypeScalarOrVector(subType.getBasicType())
+ )) throw new Error('Not a scalar or vector.');
+
+ // Vertex: assign from attribute.
+ vtx.str += '\t' + name + vecIter.toString() + ' = ' + attribName + ';\n';
+
+ // Fragment: add to res variable.
+ var scalarSize = gluShaderUtil.getDataTypeScalarSize(subType.getBasicType());
+
+ frag.str += '\tres += ';
+ if (scalarSize == 1) frag.str += 'vec4(' + name + vecIter.toString() + ')';
+ else if (scalarSize == 2) frag.str += 'vec2(' + name + vecIter.toString() + ').xxyy';
+ else if (scalarSize == 3) frag.str += 'vec3(' + name + vecIter.toString() + ').xyzx';
+ else if (scalarSize == 4) frag.str += 'vec4(' + name + vecIter.toString() + ')';
+
+ frag.str += ';\n';
+ }
+ }
+
+ frag.str += '\to_color = res * u_scale + u_bias;\n}\n';
+ //frag.str += '\tgl_FragColor = res * u_scale + u_bias;\n}\n';
+ vtx.str += '}\n';
+
+ return {
+ vertSource: vtx.str,
+ fragSource: frag.str
+ };
+ };
+
+ /**
+ * Returns a Shader program
+ * @param {es3fTransformFeedbackTests.ProgramSpec} spec
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @return {gluShaderProgram.ShaderProgram}
+ */
+ es3fTransformFeedbackTests.createVertexCaptureProgram = function(spec, bufferMode, primitiveType) {
+
+ /** @type {Object.<string, string>} */ var source = es3fTransformFeedbackTests.genShaderSources(spec, primitiveType === gluDrawUtil.primitiveType.POINTS /* Is point size required? */);
+
+ var programSources = new gluShaderProgram.ProgramSources();
+ programSources.add(new gluShaderProgram.VertexSource(source.vertSource))
+ .add(new gluShaderProgram.FragmentSource(source.fragSource))
+ .add(new gluShaderProgram.TransformFeedbackVaryings(spec.getTransformFeedbackVaryings()))
+ .add(new gluShaderProgram.TransformFeedbackMode(bufferMode));
+
+ return new gluShaderProgram.ShaderProgram(gl, programSources);
+
+ };
+
+ /**
+ * @param {Array<es3fTransformFeedbackTests.Attribute>} attributes
+ * @param {Array<es3fTransformFeedbackTests.Varying>} varyings
+ * @param {boolean} usePointSize
+ * @return {number} input stride
+ */
+ es3fTransformFeedbackTests.computeInputLayout = function(attributes, varyings, usePointSize) {
+
+ var inputStride = 0;
+
+ // Add position
+ var dataTypeVec4 = gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.precision.PRECISION_HIGHP);
+ attributes.push(new es3fTransformFeedbackTests.Attribute('a_position', dataTypeVec4, inputStride));
+ inputStride += 4 * 4; /*sizeof(deUint32)*/
+
+ if (usePointSize) {
+ var dataTypeFloat = gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT, gluShaderUtil.precision.PRECISION_HIGHP);
+ attributes.push(new es3fTransformFeedbackTests.Attribute('a_pointSize', dataTypeFloat, inputStride));
+ inputStride += 1 * 4; /*sizeof(deUint32)*/
+ }
+
+ for (var i = 0; i < varyings.length; i++) {
+ for (var vecIter = new gluVarTypeUtil.VectorTypeIterator(varyings[i].type); !vecIter.end(); vecIter.next()) {
+ var type = vecIter.getType(); // originally getType() in getVarType() within gluVARTypeUtil.hpp.
+ var name = es3fTransformFeedbackTests.getAttributeName(varyings[i].name, vecIter.getPath());
+
+ attributes.push(new es3fTransformFeedbackTests.Attribute(name, type, inputStride));
+ inputStride += gluShaderUtil.getDataTypeScalarSize(type.getBasicType()) * 4; /*sizeof(deUint32)*/
+ }
+ }
+
+ return inputStride;
+ };
+
+ /**
+ * @param {Array<es3fTransformFeedbackTests.Output>} transformFeedbackOutputs
+ * @param {Array<es3fTransformFeedbackTests.Attribute>} attributes
+ * @param {Array<es3fTransformFeedbackTests.Varying>} varyings
+ * @param {Array<string>} transformFeedbackVaryings
+ * @param {number} bufferMode
+ */
+ es3fTransformFeedbackTests.computeTransformFeedbackOutputs = function(transformFeedbackOutputs, attributes, varyings, transformFeedbackVaryings, bufferMode) {
+
+ /** @type {number} */ var accumulatedSize = 0;
+
+ // transformFeedbackOutputs.resize(transformFeedbackVaryings.size());
+ for (var varNdx = 0; varNdx < transformFeedbackVaryings.length; varNdx++) {
+ /** @type {string} */ var name = transformFeedbackVaryings[varNdx];
+ /** @type {number} */ var bufNdx = (bufferMode === gl.SEPARATE_ATTRIBS ? varNdx : 0);
+ /** @type {number} */ var offset = (bufferMode === gl.SEPARATE_ATTRIBS ? 0 : accumulatedSize);
+ /** @type {es3fTransformFeedbackTests.Output} */ var output = new es3fTransformFeedbackTests.Output();
+
+ output.name = name;
+ output.bufferNdx = bufNdx;
+ output.offset = offset;
+
+ if (name === 'gl_Position') {
+ var posIn = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_position');
+ output.type = posIn.type;
+ output.inputs.push(posIn);
+ } else if (name === 'gl_PointSize') {
+ var sizeIn = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_pointSize');
+ output.type = sizeIn.type;
+ output.inputs.push(sizeIn);
+ } else {
+ var varName = gluVarTypeUtil.parseVariableName(name);
+ var varying = es3fTransformFeedbackTests.findAttributeNameEquals(varyings, varName);
+
+ var varPath = gluVarTypeUtil.parseTypePath(name, varying.type);
+ output.type = gluVarTypeUtil.getVarType(varying.type, varPath);
+
+ // Add all vectorized attributes as inputs.
+ for (var iter = new gluVarTypeUtil.VectorTypeIterator(output.type); !iter.end(); iter.next()) {
+ var fullpath = varPath.concat(iter.getPath());
+ var attribName = es3fTransformFeedbackTests.getAttributeName(varName, fullpath);
+ var attrib = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, attribName);
+ output.inputs.push(attrib);
+ }
+ }
+ transformFeedbackOutputs.push(output);
+ accumulatedSize += output.type.getScalarSize() * 4; /*sizeof(deUint32)*/
+ }
+ };
+
+ /**
+ * @param {es3fTransformFeedbackTests.Attribute} attrib
+ * @param {ArrayBuffer} buffer
+ * @param {number} stride
+ * @param {number} numElements
+ * @param {deRandom.Random} rnd
+ */
+ es3fTransformFeedbackTests.genAttributeData = function(attrib, buffer, stride, numElements, rnd) {
+
+ /** @type {number} */ var elementSize = 4; /*sizeof(deUint32)*/
+ /** @type {boolean} */ var isFloat = gluShaderUtil.isDataTypeFloatOrVec(attrib.type.getBasicType());
+ /** @type {boolean} */ var isInt = gluShaderUtil.isDataTypeIntOrIVec(attrib.type.getBasicType());
+ /** @type {boolean} */ var isUint = gluShaderUtil.isDataTypeUintOrUVec(attrib.type.getBasicType());
+
+ /** @type {gluShaderUtil.precision} */ var precision = attrib.type.getPrecision();
+
+ /** @type {number} */ var numComps = gluShaderUtil.getDataTypeScalarSize(attrib.type.getBasicType());
+
+ for (var elemNdx = 0; elemNdx < numElements; elemNdx++) {
+ for (var compNdx = 0; compNdx < numComps; compNdx++) {
+ /** @type {number} */ var offset = attrib.offset + elemNdx * stride + compNdx * elementSize;
+ if (isFloat) {
+ var pos = new Float32Array(buffer, offset, 1);
+ switch (precision) {
+ case gluShaderUtil.precision.PRECISION_LOWP: pos[0] = 0.25 * rnd.getInt(0, 4); break;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: pos[0] = rnd.getFloat(-1e3, 1e3); break;
+ case gluShaderUtil.precision.PRECISION_HIGHP: pos[0] = rnd.getFloat(-1e5, 1e5); break;
+ default: throw new Error('Unknown precision: ' + precision);
+ }
+ } else if (isInt) {
+ var pos = new Int32Array(buffer, offset, 1);
+ switch (precision) {
+ case gluShaderUtil.precision.PRECISION_LOWP: pos[0] = rnd.getInt(-128, 127); break;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: pos[0] = rnd.getInt(-32768, 32767); break;
+ case gluShaderUtil.precision.PRECISION_HIGHP: pos[0] = rnd.getInt(); break;
+ default: throw new Error('Unknown precision: ' + precision);
+ }
+ } else if (isUint) {
+ var pos = new Uint32Array(buffer, offset, 1);
+ switch (precision) {
+ case gluShaderUtil.precision.PRECISION_LOWP: pos[0] = rnd.getInt(0, 255); break;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: pos[0] = rnd.getInt(0, 65535); break;
+ case gluShaderUtil.precision.PRECISION_HIGHP: pos[0] = Math.abs(rnd.getInt()); break;
+ default: throw new Error('Unknown precision: ' + precision);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * @param {Array<es3fTransformFeedbackTests.Attribute>} attributes
+ * @param {number} numInputs
+ * @param {number} inputStride
+ * @param {deRandom.Random} rnd
+ * @return {ArrayBuffer}
+ */
+ es3fTransformFeedbackTests.genInputData = function(attributes, numInputs, inputStride, rnd) {
+ var buffer = new ArrayBuffer(numInputs * inputStride);
+
+ var position = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_position');
+ if (!position)
+ throw new Error('Position attribute not found.');
+
+ for (var ndx = 0; ndx < numInputs; ndx++) {
+ var pos = new Float32Array(buffer, position.offset + inputStride * ndx, 4);
+ pos[0] = rnd.getFloat(-1.2, 1.2);
+ pos[1] = rnd.getFloat(-1.2, 1.2);
+ pos[2] = rnd.getFloat(-1.2, 1.2);
+ pos[3] = rnd.getFloat(0.1, 2.0);
+ }
+
+ var pointSizePos = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_pointSize');
+ if (pointSizePos) {
+ for (var ndx = 0; ndx < numInputs; ndx++) {
+ var pos = new Float32Array(buffer, pointSizePos.offset + inputStride * ndx, 1);
+ pos[0] = rnd.getFloat(1, 8);
+ }
+ }
+
+ // Random data for rest of components.
+ for (var i = 0; i < attributes.length; i++) {
+ if (attributes[i].name != 'a_position' && attributes[i].name != 'a_pointSize')
+ es3fTransformFeedbackTests.genAttributeData(attributes[i], buffer, inputStride, numInputs, rnd);
+ }
+
+ return buffer;
+ };
+
+ /**
+ * Returns the number of outputs with the es3fTransformFeedbackTests.count for the Primitives in the Transform Feedback.
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {number} numElements
+ * @return {number}
+ */
+ es3fTransformFeedbackTests.getTransformFeedbackOutputCount = function(primitiveType, numElements) {
+
+ switch (primitiveType) {
+ case gluDrawUtil.primitiveType.TRIANGLES: return numElements - numElements % 3;
+ case gluDrawUtil.primitiveType.TRIANGLE_STRIP: return Math.max(0, numElements - 2) * 3;
+ case gluDrawUtil.primitiveType.TRIANGLE_FAN: return Math.max(0, numElements - 2) * 3;
+ case gluDrawUtil.primitiveType.LINES: return numElements - numElements % 2;
+ case gluDrawUtil.primitiveType.LINE_STRIP: return Math.max(0, numElements - 1) * 2;
+ case gluDrawUtil.primitiveType.LINE_LOOP: return numElements > 1 ? numElements * 2 : 0;
+ case gluDrawUtil.primitiveType.POINTS: return numElements;
+ default:
+ throw new Error('Unrecognized primitiveType ' + primitiveType);
+ }
+
+ };
+
+ /**
+ * Returns a number with the es3fTransformFeedbackTests.count for the Primitives in the Transform Feedback.
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {number} numElements
+ * @return {number}
+ */
+ es3fTransformFeedbackTests.getTransformFeedbackPrimitiveCount = function(primitiveType, numElements) {
+
+ switch (primitiveType) {
+ case gluDrawUtil.primitiveType.TRIANGLES: return Math.floor(numElements / 3);
+ case gluDrawUtil.primitiveType.TRIANGLE_STRIP: return Math.max(0, numElements - 2);
+ case gluDrawUtil.primitiveType.TRIANGLE_FAN: return Math.max(0, numElements - 2);
+ case gluDrawUtil.primitiveType.LINES: return Math.floor(numElements / 2);
+ case gluDrawUtil.primitiveType.LINE_STRIP: return Math.max(0, numElements - 1);
+ case gluDrawUtil.primitiveType.LINE_LOOP: return numElements > 1 ? numElements : 0;
+ case gluDrawUtil.primitiveType.POINTS: return numElements;
+ default:
+ throw new Error('Unrecognized primitiveType ' + primitiveType);
+ }
+
+ };
+
+ /**
+ * Returns the type of Primitive Mode: Triangles for all Triangle Primitive's type and same for Line and Points.
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @return {number} primitiveType
+ */
+ es3fTransformFeedbackTests.getTransformFeedbackPrimitiveMode = function(primitiveType) {
+
+ switch (primitiveType) {
+ case gluDrawUtil.primitiveType.TRIANGLES:
+ case gluDrawUtil.primitiveType.TRIANGLE_STRIP:
+ case gluDrawUtil.primitiveType.TRIANGLE_FAN:
+ return gl.TRIANGLES;
+
+ case gluDrawUtil.primitiveType.LINES:
+ case gluDrawUtil.primitiveType.LINE_STRIP:
+ case gluDrawUtil.primitiveType.LINE_LOOP:
+ return gl.LINES;
+
+ case gluDrawUtil.primitiveType.POINTS:
+ return gl.POINTS;
+
+ default:
+ throw new Error('Unrecognized primitiveType ' + primitiveType);
+ }
+
+ };
+
+ /**
+ * Returns the attribute index for a certain primitive type.
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {number} numInputs
+ * @param {number} outNdx
+ * @return {number}
+ */
+ es3fTransformFeedbackTests.getAttributeIndex = function(primitiveType, numInputs, outNdx) {
+
+ switch (primitiveType) {
+
+ case gluDrawUtil.primitiveType.TRIANGLES: return outNdx;
+ case gluDrawUtil.primitiveType.LINES: return outNdx;
+ case gluDrawUtil.primitiveType.POINTS: return outNdx;
+
+ case gluDrawUtil.primitiveType.TRIANGLE_STRIP: {
+ /** @type {number} */ var triNdx = outNdx / 3;
+ /** @type {number} */ var vtxNdx = outNdx % 3;
+ return (triNdx % 2 != 0 && vtxNdx < 2) ? (triNdx + 1 - vtxNdx) : (triNdx + vtxNdx);
+ }
+
+ case gluDrawUtil.primitiveType.TRIANGLE_FAN:
+ return (outNdx % 3 != 0) ? (outNdx / 3 + outNdx % 3) : 0;
+
+ case gluDrawUtil.primitiveType.LINE_STRIP:
+ return outNdx / 2 + outNdx % 2;
+
+ case gluDrawUtil.primitiveType.LINE_LOOP: {
+ var inNdx = outNdx / 2 + outNdx % 2;
+ return inNdx < numInputs ? inNdx : 0;
+ }
+
+ default:
+ throw new Error('Unrecognized primitiveType ' + primitiveType);
+ }
+
+ };
+
+ /**
+ * @param {gluDrawUtil.primitiveType} primitiveType type number in gluDrawUtil.primitiveType
+ * @param {es3fTransformFeedbackTests.Output} output
+ * @param {number} numInputs
+ * @param {Object} buffers
+ * @return {boolean} isOk
+ */
+ es3fTransformFeedbackTests.compareTransformFeedbackOutput = function(primitiveType, output, numInputs, buffers) {
+ /** @type {boolean} */ var isOk = true;
+ /** @type {number} */ var outOffset = output.offset;
+
+ for (var attrNdx = 0; attrNdx < output.inputs.length; attrNdx++) {
+ /** @type {es3fTransformFeedbackTests.Attribute} */ var attribute = output.inputs[attrNdx];
+ /** @type {gluShaderUtil.DataType} */ var type = attribute.type.getBasicType();
+ /** @type {number} */ var numComponents = gluShaderUtil.getDataTypeScalarSize(type);
+
+ /** @type {gluShaderUtil.precision} */ var precision = attribute.type.getPrecision();
+
+ /** @type {string} */ var scalarType = gluShaderUtil.getDataTypeScalarType(type);
+ /** @type {number} */ var numOutputs = es3fTransformFeedbackTests.getTransformFeedbackOutputCount(primitiveType, numInputs);
+
+ for (var outNdx = 0; outNdx < numOutputs; outNdx++) {
+ /** @type {number} */ var inNdx = es3fTransformFeedbackTests.getAttributeIndex(primitiveType, numInputs, outNdx);
+
+ for (var compNdx = 0; compNdx < numComponents; compNdx++) {
+ /** @type {boolean} */ var isEqual = false;
+
+ if (scalarType === 'float') {
+ var outBuffer = new Float32Array(buffers.output.buffer, buffers.output.offset + buffers.output.stride * outNdx + outOffset + compNdx * 4, 1);
+ var inBuffer = new Float32Array(buffers.input.buffer, buffers.input.offset + buffers.input.stride * inNdx + attribute.offset + compNdx * 4, 1);
+ var difInOut = inBuffer[0] - outBuffer[0];
+ /* TODO: Original code used ULP comparison for highp and mediump precision. This could cause failures. */
+ switch (precision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP: {
+ isEqual = Math.abs(difInOut) < 0.1;
+ break;
+ }
+
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: {
+ isEqual = Math.abs(difInOut) < 0.1;
+ break;
+ }
+
+ case gluShaderUtil.precision.PRECISION_LOWP: {
+ isEqual = Math.abs(difInOut) < 0.1;
+ break;
+ }
+ default:
+ throw new Error('Unknown precision: ' + precision);
+ }
+ } else {
+ var outBuffer = new Uint32Array(buffers.output.buffer, buffers.output.offset + buffers.output.stride * outNdx + outOffset + compNdx * 4, 1);
+ var inBuffer = new Uint32Array(buffers.input.buffer, buffers.input.offset + buffers.input.stride * inNdx + attribute.offset + compNdx * 4, 1);
+ isEqual = (inBuffer[0] == outBuffer[0]); // Bit-exact match required for integer types.
+ }
+
+ if (!isEqual) {
+ bufferedLogToConsole('Mismatch in ' + output.name + ' (' + attribute.name + '), output = ' + outNdx + ', input = ' + inNdx + ', component = ' + compNdx);
+ isOk = false;
+ break;
+ }
+ }
+
+ if (!isOk)
+ break;
+ }
+
+ if (!isOk)
+ break;
+
+ outOffset += numComponents * 4; /*sizeof(deUint32)*/
+ }
+
+ return isOk;
+ };
+
+ /**
+ * Returns (for all the draw calls) the type of Primitive Mode, as it calls "es3fTransformFeedbackTests.getTransformFeedbackPrimitiveCount".
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {Array<es3fTransformFeedbackTests.DrawCall>} array Object.<number, boolean>
+ * @return {number} primCount
+ */
+ es3fTransformFeedbackTests.computeTransformFeedbackPrimitiveCount = function(primitiveType, array) {
+
+ /** @type {number} */ var primCount = 0;
+
+ for (var i = 0; i < array.length; ++ i) {
+
+ if (array[i].transformFeedbackEnabled)
+ primCount += es3fTransformFeedbackTests.getTransformFeedbackPrimitiveCount(primitiveType, array[i].numElements);
+ }
+
+ return primCount;
+ };
+
+ /**
+ * @param {number} target
+ * @param {number} bufferSize
+ * @param {number} guardSize
+ */
+ es3fTransformFeedbackTests.writeBufferGuard = function(target, bufferSize, guardSize) {
+ var buffer = new ArrayBuffer(guardSize);
+ var view = new Uint8Array(buffer);
+ for (var i = 0; i < guardSize; ++i) view[i] = 0xcd;
+ gl.bufferSubData(target, bufferSize, buffer);
+ };
+
+ /**
+ * Verifies guard
+ * @param {ArrayBuffer} buffer
+ * @param {number} start
+ * @return {boolean}
+ */
+ es3fTransformFeedbackTests.verifyGuard = function(buffer, start) {
+ start = start || 0;
+ var view = new Uint8Array(buffer, start);
+ for (var i = 0; i < view.length; i++) {
+ if (view[i] != 0xcd)
+ return false;
+ }
+ return true;
+ };
+
+ /**
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @constructor
+ */
+ es3fTransformFeedbackTests.TransformFeedbackCase = function(name, desc, bufferMode, primitiveType) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_bufferMode = bufferMode;
+ this.m_primitiveType = primitiveType;
+ this.m_progSpec = new es3fTransformFeedbackTests.ProgramSpec();
+
+ // Derived from es3fTransformFeedbackTests.ProgramSpec in es3fTransformFeedbackTests.init()
+ this.m_inputStride = 0;
+ this.m_attributes = []; // vector<es3fTransformFeedbackTests.Attribute>
+ this.m_transformFeedbackOutputs = []; // vector<es3fTransformFeedbackTests.Output>
+ this.m_bufferStrides = []; // vector<int>
+
+ // GL state.
+ this.m_program = null; // glu::ShaderProgram
+ this.m_transformFeedback = null; // glu::TransformFeedback
+ this.m_outputBuffers = []; // vector<deUint32>
+
+ this.m_iterNdx = 0; // int
+ this.m_testPassed = true;
+ // State machine
+ this.m_state = es3fTransformFeedbackTests.State.DRAW;
+ this.m_verifyStart = null;
+
+ this.m_frameWithTf = null;
+ this.m_frameWithoutTf = null;
+
+ this.m_viewportW = 0;
+ this.m_viewportH = 0;
+ this.m_viewportX = 0;
+ this.m_viewportY = 0;
+
+ this.m_primitiveQuery = null;
+ this.m_outputsOk = true;
+
+ };
+
+ setParentClass(es3fTransformFeedbackTests.TransformFeedbackCase, tcuTestCase.DeqpTest);
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.createVerificationResult = function(retry, result) {
+ return { retry: retry, result: result };
+ }
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.dumpShaderText = function() {
+ var dbgext = gl.getExtension('WEBGL_debug_shaders');
+ for (var ii = 0; ii < this.m_program.shaders.length; ++ii) {
+ debug('Shader source ' + ii + ' before translation:')
+ debug(this.m_program.shaders[ii].info.source);
+ debug('');
+ debug('Shader source ' + ii + ' after translation:');
+ debug(dbgext.getTranslatedShaderSource(this.m_program.shaders[ii].shader));
+ }
+ };
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.init = function() {
+ this.m_program = es3fTransformFeedbackTests.createVertexCaptureProgram(
+ this.m_progSpec,
+ this.m_bufferMode,
+ this.m_primitiveType
+ );
+
+ if (!this.m_program.isOk()) {
+ // this.dumpShaderText();
+
+ var linkFail = this.m_program.shadersOK &&
+ !this.m_program.getProgramInfo().linkOk;
+
+ if (linkFail) {
+ if (!es3fTransformFeedbackTests.isProgramSupported(this.m_progSpec, this.m_bufferMode)) {
+ var msg = 'Not Supported. Implementation limits exceeded.';
+ checkMessage(false, msg);
+ throw new TestFailedException(msg);
+ } else if (es3fTransformFeedbackTests.hasArraysInTFVaryings(this.m_progSpec)) {
+ msg = 'Capturing arrays is not supported (undefined in specification)';
+ checkMessage(false, msg);
+ throw new TestFailedException(msg);
+ } else {
+ throw new Error('Link failed: ' + this.m_program.getProgramInfo().infoLog);
+ }
+ } else {
+ throw new Error('Compile failed');
+ }
+ } else {
+ // debug('Program is ' +
+ // (gl.getProgramParameter(this.m_program.getProgram(), gl.LINK_STATUS) ? 'linked' : 'not linked'));
+ // this.dumpShaderText();
+ }
+
+// bufferedLogToConsole('Transform feedback varyings: ' + tcu.formatArray(this.m_progSpec.getTransformFeedbackVaryings()));
+ bufferedLogToConsole('Transform feedback varyings: ' + this.m_progSpec.getTransformFeedbackVaryings());
+
+ // Print out transform feedback points reported by GL.
+ // bufferedLogToConsole('Transform feedback varyings reported by compiler:');
+ //logTransformFeedbackVaryings(log, gl, this.m_program.getProgram());
+
+ // Compute input specification.
+ this.m_inputStride = es3fTransformFeedbackTests.computeInputLayout(this.m_attributes, this.m_progSpec.getVaryings(), this.m_progSpec.isPointSizeUsed());
+
+ // Build list of varyings used in transform feedback.
+ es3fTransformFeedbackTests.computeTransformFeedbackOutputs(
+ this.m_transformFeedbackOutputs,
+ this.m_attributes,
+ this.m_progSpec.getVaryings(),
+ this.m_progSpec.getTransformFeedbackVaryings(),
+ this.m_bufferMode
+ );
+ if (!this.m_transformFeedbackOutputs.length) {
+ throw new Error('transformFeedbackOutputs cannot be empty.');
+ }
+
+ if (this.m_bufferMode == gl.SEPARATE_ATTRIBS) {
+ for (var i = 0; i < this.m_transformFeedbackOutputs.length; ++i) {
+ this.m_bufferStrides.push(this.m_transformFeedbackOutputs[i].type.getScalarSize() * 4 /*sizeof(deUint32)*/);
+ }
+ } else {
+ var totalSize = 0;
+ for (var i = 0; i < this.m_transformFeedbackOutputs.length; ++i) {
+ totalSize += this.m_transformFeedbackOutputs[i].type.getScalarSize() * 4 /*sizeof(deUint32)*/;
+ }
+ this.m_bufferStrides.push(totalSize);
+ }
+
+ this.m_outputBuffers.length = this.m_bufferStrides.length;
+ for (var i = 0; i < this.m_outputBuffers.length; i++)
+ this.m_outputBuffers[i] = gl.createBuffer();
+
+ this.m_transformFeedback = gl.createTransformFeedback();
+
+ this.m_iterNdx = 0;
+// this.m_testCtx.setTestResult(QP_TEST_RESULT_PASS, 'Pass');
+
+ };
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.deinit = function() {
+ for (var i = 0; i < this.m_outputBuffers.length; i++)
+ gl.deleteBuffer(this.m_outputBuffers[i]);
+
+ // delete this.m_transformFeedback;
+ this.m_transformFeedback = null;
+
+ // delete this.m_program;
+ this.m_program = null;
+
+ // Clean up state.
+ this.m_attributes = [];
+ this.m_transformFeedbackOutputs = [];
+ this.m_bufferStrides = [];
+ this.m_inputStride = 0;
+
+ };
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.iterate = function() {
+ var s = es3fTransformFeedbackTests.TransformFeedbackCase.s_iterate;
+ var numIterations = s.iterations.length;
+ var seed = deMath.deMathHash(this.m_iterNdx);
+ switch(this.m_state) {
+ case es3fTransformFeedbackTests.State.DRAW:
+ bufferedLogToConsole('Testing ' +
+ s.testCases[s.iterations[this.m_iterNdx]].length +
+ ' draw calls, (element es3fTransformFeedbackTests.count, TF state): ' +
+ s.testCases[s.iterations[this.m_iterNdx]]
+ );
+ this.draw(s.testCases[s.iterations[this.m_iterNdx]], seed);
+ this.m_state = es3fTransformFeedbackTests.State.VERIFY;
+ break;
+ case es3fTransformFeedbackTests.State.VERIFY:
+ var verifyResult = this.verify(s.testCases[s.iterations[this.m_iterNdx]]);
+ if (verifyResult.retry) {
+ break;
+ }
+ this.m_testPassed = verifyResult.result;
+ this.m_iterNdx += 1;
+ if (this.m_testPassed && this.m_iterNdx < numIterations) {
+ this.m_state = es3fTransformFeedbackTests.State.DRAW;
+ break;
+ }
+ // Fall through
+ case es3fTransformFeedbackTests.State.FINISH:
+ if (!this.m_testPassed) testFailedOptions('Result comparison failed for iteration ' + s.iterations[this.m_iterNdx - 1], false);
+ else testPassedOptions('Result comparison succeeded', true);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ return tcuTestCase.IterateResult.CONTINUE;
+
+ };
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.draw = function(calls, seed) {
+ var _min = function(x, y) { return x < y ? x : y; };
+
+ var rnd = new deRandom.Random(seed);
+ var numInputs = 0;
+ var numOutputs = 0;
+ var width = gl.drawingBufferWidth;
+ var height = gl.drawingBufferHeight;
+ this.m_viewportW = _min(es3fTransformFeedbackTests.VIEWPORT_WIDTH, width);
+ this.m_viewportH = _min(es3fTransformFeedbackTests.VIEWPORT_HEIGHT, height);
+ this.m_viewportX = rnd.getInt(0, width - this.m_viewportW);
+ this.m_viewportY = rnd.getInt(0, height - this.m_viewportH);
+ this.m_frameWithTf = new tcuSurface.Surface(this.m_viewportW, this.m_viewportH); // tcu::Surface
+ this.m_frameWithoutTf = new tcuSurface.Surface(this.m_viewportW, this.m_viewportH); // tcu::Surface
+ this.m_primitiveQuery = gl.createQuery();
+ this.m_outputsOk = true;
+
+ // Compute totals.
+ for (var i = 0; i < calls.length; ++i) {
+ var call = calls[i];
+ numInputs += call.numElements;
+ numOutputs += call.transformFeedbackEnabled ? es3fTransformFeedbackTests.getTransformFeedbackOutputCount(this.m_primitiveType, call.numElements) : 0;
+ }
+
+ // Input data.
+ var inputData = es3fTransformFeedbackTests.genInputData(this.m_attributes, numInputs, this.m_inputStride, rnd);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, this.m_transformFeedback);
+
+ // Allocate storage for transform feedback output buffers and bind to targets.
+ for (var bufNdx = 0; bufNdx < this.m_outputBuffers.length; ++bufNdx) {
+ var buffer = this.m_outputBuffers[bufNdx]; // deUint32
+ var stride = this.m_bufferStrides[bufNdx]; // int
+ var target = bufNdx; // int
+ var size = stride * numOutputs; // int
+ var guardSize = stride * es3fTransformFeedbackTests.BUFFER_GUARD_MULTIPLIER; // int
+ var usage = gl.DYNAMIC_READ; // const deUint32
+
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, size + guardSize, usage);
+ es3fTransformFeedbackTests.writeBufferGuard(gl.TRANSFORM_FEEDBACK_BUFFER, size, guardSize);
+
+ // \todo [2012-07-30 pyry] glBindBufferRange()?
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, target, buffer);
+ }
+
+ var attribBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, attribBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, inputData, gl.STATIC_DRAW);
+
+ // Setup attributes.
+ for (var i = 0; i < this.m_attributes.length; ++i) {
+ var attrib = this.m_attributes[i];
+ var loc = gl.getAttribLocation(this.m_program.getProgram(), attrib.name);
+ /** @type {string} */
+ var scalarType = gluShaderUtil.getDataTypeScalarType(attrib.type.getBasicType());
+ /** @type {number} */
+ var numComponents = gluShaderUtil.getDataTypeScalarSize(attrib.type.getBasicType());
+
+ if (loc >= 0) {
+ gl.enableVertexAttribArray(loc);
+ switch (scalarType) {
+ case 'float':
+ gl.vertexAttribPointer(loc, numComponents, gl.FLOAT, false, this.m_inputStride, attrib.offset); break;
+ case 'int':
+ gl.vertexAttribIPointer(loc, numComponents, gl.INT, this.m_inputStride, attrib.offset); break;
+ case 'uint':
+ gl.vertexAttribIPointer(loc, numComponents, gl.UNSIGNED_INT, this.m_inputStride, attrib.offset); break;
+ }
+ }
+ }
+
+ // Setup viewport.
+ gl.viewport(this.m_viewportX, this.m_viewportY, this.m_viewportW, this.m_viewportH);
+
+ // Setup program.
+ gl.useProgram(this.m_program.getProgram());
+
+ gl.uniform4fv(
+ gl.getUniformLocation(this.m_program.getProgram(), 'u_scale'),
+ [0.01, 0.01, 0.01, 0.01]
+ );
+ gl.uniform4fv(
+ gl.getUniformLocation(this.m_program.getProgram(), 'u_bias'),
+ [0.5, 0.5, 0.5, 0.5]
+ );
+
+ // Enable query.
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, this.m_primitiveQuery);
+
+ // Draw
+ var offset = 0;
+ var tfEnabled = true;
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var tfPrimitiveMode = es3fTransformFeedbackTests.getTransformFeedbackPrimitiveMode(this.m_primitiveType);
+ gl.beginTransformFeedback(tfPrimitiveMode);
+
+ for (var i = 0; i < calls.length; ++i) {
+ var call = calls[i];
+
+ // Pause or resume transform feedback if necessary.
+ if (call.transformFeedbackEnabled != tfEnabled) {
+ if (call.transformFeedbackEnabled)
+ gl.resumeTransformFeedback();
+ else
+ gl.pauseTransformFeedback();
+ tfEnabled = call.transformFeedbackEnabled;
+ }
+
+ gl.drawArrays(gluDrawUtil.getPrimitiveGLType(gl, this.m_primitiveType), offset, call.numElements);
+ offset += call.numElements;
+ }
+
+ // Resume feedback before finishing it.
+ if (!tfEnabled)
+ gl.resumeTransformFeedback();
+
+ gl.endTransformFeedback();
+
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+
+ // Check and log query status right after submit
+ var query = this.m_primitiveQuery;
+
+ var available = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
+
+ if (available) {
+ this.m_testPassed = false;
+ this.m_state = es3fTransformFeedbackTests.State.FINISH;
+ testFailedOptions('Transform feedback query result must not be available the same frame as they are issued.', true);
+ }
+
+ // Compare result buffers.
+ for (var bufferNdx = 0; bufferNdx < this.m_outputBuffers.length; ++bufferNdx) {
+ var stride = this.m_bufferStrides[bufferNdx]; // int
+ var size = stride * numOutputs; // int
+ var guardSize = stride * es3fTransformFeedbackTests.BUFFER_GUARD_MULTIPLIER; // int
+ var buffer = new ArrayBuffer(size + guardSize); // const void*
+
+ // Bind buffer for reading.
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, this.m_outputBuffers[bufferNdx]);
+
+ gl.getBufferSubData(gl.TRANSFORM_FEEDBACK_BUFFER, 0, new Uint8Array(buffer));
+
+ // Verify all output variables that are written to this buffer.
+ for (var i = 0; i < this.m_transformFeedbackOutputs.length; ++i) {
+ var out = this.m_transformFeedbackOutputs[i];
+
+ if (out.bufferNdx != bufferNdx)
+ continue;
+
+ var inputOffset = 0;
+ var outputOffset = 0;
+
+ // Process all draw calls and check ones with transform feedback enabled
+ for (var callNdx = 0; callNdx < calls.length; ++callNdx) {
+ var call = calls[callNdx];
+
+ if (call.transformFeedbackEnabled) {
+ var inputPtr = inputData[0] + inputOffset * this.m_inputStride; // const deUint8*
+ var outputPtr = outputOffset * stride; // const deUint8*
+
+ if (!es3fTransformFeedbackTests.compareTransformFeedbackOutput(this.m_primitiveType, out, call.numElements, {
+ input: {
+ buffer: inputData,
+ offset: inputOffset * this.m_inputStride,
+ stride: this.m_inputStride
+ },
+ output: {
+ buffer: buffer,
+ offset: outputOffset * stride,
+ stride: stride
+ }
+ })) {
+ this.m_outputsOk = false;
+ break;
+ }
+ }
+
+ inputOffset += call.numElements;
+ outputOffset += call.transformFeedbackEnabled ? es3fTransformFeedbackTests.getTransformFeedbackOutputCount(this.m_primitiveType, call.numElements) : 0;
+ }
+ }
+
+ // Verify guardband.
+ if (!es3fTransformFeedbackTests.verifyGuard(buffer, size)) {
+ bufferedLogToConsole('Error: Transform feedback buffer overrun detected');
+ this.m_outputsOk = false;
+ }
+ }
+ };
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.verify = function(calls) {
+ // Check status after mapping buffers.
+ var mustBeReady = this.m_outputBuffers.length > 0; // Mapping buffer forces synchronization. // const bool
+ var expectedCount = es3fTransformFeedbackTests.computeTransformFeedbackPrimitiveCount(this.m_primitiveType, calls); // const int
+ var available = /** @type {boolean} */ (gl.getQueryParameter(this.m_primitiveQuery, gl.QUERY_RESULT_AVAILABLE));
+ var verify_offset = 0;
+ var queryOk = true;
+ if (!available) {
+ if (!this.m_verifyStart)
+ this.m_verifyStart = new Date();
+ else {
+ var current = new Date();
+ var elapsedTime = 0.001 * (current.getTime() - this.m_verifyStart.getTime());
+ if (elapsedTime > es3fTransformFeedbackTests.MAX_VERIFY_WAIT) {
+ testFailed('Query result not available after ' + elapsedTime + ' seconds.');
+ this.m_state = es3fTransformFeedbackTests.State.FINISH;
+ return this.createVerificationResult(false, false);
+ }
+ }
+ return this.createVerificationResult(true, false);
+ }
+
+ var numPrimitives = /** @type {number} */ (gl.getQueryParameter(this.m_primitiveQuery, gl.QUERY_RESULT));
+
+ if (!mustBeReady && available == false)
+ bufferedLogToConsole('ERROR: gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN result not available after mapping buffers!');
+
+ bufferedLogToConsole('gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = ' + numPrimitives);
+
+ if (numPrimitives != expectedCount) {
+ queryOk = false;
+ bufferedLogToConsole('ERROR: Expected ' + expectedCount + ' primitives!');
+ }
+
+ // Clear transform feedback state.
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ for (var bufNdx = 0; bufNdx < this.m_outputBuffers.length; ++bufNdx) {
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, bufNdx, null);
+ }
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ // Read back rendered image.
+ this.m_frameWithTf.readViewport(gl, [this.m_viewportX, this.m_viewportY, this.m_viewportW, this.m_viewportH]);
+
+ // Render without transform feedback.
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ for (var i = 0; i < calls.length; ++i) {
+ var call = calls[i];
+ gl.drawArrays(gluDrawUtil.getPrimitiveGLType(gl, this.m_primitiveType), verify_offset, call.numElements);
+ verify_offset += call.numElements;
+ }
+ this.m_frameWithoutTf.readViewport(gl, [this.m_viewportX, this.m_viewportY, this.m_viewportW, this.m_viewportH]);
+
+ // Compare images with and without transform feedback.
+ var imagesOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', this.m_frameWithoutTf, this.m_frameWithTf, [1, 1, 1, 1], tcuImageCompare.CompareLogMode.ON_ERROR);
+
+ if (imagesOk)
+ bufferedLogToConsole('Rendering result comparison between TF enabled and TF disabled passed.');
+ else
+ bufferedLogToConsole('ERROR: Rendering result comparison between TF enabled and TF disabled failed!');
+
+ return this.createVerificationResult(false, this.m_outputsOk && imagesOk && queryOk);
+
+ };
+
+ es3fTransformFeedbackTests.dc = function(numElements, tfEnabled) {
+ return new es3fTransformFeedbackTests.DrawCall(numElements, tfEnabled);
+ };
+
+ // static data
+ es3fTransformFeedbackTests.TransformFeedbackCase.s_iterate = {
+
+ testCases: {
+ elemCount1: [es3fTransformFeedbackTests.dc(1, true)],
+ elemCount2: [es3fTransformFeedbackTests.dc(2, true)],
+ elemCount3: [es3fTransformFeedbackTests.dc(3, true)],
+ elemCount4: [es3fTransformFeedbackTests.dc(4, true)],
+ elemCount123: [es3fTransformFeedbackTests.dc(123, true)],
+ basicPause1: [es3fTransformFeedbackTests.dc(64, true), es3fTransformFeedbackTests.dc(64, false), es3fTransformFeedbackTests.dc(64, true)],
+ basicPause2: [es3fTransformFeedbackTests.dc(13, true), es3fTransformFeedbackTests.dc(5, true), es3fTransformFeedbackTests.dc(17, false),
+ es3fTransformFeedbackTests.dc(3, true), es3fTransformFeedbackTests.dc(7, false)],
+ startPaused: [es3fTransformFeedbackTests.dc(123, false), es3fTransformFeedbackTests.dc(123, true)],
+ random1: [es3fTransformFeedbackTests.dc(65, true), es3fTransformFeedbackTests.dc(135, false), es3fTransformFeedbackTests.dc(74, true),
+ es3fTransformFeedbackTests.dc(16, false), es3fTransformFeedbackTests.dc(226, false), es3fTransformFeedbackTests.dc(9, true),
+ es3fTransformFeedbackTests.dc(174, false)],
+ random2: [es3fTransformFeedbackTests.dc(217, true), es3fTransformFeedbackTests.dc(171, true), es3fTransformFeedbackTests.dc(147, true),
+ es3fTransformFeedbackTests.dc(152, false), es3fTransformFeedbackTests.dc(55, true)]
+ },
+ iterations: [
+ 'elemCount1', 'elemCount2', 'elemCount3', 'elemCount4', 'elemCount123',
+ 'basicPause1', 'basicPause2', 'startPaused',
+ 'random1', 'random2'
+ ]
+ };
+
+ es3fTransformFeedbackTests.hasArraysInTFVaryings = function(spec) {
+
+ for (var i = 0; i < spec.getTransformFeedbackVaryings().length; ++i) {
+ var tfVar = spec.getTransformFeedbackVaryings()[i];
+ var varName = gluVarTypeUtil.parseVariableName(tfVar);
+
+ var attr = es3fTransformFeedbackTests.findAttributeNameEquals(spec.getVaryings(), varName);
+ if (attr && attr.type.isArrayType())
+ return true;
+ }
+ return false;
+
+ };
+
+ /** es3fTransformFeedbackTests.PositionCase
+ * @extends {es3fTransformFeedbackTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @constructor
+ */
+ es3fTransformFeedbackTests.PositionCase = function(name, desc, bufferMode, primitiveType) {
+ es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType);
+ this.m_progSpec.addTransformFeedbackVarying('gl_Position');
+ };
+
+ setParentClass(es3fTransformFeedbackTests.PositionCase, es3fTransformFeedbackTests.TransformFeedbackCase);
+
+ /** es3fTransformFeedbackTests.PointSizeCase
+ * @extends {es3fTransformFeedbackTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @constructor
+ */
+ es3fTransformFeedbackTests.PointSizeCase = function(name, desc, bufferMode, primitiveType) {
+ es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType);
+ this.m_progSpec.addTransformFeedbackVarying('gl_PointSize');
+
+ };
+
+ setParentClass(es3fTransformFeedbackTests.PointSizeCase, es3fTransformFeedbackTests.TransformFeedbackCase);
+
+ /** es3fTransformFeedbackTests.BasicTypeCase
+ * @extends {es3fTransformFeedbackTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {gluShaderUtil.DataType} type
+ * @param {gluShaderUtil.precision} precision
+ * @param {es3fTransformFeedbackTests.interpolation} interpolation enum number in this javascript
+ * @constructor
+ */
+ es3fTransformFeedbackTests.BasicTypeCase = function(name, desc, bufferMode, primitiveType, type, precision, interpolation) {
+ es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType);
+
+ this.m_progSpec.addVarying('v_varA', gluVarType.newTypeBasic(type, precision), interpolation);
+ this.m_progSpec.addVarying('v_varB', gluVarType.newTypeBasic(type, precision), interpolation);
+
+ this.m_progSpec.addTransformFeedbackVarying('v_varA');
+ this.m_progSpec.addTransformFeedbackVarying('v_varB');
+
+ };
+
+ setParentClass(es3fTransformFeedbackTests.BasicTypeCase, es3fTransformFeedbackTests.TransformFeedbackCase);
+
+ /** es3fTransformFeedbackTests.BasicArrayCase
+ * @extends {es3fTransformFeedbackTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {gluShaderUtil.DataType} type
+ * @param {gluShaderUtil.precision} precision
+ * @param {es3fTransformFeedbackTests.interpolation} interpolation enum number in this javascript
+ * @constructor
+ */
+ es3fTransformFeedbackTests.BasicArrayCase = function(name, desc, bufferMode, primitiveType, type, precision, interpolation) {
+ es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType);
+
+ if (gluShaderUtil.isDataTypeMatrix(type) || this.m_bufferMode === gl.SEPARATE_ATTRIBS) {
+ // note For matrix types we need to use reduced array sizes or otherwise we will exceed maximum attribute (16)
+ // or transform feedback component es3fTransformFeedbackTests.count (64).
+ // On separate attribs mode maximum component es3fTransformFeedbackTests.count per varying is 4.
+ this.m_progSpec.addVarying('v_varA', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 1), interpolation);
+ this.m_progSpec.addVarying('v_varB', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 2), interpolation);
+ } else {
+ this.m_progSpec.addVarying('v_varA', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 3), interpolation);
+ this.m_progSpec.addVarying('v_varB', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 4), interpolation);
+ }
+
+ this.m_progSpec.addTransformFeedbackVarying('v_varA');
+ this.m_progSpec.addTransformFeedbackVarying('v_varB');
+
+ };
+
+ setParentClass(es3fTransformFeedbackTests.BasicArrayCase, es3fTransformFeedbackTests.TransformFeedbackCase);
+
+ /** es3fTransformFeedbackTests.ArrayElementCase
+ * @extends {es3fTransformFeedbackTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {gluShaderUtil.DataType} type
+ * @param {gluShaderUtil.precision} precision
+ * @param {es3fTransformFeedbackTests.interpolation} interpolation enum number in this javascript
+ * @constructor
+ */
+ es3fTransformFeedbackTests.ArrayElementCase = function(name, desc, bufferMode, primitiveType, type, precision, interpolation) {
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType);
+
+ this.m_progSpec.addVarying('v_varA', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 3), interpolation);
+ this.m_progSpec.addVarying('v_varB', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 4), interpolation);
+
+ this.m_progSpec.addTransformFeedbackVarying('v_varA[1]');
+ this.m_progSpec.addTransformFeedbackVarying('v_varB[0]');
+ this.m_progSpec.addTransformFeedbackVarying('v_varB[3]');
+
+ };
+
+ setParentClass(es3fTransformFeedbackTests.ArrayElementCase, es3fTransformFeedbackTests.TransformFeedbackCase);
+
+ /** es3fTransformFeedbackTests.RandomCase
+ * @extends {es3fTransformFeedbackTests.TransformFeedbackCase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} bufferMode
+ * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is
+ * @param {number} seed
+ * @constructor
+ */
+ es3fTransformFeedbackTests.RandomCase = function(name, desc, bufferMode, primitiveType, seed) {
+ es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType);
+
+ };
+
+ setParentClass(es3fTransformFeedbackTests.RandomCase, es3fTransformFeedbackTests.TransformFeedbackCase);
+
+ es3fTransformFeedbackTests.RandomCase.prototype.init = function() {
+
+ /** @type {number} */
+ var seed = /*deString.deStringHash(getName()) ^ */ deMath.deMathHash(this.m_iterNdx);
+
+ /** @type {Array<gluShaderUtil.DataType>} */
+ var typeCandidates = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4,
+
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3,
+ gluShaderUtil.DataType.FLOAT_MAT4
+ ];
+
+ /** @type {Array<gluShaderUtil.precision>} */
+ var precisions = [
+ gluShaderUtil.precision.PRECISION_LOWP,
+ gluShaderUtil.precision.PRECISION_MEDIUMP,
+ gluShaderUtil.precision.PRECISION_HIGHP
+ ];
+
+ var interpModes = [{name: 'smooth', interp: es3fTransformFeedbackTests.interpolation.SMOOTH}, {name: 'flat', interp: es3fTransformFeedbackTests.interpolation.FLAT}, {name: 'centroid', interp: es3fTransformFeedbackTests.interpolation.CENTROID}
+ ];
+
+ /** @type {number} */ var maxAttributeVectors = 16;
+ //** @type {number} */ var maxTransformFeedbackComponents = 64; // note It is enough to limit attribute set size.
+ /** @type {boolean} */ var isSeparateMode = (this.m_bufferMode === gl.SEPARATE_ATTRIBS);
+ /** @type {number} */ var maxTransformFeedbackVars = isSeparateMode ? 4 : maxAttributeVectors;
+ /** @type {number} */ var arrayWeight = 0.3;
+ /** @type {number} */ var positionWeight = 0.7;
+ /** @type {number} */ var pointSizeWeight = 0.1;
+ /** @type {number} */ var captureFullArrayWeight = 0.5;
+
+ /** @type {deRandom.Random} */
+ var rnd = new deRandom.Random(seed);
+ /** @type {boolean} */ var usePosition = rnd.getFloat() < positionWeight;
+ /** @type {boolean} */ var usePointSize = rnd.getFloat() < pointSizeWeight;
+ /** @type {number} */ var numAttribVectorsToUse = rnd.getInt(
+ 1, maxAttributeVectors - 1/*position*/ - (usePointSize ? 1 : 0)
+ );
+
+ /** @type {number} */ var numAttributeVectors = 0;
+ /** @type {number} */ var varNdx = 0;
+
+ // Generate varyings.
+ while (numAttributeVectors < numAttribVectorsToUse) {
+ /** @type {number} */
+ var maxVecs = isSeparateMode ? Math.min(2 /*at most 2*mat2*/, numAttribVectorsToUse - numAttributeVectors) : numAttribVectorsToUse - numAttributeVectors;
+ /** @type {gluShaderUtil.DataType} */
+ var begin = typeCandidates[0];
+ /** @type {number} */
+ var endCandidates = begin + (
+ maxVecs >= 4 ? 21 : (
+ maxVecs >= 3 ? 18 : (
+ maxVecs >= 2 ? (isSeparateMode ? 13 : 15) : 12
+ )
+ )
+ );
+ /** @type {gluShaderUtil.DataType} */
+ var end = typeCandidates[endCandidates];
+
+ /** @type {gluShaderUtil.DataType} */
+ var type = rnd.choose(typeCandidates)[0];
+
+ /** @type {gluShaderUtil.precision} */
+ var precision = rnd.choose(precisions)[0];
+
+ /** @type {es3fTransformFeedbackTests.interpolation} */
+ var interp = (type === gluShaderUtil.DataType.FLOAT) ?
+ rnd.choose(interpModes)[0].interp :
+ es3fTransformFeedbackTests.interpolation.FLAT;
+
+ /** @type {number} */
+ var numVecs = gluShaderUtil.isDataTypeMatrix(type) ? gluShaderUtil.getDataTypeMatrixNumColumns(type) : 1;
+ /** @type {number} */
+ var numComps = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {number} */
+ var maxArrayLen = Math.max(1, isSeparateMode ? (4 / numComps) : (maxVecs / numVecs));
+ /** @type {boolean} */
+ var useArray = rnd.getFloat() < arrayWeight;
+ /** @type {number} */
+ var arrayLen = useArray ? rnd.getInt(1, maxArrayLen) : 1;
+ /** @type {string} */
+ var name = 'v_var' + varNdx;
+
+ if (useArray)
+ this.m_progSpec.addVarying(name, gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), arrayLen), interp);
+ else
+ this.m_progSpec.addVarying(name, gluVarType.newTypeBasic(type, precision), interp);
+
+ numAttributeVectors += arrayLen * numVecs;
+ varNdx += 1;
+ }
+
+ // Generate transform feedback candidate set.
+ /** @type {Array<string>} */ var tfCandidates = [];
+
+ if (usePosition) tfCandidates.push('gl_Position');
+ if (usePointSize) tfCandidates.push('gl_PointSize');
+
+ for (var ndx = 0; ndx < varNdx; ndx++) {
+ /** @type {es3fTransformFeedbackTests.Varying} */
+ var varying = this.m_progSpec.getVaryings()[ndx];
+
+ if (varying.type.isArrayType()) {
+ /** @type {boolean} */
+ var captureFull = rnd.getFloat() < captureFullArrayWeight;
+
+ if (captureFull) {
+ tfCandidates.push(varying.name);
+ } else {
+ /** @type {number} */
+ var numElem = varying.type.getArraySize();
+ for (var elemNdx = 0; elemNdx < numElem; elemNdx++)
+ tfCandidates.push(varying.name + '[' + elemNdx + ']');
+ }
+ } else
+ tfCandidates.push(varying.name);
+ }
+
+ // Pick random selection.
+ var tfVaryings = [];
+ rnd.choose(tfCandidates, tfVaryings, Math.min(tfCandidates.length, maxTransformFeedbackVars));
+ rnd.shuffle(tfVaryings);
+ for (var i = 0; i < tfVaryings.length; i++)
+ this.m_progSpec.addTransformFeedbackVarying(tfVaryings[i]);
+
+ es3fTransformFeedbackTests.TransformFeedbackCase.prototype.init.call(this);
+
+ };
+
+ /**
+ * Creates the test in order to be executed
+ **/
+ es3fTransformFeedbackTests.init = function() {
+
+ /** @const @type {tcuTestCase.DeqpTest} */
+ var testGroup = tcuTestCase.runner.testCases;
+
+ var bufferModes = [{name: 'separate', mode: gl.SEPARATE_ATTRIBS}, {name: 'interleaved', mode: gl.INTERLEAVED_ATTRIBS}
+ ];
+
+ var primitiveTypes = [{name: 'points', type: gluDrawUtil.primitiveType.POINTS}, {name: 'lines', type: gluDrawUtil.primitiveType.LINES}, {name: 'triangles', type: gluDrawUtil.primitiveType.TRIANGLES}
+ ];
+
+ /** @type {Array<gluShaderUtil.DataType>} */
+ var basicTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3,
+ gluShaderUtil.DataType.FLOAT_MAT4,
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4
+ ];
+
+ /** @type {Array<gluShaderUtil.precision>} */
+ var precisions = [
+
+ gluShaderUtil.precision.PRECISION_LOWP,
+ gluShaderUtil.precision.PRECISION_MEDIUMP,
+ gluShaderUtil.precision.PRECISION_HIGHP
+
+ // glsUBC.UniformFlags.PRECISION_LOW,
+ // glsUBC.UniformFlags.PRECISION_MEDIUM,
+ // glsUBC.UniformFlags.PRECISION_HIGH
+ ];
+
+ var interpModes = [{name: 'smooth', interp: es3fTransformFeedbackTests.interpolation.SMOOTH}, {name: 'flat', interp: es3fTransformFeedbackTests.interpolation.FLAT}, {name: 'centroid', interp: es3fTransformFeedbackTests.interpolation.CENTROID}
+ ];
+
+ // .position
+ /** @type {tcuTestCase.DeqpTest} */
+ var positionGroup = tcuTestCase.newTest('position', 'gl_Position capture using transform feedback');
+ testGroup.addChild(positionGroup);
+
+ for (var primitiveType = 0; primitiveType < primitiveTypes.length; primitiveType++) {
+ for (var bufferMode = 0; bufferMode < bufferModes.length; bufferMode++) {
+ /** @type {string} */
+ var name = primitiveTypes[primitiveType].name + '_' + bufferModes[bufferMode].name;
+
+ positionGroup.addChild(new es3fTransformFeedbackTests.PositionCase(
+ name,
+ '',
+ bufferModes[bufferMode].mode,
+ primitiveTypes[primitiveType].type
+ ));
+ }
+ }
+
+ // .point_size
+ /** @type {tcuTestCase.DeqpTest} */ var pointSizeGroup = tcuTestCase.newTest('point_size', 'gl_PointSize capture using transform feedback');
+ testGroup.addChild(pointSizeGroup);
+
+ for (var primitiveType = 0; primitiveType < primitiveTypes.length; primitiveType++) {
+ for (var bufferMode = 0; bufferMode < bufferModes.length; bufferMode++) {
+ var name = primitiveTypes[primitiveType].name + '_' + bufferModes[bufferMode].name;
+
+ pointSizeGroup.addChild(new es3fTransformFeedbackTests.PointSizeCase(
+ name,
+ '',
+ bufferModes[bufferMode].mode,
+ primitiveTypes[primitiveType].type
+ ));
+ }
+ }
+
+ // .basic_type
+ for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) {
+ /** @type {number} */
+ var bufferMode = bufferModes[bufferModeNdx].mode;
+ for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) {
+ /** @type {tcuTestCase.DeqpTest} */
+ var primitiveGroup = tcuTestCase.newTest(
+ 'basic_types.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name,
+ 'Basic types in transform feedback');
+ /** @type {number} */
+ var primitiveType = primitiveTypes[primitiveTypeNdx].type;
+ testGroup.addChild(primitiveGroup);
+
+ for (var typeNdx = 0; typeNdx < basicTypes.length; typeNdx++) {
+ /** @type {gluShaderUtil.DataType} */
+ var type = basicTypes[typeNdx];
+ /** @type {boolean} */
+ var isFloat = gluShaderUtil.getDataTypeScalarType(type) == gluShaderUtil.DataType.FLOAT;
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ /** @type {gluShaderUtil.precision} */
+ var precision = precisions[precNdx];
+ var name = gluShaderUtil.getPrecisionName(precision) + '_' + gluShaderUtil.getDataTypeName(type);
+
+ primitiveGroup.addChild(new es3fTransformFeedbackTests.BasicTypeCase(
+ name,
+ '',
+ bufferMode,
+ primitiveType,
+ type,
+ precision,
+ isFloat ? es3fTransformFeedbackTests.interpolation.SMOOTH : es3fTransformFeedbackTests.interpolation.FLAT
+ ));
+ }
+ }
+ }
+ }
+
+ // .array
+ for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) {
+ var bufferMode = bufferModes[bufferModeNdx].mode;
+ for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) {
+ var primitiveGroup = tcuTestCase.newTest(
+ 'array.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name,
+ 'Capturing whole array in TF');
+ /** @type {number} */
+ var primitiveType = primitiveTypes[primitiveTypeNdx].type;
+ testGroup.addChild(primitiveGroup);
+
+ for (var typeNdx = 0; typeNdx < basicTypes.length; typeNdx++) {
+ var type = basicTypes[typeNdx];
+ var isFloat = gluShaderUtil.getDataTypeScalarType(type) == gluShaderUtil.DataType.FLOAT;
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ var precision = precisions[precNdx];
+ var name = gluShaderUtil.getPrecisionName(precision) + '_' + gluShaderUtil.getDataTypeName(type);
+
+ primitiveGroup.addChild(new es3fTransformFeedbackTests.BasicArrayCase(
+ name,
+ '',
+ bufferMode,
+ primitiveType,
+ type,
+ precision,
+ isFloat ? es3fTransformFeedbackTests.interpolation.SMOOTH : es3fTransformFeedbackTests.interpolation.FLAT
+ ));
+ }
+ }
+ }
+ }
+
+ // .array_element
+ for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) {
+ var bufferMode = bufferModes[bufferModeNdx].mode;
+ for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) {
+ var primitiveGroup = tcuTestCase.newTest(
+ 'array_element.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name,
+ 'Capturing single array element in TF');
+ var primitiveType = primitiveTypes[primitiveTypeNdx].type;
+ testGroup.addChild(primitiveGroup);
+
+ for (var typeNdx = 0; typeNdx < basicTypes.length; typeNdx++) {
+ var type = basicTypes[typeNdx];
+ var isFloat = gluShaderUtil.getDataTypeScalarType(type) == gluShaderUtil.DataType.FLOAT;
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ var precision = precisions[precNdx];
+ var name = gluShaderUtil.getPrecisionName(precision) + '_' + gluShaderUtil.getDataTypeName(type);
+
+ primitiveGroup.addChild(new es3fTransformFeedbackTests.ArrayElementCase(
+ name,
+ '',
+ bufferMode,
+ primitiveType,
+ type,
+ precision,
+ isFloat ? es3fTransformFeedbackTests.interpolation.SMOOTH : es3fTransformFeedbackTests.interpolation.FLAT
+ ));
+ }
+ }
+ }
+ }
+
+ // .interpolation
+ for (var modeNdx = 0; modeNdx < interpModes.length; modeNdx++) {
+ var interp = interpModes[modeNdx].interp;
+ var modeGroup = tcuTestCase.newTest(
+ 'interpolation.' + interpModes[modeNdx].name,
+ 'Different interpolation modes in transform feedback varyings');
+ testGroup.addChild(modeGroup);
+
+ for (var precNdx = 0; precNdx < precisions.length; precNdx++) {
+ var precision = precisions[precNdx];
+
+ for (var primitiveType = 0; primitiveType < primitiveTypes.length; primitiveType++) {
+ for (var bufferMode = 0; bufferMode < bufferModes.length; bufferMode++) {
+ var name = (
+ gluShaderUtil.getPrecisionName(precision) +
+ '_vec4_' + primitiveTypes[primitiveType].name +
+ '_' + bufferModes[bufferMode].name
+ );
+
+ modeGroup.addChild(new es3fTransformFeedbackTests.BasicTypeCase(
+ name,
+ '',
+ bufferModes[bufferMode].mode,
+ primitiveTypes[primitiveType].type,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ precision,
+ interp
+ ));
+ }
+ }
+ }
+ }
+
+ // .random
+ for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) {
+ /** @type {number} */
+ var bufferMode = bufferModes[bufferModeNdx].mode;
+ for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) {
+ var primitiveGroup = tcuTestCase.newTest(
+ 'random.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name,
+ 'Randomized transform feedback cases');
+ /** @type {number} */
+ var primitiveType = primitiveTypes[primitiveTypeNdx].type;
+ testGroup.addChild(primitiveGroup);
+
+ for (var ndx = 0; ndx < 10; ndx++) {
+ /** @type {number} */
+ var seed = deMath.deMathHash(bufferMode) ^ deMath.deMathHash(primitiveType) ^ deMath.deMathHash(ndx);
+
+ primitiveGroup.addChild(new es3fTransformFeedbackTests.RandomCase(
+ (ndx + 1).toString(),
+ '',
+ bufferMode,
+ primitiveType,
+ seed
+ ));
+ }
+ }
+ }
+
+ };
+
+ /**
+ * Create and execute the test cases
+ */
+ es3fTransformFeedbackTests.run = function(context, range) {
+ gl = context;
+ var testName = 'transform_feedback';
+ var testDescription = 'Transform Feedback Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+ try {
+ es3fTransformFeedbackTests.init();
+ if (range)
+ state.setRange(range);
+ tcuTestCase.runTestCases();
+ } catch (err) {
+ bufferedLogToConsole(err);
+ tcuTestCase.runner.terminate();
+ }
+
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformApiTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformApiTests.js
new file mode 100644
index 0000000000..59e50f1fc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformApiTests.js
@@ -0,0 +1,3203 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fUniformApiTests');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluVarType');
+
+goog.scope(function() {
+
+ var es3fUniformApiTests = functional.gles3.es3fUniformApiTests;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluVarType = framework.opengl.gluVarType;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+
+ /** @type {WebGL2RenderingContext} */ var gl;
+
+ /** @typedef {function(gluShaderUtil.DataType): boolean} */
+ es3fUniformApiTests.dataTypePredicate;
+
+ /** @type {number} */ es3fUniformApiTests.MAX_RENDER_WIDTH = 32;
+ /** @type {number} */ es3fUniformApiTests.MAX_RENDER_HEIGHT = 32;
+ /** @type {number} */ es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS = 16;
+
+ /** @type {Array<gluShaderUtil.DataType>} */ es3fUniformApiTests.s_testDataTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3,
+ gluShaderUtil.DataType.FLOAT_MAT4,
+
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4,
+
+ gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL_VEC2,
+ gluShaderUtil.DataType.BOOL_VEC3,
+ gluShaderUtil.DataType.BOOL_VEC4,
+
+ gluShaderUtil.DataType.SAMPLER_2D,
+ gluShaderUtil.DataType.SAMPLER_CUBE
+ // \note We don't test all sampler types here.
+ ];
+
+ /**
+ * Returns a substring from the beginning to the last occurence of the
+ * specified character
+ * @param {string} str The string in which to search
+ * @param {string} c A single character
+ * @return {string}
+ */
+ es3fUniformApiTests.beforeLast = function(str, c) {
+ return str.substring(0, str.lastIndexOf(c));
+ };
+
+ /**
+ * es3fUniformApiTests.fillWithColor
+ * @param {tcuTexture.PixelBufferAccess} access ,
+ * @param {Array<number>} color Array of four color components.
+ */
+ es3fUniformApiTests.fillWithColor = function(access, color) {
+ for (var z = 0; z < access.getDepth(); z++)
+ for (var y = 0; y < access.getHeight(); y++)
+ for (var x = 0; x < access.getWidth(); x++)
+ access.setPixel(color, x, y, z);
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @return {number}
+ */
+ es3fUniformApiTests.getSamplerNumLookupDimensions = function(type) {
+ switch (type) {
+ case gluShaderUtil.DataType.SAMPLER_2D:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D:
+ return 2;
+
+ case gluShaderUtil.DataType.SAMPLER_3D:
+ case gluShaderUtil.DataType.INT_SAMPLER_3D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D:
+ case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.SAMPLER_CUBE:
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
+ return 3;
+
+ case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
+ return 4;
+
+ default:
+ throw new Error('es3fUniformApiTests.getSamplerNumLookupDimensions - Invalid type');
+ }
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @return {gluShaderUtil.DataType}
+ */
+ es3fUniformApiTests.getSamplerLookupReturnType = function(type) {
+ switch (type) {
+ case gluShaderUtil.DataType.SAMPLER_2D:
+ case gluShaderUtil.DataType.SAMPLER_CUBE:
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.SAMPLER_3D:
+ return gluShaderUtil.DataType.FLOAT_VEC4;
+
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D:
+ case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
+ case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.UINT_SAMPLER_3D:
+ return gluShaderUtil.DataType.UINT_VEC4;
+
+ case gluShaderUtil.DataType.INT_SAMPLER_2D:
+ case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
+ case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
+ case gluShaderUtil.DataType.INT_SAMPLER_3D:
+ return gluShaderUtil.DataType.INT_VEC4;
+
+ case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
+ case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
+ case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
+ return gluShaderUtil.DataType.FLOAT;
+
+ default:
+ throw new Error('es3fUniformApiTests.getSamplerLookupReturnType - Invalid type');
+ }
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} T DataType to compare the type. Used to be a template param
+ * @param {gluShaderUtil.DataType} t
+ * @return {boolean}
+ */
+ es3fUniformApiTests.dataTypeEquals = function(T, t) {
+ return t == T;
+ };
+
+ /**
+ * @param {number} N Row number. Used to be a template parameter
+ * @param {gluShaderUtil.DataType} t
+ * @return {boolean}
+ */
+ es3fUniformApiTests.dataTypeIsMatrixWithNRows = function(N, t) {
+ return gluShaderUtil.isDataTypeMatrix(t) && gluShaderUtil.getDataTypeMatrixNumRows(t) == N;
+ };
+
+ /**
+ * @param {gluVarType.VarType} type
+ * @param {es3fUniformApiTests.dataTypePredicate} predicate
+ * @return {boolean}
+ */
+ es3fUniformApiTests.typeContainsMatchingBasicType = function(type, predicate) {
+ if (type.isBasicType())
+ return predicate(type.getBasicType());
+ else if (type.isArrayType())
+ return es3fUniformApiTests.typeContainsMatchingBasicType(type.getElementType(), predicate);
+ else {
+ assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.typeContainsMatchingBasicType - not a struct type', false, true);
+ /** @type {gluVarType.StructType} */ var structType = type.getStruct();
+ for (var i = 0; i < structType.getSize(); i++)
+ if (es3fUniformApiTests.typeContainsMatchingBasicType(structType.getMember(i).getType(), predicate))
+ return true;
+ return false;
+ }
+ };
+
+ /**
+ * @param {Array<gluShaderUtil.DataType>} dst
+ * @param {gluVarType.VarType} type
+ */
+ es3fUniformApiTests.getDistinctSamplerTypes = function(dst, type) {
+ if (type.isBasicType()) {
+ /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType();
+ if (gluShaderUtil.isDataTypeSampler(basicType) && dst.indexOf(basicType) == -1)
+ dst.push(basicType);
+ } else if (type.isArrayType())
+ es3fUniformApiTests.getDistinctSamplerTypes(dst, type.getElementType());
+ else {
+ assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.getDistinctSamplerTypes - not a struct type', false, true);
+ /** @type {gluVarType.StructType} */ var structType = type.getStruct();
+ for (var i = 0; i < structType.getSize(); i++)
+ es3fUniformApiTests.getDistinctSamplerTypes(dst, structType.getMember(i).getType());
+ }
+ };
+
+ /**
+ * @param {gluVarType.VarType} type
+ * @return {number}
+ */
+ es3fUniformApiTests.getNumSamplersInType = function(type) {
+ if (type.isBasicType())
+ return gluShaderUtil.isDataTypeSampler(type.getBasicType()) ? 1 : 0;
+ else if (type.isArrayType())
+ return es3fUniformApiTests.getNumSamplersInType(type.getElementType()) * type.getArraySize();
+ else {
+ assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.getNumSamplersInType - not a struct type', false, true);
+ /** @type {gluVarType.StructType} */ var structType = type.getStruct();
+ /** @type {number} */ var sum = 0;
+ for (var i = 0; i < structType.getSize(); i++)
+ sum += es3fUniformApiTests.getNumSamplersInType(structType.getMember(i).getType());
+ return sum;
+ }
+ };
+
+ /** @typedef { {type: gluVarType.VarType, ndx: number}} */
+ es3fUniformApiTests.VarTypeWithIndex;
+
+ /**
+ * @param {number} maxDepth
+ * @param {number} curStructIdx Out parameter, instead returning it in the VarTypeWithIndex structure.
+ * @param {Array<gluVarType.StructType>} structTypesDst
+ * @param {deRandom.Random} rnd
+ * @return {es3fUniformApiTests.VarTypeWithIndex}
+ */
+ es3fUniformApiTests.generateRandomType = function(maxDepth, curStructIdx, structTypesDst, rnd) {
+ /** @type {boolean} */ var isStruct = maxDepth > 0 && rnd.getFloat() < 0.2;
+ /** @type {boolean} */ var isArray = rnd.getFloat() < 0.3;
+
+ if (isStruct) {
+ /** @type {number} */ var numMembers = rnd.getInt(1, 5);
+ /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + curStructIdx++);
+
+ for (var i = 0; i < numMembers; i++) {
+ /** @type {es3fUniformApiTests.VarTypeWithIndex} */ var typeWithIndex = es3fUniformApiTests.generateRandomType(maxDepth - 1, curStructIdx, structTypesDst, rnd);
+ curStructIdx = typeWithIndex.ndx;
+ structType.addMember('m' + i, typeWithIndex.type);
+ }
+
+ structTypesDst.push(structType);
+ return (isArray ? {
+ type: gluVarType.newTypeArray(gluVarType.newTypeStruct(structType), rnd.getInt(1, 5)),
+ ndx: curStructIdx
+ }
+ : {
+ type: gluVarType.newTypeStruct(structType),
+ ndx: curStructIdx
+ });
+ } else {
+ /** @type {gluShaderUtil.DataType} */ var basicType = es3fUniformApiTests.s_testDataTypes[rnd.getInt(0, es3fUniformApiTests.s_testDataTypes.length - 1)];
+ /** @type {gluShaderUtil.precision} */ var precision;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(basicType))
+ precision = gluShaderUtil.precision.PRECISION_MEDIUMP;
+ return (isArray ? {
+ type: gluVarType.newTypeArray(gluVarType.newTypeBasic(basicType, precision), rnd.getInt(1, 5)),
+ ndx: curStructIdx
+ }
+ : {
+ type: gluVarType.newTypeBasic(basicType, precision),
+ ndx: curStructIdx
+ });
+ }
+ };
+
+ /**
+ * es3fUniformApiTests.SamplerV structure
+ * @constructor
+ */
+ es3fUniformApiTests.SamplerV = function() {
+ this.samplerV = {
+ /** @type {number} */ unit: 0,
+ /** @type {Array<number>} */ fillColor: []
+ };
+ };
+
+ /**
+ * es3fUniformApiTests.VarValue class. may contain different types.
+ * @constructor
+ */
+ es3fUniformApiTests.VarValue = function() {
+ /** @type {gluShaderUtil.DataType} */ this.type;
+ /** @type {Array<number | boolean> | es3fUniformApiTests.SamplerV} */ this.val = [];
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fUniformApiTests.CaseShaderType = {
+ VERTEX: 0,
+ FRAGMENT: 1,
+ BOTH: 2
+ };
+
+ /**
+ * es3fUniformApiTests.Uniform struct.
+ * @param {string} name_
+ * @param {gluVarType.VarType} type_
+ * @constructor
+ */
+ es3fUniformApiTests.Uniform = function(name_, type_) {
+ /** @type {string} */ this.name = name_;
+ /** @type {gluVarType.VarType} */ this.type = type_;
+ };
+
+ // A set of uniforms, along with related struct types.
+ /**
+ * class es3fUniformApiTests.UniformCollection
+ * @constructor
+ */
+ es3fUniformApiTests.UniformCollection = function() {
+ /** @type {Array<es3fUniformApiTests.Uniform>} */ this.m_uniforms = [];
+ /** @type {Array<gluVarType.StructType>} */ this.m_structTypes = [];
+ };
+
+ /**
+ * @return {number}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.getNumUniforms = function() {return this.m_uniforms.length;};
+
+ /**
+ * @return {number}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.getNumStructTypes = function() {return this.m_structTypes.length;};
+
+ /**
+ * @param {number} ndx
+ * @return {es3fUniformApiTests.Uniform}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.getUniform = function(ndx) {return this.m_uniforms[ndx];};
+
+ /**
+ * @param {number} ndx
+ * @return {gluVarType.StructType}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.getStructType = function(ndx) {return this.m_structTypes[ndx];};
+
+ /**
+ * @param {es3fUniformApiTests.Uniform} uniform
+ */
+ es3fUniformApiTests.UniformCollection.prototype.addUniform = function(uniform) {this.m_uniforms.push(uniform);};
+
+ /**
+ * @param {gluVarType.StructType} type
+ */
+ es3fUniformApiTests.UniformCollection.prototype.addStructType = function(type) {this.m_structTypes.push(type);};
+
+ // Add the contents of m_uniforms and m_structTypes to receiver, and remove them from this one.
+ // \note receiver takes ownership of the struct types.
+ /**
+ * @param {es3fUniformApiTests.UniformCollection} receiver
+ */
+ es3fUniformApiTests.UniformCollection.prototype.moveContents = function(receiver) {
+ for (var i = 0; i < this.m_uniforms.length; i++)
+ receiver.addUniform(this.m_uniforms[i]);
+ this.m_uniforms.length = 0;
+
+ for (var i = 0; i < this.m_structTypes.length; i++)
+ receiver.addStructType(this.m_structTypes[i]);
+ this.m_structTypes.length = 0;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.dataTypePredicate} predicate
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.containsMatchingBasicType = function(predicate) {
+ for (var i = 0; i < this.m_uniforms.length; i++)
+ if (es3fUniformApiTests.typeContainsMatchingBasicType(this.m_uniforms[i].type, predicate))
+ return true;
+ return false;
+ };
+
+ /**
+ * @return {Array<gluShaderUtil.DataType>}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.getSamplerTypes = function() {
+ /** @type {Array<gluShaderUtil.DataType>} */ var samplerTypes = [];
+ for (var i = 0; i < this.m_uniforms.length; i++)
+ es3fUniformApiTests.getDistinctSamplerTypes(samplerTypes, this.m_uniforms[i].type);
+ return samplerTypes;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.containsSeveralSamplerTypes = function() {
+ return this.getSamplerTypes().length > 1;
+ };
+
+ /**
+ * @return {number}
+ */
+ es3fUniformApiTests.UniformCollection.prototype.getNumSamplers = function() {
+ var sum = 0;
+ for (var i = 0; i < this.m_uniforms.length; i++)
+ sum += es3fUniformApiTests.getNumSamplersInType(this.m_uniforms[i].type);
+ return sum;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.basic = function(type, nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+ /** @type {gluShaderUtil.precision} */ var prec;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type))
+ prec = gluShaderUtil.precision.PRECISION_MEDIUMP;
+ res.m_uniforms.push(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeBasic(type, prec)));
+ return res;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.basicArray = function(type, nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+ /** @type {gluShaderUtil.precision} */ var prec;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type))
+ prec = gluShaderUtil.precision.PRECISION_MEDIUMP;
+ res.m_uniforms.push(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeArray(gluVarType.newTypeBasic(type, prec), 3)));
+ return res;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type0
+ * @param {gluShaderUtil.DataType} type1
+ * @param {boolean} containsArrays
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.basicStruct = function(type0, type1, containsArrays, nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+ /** @type {gluShaderUtil.precision} */ var prec0;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type0))
+ prec0 = gluShaderUtil.precision.PRECISION_MEDIUMP;
+ /** @type {gluShaderUtil.precision} */ var prec1;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type1))
+ prec1 = gluShaderUtil.precision.PRECISION_MEDIUMP;
+
+ /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + nameSuffix);
+ structType.addMember('m0', gluVarType.newTypeBasic(type0, prec0));
+ structType.addMember('m1', gluVarType.newTypeBasic(type1, prec1));
+ if (containsArrays) {
+ structType.addMember('m2', gluVarType.newTypeArray(gluVarType.newTypeBasic(type0, prec0), 3));
+ structType.addMember('m3', gluVarType.newTypeArray(gluVarType.newTypeBasic(type1, prec1), 3));
+ }
+
+ res.addStructType(structType);
+ res.addUniform(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeStruct(structType)));
+
+ return res;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type0
+ * @param {gluShaderUtil.DataType} type1
+ * @param {boolean} containsArrays
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.structInArray = function(type0, type1, containsArrays, nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = es3fUniformApiTests.UniformCollection.basicStruct(type0, type1, containsArrays, nameSuffix);
+ res.getUniform(0).type = gluVarType.newTypeArray(res.getUniform(0).type, 3);
+ return res;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type0
+ * @param {gluShaderUtil.DataType} type1
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.nestedArraysStructs = function(type0, type1, nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+ /** @type {gluShaderUtil.precision} */ var prec0;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type0))
+ prec0 = gluShaderUtil.precision.PRECISION_MEDIUMP;
+ /** @type {gluShaderUtil.precision} */ var prec1;
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type1))
+ prec1 = gluShaderUtil.precision.PRECISION_MEDIUMP;
+ /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + nameSuffix);
+ /** @type {gluVarType.StructType} */ var subStructType = gluVarType.newStructType('subStructType' + nameSuffix);
+ /** @type {gluVarType.StructType} */ var subSubStructType = gluVarType.newStructType('subSubStructType' + nameSuffix);
+
+ subSubStructType.addMember('mss0', gluVarType.newTypeBasic(type0, prec0));
+ subSubStructType.addMember('mss1', gluVarType.newTypeBasic(type1, prec1));
+
+ subStructType.addMember('ms0', gluVarType.newTypeBasic(type1, prec1));
+ subStructType.addMember('ms1', gluVarType.newTypeArray(gluVarType.newTypeBasic(type0, prec0), 2));
+ subStructType.addMember('ms2', gluVarType.newTypeArray(gluVarType.newTypeStruct(subSubStructType), 2));
+
+ structType.addMember('m0', gluVarType.newTypeBasic(type0, prec0));
+ structType.addMember('m1', gluVarType.newTypeStruct(subStructType));
+ structType.addMember('m2', gluVarType.newTypeBasic(type1, prec1));
+
+ res.addStructType(subSubStructType);
+ res.addStructType(subStructType);
+ res.addStructType(structType);
+
+ res.addUniform(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeStruct(structType)));
+
+ return res;
+ };
+
+ /**
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.multipleBasic = function(nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {Array<gluShaderUtil.DataType>} */ var types = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT_VEC3, gluShaderUtil.DataType.UINT_VEC4, gluShaderUtil.DataType.FLOAT_MAT3, gluShaderUtil.DataType.BOOL_VEC2];
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+
+ for (var i = 0; i < types.length; i++) {
+ /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.basic(types[i], '_' + i + nameSuffix);
+ sub.moveContents(res);
+ }
+
+ return res;
+ };
+
+ /**
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.multipleBasicArray = function(nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {Array<gluShaderUtil.DataType>} */ var types = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT_VEC3, gluShaderUtil.DataType.BOOL_VEC2];
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+
+ for (var i = 0; i < types.length; i++) {
+ /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.basicArray(types[i], '_' + i + nameSuffix);
+ sub.moveContents(res);
+ }
+
+ return res;
+ };
+
+ /**
+ * @param {string=} nameSuffix
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs = function(nameSuffix) {
+ if (nameSuffix === undefined) nameSuffix = '';
+ /** @type {Array<gluShaderUtil.DataType>} */ var types0 = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT, gluShaderUtil.DataType.BOOL_VEC4];
+ /** @type {Array<gluShaderUtil.DataType>} */ var types1 = [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.INT_VEC4, gluShaderUtil.DataType.BOOL];
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+
+ assertMsgOptions(types0.length == types1.length, 'es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs - lengths are not the same', false, true);
+
+ for (var i = 0; i < types0.length; i++) {
+ /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.nestedArraysStructs(types0[i], types1[i], '_' + i + nameSuffix);
+ sub.moveContents(res);
+ }
+
+ return res;
+ };
+
+ /**
+ * @param {number} seed
+ * @return {es3fUniformApiTests.UniformCollection}
+ */
+ es3fUniformApiTests.UniformCollection.random = function(seed) {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
+ /** @type {number} */ var numUniforms = rnd.getInt(1, 5);
+ /** @type {number} */ var structIdx = 0;
+ /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
+
+ for (var i = 0; i < numUniforms; i++) {
+ /** @type {Array<gluVarType.StructType>} */ var structTypes = [];
+ /** @type {es3fUniformApiTests.Uniform} */ var uniform = new es3fUniformApiTests.Uniform('u_var' + i, new gluVarType.VarType());
+
+ // \note Discard uniforms that would cause number of samplers to exceed es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS.
+ do {
+ var temp = es3fUniformApiTests.generateRandomType(3, structIdx, structTypes, rnd);
+ structIdx = temp.ndx;
+ uniform.type = temp.type;
+ } while (res.getNumSamplers() + es3fUniformApiTests.getNumSamplersInType(uniform.type) > es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS);
+
+ res.addUniform(uniform);
+ for (var j = 0; j < structTypes.length; j++)
+ res.addStructType(structTypes[j]);
+ }
+
+ return res;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} sampler
+ * @return {es3fUniformApiTests.VarValue}
+ */
+ es3fUniformApiTests.getSamplerFillValue = function(sampler) {
+ assertMsgOptions(gluShaderUtil.isDataTypeSampler(sampler.type), 'es3fUniformApiTests.getSamplerFillValue - not a sampler type', false, true);
+
+ /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
+ result.type = es3fUniformApiTests.getSamplerLookupReturnType(sampler.type);
+
+ switch (result.type) {
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ for (var i = 0; i < 4; i++)
+ result.val[i] = sampler.val.samplerV.fillColor[i];
+ break;
+ case gluShaderUtil.DataType.UINT_VEC4:
+ for (var i = 0; i < 4; i++)
+ result.val[i] = sampler.val.samplerV.fillColor[i];
+ break;
+ case gluShaderUtil.DataType.INT_VEC4:
+ for (var i = 0; i < 4; i++)
+ result.val[i] = sampler.val.samplerV.fillColor[i];
+ break;
+ case gluShaderUtil.DataType.FLOAT:
+ result.val[0] = sampler.val.samplerV.fillColor[0];
+ break;
+ default:
+ throw new Error('es3fUniformApiTests.getSamplerFillValue - Invalid type');
+ }
+
+ return result;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} sampler
+ * @return {es3fUniformApiTests.VarValue}
+ */
+ es3fUniformApiTests.getSamplerUnitValue = function(sampler) {
+ assertMsgOptions(gluShaderUtil.isDataTypeSampler(sampler.type), 'es3fUniformApiTests.getSamplerUnitValue - not a sampler type', false, true);
+
+ /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
+ result.type = gluShaderUtil.DataType.INT;
+ result.val[0] = sampler.val.samplerV.unit;
+
+ return result;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} original
+ * @return {gluShaderUtil.DataType}
+ */
+ es3fUniformApiTests.getDataTypeTransposedMatrix = function(original) {
+ return gluShaderUtil.getDataTypeMatrix(gluShaderUtil.getDataTypeMatrixNumRows(original), gluShaderUtil.getDataTypeMatrixNumColumns(original));
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} original
+ * @return {es3fUniformApiTests.VarValue}
+ */
+ es3fUniformApiTests.getTransposeMatrix = function(original) {
+ assertMsgOptions(gluShaderUtil.isDataTypeMatrix(original.type), 'es3fUniformApiTests.getTransposeMatrix - not a matrix', false, true);
+
+ /** @type {number} */ var rows = gluShaderUtil.getDataTypeMatrixNumRows(original.type);
+ /** @type {number} */ var cols = gluShaderUtil.getDataTypeMatrixNumColumns(original.type);
+ /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
+ result.type = es3fUniformApiTests.getDataTypeTransposedMatrix(original.type);
+
+ for (var i = 0; i < rows; i++)
+ for (var j = 0; j < cols; j++)
+ result.val[i * cols + j] = original.val[j * rows + i];
+
+ return result;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} value
+ * @return {string}
+ */
+ es3fUniformApiTests.shaderVarValueStr = function(value) {
+ /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(value.type);
+ /** @type {string} */ var result = '';
+
+ if (numElems > 1)
+ result += gluShaderUtil.getDataTypeName(value.type) + '(';
+
+ for (var i = 0; i < numElems; i++) {
+ if (i > 0)
+ result += ', ';
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(value.type) || gluShaderUtil.isDataTypeMatrix(value.type))
+ result += value.val[i].toFixed(2);
+ else if (gluShaderUtil.isDataTypeIntOrIVec((value.type)))
+ result += value.val[i];
+ else if (gluShaderUtil.isDataTypeUintOrUVec((value.type)))
+ result += value.val[i] + 'u';
+ else if (gluShaderUtil.isDataTypeBoolOrBVec((value.type)))
+ result += value.val[i] ? 'true' : 'false';
+ else if (gluShaderUtil.isDataTypeSampler((value.type)))
+ result += es3fUniformApiTests.shaderVarValueStr(es3fUniformApiTests.getSamplerFillValue(value));
+ else
+ throw new Error('es3fUniformApiTests.shaderVarValueStr - invalid type');
+ }
+
+ if (numElems > 1)
+ result += ')';
+
+ return result;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} value
+ * @return {string}
+ */
+ es3fUniformApiTests.apiVarValueStr = function(value) {
+ /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(value.type);
+ /** @type {string} */ var result = '';
+
+ if (numElems > 1)
+ result += '(';
+
+ for (var i = 0; i < numElems; i++) {
+ if (i > 0)
+ result += ', ';
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(value.type) || gluShaderUtil.isDataTypeMatrix(value.type))
+ result += value.val[i].toFixed(2);
+ else if (gluShaderUtil.isDataTypeIntOrIVec(value.type) ||
+ gluShaderUtil.isDataTypeUintOrUVec(value.type))
+ result += value.val[i];
+ else if (gluShaderUtil.isDataTypeBoolOrBVec(value.type))
+ result += value.val[i] ? 'true' : 'false';
+ else if (gluShaderUtil.isDataTypeSampler(value.type))
+ result += value.val.samplerV.unit;
+ else
+ throw new Error('es3fUniformApiTests.apiVarValueStr - Invalid type');
+ }
+
+ if (numElems > 1)
+ result += ')';
+
+ return result;
+ };
+
+ // samplerUnit used if type is a sampler type. \note Samplers' unit numbers are not randomized.
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @param {deRandom.Random} rnd
+ * @param {number=} samplerUnit
+ * @return {es3fUniformApiTests.VarValue}
+ */
+ es3fUniformApiTests.generateRandomVarValue = function(type, rnd, samplerUnit) {
+ if (samplerUnit === undefined) samplerUnit = -1;
+ /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
+ result.type = type;
+
+ assertMsgOptions(
+ (samplerUnit >= 0) == (gluShaderUtil.isDataTypeSampler(type)),
+ 'es3fUniformApiTests.generateRandomVarValue - sampler units do not match type', false, true
+ );
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(type) || gluShaderUtil.isDataTypeMatrix(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = rnd.getFloat(-10.0, 10.0);
+ } else if (gluShaderUtil.isDataTypeIntOrIVec(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = rnd.getInt(-10, 10);
+ } else if (gluShaderUtil.isDataTypeUintOrUVec(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = rnd.getInt(0, 10);
+ } else if (gluShaderUtil.isDataTypeBoolOrBVec(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = rnd.getBool();
+ } else if (gluShaderUtil.isDataTypeSampler(type)) {
+ /** @type {gluShaderUtil.DataType} */ var texResultType = es3fUniformApiTests.getSamplerLookupReturnType(type);
+ /** @type {gluShaderUtil.DataType} */ var texResultScalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(texResultType);
+ /** @type {number} */ var texResultNumDims = gluShaderUtil.getDataTypeScalarSize(texResultType);
+
+ result.val = new es3fUniformApiTests.SamplerV();
+ result.val.samplerV.unit = samplerUnit;
+
+ for (var i = 0; i < texResultNumDims; i++) {
+ switch (texResultScalarType) {
+ case gluShaderUtil.DataType.FLOAT: result.val.samplerV.fillColor[i] = rnd.getFloat(0.0, 1.0); break;
+ case gluShaderUtil.DataType.INT: result.val.samplerV.fillColor[i] = rnd.getInt(-10, 10); break;
+ case gluShaderUtil.DataType.UINT: result.val.samplerV.fillColor[i] = rnd.getInt(0, 10); break;
+ default:
+ throw new Error('es3fUniformApiTests.generateRandomVarValue - Invalid scalar type');
+ }
+ }
+ } else
+ throw new Error('es3fUniformApiTests.generateRandomVarValue - Invalid type');
+
+ return result;
+ };
+
+ /**
+ * @param {gluShaderUtil.DataType} type
+ * @return {es3fUniformApiTests.VarValue}
+ */
+ es3fUniformApiTests.generateZeroVarValue = function(type) {
+ /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(type);
+ /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
+ result.type = type;
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(type) || gluShaderUtil.isDataTypeMatrix(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = 0.0;
+ } else if (gluShaderUtil.isDataTypeIntOrIVec(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = 0;
+ } else if (gluShaderUtil.isDataTypeUintOrUVec(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = 0;
+ } else if (gluShaderUtil.isDataTypeBoolOrBVec(type)) {
+ for (var i = 0; i < numElems; i++)
+ result.val[i] = false;
+ } else if (gluShaderUtil.isDataTypeSampler(type)) {
+ /** @type {gluShaderUtil.DataType} */ var texResultType = es3fUniformApiTests.getSamplerLookupReturnType(type);
+ /** @type {gluShaderUtil.DataType} */ var texResultScalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(texResultType);
+ /** @type {number} */ var texResultNumDims = gluShaderUtil.getDataTypeScalarSize(texResultType);
+
+ result.val = new es3fUniformApiTests.SamplerV();
+ result.val.samplerV.unit = 0;
+
+ for (var i = 0; i < texResultNumDims; i++) {
+ switch (texResultScalarType) {
+ case gluShaderUtil.DataType.FLOAT: result.val.samplerV.fillColor[i] = 0.12 * i; break;
+ case gluShaderUtil.DataType.INT: result.val.samplerV.fillColor[i] = -2 + i; break;
+ case gluShaderUtil.DataType.UINT: result.val.samplerV.fillColor[i] = 4 + i; break;
+ default:
+ throw new Error('es3fUniformApiTests.generateZeroVarValue - Invalid scalar type');
+ }
+ }
+ } else
+ throw new Error('es3fUniformApiTests.generateZeroVarValue - Invalid type');
+
+ return result;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} a
+ * @param {es3fUniformApiTests.VarValue} b
+ * @return {boolean}
+ */
+ es3fUniformApiTests.apiVarValueEquals = function(a, b) {
+ /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(a.type);
+ /** @type {number} */ var floatThreshold = 0.05;
+
+ assertMsgOptions(a.type == b.type, 'es3fUniformApiTests.apiVarValueEquals - types are different', false, true);
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(a.type) || gluShaderUtil.isDataTypeMatrix(a.type)) {
+ for (var i = 0; i < size; i++)
+ if (Math.abs(a.val[i] - b.val[i]) >= floatThreshold)
+ return false;
+ } else if (gluShaderUtil.isDataTypeIntOrIVec(a.type)) {
+ for (var i = 0; i < size; i++)
+ if (a.val[i] != b.val[i])
+ return false;
+ } else if (gluShaderUtil.isDataTypeUintOrUVec(a.type)) {
+ for (var i = 0; i < size; i++)
+ if (a.val[i] != b.val[i])
+ return false;
+ } else if (gluShaderUtil.isDataTypeBoolOrBVec(a.type)) {
+ for (var i = 0; i < size; i++)
+ if (a.val[i] != b.val[i])
+ return false;
+ } else if (gluShaderUtil.isDataTypeSampler(a.type)) {
+ if (a.val.samplerV.unit != b.val.samplerV.unit)
+ return false;
+ } else
+ throw new Error('es3fUniformApiTests.apiVarValueEquals - Invalid type');
+
+ return true;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} boolValue
+ * @param {gluShaderUtil.DataType} targetScalarType
+ * @param {deRandom.Random} rnd
+ * @return {es3fUniformApiTests.VarValue}
+ */
+ es3fUniformApiTests.getRandomBoolRepresentation = function(boolValue, targetScalarType, rnd) {
+ assertMsgOptions(
+ gluShaderUtil.isDataTypeBoolOrBVec(boolValue.type),
+ 'es3fUniformApiTests.getRandomBoolRepresentation - Data type not boolean or boolean vector',
+ false,
+ true
+ );
+
+ /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(boolValue.type);
+ /** @type {gluShaderUtil.DataType} */ var targetType = size == 1 ? targetScalarType : gluShaderUtil.getDataTypeVector(targetScalarType, size);
+ /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
+ result.type = targetType;
+
+ switch (targetScalarType) {
+ case gluShaderUtil.DataType.INT:
+ for (var i = 0; i < size; i++) {
+ if (boolValue.val[i]) {
+ result.val[i] = rnd.getInt(-10, 10);
+ if (result.val[i] == 0)
+ result.val[i] = 1;
+ } else
+ result.val[i] = 0;
+ }
+ break;
+
+ case gluShaderUtil.DataType.UINT:
+ for (var i = 0; i < size; i++) {
+ if (boolValue.val[i])
+ result.val[i] = rnd.getInt(1, 10);
+ else
+ result.val[i] = 0;
+ }
+ break;
+
+ case gluShaderUtil.DataType.FLOAT:
+ for (var i = 0; i < size; i++) {
+ if (boolValue.val[i]) {
+ result.val[i] = rnd.getFloat(-10.0, 10.0);
+ if (result.val[i] == 0.0)
+ result.val[i] = 1.0;
+ } else
+ result.val[i] = 0;
+ }
+ break;
+
+ default:
+ throw new Error('es3fUniformApiTests.getRandomBoolRepresentation - Invalid type');
+ }
+
+ return result;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.CaseShaderType} type
+ * @return {?string}
+ */
+ es3fUniformApiTests.getCaseShaderTypeName = function(type) {
+ switch (type) {
+ case es3fUniformApiTests.CaseShaderType.VERTEX: return 'vertex';
+ case es3fUniformApiTests.CaseShaderType.FRAGMENT: return 'fragment';
+ case es3fUniformApiTests.CaseShaderType.BOTH: return 'both';
+ default:
+ throw new Error('es3fUniformApiTests.getCaseShaderTypeName - Invalid shader type');
+ }
+ };
+
+ /**
+ * @param {number} seed
+ * @return {number}
+ */
+ es3fUniformApiTests.randomCaseShaderType = function(seed) {
+ return (new deRandom.Random(seed)).getInt(0, Object.keys(es3fUniformApiTests.CaseShaderType).length - 1);
+ };
+
+ //es3fUniformApiTests.UniformCase definitions
+
+ /**
+ * es3fUniformApiTests.Feature - Implemented as a function to create an object without unwanted properties.
+ * @constructor
+ */
+ es3fUniformApiTests.Feature = function() {
+ // ARRAYUSAGE_ONLY_MIDDLE_INDEX: only middle index of each array is used in shader. If not given, use all indices.
+ this.ARRAYUSAGE_ONLY_MIDDLE_INDEX = false;
+
+ // UNIFORMFUNC_VALUE: use pass-by-value versions of uniform assignment funcs, e.g. glUniform1f(), where possible. If not given, use pass-by-pointer versions.
+ this.UNIFORMFUNC_VALUE = false;
+
+ // MATRIXMODE_ROWMAJOR: pass matrices to GL in row major form. If not given, use column major.
+ this.MATRIXMODE_ROWMAJOR = false;
+
+ // ARRAYASSIGN: how basic-type arrays are assigned with glUniform*(). If none given, assign each element of an array separately.
+ this.ARRAYASSIGN_FULL = false; //!< Assign all elements of an array with one glUniform*().
+ this.ARRAYASSIGN_BLOCKS_OF_TWO = false; //!< Assign two elements per one glUniform*().
+
+ // UNIFORMUSAGE_EVERY_OTHER: use about half of the uniforms. If not given, use all uniforms (except that some array indices may be omitted according to ARRAYUSAGE).
+ this.UNIFORMUSAGE_EVERY_OTHER = false;
+
+ // BOOLEANAPITYPE: type used to pass booleans to and from GL api. If none given, use float.
+ this.BOOLEANAPITYPE_INT = false;
+ this.BOOLEANAPITYPE_UINT = false;
+
+ // UNIFORMVALUE_ZERO: use zero-valued uniforms. If not given, use random uniform values.
+ this.UNIFORMVALUE_ZERO = false;
+
+ // ARRAY_FIRST_ELEM_NAME_NO_INDEX: in certain API functions, when referring to the first element of an array, use just the array name without [0] at the end.
+ this.ARRAY_FIRST_ELEM_NAME_NO_INDEX = false;
+ };
+
+ // A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d).
+ /**
+ * @constructor
+ * @param {string} name_
+ * @param {gluShaderUtil.DataType} type_
+ * @param {boolean} isUsedInShader_
+ * @param {es3fUniformApiTests.VarValue} finalValue_
+ * @param {string=} rootName_
+ * @param {number=} elemNdx_
+ * @param {number=} rootSize_
+ */
+ es3fUniformApiTests.BasicUniform = function(name_, type_, isUsedInShader_, finalValue_, rootName_, elemNdx_, rootSize_) {
+ /** @type {string} */ this.name = name_;
+ /** @type {gluShaderUtil.DataType} */ this.type = type_;
+ /** @type {boolean} */ this.isUsedInShader = isUsedInShader_;
+ /** @type {es3fUniformApiTests.VarValue} */ this.finalValue = finalValue_; //!< The value we ultimately want to set for this uniform.
+
+ /** @type {string} */ this.rootName = rootName_ === undefined ? name_ : rootName_; //!< If this is a member of a basic-typed array, rootName is the name of that array with "[0]" appended. Otherwise it equals name.
+ /** @type {number} */ this.elemNdx = elemNdx_ === undefined ? -1 : elemNdx_; //!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1.
+ /** @type {number} */ this.rootSize = rootSize_ === undefined ? 1 : rootSize_; //!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1.
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} vec
+ * @param {string} name
+ * @return {es3fUniformApiTests.BasicUniform}
+ */
+ es3fUniformApiTests.BasicUniform.findWithName = function(vec, name) {
+ for (var i = 0; i < vec.length; i++) {
+ if (vec[i].name == name)
+ return vec[i];
+ }
+ return null;
+ };
+
+ // Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniforms().
+ /**
+ * @constructor
+ * @param {string} name_
+ * @param {gluShaderUtil.DataType} type_
+ * @param {boolean} used
+ */
+ es3fUniformApiTests.BasicUniformReportRef = function(name_, type_, used) {
+ /** @type {string} */ this.name = name_;
+ // \note minSize and maxSize are for arrays and can be distinct since implementations are allowed, but not required, to trim the inactive end indices of arrays.
+ /** @type {number} */ this.minSize = 1;
+ /** @type {number} */ this.maxSize = 1;
+ /** @type {gluShaderUtil.DataType} */ this.type = type_;
+ /** @type {boolean} */ this.isUsedInShader = used;
+ };
+
+ /**
+ * To be used after constructor
+ * @param {number} minS
+ * @param {number} maxS
+ * @return {es3fUniformApiTests.BasicUniformReportRef}
+ */
+ es3fUniformApiTests.BasicUniformReportRef.prototype.constructor_A = function(minS, maxS) {
+ this.minSize = minS;
+ this.maxSize = maxS;
+
+ assertMsgOptions(
+ this.minSize <= this.maxSize,
+ 'es3fUniformApiTests.BasicUniformReportRef.prototype.constructor_A - min size not smaller or equal than max size',
+ false,
+ true
+ );
+
+ return this;
+ };
+
+ // Info that is actually reported by glGetActiveUniform() or glGetActiveUniforms().
+ /**
+ * @constructor
+ * @param {string} name_
+ * @param {number} nameLength_
+ * @param {number} size_
+ * @param {gluShaderUtil.DataType} type_
+ * @param {number} index_
+ */
+ es3fUniformApiTests.BasicUniformReportGL = function(name_, nameLength_, size_, type_, index_) {
+ this.name = name_;
+ this.nameLength = nameLength_;
+ this.size = size_;
+ this.type = type_;
+ this.index = index_;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} vec
+ * @param {string} name
+ * @return {es3fUniformApiTests.BasicUniformReportGL}
+ */
+ es3fUniformApiTests.BasicUniformReportGL.findWithName = function(vec, name) {
+ for (var i = 0; i < vec.length; i++) {
+ if (vec[i].name == name)
+ return vec[i];
+ }
+ return null;
+ };
+
+ /**
+ * es3fUniformApiTests.UniformCase class, inherits from TestCase class
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fUniformApiTests.UniformCase = function(name, description) { // \note Randomizes caseType, uniformCollection and features.
+ tcuTestCase.DeqpTest.call(this, name, description);
+
+ /** @type {es3fUniformApiTests.Feature} */ this.m_features;
+ /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ this.m_uniformCollection;
+
+ /** @type {number} */ this.m_caseShaderType = 0;
+
+ /** @type {Array<gluTexture.Texture2D>} */ this.m_textures2d = [];
+ /** @type {Array<gluTexture.TextureCube>} */ this.m_texturesCube = [];
+ /** @type {Array<number>} */ this.m_filledTextureUnits = [];
+ };
+
+ es3fUniformApiTests.UniformCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ /** es3fUniformApiTests.UniformCase prototype restore */
+ es3fUniformApiTests.UniformCase.prototype.constructor = es3fUniformApiTests.UniformCase;
+
+ /**
+ * es3fUniformApiTests.UniformCase newC. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
+ * @param {number} seed
+ * @return {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformCase.prototype.newC = function(seed) {
+ this.m_features = this.randomFeatures(seed);
+ this.m_uniformCollection = es3fUniformApiTests.UniformCollection.random(seed);
+ this.m_caseShaderType = es3fUniformApiTests.randomCaseShaderType(seed);
+
+ return this;
+ };
+
+ /**
+ * es3fUniformApiTests.UniformCase new_B (static). Creates a es3fUniformApiTests.UniformCase
+ * @param {string} name
+ * @param {string} description
+ * @param {number} seed
+ * @return {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformCase.new_C = function(name, description, seed) {
+ var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newC(seed);
+
+ return uniformCase;
+ };
+
+ /**
+ * es3fUniformApiTests.UniformCase new_B. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
+ * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
+ * @param {es3fUniformApiTests.Feature} features
+ * @return {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformCase.prototype.newB = function(caseShaderType, uniformCollection, features) {
+ this.m_caseShaderType = caseShaderType;
+ this.m_uniformCollection = uniformCollection;
+ this.m_features = features;
+
+ return this;
+ };
+
+ /**
+ * es3fUniformApiTests.UniformCase new_B (static). Creates a es3fUniformApiTests.UniformCase
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
+ * @param {es3fUniformApiTests.Feature} features
+ * @return {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformCase.new_B = function(name, description, caseShaderType, uniformCollection, features) {
+ var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newB(caseShaderType, uniformCollection, features);
+
+ return uniformCase;
+ };
+
+ /**
+ * es3fUniformApiTests.UniformCase new_A. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
+ * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
+ * @return {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformCase.prototype.newA = function(caseShaderType, uniformCollection) {
+ this.m_caseShaderType = caseShaderType;
+ this.m_uniformCollection = uniformCollection;
+ this.m_features = null;
+
+ return this;
+ };
+
+ /**
+ * es3fUniformApiTests.UniformCase new_A (static). Creates a es3fUniformApiTests.UniformCase
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
+ * @return {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformCase.new_A = function(name, description, caseShaderType, uniformCollection) {
+ var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newA(caseShaderType, uniformCollection);
+
+ return uniformCase;
+ };
+
+ /**
+ * @param {number} seed
+ * @return {es3fUniformApiTests.Feature}
+ */
+ es3fUniformApiTests.UniformCase.prototype.randomFeatures = function(seed) {
+ /** @type {es3fUniformApiTests.Feature} */ var result = new es3fUniformApiTests.Feature();
+
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
+
+ result.ARRAYUSAGE_ONLY_MIDDLE_INDEX = rnd.getBool();
+ result.UNIFORMFUNC_VALUE = rnd.getBool();
+ result.MATRIXMODE_ROWMAJOR = rnd.getBool();
+ result.ARRAYASSIGN_FULL = rnd.getBool();
+ result.ARRAYASSIGN_BLOCKS_OF_TWO = !result.ARRAYASSIGN_FULL;
+ result.UNIFORMUSAGE_EVERY_OTHER = rnd.getBool();
+ result.BOOLEANAPITYPE_INT = rnd.getBool();
+ result.BOOLEANAPITYPE_UINT = !result.BOOLEANAPITYPE_INT;
+ result.UNIFORMVALUE_ZERO = rnd.getBool();
+
+ return result;
+ };
+
+ /**
+ * Initialize the es3fUniformApiTests.UniformCase
+ */
+ es3fUniformApiTests.UniformCase.prototype.init = function() {
+ /** @type {number} */ var numSamplerUniforms = this.m_uniformCollection.getNumSamplers();
+ /** @type {number} */ var vertexTexUnitsRequired = this.m_caseShaderType != es3fUniformApiTests.CaseShaderType.FRAGMENT ? numSamplerUniforms : 0;
+ /** @type {number} */ var fragmentTexUnitsRequired = this.m_caseShaderType != es3fUniformApiTests.CaseShaderType.VERTEX ? numSamplerUniforms : 0;
+ /** @type {number} */ var combinedTexUnitsRequired = vertexTexUnitsRequired + fragmentTexUnitsRequired;
+ var vertexTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS));
+ var fragmentTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
+ var combinedTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
+
+ assertMsgOptions(
+ numSamplerUniforms <= es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS,
+ 'es3fUniformApiTests.UniformCase.prototype.init - sampler uniforms exceed MAX_NUM_SAMPLER_UNIFORMS',
+ false,
+ true
+ );
+
+ if (vertexTexUnitsRequired > vertexTexUnitsSupported)
+ testFailedOptions('' + vertexTexUnitsRequired + ' vertex texture units required, ' + vertexTexUnitsSupported + ' supported', true);
+ if (fragmentTexUnitsRequired > fragmentTexUnitsSupported)
+ testFailedOptions('' + fragmentTexUnitsRequired + ' fragment texture units required, ' + fragmentTexUnitsSupported + ' supported', true);
+ if (combinedTexUnitsRequired > combinedTexUnitsSupported)
+ testFailedOptions('' + combinedTexUnitsRequired + ' combined texture units required, ' + combinedTexUnitsSupported + ' supported', true);
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniformsDst
+ * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsDst
+ * @param {gluVarType.VarType} varType
+ * @param {string} varName
+ * @param {boolean} isParentActive
+ * @param {number} samplerUnitCounter
+ * @param {deRandom.Random} rnd
+ * @return {number} Used to be output parameter. Sampler unit count
+ */
+ es3fUniformApiTests.UniformCase.prototype.generateBasicUniforms = function(basicUniformsDst, basicUniformReportsDst, varType, varName, isParentActive, samplerUnitCounter, rnd) {
+ /** @type {es3fUniformApiTests.VarValue} */ var value;
+
+ if (varType.isBasicType()) {
+ /** @type {boolean} */ var isActive = isParentActive && (this.m_features.UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.length % 2 == 0 : true);
+ /** @type {gluShaderUtil.DataType} */ var type = varType.getBasicType();
+ value = this.m_features.UNIFORMVALUE_ZERO ? es3fUniformApiTests.generateZeroVarValue(type) :
+ gluShaderUtil.isDataTypeSampler(type) ? es3fUniformApiTests.generateRandomVarValue(type, rnd, samplerUnitCounter++) :
+ es3fUniformApiTests.generateRandomVarValue(varType.getBasicType(), rnd);
+
+ basicUniformsDst.push(new es3fUniformApiTests.BasicUniform(varName, varType.getBasicType(), isActive, value));
+ basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportRef(varName, varType.getBasicType(), isActive));
+ } else if (varType.isArrayType()) {
+ /** @type {number} */ var size = varType.getArraySize();
+ /** @type {string} */ var arrayRootName = '' + varName + '[0]';
+ /** @type {Array<boolean>} */ var isElemActive = [];
+
+ for (var elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++) {
+ /** @type {string} */ var indexedName = '' + varName + '[' + elemNdx + ']';
+ /** @type {boolean} */ var isCurElemActive = isParentActive &&
+ (this.m_features.UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.length % 2 == 0 : true) &&
+ (this.m_features.ARRAYUSAGE_ONLY_MIDDLE_INDEX ? elemNdx == Math.floor(size / 2) : true);
+
+ isElemActive.push(isCurElemActive);
+
+ if (varType.getElementType().isBasicType()) {
+ // \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays.
+ /** @type {gluShaderUtil.DataType} */ var elemBasicType = varType.getElementType().getBasicType();
+ value = this.m_features.UNIFORMVALUE_ZERO ? es3fUniformApiTests.generateZeroVarValue(elemBasicType) :
+ gluShaderUtil.isDataTypeSampler(elemBasicType) ? es3fUniformApiTests.generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++) :
+ es3fUniformApiTests.generateRandomVarValue(elemBasicType, rnd);
+
+ basicUniformsDst.push(new es3fUniformApiTests.BasicUniform(indexedName, elemBasicType, isCurElemActive, value, arrayRootName, elemNdx, size));
+ } else
+ samplerUnitCounter = this.generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName, isCurElemActive, samplerUnitCounter, rnd);
+ }
+
+ if (varType.getElementType().isBasicType()) {
+ /** @type {number} */ var minSize;
+ for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize - 1]; minSize--) {}
+
+ basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportRef(arrayRootName, varType.getElementType().getBasicType(), isParentActive && minSize > 0).constructor_A(minSize, size));
+ }
+ } else {
+ assertMsgOptions(
+ varType.isStructType(),
+ 'es3fUniformApiTests.UniformCase.prototype.generateBasicUniforms - not a struct type',
+ false,
+ true
+ );
+
+ /** @type {gluVarType.StructType} */ var structType = varType.getStruct();
+
+ for (var i = 0; i < structType.getSize(); i++) {
+ /** @type {gluVarType.StructMember} */ var member = structType.getMember(i);
+ /** @type {string} */ var memberFullName = '' + varName + '.' + member.getName();
+
+ samplerUnitCounter = this.generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName, isParentActive, samplerUnitCounter, rnd);
+ }
+ }
+
+ return samplerUnitCounter;
+ };
+
+ /**
+ * @param {string} dst
+ * @return {string}
+ */
+ es3fUniformApiTests.UniformCase.prototype.writeUniformDefinitions = function(dst) {
+ for (var i = 0; i < this.m_uniformCollection.getNumStructTypes(); i++)
+ dst += gluVarType.declareStructType(this.m_uniformCollection.getStructType(i), 0) + ';\n';
+
+ for (var i = 0; i < this.m_uniformCollection.getNumUniforms(); i++)
+ dst += 'uniform ' + gluVarType.declareVariable(this.m_uniformCollection.getUniform(i).type, this.m_uniformCollection.getUniform(i).name, 0) + ';\n';
+
+ dst += '\n';
+
+ var compareFuncs = [{
+ requiringTypes: [gluShaderUtil.isDataTypeFloatOrVec, gluShaderUtil.isDataTypeMatrix],
+ definition: 'mediump float compare_float (mediump float a, mediump float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(2, t);}
+ ],
+ definition: 'mediump float compare_vec2 (mediump vec2 a, mediump vec2 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(3, t);}
+ ],
+ definition: 'mediump float compare_vec3 (mediump vec3 a, mediump vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(4, t);}],
+ definition: 'mediump float compare_vec4 (mediump vec4 a, mediump vec4 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat2 (mediump mat2 a, mediump mat2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2X3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat2x3 (mediump mat2x3 a, mediump mat2x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2X4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat2x4 (mediump mat2x4 a, mediump mat2x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3X2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat3x2 (mediump mat3x2 a, mediump mat3x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat3 (mediump mat3 a, mediump mat3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3X4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat3x4 (mediump mat3x4 a, mediump mat3x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4X2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat4x2 (mediump mat4x2 a, mediump mat4x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4X3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat4x3 (mediump mat4x3 a, mediump mat4x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_mat4 (mediump mat4 a, mediump mat4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_int (mediump int a, mediump int b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_ivec2 (mediump ivec2 a, mediump ivec2 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_ivec3 (mediump ivec3 a, mediump ivec3 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_ivec4 (mediump ivec4 a, mediump ivec4 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_uint (mediump uint a, mediump uint b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_uvec2 (mediump uvec2 a, mediump uvec2 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_uvec3 (mediump uvec3 a, mediump uvec3 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_uvec4 (mediump uvec4 a, mediump uvec4 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC2, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC3, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }'
+ },{
+ requiringTypes: [
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC4, t);},
+ function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
+ ],
+ definition: 'mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }'
+ }
+ ];
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var samplerTypes = this.m_uniformCollection.getSamplerTypes();
+
+ for (var compFuncNdx = 0; compFuncNdx < compareFuncs.length; compFuncNdx++) {
+ /** @type {Array<es3fUniformApiTests.dataTypePredicate>} */ var typeReq = compareFuncs[compFuncNdx].requiringTypes;
+ /** @type {boolean} */ var containsTypeSampler = false;
+
+ for (var i = 0; i < samplerTypes.length; i++) {
+ if (gluShaderUtil.isDataTypeSampler(samplerTypes[i])) {
+ /** @type {gluShaderUtil.DataType} */ var retType = es3fUniformApiTests.getSamplerLookupReturnType(samplerTypes[i]);
+ if (typeReq[0](retType) || typeReq[1](retType)) {
+ containsTypeSampler = true;
+ break;
+ }
+ }
+ }
+
+ if (containsTypeSampler || this.m_uniformCollection.containsMatchingBasicType(typeReq[0]) || this.m_uniformCollection.containsMatchingBasicType(typeReq[1]))
+ dst += compareFuncs[compFuncNdx].definition + '\n';
+ }
+
+ return dst;
+ };
+
+ /**
+ * @param {string} dst
+ * @param {es3fUniformApiTests.BasicUniform} uniform
+ * @return {string} Used to write the string in the output parameter
+ */
+ es3fUniformApiTests.UniformCase.prototype.writeUniformCompareExpr = function(dst, uniform) {
+ if (gluShaderUtil.isDataTypeSampler(uniform.type))
+ dst += 'compare_' + gluShaderUtil.getDataTypeName(es3fUniformApiTests.getSamplerLookupReturnType(uniform.type)) + '(texture(' + uniform.name + ', vec' + es3fUniformApiTests.getSamplerNumLookupDimensions(uniform.type) + '(0.0))'; //WebGL2.0
+ else
+ dst += 'compare_' + gluShaderUtil.getDataTypeName(uniform.type) + '(' + uniform.name;
+
+ dst += ', ' + es3fUniformApiTests.shaderVarValueStr(uniform.finalValue) + ')';
+
+ return dst;
+ };
+
+ /**
+ * @param {string} dst
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {string} variableName
+ * @return {string} Used to write the string in the output parameter
+ */
+ es3fUniformApiTests.UniformCase.prototype.writeUniformComparisons = function(dst, basicUniforms, variableName) {
+ for (var i = 0; i < basicUniforms.length; i++) {
+ /** @type {es3fUniformApiTests.BasicUniform} */ var unif = basicUniforms[i];
+
+ if (unif.isUsedInShader) {
+ dst += '\t' + variableName + ' *= ';
+ dst = this.writeUniformCompareExpr(dst, basicUniforms[i]);
+ dst += ';\n';
+ } else
+ dst += '\t// UNUSED: ' + basicUniforms[i].name + '\n';
+ }
+
+ return dst;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @return {string}
+ */
+ es3fUniformApiTests.UniformCase.prototype.generateVertexSource = function(basicUniforms) {
+ /** @type {boolean} */ var isVertexCase = this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.VERTEX || this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.BOTH;
+ /** @type {string} */ var result = '';
+
+ result += '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'out mediump float v_vtxOut;\n' +
+ '\n';
+
+ if (isVertexCase)
+ result = this.writeUniformDefinitions(result);
+
+ result += '\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_vtxOut = 1.0;\n';
+
+ if (isVertexCase)
+ result = this.writeUniformComparisons(result, basicUniforms, 'v_vtxOut');
+
+ result += '}\n';
+
+ return result;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @return {string}
+ */
+ es3fUniformApiTests.UniformCase.prototype.generateFragmentSource = function(basicUniforms) {
+ /**@type {boolean} */ var isFragmentCase = this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.FRAGMENT || this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.BOTH;
+ /**@type {string} */ var result = '';
+
+ result += '#version 300 es\n' +
+ 'in mediump float v_vtxOut;\n' +
+ '\n';
+
+ if (isFragmentCase)
+ result = this.writeUniformDefinitions(result);
+
+ result += '\n' +
+ 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ ' mediump float result = v_vtxOut;\n';
+
+ if (isFragmentCase)
+ result = this.writeUniformComparisons(result, basicUniforms, 'result');
+
+ result += ' dEQP_FragColor = vec4(result, result, result, 1.0);\n' +
+ '}\n';
+
+ return result;
+ };
+
+ /**
+ * @param {es3fUniformApiTests.VarValue} value
+ */
+ es3fUniformApiTests.UniformCase.prototype.setupTexture = function(value) {
+ // \note No handling for samplers other than 2D or cube.
+
+ assertMsgOptions(
+ es3fUniformApiTests.getSamplerLookupReturnType(value.type) == gluShaderUtil.DataType.FLOAT_VEC4,
+ 'es3fUniformApiTests.UniformCase.prototype.setupTexture - sampler return type should be vec4f', false, true
+ );
+
+ /** @type {number} */ var width = 32;
+ /** @type {number} */ var height = 32;
+ /** @type {Array<number>} */ var color = value.val.samplerV.fillColor;
+ /** @type {tcuTexture.TextureCube} */ var refTexture;
+ /** @type {gluTexture.TextureCube} */ var texture;
+
+ if (value.type == gluShaderUtil.DataType.SAMPLER_2D) {
+ texture = gluTexture.texture2DFromFormat(gl, gl.RGBA, gl.UNSIGNED_BYTE, width, height);
+ refTexture = texture.getRefTexture();
+ this.m_textures2d.push(texture);
+
+ refTexture.allocLevel(0);
+ es3fUniformApiTests.fillWithColor(refTexture.getLevel(0), color);
+
+ gl.activeTexture(gl.TEXTURE0 + value.val.samplerV.unit);
+ this.m_filledTextureUnits.push(value.val.samplerV.unit);
+ texture.upload();
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ } else if (value.type == gluShaderUtil.DataType.SAMPLER_CUBE) {
+ assertMsgOptions(width == height, 'es3fUniformApiTests.UniformCase.prototype.setupTexture - non square texture', false, true);
+
+ texture = gluTexture.cubeFromFormat(gl, gl.RGBA, gl.UNSIGNED_BYTE, width);
+ refTexture = texture.getRefTexture();
+ this.m_texturesCube.push(texture);
+
+ for (var face in tcuTexture.CubeFace) {
+ refTexture.allocLevel(tcuTexture.CubeFace[face], 0);
+ es3fUniformApiTests.fillWithColor(refTexture.getLevelFace(0, tcuTexture.CubeFace[face]), color);
+ }
+
+ gl.activeTexture(gl.TEXTURE0 + value.val.samplerV.unit);
+ this.m_filledTextureUnits.push(value.val.samplerV.unit);
+ texture.upload();
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ } else
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.setupTexture - Invalid sampler type');
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} basicUniformReportsDst
+ * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
+ * @param {WebGLProgram} programGL
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne = function(basicUniformReportsDst, basicUniformReportsRef, programGL) {
+ /** @type {WebGLProgram} */ var numActiveUniforms;
+ /** @type {boolean} */ var success = true;
+
+ numActiveUniforms = /** @type {WebGLProgram} */ (gl.getProgramParameter(programGL, gl.ACTIVE_UNIFORMS));
+ bufferedLogToConsole('// Number of active uniforms reported: ' + numActiveUniforms);
+
+ for (var unifNdx = 0; unifNdx < numActiveUniforms; unifNdx++) {
+ /** @type {number} (GLint)*/ var reportedSize = -1;
+ /** @type {number} (GLenum)*/ var reportedTypeGL = gl.NONE;
+ /** @type {gluShaderUtil.DataType} */ var reportedType;
+ /** @type {string} */ var reportedNameStr;
+ /** @type {WebGLActiveInfo} */ var activeInfo;
+
+ activeInfo = gl.getActiveUniform(programGL, unifNdx);
+
+ reportedNameStr = activeInfo.name;
+ reportedTypeGL = activeInfo.type;
+ reportedSize = activeInfo.size;
+
+ reportedType = gluShaderUtil.getDataTypeFromGLType(reportedTypeGL);
+
+ checkMessage(reportedType !== undefined, 'Invalid uniform type');
+
+ bufferedLogToConsole('// Got name = ' + reportedNameStr + ', size = ' + reportedSize + ', type = ' + gluShaderUtil.getDataTypeName(reportedType));
+
+ // Ignore built-in uniforms.
+ if (reportedNameStr.indexOf('gl_') == -1) {
+ /** @type {number} */ var referenceNdx;
+ for (referenceNdx = 0; referenceNdx < basicUniformReportsRef.length; referenceNdx++) {
+ if (basicUniformReportsRef[referenceNdx].name == reportedNameStr)
+ break;
+ }
+
+ if (referenceNdx >= basicUniformReportsRef.length) {
+ bufferedLogToConsole('// FAILURE: invalid non-built-in uniform name reported');
+ success = false;
+ } else {
+ /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var reference = basicUniformReportsRef[referenceNdx];
+
+ assertMsgOptions(
+ reference.type !== undefined,
+ 'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - type is undefined',
+ false,
+ true
+ );
+ assertMsgOptions(
+ reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader),
+ 'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - uniform min size does not match usage in shader',
+ false,
+ true
+ );
+ assertMsgOptions(
+ reference.minSize <= reference.maxSize,
+ 'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - uniform min size bigger than max size',
+ false,
+ true
+ );
+
+ if (es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, reportedNameStr) !== null) {
+ bufferedLogToConsole('// FAILURE: same uniform name reported twice');
+ success = false;
+ }
+
+ basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportGL(reportedNameStr, reportedNameStr.length, reportedSize, reportedType, unifNdx));
+
+ if (reportedType != reference.type) {
+ bufferedLogToConsole('// FAILURE: wrong type reported, should be ' + gluShaderUtil.getDataTypeName(reference.type));
+ success = false;
+ }
+ if (reportedSize < reference.minSize || reportedSize > reference.maxSize) {
+ bufferedLogToConsole('// FAILURE: wrong size reported, should be ' +
+ (reference.minSize == reference.maxSize ? reference.minSize : 'in the range [' + reference.minSize + ', ' + reference.maxSize + ']'));
+
+ success = false;
+ }
+ }
+ }
+ }
+
+ for (var i = 0; i < basicUniformReportsRef.length; i++) {
+ /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var expected = basicUniformReportsRef[i];
+ if (expected.isUsedInShader && es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, expected.name) === null) {
+ bufferedLogToConsole('// FAILURE: uniform with name ' + expected.name + ' was not reported by GL');
+ success = false;
+ }
+ }
+
+ return success;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} basicUniformReportsDst
+ * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
+ * @param {WebGLProgram} programGL
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.getActiveUniforms = function(basicUniformReportsDst, basicUniformReportsRef, programGL) {
+ /** @type {Array<string>} */ var queryNames = new Array(basicUniformReportsRef.length);
+ /** @type {Array<string>} */ var queryNamesC = new Array(basicUniformReportsRef.length);
+ /** @type {Array<number>} (GLuint) */ var uniformIndices = new Array(basicUniformReportsRef.length);
+ /** @type {Array<number>} */ var validUniformIndices = []; // This shall have the same contents, and in same order, as uniformIndices, but with gl.INVALID_INDEX entries removed.
+ /** @type {boolean} */ var success = true;
+
+ for (var i = 0; i < basicUniformReportsRef.length; i++) {
+ /** @type {string} */ var name = basicUniformReportsRef[i].name;
+ queryNames[i] = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && name[name.length - 1] == ']' ? es3fUniformApiTests.beforeLast(name, '[') : name;
+ queryNamesC[i] = queryNames[i];
+ }
+
+ uniformIndices = gl.getUniformIndices(programGL, queryNamesC);
+
+ for (var i = 0; i < uniformIndices.length; i++) {
+ if (uniformIndices[i] != gl.INVALID_INDEX)
+ validUniformIndices.push(uniformIndices[i]);
+ else {
+ if (basicUniformReportsRef[i].isUsedInShader) {
+ bufferedLogToConsole('// FAILURE: uniform with name ' + basicUniformReportsRef[i].name + ' received gl.INVALID_INDEX');
+ success = false;
+ }
+ }
+ }
+
+ if (validUniformIndices.length > 0) {
+ /** @type {Array<string>} */ var uniformNameBuf = new Array(validUniformIndices.length);
+ /** @type {Array<number>} (GLint) */ var uniformSizeBuf = new Array(validUniformIndices.length);
+ /** @type {Array<number>} (GLint) */ var uniformTypeBuf = new Array(validUniformIndices.length);
+
+ uniformSizeBuf = gl.getActiveUniforms(programGL, validUniformIndices, gl.UNIFORM_SIZE);
+ uniformTypeBuf = gl.getActiveUniforms(programGL, validUniformIndices, gl.UNIFORM_TYPE);
+
+ /** @type {number} */ var validNdx = -1; // Keeps the corresponding index to validUniformIndices while unifNdx is the index to uniformIndices.
+ for (var unifNdx = 0; unifNdx < uniformIndices.length; unifNdx++) {
+ if (uniformIndices[unifNdx] == gl.INVALID_INDEX)
+ continue;
+
+ validNdx++;
+
+ /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var reference = basicUniformReportsRef[unifNdx];
+ /** @type {number} */ var reportedIndex = validUniformIndices[validNdx];
+ /** @type {number} */ var reportedNameLength = reference.name.length;
+ /** @type {number} */ var reportedSize = uniformSizeBuf[validNdx];
+ /** @type {gluShaderUtil.DataType} */ var reportedType = gluShaderUtil.getDataTypeFromGLType(uniformTypeBuf[validNdx]);
+ /** @type {string} */ var reportedNameStr = reference.name;
+
+ bufferedLogToConsole('// Got name size = ' + reportedSize +
+ ', type = ' + gluShaderUtil.getDataTypeName(reportedType) +
+ ' for the uniform at index ' + reportedIndex + ' (' + reference.name + ')');
+
+ assertMsgOptions(
+ reference.type !== undefined,
+ 'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - type is undefined',
+ false,
+ true
+ );
+ assertMsgOptions(
+ reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader),
+ 'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - uniform min size does not match usage in shader',
+ false,
+ true
+ );
+ assertMsgOptions(
+ reference.minSize <= reference.maxSize,
+ 'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - uniform min size bigger than max size',
+ false,
+ true
+ );
+
+ if (es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, reportedNameStr) !== null) {
+ bufferedLogToConsole('// FAILURE: same uniform name reported twice');
+ success = false;
+ }
+ basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportGL(reference.name, reportedNameLength, reportedSize, reportedType, reportedIndex));
+
+ if (reportedType != reference.type) {
+ bufferedLogToConsole('// FAILURE: wrong type reported, should be ' + gluShaderUtil.getDataTypeName(reference.type));
+ success = false;
+ }
+
+ if (reportedSize < reference.minSize || reportedSize > reference.maxSize) {
+ bufferedLogToConsole('// FAILURE: wrong size reported, should be ' +
+ (reference.minSize == reference.maxSize ? reference.minSize : 'in the range [' + reference.minSize + ', ' + reference.maxSize + ']'));
+
+ success = false;
+ }
+ }
+ }
+
+ return success;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} uniformResults
+ * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} uniformsResults
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.uniformVsUniformsComparison = function(uniformResults, uniformsResults) {
+ /** @type {boolean} */ var success = true;
+ /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformsResult;
+
+ for (var uniformResultNdx = 0; uniformResultNdx < uniformResults.length; uniformResultNdx++) {
+ /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformResult = uniformResults[uniformResultNdx];
+ /** @type {string} */ var uniformName = uniformResult.name;
+ uniformsResult = es3fUniformApiTests.BasicUniformReportGL.findWithName(uniformsResults, uniformName);
+
+ if (uniformsResult !== null) {
+ bufferedLogToConsole('// Checking uniform ' + uniformName);
+
+ if (uniformResult.index != uniformsResult.index) {
+ bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetUniformIndices() gave different indices for uniform ' + uniformName);
+ success = false;
+ }
+ if (uniformResult.nameLength != uniformsResult.nameLength) {
+ bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave incompatible name lengths for uniform ' + uniformName);
+ success = false;
+ }
+ if (uniformResult.size != uniformsResult.size) {
+ bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave different sizes for uniform ' + uniformName);
+ success = false;
+ }
+ if (uniformResult.type != uniformsResult.type) {
+ bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave different types for uniform ' + uniformName);
+ success = false;
+ }
+ } else {
+ bufferedLogToConsole('// FAILURE: uniform ' + uniformName + ' was reported active by glGetActiveUniform() but not by glGetUniformIndices()');
+ success = false;
+ }
+ }
+
+ for (var uniformsResultNdx = 0; uniformsResultNdx < uniformsResults.length; uniformsResultNdx++) {
+ uniformsResult = uniformsResults[uniformsResultNdx];
+ /** @type {string} */ var uniformsName = uniformsResult.name;
+ /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformsResultIt = es3fUniformApiTests.BasicUniformReportGL.findWithName(uniformsResults, uniformsName);
+
+ if (uniformsResultIt === null) {
+ bufferedLogToConsole('// FAILURE: uniform ' + uniformsName + ' was reported active by glGetUniformIndices() but not by glGetActiveUniform()');
+ success = false;
+ }
+ }
+
+ return success;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.VarValue>} valuesDst
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {WebGLProgram} programGL
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.getUniforms = function(valuesDst, basicUniforms, programGL) {
+ /** @type {boolean} */ var success = true;
+
+ for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
+ /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
+ /** @type {string} */ var queryName = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? es3fUniformApiTests.beforeLast(uniform.name, '[') : uniform.name;
+ /** @type {WebGLUniformLocation} */ var location = gl.getUniformLocation(programGL, queryName);
+ /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(uniform.type);
+ /** @type {es3fUniformApiTests.VarValue} */ var value = new es3fUniformApiTests.VarValue();
+
+ if (!location) {
+ value.type = gluShaderUtil.DataType.INVALID;
+ valuesDst.push(value);
+ if (uniform.isUsedInShader) {
+ bufferedLogToConsole('// FAILURE: ' + uniform.name + ' was used in shader, but has location -1');
+ success = false;
+ }
+ continue;
+ }
+
+ value.type = uniform.type;
+
+ var result = /** @type {number} */ (gl.getUniform(programGL, location));
+
+ if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
+ value.val = new es3fUniformApiTests.SamplerV();
+ value.val.samplerV.unit = result;
+ } else
+ value.val = /** @type {Array<number>} */ (result.length === undefined ? [result] : result);
+
+ valuesDst.push(value);
+
+ bufferedLogToConsole('// Got ' + uniform.name + ' value ' + es3fUniformApiTests.apiVarValueStr(value));
+ }
+
+ return success;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.VarValue>} values
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues = function(values, basicUniforms) {
+ /** @type {boolean} */ var success = true;
+
+ assertMsgOptions(
+ values.length == basicUniforms.length,
+ 'es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues - lengths do not match',
+ false,
+ true
+ );
+
+ for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
+ /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
+ /** @type {es3fUniformApiTests.VarValue} */ var unifValue = values[unifNdx];
+ /** @type {number} */ var valSize = gluShaderUtil.getDataTypeScalarSize(uniform.type);
+
+ bufferedLogToConsole('// Checking uniform ' + uniform.name);
+
+ if (unifValue.type == gluShaderUtil.DataType.INVALID) // This happens when glGetUniformLocation() returned -1.
+ continue;
+
+ var CHECK_UNIFORM = function(ZERO) {
+ do {
+ for (var i = 0; i < valSize; i++) {
+ if (unifValue.val[i] != ZERO) {
+ bufferedLogToConsole('// FAILURE: uniform ' + uniform.name + ' has non-zero initial value');
+ success = false;
+ }
+ }
+ } while (false);
+ };
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(uniform.type) || gluShaderUtil.isDataTypeMatrix(uniform.type))
+ CHECK_UNIFORM(0.0);
+ else if (gluShaderUtil.isDataTypeIntOrIVec(uniform.type))
+ CHECK_UNIFORM(0);
+ else if (gluShaderUtil.isDataTypeUintOrUVec(uniform.type))
+ CHECK_UNIFORM(0);
+ else if (gluShaderUtil.isDataTypeBoolOrBVec(uniform.type))
+ CHECK_UNIFORM(false);
+ else if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
+ if (unifValue.val.samplerV.unit != 0) {
+ bufferedLogToConsole('// FAILURE: uniform ' + uniform.name + ' has non-zero initial value');
+ success = false;
+ }
+ } else
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues - invalid uniform type');
+ }
+
+ return success;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {WebGLProgram} programGL
+ * @param {deRandom.Random} rnd
+ */
+ es3fUniformApiTests.UniformCase.prototype.assignUniforms = function(basicUniforms, programGL, rnd) {
+ /** @type {boolean} */ var transpose = false; //No support to transpose uniform matrices in WebGL, must always be false. (this.m_features.MATRIXMODE_ROWMAJOR) != 0;
+ /** @type {boolean} (GLboolean) */ var transposeGL = transpose;
+ /** @type {gluShaderUtil.DataType} */ var boolApiType = this.m_features.BOOLEANAPITYPE_INT ? gluShaderUtil.DataType.INT :
+ this.m_features.BOOLEANAPITYPE_UINT ? gluShaderUtil.DataType.UINT :
+ gluShaderUtil.DataType.FLOAT;
+
+ for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
+ /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
+ /** @type {boolean} */ var isArrayMember = uniform.elemNdx >= 0;
+ /** @type {string} */ var queryName = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? es3fUniformApiTests.beforeLast(uniform.name, '[') : uniform.name;
+ /** @type {number} */ var numValuesToAssign = !isArrayMember ? 1 :
+ this.m_features.ARRAYASSIGN_FULL ? (uniform.elemNdx == 0 ? uniform.rootSize : 0) :
+ this.m_features.ARRAYASSIGN_BLOCKS_OF_TWO ? (uniform.elemNdx % 2 == 0 ? 2 : 0) :
+ /* Default: assign array elements separately */ 1;
+
+ assertMsgOptions(
+ numValuesToAssign >= 0,
+ 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - number of values to assign not a positive integer',
+ false,
+ true
+ );
+ assertMsgOptions(
+ numValuesToAssign == 1 || isArrayMember,
+ 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - not an array member and number of values to assign not 1',
+ false,
+ true
+ );
+
+ if (numValuesToAssign == 0) {
+ bufferedLogToConsole('// es3fUniformApiTests.Uniform ' + uniform.name + ' is covered by another glUniform*v() call to the same array');
+ continue;
+ }
+
+ /** @type {WebGLUniformLocation} */ var location = gl.getUniformLocation(programGL, queryName);
+ /** @type {number} */ var typeSize = gluShaderUtil.getDataTypeScalarSize(uniform.type);
+ /** @type {boolean} */ var assignByValue = this.m_features.UNIFORMFUNC_VALUE && !gluShaderUtil.isDataTypeMatrix(uniform.type) && numValuesToAssign == 1;
+ /** @type {Array<es3fUniformApiTests.VarValue>} */ var valuesToAssign = [];
+ /** @type {Array<number>} */ var buffer;
+
+ for (var i = 0; i < numValuesToAssign; i++) {
+ /** @type {string} */ var curName = isArrayMember ? es3fUniformApiTests.beforeLast(uniform.rootName, '[') + '[' + (uniform.elemNdx + i) + ']' : uniform.name;
+ /** @type {es3fUniformApiTests.VarValue} */ var unifValue = new es3fUniformApiTests.VarValue();
+
+ if (isArrayMember) {
+ /** @type {es3fUniformApiTests.BasicUniform} */ var elemUnif = es3fUniformApiTests.BasicUniform.findWithName(basicUniforms, curName);
+ if (elemUnif === null)
+ continue;
+ unifValue = elemUnif.finalValue;
+ } else
+ unifValue = uniform.finalValue;
+
+ /** @type {es3fUniformApiTests.VarValue} */ var apiValue = gluShaderUtil.isDataTypeBoolOrBVec(unifValue.type) ? es3fUniformApiTests.getRandomBoolRepresentation(unifValue, boolApiType, rnd) :
+ gluShaderUtil.isDataTypeSampler(unifValue.type) ? es3fUniformApiTests.getSamplerUnitValue(unifValue) :
+ unifValue;
+
+ valuesToAssign.push(gluShaderUtil.isDataTypeMatrix(apiValue.type) && transpose ? es3fUniformApiTests.getTransposeMatrix(apiValue) : apiValue);
+
+ if (gluShaderUtil.isDataTypeBoolOrBVec(uniform.type))
+ bufferedLogToConsole('// Using type ' + gluShaderUtil.getDataTypeName(boolApiType) + ' to set boolean value ' + es3fUniformApiTests.apiVarValueStr(unifValue) + ' for ' + curName);
+ else if (gluShaderUtil.isDataTypeSampler(uniform.type))
+ bufferedLogToConsole('// Texture for the sampler uniform ' + curName + ' will be filled with color ' + es3fUniformApiTests.apiVarValueStr(es3fUniformApiTests.getSamplerFillValue(uniform.finalValue)));
+ }
+
+ assertMsgOptions(
+ valuesToAssign.length > 0,
+ 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - values quantity less than one',
+ false,
+ true
+ );
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(valuesToAssign[0].type)) {
+ if (assignByValue) {
+ switch (typeSize) {
+ case 1: gl.uniform1f(location, valuesToAssign[0].val[0]); break;
+ case 2: gl.uniform2f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
+ case 3: gl.uniform3f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
+ case 4: gl.uniform4f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
+ }
+ } else {
+ buffer = new Array(valuesToAssign.length * typeSize);
+ for (var i = 0; i < buffer.length; i++)
+ buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
+
+ switch (typeSize) {
+ case 1: gl.uniform1fv(location, buffer); break;
+ case 2: gl.uniform2fv(location, buffer); break;
+ case 3: gl.uniform3fv(location, buffer); break;
+ case 4: gl.uniform4fv(location, buffer); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
+ }
+ }
+ } else if (gluShaderUtil.isDataTypeMatrix(valuesToAssign[0].type)) {
+ assertMsgOptions(
+ !assignByValue,
+ 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - assigning by value in matrix type',
+ false, true
+ );
+
+ buffer = new Array(valuesToAssign.length * typeSize);
+ for (var i = 0; i < buffer.length; i++)
+ buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
+
+ switch (uniform.type) {
+ case gluShaderUtil.DataType.FLOAT_MAT2: gl.uniformMatrix2fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3: gl.uniformMatrix3fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4: gl.uniformMatrix4fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: gl.uniformMatrix2x3fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: gl.uniformMatrix2x4fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: gl.uniformMatrix3x2fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: gl.uniformMatrix3x4fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: gl.uniformMatrix4x2fv(location, transposeGL, new Float32Array(buffer)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: gl.uniformMatrix4x3fv(location, transposeGL, new Float32Array(buffer)); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid uniform type');
+ }
+ } else if (gluShaderUtil.isDataTypeIntOrIVec(valuesToAssign[0].type)) {
+ if (assignByValue) {
+ switch (typeSize) {
+ case 1: gl.uniform1i(location, valuesToAssign[0].val[0]); break;
+ case 2: gl.uniform2i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
+ case 3: gl.uniform3i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
+ case 4: gl.uniform4i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
+ }
+ } else {
+ buffer = new Array(valuesToAssign.length * typeSize);
+ for (var i = 0; i < buffer.length; i++)
+ buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
+
+ switch (typeSize) {
+ case 1: gl.uniform1iv(location, buffer); break;
+ case 2: gl.uniform2iv(location, buffer); break;
+ case 3: gl.uniform3iv(location, buffer); break;
+ case 4: gl.uniform4iv(location, buffer); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
+ }
+ }
+ } else if (gluShaderUtil.isDataTypeUintOrUVec(valuesToAssign[0].type)) {
+ if (assignByValue) {
+ switch (typeSize) {
+ case 1: gl.uniform1ui(location, valuesToAssign[0].val[0]); break;
+ case 2: gl.uniform2ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
+ case 3: gl.uniform3ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
+ case 4: gl.uniform4ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
+ }
+ } else {
+ buffer = new Array(valuesToAssign.length * typeSize);
+ for (var i = 0; i < buffer.length; i++)
+ buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
+
+ switch (typeSize) {
+ case 1: gl.uniform1uiv(location, buffer); break;
+ case 2: gl.uniform2uiv(location, buffer); break;
+ case 3: gl.uniform3uiv(location, buffer); break;
+ case 4: gl.uniform4uiv(location, buffer); break;
+ default:
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
+ }
+ }
+ } else if (gluShaderUtil.isDataTypeSampler(valuesToAssign[0].type)) {
+ if (assignByValue)
+ gl.uniform1i(location, uniform.finalValue.val.samplerV.unit);
+ else {
+ var unit = /** @type {Array<number>} */ (uniform.finalValue.val);
+ gl.uniform1iv(location, unit);
+ }
+ } else
+ throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid uniform type');
+ }
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.VarValue>} values
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.compareUniformValues = function(values, basicUniforms) {
+ /** @type {boolean} */ var success = true;
+
+ for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
+ /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
+ /** @type {es3fUniformApiTests.VarValue} */ var unifValue = values[unifNdx];
+
+ bufferedLogToConsole('// Checking uniform ' + uniform.name);
+
+ if (unifValue.type == gluShaderUtil.DataType.INVALID) // This happens when glGetUniformLocation() returned -1.
+ continue;
+
+ if (!es3fUniformApiTests.apiVarValueEquals(unifValue, uniform.finalValue)) {
+ bufferedLogToConsole('// FAILURE: value obtained with glGetUniform*() for uniform ' + uniform.name + ' differs from value set with glUniform*()');
+ success = false;
+ }
+ }
+
+ return success;
+ };
+
+ /** @const @type {number} */ es3fUniformApiTests.VIEWPORT_WIDTH = 128;
+ /** @const @type {number} */ es3fUniformApiTests.VIEWPORT_HEIGHT = 128;
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {gluShaderProgram.ShaderProgram} program
+ * @param {deRandom.Random} rnd
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformCase.prototype.renderTest = function(basicUniforms, program, rnd) {
+ //const tcu::RenderTarget& renderTarget = m_context.getRenderTarget();
+ /** @const */ var viewportW = Math.min(gl.canvas.width, es3fUniformApiTests.VIEWPORT_WIDTH);
+ /** @const */ var viewportH = Math.min(gl.canvas.height, es3fUniformApiTests.VIEWPORT_HEIGHT);
+ /** @const */ var viewportX = rnd.getInt(0, gl.canvas.width - viewportW);
+ /** @const */ var viewportY = rnd.getInt(0, gl.canvas.height - viewportH);
+ /** @type {tcuSurface.Surface} */ var renderedImg = new tcuSurface.Surface(viewportW, viewportH);
+
+ // Assert that no two samplers of different types have the same texture unit - this is an error in GL.
+ for (var i = 0; i < basicUniforms.length; i++) {
+ if (gluShaderUtil.isDataTypeSampler(basicUniforms[i].type)) {
+ for (var j = 0; j < i; j++) {
+ if (gluShaderUtil.isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type)
+ assertMsgOptions(
+ basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit,
+ 'es3fUniformApiTests.UniformCase.prototype.renderTest - sampler units have the same texture unit',
+ false, true
+ );
+ }
+ }
+ }
+
+ for (var i = 0; i < basicUniforms.length; i++) {
+ if (gluShaderUtil.isDataTypeSampler(basicUniforms[i].type) && this.m_filledTextureUnits.indexOf(basicUniforms[i].finalValue.val) == -1) {
+ bufferedLogToConsole('// Filling texture at unit ' + es3fUniformApiTests.apiVarValueStr(basicUniforms[i].finalValue) + ' with color ' + es3fUniformApiTests.shaderVarValueStr(basicUniforms[i].finalValue));
+ this.setupTexture(basicUniforms[i].finalValue);
+ }
+ }
+
+ gl.viewport(viewportX, viewportY, viewportW, viewportH);
+
+ /** @type {Float32Array} */ var position = new Float32Array([
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0
+ ]);
+
+ /** @type {Uint16Array} */
+ var indices = new Uint16Array([0, 1, 2, 2, 1, 3]);
+
+ /** @type {number} */ var posLoc = gl.getAttribLocation(program.getProgram(), 'a_position');
+ gl.enableVertexAttribArray(posLoc);
+
+ var gl_position_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl_position_buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
+
+ var gl_index_buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_index_buffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
+
+ renderedImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
+
+ /** @type {number} */ var numFailedPixels = 0;
+ var whitePixel = new gluDrawUtil.Pixel([255.0, 255.0, 255.0, 255.0]);
+ for (var y = 0; y < renderedImg.getHeight(); y++) {
+ for (var x = 0; x < renderedImg.getWidth(); x++) {
+ var currentPixel = new gluDrawUtil.Pixel(renderedImg.getPixel(x, y));
+ if (!whitePixel.equals(currentPixel))
+ numFailedPixels += 1;
+ }
+ }
+
+ if (numFailedPixels > 0) {
+ //TODO: log << TestLog::Image("RenderedImage", "Rendered image", renderedImg);
+ bufferedLogToConsole('FAILURE: image comparison failed, got ' + numFailedPixels + ' non-white pixels');
+ return false;
+ } else {
+ bufferedLogToConsole('Success: got all-white pixels (all uniforms have correct values)');
+ return true;
+ }
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fUniformApiTests.UniformCase.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ deRandom.getBaseSeed());
+ /** @type {Array<es3fUniformApiTests.BasicUniform>} */ var basicUniforms = [];
+ /** @type {Array<es3fUniformApiTests.BasicUniformReportRef>} */ var basicUniformReportsRef = [];
+
+ /** @type {number} */ var samplerUnitCounter = 0;
+ for (var i = 0; i < this.m_uniformCollection.getNumUniforms(); i++)
+ samplerUnitCounter = this.generateBasicUniforms(basicUniforms, basicUniformReportsRef, this.m_uniformCollection.getUniform(i).type, this.m_uniformCollection.getUniform(i).name, true, samplerUnitCounter, rnd);
+
+ /** @type {string} */ var vertexSource = this.generateVertexSource(basicUniforms);
+ /** @type {string} */ var fragmentSource = this.generateFragmentSource(basicUniforms);
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexSource, fragmentSource));
+
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk()) {
+ testFailedOptions('Compile failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ gl.useProgram(program.getProgram());
+
+ /** @type {boolean} */ var success = this.test(basicUniforms, basicUniformReportsRef, program, rnd);
+ assertMsgOptions(success, '', true, false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fUniformApiTests.CaseType = {
+ UNIFORM: 0, //!< Check info returned by glGetActiveUniform().
+ INDICES_UNIFORMSIV: 1, //!< Check info returned by glGetUniformIndices() + glGetActiveUniforms(). TODO: Check 'IV' part
+ CONSISTENCY: 2 //!< Query info with both above methods, and check consistency.
+ };
+
+ /**
+ * es3fUniformApiTests.UniformInfoQueryCase class
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fUniformApiTests.CaseShaderType} shaderType
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection
+ * @param {es3fUniformApiTests.CaseType} caseType
+ * @param {es3fUniformApiTests.Feature} additionalFeatures
+ * @extends {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformInfoQueryCase = function(name, description, shaderType, uniformCollection, caseType, additionalFeatures) {
+ es3fUniformApiTests.UniformCase.call(this, name, description);
+ this.newB(shaderType, uniformCollection, additionalFeatures);
+ /** @type {es3fUniformApiTests.CaseType} */ this.m_caseType = caseType;
+ };
+
+ es3fUniformApiTests.UniformInfoQueryCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
+ /** Constructor restore */
+ es3fUniformApiTests.UniformInfoQueryCase.prototype.constructor = es3fUniformApiTests.UniformInfoQueryCase;
+
+ /**
+ * @param {es3fUniformApiTests.CaseType} caseType
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeName = function(caseType) {
+ switch (caseType) {
+ case es3fUniformApiTests.CaseType.UNIFORM: return 'active_uniform';
+ case es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV: return 'indices_active_uniformsiv';
+ case es3fUniformApiTests.CaseType.CONSISTENCY: return 'consistency';
+ default:
+ throw new Error('Invalid type');
+ }
+ };
+
+ /**
+ * @param {es3fUniformApiTests.CaseType} caseType
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeDescription = function(caseType) {
+ switch (caseType) {
+ case es3fUniformApiTests.CaseType.UNIFORM: return 'Test glGetActiveUniform()';
+ case es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV: return 'Test glGetUniformIndices() along with glGetActiveUniforms()';
+ case es3fUniformApiTests.CaseType.CONSISTENCY: return 'Check consistency between results from glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniforms()';
+ default:
+ throw new Error('Invalid type');
+ }
+ };
+
+ // \note Although this is only used in UniformApiTest::es3fUniformApiTests.init, it needs to be defined here as it's used as a template argument.
+ /**
+ * @constructor
+ * @param {?string} name
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection_
+ */
+ es3fUniformApiTests.UniformCollectionCase = function(name, uniformCollection_) {
+ /** @type {string} */ this.namePrefix = name ? name + '_' : '';
+ /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ this.uniformCollection = uniformCollection_;
+ };
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
+ * @param {gluShaderProgram.ShaderProgram} program
+ * @param {deRandom.Random} rnd
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformInfoQueryCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
+ /** @type {WebGLProgram} */ var programGL = program.getProgram();
+ /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var basicUniformReportsUniform = [];
+ /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var basicUniformReportsUniforms = [];
+ /** @type {boolean} */ var success;
+
+ if (this.m_caseType == es3fUniformApiTests.CaseType.UNIFORM || this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
+ success = false;
+
+ //TODO:: const ScopedLogSection section(log, "InfoGetActiveUniform", "es3fUniformApiTests.Uniform information queries with glGetActiveUniform()");
+ success = this.getActiveUniformsOneByOne(basicUniformReportsUniform, basicUniformReportsRef, programGL);
+
+ if (!success) {
+ if (this.m_caseType == es3fUniformApiTests.CaseType.UNIFORM)
+ return false;
+ else {
+ assertMsgOptions(
+ this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY,
+ 'es3fUniformApiTests.UniformInfoQueryCase.prototype.test - case type is not consistency',
+ false,
+ true
+ );
+ bufferedLogToConsole('// Note: this is a consistency case, so ignoring above failure(s)');
+ }
+ }
+ }
+
+ if (this.m_caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV || this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
+ success = false;
+
+ //TODO: const ScopedLogSection section(log, "InfoGetActiveUniforms", "es3fUniformApiTests.Uniform information queries with glGetUniformIndices() and glGetActiveUniforms()");
+ success = this.getActiveUniforms(basicUniformReportsUniforms, basicUniformReportsRef, programGL);
+
+ if (!success) {
+ if (this.m_caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV)
+ return false;
+ else {
+ assertMsgOptions(
+ this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY,
+ 'es3fUniformApiTests.UniformInfoQueryCase.prototype.test - case type is not consistency',
+ false,
+ true
+ );
+ bufferedLogToConsole('// Note: this is a consistency case, so ignoring above failure(s)');
+ }
+ }
+ }
+
+ if (this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
+ success = false;
+
+ //TODO: const ScopedLogSection section(log, "CompareUniformVsUniforms", "Comparison of results from glGetActiveUniform() and glGetActiveUniforms()");
+ success = this.uniformVsUniformsComparison(basicUniformReportsUniform, basicUniformReportsUniforms);
+
+ if (!success)
+ return false;
+ }
+
+ return true;
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fUniformApiTests.ValueToCheck = {
+ INITIAL: 0, //!< Verify the initial values of the uniforms (i.e. check that they're zero).
+ ASSIGNED: 1 //!< Assign values to uniforms with glUniform*(), and check those.
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fUniformApiTests.CheckMethod = {
+ GET_UNIFORM: 0, //!< Check values with glGetUniform*().
+ RENDER: 1 //!< Check values by rendering with the value-checking shader.
+ };
+
+ /**
+ * @enum {number}
+ */
+ es3fUniformApiTests.AssignMethod = {
+ POINTER: 0,
+ VALUE: 1
+ };
+
+ /**
+ * es3fUniformApiTests.UniformValueCase test class
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {es3fUniformApiTests.CaseShaderType} shaderType
+ * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
+ * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
+ * @param {es3fUniformApiTests.CheckMethod} checkMethod
+ * @param {?es3fUniformApiTests.AssignMethod} assignMethod
+ * @param {es3fUniformApiTests.Feature} additionalFeatures
+ * @extends {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.UniformValueCase = function(name, description, shaderType, uniformCollection, valueToCheck, checkMethod, assignMethod, additionalFeatures) {
+ es3fUniformApiTests.UniformCase.call(this, name, description);
+
+ additionalFeatures.UNIFORMVALUE_ZERO |= valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL;
+ additionalFeatures.UNIFORMFUNC_VALUE |= assignMethod == es3fUniformApiTests.AssignMethod.VALUE;
+ this.newB(shaderType, uniformCollection, additionalFeatures);
+
+ this.m_valueToCheck = valueToCheck;
+ this.m_checkMethod = checkMethod;
+
+ assertMsgOptions(
+ !(assignMethod === undefined && valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED),
+ 'es3fUniformApiTests.UniformValueCase - assign method is undefined when value to check requires it',
+ false,
+ true
+ );
+ };
+
+ es3fUniformApiTests.UniformValueCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
+ /** Constructor restore */
+ es3fUniformApiTests.UniformValueCase.prototype.constructor = es3fUniformApiTests.UniformValueCase;
+
+ /**
+ * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformValueCase.getValueToCheckName = function(valueToCheck) {
+ switch (valueToCheck) {
+ case es3fUniformApiTests.ValueToCheck.INITIAL: return 'initial';
+ case es3fUniformApiTests.ValueToCheck.ASSIGNED: return 'assigned';
+ default: throw new Error('es3fUniformApiTests.UniformValueCase.getValueToCheckName - Invalid value to check option');
+ }
+ };
+
+ /**
+ * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformValueCase.getValueToCheckDescription = function(valueToCheck) {
+ switch (valueToCheck) {
+ case es3fUniformApiTests.ValueToCheck.INITIAL: return 'Check initial uniform values (zeros)';
+ case es3fUniformApiTests.ValueToCheck.ASSIGNED: return 'Check assigned uniform values';
+ default: throw new Error('es3fUniformApiTests.UniformValueCase.getValueToCheckDescription - Invalid value to check option');
+ }
+ };
+
+ /**
+ * @param {es3fUniformApiTests.CheckMethod} checkMethod
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformValueCase.getCheckMethodName = function(checkMethod) {
+ switch (checkMethod) {
+ case es3fUniformApiTests.CheckMethod.GET_UNIFORM: return 'get_uniform';
+ case es3fUniformApiTests.CheckMethod.RENDER: return 'render';
+ default: throw new Error('es3fUniformApiTests.UniformValueCase.getCheckMethodName - Invalid check method');
+ }
+ };
+
+ /**
+ * @param {es3fUniformApiTests.CheckMethod} checkMethod
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformValueCase.getCheckMethodDescription = function(checkMethod) {
+ switch (checkMethod) {
+ case es3fUniformApiTests.CheckMethod.GET_UNIFORM: return 'Verify values with glGetUniform*()';
+ case es3fUniformApiTests.CheckMethod.RENDER: return 'Verify values by rendering';
+ default: throw new Error('es3fUniformApiTests.UniformValueCase.getCheckMethodDescription - Invalid check method');
+ }
+ };
+
+ /**
+ * @param {es3fUniformApiTests.AssignMethod} assignMethod
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformValueCase.getAssignMethodName = function(assignMethod) {
+ switch (assignMethod) {
+ case es3fUniformApiTests.AssignMethod.POINTER: return 'by_pointer';
+ case es3fUniformApiTests.AssignMethod.VALUE: return 'by_value';
+ default: throw new Error('es3fUniformApiTests.UniformValueCase.getAssignMethodName - Invalid assign method');
+ }
+ };
+
+ /**
+ * @param {es3fUniformApiTests.AssignMethod} assignMethod
+ * @return {?string}
+ */
+ es3fUniformApiTests.UniformValueCase.getAssignMethodDescription = function(assignMethod) {
+ switch (assignMethod) {
+ case es3fUniformApiTests.AssignMethod.POINTER: return 'Assign values by-pointer';
+ case es3fUniformApiTests.AssignMethod.VALUE: return 'Assign values by-value';
+ default: throw new Error('es3fUniformApiTests.UniformValueCase.getAssignMethodDescription - Invalid assign method');
+ }
+ };
+
+ /**
+ * es3fUniformApiTests.UniformValueCase test function
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
+ * @param {gluShaderProgram.ShaderProgram} program
+ * @param {deRandom.Random} rnd
+ * @return {boolean}
+ */
+ es3fUniformApiTests.UniformValueCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
+ /** @type {WebGLProgram} */ var programGL = program.getProgram();
+
+ if (this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED) {
+ //TODO: const ScopedLogSection section(log, "UniformAssign", "es3fUniformApiTests.Uniform value assignments");
+ this.assignUniforms(basicUniforms, programGL, rnd);
+ } else
+ assertMsgOptions(
+ this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL,
+ 'es3fUniformApiTests.UniformValueCase.prototype.test - value to check not initial',
+ false, true
+ );
+
+ /** @type {boolean}*/ var success;
+
+ if (this.m_checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM) {
+ /** @type {Array<es3fUniformApiTests.VarValue>} */ var values = [];
+
+ //TODO: const ScopedLogSection section(log, "GetUniforms", "es3fUniformApiTests.Uniform value query");
+ success = this.getUniforms(values, basicUniforms, program.getProgram());
+
+ if (!success)
+ return false;
+
+ if (this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED) {
+ //TODO: const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values");
+ success = this.compareUniformValues(values, basicUniforms);
+
+ if (!success)
+ return false;
+ } else {
+ assertMsgOptions(
+ this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL,
+ 'es3fUniformApiTests.UniformValueCase.prototype.test - value to check not initial',
+ false, true
+ );
+
+ //TODO: const ScopedLogSection section(log, "ValueCheck", "Verify that the uniforms have correct initial values (zeros)");
+ success = this.checkUniformDefaultValues(values, basicUniforms);
+
+ if (!success)
+ return false;
+ }
+ } else {
+ assertMsgOptions(
+ this.m_checkMethod == es3fUniformApiTests.CheckMethod.RENDER,
+ 'es3fUniformApiTests.UniformValueCase.prototype.test - check method different than RENDER',
+ false, true
+ );
+
+ //TODO: const ScopedLogSection section(log, "RenderTest", "Render test");
+ success = this.renderTest(basicUniforms, program, rnd);
+
+ if (!success)
+ return false;
+ }
+
+ return true;
+ };
+
+ /**
+ * es3fUniformApiTests.RandomUniformCase test class
+ * @constructor
+ * @param {string} name
+ * @param {string} description
+ * @param {number} seed
+ * @extends {es3fUniformApiTests.UniformCase}
+ */
+ es3fUniformApiTests.RandomUniformCase = function(name, description, seed) {
+ es3fUniformApiTests.UniformCase.call(this, name, description);
+ this.newC(seed ^ deRandom.getBaseSeed());
+ };
+
+ es3fUniformApiTests.RandomUniformCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
+ /** Constructor restore */
+ es3fUniformApiTests.RandomUniformCase.prototype.constructor = es3fUniformApiTests.RandomUniformCase;
+
+ /**
+ * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
+ * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
+ * @param {gluShaderProgram.ShaderProgram} program
+ * @param {deRandom.Random} rnd
+ * @return {boolean}
+ */
+ es3fUniformApiTests.RandomUniformCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
+ // \note Different sampler types may not be bound to same unit when rendering.
+ /** @type {boolean}*/ var renderingPossible = !this.m_features.UNIFORMVALUE_ZERO || !this.m_uniformCollection.containsSeveralSamplerTypes();
+
+ /** @type {boolean} */ var performGetActiveUniforms = rnd.getBool();
+ /** @type {boolean} */ var performGetActiveUniformsiv = rnd.getBool();
+ /** @type {boolean} */ var performUniformVsUniformsivComparison = performGetActiveUniforms && performGetActiveUniformsiv && rnd.getBool();
+ /** @type {boolean} */ var performGetUniforms = rnd.getBool();
+ /** @type {boolean} */ var performCheckUniformDefaultValues = performGetUniforms && rnd.getBool();
+ /** @type {boolean} */ var performAssignUniforms = rnd.getBool();
+ /** @type {boolean} */ var performCompareUniformValues = performGetUniforms && performAssignUniforms && rnd.getBool();
+ /** @type {boolean} */ var performRenderTest = renderingPossible && performAssignUniforms && rnd.getBool();
+ /** @type {WebGLProgram} */ var programGL = program.getProgram();
+
+ if (!(performGetActiveUniforms || performGetActiveUniformsiv || performUniformVsUniformsivComparison || performGetUniforms || performCheckUniformDefaultValues || performAssignUniforms || performCompareUniformValues || performRenderTest))
+ performGetActiveUniforms = true; // Do something at least.
+
+ var PERFORM_AND_CHECK = function(CALL, SECTION_NAME, SECTION_DESCRIPTION) {
+ //TODO: const ScopedLogSection section(log, (SECTION_NAME), (SECTION_DESCRIPTION));
+ /** @type {boolean} */ var success = CALL();
+ if (!success)
+ return false;
+ };
+
+ /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var reportsUniform = [];
+ /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var reportsUniformsiv = [];
+
+ var current = this; //To use "this" in anonymous function.
+
+ if (performGetActiveUniforms)
+ PERFORM_AND_CHECK(function() {current.getActiveUniformsOneByOne(reportsUniform, basicUniformReportsRef, programGL);}, 'InfoGetActiveUniform', 'es3fUniformApiTests.Uniform information queries with glGetActiveUniform()');
+
+ if (performGetActiveUniformsiv)
+ PERFORM_AND_CHECK(function() {current.getActiveUniforms(reportsUniformsiv, basicUniformReportsRef, programGL);}, 'InfoGetActiveUniformsiv', 'es3fUniformApiTests.Uniform information queries with glGetIndices() and glGetActiveUniformsiv()');
+
+ if (performUniformVsUniformsivComparison)
+ PERFORM_AND_CHECK(function() {current.uniformVsUniformsComparison(reportsUniform, reportsUniformsiv);}, 'CompareUniformVsUniformsiv', 'Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()');
+
+ /** @type {Array<es3fUniformApiTests.VarValue>} */ var uniformDefaultValues = [];
+
+ if (performGetUniforms)
+ PERFORM_AND_CHECK(function() {current.getUniforms(uniformDefaultValues, basicUniforms, programGL);}, 'GetUniformDefaults', 'es3fUniformApiTests.Uniform default value query');
+
+ if (performCheckUniformDefaultValues)
+ PERFORM_AND_CHECK(function() {current.checkUniformDefaultValues(uniformDefaultValues, basicUniforms);}, 'DefaultValueCheck', 'Verify that the uniforms have correct initial values (zeros)');
+
+ /** @type {Array<es3fUniformApiTests.VarValue>} */ var uniformValues = [];
+
+ if (performAssignUniforms) {
+ //TODO: const ScopedLogSection section(log, "UniformAssign", "es3fUniformApiTests.Uniform value assignments");
+ this.assignUniforms(basicUniforms, programGL, rnd);
+ }
+
+ if (performCompareUniformValues) {
+ PERFORM_AND_CHECK(function() {current.getUniforms(uniformValues, basicUniforms, programGL);}, 'GetUniforms', 'es3fUniformApiTests.Uniform value query');
+ PERFORM_AND_CHECK(function() {current.compareUniformValues(uniformValues, basicUniforms);}, 'ValueCheck', 'Verify that the reported values match the assigned values');
+ }
+
+ if (performRenderTest)
+ PERFORM_AND_CHECK(function() {current.renderTest(basicUniforms, program, rnd);}, 'RenderTest', 'Render test');
+
+ return true;
+ };
+
+ /**
+ * Initializes the tests to be performed.
+ */
+ es3fUniformApiTests.init = function() {
+ var state = tcuTestCase.runner;
+ var testGroup = state.testCases;
+
+ // Generate sets of UniformCollections that are used by several cases.
+ /**
+ * @enum
+ */
+ var UniformCollections = {
+ BASIC: 0,
+ BASIC_ARRAY: 1,
+ BASIC_STRUCT: 2,
+ STRUCT_IN_ARRAY: 3,
+ ARRAY_IN_STRUCT: 4,
+ NESTED_STRUCTS_ARRAYS: 5,
+ MULTIPLE_BASIC: 6,
+ MULTIPLE_BASIC_ARRAY: 7,
+ MULTIPLE_NESTED_STRUCTS_ARRAYS: 8
+ };
+
+ /**
+ * @constructor
+ */
+ var UniformCollectionGroup = function() {
+ /** @type {string} */ this.name = '';
+ /** @type {Array<es3fUniformApiTests.UniformCollectionCase>} */ this.cases = [];
+ };
+
+ /** @type {Array<UniformCollectionGroup>} */ var defaultUniformCollections = new Array(Object.keys(UniformCollections).length);
+
+ /** @type {string} */ var name;
+
+ //Initialize
+ for (var i = 0; i < defaultUniformCollections.length; i++) defaultUniformCollections[i] = new UniformCollectionGroup();
+
+ defaultUniformCollections[UniformCollections.BASIC].name = 'basic';
+ defaultUniformCollections[UniformCollections.BASIC_ARRAY].name = 'basic_array';
+ defaultUniformCollections[UniformCollections.BASIC_STRUCT].name = 'basic_struct';
+ defaultUniformCollections[UniformCollections.STRUCT_IN_ARRAY].name = 'struct_in_array';
+ defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT].name = 'array_in_struct';
+ defaultUniformCollections[UniformCollections.NESTED_STRUCTS_ARRAYS].name = 'nested_structs_arrays';
+ defaultUniformCollections[UniformCollections.MULTIPLE_BASIC].name = 'multiple_basic';
+ defaultUniformCollections[UniformCollections.MULTIPLE_BASIC_ARRAY].name = 'multiple_basic_array';
+ defaultUniformCollections[UniformCollections.MULTIPLE_NESTED_STRUCTS_ARRAYS].name = 'multiple_nested_structs_arrays';
+
+ for (var dataTypeNdx = 0; dataTypeNdx < es3fUniformApiTests.s_testDataTypes.length; dataTypeNdx++) {
+ /** @type {gluShaderUtil.DataType} */ var dataType = es3fUniformApiTests.s_testDataTypes[dataTypeNdx];
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(dataType);
+
+ defaultUniformCollections[UniformCollections.BASIC].cases.push(new es3fUniformApiTests.UniformCollectionCase(typeName, es3fUniformApiTests.UniformCollection.basic(dataType)));
+
+ if (gluShaderUtil.isDataTypeScalar(dataType) ||
+ (gluShaderUtil.isDataTypeVector(dataType) && gluShaderUtil.getDataTypeScalarSize(dataType) == 4) ||
+ dataType == gluShaderUtil.DataType.FLOAT_MAT4 ||
+ dataType == gluShaderUtil.DataType.SAMPLER_2D)
+ defaultUniformCollections[UniformCollections.BASIC_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(typeName, es3fUniformApiTests.UniformCollection.basicArray(dataType)));
+
+ if (gluShaderUtil.isDataTypeScalar(dataType) ||
+ dataType == gluShaderUtil.DataType.FLOAT_MAT4 ||
+ dataType == gluShaderUtil.DataType.SAMPLER_2D) {
+ /** @type {gluShaderUtil.DataType} */ var secondDataType;
+ if (gluShaderUtil.isDataTypeScalar(dataType))
+ secondDataType = gluShaderUtil.getDataTypeVector(dataType, 4);
+ else if (dataType == gluShaderUtil.DataType.FLOAT_MAT4)
+ secondDataType = gluShaderUtil.DataType.FLOAT_MAT2;
+ else if (dataType == gluShaderUtil.DataType.SAMPLER_2D)
+ secondDataType = gluShaderUtil.DataType.SAMPLER_CUBE;
+
+ assertMsgOptions(
+ secondDataType !== undefined,
+ 'es3fUniformApiTests.init - second data type undefined',
+ false, true
+ );
+
+ /** @type {string} */ var secondTypeName = gluShaderUtil.getDataTypeName(secondDataType);
+ name = typeName + '_' + secondTypeName;
+
+ defaultUniformCollections[UniformCollections.BASIC_STRUCT].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.basicStruct(dataType, secondDataType, false)));
+ defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.basicStruct(dataType, secondDataType, true)));
+ defaultUniformCollections[UniformCollections.STRUCT_IN_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.structInArray(dataType, secondDataType, false)));
+ defaultUniformCollections[UniformCollections.NESTED_STRUCTS_ARRAYS].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.nestedArraysStructs(dataType, secondDataType)));
+ }
+ }
+ defaultUniformCollections[UniformCollections.MULTIPLE_BASIC].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleBasic()));
+ defaultUniformCollections[UniformCollections.MULTIPLE_BASIC_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleBasicArray()));
+ defaultUniformCollections[UniformCollections.MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs()));
+
+ // Info-query cases (check info returned by e.g. glGetActiveUniforms()).
+
+ // info_query
+ /** @type {tcuTestCase.DeqpTest} */
+ var infoQueryGroup = tcuTestCase.newTest('info_query', 'Test uniform info querying functions');
+ testGroup.addChild(infoQueryGroup);
+
+ /** @type {UniformCollectionGroup} */ var collectionGroup;
+ /** @type {es3fUniformApiTests.UniformCollectionCase} */ var collectionCase;
+ /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ var uniformCollection;
+ /** @type {es3fUniformApiTests.Feature} */ var features;
+ /** @type {tcuTestCase.DeqpTest} */ var collectionTestGroup;
+ /** @type {string} */ var collName;
+ /** @type {es3fUniformApiTests.CheckMethod} */ var checkMethod;
+ /** @type {tcuTestCase.DeqpTest} */ var checkMethodGroup;
+ /** @type {string} */ var collectionGroupName;
+ /** @type {boolean} */ var containsBooleans;
+ /** @type {boolean} */ var varyBoolApiType;
+ /** @type {number} */ var numBoolVariations;
+ /** @type {es3fUniformApiTests.Feature} */ var booleanTypeFeat;
+ /** @type {string} */ var booleanTypeName;
+ /** @type {tcuTestCase.DeqpTest} */ var unusedUniformsGroup;
+
+ /** @type {Array<string>} */ var shaderTypes = Object.keys(es3fUniformApiTests.CaseShaderType);
+
+ for (var caseTypeI in es3fUniformApiTests.CaseType) {
+ /** @type {es3fUniformApiTests.CaseType} */ var caseType = es3fUniformApiTests.CaseType[caseTypeI];
+ /** @type {tcuTestCase.DeqpTest} */
+ var caseTypeGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeName(caseType), es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeDescription(caseType));
+ infoQueryGroup.addChild(caseTypeGroup);
+
+ for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
+ var numArrayFirstElemNameCases = caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV && collectionGroupNdx == UniformCollections.BASIC_ARRAY ? 2 : 1;
+
+ for (var referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) {
+ collectionGroup = defaultUniformCollections[collectionGroupNdx];
+ collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? '' : '_first_elem_without_brackets');
+ collectionTestGroup = tcuTestCase.newTest(collectionGroupName, '');
+ caseTypeGroup.addChild(collectionTestGroup);
+
+ for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
+ collectionCase = collectionGroup.cases[collectionNdx];
+
+ for (var i = 0; i < shaderTypes.length; i++) {
+ name = collectionCase.namePrefix + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
+ uniformCollection = collectionCase.uniformCollection;
+
+ features = new es3fUniformApiTests.Feature();
+ features.ARRAY_FIRST_ELEM_NAME_NO_INDEX = referToFirstArrayElemWithoutIndexI != 0;
+
+ collectionTestGroup.addChild(new es3fUniformApiTests.UniformInfoQueryCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection, caseType, features));
+ }
+ }
+ }
+ }
+
+ // Info-querying cases when unused uniforms are present.
+
+ unusedUniformsGroup = tcuTestCase.newTest('unused_uniforms', 'Test with unused uniforms');
+ caseTypeGroup.addChild(unusedUniformsGroup);
+
+ collectionGroup = defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT];
+
+ for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
+ collectionCase = collectionGroup.cases[collectionNdx];
+ collName = collectionCase.namePrefix;
+ uniformCollection = collectionCase.uniformCollection;
+
+ for (var i = 0; i < shaderTypes.length; i++) {
+ name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
+
+ features = new es3fUniformApiTests.Feature();
+ features.UNIFORMUSAGE_EVERY_OTHER = true;
+ features.ARRAYUSAGE_ONLY_MIDDLE_INDEX = true;
+
+ unusedUniformsGroup.addChild(new es3fUniformApiTests.UniformInfoQueryCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection, caseType, features));
+ }
+ }
+ }
+
+ // Cases testing uniform values.
+
+ // Cases checking uniforms' initial values (all must be zeros), with glGetUniform*() or by rendering.
+
+ /** @type {tcuTestCase.DeqpTest} */ var initialValuesGroup = tcuTestCase.newTest(
+ 'value.' + es3fUniformApiTests.UniformValueCase.getValueToCheckName(es3fUniformApiTests.ValueToCheck.INITIAL),
+ es3fUniformApiTests.UniformValueCase.getValueToCheckDescription(es3fUniformApiTests.ValueToCheck.INITIAL));
+ testGroup.addChild(initialValuesGroup);
+
+ for (var checkMethodI in es3fUniformApiTests.CheckMethod) {
+ checkMethod = es3fUniformApiTests.CheckMethod[checkMethodI];
+ checkMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getCheckMethodName(checkMethod), es3fUniformApiTests.UniformValueCase.getCheckMethodDescription(checkMethod));
+ initialValuesGroup.addChild(checkMethodGroup);
+
+ for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
+ collectionGroup = defaultUniformCollections[collectionGroupNdx];
+ collectionTestGroup = tcuTestCase.newTest(collectionGroup.name, '');
+ checkMethodGroup.addChild(collectionTestGroup);
+
+ for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
+ collectionCase = collectionGroup.cases[collectionNdx];
+ collName = collectionCase.namePrefix;
+ uniformCollection = collectionCase.uniformCollection;
+ containsBooleans = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeBoolOrBVec);
+ varyBoolApiType = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && containsBooleans &&
+ (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
+ numBoolVariations = varyBoolApiType ? 3 : 1;
+
+ if (checkMethod == es3fUniformApiTests.CheckMethod.RENDER && uniformCollection.containsSeveralSamplerTypes())
+ continue; // \note Samplers' initial API values (i.e. their texture units) are 0, and no two samplers of different types shall have same unit when rendering.
+
+ for (var booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) {
+ booleanTypeFeat = new es3fUniformApiTests.Feature();
+ booleanTypeFeat.BOOLEANAPITYPE_INT = booleanTypeI == 1;
+ booleanTypeFeat.BOOLEANAPITYPE_UINT = booleanTypeI == 2;
+
+ booleanTypeName = booleanTypeI == 1 ? 'int' :
+ booleanTypeI == 2 ? 'uint' :
+ 'float';
+ /** @type {string} */ var nameWithApiType = varyBoolApiType ? collName + 'api_' + booleanTypeName + '_' : collName;
+
+ for (var i = 0; i < shaderTypes.length; i++) {
+ name = nameWithApiType + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
+ collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
+ es3fUniformApiTests.ValueToCheck.INITIAL, checkMethod, null, booleanTypeFeat));
+ }
+ }
+ }
+ }
+ }
+
+ // Cases that first assign values to each uniform, then check the values with glGetUniform*() or by rendering.
+
+ /** @type {tcuTestCase.DeqpTest} */ var assignedValuesGroup = tcuTestCase.newTest(
+ 'value.' + es3fUniformApiTests.UniformValueCase.getValueToCheckName(es3fUniformApiTests.ValueToCheck.ASSIGNED),
+ es3fUniformApiTests.UniformValueCase.getValueToCheckDescription(es3fUniformApiTests.ValueToCheck.ASSIGNED));
+ testGroup.addChild(assignedValuesGroup);
+
+ for (var assignMethodI in es3fUniformApiTests.AssignMethod) {
+ /** @type {es3fUniformApiTests.AssignMethod} */ var assignMethod = es3fUniformApiTests.AssignMethod[assignMethodI];
+ /** @type {tcuTestCase.DeqpTest} */ var assignMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getAssignMethodName(assignMethod), es3fUniformApiTests.UniformValueCase.getAssignMethodDescription(assignMethod));
+ assignedValuesGroup.addChild(assignMethodGroup);
+
+ for (var checkMethodI in es3fUniformApiTests.CheckMethod) {
+ checkMethod = es3fUniformApiTests.CheckMethod[checkMethodI];
+ checkMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getCheckMethodName(checkMethod), es3fUniformApiTests.UniformValueCase.getCheckMethodDescription(checkMethod));
+ assignMethodGroup.addChild(checkMethodGroup);
+
+ for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
+ /** @type {number} */ var numArrayFirstElemNameCases = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && collectionGroupNdx == UniformCollections.BASIC_ARRAY ? 2 : 1;
+
+ for (var referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) {
+ collectionGroup = defaultUniformCollections[collectionGroupNdx];
+ collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? '' : '_first_elem_without_brackets');
+ collectionTestGroup = tcuTestCase.newTest(collectionGroupName, '');
+ checkMethodGroup.addChild(collectionTestGroup);
+
+ for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
+ collectionCase = collectionGroup.cases[collectionNdx];
+ collName = collectionCase.namePrefix;
+ uniformCollection = collectionCase.uniformCollection;
+ containsBooleans = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeBoolOrBVec);
+ varyBoolApiType = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && containsBooleans &&
+ (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
+ numBoolVariations = varyBoolApiType ? 3 : 1;
+ /** @type {boolean} */ var containsMatrices = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeMatrix);
+ /** @type {boolean} */ var varyMatrixMode = containsMatrices &&
+ (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
+ /** @type {number} */ var numMatVariations = varyMatrixMode ? 2 : 1;
+
+ if (containsMatrices && assignMethod != es3fUniformApiTests.AssignMethod.POINTER)
+ continue;
+
+ for (var booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) {
+ booleanTypeFeat = new es3fUniformApiTests.Feature();
+ booleanTypeFeat.BOOLEANAPITYPE_INT = booleanTypeI == 1;
+ booleanTypeFeat.BOOLEANAPITYPE_UINT = booleanTypeI == 2;
+
+ booleanTypeName = booleanTypeI == 1 ? 'int' :
+ booleanTypeI == 2 ? 'uint' :
+ 'float';
+ /** @type {string} */ var nameWithBoolType = varyBoolApiType ? collName + 'api_' + booleanTypeName + '_' : collName;
+
+ for (var matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++) {
+ /** @type {string} */ var nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? 'row_major_' : '');
+
+ for (var i = 0; i < shaderTypes.length; i++) {
+ name = nameWithMatrixType + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
+
+ booleanTypeFeat.ARRAY_FIRST_ELEM_NAME_NO_INDEX = referToFirstArrayElemWithoutIndexI != 0;
+ booleanTypeFeat.MATRIXMODE_ROWMAJOR = matrixTypeI == 1;
+
+ collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
+ es3fUniformApiTests.ValueToCheck.ASSIGNED, checkMethod, assignMethod, booleanTypeFeat));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Cases assign multiple basic-array elements with one glUniform*v() (i.e. the count parameter is bigger than 1).
+
+ /** @type {es3fUniformApiTests.Feature} */ var arrayAssignFullMode = new es3fUniformApiTests.Feature();
+ arrayAssignFullMode.ARRAYASSIGN_FULL = true;
+
+ /** @type {es3fUniformApiTests.Feature} */ var arrayAssignBlocksOfTwo = new es3fUniformApiTests.Feature();
+ arrayAssignFullMode.ARRAYASSIGN_BLOCKS_OF_TWO = true;
+
+ var arrayAssignGroups =
+ [{arrayAssignMode: arrayAssignFullMode, name: 'basic_array_assign_full', description: 'Assign entire basic-type arrays per glUniform*v() call'}, {arrayAssignMode: arrayAssignBlocksOfTwo, name: 'basic_array_assign_partial', description: 'Assign two elements of a basic-type array per glUniform*v() call'}
+ ];
+
+ for (var arrayAssignGroupNdx = 0; arrayAssignGroupNdx < arrayAssignGroups.length; arrayAssignGroupNdx++) {
+ /** @type {es3fUniformApiTests.Feature} */ var arrayAssignMode = arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode;
+ /** @type {string} */ var groupName = arrayAssignGroups[arrayAssignGroupNdx].name;
+ /** @type {string} */ var groupDesc = arrayAssignGroups[arrayAssignGroupNdx].description;
+
+ /** @type {tcuTestCase.DeqpTest} */ var curArrayAssignGroup = tcuTestCase.newTest(groupName, groupDesc);
+ assignedValuesGroup.addChild(curArrayAssignGroup);
+
+ /** @type {Array<number>} */ var basicArrayCollectionGroups = [UniformCollections.BASIC_ARRAY, UniformCollections.ARRAY_IN_STRUCT, UniformCollections.MULTIPLE_BASIC_ARRAY];
+
+ for (var collectionGroupNdx = 0; collectionGroupNdx < basicArrayCollectionGroups.length; collectionGroupNdx++) {
+ collectionGroup = defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]];
+ collectionTestGroup = tcuTestCase.newTest(collectionGroup.name, '');
+ curArrayAssignGroup.addChild(collectionTestGroup);
+
+ for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
+ collectionCase = collectionGroup.cases[collectionNdx];
+ collName = collectionCase.namePrefix;
+ uniformCollection = collectionCase.uniformCollection;
+
+ for (var i = 0; i < shaderTypes.length; i++) {
+ name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
+ collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
+ es3fUniformApiTests.ValueToCheck.ASSIGNED, es3fUniformApiTests.CheckMethod.GET_UNIFORM, es3fUniformApiTests.AssignMethod.POINTER,
+ arrayAssignMode));
+ }
+ }
+ }
+ }
+
+ // Value checking cases when unused uniforms are present.
+
+ unusedUniformsGroup = tcuTestCase.newTest('unused_uniforms', 'Test with unused uniforms');
+ assignedValuesGroup.addChild(unusedUniformsGroup);
+
+ collectionGroup = defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT];
+
+ for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
+ collectionCase = collectionGroup.cases[collectionNdx];
+ collName = collectionCase.namePrefix;
+ uniformCollection = collectionCase.uniformCollection;
+
+ for (var i = 0; i < shaderTypes.length; i++) {
+ name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
+
+ features = new es3fUniformApiTests.Feature();
+ features.ARRAYUSAGE_ONLY_MIDDLE_INDEX = true;
+ features.UNIFORMUSAGE_EVERY_OTHER = true;
+
+ unusedUniformsGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
+ es3fUniformApiTests.ValueToCheck.ASSIGNED, es3fUniformApiTests.CheckMethod.GET_UNIFORM, es3fUniformApiTests.AssignMethod.POINTER,
+ features));
+ }
+ }
+
+ // Random cases.
+
+ /** @type {number} */ var numRandomCases = 100;
+ /** @type {tcuTestCase.DeqpTest} */ var randomGroup = tcuTestCase.newTest('random', 'Random cases');
+ testGroup.addChild(randomGroup);
+
+ for (var ndx = 0; ndx < numRandomCases; ndx++)
+ randomGroup.addChild(new es3fUniformApiTests.RandomUniformCase('' + ndx, '', ndx));
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fUniformApiTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var testName = 'uniform_api';
+ var testDescription = 'es3fUniformApiTests.Uniform API Tests';
+ var state = tcuTestCase.runner;
+
+ state.testName = testName;
+ state.testCases = tcuTestCase.newTest(testName, testDescription, null);
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fUniformApiTests.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fUniformApiTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformBlockTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformBlockTests.js
new file mode 100644
index 0000000000..91a90fdc64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fUniformBlockTests.js
@@ -0,0 +1,748 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fUniformBlockTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('modules.shared.glsRandomUniformBlockCase');
+goog.require('modules.shared.glsUniformBlockCase');
+
+goog.scope(function() {
+
+ var es3fUniformBlockTests = functional.gles3.es3fUniformBlockTests;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var glsUniformBlockCase = modules.shared.glsUniformBlockCase;
+ var glsRandomUniformBlockCase = modules.shared.glsRandomUniformBlockCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+
+ /**
+ * es3fUniformBlockTests.createRandomCaseGroup
+ * @param {tcuTestCase.DeqpTest} parentGroup
+ * @param {string} groupName
+ * @param {string} description
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} features
+ * @param {number} numCases
+ * @param {number} baseSeed
+ */
+ es3fUniformBlockTests.createRandomCaseGroup = function(parentGroup, groupName, description, bufferMode, features, numCases, baseSeed) {
+ /** @type {tcuTestCase.DeqpTest} */
+ var group = tcuTestCase.newTest(groupName, description);
+ parentGroup.addChild(group);
+
+ baseSeed += deRandom.getBaseSeed();
+
+ for (var ndx = 0; ndx < numCases; ndx++)
+ group.addChild(new glsRandomUniformBlockCase.RandomUniformBlockCase('' + ndx, '', bufferMode, features, ndx + baseSeed));
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockBasicTypeCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {glsUniformBlockCase.VarType} type The type of the block
+ * @param {number} layoutFlags
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockBasicTypeCase = function(name, description, type, layoutFlags, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK);
+ /** @type {glsUniformBlockCase.UniformBlock}*/ var block = this.m_interface.allocBlock('Block');
+ block.addUniform(new glsUniformBlockCase.Uniform('var', type, 0));
+ block.setFlags(layoutFlags);
+
+ if (numInstances > 0) {
+ block.setArraySize(numInstances);
+ block.setInstanceName('block');
+ }
+ };
+
+ es3fUniformBlockTests.BlockBasicTypeCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockBasicTypeCase.prototype.constructor = es3fUniformBlockTests.BlockBasicTypeCase;
+
+ /**
+ * es3fUniformBlockTests.createBlockBasicTypeCases
+ * @param {tcuTestCase.DeqpTest} group
+ * @param {string} name
+ * @param {glsUniformBlockCase.VarType} type
+ * @param {number} layoutFlags
+ * @param {number=} numInstances
+ */
+ es3fUniformBlockTests.createBlockBasicTypeCases = function(group, name, type, layoutFlags, numInstances) {
+ numInstances = (numInstances === undefined) ? 0 : numInstances;
+ group.addChild(new es3fUniformBlockTests.BlockBasicTypeCase(name + '_vertex', '', type, layoutFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, numInstances));
+ group.addChild(new es3fUniformBlockTests.BlockBasicTypeCase(name + '_fragment', '', type, layoutFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, numInstances));
+
+ //alert(group.spec[0].m_instance);
+ if (!(layoutFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ group.addChild(new es3fUniformBlockTests.BlockBasicTypeCase(name + '_both', '', type, layoutFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, numInstances));
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockSingleStructCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {number} layoutFlags
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockSingleStructCase = function(name, description, layoutFlags, bufferMode, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_layoutFlags = layoutFlags;
+ this.m_numInstances = numInstances;
+ };
+
+ es3fUniformBlockTests.BlockSingleStructCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockSingleStructCase.prototype.constructor = es3fUniformBlockTests.BlockSingleStructCase;
+
+ es3fUniformBlockTests.BlockSingleStructCase.prototype.init = function() {
+ /**@type {glsUniformBlockCase.StructType}*/ var typeS = this.m_interface.allocStruct('S');
+ typeS.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC3, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), glsUniformBlockCase.UniformFlags.UNUSED_BOTH); // First member is unused.
+ typeS.addMember('b', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM), 4));
+ typeS.addMember('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_HIGH));
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.allocBlock('Block');
+ block.addUniform(new glsUniformBlockCase.Uniform('s', glsUniformBlockCase.newVarTypeStruct(typeS), 0));
+ block.setFlags(this.m_layoutFlags);
+
+ if (this.m_numInstances > 0) {
+ block.setInstanceName('block');
+ block.setArraySize(this.m_numInstances);
+ }
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockSingleStructArrayCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {number} layoutFlags
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockSingleStructArrayCase = function(name, description, layoutFlags, bufferMode, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_layoutFlags = layoutFlags;
+ this.m_numInstances = numInstances;
+ };
+
+ es3fUniformBlockTests.BlockSingleStructArrayCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockSingleStructArrayCase.prototype.constructor = es3fUniformBlockTests.BlockSingleStructArrayCase;
+
+ es3fUniformBlockTests.BlockSingleStructArrayCase.prototype.init = function() {
+ /**@type {glsUniformBlockCase.StructType}*/ var typeS = this.m_interface.allocStruct('S');
+ typeS.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC3, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), glsUniformBlockCase.UniformFlags.UNUSED_BOTH); // First member is unused.
+ typeS.addMember('b', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM), 4));
+ typeS.addMember('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_HIGH));
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.allocBlock('Block');
+ block.addUniform(new glsUniformBlockCase.Uniform('u', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.UINT, glsUniformBlockCase.UniformFlags.PRECISION_LOW)));
+ block.addUniform(new glsUniformBlockCase.Uniform('s', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeStruct(typeS), 3)));
+ block.addUniform(new glsUniformBlockCase.Uniform('v', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM)));
+ block.setFlags(this.m_layoutFlags);
+
+ if (this.m_numInstances > 0) {
+ block.setInstanceName('block');
+ block.setArraySize(this.m_numInstances);
+ }
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockSingleNestedStructCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {number} layoutFlags
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockSingleNestedStructCase = function(name, description, layoutFlags, bufferMode, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_layoutFlags = layoutFlags;
+ this.m_numInstances = numInstances;
+ };
+
+ es3fUniformBlockTests.BlockSingleNestedStructCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockSingleNestedStructCase.prototype.constructor = es3fUniformBlockTests.BlockSingleNestedStructCase;
+
+ es3fUniformBlockTests.BlockSingleNestedStructCase.prototype.init = function() {
+ /**@type {glsUniformBlockCase.StructType}*/ var typeS = this.m_interface.allocStruct('S');
+ typeS.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC3, glsUniformBlockCase.UniformFlags.PRECISION_HIGH));
+ typeS.addMember('b', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM), 4));
+ typeS.addMember('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), glsUniformBlockCase.UniformFlags.UNUSED_BOTH);
+
+ /**@type {glsUniformBlockCase.StructType}*/ var typeT = this.m_interface.allocStruct('T');
+ typeT.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM));
+ typeT.addMember('b', glsUniformBlockCase.newVarTypeStruct(typeS));
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.allocBlock('Block');
+ block.addUniform(new glsUniformBlockCase.Uniform('s', glsUniformBlockCase.newVarTypeStruct(typeS), 0));
+ block.addUniform(new glsUniformBlockCase.Uniform('v', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, glsUniformBlockCase.UniformFlags.PRECISION_LOW), glsUniformBlockCase.UniformFlags.UNUSED_BOTH));
+ block.addUniform(new glsUniformBlockCase.Uniform('t', glsUniformBlockCase.newVarTypeStruct(typeT), 0));
+ block.addUniform(new glsUniformBlockCase.Uniform('u', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.UINT, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), 0));
+ block.setFlags(this.m_layoutFlags);
+
+ if (this.m_numInstances > 0) {
+ block.setInstanceName('block');
+ block.setArraySize(this.m_numInstances);
+ }
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockSingleNestedStructArrayCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {number} layoutFlags
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockSingleNestedStructArrayCase = function(name, description, layoutFlags, bufferMode, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_layoutFlags = layoutFlags;
+ this.m_numInstances = numInstances;
+ };
+
+ es3fUniformBlockTests.BlockSingleNestedStructArrayCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockSingleNestedStructArrayCase.prototype.constructor = es3fUniformBlockTests.BlockSingleNestedStructArrayCase;
+
+ es3fUniformBlockTests.BlockSingleNestedStructArrayCase.prototype.init = function() {
+ /**@type {glsUniformBlockCase.StructType}*/ var typeS = this.m_interface.allocStruct('S');
+ typeS.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC3, glsUniformBlockCase.UniformFlags.PRECISION_HIGH));
+ typeS.addMember('b', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC2, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM), 4));
+ typeS.addMember('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), glsUniformBlockCase.UniformFlags.UNUSED_BOTH);
+
+ /**@type {glsUniformBlockCase.StructType}*/ var typeT = this.m_interface.allocStruct('T');
+ typeT.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM));
+ typeT.addMember('b', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeStruct(typeS), 3));
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.allocBlock('Block');
+ block.addUniform(new glsUniformBlockCase.Uniform('s', glsUniformBlockCase.newVarTypeStruct(typeS), 0));
+ block.addUniform(new glsUniformBlockCase.Uniform('v', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, glsUniformBlockCase.UniformFlags.PRECISION_LOW), glsUniformBlockCase.UniformFlags.UNUSED_BOTH));
+ block.addUniform(new glsUniformBlockCase.Uniform('t', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeStruct(typeT), 2), 0));
+ block.addUniform(new glsUniformBlockCase.Uniform('u', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.UINT, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), 0));
+ block.setFlags(this.m_layoutFlags);
+
+ if (this.m_numInstances > 0) {
+ block.setInstanceName('block');
+ block.setArraySize(this.m_numInstances);
+ }
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockMultiBasicTypesCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {number} flagsA
+ * @param {number} flagsB
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockMultiBasicTypesCase = function(name, description, flagsA, flagsB, bufferMode, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_flagsA = flagsA;
+ this.m_flagsB = flagsB;
+ this.m_numInstances = numInstances;
+ };
+
+ es3fUniformBlockTests.BlockMultiBasicTypesCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockMultiBasicTypesCase.prototype.constructor = es3fUniformBlockTests.BlockMultiBasicTypesCase;
+
+ es3fUniformBlockTests.BlockMultiBasicTypesCase.prototype.init = function() {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var blockA = this.m_interface.allocBlock('BlockA');
+ blockA.addUniform(new glsUniformBlockCase.Uniform('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT, glsUniformBlockCase.UniformFlags.PRECISION_HIGH)));
+ blockA.addUniform(new glsUniformBlockCase.Uniform('b', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.UINT_VEC3, glsUniformBlockCase.UniformFlags.PRECISION_LOW), glsUniformBlockCase.UniformFlags.UNUSED_BOTH));
+ blockA.addUniform(new glsUniformBlockCase.Uniform('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT2, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM)));
+ blockA.setInstanceName('blockA');
+ blockA.setFlags(this.m_flagsA);
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var blockB = this.m_interface.allocBlock('BlockB');
+ blockB.addUniform(new glsUniformBlockCase.Uniform('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM)));
+ blockB.addUniform(new glsUniformBlockCase.Uniform('b', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC2, glsUniformBlockCase.UniformFlags.PRECISION_LOW)));
+ blockB.addUniform(new glsUniformBlockCase.Uniform('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), glsUniformBlockCase.UniformFlags.UNUSED_BOTH));
+ blockB.addUniform(new glsUniformBlockCase.Uniform('d', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.BOOL, 0)));
+ blockB.setInstanceName('blockB');
+ blockB.setFlags(this.m_flagsB);
+
+ if (this.m_numInstances > 0) {
+ blockA.setArraySize(this.m_numInstances);
+ blockB.setArraySize(this.m_numInstances);
+ }
+ };
+
+ /**
+ * es3fUniformBlockTests.BlockMultiNestedStructCase constructor
+ * @param {string} name The name of the test
+ * @param {string} description The description of the test
+ * @param {number} flagsA
+ * @param {number} flagsB
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} numInstances
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ es3fUniformBlockTests.BlockMultiNestedStructCase = function(name, description, flagsA, flagsB, bufferMode, numInstances) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_flagsA = flagsA;
+ this.m_flagsB = flagsB;
+ this.m_numInstances = numInstances;
+ };
+
+ es3fUniformBlockTests.BlockMultiNestedStructCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ es3fUniformBlockTests.BlockMultiNestedStructCase.prototype.constructor = es3fUniformBlockTests.BlockMultiNestedStructCase;
+
+ es3fUniformBlockTests.BlockMultiNestedStructCase.prototype.init = function() {
+ /**@type {glsUniformBlockCase.StructType}*/ var typeS = this.m_interface.allocStruct('S');
+ typeS.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT3, glsUniformBlockCase.UniformFlags.PRECISION_LOW));
+ typeS.addMember('b', glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.INT_VEC2, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM), 4));
+ typeS.addMember('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, glsUniformBlockCase.UniformFlags.PRECISION_HIGH));
+
+ /**@type {glsUniformBlockCase.StructType}*/ var typeT = this.m_interface.allocStruct('T');
+ typeT.addMember('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.UINT, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM), glsUniformBlockCase.UniformFlags.UNUSED_BOTH);
+ typeT.addMember('b', glsUniformBlockCase.newVarTypeStruct(typeS));
+ typeT.addMember('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.BOOL_VEC4, 0));
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var blockA = this.m_interface.allocBlock('BlockA');
+ blockA.addUniform(new glsUniformBlockCase.Uniform('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT, glsUniformBlockCase.UniformFlags.PRECISION_HIGH)));
+ blockA.addUniform(new glsUniformBlockCase.Uniform('b', glsUniformBlockCase.newVarTypeStruct(typeS)));
+ blockA.addUniform(new glsUniformBlockCase.Uniform('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.UINT_VEC3, glsUniformBlockCase.UniformFlags.PRECISION_LOW), glsUniformBlockCase.UniformFlags.UNUSED_BOTH));
+ blockA.setInstanceName('blockA');
+ blockA.setFlags(this.m_flagsA);
+
+ /** @type {glsUniformBlockCase.UniformBlock} */ var blockB = this.m_interface.allocBlock('BlockB');
+ blockB.addUniform(new glsUniformBlockCase.Uniform('a', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.FLOAT_MAT2, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM)));
+ blockB.addUniform(new glsUniformBlockCase.Uniform('b', glsUniformBlockCase.newVarTypeStruct(typeT)));
+ blockB.addUniform(new glsUniformBlockCase.Uniform('c', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.BOOL_VEC4, 0), glsUniformBlockCase.UniformFlags.UNUSED_BOTH));
+ blockB.addUniform(new glsUniformBlockCase.Uniform('d', glsUniformBlockCase.newVarTypeBasic(gluShaderUtil.DataType.BOOL, 0)));
+ blockB.setInstanceName('blockB');
+ blockB.setFlags(this.m_flagsB);
+
+ if (this.m_numInstances > 0) {
+ blockA.setArraySize(this.m_numInstances);
+ blockB.setArraySize(this.m_numInstances);
+ }
+ };
+
+ /**
+ * Creates the test hierarchy to be executed.
+ **/
+ es3fUniformBlockTests.init = function() {
+ /** @const @type {tcuTestCase.DeqpTest} */ var testGroup = tcuTestCase.runner.testCases;
+
+ /** @type {Array<gluShaderUtil.DataType>} */
+ var basicTypes = [
+ gluShaderUtil.DataType.FLOAT,
+ gluShaderUtil.DataType.FLOAT_VEC2,
+ gluShaderUtil.DataType.FLOAT_VEC3,
+ gluShaderUtil.DataType.FLOAT_VEC4,
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.INT_VEC2,
+ gluShaderUtil.DataType.INT_VEC3,
+ gluShaderUtil.DataType.INT_VEC4,
+ gluShaderUtil.DataType.UINT,
+ gluShaderUtil.DataType.UINT_VEC2,
+ gluShaderUtil.DataType.UINT_VEC3,
+ gluShaderUtil.DataType.UINT_VEC4,
+ gluShaderUtil.DataType.BOOL,
+ gluShaderUtil.DataType.BOOL_VEC2,
+ gluShaderUtil.DataType.BOOL_VEC3,
+ gluShaderUtil.DataType.BOOL_VEC4,
+ gluShaderUtil.DataType.FLOAT_MAT2,
+ gluShaderUtil.DataType.FLOAT_MAT3,
+ gluShaderUtil.DataType.FLOAT_MAT4,
+ gluShaderUtil.DataType.FLOAT_MAT2X3,
+ gluShaderUtil.DataType.FLOAT_MAT2X4,
+ gluShaderUtil.DataType.FLOAT_MAT3X2,
+ gluShaderUtil.DataType.FLOAT_MAT3X4,
+ gluShaderUtil.DataType.FLOAT_MAT4X2,
+ gluShaderUtil.DataType.FLOAT_MAT4X3
+ ];
+
+ /** @type {Array<Object.<string, glsUniformBlockCase.UniformFlags>>} */
+ var precisionFlags = [{ name: 'lowp', flags: glsUniformBlockCase.UniformFlags.PRECISION_LOW }, { name: 'mediump', flags: glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM }, { name: 'highp', flags: glsUniformBlockCase.UniformFlags.PRECISION_HIGH }
+ ];
+
+ /** @type {Array<Object.<string, glsUniformBlockCase.UniformFlags>>} */
+ var layoutFlags = [ /* { name: 'shared', flags: glsUniformBlockCase.UniformFlags.LAYOUT_SHARED }, */
+ /* { name: 'packed', flags: glsUniformBlockCase.UniformFlags.LAYOUT_PACKED }, */ { name: 'std140', flags: glsUniformBlockCase.UniformFlags.LAYOUT_STD140 }
+ ];
+
+ /** @type {Array<Object.<string, glsUniformBlockCase.UniformFlags>>} */
+ var matrixFlags = [{ name: 'row_major', flags: glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR }, { name: 'column_major', flags: glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR }
+ ];
+
+ /** @type {Array<Object.<string, glsUniformBlockCase.UniformFlags>>} */
+ var bufferModes = [{ name: 'per_block_buffer', mode: glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK }, { name: 'single_buffer', mode: glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE }
+ ];
+
+ // ubo.single_basic_type
+ /** @type {tcuTestCase.DeqpTest} */
+ var singleBasicTypeGroup = tcuTestCase.newTest('single_basic_type', 'Single basic variable in single buffer');
+
+ testGroup.addChild(singleBasicTypeGroup);
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var layoutGroup;
+ /** @type {gluShaderUtil.DataType} */
+ var type;
+ /** @type {string} */
+ var typeName;
+ /** @type {tcuTestCase.DeqpTest} */
+ var modeGroup;
+ /** @type {string} */
+ var baseName;
+ /** @type {number} */
+ var baseFlags;
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+
+ layoutGroup = tcuTestCase.newTest(layoutFlags[layoutFlagNdx].name, '', null);
+ singleBasicTypeGroup.addChild(layoutGroup);
+
+ for (var basicTypeNdx = 0; basicTypeNdx < basicTypes.length; basicTypeNdx++) {
+ type = basicTypes[basicTypeNdx];
+ typeName = gluShaderUtil.getDataTypeName(type);
+
+ if (gluShaderUtil.isDataTypeBoolOrBVec(type))
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, typeName, glsUniformBlockCase.newVarTypeBasic(type, 0), layoutFlags[layoutFlagNdx].flags);
+ else {
+ for (var precNdx = 0; precNdx < precisionFlags.length; precNdx++)
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, precisionFlags[precNdx].name + '_' + typeName,
+ glsUniformBlockCase.newVarTypeBasic(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags);
+ }
+
+ if (gluShaderUtil.isDataTypeMatrix(type)) {
+ for (var matFlagNdx = 0; matFlagNdx < matrixFlags.length; matFlagNdx++) {
+ for (var precNdx = 0; precNdx < precisionFlags.length; precNdx++)
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, matrixFlags[matFlagNdx].name + '_' + precisionFlags[precNdx].name + '_' + typeName,
+ glsUniformBlockCase.newVarTypeBasic(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
+ }
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.single_basic_type: Tests created');
+
+ // ubo.single_basic_array
+ /** @type {tcuTestCase.DeqpTest} */
+ var singleBasicArrayGroup = tcuTestCase.newTest('single_basic_array', 'Single basic array variable in single buffer');
+ testGroup.addChild(singleBasicArrayGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ layoutGroup = tcuTestCase.newTest(layoutFlags[layoutFlagNdx].name, '', null);
+ singleBasicArrayGroup.addChild(layoutGroup);
+
+ for (var basicTypeNdx = 0; basicTypeNdx < basicTypes.length; basicTypeNdx++) {
+ type = basicTypes[basicTypeNdx];
+ typeName = gluShaderUtil.getDataTypeName(type);
+ /** @type {number} */ var arraySize = 3;
+
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, typeName,
+ glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(type, gluShaderUtil.isDataTypeBoolOrBVec(type) ? 0 : glsUniformBlockCase.UniformFlags.PRECISION_HIGH), arraySize),
+ layoutFlags[layoutFlagNdx].flags);
+
+ if (gluShaderUtil.isDataTypeMatrix(type)) {
+ for (var matFlagNdx = 0; matFlagNdx < matrixFlags.length; matFlagNdx++)
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, matrixFlags[matFlagNdx].name + '_' + typeName,
+ glsUniformBlockCase.newVarTypeArray(glsUniformBlockCase.newVarTypeBasic(type, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), arraySize),
+ layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.single_basic_array: Tests created');
+
+ // ubo.single_struct
+ /** @type {tcuTestCase.DeqpTest} */
+ var singleStructGroup = tcuTestCase.newTest('single_struct', 'Single struct in uniform block');
+ testGroup.addChild(singleStructGroup);
+
+ for (var modeNdx = 0; modeNdx < bufferModes.length; modeNdx++) {
+ modeGroup = tcuTestCase.newTest(bufferModes[modeNdx].name, '');
+ singleStructGroup.addChild(modeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ for (var isArray = 0; isArray < 2; isArray++) {
+ baseName = layoutFlags[layoutFlagNdx].name;
+ baseFlags = layoutFlags[layoutFlagNdx].flags;
+
+ if (bufferModes[modeNdx].mode == glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE && isArray == 0)
+ continue; // Doesn't make sense to add this variant.
+
+ if (isArray)
+ baseName += '_instance_array';
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleStructCase(baseName + '_vertex', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleStructCase(baseName + '_fragment', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ if (!(baseFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleStructCase(baseName + '_both', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.single_struct: Tests created');
+
+ // ubo.single_struct_array
+ /** @type {tcuTestCase.DeqpTest} */
+ var singleStructArrayGroup = tcuTestCase.newTest('single_struct_array', 'Struct array in one uniform block');
+ testGroup.addChild(singleStructArrayGroup);
+
+ for (var modeNdx = 0; modeNdx < bufferModes.length; modeNdx++) {
+ modeGroup = tcuTestCase.newTest(bufferModes[modeNdx].name, '');
+ singleStructArrayGroup.addChild(modeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ for (var isArray = 0; isArray < 2; isArray++) {
+ baseName = layoutFlags[layoutFlagNdx].name;
+ baseFlags = layoutFlags[layoutFlagNdx].flags;
+
+ if (bufferModes[modeNdx].mode == glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE && isArray == 0)
+ continue; // Doesn't make sense to add this variant.
+
+ if (isArray)
+ baseName += '_instance_array';
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleStructArrayCase(baseName + '_vertex', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleStructArrayCase(baseName + '_fragment', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ if (!(baseFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleStructArrayCase(baseName + '_both', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.single_struct_array: Tests created');
+
+ // ubo.single_nested_struct
+ /** @type {tcuTestCase.DeqpTest} */
+ var singleNestedStructGroup = tcuTestCase.newTest('single_nested_struct', 'Nested struct in one uniform block');
+ testGroup.addChild(singleNestedStructGroup);
+
+ for (var modeNdx = 0; modeNdx < bufferModes.length; modeNdx++) {
+ modeGroup = tcuTestCase.newTest(bufferModes[modeNdx].name, '');
+ singleNestedStructGroup.addChild(modeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ for (var isArray = 0; isArray < 2; isArray++) {
+ baseName = layoutFlags[layoutFlagNdx].name;
+ baseFlags = layoutFlags[layoutFlagNdx].flags;
+
+ if (bufferModes[modeNdx].mode == glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE && isArray == 0)
+ continue; // Doesn't make sense to add this variant.
+
+ if (isArray)
+ baseName += '_instance_array';
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleNestedStructCase(baseName + '_vertex', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleNestedStructCase(baseName + '_fragment', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ if (!(baseFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleNestedStructCase(baseName + '_both', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.single_nested_struct: Tests created');
+
+ // ubo.single_nested_struct_array
+ /** @type {tcuTestCase.DeqpTest} */
+ var singleNestedStructArrayGroup = tcuTestCase.newTest('single_nested_struct_array', 'Nested struct array in one uniform block');
+ testGroup.addChild(singleNestedStructArrayGroup);
+
+ for (var modeNdx = 0; modeNdx < bufferModes.length; modeNdx++) {
+ modeGroup = tcuTestCase.newTest(bufferModes[modeNdx].name, '');
+ singleNestedStructArrayGroup.addChild(modeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ for (var isArray = 0; isArray < 2; isArray++) {
+ baseName = layoutFlags[layoutFlagNdx].name;
+ baseFlags = layoutFlags[layoutFlagNdx].flags;
+
+ if (bufferModes[modeNdx].mode == glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE && isArray == 0)
+ continue; // Doesn't make sense to add this variant.
+
+ if (isArray)
+ baseName += '_instance_array';
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleNestedStructArrayCase(baseName + '_vertex', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleNestedStructArrayCase(baseName + '_fragment', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ if (!(baseFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ modeGroup.addChild(new es3fUniformBlockTests.BlockSingleNestedStructArrayCase(baseName + '_both', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.single_nested_struct_array: Tests created');
+
+ // ubo.instance_array_basic_type
+ /** @type {tcuTestCase.DeqpTest} */
+ var instanceArrayBasicTypeGroup = tcuTestCase.newTest('instance_array_basic_type', 'Single basic variable in instance array');
+ testGroup.addChild(instanceArrayBasicTypeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ layoutGroup = tcuTestCase.newTest(layoutFlags[layoutFlagNdx].name, '');
+ instanceArrayBasicTypeGroup.addChild(layoutGroup);
+
+ for (var basicTypeNdx = 0; basicTypeNdx < basicTypes.length; basicTypeNdx++) {
+ type = basicTypes[basicTypeNdx];
+ typeName = gluShaderUtil.getDataTypeName(type);
+ /** @type {number} */ var numInstances = 3;
+
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, typeName,
+ glsUniformBlockCase.newVarTypeBasic(type, gluShaderUtil.isDataTypeBoolOrBVec(type) ? 0 : glsUniformBlockCase.UniformFlags.PRECISION_HIGH),
+ layoutFlags[layoutFlagNdx].flags, numInstances);
+
+ if (gluShaderUtil.isDataTypeMatrix(type)) {
+ for (var matFlagNdx = 0; matFlagNdx < matrixFlags.length; matFlagNdx++)
+ es3fUniformBlockTests.createBlockBasicTypeCases(layoutGroup, matrixFlags[matFlagNdx].name + '_' + typeName,
+ glsUniformBlockCase.newVarTypeBasic(type, glsUniformBlockCase.UniformFlags.PRECISION_HIGH), layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags,
+ numInstances);
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.instance_array_basic_type: Tests created');
+
+ // ubo.multi_basic_types
+ /** @type {tcuTestCase.DeqpTest} */
+ var multiBasicTypesGroup = tcuTestCase.newTest('multi_basic_types', 'Multiple buffers with basic types');
+ testGroup.addChild(multiBasicTypesGroup);
+
+ for (var modeNdx = 0; modeNdx < bufferModes.length; modeNdx++) {
+ modeGroup = tcuTestCase.newTest(bufferModes[modeNdx].name, '');
+ multiBasicTypesGroup.addChild(modeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ for (var isArray = 0; isArray < 2; isArray++) {
+ baseName = layoutFlags[layoutFlagNdx].name;
+ baseFlags = layoutFlags[layoutFlagNdx].flags;
+
+ if (isArray)
+ baseName += '_instance_array';
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiBasicTypesCase(baseName + '_vertex', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiBasicTypesCase(baseName + '_fragment', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ if (!(baseFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiBasicTypesCase(baseName + '_both', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiBasicTypesCase(baseName + '_mixed', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.multi_basic_types: Tests created');
+
+ // ubo.multi_nested_struct
+ /** @type {tcuTestCase.DeqpTest} */
+ var multiNestedStructGroup = tcuTestCase.newTest('multi_nested_struct', 'Multiple buffers with basic types');
+ testGroup.addChild(multiNestedStructGroup);
+
+ for (var modeNdx = 0; modeNdx < bufferModes.length; modeNdx++) {
+ modeGroup = tcuTestCase.newTest(bufferModes[modeNdx].name, '');
+ multiNestedStructGroup.addChild(modeGroup);
+
+ for (var layoutFlagNdx = 0; layoutFlagNdx < layoutFlags.length; layoutFlagNdx++) {
+ for (var isArray = 0; isArray < 2; isArray++) {
+ baseName = layoutFlags[layoutFlagNdx].name;
+ baseFlags = layoutFlags[layoutFlagNdx].flags;
+
+ if (isArray)
+ baseName += '_instance_array';
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiNestedStructCase(baseName + '_vertex', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiNestedStructCase(baseName + '_fragment', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ if (!(baseFlags & glsUniformBlockCase.UniformFlags.LAYOUT_PACKED))
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiNestedStructCase(baseName + '_both', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+
+ modeGroup.addChild(new es3fUniformBlockTests.BlockMultiNestedStructCase(baseName + '_mixed', '', baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_VERTEX, baseFlags | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
+ }
+ }
+ }
+ bufferedLogToConsole('ubo.multi_nested_struct: Tests created');
+
+ /* ubo.random */
+ /** @type {number} */ var allShaders = glsRandomUniformBlockCase.FeatureBits.FEATURE_VERTEX_BLOCKS | glsRandomUniformBlockCase.FeatureBits.FEATURE_FRAGMENT_BLOCKS | glsRandomUniformBlockCase.FeatureBits.FEATURE_SHARED_BLOCKS;
+ /** @type {number} */ var allLayouts = glsRandomUniformBlockCase.FeatureBits.FEATURE_STD140_LAYOUT;
+ /** @type {number} */ var allBasicTypes = glsRandomUniformBlockCase.FeatureBits.FEATURE_VECTORS | glsRandomUniformBlockCase.FeatureBits.FEATURE_MATRICES;
+ /** @type {number} */ var unused = glsRandomUniformBlockCase.FeatureBits.FEATURE_UNUSED_MEMBERS | glsRandomUniformBlockCase.FeatureBits.FEATURE_UNUSED_UNIFORMS;
+ /** @type {number} */ var matFlags = glsRandomUniformBlockCase.FeatureBits.FEATURE_MATRIX_LAYOUT;
+ /** @type {number} */ var allFeatures = (~glsRandomUniformBlockCase.FeatureBits.FEATURE_ARRAYS_OF_ARRAYS & 0xFFFF);
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var randomGroup = tcuTestCase.newTest('random', 'Random Uniform Block cases');
+ testGroup.addChild(randomGroup);
+
+ // Basic types.
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'scalar_types', 'Scalar types only, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused, 25, 0);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'vector_types', 'Scalar and vector types only, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | glsRandomUniformBlockCase.FeatureBits.FEATURE_VECTORS, 25, 25);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'basic_types', 'All basic types, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags, 25, 50);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'basic_arrays', 'Arrays, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags | glsRandomUniformBlockCase.FeatureBits.FEATURE_ARRAYS, 25, 50);
+
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'basic_instance_arrays', 'Basic instance arrays, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags | glsRandomUniformBlockCase.FeatureBits.FEATURE_INSTANCE_ARRAYS, 25, 75);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'nested_structs', 'Nested structs, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags | glsRandomUniformBlockCase.FeatureBits.FEATURE_STRUCTS, 25, 100);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'nested_structs_arrays', 'Nested structs, arrays, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags | glsRandomUniformBlockCase.FeatureBits.FEATURE_STRUCTS | glsRandomUniformBlockCase.FeatureBits.FEATURE_ARRAYS, 25, 150);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'nested_structs_instance_arrays', 'Nested structs, instance arrays, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags | glsRandomUniformBlockCase.FeatureBits.FEATURE_STRUCTS | glsRandomUniformBlockCase.FeatureBits.FEATURE_INSTANCE_ARRAYS, 25, 125);
+ es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'nested_structs_arrays_instance_arrays', 'Nested structs, instance arrays, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused | allBasicTypes | matFlags | glsRandomUniformBlockCase.FeatureBits.FEATURE_STRUCTS | glsRandomUniformBlockCase.FeatureBits.FEATURE_ARRAYS | glsRandomUniformBlockCase.FeatureBits.FEATURE_INSTANCE_ARRAYS, 25, 175);
+
+ // Disabled: WebGL does not support shared or packed uniform buffers.
+ //es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'all_per_block_buffers', 'All random features, per-block buffers', glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK, allFeatures, 50, 200);
+ //es3fUniformBlockTests.createRandomCaseGroup(randomGroup, 'all_shared_buffer', 'All random features, shared buffer', glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE, allFeatures, 50, 250);
+ bufferedLogToConsole('ubo.random: Tests created');
+ };
+
+ /**
+ * Create and execute the test cases
+ */
+ es3fUniformBlockTests.run = function(range) {
+ //Set up Test Root parameters
+ var testName = 'ubo';
+ var testDescription = 'Uniform Block Tests';
+ var state = tcuTestCase.runner;
+
+ state.setRoot(tcuTestCase.newTest(testName, testDescription, null));
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ //Create test cases
+ es3fUniformBlockTests.init();
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fUniformBlockTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayObjectTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayObjectTests.js
new file mode 100644
index 0000000000..6ee46995ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayObjectTests.js
@@ -0,0 +1,875 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fVertexArrayObjectTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+var es3fVertexArrayObjectTests = functional.gles3.es3fVertexArrayObjectTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var deRandom = framework.delibs.debase.deRandom;
+var deString = framework.delibs.debase.deString;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuSurface = framework.common.tcuSurface;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var deUtil = framework.delibs.debase.deUtil;
+
+/**
+ * @constructor
+ */
+es3fVertexArrayObjectTests.Attribute = function() {
+ this.enabled = false;
+ this.size = 1;
+ this.stride = 0;
+ this.type = gl.FLOAT;
+ this.integer = false;
+ this.divisor = 0;
+ this.offset = 0;
+ this.normalized = false;
+ this.bufferNdx = 0;
+};
+
+/**
+ * @constructor
+ * @struct
+ */
+es3fVertexArrayObjectTests.VertexArrayState = function() {
+ this.attributes = [];
+ this.elementArrayBuffer = 0;
+};
+
+/**
+ * @constructor
+ * @struct
+ */
+es3fVertexArrayObjectTests.BufferSpec = function(count, size, componentCount, stride, offset, type, intRangeMin, intRangeMax, floatRangeMin, floatRangeMax) {
+ this.count = count;
+ this.size = size;
+ this.componentCount = componentCount;
+ this.stride = stride;
+ this.offset = offset;
+
+ this.type = type;
+
+ this.intRangeMin = intRangeMin;
+ this.intRangeMax = intRangeMax;
+
+ this.floatRangeMin = floatRangeMin;
+ this.floatRangeMax = floatRangeMax;
+};
+
+/**
+ * @constructor
+ */
+es3fVertexArrayObjectTests.Spec = function() {
+ this.count = -1;
+ this.instances = -1;
+ this.useDrawElements = false;
+ this.indexType = gl.NONE;
+ this.indexOffset = -1;
+ this.indexRangeMin = -1;
+ this.indexRangeMax = -1;
+ this.indexCount = -1;
+ this.buffers = [];
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {es3fVertexArrayObjectTests.Spec} spec
+ * @param {string} name
+ * @param {string} description
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest = function(spec, name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_spec = spec;
+ this.m_random = new deRandom.Random(deString.deStringHash(name));
+ /** @type Array<WebGLBuffer>} */ this.m_buffers = [];
+ // mapping 0 -> null object
+ this.m_buffers.push(null);
+};
+
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.constructor = es3fVertexArrayObjectTests.VertexArrayObjectTest;
+
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.init = function() {
+ this.m_vaoProgram = this.createProgram(this.m_spec.vao);
+ // m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
+ // m_log << *m_vaoProgram;
+ this.m_stateProgram = this.createProgram(this.m_spec.state);
+ // m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
+ // m_log << *m_stateProgram;
+
+ if (!this.m_vaoProgram.isOk() || !this.m_stateProgram.isOk())
+ testFailedOptions('Failed to compile shaders', true);
+};
+
+/**
+ * @param {number} target GL target
+ * @param {number} index Index of the buffer to bind
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.bindBuffer = function(target, index) {
+ if (typeof this.m_buffers[index] === 'undefined') {
+ var data = this.createRandomBufferData(this.m_spec.buffers[index - 1]);
+ var buffer = gl.createBuffer();
+ this.m_buffers[index] = buffer;
+
+ gl.bindBuffer(target, buffer);
+ gl.bufferData(target, data, gl.DYNAMIC_DRAW);
+ gl.bindBuffer(target, null);
+ }
+
+ gl.bindBuffer(target, this.m_buffers[index]);
+};
+
+/**
+ * @param {es3fVertexArrayObjectTests.BufferSpec} buffer
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.createRandomBufferData = function(buffer) {
+ var typedArray;
+ switch (buffer.type) {
+ case gl.FLOAT: typedArray = Float32Array; break;
+ case gl.INT: typedArray = Int32Array; break;
+ case gl.UNSIGNED_INT: typedArray = Uint32Array; break;
+ case gl.SHORT: typedArray = Int16Array; break;
+ case gl.UNSIGNED_SHORT: typedArray = Uint16Array; break;
+ case gl.BYTE: typedArray = Int8Array; break;
+ case gl.UNSIGNED_BYTE: typedArray = Uint8Array; break;
+ default:
+ throw new Error('Invalid type: ' + buffer.type);
+ }
+
+ var raw = new ArrayBuffer(buffer.size);
+ var stride;
+
+ if (buffer.stride != 0) {
+ stride = buffer.stride;
+ } else {
+ switch (buffer.type) {
+ case gl.FLOAT: stride = buffer.componentCount * 4; break;
+ case gl.INT: stride = buffer.componentCount * 4; break;
+ case gl.UNSIGNED_INT: stride = buffer.componentCount * 4; break;
+ case gl.SHORT: stride = buffer.componentCount * 2; break;
+ case gl.UNSIGNED_SHORT: stride = buffer.componentCount * 2; break;
+ case gl.BYTE: stride = buffer.componentCount * 1; break;
+ case gl.UNSIGNED_BYTE: stride = buffer.componentCount * 1; break;
+ }
+ }
+
+ var offset = 0;
+
+ for (var pos = 0; pos < buffer.count; pos++) {
+ var data = new typedArray(raw, offset, buffer.componentCount);
+ for (var componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++) {
+ switch (buffer.type) {
+ case gl.FLOAT: {
+ data[componentNdx] = this.m_random.getFloat(buffer.floatRangeMin, buffer.floatRangeMax);
+ break;
+ }
+ default: {
+ data[componentNdx] = this.m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
+ }
+ }
+ }
+
+ offset += stride;
+ }
+
+ return new typedArray(raw);
+};
+
+/**
+ * @param {es3fVertexArrayObjectTests.VertexArrayState} state
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.createProgram = function(state) {
+ var vtx = '';
+ var value = '';
+
+ vtx += '#version 300 es\n';
+
+ for (var attribNdx = 0; attribNdx < state.attributes.length; attribNdx++) {
+ if (state.attributes[attribNdx].integer)
+ vtx += 'layout(location = ' + attribNdx + ') in mediump ivec4 a_attrib' + attribNdx + ';\n';
+ else
+ vtx += 'layout(location = ' + attribNdx + ') in mediump vec4 a_attrib' + attribNdx + ';\n';
+
+ if (state.attributes[attribNdx].integer) {
+ var scale = 0.0;
+
+ // TODO: Should it be state.attributes[attribNdx].type?
+ switch (state.attributes[attribNdx].type) {
+ case gl.SHORT: scale = (1.0 / ((1 << 14) - 1)); break;
+ case gl.UNSIGNED_SHORT: scale = (1.0 / ((1 << 15) - 1)); break;
+ case gl.INT: scale = (1.0 / ((1 << 30) - 1)); break;
+ case gl.UNSIGNED_INT: scale = (1.0 / ((1 << 31) - 1)); break;
+ case gl.BYTE: scale = (1.0 / ((1 << 6) - 1)); break;
+ case gl.UNSIGNED_BYTE: scale = (1.0 / ((1 << 7) - 1)); break;
+
+ default:
+ throw new Error('Invalid type: ' + state.attributes[0].type);
+ }
+ value += (attribNdx != 0 ? ' + ' : '') + scale + ' * vec4(a_attrib' + attribNdx + ')';
+ } else if (state.attributes[attribNdx].type != gl.FLOAT && !state.attributes[attribNdx].normalized) {
+ var scale = 0.0;
+
+ switch (state.attributes[attribNdx].type) {
+ case gl.SHORT: scale = (0.5 / ((1 << 14) - 1)); break;
+ case gl.UNSIGNED_SHORT: scale = (0.5 / ((1 << 15) - 1)); break;
+ case gl.INT: scale = (0.5 / ((1 << 30) - 1)); break;
+ case gl.UNSIGNED_INT: scale = (0.5 / ((1 << 31) - 1)); break;
+ case gl.BYTE: scale = (0.5 / ((1 << 6) - 1)); break;
+ case gl.UNSIGNED_BYTE: scale = (0.5 / ((1 << 7) - 1)); break;
+
+ default:
+ throw new Error('Invalid type: ' + state.attributes[0].type);
+ }
+ value += (attribNdx != 0 ? ' + ' : '') + scale + ' * a_attrib' + attribNdx;
+ } else
+ value += (attribNdx != 0 ? ' + ' : '') + 'a_attrib' + attribNdx;
+ }
+
+ vtx +=
+ 'out mediump vec4 v_value;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ '\tv_value = ' + value + ';\n';
+
+ if (state.attributes[0].integer) {
+ var scale = 0.0;
+
+ switch (state.attributes[0].type) {
+ case gl.SHORT: scale = (1.0 / ((1 << 14) - 1)); break;
+ case gl.UNSIGNED_SHORT: scale = (1.0 / ((1 << 15) - 1)); break;
+ case gl.INT: scale = (1.0 / ((1 << 30) - 1)); break;
+ case gl.UNSIGNED_INT: scale = (1.0 / ((1 << 31) - 1)); break;
+ case gl.BYTE: scale = (1.0 / ((1 << 6) - 1)); break;
+ case gl.UNSIGNED_BYTE: scale = (1.0 / ((1 << 7) - 1)); break;
+
+ default:
+ throw new Error('Invalid type: ' + state.attributes[0].type);
+ }
+
+ vtx +=
+ '\tgl_Position = vec4(' + scale + ' * ' + 'vec3(a_attrib0.xyz), 1.0);\n' +
+ '}';
+ } else {
+ if (state.attributes[0].normalized || state.attributes[0].type == gl.FLOAT) {
+ vtx +=
+ '\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n' +
+ '}';
+ } else {
+ var scale = 0.0;
+
+ switch (state.attributes[0].type) {
+ case gl.SHORT: scale = (1.0 / ((1 << 14) - 1)); break;
+ case gl.UNSIGNED_SHORT: scale = (1.0 / ((1 << 15) - 1)); break;
+ case gl.INT: scale = (1.0 / ((1 << 30) - 1)); break;
+ case gl.UNSIGNED_INT: scale = (1.0 / ((1 << 31) - 1)); break;
+ case gl.BYTE: scale = (1.0 / ((1 << 6) - 1)); break;
+ case gl.UNSIGNED_BYTE: scale = (1.0 / ((1 << 7) - 1)); break;
+
+ default:
+ throw new Error('Invalid type: ' + state.attributes[0].type);
+ }
+
+ scale *= 0.5;
+
+ vtx +=
+ '\tgl_Position = vec4(' + scale + ' * ' + 'a_attrib0.xyz, 1.0);\n' +
+ '}';
+ }
+ }
+
+ var fragmentShader =
+ '#version 300 es\n' +
+ 'in mediump vec4 v_value;\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ '\tfragColor = vec4(v_value.xyz, 1.0);\n' +
+ '}';
+
+ return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, fragmentShader));
+};
+
+/**
+ * @param {es3fVertexArrayObjectTests.VertexArrayState} state
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.setState = function(state) {
+ this.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, state.elementArrayBuffer);
+
+ for (var attribNdx = 0; attribNdx < state.attributes.length; attribNdx++) {
+ this.bindBuffer(gl.ARRAY_BUFFER, state.attributes[attribNdx].bufferNdx);
+ if (state.attributes[attribNdx].enabled)
+ gl.enableVertexAttribArray(attribNdx);
+ else
+ gl.disableVertexAttribArray(attribNdx);
+
+ if (state.attributes[attribNdx].integer)
+ gl.vertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, state.attributes[attribNdx].offset);
+ else
+ gl.vertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, state.attributes[attribNdx].offset);
+
+ gl.vertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor);
+ }
+};
+
+/**
+ * @param {es3fVertexArrayObjectTests.VertexArrayState} state
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.makeDrawCall = function(state) {
+ gl.clearColor(0.7, 0.7, 0.7, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var spec = this.m_spec;
+
+ if (spec.useDrawElements) {
+ if (spec.instances == 0)
+ gl.drawElements(gl.TRIANGLES, spec.count, spec.indexType, spec.indexOffset);
+ else
+ gl.drawElementsInstanced(gl.TRIANGLES, spec.count, spec.indexType, spec.indexOffset, spec.instances);
+ } else {
+ if (spec.instances == 0)
+ gl.drawArrays(gl.TRIANGLES, 0, spec.count);
+ else
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, spec.count, spec.instances);
+ }
+};
+
+/**
+ * @param {tcuSurface.Surface} vaoResult
+ * @param {tcuSurface.Surface} defaultResult
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.render = function(vaoResult, defaultResult) {
+ var vao = gl.createVertexArray();
+
+ gl.bindVertexArray(vao);
+ this.setState(this.m_spec.vao);
+ gl.bindVertexArray(null);
+
+ this.setState(this.m_spec.state);
+
+ gl.bindVertexArray(vao);
+ gl.useProgram(this.m_vaoProgram.getProgram());
+ this.makeDrawCall(this.m_spec.vao);
+ vaoResult.readViewport();
+ this.setState(this.m_spec.vao);
+ gl.bindVertexArray(null);
+
+ gl.useProgram(this.m_stateProgram.getProgram());
+ this.makeDrawCall(this.m_spec.state);
+ defaultResult.readViewport();
+
+ gl.deleteVertexArray(vao);
+};
+
+/**
+ * @param {tcuSurface.Surface} vaoRef
+ * @param {tcuSurface.Surface} defaultRef
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.genReferences = function(vaoRef, defaultRef) {
+ this.setState(this.m_spec.vao);
+ gl.useProgram(this.m_vaoProgram.getProgram());
+ this.makeDrawCall(this.m_spec.vao);
+ vaoRef.readViewport();
+
+ this.setState(this.m_spec.state);
+ gl.useProgram(this.m_stateProgram.getProgram());
+ this.makeDrawCall(this.m_spec.state);
+ defaultRef.readViewport();
+};
+
+es3fVertexArrayObjectTests.VertexArrayObjectTest.prototype.iterate = function() {
+ var vaoReference = new tcuSurface.Surface();
+ var stateReference = new tcuSurface.Surface();
+ var vaoResult = new tcuSurface.Surface();
+ var stateResult = new tcuSurface.Surface();
+
+ var isOk;
+
+ // logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
+ // logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
+ this.genReferences(stateReference, vaoReference);
+ this.render(stateResult, vaoResult);
+
+ isOk = tcuImageCompare.pixelThresholdCompare('Results', 'Comparison result from rendering with Vertex Array State', stateReference, stateResult, [0, 0, 0, 0]);
+ isOk = isOk && tcuImageCompare.pixelThresholdCompare('Results', 'Comparison result from rendering with Vertex Array Object', vaoReference, vaoResult, [0, 0, 0, 0]);
+
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fVertexArrayObjectTests.VertexArrayObjectTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'vertex_array_objects', 'Vertex array object test cases');
+};
+
+es3fVertexArrayObjectTests.VertexArrayObjectTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fVertexArrayObjectTests.VertexArrayObjectTests.prototype.constructor = es3fVertexArrayObjectTests.VertexArrayObjectTests;
+
+es3fVertexArrayObjectTests.VertexArrayObjectTests.prototype.init = function() {
+ var floatCoordBuffer48_1 = new es3fVertexArrayObjectTests.BufferSpec(48, 384, 2, 0, 0, gl.FLOAT, 0, 0, -1.0, 1.0);
+ var floatCoordBuffer48_2 = new es3fVertexArrayObjectTests.BufferSpec(48, 384, 2, 0, 0, gl.FLOAT, 0, 0, -1.0, 1.0);
+
+ var shortCoordBuffer48 = new es3fVertexArrayObjectTests.BufferSpec(48, 192, 2, 0, 0, gl.SHORT, -32768, 32768, 0.0, 0.0);
+
+ var spec;
+ var state;
+ // Different buffer
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.FLOAT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = false;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(floatCoordBuffer48_1);
+ spec.buffers.push(floatCoordBuffer48_2);
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 48;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.state.attributes[0].bufferNdx = 1;
+ spec.vao.attributes[0].bufferNdx = 2;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_buffer', 'diff_buffer'));
+
+ // Different size
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.FLOAT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = false;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(floatCoordBuffer48_1);
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.state.attributes[0].size = 2;
+ spec.vao.attributes[0].size = 3;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_size', 'diff_size'));
+
+ // Different stride
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.SHORT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = true;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(shortCoordBuffer48);
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.vao.attributes[0].stride = 2;
+ spec.state.attributes[0].stride = 4;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_stride', 'diff_stride'));
+
+ // Different types
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.SHORT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = true;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(shortCoordBuffer48);
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.vao.attributes[0].type = gl.SHORT;
+ spec.state.attributes[0].type = gl.BYTE;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_type', 'diff_type'));
+
+ // Different "integer"
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.BYTE;
+ state.attributes[0].integer = true;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = false;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(shortCoordBuffer48);
+
+ spec.useDrawElements = false;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.instances = 0;
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.state.attributes[0].integer = false;
+ spec.vao.attributes[0].integer = true;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_integer', 'diff_integer'));
+
+ // Different divisor
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.SHORT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = true;
+ state.attributes[0].bufferNdx = 1;
+
+ state.attributes[1].enabled = true;
+ state.attributes[1].size = 4;
+ state.attributes[1].stride = 0;
+ state.attributes[1].type = gl.FLOAT;
+ state.attributes[1].integer = false;
+ state.attributes[1].divisor = 0;
+ state.attributes[1].offset = 0;
+ state.attributes[1].normalized = false;
+ state.attributes[1].bufferNdx = 2;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(shortCoordBuffer48);
+ spec.buffers.push(floatCoordBuffer48_1);
+
+ spec.useDrawElements = false;
+ spec.instances = 10;
+ spec.count = 12;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.vao.attributes[1].divisor = 3;
+ spec.state.attributes[1].divisor = 2;
+
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_divisor', 'diff_divisor'));
+
+ // Different offset
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.SHORT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = true;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(shortCoordBuffer48);
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.vao.attributes[0].offset = 2;
+ spec.state.attributes[0].offset = 4;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_offset', 'diff_offset'));
+
+ // Different normalize
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.SHORT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = true;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(shortCoordBuffer48);
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 48;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+
+ spec.vao.attributes[0].normalized = true;
+ spec.state.attributes[0].normalized = false;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_normalize', 'diff_normalize'));
+
+ // DrawElements with buffer
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+
+ state.attributes[0].enabled = true;
+ state.attributes[0].size = 2;
+ state.attributes[0].stride = 0;
+ state.attributes[0].type = gl.FLOAT;
+ state.attributes[0].integer = false;
+ state.attributes[0].divisor = 0;
+ state.attributes[0].offset = 0;
+ state.attributes[0].normalized = true;
+ state.attributes[0].bufferNdx = 1;
+
+ state.elementArrayBuffer = 0;
+
+ spec.buffers.push(floatCoordBuffer48_1);
+
+ var indexBuffer = new es3fVertexArrayObjectTests.BufferSpec(24, 192, 1, 0, 0, gl.UNSIGNED_SHORT, 0, 47, 0.0, 0.0);
+ spec.buffers.push(indexBuffer);
+ spec.buffers.push(indexBuffer);
+
+ spec.useDrawElements = true;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.instances = 0;
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 48;
+ spec.indexType = gl.UNSIGNED_SHORT;
+ spec.indexCount = 24;
+
+ spec.state.elementArrayBuffer = 3;
+ spec.vao.elementArrayBuffer = 2;
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'diff_indices', 'diff_indices'));
+
+ var attribCount = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ var random = new deRandom.Random(attribCount);
+ spec = new es3fVertexArrayObjectTests.Spec();
+
+ state = new es3fVertexArrayObjectTests.VertexArrayState();
+
+ spec.useDrawElements = false;
+ spec.instances = 0;
+ spec.count = 24;
+ spec.vao = state;
+ spec.state = deUtil.clone(state);
+ spec.indexOffset = 0;
+ spec.indexRangeMin = 0;
+ spec.indexRangeMax = 0;
+ spec.indexType = gl.NONE;
+ spec.indexCount = 0;
+ spec.vao.elementArrayBuffer = 0;
+ spec.state.elementArrayBuffer = 0;
+
+ // Use all attributes
+ for (var attribNdx = 0; attribNdx < attribCount; attribNdx++) {
+ spec.buffers.push(shortCoordBuffer48);
+
+ spec.state.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+ spec.state.attributes[attribNdx].enabled = (random.getInt(0, 4) == 0) ? false : true;
+ spec.state.attributes[attribNdx].size = random.getInt(2, 4);
+ spec.state.attributes[attribNdx].stride = 2 * random.getInt(1, 3);
+ spec.state.attributes[attribNdx].type = gl.SHORT;
+ spec.state.attributes[attribNdx].integer = random.getBool();
+ spec.state.attributes[attribNdx].divisor = random.getInt(0, 1);
+ spec.state.attributes[attribNdx].offset = 2 * random.getInt(0, 2);
+ spec.state.attributes[attribNdx].normalized = random.getBool();
+ spec.state.attributes[attribNdx].bufferNdx = attribNdx + 1;
+
+ if (attribNdx == 0) {
+ spec.state.attributes[attribNdx].divisor = 0;
+ spec.state.attributes[attribNdx].enabled = true;
+ spec.state.attributes[attribNdx].size = 2;
+ }
+
+ spec.vao.attributes.push(new es3fVertexArrayObjectTests.Attribute());
+ spec.vao.attributes[attribNdx].enabled = (random.getInt(0, 4) == 0) ? false : true;
+ spec.vao.attributes[attribNdx].size = random.getInt(2, 4);
+ spec.vao.attributes[attribNdx].stride = 2 * random.getInt(1, 3);
+ spec.vao.attributes[attribNdx].type = gl.SHORT;
+ spec.vao.attributes[attribNdx].integer = random.getBool();
+ spec.vao.attributes[attribNdx].divisor = random.getInt(0, 1);
+ spec.vao.attributes[attribNdx].offset = 2 * random.getInt(0, 2);
+ spec.vao.attributes[attribNdx].normalized = random.getBool();
+ spec.vao.attributes[attribNdx].bufferNdx = attribCount - attribNdx;
+
+ if (attribNdx == 0) {
+ spec.vao.attributes[attribNdx].divisor = 0;
+ spec.vao.attributes[attribNdx].enabled = true;
+ spec.vao.attributes[attribNdx].size = 2;
+ }
+
+ }
+ this.addChild(new es3fVertexArrayObjectTests.VertexArrayObjectTest(spec, 'all_attributes', 'all_attributes'));
+
+};
+
+/**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+es3fVertexArrayObjectTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fVertexArrayObjectTests.VertexArrayObjectTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fVertexArrayObjectTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayTests.js
new file mode 100644
index 0000000000..ccfd343313
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fVertexArrayTests.js
@@ -0,0 +1,1103 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fVertexArrayTests');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluVarType');
+goog.require('modules.shared.glsVertexArrayTests');
+
+goog.scope(function() {
+
+ var es3fVertexArrayTests = functional.gles3.es3fVertexArrayTests;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluVarType = framework.opengl.gluVarType;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTexture = framework.common.tcuTexture;
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deUtil = framework.delibs.debase.deUtil;
+ var glsVertexArrayTests = modules.shared.glsVertexArrayTests;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * es3fVertexArrayTests.SingleVertexArrayUsageGroup
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsVertexArrayTests.deArray.Usage} usage
+ */
+ es3fVertexArrayTests.SingleVertexArrayUsageGroup = function(usage) {
+ tcuTestCase.DeqpTest.call(
+ this,
+ "single_attribute.usages." + glsVertexArrayTests.deArray.usageTypeToString(usage),
+ glsVertexArrayTests.deArray.usageTypeToString(usage)
+ );
+ this.makeExecutable();
+ this.m_usage = usage;
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayUsageGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayUsageGroup.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayUsageGroup;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayUsageGroup.prototype.init = function() {
+ /** @type {Array<number>} */ var counts = [1, 256];
+ /** @type {Array<number>} */ var strides = [0, -1, 17, 32]; // Treat negative value as sizeof input. Same as 0, but done outside of GL.
+ /** @type {Array<glsVertexArrayTests.deArray.InputType>} */ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ /*glsVertexArrayTests.deArray.InputType.FIXED,*/
+ glsVertexArrayTests.deArray.InputType.SHORT,
+ glsVertexArrayTests.deArray.InputType.BYTE
+ ];
+
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++) {
+ for (var countNdx = 0; countNdx < counts.length; countNdx++) {
+ for (var strideNdx = 0; strideNdx < strides.length; strideNdx++) {
+ /** @type {number} */ var stride = (strides[strideNdx] < 0 ? glsVertexArrayTests.deArray.inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
+ /** @type {boolean} */ var aligned = (stride % glsVertexArrayTests.deArray.inputTypeSize(inputTypes[inputTypeNdx])) == 0;
+ /** @type {string} */ var name = 'stride' + stride + '_' + glsVertexArrayTests.deArray.inputTypeToString(inputTypes[inputTypeNdx]) + '_quads' + counts[countNdx];
+
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ inputTypes[inputTypeNdx],
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.Storage.BUFFER,
+ this.m_usage,
+ 2,
+ 0,
+ stride,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(inputTypes[inputTypeNdx]),
+ glsVertexArrayTests.GLValue.getMaxValue(inputTypes[inputTypeNdx])
+ );
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = counts[countNdx];
+ spec.first = 0;
+ spec.arrays.push(arraySpec);
+
+ if (aligned)
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, name
+ )
+ );
+ }
+ }
+ }
+ };
+
+ /**
+ * es3fVertexArrayTests.SingleVertexArrayStrideGroup
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ es3fVertexArrayTests.SingleVertexArrayStrideGroup = function(type) {
+ tcuTestCase.DeqpTest.call(this, glsVertexArrayTests.deArray.inputTypeToString(type), glsVertexArrayTests.deArray.inputTypeToString(type));
+ this.makeExecutable();
+ this.m_type = type;
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayStrideGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayStrideGroup.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayStrideGroup;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayStrideGroup.prototype.init = function() {
+ /** @type {Array<glsVertexArrayTests.deArray.Storage>} */ var storages = [
+ // User storage not supported in WebGL - glsVertexArrayTests.deArray.Storage.USER,
+ glsVertexArrayTests.deArray.Storage.BUFFER
+ ];
+ var counts = [1, 256];
+ var strides = [/*0,*/ -1, 17, 32]; // Treat negative value as sizeof input. Same as 0, but done outside of GL.
+
+ for (var storageNdx = 0; storageNdx < storages.length; storageNdx++) {
+ for (var componentCount = 2; componentCount < 5; componentCount++) {
+ for (var countNdx = 0; countNdx < counts.length; countNdx++) {
+ for (var strideNdx = 0; strideNdx < strides.length; strideNdx++) {
+ /** @type {boolean} */ var packed = this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 || this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
+ /** @type {number} */ var stride = (strides[strideNdx] < 0) ? ((packed) ? (16) : (glsVertexArrayTests.deArray.inputTypeSize(this.m_type) * componentCount)) : (strides[strideNdx]);
+ /** @type {number} */ var alignment = (packed) ? (glsVertexArrayTests.deArray.inputTypeSize(this.m_type) * componentCount) : (glsVertexArrayTests.deArray.inputTypeSize(this.m_type));
+ /** @type {boolean} */ var bufferUnaligned = (storages[storageNdx] == glsVertexArrayTests.deArray.Storage.BUFFER) && (stride % alignment) != 0;
+
+ /** @type {string} */ var name = glsVertexArrayTests.deArray.storageToString(storages[storageNdx]) + '_stride' + stride + '_components' + componentCount + '_quads' + counts[countNdx];
+
+ if ((this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10) && componentCount != 4)
+ continue;
+
+ /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ this.m_type,
+ glsVertexArrayTests.deArray.OutputType.VEC4,
+ storages[storageNdx],
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ componentCount,
+ 0,
+ stride,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(this.m_type),
+ glsVertexArrayTests.GLValue.getMaxValue(this.m_type)
+ );
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = counts[countNdx];
+ spec.first = 0;
+ spec.arrays.push(arraySpec);
+
+ if (!bufferUnaligned)
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, name
+ )
+ );
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * es3fVertexArrayTests.SingleVertexArrayStrideTests
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.SingleVertexArrayStrideTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'single_attribute.strides', 'Single stride vertex atribute');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayStrideTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayStrideTests.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayStrideTests;
+
+ es3fVertexArrayTests.SingleVertexArrayStrideTests.prototype.init = function() {
+ /** @type {Array<glsVertexArrayTests.deArray.InputType>} */ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.InputType.SHORT,
+ glsVertexArrayTests.deArray.InputType.BYTE,
+ /*glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE,
+ glsVertexArrayTests.deArray.InputType.FIXED,*/
+ glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++)
+ this.addChild(
+ new es3fVertexArrayTests.SingleVertexArrayStrideGroup(
+ inputTypes[inputTypeNdx]
+ )
+ );
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ es3fVertexArrayTests.SingleVertexArrayFirstGroup = function(type) {
+ tcuTestCase.DeqpTest.call(
+ this,
+ glsVertexArrayTests.deArray.inputTypeToString(type),
+ glsVertexArrayTests.deArray.inputTypeToString(type)
+ );
+ this.makeExecutable();
+
+ this.m_type = type;
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayFirstGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayFirstGroup.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayFirstGroup;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayFirstGroup.prototype.init = function() {
+ var counts = [5, 256];
+ var firsts = [6, 24];
+ var offsets = [1, 16, 17];
+ var strides = [/*0,*/ -1, 17, 32]; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
+
+ for (var offsetNdx = 0; offsetNdx < offsets.length; offsetNdx++) {
+ for (var countNdx = 0; countNdx < counts.length; countNdx++) {
+ for (var strideNdx = 0; strideNdx < strides.length; strideNdx++) {
+ for (var firstNdx = 0; firstNdx < firsts.length; firstNdx++) {
+ var packed = this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
+ var componentCount = packed ? 4 : 2;
+ var stride = strides[strideNdx] < 0 ?
+ (packed ? 8 : (glsVertexArrayTests.deArray.inputTypeSize(this.m_type) * componentCount)) :
+ (strides[strideNdx]);
+ var alignment = packed ?
+ (glsVertexArrayTests.deArray.inputTypeSize(this.m_type) * componentCount) :
+ (glsVertexArrayTests.deArray.inputTypeSize(this.m_type));
+ var aligned = ((stride % alignment) == 0) &&
+ ((offsets[offsetNdx] % alignment) == 0);
+ var name = 'first' + firsts[firstNdx] + '_offset' + offsets[offsetNdx] + '_stride' + stride + '_quads' + counts[countNdx];
+
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ this.m_type,
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.Storage.BUFFER,
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ componentCount,
+ offsets[offsetNdx],
+ stride,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(this.m_type),
+ glsVertexArrayTests.GLValue.getMaxValue(this.m_type)
+ );
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = counts[countNdx];
+ spec.first = firsts[firstNdx];
+ spec.arrays.push(arraySpec);
+
+ if (aligned)
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, name
+ )
+ );
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.SingleVertexArrayFirstTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'single_attribute.first', 'Single vertex attribute, different first values to drawArrays');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayFirstTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayFirstTests.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayFirstTests;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayFirstTests.prototype.init = function() {
+ // Test offset with different input types, component counts and storage, Usage(?)
+ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.InputType.BYTE,
+ glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++) {
+ this.addChild(
+ new es3fVertexArrayTests.SingleVertexArrayFirstGroup(
+ inputTypes[inputTypeNdx]
+ )
+ );
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ es3fVertexArrayTests.SingleVertexArrayOffsetGroup = function(type) {
+ tcuTestCase.DeqpTest.call(
+ this,
+ glsVertexArrayTests.deArray.inputTypeToString(type),
+ glsVertexArrayTests.deArray.inputTypeToString(type)
+ );
+ this.makeExecutable();
+ this.m_type = type;
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayOffsetGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayOffsetGroup.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayOffsetGroup;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayOffsetGroup.prototype.init = function() {
+ var counts = [1, 256];
+ var offsets = [1, 4, 17, 32];
+ var strides = [/*0,*/ -1, 17, 32]; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
+
+ for (var offsetNdx = 0; offsetNdx < offsets.length; offsetNdx++) {
+ for (var countNdx = 0; countNdx < counts.length; countNdx++) {
+ for (var strideNdx = 0; strideNdx < strides.length; strideNdx++) {
+ var packed = this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
+ var componentCount = packed ? 4 : 2;
+ var stride = (
+ strides[strideNdx] < 0 ?
+ glsVertexArrayTests.deArray.inputTypeSize(
+ this.m_type
+ ) * componentCount :
+ strides[strideNdx]
+ );
+ var alignment = packed ?
+ glsVertexArrayTests.deArray.inputTypeSize(this.m_type) * componentCount :
+ glsVertexArrayTests.deArray.inputTypeSize(this.m_type);
+
+ var aligned = ((stride % alignment) == 0) &&
+ ((offsets[offsetNdx] % alignment) == 0);
+ var name = 'offset' + offsets[offsetNdx] +
+ '_stride' + stride + '_quads' +
+ counts[countNdx];
+
+ /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ this.m_type,
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.Storage.BUFFER,
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ componentCount,
+ offsets[offsetNdx],
+ stride,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(this.m_type),
+ glsVertexArrayTests.GLValue.getMaxValue(this.m_type)
+ );
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = counts[countNdx];
+ spec.first = 0;
+ spec.arrays.push(arraySpec);
+
+ if (aligned)
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, name
+ )
+ );
+ }
+ }
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.SingleVertexArrayOffsetTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'single_attribute.offset', 'Single vertex atribute offset element');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayOffsetTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayOffsetTests.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayOffsetTests;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayOffsetTests.prototype.init = function() {
+ // Test offset with different input types, component counts and storage, Usage(?)
+ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.InputType.BYTE,
+ glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++) {
+ this.addChild(
+ new es3fVertexArrayTests.SingleVertexArrayOffsetGroup(
+ inputTypes[inputTypeNdx]
+ )
+ );
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ es3fVertexArrayTests.SingleVertexArrayNormalizeGroup = function(type) {
+ tcuTestCase.DeqpTest.call(
+ this,
+ glsVertexArrayTests.deArray.inputTypeToString(type),
+ glsVertexArrayTests.deArray.inputTypeToString(type)
+ );
+ this.makeExecutable();
+ this.m_type = type;
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayNormalizeGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayNormalizeGroup.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayNormalizeGroup;
+
+ /**
+ * init for SingleVertexArrayNormalizeGroup
+ */
+ es3fVertexArrayTests.SingleVertexArrayNormalizeGroup.prototype.init = function() {
+ var counts = [1, 256];
+
+ for (var componentCount = 2; componentCount < 5; componentCount++) {
+ for (var countNdx = 0; countNdx < counts.length; countNdx++) {
+ if (
+ (
+ this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ) && componentCount != 4
+ )
+ continue;
+
+ var name = 'components' + componentCount.toString() + '_quads' + counts[countNdx].toString();
+
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ this.m_type,
+ glsVertexArrayTests.deArray.OutputType.VEC4,
+ glsVertexArrayTests.deArray.Storage.BUFFER, //No USER Storage support in WebGL2
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ componentCount,
+ 0,
+ 0,
+ true,
+ glsVertexArrayTests.GLValue.getMinValue(this.m_type),
+ glsVertexArrayTests.GLValue.getMaxValue(this.m_type)
+ );
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = counts[countNdx];
+ spec.first = 0;
+ spec.arrays.push(arraySpec);
+
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, name
+ )
+ );
+ }
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.SingleVertexArrayNormalizeTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'single_attribute.normalize', 'Single normalize vertex atribute');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayNormalizeTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayNormalizeTests.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayNormalizeTests;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.SingleVertexArrayNormalizeTests.prototype.init = function() {
+ // Test normalization with different input types, component counts and storage
+ /** @type {Array<glsVertexArrayTests.deArray.InputType>} */ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.InputType.SHORT,
+ glsVertexArrayTests.deArray.InputType.BYTE,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE,
+ //glsVertexArrayTests.deArray.InputType.FIXED,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_INT,
+ glsVertexArrayTests.deArray.InputType.INT,
+ glsVertexArrayTests.deArray.InputType.HALF,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10,
+ glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++) {
+ this.addChild(
+ new es3fVertexArrayTests.SingleVertexArrayNormalizeGroup(
+ inputTypes[inputTypeNdx]
+ )
+ );
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ es3fVertexArrayTests.SingleVertexArrayOutputTypeGroup = function(type) {
+ tcuTestCase.DeqpTest.call(
+ this,
+ "single_attribute.output_types." + glsVertexArrayTests.deArray.inputTypeToString(type),
+ glsVertexArrayTests.deArray.inputTypeToString(type)
+ );
+ this.makeExecutable();
+ this.m_type = type;
+ };
+
+ es3fVertexArrayTests.SingleVertexArrayOutputTypeGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.SingleVertexArrayOutputTypeGroup.prototype.constructor = es3fVertexArrayTests.SingleVertexArrayOutputTypeGroup;
+
+ es3fVertexArrayTests.SingleVertexArrayOutputTypeGroup.prototype.init = function() {
+ var outputTypes = [
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.OutputType.VEC3,
+ glsVertexArrayTests.deArray.OutputType.VEC4,
+ glsVertexArrayTests.deArray.OutputType.IVEC2,
+ glsVertexArrayTests.deArray.OutputType.IVEC3,
+ glsVertexArrayTests.deArray.OutputType.IVEC4,
+ glsVertexArrayTests.deArray.OutputType.UVEC2,
+ glsVertexArrayTests.deArray.OutputType.UVEC3,
+ glsVertexArrayTests.deArray.OutputType.UVEC4
+ ];
+ var storages = [glsVertexArrayTests.deArray.Storage.BUFFER]; //No USER storage support in WebGL2
+ var counts = [1, 256];
+
+ for (var outputTypeNdx = 0; outputTypeNdx < outputTypes.length; outputTypeNdx++) {
+ for (var storageNdx = 0; storageNdx < storages.length; storageNdx++) {
+ for (var componentCount = 2; componentCount < 5; componentCount++) {
+ for (var countNdx = 0; countNdx < counts.length; countNdx++) {
+ var name = 'components' + componentCount + '_' +
+ glsVertexArrayTests.deArray.outputTypeToString(
+ outputTypes[outputTypeNdx]
+ ) +
+ '_quads' + counts[countNdx];
+
+ var inputIsSignedInteger =
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.SHORT ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.BYTE;
+
+ var inputIsUnignedInteger =
+ this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE;
+
+ var outputIsSignedInteger =
+ outputTypes[outputTypeNdx] == glsVertexArrayTests.deArray.OutputType.IVEC2 ||
+ outputTypes[outputTypeNdx] == glsVertexArrayTests.deArray.OutputType.IVEC3 ||
+ outputTypes[outputTypeNdx] == glsVertexArrayTests.deArray.OutputType.IVEC4;
+
+ var outputIsUnsignedInteger =
+ outputTypes[outputTypeNdx] == glsVertexArrayTests.deArray.OutputType.UVEC2 ||
+ outputTypes[outputTypeNdx] == glsVertexArrayTests.deArray.OutputType.UVEC3 ||
+ outputTypes[outputTypeNdx] == glsVertexArrayTests.deArray.OutputType.UVEC4;
+
+ // If input type is float type and output type is int type skip
+ if ((this.m_type == glsVertexArrayTests.deArray.InputType.FLOAT ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.HALF) &&
+ (outputTypes[outputTypeNdx] >= glsVertexArrayTests.deArray.OutputType.INT))
+ continue;
+
+ if ((this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10) &&
+ (outputTypes[outputTypeNdx] >= glsVertexArrayTests.deArray.OutputType.INT))
+ continue;
+
+ if ((this.m_type == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 ||
+ this.m_type == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10) &&
+ componentCount != 4)
+ continue;
+
+ // Loading signed data as unsigned causes undefined values and vice versa
+ if (inputIsSignedInteger && outputIsUnsignedInteger)
+ continue;
+ if (inputIsUnignedInteger && outputIsSignedInteger)
+ continue;
+
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ this.m_type,
+ outputTypes[outputTypeNdx],
+ storages[storageNdx],
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ componentCount,
+ 0,
+ 0,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(this.m_type),
+ glsVertexArrayTests.GLValue.getMaxValue(this.m_type)
+ );
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = counts[countNdx];
+ spec.first = 0;
+ spec.arrays.push(arraySpec);
+
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, name
+ )
+ );
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.MultiVertexArrayCountTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'multiple_attributes.attribute_count', 'Attribute counts');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.MultiVertexArrayCountTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.MultiVertexArrayCountTests.prototype.constructor = es3fVertexArrayTests.MultiVertexArrayCountTests;
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @return {string}
+ */
+ es3fVertexArrayTests.MultiVertexArrayCountTests.prototype.getTestName = function(spec) {
+ var name = '';
+ name += spec.arrays.length;
+
+ return name;
+ };
+
+ es3fVertexArrayTests.MultiVertexArrayCountTests.prototype.init = function() {
+ // Test attribute counts
+ var arrayCounts = [2, 3, 4, 5, 6, 7, 8];
+
+ for (var arrayCountNdx = 0; arrayCountNdx < arrayCounts.length; arrayCountNdx++) {
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = 256;
+ spec.first = 0;
+
+ for (var arrayNdx = 0; arrayNdx < arrayCounts[arrayCountNdx]; arrayNdx++) {
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.Storage.BUFFER, // No USER storage support in WebGL2
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ 2,
+ 0,
+ 0,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(glsVertexArrayTests.deArray.InputType.FLOAT),
+ glsVertexArrayTests.GLValue.getMaxValue(glsVertexArrayTests.deArray.InputType.FLOAT)
+ );
+ spec.arrays.push(arraySpec);
+ }
+
+ var name = this.getTestName(spec);
+ var desc = this.getTestName(spec);
+
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, desc
+ )
+ );
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.MultiVertexArrayStorageTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'multiple_attributes.storage', 'Attribute storages');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.MultiVertexArrayStorageTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.MultiVertexArrayStorageTests.prototype.constructor = es3fVertexArrayTests.MultiVertexArrayStorageTests;
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @return {string}
+ */
+ es3fVertexArrayTests.MultiVertexArrayStorageTests.prototype.getTestName = function(spec) {
+ var name = '';
+ name += spec.arrays.length;
+
+ for (var arrayNdx = 0; arrayNdx < spec.arrays.length; arrayNdx++)
+ name += '_' + glsVertexArrayTests.deArray.storageToString(spec.arrays[arrayNdx].storage);
+
+ return name;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @param {number} depth
+ */
+ es3fVertexArrayTests.MultiVertexArrayStorageTests.prototype.addStorageCases = function(spec, depth) {
+ if (depth == 0) {
+ // Skip trivial case, used elsewhere
+ var ok = false;
+ for (var arrayNdx = 0; arrayNdx < spec.arrays.length; arrayNdx++) {
+ if (spec.arrays[arrayNdx].storage != glsVertexArrayTests.deArray.Storage.USER) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok)
+ return;
+
+ var name = this.getTestName(spec);
+ var desc = this.getTestName(spec);
+
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, desc
+ )
+ );
+ return;
+ }
+
+ var storages = [
+ //glsVertexArrayTests.deArray.Storage.USER, Not supported in WebGL 2.0
+ glsVertexArrayTests.deArray.Storage.BUFFER
+ ];
+
+ for (var storageNdx = 0; storageNdx < storages.length; storageNdx++) {
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ storages[storageNdx],
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ 2,
+ 0,
+ 0,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(glsVertexArrayTests.deArray.InputType.FLOAT),
+ glsVertexArrayTests.GLValue.getMaxValue(glsVertexArrayTests.deArray.InputType.FLOAT)
+ );
+
+ var _spec = spec;
+ _spec.arrays.push(arraySpec);
+ this.addStorageCases(_spec, depth - 1);
+ }
+ };
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.MultiVertexArrayStorageTests.prototype.init = function() {
+ // Test different storages
+ var arrayCounts = [3];
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = 256;
+ spec.first = 0;
+
+ for (var arrayCountNdx = 0; arrayCountNdx < arrayCounts.length; arrayCountNdx++)
+ this.addStorageCases(spec, arrayCounts[arrayCountNdx]);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.MultiVertexArrayStrideTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'multiple_attributes.stride', 'Strides');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.MultiVertexArrayStrideTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.MultiVertexArrayStrideTests.prototype.constructor = es3fVertexArrayTests.MultiVertexArrayStrideTests;
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @return {string}
+ */
+ es3fVertexArrayTests.MultiVertexArrayStrideTests.prototype.getTestName = function(spec) {
+ var name = '';
+
+ name += spec.arrays.length;
+
+ for (var arrayNdx = 0; arrayNdx < spec.arrays.length; arrayNdx++) {
+ name += '_' +
+ glsVertexArrayTests.deArray.inputTypeToString(spec.arrays[arrayNdx].inputType) +
+ spec.arrays[arrayNdx].componentCount + '_' +
+ spec.arrays[arrayNdx].stride;
+ }
+
+ return name;
+ };
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.MultiVertexArrayStrideTests.prototype.init = function() {
+ // Test different strides, with multiple arrays, input types??
+ var arrayCounts = [3];
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = 256;
+ spec.first = 0;
+
+ for (var arrayCountNdx = 0; arrayCountNdx < arrayCounts.length; arrayCountNdx++)
+ this.addStrideCases(spec, arrayCounts[arrayCountNdx]);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @param {number} depth
+ */
+ es3fVertexArrayTests.MultiVertexArrayStrideTests.prototype.addStrideCases = function(spec, depth) {
+ if (depth == 0) {
+ var name = this.getTestName(spec);
+ var desc = this.getTestName(spec);
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, desc
+ )
+ );
+ return;
+ }
+
+ var strides = [0, -1, 17, 32];
+ var inputType = glsVertexArrayTests.deArray.InputType.FLOAT;
+
+ for (var strideNdx = 0; strideNdx < strides.length; strideNdx++) {
+ var componentCount = 2;
+ var stride = strides[strideNdx] >= 0 ? strides[strideNdx] : componentCount * glsVertexArrayTests.deArray.inputTypeSize(glsVertexArrayTests.deArray.InputType.FLOAT);
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ inputType,
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.Storage.BUFFER, //USER storage not supported in WebGL 2.0
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ componentCount,
+ 0,
+ stride,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(glsVertexArrayTests.deArray.InputType.FLOAT),
+ glsVertexArrayTests.GLValue.getMaxValue(glsVertexArrayTests.deArray.InputType.FLOAT)
+ );
+
+ /** @type {boolean} */ var aligned = (stride % glsVertexArrayTests.deArray.inputTypeSize(inputType)) == 0;
+ if (aligned) {
+ var _spec = /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec} */ (deUtil.clone(spec)); //To assign spec by value;
+ _spec.arrays.push(arraySpec);
+ this.addStrideCases(_spec, depth - 1);
+ }
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.MultiVertexArrayOutputTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'multiple_attributes.input_types', 'input types');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.MultiVertexArrayOutputTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.MultiVertexArrayOutputTests.prototype.constructor = es3fVertexArrayTests.MultiVertexArrayOutputTests;
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @return {string}
+ */
+ es3fVertexArrayTests.MultiVertexArrayOutputTests.prototype.getTestName = function(spec) {
+ var name = '';
+
+ name += spec.arrays.length;
+
+ for (var arrayNdx = 0; arrayNdx < spec.arrays.length; arrayNdx++) {
+ name += '_' +
+ glsVertexArrayTests.deArray.inputTypeToString(spec.arrays[arrayNdx].inputType) +
+ spec.arrays[arrayNdx].componentCount + '_' +
+ glsVertexArrayTests.deArray.outputTypeToString(spec.arrays[arrayNdx].outputType);
+ }
+
+ return name;
+ };
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.MultiVertexArrayOutputTests.prototype.init = function() {
+ // Test different input types, with multiple arrays
+ var arrayCounts = [3];
+
+ var spec = new glsVertexArrayTests.MultiVertexArrayTest.Spec();
+
+ spec.primitive = glsVertexArrayTests.deArray.Primitive.TRIANGLES;
+ spec.drawCount = 256;
+ spec.first = 0;
+
+ for (var arrayCountNdx = 0; arrayCountNdx < arrayCounts.length; arrayCountNdx++)
+ this.addInputTypeCases(spec, arrayCounts[arrayCountNdx]);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @param {number} depth
+ */
+ es3fVertexArrayTests.MultiVertexArrayOutputTests.prototype.addInputTypeCases = function(spec, depth) {
+ if (depth == 0) {
+ var name = this.getTestName(spec);
+ var desc = this.getTestName(spec);
+ this.addChild(
+ new glsVertexArrayTests.MultiVertexArrayTest(
+ spec, name, desc
+ )
+ );
+ return;
+ }
+
+ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.BYTE,
+ glsVertexArrayTests.deArray.InputType.SHORT,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
+ ];
+
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++) {
+ var arraySpec = new glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec(
+ inputTypes[inputTypeNdx],
+ glsVertexArrayTests.deArray.OutputType.VEC2,
+ glsVertexArrayTests.deArray.Storage.BUFFER, //USER storage not supported in WebGL 2.0
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ 2,
+ 0,
+ 0,
+ false,
+ glsVertexArrayTests.GLValue.getMinValue(inputTypes[inputTypeNdx]),
+ glsVertexArrayTests.GLValue.getMaxValue(inputTypes[inputTypeNdx])
+ );
+
+ var _spec = /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec} */ (deUtil.clone(spec));
+ _spec.arrays.push(arraySpec);
+ this.addInputTypeCases(_spec, depth - 1);
+ }
+ };
+
+ /**
+ * es3fVertexArrayTests.VertexArrayTestGroup
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fVertexArrayTests.VertexArrayTestGroup = function() {
+ tcuTestCase.DeqpTest.call(this, 'vertex_arrays', 'Vertex array and array tests');
+ this.makeExecutable();
+ };
+
+ es3fVertexArrayTests.VertexArrayTestGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fVertexArrayTests.VertexArrayTestGroup.prototype.constructor = es3fVertexArrayTests.VertexArrayTestGroup;
+
+ /**
+ * init
+ */
+ es3fVertexArrayTests.VertexArrayTestGroup.prototype.init = function() {
+ this.addChild(new es3fVertexArrayTests.SingleVertexArrayStrideTests());
+ this.addChild(new es3fVertexArrayTests.SingleVertexArrayNormalizeTests());
+
+ // Test output types with different input types, component counts and storage, Usage?, Precision?, float?
+ var inputTypes = [
+ glsVertexArrayTests.deArray.InputType.FLOAT,
+ glsVertexArrayTests.deArray.InputType.SHORT,
+ glsVertexArrayTests.deArray.InputType.BYTE,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_INT,
+ glsVertexArrayTests.deArray.InputType.INT,
+ glsVertexArrayTests.deArray.InputType.HALF,
+ glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10,
+ glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+ for (var inputTypeNdx = 0; inputTypeNdx < inputTypes.length; inputTypeNdx++) {
+ this.addChild(new es3fVertexArrayTests.SingleVertexArrayOutputTypeGroup(inputTypes[inputTypeNdx]));
+ }
+
+ /** @type {Array<glsVertexArrayTests.deArray.Usage>} */ var usages = [
+ glsVertexArrayTests.deArray.Usage.STATIC_DRAW,
+ glsVertexArrayTests.deArray.Usage.STREAM_DRAW,
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW,
+ glsVertexArrayTests.deArray.Usage.STATIC_COPY,
+ glsVertexArrayTests.deArray.Usage.STREAM_COPY,
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_COPY,
+ glsVertexArrayTests.deArray.Usage.STATIC_READ,
+ glsVertexArrayTests.deArray.Usage.STREAM_READ,
+ glsVertexArrayTests.deArray.Usage.DYNAMIC_READ
+ ];
+ for (var usageNdx = 0; usageNdx < usages.length; usageNdx++) {
+ this.addChild(new es3fVertexArrayTests.SingleVertexArrayUsageGroup(usages[usageNdx]));
+ }
+
+ this.addChild(new es3fVertexArrayTests.SingleVertexArrayOffsetTests());
+ this.addChild(new es3fVertexArrayTests.SingleVertexArrayFirstTests());
+
+ this.addChild(new es3fVertexArrayTests.MultiVertexArrayCountTests());
+ this.addChild(new es3fVertexArrayTests.MultiVertexArrayStorageTests());
+ this.addChild(new es3fVertexArrayTests.MultiVertexArrayStrideTests());
+ this.addChild(new es3fVertexArrayTests.MultiVertexArrayOutputTests());
+ };
+
+ /**
+ * Create and execute the test cases
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fVertexArrayTests.run = function(context, range) {
+ gl = context;
+ //Set up root Test
+ var state = tcuTestCase.runner;
+
+ var test = new es3fVertexArrayTests.VertexArrayTestGroup();
+ var testName = test.fullName();
+ var testDescription = test.getDescription();
+ state.testCases = test;
+ state.testName = testName;
+
+ //Set up name and description of this test series.
+ setCurrentTestName(testName);
+ description(testDescription);
+
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ } catch (err) {
+ testFailedOptions('Failed to es3fVertexArrayTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer.html
new file mode 100644
index 0000000000..7908636028
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContextWithWrapperThatThrowsOnGLError('canvas', null, 2);
+
+
+ try {
+ functional.gles3.es3fFboColorbufferTests.run(gl);
+ }
+ catch(err)
+ {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/00_test_list.txt
new file mode 100644
index 0000000000..d6d590a077
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/00_test_list.txt
@@ -0,0 +1,26 @@
+clear.html
+tex2d_00.html
+tex2d_01.html
+tex2d_02.html
+tex2d_03.html
+tex2d_04.html
+tex2d_05.html
+texcube_00.html
+texcube_01.html
+texcube_02.html
+texcube_03.html
+texcube_04.html
+texcube_05.html
+tex2darray_00.html
+tex2darray_01.html
+tex2darray_02.html
+tex2darray_03.html
+tex2darray_04.html
+tex2darray_05.html
+tex3d_00.html
+tex3d_01.html
+tex3d_02.html
+tex3d_03.html
+tex3d_04.html
+tex3d_05.html
+blend.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/blend.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/blend.html
new file mode 100644
index 0000000000..4826cf0cb7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/blend.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/clear.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/clear.html
new file mode 100644
index 0000000000..f431afb364
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/clear.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/fbocolorbuffer_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/fbocolorbuffer_test_generator.py
new file mode 100644
index 0000000000..9307b8d3f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/fbocolorbuffer_test_generator.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for fbocolorbuffer* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'clear',
+ 'tex2d',
+ 'texcube',
+ 'tex2darray',
+ 'tex3d',
+ 'blend',
+]
+
+_GROUP_TEST_COUNTS = [
+ 1,
+ 6,
+ 6,
+ 6,
+ 6,
+ 1
+]
+
+def GenerateFilename(group, count, index):
+ """Generate test filename."""
+ filename = group
+ assert index >= 0 and index < count
+ if count > 1:
+ index_str = str(index)
+ if index < 10:
+ index_str = "0" + index_str
+ filename += "_" + index_str
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ assert len(_GROUPS) == len(_GROUP_TEST_COUNTS)
+ test_index = 0
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ group = _GROUPS[ii]
+ count = _GROUP_TEST_COUNTS[ii]
+ for index in range(count):
+ filename = GenerateFilename(group, count, index)
+ filelist.append(filename)
+ WriteTest(filename, test_index, test_index + 1)
+ test_index += 1
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_00.html
new file mode 100644
index 0000000000..b9918b2dd7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_00.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_01.html
new file mode 100644
index 0000000000..653f89e2a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_01.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_02.html
new file mode 100644
index 0000000000..2e955cb8f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_02.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_03.html
new file mode 100644
index 0000000000..993108e86f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_03.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_04.html
new file mode 100644
index 0000000000..d7f5b2782f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_04.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_05.html
new file mode 100644
index 0000000000..1d8bdcbaab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2d_05.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_00.html
new file mode 100644
index 0000000000..5e42f0021c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_00.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_01.html
new file mode 100644
index 0000000000..e01cee3b22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_01.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_02.html
new file mode 100644
index 0000000000..2f9dd6061c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_02.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_03.html
new file mode 100644
index 0000000000..0f9b76857e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_03.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_04.html
new file mode 100644
index 0000000000..82ef5b6cf7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_04.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_05.html
new file mode 100644
index 0000000000..28668bd635
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex2darray_05.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_00.html
new file mode 100644
index 0000000000..98c04df0e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_00.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_01.html
new file mode 100644
index 0000000000..adb01c169e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_01.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_02.html
new file mode 100644
index 0000000000..87a7e291e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_02.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_03.html
new file mode 100644
index 0000000000..b7f7f18d8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_03.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_04.html
new file mode 100644
index 0000000000..a0a4473857
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_04.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_05.html
new file mode 100644
index 0000000000..91ce46cc33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/tex3d_05.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_00.html
new file mode 100644
index 0000000000..0ff04bee2d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_00.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_01.html
new file mode 100644
index 0000000000..38512eb0ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_01.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_02.html
new file mode 100644
index 0000000000..2cf3fa750e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_02.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_03.html
new file mode 100644
index 0000000000..2e55800859
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_03.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_04.html
new file mode 100644
index 0000000000..9602acaf25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_04.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_05.html
new file mode 100644
index 0000000000..a77a1bd248
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocolorbuffer/texcube_05.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fbocolorbuffer_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Color Buffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboColorbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+var ext = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboColorbufferTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocompleteness.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocompleteness.html
new file mode 100644
index 0000000000..40dc055543
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbocompleteness.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Completeness Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboCompletenessTests');</script>
+<script>goog.require('modules.shared.glsFboUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('canvas', null, 2);
+
+ try {
+ functional.gles3.es3fFboCompletenessTests.initGlDependents(gl);
+ functional.gles3.es3fFboCompletenessTests.run(gl);
+ }
+ catch(err) {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbodepthbuffer.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbodepthbuffer.html
new file mode 100644
index 0000000000..e74b8285c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbodepthbuffer.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Depthbuffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboDepthbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContextWithWrapperThatThrowsOnGLError('canvas', null, 2);
+
+
+ try {
+ functional.gles3.es3fFboDepthbufferTests.run(gl);
+ }
+ catch(err)
+ {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/00_test_list.txt
new file mode 100644
index 0000000000..189ebc1d17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/00_test_list.txt
@@ -0,0 +1,7 @@
+default.html
+whole.html
+sub.html
+format_00.html
+format_01.html
+format_02.html
+target.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/default.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/default.html
new file mode 100644
index 0000000000..ea07a5f6db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/default.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/fboinvalidate_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/fboinvalidate_test_generator.py
new file mode 100644
index 0000000000..ddb7efa091
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/fboinvalidate_test_generator.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for fboinvalidate* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'default',
+ 'whole',
+ 'sub',
+ 'format',
+ 'target',
+]
+
+_GROUP_TEST_COUNTS = [
+ 1,
+ 1,
+ 1,
+ 3,
+ 1
+]
+
+def GenerateFilename(group, count, index):
+ """Generate test filename."""
+ filename = group
+ assert index >= 0 and index < count
+ if count > 1:
+ index_str = str(index)
+ if index < 10:
+ index_str = "0" + index_str
+ filename += "_" + index_str
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ assert len(_GROUPS) == len(_GROUP_TEST_COUNTS)
+ test_index = 0
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ group = _GROUPS[ii]
+ count = _GROUP_TEST_COUNTS[ii]
+ for index in range(count):
+ filename = GenerateFilename(group, count, index)
+ filelist.append(filename)
+ WriteTest(filename, test_index, test_index + 1)
+ test_index += 1
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_00.html
new file mode 100644
index 0000000000..50a4fad63d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_00.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_01.html
new file mode 100644
index 0000000000..2a130faadb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_01.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_02.html
new file mode 100644
index 0000000000..7aecfbf1a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/format_02.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/sub.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/sub.html
new file mode 100644
index 0000000000..0a883c0c44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/sub.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/target.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/target.html
new file mode 100644
index 0000000000..e36c335d4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/target.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/whole.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/whole.html
new file mode 100644
index 0000000000..2792fa7652
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fboinvalidate/whole.html
@@ -0,0 +1,32 @@
+<!--
+
+This file is auto-generated from fboinvalidate_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL FBO Invalidate Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboInvalidateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="128" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+var extention = gl.getExtension('EXT_color_buffer_float');
+
+functional.gles3.es3fFboInvalidateTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.2_samples.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.2_samples.html
new file mode 100644
index 0000000000..1de885749a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.2_samples.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fbo Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="119" height="131"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboMultisampleTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.4_samples.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.4_samples.html
new file mode 100644
index 0000000000..5e8d75c691
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.4_samples.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fbo Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="119" height="131"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboMultisampleTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.8_samples.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.8_samples.html
new file mode 100644
index 0000000000..c1fb9e70f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbomultisample.8_samples.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fbo Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="119" height="131"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboMultisampleTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/00_test_list.txt
new file mode 100644
index 0000000000..65e66c8949
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/00_test_list.txt
@@ -0,0 +1,18 @@
+stencil_clear.html
+shared_colorbuffer_clear.html
+shared_colorbuffer_00.html
+shared_colorbuffer_01.html
+shared_colorbuffer_02.html
+shared_depth_stencil.html
+resize_00.html
+resize_01.html
+resize_02.html
+resize_03.html
+recreate_color_00.html
+recreate_color_01.html
+recreate_color_02.html
+recreate_color_03.html
+recreate_color_04.html
+recreate_color_05.html
+recreate_color_06.html
+recreate_depth_stencil.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/fborender_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/fborender_test_generator.py
new file mode 100644
index 0000000000..a1065d4629
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/fborender_test_generator.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for fborender* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'stencil_clear',
+ 'shared_colorbuffer_clear',
+ 'shared_colorbuffer',
+ 'shared_depth_stencil',
+ 'resize',
+ 'recreate_color',
+ 'recreate_depth_stencil'
+]
+
+_GROUP_TEST_COUNTS = [
+ 1,
+ 1,
+ 3,
+ 1,
+ 4,
+ 7,
+ 1
+]
+
+def GenerateFilename(group, count, index):
+ """Generate test filename."""
+ filename = group
+ assert index >= 0 and index < count
+ if count > 1:
+ index_str = str(index)
+ if index < 10:
+ index_str = "0" + index_str
+ filename += "_" + index_str
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ assert len(_GROUPS) == len(_GROUP_TEST_COUNTS)
+ test_index = 0
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ group = _GROUPS[ii]
+ count = _GROUP_TEST_COUNTS[ii]
+ for index in range(count):
+ filename = GenerateFilename(group, count, index)
+ filelist.append(filename)
+ WriteTest(filename, test_index, test_index + 1)
+ test_index += 1
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_00.html
new file mode 100644
index 0000000000..e318ee0e6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_01.html
new file mode 100644
index 0000000000..9fb93d4863
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_02.html
new file mode 100644
index 0000000000..08076ed79b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_03.html
new file mode 100644
index 0000000000..3c72f2bcab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_04.html
new file mode 100644
index 0000000000..1007e8c749
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_05.html
new file mode 100644
index 0000000000..1ec97a5912
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_06.html
new file mode 100644
index 0000000000..51ab8dec97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_color_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_depth_stencil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_depth_stencil.html
new file mode 100644
index 0000000000..0e4ca74e54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/recreate_depth_stencil.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_00.html
new file mode 100644
index 0000000000..5d9bab23f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_01.html
new file mode 100644
index 0000000000..94cb09653c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_02.html
new file mode 100644
index 0000000000..c1f4c13616
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_03.html
new file mode 100644
index 0000000000..4a6e2c81d7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/resize_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_00.html
new file mode 100644
index 0000000000..54004f2d7c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_01.html
new file mode 100644
index 0000000000..b3ac79efbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_02.html
new file mode 100644
index 0000000000..2f85029b1f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_clear.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_clear.html
new file mode 100644
index 0000000000..69a46744ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_colorbuffer_clear.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_depth_stencil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_depth_stencil.html
new file mode 100644
index 0000000000..ff5c626431
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/shared_depth_stencil.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/stencil_clear.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/stencil_clear.html
new file mode 100644
index 0000000000..59c0819fe6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fborender/stencil_clear.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fborender_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Render Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboRenderTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="128"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboRenderTest.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostatequery.html
new file mode 100644
index 0000000000..95cc36b6a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fbo State Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboStateQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostencilbuffer.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostencilbuffer.html
new file mode 100644
index 0000000000..251acc57dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fbostencilbuffer.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fbo Stencilbuffer Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFboStencilbufferTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFboStencilbufferTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/floatstatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/floatstatequery.html
new file mode 100644
index 0000000000..1fd326939e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/floatstatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Float State Query Tests Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFloatStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFloatStateQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragdepth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragdepth.html
new file mode 100644
index 0000000000..31ee874ae3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragdepth.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Frag Depth Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragDepthTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragDepthTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/00_test_list.txt
new file mode 100644
index 0000000000..8a410f6506
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/00_test_list.txt
@@ -0,0 +1,11 @@
+basic.float.html
+basic.fixed.html
+basic.int.html
+basic.uint.html
+array.float.html
+array.fixed.html
+array.int.html
+array.uint.html
+random_00.html
+random_01.html
+random_02.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.fixed.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.fixed.html
new file mode 100644
index 0000000000..ab4c17aec6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.fixed.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.float.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.float.html
new file mode 100644
index 0000000000..474fe78eec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.float.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.int.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.int.html
new file mode 100644
index 0000000000..f100e804b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.int.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.uint.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.uint.html
new file mode 100644
index 0000000000..fb3e5d96a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/array.uint.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.fixed.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.fixed.html
new file mode 100644
index 0000000000..e58eda69c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.fixed.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.float.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.float.html
new file mode 100644
index 0000000000..b0fe9a2fff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.float.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.int.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.int.html
new file mode 100644
index 0000000000..871d8d0151
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.int.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.uint.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.uint.html
new file mode 100644
index 0000000000..915aa90d9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/basic.uint.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/fragmentoutput_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/fragmentoutput_test_generator.py
new file mode 100644
index 0000000000..5f7ea66d23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/fragmentoutput_test_generator.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for fragmentoutput* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'basic.float',
+ 'basic.fixed',
+ 'basic.int',
+ 'basic.uint',
+ 'array.float',
+ 'array.fixed',
+ 'array.int',
+ 'array.uint',
+ 'random_00',
+ 'random_01',
+ 'random_02'
+]
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = _GROUPS[ii] + '.html'
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_00.html
new file mode 100644
index 0000000000..d592e2f114
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_01.html
new file mode 100644
index 0000000000..4e62689ce0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_02.html
new file mode 100644
index 0000000000..3bcf9c5442
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/fragmentoutput/random_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from fragmentoutput_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fragment Output Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFragmentOutputTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFragmentOutputTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/00_test_list.txt
new file mode 100644
index 0000000000..6aeeaf64ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/00_test_list.txt
@@ -0,0 +1,50 @@
+rect_00.html
+rect_01.html
+rect_02.html
+rect_03.html
+rect_04.html
+rect_05.html
+rect_06.html
+conversion_00.html
+conversion_01.html
+conversion_02.html
+conversion_03.html
+conversion_04.html
+conversion_05.html
+conversion_06.html
+conversion_07.html
+conversion_08.html
+conversion_09.html
+conversion_10.html
+conversion_11.html
+conversion_12.html
+conversion_13.html
+conversion_14.html
+conversion_15.html
+conversion_16.html
+conversion_17.html
+conversion_18.html
+conversion_19.html
+conversion_20.html
+conversion_21.html
+conversion_22.html
+conversion_23.html
+conversion_24.html
+conversion_25.html
+conversion_26.html
+conversion_27.html
+conversion_28.html
+conversion_29.html
+conversion_30.html
+conversion_31.html
+conversion_32.html
+conversion_33.html
+conversion_34.html
+depth_stencil.html
+default_framebuffer_00.html
+default_framebuffer_01.html
+default_framebuffer_02.html
+default_framebuffer_03.html
+default_framebuffer_04.html
+default_framebuffer_05.html
+default_framebuffer_06.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_00.html
new file mode 100644
index 0000000000..6124a65698
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_01.html
new file mode 100644
index 0000000000..d0389725fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_02.html
new file mode 100644
index 0000000000..cebfd04d06
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_03.html
new file mode 100644
index 0000000000..2539865a9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_04.html
new file mode 100644
index 0000000000..d98f9268d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_05.html
new file mode 100644
index 0000000000..6045c4a870
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_06.html
new file mode 100644
index 0000000000..f851a73d5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_07.html
new file mode 100644
index 0000000000..900c2c1567
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_08.html
new file mode 100644
index 0000000000..f9ea2cce4f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_08.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_09.html
new file mode 100644
index 0000000000..f20d4bea67
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_09.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_10.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_10.html
new file mode 100644
index 0000000000..1f15f08f1e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_10.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_11.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_11.html
new file mode 100644
index 0000000000..9a8a2760c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_11.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_12.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_12.html
new file mode 100644
index 0000000000..d4954fb187
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_12.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_13.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_13.html
new file mode 100644
index 0000000000..a68d778d84
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_13.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_14.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_14.html
new file mode 100644
index 0000000000..5fbc4b1c68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_14.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_15.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_15.html
new file mode 100644
index 0000000000..0b31db5a2a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_15.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_16.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_16.html
new file mode 100644
index 0000000000..31de2fb37e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_16.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_17.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_17.html
new file mode 100644
index 0000000000..85939968f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_17.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_18.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_18.html
new file mode 100644
index 0000000000..303b1f9d22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_18.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_19.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_19.html
new file mode 100644
index 0000000000..4ca74e4ae1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_19.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_20.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_20.html
new file mode 100644
index 0000000000..13dfe1137c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_20.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_21.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_21.html
new file mode 100644
index 0000000000..717bcbbcce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_21.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_22.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_22.html
new file mode 100644
index 0000000000..8bf21f9e3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_22.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_23.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_23.html
new file mode 100644
index 0000000000..7238bdb419
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_23.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_24.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_24.html
new file mode 100644
index 0000000000..2e7313a664
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_24.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_25.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_25.html
new file mode 100644
index 0000000000..053dd4be5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_25.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_26.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_26.html
new file mode 100644
index 0000000000..c7f79eca6f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_26.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [33, 34]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_27.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_27.html
new file mode 100644
index 0000000000..f8c41645f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_27.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [34, 35]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_28.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_28.html
new file mode 100644
index 0000000000..2222bb7f30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_28.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [35, 36]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_29.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_29.html
new file mode 100644
index 0000000000..51d29810cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_29.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [36, 37]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_30.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_30.html
new file mode 100644
index 0000000000..eae41bfcc6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_30.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [37, 38]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_31.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_31.html
new file mode 100644
index 0000000000..55e96090e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_31.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [38, 39]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_32.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_32.html
new file mode 100644
index 0000000000..2ddd49fce8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_32.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [39, 40]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_33.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_33.html
new file mode 100644
index 0000000000..83a32646ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_33.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [40, 41]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_34.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_34.html
new file mode 100644
index 0000000000..062cb7f3ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/conversion_34.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [41, 42]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_00.html
new file mode 100644
index 0000000000..749c9bff5b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [43, 44]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_01.html
new file mode 100644
index 0000000000..42cf9a6471
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [44, 45]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_02.html
new file mode 100644
index 0000000000..3789b97c6c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [45, 46]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_03.html
new file mode 100644
index 0000000000..f1b0252daa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [46, 47]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_04.html
new file mode 100644
index 0000000000..60562a9998
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [47, 48]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_05.html
new file mode 100644
index 0000000000..7bd5c7db54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [48, 49]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_06.html
new file mode 100644
index 0000000000..74645cf2c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/default_framebuffer_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [49, 50]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/depth_stencil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/depth_stencil.html
new file mode 100644
index 0000000000..fb09d67f70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/depth_stencil.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [42, 43]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/frambufferblit_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/frambufferblit_test_generator.py
new file mode 100644
index 0000000000..5e347a0ca1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/frambufferblit_test_generator.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for framebufferblit* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'rect',
+ 'conversion',
+ 'depth_stencil',
+ 'default_framebuffer',
+]
+
+_GROUP_TEST_COUNTS = [
+ 7,
+ 35,
+ 1,
+ 7
+]
+
+def GenerateFilename(group, count, index):
+ """Generate test filename."""
+ filename = group
+ assert index >= 0 and index < count
+ if count > 1:
+ index_str = str(index)
+ if index < 10:
+ index_str = "0" + index_str
+ filename += "_" + index_str
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ assert len(_GROUPS) == len(_GROUP_TEST_COUNTS)
+ test_index = 0
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ group = _GROUPS[ii]
+ count = _GROUP_TEST_COUNTS[ii]
+ for index in range(count):
+ filename = GenerateFilename(group, count, index)
+ filelist.append(filename)
+ WriteTest(filename, test_index, test_index + 1)
+ test_index += 1
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_00.html
new file mode 100644
index 0000000000..c0076c02ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_01.html
new file mode 100644
index 0000000000..d2a53cedcf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_02.html
new file mode 100644
index 0000000000..b73eb396d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_03.html
new file mode 100644
index 0000000000..86971ca0f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_04.html
new file mode 100644
index 0000000000..c9239f32f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_05.html
new file mode 100644
index 0000000000..b40353a15c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_06.html
new file mode 100644
index 0000000000..8fb90dda48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/framebufferblit/rect_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from framebufferblit_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Framebuffer Blit Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fFramebufferBlitTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="200"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fFramebufferBlitTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/indexedstatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/indexedstatequery.html
new file mode 100644
index 0000000000..ee57dcb183
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/indexedstatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Indexed Integer Values Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fIndexedStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fIndexedStateQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/instancedrendering.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/instancedrendering.html
new file mode 100644
index 0000000000..6de0a016c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/instancedrendering.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Instanced Rendering Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fInstancedRenderingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fInstancedRenderingTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/integerstatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/integerstatequery.html
new file mode 100644
index 0000000000..610ddf9888
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/integerstatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Integer Values Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fIntegerStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fIntegerStateQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/internalformatquery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/internalformatquery.html
new file mode 100644
index 0000000000..765dede408
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/internalformatquery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Internalformat query tests Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fInternalFormatQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fInternalFormatQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/lifetime.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/lifetime.html
new file mode 100644
index 0000000000..7cf80807e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/lifetime.html
@@ -0,0 +1,34 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Lifetime Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fLifetimeTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+testName = 'lifetime';
+setCurrentTestName(testName);
+description("Functional test: " + testName + ".");
+
+var wtu = WebGLTestUtils;
+/** @type {WebGL2RenderingContext} */ var gl = wtu.create3DContext('canvas', null, 2);
+
+ try{
+ functional.gles3.es3fLifetimeTests.run(gl);
+ }
+ catch(err)
+ {
+ bufferedLogToConsole(err);
+ }
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/00_test_list.txt
new file mode 100644
index 0000000000..6c5e238d0d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/00_test_list.txt
@@ -0,0 +1,6 @@
+# This file is auto-generated from multisample_test_generator.py
+# DO NOT EDIT!
+default_fbo.html
+fbo_4_samples.html
+fbo_8_samples.html
+fbo_max_samples.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/default_fbo.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/default_fbo.html
new file mode 100644
index 0000000000..71d3f06bf9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/default_fbo.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from multisample_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fMultisampleTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_4_samples.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_4_samples.html
new file mode 100644
index 0000000000..c021f57ba9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_4_samples.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from multisample_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fMultisampleTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_8_samples.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_8_samples.html
new file mode 100644
index 0000000000..adca5aeafe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_8_samples.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from multisample_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fMultisampleTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_max_samples.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_max_samples.html
new file mode 100644
index 0000000000..32c75c721f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/fbo_max_samples.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from multisample_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fMultisampleTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/multisample_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/multisample_test_generator.py
new file mode 100755
index 0000000000..2107a572f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/multisample/multisample_test_generator.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for multisample* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from multisample_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_DO_NOT_EDIT_TEST_LIST_WARNING = """# This file is auto-generated from multisample_test_generator.py
+# DO NOT EDIT!
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Multisample Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fMultisampleTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+# Note: must match CaseType in es3fMultisampleTests.js.
+_GROUPS = [
+ 'default_fbo',
+ 'fbo_4_samples',
+ 'fbo_8_samples',
+ 'fbo_max_samples',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write(_DO_NOT_EDIT_TEST_LIST_WARNING)
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativebufferapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativebufferapi.html
new file mode 100644
index 0000000000..f754359818
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativebufferapi.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Negative Buffer API Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fNegativeBufferApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('canvas', null, 2);
+
+ try {
+ functional.gles3.es3fNegativeBufferApiTests.run(gl);
+ }
+ catch(err) {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativefragmentapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativefragmentapi.html
new file mode 100644
index 0000000000..91de0c29c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativefragmentapi.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Negative Fragment API Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fNegativeFragmentApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fNegativeFragmentApiTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativeshaderapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativeshaderapi.html
new file mode 100644
index 0000000000..a1d9fc66eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativeshaderapi.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Negative Shader API Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fNegativeShaderApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fNegativeShaderApiTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativestateapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativestateapi.html
new file mode 100644
index 0000000000..d54090eaf8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativestateapi.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Negative State API Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fNegativeStateApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fNegativeStateApiTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativetextureapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativetextureapi.html
new file mode 100644
index 0000000000..dd61480039
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativetextureapi.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Negative Texture API Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fNegativeTextureApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('canvas', null, 2);
+
+ try {
+ functional.gles3.es3fNegativeTextureApiTests.run(gl);
+ }
+ catch(err) {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativevertexarrayapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativevertexarrayapi.html
new file mode 100644
index 0000000000..c93514cb85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/negativevertexarrayapi.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Negative Vertex Array API Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fNegativeVertexArrayApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('canvas', null, 2);
+
+ try {
+ functional.gles3.es3fNegativeVertexArrayApiTests.run(gl);
+ }
+ catch(err) {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_conservative.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_conservative.html
new file mode 100644
index 0000000000..d05abc128f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_conservative.html
@@ -0,0 +1,26 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Occlusion Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fOcclusionQueryTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true, preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fOcclusionQueryTests.run(gl, [31, 62]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_strict.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_strict.html
new file mode 100644
index 0000000000..bc04e961ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/occlusionquery_strict.html
@@ -0,0 +1,26 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Occlusion Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fOcclusionQueryTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true, preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fOcclusionQueryTests.run(gl, [0, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/pixelbufferobject.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/pixelbufferobject.html
new file mode 100644
index 0000000000..1d9dd317de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/pixelbufferobject.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Pixel Buffer Object Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPixelBufferObjectTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fPixelBufferObjectTest.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00.html
new file mode 100644
index 0000000000..46ea49ed22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00_test_list.txt
new file mode 100644
index 0000000000..6812378afe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/00_test_list.txt
@@ -0,0 +1,8 @@
+00.html
+01.html
+02.html
+03.html
+04.html
+05.html
+06.html
+07.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/01.html
new file mode 100644
index 0000000000..59c6331b63
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/02.html
new file mode 100644
index 0000000000..5552f59172
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/03.html
new file mode 100644
index 0000000000..c6b5fb2b9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/04.html
new file mode 100644
index 0000000000..e7354067a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/05.html
new file mode 100644
index 0000000000..4ed0938d0b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/06.html
new file mode 100644
index 0000000000..ed4039877b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/07.html
new file mode 100644
index 0000000000..bf8b47fb25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/primitiverestart_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/primitiverestart_test_generator.py
new file mode 100644
index 0000000000..8eaf5ce245
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/primitiverestart/primitiverestart_test_generator.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for primitiverestart* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from primitiverestart_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Primitive Restart Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fPrimitiveRestartTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fPrimitiveRestartTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_NUM_TESTS = 8
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(_NUM_TESTS):
+ index_str = str(ii)
+ if ii < 10:
+ index_str = "0" + index_str
+ filename = index_str + '.html'
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rasterizerdiscard.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rasterizerdiscard.html
new file mode 100644
index 0000000000..185a233404
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rasterizerdiscard.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Rasterizer Discard Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fRasterizerDiscardTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {stencil: true}, 2);
+
+functional.gles3.es3fRasterizerDiscardTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rbostatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rbostatequery.html
new file mode 100644
index 0000000000..bd11632053
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/rbostatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Rbo State Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fRboStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fRboStateQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/readpixel.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/readpixel.html
new file mode 100644
index 0000000000..bbe1167f49
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/readpixel.html
@@ -0,0 +1,26 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL ReadPixel Tests Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fReadPixelTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fReadPixelTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerobject.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerobject.html
new file mode 100644
index 0000000000..6f9187657a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerobject.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Sampler Object Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fSamplerObjectTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fSamplerObjectTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerstatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerstatequery.html
new file mode 100644
index 0000000000..c78debef2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/samplerstatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Sampler State Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fSamplerStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fSamplerStateQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderapi.html
new file mode 100644
index 0000000000..d33e78148e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderapi.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader API Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderApiTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderbuiltinvar.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderbuiltinvar.html
new file mode 100644
index 0000000000..f8a7be22e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderbuiltinvar.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Built-in Var Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderBuiltinVarTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fShaderBuiltinVarTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadercommonfunction.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadercommonfunction.html
new file mode 100644
index 0000000000..0dbad257fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadercommonfunction.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Common Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderCommonFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderCommonFunctionTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdx.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdx.html
new file mode 100644
index 0000000000..4c2c679ef4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdx.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Derivate Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderDerivateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderDerivateTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdy.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdy.html
new file mode 100644
index 0000000000..27a2da3ac1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_dfdy.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Derivate Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderDerivateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderDerivateTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_fwidth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_fwidth.html
new file mode 100644
index 0000000000..bb8b90f913
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderderivate_fwidth.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Derivate Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderDerivateTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderDerivateTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/00_test_list.txt
new file mode 100644
index 0000000000..da4d02b37d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/00_test_list.txt
@@ -0,0 +1,9 @@
+varying.html
+uniform.html
+tmp.html
+vec2.html
+vec3.html
+vec4.html
+mat_00.html
+mat_01.html
+mat_02.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_00.html
new file mode 100644
index 0000000000..2cd7e98fa2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_01.html
new file mode 100644
index 0000000000..ee6c322e31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_02.html
new file mode 100644
index 0000000000..debdc57c2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/mat_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/shaderindexing_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/shaderindexing_test_generator.py
new file mode 100644
index 0000000000..beaace3469
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/shaderindexing_test_generator.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for shaderindexing* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'varying',
+ 'uniform',
+ 'tmp',
+ 'vec2',
+ 'vec3',
+ 'vec4',
+ 'mat_00',
+ 'mat_01',
+ 'mat_02',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/tmp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/tmp.html
new file mode 100644
index 0000000000..679a8884f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/tmp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/uniform.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/uniform.html
new file mode 100644
index 0000000000..7c86a6f185
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/uniform.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/varying.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/varying.html
new file mode 100644
index 0000000000..eea9c022f8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/varying.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec2.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec2.html
new file mode 100644
index 0000000000..d2c80c1c4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec2.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec3.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec3.html
new file mode 100644
index 0000000000..aaabf027a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec3.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec4.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec4.html
new file mode 100644
index 0000000000..a896e726b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderindexing/vec4.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shaderindexing_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Indexing Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderIndexingTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderIndexingTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_do_while.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_do_while.html
new file mode 100644
index 0000000000..6b57433852
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_do_while.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Loop Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderLoopTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderLoopTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_for.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_for.html
new file mode 100644
index 0000000000..a2c5095c91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_for.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Loop Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderLoopTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderLoopTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_while.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_while.html
new file mode 100644
index 0000000000..fac36651cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderloop_while.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Loop Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderLoopTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderLoopTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/00_test_list.txt
new file mode 100644
index 0000000000..dd0bb5a550
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/00_test_list.txt
@@ -0,0 +1,33 @@
+add_const.html
+add_uniform.html
+add_dynamic.html
+sub_const.html
+sub_uniform.html
+sub_dynamic.html
+mul_const_lowp.html
+mul_const_mediump.html
+mul_const_highp.html
+mul_uniform_lowp.html
+mul_uniform_mediump.html
+mul_uniform_highp.html
+mul_dynamic_lowp.html
+mul_dynamic_mediump.html
+mul_dynamic_highp.html
+div_const.html
+div_uniform.html
+div_dynamic.html
+matrixcompmult.html
+outerproduct.html
+transpose.html
+determinant.html
+inverse.html
+unary_addition.html
+negation.html
+pre_increment.html
+pre_decrement.html
+post_increment.html
+post_decrement.html
+add_assign.html
+sub_assign.html
+mul_assign.html
+div_assign.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_assign.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_assign.html
new file mode 100644
index 0000000000..bb70e4d681
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_assign.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_const.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_const.html
new file mode 100644
index 0000000000..bf15cb29ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_const.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_dynamic.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_dynamic.html
new file mode 100644
index 0000000000..3deeb287aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_dynamic.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_uniform.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_uniform.html
new file mode 100644
index 0000000000..bf459f6c6c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/add_uniform.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/determinant.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/determinant.html
new file mode 100644
index 0000000000..5b885f8322
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/determinant.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_assign.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_assign.html
new file mode 100644
index 0000000000..2d913df799
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_assign.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_const.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_const.html
new file mode 100644
index 0000000000..a958d75036
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_const.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_dynamic.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_dynamic.html
new file mode 100644
index 0000000000..623c9a9bc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_dynamic.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_uniform.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_uniform.html
new file mode 100644
index 0000000000..4c77847c95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/div_uniform.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/inverse.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/inverse.html
new file mode 100644
index 0000000000..c14a19e2c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/inverse.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/matrixcompmult.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/matrixcompmult.html
new file mode 100644
index 0000000000..eab68d362a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/matrixcompmult.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_assign.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_assign.html
new file mode 100644
index 0000000000..771a1556b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_assign.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_highp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_highp.html
new file mode 100644
index 0000000000..80ff18f77a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_highp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_lowp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_lowp.html
new file mode 100644
index 0000000000..40559ebf7a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_lowp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_mediump.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_mediump.html
new file mode 100644
index 0000000000..21efaef930
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_const_mediump.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_highp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_highp.html
new file mode 100644
index 0000000000..e3b57badd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_highp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_lowp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_lowp.html
new file mode 100644
index 0000000000..d1d3ce1068
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_lowp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_mediump.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_mediump.html
new file mode 100644
index 0000000000..bf95faf774
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_dynamic_mediump.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_highp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_highp.html
new file mode 100644
index 0000000000..713d7d21ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_highp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_lowp.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_lowp.html
new file mode 100644
index 0000000000..8da434cd2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_lowp.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_mediump.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_mediump.html
new file mode 100644
index 0000000000..91f022cb45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/mul_uniform_mediump.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/negation.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/negation.html
new file mode 100644
index 0000000000..da0fdb831f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/negation.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/outerproduct.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/outerproduct.html
new file mode 100644
index 0000000000..1e3a5bb56a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/outerproduct.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_decrement.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_decrement.html
new file mode 100644
index 0000000000..8a5f7bd46f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_decrement.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_increment.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_increment.html
new file mode 100644
index 0000000000..a379fdb882
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/post_increment.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_decrement.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_decrement.html
new file mode 100644
index 0000000000..3921fb697f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_decrement.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_increment.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_increment.html
new file mode 100644
index 0000000000..ac06ee71b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/pre_increment.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/shadermatrix_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/shadermatrix_test_generator.py
new file mode 100644
index 0000000000..1cf1889c52
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/shadermatrix_test_generator.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for shadermatrix* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'add_const',
+ 'add_uniform',
+ 'add_dynamic',
+ 'sub_const',
+ 'sub_uniform',
+ 'sub_dynamic',
+ 'mul_const_lowp',
+ 'mul_const_mediump',
+ 'mul_const_highp',
+ 'mul_uniform_lowp',
+ 'mul_uniform_mediump',
+ 'mul_uniform_highp',
+ 'mul_dynamic_lowp',
+ 'mul_dynamic_mediump',
+ 'mul_dynamic_highp',
+ 'div_const',
+ 'div_uniform',
+ 'div_dynamic',
+ 'matrixcompmult',
+ 'outerproduct',
+ 'transpose',
+ 'determinant',
+ 'inverse',
+ 'unary_addition',
+ 'negation',
+ 'pre_increment',
+ 'pre_decrement',
+ 'post_increment',
+ 'post_decrement',
+ 'add_assign',
+ 'sub_assign',
+ 'mul_assign',
+ 'div_assign',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_assign.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_assign.html
new file mode 100644
index 0000000000..79bf1fd344
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_assign.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_const.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_const.html
new file mode 100644
index 0000000000..f574f6126b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_const.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_dynamic.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_dynamic.html
new file mode 100644
index 0000000000..4408df4743
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_dynamic.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_uniform.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_uniform.html
new file mode 100644
index 0000000000..5d7c293d0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/sub_uniform.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/transpose.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/transpose.html
new file mode 100644
index 0000000000..52465410fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/transpose.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/unary_addition.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/unary_addition.html
new file mode 100644
index 0000000000..1bcb526ebb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadermatrix/unary_addition.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadermatrix_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Matrix Test</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderMatrixTest');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderMatrixTest.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/00_test_list.txt
new file mode 100644
index 0000000000..1c197d6b8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/00_test_list.txt
@@ -0,0 +1,37 @@
+unary_operator_00.html
+unary_operator_01.html
+unary_operator_02.html
+binary_operator_00.html
+binary_operator_01.html
+binary_operator_02.html
+binary_operator_03.html
+binary_operator_04.html
+binary_operator_05.html
+binary_operator_06.html
+binary_operator_07.html
+binary_operator_08.html
+binary_operator_09.html
+binary_operator_10.html
+binary_operator_11.html
+binary_operator_12.html
+binary_operator_13.html
+binary_operator_14.html
+binary_operator_15.html
+angle_and_trigonometry_00.html
+angle_and_trigonometry_01.html
+angle_and_trigonometry_02.html
+angle_and_trigonometry_03.html
+exponential.html
+common_functions_00.html
+common_functions_01.html
+common_functions_02.html
+common_functions_03.html
+common_functions_04.html
+common_functions_05.html
+common_functions_06.html
+geometric.html
+float_compare.html
+int_compare.html
+bool_compare.html
+selection.html
+sequence.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_00.html
new file mode 100644
index 0000000000..04d3c3c26e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_00.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_01.html
new file mode 100644
index 0000000000..a342a007be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_01.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_02.html
new file mode 100644
index 0000000000..a7273c649a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_02.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_03.html
new file mode 100644
index 0000000000..6ca3ef247f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/angle_and_trigonometry_03.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_00.html
new file mode 100644
index 0000000000..35fb8043c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_00.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_01.html
new file mode 100644
index 0000000000..3740edea2c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_01.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_02.html
new file mode 100644
index 0000000000..1834fec65a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_02.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_03.html
new file mode 100644
index 0000000000..d4b3afca33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_03.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_04.html
new file mode 100644
index 0000000000..bcc0d964da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_04.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_05.html
new file mode 100644
index 0000000000..6f5a189327
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_05.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_06.html
new file mode 100644
index 0000000000..f5f2c1d8a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_06.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_07.html
new file mode 100644
index 0000000000..eb5933dc1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_07.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_08.html
new file mode 100644
index 0000000000..4a5726c562
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_08.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_09.html
new file mode 100644
index 0000000000..c64fd1d6c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_09.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_10.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_10.html
new file mode 100644
index 0000000000..16bc768646
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_10.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_11.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_11.html
new file mode 100644
index 0000000000..98a66ffe9b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_11.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_12.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_12.html
new file mode 100644
index 0000000000..c463b6ff30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_12.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_13.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_13.html
new file mode 100644
index 0000000000..8caa497062
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_13.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_14.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_14.html
new file mode 100644
index 0000000000..245db50eef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_14.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_15.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_15.html
new file mode 100644
index 0000000000..d11b9aae53
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/binary_operator_15.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/bool_compare.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/bool_compare.html
new file mode 100644
index 0000000000..d8dbfc65b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/bool_compare.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [34, 35]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_00.html
new file mode 100644
index 0000000000..f814bad597
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_00.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_01.html
new file mode 100644
index 0000000000..1c2ce0f407
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_01.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_02.html
new file mode 100644
index 0000000000..2b81002870
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_02.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_03.html
new file mode 100644
index 0000000000..8818deae4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_03.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_04.html
new file mode 100644
index 0000000000..bbd4bbc68e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_04.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_05.html
new file mode 100644
index 0000000000..b9ea2cc1d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_05.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_06.html
new file mode 100644
index 0000000000..e818da471a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_06.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/exponential.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/exponential.html
new file mode 100644
index 0000000000..849f44f9c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/exponential.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/float_compare.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/float_compare.html
new file mode 100644
index 0000000000..3510f51f9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/float_compare.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/geometric.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/geometric.html
new file mode 100644
index 0000000000..20ba764dec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/geometric.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/int_compare.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/int_compare.html
new file mode 100644
index 0000000000..50a4222e86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/int_compare.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [33, 34]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/selection.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/selection.html
new file mode 100644
index 0000000000..dfea42d3a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/selection.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [35, 36]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/sequence.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/sequence.html
new file mode 100644
index 0000000000..e1b61ed4a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/sequence.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [36, 37]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/shaderoperator_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/shaderoperator_test_generator.py
new file mode 100644
index 0000000000..cdf21b0371
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/shaderoperator_test_generator.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for shaderoperator* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'unary_operator_00',
+ 'unary_operator_01',
+ 'unary_operator_02',
+ 'binary_operator_00',
+ 'binary_operator_01',
+ 'binary_operator_02',
+ 'binary_operator_03',
+ 'binary_operator_04',
+ 'binary_operator_05',
+ 'binary_operator_06',
+ 'binary_operator_07',
+ 'binary_operator_08',
+ 'binary_operator_09',
+ 'binary_operator_10',
+ 'binary_operator_11',
+ 'binary_operator_12',
+ 'binary_operator_13',
+ 'binary_operator_14',
+ 'binary_operator_15',
+ 'angle_and_trigonometry_00',
+ 'angle_and_trigonometry_01',
+ 'angle_and_trigonometry_02',
+ 'angle_and_trigonometry_03',
+ 'exponential',
+ 'common_functions_00',
+ 'common_functions_01',
+ 'common_functions_02',
+ 'common_functions_03',
+ 'common_functions_04',
+ 'common_functions_05',
+ 'common_functions_06',
+ 'geometric',
+ 'float_compare',
+ 'int_compare',
+ 'bool_compare',
+ 'selection',
+ 'sequence',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_00.html
new file mode 100644
index 0000000000..8e80bcd623
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_00.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_01.html
new file mode 100644
index 0000000000..3dfee32749
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_01.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_02.html
new file mode 100644
index 0000000000..1b8c5e5e03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/unary_operator_02.html
@@ -0,0 +1,33 @@
+<!--
+
+This file is auto-generated from shaderoperator_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Operator Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderOperatorTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderOperatorTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderpackingfunction.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderpackingfunction.html
new file mode 100644
index 0000000000..a07e9b1d81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderpackingfunction.html
@@ -0,0 +1,26 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Packing Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>
+goog.require('functional.gles3.es3fShaderPackingFunctionTests');
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderPackingFunctionTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_float.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_float.html
new file mode 100644
index 0000000000..ef78733716
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_float.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderPrecisionTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_int.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_int.html
new file mode 100644
index 0000000000..ec659017cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_int.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderPrecisionTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_uint.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_uint.html
new file mode 100644
index 0000000000..3097ed7b19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderprecision_uint.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Precision Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderPrecisionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderPrecisionTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstatequery.html
new file mode 100644
index 0000000000..325bb0bf25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstatequery.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader State Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderStateQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+ try {
+ functional.gles3.es3fShaderStateQueryTests.run(gl);
+ }
+ catch(err)
+ {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstruct.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstruct.html
new file mode 100644
index 0000000000..e510ceb2d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderstruct.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Struct Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderStructTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderStructTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderswitch.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderswitch.html
new file mode 100644
index 0000000000..714f9044d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderswitch.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Switch Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderSwitchTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderSwitchTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/00_test_list.txt
new file mode 100644
index 0000000000..13a12534db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/00_test_list.txt
@@ -0,0 +1,15 @@
+texture.html
+textureoffset.html
+textureproj.html
+textureprojoffset.html
+texturelod.html
+texturelodoffset.html
+textureprojlod.html
+textureprojlodoffset.html
+texturegrad.html
+texturegradoffset.html
+textureprojgrad.html
+textureprojgradoffset.html
+texelfetch.html
+texelfetchoffset.html
+texturesize.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/shadertexturefunction_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/shadertexturefunction_test_generator.py
new file mode 100644
index 0000000000..3b63359d7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/shadertexturefunction_test_generator.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for shadertexturefunction* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'texture',
+ 'textureoffset',
+ 'textureproj',
+ 'textureprojoffset',
+ 'texturelod',
+ 'texturelodoffset',
+ 'textureprojlod',
+ 'textureprojlodoffset',
+ 'texturegrad',
+ 'texturegradoffset',
+ 'textureprojgrad',
+ 'textureprojgradoffset',
+ 'texelfetch',
+ 'texelfetchoffset',
+ 'texturesize'
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetch.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetch.html
new file mode 100644
index 0000000000..6787012d51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetch.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetchoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetchoffset.html
new file mode 100644
index 0000000000..1d2e0de506
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texelfetchoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texture.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texture.html
new file mode 100644
index 0000000000..f5668b4d9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texture.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegrad.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegrad.html
new file mode 100644
index 0000000000..7ef3d92104
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegrad.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegradoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegradoffset.html
new file mode 100644
index 0000000000..c016084bf9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturegradoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelod.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelod.html
new file mode 100644
index 0000000000..928bade495
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelod.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelodoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelodoffset.html
new file mode 100644
index 0000000000..23792c3d83
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturelodoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureoffset.html
new file mode 100644
index 0000000000..61b9c6affa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureproj.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureproj.html
new file mode 100644
index 0000000000..676c7cde0c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureproj.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgrad.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgrad.html
new file mode 100644
index 0000000000..c68978abbb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgrad.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgradoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgradoffset.html
new file mode 100644
index 0000000000..d2165e4f87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojgradoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlod.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlod.html
new file mode 100644
index 0000000000..fe0fc76b2a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlod.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlodoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlodoffset.html
new file mode 100644
index 0000000000..a8d9760ab8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojlodoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojoffset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojoffset.html
new file mode 100644
index 0000000000..3b383a72da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/textureprojoffset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturesize.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturesize.html
new file mode 100644
index 0000000000..245a285b51
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shadertexturefunction/texturesize.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from shadertexturefunction_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Shader Texture Function Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fShaderTextureFunctionTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fShaderTextureFunctionTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/stringquery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/stringquery.html
new file mode 100644
index 0000000000..79045db515
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/stringquery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL String Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fStringQueryTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fStringQueryTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/sync.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/sync.html
new file mode 100644
index 0000000000..7d4c09f053
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/sync.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Fence Sync Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fSyncTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+
+ try {
+ functional.gles3.es3fSyncTests.run(gl);
+ }
+ catch(err)
+ {
+ bufferedLogToConsole(err);
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/00_test_list.txt
new file mode 100644
index 0000000000..b446b8d6da
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/00_test_list.txt
@@ -0,0 +1,116 @@
+2d_formats_00.html
+2d_formats_01.html
+2d_formats_02.html
+2d_formats_03.html
+2d_formats_04.html
+2d_formats_05.html
+2d_formats_06.html
+2d_formats_07.html
+2d_formats_08.html
+2d_formats_09.html
+2d_sizes_00.html
+2d_sizes_01.html
+2d_sizes_02.html
+2d_sizes_03.html
+2d_sizes_04.html
+2d_sizes_05.html
+2d_combinations_00.html
+2d_combinations_01.html
+2d_combinations_02.html
+2d_combinations_03.html
+2d_combinations_04.html
+2d_combinations_05.html
+cube_formats_00.html
+cube_formats_01.html
+cube_formats_02.html
+cube_formats_03.html
+cube_formats_04.html
+cube_formats_05.html
+cube_formats_06.html
+cube_formats_07.html
+cube_formats_08.html
+cube_formats_09.html
+cube_sizes_00.html
+cube_sizes_01.html
+cube_sizes_02.html
+cube_sizes_03.html
+cube_sizes_04.html
+cube_combinations_00.html
+cube_combinations_01.html
+cube_combinations_02.html
+cube_combinations_03.html
+cube_combinations_04.html
+cube_combinations_05.html
+cube_no_edges_visible.html
+2d_array_formats_00.html
+2d_array_formats_01.html
+2d_array_formats_02.html
+2d_array_formats_03.html
+2d_array_formats_04.html
+2d_array_formats_05.html
+2d_array_formats_06.html
+2d_array_formats_07.html
+2d_array_formats_08.html
+2d_array_formats_09.html
+2d_array_sizes_00.html
+2d_array_sizes_01.html
+2d_array_sizes_02.html
+2d_array_sizes_03.html
+2d_array_sizes_04.html
+2d_array_combinations_00.html
+2d_array_combinations_01.html
+2d_array_combinations_02.html
+2d_array_combinations_03.html
+2d_array_combinations_04.html
+2d_array_combinations_05.html
+3d_formats_00.html
+3d_formats_01.html
+3d_formats_02.html
+3d_formats_03.html
+3d_formats_04.html
+3d_formats_05.html
+3d_formats_06.html
+3d_formats_07.html
+3d_formats_08.html
+3d_formats_09.html
+3d_sizes_00.html
+3d_sizes_01.html
+3d_sizes_02.html
+3d_sizes_03.html
+3d_sizes_04.html
+3d_combinations_00.html
+3d_combinations_01.html
+3d_combinations_02.html
+3d_combinations_03.html
+3d_combinations_04.html
+3d_combinations_05.html
+3d_combinations_06.html
+3d_combinations_07.html
+3d_combinations_08.html
+3d_combinations_09.html
+3d_combinations_10.html
+3d_combinations_11.html
+3d_combinations_12.html
+3d_combinations_13.html
+3d_combinations_14.html
+3d_combinations_15.html
+3d_combinations_16.html
+3d_combinations_17.html
+3d_combinations_18.html
+3d_combinations_19.html
+3d_combinations_20.html
+3d_combinations_21.html
+3d_combinations_22.html
+3d_combinations_23.html
+3d_combinations_24.html
+3d_combinations_25.html
+3d_combinations_26.html
+3d_combinations_27.html
+3d_combinations_28.html
+3d_combinations_29.html
+3d_combinations_30.html
+3d_combinations_31.html
+3d_combinations_32.html
+3d_combinations_33.html
+3d_combinations_34.html
+3d_combinations_35.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_00.html
new file mode 100644
index 0000000000..629813355b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [59, 60]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_01.html
new file mode 100644
index 0000000000..1fd04cdb6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [60, 61]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_02.html
new file mode 100644
index 0000000000..63f3826d5e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [61, 62]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_03.html
new file mode 100644
index 0000000000..efe23d2a7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [62, 63]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_04.html
new file mode 100644
index 0000000000..5fd151fb17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [63, 64]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_05.html
new file mode 100644
index 0000000000..d6e8d71d18
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_combinations_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [64, 65]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_00.html
new file mode 100644
index 0000000000..7c822b2f57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [44, 45]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_01.html
new file mode 100644
index 0000000000..adc218a46d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [45, 46]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_02.html
new file mode 100644
index 0000000000..afb3b67375
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [46, 47]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_03.html
new file mode 100644
index 0000000000..03acb11a19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [47, 48]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_04.html
new file mode 100644
index 0000000000..b16f7e9ed2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [48, 49]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_05.html
new file mode 100644
index 0000000000..cafc3bd48d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [49, 50]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_06.html
new file mode 100644
index 0000000000..ce5e168b98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [50, 51]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_07.html
new file mode 100644
index 0000000000..d4b59de12a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [51, 52]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_08.html
new file mode 100644
index 0000000000..121f0f74e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_08.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [52, 53]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_09.html
new file mode 100644
index 0000000000..f306f70d80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_formats_09.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [53, 54]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_00.html
new file mode 100644
index 0000000000..ce7c08c57b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [54, 55]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_01.html
new file mode 100644
index 0000000000..c83ad21fc3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [55, 56]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_02.html
new file mode 100644
index 0000000000..5c930d71c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [56, 57]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_03.html
new file mode 100644
index 0000000000..e131614e10
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [57, 58]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_04.html
new file mode 100644
index 0000000000..651e97d04b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_array_sizes_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [58, 59]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_00.html
new file mode 100644
index 0000000000..b594c81df2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_01.html
new file mode 100644
index 0000000000..f875ddc124
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_02.html
new file mode 100644
index 0000000000..51150be084
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_03.html
new file mode 100644
index 0000000000..e22d0d44d9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_04.html
new file mode 100644
index 0000000000..e94ffc04f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_05.html
new file mode 100644
index 0000000000..429ae6e3e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_combinations_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_00.html
new file mode 100644
index 0000000000..4b58c6f787
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_01.html
new file mode 100644
index 0000000000..ef0d419d3a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_02.html
new file mode 100644
index 0000000000..f670313845
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_03.html
new file mode 100644
index 0000000000..fc10d2db75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_04.html
new file mode 100644
index 0000000000..95227c1dd4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_05.html
new file mode 100644
index 0000000000..0397fbf6b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_06.html
new file mode 100644
index 0000000000..7eb40d1433
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_07.html
new file mode 100644
index 0000000000..a236ac7c5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_08.html
new file mode 100644
index 0000000000..8a29fe723c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_08.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_09.html
new file mode 100644
index 0000000000..4ae8227647
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_formats_09.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_00.html
new file mode 100644
index 0000000000..8d2e2d736a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_01.html
new file mode 100644
index 0000000000..87bc3f9a6a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_02.html
new file mode 100644
index 0000000000..b4a9c90102
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_03.html
new file mode 100644
index 0000000000..3831e58a2e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_04.html
new file mode 100644
index 0000000000..77ce5f6b12
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_05.html
new file mode 100644
index 0000000000..64f1b65a2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/2d_sizes_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_00.html
new file mode 100644
index 0000000000..e833feff80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [80, 81]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_01.html
new file mode 100644
index 0000000000..141193d5ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [81, 82]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_02.html
new file mode 100644
index 0000000000..4913ab35eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [82, 83]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_03.html
new file mode 100644
index 0000000000..b60af0ea21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [83, 84]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_04.html
new file mode 100644
index 0000000000..5e4892249a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [84, 85]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_05.html
new file mode 100644
index 0000000000..d87584684f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [85, 86]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_06.html
new file mode 100644
index 0000000000..b1c2c808cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [86, 87]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_07.html
new file mode 100644
index 0000000000..79a2be951b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [87, 88]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_08.html
new file mode 100644
index 0000000000..c32a25ab79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_08.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [88, 89]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_09.html
new file mode 100644
index 0000000000..aa4c3c50d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_09.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [89, 90]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_10.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_10.html
new file mode 100644
index 0000000000..3872150b75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_10.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [90, 91]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_11.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_11.html
new file mode 100644
index 0000000000..30763a2ea7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_11.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [91, 92]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_12.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_12.html
new file mode 100644
index 0000000000..f252f529e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_12.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [92, 93]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_13.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_13.html
new file mode 100644
index 0000000000..6c3e9b135e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_13.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [93, 94]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_14.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_14.html
new file mode 100644
index 0000000000..b4cb0d7573
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_14.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [94, 95]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_15.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_15.html
new file mode 100644
index 0000000000..2c4590dd41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_15.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [95, 96]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_16.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_16.html
new file mode 100644
index 0000000000..c0838fc3f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_16.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [96, 97]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_17.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_17.html
new file mode 100644
index 0000000000..48e924daae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_17.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [97, 98]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_18.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_18.html
new file mode 100644
index 0000000000..9cd79ceb5b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_18.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [98, 99]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_19.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_19.html
new file mode 100644
index 0000000000..e224822c62
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_19.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [99, 100]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_20.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_20.html
new file mode 100644
index 0000000000..2c959a811a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_20.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [100, 101]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_21.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_21.html
new file mode 100644
index 0000000000..78c6f0a3d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_21.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [101, 102]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_22.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_22.html
new file mode 100644
index 0000000000..9980e3a3a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_22.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [102, 103]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_23.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_23.html
new file mode 100644
index 0000000000..08c647aff0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_23.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [103, 104]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_24.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_24.html
new file mode 100644
index 0000000000..fe81630d42
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_24.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [104, 105]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_25.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_25.html
new file mode 100644
index 0000000000..aa0cff3737
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_25.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [105, 106]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_26.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_26.html
new file mode 100644
index 0000000000..a3423dcbc4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_26.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [106, 107]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_27.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_27.html
new file mode 100644
index 0000000000..071c36672e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_27.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [107, 108]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_28.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_28.html
new file mode 100644
index 0000000000..07d17edcf4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_28.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [108, 109]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_29.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_29.html
new file mode 100644
index 0000000000..cd7f63e14c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_29.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [109, 110]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_30.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_30.html
new file mode 100644
index 0000000000..56988bd046
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_30.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [110, 111]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_31.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_31.html
new file mode 100644
index 0000000000..286ace3917
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_31.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [111, 112]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_32.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_32.html
new file mode 100644
index 0000000000..1ba0ae432b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_32.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [112, 113]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_33.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_33.html
new file mode 100644
index 0000000000..19cb29fb4a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_33.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [113, 114]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_34.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_34.html
new file mode 100644
index 0000000000..5afb122414
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_34.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [114, 115]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_35.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_35.html
new file mode 100644
index 0000000000..1411f68e0f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_combinations_35.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [115, 116]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_00.html
new file mode 100644
index 0000000000..1b41ca237d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [65, 66]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_01.html
new file mode 100644
index 0000000000..c8059f7e39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [66, 67]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_02.html
new file mode 100644
index 0000000000..6529aec830
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [67, 68]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_03.html
new file mode 100644
index 0000000000..249860cee7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [68, 69]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_04.html
new file mode 100644
index 0000000000..0bb0aab1ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [69, 70]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_05.html
new file mode 100644
index 0000000000..dba6d0f666
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [70, 71]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_06.html
new file mode 100644
index 0000000000..df06c3c1e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [71, 72]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_07.html
new file mode 100644
index 0000000000..827ceba0c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [72, 73]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_08.html
new file mode 100644
index 0000000000..695d317ecb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_08.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [73, 74]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_09.html
new file mode 100644
index 0000000000..72e7b41419
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_formats_09.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [74, 75]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_00.html
new file mode 100644
index 0000000000..7ff8170258
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [75, 76]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_01.html
new file mode 100644
index 0000000000..6263ae9413
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [76, 77]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_02.html
new file mode 100644
index 0000000000..17e7a30c55
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [77, 78]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_03.html
new file mode 100644
index 0000000000..c888db7145
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [78, 79]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_04.html
new file mode 100644
index 0000000000..d1f4a5f869
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/3d_sizes_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [79, 80]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_00.html
new file mode 100644
index 0000000000..21e59eea02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [37, 38]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_01.html
new file mode 100644
index 0000000000..9833f0f84e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [38, 39]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_02.html
new file mode 100644
index 0000000000..8fc0017864
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [39, 40]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_03.html
new file mode 100644
index 0000000000..f80bc00d80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [40, 41]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_04.html
new file mode 100644
index 0000000000..2d69ac867b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [41, 42]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_05.html
new file mode 100644
index 0000000000..ea6bbb755c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_combinations_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [42, 43]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_00.html
new file mode 100644
index 0000000000..e228874f75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_01.html
new file mode 100644
index 0000000000..f9c966e680
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_02.html
new file mode 100644
index 0000000000..bf9c256bed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_03.html
new file mode 100644
index 0000000000..d3f78a46cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_04.html
new file mode 100644
index 0000000000..eb07dea652
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_05.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_05.html
new file mode 100644
index 0000000000..d7ccb2c171
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_05.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_06.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_06.html
new file mode 100644
index 0000000000..1496707baa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_06.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_07.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_07.html
new file mode 100644
index 0000000000..2683e71ea6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_07.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_08.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_08.html
new file mode 100644
index 0000000000..d69dcfae64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_08.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_09.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_09.html
new file mode 100644
index 0000000000..f34e51e8f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_formats_09.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_no_edges_visible.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_no_edges_visible.html
new file mode 100644
index 0000000000..531df3bb98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_no_edges_visible.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [43, 44]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_00.html
new file mode 100644
index 0000000000..4e4fe4dfa4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_01.html
new file mode 100644
index 0000000000..a4db3fc04c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [33, 34]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_02.html
new file mode 100644
index 0000000000..cf7ac7644d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [34, 35]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_03.html
new file mode 100644
index 0000000000..6b8d94c51f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [35, 36]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_04.html
new file mode 100644
index 0000000000..b1260c751f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/cube_sizes_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [36, 37]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/texturefiltering_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/texturefiltering_test_generator.py
new file mode 100644
index 0000000000..0b6064c8ca
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturefiltering/texturefiltering_test_generator.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for texturefilter* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from texturefiltering_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Filtering Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFilteringTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFilteringTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_FILTERABLE_FORMAT_COUNT = 10
+_SIZE_2D_COUNT = 6
+_SIZE_CUBE_COUNT = 5
+_SIZE_2D_ARRAY_COUNT = 5
+_SIZE_3D_COUNT = 5
+_MIN_FILTER_MODE_COUNT = 6
+_MAG_FILTER_MODE_COUNT = 2
+_WRAP_MODE_COUNT = 3
+
+_GROUPS = [
+ '2d_formats',
+ '2d_sizes',
+ '2d_combinations',
+ 'cube_formats',
+ 'cube_sizes',
+ 'cube_combinations',
+ 'cube_no_edges_visible',
+ '2d_array_formats',
+ '2d_array_sizes',
+ '2d_array_combinations',
+ '3d_formats',
+ '3d_sizes',
+ '3d_combinations'
+]
+
+_GROUP_TEST_COUNTS = [
+ _FILTERABLE_FORMAT_COUNT, # 2d_formats
+ _SIZE_2D_COUNT, # 2d_sizes
+ _MIN_FILTER_MODE_COUNT, # 2d_combinations
+ _FILTERABLE_FORMAT_COUNT, # cube_formats
+ _SIZE_CUBE_COUNT, # cube_sizes
+ _MIN_FILTER_MODE_COUNT, # cube_combinations
+ 1, # cube_no_edges_visible
+ _FILTERABLE_FORMAT_COUNT, # 2d_array_formats
+ _SIZE_2D_ARRAY_COUNT, # 2d_array_sizes
+ _MIN_FILTER_MODE_COUNT, # 2d_array_combinations
+ _FILTERABLE_FORMAT_COUNT, # 3d_formats
+ _SIZE_3D_COUNT, # 3d_sizes,
+ _MIN_FILTER_MODE_COUNT * _MAG_FILTER_MODE_COUNT * _WRAP_MODE_COUNT, # 3d_combinations
+]
+
+def GenerateFilename(group, count, index):
+ """Generate test filename."""
+ assert index >= 0 and index < count
+ filename = group
+ if count > 1:
+ index_str = str(index)
+ if index < 10:
+ index_str = "0" + index_str
+ filename += "_" + index_str
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ assert len(_GROUPS) == len(_GROUP_TEST_COUNTS)
+ test_index = 0
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ group = _GROUPS[ii]
+ count = _GROUP_TEST_COUNTS[ii]
+ for index in range(count):
+ filename = GenerateFilename(group, count, index)
+ filelist.append(filename)
+ WriteTest(filename, test_index, test_index + 1)
+ test_index += 1
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/00_test_list.txt
new file mode 100644
index 0000000000..cbd63eb92d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/00_test_list.txt
@@ -0,0 +1,38 @@
+unsized_2d.html
+unsized_2d_array.html
+unsized_3d.html
+sized_color_2d_pot_00.html
+sized_color_2d_pot_01.html
+sized_color_2d_pot_02.html
+sized_color_2d_pot_03.html
+sized_color_2d_npot_00.html
+sized_color_2d_npot_01.html
+sized_color_2d_npot_02.html
+sized_color_2d_npot_03.html
+sized_color_cube_pot_00.html
+sized_color_cube_pot_01.html
+sized_color_cube_pot_02.html
+sized_color_cube_pot_03.html
+sized_color_cube_npot_00.html
+sized_color_cube_npot_01.html
+sized_color_cube_npot_02.html
+sized_color_cube_npot_03.html
+sized_color_2d_array_pot_00.html
+sized_color_2d_array_pot_01.html
+sized_color_2d_array_pot_02.html
+sized_color_2d_array_pot_03.html
+sized_color_2d_array_npot_00.html
+sized_color_2d_array_npot_01.html
+sized_color_2d_array_npot_02.html
+sized_color_2d_array_npot_03.html
+sized_color_3d_pot_00.html
+sized_color_3d_pot_01.html
+sized_color_3d_pot_02.html
+sized_color_3d_pot_03.html
+sized_color_3d_npot_00.html
+sized_color_3d_npot_01.html
+sized_color_3d_npot_02.html
+sized_color_3d_npot_03.html
+sized_depth_stencil.html
+compressed_2d.html
+compressed_cube.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_2d.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_2d.html
new file mode 100644
index 0000000000..8f104f0ffc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_2d.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [36, 37]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_cube.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_cube.html
new file mode 100644
index 0000000000..39e7f2055e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/compressed_cube.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [37, 38]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_00.html
new file mode 100644
index 0000000000..c0867d87a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_01.html
new file mode 100644
index 0000000000..8f143eaf74
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_02.html
new file mode 100644
index 0000000000..92a8b2c98e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_03.html
new file mode 100644
index 0000000000..55fea6907d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_npot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_00.html
new file mode 100644
index 0000000000..975fb089b9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_01.html
new file mode 100644
index 0000000000..11267669c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_02.html
new file mode 100644
index 0000000000..26190a4f79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_03.html
new file mode 100644
index 0000000000..6d42808253
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_array_pot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_00.html
new file mode 100644
index 0000000000..c0cea16d87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_01.html
new file mode 100644
index 0000000000..ca38325a3c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_02.html
new file mode 100644
index 0000000000..04c3e0fbcf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_03.html
new file mode 100644
index 0000000000..e63de3ae2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_npot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_00.html
new file mode 100644
index 0000000000..d880ac7196
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_01.html
new file mode 100644
index 0000000000..e65f1f851e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_02.html
new file mode 100644
index 0000000000..64d4715d2f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_03.html
new file mode 100644
index 0000000000..67140d7f79
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_2d_pot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_00.html
new file mode 100644
index 0000000000..4b1eed3a10
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_01.html
new file mode 100644
index 0000000000..9adf66b652
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_02.html
new file mode 100644
index 0000000000..6f6dd722e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [33, 34]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_03.html
new file mode 100644
index 0000000000..8d2f6ed044
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_npot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [34, 35]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_00.html
new file mode 100644
index 0000000000..c1d3dedd38
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_01.html
new file mode 100644
index 0000000000..e33bb5ea91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_02.html
new file mode 100644
index 0000000000..f28f2589dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_03.html
new file mode 100644
index 0000000000..a6028c9290
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_3d_pot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_00.html
new file mode 100644
index 0000000000..1e6403f3f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_01.html
new file mode 100644
index 0000000000..9b79dd1932
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_02.html
new file mode 100644
index 0000000000..d3bfde6336
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_03.html
new file mode 100644
index 0000000000..7a9f7b3618
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_npot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_00.html
new file mode 100644
index 0000000000..9f88f7e572
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_01.html
new file mode 100644
index 0000000000..6f24c6d8eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_02.html
new file mode 100644
index 0000000000..3ce93d65a6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_03.html
new file mode 100644
index 0000000000..fcbf8d6493
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_color_cube_pot_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_depth_stencil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_depth_stencil.html
new file mode 100644
index 0000000000..bca1fbfbc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/sized_depth_stencil.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [35, 36]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/textureformat_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/textureformat_test_generator.py
new file mode 100644
index 0000000000..ba20f04899
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/textureformat_test_generator.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for textureformat* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'unsized_2d',
+ 'unsized_2d_array',
+ 'unsized_3d',
+ 'sized_color_2d_pot_00',
+ 'sized_color_2d_pot_01',
+ 'sized_color_2d_pot_02',
+ 'sized_color_2d_pot_03',
+ 'sized_color_2d_npot_00',
+ 'sized_color_2d_npot_01',
+ 'sized_color_2d_npot_02',
+ 'sized_color_2d_npot_03',
+ 'sized_color_cube_pot_00',
+ 'sized_color_cube_pot_01',
+ 'sized_color_cube_pot_02',
+ 'sized_color_cube_pot_03',
+ 'sized_color_cube_npot_00',
+ 'sized_color_cube_npot_01',
+ 'sized_color_cube_npot_02',
+ 'sized_color_cube_npot_03',
+ 'sized_color_2d_array_pot_00',
+ 'sized_color_2d_array_pot_01',
+ 'sized_color_2d_array_pot_02',
+ 'sized_color_2d_array_pot_03',
+ 'sized_color_2d_array_npot_00',
+ 'sized_color_2d_array_npot_01',
+ 'sized_color_2d_array_npot_02',
+ 'sized_color_2d_array_npot_03',
+ 'sized_color_3d_pot_00',
+ 'sized_color_3d_pot_01',
+ 'sized_color_3d_pot_02',
+ 'sized_color_3d_pot_03',
+ 'sized_color_3d_npot_00',
+ 'sized_color_3d_npot_01',
+ 'sized_color_3d_npot_02',
+ 'sized_color_3d_npot_03',
+ 'sized_depth_stencil',
+ 'compressed_2d',
+ 'compressed_cube',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d.html
new file mode 100644
index 0000000000..447e4387f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d_array.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d_array.html
new file mode 100644
index 0000000000..6eaeb451e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_2d_array.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_3d.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_3d.html
new file mode 100644
index 0000000000..8fe25fde1a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureformat/unsized_3d.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureformat_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureFormatTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="300" height="300"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureFormatTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/00_test_list.txt
new file mode 100644
index 0000000000..48498b565e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/00_test_list.txt
@@ -0,0 +1,144 @@
+2d_nearest_less_or_equal.html
+2d_nearest_greater_or_equal.html
+2d_nearest_less.html
+2d_nearest_greater.html
+2d_nearest_equal.html
+2d_nearest_not_equal.html
+2d_nearest_always.html
+2d_nearest_never.html
+2d_linear_less_or_equal.html
+2d_linear_greater_or_equal.html
+2d_linear_less.html
+2d_linear_greater.html
+2d_linear_equal.html
+2d_linear_not_equal.html
+2d_linear_always.html
+2d_linear_never.html
+2d_nearest_mipmap_nearest_less_or_equal.html
+2d_nearest_mipmap_nearest_greater_or_equal.html
+2d_nearest_mipmap_nearest_less.html
+2d_nearest_mipmap_nearest_greater.html
+2d_nearest_mipmap_nearest_equal.html
+2d_nearest_mipmap_nearest_not_equal.html
+2d_nearest_mipmap_nearest_always.html
+2d_nearest_mipmap_nearest_never.html
+2d_linear_mipmap_nearest_less_or_equal.html
+2d_linear_mipmap_nearest_greater_or_equal.html
+2d_linear_mipmap_nearest_less.html
+2d_linear_mipmap_nearest_greater.html
+2d_linear_mipmap_nearest_equal.html
+2d_linear_mipmap_nearest_not_equal.html
+2d_linear_mipmap_nearest_always.html
+2d_linear_mipmap_nearest_never.html
+2d_nearest_mipmap_linear_less_or_equal.html
+2d_nearest_mipmap_linear_greater_or_equal.html
+2d_nearest_mipmap_linear_less.html
+2d_nearest_mipmap_linear_greater.html
+2d_nearest_mipmap_linear_equal.html
+2d_nearest_mipmap_linear_not_equal.html
+2d_nearest_mipmap_linear_always.html
+2d_nearest_mipmap_linear_never.html
+2d_linear_mipmap_linear_less_or_equal.html
+2d_linear_mipmap_linear_greater_or_equal.html
+2d_linear_mipmap_linear_less.html
+2d_linear_mipmap_linear_greater.html
+2d_linear_mipmap_linear_equal.html
+2d_linear_mipmap_linear_not_equal.html
+2d_linear_mipmap_linear_always.html
+2d_linear_mipmap_linear_never.html
+cube_nearest_less_or_equal.html
+cube_nearest_greater_or_equal.html
+cube_nearest_less.html
+cube_nearest_greater.html
+cube_nearest_equal.html
+cube_nearest_not_equal.html
+cube_nearest_always.html
+cube_nearest_never.html
+cube_linear_less_or_equal.html
+cube_linear_greater_or_equal.html
+cube_linear_less.html
+cube_linear_greater.html
+cube_linear_equal.html
+cube_linear_not_equal.html
+cube_linear_always.html
+cube_linear_never.html
+cube_nearest_mipmap_nearest_less_or_equal.html
+cube_nearest_mipmap_nearest_greater_or_equal.html
+cube_nearest_mipmap_nearest_less.html
+cube_nearest_mipmap_nearest_greater.html
+cube_nearest_mipmap_nearest_equal.html
+cube_nearest_mipmap_nearest_not_equal.html
+cube_nearest_mipmap_nearest_always.html
+cube_nearest_mipmap_nearest_never.html
+cube_linear_mipmap_nearest_less_or_equal.html
+cube_linear_mipmap_nearest_greater_or_equal.html
+cube_linear_mipmap_nearest_less.html
+cube_linear_mipmap_nearest_greater.html
+cube_linear_mipmap_nearest_equal.html
+cube_linear_mipmap_nearest_not_equal.html
+cube_linear_mipmap_nearest_always.html
+cube_linear_mipmap_nearest_never.html
+cube_nearest_mipmap_linear_less_or_equal.html
+cube_nearest_mipmap_linear_greater_or_equal.html
+cube_nearest_mipmap_linear_less.html
+cube_nearest_mipmap_linear_greater.html
+cube_nearest_mipmap_linear_equal.html
+cube_nearest_mipmap_linear_not_equal.html
+cube_nearest_mipmap_linear_always.html
+cube_nearest_mipmap_linear_never.html
+cube_linear_mipmap_linear_less_or_equal.html
+cube_linear_mipmap_linear_greater_or_equal.html
+cube_linear_mipmap_linear_less.html
+cube_linear_mipmap_linear_greater.html
+cube_linear_mipmap_linear_equal.html
+cube_linear_mipmap_linear_not_equal.html
+cube_linear_mipmap_linear_always.html
+cube_linear_mipmap_linear_never.html
+2d_array_nearest_less_or_equal.html
+2d_array_nearest_greater_or_equal.html
+2d_array_nearest_less.html
+2d_array_nearest_greater.html
+2d_array_nearest_equal.html
+2d_array_nearest_not_equal.html
+2d_array_nearest_always.html
+2d_array_nearest_never.html
+2d_array_linear_less_or_equal.html
+2d_array_linear_greater_or_equal.html
+2d_array_linear_less.html
+2d_array_linear_greater.html
+2d_array_linear_equal.html
+2d_array_linear_not_equal.html
+2d_array_linear_always.html
+2d_array_linear_never.html
+2d_array_nearest_mipmap_nearest_less_or_equal.html
+2d_array_nearest_mipmap_nearest_greater_or_equal.html
+2d_array_nearest_mipmap_nearest_less.html
+2d_array_nearest_mipmap_nearest_greater.html
+2d_array_nearest_mipmap_nearest_equal.html
+2d_array_nearest_mipmap_nearest_not_equal.html
+2d_array_nearest_mipmap_nearest_always.html
+2d_array_nearest_mipmap_nearest_never.html
+2d_array_linear_mipmap_nearest_less_or_equal.html
+2d_array_linear_mipmap_nearest_greater_or_equal.html
+2d_array_linear_mipmap_nearest_less.html
+2d_array_linear_mipmap_nearest_greater.html
+2d_array_linear_mipmap_nearest_equal.html
+2d_array_linear_mipmap_nearest_not_equal.html
+2d_array_linear_mipmap_nearest_always.html
+2d_array_linear_mipmap_nearest_never.html
+2d_array_nearest_mipmap_linear_less_or_equal.html
+2d_array_nearest_mipmap_linear_greater_or_equal.html
+2d_array_nearest_mipmap_linear_less.html
+2d_array_nearest_mipmap_linear_greater.html
+2d_array_nearest_mipmap_linear_equal.html
+2d_array_nearest_mipmap_linear_not_equal.html
+2d_array_nearest_mipmap_linear_always.html
+2d_array_nearest_mipmap_linear_never.html
+2d_array_linear_mipmap_linear_less_or_equal.html
+2d_array_linear_mipmap_linear_greater_or_equal.html
+2d_array_linear_mipmap_linear_less.html
+2d_array_linear_mipmap_linear_greater.html
+2d_array_linear_mipmap_linear_equal.html
+2d_array_linear_mipmap_linear_not_equal.html
+2d_array_linear_mipmap_linear_always.html
+2d_array_linear_mipmap_linear_never.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_always.html
new file mode 100644
index 0000000000..683a50a80c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [110, 111]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_equal.html
new file mode 100644
index 0000000000..9031d2180d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [108, 109]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater.html
new file mode 100644
index 0000000000..9ef3900ea1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [107, 108]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater_or_equal.html
new file mode 100644
index 0000000000..51914257e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [105, 106]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less.html
new file mode 100644
index 0000000000..924315e72f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [106, 107]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less_or_equal.html
new file mode 100644
index 0000000000..877f3ae810
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [104, 105]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_always.html
new file mode 100644
index 0000000000..0495e7e3b0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [142, 143]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_equal.html
new file mode 100644
index 0000000000..c40fceded9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [140, 141]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater.html
new file mode 100644
index 0000000000..b813379c3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [139, 140]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater_or_equal.html
new file mode 100644
index 0000000000..01b90b1316
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [137, 138]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less.html
new file mode 100644
index 0000000000..ea6d12246a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [138, 139]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less_or_equal.html
new file mode 100644
index 0000000000..da5c45dc87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [136, 137]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_never.html
new file mode 100644
index 0000000000..6c7177d4eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [143, 144]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_not_equal.html
new file mode 100644
index 0000000000..ece2898683
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [141, 142]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_always.html
new file mode 100644
index 0000000000..d9ce0da356
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [126, 127]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_equal.html
new file mode 100644
index 0000000000..969dd028ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [124, 125]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater.html
new file mode 100644
index 0000000000..e6cdc2aba7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [123, 124]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..8f3ab4a2a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [121, 122]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less.html
new file mode 100644
index 0000000000..12cbf4d71d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [122, 123]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less_or_equal.html
new file mode 100644
index 0000000000..aa16ca2d03
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [120, 121]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_never.html
new file mode 100644
index 0000000000..ff8c6b4e7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [127, 128]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_not_equal.html
new file mode 100644
index 0000000000..b12597025a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_mipmap_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [125, 126]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_never.html
new file mode 100644
index 0000000000..aaf630f95e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [111, 112]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_not_equal.html
new file mode 100644
index 0000000000..b5f37b7a24
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [109, 110]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_always.html
new file mode 100644
index 0000000000..87e30ba530
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [102, 103]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_equal.html
new file mode 100644
index 0000000000..0121ae0c6f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [100, 101]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater.html
new file mode 100644
index 0000000000..a407700531
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [99, 100]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..2b838e0da0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [97, 98]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less.html
new file mode 100644
index 0000000000..b5e56cdc35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [98, 99]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less_or_equal.html
new file mode 100644
index 0000000000..3980fcd889
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [96, 97]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_always.html
new file mode 100644
index 0000000000..fe782c37a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [134, 135]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_equal.html
new file mode 100644
index 0000000000..57838d838e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [132, 133]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater.html
new file mode 100644
index 0000000000..ac85fd057d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [131, 132]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater_or_equal.html
new file mode 100644
index 0000000000..17074cb881
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [129, 130]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less.html
new file mode 100644
index 0000000000..849a0787c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [130, 131]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less_or_equal.html
new file mode 100644
index 0000000000..4ed680906e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [128, 129]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_never.html
new file mode 100644
index 0000000000..484b3b7a37
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [135, 136]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_not_equal.html
new file mode 100644
index 0000000000..7611bba2b3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [133, 134]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_always.html
new file mode 100644
index 0000000000..e80d611a21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [118, 119]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_equal.html
new file mode 100644
index 0000000000..0c8af699cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [116, 117]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater.html
new file mode 100644
index 0000000000..58d3f537f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [115, 116]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..26a3ca0c7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [113, 114]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less.html
new file mode 100644
index 0000000000..fc9895c7c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [114, 115]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less_or_equal.html
new file mode 100644
index 0000000000..82f5381db4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [112, 113]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_never.html
new file mode 100644
index 0000000000..2959de11e8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [119, 120]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_not_equal.html
new file mode 100644
index 0000000000..d2d2a1657d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [117, 118]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_never.html
new file mode 100644
index 0000000000..970b393e8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [103, 104]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_not_equal.html
new file mode 100644
index 0000000000..cc52419bb6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_array_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [101, 102]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_always.html
new file mode 100644
index 0000000000..0c072e4e9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_equal.html
new file mode 100644
index 0000000000..1c358069a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater.html
new file mode 100644
index 0000000000..65109bfc8c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater_or_equal.html
new file mode 100644
index 0000000000..b9065cde43
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less.html
new file mode 100644
index 0000000000..d4d98b914b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less_or_equal.html
new file mode 100644
index 0000000000..e0d4c1584f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_always.html
new file mode 100644
index 0000000000..a71e2d2e48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [46, 47]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_equal.html
new file mode 100644
index 0000000000..03e604163a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [44, 45]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater.html
new file mode 100644
index 0000000000..e0e163e2eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [43, 44]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater_or_equal.html
new file mode 100644
index 0000000000..7498d0b29d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [41, 42]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less.html
new file mode 100644
index 0000000000..8c9c018e5a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [42, 43]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less_or_equal.html
new file mode 100644
index 0000000000..0e23db2efb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [40, 41]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_never.html
new file mode 100644
index 0000000000..519746474a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [47, 48]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_not_equal.html
new file mode 100644
index 0000000000..53a9c44a7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [45, 46]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_always.html
new file mode 100644
index 0000000000..879a5eec9c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_equal.html
new file mode 100644
index 0000000000..6ddfb4a88c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater.html
new file mode 100644
index 0000000000..89f48e479c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..79962393e1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less.html
new file mode 100644
index 0000000000..f2207075cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less_or_equal.html
new file mode 100644
index 0000000000..a600187ebe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_never.html
new file mode 100644
index 0000000000..1d499f8c73
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_not_equal.html
new file mode 100644
index 0000000000..522a65e41d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_mipmap_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_never.html
new file mode 100644
index 0000000000..b7368c2759
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_not_equal.html
new file mode 100644
index 0000000000..490692b4d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_always.html
new file mode 100644
index 0000000000..d811685f8e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_equal.html
new file mode 100644
index 0000000000..f6574fe35c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater.html
new file mode 100644
index 0000000000..1b6df673ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..064388f636
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less.html
new file mode 100644
index 0000000000..1efa1a01a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less_or_equal.html
new file mode 100644
index 0000000000..10196bf59f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_always.html
new file mode 100644
index 0000000000..c799aa9ff7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [38, 39]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_equal.html
new file mode 100644
index 0000000000..cd0dd6a1d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [36, 37]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater.html
new file mode 100644
index 0000000000..5bd98c0677
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [35, 36]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater_or_equal.html
new file mode 100644
index 0000000000..dee22dc3e7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [33, 34]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less.html
new file mode 100644
index 0000000000..8b954a55a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [34, 35]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less_or_equal.html
new file mode 100644
index 0000000000..b6eb41c0ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_never.html
new file mode 100644
index 0000000000..be55dd6c41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [39, 40]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_not_equal.html
new file mode 100644
index 0000000000..996cb8a393
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [37, 38]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_always.html
new file mode 100644
index 0000000000..1eef513bef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_equal.html
new file mode 100644
index 0000000000..793c544c6f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater.html
new file mode 100644
index 0000000000..426e431255
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..4eca9eb327
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less.html
new file mode 100644
index 0000000000..a4324c2447
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less_or_equal.html
new file mode 100644
index 0000000000..b63b148823
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_never.html
new file mode 100644
index 0000000000..5e74f10bb2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_not_equal.html
new file mode 100644
index 0000000000..804b2e3ae9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_mipmap_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_never.html
new file mode 100644
index 0000000000..de447dac45
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_not_equal.html
new file mode 100644
index 0000000000..fa8977bf91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/2d_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_always.html
new file mode 100644
index 0000000000..846d6ee7e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [62, 63]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_equal.html
new file mode 100644
index 0000000000..829e0977f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [60, 61]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater.html
new file mode 100644
index 0000000000..1035f86428
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [59, 60]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater_or_equal.html
new file mode 100644
index 0000000000..e287605818
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [57, 58]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less.html
new file mode 100644
index 0000000000..cae8affb2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [58, 59]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less_or_equal.html
new file mode 100644
index 0000000000..c7ad559722
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [56, 57]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_always.html
new file mode 100644
index 0000000000..6bc8a946df
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [94, 95]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_equal.html
new file mode 100644
index 0000000000..c3cc8ca0e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [92, 93]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater.html
new file mode 100644
index 0000000000..0294b65acb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [91, 92]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater_or_equal.html
new file mode 100644
index 0000000000..d19866502b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [89, 90]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less.html
new file mode 100644
index 0000000000..4d3c98cb08
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [90, 91]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less_or_equal.html
new file mode 100644
index 0000000000..2972d989a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [88, 89]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_never.html
new file mode 100644
index 0000000000..7015dec4fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [95, 96]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_not_equal.html
new file mode 100644
index 0000000000..d67b0d5f7f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [93, 94]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_always.html
new file mode 100644
index 0000000000..a22b92d412
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [78, 79]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_equal.html
new file mode 100644
index 0000000000..2102e56dcb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [76, 77]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater.html
new file mode 100644
index 0000000000..80ed0e3b41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [75, 76]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..e590f76bb8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [73, 74]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less.html
new file mode 100644
index 0000000000..63d99bd97f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [74, 75]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less_or_equal.html
new file mode 100644
index 0000000000..53bdba5ff5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [72, 73]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_never.html
new file mode 100644
index 0000000000..fffe6fe452
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [79, 80]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_not_equal.html
new file mode 100644
index 0000000000..1ddeb39d91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_mipmap_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [77, 78]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_never.html
new file mode 100644
index 0000000000..b96321fe1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [63, 64]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_not_equal.html
new file mode 100644
index 0000000000..0c663cdaf1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [61, 62]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_always.html
new file mode 100644
index 0000000000..de25c5ef0b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [54, 55]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_equal.html
new file mode 100644
index 0000000000..6a76cb062a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [52, 53]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater.html
new file mode 100644
index 0000000000..d5fa0b62d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [51, 52]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..b7e7085da2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [49, 50]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less.html
new file mode 100644
index 0000000000..47c4b34d17
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [50, 51]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less_or_equal.html
new file mode 100644
index 0000000000..1c9f005c0a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [48, 49]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_always.html
new file mode 100644
index 0000000000..14af11c511
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [86, 87]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_equal.html
new file mode 100644
index 0000000000..96c1e1d586
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [84, 85]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater.html
new file mode 100644
index 0000000000..f7e1087a86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [83, 84]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater_or_equal.html
new file mode 100644
index 0000000000..be1773c2e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [81, 82]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less.html
new file mode 100644
index 0000000000..e4aa08d139
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [82, 83]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less_or_equal.html
new file mode 100644
index 0000000000..fe6705c20a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [80, 81]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_never.html
new file mode 100644
index 0000000000..34bc00816d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [87, 88]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_not_equal.html
new file mode 100644
index 0000000000..8d7a900a77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_linear_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [85, 86]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_always.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_always.html
new file mode 100644
index 0000000000..610869e06a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_always.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [70, 71]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_equal.html
new file mode 100644
index 0000000000..59a878d1d0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [68, 69]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater.html
new file mode 100644
index 0000000000..dc788bc5f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [67, 68]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater_or_equal.html
new file mode 100644
index 0000000000..e7e86e9cc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_greater_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [65, 66]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less.html
new file mode 100644
index 0000000000..cdb64a95ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [66, 67]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less_or_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less_or_equal.html
new file mode 100644
index 0000000000..26b6db723f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_less_or_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [64, 65]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_never.html
new file mode 100644
index 0000000000..8d71e5859f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [71, 72]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_not_equal.html
new file mode 100644
index 0000000000..6e681695fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_mipmap_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [69, 70]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_never.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_never.html
new file mode 100644
index 0000000000..15d5b531f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_never.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [55, 56]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_not_equal.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_not_equal.html
new file mode 100644
index 0000000000..3a3a41ddb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/cube_nearest_not_equal.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [53, 54]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/textureshadow_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/textureshadow_test_generator.py
new file mode 100644
index 0000000000..4ead80de86
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/textureshadow/textureshadow_test_generator.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for textureformat* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Shadow Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureShadowTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureShadowTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_TARGETS = [
+ '2d',
+ 'cube',
+ '2d_array',
+]
+
+_FILTERS = [
+ 'nearest',
+ 'linear',
+ 'nearest_mipmap_nearest',
+ 'linear_mipmap_nearest',
+ 'nearest_mipmap_linear',
+ 'linear_mipmap_linear',
+]
+
+_COMPARE_FUNCS = [
+ 'less_or_equal',
+ 'greater_or_equal',
+ 'less',
+ 'greater',
+ 'equal',
+ 'not_equal',
+ 'always',
+ 'never',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ ii = 0
+ for iTarget in range(len(_TARGETS)):
+ for iFilter in range(len(_FILTERS)):
+ for iFunc in range(len(_COMPARE_FUNCS)):
+ item = _TARGETS[iTarget] + '_' + _FILTERS[iFilter] + '_' + _COMPARE_FUNCS[iFunc]
+ filename = GenerateFilename(item)
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ ii = ii + 1
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/00_test_list.txt
new file mode 100644
index 0000000000..b3f8275d99
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/00_test_list.txt
@@ -0,0 +1,90 @@
+basic_teximage2d_2d_00.html
+basic_teximage2d_2d_01.html
+basic_teximage2d_cube_00.html
+basic_teximage2d_cube_01.html
+basic_teximage2d_cube_02.html
+basic_teximage2d_cube_03.html
+basic_teximage2d_cube_04.html
+random_teximage2d_2d.html
+random_teximage2d_cube.html
+teximage2d_align.html
+teximage2d_unpack_params.html
+teximage2d_pbo_2d_00.html
+teximage2d_pbo_2d_01.html
+teximage2d_pbo_cube_00.html
+teximage2d_pbo_cube_01.html
+teximage2d_pbo_cube_02.html
+teximage2d_pbo_cube_03.html
+teximage2d_pbo_cube_04.html
+teximage2d_pbo_params.html
+teximage2d_depth.html
+teximage2d_depth_pbo.html
+basic_texsubimage2d_2d_00.html
+basic_texsubimage2d_2d_01.html
+basic_texsubimage2d_2d_02.html
+basic_texsubimage2d_cube_00.html
+basic_texsubimage2d_cube_01.html
+basic_texsubimage2d_cube_02.html
+basic_texsubimage2d_cube_03.html
+basic_texsubimage2d_cube_04.html
+texsubimage2d_empty_tex.html
+texsubimage2d_align.html
+texsubimage2d_unpack_params.html
+texsubimage2d_pbo_2d_00.html
+texsubimage2d_pbo_2d_01.html
+texsubimage2d_pbo_cube_00.html
+texsubimage2d_pbo_cube_01.html
+texsubimage2d_pbo_cube_02.html
+texsubimage2d_pbo_cube_03.html
+texsubimage2d_pbo_cube_04.html
+texsubimage2d_pbo_params.html
+texsubimage2d_depth.html
+basic_copyteximage2d.html
+basic_copytexsubimage2d.html
+basic_teximage3d_2d_array_00.html
+basic_teximage3d_2d_array_01.html
+basic_teximage3d_2d_array_02.html
+basic_teximage3d_3d_00.html
+basic_teximage3d_3d_01.html
+basic_teximage3d_3d_02.html
+basic_teximage3d_3d_03.html
+basic_teximage3d_3d_04.html
+teximage3d_unpack_params.html
+teximage3d_pbo_2d_array_00.html
+teximage3d_pbo_2d_array_01.html
+teximage3d_pbo_3d_00.html
+teximage3d_pbo_3d_01.html
+teximage3d_pbo_params.html
+teximage3d_depth.html
+teximage3d_depth_pbo.html
+basic_texsubimage3d_00.html
+basic_texsubimage3d_01.html
+basic_texsubimage3d_02.html
+basic_texsubimage3d_03.html
+basic_texsubimage3d_04.html
+texsubimage3d_unpack_params.html
+texsubimage3d_pbo_2d_array_00.html
+texsubimage3d_pbo_2d_array_01.html
+texsubimage3d_pbo_3d_00.html
+texsubimage3d_pbo_3d_01.html
+texsubimage3d_pbo_params.html
+texsubimage3d_depth.html
+texstorage2d_format_2d_00.html
+texstorage2d_format_2d_01.html
+texstorage2d_format_2d_02.html
+texstorage2d_format_cube_00.html
+texstorage2d_format_cube_01.html
+texstorage2d_format_cube_02.html
+texstorage2d_format_cube_03.html
+texstorage2d_format_cube_04.html
+texstorage2d_format_depth_stencil.html
+texstorage2d_format_size.html
+texstorage3d_format_2d_array_00.html
+texstorage3d_format_2d_array_01.html
+texstorage3d_format_2d_array_02.html
+texstorage3d_format_3d_00.html
+texstorage3d_format_3d_01.html
+texstorage3d_format_3d_02.html
+texstorage3d_format_3d_03.html
+texstorage3d_format_depth_stencil.html
+texstorage3d_format_size.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copyteximage2d.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copyteximage2d.html
new file mode 100644
index 0000000000..8ad04f6a33
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copyteximage2d.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [41, 42]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copytexsubimage2d.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copytexsubimage2d.html
new file mode 100644
index 0000000000..01832d5e8f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_copytexsubimage2d.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [42, 43]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_00.html
new file mode 100644
index 0000000000..25a3941fd4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_01.html
new file mode 100644
index 0000000000..7258bb0f2c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_2d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_00.html
new file mode 100644
index 0000000000..a0b44fa064
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_01.html
new file mode 100644
index 0000000000..1d59fd011e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_02.html
new file mode 100644
index 0000000000..01fbabc0bd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_03.html
new file mode 100644
index 0000000000..c1f662fb71
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_04.html
new file mode 100644
index 0000000000..1c0cbda645
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage2d_cube_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_00.html
new file mode 100644
index 0000000000..04f5f82a89
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [43, 44]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_01.html
new file mode 100644
index 0000000000..fe6dbec66c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [44, 45]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_02.html
new file mode 100644
index 0000000000..b33f5c0dc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_2d_array_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [45, 46]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_00.html
new file mode 100644
index 0000000000..330a980b9e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [46, 47]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_01.html
new file mode 100644
index 0000000000..ebe8449990
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [47, 48]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_02.html
new file mode 100644
index 0000000000..941e6d3689
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [48, 49]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_03.html
new file mode 100644
index 0000000000..49bd666589
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [49, 50]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_04.html
new file mode 100644
index 0000000000..b35f582c31
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_teximage3d_3d_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [50, 51]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_00.html
new file mode 100644
index 0000000000..2c9ab82a97
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_01.html
new file mode 100644
index 0000000000..1ce8c4ed69
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_02.html
new file mode 100644
index 0000000000..ab339cc79e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_2d_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_00.html
new file mode 100644
index 0000000000..5152b59266
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_01.html
new file mode 100644
index 0000000000..519387bf4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_02.html
new file mode 100644
index 0000000000..f2d88d3094
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_03.html
new file mode 100644
index 0000000000..e32a550b44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_04.html
new file mode 100644
index 0000000000..263e5da5d1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage2d_cube_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_00.html
new file mode 100644
index 0000000000..c418c167b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [59, 60]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_01.html
new file mode 100644
index 0000000000..f24c56e383
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [60, 61]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_02.html
new file mode 100644
index 0000000000..8d761c9391
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [61, 62]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_03.html
new file mode 100644
index 0000000000..f04cd395a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [62, 63]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_04.html
new file mode 100644
index 0000000000..036df5fe25
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/basic_texsubimage3d_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [63, 64]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_2d.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_2d.html
new file mode 100644
index 0000000000..d166152cea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_2d.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_cube.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_cube.html
new file mode 100644
index 0000000000..b7fcc77142
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/random_teximage2d_cube.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_align.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_align.html
new file mode 100644
index 0000000000..bf844178ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_align.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth.html
new file mode 100644
index 0000000000..6b2e31b76e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth_pbo.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth_pbo.html
new file mode 100644
index 0000000000..0ccf52ba1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_depth_pbo.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_00.html
new file mode 100644
index 0000000000..4df9f6a0d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_01.html
new file mode 100644
index 0000000000..26f503dbb1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_00.html
new file mode 100644
index 0000000000..c0b7ce461e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_01.html
new file mode 100644
index 0000000000..24e3ebb47a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_02.html
new file mode 100644
index 0000000000..76f74ebf99
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_03.html
new file mode 100644
index 0000000000..cfc63dcf44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_04.html
new file mode 100644
index 0000000000..5f26f61bb0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_params.html
new file mode 100644
index 0000000000..cb4c7b87a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_pbo_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_unpack_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_unpack_params.html
new file mode 100644
index 0000000000..43fdf383a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage2d_unpack_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth.html
new file mode 100644
index 0000000000..a6a6691a87
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [57, 58]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth_pbo.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth_pbo.html
new file mode 100644
index 0000000000..d8ec29d395
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_depth_pbo.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [58, 59]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html
new file mode 100644
index 0000000000..2b963af9b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [52, 53]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html
new file mode 100644
index 0000000000..4a3c9e3175
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [53, 54]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html
new file mode 100644
index 0000000000..472621dc96
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [54, 55]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html
new file mode 100644
index 0000000000..4275a1c0b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [55, 56]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_params.html
new file mode 100644
index 0000000000..213bc831d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_pbo_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [56, 57]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_unpack_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_unpack_params.html
new file mode 100644
index 0000000000..9bfd6c2157
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/teximage3d_unpack_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [51, 52]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_00.html
new file mode 100644
index 0000000000..dfa571683b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [71, 72]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_01.html
new file mode 100644
index 0000000000..d764993f39
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [72, 73]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_02.html
new file mode 100644
index 0000000000..53077e684b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_2d_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [73, 74]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_00.html
new file mode 100644
index 0000000000..f8a4c6c8a4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [74, 75]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_01.html
new file mode 100644
index 0000000000..d56154d30b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [75, 76]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_02.html
new file mode 100644
index 0000000000..c575c39d6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [76, 77]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_03.html
new file mode 100644
index 0000000000..8b4a767530
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [77, 78]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_04.html
new file mode 100644
index 0000000000..2e9aa10486
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_cube_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [78, 79]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_depth_stencil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_depth_stencil.html
new file mode 100644
index 0000000000..e2454c4475
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_depth_stencil.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [79, 80]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_size.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_size.html
new file mode 100644
index 0000000000..0d7bb7c009
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage2d_format_size.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [80, 81]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_00.html
new file mode 100644
index 0000000000..b7792d85b5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [81, 82]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_01.html
new file mode 100644
index 0000000000..de3140514e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [82, 83]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_02.html
new file mode 100644
index 0000000000..831b7ba386
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_2d_array_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [83, 84]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_00.html
new file mode 100644
index 0000000000..a4bfad50ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [84, 85]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_01.html
new file mode 100644
index 0000000000..1673ca1811
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [85, 86]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_02.html
new file mode 100644
index 0000000000..cad658becf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [86, 87]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_03.html
new file mode 100644
index 0000000000..dee4ae0bf5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_3d_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [87, 88]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_depth_stencil.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_depth_stencil.html
new file mode 100644
index 0000000000..2a10ac2a94
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_depth_stencil.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [88, 89]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_size.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_size.html
new file mode 100644
index 0000000000..b681d83071
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texstorage3d_format_size.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [89, 90]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_align.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_align.html
new file mode 100644
index 0000000000..990098d190
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_align.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [30, 31]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_depth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_depth.html
new file mode 100644
index 0000000000..33194ec150
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_depth.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [40, 41]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_empty_tex.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_empty_tex.html
new file mode 100644
index 0000000000..3da5eed58c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_empty_tex.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [29, 30]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_00.html
new file mode 100644
index 0000000000..94391c252a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [32, 33]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_01.html
new file mode 100644
index 0000000000..906c70917e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [33, 34]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_00.html
new file mode 100644
index 0000000000..c96d0952c5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [34, 35]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_01.html
new file mode 100644
index 0000000000..3fd841c5cc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [35, 36]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_02.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_02.html
new file mode 100644
index 0000000000..b62a2a1579
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_02.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [36, 37]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_03.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_03.html
new file mode 100644
index 0000000000..eb6ab351b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_03.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [37, 38]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_04.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_04.html
new file mode 100644
index 0000000000..717d84018a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_04.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [38, 39]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_params.html
new file mode 100644
index 0000000000..b6e1027e0b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_pbo_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [39, 40]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_unpack_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_unpack_params.html
new file mode 100644
index 0000000000..0e341e798b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage2d_unpack_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [31, 32]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_depth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_depth.html
new file mode 100644
index 0000000000..9635f1e9c8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_depth.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [70, 71]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_00.html
new file mode 100644
index 0000000000..68443fffc2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [65, 66]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_01.html
new file mode 100644
index 0000000000..b578192827
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_2d_array_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [66, 67]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html
new file mode 100644
index 0000000000..b5adb604a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [67, 68]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html
new file mode 100644
index 0000000000..8bff387e75
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [68, 69]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_params.html
new file mode 100644
index 0000000000..cb4311db14
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_pbo_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [69, 70]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_unpack_params.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_unpack_params.html
new file mode 100644
index 0000000000..3f3f7242f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texsubimage3d_unpack_params.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [64, 65]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texturespecification_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texturespecification_test_generator.py
new file mode 100644
index 0000000000..04fd403b98
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturespecification/texturespecification_test_generator.py
@@ -0,0 +1,178 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for texturespecification* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from texturespecification_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureSpecificationTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureSpecificationTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'basic_teximage2d_2d_00',
+ 'basic_teximage2d_2d_01',
+ 'basic_teximage2d_cube_00',
+ 'basic_teximage2d_cube_01',
+ 'basic_teximage2d_cube_02',
+ 'basic_teximage2d_cube_03',
+ 'basic_teximage2d_cube_04',
+ 'random_teximage2d_2d',
+ 'random_teximage2d_cube',
+ 'teximage2d_align',
+ 'teximage2d_unpack_params',
+ 'teximage2d_pbo_2d_00',
+ 'teximage2d_pbo_2d_01',
+ 'teximage2d_pbo_cube_00',
+ 'teximage2d_pbo_cube_01',
+ 'teximage2d_pbo_cube_02',
+ 'teximage2d_pbo_cube_03',
+ 'teximage2d_pbo_cube_04',
+ 'teximage2d_pbo_params',
+ 'teximage2d_depth',
+ 'teximage2d_depth_pbo',
+ 'basic_texsubimage2d_2d_00',
+ 'basic_texsubimage2d_2d_01',
+ 'basic_texsubimage2d_2d_02',
+ 'basic_texsubimage2d_cube_00',
+ 'basic_texsubimage2d_cube_01',
+ 'basic_texsubimage2d_cube_02',
+ 'basic_texsubimage2d_cube_03',
+ 'basic_texsubimage2d_cube_04',
+ 'texsubimage2d_empty_tex',
+ 'texsubimage2d_align',
+ 'texsubimage2d_unpack_params',
+ 'texsubimage2d_pbo_2d_00',
+ 'texsubimage2d_pbo_2d_01',
+ 'texsubimage2d_pbo_cube_00',
+ 'texsubimage2d_pbo_cube_01',
+ 'texsubimage2d_pbo_cube_02',
+ 'texsubimage2d_pbo_cube_03',
+ 'texsubimage2d_pbo_cube_04',
+ 'texsubimage2d_pbo_params',
+ 'texsubimage2d_depth',
+ 'basic_copyteximage2d',
+ 'basic_copytexsubimage2d',
+ 'basic_teximage3d_2d_array_00',
+ 'basic_teximage3d_2d_array_01',
+ 'basic_teximage3d_2d_array_02',
+ 'basic_teximage3d_3d_00',
+ 'basic_teximage3d_3d_01',
+ 'basic_teximage3d_3d_02',
+ 'basic_teximage3d_3d_03',
+ 'basic_teximage3d_3d_04',
+ 'teximage3d_unpack_params',
+ 'teximage3d_pbo_2d_array_00',
+ 'teximage3d_pbo_2d_array_01',
+ 'teximage3d_pbo_3d_00',
+ 'teximage3d_pbo_3d_01',
+ 'teximage3d_pbo_params',
+ 'teximage3d_depth',
+ 'teximage3d_depth_pbo',
+ 'basic_texsubimage3d_00',
+ 'basic_texsubimage3d_01',
+ 'basic_texsubimage3d_02',
+ 'basic_texsubimage3d_03',
+ 'basic_texsubimage3d_04',
+ 'texsubimage3d_unpack_params',
+ 'texsubimage3d_pbo_2d_array_00',
+ 'texsubimage3d_pbo_2d_array_01',
+ 'texsubimage3d_pbo_3d_00',
+ 'texsubimage3d_pbo_3d_01',
+ 'texsubimage3d_pbo_params',
+ 'texsubimage3d_depth',
+ 'texstorage2d_format_2d_00',
+ 'texstorage2d_format_2d_01',
+ 'texstorage2d_format_2d_02',
+ 'texstorage2d_format_cube_00',
+ 'texstorage2d_format_cube_01',
+ 'texstorage2d_format_cube_02',
+ 'texstorage2d_format_cube_03',
+ 'texstorage2d_format_cube_04',
+ 'texstorage2d_format_depth_stencil',
+ 'texstorage2d_format_size',
+ 'texstorage3d_format_2d_array_00',
+ 'texstorage3d_format_2d_array_01',
+ 'texstorage3d_format_2d_array_02',
+ 'texstorage3d_format_3d_00',
+ 'texstorage3d_format_3d_01',
+ 'texstorage3d_format_3d_02',
+ 'texstorage3d_format_3d_03',
+ 'texstorage3d_format_depth_stencil',
+ 'texstorage3d_format_size',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturestatequery.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturestatequery.html
new file mode 100644
index 0000000000..2b6600bee2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturestatequery.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture State Query Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureStateQuery');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureStateQuery.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap.html
new file mode 100644
index 0000000000..fb19852595
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Wrap Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/00_test_list.txt
new file mode 100644
index 0000000000..7e3a90712b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/00_test_list.txt
@@ -0,0 +1,22 @@
+rgba8_pot.html
+rgba8_npot.html
+eac_r11_pot.html
+eac_r11_npot.html
+eac_signed_r11_pot.html
+eac_signed_r11_npot.html
+eac_rg11_pot.html
+eac_rg11_npot.html
+eac_signed_rg11_pot.html
+eac_signed_rg11_npot.html
+etc2_rgb8_pot.html
+etc2_rgb8_npot.html
+etc2_srgb8_pot.html
+etc2_srgb8_npot.html
+etc2_rgb8_punchthrough_alpha1_pot.html
+etc2_rgb8_punchthrough_alpha1_npot.html
+etc2_srgb8_punchthrough_alpha1_pot.html
+etc2_srgb8_punchthrough_alpha1_npot.html
+etc2_eac_rgba8_pot.html
+etc2_eac_rgba8_npot.html
+etc2_eac_srgb8_alpha8_pot.html
+etc2_eac_srgb8_alpha8_npot.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_npot.html
new file mode 100644
index 0000000000..a3cbe500a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_pot.html
new file mode 100644
index 0000000000..6c51aa998a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_r11_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_npot.html
new file mode 100644
index 0000000000..0a1ae8f924
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_pot.html
new file mode 100644
index 0000000000..9d4bf2c3ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_rg11_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_npot.html
new file mode 100644
index 0000000000..c7aeca4798
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_pot.html
new file mode 100644
index 0000000000..0cb75e22e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_r11_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_npot.html
new file mode 100644
index 0000000000..6905c76775
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_pot.html
new file mode 100644
index 0000000000..83f3a8b536
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/eac_signed_rg11_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_npot.html
new file mode 100644
index 0000000000..c3ab4caa48
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_pot.html
new file mode 100644
index 0000000000..86d1dcd030
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_rgba8_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_npot.html
new file mode 100644
index 0000000000..25c6bebb04
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_pot.html
new file mode 100644
index 0000000000..8ffef8a6ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_eac_srgb8_alpha8_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_npot.html
new file mode 100644
index 0000000000..c69e8adb3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_pot.html
new file mode 100644
index 0000000000..79cc6398ff
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_npot.html
new file mode 100644
index 0000000000..09d8c01167
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_pot.html
new file mode 100644
index 0000000000..07b5cf209d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_rgb8_punchthrough_alpha1_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_npot.html
new file mode 100644
index 0000000000..d2cb034ccd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_pot.html
new file mode 100644
index 0000000000..6f124f0489
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_npot.html
new file mode 100644
index 0000000000..e6d38338be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_pot.html
new file mode 100644
index 0000000000..27af094ed2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/etc2_srgb8_punchthrough_alpha1_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_npot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_npot.html
new file mode 100644
index 0000000000..c05a40607b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_npot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_pot.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_pot.html
new file mode 100644
index 0000000000..eeb9b4639d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/rgba8_pot.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/texturewrap_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/texturewrap_test_generator.py
new file mode 100644
index 0000000000..112c39958d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/texturewrap/texturewrap_test_generator.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for textureformat* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from texturewrap_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Texture Specification Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTextureWrapTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fTextureWrapTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'rgba8_pot',
+ 'rgba8_npot',
+ 'eac_r11_pot',
+ 'eac_r11_npot',
+ 'eac_signed_r11_pot',
+ 'eac_signed_r11_npot',
+ 'eac_rg11_pot',
+ 'eac_rg11_npot',
+ 'eac_signed_rg11_pot',
+ 'eac_signed_rg11_npot',
+ 'etc2_rgb8_pot',
+ 'etc2_rgb8_npot',
+ 'etc2_srgb8_pot',
+ 'etc2_srgb8_npot',
+ 'etc2_rgb8_punchthrough_alpha1_pot',
+ 'etc2_rgb8_punchthrough_alpha1_npot',
+ 'etc2_srgb8_punchthrough_alpha1_pot',
+ 'etc2_srgb8_punchthrough_alpha1_npot',
+ 'etc2_eac_rgba8_pot',
+ 'etc2_eac_rgba8_npot',
+ 'etc2_eac_srgb8_alpha8_pot',
+ 'etc2_eac_srgb8_alpha8_npot',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/00_test_list.txt
new file mode 100644
index 0000000000..79daefed54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/00_test_list.txt
@@ -0,0 +1,29 @@
+position.html
+point_size.html
+basic_types_separate_points.html
+basic_types_separate_lines.html
+basic_types_separate_triangles.html
+basic_types_interleaved_points.html
+basic_types_interleaved_lines.html
+basic_types_interleaved_triangles.html
+array_separate_points.html
+array_separate_lines.html
+array_separate_triangles.html
+array_interleaved_points.html
+array_interleaved_lines.html
+array_interleaved_triangles.html
+array_element_separate_points.html
+array_element_separate_lines.html
+array_element_separate_triangles.html
+array_element_interleaved_points.html
+array_element_interleaved_lines.html
+array_element_interleaved_triangles.html
+interpolation_smooth.html
+interpolation_flat.html
+interpolation_centroid.html
+random_separate_points.html
+random_separate_lines.html
+random_separate_triangles.html
+random_interleaved_points.html
+random_interleaved_lines.html
+random_interleaved_triangles.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_lines.html
new file mode 100644
index 0000000000..3bf5e0cb2d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_points.html
new file mode 100644
index 0000000000..4adc875438
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_triangles.html
new file mode 100644
index 0000000000..5fbdf00bc3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_interleaved_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_lines.html
new file mode 100644
index 0000000000..37667c6b22
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_points.html
new file mode 100644
index 0000000000..f92dd2551e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_triangles.html
new file mode 100644
index 0000000000..4bf5cf9590
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_element_separate_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_lines.html
new file mode 100644
index 0000000000..534b088d35
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_points.html
new file mode 100644
index 0000000000..fa08538f2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html
new file mode 100644
index 0000000000..5fea527b76
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_lines.html
new file mode 100644
index 0000000000..092e6e003f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_points.html
new file mode 100644
index 0000000000..c8a7ad95cb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_triangles.html
new file mode 100644
index 0000000000..79d4b7450d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/array_separate_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html
new file mode 100644
index 0000000000..66653a97b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html
new file mode 100644
index 0000000000..ed753da5a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html
new file mode 100644
index 0000000000..fc1f239126
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html
new file mode 100644
index 0000000000..191655141e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_points.html
new file mode 100644
index 0000000000..64be415928
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html
new file mode 100644
index 0000000000..1d73630fb3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_centroid.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_centroid.html
new file mode 100644
index 0000000000..ebceb16db2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_centroid.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_flat.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_flat.html
new file mode 100644
index 0000000000..5a3529867d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_flat.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_smooth.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_smooth.html
new file mode 100644
index 0000000000..39464ee263
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/interpolation_smooth.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/point_size.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/point_size.html
new file mode 100644
index 0000000000..b6391bff6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/point_size.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/position.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/position.html
new file mode 100644
index 0000000000..6b4dc6f0ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/position.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_lines.html
new file mode 100644
index 0000000000..7f63bfdcf7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [27, 28]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_points.html
new file mode 100644
index 0000000000..039029c0a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html
new file mode 100644
index 0000000000..57798a4356
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [28, 29]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_lines.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_lines.html
new file mode 100644
index 0000000000..66bfea802f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_lines.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_points.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_points.html
new file mode 100644
index 0000000000..3cd6f520ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_points.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_triangles.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_triangles.html
new file mode 100644
index 0000000000..ab221ef053
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/random_separate_triangles.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/transformfeedback_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/transformfeedback_test_generator.py
new file mode 100644
index 0000000000..cf89cb1cab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/transformfeedback/transformfeedback_test_generator.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for textureformat* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from textureshadow_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Transform Feedback Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fTransformFeedbackTests');</script>
+<script>goog.require('framework.opengl.gluVarTypeUtil');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="320" height="240"></canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', {preserveDrawingBuffer: true}, 2);
+
+functional.gles3.es3fTransformFeedbackTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'position',
+ 'point_size',
+ 'basic_types_separate_points',
+ 'basic_types_separate_lines',
+ 'basic_types_separate_triangles',
+ 'basic_types_interleaved_points',
+ 'basic_types_interleaved_lines',
+ 'basic_types_interleaved_triangles',
+ 'array_separate_points',
+ 'array_separate_lines',
+ 'array_separate_triangles',
+ 'array_interleaved_points',
+ 'array_interleaved_lines',
+ 'array_interleaved_triangles',
+ 'array_element_separate_points',
+ 'array_element_separate_lines',
+ 'array_element_separate_triangles',
+ 'array_element_interleaved_points',
+ 'array_element_interleaved_lines',
+ 'array_element_interleaved_triangles',
+ 'interpolation_smooth',
+ 'interpolation_flat',
+ 'interpolation_centroid',
+ 'random_separate_points',
+ 'random_separate_lines',
+ 'random_separate_triangles',
+ 'random_interleaved_points',
+ 'random_interleaved_lines',
+ 'random_interleaved_triangles'
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for i in xrange(len(_GROUPS)):
+ groupname = _GROUPS[i]
+ filename = GenerateFilename(groupname)
+ filelist.append(filename)
+ WriteTest(filename, i, i+1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi.html
new file mode 100644
index 0000000000..7ab136f5f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform API Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformApiTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/00_test_list.txt
new file mode 100644
index 0000000000..98735207bf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/00_test_list.txt
@@ -0,0 +1,4 @@
+info_query.html
+value_initial.html
+value_assigned.html
+random.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/info_query.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/info_query.html
new file mode 100644
index 0000000000..cb777e875f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/info_query.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformapi_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform API Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformApiTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/random.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/random.html
new file mode 100644
index 0000000000..69a20c6d4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/random.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformapi_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform API Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformApiTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/uniformapi_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/uniformapi_test_generator.py
new file mode 100644
index 0000000000..2092c562d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/uniformapi_test_generator.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for uniformapi* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from uniformapi_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform API Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformApiTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'info_query',
+ 'value_initial',
+ 'value_assigned',
+ 'random',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_assigned.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_assigned.html
new file mode 100644
index 0000000000..9cce796e6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_assigned.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformapi_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform API Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformApiTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_initial.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_initial.html
new file mode 100644
index 0000000000..0244c70cd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformapi/value_initial.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformapi_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform API Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformApiTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformApiTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/00_test_list.txt
new file mode 100644
index 0000000000..dd35e89981
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/00_test_list.txt
@@ -0,0 +1,10 @@
+single_basic_type.html
+single_basic_array.html
+single_struct.html
+single_struct_array.html
+single_nested_struct.html
+single_nested_struct_array.html
+instance_array_basic_type.html
+multi_basic_types.html
+multi_nested_struct.html
+random.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/instance_array_basic_type.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/instance_array_basic_type.html
new file mode 100644
index 0000000000..8b768722b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/instance_array_basic_type.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_basic_types.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_basic_types.html
new file mode 100644
index 0000000000..205e276ff7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_basic_types.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_nested_struct.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_nested_struct.html
new file mode 100644
index 0000000000..115256955e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/multi_nested_struct.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/random.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/random.html
new file mode 100644
index 0000000000..a1d1bf6858
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/random.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_array.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_array.html
new file mode 100644
index 0000000000..3458c3918b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_array.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_type.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_type.html
new file mode 100644
index 0000000000..a0ebbed798
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_basic_type.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct.html
new file mode 100644
index 0000000000..7a33d8731a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct_array.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct_array.html
new file mode 100644
index 0000000000..006fdf9cd3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_nested_struct_array.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct.html
new file mode 100644
index 0000000000..4977f64919
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct_array.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct_array.html
new file mode 100644
index 0000000000..cb39bbfec5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/single_struct_array.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/uniformbuffers_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/uniformbuffers_test_generator.py
new file mode 100644
index 0000000000..dbf97f7ff8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/uniformbuffers/uniformbuffers_test_generator.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for uniformbuffers* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from uniformbuffers_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Uniform Block Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fUniformBlockTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fUniformBlockTests.run([%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'single_basic_type',
+ 'single_basic_array',
+ 'single_struct',
+ 'single_struct_array',
+ 'single_nested_struct',
+ 'single_nested_struct_array',
+ 'instance_array_basic_type',
+ 'multi_basic_types',
+ 'multi_nested_struct',
+ 'random',
+]
+
+def GenerateFilename(group):
+ """Generate test filename."""
+ filename = group
+ filename += ".html"
+ return filename
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ for ii in range(len(_GROUPS)):
+ filename = GenerateFilename(_GROUPS[ii])
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrayobject.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrayobject.html
new file mode 100644
index 0000000000..e6888b059e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrayobject.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Array Object Conformance Tests</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../closure-library/closure/goog/base.js"></script>
+<script src="../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayObjectTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayObjectTests.run(gl);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/00_test_list.txt
new file mode 100644
index 0000000000..f06de02f82
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/00_test_list.txt
@@ -0,0 +1,27 @@
+single_attribute.stride.html
+single_attribute.normalize.html
+single_attribute.output_type.float.html
+single_attribute.output_type.short.html
+single_attribute.output_type.byte.html
+single_attribute.output_type.unsigned_short.html
+single_attribute.output_type.unsigned_byte.html
+single_attribute.output_type.unsigned_int.html
+single_attribute.output_type.int.html
+single_attribute.output_type.half.html
+single_attribute.output_type.unsigned_int_2_10_10_10.html
+single_attribute.output_type.int_2_10_10_10.html
+single_attribute.usage.static_draw.html
+single_attribute.usage.stream_draw.html
+single_attribute.usage.dynamic_draw.html
+single_attribute.usage.static_copy.html
+single_attribute.usage.stream_copy.html
+single_attribute.usage.dynamic_copy.html
+single_attribute.usage.static_read.html
+single_attribute.usage.stream_read.html
+single_attribute.usage.dynamic_read.html
+single_attribute.offset.html
+single_attribute.first.html
+multiple_attributes.count.html
+multiple_attributes.storage.html
+multiple_attributes.stride.html
+multiple_attributes.output.html \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.count.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.count.html
new file mode 100644
index 0000000000..be380c95ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.count.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [23, 24]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.output.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.output.html
new file mode 100644
index 0000000000..37ff4a8420
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.output.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [26, 27]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.storage.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.storage.html
new file mode 100644
index 0000000000..2dda458009
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.storage.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [24, 25]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.stride.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.stride.html
new file mode 100644
index 0000000000..8913a2d93f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/multiple_attributes.stride.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [25, 26]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.first.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.first.html
new file mode 100644
index 0000000000..dd2b1a23b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.first.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [22, 23]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.normalize.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.normalize.html
new file mode 100644
index 0000000000..c92890a97c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.normalize.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [1, 2]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.offset.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.offset.html
new file mode 100644
index 0000000000..6b9286c1ab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.offset.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [21, 22]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.byte.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.byte.html
new file mode 100644
index 0000000000..0babde2587
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.byte.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [4, 5]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.float.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.float.html
new file mode 100644
index 0000000000..a4cd67561b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.float.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [2, 3]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.half.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.half.html
new file mode 100644
index 0000000000..95740244a7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.half.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [9, 10]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int.html
new file mode 100644
index 0000000000..ec3f4903c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [8, 9]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int_2_10_10_10.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int_2_10_10_10.html
new file mode 100644
index 0000000000..95eff6d999
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.int_2_10_10_10.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [11, 12]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.short.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.short.html
new file mode 100644
index 0000000000..ff6cbffa9f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.short.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [3, 4]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_byte.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_byte.html
new file mode 100644
index 0000000000..1ef3deb9d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_byte.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [6, 7]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int.html
new file mode 100644
index 0000000000..efff6a628e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [7, 8]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int_2_10_10_10.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int_2_10_10_10.html
new file mode 100644
index 0000000000..9b90ae1ed7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_int_2_10_10_10.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [10, 11]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_short.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_short.html
new file mode 100644
index 0000000000..bf56c355ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.output_type.unsigned_short.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [5, 6]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.stride.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.stride.html
new file mode 100644
index 0000000000..46bd9e2036
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.stride.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [0, 1]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_copy.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_copy.html
new file mode 100644
index 0000000000..347834c74c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_copy.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [17, 18]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_draw.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_draw.html
new file mode 100644
index 0000000000..dab5982daf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_draw.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [14, 15]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_read.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_read.html
new file mode 100644
index 0000000000..8d868ce6a1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_read.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [20, 21]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_copy.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_copy.html
new file mode 100644
index 0000000000..0c1c286164
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_copy.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [15, 16]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_draw.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_draw.html
new file mode 100644
index 0000000000..eb3bb61265
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_draw.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [12, 13]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_read.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_read.html
new file mode 100644
index 0000000000..bfed3a9bfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.static_read.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [18, 19]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_copy.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_copy.html
new file mode 100644
index 0000000000..f7c63d107f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_copy.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [16, 17]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_draw.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_draw.html
new file mode 100644
index 0000000000..238ce5e14e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_draw.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [13, 14]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_read.html b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_read.html
new file mode 100644
index 0000000000..6dd2a736c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_read.html
@@ -0,0 +1,31 @@
+<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [19, 20]);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/vertexarrays_test_generator.py b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/vertexarrays_test_generator.py
new file mode 100644
index 0000000000..de781ccafc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/vertexarrays/vertexarrays_test_generator.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for vertexarrays* tests.
+ This file needs to be run in its folder.
+"""
+
+import sys
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from vertexarrays_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_HTML_TEMPLATE = """<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Vertex Arrays Conformance Tests</title>
+<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
+<script src="../../../../js/js-test-pre.js"></script>
+<script src="../../../../js/webgl-test-utils.js"></script>
+
+<script src="../../../../closure-library/closure/goog/base.js"></script>
+<script src="../../../deqp-deps.js"></script>
+<script>goog.require('functional.gles3.es3fVertexArrayTests');</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="200" height="100"> </canvas>
+<script>
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('canvas', null, 2);
+
+functional.gles3.es3fVertexArrayTests.run(gl, [%(start)s, %(end)s]);
+</script>
+</body>
+</html>
+"""
+
+_GROUPS = [
+ 'single_attribute.stride',
+ 'single_attribute.normalize',
+ 'single_attribute.output_type.float',
+ 'single_attribute.output_type.short',
+ 'single_attribute.output_type.byte',
+ 'single_attribute.output_type.unsigned_short',
+ 'single_attribute.output_type.unsigned_byte',
+ 'single_attribute.output_type.unsigned_int',
+ 'single_attribute.output_type.int',
+ 'single_attribute.output_type.half',
+ 'single_attribute.output_type.unsigned_int_2_10_10_10',
+ 'single_attribute.output_type.int_2_10_10_10',
+ 'single_attribute.usage.static_draw',
+ 'single_attribute.usage.stream_draw',
+ 'single_attribute.usage.dynamic_draw',
+ 'single_attribute.usage.static_copy',
+ 'single_attribute.usage.stream_copy',
+ 'single_attribute.usage.dynamic_copy',
+ 'single_attribute.usage.static_read',
+ 'single_attribute.usage.stream_read',
+ 'single_attribute.usage.dynamic_read',
+ 'single_attribute.offset',
+ 'single_attribute.first',
+ 'multiple_attributes.count',
+ 'multiple_attributes.storage',
+ 'multiple_attributes.stride',
+ 'multiple_attributes.output',
+]
+
+def WriteTest(filename, start, end):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_DO_NOT_EDIT_WARNING)
+ file.write(_HTML_TEMPLATE % {
+ 'start': start,
+ 'end': end
+ })
+ file.close
+
+def GenerateTests():
+ """Generate all tests."""
+ filelist = []
+ ii = 0
+ for ii in range(len(_GROUPS)):
+ filename = _GROUPS[ii] + ".html"
+ filelist.append(filename)
+ WriteTest(filename, ii, ii + 1)
+ return filelist
+
+def GenerateTestList(filelist):
+ file = open("00_test_list.txt", "wb")
+ file.write('\n'.join(filelist))
+ file.close
+
+def main(argv):
+ """This is the main function."""
+ filelist = GenerateTests()
+ GenerateTestList(filelist)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/genHTMLfromTest.py b/dom/canvas/test/webgl-conf/checkout/deqp/genHTMLfromTest.py
new file mode 100644
index 0000000000..47ad28ccc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/genHTMLfromTest.py
@@ -0,0 +1,43 @@
+import os
+import re
+
+# Generate an HTML file for each .test file in the current directory
+#
+
+TEST_LIST_FILE = '00_test_list.txt';
+TEMPLATE = 'template.html';
+
+def genHTML(template, test):
+ contents = re.sub('___TEST_NAME___', "'" + test + "'", template);
+ filename = test + '.html';
+ print "Generating " + filename;
+ with open(test + '.html', 'w') as f:
+ f.write(contents);
+ return filename;
+
+
+def process_test_files(template):
+ generated = [];
+ files = os.listdir(os.getcwd());
+ for file in files:
+ found = re.search('(^[^.].*)\.test$', file);
+ if found:
+ generated.append(genHTML(template,found.group(1)));
+ return generated;
+
+def readTemplate():
+ contents = None;
+ with open(TEMPLATE, 'r') as f:
+ contents = f.read();
+ return contents;
+
+
+template = readTemplate();
+if (template):
+ test_list = process_test_files(template);
+ print "Generating " + TEST_LIST_FILE;
+ with open(TEST_LIST_FILE, 'w') as f:
+ for item in test_list:
+ f.write(item + '\n');
+else:
+ print "Couldn't find template file: " + TEMPLATE;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsAttributeLocationTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsAttributeLocationTests.js
new file mode 100644
index 0000000000..5ba033ffc0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsAttributeLocationTests.js
@@ -0,0 +1,1477 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL (ES) Module
+ * -----------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Attribute location tests
+ *//*--------------------------------------------------------------------*/
+
+'use strict';
+goog.provide('modules.shared.glsAttributeLocationTests');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+
+ var glsAttributeLocationTests = modules.shared.glsAttributeLocationTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var tcuStringTemplate = framework.common.tcuStringTemplate;
+
+ /**
+ * @param {Array<number>} bindings
+ * @param {string} attrib
+ * @return {number}
+ */
+ glsAttributeLocationTests.getBoundLocation = function(bindings, attrib) {
+ return (bindings[attrib] === undefined ? glsAttributeLocationTests.LocationEnum.UNDEF : bindings[attrib]);
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @param {Array<number>} bindings
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.hasAttributeAliasing = function(attributes, bindings) {
+ /** @type {Array<boolean>} */ var reservedSpaces = [];
+
+ /** @type {number} */ var location;
+ /** @type {number} */ var size;
+
+ for (var attribNdx = 0; attribNdx < attributes.length; attribNdx++) {
+ location = glsAttributeLocationTests.getBoundLocation(bindings, attributes[attribNdx].getName());
+ size = attributes[attribNdx].getType().getLocationSize();
+
+ if (location != glsAttributeLocationTests.LocationEnum.UNDEF) {
+
+ for (var i = 0; i < size; i++) {
+ if (reservedSpaces[location + i])
+ return true;
+ reservedSpaces[location + i] = true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsAttributeLocationTests.getMaxAttributeLocations = function() {
+ /** @type {number} */ var maxAttribs;
+ maxAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+ return maxAttribs;
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @return {string}
+ */
+ glsAttributeLocationTests.generateAttributeDefinitions = function(attributes) {
+ /** @type {string} */ var src = '';
+
+ for (var i = 0; i < attributes.length; i++) {
+ if (attributes[i].getLayoutLocation() != glsAttributeLocationTests.LocationEnum.UNDEF)
+ src += ('layout(location = ' + attributes[i].getLayoutLocation() + ') ');
+
+ src += '${VTX_INPUT} mediump ';
+ src += (attributes[i].getType().getName() + ' ');
+ src += attributes[i].getName();
+ src += (attributes[i].getArraySize() != glsAttributeLocationTests.ArrayEnum.NOT ?
+ '[' + attributes[i].getArraySize() + ']' : '');
+ src += ';\n';
+ }
+
+ return src;
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @return {string}
+ */
+ glsAttributeLocationTests.generateConditionUniformDefinitions = function(attributes) {
+ /** @type {string} */ var src = '';
+ /** @type {Array<string>} */ var conditions = [];
+
+ for (var i = 0; i < attributes.length; i++) {
+ if (attributes[i].getCondition().notEquals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.NEVER)) &&
+ attributes[i].getCondition().notEquals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS)))
+ if (conditions.indexOf(attributes[i].getCondition().getName()) == -1)
+ conditions.push(attributes[i].getCondition().getName());
+ }
+
+ for (var i = 0; i < conditions.length; i++)
+ src += ('uniform mediump float u_' + conditions[i] + ';\n');
+
+ return src;
+ };
+
+ /**
+ * @param {glsAttributeLocationTests.Attribute} attrib
+ * @param {number=} id
+ * @return {string}
+ */
+ glsAttributeLocationTests.generateToVec4Expression = function(attrib, id) {
+ /** @type {string} */ var src = '';
+ id = id === undefined ? -1 : id;
+
+ /** @type {string} */
+ var variableName = (attrib.getName() + (attrib.getArraySize() != glsAttributeLocationTests.ArrayEnum.NOT ? '[' + id + ']' : ''));
+
+ switch (attrib.getType().getGLTypeEnum()) {
+ case gl.INT_VEC2:
+ case gl.UNSIGNED_INT_VEC2:
+ case gl.FLOAT_VEC2:
+ src += ('vec4(' + variableName + '.xy, ' + variableName + '.yx)');
+ break;
+
+ case gl.INT_VEC3:
+ case gl.UNSIGNED_INT_VEC3:
+ case gl.FLOAT_VEC3:
+ src += ('vec4(' + variableName + '.xyz, ' + variableName + '.x)');
+ break;
+
+ default:
+ src += ('vec4(' + variableName + ')');
+ break;
+ }
+
+ return src;
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @return {string}
+ */
+ glsAttributeLocationTests.generateOutputCode = function(attributes) {
+ /** @type {string} */ var src = '';
+
+ for (var i = 0; i < attributes.length; i++) {
+ if (attributes[i].getCondition().equals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.NEVER))) {
+ src += '\tif (0 != 0)\n\t{\n';
+
+ if (attributes[i].getArraySize() == glsAttributeLocationTests.ArrayEnum.NOT)
+ src += ('\t\tcolor += ' + glsAttributeLocationTests.generateToVec4Expression(attributes[i]) + ';\n');
+ else {
+ for (var j = 0; j < attributes[i].getArraySize(); i++)
+ src += ('\t\tcolor += ' + glsAttributeLocationTests.generateToVec4Expression(attributes[i], j) + ';\n');
+ }
+
+ src += '\t}\n';
+ } else if (attributes[i].getCondition().equals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS))) {
+ if (attributes[i].getArraySize() == glsAttributeLocationTests.ArrayEnum.NOT)
+ src += ('\tcolor += ' + glsAttributeLocationTests.generateToVec4Expression(attributes[i]) + ';\n');
+ else {
+ for (var j = 0; j < attributes[i].getArraySize(); j++)
+ src += ('\tcolor += ' + glsAttributeLocationTests.generateToVec4Expression(attributes[i], j) + ';\n');
+ }
+ } else {
+ src += ('\tif (u_' + attributes[i].getCondition().getName() + (attributes[i].getCondition().getNegate() ? ' != ' : ' == ') + '0.0)\n');
+ src += '\t{\n';
+
+ if (attributes[i].getArraySize() == glsAttributeLocationTests.ArrayEnum.NOT)
+ src += ('\t\tcolor += ' + glsAttributeLocationTests.generateToVec4Expression(attributes[i]) + ';\n');
+ else {
+ for (var j = 0; j < attributes[i].getArraySize(); i++)
+ src += ('\t\tcolor += ' + glsAttributeLocationTests.generateToVec4Expression(attributes[i], j) + ';\n');
+ }
+
+ src += '\t}\n';
+ }
+ }
+
+ return src;
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @return {string}
+ */
+ glsAttributeLocationTests.generateVertexShaderTemplate = function(attributes) {
+ /** @type {string} */ var src = '';
+
+ src = '${VERSION}\n' +
+ '${VTX_OUTPUT} mediump vec4 v_color;\n' +
+ glsAttributeLocationTests.generateAttributeDefinitions(attributes) +
+ '\n' +
+ glsAttributeLocationTests.generateConditionUniformDefinitions(attributes) +
+ '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ '\tmediump vec4 color = vec4(0.0);\n' +
+ '\n' +
+ glsAttributeLocationTests.generateOutputCode(attributes) +
+ '\n' +
+ '\tv_color = color;\n' +
+ '\tgl_Position = color;\n' +
+ '}\n';
+
+ return src;
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @param {boolean} attributeAliasing
+ * @return {string}
+ */
+ glsAttributeLocationTests.createVertexShaderSource = function(attributes, attributeAliasing) {
+ // \note On GLES only GLSL #version 100 supports aliasing
+ /** @type {gluShaderUtil.GLSLVersion} */ var glslVersion = gluShaderUtil.getGLSLVersion(gl);
+ glslVersion = attributeAliasing ? gluShaderUtil.GLSLVersion.V100_ES : glslVersion;
+ /** @type {boolean} */ var usesInOutQualifiers = gluShaderUtil.glslVersionUsesInOutQualifiers(glslVersion);
+ /** @type {string} */ var vertexShaderTemplate = glsAttributeLocationTests.generateVertexShaderTemplate(attributes);
+
+ /** @type {Array<string>} */ var parameters = [];
+
+ parameters['VERSION'] = gluShaderUtil.getGLSLVersionDeclaration(glslVersion);
+ parameters['VTX_OUTPUT'] = usesInOutQualifiers ? 'out' : 'varying';
+ parameters['VTX_INPUT'] = usesInOutQualifiers ? 'in' : 'attribute';
+ parameters['FRAG_INPUT'] = usesInOutQualifiers ? 'in' : 'varying';
+ parameters['FRAG_OUTPUT_VAR'] = usesInOutQualifiers ? 'dEQP_FragColor' : 'gl_FragColor';
+ parameters['FRAG_OUTPUT_DECLARATION'] = usesInOutQualifiers ? 'layout(location=0) out mediump vec4 dEQP_FragColor;' : '';
+
+ return tcuStringTemplate.specialize(vertexShaderTemplate, parameters);
+ };
+
+ /**
+ * @param {boolean} attributeAliasing
+ * @return {string}
+ */
+ glsAttributeLocationTests.createFragmentShaderSource = function(attributeAliasing) {
+ /** @type {string} */ var fragmentShaderSource = '';
+ fragmentShaderSource = '${VERSION}\n' +
+ '${FRAG_OUTPUT_DECLARATION}\n' +
+ '${FRAG_INPUT} mediump vec4 v_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ '\t${FRAG_OUTPUT_VAR} = v_color;\n' +
+ '}\n';
+
+ // \note On GLES only GLSL #version 100 supports aliasing
+ /** @type {gluShaderUtil.GLSLVersion} */ var glslVersion = gluShaderUtil.getGLSLVersion(gl);
+ glslVersion = attributeAliasing ? gluShaderUtil.GLSLVersion.V100_ES : glslVersion;
+ /** @type {boolean} */ var usesInOutQualifiers = gluShaderUtil.glslVersionUsesInOutQualifiers(glslVersion);
+
+ /** @type {Array<string>} */ var parameters = [];
+
+ parameters['VERSION'] = gluShaderUtil.getGLSLVersionDeclaration(glslVersion);
+ parameters['VTX_OUTPUT'] = usesInOutQualifiers ? 'out' : 'varying';
+ parameters['VTX_INPUT'] = usesInOutQualifiers ? 'in' : 'attribute';
+ parameters['FRAG_INPUT'] = usesInOutQualifiers ? 'in' : 'varying';
+ parameters['FRAG_OUTPUT_VAR'] = usesInOutQualifiers ? 'dEQP_FragColor' : 'gl_FragColor';
+ parameters['FRAG_OUTPUT_DECLARATION'] = usesInOutQualifiers ? 'layout(location=0) out mediump vec4 dEQP_FragColor;' : '';
+
+ return tcuStringTemplate.specialize(fragmentShaderSource, parameters);
+ };
+
+ glsAttributeLocationTests.logProgram = function(program) {
+ var programLinkOk = /** @type {boolean} */ (gl.getProgramParameter(program, gl.LINK_STATUS));
+ /**@type{string} */ var programInfoLog = gl.getProgramInfoLog(program);
+ /**@type{string} */ var log = 'Program Link Info: ' + programInfoLog +
+ 'Link result: ' + (programLinkOk ? 'Ok' : 'Fail');
+
+ bufferedLogToConsole(log);
+ };
+
+ glsAttributeLocationTests.logAttributes = function(attributes) {
+ /**@type{string} */ var log;
+ for (var i = 0; i < attributes.length; i++) {
+
+ log = 'Type: ' + attributes[i].getType().getName() +
+ ', Name: ' + attributes[i].getName() +
+ (attributes[i].getLayoutLocation() != glsAttributeLocationTests.LocationEnum.UNDEF ? ', Layout location ' + attributes[i].getLayoutLocation() : '');
+
+ bufferedLogToConsole(log);
+ }
+ };
+
+ /**
+ * @param {string} vertexShaderSource
+ * @param {string} vertexShaderInfoLog
+ * @param {boolean} vertexCompileOk
+ * @param {string} fragmentShaderSource
+ * @param {string} fragmentShaderInfoLog
+ * @param {boolean} fragmentCompileOk
+ */
+ glsAttributeLocationTests.logShaders = function(vertexShaderSource, vertexShaderInfoLog, vertexCompileOk, fragmentShaderSource, fragmentShaderInfoLog, fragmentCompileOk) {
+
+ /**@type{string} */ var log;
+ log = '\nVertex Shader Info: ' +
+ vertexShaderSource +
+ '\nInfo Log: ' +
+ vertexShaderInfoLog +
+ '\nCompilation result: ' + (vertexCompileOk ? 'Ok' : 'Failed') +
+
+ '\nFragment Shader Info: ' +
+ fragmentShaderSource +
+ '\nInfo Log: ' +
+ fragmentShaderInfoLog +
+ '\nCompilation result: ' + (fragmentCompileOk ? 'Ok' : 'Failed');
+
+ bufferedLogToConsole(log);
+ };
+
+ /**
+ * @param {WebGLProgram} program
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.checkActiveAttribQuery = function(program, attributes) {
+ /** @type {number} */ var activeAttribCount = 0;
+ /** @type {Array<string>} */ var activeAttributes = [];
+ /** @type {boolean} */ var isOk = true;
+ /** @type {string} */ var log;
+
+ activeAttribCount = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES));
+
+ /** @type {glsAttributeLocationTests.Attribute} */ var attrib;
+ /** @type {boolean} */ var isActive;
+ /** @type {WebGLActiveInfo} */ var activeInfo;
+
+ for (var activeAttribNdx = 0; activeAttribNdx < activeAttribCount; activeAttribNdx++) {
+
+ activeInfo = gl.getActiveAttrib(program, activeAttribNdx);
+
+ log = 'glGetActiveAttrib(program' +
+ '\nindex= ' + activeAttribNdx +
+ '\nsize= ' + activeInfo.size +
+ '\ntype= ' + activeInfo.type +
+ '\nname= ' + activeInfo.name;
+
+ bufferedLogToConsole(log);
+
+ /** @type {boolean} */ var found = false;
+
+ for (var attribNdx = 0; attribNdx < attributes.length; attribNdx++) {
+ attrib = attributes[attribNdx];
+
+ if (attrib.getName() == activeInfo.name) {
+ if (activeInfo.type != attrib.getType().getGLTypeEnum()) {
+
+ log = 'Error: Wrong type ' + attrib.getType().getGLTypeEnum() +
+ ' expected= ' + activeInfo.type;
+ bufferedLogToConsole(log);
+
+ isOk = false;
+ }
+
+ if (attrib.getArraySize() == glsAttributeLocationTests.ArrayEnum.NOT) {
+ if (activeInfo.size != 1) {
+
+ bufferedLogToConsole('Error: Wrong size ' + activeInfo.size + ' expected 1');
+ isOk = false;
+ }
+ } else {
+ if (activeInfo.size != attrib.getArraySize()) {
+ bufferedLogToConsole('Error: Wrong size ' + activeInfo.size + ' expected ' + attrib.getArraySize());
+
+ isOk = false;
+ }
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ log = 'Error: Unknown attribute ' + activeInfo.name + ' returned= by glGetActiveAttrib().';
+ bufferedLogToConsole(log);
+
+ isOk = false;
+ }
+
+ activeAttributes.push(activeInfo.name);
+ }
+
+ for (var attribNdx = 0; attribNdx < attributes.length; attribNdx++) {
+ attrib = attributes[attribNdx];
+ isActive = attrib.getCondition().notEquals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.NEVER));
+
+ if (isActive) {
+ if (activeAttributes.indexOf(attrib.getName()) == -1) {
+
+ bufferedLogToConsole('Error: Active attribute ' + attrib.getName() + 'wasn\'t returned by glGetActiveAttrib().');
+ isOk = false;
+ }
+ } else {
+ if (activeAttributes[attrib.getName()] === undefined)
+ bufferedLogToConsole('Note: Inactive attribute ' + attrib.getName() + 'was returned by glGetActiveAttrib().');
+ }
+ }
+
+ return isOk;
+ };
+
+ /**
+ * @param {WebGLProgram} program
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @param {Array<number>} bindings
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.checkAttribLocationQuery = function(program, attributes, bindings) {
+ /** @type {boolean} */ var isOk = true;
+ /** @type {string} */ var log;
+
+ for (var attribNdx = 0; attribNdx < attributes.length; attribNdx++) {
+ /** @type {glsAttributeLocationTests.Attribute} */ var attrib = attributes[attribNdx];
+ /** @type {number} */ var expectedLocation = (attrib.getLayoutLocation() != glsAttributeLocationTests.LocationEnum.UNDEF ? attrib.getLayoutLocation() : glsAttributeLocationTests.getBoundLocation(bindings, attrib.getName()));
+ var location = /** @type {number} */ (gl.getAttribLocation(program, attrib.getName()));
+
+ if (attrib.getCondition().equals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.NEVER)) && location != -1)
+ bufferedLogToConsole('Note: Inactive attribute with location.');
+
+ if (attrib.getCondition().notEquals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.NEVER)) && expectedLocation != glsAttributeLocationTests.LocationEnum.UNDEF && expectedLocation != location)
+ bufferedLogToConsole('Error: Invalid attribute location.');
+
+ isOk = (attrib.getCondition().equals(glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.NEVER)) || expectedLocation == glsAttributeLocationTests.LocationEnum.UNDEF || expectedLocation == location);
+ }
+
+ return isOk;
+ };
+
+ /**
+ * @param {WebGLProgram} program
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @param {Array<number>} bindings
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.checkQuery = function(program, attributes, bindings) {
+ /** @type {boolean} */ var isOk = glsAttributeLocationTests.checkActiveAttribQuery(program, attributes);
+
+ if (!glsAttributeLocationTests.checkAttribLocationQuery(program, attributes, bindings))
+ isOk = false;
+
+ return isOk;
+ };
+
+ /**
+ * @param {WebGLProgram} program
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @param {boolean} attributeAliasing
+ * @return {Object}
+ */
+ glsAttributeLocationTests.createAndAttachShaders = function(program, attributes, attributeAliasing) {
+ /** @type {string} */ var vertexShaderSource = glsAttributeLocationTests.createVertexShaderSource(attributes, attributeAliasing);
+ /** @type {string} */ var fragmentShaderSource = glsAttributeLocationTests.createFragmentShaderSource(attributeAliasing);
+
+ /** @type {WebGLShader} */ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+ /** @type {WebGLShader} */ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+
+ gl.shaderSource(vertexShader, vertexShaderSource);
+ gl.shaderSource(fragmentShader, fragmentShaderSource);
+
+ gl.compileShader(vertexShader);
+ gl.compileShader(fragmentShader);
+
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+
+ var vertexShaderCompileOk = /** @type {boolean} */ (gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS));
+ var fragmentShaderCompileOk = /** @type {boolean} */ (gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));
+
+ // log shaders
+ glsAttributeLocationTests.logShaders(vertexShaderSource, gl.getShaderInfoLog(vertexShader),
+ vertexShaderCompileOk,
+ fragmentShaderSource, gl.getShaderInfoLog(fragmentShader),
+ fragmentShaderCompileOk);
+
+ assertMsgOptions(vertexShaderCompileOk, 'vertex Shader compile failed', false, true);
+ assertMsgOptions(fragmentShaderCompileOk, 'fragment Shader compile failed', false, true);
+
+ gl.deleteShader(vertexShader);
+ gl.deleteShader(fragmentShader);
+
+ return {first: vertexShader, second: fragmentShader};
+
+ };
+
+ /**
+ * @param {WebGLProgram} program
+ * @param {Array<glsAttributeLocationTests.Bind>} binds
+ */
+ glsAttributeLocationTests.bindAttributes = function(program, binds) {
+ for (var i = 0; i < binds.length; i++) {
+ bufferedLogToConsole('Bind attribute: ' + binds[i].getAttributeName() + ' to ' + binds[i].getLocation());
+ gl.bindAttribLocation(program, binds[i].getLocation(), binds[i].getAttributeName());
+ }
+ };
+
+ /**
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ * @return {string}
+ */
+ glsAttributeLocationTests.generateTestName = function(type, arraySize) {
+ return type.getName() + (arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? '_array_' + arraySize : '');
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {number} locationSize
+ * @param {number} typeEnum
+ */
+ glsAttributeLocationTests.AttribType = function(name, locationSize, typeEnum) {
+ /** @type {string} */ this.m_name = name;
+ /** @type {number} */ this.m_locationSize = locationSize;
+ /** @type {number} */ this.m_glTypeEnum = typeEnum;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsAttributeLocationTests.AttribType.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsAttributeLocationTests.AttribType.prototype.getLocationSize = function() {
+ return this.m_locationSize;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsAttributeLocationTests.AttribType.prototype.getGLTypeEnum = function() {
+ return this.m_glTypeEnum;
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsAttributeLocationTests.ConstCond = {
+ ALWAYS: 0,
+ NEVER: 1
+ };
+
+ /**
+ * @constructor
+ * @param {string} name
+ * @param {boolean=} negate
+ */
+ glsAttributeLocationTests.Cond = function(name, negate) {
+ /** @type {boolean} */ this.m_negate = negate === undefined ? false : negate;
+ /** @type {string} */ this.m_name = name;
+ };
+
+ /**
+ * @param {glsAttributeLocationTests.ConstCond} cond
+ * @return {glsAttributeLocationTests.Cond}
+ */
+ glsAttributeLocationTests.NewCondWithEnum = function(cond) {
+ var condObj = new glsAttributeLocationTests.Cond('', false);
+ condObj.m_name = '__always__';
+ condObj.m_negate = (cond != glsAttributeLocationTests.ConstCond.NEVER);
+
+ return condObj;
+ };
+
+ /**
+ * @param {glsAttributeLocationTests.Cond} other
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.Cond.prototype.equals = function(other) {
+ return (this.m_negate == other.m_negate && this.m_name == other.m_name);
+ };
+
+ /**
+ * @param {glsAttributeLocationTests.Cond} other
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.Cond.prototype.notEquals = function(other) {
+ return (!this.equals(other));
+ };
+
+ /**
+ * @return {string}
+ */
+ glsAttributeLocationTests.Cond.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ glsAttributeLocationTests.Cond.prototype.getNegate = function() {
+ return this.m_negate;
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsAttributeLocationTests.LocationEnum = {
+ UNDEF: -1
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsAttributeLocationTests.ArrayEnum = {
+ NOT: -1
+ };
+
+ /**
+ * @constructor
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {string} name
+ * @param {number=} layoutLocation
+ * @param {glsAttributeLocationTests.Cond=} cond
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.Attribute = function(type, name, layoutLocation, cond, arraySize) {
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ /** @type {string} */ this.m_name = name;
+ /** @type {number} */ this.m_layoutLocation = layoutLocation === undefined ? glsAttributeLocationTests.LocationEnum.UNDEF : layoutLocation;
+ /** @type {glsAttributeLocationTests.Cond} */ this.m_cond = cond === undefined ?
+ glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS) : cond;
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ };
+
+ /**
+ * @return {glsAttributeLocationTests.AttribType}
+ */
+ glsAttributeLocationTests.Attribute.prototype.getType = function() {
+ return this.m_type;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsAttributeLocationTests.Attribute.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsAttributeLocationTests.Attribute.prototype.getLayoutLocation = function() {
+ return this.m_layoutLocation;
+ };
+
+ /**
+ * @return {glsAttributeLocationTests.Cond}
+ */
+ glsAttributeLocationTests.Attribute.prototype.getCondition = function() {
+ return this.m_cond;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsAttributeLocationTests.Attribute.prototype.getArraySize = function() {
+ return this.m_arraySize;
+ };
+
+ /**
+ * @constructor
+ * @param {string} attribute
+ * @param {number} location
+ */
+ glsAttributeLocationTests.Bind = function(attribute, location) {
+ /** @type {string} */ this.m_attribute = attribute;
+ /** @type {number} */ this.m_location = location;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsAttributeLocationTests.Bind.prototype.getAttributeName = function() {
+ return this.m_attribute;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsAttributeLocationTests.Bind.prototype.getLocation = function() {
+ return this.m_location;
+ };
+
+ /**
+ * @param {Array<glsAttributeLocationTests.Attribute>} attributes
+ * @param {Array<glsAttributeLocationTests.Bind>} preAttachBind
+ * @param {Array<glsAttributeLocationTests.Bind>} preLinkBind
+ * @param {Array<glsAttributeLocationTests.Bind>} postLinkBind
+ * @param {boolean} relink
+ * @param {boolean=} reattach
+ * @param {Array<glsAttributeLocationTests.Attribute>=} reattachAttributes
+ */
+ glsAttributeLocationTests.runTest = function(attributes, preAttachBind, preLinkBind, postLinkBind, relink, reattach, reattachAttributes) {
+ reattach = reattach === undefined ? false : reattach;
+ reattachAttributes = reattachAttributes === undefined ? [] : reattachAttributes;
+
+ try {
+ /** @type {boolean} */ var isOk = true;
+ /** @type {Array<number>} */ var activeBindings = [];
+
+ for (var bindNdx = 0; bindNdx < preAttachBind.length; bindNdx++)
+ activeBindings[preAttachBind[bindNdx].getAttributeName()] = preAttachBind[bindNdx].getLocation();
+
+ for (var bindNdx = 0; bindNdx < preLinkBind.length; bindNdx++)
+ activeBindings[preLinkBind[bindNdx].getAttributeName()] = preLinkBind[bindNdx].getLocation();
+
+ glsAttributeLocationTests.logAttributes(attributes);
+
+ /** @type {WebGLProgram} */ var program = gl.createProgram();
+
+ if (!preAttachBind.length == 0)
+ glsAttributeLocationTests.bindAttributes(program, preAttachBind);
+
+ /** @type {*} */ var shaders = glsAttributeLocationTests.createAndAttachShaders(program, attributes, glsAttributeLocationTests.hasAttributeAliasing(attributes, activeBindings));
+
+ if (!preLinkBind.length == 0)
+ glsAttributeLocationTests.bindAttributes(program, preLinkBind);
+
+ gl.linkProgram(program);
+
+ assertMsgOptions(gl.getProgramParameter(program, gl.LINK_STATUS) == true, 'link program failed', false, true);
+
+ glsAttributeLocationTests.logProgram(program);
+
+ if (!glsAttributeLocationTests.checkQuery(program, attributes, activeBindings))
+ isOk = false;
+
+ if (!postLinkBind.length == 0) {
+ glsAttributeLocationTests.bindAttributes(program, postLinkBind);
+
+ if (!glsAttributeLocationTests.checkQuery(program, attributes, activeBindings))
+ isOk = false;
+ }
+
+ if (relink) {
+ gl.linkProgram(program);
+
+ assertMsgOptions(gl.getProgramParameter(program, gl.LINK_STATUS) == true, 'link program failed', false, true);
+
+ glsAttributeLocationTests.logProgram(program);
+
+ for (var bindNdx = 0; bindNdx < postLinkBind.length; bindNdx++)
+ activeBindings[postLinkBind[bindNdx].getAttributeName()] = postLinkBind[bindNdx].getLocation();
+
+ if (!glsAttributeLocationTests.checkQuery(program, attributes, activeBindings))
+ isOk = false;
+ }
+
+ if (reattach) {
+ gl.detachShader(program, shaders.first);
+ gl.detachShader(program, shaders.second);
+
+ glsAttributeLocationTests.createAndAttachShaders(program, reattachAttributes, glsAttributeLocationTests.hasAttributeAliasing(reattachAttributes, activeBindings));
+
+ gl.linkProgram(program);
+
+ assertMsgOptions(gl.getProgramParameter(program, gl.LINK_STATUS) == true, 'link program failed', false, true);
+
+ glsAttributeLocationTests.logProgram(program);
+
+ if (!glsAttributeLocationTests.checkQuery(program, reattachAttributes, activeBindings))
+ isOk = false;
+ }
+
+ gl.deleteProgram(program);
+
+ assertMsgOptions(isOk, '', true, true);
+
+ } catch (e) {
+ if (program)
+ gl.deleteProgram(program);
+
+ throw e;
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.BindAttributeTest = function(type, arraySize) {
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.BindAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.BindAttributeTest.prototype.constructor = glsAttributeLocationTests.BindAttributeTest;
+
+ glsAttributeLocationTests.BindAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_0', glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.BindMaxAttributesTest = function(type, arraySize) {
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.BindMaxAttributesTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.BindMaxAttributesTest.prototype.constructor = glsAttributeLocationTests.BindMaxAttributesTest;
+
+ glsAttributeLocationTests.BindMaxAttributesTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {number} */ var ndx = 0;
+
+ bufferedLogToConsole('MAX_VERTEX_ATTRIBS: ' + maxAttributes);
+
+ for (var loc = maxAttributes - (arrayElementCount * this.m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * this.m_type.getLocationSize())) {
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_' + ndx, glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+ bindings.push(new glsAttributeLocationTests.Bind('a_' + ndx, loc));
+ ndx++;
+ }
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.BindHoleAttributeTest = function(type, arraySize) {
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.BindHoleAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.BindHoleAttributeTest.prototype.constructor = glsAttributeLocationTests.BindHoleAttributeTest;
+
+ glsAttributeLocationTests.BindHoleAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0'));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 0));
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_1', glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+
+ /** @type {number} */ var ndx = 2;
+ for (var loc = 1 + this.m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) {
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx));
+ bindings.push(new glsAttributeLocationTests.Bind('a_' + ndx, loc));
+
+ ndx++;
+ }
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.PreAttachBindAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'pre_attach', 'pre_attach');
+ };
+
+ glsAttributeLocationTests.PreAttachBindAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.PreAttachBindAttributeTest.prototype.constructor = glsAttributeLocationTests.PreAttachBindAttributeTest;
+
+ glsAttributeLocationTests.PreAttachBindAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {number} */ var ndx = 0;
+
+ attributes.push(new glsAttributeLocationTests.Attribute(new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4), 'a_0'));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, bindings, noBindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.PreLinkBindAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'pre_link', 'pre_link');
+ };
+
+ glsAttributeLocationTests.PreLinkBindAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.PreLinkBindAttributeTest.prototype.constructor = glsAttributeLocationTests.PreLinkBindAttributeTest;
+
+ glsAttributeLocationTests.PreLinkBindAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {number} */ var ndx = 0;
+
+ attributes.push(new glsAttributeLocationTests.Attribute(new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4), 'a_0'));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, bindings, noBindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.PostLinkBindAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'post_link', 'post_link');
+ };
+
+ glsAttributeLocationTests.PostLinkBindAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.PostLinkBindAttributeTest.prototype.constructor = glsAttributeLocationTests.PostLinkBindAttributeTest;
+
+ glsAttributeLocationTests.PostLinkBindAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4), 'a_0'));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, noBindings, bindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.BindReattachAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'reattach', 'reattach');
+ };
+
+ glsAttributeLocationTests.BindReattachAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.BindReattachAttributeTest.prototype.constructor = glsAttributeLocationTests.BindReattachAttributeTest;
+
+ glsAttributeLocationTests.BindReattachAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec2 = new glsAttributeLocationTests.AttribType('vec2', 1, gl.FLOAT_VEC2);
+
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var reattachAttributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0'));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 1));
+ bindings.push(new glsAttributeLocationTests.Bind('a_1', 1));
+
+ reattachAttributes.push(new glsAttributeLocationTests.Attribute(vec2, 'a_1'));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false, true, reattachAttributes);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.LocationAttributeTest = function(type, arraySize) {
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.LocationAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.LocationAttributeTest.prototype.constructor = glsAttributeLocationTests.LocationAttributeTest;
+
+ glsAttributeLocationTests.LocationAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_0', 3, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, noBindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.LocationMaxAttributesTest = function(type, arraySize) {
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.LocationMaxAttributesTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.LocationMaxAttributesTest.prototype.constructor = glsAttributeLocationTests.LocationMaxAttributesTest;
+
+ glsAttributeLocationTests.LocationMaxAttributesTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {number} */ var ndx = 0;
+
+ bufferedLogToConsole('MAX_VERTEX_ATTRIBS: ' + maxAttributes);
+
+ for (var loc = maxAttributes - (arrayElementCount * this.m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * this.m_type.getLocationSize())) {
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_' + ndx, loc, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+ ndx++;
+ }
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, noBindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.LocationHoleAttributeTest = function(type, arraySize) {
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.LocationHoleAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.LocationHoleAttributeTest.prototype.constructor = glsAttributeLocationTests.LocationHoleAttributeTest;
+
+ glsAttributeLocationTests.LocationHoleAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0', 0));
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_1', glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+
+ /** @type {number} */ var ndx = 2;
+ for (var loc = 1 + this.m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) {
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx, loc));
+ ndx++;
+ }
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, noBindings, noBindings, false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.MixedAttributeTest = function(type, arraySize) {
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.MixedAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.MixedAttributeTest.prototype.constructor = glsAttributeLocationTests.MixedAttributeTest;
+
+ glsAttributeLocationTests.MixedAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_0', 3, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 4));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.MixedMaxAttributesTest = function(type, arraySize) {
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.MixedMaxAttributesTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.MixedMaxAttributesTest.prototype.constructor = glsAttributeLocationTests.MixedMaxAttributesTest;
+
+ glsAttributeLocationTests.MixedMaxAttributesTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {number} */ var ndx = 0;
+
+ bufferedLogToConsole('MAX_VERTEX_ATTRIBS: ' + maxAttributes);
+
+ for (var loc = maxAttributes - (arrayElementCount * this.m_type.getLocationSize()); loc >= 0; loc -= (arrayElementCount * this.m_type.getLocationSize())) {
+ if ((ndx % 2) != 0)
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_' + ndx, loc, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+ else {
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_' + ndx, glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+ bindings.push(new glsAttributeLocationTests.Bind('a_' + ndx, loc));
+ }
+ ndx++;
+ }
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.MixedHoleAttributeTest = function(type, arraySize) {
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.MixedHoleAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.MixedHoleAttributeTest.prototype.constructor = glsAttributeLocationTests.MixedHoleAttributeTest;
+
+ glsAttributeLocationTests.MixedHoleAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0'));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 0));
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_1', glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+
+ /** @type {number} */ var ndx = 2;
+ for (var loc = 1 + this.m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) {
+ if ((ndx % 2) != 0)
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx, loc));
+ else {
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx, loc));
+ bindings.push(new glsAttributeLocationTests.Bind('a_' + ndx, loc));
+ }
+ ndx++;
+ }
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.BindRelinkAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'relink', 'relink');
+ };
+
+ glsAttributeLocationTests.BindRelinkAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.BindRelinkAttributeTest.prototype.constructor = glsAttributeLocationTests.BindRelinkAttributeTest;
+
+ glsAttributeLocationTests.BindRelinkAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var preLinkBindings = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var postLinkBindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0'));
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_1'));
+
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 5));
+
+ postLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 6));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, preLinkBindings, postLinkBindings, true);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.BindRelinkHoleAttributeTest = function(type, arraySize) {
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.BindRelinkHoleAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.BindRelinkHoleAttributeTest.prototype.constructor = glsAttributeLocationTests.BindRelinkHoleAttributeTest;
+
+ glsAttributeLocationTests.BindRelinkHoleAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var preLinkBindings = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var postLinkBindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0'));
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 0));
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_1', glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+
+ /** @type {number} */ var ndx = 2;
+ for (var loc = 1 + this.m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) {
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx));
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_' + ndx, loc));
+
+ ndx++;
+ }
+
+ postLinkBindings.push(new glsAttributeLocationTests.Bind('a_2', 1));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, preLinkBindings, postLinkBindings, true);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsAttributeLocationTests.AttribType} type
+ * @param {number=} arraySize
+ */
+ glsAttributeLocationTests.MixedRelinkHoleAttributeTest = function(type, arraySize) {
+ /** @type {glsAttributeLocationTests.AttribType} */ this.m_type = type;
+ /** @type {number} */ this.m_arraySize = arraySize === undefined ? glsAttributeLocationTests.ArrayEnum.NOT : arraySize;
+ tcuTestCase.DeqpTest.call(this, glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize), glsAttributeLocationTests.generateTestName(this.m_type, this.m_arraySize));
+ };
+
+ glsAttributeLocationTests.MixedRelinkHoleAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.MixedRelinkHoleAttributeTest.prototype.constructor = glsAttributeLocationTests.MixedRelinkHoleAttributeTest;
+
+ glsAttributeLocationTests.MixedRelinkHoleAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {number} */ var maxAttributes = glsAttributeLocationTests.getMaxAttributeLocations();
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {number} */ var arrayElementCount = (this.m_arraySize != glsAttributeLocationTests.ArrayEnum.NOT ? this.m_arraySize : 1);
+
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var preLinkBindings = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var postLinkBindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0'));
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 0));
+
+ attributes.push(new glsAttributeLocationTests.Attribute(this.m_type, 'a_1', glsAttributeLocationTests.LocationEnum.UNDEF, glsAttributeLocationTests.NewCondWithEnum(glsAttributeLocationTests.ConstCond.ALWAYS), this.m_arraySize));
+
+ /** @type {number} */ var ndx = 2;
+ for (var loc = 1 + this.m_type.getLocationSize() * arrayElementCount; loc < maxAttributes; loc++) {
+ if ((ndx % 2) != 0)
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx, loc));
+ else {
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_' + ndx));
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_' + ndx, loc));
+
+ }
+ ndx++;
+ }
+
+ postLinkBindings.push(new glsAttributeLocationTests.Bind('a_2', 1));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, preLinkBindings, postLinkBindings, true);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.PreAttachMixedAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'pre_attach', 'pre_attach');
+ };
+
+ glsAttributeLocationTests.PreAttachMixedAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.PreAttachMixedAttributeTest.prototype.constructor = glsAttributeLocationTests.PreAttachMixedAttributeTest;
+
+ glsAttributeLocationTests.PreAttachMixedAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4), 'a_0', 1));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, bindings, noBindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.PreLinkMixedAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'pre_link', 'pre_link');
+ };
+
+ glsAttributeLocationTests.PreLinkMixedAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.PreLinkMixedAttributeTest.prototype.constructor = glsAttributeLocationTests.PreLinkMixedAttributeTest;
+
+ glsAttributeLocationTests.PreLinkMixedAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4), 'a_0', 1));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.PostLinkMixedAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'post_link', 'post_link');
+ };
+
+ glsAttributeLocationTests.PostLinkMixedAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.PostLinkMixedAttributeTest.prototype.constructor = glsAttributeLocationTests.PostLinkMixedAttributeTest;
+
+ glsAttributeLocationTests.PostLinkMixedAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4), 'a_0', 1));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, noBindings, bindings, false);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.MixedReattachAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'reattach', 'reattach');
+ };
+
+ glsAttributeLocationTests.MixedReattachAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.MixedReattachAttributeTest.prototype.constructor = glsAttributeLocationTests.MixedReattachAttributeTest;
+
+ glsAttributeLocationTests.MixedReattachAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec2 = new glsAttributeLocationTests.AttribType('vec2', 1, gl.FLOAT_VEC2);
+
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var bindings = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var reattachAttributes = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0', 2));
+ bindings.push(new glsAttributeLocationTests.Bind('a_0', 1));
+ bindings.push(new glsAttributeLocationTests.Bind('a_1', 1));
+
+ reattachAttributes.push(new glsAttributeLocationTests.Attribute(vec2, 'a_1'));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, bindings, noBindings, false, true, reattachAttributes);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ glsAttributeLocationTests.MixedRelinkAttributeTest = function() {
+ tcuTestCase.DeqpTest.call(this, 'relink', 'relink');
+ };
+
+ glsAttributeLocationTests.MixedRelinkAttributeTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsAttributeLocationTests.MixedRelinkAttributeTest.prototype.constructor = glsAttributeLocationTests.MixedRelinkAttributeTest;
+
+ glsAttributeLocationTests.MixedRelinkAttributeTest.prototype.iterate = function() {
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var noBindings = [];
+ /** @type {glsAttributeLocationTests.AttribType} */ var vec4 = new glsAttributeLocationTests.AttribType('vec4', 1, gl.FLOAT_VEC4);
+
+ /** @type {Array<glsAttributeLocationTests.Attribute>} */ var attributes = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var preLinkBindings = [];
+ /** @type {Array<glsAttributeLocationTests.Bind>} */ var postLinkBindings = [];
+
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_0', 1));
+ attributes.push(new glsAttributeLocationTests.Attribute(vec4, 'a_1'));
+
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 3));
+ preLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 5));
+
+ postLinkBindings.push(new glsAttributeLocationTests.Bind('a_0', 6));
+
+ glsAttributeLocationTests.runTest(attributes, noBindings, preLinkBindings, postLinkBindings, true);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBufferTestUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBufferTestUtil.js
new file mode 100644
index 0000000000..446782b4b6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBufferTestUtil.js
@@ -0,0 +1,1068 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsBufferTestUtil');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+
+ var glsBufferTestUtil = modules.shared.glsBufferTestUtil;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuTexture = framework.common.tcuTexture;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var deUtil = framework.delibs.debase.deUtil;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+
+ glsBufferTestUtil.VERIFY_QUAD_SIZE = 8; //!< Quad size in VertexArrayVerifier
+ glsBufferTestUtil.MAX_LINES_PER_INDEX_ARRAY_DRAW = 128; //!< Maximum number of lines per one draw in IndexArrayVerifier
+ glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_WIDTH = 128;
+ glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT = 128;
+
+ // Helper functions.
+
+ /**
+ * @param {Uint8Array} ptr
+ * @param {number} numBytes
+ * @param {number} seed
+ */
+ glsBufferTestUtil.fillWithRandomBytes = function(ptr, numBytes, seed) {
+ var rnd = new deRandom.Random(seed);
+ for (var left = numBytes; left > 0; left--)
+ ptr[left - 1] = rnd.getInt();
+ };
+
+ /**
+ * @param {Uint8Array} resPtr
+ * @param {Uint8Array} refPtr
+ * @param {number} numBytes
+ * @return {boolean}
+ */
+ glsBufferTestUtil.compareByteArrays = function(resPtr, refPtr, numBytes) {
+ var isOk = true;
+ var maxSpanLen = 8;
+ var maxDiffSpans = 4;
+ var numDiffSpans = 0;
+ var diffSpanStart = -1;
+ var ndx = 0;
+
+ var log = 'Verification result: ';
+
+ for (; ndx < numBytes; ndx++) {
+ if (resPtr[ndx] != refPtr[ndx]) {
+ if (diffSpanStart < 0)
+ diffSpanStart = ndx;
+
+ isOk = false;
+ } else if (diffSpanStart >= 0) {
+ if (numDiffSpans < maxDiffSpans) {
+ var len = ndx - diffSpanStart;
+ var printLen = Math.min(len, maxSpanLen);
+
+ log += len + ' byte difference at offset ' + diffSpanStart + '\n' +
+ ' expected ' + refPtr.subarray(diffSpanStart, diffSpanStart + printLen) +
+ ' got ' + resPtr.subarray(diffSpanStart, diffSpanStart + printLen);
+ } else
+ log += '(output too long, truncated)';
+
+ numDiffSpans += 1;
+ diffSpanStart = -1;
+ }
+ }
+
+ if (diffSpanStart >= 0) {
+ if (numDiffSpans < maxDiffSpans) {
+ var len = ndx - diffSpanStart;
+ var printLen = Math.min(len, maxSpanLen);
+
+ log += len + ' byte difference at offset ' + diffSpanStart + '\n' +
+ ' expected ' + refPtr.subarray(diffSpanStart, diffSpanStart + printLen) +
+ ' got ' + resPtr.subarray(diffSpanStart, diffSpanStart + printLen);
+ } else
+ log += '(output too long, truncated)';
+ }
+
+ log += (isOk ? 'Verification passed.' : 'Verification FAILED!');
+
+ bufferedLogToConsole(log);
+
+ return isOk;
+ };
+
+ /**
+ * @param {number} target
+ * @return {string}
+ */
+ glsBufferTestUtil.getBufferTargetName = function(target) {
+ switch (target) {
+ case gl.ARRAY_BUFFER: return 'array';
+ case gl.COPY_READ_BUFFER: return 'copy_read';
+ case gl.COPY_WRITE_BUFFER: return 'copy_write';
+ case gl.ELEMENT_ARRAY_BUFFER: return 'element_array';
+ case gl.PIXEL_PACK_BUFFER: return 'pixel_pack';
+ case gl.PIXEL_UNPACK_BUFFER: return 'pixel_unpack';
+ //case gl.TEXTURE_BUFFER: return "texture"; //TODO: Unimplemented in WebGL 2. Remove?
+ case gl.TRANSFORM_FEEDBACK_BUFFER: return 'transform_feedback';
+ case gl.UNIFORM_BUFFER: return 'uniform';
+ default:
+ throw new Error('Invalid buffer target');
+ }
+ };
+
+ /**
+ * @param {number} hint
+ * @return {string}
+ */
+ glsBufferTestUtil.getUsageHintName = function(hint) {
+ switch (hint) {
+ case gl.STREAM_DRAW: return 'stream_draw';
+ case gl.STREAM_READ: return 'stream_read';
+ case gl.STREAM_COPY: return 'stream_copy';
+ case gl.STATIC_DRAW: return 'static_draw';
+ case gl.STATIC_READ: return 'static_read';
+ case gl.STATIC_COPY: return 'static_copy';
+ case gl.DYNAMIC_DRAW: return 'dynamic_draw';
+ case gl.DYNAMIC_READ: return 'dynamic_read';
+ case gl.DYNAMIC_COPY: return 'dynamic_copy';
+ default:
+ throw new Error('Invalid buffer usage hint');
+ }
+ };
+
+ // Base class for buffer cases.
+ // BufferCase
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ glsBufferTestUtil.BufferCase = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {Array<WebGLBuffer>} */ this.m_allocatedBuffers = [];
+ };
+
+ glsBufferTestUtil.BufferCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsBufferTestUtil.BufferCase.prototype.constructor = glsBufferTestUtil.BufferCase;
+
+ /**
+ * init
+ */
+ glsBufferTestUtil.BufferCase.prototype.init = function() {};
+
+ /**
+ * deinit
+ */
+ glsBufferTestUtil.BufferCase.prototype.deinit = function() {
+ for (var ndx = 0; ndx < this.m_allocatedBuffers.length; ndx++)
+ this.deleteBuffer(this.m_allocatedBuffers[ndx]);
+ };
+
+ /**
+ * @return {WebGLBuffer}
+ */
+ glsBufferTestUtil.BufferCase.prototype.genBuffer = function() {
+ var buf = 0;
+ buf = gl.createBuffer();
+ if (buf != 0) {
+ try {
+ deUtil.dePushUniqueToArray(this.m_allocatedBuffers, buf);
+ }
+ catch (err) {
+ gl.deleteBuffer(buf);
+ throw err;
+ }
+ }
+ return buf;
+ };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ */
+ glsBufferTestUtil.BufferCase.prototype.deleteBuffer = function(buffer) {
+ gl.deleteBuffer(buffer);
+ this.m_allocatedBuffers.splice(this.m_allocatedBuffers.indexOf(buffer), 1);
+ };
+
+ glsBufferTestUtil.BufferCase.prototype.checkError = function() {
+ /** @type {number} */ var err = gl.getError();
+ if (err != gl.NO_ERROR)
+ throw new TestFailedException('Got ' + WebGLTestUtils.glEnumToString(gl, err));
+ };
+
+ // Reference buffer.
+
+ /**
+ * @constructor
+ */
+ glsBufferTestUtil.ReferenceBuffer = function() {
+ /** @type {ArrayBuffer} */ this.m_data;
+ };
+
+ /**
+ * @param {number=} offset
+ * @return {Uint8Array}
+ */
+ glsBufferTestUtil.ReferenceBuffer.prototype.getPtr = function(offset) {
+ offset = offset ? offset : 0; return new Uint8Array(this.m_data, offset);
+ };
+
+ /**
+ * @param {number} numBytes
+ */
+ glsBufferTestUtil.ReferenceBuffer.prototype.setSize = function(numBytes) {
+ this.m_data = new ArrayBuffer(numBytes);
+ };
+
+ /**
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ */
+ glsBufferTestUtil.ReferenceBuffer.prototype.setData = function(numBytes, bytes) {
+ this.setSize(numBytes);
+ var dst = new Uint8Array(this.m_data);
+ dst.set(bytes.subarray(numBytes));
+ };
+
+ /**
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ */
+ glsBufferTestUtil.ReferenceBuffer.prototype.setSubData = function(offset, numBytes, bytes) {
+ assertMsgOptions(deMath.deInBounds32(offset, 0, this.m_data.byteLength) && deMath.deInRange32(offset + numBytes, offset, this.m_data.byteLength),
+ 'Parameters not in buffer bounds or range', false, true);
+ var dst = new Uint8Array(this.m_data, offset);
+ dst.set(bytes.subarray(offset, offset + numBytes));
+ };
+
+ // Buffer writer system.
+
+ /**
+ * @enum {number}
+ */
+ glsBufferTestUtil.WriteType = {
+ BUFFER_SUB_DATA: 0,
+ BUFFER_WRITE_MAP: 1,
+ TRANSFORM_FEEDBACK: 2,
+ PIXEL_PACK: 3
+ };
+
+ /**
+ * @param {glsBufferTestUtil.WriteType} write
+ * @return {string}
+ */
+ glsBufferTestUtil.getWriteTypeDescription = function(write) {
+ /** @type {Array<string>} */ var s_desc = [
+ 'gl.bufferSubData()',
+ 'gl.mapBufferRange()',
+ 'transform feedback',
+ 'gl.readPixels() into PBO binding'
+ ];
+ return /** @type {string} */ (deUtil.getArrayElement(s_desc, write));
+ };
+
+ // BufferWriterBase
+
+ /**
+ * @constructor
+ */
+ glsBufferTestUtil.BufferWriterBase = function() {};
+
+ /**
+ * //Meant to be overriden
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferWriterBase.prototype.getMinSize = function() { throw new Error('Must be overriden'); };
+
+ /**
+ * //Meant to be overriden
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferWriterBase.prototype.getAlignment = function() { throw new Error('Must be overriden'); };
+
+ /**
+ * //Meant to be overriden
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ */
+ glsBufferTestUtil.BufferWriterBase.prototype.writeNoTarget = function(buffer, offset, numBytes, bytes) { throw new Error('Must be overriden'); };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ * @param {number} targetHint
+ */
+ glsBufferTestUtil.BufferWriterBase.prototype.write = function(buffer, offset, numBytes, bytes, targetHint) {
+ this.writeNoTarget(buffer, offset, numBytes, bytes);
+ };
+
+ // BufferWriter
+
+ /**
+ * @constructor
+ * @param {glsBufferTestUtil.WriteType} writeType
+ */
+ glsBufferTestUtil.BufferWriter = function(writeType) {
+ /** @type {glsBufferTestUtil.BufferWriterBase} */ this.m_writer = null;
+ switch (writeType) {
+ case glsBufferTestUtil.WriteType.BUFFER_SUB_DATA: this.m_writer = new glsBufferTestUtil.BufferSubDataWriter(); break;
+ default:
+ testFailed('Unsupported writer');
+ }
+ };
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferWriter.prototype.getMinSize = function() {return this.m_writer.getMinSize();};
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferWriter.prototype.getAlignment = function() {return this.m_writer.getAlignment();};
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ */
+ glsBufferTestUtil.BufferWriter.prototype.writeNoTarget = function(buffer, offset, numBytes, bytes) {
+ assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
+ assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
+ assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
+ return this.m_writer.writeNoTarget(buffer, offset, numBytes, bytes);
+ };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ * @param {number} targetHint
+ */
+ glsBufferTestUtil.BufferWriter.prototype.write = function(buffer, offset, numBytes, bytes, targetHint) {
+ assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
+ assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
+ assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
+ return this.m_writer.write(buffer, offset, numBytes, bytes, targetHint);
+ };
+
+ // BufferSubDataWriter
+
+ /**
+ * @constructor
+ * @extends {glsBufferTestUtil.BufferWriterBase}
+ */
+ glsBufferTestUtil.BufferSubDataWriter = function() {
+ glsBufferTestUtil.BufferWriterBase.call(this);
+ };
+
+ glsBufferTestUtil.BufferSubDataWriter.prototype = Object.create(glsBufferTestUtil.BufferWriterBase.prototype);
+ glsBufferTestUtil.BufferSubDataWriter.prototype.constructor = glsBufferTestUtil.BufferSubDataWriter;
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferSubDataWriter.prototype.getMinSize = function() { return 1; };
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferSubDataWriter.prototype.getAlignment = function() { return 1; };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ */
+ glsBufferTestUtil.BufferSubDataWriter.prototype.writeNoTarget = function(buffer, offset, numBytes, bytes) {
+ this.write(buffer, offset, numBytes, bytes, gl.ARRAY_BUFFER);
+ };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {Uint8Array} bytes
+ * @param {number} target
+ */
+ glsBufferTestUtil.BufferSubDataWriter.prototype.write = function(buffer, offset, numBytes, bytes, target) {
+ gl.bindBuffer(target, buffer);
+ gl.bufferSubData(target, offset, bytes);
+ gl.bindBuffer(target, null);
+ };
+
+ // Buffer verifier system.
+
+ /**
+ * @enum {number}
+ */
+ glsBufferTestUtil.VerifyType = {
+ AS_VERTEX_ARRAY: 0,
+ AS_INDEX_ARRAY: 1,
+ AS_UNIFORM_BUFFER: 2,
+ AS_PIXEL_UNPACK_BUFFER: 3,
+ BUFFER_READ_MAP: 4
+ };
+
+ /**
+ * @param {glsBufferTestUtil.VerifyType} verify
+ * @return {string}
+ */
+ glsBufferTestUtil.getVerifyTypeDescription = function(verify) {
+ /** @type {Array<string>} */ var s_desc =
+ [
+ 'rendering as vertex data',
+ 'rendering as index data',
+ 'reading in shader as uniform buffer data',
+ 'using as PBO and uploading to texture',
+ 'reading back using glMapBufferRange()'
+ ];
+
+ return /** @type {string} */ (deUtil.getArrayElement(s_desc, verify));
+ };
+
+ /**
+ * @constructor
+ */
+ glsBufferTestUtil.BufferVerifierBase = function() {};
+
+ /**
+ * //Meant to be overriden
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferVerifierBase.prototype.getMinSize = function() { throw new Error('Must be overriden'); };
+
+ /**
+ * //Meant to be overriden
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferVerifierBase.prototype.getAlignment = function() { throw new Error('Must be overriden'); };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {Uint8Array} reference
+ * @param {number} offset
+ * @param {number} numBytes
+ * @return {boolean}
+ */
+ glsBufferTestUtil.BufferVerifierBase.prototype.verifyNoTarget = function(buffer, reference, offset, numBytes) {
+ throw new Error('Must be overriden');
+ };
+
+ /**
+ * //Meant to be overriden
+ * @param {WebGLBuffer} buffer
+ * @param {Uint8Array} reference
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {number} targetHint
+ * @return {boolean}
+ */
+ glsBufferTestUtil.BufferVerifierBase.prototype.verify = function(buffer, reference, offset, numBytes, targetHint) {
+ //In WebGL 2, ELEMENT_ARRAY_BUFFER and TRANSFORM_FEEDBACK_BUFFER cannot be rebound to a different
+ //type of buffer, so, let's copy their data to an ARRAY BUFFER and pass that one instead to be verified.
+ var wasReadBufferCreated = false;
+ try {
+ if (targetHint == gl.ELEMENT_ARRAY_BUFFER || targetHint == gl.TRANSFORM_FEEDBACK_BUFFER) {
+ var readBuffer = new Uint8Array(offset + numBytes);
+ gl.getBufferSubData(targetHint, 0, readBuffer);
+ buffer = gl.createBuffer();
+
+ wasReadBufferCreated = true;
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, readBuffer, gl.STATIC_DRAW);
+ }
+
+ var result = this.verifyNoTarget(buffer, reference, offset, numBytes);
+
+ if (wasReadBufferCreated)
+ gl.deleteBuffer(buffer);
+
+ return result;
+ } catch (err) {
+ if (wasReadBufferCreated)
+ gl.deleteBuffer(buffer);
+ throw err;
+ }
+ };
+
+ // BufferVerifier
+
+ /**
+ * @constructor
+ * @param {glsBufferTestUtil.VerifyType} verifyType
+ */
+ glsBufferTestUtil.BufferVerifier = function(verifyType) {
+ /** @type {glsBufferTestUtil.BufferVerifierBase} */ this.m_verifier = null;
+ switch (verifyType) {
+ case glsBufferTestUtil.VerifyType.AS_VERTEX_ARRAY: this.m_verifier = new glsBufferTestUtil.VertexArrayVerifier(); break;
+ case glsBufferTestUtil.VerifyType.AS_INDEX_ARRAY: this.m_verifier = new glsBufferTestUtil.IndexArrayVerifier(); break;
+ default:
+ testFailed('Unsupported verifier type');
+ }
+ };
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferVerifier.prototype.getMinSize = function() { return this.m_verifier.getMinSize(); };
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.BufferVerifier.prototype.getAlignment = function() { return this.m_verifier.getAlignment(); };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {Uint8Array} reference
+ * @param {number} numBytes
+ * @return {boolean}
+ */
+ glsBufferTestUtil.BufferVerifier.prototype.verifyNoTarget = function(buffer, reference, offset, numBytes) {
+ assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
+ assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
+ assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
+ return this.m_verifier.verifyNoTarget(buffer, reference, offset, numBytes);
+ };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {Uint8Array} reference
+ * @param {number} offset
+ * @param {number} numBytes
+ * @param {number} targetHint
+ * @return {boolean}
+ */
+ glsBufferTestUtil.BufferVerifier.prototype.verify = function(buffer, reference, offset, numBytes, targetHint) {
+ assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
+ assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
+ assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
+ return this.m_verifier.verify(buffer, reference, offset, numBytes, targetHint);
+ };
+
+ // VertexArrayVerifier
+
+ /**
+ * @constructor
+ * @extends {glsBufferTestUtil.BufferVerifierBase}
+ */
+ glsBufferTestUtil.VertexArrayVerifier = function() {
+ glsBufferTestUtil.BufferVerifierBase.call(this);
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ this.m_posLoc = 0;
+ this.m_byteVecLoc = 0;
+ /** @type {WebGLVertexArrayObject} */ this.m_vao = null;
+
+ /** @type {gluShaderUtil.GLSLVersion} */ var glslVersion = gluShaderUtil.getGLSLVersion(gl);
+
+ assertMsgOptions(gluShaderUtil.isGLSLVersionSupported(gl, glslVersion), 'Unsupported GLSL version', false, true);
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(
+ gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
+ 'in highp vec2 a_position;\n' +
+ 'in mediump vec3 a_byteVec;\n' +
+ 'out mediump vec3 v_byteVec;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(a_position, 0.0, 1.0);\n' +
+ ' v_byteVec = a_byteVec;\n' +
+ '}\n',
+
+ gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
+ 'in mediump vec3 v_byteVec;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = vec4(v_byteVec, 1.0);\n' +
+ '}\n'
+ ));
+
+ if (!this.m_program.isOk()) {
+ testFailed('Compile failed');
+ }
+
+ this.m_posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ this.m_byteVecLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_byteVec');
+
+ this.m_vao = gl.createVertexArray();
+ this.m_positionBuf = gl.createBuffer();
+ this.m_indexBuf = gl.createBuffer();
+ };
+
+ glsBufferTestUtil.VertexArrayVerifier.prototype = Object.create(glsBufferTestUtil.BufferVerifierBase.prototype);
+ glsBufferTestUtil.VertexArrayVerifier.prototype.constructor = glsBufferTestUtil.VertexArrayVerifier;
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.VertexArrayVerifier.prototype.getMinSize = function() { return 3 * 4; };
+
+ /**
+ * @return {number}
+ */
+ glsBufferTestUtil.VertexArrayVerifier.prototype.getAlignment = function() { return 1; };
+
+ /**
+ * deinit
+ */
+ glsBufferTestUtil.VertexArrayVerifier.prototype.deinit = function() {
+ if (this.m_vao) gl.deleteVertexArray(this.m_vao);
+ if (this.m_positionBuf) gl.deleteBuffer(this.m_positionBuf);
+ if (this.m_indexBuf) gl.deleteBuffer(this.m_indexBuf);
+ };
+
+ /**
+ * @param {number} gridSizeX
+ * @param {number} gridSizeY
+ * @return {Array<number>}
+ */
+ glsBufferTestUtil.computePositions = function(gridSizeX, gridSizeY) {
+ var positions = [];
+
+ for (var y = 0; y < gridSizeY; y++)
+ for (var x = 0; x < gridSizeX; x++) {
+ /** @type {number} */ var sx0 = (x + 0) / gridSizeX;
+ /** @type {number} */ var sy0 = (y + 0) / gridSizeY;
+ /** @type {number} */ var sx1 = (x + 1) / gridSizeX;
+ /** @type {number} */ var sy1 = (y + 1) / gridSizeY;
+ /** @type {number} */ var fx0 = 2.0 * sx0 - 1.0;
+ /** @type {number} */ var fy0 = 2.0 * sy0 - 1.0;
+ /** @type {number} */ var fx1 = 2.0 * sx1 - 1.0;
+ /** @type {number} */ var fy1 = 2.0 * sy1 - 1.0;
+ /** @type {number} */ var baseNdx = (y * gridSizeX + x) * 8;
+
+ positions[baseNdx + 0] = fx0; positions[baseNdx + 1] = fy0;
+ positions[baseNdx + 2] = fx0; positions[baseNdx + 3] = fy1;
+ positions[baseNdx + 4] = fx1; positions[baseNdx + 5] = fy0;
+ positions[baseNdx + 6] = fx1; positions[baseNdx + 7] = fy1;
+ }
+
+ return positions;
+ };
+
+ /**
+ * @param {number} gridSizeX
+ * @param {number} gridSizeY
+ * @return {Uint16Array}
+ */
+ glsBufferTestUtil.computeIndices = function(gridSizeX, gridSizeY) {
+ var indices = new Uint16Array(3 * 2 * gridSizeX * gridSizeY);
+
+ for (var quadNdx = 0; quadNdx < gridSizeX * gridSizeY; quadNdx++) {
+ /** @type {number} */ var v00 = quadNdx * 4 + 0;
+ /** @type {number} */ var v01 = quadNdx * 4 + 1;
+ /** @type {number} */ var v10 = quadNdx * 4 + 2;
+ /** @type {number} */ var v11 = quadNdx * 4 + 3;
+
+ assertMsgOptions(v11 < (1 << 16), 'Vertex index value won\'t fit into a 16-bit number', false, true);
+
+ indices[quadNdx * 6 + 0] = v10;
+ indices[quadNdx * 6 + 1] = v00;
+ indices[quadNdx * 6 + 2] = v01;
+
+ indices[quadNdx * 6 + 3] = v10;
+ indices[quadNdx * 6 + 4] = v01;
+ indices[quadNdx * 6 + 5] = v11;
+ }
+
+ return indices;
+ };
+
+ /**
+ * @param {Uint8Array} ptr
+ * @param {number} vtxNdx
+ * @return {Array<number>}
+ */
+ glsBufferTestUtil.fetchVtxColor = function(ptr, vtxNdx) {
+ return new tcuRGBA.RGBA([
+ ptr[vtxNdx * 3 + 0],
+ ptr[vtxNdx * 3 + 1],
+ ptr[vtxNdx * 3 + 2],
+ 255]).toVec();
+ };
+
+ /**
+ * @param {tcuSurface.Surface} dst
+ * @param {number} numQuads
+ * @param {number} rowLength
+ * @param {Uint8Array} inPtr
+ */
+ glsBufferTestUtil.renderQuadGridReference = function(dst, numQuads, rowLength, inPtr) {
+ dst.setSize(rowLength * glsBufferTestUtil.VERIFY_QUAD_SIZE, (Math.floor(numQuads / rowLength) + (numQuads % rowLength != 0 ? 1 : 0)) * glsBufferTestUtil.VERIFY_QUAD_SIZE);
+
+ /** @type {tcuTexture.PixelBufferAccess} */ var dstAccess = dst.getAccess();
+ dstAccess.clear([0, 0, 0, 1.0]);
+
+ for (var quadNdx = 0; quadNdx < numQuads; quadNdx++) {
+ /** @type {number} */ var x0 = (quadNdx % rowLength) * glsBufferTestUtil.VERIFY_QUAD_SIZE;
+ /** @type {number} */ var y0 = Math.floor(quadNdx / rowLength) * glsBufferTestUtil.VERIFY_QUAD_SIZE;
+ /** @type {Array<number>} */ var v00 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 0);
+ /** @type {Array<number>} */ var v10 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 1);
+ /** @type {Array<number>} */ var v01 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 2);
+ /** @type {Array<number>} */ var v11 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 3);
+
+ for (var y = 0; y < glsBufferTestUtil.VERIFY_QUAD_SIZE; y++)
+ for (var x = 0; x < glsBufferTestUtil.VERIFY_QUAD_SIZE; x++) {
+ /** @type {number} */ var fx = (x + 0.5) / glsBufferTestUtil.VERIFY_QUAD_SIZE;
+ /** @type {number} */ var fy = (y + 0.5) / glsBufferTestUtil.VERIFY_QUAD_SIZE;
+
+ /** @type {boolean} */ var tri = fx + fy <= 1.0;
+ /** @type {number} */ var tx = tri ? fx : (1.0 - fx);
+ /** @type {number} */ var ty = tri ? fy : (1.0 - fy);
+ /** @type {Array<number>} */ var t0 = tri ? v00 : v11;
+ /** @type {Array<number>} */ var t1 = tri ? v01 : v10;
+ /** @type {Array<number>} */ var t2 = tri ? v10 : v01;
+ /** @type {Array<number>} */ var color = deMath.add(
+ deMath.add(t0, deMath.scale(deMath.subtract(t1, t0), tx)),
+ deMath.scale(deMath.subtract(t2, t0), ty)
+ );
+
+ dstAccess.setPixel(color, x0 + x, y0 + y);
+ }
+ }
+ };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {Uint8Array} refPtr
+ * @param {number} offset
+ * @param {number} numBytes
+ * @return {boolean}
+ */
+ glsBufferTestUtil.VertexArrayVerifier.prototype.verifyNoTarget = function(buffer, refPtr, offset, numBytes) {
+ var numBytesInVtx = 3;
+ var numBytesInQuad = numBytesInVtx * 4;
+ var maxQuadsX = Math.min(128, Math.floor(gl.drawingBufferWidth / glsBufferTestUtil.VERIFY_QUAD_SIZE));
+ var maxQuadsY = Math.min(128, Math.floor(gl.drawingBufferHeight / glsBufferTestUtil.VERIFY_QUAD_SIZE));
+ var maxQuadsPerBatch = maxQuadsX * maxQuadsY;
+ var numVerified = 0;
+ var program = this.m_program.getProgram();
+ /** @type {tcuRGBA.RGBA} */ var threshold = /*TODO: renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(3,3,3,3);*/ new tcuRGBA.RGBA([3, 3, 3, 3]);
+ var isOk = true;
+
+ /** @type {Array<number>} */ var positions = [];
+ /** @type {Uint16Array} */var indices;
+
+ /** @type {tcuSurface.Surface} */ var rendered = new tcuSurface.Surface();
+ /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface();
+
+ // Can't render full quad with smaller buffers.
+ assertMsgOptions(numBytes >= numBytesInQuad, 'Number of bytes must be bigger than number of bytes per quad', false, true);
+
+ positions = glsBufferTestUtil.computePositions(maxQuadsX, maxQuadsY);
+ indices = glsBufferTestUtil.computeIndices(maxQuadsX, maxQuadsY);
+
+ // Reset buffer bindings.
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
+
+ // Setup rendering state.
+ gl.viewport(0, 0, maxQuadsX * glsBufferTestUtil.VERIFY_QUAD_SIZE, maxQuadsY * glsBufferTestUtil.VERIFY_QUAD_SIZE);
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.useProgram(program);
+ gl.bindVertexArray(this.m_vao);
+
+ // Upload positions
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(this.m_posLoc);
+ gl.vertexAttribPointer(this.m_posLoc, 2, gl.FLOAT, false, 0, 0);
+
+ // Upload indices
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(this.m_byteVecLoc);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+
+ while (numVerified < numBytes) {
+ /** @type {number} */ var numRemaining = numBytes - numVerified;
+ var isLeftoverBatch = numRemaining < numBytesInQuad;
+ /** @type {number} */ var numBytesToVerify = isLeftoverBatch ? numBytesInQuad : Math.min(maxQuadsPerBatch * numBytesInQuad, numRemaining - numRemaining % numBytesInQuad);
+ /** @type {number} */ var curOffset = isLeftoverBatch ? (numBytes - numBytesInQuad) : numVerified;
+ /** @type {number} */ var numQuads = Math.floor(numBytesToVerify / numBytesInQuad);
+ /** @type {number} */ var numCols = Math.min(maxQuadsX, numQuads);
+ /** @type {number} */ var numRows = Math.floor(numQuads / maxQuadsX) + (numQuads % maxQuadsX != 0 ? 1 : 0);
+ /** @type {string} */ var imageSetDesc = 'Bytes ' + (offset + curOffset) + ' to ' + (offset + curOffset + numBytesToVerify - 1);
+
+ assertMsgOptions(numBytesToVerify > 0 && numBytesToVerify % numBytesInQuad == 0, 'Bytes to verify must be greater than zero and must be a multiple of the bytes per quad', false, true);
+ assertMsgOptions(deMath.deInBounds32(curOffset, 0, numBytes), 'Offset out of bounds', false, true);
+ assertMsgOptions(deMath.deInRange32(curOffset + numBytesToVerify, curOffset, numBytes), 'Range of bytes to verify outside of bounds', false, true);
+
+ // Render batch.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.vertexAttribPointer(this.m_byteVecLoc, 3, gl.UNSIGNED_BYTE, true, 0, offset + curOffset);
+ gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_SHORT, 0);
+
+ glsBufferTestUtil.renderQuadGridReference(reference, numQuads, numCols, refPtr.subarray(offset + curOffset));
+
+ rendered.setSize(numCols * glsBufferTestUtil.VERIFY_QUAD_SIZE, numRows * glsBufferTestUtil.VERIFY_QUAD_SIZE);
+ rendered.readViewport(gl, [0, 0, numCols * glsBufferTestUtil.VERIFY_QUAD_SIZE, numRows * glsBufferTestUtil.VERIFY_QUAD_SIZE]);
+
+ if (!tcuImageCompare.pixelThresholdCompare('RenderResult', imageSetDesc, reference, rendered, threshold.toIVec(), tcuImageCompare.CompareLogMode.RESULT)) {
+ isOk = false;
+ break;
+ }
+
+ numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
+ }
+
+ gl.bindVertexArray(null);
+
+ return isOk;
+ };
+
+ // IndexArrayVerifier
+
+ /**
+ * @constructor
+ * @extends {glsBufferTestUtil.BufferVerifierBase}
+ */
+ glsBufferTestUtil.IndexArrayVerifier = function() {
+ glsBufferTestUtil.BufferVerifierBase.call(this);
+
+ this.m_program = null;
+ this.m_posLoc = 0;
+ this.m_colorLoc = 0;
+
+ /** @type {gluShaderUtil.GLSLVersion} */ var glslVersion = gluShaderUtil.GLSLVersion.V300_ES;
+
+ assertMsgOptions(gluShaderUtil.isGLSLVersionSupported(gl, glslVersion), 'GLSL version not supported', false, true);
+
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(
+ gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
+ 'in highp vec2 a_position;\n' +
+ 'in mediump vec3 a_color;\n' +
+ 'out mediump vec3 v_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(a_position, 0.0, 1.0);\n' +
+ ' v_color = a_color;\n' +
+ '}\n',
+
+ gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
+ 'in mediump vec3 v_color;\n' +
+ 'layout(location = 0) out mediump vec4 o_color;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' o_color = vec4(v_color, 1.0);\n' +
+ '}\n'));
+
+ if (!this.m_program.isOk()) {
+ testFailed('Compile failed');
+ }
+
+ this.m_posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
+ this.m_colorLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_color');
+
+ this.m_vao = gl.createVertexArray();
+ this.m_positionBuf = gl.createBuffer();
+ this.m_colorBuf = gl.createBuffer();
+ };
+
+ glsBufferTestUtil.IndexArrayVerifier.prototype = Object.create(glsBufferTestUtil.BufferVerifierBase.prototype);
+ glsBufferTestUtil.IndexArrayVerifier.prototype.constructor = glsBufferTestUtil.IndexArrayVerifier;
+
+ /**
+ * deinit
+ */
+ glsBufferTestUtil.IndexArrayVerifier.prototype.deinit = function() {
+ if (this.m_vao) gl.deleteVertexArray(this.m_vao);
+ if (this.m_positionBuf) gl.deleteBuffer(this.m_positionBuf);
+ if (this.m_colorBuf) gl.deleteBuffer(this.m_colorBuf);
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ glsBufferTestUtil.computeIndexVerifierPositions = function() {
+ var numPosX = 16;
+ var numPosY = 16;
+
+ var dst = [];
+
+ for (var y = 0; y < numPosY; y++) {
+ for (var x = 0; x < numPosX; x++) {
+ var xf = x / (numPosX - 1);
+ var yf = y / (numPosY - 1);
+
+ var offset = 2 * (y * numPosX + x);
+ dst[offset] = 2.0 * xf - 1.0;
+ dst[offset + 1] = 2.0 * yf - 1.0;
+ }
+ }
+
+ return dst;
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ glsBufferTestUtil.computeIndexVerifierColors = function() {
+ /** @type {number} */ var numColors = 256;
+ /** @type {number} */ var minVal = 0.1;
+ /** @type {number} */ var maxVal = 0.5;
+ var rnd = new deRandom.Random(0xabc231);
+
+ var dst = [];
+
+ for (var i = 0; i < numColors; ++i) {
+ dst[3 * i] = rnd.getFloat(minVal, maxVal);
+ dst[3 * i + 1] = rnd.getFloat(minVal, maxVal);
+ dst[3 * i + 2] = rnd.getFloat(minVal, maxVal);
+ }
+
+ return dst;
+ };
+
+ /**
+ * @param {Array<number>} dst
+ * @param {Array<number>} src
+ * @param {Uint8Array} indices
+ * @param {number} numIndices
+ */
+ glsBufferTestUtil.execVertexFetch = function(dst, src, indices, numIndices) {
+ for (var i = 0; i < numIndices; ++i)
+ dst[i] = src[indices[i]];
+ };
+
+ /**
+ * @param {WebGLBuffer} buffer
+ * @param {Uint8Array} refPtr
+ * @param {number} offset
+ * @param {number} numBytes
+ * @return {boolean}
+ */
+ glsBufferTestUtil.IndexArrayVerifier.prototype.verify = function(buffer, refPtr, offset, numBytes) {
+ var viewportW = Math.min(glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_WIDTH, gl.drawingBufferWidth);
+ var viewportH = Math.min(glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT, gl.drawingBufferHeight);
+ var minBytesPerBatch = 2;
+ /** @type {tcuRGBA.RGBA} */ var threshold = new tcuRGBA.RGBA([0, 0, 0, 0]);
+
+ var positions = [];
+ var colors = [];
+
+ var fetchedPos = [];
+ var fetchedColor = [];
+
+ /** @type {tcuSurface.Surface} */ var indexBufferImg = new tcuSurface.Surface(viewportW, viewportH);
+ /** @type {tcuSurface.Surface} */ var referenceImg = new tcuSurface.Surface(viewportW, viewportH);
+
+ var numVerified = 0;
+ var isOk = true;
+
+ positions = glsBufferTestUtil.computeIndexVerifierPositions();
+ colors = glsBufferTestUtil.computeIndexVerifierColors();
+
+ // Reset buffer bindings.
+ gl.bindVertexArray(this.m_vao);
+ gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
+
+ // Setup rendering state.
+ gl.viewport(0, 0, viewportW, viewportH);
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.useProgram(this.m_program.getProgram());
+ gl.enableVertexAttribArray(this.m_posLoc);
+ gl.enableVertexAttribArray(this.m_colorLoc);
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ONE);
+ gl.blendEquation(gl.FUNC_ADD);
+
+ while (numVerified < numBytes) {
+ var numRemaining = numBytes - numVerified;
+ var isLeftoverBatch = numRemaining < minBytesPerBatch;
+ var numBytesToVerify = isLeftoverBatch ? minBytesPerBatch : Math.min(glsBufferTestUtil.MAX_LINES_PER_INDEX_ARRAY_DRAW + 1, numRemaining);
+ var curOffset = isLeftoverBatch ? (numBytes - minBytesPerBatch) : numVerified;
+ /** @type {string} */ var imageSetDesc = 'Bytes ' + (offset + curOffset) + ' to ' + (offset + curOffset + numBytesToVerify - 1);
+
+ // Step 1: Render using index buffer.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STREAM_DRAW);
+ gl.vertexAttribPointer(this.m_posLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_colorBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STREAM_DRAW);
+ gl.vertexAttribPointer(this.m_colorLoc, 3, gl.FLOAT, false, 0, 0);
+
+ gl.drawElements(gl.LINE_STRIP, numBytesToVerify, gl.UNSIGNED_BYTE, offset + curOffset);
+ indexBufferImg.readViewport(gl);
+
+ // Step 2: Do manual fetch and render without index buffer.
+ glsBufferTestUtil.execVertexFetch(fetchedPos, positions, refPtr.subarray(offset + curOffset), numBytesToVerify);
+ glsBufferTestUtil.execVertexFetch(fetchedColor, colors, refPtr.subarray(offset + curOffset), numBytesToVerify);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(fetchedPos), gl.STREAM_DRAW);
+ gl.vertexAttribPointer(this.m_posLoc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.m_colorBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(fetchedColor), gl.STREAM_DRAW);
+ gl.vertexAttribPointer(this.m_colorLoc, 3, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.LINE_STRIP, 0, numBytesToVerify);
+ referenceImg.readViewport(gl, [0, 0, viewportW, viewportH]);
+
+ if (!tcuImageCompare.pixelThresholdCompare('RenderResult', imageSetDesc, referenceImg, indexBufferImg, threshold.toIVec(), tcuImageCompare.CompareLogMode.RESULT)) {
+ isOk = false;
+ break;
+ }
+
+ numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
+ }
+
+ gl.bindVertexArray(null);
+
+ return isOk;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js
new file mode 100644
index 0000000000..4dc3be70f3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js
@@ -0,0 +1,5415 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsBuiltinPrecisionTests');
+goog.require('framework.common.tcuFloatFormat');
+goog.require('framework.common.tcuInterval');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuMatrixUtil');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('modules.shared.glsBuiltinPrecisionTestsUnitTests');
+goog.require('modules.shared.glsShaderExecUtil');
+
+goog.scope(function() {
+
+ var glsBuiltinPrecisionTests = modules.shared.glsBuiltinPrecisionTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var tcuInterval = framework.common.tcuInterval;
+ var tcuFloatFormat = framework.common.tcuFloatFormat;
+ var deRandom = framework.delibs.debase.deRandom;
+ var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var deMath = framework.delibs.debase.deMath;
+ var deUtil = framework.delibs.debase.deUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var tcuMatrixUtil = framework.common.tcuMatrixUtil;
+ var ref = modules.shared.glsBuiltinPrecisionTestsUnitTests.cppreference;
+ var referenceComparison = modules.shared.glsBuiltinPrecisionTestsUnitTests.referenceComparison;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+ /** @typedef {(tcuInterval.Interval|Array<tcuInterval.Interval>|tcuMatrix.Matrix)} */
+ glsBuiltinPrecisionTests.Intervals;
+
+ /** @typedef {(number|Array<number>|tcuMatrix.Matrix)} */
+ glsBuiltinPrecisionTests.Value;
+
+ /** @typedef {(string)} */
+ glsBuiltinPrecisionTests.Typename;
+
+ //Change to true for WebGL unit testing
+ var enableUnittests = false;
+
+ /**
+ * @param {number} value
+ * @return {boolean}
+ */
+ glsBuiltinPrecisionTests.isFloat = function(value) {
+ return value % 1 !== 0;
+ };
+
+ /**
+ * @constructor
+ * @param {string} R
+ * @param {string=} P0
+ * @param {string=} P1
+ * @param {string=} P2
+ * @param {string=} P3
+ */
+ glsBuiltinPrecisionTests.Signature = function(R, P0, P1, P2, P3) {
+ this.Ret = R;
+ this.Arg0 = P0 === undefined ? 'void' : P0;
+ this.Arg1 = P1 === undefined ? 'void' : P1;
+ this.Arg2 = P2 === undefined ? 'void' : P2;
+ this.Arg3 = P3 === undefined ? 'void' : P3;
+ };
+
+ /** @typedef {Array<glsBuiltinPrecisionTests.FuncBase>} */
+ glsBuiltinPrecisionTests.FuncSet;
+
+ /**
+ * @constructor
+ * @template T
+ * @param {T} A0
+ * @param {T} A1
+ * @param {T} A2
+ * @param {T} A3
+ */
+ glsBuiltinPrecisionTests.Tuple4 = function(A0, A1, A2, A3) {
+ this.a = A0;
+ this.b = A1;
+ this.c = A2;
+ this.d = A3;
+ };
+
+ /**
+ * @typedef {!glsBuiltinPrecisionTests.Tuple4<string>}
+ */
+ glsBuiltinPrecisionTests.ParamNames;
+
+ /**
+ * Returns true for all other types except Void
+ * @param {string} typename
+ */
+ glsBuiltinPrecisionTests.isTypeValid = function(typename) {
+ if (typename === 'void')
+ return false;
+ return true;
+ };
+
+ /**
+ * Returns true for all other types except Void
+ * @param {*} In
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.numInputs = function(In) {
+ return (!glsBuiltinPrecisionTests.isTypeValid(In.In0) ? 0 :
+ !glsBuiltinPrecisionTests.isTypeValid(In.In1) ? 1 :
+ !glsBuiltinPrecisionTests.isTypeValid(In.In2) ? 2 :
+ !glsBuiltinPrecisionTests.isTypeValid(In.In3) ? 3 :
+ 4);
+ };
+
+ /**
+ * Returns true for all other types except Void
+ * @param {*} Out
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.numOutputs = function(Out) {
+ return (!glsBuiltinPrecisionTests.isTypeValid(Out.Out0) ? 0 :
+ !glsBuiltinPrecisionTests.isTypeValid(Out.Out1) ? 1 :
+ 2);
+ };
+
+ /**
+ * @constructor
+ * @param {glsBuiltinPrecisionTests.Typename=} In0_
+ * @param {glsBuiltinPrecisionTests.Typename=} In1_
+ * @param {glsBuiltinPrecisionTests.Typename=} In2_
+ * @param {glsBuiltinPrecisionTests.Typename=} In3_
+ */
+ glsBuiltinPrecisionTests.InTypes = function(In0_, In1_, In2_, In3_) {
+ this.In0 = In0_ === undefined ? 'void' : In0_;
+ this.In1 = In1_ === undefined ? 'void' : In1_;
+ this.In2 = In2_ === undefined ? 'void' : In2_;
+ this.In3 = In3_ === undefined ? 'void' : In3_;
+ };
+
+ /**
+ * @constructor
+ * @param {glsBuiltinPrecisionTests.Typename=} Out0_
+ * @param {glsBuiltinPrecisionTests.Typename=} Out1_
+ */
+ glsBuiltinPrecisionTests.OutTypes = function(Out0_, Out1_) {
+ this.Out0 = Out0_ === undefined ? 'void' : Out0_;
+ this.Out1 = Out1_ === undefined ? 'void' : Out1_;
+ };
+
+ /**
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.Environment = function() {
+ /** @type {Object} */ this.m_map = {};
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Variable} variable
+ * @param {*} value
+ */
+ glsBuiltinPrecisionTests.Environment.prototype.bind = function(variable, value) {
+ this.m_map[variable.getName()] = value;
+ };
+
+ /**
+ * @param {*} variable
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.Environment.prototype.lookup = function(variable) {
+ if (variable instanceof glsBuiltinPrecisionTests.Variable)
+ return this.m_map[variable.getName()];
+
+ throw new Error('Invalid lookup input: ' + variable);
+ };
+
+ /**
+ * @constructor
+ * @param {tcuFloatFormat.FloatFormat} format_
+ * @param {gluShaderUtil.precision} floatPrecision_
+ * @param {glsBuiltinPrecisionTests.Environment} env_
+ * @param {number=} callDepth_
+ */
+ glsBuiltinPrecisionTests.EvalContext = function(format_, floatPrecision_, env_, callDepth_) {
+ this.format = format_;
+ this.floatPrecision = floatPrecision_;
+ this.env = env_;
+ this.callDepth = callDepth_ === undefined ? 0 : callDepth_;
+ };
+
+ /**
+ * @param {string} typename typename
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {glsBuiltinPrecisionTests.Intervals} value
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.convert = function(typename, fmt, value) {
+ var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
+
+ if (value instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < value.length; i++)
+ ret.push(traits.doConvert(fmt, value[i]));
+ return ret;
+ }
+
+ if (value instanceof tcuMatrix.Matrix) {
+ var ret = new tcuMatrix.Matrix(value.rows, value.cols);
+ for (var i = 0; i < value.rows; i++)
+ for (var j = 0; j < value.cols; j++)
+ ret.set(i, j, traits.doConvert(fmt, value.get(i, j)));
+ return ret;
+ }
+
+ return traits.doConvert(fmt, value);
+ };
+
+ /**
+ * Returns true if every element of `ival` contains the corresponding element of `value`.
+ * @param {string} typename typename
+ * @param {glsBuiltinPrecisionTests.Intervals} ival
+ * @param {*} value
+ * @return {boolean}
+ */
+ glsBuiltinPrecisionTests.contains = function(typename, ival, value) {
+ var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
+ var contains = true;
+
+ if (value instanceof Array) {
+ for (var i = 0; i < value.length; i++)
+ contains &= traits.doContains(ival[i], value[i]);
+ return contains;
+ }
+
+ if (value instanceof tcuMatrix.Matrix) {
+ for (var i = 0; i < value.rows; i++)
+ for (var j = 0; j < value.cols; j++)
+ contains &= traits.doContains(ival.get(i, j), value.get(i, j));
+ return contains;
+ }
+
+ return traits.doContains(ival, value);
+ };
+
+ /**
+ * @param {string} typename typename
+ * @param {glsBuiltinPrecisionTests.Intervals} ival0
+ * @param {glsBuiltinPrecisionTests.Intervals} ival1
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.union = function(typename, ival0, ival1) {
+ var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
+
+ if (ival0 instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < ival0.length; i++)
+ ret.push(traits.doUnion(ival0[i], ival1[i]));
+ return ret;
+ }
+
+ if (ival0 instanceof tcuMatrix.Matrix) {
+ var ret = new tcuMatrix.Matrix(ival0.rows, ival0.cols);
+ for (var i = 0; i < ival0.rows; i++)
+ for (var j = 0; j < ival0.cols; j++)
+ ret.set(i, j, traits.doUnion(ival0.get(i, j), ival1.get(i, j)));
+ return ret;
+ }
+
+ return traits.doUnion(ival0, ival1);
+ };
+
+ /**
+ * @param {string} typename
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.Traits = function(typename) {
+ this.typename = typename;
+ this.rows = 1;
+ this.cols = 1;
+ };
+
+ glsBuiltinPrecisionTests.Traits.prototype.isScalar = function() {
+ return this.rows == 1 && this.cols == 1;
+ };
+
+ glsBuiltinPrecisionTests.Traits.prototype.isVector = function() {
+ return this.rows > 0 && this.cols == 1;
+ };
+
+ glsBuiltinPrecisionTests.Traits.prototype.isMatrix = function() {
+ return this.rows > 0 && this.cols > 1;
+ };
+
+ /**
+ * @param {string=} typename
+ */
+ glsBuiltinPrecisionTests.Traits.traitsFactory = function(typename) {
+ switch (typename) {
+ case 'boolean' : return new glsBuiltinPrecisionTests.TraitsBool();
+ case 'float' : case 'vec2' : case 'vec3' : case 'vec4' :
+ case 'mat2' : case 'mat2x3' : case 'mat2x4' :
+ case 'mat3x2' : case 'mat3' : case 'mat3x4' :
+ case 'mat4x2' : case 'mat4x3' : case 'mat4' :
+ return new glsBuiltinPrecisionTests.TraitsFloat(typename);
+ case 'int' : return new glsBuiltinPrecisionTests.TraitsInt();
+ case 'void' : return new glsBuiltinPrecisionTests.TraitsVoid();
+ default:
+ throw new Error('Invalid typename:' + typename);
+ }
+ };
+
+ glsBuiltinPrecisionTests.round = function(typename, fmt, value) {
+ var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
+
+ if (value instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < value.length; i++)
+ ret.push(traits.doRound(fmt, value[i]));
+ return ret;
+ }
+
+ if (value instanceof tcuMatrix.Matrix) {
+ var ret = new tcuMatrix.Matrix(value.rows, value.cols);
+ for (var i = 0; i < value.rows; i++)
+ for (var j = 0; j < value.cols; j++)
+ ret.set(i, j, traits.doRound(fmt, value.get(i, j)));
+ return ret;
+ }
+
+ return traits.doRound(fmt, value);
+ };
+
+ /**
+ * cast the input typed array to correct type
+ * @param {string} typename
+ * @param {goog.TypedArray} input
+ * @return {goog.TypedArray}
+ */
+ glsBuiltinPrecisionTests.cast = function(typename, input) {
+ var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
+ return traits.doCast(input);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Traits}
+ */
+ glsBuiltinPrecisionTests.TraitsVoid = function() {
+ glsBuiltinPrecisionTests.Traits.call(this, 'void');
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.TraitsVoid, glsBuiltinPrecisionTests.Traits);
+
+ /**
+ * @param {*} value
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doMakeIVal = function(value) {
+ return new tcuInterval.Interval();
+ };
+
+ /**
+ * @param {*} value1
+ * @param {*} value2
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doUnion = function(value1, value2) {
+ return new tcuInterval.Interval();
+ };
+
+ /**
+ * @param {*} value
+ * @return {boolean}
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doContains = function(value) {
+ return true;
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {tcuInterval.Interval} ival
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doConvert = function(fmt, ival) {
+ return new tcuInterval.Interval();
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {*} ival
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doRound = function(fmt, ival) {
+ return new tcuInterval.Interval();
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {*} ival
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doPrintIVal = function(fmt, ival) {
+ return '()';
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {*} value
+ */
+ glsBuiltinPrecisionTests.TraitsVoid.prototype.doPrintValue = function(fmt, value) {
+ return '()';
+ };
+
+ glsBuiltinPrecisionTests.dataTypeSize = function(detailedType) {
+ var size = [1, 1];
+ switch (detailedType) {
+ case 'vec2' : size[0] = 2; break;
+ case 'vec3' : size[0] = 3; break;
+ case 'vec4' : size[0] = 4; break;
+ case 'mat2' : size = [2 , 2]; break;
+ case 'mat2x3' : size = [3 , 2]; break;
+ case 'mat2x4' : size = [4 , 2]; break;
+
+ case 'mat3x2' : size = [2 , 3]; break;
+ case 'mat3' : size = [3 , 3]; break;
+ case 'mat3x4' : size = [4 , 3]; break;
+
+ case 'mat4x2' : size = [2 , 4]; break;
+ case 'mat4x3' : size = [3 , 4]; break;
+ case 'mat4' : size = [4 , 4]; break;
+ }
+ return size;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Traits}
+ * @param {string} typename
+ * @param {string=} detailedType
+ */
+ glsBuiltinPrecisionTests.ScalarTraits = function(typename, detailedType) {
+ glsBuiltinPrecisionTests.Traits.call(this, typename);
+ var size = glsBuiltinPrecisionTests.dataTypeSize(detailedType);
+ this.rows = size[0];
+ this.cols = size[1];
+
+ /** type{tcuInterval.Interval} */ this.iVal;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ScalarTraits, glsBuiltinPrecisionTests.Traits);
+
+ glsBuiltinPrecisionTests.ScalarTraits.prototype = Object.create(glsBuiltinPrecisionTests.Traits.prototype);
+ glsBuiltinPrecisionTests.ScalarTraits.prototype.constructor = glsBuiltinPrecisionTests.ScalarTraits;
+
+ /**
+ * @param {*} value
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.ScalarTraits.prototype.doMakeIVal = function(value) {
+ // Thankfully all scalar types have a well-defined conversion to `double`,
+ // hence Interval can represent their ranges without problems.
+ return new tcuInterval.Interval(/** @type {number} */ (value));
+ };
+
+ /**
+ * @param {tcuInterval.Interval} a
+ * @param {tcuInterval.Interval} b
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.ScalarTraits.prototype.doUnion = function(a, b) {
+ return a.operatorOrBinary(b);
+ };
+
+ /**
+ * @param {tcuInterval.Interval} a
+ * @param {number} value
+ * @return {boolean}
+ */
+ glsBuiltinPrecisionTests.ScalarTraits.prototype.doContains = function(a, value) {
+ return a.contains(new tcuInterval.Interval(value));
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {tcuInterval.Interval} ival
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.ScalarTraits.prototype.doConvert = function(fmt, ival) {
+ return fmt.convert(ival);
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {number} value
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.ScalarTraits.prototype.doRound = function(fmt, value) {
+ return fmt.roundOut(new tcuInterval.Interval(value), false);//TODO cast to double
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ScalarTraits}
+ * @param {string} detailedType
+ */
+ glsBuiltinPrecisionTests.TraitsFloat = function(detailedType) {
+ glsBuiltinPrecisionTests.ScalarTraits.call(this, 'float', detailedType);
+ };
+
+ glsBuiltinPrecisionTests.TraitsFloat.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype);
+ glsBuiltinPrecisionTests.TraitsFloat.prototype.constructor = glsBuiltinPrecisionTests.TraitsFloat;
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {tcuInterval.Interval} ival
+ */
+ glsBuiltinPrecisionTests.TraitsFloat.prototype.doPrintIVal = function(fmt, ival) {
+ return fmt.intervalToHex(ival);
+ };
+
+ /**
+ * @param {goog.TypedArray} input
+ * @return {goog.TypedArray}
+ */
+ glsBuiltinPrecisionTests.TraitsFloat.prototype.doCast = function(input) {
+ return new Float32Array(input.buffer);
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {number} value
+ */
+ glsBuiltinPrecisionTests.TraitsFloat.prototype.doPrintValue = function(fmt, value) {
+ return fmt.floatToHex(value);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ScalarTraits}
+ */
+ glsBuiltinPrecisionTests.TraitsBool = function() {
+ glsBuiltinPrecisionTests.ScalarTraits.call(this, 'boolean');
+ };
+
+ glsBuiltinPrecisionTests.TraitsBool.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype);
+ glsBuiltinPrecisionTests.TraitsBool.prototype.constructor = glsBuiltinPrecisionTests.TraitsBool;
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {tcuInterval.Interval} ival
+ */
+ glsBuiltinPrecisionTests.TraitsBool.prototype.doPrintIVal = function(fmt, ival) {
+ /** type{string} */ var os = '{';
+ var ifalse = new tcuInterval.Interval(0);
+ var itrue = new tcuInterval.Interval(1);
+ if (ival.contains(ifalse))
+ os += 'false';
+ if (ival.contains(ifalse) && ival.contains(itrue))
+ os += ', ';
+ if (ival.contains(itrue))
+ os += 'true';
+ os += '}';
+ return os;
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {boolean} value
+ */
+ glsBuiltinPrecisionTests.TraitsBool.prototype.doPrintValue = function(fmt, value) {
+ return value ? 'true' : 'false';
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ScalarTraits}
+ */
+ glsBuiltinPrecisionTests.TraitsInt = function() {
+ glsBuiltinPrecisionTests.ScalarTraits.call(this, 'int');
+ };
+
+ glsBuiltinPrecisionTests.TraitsInt.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype);
+ glsBuiltinPrecisionTests.TraitsInt.prototype.constructor = glsBuiltinPrecisionTests.TraitsInt;
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {tcuInterval.Interval} ival
+ */
+ glsBuiltinPrecisionTests.TraitsInt.prototype.doPrintIVal = function(fmt, ival) {
+ return '[' + (ival.lo()) + ', ' + (ival.hi()) + ']';
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {number} value
+ */
+ glsBuiltinPrecisionTests.TraitsInt.prototype.doPrintValue = function(fmt, value) {
+ return value.toString(10);
+ };
+
+ /**
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.Statement = function() {
+
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ */
+ glsBuiltinPrecisionTests.Statement.prototype.execute = function(ctx) {
+ this.doExecute(ctx);
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Statement.prototype.print = function() {
+ return this.doPrint();
+ };
+
+ glsBuiltinPrecisionTests.Statement.prototype.toString = function() {
+ return this.print();
+ };
+
+ /**
+ * Output the functions that this expression refers to
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ *
+ */
+ glsBuiltinPrecisionTests.Statement.prototype.getUsedFuncs = function(dst) {
+ this.doGetUsedFuncs(dst);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ */
+ glsBuiltinPrecisionTests.Statement.prototype.doExecute = function(ctx) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Statement.prototype.doPrint = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * Output the functions that this expression refers to
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ *
+ */
+ glsBuiltinPrecisionTests.Statement.prototype.doGetUsedFuncs = function(dst) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Statement}
+ * @param {glsBuiltinPrecisionTests.Variable} variable
+ * @param {glsBuiltinPrecisionTests.Expr} value
+ * @param {boolean} isDeclaration
+ */
+ glsBuiltinPrecisionTests.VariableStatement = function(variable, value, isDeclaration) {
+ this.m_variable = variable;
+ this.m_value = value;
+ this.m_isDeclaration = isDeclaration;
+
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.VariableStatement, glsBuiltinPrecisionTests.Statement);
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ */
+ glsBuiltinPrecisionTests.VariableStatement.prototype.doExecute = function(ctx) {
+ ctx.env.bind(this.m_variable, this.m_value.evaluate(ctx));
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.VariableStatement.prototype.doPrint = function() {
+ var v = this.m_variable;
+ var os = '';
+ if (this.m_isDeclaration)
+ os += gluVarType.declareVariable(gluVarType.getVarTypeOf(v.typename),
+ v.getName());
+ else
+ os += v.getName();
+
+ os += ' = ' + this.m_value.printExpr() + ';\n';
+
+ return os;
+ };
+
+ /**
+ * Output the functions that this expression refers to
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ *
+ */
+ glsBuiltinPrecisionTests.VariableStatement.prototype.doGetUsedFuncs = function(dst) {
+ this.m_value.getUsedFuncs(dst);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Variable} variable
+ * @param {glsBuiltinPrecisionTests.Expr} definiens
+ * @return {glsBuiltinPrecisionTests.VariableStatement}
+ */
+ glsBuiltinPrecisionTests.variableDeclaration = function(variable, definiens) {
+ return new glsBuiltinPrecisionTests.VariableStatement(variable, definiens, true);
+ };
+
+ /**
+ * @param {string} typename
+ * @param {string} name
+ * @param {glsBuiltinPrecisionTests.ExpandContext} ctx
+ * @param {glsBuiltinPrecisionTests.Expr} expr
+ * @return {glsBuiltinPrecisionTests.Variable}
+ */
+ glsBuiltinPrecisionTests.bindExpression = function(typename, name, ctx, expr) {
+ var variable = ctx.genSym(typename, name);
+ ctx.addStatement(glsBuiltinPrecisionTests.variableDeclaration(variable, expr));
+ return variable;
+ };
+
+ /**
+ * Common base class for all expressions regardless of their type.
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.ExprBase = function() {};
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.ExprBase.prototype.printExpr = function() {
+ return this.doPrintExpr();
+ };
+
+ glsBuiltinPrecisionTests.ExprBase.prototype.toString = function() {
+ return this.printExpr();
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.ExprBase.prototype.doPrintExpr = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * Output the functions that this expression refers to
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ *
+ */
+ glsBuiltinPrecisionTests.ExprBase.prototype.getUsedFuncs = function(/*FuncSet&*/ dst) {
+ this.doGetUsedFuncs(dst);
+ };
+
+ /**
+ * Output the functions that this expression refers to
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ *
+ */
+ glsBuiltinPrecisionTests.ExprBase.prototype.doGetUsedFuncs = function(/*FuncSet&*/ dst) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * Type-specific operations for an expression representing type typename.
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ExprBase}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ */
+ glsBuiltinPrecisionTests.Expr = function(typename) {
+ glsBuiltinPrecisionTests.ExprBase.call(this);
+ this.typename = typename;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Expr, glsBuiltinPrecisionTests.ExprBase);
+
+ /**
+ * Type-specific operations for an expression representing type typename.
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ */
+ glsBuiltinPrecisionTests.Expr.prototype.evaluate = function(ctx) {
+ return this.doEvaluate(ctx);
+ };
+
+ /**
+ * Type-specific operations for an expression representing type typename.
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ */
+ glsBuiltinPrecisionTests.Expr.prototype.doEvaluate = function(ctx) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Expr}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ * @param {string=} name
+ */
+ glsBuiltinPrecisionTests.Variable = function(typename, name) {
+ glsBuiltinPrecisionTests.Expr.call(this, typename);
+ /** @type {string} */ this.m_name = name || '<undefined>';
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Variable, glsBuiltinPrecisionTests.Expr);
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Variable.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Variable.prototype.doPrintExpr = function() {
+ return this.m_name;
+ };
+
+ glsBuiltinPrecisionTests.Variable.prototype.toString = function() {
+ return this.doPrintExpr();
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @return {*}
+ */
+ glsBuiltinPrecisionTests.Variable.prototype.doEvaluate = function(ctx) {
+ return ctx.env.lookup(this);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Variable}
+ * @param {*=} t
+ */
+ glsBuiltinPrecisionTests.Void = function(t) {
+ glsBuiltinPrecisionTests.Variable.call(this, 'void');
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Void, glsBuiltinPrecisionTests.Variable);
+
+ glsBuiltinPrecisionTests.Void.prototype.doEvaluate = function(ctx) {
+ return undefined;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Variable}
+ * @param {number} value
+ */
+ glsBuiltinPrecisionTests.Constant = function(value) {
+ glsBuiltinPrecisionTests.Variable.call(this, 'float');
+ this.m_value = value;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Constant, glsBuiltinPrecisionTests.Variable);
+
+ glsBuiltinPrecisionTests.Constant.prototype.doEvaluate = function(ctx) {
+ return new tcuInterval.Interval(this.m_value);
+ };
+
+ /**
+ * @constructor
+ * @param {*} typename
+ */
+ glsBuiltinPrecisionTests.DefaultSampling = function(typename) {
+ this.typename = typename;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Expr}
+ * @param {glsBuiltinPrecisionTests.Variable} vector
+ * @param {number} index
+ */
+ glsBuiltinPrecisionTests.VectorVariable = function(vector, index) {
+ glsBuiltinPrecisionTests.Expr.call(this, vector.typename);
+ this.m_vector = vector;
+ this.m_index = index;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.VectorVariable, glsBuiltinPrecisionTests.Expr);
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.VectorVariable.prototype.doEvaluate = function(ctx) {
+ var tmp = this.m_vector.doEvaluate(ctx);
+ return tmp[this.m_index];
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Expr}
+ * @param {glsBuiltinPrecisionTests.Variable} matrix
+ * @param {number} row
+ * @param {number} col
+ */
+ glsBuiltinPrecisionTests.MatrixVariable = function(matrix, row, col) {
+ glsBuiltinPrecisionTests.Expr.call(this, matrix.typename);
+ this.m_matrix = matrix;
+ this.m_row = row;
+ this.m_col = col;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.MatrixVariable, glsBuiltinPrecisionTests.Expr);
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.MatrixVariable.prototype.doEvaluate = function(ctx) {
+ var tmp = this.m_matrix.doEvaluate(ctx);
+ return tmp.get(this.m_row, this.m_col);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Expr}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ * @param {glsBuiltinPrecisionTests.Func} func
+ * @param {glsBuiltinPrecisionTests.Expr=} arg0
+ * @param {glsBuiltinPrecisionTests.Expr=} arg1
+ * @param {glsBuiltinPrecisionTests.Expr=} arg2
+ * @param {glsBuiltinPrecisionTests.Expr=} arg3
+ */
+ glsBuiltinPrecisionTests.Apply = function(typename, func, arg0, arg1, arg2, arg3) {
+ glsBuiltinPrecisionTests.Expr.call(this, typename);
+ this.m_func = func;
+ /** @type {glsBuiltinPrecisionTests.Tuple4} */ this.m_args;
+ if (arg0 instanceof glsBuiltinPrecisionTests.Tuple4)
+ this.m_args = /** @type {glsBuiltinPrecisionTests.Tuple4} */ (arg0);
+ else {
+ this.m_args = new glsBuiltinPrecisionTests.Tuple4(arg0 || new glsBuiltinPrecisionTests.Void(),
+ arg1 || new glsBuiltinPrecisionTests.Void(),
+ arg2 || new glsBuiltinPrecisionTests.Void(),
+ arg3 || new glsBuiltinPrecisionTests.Void());
+ }
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Apply, glsBuiltinPrecisionTests.Expr);
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Apply.prototype.doPrintExpr = function() {
+ var args = [this.m_args.a, this.m_args.b, this.m_args.c, this.m_args.d];
+ return this.m_func.print(args);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.Apply.prototype.doEvaluate = function(ctx) {
+ var debug = false;
+
+ if (debug) {
+ glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level = glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level || 0;
+ var level = glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level;
+ glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level++;
+ var name = this.m_func.constructor.toString();
+ name = name.replace(/[\s\S]*glsBuiltinPrecisionTests\./m, '').replace(/\.call[\s\S]*/m, '');
+ if (this.m_func.getName)
+ name += ' ' + this.m_func.getName();
+ console.log('<' + level + '> Function ' + name);
+ }
+
+ var a = this.m_args.a.evaluate(ctx);
+ var b = this.m_args.b.evaluate(ctx);
+ var c = this.m_args.c.evaluate(ctx);
+ var d = this.m_args.d.evaluate(ctx);
+ var retVal = this.m_func.applyFunction(ctx, a, b, c, d);
+
+ if (debug) {
+ console.log('<' + level + '> a: ' + a);
+ console.log('<' + level + '> b: ' + b);
+ console.log('<' + level + '> returning: ' + retVal);
+ glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level--;
+ }
+ return retVal;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Func} func
+ * @param {glsBuiltinPrecisionTests.Expr=} arg0
+ * @param {glsBuiltinPrecisionTests.Expr=} arg1
+ * @param {glsBuiltinPrecisionTests.Expr=} arg2
+ * @param {glsBuiltinPrecisionTests.Expr=} arg3
+ */
+ var app = function(func, arg0, arg1, arg2, arg3) {
+ return new glsBuiltinPrecisionTests.Apply('float', func, arg0, arg1, arg2, arg3);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ */
+ glsBuiltinPrecisionTests.Apply.prototype.doGetUsedFuncs = function(dst) {
+ this.m_func.getUsedFuncs(dst);
+ this.m_args.a.getUsedFuncs(dst);
+ this.m_args.b.getUsedFuncs(dst);
+ this.m_args.c.getUsedFuncs(dst);
+ this.m_args.d.getUsedFuncs(dst);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Apply}
+ * @param {glsBuiltinPrecisionTests.Func} func
+ * @param {glsBuiltinPrecisionTests.Expr=} arg0
+ * @param {glsBuiltinPrecisionTests.Expr=} arg1
+ * @param {glsBuiltinPrecisionTests.Expr=} arg2
+ * @param {glsBuiltinPrecisionTests.Expr=} arg3
+ */
+ glsBuiltinPrecisionTests.ApplyScalar = function(func, arg0, arg1, arg2, arg3) {
+ glsBuiltinPrecisionTests.Apply.call(this, 'float', func, arg0, arg1, arg2, arg3);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ApplyScalar, glsBuiltinPrecisionTests.Apply);
+
+ glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate = function(ctx) {
+ var debug = false;
+
+ if (debug) {
+ glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level = glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level || 0;
+ var level = glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level;
+ glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level++;
+ var name = this.m_func.constructor.toString();
+ name = name.replace(/[\s\S]*glsBuiltinPrecisionTests\./m, '').replace(/\.call[\s\S]*/m, '');
+ if (this.m_func.getName)
+ name += ' ' + this.m_func.getName();
+ console.log('scalar<' + level + '> Function ' + name);
+ }
+
+ var a = this.m_args.a.evaluate(ctx);
+ var b = this.m_args.b.evaluate(ctx);
+ var c = this.m_args.c.evaluate(ctx);
+ var d = this.m_args.d.evaluate(ctx);
+ if (a instanceof Array) {
+ var ret = [];
+ for (var i = 0; i < a.length; i++) {
+ var p0 = a instanceof Array ? a[i] : a;
+ var p1 = b instanceof Array ? b[i] : b;
+ var p2 = c instanceof Array ? c[i] : c;
+ var p3 = d instanceof Array ? d[i] : d;
+ ret.push(this.m_func.applyFunction(ctx, p0, p1, p2, p3));
+ }
+ return ret;
+ }
+
+ var retVal = this.m_func.applyFunction(ctx, a, b, c, d);
+
+ if (debug) {
+ console.log('scalar<' + level + '> a: ' + a);
+ console.log('scalar<' + level + '> b: ' + b);
+ console.log('scalar<' + level + '> return1: ' + ret);
+ console.log('scalar<' + level + '> return2: ' + retVal);
+ glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level--;
+ }
+
+ return retVal;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Apply}
+ */
+ glsBuiltinPrecisionTests.ApplyVar = function(typename, func, arg0, arg1, arg2, arg3) {
+ glsBuiltinPrecisionTests.Apply.call(this, typename, func, arg0, arg1, arg2, arg3);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ApplyVar, glsBuiltinPrecisionTests.Apply);
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.ApplyVar.prototype.doEvaluate = function(ctx) {
+ return this.m_func.applyFunction(ctx,
+ ctx.env.lookup(this.m_args.a), ctx.env.lookup(this.m_args.b),
+ ctx.env.lookup(this.m_args.c), ctx.env.lookup(this.m_args.d),
+ [this.m_args.a.getName(), this.m_args.b.getName(),
+ this.m_args.c.getName(), this.m_args.d.getName()]);
+ };
+
+ /**
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.FuncBase = function() {};
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.getName = function() {
+ return '';
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.getRequiredExtension = function() {
+ return '';
+ };
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.print = function(args) {
+ return '';
+ };
+
+ /**
+ * Index of output parameter, or -1 if none of the parameters is output.
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.getOutParamIndex = function() {
+ return -1;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.printDefinition = function() {
+ return this.doPrintDefinition();
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.doPrintDefinition = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * typedef set<const FuncBase*> FuncSet;
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.getUsedFuncs = function(dst) {
+ this.doGetUsedFuncs(dst);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ */
+ glsBuiltinPrecisionTests.FuncBase.prototype.doGetUsedFuncs = function(dst) {};
+
+ /*************************************/
+ /**
+ * \brief Function objects.
+ *
+ * Each Func object represents a GLSL function. It can be applied to interval
+ * arguments, and it returns the an interval that is a conservative
+ * approximation of the image of the GLSL function over the argument
+ * intervals. That is, it is given a set of possible arguments and it returns
+ * the set of possible values.
+ *
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FuncBase}
+ * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_>
+ */
+ glsBuiltinPrecisionTests.Func = function(Sig_) {
+ glsBuiltinPrecisionTests.FuncBase.call(this);
+ this.Sig = Sig_;
+ this.Ret = this.Sig.Ret;
+ this.Arg0 = this.Sig.Arg0;
+ this.Arg1 = this.Sig.Arg1;
+ this.Arg2 = this.Sig.Arg2;
+ this.Arg3 = this.Sig.Arg3;
+ };
+
+ glsBuiltinPrecisionTests.Func.prototype = Object.create(glsBuiltinPrecisionTests.FuncBase.prototype);
+ glsBuiltinPrecisionTests.Func.prototype.constructor = glsBuiltinPrecisionTests.Func;
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Func.prototype.print = function(args) {
+ return this.doPrint(args);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Intervals=} Iarg0
+ * @param {glsBuiltinPrecisionTests.Intervals=} Iarg1
+ * @param {glsBuiltinPrecisionTests.Intervals=} Iarg2
+ * @param {glsBuiltinPrecisionTests.Intervals=} Iarg3
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.Func.prototype.applyFunction = function(ctx, Iarg0, Iarg1, Iarg2, Iarg3, variablenames) {
+ return this.applyArgs(ctx, new glsBuiltinPrecisionTests.Tuple4(Iarg0, Iarg1, Iarg2, Iarg3), variablenames);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} args
+ * @return {glsBuiltinPrecisionTests.Intervals}
+ */
+ glsBuiltinPrecisionTests.Func.prototype.applyArgs = function(ctx, args, variablenames) {
+ return this.doApply(ctx, args, variablenames);
+ };
+
+ /**
+ * @return {glsBuiltinPrecisionTests.ParamNames}
+ */
+ glsBuiltinPrecisionTests.Func.prototype.getParamNames = function() {
+ return this.doGetParamNames();
+ };
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Func.prototype.doPrint = function(args) {
+ /** type{string} */ var os = this.getName() + '(';
+
+ // TODO: fix the generics
+ for (var i = 0; i < args.length; i++)
+ if (glsBuiltinPrecisionTests.isTypeValid(args[i].typename)) {
+ if (i != 0)
+ os += ', ';
+ os += args[i];
+ }
+
+ os += ')';
+
+ return os;
+ };
+
+ /**
+ * @return {glsBuiltinPrecisionTests.ParamNames} args
+ */
+ glsBuiltinPrecisionTests.Func.prototype.doGetParamNames = function() {
+ /** @type {glsBuiltinPrecisionTests.ParamNames} */ var names = new glsBuiltinPrecisionTests.Tuple4('a', 'b', 'c', 'd');
+ return names;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Func}
+ * @param {glsBuiltinPrecisionTests.Signature} Sig template <typename Sig>
+ *
+ */
+ glsBuiltinPrecisionTests.PrimitiveFunc = function(Sig) {
+ glsBuiltinPrecisionTests.Func.call(this, Sig);
+ this.Ret = Sig.Ret;
+ };
+
+ glsBuiltinPrecisionTests.PrimitiveFunc.prototype = Object.create(glsBuiltinPrecisionTests.Func.prototype);
+ glsBuiltinPrecisionTests.PrimitiveFunc.prototype.constructor = glsBuiltinPrecisionTests.PrimitiveFunc;
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {string} typename
+ *
+ */
+ glsBuiltinPrecisionTests.Cond = function(typename) {
+ var sig = new glsBuiltinPrecisionTests.Signature(typename, 'boolean', typename, typename);
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Cond, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ glsBuiltinPrecisionTests.Cond.prototype.getName = function() {
+ return '_cond';
+ };
+
+ glsBuiltinPrecisionTests.Cond.prototype.doPrint = function(args) {
+ var str = '(' + args[0] + ' ? ' + args[1] + ' : ' + args[2] + ')';
+ return str;
+ };
+
+ glsBuiltinPrecisionTests.Cond.prototype.doApply = function(ctx, iargs) {
+ var ret;
+ if (glsBuiltinPrecisionTests.contains(this.Sig.Arg0, iargs.a, 1))
+ ret = iargs.b;
+ if (glsBuiltinPrecisionTests.contains(this.Sig.Arg0, iargs.a, 0)) {
+ if (ret)
+ ret = glsBuiltinPrecisionTests.union(this.Sig.Ret, ret, iargs.c);
+ else
+ ret = iargs.c;
+ }
+ if (ret)
+ return ret;
+ return new tcuInterval.Interval();
+ };
+
+ /**
+ * If multipleInputs is false, GenVec duplicates first input to proper size
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {number} size
+ * @param {boolean=} multipleInputs
+ */
+ glsBuiltinPrecisionTests.GenVec = function(size, multipleInputs) {
+ var vecName = glsBuiltinPrecisionTests.sizeToName(size);
+ var p = [
+ size >= 1 ? 'float' : undefined,
+ size >= 2 ? 'float' : undefined,
+ size >= 3 ? 'float' : undefined,
+ size >= 4 ? 'float' : undefined
+ ];
+ var sig = new glsBuiltinPrecisionTests.Signature(vecName, p[0], p[1], p[2], p[3]);
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ this.size = size;
+ this.vecName = vecName;
+ this.multipleInputs = multipleInputs || false;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.GenVec, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ glsBuiltinPrecisionTests.GenVec.prototype.getName = function() {
+ return this.vecName;
+ };
+
+ glsBuiltinPrecisionTests.GenVec.prototype.doApply = function(ctx, iargs) {
+ if (this.size == 1)
+ return iargs.a;
+
+ var ret = this.multipleInputs ?
+ [iargs.a, iargs.b, iargs.c, iargs.d] :
+ [iargs.a, iargs.a, iargs.a, iargs.a];
+
+ return ret.slice(0, this.size);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.GenMat = function(rows, cols) {
+ var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
+ var vecName = glsBuiltinPrecisionTests.sizeToName(rows);
+ var p = [
+ cols >= 1 ? vecName : undefined,
+ cols >= 2 ? vecName : undefined,
+ cols >= 3 ? vecName : undefined,
+ cols >= 4 ? vecName : undefined
+ ];
+ var sig = new glsBuiltinPrecisionTests.Signature(name, p[0], p[1], p[2], p[3]);
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ this.rows = rows;
+ this.cols = cols;
+ this.name = name;
+ this.vecName = vecName;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.GenMat, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ glsBuiltinPrecisionTests.GenMat.prototype.getName = function() {
+ return this.name;
+ };
+
+ glsBuiltinPrecisionTests.GenMat.prototype.doApply = function(ctx, iargs) {
+ var ret = new tcuMatrix.Matrix(this.rows, this.cols);
+ var inputs = [iargs.a, iargs.b, iargs.c, iargs.d];
+
+ for (var i = 0; i < this.rows; i++)
+ for (var j = 0; j < this.cols; j++)
+ ret.set(i, j, inputs[j][i]);
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {string} typename
+ *
+ */
+ glsBuiltinPrecisionTests.CompareOperator = function(typename) {
+ var sig = new glsBuiltinPrecisionTests.Signature('boolean', typename, typename);
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.CompareOperator, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ glsBuiltinPrecisionTests.CompareOperator.prototype.doPrint = function(args) {
+ var str = '(' + args[0] + this.getSymbol() + args[1] + ')';
+ return str;
+ };
+
+ glsBuiltinPrecisionTests.CompareOperator.prototype.doApply = function(ctx, iargs) {
+ var arg0 = iargs.a;
+ var arg1 = iargs.b;
+
+ var ret = new tcuInterval.Interval();
+
+ if (this.canSucceed(arg0, arg1))
+ ret = new tcuInterval.Interval(1);
+ if (this.canFail(arg0, arg1))
+ ret.operatorOrAssignBinary(new tcuInterval.Interval(0));
+
+ return ret;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CompareOperator.prototype.getSymbol = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @param {tcuInterval.Interval} arg0
+ * @param {tcuInterval.Interval} arg1
+ * @return {boolean}
+ */
+ glsBuiltinPrecisionTests.CompareOperator.prototype.canSucceed = function(arg0, arg1) {
+ throw new Error('Virtual function. Please override.');
+ };
+ /**
+ * @param {tcuInterval.Interval} arg0
+ * @param {tcuInterval.Interval} arg1
+ * @return {boolean}
+ */
+ glsBuiltinPrecisionTests.CompareOperator.prototype.canFail = function(arg0, arg1) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CompareOperator}
+ * @param {string} typename
+ *
+ */
+ glsBuiltinPrecisionTests.LessThan = function(typename) {
+ glsBuiltinPrecisionTests.CompareOperator.call(this, typename);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.LessThan, glsBuiltinPrecisionTests.CompareOperator);
+
+ glsBuiltinPrecisionTests.LessThan.prototype.getSymbol = function() {
+ return '<';
+ };
+
+ glsBuiltinPrecisionTests.LessThan.prototype.canSucceed = function(a, b) {
+ return (a.lo() < b.hi());
+ };
+
+ glsBuiltinPrecisionTests.LessThan.prototype.canFail = function(a, b) {
+ return !(a.hi() < b.lo());
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ *
+ */
+ glsBuiltinPrecisionTests.FloatFunc1 = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ };
+
+ glsBuiltinPrecisionTests.FloatFunc1.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc1;
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.doApply = function(ctx, iargs) {
+ var a = /** @type {tcuInterval.Interval} */ (iargs.a);
+ return this.applyMonotone(ctx, a);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} iarg0
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.applyMonotone = function(ctx, iarg0) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {tcuInterval.Interval}
+ */
+ var body = function(x, y) {
+ x = x || 0;
+ return this.applyPoint(ctx, x);
+ };
+ ret = tcuInterval.applyMonotone1(iarg0, body.bind(this));
+
+ ret.operatorOrAssignBinary(this.innerExtrema(ctx, iarg0));
+
+ ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN)));
+
+ return ctx.format.convert(ret);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.innerExtrema = function(ctx, iargs) {
+ return new tcuInterval.Interval(); // empty interval, i.e. no extrema
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} arg0
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.applyPoint = function(ctx, arg0) {
+ var exact = this.applyExact(arg0);
+ var prec = this.precision(ctx, exact, arg0);
+
+ var a = new tcuInterval.Interval(exact);
+ var b = tcuInterval.withNumbers(-prec, prec);
+ return tcuInterval.Interval.operatorSum(a, b);
+ };
+
+ /**
+ * @param {number} x
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.applyExact = function(x) {
+ throw new Error('Internal error. Cannot apply');
+ };
+
+ /**
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.getCodomain = function() {
+ return tcuInterval.unbounded(true);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FloatFunc1.prototype.precision = function(ctx, x, y) {
+ return 0;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc1}
+ */
+ glsBuiltinPrecisionTests.Negate = function() {
+ glsBuiltinPrecisionTests.FloatFunc1.call(this);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Negate, glsBuiltinPrecisionTests.FloatFunc1);
+
+ glsBuiltinPrecisionTests.Negate.prototype.getName = function() {
+ return '_negate';
+ };
+
+ glsBuiltinPrecisionTests.Negate.prototype.doPrint = function(args) {
+ return '-' + args[0];
+ };
+
+ glsBuiltinPrecisionTests.Negate.prototype.precision = function(ctx, ret, x) {
+ return 0;
+ };
+ glsBuiltinPrecisionTests.Negate.prototype.applyExact = function(x) {
+ return -x;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc1}
+ */
+ glsBuiltinPrecisionTests.InverseSqrt = function() {
+ glsBuiltinPrecisionTests.FloatFunc1.call(this);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.InverseSqrt, glsBuiltinPrecisionTests.FloatFunc1);
+
+ glsBuiltinPrecisionTests.InverseSqrt.prototype.getName = function() {
+ return 'inversesqrt';
+ };
+
+ glsBuiltinPrecisionTests.InverseSqrt.prototype.precision = function(ctx, ret, x) {
+ if (x <= 0)
+ return NaN;
+ return ctx.format.ulp(ret, 2.0);
+ };
+
+ glsBuiltinPrecisionTests.InverseSqrt.prototype.applyExact = function(x) {
+ return 1 / Math.sqrt(x);
+ };
+
+ glsBuiltinPrecisionTests.InverseSqrt.prototype.getCodomain = function() {
+ return tcuInterval.withNumbers(0, Infinity);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc1}
+ */
+ glsBuiltinPrecisionTests.Round = function() {
+ glsBuiltinPrecisionTests.FloatFunc1.call(this);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Round, glsBuiltinPrecisionTests.FloatFunc1);
+
+ glsBuiltinPrecisionTests.Round.prototype.getName = function() {
+ return 'round';
+ };
+
+ glsBuiltinPrecisionTests.Round.prototype.precision = function(ctx, ret, x) {
+ return 0;
+ };
+
+ glsBuiltinPrecisionTests.Round.prototype.applyPoint = function(ctx, x) {
+ var truncated = Math.trunc(x);
+ var fract = x - truncated;
+ var ret = new tcuInterval.Interval();
+
+ // When x is inf or -inf, truncated would be inf or -inf too. Then fract
+ // would be NaN (inf - inf). While in native c code, it would be 0 (inf) or -0 (-inf).
+ // This behavior in JS differs from that in native c code.
+ if (Math.abs(fract) <= 0.5 || isNaN(fract))
+ ret.operatorOrAssignBinary(new tcuInterval.Interval(truncated));
+ if (Math.abs(fract) >= 0.5)
+ ret.operatorOrAssignBinary(new tcuInterval.Interval(truncated + deMath.deSign(fract)));
+
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc1}
+ * @param {string} name
+ * @param {tcuInterval.DoubleFunc1} func
+ */
+ glsBuiltinPrecisionTests.CFloatFunc1 = function(name, func) {
+ glsBuiltinPrecisionTests.FloatFunc1.call(this);
+ /** @type {string} */ this.m_name = name;
+ /** @type {tcuInterval.DoubleFunc1} */this.m_func = func;
+ };
+
+ glsBuiltinPrecisionTests.CFloatFunc1.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc1.prototype);
+ glsBuiltinPrecisionTests.CFloatFunc1.prototype.constructor = glsBuiltinPrecisionTests.CFloatFunc1;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CFloatFunc1.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @param {number} x
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.CFloatFunc1.prototype.applyExact = function(x) {
+ return this.m_func(x);
+ };
+
+ /**
+ * PrimitiveFunc<Signature<float, float, float> >
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2 = function() {
+ /** @type {glsBuiltinPrecisionTests.Signature} */ var Sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, Sig);
+ };
+
+ glsBuiltinPrecisionTests.FloatFunc2.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc2;
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.doApply = function(ctx, iargs) {
+ var a = /** @type {tcuInterval.Interval} */ (iargs.a);
+ var b = /** @type {tcuInterval.Interval} */ (iargs.b);
+ return this.applyMonotone(ctx, a, b);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} xi
+ * @param {tcuInterval.Interval} yi
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.applyMonotone = function(ctx, xi, yi) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @return {tcuInterval.Interval}
+ */
+ var body = function(x, y) {
+ x = x || 0;
+ y = y || 0;
+ return this.applyPoint(ctx, x, y);
+ };
+ ret = tcuInterval.applyMonotone2(xi, yi, body.bind(this));
+
+ ret.operatorOrAssignBinary(this.innerExtrema(ctx, xi, yi));
+
+ ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN)));
+
+ return ctx.format.convert(ret);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} xi
+ * @param {tcuInterval.Interval} yi
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.innerExtrema = function(ctx, xi, yi) {
+ return new tcuInterval.Interval(); // empty interval, i.e. no extrema
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} x
+ * @param {number} y
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.applyPoint = function(ctx, x, y) {
+ /** @type {number} */ var exact = this.applyExact(x, y);
+ var prec = this.precision(ctx, exact, x, y);
+
+ var a = new tcuInterval.Interval(exact);
+ var b = tcuInterval.withNumbers(-prec, prec);
+ return tcuInterval.Interval.operatorSum(a, b);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.applyExact = function(x, y) {
+ throw new Error('Virtual function. Please override');
+ };
+
+ /**
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.getCodomain = function() {
+ return tcuInterval.unbounded(true);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} ret
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FloatFunc2.prototype.precision = function(ctx, ret, x, y) {
+ throw new Error('Virtual function. Please override');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc2}
+ * @param {string} name
+ * @param {tcuInterval.DoubleFunc2} func
+ */
+ glsBuiltinPrecisionTests.CFloatFunc2 = function(name, func) {
+ glsBuiltinPrecisionTests.FloatFunc2.call(this);
+ /** @type {string} */ this.m_name = name;
+ /** @type {tcuInterval.DoubleFunc2} */ this.m_func = func;
+ };
+
+ glsBuiltinPrecisionTests.CFloatFunc2.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc2.prototype);
+ glsBuiltinPrecisionTests.CFloatFunc2.prototype.constructor = glsBuiltinPrecisionTests.CFloatFunc2;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CFloatFunc2.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.CFloatFunc2.prototype.applyExact = function(x, y) {
+ return this.m_func(x, y);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc2}
+ */
+ glsBuiltinPrecisionTests.InfixOperator = function() {
+ glsBuiltinPrecisionTests.FloatFunc2.call(this);
+ };
+
+ glsBuiltinPrecisionTests.InfixOperator.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc2.prototype);
+ glsBuiltinPrecisionTests.InfixOperator.prototype.constructor = glsBuiltinPrecisionTests.InfixOperator;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.InfixOperator.prototype.getSymbol = function() {
+ glsBuiltinPrecisionTests.FloatFunc2.call(this);
+ return '';
+ };
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.InfixOperator.prototype.doPrint = function(args) {
+ return '(' + args[0] + ' ' + this.getSymbol() + ' ' + args[1] + ')';
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} x
+ * @param {number} y
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.InfixOperator.prototype.applyPoint = function(ctx, x, y) {
+ /** @type {number} */ var exact = this.applyExact(x, y);
+
+ // Allow either representable number on both sides of the exact value,
+ // but require exactly representable values to be preserved.
+ return ctx.format.roundOut(new tcuInterval.Interval(exact), isFinite(x) && isFinite(y));
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.InfixOperator.prototype.precision = function(ctx, x, y, z) {
+ return 0;
+ };
+
+ /**
+ * Signature<float, float, float, float>
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3 = function() {
+ /** @type {glsBuiltinPrecisionTests.Signature} */ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float');
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ };
+
+ glsBuiltinPrecisionTests.FloatFunc3.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc3;
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.doApply = function(ctx, iargs) {
+ var a = /** @type {tcuInterval.Interval} */ (iargs.a);
+ var b = /** @type {tcuInterval.Interval} */ (iargs.b);
+ var c = /** @type {tcuInterval.Interval} */ (iargs.c);
+ var retVal = this.applyMonotone(ctx, a, b, c);
+ return retVal;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} xi
+ * @param {tcuInterval.Interval} yi
+ * @param {tcuInterval.Interval} zi
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.applyMonotone = function(ctx, xi, yi, zi) {
+ /**
+ * @param {number=} x
+ * @param {number=} y
+ * @param {number=} z
+ * @return {tcuInterval.Interval}
+ */
+ var body = function(x, y, z) {
+ x = x || 0;
+ y = y || 0;
+ z = z || 0;
+ return this.applyPoint(ctx, x, y, z);
+ };
+ var ret = tcuInterval.applyMonotone3(xi, yi, zi, body.bind(this));
+ var retVal;
+
+ ret.operatorOrAssignBinary(this.innerExtrema(ctx, xi, yi, zi));
+
+ ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN)));
+
+ retVal = ctx.format.convert(ret);
+ return retVal;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} xi
+ * @param {tcuInterval.Interval} yi
+ * @param {tcuInterval.Interval} zi
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.innerExtrema = function(ctx, xi, yi, zi) {
+ return new tcuInterval.Interval(); // empty interval, i.e. no extrema
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.applyPoint = function(ctx, x, y, z) {
+ /** @type {number} */ var exact = this.applyExact(x, y, z);
+ /** @type {number} */ var prec = this.precision(ctx, exact, x, y, z);
+
+ var a = new tcuInterval.Interval(exact);
+ var b = tcuInterval.withNumbers(-prec, prec);
+ return tcuInterval.Interval.operatorSum(a, b);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.applyExact = function(x, y, z) {
+ throw new Error('Virtual function. Please override');
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {number} result
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.precision = function(ctx, result, x, y, z) {
+ throw new Error('Virtual function. Please override');
+ };
+
+ /**
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.FloatFunc3.prototype.getCodomain = function() {
+ return tcuInterval.unbounded(true);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FloatFunc3}
+ */
+ glsBuiltinPrecisionTests.Clamp = function() {
+ glsBuiltinPrecisionTests.FloatFunc3.call(this);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Clamp, glsBuiltinPrecisionTests.FloatFunc3);
+
+ glsBuiltinPrecisionTests.Clamp.prototype.getName = function() {
+ return 'clamp';
+ };
+
+ glsBuiltinPrecisionTests.Clamp.prototype.applyExact = function(x, minVal, maxVal) {
+ var debug = false;
+ var retVal;
+
+ retVal = deMath.clamp(x, minVal, maxVal);
+ if (debug) {
+ console.log('> minVal: ' + minVal);
+ console.log('> maxVal: ' + maxVal);
+ console.log('> x: ' + x);
+ console.log('> ret: ' + retVal);
+ }
+ return retVal;
+
+ };
+
+ glsBuiltinPrecisionTests.Clamp.prototype.precision = function(ctx, result, x, minVal, maxVal) {
+ var debug = false;
+ var retVal;
+
+ retVal = minVal > maxVal ? NaN : 0;
+
+ if (debug) {
+ console.log('precision> minVal: ' + minVal);
+ console.log('precision> maxVal: ' + maxVal);
+ console.log('precision> x: ' + x);
+ console.log('precision> ret: ' + retVal);
+ }
+
+ return retVal;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.InfixOperator}
+ */
+ glsBuiltinPrecisionTests.Add = function() {
+ glsBuiltinPrecisionTests.InfixOperator.call(this);
+ };
+
+ glsBuiltinPrecisionTests.Add.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
+ glsBuiltinPrecisionTests.Add.prototype.constructor = glsBuiltinPrecisionTests.Add;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Add.prototype.getName = function() {
+ return 'add';
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Add.prototype.getSymbol = function() {
+ return '+';
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.Add.prototype.doApply = function(ctx, iargs) {
+ var a = /** @type {tcuInterval.Interval} */ (iargs.a);
+ var b = /** @type {tcuInterval.Interval} */ (iargs.b);
+ // Fast-path for common case
+ if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) {
+ /** type{tcuInterval.Interval} */ var ret;
+ ret = tcuInterval.setIntervalBounds(
+ function(dummy) {
+ return iargs.a.lo() + iargs.b.lo();
+ },
+ function(dummy) {
+ return iargs.a.hi() + iargs.b.hi();
+ });
+ return ctx.format.convert(ctx.format.roundOut(ret, true));
+ }
+ return this.applyMonotone(ctx, a, b);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.Add.prototype.applyExact = function(x, y) {
+ return x + y;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.InfixOperator}
+ */
+ glsBuiltinPrecisionTests.Sub = function() {
+ glsBuiltinPrecisionTests.InfixOperator.call(this);
+ };
+
+ glsBuiltinPrecisionTests.Sub.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
+ glsBuiltinPrecisionTests.Sub.prototype.constructor = glsBuiltinPrecisionTests.Sub;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Sub.prototype.getName = function() {
+ return 'sub';
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Sub.prototype.getSymbol = function() {
+ return '-';
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.Sub.prototype.doApply = function(ctx, iargs) {
+ var a = /** @type {tcuInterval.Interval} */ (iargs.a);
+ var b = /** @type {tcuInterval.Interval} */ (iargs.b);
+ var retVal;
+
+ // Fast-path for common case
+ if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) {
+ /** type{tcuInterval.Interval} */ var ret;
+ ret = tcuInterval.setIntervalBounds(
+ function(dummy) {
+ return iargs.a.lo() - iargs.b.hi();
+ },
+ function(dummy) {
+ return iargs.a.hi() - iargs.b.lo();
+ });
+ return ctx.format.convert(ctx.format.roundOut(ret, true));
+ }
+ retVal = this.applyMonotone(ctx, a, b);
+ return retVal;
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.Sub.prototype.applyExact = function(x, y) {
+ return x - y;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.InfixOperator}
+ */
+ glsBuiltinPrecisionTests.Mul = function() {
+ glsBuiltinPrecisionTests.InfixOperator.call(this);
+ };
+
+ glsBuiltinPrecisionTests.Mul.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
+ glsBuiltinPrecisionTests.Mul.prototype.constructor = glsBuiltinPrecisionTests.Mul;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Mul.prototype.getName = function() {
+ return 'mul';
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Mul.prototype.getSymbol = function() {
+ return '*';
+ };
+
+ glsBuiltinPrecisionTests.isNegative = function(n) {
+ return ((n = +n) || 1 / n) < 0;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.Mul.prototype.doApply = function(ctx, iargs) {
+ var a = /** @type {tcuInterval.Interval} */ (iargs.a);
+ var b = /** @type {tcuInterval.Interval} */ (iargs.b);
+ // Fast-path for common case
+ if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) {
+ /** type{tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+ if (glsBuiltinPrecisionTests.isNegative(a.hi())) {
+ a = a.operatorNegative();
+ b = b.operatorNegative();
+ }
+ if (a.lo() >= 0 && b.lo() >= 0) {
+ ret = tcuInterval.setIntervalBounds(
+ function(dummy) {
+ return iargs.a.lo() * iargs.b.lo();
+ },
+ function(dummy) {
+ return iargs.a.hi() * iargs.b.hi();
+ });
+ return ctx.format.convert(ctx.format.roundOut(ret, true));
+ }
+ if (a.lo() >= 0 && b.hi() <= 0) {
+ ret = tcuInterval.setIntervalBounds(
+ function(dummy) {
+ return iargs.a.hi() * iargs.b.lo();
+ },
+ function(dummy) {
+ return iargs.a.lo() * iargs.b.hi();
+ });
+ return ctx.format.convert(ctx.format.roundOut(ret, true));
+ }
+ }
+
+ return this.applyMonotone(ctx, a, b);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.Mul.prototype.applyExact = function(x, y) {
+ return x * y;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} xi
+ * @param {tcuInterval.Interval} yi
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.Mul.prototype.innerExtrema = function(ctx, xi, yi) {
+ if (((xi.contains(tcuInterval.NEGATIVE_INFINITY) || xi.contains(tcuInterval.POSITIVE_INFINITY)) && yi.contains(tcuInterval.ZERO)) ||
+ ((yi.contains(tcuInterval.NEGATIVE_INFINITY) || yi.contains(tcuInterval.POSITIVE_INFINITY)) && xi.contains(tcuInterval.ZERO)))
+ return new tcuInterval.Interval(NaN);
+
+ return new tcuInterval.Interval(); // empty interval, i.e. no extrema
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.InfixOperator}
+ */
+ glsBuiltinPrecisionTests.Div = function() {
+ glsBuiltinPrecisionTests.InfixOperator.call(this);
+ };
+
+ glsBuiltinPrecisionTests.Div.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
+ glsBuiltinPrecisionTests.Div.prototype.constructor = glsBuiltinPrecisionTests.Div;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Div.prototype.getName = function() {
+ return 'div';
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Div.prototype.getSymbol = function() {
+ return '/';
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {tcuInterval.Interval} nom
+ * @param {tcuInterval.Interval} den
+ * @return {tcuInterval.Interval}
+ */
+ glsBuiltinPrecisionTests.Div.prototype.innerExtrema = function(ctx, nom, den) {
+ var ret = new tcuInterval.Interval();
+ if (den.contains(tcuInterval.ZERO)) {
+ if (nom.contains(tcuInterval.ZERO))
+ ret.operatorOrAssignBinary(tcuInterval.NAN);
+ if (nom.lo() < 0 || nom.hi() > 0.0)
+ ret.operatorOrAssignBinary(tcuInterval.unbounded());
+ }
+
+ return ret;
+ };
+
+ glsBuiltinPrecisionTests.Div.prototype.precision = function(ctx, ret, nom, den) {
+ var fmt = ctx.format;
+
+ // \todo [2014-03-05 lauri] Check that the limits in GLSL 3.10 are actually correct.
+ // For now, we assume that division's precision is 2.5 ULP when the value is within
+ // [2^MINEXP, 2^MAXEXP-1]
+
+ if (den === 0)
+ return 0; // Result must be exactly inf
+ else if (deMath.deInBounds32(Math.abs(den),
+ deMath.deLdExp(1, fmt.getMinExp()),
+ deMath.deLdExp(1, fmt.getMaxExp() - 1)))
+ return fmt.ulp(ret, 2.5);
+ else
+ return Infinity; // Can be any number, but must be a number.
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.Div.prototype.applyExact = function(x, y) {
+ return x / y;
+ };
+
+ glsBuiltinPrecisionTests.Div.prototype.applyPoint = function(ctx, x, y) {
+ var ret = glsBuiltinPrecisionTests.FloatFunc2.prototype.applyPoint.call(this, ctx, x, y);
+ if (isFinite(x) && isFinite(y) && y != 0) {
+ var dst = ctx.format.convert(ret);
+ if (dst.contains(tcuInterval.NEGATIVE_INFINITY)) {
+ ret.operatorOrAssignBinary(-ctx.format.getMaxValue());
+ }
+ if (dst.contains(tcuInterval.POSITIVE_INFINITY)) {
+ ret.operatorOrAssignBinary(+ctx.format.getMaxValue());
+ }
+ }
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ */
+ glsBuiltinPrecisionTests.CompWiseFunc = function(typename, Sig) {
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, Sig);
+ this.typename = typename;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.CompWiseFunc, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CompWiseFunc.prototype.getName = function() {
+ return this.doGetScalarFunc().getName();
+ };
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CompWiseFunc.prototype.doPrint = function(args) {
+ return this.doGetScalarFunc().print(args);
+ };
+
+ /**
+ * @return {glsBuiltinPrecisionTests.Func}
+ */
+ glsBuiltinPrecisionTests.CompWiseFunc.prototype.doGetScalarFunc = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CompWiseFunc}
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.CompMatFuncBase = function(rows, cols) {
+ var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
+ glsBuiltinPrecisionTests.CompWiseFunc.call(this, 'float', new glsBuiltinPrecisionTests.Signature(name, name, name));
+ this.rows = rows;
+ this.cols = cols;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.CompMatFuncBase, glsBuiltinPrecisionTests.CompWiseFunc);
+
+ glsBuiltinPrecisionTests.CompMatFuncBase.prototype.doApply = function(ctx, iargs) {
+ var ret = new tcuMatrix.Matrix(this.rows, this.cols);
+ var fun = this.doGetScalarFunc();
+
+ for (var row = 0; row < this.rows; ++row)
+ for (var col = 0; col < this.cols; ++col)
+ ret.set(row, col, fun.applyFunction(ctx,
+ iargs.a.get(row, col),
+ iargs.b.get(row, col)));
+
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CompMatFuncBase}
+ * @param {function(new:glsBuiltinPrecisionTests.Func)} F
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.CompMatFunc = function(F, rows, cols) {
+ glsBuiltinPrecisionTests.CompMatFuncBase.call(this, rows, cols);
+ this.m_function = F;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.CompMatFunc, glsBuiltinPrecisionTests.CompMatFuncBase);
+
+ /**
+ * @return {glsBuiltinPrecisionTests.Func}
+ */
+ glsBuiltinPrecisionTests.CompMatFunc.prototype.doGetScalarFunc = function() {
+ return new this.m_function();
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Mul}
+ */
+ glsBuiltinPrecisionTests.ScalarMatrixCompMult = function() {
+ glsBuiltinPrecisionTests.Mul.call(this);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ScalarMatrixCompMult, glsBuiltinPrecisionTests.Mul);
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.ScalarMatrixCompMult.prototype.getName = function() {
+ return 'matrixCompMult';
+ };
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.ScalarMatrixCompMult.prototype.doPrint = function(args) {
+ return glsBuiltinPrecisionTests.Func.prototype.doPrint.call(this, args);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CompMatFunc}
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.MatrixCompMult = function(rows, cols) {
+ glsBuiltinPrecisionTests.CompMatFunc.call(this, glsBuiltinPrecisionTests.ScalarMatrixCompMult, rows, cols);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.MatrixCompMult, glsBuiltinPrecisionTests.CompMatFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.OuterProduct = function(rows, cols) {
+ var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
+ var sig = new glsBuiltinPrecisionTests.Signature(name, 'vec' + rows, 'vec' + cols);
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ this.rows = rows;
+ this.cols = cols;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.OuterProduct, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.OuterProduct.prototype.getName = function() {
+ return 'outerProduct';
+ };
+
+ glsBuiltinPrecisionTests.OuterProduct.prototype.doApply = function(ctx, iargs) {
+ var ret = new tcuMatrix.Matrix(this.rows, this.cols);
+ var mul = new glsBuiltinPrecisionTests.Mul();
+
+ for (var row = 0; row < this.rows; ++row) {
+ for (var col = 0; col < this.cols; ++col)
+ ret.set(row, col, mul.applyFunction(ctx, iargs.a[row], iargs.b[col]));
+ }
+
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.Transpose = function(rows, cols) {
+ var nameRet = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
+ var nameParam = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', cols, rows);
+ var sig = new glsBuiltinPrecisionTests.Signature(nameRet, nameParam);
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ this.rows = rows;
+ this.cols = cols;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Transpose, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.Transpose.prototype.getName = function() {
+ return 'transpose';
+ };
+
+ glsBuiltinPrecisionTests.Transpose.prototype.doApply = function(ctx, iargs) {
+ var ret = new tcuMatrix.Matrix(this.rows, this.cols);
+
+ for (var row = 0; row < this.rows; ++row)
+ for (var col = 0; col < this.cols; ++col)
+ ret.set(row, col, iargs.a.get(col, row));
+
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @param {*} In
+ */
+ glsBuiltinPrecisionTests.Inputs = function(In) {
+ // vector<typename In::In0> in0;
+ // vector<typename In::In1> in1;
+ // vector<typename In::In2> in2;
+ // vector<typename In::In3> in3;
+ this.in0 = [];
+ this.in1 = [];
+ this.in2 = [];
+ this.in3 = [];
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @param {*} Out
+ */
+ glsBuiltinPrecisionTests.Outputs = function(size, Out) {
+ // Outputs (size_t size) : out0(size), out1(size) {}
+ this.out0 = [];
+ this.out1 = [];
+ };
+
+ /**
+ * @constructor
+ * @param {*} In
+ * @param {*} Out
+ */
+ glsBuiltinPrecisionTests.Variables = function(In, Out) {
+ this.in0 = new glsBuiltinPrecisionTests.Variable(In.In0);
+ this.in1 = new glsBuiltinPrecisionTests.Variable(In.In1);
+ this.in2 = new glsBuiltinPrecisionTests.Variable(In.In2);
+ this.in3 = new glsBuiltinPrecisionTests.Variable(In.In3);
+ this.out0 = new glsBuiltinPrecisionTests.Variable(Out.Out0);
+ this.out1 = new glsBuiltinPrecisionTests.Variable(Out.Out1);
+ };
+
+ /**
+ * @constructor
+ * @param {function(new:glsBuiltinPrecisionTests.Func)} F
+ * @return {glsBuiltinPrecisionTests.GenFuncs}
+ */
+ glsBuiltinPrecisionTests.makeVectorizedFuncs = function(F) {
+ return new glsBuiltinPrecisionTests.GenFuncs(
+ new F(),
+ new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 2),
+ new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 3),
+ new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 4));
+ };
+
+ /**
+ * @constructor
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ */
+ glsBuiltinPrecisionTests.Sampling = function(typename) {
+ this.typename = typename;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ * @param {number=} size
+ * @return {glsBuiltinPrecisionTests.Sampling}
+ */
+ glsBuiltinPrecisionTests.SamplingFactory = function(typename, size) {
+ if (size > 1)
+ return new glsBuiltinPrecisionTests.DefaultSamplingVector(typename, size);
+ switch (typename) {
+ case 'vec4' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 4);
+ case 'vec3' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 3);
+ case 'vec2' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 2);
+ case 'boolean' : return new glsBuiltinPrecisionTests.DefaultSamplingBool(typename);
+ case 'float' : return new glsBuiltinPrecisionTests.DefaultSamplingFloat(typename);
+ case 'mat2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 2);
+ case 'mat2x3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 2);
+ case 'mat2x4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 2);
+ case 'mat3x2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 3);
+ case 'mat3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 3);
+ case 'mat3x4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 3);
+ case 'mat4x2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 4);
+ case 'mat4x3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 4);
+ case 'mat4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 4);
+ case 'int' : return new glsBuiltinPrecisionTests.DefaultSamplingInt(typename);
+ }
+ return new glsBuiltinPrecisionTests.DefaultSamplingVoid(typename);
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {Array<*>} arr
+ */
+ glsBuiltinPrecisionTests.Sampling.prototype.genFixeds = function(fmt, arr) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {gluShaderUtil.precision} precision
+ * @param {deRandom.Random} random
+ * @return {*}
+ */
+ glsBuiltinPrecisionTests.Sampling.prototype.genRandom = function(fmt, precision, random) {
+ return 0;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.Sampling.prototype.getWeight = function() {
+ return 0;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Sampling}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingVoid = function(typename) {
+ glsBuiltinPrecisionTests.Sampling.call(this, typename);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
+ glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingVoid;
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {Array<number>} dst
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype.genFixeds = function(fmt, dst) {
+ dst.push(NaN);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Sampling}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingBool = function(typename) {
+ glsBuiltinPrecisionTests.Sampling.call(this, typename);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingBool.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
+ glsBuiltinPrecisionTests.DefaultSamplingBool.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingBool;
+
+ /**
+ * @param {tcuFloatFormat.FloatFormat} fmt
+ * @param {Array<Boolean>} dst
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingBool.prototype.genFixeds = function(fmt, dst) {
+ dst.push(true);
+ dst.push(false);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Sampling}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingInt = function(typename) {
+ glsBuiltinPrecisionTests.Sampling.call(this, typename);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingInt.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
+ glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingInt;
+
+ glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.genRandom = function(fmt, prec, rnd) {
+ /** @type {number} */ var exp = rnd.getInt(0, this.getNumBits(prec) - 2);
+ /** @type {number} */ var sign = rnd.getBool() ? -1 : 1;
+
+ return sign * rnd.getInt(0, 1 << exp);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.genFixeds = function(fmt, dst) {
+ dst.push(0);
+ dst.push(-1);
+ dst.push(1);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.getWeight = function() {
+ return 1.0;
+ };
+
+ /**
+ * @param {gluShaderUtil.precision} prec
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.getNumBits = function(prec) {
+ switch (prec) {
+ case gluShaderUtil.precision.PRECISION_LOWP: return 8;
+ case gluShaderUtil.precision.PRECISION_MEDIUMP: return 16;
+ case gluShaderUtil.precision.PRECISION_HIGHP: return 32;
+ default:
+ throw new Error('Invalid precision: ' + prec);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Sampling}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingFloat = function(typename) {
+ glsBuiltinPrecisionTests.Sampling.call(this, typename);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
+ glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingFloat;
+
+ glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.genRandom = function(format, prec, rnd) {
+ /** type{number} */ var minExp = format.getMinExp();
+ /** type{number} */ var maxExp = format.getMaxExp();
+ /** type{boolean} */ var haveSubnormal = format.hasSubnormal() != tcuFloatFormat.YesNoMaybe.NO;
+
+ // Choose exponent so that the cumulative distribution is cubic.
+ // This makes the probability distribution quadratic, with the peak centered on zero.
+ /** type{number} */ var minRoot = deMath.deCbrt(minExp - 0.5 - (haveSubnormal ? 1.0 : 0.0));
+ /** type{number} */ var maxRoot = deMath.deCbrt(maxExp + 0.5);
+ /** type{number} */ var fractionBits = format.getFractionBits();
+ /** type{number} */ var exp = deMath.rint(Math.pow(rnd.getFloat(minRoot, maxRoot),
+ 3.0));
+ /** type{number} */ var base = 0.0; // integral power of two
+ /** type{number} */ var quantum = 0.0; // smallest representable difference in the binade
+ /** type{number} */ var significand = 0.0; // Significand.
+
+ // DE_ASSERT(fractionBits < std::numeric_limits<float>::digits);
+
+ // Generate some occasional special numbers
+ switch (rnd.getInt(0, 64)) {
+ case 0: return 0;
+ case 1: return Number.POSITIVE_INFINITY;
+ case 2: return Number.NEGATIVE_INFINITY;
+ case 3: return NaN;
+ default: break;
+ }
+
+ if (exp >= minExp) {
+ // Normal number
+ base = deMath.deFloatLdExp(1.0, exp);
+ quantum = deMath.deFloatLdExp(1.0, exp - fractionBits);
+ } else {
+ // Subnormal
+ base = 0.0;
+ quantum = deMath.deFloatLdExp(1.0, minExp - fractionBits);
+ }
+
+ switch (rnd.getInt(0, 16)) {
+ // The highest number in this binade, significand is all bits one.
+ case 0:
+ significand = base - quantum;
+ break;
+ // Significand is one.
+ case 1:
+ significand = quantum;
+ break;
+ // Significand is zero.
+ case 2:
+ significand = 0.0;
+ break;
+ // Random (evenly distributed) significand.
+ default: {
+ /** type{number} */ var intFraction = rnd.getInt() & ((1 << fractionBits) - 1);
+ significand = intFraction * quantum;
+ }
+ }
+
+ // Produce positive numbers more often than negative.
+ return (rnd.getInt(0, 3) == 0 ? -1.0 : 1.0) * (base + significand);
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.genFixeds = function(format, dst) {
+ /** @type {number} */ var minExp = format.getMinExp();
+ /** @type {number} */ var maxExp = format.getMaxExp();
+ /** @type {number} */ var fractionBits = format.getFractionBits();
+ /** @type {number} */ var minQuantum = deMath.deFloatLdExp(1.0, minExp - fractionBits);
+ /** @type {number} */ var minNormalized = deMath.deFloatLdExp(1.0, minExp);
+ /** @type {number} */ var maxQuantum = deMath.deFloatLdExp(1.0, maxExp - fractionBits);
+
+ // If unit testing is enabled, include exact numbers
+ if (enableUnittests) {
+ dst.push(0.2);
+ dst.push(0.5);
+ }
+
+ // NaN
+ dst.push(NaN);
+ // Zero
+ dst.push(0.0);
+
+ for (var sign = -1; sign <= 1; sign += 2) {
+ // Smallest subnormal
+ dst.push(sign * minQuantum);
+
+ // Largest subnormal
+ dst.push(sign * (minNormalized - minQuantum));
+
+ // Smallest normalized
+ dst.push(sign * minNormalized);
+
+ // Next smallest normalized
+ dst.push(sign * (minNormalized + minQuantum));
+
+ dst.push(sign * 0.5);
+ dst.push(sign * 1.0);
+ dst.push(sign * 2.0);
+
+ // Largest number
+ dst.push(sign * (deMath.deFloatLdExp(1.0, maxExp) +
+ (deMath.deFloatLdExp(1.0, maxExp) - maxQuantum)));
+
+ dst.push(sign * Number.POSITIVE_INFINITY);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Sampling}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ * @param {number} size
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingVector = function(typename, size) {
+ glsBuiltinPrecisionTests.Sampling.call(this, typename);
+ this.size = size;
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingVector.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
+ glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingVector;
+
+ glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.genRandom = function(fmt, prec, rnd) {
+ /** @type {Array<*>} */ var ret = [];
+
+ for (var ndx = 0; ndx < this.size; ++ndx)
+ ret[ndx] = glsBuiltinPrecisionTests.SamplingFactory(this.typename).genRandom(fmt, prec, rnd);
+
+ return ret;
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.genFixeds = function(fmt, dst) {
+ /** @type {Array<*>} */ var scalars = [];
+
+ glsBuiltinPrecisionTests.SamplingFactory(this.typename).genFixeds(fmt, scalars);
+
+ for (var scalarNdx = 0; scalarNdx < scalars.length; ++scalarNdx) {
+ var value = [];
+ for (var i = 0; i < this.size; i++)
+ value[i] = scalars[scalarNdx];
+ dst.push(value);
+ }
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.getWeight = function() {
+ return Math.pow(glsBuiltinPrecisionTests.SamplingFactory(this.typename).getWeight(), this.size);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Sampling}
+ * @param {glsBuiltinPrecisionTests.Typename} typename
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.DefaultSamplingMatrix = function(typename, rows, cols) {
+ glsBuiltinPrecisionTests.Sampling.call(this, typename);
+ this.rows = rows;
+ this.cols = cols;
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
+ glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingMatrix;
+
+ glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.genRandom = function(fmt, prec, rnd) {
+ /** @type {tcuMatrix.Matrix} */ var ret = new tcuMatrix.Matrix(this.rows, this.cols);
+ var sampler = glsBuiltinPrecisionTests.SamplingFactory(this.typename);
+
+ for (var rowNdx = 0; rowNdx < this.rows; ++rowNdx)
+ for (var colNdx = 0; colNdx < this.cols; ++colNdx)
+ ret.set(rowNdx, colNdx, sampler.genRandom(fmt, prec, rnd));
+
+ return ret;
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.genFixeds = function(fmt, dst) {
+ /** @type {Array<number>} */ var scalars = [];
+
+ glsBuiltinPrecisionTests.SamplingFactory(this.typename).genFixeds(fmt, scalars);
+
+ for (var scalarNdx = 0; scalarNdx < scalars.length; ++scalarNdx)
+ dst.push(new tcuMatrix.Matrix(this.rows, this.cols, scalars[scalarNdx]));
+
+ if (this.cols == this.rows) {
+ var mat = new tcuMatrix.Matrix(this.rows, this.cols, 0);
+ var x = 1;
+ mat.set(0, 0, x);
+ for (var ndx = 0; ndx < this.cols; ++ndx) {
+ mat.set(this.cols - 1 - ndx, ndx, x);
+ x *= 2;
+ }
+ dst.push(mat);
+ }
+ };
+
+ glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.getWeight = function() {
+ return Math.pow(glsBuiltinPrecisionTests.SamplingFactory(this.typename).getWeight(), this.rows * this.cols);
+ };
+
+ /**
+ * @constructor
+ * @param {number=} size
+ * @param {glsBuiltinPrecisionTests.InTypes} In
+ */
+ glsBuiltinPrecisionTests.Samplings = function(In, size) {
+ this.in0 = glsBuiltinPrecisionTests.SamplingFactory(In.In0, size);
+ this.in1 = glsBuiltinPrecisionTests.SamplingFactory(In.In1, size);
+ this.in2 = glsBuiltinPrecisionTests.SamplingFactory(In.In2, size);
+ this.in3 = glsBuiltinPrecisionTests.SamplingFactory(In.In3, size);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.InTypes} In
+ * @param {number=} size
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Samplings}
+ */
+ glsBuiltinPrecisionTests.DefaultSamplings = function(In, size) {
+ glsBuiltinPrecisionTests.Samplings.call(this, In, size);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsBuiltinPrecisionTests.Context} context
+ * @param {string} name
+ * @param {string} extension
+ */
+ glsBuiltinPrecisionTests.PrecisionCase = function(context, name, extension) {
+ /** @type {string} */ this.m_extension = extension === undefined ? '' : extension;
+ /** @type {glsBuiltinPrecisionTests.Context} */ this.m_ctx = context;
+ /** @type {*} */ this.m_status;
+ /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(1234); // (0xdeadbeefu + context.testContext.getCommandLine().getBaseSeed())
+ tcuTestCase.DeqpTest.call(this, name, extension);
+ };
+
+ glsBuiltinPrecisionTests.PrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsBuiltinPrecisionTests.PrecisionCase.prototype.constructor = glsBuiltinPrecisionTests.PrecisionCase;
+
+ /**
+ * @return {tcuFloatFormat.FloatFormat}
+ */
+ glsBuiltinPrecisionTests.PrecisionCase.prototype.getFormat = function() {
+ return this.m_ctx.floatFormat;
+ };
+
+ /**
+ * Return an output value extracted from flat array
+ * @param {goog.NumberArray} output
+ * @param {number} index Index of the element to extract
+ * @param {*} reference Reference for type informaion
+ * @return {glsBuiltinPrecisionTests.Value}
+ */
+ glsBuiltinPrecisionTests.getOutput = function(output, index, reference) {
+ if (reference instanceof Array) {
+ var ret = [];
+ var size = reference.length;
+ for (var i = 0; i < size; i++)
+ ret[i] = output[size * index + i];
+ return ret;
+ }
+ if (reference instanceof tcuMatrix.Matrix) {
+ var ret = new tcuMatrix.Matrix(reference.rows, reference.cols);
+ var size = reference.rows * reference.cols;
+ for (var i = 0; i < reference.rows; i++)
+ for (var j = 0; j < reference.cols; j++)
+ ret.set(i, j, output[size * index + j * reference.rows + i]);
+ return ret;
+ }
+
+ return output[index];
+ };
+ /**
+ * @param {glsBuiltinPrecisionTests.Variables} variables Variables<In, Out>
+ * @param {glsBuiltinPrecisionTests.Inputs} inputs Inputs<In>
+ * @param {glsBuiltinPrecisionTests.Statement} stmt
+ */
+ glsBuiltinPrecisionTests.PrecisionCase.prototype.testStatement = function(variables, inputs, stmt) {
+ /** @type {tcuFloatFormat.FloatFormat} */ var fmt = this.getFormat();
+ /** @type {number} */ var inCount = glsBuiltinPrecisionTests.numInputs(this.In);
+ /** @type {number} */ var outCount = glsBuiltinPrecisionTests.numOutputs(this.Out);
+ /** @type {number} */ var numValues = (inCount > 0) ? inputs.in0.length : 1;
+ /** @type {tcuFloatFormat.FloatFormat} */ var highpFmt = this.m_ctx.highpFormat;
+ var outputs = [];
+ /** @type {number} */ var maxMsgs = 100;
+ /** @type {number} */ var numErrors = 0;
+ /** @type {glsShaderExecUtil.ShaderSpec} */ var spec = new glsShaderExecUtil.ShaderSpec();
+ /** @type {glsBuiltinPrecisionTests.Environment} */ var env = new glsBuiltinPrecisionTests.Environment(); // Hoisted out of the inner loop for optimization.
+
+ switch (inCount) {
+ case 4: DE_ASSERT(inputs.in3.length == numValues);
+ case 3: DE_ASSERT(inputs.in2.length == numValues);
+ case 2: DE_ASSERT(inputs.in1.length == numValues);
+ case 1: DE_ASSERT(inputs.in0.length == numValues);
+ default: break;
+ }
+ if (enableUnittests)
+ numValues = 2;
+
+ // TODO: Fix logging
+ //Print out the statement and its definitions
+ // bufferedLogToConsole("Statement: " + stmt);
+ // var funcInfo = ''
+ // var funcs = {};
+ // stmt.getUsedFuncs(funcs);
+ // for (var key in funcs) {
+ // var func = funcs[key];
+ // funcInfo += func.printDefinition();
+ // };
+ // if (funcInfo.length > 0)
+ // bufferedLogToConsole('Reference definitions:' + funcInfo);
+
+ // Initialize ShaderSpec from precision, variables and statement.
+
+ spec.globalDeclarations = 'precision ' + gluShaderUtil.getPrecisionName(this.m_ctx.precision) + ' float;\n';
+
+ if (this.m_extension.length > 0)
+ spec.globalDeclarations += '#extension ' + this.m_extension + ' : require\n';
+
+ spec.inputs = [];
+
+ switch (inCount) {
+ case 4: spec.inputs[3] = this.makeSymbol(variables.in3);
+ case 3: spec.inputs[2] = this.makeSymbol(variables.in2);
+ case 2: spec.inputs[1] = this.makeSymbol(variables.in1);
+ case 1: spec.inputs[0] = this.makeSymbol(variables.in0);
+ default: break;
+ }
+
+ spec.outputs = [];
+
+ switch (outCount) {
+ case 2: spec.outputs[1] = this.makeSymbol(variables.out1);
+ case 1: spec.outputs[0] = this.makeSymbol(variables.out0);
+ default: break;
+ }
+
+ spec.source = stmt;
+
+ if (enableUnittests == false) {
+ // Run the shader with inputs.
+ /** @type {glsShaderExecUtil.ShaderExecutor} */
+ var executor = glsShaderExecUtil.createExecutor(this.m_ctx.shaderType, spec);
+ /** @type {Array<*>} */ var inputArr =
+ [
+ tcuMatrixUtil.flatten(inputs.in0), tcuMatrixUtil.flatten(inputs.in1), tcuMatrixUtil.flatten(inputs.in2), tcuMatrixUtil.flatten(inputs.in3)
+ ];
+
+ // executor.log(log());
+ if (!executor.isOk())
+ testFailed('Shader compilation failed');
+
+ executor.useProgram();
+ var outputArray = executor.execute(numValues, inputArr);
+
+ switch (outCount) {
+ case 2:
+ outputs[1] = glsBuiltinPrecisionTests.cast(this.Out.Out1, outputArray[1]);
+ case 1:
+ outputs[0] = glsBuiltinPrecisionTests.cast(this.Out.Out0, outputArray[0]);
+ default: break;
+ }
+ }
+
+ // Initialize environment with dummy values so we don't need to bind in inner loop.
+
+ var in0 = new tcuInterval.Interval();
+ var in1 = new tcuInterval.Interval();
+ var in2 = new tcuInterval.Interval();
+ var in3 = new tcuInterval.Interval();
+ var reference0 = new tcuInterval.Interval();
+ var reference1 = new tcuInterval.Interval();
+
+ env.bind(variables.in0, in0);
+ env.bind(variables.in1, in1);
+ env.bind(variables.in2, in2);
+ env.bind(variables.in3, in3);
+ env.bind(variables.out0, reference0);
+ env.bind(variables.out1, reference1);
+
+ // For each input tuple, compute output reference interval and compare
+ // shader output to the reference.
+ for (var valueNdx = 0; valueNdx < numValues; valueNdx++) {
+ /** @type {boolean} */ var result = true;
+ var value0, value1;
+ var msg = '';
+
+ var in0_ = glsBuiltinPrecisionTests.convert(this.Arg0, fmt, glsBuiltinPrecisionTests.round(this.Arg0, fmt, inputs.in0[valueNdx]));
+ var in1_ = glsBuiltinPrecisionTests.convert(this.Arg1, fmt, glsBuiltinPrecisionTests.round(this.Arg1, fmt, inputs.in1[valueNdx]));
+ var in2_ = glsBuiltinPrecisionTests.convert(this.Arg2, fmt, glsBuiltinPrecisionTests.round(this.Arg2, fmt, inputs.in2[valueNdx]));
+ var in3_ = glsBuiltinPrecisionTests.convert(this.Arg3, fmt, glsBuiltinPrecisionTests.round(this.Arg3, fmt, inputs.in3[valueNdx]));
+
+ env.bind(variables.in0, in0_);
+ env.bind(variables.in1, in1_);
+ env.bind(variables.in2, in2_);
+ env.bind(variables.in3, in3_);
+
+ stmt.execute(new glsBuiltinPrecisionTests.EvalContext(fmt, this.m_ctx.precision, env));
+
+ switch (outCount) {
+ case 2:
+ reference1 = glsBuiltinPrecisionTests.convert(this.Out.Out1, highpFmt, env.lookup(variables.out1));
+ if (enableUnittests)
+ result = referenceComparison(reference1, valueNdx + outCount - 1, this.m_ctx.floatFormat);
+ else {
+ value1 = glsBuiltinPrecisionTests.getOutput(outputs[1], valueNdx, reference1);
+ if (!glsBuiltinPrecisionTests.contains(this.Out.Out1, reference1, value1)) {
+ msg = 'Shader output 1 (' + value1 + ') is outside acceptable range: ' + reference1;
+ result = false;
+ }
+ }
+ case 1:
+ reference0 = glsBuiltinPrecisionTests.convert(this.Out.Out0, highpFmt, env.lookup(variables.out0));
+ if (enableUnittests)
+ result = referenceComparison(reference0, valueNdx + outCount - 1, this.m_ctx.floatFormat);
+ else {
+ value0 = glsBuiltinPrecisionTests.getOutput(outputs[0], valueNdx, reference0);
+ if (!glsBuiltinPrecisionTests.contains(this.Out.Out0, reference0, value0)) {
+ msg = 'Shader output 0 (' + value0 + ') is outside acceptable range: ' + reference0;
+ result = false;
+ }
+ }
+ default: break;
+ }
+
+ if (!result)
+ ++numErrors;
+
+ if (!result && numErrors <= maxMsgs) {
+ /** @type {string} */ var builder = '';
+
+ builder += (result ? 'Passed' : 'Failed') + '\n' + msg + '\n sample:\n' + valueNdx;
+
+ if (inCount > 0) {
+ builder += '\t' + variables.in0.getName() + ' = ' +
+ inputs.in0[valueNdx] + '\n';
+ }
+
+ if (inCount > 1) {
+ builder += '\t' + variables.in1.getName() + ' = ' +
+ inputs.in1[valueNdx] + '\n';
+ }
+
+ if (inCount > 2) {
+ builder += '\t' + variables.in2.getName() + ' = ' +
+ inputs.in2[valueNdx] + '\n';
+ }
+
+ if (inCount > 3) {
+ builder += '\t' + variables.in3.getName() + ' = ' +
+ inputs.in3[valueNdx] + '\n';
+ }
+
+ if (enableUnittests == false) {
+ if (outCount > 0) {
+ builder += '\t' + variables.out0.getName() + ' = ' +
+ value0 + '\n' +
+ '\tExpected range: ' +
+ reference0 + '\n';
+ }
+
+ if (outCount > 1) {
+ builder += '\t' + variables.out1.getName() + ' = ' +
+ value1 + '\n' +
+ '\tExpected range: ' +
+ reference1 + '\n';
+ }
+ }
+ bufferedLogToConsole(builder);
+ }
+ }
+
+ if (numErrors > maxMsgs) {
+ bufferedLogToConsole('(Skipped ' + (numErrors - maxMsgs) + ' messages.)');
+ }
+
+ if (numErrors == 0) {
+ testPassed('All ' + numValues + ' inputs passed.');
+ } else {
+ testFailed('' + numErrors + '/' + numValues + ' inputs failed.');
+ }
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Variable} variable Variable<typename>
+ * @return {glsShaderExecUtil.Symbol}
+ */
+ glsBuiltinPrecisionTests.PrecisionCase.prototype.makeSymbol = function(variable) {
+ var v = variable;
+ return new glsShaderExecUtil.Symbol(v.getName(), gluVarType.getVarTypeOf(v.typename, this.m_size, this.m_ctx.precision));
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Tuple4}
+ * @param {*} in0
+ * @param {*} in1
+ * @param {*} in2
+ * @param {*} in3
+ */
+ glsBuiltinPrecisionTests.InTuple = function(in0, in1, in2, in3) {
+ glsBuiltinPrecisionTests.Tuple4.call(this, in0, in1, in2, in3);
+ };
+
+ glsBuiltinPrecisionTests.InTuple.prototype = Object.create(glsBuiltinPrecisionTests.Tuple4.prototype);
+ glsBuiltinPrecisionTests.InTuple.prototype.constructor = glsBuiltinPrecisionTests.InTuple;
+
+ /**
+ * @param {*} In
+ * @param {glsBuiltinPrecisionTests.Samplings} samplings Samplings<In>
+ * @param {tcuFloatFormat.FloatFormat} floatFormat
+ * @param {gluShaderUtil.precision} intPrecision
+ * @param {number} numSamples
+ * @param {deRandom.Random} rnd
+ * @return {glsBuiltinPrecisionTests.Inputs}
+ */
+ glsBuiltinPrecisionTests.generateInputs = function(In, samplings, floatFormat, intPrecision, numSamples, rnd) {
+ /*Inputs<In>*/ var ret = new glsBuiltinPrecisionTests.Inputs(In);
+ /*Inputs<In>*/ var fixedInputs = new glsBuiltinPrecisionTests.Inputs(In);
+ // set<InTuple<In>, InputLess<InTuple<In> > > seenInputs;
+ /** @type {Array<glsBuiltinPrecisionTests.InTuple,glsBuiltinPrecisionTests.InputLess>} */
+ var seenInputs = [];
+
+ samplings.in0.genFixeds(floatFormat, fixedInputs.in0);
+ samplings.in1.genFixeds(floatFormat, fixedInputs.in1);
+ samplings.in2.genFixeds(floatFormat, fixedInputs.in2);
+ samplings.in3.genFixeds(floatFormat, fixedInputs.in3);
+
+ for (var ndx0 = 0; ndx0 < fixedInputs.in0.length; ++ndx0) {
+ for (var ndx1 = 0; ndx1 < fixedInputs.in1.length; ++ndx1) {
+ for (var ndx2 = 0; ndx2 < fixedInputs.in2.length; ++ndx2) {
+ for (var ndx3 = 0; ndx3 < fixedInputs.in3.length; ++ndx3) {
+ var tuple = new glsBuiltinPrecisionTests.InTuple(fixedInputs.in0[ndx0],
+ fixedInputs.in1[ndx1],
+ fixedInputs.in2[ndx2],
+ fixedInputs.in3[ndx3]);
+
+ seenInputs.push(tuple);
+ ret.in0.push(tuple.a);
+ ret.in1.push(tuple.b);
+ ret.in2.push(tuple.c);
+ ret.in3.push(tuple.d);
+ }
+ }
+ }
+ }
+
+ for (var ndx = 0; ndx < numSamples; ++ndx) {
+ var in0 = samplings.in0.genRandom(floatFormat, intPrecision, rnd);
+ var in1 = samplings.in1.genRandom(floatFormat, intPrecision, rnd);
+ var in2 = samplings.in2.genRandom(floatFormat, intPrecision, rnd);
+ var in3 = samplings.in3.genRandom(floatFormat, intPrecision, rnd);
+ var tuple = new glsBuiltinPrecisionTests.InTuple(in0, in1, in2, in3);
+
+ // if (de::contains(seenInputs, tuple))
+ // continue;
+
+ seenInputs.push(tuple);
+ ret.in0.push(in0);
+ ret.in1.push(in1);
+ ret.in2.push(in2);
+ ret.in3.push(in3);
+ }
+
+ return ret;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrecisionCase}
+ * @param {string} name
+ * @param {glsBuiltinPrecisionTests.FuncBase} func
+ */
+ glsBuiltinPrecisionTests.FuncCaseBase = function(context, name, func) {
+ glsBuiltinPrecisionTests.PrecisionCase.call(this, context, name, func.getRequiredExtension());
+ };
+
+ glsBuiltinPrecisionTests.FuncCaseBase.prototype = Object.create(glsBuiltinPrecisionTests.PrecisionCase.prototype);
+ glsBuiltinPrecisionTests.FuncCaseBase.prototype.constructor = glsBuiltinPrecisionTests.FuncCaseBase;
+
+ glsBuiltinPrecisionTests.FuncCaseBase.prototype.iterate = function() {
+
+ assertMsgOptions(!(this.m_extension !== undefined && this.m_extension.trim() !== '') &&
+ !sglrGLContext.isExtensionSupported(gl, this.m_extension),
+ 'Unsupported extension: ' + this.m_extension, false, true);
+
+ this.runTest();
+
+ // m_status.setTestContextResult(m_testCtx);
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FuncCaseBase}
+ * @param {glsBuiltinPrecisionTests.Context} context
+ * @param {string} name
+ * @param {glsBuiltinPrecisionTests.Func} func
+ */
+ glsBuiltinPrecisionTests.InOutFuncCase = function(context, name, func) {
+ glsBuiltinPrecisionTests.FuncCaseBase.call(this, context, name, func);
+ this.Sig = func.Sig;
+ this.m_func = func;
+ this.Ret = func.Sig.Ret;
+ this.Arg0 = func.Sig.Arg0;
+ this.Arg1 = func.Sig.Arg1;
+ this.Arg2 = func.Sig.Arg2;
+ this.Arg3 = func.Sig.Arg3;
+ this.In = new glsBuiltinPrecisionTests.InTypes(this.Arg0, this.Arg2, this.Arg3);
+ this.Out = new glsBuiltinPrecisionTests.OutTypes(this.Ret, this.Arg1);
+ this.m_size = this.m_func.m_size;
+ };
+
+ glsBuiltinPrecisionTests.InOutFuncCase.prototype = Object.create(glsBuiltinPrecisionTests.FuncCaseBase.prototype);
+ glsBuiltinPrecisionTests.InOutFuncCase.prototype.constructor = glsBuiltinPrecisionTests.InOutFuncCase;
+
+ /**
+ * Samplings<In>
+ * @return {glsBuiltinPrecisionTests.Samplings}
+ */
+ glsBuiltinPrecisionTests.InOutFuncCase.prototype.getSamplings = function() {
+ return new glsBuiltinPrecisionTests.DefaultSamplings(this.In, this.m_size);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Signature} Sig_
+ */
+ glsBuiltinPrecisionTests.InOutFuncCase.prototype.runTest = function(Sig_) {
+ /** @type {glsBuiltinPrecisionTests.Inputs} */ var inputs = (glsBuiltinPrecisionTests.generateInputs(
+ this.In,
+ this.getSamplings(),
+ this.m_ctx.floatFormat,
+ this.m_ctx.precision,
+ this.m_ctx.numRandoms,
+ this.m_rnd));
+
+ var variables = new glsBuiltinPrecisionTests.Variables(this.In, this.Out);
+ // Variables<In, Out> variables;
+ //
+ variables.out0 = new glsBuiltinPrecisionTests.Variable(this.Out.Out0, 'out0');
+ variables.out1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, 'out1');
+ variables.in0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, 'in0');
+ variables.in1 = new glsBuiltinPrecisionTests.Variable(this.Arg2, 'in1');
+ variables.in2 = new glsBuiltinPrecisionTests.Variable(this.Arg3, 'in2');
+ variables.in3 = new glsBuiltinPrecisionTests.Variable('void', 'in3');
+
+ var expr = glsBuiltinPrecisionTests.applyVar(this.m_func,
+ variables.in0, variables.out1,
+ variables.in1, variables.in2);
+ var stmt = glsBuiltinPrecisionTests.variableAssignment(variables.out0, expr);
+
+ this.testStatement(variables, inputs, stmt);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FuncCaseBase}
+ * @param {glsBuiltinPrecisionTests.Context} context
+ * @param {string} name
+ * @param {glsBuiltinPrecisionTests.Func} func
+ */
+ glsBuiltinPrecisionTests.FuncCase = function(context, name, func) {
+ glsBuiltinPrecisionTests.FuncCaseBase.call(this, context, name, func);
+ this.Sig = func.Sig;
+ this.m_func = func;
+ this.Ret = func.Sig.Ret;
+ this.Arg0 = func.Sig.Arg0;
+ this.Arg1 = func.Sig.Arg1;
+ this.Arg2 = func.Sig.Arg2;
+ this.Arg3 = func.Sig.Arg3;
+ this.In = new glsBuiltinPrecisionTests.InTypes(this.Arg0, this.Arg1, this.Arg2, this.Arg3);
+ this.Out = new glsBuiltinPrecisionTests.OutTypes(this.Ret);
+ this.m_size = this.m_func.m_size;
+ };
+
+ glsBuiltinPrecisionTests.FuncCase.prototype = Object.create(glsBuiltinPrecisionTests.FuncCaseBase.prototype);
+ glsBuiltinPrecisionTests.FuncCase.prototype.constructor = glsBuiltinPrecisionTests.FuncCase;
+
+ /**
+ * Samplings<In>
+ * @return {glsBuiltinPrecisionTests.Samplings}
+ */
+ glsBuiltinPrecisionTests.FuncCase.prototype.getSamplings = function() {
+ return new glsBuiltinPrecisionTests.DefaultSamplings(this.In, this.m_size);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Signature} Sig_
+ */
+ glsBuiltinPrecisionTests.FuncCase.prototype.runTest = function(Sig_) {
+ /** @type {glsBuiltinPrecisionTests.Inputs} */ var inputs = (glsBuiltinPrecisionTests.generateInputs(
+ this.In,
+ this.getSamplings(),
+ this.m_ctx.floatFormat,
+ this.m_ctx.precision,
+ this.m_ctx.numRandoms,
+ this.m_rnd));
+
+ var variables = new glsBuiltinPrecisionTests.Variables(this.In, this.Out);
+ // Variables<In, Out> variables;
+ //
+ variables.out0 = new glsBuiltinPrecisionTests.Variable(this.Ret, 'out0');
+ variables.out1 = new glsBuiltinPrecisionTests.Variable('void', 'out1');
+ variables.in0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, 'in0');
+ variables.in1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, 'in1');
+ variables.in2 = new glsBuiltinPrecisionTests.Variable(this.Arg2, 'in2');
+ variables.in3 = new glsBuiltinPrecisionTests.Variable(this.Arg3, 'in3');
+
+ var expr = glsBuiltinPrecisionTests.applyVar(this.m_func,
+ variables.in0, variables.in1,
+ variables.in2, variables.in3);
+ var stmt = glsBuiltinPrecisionTests.variableAssignment(variables.out0, expr);
+
+ this.testStatement(variables, inputs, stmt);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Func} func
+ * @param {glsBuiltinPrecisionTests.Variable} arg0
+ * @param {glsBuiltinPrecisionTests.Variable} arg1
+ * @param {glsBuiltinPrecisionTests.Variable} arg2
+ * @param {glsBuiltinPrecisionTests.Variable} arg3
+ * @return {glsBuiltinPrecisionTests.ApplyVar}
+ */
+ glsBuiltinPrecisionTests.applyVar = function(func, arg0, arg1, arg2, arg3) {
+ return new glsBuiltinPrecisionTests.ApplyVar(func.Sig, func, arg0, arg1, arg2, arg3);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Variable} variable
+ * @param {glsBuiltinPrecisionTests.ApplyVar} value
+ * @param {boolean} isDeclaration
+ */
+ glsBuiltinPrecisionTests.variableStatement = function(variable, value, isDeclaration) {
+ return new glsBuiltinPrecisionTests.VariableStatement(variable, value, isDeclaration);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Variable} variable
+ * @param {glsBuiltinPrecisionTests.ApplyVar} value
+ */
+ glsBuiltinPrecisionTests.variableAssignment = function(variable, value) {
+ return glsBuiltinPrecisionTests.variableStatement(variable, value, false);
+ };
+
+ /**
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.CaseFactories = function() {};
+
+ /**
+ * @return {Array<glsBuiltinPrecisionTests.CaseFactory>}
+ */
+ glsBuiltinPrecisionTests.CaseFactories.prototype.getFactories = function() {};
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CaseFactories}
+ */
+ glsBuiltinPrecisionTests.BuiltinFuncs = function() {
+ /** @type {Array<glsBuiltinPrecisionTests.CaseFactory>} */ this.m_factories = [];
+ };
+
+ glsBuiltinPrecisionTests.BuiltinFuncs.prototype = Object.create(glsBuiltinPrecisionTests.CaseFactories.prototype);
+ glsBuiltinPrecisionTests.BuiltinFuncs.prototype.constructor = glsBuiltinPrecisionTests.BuiltinFuncs;
+
+ /**
+ * @return {Array<glsBuiltinPrecisionTests.CaseFactory>}
+ */
+ glsBuiltinPrecisionTests.BuiltinFuncs.prototype.getFactories = function() {
+ return this.m_factories.slice();
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.CaseFactory} fact
+ */
+ glsBuiltinPrecisionTests.BuiltinFuncs.prototype.addFactory = function(fact) {
+ this.m_factories.push(fact);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} context
+ * @param {string} name
+ * @param {glsBuiltinPrecisionTests.Func} func
+ * @return {glsBuiltinPrecisionTests.PrecisionCase}
+ */
+ glsBuiltinPrecisionTests.createFuncCase = function(context, name, func) {
+ switch (func.getOutParamIndex()) {
+ case -1:
+ return new glsBuiltinPrecisionTests.FuncCase(context, name, func);
+ case 1:
+ return new glsBuiltinPrecisionTests.InOutFuncCase(context, name, func);
+ default:
+ throw new Error(!'Impossible');
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.CaseFactory = function() {};
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CaseFactory.prototype.getName = function() {
+ return '';
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.CaseFactory.prototype.getDesc = function() {
+ return '';
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} ctx
+ */
+ glsBuiltinPrecisionTests.CaseFactory.prototype.createCase = function(ctx) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CaseFactory}
+ * @param {glsBuiltinPrecisionTests.Func} func
+ */
+ glsBuiltinPrecisionTests.SimpleFuncCaseFactory = function(func) {
+ glsBuiltinPrecisionTests.CaseFactory.call(this);
+ this.m_func = func;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.SimpleFuncCaseFactory, glsBuiltinPrecisionTests.CaseFactory);
+
+ glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.getName = function() {
+ return this.m_func.getName().toLowerCase();
+ };
+
+ glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.getDesc = function() {
+ return "Function '" + this.getName() + "'";
+ };
+
+ glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.createCase = function(ctx) {
+ return glsBuiltinPrecisionTests.createFuncCase(ctx, ctx.name, this.m_func);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CaseFactory}
+ */
+ glsBuiltinPrecisionTests.FuncCaseFactory = function() {
+ glsBuiltinPrecisionTests.CaseFactory.call(this);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.FuncCaseFactory, glsBuiltinPrecisionTests.CaseFactory);
+
+ glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getFunc = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getName = function() {
+ return this.getFunc().getName().toLowerCase();
+ };
+
+ glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getDesc = function() {
+ return "Function '" + this.getFunc().getName() + "'";
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FuncCaseFactory}
+ */
+ glsBuiltinPrecisionTests.TemplateFuncCaseFactory = function(genF) {
+ glsBuiltinPrecisionTests.FuncCaseFactory.call(this);
+ this.m_genF = genF;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.TemplateFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory);
+
+ glsBuiltinPrecisionTests.TemplateFuncCaseFactory.prototype.getFunc = function() {
+ return new this.m_genF(1);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} ctx
+ */
+ glsBuiltinPrecisionTests.TemplateFuncCaseFactory.prototype.createCase = function(ctx) {
+ var group = tcuTestCase.newTest(ctx.name, ctx.name);
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'scalar', new this.m_genF(1)));
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec2', new this.m_genF(2)));
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec3', new this.m_genF(3)));
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec4', new this.m_genF(4)));
+
+ return group;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FuncCaseFactory}
+ */
+ glsBuiltinPrecisionTests.MatrixFuncCaseFactory = function(genF) {
+ glsBuiltinPrecisionTests.FuncCaseFactory.call(this);
+ this.m_genF = genF;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.MatrixFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory);
+
+ glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.getFunc = function() {
+ return new this.m_genF(2, 2);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} ctx
+ */
+ glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.createCase = function(ctx) {
+ var group = tcuTestCase.newTest(ctx.name, ctx.name);
+ this.addCase(ctx, group, 2, 2);
+ this.addCase(ctx, group, 3, 2);
+ this.addCase(ctx, group, 4, 2);
+ this.addCase(ctx, group, 2, 3);
+ this.addCase(ctx, group, 3, 3);
+ this.addCase(ctx, group, 4, 3);
+ this.addCase(ctx, group, 2, 4);
+ this.addCase(ctx, group, 3, 4);
+ this.addCase(ctx, group, 4, 4);
+
+ return group;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} ctx
+ * @param {tcuTestCase.DeqpTest} group
+ * @param {number} rows
+ * @param {number} cols
+ */
+ glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.addCase = function(ctx, group, rows, cols) {
+ var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, name, new this.m_genF(rows, cols)));
+ };
+
+ glsBuiltinPrecisionTests.dataTypeNameOfMatrix = function(typename, rows, cols) {
+ switch (typename) {
+ case 'float':
+ if (rows === cols)
+ return 'mat' + rows;
+ else
+ return 'mat' + cols + 'x' + rows;
+ }
+ throw new Error('Invalid arguments (' + typename + ', ' + rows + ', ' + cols + ')');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.FuncCaseFactory}
+ */
+ glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory = function(genF) {
+ glsBuiltinPrecisionTests.FuncCaseFactory.call(this);
+ this.m_genF = genF;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory);
+
+ glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory.prototype.getFunc = function() {
+ return new this.m_genF(2);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} ctx
+ */
+ glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory.prototype.createCase = function(ctx) {
+ var group = tcuTestCase.newTest(ctx.name, ctx.name);
+
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'mat2', new this.m_genF(2)));
+ return group;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ * @param {glsBuiltinPrecisionTests.Func} scalarFunc
+ * @param {number=} size
+ */
+ glsBuiltinPrecisionTests.GenFunc = function(scalarFunc, size) {
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, scalarFunc.Sig);
+ this.m_func = scalarFunc;
+ this.m_size = size;
+ };
+
+ glsBuiltinPrecisionTests.GenFunc.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
+ glsBuiltinPrecisionTests.GenFunc.prototype.constructor = glsBuiltinPrecisionTests.GenFunc;
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.GenFunc.prototype.getName = function() {
+ return this.m_func.getName();
+ };
+
+ /**
+ * @return {number}
+ */
+ glsBuiltinPrecisionTests.GenFunc.prototype.getOutParamIndex = function() {
+ return this.m_func.getOutParamIndex();
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.GenFunc.prototype.getRequiredExtension = function() {
+ return this.m_func.getRequiredExtension();
+ };
+
+ /**
+ * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
+ */
+ glsBuiltinPrecisionTests.GenFunc.prototype.doPrint = function(args) {
+ return this.m_func.print(args);
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.EvalContext} ctx
+ * @param {glsBuiltinPrecisionTests.Tuple4} iargs
+ * @return {*}
+ */
+ glsBuiltinPrecisionTests.GenFunc.prototype.doApply = function(ctx, iargs) {
+ /** @type {Array<*>} */ var ret = [];
+
+ if (this.m_size > 1) {
+ for (var ndx = 0; ndx < this.m_size; ++ndx) {
+ var a = iargs.a === undefined ? undefined : iargs.a[ndx];
+ var b = iargs.b === undefined ? undefined : iargs.b[ndx];
+ var c = iargs.c === undefined ? undefined : iargs.c[ndx];
+ var d = iargs.d === undefined ? undefined : iargs.d[ndx];
+ ret[ndx] = this.m_func.applyFunction(ctx, a, b, c, d);
+ }
+ } else
+ ret[0] = this.m_func.applyFunction(ctx, iargs.a, iargs.b, iargs.c, iargs.d);
+
+ return ret;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.FuncSet} dst
+ */
+ glsBuiltinPrecisionTests.GenFunc.prototype.doGetUsedFuncs = function(dst) {
+ this.m_func.getUsedFuncs(dst);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.GenFunc}
+ * @param {glsBuiltinPrecisionTests.Func} func
+ * @param {number} size
+ */
+ glsBuiltinPrecisionTests.VectorizedFunc = function(func, size) {
+ glsBuiltinPrecisionTests.GenFunc.call(this, func, size);
+ };
+
+ glsBuiltinPrecisionTests.VectorizedFunc.prototype = Object.create(glsBuiltinPrecisionTests.GenFunc.prototype);
+ glsBuiltinPrecisionTests.VectorizedFunc.prototype.constructor = glsBuiltinPrecisionTests.VectorizedFunc;
+
+ /**
+ * @constructor
+ * @param {glsBuiltinPrecisionTests.Func} func_
+ * @param {glsBuiltinPrecisionTests.GenFunc} func2_
+ * @param {glsBuiltinPrecisionTests.GenFunc} func3_
+ * @param {glsBuiltinPrecisionTests.GenFunc} func4_
+ */
+ glsBuiltinPrecisionTests.GenFuncs = function(func_, func2_, func3_, func4_) {
+ this.func = func_;
+ this.func2 = func2_;
+ this.func3 = func3_;
+ this.func4 = func4_;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CaseFactory}
+ * @param {glsBuiltinPrecisionTests.GenFuncs} funcs
+ * @param {string} name
+ */
+ glsBuiltinPrecisionTests.GenFuncCaseFactory = function(funcs, name) {
+ glsBuiltinPrecisionTests.CaseFactory.call(this);
+ this.m_funcs = funcs;
+ this.m_name = name;
+ };
+
+ glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype = Object.create(glsBuiltinPrecisionTests.CaseFactory.prototype);
+ glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.constructor = glsBuiltinPrecisionTests.GenFuncCaseFactory;
+
+ /**
+ * @param {glsBuiltinPrecisionTests.Context} ctx
+ * @return {tcuTestCase.DeqpTest}
+ */
+ glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.createCase = function(ctx) {
+ /** @type {tcuTestCase.DeqpTest} */
+ var group = tcuTestCase.newTest(ctx.name, ctx.name);
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'scalar', this.m_funcs.func));
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec2', this.m_funcs.func2));
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec3', this.m_funcs.func3));
+ group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec4', this.m_funcs.func4));
+
+ return group;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.getName = function() {
+ return this.m_name;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.getDesc = function() {
+ return "Function '" + this.m_funcs.func.getName() + "'";
+ };
+
+ /**
+ * @constructor
+ * @param {string} name_
+ * @param {tcuFloatFormat.FloatFormat} floatFormat_
+ * @param {tcuFloatFormat.FloatFormat} highpFormat_
+ * @param {gluShaderUtil.precision} precision_
+ * @param {gluShaderProgram.shaderType} shaderType_
+ * @param {number} numRandoms_
+ */
+ glsBuiltinPrecisionTests.Context = function(name_, floatFormat_, highpFormat_, precision_, shaderType_, numRandoms_) {
+ /** @type {string} */ this.name = name_;
+ /** @type {tcuFloatFormat.FloatFormat} */ this.floatFormat = floatFormat_;
+ /** @type {tcuFloatFormat.FloatFormat} */ this.highpFormat = highpFormat_;
+ /** @type {gluShaderUtil.precision} */ this.precision = precision_;
+ /** @type {gluShaderProgram.shaderType} */ this.shaderType = shaderType_;
+ /** @type {number} */ this.numRandoms = numRandoms_;
+ };
+
+ /**
+ * @constructor
+ * @param {tcuFloatFormat.FloatFormat} highp_
+ * @param {tcuFloatFormat.FloatFormat} mediump_
+ * @param {tcuFloatFormat.FloatFormat} lowp_
+ * @param {Array<gluShaderProgram.shaderType>} shaderTypes_
+ * @param {number} numRandoms_
+ */
+ glsBuiltinPrecisionTests.PrecisionTestContext = function(highp_, mediump_, lowp_, shaderTypes_, numRandoms_) {
+ /** @type {Array<gluShaderProgram.shaderType>} */ this.shaderTypes = shaderTypes_;
+ /** @type {Array<tcuFloatFormat.FloatFormat>} */ this.formats = [];
+ this.formats[gluShaderUtil.precision.PRECISION_HIGHP] = highp_;
+ this.formats[gluShaderUtil.precision.PRECISION_MEDIUMP] = mediump_;
+ this.formats[gluShaderUtil.precision.PRECISION_LOWP] = lowp_;
+ /** @type {number} */ this.numRandoms = numRandoms_;
+ };
+
+ /**
+ * \brief Simple incremental counter.
+ *
+ * This is used to make sure that different ExpandContexts will not produce
+ * overlapping temporary names.
+ * @constructor
+ *
+ */
+ glsBuiltinPrecisionTests.Counter = function() {
+ this.m_count = 0;
+ };
+
+ glsBuiltinPrecisionTests.Counter.prototype.get = function() {
+ return this.m_count++;
+ };
+
+ /**
+ * @constructor
+ */
+ glsBuiltinPrecisionTests.ExpandContext = function(counter) {
+ this.m_counter = counter;
+ this.m_statements = [];
+ };
+
+ /**
+ * @param {string} typename
+ * @param {string} baseName
+ * @return {glsBuiltinPrecisionTests.Variable}
+ */
+ glsBuiltinPrecisionTests.ExpandContext.prototype.genSym = function(typename, baseName) {
+ return new glsBuiltinPrecisionTests.Variable(typename, baseName + this.m_counter.get());
+ };
+
+ glsBuiltinPrecisionTests.ExpandContext.prototype.addStatement = function(/*const StatementP&*/ stmt) {
+ this.m_statements.push(stmt);
+ };
+
+ glsBuiltinPrecisionTests.ExpandContext.prototype.getStatements = function() {
+ return this.m_statements;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Func}
+ * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_>
+ */
+ glsBuiltinPrecisionTests.DerivedFunc = function(Sig_) {
+ glsBuiltinPrecisionTests.Func.call(this, Sig_);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.DerivedFunc, glsBuiltinPrecisionTests.Func);
+
+ glsBuiltinPrecisionTests.DerivedFunc.prototype.doPrintDefinition = function() {
+ var os = '';
+ var paramNames = this.getParamNames();
+
+ this.initialize();
+
+ os += this.Ret + ' ' + this.getName() +
+ '(';
+ if (glsBuiltinPrecisionTests.isTypeValid(this.Arg0))
+ os += this.Arg0 + ' ' + paramNames.a;
+ if (glsBuiltinPrecisionTests.isTypeValid(this.Arg1))
+ os += ', ' + this.Arg1 + ' ' + paramNames.b;
+ if (glsBuiltinPrecisionTests.isTypeValid(this.Arg2))
+ os += ', ' + this.Arg2 + ' ' + paramNames.c;
+ if (glsBuiltinPrecisionTests.isTypeValid(this.Arg3))
+ os += ', ' + this.Arg3 + ' ' + paramNames.d;
+ os += ')\n{\n';
+
+ for (var ndx = 0; ndx < this.m_body.length; ++ndx)
+ os += this.m_body[ndx];
+ os += 'return ' + this.m_ret + ';\n';
+ os += '}\n';
+
+ return os;
+ };
+
+ glsBuiltinPrecisionTests.DerivedFunc.prototype.doApply = function(ctx, args) {
+ var funEnv = new glsBuiltinPrecisionTests.Environment();
+ this.initialize();
+
+ funEnv.bind(this.m_var0, args.a);
+ funEnv.bind(this.m_var1, args.b);
+ funEnv.bind(this.m_var2, args.c);
+ funEnv.bind(this.m_var3, args.d);
+
+ var funCtx = new glsBuiltinPrecisionTests.EvalContext(ctx.format, ctx.floatPrecision, funEnv, ctx.callDepth);
+
+ for (var ndx = 0; ndx < this.m_body.length; ++ndx)
+ this.m_body[ndx].execute(funCtx);
+
+ var ret = this.m_ret.evaluate(funCtx);
+
+ // \todo [lauri] Store references instead of values in environment
+ args.a = funEnv.lookup(this.m_var0);
+ args.b = funEnv.lookup(this.m_var1);
+ args.c = funEnv.lookup(this.m_var2);
+ args.d = funEnv.lookup(this.m_var3);
+
+ return ret;
+ };
+
+ glsBuiltinPrecisionTests.DerivedFunc.prototype.initialize = function() {
+ if (!this.m_ret) {
+ var paramNames = this.getParamNames();
+ var symCounter = new glsBuiltinPrecisionTests.Counter();
+ var ctx = new glsBuiltinPrecisionTests.ExpandContext(symCounter);
+
+ this.m_var0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, paramNames.a);
+ this.m_var1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, paramNames.b);
+ this.m_var2 = new glsBuiltinPrecisionTests.Variable(this.Arg2, paramNames.c);
+ this.m_var3 = new glsBuiltinPrecisionTests.Variable(this.Arg3, paramNames.d);
+ var args = new glsBuiltinPrecisionTests.Tuple4(this.m_var0,
+ this.m_var1, this.m_var2, this.m_var3);
+
+ this.m_ret = this.doExpand(ctx, args);
+ this.m_body = ctx.getStatements();
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.Func}
+ * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_>
+ */
+ glsBuiltinPrecisionTests.Alternatives = function(Sig_) {
+ glsBuiltinPrecisionTests.Func.call(this, Sig_);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Alternatives,glsBuiltinPrecisionTests.Func);
+
+ glsBuiltinPrecisionTests.Alternatives.prototype.getName = function() {
+ return 'alternatives';
+ };
+
+ glsBuiltinPrecisionTests.Alternatives.prototype.doPrintDefinition = function() {};
+
+ glsBuiltinPrecisionTests.Alternatives.prototype.doGetUsedFuncs = function(dst) {};
+
+ glsBuiltinPrecisionTests.Alternatives.prototype.doApply = function(ctx,args) {
+ return glsBuiltinPrecisionTests.union(this.Sig.Ret,args.a,args.b);
+ };
+
+ glsBuiltinPrecisionTests.Alternatives.prototype.doPrint = function(args) {
+ return '{' + args[0] + '|' + args[1] + '}';
+ };
+
+ glsBuiltinPrecisionTests.sizeToName = function(size) {
+ switch (size) {
+ case 4: return 'vec4';
+ case 3: return 'vec3';
+ case 2: return 'vec2';
+ }
+ return 'float';
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Dot = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature('float', name, name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Dot, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Dot.prototype.getName = function() {
+ return 'dot';
+ };
+
+ glsBuiltinPrecisionTests.Dot.prototype.doExpand = function(ctx, args) {
+ if (this.m_inputSize > 1) {
+ var val = app(new glsBuiltinPrecisionTests.Mul(),
+ new glsBuiltinPrecisionTests.VectorVariable(args.a, 0), new glsBuiltinPrecisionTests.VectorVariable(args.b, 0));
+ for (var i = 1; i < this.m_inputSize; i++) {
+ var tmp = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Mul(),
+ new glsBuiltinPrecisionTests.VectorVariable(args.a, i), new glsBuiltinPrecisionTests.VectorVariable(args.b, i));
+ val = app(new glsBuiltinPrecisionTests.Add(), val, tmp);
+ }
+ return val;
+ } else {
+ // args.a * args.b
+ var ret = app(new glsBuiltinPrecisionTests.Mul(), args.a, args.b);
+ return ret;
+ }
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Length = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature('float', name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Length, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Length.prototype.getName = function() {
+ return 'length';
+ };
+
+ glsBuiltinPrecisionTests.Length.prototype.doExpand = function(ctx, args) {
+ //sqrt(dot(args.a, args.a));
+ var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.a, args.a);
+ var v1 = app(new glsBuiltinPrecisionTests.Sqrt(), v0);
+ return v1;
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Distance = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature('float', name, name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Distance, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Distance.prototype.getName = function() {
+ return 'distance';
+ };
+
+ glsBuiltinPrecisionTests.Distance.prototype.doExpand = function(ctx, args) {
+ //length(args.a - args.b);
+ var v0 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), args.a, args.b);
+ var v1 = app(new glsBuiltinPrecisionTests.Length(this.m_inputSize), v0);
+ return v1;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Cross = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('vec3', 'vec3', 'vec3');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = 3;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Cross, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Cross.prototype.getName = function() {
+ return 'cross';
+ };
+
+ glsBuiltinPrecisionTests.Cross.prototype.doExpand = function(ctx, args) {
+ // vec3(x.a[1] * x.b[2] - x.b[1] * x.a[2],
+ // x.a[2] * x.b[0] - x.b[2] * x.a[0],
+ // x.a[0] * x.b[1] - x.b[0] * x.a[1]);
+ var a = [], b = [];
+ for (var i = 0; i < this.m_inputSize; i++) {
+ a[i] = new glsBuiltinPrecisionTests.VectorVariable(args.a, i);
+ b[i] = new glsBuiltinPrecisionTests.VectorVariable(args.b, i);
+ }
+ var v0 = app(new glsBuiltinPrecisionTests.Mul(), a[1], b[2]);
+ var v1 = app(new glsBuiltinPrecisionTests.Mul(), b[1], a[2]);
+ var v2 = app(new glsBuiltinPrecisionTests.Sub(), v0, v1);
+
+ var v3 = app(new glsBuiltinPrecisionTests.Mul(), a[2], b[0]);
+ var v4 = app(new glsBuiltinPrecisionTests.Mul(), b[2], a[0]);
+ var v5 = app(new glsBuiltinPrecisionTests.Sub(), v3, v4);
+
+ var v6 = app(new glsBuiltinPrecisionTests.Mul(), a[0], b[1]);
+ var v7 = app(new glsBuiltinPrecisionTests.Mul(), b[0], a[1]);
+ var v8 = app(new glsBuiltinPrecisionTests.Sub(), v6, v7);
+
+ var v9 = app(new glsBuiltinPrecisionTests.GenVec(this.m_inputSize, true), v2, v5, v8);
+ return v9;
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Normalize = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature(name, name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Normalize, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Normalize.prototype.getName = function() {
+ return 'normalize';
+ };
+
+ glsBuiltinPrecisionTests.Normalize.prototype.doExpand = function(ctx, args) {
+ //args.a / length<Size>(args.a);
+ var v0 = app(new glsBuiltinPrecisionTests.Length(this.m_inputSize), args.a);
+ var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Div(), args.a, v0);
+ return v1;
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.FaceForward = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature(name, name, name, name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ this.typename = name;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.FaceForward, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.FaceForward.prototype.getName = function() {
+ return 'faceforward';
+ };
+
+ glsBuiltinPrecisionTests.FaceForward.prototype.doExpand = function(ctx, args) {
+ //cond(dot(args.c, args.b) < constant(0.0f), args.a, -args.a);
+ var zero = new glsBuiltinPrecisionTests.Constant(0);
+ var v0 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Negate(), args.a);
+ var v1 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.c, args.b);
+ var v2 = app(new glsBuiltinPrecisionTests.LessThan('float'), v1, zero);
+ var v3 = app(new glsBuiltinPrecisionTests.Cond(this.typename), v2, args.a, v0);
+ return v3;
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Reflect = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature(name, name, name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Reflect, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Reflect.prototype.getName = function() {
+ return 'reflect';
+ };
+
+ glsBuiltinPrecisionTests.Reflect.prototype.doExpand = function(ctx, args) {
+ //args.a - (args.b * dot(args.b, args.a) * constant(2.0f));
+ var two = new glsBuiltinPrecisionTests.Constant(2);
+ var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.b, args.a);
+ var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), args.b, v0);
+ var v2 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), v1, two);
+ var v3 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), args.a, v2);
+ return v3;
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Refract = function(size) {
+ var name = glsBuiltinPrecisionTests.sizeToName(size);
+ var sig = new glsBuiltinPrecisionTests.Signature(name, name, name, 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ this.m_inputSize = size;
+ this.typename = name;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Refract, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Refract.prototype.getName = function() {
+ return 'refract';
+ };
+
+ glsBuiltinPrecisionTests.Refract.prototype.doExpand = function(ctx, args) {
+ var i = args.a;
+ var n = args.b;
+ var eta = args.c;
+ var zero = new glsBuiltinPrecisionTests.Constant(0);
+ var one = new glsBuiltinPrecisionTests.Constant(1);
+ // dotNI = dot(n, i)
+ var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), n, i);
+ var dotNI = glsBuiltinPrecisionTests.bindExpression('float', 'dotNI', ctx, v0);
+ // k = 1 - eta * eta * (1 - dotNI * dotNI)
+ var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), dotNI, dotNI);
+ var v2 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), one, v1);
+ var v3 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), eta, eta);
+ var v4 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), v3, v2);
+ var v5 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), one, v4);
+ var k = glsBuiltinPrecisionTests.bindExpression('float', 'k', ctx, v5);
+
+ // i * eta - n * (eta * dotNI + sqrt(k))
+ var v6 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), eta, dotNI);
+ var v7 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sqrt(), k);
+ var v8 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Add(), v6, v7);
+ var v9 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), n, v8);
+ var v10 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), i, eta);
+ var v11 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), v10, v9);
+
+ var v12 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.LessThan('float'), k, zero);
+
+ var zeroVector = app(new glsBuiltinPrecisionTests.GenVec(this.m_inputSize), zero);
+ var v13 = app(new glsBuiltinPrecisionTests.Cond(this.typename), v12, zeroVector, v11);
+ return v13;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Radians = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Radians, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Radians.prototype.getName = function() {
+ return 'radians';
+ };
+
+ glsBuiltinPrecisionTests.Radians.prototype.doExpand = function(ctx, args) {
+ var val = app(new glsBuiltinPrecisionTests.Div(),
+ new glsBuiltinPrecisionTests.Constant(Math.PI),
+ new glsBuiltinPrecisionTests.Constant(180));
+ return new glsBuiltinPrecisionTests.Apply('float',
+ new glsBuiltinPrecisionTests.Mul(),
+ val,
+ args.a);
+
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Degrees = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Degrees, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Degrees.prototype.getName = function() {
+ return 'degrees';
+ };
+
+ glsBuiltinPrecisionTests.Degrees.prototype.doExpand = function(ctx, args) {
+ var val = app(new glsBuiltinPrecisionTests.Div(),
+ new glsBuiltinPrecisionTests.Constant(180),
+ new glsBuiltinPrecisionTests.Constant(Math.PI));
+ return new glsBuiltinPrecisionTests.Apply('float',
+ new glsBuiltinPrecisionTests.Mul(),
+ val,
+ args.a);
+
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Sinh = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Sinh, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Sinh.prototype.getName = function() {
+ return 'sinh';
+ };
+
+ glsBuiltinPrecisionTests.Sinh.prototype.doExpand = function(ctx, args) {
+ // (exp(x) - exp(-x)) / constant(2.0f)
+ var x = args.a;
+ var v0 = app(new glsBuiltinPrecisionTests.Exp(), x);
+ var v1 = app(new glsBuiltinPrecisionTests.Negate(), x);
+ var v2 = app(new glsBuiltinPrecisionTests.Exp(), v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Sub(), v0, v2);
+ var v4 = new glsBuiltinPrecisionTests.Constant(2);
+ var v5 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v3, v4);
+ return v5;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Cosh = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Cosh, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Cosh.prototype.getName = function() {
+ return 'cosh';
+ };
+
+ glsBuiltinPrecisionTests.Cosh.prototype.doExpand = function(ctx, args) {
+ // (exp(x) + exp(-x)) / constant(2.0f)
+ var x = args.a;
+ var v0 = app(new glsBuiltinPrecisionTests.Exp(), x);
+ var v1 = app(new glsBuiltinPrecisionTests.Negate(), x);
+ var v2 = app(new glsBuiltinPrecisionTests.Exp(), v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Add(), v0, v2);
+ var v4 = new glsBuiltinPrecisionTests.Constant(2);
+ var v5 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v3, v4);
+ return v5;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Tanh = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Tanh, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Tanh.prototype.getName = function() {
+ return 'tanh';
+ };
+
+ glsBuiltinPrecisionTests.Tanh.prototype.doExpand = function(ctx, args) {
+ // sinh(x) / cosh(x)
+ var x = args.a;
+ var v0 = app(new glsBuiltinPrecisionTests.Sinh(), x);
+ var v1 = app(new glsBuiltinPrecisionTests.Cosh(), x);
+ var v2 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v0, v1);
+ return v2;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.ASinh = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ASinh, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.ASinh.prototype.getName = function() {
+ return 'asinh';
+ };
+
+ glsBuiltinPrecisionTests.ASinh.prototype.doExpand = function(ctx, args) {
+ // log(x + sqrt(x * x + constant(1.0f)))
+ var x = args.a;
+ var v0 = app(new glsBuiltinPrecisionTests.Mul(), x, x);
+ var v1 = new glsBuiltinPrecisionTests.Constant(1);
+ var v2 = app(new glsBuiltinPrecisionTests.Add(), v0, v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Sqrt(), v2);
+ var v4 = app(new glsBuiltinPrecisionTests.Add(), x, v3);
+ var v5 = app(new glsBuiltinPrecisionTests.Log(), v4);
+ return v5;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.ACosh = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ACosh, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.ACosh.prototype.getName = function() {
+ return 'acosh';
+ };
+
+ glsBuiltinPrecisionTests.ACosh.prototype.doExpand = function(ctx, args) {
+ // log(x + sqrt((x + constant(1.0f)) * (x - constant(1.0f))))
+ var x = args.a;
+ var one = new glsBuiltinPrecisionTests.Constant(1);
+ var v0 = app(new glsBuiltinPrecisionTests.Add(), x, one);
+ var v1 = app(new glsBuiltinPrecisionTests.Sub(), x, one);
+ var v2 = app(new glsBuiltinPrecisionTests.Mul(), v0, v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Sqrt(), v2);
+ var v4 = app(new glsBuiltinPrecisionTests.Add(), x, v3);
+ var v5 = app(new glsBuiltinPrecisionTests.Log(), v4);
+ return v5;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.ATanh = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ATanh, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.ATanh.prototype.getName = function() {
+ return 'atanh';
+ };
+
+ glsBuiltinPrecisionTests.ATanh.prototype.doExpand = function(ctx, args) {
+ // constant(0.5f) * log((constant(1.0f) + x) / (constant(1.0f) - x))
+ var x = args.a;
+ var one = new glsBuiltinPrecisionTests.Constant(1);
+ var half = new glsBuiltinPrecisionTests.Constant(0.5);
+ var v0 = app(new glsBuiltinPrecisionTests.Add(), one, x);
+ var v1 = app(new glsBuiltinPrecisionTests.Sub(), one, x);
+ var v2 = app(new glsBuiltinPrecisionTests.Div(), v0, v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Log(), v2);
+ var v4 = app(new glsBuiltinPrecisionTests.Mul(), half, v3);
+ return v4;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Sqrt = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Sqrt, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Sqrt.prototype.getName = function() {
+ return 'sqrt';
+ };
+
+ glsBuiltinPrecisionTests.Sqrt.prototype.doExpand = function(ctx, args) {
+ // constant(1.0f) / app<InverseSqrt>(x)
+ var x = args.a;
+ var one = new glsBuiltinPrecisionTests.Constant(1);
+ var v0 = app(new glsBuiltinPrecisionTests.InverseSqrt(), x);
+ var v1 = app(new glsBuiltinPrecisionTests.Div(), one, v0);
+ return v1;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Fract = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Fract, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Fract.prototype.getName = function() {
+ return 'fract';
+ };
+
+ glsBuiltinPrecisionTests.Fract.prototype.doExpand = function(ctx, args) {
+ // x - floor(x)
+ var x = args.a;
+ var v0 = app(new glsBuiltinPrecisionTests.Floor(), x);
+ var v1 = app(new glsBuiltinPrecisionTests.Sub(), x, v0);
+ return v1;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Mod = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Mod, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Mod.prototype.getName = function() {
+ return 'mod';
+ };
+
+ glsBuiltinPrecisionTests.Mod.prototype.doExpand = function(ctx, args) {
+ // x - y * floor(x/y)
+ var x = args.a;
+ var y = args.b;
+ var v0 = app(new glsBuiltinPrecisionTests.Div(), x, y);
+ var v1 = app(new glsBuiltinPrecisionTests.Floor(), v0);
+ var v2 = app(new glsBuiltinPrecisionTests.Mul(), y, v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Sub(), x, v2);
+ return v3;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
+ */
+ glsBuiltinPrecisionTests.Modf = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
+ glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Modf, glsBuiltinPrecisionTests.PrimitiveFunc);
+
+ glsBuiltinPrecisionTests.Modf.prototype.getName = function() {
+ return 'modf';
+ };
+
+ glsBuiltinPrecisionTests.Modf.prototype.doApply = function(ctx, iargs, variablenames) {
+ var intPart;
+ var func1 = function(x) {
+ intPart = Math.trunc(x);
+ return x - intPart;
+ };
+ var func2 = function(x) {
+ return Math.trunc(x);
+ };
+
+ var fracIV = tcuInterval.applyMonotone1p(func1, iargs.a);
+ var wholeIV = tcuInterval.applyMonotone1p(func2, iargs.a);
+
+ if (!iargs.a.isFinite()) {
+ // Behavior on modf(Inf) not well-defined, allow anything as a fractional part
+ // See Khronos bug 13907
+ fracIV.operatorOrAssignBinary(tcuInterval.NAN);
+ }
+
+ ctx.env.m_map[variablenames[1]] = wholeIV;
+ return fracIV;
+ };
+
+ glsBuiltinPrecisionTests.Modf.prototype.getOutParamIndex = function() {
+ return 1;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Mix = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Mix, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Mix.prototype.getName = function() {
+ return 'mix';
+ };
+
+ glsBuiltinPrecisionTests.Mix.prototype.operation1 = function(ctx, args) {
+ // (x * (constant(1.0f) - a)) + y * a
+ var x = args.a;
+ var y = args.b;
+ var a = args.c;
+ var one = new glsBuiltinPrecisionTests.Constant(1);
+ var v0 = app(new glsBuiltinPrecisionTests.Sub(), one, a);
+ var v1 = app(new glsBuiltinPrecisionTests.Mul(), x, v0);
+ var v2 = app(new glsBuiltinPrecisionTests.Mul(), y, a);
+ var v3 = app(new glsBuiltinPrecisionTests.Add(), v1, v2);
+ return v3;
+ };
+
+ glsBuiltinPrecisionTests.Mix.prototype.operation2 = function(ctx, args) {
+ // x + (y - x) * a
+ var x = args.a;
+ var y = args.b;
+ var a = args.c;
+ var v0 = app(new glsBuiltinPrecisionTests.Sub(), y, x);
+ var v1 = app(new glsBuiltinPrecisionTests.Mul(), a, v0);
+ var v2 = app(new glsBuiltinPrecisionTests.Add(), x, v1);
+ return v2;
+ };
+
+ glsBuiltinPrecisionTests.Mix.prototype.doExpand = function(ctx, args){
+ return app(new glsBuiltinPrecisionTests.Alternatives(this.Sig), this.operation1(ctx, args), this.operation2(ctx, args), new glsBuiltinPrecisionTests.Void(), new glsBuiltinPrecisionTests.Void());
+ }
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.SmoothStep = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.SmoothStep, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.SmoothStep.prototype.getName = function() {
+ return 'smoothstep';
+ };
+
+ glsBuiltinPrecisionTests.SmoothStep.prototype.doExpand = function(ctx, args) {
+ var edge0 = args.a;
+ var edge1 = args.b;
+ var x = args.c;
+ var zero = new glsBuiltinPrecisionTests.Constant(0);
+ var one = new glsBuiltinPrecisionTests.Constant(1);
+ //clamp((x - edge0) / (edge1 - edge0), constant(0.0f), constant(1.0f));
+ var v0 = app(new glsBuiltinPrecisionTests.Sub(), x, edge0);
+ var v1 = app(new glsBuiltinPrecisionTests.Sub(), edge1, edge0);
+ var v2 = app(new glsBuiltinPrecisionTests.Div(), v0, v1);
+ var v3 = app(new glsBuiltinPrecisionTests.Clamp(), v2, zero, one);
+ var t = glsBuiltinPrecisionTests.bindExpression('float', 't', ctx, v3);
+ //(t * t * (constant(3.0f) - constant(2.0f) * t))
+ var two = new glsBuiltinPrecisionTests.Constant(2);
+ var three = new glsBuiltinPrecisionTests.Constant(3);
+ var v4 = app(new glsBuiltinPrecisionTests.Mul(), v3, v3);
+ var v5 = app(new glsBuiltinPrecisionTests.Mul(), two, v3);
+ var v6 = app(new glsBuiltinPrecisionTests.Sub(), three, v5);
+ var v7 = app(new glsBuiltinPrecisionTests.Mul(), v4, v6);
+ return v7;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Pow = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Pow, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Pow.prototype.getName = function() {
+ return 'pow';
+ };
+
+ glsBuiltinPrecisionTests.Pow.prototype.doExpand = function(ctx, args) {
+ // exp2(y * log2(x))
+ var x = args.a;
+ var y = args.b;
+ var v0 = app(new glsBuiltinPrecisionTests.Log2(), x);
+ var v1 = app(new glsBuiltinPrecisionTests.Mul(), y, v0);
+ var v2 = app(new glsBuiltinPrecisionTests.Exp2(), v1);
+ return v2;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
+ */
+ glsBuiltinPrecisionTests.ExpFunc = function(name, func) {
+ glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ExpFunc, glsBuiltinPrecisionTests.CFloatFunc1);
+
+ glsBuiltinPrecisionTests.ExpFunc.prototype.getCodomain = function() {
+ return tcuInterval.withNumbers(0, Infinity);
+ };
+
+ glsBuiltinPrecisionTests.ExpFunc.prototype.precision = function(ctx, ret, x) {
+ switch (ctx.floatPrecision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP:
+ return ctx.format.ulp(ret, 3.0 + 2.0 * Math.abs(x));
+ case gluShaderUtil.precision.PRECISION_MEDIUMP:
+ return ctx.format.ulp(ret, 2.0 + 2.0 * Math.abs(x));
+ case gluShaderUtil.precision.PRECISION_LOWP:
+ return ctx.format.ulp(ret, 2.0);
+ default:
+ throw new Error(!'Impossible');
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ExpFunc}
+ */
+ glsBuiltinPrecisionTests.Exp = function() {
+ glsBuiltinPrecisionTests.ExpFunc.call(this, 'exp', Math.exp);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Exp, glsBuiltinPrecisionTests.ExpFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ExpFunc}
+ */
+ glsBuiltinPrecisionTests.Exp2 = function() {
+ /**
+ * @param {number} x
+ * @return {number}
+ */
+ var exp2 = function(x) {
+ return Math.exp(x * Math.LN2);
+ };
+ glsBuiltinPrecisionTests.ExpFunc.call(this, 'exp2', exp2);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Exp2, glsBuiltinPrecisionTests.ExpFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
+ */
+ glsBuiltinPrecisionTests.LogFunc = function(name, func) {
+ glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.LogFunc, glsBuiltinPrecisionTests.CFloatFunc1);
+
+ glsBuiltinPrecisionTests.LogFunc.prototype.precision = function(ctx, ret, x) {
+ if (x <= 0)
+ return NaN;
+ switch (ctx.floatPrecision) {
+ case gluShaderUtil.precision.PRECISION_HIGHP:
+ return (0.5 <= x && x <= 2.0) ? deMath.deLdExp(1.0, -21) : ctx.format.ulp(ret, 3.0);
+ case gluShaderUtil.precision.PRECISION_MEDIUMP:
+ return (0.5 <= x && x <= 2.0) ? deMath.deLdExp(1.0, -7) : ctx.format.ulp(ret, 2.0);
+ case gluShaderUtil.precision.PRECISION_LOWP:
+ return ctx.format.ulp(ret, 2.0);
+ default:
+ throw new Error(!'Impossible');
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.LogFunc}
+ */
+ glsBuiltinPrecisionTests.Log = function() {
+ glsBuiltinPrecisionTests.LogFunc.call(this, 'log', Math.log);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Log, glsBuiltinPrecisionTests.LogFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.LogFunc}
+ */
+ glsBuiltinPrecisionTests.Log2 = function() {
+ glsBuiltinPrecisionTests.LogFunc.call(this, 'log2', Math.log2);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Log2, glsBuiltinPrecisionTests.LogFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
+ */
+ glsBuiltinPrecisionTests.PreciseFunc1 = function(name, func) {
+ glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.PreciseFunc1, glsBuiltinPrecisionTests.CFloatFunc1);
+
+ glsBuiltinPrecisionTests.PreciseFunc1.prototype.precision = function(ctx, ret, x) {
+ return 0;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
+ */
+ glsBuiltinPrecisionTests.Abs = function() {
+ glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'abs', Math.abs);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Abs, glsBuiltinPrecisionTests.PreciseFunc1);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
+ */
+ glsBuiltinPrecisionTests.Sign = function() {
+ glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'sign', Math.sign);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Sign, glsBuiltinPrecisionTests.PreciseFunc1);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
+ */
+ glsBuiltinPrecisionTests.Floor = function() {
+ glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'floor', Math.floor);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Floor, glsBuiltinPrecisionTests.PreciseFunc1);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
+ */
+ glsBuiltinPrecisionTests.RoundEven = function() {
+ glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'roundEven', deMath.rint);
+ };
+ setParentClass(glsBuiltinPrecisionTests.RoundEven, glsBuiltinPrecisionTests.PreciseFunc1);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
+ */
+ glsBuiltinPrecisionTests.Ceil = function() {
+ glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'ceil', Math.ceil);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Ceil, glsBuiltinPrecisionTests.PreciseFunc1);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
+ */
+ glsBuiltinPrecisionTests.Trunc = function() {
+ glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'trunc', Math.trunc);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Trunc, glsBuiltinPrecisionTests.PreciseFunc1);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc2}
+ */
+ glsBuiltinPrecisionTests.PreciseFunc2 = function(name, func) {
+ glsBuiltinPrecisionTests.CFloatFunc2.call(this, name, func);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.PreciseFunc2, glsBuiltinPrecisionTests.CFloatFunc2);
+
+ glsBuiltinPrecisionTests.PreciseFunc2.prototype.precision = function(ctx, ret, x, y) {
+ return 0;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc2}
+ */
+ glsBuiltinPrecisionTests.Min = function() {
+ glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'min', Math.min);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Min, glsBuiltinPrecisionTests.PreciseFunc2);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc2}
+ */
+ glsBuiltinPrecisionTests.Max = function() {
+ glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'max', Math.max);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Max, glsBuiltinPrecisionTests.PreciseFunc2);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.PreciseFunc2}
+ */
+ glsBuiltinPrecisionTests.Step = function() {
+ /**
+ * @param {number} edge
+ * @param {number} x
+ * return number
+ */
+ var step = function(edge, x) {
+ return x < edge ? 0.0 : 1.0;
+ };
+ glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'step', step);
+ };
+ setParentClass(glsBuiltinPrecisionTests.Step, glsBuiltinPrecisionTests.PreciseFunc2);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
+ */
+ glsBuiltinPrecisionTests.TrigFunc = function(name, func, loEx, hiEx) {
+ glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
+ this.m_loExtremum = loEx;
+ this.m_hiExtremum = hiEx;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.TrigFunc, glsBuiltinPrecisionTests.CFloatFunc1);
+
+ glsBuiltinPrecisionTests.TrigFunc.prototype.innerExtrema = function(ctx, angle) {
+ var lo = angle.lo();
+ var hi = angle.hi();
+ var loSlope = this.doGetSlope(lo);
+ var hiSlope = this.doGetSlope(hi);
+
+ // Detect the high and low values the function can take between the
+ // interval endpoints.
+ if (angle.length() >= 2.0 * Math.PI) {
+ // The interval is longer than a full cycle, so it must get all possible values.
+ return this.m_hiExtremum.operatorOrBinary(this.m_loExtremum);
+ } else if (loSlope == 1 && hiSlope == -1) {
+ // The slope can change from positive to negative only at the maximum value.
+ return this.m_hiExtremum;
+ } else if (loSlope == -1 && hiSlope == 1) {
+ // The slope can change from negative to positive only at the maximum value.
+ return this.m_loExtremum;
+ } else if (loSlope == hiSlope &&
+ deMath.deSign(this.applyExact(hi) - this.applyExact(lo)) * loSlope == -1) {
+ // The slope has changed twice between the endpoints, so both extrema are included.
+ return this.m_hiExtremum.operatorOrBinary(this.m_loExtremum);
+ }
+
+ return new tcuInterval.Interval();
+ };
+
+ glsBuiltinPrecisionTests.TrigFunc.prototype.getCodomain = function() {
+ // Ensure that result is always within [-1, 1], or NaN (for +-inf)
+ var v = tcuInterval.withIntervals(new tcuInterval.Interval(-1), new tcuInterval.Interval(1));
+ return v.operatorOrBinary(tcuInterval.NAN);
+ };
+
+ glsBuiltinPrecisionTests.TrigFunc.prototype.precision = function(ctx, ret, arg) {
+ if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) {
+ // Use precision from OpenCL fast relaxed math
+ if (-Math.PI <= arg && arg <= Math.PI) {
+ return deMath.deLdExp(1.0, -11);
+ } else {
+ // "larger otherwise", let's pick |x| * 2^-12 , which is slightly over
+ // 2^-11 at x == pi.
+ return deMath.deLdExp(Math.abs(arg), -12);
+ }
+ } else if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_MEDIUMP) {
+ if (-Math.PI <= arg && arg <= Math.PI) {
+ // from OpenCL half-float extension specification
+ return ctx.format.ulp(ret, 2.0);
+ } else {
+ // |x| * 2^-10 , slightly larger than 2 ULP at x == pi
+ return deMath.deLdExp(Math.abs(arg), -10);
+ }
+ } else {
+ // from OpenCL half-float extension specification
+ return ctx.format.ulp(ret, 2.0);
+ }
+ };
+
+ /**
+ * @param {number} angle
+ * @return number
+ */
+ glsBuiltinPrecisionTests.TrigFunc.prototype.doGetSlope = function(angle) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.TrigFunc}
+ */
+ glsBuiltinPrecisionTests.Sin = function() {
+ glsBuiltinPrecisionTests.TrigFunc.call(this, 'sin', Math.sin, new tcuInterval.Interval(-1), new tcuInterval.Interval(1));
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Sin, glsBuiltinPrecisionTests.TrigFunc);
+
+ glsBuiltinPrecisionTests.Sin.prototype.doGetSlope = function(angle) {
+ return deMath.deSign(Math.cos(angle));
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.TrigFunc}
+ */
+ glsBuiltinPrecisionTests.Cos = function() {
+ glsBuiltinPrecisionTests.TrigFunc.call(this, 'cos', Math.cos, new tcuInterval.Interval(-1), new tcuInterval.Interval(1));
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Cos, glsBuiltinPrecisionTests.TrigFunc);
+
+ glsBuiltinPrecisionTests.Cos.prototype.doGetSlope = function(angle) {
+ return -deMath.deSign(Math.sin(angle));
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Tan = function() {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Tan, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Tan.prototype.getName = function() {
+ return 'tan';
+ };
+
+ glsBuiltinPrecisionTests.Tan.prototype.doExpand = function(ctx, args) {
+ // sin(x) * (constant(1.0f) / cos(x)
+ var x = args.a;
+ var sin = app(new glsBuiltinPrecisionTests.Sin(), x);
+ var cos = app(new glsBuiltinPrecisionTests.Cos(), x);
+ var expr = app(new glsBuiltinPrecisionTests.Div(),
+ new glsBuiltinPrecisionTests.Constant(1),
+ cos);
+
+ expr = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Mul(),
+ sin,
+ expr);
+ return expr;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
+ */
+ glsBuiltinPrecisionTests.ASin = function() {
+ glsBuiltinPrecisionTests.CFloatFunc1.call(this, 'asin', Math.asin);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ASin, glsBuiltinPrecisionTests.CFloatFunc1);
+
+ glsBuiltinPrecisionTests.ASin.prototype.precision = function(ctx, ret, x) {
+ if (!deMath.deInBounds32(x, -1.0, 1.0))
+ return NaN;
+
+ if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) {
+ // Absolute error of 2^-11
+ return deMath.deLdExp(1.0, -11);
+ } else {
+ // Absolute error of 2^-8
+ return deMath.deLdExp(1.0, -8);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
+ */
+ glsBuiltinPrecisionTests.ArcTrigFunc = function(name, func, precisionULPs, domain, coddomain) {
+ glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
+ this.m_precision = precisionULPs;
+ this.m_domain = domain;
+ this.m_codomain = coddomain;
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ArcTrigFunc, glsBuiltinPrecisionTests.CFloatFunc1);
+
+ glsBuiltinPrecisionTests.ArcTrigFunc.prototype.precision = function(ctx, ret, x) {
+ if (!this.m_domain.contains(new tcuInterval.Interval(x)))
+ return NaN;
+
+ if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) {
+ // Use OpenCL's precision
+ return ctx.format.ulp(ret, this.m_precision);
+ } else {
+ // Use OpenCL half-float spec
+ return ctx.format.ulp(ret, 2.0);
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ArcTrigFunc}
+ */
+ glsBuiltinPrecisionTests.ACos = function() {
+ glsBuiltinPrecisionTests.ArcTrigFunc.call(this, 'acos', Math.acos, 4096.0,
+ tcuInterval.withNumbers(-1, 1),
+ tcuInterval.withNumbers(0, Math.PI));
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ACos, glsBuiltinPrecisionTests.ArcTrigFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.ArcTrigFunc}
+ */
+ glsBuiltinPrecisionTests.ATan = function() {
+ glsBuiltinPrecisionTests.ArcTrigFunc.call(this, 'atan', Math.atan, 4096.0,
+ tcuInterval.unbounded(),
+ tcuInterval.withNumbers(-Math.PI * 0.5, Math.PI * 0.5));
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ATan, glsBuiltinPrecisionTests.ArcTrigFunc);
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.CFloatFunc2}
+ */
+ glsBuiltinPrecisionTests.ATan2 = function() {
+ glsBuiltinPrecisionTests.CFloatFunc2.call(this, 'atan', Math.atan2);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.ATan2, glsBuiltinPrecisionTests.CFloatFunc2);
+
+ glsBuiltinPrecisionTests.ATan2.prototype.innerExtrema = function(ctx, xi, yi) {
+ var ret = new tcuInterval.Interval();
+
+ if (yi.contains(tcuInterval.ZERO)) {
+ if (xi.contains(tcuInterval.ZERO))
+ ret.operatorOrAssignBinary(tcuInterval.NAN);
+ if (xi.intersects(tcuInterval.withNumbers(-Infinity, 0)))
+ ret.operatorOrAssignBinary(tcuInterval.withNumbers(-Math.PI, Math.PI));
+ }
+
+ if (ctx.format.hasInf() != tcuFloatFormat.YesNoMaybe.YES && (!yi.isFinite() || !xi.isFinite())) {
+ // Infinities may not be supported, allow anything, including NaN
+ ret.operatorOrAssignBinary(tcuInterval.NAN);
+ }
+
+ return ret;
+ };
+
+ glsBuiltinPrecisionTests.ATan2.prototype.precision = function(ctx, ret, x, y) {
+ if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP)
+ return ctx.format.ulp(ret, 4096.0);
+ else
+ return ctx.format.ulp(ret, 2.0);
+ };
+
+ /**
+ * @constructor
+ * @param {number} size
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.DeterminantBase = function(size) {
+ var sig = new glsBuiltinPrecisionTests.Signature('float', 'mat' + size);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.DeterminantBase, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.DeterminantBase.prototype.getName = function() {
+ return 'determinant';
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DeterminantBase}
+ */
+ glsBuiltinPrecisionTests.Determinant = function() {
+ // TODO: Support sizes 3 and 4
+ this.size = 2;
+ glsBuiltinPrecisionTests.DeterminantBase.call(this, this.size);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Determinant, glsBuiltinPrecisionTests.DeterminantBase);
+
+ glsBuiltinPrecisionTests.Determinant.prototype.doExpand = function(ctx, args) {
+ // mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1]
+ var elem0_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 0);
+ var elem0_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 1);
+ var elem1_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 0);
+ var elem1_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 1);
+
+ var val0 = app(new glsBuiltinPrecisionTests.Mul(), elem0_0, elem1_1);
+ var val1 = app(new glsBuiltinPrecisionTests.Mul(), elem0_1, elem1_0);
+ return new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Sub(), val0, val1);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsBuiltinPrecisionTests.DerivedFunc}
+ */
+ glsBuiltinPrecisionTests.Inverse = function() {
+ this.size = 2;
+ var name = 'mat' + this.size;
+ var sig = new glsBuiltinPrecisionTests.Signature(name, name);
+ glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
+ };
+
+ setParentClass(glsBuiltinPrecisionTests.Inverse, glsBuiltinPrecisionTests.DerivedFunc);
+
+ glsBuiltinPrecisionTests.Inverse.prototype.getName = function() {
+ return 'inverse';
+ };
+
+ glsBuiltinPrecisionTests.Inverse.prototype.doExpand = function(ctx, args) {
+ var mat = args.a;
+ var v0 = app(new glsBuiltinPrecisionTests.Determinant(), mat);
+ var det = glsBuiltinPrecisionTests.bindExpression('float', 'det', ctx, v0);
+
+ var elem0_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 0);
+ var elem0_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 1);
+ var elem1_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 0);
+ var elem1_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 1);
+
+ var result0_0 = app(new glsBuiltinPrecisionTests.Div(), elem1_1, det);
+ var result0_1 = app(new glsBuiltinPrecisionTests.Div(), elem0_1, det);
+ result0_1 = app(new glsBuiltinPrecisionTests.Negate(), result0_1);
+ var result1_0 = app(new glsBuiltinPrecisionTests.Div(), elem1_0, det);
+ result1_0 = app(new glsBuiltinPrecisionTests.Negate(), result1_0);
+ var result1_1 = app(new glsBuiltinPrecisionTests.Div(), elem0_0, det);
+
+ var col0 = app(new glsBuiltinPrecisionTests.GenVec(this.size, true), result0_0, result1_0);
+ var col1 = app(new glsBuiltinPrecisionTests.GenVec(this.size, true), result0_1, result1_1);
+ var ret = app(new glsBuiltinPrecisionTests.GenMat(this.size, this.size), col0, col1);
+
+ return ret;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.PrecisionTestContext} ctx
+ * @param {glsBuiltinPrecisionTests.CaseFactory} factory
+ * @return {tcuTestCase.DeqpTest}
+ */
+ glsBuiltinPrecisionTests.createFuncGroup = function(ctx, factory) {
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(factory.getName(), factory.getDesc());
+
+ for (var precNdx in gluShaderUtil.precision) {
+ /** @type {gluShaderUtil.precision} */ var precision = gluShaderUtil.precision[precNdx];
+ /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision);
+ /** @type {tcuFloatFormat.FloatFormat} */ var fmt = ctx.formats[precision];
+ /** @type {tcuFloatFormat.FloatFormat} */ var highpFmt = ctx.formats[gluShaderUtil.precision.PRECISION_HIGHP];
+
+ for (var shaderNdx in ctx.shaderTypes) {
+ /** @type {gluShaderProgram.shaderType} */ var shaderType = ctx.shaderTypes[shaderNdx];
+ /** @type {string} */ var shaderName = gluShaderProgram.getShaderTypeName(shaderType);
+ /** @type {string} */ var name = precName + '_' + shaderName;
+ /** @type {glsBuiltinPrecisionTests.Context} */ var caseCtx = new glsBuiltinPrecisionTests.Context(name, fmt, highpFmt,
+ precision, shaderType, ctx.numRandoms);
+
+ group.addChild(factory.createCase(caseCtx));
+ }
+ }
+
+ return group;
+ };
+
+ /**
+ * @param {glsBuiltinPrecisionTests.CaseFactories} cases
+ * @param {Array<gluShaderProgram.shaderType>} shaderTypes
+ * @param {tcuTestCase.DeqpTest} dstGroup
+ */
+ glsBuiltinPrecisionTests.addBuiltinPrecisionTests = function(cases, shaderTypes, dstGroup) {
+ /** @type {tcuFloatFormat.FloatFormat} */ var highp = new tcuFloatFormat.FloatFormat(-126, 127, 23, true,
+ tcuFloatFormat.YesNoMaybe.MAYBE, // subnormals
+ tcuFloatFormat.YesNoMaybe.YES, // infinities
+ tcuFloatFormat.YesNoMaybe.MAYBE); // NaN
+ // \todo [2014-04-01 lauri] Check these once Khronos bug 11840 is resolved.
+ /** @type {tcuFloatFormat.FloatFormat} */ var mediump = new tcuFloatFormat.FloatFormat(-13, 13, 9, false);
+ // A fixed-point format is just a floating point format with a fixed
+ // exponent and support for subnormals.
+ /** @type {tcuFloatFormat.FloatFormat} */ var lowp = new tcuFloatFormat.FloatFormat(0, 0, 7, false, tcuFloatFormat.YesNoMaybe.YES);
+ /** @type {glsBuiltinPrecisionTests.PrecisionTestContext} */ var ctx = new glsBuiltinPrecisionTests.PrecisionTestContext(highp, mediump, lowp,
+ shaderTypes, 16384);
+
+ for (var ndx = 0; ndx < cases.getFactories().length; ++ndx)
+ dstGroup.addChild(glsBuiltinPrecisionTests.createFuncGroup(ctx, cases.getFactories()[ndx]));
+ };
+
+ /**
+ * @param {function(new:glsBuiltinPrecisionTests.Func)} F
+ * @param {glsBuiltinPrecisionTests.CaseFactories} funcs
+ * @param {string=} name
+ */
+ glsBuiltinPrecisionTests.addScalarFactory = function(F, funcs, name) {
+ if (name === undefined)
+ name = (new F()).getName();
+
+ funcs.addFactory(new glsBuiltinPrecisionTests.GenFuncCaseFactory(glsBuiltinPrecisionTests.makeVectorizedFuncs(F), name));
+ };
+
+ /**
+ * @param {function(new:glsBuiltinPrecisionTests.Func)} F
+ */
+ glsBuiltinPrecisionTests.createSimpleFuncCaseFactory = function(F) {
+ return new glsBuiltinPrecisionTests.SimpleFuncCaseFactory(new F());
+ };
+
+ /**
+ * @param {number} caseId test case Id
+ * @return {glsBuiltinPrecisionTests.CaseFactories}
+ */
+ glsBuiltinPrecisionTests.createES3BuiltinCases = function(caseId) {
+ /** @type {glsBuiltinPrecisionTests.CaseFactories} */ var funcs = new glsBuiltinPrecisionTests.BuiltinFuncs();
+
+ switch (caseId) {
+ case 0: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Add, funcs); break;
+ case 1: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sub, funcs); break;
+ case 2: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mul, funcs); break;
+ case 3: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Div, funcs); break;
+ case 4: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Radians, funcs); break;
+ case 5: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Degrees, funcs); break;
+ case 6: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sin, funcs); break;
+ case 7: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Cos, funcs); break;
+ case 8: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Tan, funcs); break;
+ case 9: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ASin, funcs); break;
+ case 10: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ACos, funcs); break;
+ case 11: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATan, funcs); break;
+ case 12: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATan2, funcs, 'atan2'); break;
+ case 13: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sinh, funcs); break;
+ case 14: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Cosh, funcs); break;
+ case 15: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Tanh, funcs); break;
+ case 16: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ASinh, funcs); break;
+ case 17: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ACosh, funcs); break;
+ case 18: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATanh, funcs); break;
+ case 19: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Pow, funcs); break;
+ case 20: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Exp, funcs); break;
+ case 21: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Exp2, funcs); break;
+ case 22: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Log, funcs); break;
+ case 23: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Log2, funcs); break;
+ case 24: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sqrt, funcs); break;
+ case 25: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.InverseSqrt, funcs); break;
+ case 26: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Abs, funcs); break;
+ case 27: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sign, funcs); break;
+ case 28: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Floor, funcs); break;
+ case 29: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Trunc, funcs); break;
+ case 30: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Round, funcs); break;
+ case 31: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.RoundEven, funcs); break;
+ case 32: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Ceil, funcs); break;
+ case 33: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Fract, funcs); break;
+ case 34: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mod, funcs); break;
+ case 35: funcs.addFactory(glsBuiltinPrecisionTests.createSimpleFuncCaseFactory(glsBuiltinPrecisionTests.Modf)); break;
+ case 36: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Min, funcs); break;
+ case 37: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Max, funcs); break;
+ case 38: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mix, funcs); break;
+ case 39: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Step, funcs); break;
+ case 40: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.SmoothStep, funcs); break;
+ case 41: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Clamp, funcs); break;
+ case 42: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Length)); break;
+ case 43: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Distance)); break;
+ case 44: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Dot)); break;
+ case 45: funcs.addFactory(glsBuiltinPrecisionTests.createSimpleFuncCaseFactory(glsBuiltinPrecisionTests.Cross)); break;
+ case 46: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Normalize)); break;
+ case 47: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.FaceForward)); break;
+ case 48: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Reflect)); break;
+ case 49: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Refract)); break;
+ case 50: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.MatrixCompMult)); break;
+ case 51: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.OuterProduct)); break;
+ case 52: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.Transpose)); break;
+ case 53: funcs.addFactory(new glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory(glsBuiltinPrecisionTests.Determinant)); break;
+ case 54: funcs.addFactory(new glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory(glsBuiltinPrecisionTests.Inverse)); break;
+ default: break;
+ }
+
+ return funcs;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTestsUnitTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTestsUnitTests.js
new file mode 100644
index 0000000000..e8df9d28e3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTestsUnitTests.js
@@ -0,0 +1,2819 @@
+'use strict';
+goog.provide('modules.shared.glsBuiltinPrecisionTestsUnitTests');
+goog.require('framework.common.tcuInterval');
+goog.require('framework.common.tcuMatrix');
+
+goog.scope(function() {
+
+ modules.shared.glsBuiltinPrecisionTestsUnitTests.cppreference = [];
+ var tcuInterval = framework.common.tcuInterval;
+ var glsBuiltinPrecisionTestsUnitTests = modules.shared.glsBuiltinPrecisionTestsUnitTests;
+ var tcuMatrix = framework.common.tcuMatrix;
+
+ var ref = modules.shared.glsBuiltinPrecisionTestsUnitTests.cppreference;
+ref.push({testName: 'precision.add.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.390625, 0.40625, false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.695313, 0.703125, false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.390625, 0.40625, false, 0.390625, 0.40625, false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.695313, 0.703125, false, 0.695313, 0.703125, false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.390625, 0.40625, false, 0.390625, 0.40625, false, 0.390625, 0.40625, false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.695313, 0.703125, false, 0.695313, 0.703125, false, 0.695313, 0.703125, false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.390625, 0.40625, false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.695313, 0.703125, false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.390625, 0.40625, false, 0.390625, 0.40625, false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.695313, 0.703125, false, 0.695313, 0.703125, false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.390625, 0.40625, false, 0.390625, 0.40625, false, 0.390625, 0.40625, false, 0.390625, 0.40625]});
+ref.push({testName: 'precision.add.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.695313, 0.703125, false, 0.695313, 0.703125, false, 0.695313, 0.703125, false, 0.695313, 0.703125]});
+ref.push({testName: 'precision.add.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.399902, 0.400391, false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.699219, 0.700195, false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.399902, 0.400391, false, 0.399902, 0.400391, false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.699219, 0.700195, false, 0.699219, 0.700195, false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.399902, 0.400391, false, 0.399902, 0.400391, false, 0.399902, 0.400391, false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.699219, 0.700195, false, 0.699219, 0.700195, false, 0.699219, 0.700195, false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.399902, 0.400391, false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.699219, 0.700195, false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.399902, 0.400391, false, 0.399902, 0.400391, false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.699219, 0.700195, false, 0.699219, 0.700195, false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.399902, 0.400391, false, 0.399902, 0.400391, false, 0.399902, 0.400391, false, 0.399902, 0.400391]});
+ref.push({testName: 'precision.add.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.699219, 0.700195, false, 0.699219, 0.700195, false, 0.699219, 0.700195, false, 0.699219, 0.700195]});
+ref.push({testName: 'precision.add.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.7, 0.7, false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.7, 0.7, false, 0.7, 0.7, false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.7, 0.7, false, 0.7, 0.7, false, 0.7, 0.7, false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.7, 0.7, false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.7, 0.7, false, 0.7, 0.7, false, 0.7, 0.7]});
+ref.push({testName: 'precision.add.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.add.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.7, 0.7, false, 0.7, 0.7, false, 0.7, 0.7, false, 0.7, 0.7]});
+ref.push({testName: 'precision.sub.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.304688, -0.296875, false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.304688, -0.296875, false, -0.304688, -0.296875, false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.304688, -0.296875, false, -0.304688, -0.296875, false, -0.304688, -0.296875, false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.304688, -0.296875, false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.304688, -0.296875, false, -0.304688, -0.296875, false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.sub.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.304688, -0.296875, false, -0.304688, -0.296875, false, -0.304688, -0.296875, false, -0.304688, -0.296875]});
+ref.push({testName: 'precision.sub.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.300293, -0.299805, false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.300293, -0.299805, false, -0.300293, -0.299805, false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.300293, -0.299805, false, -0.300293, -0.299805, false, -0.300293, -0.299805, false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.300293, -0.299805, false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.300293, -0.299805, false, -0.300293, -0.299805, false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.sub.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.300293, -0.299805, false, -0.300293, -0.299805, false, -0.300293, -0.299805, false, -0.300293, -0.299805]});
+ref.push({testName: 'precision.sub.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.3, -0.3, false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.3, -0.3, false, -0.3, -0.3, false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.3, -0.3, false, -0.3, -0.3, false, -0.3, -0.3, false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.3, -0.3, false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.3, -0.3, false, -0.3, -0.3, false, -0.3, -0.3]});
+ref.push({testName: 'precision.sub.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.sub.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.3, -0.3, false, -0.3, -0.3, false, -0.3, -0.3, false, -0.3, -0.3]});
+ref.push({testName: 'precision.mul.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.mul.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.mul.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.mul.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.mul.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.mul.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.mul.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.div.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.div.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.996338, 1.0061, false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.398682, 0.401611, false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.996338, 1.0061, false, 0.996338, 1.0061, false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.398682, 0.401611, false, 0.398682, 0.401611, false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.996338, 1.0061, false, 0.996338, 1.0061, false, 0.996338, 1.0061, false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.398682, 0.401611, false, 0.398682, 0.401611, false, 0.398682, 0.401611, false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.996338, 1.0061, false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.398682, 0.401611, false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.996338, 1.0061, false, 0.996338, 1.0061, false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.398682, 0.401611, false, 0.398682, 0.401611, false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.996338, 1.0061, false, 0.996338, 1.0061, false, 0.996338, 1.0061, false, 0.996338, 1.0061]});
+ref.push({testName: 'precision.div.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.398682, 0.401611, false, 0.398682, 0.401611, false, 0.398682, 0.401611, false, 0.398682, 0.401611]});
+ref.push({testName: 'precision.div.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.div.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.div.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.div.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.div.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.div.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.div.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.div.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.div.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.div.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4, false, 0.4, 0.4]});
+ref.push({testName: 'precision.radians.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.radians.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952, false, 0.00347137, 0.00350952]});
+ref.push({testName: 'precision.radians.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738, false, 0.00868225, 0.0087738]});
+ref.push({testName: 'precision.radians.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.radians.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066, false, 0.00349066, 0.00349066]});
+ref.push({testName: 'precision.radians.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665, false, 0.00872664, 0.00872665]});
+ref.push({testName: 'precision.degrees.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.degrees.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 11.4219, 11.5156, false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 28.5625, 28.75, false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4219, 11.5156, false, 11.4219, 11.5156, false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.5625, 28.75, false, 28.5625, 28.75, false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4219, 11.5156, false, 11.4219, 11.5156, false, 11.4219, 11.5156, false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.5625, 28.75, false, 28.5625, 28.75, false, 28.5625, 28.75, false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 11.4219, 11.5156, false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 28.5625, 28.75, false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4219, 11.5156, false, 11.4219, 11.5156, false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.5625, 28.75, false, 28.5625, 28.75, false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4219, 11.5156, false, 11.4219, 11.5156, false, 11.4219, 11.5156, false, 11.4219, 11.5156]});
+ref.push({testName: 'precision.degrees.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.5625, 28.75, false, 28.5625, 28.75, false, 28.5625, 28.75, false, 28.5625, 28.75]});
+ref.push({testName: 'precision.degrees.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 11.4592, 11.4592, false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 28.6479, 28.6479, false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4592, 11.4592, false, 11.4592, 11.4592, false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.6479, 28.6479, false, 28.6479, 28.6479, false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4592, 11.4592, false, 11.4592, 11.4592, false, 11.4592, 11.4592, false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.6479, 28.6479, false, 28.6479, 28.6479, false, 28.6479, 28.6479, false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 11.4592, 11.4592, false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 28.6479, 28.6479, false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4592, 11.4592, false, 11.4592, 11.4592, false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.6479, 28.6479, false, 28.6479, 28.6479, false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.degrees.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 11.4592, 11.4592, false, 11.4592, 11.4592, false, 11.4592, 11.4592, false, 11.4592, 11.4592]});
+ref.push({testName: 'precision.degrees.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 28.6479, 28.6479, false, 28.6479, 28.6479, false, 28.6479, 28.6479, false, 28.6479, 28.6479]});
+ref.push({testName: 'precision.sin.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.178448, 0.217356, false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.463801, 0.495051, false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.178448, 0.217356, false, 0.178448, 0.217356, false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463801, 0.495051, false, 0.463801, 0.495051, false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.178448, 0.217356, false, 0.178448, 0.217356, false, 0.178448, 0.217356, false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463801, 0.495051, false, 0.463801, 0.495051, false, 0.463801, 0.495051, false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.178448, 0.217356, false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.463801, 0.495051, false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.178448, 0.217356, false, 0.178448, 0.217356, false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463801, 0.495051, false, 0.463801, 0.495051, false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.178448, 0.217356, false, 0.178448, 0.217356, false, 0.178448, 0.217356, false, 0.178448, 0.217356]});
+ref.push({testName: 'precision.sin.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463801, 0.495051, false, 0.463801, 0.495051, false, 0.463801, 0.495051, false, 0.463801, 0.495051]});
+ref.push({testName: 'precision.sin.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.198133, 0.199349, false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.478449, 0.480402, false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198133, 0.199349, false, 0.198133, 0.199349, false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478449, 0.480402, false, 0.478449, 0.480402, false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198133, 0.199349, false, 0.198133, 0.199349, false, 0.198133, 0.199349, false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478449, 0.480402, false, 0.478449, 0.480402, false, 0.478449, 0.480402, false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.198133, 0.199349, false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.478449, 0.480402, false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198133, 0.199349, false, 0.198133, 0.199349, false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478449, 0.480402, false, 0.478449, 0.480402, false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198133, 0.199349, false, 0.198133, 0.199349, false, 0.198133, 0.199349, false, 0.198133, 0.199349]});
+ref.push({testName: 'precision.sin.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478449, 0.480402, false, 0.478449, 0.480402, false, 0.478449, 0.480402, false, 0.478449, 0.480402]});
+ref.push({testName: 'precision.sin.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.198181, 0.199158, false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.478937, 0.479914, false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198181, 0.199158, false, 0.198181, 0.199158, false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478937, 0.479914, false, 0.478937, 0.479914, false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198181, 0.199158, false, 0.198181, 0.199158, false, 0.198181, 0.199158, false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478937, 0.479914, false, 0.478937, 0.479914, false, 0.478937, 0.479914, false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.198181, 0.199158, false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.478937, 0.479914, false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198181, 0.199158, false, 0.198181, 0.199158, false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478937, 0.479914, false, 0.478937, 0.479914, false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.sin.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198181, 0.199158, false, 0.198181, 0.199158, false, 0.198181, 0.199158, false, 0.198181, 0.199158]});
+ref.push({testName: 'precision.sin.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.478937, 0.479914, false, 0.478937, 0.479914, false, 0.478937, 0.479914, false, 0.478937, 0.479914]});
+ref.push({testName: 'precision.cos.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.963816, 0.996612, false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.861958, 0.893208, false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.963816, 0.996612, false, 0.963816, 0.996612, false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.861958, 0.893208, false, 0.861958, 0.893208, false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.963816, 0.996612, false, 0.963816, 0.996612, false, 0.963816, 0.996612, false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.861958, 0.893208, false, 0.861958, 0.893208, false, 0.861958, 0.893208, false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.963816, 0.996612, false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.861958, 0.893208, false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.963816, 0.996612, false, 0.963816, 0.996612, false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.861958, 0.893208, false, 0.861958, 0.893208, false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.963816, 0.996612, false, 0.963816, 0.996612, false, 0.963816, 0.996612, false, 0.963816, 0.996612]});
+ref.push({testName: 'precision.cos.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.861958, 0.893208, false, 0.861958, 0.893208, false, 0.861958, 0.893208, false, 0.861958, 0.893208]});
+ref.push({testName: 'precision.cos.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.978075, 0.982029, false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.875629, 0.879536, false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.978075, 0.982029, false, 0.978075, 0.982029, false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.875629, 0.879536, false, 0.875629, 0.879536, false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.978075, 0.982029, false, 0.978075, 0.982029, false, 0.978075, 0.982029, false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.875629, 0.879536, false, 0.875629, 0.879536, false, 0.875629, 0.879536, false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.978075, 0.982029, false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.875629, 0.879536, false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.978075, 0.982029, false, 0.978075, 0.982029, false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.875629, 0.879536, false, 0.875629, 0.879536, false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.978075, 0.982029, false, 0.978075, 0.982029, false, 0.978075, 0.982029, false, 0.978075, 0.982029]});
+ref.push({testName: 'precision.cos.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.875629, 0.879536, false, 0.875629, 0.879536, false, 0.875629, 0.879536, false, 0.875629, 0.879536]});
+ref.push({testName: 'precision.cos.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.979578, 0.980555, false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.877094, 0.878071, false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.979578, 0.980555, false, 0.979578, 0.980555, false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.877094, 0.878071, false, 0.877094, 0.878071, false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.979578, 0.980555, false, 0.979578, 0.980555, false, 0.979578, 0.980555, false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.877094, 0.878071, false, 0.877094, 0.878071, false, 0.877094, 0.878071, false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.979578, 0.980555, false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.877094, 0.878071, false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.979578, 0.980555, false, 0.979578, 0.980555, false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.877094, 0.878071, false, 0.877094, 0.878071, false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.cos.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.979578, 0.980555, false, 0.979578, 0.980555, false, 0.979578, 0.980555, false, 0.979578, 0.980555]});
+ref.push({testName: 'precision.cos.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.877094, 0.878071, false, 0.877094, 0.878071, false, 0.877094, 0.878071, false, 0.877094, 0.878071]});
+ref.push({testName: 'precision.tan.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.tan.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.200684, 0.204834, false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.541016, 0.551758, false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.200684, 0.204834, false, 0.200684, 0.204834, false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.541016, 0.551758, false, 0.541016, 0.551758, false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.200684, 0.204834, false, 0.200684, 0.204834, false, 0.200684, 0.204834, false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.541016, 0.551758, false, 0.541016, 0.551758, false, 0.541016, 0.551758, false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.200684, 0.204834, false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.541016, 0.551758, false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.200684, 0.204834, false, 0.200684, 0.204834, false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.541016, 0.551758, false, 0.541016, 0.551758, false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.200684, 0.204834, false, 0.200684, 0.204834, false, 0.200684, 0.204834, false, 0.200684, 0.204834]});
+ref.push({testName: 'precision.tan.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.541016, 0.551758, false, 0.541016, 0.551758, false, 0.541016, 0.551758, false, 0.541016, 0.551758]});
+ref.push({testName: 'precision.tan.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.202111, 0.20331, false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.545443, 0.547163, false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202111, 0.20331, false, 0.202111, 0.20331, false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.545443, 0.547163, false, 0.545443, 0.547163, false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202111, 0.20331, false, 0.202111, 0.20331, false, 0.202111, 0.20331, false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.545443, 0.547163, false, 0.545443, 0.547163, false, 0.545443, 0.547163, false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.202111, 0.20331, false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.545443, 0.547163, false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202111, 0.20331, false, 0.202111, 0.20331, false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.545443, 0.547163, false, 0.545443, 0.547163, false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.tan.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202111, 0.20331, false, 0.202111, 0.20331, false, 0.202111, 0.20331, false, 0.202111, 0.20331]});
+ref.push({testName: 'precision.tan.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.545443, 0.547163, false, 0.545443, 0.547163, false, 0.545443, 0.547163, false, 0.545443, 0.547163]});
+ref.push({testName: 'precision.asin.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.180951, 0.220173, false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.507974, 0.539224, false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.180951, 0.220173, false, 0.180951, 0.220173, false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.507974, 0.539224, false, 0.507974, 0.539224, false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.180951, 0.220173, false, 0.180951, 0.220173, false, 0.180951, 0.220173, false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.507974, 0.539224, false, 0.507974, 0.539224, false, 0.507974, 0.539224, false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.180951, 0.220173, false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.507974, 0.539224, false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.180951, 0.220173, false, 0.180951, 0.220173, false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.507974, 0.539224, false, 0.507974, 0.539224, false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.180951, 0.220173, false, 0.180951, 0.220173, false, 0.180951, 0.220173, false, 0.180951, 0.220173]});
+ref.push({testName: 'precision.asin.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.507974, 0.539224, false, 0.507974, 0.539224, false, 0.507974, 0.539224, false, 0.507974, 0.539224]});
+ref.push({testName: 'precision.asin.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.20082, 0.202046, false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.521646, 0.525552, false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.20082, 0.202046, false, 0.20082, 0.202046, false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521646, 0.525552, false, 0.521646, 0.525552, false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.20082, 0.202046, false, 0.20082, 0.202046, false, 0.20082, 0.202046, false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521646, 0.525552, false, 0.521646, 0.525552, false, 0.521646, 0.525552, false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.20082, 0.202046, false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.521646, 0.525552, false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.20082, 0.202046, false, 0.20082, 0.202046, false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521646, 0.525552, false, 0.521646, 0.525552, false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.20082, 0.202046, false, 0.20082, 0.202046, false, 0.20082, 0.202046, false, 0.20082, 0.202046]});
+ref.push({testName: 'precision.asin.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521646, 0.525552, false, 0.521646, 0.525552, false, 0.521646, 0.525552, false, 0.521646, 0.525552]});
+ref.push({testName: 'precision.asin.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.201358, 0.201358, false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.523599, 0.523599, false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201358, 0.201358, false, 0.201358, 0.201358, false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.523599, 0.523599, false, 0.523599, 0.523599, false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201358, 0.201358, false, 0.201358, 0.201358, false, 0.201358, 0.201358, false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.523599, 0.523599, false, 0.523599, 0.523599, false, 0.523599, 0.523599, false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.201358, 0.201358, false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.523599, 0.523599, false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201358, 0.201358, false, 0.201358, 0.201358, false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.523599, 0.523599, false, 0.523599, 0.523599, false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.asin.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201358, 0.201358, false, 0.201358, 0.201358, false, 0.201358, 0.201358, false, 0.201358, 0.201358]});
+ref.push({testName: 'precision.asin.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.523599, 0.523599, false, 0.523599, 0.523599, false, 0.523599, 0.523599, false, 0.523599, 0.523599]});
+ref.push({testName: 'precision.acos.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.35062, 1.38985, false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.03157, 1.06282, false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.35062, 1.38985, false, 1.35062, 1.38985, false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.03157, 1.06282, false, 1.03157, 1.06282, false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.35062, 1.38985, false, 1.35062, 1.38985, false, 1.35062, 1.38985, false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.03157, 1.06282, false, 1.03157, 1.06282, false, 1.03157, 1.06282, false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.35062, 1.38985, false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.03157, 1.06282, false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.35062, 1.38985, false, 1.35062, 1.38985, false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.03157, 1.06282, false, 1.03157, 1.06282, false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.35062, 1.38985, false, 1.35062, 1.38985, false, 1.35062, 1.38985, false, 1.35062, 1.38985]});
+ref.push({testName: 'precision.acos.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.03157, 1.06282, false, 1.03157, 1.06282, false, 1.03157, 1.06282, false, 1.03157, 1.06282]});
+ref.push({testName: 'precision.acos.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.36533, 1.37339, false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.04329, 1.0511, false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36533, 1.37339, false, 1.36533, 1.37339, false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.04329, 1.0511, false, 1.04329, 1.0511, false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36533, 1.37339, false, 1.36533, 1.37339, false, 1.36533, 1.37339, false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.04329, 1.0511, false, 1.04329, 1.0511, false, 1.04329, 1.0511, false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.36533, 1.37339, false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.04329, 1.0511, false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36533, 1.37339, false, 1.36533, 1.37339, false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.04329, 1.0511, false, 1.04329, 1.0511, false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36533, 1.37339, false, 1.36533, 1.37339, false, 1.36533, 1.37339, false, 1.36533, 1.37339]});
+ref.push({testName: 'precision.acos.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.04329, 1.0511, false, 1.04329, 1.0511, false, 1.04329, 1.0511, false, 1.04329, 1.0511]});
+ref.push({testName: 'precision.acos.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.36944, 1.36944, false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.0472, 1.0472, false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36944, 1.36944, false, 1.36944, 1.36944, false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.0472, 1.0472, false, 1.0472, 1.0472, false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36944, 1.36944, false, 1.36944, 1.36944, false, 1.36944, 1.36944, false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.0472, 1.0472, false, 1.0472, 1.0472, false, 1.0472, 1.0472, false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.36944, 1.36944, false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.0472, 1.0472, false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36944, 1.36944, false, 1.36944, 1.36944, false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.0472, 1.0472, false, 1.0472, 1.0472, false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.acos.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.36944, 1.36944, false, 1.36944, 1.36944, false, 1.36944, 1.36944, false, 1.36944, 1.36944]});
+ref.push({testName: 'precision.acos.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.0472, 1.0472, false, 1.0472, 1.0472, false, 1.0472, 1.0472, false, 1.0472, 1.0472]});
+ref.push({testName: 'precision.atan2.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.750168, 0.820628, false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.356773, 0.401508, false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.750168, 0.820628, false, 0.750168, 0.820628, false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.356773, 0.401508, false, 0.356773, 0.401508, false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.750168, 0.820628, false, 0.750168, 0.820628, false, 0.750168, 0.820628, false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.356773, 0.401508, false, 0.356773, 0.401508, false, 0.356773, 0.401508, false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.750168, 0.820628, false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.356773, 0.401508, false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.750168, 0.820628, false, 0.750168, 0.820628, false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.356773, 0.401508, false, 0.356773, 0.401508, false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.750168, 0.820628, false, 0.750168, 0.820628, false, 0.750168, 0.820628, false, 0.750168, 0.820628]});
+ref.push({testName: 'precision.atan2.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.356773, 0.401508, false, 0.356773, 0.401508, false, 0.356773, 0.401508, false, 0.356773, 0.401508]});
+ref.push({testName: 'precision.atan2.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.782835, 0.787961, false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.379446, 0.38182, false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.782835, 0.787961, false, 0.782835, 0.787961, false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.379446, 0.38182, false, 0.379446, 0.38182, false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.782835, 0.787961, false, 0.782835, 0.787961, false, 0.782835, 0.787961, false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.379446, 0.38182, false, 0.379446, 0.38182, false, 0.379446, 0.38182, false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.782835, 0.787961, false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.379446, 0.38182, false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.782835, 0.787961, false, 0.782835, 0.787961, false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.379446, 0.38182, false, 0.379446, 0.38182, false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.782835, 0.787961, false, 0.782835, 0.787961, false, 0.782835, 0.787961, false, 0.782835, 0.787961]});
+ref.push({testName: 'precision.atan2.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.379446, 0.38182, false, 0.379446, 0.38182, false, 0.379446, 0.38182, false, 0.379446, 0.38182]});
+ref.push({testName: 'precision.atan2.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.785398, 0.785398, false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.380506, 0.380507, false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.785398, 0.785398, false, 0.785398, 0.785398, false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.380506, 0.380507, false, 0.380506, 0.380507, false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.785398, 0.785398, false, 0.785398, 0.785398, false, 0.785398, 0.785398, false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.380506, 0.380507, false, 0.380506, 0.380507, false, 0.380506, 0.380507, false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.785398, 0.785398, false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.380506, 0.380507, false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.785398, 0.785398, false, 0.785398, 0.785398, false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.380506, 0.380507, false, 0.380506, 0.380507, false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan2.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.785398, 0.785398, false, 0.785398, 0.785398, false, 0.785398, 0.785398, false, 0.785398, 0.785398]});
+ref.push({testName: 'precision.atan2.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.380506, 0.380507, false, 0.380506, 0.380507, false, 0.380506, 0.380507, false, 0.380506, 0.380507]});
+ref.push({testName: 'precision.atan.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.177259, 0.216024, false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.448023, 0.479273, false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.177259, 0.216024, false, 0.177259, 0.216024, false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.448023, 0.479273, false, 0.448023, 0.479273, false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.177259, 0.216024, false, 0.177259, 0.216024, false, 0.177259, 0.216024, false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.448023, 0.479273, false, 0.448023, 0.479273, false, 0.448023, 0.479273, false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.177259, 0.216024, false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.448023, 0.479273, false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.177259, 0.216024, false, 0.177259, 0.216024, false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.448023, 0.479273, false, 0.448023, 0.479273, false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.177259, 0.216024, false, 0.177259, 0.216024, false, 0.177259, 0.216024, false, 0.177259, 0.216024]});
+ref.push({testName: 'precision.atan.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.448023, 0.479273, false, 0.448023, 0.479273, false, 0.448023, 0.479273, false, 0.448023, 0.479273]});
+ref.push({testName: 'precision.atan.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.19686, 0.198072, false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.462671, 0.464624, false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19686, 0.198072, false, 0.19686, 0.198072, false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462671, 0.464624, false, 0.462671, 0.464624, false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19686, 0.198072, false, 0.19686, 0.198072, false, 0.19686, 0.198072, false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462671, 0.464624, false, 0.462671, 0.464624, false, 0.462671, 0.464624, false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.19686, 0.198072, false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.462671, 0.464624, false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19686, 0.198072, false, 0.19686, 0.198072, false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462671, 0.464624, false, 0.462671, 0.464624, false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19686, 0.198072, false, 0.19686, 0.198072, false, 0.19686, 0.198072, false, 0.19686, 0.198072]});
+ref.push({testName: 'precision.atan.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462671, 0.464624, false, 0.462671, 0.464624, false, 0.462671, 0.464624, false, 0.462671, 0.464624]});
+ref.push({testName: 'precision.atan.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.197395, 0.197396, false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.463647, 0.463648, false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197395, 0.197396, false, 0.197395, 0.197396, false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463647, 0.463648, false, 0.463647, 0.463648, false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197395, 0.197396, false, 0.197395, 0.197396, false, 0.197395, 0.197396, false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463647, 0.463648, false, 0.463647, 0.463648, false, 0.463647, 0.463648, false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.197395, 0.197396, false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.463647, 0.463648, false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197395, 0.197396, false, 0.197395, 0.197396, false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463647, 0.463648, false, 0.463647, 0.463648, false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.atan.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197395, 0.197396, false, 0.197395, 0.197396, false, 0.197395, 0.197396, false, 0.197395, 0.197396]});
+ref.push({testName: 'precision.atan.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.463647, 0.463648, false, 0.463647, 0.463648, false, 0.463647, 0.463648, false, 0.463647, 0.463648]});
+ref.push({testName: 'precision.sinh.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sinh.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.197144, 0.205688, false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.51416, 0.528809, false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197144, 0.205688, false, 0.197144, 0.205688, false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.51416, 0.528809, false, 0.51416, 0.528809, false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197144, 0.205688, false, 0.197144, 0.205688, false, 0.197144, 0.205688, false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.51416, 0.528809, false, 0.51416, 0.528809, false, 0.51416, 0.528809, false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.197144, 0.205688, false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.51416, 0.528809, false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197144, 0.205688, false, 0.197144, 0.205688, false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.51416, 0.528809, false, 0.51416, 0.528809, false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197144, 0.205688, false, 0.197144, 0.205688, false, 0.197144, 0.205688, false, 0.197144, 0.205688]});
+ref.push({testName: 'precision.sinh.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.51416, 0.528809, false, 0.51416, 0.528809, false, 0.51416, 0.528809, false, 0.51416, 0.528809]});
+ref.push({testName: 'precision.sinh.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.201336, 0.201336, false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.521095, 0.521096, false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201336, 0.201336, false, 0.201336, 0.201336, false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521095, 0.521096, false, 0.521095, 0.521096, false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201336, 0.201336, false, 0.201336, 0.201336, false, 0.201336, 0.201336, false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521095, 0.521096, false, 0.521095, 0.521096, false, 0.521095, 0.521096, false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.201336, 0.201336, false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.521095, 0.521096, false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201336, 0.201336, false, 0.201336, 0.201336, false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521095, 0.521096, false, 0.521095, 0.521096, false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.sinh.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.201336, 0.201336, false, 0.201336, 0.201336, false, 0.201336, 0.201336, false, 0.201336, 0.201336]});
+ref.push({testName: 'precision.sinh.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.521095, 0.521096, false, 0.521095, 0.521096, false, 0.521095, 0.521096, false, 0.521095, 0.521096]});
+ref.push({testName: 'precision.cosh.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.cosh.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.01074, 1.03027, false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.11816, 1.1377, false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.01074, 1.03027, false, 1.01074, 1.03027, false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.11816, 1.1377, false, 1.11816, 1.1377, false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.01074, 1.03027, false, 1.01074, 1.03027, false, 1.01074, 1.03027, false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.11816, 1.1377, false, 1.11816, 1.1377, false, 1.11816, 1.1377, false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.01074, 1.03027, false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.11816, 1.1377, false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.01074, 1.03027, false, 1.01074, 1.03027, false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.11816, 1.1377, false, 1.11816, 1.1377, false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.01074, 1.03027, false, 1.01074, 1.03027, false, 1.01074, 1.03027, false, 1.01074, 1.03027]});
+ref.push({testName: 'precision.cosh.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.11816, 1.1377, false, 1.11816, 1.1377, false, 1.11816, 1.1377, false, 1.11816, 1.1377]});
+ref.push({testName: 'precision.cosh.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.02007, 1.02007, false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.12763, 1.12763, false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.02007, 1.02007, false, 1.02007, 1.02007, false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.12763, 1.12763, false, 1.12763, 1.12763, false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.02007, 1.02007, false, 1.02007, 1.02007, false, 1.02007, 1.02007, false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.12763, 1.12763, false, 1.12763, 1.12763, false, 1.12763, 1.12763, false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.02007, 1.02007, false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.12763, 1.12763, false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.02007, 1.02007, false, 1.02007, 1.02007, false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.12763, 1.12763, false, 1.12763, 1.12763, false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.cosh.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.02007, 1.02007, false, 1.02007, 1.02007, false, 1.02007, 1.02007, false, 1.02007, 1.02007]});
+ref.push({testName: 'precision.cosh.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.12763, 1.12763, false, 1.12763, 1.12763, false, 1.12763, 1.12763, false, 1.12763, 1.12763]});
+ref.push({testName: 'precision.tanh.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.tanh.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.19074, 0.204113, false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.450711, 0.474146, false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19074, 0.204113, false, 0.19074, 0.204113, false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.450711, 0.474146, false, 0.450711, 0.474146, false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19074, 0.204113, false, 0.19074, 0.204113, false, 0.19074, 0.204113, false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.450711, 0.474146, false, 0.450711, 0.474146, false, 0.450711, 0.474146, false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.19074, 0.204113, false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.450711, 0.474146, false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19074, 0.204113, false, 0.19074, 0.204113, false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.450711, 0.474146, false, 0.450711, 0.474146, false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.19074, 0.204113, false, 0.19074, 0.204113, false, 0.19074, 0.204113, false, 0.19074, 0.204113]});
+ref.push({testName: 'precision.tanh.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.450711, 0.474146, false, 0.450711, 0.474146, false, 0.450711, 0.474146, false, 0.450711, 0.474146]});
+ref.push({testName: 'precision.tanh.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.197375, 0.197376, false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.462116, 0.462118, false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197375, 0.197376, false, 0.197375, 0.197376, false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462116, 0.462118, false, 0.462116, 0.462118, false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197375, 0.197376, false, 0.197375, 0.197376, false, 0.197375, 0.197376, false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462116, 0.462118, false, 0.462116, 0.462118, false, 0.462116, 0.462118, false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.197375, 0.197376, false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.462116, 0.462118, false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197375, 0.197376, false, 0.197375, 0.197376, false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462116, 0.462118, false, 0.462116, 0.462118, false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.tanh.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.197375, 0.197376, false, 0.197375, 0.197376, false, 0.197375, 0.197376, false, 0.197375, 0.197376]});
+ref.push({testName: 'precision.tanh.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.462116, 0.462118, false, 0.462116, 0.462118, false, 0.462116, 0.462118, false, 0.462116, 0.462118]});
+ref.push({testName: 'precision.asinh.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.asinh.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.183582, 0.213619, false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.468033, 0.494521, false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.183582, 0.213619, false, 0.183582, 0.213619, false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.468033, 0.494521, false, 0.468033, 0.494521, false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.183582, 0.213619, false, 0.183582, 0.213619, false, 0.183582, 0.213619, false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.468033, 0.494521, false, 0.468033, 0.494521, false, 0.468033, 0.494521, false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.183582, 0.213619, false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.468033, 0.494521, false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.183582, 0.213619, false, 0.183582, 0.213619, false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.468033, 0.494521, false, 0.468033, 0.494521, false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.183582, 0.213619, false, 0.183582, 0.213619, false, 0.183582, 0.213619, false, 0.183582, 0.213619]});
+ref.push({testName: 'precision.asinh.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.468033, 0.494521, false, 0.468033, 0.494521, false, 0.468033, 0.494521, false, 0.468033, 0.494521]});
+ref.push({testName: 'precision.asinh.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.198689, 0.198691, false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.481211, 0.481213, false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198689, 0.198691, false, 0.198689, 0.198691, false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.481211, 0.481213, false, 0.481211, 0.481213, false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198689, 0.198691, false, 0.198689, 0.198691, false, 0.198689, 0.198691, false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.481211, 0.481213, false, 0.481211, 0.481213, false, 0.481211, 0.481213, false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.198689, 0.198691, false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.481211, 0.481213, false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198689, 0.198691, false, 0.198689, 0.198691, false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.481211, 0.481213, false, 0.481211, 0.481213, false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.asinh.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.198689, 0.198691, false, 0.198689, 0.198691, false, 0.198689, 0.198691, false, 0.198689, 0.198691]});
+ref.push({testName: 'precision.asinh.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.481211, 0.481213, false, 0.481211, 0.481213, false, 0.481211, 0.481213, false, 0.481211, 0.481213]});
+ref.push({testName: 'precision.acosh.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.acosh.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.atanh.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.196289, 0.208984, false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.544922, 0.553711, false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.196289, 0.208984, false, 0.196289, 0.208984, false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.544922, 0.553711, false, 0.544922, 0.553711, false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.196289, 0.208984, false, 0.196289, 0.208984, false, 0.196289, 0.208984, false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.544922, 0.553711, false, 0.544922, 0.553711, false, 0.544922, 0.553711, false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.196289, 0.208984, false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.544922, 0.553711, false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.196289, 0.208984, false, 0.196289, 0.208984, false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.544922, 0.553711, false, 0.544922, 0.553711, false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.196289, 0.208984, false, 0.196289, 0.208984, false, 0.196289, 0.208984, false, 0.196289, 0.208984]});
+ref.push({testName: 'precision.atanh.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.544922, 0.553711, false, 0.544922, 0.553711, false, 0.544922, 0.553711, false, 0.544922, 0.553711]});
+ref.push({testName: 'precision.atanh.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.202732, 0.202733, false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.549306, 0.549306, false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202732, 0.202733, false, 0.202732, 0.202733, false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.549306, 0.549306, false, 0.549306, 0.549306, false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202732, 0.202733, false, 0.202732, 0.202733, false, 0.202732, 0.202733, false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.549306, 0.549306, false, 0.549306, 0.549306, false, 0.549306, 0.549306, false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.202732, 0.202733, false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.549306, 0.549306, false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202732, 0.202733, false, 0.202732, 0.202733, false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.549306, 0.549306, false, 0.549306, 0.549306, false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.atanh.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.202732, 0.202733, false, 0.202732, 0.202733, false, 0.202732, 0.202733, false, 0.202732, 0.202733]});
+ref.push({testName: 'precision.atanh.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.549306, 0.549306, false, 0.549306, 0.549306, false, 0.549306, 0.549306, false, 0.549306, 0.549306]});
+ref.push({testName: 'precision.pow.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 0.782566, false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0, 0.51834, false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.782566, false, 0, 0.782566, false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0, 0.51834, false, 0, 0.51834, false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.782566, false, 0, 0.782566, false, 0, 0.782566, false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0, 0.51834, false, 0, 0.51834, false, 0, 0.51834, false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 0.782566, false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0, 0.51834, false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.782566, false, 0, 0.782566, false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0, 0.51834, false, 0, 0.51834, false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.782566, false, 0, 0.782566, false, 0, 0.782566, false, 0, 0.782566]});
+ref.push({testName: 'precision.pow.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0, 0.51834, false, 0, 0.51834, false, 0, 0.51834, false, 0, 0.51834]});
+ref.push({testName: 'precision.pow.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.720704, 0.728633, false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.443535, 0.450783, false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.720704, 0.728633, false, 0.720704, 0.728633, false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.443535, 0.450783, false, 0.443535, 0.450783, false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.720704, 0.728633, false, 0.720704, 0.728633, false, 0.720704, 0.728633, false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.443535, 0.450783, false, 0.443535, 0.450783, false, 0.443535, 0.450783, false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.720704, 0.728633, false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.443535, 0.450783, false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.720704, 0.728633, false, 0.720704, 0.728633, false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.443535, 0.450783, false, 0.443535, 0.450783, false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.720704, 0.728633, false, 0.720704, 0.728633, false, 0.720704, 0.728633, false, 0.720704, 0.728633]});
+ref.push({testName: 'precision.pow.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.443535, 0.450783, false, 0.443535, 0.450783, false, 0.443535, 0.450783, false, 0.443535, 0.450783]});
+ref.push({testName: 'precision.pow.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.724779, 0.72478, false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.724779, 0.72478, false, 0.724779, 0.72478, false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.724779, 0.72478, false, 0.724779, 0.72478, false, 0.724779, 0.72478, false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.724779, 0.72478, false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.724779, 0.72478, false, 0.724779, 0.72478, false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.pow.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.724779, 0.72478, false, 0.724779, 0.72478, false, 0.724779, 0.72478, false, 0.724779, 0.72478]});
+ref.push({testName: 'precision.pow.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.exp.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.20007, 1.24085, false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.6331, 1.66435, false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.20007, 1.24085, false, 1.20007, 1.24085, false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.6331, 1.66435, false, 1.6331, 1.66435, false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.20007, 1.24085, false, 1.20007, 1.24085, false, 1.20007, 1.24085, false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.6331, 1.66435, false, 1.6331, 1.66435, false, 1.6331, 1.66435, false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.20007, 1.24085, false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.6331, 1.66435, false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.20007, 1.24085, false, 1.20007, 1.24085, false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.6331, 1.66435, false, 1.6331, 1.66435, false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.20007, 1.24085, false, 1.20007, 1.24085, false, 1.20007, 1.24085, false, 1.20007, 1.24085]});
+ref.push({testName: 'precision.exp.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.6331, 1.66435, false, 1.6331, 1.66435, false, 1.6331, 1.66435, false, 1.6331, 1.66435]});
+ref.push({testName: 'precision.exp.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.21666, 1.22633, false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.64286, 1.65458, false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.21666, 1.22633, false, 1.21666, 1.22633, false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64286, 1.65458, false, 1.64286, 1.65458, false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.21666, 1.22633, false, 1.21666, 1.22633, false, 1.21666, 1.22633, false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64286, 1.65458, false, 1.64286, 1.65458, false, 1.64286, 1.65458, false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.21666, 1.22633, false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.64286, 1.65458, false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.21666, 1.22633, false, 1.21666, 1.22633, false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64286, 1.65458, false, 1.64286, 1.65458, false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.21666, 1.22633, false, 1.21666, 1.22633, false, 1.21666, 1.22633, false, 1.21666, 1.22633]});
+ref.push({testName: 'precision.exp.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64286, 1.65458, false, 1.64286, 1.65458, false, 1.64286, 1.65458, false, 1.64286, 1.65458]});
+ref.push({testName: 'precision.exp.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.2214, 1.2214, false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.64872, 1.64872, false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.2214, 1.2214, false, 1.2214, 1.2214, false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64872, 1.64872, false, 1.64872, 1.64872, false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.2214, 1.2214, false, 1.2214, 1.2214, false, 1.2214, 1.2214, false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64872, 1.64872, false, 1.64872, 1.64872, false, 1.64872, 1.64872, false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.2214, 1.2214, false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.64872, 1.64872, false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.2214, 1.2214, false, 1.2214, 1.2214, false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64872, 1.64872, false, 1.64872, 1.64872, false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.exp.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.2214, 1.2214, false, 1.2214, 1.2214, false, 1.2214, 1.2214, false, 1.2214, 1.2214]});
+ref.push({testName: 'precision.exp.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.64872, 1.64872, false, 1.64872, 1.64872, false, 1.64872, 1.64872, false, 1.64872, 1.64872]});
+ref.push({testName: 'precision.log.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -1.64878, -1.57831, false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -0.708772, -0.677522, false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.64878, -1.57831, false, -1.64878, -1.57831, false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.708772, -0.677522, false, -0.708772, -0.677522, false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.64878, -1.57831, false, -1.64878, -1.57831, false, -1.64878, -1.57831, false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.708772, -0.677522, false, -0.708772, -0.677522, false, -0.708772, -0.677522, false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -1.64878, -1.57831, false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -0.708772, -0.677522, false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.64878, -1.57831, false, -1.64878, -1.57831, false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.708772, -0.677522, false, -0.708772, -0.677522, false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.64878, -1.57831, false, -1.64878, -1.57831, false, -1.64878, -1.57831, false, -1.64878, -1.57831]});
+ref.push({testName: 'precision.log.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.708772, -0.677522, false, -0.708772, -0.677522, false, -0.708772, -0.677522, false, -0.708772, -0.677522]});
+ref.push({testName: 'precision.log.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -1.61359, -1.60456, false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -0.70096, -0.685335, false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.61359, -1.60456, false, -1.61359, -1.60456, false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.70096, -0.685335, false, -0.70096, -0.685335, false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.61359, -1.60456, false, -1.61359, -1.60456, false, -1.61359, -1.60456, false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.70096, -0.685335, false, -0.70096, -0.685335, false, -0.70096, -0.685335, false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -1.61359, -1.60456, false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -0.70096, -0.685335, false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.61359, -1.60456, false, -1.61359, -1.60456, false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.70096, -0.685335, false, -0.70096, -0.685335, false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.61359, -1.60456, false, -1.61359, -1.60456, false, -1.61359, -1.60456, false, -1.61359, -1.60456]});
+ref.push({testName: 'precision.log.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.70096, -0.685335, false, -0.70096, -0.685335, false, -0.70096, -0.685335, false, -0.70096, -0.685335]});
+ref.push({testName: 'precision.log.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -1.60944, -1.60944, false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -0.693148, -0.693147, false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.60944, -1.60944, false, -1.60944, -1.60944, false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.693148, -0.693147, false, -0.693148, -0.693147, false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.60944, -1.60944, false, -1.60944, -1.60944, false, -1.60944, -1.60944, false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.693148, -0.693147, false, -0.693148, -0.693147, false, -0.693148, -0.693147, false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -1.60944, -1.60944, false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -0.693148, -0.693147, false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.60944, -1.60944, false, -1.60944, -1.60944, false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.693148, -0.693147, false, -0.693148, -0.693147, false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.log.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -1.60944, -1.60944, false, -1.60944, -1.60944, false, -1.60944, -1.60944, false, -1.60944, -1.60944]});
+ref.push({testName: 'precision.log.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -0.693148, -0.693147, false, -0.693148, -0.693147, false, -0.693148, -0.693147, false, -0.693148, -0.693147]});
+ref.push({testName: 'precision.exp2.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.12935, 1.16681, false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.12935, 1.16681, false, 1.12935, 1.16681, false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.12935, 1.16681, false, 1.12935, 1.16681, false, 1.12935, 1.16681, false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.12935, 1.16681, false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.12935, 1.16681, false, 1.12935, 1.16681, false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.12935, 1.16681, false, 1.12935, 1.16681, false, 1.12935, 1.16681, false, 1.12935, 1.16681]});
+ref.push({testName: 'precision.exp2.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.exp2.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.14397, 1.15354, false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.40835, 1.42007, false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.14397, 1.15354, false, 1.14397, 1.15354, false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.40835, 1.42007, false, 1.40835, 1.42007, false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.14397, 1.15354, false, 1.14397, 1.15354, false, 1.14397, 1.15354, false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.40835, 1.42007, false, 1.40835, 1.42007, false, 1.40835, 1.42007, false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.14397, 1.15354, false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.40835, 1.42007, false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.14397, 1.15354, false, 1.14397, 1.15354, false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.40835, 1.42007, false, 1.40835, 1.42007, false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.14397, 1.15354, false, 1.14397, 1.15354, false, 1.14397, 1.15354, false, 1.14397, 1.15354]});
+ref.push({testName: 'precision.exp2.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.40835, 1.42007, false, 1.40835, 1.42007, false, 1.40835, 1.42007, false, 1.40835, 1.42007]});
+ref.push({testName: 'precision.exp2.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.1487, 1.1487, false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.1487, 1.1487, false, 1.1487, 1.1487, false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.1487, 1.1487, false, 1.1487, 1.1487, false, 1.1487, 1.1487, false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.1487, 1.1487, false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.1487, 1.1487, false, 1.1487, 1.1487, false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.exp2.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.1487, 1.1487, false, 1.1487, 1.1487, false, 1.1487, 1.1487, false, 1.1487, 1.1487]});
+ref.push({testName: 'precision.exp2.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.log2.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, -1.99219, false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -1.01563, -0.984375, false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, -1.99219, false, -Infinity, -1.99219, false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.01563, -0.984375, false, -1.01563, -0.984375, false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, -1.99219, false, -Infinity, -1.99219, false, -Infinity, -1.99219, false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.01563, -0.984375, false, -1.01563, -0.984375, false, -1.01563, -0.984375, false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, -1.99219, false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -1.01563, -0.984375, false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, -1.99219, false, -Infinity, -1.99219, false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.01563, -0.984375, false, -1.01563, -0.984375, false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, -1.99219, false, -Infinity, -1.99219, false, -Infinity, -1.99219, false, -Infinity, -1.99219]});
+ref.push({testName: 'precision.log2.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.01563, -0.984375, false, -1.01563, -0.984375, false, -1.01563, -0.984375, false, -1.01563, -0.984375]});
+ref.push({testName: 'precision.log2.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -2.33009, -2.31271, false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -1.00781, -0.992188, false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.33009, -2.31271, false, -2.33009, -2.31271, false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.00781, -0.992188, false, -1.00781, -0.992188, false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.33009, -2.31271, false, -2.33009, -2.31271, false, -2.33009, -2.31271, false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.00781, -0.992188, false, -1.00781, -0.992188, false, -1.00781, -0.992188, false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -2.33009, -2.31271, false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -1.00781, -0.992188, false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.33009, -2.31271, false, -2.33009, -2.31271, false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.00781, -0.992188, false, -1.00781, -0.992188, false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.33009, -2.31271, false, -2.33009, -2.31271, false, -2.33009, -2.31271, false, -2.33009, -2.31271]});
+ref.push({testName: 'precision.log2.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -1.00781, -0.992188, false, -1.00781, -0.992188, false, -1.00781, -0.992188, false, -1.00781, -0.992188]});
+ref.push({testName: 'precision.log2.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -2.32193, -2.32193, false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -1, -1, false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.32193, -2.32193, false, -2.32193, -2.32193, false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -1, -1, false, -1, -1, false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.32193, -2.32193, false, -2.32193, -2.32193, false, -2.32193, -2.32193, false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -1, -1, false, -1, -1, false, -1, -1, false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -2.32193, -2.32193, false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -1, -1, false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.32193, -2.32193, false, -2.32193, -2.32193, false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -1, -1, false, -1, -1, false, -1, -1]});
+ref.push({testName: 'precision.log2.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -2.32193, -2.32193, false, -2.32193, -2.32193, false, -2.32193, -2.32193, false, -2.32193, -2.32193]});
+ref.push({testName: 'precision.log2.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -1, -1, false, -1, -1, false, -1, -1, false, -1, -1]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.444382, 0.450222, false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507, false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.444382, 0.450222, false, 0.444382, 0.450222, false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507, false, 0.702718, 0.711507, false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.444382, 0.450222, false, 0.444382, 0.450222, false, 0.444382, 0.450222, false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507, false, 0.702718, 0.711507, false, 0.702718, 0.711507, false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.444382, 0.450222, false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507, false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.444382, 0.450222, false, 0.444382, 0.450222, false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507, false, 0.702718, 0.711507, false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.444382, 0.450222, false, 0.444382, 0.450222, false, 0.444382, 0.450222, false, 0.444382, 0.450222]});
+ref.push({testName: 'precision.sqrt.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507, false, 0.702718, 0.711507, false, 0.702718, 0.711507, false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.sqrt.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107, false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107, false, 0.707107, 0.707107, false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107, false, 0.707107, 0.707107, false, 0.707107, 0.707107, false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107, false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107, false, 0.707107, 0.707107, false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.sqrt.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214, false, 0.447213, 0.447214]});
+ref.push({testName: 'precision.sqrt.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107, false, 0.707107, 0.707107, false, 0.707107, 0.707107, false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.99219, Infinity, false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.99219, Infinity, false, 1.99219, Infinity, false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.99219, Infinity, false, 1.99219, Infinity, false, 1.99219, Infinity, false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1.99219, Infinity, false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.99219, Infinity, false, 1.99219, Infinity, false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1.99219, Infinity, false, 1.99219, Infinity, false, 1.99219, Infinity, false, 1.99219, Infinity]});
+ref.push({testName: 'precision.inversesqrt.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984, false, 1.39859, 1.42984]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 2.22716, 2.24415, false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.41031, 1.41812, false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.22716, 2.24415, false, 2.22716, 2.24415, false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41031, 1.41812, false, 1.41031, 1.41812, false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.22716, 2.24415, false, 2.22716, 2.24415, false, 2.22716, 2.24415, false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41031, 1.41812, false, 1.41031, 1.41812, false, 1.41031, 1.41812, false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 2.22716, 2.24415, false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.41031, 1.41812, false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.22716, 2.24415, false, 2.22716, 2.24415, false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41031, 1.41812, false, 1.41031, 1.41812, false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.22716, 2.24415, false, 2.22716, 2.24415, false, 2.22716, 2.24415, false, 2.22716, 2.24415]});
+ref.push({testName: 'precision.inversesqrt.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41031, 1.41812, false, 1.41031, 1.41812, false, 1.41031, 1.41812, false, 1.41031, 1.41812]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 2.23607, 2.23607, false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.23607, 2.23607, false, 2.23607, 2.23607, false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.23607, 2.23607, false, 2.23607, 2.23607, false, 2.23607, 2.23607, false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 2.23607, 2.23607, false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.23607, 2.23607, false, 2.23607, 2.23607, false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 2.23607, 2.23607, false, 2.23607, 2.23607, false, 2.23607, 2.23607, false, 2.23607, 2.23607]});
+ref.push({testName: 'precision.inversesqrt.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421, false, 1.41421, 1.41421]});
+ref.push({testName: 'precision.abs.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.abs.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.abs.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.abs.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.abs.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.sign.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.sign.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.floor.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.floor.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.trunc.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.round.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.round.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.round.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.round.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.round.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.round.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.roundeven.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.ceil.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.ceil.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.fract.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.fract.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.fract.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.fract.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.fract.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.mod.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.mod.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.200195, false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.200195, false, -0.000244141, 0.200195, false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.200195, false, -0.000244141, 0.200195, false, -0.000244141, 0.200195, false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.200195, false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.200195, false, -0.000244141, 0.200195, false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, -0.000244141, 0.200195, false, -0.000244141, 0.200195, false, -0.000244141, 0.200195, false, -0.000244141, 0.200195]});
+ref.push({testName: 'precision.mod.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mod.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 0.2, false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.2, false, 0, 0.2, false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.2, false, 0, 0.2, false, 0, 0.2, false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 0.2, false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.2, false, 0, 0.2, false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 0.2, false, 0, 0.2, false, 0, 0.2, false, 0, 0.2]});
+ref.push({testName: 'precision.mod.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.modf.lowp_vertex', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.lowp_vertex', input: '0.2, (), (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.modf.lowp_vertex', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.lowp_vertex', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.modf.lowp_fragment', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.lowp_fragment', input: '0.2, (), (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.modf.lowp_fragment', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.lowp_fragment', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.modf.mediump_vertex', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.mediump_vertex', input: '0.2, (), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.modf.mediump_vertex', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.mediump_vertex', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.modf.mediump_fragment', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.mediump_fragment', input: '0.2, (), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.modf.mediump_fragment', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.mediump_fragment', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.modf.highp_vertex', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.highp_vertex', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.modf.highp_vertex', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.highp_vertex', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.modf.highp_fragment', input: '0.2, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.highp_fragment', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.modf.highp_fragment', input: '0.5, (), (), ()', reference: [false, 0, 0]});
+ref.push({testName: 'precision.modf.highp_fragment', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.min.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.min.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.min.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.min.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.max.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.max.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.max.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.max.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.clamp.lowp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.clamp.mediump_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.clamp.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.clamp.highp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.clamp.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.lowp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.179688, 0.210938, false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.1875, 0.203125, false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.179688, 0.210938, false, 0.179688, 0.210938, false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.1875, 0.203125, false, 0.1875, 0.203125, false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.179688, 0.210938, false, 0.179688, 0.210938, false, 0.179688, 0.210938, false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.1875, 0.203125, false, 0.1875, 0.203125, false, 0.1875, 0.203125, false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.179688, 0.210938, false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.1875, 0.203125, false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.179688, 0.210938, false, 0.179688, 0.210938, false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.1875, 0.203125, false, 0.1875, 0.203125, false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.179688, 0.210938, false, 0.179688, 0.210938, false, 0.179688, 0.210938, false, 0.179688, 0.210938]});
+ref.push({testName: 'precision.mix.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.1875, 0.203125, false, 0.1875, 0.203125, false, 0.1875, 0.203125, false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.mix.mediump_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.199707, 0.200684, false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.199707, 0.200684, false, 0.199707, 0.200684, false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.199707, 0.200684, false, 0.199707, 0.200684, false, 0.199707, 0.200684, false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.199707, 0.200684, false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.199707, 0.200684, false, 0.199707, 0.200684, false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.199707, 0.200684, false, 0.199707, 0.200684, false, 0.199707, 0.200684, false, 0.199707, 0.200684]});
+ref.push({testName: 'precision.mix.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.mix.highp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.mix.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2, false, 0.2, 0.2]});
+ref.push({testName: 'precision.step.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0, 1, false, 0, 1, false, 0, 1, false, 0, 1]});
+ref.push({testName: 'precision.step.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.step.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 1, 1, false, 1, 1, false, 1, 1, false, 1, 1]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity, true, -Infinity, Infinity]});
+ref.push({testName: 'precision.smoothstep.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, 0, 3, false, 0, 3, false, 0, 3, false, 0, 3]});
+ref.push({testName: 'precision.length.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.length.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.198712, 0.201489]});
+ref.push({testName: 'precision.length.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.497805, 0.50342]});
+ref.push({testName: 'precision.length.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.280921, 0.285045]});
+ref.push({testName: 'precision.length.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.length.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.344072, 0.349095]});
+ref.push({testName: 'precision.length.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.860664, 0.871406]});
+ref.push({testName: 'precision.length.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.397121, 0.403285]});
+ref.push({testName: 'precision.length.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.995609, 1.00684]});
+ref.push({testName: 'precision.length.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.198712, 0.201489]});
+ref.push({testName: 'precision.length.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.497805, 0.50342]});
+ref.push({testName: 'precision.length.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.280921, 0.285045]});
+ref.push({testName: 'precision.length.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.702718, 0.711507]});
+ref.push({testName: 'precision.length.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.344072, 0.349095]});
+ref.push({testName: 'precision.length.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.860664, 0.871406]});
+ref.push({testName: 'precision.length.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.397121, 0.403285]});
+ref.push({testName: 'precision.length.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.995609, 1.00684]});
+ref.push({testName: 'precision.length.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.length.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.length.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.282843, 0.282843]});
+ref.push({testName: 'precision.length.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.length.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.34641, 0.34641]});
+ref.push({testName: 'precision.length.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.866025, 0.866026]});
+ref.push({testName: 'precision.length.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.length.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.length.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.length.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.5, 0.5]});
+ref.push({testName: 'precision.length.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.282843, 0.282843]});
+ref.push({testName: 'precision.length.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.707107, 0.707107]});
+ref.push({testName: 'precision.length.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.34641, 0.34641]});
+ref.push({testName: 'precision.length.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.866025, 0.866026]});
+ref.push({testName: 'precision.length.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.length.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.distance.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.297819, 0.302277]});
+ref.push({testName: 'precision.distance.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.421276, 0.427394]});
+ref.push({testName: 'precision.distance.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.515672, 0.524075]});
+ref.push({testName: 'precision.distance.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.595637, 0.604962]});
+ref.push({testName: 'precision.distance.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.297819, 0.302277]});
+ref.push({testName: 'precision.distance.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.421276, 0.427394]});
+ref.push({testName: 'precision.distance.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.515672, 0.524075]});
+ref.push({testName: 'precision.distance.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.595637, 0.604962]});
+ref.push({testName: 'precision.distance.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.3, 0.3]});
+ref.push({testName: 'precision.distance.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.424264, 0.424264]});
+ref.push({testName: 'precision.distance.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.519615, 0.519615]});
+ref.push({testName: 'precision.distance.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.6, 0.6]});
+ref.push({testName: 'precision.distance.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.3, 0.3]});
+ref.push({testName: 'precision.distance.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.424264, 0.424264]});
+ref.push({testName: 'precision.distance.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.519615, 0.519615]});
+ref.push({testName: 'precision.distance.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [true, -Infinity, Infinity]});
+ref.push({testName: 'precision.distance.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.6, 0.6]});
+ref.push({testName: 'precision.dot.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.dot.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.dot.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.0625, 0.09375]});
+ref.push({testName: 'precision.dot.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.dot.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.09375, 0.140625]});
+ref.push({testName: 'precision.dot.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.28125, 0.304688]});
+ref.push({testName: 'precision.dot.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.125, 0.1875]});
+ref.push({testName: 'precision.dot.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.375, 0.40625]});
+ref.push({testName: 'precision.dot.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.dot.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.dot.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.0625, 0.09375]});
+ref.push({testName: 'precision.dot.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1875, 0.203125]});
+ref.push({testName: 'precision.dot.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.09375, 0.140625]});
+ref.push({testName: 'precision.dot.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.28125, 0.304688]});
+ref.push({testName: 'precision.dot.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.125, 0.1875]});
+ref.push({testName: 'precision.dot.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.375, 0.40625]});
+ref.push({testName: 'precision.dot.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.dot.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.dot.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.0799561, 0.0802002]});
+ref.push({testName: 'precision.dot.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.dot.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.119873, 0.120361]});
+ref.push({testName: 'precision.dot.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.299805, 0.300293]});
+ref.push({testName: 'precision.dot.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.159668, 0.160645]});
+ref.push({testName: 'precision.dot.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.399414, 0.400391]});
+ref.push({testName: 'precision.dot.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.dot.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.dot.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.0799561, 0.0802002]});
+ref.push({testName: 'precision.dot.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.dot.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.119873, 0.120361]});
+ref.push({testName: 'precision.dot.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.299805, 0.300293]});
+ref.push({testName: 'precision.dot.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.159668, 0.160645]});
+ref.push({testName: 'precision.dot.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.399414, 0.400391]});
+ref.push({testName: 'precision.dot.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.04, 0.04]});
+ref.push({testName: 'precision.dot.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.1, 0.1]});
+ref.push({testName: 'precision.dot.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.08, 0.08]});
+ref.push({testName: 'precision.dot.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.dot.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.12, 0.12]});
+ref.push({testName: 'precision.dot.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.3, 0.3]});
+ref.push({testName: 'precision.dot.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.16, 0.16]});
+ref.push({testName: 'precision.dot.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.dot.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.04, 0.04]});
+ref.push({testName: 'precision.dot.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.1, 0.1]});
+ref.push({testName: 'precision.dot.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.08, 0.08]});
+ref.push({testName: 'precision.dot.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.2, 0.2]});
+ref.push({testName: 'precision.dot.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.12, 0.12]});
+ref.push({testName: 'precision.dot.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.3, 0.3]});
+ref.push({testName: 'precision.dot.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.16, 0.16]});
+ref.push({testName: 'precision.dot.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.4, 0.4]});
+ref.push({testName: 'precision.cross.lowp_vertex', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.015625, 0.015625, false, -0.015625, 0.015625, false, -0.015625, 0.015625]});
+ref.push({testName: 'precision.cross.lowp_vertex', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.cross.lowp_fragment', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.015625, 0.015625, false, -0.015625, 0.015625, false, -0.015625, 0.015625]});
+ref.push({testName: 'precision.cross.lowp_fragment', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125, false, -0.0078125, 0.0078125]});
+ref.push({testName: 'precision.cross.mediump_vertex', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207]});
+ref.push({testName: 'precision.cross.mediump_vertex', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207]});
+ref.push({testName: 'precision.cross.mediump_fragment', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207]});
+ref.push({testName: 'precision.cross.mediump_fragment', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207, false, -0.00012207, 0.00012207]});
+ref.push({testName: 'precision.cross.highp_vertex', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -3.72529e-009, 3.72529e-009, false, -3.72529e-009, 3.72529e-009, false, -3.72529e-009, 3.72529e-009]});
+ref.push({testName: 'precision.cross.highp_vertex', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.cross.highp_fragment', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, -3.72529e-009, 3.72529e-009, false, -3.72529e-009, 3.72529e-009, false, -3.72529e-009, 3.72529e-009]});
+ref.push({testName: 'precision.cross.highp_fragment', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.normalize.lowp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.lowp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.normalize.mediump_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 0.989926, 1.01235]});
+ref.push({testName: 'precision.normalize.mediump_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 0.990765, 1.00929]});
+ref.push({testName: 'precision.normalize.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.699031, 0.71508, false, 0.699031, 0.71508]});
+ref.push({testName: 'precision.normalize.mediump_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.700293, 0.713965, false, 0.700293, 0.713965]});
+ref.push({testName: 'precision.normalize.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.570329, 0.584282, false, 0.570329, 0.584282, false, 0.570329, 0.584282]});
+ref.push({testName: 'precision.normalize.mediump_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.571344, 0.583388, false, 0.571344, 0.583388, false, 0.571344, 0.583388]});
+ref.push({testName: 'precision.normalize.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.494586, 0.506559, false, 0.494586, 0.506559, false, 0.494586, 0.506559, false, 0.494586, 0.506559]});
+ref.push({testName: 'precision.normalize.mediump_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.495383, 0.504646, false, 0.495383, 0.504646, false, 0.495383, 0.504646, false, 0.495383, 0.504646]});
+ref.push({testName: 'precision.normalize.mediump_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 0.989926, 1.01235]});
+ref.push({testName: 'precision.normalize.mediump_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 0.990765, 1.00929]});
+ref.push({testName: 'precision.normalize.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.699031, 0.71508, false, 0.699031, 0.71508]});
+ref.push({testName: 'precision.normalize.mediump_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.700293, 0.713965, false, 0.700293, 0.713965]});
+ref.push({testName: 'precision.normalize.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.570329, 0.584282, false, 0.570329, 0.584282, false, 0.570329, 0.584282]});
+ref.push({testName: 'precision.normalize.mediump_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.571344, 0.583388, false, 0.571344, 0.583388, false, 0.571344, 0.583388]});
+ref.push({testName: 'precision.normalize.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.494586, 0.506559, false, 0.494586, 0.506559, false, 0.494586, 0.506559, false, 0.494586, 0.506559]});
+ref.push({testName: 'precision.normalize.mediump_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.495383, 0.504646, false, 0.495383, 0.504646, false, 0.495383, 0.504646, false, 0.495383, 0.504646]});
+ref.push({testName: 'precision.normalize.highp_vertex.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.normalize.highp_vertex.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.normalize.highp_vertex.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.707106, 0.707107, false, 0.707106, 0.707107]});
+ref.push({testName: 'precision.normalize.highp_vertex.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.707106, 0.707107, false, 0.707106, 0.707107]});
+ref.push({testName: 'precision.normalize.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.57735, 0.577351, false, 0.57735, 0.577351, false, 0.57735, 0.577351]});
+ref.push({testName: 'precision.normalize.highp_vertex.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.57735, 0.577351, false, 0.57735, 0.577351, false, 0.57735, 0.577351]});
+ref.push({testName: 'precision.normalize.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.normalize.highp_vertex.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.normalize.highp_fragment.scalar', input: '0.2, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.normalize.highp_fragment.scalar', input: '0.5, (), (), ()', reference: [false, 1, 1]});
+ref.push({testName: 'precision.normalize.highp_fragment.vec2', input: 'vec2(0.2, 0.2), (), (), ()', reference: [false, 0.707106, 0.707107, false, 0.707106, 0.707107]});
+ref.push({testName: 'precision.normalize.highp_fragment.vec2', input: 'vec2(0.5, 0.5), (), (), ()', reference: [false, 0.707106, 0.707107, false, 0.707106, 0.707107]});
+ref.push({testName: 'precision.normalize.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.57735, 0.577351, false, 0.57735, 0.577351, false, 0.57735, 0.577351]});
+ref.push({testName: 'precision.normalize.highp_fragment.vec3', input: 'vec3(0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.57735, 0.577351, false, 0.57735, 0.577351, false, 0.57735, 0.577351]});
+ref.push({testName: 'precision.normalize.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.normalize.highp_fragment.vec4', input: 'vec4(0.5, 0.5, 0.5, 0.5), (), (), ()', reference: [false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5, false, 0.5, 0.5]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313, false, -0.203125, -0.195313]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951, false, -0.200195, -0.199951]});
+ref.push({testName: 'precision.faceforward.highp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.2, 0.2), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), vec2(0.5, 0.5), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.faceforward.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.reflect.lowp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.164063, 0.203125]});
+ref.push({testName: 'precision.reflect.lowp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0859375, 0.109375]});
+ref.push({testName: 'precision.reflect.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.148438, 0.1875, false, 0.148438, 0.1875]});
+ref.push({testName: 'precision.reflect.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.0078125, 0.015625, false, -0.0078125, 0.015625]});
+ref.push({testName: 'precision.reflect.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.132813, 0.171875, false, 0.132813, 0.171875, false, 0.132813, 0.171875]});
+ref.push({testName: 'precision.reflect.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.117188, -0.078125, false, -0.117188, -0.078125, false, -0.117188, -0.078125]});
+ref.push({testName: 'precision.reflect.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.117188, 0.15625, false, 0.117188, 0.15625, false, 0.117188, 0.15625, false, 0.117188, 0.15625]});
+ref.push({testName: 'precision.reflect.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.210938, -0.171875, false, -0.210938, -0.171875, false, -0.210938, -0.171875, false, -0.210938, -0.171875]});
+ref.push({testName: 'precision.reflect.lowp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.164063, 0.203125]});
+ref.push({testName: 'precision.reflect.lowp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0859375, 0.109375]});
+ref.push({testName: 'precision.reflect.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.148438, 0.1875, false, 0.148438, 0.1875]});
+ref.push({testName: 'precision.reflect.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.0078125, 0.015625, false, -0.0078125, 0.015625]});
+ref.push({testName: 'precision.reflect.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.132813, 0.171875, false, 0.132813, 0.171875, false, 0.132813, 0.171875]});
+ref.push({testName: 'precision.reflect.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.117188, -0.078125, false, -0.117188, -0.078125, false, -0.117188, -0.078125]});
+ref.push({testName: 'precision.reflect.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.117188, 0.15625, false, 0.117188, 0.15625, false, 0.117188, 0.15625, false, 0.117188, 0.15625]});
+ref.push({testName: 'precision.reflect.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.210938, -0.171875, false, -0.210938, -0.171875, false, -0.210938, -0.171875, false, -0.210938, -0.171875]});
+ref.push({testName: 'precision.reflect.mediump_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.183838, 0.184326]});
+ref.push({testName: 'precision.reflect.mediump_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0998535, 0.10022]});
+ref.push({testName: 'precision.reflect.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.167725, 0.168457, false, 0.167725, 0.168457]});
+ref.push({testName: 'precision.reflect.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.reflect.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.151611, 0.152344, false, 0.151611, 0.152344, false, 0.151611, 0.152344]});
+ref.push({testName: 'precision.reflect.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.100342, -0.0996094, false, -0.100342, -0.0996094, false, -0.100342, -0.0996094]});
+ref.push({testName: 'precision.reflect.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.135498, 0.136475, false, 0.135498, 0.136475, false, 0.135498, 0.136475, false, 0.135498, 0.136475]});
+ref.push({testName: 'precision.reflect.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.200439, -0.199219, false, -0.200439, -0.199219, false, -0.200439, -0.199219, false, -0.200439, -0.199219]});
+ref.push({testName: 'precision.reflect.mediump_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.183838, 0.184326]});
+ref.push({testName: 'precision.reflect.mediump_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.0998535, 0.10022]});
+ref.push({testName: 'precision.reflect.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.167725, 0.168457, false, 0.167725, 0.168457]});
+ref.push({testName: 'precision.reflect.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, -0.000244141, 0.000244141, false, -0.000244141, 0.000244141]});
+ref.push({testName: 'precision.reflect.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.151611, 0.152344, false, 0.151611, 0.152344, false, 0.151611, 0.152344]});
+ref.push({testName: 'precision.reflect.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.100342, -0.0996094, false, -0.100342, -0.0996094, false, -0.100342, -0.0996094]});
+ref.push({testName: 'precision.reflect.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.135498, 0.136475, false, 0.135498, 0.136475, false, 0.135498, 0.136475, false, 0.135498, 0.136475]});
+ref.push({testName: 'precision.reflect.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.200439, -0.199219, false, -0.200439, -0.199219, false, -0.200439, -0.199219, false, -0.200439, -0.199219]});
+ref.push({testName: 'precision.reflect.highp_vertex.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.184, 0.184]});
+ref.push({testName: 'precision.reflect.highp_vertex.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.1, 0.1]});
+ref.push({testName: 'precision.reflect.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.168, 0.168, false, 0.168, 0.168]});
+ref.push({testName: 'precision.reflect.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.reflect.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.152, 0.152, false, 0.152, 0.152, false, 0.152, 0.152]});
+ref.push({testName: 'precision.reflect.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.1, -0.1, false, -0.1, -0.1, false, -0.1, -0.1]});
+ref.push({testName: 'precision.reflect.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.136, 0.136, false, 0.136, 0.136, false, 0.136, 0.136, false, 0.136, 0.136]});
+ref.push({testName: 'precision.reflect.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.reflect.highp_fragment.scalar', input: '0.2, 0.2, (), ()', reference: [false, 0.184, 0.184]});
+ref.push({testName: 'precision.reflect.highp_fragment.scalar', input: '0.2, 0.5, (), ()', reference: [false, 0.1, 0.1]});
+ref.push({testName: 'precision.reflect.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.168, 0.168, false, 0.168, 0.168]});
+ref.push({testName: 'precision.reflect.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.reflect.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.152, 0.152, false, 0.152, 0.152, false, 0.152, 0.152]});
+ref.push({testName: 'precision.reflect.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, -0.1, -0.1, false, -0.1, -0.1, false, -0.1, -0.1]});
+ref.push({testName: 'precision.reflect.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.136, 0.136, false, 0.136, 0.136, false, 0.136, 0.136, false, 0.136, 0.136]});
+ref.push({testName: 'precision.reflect.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2, false, -0.2, -0.2]});
+ref.push({testName: 'precision.refract.lowp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.2, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.5, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.2, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.5, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.2, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.5, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.2, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.5, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.2, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.5, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.2, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.lowp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.5, ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.refract.mediump_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.159424, -0.155762]});
+ref.push({testName: 'precision.refract.mediump_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.0787354, -0.0756836]});
+ref.push({testName: 'precision.refract.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.2, ()', reference: [false, -0.161377, -0.157471, false, -0.161377, -0.157471]});
+ref.push({testName: 'precision.refract.mediump_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.5, ()', reference: [false, -0.0828857, -0.079834, false, -0.0828857, -0.079834]});
+ref.push({testName: 'precision.refract.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.162842, -0.158936, false, -0.162842, -0.158936, false, -0.162842, -0.158936]});
+ref.push({testName: 'precision.refract.mediump_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0872803, -0.0842285, false, -0.0872803, -0.0842285, false, -0.0872803, -0.0842285]});
+ref.push({testName: 'precision.refract.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.164551, -0.1604, false, -0.164551, -0.1604, false, -0.164551, -0.1604, false, -0.164551, -0.1604]});
+ref.push({testName: 'precision.refract.mediump_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0914307, -0.0883789, false, -0.0914307, -0.0883789, false, -0.0914307, -0.0883789, false, -0.0914307, -0.0883789]});
+ref.push({testName: 'precision.refract.mediump_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.159424, -0.155762]});
+ref.push({testName: 'precision.refract.mediump_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.0787354, -0.0756836]});
+ref.push({testName: 'precision.refract.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.2, ()', reference: [false, -0.161377, -0.157471, false, -0.161377, -0.157471]});
+ref.push({testName: 'precision.refract.mediump_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.5, ()', reference: [false, -0.0828857, -0.079834, false, -0.0828857, -0.079834]});
+ref.push({testName: 'precision.refract.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.162842, -0.158936, false, -0.162842, -0.158936, false, -0.162842, -0.158936]});
+ref.push({testName: 'precision.refract.mediump_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0872803, -0.0842285, false, -0.0872803, -0.0842285, false, -0.0872803, -0.0842285]});
+ref.push({testName: 'precision.refract.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.164551, -0.1604, false, -0.164551, -0.1604, false, -0.164551, -0.1604, false, -0.164551, -0.1604]});
+ref.push({testName: 'precision.refract.mediump_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0914307, -0.0883789, false, -0.0914307, -0.0883789, false, -0.0914307, -0.0883789, false, -0.0914307, -0.0883789]});
+ref.push({testName: 'precision.refract.highp_vertex.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.157566, -0.157566]});
+ref.push({testName: 'precision.refract.highp_vertex.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.0772513, -0.0772512]});
+ref.push({testName: 'precision.refract.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.2, ()', reference: [false, -0.159185, -0.159185, false, -0.159185, -0.159185]});
+ref.push({testName: 'precision.refract.highp_vertex.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.5, ()', reference: [false, -0.0813898, -0.0813897, false, -0.0813898, -0.0813897]});
+ref.push({testName: 'precision.refract.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.160818, -0.160818, false, -0.160818, -0.160818, false, -0.160818, -0.160818]});
+ref.push({testName: 'precision.refract.highp_vertex.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0856203, -0.0856202, false, -0.0856203, -0.0856202, false, -0.0856203, -0.0856202]});
+ref.push({testName: 'precision.refract.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.162464, -0.162464, false, -0.162464, -0.162464, false, -0.162464, -0.162464, false, -0.162464, -0.162464]});
+ref.push({testName: 'precision.refract.highp_vertex.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0899426, -0.0899425, false, -0.0899426, -0.0899425, false, -0.0899426, -0.0899425, false, -0.0899426, -0.0899425]});
+ref.push({testName: 'precision.refract.highp_fragment.scalar', input: '0.2, 0.2, 0.2, ()', reference: [false, -0.157566, -0.157566]});
+ref.push({testName: 'precision.refract.highp_fragment.scalar', input: '0.2, 0.2, 0.5, ()', reference: [false, -0.0772513, -0.0772512]});
+ref.push({testName: 'precision.refract.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.2, ()', reference: [false, -0.159185, -0.159185, false, -0.159185, -0.159185]});
+ref.push({testName: 'precision.refract.highp_fragment.vec2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), 0.5, ()', reference: [false, -0.0813898, -0.0813897, false, -0.0813898, -0.0813897]});
+ref.push({testName: 'precision.refract.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.160818, -0.160818, false, -0.160818, -0.160818, false, -0.160818, -0.160818]});
+ref.push({testName: 'precision.refract.highp_fragment.vec3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0856203, -0.0856202, false, -0.0856203, -0.0856202, false, -0.0856203, -0.0856202]});
+ref.push({testName: 'precision.refract.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.2, ()', reference: [false, -0.162464, -0.162464, false, -0.162464, -0.162464, false, -0.162464, -0.162464, false, -0.162464, -0.162464]});
+ref.push({testName: 'precision.refract.highp_fragment.vec4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), 0.5, ()', reference: [false, -0.0899426, -0.0899425, false, -0.0899426, -0.0899425, false, -0.0899426, -0.0899425, false, -0.0899426, -0.0899425]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.2, 0), vec2(0, 0.2)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.5, 0), vec2(0, 0.5)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.matrixcompmult.lowp_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.2, 0), vec2(0, 0.2)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.5, 0), vec2(0, 0.5)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), ()', reference: [false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.matrixcompmult.lowp_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), ()', reference: [false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.2, 0), vec2(0, 0.2)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.5, 0), vec2(0, 0.5)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.matrixcompmult.mediump_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.2, 0), vec2(0, 0.2)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.5, 0), vec2(0, 0.5)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), ()', reference: [false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.matrixcompmult.mediump_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), ()', reference: [false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.2, 0), vec2(0, 0.2)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0.04, 0.04]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.5, 0), vec2(0, 0.5)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0.1, 0.1]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04]});
+ref.push({testName: 'precision.matrixcompmult.highp_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.2, 0), vec2(0, 0.2)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0.04, 0.04]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), mat2(vec2(0.5, 0), vec2(0, 0.5)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0.1, 0.1]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat2x3', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat2x4', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat3x2', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat3x4', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat4x2', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat4x3', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), ()', reference: [false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.04, 0.04]});
+ref.push({testName: 'precision.matrixcompmult.highp_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), ()', reference: [false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_vertex.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875, false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.outerproduct.lowp_fragment.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563, false, 0.09375, 0.101563]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_vertex.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001, false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.outerproduct.mediump_fragment.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098, false, 0.0999756, 0.100098]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_vertex.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat2', input: 'vec2(0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat2', input: 'vec2(0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat2x3', input: 'vec3(0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat2x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec2(0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat3x2', input: 'vec2(0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat3', input: 'vec3(0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat3x4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec3(0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat4x2', input: 'vec2(0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat4x3', input: 'vec3(0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.2, 0.2, 0.2, 0.2), (), ()', reference: [false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04, false, 0.04, 0.04]});
+ref.push({testName: 'precision.outerproduct.highp_fragment.mat4', input: 'vec4(0.2, 0.2, 0.2, 0.2), vec4(0.5, 0.5, 0.5, 0.5), (), ()', reference: [false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1, false, 0.1, 0.1]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat2x3', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat2x3', input: 'mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat2x4', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat2x4', input: 'mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat3x2', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat3x2', input: 'mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat3', input: 'mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat3x4', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat3x4', input: 'mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat4x2', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat4x2', input: 'mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat4x3', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat4x3', input: 'mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.transpose.lowp_vertex.mat4', input: 'mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat2x3', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat2x3', input: 'mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat2x4', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat2x4', input: 'mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat3x2', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat3x2', input: 'mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat3', input: 'mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat3x4', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat3x4', input: 'mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat4x2', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat4x2', input: 'mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat4x3', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat4x3', input: 'mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), (), ()', reference: [false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.195313, 0.203125]});
+ref.push({testName: 'precision.transpose.lowp_fragment.mat4', input: 'mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat2x3', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat2x3', input: 'mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat2x4', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat2x4', input: 'mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat3x2', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat3x2', input: 'mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat3', input: 'mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat3x4', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat3x4', input: 'mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat4x2', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat4x2', input: 'mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat4x3', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat4x3', input: 'mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.transpose.mediump_vertex.mat4', input: 'mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat2x3', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat2x3', input: 'mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat2x4', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat2x4', input: 'mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat3x2', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat3x2', input: 'mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat3', input: 'mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat3x4', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat3x4', input: 'mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat4x2', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat4x2', input: 'mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat4x3', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat4x3', input: 'mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), (), ()', reference: [false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.199951, 0.200195]});
+ref.push({testName: 'precision.transpose.mediump_fragment.mat4', input: 'mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0.2, 0.2]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat2x3', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat2x3', input: 'mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat2x4', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat2x4', input: 'mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat3x2', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat3x2', input: 'mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat3', input: 'mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat3x4', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat3x4', input: 'mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat4x2', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat4x2', input: 'mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat4x3', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat4x3', input: 'mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2]});
+ref.push({testName: 'precision.transpose.highp_vertex.mat4', input: 'mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0.2, 0.2]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat2x3', input: 'mat3x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat2x3', input: 'mat3x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat2x4', input: 'mat4x2(vec2(0.2, 0), vec2(0, 0.2), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat2x4', input: 'mat4x2(vec2(0.5, 0), vec2(0, 0.5), vec2(0, 0), vec2(0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat3x2', input: 'mat2x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat3x2', input: 'mat2x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat3', input: 'mat3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat3', input: 'mat3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat3x4', input: 'mat4x3(vec3(0.2, 0, 0), vec3(0, 0.2, 0), vec3(0, 0, 0.2), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat3x4', input: 'mat4x3(vec3(0.5, 0, 0), vec3(0, 0.5, 0), vec3(0, 0, 0.5), vec3(0, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat4x2', input: 'mat2x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat4x2', input: 'mat2x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat4x3', input: 'mat3x4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat4x3', input: 'mat3x4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat4', input: 'mat4(vec4(0.2, 0, 0, 0), vec4(0, 0.2, 0, 0), vec4(0, 0, 0.2, 0), vec4(0, 0, 0, 0.2)), (), (), ()', reference: [false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.2, 0.2]});
+ref.push({testName: 'precision.transpose.highp_fragment.mat4', input: 'mat4(vec4(0.5, 0, 0, 0), vec4(0, 0.5, 0, 0), vec4(0, 0, 0.5, 0), vec4(0, 0, 0, 0.5)), (), (), ()', reference: [false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5, false, 0, 0, false, 0, 0, false, 0, 0, false, 0, 0, false, 0.5, 0.5]});
+ref.push({testName: 'precision.determinant.lowp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.determinant.lowp_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.25, 0.25]});
+ref.push({testName: 'precision.determinant.lowp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.03125, 0.046875]});
+ref.push({testName: 'precision.determinant.lowp_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.25, 0.25]});
+ref.push({testName: 'precision.determinant.mediump_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.determinant.mediump_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.25, 0.25]});
+ref.push({testName: 'precision.determinant.mediump_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.039978, 0.0401001]});
+ref.push({testName: 'precision.determinant.mediump_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.25, 0.25]});
+ref.push({testName: 'precision.determinant.highp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.04, 0.04]});
+ref.push({testName: 'precision.determinant.highp_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.25, 0.25]});
+ref.push({testName: 'precision.determinant.highp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 0.04, 0.04]});
+ref.push({testName: 'precision.determinant.highp_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 0.25, 0.25]});
+ref.push({testName: 'precision.inverse.lowp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.inverse.lowp_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.inverse.lowp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.inverse.lowp_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity, false, -Infinity, Infinity]});
+ref.push({testName: 'precision.inverse.mediump_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 4.96677, 5.02716, false, -5.96046e-007, 5.96046e-007, false, -5.96046e-007, 5.96046e-007, false, 4.96677, 5.02716]});
+ref.push({testName: 'precision.inverse.mediump_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 1.99512, 2.00488, false, -5.96046e-007, 5.96046e-007, false, -5.96046e-007, 5.96046e-007, false, 1.99512, 2.00488]});
+ref.push({testName: 'precision.inverse.mediump_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 4.96677, 5.02716, false, -5.96046e-007, 5.96046e-007, false, -5.96046e-007, 5.96046e-007, false, 4.96677, 5.02716]});
+ref.push({testName: 'precision.inverse.mediump_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 1.99512, 2.00488, false, -5.96046e-007, 5.96046e-007, false, -5.96046e-007, 5.96046e-007, false, 1.99512, 2.00488]});
+ref.push({testName: 'precision.inverse.highp_vertex.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 5, 5, false, -2.8026e-045, 2.8026e-045, false, -2.8026e-045, 2.8026e-045, false, 5, 5]});
+ref.push({testName: 'precision.inverse.highp_vertex.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 2, 2, false, -2.8026e-045, 2.8026e-045, false, -2.8026e-045, 2.8026e-045, false, 2, 2]});
+ref.push({testName: 'precision.inverse.highp_fragment.mat2', input: 'mat2(vec2(0.2, 0), vec2(0, 0.2)), (), (), ()', reference: [false, 5, 5, false, -2.8026e-045, 2.8026e-045, false, -2.8026e-045, 2.8026e-045, false, 5, 5]});
+ref.push({testName: 'precision.inverse.highp_fragment.mat2', input: 'mat2(vec2(0.5, 0), vec2(0, 0.5)), (), (), ()', reference: [false, 2, 2, false, -2.8026e-045, 2.8026e-045, false, -2.8026e-045, 2.8026e-045, false, 2, 2]});
+
+ glsBuiltinPrecisionTestsUnitTests.plainArray = function(input) {
+ var ret = [];
+
+ if (input instanceof tcuInterval.Interval) {
+ var i = 0;
+ ret[i] = input.m_hasNaN;
+ i++;
+ ret[i] = input.m_lo;
+ i++;
+ ret[i] = input.m_hi;
+ return ret;
+ }
+
+ if (input instanceof tcuMatrix.Matrix) {
+ for (var i = 0, l = 0; i < input.cols; i++)
+ for (var j = 0; j < input.rows; j++, l++) {
+ ret[l] = input.matrix[i][j].m_hasNaN;
+ l++;
+ ret[l] = input.matrix[i][j].m_lo;
+ l++;
+ ret[l] = input.matrix[i][j].m_hi;
+ }
+ return ret;
+ }
+
+ if (input instanceof Array) {
+ var size = input.length;
+ for (var i = 0, j = 0; j < size; j++, i++) {
+ ret[i] = input[j].m_hasNaN;
+ i++;
+ ret[i] = input[j].m_lo;
+ i++;
+ ret[i] = input[j].m_hi;
+ }
+ return ret;
+ }
+ return ret;
+ };
+
+ glsBuiltinPrecisionTestsUnitTests.Compare = function(num1, num2, diff) {
+ if (isFinite(num1))
+ if (Math.abs(Math.abs(num1) - Math.abs(num2)) <= diff)
+ return true;
+ else
+ return false;
+ else
+ if (isFinite(num2))
+ return false;
+ else
+ return true;
+ };
+
+ glsBuiltinPrecisionTestsUnitTests.referenceComparison = function(reference, index, precision) {
+ if (index > 1)
+ return true;
+
+ var testName = _currentTestName;
+ var message1 = '';
+ var ref1 = glsBuiltinPrecisionTestsUnitTests.plainArray(reference);
+ var a = ref.length;
+ var len;
+ var ref_len = ref1.length;
+ var cpp_nan;
+ var ref_nan;
+ var ref_lo;
+ var ref_hi;
+ var cpp_lo;
+ var cpp_hi;
+ var str;
+ var retVal1;
+ var retVal2;
+ var varfix = Math.max(0.0001, precision.ulp(0, 2));
+ var error = false;
+
+ for (var i = 0; i < a; i++) {
+ str = ref[i].testName;
+
+ if (testName == str) {
+ len = ref[i].reference.length;
+
+ if (len != ref_len)
+ return false;
+
+ for (var j = 0; j < len; j++) {
+ cpp_nan = ref[i + index].reference[j];
+ ref_nan = ref1[j];
+ j++;
+ cpp_lo = ref[i + index].reference[j];
+ ref_lo = ref1[j];
+ j++;
+ cpp_hi = ref[i + index].reference[j];
+ ref_hi = ref1[j];
+
+ if (ref_nan == cpp_nan) {
+ retVal1 = glsBuiltinPrecisionTestsUnitTests.Compare(ref_lo, cpp_lo, varfix);
+ retVal2 = glsBuiltinPrecisionTestsUnitTests.Compare(ref_hi, ref_hi, varfix);
+
+ if ((retVal1 != true) || (retVal2 != true)) {
+ message1 = 'Error: ' + varfix;
+ bufferedLogToConsole(message1);
+ message1 = 'C++ Reference values: ' + cpp_nan + ', ' + cpp_lo + ', ' + cpp_hi;
+ bufferedLogToConsole(message1);
+ message1 = 'JS values: ' + ref_nan + ', ' + ref_lo + ', ' + ref_hi;
+ bufferedLogToConsole(message1);
+ error = true;
+ }
+ }
+ }
+ if (error)
+ return false;
+ else
+ return true;
+ }
+ }
+ return true;
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsDrawTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsDrawTests.js
new file mode 100644
index 0000000000..eb7a4b2935
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsDrawTests.js
@@ -0,0 +1,3452 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsDrawTests');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluStrUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+ var glsDrawTests = modules.shared.glsDrawTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuTextureUtil = framework.common.tcuTextureUtil;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluStrUtil = framework.opengl.gluStrUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+
+ /** @const {number} */ glsDrawTests.MAX_RENDER_TARGET_SIZE = 512;
+
+ // Utils
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec.Target} target
+ * @return {number}
+ */
+ glsDrawTests.targetToGL = function(target) {
+ assertMsgOptions(target != null, 'Target is null', false, true);
+
+ var targets = [
+ gl.ELEMENT_ARRAY_BUFFER, // TARGET_ELEMENT_ARRAY = 0,
+ gl.ARRAY_BUFFER // TARGET_ARRAY,
+ ];
+
+ return targets[target];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Usage} usage
+ * @return {number}
+ */
+ glsDrawTests.usageToGL = function(usage) {
+ assertMsgOptions(usage != null, 'Usage is null', false, true);
+
+ var usages = [
+ gl.DYNAMIC_DRAW, // USAGE_DYNAMIC_DRAW = 0,
+ gl.STATIC_DRAW, // USAGE_STATIC_DRAW,
+ gl.STREAM_DRAW, // USAGE_STREAM_DRAW,
+
+ gl.STREAM_READ, // USAGE_STREAM_READ,
+ gl.STREAM_COPY, // USAGE_STREAM_COPY,
+
+ gl.STATIC_READ, // USAGE_STATIC_READ,
+ gl.STATIC_COPY, // USAGE_STATIC_COPY,
+
+ gl.DYNAMIC_READ, // USAGE_DYNAMIC_READ,
+ gl.DYNAMIC_COPY // USAGE_DYNAMIC_COPY,
+ ];
+ assertMsgOptions(usages.length == Object.keys(glsDrawTests.DrawTestSpec.Usage).length,
+ 'Amount of usage gl vlaues is different from amount of usages', false, true);
+
+ return usages[usage];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {number}
+ */
+ glsDrawTests.inputTypeToGL = function(type) {
+ assertMsgOptions(type != null, 'Input type is null', false, true);
+
+ var types = [
+ gl.FLOAT, // INPUTTYPE_FLOAT = 0,
+ gl.BYTE, // INPUTTYPE_BYTE,
+ gl.SHORT, // INPUTTYPE_SHORT,
+ gl.UNSIGNED_BYTE, // INPUTTYPE_UNSIGNED_BYTE,
+ gl.UNSIGNED_SHORT, // INPUTTYPE_UNSIGNED_SHORT,
+
+ gl.INT, // INPUTTYPE_INT,
+ gl.UNSIGNED_INT, // INPUTTYPE_UNSIGNED_INT,
+ gl.HALF_FLOAT, // INPUTTYPE_HALF,
+ gl.UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
+ gl.INT_2_10_10_10_REV // INPUTTYPE_INT_2_10_10_10,
+ ];
+ assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
+ 'Amount of gl input types is different from amount of input types', false, true);
+
+ return types[type];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {string}
+ */
+ glsDrawTests.outputTypeToGLType = function(type) {
+ assertMsgOptions(type != null, 'Output type is null', false, true);
+
+ var types = [
+ 'float', // OUTPUTTYPE_FLOAT = 0,
+ 'vec2', // OUTPUTTYPE_VEC2,
+ 'vec3', // OUTPUTTYPE_VEC3,
+ 'vec4', // OUTPUTTYPE_VEC4,
+
+ 'int', // OUTPUTTYPE_INT,
+ 'uint', // OUTPUTTYPE_UINT,
+
+ 'ivec2', // OUTPUTTYPE_IVEC2,
+ 'ivec3', // OUTPUTTYPE_IVEC3,
+ 'ivec4', // OUTPUTTYPE_IVEC4,
+
+ 'uvec2', // OUTPUTTYPE_UVEC2,
+ 'uvec3', // OUTPUTTYPE_UVEC3,
+ 'uvec4' // OUTPUTTYPE_UVEC4,
+ ];
+ assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.OutputType).length,
+ 'Amount of output type names is different than amount of output types', false, true);
+
+ return types[type];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
+ * @return {number}
+ */
+ glsDrawTests.primitiveToGL = function(primitive) {
+ var primitives = [
+ gl.POINTS, // PRIMITIVE_POINTS = 0,
+ gl.TRIANGLES, // PRIMITIVE_TRIANGLES,
+ gl.TRIANGLE_FAN, // PRIMITIVE_TRIANGLE_FAN,
+ gl.TRIANGLE_STRIP, // PRIMITIVE_TRIANGLE_STRIP,
+ gl.LINES, // PRIMITIVE_LINES
+ gl.LINE_STRIP, // PRIMITIVE_LINE_STRIP
+ gl.LINE_LOOP
+ ];
+ assertMsgOptions(primitives.length == Object.keys(glsDrawTests.DrawTestSpec.Primitive).length,
+ 'Amount of gl primitive values is different than amount of primitives', false, true);
+
+ return primitives[primitive];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
+ * @return {number}
+ */
+ glsDrawTests.indexTypeToGL = function(indexType) {
+ var indexTypes = [
+ gl.UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0,
+ gl.UNSIGNED_SHORT, // INDEXTYPE_SHORT,
+ gl.UNSIGNED_INT // INDEXTYPE_INT,
+ ];
+ assertMsgOptions(indexTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
+ 'Amount of gl index types is different than amount of index types', false, true);
+
+ return indexTypes[indexType];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
+ * @return {?glsDrawTests.DrawTestSpec.InputType}
+ */
+ glsDrawTests.indexTypeToInputType = function(indexType) {
+ var inputTypes = [
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0,
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT, // INDEXTYPE_SHORT,
+ glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT // INDEXTYPE_INT,
+ ];
+ assertMsgOptions(inputTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
+ 'Amount of relevant input types is different than amount of index types', false, true);
+
+ return inputTypes[indexType];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {boolean}
+ */
+ glsDrawTests.inputTypeIsFloatType = function(type) {
+ if (type == glsDrawTests.DrawTestSpec.InputType.FLOAT)
+ return true;
+ if (type == glsDrawTests.DrawTestSpec.InputType.HALF)
+ return true;
+ return false;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {boolean}
+ */
+ glsDrawTests.outputTypeIsFloatType = function(type) {
+ if (type == glsDrawTests.DrawTestSpec.OutputType.FLOAT ||
+ type == glsDrawTests.DrawTestSpec.OutputType.VEC2 ||
+ type == glsDrawTests.DrawTestSpec.OutputType.VEC3 ||
+ type == glsDrawTests.DrawTestSpec.OutputType.VEC4)
+ return true;
+
+ return false;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {boolean}
+ */
+ glsDrawTests.outputTypeIsIntType = function(type) {
+ if (type == glsDrawTests.DrawTestSpec.OutputType.INT ||
+ type == glsDrawTests.DrawTestSpec.OutputType.IVEC2 ||
+ type == glsDrawTests.DrawTestSpec.OutputType.IVEC3 ||
+ type == glsDrawTests.DrawTestSpec.OutputType.IVEC4)
+ return true;
+
+ return false;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {boolean}
+ */
+ glsDrawTests.outputTypeIsUintType = function(type) {
+ if (type == glsDrawTests.DrawTestSpec.OutputType.UINT ||
+ type == glsDrawTests.DrawTestSpec.OutputType.UVEC2 ||
+ type == glsDrawTests.DrawTestSpec.OutputType.UVEC3 ||
+ type == glsDrawTests.DrawTestSpec.OutputType.UVEC4)
+ return true;
+
+ return false;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
+ * @param {number} primitiveCount
+ * @return {number}
+ */
+ glsDrawTests.getElementCount = function(primitive, primitiveCount) {
+ switch (primitive) {
+ case glsDrawTests.DrawTestSpec.Primitive.POINTS: return primitiveCount;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: return primitiveCount * 3;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: return primitiveCount + 2;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: return primitiveCount + 2;
+ case glsDrawTests.DrawTestSpec.Primitive.LINES: return primitiveCount * 2;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: return primitiveCount + 1;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: return (primitiveCount == 1) ? (2) : (primitiveCount);
+ default:
+ throw new Error('Invalid primitive');
+ }
+ };
+
+ //MethodInfo
+
+ /**
+ * @typedef {{indexed: boolean, instanced: boolean, ranged: boolean, first: boolean}}
+ */
+ glsDrawTests.MethodInfo = {
+ /** @type {boolean} */ indexed: false,
+ /** @type {boolean} */ instanced: false,
+ /** @type {boolean} */ ranged: false,
+ /** @type {boolean} */ first: false
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method
+ * @return {glsDrawTests.MethodInfo}
+ */
+ glsDrawTests.getMethodInfo = function(method) {
+ /** @type {Array<glsDrawTests.MethodInfo>} */ var infos = [{
+ indexed: false, instanced: false, ranged: false, first: true //!< DRAWMETHOD_DRAWARRAYS,
+ },{
+ indexed: false, instanced: true, ranged: false, first: true //!< DRAWMETHOD_DRAWARRAYS_INSTANCED,
+ },{
+ indexed: true, instanced: false, ranged: false, first: false //!< DRAWMETHOD_DRAWELEMENTS,
+ },{
+ indexed: true, instanced: false, ranged: true, first: false //!< DRAWMETHOD_DRAWELEMENTS_RANGED,
+ },{
+ indexed: true, instanced: true, ranged: false, first: false //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED
+ }
+ ];
+
+ assertMsgOptions(infos.length == Object.keys(glsDrawTests.DrawTestSpec.DrawMethod).length,
+ 'Number of info names', false, true);
+ assertMsgOptions(method < infos.length, 'Invalid method', false, true);
+ return /** @type {glsDrawTests.MethodInfo} */ (infos[method]);
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec} a
+ * @param {glsDrawTests.DrawTestSpec} b
+ * @return {boolean}
+ */
+ glsDrawTests.checkSpecsShaderCompatible = function(a, b) {
+ // Only the attributes matter
+ if (a.attribs.length != b.attribs.length)
+ return false;
+
+ for (var ndx = 0; ndx < a.attribs.length; ++ndx) {
+ // Only the output type (== shader input type) matters and the usage in the shader.
+
+ if (a.attribs[ndx].additionalPositionAttribute != b.attribs[ndx].additionalPositionAttribute)
+ return false;
+
+ // component counts need not to match
+ if (glsDrawTests.outputTypeIsFloatType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsFloatType(b.attribs[ndx].outputType))
+ continue;
+ if (glsDrawTests.outputTypeIsIntType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsIntType(b.attribs[ndx].outputType))
+ continue;
+ if (glsDrawTests.outputTypeIsUintType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsUintType(b.attribs[ndx].outputType))
+ continue;
+
+ return false;
+ }
+
+ return true;
+ };
+
+ // generate random vectors in a way that does not depend on argument evaluation order
+
+ /**
+ * @param {deRandom.Random} random
+ * @return {Array<number>}
+ */
+ glsDrawTests.generateRandomVec4 = function(random) {
+ /** @type {Array<number>} */ var retVal = [];
+
+ for (var i = 0; i < 4; ++i)
+ retVal[i] = random.getFloat();
+
+ return retVal;
+ };
+
+ /**
+ * @param {deRandom.Random} random
+ * @return {Array<number>}
+ */
+ glsDrawTests.generateRandomIVec4 = function(random) {
+ /** @type {Array<number>} */ var retVal = [];
+
+ for (var i = 0; i < 4; ++i)
+ retVal[i] = random.getInt();
+
+ return retVal;
+ };
+
+ /**
+ * @param {deRandom.Random} random
+ * @return {Array<number>}
+ */
+ glsDrawTests.generateRandomUVec4 = function(random) {
+ /** @type {Array<number>} */ var retVal = [];
+
+ for (var i = 0; i < 4; ++i)
+ retVal[i] = Math.abs(random.getInt());
+
+ return retVal;
+ };
+
+ //GLValue
+
+ /**
+ * glsDrawTests.GLValue class
+ * @constructor
+ */
+ glsDrawTests.GLValue = function() {
+ /** @type {goog.NumberArray} */ this.m_value = [0];
+ /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.m_type;
+ };
+
+ /**
+ * @param {goog.TypedArray} dst
+ * @param {glsDrawTests.GLValue} val
+ */
+ glsDrawTests.copyGLValueToArray = function(dst, val) {
+ /** @type {Uint8Array} */ var dst8 = new Uint8Array(dst.buffer).subarray(dst.byteOffset, dst.byteOffset + dst.byteLength);
+ /** @type {Uint8Array} */ var val8 = new Uint8Array(val.m_value.buffer); // TODO: Fix encapsulation issue
+ dst8.set(val8);
+ };
+
+ /**
+ * @param {goog.TypedArray} dst
+ * @param {goog.TypedArray} src
+ */
+ glsDrawTests.copyArray = function(dst, src) {
+ /** @type {Uint8Array} */ var dst8 = new Uint8Array(dst.buffer).subarray(dst.byteOffset, dst.byteOffset + dst.byteLength);
+ /** @type {Uint8Array} */ var src8 = new Uint8Array(src.buffer).subarray(src.byteOffset, src.byteOffset + src.byteLength);
+ dst8.set(src8);
+ };
+
+ /**
+ * typeToTypedArray function. Determines which type of array will store the value, and stores it.
+ * @param {number} value
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ */
+ glsDrawTests.GLValue.typeToTypedArray = function(value, type) {
+ var array;
+
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ array = new Float32Array(1);
+ break;
+
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ array = new Int8Array(1);
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ array = new Int16Array(1);
+ break;
+
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ array = new Uint8Array(1);
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ array = new Uint16Array(1);
+ break;
+
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ array = new Int32Array(1);
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ array = new Uint32Array(1);
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.HALF:
+ array = new Uint16Array(1);
+ value = glsDrawTests.GLValue.floatToHalf(value);
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10:
+ array = new Uint32Array(1);
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10:
+ array = new Int32Array(1);
+ break;
+ default:
+ throw new Error('glsDrawTests.GLValue.typeToTypedArray - Invalid InputType');
+ }
+
+ array[0] = value;
+ return array;
+ };
+
+ /**
+ * glsDrawTests.GLValue.create
+ * @param {number} value
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ */
+ glsDrawTests.GLValue.create = function(value, type) {
+ var v = new glsDrawTests.GLValue();
+ v.m_value = glsDrawTests.GLValue.typeToTypedArray(value, type);
+ v.m_type = type;
+ return v;
+ };
+
+ /**
+ * glsDrawTests.GLValue.halfToFloat
+ * @param {number} value
+ * @return {number}
+ */
+ glsDrawTests.GLValue.halfToFloat = function(value) {
+ return tcuFloat.halfFloatToNumberNoDenorm(value);
+ };
+
+ /**
+ * @param {number} f
+ * @return {number}
+ */
+ glsDrawTests.GLValue.floatToHalf = function(f) {
+ // No denorm support.
+ return tcuFloat.numberToHalfFloatNoDenorm(f);
+ };
+
+ /**
+ * glsDrawTests.GLValue.getMaxValue
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.getMaxValue = function(type) {
+ var value = 0;
+
+ assertMsgOptions(type >= 0 && type < Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
+ 'Invalid type for GLValue', false, true);
+
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ value = 127;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ value = 127;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ value = 32760;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ value = 255;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ value = 65530;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ value = 2147483647;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ value = 4294967295;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.HALF:
+ value = 256;
+ break;
+ default: //For any other valid type, return 0
+ value = 0;
+ }
+
+ return glsDrawTests.GLValue.create(value, type);
+ };
+
+ /**
+ * glsDrawTests.GLValue.getMinValue
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.getMinValue = function(type) {
+ var value = 0;
+
+ assertMsgOptions(type >= 0 && type < Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
+ 'Invalid type for GLValue', false, true);
+
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ value = -127;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ value = -127;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ value = -32760;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ value = 0;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ value = 0;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ value = -2147483647;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ value = 0;
+ break;
+ case glsDrawTests.DrawTestSpec.InputType.HALF:
+ value = -256;
+ break;
+ default: //For any other valid type, return 0
+ value = 0;
+ }
+
+ return glsDrawTests.GLValue.create(value, type);
+ };
+
+ /**
+ * glsDrawTests.GLValue.getRandom
+ * @param {deRandom.Random} rnd
+ * @param {glsDrawTests.GLValue} min
+ * @param {glsDrawTests.GLValue} max
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.getRandom = function(rnd, min, max) {
+ assertMsgOptions(min.getType() == max.getType(), 'Min and max types differ', false, true);
+
+ var minv = min.interpret();
+ var maxv = max.interpret();
+ var type = min.getType();
+ var value;
+
+ if (maxv < minv)
+ return min;
+
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.InputType.HALF: {
+ return glsDrawTests.GLValue.create(minv + rnd.getFloat() * (maxv - minv), type);
+ break;
+ }
+
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: {
+ return glsDrawTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type);
+ break;
+ }
+
+ default:
+ throw new Error('glsDrawTests.GLValue.getRandom - Invalid input type');
+ break;
+ }
+ };
+
+ // Minimum difference required between coordinates
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.minValue = function(type) {
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ case glsDrawTests.DrawTestSpec.InputType.HALF:
+ return glsDrawTests.GLValue.create(4, type);
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ return glsDrawTests.GLValue.create(4 * 256, type);
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ return glsDrawTests.GLValue.create(4 * 2, type);
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ return glsDrawTests.GLValue.create(4 * 16777216, type);
+
+ default:
+ throw new Error('glsDrawTests.GLValue.minValue - Invalid input type');
+ }
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} val
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.abs = function(val) {
+ var type = val.getType();
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ return glsDrawTests.GLValue.create(0x7FFF & val.getValue(), type);
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ return glsDrawTests.GLValue.create(0x7F & val.getValue(), type);
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ return val;
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.InputType.HALF:
+ return glsDrawTests.GLValue.create(Math.abs(val.interpret()), type);
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ return glsDrawTests.GLValue.create(0x7FFFFFFF & val.getValue(), type);
+ default:
+ throw new Error('glsDrawTests.GLValue.abs - Invalid input type');
+ }
+ };
+
+ /**
+ * @return {?glsDrawTests.DrawTestSpec.InputType}
+ */
+ glsDrawTests.GLValue.prototype.getType = function() {
+ return this.m_type;
+ };
+
+ /**
+ * glsDrawTests.GLValue.toFloat
+ * @return {number}
+ */
+ glsDrawTests.GLValue.prototype.toFloat = function() {
+ return this.interpret();
+ };
+
+ /**
+ * glsDrawTests.GLValue.getValue
+ * @return {number}
+ */
+ glsDrawTests.GLValue.prototype.getValue = function() {
+ return this.m_value[0];
+ };
+
+ /**
+ * interpret function. Returns the m_value as a quantity so arithmetic operations can be performed on it
+ * Only some types require this.
+ * @return {number}
+ */
+ glsDrawTests.GLValue.prototype.interpret = function() {
+ if (this.m_type == glsDrawTests.DrawTestSpec.InputType.HALF)
+ return glsDrawTests.GLValue.halfToFloat(this.m_value[0]);
+
+ return this.m_value[0];
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.add = function(other) {
+ return glsDrawTests.GLValue.create(this.interpret() + other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.mul = function(other) {
+ return glsDrawTests.GLValue.create(this.interpret() * other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.div = function(other) {
+ return glsDrawTests.GLValue.create(this.interpret() / other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.sub = function(other) {
+ return glsDrawTests.GLValue.create(this.interpret() - other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.addToSelf = function(other) {
+ this.m_value[0] = this.interpret() + other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.subToSelf = function(other) {
+ this.m_value[0] = this.interpret() - other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.mulToSelf = function(other) {
+ this.m_value[0] = this.interpret() * other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {glsDrawTests.GLValue}
+ */
+ glsDrawTests.GLValue.prototype.divToSelf = function(other) {
+ this.m_value[0] = this.interpret() / other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {boolean}
+ */
+ glsDrawTests.GLValue.prototype.equals = function(other) {
+ return this.m_value[0] == other.getValue();
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {boolean}
+ */
+ glsDrawTests.GLValue.prototype.lessThan = function(other) {
+ return this.interpret() < other.interpret();
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {boolean}
+ */
+ glsDrawTests.GLValue.prototype.greaterThan = function(other) {
+ return this.interpret() > other.interpret();
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {boolean}
+ */
+ glsDrawTests.GLValue.prototype.lessOrEqualThan = function(other) {
+ return this.interpret() <= other.interpret();
+ };
+
+ /**
+ * @param {glsDrawTests.GLValue} other
+ * @return {boolean}
+ */
+ glsDrawTests.GLValue.prototype.greaterOrEqualThan = function(other) {
+ return this.interpret() >= other.interpret();
+ };
+
+ // AttriuteArray
+
+ /**
+ * AttributeArray
+ * @constructor
+ * @param {?glsDrawTests.DrawTestSpec.Storage} storage
+ * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} context
+ */
+ glsDrawTests.AttributeArray = function(storage, context) {
+ /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.m_storage = storage;
+ /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = context;
+ /** @type {WebGLBuffer|sglrReferenceContext.DataBuffer|null} */ this.m_glBuffer;
+
+ /** @type {number} */ this.m_size = 0;
+ /** @type {Uint8Array} */ this.m_data; //NOTE: Used in unsupported user storage
+ /** @type {number} */ this.m_componentCount;
+ /** @type {boolean} */ this.m_bound = false;
+ /** @type {glsDrawTests.DrawTestSpec.Target} */ this.m_target = glsDrawTests.DrawTestSpec.Target.ARRAY;
+ /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.m_inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
+ /** @type {?glsDrawTests.DrawTestSpec.OutputType} */ this.m_outputType = glsDrawTests.DrawTestSpec.OutputType.VEC4;
+ /** @type {boolean} */ this.m_normalize = false;
+ /** @type {number} */ this.m_stride = 0;
+ /** @type {number} */ this.m_offset = 0;
+ /** @type {Array<number>} */ this.m_defaultAttrib;
+ /** @type {number} */ this.m_instanceDivisor = 0;
+ /** @type {boolean} */ this.m_isPositionAttr = false;
+
+ if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ this.m_glBuffer = this.m_ctx.createBuffer();
+ }
+ };
+
+ /** @return {number} */ glsDrawTests.AttributeArray.prototype.getComponentCount = function() {return this.m_componentCount;};
+
+ /** @return {?glsDrawTests.DrawTestSpec.Target} */ glsDrawTests.AttributeArray.prototype.getTarget = function() {return this.m_target;};
+
+ /** @return {?glsDrawTests.DrawTestSpec.InputType} */ glsDrawTests.AttributeArray.prototype.getInputType = function() {return this.m_inputType;};
+
+ /** @return {?glsDrawTests.DrawTestSpec.OutputType} */ glsDrawTests.AttributeArray.prototype.getOutputType = function() {return this.m_outputType;};
+
+ /** @return {?glsDrawTests.DrawTestSpec.Storage} */ glsDrawTests.AttributeArray.prototype.getStorageType = function() {return this.m_storage;};
+
+ /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.getNormalized = function() {return this.m_normalize;};
+
+ /** @return {number} */ glsDrawTests.AttributeArray.prototype.getStride = function() {return this.m_stride;};
+
+ /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.isBound = function() {return this.m_bound;};
+
+ /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.isPositionAttribute = function() {return this.m_isPositionAttr;};
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec.Target} target
+ * @param {number} size
+ * @param {goog.TypedArray} ptr
+ * @param {?glsDrawTests.DrawTestSpec.Usage} usage
+ */
+ glsDrawTests.AttributeArray.prototype.data = function(target, size, ptr, usage) {
+ this.m_size = size;
+ this.m_target = target;
+
+ if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer);
+ this.m_ctx.bufferData(glsDrawTests.targetToGL(target), ptr, glsDrawTests.usageToGL(usage));
+ } else
+ throw new Error('Wrong storage type');
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec.Target} target
+ * @param {number} offset
+ * @param {number} size
+ * @param {goog.TypedArray} ptr
+ */
+ glsDrawTests.AttributeArray.prototype.subdata = function(target, offset, size, ptr) {
+ this.m_target = target;
+
+ if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer);
+
+ this.m_ctx.bufferSubData(glsDrawTests.targetToGL(target), offset, size, ptr);
+ } else
+ throw new Error('Wrong storage type');
+ };
+
+ /**
+ * @param {boolean} bound
+ * @param {number} offset
+ * @param {number} size
+ * @param {?glsDrawTests.DrawTestSpec.InputType} inputType
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} outType
+ * @param {boolean} normalized
+ * @param {number} stride
+ * @param {number} instanceDivisor
+ * @param {Array<number>} defaultAttrib
+ * @param {boolean} isPositionAttr
+ */
+ glsDrawTests.AttributeArray.prototype.setupArray = function(bound, offset, size, inputType, outType,
+ normalized, stride, instanceDivisor, defaultAttrib, isPositionAttr) {
+ this.m_componentCount = size;
+ this.m_bound = bound;
+ this.m_inputType = inputType;
+ this.m_outputType = outType;
+ this.m_normalize = normalized;
+ this.m_stride = stride;
+ this.m_offset = offset;
+ this.m_defaultAttrib = defaultAttrib;
+ this.m_instanceDivisor = instanceDivisor;
+ this.m_isPositionAttr = isPositionAttr;
+ };
+
+ /**
+ * @param {number} loc (32-bit)
+ */
+ glsDrawTests.AttributeArray.prototype.bindAttribute = function(loc) {
+ if (!this.isBound()) {
+ /** @type {Array<number>} */ var attr = this.m_defaultAttrib;
+ switch (this.m_inputType) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT: {
+ switch (this.m_componentCount) {
+ case 1: this.m_ctx.vertexAttrib1f(loc, attr[0]); break;
+ case 2: this.m_ctx.vertexAttrib2f(loc, attr[0], attr[1]); break;
+ case 3: this.m_ctx.vertexAttrib3f(loc, attr[0], attr[1], attr[2]); break;
+ case 4: this.m_ctx.vertexAttrib4f(loc, attr[0], attr[1], attr[2], attr[3]); break;
+ default: throw new Error('Invalid component count'); break;
+ }
+ break;
+ }
+ case glsDrawTests.DrawTestSpec.InputType.INT: {
+ this.m_ctx.vertexAttribI4i(loc, attr[0], attr[1], attr[2], attr[3]);
+ break;
+ }
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: {
+ this.m_ctx.vertexAttribI4ui(loc, attr[0], attr[1], attr[2], attr[3]);
+ break;
+ }
+ default:
+ throw new Error('Invalid input type');
+ break;
+ }
+ } else {
+ /** @type {Uint8Array} */ var basePtr = null;
+
+ if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsDrawTests.targetToGL(this.m_target), this.m_glBuffer);
+
+ basePtr = null;
+ } else
+ throw new Error('Invalid storage type');
+
+ if (!glsDrawTests.inputTypeIsFloatType(this.m_inputType)) {
+ // Input is not float type
+
+ if (glsDrawTests.outputTypeIsFloatType(this.m_outputType)) {
+ var size = this.m_componentCount;
+
+ // Output type is float type
+ this.m_ctx.vertexAttribPointer(loc, size, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset);
+ } else {
+ // Output type is int type
+ this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_stride, this.m_offset);
+ }
+ } else {
+ // Input type is float type
+
+ // Output type must be float type
+ assertMsgOptions(glsDrawTests.outputTypeIsFloatType(this.m_outputType), 'Output type is not float', false, true);
+
+ this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_normalize,
+ this.m_stride, this.m_offset);
+ }
+
+ if (this.m_instanceDivisor)
+ this.m_ctx.vertexAttribDivisor(loc, this.m_instanceDivisor);
+ }
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec.Target} target
+ */
+ glsDrawTests.AttributeArray.prototype.bindIndexArray = function(target) {
+ if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer);
+ }
+ };
+
+ // DrawTestShaderProgram
+
+ /**
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {Array<glsDrawTests.AttributeArray>} arrays
+ */
+ glsDrawTests.DrawTestShaderProgram = function(arrays) {
+ sglrShaderProgram.ShaderProgram.call(this, this.createProgramDeclaration(arrays));
+
+ this.m_componentCount = [];
+ this.m_isCoord = [];
+ this.m_attrType = [];
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
+ this.m_componentCount[arrayNdx] = this.getComponentCount(arrays[arrayNdx].getOutputType());
+ this.m_isCoord[arrayNdx] = arrays[arrayNdx].isPositionAttribute();
+ this.m_attrType[arrayNdx] = this.mapOutputType(arrays[arrayNdx].getOutputType());
+ }
+ };
+
+ glsDrawTests.DrawTestShaderProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ glsDrawTests.DrawTestShaderProgram.prototype.constructor = glsDrawTests.DrawTestShaderProgram;
+
+ /**
+ * @param {Array<number>} color
+ * @param {goog.NumberArray} attribValue
+ * @param {number} numComponents
+ * @return {Array<number>}
+ */
+ glsDrawTests.calcShaderColor = function(color, attribValue, numComponents) {
+ switch (numComponents) {
+ case 1:
+ color[0] = deMath.scale(color, attribValue[0])[0];
+ break;
+
+ case 2:
+ color[0] = color[0] * attribValue[0];
+ color[1] = color[1] * attribValue[1];
+ break;
+
+ case 3:
+ color[0] = color[0] * attribValue[0];
+ color[1] = color[1] * attribValue[1];
+ color[2] = color[2] * attribValue[2];
+ break;
+
+ case 4:
+ color[0] = color[0] * attribValue[0] * attribValue[3];
+ color[1] = color[1] * attribValue[1] * attribValue[3];
+ color[2] = color[2] * attribValue[2] * attribValue[3];
+ break;
+
+ default:
+ throw new Error('Invalid component count');
+ }
+
+ return color;
+ };
+
+ /**
+ * @param {Array<number>} coord
+ * @param {goog.NumberArray} attribValue
+ * @param {number} numComponents
+ * @return {Array<number>}
+ */
+ glsDrawTests.calcShaderCoord = function(coord, attribValue, numComponents) {
+ switch (numComponents) {
+ case 1:
+
+ coord = deMath.add(coord, [attribValue[0], attribValue[0]]);
+ coord[0] = coord[0];
+ coord[1] = coord[1];
+ break;
+ case 2:
+ coord = deMath.add(coord, [attribValue[0], attribValue[1]]);
+ coord[0] = coord[0];
+ coord[1] = coord[1];
+ break;
+ case 3:
+ coord = deMath.add(coord, [attribValue[0] + attribValue[2], attribValue[1]]);
+ coord[0] = coord[0];
+ coord[1] = coord[1];
+ coord[2] = coord[2];
+ break;
+ case 4:
+ coord = deMath.add(coord, [attribValue[0] + attribValue[2], attribValue[1] + attribValue[3]]);
+ coord[0] = coord[0];
+ coord[1] = coord[1];
+ coord[2] = coord[2];
+ coord[3] = coord[3];
+ break;
+
+ default:
+ throw new Error('Invalid component count');
+ }
+
+ return coord;
+ };
+
+ /**
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ var u_coordScale = this.getUniformByName('u_coordScale').value;
+ var u_colorScale = this.getUniformByName('u_colorScale').value;
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ var varyingLocColor = 0;
+
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ // Calc output color
+ /** @type {Array<number>} */ var coord = [0.0, 0.0];
+ /** @type {Array<number>} */ var color = [1.0, 1.0, 1.0];
+
+ for (var attribNdx = 0; attribNdx < this.m_attrType.length; attribNdx++) {
+ var numComponents = this.m_componentCount[attribNdx];
+ /** @type {boolean} */ var isCoord = this.m_isCoord[attribNdx];
+
+ var attrib = rrVertexAttrib.readVertexAttrib(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx, this.m_attrType[attribNdx]);
+
+ if (isCoord) {
+ coord = glsDrawTests.calcShaderCoord(
+ coord,
+ attrib,
+ numComponents
+ );
+ } else {
+ color = glsDrawTests.calcShaderColor(
+ color,
+ attrib,
+ numComponents
+ );
+ }
+ }
+
+ // Transform position
+ packet.position = [u_coordScale * coord[0], u_coordScale * coord[1], 1.0, 1.0];
+ packet.pointSize = 1.0;
+
+ // Pass color to FS
+ packet.outputs[varyingLocColor] = deMath.add(deMath.scale([u_colorScale * color[0], u_colorScale * color[1], u_colorScale * color[2], 1.0], 0.5), [0.5, 0.5, 0.5, 0.5]);
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packets
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.shadeFragments = function(packets, context) {
+ var varyingLocColor = 0;
+
+ for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) {
+ /** @type {rrFragmentOperations.Fragment} */ var packet = packets[packetNdx];
+ packet.value = rrShadingContext.readVarying(packet, context, varyingLocColor);
+ }
+ };
+
+ /**
+ * @param {Array<glsDrawTests.AttributeArray>} arrays
+ * @return {string}
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.genVertexSource = function(arrays) {
+ /** @type {Array<string>}*/ var params;
+ var vertexShaderTmpl = '';
+
+ params = this.generateShaderParams();
+
+ vertexShaderTmpl += params['VTX_HDR'];
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
+ vertexShaderTmpl += params['VTX_IN'] + ' highp ' + glsDrawTests.outputTypeToGLType(arrays[arrayNdx].getOutputType()) + ' a_' + arrayNdx + ';\n';
+ }
+
+ vertexShaderTmpl +=
+ 'uniform highp float u_coordScale;\n' +
+ 'uniform highp float u_colorScale;\n' +
+ params['VTX_OUT'] + ' ' + params['COL_PRECISION'] + ' vec4 v_color;\n' +
+ 'void main(void)\n' +
+ '{\n' +
+ '\tgl_PointSize = 1.0;\n' +
+ '\thighp vec2 coord = vec2(0.0, 0.0);\n' +
+ '\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n';
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
+ var isPositionAttr = arrays[arrayNdx].isPositionAttribute();
+
+ if (isPositionAttr) {
+ switch (arrays[arrayNdx].getOutputType()) {
+ case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.OutputType.INT:
+ case glsDrawTests.DrawTestSpec.OutputType.UINT:
+ vertexShaderTmpl +=
+ '\tcoord += vec2(float(a_' + arrayNdx + '), float(a_' + arrayNdx + '));\n';
+ break;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
+ vertexShaderTmpl +=
+ '\tcoord += vec2(a_' + arrayNdx + '.xy);\n';
+ break;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
+ vertexShaderTmpl +=
+ '\tcoord += vec2(a_' + arrayNdx + '.xy);\n' +
+ '\tcoord.x += float(a_' + arrayNdx + '.z);\n';
+ break;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC4:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
+ vertexShaderTmpl +=
+ '\tcoord += vec2(a_' + arrayNdx + '.xy);\n' +
+ '\tcoord += vec2(a_' + arrayNdx + '.zw);\n';
+ break;
+
+ default:
+ throw new Error('Invalid output type');
+ break;
+ }
+ } else {
+ switch (arrays[arrayNdx].getOutputType()) {
+ case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.OutputType.INT:
+ case glsDrawTests.DrawTestSpec.OutputType.UINT:
+ vertexShaderTmpl +=
+ '\tcolor = color * float(a_' + arrayNdx + ');\n';
+ break;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
+ vertexShaderTmpl +=
+ '\tcolor.rg = color.rg * vec2(a_' + arrayNdx + '.xy);\n';
+ break;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
+ vertexShaderTmpl +=
+ '\tcolor = color.rgb * vec3(a_' + arrayNdx + '.xyz);\n';
+ break;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC4:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
+ vertexShaderTmpl +=
+ '\tcolor = color.rgb * vec3(a_' + arrayNdx + '.xyz) * float(a_' + arrayNdx + '.w);\n';
+ break;
+
+ default:
+ throw new Error('Invalid output type');
+ break;
+ }
+ }
+ }
+
+ vertexShaderTmpl +=
+ '\tv_color = vec4(u_colorScale * color, 1.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);\n' +
+ '\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n' +
+ '}\n';
+
+ return vertexShaderTmpl;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.genFragmentSource = function() {
+ /** @type {Array<string>} */ var params;
+
+ params = this.generateShaderParams();
+
+ var fragmentShaderTmpl = params['FRAG_HDR'] +
+ params['FRAG_IN'] + ' ' + params['COL_PRECISION'] + ' vec4 v_color;\n' +
+ 'void main(void)\n' +
+ '{\n' +
+ '\t' + params['FRAG_COLOR'] + '= v_color;\n' +
+ '}\n';
+
+ return fragmentShaderTmpl;
+ };
+
+ /**
+ * @return {Array<string>}
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.generateShaderParams = function() {
+ /** @type {Array<string>} */ var params = [];
+ if (gluShaderUtil.isGLSLVersionSupported(gl, gluShaderUtil.GLSLVersion.V300_ES)) {
+ params['VTX_IN'] = 'in';
+ params['VTX_OUT'] = 'out';
+ params['FRAG_IN'] = 'in';
+ params['FRAG_COLOR'] = 'dEQP_FragColor';
+ params['VTX_HDR'] = '#version 300 es\n';
+ params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+ params['COL_PRECISION'] = 'mediump';
+ } else if (gluShaderUtil.isGLSLVersionSupported(gl, gluShaderUtil.GLSLVersion.V100_ES)) {
+ params['VTX_IN'] = 'attribute';
+ params['VTX_OUT'] = 'varying';
+ params['FRAG_IN'] = 'varying';
+ params['FRAG_COLOR'] = 'gl_FragColor';
+ params['VTX_HDR'] = '';
+ params['FRAG_HDR'] = '';
+ params['COL_PRECISION'] = 'mediump';
+ } else
+ throw new Error('Invalid GL version');
+
+ return params;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {rrGenericVector.GenericVecType}
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.mapOutputType = function(type) {
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.OutputType.VEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.VEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.VEC4:
+ return rrGenericVector.GenericVecType.FLOAT;
+
+ case glsDrawTests.DrawTestSpec.OutputType.INT:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
+ return rrGenericVector.GenericVecType.INT32;
+
+ case glsDrawTests.DrawTestSpec.OutputType.UINT:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
+ return rrGenericVector.GenericVecType.UINT32;
+
+ default:
+ throw new Error('Invalid output type');
+ }
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {number}
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.getComponentCount = function(type) {
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.OutputType.INT:
+ case glsDrawTests.DrawTestSpec.OutputType.UINT:
+ return 1;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
+ return 2;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
+ return 3;
+
+ case glsDrawTests.DrawTestSpec.OutputType.VEC4:
+ case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
+ case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
+ return 4;
+
+ default:
+ throw new Error('Invalid output type');
+ }
+ };
+
+ /**
+ * @param {Array<glsDrawTests.AttributeArray>} arrays
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ glsDrawTests.DrawTestShaderProgram.prototype.createProgramDeclaration = function(arrays) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++)
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_' + arrayNdx, this.mapOutputType(arrays[arrayNdx].getOutputType())));
+
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(this.genVertexSource(arrays)));
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(this.genFragmentSource()));
+
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_coordScale', gluShaderUtil.DataType.FLOAT));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_colorScale', gluShaderUtil.DataType.FLOAT));
+
+ return decl;
+ };
+
+ /**
+ * @typedef {glsDrawTests.RandomArrayGenerator}
+ */
+ glsDrawTests.RandomArrayGenerator = {};
+
+ /**
+ * @param {goog.TypedArray} data
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @param {deRandom.Random} rnd
+ * @param {glsDrawTests.GLValue} min
+ * @param {glsDrawTests.GLValue} max
+ */
+ glsDrawTests.RandomArrayGenerator.setData = function(data, type, rnd, min, max) {
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ case glsDrawTests.DrawTestSpec.InputType.SHORT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
+ case glsDrawTests.DrawTestSpec.InputType.BYTE:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ case glsDrawTests.DrawTestSpec.InputType.HALF:
+ glsDrawTests.copyGLValueToArray(data, glsDrawTests.GLValue.getRandom(rnd, min, max));
+ break;
+ default:
+ throw new Error('Invalid input type');
+ }
+ };
+
+ /**
+ * createBasicArray
+ * @param {number} seed
+ * @param {number} elementCount
+ * @param {number} componentCount
+ * @param {number} offset
+ * @param {number} stride
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @param {number} first
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
+ * @param {?goog.TypedArray} indices
+ * @param {number} indexSize
+ * @return {goog.TypedArray}
+ */
+ glsDrawTests.RandomArrayGenerator.createArray = function(seed, elementCount, componentCount, offset, stride, type, first, primitive, indices, indexSize) {
+ assertMsgOptions(componentCount >= 1 && componentCount <= 4, 'Unacceptable number of components', false, true);
+
+ /** @type {glsDrawTests.GLValue} */ var min = glsDrawTests.GLValue.getMinValue(type);
+ /** @type {glsDrawTests.GLValue} */ var max = glsDrawTests.GLValue.getMaxValue(type);
+
+ var packed = type == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10 ||
+ type == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10;
+ /** @type {number} */ var limit10 = (1 << 10);
+ /** @type {number} */ var limit2 = (1 << 2);
+
+
+ /** @type {number} */ var componentSize = glsDrawTests.DrawTestSpec.inputTypeSize(type);
+ /** @type {number} */ var elementSize = componentSize * componentCount;
+ /** @type {number} */ var bufferSize = offset + Math.max(elementCount * stride, elementCount * elementSize);
+
+ var data = new ArrayBuffer(bufferSize);
+ var writePtr = new Uint8Array(data, offset);
+
+ var previousComponentsFloat = [0, 0, 0, 0];
+ var rnd = new deRandom.Random(seed);
+
+ for (var vertexNdx = 0; vertexNdx < elementCount; vertexNdx++) {
+ var components = [];
+
+ for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
+ var getRandomComponent = function() {
+ // For packed formats we can't use GLValue
+ if (packed) {
+ if (componentNdx == 3) {
+ return rnd.getInt() % limit2;
+ } else {
+ return rnd.getInt() % limit10;
+ }
+ } else {
+ return glsDrawTests.GLValue.getRandom(rnd, min, max);
+ }
+ };
+
+ var component = getRandomComponent();
+ var componentFloat = (component instanceof glsDrawTests.GLValue) ? component.toFloat() : component;
+
+ // Try to not create vertex near previous
+ if (vertexNdx != 0 && Math.abs(componentFloat - previousComponentsFloat[componentNdx]) < min.toFloat()) {
+ // Too close, try again (but only once)
+ component = getRandomComponent();
+ componentFloat = (component instanceof glsDrawTests.GLValue) ? component.toFloat() : component;
+ }
+
+ components.push(component);
+ previousComponentsFloat[componentNdx] = componentFloat;
+ }
+
+ if (packed) {
+ var packedValue = deMath.binaryOp(
+ deMath.shiftLeft(/** @type {Array<number>} */ (components)[3], 30), deMath.binaryOp(
+ deMath.shiftLeft(/** @type {Array<number>} */ (components)[2], 20), deMath.binaryOp(
+ deMath.shiftLeft(/** @type {Array<number>} */ (components)[1], 10), /** @type {Array<number>} */ (components)[0], deMath.BinaryOp.OR
+ ), deMath.BinaryOp.OR
+ ), deMath.BinaryOp.OR
+ );
+ glsDrawTests.copyArray(writePtr, new Uint32Array([packedValue]));
+ } else {
+ for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
+ glsDrawTests.copyGLValueToArray(writePtr.subarray(componentNdx * componentSize), components[componentNdx]);
+ }
+ }
+
+ writePtr = writePtr.subarray(stride);
+ }
+
+ return new Uint8Array(data);
+ };
+
+ /**
+ * @param {number} seed
+ * @param {number} elementCount
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} type
+ * @param {number} offset
+ * @param {number} min
+ * @param {number} max
+ * @return {goog.TypedArray}
+ */
+ glsDrawTests.RandomArrayGenerator.generateIndices = function(seed, elementCount, type, offset, min, max) {
+ return glsDrawTests.RandomArrayGenerator.createIndices(seed, elementCount, offset, min, max, type);
+ };
+
+ /**
+ * @param {number} seed
+ * @param {number} elementCount
+ * @param {number} offset
+ * @param {number} min
+ * @param {number} max
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} type
+ * @return {goog.TypedArray}
+ */
+ glsDrawTests.RandomArrayGenerator.createIndices = function(seed, elementCount, offset, min, max, type) {
+ /** @type {number}*/ var elementSize = glsDrawTests.DrawTestSpec.indexTypeSize(type);
+ /** @type {number}*/ var bufferSize = offset + elementCount * elementSize;
+
+ var data = new ArrayBuffer(bufferSize);
+ var writePtr = new Uint8Array(data).subarray(offset);
+
+ var rnd = new deRandom.Random(seed);
+
+ /* TODO: get limits for given index type --> if (min < 0 || min > std::numeric_limits<T>::max() ||
+ max < 0 || max > std::numeric_limits<T>::max() ||
+ min > max)
+ DE_ASSERT(!"Invalid range");*/
+
+ // JS refrast requires shuffled unique keys
+ var keys = [];
+ for (var key = 0; key < elementCount; key++)
+ keys.push(glsDrawTests.GLValue.create(key, glsDrawTests.indexTypeToInputType(type)));
+
+ for (var elementNdx = 0; elementNdx < elementCount; ++elementNdx) {
+ var randomkey = rnd.getInt(0, keys.length - 1);
+ var ndx = keys[randomkey];
+
+ keys.splice(randomkey, 1);
+
+ glsDrawTests.copyArray(
+ writePtr.subarray(elementSize * elementNdx),
+ new Uint8Array(ndx.m_value.buffer)
+ );
+ }
+
+ return new Uint8Array(data);
+ };
+
+ /**
+ * @param {number} seed
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {Array<number>}
+ */
+ glsDrawTests.RandomArrayGenerator.generateAttributeValue = function(seed, type) {
+ var random = new deRandom.Random(seed);
+
+ switch (type) {
+ case glsDrawTests.DrawTestSpec.InputType.FLOAT:
+ return glsDrawTests.generateRandomVec4(random);
+
+ case glsDrawTests.DrawTestSpec.InputType.INT:
+ return glsDrawTests.generateRandomIVec4(random);
+
+ case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
+ return glsDrawTests.generateRandomUVec4(random);
+
+ default:
+ throw new Error('Invalid attribute type');
+ }
+ };
+
+ // AttributePack
+
+ /**
+ * @param {sglrReferenceContext.ReferenceContext | sglrGLContext.GLContext} drawContext
+ * @param {Array<number>} screenSize (2 positive elements in array)
+ * @param {boolean} useVao
+ * @param {boolean} logEnabled
+ * @constructor
+ */
+ glsDrawTests.AttributePack = function(drawContext, screenSize, useVao, logEnabled) {
+ /** @type {sglrReferenceContext.ReferenceContext | sglrGLContext.GLContext} */ this.m_ctx = drawContext;
+
+ /** @type {Array<glsDrawTests.AttributeArray>} */ this.m_arrays = [];
+ /** @type {sglrShaderProgram.ShaderProgram} */ this.m_program;
+ /** @type {tcuSurface.Surface} */ this.m_screen = new tcuSurface.Surface(screenSize[0], screenSize[1]);
+ /** @type {boolean} */ this.m_useVao = useVao;
+ /** @type {boolean} */ this.m_logEnabled = logEnabled;
+ /** @type {WebGLProgram | sglrShaderProgram.ShaderProgram | null} */ this.m_programID = null;
+ /** @type {WebGLVertexArrayObject|sglrReferenceContext.VertexArray|null} */ this.m_vaoID = null;
+
+ if (this.m_useVao)
+ this.m_vaoID = this.m_ctx.createVertexArray();
+ };
+
+ /**
+ * @return {tcuSurface.Surface}
+ */
+ glsDrawTests.AttributePack.prototype.getSurface = function() {
+ return this.m_screen;
+ };
+
+ /**
+ * @param {number} i
+ * @return {glsDrawTests.AttributeArray}
+ */
+ glsDrawTests.AttributePack.prototype.getArray = function(i) {
+ return this.m_arrays[i];
+ };
+
+ /**
+ * @return number
+ */
+ glsDrawTests.AttributePack.prototype.getArrayCount = function() {
+ return this.m_arrays.length;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Storage} storage
+ */
+ glsDrawTests.AttributePack.prototype.newArray = function(storage) {
+ this.m_arrays.push(new glsDrawTests.AttributeArray(storage, this.m_ctx));
+ };
+
+ /**
+ * clearArrays
+ */
+ glsDrawTests.AttributePack.prototype.clearArrays = function() {
+ this.m_arrays.length = 0;
+ };
+
+ /**
+ * updateProgram
+ */
+ glsDrawTests.AttributePack.prototype.updateProgram = function() {
+ if (this.m_programID)
+ this.m_ctx.deleteProgram(this.m_programID);
+
+ this.m_program = new glsDrawTests.DrawTestShaderProgram(this.m_arrays);
+ this.m_programID = this.m_ctx.createProgram(this.m_program);
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod
+ * @param {number} firstVertex
+ * @param {number} vertexCount
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
+ * @param {number} indexOffset
+ * @param {number} rangeStart
+ * @param {number} rangeEnd
+ * @param {number} instanceCount
+ * @param {number} coordScale
+ * @param {number} colorScale
+ * @param {glsDrawTests.AttributeArray} indexArray
+ */
+ glsDrawTests.AttributePack.prototype.render = function(primitive, drawMethod, firstVertex, vertexCount, indexType,
+ indexOffset, rangeStart, rangeEnd, instanceCount, coordScale, colorScale, indexArray) {
+ assertMsgOptions(this.m_program != null, 'Program is null', false, true);
+ assertMsgOptions(this.m_programID != null, 'No context created program', false, true);
+
+ this.m_ctx.viewport(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight());
+ this.m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
+ this.m_ctx.clear(gl.COLOR_BUFFER_BIT);
+
+ this.m_ctx.useProgram(this.m_programID);
+
+ this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(this.m_programID, 'u_coordScale'), coordScale);
+ this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(this.m_programID, 'u_colorScale'), colorScale);
+
+ if (this.m_useVao)
+ this.m_ctx.bindVertexArray(this.m_vaoID);
+
+ if (indexArray)
+ indexArray.bindIndexArray(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY);
+
+ for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
+ var attribName = '';
+ attribName += 'a_' + arrayNdx;
+
+ var loc = this.m_ctx.getAttribLocation(this.m_programID, attribName);
+
+ if (this.m_arrays[arrayNdx].isBound())
+ this.m_ctx.enableVertexAttribArray(loc);
+
+ this.m_arrays[arrayNdx].bindAttribute(loc);
+ }
+
+ if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS)
+ this.m_ctx.drawArrays(glsDrawTests.primitiveToGL(primitive), firstVertex, vertexCount);
+ else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED)
+ this.m_ctx.drawArraysInstanced(glsDrawTests.primitiveToGL(primitive), firstVertex, vertexCount, instanceCount);
+ else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS)
+ this.m_ctx.drawElements(glsDrawTests.primitiveToGL(primitive), vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset);
+ else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED)
+ this.m_ctx.drawRangeElements(glsDrawTests.primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset);
+ else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED)
+ this.m_ctx.drawElementsInstanced(glsDrawTests.primitiveToGL(primitive), vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset, instanceCount);
+ else
+ throw new Error('Invalid draw method');
+
+ for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
+ if (this.m_arrays[arrayNdx].isBound()) {
+ var attribName = '';
+ attribName += 'a_' + arrayNdx;
+
+ var loc = this.m_ctx.getAttribLocation(this.m_programID, attribName);
+
+ this.m_ctx.disableVertexAttribArray(loc);
+ }
+ }
+
+ if (this.m_useVao)
+ this.m_ctx.bindVertexArray(null);
+
+ this.m_ctx.useProgram(null);
+ this.m_screen.readViewport(this.m_ctx, [0 , 0, this.m_screen.getWidth(), this.m_screen.getHeight()]);
+ };
+
+ // DrawTestSpec
+
+ /**
+ * @constructor
+ */
+ glsDrawTests.DrawTestSpec = function() {
+ /** @type {?glsDrawTests.DrawTestSpec.Primitive} */ this.primitive = null;
+ /** @type {number} */ this.primitiveCount = 0; //!< number of primitives to draw (per instance)
+
+ /** @type {?glsDrawTests.DrawTestSpec.DrawMethod} */ this.drawMethod = null;
+ /** @type {?glsDrawTests.DrawTestSpec.IndexType} */ this.indexType = null; //!< used only if drawMethod = DrawElements*
+ /** @type {number} */ this.indexPointerOffset = 0; //!< used only if drawMethod = DrawElements*
+ /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.indexStorage = null; //!< used only if drawMethod = DrawElements*
+ /** @type {number} */ this.first = 0; //!< used only if drawMethod = DrawArrays*
+ /** @type {number} */ this.indexMin = 0; //!< used only if drawMethod = Draw*Ranged
+ /** @type {number} */ this.indexMax = 0; //!< used only if drawMethod = Draw*Ranged
+ /** @type {number} */ this.instanceCount = 0; //!< used only if drawMethod = Draw*Instanced or Draw*Indirect
+ /** @type {number} */ this.indirectOffset = 0; //!< used only if drawMethod = Draw*Indirect
+ /** @type {number} */ this.baseVertex = 0; //!< used only if drawMethod = DrawElementsIndirect or *BaseVertex
+
+ /** @type {Array<glsDrawTests.DrawTestSpec.AttributeSpec>} */ this.attribs = [];
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec.Target} target
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.targetToString = function(target) {
+ assertMsgOptions(target != null, 'Target is null', false, true);
+
+ var targets = [
+ 'element_array', // TARGET_ELEMENT_ARRAY = 0,
+ 'array' // TARGET_ARRAY,
+ ];
+ assertMsgOptions(targets.length == Object.keys(glsDrawTests.DrawTestSpec.Target).length,
+ 'The amount of target names is different than the amount of targets', false, true);
+
+ return targets[target];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.inputTypeToString = function(type) {
+ assertMsgOptions(type != null, 'Type is null', false, true);
+
+ var types = [
+ 'float', // INPUTTYPE_FLOAT = 0,
+
+ 'byte', // INPUTTYPE_BYTE,
+ 'short', // INPUTTYPE_SHORT,
+
+ 'unsigned_byte', // INPUTTYPE_UNSIGNED_BYTE,
+ 'unsigned_short', // INPUTTYPE_UNSIGNED_SHORT,
+
+ 'int', // INPUTTYPE_INT,
+ 'unsigned_int', // INPUTTYPE_UNSIGNED_INT,
+ 'half', // INPUTTYPE_HALF,
+ 'unsigned_int2_10_10_10', // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
+ 'int2_10_10_10' // INPUTTYPE_INT_2_10_10_10,
+ ];
+ assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
+ 'The amount of type names is different than the amount of types', false, true);
+
+ return types[type];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} type
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.outputTypeToString = function(type) {
+ assertMsgOptions(type != null, 'Type is null', false, true);
+
+ var types = [
+ 'float', // OUTPUTTYPE_FLOAT = 0,
+ 'vec2', // OUTPUTTYPE_VEC2,
+ 'vec3', // OUTPUTTYPE_VEC3,
+ 'vec4', // OUTPUTTYPE_VEC4,
+
+ 'int', // OUTPUTTYPE_INT,
+ 'uint', // OUTPUTTYPE_UINT,
+
+ 'ivec2', // OUTPUTTYPE_IVEC2,
+ 'ivec3', // OUTPUTTYPE_IVEC3,
+ 'ivec4', // OUTPUTTYPE_IVEC4,
+
+ 'uvec2', // OUTPUTTYPE_UVEC2,
+ 'uvec3', // OUTPUTTYPE_UVEC3,
+ 'uvec4' // OUTPUTTYPE_UVEC4,
+ ];
+ assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.OutputType).length,
+ 'The amount of type names is different than the amount of types', false, true);
+
+ return types[type];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Usage} usage
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.usageTypeToString = function(usage) {
+ assertMsgOptions(usage != null, 'Usage is null', false, true);
+
+ var usages = [
+ 'dynamic_draw', // USAGE_DYNAMIC_DRAW = 0,
+ 'static_draw', // USAGE_STATIC_DRAW,
+ 'stream_draw', // USAGE_STREAM_DRAW,
+
+ 'stream_read', // USAGE_STREAM_READ,
+ 'stream_copy', // USAGE_STREAM_COPY,
+
+ 'static_read', // USAGE_STATIC_READ,
+ 'static_copy', // USAGE_STATIC_COPY,
+
+ 'dynamic_read', // USAGE_DYNAMIC_READ,
+ 'dynamic_copy' // USAGE_DYNAMIC_COPY,
+ ];
+ assertMsgOptions(usages.length == Object.keys(glsDrawTests.DrawTestSpec.Usage).length,
+ 'The amount of usage names is different than the amount of usages', false, true);
+
+ return usages[usage];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Storage} storage
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.storageToString = function(storage) {
+ assertMsgOptions(storage != null, 'Storage is null', false, true);
+
+ var storages = [
+ 'user_ptr', // STORAGE_USER = 0,
+ 'buffer' // STORAGE_BUFFER,
+ ];
+ assertMsgOptions(storages.length == Object.keys(glsDrawTests.DrawTestSpec.Storage).length,
+ 'The amount of storage names is different than the amount of storages', false, true);
+
+ return storages[storage];
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec.Primitive} primitive
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.primitiveToString = function(primitive) {
+ assertMsgOptions(primitive != null, 'Primitive is null', false, true);
+
+ var primitives = [
+ 'points', // PRIMITIVE_POINTS ,
+ 'triangles', // PRIMITIVE_TRIANGLES,
+ 'triangle_fan', // PRIMITIVE_TRIANGLE_FAN,
+ 'triangle_strip', // PRIMITIVE_TRIANGLE_STRIP,
+ 'lines', // PRIMITIVE_LINES
+ 'line_strip', // PRIMITIVE_LINE_STRIP
+ 'line_loop'
+ ];
+ assertMsgOptions(primitives.length == Object.keys(glsDrawTests.DrawTestSpec.Primitive).length,
+ 'The amount of primitive names is different than the amount of primitives', false, true);
+
+ return primitives[primitive];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} type
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.indexTypeToString = function(type) {
+ assertMsgOptions(type != null, 'Index type is null', false, true);
+
+ var indexTypes = [
+ 'byte', // INDEXTYPE_BYTE = 0,
+ 'short', // INDEXTYPE_SHORT,
+ 'int' // INDEXTYPE_INT,
+ ];
+ assertMsgOptions(indexTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
+ 'The amount of index type names is different than the amount of index types', false, true);
+
+ return indexTypes[type];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.drawMethodToString = function(method) {
+ assertMsgOptions(method != null, 'Method is null', false, true);
+
+ var methods = [
+ 'draw_arrays', //!< DRAWMETHOD_DRAWARRAYS
+ 'draw_arrays_instanced', //!< DRAWMETHOD_DRAWARRAYS_INSTANCED
+ 'draw_elements', //!< DRAWMETHOD_DRAWELEMENTS
+ 'draw_range_elements', //!< DRAWMETHOD_DRAWELEMENTS_RANGED
+ 'draw_elements_instanced' //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED
+ ];
+ assertMsgOptions(methods.length == Object.keys(glsDrawTests.DrawTestSpec.DrawMethod).length,
+ 'The amount of method names is different than the amount of methods', false, true);
+
+ return methods[method];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} type
+ * @return {number}
+ */
+ glsDrawTests.DrawTestSpec.inputTypeSize = function(type) {
+ assertMsgOptions(type != null, 'Input type is null', false, true);
+
+ var size = [
+ 4, // INPUTTYPE_FLOAT = 0,
+
+ 1, // INPUTTYPE_BYTE,
+ 2, // INPUTTYPE_SHORT,
+
+ 1, // INPUTTYPE_UNSIGNED_BYTE,
+ 2, // INPUTTYPE_UNSIGNED_SHORT,
+
+ 4, // INPUTTYPE_INT,
+ 4, // INPUTTYPE_UNSIGNED_INT,
+ 2, // INPUTTYPE_HALF,
+ 4 / 4, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
+ 4 / 4 // INPUTTYPE_INT_2_10_10_10,
+ ];
+ assertMsgOptions(size.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
+ 'The amount of type names is different than the amount of types', false, true);
+
+ return size[type];
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.IndexType} type
+ * @return {number}
+ */
+ glsDrawTests.DrawTestSpec.indexTypeSize = function(type) {
+ assertMsgOptions(type != null, 'Type is null', false, true);
+
+ var size = [
+ 1, // INDEXTYPE_BYTE,
+ 2, // INDEXTYPE_SHORT,
+ 4 // INDEXTYPE_INT,
+ ];
+ assertMsgOptions(size.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
+ 'The amount of type names is different than the amount of types', false, true);
+
+ return size[type];
+ };
+
+ /**
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.prototype.getName = function() {
+ /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
+ /** @type {boolean} */ var hasFirst = methodInfo.first;
+ /** @type {boolean} */ var instanced = methodInfo.instanced;
+ /** @type {boolean} */ var ranged = methodInfo.ranged;
+ /** @type {boolean} */ var indexed = methodInfo.indexed;
+
+ var name = '';
+
+ for (var ndx = 0; ndx < this.attribs.length; ++ndx) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec}*/ var attrib = this.attribs[ndx];
+
+ if (this.attribs.length > 1)
+ name += 'attrib' + ndx + '_';
+
+ if (ndx == 0 || attrib.additionalPositionAttribute)
+ name += 'pos_';
+ else
+ name += 'col_';
+
+ if (attrib.useDefaultAttribute) {
+ name += 'non_array_' +
+ glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '_' +
+ attrib.componentCount + '_' +
+ glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '_';
+ } else {
+ name += glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + '_' +
+ attrib.offset + '_' +
+ attrib.stride + '_' +
+ glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType));
+ if (attrib.inputType != glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 && attrib.inputType != glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10)
+ name += attrib.componentCount;
+ name += '_' +
+ (attrib.normalize ? 'normalized_' : '') +
+ glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '_' +
+ glsDrawTests.DrawTestSpec.usageTypeToString(attrib.usage) + '_' +
+ attrib.instanceDivisor + '_';
+ }
+ }
+
+ if (indexed)
+ name += 'index_' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '_' +
+ glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '_' +
+ 'offset' + this.indexPointerOffset + '_';
+ if (hasFirst)
+ name += 'first' + this.first + '_';
+ if (ranged)
+ name += 'ranged_' + this.indexMin + '_' + this.indexMax + '_';
+ if (instanced)
+ name += 'instances' + this.instanceCount + '_';
+
+ switch (this.primitive) {
+ case glsDrawTests.DrawTestSpec.Primitive.POINTS:
+ name += 'points_';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
+ name += 'triangles_';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
+ name += 'triangle_fan_';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
+ name += 'triangle_strip_';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINES:
+ name += 'lines_';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
+ name += 'line_strip_';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
+ name += 'line_loop_';
+ break;
+ default:
+ throw new Error('Invalid primitive');
+ break;
+ }
+
+ name += this.primitiveCount;
+
+ return name;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.prototype.getDesc = function() {
+ var desc = '';
+
+ for (var ndx = 0; ndx < this.attribs.length; ++ndx) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attrib = this.attribs[ndx];
+
+ if (attrib.useDefaultAttribute) {
+ desc += 'Attribute ' + ndx + ': default, ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position ,') : ('color ,')) +
+ 'input datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + ', ' +
+ 'input component count ' + attrib.componentCount + ', ' +
+ 'used as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + ', ';
+ } else {
+ desc += 'Attribute ' + ndx + ': ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position ,') : ('color ,')) +
+ 'Storage in ' + glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + ', ' +
+ 'stride ' + attrib.stride + ', ' +
+ 'input datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + ', ' +
+ 'input component count ' + attrib.componentCount + ', ' +
+ (attrib.normalize ? 'normalized, ' : '') +
+ 'used as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + ', ' +
+ 'instance divisor ' + attrib.instanceDivisor + ', ';
+ }
+ }
+
+ if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) {
+ desc += 'drawArrays(), ' +
+ 'first ' + this.first + ', ';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) {
+ desc += 'drawArraysInstanced(), ' +
+ 'first ' + this.first + ', ' +
+ 'instance count ' + this.instanceCount + ', ';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) {
+ desc += 'drawElements(), ' +
+ 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' +
+ 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' +
+ 'index offset ' + this.indexPointerOffset + ', ';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) {
+ desc += 'drawElementsRanged(), ' +
+ 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' +
+ 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' +
+ 'index offset ' + this.indexPointerOffset + ', ' +
+ 'range start ' + this.indexMin + ', ' +
+ 'range end ' + this.indexMax + ', ';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) {
+ desc += 'drawElementsInstanced(), ' +
+ 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' +
+ 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' +
+ 'index offset ' + this.indexPointerOffset + ', ' +
+ 'instance count ' + this.instanceCount + ', ';
+ } else
+ throw new Error('Invalid draw method');
+
+ desc += this.primitiveCount;
+
+ switch (this.primitive) {
+ case glsDrawTests.DrawTestSpec.Primitive.POINTS:
+ desc += 'points';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
+ desc += 'triangles';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
+ desc += 'triangles (fan)';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
+ desc += 'triangles (strip)';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINES:
+ desc += 'lines';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
+ desc += 'lines (strip)';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
+ desc += 'lines (loop)';
+ break;
+ default:
+ throw new Error('Invalid primitive');
+ break;
+ }
+
+ return desc;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsDrawTests.DrawTestSpec.prototype.getMultilineDesc = function() {
+ var desc = '';
+
+ for (var ndx = 0; ndx < this.attribs.length; ++ndx) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attrib = this.attribs[ndx];
+
+ if (attrib.useDefaultAttribute) {
+ desc += 'Attribute ' + ndx + ': default, ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position\n') : ('color\n')) +
+ '\tinput datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '\n' +
+ '\tinput component count ' + attrib.componentCount + '\n' +
+ '\tused as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '\n';
+ } else {
+ desc += 'Attribute ' + ndx + ': ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position\n') : ('color\n')) +
+ '\tStorage in ' + glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + '\n' +
+ '\tstride ' + attrib.stride + '\n' +
+ '\tinput datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '\n' +
+ '\tinput component count ' + attrib.componentCount + '\n' +
+ (attrib.normalize ? '\tnormalized\n' : '') +
+ '\tused as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '\n' +
+ '\tinstance divisor ' + attrib.instanceDivisor + '\n';
+ }
+ }
+
+ if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) {
+ desc += 'drawArrays()\n' +
+ '\tfirst ' + this.first + '\n';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) {
+ desc += 'drawArraysInstanced()\n' +
+ '\tfirst ' + this.first + '\n' +
+ '\tinstance count ' + this.instanceCount + '\n';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) {
+ desc += 'drawElements()\n' +
+ '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' +
+ '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' +
+ '\tindex offset ' + this.indexPointerOffset + '\n';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) {
+ desc += 'drawElementsRanged()\n' +
+ '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' +
+ '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' +
+ '\tindex offset ' + this.indexPointerOffset + '\n' +
+ '\trange start ' + this.indexMin + '\n' +
+ '\trange end ' + this.indexMax + '\n';
+ } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) {
+ desc += 'drawElementsInstanced()\n' +
+ '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' +
+ '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' +
+ '\tindex offset ' + this.indexPointerOffset + '\n' +
+ '\tinstance count ' + this.instanceCount + '\n';
+ } else
+ throw new Error('Invalid draw method');
+
+ desc += '\t' + this.primitiveCount + ' ';
+
+ switch (this.primitive) {
+ case glsDrawTests.DrawTestSpec.Primitive.POINTS:
+ desc += 'points';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
+ desc += 'triangles';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
+ desc += 'triangles (fan)';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
+ desc += 'triangles (strip)';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINES:
+ desc += 'lines';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
+ desc += 'lines (strip)';
+ break;
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
+ desc += 'lines (loop)';
+ break;
+ default:
+ throw new Error('Invalid primitive');
+ break;
+ }
+
+ desc += '\n';
+
+ return desc;
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.Target = {
+ ELEMENT_ARRAY: 0,
+ ARRAY: 1
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.InputType = {
+ FLOAT: 0,
+
+ BYTE: 1,
+ SHORT: 2,
+
+ UNSIGNED_BYTE: 3,
+ UNSIGNED_SHORT: 4,
+
+ INT: 5,
+ UNSIGNED_INT: 6,
+ HALF: 7,
+ UNSIGNED_INT_2_10_10_10: 8,
+ INT_2_10_10_10: 9
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.OutputType = {
+ FLOAT: 0,
+ VEC2: 1,
+ VEC3: 2,
+ VEC4: 3,
+
+ INT: 4,
+ UINT: 5,
+
+ IVEC2: 6,
+ IVEC3: 7,
+ IVEC4: 8,
+
+ UVEC2: 9,
+ UVEC3: 10,
+ UVEC4: 11
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.Usage = {
+ DYNAMIC_DRAW: 0,
+ STATIC_DRAW: 1,
+ STREAM_DRAW: 2,
+
+ STREAM_READ: 3,
+ STREAM_COPY: 4,
+
+ STATIC_READ: 5,
+ STATIC_COPY: 6,
+
+ DYNAMIC_READ: 7,
+ DYNAMIC_COPY: 8
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.Storage = {
+ USER: 0,
+ BUFFER: 1
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.Primitive = {
+ POINTS: 0,
+ TRIANGLES: 1,
+ TRIANGLE_FAN: 2,
+ TRIANGLE_STRIP: 3,
+ LINES: 4,
+ LINE_STRIP: 5,
+ LINE_LOOP: 6
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.IndexType = {
+ BYTE: 0,
+ SHORT: 1,
+ INT: 2
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.DrawMethod = {
+ DRAWARRAYS: 0,
+ DRAWARRAYS_INSTANCED: 1,
+ DRAWELEMENTS: 2,
+ DRAWELEMENTS_RANGED: 3,
+ DRAWELEMENTS_INSTANCED: 4
+ };
+
+ /**
+ * @enum {number}
+ */
+ glsDrawTests.DrawTestSpec.CompatibilityTestType = {
+ NONE: 0,
+ UNALIGNED_OFFSET: 1,
+ UNALIGNED_STRIDE: 2
+ };
+
+ /**
+ * @return {number}
+ */
+ glsDrawTests.DrawTestSpec.prototype.hash = function() {
+ // Use only drawmode-relevant values in "hashing" as the unrelevant values might not be set (causing non-deterministic behavior).
+ /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
+ /** @type {boolean} */ var arrayed = methodInfo.first;
+ /** @type {boolean} */ var instanced = methodInfo.instanced;
+ /** @type {boolean} */ var ranged = methodInfo.ranged;
+ /** @type {boolean} */ var indexed = methodInfo.indexed;
+
+ /** @type {number} */ var indexHash = (!indexed) ? (0) : (this.indexType + 10 * this.indexPointerOffset + 100 * this.indexStorage);
+ /** @type {number} */ var arrayHash = (!arrayed) ? (0) : (this.first);
+ /** @type {number} */ var indexRangeHash = (!ranged) ? (0) : (this.indexMin + 10 * this.indexMax);
+ /** @type {number} */ var instanceHash = (!instanced) ? (0) : (this.instanceCount);
+ /** @type {number} */ var basicHash = this.primitive + 10 * this.primitiveCount + 100 * this.drawMethod;
+
+ return indexHash + 3 * arrayHash + 5 * indexRangeHash + 7 * instanceHash + 13 * basicHash + 17 * this.attribs.length + 19 * this.primitiveCount;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ glsDrawTests.DrawTestSpec.prototype.valid = function() {
+ assertMsgOptions(this.primitive != null, 'Primitive is null', false, true);
+ assertMsgOptions(this.drawMethod != null, 'Draw method is null', false, true);
+
+ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
+
+ if (methodInfo.ranged) {
+ var maxIndexValue = 0;
+ if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.BYTE)
+ maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE).interpret();
+ else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.SHORT)
+ maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT).interpret();
+ else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.INT)
+ maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT).interpret();
+ else
+ throw new Error('Invalid index type');
+
+ if (this.indexMin > this.indexMax)
+ return false;
+ if (this.indexMin < 0 || this.indexMax < 0)
+ return false;
+ if (this.indexMin > maxIndexValue || this.indexMax > maxIndexValue)
+ return false;
+ }
+
+ if (methodInfo.first && this.first < 0)
+ return false;
+
+ return true;
+ };
+
+ /**
+ * @return {glsDrawTests.DrawTestSpec.CompatibilityTestType}
+ */
+ glsDrawTests.DrawTestSpec.prototype.isCompatibilityTest = function() {
+ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
+
+ var bufferAlignmentBad = false;
+ var strideAlignmentBad = false;
+
+ // Attribute buffer alignment
+ for (var ndx = 0; ndx < this.attribs.length; ++ndx)
+ if (!this.attribs[ndx].isBufferAligned())
+ bufferAlignmentBad = true;
+
+ // Attribute stride alignment
+ for (var ndx = 0; ndx < this.attribs.length; ++ndx)
+ if (!this.attribs[ndx].isBufferStrideAligned())
+ strideAlignmentBad = true;
+
+ // Index buffer alignment
+ if (methodInfo.indexed) {
+ if (this.indexStorage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ var indexSize = 0;
+ if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.BYTE)
+ indexSize = 1;
+ else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.SHORT)
+ indexSize = 2;
+ else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.INT)
+ indexSize = 4;
+ else
+ throw new Error('');
+
+ if (this.indexPointerOffset % indexSize != 0)
+ bufferAlignmentBad = true;
+ }
+ }
+
+ // \note combination bad alignment & stride is treated as bad offset
+ if (bufferAlignmentBad)
+ return glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET;
+ else if (strideAlignmentBad)
+ return glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE;
+ else
+ return glsDrawTests.DrawTestSpec.CompatibilityTestType.NONE;
+ };
+
+ // DrawTestSpec.AttributeSpec
+
+ /**
+ * @constructor
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec = function() {
+ /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.inputType = null;
+ /** @type {?glsDrawTests.DrawTestSpec.OutputType} */ this.outputType = null;
+ /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.storage = glsDrawTests.DrawTestSpec.Storage.BUFFER; //Always BUFFER in WebGL up to 2
+ /** @type {?glsDrawTests.DrawTestSpec.Usage} */ this.usage = null;
+ /** @type {number} */ this.componentCount = 0;
+ /** @type {number} */ this.offset = 0;
+ /** @type {number} */ this.stride = 0;
+ /** @type {boolean} */ this.normalize = false;
+ /** @type {number} */ this.instanceDivisor = 0; //!< used only if drawMethod = Draw*Instanced
+ /** @type {boolean} */ this.useDefaultAttribute = false;
+
+ /** @type {boolean} */ this.additionalPositionAttribute = false; //!< treat this attribute as position attribute. Attribute at index 0 is alway treated as such. False by default
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} inputType
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} outputType
+ * @param {?glsDrawTests.DrawTestSpec.Storage} storage
+ * @param {?glsDrawTests.DrawTestSpec.Usage} usage
+ * @param {number} componentCount
+ * @param {number} offset
+ * @param {number} stride
+ * @param {boolean} normalize
+ * @param {number} instanceDivisor
+ * @return {glsDrawTests.DrawTestSpec.AttributeSpec}
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec.createAttributeArray = function(inputType, outputType, storage, usage, componentCount,
+ offset, stride, normalize, instanceDivisor) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var spec;
+
+ spec.inputType = inputType;
+ spec.outputType = outputType;
+ spec.storage = storage;
+ spec.usage = usage;
+ spec.componentCount = componentCount;
+ spec.offset = offset;
+ spec.stride = stride;
+ spec.normalize = normalize;
+ spec.instanceDivisor = instanceDivisor;
+
+ spec.useDefaultAttribute = false;
+
+ return spec;
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.InputType} inputType
+ * @param {?glsDrawTests.DrawTestSpec.OutputType} outputType
+ * @param {number} componentCount
+ * @return {glsDrawTests.DrawTestSpec.AttributeSpec}
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec.createDefaultAttribute = function(inputType, outputType, componentCount) {
+ assertMsgOptions(inputType == glsDrawTests.DrawTestSpec.InputType.INT || inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT || inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT, 'Invalid input type', false, true);
+ assertMsgOptions(inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT || componentCount == 4, 'If not float, input type should have 4 components', false, true);
+
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var spec;
+
+ spec.inputType = inputType;
+ spec.outputType = outputType;
+ spec.storage = glsDrawTests.DrawTestSpec.Storage.BUFFER; //Always BUFFER in WebGL up to 2
+ spec.usage = null;
+ spec.componentCount = componentCount;
+ spec.offset = 0;
+ spec.stride = 0;
+ spec.normalize = false;
+ spec.instanceDivisor = 0;
+
+ spec.useDefaultAttribute = true;
+
+ return spec;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec.prototype.hash = function() {
+ if (this.useDefaultAttribute) {
+ return 1 * this.inputType + 7 * this.outputType + 13 * this.componentCount;
+ } else {
+ return 1 * this.inputType + 2 * this.outputType + 3 * this.storage + 5 * this.usage + 7 * this.componentCount + 11 * this.offset + 13 * this.stride + 17 * (this.normalize ? 0 : 1) + 19 * this.instanceDivisor;
+ }
+ };
+
+ /**
+ * @return {boolean}
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec.prototype.valid = function(/*ctxType*/) {
+ /** @type {boolean} */ var inputTypeFloat = this.inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT || this.inputType == glsDrawTests.DrawTestSpec.InputType.HALF;
+ /** @type {boolean} */ var inputTypeUnsignedInteger = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10;
+ /** @type {boolean} */ var inputTypeSignedInteger = this.inputType == glsDrawTests.DrawTestSpec.InputType.BYTE || this.inputType == glsDrawTests.DrawTestSpec.InputType.SHORT || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
+ /** @type {boolean} */ var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
+
+ /** @type {boolean} */ var outputTypeFloat = this.outputType == glsDrawTests.DrawTestSpec.OutputType.FLOAT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4;
+ /** @type {boolean} */ var outputTypeSignedInteger = this.outputType == glsDrawTests.DrawTestSpec.OutputType.INT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4;
+ /** @type {boolean} */ var outputTypeUnsignedInteger = this.outputType == glsDrawTests.DrawTestSpec.OutputType.UINT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4;
+
+ if (this.useDefaultAttribute) {
+ if (this.inputType != glsDrawTests.DrawTestSpec.InputType.INT && this.inputType != glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT && this.inputType != glsDrawTests.DrawTestSpec.InputType.FLOAT)
+ return false;
+
+ if (this.inputType != glsDrawTests.DrawTestSpec.InputType.FLOAT && this.componentCount != 4)
+ return false;
+
+ // no casting allowed (undefined results)
+ if (this.inputType == glsDrawTests.DrawTestSpec.InputType.INT && !outputTypeSignedInteger)
+ return false;
+ if (this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT && !outputTypeUnsignedInteger)
+ return false;
+ }
+
+ if (inputTypePacked && this.componentCount != 4)
+ return false;
+
+ // Invalid conversions:
+
+ // float -> [u]int
+ if (inputTypeFloat && !outputTypeFloat)
+ return false;
+
+ // uint -> int (undefined results)
+ if (inputTypeUnsignedInteger && outputTypeSignedInteger)
+ return false;
+
+ // int -> uint (undefined results)
+ if (inputTypeSignedInteger && outputTypeUnsignedInteger)
+ return false;
+
+ // packed -> non-float (packed formats are converted to floats)
+ if (inputTypePacked && !outputTypeFloat)
+ return false;
+
+ // Invalid normalize. Normalize is only valid if output type is float
+ if (this.normalize && !outputTypeFloat)
+ return false;
+
+ return true;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec.prototype.isBufferAligned = function() {
+ var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
+
+ // Buffer alignment, offset is a multiple of underlying data type size?
+ if (this.storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ var dataTypeSize = glsDrawTests.DrawTestSpec.inputTypeSize(this.inputType);
+ if (inputTypePacked)
+ dataTypeSize = 4;
+
+ if (this.offset % dataTypeSize != 0)
+ return false;
+ }
+
+ return true;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ glsDrawTests.DrawTestSpec.AttributeSpec.prototype.isBufferStrideAligned = function() {
+ var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
+
+ // Buffer alignment, offset is a multiple of underlying data type size?
+ if (this.storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
+ var dataTypeSize = glsDrawTests.DrawTestSpec.inputTypeSize(this.inputType);
+ if (inputTypePacked)
+ dataTypeSize = 4;
+
+ if (this.stride % dataTypeSize != 0)
+ return false;
+ }
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {glsDrawTests.DrawTestSpec} spec
+ * @param {string} name
+ * @param {string} desc
+ */
+ glsDrawTests.DrawTest = function(spec, name, desc) {
+ tcuTestCase.DeqpTest.call(this, name, desc, spec);
+
+ /** @type {WebGL2RenderingContext} */ this.m_renderCtx = gl;
+ /** @type {tcuPixelFormat.PixelFormat} */ this.m_pixelformat = new tcuPixelFormat.PixelFormat(
+ /** @type {number} */ (gl.getParameter(gl.RED_BITS)), /** @type {number} */ (gl.getParameter(gl.GREEN_BITS)),
+ /** @type {number} */ (gl.getParameter(gl.BLUE_BITS)), /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS))
+ );
+
+ /** @type {sglrReferenceContext.ReferenceContextBuffers} */ this.m_refBuffers = null;
+ /** @type {sglrReferenceContext.ReferenceContext} */ this.m_refContext = null;
+ /** @type {sglrGLContext.GLContext} */ this.m_glesContext = null;
+
+ /** @type {glsDrawTests.AttributePack} */ this.m_glArrayPack = null;
+ /** @type {glsDrawTests.AttributePack} */ this.m_rrArrayPack = null;
+
+ /** @type {number} */ this.m_maxDiffRed = -1;
+ /** @type {number} */ this.m_maxDiffGreen = -1;
+ /** @type {number} */ this.m_maxDiffBlue = -1;
+
+ /** @type {Array<glsDrawTests.DrawTestSpec>} */ this.m_specs = [];
+ /** @type {Array<string>} */this.m_iteration_descriptions = [];
+ /** @type {number} */ this.m_iteration = 0;
+
+ if (spec)
+ this.addIteration(spec);
+ };
+
+ glsDrawTests.DrawTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsDrawTests.DrawTest.prototype.constructor = glsDrawTests.DrawTest;
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec} spec
+ * @param {string=} description
+ */
+ glsDrawTests.DrawTest.prototype.addIteration = function(spec, description) {
+ // Validate spec
+ /** @type {boolean} */ var validSpec = spec.valid();
+
+ if (!validSpec)
+ return;
+
+ this.m_specs.push(spec);
+
+ if (description)
+ this.m_iteration_descriptions.push(description);
+ else
+ this.m_iteration_descriptions.push('');
+ };
+
+ /**
+ * init
+ */
+ glsDrawTests.DrawTest.prototype.init = function() {
+ var renderTargetWidth = Math.min(glsDrawTests.MAX_RENDER_TARGET_SIZE, gl.canvas.width);
+ var renderTargetHeight = Math.min(glsDrawTests.MAX_RENDER_TARGET_SIZE, gl.canvas.height);
+ /** @type {sglrReferenceContext.ReferenceContextLimits} */ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+ /** @type {boolean} */ var useVao = true;
+
+ this.m_glesContext = new sglrGLContext.GLContext(gl);
+
+ assertMsgOptions(this.m_specs.length > 0, 'Specs is empty', false, true);
+
+ this.m_refBuffers = new sglrReferenceContext.ReferenceContextBuffers(this.m_pixelformat, 0, 0, renderTargetWidth, renderTargetHeight);
+ this.m_refContext = new sglrReferenceContext.ReferenceContext(limits, this.m_refBuffers.getColorbuffer(), this.m_refBuffers.getDepthbuffer(), this.m_refBuffers.getStencilbuffer());
+
+ this.m_glArrayPack = new glsDrawTests.AttributePack(this.m_glesContext, [renderTargetWidth, renderTargetHeight], useVao, true);
+ this.m_rrArrayPack = new glsDrawTests.AttributePack(this.m_refContext, [renderTargetWidth, renderTargetHeight], useVao, false);
+
+ this.m_maxDiffRed = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.redBits)));
+ this.m_maxDiffGreen = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.greenBits)));
+ this.m_maxDiffBlue = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.blueBits)));
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ glsDrawTests.DrawTest.prototype.iterate = function() {
+ var specNdx = Math.floor(this.m_iteration / 2);
+ var drawStep = (this.m_iteration % 2) == 0;
+ var compareStep = (this.m_iteration % 2) == 1;
+ /** @type {tcuTestCase.IterateResult} */ var iterateResult = (this.m_iteration + 1 == this.m_specs.length * 2) ? (tcuTestCase.IterateResult.STOP) : (tcuTestCase.IterateResult.CONTINUE);
+ /** @type {glsDrawTests.DrawTestSpec} */ var spec = this.m_specs[specNdx];
+ var updateProgram = (this.m_iteration == 0) || (drawStep && !glsDrawTests.checkSpecsShaderCompatible(this.m_specs[specNdx], this.m_specs[specNdx - 1])); // try to use the same shader in all iterations
+
+ if (drawStep && this.m_specs.length != 1)
+ debug('Iteration ' + specNdx + ' of ' + (this.m_specs.length - 1) + ': ' + this.m_iteration_descriptions[specNdx]);
+
+ this.m_iteration++;
+
+ if (drawStep) {
+ /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(spec.drawMethod);
+ /** @type {boolean} */ var indexed = methodInfo.indexed;
+ /** @type {boolean} */ var instanced = methodInfo.instanced;
+ /** @type {boolean} */ var ranged = methodInfo.ranged;
+ /** @type {boolean} */ var hasFirst = methodInfo.first;
+
+ /** @type {number} */ var primitiveElementCount = glsDrawTests.getElementCount(spec.primitive, spec.primitiveCount); // !< elements to be drawn
+ /** @type {number} */ var indexMin = (ranged) ? (spec.indexMin) : (0);
+ /** @type {number} */ var firstAddition = (hasFirst) ? (spec.first) : (0);
+ /** @type {number} */ var elementCount = primitiveElementCount + indexMin + firstAddition; // !< elements in buffer (buffer should have at least primitiveElementCount ACCESSIBLE (index range, first) elements)
+ /** @type {number} */ var maxElementIndex = primitiveElementCount + indexMin + firstAddition - 1;
+ /** @type {number} */ var indexMax = Math.max(0, (ranged) ? (deMath.clamp(spec.indexMax, 0, maxElementIndex)) : (maxElementIndex));
+ /** @type {number} */ var coordScale = this.getCoordScale(spec);
+ /** @type {number} */ var colorScale = this.getColorScale(spec);
+
+ /** @type {Array<number>} */ var nullAttribValue = [];
+
+ // Log info
+ bufferedLogToConsole(spec.getMultilineDesc());
+
+ // Data
+ this.m_glArrayPack.clearArrays();
+ this.m_rrArrayPack.clearArrays();
+
+ // indices
+ /** @type {number} */ var seed;
+ /** @type {number} */ var indexElementSize;
+ /** @type {number} */ var indexArraySize;
+ /** @type {goog.TypedArray} */ var indexArray;
+ /** @type {goog.TypedArray} */ var indexPointer;
+
+ /** @type {glsDrawTests.AttributeArray}*/ var glArray;
+ /** @type {glsDrawTests.AttributeArray}*/ var rrArray;
+
+ if (indexed) {
+ seed = spec.hash();
+ indexElementSize = glsDrawTests.DrawTestSpec.indexTypeSize(spec.indexType);
+ indexArraySize = spec.indexPointerOffset + indexElementSize * elementCount;
+ indexArray = glsDrawTests.RandomArrayGenerator.generateIndices(seed, elementCount, spec.indexType, spec.indexPointerOffset, indexMin, indexMax);
+ indexPointer = indexArray.subarray(spec.indexPointerOffset);
+
+ glArray = new glsDrawTests.AttributeArray(spec.indexStorage, this.m_glesContext);
+ rrArray = new glsDrawTests.AttributeArray(spec.indexStorage, this.m_refContext);
+
+ glArray.data(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY, indexArraySize, indexArray, glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW);
+ rrArray.data(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY, indexArraySize, indexArray, glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW);
+
+ indexArray = null;
+ }
+
+ // attributes
+ for (var attribNdx = 0; attribNdx < spec.attribs.length; attribNdx++) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[attribNdx];
+ var isPositionAttr = (attribNdx == 0) || (attribSpec.additionalPositionAttribute);
+
+ if (attribSpec.useDefaultAttribute) {
+ seed = 10 * attribSpec.hash() + 100 * spec.hash() + attribNdx;
+ /** @type {Array<number>} */ var attribValue = glsDrawTests.RandomArrayGenerator.generateAttributeValue(seed, attribSpec.inputType);
+
+ // changed USER for BUFFER in JS version
+ this.m_glArrayPack.newArray(glsDrawTests.DrawTestSpec.Storage.BUFFER);
+ this.m_rrArrayPack.newArray(glsDrawTests.DrawTestSpec.Storage.BUFFER);
+
+ this.m_glArrayPack.getArray(attribNdx).setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr);
+ this.m_rrArrayPack.getArray(attribNdx).setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr);
+ } else {
+ seed = attribSpec.hash() + 100 * spec.hash() + attribNdx;
+ /** @type {number} */ var elementSize = attribSpec.componentCount * glsDrawTests.DrawTestSpec.inputTypeSize(attribSpec.inputType);
+ /** @type {number} */ var stride = (attribSpec.stride == 0) ? (elementSize) : (attribSpec.stride);
+ /** @type {number} */ var evaluatedElementCount = (instanced && attribSpec.instanceDivisor > 0) ? (spec.instanceCount / attribSpec.instanceDivisor + 1) : (elementCount);
+ /** @type {number} */ var referencedElementCount = (ranged) ? (Math.max(evaluatedElementCount, spec.indexMax + 1)) : (evaluatedElementCount);
+ /** @type {number} */ var bufferSize = attribSpec.offset + stride * (referencedElementCount - 1) + elementSize;
+ /** @type {goog.TypedArray} */ var data = glsDrawTests.RandomArrayGenerator.createArray(
+ seed,
+ referencedElementCount,
+ attribSpec.componentCount,
+ attribSpec.offset,
+ stride,
+ attribSpec.inputType,
+ indexed ? 0 : spec.first,
+ spec.primitive,
+ indexed ? indexPointer : null,
+ indexElementSize
+ );
+
+ this.m_glArrayPack.newArray(attribSpec.storage);
+ this.m_rrArrayPack.newArray(attribSpec.storage);
+
+ this.m_glArrayPack.getArray(attribNdx).data(glsDrawTests.DrawTestSpec.Target.ARRAY, bufferSize, data, attribSpec.usage);
+ this.m_rrArrayPack.getArray(attribNdx).data(glsDrawTests.DrawTestSpec.Target.ARRAY, bufferSize, data, attribSpec.usage);
+
+ this.m_glArrayPack.getArray(attribNdx).setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr);
+ this.m_rrArrayPack.getArray(attribNdx).setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr);
+
+ data = null;
+ }
+ }
+
+ // Shader program
+ if (updateProgram) {
+ this.m_glArrayPack.updateProgram();
+ this.m_rrArrayPack.updateProgram();
+ }
+
+ /** @type {glsDrawTests.DrawTestSpec.CompatibilityTestType} */ var ctype;
+
+ // Draw
+ try {
+ // indices
+ if (indexed) {
+ this.m_glArrayPack.render(spec.primitive, spec.drawMethod, 0, primitiveElementCount, spec.indexType, spec.indexPointerOffset, spec.indexMin, spec.indexMax, spec.instanceCount, coordScale, colorScale, glArray);
+ this.m_rrArrayPack.render(spec.primitive, spec.drawMethod, 0, primitiveElementCount, spec.indexType, spec.indexPointerOffset, spec.indexMin, spec.indexMax, spec.instanceCount, coordScale, colorScale, rrArray);
+ } else {
+ this.m_glArrayPack.render(spec.primitive, spec.drawMethod, spec.first, primitiveElementCount, null, 0, 0, 0, spec.instanceCount, coordScale, colorScale, null);
+ this.m_rrArrayPack.render(spec.primitive, spec.drawMethod, spec.first, primitiveElementCount, null, 0, 0, 0, spec.instanceCount, coordScale, colorScale, null);
+ }
+ } catch (err) {
+ if (err instanceof wtu.GLErrorException) {
+ // GL Errors are ok if the mode is not properly aligned
+ ctype = spec.isCompatibilityTest();
+
+ bufferedLogToConsole('Got error: ' + err.message);
+
+ if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET)
+ checkMessage(false, 'Failed to draw with unaligned buffers.');
+ else if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE)
+ checkMessage(false, 'Failed to draw with unaligned stride.');
+ else
+ throw err;
+ }
+ }
+ } else if (compareStep) {
+ if (!this.compare(spec.primitive)) {
+ ctype = spec.isCompatibilityTest();
+
+ if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET)
+ checkMessage(false, 'Failed to draw with unaligned buffers.');
+ else if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE)
+ checkMessage(false, 'Failed to draw with unaligned stride.');
+ else
+ testFailedOptions('Image comparison failed.', false);
+ return iterateResult;
+ }
+ } else {
+ testFailedOptions('Image comparison failed.', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ if (iterateResult == tcuTestCase.IterateResult.STOP)
+ testPassed('');
+
+ return iterateResult;
+ };
+
+ /**
+ * @enum {number} PrimitiveClass
+ */
+ glsDrawTests.PrimitiveClass = {
+ POINT: 0,
+ LINE: 1,
+ TRIANGLE: 2
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitiveType
+ * @return {glsDrawTests.PrimitiveClass}
+ */
+ glsDrawTests.getDrawPrimitiveClass = function(primitiveType) {
+ switch (primitiveType) {
+ case glsDrawTests.DrawTestSpec.Primitive.POINTS:
+ return glsDrawTests.PrimitiveClass.POINT;
+
+ case glsDrawTests.DrawTestSpec.Primitive.LINES:
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
+ case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
+ return glsDrawTests.PrimitiveClass.LINE;
+
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
+ case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
+ return glsDrawTests.PrimitiveClass.TRIANGLE;
+
+ default:
+ throw new Error('Invalid primitive type');
+ }
+ };
+
+ /**
+ * @param {number} c1
+ * @param {number} c2
+ * @param {Array<number>} threshold
+ * @return {boolean}
+ */
+ glsDrawTests.compareUintRGB8 = function(c1, c2, threshold) {
+ return (Math.abs(((c1 >> 16) & 0xff) - ((c2 >> 16) & 0xff)) <= threshold[0] && // Red
+ Math.abs(((c1 >> 8) & 0xff) - ((c2 >> 8) & 0xff)) <= threshold[1] && // Green
+ Math.abs((c1 & 0xff) - (c2 & 0xff)) <= threshold[2]); // Blue
+ };
+
+ /**
+ * @param {number} c1
+ * @param {number} c2
+ * @param {number} c3
+ * @param {number} renderTargetDifference
+ * @return {boolean}
+ */
+ glsDrawTests.isEdgeTripletComponent = function(c1, c2, c3, renderTargetDifference) {
+ /** @type {number} */ var roundingDifference = 2 * renderTargetDifference; // src and dst pixels rounded to different directions
+ /** @type {number} */ var d1 = c2 - c1;
+ /** @type {number} */ var d2 = c3 - c2;
+ /** @type {number} */ var rampDiff = Math.abs(d2 - d1);
+
+ return rampDiff > roundingDifference;
+ };
+
+ /**
+ * @param {tcuRGBA.RGBA} c1
+ * @param {tcuRGBA.RGBA} c2
+ * @param {tcuRGBA.RGBA} c3
+ * @param {Array<number>} renderTargetThreshold
+ * @return {boolean}
+ */
+ glsDrawTests.isEdgeTriplet = function(c1, c2, c3, renderTargetThreshold) {
+ // black (background color) and non-black is always an edge
+ /** @type {boolean} */ var b1 = c1 == 0x000000;
+ /** @type {boolean} */ var b2 = c2 == 0x000000;
+ /** @type {boolean} */ var b3 = c3 == 0x000000;
+
+ // both pixels with coverage and pixels without coverage
+ if ((b1 && b2 && b3) == false && (b1 || b2 || b3) == true)
+ return true;
+ // all black
+ if (b1 && b2 && b3)
+ return false;
+ // all with coverage
+ assertMsgOptions(!b1 && !b2 && !b3, 'All colors with coverage', false, true);
+
+ // Color is always linearly interpolated => component values change nearly linearly
+ // in any constant direction on triangle hull. (df/dx ~= C).
+
+ // Edge detection (this function) is run against the reference image
+ // => no dithering to worry about
+
+ return glsDrawTests.isEdgeTripletComponent((c1 >> 16) && 0xff, (c2 >> 16) && 0xff, (c3 >> 16) && 0xff, renderTargetThreshold[0]) ||
+ glsDrawTests.isEdgeTripletComponent((c1 >> 8) && 0xff, (c2 >> 8) && 0xff, (c3 >> 8) && 0xff, renderTargetThreshold[1]) ||
+ glsDrawTests.isEdgeTripletComponent(c1 && 0xff, c2 && 0xff, c3 && 0xff, renderTargetThreshold[2]);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {tcuSurface.Surface} ref
+ * @param {Array<number>} renderTargetThreshold
+ * @return {boolean}
+ */
+ glsDrawTests.pixelNearEdge = function(x, y, ref, renderTargetThreshold) {
+ // should not be called for edge pixels
+ assertMsgOptions(x >= 1 && x <= ref.getWidth() - 2, 'The pixel was on the edge', false, true);
+ assertMsgOptions(y >= 1 && y <= ref.getHeight() - 2, 'The pixel was on the edge', false, true);
+
+ // horizontal
+
+ /** @type {number} */ var c1;
+ /** @type {number} */ var c2;
+ /** @type {number} */ var c3;
+
+ for (var dy = -1; dy < 2; ++dy) {
+ c1 = ref.getPixelUintRGB8(x - 1, y + dy);
+ c2 = ref.getPixelUintRGB8(x, y + dy);
+ c3 = ref.getPixelUintRGB8(x + 1, y + dy);
+ if (glsDrawTests.isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
+ return true;
+ }
+
+ // vertical
+
+ for (var dx = -1; dx < 2; ++dx) {
+ c1 = ref.getPixelUintRGB8(x + dx, y - 1);
+ c2 = ref.getPixelUintRGB8(x + dx, y);
+ c3 = ref.getPixelUintRGB8(x + dx, y + 1);
+ if (glsDrawTests.isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {number} c
+ * @return {number}
+ */
+ glsDrawTests.getVisualizationGrayscaleColorUintRGB8 = function(c) {
+ // make triangle coverage and error pixels obvious by converting coverage to grayscale
+ if (c == 0x000000)
+ return 0;
+ else
+ return 50 + Math.floor((((c >> 16) & 0xff) + ((c >> 8) & 0xff) + (c & 0xff)) / 8);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {tcuSurface.Surface} target
+ * @return {boolean}
+ */
+ glsDrawTests.pixelNearLineIntersection = function(x, y, target) {
+ // should not be called for edge pixels
+ assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true);
+ assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true);
+
+ var coveredPixels = 0;
+
+ for (var dy = -1; dy < 2; dy++)
+ for (var dx = -1; dx < 2; dx++) {
+ var targetCoverage = target.getPixelUintRGB8(x + dx, y + dy);
+ if (targetCoverage) {
+ ++coveredPixels;
+
+ // A single thin line cannot have more than 3 covered pixels in a 3x3 area
+ if (coveredPixels >= 4)
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ // search 3x3 are for matching color
+ /**
+ * @param {tcuSurface.Surface} target
+ * @param {number} x
+ * @param {number} y
+ * @param {tcuRGBA.RGBA} color
+ * @param {Array<number>} compareThreshold
+ * @return {boolean}
+ */
+ glsDrawTests.pixelNeighborhoodContainsColor = function(target, x, y, color, compareThreshold) {
+ // should not be called for edge pixels
+ assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true);
+ assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true);
+
+ for (var dy = -1; dy < 2; dy++)
+ for (var dx = -1; dx < 2; dx++) {
+ if (glsDrawTests.compareUintRGB8(color, target.getPixelUintRGB8(x + dx, y + dy), compareThreshold))
+ return true;
+ }
+
+ return false;
+ };
+
+ // search 3x3 are for matching coverage (coverage == (color != background color))
+ /**
+ * @param {tcuSurface.Surface} target
+ * @param {number} x
+ * @param {number} y
+ * @param {boolean} coverage
+ * @return {boolean}
+ */
+ glsDrawTests.pixelNeighborhoodContainsCoverage = function(target, x, y, coverage) {
+ // should not be called for edge pixels
+ assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true);
+ assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true);
+
+ for (var dy = -1; dy < 2; dy++)
+ for (var dx = -1; dx < 2; dx++) {
+ var targetCmpCoverage = target.getPixelUintRGB8(x + dx, y + dy) != 0x000000; // Pixel is not black
+ if (targetCmpCoverage == coverage)
+ return true;
+ }
+
+ return false;
+ };
+
+ /**
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @param {Array<number>} compareThreshold
+ * @param {Array<number>} renderTargetThreshold
+ * @param {number} maxAllowedInvalidPixels
+ * @return {boolean}
+ */
+ glsDrawTests.edgeRelaxedImageCompare = function(imageSetName, imageSetDesc, reference, result, compareThreshold, renderTargetThreshold, maxAllowedInvalidPixels) {
+ assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Reference and result images have different dimensions', false, true);
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ /** @type {Array<number>} */ var errorColor = [255, 0, 0, 255];
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+ /** @type {number} */ var numFailingPixels = 0;
+
+ // clear errormask edges which would otherwise be transparent
+
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, width, 1, 1).clear(green);
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, height - 1, 0, width, 1, 1).clear(green);
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, 1, height, 1).clear(green);
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), width - 1, 0, 0, 1, height, 1).clear(green);
+
+ // skip edge pixels since coverage on edge cannot be verified
+
+ for (var y = 1; y < height - 1; ++y)
+ for (var x = 1; x < width - 1; ++x) {
+ /** @type {number} */ var refPixel = reference.getPixelUintRGB8(x, y);
+ /** @type {number} */ var screenPixel = result.getPixelUintRGB8(x, y);
+ /** @type {boolean} */ var isOkReferencePixel = glsDrawTests.pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
+ /** @type {boolean} */ var isOkScreenPixel = glsDrawTests.pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
+
+ if (isOkScreenPixel && isOkReferencePixel) {
+ // pixel valid, write greenish pixels to make the result image easier to read
+ /** @type {number} */ var grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
+ errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
+ } else if (!glsDrawTests.pixelNearEdge(x, y, reference, renderTargetThreshold)) {
+ // non-edge pixel values must be within threshold of the reference values
+ errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
+ ++numFailingPixels;
+ } else {
+ // we are on/near an edge, verify only coverage (coverage == not background colored)
+ /** @type {boolean} */ var referenceCoverage = refPixel != 0x000000; // Not black
+ /** @type {boolean} */ var screenCoverage = screenPixel != 0x000000; // Not black
+ /** @type {boolean} */ var isOkReferenceCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel
+ /** @type {boolean} */ var isOkScreenCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel
+
+ if (isOkScreenCoverage && isOkReferenceCoverage) {
+ // pixel valid, write greenish pixels to make the result image easier to read
+ var grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
+ errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
+ } else {
+ // coverage does not match
+ errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
+ ++numFailingPixels;
+ }
+ }
+ }
+
+ bufferedLogToConsole(
+ 'Comparing images:</br>' +
+ '<span> </span>allowed deviation in pixel positions = 1</br>' +
+ '<span> </span>number of allowed invalid pixels = ' + maxAllowedInvalidPixels + '</br>' +
+ '<span> </span>number of invalid pixels = ' + numFailingPixels
+ );
+
+ if (numFailingPixels > maxAllowedInvalidPixels) {
+ debug('Image comparison failed. Color threshold = (' + compareThreshold[0] + ', ' + compareThreshold[1] + ', ' + compareThreshold[2] + ')');
+ tcuImageCompare.displayImages(result.getAccess(), reference.getAccess(), errorMask.getAccess());
+
+ return false;
+ } else {
+ return true;
+ }
+ };
+
+ /**
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} result
+ * @param {Array<number>} compareThreshold
+ * @param {number} maxAllowedInvalidPixels
+ * @return {boolean}
+ */
+ glsDrawTests.intersectionRelaxedLineImageCompare = function(imageSetName, imageSetDesc, reference, result, compareThreshold, maxAllowedInvalidPixels) {
+ assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Reference and result images have different dimensions', false, true);
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ /** @type {Array<number>} */ var errorColor = [255, 0, 0, 255];
+ var width = reference.getWidth();
+ var height = reference.getHeight();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+ /** @type {number} */ var numFailingPixels = 0;
+
+ // clear errormask edges which would otherwise be transparent
+
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, width, 1, 1).clear(green);
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, height - 1, 0, width, 1, 1).clear(green);
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, 1, height, 1).clear(green);
+ tcuTextureUtil.getSubregion(errorMask.getAccess(), width - 1, 0, 0, 1, height, 1).clear(green);
+
+ // skip edge pixels since coverage on edge cannot be verified
+
+ for (var y = 1; y < height - 1; ++y)
+ for (var x = 1; x < width - 1; ++x) {
+ /** @type {number} */ var refPixel = reference.getPixelUintRGB8(x, y);
+ /** @type {number} */ var screenPixel = result.getPixelUintRGB8(x, y);
+ /** @type {boolean} */ var isOkScreenPixel = glsDrawTests.pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
+ /** @type {boolean} */ var isOkReferencePixel = glsDrawTests.pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
+
+ /** @type {number} */ var grayscaleValue;
+
+ if (isOkScreenPixel && isOkReferencePixel) {
+ // pixel valid, write greenish pixels to make the result image easier to read
+ grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
+ errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
+ } else if (!glsDrawTests.pixelNearLineIntersection(x, y, reference) &&
+ !glsDrawTests.pixelNearLineIntersection(x, y, result)) {
+ // non-intersection pixel values must be within threshold of the reference values
+ errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
+ ++numFailingPixels;
+ } else {
+ // pixel is near a line intersection
+ // we are on/near an edge, verify only coverage (coverage == not background colored)
+ /** @type {boolean} */ var referenceCoverage = refPixel != 0x000000; // Not Black
+ /** @type {boolean} */ var screenCoverage = screenPixel != 0x000000; // Not Black
+ /** @type {boolean} */ var isOkScreenCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel
+ /** @type {boolean} */ var isOkReferenceCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel
+
+ if (isOkScreenCoverage && isOkReferenceCoverage) {
+ // pixel valid, write greenish pixels to make the result image easier to read
+ grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
+ errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
+ } else {
+ // coverage does not match
+ errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
+ ++numFailingPixels;
+ }
+ }
+ }
+
+ bufferedLogToConsole(
+ 'Comparing images:</br>' +
+ '<span> </span>allowed deviation in pixel positions = 1</br>' +
+ '<span> </span>number of allowed invalid pixels = ' + maxAllowedInvalidPixels + '</br>' +
+ '<span> </span>number of invalid pixels = ' + numFailingPixels
+ );
+
+ if (numFailingPixels > maxAllowedInvalidPixels) {
+ debug('Image comparison failed. Color threshold = (' + compareThreshold[0] + ', ' + compareThreshold[1] + ', ' + compareThreshold[2] + ')');
+ tcuImageCompare.displayImages(result.getAccess(), reference.getAccess(), errorMask.getAccess());
+
+ return false;
+ } else {
+ return true;
+ }
+ };
+
+ /**
+ * @param {?glsDrawTests.DrawTestSpec.Primitive} primitiveType
+ * @return {boolean}
+ */
+ glsDrawTests.DrawTest.prototype.compare = function(primitiveType) {
+ /** @type {tcuSurface.Surface} */ var ref = this.m_rrArrayPack.getSurface();
+ /** @type {tcuSurface.Surface} */ var screen = this.m_glArrayPack.getSurface();
+
+ if (/** @type {number} */ (gl.getParameter(gl.SAMPLES)) > 1) {
+ // \todo [mika] Improve compare when using multisampling
+ bufferedLogToConsole('Warning: Comparision of result from multisample render targets are not as strict as without multisampling. Might produce false positives!');
+ return tcuImageCompare.fuzzyCompare('Compare Results', 'Compare Results', ref.getAccess(), screen.getAccess(), 0.3, tcuImageCompare.CompareLogMode.RESULT);
+ } else {
+ /** @type {glsDrawTests.PrimitiveClass} */ var primitiveClass = glsDrawTests.getDrawPrimitiveClass(primitiveType);
+
+ switch (primitiveClass) {
+ case glsDrawTests.PrimitiveClass.POINT: {
+ // Point are extremely unlikely to have overlapping regions, don't allow any no extra / missing pixels
+ /**@type {number} */ var maxAllowedInvalidPixelsWithPoints = 0;
+ return tcuImageCompare.intThresholdPositionDeviationErrorThresholdCompare(
+ 'CompareResult',
+ 'Result of rendering',
+ ref.getAccess(),
+ screen.getAccess(),
+ [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue, 256],
+ [1, 1, 0], //!< 3x3 search kernel
+ true, //!< relax comparison on the image boundary
+ maxAllowedInvalidPixelsWithPoints //!< error threshold
+ );
+ }
+
+ case glsDrawTests.PrimitiveClass.LINE: {
+ // Lines can potentially have a large number of overlapping pixels. Pixel comparison may potentially produce
+ // false negatives in such pixels if for example the pixel in question is overdrawn by another line in the
+ // reference image but not in the resultin image. Relax comparison near line intersection points (areas) and
+ // compare only coverage, not color, in such pixels
+ /**@type {number} */ var maxAllowedInvalidPixelsWithLines = 15; // line are allowed to have a few bad pixels
+ return glsDrawTests.intersectionRelaxedLineImageCompare(
+ 'CompareResult',
+ 'Result of rendering',
+ ref,
+ screen,
+ [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue],
+ maxAllowedInvalidPixelsWithLines
+ );
+ }
+
+ case glsDrawTests.PrimitiveClass.TRIANGLE: {
+ // Triangles are likely to partially or fully overlap. Pixel difference comparison is fragile in pixels
+ // where there could be potential overlapping since the pixels might be covered by one triangle in the
+ // reference image and by the other in the result image. Relax comparsion near primitive edges and
+ // compare only coverage, not color, in such pixels.
+ /** @type {number} */ var maxAllowedInvalidPixelsWithTriangles = 10;
+
+ /* TODO: Implement
+ var renderTargetThreshold = //TODO: get color threshold from the pixel format --> m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().xyz();
+ */
+
+ /** @type {Array<number>} */ var renderTargetThreshold = [3, 3, 3, 3];
+
+ return glsDrawTests.edgeRelaxedImageCompare(
+ 'CompareResult',
+ 'Result of rendering',
+ ref,
+ screen,
+ [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue],
+ renderTargetThreshold,
+ maxAllowedInvalidPixelsWithTriangles
+ );
+ }
+
+ default:
+ throw new Error('Invalid primitive class');
+ }
+ }
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec} spec
+ * @return {number}
+ */
+ glsDrawTests.DrawTest.prototype.getCoordScale = function(spec) {
+ var maxValue = 1.0;
+
+ for (var arrayNdx = 0; arrayNdx < spec.attribs.length; arrayNdx++) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[arrayNdx];
+ /** @type {boolean} */ var isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
+ /** @type {number} */ var attrMaxValue = 0;
+
+ if (!isPositionAttr)
+ continue;
+
+ if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10) {
+ if (attribSpec.normalize)
+ attrMaxValue += 1.0;
+ else
+ attrMaxValue += 1024.0;
+ } else if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) {
+ if (attribSpec.normalize)
+ attrMaxValue += 1.0;
+ else
+ attrMaxValue += 512.0;
+ } else {
+ var max = glsDrawTests.GLValue.getMaxValue(attribSpec.inputType).getValue();
+
+ attrMaxValue += (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType)) ? (1.0) : (max * 1.1);
+ }
+
+ if (attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4 ||
+ attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4 ||
+ attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4)
+ attrMaxValue *= 2;
+
+ maxValue += attrMaxValue;
+ }
+
+ return 1.0 / maxValue;
+ };
+
+ /**
+ * @param {glsDrawTests.DrawTestSpec} spec
+ * @return {number}
+ */
+ glsDrawTests.DrawTest.prototype.getColorScale = function(spec) {
+ var colorScale = 1.0;
+
+ for (var arrayNdx = 1; arrayNdx < spec.attribs.length; arrayNdx++) {
+ /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[arrayNdx];
+ /** @type {boolean} */ var isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
+
+ if (isPositionAttr)
+ continue;
+
+ if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10) {
+ if (!attribSpec.normalize)
+ colorScale *= 1.0 / 1024.0;
+ } else if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) {
+ if (!attribSpec.normalize)
+ colorScale *= 1.0 / 512.0;
+ } else {
+ var max = glsDrawTests.GLValue.getMaxValue(attribSpec.inputType).toFloat();
+
+ colorScale *= (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType) ? 1.0 : (1.0 / max));
+ if (attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4 ||
+ attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4 ||
+ attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4)
+ colorScale *= (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType) ? 1.0 : 1.0 / max);
+ }
+ }
+
+ return colorScale;
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboCompletenessTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboCompletenessTests.js
new file mode 100644
index 0000000000..c0f59c2092
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboCompletenessTests.js
@@ -0,0 +1,961 @@
+'use strict';
+goog.provide('modules.shared.glsFboCompletenessTests');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluObjectWrapper');
+goog.require('framework.opengl.gluStrUtil');
+goog.require('modules.shared.glsFboUtil');
+
+goog.scope(function() {
+
+ var glsFboCompletenessTests = modules.shared.glsFboCompletenessTests;
+ var glsFboUtil = modules.shared.glsFboUtil;
+ var gluObjectWrapper = framework.opengl.gluObjectWrapper;
+ var gluStrUtil = framework.opengl.gluStrUtil;
+ var tcuTestCase = framework.common.tcuTestCase;
+
+ /**
+ * @param {WebGL2RenderingContext} gl
+ */
+ glsFboCompletenessTests.initGlDependents = function(gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ // The following extensions are applicable both to ES2 and ES3.
+ /**
+ * OES_depth_texture
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesDepthTextureFormats = [
+ glsFboUtil.formatkey(gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT),
+ glsFboUtil.formatkey(gl.DEPTH_COMPONENT, gl.UNSIGNED_INT)
+ ];
+
+ /**
+ * OES_packed_depth_stencil
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesPackedDepthStencilSizedFormats = [
+ gl.DEPTH24_STENCIL8
+ ];
+
+ /**
+ * s_oesPackedDepthStencilTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesPackedDepthStencilTexFormats = [
+ glsFboUtil.formatkey(gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8)
+ ];
+
+ /**
+ * OES_required_internalformat
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesRequiredInternalFormatColorFormats = [
+ // Same as ES2 RBO formats, plus RGBA8 (even without OES_rgb8_rgba8)
+ gl.RGB5_A1, gl.RGBA8, gl.RGBA4, gl.RGB565
+ ];
+
+ /**
+ * s_oesRequiredInternalFormatDepthFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesRequiredInternalFormatDepthFormats = [
+ gl.DEPTH_COMPONENT16
+ ];
+
+ /**
+ * EXT_color_buffer_half_float
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extColorBufferHalfFloatFormats = [
+ gl.RGBA16F, gl.RGB16F, gl.RG16F, gl.R16F
+ ];
+
+ /**
+ * s_oesDepth24SizedFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesDepth24SizedFormats = [
+ gl.DEPTH_COMPONENT24
+ ];
+
+ /**
+ * s_oesDepth32SizedFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesDepth32SizedFormats = [
+ gl['DEPTH_COMPONENT32']
+ ];
+
+ /**
+ * s_oesRgb8Rgba8RboFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesRgb8Rgba8RboFormats = [
+ gl.RGB8, gl.RGBA8
+ ];
+
+ /**
+ * s_oesRequiredInternalFormatRgb8ColorFormat
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesRequiredInternalFormatRgb8ColorFormat = [
+ gl.RGB8
+ ];
+
+ /**
+ * s_extTextureType2101010RevFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extTextureType2101010RevFormats = [
+ glsFboUtil.formatkey(gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV),
+ glsFboUtil.formatkey(gl.RGB, gl.UNSIGNED_INT_2_10_10_10_REV)
+ ];
+
+ /**
+ * s_oesRequiredInternalFormat10bitColorFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesRequiredInternalFormat10bitColorFormats = [
+ gl.RGB10_A2, gl['RGB10']
+ ];
+
+ /**
+ * s_extTextureRgRboFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extTextureRgRboFormats = [
+ gl.R8, gl.RG8
+ ];
+
+ /**
+ * s_extTextureRgTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extTextureRgTexFormats = [
+ glsFboUtil.formatkey(gl.RED, gl.UNSIGNED_BYTE),
+ glsFboUtil.formatkey(gl.RG, gl.UNSIGNED_BYTE)
+ ];
+
+ /**
+ * s_extTextureRgFloatTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extTextureRgFloatTexFormats = [
+ glsFboUtil.formatkey(gl.RED, gl.FLOAT),
+ glsFboUtil.formatkey(gl.RG, gl.FLOAT)
+ ];
+
+ /**
+ * s_extTextureRgHalfFloatTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extTextureRgHalfFloatTexFormats = [
+ glsFboUtil.formatkey(gl.RED, gl['HALF_FLOAT_OES']),
+ glsFboUtil.formatkey(gl.RG, gl['HALF_FLOAT_OES'])
+ ];
+
+ /**
+ * s_nvPackedFloatRboFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_nvPackedFloatRboFormats = [
+ gl.R11F_G11F_B10F
+ ];
+
+ /**
+ * s_nvPackedFloatTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_nvPackedFloatTexFormats = [
+ glsFboUtil.formatkey(gl.RGB, gl.UNSIGNED_INT_10F_11F_11F_REV)
+ ];
+
+ /**
+ * s_extSrgbRboFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extSrgbRboFormats = [
+ gl.SRGB8_ALPHA8
+ ];
+
+ /**
+ * s_extSrgbRenderableTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extSrgbRenderableTexFormats = [
+ glsFboUtil.formatkey(gl['SRGB_ALPHA'], gl.UNSIGNED_BYTE)
+ ];
+
+ /**
+ * s_extSrgbNonRenderableTexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_extSrgbNonRenderableTexFormats = [
+ glsFboUtil.formatkey(gl.SRGB, gl.UNSIGNED_BYTE),
+ gl.SRGB8
+ ];
+
+ /**
+ * s_nvSrgbFormatsRboFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_nvSrgbFormatsRboFormats = [
+ gl.SRGB8
+ ];
+
+ /**
+ * s_nvSrgbFormatsTextureFormats
+ * The extension does not actually require any unsized format
+ * to be renderable. However, the renderablility of unsized
+ * SRGB,UBYTE internalformat-type pair is implied.
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_nvSrgbFormatsTextureFormats = [
+ gl.SRGB8,
+ glsFboUtil.formatkey(gl.SRGB, gl.UNSIGNED_BYTE)
+ ];
+
+ /**
+ * s_oesRgb8Rgba8TexFormats
+ * @type {Array<number>}
+ */
+ glsFboCompletenessTests.s_oesRgb8Rgba8TexFormats = [
+ glsFboUtil.formatkey(gl.RGB, gl.UNSIGNED_BYTE),
+ glsFboUtil.formatkey(gl.RGBA, gl.UNSIGNED_BYTE)
+ ];
+
+ var fmt = glsFboUtil.FormatFlags;
+
+ /**
+ * s_esExtFormats
+ * @type {Array<glsFboUtil.FormatExtEntry>}
+ */
+ glsFboCompletenessTests.s_esExtFormats = [
+ new glsFboUtil.FormatExtEntry(
+ 'OES_depth_texture',
+ fmt.REQUIRED_RENDERABLE | fmt.DEPTH_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesDepthTextureFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_packed_depth_stencil',
+ fmt.REQUIRED_RENDERABLE | fmt.DEPTH_RENDERABLE | fmt.STENCIL_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesPackedDepthStencilSizedFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_packed_depth_stencil OES_required_internalformat',
+ fmt.DEPTH_RENDERABLE | fmt.STENCIL_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesPackedDepthStencilTexFormats)
+ ),
+
+ // \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a
+ // requirement on ES3 also. Or is color_buffer_half_float applicatble at
+ // all on ES3, since there's also EXT_color_buffer_float?
+ new glsFboUtil.FormatExtEntry(
+ 'OES_texture_half_float EXT_color_buffer_half_float',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extColorBufferHalfFloatFormats)
+ ),
+
+ // OES_required_internalformat doesn't actually specify that these are renderable,
+ // since it was written against ES 1.1.
+ new glsFboUtil.FormatExtEntry(
+ 'OES_required_internalformat',
+ // Allow but don't require RGBA8 to be color-renderable if
+ // OES_rgb8_rgba8 is not present.
+ fmt.COLOR_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesRequiredInternalFormatColorFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_required_internalformat',
+ fmt.DEPTH_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesRequiredInternalFormatDepthFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_texture_rg',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extTextureRgRboFormats)
+ ),
+
+ // These are not specified to be color-renderable, but the wording is
+ // exactly as ambiguous as the wording in the ES2 spec.
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_texture_rg',
+ fmt.REQUIRED_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extTextureRgTexFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_texture_rg OES_texture_float',
+ fmt.REQUIRED_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extTextureRgFloatTexFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_texture_rg OES_texture_half_float',
+ fmt.REQUIRED_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extTextureRgHalfFloatTexFormats)
+ ),
+
+ // Some Tegra drivers report gl.EXT_packed_float even for ES. Treat it as
+ // a synonym for the NV_ version.
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_packed_float',
+ fmt.REQUIRED_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_nvPackedFloatTexFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_packed_float EXT_color_buffer_half_float',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_nvPackedFloatRboFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_sRGB',
+ fmt.COLOR_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extSrgbRenderableTexFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_sRGB',
+ fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extSrgbNonRenderableTexFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_sRGB',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extSrgbRboFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'NV_sRGB_formats',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_nvSrgbFormatsRboFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'NV_sRGB_formats',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_nvSrgbFormatsTextureFormats)
+ ),
+
+ // In Khronos bug 7333 discussion, the consensus is that these texture
+ // formats, at least, should be color-renderable. Still, that cannot be
+ // found in any extension specs, so only allow it, not require it.
+ new glsFboUtil.FormatExtEntry(
+ 'OES_rgb8_rgba8',
+ fmt.COLOR_RENDERABLE | fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesRgb8Rgba8TexFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_rgb8_rgba8',
+ fmt.REQUIRED_RENDERABLE | fmt.COLOR_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesRgb8Rgba8RboFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_rgb8_rgba8 OES_required_internalformat',
+ fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesRequiredInternalFormatRgb8ColorFormat)
+ ),
+
+ // The depth-renderability of the depth RBO formats is not explicitly
+ // spelled out, but all renderbuffer formats are meant to be renderable.
+ new glsFboUtil.FormatExtEntry(
+ 'OES_depth24',
+ fmt.REQUIRED_RENDERABLE | fmt.DEPTH_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesDepth24SizedFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_depth24 OES_required_internalformat OES_depth_texture',
+ fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesDepth24SizedFormats)
+ ),
+
+ new glsFboUtil.FormatExtEntry(
+ 'OES_depth32',
+ fmt.REQUIRED_RENDERABLE | fmt.DEPTH_RENDERABLE | fmt.RENDERBUFFER_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesDepth32SizedFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'OES_depth32 OES_required_internalformat OES_depth_texture',
+ fmt.TEXTURE_VALID,
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesDepth32SizedFormats)
+ ),
+
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_texture_type_2_10_10_10_REV',
+ fmt.TEXTURE_VALID, // explicitly unrenderable
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_extTextureType2101010RevFormats)
+ ),
+ new glsFboUtil.FormatExtEntry(
+ 'EXT_texture_type_2_10_10_10_REV OES_required_internalformat',
+ fmt.TEXTURE_VALID, // explicitly unrenderable
+ glsFboUtil.rangeArray(glsFboCompletenessTests.s_oesRequiredInternalFormat10bitColorFormats)
+ )
+ ];
+
+ }; // initGlDependents ----------------------------------------
+
+ /**
+ * @constructor
+ * @param {null} testCtx
+ * @param {WebGLRenderingContextBase} renderCtx
+ * @param {glsFboUtil.CheckerFactory} factory
+ */
+ glsFboCompletenessTests.Context = function(testCtx, renderCtx, factory) {
+
+ this.m_testCtx = testCtx;
+ this.m_renderCtx = renderCtx;
+ this.m_ctxFormats = new glsFboUtil.FormatDB();
+ this.m_minFormats = new glsFboUtil.FormatDB();
+ this.m_maxFormats = new glsFboUtil.FormatDB();
+ this.m_verifier = new glsFboUtil.FboVerifier(this.m_ctxFormats, factory);
+ this.m_haveMultiColorAtts = false;
+
+ // FormatExtEntries
+ var extRange = glsFboUtil.rangeArray(glsFboCompletenessTests.s_esExtFormats);
+ this.addExtFormats(extRange);
+
+ };
+
+ // RenderContext&
+ glsFboCompletenessTests.Context.prototype.getRenderContext = function() {
+ return this.m_renderCtx;
+ };
+
+ // TestContext&
+ glsFboCompletenessTests.Context.prototype.getTestContext = function() {
+ return this.m_testCtx;
+ };
+
+ // const FboVerifier&
+ glsFboCompletenessTests.Context.prototype.getVerifier = function() {
+ return this.m_verifier;
+ };
+
+ // const FormatDB&
+ glsFboCompletenessTests.Context.prototype.getMinFormats = function() {
+ return this.m_minFormats;
+ };
+
+ // const FormatDB&
+ glsFboCompletenessTests.Context.prototype.getCtxFormats = function() {
+ return this.m_ctxFormats;
+ };
+
+ // bool
+ glsFboCompletenessTests.Context.prototype.haveMultiColorAtts = function() {
+ return this.m_haveMultiColorAtts;
+ };
+
+ glsFboCompletenessTests.Context.prototype.setHaveMulticolorAtts = function(have) {
+ this.m_haveMultiColorAtts = (have == true);
+ };
+
+ glsFboCompletenessTests.Context.prototype.addFormats = function(fmtRange) {
+ glsFboUtil.addFormats(this.m_minFormats, fmtRange);
+ glsFboUtil.addFormats(this.m_ctxFormats, fmtRange);
+ glsFboUtil.addFormats(this.m_maxFormats, fmtRange);
+ };
+ glsFboCompletenessTests.Context.prototype.addExtFormats = function(extRange) {
+ glsFboUtil.addExtFormats(this.m_ctxFormats, extRange, this.m_renderCtx);
+ glsFboUtil.addExtFormats(this.m_maxFormats, extRange, this.m_renderCtx);
+ };
+
+ glsFboCompletenessTests.Context.prototype.createRenderableTests = function(gl) {
+
+ /** @type {tcuTestCase.DeqpTest} */
+ var renderableTests = tcuTestCase.newTest('renderable', 'Tests for support of renderable image formats');
+ /** @type {tcuTestCase.DeqpTest} */
+ var rbRenderableTests = tcuTestCase.newTest('renderbuffer', 'Tests for renderbuffer formats');
+ /** @type {tcuTestCase.DeqpTest} */
+ var texRenderableTests = tcuTestCase.newTest('texture', 'Tests for texture formats');
+
+ var attPoints = [
+ [gl.DEPTH_ATTACHMENT, 'depth', 'Tests for depth attachments'],
+ [gl.STENCIL_ATTACHMENT, 'stencil', 'Tests for stencil attachments'],
+ [gl.COLOR_ATTACHMENT0, 'color0', 'Tests for color attachments']
+ ];
+
+ // At each attachment point, iterate through all the possible formats to
+ // detect both false positives and false negatives.
+ var rboFmts = this.m_maxFormats.getFormats(glsFboUtil.FormatFlags.ANY_FORMAT);
+ var texFmts = this.m_maxFormats.getFormats(glsFboUtil.FormatFlags.ANY_FORMAT);
+
+ for (var i = 0, l_attPoints = attPoints.length; i < l_attPoints; ++i) {
+ var rbAttTests = tcuTestCase.newTest(attPoints[i][1], attPoints[i][2]);
+ var texAttTests = tcuTestCase.newTest(attPoints[i][1], attPoints[i][2]);
+
+ for (var j = 0, l_rboFmts = rboFmts.length; j < l_rboFmts; ++j) {
+ var params = glsFboCompletenessTests.renderableParams(
+ attPoints[i][0], gl.RENDERBUFFER, rboFmts[j]
+ );
+ rbAttTests.addChild(
+ new glsFboCompletenessTests.RenderableTest(
+ glsFboCompletenessTests.renderableParams.getName(params),
+ glsFboCompletenessTests.renderableParams.getDescription(params),
+ this, params
+ )
+ );
+ }
+ rbRenderableTests.addChild(rbAttTests);
+
+ for (var j = 0, l_texFmts = texFmts.length; j < l_texFmts; ++j) {
+ var params = glsFboCompletenessTests.renderableParams(
+ attPoints[i][0], gl.TEXTURE, texFmts[j]
+ );
+ texAttTests.addChild(
+ new glsFboCompletenessTests.RenderableTest(
+ glsFboCompletenessTests.renderableParams.getName(params),
+ glsFboCompletenessTests.renderableParams.getDescription(params),
+ this, params
+ )
+ );
+ }
+ texRenderableTests.addChild(texAttTests);
+
+ }
+ renderableTests.addChild(rbRenderableTests);
+ renderableTests.addChild(texRenderableTests);
+
+ return renderableTests;
+ };
+
+ glsFboCompletenessTests.Context.prototype.createAttachmentTests = function(gl) {
+
+ var attCombTests = tcuTestCase.newTest('attachment_combinations', 'Tests for attachment combinations');
+
+ var s_bufTypes = [gl.NONE, gl.RENDERBUFFER, gl.TEXTURE];
+ var ls_bufTypes = s_bufTypes.length;
+
+ for (var col0 = 0; col0 < ls_bufTypes; ++col0)
+ for (var coln = 0; coln < ls_bufTypes; ++coln)
+ for (var dep = 0; dep < ls_bufTypes; ++dep)
+ for (var stc = 0; stc < ls_bufTypes; ++stc) {
+ var params = glsFboCompletenessTests.attachmentParams(
+ s_bufTypes[col0], s_bufTypes[coln], s_bufTypes[dep], s_bufTypes[stc]
+ );
+ attCombTests.addChild(new glsFboCompletenessTests.AttachmentTest(
+ glsFboCompletenessTests.attachmentParams.getName(params),
+ glsFboCompletenessTests.attachmentParams.getDescription(params),
+ this, params
+ ));
+ }
+ return attCombTests;
+ };
+
+ glsFboCompletenessTests.Context.prototype.createSizeTests = function(gl) {
+
+ var sizeTests = tcuTestCase.newTest('size', 'Tests for attachment sizes');
+
+ sizeTests.addChild(new glsFboCompletenessTests.EmptyImageTest(
+ 'zero', 'Test for zero-sized image attachment', this
+ ));
+
+ return sizeTests;
+
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} desc
+ * @param {Object} params
+ */
+ glsFboCompletenessTests.TestBase = function(name, desc, params) {
+ tcuTestCase.DeqpTest.call(this, name, desc);
+ this.m_params = params;
+ };
+ glsFboCompletenessTests.TestBase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsFboCompletenessTests.TestBase.prototype.constructor = glsFboCompletenessTests.TestBase;
+
+ glsFboCompletenessTests.TestBase.prototype.getContext = function() {
+ return tcuTestCase.runner;
+ };
+
+ // GLenum attPoint, GLenum bufType
+ /**
+ * @param {number} attPoint
+ * @param {number} bufType
+ * @param {WebGLRenderingContextBase=} gl
+ */
+ glsFboCompletenessTests.TestBase.prototype.getDefaultFormat = function(attPoint, bufType, gl) {
+ gl = gl || window.gl;
+
+ if (bufType == gl.NONE) {
+ return glsFboUtil.ImageFormat.none();
+ }
+
+ // Prefer a standard format, if there is one, but if not, use a format
+ // provided by an extension.
+ var formats = this.m_ctx.getMinFormats().getFormats(
+ glsFboUtil.formatFlag(attPoint, gl) | glsFboUtil.formatFlag(bufType, gl)
+ );
+
+ if (!formats.length) {
+ formats = this.m_ctx.getCtxFormats().getFormats(
+ glsFboUtil.formatFlag(attPoint, gl) | glsFboUtil.formatFlag(bufType, gl)
+ );
+ }
+ if (!formats.length) {
+ throw new Error('Unsupported attachment kind for attachment point');
+ }
+
+ return formats[0];
+
+ };
+
+ /**
+ * @param {number} bufType
+ * @param {glsFboUtil.ImageFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {glsFboUtil.FboBuilder} builder
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {glsFboUtil.Image}
+ */
+ glsFboCompletenessTests.makeImage = function(bufType, format, width, height, builder, gl) {
+ gl = gl || window.gl;
+ var image = 0;
+ switch (bufType) {
+ case gl.NONE:
+ return null;
+ break;
+ case gl.RENDERBUFFER:
+ image = /** @type {glsFboUtil.Renderbuffer}*/(builder.makeConfig(glsFboUtil.Renderbuffer));
+ break;
+ case gl.TEXTURE:
+ image = /** @type {glsFboUtil.Texture2D}*/(builder.makeConfig(glsFboUtil.Texture2D));
+ break;
+ default:
+ throw new Error('Impossible case');
+ }
+ image.internalFormat = format;
+ image.width = width;
+ image.height = height;
+ return image;
+ };
+
+ /**
+ * @param {number} bufType
+ * @param {glsFboUtil.ImageFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {glsFboUtil.FboBuilder} builder
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {glsFboUtil.Attachment}
+ */
+ glsFboCompletenessTests.makeAttachment = function(bufType, format, width, height, builder, gl) {
+ gl = gl || window.gl;
+ var cfg = glsFboCompletenessTests.makeImage(bufType, format, width, height, builder, gl);
+ if (cfg == null) return null;
+
+ /** @type {glsFboUtil.Attachment} */ var att = null;
+ var img = 0;
+
+ var mask = glsFboUtil.Config.s_types.RENDERBUFFER | glsFboUtil.Config.s_types.TEXTURE_2D;
+
+ switch (cfg.type & mask) {
+ case glsFboUtil.Config.s_types.RENDERBUFFER:
+ img = builder.glCreateRbo(/** @type {glsFboUtil.Renderbuffer} */(cfg));
+ att = /** @type {glsFboUtil.RenderbufferAttachment} */ (builder.makeConfig(glsFboUtil.RenderbufferAttachment));
+ break;
+ case glsFboUtil.Config.s_types.TEXTURE_2D:
+ img = builder.glCreateTexture(/** @type {glsFboUtil.Texture2D} */(cfg));
+ att = /** @type {glsFboUtil.TextureFlatAttachment} */ (builder.makeConfig(glsFboUtil.TextureFlatAttachment));
+ att.texTarget = gl.TEXTURE_2D;
+ break;
+ default:
+ throw new Error('Unsupported config.');
+ }
+ att.imageName = img;
+ return att;
+ };
+
+ //GLenum target, GLenum bufType, ImageFormat format, GLsizei width, GLsizei height, FboBuilder& builder, webglctx
+ /**
+ * @param {number} target
+ * @param {number} bufType
+ * @param {glsFboUtil.ImageFormat} format
+ * @param {number} width
+ * @param {number} height
+ * @param {glsFboUtil.FboBuilder} builder
+ * @param {WebGL2RenderingContext} gl
+ */
+ glsFboCompletenessTests.TestBase.prototype.attachTargetToNew = function(
+ target, bufType, format, width, height, builder, gl
+ ) {
+ var imgFmt = format;
+ if (imgFmt.format == gl.NONE)
+ imgFmt = this.getDefaultFormat(target, bufType, gl);
+ var att = glsFboCompletenessTests.makeAttachment(bufType, imgFmt, width, height, builder, gl);
+ builder.glAttach(target, att);
+ };
+
+ /**
+ * @param {number} status
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {string}
+ */
+ glsFboCompletenessTests.statusName = function(status, gl) {
+ gl = gl || window.gl;
+
+ var errorName = gluStrUtil.getErrorName(status);
+ if (status != gl.NO_ERROR && errorName != '')
+ return errorName + ' (during FBO initialization)';
+
+ var fbStatusName = gluStrUtil.getFramebufferStatusName(status);
+ if (fbStatusName != '')
+ return fbStatusName;
+
+ return 'unknown value (' + status + ')';
+ };
+
+ glsFboCompletenessTests.TestBase.prototype.iterate = function() {
+ var gl = window.gl;
+
+ var fbo = new gluObjectWrapper.Framebuffer(gl);
+ var builder = new glsFboUtil.FboBuilder(fbo.get(), gl.FRAMEBUFFER, gl);
+ var ret = this.build(builder, gl);
+ var statuses = this.m_ctx.getVerifier().validStatusCodes(builder, gl);
+
+ var errorCode = builder.getError();
+ if (errorCode != gl.NO_ERROR) {
+ bufferedLogToConsole('Received ' + gluStrUtil.getErrorName(errorCode) + ' (during FBO initialization).');
+ if (statuses.isErrorCodeValid(errorCode))
+ testPassed();
+ else if (statuses.isErrorCodeRequired(gl.NO_ERROR))
+ testFailedOptions('Excepted no error but got ' + gluStrUtil.getErrorName(errorCode), true);
+ else
+ testFailedOptions('Got wrong error code', true);
+ } else {
+ var fboStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ var validStatus = statuses.isFBOStatusValid(fboStatus);
+ bufferedLogToConsole('Received ' + gluStrUtil.getFramebufferStatusName(fboStatus));
+ if (!validStatus) {
+ if (fboStatus == gl.FRAMEBUFFER_COMPLETE) {
+ testFailedOptions('Framebuffer checked as complete, expected incomplete', true);
+ } else if (statuses.isFBOStatusRequired(gl.FRAMEBUFFER_COMPLETE)) {
+ testFailedOptions('Framebuffer checked as incomplete, expected complete', true);
+ } else {
+ // An incomplete status is allowed, but not _this_ incomplete status.
+ testFailedOptions('Framebuffer checked as incomplete, but with wrong status', true);
+ }
+ } else if (fboStatus != gl.FRAMEBUFFER_COMPLETE && statuses.isFBOStatusValid(gl.FRAMEBUFFER_COMPLETE)) {
+ testPassedOptions('Warning: framebuffer object could have checked as complete but did not.', true);
+ } else {
+ // pass
+ testPassed();
+ }
+ }
+ builder.deinit();
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ glsFboCompletenessTests.formatName = function(format, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid GL object');
+
+ var s = gluStrUtil.getPixelFormatName(format.format).substr(3).toLowerCase();
+
+ if (format.unsizedType != gl.NONE)
+ s += '_' + gluStrUtil.getTypeName(format.unsizedType).substr(3).toLowerCase();
+
+ return s;
+ };
+ glsFboCompletenessTests.formatDesc = function(format, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid GL object');
+
+ var s = gluStrUtil.getPixelFormatName(format.format);
+
+ if (format.unsizedType != gl.NONE)
+ s += ' with type ' + gluStrUtil.getTypeName(format.unsizedType);
+
+ return s;
+ };
+
+ /**
+ * @typedef {{attPoint: number, bufType: number, format: glsFboUtil.ImageFormat}}
+ */
+ glsFboCompletenessTests.renderableParamsT;
+
+ /**
+ * @param {number} attPoint
+ * @param {number} bufType
+ * @param {glsFboUtil.ImageFormat} format
+ * @return {glsFboCompletenessTests.renderableParamsT}
+ */
+ glsFboCompletenessTests.renderableParams = function(attPoint, bufType, format) {
+ var ret = {
+ attPoint: attPoint,
+ bufType: bufType,
+ format: format
+ };
+ return ret;
+ };
+ /**
+ * @param {glsFboCompletenessTests.renderableParamsT} params
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {string}
+ */
+ glsFboCompletenessTests.renderableParams.getName = function(params, gl) {
+ return glsFboCompletenessTests.formatName(params.format, gl);
+ };
+ /**
+ * @param {glsFboCompletenessTests.renderableParamsT} params
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {string}
+ */
+ glsFboCompletenessTests.renderableParams.getDescription = function(params, gl) {
+ return glsFboCompletenessTests.formatDesc(params.format, gl);
+ };
+
+ /**
+ * @constructor
+ * @extends {glsFboCompletenessTests.TestBase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {glsFboCompletenessTests.Context} ctx
+ * @param {glsFboCompletenessTests.renderableParamsT} params
+ */
+ glsFboCompletenessTests.RenderableTest = function(name, desc, ctx, params) {
+ glsFboCompletenessTests.TestBase.call(this, name, desc, params);
+ this.m_ctx = ctx;
+ };
+ glsFboCompletenessTests.RenderableTest.prototype = Object.create(glsFboCompletenessTests.TestBase.prototype);
+ glsFboCompletenessTests.RenderableTest.prototype.constructor = glsFboCompletenessTests.RenderableTest;
+
+ glsFboCompletenessTests.RenderableTest.prototype.build = function(builder, gl) {
+ this.attachTargetToNew(this.m_params.attPoint, this.m_params.bufType, this.m_params.format, 64, 64, builder, gl);
+ return true;
+ };
+
+ glsFboCompletenessTests.attTypeName = function(bufType, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid GL object');
+ switch (bufType) {
+ case gl.NONE: return 'none';
+ case gl.RENDERBUFFER: return 'rbo';
+ case gl.TEXTURE: return 'tex';
+ default: break;
+ }
+ throw new Error('Impossible case');
+ };
+
+ /**
+ * @typedef {{color0Kind: number, colornKind: number, depthKind: number, stencilKind: number}}
+ */
+ glsFboCompletenessTests.attachmentParamsT;
+
+ /**
+ * @param {number} color0Kind
+ * @param {number} colornKind
+ * @param {number} depthKind
+ * @param {number} stencilKind
+ * @return {glsFboCompletenessTests.attachmentParamsT}
+ */
+ glsFboCompletenessTests.attachmentParams = function(color0Kind, colornKind, depthKind, stencilKind) {
+ var ret = {
+ color0Kind: color0Kind,
+ colornKind: colornKind,
+ depthKind: depthKind,
+ stencilKind: stencilKind
+ };
+ return ret;
+ };
+ /**
+ * @param {glsFboCompletenessTests.attachmentParamsT} params
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {string}
+ */
+ glsFboCompletenessTests.attachmentParams.getName = function(params, gl) {
+ return (glsFboCompletenessTests.attTypeName(params.color0Kind, gl) + '_' +
+ glsFboCompletenessTests.attTypeName(params.colornKind, gl) + '_' +
+ glsFboCompletenessTests.attTypeName(params.depthKind, gl) + '_' +
+ glsFboCompletenessTests.attTypeName(params.stencilKind, gl));
+ };
+ /**
+ * @param {glsFboCompletenessTests.attachmentParamsT} params
+ * @return {string}
+ */
+ glsFboCompletenessTests.attachmentParams.getDescription = glsFboCompletenessTests.attachmentParams.getName;
+
+ /**
+ * @constructor
+ * @extends {glsFboCompletenessTests.TestBase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {glsFboCompletenessTests.Context} ctx
+ * @param {glsFboCompletenessTests.attachmentParamsT} params
+ */
+ glsFboCompletenessTests.AttachmentTest = function(name, desc, ctx, params) {
+ glsFboCompletenessTests.TestBase.call(this, name, desc, params);
+ this.m_ctx = ctx;
+ };
+ glsFboCompletenessTests.AttachmentTest.prototype = Object.create(glsFboCompletenessTests.TestBase.prototype);
+ glsFboCompletenessTests.AttachmentTest.prototype.constructor = glsFboCompletenessTests.AttachmentTest;
+
+ glsFboCompletenessTests.AttachmentTest.prototype.makeDepthAndStencil = function(builder, gl) {
+
+ /** @type {glsFboUtil.Attachment} */
+ var att = null;
+
+ if (this.m_params.stencilKind == this.m_params.depthKind) {
+ // If there is a common stencil+depth -format, try to use a common
+ // image for both attachments.
+ var flags = glsFboUtil.FormatFlags.DEPTH_RENDERABLE |
+ glsFboUtil.FormatFlags.STENCIL_RENDERABLE |
+ glsFboUtil.formatFlag(this.m_params.stencilKind, gl);
+
+ var formats = this.m_ctx.getMinFormats().getFormats(flags);
+ if (formats.length) {
+ var format = formats[0];
+ att = glsFboCompletenessTests.makeAttachment(this.m_params.depthKind, format, 64, 64, builder, gl);
+ builder.glAttach(gl.DEPTH_ATTACHMENT, att);
+ builder.glAttach(gl.STENCIL_ATTACHMENT, att);
+ return;
+ }
+ }
+ // Either the kinds were separate, or a suitable format was not found.
+ // Create separate images.
+ this.attachTargetToNew(gl.STENCIL_ATTACHMENT, this.m_params.stencilKind,
+ glsFboUtil.ImageFormat.none(), 64, 64, builder, gl);
+ this.attachTargetToNew(gl.DEPTH_ATTACHMENT, this.m_params.depthKind,
+ glsFboUtil.ImageFormat.none(), 64, 64, builder, gl);
+ };
+
+ glsFboCompletenessTests.AttachmentTest.prototype.build = function(builder, gl) {
+
+ this.attachTargetToNew(gl.COLOR_ATTACHMENT0, this.m_params.color0Kind,
+ glsFboUtil.ImageFormat.none(), 64, 64, builder, gl);
+
+ if (this.m_params.colornKind != gl.NONE) {
+ if (this.m_ctx.haveMultiColorAtts())
+ throw new Error('Multiple attachments not supported');
+ var maxAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+
+ for (var i = 1; i < maxAttachments; ++i) {
+ this.attachTargetToNew(gl.COLOR_ATTACHMENT0 + i, this.m_params.colornKind,
+ glsFboUtil.ImageFormat.none(), 64, 64, builder, gl);
+ }
+ }
+
+ this.makeDepthAndStencil(builder, gl);
+
+ return true;
+ };
+
+ /**
+ * @constructor
+ * @extends {glsFboCompletenessTests.TestBase}
+ * @param {string} name
+ * @param {string} desc
+ * @param {glsFboCompletenessTests.Context} ctx
+ */
+ glsFboCompletenessTests.EmptyImageTest = function(name, desc, ctx) {
+ glsFboCompletenessTests.TestBase.call(this, name, desc, null);
+ this.m_ctx = ctx;
+ };
+ glsFboCompletenessTests.EmptyImageTest.prototype = Object.create(glsFboCompletenessTests.TestBase.prototype);
+ glsFboCompletenessTests.EmptyImageTest.prototype.constructor = glsFboCompletenessTests.EmptyImageTest;
+
+ glsFboCompletenessTests.EmptyImageTest.prototype.build = function(builder, gl) {
+ this.attachTargetToNew(gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER,
+ glsFboUtil.ImageFormat.none(), 0, 0, builder, gl);
+ return true;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboUtil.js
new file mode 100644
index 0000000000..86d05891f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsFboUtil.js
@@ -0,0 +1,1413 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsFboUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.gluStrUtil');
+
+goog.scope(function() {
+
+ var glsFboUtil = modules.shared.glsFboUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluStrUtil = framework.opengl.gluStrUtil;
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * @constructor
+ * @template KeyT
+ * @template ValueT
+ * @param {function(!KeyT, !KeyT):boolean} comparefnc
+ */
+ glsFboUtil.Map = function(comparefnc) {
+ /** @type {Array<{first: !KeyT, second: ValueT}>} */
+ this.store = [];
+ this.compare = comparefnc;
+ this.length = 0;
+ };
+
+ /**
+ * @param {number} num1
+ * @param {number} num2
+ * @return {boolean}
+ */
+ glsFboUtil.Map.compareNumber = function(num1, num2) {
+ return num1 < num2;
+ };
+
+ /**
+ * @param {!KeyT} key
+ * @param {ValueT} value
+ * @return {{first: !KeyT, second: ValueT}}
+ */
+ glsFboUtil.Map.prototype.pair = function(key, value) {
+ return {
+ first: key,
+ second: value
+ };
+ };
+
+ /**
+ * @protected
+ * @param {!KeyT} key
+ * @return {number}
+ */
+ glsFboUtil.Map.prototype.findInsertionPoint = function(key) {
+ var /** @type {number} */i, /** @type {number} */length;
+ for (i = 0, length = this.store.length; i < length; ++i) {
+ if (!this.compare(key, this.store[i].first)) break;
+ }
+ return i;
+ };
+
+ /**
+ * index should be a value returned from findInsertionPoint.
+ * returns true if the compare function returns false reflexively
+ * (i.e. no matter the order in which the keys are passed as arguments).
+ * @protected
+ * @param {!KeyT} key
+ * @param {number} index
+ * @return {boolean}
+ */
+ glsFboUtil.Map.prototype.foundIndexMatches = function(key, index) {
+ return (
+ this.store[index] !== undefined &&
+ !this.compare(this.store[index].first, key)
+ );
+ };
+
+ /**
+ * @param {!KeyT} key
+ * @return {boolean}
+ */
+ glsFboUtil.Map.prototype.isset = function(key) {
+ return this.foundIndexMatches(key, this.findInsertionPoint(key));
+ };
+
+ /**
+ * @param {!KeyT} key
+ * @param {ValueT} value
+ */
+ glsFboUtil.Map.prototype.set = function(key, value) {
+ var index = this.findInsertionPoint(key);
+ if (this.foundIndexMatches(key, index)) {
+ this.store[index].second = value;
+ } else {
+ this.store.splice(index, 0, this.pair(key, value));
+ ++this.length;
+ }
+ };
+
+ /**
+ * @param {!KeyT} key
+ * @return {?ValueT}
+ */
+ glsFboUtil.Map.prototype.remove = function(key) {
+ var index = this.findInsertionPoint(key);
+ /** @type {?ValueT} */ var ret = null;
+ if (this.foundIndexMatches(key, index)) {
+ ret = this.store[index].second;
+ this.store.splice(index, 1);
+ --this.length;
+ }
+ return ret;
+ };
+
+ /**
+ * @param {KeyT} key
+ * @return {?{first: KeyT, second: ValueT}}
+ */
+ glsFboUtil.Map.prototype.get = function(key) {
+ var index = this.findInsertionPoint(key);
+ if (this.foundIndexMatches(key, index)) return this.store[index];
+ return null;
+ };
+
+ /**
+ * @param {KeyT} key
+ * @return {?ValueT}
+ */
+ glsFboUtil.Map.prototype.getValue = function(key) {
+ var index = this.findInsertionPoint(key);
+ if (this.foundIndexMatches(key, index)) return this.store[index].second;
+ return null;
+ };
+
+ /**
+ * @param {!KeyT} key
+ * @param {ValueT} fallback
+ * @return {ValueT}
+ */
+ glsFboUtil.Map.prototype.lookupDefault = function(key, fallback) {
+ var index = this.findInsertionPoint(key);
+ if (this.foundIndexMatches(key, index)) return this.store[index].second;
+ return fallback;
+ };
+
+ /**
+ * @param {number} index
+ * @return {{first: KeyT, second: ValueT}|undefined}
+ */
+ glsFboUtil.Map.prototype.getIndex = function(index) {
+ return this.store[index];
+ };
+
+ /**
+ * Use the callback to set the value to be identified by key.
+ * If a value is already identified by the key, it will be passed to the callback
+ * @param {!KeyT} key
+ * @param {function(ValueT=):!ValueT} callback
+ */
+ glsFboUtil.Map.prototype.transform = function(key, callback) {
+ var index = this.findInsertionPoint(key);
+ if (this.foundIndexMatches(key, index)) {
+ this.store[index].second = callback(this.store[index].second);
+ } else {
+ this.store.splice(index, 0, this.pair(key, callback()));
+ ++this.length;
+ }
+ };
+
+ /**
+ * removed all elements from the Map
+ */
+ glsFboUtil.Map.prototype.clear = function() {
+ this.store.splice(0, this.length);
+ this.length = 0;
+ };
+
+ /**
+ * @constructor
+ */
+ glsFboUtil.FormatDB = function() {
+ this.m_map = /** @type {glsFboUtil.Map<glsFboUtil.ImageFormat,number>} */(
+ new glsFboUtil.Map(glsFboUtil.ImageFormat.lessthan)
+ );
+ };
+
+ /**
+ * @param {glsFboUtil.ImageFormat} format
+ * @param {number} newFlags
+ */
+ glsFboUtil.FormatDB.prototype.addFormat = function(format, newFlags) {
+ this.m_map.transform(format, function(flags) {
+ return flags | newFlags;
+ });
+ };
+
+ /**
+ * @param {number} requirements
+ * @return {Array<glsFboUtil.ImageFormat>}
+ */
+ glsFboUtil.FormatDB.prototype.getFormats = function(requirements) {
+ /** @type {Array<glsFboUtil.ImageFormat>} */ var ret = [];
+ for (var i = 0; i < this.m_map.length; ++i) {
+ var pair = this.m_map.getIndex(i);
+ if ((pair.second & requirements) == requirements)
+ ret.push(pair.first);
+ }
+
+ return ret;
+ };
+
+ /**
+ * @param {glsFboUtil.ImageFormat} format
+ * @param {number} fallback
+ * @return {number}
+ */
+ glsFboUtil.FormatDB.prototype.getFormatInfo = function(format, fallback) {
+ return this.m_map.lookupDefault(format, fallback);
+ };
+
+ /**
+ * @param {Object} map
+ * @param {number} key
+ * @param {number} fallback
+ * @return {number}
+ */
+ glsFboUtil.lookupDefault = function(map, key, fallback) {
+ return (map[key] !== undefined) ? map[key] : fallback;
+ };
+
+ /**
+ * @param {Array<number>} array
+ * @param {number} item
+ * @return {boolean}
+ */
+ glsFboUtil.contains = function(array, item) {
+ var l = array.length;
+ for (var i = 0; i < l; ++i)
+ if (array[i] == item) return true;
+ return false;
+ };
+
+ /**
+ * @typedef {Array<(number | glsFboUtil.Range<number>)>}
+ */
+ glsFboUtil.formatT;
+
+ /**
+ * @param {glsFboUtil.FormatDB} db
+ * @param {glsFboUtil.Range<glsFboUtil.formatT>} stdFmts
+ */
+ glsFboUtil.addFormats = function(db, stdFmts) {
+ for (var set = stdFmts.reset(); set = stdFmts.current(); stdFmts.next()) {
+ for (var fmt = set[1].reset(); fmt = set[1].current(); set[1].next()) {
+ db.addFormat(glsFboUtil.formatKeyInfo(fmt), set[0]);
+ }
+ }
+ };
+
+ /**
+ * @param {glsFboUtil.FormatDB} db
+ * @param {glsFboUtil.Range} extFmts
+ * @param {WebGLRenderingContextBase=} gl
+ * @throws {Error}
+ */
+ glsFboUtil.addExtFormats = function(db, extFmts, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+ var extensions = gl.getSupportedExtensions();
+
+ // loop through the range, looking at the extentions.
+ for (var ext = extFmts.reset(); ext = extFmts.current(); extFmts.next()) {
+ var tokens = ext.extensions.split(/\s+/);
+
+ var supported = function() {
+ for (var i = 0, l = tokens.length; i < l; ++i)
+ if (extensions.indexOf(tokens[i]) === -1) return false;
+ return true;
+ }();
+
+ if (supported) {
+ for (var format = ext.formats.reset(); format = ext.formats.current(); ext.formats.next()) {
+ db.addFormat(glsFboUtil.formatKeyInfo(format), ext.flags);
+ }
+ }
+
+ }
+
+ };
+
+ /**
+ * @param {number} glenum
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {number}
+ * @throws {Error}
+ */
+ glsFboUtil.formatFlag = function(glenum, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ switch (glenum) {
+ case gl.NONE:
+ return glsFboUtil.FormatFlags.ANY_FORMAT;
+ case gl.RENDERBUFFER:
+ return glsFboUtil.FormatFlags.RENDERBUFFER_VALID;
+ case gl.TEXTURE:
+ return glsFboUtil.FormatFlags.TEXTURE_VALID;
+ case gl.STENCIL_ATTACHMENT:
+ return glsFboUtil.FormatFlags.STENCIL_RENDERABLE;
+ case gl.DEPTH_ATTACHMENT:
+ return glsFboUtil.FormatFlags.DEPTH_RENDERABLE;
+ default:
+ if (glenum < gl.COLOR_ATTACHMENT0 || glenum > gl.COLOR_ATTACHMENT15) {
+ throw new Error('glenum out of range');
+ }
+ }
+ return glsFboUtil.FormatFlags.COLOR_RENDERABLE;
+ };
+
+ /**
+ * Remove value from array
+ * @param {Array} array
+ * @param {number} value
+ */
+ glsFboUtil.remove_from_array = function(array, value) {
+ var index = 0;
+ while ((index = array.indexOf(value)) != -1) {
+ array.splice(index, 1);
+ }
+ };
+
+ /**
+ * glsFboUtil.FormatExtEntry
+ * @constructor
+ * @struct
+ * @param {string=} extensions
+ * @param {number=} flags
+ * @param {glsFboUtil.Range=} formats
+ */
+ glsFboUtil.FormatExtEntry = function(extensions, flags, formats) {
+ this.extensions = null;
+ this.flags = null;
+ this.formats = null;
+
+ if (extensions !== undefined) {
+ this.extensions = extensions;
+ if (flags !== undefined) {
+ this.flags = flags;
+ if (formats !== undefined)
+ this.formats = formats;
+ }
+ }
+
+ };
+
+ /**
+ * glsFboUtil.Range
+ * @constructor
+ * @struct
+ * @template T
+ * @param {Array<T>} array
+ * @param {number=} begin
+ * @param {number=} end
+ */
+ glsFboUtil.Range = function(array, begin, end) {
+ // @private
+ this.m_begin = (begin === undefined ? 0 : begin);
+ // @private
+ this.m_end = end || array.length;
+ /**
+ * @private
+ * @type {Array<T>}
+ */
+ this.m_array = array;
+ // @private
+ this.m_index = this.m_begin;
+ };
+
+ /**
+ * @return {Array<T>}
+ */
+ glsFboUtil.Range.prototype.array = function() {
+ return this.m_array;
+ };
+
+ /**
+ * @return {number}
+ */
+ glsFboUtil.Range.prototype.begin = function() {
+ return this.m_begin;
+ };
+
+ /** *generated by script*
+ * @return {number}
+ */
+ glsFboUtil.Range.prototype.end = function() {
+ return this.m_end;
+ };
+
+ /**
+ * Returns the current pointer index as well as the current object
+ * @param {number} id
+ * @return {{first: number, second: T}}
+ */
+ glsFboUtil.Range.prototype.get = function(id) {
+ return {
+ first: id,
+ second: this.m_array[id]
+ };
+ };
+
+ /**
+ * Sets the internal pointer to the beginning of the range, and returns the first object.
+ * @return {T}
+ */
+ glsFboUtil.Range.prototype.reset = function() {
+ this.m_index = this.m_begin;
+ return this.current();
+ };
+
+ /**
+ * returns the current object within the specified range. The internal pointer is unaltered.
+ * @return {T}
+ */
+ glsFboUtil.Range.prototype.current = function() {
+ return this.m_index < this.m_end ? this.m_array[this.m_index] : null;
+ };
+
+ /**
+ * Increments the internal pointer
+ */
+ glsFboUtil.Range.prototype.next = function() {
+ ++this.m_index;
+ };
+
+ /**
+ * glsFboUtil.rangeArray
+ * replaces the macro GLS_ARRAY_RANGE
+ * Creates a new Range object from the specified array, spanning the whole array.
+ * @template T
+ * @param {Array<T>} array
+ * @return {glsFboUtil.Range<T>}
+ */
+ glsFboUtil.rangeArray = function(array) {
+ return new glsFboUtil.Range(array);
+ };
+
+ /**
+ * @constructor
+ * @struct
+ * @param {number=} format
+ * @param {number=} unsizedType
+ */
+ glsFboUtil.ImageFormat = function(format, unsizedType) {
+ this.format = format || 0;
+ //! Type if format is unsized, gl.NONE if sized.
+ this.unsizedType = unsizedType || 0;
+
+ };
+
+ /**
+ * @param {!glsFboUtil.ImageFormat} obj1
+ * @param {!glsFboUtil.ImageFormat} obj2
+ * @return {boolean}
+ */
+ glsFboUtil.ImageFormat.lessthan = function(obj1, obj2) {
+ return (
+ (obj1.format < obj2.format) ||
+ (obj1.format == obj2.format && obj1.unsizedType < obj2.unsizedType)
+ );
+ };
+
+ /**
+ * Sets the object's parameters to gl.NONE
+ */
+ glsFboUtil.ImageFormat.prototype.none = function() {
+ this.format = 0;
+ this.unsizedType = 0;
+ };
+
+ /**
+ * @return {glsFboUtil.ImageFormat}
+ */
+ glsFboUtil.ImageFormat.none = function() {
+ var obj = new glsFboUtil.ImageFormat();
+ obj.none();
+ return obj;
+ };
+
+ // where key is a FormatKey, and a FormatKey is a unsigned 32bit int.
+
+ /**
+ * @param {number} key
+ * @return {glsFboUtil.ImageFormat}
+ */
+ glsFboUtil.formatKeyInfo = function(key) {
+ return new glsFboUtil.ImageFormat(
+ (key & 0x0000ffff),
+ (key & 0xffff0000) >>> 16
+ );
+ };
+
+ /**
+ * glsFboUtil.Config Class.
+ * @constructor
+ */
+ glsFboUtil.Config = function() {
+ this.type = glsFboUtil.Config.s_types.CONFIG;
+ this.target = glsFboUtil.Config.s_target.NONE;
+ };
+ /**
+ * @enum {number}
+ */
+ glsFboUtil.Config.s_target = {
+ NONE: 0,
+ RENDERBUFFER: 0x8D41,
+ TEXTURE_2D: 0x0DE1,
+ TEXTURE_CUBE_MAP: 0x8513,
+ TEXTURE_3D: 0x806F,
+ TEXTURE_2D_ARRAY: 0x8C1A,
+
+ FRAMEBUFFER: 0x8D40
+ };
+
+ // the c++ uses dynamic casts to determain if an object inherits from a
+ // given class. Here, each class' constructor assigns a bit to obj.type.
+ // look for the bit to see if an object inherits that class.
+
+ /**
+ * @enum
+ */
+ glsFboUtil.Config.s_types = {
+ CONFIG: 0x000001,
+
+ IMAGE: 0x000010,
+ RENDERBUFFER: 0x000020,
+ TEXTURE: 0x000040,
+ TEXTURE_FLAT: 0x000080,
+ TEXTURE_2D: 0x000100,
+ TEXTURE_CUBE_MAP: 0x000200,
+ TEXTURE_LAYERED: 0x000400,
+ TEXTURE_3D: 0x000800,
+ TEXTURE_2D_ARRAY: 0x001000,
+
+ ATTACHMENT: 0x010000,
+ ATT_RENDERBUFFER: 0x020000,
+ ATT_TEXTURE: 0x040000,
+ ATT_TEXTURE_FLAT: 0x080000,
+ ATT_TEXTURE_LAYER: 0x100000,
+
+ UNUSED: 0xFFE0E00E
+ };
+
+ /**
+ * glsFboUtil.Image Class.
+ * @constructor
+ * @extends {glsFboUtil.Config}
+ */
+ glsFboUtil.Image = function() {
+ glsFboUtil.Config.call(this);
+ this.type |= glsFboUtil.Config.s_types.IMAGE;
+ this.width = 0;
+ this.height = 0;
+ this.internalFormat = new glsFboUtil.ImageFormat();
+ };
+
+ /**
+ * glsFboUtil.Renderbuffer Class.
+ * @constructor
+ * @extends {glsFboUtil.Image}
+ */
+ glsFboUtil.Renderbuffer = function() {
+ glsFboUtil.Image.call(this);
+ this.type |= glsFboUtil.Config.s_types.RENDERBUFFER;
+ this.target = glsFboUtil.Config.s_target.RENDERBUFFER;
+ this.numSamples = 0;
+ };
+
+ /**
+ * glsFboUtil.Texture Class.
+ * @constructor
+ * @extends {glsFboUtil.Image}
+ */
+ glsFboUtil.Texture = function() {
+ glsFboUtil.Image.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE;
+ this.numLevels = 1;
+ };
+
+ /**
+ * glsFboUtil.TextureFlat Class.
+ * @constructor
+ * @extends {glsFboUtil.Texture}
+ */
+ glsFboUtil.TextureFlat = function() {
+ glsFboUtil.Texture.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE_FLAT;
+ };
+
+ /**
+ * glsFboUtil.Texture2D Class.
+ * @constructor
+ * @extends {glsFboUtil.TextureFlat}
+ */
+ glsFboUtil.Texture2D = function() {
+ glsFboUtil.TextureFlat.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE_2D;
+ this.target = glsFboUtil.Config.s_target.TEXTURE_2D;
+ };
+
+ /**
+ * glsFboUtil.TextureCubeMap Class.
+ * @constructor
+ * @extends {glsFboUtil.TextureFlat}
+ */
+ glsFboUtil.TextureCubeMap = function() {
+ glsFboUtil.TextureFlat.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP;
+ this.target = glsFboUtil.Config.s_target.TEXTURE_CUBE_MAP;
+ };
+
+ /**
+ * glsFboUtil.TextureLayered Class.
+ * @constructor
+ * @extends {glsFboUtil.Texture}
+ */
+ glsFboUtil.TextureLayered = function() {
+ glsFboUtil.Texture.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE_LAYERED;
+ this.numLayers = 1;
+ };
+
+ /**
+ * glsFboUtil.Texture3D Class.
+ * @constructor
+ * @extends {glsFboUtil.TextureLayered}
+ */
+ glsFboUtil.Texture3D = function() {
+ glsFboUtil.TextureLayered.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE_3D;
+ this.target = glsFboUtil.Config.s_target.TEXTURE_3D;
+ };
+
+ /**
+ * glsFboUtil.Texture2DArray Class.
+ * @constructor
+ * @extends {glsFboUtil.TextureLayered}
+ */
+ glsFboUtil.Texture2DArray = function() {
+ glsFboUtil.TextureLayered.call(this);
+ this.type |= glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY;
+ this.target = glsFboUtil.Config.s_target.TEXTURE_2D_ARRAY;
+ };
+
+ /**
+ * glsFboUtil.Attachment Class.
+ * @constructor
+ * @extends {glsFboUtil.Config}
+ */
+ glsFboUtil.Attachment = function() {
+ glsFboUtil.Config.call(this);
+
+ this.type |= glsFboUtil.Config.s_types.ATTACHMENT;
+
+ /** @type {glsFboUtil.Config.s_target} */
+ this.target = glsFboUtil.Config.s_target.FRAMEBUFFER;
+
+ /** @type {WebGLObject} */
+ this.imageName = null;
+ };
+
+ /**
+ * this function is declared, but has no definition/is unused in the c++
+ * @param {number} attPoint
+ * @param {number} image
+ * @param {number} vfr
+ */
+ glsFboUtil.Attachment.prototype.isComplete = function(attPoint, image, vfr) { };
+
+ /**
+ * glsFboUtil.RenderBufferAttachments Class.
+ * @constructor
+ * @extends {glsFboUtil.Attachment}
+ */
+ glsFboUtil.RenderbufferAttachment = function() {
+ glsFboUtil.Attachment.call(this);
+ this.type |= glsFboUtil.Config.s_types.ATT_RENDERBUFFER;
+ this.renderbufferTarget = glsFboUtil.Config.s_target.RENDERBUFFER;
+ };
+ glsFboUtil.RenderbufferAttachment.prototype = Object.create(glsFboUtil.Attachment.prototype);
+ glsFboUtil.RenderbufferAttachment.prototype.constructor = glsFboUtil.RenderbufferAttachment;
+
+ /**
+ * glsFboUtil.TextureAttachment Class.
+ * @constructor
+ * @extends {glsFboUtil.Attachment}
+ */
+ glsFboUtil.TextureAttachment = function() {
+ glsFboUtil.Attachment.call(this);
+ this.type |= glsFboUtil.Config.s_types.ATT_TEXTURE;
+ this.level = 0;
+ };
+ glsFboUtil.TextureAttachment.prototype = Object.create(glsFboUtil.Attachment.prototype);
+ glsFboUtil.TextureAttachment.prototype.constructor = glsFboUtil.TextureAttachment;
+
+ /**
+ * glsFboUtil.TextureFlatAttachment Class.
+ * @constructor
+ * @extends {glsFboUtil.TextureAttachment}
+ */
+ glsFboUtil.TextureFlatAttachment = function() {
+ glsFboUtil.TextureAttachment.call(this);
+ this.type |= glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT;
+ this.texTarget = glsFboUtil.Config.s_target.NONE;
+ };
+ glsFboUtil.TextureFlatAttachment.prototype = Object.create(glsFboUtil.TextureAttachment.prototype);
+ glsFboUtil.TextureFlatAttachment.prototype.constructor = glsFboUtil.TextureFlatAttachment;
+
+ /**
+ * glsFboUtil.TextureLayerAttachment Class.
+ * @constructor
+ * @extends {glsFboUtil.TextureAttachment}
+ */
+ glsFboUtil.TextureLayerAttachment = function() {
+ glsFboUtil.TextureAttachment.call(this);
+ this.type |= glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER;
+ this.layer = 0;
+ };
+ glsFboUtil.TextureLayerAttachment.prototype = Object.create(glsFboUtil.TextureAttachment.prototype);
+ glsFboUtil.TextureLayerAttachment.prototype.constructor = glsFboUtil.TextureLayerAttachment;
+
+ // these are a collection of helper functions for creating various gl textures.
+ glsFboUtil.glsup = function() {
+
+ var glInit = function(cfg, gl) {
+ if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_2D) != 0) {
+ glInitFlat(cfg, glTarget(cfg, gl), gl);
+
+ } else if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP) != 0) {
+ for (var i = gl.TEXTURE_CUBE_MAP_NEGATIVE_X; i <= gl.TEXTURE_CUBE_MAP_POSITIVE_Z; ++i)
+ glInitFlat(cfg, i, gl);
+ } else if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_3D) != 0) {
+ glInitLayered(cfg, 2, gl);
+
+ } else if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY) != 0) {
+ glInitLayered(cfg, 1, gl);
+ }
+ };
+
+ var glInitFlat = function(cfg, target, gl) {
+ var format = glsFboUtil.transferImageFormat(cfg.internalFormat, gl);
+ var w = cfg.width;
+ var h = cfg.height;
+ for (var level = 0; level < cfg.numLevels; ++level) {
+ gl.texImage2D(
+ target, level, cfg.internalFormat.format,
+ w, h, 0, format.format, format.dataType, null
+ );
+ w = Math.max(1, w / 2);
+ h = Math.max(1, h / 2);
+ }
+ };
+
+ var glInitLayered = function(cfg, depth_divider, gl) {
+ var format = glsFboUtil.transferImageFormat(cfg.internalFormat, gl);
+ var w = cfg.width;
+ var h = cfg.height;
+ var depth = cfg.numLayers;
+ for (var level = 0; level < cfg.numLevels; ++level) {
+ gl.texImage3D(
+ glTarget(cfg, gl), level, cfg.internalFormat.format,
+ w, h, depth, 0, format.format, format.dataType, null
+ );
+ w = Math.max(1, w / 2);
+ h = Math.max(1, h / 2);
+ depth = Math.max(1, depth / depth_divider);
+ }
+ };
+
+ var glCreate = function(cfg, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ if (cfg.type & glsFboUtil.Config.s_types.RENDERBUFFER) {
+ var ret = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, ret);
+
+ if (cfg.numSamples == 0) {
+ gl.renderbufferStorage(
+ gl.RENDERBUFFER,
+ cfg.internalFormat.format,
+ cfg.width, cfg.height
+ );
+ } else {
+ gl.renderbufferStorageMultisample(
+ gl.RENDERBUFFER,
+ cfg.numSamples,
+ cfg.internalFormat.format,
+ cfg.width, cfg.height
+ );
+ }
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+
+ } else if (cfg.type & glsFboUtil.Config.s_types.TEXTURE) {
+ var ret = gl.createTexture();
+ gl.bindTexture(glTarget(cfg, gl), ret);
+ glInit(cfg, gl);
+ gl.bindTexture(glTarget(cfg, gl), null);
+
+ } else {
+ throw new Error('Impossible image type');
+ }
+ return ret;
+ };
+
+ var glTarget = function(cfg, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+ var mask = (
+ glsFboUtil.Config.s_types.RENDERBUFFER |
+ glsFboUtil.Config.s_types.TEXTURE_2D |
+ glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP |
+ glsFboUtil.Config.s_types.TEXTURE_3D |
+ glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY
+ );
+ switch (cfg.type & mask) {
+ case glsFboUtil.Config.s_types.RENDERBUFFER: return gl.RENDERBUFFER;
+ case glsFboUtil.Config.s_types.TEXTURE_2D: return gl.TEXTURE_2D;
+ case glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP: return gl.TEXTURE_CUBE_MAP;
+ case glsFboUtil.Config.s_types.TEXTURE_3D: return gl.TEXTURE_3D;
+ case glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY: return gl.TEXTURE_2D_ARRAY;
+ default: break;
+ }
+ throw new Error('Impossible image type.');
+ };
+
+ var glDelete = function(cfg, img, gl) {
+ if (cfg.type & glsFboUtil.Config.s_types.RENDERBUFFER)
+ gl.deleteRenderbuffer(img);
+ else if (cfg.type & glsFboUtil.Config.s_types.TEXTURE)
+ gl.deleteTexture(img);
+ else
+ throw new Error('Impossible image type');
+ };
+
+ return {
+ create: glCreate,
+ remove: glDelete
+ };
+
+ }();
+
+ /** *generated by script*
+ * @param {number} img
+ * @return {number}
+ */
+ glsFboUtil.imageNumSamples = function(img) {
+ return (img.numSamples != undefined) ? img.numSamples : 0;
+ };
+
+ /** *generated by script*
+ * @param {glsFboUtil.Attachment} att
+ * @param {number} attPoint
+ * @param {WebGLRenderingContextBase=} gl
+ * @throws {Error}
+ */
+ glsFboUtil.attachAttachment = function(att, attPoint, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ var mask = (
+ glsFboUtil.Config.s_types.ATT_RENDERBUFFER |
+ glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT |
+ glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER
+ );
+
+ switch (att.type & mask) {
+ case glsFboUtil.Config.s_types.ATT_RENDERBUFFER:
+ gl.framebufferRenderbuffer(
+ att.target, attPoint, att.renderbufferTarget, /** @type {WebGLRenderbuffer} */(att.imageName)
+ );
+ break;
+ case glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT:
+ gl.framebufferTexture2D(
+ att.target, attPoint, att.texTarget, /** @type {WebGLTexture} */(att.imageName), att.level
+ );
+ break;
+ case glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER:
+ gl.framebufferTextureLayer(
+ att.target, attPoint, /** @type {WebGLTexture} */(att.imageName), att.level, att.layer
+ );
+ break;
+ default:
+ throw new Error('Impossible attachment type');
+ }
+
+ };
+
+ /** *generated by script*
+ * @param {glsFboUtil.Attachment} att
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {number}
+ * @throws {Error}
+ */
+ glsFboUtil.attachmentType = function(att, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ if (att.type & glsFboUtil.Config.s_types.ATT_RENDERBUFFER) {
+ return gl.RENDERBUFFER;
+ }
+ if (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE) {
+ return gl.TEXTURE;
+ }
+ throw new Error('Impossible attachment type.');
+
+ };
+
+ /**
+ * @param {glsFboUtil.Attachment} att
+ * @return {number}
+ * @throws {Error}
+ */
+ glsFboUtil.textureLayer = function(att) {
+ if (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT) return 0;
+ if (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER) return att.layer;
+ throw new Error('Impossible attachment type.');
+ };
+
+ /**
+ * @param {glsFboUtil.Checker} cctx
+ * @param {glsFboUtil.Attachment} att
+ * @param {number} attPoint
+ * @param {glsFboUtil.Image} image
+ * @param {glsFboUtil.FormatDB} db
+ * @param {WebGLRenderingContextBase=} gl
+ * @throws {Error}
+ */
+ glsFboUtil.checkAttachmentCompleteness = function(cctx, att, attPoint, image, db, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ // GLES2 4.4.5 / GLES3 4.4.4, "glsFboUtil.Framebuffer attachment completeness"
+ if (
+ (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE) &&
+ (image.type & glsFboUtil.Config.s_types.TEXTURE_LAYERED)
+ ) {
+ // GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is
+ // TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a
+ // three-dimensional texture, then the value of
+ // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the depth
+ // of the texture.
+ //
+ // GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is
+ // TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a
+ // two-dimensional array texture, then the value of
+ // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the
+ // number of layers in the texture.
+ cctx.addFBOStatus(
+ glsFboUtil.textureLayer(att) < image.numLayers,
+ gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
+ );
+ }
+
+ // "The width and height of image are non-zero."
+ cctx.addFBOStatus(
+ image.width > 0 && image.height > 0,
+ gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
+ );
+
+ // Check for renderability
+ var flags = db.getFormatInfo(image.internalFormat, glsFboUtil.FormatFlags.ANY_FORMAT);
+
+ // If the format does not have the proper renderability flag, the
+ // completeness check _must_ fail.
+ cctx.addFBOStatus(
+ (flags & glsFboUtil.formatFlag(attPoint)) != 0,
+ gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
+ );
+
+ // If the format is only optionally renderable, the completeness check _can_ fail.
+ cctx.addPotentialFBOStatus(
+ (flags & glsFboUtil.FormatFlags.REQUIRED_RENDERABLE) != 0,
+ gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
+ );
+
+ };
+
+ // replaces GLS_UNSIZED_FORMATKEY
+
+ /**
+ * All params and return types for this function are 32 bit
+ * @param {number} format
+ * @param {number} type
+ * @return {number}
+ */
+ glsFboUtil.formatkey = function(format, type) {
+ // The formatkey value should be 32-bit unsigned int.
+ return ((type << 16) >>> 0 | format) & 0xFFFFFFFF;
+ };
+
+ /**
+ * @enum
+ */
+ glsFboUtil.FormatFlags = {
+ ANY_FORMAT: 0x00,
+ COLOR_RENDERABLE: 0x01,
+ DEPTH_RENDERABLE: 0x02,
+ STENCIL_RENDERABLE: 0x04,
+ RENDERBUFFER_VALID: 0x08,
+ TEXTURE_VALID: 0x10,
+ REQUIRED_RENDERABLE: 0x20 //< Without this, renderability is allowed, not required.
+ };
+
+ /**
+ * A framebuffer configuration
+ * @constructor
+ * @param {WebGLRenderingContextBase=} gl
+ */
+ glsFboUtil.Framebuffer = function(gl) {
+ this.m_gl = gl || window.gl;
+ this.fbid = 0;
+
+ var fbidCompare = function(obj1, obj2) {
+ return obj1._fbid < obj2._fbid;
+ };
+
+ this.attachments = /** @type {glsFboUtil.Map<number,glsFboUtil.Attachment>} */(
+ new glsFboUtil.Map(glsFboUtil.Map.compareNumber)
+ );
+ this.textures = /** @type {glsFboUtil.Map<Object,glsFboUtil.Texture>} */(
+ new glsFboUtil.Map(fbidCompare)
+ );
+ this.rbos = /** @type {glsFboUtil.Map<Object,glsFboUtil.Renderbuffer>} */(
+ new glsFboUtil.Map(fbidCompare)
+ );
+ };
+
+ /**
+ * @param {number} attPoint
+ * @param {glsFboUtil.Attachment} att
+ */
+ glsFboUtil.Framebuffer.prototype.attach = function(attPoint, att) {
+ if (!att) {
+ this.attachments.remove(attPoint);
+ } else {
+ this.attachments.set(attPoint, att);
+ }
+ };
+
+ /**
+ * @param {WebGLTexture} texName
+ * @param {glsFboUtil.Texture} texCfg
+ */
+ glsFboUtil.Framebuffer.prototype.setTexture = function(texName, texCfg) {
+ texName._fbid = this.fbid++;
+ this.textures.set(texName, texCfg);
+ };
+
+ /**
+ * @param {WebGLRenderbuffer} rbName
+ * @param {glsFboUtil.Renderbuffer} rbCfg
+ */
+ glsFboUtil.Framebuffer.prototype.setRbo = function(rbName, rbCfg) {
+ rbName._fbid = this.fbid++;
+ this.rbos.set(rbName, rbCfg);
+ };
+
+ /**
+ * @param {number} type
+ * @param {WebGLObject} imgName
+ * @return {glsFboUtil.Image}
+ * @throws {Error}
+ */
+ glsFboUtil.Framebuffer.prototype.getImage = function(type, imgName) {
+ switch (type) {
+ case this.m_gl.TEXTURE: return this.textures.lookupDefault(/** @type {WebGLTexture} */(imgName), null);
+ case this.m_gl.RENDERBUFFER: return this.rbos.lookupDefault(/** @type {WebGLTexture} */(imgName), null);
+ default: break;
+ }
+ throw new Error('Bad image type.');
+ };
+
+ /**
+ * @constructor
+ * @extends {glsFboUtil.Framebuffer}
+ * @param {WebGLFramebuffer} fbo
+ * @param {number} target
+ * @param {WebGLRenderingContextBase=} gl
+ */
+ glsFboUtil.FboBuilder = function(fbo, target, gl) {
+ glsFboUtil.Framebuffer.call(this, gl);
+
+ this.m_gl = gl || window.gl;
+ this.m_target = target;
+ this.m_configs = [];
+ this.m_error = this.m_gl.NO_ERROR;
+
+ this.m_gl.bindFramebuffer(this.m_target, fbo);
+
+ };
+
+ glsFboUtil.FboBuilder.prototype = Object.create(glsFboUtil.Framebuffer.prototype);
+ glsFboUtil.FboBuilder.prototype.constructor = glsFboUtil.FboBuilder;
+
+ glsFboUtil.FboBuilder.prototype.deinit = function() {
+
+ var pair;
+ for (var i = 0; i < this.textures.length; ++i) {
+ pair = this.textures.getIndex(i);
+ glsFboUtil.glsup.remove(pair.second, pair.first, this.m_gl);
+ }
+ this.textures.clear();
+
+ for (var i = 0; i < this.rbos.length; ++i) {
+ pair = this.rbos.getIndex(i);
+ glsFboUtil.glsup.remove(pair.second, pair.first, this.m_gl);
+ }
+ this.rbos.clear();
+
+ this.m_gl.bindFramebuffer(this.m_target, null);
+/*
+ for (var i = 0 ; i < this.m_configs.length ; ++i) {
+ delete this.m_configs[i];
+ }
+//*/
+ };
+
+ /**
+ * @param {number} attPoint
+ * @param {glsFboUtil.Attachment} att
+ */
+ glsFboUtil.FboBuilder.prototype.glAttach = function(attPoint, att) {
+ if (!att) {
+ this.m_gl.framebufferRenderbuffer(this.m_target, attPoint, this.m_gl.RENDERBUFFER, null);
+ } else {
+ glsFboUtil.attachAttachment(att, attPoint, this.m_gl);
+ }
+ this.checkError();
+ this.attach(attPoint, att);
+ };
+
+ /**
+ * @param {glsFboUtil.Texture} texCfg
+ * @return {WebGLTexture}
+ */
+ glsFboUtil.FboBuilder.prototype.glCreateTexture = function(texCfg) {
+ var texName = glsFboUtil.glsup.create(texCfg, this.m_gl);
+ this.checkError();
+ this.setTexture(texName, texCfg);
+ return texName;
+ };
+
+ /** *generated by script*
+ * @param {glsFboUtil.Renderbuffer} rbCfg
+ * @return {WebGLRenderbuffer}
+ */
+ glsFboUtil.FboBuilder.prototype.glCreateRbo = function(rbCfg) {
+ var rbName = glsFboUtil.glsup.create(rbCfg, this.m_gl);
+ this.checkError();
+ this.setRbo(rbName, rbCfg);
+ return rbName;
+ };
+
+ /**
+ * @param {function(new:glsFboUtil.Config)} Definition
+ * @return {glsFboUtil.Config}
+ */
+ glsFboUtil.FboBuilder.prototype.makeConfig = function(Definition) {
+ var cfg = new Definition();
+ this.m_configs.push(cfg);
+ return cfg;
+ };
+
+ /**
+ */
+ glsFboUtil.FboBuilder.prototype.checkError = function() {
+ var error = this.m_gl.getError();
+ if (error != this.m_gl.NO_ERROR && this.m_error == this.m_gl.NO_ERROR) {
+ this.m_error = error;
+ }
+ };
+
+ /** *generated by script*
+ * @return {number}
+ */
+ glsFboUtil.FboBuilder.prototype.getError = function() {
+ return this.m_error;
+ };
+
+ glsFboUtil.isFramebufferStatus = function(fboStatus) {
+ return gluStrUtil.getFramebufferStatusName(fboStatus) != '';
+ }
+
+ glsFboUtil.isErrorCode = function(errorCode) {
+ return gluStrUtil.getErrorName(errorCode) != '';
+ }
+
+ /**
+ * @typedef {funcion(): glsFboUtil.ValidStatusCodes}
+ */
+ glsFboUtil.ValidStatusCodes = function() {
+ this.m_errorCodes = [];
+ this.m_errorStatusCodes = [];
+ this.m_allowComplete = false;
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.isFBOStatusValid = function(fboStatus) {
+ if (fboStatus == gl.FRAMEBUFFER_COMPLETE)
+ return this.m_allowComplete;
+ else {
+ for(var ndx = 0; ndx < this.m_errorStatusCodes.length; ++ndx) {
+ if (this.m_errorStatusCodes[ndx] == fboStatus)
+ return true;
+ }
+ return false;
+ }
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.isFBOStatusRequired = function(fboStatus) {
+ if (fboStatus == gl.FRAMEBUFFER_COMPLETE)
+ return this.m_allowComplete && this.m_errorStatusCodes.length == 0;
+ else
+ // fboStatus is the only allowed error status and succeeding is forbidden
+ return !this.m_allowComplete && this.m_errorStatusCodes.length == 1 && this.m_errorStatusCodes[0] == fboStatus;
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.isErrorCodeValid = function(errorCode) {
+ if (errorCode == gl.NO_ERROR)
+ return this.m_errorCodes.length == 0;
+ else {
+ // rule violation exists?
+ for (var ndx = 0; ndx < this.m_errorCodes.length; ++ndx) {
+ if (this.m_errorCodes[ndx] == errorCode)
+ return true;
+ }
+ return false;
+ }
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.isErrorCodeRequired = function(errorCode) {
+ if (this.m_errorCodes.length == 0 && errorCode == gl.NO_ERROR)
+ return true;
+ else
+ // only this error code listed
+ return this.m_errorCodes.length == 1 && merrorCodes[0] == errorCode;
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.addErrorCode = function(error) {
+ DE_ASSERT(glsFboUtil.isErrorCode(error));
+ DE_ASSERT(error != gl.NO_ERROR)
+ this.m_errorCodes.push(error);
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.addFBOErrorStatus = function(status) {
+ DE_ASSERT(glsFboUtil.isFramebufferStatus(status));
+ DE_ASSERT(status != gl.FRAMEBUFFER_COMPLETE)
+ this.m_errorStatusCodes.push(status);
+ };
+
+ glsFboUtil.ValidStatusCodes.prototype.setAllowComplete = function(b) {
+ this.m_allowComplete = b;
+ };
+
+ /**
+ * @typedef {function(): glsFboUtil.Checker}
+ */
+ glsFboUtil.CheckerFactory;
+
+ /**
+ * @constructor
+ * @param {WebGLRenderingContextBase=} gl
+ * @throws {Error}
+ */
+ glsFboUtil.Checker = function(gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ this.m_statusCodes = new glsFboUtil.ValidStatusCodes();
+ this.m_statusCodes.setAllowComplete(true);
+
+ if (typeof(this.check) != 'function')
+ throw new Error('Constructor called on virtual class: glsFboUtil.Checker');
+ };
+
+ /**
+ * @param {boolean} condition
+ * @param {number} error
+ */
+ glsFboUtil.Checker.prototype.addGLError = function(condition, error) {
+ if (!condition) {
+ this.m_statusCodes.addErrorCode(error);
+ this.m_statusCodes.setAllowComplete(false);
+ }
+ };
+
+ /**
+ * @param {boolean} condition
+ * @param {number} error
+ */
+ glsFboUtil.Checker.prototype.addPotentialGLError = function(condition, error) {
+ if (!condition) {
+ this.m_statusCodes.addErrorCode(error);
+ }
+ };
+
+ /**
+ * @param {boolean} condition
+ * @param {number} status
+ */
+ glsFboUtil.Checker.prototype.addFBOStatus = function(condition, status) {
+ if (!condition) {
+ this.m_statusCodes.addFBOErrorStatus(status);
+ this.m_statusCodes.setAllowComplete(false);
+ }
+ };
+
+ /**
+ * @param {boolean} condition
+ * @param {number} status
+ */
+ glsFboUtil.Checker.prototype.addPotentialFBOStatus = function(condition, status) {
+ if (!condition) {
+ this.m_statusCodes.addFBOErrorStatus(status);
+ }
+ };
+
+ /**
+ * @return {Array<number>}
+ */
+ glsFboUtil.Checker.prototype.getStatusCodes = function () {
+ return this.m_statusCodes;
+ };
+
+ /**
+ * @param {glsFboUtil.ImageFormat} imgFormat
+ * @param {WebGLRenderingContextBase=} gl
+ * @return {gluTextureUtil.TransferFormat}
+ * @throws {Error}
+ */
+ glsFboUtil.transferImageFormat = function(imgFormat, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+ if (imgFormat.unsizedType == gl.NONE)
+ return gluTextureUtil.getTransferFormat(gluTextureUtil.mapGLInternalFormat(imgFormat.format));
+ else
+ return new gluTextureUtil.TransferFormat(imgFormat.format, imgFormat.unsizedType);
+ };
+
+ // FormatDB, CheckerFactory
+
+ /**
+ * @constructor
+ * @param {glsFboUtil.FormatDB} formats
+ * @param {glsFboUtil.CheckerFactory} factory
+ */
+ glsFboUtil.FboVerifier = function(formats, factory) {
+ this.m_formats = formats;
+ this.m_factory = factory;
+ };
+ // config::Framebuffer
+ glsFboUtil.FboVerifier.prototype.validStatusCodes = function(cfg, gl) {
+ if (!(gl = gl || window.gl)) throw new Error('Invalid gl object');
+
+ /** @type {glsFboUtil.Checker} */
+ var cctx = this.m_factory();
+
+ for (var id = 0; id < cfg.textures.length; ++id) {
+ var flags = this.m_formats.getFormatInfo(cfg.textures.getIndex(id).second.internalFormat, glsFboUtil.FormatFlags.ANY_FORMAT);
+ var textureIsValid = (flags & glsFboUtil.FormatFlags.TEXTURE_VALID) != 0;
+ cctx.addGLError(textureIsValid, gl.INVALID_ENUM);
+ cctx.addGLError(textureIsValid, gl.INVALID_OPERATION);
+ cctx.addGLError(textureIsValid, gl.INVALID_VALUE);
+ }
+
+ for (var id = 0; id < cfg.rbos.length; ++id) {
+ var flags = this.m_formats.getFormatInfo(cfg.rbos.getIndex(id).second.internalFormat, glsFboUtil.FormatFlags.ANY_FORMAT);
+ var rboIsValid = (flags & glsFboUtil.FormatFlags.RENDERBUFFER_VALID) != 0;
+ cctx.addGLError(rboIsValid, gl.INVALID_ENUM);
+ }
+
+ var count = 0;
+ for (var index = 0; index < cfg.attachments.length; ++index) {
+ var attPoint = cfg.attachments.getIndex(index).first;
+ var att = cfg.attachments.getIndex(index).second;
+ /** @type {glsFboUtil.Image}*/
+ var image = cfg.getImage(glsFboUtil.attachmentType(att, gl), att.imageName);
+ glsFboUtil.checkAttachmentCompleteness(cctx, att, attPoint, image, this.m_formats, gl);
+ cctx.check(attPoint, att, image);
+ ++count;
+ }
+
+ // "There is at least one image attached to the framebuffer."
+ // TODO: support XXX_framebuffer_no_attachments
+ cctx.addFBOStatus(count > 0, gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+
+ return cctx.getStatusCodes();
+
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsLifetimeTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsLifetimeTests.js
new file mode 100644
index 0000000000..427a3a4fce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsLifetimeTests.js
@@ -0,0 +1,1118 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+'use strict';
+goog.provide('modules.shared.glsLifetimeTests');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('modules.shared.glsTextureTestUtil');
+
+goog.scope(function() {
+var glsLifetimeTests = modules.shared.glsLifetimeTests;
+var tcuStringTemplate = framework.common.tcuStringTemplate;
+var tcuSurface = framework.common.tcuSurface;
+var deRandom = framework.delibs.debase.deRandom;
+var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuTestCase = framework.common.tcuTestCase;
+var tcuImageCompare = framework.common.tcuImageCompare;
+
+/** @const */ var VIEWPORT_SIZE = 128;
+/** @const */ var FRAMEBUFFER_SIZE = 128;
+
+var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+};
+
+/** @const */ var s_vertexShaderSrc =
+ '#version 100\n' +
+ 'attribute vec2 pos;\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = vec4(pos.xy, 0.0, 1.0);\n' +
+ '}\n';
+
+/** @const */ var s_fragmentShaderSrc =
+ '#version 100\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_FragColor = vec4(1.0);\n' +
+ '}\n';
+
+/**
+ * @constructor
+ * @extends {gluShaderProgram.Shader}
+ * @param {gluShaderProgram.shaderType} type
+ * @param {string} src
+ */
+glsLifetimeTests.CheckedShader = function(type, src) {
+ gluShaderProgram.Shader.call(this, gl, type);
+ this.setSources(src);
+ this.compile();
+ assertMsgOptions(this.getCompileStatus() === true, 'Failed to compile shader', false, true);
+};
+
+setParentClass(glsLifetimeTests.CheckedShader, gluShaderProgram.Shader);
+
+/**
+ * @constructor
+ * @extends {gluShaderProgram.Program}
+ * @param {WebGLShader} vtxShader
+ * @param {WebGLShader} fragShader
+ */
+glsLifetimeTests.CheckedProgram = function(vtxShader, fragShader) {
+ gluShaderProgram.Program.call(this, gl);
+ this.attachShader(vtxShader);
+ this.attachShader(fragShader);
+ this.link();
+ assertMsgOptions(this.info.linkOk === true, 'Failed to link program', false, true);
+};
+
+setParentClass(glsLifetimeTests.CheckedProgram, gluShaderProgram.Program);
+
+/**
+ * @constructor
+ */
+glsLifetimeTests.Binder = function() {
+};
+
+/**
+ * @param {WebGLObject} obj
+ */
+glsLifetimeTests.Binder.prototype.bind = function(obj) { throw new Error('Virtual function'); };
+
+/**
+ * @return {WebGLObject}
+ */
+glsLifetimeTests.Binder.prototype.getBinding = function() { throw new Error('Virtual function'); };
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Binder}
+ * @param {?function(number, ?)} bindFunc
+ * @param {number} bindTarget
+ * @param {number} bindingParam
+ */
+glsLifetimeTests.SimpleBinder = function(bindFunc, bindTarget, bindingParam) {
+ glsLifetimeTests.Binder.call(this);
+ this.m_bindFunc = bindFunc;
+ this.m_bindTarget = bindTarget;
+ this.m_bindingParam = bindingParam;
+};
+
+setParentClass(glsLifetimeTests.SimpleBinder, glsLifetimeTests.Binder);
+
+glsLifetimeTests.SimpleBinder.prototype.bind = function(obj) {
+ this.m_bindFunc.call(gl, this.m_bindTarget, obj);
+};
+
+glsLifetimeTests.SimpleBinder.prototype.getBinding = function() {
+ return /** @type {WebGLObject} */ (gl.getParameter(this.m_bindingParam));
+};
+
+/**
+ * @constructor
+ */
+glsLifetimeTests.Type = function() {
+};
+
+/**
+ * Create a type
+ * @return {WebGLObject}
+ */
+glsLifetimeTests.Type.prototype.gen = function() { throw new Error('Virtual function'); };
+
+/**
+ * Destroy a type
+ * @param {WebGLObject} obj
+ */
+glsLifetimeTests.Type.prototype.release = function(obj) { throw new Error('Virtual function'); };
+
+/**
+ * Is object valid
+ * @param {WebGLObject} obj
+ */
+glsLifetimeTests.Type.prototype.exists = function(obj) { throw new Error('Virtual function'); };
+
+/**
+ * Is object flagged for deletion
+ * @param {WebGLObject} obj
+ */
+glsLifetimeTests.Type.prototype.isDeleteFlagged = function(obj) { return false; };
+
+/**
+ * @return {glsLifetimeTests.Binder}
+ */
+glsLifetimeTests.Type.prototype.binder = function() { return null; };
+
+/**
+ * @return {string}
+ */
+glsLifetimeTests.Type.prototype.getName = function() { throw new Error('Virtual function'); };
+
+/**
+ * Is the object unbound automatically when it is deleted?
+ * @return {boolean}
+ */
+glsLifetimeTests.Type.prototype.nameLingers = function() { return false; };
+
+/**
+ * Does 'create' creates the object fully?
+ * If not, the object is created at bound time
+ * @return {boolean}
+ */
+glsLifetimeTests.Type.prototype.genCreates = function() { return false; };
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Type}
+ * @param {string} name
+ * @param {function(): WebGLObject} genFunc
+ * @param {function(?)} deleteFunc
+ * @param {function(?): boolean} existsFunc
+ * @param {glsLifetimeTests.Binder} binder
+ * @param {boolean=} genCreates
+ */
+glsLifetimeTests.SimpleType = function(name, genFunc, deleteFunc, existsFunc, binder, genCreates) {
+ glsLifetimeTests.Type.call(this);
+ this.m_getName = name;
+ this.m_genFunc = genFunc;
+ this.m_deleteFunc = deleteFunc;
+ this.m_existsFunc = existsFunc;
+ this.m_binder = binder;
+ this.m_genCreates = genCreates || false;
+};
+
+setParentClass(glsLifetimeTests.SimpleType, glsLifetimeTests.Type);
+
+glsLifetimeTests.SimpleType.prototype.gen = function() { return this.m_genFunc.call(gl); };
+
+glsLifetimeTests.SimpleType.prototype.release = function(obj) { return this.m_deleteFunc.call(gl, obj); };
+
+glsLifetimeTests.SimpleType.prototype.exists = function(obj) { return this.m_existsFunc.call(gl, obj); };
+
+glsLifetimeTests.SimpleType.prototype.binder = function() { return this.m_binder; };
+
+glsLifetimeTests.SimpleType.prototype.getName = function() { return this.m_getName; };
+
+glsLifetimeTests.SimpleType.prototype.genCreates = function() { return this.m_genCreates; };
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Type}
+ */
+glsLifetimeTests.ProgramType = function() {
+ glsLifetimeTests.Type.call(this);
+};
+
+setParentClass(glsLifetimeTests.ProgramType, glsLifetimeTests.Type);
+
+glsLifetimeTests.ProgramType.prototype.gen = function() { return gl.createProgram(); };
+
+glsLifetimeTests.ProgramType.prototype.release = function(obj) { return gl.deleteProgram(/** @type {WebGLProgram} */ (obj)); };
+
+glsLifetimeTests.ProgramType.prototype.exists = function(obj) { return gl.isProgram(/** @type {WebGLProgram} */ (obj)); };
+
+glsLifetimeTests.ProgramType.prototype.getName = function() { return 'program'; };
+
+glsLifetimeTests.ProgramType.prototype.genCreates = function() { return true; };
+
+glsLifetimeTests.ProgramType.prototype.nameLingers = function() { return true; };
+
+glsLifetimeTests.ProgramType.prototype.isDeleteFlagged = function(obj) { return gl.getProgramParameter(/** @type {WebGLProgram} */ (obj), gl.DELETE_STATUS); };
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Type}
+ */
+glsLifetimeTests.ShaderType = function() {
+ glsLifetimeTests.Type.call(this);
+};
+
+setParentClass(glsLifetimeTests.ShaderType, glsLifetimeTests.Type);
+
+glsLifetimeTests.ShaderType.prototype.gen = function() { return gl.createShader(gl.FRAGMENT_SHADER); };
+
+glsLifetimeTests.ShaderType.prototype.release = function(obj) { return gl.deleteShader(/** @type {WebGLShader} */ (obj)); };
+
+glsLifetimeTests.ShaderType.prototype.exists = function(obj) { return gl.isShader(/** @type {WebGLShader} */ (obj)); };
+
+glsLifetimeTests.ShaderType.prototype.getName = function() { return 'shader'; };
+
+glsLifetimeTests.ShaderType.prototype.genCreates = function() { return true; };
+
+glsLifetimeTests.ShaderType.prototype.nameLingers = function() { return true; };
+
+glsLifetimeTests.ShaderType.prototype.isDeleteFlagged = function(obj) { return gl.getShaderParameter(/** @type {WebGLShader} */ (obj), gl.DELETE_STATUS); };
+
+/**
+ * @constructor
+ * @param {glsLifetimeTests.Type} elementType
+ * @param {glsLifetimeTests.Type} containerType
+ */
+glsLifetimeTests.Attacher = function(elementType, containerType) {
+ this.m_elementType = elementType;
+ this.m_containerType = containerType;
+};
+
+/**
+ * @param {number} seed
+ * @param {WebGLObject} obj
+ */
+glsLifetimeTests.Attacher.prototype.initAttachment = function(seed, obj) { throw new Error('Virtual function'); };
+
+/**
+ * @param {WebGLObject} element
+ * @param {WebGLObject} target
+ */
+glsLifetimeTests.Attacher.prototype.attach = function(element, target) { throw new Error('Virtual function'); };
+
+/**
+ * @param {WebGLObject} element
+ * @param {WebGLObject} target
+ */
+glsLifetimeTests.Attacher.prototype.detach = function(element, target) { throw new Error('Virtual function'); };
+glsLifetimeTests.Attacher.prototype.canAttachDeleted = function() { return true; };
+
+/**
+ * @return {glsLifetimeTests.Type}
+ */
+glsLifetimeTests.Attacher.prototype.getElementType = function() { return this.m_elementType; };
+
+/**
+ * @return {glsLifetimeTests.Type}
+ */
+glsLifetimeTests.Attacher.prototype.getContainerType = function() { return this.m_containerType; };
+
+/**
+ * @constructor
+ */
+glsLifetimeTests.InputAttacher = function(attacher) {
+ this.m_attacher = attacher;
+};
+
+glsLifetimeTests.InputAttacher.prototype.getAttacher = function() { return this.m_attacher; };
+
+/**
+ * @param {WebGLObject} container
+ * @param {tcuSurface.Surface} dst
+ */
+glsLifetimeTests.InputAttacher.prototype.drawContainer = function(container, dst) { throw new Error('Virtual function'); };
+
+/**
+ * @constructor
+ */
+glsLifetimeTests.OutputAttacher = function(attacher) {
+ this.m_attacher = attacher;
+};
+
+glsLifetimeTests.OutputAttacher.prototype.getAttacher = function() { return this.m_attacher; };
+
+/**
+ * @param {number} seed
+ * @param {WebGLObject} container
+ */
+glsLifetimeTests.OutputAttacher.prototype.setupContainer = function(seed, container) { throw new Error('Virtual function'); };
+
+/**
+ * @param {WebGLObject} attachment
+ * @param {tcuSurface.Surface} dst
+ */
+glsLifetimeTests.OutputAttacher.prototype.drawAttachment = function(attachment, dst) { throw new Error('Virtual function'); };
+
+/**
+ * @constructor
+ */
+glsLifetimeTests.Types = function() {
+ /** @type {Array<glsLifetimeTests.Type>} */ this.m_types = [];
+ /** @type {Array<glsLifetimeTests.Attacher>} */ this.m_attachers = [];
+ /** @type {Array<glsLifetimeTests.InputAttacher>} */ this.m_inAttachers = [];
+ /** @type {Array<glsLifetimeTests.OutputAttacher>} */ this.m_outAttachers = [];
+};
+
+/**
+ * @return {glsLifetimeTests.ProgramType}
+ */
+glsLifetimeTests.Types.prototype.getProgramType = function() { throw new Error('Virtual function'); };
+
+glsLifetimeTests.Types.prototype.getTypes = function() { return this.m_types; };
+
+glsLifetimeTests.Types.prototype.getAttachers = function() { return this.m_attachers; };
+
+glsLifetimeTests.Types.prototype.getInputAttachers = function() { return this.m_inAttachers; };
+
+glsLifetimeTests.Types.prototype.getOutputAttachers = function() { return this.m_outAttachers; };
+
+/**
+ * @param {number} seed
+ * @param {WebGLFramebuffer} fbo
+ */
+glsLifetimeTests.setupFbo = function(seed, fbo) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+
+ if (seed == 0) {
+ gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ } else {
+ var rnd = new deRandom.Random(seed);
+ var width = rnd.getInt(0, FRAMEBUFFER_SIZE);
+ var height = rnd.getInt(0, FRAMEBUFFER_SIZE);
+ var x = rnd.getInt(0, FRAMEBUFFER_SIZE - width);
+ var y = rnd.getInt(0, FRAMEBUFFER_SIZE - height);
+ var r1 = rnd.getFloat();
+ var g1 = rnd.getFloat();
+ var b1 = rnd.getFloat();
+ var a1 = rnd.getFloat();
+ var r2 = rnd.getFloat();
+ var g2 = rnd.getFloat();
+ var b2 = rnd.getFloat();
+ var a2 = rnd.getFloat();
+
+ gl.clearColor(r1, g1, b1, a1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.scissor(x, y, width, height);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(r2, g2, b2, a2);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.disable(gl.SCISSOR_TEST);
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+};
+
+/**
+ * @param {{x: number, y:number, width: number, height: number}} rect
+ * @param {tcuSurface.Surface} dst
+ */
+glsLifetimeTests.readRectangle = function(rect, dst) {
+ dst.readViewport(gl, rect);
+};
+
+/**
+ * @param {WebGLFramebuffer} fbo
+ * @param {tcuSurface.Surface} dst
+ */
+glsLifetimeTests.drawFbo = function(fbo, dst) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ dst.readViewport(gl, [0, 0, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE]);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Attacher}
+ */
+glsLifetimeTests.FboAttacher = function(elementType, containerType) {
+ glsLifetimeTests.Attacher.call(this, elementType, containerType);
+};
+
+setParentClass(glsLifetimeTests.FboAttacher, glsLifetimeTests.Attacher);
+
+glsLifetimeTests.FboAttacher.prototype.initStorage = function() { throw new Error('Virtual function'); };
+
+glsLifetimeTests.FboAttacher.prototype.initAttachment = function(seed, element) {
+ var binder = this.getElementType().binder();
+ var fbo = gl.createFramebuffer();
+
+ binder.bind(element);
+ this.initStorage();
+ binder.bind(null);
+
+ this.attach(element, fbo);
+ glsLifetimeTests.setupFbo(seed, fbo);
+ this.detach(element, fbo);
+
+ gl.deleteFramebuffer(fbo);
+
+ bufferedLogToConsole('Drew to ' + this.getElementType().getName() + ' ' + element + ' with seed ' + seed + '.');
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.InputAttacher}
+ */
+glsLifetimeTests.FboInputAttacher = function(attacher) {
+ glsLifetimeTests.InputAttacher.call(this, attacher);
+};
+
+setParentClass(glsLifetimeTests.FboInputAttacher, glsLifetimeTests.InputAttacher);
+
+glsLifetimeTests.FboInputAttacher.prototype.drawContainer = function(obj, dst) {
+ var fbo = /** @type {WebGLFramebuffer} */ (obj);
+ glsLifetimeTests.drawFbo(fbo, dst);
+ bufferedLogToConsole('Read pixels from framebuffer ' + fbo + ' to output image.');
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.OutputAttacher}
+ */
+glsLifetimeTests.FboOutputAttacher = function(attacher) {
+ glsLifetimeTests.OutputAttacher.call(this, attacher);
+};
+
+setParentClass(glsLifetimeTests.FboOutputAttacher, glsLifetimeTests.OutputAttacher);
+
+glsLifetimeTests.FboOutputAttacher.prototype.setupContainer = function(seed, fbo) {
+ glsLifetimeTests.setupFbo(seed, /** @type {WebGLFramebuffer} */ (fbo));
+ bufferedLogToConsole('Drew to framebuffer ' + fbo + ' with seed ' + seed + '.');
+};
+
+glsLifetimeTests.FboOutputAttacher.prototype.drawAttachment = function(element, dst) {
+ var fbo = gl.createFramebuffer();
+ this.m_attacher.attach(element, fbo);
+ glsLifetimeTests.drawFbo(fbo, dst);
+ this.m_attacher.detach(element, fbo);
+ gl.deleteFramebuffer(fbo);
+ bufferedLogToConsole('Read pixels from ' + this.m_attacher.getElementType().getName() + ' ' + element + ' to output image.');
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.FboAttacher}
+ */
+glsLifetimeTests.TextureFboAttacher = function(elementType, containerType) {
+ glsLifetimeTests.FboAttacher.call(this, elementType, containerType);
+};
+
+setParentClass(glsLifetimeTests.TextureFboAttacher, glsLifetimeTests.FboAttacher);
+
+glsLifetimeTests.TextureFboAttacher.prototype.initStorage = function() {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE, 0,
+ gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, null);
+
+};
+
+glsLifetimeTests.TextureFboAttacher.prototype.attach = function(element, target) {
+ var texture = /** @type {WebGLTexture} */ (element);
+ var fbo = /** @type {WebGLFramebuffer} */ (target);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, texture, 0);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+};
+
+glsLifetimeTests.TextureFboAttacher.prototype.detach = function(texture, target) {
+ var fbo = /** @type {WebGLFramebuffer} */ (target);
+ this.attach(null, fbo);
+};
+
+glsLifetimeTests.getFboAttachment = function(fbo, requiredType) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ var type = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ var name = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ var ret = type == requiredType ? name : null;
+ return ret;
+};
+
+glsLifetimeTests.TextureFboAttacher.prototype.getAttachment = function(fbo) {
+ return glsLifetimeTests.getFboAttachment(fbo, gl.TEXTURE);
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.FboAttacher}
+ */
+glsLifetimeTests.RboFboAttacher = function(elementType, containerType) {
+ glsLifetimeTests.FboAttacher.call(this, elementType, containerType);
+};
+
+setParentClass(glsLifetimeTests.RboFboAttacher, glsLifetimeTests.FboAttacher);
+
+glsLifetimeTests.RboFboAttacher.prototype.initStorage = function() {
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE);
+
+};
+
+glsLifetimeTests.RboFboAttacher.prototype.attach = function(element, target) {
+ var rbo = /** @type {WebGLRenderbuffer} */ (element);
+ var fbo = /** @type {WebGLFramebuffer} */ (target);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+};
+
+glsLifetimeTests.RboFboAttacher.prototype.detach = function(rbo, target) {
+ var fbo = /** @type {WebGLFramebuffer} */ (target);
+ this.attach(null, fbo);
+};
+
+glsLifetimeTests.RboFboAttacher.prototype.getAttachment = function(fbo) {
+ return glsLifetimeTests.getFboAttachment(fbo, gl.RENDERBUFFER);
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Attacher}
+ */
+glsLifetimeTests.ShaderProgramAttacher = function(elementType, containerType) {
+ glsLifetimeTests.Attacher.call(this, elementType, containerType);
+};
+
+setParentClass(glsLifetimeTests.ShaderProgramAttacher, glsLifetimeTests.Attacher);
+
+glsLifetimeTests.ShaderProgramAttacher.prototype.initAttachment = function(seed, obj) {
+ var shader = /** @type {WebGLShader} */ (obj);
+ var s_fragmentShaderTemplate =
+ '#version 100\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_FragColor = vec4(${RED}, ${GREEN}, ${BLUE}, 1.0);\n' +
+ '}';
+
+ var rnd = new deRandom.Random(seed);
+ var params = [];
+ params['RED'] = rnd.getFloat().toString(10);
+ params['GREEN'] = rnd.getFloat().toString(10);
+ params['BLUE'] = rnd.getFloat().toString(10);
+
+ var source = tcuStringTemplate.specialize(s_fragmentShaderTemplate, params);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+ var compileStatus = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+ assertMsgOptions(compileStatus === true, 'Failed to compile shader: ' + source, false, true);
+};
+
+glsLifetimeTests.ShaderProgramAttacher.prototype.attach = function(element, target) {
+ var shader = /** @type {WebGLShader} */ (element);
+ var program = /** @type {WebGLProgram} */ (target);
+ gl.attachShader(program, shader);
+};
+
+glsLifetimeTests.ShaderProgramAttacher.prototype.detach = function(element, target) {
+ var shader = /** @type {WebGLShader} */ (element);
+ var program = /** @type {WebGLProgram} */ (target);
+ gl.detachShader(program, shader);
+};
+
+glsLifetimeTests.ShaderProgramAttacher.prototype.getAttachment = function(program) {
+ var shaders = gl.getAttachedShaders(program);
+ for (var i = 0; i < shaders.length; i++) {
+ var shader = shaders[i];
+ var type = gl.getShaderParameter(shader, gl.SHADER_TYPE);
+ if (type === gl.FRAGMENT_SHADER)
+ return shader;
+ }
+ return null;
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.InputAttacher}
+ */
+glsLifetimeTests.ShaderProgramInputAttacher = function(attacher) {
+ glsLifetimeTests.InputAttacher.call(this, attacher);
+};
+
+setParentClass(glsLifetimeTests.ShaderProgramInputAttacher, glsLifetimeTests.InputAttacher);
+
+glsLifetimeTests.ShaderProgramInputAttacher.prototype.drawContainer = function(container, dst) {
+ var program = /** @type {WebGLProgram} */ (container);
+ var s_vertices = [-1.0, 0.0, 1.0, 1.0, 0.0, -1.0];
+ glsLifetimeTests.ShaderProgramInputAttacher.seed = glsLifetimeTests.ShaderProgramInputAttacher.seed || 0;
+ var vtxShader = new glsLifetimeTests.CheckedShader(gluShaderProgram.shaderType.VERTEX, s_vertexShaderSrc);
+ var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_SIZE, VIEWPORT_SIZE, glsLifetimeTests.ShaderProgramInputAttacher.seed);
+
+ gl.attachShader(program, vtxShader.getShader());
+ gl.linkProgram(program);
+
+ var linkStatus = gl.getProgramParameter(program, gl.LINK_STATUS);
+ assertMsgOptions(linkStatus === true, 'Program link failed', false, true);
+
+ bufferedLogToConsole('Attached a temporary vertex shader and linked program ' + program);
+
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ bufferedLogToConsole('Positioned viewport randomly');
+
+ gl.useProgram(program);
+
+ var posLoc = gl.getAttribLocation(program, 'pos');
+ assertMsgOptions(posLoc >= 0, 'Could not find pos attribute', false, true);
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(s_vertices), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(posLoc);
+ gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ gl.disableVertexAttribArray(posLoc);
+ gl.deleteBuffer(buf);
+ bufferedLogToConsole('Drew a fixed triangle');
+
+ gl.useProgram(null);
+
+ glsLifetimeTests.readRectangle(viewport, dst);
+ bufferedLogToConsole('Copied viewport to output image');
+
+ gl.detachShader(program, vtxShader.getShader());
+ bufferedLogToConsole('Removed temporary vertex shader');
+};
+
+/**
+ * @constructor
+ * @extends {glsLifetimeTests.Types}
+ */
+glsLifetimeTests.ES2Types = function() {
+ glsLifetimeTests.Types.call(this);
+ this.m_bufferBind = new glsLifetimeTests.SimpleBinder(gl.bindBuffer, gl.ARRAY_BUFFER, gl.ARRAY_BUFFER_BINDING);
+ this.m_bufferType = new glsLifetimeTests.SimpleType('buffer', gl.createBuffer, gl.deleteBuffer, gl.isBuffer, this.m_bufferBind);
+ this.m_textureBind = new glsLifetimeTests.SimpleBinder(gl.bindTexture, gl.TEXTURE_2D, gl.TEXTURE_BINDING_2D);
+ this.m_textureType = new glsLifetimeTests.SimpleType('texture', gl.createTexture, gl.deleteTexture, gl.isTexture, this.m_textureBind);
+ this.m_rboBind = new glsLifetimeTests.SimpleBinder(gl.bindRenderbuffer, gl.RENDERBUFFER, gl.RENDERBUFFER_BINDING);
+ this.m_rboType = new glsLifetimeTests.SimpleType('renderbuffer', gl.createRenderbuffer, gl.deleteRenderbuffer, gl.isRenderbuffer, this.m_rboBind);
+ this.m_fboBind = new glsLifetimeTests.SimpleBinder(gl.bindFramebuffer, gl.FRAMEBUFFER, gl.FRAMEBUFFER_BINDING);
+ this.m_fboType = new glsLifetimeTests.SimpleType('framebuffer', gl.createFramebuffer, gl.deleteFramebuffer, gl.isFramebuffer, this.m_fboBind);
+ this.m_shaderType = new glsLifetimeTests.ShaderType();
+ this.m_programType = new glsLifetimeTests.ProgramType();
+ this.m_texFboAtt = new glsLifetimeTests.TextureFboAttacher(this.m_textureType, this.m_fboType);
+ this.m_texFboInAtt = new glsLifetimeTests.FboInputAttacher(this.m_texFboAtt);
+ this.m_texFboOutAtt = new glsLifetimeTests.FboOutputAttacher(this.m_texFboAtt);
+ this.m_rboFboAtt = new glsLifetimeTests.RboFboAttacher(this.m_rboType, this.m_fboType);
+ this.m_rboFboInAtt = new glsLifetimeTests.FboInputAttacher(this.m_rboFboAtt);
+ this.m_rboFboOutAtt = new glsLifetimeTests.FboOutputAttacher(this.m_rboFboAtt);
+ this.m_shaderAtt = new glsLifetimeTests.ShaderProgramAttacher(this.m_shaderType, this.m_programType);
+ this.m_shaderInAtt = new glsLifetimeTests.ShaderProgramInputAttacher(this.m_shaderAtt);
+
+ this.m_types.push(this.m_bufferType, this.m_textureType, this.m_rboType, this.m_fboType, this.m_shaderType, this.m_programType);
+ this.m_attachers.push(this.m_texFboAtt, this.m_rboFboAtt, this.m_shaderAtt);
+ this.m_inAttachers.push(this.m_texFboInAtt, this.m_rboFboInAtt, this.m_shaderInAtt);
+ this.m_outAttachers.push(this.m_texFboOutAtt, this.m_rboFboOutAtt);
+};
+
+setParentClass(glsLifetimeTests.ES2Types, glsLifetimeTests.Types);
+
+glsLifetimeTests.ES2Types.prototype.getProgramType = function() { return this.m_programType; };
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {glsLifetimeTests.Type} type
+ * @param {function()} test
+ */
+glsLifetimeTests.LifeTest = function(name, description, type, test) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_type = type;
+ this.m_test = test;
+};
+
+setParentClass(glsLifetimeTests.LifeTest, tcuTestCase.DeqpTest);
+
+glsLifetimeTests.LifeTest.prototype.iterate = function() {
+ this.m_test();
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @this {glsLifetimeTests.LifeTest}
+ */
+glsLifetimeTests.LifeTest.testGen = function() {
+ var obj = this.m_type.gen();
+ if (this.m_type.genCreates())
+ assertMsgOptions(this.m_type.exists(obj), "create* should have created an object, but didn't", false, true);
+ else
+ assertMsgOptions(!this.m_type.exists(obj), 'create* should not have created an object, but did', false, true);
+ this.m_type.release(obj);
+ testPassed();
+};
+
+/**
+ * @this {glsLifetimeTests.LifeTest}
+ */
+glsLifetimeTests.LifeTest.testDelete = function() {
+ var obj = this.m_type.gen();
+ this.m_type.release(obj);
+ assertMsgOptions(!this.m_type.exists(obj), 'Object still exists after deletion', false, true);
+ testPassed();
+};
+
+/**
+ * @this {glsLifetimeTests.LifeTest}
+ */
+glsLifetimeTests.LifeTest.testBind = function() {
+ var obj = this.m_type.gen();
+ this.m_type.binder().bind(obj);
+ var err = gl.getError();
+ assertMsgOptions(err == gl.NONE, 'Bind failed', false, true);
+ assertMsgOptions(this.m_type.exists(obj), 'Object does not exist after binding', false, true);
+ this.m_type.binder().bind(null);
+ this.m_type.release(obj);
+ testPassed();
+};
+
+/**
+ * @this {glsLifetimeTests.LifeTest}
+ */
+glsLifetimeTests.LifeTest.testDeleteBound = function() {
+ var obj = this.m_type.gen();
+ this.m_type.binder().bind(obj);
+ this.m_type.release(obj);
+ if (this.m_type.nameLingers()) {
+ assertMsgOptions(gl.getError() == gl.NONE, 'Deleting bound object failed', false, true);
+ assertMsgOptions(this.m_type.binder().getBinding() === obj, 'Deleting bound object did not retain binding', false, true);
+ assertMsgOptions(this.m_type.exists(obj), 'Deleting bound object made its name invalid', false, true);
+ assertMsgOptions(this.m_type.isDeleteFlagged(obj), 'Deleting bound object did not flag the object for deletion', false, true);
+ this.m_type.binder().bind(null);
+ } else {
+ assertMsgOptions(gl.getError() == gl.NONE, 'Deleting bound object failed', false, true);
+ assertMsgOptions(this.m_type.binder().getBinding() === null, 'Deleting bound object did not remove binding', false, true);
+ assertMsgOptions(!this.m_type.exists(obj), 'Deleting bound object did not make its name invalid', false, true);
+ }
+ assertMsgOptions(this.m_type.binder().getBinding() === null, "Unbinding didn't remove binding", false, true);
+ assertMsgOptions(!this.m_type.exists(obj), 'Name is still valid after deleting and unbinding', false, true);
+ testPassed();
+};
+
+/**
+ * @this {glsLifetimeTests.LifeTest}
+ */
+glsLifetimeTests.LifeTest.testDeleteUsed = function() {
+ var vtxShader = new glsLifetimeTests.CheckedShader(gluShaderProgram.shaderType.VERTEX, s_vertexShaderSrc);
+ var fragShader = new glsLifetimeTests.CheckedShader(gluShaderProgram.shaderType.FRAGMENT, s_fragmentShaderSrc);
+ var program = new glsLifetimeTests.CheckedProgram(vtxShader.getShader(), fragShader.getShader());
+ var programId = program.getProgram();
+ bufferedLogToConsole('Created and linked program ' + programId);
+ gl.useProgram(programId);
+
+ gl.deleteProgram(programId);
+ bufferedLogToConsole('Deleted program ' + programId);
+ assertMsgOptions(gl.isProgram(programId), 'Deleted current program', false, true);
+ var deleteFlagged = gl.getProgramParameter(programId, gl.DELETE_STATUS);
+ assertMsgOptions(deleteFlagged == true, 'Program object was not flagged as deleted', false, true);
+ gl.useProgram(null);
+ assertMsgOptions(!gl.isProgram(programId), 'Deleted program name still valid after being made non-current', false, true);
+ testPassed();
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {glsLifetimeTests.Attacher} attacher
+ * @param {function()} test
+ */
+glsLifetimeTests.AttachmentTest = function(name, description, attacher, test) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_attacher = attacher;
+ this.m_test = test;
+};
+
+setParentClass(glsLifetimeTests.AttachmentTest, tcuTestCase.DeqpTest);
+
+glsLifetimeTests.AttachmentTest.prototype.iterate = function() {
+ this.m_test();
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @this {glsLifetimeTests.AttachmentTest}
+ */
+glsLifetimeTests.AttachmentTest.testDeletedNames = function() {
+ var getAttachment = function(attacher, container) {
+ var queriedAttachment = attacher.getAttachment(container);
+ bufferedLogToConsole('Result of query for ' + attacher.getElementType().getName() +
+ ' attached to ' + attacher.getContainerType().getName() + ' ' +
+ container + ': ' + queriedAttachment);
+ return queriedAttachment;
+ };
+
+ var elemType = this.m_attacher.getElementType();
+ var containerType = this.m_attacher.getContainerType();
+ var container = containerType.gen();
+
+ var element = elemType.gen();
+ this.m_attacher.initAttachment(0, element);
+ this.m_attacher.attach(element, container);
+ assertMsgOptions(getAttachment(this.m_attacher, container) == element,
+ 'Attachment not returned by query even before deletion.', false, true);
+
+ elemType.release(element);
+ // "Such a container or other context may continue using the object, and
+ // may still contain state identifying its name as being currently bound"
+ //
+ // We here interpret "may" to mean that whenever the container has a
+ // deleted object attached to it, a query will return that object's former
+ // name.
+ assertMsgOptions(getAttachment(this.m_attacher, container) == element,
+ 'Attachment name not returned by query after attachment was deleted.', false, true);
+
+ if (elemType.nameLingers())
+ assertMsgOptions(elemType.exists(element),
+ 'Attached object name no longer valid after deletion.', false, true);
+ else
+ assertMsgOptions(!elemType.exists(element),
+ 'Attached object name still valid after deletion.', false, true);
+
+ this.m_attacher.detach(element, container);
+ assertMsgOptions(getAttachment(this.m_attacher, container) == null,
+ 'Attachment name returned by query even after detachment.', false, true);
+ assertMsgOptions(!elemType.exists(element),
+ 'Deleted attached object name still usable after detachment.', false, true);
+ testPassed();
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {glsLifetimeTests.InputAttacher} attacher
+ */
+glsLifetimeTests.InputAttachmentTest = function(name, description, attacher) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_inputAttacher = attacher;
+};
+
+setParentClass(glsLifetimeTests.InputAttachmentTest, tcuTestCase.DeqpTest);
+
+glsLifetimeTests.InputAttachmentTest.prototype.iterate = function() {
+ var attacher = this.m_inputAttacher.getAttacher();
+ var containerType = attacher.getContainerType();
+ var elementType = attacher.getElementType();
+ var container = containerType.gen();
+
+ glsLifetimeTests.InputAttachmentTest.seed = glsLifetimeTests.InputAttachmentTest.seed || 0;
+ ++glsLifetimeTests.InputAttachmentTest.seed;
+ var rnd = new deRandom.Random(glsLifetimeTests.InputAttachmentTest.seed);
+ var refSeed = rnd.getInt();
+ var newSeed = rnd.getInt();
+
+ var refSurface = new tcuSurface.Surface(VIEWPORT_SIZE, VIEWPORT_SIZE); // Surface from drawing with refSeed-seeded attachment
+ var delSurface = new tcuSurface.Surface(VIEWPORT_SIZE, VIEWPORT_SIZE); // Surface from drawing with deleted refSeed attachment
+ var newSurface = new tcuSurface.Surface(VIEWPORT_SIZE, VIEWPORT_SIZE); // Surface from drawing with newSeed-seeded attachment
+
+ bufferedLogToConsole('Testing if writing to a newly created object modifies a deleted attachment');
+
+ bufferedLogToConsole('Writing to an original attachment');
+ var element = elementType.gen();
+
+ attacher.initAttachment(refSeed, element);
+ attacher.attach(element, container);
+ this.m_inputAttacher.drawContainer(container, refSurface);
+ // element gets deleted here
+ bufferedLogToConsole('Deleting attachment');
+ elementType.release(element);
+
+ bufferedLogToConsole('Writing to a new attachment after deleting the original');
+ var newElement = elementType.gen();
+
+ attacher.initAttachment(newSeed, newElement);
+
+ this.m_inputAttacher.drawContainer(container, delSurface);
+ attacher.detach(element, container);
+
+ attacher.attach(newElement, container);
+ this.m_inputAttacher.drawContainer(container, newSurface);
+ attacher.detach(newElement, container);
+ var surfacesMatch = tcuImageCompare.pixelThresholdCompare(
+ 'Reading from deleted',
+ 'Comparison result from reading from a container with a deleted attachment ' +
+ 'before and after writing to a fresh object.',
+ refSurface, delSurface, [0, 0, 0, 0]);
+
+ /* TODO: Add logging images */
+ // if (!surfacesMatch)
+ // log() << TestLog::Image("New attachment",
+ // "Container state after attached to the fresh object",
+ // newSurface);
+
+ assertMsgOptions(surfacesMatch,
+ 'Writing to a fresh object modified the container with a deleted attachment.', false, true);
+
+ testPassed();
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {glsLifetimeTests.OutputAttacher} attacher
+ */
+glsLifetimeTests.OutputAttachmentTest = function(name, description, attacher) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ this.m_outputAttacher = attacher;
+};
+
+setParentClass(glsLifetimeTests.OutputAttachmentTest, tcuTestCase.DeqpTest);
+
+glsLifetimeTests.OutputAttachmentTest.prototype.iterate = function() {
+ var attacher = this.m_outputAttacher.getAttacher();
+ var containerType = attacher.getContainerType();
+ var elementType = attacher.getElementType();
+ var container = containerType.gen();
+ glsLifetimeTests.InputAttachmentTest.seed = glsLifetimeTests.InputAttachmentTest.seed || 0;
+ ++glsLifetimeTests.InputAttachmentTest.seed;
+ var rnd = new deRandom.Random(glsLifetimeTests.InputAttachmentTest.seed);
+ var refSeed = rnd.getInt();
+ var newSeed = rnd.getInt();
+
+ var refSurface = new tcuSurface.Surface(VIEWPORT_SIZE, VIEWPORT_SIZE); // Surface from drawing with refSeed-seeded attachment
+ var delSurface = new tcuSurface.Surface(VIEWPORT_SIZE, VIEWPORT_SIZE); // Surface from drawing with deleted refSeed attachment
+ var newSurface = new tcuSurface.Surface(VIEWPORT_SIZE, VIEWPORT_SIZE); // Surface from drawing with newSeed-seeded attachment
+
+ bufferedLogToConsole('Testing if writing to a container with a deleted attachment ' +
+ 'modifies a newly created object');
+
+ bufferedLogToConsole('Writing to a container with an existing attachment');
+ var element = elementType.gen();
+
+ attacher.initAttachment(0, element);
+ attacher.attach(element, container);
+
+ // For reference purposes, make note of what refSeed looks like.
+ this.m_outputAttacher.setupContainer(refSeed, container);
+ // Since in WebGL, buffer bound to TRANSFORM_FEEDBACK_BUFFER can not be bound to other targets.
+ // Unfortunately, element will be bound again in drawAttachment() for drawing.
+ // Detach element from container before drawing, then reattach it after drawing.
+ attacher.detach(element, container);
+ this.m_outputAttacher.drawAttachment(element, refSurface);
+ attacher.attach(element, container);
+ elementType.release(element);
+
+ bufferedLogToConsole('Writing to a container after deletion of attachment');
+ var newElement = elementType.gen();
+ bufferedLogToConsole('Creating a new object ');
+
+ bufferedLogToConsole('Recording state of new object before writing to container');
+ attacher.initAttachment(newSeed, newElement);
+ this.m_outputAttacher.drawAttachment(newElement, newSurface);
+
+ bufferedLogToConsole('Writing to container');
+
+ // Now re-write refSeed to the container.
+ this.m_outputAttacher.setupContainer(refSeed, container);
+ // Does it affect the newly created attachment object?
+ this.m_outputAttacher.drawAttachment(newElement, delSurface);
+ attacher.detach(element, container);
+
+ var surfacesMatch = tcuImageCompare.pixelThresholdCompare(
+ 'Writing to deleted',
+ 'Comparison result from reading from a fresh object before and after ' +
+ 'writing to a container with a deleted attachment',
+ newSurface, delSurface, [0, 0, 0, 0]);
+
+ /* TODO: Add logging images */
+ // if (!surfacesMatch)
+ // log() << TestLog::Image(
+ // "Original attachment",
+ // "Result of container modification on original attachment before deletion.",
+ // refSurface);
+
+ assertMsgOptions(surfacesMatch,
+ 'Writing to container with deleted attachment modified a new object.', false, true);
+
+ testPassed();
+ return tcuTestCase.IterateResult.STOP;
+};
+
+glsLifetimeTests.createLifeTestGroup = function(spec, types) {
+ var group = tcuTestCase.newTest(spec.name, spec.name);
+
+ for (var i = 0; i < types.length; i++) {
+ var type = types[i];
+ var name = type.getName();
+ if (!spec.needBind || type.binder() != null)
+ group.addChild(new glsLifetimeTests.LifeTest(name, name, type, spec.func));
+ }
+
+ return group;
+};
+
+/**
+ * @param {tcuTestCase.DeqpTest} group
+ * @param {glsLifetimeTests.Types} types
+ */
+glsLifetimeTests.addTestCases = function(group, types) {
+ var attacherName = function(attacher) {
+ return attacher.getElementType().getName() + '_' + attacher.getContainerType().getName();
+ };
+
+ var s_lifeTests = [
+ /* Create */ { name: 'gen', func: glsLifetimeTests.LifeTest.testGen, needBind: false },
+ /* Delete */ { name: 'delete', func: glsLifetimeTests.LifeTest.testDelete, needBind: false },
+ /* Bind */ { name: 'bind', func: glsLifetimeTests.LifeTest.testBind, needBind: true },
+ /* Delete bound */ { name: 'delete_bound', func: glsLifetimeTests.LifeTest.testDeleteBound, needBind: true }
+ ];
+
+ s_lifeTests.forEach(function(spec) {
+ group.addChild(glsLifetimeTests.createLifeTestGroup(spec, types.getTypes()));
+ });
+
+ var delUsedGroup = tcuTestCase.newTest('delete_used', 'Delete current program');
+ group.addChild(delUsedGroup);
+
+ delUsedGroup.addChild(new glsLifetimeTests.LifeTest('program', 'program', types.getProgramType(),
+ glsLifetimeTests.LifeTest.testDeleteUsed));
+
+ var attGroup = tcuTestCase.newTest('attach', 'Attachment tests');
+ group.addChild(attGroup);
+
+ var nameGroup = tcuTestCase.newTest('deleted_name', 'Name of deleted attachment');
+ attGroup.addChild(nameGroup);
+
+ var atts = types.getAttachers();
+ for (var i = 0; i < atts.length; i++) {
+ var att = atts[i];
+ var name = attacherName(att);
+ nameGroup.addChild(new glsLifetimeTests.AttachmentTest(name, name, att,
+ glsLifetimeTests.AttachmentTest.testDeletedNames));
+ }
+
+ var inputGroup = tcuTestCase.newTest('deleted_input', 'Input from deleted attachment');
+ attGroup.addChild(inputGroup);
+
+ var inAtts = types.getInputAttachers();
+ for (var i = 0; i < inAtts.length; i++) {
+ var att = inAtts[i];
+ var name = attacherName(att.getAttacher());
+ inputGroup.addChild(new glsLifetimeTests.InputAttachmentTest(name, name, att));
+ }
+
+ var outputGroup = tcuTestCase.newTest('deleted_output', 'Output to deleted attachment');
+ attGroup.addChild(outputGroup);
+
+ var outAtts = types.getOutputAttachers();
+ for (var i = 0; i < outAtts.length; i++) {
+ var att = outAtts[i];
+ var name = attacherName(att.getAttacher());
+ outputGroup.addChild(new glsLifetimeTests.OutputAttachmentTest(name, name, att));
+ }
+
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsRandomUniformBlockCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsRandomUniformBlockCase.js
new file mode 100644
index 0000000000..20b8dcd472
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsRandomUniformBlockCase.js
@@ -0,0 +1,282 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsRandomUniformBlockCase');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('modules.shared.glsUniformBlockCase');
+
+goog.scope(function() {
+
+ var glsRandomUniformBlockCase = modules.shared.glsRandomUniformBlockCase;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var glsUniformBlockCase = modules.shared.glsUniformBlockCase;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+
+ glsRandomUniformBlockCase.FeatureBits = {
+ FEATURE_VECTORS: (1 << 0),
+ FEATURE_MATRICES: (1 << 1),
+ FEATURE_ARRAYS: (1 << 2),
+ FEATURE_STRUCTS: (1 << 3),
+ FEATURE_NESTED_STRUCTS: (1 << 4),
+ FEATURE_INSTANCE_ARRAYS: (1 << 5),
+ FEATURE_VERTEX_BLOCKS: (1 << 6),
+ FEATURE_FRAGMENT_BLOCKS: (1 << 7),
+ FEATURE_SHARED_BLOCKS: (1 << 8),
+ FEATURE_UNUSED_UNIFORMS: (1 << 9),
+ FEATURE_UNUSED_MEMBERS: (1 << 10),
+ FEATURE_PACKED_LAYOUT: (1 << 11),
+ FEATURE_SHARED_LAYOUT: (1 << 12),
+ FEATURE_STD140_LAYOUT: (1 << 13),
+ FEATURE_MATRIX_LAYOUT: (1 << 14), //!< Matrix layout flags.
+ FEATURE_ARRAYS_OF_ARRAYS: (1 << 15)
+ };
+
+ /**
+ * glsRandomUniformBlockCase.RandomUniformBlockCase class
+ * @param {string} name
+ * @param {string} description
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @param {number} features
+ * @param {number} seed
+ * @constructor
+ * @extends {glsUniformBlockCase.UniformBlockCase}
+ */
+ glsRandomUniformBlockCase.RandomUniformBlockCase = function(name, description, bufferMode, features, seed) {
+ glsUniformBlockCase.UniformBlockCase.call(this, name, description, bufferMode);
+ this.m_features = features;
+ this.m_maxVertexBlocks = ((features & glsRandomUniformBlockCase.FeatureBits.FEATURE_VERTEX_BLOCKS) ? 4 : 0);
+ this.m_maxFragmentBlocks = ((features & glsRandomUniformBlockCase.FeatureBits.FEATURE_FRAGMENT_BLOCKS) ? 4 : 0);
+ this.m_maxSharedBlocks = ((features & glsRandomUniformBlockCase.FeatureBits.FEATURE_SHARED_BLOCKS) ? 4 : 0);
+ this.m_maxInstances = ((features & glsRandomUniformBlockCase.FeatureBits.FEATURE_INSTANCE_ARRAYS) ? 3 : 0);
+ this.m_maxArrayLength = ((features & glsRandomUniformBlockCase.FeatureBits.FEATURE_ARRAYS) ? 8 : 0);
+ this.m_maxStructDepth = ((features & glsRandomUniformBlockCase.FeatureBits.FEATURE_STRUCTS) ? 2 : 0);
+ this.m_maxBlockMembers = 5;
+ this.m_maxStructMembers = 4;
+ this.m_seed = seed;
+ this.m_blockNdx = 1;
+ this.m_uniformNdx = 1;
+ this.m_structNdx = 1;
+ };
+
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype = Object.create(glsUniformBlockCase.UniformBlockCase.prototype);
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype.constructor = glsRandomUniformBlockCase.RandomUniformBlockCase;
+
+ /**
+ * generateType
+ * @param {deRandom.Random} rnd
+ * @param {number} typeDepth
+ * @param {boolean} arrayOk
+ * @return {glsUniformBlockCase.VarType}
+ */
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype.generateType = function(rnd, typeDepth, arrayOk) {
+ /** @type {number} */ var structWeight = 0.1;
+ /** @type {number} */ var arrayWeight = 0.1;
+ /** @type {number} */ var flags;
+
+ if (typeDepth < this.m_maxStructDepth && rnd.getFloat() < structWeight) {
+ /** @type {number} */ var unusedVtxWeight = 0.15;
+ /** @type {number} */ var unusedFragWeight = 0.15;
+ /** @type {boolean} */ var unusedOk = (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_UNUSED_MEMBERS) != 0;
+ /** @type {Array<glsUniformBlockCase.VarType>} */ var memberTypes = [];
+ /** @type {number} */ var numMembers = rnd.getInt(1, this.m_maxStructMembers);
+
+ // Generate members first so nested struct declarations are in correct order.
+ for (var ndx = 0; ndx < numMembers; ndx++)
+ memberTypes.push(this.generateType(rnd, typeDepth + 1, true));
+
+ /** @type {glsUniformBlockCase.StructType} */ var structType = this.m_interface.allocStruct('s' + this.genName('A'.charCodeAt(0), 'Z'.charCodeAt(0), this.m_structNdx));
+ this.m_structNdx += 1;
+
+ assertMsgOptions(this.m_blockNdx <= 'Z'.charCodeAt(0) - 'A'.charCodeAt(0), 'generateType', false, true);
+ for (var ndx = 0; ndx < numMembers; ndx++) {
+ flags = 0;
+
+ flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? glsUniformBlockCase.UniformFlags.UNUSED_VERTEX : 0;
+ flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT : 0;
+
+ structType.addMember('m' + ('A'.charCodeAt(0) + ndx), memberTypes[ndx], flags);
+ }
+
+ return glsUniformBlockCase.newVarTypeStruct(structType);
+ } else if (this.m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight) {
+ /** @type {boolean} */ var arraysOfArraysOk = (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_ARRAYS_OF_ARRAYS) != 0;
+ /** @type {number} */ var arrayLength = rnd.getInt(1, this.m_maxArrayLength);
+ /** @type {glsUniformBlockCase.VarType} */ var elementType = this.generateType(rnd, typeDepth, arraysOfArraysOk);
+ return glsUniformBlockCase.newVarTypeArray(elementType, arrayLength);
+ } else {
+ /** @type {Array<gluShaderUtil.DataType>} */ var typeCandidates = [];
+
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT);
+ typeCandidates.push(gluShaderUtil.DataType.INT);
+ typeCandidates.push(gluShaderUtil.DataType.UINT);
+ typeCandidates.push(gluShaderUtil.DataType.BOOL);
+
+ if (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_VECTORS) {
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_VEC2);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_VEC3);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_VEC4);
+ typeCandidates.push(gluShaderUtil.DataType.INT_VEC2);
+ typeCandidates.push(gluShaderUtil.DataType.INT_VEC3);
+ typeCandidates.push(gluShaderUtil.DataType.INT_VEC4);
+ typeCandidates.push(gluShaderUtil.DataType.UINT_VEC2);
+ typeCandidates.push(gluShaderUtil.DataType.UINT_VEC3);
+ typeCandidates.push(gluShaderUtil.DataType.UINT_VEC4);
+ typeCandidates.push(gluShaderUtil.DataType.BOOL_VEC2);
+ typeCandidates.push(gluShaderUtil.DataType.BOOL_VEC3);
+ typeCandidates.push(gluShaderUtil.DataType.BOOL_VEC4);
+ }
+
+ if (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_MATRICES) {
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT2);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT2X3);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT3X2);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT3);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT3X4);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT4X2);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT4X3);
+ typeCandidates.push(gluShaderUtil.DataType.FLOAT_MAT4);
+ }
+
+ /** @type {gluShaderUtil.DataType} */ var type = (rnd.choose(typeCandidates)[0]);
+ flags = 0;
+
+ if (!gluShaderUtil.isDataTypeBoolOrBVec(type)) {
+ // Precision.
+ /** @type {Array<number>} */ var precisionCandidates = [glsUniformBlockCase.UniformFlags.PRECISION_LOW, glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM, glsUniformBlockCase.UniformFlags.PRECISION_HIGH];
+ flags |= rnd.choose(precisionCandidates)[0];
+ }
+
+ return glsUniformBlockCase.newVarTypeBasic(type, flags);
+ }
+ };
+
+ /**
+ * genName
+ * @param {number} first
+ * @param {number} last
+ * @param {number} ndx
+ * @return {string}
+ */
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype.genName = function(first, last, ndx) {
+ /** @type {string} */ var str = '';
+ /** @type {number} */ var alphabetLen = last - first + 1;
+
+ while (ndx > alphabetLen) {
+ str = String.fromCharCode(first + ((ndx - 1) % alphabetLen)) + str;
+ ndx = Math.floor((ndx - 1) / alphabetLen);
+ }
+
+ str = String.fromCharCode(first + (ndx % (alphabetLen + 1)) - 1) + str;
+
+ return str;
+ };
+
+ /**
+ * generateUniform
+ * @param {deRandom.Random} rnd
+ * @param {glsUniformBlockCase.UniformBlock} block
+ */
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype.generateUniform = function(rnd, block) {
+ /** @type {number} */ var unusedVtxWeight = 0.15;
+ /** @type {number} */ var unusedFragWeight = 0.15;
+ /** @type {boolean} */ var unusedOk = (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_UNUSED_UNIFORMS) != 0;
+ /** @type {number} */ var flags = 0;
+ /** @type {string} */ var name = this.genName('a'.charCodeAt(0), 'z'.charCodeAt(0), this.m_uniformNdx);
+ /** @type {glsUniformBlockCase.VarType} */ var type = this.generateType(rnd, 0, true); //TODO: implement this.
+
+ flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? glsUniformBlockCase.UniformFlags.UNUSED_VERTEX : 0;
+ flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT : 0;
+
+ block.addUniform(new glsUniformBlockCase.Uniform(name, type, flags));
+
+ this.m_uniformNdx += 1;
+ };
+
+ /**
+ * generateBlock
+ * @param {deRandom.Random} rnd
+ * @param {number} layoutFlags
+ */
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype.generateBlock = function(rnd, layoutFlags) {
+ assertMsgOptions(this.m_blockNdx <= 'z'.charCodeAt(0) - 'a'.charCodeAt(0), 'generateBlock', false, true);
+
+ /** @type {number} */ var instanceArrayWeight = 0.3;
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.allocBlock('Block' + String.fromCharCode('A'.charCodeAt(0) + this.m_blockNdx));
+ /** @type {number} */ var numInstances = (this.m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, this.m_maxInstances) : 0;
+ /** @type {number} */ var numUniforms = rnd.getInt(1, this.m_maxBlockMembers);
+
+ if (numInstances > 0)
+ block.setArraySize(numInstances);
+
+ if (numInstances > 0 || rnd.getBool())
+ block.setInstanceName('block' + String.fromCharCode('A'.charCodeAt(0) + this.m_blockNdx));
+
+ // Layout flag candidates.
+ /** @type {Array<number>} */ var layoutFlagCandidates = [];
+ layoutFlagCandidates.push(0);
+ if (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_PACKED_LAYOUT)
+ layoutFlagCandidates.push(glsUniformBlockCase.UniformFlags.LAYOUT_SHARED);
+ if ((this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_SHARED_LAYOUT) && ((layoutFlags & glsUniformBlockCase.UniformFlags.DECLARE_BOTH) != glsUniformBlockCase.UniformFlags.DECLARE_BOTH))
+ layoutFlagCandidates.push(glsUniformBlockCase.UniformFlags.LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
+ if (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_STD140_LAYOUT)
+ layoutFlagCandidates.push(glsUniformBlockCase.UniformFlags.LAYOUT_STD140);
+
+ layoutFlags |= rnd.choose(layoutFlagCandidates)[0]; //In Javascript, this function returns an array, so taking element 0.
+
+ if (this.m_features & glsRandomUniformBlockCase.FeatureBits.FEATURE_MATRIX_LAYOUT) {
+ /** @type {Array<number>}*/ var matrixCandidates = [0, glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR, glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR];
+ layoutFlags |= rnd.choose(matrixCandidates)[0];
+ }
+
+ block.setFlags(layoutFlags);
+
+ for (var ndx = 0; ndx < numUniforms; ndx++)
+ this.generateUniform(rnd, block);
+
+ this.m_blockNdx += 1;
+ };
+
+ /**
+ * Initializes the glsRandomUniformBlockCase.RandomUniformBlockCase
+ */
+ glsRandomUniformBlockCase.RandomUniformBlockCase.prototype.init = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(this.m_seed);
+
+ /** @type {number} */ var numShared = this.m_maxSharedBlocks > 0 ? rnd.getInt(1, this.m_maxSharedBlocks) : 0;
+ /** @type {number} */ var numVtxBlocks = this.m_maxVertexBlocks - numShared > 0 ? rnd.getInt(1, this.m_maxVertexBlocks - numShared) : 0;
+ /** @type {number} */ var numFragBlocks = this.m_maxFragmentBlocks - numShared > 0 ? rnd.getInt(1, this.m_maxFragmentBlocks - numShared) : 0;
+
+ for (var ndx = 0; ndx < numShared; ndx++)
+ this.generateBlock(rnd, glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT);
+
+ for (var ndx = 0; ndx < numVtxBlocks; ndx++)
+ this.generateBlock(rnd, glsUniformBlockCase.UniformFlags.DECLARE_VERTEX);
+
+ for (var ndx = 0; ndx < numFragBlocks; ndx++)
+ this.generateBlock(rnd, glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsSamplerObjectTest.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsSamplerObjectTest.js
new file mode 100644
index 0000000000..0d4030bd91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsSamplerObjectTest.js
@@ -0,0 +1,1148 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsSamplerObjectTest');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluTextureUtil');
+
+goog.scope(function() {
+
+var glsSamplerObjectTest = modules.shared.glsSamplerObjectTest;
+var tcuTestCase = framework.common.tcuTestCase;
+var deRandom = framework.delibs.debase.deRandom;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuTexture = framework.common.tcuTexture;
+var tcuSurface = framework.common.tcuSurface;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var gluDrawUtil = framework.opengl.gluDrawUtil;
+var gluTextureUtil = framework.opengl.gluTextureUtil;
+var deString = framework.delibs.debase.deString;
+
+ var DE_ASSERT = function(expression) {
+ if (!expression) throw new Error('Assert failed');
+ };
+
+ // glsSamplerObjectTest.TextureSamplerTest
+
+ /** @const @type {number} */ glsSamplerObjectTest.VIEWPORT_WIDTH = 128;
+ /** @const @type {number} */ glsSamplerObjectTest.VIEWPORT_HEIGHT = 128;
+
+ /** @const @type {number} */ glsSamplerObjectTest.TEXTURE2D_WIDTH = 32;
+ /** @const @type {number} */ glsSamplerObjectTest.TEXTURE2D_HEIGHT = 32;
+
+ /** @const @type {number} */ glsSamplerObjectTest.TEXTURE3D_WIDTH = 32;
+ /** @const @type {number} */ glsSamplerObjectTest.TEXTURE3D_HEIGHT = 32;
+ /** @const @type {number} */ glsSamplerObjectTest.TEXTURE3D_DEPTH = 32;
+
+ /** @const @type {number} */ glsSamplerObjectTest.CUBEMAP_SIZE = 32;
+
+ /** @const @type {Array<number>} */ glsSamplerObjectTest.s_positions = [
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0
+ ];
+
+ /** @const @type {Array<number>} */ glsSamplerObjectTest.s_positions3D = [
+ -1.0, -1.0, -1.0,
+ 1.0, -1.0, 1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ -1.0, 1.0, 1.0,
+ -1.0, -1.0, -1.0
+ ];
+
+ /** @const @type {Array<number>} */ glsSamplerObjectTest.s_positionsCube = [
+ -1.0, -1.0, -1.0, -0.5,
+ 1.0, -1.0, 1.0, -0.5,
+ 1.0, 1.0, 1.0, 0.5,
+ 1.0, 1.0, 1.0, 0.5,
+ -1.0, 1.0, -1.0, 0.5,
+ -1.0, -1.0, -1.0, -0.5
+ ];
+
+ /**
+ * @struct
+ * @constructor
+ */
+ glsSamplerObjectTest.SamplingState = function(minFilter, magFilter, wrapT, wrapS, wrapR, minLod, maxLod) {
+ /** @type {number} */ this.minFilter = minFilter;
+ /** @type {number} */ this.magFilter = magFilter;
+ /** @type {number} */ this.wrapT = wrapT;
+ /** @type {number} */ this.wrapS = wrapS;
+ /** @type {number} */ this.wrapR = wrapR;
+ /** @type {number} */ this.minLod = minLod;
+ /** @type {number} */ this.maxLod = maxLod;
+ };
+
+ /**
+ * @struct
+ * @param {string} name
+ * @param {string} desc
+ * @param {number} target
+ * @param {glsSamplerObjectTest.SamplingState} state1
+ * @param {glsSamplerObjectTest.SamplingState} state2
+ * @param {glsSamplerObjectTest.SamplingState=} state3
+ * @constructor
+ */
+ glsSamplerObjectTest.TestSpec = function(name, desc, target, state1, state2, state3) {
+ /** @type {string} */ this.name = name;
+ /** @type {string} */ this.desc = desc;
+ /** @type {number} */ this.target = target;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.textureState = state1;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.textureState2 = state3 !== undefined ? state2 : null; // merging TST and MTST structs
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.samplerState = state3 !== undefined ? state3 : state2;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @const @param {glsSamplerObjectTest.TestSpec} spec
+ */
+ glsSamplerObjectTest.TextureSamplerTest = function(spec) {
+ tcuTestCase.DeqpTest.call(this, spec.name, spec.desc);
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {number} */ this.m_target = spec.target;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.m_textureState = spec.textureState;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.m_samplerState = spec.samplerState;
+ /** @type {deRandom.Random} */ this.m_random = new deRandom.Random(deString.deStringHash(spec.name));
+ };
+
+ glsSamplerObjectTest.TextureSamplerTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsSamplerObjectTest.TextureSamplerTest.prototype.constructor = glsSamplerObjectTest.TextureSamplerTest;
+
+ /**
+ * @private
+ * @param {tcuSurface.Surface} textureRef
+ * @param {tcuSurface.Surface} samplerRef
+ * @param {number} x
+ * @param {number} y
+ */
+ glsSamplerObjectTest.TextureSamplerTest.prototype.renderReferences = function(textureRef, samplerRef, x, y) {
+ /** @type {WebGLTexture} */ var texture = glsSamplerObjectTest.TextureSamplerTest.createTexture(this.m_target);
+
+ gl.viewport(x, y, glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ gl.bindTexture(this.m_target, texture);
+
+ glsSamplerObjectTest.TextureSamplerTest.setTextureState(this.m_target, this.m_textureState);
+ this.render();
+ var texRef = textureRef.getAccess();
+ var texRefTransferFormat = gluTextureUtil.getTransferFormat(texRef.getFormat());
+ gl.readPixels(x, y, texRef.m_width, texRef.m_height, texRefTransferFormat.format, texRefTransferFormat.dataType, textureRef.m_pixels);
+
+ glsSamplerObjectTest.TextureSamplerTest.setTextureState(this.m_target, this.m_samplerState);
+ this.render();
+ var sampRef = samplerRef.getAccess();
+ var sampRefTransferFormat = gluTextureUtil.getTransferFormat(sampRef.getFormat());
+ gl.readPixels(x, y, sampRef.m_width, sampRef.m_height, sampRefTransferFormat.format, sampRefTransferFormat.dataType, samplerRef.m_pixels);
+
+ gl.deleteTexture(texture);
+ };
+
+ /**
+ * @private
+ * @param {tcuSurface.Surface} textureResult
+ * @param {tcuSurface.Surface} samplerResult
+ * @param {number} x
+ * @param {number} y
+ */
+ glsSamplerObjectTest.TextureSamplerTest.prototype.renderResults = function(textureResult, samplerResult, x, y) {
+ /** @type {WebGLTexture} */ var texture = glsSamplerObjectTest.TextureSamplerTest.createTexture(this.m_target);
+
+ gl.viewport(x, y, glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ var sampler = gl.createSampler();
+ DE_ASSERT(sampler != -1);
+
+ gl.bindSampler(0, sampler);
+
+ // First set sampler state
+ glsSamplerObjectTest.TextureSamplerTest.setSamplerState(this.m_samplerState, sampler);
+
+ // Set texture state
+ gl.bindTexture(this.m_target, texture);
+
+ glsSamplerObjectTest.TextureSamplerTest.setTextureState(this.m_target, this.m_textureState);
+ // Render using sampler
+ this.render();
+ var sampRes = samplerResult.getAccess();
+ var sampResTransferFormat = gluTextureUtil.getTransferFormat(sampRes.getFormat());
+ gl.readPixels(x, y, sampRes.m_width, sampRes.m_height, sampResTransferFormat.format, sampResTransferFormat.dataType, samplerResult.m_pixels);
+
+ // Render without sampler
+ gl.bindSampler(0, null);
+ gl.deleteSampler(sampler);
+
+ this.render();
+ var texRes = textureResult.getAccess();
+ var texResTransferFormat = gluTextureUtil.getTransferFormat(texRes.getFormat());
+ gl.readPixels(x, y, texRes.m_width, texRes.m_height, texResTransferFormat.format, texResTransferFormat.dataType, textureResult.m_pixels);
+
+ gl.deleteSampler(sampler);
+ gl.deleteTexture(texture);
+ };
+
+ /**
+ * @private
+ */
+ glsSamplerObjectTest.TextureSamplerTest.prototype.render = function() {
+ /** @type {WebGLUniformLocation} */ var samplerLoc;
+ /** @type {WebGLUniformLocation} */ var scaleLoc;
+
+ gl.useProgram(this.m_program.getProgram());
+
+ samplerLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_sampler');
+ DE_ASSERT(samplerLoc != null);
+
+ scaleLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_posScale');
+ DE_ASSERT(scaleLoc != null);
+
+ gl.clearColor(0.5, 0.5, 0.5, 1.0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform1i(samplerLoc, 0);
+
+ gl.uniform1f(scaleLoc, 1.0);
+
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays;
+ switch (this.m_target) {
+ case gl.TEXTURE_2D: {
+ vertexArrays = [
+ gluDrawUtil.vabFromBindingPointAndArrayPointer(
+ gluDrawUtil.bindingPointFromName('a_position'),
+ new gluDrawUtil.VertexArrayPointer(
+ gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE,
+ 2,
+ 6,
+ 0,
+ glsSamplerObjectTest.s_positions))
+ ];
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ gl.uniform1f(scaleLoc, 0.25);
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ break;
+ }
+
+ case gl.TEXTURE_3D: {
+ vertexArrays = [
+ gluDrawUtil.vabFromBindingPointAndArrayPointer(
+ gluDrawUtil.bindingPointFromName('a_position'),
+ new gluDrawUtil.VertexArrayPointer(
+ gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE,
+ 3,
+ 6,
+ 0,
+ glsSamplerObjectTest.s_positions3D))
+ ];
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ gl.uniform1f(scaleLoc, 0.25);
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ break;
+ }
+
+ case gl.TEXTURE_CUBE_MAP: {
+ vertexArrays = [
+ gluDrawUtil.vabFromBindingPointAndArrayPointer(
+ gluDrawUtil.bindingPointFromName('a_position'),
+ new gluDrawUtil.VertexArrayPointer(
+ gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE,
+ 4,
+ 6,
+ 0,
+ glsSamplerObjectTest.s_positionsCube))
+ ];
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ gl.uniform1f(scaleLoc, 0.25);
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ break;
+ }
+
+ default:
+ DE_ASSERT(false);
+ }
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @param {glsSamplerObjectTest.SamplingState} state
+ */
+ glsSamplerObjectTest.TextureSamplerTest.setTextureState = function(target, state) {
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, state.minFilter);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, state.magFilter);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, state.wrapS);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, state.wrapT);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_R, state.wrapR);
+ gl.texParameterf(target, gl.TEXTURE_MAX_LOD, state.maxLod);
+ gl.texParameterf(target, gl.TEXTURE_MIN_LOD, state.minLod);
+ };
+
+ /**
+ * @private
+ * @param {glsSamplerObjectTest.SamplingState} state
+ * @param {WebGLSampler} sampler
+ */
+ glsSamplerObjectTest.TextureSamplerTest.setSamplerState = function(state, sampler) {
+ gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, state.minFilter);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, state.magFilter);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, state.wrapS);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, state.wrapT);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_R, state.wrapR);
+ gl.samplerParameterf(sampler, gl.TEXTURE_MAX_LOD, state.maxLod);
+ gl.samplerParameterf(sampler, gl.TEXTURE_MIN_LOD, state.minLod);
+ };
+
+ /**
+ * @private
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.TextureSamplerTest.createTexture2D = function() {
+ /** @type {WebGLTexture} */ var texture = null;
+ /** @type {tcuTexture.Texture2D} */ var refTexture = new tcuTexture.Texture2D(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8),
+ glsSamplerObjectTest.TEXTURE2D_WIDTH,
+ glsSamplerObjectTest.TEXTURE2D_HEIGHT);
+
+ refTexture.allocLevel(0);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevel(0), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+
+ texture = gl.createTexture();
+
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, refTexture.getWidth(), refTexture.getHeight(), 0, gl.RGBA, gl.UNSIGNED_BYTE, refTexture.getLevel(0).getDataPtr());
+
+ gl.generateMipmap(gl.TEXTURE_2D);
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.TextureSamplerTest.createTexture3D = function() {
+ /** @type {WebGLTexture} */ var texture = null;
+ /** @type {tcuTexture.Texture3D} */ var refTexture = new tcuTexture.Texture3D(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8),
+ glsSamplerObjectTest.TEXTURE3D_WIDTH,
+ glsSamplerObjectTest.TEXTURE3D_HEIGHT,
+ glsSamplerObjectTest.TEXTURE3D_DEPTH);
+
+ refTexture.allocLevel(0);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevel(0), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+
+ texture = gl.createTexture();
+
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, refTexture.getWidth(), refTexture.getHeight(), refTexture.getDepth(), 0, gl.RGBA, gl.UNSIGNED_BYTE, refTexture.getLevel(0).getDataPtr());
+
+ gl.generateMipmap(gl.TEXTURE_3D);
+
+ gl.bindTexture(gl.TEXTURE_3D, null);
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.TextureSamplerTest.createTextureCube = function() {
+ /** @type {WebGLTexture} */ var texture = null;
+ /** @type {tcuTexture.TextureCube} */ var refTexture = new tcuTexture.TextureCube(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8),
+ glsSamplerObjectTest.CUBEMAP_SIZE);
+
+ texture = gl.createTexture();
+
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_POSITIVE_X, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z, 0);
+
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_X), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+ // TODO: check internalFormat / format parameters in texImage2D (were RGBA8 and RGBA respectively)
+ for (var face in tcuTexture.CubeFace) {
+ /** @const @type {number} */ var target = gluTextureUtil.getGLCubeFace(tcuTexture.CubeFace[face]);
+ gl.texImage2D(target, 0, gl.RGBA, refTexture.getSize(), refTexture.getSize(), 0, gl.RGBA, gl.UNSIGNED_BYTE, refTexture.getLevelFace(0, tcuTexture.CubeFace[face]).getDataPtr());
+ }
+
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.TextureSamplerTest.createTexture = function(target) {
+ /** @type {WebGLTexture} */ var texture;
+ switch (target) {
+ case gl.TEXTURE_2D:
+ texture = glsSamplerObjectTest.TextureSamplerTest.createTexture2D();
+ break;
+
+ case gl.TEXTURE_3D:
+ texture = glsSamplerObjectTest.TextureSamplerTest.createTexture3D();
+ break;
+
+ case gl.TEXTURE_CUBE_MAP:
+ texture = glsSamplerObjectTest.TextureSamplerTest.createTextureCube();
+ break;
+
+ default:
+ throw new Error('Unsupported target: ' + WebGLTestUtils.glEnumToString(gl, target));
+ }
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @return {string}
+ */
+ glsSamplerObjectTest.TextureSamplerTest.selectVertexShader = function(target) {
+ switch (target) {
+ case gl.TEXTURE_2D:
+ return '#version 300 es\n' +
+ 'in highp vec2 a_position;\n' +
+ 'uniform highp float u_posScale;\n' +
+ 'out mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\tv_texCoord = a_position;\n' +
+ '\tgl_Position = vec4(u_posScale * a_position, 0.0, 1.0);\n' +
+ '}';
+
+ case gl.TEXTURE_3D:
+ return '#version 300 es\n' +
+ 'in highp vec3 a_position;\n' +
+ 'uniform highp float u_posScale;\n' +
+ 'out mediump vec3 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\tv_texCoord = a_position;\n' +
+ '\tgl_Position = vec4(u_posScale * a_position.xy, 0.0, 1.0);\n' +
+ '}';
+
+ case gl.TEXTURE_CUBE_MAP:
+ return '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'uniform highp float u_posScale;\n' +
+ 'out mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\tv_texCoord = a_position.zw;\n' +
+ '\tgl_Position = vec4(u_posScale * a_position.xy, 0.0, 1.0);\n' +
+ '}';
+
+ default:
+ DE_ASSERT(false);
+ return '';
+ }
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @return {string}
+ */
+ glsSamplerObjectTest.TextureSamplerTest.selectFragmentShader = function(target) {
+ switch (target) {
+ case gl.TEXTURE_2D:
+ return '#version 300 es\nlayout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform lowp sampler2D u_sampler;\n' +
+ 'in mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\to_color = texture(u_sampler, v_texCoord);\n' +
+ '}';
+
+ case gl.TEXTURE_3D:
+ return '#version 300 es\nlayout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform lowp sampler3D u_sampler;\n' +
+ 'in mediump vec3 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\to_color = texture(u_sampler, v_texCoord);\n' +
+ '}';
+
+ case gl.TEXTURE_CUBE_MAP:
+ return '#version 300 es\nlayout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform lowp samplerCube u_sampler;\n' +
+ 'in mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\to_color = texture(u_sampler, vec3(cos(3.14 * v_texCoord.y) * sin(3.14 * v_texCoord.x), sin(3.14 * v_texCoord.y), cos(3.14 * v_texCoord.y) * cos(3.14 * v_texCoord.x)));\n' +
+ '}';
+
+ default:
+ DE_ASSERT(false);
+ return '';
+ }
+ };
+
+ glsSamplerObjectTest.TextureSamplerTest.prototype.init = function() {
+ /** @const @type {string} */ var vertexShaderTemplate = glsSamplerObjectTest.TextureSamplerTest.selectVertexShader(this.m_target);
+ /** @const @type {string} */ var fragmentShaderTemplate = glsSamplerObjectTest.TextureSamplerTest.selectFragmentShader(this.m_target);
+
+ DE_ASSERT(!this.m_program);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl,
+ gluShaderProgram.makeVtxFragSources(
+ vertexShaderTemplate,
+ fragmentShaderTemplate));
+
+ if (!this.m_program.isOk()) {
+ // tcu::TestLog& log = m_testCtx.getLog();
+ // log << *m_program;
+ throw new Error('Failed to compile shaders');
+ }
+ };
+
+ glsSamplerObjectTest.TextureSamplerTest.prototype.iterate = function() {
+ //tcu::TestLog& log = m_testCtx.getLog();
+
+ /** @type {tcuSurface.Surface} */ var textureRef = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+ /** @type {tcuSurface.Surface} */ var samplerRef = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ /** @type {tcuSurface.Surface} */ var textureResult = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+ /** @type {tcuSurface.Surface} */ var samplerResult = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ /** @type {number} */ var x = this.m_random.getInt(0, gl.drawingBufferWidth - glsSamplerObjectTest.VIEWPORT_WIDTH);
+ /** @type {number} */ var y = this.m_random.getInt(0, gl.drawingBufferHeight - glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ this.renderReferences(textureRef, samplerRef, x, y);
+ this.renderResults(textureResult, samplerResult, x, y);
+
+ /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Sampler render result', 'Result from rendering with sampler', samplerRef, samplerResult, [0, 0, 0, 0]);
+
+ if (!tcuImageCompare.pixelThresholdCompare('Texture render result', 'Result from rendering with texture state', textureRef, textureResult, [0, 0, 0, 0]))
+ isOk = false;
+
+ assertMsgOptions(isOk, '', true, false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ // glsSamplerObjectTest.MultiTextureSamplerTest
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @const @param {glsSamplerObjectTest.TestSpec} spec
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest = function(spec) {
+ tcuTestCase.DeqpTest.call(this, spec.name, spec.desc);
+ /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ /** @type {number} */ this.m_target = spec.target;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.m_textureState1 = spec.textureState;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.m_textureState2 = spec.textureState2;
+ /** @type {glsSamplerObjectTest.SamplingState} */ this.m_samplerState = spec.samplerState;
+ /** @type {deRandom.Random} */ this.m_random = new deRandom.Random(deString.deStringHash(spec.name));
+ };
+
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.constructor = glsSamplerObjectTest.MultiTextureSamplerTest;
+
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.init = function() {
+ /** @type {string} */ var vertexShaderTemplate = glsSamplerObjectTest.MultiTextureSamplerTest.selectVertexShader(this.m_target);
+ /** @type {string} */ var fragmentShaderTemplate = glsSamplerObjectTest.MultiTextureSamplerTest.selectFragmentShader(this.m_target);
+
+ DE_ASSERT(!this.m_program);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl,
+ gluShaderProgram.makeVtxFragSources(
+ vertexShaderTemplate,
+ fragmentShaderTemplate));
+ if (!this.m_program.isOk()) {
+ // tcu::TestLog& log = m_testCtx.getLog();
+ //
+ // log << *m_program;
+ throw new Error('Failed to compile shaders');
+ }
+ };
+
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.deinit = function() {
+ gl.activeTexture(gl.TEXTURE0);
+ }
+
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.iterate = function() {
+ //tcu::TestLog& log = m_testCtx.getLog();
+
+ /** @type {tcuSurface.Surface} */ var textureRef = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+ /** @type {tcuSurface.Surface} */ var samplerRef = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ /** @type {tcuSurface.Surface} */ var textureResult = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+ /** @type {tcuSurface.Surface} */ var samplerResult = new tcuSurface.Surface(glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ /** @type {number} */ var x = this.m_random.getInt(0, gl.drawingBufferWidth - glsSamplerObjectTest.VIEWPORT_WIDTH);
+ /** @type {number} */ var y = this.m_random.getInt(0, gl.drawingBufferHeight - glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ this.renderReferences(textureRef, samplerRef, x, y);
+ this.renderResults(textureResult, samplerResult, x, y);
+
+ /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Sampler render result', 'Result from rendering with sampler', samplerRef, samplerResult, [0, 0, 0, 0]);
+
+ if (!tcuImageCompare.pixelThresholdCompare('Texture render result', 'Result from rendering with texture state', textureRef, textureResult, [0, 0, 0, 0]))
+ isOk = false;
+
+ assertMsgOptions(isOk, '', true, false);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @private
+ * @param {tcuSurface.Surface} textureRef
+ * @param {tcuSurface.Surface} samplerRef
+ * @param {number} x
+ * @param {number} y
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.renderReferences = function(textureRef, samplerRef, x, y) {
+ /** @type {WebGLTexture} */ var texture1 = glsSamplerObjectTest.MultiTextureSamplerTest.createTexture(this.m_target, 0);
+ /** @type {WebGLTexture} */ var texture2 = glsSamplerObjectTest.MultiTextureSamplerTest.createTexture(this.m_target, 1);
+
+ gl.viewport(x, y, glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ // Generate texture rendering reference
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(this.m_target, texture1);
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState(this.m_target, this.m_textureState1);
+
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(this.m_target, texture2);
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState(this.m_target, this.m_textureState2);
+
+ this.render();
+ var texRef = textureRef.getAccess();
+ var texRefTransferFormat = gluTextureUtil.getTransferFormat(texRef.getFormat());
+ gl.readPixels(x, y, texRef.m_width, texRef.m_height, texRefTransferFormat.format, texRefTransferFormat.dataType, textureRef.m_pixels);
+
+ // Generate sampler rendering reference
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(this.m_target, texture1);
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState(this.m_target, this.m_samplerState);
+
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(this.m_target, texture2);
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState(this.m_target, this.m_samplerState);
+
+ this.render();
+ var sampRef = samplerRef.getAccess();
+ var sampRefTransferFormat = gluTextureUtil.getTransferFormat(sampRef.getFormat());
+ gl.readPixels(x, y, sampRef.m_width, sampRef.m_height, sampRefTransferFormat.format, sampRefTransferFormat.dataType, samplerRef.m_pixels);
+ };
+
+ /**
+ * @private
+ * @param {tcuSurface.Surface} textureResult
+ * @param {tcuSurface.Surface} samplerResult
+ * @param {number} x
+ * @param {number} y
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.renderResults = function(textureResult, samplerResult, x, y) {
+ /** @type {WebGLTexture} */ var texture1 = glsSamplerObjectTest.MultiTextureSamplerTest.createTexture(this.m_target, 0);
+ /** @type {WebGLTexture} */ var texture2 = glsSamplerObjectTest.MultiTextureSamplerTest.createTexture(this.m_target, 1);
+
+ gl.viewport(x, y, glsSamplerObjectTest.VIEWPORT_WIDTH, glsSamplerObjectTest.VIEWPORT_HEIGHT);
+
+ /** @type {WebGLSampler} */ var sampler = gl.createSampler();
+ DE_ASSERT(sampler != -1);
+
+ gl.bindSampler(0, sampler);
+ gl.bindSampler(1, sampler);
+
+ // First set sampler state
+ glsSamplerObjectTest.MultiTextureSamplerTest.setSamplerState(this.m_samplerState, sampler);
+
+ // Set texture state
+ gl.bindTexture(this.m_target, texture1);
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState(this.m_target, this.m_textureState1);
+
+ gl.bindTexture(this.m_target, texture2);
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState(this. m_target, this.m_textureState2);
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(this.m_target, texture1);
+
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(this.m_target, texture2);
+
+ // Render using sampler
+ this.render();
+ var sampRes = samplerResult.getAccess();
+ var sampResTransferFormat = gluTextureUtil.getTransferFormat(sampRes.getFormat());
+ gl.readPixels(x, y, sampRes.m_width, sampRes.m_height, sampResTransferFormat.format, sampResTransferFormat.dataType, samplerResult.m_pixels);
+
+ gl.bindSampler(0, null);
+ gl.bindSampler(1, null);
+
+ this.render();
+ var texRes = textureResult.getAccess();
+ var texResTransferFormat = gluTextureUtil.getTransferFormat(texRes.getFormat());
+ gl.readPixels(x, y, texRes.m_width, texRes.m_height, texResTransferFormat.format, texResTransferFormat.dataType, textureResult.m_pixels);
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(this.m_target, null);
+
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(this.m_target, null);
+
+ gl.deleteSampler(sampler);
+ gl.deleteTexture(texture1);
+ gl.deleteTexture(texture2);
+ };
+
+ glsSamplerObjectTest.MultiTextureSamplerTest.prototype.render = function() {
+
+ gl.useProgram(this.m_program.getProgram());
+
+ /** @type {WebGLUniformLocation} */ var samplerLoc1 = gl.getUniformLocation(this.m_program.getProgram(), 'u_sampler1');
+ DE_ASSERT(samplerLoc1 != -1);
+
+ /** @type {WebGLUniformLocation} */ var samplerLoc2 = gl.getUniformLocation(this.m_program.getProgram(), 'u_sampler2');
+ DE_ASSERT(samplerLoc2 != -1);
+
+ /** @type {WebGLUniformLocation} */ var scaleLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_posScale');
+ DE_ASSERT(scaleLoc != -1);
+
+ gl.clearColor(0.5, 0.5, 0.5, 1.0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.uniform1i(samplerLoc1, 0);
+
+ gl.uniform1i(samplerLoc2, 1);
+
+ gl.uniform1f(scaleLoc, 1.0);
+
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays;
+ switch (this.m_target) {
+ case gl.TEXTURE_2D: {
+ vertexArrays = [
+ gluDrawUtil.vabFromBindingPointAndArrayPointer(
+ gluDrawUtil.bindingPointFromName('a_position'),
+ new gluDrawUtil.VertexArrayPointer(
+ gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE,
+ 2,
+ 6,
+ 0,
+ glsSamplerObjectTest.s_positions))
+ ];
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ gl.uniform1f(scaleLoc, 0.25);
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ break;
+ }
+
+ case gl.TEXTURE_3D: {
+ vertexArrays = [
+ gluDrawUtil.vabFromBindingPointAndArrayPointer(
+ gluDrawUtil.bindingPointFromName('a_position'),
+ new gluDrawUtil.VertexArrayPointer(
+ gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE,
+ 3,
+ 6,
+ 0,
+ glsSamplerObjectTest.s_positions3D))
+ ];
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ gl.uniform1f(scaleLoc, 0.25);
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ break;
+ }
+
+ case gl.TEXTURE_CUBE_MAP: {
+ vertexArrays = [
+ gluDrawUtil.vabFromBindingPointAndArrayPointer(
+ gluDrawUtil.bindingPointFromName('a_position'),
+ new gluDrawUtil.VertexArrayPointer(
+ gluDrawUtil.VertexComponentType.VTX_COMP_FLOAT,
+ gluDrawUtil.VertexComponentConversion.VTX_COMP_CONVERT_NONE,
+ 4,
+ 6,
+ 0,
+ glsSamplerObjectTest.s_positionsCube))
+ ];
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ gl.uniform1f(scaleLoc, 0.25);
+
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays, new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.TRIANGLES, 6));
+
+ break;
+ }
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @param {glsSamplerObjectTest.SamplingState} state
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.setTextureState = function(target, state) {
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, state.minFilter);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, state.magFilter);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, state.wrapS);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, state.wrapT);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_R, state.wrapR);
+ gl.texParameterf(target, gl.TEXTURE_MAX_LOD, state.maxLod);
+ gl.texParameterf(target, gl.TEXTURE_MIN_LOD, state.minLod);
+ };
+
+ /**
+ * @private
+ * @param {glsSamplerObjectTest.SamplingState} state
+ * @param {WebGLSampler} sampler
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.setSamplerState = function(state, sampler) {
+ gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, state.minFilter);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, state.magFilter);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, state.wrapS);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, state.wrapT);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_R, state.wrapR);
+ gl.samplerParameterf(sampler, gl.TEXTURE_MAX_LOD, state.maxLod);
+ gl.samplerParameterf(sampler, gl.TEXTURE_MIN_LOD, state.minLod);
+ };
+
+ /**
+ * @private
+ * @param {number} id
+ * @return {WebGLTexture }
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.createTexture2D = function(id) {
+ /** @type {WebGLTexture} */ var texture = null;
+ /** @type {tcuTexture.Texture2D} */ var refTexture = new tcuTexture.Texture2D(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8),
+ glsSamplerObjectTest.TEXTURE2D_WIDTH,
+ glsSamplerObjectTest.TEXTURE2D_HEIGHT);
+
+ refTexture.allocLevel(0);
+
+ texture = gl.createTexture();
+
+ switch (id) {
+ case 0:
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevel(0), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 0.5, 0.5]);
+ break;
+
+ case 1:
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevel(0), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 1.0, 1.0]);
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, refTexture.getWidth(), refTexture.getHeight(), 0, gl.RGBA, gl.UNSIGNED_BYTE, refTexture.getLevel(0).getDataPtr());
+
+ gl.generateMipmap(gl.TEXTURE_2D);
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @param {number} id
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.createTexture3D = function(id) {
+ /** @type {WebGLTexture} */ var texture = null;
+ /** @type {tcuTexture.Texture3D} */ var refTexture = new tcuTexture.Texture3D(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8),
+ glsSamplerObjectTest.TEXTURE3D_WIDTH,
+ glsSamplerObjectTest.TEXTURE3D_HEIGHT,
+ glsSamplerObjectTest.TEXTURE3D_DEPTH);
+
+ refTexture.allocLevel(0);
+
+ texture = gl.createTexture();
+
+ switch (id) {
+ case 0:
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevel(0), [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 0.5, 0.5]);
+ break;
+
+ case 1:
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevel(0), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 1.0, 1.0]);
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ gl.bindTexture(gl.TEXTURE_3D, texture);
+ // TODO: check internalFormat and format in texImage3D
+ gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, refTexture.getWidth(), refTexture.getHeight(), refTexture.getDepth(), 0, gl.RGBA, gl.UNSIGNED_BYTE, refTexture.getLevel(0).getDataPtr());
+
+ gl.generateMipmap(gl.TEXTURE_3D);
+
+ gl.bindTexture(gl.TEXTURE_3D, null);
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @param {number} id
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.createTextureCube = function(id) {
+ /** @type {WebGLTexture} */ var texture = null;
+ /** @type {tcuTexture.TextureCube} */ var refTexture = new tcuTexture.TextureCube(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA,
+ tcuTexture.ChannelType.UNORM_INT8),
+ glsSamplerObjectTest.CUBEMAP_SIZE);
+
+ texture = gl.createTexture();
+
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_POSITIVE_X, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y, 0);
+ refTexture.allocLevel(tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z, 0);
+
+ switch (id) {
+ case 0:
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_X), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 0.5, 0.5]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 0.5, 0.5]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 0.5, 0.5]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 0.5, 0.5]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 0.5, 0.5]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z), [0.0, 0.0, 0.0, 0.0], [0.5, 0.5, 0.5, 0.5]);
+ break;
+
+ case 1:
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_X), [0.5, 0.5, 0.5, 0.5], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y), [0.5, 0.5, 0.5, 0.5], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z), [0.5, 0.5, 0.5, 0.5], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X), [0.5, 0.5, 0.5, 0.5], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y), [0.5, 0.5, 0.5, 0.5], [1.0, 1.0, 1.0, 1.0]);
+ tcuTextureUtil.fillWithComponentGradients(refTexture.getLevelFace(0, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z), [0.5, 0.5, 0.5, 0.5], [1.0, 1.0, 1.0, 1.0]);
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+
+ for (var face in tcuTexture.CubeFace) {
+ /** @const @type {number} */ var target = gluTextureUtil.getGLCubeFace(tcuTexture.CubeFace[face]);
+ gl.texImage2D(target, 0, gl.RGBA, refTexture.getSize(), refTexture.getSize(), 0, gl.RGBA, gl.UNSIGNED_BYTE, refTexture.getLevelFace(0, tcuTexture.CubeFace[face]).getDataPtr());
+ }
+
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @param {number} id
+ * @return {WebGLTexture}
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.createTexture = function(target, id) {
+ /** @type {WebGLTexture} */ var texture;
+ switch (target) {
+ case gl.TEXTURE_2D:
+ texture = glsSamplerObjectTest.MultiTextureSamplerTest.createTexture2D(id);
+ break;
+
+ case gl.TEXTURE_3D:
+ texture = glsSamplerObjectTest.MultiTextureSamplerTest.createTexture3D(id);
+ break;
+
+ case gl.TEXTURE_CUBE_MAP:
+ texture = glsSamplerObjectTest.MultiTextureSamplerTest.createTextureCube(id);
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ return texture;
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @return {string}
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.selectVertexShader = function(target) {
+ switch (target) {
+ case gl.TEXTURE_2D:
+ return '#version 300 es\n' +
+ 'in highp vec2 a_position;\n' +
+ 'uniform highp float u_posScale;\n' +
+ 'out mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\tv_texCoord = a_position;\n' +
+ '\tgl_Position = vec4(u_posScale * a_position, 0.0, 1.0);\n' +
+ '}';
+
+ case gl.TEXTURE_3D:
+ return '#version 300 es\n' +
+ 'in highp vec3 a_position;\n' +
+ 'uniform highp float u_posScale;\n' +
+ 'out mediump vec3 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\tv_texCoord = a_position;\n' +
+ '\tgl_Position = vec4(u_posScale * a_position.xy, 0.0, 1.0);\n' +
+ '}';
+
+ case gl.TEXTURE_CUBE_MAP:
+ return '#version 300 es\n' +
+ 'in highp vec4 a_position;\n' +
+ 'uniform highp float u_posScale;\n' +
+ 'out mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\tv_texCoord = a_position.zw;\n' +
+ '\tgl_Position = vec4(u_posScale * a_position.xy, 0.0, 1.0);\n' +
+ '}';
+
+ default:
+ DE_ASSERT(false);
+ return '';
+ }
+ };
+
+ /**
+ * @private
+ * @param {number} target
+ * @return {string}
+ */
+ glsSamplerObjectTest.MultiTextureSamplerTest.selectFragmentShader = function(target) {
+ switch (target) {
+ case gl.TEXTURE_2D:
+ return '#version 300 es\nlayout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform lowp sampler2D u_sampler1;\n' +
+ 'uniform lowp sampler2D u_sampler2;\n' +
+ 'in mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\to_color = vec4(0.75, 0.75, 0.75, 1.0) * (texture(u_sampler1, v_texCoord) + texture(u_sampler2, v_texCoord));\n' +
+ '}';
+
+ break;
+
+ case gl.TEXTURE_3D:
+ return '#version 300 es\nlayout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform lowp sampler3D u_sampler1;\n' +
+ 'uniform lowp sampler3D u_sampler2;\n' +
+ 'in mediump vec3 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\to_color = vec4(0.75, 0.75, 0.75, 1.0) * (texture(u_sampler1, v_texCoord) + texture(u_sampler2, v_texCoord));\n' +
+ '}';
+
+ case gl.TEXTURE_CUBE_MAP:
+ return '#version 300 es\nlayout(location = 0) out mediump vec4 o_color;\n' +
+ 'uniform lowp samplerCube u_sampler1;\n' +
+ 'uniform lowp samplerCube u_sampler2;\n' +
+ 'in mediump vec2 v_texCoord;\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ '\to_color = vec4(0.5, 0.5, 0.5, 1.0) * (texture(u_sampler1, vec3(cos(3.14 * v_texCoord.y) * sin(3.14 * v_texCoord.x), sin(3.14 * v_texCoord.y), cos(3.14 * v_texCoord.y) * cos(3.14 * v_texCoord.x)))' +
+ '+ texture(u_sampler2, vec3(cos(3.14 * v_texCoord.y) * sin(3.14 * v_texCoord.x), sin(3.14 * v_texCoord.y), cos(3.14 * v_texCoord.y) * cos(3.14 * v_texCoord.x))));\n' +
+ '}';
+
+ default:
+ DE_ASSERT(false);
+ return '';
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderExecUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderExecUtil.js
new file mode 100644
index 0000000000..9ea29e7e4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderExecUtil.js
@@ -0,0 +1,731 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL (ES) Module
+ * -----------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Shader execution utilities.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('modules.shared.glsShaderExecUtil');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuMatrixUtil');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.gluVarType');
+
+goog.scope(function() {
+
+ var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var tcuMatrixUtil = framework.common.tcuMatrixUtil;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ var setParentClass = function(child, parent) {
+ child.prototype = Object.create(parent.prototype);
+ child.prototype.constructor = child;
+ };
+
+ /**
+ * @constructor
+ * @param {string=} name
+ * @param {gluVarType.VarType=} varType
+ */
+ glsShaderExecUtil.Symbol = function(name, varType) {
+ name = name === undefined ? '<unnamed>' : name;
+ /** @type {string} */ this.name = name;
+ /** @type {gluVarType.VarType} */ this.varType = varType || null;
+ };
+
+ //! Complete shader specification.
+ /**
+ * @constructor
+ */
+ glsShaderExecUtil.ShaderSpec = function() {
+ /** @type {gluShaderUtil.GLSLVersion} */ this.version = gluShaderUtil.GLSLVersion.V300_ES; //!< Shader version.
+ /** @type {Array<glsShaderExecUtil.Symbol>} */ this.inputs = [];
+ /** @type {Array<glsShaderExecUtil.Symbol>} */ this.outputs = [];
+ /** @type {string} */ this.globalDeclarations = ''; //!< These are placed into global scope. Can contain uniform declarations for example.
+ /** @type {*} */ this.source; //!< Source snippet to be executed.
+ };
+
+ /**
+ * Base class for shader executor.
+ * @constructor
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ */
+ glsShaderExecUtil.ShaderExecutor = function(shaderSpec) {
+ /** @type {Array<glsShaderExecUtil.Symbol>} */ this.m_inputs = shaderSpec.inputs;
+ /** @type {Array<glsShaderExecUtil.Symbol>} */ this.m_outputs = shaderSpec.outputs;
+ };
+
+ glsShaderExecUtil.ShaderExecutor.prototype.useProgram = function() {
+ DE_ASSERT(this.isOk);
+ gl.useProgram(this.getProgram());
+ };
+
+ /**
+ * @return {boolean}
+ */
+ glsShaderExecUtil.ShaderExecutor.prototype.isOk = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @return {WebGLProgram}
+ */
+ glsShaderExecUtil.ShaderExecutor.prototype.getProgram = function() {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * @param {number} numValues
+ * @param {Array<Array<number>>} inputs
+ * @return {Array<goog.TypedArray>} outputs
+ */
+ glsShaderExecUtil.ShaderExecutor.prototype.execute = function(numValues, inputs) {
+ throw new Error('Virtual function. Please override.');
+ };
+
+ /**
+ * Base class for shader executor.
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ * @return {glsShaderExecUtil.ShaderExecutor}
+ */
+ glsShaderExecUtil.createExecutor = function(shaderType, shaderSpec) {
+ switch (shaderType) {
+ case gluShaderProgram.shaderType.VERTEX: return new glsShaderExecUtil.VertexShaderExecutor(shaderSpec);
+ case gluShaderProgram.shaderType.FRAGMENT: return new glsShaderExecUtil.FragmentShaderExecutor(shaderSpec);
+ default:
+ throw new Error('Unsupported shader type: ' + shaderType);
+ }
+ };
+
+ /**
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ * @return {string}
+ */
+ glsShaderExecUtil.generateVertexShader = function(shaderSpec) {
+ /** @type {boolean} */ var usesInout = true;
+ /** @type {string} */ var in_ = usesInout ? 'in' : 'attribute';
+ /** @type {string} */ var out = usesInout ? 'out' : 'varying';
+ /** @type {string} */ var src = '';
+ /** @type {number} */ var vecSize;
+ /** @type {gluShaderUtil.DataType} */ var intBaseType;
+
+ src += '#version 300 es\n';
+
+ if (shaderSpec.globalDeclarations.length > 0)
+ src += (shaderSpec.globalDeclarations + '\n');
+
+ for (var i = 0; i < shaderSpec.inputs.length; ++i)
+ src += (in_ + ' ' + gluVarType.declareVariable(shaderSpec.inputs[i].varType, shaderSpec.inputs[i].name) + ';\n');
+
+ for (var i = 0; i < shaderSpec.outputs.length; i++) {
+ var output = shaderSpec.outputs[i];
+ DE_ASSERT(output.varType.isBasicType());
+
+ if (gluShaderUtil.isDataTypeBoolOrBVec(output.varType.getBasicType())) {
+ vecSize = gluShaderUtil.getDataTypeScalarSize(output.varType.getBasicType());
+ intBaseType = vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) : gluShaderUtil.DataType.INT;
+ /** @type {gluVarType.VarType} */ var intType = new gluVarType.VarType().VarTypeBasic(intBaseType, gluShaderUtil.precision.PRECISION_HIGHP);
+
+ src += ('flat ' + out + ' ' + gluVarType.declareVariable(intType, 'o_' + output.name) + ';\n');
+ } else
+ src += ('flat ' + out + ' ' + gluVarType.declareVariable(output.varType, output.name) + ';\n');
+ }
+
+ src += '\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' gl_Position = vec4(0.0);\n' +
+ ' gl_PointSize = 1.0;\n\n';
+
+ // Declare necessary output variables (bools).
+ for (var i = 0; i < shaderSpec.outputs.length; i++) {
+ if (gluShaderUtil.isDataTypeBoolOrBVec(shaderSpec.outputs[i].varType.getBasicType()))
+ src += ('\t' + gluVarType.declareVariable(shaderSpec.outputs[i].varType, shaderSpec.outputs[i].name) + ';\n');
+ }
+
+ //Operation - indented to correct level.
+ // TODO: Add indenting
+ src += shaderSpec.source;
+
+ // Assignments to outputs.
+ for (var i = 0; i < shaderSpec.outputs.length; i++) {
+ if (gluShaderUtil.isDataTypeBoolOrBVec(output.varType.getBasicType())) {
+ vecSize = gluShaderUtil.getDataTypeScalarSize(output.varType.getBasicType());
+ intBaseType = vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) : gluShaderUtil.DataType.INT;
+
+ src += ('\to_' + output.name + ' = ' + gluShaderUtil.getDataTypeName(intBaseType) + '(' + output.name + ');\n');
+ }
+ }
+
+ src += '}\n';
+
+ return src;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsShaderExecUtil.generateEmptyFragmentSource = function() {
+ /** @type {string} */ var src;
+
+ src = '#version 300 es\n';
+ src += 'out lowp vec4 color;\n';
+ src += 'void main (void)\n{\n';
+ src += ' color = vec4(0.0);\n';
+ src += '}\n';
+
+ return src;
+ };
+
+ /**
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ * @param {string} inputPrefix
+ * @param {string} outputPrefix
+ * @return {string}
+ */
+ glsShaderExecUtil.generatePassthroughVertexShader = function(shaderSpec, inputPrefix, outputPrefix) {
+ // flat qualifier is not present in earlier versions?
+ // DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
+
+ /** @type {string} */ var src;
+
+ src = '#version 300 es\n' +
+ 'in highp vec4 a_position;\n';
+
+ for (var i = 0; i < shaderSpec.inputs.length; i++) {
+ src += ('in ' + gluVarType.declareVariable(shaderSpec.inputs[i].varType, inputPrefix + shaderSpec.inputs[i].name) + ';\n' +
+ 'flat out ' + gluVarType.declareVariable(shaderSpec.inputs[i].varType, outputPrefix + shaderSpec.inputs[i].name) + ';\n');
+ }
+
+ src += '\nvoid main (void)\n{\n' +
+ ' gl_Position = a_position;\n' +
+ ' gl_PointSize = 1.0;\n';
+
+ for (var i = 0; i < shaderSpec.inputs.length; i++)
+ src += ('\t' + outputPrefix + shaderSpec.inputs[i].name + ' = ' + inputPrefix + shaderSpec.inputs[i].name + ';\n');
+
+ src += '}\n';
+
+ return src;
+ };
+
+ /**
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ * @param {boolean} useIntOutputs
+ * @param {*} outLocationMap
+ * @return {string}
+ */
+ glsShaderExecUtil.generateFragmentShader = function(shaderSpec, useIntOutputs, outLocationMap) {
+ /** @type {number} */ var vecSize;
+ /** @type {number} */ var numVecs;
+ /** @type {gluShaderUtil.DataType} */ var intBasicType;
+ /** @type {gluShaderUtil.DataType} */ var uintBasicType;
+ /** @type {gluVarType.VarType} */ var uintType;
+ /** @type {gluVarType.VarType} */ var intType;
+
+ /** @type {string} */ var src;
+ src = '#version 300 es\n';
+
+ if (!shaderSpec.globalDeclarations.length > 0)
+ src += (shaderSpec.globalDeclarations + '\n');
+
+ for (var i = 0; i < shaderSpec.inputs.length; i++)
+ src += ('flat in ' + gluVarType.declareVariable(shaderSpec.inputs[i].varType, shaderSpec.inputs[i].name) + ';\n');
+
+ for (var outNdx = 0; outNdx < shaderSpec.outputs.length; ++outNdx) {
+ /** @type {glsShaderExecUtil.Symbol} */ var output = shaderSpec.outputs[outNdx];
+ /** @type {number} */ var location = outLocationMap[output.name];
+ /** @type {string} */ var outVarName = 'o_' + output.name;
+ /** @type {gluVarType.VariableDeclaration} */ var decl = new gluVarType.VariableDeclaration(output.varType, outVarName, gluVarType.Storage.STORAGE_OUT, undefined, new gluVarType.Layout(location));
+
+ DE_ASSERT(output.varType.isBasicType());
+
+ if (useIntOutputs && gluShaderUtil.isDataTypeFloatOrVec(output.varType.getBasicType())) {
+ vecSize = gluShaderUtil.getDataTypeScalarSize(output.varType.getBasicType());
+ uintBasicType = vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.UINT, vecSize) : gluShaderUtil.DataType.UINT;
+ uintType = gluVarType.newTypeBasic(uintBasicType, gluShaderUtil.precision.PRECISION_HIGHP);
+
+ decl.varType = uintType;
+ src += (decl + ';\n');
+ } else if (gluShaderUtil.isDataTypeBoolOrBVec(output.varType.getBasicType())) {
+ vecSize = gluShaderUtil.getDataTypeScalarSize(output.varType.getBasicType());
+ intBasicType = vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) : gluShaderUtil.DataType.INT;
+ intType = gluVarType.newTypeBasic(intBasicType, gluShaderUtil.precision.PRECISION_HIGHP);
+
+ decl.varType = intType;
+ src += (decl + ';\n');
+ } else if (gluShaderUtil.isDataTypeMatrix(output.varType.getBasicType())) {
+ vecSize = gluShaderUtil.getDataTypeMatrixNumRows(output.varType.getBasicType());
+ numVecs = gluShaderUtil.getDataTypeMatrixNumColumns(output.varType.getBasicType());
+ uintBasicType = gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.UINT, vecSize);
+ uintType = gluVarType.newTypeBasic(uintBasicType, gluShaderUtil.precision.PRECISION_HIGHP);
+
+ decl.varType = uintType;
+ for (var vecNdx = 0; vecNdx < numVecs; ++vecNdx) {
+ decl.name = outVarName + '_' + (vecNdx);
+ decl.layout.location = location + vecNdx;
+ src += (decl + ';\n');
+ }
+ } else //src += '';//glu::VariableDeclaration(output.varType, output.name, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, location) << ";\n";
+ src += new gluVarType.VariableDeclaration(output.varType, output.name, gluVarType.Storage.STORAGE_OUT, undefined, new gluVarType.Layout(location)) + ';\n';
+ }
+
+ src += '\nvoid main (void)\n{\n';
+
+ for (var i = 0; i < shaderSpec.outputs.length; i++) {
+ if ((useIntOutputs && gluShaderUtil.isDataTypeFloatOrVec(shaderSpec.outputs[i].varType.getBasicType())) ||
+ gluShaderUtil.isDataTypeBoolOrBVec(shaderSpec.outputs[i].varType.getBasicType()) ||
+ gluShaderUtil.isDataTypeMatrix(shaderSpec.outputs[i].varType.getBasicType()))
+ src += ('\t' + gluVarType.declareVariable(shaderSpec.outputs[i].varType, shaderSpec.outputs[i].name) + ';\n');
+ }
+
+ // Operation - indented to correct level.
+ // TODO: Add indenting
+ src += shaderSpec.source;
+ // {
+ // std::istringstream opSrc (shaderSpec.source);
+ // /** @type{number} */ var line;
+ //
+ // while (std::getline(opSrc, line))
+ // src += ('\t' << line << '\n');
+ // }
+
+ for (var i = 0; i < shaderSpec.outputs.length; i++) {
+ if (useIntOutputs && gluShaderUtil.isDataTypeFloatOrVec(shaderSpec.outputs[i].varType.getBasicType()))
+ src += (' o_' + shaderSpec.outputs[i].name + ' = floatBitsToUint(' + shaderSpec.outputs[i].name + ');\n');
+ else if (gluShaderUtil.isDataTypeMatrix(shaderSpec.outputs[i].varType.getBasicType())) {
+ numVecs = gluShaderUtil.getDataTypeMatrixNumColumns(shaderSpec.outputs[i].varType.getBasicType());
+
+ for (var vecNdx = 0; vecNdx < numVecs; ++vecNdx)
+ if (useIntOutputs)
+ src += ('\to_' + shaderSpec.outputs[i].name + '_' + vecNdx + ' = floatBitsToUint(' + shaderSpec.outputs[i].name + '[' + vecNdx + ']);\n');
+ else
+ src += ('\to_' + shaderSpec.outputs[i].name + '_' + vecNdx + ' = ' + shaderSpec.outputs[i].name + '[' + vecNdx + '];\n');
+ } else if (gluShaderUtil.isDataTypeBoolOrBVec(shaderSpec.outputs[i].varType.getBasicType())) {
+ vecSize = gluShaderUtil.getDataTypeScalarSize(shaderSpec.outputs[i].varType.getBasicType());
+ intBasicType = vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) : gluShaderUtil.DataType.INT;
+
+ src += ('\to_' + shaderSpec.outputs[i].name + ' = ' + gluShaderUtil.getDataTypeName(intBasicType) + '(' + shaderSpec.outputs[i].name + ');\n');
+ }
+ }
+
+ src += '}\n';
+
+ return src;
+ };
+
+ /**
+ * @param {Array<glsShaderExecUtil.Symbol>} outputs
+ * @return {gluShaderProgram.TransformFeedbackVaryings}
+ */
+ glsShaderExecUtil.getTFVaryings = function(outputs) {
+ var names = [];
+ for (var i = 0; i < outputs.length; i++) {
+ if (gluShaderUtil.isDataTypeBoolOrBVec(outputs[i].varType.getBasicType())) {
+ names.push('o_' + outputs[i].name);
+ } else {
+ names.push(outputs[i].name);
+ }
+ }
+ return new gluShaderProgram.TransformFeedbackVaryings(names);
+ };
+
+ // VertexProcessorExecutor (base class for vertex and geometry executors)
+
+ /**
+ * @constructor
+ * @extends {glsShaderExecUtil.ShaderExecutor}
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ * @param {gluShaderProgram.ProgramSources} sources
+ */
+ glsShaderExecUtil.VertexProcessorExecutor = function(shaderSpec, sources) {
+ sources.add(glsShaderExecUtil.getTFVaryings(shaderSpec.outputs));
+ sources.add(new gluShaderProgram.TransformFeedbackMode(gl.INTERLEAVED_ATTRIBS));
+ glsShaderExecUtil.ShaderExecutor.call(this, shaderSpec);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, sources);
+ };
+
+ setParentClass(glsShaderExecUtil.VertexProcessorExecutor, glsShaderExecUtil.ShaderExecutor);
+
+ /**
+ * @return {boolean}
+ */
+ glsShaderExecUtil.VertexProcessorExecutor.prototype.isOk = function() {
+ return this.m_program.isOk();
+ };
+
+ /**
+ * @return {WebGLProgram}
+ */
+ glsShaderExecUtil.VertexProcessorExecutor.prototype.getProgram = function() {
+ return this.m_program.getProgram();
+ };
+
+ /**
+ * @param {Array<*>} arr
+ * @return {number}
+ */
+ glsShaderExecUtil.computeTotalScalarSize = function(arr) {
+ /** @type {number} */ var size = 0;
+ for (var i = 0; i < arr.length; i++)
+ size += arr[i].varType.getScalarSize();
+ return size;
+ };
+
+ /**
+ * @param {Array<number>} ptr
+ * @param {number} colNdx
+ * @param {number} size Column size
+ * @return {Array<number>}
+ */
+ glsShaderExecUtil.getColumn = function(ptr, colNdx, size) {
+ var begin = colNdx * size;
+ var end = (colNdx + 1) * size;
+ return ptr.slice(begin, end);
+ };
+
+ glsShaderExecUtil.VertexProcessorExecutor.prototype.execute = function(numValues, inputs) {
+ /** @type {glsShaderExecUtil.Symbol} */ var symbol;
+ var outputs = [];
+ /** @type {boolean} */ var useTFObject = true;
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
+ var transformFeedback = gl.createTransformFeedback();
+ var outputBuffer = gl.createBuffer();
+
+ /** @type {number} */ var outputBufferStride = glsShaderExecUtil.computeTotalScalarSize(this.m_outputs) * 4;
+
+ // Setup inputs.
+ for (var inputNdx = 0; inputNdx < this.m_inputs.length; inputNdx++) {
+ symbol = this.m_inputs[inputNdx];
+ /*const void* */var ptr = inputs[inputNdx];
+ /** @type {gluShaderUtil.DataType} */ var basicType = symbol.varType.getBasicType();
+ /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(basicType);
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(basicType))
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding(symbol.name, vecSize, numValues, 0, ptr));
+ else if (gluShaderUtil.isDataTypeIntOrIVec(basicType))
+ vertexArrays.push(gluDrawUtil.newInt32VertexArrayBinding(symbol.name, vecSize, numValues, 0, ptr));
+ else if (gluShaderUtil.isDataTypeUintOrUVec(basicType))
+ vertexArrays.push(gluDrawUtil.newUint32VertexArrayBinding(symbol.name, vecSize, numValues, 0, ptr));
+ else if (gluShaderUtil.isDataTypeMatrix(basicType)) {
+ /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(basicType);
+ /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(basicType);
+ // A matrix consists of several (column-major) vectors. A buffer is created for
+ // every vector in gluDrawUtil.draw() below. Data in every buffer will be tightly
+ // packed. So the stride should be 0. This is different from the code in native
+ // deqp, which use only one buffer for a matrix, the data is interleaved.
+ /** @type {number} */ var stride = 0;
+
+ for (var colNdx = 0; colNdx < numCols; ++colNdx)
+ vertexArrays.push(gluDrawUtil.newFloatColumnVertexArrayBinding(symbol.name,
+ colNdx,
+ numRows,
+ numValues,
+ stride,
+ glsShaderExecUtil.getColumn(ptr, colNdx, numRows * numValues)));
+ } else
+ DE_ASSERT(false);
+ }
+
+ // Setup TF outputs.
+ if (useTFObject)
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, outputBuffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, outputBufferStride * numValues, gl.STREAM_READ);
+ gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, outputBuffer);
+
+ // Draw with rasterization disabled.
+ gl.beginTransformFeedback(gl.POINTS);
+ gl.enable(gl.RASTERIZER_DISCARD);
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays,
+ new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.POINTS, numValues));
+ gl.disable(gl.RASTERIZER_DISCARD);
+ gl.endTransformFeedback();
+
+ // Read back data.
+ var result = new ArrayBuffer(outputBufferStride * numValues);
+ gl.getBufferSubData(gl.TRANSFORM_FEEDBACK_BUFFER, 0, new Uint8Array(result));
+ /** @type {number} */ var curOffset = 0; // Offset in buffer in bytes.
+
+ for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) {
+ symbol = this.m_outputs[outputNdx];
+ /** @type {number} */ var scalarSize = symbol.varType.getScalarSize();
+ var readPtr = new Uint8Array(result, curOffset);
+
+ if (scalarSize * 4 === outputBufferStride)
+ outputs[outputNdx] = readPtr;
+ else {
+ var dstPtr = new Uint8Array(scalarSize * numValues * 4);
+
+ for (var ndx = 0; ndx < numValues; ndx++)
+ for (var j = 0; j < scalarSize * 4; j++) {
+ dstPtr[scalarSize * 4 * ndx + j] = readPtr[ndx * outputBufferStride + j];
+ }
+ outputs[outputNdx] = dstPtr;
+ }
+ curOffset += scalarSize * 4;
+ }
+
+ if (useTFObject)
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
+
+ return outputs;
+ };
+
+ // VertexShaderExecutor
+
+ /**
+ * @constructor
+ * @extends {glsShaderExecUtil.VertexProcessorExecutor}
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ */
+ glsShaderExecUtil.VertexShaderExecutor = function(shaderSpec) {
+ var sources = gluShaderProgram.makeVtxFragSources(glsShaderExecUtil.generateVertexShader(shaderSpec),
+ glsShaderExecUtil.generateEmptyFragmentSource());
+ glsShaderExecUtil.VertexProcessorExecutor.call(this, shaderSpec, sources);
+ };
+
+ setParentClass(glsShaderExecUtil.VertexShaderExecutor, glsShaderExecUtil.VertexProcessorExecutor);
+
+ /**
+ * @constructor
+ * @extends {glsShaderExecUtil.ShaderExecutor}
+ * @param {glsShaderExecUtil.ShaderSpec} shaderSpec
+ */
+ glsShaderExecUtil.FragmentShaderExecutor = function(shaderSpec) {
+ glsShaderExecUtil.ShaderExecutor.call(this, shaderSpec);
+ /** @type {Array<glsShaderExecUtil.Symbol>} */ this.m_outLocationSymbols = [];
+ this.m_outLocationMap = glsShaderExecUtil.generateLocationMap(this.m_outputs, this.m_outLocationSymbols);
+ var sources = gluShaderProgram.makeVtxFragSources(glsShaderExecUtil.generatePassthroughVertexShader(shaderSpec, 'a_', ''),
+ glsShaderExecUtil.generateFragmentShader(shaderSpec, true, this.m_outLocationMap));
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, sources);
+ };
+
+ setParentClass(glsShaderExecUtil.FragmentShaderExecutor, glsShaderExecUtil.ShaderExecutor);
+
+ /**
+ * @return {boolean}
+ */
+ glsShaderExecUtil.FragmentShaderExecutor.prototype.isOk = function() {
+ return this.m_program.isOk();
+ };
+
+ /**
+ * @return {WebGLProgram}
+ */
+ glsShaderExecUtil.FragmentShaderExecutor.prototype.getProgram = function() {
+ return this.m_program.getProgram();
+ };
+
+ /**
+ * @param {gluVarType.VarType} outputType
+ * @param {boolean} useIntOutputs
+ * @return {tcuTexture.TextureFormat}
+ */
+ glsShaderExecUtil.getRenderbufferFormatForOutput = function(outputType, useIntOutputs) {
+ var channelOrderMap = [
+ tcuTexture.ChannelOrder.R,
+ tcuTexture.ChannelOrder.RG,
+ tcuTexture.ChannelOrder.RGBA, // No RGB variants available.
+ tcuTexture.ChannelOrder.RGBA
+ ];
+
+ var basicType = outputType.getBasicType();
+ var numComps = gluShaderUtil.getDataTypeNumComponents(basicType);
+ var channelType;
+
+ switch (gluShaderUtil.getDataTypeScalarType(basicType)) {
+ case 'uint': channelType = tcuTexture.ChannelType.UNSIGNED_INT32; break;
+ case 'int': channelType = tcuTexture.ChannelType.SIGNED_INT32; break;
+ case 'bool': channelType = tcuTexture.ChannelType.SIGNED_INT32; break;
+ case 'float': channelType = useIntOutputs ? tcuTexture.ChannelType.UNSIGNED_INT32 : tcuTexture.ChannelType.FLOAT; break;
+ default:
+ throw new Error('Invalid output type ' + gluShaderUtil.getDataTypeScalarType(basicType));
+ }
+
+ return new tcuTexture.TextureFormat(channelOrderMap[numComps - 1], channelType);
+ };
+
+ glsShaderExecUtil.FragmentShaderExecutor.prototype.execute = function(numValues, inputs) {
+ /** @type {boolean} */ var useIntOutputs = true;
+ /** @type {glsShaderExecUtil.Symbol} */ var symbol;
+ var outputs = [];
+ var maxRenderbufferSize = /** @type {number} */ (gl.getParameter(gl.MAX_RENDERBUFFER_SIZE));
+ /** @type {number} */ var framebufferW = Math.min(maxRenderbufferSize, numValues);
+ /** @type {number} */ var framebufferH = Math.ceil(numValues / framebufferW);
+
+ var framebuffer = gl.createFramebuffer();
+ var renderbuffers = [];
+ for (var i = 0; i < this.m_outLocationSymbols.length; i++)
+ renderbuffers.push(gl.createRenderbuffer());
+
+ var vertexArrays = [];
+ var positions = [];
+
+ if (framebufferH > maxRenderbufferSize)
+ throw new Error('Value count is too high for maximum supported renderbuffer size');
+
+ // Compute positions - 1px points are used to drive fragment shading.
+ for (var valNdx = 0; valNdx < numValues; valNdx++) {
+ /** @type {number} */ var ix = valNdx % framebufferW;
+ /** @type {number} */ var iy = Math.floor(valNdx / framebufferW);
+ var fx = -1 + 2 * (ix + 0.5) / framebufferW;
+ var fy = -1 + 2 * (iy + 0.5) / framebufferH;
+
+ positions[2 * valNdx] = fx;
+ positions[2 * valNdx + 1] = fy;
+ }
+
+ // Vertex inputs.
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding('a_position', 2, numValues, 0, positions));
+
+ for (var inputNdx = 0; inputNdx < this.m_inputs.length; inputNdx++) {
+ symbol = this.m_inputs[inputNdx];
+ var attribName = 'a_' + symbol.name;
+ var ptr = inputs[inputNdx];
+ /** @type {gluShaderUtil.DataType} */ var basicType = symbol.varType.getBasicType();
+ /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(basicType);
+
+ if (gluShaderUtil.isDataTypeFloatOrVec(basicType))
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding(attribName, vecSize, numValues, 0, ptr));
+ else if (gluShaderUtil.isDataTypeIntOrIVec(basicType))
+ vertexArrays.push(gluDrawUtil.newInt32VertexArrayBinding(attribName, vecSize, numValues, 0, ptr));
+ else if (gluShaderUtil.isDataTypeUintOrUVec(basicType))
+ vertexArrays.push(gluDrawUtil.newUint32VertexArrayBinding(attribName, vecSize, numValues, 0, ptr));
+ else if (gluShaderUtil.isDataTypeMatrix(basicType)) {
+ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(basicType);
+ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(basicType);
+ // A matrix consists of several (column-major) vectors. A buffer is created for
+ // every vector in gluDrawUtil.draw() below. Data in every buffer will be tightly
+ // packed. So the stride should be 0. This is different from the code in native
+ // deqp, which use only one buffer for a matrix, the data is interleaved.
+ var stride = 0;
+
+ for (var colNdx = 0; colNdx < numCols; ++colNdx)
+ vertexArrays.push(gluDrawUtil.newFloatColumnVertexArrayBinding(attribName,
+ colNdx,
+ numRows,
+ numValues,
+ stride,
+ glsShaderExecUtil.getColumn(ptr, colNdx, numRows * numValues)));
+ } else
+ DE_ASSERT(false);
+ }
+
+ // Construct framebuffer.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+
+ for (var outNdx = 0; outNdx < this.m_outLocationSymbols.length; ++outNdx) {
+ symbol = this.m_outLocationSymbols[outNdx];
+ var renderbuffer = renderbuffers[outNdx];
+ var format = gluTextureUtil.getInternalFormat(glsShaderExecUtil.getRenderbufferFormatForOutput(symbol.varType, useIntOutputs));
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, format, framebufferW, framebufferH);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + outNdx, gl.RENDERBUFFER, renderbuffer);
+ }
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
+
+ var drawBuffers = [];
+ for (var ndx = 0; ndx < this.m_outLocationSymbols.length; ndx++)
+ drawBuffers[ndx] = gl.COLOR_ATTACHMENT0 + ndx;
+ gl.drawBuffers(drawBuffers);
+
+ // Render
+ gl.viewport(0, 0, framebufferW, framebufferH);
+ gluDrawUtil.draw(gl, this.m_program.getProgram(), vertexArrays,
+ new gluDrawUtil.PrimitiveList(gluDrawUtil.primitiveType.POINTS, numValues));
+
+ // Read back pixels.
+
+ // \todo [2013-08-07 pyry] Some fast-paths could be added here.
+
+ for (var outNdx = 0; outNdx < this.m_outputs.length; ++outNdx) {
+ symbol = this.m_outputs[outNdx];
+ /** @type {number} */ var outSize = symbol.varType.getScalarSize();
+ /** @type {number} */ var outVecSize = gluShaderUtil.getDataTypeNumComponents(symbol.varType.getBasicType());
+ /** @type {number} */ var outNumLocs = gluShaderUtil.getDataTypeNumLocations(symbol.varType.getBasicType());
+ var format = glsShaderExecUtil.getRenderbufferFormatForOutput(symbol.varType, useIntOutputs);
+ var readFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, format.type);
+ var transferFormat = gluTextureUtil.getTransferFormat(readFormat);
+ /** @type {number} */ var outLocation = this.m_outLocationMap[symbol.name];
+ var tmpBuf = new tcuTexture.TextureLevel(readFormat, framebufferW, framebufferH);
+
+ for (var locNdx = 0; locNdx < outNumLocs; ++locNdx) {
+ gl.readBuffer(gl.COLOR_ATTACHMENT0 + outLocation + locNdx);
+ gl.readPixels(0, 0, framebufferW, framebufferH, transferFormat.format, transferFormat.dataType, tmpBuf.getAccess().getDataPtr());
+
+ if (outSize == 4 && outNumLocs == 1) {
+ outputs[outNdx] = new Uint8Array(tmpBuf.getAccess().getBuffer());
+ } else {
+ if (locNdx == 0)
+ outputs[outNdx] = new Uint32Array(numValues * outVecSize);
+ var srcPtr = new Uint32Array(tmpBuf.getAccess().getBuffer());
+ for (var valNdx = 0; valNdx < numValues; valNdx++) {
+ var srcOffset = valNdx * 4;
+ var dstOffset = outSize * valNdx + outVecSize * locNdx;
+ for (var j = 0; j < outVecSize; j++)
+ outputs[outNdx][dstOffset + j] = srcPtr[srcOffset + j];
+ }
+ }
+ }
+ }
+
+ // \todo [2013-08-07 pyry] Clear draw buffers & viewport?
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ return outputs;
+ };
+
+ glsShaderExecUtil.generateLocationMap = function(symbols, locationSymbols) {
+ var ret = [];
+ locationSymbols.length = 0;
+ var location = 0;
+
+ for (var i = 0; i < symbols.length; i++) {
+ var symbol = symbols[i];
+ var numLocations = gluShaderUtil.getDataTypeNumLocations(symbol.varType.getBasicType());
+ ret[symbol.name] = location;
+ location += numLocations;
+
+ for (var ndx = 0; ndx < numLocations; ++ndx)
+ locationSymbols.push(symbol);
+ }
+
+ return ret;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibrary.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibrary.js
new file mode 100644
index 0000000000..27f86e055c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibrary.js
@@ -0,0 +1,1114 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsShaderLibrary');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('modules.shared.glsShaderLibraryCase');
+
+goog.scope(function() {
+
+var glsShaderLibrary = modules.shared.glsShaderLibrary;
+var tcuTestCase = framework.common.tcuTestCase;
+var glsShaderLibraryCase = modules.shared.glsShaderLibraryCase;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+
+ glsShaderLibrary.generateTestCases = function() {
+ /** @type {glsShaderLibrary.Parser} */ var parser = new glsShaderLibrary.Parser();
+ try {
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ var tree = parser.parse(state.testFile);
+ var rootTest = tcuTestCase.newTest(state.testName, 'Top level');
+ rootTest.setChildren(tree);
+ state.setRoot(rootTest);
+ }
+ catch (err) {
+ bufferedLogToConsole(err);
+ testFailed('Failed to parse shader test case file');
+ return false;
+ }
+ return true;
+ };
+
+ glsShaderLibrary.processTestFile = function() {
+ if (glsShaderLibrary.generateTestCases()) {
+ tcuTestCase.runner.runCallback(glsShaderLibraryCase.runTestCases);
+ } else {
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+ glsShaderLibrary.isWhitespace = function(value) {
+ return /^[ \t\r\n]+$/.test(value);
+ };
+ glsShaderLibrary.isEOL = function(value) {
+ return /^[\r\n]+$/.test(value);
+ };
+ glsShaderLibrary.isAlpha = function(value) {
+ return /^[a-zA-Z]$/.test(value);
+ };
+ glsShaderLibrary.isNumeric = function(value) {
+ return /^[0-9]$/.test(value);
+ };
+ glsShaderLibrary.isCaseNameChar = function(value) {
+ return /^[a-zA-Z0-9_\-\.]$/.test(value);
+ };
+
+ /**
+ * Removes however many indents there are on the first line from all lines.
+ * @param {string} str
+ * @return {string} output
+ */
+ glsShaderLibrary.removeExtraIndentation = function(str) {
+ return glsShaderLibrary.removeExtraIndentationArray(
+ str.split(/\r\n|\r|\n/)
+ ).join('\n');
+ };
+
+ /**
+ * Returns an array of strings without indentation.
+ * @param {Array<string>} arr
+ * @return {Array<string>} output
+ */
+ glsShaderLibrary.removeExtraIndentationArray = function(arr) {
+ /** @type {Array<string>} */ var output = [];
+
+ if (arr.length) {
+
+ /** @type {number} */ var numIndentChars = 0;
+ for (var i = 0; i < arr[0].length && glsShaderLibrary.isWhitespace(arr[0].charAt(i)); ++i) {
+ numIndentChars += arr[0].charAt(i) === '\t' ? 4 : 1;
+ }
+
+ for (var i = 0; i < arr.length; ++i) {
+ /** @type {number} */ var removed = 0;
+ /** @type {number} */ var j;
+ // Some tests are indented inconsistently, so we have to check for non-whitespace characters here.
+ for (j = 0; removed < numIndentChars && j < arr[i].length && glsShaderLibrary.isWhitespace(arr[i].charAt(j)); ++j) {
+ removed += (arr[i].charAt(j) === '\t' ? 4 : 1);
+ }
+
+ output.push(arr[i].substr(j, arr[i].length - j));
+ }
+
+ }
+
+ return output;
+ };
+
+ glsShaderLibrary.de_assert = function(condition) {
+ if (!condition) {
+ throw Error();
+ }
+ };
+
+ /**
+ * @param {string} str
+ * @param {string} endstr end of string character
+ * @param {boolean=} trimFront trim leading whitespace
+ * @return {string} str
+ * @private
+ */
+ glsShaderLibrary.parseStringLiteralHelper = function(str, endstr, trimFront) {
+ trimFront = trimFront || false;
+
+ /** @type {number} */ var index_end = 0;
+ // isolate the string
+ do {
+ index_end = str.indexOf(endstr, index_end + 1);
+ } while (index_end >= 0 && str.charAt(index_end - 1) === '\\');
+
+ if (index_end <= 0) {
+ index_end = str.length;
+ }
+
+ // strip quotes, replace \n and \t with nl and tabs respectively
+ str = str.substr(endstr.length, index_end - endstr.length);
+ if (trimFront)
+ str = str.replace(/^\s*\n/, '');
+ var result = '';
+ var i = 0;
+ while (str[i] != undefined) {
+ if (str[i] == '\\') {
+ switch (str[i + 1]) {
+ case undefined:
+ break;
+ case 'n':
+ result += '\n';
+ break;
+ case 't':
+ result += '\t';
+ break;
+ default:
+ result += str[i + 1];
+ break;
+ }
+ i += 2;
+ } else {
+ result += str[i];
+ i++;
+ }
+ }
+ return result;
+
+ };
+
+ /**
+ * glsShaderLibrary.Parser class
+ * @constructor
+ */
+ glsShaderLibrary.Parser = function() {
+
+ /* data members */
+
+ /**
+ * The Token constants
+ * @enum {number}
+ */
+ var Token = {
+ TOKEN_INVALID: 0,
+ TOKEN_EOF: 1,
+ TOKEN_STRING: 2,
+ TOKEN_SHADER_SOURCE: 3,
+
+ TOKEN_INT_LITERAL: 4,
+ TOKEN_FLOAT_LITERAL: 5,
+
+ // identifiers
+ TOKEN_IDENTIFIER: 6,
+ TOKEN_TRUE: 7,
+ TOKEN_FALSE: 8,
+ TOKEN_DESC: 9,
+ TOKEN_EXPECT: 10,
+ TOKEN_GROUP: 11,
+ TOKEN_CASE: 12,
+ TOKEN_END: 13,
+ TOKEN_VALUES: 14,
+ TOKEN_BOTH: 15,
+ TOKEN_VERTEX: 26,
+ TOKEN_FRAGMENT: 17,
+ TOKEN_UNIFORM: 18,
+ TOKEN_INPUT: 19,
+ TOKEN_OUTPUT: 20,
+ TOKEN_FLOAT: 21,
+ TOKEN_FLOAT_VEC2: 22,
+ TOKEN_FLOAT_VEC3: 23,
+ TOKEN_FLOAT_VEC4: 24,
+ TOKEN_FLOAT_MAT2: 25,
+ TOKEN_FLOAT_MAT2X3: 26,
+ TOKEN_FLOAT_MAT2X4: 27,
+ TOKEN_FLOAT_MAT3X2: 28,
+ TOKEN_FLOAT_MAT3: 29,
+ TOKEN_FLOAT_MAT3X4: 30,
+ TOKEN_FLOAT_MAT4X2: 31,
+ TOKEN_FLOAT_MAT4X3: 32,
+ TOKEN_FLOAT_MAT4: 33,
+ TOKEN_INT: 34,
+ TOKEN_INT_VEC2: 35,
+ TOKEN_INT_VEC3: 36,
+ TOKEN_INT_VEC4: 37,
+ TOKEN_UINT: 38,
+ TOKEN_UINT_VEC2: 39,
+ TOKEN_UINT_VEC3: 40,
+ TOKEN_UINT_VEC4: 41,
+ TOKEN_BOOL: 42,
+ TOKEN_BOOL_VEC2: 43,
+ TOKEN_BOOL_VEC3: 44,
+ TOKEN_BOOL_VEC4: 45,
+ TOKEN_VERSION: 46,
+
+ // symbols
+ TOKEN_ASSIGN: 47,
+ TOKEN_PLUS: 48,
+ TOKEN_MINUS: 49,
+ TOKEN_COMMA: 50,
+ TOKEN_VERTICAL_BAR: 51,
+ TOKEN_SEMI_COLON: 52,
+ TOKEN_LEFT_PAREN: 53,
+ TOKEN_RIGHT_PAREN: 54,
+ TOKEN_LEFT_BRACKET: 55,
+ TOKEN_RIGHT_BRACKET: 56,
+ TOKEN_LEFT_BRACE: 57,
+ TOKEN_RIGHT_BRACE: 58,
+
+ TOKEN_LAST: 59
+ };
+
+ /** @type {string} */ var m_input = '';
+ /** @type {number} */ var m_curPtr = 0;
+ /** @type {number} */ var m_curToken;// = Token.TOKEN_INVALID;
+ /** @type {string} */ var m_curTokenStr = '';
+
+ /* function members */
+ this.parse = function(input) {
+
+ // initialise parser
+ m_input = input;
+ m_curPtr = 0;
+ m_curToken = Token.TOKEN_INVALID;
+ m_curTokenStr = '';
+ advanceToken();
+
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var nodeList = [];
+
+ for (;;) {
+
+ if (m_curToken === Token.TOKEN_CASE) {
+ parseShaderCase(nodeList);
+ } else if (m_curToken === Token.TOKEN_GROUP) {
+ parseShaderGroup(nodeList);
+ } else if (m_curToken === Token.TOKEN_EOF) {
+ break;
+ } else {
+ // throw Error("invalid token encountered at main level: '" + m_curTokenStr + "'");
+ testFailed("invalid token encountered at main level: '" + m_curTokenStr + "'");
+ tcuTestCase.runner.terminate();
+ }
+
+ }
+
+ return nodeList;
+
+ };
+
+ /**
+ * ensures that the token exists
+ * otherwise it returns the corresponding token's name depending on enum number value
+ * @param {number} id
+ * @return {string} name
+ */
+ var resolveTokenName = function(id) {
+ for (var name in Token) {
+ if (Token[name] === id) return name;
+ }
+ return 'TOKEN_UNKNOWN';
+ };
+
+ /**
+ * Throws an error which contains the passed string
+ * @param {string} errorStr that contains an error to notify
+ * @return {string} error
+ */
+ var parseError = function(errorStr) {
+ // abort
+ throw 'glsShaderLibrary.Parser error: ' + errorStr + ' near ' + m_input.substr(m_curPtr, m_curPtr + 80);
+ };
+
+ /**
+ * Converts string into float
+ * @param {string} str
+ * @return {number}
+ */
+ var parseFloatLiteral = function(str) {
+ return parseFloat(str);
+ };
+
+ /**
+ * Converts string into integer
+ * @param {string} str
+ * @return {number}
+ */
+ var parseIntLiteral = function(str) {
+ return parseInt(str, 10);
+ };
+ var parseStringLiteral = function(str) {
+ /**
+ * @type {string}
+ * find delimitor
+ */ var endchar = str.substr(0, 1);
+ return glsShaderLibrary.parseStringLiteralHelper(str, endchar);
+ };
+ var parseShaderSource = function(str) {
+ // similar to parse literal, delimitors are two double quotes ("")
+ return glsShaderLibrary.removeExtraIndentation(
+ glsShaderLibrary.parseStringLiteralHelper(str, '""', true)
+ );
+ };
+
+ var advanceTokenWorker = function() {
+
+ // Skip old token
+ m_curPtr += m_curTokenStr.length;
+
+ // Reset token (for safety).
+ m_curToken = Token.TOKEN_INVALID;
+ m_curTokenStr = '';
+
+ // Eat whitespace & comments while they last.
+ for (;;) {
+
+ while (glsShaderLibrary.isWhitespace(m_input.charAt(m_curPtr))) ++m_curPtr;
+
+ // check for EOL comment
+ if (m_input.charAt(m_curPtr) === '#') {
+ // if m_input is to be an array of lines then this probably wont work very well
+ while (
+ m_curPtr < m_input.length &&
+ !glsShaderLibrary.isEOL(m_input.charAt(m_curPtr))
+ ) ++m_curPtr;
+ } else {
+ break;
+ }
+
+ }
+
+ if (m_curPtr >= m_input.length) {
+
+ m_curToken = Token.TOKEN_EOF;
+ m_curTokenStr = '<EOF>';
+
+ } else if (glsShaderLibrary.isAlpha(m_input.charAt(m_curPtr))) {
+
+ /** @type {number} */ var end = m_curPtr + 1;
+ while (glsShaderLibrary.isCaseNameChar(m_input.charAt(end))) ++end;
+
+ m_curTokenStr = m_input.substr(m_curPtr, end - m_curPtr);
+
+ m_curToken = (function() {
+ // consider reimplementing with a binary search
+ switch (m_curTokenStr) {
+ case 'true': return Token.TOKEN_TRUE;
+ case 'false': return Token.TOKEN_FALSE;
+ case 'desc': return Token.TOKEN_DESC;
+ case 'expect': return Token.TOKEN_EXPECT;
+ case 'group': return Token.TOKEN_GROUP;
+ case 'case': return Token.TOKEN_CASE;
+ case 'end': return Token.TOKEN_END;
+ case 'values': return Token.TOKEN_VALUES;
+ case 'both': return Token.TOKEN_BOTH;
+ case 'vertex': return Token.TOKEN_VERTEX;
+ case 'fragment': return Token.TOKEN_FRAGMENT;
+ case 'uniform': return Token.TOKEN_UNIFORM;
+ case 'input': return Token.TOKEN_INPUT;
+ case 'output': return Token.TOKEN_OUTPUT;
+ case 'float': return Token.TOKEN_FLOAT;
+ case 'vec2': return Token.TOKEN_FLOAT_VEC2;
+ case 'vec3': return Token.TOKEN_FLOAT_VEC3;
+ case 'vec4': return Token.TOKEN_FLOAT_VEC4;
+ case 'mat2': return Token.TOKEN_FLOAT_MAT2;
+ case 'mat2x3': return Token.TOKEN_FLOAT_MAT2X3;
+ case 'mat2x4': return Token.TOKEN_FLOAT_MAT2X4;
+ case 'mat3x2': return Token.TOKEN_FLOAT_MAT3X2;
+ case 'mat3': return Token.TOKEN_FLOAT_MAT3;
+ case 'mat3x4': return Token.TOKEN_FLOAT_MAT3X4;
+ case 'mat4x2': return Token.TOKEN_FLOAT_MAT4X2;
+ case 'mat4x3': return Token.TOKEN_FLOAT_MAT4X3;
+ case 'mat4': return Token.TOKEN_FLOAT_MAT4;
+ case 'int': return Token.TOKEN_INT;
+ case 'ivec2': return Token.TOKEN_INT_VEC2;
+ case 'ivec3': return Token.TOKEN_INT_VEC3;
+ case 'ivec4': return Token.TOKEN_INT_VEC4;
+ case 'uint': return Token.TOKEN_UINT;
+ case 'uvec2': return Token.TOKEN_UINT_VEC2;
+ case 'uvec3': return Token.TOKEN_UINT_VEC3;
+ case 'uvec4': return Token.TOKEN_UINT_VEC4;
+ case 'bool': return Token.TOKEN_BOOL;
+ case 'bvec2': return Token.TOKEN_BOOL_VEC2;
+ case 'bvec3': return Token.TOKEN_BOOL_VEC3;
+ case 'bvec4': return Token.TOKEN_BOOL_VEC4;
+ case 'version': return Token.TOKEN_VERSION;
+ default: return Token.TOKEN_IDENTIFIER;
+ }
+ }());
+
+ } else if (glsShaderLibrary.isNumeric(m_input.charAt(m_curPtr))) {
+
+ /** @type {number} */ var p = m_curPtr;
+ while (glsShaderLibrary.isNumeric(m_input.charAt(p))) ++p;
+
+ if (m_input.charAt(p) === '.') { // float
+
+ ++p;
+ while (glsShaderLibrary.isNumeric(m_input.charAt(p))) ++p;
+
+ if (m_input.charAt(p) === 'e' || m_input.charAt(p) === 'E') {
+
+ ++p;
+ if (m_input.charAt(p) === '+' || m_input.charAt(p) === '-') ++p;
+
+ glsShaderLibrary.de_assert(p < m_input.length && glsShaderLibrary.isNumeric(m_input.charAt(p)));
+ while (glsShaderLibrary.isNumeric(m_input.charAt(p))) ++p;
+
+ }
+
+ m_curToken = Token.TOKEN_FLOAT_LITERAL;
+ m_curTokenStr = m_input.substr(m_curPtr, p - m_curPtr);
+
+ } else {
+
+ m_curToken = Token.TOKEN_INT_LITERAL;
+ m_curTokenStr = m_input.substr(m_curPtr, p - m_curPtr);
+
+ }
+
+ } else if (m_input.charAt(m_curPtr) === '"' && m_input.charAt(m_curPtr + 1) === '"') { // shader source
+
+ var p = m_curPtr + 2;
+
+ while (m_input.charAt(p) != '"' || m_input.charAt(p + 1) != '"') {
+ glsShaderLibrary.de_assert(p < m_input.length);
+ if (m_input.charAt(p) === '\\') {
+ glsShaderLibrary.de_assert(p + 1 < m_input.length);
+ p += 2;
+ } else {
+ ++p;
+ }
+ }
+ p += 2;
+
+ m_curToken = Token.TOKEN_SHADER_SOURCE;
+ m_curTokenStr = m_input.substr(m_curPtr, p - m_curPtr);
+
+ } else if (m_input.charAt(m_curPtr) === '"' || m_input.charAt(m_curPtr) === "'") {
+
+ /** @type {string} */ var delimitor = m_input.charAt(m_curPtr);
+ var p = m_curPtr + 1;
+
+ while (m_input.charAt(p) != delimitor) {
+
+ glsShaderLibrary.de_assert(p < m_input.length);
+ if (m_input.charAt(p) === '\\') {
+ glsShaderLibrary.de_assert(p + 1 < m_input.length);
+ p += 2;
+ } else {
+ ++p;
+ }
+
+ }
+ ++p;
+
+ m_curToken = Token.TOKEN_STRING;
+ m_curTokenStr = m_input.substr(m_curPtr, p - m_curPtr);
+
+ } else {
+
+ m_curTokenStr = m_input.charAt(m_curPtr);
+ m_curToken = (function() {
+ // consider reimplementing with a binary search
+ switch (m_curTokenStr) {
+ case '=': return Token.TOKEN_ASSIGN;
+ case '+': return Token.TOKEN_PLUS;
+ case '-': return Token.TOKEN_MINUS;
+ case ',': return Token.TOKEN_COMMA;
+ case '|': return Token.TOKEN_VERTICAL_BAR;
+ case ';': return Token.TOKEN_SEMI_COLON;
+ case '(': return Token.TOKEN_LEFT_PAREN;
+ case ')': return Token.TOKEN_RIGHT_PAREN;
+ case '[': return Token.TOKEN_LEFT_BRACKET;
+ case ']': return Token.TOKEN_RIGHT_BRACKET;
+ case '{': return Token.TOKEN_LEFT_BRACE;
+ case '}': return Token.TOKEN_RIGHT_BRACE;
+
+ default: return Token.TOKEN_INVALID;
+ }
+ }());
+
+ }
+
+ };
+
+ /**
+ * @return {Object.<number, string, string>}
+ */
+ var advanceTokenTester = function(input, current_index) {
+ m_input = input;
+ m_curPtr = current_index;
+ m_curTokenStr = '';
+ advanceTokenWorker();
+ return {
+ /** @type {number} */ idType: m_curToken,
+ /** @type {string} */ name: resolveTokenName(m_curToken),
+ /** @type {string} */ value: m_curTokenStr
+ };
+ };
+
+ /**
+ * @param {Token=} tokenAssumed
+ */
+ var advanceToken = function(tokenAssumed) {
+ if (typeof(tokenAssumed) !== 'undefined') {
+ assumeToken(tokenAssumed);
+ }
+ advanceTokenWorker();
+ };
+ var assumeToken = function(token) {
+
+ if (m_curToken != token) {
+ // parse error
+ /** @type {string} */ var msg = "unexpected token '" + m_curTokenStr + "', expecting '" + getTokenName(token) + "'";
+ throw Error('Parse Error. ' + msg + ' near ' + m_curPtr + ' ...');
+ }
+ };
+ var mapDataTypeToken = function(token) {
+ switch (token) {
+ case Token.TOKEN_FLOAT: return gluShaderUtil.DataType.FLOAT;
+ case Token.TOKEN_FLOAT_VEC2: return gluShaderUtil.DataType.FLOAT_VEC2;
+ case Token.TOKEN_FLOAT_VEC3: return gluShaderUtil.DataType.FLOAT_VEC3;
+ case Token.TOKEN_FLOAT_VEC4: return gluShaderUtil.DataType.FLOAT_VEC4;
+ case Token.TOKEN_FLOAT_MAT2: return gluShaderUtil.DataType.FLOAT_MAT2;
+ case Token.TOKEN_FLOAT_MAT2X3: return gluShaderUtil.DataType.FLOAT_MAT2X3;
+ case Token.TOKEN_FLOAT_MAT2X4: return gluShaderUtil.DataType.FLOAT_MAT2X4;
+ case Token.TOKEN_FLOAT_MAT3X2: return gluShaderUtil.DataType.FLOAT_MAT3X2;
+ case Token.TOKEN_FLOAT_MAT3: return gluShaderUtil.DataType.FLOAT_MAT3;
+ case Token.TOKEN_FLOAT_MAT3X4: return gluShaderUtil.DataType.FLOAT_MAT3X4;
+ case Token.TOKEN_FLOAT_MAT4X2: return gluShaderUtil.DataType.FLOAT_MAT4X2;
+ case Token.TOKEN_FLOAT_MAT4X3: return gluShaderUtil.DataType.FLOAT_MAT4X3;
+ case Token.TOKEN_FLOAT_MAT4: return gluShaderUtil.DataType.FLOAT_MAT4;
+ case Token.TOKEN_INT: return gluShaderUtil.DataType.INT;
+ case Token.TOKEN_INT_VEC2: return gluShaderUtil.DataType.INT_VEC2;
+ case Token.TOKEN_INT_VEC3: return gluShaderUtil.DataType.INT_VEC3;
+ case Token.TOKEN_INT_VEC4: return gluShaderUtil.DataType.INT_VEC4;
+ case Token.TOKEN_UINT: return gluShaderUtil.DataType.UINT;
+ case Token.TOKEN_UINT_VEC2: return gluShaderUtil.DataType.UINT_VEC2;
+ case Token.TOKEN_UINT_VEC3: return gluShaderUtil.DataType.UINT_VEC3;
+ case Token.TOKEN_UINT_VEC4: return gluShaderUtil.DataType.UINT_VEC4;
+ case Token.TOKEN_BOOL: return gluShaderUtil.DataType.BOOL;
+ case Token.TOKEN_BOOL_VEC2: return gluShaderUtil.DataType.BOOL_VEC2;
+ case Token.TOKEN_BOOL_VEC3: return gluShaderUtil.DataType.BOOL_VEC3;
+ case Token.TOKEN_BOOL_VEC4: return gluShaderUtil.DataType.BOOL_VEC4;
+ default: return gluShaderUtil.DataType.INVALID;
+ }
+ };
+
+ /**
+ * Returns the corresponding token's name depending on enum number value
+ * @param {number} token
+ * @return {string}
+ */
+ var getTokenName = function(token) {
+ switch (token) {
+ case Token.TOKEN_INVALID: return '<invalid>';
+ case Token.TOKEN_EOF: return '<eof>';
+ case Token.TOKEN_STRING: return '<string>';
+ case Token.TOKEN_SHADER_SOURCE: return 'source';
+
+ case Token.TOKEN_INT_LITERAL: return '<int>';
+ case Token.TOKEN_FLOAT_LITERAL: return '<float>';
+
+ // identifiers
+ case Token.TOKEN_IDENTIFIER: return '<identifier>';
+ case Token.TOKEN_TRUE: return 'true';
+ case Token.TOKEN_FALSE: return 'false';
+ case Token.TOKEN_DESC: return 'desc';
+ case Token.TOKEN_EXPECT: return 'expect';
+ case Token.TOKEN_GROUP: return 'group';
+ case Token.TOKEN_CASE: return 'case';
+ case Token.TOKEN_END: return 'end';
+ case Token.TOKEN_VALUES: return 'values';
+ case Token.TOKEN_BOTH: return 'both';
+ case Token.TOKEN_VERTEX: return 'vertex';
+ case Token.TOKEN_FRAGMENT: return 'fragment';
+ case Token.TOKEN_UNIFORM: return 'uniform';
+ case Token.TOKEN_INPUT: return 'input';
+ case Token.TOKEN_OUTPUT: return 'output';
+ case Token.TOKEN_FLOAT: return 'float';
+ case Token.TOKEN_FLOAT_VEC2: return 'vec2';
+ case Token.TOKEN_FLOAT_VEC3: return 'vec3';
+ case Token.TOKEN_FLOAT_VEC4: return 'vec4';
+ case Token.TOKEN_FLOAT_MAT2: return 'mat2';
+ case Token.TOKEN_FLOAT_MAT2X3: return 'mat2x3';
+ case Token.TOKEN_FLOAT_MAT2X4: return 'mat2x4';
+ case Token.TOKEN_FLOAT_MAT3X2: return 'mat3x2';
+ case Token.TOKEN_FLOAT_MAT3: return 'mat3';
+ case Token.TOKEN_FLOAT_MAT3X4: return 'mat3x4';
+ case Token.TOKEN_FLOAT_MAT4X2: return 'mat4x2';
+ case Token.TOKEN_FLOAT_MAT4X3: return 'mat4x3';
+ case Token.TOKEN_FLOAT_MAT4: return 'mat4';
+ case Token.TOKEN_INT: return 'int';
+ case Token.TOKEN_INT_VEC2: return 'ivec2';
+ case Token.TOKEN_INT_VEC3: return 'ivec3';
+ case Token.TOKEN_INT_VEC4: return 'ivec4';
+ case Token.TOKEN_UINT: return 'uint';
+ case Token.TOKEN_UINT_VEC2: return 'uvec2';
+ case Token.TOKEN_UINT_VEC3: return 'uvec3';
+ case Token.TOKEN_UINT_VEC4: return 'uvec4';
+ case Token.TOKEN_BOOL: return 'bool';
+ case Token.TOKEN_BOOL_VEC2: return 'bvec2';
+ case Token.TOKEN_BOOL_VEC3: return 'bvec3';
+ case Token.TOKEN_BOOL_VEC4: return 'bvec4';
+
+ case Token.TOKEN_ASSIGN: return '=';
+ case Token.TOKEN_PLUS: return '+';
+ case Token.TOKEN_MINUS: return '-';
+ case Token.TOKEN_COMMA: return ',';
+ case Token.TOKEN_VERTICAL_BAR: return '|';
+ case Token.TOKEN_SEMI_COLON: return ';';
+ case Token.TOKEN_LEFT_PAREN: return '(';
+ case Token.TOKEN_RIGHT_PAREN: return ')';
+ case Token.TOKEN_LEFT_BRACKET: return '[';
+ case Token.TOKEN_RIGHT_BRACKET: return ']';
+ case Token.TOKEN_LEFT_BRACE: return ' {';
+ case Token.TOKEN_RIGHT_BRACE: return '}';
+
+ default: return '<unknown>';
+ }
+ };
+
+ /**
+ * @param {?gluShaderUtil.DataType} expectedDataType
+ * @param {Object} result
+ */
+ var parseValueElement = function(expectedDataType, result) {
+ /** @type {?string} */ var scalarType = null;
+ /** @type {number} */ var scalarSize = 0;
+ if (expectedDataType) {
+ scalarType = gluShaderUtil.getDataTypeScalarType(expectedDataType);
+ scalarSize = gluShaderUtil.getDataTypeScalarSize(expectedDataType);
+ }
+
+ /** @type {Array<number>} */ var elems = [];
+
+ if (scalarSize > 1) {
+ glsShaderLibrary.de_assert(mapDataTypeToken(m_curToken) === expectedDataType);
+ advanceToken(); // data type(float, vec2, etc.)
+ advanceToken(Token.TOKEN_LEFT_PAREN);
+ }
+
+ for (var i = 0; i < scalarSize; ++i) {
+ if (scalarType === 'float') {
+
+ /** @type {number} */ var signMult = 1.0;
+ if (m_curToken === Token.TOKEN_MINUS) {
+ signMult = -1.0;
+ advanceToken();
+ }
+
+ assumeToken(Token.TOKEN_FLOAT_LITERAL);
+ elems.push(signMult * parseFloatLiteral(m_curTokenStr));
+ advanceToken(Token.TOKEN_FLOAT_LITERAL);
+
+ } else if (scalarType === 'int' || scalarType === 'uint') {
+
+ var signMult = 1;
+ if (m_curToken === Token.TOKEN_MINUS) {
+ signMult = -1;
+ advanceToken();
+ }
+
+ assumeToken(Token.TOKEN_INT_LITERAL);
+ elems.push(signMult * parseIntLiteral(m_curTokenStr));
+ advanceToken(Token.TOKEN_INT_LITERAL);
+
+ } else {
+
+ glsShaderLibrary.de_assert(scalarType === 'bool');
+ elems.push(m_curToken === Token.TOKEN_TRUE);
+ if (m_curToken != Token.TOKEN_TRUE && m_curToken != Token.TOKEN_FALSE) {
+ throw Error('unexpected token, expecting bool: ' + m_curTokenStr);
+ }
+ advanceToken(); // true/false
+
+ }
+
+ if (i != (scalarSize - 1)) {
+ advanceToken(Token.TOKEN_COMMA);
+ }
+ }
+
+ if (scalarSize > 1) {
+ advanceToken(Token.TOKEN_RIGHT_PAREN);
+ }
+
+ for (var i = 0; i < elems.length; i++)
+ result.elements.push(elems[i]);
+
+ };
+
+ /**
+ * @param {Object.<Array, number>} valueBlock
+ */
+ var parseValue = function(valueBlock) {
+
+ /**
+ * @type {Object}
+ */
+ var result = {
+ /** @type {?gluShaderUtil.DataType} */ dataType: null,
+ /** @type {?glsShaderLibraryCase.shaderCase} */ storageType: null,
+ /** @type {?string} */ valueName: null,
+ /** @type {Array} */ elements: []
+ };
+
+ // parse storage
+ switch (m_curToken) {
+ case Token.TOKEN_UNIFORM:
+ result.storageType = glsShaderLibraryCase.shaderCase.STORAGE_UNIFORM;
+ break;
+ case Token.TOKEN_INPUT:
+ result.storageType = glsShaderLibraryCase.shaderCase.STORAGE_INPUT;
+ break;
+ case Token.TOKEN_OUTPUT:
+ result.storageType = glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT;
+ break;
+ default:
+ throw Error('unexpected token encountered when parsing value classifier');
+ break;
+ }
+ advanceToken();
+
+ // parse data type
+ result.dataType = mapDataTypeToken(m_curToken);
+ if (result.dataType === gluShaderUtil.DataType.INVALID) {
+ throw Error('unexpected token when parsing value data type: ' + m_curTokenStr);
+ }
+ advanceToken();
+
+ // parse value name
+ if (m_curToken === Token.TOKEN_IDENTIFIER) {
+ result.valueName = m_curTokenStr;
+ } else if (m_curToken === Token.TOKEN_STRING) {
+ result.valueName = parseStringLiteral(m_curTokenStr);
+ } else {
+ throw Error('unexpected token when parsing value name: ' + m_curTokenStr);
+ }
+ advanceToken();
+
+ // parse assignment operator.
+ advanceToken(Token.TOKEN_ASSIGN);
+
+ // parse actual value
+ if (m_curToken === Token.TOKEN_LEFT_BRACKET) { // value list
+ advanceToken(Token.TOKEN_LEFT_BRACKET);
+ result.arrayLength = 0;
+
+ for (;;) {
+ parseValueElement(result.dataType, result);
+ result.arrayLength += 1;
+
+ if (m_curToken === Token.TOKEN_RIGHT_BRACKET) {
+ break;
+ } else if (m_curToken === Token.TOKEN_VERTICAL_BAR) { // pipe?
+ advanceToken();
+ continue;
+ } else {
+ throw Error('unexpected token in value element array: ' + m_curTokenStr);
+ }
+ }
+
+ advanceToken(Token.TOKEN_RIGHT_BRACKET);
+
+ } else { // arrays, single elements
+ parseValueElement(result.dataType, result);
+ result.arrayLength = 1;
+ }
+
+ advanceToken(Token.TOKEN_SEMI_COLON);
+
+ valueBlock.values.push(result);
+
+ };
+
+ /**
+ * @param {Object.<Array, number>} valueBlock
+ */
+ var parseValueBlock = function(valueBlock) {
+
+ advanceToken(Token.TOKEN_VALUES);
+ advanceToken(Token.TOKEN_LEFT_BRACE);
+
+ for (;;) {
+ if (
+ m_curToken === Token.TOKEN_UNIFORM ||
+ m_curToken === Token.TOKEN_INPUT ||
+ m_curToken === Token.TOKEN_OUTPUT
+ ) {
+ parseValue(valueBlock);
+ } else if (m_curToken === Token.TOKEN_RIGHT_BRACE) {
+ break;
+ } else {
+ throw Error('unexpected( token when parsing a value block: ' + m_curTokenStr);
+ }
+ }
+
+ advanceToken(Token.TOKEN_RIGHT_BRACE);
+
+ /** @type {number} */ var arrayLength = 1;
+ // compute combined array length of value block.
+ for (var i = 0; i < valueBlock.values.length; ++i) {
+ if (valueBlock.values[i].arrayLength > 1) {
+ glsShaderLibrary.de_assert(arrayLength === 1 || arrayLength === valueBlock.values[i].arrayLength);
+ arrayLength = valueBlock.values[i].arrayLength;
+ }
+ }
+
+ valueBlock.arrayLength = arrayLength;
+
+ };
+
+ /**
+ * @param {Array<tcuTestCase.DeqpTest>} shaderNodeList
+ */
+ var parseShaderCase = function(shaderNodeList) {
+
+ // parse case
+ advanceToken(Token.TOKEN_CASE);
+
+ /**
+ * @type {string}
+ * parse case name
+ */
+ var caseName = m_curTokenStr;
+ advanceToken(); // \note [pyry] All token types are allowed here.
+
+ /**
+ * @type {Array<Object>}
+ * setup case
+ */
+ var valueBlockList = [];
+
+ /** TODO: Should the default version be defined elsewhere? */
+ /** @type {string} */ var version = '100';
+ /** @type {number} */ var expectResult = glsShaderLibraryCase.expectResult.EXPECT_PASS;
+ /** @type {string} */ var description;
+ /** @type {string} */ var bothSource = '';
+ /** @type {string} */ var vertexSource = '';
+ /** @type {string} */ var fragmentSource = '';
+
+ for (;;) {
+
+ if (m_curToken === Token.TOKEN_END) {
+
+ break;
+
+ } else if (m_curToken === Token.TOKEN_DESC) {
+
+ advanceToken();
+ assumeToken(Token.TOKEN_STRING);
+
+ description = parseStringLiteral(m_curTokenStr);
+ advanceToken();
+
+ } else if (m_curToken === Token.TOKEN_EXPECT) {
+
+ advanceToken();
+ assumeToken(Token.TOKEN_IDENTIFIER);
+
+ expectResult = (function(token) {
+ switch (token) {
+ case 'pass': return glsShaderLibraryCase.expectResult.EXPECT_PASS;
+ case 'compile_fail': return glsShaderLibraryCase.expectResult.EXPECT_COMPILE_FAIL;
+ case 'link_fail': return glsShaderLibraryCase.expectResult.EXPECT_LINK_FAIL;
+ case 'compile_or_link_fail': return glsShaderLibraryCase.expectResult.EXPECT_COMPILE_LINK_FAIL;
+ case 'build_successful': return glsShaderLibraryCase.expectResult.EXPECT_BUILD_SUCCESSFUL;
+ default:
+ throw Error('invalid expected result value: ' + m_curTokenStr);
+ }
+ }(m_curTokenStr));
+
+ advanceToken();
+
+ } else if (m_curToken === Token.TOKEN_VALUES) {
+
+ /** @type {Object.<Array, number>} */ var block = glsShaderLibraryCase.genValueBlock();
+ parseValueBlock(block);
+ valueBlockList.push(block);
+
+ } else if (
+ m_curToken === Token.TOKEN_BOTH ||
+ m_curToken === Token.TOKEN_VERTEX ||
+ m_curToken === Token.TOKEN_FRAGMENT
+ ) {
+
+ /** @type {number} */ var token = m_curToken;
+ advanceToken();
+ assumeToken(Token.TOKEN_SHADER_SOURCE);
+ /** @type {string} */ var source = parseShaderSource(m_curTokenStr);
+
+ advanceToken();
+ switch (token) {
+ case Token.TOKEN_BOTH: bothSource = source; break;
+ case Token.TOKEN_VERTEX: vertexSource = source; break;
+ case Token.TOKEN_FRAGMENT: fragmentSource = source; break;
+ default: glsShaderLibrary.de_assert(false); break;
+ }
+
+ } else if (m_curToken === Token.TOKEN_VERSION) {
+
+ advanceToken();
+
+ /** @type {number} */ var versionNum = 0;
+ /** @type {string} */ var postfix = '';
+
+ assumeToken(Token.TOKEN_INT_LITERAL);
+ versionNum = parseIntLiteral(m_curTokenStr);
+ advanceToken();
+
+ if (m_curToken === Token.TOKEN_IDENTIFIER) {
+ postfix = m_curTokenStr;
+ advanceToken();
+ }
+
+ // TODO: need to fix these constants, we dont have glu
+ if (versionNum === 100 && postfix === 'es') version = '100';
+ else if (versionNum === 300 && postfix === 'es') version = '300 es';
+ else if (versionNum === 310 && postfix === 'es') version = '310 es';
+ else if (versionNum === 130) version = '130';
+ else if (versionNum === 140) version = '140';
+ else if (versionNum === 150) version = '150';
+ else if (versionNum === 330) version = '330';
+ else if (versionNum === 400) version = '400';
+ else if (versionNum === 410) version = '410';
+ else if (versionNum === 420) version = '420';
+ else if (versionNum === 430) version = '430';
+ else if (versionNum === 440) version = '440';
+ else if (versionNum === 450) version = '450';
+ else {
+ throw Error('Unknown GLSL version');
+ }
+
+ } else {
+ throw Error('unexpected token while parsing shader case: ' + m_curTokenStr);
+ }
+
+ }
+
+ advanceToken(Token.TOKEN_END); // case end
+
+ /**
+ * no ShaderCase yet?
+ * @param {?string} vert
+ * @param {?string} frag
+ * @param {glsShaderLibraryCase.caseType} type
+ * @return {Object}
+ */
+ var getShaderSpec = function(vert, frag, type) {
+ return {
+ /** @type {glsShaderLibraryCase.expectResult} */ expectResult: expectResult,
+ /** @type {glsShaderLibraryCase.caseType} */ caseType: type,
+ /** @type {Array<Object>} */ valueBlockList: valueBlockList,
+ /** @type {string} */ targetVersion: version,
+ /** @type {?string} */ vertexSource: vert,
+ /** @type {?string} */ fragmentSource: frag
+ };
+ };
+ getShaderSpec.bind(this);
+
+ if (bothSource.length) {
+
+ glsShaderLibrary.de_assert(!vertexSource);
+ glsShaderLibrary.de_assert(!fragmentSource);
+
+ shaderNodeList.push(tcuTestCase.newTest(caseName + '_vertex', description, getShaderSpec(bothSource, null,
+ glsShaderLibraryCase.caseType.CASETYPE_VERTEX_ONLY)));
+ shaderNodeList.push(tcuTestCase.newTest(caseName + '_fragment', description, getShaderSpec(null, bothSource,
+ glsShaderLibraryCase.caseType.CASETYPE_FRAGMENT_ONLY)));
+
+ } else {
+ glsShaderLibrary.de_assert(vertexSource);
+ glsShaderLibrary.de_assert(fragmentSource);
+
+ shaderNodeList.push(tcuTestCase.newTest(caseName, description, getShaderSpec(vertexSource, fragmentSource,
+ glsShaderLibraryCase.caseType.CASETYPE_COMPLETE)));
+ }
+ };
+
+ /**
+ * @param {Array<tcuTestCase.DeqpTest>} shaderNodeList
+ */
+ var parseShaderGroup = function(shaderNodeList) {
+
+ // parse 'case'
+ advanceToken(Token.TOKEN_GROUP);
+
+ /** @type {string}
+ * parse case name
+ */ var name = m_curTokenStr;
+ advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
+
+ // Parse description.
+ assumeToken(Token.TOKEN_STRING);
+ /** @type {string} */ var description = parseStringLiteral(m_curTokenStr);
+ advanceToken(Token.TOKEN_STRING);
+
+ /** @type {Array<tcuTestCase.DeqpTest>} */ var children = [];
+
+ for (;;) {
+
+ if (m_curToken === Token.TOKEN_END) {
+ break;
+ } else if (m_curToken === Token.TOKEN_GROUP) {
+ parseShaderGroup(children);
+ } else if (m_curToken === Token.TOKEN_CASE) {
+ parseShaderCase(children);
+ } else {
+ testFailed('unexpected token while parsing shader group: ' + m_curTokenStr);
+ tcuTestCase.runner.terminate();
+ }
+
+ }
+
+ advanceToken(Token.TOKEN_END); // group end
+
+ /** @type {tcuTestCase.DeqpTest} */ var groupNode = tcuTestCase.newTest(name, description, null);
+ groupNode.setChildren(children);
+
+ shaderNodeList.push(groupNode);
+
+ };
+
+ // uncomment to expose private functions
+ (function(obj) {
+ obj.priv = {
+ m_curPtr: m_curPtr,
+
+ parseError: parseError,
+ parseFloatLiteral: parseFloatLiteral,
+ parseIntLiteral: parseIntLiteral,
+ parseStringLiteral: parseStringLiteral,
+ parseShaderSource: parseShaderSource,
+ advanceTokenTester: advanceTokenTester,
+ assumeToken: assumeToken,
+ mapDataTypeToken: mapDataTypeToken,
+ getTokenName: getTokenName,
+
+ Token: Token,
+
+ parseValueElement: parseValueElement,
+ parseValue: parseValue,
+ parseValueBlock: parseValueBlock,
+ parseShaderCase: parseShaderCase,
+ parseShaderGroup: parseShaderGroup,
+
+ none: false
+ };
+ }(this));
+ //*/
+ };
+
+/**
+ * Parse the test file and execute the test cases
+ * @param {string} testName Name of the test file (without extension)
+ * @param {string} filter Optional filter. Common substring of the names of the tests that should be glsShaderLibrary.run.
+ */
+glsShaderLibrary.run = function(testName, filter) {
+ WebGLTestUtils.loadTextFileAsync(testName + '.test', function(success, content) {
+ if (success) {
+ tcuTestCase.runner.testFile = content;
+ tcuTestCase.runner.testName = testName;
+ tcuTestCase.runner.runCallback(glsShaderLibrary.processTestFile);
+ } else {
+ testFailed('Failed to load test file: ' + testName);
+ tcuTestCase.runner.terminate();
+ }
+ });
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibraryCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibraryCase.js
new file mode 100644
index 0000000000..fa9666de56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderLibraryCase.js
@@ -0,0 +1,1132 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsShaderLibraryCase');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+
+var glsShaderLibraryCase = modules.shared.glsShaderLibraryCase;
+var tcuTestCase = framework.common.tcuTestCase;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluDrawUtil = framework.opengl.gluDrawUtil;
+
+ /** @const @type {number} */ glsShaderLibraryCase.VIEWPORT_WIDTH = 128;
+ /** @const @type {number} */ glsShaderLibraryCase.VIEWPORT_HEIGHT = 128;
+
+/**
+ * Shader compilation expected result enum
+ * @enum {number}
+ */
+glsShaderLibraryCase.expectResult = {
+ EXPECT_PASS: 0,
+ EXPECT_COMPILE_FAIL: 1,
+ EXPECT_LINK_FAIL: 2,
+ EXPECT_COMPILE_LINK_FAIL: 3,
+ EXPECT_VALIDATION_FAIL: 4,
+ EXPECT_BUILD_SUCCESSFUL: 5
+};
+
+/**
+ * Test case type
+ * @enum {number}
+ */
+glsShaderLibraryCase.caseType = {
+ CASETYPE_COMPLETE: 0, //!< Has all shaders specified separately.
+ CASETYPE_VERTEX_ONLY: 1, //!< "Both" case, vertex shader sub case.
+ CASETYPE_FRAGMENT_ONLY: 2 //!< "Both" case, fragment shader sub case.
+};
+
+/**
+ * glsShaderLibraryCase.BeforeDrawValidator target type enum
+ * @enum {number}
+ */
+glsShaderLibraryCase.targetType = {
+ PROGRAM: 0,
+ PIPELINE: 1
+};
+
+/**
+ * Shader case type enum
+ * @enum {number}
+ */
+glsShaderLibraryCase.shaderCase = {
+ STORAGE_INPUT: 0,
+ STORAGE_OUTPUT: 1,
+ STORAGE_UNIFORM: 2
+};
+
+/**
+ * Checks if shader uses in/out qualifiers depending on the version
+ * @param {string} version
+ * @return {boolean} version
+ */
+glsShaderLibraryCase.usesShaderInoutQualifiers = function(version) {
+ switch (version) {
+ case '100':
+ case '130':
+ case '140':
+ case '150':
+ return false;
+
+ default:
+ return true;
+ }
+};
+
+/**
+ * Checks if version supports fragment highp precision
+ * @param {string} version
+ * @return {boolean} version ,True when is different from version 100
+ */
+glsShaderLibraryCase.supportsFragmentHighp = function(version) {
+ return version !== '100';
+};
+
+/**
+ * This functions builds a matching vertex shader for a 'both' case, when
+ * the fragment shader is being tested.
+ * We need to build attributes and varyings for each 'input'.
+ * @param { {values:Array}} valueBlock
+ * @return {string} res
+ */
+glsShaderLibraryCase.genVertexShader = function(valueBlock) {
+ /** @type {string} */ var res = '';
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ /** @type {boolean} */ var usesInout = glsShaderLibraryCase.usesShaderInoutQualifiers(state.currentTest.spec.targetVersion);
+ /** @type {string} */ var vtxIn = usesInout ? 'in' : 'attribute';
+ /** @type {string} */ var vtxOut = usesInout ? 'out' : 'varying';
+
+ res += '#version ' + state.currentTest.spec.targetVersion + '\n';
+ res += 'precision highp float;\n';
+ res += 'precision highp int;\n';
+ res += '\n';
+ res += vtxIn + ' highp vec4 dEQP_Position;\n';
+
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ var val = valueBlock.values[ndx];
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_INPUT) {
+ /** @type {string} */ var floatType = gluShaderUtil.getDataTypeFloatScalars(val.dataType);
+ res += vtxIn + ' ' + floatType + ' a_' + val.valueName + ';\n';
+
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float')
+ res += vtxOut + ' ' + floatType + ' ' + val.valueName + ';\n';
+ else
+ res += vtxOut + ' ' + floatType + ' v_' + val.valueName + ';\n';
+ }
+ }
+ res += '\n';
+
+ // Main function.
+ // - gl_Position = dEQP_Position;
+ // - for each input: write attribute directly to varying
+ res += 'void main()\n';
+ res += ' {\n';
+ res += '\tgl_Position = dEQP_Position;\n';
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ var val = valueBlock.values[ndx];
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_INPUT) {
+ /** @type {string} */ var name = val.valueName;
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float')
+ res += '\t' + name + ' = a_' + name + ';\n';
+ else
+ res += '\tv_' + name + ' = a_' + name + ';\n';
+ }
+ }
+
+ res += '}\n';
+ return res;
+};
+
+/**
+ * @param { {values:Array}} valueBlock
+ * @param {boolean} useFloatTypes
+ * @return {string} stream
+ */
+glsShaderLibraryCase.genCompareFunctions = function(valueBlock, useFloatTypes) {
+ var cmpTypeFound = {};
+ /** @type {string} */ var stream = '';
+
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT)
+ cmpTypeFound[gluShaderUtil.getDataTypeName(val.dataType)] = true;
+
+ }
+ if (useFloatTypes) {
+ if (cmpTypeFound['bool']) stream += 'bool isOk (float a, bool b) { return ((a > 0.5) == b); }\n';
+ if (cmpTypeFound['bvec2']) stream += 'bool isOk (vec2 a, bvec2 b) { return (greaterThan(a, vec2(0.5)) == b); }\n';
+ if (cmpTypeFound['bvec3']) stream += 'bool isOk (vec3 a, bvec3 b) { return (greaterThan(a, vec3(0.5)) == b); }\n';
+ if (cmpTypeFound['bvec4']) stream += 'bool isOk (vec4 a, bvec4 b) { return (greaterThan(a, vec4(0.5)) == b); }\n';
+ if (cmpTypeFound['int']) stream += 'bool isOk (float a, int b) { float atemp = a+0.5; return (float(b) <= atemp && atemp <= float(b+1)); }\n';
+ if (cmpTypeFound['ivec2']) stream += 'bool isOk (vec2 a, ivec2 b) { return (ivec2(floor(a + 0.5)) == b); }\n';
+ if (cmpTypeFound['ivec3']) stream += 'bool isOk (vec3 a, ivec3 b) { return (ivec3(floor(a + 0.5)) == b); }\n';
+ if (cmpTypeFound['ivec4']) stream += 'bool isOk (vec4 a, ivec4 b) { return (ivec4(floor(a + 0.5)) == b); }\n';
+ if (cmpTypeFound['uint']) stream += 'bool isOk (float a, uint b) { float atemp = a+0.5; return (float(b) <= atemp && atemp <= float(b+1u)); }\n';
+ if (cmpTypeFound['uvec2']) stream += 'bool isOk (vec2 a, uvec2 b) { return (uvec2(floor(a + 0.5)) == b); }\n';
+ if (cmpTypeFound['uvec3']) stream += 'bool isOk (vec3 a, uvec3 b) { return (uvec3(floor(a + 0.5)) == b); }\n';
+ if (cmpTypeFound['uvec4']) stream += 'bool isOk (vec4 a, uvec4 b) { return (uvec4(floor(a + 0.5)) == b); }\n';
+ } else {
+ if (cmpTypeFound['bool']) stream += 'bool isOk (bool a, bool b) { return (a == b); }\n';
+ if (cmpTypeFound['bvec2']) stream += 'bool isOk (bvec2 a, bvec2 b) { return (a == b); }\n';
+ if (cmpTypeFound['bvec3']) stream += 'bool isOk (bvec3 a, bvec3 b) { return (a == b); }\n';
+ if (cmpTypeFound['bvec4']) stream += 'bool isOk (bvec4 a, bvec4 b) { return (a == b); }\n';
+ if (cmpTypeFound['int']) stream += 'bool isOk (int a, int b) { return (a == b); }\n';
+ if (cmpTypeFound['ivec2']) stream += 'bool isOk (ivec2 a, ivec2 b) { return (a == b); }\n';
+ if (cmpTypeFound['ivec3']) stream += 'bool isOk (ivec3 a, ivec3 b) { return (a == b); }\n';
+ if (cmpTypeFound['ivec4']) stream += 'bool isOk (ivec4 a, ivec4 b) { return (a == b); }\n';
+ if (cmpTypeFound['uint']) stream += 'bool isOk (uint a, uint b) { return (a == b); }\n';
+ if (cmpTypeFound['uvec2']) stream += 'bool isOk (uvec2 a, uvec2 b) { return (a == b); }\n';
+ if (cmpTypeFound['uvec3']) stream += 'bool isOk (uvec3 a, uvec3 b) { return (a == b); }\n';
+ if (cmpTypeFound['uvec4']) stream += 'bool isOk (uvec4 a, uvec4 b) { return (a == b); }\n';
+ }
+
+ if (cmpTypeFound['float'])
+ stream += 'bool isOk (float a, float b, float eps) { return (abs(a-b) <= (eps*abs(b) + eps)); }\n';
+ if (cmpTypeFound['vec2'])
+ stream += 'bool isOk (vec2 a, vec2 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n';
+ if (cmpTypeFound['vec3'])
+ stream += 'bool isOk (vec3 a, vec3 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n';
+ if (cmpTypeFound['vec4'])
+ stream += 'bool isOk (vec4 a, vec4 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n';
+
+ if (cmpTypeFound['mat2'])
+ stream += 'bool isOk (mat2 a, mat2 b, float eps) { vec2 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec2(eps))); }\n';
+ if (cmpTypeFound['mat2x3'])
+ stream += 'bool isOk (mat2x3 a, mat2x3 b, float eps) { vec3 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec3(eps))); }\n';
+ if (cmpTypeFound['mat2x4'])
+ stream += 'bool isOk (mat2x4 a, mat2x4 b, float eps) { vec4 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec4(eps))); }\n';
+ if (cmpTypeFound['mat3x2'])
+ stream += 'bool isOk (mat3x2 a, mat3x2 b, float eps) { vec2 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec2(eps))); }\n';
+ if (cmpTypeFound['mat3'])
+ stream += 'bool isOk (mat3 a, mat3 b, float eps) { vec3 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec3(eps))); }\n';
+ if (cmpTypeFound['mat3x4'])
+ stream += 'bool isOk (mat3x4 a, mat3x4 b, float eps) { vec4 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec4(eps))); }\n';
+ if (cmpTypeFound['mat4x2'])
+ stream += 'bool isOk (mat4x2 a, mat4x2 b, float eps) { vec2 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec2(eps))); }\n';
+ if (cmpTypeFound['mat4x3'])
+ stream += 'bool isOk (mat4x3 a, mat4x3 b, float eps) { vec3 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec3(eps))); }\n';
+ if (cmpTypeFound['mat4'])
+ stream += 'bool isOk (mat4 a, mat4 b, float eps) { vec4 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec4(eps))); }\n';
+
+ return stream;
+};
+
+/**
+ * @param {string} dstVec4Var
+ * @param { {values:Array}} valueBlock
+ * @param {string} nonFloatNamePrefix
+ * @param {?string=} checkVarName
+ * @return {string} output
+ */
+glsShaderLibraryCase.genCompareOp = function(dstVec4Var, valueBlock, nonFloatNamePrefix, checkVarName) {
+
+ /** @type {boolean} */ var isFirstOutput = true;
+ /** @type {string} */ var output = '';
+
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ /** @type {string} */ var valueName = val.valueName;
+
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT) {
+ // Check if we're only interested in one variable (then skip if not the right one).
+ if (checkVarName && (valueName !== checkVarName))
+ continue;
+
+ // Prefix.
+ if (isFirstOutput) {
+ output += 'bool RES = ';
+ isFirstOutput = false;
+ } else
+ output += 'RES = RES && ';
+
+ // Generate actual comparison.
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float')
+ output += 'isOk(' + valueName + ', ref_' + valueName + ', 0.05);\n';
+ else
+ output += 'isOk(' + nonFloatNamePrefix + valueName + ', ref_' + valueName + ');\n';
+ }
+ // \note Uniforms are already declared in shader.
+ }
+
+ if (isFirstOutput)
+ output += dstVec4Var + ' = vec4(1.0);\n'; // \todo [petri] Should we give warning if not expect-failure case?
+ else
+ output += dstVec4Var + ' = vec4(RES, RES, RES, 1.0);\n';
+
+ return output;
+};
+
+/**
+ * @param { {values:Array}} valueBlock
+ * @return {string} shader
+ */
+glsShaderLibraryCase.genFragmentShader = function(valueBlock) {
+ /** @type {string} */ var shader = '';
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ /** @type {boolean} */ var usesInout = glsShaderLibraryCase.usesShaderInoutQualifiers(state.currentTest.spec.targetVersion);
+ /** @type {string} */ var vtxIn = usesInout ? 'in' : 'attribute';
+ /** @type {string} */ var vtxOut = usesInout ? 'out' : 'varying';
+ /** @type {boolean} */ var customColorOut = usesInout;
+ /** @type {string} */ var fragIn = usesInout ? 'in' : 'varying';
+ /** @type {string} */ var prec = glsShaderLibraryCase.supportsFragmentHighp(state.currentTest.spec.targetVersion) ? 'highp' : 'mediump';
+
+ shader += '#version ' + state.currentTest.spec.targetVersion + '\n';
+
+ shader += 'precision ' + prec + ' float;\n';
+ shader += 'precision ' + prec + ' int;\n';
+ shader += '\n';
+
+ if (customColorOut) {
+ shader += 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+ shader += '\n';
+ }
+
+ shader += glsShaderLibraryCase.genCompareFunctions(valueBlock, true);
+ shader += '\n';
+
+ // Declarations (varying, reference for each output).
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ /** @type {string} */ var floatType = gluShaderUtil.getDataTypeFloatScalars(val.dataType);
+ /** @type {string} */ var refType = gluShaderUtil.getDataTypeName(val.dataType);
+
+ if (val.storageType == glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT) {
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float')
+ shader += fragIn + ' ' + floatType + ' ' + val.valueName + ';\n';
+ else
+ shader += fragIn + ' ' + floatType + ' v_' + val.valueName + ';\n';
+
+ shader += 'uniform ' + refType + ' ref_' + val.valueName + ';\n';
+ }
+ }
+
+ shader += '\n';
+ shader += 'void main()\n';
+ shader += ' {\n';
+
+ shader += '\t';
+ shader += glsShaderLibraryCase.genCompareOp(customColorOut ? 'dEQP_FragColor' : 'gl_FragColor', valueBlock, 'v_', null);
+
+ shader += '}\n';
+ return shader;
+};
+
+glsShaderLibraryCase.caseRequirement = (function() {
+
+/**
+ * @constructor
+ */
+var CaseRequirement = function() {
+
+/**
+ * @param {number} shaderType
+ * @return {boolean}
+ */
+ this.isAffected = function(shaderType) {
+ for (var i = 0; i < this.shaderTypes.length; i++)
+ if (this.shaderTypes[i] === shaderType)
+ return true;
+ return false;
+ };
+
+ this.checkRequirements = function(gl) {
+ if (this.type === requirementType.EXTENSION) {
+ var extns = gl.getSupportedExtensions();
+ for (var i = 0; i < extns.length; i++)
+ for (var j = 0; j < this.requirements.length; j++)
+ if (extns[i] === this.requirements[j]) {
+ this.supportedExtension = this.requirements[j];
+ return true;
+ }
+ if (this.requirements.length === 1)
+ throw Error('Test requires extension of ' + this.requirements[0]);
+ else
+ throw Error('Test requires any extension of ' + this.requirements);
+ } else if (this.type === requirementType.IMPLEMENTATION_LIMIT) {
+ var value = gl.getParameter(this.enumName);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Failed to read parameter ' + this.enumName, false, true);
+
+ if (!(value > this.referenceValue))
+ throw Error('Test requires ' + this.enumName + ' (' + value + ') > ' + this.referenceValue);
+ }
+ };
+
+ this.getSupportedExtension = function() {
+ return this.supportedExtension;
+ };
+
+};
+
+var createAnyExtensionRequirement = function(requirements, shaderTypes) {
+ var cr = new CaseRequirement();
+ cr.type = requirementType.EXTENSION;
+ cr.requirements = requirements;
+ cr.shaderTypes = shaderTypes;
+ return cr;
+};
+
+var createLimitRequirement = function(enumName, ref) {
+ var cr = new CaseRequirement();
+ cr.type = requirementType.IMPLEMENTATION_LIMIT;
+ cr.enumName = enumName;
+ cr.referenceValue = ref;
+};
+
+/**
+ * @enum {number}
+ */
+var requirementType = {
+ EXTENSION: 0,
+ IMPLEMENTATION_LIMIT: 1
+};
+
+return {
+ createAnyExtensionRequirement: createAnyExtensionRequirement,
+ createLimitRequirement: createLimitRequirement,
+ requirementType: requirementType
+};
+
+}());
+
+/** Specialize a shader only for the vertex test case.
+ * @param {string} baseCode
+ * @param {number} shaderType
+ * @param {Array<Object>} requirements
+ * @return {string} resultBuf
+ */
+glsShaderLibraryCase.injectExtensionRequirements = function(baseCode, shaderType, requirements) {
+/**
+ * @param {Array<Object>} requirements
+ * @param {number} shaderType
+ * @return {string} buf
+ */
+ var generateExtensionStatements = function(requirements, shaderType) {
+ /** @type {string} */ var buf = '';
+
+ if (requirements)
+ for (var ndx = 0; ndx < requirements.length; ndx++)
+ if (requirements[ndx].type === glsShaderLibraryCase.caseRequirement.requirementType.EXTENSION &&
+ requirements[ndx].isAffected(shaderType))
+ buf += '#extension ' + requirements[ndx].getSupportedExtension() + ' : require\n';
+
+ return buf;
+ };
+
+ /** @type {string} */ var extensions = generateExtensionStatements(requirements, shaderType);
+
+ if (extensions.length === 0)
+ return baseCode;
+
+ /** @type {Array<string>} */ var splitLines = baseCode.split('\n');
+ /** @type {boolean} */ var firstNonPreprocessorLine = true;
+ /** @type {string} */ var resultBuf = '';
+
+ for (var i = 0; i < splitLines.length; i++) {
+ /** @const @type {boolean} */ var isPreprocessorDirective = (splitLines[i].match(/^\s*#/) !== null);
+
+ if (!isPreprocessorDirective && firstNonPreprocessorLine) {
+ firstNonPreprocessorLine = false;
+ resultBuf += extensions;
+ }
+
+ resultBuf += splitLines[i] + '\n';
+ }
+
+ return resultBuf;
+};
+
+/** Specialize a shader for the vertex shader test case.
+ * @param {string} src
+ * @param { {values:Array}} valueBlock
+ * @return {string} withExt
+ */
+glsShaderLibraryCase.specializeVertexShader = function(src, valueBlock) {
+ /** @type {string} */ var decl = '';
+ /** @type {string} */ var setup = '';
+ /** @type {string} */ var output = '';
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ /** @type {boolean} */ var usesInout = glsShaderLibraryCase.usesShaderInoutQualifiers(state.currentTest.spec.targetVersion);
+ /** @type {string} */ var vtxIn = usesInout ? 'in' : 'attribute';
+ /** @type {string} */ var vtxOut = usesInout ? 'out' : 'varying';
+
+ // Output (write out position).
+ output += 'gl_Position = dEQP_Position;\n';
+
+ // Declarations (position + attribute for each input, varying for each output).
+ decl += vtxIn + ' highp vec4 dEQP_Position;\n';
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ /** @type {string} */ var valueName = val.valueName;
+ /** @type {string} */ var floatType = gluShaderUtil.getDataTypeFloatScalars(val.dataType);
+ /** @type {string} */ var dataTypeName = gluShaderUtil.getDataTypeName(val.dataType);
+
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_INPUT) {
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float') {
+ decl += vtxIn + ' ' + floatType + ' ' + valueName + ';\n';
+ } else {
+ decl += vtxIn + ' ' + floatType + ' a_' + valueName + ';\n';
+ setup += dataTypeName + ' ' + valueName + ' = ' + dataTypeName + '(a_' + valueName + ');\n';
+ }
+ } else if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT) {
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float')
+ decl += vtxOut + ' ' + floatType + ' ' + valueName + ';\n';
+ else {
+ decl += vtxOut + ' ' + floatType + ' v_' + valueName + ';\n';
+ decl += dataTypeName + ' ' + valueName + ';\n';
+
+ output += 'v_' + valueName + ' = ' + floatType + '(' + valueName + ');\n';
+ }
+ }
+ }
+
+ /** @type {string} */
+ var baseSrc = src
+ .replace(/\$\{DECLARATIONS\}/g, decl)
+ .replace(/\$\{DECLARATIONS:single-line\}/g, decl.replace(/\n/g, ' '))
+ .replace(/\$\{SETUP\}/g, setup)
+ .replace(/\$\{OUTPUT\}/g, output)
+ .replace(/\$\{POSITION_FRAG_COLOR\}/g, 'gl_Position');
+
+ /** @type {string} */
+ var withExt = glsShaderLibraryCase.injectExtensionRequirements(baseSrc, gluShaderProgram.shaderType.VERTEX, state.currentTest.spec.requirements);
+
+ return withExt;
+};
+
+/** Specialize a shader only for the vertex test case.
+ * @param {string} src
+ * @param { {values:Array}} valueBlock
+ * @return {string} withExt
+ */
+glsShaderLibraryCase.specializeVertexOnly = function(src, valueBlock) {
+ /** @type {string} */ var decl = '';
+ /** @type {string} */ var setup = '';
+ /** @type {string} */ var output = '';
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ /** @type {boolean} */ var usesInout = glsShaderLibraryCase.usesShaderInoutQualifiers(state.currentTest.spec.targetVersion);
+ /** @type {string} */ var vtxIn = usesInout ? 'in' : 'attribute';
+
+ // Output (write out position).
+ output += 'gl_Position = dEQP_Position;\n';
+
+ // Declarations (position + attribute for each input, varying for each output).
+ decl += vtxIn + ' highp vec4 dEQP_Position;\n';
+
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ /** @type {string} */ var valueName = val.valueName;
+ /** @type {string} */ var type = gluShaderUtil.getDataTypeName(val.dataType);
+
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_INPUT) {
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float') {
+ decl += vtxIn + ' ' + type + ' ' + valueName + ';\n';
+ } else {
+ /** @type {string} */ var floatType = gluShaderUtil.getDataTypeFloatScalars(val.dataType);
+
+ decl += vtxIn + ' ' + floatType + ' a_' + valueName + ';\n';
+ setup += type + ' ' + valueName + ' = ' + type + '(a_' + valueName + ');\n';
+ }
+ } else if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_UNIFORM &&
+ !val.valueName.match('\\.'))
+ decl += 'uniform ' + type + ' ' + valueName + ';\n';
+ }
+
+ /** @type {string} */
+ var baseSrc = src
+ .replace(/\$\{VERTEX_DECLARATIONS\}/g, decl)
+ .replace(/\$\{VERTEX_DECLARATIONS:single-line\}/g, decl.replace(/\n/g, ' '))
+ .replace(/\$\{VERTEX_SETUP\}/g, setup)
+ .replace(/\$\{VERTEX_OUTPUT\}/g, output);
+
+ /** @type {string} */
+ var withExt = glsShaderLibraryCase.injectExtensionRequirements(baseSrc, gluShaderProgram.shaderType.VERTEX, state.currentTest.spec.requirements);
+
+ return withExt;
+};
+
+/** Specialize a shader for the fragment shader test case.
+ * @param {string} src
+ * @param { {values:Array}} valueBlock
+ * @return {string} withExt
+ */
+glsShaderLibraryCase.specializeFragmentShader = function(src, valueBlock) {
+ /** @type {string} */ var decl = '';
+ /** @type {string} */ var setup = '';
+ /** @type {string} */ var output = '';
+
+ /** @type {Object} */ var state = tcuTestCase.runner;
+
+ /** @type {boolean} */ var usesInout = glsShaderLibraryCase.usesShaderInoutQualifiers(state.currentTest.spec.targetVersion);
+ /** @type {boolean} */ var customColorOut = usesInout;
+ /** @type {string} */ var fragIn = usesInout ? 'in' : 'varying';
+ /** @type {string} */ var fragColor = customColorOut ? 'dEQP_FragColor' : 'gl_FragColor';
+
+ decl += glsShaderLibraryCase.genCompareFunctions(valueBlock, false);
+ output += glsShaderLibraryCase.genCompareOp(fragColor, valueBlock, '', null);
+
+ if (customColorOut)
+ decl += 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ /** @type {string} */ var valueName = val.valueName;
+ /** @type {string} */ var floatType = gluShaderUtil.getDataTypeFloatScalars(val.dataType);
+ /** @type {string} */ var refType = gluShaderUtil.getDataTypeName(val.dataType);
+
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_INPUT) {
+ if (gluShaderUtil.getDataTypeScalarType(val.dataType) === 'float')
+ decl += fragIn + ' ' + floatType + ' ' + valueName + ';\n';
+ else {
+ decl += fragIn + ' ' + floatType + ' v_' + valueName + ';\n';
+ var offset = gluShaderUtil.isDataTypeIntOrIVec(val.dataType) ? ' * 1.0025' : ''; // \todo [petri] bit of a hack to avoid errors in chop() due to varying interpolation
+ setup += refType + ' ' + valueName + ' = ' + refType + '(v_' + valueName + offset + ');\n';
+ }
+ } else if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT) {
+ decl += 'uniform ' + refType + ' ref_' + valueName + ';\n';
+ decl += refType + ' ' + valueName + ';\n';
+ }
+ }
+
+ /* \todo [2010-04-01 petri] Check all outputs. */
+
+ /** @type {string} */
+ var baseSrc = src
+ .replace(/\$\{DECLARATIONS\}/g, decl)
+ .replace(/\$\{DECLARATIONS:single-line\}/g, decl.replace(/\n/g, ' '))
+ .replace(/\$\{SETUP\}/g, setup)
+ .replace(/\$\{OUTPUT\}/g, output)
+ .replace(/\$\{POSITION_FRAG_COLOR\}/g, fragColor);
+
+ /** @type {string} */
+ var withExt = glsShaderLibraryCase.injectExtensionRequirements(baseSrc, gluShaderProgram.shaderType.FRAGMENT, state.currentTest.spec.requirements);
+
+ return withExt;
+};
+
+/** Specialize a shader only for the fragment test case.
+ * @param {string} src
+ * @param { {values:Array}} valueBlock
+ * @return {string} withExt
+ */
+glsShaderLibraryCase.specializeFragmentOnly = function(src, valueBlock) {
+ /** @type {string} */ var decl = '';
+ /** @type {string} */ var output = '';
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ /** @type {boolean} */ var usesInout = glsShaderLibraryCase.usesShaderInoutQualifiers(state.currentTest.spec.targetVersion);
+ /** @type {boolean} */ var customColorOut = usesInout;
+ /** @type {string} */ var fragIn = usesInout ? 'in' : 'varying';
+ /** @type {string} */ var fragColor = customColorOut ? 'dEQP_FragColor' : 'gl_FragColor';
+
+ decl += glsShaderLibraryCase.genCompareFunctions(valueBlock, false);
+ output += glsShaderLibraryCase.genCompareOp(fragColor, valueBlock, '', null);
+
+ if (customColorOut)
+ decl += 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+
+ for (var ndx = 0; ndx < valueBlock.values.length; ndx++) {
+ /** @type {Array} */ var val = valueBlock.values[ndx];
+ /** @type {string} */ var valueName = val.valueName;
+ /** @type {string} */ var floatType = gluShaderUtil.getDataTypeFloatScalars(val.dataType);
+ /** @type {string} */ var refType = gluShaderUtil.getDataTypeName(val.dataType);
+
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT) {
+ decl += 'uniform ' + refType + ' ref_' + valueName + ';\n';
+ decl += refType + ' ' + valueName + ';\n';
+ } else if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_UNIFORM &&
+ !valueName.match('\\.'))
+ decl += 'uniform ' + refType + ' ' + valueName + ';\n';
+ }
+
+ /** @type {string} */
+ var baseSrc = src
+ .replace(/\$\{FRAGMENT_DECLARATIONS\}/g, decl)
+ .replace(/\$\{FRAGMENT_DECLARATIONS:single-line\}/g, decl.replace(/\n/g, ' '))
+ .replace(/\$\{FRAGMENT_OUTPUT\}/g, output)
+ .replace(/\$\{FRAG_COLOR\}/g, fragColor);
+
+ /** @type {string} */
+ var withExt = glsShaderLibraryCase.injectExtensionRequirements(baseSrc, gluShaderProgram.shaderType.FRAGMENT, state.currentTest.spec.requirements);
+
+ return withExt;
+};
+
+/**
+ * Is tessellation present
+ * @return {boolean} True if tessellation is present
+ */
+glsShaderLibraryCase.isTessellationPresent = function() {
+ /* TODO: GLES 3.1: implement */
+ return false;
+};
+
+glsShaderLibraryCase.setUniformValue = function(gl, pipelinePrograms, name, val, arrayNdx) {
+ /** @type {boolean} */ var foundAnyMatch = false;
+
+ for (var programNdx = 0; programNdx < pipelinePrograms.length; ++programNdx) {
+ /** @const @type {WebGLUniformLocation} */ var loc = gl.getUniformLocation(pipelinePrograms[programNdx], name);
+ /** @const @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(val.dataType);
+ /** @const @type {number} */ var elemNdx = (val.arrayLength === 1) ? (0) : (arrayNdx * scalarSize);
+
+ if (!loc)
+ continue;
+
+ foundAnyMatch = true;
+
+ gl.useProgram(pipelinePrograms[programNdx]);
+
+ /** @type {Array} */ var element = val.elements.slice(elemNdx, elemNdx + scalarSize);
+ switch (val.dataType) {
+ case gluShaderUtil.DataType.FLOAT: gl.uniform1fv(loc, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_VEC2: gl.uniform2fv(loc, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_VEC3: gl.uniform3fv(loc, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_VEC4: gl.uniform4fv(loc, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2: gl.uniformMatrix2fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3: gl.uniformMatrix3fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4: gl.uniformMatrix4fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.INT: gl.uniform1iv(loc, new Int32Array(element)); break;
+ case gluShaderUtil.DataType.INT_VEC2: gl.uniform2iv(loc, new Int32Array(element)); break;
+ case gluShaderUtil.DataType.INT_VEC3: gl.uniform3iv(loc, new Int32Array(element)); break;
+ case gluShaderUtil.DataType.INT_VEC4: gl.uniform4iv(loc, new Int32Array(element)); break;
+
+ /** TODO: What type should be used for bool uniforms? */
+ case gluShaderUtil.DataType.BOOL: gl.uniform1iv(loc, new Int32Array(element)); break;
+ case gluShaderUtil.DataType.BOOL_VEC2: gl.uniform2iv(loc, new Int32Array(element)); break;
+ case gluShaderUtil.DataType.BOOL_VEC3: gl.uniform3iv(loc, new Int32Array(element)); break;
+ case gluShaderUtil.DataType.BOOL_VEC4: gl.uniform4iv(loc, new Int32Array(element)); break;
+
+ case gluShaderUtil.DataType.UINT: gl.uniform1uiv(loc, new Uint32Array(element)); break;
+ case gluShaderUtil.DataType.UINT_VEC2: gl.uniform2uiv(loc, new Uint32Array(element)); break;
+ case gluShaderUtil.DataType.UINT_VEC3: gl.uniform3uiv(loc, new Uint32Array(element)); break;
+ case gluShaderUtil.DataType.UINT_VEC4: gl.uniform4uiv(loc, new Uint32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: gl.uniformMatrix2x3fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: gl.uniformMatrix2x4fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: gl.uniformMatrix3x2fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: gl.uniformMatrix3x4fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: gl.uniformMatrix4x2fv(loc, false, new Float32Array(element)); break;
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: gl.uniformMatrix4x3fv(loc, false, new Float32Array(element)); break;
+
+ default:
+ testFailed('Unknown data type ' + val.dataType);
+ }
+ }
+
+ if (!foundAnyMatch)
+ bufferedLogToConsole('WARNING // Uniform \"' + name + '\" location is not valid, location = -1. Cannot set value to the uniform.');
+};
+
+/**
+ * Evaluates pixels, if they are white, black or there is any unexpected result
+ * @param {gluDrawUtil.Surface} surface
+ * @param {number} minX
+ * @param {number} maxX
+ * @param {number} minY
+ * @param {number} maxY
+ * @return {boolean} True if tessellation is present
+ */
+glsShaderLibraryCase.checkPixels = function(surface, minX, maxX, minY, maxY) {
+ /** @type {boolean} */ var allWhite = true;
+ /** @type {boolean} */ var allBlack = true;
+ /** @type {boolean} */ var anyUnexpected = false;
+
+ assertMsgOptions((maxX > minX) && (maxY > minY), 'glsShaderLibraryCase.checkPixels sanity check', false, true);
+
+ for (var y = minY; y <= maxY; y++) {
+ for (var x = minX; x <= maxX; x++) {
+ /** @type {number} */ var pixel = surface.getPixelUintRGB8(x, y);
+ /** @type {boolean} */ var isWhite = (pixel == 0xFFFFFF);
+ /** @type {boolean} */ var isBlack = (pixel == 0x000000);
+
+ allWhite = allWhite && isWhite;
+ allBlack = allBlack && isBlack;
+ anyUnexpected = anyUnexpected || (!isWhite && !isBlack);
+
+ // Early terminate as soon as we know the check hasn't passed
+ if (!allWhite && !allBlack)
+ break;
+ }
+ }
+
+ if (!allWhite) {
+ if (anyUnexpected)
+ testFailed('WARNING: expecting all rendered pixels to be white or black, but got other colors as well!');
+ else if (!allBlack)
+ testFailed('WARNING: got inconsistent results over the image, when all pixels should be the same color!');
+
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Initialize a test case
+ */
+glsShaderLibraryCase.init = function() {
+/** @type {Object} */ var state = tcuTestCase.runner;
+/** @type {Object} */ var test = state.currentTest;
+
+ bufferedLogToConsole('Processing ' + test.fullName());
+
+ if (!test.spec.valueBlockList.length)
+ test.spec.valueBlockList.push(glsShaderLibraryCase.genValueBlock());
+ /** @type { {values:Array}} */ var valueBlock = test.spec.valueBlockList[0];
+
+ if (test.spec.requirements)
+ for (var ndx = 0; ndx < test.spec.requirements.length; ++ndx)
+ test.spec.requirements[ndx].checkRequirements();
+
+ /** @type {Array<gluShaderProgram.ShaderInfo>} */ var sources = [];
+
+ if (test.spec.caseType === glsShaderLibraryCase.caseType.CASETYPE_COMPLETE) {
+ /** @type {string} */ var vertex = glsShaderLibraryCase.specializeVertexOnly(test.spec.vertexSource, valueBlock);
+ /** @type {string} */ var fragment = glsShaderLibraryCase.specializeFragmentOnly(test.spec.fragmentSource, valueBlock);
+ sources.push(gluShaderProgram.genVertexSource(vertex));
+ sources.push(gluShaderProgram.genFragmentSource(fragment));
+ } else if (test.spec.caseType === glsShaderLibraryCase.caseType.CASETYPE_VERTEX_ONLY) {
+ sources.push(gluShaderProgram.genVertexSource(glsShaderLibraryCase.specializeVertexShader(test.spec.vertexSource, valueBlock)));
+ sources.push(gluShaderProgram.genFragmentSource(glsShaderLibraryCase.genFragmentShader(valueBlock)));
+ } else if (test.spec.caseType === glsShaderLibraryCase.caseType.CASETYPE_FRAGMENT_ONLY) {
+ sources.push(gluShaderProgram.genVertexSource(glsShaderLibraryCase.genVertexShader(valueBlock)));
+ sources.push(gluShaderProgram.genFragmentSource(glsShaderLibraryCase.specializeFragmentShader(test.spec.fragmentSource, valueBlock)));
+ }
+
+ test.programs = [];
+ test.programs.push({
+ programSources: {
+ sources: sources
+ }
+ }
+ );
+
+};
+
+/**
+ * Execute a test case
+ * @return {boolean} True if test case passed
+ */
+glsShaderLibraryCase.execute = function() {
+ /** @const @type {number} */ var quadSize = 1.0;
+ /** @const @type {Array<number>} */
+ var s_positions = [
+ -quadSize, -quadSize, 0.0, 1.0,
+ -quadSize, +quadSize, 0.0, 1.0,
+ +quadSize, -quadSize, 0.0, 1.0,
+ +quadSize, +quadSize, 0.0, 1.0
+ ];
+
+ /** @const @type {Array<number>} */
+ var s_indices = [
+ 0, 1, 2,
+ 1, 3, 2
+ ];
+
+ var wtu = WebGLTestUtils;
+ /** @type {WebGL2RenderingContext} */ var gl = wtu.create3DContext('canvas');
+ /** @type {Object} */ var state = tcuTestCase.runner;
+ /** @type {Object} */ var test = state.currentTest;
+ /** @type {Object} */ var spec = test.spec;
+
+ // Compute viewport.
+ /* TODO: original code used random number generator to compute viewport, we use whole canvas */
+ /** @const @type {number} */ var width = Math.min(canvas.width, glsShaderLibraryCase.VIEWPORT_WIDTH);
+ /** @const @type {number} */ var height = Math.min(canvas.height, glsShaderLibraryCase.VIEWPORT_HEIGHT);
+ /** @const @type {number} */ var viewportX = 0;
+ /** @const @type {number} */ var viewportY = 0;
+ /** @const @type {number} */ var numVerticesPerDraw = 4;
+ /** @const @type {boolean} */ var tessellationPresent = glsShaderLibraryCase.isTessellationPresent();
+
+ /** @type {boolean} */ var allCompilesOk = true;
+ /** @type {boolean} */ var allLinksOk = true;
+ /** @type {?string} */ var failReason = null;
+
+ /** @type {number} */ var vertexProgramID = -1;
+ /** @type {Array<WebGLProgram>} */ var pipelineProgramIDs = [];
+ /** @type {Array<gluShaderProgram.ShaderProgram>} */ var programs = [];
+ var programPipeline;
+
+ // Set the name of the current test so testFailedOptions/testPassedOptions can use it.
+ setCurrentTestName(test.fullName());
+ debug('Start testcase: ' + test.fullName());
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Start testcase: ' + test.fullName(), false, true);
+
+ /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, test.programs[0].programSources);
+
+ vertexProgramID = program.getProgram();
+ pipelineProgramIDs.push(program.getProgram());
+ programs.push(program);
+
+ // Check that compile/link results are what we expect.
+
+ for (var i = 0; i < program.shaders.length; i++) {
+ if (!program.shaders[i].info.compileOk)
+ allCompilesOk = false;
+ }
+
+ if (!program.getProgramInfo().linkOk)
+ allLinksOk = false;
+
+ switch (spec.expectResult) {
+ case glsShaderLibraryCase.expectResult.EXPECT_PASS:
+ case glsShaderLibraryCase.expectResult.EXPECT_VALIDATION_FAIL:
+ case glsShaderLibraryCase.expectResult.EXPECT_BUILD_SUCCESSFUL:
+ if (!allCompilesOk)
+ failReason = 'expected shaders to compile and link properly, but failed to compile.';
+ else if (!allLinksOk)
+ failReason = 'expected shaders to compile and link properly, but failed to link.';
+ break;
+
+ case glsShaderLibraryCase.expectResult.EXPECT_COMPILE_FAIL:
+ if (allCompilesOk && !allLinksOk)
+ failReason = 'expected compilation to fail, but shaders compiled and link failed.';
+ else if (allCompilesOk)
+ failReason = 'expected compilation to fail, but shaders compiled correctly.';
+ break;
+
+ case glsShaderLibraryCase.expectResult.EXPECT_LINK_FAIL:
+ if (!allCompilesOk)
+ failReason = 'expected linking to fail, but unable to compile.';
+ else if (allLinksOk)
+ failReason = 'expected linking to fail, but passed.';
+ break;
+
+ case glsShaderLibraryCase.expectResult.EXPECT_COMPILE_LINK_FAIL:
+ if (allCompilesOk && allLinksOk)
+ failReason = 'expected compile or link to fail, but passed.';
+ break;
+
+ default:
+ testFailedOptions('Unknown expected result', true);
+ return false;
+ }
+
+ if (failReason != null) {
+ // \todo [2010-06-07 petri] These should be handled in the test case?
+
+ // If implementation parses shader at link time, report it as quality warning.
+ if (spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_COMPILE_FAIL && allCompilesOk && !allLinksOk)
+ bufferedLogToConsole('Quality warning: implementation parses shader at link time: ' + failReason);
+ else {
+ bufferedLogToConsole('ERROR: ' + failReason);
+ testFailedOptions(failReason, true);
+ }
+ return false;
+ }
+
+ // Return if compile/link expected to fail.
+ if (spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_COMPILE_FAIL ||
+ spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_COMPILE_LINK_FAIL ||
+ spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_LINK_FAIL ||
+ spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_BUILD_SUCCESSFUL) {
+ if (spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_BUILD_SUCCESSFUL) {
+ testPassedOptions('Compile/link is expected to succeed', true);
+ } else {
+ testPassedOptions('Compile/link is expected to fail', true);
+ }
+ setCurrentTestName('');
+ return (failReason === null);
+ }
+
+ // Setup viewport.
+ gl.viewport(viewportX, viewportY, width, height);
+
+ // Start using program
+ gl.useProgram(vertexProgramID);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'glUseProgram()', false, true);
+
+ // Fetch location for positions positions.
+ /** @type {number} */ var positionLoc = gl.getAttribLocation(vertexProgramID, 'dEQP_Position');
+ if (positionLoc === -1) {
+ testFailedOptions("no location found for attribute 'dEQP_Position'", true);
+ return false;
+ }
+
+ // Iterate all value blocks.
+ for (var blockNdx = 0; blockNdx < spec.valueBlockList.length; blockNdx++) {
+ /** @type { {values:Array}} */ var block = spec.valueBlockList[blockNdx];
+
+ // always render at least one pass even if there is no input/output data
+ /** @const @type {number} */ var numRenderPasses = Math.max(block.arrayLength, 1);
+
+ // Iterate all array sub-cases.
+ for (var arrayNdx = 0; arrayNdx < numRenderPasses; arrayNdx++) {
+ /** @const @type {number} */ var numValues = block.values.length;
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
+ /** @type {number} */ var attribValueNdx = 0;
+ /** @type {number} */ var postDrawError;
+
+ vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, positionLoc, 4, numVerticesPerDraw, s_positions));
+
+ // Collect VA pointer for inputs
+ for (var valNdx = 0; valNdx < numValues; valNdx++) {
+ var val = block.values[valNdx];
+ /** @const @type {string} */ var valueName = val.valueName;
+ /** @const @type {gluShaderUtil.DataType} */ var dataType = val.dataType;
+ /** @const @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(val.dataType);
+
+ if (val.storageType === glsShaderLibraryCase.shaderCase.STORAGE_INPUT) {
+ // Replicate values four times.
+ /** @type {Array} */ var scalars = [];
+
+ for (var repNdx = 0; repNdx < numVerticesPerDraw; repNdx++)
+ for (var ndx = 0; ndx < scalarSize; ndx++)
+ scalars[repNdx * scalarSize + ndx] = val.elements[arrayNdx * scalarSize + ndx];
+
+ // Attribute name prefix.
+ /** @type {string} */ var attribPrefix = '';
+ // \todo [2010-05-27 petri] Should latter condition only apply for vertex cases (or actually non-fragment cases)?
+ if ((spec.caseType === glsShaderLibraryCase.caseType.CASETYPE_FRAGMENT_ONLY) || (gluShaderUtil.getDataTypeScalarType(dataType) !== 'float'))
+ attribPrefix = 'a_';
+
+ // Input always given as attribute.
+ /** @type {string} */ var attribName = attribPrefix + valueName;
+ /** @type {number} */ var attribLoc = gl.getAttribLocation(vertexProgramID, attribName);
+ if (attribLoc === -1) {
+ bufferedLogToConsole("Warning: no location found for attribute '" + attribName + "'");
+ continue;
+ }
+
+ if (gluShaderUtil.isDataTypeMatrix(dataType)) {
+ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(dataType);
+ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(dataType);
+
+ assertMsgOptions(scalarSize === numCols * numRows, 'Matrix size sanity check', false, true);
+
+ for (var i = 0; i < numCols; i++)
+ vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, attribLoc + i, numRows, numVerticesPerDraw, scalars, scalarSize * 4, i * numRows * 4));
+ } else
+ vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, attribLoc, scalarSize, numVerticesPerDraw, scalars));
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'set vertex attrib array', false, true);
+ }
+ }
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'before set uniforms', false, true);
+
+ // set uniform values for outputs (refs).
+ for (var valNdx = 0; valNdx < numValues; valNdx++) {
+ /** @type {Array} */ var val1 = block.values[valNdx];
+ /** @type {string} */ var valueName1 = val1.valueName;
+
+ if (val1.storageType === glsShaderLibraryCase.shaderCase.STORAGE_OUTPUT) {
+ // Set reference value.
+ glsShaderLibraryCase.setUniformValue(gl, pipelineProgramIDs, 'ref_' + valueName1, val1, arrayNdx);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'set reference uniforms', false, true);
+ } else if (val1.storageType === glsShaderLibraryCase.shaderCase.STORAGE_UNIFORM) {
+ glsShaderLibraryCase.setUniformValue(gl, pipelineProgramIDs, valueName1, val1, arrayNdx);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'set uniforms', false, true);
+ }
+ }
+
+ // Clear.
+ gl.clearColor(0.125, 0.25, 0.5, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'clear buffer', false, true);
+
+ // Use program or pipeline
+ if (spec.separatePrograms)
+ gl.useProgram(null);
+ else
+ gl.useProgram(vertexProgramID);
+
+ // Draw.
+ // if (tessellationPresent) {
+ // gl.patchParameteri(gl.PATCH_VERTICES, 3);
+ // assertMsgOptions(gl.getError() === gl.NO_ERROR, 'set patchParameteri(PATCH_VERTICES, 3)', false, true);
+ // }
+
+ gluDrawUtil.draw(gl, vertexProgramID, vertexArrays, gluDrawUtil.triangles(s_indices));
+
+ postDrawError = gl.getError();
+
+ if (spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_PASS) {
+ /** @type {gluDrawUtil.Surface} */ var surface = new gluDrawUtil.Surface();
+ /** @const @type {number} */ var w = s_positions[3];
+ /** @const @type {number} */ var minY = Math.ceil(((-quadSize / w) * 0.5 + 0.5) * height + 1.0);
+ /** @const @type {number} */ var maxY = Math.floor(((+quadSize / w) * 0.5 + 0.5) * height - 0.5);
+ /** @const @type {number} */ var minX = Math.ceil(((-quadSize / w) * 0.5 + 0.5) * width + 1.0);
+ /** @const @type {number} */ var maxX = Math.floor(((+quadSize / w) * 0.5 + 0.5) * width - 0.5);
+
+ assertMsgOptions(postDrawError === gl.NO_ERROR, 'draw', false, true);
+
+ surface.readSurface(gl, viewportX, viewportY, width, height);
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, 'read pixels', false, true);
+
+ if (!glsShaderLibraryCase.checkPixels(surface, minX, maxX, minY, maxY)) {
+ testFailedOptions((
+ 'INCORRECT RESULT for (value block ' + (blockNdx + 1) +
+ ' of ' + spec.valueBlockList.length + ', sub-case ' +
+ (arrayNdx + 1) + ' of ' + block.arrayLength + '):'
+ ), true);
+
+ /* TODO: Port */
+ /*
+ log << TestLog::Message << "Failing shader input/output values:" << TestLog::EndMessage;
+ dumpValues(block, arrayNdx);
+
+ // Dump image on failure.
+ log << TestLog::Image("Result", "Rendered result image", surface);
+
+ */
+ gl.useProgram(null);
+
+ return false;
+ }
+ } else if (spec.expectResult === glsShaderLibraryCase.expectResult.EXPECT_VALIDATION_FAIL) {
+ /** TODO: GLES 3.1: Implement */
+ testFailedOptions('Unsupported test case', true);
+ }
+ }
+ }
+ gl.useProgram(null);
+
+ assertMsgOptions(gl.getError() === gl.NO_ERROR, '', true, true);
+ setCurrentTestName('');
+
+ return true;
+};
+
+glsShaderLibraryCase.runTestCases = function() {
+/** @type {Object} */ var state = tcuTestCase.runner;
+ if (state.next()) {
+ try {
+ glsShaderLibraryCase.init();
+ glsShaderLibraryCase.execute();
+ } catch (err) {
+ bufferedLogToConsole(err);
+ }
+ tcuTestCase.runner.runCallback(glsShaderLibraryCase.runTestCases);
+ } else
+ tcuTestCase.runner.terminate();
+
+};
+
+glsShaderLibraryCase.genValueBlock = function() {
+ return {
+ /** @type {Array} */ values: [],
+ /** @type {number} */ arrayLength: 0
+ };
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderRenderCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderRenderCase.js
new file mode 100644
index 0000000000..31f59de1f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsShaderRenderCase.js
@@ -0,0 +1,1200 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsShaderRenderCase');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuMatrix');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluTexture');
+goog.require('framework.opengl.gluTextureUtil');
+goog.require('framework.opengl.gluShaderProgram');
+
+goog.scope(function() {
+ var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+
+ var deMath = framework.delibs.debase.deMath;
+ var deString = framework.delibs.debase.deString;
+ var deRandom = framework.delibs.debase.deRandom;
+ var gluTextureUtil = framework.opengl.gluTextureUtil;
+ var gluTexture = framework.opengl.gluTexture;
+ var gluDrawUtil = framework.opengl.gluDrawUtil;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuTexture = framework.common.tcuTexture;
+ var tcuMatrix = framework.common.tcuMatrix;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuSurface = framework.common.tcuSurface;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+
+ /** @typedef {function(glsShaderRenderCase.ShaderEvalContext)} */ glsShaderRenderCase.ShaderEvalFunc;
+
+ /** @const {number} */ glsShaderRenderCase.GRID_SIZE = 64;
+ /** @const {number} */ glsShaderRenderCase.MAX_RENDER_WIDTH = 128;
+ /** @const {number} */ glsShaderRenderCase.MAX_RENDER_HEIGHT = 112;
+ /** @const {Array<number>} */ glsShaderRenderCase.DEFAULT_CLEAR_COLOR = [0.125, 0.25, 0.5, 1.0];
+ /** @const {number} */ glsShaderRenderCase.MAX_USER_ATTRIBS = 4;
+ /** @const {number} */ glsShaderRenderCase.MAX_TEXTURES = 4;
+
+ /**
+ * @param {Array<number>} a
+ * @return {tcuRGBA.RGBA}
+ */
+ glsShaderRenderCase.toRGBA = function(a) {
+ return tcuRGBA.newRGBAComponents(
+ deMath.clamp(Math.round(a[0] * 255.0), 0, 255),
+ deMath.clamp(Math.round(a[1] * 255.0), 0, 255),
+ deMath.clamp(Math.round(a[2] * 255.0), 0, 255),
+ deMath.clamp(Math.round(a[3] * 255.0), 0, 255));
+ };
+
+ /**
+ * Helper function
+ * @param {?(gluTexture.Texture2D|gluTexture.TextureCube|gluTexture.Texture2DArray|gluTexture.Texture3D)} tex
+ * @return {gluTexture.Type}
+ */
+ glsShaderRenderCase.getTextureType = function(tex) {
+ if (tex === null || tex.getType() <= 0)
+ return gluTexture.Type.TYPE_NONE;
+ else
+ return tex.getType();
+ };
+
+ /**
+ * @constructor
+ * @param {number=} indent
+ */
+ glsShaderRenderCase.LineStream = function(indent) {
+ indent = indent === undefined ? 0 : indent;
+ /** @type {number} */ this.m_indent = indent;
+ /** @type {string} */ this.m_stream;
+ /** @type {string} */ this.m_string;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsShaderRenderCase.LineStream.prototype.str = function() {
+ this.m_string = this.m_stream;
+ return this.m_string;
+ };
+
+ /**
+ * @constructor
+ * @param {(gluTexture.Texture2D|gluTexture.TextureCube|gluTexture.Texture2DArray|gluTexture.Texture3D)=} tex
+ * @param {tcuTexture.Sampler=} sampler
+ */
+ glsShaderRenderCase.TextureBinding = function(tex, sampler) {
+ tex = tex === undefined ? null : tex;
+ sampler = sampler === undefined ? null : sampler;
+ /** @type {gluTexture.Type} */ this.m_type = glsShaderRenderCase.getTextureType(tex);
+ /** @type {tcuTexture.Sampler} */ this.m_sampler = sampler;
+ /** @type {(gluTexture.Texture2D|gluTexture.TextureCube|gluTexture.Texture2DArray|gluTexture.Texture3D)} */
+ this.m_binding = tex;
+ };
+
+ /**
+ * @param {tcuTexture.Sampler} sampler
+ */
+ glsShaderRenderCase.TextureBinding.prototype.setSampler = function(sampler) {
+ this.m_sampler = sampler;
+ };
+
+ /**
+ * @param {(gluTexture.Texture2D|gluTexture.TextureCube|gluTexture.Texture2DArray|gluTexture.Texture3D)} tex
+ */
+ glsShaderRenderCase.TextureBinding.prototype.setTexture = function(tex) {
+ this.m_type = glsShaderRenderCase.getTextureType(tex);
+ this.m_binding = tex;
+ };
+
+ /** @return {gluTexture.Type} */
+ glsShaderRenderCase.TextureBinding.prototype.getType = function() {
+ return this.m_type;
+ };
+
+ /** @return {tcuTexture.Sampler} */
+ glsShaderRenderCase.TextureBinding.prototype.getSampler = function() {
+ return this.m_sampler;
+ };
+
+ /** @return {(gluTexture.Texture2D|gluTexture.TextureCube|gluTexture.Texture2DArray|gluTexture.Texture3D)} */
+ glsShaderRenderCase.TextureBinding.prototype.getBinding = function() {
+ return this.m_binding;
+ };
+
+ /**
+ * @constructor
+ * @param {number} gridSize
+ * @param {number} width
+ * @param {number} height
+ * @param {Array<number>} constCoords
+ * @param {Array<tcuMatrix.Matrix>} userAttribTransforms
+ * @param {Array<glsShaderRenderCase.TextureBinding>} textures
+ */
+ glsShaderRenderCase.QuadGrid = function(gridSize, width, height, constCoords, userAttribTransforms, textures) {
+ /** @type {number} */ this.m_gridSize = gridSize;
+ /** @type {number} */ this.m_numVertices = (gridSize + 1) * (gridSize + 1);
+ /** @type {number} */ this.m_numTriangles = (gridSize * gridSize *2);
+ /** @type {Array<number>} */ this.m_constCoords = constCoords;
+ /** @type {Array<tcuMatrix.Matrix>} */ this.m_userAttribTransforms = userAttribTransforms;
+ /** @type {Array<glsShaderRenderCase.TextureBinding>} */ this.m_textures = textures;
+ /** @type {Array<Array<number>>} */ this.m_screenPos = [];
+ /** @type {Array<Array<number>>} */ this.m_positions = [];
+ /** @type {Array<Array<number>>} */ this.m_coords = []; //!< Near-unit coordinates, roughly [-2.0 .. 2.0].
+ /** @type {Array<Array<number>>} */ this.m_unitCoords = []; //!< Positive-only coordinates [0.0 .. 1.5].
+ /** @type {Array<number>} */ this.m_attribOne = [];
+ /** @type {Array<Array<number>>} */ this.m_userAttribs = [];
+ for (var attribNdx = 0; attribNdx < this.getNumUserAttribs(); attribNdx++)
+ this.m_userAttribs[attribNdx] = [];
+ /** @type {Array<number>} */ this.m_indices = [];
+
+ /** @type Array<number>} */ var viewportScale = [width, height, 0, 0];
+ for (var y = 0; y < gridSize + 1; y++)
+ for (var x = 0; x < gridSize + 1; x++) {
+ /** @type {number} */ var sx = x / gridSize;
+ /** @type {number} */ var sy = y / gridSize;
+ /** @type {number} */ var fx = 2.0 * sx - 1.0;
+ /** @type {number} */ var fy = 2.0 * sy - 1.0;
+ /** @type {number} */ var vtxNdx = ((y * (gridSize + 1)) + x);
+
+ this.m_positions[vtxNdx] = [fx, fy, 0.0, 1.0];
+ this.m_attribOne[vtxNdx] = 1.0;
+ this.m_screenPos[vtxNdx] = deMath.multiply([sx, sy, 0.0, 1.0], viewportScale);
+ this.m_coords[vtxNdx] = this.getCoords(sx, sy);
+ this.m_unitCoords[vtxNdx] = this.getUnitCoords(sx, sy);
+
+ for (var attribNdx = 0; attribNdx < this.getNumUserAttribs(); attribNdx++)
+ this.m_userAttribs[attribNdx][vtxNdx] = this.getUserAttrib(attribNdx, sx, sy);
+ }
+
+ // Compute indices.
+ for (var y = 0; y < gridSize; y++)
+ for (var x = 0; x < gridSize; x++) {
+ /** @type {number} */ var stride = gridSize + 1;
+ /** @type {number} */ var v00 = (y * stride) + x;
+ /** @type {number} */ var v01 = (y * stride) + x + 1;
+ /** @type {number} */ var v10 = ((y + 1) * stride) + x;
+ /** @type {number} */ var v11 = ((y + 1) * stride) + x + 1;
+
+ /** @type {number} */ var baseNdx = ((y * gridSize) + x) * 6;
+ this.m_indices[baseNdx + 0] = v10;
+ this.m_indices[baseNdx + 1] = v00;
+ this.m_indices[baseNdx + 2] = v01;
+
+ this.m_indices[baseNdx + 3] = v10;
+ this.m_indices[baseNdx + 4] = v01;
+ this.m_indices[baseNdx + 5] = v11;
+ }
+ };
+
+ /** @return {number} */
+ glsShaderRenderCase.QuadGrid.prototype.getGridSize = function() {
+ return this.m_gridSize;
+ };
+
+ /** @return {number} */
+ glsShaderRenderCase.QuadGrid.prototype.getNumVertices = function() {
+ return this.m_numVertices;
+ };
+
+ /** @return {number} */
+ glsShaderRenderCase.QuadGrid.prototype.getNumTriangles = function() {
+ return this.m_numTriangles;
+ };
+
+ /** @return {Array<number>} */
+ glsShaderRenderCase.QuadGrid.prototype.getConstCoords = function() {
+ return this.m_constCoords;
+ };
+
+ /** @return {Array<tcuMatrix.Matrix>} */
+ glsShaderRenderCase.QuadGrid.prototype.getUserAttribTransforms = function() {
+ return this.m_userAttribTransforms;
+ };
+
+ /** @return {Array<glsShaderRenderCase.TextureBinding>} */
+ glsShaderRenderCase.QuadGrid.prototype.getTextures = function() {
+ return this.m_textures;
+ };
+
+ /** @return {Array<Array<number>>} */
+ glsShaderRenderCase.QuadGrid.prototype.getPositions = function() {
+ return this.m_positions;
+ };
+
+ /** @return {Array<number>} */
+ glsShaderRenderCase.QuadGrid.prototype.getAttribOne = function() {
+ return this.m_attribOne;
+ };
+
+ /** @return {Array<Array<number>>} */
+ glsShaderRenderCase.QuadGrid.prototype.getCoordsArray = function() {
+ return this.m_coords;
+ };
+
+ /** @return {Array<Array<number>>} */
+ glsShaderRenderCase.QuadGrid.prototype.getUnitCoordsArray = function() {
+ return this.m_unitCoords;
+ };
+
+ /**
+ * @param {number} attribNdx
+ * @return {Array<number>}
+ */
+ glsShaderRenderCase.QuadGrid.prototype.getUserAttribByIndex = function(attribNdx) {
+ return this.m_userAttribs[attribNdx];
+ };
+
+ /** @return {Array<number>} */
+ glsShaderRenderCase.QuadGrid.prototype.getIndices = function() {
+ return this.m_indices;
+ };
+
+ /**
+ * @param {number} sx
+ * @param {number} sy
+ * @return {Array<number>}
+ */
+ glsShaderRenderCase.QuadGrid.prototype.getCoords = function(sx, sy) {
+ /** @type {number} */ var fx = 2.0 * sx - 1.0;
+ /** @type {number} */ var fy = 2.0 * sy - 1.0;
+ return [fx, fy, -fx + 0.33 * fy, -0.275 * fx - fy];
+ };
+
+ /**
+ * @param {number} sx
+ * @param {number} sy
+ * @return {Array<number>}
+ */
+ glsShaderRenderCase.QuadGrid.prototype.getUnitCoords = function(sx, sy) {
+ return [sx, sy, 0.33 * sx + 0.5 * sy, 0.5 * sx + 0.25 * sy];
+ };
+
+ /**
+ * @return {number}
+ */
+ glsShaderRenderCase.QuadGrid.prototype.getNumUserAttribs = function() {
+ return this.m_userAttribTransforms.length;
+ };
+
+ /**
+ * @param {number} attribNdx
+ * @param {number} sx
+ * @param {number} sy
+ * @return {Array<number>}
+ */
+ glsShaderRenderCase.QuadGrid.prototype.getUserAttrib = function(attribNdx, sx, sy) {
+ // homogeneous normalized screen-space coordinates
+ return tcuMatrix.multiplyMatVec(this.m_userAttribTransforms[attribNdx], [sx, sy, 0.0, 1.0]);
+ };
+
+ /**
+ * @constructor
+ * @struct
+ */
+ glsShaderRenderCase.ShaderSampler = function() {
+ /** @type {tcuTexture.Sampler} */ this.sampler;
+ /** @type {tcuTexture.Texture2D} */ this.tex2D = null;
+ /** @type {tcuTexture.TextureCube} */ this.texCube = null;
+ /** @type {tcuTexture.Texture2DArray} */ this.tex2DArray = null;
+ /** @type {tcuTexture.Texture3D} */ this.tex3D = null;
+ };
+
+ /**
+ * @constructor
+ * @param {glsShaderRenderCase.QuadGrid} quadGrid_
+ */
+ glsShaderRenderCase.ShaderEvalContext = function(quadGrid_) {
+ /** @type {Array<number>} */ this.coords = [0, 0, 0, 0]
+ /** @type {Array<number>} */ this.unitCoords = [0, 0, 0, 0]
+ /** @type {Array<number>} */ this.constCoords = quadGrid_.getConstCoords();
+ /** @type {Array<Array<number>>} */ this.in_ = [];
+ /** @type {Array<glsShaderRenderCase.ShaderSampler>} */ this.textures = [];
+ /** @type {Array<number>} */ this.color = [0, 0, 0, 0.0];
+ /** @type {boolean} */ this.isDiscarded = false;
+ /** @type {glsShaderRenderCase.QuadGrid} */ this.quadGrid = quadGrid_;
+
+ /** @type {Array<glsShaderRenderCase.TextureBinding>} */ var bindings = this.quadGrid.getTextures();
+ assertMsgOptions(bindings.length <= glsShaderRenderCase.MAX_TEXTURES, 'Too many bindings.', false, true);
+
+ // Fill in texture array.
+ for (var ndx = 0; ndx < bindings.length; ndx++) {
+ /** @type {glsShaderRenderCase.TextureBinding} */ var binding = bindings[ndx];
+
+ this.textures[ndx] = new glsShaderRenderCase.ShaderSampler();
+
+ if (binding.getType() == gluTexture.Type.TYPE_NONE)
+ continue;
+
+ this.textures[ndx].sampler = binding.getSampler();
+
+ switch (binding.getType()) {
+ case gluTexture.Type.TYPE_2D:
+ this.textures[ndx].tex2D = binding.getBinding().getRefTexture();
+ break;
+ case gluTexture.Type.TYPE_CUBE_MAP:
+ this.textures[ndx].texCube = binding.getBinding().getRefTexture();
+ break;
+ case gluTexture.Type.TYPE_2D_ARRAY:
+ this.textures[ndx].tex2DArray = binding.getBinding().getRefTexture();
+ break;
+ case gluTexture.Type.TYPE_3D:
+ this.textures[ndx].tex3D = binding.getBinding().getRefTexture();
+ break;
+ default:
+ throw new Error("Binding type not supported");
+ }
+ }
+ };
+
+ /**
+ * @param {number} sx
+ * @param {number} sy
+ */
+ glsShaderRenderCase.ShaderEvalContext.prototype.reset = function(sx, sy) {
+ // Clear old values
+ this.color = [0.0, 0.0, 0.0, 1.0];
+ this.isDiscarded = false;
+
+ // Compute coords
+ this.coords = this.quadGrid.getCoords(sx, sy);
+ this.unitCoords = this.quadGrid.getUnitCoords(sx, sy);
+
+ // Compute user attributes.
+ /** @type {number} */ var numAttribs = this.quadGrid.getNumUserAttribs();
+ assertMsgOptions(numAttribs <= glsShaderRenderCase.MAX_USER_ATTRIBS, 'numAttribs out of range', false, true);
+ for (var attribNdx = 0; attribNdx < numAttribs; attribNdx++)
+ this.in_[attribNdx] = this.quadGrid.getUserAttrib(attribNdx, sx, sy);
+ };
+
+ glsShaderRenderCase.ShaderEvalContext.prototype.discard = function() {
+ this.isDiscarded = true;
+ };
+
+ /**
+ * @param {number} unitNdx
+ * @param {Array<number>} coords
+ */
+ glsShaderRenderCase.ShaderEvalContext.prototype.texture2D = function(unitNdx, coords) {
+ if (this.textures.length > 0 && this.textures[unitNdx].tex2D)
+ return this.textures[unitNdx].tex2D.getView().sample(this.textures[unitNdx].sampler, coords, 0.0);
+ else
+ return [0.0, 0.0, 0.0, 1.0];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ glsShaderRenderCase.evalCoordsPassthroughX = function(c) {
+ c.color[0] = c.coords[0];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ glsShaderRenderCase.evalCoordsPassthroughXY = function(c) {
+ var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
+ c.color[0] = swizzle01[0];
+ c.color[1] = swizzle01[1];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ glsShaderRenderCase.evalCoordsPassthroughXYZ = function(c) {
+ var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
+ c.color[0] = swizzle012[0];
+ c.color[1] = swizzle012[1];
+ c.color[2] = swizzle012[2];
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ glsShaderRenderCase.evalCoordsPassthrough = function(c) {
+ c.color = c.coords;
+ };
+
+ /** @param {glsShaderRenderCase.ShaderEvalContext} c */
+ glsShaderRenderCase.evalCoordsSwizzleWZYX = function(c) {
+ c.color = deMath.swizzle(c.coords, [3, 2, 1, 0]);
+ };
+
+ /**
+ * @constructor
+ * @param {?glsShaderRenderCase.ShaderEvalFunc=} evalFunc
+ */
+ glsShaderRenderCase.ShaderEvaluator = function(evalFunc) {
+ /** @type {?glsShaderRenderCase.ShaderEvalFunc} */ this.m_evalFunc = evalFunc || null;
+ };
+
+ /**
+ * @param {glsShaderRenderCase.ShaderEvalContext} ctx
+ */
+ glsShaderRenderCase.ShaderEvaluator.prototype.evaluate = function(ctx) {
+ assertMsgOptions(this.m_evalFunc !== null, 'No evaluation function specified.', false, true);
+ this.m_evalFunc(ctx);
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {glsShaderRenderCase.ShaderEvalFunc=} evalFunc
+ */
+ glsShaderRenderCase.ShaderRenderCase = function(name, description, isVertexCase, evalFunc) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ // evalFunc = evalFunc || null;
+ /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
+ /** @type {?glsShaderRenderCase.ShaderEvalFunc} */ this.m_defaultEvaluator = evalFunc || null;
+ /** @type {glsShaderRenderCase.ShaderEvaluator} */ this.m_evaluator = new glsShaderRenderCase.ShaderEvaluator(this.m_defaultEvaluator);
+ /** @type {string} */ this.m_vertShaderSource = '';
+ /** @type {string} */ this.m_fragShaderSource = '';
+ /** @type {Array<number>} */ this.m_clearColor = glsShaderRenderCase.DEFAULT_CLEAR_COLOR;
+ /** @type {Array<tcuMatrix.Matrix>} */ this.m_userAttribTransforms = [];
+ /** @type {Array<glsShaderRenderCase.TextureBinding>} */ this.m_textures = [];
+ /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
+ };
+
+ /**
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {glsShaderRenderCase.ShaderEvaluator} evaluator
+ * @return {glsShaderRenderCase.ShaderRenderCase}
+ */
+ glsShaderRenderCase.ShaderRenderCase.newWithEvaluator = function(name, description, isVertexCase, evaluator) {
+ var renderCase = new glsShaderRenderCase.ShaderRenderCase(name, description, isVertexCase);
+ renderCase.m_evaluator = evaluator;
+ return renderCase;
+ };
+
+ glsShaderRenderCase.ShaderRenderCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsShaderRenderCase.ShaderRenderCase.prototype.constructor = glsShaderRenderCase.ShaderRenderCase;
+
+ glsShaderRenderCase.ShaderRenderCase.prototype.deinit = function() {
+ this.m_program = null;
+ };
+
+ glsShaderRenderCase.ShaderRenderCase.prototype.init = function() {
+ this.postinit();
+ };
+
+ glsShaderRenderCase.ShaderRenderCase.prototype.postinit = function() {
+ if (this.m_vertShaderSource.length === 0 || this.m_fragShaderSource.length === 0) {
+ assertMsgOptions(this.m_vertShaderSource.length === 0 && this.m_fragShaderSource.length === 0, 'No shader source.', false, true);
+ this.setupShaderData();
+ }
+
+ assertMsgOptions(!this.m_program, 'Program defined.', false, true);
+ this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(this.m_vertShaderSource, this.m_fragShaderSource));
+
+ try {
+ bufferedLogToConsole(this.m_program.program.info.infoLog); // Always log shader program.
+
+ if (!this.m_program.isOk())
+ throw new Error("Shader compile error.");
+ }
+ catch (exception) {
+ // Clean up.
+ this.deinit();
+ throw exception;
+ }
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.postiterate = function() {
+ assertMsgOptions(this.m_program !== null, 'Program not specified.', false, true);
+ /** @type {?WebGLProgram} */ var programID = this.m_program.getProgram();
+ gl.useProgram(programID);
+
+ // Create quad grid.
+ /** @type {Array<number>} */ var viewportSize = this.getViewportSize();
+ /** @type {number} */ var width = viewportSize[0];
+ /** @type {number} */ var height = viewportSize[1];
+
+ // \todo [petri] Better handling of constCoords (render in multiple chunks, vary coords).
+ /** @type {glsShaderRenderCase.QuadGrid} */
+ var quadGrid = new glsShaderRenderCase.QuadGrid(
+ this.m_isVertexCase ? glsShaderRenderCase.GRID_SIZE : 4, width, height,
+ [0.125, 0.25, 0.5, 1.0], this.m_userAttribTransforms, this.m_textures);
+
+ // Render result.
+ /** @type {tcuSurface.Surface} */ var resImage = new tcuSurface.Surface(width, height);
+ this.render(resImage, programID, quadGrid);
+
+ // Compute reference.
+ /** @type {tcuSurface.Surface} */ var refImage = new tcuSurface.Surface(width, height);
+ if (this.m_isVertexCase)
+ this.computeVertexReference(refImage, quadGrid);
+ else
+ this.computeFragmentReference(refImage, quadGrid);
+
+ // Compare.
+ /** @type {boolean} */ var testOk = this.compareImages(resImage, refImage, 0.05);
+
+ // De-initialize.
+ gl.useProgram(null);
+
+ if (!testOk)
+ testFailedOptions("Fail", false);
+ else
+ testPassedOptions("Pass", true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.iterate = function() {
+ return this.postiterate();
+ };
+
+ glsShaderRenderCase.ShaderRenderCase.prototype.setupShaderData = function() {};
+
+ /**
+ * @param {?WebGLProgram} programId
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.setup = function(programId) {};
+
+ /**
+ * @param {?WebGLProgram} programId
+ * @param {Array<number>} constCoords
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.setupUniforms = function(programId, constCoords) {};
+
+ /**
+ * @return {Array<number>}
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.getViewportSize = function() {
+ return [Math.min(gl.canvas.width, glsShaderRenderCase.MAX_RENDER_WIDTH),
+ Math.min(gl.canvas.height, glsShaderRenderCase.MAX_RENDER_HEIGHT)];
+ };
+
+ /**
+ * @param {?WebGLProgram} programId
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.setupDefaultInputs = function(programId) {
+ // SETUP UNIFORMS.
+ glsShaderRenderCase.setupDefaultUniforms(programId);
+
+ // SETUP TEXTURES.
+ for (var ndx = 0; ndx < this.m_textures.length; ndx++) {
+ /** @type {glsShaderRenderCase.TextureBinding} */ var tex = this.m_textures[ndx];
+ /** @type {tcuTexture.Sampler} */ var sampler = tex.getSampler();
+ /** @type {number} */ var texTarget = gl.NONE;
+ /** @type {number} */ var texObj = 0;
+
+ if (tex.getType() === gluTexture.Type.TYPE_NONE)
+ continue;
+
+ switch (tex.getType()) {
+ case gluTexture.Type.TYPE_2D:
+ texTarget = gl.TEXTURE_2D;
+ texObj = tex.getBinding().getGLTexture();
+ break;
+ case gluTexture.Type.TYPE_CUBE_MAP:
+ texTarget = gl.TEXTURE_CUBE_MAP;
+ texObj = tex.getBinding().getGLTexture();
+ break;
+ case gluTexture.Type.TYPE_2D_ARRAY:
+ texTarget = gl.TEXTURE_2D_ARRAY;
+ texObj = tex.getBinding().getGLTexture();
+ break;
+ case gluTexture.Type.TYPE_3D:
+ texTarget = gl.TEXTURE_3D;
+ texObj = tex.getBinding().getGLTexture();
+ break;
+ default:
+ throw new Error("Type not supported");
+ }
+
+ gl.activeTexture(gl.TEXTURE0+ ndx);
+ gl.bindTexture(texTarget, texObj);
+ gl.texParameteri(texTarget, gl.TEXTURE_WRAP_S, gluTextureUtil.getGLWrapMode(sampler.wrapS));
+ gl.texParameteri(texTarget, gl.TEXTURE_WRAP_T, gluTextureUtil.getGLWrapMode(sampler.wrapT));
+ gl.texParameteri(texTarget, gl.TEXTURE_MIN_FILTER, gluTextureUtil.getGLFilterMode(sampler.minFilter));
+ gl.texParameteri(texTarget, gl.TEXTURE_MAG_FILTER, gluTextureUtil.getGLFilterMode(sampler.magFilter));
+
+ if (texTarget === gl.TEXTURE_3D)
+ gl.texParameteri(texTarget, gl.TEXTURE_WRAP_R, gluTextureUtil.getGLWrapMode(sampler.wrapR));
+
+ if (sampler.compare != tcuTexture.CompareMode.COMPAREMODE_NONE)
+ {
+ gl.texParameteri(texTarget, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.texParameteri(texTarget, gl.TEXTURE_COMPARE_FUNC, gluTextureUtil.getGLCompareFunc(sampler.compare));
+ }
+ }
+ };
+
+ /**
+ * @param {tcuSurface.Surface} result
+ * @param {?WebGLProgram} programId
+ * @param {glsShaderRenderCase.QuadGrid} quadGrid
+ **/
+ glsShaderRenderCase.ShaderRenderCase.prototype.render = function(result, programId, quadGrid) {
+ // Buffer info.
+ /** @type {number} */ var width = result.getWidth();
+ /** @type {number} */ var height = result.getHeight();
+
+ /** @type {number} */ var xOffsetMax = gl.drawingBufferWidth - width;
+ /** @type {number} */ var yOffsetMax = gl.drawingBufferHeight - height;
+
+ /** @type {number} */ var hash = deString.deStringHash(this.m_vertShaderSource) + deString.deStringHash(this.m_fragShaderSource);
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(hash);
+
+ /** @type {number} */ var xOffset = rnd.getInt(0, xOffsetMax);
+ /** @type {number} */ var yOffset = rnd.getInt(0, yOffsetMax);
+
+ gl.viewport(xOffset, yOffset, width, height);
+
+ // Setup program.
+ this.setupUniforms(programId, quadGrid.getConstCoords());
+ this.setupDefaultInputs(programId);
+
+ // Clear.
+ gl.clearColor(this.m_clearColor[0], this.m_clearColor[1], this.m_clearColor[2], this.m_clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw.
+ /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
+ /** @type {number} */ var numElements = quadGrid.getNumTriangles()*3;
+
+ glsShaderRenderCase.getDefaultVertexArrays(quadGrid, programId, vertexArrays);
+
+ gluDrawUtil.draw(gl, programId, vertexArrays, gluDrawUtil.triangles(quadGrid.getIndices()));
+
+ // Read back results.
+ result.readViewport(gl, [xOffset, yOffset, width, height]);
+
+ };
+
+ /**
+ * @param {tcuSurface.Surface} result
+ * @param {glsShaderRenderCase.QuadGrid} quadGrid
+ **/
+ glsShaderRenderCase.ShaderRenderCase.prototype.computeVertexReference = function(result, quadGrid) {
+ // Buffer info.
+ /** @type {number} */ var width = result.getWidth();
+ /** @type {number} */ var height = result.getHeight();
+ /** @type {number} */ var gridSize = quadGrid.getGridSize();
+ /** @type {number} */ var stride = gridSize + 1;
+ /** @type {boolean} */ var hasAlpha = gl.getContextAttributes().alpha;
+ /** @type {glsShaderRenderCase.ShaderEvalContext} */
+ var evalCtx = new glsShaderRenderCase.ShaderEvalContext(quadGrid);
+ /** @type {Array<number>} */ var color = [];
+ // Evaluate color for each vertex.
+ /** @type {Array<Array<number>>} */ var colors = [];
+ for (var y = 0; y < gridSize + 1; y++)
+ for (var x = 0; x < gridSize + 1; x++) {
+ /** @type {number} */ var sx = x / gridSize;
+ /** @type {number} */ var sy = y / gridSize;
+ /** @type {number} */ var vtxNdx = ((y * (gridSize+ 1 )) + x);
+
+ evalCtx.reset(sx, sy);
+ this.m_evaluator.evaluate(evalCtx);
+ assertMsgOptions(!evalCtx.isDiscarded, 'Discard is not available in vertex shader.', false, true);
+ color = evalCtx.color;
+
+ if (!hasAlpha)
+ color[3] = 1.0;
+
+ colors[vtxNdx] = color;
+ }
+ // Render quads.
+ for (var y = 0; y < gridSize; y++)
+ for (var x = 0; x < gridSize; x++) {
+ /** @type {number} */ var x0 = x / gridSize;
+ /** @type {number} */ var x1 = (x + 1) / gridSize;
+ /** @type {number} */ var y0 = y / gridSize;
+ /** @type {number} */ var y1 = (y + 1) / gridSize;
+
+ /** @type {number} */ var sx0 = x0 * width;
+ /** @type {number} */ var sx1 = x1 * width;
+ /** @type {number} */ var sy0 = y0 * height;
+ /** @type {number} */ var sy1 = y1 * height;
+ /** @type {number} */ var oosx = 1.0 / (sx1 - sx0);
+ /** @type {number} */ var oosy = 1.0 / (sy1 - sy0);
+
+ /** @type {number} */ var ix0 = Math.ceil(sx0 - 0.5);
+ /** @type {number} */ var ix1 = Math.ceil(sx1 - 0.5);
+ /** @type {number} */ var iy0 = Math.ceil(sy0 - 0.5);
+ /** @type {number} */ var iy1 = Math.ceil(sy1 - 0.5);
+
+ /** @type {number} */ var v00 = (y * stride) + x;
+ /** @type {number} */ var v01 = (y * stride) + x + 1;
+ /** @type {number} */ var v10 = ((y + 1) * stride) + x;
+ /** @type {number} */ var v11 = ((y + 1) * stride) + x + 1;
+ /** @type {Array<number>} */ var c00 = colors[v00];
+ /** @type {Array<number>} */ var c01 = colors[v01];
+ /** @type {Array<number>} */ var c10 = colors[v10];
+ /** @type {Array<number>} */ var c11 = colors[v11];
+
+ for (var iy = iy0; iy < iy1; iy++)
+ for (var ix = ix0; ix < ix1; ix++) {
+ assertMsgOptions(deMath.deInBounds32(ix, 0, width), 'Out of bounds.', false, true);
+ assertMsgOptions(deMath.deInBounds32(iy, 0, height), 'Out of bounds.', false, true);
+
+ /** @type {number} */ var sfx = ix + 0.5;
+ /** @type {number} */ var sfy = iy + 0.5;
+ /** @type {number} */ var fx1 = deMath.clamp((sfx - sx0) * oosx, 0.0, 1.0);
+ /** @type {number} */ var fy1 = deMath.clamp((sfy - sy0) * oosy, 0.0, 1.0);
+
+ // Triangle quad interpolation.
+ /** @type {boolean} */ var tri = fx1 + fy1 <= 1.0;
+ /** @type {number} */ var tx = tri ? fx1 : (1.0 - fx1);
+ /** @type {number} */ var ty = tri ? fy1 : (1.0 - fy1);
+ /** @type {Array<number>} */ var t0 = tri ? c00 : c11;
+ /** @type {Array<number>} */ var t1 = tri ? c01 : c10;
+ /** @type {Array<number>} */ var t2 = tri ? c10 : c01;
+ color = deMath.add(t0, deMath.add(deMath.scale(deMath.subtract(t1, t0), tx), deMath.scale(deMath.subtract(t2, t0), ty)));
+
+ result.setPixel(ix, iy, glsShaderRenderCase.toRGBA(color).toIVec());
+ }
+ }
+ };
+
+ /**
+ * @param {tcuSurface.Surface} result
+ * @param {glsShaderRenderCase.QuadGrid} quadGrid
+ **/
+ glsShaderRenderCase.ShaderRenderCase.prototype.computeFragmentReference = function(result, quadGrid) {
+ // Buffer info.
+ /** @type {number} */ var width = result.getWidth();
+ /** @type {number} */ var height = result.getHeight();
+ /** @type {boolean} */ var hasAlpha = gl.getContextAttributes().alpha;
+ /** @type {glsShaderRenderCase.ShaderEvalContext} */ var evalCtx = new glsShaderRenderCase.ShaderEvalContext(quadGrid);
+
+ // Render.
+ for (var y = 0; y < height; y++)
+ for (var x = 0; x < width; x++) {
+ /** @type {number} */ var sx = (x + 0.5) / width;
+ /** @type {number} */ var sy = (y + 0.5) / height;
+
+ evalCtx.reset(sx, sy);
+ this.m_evaluator.evaluate(evalCtx);
+ // Select either clear color or computed color based on discarded bit.
+ /** @type {Array<number>} */ var color = evalCtx.isDiscarded ? this.m_clearColor : evalCtx.color;
+
+ if (!hasAlpha)
+ color[3] = 1.0;
+
+ result.setPixel(x, y, glsShaderRenderCase.toRGBA(color).toIVec());
+ }
+ };
+
+ /**
+ * @param {tcuSurface.Surface} resImage
+ * @param {tcuSurface.Surface} refImage
+ * @param {number} errorThreshold
+ * @return {boolean}
+ */
+ glsShaderRenderCase.ShaderRenderCase.prototype.compareImages = function(resImage, refImage, errorThreshold) {
+ return tcuImageCompare.fuzzyCompare("ComparisonResult", "Image comparison result", refImage.getAccess(), resImage.getAccess(), errorThreshold);
+ };
+
+ /**
+ * @param {number} number
+ * @return {string} */
+ glsShaderRenderCase.getIntUniformName = function(number) {
+ switch (number) {
+ case 0: return "ui_zero";
+ case 1: return "ui_one";
+ case 2: return "ui_two";
+ case 3: return "ui_three";
+ case 4: return "ui_four";
+ case 5: return "ui_five";
+ case 6: return "ui_six";
+ case 7: return "ui_seven";
+ case 8: return "ui_eight";
+ case 101: return "ui_oneHundredOne";
+ default:
+ throw new Error("Uniform not supported.");
+ }
+ };
+
+ /**
+ * @param {number} number
+ * @return {string} */
+ glsShaderRenderCase.getFloatUniformName = function(number) {
+ switch (number) {
+ case 0: return "uf_zero";
+ case 1: return "uf_one";
+ case 2: return "uf_two";
+ case 3: return "uf_three";
+ case 4: return "uf_four";
+ case 5: return "uf_five";
+ case 6: return "uf_six";
+ case 7: return "uf_seven";
+ case 8: return "uf_eight";
+ default:
+ throw new Error("Uniform not supported.");
+ }
+ };
+
+ /**
+ * @param {number} number
+ * @return {string} */
+ glsShaderRenderCase.getFloatFractionUniformName = function(number) {
+ switch (number) {
+ case 1: return "uf_one";
+ case 2: return "uf_half";
+ case 3: return "uf_third";
+ case 4: return "uf_fourth";
+ case 5: return "uf_fifth";
+ case 6: return "uf_sixth";
+ case 7: return "uf_seventh";
+ case 8: return "uf_eighth";
+ default:
+ throw new Error("Uniform not supported.");
+ }
+ };
+
+ /**
+ * @param {?WebGLProgram} programID
+ */
+ glsShaderRenderCase.setupDefaultUniforms = function(programID) {
+ /** @type {?WebGLUniformLocation} */ var uniLoc;
+ // Bool.
+ /**
+ * @constructor
+ * @struct
+ */
+ var BoolUniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {boolean} */ this.value = value;
+ };
+
+ /** @type {Array<BoolUniform>} */ var s_boolUniforms = [
+ new BoolUniform("ub_true", true),
+ new BoolUniform("ub_false", false)
+ ];
+
+ for (var i = 0; i < s_boolUniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_boolUniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform1i(uniLoc, s_boolUniforms[i].value ? 1 : 0);
+ }
+
+ // BVec4.
+ /**
+ * @constructor
+ * @struct
+ */
+ var BVec4Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<boolean>} */ this.value = value;
+ };
+
+ /** @type {Array<BVec4Uniform>} */ var s_bvec4Uniforms = [
+ new BVec4Uniform("ub4_true", [true, true, true, true]),
+ new BVec4Uniform("ub4_false", [false, false, false, false])
+ ];
+
+ for (var i = 0; i < s_bvec4Uniforms.length; i++) {
+ /** @type {BVec4Uniform} */ var uni = s_bvec4Uniforms[i];
+ /** @type {Array<number>} */ var arr = [];
+ arr[0] = uni.value[0] ? 1 : 0;
+ arr[1] = uni.value[1] ? 1 : 0;
+ arr[2] = uni.value[2] ? 1 : 0;
+ arr[3] = uni.value[3] ? 1 : 0;
+ uniLoc = gl.getUniformLocation(programID, uni.name);
+ if (uniLoc != null)
+ gl.uniform4iv(uniLoc, new Int32Array(arr));
+ }
+
+ // Int.
+ /**
+ * @constructor
+ * @struct
+ */
+ var IntUniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.value = value;
+ };
+
+ /** @type {Array<IntUniform>} */ var s_intUniforms = [
+ new IntUniform("ui_minusOne", -1),
+ new IntUniform("ui_zero", 0),
+ new IntUniform("ui_one", 1),
+ new IntUniform("ui_two", 2),
+ new IntUniform("ui_three", 3),
+ new IntUniform("ui_four", 4),
+ new IntUniform("ui_five", 5),
+ new IntUniform("ui_six", 6),
+ new IntUniform("ui_seven", 7),
+ new IntUniform("ui_eight", 8),
+ new IntUniform("ui_oneHundredOne", 101)
+ ];
+
+ for (var i = 0; i < s_intUniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_intUniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform1i(uniLoc, s_intUniforms[i].value);
+ }
+
+ // IVec2.
+ /**
+ * @constructor
+ * @struct
+ */
+ var IVec2Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<number>} */ this.value = value;
+ };
+
+ /** @type {Array<IVec2Uniform>} */ var s_ivec2Uniforms = [
+ new IVec2Uniform("ui2_minusOne", [-1, -1]),
+ new IVec2Uniform("ui2_zero", [0, 0]),
+ new IVec2Uniform("ui2_one", [1, 1]),
+ new IVec2Uniform("ui2_two", [2, 2]),
+ new IVec2Uniform("ui2_four", [4, 4]),
+ new IVec2Uniform("ui2_five", [5, 5])
+ ];
+
+ for (var i = 0; i < s_ivec2Uniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_ivec2Uniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform2iv(uniLoc, new Int32Array(s_ivec2Uniforms[i].value));
+ }
+
+ // IVec3.
+ /**
+ * @constructor
+ * @struct
+ */
+ var IVec3Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<number>} */ this.value = value;
+ };
+
+ /** @type {Array<IVec3Uniform>} */ var s_ivec3Uniforms = [
+ new IVec3Uniform("ui3_minusOne", [-1, -1, -1]),
+ new IVec3Uniform("ui3_zero", [0, 0, 0]),
+ new IVec3Uniform("ui3_one", [1, 1, 1]),
+ new IVec3Uniform("ui3_two", [2, 2, 2]),
+ new IVec3Uniform("ui3_four", [4, 4, 4]),
+ new IVec3Uniform("ui3_five", [5, 5, 5])
+ ];
+
+ for (var i = 0; i < s_ivec3Uniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_ivec3Uniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform3iv(uniLoc, new Int32Array(s_ivec3Uniforms[i].value));
+ }
+
+ // IVec4.
+ /**
+ * @constructor
+ * @struct
+ */
+ var IVec4Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<number>} */ this.value = value;
+ };
+ /** @type {Array<IVec4Uniform>} */ var s_ivec4Uniforms = [
+ new IVec4Uniform("ui4_minusOne", [-1, -1, -1, -1]),
+ new IVec4Uniform("ui4_zero", [0, 0, 0, 0]),
+ new IVec4Uniform("ui4_one", [1, 1, 1, 1]),
+ new IVec4Uniform("ui4_two", [2, 2, 2, 2]),
+ new IVec4Uniform("ui4_four", [4, 4, 4, 4]),
+ new IVec4Uniform("ui4_five", [5, 5, 5, 5])
+ ];
+
+ for (var i = 0; i < s_ivec4Uniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_ivec4Uniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform4iv(uniLoc, new Int32Array(s_ivec4Uniforms[i].value));
+ }
+
+ // Float.
+ /**
+ * @constructor
+ * @struct
+ */
+ var FloatUniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {number} */ this.value = value;
+ };
+ /** @type {Array<FloatUniform>} */ var s_floatUniforms = [
+ new FloatUniform("uf_zero", 0.0),
+ new FloatUniform("uf_one", 1.0),
+ new FloatUniform("uf_two", 2.0),
+ new FloatUniform("uf_three", 3.0),
+ new FloatUniform("uf_four", 4.0),
+ new FloatUniform("uf_five", 5.0),
+ new FloatUniform("uf_six", 6.0),
+ new FloatUniform("uf_seven", 7.0),
+ new FloatUniform("uf_eight", 8.0),
+ new FloatUniform("uf_half", 1.0 / 2.0),
+ new FloatUniform("uf_third", 1.0 / 3.0),
+ new FloatUniform("uf_fourth", 1.0 / 4.0),
+ new FloatUniform("uf_fifth", 1.0 / 5.0),
+ new FloatUniform("uf_sixth", 1.0 / 6.0),
+ new FloatUniform("uf_seventh", 1.0 / 7.0),
+ new FloatUniform("uf_eighth", 1.0 / 8.0)
+ ];
+
+ for (var i = 0; i < s_floatUniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_floatUniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform1f(uniLoc, s_floatUniforms[i].value);
+ }
+
+ // Vec2.
+ /**
+ * @constructor
+ * @struct
+ */
+ var Vec2Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<number>} */ this.value = value;
+ };
+ /** @type {Array<Vec2Uniform>} */ var s_vec2Uniforms = [
+ new Vec2Uniform("uv2_minusOne", [-1.0, -1.0]),
+ new Vec2Uniform("uv2_zero", [0.0, 0.0]),
+ new Vec2Uniform("uv2_half", [0.5, 0.5]),
+ new Vec2Uniform("uv2_one", [1.0, 1.0]),
+ new Vec2Uniform("uv2_two", [2.0, 2.0])
+ ];
+
+ for (var i = 0; i < s_vec2Uniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_vec2Uniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform2fv(uniLoc, new Float32Array(s_vec2Uniforms[i].value));
+ }
+
+ // Vec3.
+ /**
+ * @constructor
+ * @struct
+ */
+ var Vec3Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<number>} */ this.value = value;
+ };
+ /** @type {Array<Vec3Uniform>} */ var s_vec3Uniforms = [
+ new Vec3Uniform("uv3_minusOne", [-1.0, -1.0, -1.0]),
+ new Vec3Uniform("uv3_zero", [0.0, 0.0, 0.0]),
+ new Vec3Uniform("uv3_half", [0.5, 0.5, 0.5]),
+ new Vec3Uniform("uv3_one", [1.0, 1.0, 1.0]),
+ new Vec3Uniform("uv3_two", [2.0, 2.0, 2.0])
+ ];
+
+ for (var i = 0; i < s_vec3Uniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_vec3Uniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform3fv(uniLoc, new Float32Array(s_vec3Uniforms[i].value));
+ }
+
+ // Vec4.
+ /**
+ * @constructor
+ * @struct
+ */
+ var Vec4Uniform = function(name, value) {
+ /** @type {string} */ this.name = name;
+ /** @type {Array<number>} */ this.value = value;
+ };
+ /** @type {Array<Vec4Uniform>} */ var s_vec4Uniforms = [
+ new Vec4Uniform("uv4_minusOne", [-1.0, -1.0, -1.0, -1.0]),
+ new Vec4Uniform("uv4_zero", [0.0, 0.0, 0.0, 0.0]),
+ new Vec4Uniform("uv4_half", [0.5, 0.5, 0.5, 0.5]),
+ new Vec4Uniform("uv4_one", [1.0, 1.0, 1.0, 1.0]),
+ new Vec4Uniform("uv4_two", [2.0, 2.0, 2.0, 2.0]),
+ new Vec4Uniform("uv4_black", [0.0, 0.0, 0.0, 1.0]),
+ new Vec4Uniform("uv4_gray", [0.5, 0.5, 0.5, 1.0]),
+ new Vec4Uniform("uv4_white", [1.0, 1.0, 1.0, 1.0])
+ ];
+
+ for (var i = 0; i < s_vec4Uniforms.length; i++) {
+ uniLoc = gl.getUniformLocation(programID, s_vec4Uniforms[i].name);
+ if (uniLoc != null)
+ gl.uniform4fv(uniLoc, new Float32Array(s_vec4Uniforms[i].value));
+ }
+ };
+
+ /**
+ * @param {glsShaderRenderCase.QuadGrid} quadGrid
+ * @param {?WebGLProgram} program
+ * @param {Array<gluDrawUtil.VertexArrayBinding>} vertexArrays
+ */
+ glsShaderRenderCase.getDefaultVertexArrays = function(quadGrid, program, vertexArrays) {
+ /** @type {number} */ var numElements = quadGrid.getNumVertices();
+ var posArray = [].concat.apply([], quadGrid.getPositions());
+ var coordsArray = [].concat.apply([], quadGrid.getCoordsArray());
+ var unitCoordsArray = [].concat.apply([], quadGrid.getUnitCoordsArray());
+
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numElements, 0, posArray));
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding("a_coords", 4, numElements, 0, coordsArray));
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding("a_unitCoords", 4, numElements, 0, unitCoordsArray));
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding("a_one", 1, numElements, 0, quadGrid.getAttribOne()));
+
+ // a_inN.
+ for (var userNdx = 0; userNdx < quadGrid.getNumUserAttribs(); userNdx++) {
+ /** @type {string} */ var name = "a_in" + userNdx;
+ var userAttribArray = [].concat.apply([], quadGrid.getUserAttribByIndex(userNdx));
+ vertexArrays.push(gluDrawUtil.newFloatVertexArrayBinding(name, 4, numElements, 0, userAttribArray));
+ }
+
+ // Matrix attributes - these are set by location
+ /**
+ * @constructor
+ * @struct
+ */
+ var Matrix = function(name, cols, rows) {
+ this.name = name;
+ this.numCols = cols;
+ this.numRows = rows;
+ };
+
+ /** @type {Array<Matrix>} */ var matrices = [
+ new Matrix('a_mat2', 2, 2),
+ new Matrix('a_mat2x3', 2, 3),
+ new Matrix('a_mat2x4', 2, 4),
+ new Matrix('a_mat3x2', 3, 2),
+ new Matrix('a_mat3', 3, 3),
+ new Matrix('a_mat3x4', 3, 4),
+ new Matrix('a_mat4x2', 4, 2),
+ new Matrix('a_mat4x3', 4, 3),
+ new Matrix('a_mat4', 4, 4)
+ ];
+
+ for (var matNdx = 0; matNdx < matrices.length; matNdx++) {
+ /** @type {number} */ var loc = gl.getAttribLocation(program, matrices[matNdx].name);
+
+ if (loc < 0)
+ continue; // Not used in shader.
+
+ /** @type {number} */ var numRows = matrices[matNdx].numRows;
+ /** @type {number} */ var numCols = matrices[matNdx].numCols;
+
+ for (var colNdx = 0; colNdx < numCols; colNdx++) {
+ var data = [].concat.apply([], quadGrid.getUserAttribByIndex(colNdx));
+ vertexArrays.push(gluDrawUtil.newFloatColumnVertexArrayBinding(matrices[matNdx].name, colNdx, numRows, numElements, 4 * 4, data));
+ }
+ }
+ };
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsStateQuery.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsStateQuery.js
new file mode 100644
index 0000000000..962d87fb47
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsStateQuery.js
@@ -0,0 +1,367 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsStateQuery');
+
+goog.scope(function() {
+var glsStateQuery = modules.shared.glsStateQuery;
+
+/**
+ * Compare two objects. Objects must have the same type and contents.
+ * If comparing numbers, allow some epsilon differences
+ * @param {*} a
+ * @param {*} b
+ * return {boolean}
+ */
+glsStateQuery.compare = function(a, b) {
+ /** @const */ var eps = 0.01;
+ if (a === b)
+ return true;
+
+ if (typeof a === 'number' && typeof b === 'number')
+ return Math.abs(a - b) < eps;
+
+ //compare array-like parameters
+ if (typeof a == 'object' && typeof b == 'object') {
+ if (a.constructor !== b.constructor)
+ return false;
+
+ if ('length' in a && 'length' in b) {
+ if (a.length !== b.length)
+ return false;
+ for (var i = 0; i < a.length; i++) {
+ if (typeof a[i] === 'number' && typeof b[i] === 'number') {
+ if (Math.abs(a[i] - b[i]) >= eps)
+ return false;
+ } else if (a[i] !== b[i])
+ return false;
+ }
+ return true;
+ }
+
+ }
+ return false;
+};
+
+/**
+ * Verify that WebGL state 'param' has the expected value
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verify = function(param, reference) {
+ var value = gl.getParameter(param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL current vertex attrib has the expected value
+ * @param {number} index
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyCurrentVertexAttrib = function(index, reference) {
+ var value = gl.getVertexAttrib(index, gl.CURRENT_VERTEX_ATTRIB);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL vertex attrib attribute 'param' has the expected value
+ * @param {number} index
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyVertexAttrib = function(index, param, reference) {
+ var value = (param == gl.VERTEX_ATTRIB_ARRAY_POINTER) ?
+ gl.getVertexAttribOffset(index, param) :
+ gl.getVertexAttrib(index, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL uniform has the expected value
+ * @param {WebGLProgram} program
+ * @param {WebGLUniformLocation} location
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyUniform = function(program, location, reference) {
+ var value = gl.getUniform(program, location);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL shader state 'param' has the expected value
+ * @param {WebGLShader} shader
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyShader = function(shader, param, reference) {
+ var value = gl.getShaderParameter(shader, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL program state 'param' has the expected value
+ * @param {WebGLProgram} program
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyProgram = function(program, param, reference) {
+ var value = gl.getProgramParameter(program, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL sampler state 'param' has the expected value
+ * @param {WebGLSampler} sampler
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifySampler = function(sampler, param, reference) {
+ var value = gl.getSamplerParameter(sampler, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL texture state 'param' has the expected value
+ * @param {number} target
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyTexture = function(target, param, reference) {
+ var value = gl.getTexParameter(target, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL state 'param' has one of the expected values
+ * @param {number} param
+ * @param {Array<*>} reference
+ * return {boolean}
+ */
+glsStateQuery.verifyAnyOf = function(param, reference) {
+ var value = gl.getParameter(param);
+ for (var i = 0; i < reference.length; i++)
+ if (glsStateQuery.compare(value, reference[i]))
+ return true;
+ bufferedLogToConsole('Result: ' + value + ' Expected one of: ' + reference);
+ return false;
+};
+
+/**
+ * Verify that WebGL state 'param' has the expected value
+ * @param {number} param
+ * @param {number|Array<number>} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyGreaterOrEqual = function(param, reference) {
+ var value = gl.getParameter(param);
+ if (reference instanceof Array) {
+ var v = /** @type {Array<number>} */ (value);
+ if (v.length != reference.length) {
+ bufferedLogToConsole('Result: ' + value + ' Expected >= : ' + reference);
+ return false;
+ }
+ for (var i = 0; i < reference.length; i++)
+ if (v[i] < reference[i]) {
+ bufferedLogToConsole('Result: ' + value + ' Expected >= : ' + reference);
+ return false;
+ }
+ return true;
+ }
+ var n = /** @type {number} */ (value);
+ if (n < reference) {
+ bufferedLogToConsole('Result: ' + value + ' Expected >= : ' + reference);
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Verify that WebGL state 'param' has the expected value
+ * @param {number} param
+ * @param {number|Array<number>} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyLessOrEqual = function(param, reference) {
+ var value = gl.getParameter(param);
+ if (reference instanceof Array) {
+ var v = /** @type {Array<number>} */ (value);
+ if (v.length != reference.length) {
+ bufferedLogToConsole('Result: ' + value + ' Expected <= : ' + reference);
+ return false;
+ }
+ for (var i = 0; i > reference.length; i++)
+ if (v[i] < reference[i]) {
+ bufferedLogToConsole('Result: ' + value + ' Expected <= : ' + reference);
+ return false;
+ }
+ return true;
+ }
+ var n = /** @type {number} */ (value);
+ if (n > reference) {
+ bufferedLogToConsole('Result: ' + value + ' Expected <= : ' + reference);
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Verify that WebGL state 'param' has the expected value (value & mask == reference)
+ * @param {number} param
+ * @param {number} reference
+ * @param {number} mask
+ * @return {boolean}
+ */
+glsStateQuery.verifyMasked = function(param, reference, mask) {
+ var value = /** @type {number} */ (gl.getParameter(param));
+ if ((value & mask) !== reference) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference + 'Mask: 0x' + mask.toString(16));
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Verify that WebGL fbo attachment 'param' has the expected value
+ * @param {number} fbo
+ * @param {number} attachment
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyAttachment = function(fbo, attachment, param, reference) {
+ var value = gl.getFramebufferAttachmentParameter(fbo, attachment, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL fbo color attachment 'param' has the expected value
+ * @param {number} fbo
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyColorAttachment = function(fbo, param, reference) {
+ return glsStateQuery.verifyAttachment(fbo, gl.COLOR_ATTACHMENT0, param, reference);
+};
+
+/**
+ * Verify that WebGL rbo attribute 'param' has the expected value
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyRenderbuffer = function(param, reference) {
+ var value = gl.getRenderbufferParameter(gl.RENDERBUFFER, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * Verify that WebGL active uniform block's attribute 'param' has the expected value
+ * @param {WebGLProgram} program
+ * @param {number} index
+ * @param {number} param
+ * @param {*} reference
+ * @return {boolean}
+ */
+glsStateQuery.verifyActiveUniformBlock = function(program, index, param, reference) {
+ var value = gl.getActiveUniformBlockParameter(program, index, param);
+ var result = glsStateQuery.compare(value, reference);
+ if (!result) {
+ bufferedLogToConsole('Result: ' + value + ' Expected: ' + reference);
+ }
+ return result;
+};
+
+/**
+ * @param {number} param
+ * @param {Array<number>} reference
+ * @param {Array<boolean>} enableRef
+ * @return {boolean}
+ */
+
+glsStateQuery.verifyMask = function(param, reference, enableRef) {
+ var intVector4 = /** @type {Array<number>} */ (gl.getParameter(param));
+
+ if ((enableRef[0] && (intVector4[0] != reference[0])) ||
+ (enableRef[1] && (intVector4[1] != reference[1])) ||
+ (enableRef[2] && (intVector4[2] != reference[2])) ||
+ (enableRef[3] && (intVector4[3] != reference[3])))
+ {
+ bufferedLogToConsole("// ERROR: expected " +
+ (enableRef[0] ? "" : "(") + reference[0] + (enableRef[0] ? "" : ")") + ", " +
+ (enableRef[1] ? "" : "(") + reference[1] + (enableRef[1] ? "" : ")") + ", " +
+ (enableRef[2] ? "" : "(") + reference[2] + (enableRef[2] ? "" : ")") + ", " +
+ (enableRef[3] ? "" : "(") + reference[3] + (enableRef[3] ? "" : ")"));
+
+ return false;
+ }
+ return true;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsTextureTestUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsTextureTestUtil.js
new file mode 100644
index 0000000000..f35d942261
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsTextureTestUtil.js
@@ -0,0 +1,2642 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsTextureTestUtil');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexLookupVerifier');
+goog.require('framework.common.tcuTexCompareVerifier');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.delibs.debase.deRandom');
+
+goog.scope(function() {
+var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
+var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier;
+var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
+var gluDrawUtil = framework.opengl.gluDrawUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var tcuTexture = framework.common.tcuTexture;
+var tcuSurface = framework.common.tcuSurface;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var tcuStringTemplate = framework.common.tcuStringTemplate;
+var deMath = framework.delibs.debase.deMath;
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuPixelFormat = framework.common.tcuPixelFormat;
+var tcuRGBA = framework.common.tcuRGBA;
+var deRandom = framework.delibs.debase.deRandom;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+var MIN_SUBPIXEL_BITS = 4;
+
+/**
+ * @enum
+ */
+glsTextureTestUtil.textureType = {
+ TEXTURETYPE_2D: 0,
+ TEXTURETYPE_CUBE: 1,
+ TEXTURETYPE_2D_ARRAY: 2,
+ TEXTURETYPE_3D: 3,
+ TEXTURETYPE_CUBE_ARRAY: 4,
+ TEXTURETYPE_1D: 5,
+ TEXTURETYPE_1D_ARRAY: 6,
+ TEXTURETYPE_BUFFER: 7
+};
+
+/**
+ * @enum
+ */
+glsTextureTestUtil.samplerType = {
+ SAMPLERTYPE_FLOAT: 0,
+ SAMPLERTYPE_INT: 1,
+ SAMPLERTYPE_UINT: 2,
+ SAMPLERTYPE_SHADOW: 3,
+
+ SAMPLERTYPE_FETCH_FLOAT: 4,
+ SAMPLERTYPE_FETCH_INT: 5,
+ SAMPLERTYPE_FETCH_UINT: 6
+};
+
+/**
+ * @param {tcuTexture.TextureFormat} format
+ * @return {glsTextureTestUtil.samplerType}
+ */
+glsTextureTestUtil.getSamplerType = function(format) {
+ if (format == null)
+ throw new Error('Missing format information');
+
+ switch (format.type) {
+ case tcuTexture.ChannelType.SIGNED_INT8:
+ case tcuTexture.ChannelType.SIGNED_INT16:
+ case tcuTexture.ChannelType.SIGNED_INT32:
+ return glsTextureTestUtil.samplerType.SAMPLERTYPE_INT;
+
+ case tcuTexture.ChannelType.UNSIGNED_INT8:
+ case tcuTexture.ChannelType.UNSIGNED_INT32:
+ case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV:
+ return glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT;
+
+ // Texture formats used in depth/stencil textures.
+ case tcuTexture.ChannelType.UNSIGNED_INT16:
+ case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
+ return (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS) ? glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT : glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT;
+
+ default:
+ return glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT;
+ }
+};
+
+/**
+ * @constructor
+ * @param {HTMLElement} canvas
+ * @param {number} preferredWidth
+ * @param {number} preferredHeight
+ * @param {number=} seed
+ */
+glsTextureTestUtil.RandomViewport = function(canvas, preferredWidth, preferredHeight, seed) {
+ this.width = Math.min(canvas.width, preferredWidth);
+ this.height = Math.min(canvas.height, preferredHeight);
+
+ if (typeof seed === 'undefined')
+ seed = preferredWidth + preferredHeight;
+
+ var rnd = new deRandom.Random(seed);
+ this.x = rnd.getInt(0, canvas.width - this.width);
+ this.y = rnd.getInt(0, canvas.height - this.height);
+};
+
+/**
+ * @constructor
+ * @param {glsTextureTestUtil.textureType} texType
+ */
+glsTextureTestUtil.RenderParams = function(texType) {
+ this.flags = {
+ projected: false,
+ use_bias: false,
+ log_programs: false,
+ log_uniforms: false
+ };
+ this.texType = texType;
+ this.w = [1, 1, 1, 1];
+ this.bias = 0;
+ this.ref = 0;
+ this.colorScale = [1, 1, 1, 1];
+ this.colorBias = [0, 0, 0, 0];
+ this.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT;
+};
+
+/**
+ * @enum
+ */
+glsTextureTestUtil.lodMode = {
+ EXACT: 0, //!< Ideal lod computation.
+ MIN_BOUND: 1, //!< Use estimation range minimum bound.
+ MAX_BOUND: 2 //!< Use estimation range maximum bound.
+
+};
+
+/**
+ * @constructor
+ * @extends {glsTextureTestUtil.RenderParams}
+ * @param {glsTextureTestUtil.textureType} texType
+ * @param {tcuTexture.Sampler=} sampler
+ * @param {glsTextureTestUtil.lodMode=} lodMode_
+ */
+glsTextureTestUtil.ReferenceParams = function(texType, sampler, lodMode_) {
+ glsTextureTestUtil.RenderParams.call(this, texType);
+ if (sampler)
+ this.sampler = sampler;
+ if (lodMode_)
+ this.lodMode = lodMode_;
+ else
+ this.lodMode = glsTextureTestUtil.lodMode.EXACT;
+ this.minLod = -1000;
+ this.maxLod = 1000;
+ this.baseLevel = 0;
+ this.maxLevel = 1000;
+};
+
+glsTextureTestUtil.ReferenceParams.prototype = Object.create(glsTextureTestUtil.RenderParams.prototype);
+
+/** Copy constructor */
+glsTextureTestUtil.ReferenceParams.prototype.constructor = glsTextureTestUtil.ReferenceParams;
+
+/**
+ * @param {Array<number>} bottomLeft
+ * @param {Array<number>} topRight
+ * @return {Array<number>}
+ */
+glsTextureTestUtil.computeQuadTexCoord2D = function(bottomLeft, topRight) {
+ var dst = [];
+ dst.length = 4 * 2;
+
+ dst[0] = bottomLeft[0]; dst[1] = bottomLeft[1];
+ dst[2] = bottomLeft[0]; dst[3] = topRight[1];
+ dst[4] = topRight[0]; dst[5] = bottomLeft[1];
+ dst[6] = topRight[0]; dst[7] = topRight[1];
+
+ return dst;
+};
+
+/**
+ * @param {tcuTexture.CubeFace} face
+ * @return {Array<number>}
+ */
+glsTextureTestUtil.computeQuadTexCoordCube = function(face) {
+ var texCoordNegX = [
+ -1, 1, -1,
+ -1, -1, -1,
+ -1, 1, 1,
+ -1, -1, 1
+ ];
+ var texCoordPosX = [
+ +1, 1, 1,
+ +1, -1, 1,
+ +1, 1, -1,
+ +1, -1, -1
+ ];
+ var texCoordNegY = [
+ -1, -1, 1,
+ -1, -1, -1,
+ 1, -1, 1,
+ 1, -1, -1
+ ];
+ var texCoordPosY = [
+ -1, +1, -1,
+ -1, +1, 1,
+ 1, +1, -1,
+ 1, +1, 1
+ ];
+ var texCoordNegZ = [
+ 1, 1, -1,
+ 1, -1, -1,
+ -1, 1, -1,
+ -1, -1, -1
+ ];
+ var texCoordPosZ = [
+ -1, 1, +1,
+ -1, -1, +1,
+ 1, 1, +1,
+ 1, -1, +1
+ ];
+
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return texCoordNegX;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return texCoordPosX;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return texCoordNegY;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return texCoordPosY;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return texCoordNegZ;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return texCoordPosZ;
+ }
+ throw new Error('Unrecognized face ' + face);
+};
+
+/**
+ * @param {tcuTexture.CubeFace} face
+ * @param {Array<number>} bottomLeft
+ * @param {Array<number>} topRight
+ * @return {Array<number>}
+ */
+glsTextureTestUtil.computeQuadTexCoordCubeFace = function(face, bottomLeft, topRight) {
+ var dst = [];
+ /** @type {number} */ var sRow = 0;
+ /** @type {number} */ var tRow = 0;
+ /** @type {number} */ var mRow = 0;
+ /** @type {number} */ var sSign = 1.0;
+ /** @type {number} */ var tSign = 1.0;
+ /** @type {number} */ var mSign = 1.0;
+
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0; tSign = -1.0; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1; sSign = -1.0; tSign = -1.0; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0; tSign = -1.0; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0; sSign = -1.0; tSign = -1.0; break;
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1; tSign = -1.0; break;
+ default:
+ throw new Error('Invalid cube face specified.');
+ }
+
+ dst[0 + mRow] = mSign;
+ dst[3 + mRow] = mSign;
+ dst[6 + mRow] = mSign;
+ dst[9 + mRow] = mSign;
+
+ dst[0 + sRow] = sSign * bottomLeft[0];
+ dst[3 + sRow] = sSign * bottomLeft[0];
+ dst[6 + sRow] = sSign * topRight[0];
+ dst[9 + sRow] = sSign * topRight[0];
+
+ dst[0 + tRow] = tSign * bottomLeft[1];
+ dst[3 + tRow] = tSign * topRight[1];
+ dst[6 + tRow] = tSign * bottomLeft[1];
+ dst[9 + tRow] = tSign * topRight[1];
+
+ return dst;
+};
+
+/**
+ * @param {number} layerNdx
+ * @param {Array<number>} bottomLeft
+ * @param {Array<number>} topRight
+ * @return {Array<number>}
+ */
+glsTextureTestUtil.computeQuadTexCoord2DArray = function(layerNdx, bottomLeft, topRight) {
+ var dst = [];
+ dst.length = 4 * 3;
+
+ dst[0] = bottomLeft[0]; dst[1] = bottomLeft[1]; dst[2] = layerNdx;
+ dst[3] = bottomLeft[0]; dst[4] = topRight[1]; dst[5] = layerNdx;
+ dst[6] = topRight[0]; dst[7] = bottomLeft[1]; dst[8] = layerNdx;
+ dst[9] = topRight[0]; dst[10] = topRight[1]; dst[11] = layerNdx;
+
+ return dst;
+};
+
+/**
+ * @param {Array<number>} a
+ * @param {Array<number>} b
+ * @param {Array<number>} c
+ * @return {Array<number>} a + (b - a) * c
+ */
+glsTextureTestUtil.selectCoords = function(a, b, c) {
+ var x1 = deMath.subtract(b, a);
+ var x2 = deMath.multiply(x1, c);
+ var x3 = deMath.add(a, x2);
+ return x3;
+};
+
+/**
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ * @param {Array<number>} dirSwz
+ * @return {Array<number>}
+ */
+glsTextureTestUtil.computeQuadTexCoord3D = function(p0, p1, dirSwz) {
+ var dst = [];
+ dst.length = 4 * 3;
+
+ var f0 = deMath.swizzle(([0, 0, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
+ var f1 = deMath.swizzle(([0, 1, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
+ var f2 = deMath.swizzle(([1, 0, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
+ var f3 = deMath.swizzle(([1, 1, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
+
+ var v0 = glsTextureTestUtil.selectCoords(p0, p1, f0);
+ var v1 = glsTextureTestUtil.selectCoords(p0, p1, f1);
+ var v2 = glsTextureTestUtil.selectCoords(p0, p1, f2);
+ var v3 = glsTextureTestUtil.selectCoords(p0, p1, f3);
+
+ dst[0] = v0[0]; dst[1] = v0[1]; dst[2] = v0[2];
+ dst[3] = v1[0]; dst[4] = v1[1]; dst[5] = v1[2];
+ dst[6] = v2[0]; dst[7] = v2[1]; dst[8] = v2[2];
+ dst[9] = v3[0]; dst[10] = v3[1]; dst[11] = v3[2];
+
+ return dst;
+};
+
+/**
+ * @enum
+ */
+glsTextureTestUtil.programType = {
+ PROGRAM_2D_FLOAT: 0,
+ PROGRAM_2D_INT: 1,
+ PROGRAM_2D_UINT: 2,
+ PROGRAM_2D_SHADOW: 3,
+
+ PROGRAM_2D_FLOAT_BIAS: 4,
+ PROGRAM_2D_INT_BIAS: 5,
+ PROGRAM_2D_UINT_BIAS: 6,
+ PROGRAM_2D_SHADOW_BIAS: 7,
+
+ PROGRAM_1D_FLOAT: 8,
+ PROGRAM_1D_INT: 9,
+ PROGRAM_1D_UINT: 10,
+ PROGRAM_1D_SHADOW: 11,
+
+ PROGRAM_1D_FLOAT_BIAS: 12,
+ PROGRAM_1D_INT_BIAS: 13,
+ PROGRAM_1D_UINT_BIAS: 14,
+ PROGRAM_1D_SHADOW_BIAS: 15,
+
+ PROGRAM_CUBE_FLOAT: 16,
+ PROGRAM_CUBE_INT: 17,
+ PROGRAM_CUBE_UINT: 18,
+ PROGRAM_CUBE_SHADOW: 19,
+
+ PROGRAM_CUBE_FLOAT_BIAS: 20,
+ PROGRAM_CUBE_INT_BIAS: 21,
+ PROGRAM_CUBE_UINT_BIAS: 22,
+ PROGRAM_CUBE_SHADOW_BIAS: 23,
+
+ PROGRAM_1D_ARRAY_FLOAT: 24,
+ PROGRAM_1D_ARRAY_INT: 25,
+ PROGRAM_1D_ARRAY_UINT: 26,
+ PROGRAM_1D_ARRAY_SHADOW: 27,
+
+ PROGRAM_2D_ARRAY_FLOAT: 28,
+ PROGRAM_2D_ARRAY_INT: 29,
+ PROGRAM_2D_ARRAY_UINT: 30,
+ PROGRAM_2D_ARRAY_SHADOW: 31,
+
+ PROGRAM_3D_FLOAT: 32,
+ PROGRAM_3D_INT: 33,
+ PROGRAM_3D_UINT: 34,
+
+ PROGRAM_3D_FLOAT_BIAS: 35,
+ PROGRAM_3D_INT_BIAS: 36,
+ PROGRAM_3D_UINT_BIAS: 37,
+
+ PROGRAM_CUBE_ARRAY_FLOAT: 38,
+ PROGRAM_CUBE_ARRAY_INT: 39,
+ PROGRAM_CUBE_ARRAY_UINT: 40,
+ PROGRAM_CUBE_ARRAY_SHADOW: 41,
+
+ PROGRAM_BUFFER_FLOAT: 42,
+ PROGRAM_BUFFER_INT: 43,
+ PROGRAM_BUFFER_UINT: 44
+};
+
+/**
+ * @constructor
+ * @param {string} version GL version
+ * @param {gluShaderUtil.precision} precision
+ */
+glsTextureTestUtil.ProgramLibrary = function(version, precision) {
+ this.m_glslVersion = version;
+ this.m_texCoordPrecision = precision;
+};
+
+/**
+ * @param {glsTextureTestUtil.programType} program
+ * @return {gluShaderProgram.ShaderProgram}
+ */
+glsTextureTestUtil.ProgramLibrary.prototype.getProgram = function(program) {
+ /* TODO: Implement */
+ // if (m_programs.find(program) != m_programs.end())
+ // return m_programs[program]; // Return from cache.
+
+ var vertShaderTemplate =
+ '${VTX_HEADER}' +
+ '${VTX_IN} highp vec4 a_position;\n' +
+ '${VTX_IN} ${PRECISION} ${TEXCOORD_TYPE} a_texCoord;\n' +
+ '${VTX_OUT} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ ' gl_Position = a_position;\n' +
+ ' v_texCoord = a_texCoord;\n' +
+ '}\n';
+ var fragShaderTemplate =
+ '${FRAG_HEADER}' +
+ '${FRAG_IN} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n' +
+ 'uniform ${PRECISION} float u_bias;\n' +
+ 'uniform ${PRECISION} float u_ref;\n' +
+ 'uniform ${PRECISION} vec4 u_colorScale;\n' +
+ 'uniform ${PRECISION} vec4 u_colorBias;\n' +
+ 'uniform ${PRECISION} ${SAMPLER_TYPE} u_sampler;\n' +
+ '\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ ' ${FRAG_COLOR} = ${LOOKUP} * u_colorScale + u_colorBias;\n' +
+ '}\n';
+
+ var params = [];
+
+ var isCube = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT, glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS);
+ var isArray = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW) ||
+ deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW);
+
+ var is1D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS) ||
+ deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW) ||
+ deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT, glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT);
+
+ var is2D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS) ||
+ deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW);
+
+ var is3D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_3D_FLOAT, glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS);
+ var isCubeArray = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW);
+ var isBuffer = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT, glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT);
+
+ if (this.m_glslVersion === '100 es') {
+ params['FRAG_HEADER'] = '';
+ params['VTX_HEADER'] = '';
+ params['VTX_IN'] = 'attribute';
+ params['VTX_OUT'] = 'varying';
+ params['FRAG_IN'] = 'varying';
+ params['FRAG_COLOR'] = 'gl_FragColor';
+ } else if (this.m_glslVersion === '300 es' || this.m_glslVersion === '310 es' || this.m_glslVersion === '330 es') {
+ var ext = null;
+
+ // if (isCubeArray && glu::glslVersionIsES(m_glslVersion))
+ // ext = "gl.EXT_texture_cube_map_array";
+ // else if (isBuffer && glu::glslVersionIsES(m_glslVersion))
+ // ext = "gl.EXT_texture_buffer";
+
+ var extension = '';
+ if (ext)
+ extension = '\n#extension ' + ext + ' : require';
+
+ params['FRAG_HEADER'] = '#version ' + this.m_glslVersion + extension + '\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+ params['VTX_HEADER'] = '#version ' + this.m_glslVersion + '\n';
+ params['VTX_IN'] = 'in';
+ params['VTX_OUT'] = 'out';
+ params['FRAG_IN'] = 'in';
+ params['FRAG_COLOR'] = 'dEQP_FragColor';
+ } else
+ throw new Error('Unsupported version: ' + this.m_glslVersion);
+
+ params['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_texCoordPrecision);
+
+ if (isCubeArray)
+ params['TEXCOORD_TYPE'] = 'vec4';
+ else if (isCube || (is2D && isArray) || is3D)
+ params['TEXCOORD_TYPE'] = 'vec3';
+ else if ((is1D && isArray) || is2D)
+ params['TEXCOORD_TYPE'] = 'vec2';
+ else if (is1D)
+ params['TEXCOORD_TYPE'] = 'float';
+ else
+ DE_ASSERT(false);
+
+ var sampler = null;
+ var lookup = null;
+
+ if (this.m_glslVersion === '300 es' || this.m_glslVersion === '310 es' || this.m_glslVersion === '330 es') {
+ switch (program) {
+ case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT: sampler = 'sampler2D'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_INT: sampler = 'isampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_UINT: sampler = 'usampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_SHADOW: sampler = 'sampler2DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS: sampler = 'sampler2D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_INT_BIAS: sampler = 'isampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS: sampler = 'usampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_SHADOW_BIAS: sampler = 'sampler2DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_FLOAT: sampler = 'sampler1D'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_INT: sampler = 'isampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_UINT: sampler = 'usampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_SHADOW: sampler = 'sampler1DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_FLOAT_BIAS: sampler = 'sampler1D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_INT_BIAS: sampler = 'isampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS: sampler = 'usampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_SHADOW_BIAS: sampler = 'sampler1DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT: sampler = 'samplerCube'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_INT: sampler = 'isamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_UINT: sampler = 'usamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW: sampler = 'samplerCubeShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS: sampler = 'samplerCube'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_INT_BIAS: sampler = 'isamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_UINT_BIAS: sampler = 'usamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS: sampler = 'samplerCubeShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT: sampler = 'sampler2DArray'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_INT: sampler = 'isampler2DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_UINT: sampler = 'usampler2DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW: sampler = 'sampler2DArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_3D_FLOAT: sampler = 'sampler3D'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_3D_INT: sampler = 'isampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_3D_UINT: sampler = ' usampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_3D_FLOAT_BIAS: sampler = 'sampler3D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_3D_INT_BIAS: sampler = 'isampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS: sampler = ' usampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT: sampler = 'samplerCubeArray'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_INT: sampler = 'isamplerCubeArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_UINT: sampler = 'usamplerCubeArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW: sampler = 'samplerCubeArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT: sampler = 'sampler1DArray'; lookup = 'texture(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_INT: sampler = 'isampler1DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_UINT: sampler = 'usampler1DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW: sampler = 'sampler1DArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT: sampler = 'samplerBuffer'; lookup = 'texelFetch(u_sampler, int(v_texCoord))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_BUFFER_INT: sampler = 'isamplerBuffer'; lookup = 'vec4(texelFetch(u_sampler, int(v_texCoord)))'; break;
+ case glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT: sampler = 'usamplerBuffer'; lookup = 'vec4(texelFetch(u_sampler, int(v_texCoord)))'; break;
+ default:
+ DE_ASSERT(false);
+ }
+ } else if (this.m_glslVersion === '100 es') {
+ sampler = isCube ? 'samplerCube' : 'sampler2D';
+
+ switch (program) {
+ case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT: lookup = 'texture2D(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS: lookup = 'texture2D(u_sampler, v_texCoord, u_bias)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT: lookup = 'textureCube(u_sampler, v_texCoord)'; break;
+ case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS: lookup = 'textureCube(u_sampler, v_texCoord, u_bias)'; break;
+ default:
+ DE_ASSERT(false);
+ }
+ } else
+ DE_ASSERT(!'Unsupported version');
+
+ params['SAMPLER_TYPE'] = sampler;
+ params['LOOKUP'] = lookup;
+
+ var vertSrc = tcuStringTemplate.specialize(vertShaderTemplate, params);
+ var fragSrc = tcuStringTemplate.specialize(fragShaderTemplate, params);
+ var progObj = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertSrc, fragSrc));
+ // if (!progObj.isOk()) {
+ // // log << *progObj;
+ // testFailedOptions("Failed to create shader", true);
+ // }
+
+ // try
+ // {
+ // m_programs[program] = progObj;
+ // }
+ // catch (...)
+ // {
+ // delete progObj;
+ // throw;
+ // }
+
+ return progObj;
+};
+
+// public:
+// glsTextureTestUtil.ProgramLibrary (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision);
+// ~glsTextureTestUtil.ProgramLibrary (void);
+
+// glu::ShaderProgram* getProgram (Program program);
+// void clear (void);
+
+// private:
+// glsTextureTestUtil.ProgramLibrary (const glsTextureTestUtil.ProgramLibrary& other);
+// glsTextureTestUtil.ProgramLibrary& operator= (const glsTextureTestUtil.ProgramLibrary& other);
+
+// const glu::RenderContext& m_context;
+// tcu::TestContext& m_testCtx;
+// glu::GLSLVersion m_glslVersion;
+// glu::Precision m_texCoordPrecision;
+// std::map<Program, glu::ShaderProgram*> m_programs;
+// };
+
+/**
+ * @constructor
+ * @param {string} version GL version
+ * @param {gluShaderUtil.precision} precision
+ */
+glsTextureTestUtil.TextureRenderer = function(version, precision) {
+ this.m_programLibrary = new glsTextureTestUtil.ProgramLibrary(version, precision);
+};
+
+/**
+ * @param {tcuPixelFormat.PixelFormat} format
+ * @return {Array<boolean>}
+ */
+glsTextureTestUtil.getCompareMask = function(format) {
+ return [
+ format.redBits > 0,
+ format.greenBits > 0,
+ format.blueBits > 0,
+ format.alphaBits > 0
+ ];
+};
+
+/**
+ * @param {tcuPixelFormat.PixelFormat} format
+ * @return {Array<number>}
+ */
+glsTextureTestUtil.getBitsVec = function(format) {
+ return [
+ format.redBits,
+ format.greenBits,
+ format.blueBits,
+ format.alphaBits
+ ];
+};
+
+/**
+ * @param {number} texUnit
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.RenderParams} params
+ */
+glsTextureTestUtil.TextureRenderer.prototype.renderQuad = function(texUnit, texCoord, params) {
+ var wCoord = params.flags.projected ? params.w : [1, 1, 1, 1];
+ var useBias = params.flags.use_bias;
+ var logUniforms = params.flags.log_uniforms;
+
+ // Render quad with texture.
+ var position = [
+ -1 * wCoord[0], -1 * wCoord[0], 0, wCoord[0],
+ -1 * wCoord[1], +1 * wCoord[1], 0, wCoord[1],
+ +1 * wCoord[2], -1 * wCoord[2], 0, wCoord[2],
+ +1 * wCoord[3], +1 * wCoord[3], 0, wCoord[3]
+ ];
+ /** @const */ var indices = [0, 1, 2, 2, 1, 3];
+
+ /** @type {?glsTextureTestUtil.programType} */ var progSpec = null;
+ var numComps = 0;
+ if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_2D) {
+ numComps = 2;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_UINT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_SHADOW; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_1D) {
+ numComps = 1;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_UINT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_SHADOW; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_CUBE) {
+ numComps = 3;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_UINT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_3D) {
+ numComps = 3;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_UINT; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY) {
+ DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
+
+ numComps = 3;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_UINT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_CUBE_ARRAY) {
+ DE_ASSERT(!useBias);
+
+ numComps = 4;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_UINT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_1D_ARRAY) {
+ DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
+
+ numComps = 2;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_UINT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_BUFFER) {
+ numComps = 1;
+
+ switch (params.samplerType) {
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_INT; break;
+ case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT; break;
+ default: throw new Error('Unrecognized sampler type:' + params.samplerType);
+ }
+ } else
+ throw new Error('Unrecognized texture type:' + params.texType);
+
+ if (progSpec === null)
+ throw new Error('Could not find program specification');
+
+ var program = this.m_programLibrary.getProgram(progSpec);
+
+ // \todo [2012-09-26 pyry] Move to glsTextureTestUtil.ProgramLibrary and log unique programs only(?)
+ /* TODO: Port logging
+ if (params.flags.log_programs)
+ log << *program;
+ */
+
+ // Program and uniforms.
+ var prog = program.getProgram();
+ gl.useProgram(prog);
+
+ var loc = gl.getUniformLocation(prog, 'u_sampler');
+ gl.uniform1i(loc, texUnit);
+ // if (logUniforms)
+ // log << TestLog::Message << "u_sampler = " << texUnit << TestLog::EndMessage;
+
+ if (useBias) {
+ gl.uniform1f(gl.getUniformLocation(prog, 'u_bias'), params.bias);
+ // if (logUniforms)
+ // log << TestLog::Message << "u_bias = " << params.bias << TestLog::EndMessage;
+ }
+
+ if (params.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW) {
+ gl.uniform1f(gl.getUniformLocation(prog, 'u_ref'), params.ref);
+ // if (logUniforms)
+ // log << TestLog::Message << "u_ref = " << params.ref << TestLog::EndMessage;
+ }
+
+ gl.uniform4fv(gl.getUniformLocation(prog, 'u_colorScale'), params.colorScale);
+ gl.uniform4fv(gl.getUniformLocation(prog, 'u_colorBias'), params.colorBias);
+
+ // if (logUniforms)
+ // {
+ // log << TestLog::Message << "u_colorScale = " << params.colorScale << TestLog::EndMessage;
+ // log << TestLog::Message << "u_colorBias = " << params.colorBias << TestLog::EndMessage;
+ // }
+ var vertexArrays = [];
+
+ var posLoc = gl.getAttribLocation(prog, 'a_position');
+ if (posLoc === -1) {
+ testFailedOptions("no location found for attribute 'a_position'", true);
+ }
+ var texLoc = gl.getAttribLocation(prog, 'a_texCoord');
+ if (texLoc === -1) {
+ testFailedOptions("no location found for attribute 'a_texCoord'", true);
+ }
+
+ vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, 4, position));
+ vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, texLoc, numComps, 4, texCoord));
+ gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
+};
+
+// public:
+// glsTextureTestUtil.TextureRenderer (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision);
+// ~glsTextureTestUtil.TextureRenderer (void);
+
+// void clear (void); //!< Frees allocated resources. Destructor will call clear() as well.
+
+// void renderQuad (int texUnit, const float* texCoord, TextureType texType);
+// void renderQuad (int texUnit, const float* texCoord, const glsTextureTestUtil.RenderParams& params);
+
+// private:
+// glsTextureTestUtil.TextureRenderer (const glsTextureTestUtil.TextureRenderer& other);
+// glsTextureTestUtil.TextureRenderer& operator= (const glsTextureTestUtil.TextureRenderer& other);
+
+// const glu::RenderContext& m_renderCtx;
+// tcu::TestContext& m_testCtx;
+// glsTextureTestUtil.ProgramLibrary m_programLibrary;
+// };
+
+/**
+ * @constructor
+ * @param {tcuSurface.Surface} surface
+ * @param {tcuPixelFormat.PixelFormat=} colorFmt
+ * @param {number=} x
+ * @param {number=} y
+ * @param {number=} width
+ * @param {number=} height
+ */
+glsTextureTestUtil.SurfaceAccess = function(surface, colorFmt, x, y, width, height) {
+ this.m_surface = surface;
+ this.colorMask = undefined; /*TODO*/
+ this.m_x = x || 0;
+ this.m_y = y || 0;
+ this.m_width = width || surface.getWidth();
+ this.m_height = height || surface.getHeight();
+};
+
+/** @return {number} */
+glsTextureTestUtil.SurfaceAccess.prototype.getWidth = function() { return this.m_width; };
+/** @return {number} */
+glsTextureTestUtil.SurfaceAccess.prototype.getHeight = function() { return this.m_height; };
+
+/**
+ * @param {Array<number>} color
+ * @param {number} x
+ * @param {number} y
+ */
+glsTextureTestUtil.SurfaceAccess.prototype.setPixel = function(color, x, y) {
+ /* TODO: Apply color mask */
+ var c = color;
+ for (var i = 0; i < c.length; i++)
+ c[i] = deMath.clamp(Math.round(color[i] * 255), 0, 255);
+ this.m_surface.setPixel(x, y, c);
+};
+
+/**
+ * @param {glsTextureTestUtil.lodMode} mode
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dwdx
+ * @param {number} dudy
+ * @param {number} dvdy
+ * @param {number} dwdy
+ * @return {number}
+ */
+glsTextureTestUtil.computeLodFromDerivates3D = function(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy) {
+ var p = 0;
+ switch (mode) {
+ case glsTextureTestUtil.lodMode.EXACT:
+ p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx + dwdx * dwdx), Math.sqrt(dudy * dudy + dvdy * dvdy + dwdy * dwdy));
+ break;
+
+ case glsTextureTestUtil.lodMode.MIN_BOUND:
+ case glsTextureTestUtil.lodMode.MAX_BOUND: {
+ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
+ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
+ var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy));
+
+ p = (mode == glsTextureTestUtil.lodMode.MIN_BOUND) ? Math.max(mu, mv, mw) : mu + mv + mw;
+ break;
+ }
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ // Native dEQP uses 32-bit numbers. So here 64-bit floating numbers should be transformed into 32-bit ones to ensure the correctness of the result.
+ return deMath.toFloat32(Math.log(p)) * deMath.INV_LOG_2_FLOAT32;
+};
+
+/**
+ * @param {glsTextureTestUtil.lodMode} mode
+ * @param {Array<number>} dstSize
+ * @param {Array<number>} srcSize
+ * @param {Array<number>} sq
+ * @param {Array<number>} tq
+ * @param {Array<number>=} rq
+ * @return {number}
+ */
+glsTextureTestUtil.computeNonProjectedTriLod = function(mode, dstSize, srcSize, sq, tq, rq) {
+ var dux = (sq[2] - sq[0]) * srcSize[0];
+ var duy = (sq[1] - sq[0]) * srcSize[0];
+ var dvx = (tq[2] - tq[0]) * srcSize[1];
+ var dvy = (tq[1] - tq[0]) * srcSize[1];
+ var dwx = 0;
+ var dwy = 0;
+ if (rq) {
+ dwx = (rq[2] - rq[0]) * srcSize[2];
+ dwy = (rq[1] - rq[0]) * srcSize[2];
+ }
+ var dx = dstSize[0];
+ var dy = dstSize[1];
+
+ return glsTextureTestUtil.computeLodFromDerivates3D(mode, dux / dx, dvx / dx, dwx / dx, duy / dy, dvy / dy, dwy / dy);
+};
+
+/**
+ * @param {Array<number>} v
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+glsTextureTestUtil.triangleInterpolate = function(v, x, y) {
+ return v[0] + (v[2] - v[0]) * x + (v[1] - v[0]) * y;
+};
+
+/**
+ * @param {Array<number>} s
+ * @param {Array<number>} w
+ * @param {number} wx
+ * @param {number} width
+ * @param {number} ny
+ * @return {number}
+ */
+glsTextureTestUtil.triDerivateX = function(s, w, wx, width, ny) {
+ var d = w[1] * w[2] * (width * (ny - 1) + wx) - w[0] * (w[2] * width * ny + w[1] * wx);
+ return (w[0] * w[1] * w[2] * width * (w[1] * (s[0] - s[2]) * (ny - 1) + ny * (w[2] * (s[1] - s[0]) + w[0] * (s[2] - s[1])))) / (d * d);
+};
+
+/**
+ * @param {Array<number>} s
+ * @param {Array<number>} w
+ * @param {number} wy
+ * @param {number} height
+ * @param {number} nx
+ * @return {number}
+ */
+glsTextureTestUtil.triDerivateY = function(s, w, wy, height, nx) {
+ var d = w[1] * w[2] * (height * (nx - 1) + wy) - w[0] * (w[1] * height * nx + w[2] * wy);
+ return (w[0] * w[1] * w[2] * height * (w[2] * (s[0] - s[1]) * (nx - 1) + nx * (w[0] * (s[1] - s[2]) + w[1] * (s[2] - s[0])))) / (d * d);
+};
+
+/**
+ * @param {(tcuTexture.Texture2DView|tcuTexture.Texture2DArrayView|tcuTexture.TextureCubeView)} src
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ * @param {Array<number>} texCoord Texture coordinates
+ * @param {number} lod
+ * @return {Array<number>} sample
+ */
+glsTextureTestUtil.execSample = function(src, params, texCoord, lod) {
+ if (params.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW)
+ return [src.sampleCompare(params.sampler, params.ref, texCoord, lod), 0, 0, 1];
+ else
+ return src.sample(params.sampler, texCoord, lod);
+};
+
+/**
+ * @param {Array<number>} pixel
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+glsTextureTestUtil.applyScaleAndBias = function(pixel, scale, bias) {
+ pixel[0] = pixel[0] * scale[0] + bias[0];
+ pixel[1] = pixel[1] * scale[1] + bias[1];
+ pixel[2] = pixel[2] * scale[2] + bias[2];
+ pixel[3] = pixel[3] * scale[3] + bias[3];
+};
+
+/**
+ * @param {Array<number>} pixel
+ * @param {Array<number>} scale
+ * @param {Array<number>} bias
+ */
+glsTextureTestUtil.deapplyScaleAndBias = function(pixel, scale, bias) {
+ pixel[0] = (pixel[0] - bias[0]) / scale[0];
+ pixel[1] = (pixel[1] - bias[1]) / scale[1];
+ pixel[2] = (pixel[2] - bias[2]) / scale[2];
+ pixel[3] = (pixel[3] - bias[3]) / scale[3];
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture2DView} src
+ * @param {Array<number>} sq
+ * @param {Array<number>} tq
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTextureProjected2D = function(dst, src, sq, tq, params) {
+ /** @type {number} */ var lodBias = params.flags.use_bias ? params.bias : 0.0;
+ /** @type {number} */ var dstW = dst.getWidth();
+ /** @type {number} */ var dstH = dst.getHeight();
+
+ /** @type {Array<number>} */ var uq = deMath.scale(sq, src.getWidth());
+ /** @type {Array<number>} */ var vq = deMath.scale(tq, src.getHeight());
+
+ /** @type {Array<Array<number>>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triU = [deMath.swizzle(uq, [0, 1, 2]), deMath.swizzle(uq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triV = [deMath.swizzle(vq, [0, 1, 2]), deMath.swizzle(vq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triW = [deMath.swizzle(params.w, [0, 1, 2]), deMath.swizzle(params.w, [3, 2, 1])];
+
+ for (var py = 0; py < dst.getHeight(); py++) {
+ for (var px = 0; px < dst.getWidth(); px++) {
+ /** @type {number} */ var wx = px + 0.5;
+ /** @type {number} */ var wy = py + 0.5;
+ /** @type {number} */ var nx = wx / dstW;
+ /** @type {number} */ var ny = wy / dstH;
+
+ /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0;
+ /** @type {number} */ var triWx = triNdx ? dstW - wx : wx;
+ /** @type {number} */ var triWy = triNdx ? dstH - wy : wy;
+ /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx;
+ /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny;
+
+ /** @type {number} */ var s = glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
+ /** @type {number} */ var t = glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy);
+ /** @type {number} */ var lod = glsTextureTestUtil.computeProjectedTriLod2D(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, dst.getWidth(), dst.getHeight()) + lodBias;
+
+ var pixel = glsTextureTestUtil.execSample(src, params, [s, t], lod);
+ glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
+ dst.setPixel(pixel, px, py);
+ }
+ }
+};
+
+/**
+ * @param {glsTextureTestUtil.lodMode} mode
+ * @param {Array<number>} u
+ * @param {Array<number>} v
+ * @param {Array<number>} projection
+ * @param {number} wx
+ * @param {number} wy
+ * @param {number} width
+ * @param {number} height
+ * @return {number}
+ */
+glsTextureTestUtil.computeProjectedTriLod2D = function(mode, u, v, projection, wx, wy, width, height) {
+ // Exact derivatives.
+ /** @type {number} */ var dudx = glsTextureTestUtil.triDerivateX(u, projection, wx, width, wy / height);
+ /** @type {number} */ var dvdx = glsTextureTestUtil.triDerivateX(v, projection, wx, width, wy / height);
+ /** @type {number} */ var dudy = glsTextureTestUtil.triDerivateY(u, projection, wy, height, wx / width);
+ /** @type {number} */ var dvdy = glsTextureTestUtil.triDerivateY(v, projection, wy, height, wx / width);
+
+ return glsTextureTestUtil.computeLodFromDerivates2D(mode, dudx, dvdx, dudy, dvdy);
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture2DView} src
+ * @param {Array<number>} sq
+ * @param {Array<number>} tq
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTextureNonProjected2D = function(dst, src, sq, tq, params) {
+ var lodBias = params.flags.use_bias ? params.bias : 0;
+
+ var dstSize = [dst.getWidth(), dst.getHeight()];
+ var srcSize = [src.getWidth(), src.getHeight()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triLod = [deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias), params.minLod, params.maxLod),
+ deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias), params.minLod, params.maxLod)];
+
+
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ var yf = (y + 0.5) / dst.getHeight();
+ var xf = (x + 0.5) / dst.getWidth();
+
+ var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule.
+ var triX = triNdx ? 1 - xf : xf;
+ var triY = triNdx ? 1 - yf : yf;
+
+ var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY);
+ var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY);
+ var lod = triLod[triNdx];
+
+ var pixel = glsTextureTestUtil.execSample(src, params, [s, t], lod);
+ glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
+ dst.setPixel(pixel, x, y);
+ }
+ }
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture2DArrayView} src
+ * @param {Array<number>} sq
+ * @param {Array<number>} tq
+ * @param {Array<number>} rq
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTextureNonProjected2DArray = function(dst, src, sq, tq, rq, params) {
+ var lodBias = (params.flags.use_bias) ? params.bias : 0;
+
+ var dstSize = [dst.getWidth(), dst.getHeight()];
+ var srcSize = [src.getWidth(), src.getHeight()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triLod = [glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias,
+ glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias];
+
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ var yf = (y + 0.5) / dst.getHeight();
+ var xf = (x + 0.5) / dst.getWidth();
+
+ var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule.
+ var triX = triNdx ? 1 - xf : xf;
+ var triY = triNdx ? 1 - yf : yf;
+
+ var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY);
+ var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY);
+ var r = glsTextureTestUtil.triangleInterpolate(triR[triNdx], triX, triY);
+ var lod = triLod[triNdx];
+
+ var pixel = glsTextureTestUtil.execSample(src, params, [s, t, r], lod);
+ glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
+ dst.setPixel(pixel, x, y);
+ }
+ }
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture2DView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTexture2D = function(dst, src, texCoord, params) {
+ var view = src.getSubView(params.baseLevel, params.maxLevel);
+ var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]];
+
+ if (params.flags.projected)
+ glsTextureTestUtil.sampleTextureProjected2D(dst, view, sq, tq, params);
+ else
+ glsTextureTestUtil.sampleTextureNonProjected2D(dst, view, sq, tq, params);
+};
+
+/**
+ * @param {glsTextureTestUtil.lodMode} mode
+ * @param {number} dudx
+ * @param {number} dvdx
+ * @param {number} dudy
+ * @param {number} dvdy
+ * @return {number}
+ */
+glsTextureTestUtil.computeLodFromDerivates2D = function(mode, dudx, dvdx, dudy, dvdy) {
+ var p = 0;
+ switch (mode) {
+ case glsTextureTestUtil.lodMode.EXACT:
+ p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx), Math.sqrt(dudy * dudy + dvdy * dvdy));
+ break;
+
+ case glsTextureTestUtil.lodMode.MIN_BOUND:
+ case glsTextureTestUtil.lodMode.MAX_BOUND: {
+ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
+ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
+
+ p = (mode == glsTextureTestUtil.lodMode.MIN_BOUND) ? Math.max(mu, mv) : mu + mv;
+ break;
+ }
+
+ default:
+ throw new Error('Unrecognized mode:' + mode);
+ }
+
+ // Native dEQP uses 32-bit numbers. So here 64-bit floating numbers should be transformed into 32-bit ones to ensure the correctness of the result.
+ return deMath.toFloat32(Math.log(p)) * deMath.INV_LOG_2_FLOAT32;
+};
+
+/**
+ * @param {glsTextureTestUtil.lodMode} lodModeParm
+ * @param {Array<number>} coord
+ * @param {Array<number>} coordDx
+ * @param {Array<number>} coordDy
+ * @param {number} faceSize
+ * @return {number}
+ */
+glsTextureTestUtil.computeCubeLodFromDerivates = function(lodModeParm, coord, coordDx, coordDy, faceSize) {
+ var face = tcuTexture.selectCubeFace(coord);
+ var maNdx = 0;
+ var sNdx = 0;
+ var tNdx = 0;
+
+ // \note Derivate signs don't matter when computing lod
+ switch (face) {
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X:
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y:
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
+ case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z:
+ case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
+ default:
+ throw new Error('Unrecognized face ' + face);
+ } {
+ var sc = coord[sNdx];
+ var tc = coord[tNdx];
+ var ma = Math.abs(coord[maNdx]);
+ var scdx = coordDx[sNdx];
+ var tcdx = coordDx[tNdx];
+ var madx = Math.abs(coordDx[maNdx]);
+ var scdy = coordDy[sNdx];
+ var tcdy = coordDy[tNdx];
+ var mady = Math.abs(coordDy[maNdx]);
+ var dudx = faceSize * 0.5 * (scdx * ma - sc * madx) / (ma * ma);
+ var dvdx = faceSize * 0.5 * (tcdx * ma - tc * madx) / (ma * ma);
+ var dudy = faceSize * 0.5 * (scdy * ma - sc * mady) / (ma * ma);
+ var dvdy = faceSize * 0.5 * (tcdy * ma - tc * mady) / (ma * ma);
+ return glsTextureTestUtil.computeLodFromDerivates2D(lodModeParm, dudx, dvdx, dudy, dvdy);
+ }
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.TextureCubeView} src
+ * @param {Array<number>} sq
+ * @param {Array<number>} tq
+ * @param {Array<number>} rq
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTextureCube_str = function(dst, src, sq, tq, rq, params) {
+ var dstSize = [dst.getWidth(), dst.getHeight()];
+ var dstW = dstSize[0];
+ var dstH = dstSize[1];
+ var srcSize = src.getSize();
+
+ // Coordinates per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triW = [deMath.swizzle(params.w, [0, 1, 2]), deMath.swizzle(params.w, [3, 2, 1])];
+
+ var lodBias = (params.flags.use_bias ? params.bias : 0);
+
+ for (var py = 0; py < dst.getHeight(); py++) {
+ for (var px = 0; px < dst.getWidth(); px++) {
+ var wx = px + 0.5;
+ var wy = py + 0.5;
+ var nx = wx / dstW;
+ var ny = wy / dstH;
+ var triNdx = nx + ny >= 1 ? 1 : 0;
+ var triNx = triNdx ? 1 - nx : nx;
+ var triNy = triNdx ? 1 - ny : ny;
+
+ var coord = [glsTextureTestUtil.triangleInterpolate(triS[triNdx], triNx, triNy),
+ glsTextureTestUtil.triangleInterpolate(triT[triNdx], triNx, triNy),
+ glsTextureTestUtil.triangleInterpolate(triR[triNdx], triNx, triNy)];
+ var coordDx = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)];
+ var coordDy = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)];
+
+ var lod = deMath.clamp((glsTextureTestUtil.computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias), params.minLod, params.maxLod);
+
+ var pixel = glsTextureTestUtil.execSample(src, params, coord, lod);
+ glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
+ dst.setPixel(pixel, px, py);
+ }
+ }
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.TextureCubeView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTextureCube = function(dst, src, texCoord, params) {
+ /*const tcu::TextureCubeView*/ var view = src.getSubView(params.baseLevel, params.maxLevel);
+ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ glsTextureTestUtil.sampleTextureCube_str(dst, view, sq, tq, rq, params);
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture2DArrayView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTexture2DArray = function(dst, src, texCoord, params) {
+ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ DE_ASSERT(!(params.flags.projected)); // \todo [2012-02-17 pyry] Support projected lookups.
+ glsTextureTestUtil.sampleTextureNonProjected2DArray(dst, src, sq, tq, rq, params);
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture3DView} src
+ * @param {Array<number>} sq
+ * @param {Array<number>} tq
+ * @param {Array<number>} rq
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTextureNonProjected3D = function(dst, src, sq, tq, rq, params) {
+ var lodBias = params.flags.use_bias ? params.bias : 0;
+
+ var dstSize = [dst.getWidth(), dst.getHeight()];
+ var srcSize = [src.getWidth(), src.getHeight(), src.getDepth()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triLod = [deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias), params.minLod, params.maxLod),
+ deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias), params.minLod, params.maxLod)];
+
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ var yf = (y + 0.5) / dst.getHeight();
+ var xf = (x + 0.5) / dst.getWidth();
+
+ var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule.
+ var triX = triNdx ? 1 - xf : xf;
+ var triY = triNdx ? 1 - yf : yf;
+
+ var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY);
+ var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY);
+ var r = glsTextureTestUtil.triangleInterpolate(triR[triNdx], triX, triY);
+ var lod = triLod[triNdx];
+
+ var pixel = src.sample(params.sampler, [s, t, r], lod);
+ glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
+ dst.setPixel(pixel, x, y);
+ }
+ }
+};
+
+/**
+ * @param {glsTextureTestUtil.SurfaceAccess} dst
+ * @param {tcuTexture.Texture3DView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} params
+ */
+glsTextureTestUtil.sampleTexture3D = function(dst, src, texCoord, params) {
+ /*const tcu::TextureCubeView*/ var view = src.getSubView(params.baseLevel, params.maxLevel);
+ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ glsTextureTestUtil.sampleTextureNonProjected3D(dst, view, sq, tq, rq, params);
+};
+
+/**
+ * @param {tcuSurface.Surface} reference
+ * @param {tcuSurface.Surface} rendered
+ * @param {Array<number>} threshold
+ * @param {Array< Array<number> >} skipPixels
+ *
+ * @return {boolean}
+ */
+glsTextureTestUtil.compareImages = function(reference, rendered, threshold, skipPixels) {
+ return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, rendered, threshold, undefined /*tcu::COMPARE_LOG_RESULT*/, skipPixels);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.Texture2DView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ * @return {boolean}
+ */
+glsTextureTestUtil.verifyTexture2DResult = function(result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat) {
+ DE_ASSERT(deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask));
+ /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ /** @type {number} */ var numFailedPixels;
+
+ /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
+
+ glsTextureTestUtil.sampleTexture2D(surface, src, texCoord, sampleParams);
+ numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff2D(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec/*, testCtx.getWatchDog()*/);
+
+ if (numFailedPixels > 0)
+ tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
+
+ return numFailedPixels == 0;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.Texture2DView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {Array<number>} nonShadowThreshold
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureCompareDiff2D = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) {
+ DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
+ DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
+
+ var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]];
+
+ var dstSize = [result.getWidth(), result.getHeight()];
+ var dstW = dstSize[0];
+ var dstH = dstSize[1];
+ var srcSize = [src.getWidth(), src.getHeight()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
+
+ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0];
+ var numFailed = 0;
+
+ var lodOffsets = [
+ [-1, 0],
+ [1, 0],
+ [0, -1],
+ [0, 1]
+ ];
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ errorMask.clear(green);
+
+ /** @type {Array<number>} */ var red = [];
+ for (var py = 0; py < result.getHeight(); py++) {
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+
+ if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(refPix, [1, 2, 3]), deMath.swizzle(resPix, [1, 2, 3])), nonShadowThreshold))) {
+ red = [255, 0, 0, 255];
+ errorMask.setPixel(red, px, py);
+ numFailed += 1;
+ continue;
+ }
+
+ if (resPix[0] != refPix[0]) {
+ var wx = px + 0.5;
+ var wy = py + 0.5;
+ var nx = wx / dstW;
+ var ny = wy / dstH;
+
+ var triNdx = nx + ny >= 1.0 ? 1 : 0;
+ var triWx = triNdx ? dstW - wx : wx;
+ var triWy = triNdx ? dstH - wy : wy;
+ var triNx = triNdx ? 1.0 - nx : nx;
+ var triNy = triNdx ? 1.0 - ny : ny;
+
+ var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)];
+ var coordDx = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
+ var coordDy = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
+
+ var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
+ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ var nxo = wxo / dstW;
+ var nyo = wyo / dstH;
+
+ var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)];
+ var coordDxo = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize);
+ var coordDyo = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize);
+ var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
+ var isOk = tcuTexCompareVerifier.isTexCompareResultValid2D(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]);
+
+ if (!isOk) {
+ red = [255, 0, 0, 255];
+ errorMask.setPixel(red, px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.Texture3DView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ * @return {boolean}
+ */
+glsTextureTestUtil.verifyTexture3DResult = function(
+ result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat
+) {
+ /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ var numFailedPixels = 0;
+
+ assertMsgOptions(
+ deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask),
+ 'Compare color masks do not match', false, true
+ );
+
+ /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
+ glsTextureTestUtil.sampleTexture3D(surface, src, texCoord, sampleParams);
+ numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff3D(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec);
+
+ if (numFailedPixels > 0)
+ tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
+
+ return numFailedPixels == 0;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.Texture3DView} baseView
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureLookupDiff3D = function(
+ result, reference, errorMask, baseView, texCoord,
+ sampleParams, lookupPrec, lodPrec
+) {
+ assertMsgOptions(
+ result.getWidth() == reference.getWidth() &&
+ result.getHeight() == reference.getHeight(),
+ 'Result and reference images are not the same size', false, true
+ );
+ assertMsgOptions(
+ result.getWidth() == errorMask.getWidth() &&
+ result.getHeight() == errorMask.getHeight(),
+ 'Result and error mask images are not the same size', false, true
+ );
+
+ /** @type {tcuTexture.Texture3DView} */
+ var src = baseView.getSubView(
+ sampleParams.baseLevel, sampleParams.maxLevel
+ );
+
+ var sq =
+ [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq =
+ [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq =
+ [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ var dstSize = [result.getWidth(), result.getHeight()];
+ var dstW = dstSize[0];
+ var dstH = dstSize[1];
+ var srcSize = [src.getWidth(), src.getHeight(), src.getDepth()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triW = [
+ deMath.swizzle(sampleParams.w, [0, 1, 2]),
+ deMath.swizzle(sampleParams.w, [3, 2, 1])
+ ];
+
+ var lodBias = sampleParams.flags.useBias ? sampleParams.bias : 0.0;
+
+ var posEps = 1.0 / ((1 << MIN_SUBPIXEL_BITS) + 1);
+
+ var numFailed = 0;
+
+ var lodOffsets = [
+ [-1, 0],
+ [+1, 0],
+ [0, -1],
+ [0, +1]
+ ];
+
+ var green = [0, 255, 0, 255];
+ errorMask.clear(new tcuRGBA.RGBA(green).toVec());
+
+ for (var py = 0; py < result.getHeight(); py++) {
+ // Ugly hack, validation can take way too long at the moment.
+ /*TODO: if (watchDog)
+ qpWatchDog_touch(watchDog);*/
+
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
+
+ // Try comparison to ideal reference first,
+ // and if that fails use slower verificator.
+ if (!deMath.boolAll(deMath.lessThanEqual(
+ deMath.absDiff(resPix, refPix),
+ lookupPrec.colorThreshold))
+ ) {
+ /** @type {number} */ var wx = px + 0.5;
+ /** @type {number} */ var wy = py + 0.5;
+ /** @type {number} */ var nx = wx / dstW;
+ /** @type {number} */ var ny = wy / dstH;
+
+ /** @type {boolean} */ var tri0 = nx + ny - posEps <= 1.0;
+ /** @type {boolean} */ var tri1 = nx + ny + posEps >= 1.0;
+
+ var isOk = false;
+
+ assertMsgOptions(
+ tri0 || tri1,
+ 'Pixel should belong at least to one triangle',
+ false, true
+ );
+
+ // Pixel can belong to either of the triangles
+ // if it lies close enough to the edge.
+ for (var triNdx = (tri0 ? 0 : 1);
+ triNdx <= (tri1 ? 1 : 0);
+ triNdx++) {
+ var triWx = triNdx ? dstW - wx : wx;
+ var triWy = triNdx ? dstH - wy : wy;
+ var triNx = triNdx ? 1.0 - nx : nx;
+ var triNy = triNdx ? 1.0 - ny : ny;
+
+ var coord = [
+ glsTextureTestUtil.projectedTriInterpolate(
+ triS[triNdx], triW[triNdx], triNx, triNy
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triT[triNdx], triW[triNdx], triNx, triNy
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triR[triNdx], triW[triNdx], triNx, triNy
+ )
+ ];
+ var coordDx = deMath.multiply([
+ glsTextureTestUtil.triDerivateX(
+ triS[triNdx], triW[triNdx], wx, dstW, triNy
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triT[triNdx], triW[triNdx], wx, dstW, triNy
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triR[triNdx], triW[triNdx], wx, dstW, triNy
+ )
+ ], srcSize);
+ var coordDy = deMath.multiply([
+ glsTextureTestUtil.triDerivateY(
+ triS[triNdx], triW[triNdx], wy, dstH, triNx
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triT[triNdx], triW[triNdx], wy, dstH, triNx
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triR[triNdx], triW[triNdx], wy, dstH, triNx
+ )
+ ], srcSize);
+
+ var lodBounds =
+ tcuTexLookupVerifier.computeLodBoundsFromDerivates(
+ coordDx[0], coordDx[1], coordDx[2],
+ coordDy[0], coordDy[1], coordDy[2], lodPrec
+ );
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0;
+ lodOffsNdx < lodOffsets.length;
+ lodOffsNdx++) {
+ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ var nxo = wxo / dstW;
+ var nyo = wyo / dstH;
+
+ var coordO = [
+ glsTextureTestUtil.projectedTriInterpolate(
+ triS[triNdx], triW[triNdx], nxo, nyo
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triT[triNdx], triW[triNdx], nxo, nyo
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triR[triNdx], triW[triNdx], nxo, nyo
+ )
+ ];
+ var coordDxo = deMath.multiply([
+ glsTextureTestUtil.triDerivateX(
+ triS[triNdx], triW[triNdx], wxo, dstW, nyo
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triT[triNdx], triW[triNdx], wxo, dstW, nyo
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triR[triNdx], triW[triNdx], wxo, dstW, nyo
+ )
+ ], srcSize);
+ var coordDyo = deMath.multiply([
+ glsTextureTestUtil.triDerivateY(
+ triS[triNdx], triW[triNdx], wyo, dstH, nxo
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triT[triNdx], triW[triNdx], wyo, dstH, nxo
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triR[triNdx], triW[triNdx], wyo, dstH, nxo
+ )
+ ], srcSize);
+ var lodO =
+ tcuTexLookupVerifier.computeLodBoundsFromDerivates(
+ coordDxo[0], coordDxo[1], coordDxo[2],
+ coordDyo[0], coordDyo[1], coordDyo[2], lodPrec
+ );
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ var clampedLod = tcuTexLookupVerifier.clampLodBounds(
+ deMath.addScalar(lodBounds, lodBias),
+ [sampleParams.minLod, sampleParams.maxLod],
+ lodPrec
+ );
+
+ if (
+ tcuTexLookupVerifier.isLookupResultValid(
+ src, sampleParams.sampler, lookupPrec,
+ coord, clampedLod, resPix
+ )
+ ) {
+ isOk = true;
+ break;
+ }
+ }
+
+ if (!isOk) {
+ var red = [255, 0, 0, 255];
+ errorMask.setPixel(new tcuRGBA.RGBA(red).toVec(), px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.TextureCubeView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ * @return {boolean}
+ */
+glsTextureTestUtil.verifyTextureCubeResult = function(
+ result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat
+) {
+ /** @type {tcuSurface.Surface} */
+ var reference = new tcuSurface.Surface(
+ result.getWidth(), result.getHeight()
+ );
+ /** @type {tcuSurface.Surface} */
+ var errorMask = new tcuSurface.Surface(
+ result.getWidth(), result.getHeight()
+ );
+ /** @type {number} */ var numFailedPixels = 0;
+
+ assertMsgOptions(
+ deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask),
+ 'Compare color masks do not match', false, true
+ );
+
+ /** @type {glsTextureTestUtil.SurfaceAccess} */
+ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
+
+ glsTextureTestUtil.sampleTextureCube(
+ surface, src, texCoord, sampleParams
+ );
+
+ numFailedPixels = glsTextureTestUtil.computeTextureLookupDiffCube(
+ result, reference.getAccess(), errorMask.getAccess(),
+ src, texCoord, sampleParams, lookupPrec, lodPrec
+ /*, testCtx.getWatchDog()*/
+ );
+
+ if (numFailedPixels > 0)
+ tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
+
+ return numFailedPixels == 0;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.TextureCubeView} baseView
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureLookupDiffCube = function(
+ result, reference, errorMask, baseView, texCoord,
+ sampleParams, lookupPrec, lodPrec
+) {
+ assertMsgOptions(
+ result.getWidth() == reference.getWidth() &&
+ result.getHeight() == reference.getHeight(),
+ 'Result and reference images are not the same size', false, true
+ );
+ assertMsgOptions(
+ result.getWidth() == errorMask.getWidth() &&
+ result.getHeight() == errorMask.getHeight(),
+ 'Result and error mask images are not the same size', false, true
+ );
+
+ /** @type {tcuTexture.TextureCubeView} */
+ var src = baseView.getSubView(
+ sampleParams.baseLevel, sampleParams.maxLevel
+ );
+
+ var sq =
+ [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq =
+ [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq =
+ [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ var dstSize = [result.getWidth(), result.getHeight()];
+ var dstW = dstSize[0];
+ var dstH = dstSize[1];
+ var srcSize = [src.getSize(), src.getSize()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triW = [
+ deMath.swizzle(sampleParams.w, [0, 1, 2]),
+ deMath.swizzle(sampleParams.w, [3, 2, 1])
+ ];
+
+ var lodBias = sampleParams.flags.useBias ? sampleParams.bias : 0.0;
+
+ var posEps = 1.0 / ((1 << MIN_SUBPIXEL_BITS) + 1);
+
+ var numFailed = 0;
+
+ var lodOffsets = [
+ [-1, 0],
+ [+1, 0],
+ [0, -1],
+ [0, +1],
+
+ // \note Not strictly allowed by spec,
+ // but implementations do this in practice.
+ [-1, -1],
+ [-1, 1],
+ [1, -1],
+ [1, 1]
+ ];
+
+ var green = [0, 255, 0, 255];
+ errorMask.clear(new tcuRGBA.RGBA(green).toVec());
+
+ for (var py = 0; py < result.getHeight(); py++) {
+ // Ugly hack, validation can take way too long at the moment.
+ /*TODO: if (watchDog)
+ qpWatchDog_touch(watchDog);*/
+
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
+
+ // Try comparison to ideal reference first,
+ // and if that fails use slower verificator.
+ if (!deMath.boolAll(deMath.lessThanEqual(
+ deMath.absDiff(resPix, refPix),
+ lookupPrec.colorThreshold))
+ ) {
+ /** @type {number} */ var wx = px + 0.5;
+ /** @type {number} */ var wy = py + 0.5;
+ /** @type {number} */ var nx = wx / dstW;
+ /** @type {number} */ var ny = wy / dstH;
+
+ /** @type {boolean} */ var tri0 = nx + ny - posEps <= 1.0;
+ /** @type {boolean} */ var tri1 = nx + ny + posEps >= 1.0;
+
+ var isOk = false;
+
+ assertMsgOptions(
+ tri0 || tri1,
+ 'Pixel should belong at least to one triangle',
+ false, true
+ );
+
+ // Pixel can belong to either of the triangles
+ // if it lies close enough to the edge.
+ for (var triNdx = (tri0 ? 0 : 1);
+ triNdx <= (tri1 ? 1 : 0);
+ triNdx++) {
+ var triWx = triNdx ? dstW - wx : wx;
+ var triWy = triNdx ? dstH - wy : wy;
+ var triNx = triNdx ? 1.0 - nx : nx;
+ var triNy = triNdx ? 1.0 - ny : ny;
+
+ var coord = [
+ glsTextureTestUtil.projectedTriInterpolate(
+ triS[triNdx], triW[triNdx], triNx, triNy
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triT[triNdx], triW[triNdx], triNx, triNy
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triR[triNdx], triW[triNdx], triNx, triNy
+ )
+ ];
+ var coordDx = [
+ glsTextureTestUtil.triDerivateX(
+ triS[triNdx], triW[triNdx], wx, dstW, triNy
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triT[triNdx], triW[triNdx], wx, dstW, triNy
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triR[triNdx], triW[triNdx], wx, dstW, triNy
+ )
+ ];
+ var coordDy = [
+ glsTextureTestUtil.triDerivateY(
+ triS[triNdx], triW[triNdx], wy, dstH, triNx
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triT[triNdx], triW[triNdx], wy, dstH, triNx
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triR[triNdx], triW[triNdx], wy, dstH, triNx
+ )
+ ];
+
+ var lodBounds =
+ tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(
+ coord, coordDx, coordDy, src.getSize(), lodPrec
+ );
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0;
+ lodOffsNdx < lodOffsets.length;
+ lodOffsNdx++) {
+ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ var nxo = wxo / dstW;
+ var nyo = wyo / dstH;
+
+ var coordO = [
+ glsTextureTestUtil.projectedTriInterpolate(
+ triS[triNdx], triW[triNdx], nxo, nyo
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triT[triNdx], triW[triNdx], nxo, nyo
+ ),
+ glsTextureTestUtil.projectedTriInterpolate(
+ triR[triNdx], triW[triNdx], nxo, nyo
+ )
+ ];
+ var coordDxo = [
+ glsTextureTestUtil.triDerivateX(
+ triS[triNdx], triW[triNdx], wxo, dstW, nyo
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triT[triNdx], triW[triNdx], wxo, dstW, nyo
+ ),
+ glsTextureTestUtil.triDerivateX(
+ triR[triNdx], triW[triNdx], wxo, dstW, nyo
+ )
+ ];
+ var coordDyo = [
+ glsTextureTestUtil.triDerivateY(
+ triS[triNdx], triW[triNdx], wyo, dstH, nxo
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triT[triNdx], triW[triNdx], wyo, dstH, nxo
+ ),
+ glsTextureTestUtil.triDerivateY(
+ triR[triNdx], triW[triNdx], wyo, dstH, nxo
+ )
+ ];
+ var lodO =
+ tcuTexLookupVerifier.
+ computeCubeLodBoundsFromDerivates(
+ coordO, coordDxo, coordDyo,
+ src.getSize(), lodPrec
+ );
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ var clampedLod = tcuTexLookupVerifier.clampLodBounds(
+ deMath.addScalar(lodBounds, lodBias),
+ [sampleParams.minLod, sampleParams.maxLod],
+ lodPrec
+ );
+
+ if (tcuTexLookupVerifier.
+ isLookupResultValid_TextureCubeView(
+ src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix
+ )
+ ) {
+ isOk = true;
+ break;
+ }
+ }
+
+ if (!isOk) {
+ var red = [255, 0, 0, 255];
+ errorMask.setPixel(new tcuRGBA.RGBA(red).toVec(), px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.Texture2DArrayView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {tcuPixelFormat.PixelFormat} pixelFormat
+ * @return {boolean}
+ */
+glsTextureTestUtil.verifyTexture2DArrayResult = function(result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat) {
+ DE_ASSERT(deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask));
+ /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
+ /** @type {number} */ var numFailedPixels;
+
+ /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
+
+ glsTextureTestUtil.sampleTexture2DArray(surface, src, texCoord, sampleParams);
+ numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec/*, testCtx.getWatchDog()*/);
+
+ if (numFailedPixels > 0)
+ tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
+
+ return numFailedPixels == 0;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.Texture2DArrayView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {Array<number>} nonShadowThreshold
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureCompareDiff2DArray = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) {
+ DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
+ DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
+
+ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ var dstSize = [result.getWidth(), result.getHeight()];
+ var dstW = dstSize[0];
+ var dstH = dstSize[1];
+ var srcSize = [src.getWidth(), src.getHeight()];
+
+ // Coordinates and lod per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
+
+ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0];
+ var numFailed = 0;
+
+ var lodOffsets = [
+ [-1, 0],
+ [1, 0],
+ [0, -1],
+ [0, 1]
+ ];
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ errorMask.clear(green);
+
+ /** @type {Array<number>} */ var red = [];
+ for (var py = 0; py < result.getHeight(); py++) {
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+
+ if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(refPix, [1, 2, 3]), deMath.swizzle(resPix, [1, 2, 3])), nonShadowThreshold))) {
+ red = [255, 0, 0, 255];
+ errorMask.setPixel(red, px, py);
+ numFailed += 1;
+ continue;
+ }
+
+ if (resPix[0] != refPix[0]) {
+ var wx = px + 0.5;
+ var wy = py + 0.5;
+ var nx = wx / dstW;
+ var ny = wy / dstH;
+
+ var triNdx = nx + ny >= 1.0 ? 1 : 0;
+ var triWx = triNdx ? dstW - wx : wx;
+ var triWy = triNdx ? dstH - wy : wy;
+ var triNx = triNdx ? 1.0 - nx : nx;
+ var triNy = triNdx ? 1.0 - ny : ny;
+
+ var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)];
+ var coordDx = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
+ var coordDy = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
+
+ var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
+ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ var nxo = wxo / dstW;
+ var nyo = wyo / dstH;
+
+ var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)];
+ var coordDxo = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize);
+ var coordDyo = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize);
+ var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
+ var isOk = tcuTexCompareVerifier.isTexCompareResultValid2DArray(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]);
+
+ if (!isOk) {
+ red = [255, 0, 0, 255];
+ errorMask.setPixel(red, px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.TextureCubeView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {Array<number>} nonShadowThreshold
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureCompareDiffCube = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) {
+ DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
+ DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
+
+ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ var dstSize = [result.getWidth(), result.getHeight()];
+ var dstW = dstSize[0];
+ var dstH = dstSize[1];
+ var srcSize = src.getSize();
+
+ // Coordinates per triangle.
+ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
+
+ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0];
+ var numFailed = 0;
+
+ var lodOffsets = [
+ [-1, 0],
+ [1, 0],
+ [0, -1],
+ [0, 1]
+ ];
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ errorMask.clear(new tcuRGBA.RGBA(green).toVec());
+
+ /** @type {Array<number>} */ var red = [];
+ for (var py = 0; py < result.getHeight(); py++) {
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+
+ if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(resPix, [1, 2, 3]), deMath.swizzle(refPix, [1, 2, 3])), nonShadowThreshold))) {
+ red = [255, 0, 0, 255];
+ errorMask.setPixel(red, px, py);
+ numFailed += 1;
+ continue;
+ }
+
+ if (resPix[0] != refPix[0]) {
+ var wx = px + 0.5;
+ var wy = py + 0.5;
+ var nx = wx / dstW;
+ var ny = wy / dstH;
+
+ var triNdx = nx + ny >= 1.0 ? 1 : 0;
+ var triWx = triNdx ? dstW - wx : wx;
+ var triWy = triNdx ? dstH - wy : wy;
+ var triNx = triNdx ? 1.0 - nx : nx;
+ var triNy = triNdx ? 1.0 - ny : ny;
+
+ var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)];
+ var coordDx = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)];
+ var coordDy = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)];
+
+ var lodBounds = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
+ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ var nxo = wxo / dstW;
+ var nyo = wyo / dstH;
+
+ var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)];
+ var coordDxo = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
+ glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)];
+ var coordDyo = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
+ glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)];
+ var lodO = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
+ var isOk = tcuTexCompareVerifier.isTexCompareResultValidCube(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]);
+
+ if (!isOk) {
+ red = [255, 0, 0, 255];
+ errorMask.setPixel(red, px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+/**
+ * @param {Array<number>} s
+ * @param {Array<number>} w
+ * @param {number} nx
+ * @param {number} ny
+ * @return {number}
+ */
+glsTextureTestUtil.projectedTriInterpolate = function(s, w, nx, ny) {
+ return (s[0] * (1.0 - nx - ny) / w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) / ((1.0 - nx - ny) / w[0] + ny / w[1] + nx / w[2]);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.Texture2DView} baseView
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {*=} watchDog - TODO: ??
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureLookupDiff2D = function(result, reference, errorMask, baseView, texCoord, sampleParams, lookupPrec, lodPrec, watchDog) {
+ DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
+ DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
+
+ /** @type {tcuTexture.Texture2DView} */ var src = baseView.getSubView(sampleParams.baseLevel, sampleParams.maxLevel);
+
+ /** @type {Array<number>} */ var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]];
+ /** @type {Array<number>} */ var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]];
+
+ /** @type {Array<number>} */ var dstSize = [result.getWidth(), result.getHeight()];
+ /** @type {number} */ var dstW = dstSize[0];
+ /** @type {number} */ var dstH = dstSize[1];
+ /** @type {Array<number>} */ var srcSize = [src.getWidth(), src.getHeight()];
+
+ // Coordinates and lod per triangle.
+ /** @type {Array<Array<number>>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
+
+ /** @type {Array<number>} */ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0.0, 0.0];
+
+ /** @type {number} */ var numFailed = 0;
+
+ /** @type {Array<Array<number>>} */ var lodOffsets = [
+ [-1, 0],
+ [1, 0],
+ [0, -1],
+ [0, 1]
+ ];
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ errorMask.clear(new tcuRGBA.RGBA(green).toVec());
+
+ for (var py = 0; py < result.getHeight(); py++) {
+ // Ugly hack, validation can take way too long at the moment.
+
+ // TODO:are we implementing qpWatchDog? skipping in the meantime
+ // if (watchDog)
+ // qpWatchDog_touch(watchDog);
+
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
+
+ // Try comparison to ideal reference first, and if that fails use slower verificator.
+ if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold))) {
+ /** @type {number} */ var wx = px + 0.5;
+ /** @type {number} */ var wy = py + 0.5;
+ /** @type {number} */ var nx = wx / dstW;
+ /** @type {number} */ var ny = wy / dstH;
+
+ /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0;
+ /** @type {number} */ var triWx = triNdx ? dstW - wx : wx;
+ /** @type {number} */ var triWy = triNdx ? dstH - wy : wy;
+ /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx;
+ /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny;
+
+ /** @type {Array<number>} */ var coord = [
+ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)
+ ];
+ /** @type {Array<number>} */ var coordDx = deMath.multiply([
+ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
+ /** @type {Array<number>} */ var coordDy = deMath.multiply([
+ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
+
+ /** @type {Array<number>} */
+ var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
+ /** @type {number} */ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ /** @type {number} */ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ /** @type {number} */ var nxo = wxo / dstW;
+ /** @type {number} */ var nyo = wyo / dstH;
+
+ /** @type {Array<number>} */ var coordO = [
+ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)];
+ /** @type {Array<number>} */ var coordDxo = deMath.multiply([
+ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize);
+ /** @type {Array<number>} */ var coordDyo = deMath.multiply([
+ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize);
+ /** @type {Array<number>} */
+ var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ /** @type {Array<number>} */ var clampedLod = tcuTexLookupVerifier.clampLodBounds(
+ deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
+ /** @type {boolean} */
+ var isOk = tcuTexLookupVerifier.isLookupResultValid_Texture2DView(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
+
+ if (!isOk) {
+ /** @type {tcuRGBA.RGBA} */ var red = tcuRGBA.newRGBAComponents(255, 0, 0, 255);
+ errorMask.setPixel(red.toVec(), px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+// Verifies texture lookup results and returns number of failed pixels.
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.Texture2DArrayView} src
+ * @param {Array<number>} texCoord
+ * @param {glsTextureTestUtil.ReferenceParams} sampleParams
+ * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
+ * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
+ * @param {*=} watchDog - TODO: ??
+ * @return {number}
+ */
+glsTextureTestUtil.computeTextureLookupDiff2DArray = function(result, reference, errorMask, src, texCoord, sampleParams, lookupPrec, lodPrec, watchDog) {
+ DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
+ DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
+
+ /** @type {Array<number>} */ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
+ /** @type {Array<number>} */ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
+ /** @type {Array<number>} */ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
+
+ /** @type {Array<number>} */ var dstSize = [result.getWidth(), result.getHeight()];
+ /** @type {number} */ var dstW = dstSize[0];
+ /** @type {number} */ var dstH = dstSize[1];
+ /** @type {Array<number>} */ var srcSize = [src.getWidth(), src.getHeight()];
+
+ // Coordinates and lod per triangle.
+ /** @type {Array<Array<number>>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
+ /** @type {Array<Array<number>>} */ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
+
+ /** @type {Array<number>} */ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0.0, 0.0];
+
+ /** @type {number} */ var numFailed = 0;
+
+ /** @type {Array<Array<number>>} */ var lodOffsets = [
+ [-1, 0],
+ [1, 0],
+ [0, -1],
+ [0, 1]
+ ];
+
+ /** @type {Array<number>} */ var green = [0, 255, 0, 255];
+ errorMask.clear(new tcuRGBA.RGBA(green).toVec());
+
+ for (var py = 0; py < result.getHeight(); py++) {
+ // Ugly hack, validation can take way too long at the moment.
+
+ // TODO:are we implementing qpWatchDog? skipping in the meantime
+ // if (watchDog)
+ // qpWatchDog_touch(watchDog);
+
+ for (var px = 0; px < result.getWidth(); px++) {
+ /** @type {Array<number>} */
+ var resPix = result.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
+ /** @type {Array<number>} */
+ var refPix = reference.getPixel(px, py);
+ glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
+
+
+ // Try comparison to ideal reference first, and if that fails use slower verificator.
+ if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold))) {
+ /** @type {number} */ var wx = px + 0.5;
+ /** @type {number} */ var wy = py + 0.5;
+ /** @type {number} */ var nx = wx / dstW;
+ /** @type {number} */ var ny = wy / dstH;
+
+ /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0;
+ /** @type {number} */ var triWx = triNdx ? dstW - wx : wx;
+ /** @type {number} */ var triWy = triNdx ? dstH - wy : wy;
+ /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx;
+ /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny;
+
+ /** @type {Array<number>} */ var coord = [
+ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
+ glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)
+ ];
+ /** @type {Array<number>} */ var coordDx = deMath.multiply([
+ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
+ /** @type {Array<number>} */ var coordDy = deMath.multiply([
+ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
+
+ /** @type {Array<number>} */
+ var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
+
+ // Compute lod bounds across lodOffsets range.
+ for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
+ /** @type {number} */ var wxo = triWx + lodOffsets[lodOffsNdx][0];
+ /** @type {number} */ var wyo = triWy + lodOffsets[lodOffsNdx][1];
+ /** @type {number} */ var nxo = wxo / dstW;
+ /** @type {number} */ var nyo = wyo / dstH;
+
+ /** @type {Array<number>} */ var coordO = [
+ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
+ glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)
+ ];
+ /** @type {Array<number>} */ var coordDxo = deMath.multiply([
+ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
+ glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize
+ );
+ /** @type {Array<number>} */ var coordDyo = deMath.multiply([
+ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
+ glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize
+ );
+ /** @type {Array<number>} */
+ var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
+
+ lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
+ lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
+ }
+
+ /** @type {Array<number>} */ var clampedLod = tcuTexLookupVerifier.clampLodBounds(
+ deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
+ /** @type {boolean} */
+ var isOk = tcuTexLookupVerifier.isLookupResultValid_Texture2DArrayView(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
+
+ if (!isOk) {
+ /** @type {tcuRGBA.RGBA} */ var red = tcuRGBA.newRGBAComponents(255, 0, 0, 255);
+ errorMask.setPixel(red.toVec(), px, py);
+ numFailed += 1;
+ }
+ }
+ }
+ }
+
+ return numFailed;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsUniformBlockCase.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsUniformBlockCase.js
new file mode 100644
index 0000000000..e9c45366ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsUniformBlockCase.js
@@ -0,0 +1,2451 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsUniformBlockCase');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.gluDrawUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+
+goog.scope(function() {
+
+var glsUniformBlockCase = modules.shared.glsUniformBlockCase;
+var tcuTestCase = framework.common.tcuTestCase;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluDrawUtil = framework.opengl.gluDrawUtil;
+var deUtil = framework.delibs.debase.deUtil;
+var deMath = framework.delibs.debase.deMath;
+var deRandom = framework.delibs.debase.deRandom;
+var deString = framework.delibs.debase.deString;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+var littleEndian = (function() {
+ var buffer = new ArrayBuffer(2);
+ new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
+ // Int16Array uses the platform's endianness.
+ return new Int16Array(buffer)[0] === 256;
+})();
+
+/**
+ * Class to implement some pointers functionality.
+ * @constructor
+ */
+glsUniformBlockCase.BlockPointers = function() {
+ /** @type {ArrayBuffer} */ this.data; //!< Data (vector<deUint8>).
+ /** @type {Array<number>} */ this.offsets = []; //!< Reference block pointers (map<int, void*>).
+ /** @type {Array<number>} */ this.sizes = [];
+};
+
+/**
+ * push - Adds an offset/size pair to the collection
+ * @param {number} offset Offset of the element to refer.
+ * @param {number} size Size of the referred element.
+ */
+glsUniformBlockCase.BlockPointers.prototype.push = function(offset, size) {
+ this.offsets.push(offset);
+ this.sizes.push(size);
+};
+
+/**
+ * find - Finds and maps the data at the given offset, and returns a Uint8Array
+ * @param {number} index of the element to find.
+ * @return {Uint8Array}
+ */
+glsUniformBlockCase.BlockPointers.prototype.find = function(index) {
+ return new Uint8Array(this.data, this.offsets[index], this.sizes[index]);
+};
+
+/**
+ * resize - Replaces resize of a vector in C++. Sets the size of the data buffer.
+ * NOTE: In this case however, if you resize, the data is lost.
+ * @param {number} newsize The new size of the data buffer.
+ */
+glsUniformBlockCase.BlockPointers.prototype.resize = function(newsize) {
+ this.data = new ArrayBuffer(newsize);
+};
+
+/**
+ * glsUniformBlockCase.isSupportedGLSLVersion
+ * @param {gluShaderUtil.GLSLVersion} version
+ * @return {boolean}
+ */
+glsUniformBlockCase.isSupportedGLSLVersion = function(version) {
+ return version >= gluShaderUtil.GLSLVersion.V300_ES;
+};
+
+/**
+ * @enum {number}
+ */
+glsUniformBlockCase.UniformFlags = {
+ PRECISION_LOW: (1 << 0),
+ PRECISION_MEDIUM: (1 << 1),
+ PRECISION_HIGH: (1 << 2),
+
+ LAYOUT_SHARED: (1 << 3),
+ LAYOUT_PACKED: (1 << 4),
+ LAYOUT_STD140: (1 << 5),
+ LAYOUT_ROW_MAJOR: (1 << 6),
+ LAYOUT_COLUMN_MAJOR: (1 << 7), //!< \note Lack of both flags means column-major matrix.
+
+ DECLARE_VERTEX: (1 << 8),
+ DECLARE_FRAGMENT: (1 << 9),
+
+ UNUSED_VERTEX: (1 << 10), //!< glsUniformBlockCase.Uniform or struct member is not read in vertex shader.
+ UNUSED_FRAGMENT: (1 << 11) //!< glsUniformBlockCase.Uniform or struct member is not read in fragment shader.
+};
+
+/** @const */ glsUniformBlockCase.UniformFlags.PRECISION_MASK = glsUniformBlockCase.UniformFlags.PRECISION_LOW | glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM | glsUniformBlockCase.UniformFlags.PRECISION_HIGH;
+/** @const */ glsUniformBlockCase.UniformFlags.LAYOUT_MASK = glsUniformBlockCase.UniformFlags.LAYOUT_SHARED | glsUniformBlockCase.UniformFlags.LAYOUT_PACKED | glsUniformBlockCase.UniformFlags.LAYOUT_STD140 | glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR | glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR;
+/** @const */ glsUniformBlockCase.UniformFlags.DECLARE_BOTH = glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT;
+/** @const */ glsUniformBlockCase.UniformFlags.UNUSED_BOTH = glsUniformBlockCase.UniformFlags.UNUSED_VERTEX | glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT;
+
+/**
+* glsUniformBlockCase.VarType types enum
+* @enum {number}
+*/
+glsUniformBlockCase.Type = {
+ TYPE_BASIC: 0,
+ TYPE_ARRAY: 1,
+ TYPE_STRUCT: 2
+};
+
+glsUniformBlockCase.Type.TYPE_LAST = Object.keys(glsUniformBlockCase.Type).length;
+
+/**
+* glsUniformBlockCase.TypeArray struct (nothing to do with JS's TypedArrays)
+* @param {glsUniformBlockCase.VarType} elementType
+* @param {number} arraySize
+* @constructor
+*/
+glsUniformBlockCase.TypeArray = function(elementType, arraySize) {
+ /** @type {glsUniformBlockCase.VarType} */ this.elementType = elementType;
+ /** @type {number} */ this.size = arraySize;
+};
+
+/**
+ * glsUniformBlockCase.VarType class
+ * @constructor
+ */
+glsUniformBlockCase.VarType = function() {
+ /** @type {glsUniformBlockCase.Type} */ this.m_type;
+ /** @type {number} */ this.m_flags = 0;
+
+ /*
+ * m_data used to be a 'Data' union in C++. Using a var is enough here.
+ * it will contain any necessary value.
+ */
+
+ /** @type {(gluShaderUtil.DataType|glsUniformBlockCase.TypeArray|glsUniformBlockCase.StructType)} */
+ this.m_data;
+};
+
+/**
+* Creates a basic type glsUniformBlockCase.VarType. Use this after the constructor call.
+* @param {gluShaderUtil.DataType} basicType
+* @param {number} flags
+* @return {glsUniformBlockCase.VarType} The currently modified object
+*/
+glsUniformBlockCase.VarType.prototype.VarTypeBasic = function(basicType, flags) {
+ this.m_type = glsUniformBlockCase.Type.TYPE_BASIC;
+ this.m_flags = flags;
+ this.m_data = basicType;
+
+ return this;
+};
+
+/**
+* Creates an array type glsUniformBlockCase.VarType. Use this after the constructor call.
+* @param {glsUniformBlockCase.VarType} elementType
+* @param {number} arraySize
+* @return {glsUniformBlockCase.VarType} The currently modified object
+*/
+glsUniformBlockCase.VarType.prototype.VarTypeArray = function(elementType, arraySize) {
+ this.m_type = glsUniformBlockCase.Type.TYPE_ARRAY;
+ this.m_flags = 0;
+ this.m_data = new glsUniformBlockCase.TypeArray(elementType, arraySize);
+
+ return this;
+};
+
+/**
+* Creates a struct type glsUniformBlockCase.VarType. Use this after the constructor call.
+* @param {glsUniformBlockCase.StructType} structPtr
+* @return {glsUniformBlockCase.VarType} The currently modified object
+*/
+glsUniformBlockCase.VarType.prototype.VarTypeStruct = function(structPtr) {
+ this.m_type = glsUniformBlockCase.Type.TYPE_STRUCT;
+ this.m_flags = 0;
+ this.m_data = structPtr;
+
+ return this;
+};
+
+/** isBasicType
+* @return {boolean} true if the glsUniformBlockCase.VarType represents a basic type.
+**/
+glsUniformBlockCase.VarType.prototype.isBasicType = function() {
+ return this.m_type == glsUniformBlockCase.Type.TYPE_BASIC;
+};
+
+/** isArrayType
+* @return {boolean} true if the glsUniformBlockCase.VarType represents an array.
+**/
+glsUniformBlockCase.VarType.prototype.isArrayType = function() {
+ return this.m_type == glsUniformBlockCase.Type.TYPE_ARRAY;
+};
+
+/** isStructType
+* @return {boolean} true if the glsUniformBlockCase.VarType represents a struct.
+**/
+glsUniformBlockCase.VarType.prototype.isStructType = function() {
+ return this.m_type == glsUniformBlockCase.Type.TYPE_STRUCT;
+};
+
+/** getFlags
+* @return {number} returns the flags of the glsUniformBlockCase.VarType.
+**/
+glsUniformBlockCase.VarType.prototype.getFlags = function() {
+ return this.m_flags;
+};
+
+/** getBasicType
+* @return {gluShaderUtil.DataType} returns the basic data type of the glsUniformBlockCase.VarType.
+**/
+glsUniformBlockCase.VarType.prototype.getBasicType = function() {
+ return /** @type {gluShaderUtil.DataType} */ (this.m_data);
+};
+
+/** getElementType
+* @return {glsUniformBlockCase.VarType} returns the glsUniformBlockCase.VarType of the element in case of an Array.
+**/
+glsUniformBlockCase.VarType.prototype.getElementType = function() {
+ return this.m_data.elementType;
+};
+
+/** getArraySize
+* (not to be confused with a javascript array)
+* @return {number} returns the size of the array in case it is an array.
+**/
+glsUniformBlockCase.VarType.prototype.getArraySize = function() {
+ return this.m_data.size;
+};
+
+/** getStruct
+* @return {glsUniformBlockCase.StructType} returns the structure when it is a glsUniformBlockCase.StructType.
+**/
+glsUniformBlockCase.VarType.prototype.getStruct = function() {
+ return /** @type {glsUniformBlockCase.StructType} */ (this.m_data);
+};
+
+/**
+ * Creates a basic type glsUniformBlockCase.VarType.
+ * @param {gluShaderUtil.DataType} basicType
+ * @param {number} flags
+ * @return {glsUniformBlockCase.VarType}
+ */
+glsUniformBlockCase.newVarTypeBasic = function(basicType, flags) {
+ return new glsUniformBlockCase.VarType().VarTypeBasic(basicType, flags);
+};
+
+/**
+* Creates an array type glsUniformBlockCase.VarType.
+* @param {glsUniformBlockCase.VarType} elementType
+* @param {number} arraySize
+* @return {glsUniformBlockCase.VarType}
+*/
+glsUniformBlockCase.newVarTypeArray = function(elementType, arraySize) {
+ return new glsUniformBlockCase.VarType().VarTypeArray(elementType, arraySize);
+};
+
+/**
+* Creates a struct type glsUniformBlockCase.VarType.
+* @param {glsUniformBlockCase.StructType} structPtr
+* @return {glsUniformBlockCase.VarType}
+*/
+glsUniformBlockCase.newVarTypeStruct = function(structPtr) {
+ return new glsUniformBlockCase.VarType().VarTypeStruct(structPtr);
+};
+
+/** glsUniformBlockCase.StructMember
+ * in the JSDoc annotations or if a number would do.
+ * @constructor
+**/
+glsUniformBlockCase.StructMember = function() {
+ /** @type {string} */ this.m_name;
+ /** @type {glsUniformBlockCase.VarType} */ this.m_type;
+ /** @type {number} */ this.m_flags = 0;
+};
+
+/**
+ * Creates a glsUniformBlockCase.StructMember. Use this after the constructor call.
+ * @param {string} name
+ * @param {glsUniformBlockCase.VarType} type
+ * @param {number} flags
+ * @return {glsUniformBlockCase.StructMember} The currently modified object
+ */
+glsUniformBlockCase.StructMember.prototype.Constructor = function(name, type, flags) {
+ this.m_type = type;
+ this.m_name = name;
+ this.m_flags = flags;
+
+ return this;
+};
+
+/** getName
+* @return {string} the name of the member
+**/
+glsUniformBlockCase.StructMember.prototype.getName = function() { return this.m_name; };
+
+/** getType
+* @return {glsUniformBlockCase.VarType} the type of the member
+**/
+glsUniformBlockCase.StructMember.prototype.getType = function() { return this.m_type; };
+
+/** getFlags
+* @return {number} the flags in the member
+**/
+glsUniformBlockCase.StructMember.prototype.getFlags = function() { return this.m_flags; };
+
+/**
+ * Creates a glsUniformBlockCase.StructMember with name, type and flags.
+ * @param {string} name
+ * @param {glsUniformBlockCase.VarType} type
+ * @return {glsUniformBlockCase.StructMember}
+ */
+ glsUniformBlockCase.newStructMember = function(name, type, flags) {
+ return new glsUniformBlockCase.StructMember().Constructor(name, type, flags);
+ };
+
+/**
+ * glsUniformBlockCase.StructType
+ * @constructor
+ */
+glsUniformBlockCase.StructType = function() {
+ /** @type {string}*/ this.m_typeName;
+ /** @type {Array<glsUniformBlockCase.StructMember>} */ this.m_members = [];
+};
+
+/**
+ * glsUniformBlockCase.StructType - Constructor with type name
+ * @param {string} typeName
+ * @return {glsUniformBlockCase.StructType} The currently modified object.
+ */
+glsUniformBlockCase.StructType.prototype.Constructor = function(typeName) {
+ /** @type {string}*/ this.m_typeName = typeName;
+ return this;
+};
+
+/** getTypeName
+* @return {string}
+**/
+glsUniformBlockCase.StructType.prototype.getTypeName = function() {
+ return this.m_typeName;
+};
+
+/*
+ * Instead of iterators, we'll add
+ * a getter for a specific element (getMember),
+ * and current members amount (getSize).
+ */
+
+/** getMember
+* @param {number} memberNdx The index of the member to retrieve.
+* @return {glsUniformBlockCase.StructMember}
+**/
+glsUniformBlockCase.StructType.prototype.getMember = function(memberNdx) {
+ if (memberNdx >= 0 && memberNdx < this.m_members.length)
+ return this.m_members[memberNdx];
+ else {
+ throw new Error("Invalid member index for glsUniformBlockCase.StructType's members");
+ }
+};
+
+/** getSize
+* @return {number} The size of the m_members array.
+**/
+glsUniformBlockCase.StructType.prototype.getSize = function() {
+ return this.m_members.length;
+};
+
+/** addMember
+* @param {string} member_name
+* @param {glsUniformBlockCase.VarType} member_type
+* @param {number=} member_flags
+**/
+glsUniformBlockCase.StructType.prototype.addMember = function(member_name, member_type, member_flags) {
+ var member = glsUniformBlockCase.newStructMember(member_name, member_type, member_flags);
+
+ this.m_members.push(member);
+};
+
+/**
+ * Creates a glsUniformBlockCase.StructType.
+ * @param {string} name
+ * @return {glsUniformBlockCase.StructType}
+ */
+glsUniformBlockCase.newStructType = function(name) {
+ return new glsUniformBlockCase.StructType().Constructor(name);
+};
+
+/** glsUniformBlockCase.Uniform
+ * @param {string} name
+ * @param {glsUniformBlockCase.VarType} type
+ * @param {number=} flags
+ * @constructor
+**/
+glsUniformBlockCase.Uniform = function(name, type, flags) {
+ /** @type {string} */ this.m_name = name;
+ /** @type {glsUniformBlockCase.VarType} */ this.m_type = type;
+ /** @type {number} */ this.m_flags = (typeof flags === 'undefined') ? 0 : flags;
+};
+
+/** getName
+ * @return {string}
+ */
+glsUniformBlockCase.Uniform.prototype.getName = function() {
+ return this.m_name;
+};
+
+/** getType
+ * @return {glsUniformBlockCase.VarType}
+ */
+glsUniformBlockCase.Uniform.prototype.getType = function() {
+ return this.m_type;
+};
+
+/** getFlags
+* @return {number}
+**/
+glsUniformBlockCase.Uniform.prototype.getFlags = function() {
+ return this.m_flags;
+};
+
+/** glsUniformBlockCase.UniformBlock
+ * @param {string} blockName
+ * @constructor
+**/
+glsUniformBlockCase.UniformBlock = function(blockName) {
+ /** @type {string} */ this.m_blockName = blockName;
+ /** @type {string} */ this.m_instanceName;
+ /** @type {Array<glsUniformBlockCase.Uniform>} */ this.m_uniforms = [];
+ /** @type {number} */ this.m_arraySize = 0; //!< Array size or 0 if not interface block array.
+ /** @type {number} */ this.m_flags = 0;
+};
+
+/** getBlockName
+* @return {string}
+**/
+glsUniformBlockCase.UniformBlock.prototype.getBlockName = function() {
+ return this.m_blockName;
+};
+
+/** getInstanceName
+* @return {string}
+**/
+glsUniformBlockCase.UniformBlock.prototype.getInstanceName = function() {
+ return this.m_instanceName;
+};
+
+/** isArray
+* @return {boolean}
+**/
+glsUniformBlockCase.UniformBlock.prototype.isArray = function() {
+ return this.m_arraySize > 0;
+};
+
+/** getArraySize
+* @return {number}
+**/
+glsUniformBlockCase.UniformBlock.prototype.getArraySize = function() {
+ return this.m_arraySize;
+};
+
+/** getFlags
+* @return {number}
+**/
+glsUniformBlockCase.UniformBlock.prototype.getFlags = function() {
+ return this.m_flags;
+};
+
+/** setInstanceName
+* @param {string} name
+**/
+glsUniformBlockCase.UniformBlock.prototype.setInstanceName = function(name) {
+ this.m_instanceName = name;
+};
+
+/** setFlags
+* @param {number} flags
+**/
+glsUniformBlockCase.UniformBlock.prototype.setFlags = function(flags) {
+ this.m_flags = flags;
+};
+
+/** setArraySize
+* @param {number} arraySize
+**/
+glsUniformBlockCase.UniformBlock.prototype.setArraySize = function(arraySize) {
+ this.m_arraySize = arraySize;
+};
+
+/** addUniform
+* @param {glsUniformBlockCase.Uniform} uniform
+**/
+glsUniformBlockCase.UniformBlock.prototype.addUniform = function(uniform) {
+ this.m_uniforms.push(uniform);
+};
+
+/*
+ * Using uniform getter (getUniform),
+ * and uniform array size getter (countUniforms)
+ * instead of iterators.
+*/
+
+/**
+ * getUniform
+ * @param {number} index
+ * @return {glsUniformBlockCase.Uniform}
+ */
+glsUniformBlockCase.UniformBlock.prototype.getUniform = function(index) {
+ if (index >= 0 && index < this.m_uniforms.length)
+ return this.m_uniforms[index];
+ else {
+ throw new Error("Invalid uniform index for glsUniformBlockCase.UniformBlock's uniforms");
+ }
+};
+
+/**
+ * countUniforms
+ * @return {number}
+ */
+glsUniformBlockCase.UniformBlock.prototype.countUniforms = function() {
+ return this.m_uniforms.length;
+};
+
+/**
+ * glsUniformBlockCase.ShaderInterface
+ * @constructor
+ */
+glsUniformBlockCase.ShaderInterface = function() {
+ /** @type {Array<glsUniformBlockCase.StructType>} */ this.m_structs = [];
+ /** @type {Array<glsUniformBlockCase.UniformBlock>} */ this.m_uniformBlocks = [];
+};
+
+/** allocStruct
+* @param {string} name
+* @return {glsUniformBlockCase.StructType}
+**/
+glsUniformBlockCase.ShaderInterface.prototype.allocStruct = function(name) {
+ //m_structs.reserve(m_structs.length + 1);
+ this.m_structs.push(glsUniformBlockCase.newStructType(name));
+ return this.m_structs[this.m_structs.length - 1];
+};
+
+/** findStruct
+* @param {string} name
+* @return {glsUniformBlockCase.StructType}
+**/
+glsUniformBlockCase.ShaderInterface.prototype.findStruct = function(name) {
+ for (var pos = 0; pos < this.m_structs.length; pos++) {
+ if (this.m_structs[pos].getTypeName() == name)
+ return this.m_structs[pos];
+ }
+ return null;
+};
+
+/** getNamedStructs
+* @param {Array<glsUniformBlockCase.StructType>} structs
+**/
+glsUniformBlockCase.ShaderInterface.prototype.getNamedStructs = function(structs) {
+ for (var pos = 0; pos < this.m_structs.length; pos++) {
+ if (this.m_structs[pos].getTypeName() != undefined)
+ structs.push(this.m_structs[pos]);
+ }
+};
+
+/** allocBlock
+* @param {string} name
+* @return {glsUniformBlockCase.UniformBlock}
+**/
+glsUniformBlockCase.ShaderInterface.prototype.allocBlock = function(name) {
+ this.m_uniformBlocks.push(new glsUniformBlockCase.UniformBlock(name));
+ return this.m_uniformBlocks[this.m_uniformBlocks.length - 1];
+};
+
+/** getNumUniformBlocks
+* @return {number}
+**/
+glsUniformBlockCase.ShaderInterface.prototype.getNumUniformBlocks = function() {
+ return this.m_uniformBlocks.length;
+};
+
+/** getUniformBlock
+* @param {number} ndx
+* @return {glsUniformBlockCase.UniformBlock}
+**/
+glsUniformBlockCase.ShaderInterface.prototype.getUniformBlock = function(ndx) {
+ return this.m_uniformBlocks[ndx];
+};
+
+/**
+ * @constructor
+ */
+glsUniformBlockCase.BlockLayoutEntry = function() {
+ return {
+ /** @type {number} */ size: 0,
+ /** @type {string} */ name: '',
+ /** @type {Array<number>} */ activeUniformIndices: []
+ };
+};
+
+/**
+ * @constructor
+ */
+glsUniformBlockCase.UniformLayoutEntry = function() {
+ return {
+ /** @type {string} */ name: '',
+ /** @type {gluShaderUtil.DataType} */ type: gluShaderUtil.DataType.INVALID,
+ /** @type {number} */ size: 0,
+ /** @type {number} */ blockNdx: -1,
+ /** @type {number} */ offset: -1,
+ /** @type {number} */ arrayStride: -1,
+ /** @type {number} */ matrixStride: -1,
+ /** @type {boolean} */ isRowMajor: false
+ };
+};
+
+/**
+ * @constructor
+ */
+glsUniformBlockCase.UniformLayout = function() {
+ /** @type {Array<glsUniformBlockCase.BlockLayoutEntry>}*/ this.blocks = [];
+ /** @type {Array<glsUniformBlockCase.UniformLayoutEntry>}*/ this.uniforms = [];
+};
+
+/** getUniformIndex, returns a uniform index number in the layout,
+ * given the uniform's name.
+ * @param {string} name
+ * @return {number} uniform's index
+ */
+glsUniformBlockCase.UniformLayout.prototype.getUniformIndex = function(name) {
+ for (var ndx = 0; ndx < this.uniforms.length; ndx++) {
+ if (this.uniforms[ndx].name == name)
+ return ndx;
+ }
+ return -1;
+};
+
+/** getBlockIndex, returns a block index number in the layout,
+ * given the block's name.
+ * @param {string} name the name of the block
+ * @return {number} block's index
+ */
+glsUniformBlockCase.UniformLayout.prototype.getBlockIndex = function(name) {
+ for (var ndx = 0; ndx < this.blocks.length; ndx++) {
+ if (this.blocks[ndx].name == name)
+ return ndx;
+ }
+ return -1;
+};
+
+/**
+ * @enum {number}
+ */
+glsUniformBlockCase.BufferMode = {
+ BUFFERMODE_SINGLE: 0, //!< Single buffer shared between uniform blocks.
+ BUFFERMODE_PER_BLOCK: 1 //!< Per-block buffers
+};
+
+glsUniformBlockCase.BufferMode.BUFFERMODE_LAST = Object.keys(glsUniformBlockCase.BufferMode).length;
+
+/**
+ * glsUniformBlockCase.PrecisionFlagsFmt
+ * @param {number} flags
+ * @return {string}
+ */
+glsUniformBlockCase.PrecisionFlagsFmt = function(flags) {
+ // Precision.
+ DE_ASSERT(deMath.dePop32(flags & (glsUniformBlockCase.UniformFlags.PRECISION_LOW | glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM | glsUniformBlockCase.UniformFlags.PRECISION_HIGH)) <= 1);
+ var str = '';
+ str += (flags & glsUniformBlockCase.UniformFlags.PRECISION_LOW ? 'lowp' :
+ flags & glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM ? 'mediump' :
+ flags & glsUniformBlockCase.UniformFlags.PRECISION_HIGH ? 'highp' : '');
+
+ return str;
+};
+
+/**
+ * glsUniformBlockCase.LayoutFlagsFmt
+ * @param {number} flags_
+ * @return {string}
+ */
+glsUniformBlockCase.LayoutFlagsFmt = function(flags_) {
+ var str = '';
+ var bitDesc =
+ [{ bit: glsUniformBlockCase.UniformFlags.LAYOUT_SHARED, token: 'shared' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_PACKED, token: 'packed' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_STD140, token: 'std140' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR, token: 'row_major' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR, token: 'column_major' }
+ ];
+
+ /** @type {number} */ var remBits = flags_;
+ for (var descNdx = 0; descNdx < bitDesc.length; descNdx++) {
+ if (remBits & bitDesc[descNdx].bit) {
+ if (remBits != flags_)
+ str += ', ';
+ str += bitDesc[descNdx].token;
+ remBits &= (~bitDesc[descNdx].bit) & 0xFFFFFFFF; //0xFFFFFFFF truncate to 32 bit value
+ }
+ }
+ DE_ASSERT(remBits == 0);
+
+ return str;
+};
+
+/**
+ * @constructor
+ */
+glsUniformBlockCase.UniformBufferManager = function(renderCtx) {
+ this.m_renderCtx = renderCtx;
+ /** @type {Array<number>} */ this.m_buffers = [];
+};
+
+/**
+ * allocBuffer
+ * @return {WebGLBuffer}
+ */
+glsUniformBlockCase.UniformBufferManager.prototype.allocBuffer = function() {
+ /** @type {WebGLBuffer} */ var buf = this.m_renderCtx.createBuffer();
+
+ this.m_buffers.push(buf);
+
+ return buf;
+};
+
+/**
+ * @param {string} name
+ * @param {string} description
+ * @param {glsUniformBlockCase.BufferMode} bufferMode
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+glsUniformBlockCase.UniformBlockCase = function(name, description, bufferMode) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {string} */ this.m_name = name;
+ /** @type {string} */ this.m_description = description;
+ /** @type {glsUniformBlockCase.BufferMode} */ this.m_bufferMode = bufferMode;
+ /** @type {glsUniformBlockCase.ShaderInterface} */ this.m_interface = new glsUniformBlockCase.ShaderInterface();
+};
+
+glsUniformBlockCase.UniformBlockCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+glsUniformBlockCase.UniformBlockCase.prototype.constructor = glsUniformBlockCase.UniformBlockCase;
+
+/**
+ * glsUniformBlockCase.getDataTypeByteSize
+ * @param {gluShaderUtil.DataType} type
+ * @return {number}
+ */
+glsUniformBlockCase.getDataTypeByteSize = function(type) {
+ return gluShaderUtil.getDataTypeScalarSize(type) * deMath.INT32_SIZE;
+};
+
+/**
+ * glsUniformBlockCase.getDataTypeByteAlignment
+ * @param {gluShaderUtil.DataType} type
+ * @return {number}
+ */
+glsUniformBlockCase.getDataTypeByteAlignment = function(type) {
+ switch (type) {
+ case gluShaderUtil.DataType.FLOAT:
+ case gluShaderUtil.DataType.INT:
+ case gluShaderUtil.DataType.UINT:
+ case gluShaderUtil.DataType.BOOL: return 1 * deMath.INT32_SIZE;
+
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ case gluShaderUtil.DataType.INT_VEC2:
+ case gluShaderUtil.DataType.UINT_VEC2:
+ case gluShaderUtil.DataType.BOOL_VEC2: return 2 * deMath.INT32_SIZE;
+
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ case gluShaderUtil.DataType.INT_VEC3:
+ case gluShaderUtil.DataType.UINT_VEC3:
+ case gluShaderUtil.DataType.BOOL_VEC3: // Fall-through to vec4
+
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ case gluShaderUtil.DataType.INT_VEC4:
+ case gluShaderUtil.DataType.UINT_VEC4:
+ case gluShaderUtil.DataType.BOOL_VEC4: return 4 * deMath.INT32_SIZE;
+
+ default:
+ DE_ASSERT(false);
+ return 0;
+ }
+};
+
+/**
+ * glsUniformBlockCase.getDataTypeArrayStride
+ * @param {gluShaderUtil.DataType} type
+ * @return {number}
+ */
+glsUniformBlockCase.getDataTypeArrayStride = function(type) {
+ DE_ASSERT(!gluShaderUtil.isDataTypeMatrix(type));
+
+ /** @type {number} */ var baseStride = glsUniformBlockCase.getDataTypeByteSize(type);
+ /** @type {number} */ var vec4Alignment = deMath.INT32_SIZE * 4;
+
+ DE_ASSERT(baseStride <= vec4Alignment);
+ return Math.max(baseStride, vec4Alignment); // Really? See rule 4.
+};
+
+/**
+ * glsUniformBlockCase.deRoundUp32 Rounds up 'a' in case the
+ * relationship with 'b' has a decimal part.
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+glsUniformBlockCase.deRoundUp32 = function(a, b) {
+ var d = Math.trunc(a / b);
+ return d * b == a ? a : (d + 1) * b;
+};
+
+/**
+ * glsUniformBlockCase.computeStd140BaseAlignment
+ * @param {glsUniformBlockCase.VarType} type
+ * @return {number}
+ */
+glsUniformBlockCase.computeStd140BaseAlignment = function(type) {
+ /** @type {number} */ var vec4Alignment = deMath.INT32_SIZE * 4;
+
+ if (type.isBasicType()) {
+ /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType();
+
+ if (gluShaderUtil.isDataTypeMatrix(basicType)) {
+ /** @type {boolean} */ var isRowMajor = !!(type.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR);
+ /** @type {number} */ var vecSize = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(basicType) :
+ gluShaderUtil.getDataTypeMatrixNumRows(basicType);
+
+ return glsUniformBlockCase.getDataTypeArrayStride(gluShaderUtil.getDataTypeFloatVec(vecSize));
+ } else
+ return glsUniformBlockCase.getDataTypeByteAlignment(basicType);
+ } else if (type.isArrayType()) {
+ /** @type {number} */ var elemAlignment = glsUniformBlockCase.computeStd140BaseAlignment(type.getElementType());
+
+ // Round up to alignment of vec4
+ return glsUniformBlockCase.deRoundUp32(elemAlignment, vec4Alignment);
+ } else {
+ DE_ASSERT(type.isStructType());
+
+ /** @type {number} */ var maxBaseAlignment = 0;
+
+ for (var memberNdx = 0; memberNdx < type.getStruct().getSize(); memberNdx++) {
+ /** @type {glsUniformBlockCase.StructMember} */ var memberIter = type.getStruct().getMember(memberNdx);
+ maxBaseAlignment = Math.max(maxBaseAlignment, glsUniformBlockCase.computeStd140BaseAlignment(memberIter.getType()));
+ }
+
+ return glsUniformBlockCase.deRoundUp32(maxBaseAlignment, vec4Alignment);
+ }
+};
+
+/**
+ * mergeLayoutflags
+ * @param {number} prevFlags
+ * @param {number} newFlags
+ * @return {number}
+ */
+glsUniformBlockCase.mergeLayoutFlags = function(prevFlags, newFlags) {
+ /** @type {number} */ var packingMask = glsUniformBlockCase.UniformFlags.LAYOUT_PACKED | glsUniformBlockCase.UniformFlags.LAYOUT_SHARED | glsUniformBlockCase.UniformFlags.LAYOUT_STD140;
+ /** @type {number} */ var matrixMask = glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR | glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR;
+
+ /** @type {number} */ var mergedFlags = 0;
+
+ mergedFlags |= ((newFlags & packingMask) ? newFlags : prevFlags) & packingMask;
+ mergedFlags |= ((newFlags & matrixMask) ? newFlags : prevFlags) & matrixMask;
+
+ return mergedFlags;
+};
+
+/**
+ * glsUniformBlockCase.computeStd140Layout_B
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {number} curOffset
+ * @param {number} curBlockNdx
+ * @param {string} curPrefix
+ * @param {glsUniformBlockCase.VarType} type
+ * @param {number} layoutFlags
+ * @return {number} //This is what would return in the curOffset output parameter in the original C++ project.
+ */
+glsUniformBlockCase.computeStd140Layout_B = function(layout, curOffset, curBlockNdx, curPrefix, type, layoutFlags) {
+ /** @type {number} */ var baseAlignment = glsUniformBlockCase.computeStd140BaseAlignment(type);
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entry;
+ /** @type {number} */ var stride;
+ /** @type {gluShaderUtil.DataType} */ var elemBasicType;
+ /** @type {boolean} */ var isRowMajor;
+ /** @type {number} */ var vecSize;
+ /** @type {number} */ var numVecs;
+
+ curOffset = deMath.deAlign32(curOffset, baseAlignment);
+
+ if (type.isBasicType()) {
+ /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType();
+ entry = new glsUniformBlockCase.UniformLayoutEntry();
+
+ entry.name = curPrefix;
+ entry.type = basicType;
+ entry.size = 1;
+ entry.arrayStride = 0;
+ entry.matrixStride = 0;
+ entry.blockNdx = curBlockNdx;
+
+ if (gluShaderUtil.isDataTypeMatrix(basicType)) {
+ // Array of vectors as specified in rules 5 & 7.
+ isRowMajor = !!(layoutFlags & glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR);
+ vecSize = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(basicType) :
+ gluShaderUtil.getDataTypeMatrixNumRows(basicType);
+ numVecs = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(basicType) :
+ gluShaderUtil.getDataTypeMatrixNumColumns(basicType);
+ stride = glsUniformBlockCase.getDataTypeArrayStride(gluShaderUtil.getDataTypeFloatVec(vecSize));
+
+ entry.offset = curOffset;
+ entry.matrixStride = stride;
+ entry.isRowMajor = isRowMajor;
+
+ curOffset += numVecs * stride;
+ } else {
+ // Scalar or vector.
+ entry.offset = curOffset;
+
+ curOffset += glsUniformBlockCase.getDataTypeByteSize(basicType);
+ }
+
+ layout.uniforms.push(entry);
+ } else if (type.isArrayType()) {
+ /** @type {glsUniformBlockCase.VarType} */ var elemType = type.getElementType();
+
+ if (elemType.isBasicType() && !gluShaderUtil.isDataTypeMatrix(elemType.getBasicType())) {
+ // Array of scalars or vectors.
+ elemBasicType = elemType.getBasicType();
+ entry = new glsUniformBlockCase.UniformLayoutEntry();
+ stride = glsUniformBlockCase.getDataTypeArrayStride(elemBasicType);
+
+ entry.name = curPrefix + '[0]'; // Array uniforms are always postfixed with [0]
+ entry.type = elemBasicType;
+ entry.blockNdx = curBlockNdx;
+ entry.offset = curOffset;
+ entry.size = type.getArraySize();
+ entry.arrayStride = stride;
+ entry.matrixStride = 0;
+
+ curOffset += stride * type.getArraySize();
+
+ layout.uniforms.push(entry);
+ } else if (elemType.isBasicType() && gluShaderUtil.isDataTypeMatrix(elemType.getBasicType())) {
+ // Array of matrices.
+ elemBasicType = elemType.getBasicType();
+ isRowMajor = !!(layoutFlags & glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR);
+ vecSize = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(elemBasicType) :
+ gluShaderUtil.getDataTypeMatrixNumRows(elemBasicType);
+ numVecs = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(elemBasicType) :
+ gluShaderUtil.getDataTypeMatrixNumColumns(elemBasicType);
+ stride = glsUniformBlockCase.getDataTypeArrayStride(gluShaderUtil.getDataTypeFloatVec(vecSize));
+ entry = new glsUniformBlockCase.UniformLayoutEntry();
+
+ entry.name = curPrefix + '[0]'; // Array uniforms are always postfixed with [0]
+ entry.type = elemBasicType;
+ entry.blockNdx = curBlockNdx;
+ entry.offset = curOffset;
+ entry.size = type.getArraySize();
+ entry.arrayStride = stride * numVecs;
+ entry.matrixStride = stride;
+ entry.isRowMajor = isRowMajor;
+
+ curOffset += numVecs * type.getArraySize() * stride;
+
+ layout.uniforms.push(entry);
+ } else {
+ DE_ASSERT(elemType.isStructType() || elemType.isArrayType());
+
+ for (var elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
+ curOffset = glsUniformBlockCase.computeStd140Layout_B(layout, curOffset, curBlockNdx, curPrefix + '[' + elemNdx + ']', type.getElementType(), layoutFlags);
+ }
+ } else {
+ DE_ASSERT(type.isStructType());
+
+ for (var memberNdx = 0; memberNdx < type.getStruct().getSize(); memberNdx++) {
+ /** @type {glsUniformBlockCase.StructMember} */ var memberIter = type.getStruct().getMember(memberNdx);
+ curOffset = glsUniformBlockCase.computeStd140Layout_B(layout, curOffset, curBlockNdx, curPrefix + '.' + memberIter.getName(), memberIter.getType(), layoutFlags);
+ }
+
+ curOffset = deMath.deAlign32(curOffset, baseAlignment);
+ }
+
+ return curOffset;
+};
+
+/**
+ * glsUniformBlockCase.computeStd140Layout
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {glsUniformBlockCase.ShaderInterface} sinterface
+ */
+glsUniformBlockCase.computeStd140Layout = function(layout, sinterface) {
+ // \todo [2012-01-23 pyry] Uniforms in default block.
+
+ /** @type {number} */ var numUniformBlocks = sinterface.getNumUniformBlocks();
+
+ for (var blockNdx = 0; blockNdx < numUniformBlocks; blockNdx++) {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx);
+ /** @type {boolean} */ var hasInstanceName = block.getInstanceName() !== undefined;
+ /** @type {string} */ var blockPrefix = hasInstanceName ? (block.getBlockName() + '.') : '';
+ /** @type {number} */ var curOffset = 0;
+ /** @type {number} */ var activeBlockNdx = layout.blocks.length;
+ /** @type {number} */ var firstUniformNdx = layout.uniforms.length;
+
+ for (var ubNdx = 0; ubNdx < block.countUniforms(); ubNdx++) {
+ /** @type {glsUniformBlockCase.Uniform} */ var uniform = block.getUniform(ubNdx);
+ curOffset = glsUniformBlockCase.computeStd140Layout_B(layout, curOffset, activeBlockNdx, blockPrefix + uniform.getName(), uniform.getType(), glsUniformBlockCase.mergeLayoutFlags(block.getFlags(), uniform.getFlags()));
+ }
+
+ /** @type {number} */ var uniformIndicesEnd = layout.uniforms.length;
+ /** @type {number} */ var blockSize = curOffset;
+ /** @type {number} */ var numInstances = block.isArray() ? block.getArraySize() : 1;
+
+ // Create block layout entries for each instance.
+ for (var instanceNdx = 0; instanceNdx < numInstances; instanceNdx++) {
+ // Allocate entry for instance.
+ layout.blocks.push(new glsUniformBlockCase.BlockLayoutEntry());
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var blockEntry = layout.blocks[layout.blocks.length - 1];
+
+ blockEntry.name = block.getBlockName();
+ blockEntry.size = blockSize;
+
+ // Compute active uniform set for block.
+ for (var uniformNdx = firstUniformNdx; uniformNdx < uniformIndicesEnd; uniformNdx++)
+ blockEntry.activeUniformIndices.push(uniformNdx);
+
+ if (block.isArray())
+ blockEntry.name += '[' + instanceNdx + ']';
+ }
+ }
+};
+
+/**
+ * glsUniformBlockCase.generateValue - Value generator
+ * @param {glsUniformBlockCase.UniformLayoutEntry} entry
+ * @param {Uint8Array} basePtr
+ * @param {deRandom.Random} rnd
+ */
+glsUniformBlockCase.generateValue = function(entry, basePtr, rnd) {
+ /** @type {gluShaderUtil.DataType}*/ var scalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(entry.type); //Using a more appropriate function in this case.
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(entry.type);
+ /** @type {boolean} */ var isMatrix = gluShaderUtil.isDataTypeMatrix(entry.type);
+ /** @type {number} */ var numVecs = isMatrix ? (entry.isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(entry.type) : gluShaderUtil.getDataTypeMatrixNumColumns(entry.type)) : 1;
+ /** @type {number} */ var vecSize = scalarSize / numVecs;
+ /** @type {boolean} */ var isArray = entry.size > 1;
+ /** @type {number} */ var compSize = deMath.INT32_SIZE;
+
+ DE_ASSERT(scalarSize % numVecs == 0);
+
+ for (var elemNdx = 0; elemNdx < entry.size; elemNdx++) {
+ /** @type {Uint8Array} */ var elemPtr = basePtr.subarray(entry.offset + (isArray ? elemNdx * entry.arrayStride : 0));
+
+ for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) {
+ /** @type {Uint8Array} */ var vecPtr = elemPtr.subarray(isMatrix ? vecNdx * entry.matrixStride : 0);
+
+ for (var compNdx = 0; compNdx < vecSize; compNdx++) {
+ /** @type {Uint8Array} */ var compPtr = vecPtr.subarray(compSize * compNdx);
+ /** @type {number} */ var _random;
+
+ //Copy the random data byte per byte
+ var _size = glsUniformBlockCase.getDataTypeByteSize(scalarType);
+
+ var nbuffer = new ArrayBuffer(_size);
+ var nview = new DataView(nbuffer);
+
+ switch (scalarType) {
+ case gluShaderUtil.DataType.FLOAT:
+ _random = rnd.getInt(-9, 9);
+ nview.setFloat32(0, _random, littleEndian);
+ break;
+ case gluShaderUtil.DataType.INT:
+ _random = rnd.getInt(-9, 9);
+ nview.setInt32(0, _random, littleEndian);
+ break;
+ case gluShaderUtil.DataType.UINT:
+ _random = rnd.getInt(0, 9);
+ nview.setUint32(0, _random, littleEndian);
+ break;
+ // \note Random bit pattern is used for true values. Spec states that all non-zero values are
+ // interpreted as true but some implementations fail this.
+ case gluShaderUtil.DataType.BOOL:
+ _random = rnd.getBool() ? 1 : 0;
+ nview.setUint32(0, _random, littleEndian);
+ break;
+ default:
+ DE_ASSERT(false);
+ }
+
+ for (var i = 0; i < _size; i++) {
+ compPtr[i] = nview.getUint8(i);
+ }
+ }
+ }
+ }
+};
+
+/**
+ * glsUniformBlockCase.generateValues
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {glsUniformBlockCase.BlockPointers} blockPointers
+ * @param {number} seed
+ */
+glsUniformBlockCase.generateValues = function(layout, blockPointers, seed) {
+ /** @type  {deRandom.Random} */ var rnd = new deRandom.Random(seed);
+ /** @type  {number} */ var numBlocks = layout.blocks.length;
+
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ /** @type {Uint8Array} */ var basePtr = blockPointers.find(blockNdx);
+ /** @type  {number} */ var numEntries = layout.blocks[blockNdx].activeUniformIndices.length;
+
+ for (var entryNdx = 0; entryNdx < numEntries; entryNdx++) {
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entry = layout.uniforms[layout.blocks[blockNdx].activeUniformIndices[entryNdx]];
+ glsUniformBlockCase.generateValue(entry, basePtr, rnd);
+ }
+ }
+};
+
+// Shader generator.
+
+/**
+ * glsUniformBlockCase.getCompareFuncForType
+ * @param {gluShaderUtil.DataType} type
+ * @return {string}
+ */
+glsUniformBlockCase.getCompareFuncForType = function(type) {
+ switch (type) {
+ case gluShaderUtil.DataType.FLOAT: return 'mediump float compare_float (highp float a, highp float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.FLOAT_VEC2: return 'mediump float compare_vec2 (highp vec2 a, highp vec2 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }\n';
+ case gluShaderUtil.DataType.FLOAT_VEC3: return 'mediump float compare_vec3 (highp vec3 a, highp vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }\n';
+ case gluShaderUtil.DataType.FLOAT_VEC4: return 'mediump float compare_vec4 (highp vec4 a, highp vec4 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT2: return 'mediump float compare_mat2 (highp mat2 a, highp mat2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT2X3: return 'mediump float compare_mat2x3 (highp mat2x3 a, highp mat2x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT2X4: return 'mediump float compare_mat2x4 (highp mat2x4 a, highp mat2x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT3X2: return 'mediump float compare_mat3x2 (highp mat3x2 a, highp mat3x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT3: return 'mediump float compare_mat3 (highp mat3 a, highp mat3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT3X4: return 'mediump float compare_mat3x4 (highp mat3x4 a, highp mat3x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT4X2: return 'mediump float compare_mat4x2 (highp mat4x2 a, highp mat4x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT4X3: return 'mediump float compare_mat4x3 (highp mat4x3 a, highp mat4x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }\n';
+ case gluShaderUtil.DataType.FLOAT_MAT4: return 'mediump float compare_mat4 (highp mat4 a, highp mat4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }\n';
+ case gluShaderUtil.DataType.INT: return 'mediump float compare_int (highp int a, highp int b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.INT_VEC2: return 'mediump float compare_ivec2 (highp ivec2 a, highp ivec2 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.INT_VEC3: return 'mediump float compare_ivec3 (highp ivec3 a, highp ivec3 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.INT_VEC4: return 'mediump float compare_ivec4 (highp ivec4 a, highp ivec4 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.UINT: return 'mediump float compare_uint (highp uint a, highp uint b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.UINT_VEC2: return 'mediump float compare_uvec2 (highp uvec2 a, highp uvec2 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.UINT_VEC3: return 'mediump float compare_uvec3 (highp uvec3 a, highp uvec3 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.UINT_VEC4: return 'mediump float compare_uvec4 (highp uvec4 a, highp uvec4 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.BOOL: return 'mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.BOOL_VEC2: return 'mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.BOOL_VEC3: return 'mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }\n';
+ case gluShaderUtil.DataType.BOOL_VEC4: return 'mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }\n';
+ default:
+ throw new Error('Type "' + type + '" not supported.');
+
+ }
+};
+
+/**
+ * glsUniformBlockCase.getCompareDependencies
+ * @param {Array<gluShaderUtil.DataType>} compareFuncs Should contain unique elements
+ * @param {gluShaderUtil.DataType} basicType
+ */
+glsUniformBlockCase.getCompareDependencies = function(compareFuncs, basicType) {
+ switch (basicType) {
+ case gluShaderUtil.DataType.FLOAT_VEC2:
+ case gluShaderUtil.DataType.FLOAT_VEC3:
+ case gluShaderUtil.DataType.FLOAT_VEC4:
+ deUtil.dePushUniqueToArray(compareFuncs, gluShaderUtil.DataType.FLOAT);
+ deUtil.dePushUniqueToArray(compareFuncs, basicType);
+ break;
+
+ case gluShaderUtil.DataType.FLOAT_MAT2:
+ case gluShaderUtil.DataType.FLOAT_MAT2X3:
+ case gluShaderUtil.DataType.FLOAT_MAT2X4:
+ case gluShaderUtil.DataType.FLOAT_MAT3X2:
+ case gluShaderUtil.DataType.FLOAT_MAT3:
+ case gluShaderUtil.DataType.FLOAT_MAT3X4:
+ case gluShaderUtil.DataType.FLOAT_MAT4X2:
+ case gluShaderUtil.DataType.FLOAT_MAT4X3:
+ case gluShaderUtil.DataType.FLOAT_MAT4:
+ deUtil.dePushUniqueToArray(compareFuncs, gluShaderUtil.DataType.FLOAT);
+ deUtil.dePushUniqueToArray(compareFuncs, gluShaderUtil.getDataTypeFloatVec(gluShaderUtil.getDataTypeMatrixNumRows(basicType)));
+ deUtil.dePushUniqueToArray(compareFuncs, basicType);
+ break;
+
+ default:
+ deUtil.dePushUniqueToArray(compareFuncs, basicType);
+ break;
+ }
+};
+
+/**
+ * glsUniformBlockCase.collectUniqueBasicTypes_B
+ * @param {Array<gluShaderUtil.DataType>} basicTypes Should contain unique elements
+ * @param {glsUniformBlockCase.VarType} type
+ */
+glsUniformBlockCase.collectUniqueBasicTypes_B = function(basicTypes, type) {
+ if (type.isStructType()) {
+ /** @type {glsUniformBlockCase.StructType} */ var stype = type.getStruct();
+ for (var memberNdx = 0; memberNdx < stype.getSize(); memberNdx++)
+ glsUniformBlockCase.collectUniqueBasicTypes_B(basicTypes, stype.getMember(memberNdx).getType());
+ } else if (type.isArrayType())
+ glsUniformBlockCase.collectUniqueBasicTypes_B(basicTypes, type.getElementType());
+ else {
+ DE_ASSERT(type.isBasicType());
+ deUtil.dePushUniqueToArray(basicTypes, type.getBasicType());
+ }
+};
+
+/**
+ * glsUniformBlockCase.collectUniqueBasicTypes_A
+ * @param {Array<gluShaderUtil.DataType>} basicTypes Should contain unique elements
+ * @param {glsUniformBlockCase.UniformBlock} uniformBlock
+ */
+glsUniformBlockCase.collectUniqueBasicTypes_A = function(basicTypes, uniformBlock) {
+ for (var uniformNdx = 0; uniformNdx < uniformBlock.countUniforms(); uniformNdx++)
+ glsUniformBlockCase.collectUniqueBasicTypes_B(basicTypes, uniformBlock.getUniform(uniformNdx).getType());
+};
+
+/**
+ * glsUniformBlockCase.collectUniqueBasicTypes
+ * @param {Array<gluShaderUtil.DataType>} basicTypes Should contain unique elements
+ * @param {glsUniformBlockCase.ShaderInterface} sinterface
+ */
+glsUniformBlockCase.collectUniqueBasicTypes = function(basicTypes, sinterface) {
+ for (var ndx = 0; ndx < sinterface.getNumUniformBlocks(); ++ndx)
+ glsUniformBlockCase.collectUniqueBasicTypes_A(basicTypes, sinterface.getUniformBlock(ndx));
+};
+
+/**
+ * glsUniformBlockCase.collectUniqueBasicTypes
+ * @return {string} Was originally an output parameter. As it is a basic type, we have to return it instead.
+ * @param {glsUniformBlockCase.ShaderInterface} sinterface
+ */
+glsUniformBlockCase.generateCompareFuncs = function(sinterface) {
+ /** @type {string} */ var str = '';
+ /** @type {Array<gluShaderUtil.DataType>} */ var types = []; //Will contain unique elements.
+ /** @type {Array<gluShaderUtil.DataType>} */ var compareFuncs = []; //Will contain unique elements.
+
+ // Collect unique basic types
+ glsUniformBlockCase.collectUniqueBasicTypes(types, sinterface);
+
+ // Set of compare functions required
+ for (var typeNdx = 0; typeNdx < types.length; typeNdx++)
+ glsUniformBlockCase.getCompareDependencies(compareFuncs, types[typeNdx]);
+
+ for (var type in gluShaderUtil.DataType) {
+ if (compareFuncs.indexOf(gluShaderUtil.DataType[type]) > -1)
+ str += glsUniformBlockCase.getCompareFuncForType(gluShaderUtil.DataType[type]);
+ }
+
+ return str;
+};
+
+/**
+ * glsUniformBlockCase.Indent - Prints level_ number of tab chars
+ * @param {number} level_
+ * @return {string}
+ */
+glsUniformBlockCase.Indent = function(level_) {
+ var str = '';
+ for (var i = 0; i < level_; i++)
+ str += '\t';
+
+ return str;
+};
+
+/**
+ * glsUniformBlockCase.generateDeclaration_C
+ * @return {string} src
+ * @param {glsUniformBlockCase.StructType} structType
+ * @param {number} indentLevel
+ */
+glsUniformBlockCase.generateDeclaration_C = function(structType, indentLevel) {
+ /** @type {string} */ var src = '';
+
+ DE_ASSERT(structType.getTypeName() !== undefined);
+ src += glsUniformBlockCase.generateFullDeclaration(structType, indentLevel);
+ src += ';\n';
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateFullDeclaration
+ * @return {string} src
+ * @param {glsUniformBlockCase.StructType} structType
+ * @param {number} indentLevel
+ */
+glsUniformBlockCase.generateFullDeclaration = function(structType, indentLevel) {
+ var src = 'struct';
+ if (structType.getTypeName())
+ src += ' ' + structType.getTypeName();
+ src += '\n' + glsUniformBlockCase.Indent(indentLevel) + ' {\n';
+
+ for (var memberNdx = 0; memberNdx < structType.getSize(); memberNdx++) {
+ src += glsUniformBlockCase.Indent(indentLevel + 1);
+ /** @type {glsUniformBlockCase.StructMember} */ var memberIter = structType.getMember(memberNdx);
+ src += glsUniformBlockCase.generateDeclaration_B(memberIter.getType(), memberIter.getName(), indentLevel + 1, memberIter.getFlags() & glsUniformBlockCase.UniformFlags.UNUSED_BOTH);
+ }
+
+ src += glsUniformBlockCase.Indent(indentLevel) + '}';
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateLocalDeclaration
+ * @return {string} src
+ * @param {glsUniformBlockCase.StructType} structType
+ * @param {number} indentLevel
+ */
+glsUniformBlockCase.generateLocalDeclaration = function(structType, indentLevel) {
+ /** @type {string} */ var src = '';
+
+ if (structType.getTypeName() === undefined)
+ src += glsUniformBlockCase.generateFullDeclaration(structType, indentLevel);
+ else
+ src += structType.getTypeName();
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateDeclaration_B
+ * @return {string} src
+ * @param {glsUniformBlockCase.VarType} type
+ * @param {string} name
+ * @param {number} indentLevel
+ * @param {number} unusedHints
+ */
+glsUniformBlockCase.generateDeclaration_B = function(type, name, indentLevel, unusedHints) {
+ /** @type {string} */ var src = '';
+ /** @type {number} */ var flags = type.getFlags();
+
+ if ((flags & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) != 0)
+ src += 'layout(' + glsUniformBlockCase.LayoutFlagsFmt(flags & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) + ') ';
+
+ if ((flags & glsUniformBlockCase.UniformFlags.PRECISION_MASK) != 0)
+ src += glsUniformBlockCase.PrecisionFlagsFmt(flags & glsUniformBlockCase.UniformFlags.PRECISION_MASK) + ' ';
+
+ if (type.isBasicType())
+ src += gluShaderUtil.getDataTypeName(type.getBasicType()) + ' ' + name;
+ else if (type.isArrayType()) {
+ /** @type {Array<number>} */ var arraySizes = [];
+ /** @type {glsUniformBlockCase.VarType} */ var curType = type;
+ while (curType.isArrayType()) {
+ arraySizes.push(curType.getArraySize());
+ curType = curType.getElementType();
+ }
+
+ if (curType.isBasicType()) {
+ if ((curType.getFlags() & glsUniformBlockCase.UniformFlags.PRECISION_MASK) != 0)
+ src += glsUniformBlockCase.PrecisionFlagsFmt(curType.getFlags() & glsUniformBlockCase.UniformFlags.PRECISION_MASK) + ' ';
+ src += gluShaderUtil.getDataTypeName(curType.getBasicType());
+ } else {
+ DE_ASSERT(curType.isStructType());
+ src += glsUniformBlockCase.generateLocalDeclaration(curType.getStruct(), indentLevel + 1);
+ }
+
+ src += ' ' + name;
+
+ for (var sizeNdx = 0; sizeNdx < arraySizes.length; sizeNdx++)
+ src += '[' + arraySizes[sizeNdx] + ']';
+ } else {
+ src += glsUniformBlockCase.generateLocalDeclaration(type.getStruct(), indentLevel + 1);
+ src += ' ' + name;
+ }
+
+ src += ';';
+
+ // Print out unused hints.
+ if (unusedHints != 0)
+ src += ' // unused in ' + (unusedHints == glsUniformBlockCase.UniformFlags.UNUSED_BOTH ? 'both shaders' :
+ unusedHints == glsUniformBlockCase.UniformFlags.UNUSED_VERTEX ? 'vertex shader' :
+ unusedHints == glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT ? 'fragment shader' : '???');
+
+ src += '\n';
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateDeclaration_A
+ * @return {string} src
+ * @param {glsUniformBlockCase.Uniform} uniform
+ * @param {number} indentLevel
+ */
+glsUniformBlockCase.generateDeclaration_A = function(uniform, indentLevel) {
+ /** @type {string} */ var src = '';
+
+ if ((uniform.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) != 0)
+ src += 'layout(' + glsUniformBlockCase.LayoutFlagsFmt(uniform.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) + ') ';
+
+ src += glsUniformBlockCase.generateDeclaration_B(uniform.getType(), uniform.getName(), indentLevel, uniform.getFlags() & glsUniformBlockCase.UniformFlags.UNUSED_BOTH);
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateDeclaration
+ * @return {string} src
+ * @param {glsUniformBlockCase.UniformBlock} block
+ */
+glsUniformBlockCase.generateDeclaration = function(block) {
+ /** @type {string} */ var src = '';
+
+ if ((block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) != 0)
+ src += 'layout(' + glsUniformBlockCase.LayoutFlagsFmt(block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) + ') ';
+
+ src += 'uniform ' + block.getBlockName();
+ src += '\n {\n';
+
+ for (var uniformNdx = 0; uniformNdx < block.countUniforms(); uniformNdx++) {
+ src += glsUniformBlockCase.Indent(1);
+ src += glsUniformBlockCase.generateDeclaration_A(block.getUniform(uniformNdx), 1 /* indent level */);
+ }
+
+ src += '}';
+
+ if (block.getInstanceName() !== undefined) {
+ src += ' ' + block.getInstanceName();
+ if (block.isArray())
+ src += '[' + block.getArraySize() + ']';
+ } else
+ DE_ASSERT(!block.isArray());
+
+ src += ';\n';
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.newArrayBufferFromView - Creates a new buffer copying data from a given view
+ * @param {goog.NumberArray} view
+ * @return {ArrayBuffer} The newly created buffer
+ */
+glsUniformBlockCase.newArrayBufferFromView = function(view) {
+ var buffer = new ArrayBuffer(view.length * view.BYTES_PER_ELEMENT);
+ var copyview;
+ switch (view.BYTES_PER_ELEMENT) {
+ case 1:
+ copyview = new Uint8Array(buffer); break;
+ case 2:
+ copyview = new Uint16Array(buffer); break;
+ case 4:
+ copyview = new Uint32Array(buffer); break;
+ default:
+ assertMsgOptions(false, 'Unexpected value for BYTES_PER_ELEMENT in view', false, true);
+ }
+ for (var i = 0; i < view.length; i++)
+ copyview[i] = view[i];
+
+ return buffer;
+};
+
+/**
+ * glsUniformBlockCase.generateValueSrc
+ * @return {string} Used to be an output parameter in C++ project
+ * @param {glsUniformBlockCase.UniformLayoutEntry} entry
+ * @param {Uint8Array} basePtr
+ * @param {number} elementNdx
+ */
+glsUniformBlockCase.generateValueSrc = function(entry, basePtr, elementNdx) {
+ /** @type {string} */ var src = '';
+ /** @type {gluShaderUtil.DataType} */ var scalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(entry.type);
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(entry.type);
+ /** @type {boolean} */ var isArray = entry.size > 1;
+ /** @type {Uint8Array} */ var elemPtr = basePtr.subarray(entry.offset + (isArray ? elementNdx * entry.arrayStride : 0));
+ /** @type {number} */ var compSize = deMath.INT32_SIZE;
+ /** @type {Uint8Array} */ var compPtr;
+ if (scalarSize > 1)
+ src += gluShaderUtil.getDataTypeName(entry.type) + '(';
+
+ if (gluShaderUtil.isDataTypeMatrix(entry.type)) {
+ /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(entry.type);
+ /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(entry.type);
+
+ DE_ASSERT(scalarType == gluShaderUtil.DataType.FLOAT);
+
+ // Constructed in column-wise order.
+ for (var colNdx = 0; colNdx < numCols; colNdx++) {
+ for (var rowNdx = 0; rowNdx < numRows; rowNdx++) {
+ compPtr = elemPtr.subarray(entry.isRowMajor ? rowNdx * entry.matrixStride + colNdx * compSize :
+ colNdx * entry.matrixStride + rowNdx * compSize);
+
+ if (colNdx > 0 || rowNdx > 0)
+ src += ', ';
+
+ var newbuffer = new Uint8Array(compPtr.subarray(0, 4)).buffer;
+ var newview = new DataView(newbuffer);
+ src += parseFloat(newview.getFloat32(0, littleEndian)).toFixed(1);
+ }
+ }
+ } else {
+ for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
+ compPtr = elemPtr.subarray(scalarNdx * compSize);
+
+ if (scalarNdx > 0)
+ src += ', ';
+
+ var newbuffer = glsUniformBlockCase.newArrayBufferFromView(compPtr.subarray(0, 4));
+ var newview = new DataView(newbuffer);
+
+ switch (scalarType) {
+ case gluShaderUtil.DataType.FLOAT: src += parseFloat(newview.getFloat32(0, littleEndian) * 100 / 100).toFixed(1); break;
+ case gluShaderUtil.DataType.INT: src += newview.getInt32(0, littleEndian); break;
+ case gluShaderUtil.DataType.UINT: src += newview.getUint32(0, littleEndian) + 'u'; break;
+ case gluShaderUtil.DataType.BOOL: src += (newview.getUint32(0, littleEndian) != 0 ? 'true' : 'false'); break;
+ default:
+ DE_ASSERT(false);
+ }
+ }
+ }
+
+ if (scalarSize > 1)
+ src += ')';
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateCompareSrc_A
+ * @return {string} Used to be an output parameter in C++ project
+ * @param {string} resultVar
+ * @param {glsUniformBlockCase.VarType} type
+ * @param {string} srcName
+ * @param {string} apiName
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {Uint8Array} basePtr
+ * @param {number} unusedMask
+ */
+glsUniformBlockCase.generateCompareSrc_A = function(resultVar, type, srcName, apiName, layout, basePtr, unusedMask) {
+ /** @type {string} */ var src = '';
+ /** @type {string} */ var op;
+ /** @type {glsUniformBlockCase.VarType|gluShaderUtil.DataType} */ var elementType;
+
+ if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType())) {
+ // Basic type or array of basic types.
+ /** @type {boolean} */ var isArray = type.isArrayType();
+ elementType = isArray ? type.getElementType().getBasicType() : type.getBasicType();
+ /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(elementType);
+ /** @type {string} */ var fullApiName = apiName + (isArray ? '[0]' : ''); // Arrays are always postfixed with [0]
+ /** @type {number} */ var uniformNdx = layout.getUniformIndex(fullApiName);
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entry = layout.uniforms[uniformNdx];
+
+ if (isArray) {
+ for (var elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++) {
+ src += '\tresult *= compare_' + typeName + '(' + srcName + '[' + elemNdx + '], ';
+ src += glsUniformBlockCase.generateValueSrc(entry, basePtr, elemNdx);
+ src += ');\n';
+ }
+ } else {
+ src += '\tresult *= compare_' + typeName + '(' + srcName + ', ';
+ src += glsUniformBlockCase.generateValueSrc(entry, basePtr, 0);
+ src += ');\n';
+ }
+ } else if (type.isArrayType()) {
+ elementType = type.getElementType();
+
+ for (var elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++) {
+ op = '[' + elementNdx + ']';
+ src += glsUniformBlockCase.generateCompareSrc_A(resultVar, elementType, srcName + op, apiName + op, layout, basePtr, unusedMask);
+ }
+ } else {
+ DE_ASSERT(type.isStructType());
+
+ /** @type {glsUniformBlockCase.StructType} */ var stype = type.getStruct();
+ for (var memberNdx = 0; memberNdx < stype.getSize(); memberNdx++) {
+ /** @type {glsUniformBlockCase.StructMember} */ var memberIter = stype.getMember(memberNdx);
+ if (memberIter.getFlags() & unusedMask)
+ continue; // Skip member.
+
+ op = '.' + memberIter.getName();
+ src += glsUniformBlockCase.generateCompareSrc_A(resultVar, memberIter.getType(), srcName + op, apiName + op, layout, basePtr, unusedMask);
+ }
+ }
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateCompareSrc
+ * @return {string} Used to be an output parameter in C++ project
+ * @param {string} resultVar
+ * @param {glsUniformBlockCase.ShaderInterface} sinterface
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {glsUniformBlockCase.BlockPointers} blockPointers
+ * @param {boolean} isVertex
+ */
+glsUniformBlockCase.generateCompareSrc = function(resultVar, sinterface, layout, blockPointers, isVertex) {
+ /** @type {string} */ var src = '';
+ /** @type {number} */ var unusedMask = isVertex ? glsUniformBlockCase.UniformFlags.UNUSED_VERTEX : glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT;
+
+ for (var blockNdx = 0; blockNdx < sinterface.getNumUniformBlocks(); blockNdx++) {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx);
+
+ if ((block.getFlags() & (isVertex ? glsUniformBlockCase.UniformFlags.DECLARE_VERTEX : glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)) == 0)
+ continue; // Skip.
+
+ /** @type {boolean} */ var hasInstanceName = block.getInstanceName() !== undefined;
+ /** @type {boolean} */ var isArray = block.isArray();
+ /** @type {number} */ var numInstances = isArray ? block.getArraySize() : 1;
+ /** @type {string} */ var apiPrefix = hasInstanceName ? block.getBlockName() + '.' : '';
+
+ DE_ASSERT(!isArray || hasInstanceName);
+
+ for (var instanceNdx = 0; instanceNdx < numInstances; instanceNdx++) {
+ /** @type {string} */ var instancePostfix = isArray ? '[' + instanceNdx + ']' : '';
+ /** @type {string} */ var blockInstanceName = block.getBlockName() + instancePostfix;
+ /** @type {string} */ var srcPrefix = hasInstanceName ? block.getInstanceName() + instancePostfix + '.' : '';
+ /** @type {number} */ var activeBlockNdx = layout.getBlockIndex(blockInstanceName);
+ /** @type {Uint8Array} */ var basePtr = blockPointers.find(activeBlockNdx);
+
+ for (var uniformNdx = 0; uniformNdx < block.countUniforms(); uniformNdx++) {
+ /** @type {glsUniformBlockCase.Uniform} */ var uniform = block.getUniform(uniformNdx);
+
+ if (uniform.getFlags() & unusedMask)
+ continue; // Don't read from that uniform.
+
+ src += glsUniformBlockCase.generateCompareSrc_A(resultVar, uniform.getType(), srcPrefix + uniform.getName(), apiPrefix + uniform.getName(), layout, basePtr, unusedMask);
+ }
+ }
+ }
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateVertexShader
+ * @return {string} src
+ * @param {glsUniformBlockCase.ShaderInterface} sinterface
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {glsUniformBlockCase.BlockPointers} blockPointers
+ */
+glsUniformBlockCase.generateVertexShader = function(sinterface, layout, blockPointers) {
+ /** @type {string} */ var src = '';
+
+ DE_ASSERT(glsUniformBlockCase.isSupportedGLSLVersion(gluShaderUtil.getGLSLVersion(gl)));
+
+ src += gluShaderUtil.getGLSLVersionDeclaration(gluShaderUtil.getGLSLVersion(gl)) + '\n';
+ src += 'in highp vec4 a_position;\n';
+ src += 'out mediump float v_vtxResult;\n';
+ src += '\n';
+
+ /** @type {Array<glsUniformBlockCase.StructType>} */ var namedStructs = [];
+ sinterface.getNamedStructs(namedStructs);
+ for (var structNdx = 0; structNdx < namedStructs.length; structNdx++)
+ src += glsUniformBlockCase.generateDeclaration_C(namedStructs[structNdx], 0);
+
+ for (var blockNdx = 0; blockNdx < sinterface.getNumUniformBlocks(); blockNdx++) {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx);
+ if (block.getFlags() & glsUniformBlockCase.UniformFlags.DECLARE_VERTEX)
+ src += glsUniformBlockCase.generateDeclaration(block);
+ }
+
+ // Comparison utilities.
+ src += '\n';
+ src += glsUniformBlockCase.generateCompareFuncs(sinterface);
+
+ src += '\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ ' gl_Position = a_position;\n' +
+ ' mediump float result = 1.0;\n';
+
+ // Value compare.
+ src += glsUniformBlockCase.generateCompareSrc('result', sinterface, layout, blockPointers, true);
+
+ src += ' v_vtxResult = result;\n' +
+ '}\n';
+
+ return src;
+};
+
+/**
+ * glsUniformBlockCase.generateFragmentShader
+ * @return {string} Used to be an output parameter
+ * @param {glsUniformBlockCase.ShaderInterface} sinterface
+ * @param {glsUniformBlockCase.UniformLayout} layout
+ * @param {glsUniformBlockCase.BlockPointers} blockPointers
+ */
+glsUniformBlockCase.generateFragmentShader = function(sinterface, layout, blockPointers) {
+ /** @type {string} */ var src = '';
+ DE_ASSERT(glsUniformBlockCase.isSupportedGLSLVersion(gluShaderUtil.getGLSLVersion(gl)));
+
+ src += gluShaderUtil.getGLSLVersionDeclaration(gluShaderUtil.getGLSLVersion(gl)) + '\n';
+ src += 'in mediump float v_vtxResult;\n';
+ src += 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+ src += '\n';
+
+ /** @type {Array<glsUniformBlockCase.StructType>} */ var namedStructs = [];
+ sinterface.getNamedStructs(namedStructs);
+ for (var structNdx = 0; structNdx < namedStructs.length; structNdx++)
+ src += glsUniformBlockCase.generateDeclaration_C(namedStructs[structNdx], 0);
+
+ for (var blockNdx = 0; blockNdx < sinterface.getNumUniformBlocks(); blockNdx++) {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx);
+ if (block.getFlags() & glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)
+ src += glsUniformBlockCase.generateDeclaration(block);
+ }
+
+ // Comparison utilities.
+ src += '\n';
+ src += glsUniformBlockCase.generateCompareFuncs(sinterface);
+
+ src += '\n' +
+ 'void main (void)\n' +
+ ' {\n' +
+ ' mediump float result = 1.0;\n';
+
+ // Value compare.
+ src += glsUniformBlockCase.generateCompareSrc('result', sinterface, layout, blockPointers, false);
+
+ src += ' dEQP_FragColor = vec4(1.0, v_vtxResult, result, 1.0);\n' +
+ '}\n';
+
+ return src;
+};
+
+/**
+ * TODO: test glsUniformBlockCase.getGLUniformLayout Gets the uniform blocks and uniforms in the program.
+ * @param {WebGL2RenderingContext} gl
+ * @param {glsUniformBlockCase.UniformLayout} layout To store the layout described in program.
+ * @param {WebGLProgram} program id
+ */
+glsUniformBlockCase.getGLUniformLayout = function(gl, layout, program) {
+ /** @type {number} */ var numActiveUniforms = 0;
+ /** @type {number} */ var numActiveBlocks = 0;
+
+ numActiveUniforms = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS)); // ACTIVE_UNIFORM* returns GLInt
+ numActiveBlocks = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS));
+
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var entryBlock;
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entryUniform;
+ /** @type {number} */ var size;
+ /** @type {number} */ var nameLen;
+ /** @type {string} */ var nameBuf;
+ /** @type {number} */ var numBlockUniforms;
+
+ // Block entries.
+ //No need to allocate these beforehand: layout.blocks.resize(numActiveBlocks);
+ for (var blockNdx = 0; blockNdx < numActiveBlocks; blockNdx++) {
+ entryBlock = new glsUniformBlockCase.BlockLayoutEntry();
+
+ size = /** @type {number} */ (gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_DATA_SIZE));
+ // nameLen not used so this line is removed.
+ // nameLen = gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_NAME_LENGTH); // TODO: UNIFORM_BLOCK_NAME_LENGTH is removed in WebGL2
+ numBlockUniforms = /** @type {number} */ (gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS));
+
+ nameBuf = gl.getActiveUniformBlockName(program, blockNdx);
+
+ entryBlock.name = nameBuf;
+ entryBlock.size = size;
+ //entry.activeUniformIndices.resize(numBlockUniforms);
+
+ if (numBlockUniforms > 0)
+ entryBlock.activeUniformIndices = gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
+
+ layout.blocks.push(entryBlock); //Pushing the block into the array here.
+ }
+
+ if (numActiveUniforms > 0) {
+ // glsUniformBlockCase.Uniform entries.
+ /** @type {Array<number>} */ var uniformIndices = [];
+ for (var i = 0; i < numActiveUniforms; i++)
+ uniformIndices.push(i);
+
+ /** @type {Array<number>} */ var types = [];
+ /** @type {Array<number>} */ var sizes = [];
+ /** @type {Array<number>} */ var nameLengths = [];
+ /** @type {Array<number>} */ var blockIndices = [];
+ /** @type {Array<number>} */ var offsets = [];
+ /** @type {Array<number>} */ var arrayStrides = [];
+ /** @type {Array<number>} */ var matrixStrides = [];
+ /** @type {Array<number>} */ var rowMajorFlags = [];
+
+ // Execute queries.
+ types = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_TYPE);
+ sizes = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_SIZE);
+ // Remove this: nameLengths = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_NAME_LENGTH);
+ blockIndices = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_BLOCK_INDEX);
+ offsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ arrayStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_ARRAY_STRIDE);
+ matrixStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_MATRIX_STRIDE);
+ rowMajorFlags = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_IS_ROW_MAJOR);
+
+ // Translate to LayoutEntries
+ // No resize needed. Will push them: layout.uniforms.resize(numActiveUniforms);
+ for (var uniformNdx = 0; uniformNdx < numActiveUniforms; uniformNdx++) {
+ entryUniform = new glsUniformBlockCase.UniformLayoutEntry();
+
+ // Remove this: nameLen = 0;
+ size = 0;
+ /** @type {number} */ var type = gl.NONE;
+
+ var uniform = gl.getActiveUniform(program, uniformNdx);
+
+ nameBuf = uniform.name;
+ // Remove this: nameLen = nameBuf.length;
+ size = uniform.size;
+ type = uniform.type;
+
+ // Remove this: nameLen != nameLengths[uniformNdx] ||
+ if (size != sizes[uniformNdx] ||
+ type != types[uniformNdx])
+ testFailedOptions("Values returned by gl.getActiveUniform() don't match with values queried with gl.getActiveUniforms().", true);
+
+ entryUniform.name = nameBuf;
+ entryUniform.type = gluShaderUtil.getDataTypeFromGLType(types[uniformNdx]);
+ entryUniform.size = sizes[uniformNdx];
+ entryUniform.blockNdx = blockIndices[uniformNdx];
+ entryUniform.offset = offsets[uniformNdx];
+ entryUniform.arrayStride = arrayStrides[uniformNdx];
+ entryUniform.matrixStride = matrixStrides[uniformNdx];
+ entryUniform.isRowMajor = rowMajorFlags[uniformNdx] != false;
+
+ layout.uniforms.push(entryUniform); //Pushing this uniform in the end.
+ }
+ }
+};
+
+/**
+ * glsUniformBlockCase.copyUniformData_A - Copies a source uniform buffer segment to a destination uniform buffer segment.
+ * @param {glsUniformBlockCase.UniformLayoutEntry} dstEntry
+ * @param {Uint8Array} dstBlockPtr
+ * @param {glsUniformBlockCase.UniformLayoutEntry} srcEntry
+ * @param {Uint8Array} srcBlockPtr
+ */
+glsUniformBlockCase.copyUniformData_A = function(dstEntry, dstBlockPtr, srcEntry, srcBlockPtr) {
+ /** @type {Uint8Array} */ var dstBasePtr = dstBlockPtr.subarray(dstEntry.offset);
+ /** @type {Uint8Array} */ var srcBasePtr = srcBlockPtr.subarray(srcEntry.offset);
+
+ DE_ASSERT(dstEntry.size <= srcEntry.size);
+ DE_ASSERT(dstEntry.type == srcEntry.type);
+
+ /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(dstEntry.type);
+ /** @type {boolean} */ var isMatrix = gluShaderUtil.isDataTypeMatrix(dstEntry.type);
+ /** @type {number} */ var compSize = deMath.INT32_SIZE;
+
+ for (var elementNdx = 0; elementNdx < dstEntry.size; elementNdx++) {
+ /** @type {Uint8Array} */ var dstElemPtr = dstBasePtr.subarray(elementNdx * dstEntry.arrayStride);
+ /** @type {Uint8Array} */ var srcElemPtr = srcBasePtr.subarray(elementNdx * srcEntry.arrayStride);
+
+ if (isMatrix) {
+ /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(dstEntry.type);
+ /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(dstEntry.type);
+
+ for (var colNdx = 0; colNdx < numCols; colNdx++) {
+ for (var rowNdx = 0; rowNdx < numRows; rowNdx++) {
+ var srcoffset = dstEntry.isRowMajor ? rowNdx * dstEntry.matrixStride + colNdx * compSize :
+ colNdx * dstEntry.matrixStride + rowNdx * compSize;
+ /** @type {Uint8Array} */ var dstCompPtr = dstElemPtr.subarray(srcoffset, srcoffset + compSize);
+ var dstoffset = srcEntry.isRowMajor ? rowNdx * srcEntry.matrixStride + colNdx * compSize :
+ colNdx * srcEntry.matrixStride + rowNdx * compSize;
+ /** @type {Uint8Array} */ var srcCompPtr = srcElemPtr.subarray(dstoffset, dstoffset + compSize);
+
+ //Copy byte per byte
+ for (var i = 0; i < compSize; i++)
+ dstCompPtr[i] = srcCompPtr[i];
+ }
+ }
+ } else
+ //Copy byte per byte
+ for (var i = 0; i < scalarSize * compSize; i++)
+ dstElemPtr[i] = srcElemPtr[i];
+ }
+};
+
+/**
+ * glsUniformBlockCase.copyUniformData - Copies a source uniform buffer to a destination uniform buffer.
+ * @param {glsUniformBlockCase.UniformLayout} dstLayout
+ * @param {glsUniformBlockCase.BlockPointers} dstBlockPointers
+ * @param {glsUniformBlockCase.UniformLayout} srcLayout
+ * @param {glsUniformBlockCase.BlockPointers} srcBlockPointers
+ */
+glsUniformBlockCase.copyUniformData = function(dstLayout, dstBlockPointers, srcLayout, srcBlockPointers) {
+ // \note Src layout is used as reference in case of activeUniforms happens to be incorrect in dstLayout blocks.
+ /** @type {number} */ var numBlocks = srcLayout.blocks.length;
+
+ for (var srcBlockNdx = 0; srcBlockNdx < numBlocks; srcBlockNdx++) {
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var srcBlock = srcLayout.blocks[srcBlockNdx];
+ /** @type {Uint8Array} */ var srcBlockPtr = srcBlockPointers.find(srcBlockNdx);
+ /** @type {number} */ var dstBlockNdx = dstLayout.getBlockIndex(srcBlock.name);
+ /** @type {Uint8Array} */ var dstBlockPtr = dstBlockNdx >= 0 ? dstBlockPointers.find(dstBlockNdx) : null;
+
+ if (dstBlockNdx < 0)
+ continue;
+
+ for (var srcUniformNdx = 0; srcUniformNdx < srcBlock.activeUniformIndices.length; srcUniformNdx++) {
+ /** @type {number} */ var srcUniformNdxIter = srcBlock.activeUniformIndices[srcUniformNdx];
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var srcEntry = srcLayout.uniforms[srcUniformNdxIter];
+ /** @type {number} */ var dstUniformNdx = dstLayout.getUniformIndex(srcEntry.name);
+
+ if (dstUniformNdx < 0)
+ continue;
+
+ glsUniformBlockCase.copyUniformData_A(dstLayout.uniforms[dstUniformNdx], dstBlockPtr, srcEntry, srcBlockPtr);
+ }
+ }
+};
+
+ /**
+ * TODO: Test with an actual WebGL 2.0 context
+ * iterate - The actual execution of the test.
+ * @return {tcuTestCase.IterateResult}
+ */
+ glsUniformBlockCase.UniformBlockCase.prototype.iterate = function() {
+ /** @type {glsUniformBlockCase.UniformLayout} */ var refLayout = new glsUniformBlockCase.UniformLayout(); //!< std140 layout.
+ /** @type {glsUniformBlockCase.BlockPointers} */ var blockPointers = new glsUniformBlockCase.BlockPointers();
+
+ // Compute reference layout.
+ glsUniformBlockCase.computeStd140Layout(refLayout, this.m_interface);
+
+ // Assign storage for reference values.
+ /** @type {number} */ var totalSize = 0;
+ for (var blockNdx = 0; blockNdx < refLayout.blocks.length; blockNdx++) {
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var blockIter = refLayout.blocks[blockNdx];
+ totalSize += blockIter.size;
+ }
+ blockPointers.resize(totalSize);
+
+ // Pointers for each block.
+ var curOffset = 0;
+ for (var blockNdx = 0; blockNdx < refLayout.blocks.length; blockNdx++) {
+ var size = refLayout.blocks[blockNdx].size;
+ blockPointers.push(curOffset, size);
+ curOffset += size;
+ }
+
+ // Generate values.
+ glsUniformBlockCase.generateValues(refLayout, blockPointers, 1 /* seed */);
+
+ // Generate shaders and build program.
+ /** @type {string} */ var vtxSrc = glsUniformBlockCase.generateVertexShader(this.m_interface, refLayout, blockPointers);
+ /** @type {string} */ var fragSrc = glsUniformBlockCase.generateFragmentShader(this.m_interface, refLayout, blockPointers);
+
+ /** @type {gluShaderProgram.ShaderProgram}*/ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSrc, fragSrc));
+ bufferedLogToConsole(program.getProgramInfo().infoLog);
+
+ if (!program.isOk()) {
+ // Compile failed.
+ testFailedOptions('Compile failed', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ // Query layout from GL.
+ /** @type {glsUniformBlockCase.UniformLayout} */ var glLayout = new glsUniformBlockCase.UniformLayout();
+ glsUniformBlockCase.getGLUniformLayout(gl, glLayout, program.getProgram());
+
+ // Print layout to log.
+ bufferedLogToConsole('Active glsUniformBlockCase.Uniform Blocks');
+ for (var blockNdx = 0; blockNdx < glLayout.blocks.length; blockNdx++)
+ bufferedLogToConsole(blockNdx + ': ' + glLayout.blocks[blockNdx]);
+
+ bufferedLogToConsole('Active Uniforms');
+ for (var uniformNdx = 0; uniformNdx < glLayout.uniforms.length; uniformNdx++)
+ bufferedLogToConsole(uniformNdx + ': ' + glLayout.uniforms[uniformNdx]);
+
+ // Check that we can even try rendering with given layout.
+ if (!this.checkLayoutIndices(glLayout) || !this.checkLayoutBounds(glLayout) || !this.compareTypes(refLayout, glLayout)) {
+ testFailedOptions('Invalid layout', false);
+ return tcuTestCase.IterateResult.STOP; // It is not safe to use the given layout.
+ }
+
+ // Verify all std140 blocks.
+ if (!this.compareStd140Blocks(refLayout, glLayout))
+ testFailedOptions('Invalid std140 layout', false);
+
+ // Verify all shared blocks - all uniforms should be active, and certain properties match.
+ if (!this.compareSharedBlocks(refLayout, glLayout))
+ testFailedOptions('Invalid shared layout', false);
+
+ // Check consistency with index queries
+ if (!this.checkIndexQueries(program.getProgram(), glLayout))
+ testFailedOptions('Inconsintent block index query results', false);
+
+ // Use program.
+ gl.useProgram(program.getProgram());
+
+ /** @type {number} */ var binding;
+ /** @type {WebGLBuffer} */ var buffer;
+
+ // Assign binding points to all active uniform blocks.
+ for (var blockNdx = 0; blockNdx < glLayout.blocks.length; blockNdx++) {
+ binding = blockNdx; // \todo [2012-01-25 pyry] Randomize order?
+ gl.uniformBlockBinding(program.getProgram(), blockNdx, binding);
+ }
+
+ /** @type {number} */ var numBlocks;
+ /** @type {glsUniformBlockCase.BlockPointers} */ var glBlockPointers;
+
+ // Allocate buffers, write data and bind to targets.
+ /** @type {glsUniformBlockCase.UniformBufferManager} */ var bufferManager = new glsUniformBlockCase.UniformBufferManager(gl);
+ if (this.m_bufferMode == glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK) {
+ numBlocks = glLayout.blocks.length;
+ glBlockPointers = new glsUniformBlockCase.BlockPointers();
+
+ var totalsize = 0;
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++)
+ totalsize += glLayout.blocks[blockNdx].size;
+
+ glBlockPointers.resize(totalsize);
+
+ var offset = 0;
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ glBlockPointers.push(offset, glLayout.blocks[blockNdx].size);
+ offset += glLayout.blocks[blockNdx].size;
+ }
+
+ glsUniformBlockCase.copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers);
+
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ buffer = bufferManager.allocBuffer();
+ binding = blockNdx;
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
+ gl.bufferData(gl.UNIFORM_BUFFER, glBlockPointers.find(blockNdx) /*(glw::GLsizeiptr)glData[blockNdx].size(), &glData[blockNdx][0]*/, gl.STATIC_DRAW);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, buffer);
+ }
+ } else {
+ DE_ASSERT(this.m_bufferMode == glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE);
+
+ totalSize = 0;
+ curOffset = 0;
+ numBlocks = glLayout.blocks.length;
+ /** @type {number} */ var bindingAlignment = 0;
+ glBlockPointers = new glsUniformBlockCase.BlockPointers();
+
+ bindingAlignment = /** @type {number} */ (gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT));
+
+ // Compute total size and offsets.
+ curOffset = 0;
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ if (bindingAlignment > 0)
+ curOffset = glsUniformBlockCase.deRoundUp32(curOffset, bindingAlignment);
+ glBlockPointers.push(curOffset, glLayout.blocks[blockNdx].size);
+ curOffset += glLayout.blocks[blockNdx].size;
+ }
+ totalSize = curOffset;
+ glBlockPointers.resize(totalSize);
+
+ // Copy to gl format.
+ glsUniformBlockCase.copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers);
+
+ // Allocate buffer and upload data.
+ buffer = bufferManager.allocBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
+ if (glBlockPointers.data.byteLength > 0 /*!glData.empty()*/)
+ gl.bufferData(gl.UNIFORM_BUFFER, glBlockPointers.find(blockNdx) /*(glw::GLsizeiptr)glData.size(), &glData[0]*/, gl.STATIC_DRAW);
+
+ // Bind ranges to binding points.
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ binding = blockNdx;
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, binding, buffer, glBlockPointers.offsets[blockNdx], glLayout.blocks[blockNdx].size);
+ }
+ }
+
+ /** @type {boolean} */ var renderOk = this.render(program);
+ if (!renderOk)
+ testFailedOptions('Image compare failed', false);
+ else
+ assertMsgOptions(renderOk, '', true, false);
+
+ return tcuTestCase.IterateResult.STOP;
+};
+
+/**
+* compareStd140Blocks
+* @param {glsUniformBlockCase.UniformLayout} refLayout
+* @param {glsUniformBlockCase.UniformLayout} cmpLayout
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.compareStd140Blocks = function(refLayout, cmpLayout) {
+ /**@type {boolean} */ var isOk = true;
+ /**@type {number} */ var numBlocks = this.m_interface.getNumUniformBlocks();
+
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ /**@type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.getUniformBlock(blockNdx);
+ /**@type {boolean} */ var isArray = block.isArray();
+ /**@type {string} */ var instanceName = block.getBlockName() + (isArray ? '[0]' : '');
+ /**@type {number} */ var refBlockNdx = refLayout.getBlockIndex(instanceName);
+ /**@type {number} */ var cmpBlockNdx = cmpLayout.getBlockIndex(instanceName);
+ /**@type {boolean} */ var isUsed = (block.getFlags() & (glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)) != 0;
+
+ if ((block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_STD140) == 0)
+ continue; // Not std140 layout.
+
+ DE_ASSERT(refBlockNdx >= 0);
+
+ if (cmpBlockNdx < 0) {
+ // Not found, should it?
+ if (isUsed) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform block '" + instanceName + "' not found");
+ isOk = false;
+ }
+
+ continue; // Skip block.
+ }
+
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var refBlockLayout = refLayout.blocks[refBlockNdx];
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
+
+ // \todo [2012-01-24 pyry] Verify that activeUniformIndices is correct.
+ // \todo [2012-01-24 pyry] Verify all instances.
+ if (refBlockLayout.activeUniformIndices.length != cmpBlockLayout.activeUniformIndices.length) {
+ bufferedLogToConsole("Error: Number of active uniforms differ in block '" + instanceName +
+ "' (expected " + refBlockLayout.activeUniformIndices.length +
+ ', got ' + cmpBlockLayout.activeUniformIndices.length +
+ ')');
+ isOk = false;
+ }
+
+ for (var ndx = 0; ndx < refBlockLayout.activeUniformIndices.length; ndx++) {
+ /** @type {number} */ var ndxIter = refBlockLayout.activeUniformIndices[ndx];
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var refEntry = refLayout.uniforms[ndxIter];
+ /** @type {number} */ var cmpEntryNdx = cmpLayout.getUniformIndex(refEntry.name);
+
+ if (cmpEntryNdx < 0) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + refEntry.name + "' not found");
+ isOk = false;
+ continue;
+ }
+
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var cmpEntry = cmpLayout.uniforms[cmpEntryNdx];
+
+ if (refEntry.type != cmpEntry.type ||
+ refEntry.size != cmpEntry.size ||
+ refEntry.offset != cmpEntry.offset ||
+ refEntry.arrayStride != cmpEntry.arrayStride ||
+ refEntry.matrixStride != cmpEntry.matrixStride ||
+ refEntry.isRowMajor != cmpEntry.isRowMajor) {
+ bufferedLogToConsole("Error: Layout mismatch in '" + refEntry.name + "':\n" +
+ ' expected: type = ' + gluShaderUtil.getDataTypeName(refEntry.type) + ', size = ' + refEntry.size + ', row major = ' + (refEntry.isRowMajor ? 'true' : 'false') + '\n' +
+ ' got: type = ' + gluShaderUtil.getDataTypeName(cmpEntry.type) + ', size = ' + cmpEntry.size + ', row major = ' + (cmpEntry.isRowMajor ? 'true' : 'false'));
+ isOk = false;
+ }
+ }
+ }
+
+ return isOk;
+};
+
+/**
+* compareSharedBlocks
+* @param {glsUniformBlockCase.UniformLayout} refLayout
+* @param {glsUniformBlockCase.UniformLayout} cmpLayout
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.compareSharedBlocks = function(refLayout, cmpLayout) {
+ /** @type {boolean} */ var isOk = true;
+ /** @type {number} */ var numBlocks = this.m_interface.getNumUniformBlocks();
+
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.getUniformBlock(blockNdx);
+ /** @type {boolean} */ var isArray = block.isArray();
+ /** @type {string} */ var instanceName = block.getBlockName() + (isArray ? '[0]' : '');
+ /** @type {number} */ var refBlockNdx = refLayout.getBlockIndex(instanceName);
+ /** @type {number} */ var cmpBlockNdx = cmpLayout.getBlockIndex(instanceName);
+ /** @type {boolean} */ var isUsed = (block.getFlags() & (glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)) != 0;
+
+ if ((block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_SHARED) == 0)
+ continue; // Not shared layout.
+
+ DE_ASSERT(refBlockNdx >= 0);
+
+ if (cmpBlockNdx < 0) {
+ // Not found, should it?
+ if (isUsed) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform block '" + instanceName + "' not found");
+ isOk = false;
+ }
+
+ continue; // Skip block.
+ }
+
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var refBlockLayout = refLayout.blocks[refBlockNdx];
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
+
+ if (refBlockLayout.activeUniformIndices.length != cmpBlockLayout.activeUniformIndices.length) {
+ bufferedLogToConsole("Error: Number of active uniforms differ in block '" + instanceName +
+ "' (expected " + refBlockLayout.activeUniformIndices.length +
+ ', got ' + cmpBlockLayout.activeUniformIndices.length +
+ ')');
+ isOk = false;
+ }
+
+ for (var ndx = 0; ndx < refBlockLayout.activeUniformIndices.length; ndx++) {
+ /** @type {number} */ var ndxIter = refBlockLayout.activeUniformIndices[ndx];
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var refEntry = refLayout.uniforms[ndxIter];
+ /** @type {number} */ var cmpEntryNdx = cmpLayout.getUniformIndex(refEntry.name);
+
+ if (cmpEntryNdx < 0) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + refEntry.name + "' not found");
+ isOk = false;
+ continue;
+ }
+
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var cmpEntry = cmpLayout.uniforms[cmpEntryNdx];
+
+ if (refEntry.type != cmpEntry.type ||
+ refEntry.size != cmpEntry.size ||
+ refEntry.isRowMajor != cmpEntry.isRowMajor) {
+ bufferedLogToConsole("Error: Layout mismatch in '" + refEntry.name + "':\n" +
+ ' expected: type = ' + gluShaderUtil.getDataTypeName(refEntry.type) + ', size = ' + refEntry.size + ', row major = ' + (refEntry.isRowMajor ? 'true' : 'false') + '\n' +
+ ' got: type = ' + gluShaderUtil.getDataTypeName(cmpEntry.type) + ', size = ' + cmpEntry.size + ', row major = ' + (cmpEntry.isRowMajor ? 'true' : 'false'));
+ isOk = false;
+ }
+ }
+ }
+
+ return isOk;
+};
+
+/** compareTypes
+* @param {glsUniformBlockCase.UniformLayout} refLayout
+* @param {glsUniformBlockCase.UniformLayout} cmpLayout
+* @return {boolean} true if uniform types are the same
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.compareTypes = function(refLayout, cmpLayout) {
+ /** @type {boolean} */ var isOk = true;
+ /** @type {number} */ var numBlocks = this.m_interface.getNumUniformBlocks();
+
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.getUniformBlock(blockNdx);
+ /** @type {boolean} */ var isArray = block.isArray();
+ /** @type {number} */ var numInstances = isArray ? block.getArraySize() : 1;
+
+ for (var instanceNdx = 0; instanceNdx < numInstances; instanceNdx++) {
+ /** @type {string} */ var instanceName;
+
+ instanceName += block.getBlockName();
+ if (isArray)
+ instanceName = instanceName + '[' + instanceNdx + ']';
+
+ /** @type {number} */ var cmpBlockNdx = cmpLayout.getBlockIndex(instanceName);
+
+ if (cmpBlockNdx < 0)
+ continue;
+
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
+
+ for (var ndx = 0; ndx < cmpBlockLayout.activeUniformIndices.length; ndx++) {
+ /** @type {number} */ var ndxIter = cmpBlockLayout.activeUniformIndices[ndx];
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var cmpEntry = cmpLayout.uniforms[ndxIter];
+ /** @type {number} */ var refEntryNdx = refLayout.getUniformIndex(cmpEntry.name);
+
+ if (refEntryNdx < 0) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + cmpEntry.name + "' not found in reference layout");
+ isOk = false;
+ continue;
+ }
+
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var refEntry = refLayout.uniforms[refEntryNdx];
+
+ // \todo [2012-11-26 pyry] Should we check other properties as well?
+ if (refEntry.type != cmpEntry.type) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform type mismatch in '" + refEntry.name + "':</br>" +
+ "' expected: '" + gluShaderUtil.getDataTypeName(refEntry.type) + "'</br>" +
+ "' got: '" + gluShaderUtil.getDataTypeName(cmpEntry.type) + "'");
+ isOk = false;
+ }
+ }
+ }
+ }
+
+ return isOk;
+};
+
+/** checkLayoutIndices
+* @param {glsUniformBlockCase.UniformLayout} layout Layout whose indices are to be checked
+* @return {boolean} true if all is ok
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.checkLayoutIndices = function(layout) {
+ /** @type {number} */ var numUniforms = layout.uniforms.length;
+ /** @type {number} */ var numBlocks = layout.blocks.length;
+ /** @type {boolean} */ var isOk = true;
+
+ // Check uniform block indices.
+ for (var uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++) {
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var uniform = layout.uniforms[uniformNdx];
+
+ if (uniform.blockNdx < 0 || !deMath.deInBounds32(uniform.blockNdx, 0, numBlocks)) {
+ bufferedLogToConsole("Error: Invalid block index in uniform '" + uniform.name + "'");
+ isOk = false;
+ }
+ }
+
+ // Check active uniforms.
+ for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) {
+ /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var block = layout.blocks[blockNdx];
+
+ for (var uniformNdx = 0; uniformNdx < block.activeUniformIndices.length; uniformNdx++) {
+ /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var activeUniformNdx = block.activeUniformIndices[uniformNdx];
+ if (!deMath.deInBounds32(activeUniformNdx, 0, numUniforms)) {
+ bufferedLogToConsole('Error: Invalid active uniform index ' + activeUniformNdx + " in block '" + block.name);
+ isOk = false;
+ }
+ }
+ }
+ return isOk;
+};
+
+/** checkLayoutBounds
+* @param {glsUniformBlockCase.UniformLayout} layout The uniform layout to check
+* @return {boolean} true if all is within bounds
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.checkLayoutBounds = function(layout) {
+ /** @type {number} */ var numUniforms = layout.uniforms.length;
+ /** @type {boolean}*/ var isOk = true;
+
+ for (var uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++) {
+ /** @type {glsUniformBlockCase.UniformLayoutEntry}*/ var uniform = layout.uniforms[uniformNdx];
+
+ if (uniform.blockNdx < 0)
+ continue;
+
+ /** @type {glsUniformBlockCase.BlockLayoutEntry}*/ var block = layout.blocks[uniform.blockNdx];
+ /** @type {boolean}*/ var isMatrix = gluShaderUtil.isDataTypeMatrix(uniform.type);
+ /** @type {number}*/ var numVecs = isMatrix ? (uniform.isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(uniform.type) : gluShaderUtil.getDataTypeMatrixNumColumns(uniform.type)) : 1;
+ /** @type {number}*/ var numComps = isMatrix ? (uniform.isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(uniform.type) : gluShaderUtil.getDataTypeMatrixNumRows(uniform.type)) : gluShaderUtil.getDataTypeScalarSize(uniform.type);
+ /** @type {number}*/ var numElements = uniform.size;
+ /** @type {number}*/ var compSize = deMath.INT32_SIZE;
+ /** @type {number}*/ var vecSize = numComps * compSize;
+
+ /** @type {number}*/ var minOffset = 0;
+ /** @type {number}*/ var maxOffset = 0;
+
+ // For negative strides.
+ minOffset = Math.min(minOffset, (numVecs - 1) * uniform.matrixStride);
+ minOffset = Math.min(minOffset, (numElements - 1) * uniform.arrayStride);
+ minOffset = Math.min(minOffset, (numElements - 1) * uniform.arrayStride + (numVecs - 1) * uniform.matrixStride);
+
+ maxOffset = Math.max(maxOffset, vecSize);
+ maxOffset = Math.max(maxOffset, (numVecs - 1) * uniform.matrixStride + vecSize);
+ maxOffset = Math.max(maxOffset, (numElements - 1) * uniform.arrayStride + vecSize);
+ maxOffset = Math.max(maxOffset, (numElements - 1) * uniform.arrayStride + (numVecs - 1) * uniform.matrixStride + vecSize);
+
+ if (uniform.offset + minOffset < 0 || uniform.offset + maxOffset > block.size) {
+ bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + uniform.name + "' out of block bounds");
+ isOk = false;
+ }
+ }
+
+ return isOk;
+};
+
+/** checkIndexQueries
+* @param {WebGLProgram} program The shader program to be checked against
+* @param {glsUniformBlockCase.UniformLayout} layout The layout to check
+* @return {boolean} true if everything matches.
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.checkIndexQueries = function(program, layout) {
+ /** @type {boolean}*/ var allOk = true;
+
+ // \note Spec mandates that uniform blocks are assigned consecutive locations from 0
+ // to ACTIVE_UNIFORM_BLOCKS. BlockLayoutEntries are stored in that order in glsUniformBlockCase.UniformLayout.
+ for (var blockNdx = 0; blockNdx < layout.blocks.length; blockNdx++) {
+ /** @const */ var block = layout.blocks[blockNdx];
+ /** @const */ var queriedNdx = gl.getUniformBlockIndex(program, block.name);
+
+ if (queriedNdx != blockNdx) {
+ bufferedLogToConsole('ERROR: glGetUniformBlockIndex(' + block.name + ') returned ' + queriedNdx + ', expected ' + blockNdx + '!');
+ allOk = false;
+ }
+ }
+
+ return allOk;
+};
+
+/** @const @type {number} */ glsUniformBlockCase.VIEWPORT_WIDTH = 128;
+/** @const @type {number} */ glsUniformBlockCase.VIEWPORT_HEIGHT = 128;
+
+/** Renders a white square, and then tests all pixels are
+* effectively white in the color buffer.
+* @param {gluShaderProgram.ShaderProgram} program The shader program to use.
+* @return {boolean} false if there was at least one incorrect pixel
+**/
+glsUniformBlockCase.UniformBlockCase.prototype.render = function(program) {
+ // Compute viewport.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name));
+ /** @const */ var viewportW = Math.min(gl.canvas.width, glsUniformBlockCase.VIEWPORT_WIDTH);
+ /** @const */ var viewportH = Math.min(gl.canvas.height, glsUniformBlockCase.VIEWPORT_HEIGHT);
+ /** @const */ var viewportX = rnd.getInt(0, gl.canvas.width);
+ /** @const */ var viewportY = rnd.getInt(0, gl.canvas.height);
+
+ gl.clearColor(0.125, 0.25, 0.5, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+ //Draw
+ var position = [
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0
+ ];
+ var indices = [0, 1, 2, 2, 1, 3];
+
+ gl.viewport(viewportX, viewportY, viewportW, viewportH);
+
+ // Access
+ var posLoc = gl.getAttribLocation(program.getProgram(), 'a_position');
+ var posArray = [new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, 4, position)];
+ gluDrawUtil.draw(gl, program.getProgram(), posArray, gluDrawUtil.triangles(indices));
+
+ // Verify that all pixels are white.
+ var pixels = new gluDrawUtil.Surface();
+ var numFailedPixels = 0;
+
+ var readPixelsX = (viewportX + viewportW) > gl.canvas.width
+ ? (gl.canvas.width - viewportX) : viewportW;
+ var readPixelsY = (viewportY + viewportH) > gl.canvas.height
+ ? (gl.canvas.height - viewportY) : viewportH;
+
+ var buffer = pixels.readSurface(gl, viewportX, viewportY, readPixelsX, readPixelsY);
+
+ var whitePixel = new gluDrawUtil.Pixel([255.0, 255.0, 255.0, 255.0]);
+ for (var y = 0; y < readPixelsY; y++) {
+ for (var x = 0; x < readPixelsX; x++) {
+ if (!pixels.getPixel(x, y).equals(whitePixel))
+ numFailedPixels += 1;
+ }
+ }
+
+ if (numFailedPixels > 0) {
+ bufferedLogToConsole('Image comparison failed, got ' + numFailedPixels + ' non-white pixels.');
+ }
+
+ return numFailedPixels == 0;
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsVertexArrayTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsVertexArrayTests.js
new file mode 100644
index 0000000000..99dc79f35e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsVertexArrayTests.js
@@ -0,0 +1,2534 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('modules.shared.glsVertexArrayTests');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuPixelFormat');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+ var glsVertexArrayTests = modules.shared.glsVertexArrayTests;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var tcuRGBA = framework.common.tcuRGBA;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuPixelFormat = framework.common.tcuPixelFormat;
+ var tcuSurface = framework.common.tcuSurface;
+ var tcuImageCompare = framework.common.tcuImageCompare;
+ var tcuLogImage = framework.common.tcuLogImage;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+ var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+ var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * @interface
+ */
+ glsVertexArrayTests.deArray = function() {};
+
+ /**
+ * glsVertexArrayTests.deArray.Target enum
+ * @enum
+ */
+ glsVertexArrayTests.deArray.Target = {
+ ELEMENT_ARRAY: 0,
+ ARRAY: 1
+ };
+
+ /**
+ * glsVertexArrayTests.deArray.InputType enum
+ * @enum
+ */
+ glsVertexArrayTests.deArray.InputType = {
+ FLOAT: 0,
+ /*FIXED: 1,
+ DOUBLE: 2,*/
+
+ BYTE: 1,
+ SHORT: 2,
+
+ UNSIGNED_BYTE: 3,
+ UNSIGNED_SHORT: 4,
+
+ INT: 5,
+ UNSIGNED_INT: 6,
+ HALF: 7,
+ UNSIGNED_INT_2_10_10_10: 8,
+ INT_2_10_10_10: 9
+ };
+
+ /**
+ * glsVertexArrayTests.deArray.OutputType enum
+ * @enum
+ */
+ glsVertexArrayTests.deArray.OutputType = {
+ FLOAT: 0,
+ VEC2: 1,
+ VEC3: 2,
+ VEC4: 3,
+
+ INT: 4,
+ UINT: 5,
+
+ IVEC2: 6,
+ IVEC3: 7,
+ IVEC4: 8,
+
+ UVEC2: 9,
+ UVEC3: 10,
+ UVEC4: 11
+ };
+
+ /**
+ * glsVertexArrayTests.deArray.Usage enum
+ * @enum
+ */
+ glsVertexArrayTests.deArray.Usage = {
+ DYNAMIC_DRAW: 0,
+ STATIC_DRAW: 1,
+ STREAM_DRAW: 2,
+
+ STREAM_READ: 3,
+ STREAM_COPY: 4,
+
+ STATIC_READ: 5,
+ STATIC_COPY: 6,
+
+ DYNAMIC_READ: 7,
+ DYNAMIC_COPY: 8
+ };
+
+ /**
+ * glsVertexArrayTests.deArray.Storage enum
+ * @enum
+ */
+ glsVertexArrayTests.deArray.Storage = {
+ USER: 0,
+ BUFFER: 1
+ };
+
+ /**
+ * glsVertexArrayTests.deArray.Primitive enum
+ * @enum
+ */
+ glsVertexArrayTests.deArray.Primitive = {
+ POINTS: 0,
+ TRIANGLES: 1,
+ TRIANGLE_FAN: 2,
+ TRIANGLE_STRIP: 3
+ };
+
+ //glsVertexArrayTests.deArray static functions
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ * @return {string}
+ */
+ glsVertexArrayTests.deArray.targetToString = function(target) {
+ DE_ASSERT(target < Object.keys(glsVertexArrayTests.deArray.Target).length);
+
+ /** @type {Array<string>} */ var targets =
+ [
+ 'element_array', // glsVertexArrayTests.deArray.Target.ELEMENT_ARRAY
+ 'array' // glsVertexArrayTests.deArray.Target.ARRAY
+ ];
+ DE_ASSERT(targets.length == Object.keys(glsVertexArrayTests.deArray.Target).length);
+
+ return targets[target];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {string}
+ */
+ glsVertexArrayTests.deArray.inputTypeToString = function(type) {
+ DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.InputType).length);
+
+ /** @type {Array<string>} */ var types =
+ [
+ 'float', // glsVertexArrayTests.deArray.InputType.FLOAT
+
+ 'byte', // glsVertexArrayTests.deArray.InputType.BYTE
+ 'short', // glsVertexArrayTests.deArray.InputType.SHORT
+
+ 'unsigned_byte', // glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE
+ 'unsigned_short', // glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
+
+ 'int', // glsVertexArrayTests.deArray.InputType.INT
+ 'unsigned_int', // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT
+ 'half', // glsVertexArrayTests.deArray.InputType.HALF
+ 'unsigned_int2_10_10_10', // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10
+ 'int2_10_10_10' // glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+ DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.InputType).length);
+
+ return types[type];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.OutputType} type
+ * @return {string}
+ */
+ glsVertexArrayTests.deArray.outputTypeToString = function(type) {
+ DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.OutputType).length);
+
+ /** @type {Array<string>} */ var types =
+ [
+ 'float', // glsVertexArrayTests.deArray.OutputType.FLOAT
+ 'vec2', // glsVertexArrayTests.deArray.OutputType.VEC2
+ 'vec3', // glsVertexArrayTests.deArray.OutputType.VEC3
+ 'vec4', // glsVertexArrayTests.deArray.OutputType.VEC4
+
+ 'int', // glsVertexArrayTests.deArray.OutputType.INT
+ 'uint', // glsVertexArrayTests.deArray.OutputType.UINT
+
+ 'ivec2', // glsVertexArrayTests.deArray.OutputType.IVEC2
+ 'ivec3', // glsVertexArrayTests.deArray.OutputType.IVEC3
+ 'ivec4', // glsVertexArrayTests.deArray.OutputType.IVEC4
+
+ 'uvec2', // glsVertexArrayTests.deArray.OutputType.UVEC2
+ 'uvec3', // glsVertexArrayTests.deArray.OutputType.UVEC3
+ 'uvec4' // glsVertexArrayTests.deArray.OutputType.UVEC4
+ ];
+ DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.OutputType).length);
+
+ return types[type];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Usage} usage
+ * @return {string}
+ */
+ glsVertexArrayTests.deArray.usageTypeToString = function(usage) {
+ DE_ASSERT(usage < Object.keys(glsVertexArrayTests.deArray.Usage).length);
+
+ /** @type {Array<string>} */ var usages =
+ [
+ 'dynamic_draw', // glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW
+ 'static_draw', // glsVertexArrayTests.deArray.Usage.STATIC_DRAW
+ 'stream_draw', // glsVertexArrayTests.deArray.Usage.STREAM_DRAW
+
+ 'stream_read', // glsVertexArrayTests.deArray.Usage.STREAM_READ
+ 'stream_copy', // glsVertexArrayTests.deArray.Usage.STREAM_COPY
+
+ 'static_read', // glsVertexArrayTests.deArray.Usage.STATIC_READ
+ 'static_copy', // glsVertexArrayTests.deArray.Usage.STATIC_COPY
+
+ 'dynamic_read', // glsVertexArrayTests.deArray.Usage.DYNAMIC_READ
+ 'dynamic_copy' // glsVertexArrayTests.deArray.Usage.DYNAMIC_COPY
+ ];
+ DE_ASSERT(usages.length == Object.keys(glsVertexArrayTests.deArray.Usage).length);
+
+ return usages[usage];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Storage} storage
+ * @return {string}
+ */
+ glsVertexArrayTests.deArray.storageToString = function(storage) {
+ DE_ASSERT(storage < Object.keys(glsVertexArrayTests.deArray.Storage).length);
+
+ /** @type {Array<string>} */ var storages =
+ [
+ 'user_ptr', // glsVertexArrayTests.deArray.Storage.USER
+ 'buffer' // glsVertexArrayTests.deArray.Storage.BUFFER
+ ];
+ DE_ASSERT(storages.length == Object.keys(glsVertexArrayTests.deArray.Storage).length);
+
+ return storages[storage];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @return {string}
+ */
+ glsVertexArrayTests.deArray.primitiveToString = function(primitive) {
+ DE_ASSERT(primitive < Object.keys(glsVertexArrayTests.deArray.Primitive).length);
+
+ /** @type {Array<string>} */ var primitives =
+ [
+ 'points', // glsVertexArrayTests.deArray.Primitive.POINTS
+ 'triangles', // glsVertexArrayTests.deArray.Primitive.TRIANGLES
+ 'triangle_fan', // glsVertexArrayTests.deArray.Primitive.TRIANGLE_FAN
+ 'triangle_strip' // glsVertexArrayTests.deArray.Primitive.TRIANGLE_STRIP
+ ];
+ DE_ASSERT(primitives.length == Object.keys(glsVertexArrayTests.deArray.Primitive).length);
+
+ return primitives[primitive];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {number}
+ */
+ glsVertexArrayTests.deArray.inputTypeSize = function(type) {
+ DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.InputType).length);
+
+ /** @type {Array<number>} */ var size = [
+ 4, // glsVertexArrayTests.deArray.InputType.FLOAT
+
+ 1, // glsVertexArrayTests.deArray.InputType.BYTE
+ 2, // glsVertexArrayTests.deArray.InputType.SHORT
+
+ 1, // glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE
+ 2, // glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
+
+ 4, // glsVertexArrayTests.deArray.InputType.INT
+ 4, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT
+ 2, // glsVertexArrayTests.deArray.InputType.HALF
+ 4 / 4, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10
+ 4 / 4 // glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+ DE_ASSERT(size.length == Object.keys(glsVertexArrayTests.deArray.InputType).length);
+
+ return size[type];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {boolean}
+ */
+ glsVertexArrayTests.inputTypeIsFloatType = function(type) {
+ if (type == glsVertexArrayTests.deArray.InputType.FLOAT)
+ return true;
+ /*if (type == glsVertexArrayTests.deArray.InputType.FIXED)
+ return true;
+ if (type == glsVertexArrayTests.deArray.InputType.DOUBLE)
+ return true;*/
+ if (type == glsVertexArrayTests.deArray.InputType.HALF)
+ return true;
+ return false;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.OutputType} type
+ * @return {boolean}
+ */
+ glsVertexArrayTests.outputTypeIsFloatType = function(type) {
+ if (type == glsVertexArrayTests.deArray.OutputType.FLOAT ||
+ type == glsVertexArrayTests.deArray.OutputType.VEC2 ||
+ type == glsVertexArrayTests.deArray.OutputType.VEC3 ||
+ type == glsVertexArrayTests.deArray.OutputType.VEC4)
+ return true;
+
+ return false;
+ };
+
+ //glsVertexArrayTests.deArray member functions (all virtual, since this is an interface)
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ * @param {number} size
+ * @param {Uint8Array} data
+ * @param {glsVertexArrayTests.deArray.Usage} usage
+ */
+ glsVertexArrayTests.deArray.prototype.data = function(target, size, data, usage) {};
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ * @param {number} offset
+ * @param {number} size
+ * @param {Uint8Array} data
+ */
+ glsVertexArrayTests.deArray.prototype.subdata = function(target, offset, size, data) {};
+
+ /**
+ * @param {number} attribNdx
+ * @param {number} offset
+ * @param {number} size
+ * @param {glsVertexArrayTests.deArray.InputType} inType
+ * @param {glsVertexArrayTests.deArray.OutputType} outType
+ * @param {boolean} normalized
+ * @param {number} stride
+ */
+ glsVertexArrayTests.deArray.prototype.bind = function(attribNdx, offset, size, inType, outType, normalized, stride) {};
+
+ /**
+ * unBind
+ */
+ glsVertexArrayTests.deArray.prototype.unBind = function() {};
+
+ /**
+ * @return {boolean}
+ */
+ glsVertexArrayTests.deArray.prototype.isBound = function() {};
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.deArray.prototype.getComponentCount = function() {};
+
+ /**
+ * @return {glsVertexArrayTests.deArray.Target}
+ */
+ glsVertexArrayTests.deArray.prototype.getTarget = function() {};
+
+ /**
+ * @return {glsVertexArrayTests.deArray.InputType}
+ */
+ glsVertexArrayTests.deArray.prototype.getInputType = function() {};
+
+ /**
+ * @return {glsVertexArrayTests.deArray.OutputType}
+ */
+ glsVertexArrayTests.deArray.prototype.getOutputType = function() {};
+
+ /**
+ * @return {glsVertexArrayTests.deArray.Storage}
+ */
+ glsVertexArrayTests.deArray.prototype.getStorageType = function() {};
+
+ /**
+ * @return {boolean}
+ */
+ glsVertexArrayTests.deArray.prototype.getNormalized = function() {};
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.deArray.prototype.getStride = function() {};
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.deArray.prototype.getAttribNdx = function() {};
+
+ /**
+ * @param {number} attribNdx
+ */
+ glsVertexArrayTests.deArray.prototype.setAttribNdx = function(attribNdx) {};
+
+ //glsVertexArrayTests.ContextArray class, implements glsVertexArrayTests.deArray interface
+
+ /**
+ * @constructor
+ * @implements {glsVertexArrayTests.deArray}
+ * @param {glsVertexArrayTests.deArray.Storage} storage
+ * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} context
+ */
+ glsVertexArrayTests.ContextArray = function(storage, context) {
+ /** @type {glsVertexArrayTests.deArray.Storage} */ this.m_storage = storage;
+ /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = context;
+ /** @type {WebGLBuffer|sglrReferenceContext.DataBuffer|null} */ this.m_glBuffer = null;
+
+ /** @type {boolean} */ this.m_bound = false;
+ /** @type {number} */ this.m_attribNdx = 0;
+ /** @type {number} */ this.m_size = 0;
+ /** @type {Uint8Array} */ this.m_data = null;
+ /** @type {number} */ this.m_componentCount = 1;
+ /** @type {glsVertexArrayTests.deArray.Target} */ this.m_target = glsVertexArrayTests.deArray.Target.ARRAY;
+ /** @type {glsVertexArrayTests.deArray.InputType} */ this.m_inputType = glsVertexArrayTests.deArray.InputType.FLOAT;
+ /** @type {glsVertexArrayTests.deArray.OutputType} */ this.m_outputType = glsVertexArrayTests.deArray.OutputType.FLOAT;
+ /** @type {boolean} */ this.m_normalize = false;
+ /** @type {number} */ this.m_stride = 0;
+ /** @type {number} */ this.m_offset = 0;
+
+ if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ this.m_glBuffer = this.m_ctx.createBuffer();
+ }
+ };
+
+ // glsVertexArrayTests.ContextArray member functions
+
+ /**
+ * unBind
+ */
+ glsVertexArrayTests.ContextArray.prototype.unBind = function() { this.m_bound = false; };
+
+ /**
+ * @return {boolean}
+ */
+ glsVertexArrayTests.ContextArray.prototype.isBound = function() { return this.m_bound; };
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getComponentCount = function() { return this.m_componentCount; };
+
+ /**
+ * @return {glsVertexArrayTests.deArray.Target}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getTarget = function() { return this.m_target; };
+
+ /**
+ * @return {glsVertexArrayTests.deArray.InputType}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getInputType = function() { return this.m_inputType; };
+
+ /**
+ * @return {glsVertexArrayTests.deArray.OutputType}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getOutputType = function() { return this.m_outputType; };
+
+ /**
+ * @return {glsVertexArrayTests.deArray.Storage}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getStorageType = function() { return this.m_storage; };
+
+ /**
+ * @return {boolean}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getNormalized = function() { return this.m_normalize; };
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getStride = function() { return this.m_stride; };
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.prototype.getAttribNdx = function() { return this.m_attribNdx; };
+
+ /**
+ * @param {number} attribNdx
+ */
+ glsVertexArrayTests.ContextArray.prototype.setAttribNdx = function(attribNdx) { this.m_attribNdx = attribNdx; };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {glsVertexArrayTests.deArray.Usage} usage
+ */
+ glsVertexArrayTests.ContextArray.prototype.data = function(target, size, ptr, usage) {
+ this.m_size = size;
+ this.m_target = target;
+
+ if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(target), this.m_glBuffer);
+
+ //No need for size param here, as opposed to GL ES.
+ this.m_ctx.bufferData(glsVertexArrayTests.ContextArray.targetToGL(target), ptr, glsVertexArrayTests.ContextArray.usageToGL(usage));
+ } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER) {
+ this.m_data = new Uint8Array(size);
+ for (var i = 0; i < size; i++)
+ this.m_data[i] = ptr[i];
+ } else
+ throw new Error('glsVertexArrayTests.ContextArray.prototype.data - Invalid storage type specified');
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ * @param {number} offset
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ glsVertexArrayTests.ContextArray.prototype.subdata = function(target, offset, size, ptr) {
+ this.m_target = target;
+
+ if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(target), this.m_glBuffer);
+
+ this.m_ctx.bufferSubData(glsVertexArrayTests.ContextArray.targetToGL(target), offset, ptr);
+ } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER)
+ for (var i = offset; i < size; i++)
+ this.m_data[i] = ptr[i];
+ else
+ throw new Error('glsVertexArrayTests.ContextArray.prototype.subdata - Invalid storage type specified');
+ };
+
+ /**
+ * @param {number} attribNdx
+ * @param {number} offset
+ * @param {number} size
+ * @param {glsVertexArrayTests.deArray.InputType} inType
+ * @param {glsVertexArrayTests.deArray.OutputType} outType
+ * @param {boolean} normalized
+ * @param {number} stride
+ */
+ glsVertexArrayTests.ContextArray.prototype.bind = function(attribNdx, offset, size, inType, outType, normalized, stride) {
+ this.m_attribNdx = attribNdx;
+ this.m_bound = true;
+ this.m_componentCount = size;
+ this.m_inputType = inType;
+ this.m_outputType = outType;
+ this.m_normalize = normalized;
+ this.m_stride = stride;
+ this.m_offset = offset;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ */
+ glsVertexArrayTests.ContextArray.prototype.bindIndexArray = function(target) {
+ if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER) {
+ } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(target), this.m_glBuffer);
+ }
+ };
+
+ /**
+ * @param {number} loc
+ */
+ glsVertexArrayTests.ContextArray.prototype.glBind = function(loc) {
+ if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(this.m_target), this.m_glBuffer);
+
+ if (!glsVertexArrayTests.inputTypeIsFloatType(this.m_inputType)) {
+ // Input is not float type
+
+ if (glsVertexArrayTests.outputTypeIsFloatType(this.m_outputType)) {
+ // Output type is float type
+ this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset);
+ } else {
+ // Output type is int type
+ this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_stride, this.m_offset);
+ }
+ } else {
+ // Input type is float type
+ // Output type must be float type
+ DE_ASSERT(this.m_outputType == glsVertexArrayTests.deArray.OutputType.FLOAT || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC2 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC3 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC4);
+
+ this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset);
+ }
+
+ this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(this.m_target), null);
+ } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER) {
+ this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(this.m_target), null);
+
+ if (!glsVertexArrayTests.inputTypeIsFloatType(this.m_inputType)) {
+ // Input is not float type
+
+ if (glsVertexArrayTests.outputTypeIsFloatType(this.m_outputType)) {
+ // Output type is float type
+ this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_data.subarray(this.m_offset));
+ } else {
+ // Output type is int type
+ this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_stride, this.m_data.subarray(this.m_offset));
+ }
+ } else {
+ // Input type is float type
+
+ // Output type must be float type
+ DE_ASSERT(this.m_outputType == glsVertexArrayTests.deArray.OutputType.FLOAT || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC2 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC3 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC4);
+
+ this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_data.subarray(this.m_offset));
+ }
+ } else
+ throw new Error('glsVertexArrayTests.ContextArray.prototype.glBind - Invalid storage type specified');
+ };
+
+ //glsVertexArrayTests.ContextArray static functions
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Target} target
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.targetToGL = function(target) {
+ DE_ASSERT(target < Object.keys(glsVertexArrayTests.deArray.Target).length);
+
+ /** @type {Array<number>} */ var targets =
+ [
+ gl.ELEMENT_ARRAY_BUFFER, // glsVertexArrayTests.deArray.Target.ELEMENT_ARRAY
+ gl.ARRAY_BUFFER // glsVertexArrayTests.deArray.Target.ARRAY
+ ];
+
+ return targets[target];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Usage} usage
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.usageToGL = function(usage) {
+ DE_ASSERT(usage < Object.keys(glsVertexArrayTests.deArray.Usage).length);
+
+ /** @type {Array<number>} */ var usages =
+ [
+ gl.DYNAMIC_DRAW, // glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW
+ gl.STATIC_DRAW, // glsVertexArrayTests.deArray.Usage.STATIC_DRAW
+ gl.STREAM_DRAW, // glsVertexArrayTests.deArray.Usage.STREAM_DRAW
+
+ gl.STREAM_READ, // glsVertexArrayTests.deArray.Usage.STREAM_READ
+ gl.STREAM_COPY, // glsVertexArrayTests.deArray.Usage.STREAM_COPY
+
+ gl.STATIC_READ, // glsVertexArrayTests.deArray.Usage.STATIC_READ
+ gl.STATIC_COPY, // glsVertexArrayTests.deArray.Usage.STATIC_COPY
+
+ gl.DYNAMIC_READ, // glsVertexArrayTests.deArray.Usage.DYNAMIC_READ
+ gl.DYNAMIC_COPY // glsVertexArrayTests.deArray.Usage.DYNAMIC_COPY
+ ];
+ DE_ASSERT(usages.length == Object.keys(glsVertexArrayTests.deArray.Usage).length);
+
+ return usages[usage];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.inputTypeToGL = function(type) {
+ DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.InputType).length);
+
+ /** @type {Array<number>} */ var types =
+ [
+ gl.FLOAT, // glsVertexArrayTests.deArray.InputType.FLOAT
+
+ gl.BYTE, // glsVertexArrayTests.deArray.InputType.BYTE
+ gl.SHORT, // glsVertexArrayTests.deArray.InputType.SHORT
+ gl.UNSIGNED_BYTE, // glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE
+ gl.UNSIGNED_SHORT, // glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
+
+ gl.INT, // glsVertexArrayTests.deArray.InputType.INT
+ gl.UNSIGNED_INT, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT
+ gl.HALF_FLOAT, // glsVertexArrayTests.deArray.InputType.HALF
+ gl.UNSIGNED_INT_2_10_10_10_REV, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10
+ gl.INT_2_10_10_10_REV // glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
+ ];
+ DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.InputType).length);
+
+ return types[type];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.OutputType} type
+ * @return {string}
+ */
+ glsVertexArrayTests.ContextArray.outputTypeToGLType = function(type) {
+ DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.OutputType).length);
+
+ /** @type {Array<string>} */ var types =
+ [
+ 'float', // glsVertexArrayTests.deArray.OutputType.FLOAT
+ 'vec2', // glsVertexArrayTests.deArray.OutputType.VEC2
+ 'vec3', // glsVertexArrayTests.deArray.OutputType.VEC3
+ 'vec4', // glsVertexArrayTests.deArray.OutputType.VEC4
+
+ 'int', // glsVertexArrayTests.deArray.OutputType.INT
+ 'uint', // glsVertexArrayTests.deArray.OutputType.UINT
+
+ 'ivec2', // glsVertexArrayTests.deArray.OutputType.IVEC2
+ 'ivec3', // glsVertexArrayTests.deArray.OutputType.IVEC3
+ 'ivec4', // glsVertexArrayTests.deArray.OutputType.IVEC4
+
+ 'uvec2', // glsVertexArrayTests.deArray.OutputType.UVEC2
+ 'uvec3', // glsVertexArrayTests.deArray.OutputType.UVEC3
+ 'uvec4' // glsVertexArrayTests.deArray.OutputType.UVEC4
+ ];
+ DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.OutputType).length);
+
+ return types[type];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArray.primitiveToGL = function(primitive) {
+ /** @type {Array<number>} */ var primitives =
+ [
+ gl.POINTS, // glsVertexArrayTests.deArray.Primitive.POINTS
+ gl.TRIANGLES, // glsVertexArrayTests.deArray.Primitive.TRIANGLES
+ gl.TRIANGLE_FAN, // glsVertexArrayTests.deArray.Primitive.TRIANGLE_FAN
+ gl.TRIANGLE_STRIP // glsVertexArrayTests.deArray.Primitive.TRIANGLE_STRIP
+ ];
+ DE_ASSERT(primitives.length == Object.keys(glsVertexArrayTests.deArray.Primitive).length);
+
+ return primitives[primitive];
+ };
+
+ /**
+ * @constructor
+ * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} drawContext
+ */
+ glsVertexArrayTests.ContextArrayPack = function(drawContext) {
+ /** @type {WebGLRenderingContextBase} */ this.m_renderCtx = gl;
+ //TODO: Reference rasterizer implementation.
+ /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = drawContext;
+
+ /** @type {Array<glsVertexArrayTests.ContextArray>} */ this.m_arrays = [];
+ /** @type {sglrShaderProgram.ShaderProgram} */ this.m_program;
+ /** @type {tcuSurface.Surface} */ this.m_screen = new tcuSurface.Surface(
+ Math.min(512, canvas.width),
+ Math.min(512, canvas.height)
+ );
+ };
+
+ /**
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextArrayPack.prototype.getArrayCount = function() {
+ return this.m_arrays.length;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Storage} storage
+ */
+ glsVertexArrayTests.ContextArrayPack.prototype.newArray = function(storage) {
+ this.m_arrays.push(new glsVertexArrayTests.ContextArray(storage, this.m_ctx));
+ };
+
+ /**
+ * @param {number} i
+ * @return {glsVertexArrayTests.ContextArray}
+ */
+ glsVertexArrayTests.ContextArrayPack.prototype.getArray = function(i) {
+ return this.m_arrays[i];
+ };
+
+ /**
+ * updateProgram
+ */
+ glsVertexArrayTests.ContextArrayPack.prototype.updateProgram = function() {
+ this.m_program = new glsVertexArrayTests.ContextShaderProgram(this.m_renderCtx, this.m_arrays);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @param {number} firstVertex
+ * @param {number} vertexCount
+ * @param {boolean} useVao
+ * @param {number} coordScale
+ * @param {number} colorScale
+ */
+ glsVertexArrayTests.ContextArrayPack.prototype.render = function(primitive, firstVertex, vertexCount, useVao, coordScale, colorScale) {
+ var program;
+ /** @type {(WebGLVertexArrayObject|sglrReferenceContext.VertexArray|null)} */ var vaoID = null;
+
+ this.updateProgram();
+
+ this.m_ctx.viewport(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight());
+ this.m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
+ this.m_ctx.clear(gl.COLOR_BUFFER_BIT);
+
+ program = this.m_ctx.createProgram(this.m_program);
+
+ this.m_ctx.useProgram(program);
+
+ this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(program, 'u_coordScale'), coordScale);
+ this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(program, 'u_colorScale'), colorScale);
+
+ if (useVao) {
+ vaoID = this.m_ctx.createVertexArray();
+ this.m_ctx.bindVertexArray(vaoID);
+ }
+
+ /** @type {string} */ var attribName;
+ /** @type {number} */ var loc;
+ for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
+ if (this.m_arrays[arrayNdx].isBound()) {
+ attribName = 'a_' + this.m_arrays[arrayNdx].getAttribNdx();
+ loc = this.m_ctx.getAttribLocation(program, attribName);
+ this.m_ctx.enableVertexAttribArray(loc);
+
+ this.m_arrays[arrayNdx].glBind(loc);
+ }
+ }
+
+ DE_ASSERT((firstVertex % 6) == 0);
+ //this.m_ctx.drawArrays(glsVertexArrayTests.ContextArray.primitiveToGL(primitive), firstVertex, vertexCount - firstVertex);
+ this.m_ctx.drawQuads(gl.TRIANGLES, firstVertex, vertexCount - firstVertex);
+
+ for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
+ if (this.m_arrays[arrayNdx].isBound()) {
+ attribName = 'a_' + this.m_arrays[arrayNdx].getAttribNdx();
+ loc = this.m_ctx.getAttribLocation(program, attribName);
+
+ this.m_ctx.disableVertexAttribArray(loc);
+ }
+ }
+
+ if (useVao)
+ vaoID = this.m_ctx.deleteVertexArray(vaoID);
+
+ this.m_ctx.deleteProgram(program);
+ this.m_ctx.useProgram(null);
+ this.m_ctx.readPixels(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight(), gl.RGBA, gl.UNSIGNED_BYTE, this.m_screen.getAccess().getDataPtr());
+ };
+
+ /**
+ * @return {tcuSurface.Surface}
+ */
+ glsVertexArrayTests.ContextArrayPack.prototype.getSurface = function() { return this.m_screen; };
+
+ /**
+ * glsVertexArrayTests.ContextShaderProgram class
+ * @constructor
+ * @extends {sglrShaderProgram.ShaderProgram}
+ * @param {WebGLRenderingContextBase | sglrReferenceContext.ReferenceContext} ctx
+ * @param {Array<glsVertexArrayTests.ContextArray>} arrays
+ */
+ glsVertexArrayTests.ContextShaderProgram = function(ctx, arrays) {
+ sglrShaderProgram.ShaderProgram.call(this, this.createProgramDeclaration(ctx, arrays));
+ this.m_componentCount = new Array(arrays.length);
+ /** @type {Array<rrGenericVector.GenericVecType>} */ this.m_attrType = new Array(arrays.length);
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
+ this.m_componentCount[arrayNdx] = this.getComponentCount(arrays[arrayNdx].getOutputType());
+ this.m_attrType[arrayNdx] = this.mapOutputType(arrays[arrayNdx].getOutputType());
+ }
+ };
+
+ glsVertexArrayTests.ContextShaderProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
+ glsVertexArrayTests.ContextShaderProgram.prototype.constructor = glsVertexArrayTests.ContextShaderProgram;
+
+ /**
+ * glsVertexArrayTests.calcShaderColorCoord function
+ * @param {Array<number>} coord (2 elements)
+ * @param {Array<number>} color (3 elements)
+ * @param {goog.NumberArray} attribValue (4 elements)
+ * @param {boolean} isCoordinate
+ * @param {number} numComponents
+ */
+ glsVertexArrayTests.calcShaderColorCoord = function(coord, color, attribValue, isCoordinate, numComponents) {
+ if (isCoordinate)
+ switch (numComponents) {
+ case 1:
+ coord[0] = attribValue[0];
+ coord[1] = attribValue[0];
+ break;
+ case 2:
+ coord[0] = attribValue[0];
+ coord[1] = attribValue[1];
+ break;
+ case 3:
+ coord[0] = attribValue[0] + attribValue[2];
+ coord[1] = attribValue[1];
+ break;
+ case 4:
+ coord[0] = attribValue[0] + attribValue[2];
+ coord[1] = attribValue[1] + attribValue[3];
+ break;
+ default:
+ throw new Error('glsVertexArrayTests.calcShaderColorCoord - Invalid number of components');
+ } else {
+ switch (numComponents) {
+ case 1:
+ color[0] = color[0] * attribValue[0];
+ break;
+ case 2:
+ color[0] = color[0] * attribValue[0];
+ color[1] = color[1] * attribValue[1];
+ break;
+ case 3:
+ color[0] = color[0] * attribValue[0];
+ color[1] = color[1] * attribValue[1];
+ color[2] = color[2] * attribValue[2];
+ break;
+ case 4:
+ color[0] = color[0] * attribValue[0] * attribValue[3];
+ color[1] = color[1] * attribValue[1] * attribValue[3];
+ color[2] = color[2] * attribValue[2] * attribValue[3];
+ break;
+ default:
+ throw new Error('glsVertexArrayTests.calcShaderColorCoord - Invalid number of components');
+ }
+ }
+ };
+
+ /**
+ * glsVertexArrayTests.ContextShaderProgram.shadeVertices
+ * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
+ * @param {Array<rrVertexPacket.VertexPacket>} packets
+ * @param {number} numPackets
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
+ /** @type {number} */ var u_coordScale = this.getUniformByName('u_coordScale').value[0];
+ /** @type {number} */ var u_colorScale = this.getUniformByName('u_colorScale').value[0];
+
+ for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
+ /** @type {number} */ var varyingLocColor = 0;
+
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
+
+ // Calc output color
+ /** @type {Array<number>} */ var coord = [1.0, 1.0];
+ /** @type {Array<number>} */ var color = [1.0, 1.0, 1.0];
+
+ for (var attribNdx = 0; attribNdx < this.m_attrType.length; attribNdx++) {
+ /** @type {number} */ var numComponents = this.m_componentCount[attribNdx];
+
+ glsVertexArrayTests.calcShaderColorCoord(coord, color, rrVertexAttrib.readVertexAttrib(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx, this.m_attrType[attribNdx]), attribNdx == 0, numComponents);
+ }
+
+ // Transform position
+ packet.position = [u_coordScale * coord[0], u_coordScale * coord[1], 1.0, 1.0];
+
+ // Pass color to FS
+ packet.outputs[varyingLocColor] = [u_colorScale * color[0], u_colorScale * color[1], u_colorScale * color[2], 1.0];
+ }
+ };
+
+ /**
+ * @param {Array<rrFragmentOperations.Fragment>} packets
+ * @param {rrShadingContext.FragmentShadingContext} context
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.shadeFragments = function(packets, context) {
+ var varyingLocColor = 0;
+
+ // Normal shading
+ for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx)
+ packets[packetNdx].value = rrShadingContext.readTriangleVarying(packets[packetNdx], context, varyingLocColor);
+ };
+
+ /**
+ * @param {Array<glsVertexArrayTests.ContextArray>} arrays
+ * @return string
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.genVertexSource = function(arrays) {
+ var vertexShaderSrc = '';
+ var params = [];
+
+ params['VTX_IN'] = 'in';
+ params['VTX_OUT'] = 'out';
+ params['FRAG_IN'] = 'in';
+ params['FRAG_COLOR'] = 'dEQP_FragColor';
+ params['VTX_HDR'] = '#version 300 es\n';
+ params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+
+ vertexShaderSrc += params['VTX_HDR'];
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
+ vertexShaderSrc += params['VTX_IN'] + ' highp ' + glsVertexArrayTests.ContextArray.outputTypeToGLType(arrays[arrayNdx].getOutputType()) + ' a_' + arrays[arrayNdx].getAttribNdx() + ';\n';
+ }
+
+ vertexShaderSrc +=
+ 'uniform highp float u_coordScale;\n' +
+ 'uniform highp float u_colorScale;\n' +
+ params['VTX_OUT'] + ' mediump vec4 v_color;\n' +
+ 'void main(void)\n' +
+ ' {\n' +
+ '\tgl_PointSize = 1.0;\n' +
+ '\thighp vec2 coord = vec2(1.0, 1.0);\n' +
+ '\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n';
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
+ if (arrays[arrayNdx].getAttribNdx() == 0) {
+ switch (arrays[arrayNdx].getOutputType()) {
+ case (glsVertexArrayTests.deArray.OutputType.FLOAT):
+ vertexShaderSrc +=
+ '\tcoord = vec2(a_0);\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC2):
+ vertexShaderSrc +=
+ '\tcoord = a_0.xy;\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC3):
+ vertexShaderSrc +=
+ '\tcoord = a_0.xy;\n' +
+ '\tcoord.x = coord.x + a_0.z;\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC4):
+ vertexShaderSrc +=
+ '\tcoord = a_0.xy;\n' +
+ '\tcoord += a_0.zw;\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.IVEC2):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC2):
+ vertexShaderSrc +=
+ '\tcoord = vec2(a_0.xy);\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.IVEC3):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC3):
+ vertexShaderSrc +=
+ '\tcoord = vec2(a_0.xy);\n' +
+ '\tcoord.x = coord.x + float(a_0.z);\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.IVEC4):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC4):
+ vertexShaderSrc +=
+ '\tcoord = vec2(a_0.xy);\n' +
+ '\tcoord += vec2(a_0.zw);\n';
+ break;
+
+ default:
+ throw new Error('Invalid output type');
+ break;
+ }
+ continue;
+ }
+
+ switch (arrays[arrayNdx].getOutputType()) {
+ case (glsVertexArrayTests.deArray.OutputType.FLOAT):
+ vertexShaderSrc +=
+ '\tcolor = color * a_' + arrays[arrayNdx].getAttribNdx() + ';\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC2):
+ vertexShaderSrc +=
+ '\tcolor.rg = color.rg * a_' + arrays[arrayNdx].getAttribNdx() + '.xy;\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC3):
+ vertexShaderSrc +=
+ '\tcolor = color.rgb * a_' + arrays[arrayNdx].getAttribNdx() + '.xyz;\n';
+ break;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC4):
+ vertexShaderSrc +=
+ '\tcolor = color.rgb * a_' + arrays[arrayNdx].getAttribNdx() + '.xyz * a_' + arrays[arrayNdx].getAttribNdx() + '.w;\n';
+ break;
+
+ default:
+ throw new Error('Invalid output type');
+ break;
+ }
+ }
+
+ vertexShaderSrc +=
+ '\tv_color = vec4(u_colorScale * color, 1.0);\n' +
+ '\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n' +
+ '}\n';
+
+ return vertexShaderSrc;
+ };
+
+ /**
+ * @return {string}
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.genFragmentSource = function() {
+ var params = [];
+
+ params['VTX_IN'] = 'in';
+ params['VTX_OUT'] = 'out';
+ params['FRAG_IN'] = 'in';
+ params['FRAG_COLOR'] = 'dEQP_FragColor';
+ params['VTX_HDR'] = '#version 300 es\n';
+ params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
+
+ /* TODO: Check if glsl supported version check function is needed.*/
+
+ var fragmentShaderSrc = params['FRAG_HDR'] +
+ params['FRAG_IN'] + ' mediump vec4 v_color;\n' +
+ 'void main(void)\n' +
+ ' {\n' +
+ '\t' + params['FRAG_COLOR'] + ' = v_color;\n' +
+ '}\n';
+
+ return fragmentShaderSrc;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.OutputType} type
+ * @return {rrGenericVector.GenericVecType}
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.mapOutputType = function(type) {
+ switch (type) {
+ case (glsVertexArrayTests.deArray.OutputType.FLOAT):
+ case (glsVertexArrayTests.deArray.OutputType.VEC2):
+ case (glsVertexArrayTests.deArray.OutputType.VEC3):
+ case (glsVertexArrayTests.deArray.OutputType.VEC4):
+ return rrGenericVector.GenericVecType.FLOAT;
+
+ case (glsVertexArrayTests.deArray.OutputType.INT):
+ case (glsVertexArrayTests.deArray.OutputType.IVEC2):
+ case (glsVertexArrayTests.deArray.OutputType.IVEC3):
+ case (glsVertexArrayTests.deArray.OutputType.IVEC4):
+ return rrGenericVector.GenericVecType.INT32;
+
+ case (glsVertexArrayTests.deArray.OutputType.UINT):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC2):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC3):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC4):
+ return rrGenericVector.GenericVecType.UINT32;
+
+ default:
+ throw new Error('Invalid output type');
+ }
+ };
+
+ /**
+ * @param {glsVertexArrayTests.deArray.OutputType} type
+ * @return {number}
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.getComponentCount = function(type) {
+ switch (type) {
+ case (glsVertexArrayTests.deArray.OutputType.FLOAT):
+ case (glsVertexArrayTests.deArray.OutputType.INT):
+ case (glsVertexArrayTests.deArray.OutputType.UINT):
+ return 1;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC2):
+ case (glsVertexArrayTests.deArray.OutputType.IVEC2):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC2):
+ return 2;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC3):
+ case (glsVertexArrayTests.deArray.OutputType.IVEC3):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC3):
+ return 3;
+
+ case (glsVertexArrayTests.deArray.OutputType.VEC4):
+ case (glsVertexArrayTests.deArray.OutputType.IVEC4):
+ case (glsVertexArrayTests.deArray.OutputType.UVEC4):
+ return 4;
+
+ default:
+ throw new Error('Invalid output type');
+ }
+ };
+
+ /**
+ * @param {WebGLRenderingContextBase | sglrReferenceContext.ReferenceContext} ctx
+ * @param {Array<glsVertexArrayTests.ContextArray>} arrays
+ * @return {sglrShaderProgram.ShaderProgramDeclaration}
+ */
+ glsVertexArrayTests.ContextShaderProgram.prototype.createProgramDeclaration = function(ctx, arrays) {
+ /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
+
+ for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++)
+ decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_' + arrayNdx, this.mapOutputType(arrays[arrayNdx].getOutputType())));
+
+ decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
+ decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
+
+ decl.pushVertexSource(new sglrShaderProgram.VertexSource(this.genVertexSource(/*ctx,*/ arrays))); //TODO: Check if we need to review the support of a given GLSL version (we'd need the ctx)
+ decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(this.genFragmentSource(/*ctx*/)));
+
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_coordScale', gluShaderUtil.DataType.FLOAT));
+ decl.pushUniform(new sglrShaderProgram.Uniform('u_colorScale', gluShaderUtil.DataType.FLOAT));
+
+ return decl;
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue class
+ * @constructor
+ */
+ glsVertexArrayTests.GLValue = function() {
+ /** @type {goog.NumberArray} */ this.m_value = [0];
+ /** @type {glsVertexArrayTests.deArray.InputType} */ this.m_type;
+ };
+
+ /**
+ * @param {Uint8Array} dst
+ * @param {glsVertexArrayTests.GLValue} val
+ */
+ glsVertexArrayTests.copyGLValueToArray = function(dst, val) {
+ /** @type {Uint8Array} */ var val8 = new Uint8Array(val.m_value.buffer); // TODO: Fix encapsulation issue
+ dst.set(val8);
+ };
+
+ /**
+ * @param {Uint8Array} dst
+ * @param {goog.NumberArray} src
+ */
+ glsVertexArrayTests.copyArray = function(dst, src) {
+ /** @type {Uint8Array} */ var src8 = new Uint8Array(src.buffer).subarray(src.byteOffset, src.byteOffset + src.byteLength); // TODO: Fix encapsulation issue
+ dst.set(src8);
+ };
+
+ /**
+ * typeToTypedArray function. Determines which type of array will store the value, and stores it.
+ * @param {number} value
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ glsVertexArrayTests.GLValue.typeToTypedArray = function(value, type) {
+ var array;
+
+ switch (type) {
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ array = new Float32Array(1);
+ break;
+ /*case glsVertexArrayTests.deArray.InputType.FIXED:
+ array = new Int32Array(1);
+ break;
+ case glsVertexArrayTests.deArray.InputType.DOUBLE:
+ array = new Float32Array(1); // 64-bit?
+ break;*/
+
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ array = new Int8Array(1);
+ break;
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ array = new Int16Array(1);
+ break;
+
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ array = new Uint8Array(1);
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ array = new Uint16Array(1);
+ break;
+
+ case glsVertexArrayTests.deArray.InputType.INT:
+ array = new Int32Array(1);
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
+ array = new Uint32Array(1);
+ break;
+ case glsVertexArrayTests.deArray.InputType.HALF:
+ array = new Uint16Array(1);
+ value = glsVertexArrayTests.GLValue.floatToHalf(value);
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10:
+ array = new Uint32Array(1);
+ break;
+ case glsVertexArrayTests.deArray.InputType.INT_2_10_10_10:
+ array = new Int32Array(1);
+ break;
+ default:
+ throw new Error('glsVertexArrayTests.GLValue.typeToTypedArray - Invalid InputType');
+ }
+
+ array[0] = value;
+ return array;
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.create
+ * @param {number} value
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ */
+ glsVertexArrayTests.GLValue.create = function(value, type) {
+ var v = new glsVertexArrayTests.GLValue();
+ v.m_value = glsVertexArrayTests.GLValue.typeToTypedArray(value, type);
+ v.m_type = type;
+ return v;
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.halfToFloat
+ * @param {number} value
+ * @return {number}
+ */
+ glsVertexArrayTests.GLValue.halfToFloat = function(value) {
+ return tcuFloat.halfFloatToNumberNoDenorm(value);
+ };
+
+ /**
+ * @param {number} f
+ * @return {number}
+ */
+ glsVertexArrayTests.GLValue.floatToHalf = function(f) {
+ // No denorm support.
+ return tcuFloat.numberToHalfFloatNoDenorm(f);
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.getMaxValue
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.getMaxValue = function(type) {
+ var value;
+
+ switch (type) {
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ value = 127;
+ break;
+ /*case glsVertexArrayTests.deArray.InputType.FIXED:
+ value = 32760;
+ break;
+ case glsVertexArrayTests.deArray.InputType.DOUBLE:
+ value = 127;
+ break;*/
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ value = 127;
+ break;
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ value = 32760;
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ value = 255;
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ value = 65530;
+ break;
+ case glsVertexArrayTests.deArray.InputType.INT:
+ value = 2147483647;
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
+ value = 4294967295;
+ break;
+ case glsVertexArrayTests.deArray.InputType.HALF:
+ value = 256;
+ break;
+ default: //Original code returns garbage-filled GLValues
+ return new glsVertexArrayTests.GLValue();
+ }
+
+ return glsVertexArrayTests.GLValue.create(value, type);
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.getMinValue
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.getMinValue = function(type) {
+ var value;
+
+ switch (type) {
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ value = -127;
+ break;
+ /*case glsVertexArrayTests.deArray.InputType.FIXED:
+ value = -32760;
+ break;
+ case glsVertexArrayTests.deArray.InputType.DOUBLE:
+ value = -127;
+ break;*/
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ value = -127;
+ break;
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ value = -32760;
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ value = 0;
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ value = 0;
+ break;
+ case glsVertexArrayTests.deArray.InputType.INT:
+ value = -2147483647;
+ break;
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
+ value = 0;
+ break;
+ case glsVertexArrayTests.deArray.InputType.HALF:
+ value = -256;
+ break;
+
+ default: //Original code returns garbage-filled GLValues
+ return new glsVertexArrayTests.GLValue();
+ }
+
+ return glsVertexArrayTests.GLValue.create(value, type);
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.getRandom
+ * @param {deRandom.Random} rnd
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.getRandom = function(rnd, min, max) {
+ DE_ASSERT(min.getType() == max.getType());
+
+ var minv = min.interpret();
+ var maxv = max.interpret();
+ var type = min.getType();
+ var value;
+
+ if (maxv < minv)
+ return min;
+
+ switch (type) {
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ //case glsVertexArrayTests.deArray.InputType.DOUBLE:
+ case glsVertexArrayTests.deArray.InputType.HALF: {
+ return glsVertexArrayTests.GLValue.create(minv + rnd.getFloat() * (maxv - minv), type);
+ break;
+ }
+
+ /*case glsVertexArrayTests.deArray.InputType.FIXED: {
+ return minv == maxv ? min : glsVertexArrayTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type);
+ break;
+ }*/
+
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ case glsVertexArrayTests.deArray.InputType.INT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT: {
+ return glsVertexArrayTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type);
+ break;
+ }
+
+ default:
+ throw new Error('glsVertexArrayTests.GLValue.getRandom - Invalid input type');
+ break;
+ }
+ };
+
+ // Minimum difference required between coordinates
+
+ /**
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.minValue = function(type) {
+ switch (type) {
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ case glsVertexArrayTests.deArray.InputType.HALF:
+ //case glsVertexArrayTests.deArray.InputType.DOUBLE:
+ return glsVertexArrayTests.GLValue.create(4, type);
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ return glsVertexArrayTests.GLValue.create(4 * 256, type);
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ return glsVertexArrayTests.GLValue.create(4 * 2, type);
+ /*case glsVertexArrayTests.deArray.InputType.FIXED:
+ return glsVertexArrayTests.GLValue.create(4 * 512, type);*/
+ case glsVertexArrayTests.deArray.InputType.INT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
+ return glsVertexArrayTests.GLValue.create(4 * 16777216, type);
+
+ default:
+ throw new Error('glsVertexArrayTests.GLValue.minValue - Invalid input type');
+ }
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} val
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.abs = function(val) {
+ var type = val.getType();
+ switch (type) {
+ //case glsVertexArrayTests.deArray.InputType.FIXED:
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ return glsVertexArrayTests.GLValue.create(0x7FFF & val.getValue(), type);
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ return glsVertexArrayTests.GLValue.create(0x7F & val.getValue(), type);
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
+ return val;
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ case glsVertexArrayTests.deArray.InputType.HALF:
+ //case glsVertexArrayTests.deArray.InputType.DOUBLE:
+ return glsVertexArrayTests.GLValue.create(Math.abs(val.interpret()), type);
+ case glsVertexArrayTests.deArray.InputType.INT:
+ return glsVertexArrayTests.GLValue.create(0x7FFFFFFF & val.getValue(), type);
+ default:
+ throw new Error('glsVertexArrayTests.GLValue.abs - Invalid input type');
+ }
+ };
+
+ /**
+ * @return {glsVertexArrayTests.deArray.InputType}
+ */
+ glsVertexArrayTests.GLValue.prototype.getType = function() {
+ return this.m_type;
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.toFloat
+ * @return {number}
+ */
+ glsVertexArrayTests.GLValue.prototype.toFloat = function() {
+ return this.interpret();
+ };
+
+ /**
+ * glsVertexArrayTests.GLValue.getValue
+ * @return {number}
+ */
+ glsVertexArrayTests.GLValue.prototype.getValue = function() {
+ return this.m_value[0];
+ };
+
+ /**
+ * interpret function. Returns the m_value as a quantity so arithmetic operations can be performed on it
+ * Only some types require this.
+ * @return {number}
+ */
+ glsVertexArrayTests.GLValue.prototype.interpret = function() {
+ if (this.m_type == glsVertexArrayTests.deArray.InputType.HALF)
+ return glsVertexArrayTests.GLValue.halfToFloat(this.m_value[0]);
+ /*else if (this.m_type == glsVertexArrayTests.deArray.InputType.FIXED) {
+ var maxValue = 65536;
+ return Math.floor((2 * this.m_value[0] + 1) / (maxValue - 1));
+ }*/
+
+ return this.m_value[0];
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.add = function(other) {
+ return glsVertexArrayTests.GLValue.create(this.interpret() + other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.mul = function(other) {
+ return glsVertexArrayTests.GLValue.create(this.interpret() * other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.div = function(other) {
+ return glsVertexArrayTests.GLValue.create(this.interpret() / other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.sub = function(other) {
+ return glsVertexArrayTests.GLValue.create(this.interpret() - other.interpret(), this.m_type);
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.addToSelf = function(other) {
+ this.m_value[0] = this.interpret() + other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.subToSelf = function(other) {
+ this.m_value[0] = this.interpret() - other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.mulToSelf = function(other) {
+ this.m_value[0] = this.interpret() * other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {glsVertexArrayTests.GLValue}
+ */
+ glsVertexArrayTests.GLValue.prototype.divToSelf = function(other) {
+ this.m_value[0] = this.interpret() / other.interpret();
+ return this;
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {boolean}
+ */
+ glsVertexArrayTests.GLValue.prototype.equals = function(other) {
+ return this.m_value[0] == other.getValue();
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {boolean}
+ */
+ glsVertexArrayTests.GLValue.prototype.lessThan = function(other) {
+ return this.interpret() < other.interpret();
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {boolean}
+ */
+ glsVertexArrayTests.GLValue.prototype.greaterThan = function(other) {
+ return this.interpret() > other.interpret();
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {boolean}
+ */
+ glsVertexArrayTests.GLValue.prototype.lessOrEqualThan = function(other) {
+ return this.interpret() <= other.interpret();
+ };
+
+ /**
+ * @param {glsVertexArrayTests.GLValue} other
+ * @return {boolean}
+ */
+ glsVertexArrayTests.GLValue.prototype.greaterOrEqualThan = function(other) {
+ return this.interpret() >= other.interpret();
+ };
+
+ /**
+ * glsVertexArrayTests.RandomArrayGenerator class. Contains static methods only
+ */
+ glsVertexArrayTests.RandomArrayGenerator = function() {};
+
+ /**
+ * glsVertexArrayTests.RandomArrayGenerator.setData
+ * @param {Uint8Array} data
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @param {deRandom.Random} rnd
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ */
+ glsVertexArrayTests.RandomArrayGenerator.setData = function(data, type, rnd, min, max) {
+ // Parameter type is not necessary, but we'll use it to assert the created glsVertexArrayTests.GLValue is of the correct type.
+ /** @type {glsVertexArrayTests.GLValue} */ var value = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
+ DE_ASSERT(value.getType() == type);
+
+ glsVertexArrayTests.copyGLValueToArray(data, value);
+ };
+
+ /**
+ * generateArray
+ * @param {number} seed
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ * @param {number} count
+ * @param {number} componentCount
+ * @param {number} stride
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @return {ArrayBuffer}
+ */
+ glsVertexArrayTests.RandomArrayGenerator.generateArray = function(seed, min, max, count, componentCount, stride, type) {
+ /** @type {ArrayBuffer} */ var data;
+ /** @type {Uint8Array} */ var data8;
+
+ var rnd = new deRandom.Random(seed);
+
+ if (stride == 0)
+ stride = componentCount * glsVertexArrayTests.deArray.inputTypeSize(type);
+
+ data = new ArrayBuffer(stride * count);
+ data8 = new Uint8Array(data);
+
+ for (var vertexNdx = 0; vertexNdx < count; vertexNdx++) {
+ for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
+ glsVertexArrayTests.RandomArrayGenerator.setData(data8.subarray(vertexNdx * stride + glsVertexArrayTests.deArray.inputTypeSize(type) * componentNdx), type, rnd, min, max);
+ }
+ }
+
+ return data;
+ };
+
+ /* {
+ static char* generateQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, glsVertexArrayTests.GLValue min, glsVertexArrayTests.GLValue max);
+ static char* generatePerQuad (int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, glsVertexArrayTests.GLValue min, glsVertexArrayTests.GLValue max);
+
+ private:
+ template<typename T>
+ static char* createQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max);
+ template<typename T>
+ static char* createPerQuads (int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max);
+ static char* createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive);
+ };*/
+
+ /**
+ * @param {number} seed
+ * @param {number} count
+ * @param {number} componentCount
+ * @param {number} offset
+ * @param {number} stride
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ * @param {number} scale Coordinate scaling factor
+ * @return {ArrayBuffer}
+ */
+ glsVertexArrayTests.RandomArrayGenerator.generateQuads = function(seed, count, componentCount, offset, stride, primitive, type, min, max, scale) {
+ /** @type {ArrayBuffer} */ var data;
+
+ switch (type) {
+ case glsVertexArrayTests.deArray.InputType.FLOAT:
+ /*case glsVertexArrayTests.deArray.InputType.FIXED:
+ case glsVertexArrayTests.deArray.InputType.DOUBLE:*/
+ case glsVertexArrayTests.deArray.InputType.BYTE:
+ case glsVertexArrayTests.deArray.InputType.SHORT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
+ case glsVertexArrayTests.deArray.InputType.INT:
+ case glsVertexArrayTests.deArray.InputType.HALF:
+ data = glsVertexArrayTests.RandomArrayGenerator.createQuads(seed, count, componentCount, offset, stride, primitive, min, max, scale);
+ break;
+
+ case glsVertexArrayTests.deArray.InputType.INT_2_10_10_10:
+ case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10:
+ data = glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked(seed, count, componentCount, offset, stride, primitive);
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.RandomArrayGenerator.generateQuads - Invalid input type');
+ break;
+ }
+
+ return data;
+ };
+
+ /**
+ * @param {number} seed
+ * @param {number} count
+ * @param {number} componentCount
+ * @param {number} offset
+ * @param {number} stride
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @return {ArrayBuffer}
+ */
+ glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked = function(seed, count, componentCount, offset, stride, primitive) {
+ DE_ASSERT(componentCount == 4);
+
+ /** @type {number} */ var quadStride = 0;
+
+ if (stride == 0)
+ stride = deMath.INT32_SIZE;
+
+ switch (primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
+ quadStride = stride * 6;
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked - Invalid primitive');
+ break;
+ }
+
+ /** @type {ArrayBuffer} */ var _data = new ArrayBuffer(offset + quadStride * (count - 1) + stride * 5 + componentCount * glsVertexArrayTests.deArray.inputTypeSize(glsVertexArrayTests.deArray.InputType.INT_2_10_10_10)); // last element must be fully in the array
+ /** @type {Uint8Array} */ var resultData = new Uint8Array(_data).subarray(offset);
+
+ /** @type {number} */ var max = 1024;
+ /** @type {number} */ var min = 10;
+ /** @type {number} */ var max2 = 4;
+
+ var rnd = new deRandom.Random(seed);
+
+ switch (primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES: {
+ for (var quadNdx = 0; quadNdx < count; quadNdx++) {
+ /** @type {number} */ var x1 = min + rnd.getInt() % (max - min);
+ /** @type {number} */ var x2 = min + rnd.getInt() % (max - x1);
+
+ /** @type {number} */ var y1 = min + rnd.getInt() % (max - min);
+ /** @type {number} */ var y2 = min + rnd.getInt() % (max - y1);
+
+ /** @type {number} */ var z = min + rnd.getInt() % (max - min);
+ /** @type {number} */ var w = rnd.getInt() % max2;
+
+ /** @type {number} */ var val1 = (w << 30) | (z << 20) | (y1 << 10) | x1;
+ /** @type {number} */ var val2 = (w << 30) | (z << 20) | (y1 << 10) | x2;
+ /** @type {number} */ var val3 = (w << 30) | (z << 20) | (y2 << 10) | x1;
+
+ /** @type {number} */ var val4 = (w << 30) | (z << 20) | (y2 << 10) | x1;
+ /** @type {number} */ var val5 = (w << 30) | (z << 20) | (y1 << 10) | x2;
+ /** @type {number} */ var val6 = (w << 30) | (z << 20) | (y2 << 10) | x2;
+
+ glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 0), new Uint32Array([val1]));
+ glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 1), new Uint32Array([val2]));
+ glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 2), new Uint32Array([val3]));
+ glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 3), new Uint32Array([val4]));
+ glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 4), new Uint32Array([val5]));
+ glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 5), new Uint32Array([val6]));
+ }
+
+ break;
+ }
+
+ default:
+ throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked - Invalid primitive');
+ break;
+ }
+
+ return _data;
+ };
+
+ /**
+ * @param {number} seed
+ * @param {number} count
+ * @param {number} componentCount
+ * @param {number} offset
+ * @param {number} stride
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ * @param {number} scale Coordinate scaling factor
+ * @return {ArrayBuffer}
+ */
+ glsVertexArrayTests.RandomArrayGenerator.createQuads = function(seed, count, componentCount, offset, stride, primitive, min, max, scale) {
+ var componentStride = min.m_value.byteLength; //TODO: Fix encapsulation issue
+ var quadStride = 0;
+ var type = min.getType(); //Instead of using the template parameter.
+
+ if (stride == 0)
+ stride = componentCount * componentStride;
+ DE_ASSERT(stride >= componentCount * componentStride);
+
+ switch (primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
+ quadStride = stride * 6;
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuads - Invalid primitive');
+ break;
+ }
+
+ /** @type {ArrayBuffer} */ var _data = new ArrayBuffer(offset + quadStride * count);
+ /** @type {Uint8Array} */ var resultData = new Uint8Array(_data).subarray(offset);
+
+ var rnd = new deRandom.Random(seed);
+
+ switch (primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES: {
+ for (var quadNdx = 0; quadNdx < count; ++quadNdx) {
+ /** @type {glsVertexArrayTests.GLValue} */ var x1 = null;
+ /** @type {glsVertexArrayTests.GLValue} */ var x2 = null;
+ /** @type {glsVertexArrayTests.GLValue} */ var y1 = null;
+ /** @type {glsVertexArrayTests.GLValue} */ var y2 = null;
+ /** @type {glsVertexArrayTests.GLValue} */ var z = null;
+ /** @type {glsVertexArrayTests.GLValue} */ var w = null;
+
+ // attempt to find a good (i.e not extremely small) quad
+ for (var attemptNdx = 0; attemptNdx < 4; ++attemptNdx) {
+ x1 = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
+ x2 = glsVertexArrayTests.GLValue.getRandom(rnd, glsVertexArrayTests.GLValue.minValue(type), glsVertexArrayTests.GLValue.abs(max.sub(x1)));
+
+ y1 = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
+ y2 = glsVertexArrayTests.GLValue.getRandom(rnd, glsVertexArrayTests.GLValue.minValue(type), glsVertexArrayTests.GLValue.abs(max.sub(y1)));
+
+ z = (componentCount > 2) ? (glsVertexArrayTests.GLValue.getRandom(rnd, min, max)) : (glsVertexArrayTests.GLValue.create(0, type));
+ w = (componentCount > 3) ? (glsVertexArrayTests.GLValue.getRandom(rnd, min, max)) : (glsVertexArrayTests.GLValue.create(1, type));
+
+ // no additional components, all is good
+ if (componentCount <= 2)
+ break;
+
+ // The result quad is too thin?
+ if ((Math.abs(x2.interpret() + z.interpret()) < glsVertexArrayTests.GLValue.minValue(type).interpret()) ||
+ (Math.abs(y2.interpret() + w.interpret()) < glsVertexArrayTests.GLValue.minValue(type).interpret()))
+ continue;
+
+ // all ok
+ break;
+ }
+
+ x2 = x1.add(x2);
+ y2 = y1.add(y2);
+
+ /**
+ * Transform GL vertex coordinates so that after vertex shading the vertices will be rounded.
+ * We want to avoid quads that cover a pixel partially
+ */
+ var round = function(pos, scale, offset, range) {
+ // Perform the same transformation as the vertex shader
+ var val = (pos.interpret() + offset) * scale;
+ var half = range / 2;
+ val = val * half + half;
+ // Round it
+ val = Math.round(val);
+ // And reverse the vertex shading transformation
+ val = (val - half) / half;
+ val = val / scale - offset;
+ return glsVertexArrayTests.GLValue.create(val, pos.m_type);
+ };
+
+ var viewport = gl.getParameter(gl.VIEWPORT);
+ var voffset = 0;
+ if (componentCount > 2)
+ voffset = z.interpret();
+ x1 = round(x1, scale, voffset, viewport[2]);
+ x2 = round(x2, scale, voffset, viewport[2]);
+ voffset = 1;
+ if (componentCount > 3)
+ voffset = w.interpret();
+ y1 = round(y1, scale, voffset, viewport[3]);
+ y2 = round(y2, scale, voffset, viewport[3]);
+
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride), x1);
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + componentStride), y1);
+
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride), x2);
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride + componentStride), y1);
+
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 2), x1);
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 2 + componentStride), y2);
+
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 3), x1);
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 3 + componentStride), y2);
+
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 4), x2);
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 4 + componentStride), y1);
+
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 5), x2);
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 5 + componentStride), y2);
+
+ if (componentCount > 2) {
+ for (var i = 0; i < 6; i++)
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * i + componentStride * 2), z);
+ }
+
+ if (componentCount > 3) {
+ for (var i = 0; i < 6; i++)
+ glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * i + componentStride * 3), w);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuads - Invalid primitive');
+ break;
+ }
+
+ return _data;
+ };
+
+ /**
+ * @param {number} seed
+ * @param {number} count
+ * @param {number} componentCount
+ * @param {number} stride
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @param {glsVertexArrayTests.deArray.InputType} type
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ */
+ glsVertexArrayTests.RandomArrayGenerator.generatePerQuad = function(seed, count, componentCount, stride, primitive, type, min, max) {
+ /** @type {ArrayBuffer} */ var data = null;
+
+ data = glsVertexArrayTests.RandomArrayGenerator.createPerQuads(seed, count, componentCount, stride, primitive, min, max);
+ return data;
+ };
+
+ /**
+ * @param {number} seed
+ * @param {number} count
+ * @param {number} componentCount
+ * @param {number} stride
+ * @param {glsVertexArrayTests.deArray.Primitive} primitive
+ * @param {glsVertexArrayTests.GLValue} min
+ * @param {glsVertexArrayTests.GLValue} max
+ */
+ glsVertexArrayTests.RandomArrayGenerator.createPerQuads = function(seed, count, componentCount, stride, primitive, min, max) {
+ var rnd = new deRandom.Random(seed);
+
+ var componentStride = min.m_value.byteLength; //TODO: Fix encapsulation issue.
+
+ if (stride == 0)
+ stride = componentStride * componentCount;
+
+ var quadStride = 0;
+
+ switch (primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
+ quadStride = stride * 6;
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.RandomArrayGenerator.createPerQuads - Invalid primitive');
+ break;
+ }
+
+ /** @type {ArrayBuffer} */ var data = new ArrayBuffer(count * quadStride);
+
+ for (var quadNdx = 0; quadNdx < count; quadNdx++) {
+ for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
+ /** @type {glsVertexArrayTests.GLValue} */ var val = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
+
+ var data8 = new Uint8Array(data);
+ glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 0 + componentStride * componentNdx), val);
+ glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 1 + componentStride * componentNdx), val);
+ glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 2 + componentStride * componentNdx), val);
+ glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 3 + componentStride * componentNdx), val);
+ glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 4 + componentStride * componentNdx), val);
+ glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 5 + componentStride * componentNdx), val);
+ }
+ }
+
+ return data;
+ };
+
+ /**
+ * class glsVertexArrayTests.VertexArrayTest
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ */
+ glsVertexArrayTests.VertexArrayTest = function(name, description) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+
+ var r = /** @type {number} */ (gl.getParameter(gl.RED_BITS));
+ var g = /** @type {number} */ (gl.getParameter(gl.GREEN_BITS));
+ var b = /** @type {number} */ (gl.getParameter(gl.BLUE_BITS));
+ var a = /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS));
+ this.m_pixelformat = new tcuPixelFormat.PixelFormat(r, g, b, a);
+
+ /** @type {sglrReferenceContext.ReferenceContextBuffers} */ this.m_refBuffers = null;
+ /** @type {sglrReferenceContext.ReferenceContext} */ this.m_refContext = null;
+ /** @type {sglrGLContext.GLContext} */ this.m_glesContext = null;
+ /** @type {glsVertexArrayTests.ContextArrayPack} */ this.m_glArrayPack = null;
+ /** @type {glsVertexArrayTests.ContextArrayPack} */ this.m_rrArrayPack = null;
+ /** @type {boolean} */ this.m_isOk = false;
+ /** @type {number} */ this.m_maxDiffRed = Math.ceil(256.0 * (2.0 / (1 << this.m_pixelformat.redBits)));
+ /** @type {number} */ this.m_maxDiffGreen = Math.ceil(256.0 * (2.0 / (1 << this.m_pixelformat.greenBits)));
+ /** @type {number} */ this.m_maxDiffBlue = Math.ceil(256.0 * (2.0 / (1 << this.m_pixelformat.blueBits)));
+ };
+
+ glsVertexArrayTests.VertexArrayTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ glsVertexArrayTests.VertexArrayTest.prototype.constructor = glsVertexArrayTests.VertexArrayTest;
+
+ /**
+ * init
+ */
+ glsVertexArrayTests.VertexArrayTest.prototype.init = function() {
+ /** @type {number}*/ var renderTargetWidth = Math.min(512, canvas.width);
+ /** @type {number}*/ var renderTargetHeight = Math.min(512, canvas.height);
+ /** @type {sglrReferenceContext.ReferenceContextLimits} */ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
+
+ this.m_glesContext = new sglrGLContext.GLContext(gl);
+ this.m_refBuffers = new sglrReferenceContext.ReferenceContextBuffers(this.m_pixelformat, 0, 0, renderTargetWidth, renderTargetHeight);
+ this.m_refContext = new sglrReferenceContext.ReferenceContext(limits, this.m_refBuffers.getColorbuffer(), this.m_refBuffers.getDepthbuffer(), this.m_refBuffers.getStencilbuffer());
+
+ this.m_glArrayPack = new glsVertexArrayTests.ContextArrayPack(this.m_glesContext);
+ this.m_rrArrayPack = new glsVertexArrayTests.ContextArrayPack(this.m_refContext);
+ };
+
+ /**
+ * compare
+ */
+ glsVertexArrayTests.VertexArrayTest.prototype.compare = function() {
+ /** @type {tcuSurface.Surface} */ var ref = this.m_rrArrayPack.getSurface();
+ /** @type {tcuSurface.Surface} */ var screen = this.m_glArrayPack.getSurface();
+
+ if (/** @type {number} */ (this.m_glesContext.getParameter(gl.SAMPLES)) > 1) {
+ // \todo [mika] Improve compare when using multisampling
+ bufferedLogToConsole('Warning: Comparison of result from multisample render targets are not as strict as without multisampling. Might produce false positives!');
+ this.m_isOk = tcuImageCompare.fuzzyCompare('Compare Results', 'Compare Results', ref.getAccess(), screen.getAccess(), 1.5);
+ } else {
+ /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.newRGBAComponents(this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue, 255);
+ /** @type {tcuSurface.Surface} */ var error = new tcuSurface.Surface(ref.getWidth(), ref.getHeight());
+
+ this.m_isOk = true;
+
+ for (var y = 1; y < ref.getHeight() - 1; y++) {
+ for (var x = 1; x < ref.getWidth() - 1; x++) {
+ /** @type {tcuRGBA.RGBA} */ var refPixel = tcuRGBA.newRGBAFromArray(ref.getPixel(x, y));
+ /** @type {tcuRGBA.RGBA} */ var screenPixel = tcuRGBA.newRGBAFromArray(screen.getPixel(x, y));
+ /** @type {boolean} */ var isOkPixel = false;
+
+ // Don't do comparisons for this pixel if it belongs to a one-pixel-thin part (i.e. it doesn't have similar-color neighbors in both x and y directions) in both result and reference.
+ // This fixes some false negatives.
+ /** @type {boolean} */ var refThin = (
+ !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x - 1, y)), threshold) &&
+ !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x + 1, y)), threshold)
+ ) || (
+ !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x, y - 1)), threshold) &&
+ !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x, y + 1)), threshold)
+ );
+
+ /** @type {boolean} */ var screenThin = (
+ !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x - 1, y)), threshold) &&
+ !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x + 1, y)), threshold)
+ ) || (
+ !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x, y - 1)), threshold) &&
+ !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x, y + 1)), threshold)
+ );
+
+ if (refThin && screenThin)
+ isOkPixel = true;
+ else {
+ //NOTE: This will ignore lines less than three pixels wide, so
+ //even if there's a difference, the test will pass.
+ for (var dy = -1; dy < 2 && !isOkPixel; dy++) {
+ for (var dx = -1; dx < 2 && !isOkPixel; dx++) {
+ // Check reference pixel against screen pixel
+ /** @type {tcuRGBA.RGBA} */ var screenCmpPixel = tcuRGBA.newRGBAFromArray(screen.getPixel(x + dx, y + dy));
+ /** @type {number} (8-bit) */ var r = Math.abs(refPixel.getRed() - screenCmpPixel.getRed());
+ /** @type {number} (8-bit) */ var g = Math.abs(refPixel.getGreen() - screenCmpPixel.getGreen());
+ /** @type {number} (8-bit) */ var b = Math.abs(refPixel.getBlue() - screenCmpPixel.getBlue());
+
+ if (r <= this.m_maxDiffRed && g <= this.m_maxDiffGreen && b <= this.m_maxDiffBlue)
+ isOkPixel = true;
+
+ // Check screen pixels against reference pixel
+ /** @type {tcuRGBA.RGBA} */ var refCmpPixel = tcuRGBA.newRGBAFromArray(ref.getPixel(x + dx, y + dy));
+ r = Math.abs(refCmpPixel.getRed() - screenPixel.getRed());
+ g = Math.abs(refCmpPixel.getGreen() - screenPixel.getGreen());
+ b = Math.abs(refCmpPixel.getBlue() - screenPixel.getBlue());
+
+ if (r <= this.m_maxDiffRed && g <= this.m_maxDiffGreen && b <= this.m_maxDiffBlue)
+ isOkPixel = true;
+ }
+ }
+ }
+
+ if (isOkPixel)
+ error.setPixel(x, y,
+ [tcuRGBA.newRGBAFromArray(screen.getPixel(x, y)).getRed(),
+ (tcuRGBA.newRGBAFromArray(screen.getPixel(x, y)).getGreen() + 255) / 2,
+ tcuRGBA.newRGBAFromArray(screen.getPixel(x, y)).getBlue(), 255]
+ );
+ else {
+ error.setPixel(x, y, [255, 0, 0, 255]);
+ this.m_isOk = false;
+ }
+ }
+ }
+
+ if (!this.m_isOk) {
+ debug('Image comparison failed, threshold = (' + this.m_maxDiffRed + ', ' + this.m_maxDiffGreen + ', ' + this.m_maxDiffBlue + ')');
+ //log << TestLog::ImageSet("Compare result", "Result of rendering");
+ tcuImageCompare.displayImages(screen.getAccess(), ref.getAccess(), error.getAccess());
+ } else {
+ //log << TestLog::ImageSet("Compare result", "Result of rendering")
+ tcuLogImage.logImage('Result', '', screen.getAccess());
+ }
+ }
+ };
+
+ //TODO: Is this actually used? -> glsVertexArrayTests.VertexArrayTest& operator= (const glsVertexArrayTests.VertexArrayTest& other);
+
+ /**
+ * glsVertexArrayTests.MultiVertexArrayTest class
+ * @constructor
+ * @extends {glsVertexArrayTests.VertexArrayTest}
+ * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
+ * @param {string} name
+ * @param {string} desc
+ */
+ glsVertexArrayTests.MultiVertexArrayTest = function(spec, name, desc) {
+ glsVertexArrayTests.VertexArrayTest.call(this, name, desc);
+
+ /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec} */ this.m_spec = spec;
+ /** @type {number} */ this.m_iteration = 0;
+ };
+
+ glsVertexArrayTests.MultiVertexArrayTest.prototype = Object.create(glsVertexArrayTests.VertexArrayTest.prototype);
+ glsVertexArrayTests.MultiVertexArrayTest.prototype.constructor = glsVertexArrayTests.MultiVertexArrayTest;
+
+ /**
+ * glsVertexArrayTests.MultiVertexArrayTest.Spec class
+ * @constructor
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.Spec = function() {
+ /** @type {glsVertexArrayTests.deArray.Primitive} */ this.primitive;
+ /** @type {number} */ this.drawCount = 0;
+ /** @type {number} */ this.first = 0;
+ /** @type {Array<glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec>} */ this.arrays = [];
+ };
+
+ /**
+ * glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec class
+ * @constructor
+ * @param {glsVertexArrayTests.deArray.InputType} inputType_
+ * @param {glsVertexArrayTests.deArray.OutputType} outputType_
+ * @param {glsVertexArrayTests.deArray.Storage} storage_
+ * @param {glsVertexArrayTests.deArray.Usage} usage_
+ * @param {number} componentCount_
+ * @param {number} offset_
+ * @param {number} stride_
+ * @param {boolean} normalize_
+ * @param {glsVertexArrayTests.GLValue} min_
+ * @param {glsVertexArrayTests.GLValue} max_
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec = function(inputType_, outputType_, storage_, usage_, componentCount_, offset_, stride_, normalize_, min_, max_) {
+ this.inputType = inputType_;
+ this.outputType = outputType_;
+ this.storage = storage_;
+ this.usage = usage_;
+ this.componentCount = componentCount_;
+ this.offset = offset_;
+ /** @type {number} */ this.stride = stride_;
+ this.normalize = normalize_;
+ this.min = min_;
+ this.max = max_;
+ };
+
+ /**
+ * getName
+ * @return {string}
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.Spec.prototype.getName = function() {
+ var name = '';
+
+ for (var ndx = 0; ndx < this.arrays.length; ++ndx) {
+ /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var array = this.arrays[ndx];
+
+ if (this.arrays.length > 1)
+ name += 'array' + ndx + '_';
+
+ name += glsVertexArrayTests.deArray.storageToString(array.storage) + '_' +
+ array.offset + '_' +
+ array.stride + '_' +
+ glsVertexArrayTests.deArray.inputTypeToString(array.inputType);
+
+ if (array.inputType != glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 && array.inputType != glsVertexArrayTests.deArray.InputType.INT_2_10_10_10)
+ name += array.componentCount;
+ name += '_' +
+ (array.normalize ? 'normalized_' : '') +
+ glsVertexArrayTests.deArray.outputTypeToString(array.outputType) + '_' +
+ glsVertexArrayTests.deArray.usageTypeToString(array.usage) + '_';
+ }
+
+ if (this.first)
+ name += 'first' + this.first + '_';
+
+ switch (this.primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
+ name += 'quads_';
+ break;
+ case glsVertexArrayTests.deArray.Primitive.POINTS:
+ name += 'points_';
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.MultiVertexArrayTest.Spec.getName - Invalid primitive type');
+ break;
+ }
+
+ name += this.drawCount;
+
+ return name;
+ };
+
+ /**
+ * getName
+ * @return {string}
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.Spec.prototype.getDesc = function() {
+ var desc = '';
+
+ for (var ndx = 0; ndx < this.arrays.length; ++ndx) {
+ /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var array = this.arrays[ndx];
+
+ desc += 'Array ' + ndx + ': ' +
+ 'Storage in ' + glsVertexArrayTests.deArray.storageToString(array.storage) + ', ' +
+ 'stride ' + array.stride + ', ' +
+ 'input datatype ' + glsVertexArrayTests.deArray.inputTypeToString(array.inputType) + ', ' +
+ 'input component count ' + array.componentCount + ', ' +
+ (array.normalize ? 'normalized, ' : '') +
+ 'used as ' + glsVertexArrayTests.deArray.outputTypeToString(array.outputType) + ', ';
+ }
+
+ desc += 'drawArrays(), ' +
+ 'first ' + this.first + ', ' +
+ this.drawCount;
+
+ switch (this.primitive) {
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
+ desc += 'quads ';
+ break;
+ case glsVertexArrayTests.deArray.Primitive.POINTS:
+ desc += 'points';
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.MultiVertexArrayTest.Spec.getDesc - Invalid primitive type');
+ break;
+ }
+
+ return desc;
+ };
+
+ /**
+ * iterate
+ * @return {tcuTestCase.IterateResult}
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.prototype.iterate = function() {
+ if (this.m_iteration == 0) {
+ var primitiveSize = (this.m_spec.primitive == glsVertexArrayTests.deArray.Primitive.TRIANGLES) ? (6) : (1); // in non-indexed draw Triangles means rectangles
+ var coordScale = 1.0;
+ var colorScale = 1.0;
+ var useVao = true; // WebGL, WebGL 2.0 - gl.getType().getProfile() == glu::PROFILE_CORE;
+
+ // Log info
+ bufferedLogToConsole(this.m_spec.getDesc());
+
+ // Color and Coord scale
+
+ // First array is always position
+ /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var arraySpec = this.m_spec.arrays[0];
+ if (arraySpec.inputType == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10) {
+ if (arraySpec.normalize)
+ coordScale = 1;
+ else
+ coordScale = 1 / 1024;
+ } else if (arraySpec.inputType == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10) {
+ if (arraySpec.normalize)
+ coordScale = 1.0;
+ else
+ coordScale = 1.0 / 512.0;
+ } else
+ coordScale = arraySpec.normalize && !glsVertexArrayTests.inputTypeIsFloatType(arraySpec.inputType) ? 1.0 : 0.9 / arraySpec.max.toFloat();
+
+ if (arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.VEC3 || arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.VEC4 ||
+ arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.IVEC3 || arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.IVEC4 ||
+ arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.UVEC3 || arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.UVEC4)
+ coordScale = coordScale * 0.5;
+
+ // And other arrays are color-like
+ for (var arrayNdx = 1; arrayNdx < this.m_spec.arrays.length; arrayNdx++) {
+ arraySpec = this.m_spec.arrays[arrayNdx];
+
+ colorScale *= (arraySpec.normalize && !glsVertexArrayTests.inputTypeIsFloatType(arraySpec.inputType) ? 1.0 : 1.0 / arraySpec.max.toFloat());
+ if (arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.VEC4)
+ colorScale *= (arraySpec.normalize && !glsVertexArrayTests.inputTypeIsFloatType(arraySpec.inputType) ? 1.0 : 1.0 / arraySpec.max.toFloat());
+ }
+
+ // Data
+
+ for (var arrayNdx = 0; arrayNdx < this.m_spec.arrays.length; arrayNdx++) {
+ arraySpec = this.m_spec.arrays[arrayNdx];
+ /** @type {number} */ var seed = arraySpec.inputType + 10 * arraySpec.outputType + 100 * arraySpec.storage + 1000 * this.m_spec.primitive + 10000 * arraySpec.usage + this.m_spec.drawCount + 12 * arraySpec.componentCount + arraySpec.stride + arraySpec.normalize;
+ /** @type {ArrayBuffer} */ var data = null;
+ /** @type {number} */ var stride = arraySpec.stride == 0 ? arraySpec.componentCount * glsVertexArrayTests.deArray.inputTypeSize(arraySpec.inputType) : arraySpec.stride;
+ /** @type {number} */ var bufferSize = arraySpec.offset + stride * (this.m_spec.drawCount * primitiveSize - 1) + arraySpec.componentCount * glsVertexArrayTests.deArray.inputTypeSize(arraySpec.inputType);
+
+ switch (this.m_spec.primitive) {
+ // case glsVertexArrayTests.deArray.Primitive.POINTS:
+ // data = glsVertexArrayTests.RandomArrayGenerator.generateArray(seed, arraySpec.min, arraySpec.max, arraySpec.count, arraySpec.componentCount, arraySpec.stride, arraySpec.inputType);
+ // break;
+ case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
+ if (arrayNdx == 0) {
+ data = glsVertexArrayTests.RandomArrayGenerator.generateQuads(seed, this.m_spec.drawCount, arraySpec.componentCount, arraySpec.offset, arraySpec.stride, this.m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max, coordScale);
+ } else {
+ DE_ASSERT(arraySpec.offset == 0); // \note [jarkko] it just hasn't been implemented
+ data = glsVertexArrayTests.RandomArrayGenerator.generatePerQuad(seed, this.m_spec.drawCount, arraySpec.componentCount, arraySpec.stride, this.m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max);
+ }
+ break;
+
+ default:
+ throw new Error('glsVertexArrayTests.MultiVertexArrayTest.prototype.iterate - Invalid primitive type');
+ break;
+ }
+
+ this.m_glArrayPack.newArray(arraySpec.storage);
+ this.m_rrArrayPack.newArray(arraySpec.storage);
+
+ this.m_glArrayPack.getArray(arrayNdx).data(glsVertexArrayTests.deArray.Target.ARRAY, bufferSize, new Uint8Array(data), arraySpec.usage);
+ this.m_rrArrayPack.getArray(arrayNdx).data(glsVertexArrayTests.deArray.Target.ARRAY, bufferSize, new Uint8Array(data), arraySpec.usage);
+
+ this.m_glArrayPack.getArray(arrayNdx).bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
+ this.m_rrArrayPack.getArray(arrayNdx).bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
+ }
+
+ try {
+ this.m_glArrayPack.render(this.m_spec.primitive, this.m_spec.first, this.m_spec.drawCount * primitiveSize, useVao, coordScale, colorScale);
+ this.m_rrArrayPack.render(this.m_spec.primitive, this.m_spec.first, this.m_spec.drawCount * primitiveSize, useVao, coordScale, colorScale);
+ }
+ catch (err) {
+ // GL Errors are ok if the mode is not properly aligned
+
+ bufferedLogToConsole('Got error: ' + err.message);
+
+ if (this.isUnalignedBufferOffsetTest())
+ testFailedOptions('Failed to draw with unaligned buffers', false); // TODO: QP_TEST_RESULT_COMPATIBILITY_WARNING
+ else if (this.isUnalignedBufferStrideTest())
+ testFailedOptions('Failed to draw with unaligned stride', false); // QP_TEST_RESULT_COMPATIBILITY_WARNING
+ else
+ throw new Error(err.message);
+
+ return tcuTestCase.IterateResult.STOP;
+ }
+
+ this.m_iteration++;
+ return tcuTestCase.IterateResult.CONTINUE;
+ } else if (this.m_iteration == 1) {
+ this.compare();
+
+ if (this.m_isOk) {
+ testPassedOptions('', true);
+ } else {
+ if (this.isUnalignedBufferOffsetTest())
+ testFailedOptions('Failed to draw with unaligned buffers', false); // QP_TEST_RESULT_COMPATIBILITY_WARNING
+ else if (this.isUnalignedBufferStrideTest())
+ testFailedOptions('Failed to draw with unaligned stride', false); // QP_TEST_RESULT_COMPATIBILITY_WARNING
+ else
+ testFailedOptions('Image comparison failed', false);
+ }
+
+ this.m_iteration++;
+ return tcuTestCase.IterateResult.STOP;
+ } else {
+ testFailedOptions('glsVertexArrayTests.MultiVertexArrayTest.iterate - Invalid iteration stage', false);
+ return tcuTestCase.IterateResult.STOP;
+ }
+ };
+
+ /**
+ * isUnalignedBufferOffsetTest
+ * @return {boolean}
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.prototype.isUnalignedBufferOffsetTest = function() {
+ // Buffer offsets should be data type size aligned
+ for (var i = 0; i < this.m_spec.arrays.length; ++i) {
+ if (this.m_spec.arrays[i].storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ /** @type {boolean} */ var inputTypePacked = this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 || this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
+
+ /** @type {number} */ var dataTypeSize = glsVertexArrayTests.deArray.inputTypeSize(this.m_spec.arrays[i].inputType);
+ if (inputTypePacked)
+ dataTypeSize = 4;
+
+ if (this.m_spec.arrays[i].offset % dataTypeSize != 0)
+ return true;
+ }
+ }
+ return false;
+ };
+
+ /**
+ * isUnalignedBufferStrideTest
+ * @return {boolean}
+ */
+ glsVertexArrayTests.MultiVertexArrayTest.prototype.isUnalignedBufferStrideTest = function() {
+ // Buffer strides should be data type size aligned
+ for (var i = 0; i < this.m_spec.arrays.length; ++i) {
+ if (this.m_spec.arrays[i].storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
+ /** @type {boolean} */ var inputTypePacked = this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 || this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
+
+ /** @type {number} */ var dataTypeSize = glsVertexArrayTests.deArray.inputTypeSize(this.m_spec.arrays[i].inputType);
+ if (inputTypePacked)
+ dataTypeSize = 4;
+
+ if (this.m_spec.arrays[i].stride % dataTypeSize != 0)
+ return true;
+ }
+ }
+ return false;
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/run-closure.sh b/dom/canvas/test/webgl-conf/checkout/deqp/run-closure.sh
new file mode 100755
index 0000000000..7dcc44c12c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/run-closure.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Helper script for properly invoking the closure compiler in order to
+# type check the ported dEQP tests.
+#
+# Assumes the Closure compiler:
+# https://github.com/google/closure-compiler
+# is installed side-by-side with the WebGL repository, for example:
+#
+# WebGL/
+# doc/
+# extensions/
+# sdk/
+# ...
+# closure/
+# compiler.jar
+#
+# The externs.zip file inside the closure compiler needs to be modified
+# to support WebGL2.
+# and that the shell is cd'd into the directory containing this
+# script.
+#
+
+: ${JAVA:=java}
+
+$JAVA -jar ../../../../closure/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --warning_level VERBOSE --externs compiler_additional_extern.js --js functional/**.js framework/**.js modules/**.js --js_output_file /dev/null --js ../closure-library/closure/**.js
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/chrome.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/chrome.js
new file mode 100644
index 0000000000..7cd036f1f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/chrome.js
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2013 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for globals in Chrome. This file describes the
+ * externs API for the chrome.* object when running in a normal browser
+ * context. For APIs available in Chrome Extensions, see chrome_extensions.js
+ * in this directory.
+ * @externs
+ */
+
+
+/**
+ * namespace
+ * @const
+ */
+var chrome = {};
+
+
+
+/**
+ * Returns an object representing current load times. Note that the properties
+ * on the object do not change and the function must be called again to get
+ * up-to-date data.
+ *
+ * @see http://goto.google.com/chromeloadtimesextension
+ *
+ * @return {!ChromeLoadTimes}
+ */
+chrome.loadTimes = function() {};
+
+
+
+/**
+ * The data object given by chrome.loadTimes().
+ * @constructor
+ */
+function ChromeLoadTimes() {}
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.requestTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.startLoadTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.commitLoadTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.finishDocumentLoadTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.finishLoadTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.firstPaintTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.firstPaintAfterLoadTime;
+
+
+/** @type {number} */
+ChromeLoadTimes.prototype.navigationType;
+
+
+/**
+ * True iff the resource was fetched over SPDY.
+ * @type {boolean}
+ */
+ChromeLoadTimes.prototype.wasFetchedViaSpdy;
+
+
+/** @type {boolean} */
+ChromeLoadTimes.prototype.wasNpnNegotiated;
+
+
+/** @type {string} */
+ChromeLoadTimes.prototype.npnNegotiatedProtocol;
+
+
+/** @type {boolean} */
+ChromeLoadTimes.prototype.wasAlternateProtocolAvailable;
+
+
+/** @type {string} */
+ChromeLoadTimes.prototype.connectionInfo;
+
+
+/**
+ * Returns an object containing timing information.
+ * @return {!ChromeCsiInfo}
+ */
+chrome.csi = function() {};
+
+
+
+/**
+ * The data object given by chrome.csi().
+ * @constructor
+ */
+function ChromeCsiInfo() {}
+
+
+/**
+ * Same as chrome.loadTimes().requestTime, if defined.
+ * Otherwise, gives the same value as chrome.loadTimes().startLoadTime.
+ * In milliseconds, truncated.
+ * @type {number}
+ */
+ChromeCsiInfo.prototype.startE;
+
+
+/**
+ * Same as chrome.loadTimes().finishDocumentLoadTime but in milliseconds and
+ * truncated.
+ * @type {number}
+ */
+ChromeCsiInfo.prototype.onloadT;
+
+
+/**
+ * The time since startE in milliseconds.
+ * @type {number}
+ */
+ChromeCsiInfo.prototype.pageT;
+
+
+/** @type {number} */
+ChromeCsiInfo.prototype.tran;
+
+
+/**
+ * @param {string|!ArrayBuffer|!Object} message
+ * @see https://developers.google.com/native-client/devguide/tutorial
+ */
+HTMLEmbedElement.prototype.postMessage = function(message) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/deprecated.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/deprecated.js
new file mode 100644
index 0000000000..9dcf947c9d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/deprecated.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview JavaScript Built-Ins that are not
+ * part of any specifications but are
+ * still needed in some project's build.
+ * @externs
+ *
+ */
+
+// Do we need an opera.js?
+var opera;
+Window.prototype.opera;
+Window.prototype.opera.postError;
+
+/** @constructor */ function XSLTProcessor() {}
+/**
+ * @param {*=} opt_text
+ * @param {*=} opt_value
+ * @param {*=} opt_defaultSelected
+ * @param {*=} opt_selected
+ * @constructor
+ * @extends {Element}
+ */
+function Option(opt_text, opt_value, opt_defaultSelected, opt_selected) {}
+
+
+// The "methods" object is a place to hang arbitrary external
+// properties. It is a throwback to pre-typed days, and should
+// not be used for any new definitions; it exists only to bridge
+// the gap between the old way and the new way.
+var methods = {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es3.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es3.js
new file mode 100644
index 0000000000..934b1fe2b7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es3.js
@@ -0,0 +1,2236 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview ECMAScript 3 Built-Ins. This include common extensions so this
+ * is actually ES3+Reality.
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ * @author nicksantos@google.com (Nick Santos)
+ * @author arv@google.com (Erik Arvidsson)
+ * @author johnlenz@google.com (John Lenz)
+ */
+
+
+// These built-ins are still needed for compilation.
+
+/**
+ * @constructor
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments
+ */
+function Arguments() {}
+
+/**
+ * @type {Function}
+ * @see http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments/callee
+ */
+Arguments.prototype.callee;
+
+/**
+ * Use the non-standard {@see Function.prototype.caller} property of a function
+ * object instead.
+ * @type {Function}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions/arguments/caller
+ * @deprecated
+ */
+Arguments.prototype.caller;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments/length
+ */
+Arguments.prototype.length;
+
+/**
+ * @type {!Arguments}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments
+ */
+var arguments;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Properties/Infinity
+ * @const
+ */
+var Infinity;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Properties/NaN
+ * @const
+ */
+var NaN;
+
+/**
+ * @type {undefined}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Properties/undefined
+ * @const
+ */
+var undefined;
+
+/**
+ * @param {string} uri
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/decodeURI
+ */
+function decodeURI(uri) {}
+
+/**
+ * @param {string} uri
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/decodeURIComponent
+ */
+function decodeURIComponent(uri) {}
+
+/**
+ * @param {string} uri
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/encodeURI
+ */
+function encodeURI(uri) {}
+
+/**
+ * @param {string} uri
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/encodeURIComponent
+ */
+function encodeURIComponent(uri) {}
+
+/**
+ * Should only be used in browsers where encode/decodeURIComponent
+ * are not present, as the latter handle fancy Unicode characters.
+ * @param {string} str
+ * @return {string}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Functions/escape_and_unescape_Functions
+ */
+function escape(str) {}
+
+/**
+ * Should only be used in browsers where encode/decodeURIComponent
+ * are not present, as the latter handle fancy Unicode characters.
+ * @param {string} str
+ * @return {string}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Functions/escape_and_unescape_Functions
+ */
+function unescape(str) {}
+
+/**
+ * @param {*} num
+ * @return {boolean}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/isFinite
+ */
+function isFinite(num) {}
+
+/**
+ * @param {*} num
+ * @return {boolean}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/isNaN
+ */
+function isNaN(num) {}
+
+/**
+ * @param {*} num
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseFloat
+ */
+function parseFloat(num) {}
+
+/**
+ * Parse an integer. Use of {@code parseInt} without {@code base} is strictly
+ * banned in Google. If you really want to parse octal or hex based on the
+ * leader, then pass {@code undefined} as the base.
+ *
+ * @param {*} num
+ * @param {number|undefined} base
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseInt
+ */
+function parseInt(num, base) {}
+
+/**
+ * @param {string} code
+ * @return {*}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/eval
+ */
+function eval(code) {}
+
+/**
+ * @constructor
+ * @param {*=} opt_value
+ * @return {!Object}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object
+ */
+function Object(opt_value) {}
+
+/**
+ * The constructor of the current object.
+ * @type {Function}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/constructor
+ */
+Object.prototype.constructor = function() {};
+
+/**
+ * Binds an object's property to a function to be called when that property is
+ * looked up.
+ * Mozilla-only.
+ *
+ * @param {string} sprop
+ * @param {Function} fun
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/defineGetter
+ */
+Object.prototype.__defineGetter__ = function(sprop, fun) {};
+
+/**
+ * Binds an object's property to a function to be called when an attempt is made
+ * to set that property.
+ * Mozilla-only.
+ *
+ * @param {string} sprop
+ * @param {Function} fun
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/defineSetter
+ */
+Object.prototype.__defineSetter__ = function(sprop, fun) {};
+
+/**
+ * Returns whether the object has a property with the specified name.
+ *
+ * @param {*} propertyName Implicitly cast to a string.
+ * @return {boolean}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/hasOwnProperty
+ */
+Object.prototype.hasOwnProperty = function(propertyName) {};
+
+/**
+ * Returns whether an object exists in another object's prototype chain.
+ *
+ * @param {Object} other
+ * @return {boolean}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/isPrototypeOf
+ */
+Object.prototype.isPrototypeOf = function(other) {};
+
+/**
+ * Return the function bound as a getter to the specified property.
+ * Mozilla-only.
+ *
+ * @param {string} sprop a string containing the name of the property whose
+ * getter should be returned
+ * @return {Function}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/lookupGetter
+ */
+Object.prototype.__lookupGetter__ = function(sprop) {};
+
+/**
+ * Return the function bound as a setter to the specified property.
+ * Mozilla-only.
+ *
+ * @param {string} sprop a string containing the name of the property whose
+ * setter should be returned.
+ * @return {Function}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/lookupSetter
+ */
+Object.prototype.__lookupSetter__ = function(sprop) {};
+
+/**
+ * Executes a function when a non-existent method is called on an object.
+ * Mozilla-only.
+ *
+ * @param {Function} fun
+ * @return {*}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/noSuchMethod
+ */
+Object.prototype.__noSuchMethod__ = function(fun) {};
+
+/**
+ * Points to an object's context. For top-level objects, this is the e.g. window.
+ * Mozilla-only.
+ *
+ * @type {Object}
+ * @deprecated
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/parent
+ */
+Object.prototype.__parent__;
+
+/**
+ * Points to the object which was used as prototype when the object was instantiated.
+ * Mozilla-only.
+ *
+ * Will be null on Object.prototype.
+ *
+ * @type {Object}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/proto
+ */
+Object.prototype.__proto__;
+
+/**
+ * Determine whether the specified property in an object can be enumerated by a
+ * for..in loop, with the exception of properties inherited through the
+ * prototype chain.
+ *
+ * @param {string} propertyName
+ * @return {boolean}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/propertyIsEnumerable
+ */
+Object.prototype.propertyIsEnumerable = function(propertyName) {};
+
+/**
+ * Returns a localized string representing the object.
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/toLocaleString
+ */
+Object.prototype.toLocaleString = function() {};
+
+/**
+ * Returns a string representing the source code of the object.
+ * Mozilla-only.
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/toSource
+ */
+Object.prototype.toSource = function() {};
+
+/**
+ * Returns a string representing the object.
+ * @this {*}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/toString
+ */
+Object.prototype.toString = function() {};
+
+/**
+ * Removes a watchpoint set with the {@see Object.prototype.watch} method.
+ * Mozilla-only.
+ * @param {string} prop The name of a property of the object.
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/unwatch
+ */
+Object.prototype.unwatch = function(prop) {};
+
+/**
+ * Returns the object's {@code this} value.
+ * @return {*}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/valueOf
+ */
+Object.prototype.valueOf = function() {};
+
+/**
+ * Sets a watchpoint method.
+ * Mozilla-only.
+ * @param {string} prop The name of a property of the object.
+ * @param {Function} handler A function to call.
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/watch
+ */
+Object.prototype.watch = function(prop, handler) {};
+
+
+/**
+ * @constructor
+ * @param {...*} var_args
+ * @nosideeffects
+ * @throws {Error}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function
+ */
+function Function(var_args) {}
+
+/**
+ * @param {...*} var_args
+ * @return {*}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/call
+ */
+Function.prototype.call = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ * @return {*}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/apply
+ */
+Function.prototype.apply = function(var_args) {};
+
+Function.prototype.arguments;
+
+/**
+ * @type {number}
+ * @deprecated
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/arity
+ */
+Function.prototype.arity;
+
+/**
+ * Nonstandard; Mozilla and JScript only.
+ * @type {Function}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/caller
+ */
+Function.prototype.caller;
+
+/**
+ * Nonstandard.
+ * @type {?}
+ * @see http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/displayName
+ */
+Function.prototype.displayName;
+
+/**
+ * Expected number of arguments.
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/length
+ */
+Function.prototype.length;
+
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/name
+ */
+Function.prototype.name;
+
+/**
+ * @this {Function}
+ * @return {string}
+ * @nosideeffects
+ * @override
+ */
+Function.prototype.toString = function() {};
+
+
+/**
+ * @constructor
+ * @param {...*} var_args
+ * @return {!Array.<?>}
+ * @nosideeffects
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array
+ */
+function Array(var_args) {}
+
+// Functions:
+
+/**
+ * Returns a new array comprised of this array joined with other array(s)
+ * and/or value(s).
+ *
+ * @param {...*} var_args
+ * @return {!Array.<?>}
+ * @this {*}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/concat
+ */
+Array.prototype.concat = function(var_args) {};
+
+/**
+ * Joins all elements of an array into a string.
+ *
+ * @param {*=} opt_separator Specifies a string to separate each element of the
+ * array. The separator is converted to a string if necessary. If omitted,
+ * the array elements are separated with a comma.
+ * @return {string}
+ * @this {{length: number}|string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/join
+ */
+Array.prototype.join = function(opt_separator) {};
+
+/**
+ * Removes the last element from an array and returns that element.
+ *
+ * @return {T}
+ * @this {{length: number}|Array.<T>}
+ * @modifies {this}
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/pop
+ */
+Array.prototype.pop = function() {};
+
+/**
+ * Mutates an array by appending the given elements and returning the new
+ * length of the array.
+ *
+ * @param {...T} var_args
+ * @return {number} The new length of the array.
+ * @this {{length: number}|Array.<T>}
+ * @template T
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/push
+ */
+Array.prototype.push = function(var_args) {};
+
+/**
+ * Transposes the elements of an array in place: the first array element becomes the
+ * last and the last becomes the first.
+ *
+ * @this {{length: number}}
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/reverse
+ */
+Array.prototype.reverse = function() {};
+
+/**
+ * Removes the first element from an array and returns that element. This
+ * method changes the length of the array.
+ *
+ * @this {{length: number}|Array.<T>}
+ * @modifies {this}
+ * @return {T}
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/shift
+ */
+Array.prototype.shift = function() {};
+
+/**
+ * Extracts a section of an array and returns a new array.
+ *
+ * @param {*=} opt_begin Zero-based index at which to begin extraction. A
+ * non-number type will be auto-cast by the browser to a number.
+ * @param {*=} opt_end Zero-based index at which to end extraction. slice
+ * extracts up to but not including end.
+ * @return {!Array.<T>}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice
+ */
+Array.prototype.slice = function(opt_begin, opt_end) {};
+
+/**
+ * Sorts the elements of an array in place.
+ *
+ * @param {function(T,T):number=} opt_compareFunction Specifies a function that
+ * defines the sort order.
+ * @this {{length: number}|Array.<T>}
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/sort
+ */
+Array.prototype.sort = function(opt_compareFunction) {};
+
+/**
+ * Changes the content of an array, adding new elements while removing old
+ * elements.
+ *
+ * @param {*=} opt_index Index at which to start changing the array. If negative,
+ * will begin that many elements from the end. A non-number type will be
+ * auto-cast by the browser to a number.
+ * @param {*=} opt_howMany An integer indicating the number of old array elements
+ * to remove.
+ * @param {...T} var_args
+ * @return {!Array.<T>}
+ * @this {{length: number}|Array.<T>}
+ * @modifies {this}
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/splice
+ */
+Array.prototype.splice = function(opt_index, opt_howMany, var_args) {};
+
+/**
+ * @return {string}
+ * @this {Object}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/toSource
+ */
+Array.prototype.toSource;
+
+/**
+ * @this {Array.<?>}
+ * @return {string}
+ * @nosideeffects
+ * @override
+ */
+Array.prototype.toString = function() {};
+
+/**
+ * Adds one or more elements to the beginning of an array and returns the new
+ * length of the array.
+ *
+ * @param {...*} var_args
+ * @return {number} The new length of the array
+ * @this {{length: number}}
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/unshift
+ */
+Array.prototype.unshift = function(var_args) {};
+
+/**
+ * Apply a function simultaneously against two values of the array (from
+ * left-to-right) as to reduce it to a single value.
+ *
+ * @param {?function(?, T, number, !Array.<T>) : R} callback
+ * @param {*=} opt_initialValue
+ * @return {R}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,R
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/reduce
+ */
+Array.prototype.reduce = function(callback, opt_initialValue) {};
+
+/**
+ * Apply a function simultaneously against two values of the array (from
+ * right-to-left) as to reduce it to a single value.
+ *
+ * @param {?function(?, T, number, !Array.<T>) : R} callback
+ * @param {*=} opt_initialValue
+ * @return {R}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,R
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/reduceRight
+ */
+Array.prototype.reduceRight = function(callback, opt_initialValue) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {?function(this:S, T, number, !Array.<T>): ?} callback
+ * @param {S=} opt_thisobj
+ * @return {boolean}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,S
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/every
+ */
+Array.prototype.every = function(callback, opt_thisobj) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {?function(this:S, T, number, !Array.<T>): ?} callback
+ * @param {S=} opt_thisobj
+ * @return {!Array.<T>}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,S
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter
+ */
+Array.prototype.filter = function(callback, opt_thisobj) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {?function(this:S, T, number, !Array.<T>): ?} callback
+ * @param {S=} opt_thisobj
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,S
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/forEach
+ */
+Array.prototype.forEach = function(callback, opt_thisobj) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {T} obj
+ * @param {number=} opt_fromIndex
+ * @return {number}
+ * @this {{length: number}|Array.<T>|string}
+ * @nosideeffects
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf
+ */
+Array.prototype.indexOf = function(obj, opt_fromIndex) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {T} obj
+ * @param {number=} opt_fromIndex
+ * @return {number}
+ * @this {{length: number}|Array.<T>|string}
+ * @nosideeffects
+ * @template T
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/lastIndexOf
+ */
+Array.prototype.lastIndexOf = function(obj, opt_fromIndex) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {?function(this:S, T, number, !Array.<T>): R} callback
+ * @param {S=} opt_thisobj
+ * @return {!Array.<R>}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,S,R
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map
+ */
+Array.prototype.map = function(callback, opt_thisobj) {};
+
+/**
+ * Available in ECMAScript 5, Mozilla 1.6+.
+ * @param {?function(this:S, T, number, !Array.<T>): ?} callback
+ * @param {S=} opt_thisobj
+ * @return {boolean}
+ * @this {{length: number}|Array.<T>|string}
+ * @template T,S
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some
+ */
+Array.prototype.some = function(callback, opt_thisobj) {};
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/index
+ */
+Array.prototype.index;
+
+/**
+ * @type {?string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/input
+ */
+Array.prototype.input;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/length
+ */
+Array.prototype.length;
+
+/**
+ * @param {{length: number}|Array.<T>} arr
+ * @param {?function(this:S, T, number, ?) : ?} callback
+ * @param {S=} opt_context
+ * @return {boolean}
+ * @template T,S
+ */
+Array.every = function(arr, callback, opt_context) {};
+
+/**
+ * @param {{length: number}|Array.<T>} arr
+ * @param {?function(this:S, T, number, ?) : ?} callback
+ * @param {S=} opt_context
+ * @return {!Array.<T>}
+ * @template T,S
+ */
+Array.filter = function(arr, callback, opt_context) {};
+
+/**
+ * @param {{length: number}|Array.<T>} arr
+ * @param {?function(this:S, T, number, ?) : ?} callback
+ * @param {S=} opt_context
+ * @template T,S
+ */
+Array.forEach = function(arr, callback, opt_context) {};
+
+/**
+ * Mozilla 1.6+ only.
+ * @param {{length: number}|Array.<T>} arr
+ * @param {T} obj
+ * @param {number=} opt_fromIndex
+ * @return {number}
+ * @template T
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf
+ */
+Array.indexOf = function(arr, obj, opt_fromIndex) {};
+
+/**
+ * Mozilla 1.6+ only.
+ * @param {{length: number}|Array.<T>} arr
+ * @param {T} obj
+ * @param {number=} opt_fromIndex
+ * @return {number}
+ * @template T
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/lastIndexOf
+ */
+Array.lastIndexOf = function(arr, obj, opt_fromIndex) {};
+
+/**
+ * @param {{length: number}|Array.<T>} arr
+ * @param {?function(this:S, T, number, !Array.<T>): R} callback
+ * @param {S=} opt_context
+ * @return {!Array.<R>}
+ * @template T,S,R
+ */
+Array.map = function(arr, callback, opt_context) {};
+
+/**
+ * @param {{length: number}|Array.<T>} arr
+ * @param {?function(this:S, T, number, ?) : ?} callback
+ * @param {S=} opt_context
+ * @return {boolean}
+ * @template T,S
+ */
+Array.some = function(arr, callback, opt_context) {};
+
+/**
+ * Introduced in 1.8.5.
+ * @param {*} arr
+ * @return {boolean}
+ * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
+ */
+Array.isArray = function(arr) {};
+
+/**
+ * @constructor
+ * @param {*=} opt_value
+ * @return {boolean}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Boolean
+ */
+function Boolean(opt_value) {}
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Boolean/toSource
+ * @override
+ */
+Boolean.prototype.toSource = function() {};
+
+/**
+ * @this {boolean|Boolean}
+ * @return {string}
+ * @nosideeffects
+ * @override
+ */
+Boolean.prototype.toString = function() {};
+
+/**
+ * @constructor
+ * @param {*=} opt_value
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number
+ */
+function Number(opt_value) {}
+
+/**
+ * @this {Number|number}
+ * @param {number=} opt_fractionDigits
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/toExponential
+ */
+Number.prototype.toExponential = function(opt_fractionDigits) {};
+
+/**
+ * @this {Number|number}
+ * @param {*=} opt_digits
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/toFixed
+ */
+Number.prototype.toFixed = function(opt_digits) {};
+
+/**
+ * @this {Number|number}
+ * @param {number=} opt_precision
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/toPrecision
+ */
+Number.prototype.toPrecision = function(opt_precision) {};
+
+/**
+ * Returns a string representing the number.
+ * @this {Number|number}
+ * @param {(number|Number)=} opt_radix An optional radix.
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/toString
+ * @override
+ */
+Number.prototype.toString = function(opt_radix) {};
+
+// Properties.
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/MAX_VALUE
+ */
+Number.MAX_VALUE;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/MIN_VALUE
+ */
+Number.MIN_VALUE;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/NaN
+ */
+Number.NaN;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/NEGATIVE_INFINITY
+ */
+Number.NEGATIVE_INFINITY;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/POSITIVE_INFINITY
+ */
+Number.POSITIVE_INFINITY;
+
+
+/**
+ * @const
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math
+ */
+var Math = {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/abs
+ */
+Math.abs = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/acos
+ */
+Math.acos = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/asin
+ */
+Math.asin = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/atan
+ */
+Math.atan = function(x) {};
+
+/**
+ * @param {*} y
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/atan2
+ */
+Math.atan2 = function(y, x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/ceil
+ */
+Math.ceil = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/cos
+ */
+Math.cos = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/exp
+ */
+Math.exp = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/floor
+ */
+Math.floor = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/log
+ */
+Math.log = function(x) {};
+
+/**
+ * @param {...*} var_args
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/max
+ */
+Math.max = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/min
+ */
+Math.min = function(var_args) {};
+
+/**
+ * @param {*} x
+ * @param {*} y
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/pow
+ */
+Math.pow = function(x, y) {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/random
+ */
+Math.random = function() {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/round
+ */
+Math.round = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/sin
+ */
+Math.sin = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/sqrt
+ */
+Math.sqrt = function(x) {};
+
+/**
+ * @param {*} x
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/tan
+ */
+Math.tan = function(x) {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/toSource
+ */
+Math.toSource = function() {};
+
+// Properties:
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/E
+ */
+Math.E;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/LN2
+ */
+Math.LN2;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/LN10
+ */
+Math.LN10;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/LOG2E
+ */
+Math.LOG2E;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/LOG10E
+ */
+Math.LOG10E;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/PI
+ */
+Math.PI;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/SQRT1_2
+ */
+Math.SQRT1_2;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/SQRT2
+ */
+Math.SQRT2;
+
+
+/**
+ * @param {?=} opt_yr_num
+ * @param {?=} opt_mo_num
+ * @param {?=} opt_day_num
+ * @param {?=} opt_hr_num
+ * @param {?=} opt_min_num
+ * @param {?=} opt_sec_num
+ * @param {?=} opt_ms_num
+ * @constructor
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date
+ */
+function Date(opt_yr_num, opt_mo_num, opt_day_num, opt_hr_num, opt_min_num,
+ opt_sec_num, opt_ms_num) {}
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/now
+ */
+Date.now = function() {};
+
+/**
+ * Parses a string representation of a date, and returns the number
+ * of milliseconds since January 1, 1970, 00:00:00, local time.
+ * @param {*} date
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/parse
+ */
+Date.parse = function(date) {};
+
+/**
+ * @param {number} year
+ * @param {number} month
+ * @param {number=} opt_date
+ * @param {number=} opt_hours
+ * @param {number=} opt_minute
+ * @param {number=} opt_second
+ * @param {number=} opt_ms
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/UTC
+ */
+Date.UTC = function(year, month,
+ opt_date, opt_hours, opt_minute, opt_second, opt_ms) {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getDate
+ */
+Date.prototype.getDate = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getDay
+ */
+Date.prototype.getDay = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getMonth
+ */
+Date.prototype.getMonth = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getFullYear
+ */
+Date.prototype.getFullYear = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getYear
+ */
+Date.prototype.getYear = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getHours
+ */
+Date.prototype.getHours = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getMinutes
+ */
+Date.prototype.getMinutes = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getSeconds
+ */
+Date.prototype.getSeconds = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getMilliseconds
+ */
+Date.prototype.getMilliseconds = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getTime
+ */
+Date.prototype.getTime = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getTimezoneOffset
+ */
+Date.prototype.getTimezoneOffset = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCDate
+ */
+Date.prototype.getUTCDate = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCDay
+ */
+Date.prototype.getUTCDay = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCMonth
+ */
+Date.prototype.getUTCMonth = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCFullYear
+ */
+Date.prototype.getUTCFullYear = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCHours
+ */
+Date.prototype.getUTCHours = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCMinutes
+ */
+Date.prototype.getUTCMinutes = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCSeconds
+ */
+Date.prototype.getUTCSeconds = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getUTCMilliseconds
+ */
+Date.prototype.getUTCMilliseconds = function() {};
+
+/**
+ * Sets the day of the month for a specified date according to local time.
+ *
+ * @param {number} dayValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setDate
+ */
+Date.prototype.setDate = function(dayValue) {};
+
+/**
+ * Set the month for a specified date according to local time.
+ *
+ * @param {number} monthValue
+ * @param {number=} opt_dayValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setMonth
+ */
+Date.prototype.setMonth = function(monthValue, opt_dayValue) {};
+
+/**
+ * Sets the full year for a specified date according to local time.
+ *
+ * @param {number} yearValue
+ * @param {number=} opt_monthValue
+ * @param {number=} opt_dayValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setFullYear
+ */
+Date.prototype.setFullYear =
+ function(yearValue, opt_monthValue, opt_dayValue) {};
+
+/**
+ * Sets the year for a specified date according to local time.
+ *
+ * @param {number} yearValue
+ * @deprecated
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setYear
+ */
+Date.prototype.setYear = function(yearValue) {};
+
+/**
+ * Sets the hours for a specified date according to local time.
+ *
+ * @param {number} hoursValue
+ * @param {number=} opt_minutesValue
+ * @param {number=} opt_secondsValue
+ * @param {number=} opt_msValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setHours
+ */
+Date.prototype.setHours = function(hoursValue, opt_minutesValue,
+ opt_secondsValue, opt_msValue) {};
+
+/**
+ * Sets the minutes for a specified date according to local time.
+ *
+ * @param {number} minutesValue
+ * @param {number=} opt_secondsValue
+ * @param {number=} opt_msValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setMinutes
+ */
+Date.prototype.setMinutes =
+ function(minutesValue, opt_secondsValue, opt_msValue) {};
+
+/**
+ * Sets the seconds for a specified date according to local time.
+ *
+ * @param {number} secondsValue
+ * @param {number=} opt_msValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setSeconds
+ */
+Date.prototype.setSeconds = function(secondsValue, opt_msValue) {};
+
+/**
+ * Sets the milliseconds for a specified date according to local time.
+ *
+ * @param {number} millisecondsValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setMilliseconds
+ */
+Date.prototype.setMilliseconds = function(millisecondsValue) {};
+
+/**
+ * Sets the Date object to the time represented by a number of milliseconds
+ * since January 1, 1970, 00:00:00 UTC.
+ *
+ * @param {number} timeValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setTime
+ */
+Date.prototype.setTime = function(timeValue) {};
+
+/**
+ * Sets the day of the month for a specified date according to universal time.
+ *
+ * @param {number} dayValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCDate
+ */
+Date.prototype.setUTCDate = function(dayValue) {};
+
+/**
+ * Sets the month for a specified date according to universal time.
+ *
+ * @param {number} monthValue
+ * @param {number=} opt_dayValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCMonth
+ */
+Date.prototype.setUTCMonth = function(monthValue, opt_dayValue) {};
+
+/**
+ * Sets the full year for a specified date according to universal time.
+ *
+ * @param {number} yearValue
+ * @param {number=} opt_monthValue
+ * @param {number=} opt_dayValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCFullYear
+ */
+Date.prototype.setUTCFullYear = function(yearValue, opt_monthValue,
+ opt_dayValue) {};
+
+/**
+ * Sets the hour for a specified date according to universal time.
+ *
+ * @param {number} hoursValue
+ * @param {number=} opt_minutesValue
+ * @param {number=} opt_secondsValue
+ * @param {number=} opt_msValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCHours
+ */
+Date.prototype.setUTCHours = function(hoursValue, opt_minutesValue,
+ opt_secondsValue, opt_msValue) {};
+
+/**
+ * Sets the minutes for a specified date according to universal time.
+ *
+ * @param {number} minutesValue
+ * @param {number=} opt_secondsValue
+ * @param {number=} opt_msValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCMinutes
+ */
+Date.prototype.setUTCMinutes = function(minutesValue, opt_secondsValue,
+ opt_msValue) {};
+
+
+/**
+ * Sets the seconds for a specified date according to universal time.
+ *
+ * @param {number} secondsValue
+ * @param {number=} opt_msValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCSeconds
+ */
+Date.prototype.setUTCSeconds = function(secondsValue, opt_msValue) {};
+
+/**
+ * Sets the milliseconds for a specified date according to universal time.
+ *
+ * @param {number} millisecondsValue
+ * @modifies {this}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/setUTCMilliseconds
+ */
+Date.prototype.setUTCMilliseconds = function(millisecondsValue) {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toSource
+ * @override
+ */
+Date.prototype.toSource = function() {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toDateString
+ */
+Date.prototype.toDateString = function() {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toGMTString
+ */
+Date.prototype.toGMTString = function() {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toTimeString
+ */
+Date.prototype.toTimeString = function() {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toUTCString
+ */
+Date.prototype.toUTCString = function() {};
+
+/**
+ * @param {(string|Array.<string>)=} opt_locales
+ * @param {Object=} opt_options
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toLocaleDateString
+ */
+Date.prototype.toLocaleDateString = function(opt_locales, opt_options) {};
+
+/**
+ * @param {string} formatString
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toLocaleFormat
+ */
+Date.prototype.toLocaleFormat = function(formatString) {};
+
+/**
+ * @param {string|Array.<string>=} opt_locales
+ * @param {Object=} opt_options
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toLocaleString
+ * @see http://www.ecma-international.org/ecma-402/1.0/#sec-13.3.1
+ * @override
+ */
+Date.prototype.toLocaleString = function(opt_locales, opt_options) {};
+
+/**
+ * @param {(string|Array.<string>)=} opt_locales
+ * @param {Object=} opt_options
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toLocaleTimeString
+ */
+Date.prototype.toLocaleTimeString = function(opt_locales, opt_options) {};
+
+/**
+ * @this {Date}
+ * @return {string}
+ * @nosideeffects
+ * @override
+ */
+Date.prototype.toString = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/valueOf
+ */
+Date.prototype.valueOf;
+
+/**
+ * @constructor
+ * @param {*=} opt_str
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String
+ */
+function String(opt_str) {}
+// Functions:
+
+/**
+ * @param {...number} var_args
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/fromCharCode
+ */
+String.fromCharCode = function(var_args) {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/anchor
+ */
+String.prototype.anchor = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/big
+ */
+String.prototype.big = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/blink
+ */
+String.prototype.blink = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/bold
+ */
+String.prototype.bold = function() {};
+
+/**
+ * Returns the specified character from a string.
+ *
+ * @this {String|string}
+ * @param {number} index
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/charAt
+ */
+String.prototype.charAt = function(index) {};
+
+/**
+ * Returns a number indicating the Unicode value of the character at the given
+ * index.
+ *
+ * @this {String|string}
+ * @param {number=} opt_index
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/charCodeAt
+ */
+String.prototype.charCodeAt = function(opt_index) {};
+
+/**
+ * Combines the text of two or more strings and returns a new string.
+ *
+ * @this {String|string}
+ * @param {...*} var_args
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/concat
+ */
+String.prototype.concat = function(var_args) {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/fixed
+ */
+String.prototype.fixed = function() {};
+
+/**
+ * @this {String|string}
+ * @param {string} color
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/fontcolor
+ */
+String.prototype.fontcolor = function(color) {};
+
+/**
+ * @this {String|string}
+ * @param {number} size
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/fontsize
+ */
+String.prototype.fontsize = function(size) {};
+
+/**
+ * Returns the index within the calling String object of the first occurrence
+ * of the specified value, starting the search at fromIndex, returns -1 if the
+ * value is not found.
+ *
+ * @this {String|string}
+ * @param {string|null} searchValue
+ * @param {(number|null)=} opt_fromIndex
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/indexOf
+ */
+String.prototype.indexOf = function(searchValue, opt_fromIndex) {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/italics
+ */
+String.prototype.italics = function() {};
+
+/**
+ * Returns the index within the calling String object of the last occurrence of
+ * the specified value, or -1 if not found. The calling string is searched
+ * backward, starting at fromIndex.
+ *
+ * @this {String|string}
+ * @param {string|null} searchValue
+ * @param {(number|null)=} opt_fromIndex
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/lastIndexOf
+ */
+String.prototype.lastIndexOf = function(searchValue, opt_fromIndex) {};
+
+/**
+ * @this {String|string}
+ * @param {string} hrefAttribute
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/link
+ */
+String.prototype.link = function(hrefAttribute) {};
+
+/**
+ * Returns a number indicating whether a reference string comes before or after
+ * or is the same as the given string in sort order.
+ *
+ * @this {*}
+ * @param {?string} compareString
+ * @param {string|Array.<string>=} locales
+ * @param {Object=} options
+ * @return {number}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/String/localeCompare
+ * @see http://www.ecma-international.org/ecma-402/1.0/#sec-13.1.1
+ */
+String.prototype.localeCompare = function(compareString, locales, options) {};
+
+/**
+ * Used to retrieve the matches when matching a string against a regular
+ * expression.
+ *
+ * @this {String|string}
+ * @param {*} regexp
+ * @return {Array.<string>} This should really return an Array with a few
+ * special properties, but we do not have a good way to model this in
+ * our type system. Also see Regexp.prototype.exec.
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/match
+ */
+String.prototype.match = function(regexp) {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/quote
+ */
+String.prototype.quote = function() {};
+
+/**
+ * Finds a match between a regular expression and a string, and replaces the
+ * matched substring with a new substring.
+ *
+ * This may have side-effects if the replacement function has side-effects.
+ *
+ * @this {String|string}
+ * @param {RegExp|string} regex
+ * @param {string|Function} str
+ * @param {string=} opt_flags
+ * @return {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace
+ */
+String.prototype.replace = function(regex, str, opt_flags) {};
+
+/**
+ * Executes the search for a match between a regular expression and this String
+ * object.
+ *
+ * @this {String|string}
+ * @param {RegExp|string} regexp
+ * @return {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/search
+ */
+String.prototype.search = function(regexp) {};
+
+/**
+ * @this {String|string}
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/slice
+ */
+String.prototype.slice = function(begin, opt_end) {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/small
+ */
+String.prototype.small = function() {};
+
+/**
+ * @this {String|string}
+ * @param {*=} opt_separator
+ * @param {number=} opt_limit
+ * @return {!Array.<string>}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/split
+ */
+String.prototype.split = function(opt_separator, opt_limit) {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/strike
+ */
+String.prototype.strike = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/sub
+ */
+String.prototype.sub = function() {};
+
+/**
+ * @this {String|string}
+ * @param {number} start
+ * @param {number=} opt_length
+ * @return {string} The specified substring.
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/substr
+ */
+String.prototype.substr = function(start, opt_length) {};
+
+/**
+ * @this {String|string}
+ * @param {number} start
+ * @param {number=} opt_end
+ * @return {string} The specified substring.
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/substring
+ */
+String.prototype.substring = function(start, opt_end) {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/sup
+ */
+String.prototype.sup = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/toLocaleUpperCase
+ */
+String.prototype.toLocaleUpperCase = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/toLocaleLowerCase
+ */
+String.prototype.toLocaleLowerCase = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/toLowerCase
+ */
+String.prototype.toLowerCase = function() {};
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/toUpperCase
+ */
+String.prototype.toUpperCase = function() {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/toSource
+ * @override
+ */
+String.prototype.toSource = function() {};
+
+/**
+ * @this {string|String}
+ * @return {string}
+ * @nosideeffects
+ * @override
+ */
+String.prototype.toString = function() {};
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/valueOf
+ */
+String.prototype.valueOf;
+
+/**
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/length
+ */
+String.prototype.length;
+
+/**
+ * @constructor
+ * @param {*=} opt_pattern
+ * @param {*=} opt_flags
+ * @return {!RegExp}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+function RegExp(opt_pattern, opt_flags) {}
+
+/**
+ * @param {*} pattern
+ * @param {*=} opt_flags
+ * @return {void}
+ * @modifies {this}
+ * @deprecated
+ * @see http://msdn.microsoft.com/en-us/library/x9cswe0z(v=VS.85).aspx
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/compile
+ */
+RegExp.prototype.compile = function(pattern, opt_flags) {};
+
+/**
+ * @param {*} str The string to search.
+ * @return {Array.<string>} This should really return an Array with a few
+ * special properties, but we do not have a good way to model this in
+ * our type system. Also see String.prototype.match.
+ * @see http://msdn.microsoft.com/en-us/library/z908hy33(VS.85).aspx
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/exec
+ */
+RegExp.prototype.exec = function(str) {};
+
+/**
+ * @param {*} str The string to search.
+ * @return {boolean} Whether the string was matched.
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/test
+ */
+RegExp.prototype.test = function(str) {};
+
+/**
+ * @this {RegExp}
+ * @return {string}
+ * @nosideeffects
+ * @override
+ */
+RegExp.prototype.toString = function() {};
+
+// Constructor properties:
+
+/**
+ * The string against which the last regexp was matched.
+ * @type {string}
+ * @see http://www.devguru.com/Technologies/Ecmascript/Quickref/regexp_input.html
+ */
+RegExp.input;
+
+/**
+ * The last matched characters.
+ * @type {string}
+ * @see http://www.devguru.com/Technologies/Ecmascript/Quickref/regexp_lastMatch.html
+ */
+RegExp.lastMatch;
+
+/**
+ * The last matched parenthesized substring, if any.
+ * @type {string}
+ * @see http://www.devguru.com/Technologies/Ecmascript/Quickref/regexp_lastParen.html
+ */
+RegExp.lastParen;
+
+/**
+ * The substring of the input up to the characters most recently matched.
+ * @type {string}
+ * @see http://www.devguru.com/Technologies/Ecmascript/Quickref/regexp_leftContext.html
+ */
+RegExp.leftContext;
+
+/**
+ * The substring of the input after the characters most recently matched.
+ * @type {string}
+ * @see http://www.devguru.com/Technologies/Ecmascript/Quickref/regexp_rightContext.html
+ */
+RegExp.rightContext;
+
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$1;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$2;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$3;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$4;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$5;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$6;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$7;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$8;
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
+ */
+RegExp.$9;
+
+// Prototype properties:
+
+/**
+ * Whether to test the regular expression against all possible matches
+ * in a string, or only against the first.
+ * @type {boolean}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/global
+ */
+RegExp.prototype.global;
+
+/**
+ * Whether to ignore case while attempting a match in a string.
+ * @type {boolean}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/ignoreCase
+ */
+RegExp.prototype.ignoreCase;
+
+/**
+ * The index at which to start the next match.
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/lastIndex
+ */
+RegExp.prototype.lastIndex;
+
+/**
+ * Whether or not to search in strings across multiple lines.
+ * @type {boolean}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/multiline
+ */
+RegExp.prototype.multiline;
+
+/**
+ * The text of the pattern.
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/source
+ */
+RegExp.prototype.source;
+
+
+/**
+ * @constructor
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!Error}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error
+ */
+function Error(opt_message, opt_file, opt_line) {}
+
+
+/**
+ * Chrome/v8 specific, altering the maximum depth of the stack trace
+ * (10 by default).
+ * @type {number}
+ * @see http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+ */
+Error.stackTraceLimit;
+
+
+/**
+ * Chrome/v8 specific, adds a stack trace to the error object. The optional
+ * constructorOpt parameter allows you to pass in a function value. When
+ * collecting the stack trace all frames above the topmost call to this
+ * function, including that call, will be left out of the stack trace.
+ * @param {Object} error The object to add the stack trace to.
+ * @param {Function=} opt_constructor A function in the stack trace
+ * @see http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+ */
+Error.captureStackTrace = function(error, opt_constructor){};
+
+
+/**
+ * IE-only.
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/2w6a45b5.aspx
+ */
+Error.prototype.description;
+
+
+/**
+ * Mozilla-only.
+ * @type {number}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/lineNumber
+ */
+Error.prototype.lineNumber;
+
+/**
+ * Mozilla-only
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/fileName
+ */
+Error.prototype.fileName;
+
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/name
+ */
+Error.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/message
+ */
+Error.prototype.message;
+
+/**
+ * Doesn't seem to exist, but closure/debug.js references it.
+ */
+Error.prototype.sourceURL;
+
+/** @type {string} */
+Error.prototype.stack;
+
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!EvalError}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/EvalError
+ */
+function EvalError(opt_message, opt_file, opt_line) {}
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!RangeError}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RangeError
+ */
+function RangeError(opt_message, opt_file, opt_line) {}
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!ReferenceError}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/ReferenceError
+ */
+function ReferenceError(opt_message, opt_file, opt_line) {}
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!SyntaxError}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/SyntaxError
+ */
+function SyntaxError(opt_message, opt_file, opt_line) {}
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!TypeError}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/TypeError
+ */
+function TypeError(opt_message, opt_file, opt_line) {}
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @param {*=} opt_message
+ * @param {*=} opt_file
+ * @param {*=} opt_line
+ * @return {!URIError}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/URIError
+ */
+function URIError(opt_message, opt_file, opt_line) {}
+
+
+// JScript extensions.
+// @see http://msdn.microsoft.com/en-us/library/894hfyb4(VS.80).aspx
+
+/**
+ * @param {string} progId
+ * @param {string=} opt_location
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/7sw4ddf8.aspx
+ */
+function ActiveXObject(progId, opt_location) {}
+
+/**
+ * @return {string}
+ * @nosideeffects
+ * @see http://msdn.microsoft.com/en-us/library/9k34bww2(VS.80).aspx
+ */
+function ScriptEngine() {}
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://msdn.microsoft.com/en-us/library/yf25ky07(VS.80).aspx
+ */
+function ScriptEngineMajorVersion() {}
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://msdn.microsoft.com/en-us/library/wx3812cz(VS.80).aspx
+ */
+function ScriptEngineMinorVersion() {}
+
+/**
+ * @return {number}
+ * @nosideeffects
+ * @see http://msdn.microsoft.com/en-us/library/e98hsk2f(VS.80).aspx
+ */
+function ScriptEngineBuildVersion() {}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es5.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es5.js
new file mode 100644
index 0000000000..a7d444a8aa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es5.js
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for ECMAScript 5.
+ * @see http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
+ * @externs
+ */
+
+
+/**
+ * @param {Object|undefined} selfObj Specifies the object to which |this| should
+ * point when the function is run. If the value is null or undefined, it
+ * will default to the global object.
+ * @param {...*} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {!Function} A partially-applied form of the Function on which
+ * bind() was invoked as a method.
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
+ */
+Function.prototype.bind = function(selfObj, var_args) {};
+
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim
+ */
+String.prototype.trim = function() {};
+
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/TrimLeft
+ */
+String.prototype.trimLeft = function() {};
+
+
+/**
+ * @this {String|string}
+ * @return {string}
+ * @nosideeffects
+ * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/TrimRight
+ */
+String.prototype.trimRight = function() {};
+
+
+/**
+ * A object property descriptor used by Object.create, Object.defineProperty,
+ * Object.defineProperties, Object.getOwnPropertyDescriptor.
+ *
+ * Note: not a real constructor.
+ * @constructor
+ */
+var ObjectPropertyDescriptor = function(){};
+
+/** @type {*} */
+ObjectPropertyDescriptor.prototype.value;
+
+/** @type {(function():?)||undefined} */
+ObjectPropertyDescriptor.prototype.get;
+
+/** @type {(function(?):void)||undefined} */
+ObjectPropertyDescriptor.prototype.set;
+
+/** @type {boolean|undefined} */
+ObjectPropertyDescriptor.prototype.writable;
+
+/** @type {boolean|undefined} */
+ObjectPropertyDescriptor.prototype.enumerable;
+
+/** @type {boolean|undefined} */
+ObjectPropertyDescriptor.prototype.configurable;
+
+
+/**
+ * @param {Object} proto
+ * @param {Object=} opt_properties A map of ObjectPropertyDescriptors.
+ * @return {!Object}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create
+ */
+Object.create = function(proto, opt_properties) {};
+
+
+/**
+ * @param {!Object} obj
+ * @param {string} prop
+ * @param {!Object} descriptor A ObjectPropertyDescriptor.
+ * @return {!Object}
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
+ */
+Object.defineProperty = function(obj, prop, descriptor) {};
+
+
+/**
+ * @param {!Object} obj
+ * @param {!Object} props A map of ObjectPropertyDescriptors.
+ * @return {!Object}
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperties
+ */
+Object.defineProperties = function(obj, props) {};
+
+
+/**
+ * @param {!Object} obj
+ * @param {string} prop
+ * @return {!ObjectPropertyDescriptor|undefined}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
+ */
+Object.getOwnPropertyDescriptor = function(obj, prop) {};
+
+
+/**
+ * @param {!Object} obj
+ * @return {!Array.<string>}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
+ */
+Object.keys = function(obj) {};
+
+
+/**
+ * @param {!Object} obj
+ * @return {!Array.<string>}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
+ */
+Object.getOwnPropertyNames = function(obj) {};
+
+
+/**
+ * @param {!Object} obj
+ * @return {Object}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/GetPrototypeOf
+ */
+Object.getPrototypeOf = function(obj) {};
+
+
+/**
+ * @param {T} obj
+ * @return {T}
+ * @template T
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/preventExtensions
+ */
+Object.preventExtensions = function(obj) {};
+
+
+/**
+ * @param {T} obj
+ * @return {T}
+ * @template T
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/seal
+ */
+Object.seal = function(obj) {};
+
+
+/**
+ * @param {T} obj
+ * @return {T}
+ * @template T
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze
+ */
+Object.freeze = function(obj) {};
+
+
+/**
+ * @param {!Object} obj
+ * @return {boolean}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isExtensible
+ */
+Object.isExtensible = function(obj) {};
+
+
+/**
+ * @param {!Object} obj
+ * @return {boolean}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isSealed
+ */
+Object.isSealed = function(obj) {};
+
+
+/**
+ * @param {!Object} obj
+ * @return {boolean}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isFrozen
+ */
+Object.isFrozen = function(obj) {};
+
+
+/**
+ * As per ECMAScript 5, 15.12.3.
+ * @param {string=} opt_key The JSON key for this object.
+ * @return {*} The serializable representation of this object. Note that this
+ * need not be a string. See http://goo.gl/PEUvs.
+ */
+Object.prototype.toJSON = function(opt_key) {};
+
+
+/**
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toISOString
+ * @return {string}
+ */
+Date.prototype.toISOString = function() {};
+
+
+/**
+ * @param {*=} opt_ignoredKey
+ * @return {string}
+ * @override
+ */
+Date.prototype.toJSON = function(opt_ignoredKey) {};
+
+
+/**
+ * A fake type to model the JSON object.
+ * @constructor
+ */
+var JSONType = function() {};
+
+
+/**
+ * @param {string} jsonStr The string to parse.
+ * @param {(function(string, *) : *)=} opt_reviver
+ * @return {*} The JSON object.
+ * @throws {Error}
+ * @nosideeffects
+ */
+JSONType.prototype.parse = function(jsonStr, opt_reviver) {};
+
+
+/**
+ * @param {*} jsonObj Input object.
+ * @param {(Array.<string>|(function(string, *) : *)|null)=} opt_replacer
+ * @param {(number|string)=} opt_space
+ * @return {string} JSON string which represents jsonObj.
+ * @throws {Error}
+ * @nosideeffects
+ */
+JSONType.prototype.stringify = function(jsonObj, opt_replacer, opt_space) {};
+
+
+/**
+ * @type {!JSONType}
+ * @suppress {duplicate}
+ */
+var JSON;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6.js
new file mode 100644
index 0000000000..4afb5777a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6.js
@@ -0,0 +1,856 @@
+/*
+ * Copyright 2014 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for ECMAScript 6.
+ * @see http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
+ * @see https://www.khronos.org/registry/typedarray/specs/latest/
+ * @externs
+ */
+
+// TODO(johnlenz): symbol should be a primitive type.
+/** @typedef {?} */
+var symbol;
+
+/**
+ * @param {string} description
+ * @return {symbol}
+ */
+function Symbol(description) {}
+
+/** @const {symbol} */
+Symbol.iterator;
+
+
+/**
+ * @interface
+ * @template VALUE
+ */
+function Iterable() {}
+
+// TODO(johnlenz): remove this when the compiler understands "symbol" natively
+/**
+ * @return {Iterator.<VALUE>}
+ * @suppress {externsValidation}
+ */
+Iterable.prototype[Symbol.iterator] = function() {};
+
+
+
+// TODO(johnlenz): Iterator should be a templated record type.
+/**
+ * @interface
+ * @template VALUE
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
+ */
+function Iterator() {}
+
+/**
+ * @param {VALUE=} value
+ * @return {{value:VALUE, done:boolean}}
+ */
+Iterator.prototype.next;
+
+
+/**
+ * @constructor
+ * @see http://people.mozilla.org/~jorendorff/es6-draft.html#sec-generator-objects
+ * @implements {Iterator<VALUE>}
+ * @template VALUE
+ */
+var Generator = function() {};
+
+/**
+ * @param {?=} opt_value
+ * @return {{value:VALUE, done:boolean}}
+ * @override
+ */
+Generator.prototype.next = function(opt_value) {};
+
+/**
+ * @param {VALUE} value
+ * @return {{value:VALUE, done:boolean}}
+ */
+Generator.prototype.return = function(value) {};
+
+/**
+ * @param {?} exception
+ * @return {{value:VALUE, done:boolean}}
+ */
+Generator.prototype.throw = function(exception) {};
+
+
+// TODO(johnlenz): Array should be Iterable.
+
+
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.log10 = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.log2 = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.log1p = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.expm1 = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.cosh = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.sinh = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.tanh = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.acosh = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.asinh = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.atanh = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.trunc = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.sign = function(value) {};
+
+/**
+ * @param {number} value
+ * @return {number}
+ * @nosideeffects
+ */
+Math.cbrt = function(value) {};
+
+/**
+ * @param {number} value1
+ * @param {...number} var_args
+ * @return {number}
+ * @nosideeffects
+ * @see http://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.hypot
+ */
+Math.hypot = function(value1, var_args) {};
+
+
+/**
+ * @param {*} a
+ * @param {*} b
+ * @return {boolean}
+ * @see http://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.is
+ */
+Object.is;
+
+
+/**
+ * Returns a language-sensitive string representation of this number.
+ * @param {(string|!Array<string>)=} opt_locales
+ * @param {Object=} opt_options
+ * @return {string}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
+ * @see http://www.ecma-international.org/ecma-402/1.0/#sec-13.2.1
+ * @override
+ */
+Number.prototype.toLocaleString = function(opt_locales, opt_options) {};
+
+
+/**
+ * @see http://dev.w3.org/html5/postmsg/
+ * @interface
+ */
+function Transferable() {}
+
+/**
+ * @param {number} length The length in bytes
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @nosideeffects
+ * @implements {Transferable}
+ */
+function ArrayBuffer(length) {}
+
+/** @type {number} */
+ArrayBuffer.prototype.byteLength;
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!ArrayBuffer}
+ * @nosideeffects
+ */
+ArrayBuffer.prototype.slice = function(begin, opt_end) {};
+
+
+/**
+ * @constructor
+ * @noalias
+ */
+function ArrayBufferView() {}
+
+/** @type {!ArrayBuffer} */
+ArrayBufferView.prototype.buffer;
+
+/** @type {number} */
+ArrayBufferView.prototype.byteOffset;
+
+/** @type {number} */
+ArrayBufferView.prototype.byteLength;
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments} If the user passes a backing array, then indexed
+ * accesses will modify the backing array. JSCompiler does not model
+ * this well. In other words, if you have:
+ * <code>
+ * var x = new ArrayBuffer(1);
+ * var y = new Int8Array(x);
+ * y[0] = 2;
+ * </code>
+ * JSCompiler will not recognize that the last assignment modifies x.
+ * We workaround this by marking all these arrays as @modifies {arguments},
+ * to introduce the possibility that x aliases y.
+ */
+function Int8Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Int8Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Int8Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Int8Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Int8Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Int8Array}
+ * @nosideeffects
+ */
+Int8Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Uint8Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Uint8Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint8Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint8Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Uint8Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Uint8Array}
+ * @nosideeffects
+ */
+Uint8Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Uint8ClampedArray(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Uint8ClampedArray.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint8ClampedArray.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint8ClampedArray.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Uint8ClampedArray.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Uint8ClampedArray}
+ * @nosideeffects
+ */
+Uint8ClampedArray.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @typedef {Uint8ClampedArray}
+ * @deprecated CanvasPixelArray has been replaced by Uint8ClampedArray
+ * in the latest spec.
+ * @see http://www.w3.org/TR/2dcontext/#imagedata
+ */
+var CanvasPixelArray;
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Int16Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Int16Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Int16Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Int16Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Int16Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Int16Array}
+ * @nosideeffects
+ */
+Int16Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Uint16Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Uint16Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint16Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint16Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Uint16Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Uint16Array}
+ * @nosideeffects
+ */
+Uint16Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Int32Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Int32Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Int32Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Int32Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Int32Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Int32Array}
+ * @nosideeffects
+ */
+Int32Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Uint32Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Uint32Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint32Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Uint32Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Uint32Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Uint32Array}
+ * @nosideeffects
+ */
+Uint32Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Float32Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Float32Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Float32Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Float32Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Float32Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Float32Array}
+ * @nosideeffects
+ */
+Float32Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {number|ArrayBufferView|Array.<number>|ArrayBuffer} length or array
+ * or buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_length
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @modifies {arguments}
+ */
+function Float64Array(length, opt_byteOffset, opt_length) {}
+
+/** @type {number} */
+Float64Array.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Float64Array.prototype.BYTES_PER_ELEMENT;
+
+/** @type {number} */
+Float64Array.prototype.length;
+
+/**
+ * @param {ArrayBufferView|Array.<number>} array
+ * @param {number=} opt_offset
+ */
+Float64Array.prototype.set = function(array, opt_offset) {};
+
+/**
+ * @param {number} begin
+ * @param {number=} opt_end
+ * @return {!Float64Array}
+ * @nosideeffects
+ */
+Float64Array.prototype.subarray = function(begin, opt_end) {};
+
+
+/**
+ * @param {ArrayBuffer} buffer
+ * @param {number=} opt_byteOffset
+ * @param {number=} opt_byteLength
+ * @extends {ArrayBufferView}
+ * @constructor
+ * @noalias
+ * @throws {Error}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/DataView
+ */
+function DataView(buffer, opt_byteOffset, opt_byteLength) {}
+
+/**
+ * @param {number} byteOffset
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getInt8 = function(byteOffset) {};
+
+/**
+ * @param {number} byteOffset
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getUint8 = function(byteOffset) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {boolean=} opt_littleEndian
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getInt16 = function(byteOffset, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {boolean=} opt_littleEndian
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getUint16 = function(byteOffset, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {boolean=} opt_littleEndian
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getInt32 = function(byteOffset, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {boolean=} opt_littleEndian
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getUint32 = function(byteOffset, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {boolean=} opt_littleEndian
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getFloat32 = function(byteOffset, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {boolean=} opt_littleEndian
+ * @return {number}
+ * @throws {Error}
+ * @nosideeffects
+ */
+DataView.prototype.getFloat64 = function(byteOffset, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @throws {Error}
+ */
+DataView.prototype.setInt8 = function(byteOffset, value) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @throws {Error}
+ */
+DataView.prototype.setUint8 = function(byteOffset, value) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @param {boolean=} opt_littleEndian
+ * @throws {Error}
+ */
+DataView.prototype.setInt16 = function(byteOffset, value, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @param {boolean=} opt_littleEndian
+ * @throws {Error}
+ */
+DataView.prototype.setUint16 = function(byteOffset, value, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @param {boolean=} opt_littleEndian
+ * @throws {Error}
+ */
+DataView.prototype.setInt32 = function(byteOffset, value, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @param {boolean=} opt_littleEndian
+ * @throws {Error}
+ */
+DataView.prototype.setUint32 = function(byteOffset, value, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @param {boolean=} opt_littleEndian
+ * @throws {Error}
+ */
+DataView.prototype.setFloat32 = function(
+ byteOffset, value, opt_littleEndian) {};
+
+/**
+ * @param {number} byteOffset
+ * @param {number} value
+ * @param {boolean=} opt_littleEndian
+ * @throws {Error}
+ */
+DataView.prototype.setFloat64 = function(
+ byteOffset, value, opt_littleEndian) {};
+
+
+/**
+ * @see https://github.com/promises-aplus/promises-spec
+ * @typedef {{then: !Function}}
+ */
+var Thenable;
+
+
+/**
+ * This is not an official DOM interface. It is used to add generic typing
+ * and respective type inference where available.
+ * {@see goog.Thenable} inherits from this making all promises
+ * interoperate.
+ * @interface
+ * @template TYPE
+ */
+var IThenable = function() {};
+
+
+/**
+ * @param {?(function(TYPE):
+ * (RESULT|IThenable.<RESULT>|Thenable))=} opt_onFulfilled
+ * @param {?(function(*): *)=} opt_onRejected
+ * @return {!IThenable.<RESULT>}
+ * @template RESULT
+ */
+IThenable.prototype.then = function(opt_onFulfilled, opt_onRejected) {};
+
+
+/**
+ * @see https://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-objects
+ * @param {function(
+ * function((TYPE|IThenable.<TYPE>|Thenable|null)=),
+ * function(*=))} resolver
+ * @constructor
+ * @implements {IThenable.<TYPE>}
+ * @template TYPE
+ */
+var Promise = function(resolver) {};
+
+
+/**
+ * @param {(TYPE|IThenable.<TYPE>)=} opt_value
+ * @return {!Promise.<TYPE>}
+ * @template TYPE
+ */
+Promise.resolve = function(opt_value) {};
+
+
+/**
+ * @param {*=} opt_error
+ * @return {!Promise.<?>}
+ */
+Promise.reject = function(opt_error) {};
+
+
+/**
+ * @template T
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
+ * @param {!Array<T|!Promise<T>>} iterable
+ * @return {!Promise<!Array<T>>}
+ */
+Promise.all = function(iterable) {};
+
+
+/**
+ * @template T
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
+ * @param {!Array.<T>} iterable
+ * @return {!Promise.<T>}
+ */
+Promise.race = function(iterable) {};
+
+
+/**
+ * @param {?(function(TYPE):
+ * (RESULT|IThenable.<RESULT>|Thenable))=} opt_onFulfilled
+ * @param {?(function(*): *)=} opt_onRejected
+ * @return {!Promise.<RESULT>}
+ * @template RESULT
+ * @override
+ */
+Promise.prototype.then = function(opt_onFulfilled, opt_onRejected) {};
+
+
+/**
+ * @param {function(*): RESULT} onRejected
+ * @return {!Promise.<RESULT>}
+ * @template RESULT
+ */
+Promise.prototype.catch = function(onRejected) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6_collections.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6_collections.js
new file mode 100644
index 0000000000..8be2d6daa4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/es6_collections.js
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2014 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for ECMAScript 6.
+ * @see http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
+ * @externs
+ */
+
+// TODO(johnlenz): Use Tuples for the Map and Set iterators where appropriate.
+
+/**
+ * @constructor
+ * @param {Iterable.<!Array.<KEY|VALUE>>|!Array.<!Array.<KEY|VALUE>>=} opt_iterable
+ * @implements {Iterable.<!Array.<KEY|VALUE>>}
+ * @template KEY, VALUE
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
+ */
+function Map(opt_iterable) {}
+
+/** @return {void} */
+Map.prototype.clear;
+
+/**
+ * @param {KEY} key
+ * @return {boolean}
+ */
+Map.prototype.delete;
+
+/**
+ * @return {!Iterator.<!Array.<KEY|VALUE>>}
+ * @nosideeffects
+ */
+Map.prototype.entries;
+
+/**
+ * @param {function(this:THIS, VALUE, KEY, MAP):void} callback
+ * @param {THIS} thisArg
+ * @this {MAP}
+ * @template MAP,THIS
+ */
+Map.prototype.forEach;
+
+/**
+ * @param {KEY} key
+ * @return {VALUE|undefined}
+ * @nosideeffects
+ */
+Map.prototype.get;
+
+/**
+ * @param {KEY} key
+ * @return {boolean}
+ * @nosideeffects
+ */
+Map.prototype.has;
+
+/**
+ * @return {!Iterator.<KEY>}
+ */
+Map.prototype.keys;
+
+/**
+ * @param {KEY} key
+ * @param {VALUE} value
+ * @return {THIS}
+ * @this {THIS}
+ * @template THIS
+ */
+Map.prototype.set;
+
+/**
+ * @type {number}
+ * (readonly)
+ */
+Map.prototype.size;
+
+/**
+ * @return {!Iterator.<VALUE>}
+ * @nosideeffects
+ */
+Map.prototype.values;
+
+/**
+ * @return {!Iterator.<!Array.<KEY|VALUE>>}
+ */
+Map.prototype[Symbol.iterator] = function() {};
+
+
+/**
+ * @constructor
+ * @param {Iterable.<!Array.<KEY|VALUE>>|!Array.<!Array.<KEY|VALUE>>=} opt_iterable
+ * @template KEY, VALUE
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
+ */
+function WeakMap(opt_iterable) {}
+
+/** @return {void} */
+WeakMap.prototype.clear;
+
+/**
+ * @param {KEY} key
+ * @return {boolean}
+ */
+WeakMap.prototype.delete;
+
+/**
+ * @param {KEY} key
+ * @return {VALUE|undefined}
+ * @nosideeffects
+ */
+WeakMap.prototype.get;
+
+/**
+ * @param {KEY} key
+ * @return {boolean}
+ * @nosideeffects
+ */
+WeakMap.prototype.has;
+
+/**
+ * @param {KEY} key
+ * @param {VALUE} value
+ * @return {THIS}
+ * @this {THIS}
+ * @template THIS
+ */
+WeakMap.prototype.set;
+
+
+
+/**
+ * @constructor
+ * @param {Iterable.<VALUE>|Array.<VALUE>=} opt_iterable
+ * @implements {Iterable.<VALUE>}
+ * @template VALUE
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
+ */
+function Set(opt_iterable) {}
+
+/**
+ * @param {VALUE} value
+ * @return {THIS}
+ * @this {THIS}
+ * @template THIS
+ */
+Set.prototype.add;
+
+/**
+ * @return {void}
+ */
+Set.prototype.clear;
+
+/**
+ * @param {VALUE} value
+ * @return {boolean}
+ */
+Set.prototype.delete;
+
+/**
+ * @return {!Iterator.<!Array.<VALUE>>} Where each array has two entries:
+ * [value, value]
+ * @nosideeffects
+ */
+Set.prototype.entries;
+
+/**
+ * @param {function(VALUE, VALUE, SET)} callback
+ * @param {THIS} thisArg
+ * @this {SET}
+ * @template SET,THIS
+ */
+Set.prototype.forEach;
+
+/**
+ * @param {VALUE} value
+ * @return {boolean}
+ * @nosideeffects
+ */
+Set.prototype.has;
+
+/**
+ * @type {number} (readonly)
+ */
+Set.prototype.size;
+
+/**
+ * @return {!Iterator.<VALUE>}
+ * @nosideeffects
+ */
+Set.prototype.keys;
+
+/**
+ * @return {!Iterator.<VALUE>}
+ * @nosideeffects
+ */
+Set.prototype.values;
+
+/**
+ * @return {!Iterator.<VALUE>}
+ */
+Set.prototype[Symbol.iterator] = function() {};
+
+
+
+/**
+ * @constructor
+ * @param {Iterable.<VALUE>|Array.<VALUE>=} opt_iterable
+ * @template VALUE
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
+ */
+function WeakSet(opt_iterable) {}
+
+/**
+ * @param {VALUE} value
+ * @return {THIS}
+ * @this {THIS}
+ * @template THIS
+ */
+WeakSet.prototype.add;
+
+/**
+ * @return {void}
+ */
+WeakSet.prototype.clear;
+
+/**
+ * @param {VALUE} value
+ * @return {boolean}
+ */
+WeakSet.prototype.delete;
+
+/**
+ * @param {VALUE} value
+ * @return {boolean}
+ * @nosideeffects
+ */
+WeakSet.prototype.has;
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/fileapi.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/fileapi.js
new file mode 100644
index 0000000000..f878a9d227
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/fileapi.js
@@ -0,0 +1,961 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for objects in the File API, File Writer API, and
+ * File System API. Details of the API are at:
+ * http://www.w3.org/TR/FileAPI/
+ * http://www.w3.org/TR/file-writer-api/
+ * http://www.w3.org/TR/file-system-api/
+ *
+ * @externs
+ * @author dbk@google.com (David Barrett-Kahn)
+ */
+
+
+/**
+ * @see http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob
+ * @param {Array.<ArrayBufferView|Blob|string>=} opt_blobParts
+ * @param {Object=} opt_options
+ * @constructor
+ * @nosideeffects
+ */
+function Blob(opt_blobParts, opt_options) {}
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-size
+ * @type {number}
+ */
+Blob.prototype.size;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-type
+ * @type {string}
+ */
+Blob.prototype.type;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-slice
+ * @param {number} start
+ * @param {number} length
+ * @return {!Blob}
+ * @nosideeffects
+ */
+Blob.prototype.slice = function(start, length) {};
+
+/**
+ * This replaces Blob.slice in Chrome since WebKit revision 84005.
+ * @see http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/0222.html
+ * @param {number} start
+ * @param {number} end
+ * @return {!Blob}
+ * @nosideeffects
+ */
+Blob.prototype.webkitSlice = function(start, end) {};
+
+/**
+ * This replaces Blob.slice in Firefox.
+ * @see http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/0222.html
+ * @param {number} start
+ * @param {number} end
+ * @return {!Blob}
+ * @nosideeffects
+ */
+Blob.prototype.mozSlice = function(start, end) {};
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#the-blobbuilder-interface
+ * @constructor
+ */
+function BlobBuilder() {}
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-append0
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-append1
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-append2
+ * @param {string|Blob|ArrayBuffer} data
+ * @param {string=} endings
+ */
+BlobBuilder.prototype.append = function(data, endings) {};
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-getBlob
+ * @param {string=} contentType
+ * @return {!Blob}
+ */
+BlobBuilder.prototype.getBlob = function(contentType) {};
+
+/**
+ * This has replaced BlobBuilder in Chrome since WebKit revision 84008.
+ * @see http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/0222.html
+ * @constructor
+ */
+function WebKitBlobBuilder() {}
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-append0
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-append1
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-append2
+ * @param {string|Blob|ArrayBuffer} data
+ * @param {string=} endings
+ */
+WebKitBlobBuilder.prototype.append = function(data, endings) {};
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-BlobBuilder-getBlob
+ * @param {string=} contentType
+ * @return {!Blob}
+ */
+WebKitBlobBuilder.prototype.getBlob = function(contentType) {};
+
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#the-directoryentry-interface
+ * @constructor
+ * @extends {Entry}
+ */
+function DirectoryEntry() {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntry-createReader
+ * @return {!DirectoryReader}
+ */
+DirectoryEntry.prototype.createReader = function() {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntry-getFile
+ * @param {string} path
+ * @param {Object=} options
+ * @param {function(!FileEntry)=} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+DirectoryEntry.prototype.getFile = function(path, options, successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntry-getDirectory
+ * @param {string} path
+ * @param {Object=} options
+ * @param {function(!DirectoryEntry)=} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+DirectoryEntry.prototype.getDirectory = function(path, options, successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntry-removeRecursively
+ * @param {function()} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+DirectoryEntry.prototype.removeRecursively = function(successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#the-directoryreader-interface
+ * @constructor
+ */
+function DirectoryReader() {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryReader-readEntries
+ * @param {function(!Array.<!Entry>)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+DirectoryReader.prototype.readEntries = function(successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#the-entry-interface
+ * @constructor
+ */
+function Entry() {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-isFile
+ * @type {boolean}
+ */
+Entry.prototype.isFile;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-isDirectory
+ * @type {boolean}
+ */
+Entry.prototype.isDirectory;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-name
+ * @type {string}
+ */
+Entry.prototype.name;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-fullPath
+ * @type {string}
+ */
+Entry.prototype.fullPath;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-filesystem
+ * @type {!FileSystem}
+ */
+Entry.prototype.filesystem;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-moveTo
+ * @param {!DirectoryEntry} parent
+ * @param {string=} newName
+ * @param {function(!Entry)=} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Entry.prototype.moveTo = function(parent, newName, successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-copyTo
+ * @param {!DirectoryEntry} parent
+ * @param {string=} newName
+ * @param {function(!Entry)=} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Entry.prototype.copyTo = function(parent, newName, successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-toURL
+ * @param {string=} mimeType
+ * @return {string}
+ */
+Entry.prototype.toURL = function(mimeType) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-remove
+ * @param {function()} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Entry.prototype.remove = function(successCallback, errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-getMetadata
+ * @param {function(!Metadata)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Entry.prototype.getMetadata = function(successCallback, errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Entry-getParent
+ * @param {function(!Entry)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Entry.prototype.getParent = function(successCallback, errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-file
+ * @constructor
+ * @extends {Blob}
+ */
+function File() {}
+
+/**
+ * Chrome uses this instead of name.
+ * @deprecated Use name instead.
+ * @type {string}
+ */
+File.prototype.fileName;
+
+/**
+ * Chrome uses this instead of size.
+ * @deprecated Use size instead.
+ * @type {string}
+ */
+File.prototype.fileSize;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-name
+ * @type {string}
+ */
+File.prototype.name;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate
+ * @type {Date}
+ */
+File.prototype.lastModifiedDate;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#the-fileentry-interface
+ * @constructor
+ * @extends {Entry}
+ */
+function FileEntry() {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileEntry-createWriter
+ * @param {function(!FileWriter)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+FileEntry.prototype.createWriter = function(successCallback, errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileEntry-file
+ * @param {function(!File)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+FileEntry.prototype.file = function(successCallback, errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#FileErrorInterface
+ * @constructor
+ * @extends {DOMError}
+ */
+function FileError() {}
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-NOT_FOUND_ERR
+ * @type {number}
+ */
+FileError.prototype.NOT_FOUND_ERR = 1;
+
+/** @type {number} */
+FileError.NOT_FOUND_ERR = 1;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-SECURITY_ERR
+ * @type {number}
+ */
+FileError.prototype.SECURITY_ERR = 2;
+
+/** @type {number} */
+FileError.SECURITY_ERR = 2;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-ABORT_ERR
+ * @type {number}
+ */
+FileError.prototype.ABORT_ERR = 3;
+
+/** @type {number} */
+FileError.ABORT_ERR = 3;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-NOT_READABLE_ERR
+ * @type {number}
+ */
+FileError.prototype.NOT_READABLE_ERR = 4;
+
+/** @type {number} */
+FileError.NOT_READABLE_ERR = 4;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-ENCODING_ERR
+ * @type {number}
+ */
+FileError.prototype.ENCODING_ERR = 5;
+
+/** @type {number} */
+FileError.ENCODING_ERR = 5;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileError-NO_MODIFICATION_ALLOWED_ERR
+ * @type {number}
+ */
+FileError.prototype.NO_MODIFICATION_ALLOWED_ERR = 6;
+
+/** @type {number} */
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-INVALID_STATE_ERR
+ * @type {number}
+ */
+FileError.prototype.INVALID_STATE_ERR = 7;
+
+/** @type {number} */
+FileError.INVALID_STATE_ERR = 7;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-SYNTAX_ERR
+ * @type {number}
+ */
+FileError.prototype.SYNTAX_ERR = 8;
+
+/** @type {number} */
+FileError.SYNTAX_ERR = 8;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileError-INVALID_MODIFICATION_ERR
+ * @type {number}
+ */
+FileError.prototype.INVALID_MODIFICATION_ERR = 9;
+
+/** @type {number} */
+FileError.INVALID_MODIFICATION_ERR = 9;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileError-QUOTA_EXCEEDED_ERR
+ * @type {number}
+ */
+FileError.prototype.QUOTA_EXCEEDED_ERR = 10;
+
+/** @type {number} */
+FileError.QUOTA_EXCEEDED_ERR = 10;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileException-TYPE_MISMATCH_ERR
+ * @type {number}
+ */
+FileError.prototype.TYPE_MISMATCH_ERR = 11;
+
+/** @type {number} */
+FileError.TYPE_MISMATCH_ERR = 11;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileException-PATH_EXISTS_ERR
+ * @type {number}
+ */
+FileError.prototype.PATH_EXISTS_ERR = 12;
+
+/** @type {number} */
+FileError.PATH_EXISTS_ERR = 12;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-code-exception
+ * @type {number}
+ * @deprecated Use the 'name' or 'message' attributes of DOMError rather than
+ * 'code'
+ */
+FileError.prototype.code;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-filereader
+ * @constructor
+ * @implements {EventTarget}
+ */
+function FileReader() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+FileReader.prototype.addEventListener = function(type, listener, opt_useCapture)
+ {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+FileReader.prototype.removeEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/** @override */
+FileReader.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-readAsArrayBuffer
+ * @param {!Blob} blob
+ */
+FileReader.prototype.readAsArrayBuffer = function(blob) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-readAsBinaryStringAsync
+ * @param {!Blob} blob
+ */
+FileReader.prototype.readAsBinaryString = function(blob) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-readAsText
+ * @param {!Blob} blob
+ * @param {string=} encoding
+ */
+FileReader.prototype.readAsText = function(blob, encoding) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-readAsDataURL
+ * @param {!Blob} blob
+ */
+FileReader.prototype.readAsDataURL = function(blob) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-abort
+ */
+FileReader.prototype.abort = function() {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-empty
+ * @type {number}
+ */
+FileReader.prototype.EMPTY = 0;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-loading
+ * @type {number}
+ */
+FileReader.prototype.LOADING = 1;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-done
+ * @type {number}
+ */
+FileReader.prototype.DONE = 2;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-readystate
+ * @type {number}
+ */
+FileReader.prototype.readyState;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-result
+ * @type {string|Blob|ArrayBuffer}
+ */
+FileReader.prototype.result;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-error
+ * @type {FileError}
+ */
+FileReader.prototype.error;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-onloadstart
+ * @type {?function(!ProgressEvent)}
+ */
+FileReader.prototype.onloadstart;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-onprogress
+ * @type {?function(!ProgressEvent)}
+ */
+FileReader.prototype.onprogress;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-onload
+ * @type {?function(!ProgressEvent)}
+ */
+FileReader.prototype.onload;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-onabort
+ * @type {?function(!ProgressEvent)}
+ */
+FileReader.prototype.onabort;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-onerror
+ * @type {?function(!ProgressEvent)}
+ */
+FileReader.prototype.onerror;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-onloadend
+ * @type {?function(!ProgressEvent)}
+ */
+FileReader.prototype.onloadend;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#idl-def-FileSaver
+ * @constructor
+ */
+function FileSaver() {};
+
+/** @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-abort */
+FileSaver.prototype.abort = function() {};
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-INIT
+ * @type {number}
+ */
+FileSaver.prototype.INIT = 0;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-WRITING
+ * @type {number}
+ */
+FileSaver.prototype.WRITING = 1;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-DONE
+ * @type {number}
+ */
+FileSaver.prototype.DONE = 2;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-readyState
+ * @type {number}
+ */
+FileSaver.prototype.readyState;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-error
+ * @type {FileError}
+ */
+FileSaver.prototype.error;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-onwritestart
+ * @type {?function(!ProgressEvent)}
+ */
+FileSaver.prototype.onwritestart;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-onprogress
+ * @type {?function(!ProgressEvent)}
+ */
+FileSaver.prototype.onprogress;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-onwrite
+ * @type {?function(!ProgressEvent)}
+ */
+FileSaver.prototype.onwrite;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-onabort
+ * @type {?function(!ProgressEvent)}
+ */
+FileSaver.prototype.onabort;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-onerror
+ * @type {?function(!ProgressEvent)}
+ */
+FileSaver.prototype.onerror;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileSaver-onwriteend
+ * @type {?function(!ProgressEvent)}
+ */
+FileSaver.prototype.onwriteend;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#the-filesystem-interface
+ * @constructor
+ */
+function FileSystem() {}
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileSystem-name
+ * @type {string}
+ */
+FileSystem.prototype.name;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-FileSystem-root
+ * @type {!DirectoryEntry}
+ */
+FileSystem.prototype.root;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#idl-def-FileWriter
+ * @constructor
+ * @extends {FileSaver}
+ */
+function FileWriter() {}
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-position
+ * @type {number}
+ */
+FileWriter.prototype.position;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-length
+ * @type {number}
+ */
+FileWriter.prototype.length;
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-write
+ * @param {!Blob} blob
+ */
+FileWriter.prototype.write = function(blob) {};
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-seek
+ * @param {number} offset
+ */
+FileWriter.prototype.seek = function(offset) {};
+
+/**
+ * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-truncate
+ * @param {number} size
+ */
+FileWriter.prototype.truncate = function(size) {};
+
+/**
+ * LocalFileSystem interface, implemented by Window and WorkerGlobalScope.
+ * @see http://www.w3.org/TR/file-system-api/#idl-def-LocalFileSystem
+ * @constructor
+ */
+function LocalFileSystem() {}
+
+/**
+ * Metadata interface.
+ * @see http://www.w3.org/TR/file-system-api/#idl-def-Metadata
+ * @constructor
+ */
+function Metadata() {}
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Metadata-modificationTime
+ * @type {!Date}
+ */
+Metadata.prototype.modificationTime;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-Metadata-size
+ * @type {number}
+ */
+Metadata.prototype.size;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-TEMPORARY
+ * @type {number}
+*/
+Window.prototype.TEMPORARY = 0;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-PERSISTENT
+ * @type {number}
+*/
+Window.prototype.PERSISTENT = 1;
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-requestFileSystem
+ * @param {number} type
+ * @param {number} size
+ * @param {function(!FileSystem)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+function requestFileSystem(type, size, successCallback, errorCallback) {}
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-requestFileSystem
+ * @param {number} type
+ * @param {number} size
+ * @param {function(!FileSystem)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Window.prototype.requestFileSystem = function(type, size, successCallback,
+ errorCallback) {};
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-resolveLocalFileSystemURI
+ * @param {string} uri
+ * @param {function(!Entry)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+function resolveLocalFileSystemURI(uri, successCallback, errorCallback) {}
+
+/**
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-resolveLocalFileSystemURI
+ * @param {string} uri
+ * @param {function(!Entry)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Window.prototype.resolveLocalFileSystemURI = function(uri, successCallback,
+ errorCallback) {}
+
+/**
+ * This has replaced requestFileSystem in Chrome since WebKit revision 84224.
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-requestFileSystem
+ * @param {number} type
+ * @param {number} size
+ * @param {function(!FileSystem)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+function webkitRequestFileSystem(type, size, successCallback, errorCallback) {}
+
+/**
+ * This has replaced requestFileSystem in Chrome since WebKit revision 84224.
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-requestFileSystem
+ * @param {number} type
+ * @param {number} size
+ * @param {function(!FileSystem)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Window.prototype.webkitRequestFileSystem = function(type, size, successCallback,
+ errorCallback) {};
+
+/**
+ * This has replaced resolveLocalFileSystemURI in Chrome since WebKit revision
+ * 84224.
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-resolveLocalFileSystemURI
+ * @param {string} uri
+ * @param {function(!Entry)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+function webkitResolveLocalFileSystemURI(uri, successCallback, errorCallback) {}
+
+/**
+ * This has replaced resolveLocalFileSystemURI in Chrome since WebKit revision
+ * 84224.
+ * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystem-resolveLocalFileSystemURI
+ * @param {string} uri
+ * @param {function(!Entry)} successCallback
+ * @param {function(!FileError)=} errorCallback
+ */
+Window.prototype.webkitResolveLocalFileSystemURI = function(uri, successCallback,
+ errorCallback) {}
+
+// WindowBlobURIMethods interface, implemented by Window and WorkerGlobalScope.
+// There are three APIs for this: the old specced API, the new specced API, and
+// the webkit-prefixed API.
+// @see http://www.w3.org/TR/FileAPI/#creating-revoking
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-createObjectURL
+ * @param {!Object} obj
+ * @return {string}
+ */
+function createObjectURL(obj) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-createObjectURL
+ * @param {!Object} obj
+ * @return {string}
+ */
+Window.prototype.createObjectURL = function(obj) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-revokeObjectURL
+ * @param {string} url
+ */
+function revokeObjectURL(url) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-revokeObjectURL
+ * @param {string} url
+ */
+Window.prototype.revokeObjectURL = function(url) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#URL-object
+ * @constructor
+ */
+function DOMURL() {}
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#
+ * @constructor
+ * @param {string} urlString
+ * @param {string=} opt_base
+ * @extends {DOMURL}
+ */
+function URL(urlString, opt_base) {}
+
+/** @type {string} */
+URL.prototype.protocol;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-createObjectURL
+ * @param {!File|!Blob|!MediaSource|!MediaStream} obj
+ * @return {string}
+ */
+URL.createObjectURL = function(obj) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-revokeObjectURL
+ * @param {string} url
+ */
+URL.revokeObjectURL = function(url) {};
+
+/**
+ * This has been replaced by URL in Chrome since WebKit revision 75739.
+ * @constructor
+ * @param {string} urlString
+ * @param {string=} opt_base
+ * @extends {DOMURL}
+ */
+function webkitURL(urlString, opt_base) {}
+
+/** @constructor */
+window.webkitURL = webkitURL;
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-createObjectURL
+ * @param {!Object} obj
+ * @return {string}
+ */
+webkitURL.createObjectURL = function(obj) {};
+
+/**
+ * @see http://www.w3.org/TR/FileAPI/#dfn-revokeObjectURL
+ * @param {string} url
+ */
+webkitURL.revokeObjectURL = function(url) {};
+
+/**
+ * @see https://developers.google.com/chrome/whitepapers/storage
+ * @constructor
+ */
+function StorageInfo() {}
+
+/**
+ * @see https://developers.google.com/chrome/whitepapers/storage
+ * @type {number}
+ * */
+StorageInfo.prototype.TEMPORARY = 0;
+
+/**
+ * @see https://developers.google.com/chrome/whitepapers/storage
+ * @type {number}
+ */
+StorageInfo.prototype.PERSISTENT = 1;
+
+/**
+ * @see https://developers.google.com/chrome/whitepapers/storage#requestQuota
+ * @param {number} type
+ * @param {number} size
+ * @param {function(number)} successCallback
+ * @param {function(!DOMException)=} errorCallback
+ */
+StorageInfo.prototype.requestQuota = function(type, size, successCallback,
+ errorCallback) {};
+
+/**
+ * @see https://developers.google.com/chrome/whitepapers/storage#queryUsageAndQuota
+ * @param {number} type
+ * @param {function(number, number)} successCallback
+ * @param {function(!DOMException)=} errorCallback
+ */
+StorageInfo.prototype.queryUsageAndQuota = function(type, successCallback,
+ errorCallback) {};
+
+/**
+ * @see https://developers.google.com/chrome/whitepapers/storage
+ * @type {!StorageInfo}
+ */
+Window.prototype.webkitStorageInfo;
+
+/**
+ * @see https://dvcs.w3.org/hg/quota/raw-file/tip/Overview.html#storagequota-interface.
+ * @constructor
+ */
+function StorageQuota() {}
+
+/**
+ * @param {number} size
+ * @param {function(number)=} opt_successCallback
+ * @param {function(!DOMException)=} opt_errorCallback
+ */
+StorageQuota.prototype.requestQuota = function(size, opt_successCallback,
+ opt_errorCallback) {};
+
+/**
+ * @param {function(number, number)} successCallback
+ * @param {function(!DOMException)=} opt_errorCallback
+ */
+StorageQuota.prototype.queryUsageAndQuota = function(successCallback,
+ opt_errorCallback) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/flash.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/flash.js
new file mode 100644
index 0000000000..097bd86914
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/flash.js
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for all the Flash Object JavaScript methods. This
+ * file depends on w3c_dom2.js.
+ * Created from
+ * http://www.adobe.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_03.html
+ *
+ * @externs
+ */
+
+
+// Standard Methods.
+
+/**
+ * Call a Flash function exported by ExternalInterface.
+ * @param {string} xmlString The XML string passed to Flash. The outer element
+ * should be {@code <invoke>}. A sample invocation string:
+ * {@code <invoke name="function_name" returntype="javascript">
+ * <string>test</string></invoke>}
+ * @return {string} The serialized return value from Flash that you can eval.
+ */
+HTMLObjectElement.prototype.CallFunction = function(xmlString) {};
+
+/**
+ * Returns the value of the Flash variable specified by varName or null if the
+ * variable does not exist.
+ * @param {string} varName The variable name.
+ * @return {string?} The variable value.
+ */
+HTMLObjectElement.prototype.GetVariable = function(varName) {};
+
+/**
+ * Activates the frame number specified by {@code frameNumber} in the current
+ * movie.
+ * @param {number} frameNumber A non-negative integer frame number.
+ */
+HTMLObjectElement.prototype.GotoFrame = function(frameNumber) {};
+
+/**
+ * @return {boolean} Whether the movie is currently playing.
+ */
+HTMLObjectElement.prototype.IsPlaying = function() {};
+
+/**
+ * Loads the movie identified by {@code url} to the layer specified by {@code
+ * layerNumber}.
+ * @param {number} layerNumber The layer number.
+ * @param {string} url The movie URL.
+ */
+HTMLObjectElement.prototype.LoadMovie = function(layerNumber, url) {};
+
+/**
+ * Pans a zoomed-in movie to the coordinates specified by x and y. Use mode to
+ * specify whether the values for x and y are pixels or a percent of the window.
+ * When mode is 0, the coordinates are pixels; when mode is 1, the coordinates
+ * are percent of the window.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @param {number} mode The mode.
+ */
+HTMLObjectElement.prototype.Pan = function(x, y, mode) {};
+
+/**
+ * @return {number} The percent of the Flash Player movie that has streamed
+ * into the browser so far; Possible values are from 0 to 100.
+ */
+HTMLObjectElement.prototype.PercentLoaded = function() {};
+
+/**
+ * Starts playing the movie.
+ */
+HTMLObjectElement.prototype.Play = function() {};
+
+/**
+ * Goes to the first frame.
+ */
+HTMLObjectElement.prototype.Rewind = function() {};
+
+/**
+ * Sets the value of the flash variable.
+ * @param {string} variableName The variable name.
+ * @param {string} value The value.
+ */
+HTMLObjectElement.prototype.SetVariable = function(variableName, value) {};
+
+/**
+ * Zooms in on a rectangular area of the movie. The units of the coordinates
+ * are in twips (1440 units per inch).
+ * @param {number} left The left coordinate.
+ * @param {number} top The top coordinate.
+ * @param {number} right The right coordinate.
+ * @param {number} bottom The bottom coordinate.
+ */
+HTMLObjectElement.prototype.SetZoomRect = function(left, top, right, bottom) {};
+
+/**
+ * Stops playing the movie.
+ */
+HTMLObjectElement.prototype.StopPlay = function() {};
+
+/**
+ * @return {number} The total number of frames in the movie.
+ */
+HTMLObjectElement.prototype.TotalFrames = function() {};
+
+/**
+ * Zooms the view by a relative scale factor.
+ * @param {number} percent The percentage scale factor, should be an integer.
+ */
+HTMLObjectElement.prototype.Zoom = function(percent) {};
+
+
+// TellTarget Methods.
+
+/**
+ * Executes the action in the timeline specified by {@code target} in the
+ * specified frame.
+ * @param {string} target The timeline.
+ * @param {number} frameNumber The frame number.
+ */
+HTMLObjectElement.prototype.TCallFrame = function(target, frameNumber) {};
+
+/**
+ * Executes the action in the timeline specified by {@code target} in the
+ * specified frame.
+ * @param {string} target The timeline.
+ * @param {string} label The frame label.
+ */
+HTMLObjectElement.prototype.TCallLabel = function(target, label) {};
+
+/**
+ * Returns the number of the current frame for the specified timeline.
+ * @param {string} target The timeline.
+ * @return {number} The number of the current frame.
+ */
+HTMLObjectElement.prototype.TCurentFrame = function(target) {};
+
+/**
+ * Returns the label of the current frame for the specified timeline.
+ * @param {string} target The timeline.
+ * @return {string} The label of the current frame, empty string if no
+ * current frame.
+ */
+HTMLObjectElement.prototype.TCurrentLabel = function(target) {};
+
+/**
+ * Returns a string indicating the value of the property in the
+ * specified timeline.
+ * @param {string} target The timeline.
+ * @param {number} property The integer corresponding to the desired property.
+ * @return {string} The value of the property.
+ */
+HTMLObjectElement.prototype.TGetProperty = function(target, property) {};
+
+/**
+ * Returns a number indicating the value of the property in the specified
+ * timeline.
+ * @param {string} target The timeline.
+ * @param {number} property The integer corresponding to the desired property.
+ * @return {number} A number indicating the value of the property.
+ */
+HTMLObjectElement.prototype.TGetPropertyAsNumber = function(target, property) {};
+
+/**
+ * Goes to the specified frame number in the specified timeline.
+ * @param {string} target The timeline.
+ * @param {number} frameNumber The frame number.
+ */
+HTMLObjectElement.prototype.TGotoFrame = function(target, frameNumber) {};
+
+/**
+ * Goes to the specified frame label in the specified timeline.
+ * @param {string} target The timeline.
+ * @param {string} label The framelabel.
+ */
+HTMLObjectElement.prototype.TGotoLabel = function(target, label) {};
+
+/**
+ * Plays the specified timeline.
+ * @param {number} target The timeline.
+ */
+HTMLObjectElement.prototype.TPlay = function(target) {};
+
+/**
+ * Sets the value of the property in the specified timeline.
+ * @param {number} target The timeline.
+ * @param {number} property The integer corresponding to the desired property.
+ * @param {string|number} value The value.
+ */
+HTMLObjectElement.prototype.TSetProperty = function(target, property, value) {};
+
+/**
+ * Stops the specified timeline.
+ * @param {number} target The timeline.
+ */
+HTMLObjectElement.prototype.TStopPlay = function(target) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_css.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_css.js
new file mode 100644
index 0000000000..c85f7b10fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_css.js
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for Gecko's custom CSS properties. Copied from:
+ * http://mxr.mozilla.org/mozilla2.0/source/dom/interfaces/css/nsIDOMCSS2Properties.idl
+ *
+ * @externs
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+
+/** @type {string} */ CSSProperties.prototype.MozAppearance;
+/** @type {string} */ CSSProperties.prototype.MozBackfaceVisibility;
+/** @type {string} */ CSSProperties.prototype.MozBackgroundClip;
+/** @type {string} */ CSSProperties.prototype.MozBackgroundInlinePolicy;
+/** @type {string} */ CSSProperties.prototype.MozBackgroundOrigin;
+/** @type {string} */ CSSProperties.prototype.MozBinding;
+/** @type {string} */ CSSProperties.prototype.MozBorderBottomColors;
+/** @type {string} */ CSSProperties.prototype.MozBorderEnd;
+/** @type {string} */ CSSProperties.prototype.MozBorderEndColor;
+/** @type {string} */ CSSProperties.prototype.MozBorderEndStyle;
+/** @type {string} */ CSSProperties.prototype.MozBorderEndWidth;
+/** @type {string} */ CSSProperties.prototype.MozBorderImage;
+/** @type {string} */ CSSProperties.prototype.MozBorderLeftColors;
+/** @type {string} */ CSSProperties.prototype.MozBorderRadius;
+/** @type {string} */ CSSProperties.prototype.MozBorderRadiusTopleft;
+/** @type {string} */ CSSProperties.prototype.MozBorderRadiusTopright;
+/** @type {string} */ CSSProperties.prototype.MozBorderRadiusBottomleft;
+/** @type {string} */ CSSProperties.prototype.MozBorderRadiusBottomright;
+/** @type {string} */ CSSProperties.prototype.MozBorderRightColors;
+/** @type {string} */ CSSProperties.prototype.MozBorderStart;
+/** @type {string} */ CSSProperties.prototype.MozBorderStartColor;
+/** @type {string} */ CSSProperties.prototype.MozBorderStartStyle;
+/** @type {string} */ CSSProperties.prototype.MozBorderStartWidth;
+/** @type {string} */ CSSProperties.prototype.MozBorderTopColors;
+/** @type {string} */ CSSProperties.prototype.MozBoxAlign;
+/** @type {string} */ CSSProperties.prototype.MozBoxDirection;
+/** @type {string} */ CSSProperties.prototype.MozBoxFlex;
+/** @type {string} */ CSSProperties.prototype.MozBoxOrdinalGroup;
+/** @type {string} */ CSSProperties.prototype.MozBoxOrient;
+/** @type {string} */ CSSProperties.prototype.MozBoxPack;
+/** @type {string} */ CSSProperties.prototype.MozBoxSizing;
+/** @type {string} */ CSSProperties.prototype.MozBoxShadow;
+/** @type {string} */ CSSProperties.prototype.MozColumnCount;
+/** @type {string} */ CSSProperties.prototype.MozColumnGap;
+/** @type {string} */ CSSProperties.prototype.MozColumnRule;
+/** @type {string} */ CSSProperties.prototype.MozColumnRuleColor;
+/** @type {string} */ CSSProperties.prototype.MozColumnRuleStyle;
+/** @type {string} */ CSSProperties.prototype.MozColumnRuleWidth;
+/** @type {string} */ CSSProperties.prototype.MozColumnWidth;
+/** @type {string} */ CSSProperties.prototype.MozFloatEdge;
+/** @type {string} */ CSSProperties.prototype.MozFontFeatureSettings;
+/** @type {string} */ CSSProperties.prototype.MozFontLanguageOverride;
+/** @type {string} */ CSSProperties.prototype.MozForceBrokenImageIcon;
+/** @type {string} */ CSSProperties.prototype.MozImageRegion;
+/** @type {string} */ CSSProperties.prototype.MozMarginEnd;
+/** @type {string} */ CSSProperties.prototype.MozMarginStart;
+/** @type {number|string} */ CSSProperties.prototype.MozOpacity;
+/** @type {string} */ CSSProperties.prototype.MozOutline;
+/** @type {string} */ CSSProperties.prototype.MozOutlineColor;
+/** @type {string} */ CSSProperties.prototype.MozOutlineOffset;
+/** @type {string} */ CSSProperties.prototype.MozOutlineRadius;
+/** @type {string} */ CSSProperties.prototype.MozOutlineRadiusBottomleft;
+/** @type {string} */ CSSProperties.prototype.MozOutlineRadiusBottomright;
+/** @type {string} */ CSSProperties.prototype.MozOutlineRadiusTopleft;
+/** @type {string} */ CSSProperties.prototype.MozOutlineRadiusTopright;
+/** @type {string} */ CSSProperties.prototype.MozOutlineStyle;
+/** @type {string} */ CSSProperties.prototype.MozOutlineWidth;
+/** @type {string} */ CSSProperties.prototype.MozPaddingEnd;
+/** @type {string} */ CSSProperties.prototype.MozPaddingStart;
+/** @type {string} */ CSSProperties.prototype.MozPerspective;
+/** @type {string} */ CSSProperties.prototype.MozStackSizing;
+/** @type {string} */ CSSProperties.prototype.MozTabSize;
+/** @type {string} */ CSSProperties.prototype.MozTransform;
+/** @type {string} */ CSSProperties.prototype.MozTransformOrigin;
+/** @type {string} */ CSSProperties.prototype.MozTransition;
+/** @type {string} */ CSSProperties.prototype.MozTransitionDelay;
+/** @type {string} */ CSSProperties.prototype.MozTransitionDuration;
+/** @type {string} */ CSSProperties.prototype.MozTransitionProperty;
+/** @type {string} */ CSSProperties.prototype.MozTransitionTimingFunction;
+/** @type {string} */ CSSProperties.prototype.MozUserFocus;
+/** @type {string} */ CSSProperties.prototype.MozUserInput;
+/** @type {string} */ CSSProperties.prototype.MozUserModify;
+/** @type {string} */ CSSProperties.prototype.MozUserSelect;
+/** @type {string} */ CSSProperties.prototype.MozWindowShadow;
+
+
+// These are non-standard Gecko CSSOM properties on Window.prototype.screen.
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/window.screen.availTop
+ */
+Screen.prototype.availTop;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/window.screen.availLeft
+ */
+Screen.prototype.availLeft;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/window.screen.left
+ */
+Screen.prototype.left;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/window.screen.top
+ */
+Screen.prototype.top;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_dom.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_dom.js
new file mode 100644
index 0000000000..a3314d8123
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_dom.js
@@ -0,0 +1,1120 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over
+ * W3C's DOM specification by Gecko. This file depends on
+ * w3c_dom2.js.
+ *
+ * When a non-standard extension appears in both Gecko and IE, we put
+ * it in gecko_dom.js
+ *
+ * @externs
+ */
+
+// TODO: Almost all of it has not been annotated with types.
+
+// Gecko DOM;
+
+/**
+ * Mozilla only???
+ * @constructor
+ * @extends {HTMLElement}
+ */
+function HTMLSpanElement() {}
+
+/**
+ * @see https://developer.mozilla.org/en/Components_object
+ */
+Window.prototype.Components;
+
+/**
+ * @type Window
+ * @see https://developer.mozilla.org/en/DOM/window.content
+ */
+Window.prototype.content;
+
+/**
+ * @type {boolean}
+ * @see https://developer.mozilla.org/en/DOM/window.closed
+ */
+Window.prototype.closed;
+
+/** @see https://developer.mozilla.org/en/DOM/window.controllers */
+Window.prototype.controllers;
+
+/** @see https://developer.mozilla.org/en/DOM/window.crypto */
+Window.prototype.crypto;
+
+/**
+ * Gets/sets the status bar text for the given window.
+ * @type {string}
+ * @see https://developer.mozilla.org/en/DOM/window.defaultStatus
+ */
+Window.prototype.defaultStatus;
+
+/** @see https://developer.mozilla.org/en/DOM/window.dialogArguments */
+Window.prototype.dialogArguments;
+
+/** @see https://developer.mozilla.org/en/DOM/window.directories */
+Window.prototype.directories;
+
+/**
+ * @type {HTMLObjectElement|HTMLIFrameElement|null}
+ * @see https://developer.mozilla.org/en/DOM/window.frameElement
+ */
+Window.prototype.frameElement;
+
+/**
+ * Allows lookup of frames by index or by name.
+ * @type {?Object}
+ * @see https://developer.mozilla.org/en/DOM/window.frames
+ */
+Window.prototype.frames;
+
+/**
+ * @type {boolean}
+ * @see https://developer.mozilla.org/en/DOM/window.fullScreen
+ */
+Window.prototype.fullScreen;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/Storage#globalStorage
+ */
+Window.prototype.globalStorage;
+
+/**
+ * @type {!History}
+ * @see https://developer.mozilla.org/en/DOM/window.history
+ */
+Window.prototype.history;
+
+/**
+ * Returns the number of frames (either frame or iframe elements) in the
+ * window.
+ *
+ * @type {number}
+ * @see https://developer.mozilla.org/en/DOM/window.length
+ */
+Window.prototype.length;
+
+/**
+ * @type {!Location}
+ * @implicitCast
+ * @see https://developer.mozilla.org/en/DOM/window.location
+ */
+Window.prototype.location;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/window.locationbar
+ */
+Window.prototype.locationbar;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/window.menubar
+ */
+Window.prototype.menubar;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/DOM/window.name
+ */
+Window.prototype.name;
+
+/**
+ * @type {Navigator}
+ * @see https://developer.mozilla.org/en/DOM/window.navigator
+ */
+Window.prototype.navigator;
+
+/**
+ * @type {?Window}
+ * @see https://developer.mozilla.org/en/DOM/window.opener
+ */
+Window.prototype.opener;
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/en/DOM/window.parent
+ */
+Window.prototype.parent;
+
+/** @see https://developer.mozilla.org/en/DOM/window.personalbar */
+Window.prototype.personalbar;
+
+/** @see https://developer.mozilla.org/en/DOM/window.pkcs11 */
+Window.prototype.pkcs11;
+
+/** @see https://developer.mozilla.org/en/DOM/window */
+Window.prototype.returnValue;
+
+/** @see https://developer.mozilla.org/en/DOM/window.scrollbars */
+Window.prototype.scrollbars;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/window.scrollMaxX
+ */
+Window.prototype.scrollMaxX;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/window.scrollMaxY
+ */
+Window.prototype.scrollMaxY;
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/en/DOM/window.self
+ */
+Window.prototype.self;
+
+/** @see https://developer.mozilla.org/en/DOM/Storage#sessionStorage */
+Window.prototype.sessionStorage;
+
+/** @see https://developer.mozilla.org/en/DOM/window.sidebar */
+Window.prototype.sidebar;
+
+/**
+ * @type {?string}
+ * @see https://developer.mozilla.org/en/DOM/window.status
+ */
+Window.prototype.status;
+
+/** @see https://developer.mozilla.org/en/DOM/window.statusbar */
+Window.prototype.statusbar;
+
+/** @see https://developer.mozilla.org/en/DOM/window.toolbar */
+Window.prototype.toolbar;
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/en/DOM/window.self
+ */
+Window.prototype.top;
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/en/DOM/window.self
+ */
+Window.prototype.window;
+
+/**
+ * @param {*} message
+ * @see https://developer.mozilla.org/en/DOM/window.alert
+ */
+Window.prototype.alert = function(message) {};
+
+/**
+ * Decodes a string of data which has been encoded using base-64 encoding.
+ *
+ * @param {string} encodedData
+ * @return {string}
+ * @see https://developer.mozilla.org/en/DOM/window.atob
+ * @nosideeffects
+ */
+function atob(encodedData) {}
+
+/** @see https://developer.mozilla.org/en/DOM/window.back */
+Window.prototype.back = function() {};
+
+/** @see https://developer.mozilla.org/en/DOM/window.blur */
+Window.prototype.blur = function() {};
+
+/**
+ * @param {string} stringToEncode
+ * @return {string}
+ * @see https://developer.mozilla.org/en/DOM/window.btoa
+ * @nosideeffects
+ */
+function btoa(stringToEncode) {}
+
+/** @deprecated */
+Window.prototype.captureEvents;
+
+/** @see https://developer.mozilla.org/en/DOM/window.close */
+Window.prototype.close = function() {};
+
+/** @see https://developer.mozilla.org/en/DOM/window.find */
+Window.prototype.find;
+
+/** @see https://developer.mozilla.org/en/DOM/window.focus */
+Window.prototype.focus = function() {};
+
+/** @see https://developer.mozilla.org/en/DOM/window.forward */
+Window.prototype.forward = function() {};
+
+/** @see https://developer.mozilla.org/en/DOM/window.getAttention */
+Window.prototype.getAttention = function() {};
+
+/**
+ * @return {Selection}
+ * @see https://developer.mozilla.org/en/DOM/window.getSelection
+ * @nosideeffects
+ */
+Window.prototype.getSelection = function() {};
+
+/** @see https://developer.mozilla.org/en/DOM/window.home */
+Window.prototype.home = function() {};
+
+Window.prototype.openDialog;
+Window.prototype.releaseEvents;
+Window.prototype.scrollByLines;
+Window.prototype.scrollByPages;
+
+/**
+ * @param {string} uri
+ * @param {?=} opt_arguments
+ * @param {string=} opt_options
+ * @see https://developer.mozilla.org/en/DOM/window.showModalDialog
+ */
+Window.prototype.showModalDialog;
+
+Window.prototype.sizeToContent;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536769(VS.85).aspx
+ */
+Window.prototype.stop = function() {};
+
+Window.prototype.updateCommands;
+
+// properties of Document
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.alinkColor
+ * @type {string}
+ */
+Document.prototype.alinkColor;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.anchors
+ * @type {HTMLCollection}
+ */
+Document.prototype.anchors;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.applets
+ * @type {HTMLCollection}
+ */
+Document.prototype.applets;
+/** @type {boolean} */ Document.prototype.async;
+/** @type {string?} */ Document.prototype.baseURI;
+Document.prototype.baseURIObject;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.bgColor
+ * @type {string}
+ */
+Document.prototype.bgColor;
+
+/** @type {HTMLBodyElement} */ Document.prototype.body;
+Document.prototype.characterSet;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.compatMode
+ * @type {string}
+ */
+Document.prototype.compatMode;
+
+Document.prototype.contentType;
+/** @type {string} */ Document.prototype.cookie;
+Document.prototype.defaultView;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.designMode
+ * @type {string}
+ */
+Document.prototype.designMode;
+
+Document.prototype.documentURIObject;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.domain
+ * @type {string}
+ */
+Document.prototype.domain;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.embeds
+ * @type {HTMLCollection}
+ */
+Document.prototype.embeds;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.fgColor
+ * @type {string}
+ */
+Document.prototype.fgColor;
+
+/** @type {Element} */ Document.prototype.firstChild;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.forms
+ * @type {HTMLCollection}
+ */
+Document.prototype.forms;
+
+/** @type {number} */ Document.prototype.height;
+/** @type {HTMLCollection} */ Document.prototype.images;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/DOM/document.lastModified
+ */
+Document.prototype.lastModified;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/DOM/document.linkColor
+ */
+Document.prototype.linkColor;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.links
+ * @type {HTMLCollection}
+ */
+Document.prototype.links;
+
+/**
+ * @type {!Location}
+ * @implicitCast
+ */
+Document.prototype.location;
+
+Document.prototype.namespaceURI;
+Document.prototype.nodePrincipal;
+Document.prototype.plugins;
+Document.prototype.popupNode;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/DOM/document.referrer
+ */
+Document.prototype.referrer;
+
+/**
+ * @type {StyleSheetList}
+ * @see https://developer.mozilla.org/en/DOM/document.styleSheets
+ */
+Document.prototype.styleSheets;
+
+/** @type {?string} */ Document.prototype.title;
+Document.prototype.tooltipNode;
+/** @type {string} */ Document.prototype.URL;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/DOM/document.vlinkColor
+ */
+Document.prototype.vlinkColor;
+
+/** @type {number} */ Document.prototype.width;
+
+// Methods of Document
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.clear
+ */
+Document.prototype.clear = function() {};
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.close
+ */
+Document.prototype.close;
+
+/**
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/document.createElementNS
+ * @see http://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-instantiate
+ * @param {?string} namespaceURI
+ * @param {string} qualifiedName
+ * @param {string=} opt_typeExtension
+ * @return {!Element}
+ */
+Document.prototype.createElementNS =
+ function(namespaceURI, qualifiedName, opt_typeExtension) {};
+
+/**
+ * @param {string} type
+ * @return {Event}
+ */
+Document.prototype.createEvent = function(type) {};
+Document.prototype.createNSResolver;
+/** @return {Range} */ Document.prototype.createRange = function() {};
+Document.prototype.createTreeWalker;
+
+Document.prototype.evaluate;
+
+/**
+ * @param {string} commandName
+ * @param {?boolean=} opt_showUi
+ * @param {*=} opt_value
+ * @see https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla#Executing_Commands
+ */
+Document.prototype.execCommand;
+
+/**
+ * @param {string} s id.
+ * @return {HTMLElement}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/DOM/document.getElementById
+ */
+Document.prototype.getElementById = function(s) {};
+
+/**
+ * @param {string} name
+ * @return {!NodeList}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/DOM/document.getElementsByClassName
+ */
+Document.prototype.getElementsByClassName = function(name) {};
+
+/**
+ * @param {string} name
+ * @return {!NodeList}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/DOM/document.getElementsByName
+ */
+Document.prototype.getElementsByName = function(name) {};
+
+/**
+ * @param {string} namespace
+ * @param {string} name
+ * @return {!NodeList}
+ * @nosideeffects
+ * @see https://developer.mozilla.org/en/DOM/document.getElementsByTagNameNS
+ */
+Document.prototype.getElementsByTagNameNS = function(namespace, name) {};
+
+/**
+ * @param {Node} externalNode
+ * @param {boolean} deep
+ * @return {Node}
+ */
+Document.prototype.importNode = function(externalNode, deep) {};
+
+/** @param {string} uri */
+Document.prototype.load = function(uri) {};
+Document.prototype.loadOverlay;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.open
+ */
+Document.prototype.open;
+
+/**
+ * @see https://developer.mozilla.org/en/Midas
+ * @see http://msdn.microsoft.com/en-us/library/ms536676(VS.85).aspx
+ */
+Document.prototype.queryCommandEnabled;
+
+/**
+ * @see https://developer.mozilla.org/en/Midas
+ * @see http://msdn.microsoft.com/en-us/library/ms536678(VS.85).aspx
+ */
+Document.prototype.queryCommandIndeterm;
+
+/**
+ * @see https://developer.mozilla.org/en/Midas
+ * @see http://msdn.microsoft.com/en-us/library/ms536679(VS.85).aspx
+ */
+Document.prototype.queryCommandState;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.queryCommandSupported
+ * @see http://msdn.microsoft.com/en-us/library/ms536681(VS.85).aspx
+ * @param {string} command
+ * @return {?} Implementation-specific.
+ */
+Document.prototype.queryCommandSupported;
+
+/**
+ * @see https://developer.mozilla.org/en/Midas
+ * @see http://msdn.microsoft.com/en-us/library/ms536683(VS.85).aspx
+ */
+Document.prototype.queryCommandValue;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.write
+ * @param {string} text
+ */
+Document.prototype.write = function(text) {};
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/document.writeln
+ * @param {string} text
+ */
+Document.prototype.writeln = function(text) {};
+
+Document.prototype.ononline;
+Document.prototype.onoffline;
+
+// XUL
+/**
+ * @see http://developer.mozilla.org/en/DOM/document.getBoxObjectFor
+ * @return {BoxObject}
+ * @nosideeffects
+ */
+Document.prototype.getBoxObjectFor = function(element) {};
+
+// From:
+// http://lxr.mozilla.org/mozilla1.8/source/dom/public/idl/range/nsIDOMNSRange.idl
+
+/**
+ * @param {string} tag
+ * @return {DocumentFragment}
+ */
+Range.prototype.createContextualFragment;
+
+/**
+ * @param {Node} parent
+ * @param {number} offset
+ * @return {boolean}
+ * @nosideeffects
+ */
+Range.prototype.isPointInRange;
+
+/**
+ * @param {Node} parent
+ * @param {number} offset
+ * @return {number}
+ * @nosideeffects
+ */
+Range.prototype.comparePoint;
+
+/**
+ * @param {Node} n
+ * @return {boolean}
+ * @nosideeffects
+ */
+Range.prototype.intersectsNode;
+
+/**
+ * @param {Node} n
+ * @return {number}
+ * @nosideeffects
+ */
+Range.prototype.compareNode;
+
+
+/** @constructor */
+function Selection() {}
+
+/**
+ * @type {Node}
+ * @see https://developer.mozilla.org/en/DOM/Selection/anchorNode
+ */
+Selection.prototype.anchorNode;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/en/DOM/Selection/anchorOffset
+ */
+Selection.prototype.anchorOffset;
+
+/**
+ * @type {Node}
+ * @see https://developer.mozilla.org/en/DOM/Selection/focusNode
+ */
+Selection.prototype.focusNode;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/en/DOM/Selection/focusOffset
+ */
+Selection.prototype.focusOffset;
+
+/**
+ * @type {boolean}
+ * @see https://developer.mozilla.org/en/DOM/Selection/isCollapsed
+ */
+Selection.prototype.isCollapsed;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/en/DOM/Selection/rangeCount
+ */
+Selection.prototype.rangeCount;
+
+/**
+ * @param {Range} range
+ * @return {undefined}
+ * @see https://developer.mozilla.org/en/DOM/Selection/addRange
+ */
+Selection.prototype.addRange = function(range) {};
+
+/**
+ * @param {number} index
+ * @return {Range}
+ * @see https://developer.mozilla.org/en/DOM/Selection/getRangeAt
+ * @nosideeffects
+ */
+Selection.prototype.getRangeAt = function(index) {};
+
+/**
+ * @param {Node} node
+ * @param {number} index
+ * @return {undefined}
+ * @see https://developer.mozilla.org/en/DOM/Selection/collapse
+ */
+Selection.prototype.collapse = function(node, index) {};
+
+/**
+ * @return {undefined}
+ * @see https://developer.mozilla.org/en/DOM/Selection/collapseToEnd
+ */
+Selection.prototype.collapseToEnd = function() {};
+
+/**
+ * @return {undefined}
+ * @see https://developer.mozilla.org/en/DOM/Selection/collapseToStart
+ */
+Selection.prototype.collapseToStart = function() {};
+
+/**
+ * @param {Node} node
+ * @param {boolean} partlyContained
+ * @return {boolean}
+ * @see https://developer.mozilla.org/en/DOM/Selection/containsNode
+ * @nosideeffects
+ */
+Selection.prototype.containsNode = function(node, partlyContained) {};
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/Selection/deleteFromDocument
+ */
+Selection.prototype.deleteFromDocument = function() {};
+
+/**
+ * @param {Node} parentNode
+ * @param {number} offset
+ * @see https://developer.mozilla.org/en/DOM/Selection/extend
+ */
+Selection.prototype.extend = function(parentNode, offset) {};
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/Selection/removeAllRanges
+ */
+Selection.prototype.removeAllRanges = function() {};
+
+/**
+ * @param {Range} range
+ * @see https://developer.mozilla.org/en/DOM/Selection/removeRange
+ */
+Selection.prototype.removeRange = function(range) {};
+
+/**
+ * @param {Node} parentNode
+ * @see https://developer.mozilla.org/en/DOM/Selection/selectAllChildren
+ */
+Selection.prototype.selectAllChildren;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/Selection/selectionLanguageChange
+ */
+Selection.prototype.selectionLanguageChange;
+
+/** @type {NamedNodeMap} */ Element.prototype.attributes;
+Element.prototype.baseURIObject;
+/** @type {!NodeList} */ Element.prototype.childNodes;
+
+/**
+ * @type {!NodeList}
+ * @see https://developer.mozilla.org/en/DOM/element.children
+ */
+Element.prototype.children;
+
+/**
+ * @type {string}
+ * @implicitCast
+ */
+Element.prototype.className;
+/** @type {string} */ Element.prototype.dir;
+
+/**
+ * Firebug sets this property on elements it is inserting into the DOM.
+ * @type {boolean}
+ */
+Element.prototype.firebugIgnore;
+
+/** @type {Node} */ Element.prototype.firstChild;
+/**
+ * @type {string}
+ * @implicitCast
+ */
+Element.prototype.id;
+/**
+ * @type {string}
+ * @implicitCast
+ */
+Element.prototype.innerHTML;
+/** @type {string} */ Element.prototype.lang;
+/** @type {Node} */ Element.prototype.lastChild;
+Element.prototype.localName;
+Element.prototype.name;
+Element.prototype.namespaceURI;
+/** @type {Node} */ Element.prototype.nextSibling;
+Element.prototype.nodeName;
+Element.prototype.nodePrincipal;
+/** @type {number} */ Element.prototype.nodeType;
+Element.prototype.nodeValue;
+/** @type {Document} */ Element.prototype.ownerDocument;
+/** @type {Node} */ Element.prototype.parentNode;
+Element.prototype.prefix;
+/** @type {Node} */ Element.prototype.previousSibling;
+/** @type {!CSSStyleDeclaration} */ Element.prototype.style;
+/**
+ * @type {number}
+ * @implicitCast
+ */
+Element.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @implicitCast
+ */
+Element.prototype.textContent;
+/** @type {string} */ Element.prototype.title;
+
+/**
+ * @param {Node} child
+ * @return {Node} appendedElement.
+ * @override
+ */
+Element.prototype.appendChild = function(child) {};
+
+/**
+ * @override
+ * @return {!Element}
+ */
+Element.prototype.cloneNode = function(deep) {};
+
+/** @override */
+Element.prototype.dispatchEvent = function(event) {};
+
+/** @return {undefined} */
+Element.prototype.blur = function() {};
+
+/** @return {undefined} */
+Element.prototype.click = function() {};
+
+/** @return {undefined} */
+Element.prototype.focus = function() {};
+
+/**
+ * @return {boolean}
+ * @override
+ * @nosideeffects
+ */
+Element.prototype.hasAttributes = function() {};
+
+/**
+ * @return {boolean}
+ * @override
+ * @nosideeffects
+ */
+Element.prototype.hasChildNodes = function() {};
+
+/** @override */
+Element.prototype.insertBefore = function(insertedNode, adjacentNode) {};
+
+/**
+ * @return {undefined}
+ * @override
+ */
+Element.prototype.normalize = function() {};
+
+/**
+ * @param {Node} removedNode
+ * @return {!Node}
+ * @override
+ */
+Element.prototype.removeChild = function(removedNode) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Element.prototype.removeEventListener = function(type, handler, opt_useCapture)
+ {};
+
+/** @override */
+Element.prototype.replaceChild = function(insertedNode, replacedNode) {};
+
+/** @type {number} */
+HTMLInputElement.prototype.selectionStart;
+
+/** @type {number} */
+HTMLInputElement.prototype.selectionEnd;
+
+/**
+ * @param {number} selectionStart
+ * @param {number} selectionEnd
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#dom-textarea/input-setselectionrange
+ */
+HTMLInputElement.prototype.setSelectionRange =
+ function(selectionStart, selectionEnd) {};
+
+/** @type {number} */
+HTMLTextAreaElement.prototype.selectionStart;
+
+/** @type {number} */
+HTMLTextAreaElement.prototype.selectionEnd;
+
+/**
+ * @param {number} selectionStart
+ * @param {number} selectionEnd
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#dom-textarea/input-setselectionrange
+ */
+HTMLTextAreaElement.prototype.setSelectionRange =
+ function(selectionStart, selectionEnd) {};
+
+/** @constructor */
+function Navigator() {}
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.appCodeName
+ */
+Navigator.prototype.appCodeName;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.appVersion
+ */
+Navigator.prototype.appName;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.appVersion
+ */
+Navigator.prototype.appVersion;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.buildID
+ */
+Navigator.prototype.buildID;
+
+/**
+ * @type {boolean}
+ * @see https://developer.mozilla.org/en/Navigator.cookieEnabled
+ */
+Navigator.prototype.cookieEnabled;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.language
+ */
+Navigator.prototype.language;
+
+/**
+ * @type {MimeTypeArray}
+ * @see https://developer.mozilla.org/en/Navigator.mimeTypes
+ */
+Navigator.prototype.mimeTypes;
+
+/**
+ * @type {boolean}
+ * @see https://developer.mozilla.org/en/Navigator.onLine
+ */
+Navigator.prototype.onLine;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.oscpu
+ */
+Navigator.prototype.oscpu;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.platform
+ */
+Navigator.prototype.platform;
+
+/**
+ * @type {PluginArray}
+ * @see https://developer.mozilla.org/en/Navigator.plugins
+ */
+Navigator.prototype.plugins;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.product
+ */
+Navigator.prototype.product;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.productSub
+ */
+Navigator.prototype.productSub;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.securityPolicy
+ */
+Navigator.prototype.securityPolicy;
+
+/**
+ * @param {string} url
+ * @param {ArrayBufferView|Blob|string|FormData=} opt_data
+ * @return {boolean}
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/navigator.sendBeacon
+ */
+Navigator.prototype.sendBeacon = function(url, opt_data) {};
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.userAgent
+ */
+Navigator.prototype.userAgent;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.vendor
+ */
+Navigator.prototype.vendor;
+
+/**
+ * @type {string}
+ * @see https://developer.mozilla.org/en/Navigator.vendorSub
+ */
+Navigator.prototype.vendorSub;
+
+/**
+ * @type {function(): boolean}
+ * @see https://developer.mozilla.org/en/Navigator.javaEnabled
+ * @nosideeffects
+ */
+Navigator.prototype.javaEnabled = function() {};
+
+/**
+ * @constructor
+ * @see https://developer.mozilla.org/en/DOM/PluginArray
+ */
+function PluginArray() {}
+
+/** @type {number} */
+PluginArray.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {Plugin}
+ */
+PluginArray.prototype.item = function(index) {};
+
+/**
+ * @param {string} name
+ * @return {Plugin}
+ */
+PluginArray.prototype.namedItem = function(name) {};
+
+/** @param {boolean=} reloadDocuments */
+PluginArray.prototype.refresh = function(reloadDocuments) {};
+
+/** @constructor */
+function MimeTypeArray() {}
+
+/**
+ * @param {number} index
+ * @return {MimeType}
+ */
+MimeTypeArray.prototype.item = function(index) {};
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/en/DOM/window.navigator.mimeTypes
+ */
+MimeTypeArray.prototype.length;
+
+/**
+ * @param {string} name
+ * @return {MimeType}
+ */
+MimeTypeArray.prototype.namedItem = function(name) {};
+
+/** @constructor */
+function MimeType() {}
+
+/** @type {string} */
+MimeType.prototype.description;
+
+/** @type {Plugin} */
+MimeType.prototype.enabledPlugin;
+
+/** @type {string} */
+MimeType.prototype.suffixes;
+
+/** @type {string} */
+MimeType.prototype.type;
+
+/** @constructor */
+function Plugin() {}
+
+/** @type {string} */
+Plugin.prototype.description;
+
+/** @type {string} */
+Plugin.prototype.filename;
+
+/** @type {number} */
+Plugin.prototype.length;
+
+/** @type {string} */
+Plugin.prototype.name;
+
+/** @constructor */
+function BoxObject() {}
+
+/** @type {Element} */
+BoxObject.prototype.element;
+
+/** @type {number} */
+BoxObject.prototype.screenX;
+
+/** @type {number} */
+BoxObject.prototype.screenY;
+
+/** @type {number} */
+BoxObject.prototype.x;
+
+/** @type {number} */
+BoxObject.prototype.y;
+
+/** @type {number} */
+BoxObject.prototype.width;
+
+
+/**
+ * @type {number}
+ * @see http://www.google.com/codesearch/p?hl=en#eksvcKKj5Ng/mozilla/dom/public/idl/html/nsIDOMNSHTMLImageElement.idl&q=naturalWidth
+ */
+HTMLImageElement.prototype.naturalWidth;
+
+/**
+ * @type {number}
+ * @see http://www.google.com/codesearch/p?hl=en#eksvcKKj5Ng/mozilla/dom/public/idl/html/nsIDOMNSHTMLImageElement.idl&q=naturalHeight
+ */
+HTMLImageElement.prototype.naturalHeight;
+
+
+/**
+ * @param {Element} element
+ * @param {?string=} pseudoElt
+ * @return {CSSStyleDeclaration}
+ * @nosideeffects
+ */
+function getComputedStyle(element, pseudoElt) {}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_event.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_event.js
new file mode 100644
index 0000000000..cf3b21bf1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_event.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over
+ * W3C's event specification by Gecko. This file depends on
+ * w3c_event.js.
+ *
+ * @externs
+ */
+
+// TODO: Almost all of it has not been annotated with types.
+
+/** @type {number} */ Event.prototype.HORIZONTAL_AXIS;
+/** @type {number} */ Event.prototype.VERTICAL_AXIS;
+/** @type {boolean} */ Event.prototype.altKey;
+/** @type {number} */ Event.prototype.axis;
+/** @type {number} */ Event.prototype.button;
+/** @type {boolean} */ Event.prototype.cancelBubble;
+/** @type {number} */ Event.prototype.charCode;
+/** @type {number} */ Event.prototype.clientX;
+/** @type {number} */ Event.prototype.clientY;
+/** @type {boolean} */ Event.prototype.ctrlKey;
+/** @type {EventTarget} */ Event.prototype.explicitOriginalTarget;
+/** @type {boolean} */ Event.prototype.isChar;
+/** @type {number} */ Event.prototype.keyCode;
+/** @type {number} */ Event.prototype.layerX;
+/** @type {number} */ Event.prototype.layerY;
+/** @type {boolean} */ Event.prototype.metaKey;
+/** @type {EventTarget} */ Event.prototype.originalTarget;
+/** @type {number} */ Event.prototype.pageX;
+/** @type {number} */ Event.prototype.pageY;
+/** @type {EventTarget} */ Event.prototype.relatedTarget;
+/** @type {number} */ Event.prototype.screenX;
+/** @type {number} */ Event.prototype.screenY;
+/** @type {boolean} */ Event.prototype.shiftKey;
+/** @type {Window} */ Event.prototype.view;
+/** @type {number} */ Event.prototype.which;
+
+/** @constructor */ function nsIDOMPageTransitionEvent() {}
+/** @type {boolean} */ nsIDOMPageTransitionEvent.prototype.persisted;
+
+//Methods
+Event.prototype.initKeyEvent;
+Event.prototype.initMouseEvent;
+Event.prototype.initUIEvent;
+Event.prototype.initMessageEvent;
+Event.prototype.preventBubble;
+Event.prototype.preventCapture;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_xml.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_xml.js
new file mode 100644
index 0000000000..ccab53d672
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/gecko_xml.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over some of the
+ * W3C's XML specifications by Gecko. This file depends on
+ * w3c_xml.js. The whole file has been fully type annotated.
+ *
+ * @externs
+ */
+
+/**
+ * XMLSerializer can be used to convert DOM subtree or DOM document into text.
+ * XMLSerializer is available to unprivileged scripts.
+ *
+ * XMLSerializer is mainly useful for applications and extensions based on
+ * Mozilla platform. While it's available to web pages, it's not part of any
+ * standard and level of support in other browsers is unknown.
+ *
+ * @constructor
+ */
+function XMLSerializer() {}
+
+/**
+ * Returns the serialized subtree in the form of a string
+ * @param {Node} subtree
+ * @return {string}
+ */
+XMLSerializer.prototype.serializeToString = function(subtree) {};
+
+/**
+ * The subtree rooted by the specified element is serialized to a byte stream
+ * using the character set specified.
+ *
+ * @param {Node} subtree
+ * @return {Object}
+ */
+XMLSerializer.prototype.serializeToStream = function(subtree) {};
+
+/**
+ * DOMParser is mainly useful for applications and extensions based on Mozilla
+ * platform. While it's available to web pages, it's not part of any standard and
+ * level of support in other browsers is unknown.
+ *
+ * @constructor
+ */
+function DOMParser() {}
+
+/**
+ * The string passed in is parsed into a DOM document.
+ *
+ * Example:
+ * var parser = new DOMParser();
+ * var doc = parser.parseFromString(aStr, "text/xml");
+ *
+ * @param {string} src The UTF16 string to be parsed.
+ * @param {string} type The content type of the string.
+ * @return {Document}
+ */
+DOMParser.prototype.parseFromString = function(src, type) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/google.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/google.js
new file mode 100644
index 0000000000..adb0e1a3fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/google.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Declaration of the type level google namespace.
+ * @externs
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+/**
+ * Suppresses the compiler warning when multiple externs files declare the
+ * google namespace.
+ * @suppress {duplicate}
+ * @noalias
+ */
+// TODO(nicksantos): Consolidate to one google namespace declaration.
+var google = {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/html5.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/html5.js
new file mode 100644
index 0000000000..4e8fbd0ec7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/html5.js
@@ -0,0 +1,3231 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for all the extensions over the
+ * W3C's DOM3 specification in HTML5. This file depends on
+ * w3c_dom3.js. The whole file has been fully type annotated.
+ *
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/index.html
+ * @see http://dev.w3.org/html5/spec/Overview.html
+ *
+ * This also includes Typed Array definitions from
+ * http://www.khronos.org/registry/typedarray/specs/latest/
+ *
+ * This relies on w3c_event.js being included first.
+ *
+ * @externs
+ */
+
+
+/**
+ * Note: In IE, the contains() method only exists on Elements, not Nodes.
+ * Therefore, it is recommended that you use the Conformance framework to
+ * prevent calling this on Nodes which are not Elements.
+ * @see https://connect.microsoft.com/IE/feedback/details/780874/node-contains-is-incorrect
+ *
+ * @param {Node} n The node to check
+ * @return {boolean} If 'n' is this Node, or is contained within this Node.
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Node.contains
+ * @nosideeffects
+ */
+Node.prototype.contains = function(n) {};
+
+
+/**
+ * @constructor
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
+ * @extends {HTMLElement}
+ */
+function HTMLCanvasElement() {}
+
+/** @type {number} */
+HTMLCanvasElement.prototype.width;
+
+/** @type {number} */
+HTMLCanvasElement.prototype.height;
+
+/**
+ * @param {string=} opt_type
+ * @param {...*} var_args
+ * @return {string}
+ * @throws {Error}
+ * @nosideeffects
+ */
+HTMLCanvasElement.prototype.toDataURL = function(opt_type, var_args) {};
+
+/**
+ * @param {string} contextId
+ * @param {Object=} opt_args
+ * @return {Object}
+ */
+HTMLCanvasElement.prototype.getContext = function(contextId, opt_args) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/2dcontext/#canvasrenderingcontext2d
+ */
+function CanvasRenderingContext2D() {}
+
+/** @type {HTMLCanvasElement} */
+CanvasRenderingContext2D.prototype.canvas;
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.save = function() {};
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.restore = function() {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.scale = function(x, y) {};
+
+/**
+ * @param {number} angle
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.rotate = function(angle) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.translate = function(x, y) {};
+
+/**
+ * @param {number} m11
+ * @param {number} m12
+ * @param {number} m21
+ * @param {number} m22
+ * @param {number} dx
+ * @param {number} dy
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.transform = function(
+ m11, m12, m21, m22, dx, dy) {};
+
+/**
+ * @param {number} m11
+ * @param {number} m12
+ * @param {number} m21
+ * @param {number} m22
+ * @param {number} dx
+ * @param {number} dy
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.setTransform = function(
+ m11, m12, m21, m22, dx, dy) {};
+
+/**
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} x1
+ * @param {number} y1
+ * @return {CanvasGradient}
+ * @throws {Error}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.createLinearGradient = function(
+ x0, y0, x1, y1) {};
+
+/**
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} r0
+ * @param {number} x1
+ * @param {number} y1
+ * @param {number} r1
+ * @return {CanvasGradient}
+ * @throws {Error}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.createRadialGradient = function(
+ x0, y0, r0, x1, y1, r1) {};
+
+/**
+ * @param {HTMLImageElement|HTMLCanvasElement} image
+ * @param {string} repetition
+ * @return {CanvasPattern}
+ * @throws {Error}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.createPattern = function(
+ image, repetition) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} w
+ * @param {number} h
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.clearRect = function(x, y, w, h) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} w
+ * @param {number} h
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.fillRect = function(x, y, w, h) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} w
+ * @param {number} h
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.strokeRect = function(x, y, w, h) {};
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.beginPath = function() {};
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.closePath = function() {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.moveTo = function(x, y) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.lineTo = function(x, y) {};
+
+/**
+ * @param {number} cpx
+ * @param {number} cpy
+ * @param {number} x
+ * @param {number} y
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.quadraticCurveTo = function(
+ cpx, cpy, x, y) {};
+
+/**
+ * @param {number} cp1x
+ * @param {number} cp1y
+ * @param {number} cp2x
+ * @param {number} cp2y
+ * @param {number} x
+ * @param {number} y
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.bezierCurveTo = function(
+ cp1x, cp1y, cp2x, cp2y, x, y) {};
+
+/**
+ * @param {number} x1
+ * @param {number} y1
+ * @param {number} x2
+ * @param {number} y2
+ * @param {number} radius
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.arcTo = function(x1, y1, x2, y2, radius) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} w
+ * @param {number} h
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.rect = function(x, y, w, h) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} radius
+ * @param {number} startAngle
+ * @param {number} endAngle
+ * @param {boolean=} opt_anticlockwise
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.arc = function(
+ x, y, radius, startAngle, endAngle, opt_anticlockwise) {};
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.fill = function() {};
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.stroke = function() {};
+
+/**
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.clip = function() {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {boolean}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.isPointInPath = function(x, y) {};
+
+/**
+ * @param {string} text
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} opt_maxWidth
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.fillText = function(
+ text, x, y, opt_maxWidth) {};
+
+/**
+ * @param {string} text
+ * @param {number} x
+ * @param {number} y
+ * @param {number=} opt_maxWidth
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.strokeText = function(
+ text, x, y, opt_maxWidth) {};
+
+/**
+ * @param {string} text
+ * @return {TextMetrics}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.measureText = function(text) {};
+
+/**
+ * @param {HTMLImageElement|HTMLCanvasElement|Image|HTMLVideoElement} image
+ * @param {number} dx Destination x coordinate.
+ * @param {number} dy Destination y coordinate.
+ * @param {number=} opt_dw Destination box width. Defaults to the image width.
+ * @param {number=} opt_dh Destination box height.
+ * Defaults to the image height.
+ * @param {number=} opt_sx Source box x coordinate. Used to select a portion of
+ * the source image to draw. Defaults to 0.
+ * @param {number=} opt_sy Source box y coordinate. Used to select a portion of
+ * the source image to draw. Defaults to 0.
+ * @param {number=} opt_sw Source box width. Used to select a portion of
+ * the source image to draw. Defaults to the full image width.
+ * @param {number=} opt_sh Source box height. Used to select a portion of
+ * the source image to draw. Defaults to the full image height.
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.drawImage = function(
+ image, dx, dy, opt_dw, opt_dh, opt_sx, opt_sy, opt_sw, opt_sh) {};
+
+/**
+ * @param {number} sw
+ * @param {number} sh
+ * @return {ImageData}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.createImageData = function(sw, sh) {};
+
+/**
+ * @param {number} sx
+ * @param {number} sy
+ * @param {number} sw
+ * @param {number} sh
+ * @return {ImageData}
+ * @throws {Error}
+ * @nosideeffects
+ */
+CanvasRenderingContext2D.prototype.getImageData = function(sx, sy, sw, sh) {};
+
+/**
+ * @param {ImageData} imagedata
+ * @param {number} dx
+ * @param {number} dy
+ * @param {number=} opt_dirtyX
+ * @param {number=} opt_dirtyY
+ * @param {number=} opt_dirtyWidth
+ * @param {number=} opt_dirtyHeight
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.putImageData = function(imagedata, dx, dy,
+ opt_dirtyX, opt_dirtyY, opt_dirtyWidth, opt_dirtyHeight) {};
+
+/**
+ * Note: WebKit only
+ * @param {number|string=} opt_a
+ * @param {number=} opt_b
+ * @param {number=} opt_c
+ * @param {number=} opt_d
+ * @param {number=} opt_e
+ * @see http://developer.apple.com/library/safari/#documentation/appleapplications/reference/WebKitDOMRef/CanvasRenderingContext2D_idl/Classes/CanvasRenderingContext2D/index.html
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.setFillColor;
+
+/**
+ * Note: WebKit only
+ * @param {number|string=} opt_a
+ * @param {number=} opt_b
+ * @param {number=} opt_c
+ * @param {number=} opt_d
+ * @param {number=} opt_e
+ * @see http://developer.apple.com/library/safari/#documentation/appleapplications/reference/WebKitDOMRef/CanvasRenderingContext2D_idl/Classes/CanvasRenderingContext2D/index.html
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.setStrokeColor;
+
+/**
+ * @return {Array.<number>}
+ */
+CanvasRenderingContext2D.prototype.getLineDash;
+
+/**
+ * @param {Array.<number>} segments
+ * @return {undefined}
+ */
+CanvasRenderingContext2D.prototype.setLineDash;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.fillColor;
+
+/**
+ * @type {string}
+ * @implicitCast
+ */
+CanvasRenderingContext2D.prototype.fillStyle;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.font;
+
+/** @type {number} */
+CanvasRenderingContext2D.prototype.globalAlpha;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.globalCompositeOperation;
+
+/** @type {number} */
+CanvasRenderingContext2D.prototype.lineWidth;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.lineCap;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.lineJoin;
+
+/** @type {number} */
+CanvasRenderingContext2D.prototype.miterLimit;
+
+/** @type {number} */
+CanvasRenderingContext2D.prototype.shadowBlur;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.shadowColor;
+
+/** @type {number} */
+CanvasRenderingContext2D.prototype.shadowOffsetX;
+
+/** @type {number} */
+CanvasRenderingContext2D.prototype.shadowOffsetY;
+
+/**
+ * @type {string}
+ * @implicitCast
+ */
+CanvasRenderingContext2D.prototype.strokeStyle;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.strokeColor;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.textAlign;
+
+/** @type {string} */
+CanvasRenderingContext2D.prototype.textBaseline;
+
+/**
+ * @constructor
+ */
+function CanvasGradient() {}
+
+/**
+ * @param {number} offset
+ * @param {string} color
+ * @return {undefined}
+ */
+CanvasGradient.prototype.addColorStop = function(offset, color) {};
+
+/**
+ * @constructor
+ */
+function CanvasPattern() {}
+
+/**
+ * @constructor
+ */
+function TextMetrics() {}
+
+/** @type {number} */
+TextMetrics.prototype.width;
+
+/**
+ * @constructor
+ */
+function ImageData() {}
+
+/** @type {Uint8ClampedArray} */
+ImageData.prototype.data;
+
+/** @type {number} */
+ImageData.prototype.width;
+
+/** @type {number} */
+ImageData.prototype.height;
+
+/**
+ * @constructor
+ */
+function ClientInformation() {}
+
+/** @type {boolean} */
+ClientInformation.prototype.onLine;
+
+/**
+ * @param {string} protocol
+ * @param {string} uri
+ * @param {string} title
+ * @return {undefined}
+ */
+ClientInformation.prototype.registerProtocolHandler = function(
+ protocol, uri, title) {};
+
+/**
+ * @param {string} mimeType
+ * @param {string} uri
+ * @param {string} title
+ * @return {undefined}
+ */
+ClientInformation.prototype.registerContentHandler = function(
+ mimeType, uri, title) {};
+
+// HTML5 Database objects
+/**
+ * @constructor
+ */
+function Database() {}
+
+/**
+ * @type {string}
+ */
+Database.prototype.version;
+
+/**
+ * @param {function(!SQLTransaction) : void} callback
+ * @param {(function(!SQLError) : void)=} opt_errorCallback
+ * @param {Function=} opt_Callback
+ */
+Database.prototype.transaction = function(
+ callback, opt_errorCallback, opt_Callback) {};
+
+/**
+ * @param {function(!SQLTransaction) : void} callback
+ * @param {(function(!SQLError) : void)=} opt_errorCallback
+ * @param {Function=} opt_Callback
+ */
+Database.prototype.readTransaction = function(
+ callback, opt_errorCallback, opt_Callback) {};
+
+/**
+ * @param {string} oldVersion
+ * @param {string} newVersion
+ * @param {function(!SQLTransaction) : void} callback
+ * @param {function(!SQLError) : void} errorCallback
+ * @param {Function} successCallback
+ */
+Database.prototype.changeVersion = function(
+ oldVersion, newVersion, callback, errorCallback, successCallback) {};
+
+/**
+ * @interface
+ */
+function DatabaseCallback() {}
+
+/**
+ * @param {!Database} db
+ * @return {undefined}
+ */
+DatabaseCallback.prototype.handleEvent = function(db) {};
+
+/**
+ * @constructor
+ */
+function SQLError() {}
+
+/**
+ * @type {number}
+ */
+SQLError.prototype.code;
+
+/**
+ * @type {string}
+ */
+SQLError.prototype.message;
+
+/**
+ * @constructor
+ */
+function SQLTransaction() {}
+
+/**
+ * @param {string} sqlStatement
+ * @param {Array.<*>=} opt_queryArgs
+ * @param {SQLStatementCallback=} opt_callback
+ * @param {(function(!SQLTransaction, !SQLError) : (boolean|void))=}
+ * opt_errorCallback
+ */
+SQLTransaction.prototype.executeSql = function(
+ sqlStatement, opt_queryArgs, opt_callback, opt_errorCallback) {};
+
+/**
+ * @typedef {(function(!SQLTransaction, !SQLResultSet) : void)}
+ */
+var SQLStatementCallback;
+
+/**
+ * @constructor
+ */
+function SQLResultSet() {}
+
+/**
+ * @type {number}
+ */
+SQLResultSet.prototype.insertId;
+
+/**
+ * @type {number}
+ */
+SQLResultSet.prototype.rowsAffected;
+
+/**
+ * @type {SQLResultSetRowList}
+ */
+SQLResultSet.prototype.rows;
+
+/**
+ * @constructor
+ */
+function SQLResultSetRowList() {}
+
+/**
+ * @type {number}
+ */
+SQLResultSetRowList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {Object}
+ * @nosideeffects
+ */
+SQLResultSetRowList.prototype.item = function(index) {};
+
+/**
+ * @param {string} name
+ * @param {string} version
+ * @param {string} description
+ * @param {number} size
+ * @param {(DatabaseCallback|function(Database))=} opt_callback
+ * @return {Database}
+ */
+function openDatabase(name, version, description, size, opt_callback) {}
+
+/**
+ * @param {string} name
+ * @param {string} version
+ * @param {string} description
+ * @param {number} size
+ * @param {(DatabaseCallback|function(Database))=} opt_callback
+ * @return {Database}
+ */
+Window.prototype.openDatabase =
+ function(name, version, description, size, opt_callback) {};
+
+/**
+ * @type {boolean}
+ */
+HTMLImageElement.prototype.complete;
+
+/**
+ * @type {string}
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#attr-img-crossorigin
+ */
+HTMLImageElement.prototype.crossOrigin;
+
+/**
+ * This is a superposition of the Window and Worker postMessage methods.
+ * @param {*} message
+ * @param {(string|!Array.<!Transferable>)=} opt_targetOriginOrTransfer
+ * @param {(string|!Array.<!MessagePort>|!Array.<!Transferable>)=}
+ * opt_targetOriginOrPortsOrTransfer
+ * @return {void}
+ */
+function postMessage(message, opt_targetOriginOrTransfer,
+ opt_targetOriginOrPortsOrTransfer) {}
+
+/**
+ * The postMessage method (as implemented in Opera).
+ * @param {string} message
+ */
+Document.prototype.postMessage = function(message) {};
+
+/**
+ * Document head accessor.
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#the-head-element-0
+ * @type {HTMLHeadElement}
+ */
+Document.prototype.head;
+
+/**
+ * @see https://developer.apple.com/webapps/docs/documentation/AppleApplications/Reference/SafariJSRef/DOMApplicationCache/DOMApplicationCache.html
+ * @constructor
+ * @implements {EventTarget}
+ */
+function DOMApplicationCache() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+DOMApplicationCache.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+DOMApplicationCache.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+DOMApplicationCache.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * The object isn't associated with an application cache. This can occur if the
+ * update process fails and there is no previous cache to revert to, or if there
+ * is no manifest file.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.UNCACHED = 0;
+
+/**
+ * The cache is idle.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.IDLE = 1;
+
+/**
+ * The update has started but the resources are not downloaded yet - for
+ * example, this can happen when the manifest file is fetched.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.CHECKING = 2;
+
+/**
+ * The resources are being downloaded into the cache.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.DOWNLOADING = 3;
+
+/**
+ * Resources have finished downloading and the new cache is ready to be used.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.UPDATEREADY = 4;
+
+/**
+ * The cache is obsolete.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.OBSOLETE = 5;
+
+/**
+ * The current status of the application cache.
+ * @type {number}
+ */
+DOMApplicationCache.prototype.status;
+
+/**
+ * Sent when the update process finishes for the first time; that is, the first
+ * time an application cache is saved.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.oncached;
+
+/**
+ * Sent when the cache update process begins.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.onchecking;
+
+/**
+ * Sent when the update process begins downloading resources in the manifest
+ * file.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.ondownloading;
+
+/**
+ * Sent when an error occurs.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.onerror;
+
+/**
+ * Sent when the update process finishes but the manifest file does not change.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.onnoupdate;
+
+/**
+ * Sent when each resource in the manifest file begins to download.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.onprogress;
+
+/**
+ * Sent when there is an existing application cache, the update process
+ * finishes, and there is a new application cache ready for use.
+ * @type {?function(!Event)}
+ */
+DOMApplicationCache.prototype.onupdateready;
+
+/**
+ * Replaces the active cache with the latest version.
+ * @throws {DOMException}
+ */
+DOMApplicationCache.prototype.swapCache = function() {};
+
+/**
+ * Manually triggers the update process.
+ * @throws {DOMException}
+ */
+DOMApplicationCache.prototype.update = function() {};
+
+/** @type {DOMApplicationCache} */
+var applicationCache;
+
+/** @type {DOMApplicationCache} */
+Window.prototype.applicationCache;
+
+/**
+ * @see https://developer.mozilla.org/En/DOM/Worker/Functions_available_to_workers
+ * @param {...string} var_args
+ */
+Window.prototype.importScripts = function(var_args) {};
+
+/**
+ * @see https://developer.mozilla.org/En/DOM/Worker/Functions_available_to_workers
+ * @param {...string} var_args
+ */
+var importScripts = function(var_args) {};
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @constructor
+ * @implements {EventTarget}
+ */
+function WebWorker() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+WebWorker.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+WebWorker.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+WebWorker.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * Stops the worker process
+ */
+WebWorker.prototype.terminate = function() {};
+
+/**
+ * Posts a message to the worker thread.
+ * @param {string} message
+ */
+WebWorker.prototype.postMessage = function(message) {};
+
+/**
+ * Sent when the worker thread posts a message to its creator.
+ * @type {?function(!MessageEvent.<*>)}
+ */
+WebWorker.prototype.onmessage;
+
+/**
+ * Sent when the worker thread encounters an error.
+ * TODO(tbreisacher): Should this change to function(!ErrorEvent)?
+ * @type {?function(!Event)}
+ */
+WebWorker.prototype.onerror;
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @constructor
+ * @implements {EventTarget}
+ */
+function Worker(opt_arg0) {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Worker.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Worker.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+Worker.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * Stops the worker process
+ */
+Worker.prototype.terminate = function() {};
+
+/**
+ * Posts a message to the worker thread.
+ * @param {*} message
+ * @param {Array.<!Transferable>=} opt_transfer
+ */
+Worker.prototype.postMessage = function(message, opt_transfer) {};
+
+/**
+ * Posts a message to the worker thread.
+ * @param {*} message
+ * @param {Array.<!Transferable>=} opt_transfer
+ */
+Worker.prototype.webkitPostMessage = function(message, opt_transfer) {};
+
+/**
+ * Sent when the worker thread posts a message to its creator.
+ * @type {?function(!MessageEvent.<*>)}
+ */
+Worker.prototype.onmessage;
+
+/**
+ * Sent when the worker thread encounters an error.
+ * TODO(tbreisacher): Should this change to function(!ErrorEvent)?
+ * @type {?function(!Event)}
+ */
+Worker.prototype.onerror;
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @param {string} scriptURL The URL of the script to run in the SharedWorker.
+ * @param {string=} opt_name A name that can later be used to obtain a
+ * reference to the same SharedWorker.
+ * @constructor
+ * @implements {EventTarget}
+ */
+function SharedWorker(scriptURL, opt_name) {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+SharedWorker.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+SharedWorker.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+SharedWorker.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @type {!MessagePort}
+ */
+SharedWorker.prototype.port;
+
+/**
+ * Called on network errors for loading the initial script.
+ * TODO(tbreisacher): Should this change to function(!ErrorEvent)?
+ * @type {?function(!Event)}
+ */
+SharedWorker.prototype.onerror;
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @interface
+ */
+function WorkerLocation() {}
+
+/** @type {string} */
+WorkerLocation.prototype.protocol;
+
+/** @type {string} */
+WorkerLocation.prototype.host;
+
+/** @type {string} */
+WorkerLocation.prototype.hostname;
+
+/** @type {string} */
+WorkerLocation.prototype.port;
+
+/** @type {string} */
+WorkerLocation.prototype.pathname;
+
+/** @type {string} */
+WorkerLocation.prototype.search;
+
+/** @type {string} */
+WorkerLocation.prototype.hash;
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @interface
+ * @extends {EventTarget}
+ */
+function WorkerGlobalScope() {}
+
+/** @type {WorkerGlobalScope} */
+WorkerGlobalScope.prototype.self;
+
+/** @type {WorkerLocation} */
+WorkerGlobalScope.prototype.location;
+
+/**
+ * Closes the worker represented by this WorkerGlobalScope.
+ */
+WorkerGlobalScope.prototype.close = function() {};
+
+/**
+ * Sent when the worker encounters an error.
+ * @type {?function(!Event)}
+ */
+WorkerGlobalScope.prototype.onerror;
+
+/**
+ * Sent when the worker goes offline.
+ * @type {?function(!Event)}
+ */
+WorkerGlobalScope.prototype.onoffline;
+
+/**
+ * Sent when the worker goes online.
+ * @type {?function(!Event)}
+ */
+WorkerGlobalScope.prototype.ononline;
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @interface
+ * @extends {WorkerGlobalScope}
+ */
+function DedicatedWorkerGlobalScope() {}
+
+/**
+ * Posts a message to creator of this worker.
+ * @param {*} message
+ * @param {Array.<!Transferable>=} opt_transfer
+ */
+DedicatedWorkerGlobalScope.prototype.postMessage =
+ function(message, opt_transfer) {};
+
+/**
+ * Posts a message to creator of this worker.
+ * @param {*} message
+ * @param {Array.<!Transferable>=} opt_transfer
+ */
+DedicatedWorkerGlobalScope.prototype.webkitPostMessage =
+ function(message, opt_transfer) {};
+
+/**
+ * Sent when the creator posts a message to this worker.
+ * @type {?function(!MessageEvent.<*>)}
+ */
+DedicatedWorkerGlobalScope.prototype.onmessage;
+
+/**
+ * @see http://dev.w3.org/html5/workers/
+ * @interface
+ * @extends {WorkerGlobalScope}
+ */
+function SharedWorkerGlobalScope() {}
+
+/** @type {string} */
+SharedWorkerGlobalScope.prototype.name;
+
+/**
+ * Sent when a connection to this worker is opened.
+ * @type {?function(!Event)}
+ */
+SharedWorkerGlobalScope.prototype.onconnect;
+
+/** @type {Element} */
+HTMLElement.prototype.contextMenu;
+
+/** @type {boolean} */
+HTMLElement.prototype.draggable;
+
+/**
+ * This is actually a DOMSettableTokenList property. However since that
+ * interface isn't currently defined and no known browsers implement this
+ * feature, just define the property for now.
+ *
+ * @const
+ * @type {Object}
+ */
+HTMLElement.prototype.dropzone;
+
+/**
+ * @see http://www.w3.org/TR/html5/dom.html#dom-getelementsbyclassname
+ * @param {string} classNames
+ * @return {!NodeList}
+ * @nosideeffects
+ */
+HTMLElement.prototype.getElementsByClassName = function(classNames) {};
+// NOTE: Document.prototype.getElementsByClassName is in gecko_dom.js
+
+/** @type {boolean} */
+HTMLElement.prototype.hidden;
+
+/** @type {boolean} */
+HTMLElement.prototype.spellcheck;
+
+/**
+ * @see http://www.w3.org/TR/components-intro/
+ * @return {!ShadowRoot}
+ */
+HTMLElement.prototype.createShadowRoot;
+
+/**
+ * @see http://www.w3.org/TR/components-intro/
+ * @return {!ShadowRoot}
+ */
+HTMLElement.prototype.webkitCreateShadowRoot;
+
+/**
+ * @see http://www.w3.org/TR/shadow-dom/
+ * @type {ShadowRoot}
+ */
+HTMLElement.prototype.shadowRoot;
+
+/**
+ * @see http://www.w3.org/TR/shadow-dom/
+ * @return {!NodeList}
+ */
+HTMLElement.prototype.getDestinationInsertionPoints = function() {};
+
+/**
+ * @see http://www.w3.org/TR/components-intro/
+ * @type {function()}
+ */
+HTMLElement.prototype.createdCallback;
+
+/**
+ * @see http://w3c.github.io/webcomponents/explainer/#lifecycle-callbacks
+ * @type {function()}
+ */
+HTMLElement.prototype.attachedCallback;
+
+/**
+ * @see http://w3c.github.io/webcomponents/explainer/#lifecycle-callbacks
+ * @type {function()}
+ */
+HTMLElement.prototype.detachedCallback;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.hash;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.host;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.hostname;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.pathname;
+
+/**
+ * The 'ping' attribute is known to be supported in recent versions (as of
+ * mid-2014) of Chrome, Safari, and Firefox, and is not supported in any
+ * current version of Internet Explorer.
+ *
+ * @type {string}
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#hyperlink-auditing
+ */
+HTMLAnchorElement.prototype.ping;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.port;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.protocol;
+
+/** @type {string} */
+HTMLAnchorElement.prototype.search;
+
+/**
+ * @type {string}
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#hyperlink-auditing
+ */
+HTMLAreaElement.prototype.ping;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html-markup/iframe.html#iframe.attrs.srcdoc
+ */
+HTMLIFrameElement.prototype.srcdoc;
+
+/** @type {string} */
+HTMLInputElement.prototype.autocomplete;
+
+/** @type {string} */
+HTMLInputElement.prototype.dirname;
+
+/** @type {FileList} */
+HTMLInputElement.prototype.files;
+
+/** @type {string} */
+HTMLInputElement.prototype.list;
+
+/** @type {string} */
+HTMLInputElement.prototype.max;
+
+/** @type {string} */
+HTMLInputElement.prototype.min;
+
+/** @type {string} */
+HTMLInputElement.prototype.pattern;
+
+/** @type {boolean} */
+HTMLInputElement.prototype.multiple;
+
+/** @type {string} */
+HTMLInputElement.prototype.placeholder;
+
+/** @type {boolean} */
+HTMLInputElement.prototype.required;
+
+/** @type {string} */
+HTMLInputElement.prototype.step;
+
+/** @type {Date} */
+HTMLInputElement.prototype.valueAsDate;
+
+/** @type {number} */
+HTMLInputElement.prototype.valueAsNumber;
+
+/**
+ * Changes the form control's value by the value given in the step attribute
+ * multiplied by opt_n.
+ * @param {number=} opt_n step multiplier. Defaults to 1.
+ */
+HTMLInputElement.prototype.stepDown = function(opt_n) {};
+
+/**
+ * Changes the form control's value by the value given in the step attribute
+ * multiplied by opt_n.
+ * @param {number=} opt_n step multiplier. Defaults to 1.
+ */
+HTMLInputElement.prototype.stepUp = function(opt_n) {};
+
+
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
+ */
+function HTMLMediaElement() {}
+
+/**
+ * @type {number}
+ * @const
+ */
+HTMLMediaElement.HAVE_NOTHING; // = 0
+
+/**
+ * @type {number}
+ * @const
+ */
+HTMLMediaElement.HAVE_METADATA; // = 1
+
+/**
+ * @type {number}
+ * @const
+ */
+HTMLMediaElement.HAVE_CURRENT_DATA; // = 2
+
+/**
+ * @type {number}
+ * @const
+ */
+HTMLMediaElement.HAVE_FUTURE_DATA; // = 3
+
+/**
+ * @type {number}
+ * @const
+ */
+HTMLMediaElement.HAVE_ENOUGH_DATA; // = 4
+
+/** @type {MediaError} */
+HTMLMediaElement.prototype.error;
+
+/** @type {string} */
+HTMLMediaElement.prototype.src;
+
+/** @type {string} */
+HTMLMediaElement.prototype.currentSrc;
+
+/** @type {number} */
+HTMLMediaElement.prototype.networkState;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.autobuffer;
+
+/** @type {TimeRanges} */
+HTMLMediaElement.prototype.buffered;
+
+/**
+ * Loads the media element.
+ */
+HTMLMediaElement.prototype.load = function() {};
+
+/**
+ * @param {string} type Type of the element in question in question.
+ * @return {string} Whether it can play the type.
+ * @nosideeffects
+ */
+HTMLMediaElement.prototype.canPlayType = function(type) {};
+
+/**
+ * Callback when the media is buffered and ready to play through.
+ * @type {function(!Event)}
+ */
+HTMLMediaElement.prototype.oncanplaythrough;
+
+/** @type {number} */
+HTMLMediaElement.prototype.readyState;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.seeking;
+
+/**
+ * The current time, in seconds.
+ * @type {number}
+ */
+HTMLMediaElement.prototype.currentTime;
+
+/**
+ * The absolute timeline offset.
+ * @return {!Date}
+ */
+HTMLMediaElement.prototype.getStartDate = function() {};
+
+/**
+ * The length of the media in seconds.
+ * @type {number}
+ */
+HTMLMediaElement.prototype.duration;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.paused;
+
+/** @type {number} */
+HTMLMediaElement.prototype.defaultPlaybackRate;
+
+/** @type {number} */
+HTMLMediaElement.prototype.playbackRate;
+
+/** @type {TimeRanges} */
+HTMLMediaElement.prototype.played;
+
+/** @type {TimeRanges} */
+HTMLMediaElement.prototype.seekable;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.ended;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.autoplay;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.loop;
+
+/**
+ * Starts playing the media.
+ */
+HTMLMediaElement.prototype.play = function() {};
+
+/**
+ * Pauses the media.
+ */
+HTMLMediaElement.prototype.pause = function() {};
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.controls;
+
+/**
+ * The audio volume, from 0.0 (silent) to 1.0 (loudest).
+ * @type {number}
+ */
+HTMLMediaElement.prototype.volume;
+
+/** @type {boolean} */
+HTMLMediaElement.prototype.muted;
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-media-addtexttrack
+ * @param {string} kind Kind of the text track.
+ * @param {string=} opt_label Label of the text track.
+ * @param {string=} opt_language Language of the text track.
+ * @return {TextTrack} TextTrack object added to the media element.
+ */
+HTMLMediaElement.prototype.addTextTrack =
+ function(kind, opt_label, opt_language) {};
+
+/** @type {TextTrackList} */
+HTMLMediaElement.prototype.textTracks;
+
+
+/**
+ * @see http://www.w3.org/TR/shadow-dom/
+ * @return {!NodeList}
+ */
+Text.prototype.getDestinationInsertionPoints = function() {};
+
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttracklist
+ * @constructor
+ */
+function TextTrackList() {}
+
+/** @type {number} */
+TextTrackList.prototype.length;
+
+/**
+ * @param {string} id
+ * @return {TextTrack}
+ */
+TextTrackList.prototype.getTrackById = function(id) {};
+
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrack
+ * @constructor
+ * @implements {EventTarget}
+ */
+function TextTrack() {}
+
+/**
+ * @param {TextTrackCue} cue
+ */
+TextTrack.prototype.addCue = function(cue) {};
+
+/**
+ * @param {TextTrackCue} cue
+ */
+TextTrack.prototype.removeCue = function(cue) {};
+
+/**
+ * @const {TextTrackCueList}
+ */
+TextTrack.prototype.activeCues;
+
+/**
+ * @const {TextTrackCueList}
+ */
+TextTrack.prototype.cues;
+
+/** @override */
+TextTrack.prototype.addEventListener = function(type, listener, useCapture) {};
+
+/** @override */
+TextTrack.prototype.dispatchEvent = function(evt) {};
+
+/** @override */
+TextTrack.prototype.removeEventListener = function(type, listener, useCapture)
+ {};
+
+
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcuelist
+ * @constructor
+ */
+function TextTrackCueList() {}
+
+/** @const {number} */
+TextTrackCueList.prototype.length;
+
+/**
+ * @param {string} id
+ * @return {TextTrackCue}
+ */
+TextTrackCueList.prototype.getCueById = function(id) {};
+
+
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcue
+ * @constructor
+ * @param {number} startTime
+ * @param {number} endTime
+ * @param {string} text
+ */
+function TextTrackCue(startTime, endTime, text) {}
+
+/** @type {string} */
+TextTrackCue.prototype.id;
+
+/** @type {number} */
+TextTrackCue.prototype.startTime;
+
+/** @type {number} */
+TextTrackCue.prototype.endTime;
+
+/** @type {string} */
+TextTrackCue.prototype.text;
+
+
+/**
+ * @see http://dev.w3.org/html5/webvtt/#the-vttcue-interface
+ * @constructor
+ * @extends {TextTrackCue}
+ */
+function VTTCue(startTime, endTime, text) {}
+
+
+/**
+ * @constructor
+ * @extends {HTMLMediaElement}
+ */
+function HTMLAudioElement() {}
+
+/**
+ * @constructor
+ * @extends {HTMLMediaElement}
+ * The webkit-prefixed attributes are defined in
+ * https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/html/HTMLVideoElement.idl
+ */
+function HTMLVideoElement() {}
+
+/**
+ * Starts displaying the video in full screen mode.
+ */
+HTMLVideoElement.prototype.webkitEnterFullscreen = function() {};
+
+/**
+ * Starts displaying the video in full screen mode.
+ */
+HTMLVideoElement.prototype.webkitEnterFullScreen = function() {};
+
+/**
+ * Stops displaying the video in full screen mode.
+ */
+HTMLVideoElement.prototype.webkitExitFullscreen = function() {};
+
+/**
+ * Stops displaying the video in full screen mode.
+ */
+HTMLVideoElement.prototype.webkitExitFullScreen = function() {};
+
+/** @type {string} */
+HTMLVideoElement.prototype.width;
+
+/** @type {string} */
+HTMLVideoElement.prototype.height;
+
+/** @type {number} */
+HTMLVideoElement.prototype.videoWidth;
+
+/** @type {number} */
+HTMLVideoElement.prototype.videoHeight;
+
+/** @type {string} */
+HTMLVideoElement.prototype.poster;
+
+/** @type {boolean} */
+HTMLVideoElement.prototype.webkitSupportsFullscreen;
+
+/** @type {boolean} */
+HTMLVideoElement.prototype.webkitDisplayingFullscreen;
+
+/** @type {number} */
+HTMLVideoElement.prototype.webkitDecodedFrameCount;
+
+/** @type {number} */
+HTMLVideoElement.prototype.webkitDroppedFrameCount;
+
+/**
+ * @constructor
+ */
+function MediaError() {}
+
+/** @type {number} */
+MediaError.prototype.code;
+
+// HTML5 MessageChannel
+/**
+ * @see http://dev.w3.org/html5/spec/comms.html#messagechannel
+ * @constructor
+ */
+function MessageChannel() {}
+
+/**
+ * Returns the first port.
+ * @type {!MessagePort}
+ */
+MessageChannel.prototype.port1;
+
+/**
+ * Returns the second port.
+ * @type {!MessagePort}
+ */
+MessageChannel.prototype.port2;
+
+// HTML5 MessagePort
+/**
+ * @see http://dev.w3.org/html5/spec/comms.html#messageport
+ * @constructor
+ * @implements {EventTarget}
+ * @implements {Transferable}
+ */
+function MessagePort() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+MessagePort.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+MessagePort.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+MessagePort.prototype.dispatchEvent = function(evt) {};
+
+
+/**
+ * Posts a message through the channel, optionally with the given
+ * Array of Transferables.
+ * @param {*} message
+ * @param {Array.<!Transferable>=} opt_transfer
+ */
+MessagePort.prototype.postMessage = function(message, opt_transfer) {
+};
+
+/**
+ * Begins dispatching messages received on the port.
+ */
+MessagePort.prototype.start = function() {};
+
+/**
+ * Disconnects the port, so that it is no longer active.
+ */
+MessagePort.prototype.close = function() {};
+
+/**
+ * TODO(blickly): Change this to MessageEvent.<*> and add casts as needed
+ * @type {?function(!MessageEvent.<?>)}
+ */
+MessagePort.prototype.onmessage;
+
+// HTML5 MessageEvent class
+/**
+ * @see http://dev.w3.org/html5/spec/comms.html#messageevent
+ * @constructor
+ * @extends {Event}
+ * @template T
+ */
+function MessageEvent() {}
+
+/**
+ * The data payload of the message.
+ * @type {T}
+ */
+MessageEvent.prototype.data;
+
+/**
+ * The origin of the message, for server-sent events and cross-document
+ * messaging.
+ * @type {string}
+ */
+MessageEvent.prototype.origin;
+
+/**
+ * The last event ID, for server-sent events.
+ * @type {string}
+ */
+MessageEvent.prototype.lastEventId;
+
+/**
+ * The window that dispatched the event.
+ * @type {Window}
+ */
+MessageEvent.prototype.source;
+
+/**
+ * The Array of MessagePorts sent with the message, for cross-document
+ * messaging and channel messaging.
+ * @type {Array.<MessagePort>}
+ */
+MessageEvent.prototype.ports;
+
+/**
+ * Initializes the event in a manner analogous to the similarly-named methods in
+ * the DOM Events interfaces.
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {T} dataArg
+ * @param {string} originArg
+ * @param {string} lastEventIdArg
+ * @param {Window} sourceArg
+ * @param {Array.<MessagePort>} portsArg
+ */
+MessageEvent.prototype.initMessageEvent = function(typeArg, canBubbleArg,
+ cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, portsArg) {};
+
+/**
+ * Initializes the event in a manner analogous to the similarly-named methods in
+ * the DOM Events interfaces.
+ * @param {string} namespaceURI
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {T} dataArg
+ * @param {string} originArg
+ * @param {string} lastEventIdArg
+ * @param {Window} sourceArg
+ * @param {Array.<MessagePort>} portsArg
+ */
+MessageEvent.prototype.initMessageEventNS = function(namespaceURI, typeArg,
+ canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg,
+ portsArg) {};
+
+/**
+ * HTML5 DataTransfer class.
+ *
+ * We say that this extends ClipboardData, because Event.prototype.clipboardData
+ * is a DataTransfer on WebKit but a ClipboardData on IE. The interfaces are so
+ * similar that it's easier to merge them.
+ *
+ * @see http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html
+ * @see http://developers.whatwg.org/dnd.html#datatransferitem
+ * @constructor
+ * @extends {ClipboardData}
+ */
+function DataTransfer() {}
+
+/** @type {string} */
+DataTransfer.prototype.dropEffect;
+
+/** @type {string} */
+DataTransfer.prototype.effectAllowed;
+
+/** @type {Array.<string>} */
+DataTransfer.prototype.types;
+
+/** @type {FileList} */
+DataTransfer.prototype.files;
+
+/**
+ * @param {string=} opt_format Format for which to remove data.
+ * @override
+ */
+DataTransfer.prototype.clearData = function(opt_format) {};
+
+/**
+ * @param {string} format Format for which to set data.
+ * @param {string} data Data to add.
+ * @override
+ */
+DataTransfer.prototype.setData = function(format, data) {};
+
+/**
+ * @param {string} format Format for which to set data.
+ * @return {string} Data for the given format.
+ * @override
+ */
+DataTransfer.prototype.getData = function(format) { return ''; };
+
+/**
+ * @param {HTMLElement} img The image to use when dragging.
+ * @param {number} x Horizontal position of the cursor.
+ * @param {number} y Vertical position of the cursor.
+ */
+DataTransfer.prototype.setDragImage = function(img, x, y) {};
+
+/**
+ * @param {HTMLElement} elem Element to receive drag result events.
+ */
+DataTransfer.prototype.addElement = function(elem) {};
+
+/**
+ * Addition for accessing clipboard file data that are part of the proposed
+ * HTML5 spec.
+ * @type {DataTransfer}
+ */
+MouseEvent.prototype.dataTransfer;
+
+/**
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined),
+ * view: (Window|undefined),
+ * detail: (number|undefined),
+ * screenX: (number|undefined),
+ * screenY: (number|undefined),
+ * clientX: (number|undefined),
+ * clientY: (number|undefined),
+ * ctrlKey: (boolean|undefined),
+ * shiftKey: (boolean|undefined),
+ * altKey: (boolean|undefined),
+ * metaKey: (boolean|undefined),
+ * button: (number|undefined),
+ * buttons: (number|undefined),
+ * relatedTarget: (EventTarget|undefined),
+ * deltaX: (number|undefined),
+ * deltaY: (number|undefined),
+ * deltaZ: (number|undefined),
+ * deltaMode: (number|undefined)
+ * }}
+ */
+var WheelEventInit;
+
+/**
+ * @param {string} type
+ * @param {WheelEventInit=} opt_eventInitDict
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#interface-WheelEvent
+ * @constructor
+ * @extends {MouseEvent}
+ */
+var WheelEvent = function(type, opt_eventInitDict) {};
+
+/** @const {number} */
+WheelEvent.prototype.deltaX;
+
+/** @const {number} */
+WheelEvent.prototype.deltaY;
+
+/** @const {number} */
+WheelEvent.prototype.deltaZ;
+
+/** @const {number} */
+WheelEvent.prototype.deltaMode;
+
+/**
+ * HTML5 DataTransferItem class.
+ *
+ * @see http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html
+ * @see http://developers.whatwg.org/dnd.html#datatransferitem
+ * @constructor
+ */
+var DataTransferItem = function() {};
+
+/** @type {string} */
+DataTransferItem.prototype.kind;
+
+/** @type {string} */
+DataTransferItem.prototype.type;
+
+/**
+ * @param {function(string)} callback
+ * @nosideeffects
+ */
+DataTransferItem.prototype.getAsString = function(callback) {};
+
+/**
+ * @return {?File} The file corresponding to this item, or null.
+ * @nosideeffects
+ */
+DataTransferItem.prototype.getAsFile = function() { return null; };
+
+/**
+ * @return {?Entry} The Entry corresponding to this item, or null. Note that
+ * despite its name,this method only works in Chrome, and will eventually
+ * be renamed to {@code getAsEntry}.
+ * @nosideeffects
+ */
+DataTransferItem.prototype.webkitGetAsEntry = function() { return null; };
+
+/**
+ * HTML5 DataTransferItemList class. There are some discrepancies in the docs
+ * on the whatwg.org site. When in doubt, these prototypes match what is
+ * implemented as of Chrome 30.
+ *
+ * @see http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html
+ * @see http://developers.whatwg.org/dnd.html#datatransferitem
+ * @constructor
+ */
+var DataTransferItemList = function() {};
+
+/** @type {number} */
+DataTransferItemList.prototype.length;
+
+/**
+ * @param {number} i File to return from the list.
+ * @return {DataTransferItem} The ith DataTransferItem in the list, or null.
+ * @nosideeffects
+ */
+DataTransferItemList.prototype.item = function(i) { return null; };
+
+/**
+ * Adds an item to the list.
+ * @param {string|!File} data Data for the item being added.
+ * @param {string=} opt_type Mime type of the item being added. MUST be present
+ * if the {@code data} parameter is a string.
+ */
+DataTransferItemList.prototype.add = function(data, opt_type) {};
+
+/**
+ * Removes an item from the list.
+ * @param {number} i File to remove from the list.
+ */
+DataTransferItemList.prototype.remove = function(i) {};
+
+/**
+ * Removes all items from the list.
+ */
+DataTransferItemList.prototype.clear = function() {};
+
+/** @type {!DataTransferItemList} */
+DataTransfer.prototype.items;
+
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-dragevent-interface
+ * @constructor
+ * @extends {MouseEvent}
+ */
+function DragEvent() {}
+
+/** @type {DataTransfer} */
+DragEvent.prototype.dataTransfer;
+
+
+/**
+ * @typedef {{
+ * lengthComputable: (boolean|undefined),
+ * loaded: (number|undefined),
+ * total: (number|undefined)
+ * }}
+ */
+var ProgressEventInit;
+
+/**
+ * @constructor
+ * @param {string} type
+ * @param {ProgressEventInit=} opt_progressEventInitDict
+ * @extends {Event}
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent
+ */
+function ProgressEvent(type, opt_progressEventInitDict) {}
+
+/** @type {number} */
+ProgressEvent.prototype.total;
+
+/** @type {number} */
+ProgressEvent.prototype.loaded;
+
+/** @type {boolean} */
+ProgressEvent.prototype.lengthComputable;
+
+
+/**
+ * @constructor
+ */
+function TimeRanges() {}
+
+/** @type {number} */
+TimeRanges.prototype.length;
+
+/**
+ * @param {number} index The index.
+ * @return {number} The start time of the range at index.
+ * @throws {DOMException}
+ */
+TimeRanges.prototype.start = function(index) { return 0; };
+
+/**
+ * @param {number} index The index.
+ * @return {number} The end time of the range at index.
+ * @throws {DOMException}
+ */
+TimeRanges.prototype.end = function(index) { return 0; };
+
+
+// HTML5 Web Socket class
+/**
+ * @see http://dev.w3.org/html5/websockets/
+ * @constructor
+ * @param {string} url
+ * @param {string=} opt_protocol
+ * @implements {EventTarget}
+ */
+function WebSocket(url, opt_protocol) {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+WebSocket.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+WebSocket.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+WebSocket.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * Returns the URL value that was passed to the constructor.
+ * @type {string}
+ */
+WebSocket.prototype.URL;
+
+/**
+ * The connection has not yet been established.
+ * @type {number}
+ */
+WebSocket.prototype.CONNECTING = 0;
+
+/**
+ * The Web Socket connection is established and communication is possible.
+ * @type {number}
+ */
+WebSocket.prototype.OPEN = 1;
+
+/**
+ * The connection has been closed or could not be opened.
+ * @type {number}
+ */
+WebSocket.prototype.CLOSED = 2;
+
+/**
+ * Represents the state of the connection.
+ * @type {number}
+ */
+WebSocket.prototype.readyState;
+
+/**
+ * Returns the number of bytes that have been queued but not yet sent.
+ * @type {number}
+ */
+WebSocket.prototype.bufferedAmount;
+
+/**
+ * An event handler called on open event.
+ * @type {?function(!Event)}
+ */
+WebSocket.prototype.onopen;
+
+/**
+ * An event handler called on message event.
+ * TODO(blickly): Change this to MessageEvent.<*> and add casts as needed
+ * @type {?function(!MessageEvent.<?>)}
+ */
+WebSocket.prototype.onmessage;
+
+/**
+ * An event handler called on close event.
+ * @type {?function(!Event)}
+ */
+WebSocket.prototype.onclose;
+
+/**
+ * Transmits data using the connection.
+ * @param {string|ArrayBuffer|ArrayBufferView} data
+ * @return {boolean}
+ */
+WebSocket.prototype.send = function(data) {};
+
+/**
+ * Closes the Web Socket connection or connection attempt, if any.
+ */
+WebSocket.prototype.close = function() {};
+
+/**
+ * @type {string} Sets the type of data (blob or arraybuffer) for binary data.
+ */
+WebSocket.prototype.binaryType;
+
+// HTML5 History
+/**
+ * Pushes a new state into the session history.
+ * @see http://www.w3.org/TR/html5/history.html#the-history-interface
+ * @param {*} data New state.
+ * @param {string} title The title for a new session history entry.
+ * @param {string=} opt_url The URL for a new session history entry.
+ */
+History.prototype.pushState = function(data, title, opt_url) {};
+
+/**
+ * Replaces the current state in the session history.
+ * @see http://www.w3.org/TR/html5/history.html#the-history-interface
+ * @param {*} data New state.
+ * @param {string} title The title for a session history entry.
+ * @param {string=} opt_url The URL for a new session history entry.
+ */
+History.prototype.replaceState = function(data, title, opt_url) {};
+
+/**
+ * Pending state object.
+ * @see https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#Reading_the_current_state
+ * @type {*}
+ */
+History.prototype.state;
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/#popstateevent
+ * @constructor
+ * @extends {Event}
+ *
+ * @param {string} type
+ * @param {{state: *}=} opt_eventInitDict
+ */
+function PopStateEvent(type, opt_eventInitDict) {}
+
+/**
+ * @type {*}
+ */
+PopStateEvent.prototype.state;
+
+/**
+ * Initializes the event after it has been created with document.createEvent
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {*} stateArg
+ */
+PopStateEvent.prototype.initPopStateEvent = function(typeArg, canBubbleArg,
+ cancelableArg, stateArg) {};
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/#hashchangeevent
+ * @constructor
+ * @extends {Event}
+ *
+ * @param {string} type
+ * @param {{oldURL: string, newURL: string}=} opt_eventInitDict
+ */
+function HashChangeEvent(type, opt_eventInitDict) {}
+
+/** @type {string} */
+HashChangeEvent.prototype.oldURL;
+
+/** @type {string} */
+HashChangeEvent.prototype.newURL;
+
+/**
+ * Initializes the event after it has been created with document.createEvent
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {string} oldURLArg
+ * @param {string} newURLArg
+ */
+HashChangeEvent.prototype.initHashChangeEvent = function(typeArg, canBubbleArg,
+ cancelableArg, oldURLArg, newURLArg) {};
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/#pagetransitionevent
+ * @constructor
+ * @extends {Event}
+ *
+ * @param {string} type
+ * @param {{persisted: boolean}=} opt_eventInitDict
+ */
+function PageTransitionEvent(type, opt_eventInitDict) {}
+
+/** @type {boolean} */
+PageTransitionEvent.prototype.persisted;
+
+/**
+ * Initializes the event after it has been created with document.createEvent
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {*} persistedArg
+ */
+PageTransitionEvent.prototype.initPageTransitionEvent = function(typeArg,
+ canBubbleArg, cancelableArg, persistedArg) {};
+
+/**
+ * @constructor
+ */
+function FileList() {}
+
+/** @type {number} */
+FileList.prototype.length;
+
+/**
+ * @param {number} i File to return from the list.
+ * @return {File} The ith file in the list.
+ * @nosideeffects
+ */
+FileList.prototype.item = function(i) { return null; };
+
+/**
+ * @type {boolean}
+ * @see http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#withcredentials
+ */
+XMLHttpRequest.prototype.withCredentials;
+
+/**
+ * @type {XMLHttpRequestUpload}
+ * @see http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-upload-attribute
+ */
+XMLHttpRequest.prototype.upload;
+
+/**
+ * @param {string} mimeType The mime type to override with.
+ */
+XMLHttpRequest.prototype.overrideMimeType = function(mimeType) {};
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-responsetype-attribute
+ */
+XMLHttpRequest.prototype.responseType;
+
+/**
+ * @type {*}
+ * @see http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-responsetype-attribute
+ */
+XMLHttpRequest.prototype.response;
+
+
+/**
+ * @type {ArrayBuffer}
+ * Implemented as a draft spec in Firefox 4 as the way to get a requested array
+ * buffer from an XMLHttpRequest.
+ * @see https://developer.mozilla.org/En/Using_XMLHttpRequest#Receiving_binary_data_using_JavaScript_typed_arrays
+ */
+XMLHttpRequest.prototype.mozResponseArrayBuffer;
+
+/**
+ * XMLHttpRequestEventTarget defines events for checking the status of a data
+ * transfer between a client and a server. This should be a common base class
+ * for XMLHttpRequest and XMLHttpRequestUpload.
+ *
+ * @constructor
+ * @implements {EventTarget}
+ */
+function XMLHttpRequestEventTarget() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+XMLHttpRequestEventTarget.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+XMLHttpRequestEventTarget.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+XMLHttpRequestEventTarget.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * An event target to track the status of an upload.
+ *
+ * @constructor
+ * @extends {XMLHttpRequestEventTarget}
+ */
+function XMLHttpRequestUpload() {}
+
+/**
+ * @param {number=} opt_width
+ * @param {number=} opt_height
+ * @constructor
+ * @extends {HTMLImageElement}
+ */
+function Image(opt_width, opt_height) {}
+
+
+/**
+ * Dataset collection.
+ * This is really a DOMStringMap but it behaves close enough to an object to
+ * pass as an object.
+ * @type {Object}
+ * @const
+ */
+HTMLElement.prototype.dataset;
+
+
+/**
+ * @constructor
+ * @see https://dom.spec.whatwg.org/#interface-domtokenlist
+ */
+function DOMTokenList() {}
+
+/**
+ * Returns the number of CSS classes applied to this Element.
+ * @type {number}
+ */
+DOMTokenList.prototype.length;
+
+/**
+ * @param {number} index The index of the item to return.
+ * @return {string} The CSS class at the specified index.
+ * @nosideeffects
+ */
+DOMTokenList.prototype.item = function(index) {};
+
+/**
+ * @param {string} token The CSS class to check for.
+ * @return {boolean} Whether the CSS class has been applied to the Element.
+ * @nosideeffects
+ */
+DOMTokenList.prototype.contains = function(token) {};
+
+/**
+ * @param {...string} var_args The CSS class(es) to add to this element.
+ */
+DOMTokenList.prototype.add = function(var_args) {};
+
+/**
+ * @param {...string} var_args The CSS class(es) to remove from this element.
+ */
+DOMTokenList.prototype.remove = function(var_args) {};
+
+/**
+ * @param {string} token The CSS class to toggle from this element.
+ * @param {boolean=} opt_force True to add the class whether it exists
+ * or not. False to remove the class whether it exists or not.
+ * This argument is not supported on IE 10 and below, according to
+ * the MDN page linked below.
+ * @return {boolean} False if the token was removed; True otherwise.
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element.classList
+ */
+DOMTokenList.prototype.toggle = function(token, opt_force) {};
+
+/**
+ * @return {string} A stringified representation of CSS classes.
+ * @nosideeffects
+ * @override
+ */
+DOMTokenList.prototype.toString = function() {};
+
+/**
+ * A better interface to CSS classes than className.
+ * @type {DOMTokenList}
+ * @see http://www.w3.org/TR/html5/elements.html#dom-classlist
+ * @const
+ */
+HTMLElement.prototype.classList;
+
+/**
+ * Web Cryptography API
+ * @see http://www.w3.org/TR/WebCryptoAPI/
+ */
+
+/** @see https://developer.mozilla.org/en/DOM/window.crypto */
+Window.prototype.crypto;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/window.crypto.getRandomValues
+ * @param {!ArrayBufferView} typedArray
+ * @return {!ArrayBufferView}
+ * @throws {Error}
+ */
+Window.prototype.crypto.getRandomValues = function(typedArray) {};
+
+/**
+ * Constraint Validation API properties and methods
+ * @see http://www.w3.org/TR/2009/WD-html5-20090423/forms.html#the-constraint-validation-api
+ */
+
+/** @return {boolean} */
+HTMLFormElement.prototype.checkValidity = function() {};
+
+/** @type {boolean} */
+HTMLFormElement.prototype.noValidate;
+
+/** @constructor */
+function ValidityState() {}
+
+/** @type {boolean} */
+ValidityState.prototype.customError;
+
+/** @type {boolean} */
+ValidityState.prototype.patternMismatch;
+
+/** @type {boolean} */
+ValidityState.prototype.rangeOverflow;
+
+/** @type {boolean} */
+ValidityState.prototype.rangeUnderflow;
+
+/** @type {boolean} */
+ValidityState.prototype.stepMismatch;
+
+/** @type {boolean} */
+ValidityState.prototype.typeMismatch;
+
+/** @type {boolean} */
+ValidityState.prototype.tooLong;
+
+/** @type {boolean} */
+ValidityState.prototype.valid;
+
+/** @type {boolean} */
+ValidityState.prototype.valueMissing;
+
+
+/** @type {boolean} */
+HTMLButtonElement.prototype.autofocus;
+
+/**
+ * @const
+ * @type {NodeList}
+ */
+HTMLButtonElement.prototype.labels;
+
+/** @type {string} */
+HTMLButtonElement.prototype.validationMessage;
+
+/**
+ * @const
+ * @type {ValidityState}
+ */
+HTMLButtonElement.prototype.validity;
+
+/** @type {boolean} */
+HTMLButtonElement.prototype.willValidate;
+
+/** @return {boolean} */
+HTMLButtonElement.prototype.checkValidity = function() {};
+
+/** @param {string} message */
+HTMLButtonElement.prototype.setCustomValidity = function(message) {};
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formaction
+ */
+HTMLButtonElement.prototype.formAction;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formenctype
+ */
+HTMLButtonElement.prototype.formEnctype;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formmethod
+ */
+HTMLButtonElement.prototype.formMethod;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formtarget
+ */
+HTMLButtonElement.prototype.formTarget;
+
+/** @type {boolean} */
+HTMLInputElement.prototype.autofocus;
+
+/** @type {boolean} */
+HTMLInputElement.prototype.formNoValidate;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formaction
+ */
+HTMLInputElement.prototype.formAction;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formenctype
+ */
+HTMLInputElement.prototype.formEnctype;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formmethod
+ */
+HTMLInputElement.prototype.formMethod;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/forms.html#attr-fs-formtarget
+ */
+HTMLInputElement.prototype.formTarget;
+
+/**
+ * @const
+ * @type {NodeList}
+ */
+HTMLInputElement.prototype.labels;
+
+/** @type {string} */
+HTMLInputElement.prototype.validationMessage;
+
+/**
+ * @const
+ * @type {ValidityState}
+ */
+HTMLInputElement.prototype.validity;
+
+/** @type {boolean} */
+HTMLInputElement.prototype.willValidate;
+
+/** @return {boolean} */
+HTMLInputElement.prototype.checkValidity = function() {};
+
+/** @param {string} message */
+HTMLInputElement.prototype.setCustomValidity = function(message) {};
+
+/** @type {Element} */
+HTMLLabelElement.prototype.control;
+
+/** @type {boolean} */
+HTMLSelectElement.prototype.autofocus;
+
+/**
+ * @const
+ * @type {NodeList}
+ */
+HTMLSelectElement.prototype.labels;
+
+/** @type {HTMLCollection} */
+HTMLSelectElement.prototype.selectedOptions;
+
+/** @type {string} */
+HTMLSelectElement.prototype.validationMessage;
+
+/**
+ * @const
+ * @type {ValidityState}
+ */
+HTMLSelectElement.prototype.validity;
+
+/** @type {boolean} */
+HTMLSelectElement.prototype.willValidate;
+
+/** @return {boolean} */
+HTMLSelectElement.prototype.checkValidity = function() {};
+
+/** @param {string} message */
+HTMLSelectElement.prototype.setCustomValidity = function(message) {};
+
+/** @type {boolean} */
+HTMLTextAreaElement.prototype.autofocus;
+
+/**
+ * @const
+ * @type {NodeList}
+ */
+HTMLTextAreaElement.prototype.labels;
+
+/** @type {string} */
+HTMLTextAreaElement.prototype.validationMessage;
+
+/**
+ * @const
+ * @type {ValidityState}
+ */
+HTMLTextAreaElement.prototype.validity;
+
+/** @type {boolean} */
+HTMLTextAreaElement.prototype.willValidate;
+
+/** @return {boolean} */
+HTMLTextAreaElement.prototype.checkValidity = function() {};
+
+/** @param {string} message */
+HTMLTextAreaElement.prototype.setCustomValidity = function(message) {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/html5/the-embed-element.html#htmlembedelement
+ */
+function HTMLEmbedElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/dimension-attributes.html#dom-dim-width
+ */
+HTMLEmbedElement.prototype.width;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/dimension-attributes.html#dom-dim-height
+ */
+HTMLEmbedElement.prototype.height;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/the-embed-element.html#dom-embed-src
+ */
+HTMLEmbedElement.prototype.src;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/html5/the-embed-element.html#dom-embed-type
+ */
+HTMLEmbedElement.prototype.type;
+
+// Fullscreen APIs.
+
+/**
+ * @see http://www.w3.org/TR/2012/WD-fullscreen-20120703/#dom-element-requestfullscreen
+ */
+Element.prototype.requestFullscreen = function() {};
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2012/WD-fullscreen-20120703/#dom-document-fullscreenenabled
+ */
+Document.prototype.fullscreenEnabled;
+
+/**
+ * @type {Element}
+ * @see http://www.w3.org/TR/2012/WD-fullscreen-20120703/#dom-document-fullscreenelement
+ */
+Document.prototype.fullscreenElement;
+
+/**
+ * @see http://www.w3.org/TR/2012/WD-fullscreen-20120703/#dom-document-exitfullscreen
+ */
+Document.prototype.exitFullscreen = function() {};
+
+// Externs definitions of browser current implementations.
+// Firefox 10 implementation.
+Element.prototype.mozRequestFullScreen = function() {};
+
+Element.prototype.mozRequestFullScreenWithKeys = function() {};
+
+/** @type {boolean} */
+Document.prototype.mozFullScreen;
+
+Document.prototype.mozCancelFullScreen = function() {};
+
+/** @type {Element} */
+Document.prototype.mozFullScreenElement;
+
+/** @type {boolean} */
+Document.prototype.mozFullScreenEnabled;
+
+// Chrome 21 implementation.
+/**
+ * The current fullscreen element for the document is set to this element.
+ * Valid only for Webkit browsers.
+ * @param {number=} opt_allowKeyboardInput Whether keyboard input is desired.
+ * Should use ALLOW_KEYBOARD_INPUT constant.
+ */
+Element.prototype.webkitRequestFullScreen = function(opt_allowKeyboardInput) {};
+
+/**
+ * The current fullscreen element for the document is set to this element.
+ * Valid only for Webkit browsers.
+ * @param {number=} opt_allowKeyboardInput Whether keyboard input is desired.
+ * Should use ALLOW_KEYBOARD_INPUT constant.
+ */
+Element.prototype.webkitRequestFullscreen = function(opt_allowKeyboardInput) {};
+
+/** @type {boolean} */
+Document.prototype.webkitIsFullScreen;
+
+Document.prototype.webkitCancelFullScreen = function() {};
+
+/** @type {Element} */
+Document.prototype.webkitCurrentFullScreenElement;
+
+/** @type {Element} */
+Document.prototype.webkitFullscreenElement;
+
+/** @type {boolean} */
+Document.prototype.webkitFullScreenKeyboardInputAllowed;
+
+// IE 11 implementation.
+// http://msdn.microsoft.com/en-us/library/ie/dn265028(v=vs.85).aspx
+/** @return {void} */
+Element.prototype.msRequestFullscreen = function() {};
+
+/** @return {void} */
+Element.prototype.msExitFullscreen = function() {};
+
+/** @type {boolean} */
+Document.prototype.msFullscreenEnabled;
+
+/** @type {Element} */
+Document.prototype.msFullscreenElement;
+
+/** @type {number} */
+Element.ALLOW_KEYBOARD_INPUT = 1;
+
+/** @type {number} */
+Element.prototype.ALLOW_KEYBOARD_INPUT = 1;
+
+
+/** @constructor */
+function MutationObserverInit() {}
+
+/** @type {boolean} */
+MutationObserverInit.prototype.childList;
+
+/** @type {boolean} */
+MutationObserverInit.prototype.attributes;
+
+/** @type {boolean} */
+MutationObserverInit.prototype.characterData;
+
+/** @type {boolean} */
+MutationObserverInit.prototype.subtree;
+
+/** @type {boolean} */
+MutationObserverInit.prototype.attributeOldValue;
+
+/** @type {boolean} */
+MutationObserverInit.prototype.characterDataOldValue;
+
+/** @type {Array.<string>} */
+MutationObserverInit.prototype.attributeFilter;
+
+
+/** @constructor */
+function MutationRecord() {}
+
+/** @type {string} */
+MutationRecord.prototype.type;
+
+/** @type {Node} */
+MutationRecord.prototype.target;
+
+/** @type {NodeList} */
+MutationRecord.prototype.addedNodes;
+
+/** @type {NodeList} */
+MutationRecord.prototype.removedNodes;
+
+/** @type {Node} */
+MutationRecord.prototype.previouSibling;
+
+/** @type {Node} */
+MutationRecord.prototype.nextSibling;
+
+/** @type {?string} */
+MutationRecord.prototype.attributeName;
+
+/** @type {?string} */
+MutationRecord.prototype.attributeNamespace;
+
+/** @type {?string} */
+MutationRecord.prototype.oldValue;
+
+
+/**
+ * @see http://www.w3.org/TR/domcore/#mutation-observers
+ * @param {function(Array.<MutationRecord>, MutationObserver)} callback
+ * @constructor
+ */
+function MutationObserver(callback) {}
+
+/**
+ * @param {Node} target
+ * @param {MutationObserverInit=} options
+ */
+MutationObserver.prototype.observe = function(target, options) {};
+
+MutationObserver.prototype.disconnect = function() {};
+
+/**
+ * @type {function(new:MutationObserver, function(Array.<MutationRecord>))}
+ */
+Window.prototype.WebKitMutationObserver;
+
+/**
+ * @type {function(new:MutationObserver, function(Array.<MutationRecord>))}
+ */
+Window.prototype.MozMutationObserver;
+
+
+/**
+ * @see http://www.w3.org/TR/page-visibility/
+ * @type {VisibilityState}
+ */
+Document.prototype.visibilityState;
+
+/**
+ * @type {string}
+ */
+Document.prototype.webkitVisibilityState;
+
+/**
+ * @type {string}
+ */
+Document.prototype.msVisibilityState;
+
+/**
+ * @see http://www.w3.org/TR/page-visibility/
+ * @type {boolean}
+ */
+Document.prototype.hidden;
+
+/**
+ * @type {boolean}
+ */
+Document.prototype.webkitHidden;
+
+/**
+ * @type {boolean}
+ */
+Document.prototype.msHidden;
+
+/**
+ * @see http://www.w3.org/TR/components-intro/
+ * @see http://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-register
+ * @param {string} type
+ * @param {{extends: (string|undefined), prototype: (Object|undefined)}} options
+ */
+Document.prototype.registerElement;
+
+/**
+ * This method is deprecated and should be removed by the end of 2014.
+ * @see http://www.w3.org/TR/components-intro/
+ * @see http://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-register
+ * @param {string} type
+ * @param {{extends: (string|undefined), prototype: (Object|undefined)}} options
+ */
+Document.prototype.register;
+
+/**
+ * @type {!FontFaceSet}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfacesource-fonts
+ */
+Document.prototype.fonts;
+
+
+/**
+ * Definition of ShadowRoot interface,
+ * @see http://www.w3.org/TR/shadow-dom/#api-shadow-root
+ * @constructor
+ * @extends {DocumentFragment}
+ */
+function ShadowRoot() {}
+
+/**
+ * The host element that a ShadowRoot is attached to.
+ * Note: this is not yet W3C standard but is undergoing development.
+ * W3C feature tracking bug:
+ * https://www.w3.org/Bugs/Public/show_bug.cgi?id=22399
+ * Draft specification:
+ * https://dvcs.w3.org/hg/webcomponents/raw-file/6743f1ace623/spec/shadow/index.html#shadow-root-object
+ * @type {!Element}
+ */
+ShadowRoot.prototype.host;
+
+/**
+ * @param {string} id id.
+ * @return {HTMLElement}
+ * @nosideeffects
+ */
+ShadowRoot.prototype.getElementById = function(id) {};
+
+
+/**
+ * @param {string} className
+ * @return {!NodeList}
+ * @nosideeffects
+ */
+ShadowRoot.prototype.getElementsByClassName = function(className) {};
+
+
+/**
+ * @param {string} tagName
+ * @return {!NodeList}
+ * @nosideeffects
+ */
+ShadowRoot.prototype.getElementsByTagName = function(tagName) {};
+
+
+/**
+ * @param {string} namespace
+ * @param {string} localName
+ * @return {!NodeList}
+ * @nosideeffects
+ */
+ShadowRoot.prototype.getElementsByTagNameNS = function(namespace, localName) {};
+
+
+/**
+ * @return {Selection}
+ * @nosideeffects
+ */
+ShadowRoot.prototype.getSelection = function() {};
+
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {Element}
+ * @nosideeffects
+ */
+ShadowRoot.prototype.elementFromPoint = function(x, y) {};
+
+
+/**
+ * @type {boolean}
+ */
+ShadowRoot.prototype.applyAuthorStyles;
+
+
+/**
+ * @type {boolean}
+ */
+ShadowRoot.prototype.resetStyleInheritance;
+
+
+/**
+ * @type {Element}
+ */
+ShadowRoot.prototype.activeElement;
+
+
+/**
+ * @type {?ShadowRoot}
+ */
+ShadowRoot.prototype.olderShadowRoot;
+
+
+/**
+ * @type {string}
+ */
+ShadowRoot.prototype.innerHTML;
+
+
+/**
+ * @type {!StyleSheetList}
+ */
+ShadowRoot.prototype.styleSheets;
+
+
+
+/**
+ * @see http://www.w3.org/TR/shadow-dom/#the-content-element
+ * @constructor
+ * @extends {HTMLElement}
+ */
+function HTMLContentElement() {}
+
+/**
+ * @type {!string}
+ */
+HTMLContentElement.prototype.select;
+
+/**
+ * @return {!NodeList}
+ */
+HTMLContentElement.prototype.getDistributedNodes = function() {};
+
+
+/**
+ * @see http://www.w3.org/TR/shadow-dom/#the-shadow-element
+ * @constructor
+ * @extends {HTMLElement}
+ */
+function HTMLShadowElement() {}
+
+/**
+ * @return {!NodeList}
+ */
+HTMLShadowElement.prototype.getDistributedNodes = function() {};
+
+
+/**
+ * @see http://www.w3.org/TR/html5/webappapis.html#the-errorevent-interface
+ *
+ * @constructor
+ * @extends {Event}
+ *
+ * @param {string} type
+ * @param {ErrorEventInit=} opt_eventInitDict
+ */
+function ErrorEvent(type, opt_eventInitDict) {}
+
+/** @const {string} */
+ErrorEvent.prototype.message;
+
+/** @const {string} */
+ErrorEvent.prototype.filename;
+
+/** @const {number} */
+ErrorEvent.prototype.lineno;
+
+/** @const {number} */
+ErrorEvent.prototype.colno;
+
+/** @const {*} */
+ErrorEvent.prototype.error;
+
+
+/**
+ * @see http://www.w3.org/TR/html5/webappapis.html#the-errorevent-interface
+ *
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined),
+ * message: string,
+ * filename: string,
+ * lineno: number,
+ * colno: number,
+ * error: *
+ * }}
+ */
+ var ErrorEventInit;
+
+
+/**
+ * @see http://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
+ * @param {string=} opt_title A title to give the new HTML document
+ * @return {!HTMLDocument}
+ */
+DOMImplementation.prototype.createHTMLDocument = function(opt_title) {};
+
+
+
+/**
+ * @constructor
+ * @see https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element
+ * @extends {HTMLElement}
+ */
+function HTMLPictureElement() {}
+
+/**
+ * @constructor
+ * @see https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element
+ * @extends {HTMLElement}
+ */
+function HTMLSourceElement() {}
+
+/** @type {string} */
+HTMLSourceElement.prototype.media;
+
+/** @type {string} */
+HTMLSourceElement.prototype.sizes;
+
+/** @type {string} */
+HTMLSourceElement.prototype.src;
+
+/** @type {string} */
+HTMLSourceElement.prototype.srcset;
+
+/** @type {string} */
+HTMLSourceElement.prototype.type;
+
+/** @type {string} */
+HTMLImageElement.prototype.sizes;
+
+/** @type {string} */
+HTMLImageElement.prototype.srcset;
+
+
+/**
+ * 4.11 Interactive elements
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html
+ */
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#the-details-element
+ * @constructor
+ * @extends {HTMLElement}
+ */
+function HTMLDetailsElement() {}
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-details-open
+ * @type {boolean}
+ */
+HTMLDetailsElement.prototype.open;
+
+
+// As of 2/20/2015, <summary> has no special web IDL interface nor global
+// constructor (i.e. HTMLSummaryElement).
+
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menu-type
+ * @type {string}
+ */
+HTMLMenuElement.prototype.type;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menu-label
+ * @type {string}
+ */
+HTMLMenuElement.prototype.label;
+
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#the-menuitem-element
+ * @constructor
+ * @extends {HTMLElement}
+ */
+function HTMLMenuItemElement() {}
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-type
+ * @type {string}
+ */
+HTMLMenuItemElement.prototype.type;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-label
+ * @type {string}
+ */
+HTMLMenuItemElement.prototype.label;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-icon
+ * @type {string}
+ */
+HTMLMenuItemElement.prototype.icon;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-disabled
+ * @type {boolean}
+ */
+HTMLMenuItemElement.prototype.disabled;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-checked
+ * @type {boolean}
+ */
+HTMLMenuItemElement.prototype.checked;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-radiogroup
+ * @type {string}
+ */
+HTMLMenuItemElement.prototype.radiogroup;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-menuitem-default
+ * @type {boolean}
+ */
+HTMLMenuItemElement.prototype.default;
+
+// TODO(dbeam): add HTMLMenuItemElement.prototype.command if it's implemented.
+
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#relatedevent
+ * @param {string} type
+ * @param {{relatedTarget: (EventTarget|undefined)}=} opt_eventInitDict
+ * @constructor
+ * @extends {Event}
+ */
+function RelatedEvent(type, opt_eventInitDict) {}
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-relatedevent-relatedtarget
+ * @type {EventTarget|undefined}
+ */
+RelatedEvent.prototype.relatedTarget;
+
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#the-dialog-element
+ * @constructor
+ * @extends {HTMLElement}
+ */
+function HTMLDialogElement() {}
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-dialog-open
+ * @type {boolean}
+ */
+HTMLDialogElement.prototype.open;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-dialog-returnvalue
+ * @type {string}
+ */
+HTMLDialogElement.prototype.returnValue;
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-dialog-show
+ * @param {(MouseEvent|Element)=} opt_anchor
+ */
+HTMLDialogElement.prototype.show = function(opt_anchor) {};
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-dialog-showmodal
+ * @param {(MouseEvent|Element)=} opt_anchor
+ */
+HTMLDialogElement.prototype.showModal = function(opt_anchor) {};
+
+/**
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#dom-dialog-close
+ * @param {string=} opt_returnValue
+ */
+HTMLDialogElement.prototype.close = function(opt_returnValue) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_css.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_css.js
new file mode 100644
index 0000000000..359b9ceb41
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_css.js
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for IE's custom CSS properties, as defined here:
+ * http://msdn.microsoft.com/en-us/library/aa768661(VS.85).aspx
+ *
+ * This page is also useful for the IDL definitions:
+ * http://source.winehq.org/source/include/mshtml.idl
+ *
+ * @externs
+ * @author nicksantos@google.com
+ */
+
+/** @type {Element} */
+StyleSheet.prototype.owningElement;
+
+/** @type {boolean} */
+StyleSheet.prototype.readOnly;
+
+/** @type {StyleSheetList} */
+StyleSheet.prototype.imports;
+
+/** @type {string} */
+StyleSheet.prototype.id;
+
+/**
+ * @param {string} bstrURL
+ * @param {number} lIndex
+ * @return {number}
+ */
+StyleSheet.prototype.addImport;
+
+/**
+ * @param {string} bstrSelector
+ * @param {string} bstrStyle
+ * @param {number=} opt_iIndex
+ * @return {number}
+ * @see http://msdn.microsoft.com/en-us/library/aa358796%28v=vs.85%29.aspx
+ */
+StyleSheet.prototype.addRule;
+
+/**
+ * @param {number} lIndex
+ */
+StyleSheet.prototype.removeImport;
+
+/**
+ * @param {number} lIndex
+ */
+StyleSheet.prototype.removeRule;
+
+/** @type {string} */
+StyleSheet.prototype.cssText;
+
+/** @type {CSSRuleList} */
+StyleSheet.prototype.rules;
+
+// StyleSheet methods
+
+/**
+ * @param {string} propName
+ * @return {string}
+ * @see http://msdn.microsoft.com/en-us/library/aa358797(VS.85).aspx
+ */
+StyleSheet.prototype.getExpression;
+
+/**
+ * @param {string} name
+ * @param {string} expression
+ * @return {undefined}
+ * @see http://msdn.microsoft.com/en-us/library/ms531196(VS.85).aspx
+ */
+StyleSheet.prototype.setExpression;
+
+/**
+ * @param {string} expression
+ * @return {undefined}
+ * @see http://msdn.microsoft.com/en-us/library/aa358798(VS.85).aspx
+ */
+StyleSheet.prototype.removeExpression;
+
+// IE-only CSS style names.
+
+/** @type {string} */ CSSProperties.prototype.backgroundPositionX;
+
+/** @type {string} */ CSSProperties.prototype.backgroundPositionY;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ie/ms531081(v=vs.85).aspx
+ * NOTE: Left untyped to avoid conflict with caller.
+ */
+CSSProperties.prototype.behavior;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms533883.aspx
+ */
+CSSProperties.prototype.imeMode;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms534176(VS.85).aspx
+ */
+CSSProperties.prototype.msInterpolationMode;
+
+/** @type {string} */ CSSProperties.prototype.overflowX;
+
+/** @type {string} */ CSSProperties.prototype.overflowY;
+
+/** @type {number} */ CSSProperties.prototype.pixelWidth;
+
+/** @type {number} */ CSSProperties.prototype.pixelHeight;
+
+/** @type {number} */ CSSProperties.prototype.pixelLeft;
+
+/** @type {number} */ CSSProperties.prototype.pixelTop;
+
+/** @type {string} */ CSSProperties.prototype.styleFloat;
+
+/**
+ * @type {string|number}
+ * @see http://msdn.microsoft.com/en-us/library/ms535169(VS.85).aspx
+ */
+CSSProperties.prototype.zoom;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms535153(VS.85).aspx
+ */
+CSSProperties.prototype.writingMode;
+
+/**
+ * IE-specific extensions.
+ * @see http://blogs.msdn.com/b/ie/archive/2008/09/08/microsoft-css-vendor-extensions.aspx
+ */
+
+/** @type {string} */
+CSSProperties.prototype.MsAccelerator;
+
+/** @type {string} */
+CSSProperties.prototype.MsBackgroundPositionX;
+
+/** @type {string} */
+CSSProperties.prototype.MsBackgroundPositionY;
+
+/** @type {string} */
+CSSProperties.prototype.MsBehavior;
+
+/** @type {string} */
+CSSProperties.prototype.MsBlockProgression;
+
+/** @type {string} */
+CSSProperties.prototype.MsFilter;
+
+/** @type {string} */
+CSSProperties.prototype.MsImeMode;
+
+/** @type {string} */
+CSSProperties.prototype.MsLayoutGrid;
+
+/** @type {string} */
+CSSProperties.prototype.MsLayoutGridChar;
+
+/** @type {string} */
+CSSProperties.prototype.MsLayoutGridLine;
+
+/** @type {string} */
+CSSProperties.prototype.MsLayoutGridMode;
+
+/** @type {string} */
+CSSProperties.prototype.MsLayoutGridType;
+
+/** @type {string} */
+CSSProperties.prototype.MsLineBreak;
+
+/** @type {string} */
+CSSProperties.prototype.MsLineGridMode;
+
+/** @type {string} */
+CSSProperties.prototype.MsInterpolationMode;
+
+/** @type {string} */
+CSSProperties.prototype.MsOverflowX;
+
+/** @type {string} */
+CSSProperties.prototype.MsOverflowY;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbar3dlightColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbarArrowColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbarBaseColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbarDarkshadowColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbarFaceColor;
+
+CSSProperties.prototype.MsScrollbarHighlightColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbarShadowColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsScrollbarTrackColor;
+
+/** @type {string} */
+CSSProperties.prototype.MsTextAlignLast;
+
+/** @type {string} */
+CSSProperties.prototype.MsTextAutospace;
+
+/** @type {string} */
+CSSProperties.prototype.MsTextJustify;
+
+/** @type {string} */
+CSSProperties.prototype.MsTextKashidaSpace;
+
+/** @type {string} */
+CSSProperties.prototype.MsTextOverflow;
+
+/** @type {string} */
+CSSProperties.prototype.MsTextUnderlinePosition;
+
+/** @type {string} */
+CSSProperties.prototype.MsWordBreak;
+
+/** @type {string} */
+CSSProperties.prototype.MsWordWrap;
+
+/** @type {string} */
+CSSProperties.prototype.MsWritingMode;
+
+/** @type {string} */
+CSSProperties.prototype.MsZoom;
+
+// See: http://msdn.microsoft.com/en-us/library/windows/apps/Hh702466.aspx
+
+/** @type {string} */
+CSSProperties.prototype.msContentZooming;
+
+/** @type {string} */
+CSSProperties.prototype.msTouchAction;
+
+/** @type {string} */
+CSSProperties.prototype.msTransform;
+
+/** @type {string} */
+CSSProperties.prototype.msTransition;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_dom.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_dom.js
new file mode 100644
index 0000000000..cbb2ea5adb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_dom.js
@@ -0,0 +1,1395 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over the
+ * W3C's DOM specification by IE in JScript. This file depends on
+ * w3c_dom2.js. The whole file has NOT been fully type annotated.
+ *
+ * When a non-standard extension appears in both Gecko and IE, we put
+ * it in gecko_dom.js
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+
+// TODO(nicksantos): Rewrite all the DOM interfaces as interfaces, instead
+// of kludging them as an inheritance hierarchy.
+
+/**
+ * @constructor
+ * @extends {Document}
+ * @see http://msdn.microsoft.com/en-us/library/ms757878(VS.85).aspx
+ */
+function XMLDOMDocument() {}
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms761398(VS.85).aspx
+ */
+XMLDOMDocument.prototype.async;
+
+/**
+ * @type {!Function}
+ * @see http://msdn.microsoft.com/en-us/library/ms762647(VS.85).aspx
+ */
+XMLDOMDocument.prototype.ondataavailable;
+
+/**
+ * @type {!Function}
+ * @see http://msdn.microsoft.com/en-us/library/ms764640(VS.85).aspx
+ */
+XMLDOMDocument.prototype.onreadystatechange;
+
+/**
+ * @type {!Function}
+ * @see http://msdn.microsoft.com/en-us/library/ms753795(VS.85).aspx
+ */
+XMLDOMDocument.prototype.ontransformnode;
+
+/**
+ * @type {Object}
+ * @see http://msdn.microsoft.com/en-us/library/ms756041(VS.85).aspx
+ */
+XMLDOMDocument.prototype.parseError;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms761353(VS.85).aspx
+ */
+XMLDOMDocument.prototype.preserveWhiteSpace;
+
+/**
+ * @type {number}
+ * @see http://msdn.microsoft.com/en-us/library/ms753702(VS.85).aspx
+ */
+XMLDOMDocument.prototype.readyState;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms762283(VS.85).aspx
+ * @type {boolean}
+ */
+XMLDOMDocument.prototype.resolveExternals;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms760290(v=vs.85).aspx
+ * @param {string} name
+ * @param {*} value
+ */
+XMLDOMDocument.prototype.setProperty = function(name, value) {};
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms767669(VS.85).aspx
+ */
+XMLDOMDocument.prototype.url;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms762791(VS.85).aspx
+ */
+XMLDOMDocument.prototype.validateOnParse;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms763830(VS.85).aspx
+ */
+XMLDOMDocument.prototype.abort = function() {};
+
+/**
+ * @param {*} type
+ * @param {string} name
+ * @param {string} namespaceURI
+ * @return {Node}
+ * @see http://msdn.microsoft.com/en-us/library/ms757901(VS.85).aspx
+ * @nosideeffects
+ */
+XMLDOMDocument.prototype.createNode = function(type, name, namespaceURI) {};
+
+/**
+ * @param {string} xmlSource
+ * @return {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms762722(VS.85).aspx
+ * @override
+ */
+XMLDOMDocument.prototype.load = function(xmlSource) {};
+
+/**
+ * @param {string} xmlString
+ * @return {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms754585(VS.85).aspx
+ * @override
+ */
+XMLDOMDocument.prototype.loadXML = function(xmlString) {};
+
+/**
+ * @param {string} id
+ * @return {Node}
+ * @see http://msdn.microsoft.com/en-us/library/ms766397(VS.85).aspx
+ */
+XMLDOMDocument.prototype.nodeFromID = function(id) {};
+
+//==============================================================================
+// XMLNode methods and properties
+// In a real DOM hierarchy, XMLDOMDocument inherits from XMLNode and Document.
+// Since we can't express that in our type system, we put XMLNode properties
+// on Node.
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms767570(VS.85).aspx
+ */
+Node.prototype.baseName;
+
+/**
+ * @type {?string}
+ * @see http://msdn.microsoft.com/en-us/library/ms762763(VS.85).aspx
+ */
+Node.prototype.dataType;
+
+/**
+ * @type {Node}
+ * @see http://msdn.microsoft.com/en-us/library/ms764733(VS.85).aspx
+ */
+Node.prototype.definition;
+
+/**
+ * IE5 used document instead of ownerDocument.
+ * Old versions of WebKit used document instead of contentDocument.
+ * @type {Document}
+ */
+Node.prototype.document;
+
+
+/**
+ * Inserts the given HTML text into the element at the location.
+ * @param {string} sWhere Where to insert the HTML text, one of 'beforeBegin',
+ * 'afterBegin', 'beforeEnd', 'afterEnd'.
+ * @param {string} sText HTML text to insert.
+ * @see http://msdn.microsoft.com/en-us/library/ms536452(VS.85).aspx
+ */
+Node.prototype.insertAdjacentHTML = function(sWhere, sText) {};
+
+
+/**
+ * @type {*}
+ * @see http://msdn.microsoft.com/en-us/library/ms762308(VS.85).aspx
+ */
+Node.prototype.nodeTypedValue;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms757895(VS.85).aspx
+ */
+Node.prototype.nodeTypeString;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms762237(VS.85).aspx
+ */
+Node.prototype.parsed;
+
+/**
+ * @type {Element}
+ * @see http://msdn.microsoft.com/en-us/library/ms534327(VS.85).aspx
+ */
+Node.prototype.parentElement;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms753816(VS.85).aspx
+ */
+Node.prototype.specified;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms762687(VS.85).aspx
+ */
+Node.prototype.text;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms755989(VS.85).aspx
+ */
+Node.prototype.xml;
+
+/**
+ * @param {string} expression An XPath expression.
+ * @return {NodeList}
+ * @see http://msdn.microsoft.com/en-us/library/ms754523(VS.85).aspx
+ * @nosideeffects
+ */
+Node.prototype.selectNodes = function(expression) {};
+
+/**
+ * @param {string} expression An XPath expression.
+ * @return {Node}
+ * @see http://msdn.microsoft.com/en-us/library/ms757846(VS.85).aspx
+ * @nosideeffects
+ */
+Node.prototype.selectSingleNode = function(expression) {};
+
+/**
+ * @param {Node} stylesheet XSLT stylesheet.
+ * @return {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms761399(VS.85).aspx
+ * @nosideeffects
+ */
+Node.prototype.transformNode = function(stylesheet) {};
+
+/**
+ * @param {Node} stylesheet XSLT stylesheet.
+ * @param {Object} outputObject
+ * @see http://msdn.microsoft.com/en-us/library/ms766561(VS.85).aspx
+ */
+Node.prototype.transformNodeToObject =
+ function(stylesheet, outputObject) {};
+
+//==============================================================================
+// Node methods
+
+/**
+ * @param {boolean=} opt_bRemoveChildren Whether to remove the entire sub-tree.
+ * Defaults to false.
+ * @return {Node} The object that was removed.
+ * @see http://msdn.microsoft.com/en-us/library/ms536708(VS.85).aspx
+ */
+Node.prototype.removeNode = function(opt_bRemoveChildren) {};
+
+/**
+ * @constructor
+ */
+function ClipboardData() {}
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535220(VS.85).aspx
+ * @param {string=} opt_type Type of clipboard data to clear. 'Text' or
+ * 'URL' or 'File' or 'HTML' or 'Image'.
+ */
+ClipboardData.prototype.clearData = function(opt_type) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535220(VS.85).aspx
+ * @param {string} type Type of clipboard data to set ('Text' or 'URL').
+ * @param {string} data Data to set
+ * @return {boolean} Whether the data were set correctly.
+ */
+ClipboardData.prototype.setData = function(type, data) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535220(VS.85).aspx
+ * @param {string} type Type of clipboard data to get ('Text' or 'URL').
+ * @return {string} The current data
+ */
+ClipboardData.prototype.getData = function(type) { };
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/en/DOM/window
+ */
+var window;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535220(VS.85).aspx
+ * @type ClipboardData
+ */
+Window.prototype.clipboardData;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533724(VS.85).aspx
+ */
+Window.prototype.dialogHeight;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533725(VS.85).aspx
+ */
+Window.prototype.dialogLeft;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533726(VS.85).aspx
+ */
+Window.prototype.dialogTop;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533727(VS.85).aspx
+ */
+Window.prototype.dialogWidth;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535863(VS.85).aspx
+ */
+Window.prototype.event;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc197012(VS.85).aspx
+ */
+Window.prototype.maxConnectionsPer1_0Server;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc197013(VS.85).aspx
+ */
+Window.prototype.maxConnectionsPerServer;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534198(VS.85).aspx
+ */
+Window.prototype.offscreenBuffering;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534389(VS.85).aspx
+ */
+Window.prototype.screenLeft;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534389(VS.85).aspx
+ */
+Window.prototype.screenTop;
+
+// Functions
+
+/**
+ * @param {string} event
+ * @param {Function} handler
+ * @see http://msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx
+ */
+Window.prototype.attachEvent;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536392(VS.85).aspx
+ */
+Window.prototype.createPopup;
+
+/**
+ * @param {string} event
+ * @param {Function} handler
+ * @see http://msdn.microsoft.com/en-us/library/ms536411(VS.85).aspx
+ */
+Window.prototype.detachEvent;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536420(VS.85).aspx
+ */
+Window.prototype.execScript;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536425(VS.85).aspx
+ */
+Window.prototype.focus;
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @see http://msdn.microsoft.com/en-us/library/ms536618(VS.85).aspx
+ */
+Window.prototype.moveBy = function(x, y) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @see http://msdn.microsoft.com/en-us/library/ms536626(VS.85).aspx
+ */
+Window.prototype.moveTo = function(x, y) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536638(VS.85).aspx
+ */
+Window.prototype.navigate;
+
+/**
+ * @param {*=} opt_url
+ * @param {string=} opt_windowName
+ * @param {string=} opt_windowFeatures
+ * @param {boolean=} opt_replace
+ * @return {Window}
+ * @see http://msdn.microsoft.com/en-us/library/ms536651(VS.85).aspx
+ */
+Window.prototype.open = function(opt_url, opt_windowName, opt_windowFeatures,
+ opt_replace) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536672(VS.85).aspx
+ */
+Window.prototype.print = function() {};
+
+/**
+ * @param {number} width
+ * @param {number} height
+ * @see http://msdn.microsoft.com/en-us/library/ms536722(VS.85).aspx
+ */
+Window.prototype.resizeBy = function(width, height) {};
+
+/**
+ * @param {number} width
+ * @param {number} height
+ * @see http://msdn.microsoft.com/en-us/library/ms536723(VS.85).aspx
+ */
+Window.prototype.resizeTo = function(width, height) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536738(VS.85).aspx
+ */
+Window.prototype.setActive;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536758(VS.85).aspx
+ */
+Window.prototype.showHelp;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536761(VS.85).aspx
+ */
+Window.prototype.showModelessDialog;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535246%28v=vs.85%29.aspx
+ * @const {!Object}
+ */
+Window.prototype.external;
+
+/**
+ * @constructor
+ */
+function History() { };
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535864(VS.85).aspx
+ * @param {number|string} delta The number of entries to go back, or
+ * the URL to which to go back. (URL form is supported only in IE)
+ */
+History.prototype.go = function(delta) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535864(VS.85).aspx
+ * @param {number=} opt_distance The number of entries to go back
+ * (Mozilla doesn't support distance -- use #go instead)
+ */
+History.prototype.back = function(opt_distance) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535864(VS.85).aspx
+ * @type {number}
+ */
+History.prototype.length;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535864(VS.85).aspx
+ */
+History.prototype.forward = function() {};
+
+/**
+ * @type {boolean}
+ * @implicitCast
+ * @see http://msdn.microsoft.com/en-us/library/ie/ms533072(v=vs.85).aspx
+ */
+HTMLFrameElement.prototype.allowTransparency;
+
+/**
+ * @type {Window}
+ * @see http://msdn.microsoft.com/en-us/library/ms533692(VS.85).aspx
+ */
+HTMLFrameElement.prototype.contentWindow;
+
+/**
+ * @type {boolean}
+ * @implicitCast
+ * @see http://msdn.microsoft.com/en-us/library/ie/ms533072(v=vs.85).aspx
+ */
+HTMLIFrameElement.prototype.allowTransparency;
+
+/**
+ * @type {Window}
+ * @see http://msdn.microsoft.com/en-us/library/ms533692(VS.85).aspx
+ */
+HTMLIFrameElement.prototype.contentWindow;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536385(VS.85).aspx
+ */
+HTMLBodyElement.prototype.createControlRange;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx
+ */
+HTMLScriptElement.prototype.readyState;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx
+ */
+HTMLIFrameElement.prototype.readyState;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx
+ */
+HTMLImageElement.prototype.readyState;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx
+ */
+HTMLObjectElement.prototype.readyState;
+
+
+/**
+ * @constructor
+ */
+function ControlRange() {}
+
+ControlRange.prototype.add;
+ControlRange.prototype.addElement;
+ControlRange.prototype.execCommand;
+ControlRange.prototype.item;
+ControlRange.prototype.queryCommandEnabled;
+ControlRange.prototype.queryCommandIndeterm;
+ControlRange.prototype.queryCommandState;
+ControlRange.prototype.queryCommandSupported;
+ControlRange.prototype.queryCommandValue;
+ControlRange.prototype.remove;
+ControlRange.prototype.scrollIntoView;
+ControlRange.prototype.select;
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/ms535872.aspx
+ */
+function TextRange() {}
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533538(VS.85).aspx
+ */
+TextRange.prototype.boundingHeight;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533539(VS.85).aspx
+ */
+TextRange.prototype.boundingLeft;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533540(VS.85).aspx
+ */
+TextRange.prototype.boundingTop;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533541(VS.85).aspx
+ */
+TextRange.prototype.boundingWidth;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533874(VS.85).aspx
+ */
+TextRange.prototype.htmlText;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534200(VS.85).aspx
+ */
+TextRange.prototype.offsetLeft;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534303(VS.85).aspx
+ */
+TextRange.prototype.offsetTop;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534676(VS.85).aspx
+ */
+TextRange.prototype.text;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536371(VS.85).aspx
+ */
+TextRange.prototype.collapse;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536373(VS.85).aspx
+ */
+TextRange.prototype.compareEndPoints;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536416(VS.85).aspx
+ */
+TextRange.prototype.duplicate;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536419(VS.85).aspx
+ */
+TextRange.prototype.execCommand;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536421(VS.85).aspx
+ */
+TextRange.prototype.expand;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536422(VS.85).aspx
+ */
+TextRange.prototype.findText;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536432(VS.85).aspx
+ */
+TextRange.prototype.getBookmark;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536433(VS.85).aspx
+ */
+TextRange.prototype.getBoundingClientRect;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536435(VS.85).aspx
+ */
+TextRange.prototype.getClientRects;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536450(VS.85).aspx
+ */
+TextRange.prototype.inRange;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536458(VS.85).aspx
+ */
+TextRange.prototype.isEqual;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536616(VS.85).aspx
+ */
+TextRange.prototype.move;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536620(VS.85).aspx
+ */
+TextRange.prototype.moveEnd;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536623(VS.85).aspx
+ */
+TextRange.prototype.moveStart;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536628(VS.85).aspx
+ */
+TextRange.prototype.moveToBookmark;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536630(VS.85).aspx
+ */
+TextRange.prototype.moveToElementText;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536632(VS.85).aspx
+ */
+TextRange.prototype.moveToPoint;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536654(VS.85).aspx
+ */
+TextRange.prototype.parentElement;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536656(VS.85).aspx
+ */
+TextRange.prototype.pasteHTML;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536676(VS.85).aspx
+ */
+TextRange.prototype.queryCommandEnabled;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536678(VS.85).aspx
+ */
+TextRange.prototype.queryCommandIndeterm;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536679(VS.85).aspx
+ */
+TextRange.prototype.queryCommandState;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536681(VS.85).aspx
+ */
+TextRange.prototype.queryCommandSupported;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536683(VS.85).aspx
+ */
+TextRange.prototype.queryCommandValue;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536730(VS.85).aspx
+ */
+TextRange.prototype.scrollIntoView;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536735(VS.85).aspx
+ */
+TextRange.prototype.select;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536745(VS.85).aspx
+ */
+TextRange.prototype.setEndPoint;
+
+/**
+ * @return {undefined}
+ * @see http://msdn.microsoft.com/en-us/library/ms536418(VS.85).aspx
+ */
+Selection.prototype.clear = function() {};
+
+/**
+ * @return {TextRange|ControlRange}
+ * @see http://msdn.microsoft.com/en-us/library/ms536394(VS.85).aspx
+ */
+Selection.prototype.createRange = function() {};
+
+/**
+ * @return {Array.<TextRange>}
+ * @see http://msdn.microsoft.com/en-us/library/ms536396(VS.85).aspx
+ */
+Selection.prototype.createRangeCollection = function() {};
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/ms537447(VS.85).aspx
+ */
+function controlRange() {}
+
+
+Document.prototype.loadXML;
+
+
+// http://msdn.microsoft.com/en-us/library/ms531073(VS.85).aspx
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx
+ */
+Document.prototype.activeElement;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533553(VS.85).aspx
+ */
+Document.prototype.charset;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533693(VS.85).aspx
+ */
+Document.prototype.cookie;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533714(VS.85).aspx
+ */
+Document.prototype.defaultCharset;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533731(VS.85).aspx
+ */
+Document.prototype.dir;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc196988(VS.85).aspx
+ */
+Document.prototype.documentMode;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533747(VS.85).aspx
+ */
+Document.prototype.expando;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533750(VS.85).aspx
+ */
+Document.prototype.fileCreatedDate;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533751(VS.85).aspx
+ */
+Document.prototype.fileModifiedDate;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533752(VS.85).aspx
+ */
+Document.prototype.fileSize;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534331(VS.85).aspx
+ */
+Document.prototype.parentWindow;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534353(VS.85).aspx
+ */
+Document.prototype.protocol;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx
+ */
+HTMLDocument.prototype.readyState;
+
+/**
+ * @type {Selection}
+ * @see http://msdn.microsoft.com/en-us/library/ms535869(VS.85).aspx
+ */
+Document.prototype.selection;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534704(VS.85).aspx
+ */
+Document.prototype.uniqueID;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534709(VS.85).aspx
+ */
+Document.prototype.URLUnencoded;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535155(VS.85).aspx
+ */
+Document.prototype.XMLDocument;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535163(VS.85).aspx
+ */
+Document.prototype.XSLDocument;
+
+// functions
+
+/**
+ * @param {string} event
+ * @param {Function} handler
+ * @see http://msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx
+ */
+Document.prototype.attachEvent;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536390(VS.85).aspx
+ */
+Document.prototype.createEventObject;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms531194(VS.85).aspx
+ */
+Document.prototype.createStyleSheet;
+
+/**
+ * @param {string} event
+ * @param {Function} handler
+ * @see http://msdn.microsoft.com/en-us/library/ms536411(VS.85).aspx
+ */
+Document.prototype.detachEvent;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536425(VS.85).aspx
+ */
+Document.prototype.focus;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536447(VS.85).aspx
+ * @return {boolean}
+ */
+Document.prototype.hasFocus = function() {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536614(VS.85).aspx
+ */
+Document.prototype.mergeAttributes;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536685(VS.85).aspx
+ */
+Document.prototype.recalc;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536689(VS.85).aspx
+ */
+Document.prototype.releaseCapture;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536738(VS.85).aspx
+ */
+Document.prototype.setActive;
+
+
+// collections
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537434(VS.85).aspx
+ */
+Document.prototype.all;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537445(VS.85).aspx
+ */
+Document.prototype.childNodes;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537459(VS.85).aspx
+ */
+Document.prototype.frames;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537470(VS.85).aspx
+ */
+Document.prototype.namespaces;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537487(VS.85).aspx
+ */
+Document.prototype.scripts;
+
+/**
+ * @param {string} sUrl
+ * @return {number}
+ * @see http://msdn.microsoft.com/en-us/library/ms535922(VS.85).aspx
+ */
+Element.prototype.addBehavior = function(sUrl) {};
+
+/**
+ * @param {string} event
+ * @param {Function} handler
+ * @see http://msdn.microsoft.com/en-us/library/mm536343(v=vs.85).aspx
+ */
+Element.prototype.attachEvent;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms533546(VS.85).aspx
+ */
+Element.prototype.canHaveChildren;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms533559(v=vs.85).aspx
+ */
+Element.prototype.classid;
+
+/**
+ * @param {number} iCoordX Integer that specifies the client window coordinate
+ * of x.
+ * @param {number} iCoordY Integer that specifies the client window coordinate
+ * of y.
+ * @return {string} The component of an element located at the specified
+ * coordinates.
+ * @see http://msdn.microsoft.com/en-us/library/ms536375(VS.85).aspx
+ * @nosideeffects
+ */
+Element.prototype.componentFromPoint = function(iCoordX, iCoordY) {};
+
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms533690(VS.85).aspx
+ */
+Element.prototype.contentEditable;
+
+/**
+ * @return {TextRange}
+ * @see http://msdn.microsoft.com/en-us/library/ms536401(VS.85).aspx
+ */
+Element.prototype.createTextRange;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms535231(VS.85).aspx
+ */
+Element.prototype.currentStyle;
+
+/**
+ * @param {string} event
+ * @param {Function} handler
+ * @see http://msdn.microsoft.com/en-us/library/ie/ms536411(v=vs.85).aspx
+ */
+Element.prototype.detachEvent;
+
+/**
+ * @param {string=} opt_action
+ * @see http://msdn.microsoft.com/en-us/library/ms536414%28VS.85%29.aspx
+ */
+Element.prototype.doScroll = function(opt_action) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536423(VS.85).aspx
+ */
+Element.prototype.fireEvent;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms533783(VS.85).aspx
+ */
+Element.prototype.hideFocus;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533899.aspx
+ */
+Element.prototype.innerText;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537838(VS.85).aspx
+ */
+Element.prototype.isContentEditable;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms531395(v=vs.85).aspx
+ * NOTE: Left untyped to avoid conflict with subclasses.
+ */
+Element.prototype.load;
+
+/**
+ * @param {number} pointerId Id of the pointer that is assign to the element.
+ * @see http://msdn.microsoft.com/en-us/library/ie/hh771882(v=vs.85).aspx
+ */
+Element.prototype.msSetPointerCapture = function(pointerId) {};
+
+/**
+ * @param {number} pointerId
+ * @see http://msdn.microsoft.com/en-us/library/ie/hh771880.aspx
+ */
+Element.prototype.msReleasePointerCapture = function(pointerId) {};
+
+/**
+ * @type {?function(Event)}
+ * @see http://msdn.microsoft.com/en-us/library/ms536903(v=vs.85).aspx
+ */
+Element.prototype.onbeforedeactivate;
+
+/**
+ * @type {?function(Event)}
+ * @see http://msdn.microsoft.com/en-us/library/ms536945(VS.85).aspx
+ */
+Element.prototype.onmouseenter;
+
+/**
+ * @type {?function(Event)}
+ * @see http://msdn.microsoft.com/en-us/library/ms536946(VS.85).aspx
+ */
+Element.prototype.onmouseleave;
+
+/**
+ * @type {?function(Event)}
+ * @see http://msdn.microsoft.com/en-us/library/ms536969(VS.85).aspx
+ */
+Element.prototype.onselectstart;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/aa752326(VS.85).aspx
+ */
+Element.prototype.outerHTML;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536689(VS.85).aspx
+ */
+Element.prototype.releaseCapture = function() {};
+
+/**
+ * @param {number} iID
+ * @return {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms536700(VS.85).aspx
+ */
+Element.prototype.removeBehavior = function(iID) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/aa703996(VS.85).aspx
+ */
+Element.prototype.runtimeStyle;
+
+/**
+ * @param {string} sStoreName The arbitrary name assigned to a persistent object
+ * in a UserData store.
+ * @see http://msdn.microsoft.com/en-us/library/ms531403(v=vs.85).aspx
+ */
+Element.prototype.save = function(sStoreName) {};
+
+/**
+ * @param {boolean=} opt_bContainerCapture Events originating in a container are
+ * captured by the container. Defaults to true.
+ * @see http://msdn.microsoft.com/en-us/library/ms536742(VS.85).aspx
+ */
+Element.prototype.setCapture = function(opt_bContainerCapture) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534635(VS.85).aspx
+ */
+Element.prototype.sourceIndex;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms537840.aspx
+ */
+Element.prototype.unselectable;
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/aa752462(v=vs.85).aspx
+ */
+function HTMLFiltersCollection() {}
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/aa752463(v=vs.85).aspx
+ * @type {number}
+ */
+HTMLFiltersCollection.prototype.length;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms537452(v=vs.85).aspx
+ * @type {HTMLFiltersCollection}
+ */
+Element.prototype.filters;
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/ms532853(v=vs.85).aspx
+ */
+function HTMLFilter() {}
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms532954(v=vs.85).aspx
+ */
+HTMLFilter.prototype.apply = function() {};
+
+/**
+ * @constructor
+ * @extends {HTMLFilter}
+ * @see http://msdn.microsoft.com/en-us/library/ms532967(v=vs.85).aspx
+ */
+function AlphaFilter() {}
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms532910(v=vs.85).aspx
+ * @type {number}
+ */
+AlphaFilter.prototype.Opacity;
+
+/**
+ * @constructor
+ * @extends {HTMLFilter}
+ * @see http://msdn.microsoft.com/en-us/library/ms532969(v=vs.85).aspx
+ */
+function AlphaImageLoaderFilter() {}
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms532920(v=vs.85).aspx
+ * @type {string}
+ */
+AlphaImageLoaderFilter.prototype.sizingMethod;
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/ms535866(VS.85).aspx
+ */
+function Location() {}
+
+/**
+ * @see http://trac.webkit.org/changeset/113945
+ * @type {DOMStringList}
+ */
+Location.prototype.ancestorOrigins;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533775(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.hash;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533784(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.host;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533785(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.hostname;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms533867(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.href;
+
+/**
+ * @see https://docs.google.com/document/view?id=1r_VTFKApVOaNIkocrg0z-t7lZgzisTuGTXkdzAk4gLU&hl=en
+ * @type {string}
+ */
+Location.prototype.origin;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534332(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.pathname;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534342(VS.85).aspx
+ */
+Location.prototype.port;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534353(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.protocol;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms534620(VS.85).aspx
+ * @type {string}
+ */
+Location.prototype.search;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ms536342(VS.85).aspx
+ * @param {string} url
+ */
+Location.prototype.assign = function(url) {};
+
+/**
+ * @param {boolean=} opt_forceReload If true, reloads the page from
+ * the server. Defaults to false.
+ * @see http://msdn.microsoft.com/en-us/library/ms536691(VS.85).aspx
+ */
+Location.prototype.reload = function(opt_forceReload) {};
+
+/**
+ * @param {string} url
+ * @see http://msdn.microsoft.com/en-us/library/ms536712(VS.85).aspx
+ */
+Location.prototype.replace = function(url) {};
+
+
+// For IE, returns an object representing key-value pairs for all the global
+// variables prefixed with str, e.g. test*
+
+/** @param {*=} opt_str */
+function RuntimeObject(opt_str) {}
+
+
+/**
+ * @type {StyleSheet}
+ * @see http://msdn.microsoft.com/en-us/library/dd347030(VS.85).aspx
+ */
+HTMLStyleElement.prototype.styleSheet;
+
+
+/**
+ * IE implements Cross Origin Resource Sharing (cross-domain XMLHttpRequests)
+ * via the XDomainRequest object.
+ *
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/cc288060(v=vs.85).aspx
+ * @see http://www.w3.org/TR/cors/
+ */
+function XDomainRequest() {}
+
+/**
+ * Aborts the request.
+ * @see http://msdn.microsoft.com/en-us/library/cc288129(v=vs.85).aspx
+ */
+XDomainRequest.prototype.abort = function() {};
+
+/**
+ * Sets the method and URL for the request.
+ * @param {string} bstrMethod Either "GET" or "POST"
+ * @param {string} bstrUrl The target URL
+ * @see http://msdn.microsoft.com/en-us/library/cc288168(v=vs.85).aspx
+ */
+XDomainRequest.prototype.open = function(bstrMethod, bstrUrl) {};
+
+/**
+ * Sends the request.
+ * @param {string=} varBody The POST body to send to the server. If omitted,
+ * the behavior is identical to sending an empty string.
+ * @see http://msdn.microsoft.com/en-us/library/cc288207(v=vs.85).aspx
+ */
+XDomainRequest.prototype.send = function(varBody) {};
+
+/**
+ * Called if the request could not be completed. Note that error information is
+ * not available.
+ * @see http://msdn.microsoft.com/en-us/library/ms536930%28v=VS.85%29.aspx
+ * @type {?function()}
+ */
+XDomainRequest.prototype.onerror;
+
+/**
+ * Called when the response has finished.
+ * @see http://msdn.microsoft.com/en-us/library/ms536942%28v=VS.85%29.aspx
+ * @type {?function()}
+ */
+XDomainRequest.prototype.onload;
+
+/**
+ * Called every time part of the response has been received.
+ * @see http://msdn.microsoft.com/en-us/library/cc197058%28v=VS.85%29.aspx
+ * @type {?function()}
+ */
+XDomainRequest.prototype.onprogress;
+
+/**
+ * Called if the timeout period has elapsed.
+ * @see http://msdn.microsoft.com/en-us/library/cc197061%28v=VS.85%29.aspx
+ * @type {?function()}
+ */
+XDomainRequest.prototype.ontimeout;
+
+/**
+ * The current response body.
+ * @see http://msdn.microsoft.com/en-us/library/cc287956%28v=VS.85%29.aspx
+ * @type {string}
+ */
+XDomainRequest.prototype.responseText;
+
+/**
+ * The timeout (in milliseconds) for the request.
+ * @type {number}
+ */
+XDomainRequest.prototype.timeout;
+
+/**
+ * The Content-Type of the response, or an empty string.
+ * @type {string}
+ */
+XDomainRequest.prototype.contentType;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/ms533542(v=vs.85).aspx
+ */
+Navigator.prototype.browserLanguage;
+
+/**
+ * @type {boolean}
+ * @see http://blogs.msdn.com/b/ie/archive/2011/09/20/touch-input-for-ie10-and-metro-style-apps.aspx
+ */
+Navigator.prototype.msPointerEnabled;
+
+/**
+ * @type {number}
+ * @see http://msdn.microsoft.com/en-us/library/ms533721(v=vs.85).aspx
+ */
+Screen.prototype.deviceXDPI;
+
+/**
+ * @type {number}
+ * @see http://msdn.microsoft.com/en-us/library/ms534128%28v=vs.85%29.aspx
+ */
+Screen.prototype.logicalXDPI;
+
+/**
+ * @type {number}
+ * @see http://msdn.microsoft.com/en-us/library/ms534130%28v=vs.85%29.aspx
+ */
+Screen.prototype.logicalYDPI;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_event.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_event.js
new file mode 100644
index 0000000000..de2b899046
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_event.js
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over the
+ * W3C's event specification by IE in JScript. This file depends on
+ * w3c_event.js.
+ *
+ * @see http://msdn.microsoft.com/en-us/library/ms535863.aspx
+ * @externs
+ */
+
+/** @type {string} */
+Event.prototype.Abstract;
+
+/** @type {boolean} */
+Event.prototype.altLeft;
+
+/** @type {string} */
+Event.prototype.Banner;
+
+/**
+ * A ClipboardData on IE, but a DataTransfer on WebKit.
+ * @see http://msdn.microsoft.com/en-us/library/ms535220.aspx
+ * @type {(ClipboardData|undefined)}
+ */
+Event.prototype.clipboardData;
+
+/** @type {boolean} */
+Event.prototype.contentOverflow;
+
+/** @type {boolean} */
+Event.prototype.ctrlLeft;
+
+/** @type {string} */
+Event.prototype.dataFld;
+
+Event.prototype.domain;
+
+/** @type {Element} */
+Event.prototype.fromElement;
+
+/** @type {string} */
+Event.prototype.MoreInfo;
+
+/** @type {string} */
+Event.prototype.nextPage;
+
+/** @type {number} */
+Event.prototype.offsetX;
+
+/** @type {number} */
+Event.prototype.offsetY;
+
+/** @type {string} */
+Event.prototype.propertyName;
+
+/** @type {string} */
+Event.prototype.qualifier;
+
+/** @type {number} */
+Event.prototype.reason;
+
+/** @type {Object.<*,*>} */
+Event.prototype.recordset;
+
+/** @type {boolean} */
+Event.prototype.repeat;
+
+/** @type {(boolean|string|undefined)} */
+Event.prototype.returnValue;
+
+/** @type {string} */
+Event.prototype.saveType;
+
+Event.prototype.scheme;
+
+/** @type {boolean} */
+Event.prototype.shiftLeft;
+
+/** @type {Window} */
+Event.prototype.source;
+
+/** @type {Element} */
+Event.prototype.srcElement;
+
+Event.prototype.srcFilter;
+
+/** @type {string} */
+Event.prototype.srcUrn;
+
+/** @type {Element} */
+Event.prototype.toElement;
+
+Event.prototype.userName;
+
+/** @type {number} */
+Event.prototype.wheelDelta;
+
+/** @type {number} */
+Event.prototype.x;
+
+/** @type {number} */
+Event.prototype.y;
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/windows/apps/hh441257.aspx
+ */
+function MSPointerPoint() {}
+
+/** @type {number} */
+MSPointerPoint.prototype.pointerId;
+
+/** @type {number} */
+MSPointerPoint.prototype.pointerType;
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @see http://msdn.microsoft.com/en-us/library/windows/apps/hh441233.aspx
+ */
+function MSPointerEvent() {}
+
+/** @type {number} */
+MSPointerEvent.MSPOINTER_TYPE_MOUSE;
+
+/** @type {number} */
+MSPointerEvent.MSPOINTER_TYPE_PEN;
+
+/** @type {number} */
+MSPointerEvent.MSPOINTER_TYPE_TOUCH;
+
+/** @type {number} */
+MSPointerEvent.prototype.height;
+
+/** @type {number} */
+MSPointerEvent.prototype.hwTimestamp;
+
+/** @type {boolean} */
+MSPointerEvent.prototype.isPrimary;
+
+/** @type {number} */
+MSPointerEvent.prototype.pointerId;
+
+/** @type {number} */
+MSPointerEvent.prototype.pointerType;
+
+/** @type {number} */
+MSPointerEvent.prototype.pressure;
+
+/** @type {number} */
+MSPointerEvent.prototype.rotation;
+
+/** @type {number} */
+MSPointerEvent.prototype.tiltX;
+
+/** @type {number} */
+MSPointerEvent.prototype.tiltY;
+
+/** @type {number} */
+MSPointerEvent.prototype.timeStamp;
+
+/** @type {number} */
+MSPointerEvent.prototype.width;
+
+/**
+ * @param {number} pointerId
+ * @return {undefined}
+ */
+MSPointerEvent.prototype.msReleasePointerCapture;
+
+/**
+ * @param {number} pointerId
+ * @return {undefined}
+ */
+MSPointerEvent.prototype.msSetPointerCapture;
+
+/**
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {Window} viewArg
+ * @param {number} detailArg
+ * @param {number} screenXArg
+ * @param {number} screenYArg
+ * @param {number} clientXArg
+ * @param {number} clientYArg
+ * @param {boolean} ctrlKeyArg
+ * @param {boolean} altKeyArg
+ * @param {boolean} shiftKeyArg
+ * @param {boolean} metaKeyArg
+ * @param {number} buttonArg
+ * @param {Element} relatedTargetArg
+ * @param {number} offsetXArg
+ * @param {number} offsetYArg
+ * @param {number} widthArg
+ * @param {number} heightArg
+ * @param {number} pressure
+ * @param {number} rotation
+ * @param {number} tiltX
+ * @param {number} tiltY
+ * @param {number} pointerIdArg
+ * @param {number} pointerType
+ * @param {number} hwTimestampArg
+ * @param {boolean} isPrimary
+ * @return {undefined}
+ * @see http://msdn.microsoft.com/en-us/library/windows/apps/hh441246.aspx
+ */
+MSPointerEvent.prototype.initPointerEvent;
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/ie/hh968249(v=vs.85).aspx
+ */
+function MSGesture() {}
+
+/**
+ * @type {Element}
+ */
+MSGesture.prototype.target;
+
+/**
+ * @param {number} pointerId
+ */
+MSGesture.prototype.addPointer = function(pointerId) {};
+
+MSGesture.prototype.stop = function() {};
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @see http://msdn.microsoft.com/en-us/library/ie/hh772076(v=vs.85).aspx
+ */
+function MSGestureEvent() {}
+
+/** @type {number} */
+MSGestureEvent.prototype.expansion;
+
+/** @type {!MSGesture} */
+MSGestureEvent.prototype.gestureObject;
+
+/** @type {number} */
+MSGestureEvent.prototype.hwTimestamp;
+
+/** @type {number} */
+MSGestureEvent.prototype.rotation;
+
+/** @type {number} */
+MSGestureEvent.prototype.scale;
+
+/** @type {number} */
+MSGestureEvent.prototype.translationX;
+
+/** @type {number} */
+MSGestureEvent.prototype.translationY;
+
+/** @type {number} */
+MSGestureEvent.prototype.velocityAngular;
+
+/** @type {number} */
+MSGestureEvent.prototype.velocityExpansion;
+
+/** @type {number} */
+MSGestureEvent.prototype.velocityX;
+
+/** @type {number} */
+MSGestureEvent.prototype.velocityY;
+
+/**
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {Window} viewArg
+ * @param {number} detailArg
+ * @param {number} screenXArg
+ * @param {number} screenYArg
+ * @param {number} clientXArg
+ * @param {number} clientYArg
+ * @param {number} offsetXArg
+ * @param {number} offsetYArg
+ * @param {number} translationXArg
+ * @param {number} translationYArg
+ * @param {number} scaleArg
+ * @param {number} expansionArg
+ * @param {number} rotationArg
+ * @param {number} velocityXArg
+ * @param {number} velocityYArg
+ * @param {number} velocityExpansionArg
+ * @param {number} velocityAngularArg
+ * @param {number} hwTimestampArg
+ * @param {EventTarget} relatedTargetArg
+ * @return {undefined}
+ * @see http://msdn.microsoft.com/en-us/library/windows/apps/hh441187.aspx
+ */
+MSGestureEvent.prototype.initGestureEvent;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_vml.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_vml.js
new file mode 100644
index 0000000000..249ffc73a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/ie_vml.js
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for IE's vector markup language, or VML.
+ *
+ * @externs
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+/**
+ * @type {Object|string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263836(VS.85).aspx
+ */
+Element.prototype.coordorigin;
+
+/**
+ * @type {Object|string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263837(VS.85).aspx
+ */
+Element.prototype.coordsize;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263839(VS.85).aspx
+ */
+Element.prototype.fillcolor;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/bb263840(VS.85).aspx
+ */
+Element.prototype.filled;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263871(VS.85).aspx
+ */
+Element.prototype.path;
+
+/**
+ * @type {number|string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263877(VS.85).aspx
+ */
+Element.prototype.rotation;
+
+/**
+ * @type {string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263881(VS.85).aspx
+ */
+Element.prototype.strokecolor;
+
+/**
+ * @type {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/bb263882(VS.85).aspx
+ */
+Element.prototype.stroked;
+
+/**
+ * @type {number|string}
+ * @see http://msdn.microsoft.com/en-us/library/bb263883(VS.85).aspx
+ */
+Element.prototype.strokeweight;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/intl.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/intl.js
new file mode 100644
index 0000000000..d1404872af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/intl.js
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2013 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for the JS Internationalization API as defined in
+ * http://www.ecma-international.org/ecma-402/1.0/
+ *
+ * @externs
+ */
+
+/** @const */
+var Intl = {};
+
+/**
+ * NOTE: this API is not from ecma402 and is subject to change.
+ * @param {string|Array.<string>=} opt_locales
+ * @param {{type: (string|undefined)}=}
+ * opt_options
+ * @constructor
+ */
+Intl.v8BreakIterator = function(opt_locales, opt_options) {};
+
+/**
+ * @param {string} text
+ */
+Intl.v8BreakIterator.prototype.adoptText = function(text) {};
+
+/**
+ * @return {string}
+ */
+Intl.v8BreakIterator.prototype.breakType = function() {};
+
+/**
+ * @return {number}
+ */
+Intl.v8BreakIterator.prototype.current = function() {};
+
+/**
+ * @return {number}
+ */
+Intl.v8BreakIterator.prototype.first = function() {};
+
+/**
+ * @return {number}
+ */
+Intl.v8BreakIterator.prototype.next = function() {};
+
+/**
+ * @constructor
+ * @param {string|Array.<string>=} opt_locales
+ * @param {{usage: (string|undefined), localeMatcher: (string|undefined),
+ * sensitivity: (string|undefined), ignorePunctuation: (boolean|undefined),
+ * numeric: (boolean|undefined), caseFirst: (string|undefined)}=}
+ * opt_options
+ */
+Intl.Collator = function(opt_locales, opt_options) {};
+
+/**
+ * @param {Array.<string>} locales
+ * @param {{localeMatcher: (string|undefined)}=} opt_options
+ */
+Intl.Collator.supportedLocalesOf = function(locales, opt_options) {};
+
+/**
+ * @param {string} arg1
+ * @param {string} arg2
+ * @return {number}
+ */
+Intl.Collator.prototype.compare = function(arg1, arg2) {};
+
+/**
+ * @return {{locale: string, usage: string, sensitivity: string,
+ * ignorePunctuation: boolean, collation: string, numeric: boolean,
+ * caseFirst: string}}
+ */
+Intl.Collator.prototype.resolvedOptions = function() {};
+
+/**
+ * @constructor
+ * @param {string|Array.<string>=} opt_locales
+ * @param {{localeMatcher: (string|undefined), useGrouping: (boolean|undefined),
+ * numberingSystem: (string|undefined), style: (string|undefined),
+ * currency: (string|undefined), currencyDisplay: (string|undefined),
+ * minimumIntegerDigits: (number|undefined),
+ * minimumFractionDigits: (number|undefined),
+ * maximumFractionDigits: (number|undefined),
+ * minimumSignificantDigits: (number|undefined),
+ * maximumSignificantDigits: (number|undefined)}=}
+ * opt_options
+ */
+Intl.NumberFormat = function(opt_locales, opt_options) {};
+
+/**
+ * @param {Array.<string>} locales
+ * @param {{localeMatcher: (string|undefined)}=} opt_options
+ */
+Intl.NumberFormat.supportedLocalesOf = function(locales, opt_options) {};
+
+/**
+ * @param {number} num
+ * @return {string}
+ */
+Intl.NumberFormat.prototype.format = function(num) {};
+
+/**
+ * @return {{locale: string, numberingSystem: string, style: string,
+ * currency: (string|undefined), currencyDisplay: (string|undefined),
+ * minimumIntegerDigits: number, minimumFractionDigits: number,
+ * maximumFractionDigits: number, minimumSignificantDigits: number,
+ * maximumSignificantDigits: number, useGrouping: boolean}}
+ */
+Intl.NumberFormat.prototype.resolvedOptions = function() {};
+
+/**
+ * @constructor
+ * @param {string|Array.<string>=} opt_locales
+ * @param {{localeMatcher: (string|undefined),
+ * formatMatcher: (string|undefined), calendar: (string|undefined),
+ * numberingSystem: (string|undefined), tz: (string|undefined),
+ * weekday: (string|undefined), era: (string|undefined),
+ * year: (string|undefined), month: (string|undefined),
+ * day: (string|undefined), hour: (string|undefined),
+ * minute: (string|undefined), second: (string|undefined),
+ * timeZoneName: (string|undefined), hour12: (boolean|undefined)}=}
+ * opt_options
+ */
+Intl.DateTimeFormat = function(opt_locales, opt_options) {};
+
+/**
+ * @param {Array.<string>} locales
+ * @param {{localeMatcher: string}=} opt_options
+ */
+Intl.DateTimeFormat.supportedLocalesOf = function(locales, opt_options) {};
+
+/**
+ * @param {number} date
+ * @return {string}
+ */
+Intl.DateTimeFormat.prototype.format = function(date) {};
+
+/**
+ * @return {{locale: string, calendar: string, numberingSystem: string,
+ * timeZone: (string|undefined), weekday: (string|undefined),
+ * era: (string|undefined), year: (string|undefined),
+ * month: (string|undefined), day: (string|undefined),
+ * hour: (string|undefined), minute: (string|undefined),
+ * second: (string|undefined), timeZoneName: (string|undefined),
+ * hour12: (boolean|undefined)}}
+ */
+Intl.DateTimeFormat.prototype.resolvedOptions = function() {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/iphone.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/iphone.js
new file mode 100644
index 0000000000..232014149e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/iphone.js
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for all iPhone extensions. Created from:
+ * http://developer.apple.com/library/safari/navigation/
+ *
+ * @externs
+ * @author agrieve@google.com (Andrew Grieve)
+ */
+
+/**
+ * The Touch class represents a single touch on the surface. A touch is the
+ * presence or movement of a finger that is part of a unique multi-touch
+ * sequence.
+ * @see http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/TouchClassReference/Touch/Touch.html
+ * @constructor
+ */
+function Touch() {}
+
+/**
+ * The x-coordinate of the touch's location relative to the window's viewport.
+ * @type {number}
+ */
+Touch.prototype.clientX;
+
+/**
+ * The y-coordinate of the touch's location relative to the window's viewport.
+ * @type {number}
+ */
+Touch.prototype.clientY;
+
+/**
+ * The unique identifier for this touch object.
+ * @type {number}
+ */
+Touch.prototype.identifier;
+
+/**
+ * The x-coordinate of the touch's location in page coordinates.
+ * @type {number}
+ */
+Touch.prototype.pageX;
+
+/**
+ * The y-coordinate of the touch's location in page coordinates.
+ * @type {number}
+ */
+Touch.prototype.pageY;
+
+/**
+ * The x-coordinate of the touch's location in screen coordinates.
+ * @type {number}
+ */
+Touch.prototype.screenX;
+
+/**
+ * The y-coordinate of the touch's location in screen coordinates.
+ * @type {number}
+ */
+Touch.prototype.screenY;
+
+/**
+ * The target of this touch.
+ * @type {EventTarget}
+ */
+Touch.prototype.target;
+
+/**
+ * Creates a new Touch object.
+ * @see http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html#//apple_ref/javascript/instm/Document/createTouch
+ * @param {Window} view
+ * @param {EventTarget} target
+ * @param {number} identifier
+ * @param {number} pageX
+ * @param {number} pageY
+ * @param {number} screenX
+ * @param {number} screenY
+ * @return {Touch}
+ */
+Document.prototype.createTouch = function(view, target, identifier, pageX,
+ pageY, screenX, screenY) {};
+
+/**
+ * The TouchList class is used to represent a collection of Touch objects.
+ * @see http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/TouchListClassReference/TouchList/TouchList.html
+ * @constructor
+ */
+function TouchList() {}
+
+/**
+ * The number of Touch objects in this TouchList object.
+ * @type {number}
+ */
+TouchList.prototype.length;
+
+/**
+ * Returns the Touch object at the given index.
+ * @param {number} index
+ * @return {!Touch}
+ */
+TouchList.prototype.item = function(index) {};
+
+/**
+ * Creates a new TouchList object.
+ * @see http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html#//apple_ref/javascript/instm/Document/createTouchList
+ * @param {Array.<Touch>} touches
+ * @return {TouchList}
+ */
+Document.prototype.createTouchList = function(touches) {};
+
+/**
+ * The TouchEvent class encapsulates information about a touch event.
+ *
+ * <p>The system continually sends TouchEvent objects to an application as
+ * fingers touch and move across a surface. A touch event provides a snapshot of
+ * all touches during a multi-touch sequence, most importantly the touches that
+ * are new or have changed for a particular target. A multi-touch sequence
+ * begins when a finger first touches the surface. Other fingers may
+ * subsequently touch the surface, and all fingers may move across the surface.
+ * The sequence ends when the last of these fingers is lifted from the surface.
+ * An application receives touch event objects during each phase of any touch.
+ * </p>
+ *
+ * <p>The different types of TouchEvent objects that can occur are:
+ * <ul>
+ * <li>touchstart - Sent when a finger for a given event touches the surface.
+ * <li>touchmove - Sent when a given event moves on the surface.
+ * <li>touchend - Sent when a given event lifts from the surface.
+ * <li>touchcancel - Sent when the system cancels tracking for the touch.
+ * </ul>
+ * TouchEvent objects are combined together to form high-level GestureEvent
+ * objects that are also sent during a multi-touch sequence.</p>
+ *
+ * @see http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html
+ * @extends {UIEvent}
+ * @constructor
+ */
+function TouchEvent() {}
+
+/**
+ * A collection of Touch objects representing all touches associated with this
+ * target.
+ * @type {TouchList}
+ */
+TouchEvent.prototype.touches;
+
+/**
+ * A collection of Touch objects representing all touches associated with this
+ * target.
+ * @type {TouchList}
+ */
+TouchEvent.prototype.targetTouches;
+
+/**
+ * A collection of Touch objects representing all touches that changed in this event.
+ * @type {TouchList}
+ */
+TouchEvent.prototype.changedTouches;
+
+/**
+ * The distance between two fingers since the start of an event as a multiplier
+ * of the initial distance. The initial value is 1.0. If less than 1.0, the
+ * gesture is pinch close (to zoom out). If greater than 1.0, the gesture is
+ * pinch open (to zoom in).
+ * @type {number}
+ */
+TouchEvent.prototype.scale;
+
+/**
+ * The delta rotation since the start of an event, in degrees, where clockwise
+ * is positive and counter-clockwise is negative. The initial value is 0.0.
+ * @type {number}
+ */
+TouchEvent.prototype.rotation;
+
+/**
+ * Initializes a newly created TouchEvent object.
+ * @param {string} type
+ * @param {boolean} canBubble
+ * @param {boolean} cancelable
+ * @param {Window} view
+ * @param {number} detail
+ * @param {number} screenX
+ * @param {number} screenY
+ * @param {number} clientX
+ * @param {number} clientY
+ * @param {boolean} ctrlKey
+ * @param {boolean} altKey
+ * @param {boolean} shiftKey
+ * @param {boolean} metaKey
+ * @param {TouchList} touches
+ * @param {TouchList} targetTouches
+ * @param {TouchList} changedTouches
+ * @param {number} scale
+ * @param {number} rotation
+ */
+TouchEvent.prototype.initTouchEvent = function(type, canBubble, cancelable,
+ view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey,
+ metaKey, touches, targetTouches, changedTouches, scale, rotation) {};
+
+/**
+ * The GestureEvent class encapsulates information about a multi-touch gesture.
+ *
+ * GestureEvent objects are high-level events that encapsulate the low-level
+ * TouchEvent objects. Both GestureEvent and TouchEvent events are sent during
+ * a multi-touch sequence. Gesture events contain scaling and rotation
+ * information allowing gestures to be combined, if supported by the platform.
+ * If not supported, one gesture ends before another starts. Listen for
+ * GestureEvent events if you want to respond to gestures only, not process
+ * the low-level TouchEvent objects.
+ *
+ * @see http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/GestureEventClassReference/GestureEvent/GestureEvent.html
+ * @extends {UIEvent}
+ * @constructor
+ */
+function GestureEvent() {}
+
+/**
+ * The distance between two fingers since the start of an event as a multiplier
+ * of the initial distance. The initial value is 1.0. If less than 1.0, the
+ * gesture is pinch close (to zoom out). If greater than 1.0, the gesture is
+ * pinch open (to zoom in).
+ * @type {number}
+ */
+GestureEvent.prototype.scale;
+
+/**
+ * The delta rotation since the start of an event, in degrees, where clockwise
+ * is positive and counter-clockwise is negative. The initial value is 0.0.
+ * @type {number}
+ */
+GestureEvent.prototype.rotation;
+
+/**
+ * The target of this gesture.
+ * @type {EventTarget}
+ */
+GestureEvent.prototype.target;
+
+/**
+ * Initializes a newly created GestureEvent object.
+ * @param {string} type
+ * @param {boolean} canBubble
+ * @param {boolean} cancelable
+ * @param {Window} view
+ * @param {number} detail
+ * @param {number} screenX
+ * @param {number} screenY
+ * @param {number} clientX
+ * @param {number} clientY
+ * @param {boolean} ctrlKey
+ * @param {boolean} altKey
+ * @param {boolean} shiftKey
+ * @param {boolean} metaKey
+ * @param {EventTarget} target
+ * @param {number} scale
+ * @param {number} rotation
+ */
+GestureEvent.prototype.initGestureEvent = function(type, canBubble, cancelable,
+ view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey,
+ metaKey, target, scale, rotation) {};
+
+/**
+ * Specifies the JavaScript method to invoke when the system cancels tracking
+ * for the touch.
+ * @type {?function(!TouchEvent)}
+ */
+Element.prototype.ontouchcancel;
+
+/**
+ * Specifies the JavaScript method to invoke when a given event lifts from the
+ * surface.
+ * @type {?function(!TouchEvent)}
+ */
+Element.prototype.ontouchend;
+
+/**
+ * Specifies the JavaScript method to invoke when a finger for a given event
+ * moves on the surface.
+ * @type {?function(!TouchEvent)}
+ */
+Element.prototype.ontouchmove;
+
+/**
+ * Specifies the JavaScript method to invoke when a finger for a given event
+ * touches the surface.
+ * @type {?function(!TouchEvent)}
+ */
+Element.prototype.ontouchstart;
+
+/**
+ * Specifies the JavaScript method to invoke when a gesture is started by
+ * two or more fingers touching the surface.
+ * @type {?function(!GestureEvent)}
+ */
+Element.prototype.ongesturestart;
+
+/**
+ * Specifies the JavaScript method to invoke when fingers are moved during a
+ * gesture.
+ * @type {?function(!GestureEvent)}
+ */
+Element.prototype.ongesturechange;
+
+/**
+ * Specifies the JavaScript method to invoke when a gesture ends (when there are
+ * 0 or 1 fingers touching the surface).
+ * @type {?function(!GestureEvent)}
+ */
+Element.prototype.ongestureend;
+
+/**
+ * Specifies the JavaScript method to invoke when the browser device's
+ * orientation changes, i.e.the device is rotated.
+ * @type {?function(!Event)}
+ * @see http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
+ */
+Window.prototype.onorientationchange;
+
+/**
+ * Returns the orientation of the browser's device, one of [-90, 0, 90, 180].
+ * @type {number}
+ * @see http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
+ */
+Window.prototype.orientation;
+
+/**
+ * @implicitCast
+ * @type {boolean}
+ */
+HTMLInputElement.prototype.autocorrect;
+
+/**
+ * @implicitCast
+ * @type {boolean}
+ */
+HTMLInputElement.prototype.autocapitalize;
+
+/**
+ * @implicitCast
+ * @type {boolean}
+ */
+HTMLTextAreaElement.prototype.autocorrect;
+
+/**
+ * @implicitCast
+ * @type {boolean}
+ */
+HTMLTextAreaElement.prototype.autocapitalize;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/mediasource.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/mediasource.js
new file mode 100644
index 0000000000..f813ede3ea
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/mediasource.js
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for the Media Source Extensions. Note that the
+ * properties available here are the union of several versions of the spec.
+ * @see http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html
+ *
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ */
+function MediaSource() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+MediaSource.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+MediaSource.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+MediaSource.prototype.dispatchEvent = function(evt) {};
+
+/** @type {Array.<SourceBuffer>} */
+MediaSource.prototype.sourceBuffers;
+
+/** @type {Array.<SourceBuffer>} */
+MediaSource.prototype.activeSourceBuffers;
+
+/** @type {number} */
+MediaSource.prototype.duration;
+
+/**
+ * @param {string} type
+ * @return {SourceBuffer}
+ */
+MediaSource.prototype.addSourceBuffer = function(type) {};
+
+/**
+ * @param {SourceBuffer} sourceBuffer
+ */
+MediaSource.prototype.removeSourceBuffer = function(sourceBuffer) {};
+
+/** @type {string} */
+MediaSource.prototype.readyState;
+
+/**
+ * @param {string=} opt_error
+ */
+MediaSource.prototype.endOfStream = function(opt_error) {};
+
+/**
+ * @param {string} type
+ * @return {boolean}
+ */
+MediaSource.isTypeSupported = function(type) {};
+
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ */
+function SourceBuffer() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+SourceBuffer.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+SourceBuffer.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+SourceBuffer.prototype.dispatchEvent = function(evt) {};
+
+/** @type {string} */
+SourceBuffer.prototype.appendMode;
+
+/** @type {boolean} */
+SourceBuffer.prototype.updating;
+
+/** @type {TimeRanges} */
+SourceBuffer.prototype.buffered;
+
+/** @type {number} */
+SourceBuffer.prototype.timestampOffset;
+
+/** @type {number} */
+SourceBuffer.prototype.appendWindowStart;
+
+/** @type {number} */
+SourceBuffer.prototype.appendWindowEnd;
+
+/**
+ * @param {Uint8Array} data
+ */
+SourceBuffer.prototype.append = function(data) {};
+
+/**
+ * @param {ArrayBuffer|ArrayBufferView} data
+ */
+SourceBuffer.prototype.appendBuffer = function(data) {};
+
+/**
+ * Abort the current segment append sequence.
+ */
+SourceBuffer.prototype.abort = function() {};
+
+/**
+ * @param {number} start
+ * @param {number} end
+ */
+SourceBuffer.prototype.remove = function(start, end) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/page_visibility.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/page_visibility.js
new file mode 100644
index 0000000000..42bc9a4cdf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/page_visibility.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2015 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Externs for Page Visibility.
+ *
+ * @see http://www.w3.org/TR/page-visibility
+ * @externs
+ */
+
+/**
+ * @enum {string}
+ * @see http://www.w3.org/TR/page-visibility/#VisibilityState
+ */
+var VisibilityState = {
+ HIDDEN: 'hidden',
+ VISIBLE: 'visible',
+ PRERENDER: 'prerender',
+ UNLOADED: 'unloaded'
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/v8.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/v8.js
new file mode 100644
index 0000000000..be11bd83a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/v8.js
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2013 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview This file describes the externs API for V8-specific objects.
+ * @externs
+ */
+
+
+
+/**
+ * Stack frame elements in V8.
+ * @constructor
+ */
+function CallSite() {}
+
+
+/**
+ * Returns the value of this.
+ * @return {Object|undefined}
+ */
+CallSite.prototype.getThis = function() {};
+
+
+/**
+ * Returns the type of this as a string. This is the name of the function stored
+ * in the constructor field of this, if available, otherwise the object's
+ * [[Class]] internal property.
+ * @return {string|undefined}
+ */
+CallSite.prototype.getTypeName = function() {};
+
+
+/**
+ * Returns the current function.
+ * @return {!Function|undefined}
+ */
+CallSite.prototype.getFunction = function() {};
+
+
+/**
+ * Returns the name of the current function, typically its name property. If a
+ * name property is not available an attempt will be made to try to infer a name
+ * from the function's context.
+ * @return {string|undefined}
+ */
+CallSite.prototype.getFunctionName = function() {};
+
+
+/**
+ * Returns the name of the property of this or one of its prototypes that holds
+ * the current function.
+ * @return {string|undefined}
+ */
+CallSite.prototype.getMethodName = function() {};
+
+
+/**
+ * If this function was defined in a script returns the name of the script
+ * @return {string|undefined}
+ */
+CallSite.prototype.getFileName = function() {};
+
+
+/**
+ * If this function was defined in a script returns the current line number.
+ * @return {number|undefined}
+ */
+CallSite.prototype.getLineNumber = function() {};
+
+
+/**
+ * If this function was defined in a script returns the current column number.
+ * @return {number|undefined}
+ */
+CallSite.prototype.getColumnNumber = function() {};
+
+
+/**
+ * If this function was created using a call to eval, returns a CallSite object
+ * representing the location where eval was called
+ * @return {CallSite|undefined}
+ */
+CallSite.prototype.getEvalOrigin = function() {};
+
+
+/**
+ * Is this a toplevel invocation, that is, is this the global object?
+ * @return {boolean}
+ */
+CallSite.prototype.isToplevel = function() {};
+
+
+/**
+ * Does this call take place in code defined by a call to eval?
+ * @return {boolean}
+ */
+CallSite.prototype.isEval = function() {};
+
+
+/**
+ * Is this call in native V8 code?
+ * @return {boolean}
+ */
+CallSite.prototype.isNative = function() {};
+
+
+/**
+ * Is this a constructor call?
+ * @return {boolean}
+ */
+CallSite.prototype.isConstructor = function() {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_anim_timing.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_anim_timing.js
new file mode 100644
index 0000000000..ea34abef54
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_anim_timing.js
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2011 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for timing control for script base animations. The
+ * whole file has been fully type annotated.
+ *
+ * @see http://www.w3.org/TR/animation-timing/
+ * @see http://webstuff.nfshost.com/anim-timing/Overview.html
+ * @externs
+ */
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element In early versions of this API, the callback
+ * was invoked only if the element was visible.
+ * @return {number}
+ */
+function requestAnimationFrame(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+function cancelRequestAnimationFrame(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+function webkitRequestAnimationFrame(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+function webkitCancelRequestAnimationFrame(handle) {};
+
+/**
+ * @param {number} handle
+ */
+function webkitCancelAnimationFrame(handle) {};
+
+/**
+ * @param {?function(number)} callback It's legitimate to pass a null
+ * callback and listen on the MozBeforePaint event instead.
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+function mozRequestAnimationFrame(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+function mozCancelRequestAnimationFrame(handle) {};
+
+/**
+ * @param {number} handle
+ */
+function mozCancelAnimationFrame(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+function msRequestAnimationFrame(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+function msCancelRequestAnimationFrame(handle) {};
+
+/**
+ * @param {number} handle
+ */
+function msCancelAnimationFrame(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+function oRequestAnimationFrame(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+function oCancelRequestAnimationFrame(handle) {};
+
+/**
+ * @param {number} handle
+ */
+function oCancelAnimationFrame(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+Window.prototype.requestAnimationFrame = function(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.cancelRequestAnimationFrame = function(handle) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.cancelAnimationFrame = function(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+Window.prototype.webkitRequestAnimationFrame = function(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.webkitCancelRequestAnimationFrame = function(handle) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.webkitCancelAnimationFrame = function(handle) {};
+
+/**
+ * @param {?function(number)} callback It's legitimate to pass a null
+ * callback and listen on the MozBeforePaint event instead.
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+Window.prototype.mozRequestAnimationFrame = function(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.mozCancelRequestAnimationFrame = function(handle) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.mozCancelAnimationFrame = function(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+Window.prototype.msRequestAnimationFrame = function(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.msCancelRequestAnimationFrame = function(handle) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.msCancelAnimationFrame = function(handle) {};
+
+/**
+ * @param {function(number)} callback
+ * @param {Element=} opt_element
+ * @return {number}
+ */
+Window.prototype.oRequestAnimationFrame = function(callback, opt_element) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.oCancelRequestAnimationFrame = function(handle) {};
+
+/**
+ * @param {number} handle
+ */
+Window.prototype.oCancelAnimationFrame = function(handle) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css.js
new file mode 100644
index 0000000000..e3b4ebae95
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css.js
@@ -0,0 +1,2505 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's CSS specification
+ * The whole file has been fully type annotated.
+ * http://www.w3.org/TR/DOM-Level-2-Style/css.html
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ *
+ * TODO(nicksantos): When there are no more occurrences of w3c_range.js and
+ * gecko_dom.js being included directly in BUILD files, bug dbeam to split the
+ * bottom part of this file into a separate externs.
+ */
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet
+ */
+function StyleSheet() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-type
+ */
+StyleSheet.prototype.type;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-disabled
+ */
+StyleSheet.prototype.disabled;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-owner
+ */
+StyleSheet.prototype.ownerNode;
+
+/**
+ * @type {StyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-parentStyleSheet
+ */
+StyleSheet.prototype.parentStyleSheet;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-href
+ */
+StyleSheet.prototype.href;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-title
+ */
+StyleSheet.prototype.title;
+
+/**
+ * @type {MediaList}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-media
+ */
+StyleSheet.prototype.media;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheetList
+ */
+function StyleSheetList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheetList-length
+ */
+StyleSheetList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {StyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheetList-item
+ */
+StyleSheetList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-MediaList
+ */
+function MediaList() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-MediaList-mediaText
+ */
+MediaList.prototype.mediaText;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-MediaList-length
+ */
+MediaList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-MediaList-item
+ */
+MediaList.prototype.item = function(index) {};
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-LinkStyle
+ */
+function LinkStyle() {}
+
+/**
+ * @type {StyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-LinkStyle-sheet
+ */
+LinkStyle.prototype.sheet;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-DocumentStyle
+ */
+function DocumentStyle() {}
+
+/**
+ * @type {StyleSheetList}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-DocumentStyle-styleSheets
+ */
+DocumentStyle.prototype.styleSheets;
+
+/**
+ * @constructor
+ * @extends {StyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet
+ */
+function CSSStyleSheet() {}
+
+/**
+ * @type {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-ownerRule
+ */
+CSSStyleSheet.prototype.ownerRule;
+
+/**
+ * @type {CSSRuleList}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-cssRules
+ */
+CSSStyleSheet.prototype.cssRules;
+
+/**
+ * @param {string} rule
+ * @param {number} index
+ * @return {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
+ */
+CSSStyleSheet.prototype.insertRule = function(rule, index) {};
+
+/**
+ * @param {number} index
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-deleteRule
+ */
+CSSStyleSheet.prototype.deleteRule = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRuleList
+ */
+function CSSRuleList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRuleList-length
+ */
+CSSRuleList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRuleList-item
+ */
+CSSRuleList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule
+ */
+function CSSRule() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-cssText
+ */
+CSSRule.prototype.cssText;
+
+/**
+ * @type {CSSStyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-sheet
+ */
+CSSRule.prototype.parentStyleSheet;
+
+/**
+ * @type {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-parentRule
+ */
+CSSRule.prototype.parentRule;
+
+/**
+ * @type {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule
+ */
+CSSRule.prototype.style;
+
+/**
+ * Indicates that the rule is a {@see CSSUnknownRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.UNKNOWN_RULE = 0;
+
+/**
+ * Indicates that the rule is a {@see CSSStyleRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.STYLE_RULE = 1;
+
+/**
+ * Indicates that the rule is a {@see CSSCharsetRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.CHARSET_RULE = 2;
+
+/**
+ * Indicates that the rule is a {@see CSSImportRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.IMPORT_RULE = 3;
+
+/**
+ * Indicates that the rule is a {@see CSSMediaRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.MEDIA_RULE = 4;
+
+/**
+ * Indicates that the rule is a {@see CSSFontFaceRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.FONT_FACE_RULE = 5;
+
+/**
+ * Indicates that the rule is a {@see CSSPageRule}.
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule-ruleType
+ */
+CSSRule.PAGE_RULE = 6;
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule
+ */
+function CSSStyleRule() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule-selectorText
+ */
+CSSStyleRule.prototype.selectorText;
+
+/**
+ * @type {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule-style
+ */
+CSSStyleRule.prototype.style;
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule
+ */
+function CSSMediaRule() {}
+
+/**
+ * @type {MediaList}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule-mediaTypes
+ */
+CSSMediaRule.prototype.media;
+
+/**
+ * @type {CSSRuleList}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule-cssRules
+ */
+CSSMediaRule.prototype.cssRules;
+
+/**
+ * @param {string} rule
+ * @param {number} index
+ * @return {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule-insertRule
+ */
+CSSMediaRule.prototype.insertRule = function(rule, index) {};
+
+/**
+ * @param {number} index
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule-deleteRule
+ */
+CSSMediaRule.prototype.deleteRule = function(index) {};
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSFontFaceRule
+ */
+function CSSFontFaceRule() {}
+
+/**
+ * @type {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSFontFaceRule-style
+ */
+CSSFontFaceRule.prototype.style;
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPageRule
+ */
+function CSSPageRule() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPageRule-name
+ */
+CSSPageRule.prototype.selectorText;
+
+/**
+ * @type {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPageRule-style
+ */
+CSSPageRule.prototype.style;
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule
+ */
+function CSSImportRule() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule-href
+ */
+CSSImportRule.prototype.href;
+
+/**
+ * @type {MediaList}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule-media
+ */
+CSSImportRule.prototype.media;
+
+/**
+ * @type {CSSStyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule-styleSheet
+ */
+CSSImportRule.prototype.styleSheet;
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSCharsetRule
+ */
+function CSSCharsetRule() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSCharsetRule-encoding
+ */
+CSSCharsetRule.prototype.encoding;
+
+/**
+ * @constructor
+ * @extends {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSUnknownRule
+ */
+function CSSUnknownRule() {}
+
+/**
+ * @constructor
+ * @extends {CSSProperties}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
+ */
+function CSSStyleDeclaration() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-cssText
+ */
+CSSStyleDeclaration.prototype.cssText;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-length
+ */
+CSSStyleDeclaration.prototype.length;
+
+/**
+ * @type {CSSRule}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-parentRule
+ */
+CSSStyleDeclaration.prototype.parentRule;
+
+/**
+ * @param {string} propertyName
+ * @return {CSSValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyCSSValue
+ */
+CSSStyleDeclaration.prototype.getPropertyCSSValue = function(propertyName) {};
+
+/**
+ * @param {string} propertyName
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyPriority
+ */
+CSSStyleDeclaration.prototype.getPropertyPriority = function(propertyName) {};
+
+/**
+ * @param {string} propertyName
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue
+ */
+CSSStyleDeclaration.prototype.getPropertyValue = function(propertyName) {};
+
+/**
+ * @param {number} index
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-item
+ */
+CSSStyleDeclaration.prototype.item = function(index) {};
+
+/**
+ * @param {string} propertyName
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty
+ */
+CSSStyleDeclaration.prototype.removeProperty = function(propertyName) {};
+
+/**
+ * @param {string} propertyName
+ * @param {string} value
+ * @param {string=} opt_priority
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
+ */
+CSSStyleDeclaration.prototype.setProperty = function(propertyName, value, opt_priority) {};
+
+// IE-specific
+
+/**
+ * @param {string} name
+ * @param {number=} opt_flags
+ * @return {string|number|boolean|null}
+ * @see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
+ */
+CSSStyleDeclaration.prototype.getAttribute = function(name, opt_flags) {};
+
+/**
+ * @param {string} name
+ * @return {string|number|boolean|null}
+ * @see http://msdn.microsoft.com/en-us/library/aa358797(VS.85).aspx
+ */
+CSSStyleDeclaration.prototype.getExpression = function(name) {};
+
+/**
+ * @param {string} name
+ * @param {number=} opt_flags
+ * @return {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/ms536696(VS.85).aspx
+ */
+CSSStyleDeclaration.prototype.removeAttribute =
+ function(name, opt_flags) {};
+
+/**
+ * @param {string} name
+ * @return {boolean}
+ * @see http://msdn.microsoft.com/en-us/library/aa358798(VS.85).aspx
+ */
+CSSStyleDeclaration.prototype.removeExpression = function(name) {};
+
+/**
+ * @param {string} name
+ * @param {*} value
+ * @param {number=} opt_flags
+ * @see http://msdn.microsoft.com/en-us/library/ms536739(VS.85).aspx
+ */
+CSSStyleDeclaration.prototype.setAttribute = function(name, value, opt_flags) {};
+
+/**
+ * @param {string} name
+ * @param {string} expr
+ * @param {string=} opt_language
+ * @return {undefined}
+ * @see http://msdn.microsoft.com/en-us/library/ms531196(VS.85).aspx
+ */
+CSSStyleDeclaration.prototype.setExpression =
+ function(name, expr, opt_language) {};
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
+ */
+function CSSValue() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue-cssText
+ */
+CSSValue.prototype.cssText;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue-cssValueType
+ */
+CSSValue.prototype.cssValueType;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue-types
+ */
+CSSValue.CSS_INHERIT = 0;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue-types
+ */
+CSSValue.CSS_PRIMITIVE_VALUE = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue-types
+ */
+CSSValue.CSS_VALUE_LIST = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue-types
+ */
+CSSValue.CSS_CUSTOM = 3;
+
+/**
+ * @constructor
+ * @extends {CSSValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+function CSSPrimitiveValue() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.prototype.primitiveType;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_UNKNOWN = 0;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_NUMBER = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_PERCENTAGE = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_EMS = 3;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_EXS = 4;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_PX = 5;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_CM = 6;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_MM = 7;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_IN = 8;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_PT = 9;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_PC = 10;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_DEG = 11;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_RAD = 12;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_GRAD = 13;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_MS = 14;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_S = 15;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_HZ = 16;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_KHZ = 17;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_DIMENSION = 18;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_STRING = 19;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_URI = 20;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_IDENT = 21;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_ATTR = 22;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_COUNTER = 23;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_RECT = 24;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
+ */
+CSSPrimitiveValue.CSS_RGBCOLOR = 25;
+
+/**
+ * @return {Counter}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-getCounterValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR}
+ */
+CSSPrimitiveValue.prototype.getCounterValue = function() {};
+
+/**
+ * @param {number} unitType
+ * @return {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-getFloatValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR}
+ */
+CSSPrimitiveValue.prototype.getFloatValue = function(unitType) {};
+
+/**
+ * @return {RGBColor}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-getRGBColorValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR}
+ */
+CSSPrimitiveValue.prototype.getRGBColorValue = function() {};
+
+/**
+ * @return {Rect}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-getRectValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR}
+ */
+CSSPrimitiveValue.prototype.getRectValue = function() {};
+
+/**
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-getStringValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR}
+ */
+CSSPrimitiveValue.prototype.getStringValue = function() {};
+
+/**
+ * @param {number} unitType
+ * @param {number} floatValue
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-setFloatValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR},
+ * {@see DomException.NO_MODIFICATION_ALLOWED_ERR}
+ */
+CSSPrimitiveValue.prototype.setFloatValue = function(unitType, floatValue) {};
+
+/**
+ * @param {number} stringType
+ * @param {string} stringValue
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-setStringValue
+ * @throws DOMException {@see DomException.INVALID_ACCESS_ERR},
+ * {@see DomException.NO_MODIFICATION_ALLOWED_ERR}
+ */
+CSSPrimitiveValue.prototype.setStringValue = function(stringType, stringValue) {};
+
+/**
+ * @constructor
+ * @extends {CSSValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValueList
+ */
+function CSSValueList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValueList-length
+ */
+CSSValueList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {CSSValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValueList-item
+ */
+CSSValueList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-RGBColor
+ */
+function RGBColor() {}
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-RGBColor-red
+ */
+RGBColor.prototype.red;
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-RGBColor-green
+ */
+RGBColor.prototype.green;
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-RGBColor-blue
+ */
+RGBColor.prototype.blue;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Rect
+ */
+function Rect() {}
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Rect-top
+ */
+Rect.prototype.top;
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Rect-right
+ */
+Rect.prototype.right;
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Rect-bottom
+ */
+Rect.prototype.bottom;
+
+/**
+ * @type {CSSPrimitiveValue}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Rect-left
+ */
+Rect.prototype.left;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Counter
+ */
+function Counter() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Counter-identifier
+ */
+Counter.prototype.identifier;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Counter-listStyle
+ */
+Counter.prototype.listStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Counter-separator
+ */
+Counter.prototype.separator;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-ViewCSS
+ */
+function ViewCSS() {}
+
+/**
+ * @param {Element} elt
+ * @param {?string=} opt_pseudoElt This argument is required according to the
+ * CSS2 specification, but optional in all major browsers. See the note at
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window.getComputedStyle
+ * @return {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSview-getComputedStyle
+ */
+ViewCSS.prototype.getComputedStyle = function(elt, opt_pseudoElt) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-DocumentCSS
+ */
+function DocumentCSS() {}
+
+/**
+ * @param {Element} elt
+ * @param {string} pseudoElt
+ * @return {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-DocumentCSS-getOverrideStyle
+ */
+DocumentCSS.prototype.getOverrideStyle = function(elt, pseudoElt) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-DOMImplementationCSS
+ */
+function DOMImplementationCSS() {}
+
+/**
+ * @param {string} title
+ * @param {string} media
+ * @return {CSSStyleSheet}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-DOMImplementationCSS-createCSSStyleSheet
+ * @throws DOMException {@see DomException.SYNTAX_ERR}
+ */
+DOMImplementationCSS.prototype.createCSSStyleSheet = function(title, media) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-ElementCSSInlineStyle
+ */
+function ElementCSSInlineStyle() {}
+
+/**
+ * @type {CSSStyleDeclaration}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-ElementCSSInlineStyle-style
+ */
+ElementCSSInlineStyle.prototype.style;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties
+ */
+function CSSProperties() {}
+
+// CSS 2 properties
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-azimuth
+ */
+CSSProperties.prototype.azimuth;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-background
+ */
+CSSProperties.prototype.background;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-backgroundAttachment
+ */
+CSSProperties.prototype.backgroundAttachment;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-backgroundColor
+ */
+CSSProperties.prototype.backgroundColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-backgroundImage
+ */
+CSSProperties.prototype.backgroundImage;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-backgroundPosition
+ */
+CSSProperties.prototype.backgroundPosition;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-backgroundRepeat
+ */
+CSSProperties.prototype.backgroundRepeat;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-background/#the-background-size
+ */
+CSSProperties.prototype.backgroundSize;
+
+/**
+ * @implicitCast
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-border
+ */
+CSSProperties.prototype.border;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderCollapse
+ */
+CSSProperties.prototype.borderCollapse;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderColor
+ */
+CSSProperties.prototype.borderColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderSpacing
+ */
+CSSProperties.prototype.borderSpacing;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue-borderStyle
+ */
+CSSProperties.prototype.borderStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderTop
+ */
+CSSProperties.prototype.borderTop;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderRight
+ */
+CSSProperties.prototype.borderRight;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderBottom
+ */
+CSSProperties.prototype.borderBottom;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderLeft
+ */
+CSSProperties.prototype.borderLeft;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderTopColor
+ */
+CSSProperties.prototype.borderTopColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderRightColor
+ */
+CSSProperties.prototype.borderRightColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderBottomColor
+ */
+CSSProperties.prototype.borderBottomColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderLeftColor
+ */
+CSSProperties.prototype.borderLeftColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderTopStyle
+ */
+CSSProperties.prototype.borderTopStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderRightStyle
+ */
+CSSProperties.prototype.borderRightStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderBottomStyle
+ */
+CSSProperties.prototype.borderBottomStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderLeftStyle
+ */
+CSSProperties.prototype.borderLeftStyle;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderTopWidth
+ */
+CSSProperties.prototype.borderTopWidth;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderRightWidth
+ */
+CSSProperties.prototype.borderRightWidth;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderBottomWidth
+ */
+CSSProperties.prototype.borderBottomWidth;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderLeftWidth
+ */
+CSSProperties.prototype.borderLeftWidth;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-borderWidth
+ */
+CSSProperties.prototype.borderWidth;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-background/#the-border-radius
+ */
+CSSProperties.prototype.borderRadius;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-background/#the-border-radius
+ */
+CSSProperties.prototype.borderBottomLeftRadius;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-background/#the-border-radius
+ */
+CSSProperties.prototype.borderBottomRightRadius;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-background/#the-border-radius
+ */
+CSSProperties.prototype.borderTopLeftRadius;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-background/#the-border-radius
+ */
+CSSProperties.prototype.borderTopRightRadius;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-bottom
+ */
+CSSProperties.prototype.bottom;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-captionSide
+ */
+CSSProperties.prototype.captionSide;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-clear
+ */
+CSSProperties.prototype.clear;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-clip
+ */
+CSSProperties.prototype.clip;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-color
+ */
+CSSProperties.prototype.color;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-content
+ */
+CSSProperties.prototype.content;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-counterIncrement
+ */
+CSSProperties.prototype.counterIncrement;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-counterReset
+ */
+CSSProperties.prototype.counterReset;
+
+/**
+ * This is not an official part of the W3C spec. In practice, this is a settable
+ * property that works cross-browser. It is used in goog.dom.setProperties() and
+ * needs to be extern'd so the --disambiguate_properties JS compiler pass works.
+ * @type {string}
+ */
+CSSProperties.prototype.cssText;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-cue
+ */
+CSSProperties.prototype.cue;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-cueAfter
+ */
+CSSProperties.prototype.cueAfter;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-cueBefore
+ */
+CSSProperties.prototype.cueBefore;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-cursor
+ */
+CSSProperties.prototype.cursor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-direction
+ */
+CSSProperties.prototype.direction;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-display
+ */
+CSSProperties.prototype.display;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-elevation
+ */
+CSSProperties.prototype.elevation;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-emptyCells
+ */
+CSSProperties.prototype.emptyCells;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-cssFloat
+ */
+CSSProperties.prototype.cssFloat;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-font
+ */
+CSSProperties.prototype.font;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontFamily
+ */
+CSSProperties.prototype.fontFamily;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontSize
+ */
+CSSProperties.prototype.fontSize;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontSizeAdjust
+ */
+CSSProperties.prototype.fontSizeAdjust;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontStretch
+ */
+CSSProperties.prototype.fontStretch;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontStyle
+ */
+CSSProperties.prototype.fontStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontVariant
+ */
+CSSProperties.prototype.fontVariant;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-fontWeight
+ */
+CSSProperties.prototype.fontWeight;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-height
+ */
+CSSProperties.prototype.height;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-left
+ */
+CSSProperties.prototype.left;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-letterSpacing
+ */
+CSSProperties.prototype.letterSpacing;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-lineHeight
+ */
+CSSProperties.prototype.lineHeight;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-listStyle
+ */
+CSSProperties.prototype.listStyle;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-listStyleImage
+ */
+CSSProperties.prototype.listStyleImage;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-listStylePosition
+ */
+CSSProperties.prototype.listStylePosition;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-listStyleType
+ */
+CSSProperties.prototype.listStyleType;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-margin
+ */
+CSSProperties.prototype.margin;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-marginTop
+ */
+CSSProperties.prototype.marginTop;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-marginRight
+ */
+CSSProperties.prototype.marginRight;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-marginBottom
+ */
+CSSProperties.prototype.marginBottom;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-marginLeft
+ */
+CSSProperties.prototype.marginLeft;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-markerOffset
+ */
+CSSProperties.prototype.markerOffset;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-marks
+ */
+CSSProperties.prototype.marks;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-maxHeight
+ */
+CSSProperties.prototype.maxHeight;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-maxWidth
+ */
+CSSProperties.prototype.maxWidth;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-minHeight
+ */
+CSSProperties.prototype.minHeight;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-minWidth
+ */
+CSSProperties.prototype.minWidth;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-orphans
+ */
+CSSProperties.prototype.orphans;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-outline
+ */
+CSSProperties.prototype.outline;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-outlineColor
+ */
+CSSProperties.prototype.outlineColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-outlineStyle
+ */
+CSSProperties.prototype.outlineStyle;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-outlineWidth
+ */
+CSSProperties.prototype.outlineWidth;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-overflow
+ */
+CSSProperties.prototype.overflow;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-padding
+ */
+CSSProperties.prototype.padding;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-paddingTop
+ */
+CSSProperties.prototype.paddingTop;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-paddingRight
+ */
+CSSProperties.prototype.paddingRight;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-paddingBottom
+ */
+CSSProperties.prototype.paddingBottom;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-paddingLeft
+ */
+CSSProperties.prototype.paddingLeft;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-page
+ */
+CSSProperties.prototype.page;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pageBreakAfter
+ */
+CSSProperties.prototype.pageBreakAfter;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pageBreakBefore
+ */
+CSSProperties.prototype.pageBreakBefore;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pageBreakInside
+ */
+CSSProperties.prototype.pageBreakInside;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pause
+ */
+CSSProperties.prototype.pause;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pauseAfter
+ */
+CSSProperties.prototype.pauseAfter;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pauseBefore
+ */
+CSSProperties.prototype.pauseBefore;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pitch
+ */
+CSSProperties.prototype.pitch;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-pitchRange
+ */
+CSSProperties.prototype.pitchRange;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-playDuring
+ */
+CSSProperties.prototype.playDuring;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-position
+ */
+CSSProperties.prototype.position;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-quotes
+ */
+CSSProperties.prototype.quotes;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-ui/#resize
+ */
+CSSProperties.prototype.resize;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-richness
+ */
+CSSProperties.prototype.richness;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-right
+ */
+CSSProperties.prototype.right;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-size
+ */
+CSSProperties.prototype.size;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-speak
+ */
+CSSProperties.prototype.speak;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-speakHeader
+ */
+CSSProperties.prototype.speakHeader;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-speakNumeral
+ */
+CSSProperties.prototype.speakNumeral;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-speakPunctuation
+ */
+CSSProperties.prototype.speakPunctuation;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-speechRate
+ */
+CSSProperties.prototype.speechRate;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-stress
+ */
+CSSProperties.prototype.stress;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-tableLayout
+ */
+CSSProperties.prototype.tableLayout;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-textAlign
+ */
+CSSProperties.prototype.textAlign;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-textDecoration
+ */
+CSSProperties.prototype.textDecoration;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-textIndent
+ */
+CSSProperties.prototype.textIndent;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-textShadow
+ */
+CSSProperties.prototype.textShadow;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-textTransform
+ */
+CSSProperties.prototype.textTransform;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-top
+ */
+CSSProperties.prototype.top;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-unicodeBidi
+ */
+CSSProperties.prototype.unicodeBidi;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-verticalAlign
+ */
+CSSProperties.prototype.verticalAlign;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-visibility
+ */
+CSSProperties.prototype.visibility;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-voiceFamily
+ */
+CSSProperties.prototype.voiceFamily;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-volume
+ */
+CSSProperties.prototype.volume;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-whiteSpace
+ */
+CSSProperties.prototype.whiteSpace;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-widows
+ */
+CSSProperties.prototype.widows;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-width
+ */
+CSSProperties.prototype.width;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-wordSpacing
+ */
+CSSProperties.prototype.wordSpacing;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-wordWrap
+ */
+CSSProperties.prototype.wordWrap;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSProperties-zIndex
+ */
+CSSProperties.prototype.zIndex;
+
+// CSS 3 properties
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-background/#box-shadow
+ */
+CSSProperties.prototype.boxShadow;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-ui/#box-sizing
+ */
+CSSProperties.prototype.boxSizing;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-color/#transparency
+ */
+CSSProperties.prototype.opacity;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-ui/#text-overflow
+ */
+CSSProperties.prototype.textOverflow;
+
+// CSS 3 transforms
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-2d-transforms/#backface-visibility-property
+ */
+CSSProperties.prototype.backfaceVisibility;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-2d-transforms/#perspective
+ */
+CSSProperties.prototype.perspective;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-2d-transforms/#perspective-origin
+ */
+CSSProperties.prototype.perspectiveOrigin;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-2d-transforms/#effects
+ */
+CSSProperties.prototype.transform;
+
+/**
+ * @type {string|number}
+ * @see http://www.w3.org/TR/css3-2d-transforms/#transform-origin
+ */
+CSSProperties.prototype.transformOrigin;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-2d-transforms/#transform-style
+ */
+CSSProperties.prototype.transformStyle;
+
+// CSS 3 transitions
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-transitions/#transition
+ */
+CSSProperties.prototype.transition;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-transitions/#transition-delay
+ */
+CSSProperties.prototype.transitionDelay;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-transitions/#transition-duration
+ */
+CSSProperties.prototype.transitionDuration;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-transitions/#transition-property-property
+ */
+CSSProperties.prototype.transitionProperty;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/css3-transitions/#transition-timing-function
+ */
+CSSProperties.prototype.transitionTimingFunction;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty
+ */
+CSSProperties.prototype.pointerEvents;
+
+/**
+ * TODO(dbeam): Put this in separate file named w3c_cssom.js.
+ * Externs for the CSSOM View Module.
+ * @see http://www.w3.org/TR/cssom-view/
+ */
+
+// http://www.w3.org/TR/cssom-view/#extensions-to-the-window-interface
+
+/**
+ * @param {string} media_query_list
+ * @return {MediaQueryList}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-matchmedia
+ */
+Window.prototype.matchMedia = function(media_query_list) {};
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-innerwidth
+ */
+Window.prototype.innerWidth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-innerheight
+ */
+Window.prototype.innerHeight;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-scrollx
+ */
+Window.prototype.scrollX;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-pagexoffset
+ */
+Window.prototype.pageXOffset;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-scrolly
+ */
+Window.prototype.scrollY;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-pageyoffset
+ */
+Window.prototype.pageYOffset;
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-scroll
+ */
+Window.prototype.scroll = function(x, y) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-scrollto
+ */
+Window.prototype.scrollTo = function(x, y) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-scrollby
+ */
+Window.prototype.scrollBy = function(x, y) {};
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-screenx
+ */
+Window.prototype.screenX;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-screeny
+ */
+Window.prototype.screenY;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-outerwidth
+ */
+Window.prototype.outerWidth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-window-outerheight
+ */
+Window.prototype.outerHeight;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/cssom-view/#mediaquerylist
+ */
+function MediaQueryList() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mediaquerylist-media
+ */
+MediaQueryList.prototype.media;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mediaquerylist-matches
+ */
+MediaQueryList.prototype.matches;
+
+/**
+ * @param {MediaQueryListListener} listener
+ * @see http://www.w3.org/TR/cssom-view/#dom-mediaquerylist-addlistener
+ */
+MediaQueryList.prototype.addListener = function(listener) {};
+
+/**
+ * @param {MediaQueryListListener} listener
+ * @see http://www.w3.org/TR/cssom-view/#dom-mediaquerylist-removelistener
+ */
+MediaQueryList.prototype.removeListener = function(listener) {};
+
+/**
+ * @typedef {(function(!MediaQueryList) : void)}
+ * @see http://www.w3.org/TR/cssom-view/#mediaquerylistlistener
+ */
+var MediaQueryListListener;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/cssom-view/#screen
+ */
+function Screen() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-screen-availwidth
+ */
+Screen.prototype.availWidth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-screen-availheight
+ */
+Screen.prototype.availHeight;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-screen-width
+ */
+Screen.prototype.width;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-screen-height
+ */
+Screen.prototype.height;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-screen-colordepth
+ */
+Screen.prototype.colorDepth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-screen-pixeldepth
+ */
+Screen.prototype.pixelDepth;
+
+
+// http://www.w3.org/TR/cssom-view/#extensions-to-the-document-interface
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {?Element}
+ * @see http://www.w3.org/TR/cssom-view/#dom-document-elementfrompoint
+ */
+Document.prototype.elementFromPoint = function(x, y) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {CaretPosition}
+ * @see http://www.w3.org/TR/cssom-view/#dom-document-caretpositionfrompoint
+ */
+Document.prototype.caretPositionFromPoint = function(x, y) {};
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/cssom-view/#caretposition
+ */
+function CaretPosition() {}
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/cssom-view/#dom-caretposition-offsetnode
+ */
+CaretPosition.prototype.offsetNode;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-caretposition-offset
+ */
+CaretPosition.prototype.offset;
+
+
+// http://www.w3.org/TR/cssom-view/#extensions-to-the-element-interface
+
+/**
+ * @return {!ClientRectList}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-getclientrects
+ */
+Element.prototype.getClientRects = function() {};
+
+/**
+ * @return {!ClientRect}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-getboundingclientrect
+ */
+Element.prototype.getBoundingClientRect = function() {};
+
+/**
+ * @param {boolean=} opt_top
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-scrollintoview
+ */
+Element.prototype.scrollIntoView = function(opt_top) {};
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-scrolltop
+ */
+Element.prototype.scrollTop;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-scrollleft
+ */
+Element.prototype.scrollLeft;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-scrollwidth
+ */
+Element.prototype.scrollWidth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-scrollheight
+ */
+Element.prototype.scrollHeight;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-clienttop
+ */
+Element.prototype.clientTop;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-clientleft
+ */
+Element.prototype.clientLeft;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-clientwidth
+ */
+Element.prototype.clientWidth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-clientheight
+ */
+Element.prototype.clientHeight;
+
+// http://www.w3.org/TR/cssom-view/#extensions-to-the-htmlelement-interface
+
+/**
+ * @type {Element}
+ * @see http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsetparent
+ */
+HTMLElement.prototype.offsetParent;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsettop
+ */
+HTMLElement.prototype.offsetTop;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsetleft
+ */
+HTMLElement.prototype.offsetLeft;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsetwidth
+ */
+HTMLElement.prototype.offsetWidth;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsetheight
+ */
+HTMLElement.prototype.offsetHeight;
+
+
+// http://www.w3.org/TR/cssom-view/#extensions-to-the-range-interface
+
+/**
+ * @return {!ClientRectList}
+ * @see http://www.w3.org/TR/cssom-view/#dom-range-getclientrects
+ */
+Range.prototype.getClientRects = function() {};
+
+/**
+ * @return {!ClientRect}
+ * @see http://www.w3.org/TR/cssom-view/#dom-range-getboundingclientrect
+ */
+Range.prototype.getBoundingClientRect = function() {};
+
+
+// http://www.w3.org/TR/cssom-view/#extensions-to-the-mouseevent-interface
+
+// MouseEvent: screen{X,Y} and client{X,Y} are in DOM Level 2/3 Event as well,
+// so it seems like a specification issue. I've emailed www-style@w3.org in
+// hopes of resolving the conflict, but in the mean time they can live here
+// (http://lists.w3.org/Archives/Public/www-style/2012May/0039.html).
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-screenx
+ */
+//MouseEvent.prototype.screenX;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-screeny
+ */
+//MouseEvent.prototype.screenY;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-pagex
+ */
+MouseEvent.prototype.pageX;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-pagey
+ */
+MouseEvent.prototype.pageY;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-clientx
+ */
+//MouseEvent.prototype.clientX;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-clienty
+ */
+//MouseEvent.prototype.clientY;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-x
+ */
+MouseEvent.prototype.x;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-y
+ */
+MouseEvent.prototype.y;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-offsetx
+ */
+MouseEvent.prototype.offsetX;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-mouseevent-offsety
+ */
+MouseEvent.prototype.offsetY;
+
+
+// http://www.w3.org/TR/cssom-view/#rectangles
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/cssom-view/#the-clientrectlist-interface
+ */
+function ClientRectList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrectlist-length
+ */
+ClientRectList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {ClientRect}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrectlist-item
+ */
+ClientRectList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/cssom-view/#the-clientrect-interface
+ */
+function ClientRect() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrect-top
+ */
+ClientRect.prototype.top;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrect-right
+ */
+ClientRect.prototype.right;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrect-bottom
+ */
+ClientRect.prototype.bottom;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrect-left
+ */
+ClientRect.prototype.left;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrect-width
+ */
+ClientRect.prototype.width;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-clientrect-height
+ */
+ClientRect.prototype.height;
+
+/**
+ * @constructor
+ * http://www.w3.org/TR/css3-conditional/#CSS-interface
+ */
+function CSSInterface() {}
+
+/**
+ * @param {string} property
+ * @param {string=} opt_value
+ * @return {boolean}
+ */
+CSSInterface.prototype.supports = function(property, opt_value) {};
+
+/**
+ * TODO(nicksantos): This suppress tag probably isn't needed, and
+ * should be removed.
+ * @suppress {duplicate}
+ * @type {CSSInterface}
+ */
+var CSS;
+
+/** @type {CSSInterface} */
+Window.prototype.CSS;
+
+// http://dev.w3.org/csswg/css-font-loading/
+
+/**
+ * @enum {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#enumdef-fontfaceloadstatus
+ */
+var FontFaceLoadStatus = {
+ ERROR: 'error',
+ LOADED: 'loaded',
+ LOADING: 'loading',
+ UNLOADED: 'unloaded'
+};
+
+/**
+ * @typedef {{
+ * style: (string|undefined),
+ * weight: (string|undefined),
+ * stretch: (string|undefined),
+ * unicodeRange: (string|undefined),
+ * variant: (string|undefined),
+ * featureSettings: (string|undefined)
+ * }}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dictdef-fontfacedescriptors
+ */
+var FontFaceDescriptors;
+
+/**
+ * @constructor
+ * @param {string} fontFamily
+ * @param {string} source
+ * @param {!FontFaceDescriptors} descriptors
+ * @see http://dev.w3.org/csswg/css-font-loading/#font-face-constructor
+ */
+function FontFace(fontFamily, source, descriptors) {}
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-family
+ */
+FontFace.prototype.family;
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-style
+ */
+FontFace.prototype.style;
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-weight
+ */
+FontFace.prototype.weight;
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-stretch
+ */
+FontFace.prototype.stretch;
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-unicoderange
+ */
+FontFace.prototype.unicodeRange;
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-variant
+ */
+FontFace.prototype.variant;
+
+/**
+ * @type {string}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-featuresettings
+ */
+FontFace.prototype.featureSettings;
+
+/**
+ * @type {FontFaceLoadStatus}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontface-status
+ */
+FontFace.prototype.status;
+
+/**
+ * @return {!Promise.<!FontFace>}
+ * @see http://dev.w3.org/csswg/css-font-loading/#font-face-load
+ */
+FontFace.prototype.load = function() {};
+
+/**
+ * @enum
+ * @see http://dev.w3.org/csswg/css-font-loading/#enumdef-fontfacesetloadstatus
+ */
+var FontFaceSetLoadStatus = {
+ LOADED: 'loaded',
+ LOADING: 'loading'
+};
+
+/**
+ * @interface
+ * @see http://dev.w3.org/csswg/css-font-loading/#FontFaceSet-interface
+ */
+function FontFaceSet() {}
+
+// Event handlers
+// http://dev.w3.org/csswg/css-font-loading/#FontFaceSet-events
+
+/** @type {?function (Event)} */ FontFaceSet.prototype.onloading;
+/** @type {?function (Event)} */ FontFaceSet.prototype.onloadingdone;
+/** @type {?function (Event)} */ FontFaceSet.prototype.onloadingerror;
+
+/**
+ * @param {!FontFace} value
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-add
+ */
+FontFaceSet.prototype.add = function(value) {};
+
+/**
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-clear
+ */
+FontFaceSet.prototype.clear = function() {};
+
+/**
+ * @param {!FontFace} value
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-delete
+ */
+FontFaceSet.prototype.delete = function(value) {};
+
+/**
+ * @param {!FontFace} font
+ * @return {boolean}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-has
+ */
+FontFaceSet.prototype.has = function(font) {};
+
+/**
+ * @param {function(!FontFace, number, !FontFaceSet)} cb
+ * @param {Object|undefined=} opt_selfObj
+ * see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-foreach
+ */
+FontFaceSet.prototype.forEach = function(cb, opt_selfObj) {};
+
+/**
+ * @param {string} font
+ * @param {string=} opt_text
+ * @return {!Promise.<!Array.<!FontFace>>}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-load
+ */
+FontFaceSet.prototype.load = function(font, opt_text) {};
+
+/**
+ * @param {string} font
+ * @param {string=} opt_text
+ * @return {boolean}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-check
+ */
+FontFaceSet.prototype.check = function(font, opt_text) {};
+
+/**
+ * @type {!Promise.<!FontFaceSet>}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-ready
+ */
+FontFaceSet.prototype.ready;
+
+/**
+ * @type {FontFaceSetLoadStatus}
+ * @see http://dev.w3.org/csswg/css-font-loading/#dom-fontfaceset-status
+ */
+FontFaceSet.prototype.status;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css3d.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css3d.js
new file mode 100644
index 0000000000..1c3d64c93a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_css3d.js
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's CSS 3D Transforms specification.
+ * The whole file has been fully type annotated. Created from
+ * https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html
+ *
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @param {string=} opt_matrix
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#the-cssmatrix-interface
+ */
+function CSSMatrix(opt_matrix) {}
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m11;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m12;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m13;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m14;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m21;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m22;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m23;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m24;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m31;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m32;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m33;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m34;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m41;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m42;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m43;
+
+/**
+ * @type {number}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#three-dimensional-attributes
+ */
+CSSMatrix.prototype.m44;
+
+/**
+ * @param {string} string
+ * @return {void}
+ */
+CSSMatrix.prototype.setMatrixValue = function(string) {};
+
+/**
+ * @param {!CSSMatrix} secondMatrix
+ * @return {!CSSMatrix}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#widl-CSSMatrix-multiply-CSSMatrix-CSSMatrix-other
+ */
+CSSMatrix.prototype.multiply = function(secondMatrix) {};
+
+/**
+ * @return {CSSMatrix} Returns void if the matrix is non-invertable.
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#widl-CSSMatrix-inverse-CSSMatrix
+ */
+CSSMatrix.prototype.inverse = function() {};
+
+/**
+ * @param {number=} opt_x Defaults to 0.
+ * @param {number=} opt_y Defaults to 0.
+ * @param {number=} opt_z Defaults to 0.
+ * @return {!CSSMatrix}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#widl-CSSMatrix-translate-CSSMatrix-unrestricted-double-tx-unrestricted-double-ty-unrestricted-double-tz
+ */
+CSSMatrix.prototype.translate = function(opt_x, opt_y, opt_z) {};
+
+/**
+ * @param {number=} opt_scaleX Defaults to 1.
+ * @param {number=} opt_scaleY Defaults to scaleX.
+ * @param {number=} opt_scaleZ Defaults to 1.
+ * @return {!CSSMatrix}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#widl-CSSMatrix-scale-CSSMatrix-unrestricted-double-scale-unrestricted-double-originX-unrestricted-double-originY
+ */
+CSSMatrix.prototype.scale = function(opt_scaleX, opt_scaleY, opt_scaleZ) {};
+
+/**
+ * @param {number=} opt_rotX Defaults to 0.
+ * @param {number=} opt_rotY Defaults to 0.
+ * @param {number=} opt_rotZ Defaults to rotX if rotY is not defined, else 0.
+ * @return {!CSSMatrix}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#widl-CSSMatrix-rotate-CSSMatrix-unrestricted-double-angle-unrestricted-double-originX-unrestricted-double-originY
+ */
+CSSMatrix.prototype.rotate = function(opt_rotX, opt_rotY, opt_rotZ) {};
+
+/**
+ * @param {number=} opt_x Defaults to 0.
+ * @param {number=} opt_y Defaults to 0.
+ * @param {number=} opt_z Defaults to 0.
+ * @param {number=} opt_angle Defaults to 0.
+ * @return {!CSSMatrix}
+ * @see https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html#widl-CSSMatrix-rotateAxisAngle-CSSMatrix-unrestricted-double-x-unrestricted-double-y-unrestricted-double-z-unrestricted-double-angle
+ */
+CSSMatrix.prototype.rotateAxisAngle =
+ function(opt_x, opt_y, opt_z, opt_angle) {};
+
+/**
+ * @constructor
+ * @param {string=} opt_matrix
+ * @extends {CSSMatrix}
+ * @see http://developer.apple.com/safari/library/documentation/AudioVideo/Reference/WebKitCSSMatrixClassReference/WebKitCSSMatrix/WebKitCSSMatrix.html#//apple_ref/javascript/instm/WebKitCSSMatrix/setMatrixValue
+ */
+function WebKitCSSMatrix(opt_matrix) {}
+
+/**
+ * @constructor
+ * @param {string=} opt_matrix
+ * @extends {CSSMatrix}
+ * @see http://msdn.microsoft.com/en-us/library/windows/apps/hh453593.aspx
+ */
+function MSCSSMatrix(opt_matrix) {}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_device_sensor_event.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_device_sensor_event.js
new file mode 100644
index 0000000000..de36ea3244
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_device_sensor_event.js
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2013 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's device orientation and device motion
+ * events specification.
+ * This file depends on w3c_event.js.
+ * The whole file has been partially type annotated.
+ * Created from http://dev.w3.org/geo/api/spec-source-orientation.
+ *
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @extends {Event}
+ */
+function DeviceOrientationEvent() {}
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.alpha;
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.beta;
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.gamma;
+
+/** @type {boolean} */
+DeviceOrientationEvent.prototype.absolute;
+
+/**
+ * @type {?number}
+ * @see https://developer.apple.com/library/safari/documentation/SafariDOMAdditions/Reference/DeviceOrientationEventClassRef/DeviceOrientationEvent/DeviceOrientationEvent.html#//apple_ref/javascript/instp/DeviceOrientationEvent/webkitCompassAccuracy
+ */
+DeviceOrientationEvent.prototype.webkitCompassAccuracy;
+
+/**
+ * @type {?number}
+ * @see https://developer.apple.com/library/safari/documentation/SafariDOMAdditions/Reference/DeviceOrientationEventClassRef/DeviceOrientationEvent/DeviceOrientationEvent.html#//apple_ref/javascript/instp/DeviceOrientationEvent/webkitCompassHeading
+ */
+DeviceOrientationEvent.prototype.webkitCompassHeading;
+
+/**
+ * @constructor
+ */
+function DeviceAcceleration() {}
+
+/** @type {?number} */
+DeviceAcceleration.prototype.x;
+
+/** @type {?number} */
+DeviceAcceleration.prototype.y;
+
+/** @type {?number} */
+DeviceAcceleration.prototype.z;
+
+/**
+ * @constructor
+ */
+function DeviceRotationRate() {}
+
+/** @type {?number} */
+DeviceRotationRate.prototype.alpha;
+
+/** @type {?number} */
+DeviceRotationRate.prototype.beta;
+
+/** @type {?number} */
+DeviceRotationRate.prototype.gamma;
+
+/**
+ * @constructor
+ * @extends {Event}
+ */
+function DeviceMotionEvent() {}
+
+/** @type {?DeviceAcceleration} */
+DeviceMotionEvent.prototype.acceleration;
+
+/** @type {?DeviceAcceleration} */
+DeviceMotionEvent.prototype.accelerationIncludingGravity;
+
+/** @type {?DeviceRotationRate} */
+DeviceMotionEvent.prototype.rotationRate;
+
+/** @type {?number} */
+DeviceMotionEvent.prototype.interval;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom1.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom1.js
new file mode 100644
index 0000000000..d00f73fd4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom1.js
@@ -0,0 +1,874 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's DOM Level 1 specification.
+ * The whole file has been fully type annotated. Created from
+ * http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-17189187
+ */
+function DOMException() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.INDEX_SIZE_ERR = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.DOMSTRING_SIZE_ERR = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.HIERARCHY_REQUEST_ERR = 3;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.WRONG_DOCUMENT_ERR = 4;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.INVALID_CHARACTER_ERR = 5;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.NO_DATA_ALLOWED_ERR = 6;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.NO_MODIFICATION_ALLOWED_ERR = 7;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.NOT_FOUND_ERR = 8;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.NOT_SUPPORTED_ERR = 9;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+DOMException.INUSE_ATTRIBUTE_ERR = 10;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-258A00AF
+ */
+function ExceptionCode() {}
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-102161490
+ */
+function DOMImplementation() {}
+
+/**
+ * @param {string} feature
+ * @param {string} version
+ * @return {boolean}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-5CED94D7
+ * @nosideeffects
+ */
+DOMImplementation.prototype.hasFeature = function(feature, version) {};
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+function Node() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Node.prototype.addEventListener = function(type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Node.prototype.removeEventListener = function(type, listener, opt_useCapture) {};
+
+/** @override */
+Node.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @type {NamedNodeMap}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-attributes
+ */
+Node.prototype.attributes;
+
+/**
+ * @type {!NodeList}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-childNodes
+ */
+Node.prototype.childNodes;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-firstChild
+ */
+Node.prototype.firstChild;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-lastChild
+ */
+Node.prototype.lastChild;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-nextSibling
+ */
+Node.prototype.nextSibling;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-nodeName
+ */
+Node.prototype.nodeName;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-nodeValue
+ */
+Node.prototype.nodeValue;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-nodeType
+ */
+Node.prototype.nodeType;
+
+/**
+ * @type {Document}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-ownerDocument
+ */
+Node.prototype.ownerDocument;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-parentNode
+ */
+Node.prototype.parentNode;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-previousSibling
+ */
+Node.prototype.previousSibling;
+
+/**
+ * @param {Node} newChild
+ * @return {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-appendChild
+ */
+Node.prototype.appendChild = function(newChild) {};
+
+/**
+ * @param {boolean} deep
+ * @return {!Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-cloneNode
+ * @nosideeffects
+ */
+Node.prototype.cloneNode = function(deep) {};
+
+/**
+ * @return {boolean}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-hasChildNodes
+ * @nosideeffects
+ */
+Node.prototype.hasChildNodes = function() {};
+
+/**
+ * @param {Node} newChild
+ * @param {Node} refChild
+ * @return {!Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-insertBefore
+ */
+Node.prototype.insertBefore = function(newChild, refChild) {};
+
+/**
+ * @param {Node} oldChild
+ * @return {!Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-removeChild
+ */
+Node.prototype.removeChild = function(oldChild) {};
+
+/**
+ * @param {Node} newChild
+ * @param {Node} oldChild
+ * @return {!Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-replaceChild
+ */
+Node.prototype.replaceChild = function(newChild, oldChild) {};
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.ATTRIBUTE_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.CDATA_SECTION_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.COMMENT_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.DOCUMENT_FRAGMENT_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.DOCUMENT_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.DOCUMENT_TYPE_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.ELEMENT_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.ENTITY_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.ENTITY_REFERENCE_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.PROCESSING_INSTRUCTION_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.TEXT_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.XPATH_NAMESPACE_NODE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+Node.NOTATION_NODE;
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-B63ED1A3
+ */
+function DocumentFragment() {}
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#i-Document
+ */
+function Document() {}
+
+/**
+ * @type {DocumentType}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-doctype
+ */
+Document.prototype.doctype;
+
+/**
+ * @type {!Element}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-documentElement
+ */
+Document.prototype.documentElement;
+
+/**
+ * @type {DOMImplementation}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-implementation
+ */
+Document.prototype.implementation;
+
+/**
+ * @param {string} name
+ * @return {!Attr}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createAttribute
+ * @nosideeffects
+ */
+Document.prototype.createAttribute = function(name) {};
+
+/**
+ * @param {string} data
+ * @return {!Comment}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createComment
+ * @nosideeffects
+ */
+Document.prototype.createComment = function(data) {};
+
+/**
+ * @param {string} data
+ * @return {!CDATASection}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createCDATASection
+ * @nosideeffects
+ */
+Document.prototype.createCDATASection = function(data) {};
+
+/**
+ * @return {!DocumentFragment}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createDocumentFragment
+ * @nosideeffects
+ */
+Document.prototype.createDocumentFragment = function() {};
+
+/**
+ * Create a DOM element.
+ *
+ * Web components introduced the second parameter as a way of extending existing
+ * tags (e.g. document.createElement('button', 'fancy-button')).
+ *
+ * @param {string} tagName
+ * @param {string=} opt_typeExtension
+ * @return {!Element}
+ * @nosideeffects
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createElement
+ * @see http://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-instantiate
+ */
+Document.prototype.createElement = function(tagName, opt_typeExtension) {};
+
+/**
+ * @param {string} name
+ * @return {!EntityReference}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createEntityReference
+ * @nosideeffects
+ */
+Document.prototype.createEntityReference = function(name) {};
+
+/**
+ * @param {string} target
+ * @param {string} data
+ * @return {!ProcessingInstruction}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createProcessingInstruction
+ * @nosideeffects
+ */
+Document.prototype.createProcessingInstruction = function(target, data) {};
+
+/**
+ * @param {number|string} data
+ * @return {!Text}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-createTextNode
+ * @nosideeffects
+ */
+Document.prototype.createTextNode = function(data) {};
+
+/**
+ * @param {string} tagname
+ * @return {!NodeList}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-A6C9094
+ * @nosideeffects
+ */
+Document.prototype.getElementsByTagName = function(tagname) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-536297177
+ */
+function NodeList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-203510337
+ */
+NodeList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-844377136
+ */
+NodeList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1780488922
+ */
+function NamedNodeMap() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-6D0FB19E
+ */
+NamedNodeMap.prototype.length;
+
+/**
+ * @param {string} name
+ * @return {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1074577549
+ * @nosideeffects
+ */
+NamedNodeMap.prototype.getNamedItem = function(name) {};
+
+/**
+ * @param {number} index
+ * @return {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-349467F9
+ * @nosideeffects
+ */
+NamedNodeMap.prototype.item = function(index) {};
+
+/**
+ * @param {string} name
+ * @return {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-D58B193
+ */
+NamedNodeMap.prototype.removeNamedItem = function(name) {};
+
+/**
+ * @param {Node} arg
+ * @return {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1025163788
+ */
+NamedNodeMap.prototype.setNamedItem = function(arg) {};
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-FF21A306
+ */
+function CharacterData() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-72AB8359
+ */
+CharacterData.prototype.data;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-7D61178C
+ */
+CharacterData.prototype.length;
+
+/**
+ * @param {string} arg
+ * @return {undefined}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-32791A2F
+ */
+CharacterData.prototype.appendData = function(arg) {};
+
+/**
+ * @param {number} offset
+ * @param {number} count
+ * @return {undefined}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-7C603781
+ */
+CharacterData.prototype.deleteData = function(offset, count) {};
+
+/**
+ * @param {number} offset
+ * @param {string} arg
+ * @return {undefined}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-3EDB695F
+ */
+CharacterData.prototype.insertData = function(offset, arg) {};
+
+/**
+ * @param {number} offset
+ * @param {number} count
+ * @param {string} arg
+ * @return {undefined}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-E5CBA7FB
+ */
+CharacterData.prototype.replaceData = function(offset, count, arg) {};
+
+/**
+ * @param {number} offset
+ * @param {number} count
+ * @return {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-6531BCCF
+ * @nosideeffects
+ */
+CharacterData.prototype.substringData = function(offset, count) {};
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-637646024
+ */
+function Attr() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1112119403
+ */
+Attr.prototype.name;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-862529273
+ */
+Attr.prototype.specified;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-221662474
+ */
+Attr.prototype.value;
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-745549614
+ */
+function Element() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#attribute-tagName
+ */
+Element.prototype.tagName;
+
+/**
+ * @param {string} name
+ * @param {number?=} opt_flags
+ * @return {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-getAttribute
+ * @see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
+ * @nosideeffects
+ */
+Element.prototype.getAttribute = function(name, opt_flags) {};
+
+/**
+ * @param {string} name
+ * @return {Attr}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-getAttributeNode
+ * @nosideeffects
+ */
+Element.prototype.getAttributeNode = function(name) {};
+
+/**
+ * @param {string} tagname
+ * @return {!NodeList}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1938918D
+ * @nosideeffects
+ */
+Element.prototype.getElementsByTagName = function(tagname) {};
+
+/**
+ * @param {string} name
+ * @return {undefined}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-removeAttribute
+ */
+Element.prototype.removeAttribute = function(name) {};
+
+/**
+ * @param {Attr} oldAttr
+ * @return {?Attr}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-removeAttributeNode
+ */
+Element.prototype.removeAttributeNode = function(oldAttr) {};
+
+/**
+ * @param {string} name
+ * @param {string|number|boolean} value Values are converted to strings with
+ * ToString, so we accept number and boolean since both convert easily to
+ * strings.
+ * @return {undefined}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-setAttribute
+ */
+Element.prototype.setAttribute = function(name, value) {};
+
+/**
+ * @param {Attr} newAttr
+ * @return {?Attr}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#method-setAttributeNode
+ */
+Element.prototype.setAttributeNode = function(newAttr) {};
+
+// Event handlers
+// The DOM level 3 spec has a good index of these
+// http://www.w3.org/TR/DOM-Level-3-Events/#event-types
+
+/** @type {?function (Event)} */ Element.prototype.onabort;
+/** @type {?function (Event)} */ Element.prototype.onbeforeinput;
+/** @type {?function (Event)} */ Element.prototype.onbeforeunload;
+/** @type {?function (Event)} */ Element.prototype.onblur;
+/** @type {?function (Event)} */ Element.prototype.onchange;
+/** @type {?function (Event)} */ Element.prototype.onclick;
+/** @type {?function (Event)} */ Element.prototype.oncompositionstart;
+/** @type {?function (Event)} */ Element.prototype.oncompositionupdate;
+/** @type {?function (Event)} */ Element.prototype.oncompositionend;
+/** @type {?function (Event)} */ Element.prototype.oncontextmenu;
+/** @type {?function (Event)} */ Element.prototype.oncopy;
+/** @type {?function (Event)} */ Element.prototype.oncut;
+/** @type {?function (Event)} */ Element.prototype.ondblclick;
+/** @type {?function (Event)} */ Element.prototype.onerror;
+/** @type {?function (Event)} */ Element.prototype.onfocus;
+/** @type {?function (Event)} */ Element.prototype.onfocusin;
+/** @type {?function (Event)} */ Element.prototype.onfocusout;
+/** @type {?function (Event)} */ Element.prototype.oninput;
+/** @type {?function (Event)} */ Element.prototype.onkeydown;
+/** @type {?function (Event)} */ Element.prototype.onkeypress;
+/** @type {?function (Event)} */ Element.prototype.onkeyup;
+/** @type {?function (Event)} */ Element.prototype.onload;
+/** @type {?function (Event)} */ Element.prototype.onunload;
+/** @type {?function (Event)} */ Element.prototype.onmousedown;
+/** @type {?function (Event)} */ Element.prototype.onmousemove;
+/** @type {?function (Event)} */ Element.prototype.onmouseout;
+/** @type {?function (Event)} */ Element.prototype.onmouseover;
+/** @type {?function (Event)} */ Element.prototype.onmouseup;
+/** @type {?function (Event)} */ Element.prototype.onmousewheel;
+/** @type {?function (Event)} */ Element.prototype.onpaste;
+/** @type {?function (Event)} */ Element.prototype.onreset;
+/** @type {?function (Event)} */ Element.prototype.onresize;
+/** @type {?function (Event)} */ Element.prototype.onscroll;
+/** @type {?function (Event)} */ Element.prototype.onselect;
+/** @type {?function (Event=)} */ Element.prototype.onsubmit;
+/** @type {?function (Event)} */ Element.prototype.ontextinput;
+/** @type {?function (Event)} */ Element.prototype.onwheel;
+
+/**
+ * @constructor
+ * @extends {CharacterData}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1312295772
+ */
+function Text() {}
+
+/**
+ * @param {number} offset
+ * @return {Text}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-38853C1D
+ */
+Text.prototype.splitText = function(offset) {};
+
+/**
+ * @constructor
+ * @extends {CharacterData}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1728279322
+ */
+function Comment() {}
+
+/**
+ * @constructor
+ * @extends {Text}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-667469212
+ */
+function CDATASection() {}
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-412266927
+ */
+function DocumentType() {}
+
+/**
+ * @type {NamedNodeMap}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1788794630
+ */
+DocumentType.prototype.entities;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1844763134
+ */
+DocumentType.prototype.name;
+
+/**
+ * @type {NamedNodeMap}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-D46829EF
+ */
+DocumentType.prototype.notations;
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-5431D1B9
+ */
+function Notation() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-54F2B4D0
+ */
+Notation.prototype.publicId;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-E8AAB1D0
+ */
+Notation.prototype.systemId;
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-527DCFF2
+ */
+function Entity() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-D7303025
+ */
+Entity.prototype.publicId;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-D7C29F3E
+ */
+Entity.prototype.systemId;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-6ABAEB38
+ */
+Entity.prototype.notationName;
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-11C98490
+ */
+function EntityReference() {}
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1004215813
+ */
+function ProcessingInstruction() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-837822393
+ */
+ProcessingInstruction.prototype.data;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1478689192
+ */
+ProcessingInstruction.prototype.target;
+
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ */
+function Window() {}
+Window.prototype.Window;
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Window.prototype.addEventListener = function(type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Window.prototype.removeEventListener = function(type, listener, opt_useCapture)
+ {};
+
+/** @override */
+Window.prototype.dispatchEvent = function(evt) {};
+
+/** @type {?function (Event)} */ Window.prototype.onabort;
+/** @type {?function (Event)} */ Window.prototype.onbeforeunload;
+/** @type {?function (Event)} */ Window.prototype.onblur;
+/** @type {?function (Event)} */ Window.prototype.onchange;
+/** @type {?function (Event)} */ Window.prototype.onclick;
+/** @type {?function (Event)} */ Window.prototype.onclose;
+/** @type {?function (Event)} */ Window.prototype.oncontextmenu;
+/** @type {?function (Event)} */ Window.prototype.ondblclick;
+/** @type {?function (Event)} */ Window.prototype.ondragdrop;
+// onerror has a special signature.
+// See https://developer.mozilla.org/en/DOM/window.onerror
+// and http://msdn.microsoft.com/en-us/library/cc197053(VS.85).aspx
+/** @type {?function (string, string, number)} */
+Window.prototype.onerror;
+/** @type {?function (Event)} */ Window.prototype.onfocus;
+/** @type {?function (Event)} */ Window.prototype.onhashchange;
+/** @type {?function (Event)} */ Window.prototype.onkeydown;
+/** @type {?function (Event)} */ Window.prototype.onkeypress;
+/** @type {?function (Event)} */ Window.prototype.onkeyup;
+/** @type {?function (Event)} */ Window.prototype.onload;
+/** @type {?function (Event)} */ Window.prototype.onmousedown;
+/** @type {?function (Event)} */ Window.prototype.onmousemove;
+/** @type {?function (Event)} */ Window.prototype.onmouseout;
+/** @type {?function (Event)} */ Window.prototype.onmouseover;
+/** @type {?function (Event)} */ Window.prototype.onmouseup;
+/** @type {?function (Event)} */ Window.prototype.onmousewheel;
+/** @type {?function (Event)} */ Window.prototype.onpaint;
+/** @type {?function (Event)} */ Window.prototype.onpopstate;
+/** @type {?function (Event)} */ Window.prototype.onreset;
+/** @type {?function (Event)} */ Window.prototype.onresize;
+/** @type {?function (Event)} */ Window.prototype.onscroll;
+/** @type {?function (Event)} */ Window.prototype.onselect;
+/** @type {?function (Event=)} */ Window.prototype.onsubmit;
+/** @type {?function (Event)} */ Window.prototype.onunload;
+/** @type {?function (Event)} */ Window.prototype.onwheel;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom2.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom2.js
new file mode 100644
index 0000000000..d6642074cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom2.js
@@ -0,0 +1,2619 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's DOM Level 2 specification.
+ * This file depends on w3c_dom1.js.
+ * The whole file has been fully type annotated.
+ * Created from
+ * http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+// All the provided definitions have been type annotated.
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75708506
+ */
+function HTMLCollection() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40057551
+ */
+HTMLCollection.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {Node}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-33262535
+ * @nosideeffects
+ */
+HTMLCollection.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-HTML/html.html#HTMLOptionsCollection
+ */
+function HTMLOptionsCollection() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-HTML/html.html#HTMLOptionsCollection-length
+ */
+HTMLOptionsCollection.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {Node}
+ * @see http://www.w3.org/TR/DOM-Level-2-HTML/html.html#HTMLOptionsCollection-item
+ * @nosideeffects
+ */
+HTMLOptionsCollection.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @extends {Document}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-26809268
+ */
+function HTMLDocument() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-18446827
+ */
+HTMLDocument.prototype.title;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-95229140
+ */
+HTMLDocument.prototype.referrer;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-2250147
+ */
+HTMLDocument.prototype.domain;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-46183437
+ */
+HTMLDocument.prototype.URL;
+
+/**
+ * @type {HTMLBodyElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-56360201
+ */
+HTMLDocument.prototype.body;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-90379117
+ */
+HTMLDocument.prototype.images;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-85113862
+ */
+HTMLDocument.prototype.applets;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-7068919
+ */
+HTMLDocument.prototype.links;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-1689064
+ */
+HTMLDocument.prototype.forms;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-7577272
+ */
+HTMLDocument.prototype.anchors;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-8747038
+ */
+HTMLDocument.prototype.cookie;
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-72161170
+ * @override
+ */
+HTMLDocument.prototype.open = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-98948567
+ * @override
+ */
+HTMLDocument.prototype.close = function() {};
+
+/**
+ * @param {string} text
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75233634
+ * @override
+ */
+HTMLDocument.prototype.write = function(text) {};
+
+/**
+ * @param {string} text
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-35318390
+ * @override
+ */
+HTMLDocument.prototype.writeln = function(text) {};
+
+/**
+ * @param {string} elementName
+ * @return {!NodeList}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-71555259
+ * @override
+ * @nosideeffects
+ */
+HTMLDocument.prototype.getElementsByName = function(elementName) {};
+
+/**
+ * @param {Node} root
+ * @param {number=} whatToShow
+ * @param {NodeFilter=} filter
+ * @param {boolean=} entityReferenceExpansion
+ * @return {!NodeIterator}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-Document
+ * @nosideeffects
+ */
+HTMLDocument.prototype.createNodeIterator = function(
+ root, whatToShow, filter, entityReferenceExpansion) {};
+
+/**
+ * @param {Node} root
+ * @param {number=} whatToShow
+ * @param {NodeFilter=} filter
+ * @param {boolean=} entityReferenceExpansion
+ * @return {!TreeWalker}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-Document
+ * @nosideeffects
+ */
+HTMLDocument.prototype.createTreeWalker = function(
+ root, whatToShow, filter, entityReferenceExpansion) {};
+
+
+/** @typedef {{
+ createNodeIterator: function(Node, number=, NodeFilter=, boolean=) : NodeIterator,
+ createTreeWalker: function(Node, number=, NodeFilter=, boolean=) : TreeWalker
+}} */
+var TraversalDocument;
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeFilter
+*/
+function NodeFilter() {}
+
+/* Constants for whatToShow */
+/** @const {number} */ NodeFilter.SHOW_ALL;
+/** @const {number} */ NodeFilter.SHOW_ATTRIBUTE;
+/** @const {number} */ NodeFilter.SHOW_CDATA_SECTION;
+/** @const {number} */ NodeFilter.SHOW_COMMENT;
+/** @const {number} */ NodeFilter.SHOW_DOCUMENT;
+/** @const {number} */ NodeFilter.SHOW_DOCUMENT_FRAGMENT;
+/** @const {number} */ NodeFilter.SHOW_DOCUMENT_TYPE;
+/** @const {number} */ NodeFilter.SHOW_ELEMENT;
+/** @const {number} */ NodeFilter.SHOW_ENTITY;
+/** @const {number} */ NodeFilter.SHOW_ENTITY_REFERENCE;
+/** @const {number} */ NodeFilter.SHOW_NOTATION;
+/** @const {number} */ NodeFilter.SHOW_PROCESSING_INSTRUCTION;
+/** @const {number} */ NodeFilter.SHOW_TEXT;
+
+/* Consants for acceptNode */
+/** @const {number} */ NodeFilter.FILTER_ACCEPT;
+/** @const {number} */ NodeFilter.FILTER_REJECT;
+/** @const {number} */ NodeFilter.FILTER_SKIP;
+
+/**
+ * @param {Node} n
+ * @return {number} Any of NodeFilter.FILTER_* constants.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeFilter-acceptNode
+*/
+NodeFilter.prototype.acceptNode = function(n) {};
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeIterator
+*/
+function NodeIterator() {}
+
+/**
+ * Detach and invalidate the NodeIterator.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeIterator-detach
+ */
+NodeIterator.prototype.detach = function() {};
+
+/**
+ * @return {Node} Next node in the set.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeIterator-nextNode
+ */
+NodeIterator.prototype.nextNode = function() {};
+
+/**
+ * @return {Node} Previous node in the set.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeIterator-previousNode
+ */
+NodeIterator.prototype.previousNode = function() {};
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker
+*/
+function TreeWalker() {}
+
+/**
+ * @return {?Node} The new Node or null.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-firstChild
+ */
+TreeWalker.prototype.firstChild = function() {};
+
+/**
+ * @return {?Node} The new Node or null..
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-lastChild
+ */
+TreeWalker.prototype.lastChild = function() {};
+
+/**
+ * @return {?Node} The new Node or null.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-nextNode
+ */
+TreeWalker.prototype.nextNode = function() {};
+
+/**
+ * @return {?Node} The new Node or null.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-nextSibling
+ */
+TreeWalker.prototype.nextSibling = function() {};
+
+/**
+ * @return {?Node} The new Node or null.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-parentNode
+ */
+TreeWalker.prototype.parentNode = function() {};
+
+/**
+ * @return {?Node} The new Node or null.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-previousNode
+ */
+TreeWalker.prototype.previousNode = function() {};
+
+/**
+ * @return {?Node} The new Node or null.
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-TreeWalker-previousSibling
+ */
+TreeWalker.prototype.previousSibling = function() {};
+
+/**
+ * @type {Node}
+ */
+TreeWalker.prototype.root;
+
+/**
+ * @type {number}
+ */
+TreeWalker.prototype.whatToShow;
+
+/**
+ * @type {NodeFilter}
+ */
+TreeWalker.prototype.filter;
+
+/**
+ * @type {boolean}
+ */
+TreeWalker.prototype.expandEntityReference;
+
+/**
+ * @type {Node}
+ */
+TreeWalker.prototype.currentNode;
+
+/**
+ * @constructor
+ * @extends {Element}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58190037
+ */
+function HTMLElement() {}
+
+/**
+ * @implicitCast
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-63534901
+ */
+HTMLElement.prototype.id;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-78276800
+ */
+HTMLElement.prototype.title;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-59132807
+ */
+HTMLElement.prototype.lang;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-52460740
+ */
+HTMLElement.prototype.dir;
+
+/**
+ * @implicitCast
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-95362176
+ */
+HTMLElement.prototype.className;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-33759296
+ */
+function HTMLHtmlElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-9383775
+ */
+HTMLHtmlElement.prototype.version;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77253168
+ */
+function HTMLHeadElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96921909
+ */
+HTMLHeadElement.prototype.profile;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @implements {LinkStyle}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-35143001
+ */
+function HTMLLinkElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87355129
+ */
+HTMLLinkElement.prototype.disabled;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-63954491
+ */
+HTMLLinkElement.prototype.charset;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-33532588
+ */
+HTMLLinkElement.prototype.href;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-85145682
+ */
+HTMLLinkElement.prototype.hreflang;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75813125
+ */
+HTMLLinkElement.prototype.media;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-41369587
+ */
+HTMLLinkElement.prototype.rel;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40715461
+ */
+HTMLLinkElement.prototype.rev;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-84183095
+ */
+HTMLLinkElement.prototype.target;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-32498296
+ */
+HTMLLinkElement.prototype.type;
+
+/** @type {StyleSheet} */
+HTMLLinkElement.prototype.sheet;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79243169
+ */
+function HTMLTitleElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77500413
+ */
+HTMLTitleElement.prototype.text;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-37041454
+ */
+function HTMLMetaElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87670826
+ */
+HTMLMetaElement.prototype.content;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77289449
+ */
+HTMLMetaElement.prototype.httpEquiv;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-31037081
+ */
+HTMLMetaElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-35993789
+ */
+HTMLMetaElement.prototype.scheme;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-73629039
+ */
+function HTMLBaseElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-65382887
+ */
+HTMLBaseElement.prototype.href;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-73844298
+ */
+HTMLBaseElement.prototype.target;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-85283003
+ */
+function HTMLIsIndexElement() {}
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87069980
+ */
+HTMLIsIndexElement.prototype.form;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-33589862
+ */
+HTMLIsIndexElement.prototype.prompt;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @implements {LinkStyle}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-16428977
+ */
+function HTMLStyleElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-51162010
+ */
+HTMLStyleElement.prototype.disabled;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-76412738
+ */
+HTMLStyleElement.prototype.media;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-22472002
+ */
+HTMLStyleElement.prototype.type;
+
+/** @type {StyleSheet} */
+HTMLStyleElement.prototype.sheet;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-62018039
+ */
+function HTMLBodyElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-59424581
+ */
+HTMLBodyElement.prototype.aLink;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-37574810
+ */
+HTMLBodyElement.prototype.background;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-24940084
+ */
+HTMLBodyElement.prototype.bgColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-7662206
+ */
+HTMLBodyElement.prototype.link;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-73714763
+ */
+HTMLBodyElement.prototype.text;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-83224305
+ */
+HTMLBodyElement.prototype.vLink;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40002357
+ */
+function HTMLFormElement() {}
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-76728479
+ */
+HTMLFormElement.prototype.elements;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#HTML-HTMLFormElement-length
+ */
+HTMLFormElement.prototype.length;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-22051454
+ */
+HTMLFormElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-19661795
+ */
+HTMLFormElement.prototype.acceptCharset;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-74049184
+ */
+HTMLFormElement.prototype.action;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-84227810
+ */
+HTMLFormElement.prototype.enctype;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-82545539
+ */
+HTMLFormElement.prototype.method;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6512890
+ */
+HTMLFormElement.prototype.target;
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-76767676
+ */
+HTMLFormElement.prototype.submit = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-76767677
+ */
+HTMLFormElement.prototype.reset = function() {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-94282980
+ */
+function HTMLSelectElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58783172
+ */
+HTMLSelectElement.prototype.type;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-85676760
+ */
+HTMLSelectElement.prototype.selectedIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-59351919
+ */
+HTMLSelectElement.prototype.value;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-5933486
+ */
+HTMLSelectElement.prototype.length;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-20489458
+ */
+HTMLSelectElement.prototype.form;
+
+/**
+ * @type {!HTMLOptionsCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-30606413
+ */
+HTMLSelectElement.prototype.options;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79102918
+ */
+HTMLSelectElement.prototype.disabled;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-13246613
+ */
+HTMLSelectElement.prototype.multiple;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-41636323
+ */
+HTMLSelectElement.prototype.name;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-18293826
+ */
+HTMLSelectElement.prototype.size;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40676705
+ */
+HTMLSelectElement.prototype.tabIndex;
+
+/**
+ * @param {HTMLElement} element
+ * @param {HTMLElement} before
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-14493106
+ */
+HTMLSelectElement.prototype.add = function(element, before) {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-28216144
+ * @override
+ */
+HTMLSelectElement.prototype.blur = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-32130014
+ * @override
+ */
+HTMLSelectElement.prototype.focus = function() {};
+
+/**
+ * @param {number} index
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-33404570
+ */
+HTMLSelectElement.prototype.remove = function(index) {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-38450247
+ */
+function HTMLOptGroupElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-15518803
+ */
+HTMLOptGroupElement.prototype.disabled;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-95806054
+ */
+HTMLOptGroupElement.prototype.label;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70901257
+ */
+function HTMLOptionElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-37770574
+ */
+HTMLOptionElement.prototype.defaultSelected;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-23482473
+ */
+HTMLOptionElement.prototype.disabled;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-17116503
+ */
+HTMLOptionElement.prototype.form;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-14038413
+ */
+HTMLOptionElement.prototype.index;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40736115
+ */
+HTMLOptionElement.prototype.label;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70874476
+ */
+HTMLOptionElement.prototype.selected;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-48154426
+ */
+HTMLOptionElement.prototype.text;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6185554
+ */
+HTMLOptionElement.prototype.value;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6043025
+ */
+function HTMLInputElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-15328520
+ */
+HTMLInputElement.prototype.accept;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-59914154
+ */
+HTMLInputElement.prototype.accessKey;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96991182
+ */
+HTMLInputElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-92701314
+ */
+HTMLInputElement.prototype.alt;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-30233917
+ */
+HTMLInputElement.prototype.checked;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-20509171
+ */
+HTMLInputElement.prototype.defaultChecked;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-26091157
+ */
+HTMLInputElement.prototype.defaultValue;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-50886781
+ */
+HTMLInputElement.prototype.disabled;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-63239895
+ */
+HTMLInputElement.prototype.form;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-54719353
+ */
+HTMLInputElement.prototype.maxLength;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-89658498
+ */
+HTMLInputElement.prototype.name;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-88461592
+ */
+HTMLInputElement.prototype.readOnly;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79659438
+ */
+HTMLInputElement.prototype.size;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-97320704
+ */
+HTMLInputElement.prototype.src;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-62176355
+ */
+HTMLInputElement.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-62883744
+ */
+HTMLInputElement.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-32463706
+ */
+HTMLInputElement.prototype.useMap;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-49531485
+ */
+HTMLInputElement.prototype.value;
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-26838235
+ * @override
+ */
+HTMLInputElement.prototype.blur = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-2651361
+ * @override
+ */
+HTMLInputElement.prototype.click = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-65996295
+ * @override
+ */
+HTMLInputElement.prototype.focus = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-34677168
+ */
+HTMLInputElement.prototype.select = function() {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-24874179
+ */
+function HTMLTextAreaElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-93102991
+ */
+HTMLTextAreaElement.prototype.accessKey;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-51387225
+ */
+HTMLTextAreaElement.prototype.cols;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-36152213
+ */
+HTMLTextAreaElement.prototype.defaultValue;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-98725443
+ */
+HTMLTextAreaElement.prototype.disabled;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-18911464
+ */
+HTMLTextAreaElement.prototype.form;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70715578
+ */
+HTMLTextAreaElement.prototype.name;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39131423
+ */
+HTMLTextAreaElement.prototype.readOnly;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-46975887
+ */
+HTMLTextAreaElement.prototype.rows;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-60363303
+ */
+HTMLTextAreaElement.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#HTML-HTMLTextAreaElement-type
+ */
+HTMLTextAreaElement.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70715579
+ */
+HTMLTextAreaElement.prototype.value;
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6750689
+ * @override
+ */
+HTMLTextAreaElement.prototype.blur = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39055426
+ * @override
+ */
+HTMLTextAreaElement.prototype.focus = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-48880622
+ */
+HTMLTextAreaElement.prototype.select = function() {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-34812697
+ */
+function HTMLButtonElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-73169431
+ */
+HTMLButtonElement.prototype.accessKey;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-92757155
+ */
+HTMLButtonElement.prototype.disabled;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-71254493
+ */
+HTMLButtonElement.prototype.form;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-11029910
+ */
+HTMLButtonElement.prototype.name;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39190908
+ */
+HTMLButtonElement.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-27430092
+ */
+HTMLButtonElement.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-72856782
+ */
+HTMLButtonElement.prototype.value;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-13691394
+ */
+function HTMLLabelElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-43589892
+ */
+HTMLLabelElement.prototype.accessKey;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-32480901
+ */
+HTMLLabelElement.prototype.form;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96509813
+ */
+HTMLLabelElement.prototype.htmlFor;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-7365882
+ */
+function HTMLFieldSetElement() {}
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75392630
+ */
+HTMLFieldSetElement.prototype.form;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-21482039
+ */
+function HTMLLegendElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-11297832
+ */
+HTMLLegendElement.prototype.accessKey;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79538067
+ */
+HTMLLegendElement.prototype.align;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-29594519
+ */
+HTMLLegendElement.prototype.form;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-86834457
+ */
+function HTMLUListElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39864178
+ */
+HTMLUListElement.prototype.compact;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96874670
+ */
+HTMLUListElement.prototype.type;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58056027
+ */
+function HTMLOListElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-76448506
+ */
+HTMLOListElement.prototype.compact;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-14793325
+ */
+HTMLOListElement.prototype.start;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40971103
+ */
+HTMLOListElement.prototype.type;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-52368974
+ */
+function HTMLDListElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-21738539
+ */
+HTMLDListElement.prototype.compact;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-71600284
+ */
+function HTMLDirectoryElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75317739
+ */
+HTMLDirectoryElement.prototype.compact;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-72509186
+ * @see http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#the-menu-element
+ */
+function HTMLMenuElement() {}
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-68436464
+ */
+HTMLMenuElement.prototype.compact;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-74680021
+ */
+function HTMLLIElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-52387668
+ */
+HTMLLIElement.prototype.type;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-45496263
+ */
+HTMLLIElement.prototype.value;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-22445964
+ */
+function HTMLDivElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70908791
+ */
+HTMLDivElement.prototype.align;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-84675076
+ */
+function HTMLParagraphElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-53465507
+ */
+HTMLParagraphElement.prototype.align;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-43345119
+ */
+function HTMLHeadingElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6796462
+ */
+HTMLHeadingElement.prototype.align;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70319763
+ */
+function HTMLQuoteElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-53895598
+ */
+HTMLQuoteElement.prototype.cite;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-11383425
+ */
+function HTMLPreElement() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-13894083
+ */
+HTMLPreElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-56836063
+ */
+function HTMLBRElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-82703081
+ */
+HTMLBRElement.prototype.clear;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-32774408
+ */
+function HTMLBaseFontElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87502302
+ */
+HTMLBaseFontElement.prototype.color;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-88128969
+ */
+HTMLBaseFontElement.prototype.face;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-38930424
+ */
+HTMLBaseFontElement.prototype.size;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-43943847
+ */
+function HTMLFontElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-53532975
+ */
+HTMLFontElement.prototype.color;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-55715655
+ */
+HTMLFontElement.prototype.face;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-90127284
+ */
+HTMLFontElement.prototype.size;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-68228811
+ */
+function HTMLHRElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-15235012
+ */
+HTMLHRElement.prototype.align;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79813978
+ */
+HTMLHRElement.prototype.noShade;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77612587
+ */
+HTMLHRElement.prototype.size;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87744198
+ */
+HTMLHRElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79359609
+ */
+function HTMLModElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75101708
+ */
+HTMLModElement.prototype.cite;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-88432678
+ */
+HTMLModElement.prototype.dateTime;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-48250443
+ */
+function HTMLAnchorElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-89647724
+ */
+HTMLAnchorElement.prototype.accessKey;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-67619266
+ */
+HTMLAnchorElement.prototype.charset;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-92079539
+ */
+HTMLAnchorElement.prototype.coords;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-88517319
+ */
+HTMLAnchorElement.prototype.href;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87358513
+ */
+HTMLAnchorElement.prototype.hreflang;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-32783304
+ */
+HTMLAnchorElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-3815891
+ */
+HTMLAnchorElement.prototype.rel;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58259771
+ */
+HTMLAnchorElement.prototype.rev;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-49899808
+ */
+HTMLAnchorElement.prototype.shape;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-41586466
+ */
+HTMLAnchorElement.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6414197
+ */
+HTMLAnchorElement.prototype.target;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-63938221
+ */
+HTMLAnchorElement.prototype.type;
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-65068939
+ * @override
+ */
+HTMLAnchorElement.prototype.blur = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-47150313
+ * @override
+ */
+HTMLAnchorElement.prototype.focus = function() {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-17701901
+ */
+function HTMLImageElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-3211094
+ */
+HTMLImageElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-95636861
+ */
+HTMLImageElement.prototype.alt;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-136671
+ */
+HTMLImageElement.prototype.border;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-91561496
+ */
+HTMLImageElement.prototype.height;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-53675471
+ */
+HTMLImageElement.prototype.hspace;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58983880
+ */
+HTMLImageElement.prototype.isMap;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77376969
+ */
+HTMLImageElement.prototype.longDesc;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-91256910
+ */
+HTMLImageElement.prototype.lowSrc;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-47534097
+ */
+HTMLImageElement.prototype.name;
+
+/**
+ * @type {string}
+ * @implicitCast
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-87762984
+ */
+HTMLImageElement.prototype.src;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-35981181
+ */
+HTMLImageElement.prototype.useMap;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-85374897
+ */
+HTMLImageElement.prototype.vspace;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-13839076
+ */
+HTMLImageElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-9893177
+ */
+function HTMLObjectElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-16962097
+ */
+HTMLObjectElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-47783837
+ */
+HTMLObjectElement.prototype.archive;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-82818419
+ */
+HTMLObjectElement.prototype.border;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75241146
+ */
+HTMLObjectElement.prototype.code;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-25709136
+ */
+HTMLObjectElement.prototype.codeBase;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-19945008
+ */
+HTMLObjectElement.prototype.codeType;
+
+/**
+ * @type {Document}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-38538621
+ */
+HTMLObjectElement.prototype.contentDocument;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-81766986
+ */
+HTMLObjectElement.prototype.data;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-942770
+ */
+HTMLObjectElement.prototype.declare;
+
+/**
+ * @type {HTMLFormElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-46094773
+ */
+HTMLObjectElement.prototype.form;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-88925838
+ */
+HTMLObjectElement.prototype.height;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-17085376
+ */
+HTMLObjectElement.prototype.hspace;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-20110362
+ */
+HTMLObjectElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-25039673
+ */
+HTMLObjectElement.prototype.standby;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-27083787
+ */
+HTMLObjectElement.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-91665621
+ */
+HTMLObjectElement.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6649772
+ */
+HTMLObjectElement.prototype.useMap;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-8682483
+ */
+HTMLObjectElement.prototype.vspace;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-38538620
+ */
+HTMLObjectElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-64077273
+ */
+function HTMLParamElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-59871447
+ */
+HTMLParamElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-18179888
+ */
+HTMLParamElement.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77971357
+ */
+HTMLParamElement.prototype.value;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-23931872
+ */
+HTMLParamElement.prototype.valueType;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-31006348
+ */
+function HTMLAppletElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-8049912
+ */
+HTMLAppletElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58610064
+ */
+HTMLAppletElement.prototype.alt;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-14476360
+ */
+HTMLAppletElement.prototype.archive;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-61509645
+ */
+HTMLAppletElement.prototype.code;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6581160
+ */
+HTMLAppletElement.prototype.codeBase;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-90184867
+ */
+HTMLAppletElement.prototype.height;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-1567197
+ */
+HTMLAppletElement.prototype.hspace;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39843695
+ */
+HTMLAppletElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-93681523
+ */
+HTMLAppletElement.prototype.object;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-22637173
+ */
+HTMLAppletElement.prototype.vspace;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-16526327
+ */
+HTMLAppletElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-94109203
+ */
+function HTMLMapElement() {}
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-71838730
+ */
+HTMLMapElement.prototype.areas;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-52696514
+ */
+HTMLMapElement.prototype.name;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-26019118
+ */
+function HTMLAreaElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-57944457
+ */
+HTMLAreaElement.prototype.accessKey;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39775416
+ */
+HTMLAreaElement.prototype.alt;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-66021476
+ */
+HTMLAreaElement.prototype.coords;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-34672936
+ */
+HTMLAreaElement.prototype.href;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-61826871
+ */
+HTMLAreaElement.prototype.noHref;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-85683271
+ */
+HTMLAreaElement.prototype.shape;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-8722121
+ */
+HTMLAreaElement.prototype.tabIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-46054682
+ */
+HTMLAreaElement.prototype.target;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-81598695
+ */
+function HTMLScriptElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-35305677
+ */
+HTMLScriptElement.prototype.charset;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-93788534
+ */
+HTMLScriptElement.prototype.defer;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-56700403
+ */
+HTMLScriptElement.prototype.event;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-66979266
+ */
+HTMLScriptElement.prototype.htmlFor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-75147231
+ */
+HTMLScriptElement.prototype.src;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-46872999
+ */
+HTMLScriptElement.prototype.text;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-30534818
+ */
+HTMLScriptElement.prototype.type;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-64060425
+ */
+function HTMLTableElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-23180977
+ */
+HTMLTableElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-83532985
+ */
+HTMLTableElement.prototype.bgColor;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-50969400
+ */
+HTMLTableElement.prototype.border;
+
+/**
+ * @type {HTMLTableCaptionElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-14594520
+ */
+HTMLTableElement.prototype.caption;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-59162158
+ */
+HTMLTableElement.prototype.cellPadding;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-68907883
+ */
+HTMLTableElement.prototype.cellSpacing;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-64808476
+ */
+HTMLTableElement.prototype.frame;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6156016
+ */
+HTMLTableElement.prototype.rows;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-26347553
+ */
+HTMLTableElement.prototype.rules;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-44998528
+ */
+HTMLTableElement.prototype.summary;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-63206416
+ */
+HTMLTableElement.prototype.tBodies;
+
+/**
+ * @type {HTMLTableSectionElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-64197097
+ */
+HTMLTableElement.prototype.tFoot;
+
+/**
+ * @type {HTMLTableSectionElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-9530944
+ */
+HTMLTableElement.prototype.tHead;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-77447361
+ */
+HTMLTableElement.prototype.width;
+
+/**
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96920263
+ */
+HTMLTableElement.prototype.createCaption = function() {};
+
+/**
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-8453710
+ */
+HTMLTableElement.prototype.createTFoot = function() {};
+
+/**
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70313345
+ */
+HTMLTableElement.prototype.createTHead = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-22930071
+ */
+HTMLTableElement.prototype.deleteCaption = function() {};
+
+/**
+ * @param {number} index
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-13114938
+ */
+HTMLTableElement.prototype.deleteRow = function(index) {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-78363258
+ */
+HTMLTableElement.prototype.deleteTFoot = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-38310198
+ */
+HTMLTableElement.prototype.deleteTHead = function() {};
+
+/**
+ * @param {number} index
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-39872903
+ */
+HTMLTableElement.prototype.insertRow = function(index) {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-12035137
+ */
+function HTMLTableCaptionElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79875068
+ */
+HTMLTableCaptionElement.prototype.align;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-84150186
+ */
+function HTMLTableColElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-31128447
+ */
+HTMLTableColElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-9447412
+ */
+HTMLTableColElement.prototype.ch;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-57779225
+ */
+HTMLTableColElement.prototype.chOff;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96511335
+ */
+HTMLTableColElement.prototype.span;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-83291710
+ */
+HTMLTableColElement.prototype.vAlign;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-25196799
+ */
+HTMLTableColElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-67417573
+ */
+function HTMLTableSectionElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-40530119
+ */
+HTMLTableSectionElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-83470012
+ */
+HTMLTableSectionElement.prototype.ch;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-53459732
+ */
+HTMLTableSectionElement.prototype.chOff;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-52092650
+ */
+HTMLTableSectionElement.prototype.rows;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-4379116
+ */
+HTMLTableSectionElement.prototype.vAlign;
+
+/**
+ * @param {number} index
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-5625626
+ */
+HTMLTableSectionElement.prototype.deleteRow = function(index) {};
+
+/**
+ * @param {number} index
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-93995626
+ */
+HTMLTableSectionElement.prototype.insertRow = function(index) {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-6986576
+ */
+function HTMLTableRowElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-74098257
+ */
+HTMLTableRowElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-18161327
+ */
+HTMLTableRowElement.prototype.bgColor;
+
+/**
+ * @type {HTMLCollection}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-67349879
+ */
+HTMLTableRowElement.prototype.cells;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-16230502
+ */
+HTMLTableRowElement.prototype.ch;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-68207461
+ */
+HTMLTableRowElement.prototype.chOff;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-67347567
+ */
+HTMLTableRowElement.prototype.rowIndex;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-79105901
+ */
+HTMLTableRowElement.prototype.sectionRowIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-90000058
+ */
+HTMLTableRowElement.prototype.vAlign;
+
+/**
+ * @param {number} index
+ * @return {undefined}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-11738598
+ */
+HTMLTableRowElement.prototype.deleteCell = function(index) {};
+
+/**
+ * @param {number} index
+ * @return {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-68927016
+ */
+HTMLTableRowElement.prototype.insertCell = function(index) {};
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-82915075
+ */
+function HTMLTableCellElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-74444037
+ */
+HTMLTableCellElement.prototype.abbr;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-98433879
+ */
+HTMLTableCellElement.prototype.align;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-76554418
+ */
+HTMLTableCellElement.prototype.axis;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-88135431
+ */
+HTMLTableCellElement.prototype.bgColor;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-80748363
+ */
+HTMLTableCellElement.prototype.cellIndex;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-30914780
+ */
+HTMLTableCellElement.prototype.ch;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-20144310
+ */
+HTMLTableCellElement.prototype.chOff;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-84645244
+ */
+HTMLTableCellElement.prototype.colSpan;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-89104817
+ */
+HTMLTableCellElement.prototype.headers;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-83679212
+ */
+HTMLTableCellElement.prototype.height;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-62922045
+ */
+HTMLTableCellElement.prototype.noWrap;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-48237625
+ */
+HTMLTableCellElement.prototype.rowSpan;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-36139952
+ */
+HTMLTableCellElement.prototype.scope;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-58284221
+ */
+HTMLTableCellElement.prototype.vAlign;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-27480795
+ */
+HTMLTableCellElement.prototype.width;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-43829095
+ */
+function HTMLFrameSetElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-98869594
+ */
+HTMLFrameSetElement.prototype.cols;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-19739247
+ */
+HTMLFrameSetElement.prototype.rows;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-97790553
+ */
+function HTMLFrameElement() {}
+
+/**
+ * @type {Document}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-78799536
+ */
+HTMLFrameElement.prototype.contentDocument;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-11858633
+ */
+HTMLFrameElement.prototype.frameBorder;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-7836998
+ */
+HTMLFrameElement.prototype.longDesc;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-55569778
+ */
+HTMLFrameElement.prototype.marginHeight;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-8369969
+ */
+HTMLFrameElement.prototype.marginWidth;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-91128709
+ */
+HTMLFrameElement.prototype.name;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-80766578
+ */
+HTMLFrameElement.prototype.noResize;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-45411424
+ */
+HTMLFrameElement.prototype.scrolling;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-78799535
+ */
+HTMLFrameElement.prototype.src;
+
+/**
+ * @constructor
+ * @extends {HTMLElement}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-50708718
+ */
+function HTMLIFrameElement() {}
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-11309947
+ */
+HTMLIFrameElement.prototype.align;
+
+/**
+ * @type {Document}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-67133006
+ */
+HTMLIFrameElement.prototype.contentDocument;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-22463410
+ */
+HTMLIFrameElement.prototype.frameBorder;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-1678118
+ */
+HTMLIFrameElement.prototype.height;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-70472105
+ */
+HTMLIFrameElement.prototype.longDesc;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-91371294
+ */
+HTMLIFrameElement.prototype.marginHeight;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-66486595
+ */
+HTMLIFrameElement.prototype.marginWidth;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-96819659
+ */
+HTMLIFrameElement.prototype.name;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-36369822
+ */
+HTMLIFrameElement.prototype.scrolling;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-43933957
+ */
+HTMLIFrameElement.prototype.src;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/html.html#ID-67133005
+ */
+HTMLIFrameElement.prototype.width;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-258A00AF
+ */
+DOMException.INVALID_STATE_ERR = 11;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-258A00AF
+ */
+DOMException.SYNTAX_ERR = 12;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-258A00AF
+ */
+DOMException.INVALID_MODIFICATION_ERR = 13;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-258A00AF
+ */
+DOMException.NAMESPACE_ERR = 14;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-258A00AF
+ */
+DOMException.INVALID_ACCESS_ERR = 15;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom3.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom3.js
new file mode 100644
index 0000000000..ad34d56587
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_dom3.js
@@ -0,0 +1,854 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's DOM Level 3 specification.
+ * This file depends on w3c_dom2.js.
+ * The whole file has been fully type annotated.
+ * Created from
+ * http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-258A00AF
+ */
+DOMException.prototype.code;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-258A00AF
+ */
+DOMException.VALIDATION_ERR = 16;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-258A00AF
+ */
+DOMException.TYPE_MISMATCH_ERR = 17;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMStringList
+ */
+function DOMStringList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMStringList-length
+ */
+DOMStringList.prototype.length;
+
+/**
+ * @param {string} str
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMStringList-contains
+ */
+DOMStringList.prototype.contains = function(str) {};
+
+/**
+ * @param {number} index
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMStringList-item
+ */
+DOMStringList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#NameList
+ */
+function NameList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#NameList-length
+ */
+NameList.prototype.length;
+
+/**
+ * @param {string} str
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#NameList-contains
+ * @nosideeffects
+ */
+NameList.prototype.contains = function(str) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} name
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#NameList-containsNS
+ * @nosideeffects
+ */
+NameList.prototype.containsNS = function(namespaceURI, name) {};
+
+/**
+ * @param {number} index
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#NameList-getName
+ * @nosideeffects
+ */
+NameList.prototype.getName = function(index) {};
+
+/**
+ * @param {number} index
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#NameList-getNamespaceURI
+ * @nosideeffects
+ */
+NameList.prototype.getNamespaceURI = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMImplementationList
+ */
+function DOMImplementationList() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMImplementationList-length
+ */
+DOMImplementationList.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {DOMImplementation}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMImplementationList-item
+ * @nosideeffects
+ */
+DOMImplementationList.prototype.item = function(index) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMImplementationSource
+ */
+function DOMImplementationSource() {}
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} publicId
+ * @param {DocumentType} doctype
+ * @return {Document}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Level-2-Core-DOM-createDocument
+ * @nosideeffects
+ */
+DOMImplementation.prototype.createDocument = function(namespaceURI, publicId, doctype) {};
+
+/**
+ * @param {string} qualifiedName
+ * @param {string} publicId
+ * @param {string} systemId
+ * @return {DocumentType}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Level-2-Core-DOM-createDocType
+ * @nosideeffects
+ */
+DOMImplementation.prototype.createDocumentType = function(qualifiedName, publicId, systemId) {};
+
+/**
+ * @param {string} features
+ * @return {DOMImplementation}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-getDOMImpl
+ * @nosideeffects
+ */
+DOMImplementationSource.prototype.getDOMImplementation = function(features) {};
+
+/**
+ * @param {string} features
+ * @return {DOMImplementationList}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-getDOMImpls
+ * @nosideeffects
+ */
+DOMImplementationSource.prototype.getDOMImplementationList = function(features) {};
+
+/**
+ * @param {string} feature
+ * @param {string} version
+ * @return {Object}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMImplementation3-getFeature
+ * @nosideeffects
+ */
+DOMImplementation.prototype.getFeature = function(feature, version) {};
+
+/**
+ * @param {Node} externalNode
+ * @return {Node}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-adoptNode
+ */
+Document.prototype.adoptNode = function(externalNode) {};
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-documentURI
+ */
+Document.prototype.documentURI;
+
+/**
+ * @type {DOMConfiguration}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-domConfig
+ */
+Document.prototype.domConfig;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-inputEncoding
+ */
+Document.prototype.inputEncoding;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-strictErrorChecking
+ */
+Document.prototype.strictErrorChecking;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-encoding
+ */
+Document.prototype.xmlEncoding;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-standalone
+ */
+Document.prototype.xmlStandalone;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-version
+ */
+Document.prototype.xmlVersion;
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-normalizeDocument
+ */
+Document.prototype.normalizeDocument = function() {};
+
+/**
+ * @param {Node} n
+ * @param {string} namespaceURI
+ * @param {string} qualifiedName
+ * @return {Node}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-renameNode
+ */
+Document.prototype.renameNode = function(n, namespaceURI, qualifiedName) {};
+
+/**
+ * @type {?string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-baseURI
+ */
+Node.prototype.baseURI;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeNSLocalN
+ */
+Node.prototype.localName;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeNSname
+ */
+Node.prototype.namespaceURI;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeNSPrefix
+ */
+Node.prototype.prefix;
+
+/**
+ * @type {string}
+ * @implicitCast
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-textContent
+ */
+Node.prototype.textContent;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node-DOCUMENT_POSITION_DISCONNECTED
+ */
+Node.DOCUMENT_POSITION_DISCONNECTED = 0x01;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node-DOCUMENT_POSITION_PRECEDING
+ */
+Node.DOCUMENT_POSITION_PRECEDING = 0x02;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node-DOCUMENT_POSITION_FOLLOWING
+ */
+Node.DOCUMENT_POSITION_FOLLOWING = 0x04;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node-DOCUMENT_POSITION_CONTAINS
+ */
+Node.DOCUMENT_POSITION_CONTAINS = 0x08;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node-DOCUMENT_POSITION_CONTAINED_BY
+ */
+Node.DOCUMENT_POSITION_CONTAINED_BY = 0x10;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node-DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
+ */
+Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+
+/**
+ * @param {Node} other
+ * @return {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition
+ * @nosideeffects
+ */
+Node.prototype.compareDocumentPosition = function(other) {};
+
+/**
+ * @param {string} feature
+ * @param {string} version
+ * @return {Object}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-getFeature
+ * @nosideeffects
+ */
+Node.prototype.getFeature = function(feature, version) {};
+
+/**
+ * @param {string} key
+ * @return {Object}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-getUserData
+ * @nosideeffects
+ */
+Node.prototype.getUserData = function(key) {};
+
+/**
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeHasAttrs
+ * @nosideeffects
+ */
+Node.prototype.hasAttributes = function() {};
+
+/**
+ * @param {string} namespaceURI
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace
+ * @nosideeffects
+ */
+Node.prototype.isDefaultNamespace = function(namespaceURI) {};
+
+/**
+ * @param {Node} arg
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isEqualNode
+ * @nosideeffects
+ */
+Node.prototype.isEqualNode = function(arg) {};
+
+/**
+ * @param {Node} other
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isSameNode
+ * @nosideeffects
+ */
+Node.prototype.isSameNode = function(other) {};
+
+/**
+ * @param {string} feature
+ * @param {string} version
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Level-2-Core-Node-supports
+ * @nosideeffects
+ */
+Node.prototype.isSupported = function(feature, version) {};
+
+/**
+ * @param {string} prefix
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI
+ * @nosideeffects
+ */
+Node.prototype.lookupNamespaceURI = function(prefix) {};
+
+/**
+ * @param {string} namespaceURI
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix
+ * @nosideeffects
+ */
+Node.prototype.lookupPrefix = function(namespaceURI) {};
+
+/**
+ * @return undefined
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-normalize
+ */
+Node.prototype.normalize = function() {};
+
+/**
+ * @param {Object} key
+ * @param {Object} data
+ * @param {UserDataHandler} handler
+ * @return {Object}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-setUserData'
+ */
+Node.prototype.setUserData = function(key, data, handler) {};
+
+/**
+ * @param {string} query
+ * @return {Node}
+ * @see http://www.w3.org/TR/selectors-api/#queryselector
+ * @nosideeffects
+ */
+Node.prototype.querySelector = function(query) {};
+
+/**
+ * @param {string} query
+ * @return {!NodeList}
+ * @see http://www.w3.org/TR/selectors-api/#queryselectorall
+ * @nosideeffects
+ */
+Node.prototype.querySelectorAll = function(query) {};
+
+/**
+ * @type {Element}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Attr-ownerElement
+ */
+Attr.prototype.ownerElement;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Attr-isId
+ */
+Attr.prototype.isId;
+
+/**
+ * @type {TypeInfo}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Attr-schemaTypeInfo
+ */
+Attr.prototype.schemaTypeInfo;
+
+/**
+ * @type {TypeInfo}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Element-schemaTypeInfo
+ */
+Element.prototype.schemaTypeInfo;
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} localName
+ * @return {Attr}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElGetAtNodeNS
+ * @nosideeffects
+ */
+Element.prototype.getAttributeNodeNS = function(namespaceURI, localName) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} localName
+ * @return {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElGetAttrNS
+ * @nosideeffects
+ */
+Element.prototype.getAttributeNS = function(namespaceURI, localName) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} localName
+ * @return {!NodeList}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-A6C90942
+ * @nosideeffects
+ */
+Element.prototype.getElementsByTagNameNS = function(namespaceURI, localName) {};
+
+/**
+ * @param {string} name
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElHasAttr
+ * @nosideeffects
+ */
+Element.prototype.hasAttribute = function(name) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} localName
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElHasAttrNS
+ * @nosideeffects
+ */
+Element.prototype.hasAttributeNS = function(namespaceURI, localName) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} localName
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElRemAtNS
+ */
+Element.prototype.removeAttributeNS = function(namespaceURI, localName) {};
+
+/**
+ * @param {Attr} newAttr
+ * @return {Attr}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElSetAtNodeNS
+ */
+Element.prototype.setAttributeNodeNS = function(newAttr) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} qualifiedName
+ * @param {string|number|boolean} value Values are converted to strings with
+ * ToString, so we accept number and boolean since both convert easily to
+ * strings.
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElSetAttrNS
+ */
+Element.prototype.setAttributeNS = function(namespaceURI, qualifiedName, value) {};
+
+/**
+ * @param {string} name
+ * @param {boolean} isId
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElSetIdAttr
+ */
+Element.prototype.setIdAttribute = function(name, isId) {};
+
+/**
+ * @param {Attr} idAttr
+ * @param {boolean} isId
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElSetIdAttrNode
+ */
+Element.prototype.setIdAttributeNode = function(idAttr, isId) {};
+
+/**
+ * @param {string} namespaceURI
+ * @param {string} localName
+ * @param {boolean} isId
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElSetIdAttrNS
+ */
+Element.prototype.setIdAttributeNS = function(namespaceURI, localName, isId) {};
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Text3-wholeText
+ */
+Text.prototype.wholeText;
+
+/**
+ * @param {string} newText
+ * @return {Text}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Text3-replaceWholeText
+ */
+Text.prototype.replaceWholeText = function(newText) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo
+ */
+function TypeInfo() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-DERIVATION_EXTENSION
+ */
+TypeInfo.prototype.DERIVATION_EXTENSION;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-DERIVATION_LIST
+ */
+TypeInfo.prototype.DERIVATION_LIST;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-DERIVATION_RESTRICTION
+ */
+TypeInfo.prototype.DERIVATION_RESTRICTION;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-DERIVATION_UNION
+ */
+TypeInfo.prototype.DERIVATION_UNION;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-typeName
+ */
+TypeInfo.prototype.typeName;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-typeNamespace
+ */
+TypeInfo.prototype.typeNamespace;
+
+/**
+ * @param {string} typeNamespaceArg
+ * @param {string} typeNameArg
+ * @param {number} derivationMethod
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
+ * @nosideeffects
+ */
+TypeInfo.prototype.isDerivedFrom = function(typeNamespaceArg, typeNameArg, derivationMethod) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#UserDataHandler
+ */
+function UserDataHandler() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#UserDataHandler-CLONED
+ */
+UserDataHandler.prototype.NODE_CLONED = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#UserDataHandler-IMPORTED
+ */
+UserDataHandler.prototype.NODE_IMPORTED = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#UserDataHandler-DELETED
+ */
+UserDataHandler.prototype.NODE_DELETED = 3;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#UserDataHandler-RENAMED
+ */
+UserDataHandler.prototype.NODE_RENAMED = 4;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#UserDataHandler-ADOPTED
+ */
+UserDataHandler.prototype.NODE_ADOPTED = 5;
+
+/**
+ * @param {number} operation
+ * @param {string} key
+ * @param {*=} opt_data
+ * @param {?Node=} opt_src
+ * @param {?Node=} opt_dst
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-handleUserDataEvent
+ */
+UserDataHandler.prototype.handle = function(operation, key, opt_data,
+ opt_src, opt_dst) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-Interfaces-DOMError
+ */
+function DOMError() {}
+
+/**
+ * @type {DOMLocator}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-location
+ */
+DOMError.prototype.location;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-message
+ */
+DOMError.prototype.message;
+
+/**
+ * @type {Object}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-relatedData
+ */
+DOMError.prototype.relatedData;
+
+/**
+ * @type {Object}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-relatedException
+ */
+DOMError.prototype.relatedException;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-severity-warning
+ */
+DOMError.SEVERITY_WARNING = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-severity-error
+ */
+DOMError.SEVERITY_ERROR = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-severity-fatal-error
+ */
+DOMError.SEVERITY_FATAL_ERROR = 3;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-severity
+ */
+DOMError.prototype.severity;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-DOMError-type
+ */
+DOMError.prototype.type;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/dom/#domerror
+ */
+DOMError.prototype.name;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ERROR-Interfaces-DOMErrorHandler
+ */
+function DOMErrorHandler() {}
+
+/**
+ * @param {DOMError} error
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ERRORS-DOMErrorHandler-handleError
+ */
+DOMErrorHandler.prototype.handleError = function(error) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Interfaces-DOMLocator
+ */
+function DOMLocator() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMLocator-byteOffset
+ */
+DOMLocator.prototype.byteOffset;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMLocator-column-number
+ */
+DOMLocator.prototype.columnNumber;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMLocator-line-number
+ */
+DOMLocator.prototype.lineNumber;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMLocator-node
+ */
+DOMLocator.prototype.relatedNode;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMLocator-uri
+ */
+DOMLocator.prototype.uri;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMLocator-utf16Offset
+ */
+DOMLocator.prototype.utf16Offset;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMConfiguration
+ */
+function DOMConfiguration() {}
+
+/**
+ * @type {DOMStringList}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMConfiguration-parameterNames
+ */
+DOMConfiguration.prototype.parameterNames;
+
+/**
+ * @param {string} name
+ * @return {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMConfiguration-canSetParameter
+ * @nosideeffects
+ */
+DOMConfiguration.prototype.canSetParameter = function(name) {};
+
+/**
+ * @param {string} name
+ * @return {*}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMConfiguration-getParameter
+ * @nosideeffects
+ */
+DOMConfiguration.prototype.getParameter = function(name) {};
+
+/**
+ * @param {string} name
+ * @param {*} value
+ * @return {*}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMConfiguration-property
+ */
+DOMConfiguration.prototype.setParameter = function(name, value) {};
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-Core-DocType-internalSubset
+ */
+DocumentType.prototype.internalSubset;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-Core-DocType-publicId
+ */
+DocumentType.prototype.publicId;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-Core-DocType-systemId
+ */
+DocumentType.prototype.systemId;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Entity3-inputEncoding
+ */
+Entity.prototype.inputEncoding;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Entity3-encoding
+ */
+Entity.prototype.xmlEncoding;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Entity3-version
+ */
+Entity.prototype.xmlVersion;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_elementtraversal.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_elementtraversal.js
new file mode 100644
index 0000000000..ee4b4589af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_elementtraversal.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for DOM Element Traversal interface.
+ * This file depends on w3c_dom1.js.
+ * The whole file has been fully type annotated.
+ * Created from:
+ * http://www.w3.org/TR/ElementTraversal/#ecmascript-bindings
+ *
+ * @externs
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+/**
+ * @type {Element}
+ * @see https://developer.mozilla.org/En/DOM/Element.firstElementChild
+ */
+Element.prototype.firstElementChild;
+
+/**
+ * @type {Element}
+ * @see https://developer.mozilla.org/En/DOM/Element.lastElementChild
+ */
+Element.prototype.lastElementChild;
+
+/**
+ * @type {Element}
+ * @see https://developer.mozilla.org/En/DOM/Element.previousElementSibling
+ */
+Element.prototype.previousElementSibling;
+
+/**
+ * @type {Element}
+ * @see https://developer.mozilla.org/En/DOM/Element.nextElementSibling
+ */
+Element.prototype.nextElementSibling;
+
+/**
+ * @type {number}
+ * @see https://developer.mozilla.org/En/DOM/Element.childElementCount
+ */
+Element.prototype.childElementCount;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_encoding.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_encoding.js
new file mode 100644
index 0000000000..947821a909
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_encoding.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's Encoding specification
+ * https://encoding.spec.whatwg.org
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @param {string=} encoding
+ * @param {Object=} options
+ */
+function TextDecoder(encoding, options) {}
+
+/** @type {string} **/ TextDecoder.prototype.encoding;
+/** @type {boolean} **/ TextDecoder.prototype.fatal;
+/** @type {boolean} **/ TextDecoder.prototype.ignoreBOM;
+
+/**
+ * @param {!Uint8Array} input
+ * @param {Object=} options
+ * @return {string}
+ */
+TextDecoder.prototype.decode = function decode(input, options) {};
+
+/**
+ * @constructor
+ * @param {string=} encoding
+ * @param {Object=} options
+ */
+function TextEncoder(encoding, options) {}
+
+/** @type {string} **/ TextEncoder.prototype.encoding;
+
+/**
+ * @param {string} input
+ * @return {!Uint8Array}
+ */
+TextEncoder.prototype.encode = function(input) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event.js
new file mode 100644
index 0000000000..7c72dd1836
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event.js
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's event specification.
+ * The whole file has been fully type annotated.
+ * Created from
+ * http://www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html
+ *
+ * @externs
+ */
+
+
+/**
+ * @interface
+ */
+function EventTarget() {}
+
+/**
+ * @param {string} type
+ * @param {EventListener|function(!Event):(boolean|undefined)} listener
+ * @param {boolean} useCapture
+ * @return {undefined}
+ */
+EventTarget.prototype.addEventListener = function(type, listener, useCapture)
+ {};
+
+/**
+ * @param {string} type
+ * @param {EventListener|function(!Event):(boolean|undefined)} listener
+ * @param {boolean} useCapture
+ * @return {undefined}
+ */
+EventTarget.prototype.removeEventListener = function(type, listener, useCapture)
+ {};
+
+/**
+ * @param {!Event} evt
+ * @return {boolean}
+ */
+EventTarget.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @interface
+ */
+function EventListener() {}
+
+/**
+ * @param {!Event} evt
+ * @return {undefined}
+ */
+EventListener.prototype.handleEvent = function(evt) {};
+
+// The EventInit interface and the parameters to the Event constructor are part
+// of DOM Level 3 (suggested) and the DOM "Living Standard" (mandated). They are
+// included here as externs cannot be redefined. The same applies to other
+// *EventInit interfaces and *Event constructors throughout this file. See:
+// http://www.w3.org/TR/DOM-Level-3-Events/#event-initializers
+// http://dom.spec.whatwg.org/#constructing-events
+// https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm#event-constructors
+
+/**
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined)
+ * }}
+ */
+var EventInit;
+
+/**
+ * @constructor
+ * @param {string} type
+ * @param {EventInit=} opt_eventInitDict
+ */
+function Event(type, opt_eventInitDict) {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html
+ */
+Event.AT_TARGET;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html
+ */
+Event.BUBBLING_PHASE;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html
+ */
+Event.CAPTURING_PHASE;
+
+
+/** @type {string} */
+Event.prototype.type;
+
+/** @type {EventTarget} */
+Event.prototype.target;
+
+/** @type {EventTarget} */
+Event.prototype.currentTarget;
+
+/** @type {number} */
+Event.prototype.eventPhase;
+
+/** @type {boolean} */
+Event.prototype.bubbles;
+
+/** @type {boolean} */
+Event.prototype.cancelable;
+
+/** @type {number} */
+Event.prototype.timeStamp;
+
+/**
+ * Present for events spawned in browsers that support shadow dom.
+ * @type {Array.<!Element>|undefined}
+ */
+Event.prototype.path;
+
+/**
+ * @return {undefined}
+ */
+Event.prototype.stopPropagation = function() {};
+
+/**
+ * @return {undefined}
+ */
+Event.prototype.preventDefault = function() {};
+
+/**
+ * @param {string} eventTypeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @return {undefined}
+ */
+Event.prototype.initEvent = function(eventTypeArg, canBubbleArg, cancelableArg) {};
+
+/**
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined),
+ * detail: *
+ * }}
+ */
+var CustomEventInit;
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @param {string} type
+ * @param {CustomEventInit=} opt_eventInitDict
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#interface-CustomEvent
+ */
+function CustomEvent(type, opt_eventInitDict) {}
+
+/**
+ * @param {string} eventType
+ * @param {boolean} bubbles
+ * @param {boolean} cancelable
+ * @param {*} detail
+ */
+CustomEvent.prototype.initCustomEvent = function(
+ eventType, bubbles, cancelable, detail) {};
+
+/**
+ * @type {*}
+ */
+CustomEvent.prototype.detail;
+
+/**
+ * @interface
+ */
+function DocumentEvent() {}
+
+/**
+ * @param {string} eventType
+ * @return {!Event}
+ */
+DocumentEvent.prototype.createEvent = function(eventType) {};
+
+/**
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined),
+ * view: (Window|undefined),
+ * detail: (number|undefined)
+ * }}
+ */
+var UIEventInit;
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @param {string} type
+ * @param {UIEventInit=} opt_eventInitDict
+ */
+function UIEvent(type, opt_eventInitDict) {}
+
+/** @type {number} */
+UIEvent.prototype.detail;
+
+/**
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {Window} viewArg
+ * @param {number} detailArg
+ * @return {undefined}
+ */
+UIEvent.prototype.initUIEvent = function(typeArg, canBubbleArg, cancelableArg,
+ viewArg, detailArg) {};
+
+/**
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined),
+ * view: (Window|undefined),
+ * detail: (number|undefined),
+ * screenX: (number|undefined),
+ * screenY: (number|undefined),
+ * clientX: (number|undefined),
+ * clientY: (number|undefined),
+ * ctrlKey: (boolean|undefined),
+ * shiftKey: (boolean|undefined),
+ * altKey: (boolean|undefined),
+ * metaKey: (boolean|undefined),
+ * button: (number|undefined),
+ * buttons: (number|undefined),
+ * relatedTarget: (EventTarget|undefined)
+ * }}
+ */
+var MouseEventInit;
+
+/**
+ * @constructor
+ * @extends {UIEvent}
+ * @param {string} type
+ * @param {MouseEventInit=} opt_eventInitDict
+ */
+function MouseEvent(type, opt_eventInitDict) {}
+
+/** @type {number} */
+MouseEvent.prototype.screenX;
+
+/** @type {number} */
+MouseEvent.prototype.screenY;
+
+/** @type {number} */
+MouseEvent.prototype.clientX;
+
+/** @type {number} */
+MouseEvent.prototype.clientY;
+
+/** @type {boolean} */
+MouseEvent.prototype.ctrlKey;
+
+/** @type {boolean} */
+MouseEvent.prototype.shiftKey;
+
+/** @type {boolean} */
+MouseEvent.prototype.altKey;
+
+/** @type {boolean} */
+MouseEvent.prototype.metaKey;
+
+/** @type {number} */
+MouseEvent.prototype.button;
+
+/** @type {EventTarget} */
+MouseEvent.prototype.relatedTarget;
+
+
+/**
+ * @constructor
+ * @extends {Event}
+ */
+function MutationEvent() {}
+
+/** @type {Node} */
+MutationEvent.prototype.relatedNode;
+
+/** @type {string} */
+MutationEvent.prototype.prevValue;
+
+/** @type {string} */
+MutationEvent.prototype.newValue;
+
+/** @type {string} */
+MutationEvent.prototype.attrName;
+
+/** @type {number} */
+MutationEvent.prototype.attrChange;
+
+/**
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {Node} relatedNodeArg
+ * @param {string} prevValueArg
+ * @param {string} newValueArg
+ * @param {string} attrNameArg
+ * @param {number} attrChangeArg
+ * @return {undefined}
+ */
+MutationEvent.prototype.initMutationEvent = function(typeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevValueArg, newValueArg, attrNameArg, attrChangeArg) {};
+
+
+// DOM3
+/**
+ * @typedef {{
+ * bubbles: (boolean|undefined),
+ * cancelable: (boolean|undefined),
+ * view: (Window|undefined),
+ * detail: (number|undefined),
+ * char: (string|undefined),
+ * key: (string|undefined),
+ * code: (string|undefined),
+ * location: (number|undefined),
+ * ctrlKey: (boolean|undefined),
+ * shiftKey: (boolean|undefined),
+ * altKey: (boolean|undefined),
+ * metaKey: (boolean|undefined),
+ * repeat: (boolean|undefined),
+ * locale: (string|undefined)
+ * }}
+ */
+var KeyboardEventInit;
+
+/**
+ * @constructor
+ * @extends {UIEvent}
+ * @param {string} type
+ * @param {KeyboardEventInit=} opt_eventInitDict
+ */
+function KeyboardEvent(type, opt_eventInitDict) {}
+
+/** @type {string} */
+KeyboardEvent.prototype.keyIdentifier;
+
+/** @type {boolean} */
+KeyboardEvent.prototype.ctrlKey;
+
+/** @type {boolean} */
+KeyboardEvent.prototype.shiftKey;
+
+/** @type {boolean} */
+KeyboardEvent.prototype.altKey;
+
+/** @type {boolean} */
+KeyboardEvent.prototype.metaKey;
+
+/**
+ * @param {string} keyIdentifierArg
+ * @return {boolean}
+ */
+KeyboardEvent.prototype.getModifierState = function(keyIdentifierArg) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event3.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event3.js
new file mode 100644
index 0000000000..e98716e2fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_event3.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's event Level 3 specification.
+ * This file depends on w3c_event.js.
+ * The whole file has been partially type annotated.
+ * Created from
+ * http://www.w3.org/TR/DOM-Level-3-Events/#ecma-script-binding-ecma-binding
+ *
+ * @externs
+ */
+
+/**
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {Window} viewArg
+ * @param {string} keyIdentifierArg
+ * @param {number} keyLocationArg
+ * @param {string} modifiersList
+ */
+KeyboardEvent.prototype.initKeyboardEvent = function(typeArg, canBubbleArg, cancelableArg, viewArg, keyIdentifierArg, keyLocationArg, modifiersList) {};
+
+/** @type {string} */
+KeyboardEvent.prototype.char;
+
+/** @type {string} */
+KeyboardEvent.prototype.key;
+
+/** @type {number} */
+KeyboardEvent.prototype.location;
+
+/** @type {boolean} */
+KeyboardEvent.prototype.repeat;
+
+/** @type {string} */
+KeyboardEvent.prototype.locale;
+
+/** @type {number} */
+MouseEvent.prototype.buttons;
+
+/** @type {boolean} */
+Event.prototype.defaultPrevented;
+
+/** @type {string} */
+Event.prototype.namespaceURI;
+
+/** @return {undefined} */
+Event.prototype.stopImmediatePropagation = function() {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_geolocation.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_geolocation.js
new file mode 100644
index 0000000000..0b9db09137
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_geolocation.js
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's Geolocation specification
+ * http://www.w3.org/TR/geolocation-API/
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/geolocation-API/#geolocation
+ */
+function Geolocation() {}
+
+/**
+ * @param {function(GeolocationPosition)} successCallback
+ * @param {(function(GeolocationPositionError)|null)=} opt_errorCallback
+ * @param {GeolocationPositionOptions=} opt_options
+ */
+Geolocation.prototype.getCurrentPosition = function(successCallback,
+ opt_errorCallback,
+ opt_options) {};
+
+/**
+ * @param {function(GeolocationPosition)} successCallback
+ * @param {(function(GeolocationPositionError)|null)=} opt_errorCallback
+ * @param {GeolocationPositionOptions=} opt_options
+ * @return {number}
+ */
+Geolocation.prototype.watchPosition = function(successCallback,
+ opt_errorCallback,
+ opt_options) {};
+
+/** @param {number} watchId */
+Geolocation.prototype.clearWatch = function(watchId) {};
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/geolocation-API/#coordinates
+ */
+function GeolocationCoordinates() {}
+/** @type {number} */ GeolocationCoordinates.prototype.latitude;
+/** @type {number} */ GeolocationCoordinates.prototype.longitude;
+/** @type {number} */ GeolocationCoordinates.prototype.accuracy;
+/** @type {number} */ GeolocationCoordinates.prototype.altitude;
+/** @type {number} */ GeolocationCoordinates.prototype.altitudeAccuracy;
+/** @type {number} */ GeolocationCoordinates.prototype.heading;
+/** @type {number} */ GeolocationCoordinates.prototype.speed;
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/geolocation-API/#position
+ */
+function GeolocationPosition() {}
+/** @type {GeolocationCoordinates} */
+GeolocationPosition.prototype.coords;
+/** @type {Date} */ GeolocationPosition.prototype.timestamp;
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/geolocation-API/#position-options
+ */
+function GeolocationPositionOptions() {}
+/** @type {boolean} */
+GeolocationPositionOptions.prototype.enableHighAccuracy;
+/** @type {number} */ GeolocationPositionOptions.prototype.maximumAge;
+/** @type {number} */ GeolocationPositionOptions.prototype.timeout;
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/geolocation-API/#position-error
+ */
+function GeolocationPositionError() {}
+/** @type {number} */ GeolocationPositionError.prototype.code;
+/** @type {string} */ GeolocationPositionError.prototype.message;
+/** @type {number} */ GeolocationPositionError.prototype.UNKNOWN_ERROR;
+/** @type {number} */ GeolocationPositionError.prototype.PERMISSION_DENIED;
+/** @type {number} */
+GeolocationPositionError.prototype.POSITION_UNAVAILABLE;
+/** @type {number} */ GeolocationPositionError.prototype.TIMEOUT;
+
+/** @type {Geolocation} */
+Navigator.prototype.geolocation;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_indexeddb.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_indexeddb.js
new file mode 100644
index 0000000000..19c35ec1ee
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_indexeddb.js
@@ -0,0 +1,914 @@
+/*
+ * Copyright 2011 The Closure Compiler Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's IndexedDB API. In Chrome all the
+ * IndexedDB classes are prefixed with 'webkit'. In order to access constants
+ * and static methods of these classes they must be duplicated with the
+ * prefix here.
+ * @see http://www.w3.org/TR/IndexedDB/
+ *
+ * @externs
+ * @author guido.tapia@picnet.com.au (Guido Tapia)
+ */
+
+/** @type {IDBFactory} */
+Window.prototype.moz_indexedDB;
+
+/** @type {IDBFactory} */
+Window.prototype.mozIndexedDB;
+
+/** @type {IDBFactory} */
+Window.prototype.webkitIndexedDB;
+
+/** @type {IDBFactory} */
+Window.prototype.msIndexedDB;
+
+/** @type {IDBFactory} */
+Window.prototype.indexedDB;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBFactory
+ */
+function IDBFactory() {}
+
+/**
+ * @param {string} name The name of the database to open.
+ * @param {number=} opt_version The version at which to open the database.
+ * @return {!IDBOpenDBRequest} The IDBRequest object.
+ */
+IDBFactory.prototype.open = function(name, opt_version) {};
+
+/**
+ * @param {string} name The name of the database to delete.
+ * @return {!IDBOpenDBRequest} The IDBRequest object.
+ */
+IDBFactory.prototype.deleteDatabase = function(name) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBDatabaseException
+ */
+function IDBDatabaseException() {}
+
+/**
+ * @constructor
+ * @extends {IDBDatabaseException}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBDatabaseException
+ */
+function webkitIDBDatabaseException() {}
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.UNKNOWN_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.UNKNOWN_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.NON_TRANSIENT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.NON_TRANSIENT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.NOT_FOUND_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.NOT_FOUND_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.CONSTRAINT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.CONSTRAINT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.DATA_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.DATA_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.NOT_ALLOWED_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.NOT_ALLOWED_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.TRANSACTION_INACTIVE_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.TRANSACTION_INACTIVE_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.ABORT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.ABORT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.READ_ONLY_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.READ_ONLY_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.TIMEOUT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.TIMEOUT_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.QUOTA_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.QUOTA_ERR;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBDatabaseException.prototype.code;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBDatabaseException.prototype.code;
+
+/**
+ * @const
+ * @type {string}
+ */
+IDBDatabaseException.prototype.message;
+
+/**
+ * @const
+ * @type {string}
+ */
+webkitIDBDatabaseException.prototype.message;
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBRequest
+ */
+function IDBRequest() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+IDBRequest.prototype.addEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+IDBRequest.prototype.removeEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/** @override */
+IDBRequest.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @constructor
+ * @extends {IDBRequest}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBRequest
+ */
+function webkitIDBRequest() {}
+
+/**
+ * @type {number}
+ * @const
+ */
+IDBRequest.LOADING;
+
+/**
+ * @type {number}
+ * @const
+ */
+webkitIDBRequest.LOADING;
+
+/**
+ * @type {number}
+ * @const
+ */
+IDBRequest.DONE;
+
+/**
+ * @type {number}
+ * @const
+ */
+webkitIDBRequest.DONE;
+
+/** @type {number} */
+IDBRequest.prototype.readyState; // readonly
+
+/** @type {function(!Event)} */
+IDBRequest.prototype.onsuccess = function(e) {};
+
+/** @type {function(!Event)} */
+IDBRequest.prototype.onerror = function(e) {};
+
+/** @type {*} */
+IDBRequest.prototype.result; // readonly
+
+/**
+ * @type {number}
+ * @deprecated Use "error"
+ */
+IDBRequest.prototype.errorCode; // readonly
+
+
+/** @type {!DOMError} */
+IDBRequest.prototype.error; // readonly
+
+/** @type {Object} */
+IDBRequest.prototype.source; // readonly
+
+/** @type {IDBTransaction} */
+IDBRequest.prototype.transaction; // readonly
+
+/**
+ * @constructor
+ * @extends {IDBRequest}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBOpenDBRequest
+ */
+function IDBOpenDBRequest() {}
+
+/**
+ * @type {function(!IDBVersionChangeEvent)}
+ */
+IDBOpenDBRequest.prototype.onblocked = function(e) {};
+
+/**
+ * @type {function(!IDBVersionChangeEvent)}
+ */
+IDBOpenDBRequest.prototype.onupgradeneeded = function(e) {};
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBDatabase
+ */
+function IDBDatabase() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+IDBDatabase.prototype.name;
+
+/**
+ * @type {string}
+ * @const
+ */
+IDBDatabase.prototype.description;
+
+/**
+ * @type {string}
+ * @const
+ */
+IDBDatabase.prototype.version;
+
+/**
+ * @type {DOMStringList}
+ * @const
+ */
+IDBDatabase.prototype.objectStoreNames;
+
+/**
+ * @param {string} name The name of the object store.
+ * @param {Object=} opt_parameters Parameters to be passed
+ * creating the object store.
+ * @return {!IDBObjectStore} The created/open object store.
+ */
+IDBDatabase.prototype.createObjectStore =
+ function(name, opt_parameters) {};
+
+/**
+ * @param {string} name The name of the object store to remove.
+ */
+IDBDatabase.prototype.deleteObjectStore = function(name) {};
+
+/**
+ * @param {string} version The new version of the database.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBDatabase.prototype.setVersion = function(version) {};
+
+/**
+ * @param {Array.<string>} storeNames The stores to open in this transaction.
+ * @param {(number|string)=} mode The mode for opening the object stores.
+ * @return {!IDBTransaction} The IDBRequest object.
+ */
+IDBDatabase.prototype.transaction = function(storeNames, mode) {};
+
+/**
+ * Closes the database connection.
+ */
+IDBDatabase.prototype.close = function() {};
+
+/**
+ * @type {Function}
+ */
+IDBDatabase.prototype.onabort = function() {};
+
+/**
+ * @type {Function}
+ */
+IDBDatabase.prototype.onerror = function() {};
+
+/**
+ * @type {Function}
+ */
+IDBDatabase.prototype.onversionchange = function() {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+IDBDatabase.prototype.addEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+IDBDatabase.prototype.removeEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/** @override */
+IDBDatabase.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * Typedef for valid key types according to the w3 specification. Note that this
+ * is slightly wider than what is actually allowed, as all Array elements must
+ * have a valid key type.
+ * @see http://www.w3.org/TR/IndexedDB/#key-construct
+ * @typedef {number|string|!Date|!Array.<?>}
+ */
+var IDBKeyType;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBObjectStore
+ */
+function IDBObjectStore() {}
+
+/**
+ * @type {string}
+ */
+IDBObjectStore.prototype.name;
+
+/**
+ * @type {string}
+ */
+IDBObjectStore.prototype.keyPath;
+
+/**
+ * @type {DOMStringList}
+ */
+IDBObjectStore.prototype.indexNames;
+
+/** @type {IDBTransaction} */
+IDBObjectStore.prototype.transaction;
+
+/** @type {boolean} */
+IDBObjectStore.prototype.autoIncrement;
+
+/**
+ * @param {*} value The value to put into the object store.
+ * @param {IDBKeyType=} key The key of this value.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBObjectStore.prototype.put = function(value, key) {};
+
+/**
+ * @param {*} value The value to add into the object store.
+ * @param {IDBKeyType=} key The key of this value.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBObjectStore.prototype.add = function(value, key) {};
+
+/**
+ * @param {IDBKeyType} key The key of this value.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBObjectStore.prototype.delete = function(key) {};
+
+/**
+ * @param {IDBKeyType|!IDBKeyRange} key The key of the document to retrieve.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBObjectStore.prototype.get = function(key) {};
+
+/**
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBObjectStore.prototype.clear = function() {};
+
+/**
+ * @param {IDBKeyRange=} range The range of the cursor.
+ * @param {(number|string)=} direction The direction of cursor enumeration.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBObjectStore.prototype.openCursor = function(range, direction) {};
+
+/**
+ * @param {string} name The name of the index.
+ * @param {string|!Array.<string>} keyPath The path to the index key.
+ * @param {Object=} opt_paramters Optional parameters
+ * for the created index.
+ * @return {!IDBIndex} The IDBIndex object.
+ */
+IDBObjectStore.prototype.createIndex = function(name, keyPath, opt_paramters) {};
+
+/**
+ * @param {string} name The name of the index to retrieve.
+ * @return {!IDBIndex} The IDBIndex object.
+ */
+IDBObjectStore.prototype.index = function(name) {};
+
+/**
+ * @param {string} indexName The name of the index to remove.
+ */
+IDBObjectStore.prototype.deleteIndex = function(indexName) {};
+
+/**
+ * @param {(IDBKeyType|IDBKeyRange)=} key The key of this value.
+ * @return {!IDBRequest} The IDBRequest object.
+ * @see http://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-count
+ */
+IDBObjectStore.prototype.count = function(key) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndex
+ */
+function IDBIndex() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+IDBIndex.prototype.name;
+
+/**
+ * @type {!IDBObjectStore}
+ * @const
+ */
+IDBIndex.prototype.objectStore;
+
+/**
+ * @type {string}
+ * @const
+ */
+IDBIndex.prototype.keyPath;
+
+/**
+ * @type {boolean}
+ * @const
+ */
+IDBIndex.prototype.unique;
+
+/**
+ * @param {IDBKeyRange=} range The range of the cursor.
+ * @param {(number|string)=} direction The direction of cursor enumeration.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBIndex.prototype.openCursor = function(range, direction) {};
+
+/**
+ * @param {IDBKeyRange=} range The range of the cursor.
+ * @param {(number|string)=} direction The direction of cursor enumeration.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBIndex.prototype.openKeyCursor = function(range, direction) {};
+
+/**
+ * @param {IDBKeyType|!IDBKeyRange} key The id of the object to retrieve.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBIndex.prototype.get = function(key) {};
+
+/**
+ * @param {IDBKeyType|!IDBKeyRange} key The id of the object to retrieve.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBIndex.prototype.getKey = function(key) {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursor
+ */
+function IDBCursor() {}
+
+/**
+ * @constructor
+ * @extends {IDBCursor}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursor
+ */
+function webkitIDBCursor() {}
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBCursor.NEXT;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBCursor.NEXT;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBCursor.NEXT_NO_DUPLICATE;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBCursor.NEXT_NO_DUPLICATE;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBCursor.PREV;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBCursor.PREV;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBCursor.PREV_NO_DUPLICATE;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBCursor.PREV_NO_DUPLICATE;
+
+/**
+ * @type {*}
+ * @const
+ */
+IDBCursor.prototype.source;
+
+/**
+ * @type {number}
+ * @const
+ */
+IDBCursor.prototype.direction;
+
+/**
+ * @type {IDBKeyType}
+ * @const
+ */
+IDBCursor.prototype.key;
+
+/**
+ * @type {number}
+ * @const
+ */
+IDBCursor.prototype.primaryKey;
+
+/**
+ * @param {*} value The new value for the current object in the cursor.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBCursor.prototype.update = function(value) {};
+
+/**
+ * Note: Must be quoted to avoid parse error.
+ * @param {IDBKeyType=} key Continue enumerating the cursor from the specified
+ * key (or next).
+ */
+IDBCursor.prototype.continue = function(key) {};
+
+/**
+ * @param {number} count Number of times to iterate the cursor.
+ */
+IDBCursor.prototype.advance = function(count) {};
+
+/**
+ * Note: Must be quoted to avoid parse error.
+ * @return {!IDBRequest} The IDBRequest object.
+ */
+IDBCursor.prototype.delete = function() {};
+
+/**
+ * @constructor
+ * @extends {IDBCursor}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursorWithValue
+ */
+function IDBCursorWithValue() {}
+
+/** @type {*} */
+IDBCursorWithValue.prototype.value; // readonly
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBTransaction
+ */
+function IDBTransaction() {}
+
+/**
+ * @constructor
+ * @extends {IDBTransaction}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBTransaction
+ */
+function webkitIDBTransaction() {}
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBTransaction.READ_WRITE;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBTransaction.READ_WRITE;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBTransaction.READ_ONLY;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBTransaction.READ_ONLY;
+
+/**
+ * @const
+ * @type {number}
+ */
+IDBTransaction.VERSION_CHANGE;
+
+/**
+ * @const
+ * @type {number}
+ */
+webkitIDBTransaction.VERSION_CHANGE;
+
+/**
+ * @type {number|string}
+ * @const
+ */
+IDBTransaction.prototype.mode;
+
+/**
+ * @type {IDBDatabase}
+ * @const
+ */
+IDBTransaction.prototype.db;
+
+/**
+ * @param {string} name The name of the object store to retrieve.
+ * @return {!IDBObjectStore} The object store.
+ */
+IDBTransaction.prototype.objectStore = function(name) {};
+
+/**
+ * Aborts the transaction.
+ */
+IDBTransaction.prototype.abort = function() {};
+
+/**
+ * @type {Function}
+ */
+IDBTransaction.prototype.onabort = function() {};
+
+/**
+ * @type {Function}
+ */
+IDBTransaction.prototype.oncomplete = function() {};
+
+/**
+ * @type {Function}
+ */
+IDBTransaction.prototype.onerror = function() {};
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBKeyRange
+ */
+function IDBKeyRange() {}
+
+/**
+ * @constructor
+ * @extends {IDBKeyRange}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBKeyRange
+ */
+function webkitIDBKeyRange() {}
+
+/**
+ * @type {*}
+ * @const
+ */
+IDBKeyRange.prototype.lower;
+
+/**
+ * @type {*}
+ * @const
+ */
+IDBKeyRange.prototype.upper;
+
+/**
+ * @type {*}
+ * @const
+ */
+IDBKeyRange.prototype.lowerOpen;
+
+/**
+ * @type {*}
+ * @const
+ */
+IDBKeyRange.prototype.upperOpen;
+
+/**
+ * @param {IDBKeyType} value The single key value of this range.
+ * @return {!IDBKeyRange} The key range.
+ */
+IDBKeyRange.only = function(value) {};
+
+/**
+ * @param {IDBKeyType} value The single key value of this range.
+ * @return {!IDBKeyRange} The key range.
+ */
+webkitIDBKeyRange.only = function(value) {};
+
+/**
+ * @param {IDBKeyType} bound Creates a lower bound key range.
+ * @param {boolean=} open Open the key range.
+ * @return {!IDBKeyRange} The key range.
+ */
+IDBKeyRange.lowerBound = function(bound, open) {};
+
+/**
+ * @param {IDBKeyType} bound Creates a lower bound key range.
+ * @param {boolean=} open Open the key range.
+ * @return {!IDBKeyRange} The key range.
+ */
+webkitIDBKeyRange.lowerBound = function(bound, open) {};
+
+/**
+ * @param {IDBKeyType} bound Creates an upper bound key range.
+ * @param {boolean=} open Open the key range.
+ * @return {!IDBKeyRange} The key range.
+ */
+IDBKeyRange.upperBound = function(bound, open) {};
+
+/**
+ * @param {IDBKeyType} bound Creates an upper bound key range.
+ * @param {boolean=} open Open the key range.
+ * @return {!IDBKeyRange} The key range.
+ */
+webkitIDBKeyRange.upperBound = function(bound, open) {};
+
+/**
+ * @param {IDBKeyType} left The left bound value.
+ * @param {IDBKeyType} right The right bound value.
+ * @param {boolean=} openLeft Whether the left bound value should be excluded.
+ * @param {boolean=} openRight Whether the right bound value should be excluded.
+ * @return {!IDBKeyRange} The key range.
+ */
+IDBKeyRange.bound = function(left, right, openLeft, openRight) {};
+
+/**
+ * @param {IDBKeyType} left The left bound value.
+ * @param {IDBKeyType} right The right bound value.
+ * @param {boolean=} openLeft Whether the left bound value should be excluded.
+ * @param {boolean=} openRight Whether the right bound value should be excluded.
+ * @return {!IDBKeyRange} The key range.
+ */
+webkitIDBKeyRange.bound = function(left, right, openLeft, openRight) {};
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBVersionChangeEvent
+ */
+function IDBVersionChangeEvent() {}
+
+/**
+ * @type {number}
+ * @const
+ */
+IDBVersionChangeEvent.prototype.oldVersion;
+
+/**
+ * @type {?number}
+ * @const
+ */
+IDBVersionChangeEvent.prototype.newVersion;
+
+/**
+ * @constructor
+ * @extends {IDBVersionChangeEvent}
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBVersionChangeEvent
+ */
+function webkitIDBVersionChangeEvent() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+webkitIDBVersionChangeEvent.prototype.version;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_navigation_timing.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_navigation_timing.js
new file mode 100644
index 0000000000..cf0315e7e5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_navigation_timing.js
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2011 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's Navigation Timing specification.
+ *
+ * Created from
+ * @see http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
+ * @see http://w3c-test.org/webperf/specs/ResourceTiming
+ * @see http://www.w3.org/TR/performance-timeline
+ *
+ * @externs
+ */
+
+/** @constructor */
+function PerformanceTiming() {}
+/** @type {number} */ PerformanceTiming.prototype.navigationStart;
+/** @type {number} */ PerformanceTiming.prototype.unloadEventStart;
+/** @type {number} */ PerformanceTiming.prototype.unloadEventEnd;
+/** @type {number} */ PerformanceTiming.prototype.redirectStart;
+/** @type {number} */ PerformanceTiming.prototype.redirectEnd;
+/** @type {number} */ PerformanceTiming.prototype.fetchStart;
+/** @type {number} */ PerformanceTiming.prototype.domainLookupStart;
+/** @type {number} */ PerformanceTiming.prototype.domainLookupEnd;
+/** @type {number} */ PerformanceTiming.prototype.connectStart;
+/** @type {number} */ PerformanceTiming.prototype.connectEnd;
+/** @type {number} */ PerformanceTiming.prototype.secureConnectionStart;
+/** @type {number} */ PerformanceTiming.prototype.requestStart;
+/** @type {number} */ PerformanceTiming.prototype.responseStart;
+/** @type {number} */ PerformanceTiming.prototype.responseEnd;
+/** @type {number} */ PerformanceTiming.prototype.domLoading;
+/** @type {number} */ PerformanceTiming.prototype.domInteractive;
+/** @type {number} */ PerformanceTiming.prototype.domContentLoadedEventStart;
+/** @type {number} */ PerformanceTiming.prototype.domContentLoadedEventEnd;
+/** @type {number} */ PerformanceTiming.prototype.domComplete;
+/** @type {number} */ PerformanceTiming.prototype.loadEventStart;
+/** @type {number} */ PerformanceTiming.prototype.loadEventEnd;
+
+/** @constructor */
+function PerformanceEntry() {}
+/** @type {string} */ PerformanceEntry.prototype.name;
+/** @type {string} */ PerformanceEntry.prototype.entryType;
+/** @type {number} */ PerformanceEntry.prototype.startTime;
+/** @type {number} */ PerformanceEntry.prototype.duration;
+
+/**
+ * @constructor
+ * @extends {PerformanceEntry}
+ */
+function PerformanceResourceTiming() {}
+/** @type {number} */ PerformanceResourceTiming.prototype.redirectStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.redirectEnd;
+/** @type {number} */ PerformanceResourceTiming.prototype.fetchStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.domainLookupStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.domainLookupEnd;
+/** @type {number} */ PerformanceResourceTiming.prototype.connectStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.connectEnd;
+/** @type {number} */
+PerformanceResourceTiming.prototype.secureConnectionStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.requestStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.responseStart;
+/** @type {number} */ PerformanceResourceTiming.prototype.responseEnd;
+/** @type {string} */ PerformanceResourceTiming.prototype.initiatorType;
+
+/** @constructor */
+function PerformanceNavigation() {}
+/** @type {number} */ PerformanceNavigation.prototype.TYPE_NAVIGATE = 0;
+/** @type {number} */ PerformanceNavigation.prototype.TYPE_RELOAD = 1;
+/** @type {number} */ PerformanceNavigation.prototype.TYPE_BACK_FORWARD = 2;
+/** @type {number} */ PerformanceNavigation.prototype.TYPE_RESERVED = 255;
+/** @type {number} */ PerformanceNavigation.prototype.type;
+/** @type {number} */ PerformanceNavigation.prototype.redirectCount;
+
+// Only available in WebKit, and only with the --enable-memory-info flag.
+/** @constructor */
+function PerformanceMemory() {}
+/** @type {number} */ PerformanceMemory.prototype.jsHeapSizeLimit;
+/** @type {number} */ PerformanceMemory.prototype.totalJSHeapSize;
+/** @type {number} */ PerformanceMemory.prototype.usedJSHeapSize;
+
+/** @constructor */
+function Performance() {}
+/** @type {PerformanceTiming} */ Performance.prototype.timing;
+/** @type {PerformanceNavigation} */ Performance.prototype.navigation;
+
+/**
+ * Clears the buffer used to store the current list of
+ * PerformanceResourceTiming resources.
+ * @return {undefined}
+ */
+Performance.prototype.clearResourceTimings = function() {};
+
+/**
+ * Clear out the buffer of performance timing events for webkit browsers.
+ * @return {undefined}
+ */
+Performance.prototype.webkitClearResourceTimings = function() {};
+
+/**
+ * Set the maximum number of PerformanceResourceTiming resources that may be
+ * stored in the buffer.
+ * @param {number} maxSize
+ */
+Performance.prototype.setResourceTimingBufferSize = function(maxSize) {};
+
+/**
+ * @return {Array.<PerformanceEntry>} A copy of the PerformanceEntry list,
+ * in chronological order with respect to startTime.
+ * @nosideeffects
+ */
+Performance.prototype.getEntries = function() {};
+
+/**
+ * @param {string} entryType Only return {@code PerformanceEntry}s with this
+ * entryType.
+ * @return {Array.<PerformanceEntry>} A copy of the PerformanceEntry list,
+ * in chronological order with respect to startTime.
+ * @nosideeffects
+ */
+Performance.prototype.getEntriesByType = function(entryType) {};
+
+/**
+ * @param {string} name Only return {@code PerformanceEntry}s with this name.
+ * @param {string=} opt_entryType Only return {@code PerformanceEntry}s with
+ * this entryType.
+ * @return {Array.<PerformanceEntry>} PerformanceEntry list in chronological
+ * order with respect to startTime.
+ * @nosideeffects
+ */
+Performance.prototype.getEntriesByName = function(name, opt_entryType) {};
+
+// Only available in WebKit, and only with the --enable-memory-info flag.
+/** @type {PerformanceMemory} */ Performance.prototype.memory;
+
+/**
+ * @return {number}
+ * @nosideeffects
+ */
+Performance.prototype.now = function() {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ */
+Performance.prototype.webkitNow = function() {};
+
+/** @type {Performance} */
+Window.prototype.performance;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_range.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_range.js
new file mode 100644
index 0000000000..fb79fd2364
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_range.js
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's range specification.
+ * This file depends on w3c_dom2.js.
+ * The whole file has been fully type annotated.
+ * Created from
+ * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Interface
+ */
+function Range() {}
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-attr-startParent
+ */
+Range.prototype.startContainer;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-attr-startOffset
+ */
+Range.prototype.startOffset;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-attr-endParent
+ */
+Range.prototype.endContainer;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-attr-endOffset
+ */
+Range.prototype.endOffset;
+
+/**
+ * @type {boolean}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-attr-collapsed
+ */
+Range.prototype.collapsed;
+
+/**
+ * @type {Node}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-attr-commonParent
+ */
+Range.prototype.commonAncestorContainer;
+
+/**
+ * @param {Node} refNode
+ * @param {number} offset
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-setStart
+ */
+Range.prototype.setStart = function(refNode, offset) {};
+
+/**
+ * @param {Node} refNode
+ * @param {number} offset
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-setEnd
+ */
+Range.prototype.setEnd = function(refNode, offset) {};
+
+/**
+ * @param {Node} refNode
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-setStartBefore
+ */
+Range.prototype.setStartBefore = function(refNode) {};
+
+/**
+ * @param {Node} refNode
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-setStartAfter
+ */
+Range.prototype.setStartAfter = function(refNode) {};
+
+/**
+ * @param {Node} refNode
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-setEndBefore
+ */
+Range.prototype.setEndBefore = function(refNode) {};
+
+/**
+ * @param {Node} refNode
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-setEndAfter
+ */
+Range.prototype.setEndAfter = function(refNode) {};
+
+/**
+ * @param {boolean} toStart
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-collapse
+ */
+Range.prototype.collapse = function(toStart) {};
+
+/**
+ * @param {Node} refNode
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-selectNode
+ */
+Range.prototype.selectNode = function(refNode) {};
+
+/**
+ * @param {Node} refNode
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-selectNodeContents
+ */
+Range.prototype.selectNodeContents = function(refNode) {};
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-compareHow
+ */
+Range.prototype.START_TO_START = 0;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-compareHow
+ */
+Range.prototype.START_TO_END = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-compareHow
+ */
+Range.prototype.END_TO_END = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-compareHow
+ */
+Range.prototype.END_TO_START = 3;
+
+/**
+ * @param {number} how
+ * @param {Range} sourceRange
+ * @return {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-compareBoundaryPoints
+ */
+Range.prototype.compareBoundaryPoints = function(how, sourceRange) {};
+
+/**
+ * @return {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-deleteContents
+ */
+Range.prototype.deleteContents = function() {};
+
+/**
+ * @return {DocumentFragment}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-extractContents
+ */
+Range.prototype.extractContents = function() {};
+
+/**
+ * @return {DocumentFragment}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-cloneContents
+ */
+Range.prototype.cloneContents = function() {};
+
+/**
+ * @param {Node} newNode
+ * @return {DocumentFragment}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-insertNode
+ */
+Range.prototype.insertNode = function(newNode) {};
+
+/**
+ * @param {Node} newParent
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-surroundContents
+ */
+Range.prototype.surroundContents = function(newParent) {};
+
+/**
+ * @return {Range}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-clone
+ */
+Range.prototype.cloneRange = function() {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-Range-method-detach
+ */
+Range.prototype.detach = function() {};
+
+// Introduced in DOM Level 2:
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-DocumentRange-idl
+ */
+function DocumentRange() {}
+
+/**
+ * @return {Range}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-DocumentRange-method-createRange
+ */
+DocumentRange.prototype.createRange = function() {};
+
+// Introduced in DOM Level 2:
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException
+ */
+function RangeException() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeExceptionCode
+ */
+RangeException.prototype.code;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeExceptionCode
+ */
+RangeException.prototype.BAD_BOUNDARYPOINTS_ERR = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeExceptionCode
+ */
+RangeException.prototype.INVALID_NODE_TYPE_ERR = 2;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_rtc.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_rtc.js
new file mode 100644
index 0000000000..f10971f910
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_rtc.js
@@ -0,0 +1,1002 @@
+/*
+ * Copyright 2012 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for components of the WebRTC browser API.
+ * @see http://dev.w3.org/2011/webrtc/editor/webrtc.html
+ * @see http://tools.ietf.org/html/draft-ietf-rtcweb-jsep-01
+ * @see http://www.w3.org/TR/mediacapture-streams/
+ *
+ * @externs
+ * @author bemasc@google.com (Benjamin M. Schwartz)
+ */
+
+/**
+ * @typedef {string}
+ * @see {http://dev.w3.org/2011/webrtc/editor/getusermedia.html
+ * #idl-def-MediaStreamTrackState}
+ * In WebIDL this is an enum with values 'live', 'mute', and 'ended',
+ * but there is no mechanism in Closure for describing a specialization of
+ * the string type.
+ */
+var MediaStreamTrackState;
+
+/**
+ * @interface
+ */
+function SourceInfo() {}
+
+/** @const {string} */
+SourceInfo.prototype.kind;
+
+/** @const {string} */
+SourceInfo.prototype.id;
+
+/** @const {?string} */
+SourceInfo.prototype.label;
+
+/** @const {boolean} */
+SourceInfo.prototype.facing;
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/mediacapture-streams/#mediastreamtrack
+ */
+function MediaStreamTrack() {}
+
+/**
+ * @param {!function(!Array.<!SourceInfo>)} callback
+ */
+MediaStreamTrack.getSources = function(callback) {};
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStreamTrack.prototype.kind;
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStreamTrack.prototype.id;
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStreamTrack.prototype.label;
+
+/**
+ * @type {boolean}
+ */
+MediaStreamTrack.prototype.enabled;
+
+/**
+ * @type {MediaStreamTrackState}
+ * Read only.
+ */
+MediaStreamTrack.prototype.readyState;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onmute;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onunmute;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onended;
+
+/**
+ * @return {!MediaStreamTrack}
+ */
+MediaStreamTrack.prototype.clone = function() {};
+
+/** @return {void} */
+MediaStreamTrack.prototype.stop = function() {};
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @private
+ * @see http://dev.w3.org/2011/webrtc/editor/
+ * webrtc-20120720.html#mediastreamtrackevent
+ * TODO(bemasc): Update this link to the final definition once one exists
+ * (https://www.w3.org/Bugs/Public/show_bug.cgi?id=19568)
+ */
+function MediaStreamTrackEvent() {}
+
+/**
+ * @type {!MediaStreamTrack}
+ * @const
+ */
+MediaStreamTrackEvent.prototype.track;
+
+/**
+ * @param {!MediaStream|!Array.<!MediaStreamTrack>=} streamOrTracks
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://www.w3.org/TR/mediacapture-streams/#mediastream
+ */
+function MediaStream(streamOrTracks) {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+MediaStream.prototype.addEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+MediaStream.prototype.removeEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/** @override */
+MediaStream.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * TODO(bemasc): Remove this property.
+ * @deprecated
+ * @type {string}
+ * @const
+ */
+MediaStream.prototype.label;
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStream.prototype.id;
+
+/**
+ * @return {!Array.<!MediaStreamTrack>}
+ */
+MediaStream.prototype.getAudioTracks = function() {};
+
+/**
+ * @return {!Array.<!MediaStreamTrack>}
+ */
+MediaStream.prototype.getVideoTracks = function() {};
+
+/**
+ * @param {string} trackId
+ * @return {MediaStreamTrack}
+ */
+MediaStream.prototype.getTrackById = function(trackId) {};
+
+/**
+ * @param {!MediaStreamTrack} track
+ */
+MediaStream.prototype.addTrack = function(track) {};
+
+/**
+ * @param {!MediaStreamTrack} track
+ */
+MediaStream.prototype.removeTrack = function(track) {};
+
+/**
+ * @type {boolean}
+ */
+MediaStream.prototype.ended;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStream.prototype.onended;
+
+/**
+ * @type {?function(!MediaStreamTrackEvent)}
+ */
+MediaStream.prototype.onaddtrack;
+
+/**
+ * @type {?function(!MediaStreamTrackEvent)}
+ */
+MediaStream.prototype.onremovetrack;
+
+/**
+ * @deprecated
+ * TODO(bemasc): Remove this method once browsers have updated to
+ * MediaStreamTrack.stop().
+ */
+MediaStream.prototype.stop = function() {};
+
+/**
+ * @type {function(new: MediaStream,
+ * (!MediaStream|!Array.<!MediaStreamTrack>)=)}
+ */
+var webkitMediaStream;
+
+/**
+ * This interface defines the available constraint attributes. These are the
+ * attributes defined in
+ * {@see http://tools.ietf.org/html/draft-alvestrand-constraints-resolution-01}.
+ * Note that although that draft refers to "Media Constraints", the W3C uses
+ * the terms "Media[Stream|Track]Constraints" for this type, and
+ * defines a different type (for RTCPeerConnection) called "MediaConstraints".
+ *
+ * This interface type is not part of any standard, so it is marked as private.
+ * It is defined here in order to reserve the property names, which would
+ * otherwise be rewritten when the compiler processes an object literal.
+ * Several subsequent interfaces are defined in the same pattern.
+ *
+ * Note that although this list includes all the properties supported by
+ * libjingle (and hence by Chromium), browsers are permitted to offer other
+ * properties as well ({
+ * @see http://tools.ietf.org/html/draft-burnett-rtcweb-constraints-registry-02
+ * }), and browsers are expected to silently ignore unknown properties. This
+ * creates the potential for a very confusing situation in which properties
+ * not listed here are renamed by the compiler and then ignored by the browser.
+ *
+ * @interface
+ * @private
+ */
+function MediaTrackConstraintSetInterface_() {}
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.minWidth;
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.maxWidth;
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.minHeight;
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.maxHeight;
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.minAspectRatio;
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.maxAspectRatio;
+
+/**
+ * Due to a typo, this is called "minFramerate" in the -01 draft.
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.minFrameRate;
+
+/**
+ * @type {?number}
+ */
+MediaTrackConstraintSetInterface_.prototype.maxFrameRate;
+
+/**
+ * This type and two more below are defined as unions with Object because they
+ * are normally used as record types by constructing an Object literal, but all
+ * of their properties are optional.
+ * @typedef {Object|MediaTrackConstraintSetInterface_}
+ */
+var MediaTrackConstraintSet;
+
+/**
+ * @interface
+ * @private
+ */
+function MediaTrackConstraintsInterface_() {}
+
+/**
+ * @type {?MediaTrackConstraintSet}
+ */
+MediaTrackConstraintsInterface_.prototype.mandatory;
+
+/**
+ * @type {?Array.<!MediaTrackConstraintSet>}
+ */
+MediaTrackConstraintsInterface_.prototype.optional;
+
+/**
+ * @typedef {Object|MediaTrackConstraintsInterface_}
+ */
+var MediaTrackConstraints;
+
+/**
+ * @interface
+ * @private
+ */
+function MediaStreamConstraintsInterface_() {}
+
+/**
+ * @type {boolean|MediaTrackConstraints}
+ */
+MediaStreamConstraintsInterface_.prototype.audio;
+
+/**
+ * @type {boolean|MediaTrackConstraints}
+ */
+MediaStreamConstraintsInterface_.prototype.video;
+
+/**
+ * @typedef {Object|MediaStreamConstraintsInterface_}
+ */
+var MediaStreamConstraints;
+
+/**
+ * @see {http://dev.w3.org/2011/webrtc/editor/getusermedia.html#
+ * navigatorusermediaerror-and-navigatorusermediaerrorcallback}
+ * @interface
+ */
+function NavigatorUserMediaError() {}
+
+/**
+ * @type {number}
+ * @deprecated Removed from the standard and some browsers.
+ * @const
+ */
+NavigatorUserMediaError.prototype.PERMISSION_DENIED; /** 1 */
+
+/**
+ * @type {number}
+ * @deprecated Removed from the standard and some browsers.
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.code;
+
+/**
+ * @type {string}
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.name;
+
+/**
+ * @type {?string}
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.message;
+
+/**
+ * @type {?string}
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.constraintName;
+
+/**
+ * @param {MediaStreamConstraints} constraints A MediaStreamConstraints object.
+ * @param {function(!MediaStream)} successCallback
+ * A NavigatorUserMediaSuccessCallback function.
+ * @param {function(!NavigatorUserMediaError)=} errorCallback A
+ * NavigatorUserMediaErrorCallback function.
+ * @see http://dev.w3.org/2011/webrtc/editor/getusermedia.html
+ * @see http://www.w3.org/TR/mediacapture-streams/
+ */
+Navigator.prototype.webkitGetUserMedia =
+ function(constraints, successCallback, errorCallback) {};
+
+/**
+ * @param {string} type
+ * @param {!Object} eventInitDict
+ * @constructor
+ */
+function MediaStreamEvent(type, eventInitDict) {}
+
+/**
+ * @type {?MediaStream}
+ * @const
+ */
+MediaStreamEvent.prototype.stream;
+
+/**
+ * @typedef {string}
+ * @see http://www.w3.org/TR/webrtc/#rtcsdptype
+ * In WebIDL this is an enum with values 'offer', 'pranswer', and 'answer',
+ * but there is no mechanism in Closure for describing a specialization of
+ * the string type.
+ */
+var RTCSdpType;
+
+/**
+ * @param {!Object=} descriptionInitDict The RTCSessionDescriptionInit
+ * dictionary. This optional argument may have type
+ * {type:RTCSdpType, sdp:string}, but neither of these keys are required to be
+ * present, and other keys are ignored, so the closest Closure type is Object.
+ * @constructor
+ * @see http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcsessiondescription-class
+ */
+function RTCSessionDescription(descriptionInitDict) {}
+
+/**
+ * @type {?RTCSdpType}
+ * @see http://www.w3.org/TR/webrtc/#widl-RTCSessionDescription-type
+ */
+RTCSessionDescription.prototype.type;
+
+/**
+ * @type {?string}
+ * @see http://www.w3.org/TR/webrtc/#widl-RTCSessionDescription-sdp
+ */
+RTCSessionDescription.prototype.sdp;
+
+/**
+ * TODO(bemasc): Remove this definition once it is removed from the browser.
+ * @param {string} label The label index (audio/video/data -> 0,1,2)
+ * @param {string} sdp The ICE candidate in SDP text form
+ * @constructor
+ */
+function IceCandidate(label, sdp) {}
+
+/**
+ * @return {string}
+ */
+IceCandidate.prototype.toSdp = function() {};
+
+/**
+ * @type {?string}
+ */
+IceCandidate.prototype.label;
+
+/**
+ * @param {!Object=} candidateInitDict The RTCIceCandidateInit dictionary.
+ * This optional argument may have type
+ * {candidate: string, sdpMid: string, sdpMLineIndex:number}, but none of
+ * these keys are required to be present, and other keys are ignored, so the
+ * closest Closure type is Object.
+ * @constructor
+ * @see http://www.w3.org/TR/webrtc/#rtcicecandidate-type
+ */
+function RTCIceCandidate(candidateInitDict) {}
+
+/**
+ * @type {?string}
+ */
+RTCIceCandidate.prototype.candidate;
+
+/**
+ * @type {?string}
+ */
+RTCIceCandidate.prototype.sdpMid;
+
+/**
+ * @type {?number}
+ */
+RTCIceCandidate.prototype.sdpMLineIndex;
+
+/**
+ * @typedef {{url: string}}
+ * @private
+ * @see http://www.w3.org/TR/webrtc/#rtciceserver-type
+ * This dictionary type also has an optional key {credential: ?string}.
+ */
+var RTCIceServerRecord_;
+
+/**
+ * @interface
+ * @private
+ */
+function RTCIceServerInterface_() {}
+
+/**
+ * @type {string}
+ */
+RTCIceServerInterface_.prototype.url;
+
+/**
+ * @type {?string}
+ */
+RTCIceServerInterface_.prototype.credential;
+
+/**
+ * This type, and several below it, are constructed as unions between records
+ *
+ * @typedef {RTCIceServerRecord_|RTCIceServerInterface_}
+ * @private
+ */
+var RTCIceServer;
+
+/**
+ * @typedef {{iceServers: !Array.<!RTCIceServer>}}
+ * @private
+ */
+var RTCConfigurationRecord_;
+
+/**
+ * @interface
+ * @private
+ */
+function RTCConfigurationInterface_() {}
+
+/**
+ * @type {!Array.<!RTCIceServer>}
+ */
+RTCConfigurationInterface_.prototype.iceServers;
+
+/**
+ * @typedef {RTCConfigurationRecord_|RTCConfigurationInterface_}
+ */
+var RTCConfiguration;
+
+/**
+ * @typedef {function(!RTCSessionDescription)}
+ */
+var RTCSessionDescriptionCallback;
+
+/**
+ * @typedef {function(string)}
+ */
+var RTCPeerConnectionErrorCallback;
+
+/**
+ * @typedef {function()}
+ */
+var RTCVoidCallback;
+
+/**
+ * @typedef {string}
+ */
+var RTCSignalingState;
+
+/**
+ * @typedef {string}
+ */
+var RTCIceConnectionState;
+
+/**
+ * @typedef {string}
+ */
+var RTCIceGatheringState;
+
+/**
+ * @param {string} type
+ * @param {!Object} eventInitDict
+ * @constructor
+ */
+function RTCPeerConnectionIceEvent(type, eventInitDict) {}
+
+/**
+ * @type {RTCIceCandidate}
+ * @const
+ */
+RTCPeerConnectionIceEvent.prototype.candidate;
+
+// Note: The specification of RTCStats types is still under development.
+// Declarations here will be updated and removed to follow the development of
+// modern browsers, breaking compatibility with older versions as they become
+// obsolete.
+/**
+ * @interface
+ */
+function RTCStatsReport() {}
+
+/**
+ * @type {Date}
+ * @const
+ */
+RTCStatsReport.prototype.timestamp;
+
+/**
+ * @return {!Array.<!string>}
+ */
+RTCStatsReport.prototype.names = function() {};
+
+/**
+ * @param {string} name
+ * @return {string}
+ */
+RTCStatsReport.prototype.stat = function(name) {};
+
+/**
+ * @deprecated
+ * @type {RTCStatsReport}
+ * @const
+ */
+RTCStatsReport.prototype.local;
+
+/**
+ * @deprecated
+ * @type {RTCStatsReport}
+ * @const
+ */
+RTCStatsReport.prototype.remote;
+
+/**
+ * @type {string}
+ * @const
+ */
+RTCStatsReport.prototype.type;
+
+/**
+ * @type {string}
+ * @const
+ */
+RTCStatsReport.prototype.id;
+
+/**
+ * TODO(bemasc): Remove this type once it is no longer in use. It has already
+ * been removed from the specification.
+ * @typedef {RTCStatsReport}
+ * @deprecated
+ */
+var RTCStatsElement;
+
+/**
+ * @interface
+ */
+function RTCStatsResponse() {}
+
+/**
+ * @return {!Array.<!RTCStatsReport>}
+ */
+RTCStatsResponse.prototype.result = function() {};
+
+/**
+ * @typedef {function(!RTCStatsResponse, MediaStreamTrack=)}
+ */
+var RTCStatsCallback;
+
+/**
+ * This type is not yet standardized, so the properties here only represent
+ * the current capabilities of libjingle (and hence Chromium).
+ * TODO(bemasc): Add a link to the relevant standard once MediaConstraint has a
+ * standard definition.
+ *
+ * @interface
+ * @private
+ */
+function MediaConstraintSetInterface_() {}
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.OfferToReceiveAudio;
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.OfferToReceiveVideo;
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.DtlsSrtpKeyAgreement;
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.RtpDataChannels;
+
+/**
+ * TODO(bemasc): Make this type public once it is defined in a standard.
+ *
+ * @typedef {Object|MediaConstraintSetInterface_}
+ * @private
+ */
+var MediaConstraintSet_;
+
+/**
+ * @interface
+ * @private
+ */
+function MediaConstraintsInterface_() {}
+
+/**
+ * @type {?MediaConstraintSet_}
+ */
+MediaConstraintsInterface_.prototype.mandatory;
+
+/**
+ * @type {?Array.<!MediaConstraintSet_>}
+ */
+MediaConstraintsInterface_.prototype.optional;
+
+/**
+ * This type is used extensively in
+ * {@see http://dev.w3.org/2011/webrtc/editor/webrtc.html} but is not yet
+ * defined.
+ *
+ * @typedef {Object|MediaConstraintsInterface_}
+ */
+var MediaConstraints;
+
+/**
+ * @interface
+ */
+function RTCDataChannel() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+RTCDataChannel.prototype.label;
+
+/**
+ * @type {boolean}
+ * @const
+ */
+RTCDataChannel.prototype.reliable;
+
+/**
+ * An enumerated string type (RTCDataChannelState) with values:
+ * "connecting", "open", "closing", and "closed".
+ * @type {string}
+ * Read only.
+ */
+RTCDataChannel.prototype.readyState;
+
+/**
+ * @type {number}
+ * Read only.
+ */
+RTCDataChannel.prototype.bufferedAmount;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCDataChannel.prototype.onopen;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCDataChannel.prototype.onerror;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCDataChannel.prototype.onclose;
+
+RTCDataChannel.prototype.close = function() {};
+
+/**
+ * @type {?function(!MessageEvent.<*>)}
+ */
+RTCDataChannel.prototype.onmessage;
+
+/**
+ * @type {string}
+ */
+RTCDataChannel.prototype.binaryType;
+
+/**
+ * @param {string|!Blob|!ArrayBuffer|!ArrayBufferView} data
+ */
+RTCDataChannel.prototype.send = function(data) {};
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @private
+ */
+function RTCDataChannelEvent() {}
+
+/**
+ * @type {!RTCDataChannel}
+ * Read only.
+ */
+RTCDataChannelEvent.prototype.channel;
+
+/**
+ * @typedef {{reliable: boolean}}
+ */
+var RTCDataChannelInitRecord_;
+
+/**
+ * @interface
+ * @private
+ */
+function RTCDataChannelInitInterface_() {}
+
+/**
+ * @type {boolean}
+ */
+RTCDataChannelInitInterface_.prototype.reliable;
+
+/**
+ * @typedef {RTCDataChannelInitInterface_|RTCDataChannelInitRecord_}
+ */
+var RTCDataChannelInit;
+
+/**
+ * @param {RTCConfiguration} configuration
+ * @param {!MediaConstraints=} constraints
+ * @constructor
+ * @implements {EventTarget}
+ */
+function RTCPeerConnection(configuration, constraints) {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+RTCPeerConnection.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+RTCPeerConnection.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/** @override */
+RTCPeerConnection.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @param {!RTCSessionDescriptionCallback} successCallback
+ * @param {!RTCPeerConnectionErrorCallback=} failureCallback
+ * @param {!MediaConstraints=} constraints
+ */
+RTCPeerConnection.prototype.createOffer = function(successCallback,
+ failureCallback, constraints) {};
+
+/**
+ * @param {RTCSessionDescriptionCallback} successCallback
+ * @param {?RTCPeerConnectionErrorCallback=} failureCallback
+ * @param {!MediaConstraints=} constraints
+ */
+RTCPeerConnection.prototype.createAnswer = function(successCallback,
+ failureCallback, constraints) {};
+
+/**
+ * @param {!RTCSessionDescription} description
+ * @param {!RTCVoidCallback=} successCallback
+ * @param {!RTCPeerConnectionErrorCallback=} failureCallback
+ */
+RTCPeerConnection.prototype.setLocalDescription = function(description,
+ successCallback, failureCallback) {};
+
+/**
+ * @param {!RTCSessionDescription} description
+ * @param {!RTCVoidCallback=} successCallback
+ * @param {!RTCPeerConnectionErrorCallback=} failureCallback
+ */
+RTCPeerConnection.prototype.setRemoteDescription = function(description,
+ successCallback, failureCallback) {};
+
+/**
+ * @type {?RTCSessionDescription}
+ * Read only.
+ */
+RTCPeerConnection.prototype.localDescription;
+
+/**
+ * @type {?RTCSessionDescription}
+ * Read only.
+ */
+RTCPeerConnection.prototype.remoteDescription;
+
+/**
+ * @type {RTCSignalingState}
+ * Read only.
+ */
+RTCPeerConnection.prototype.signalingState;
+
+/**
+ * @param {?RTCConfiguration=} configuration
+ * @param {?MediaConstraints=} constraints
+ */
+RTCPeerConnection.prototype.updateIce = function(configuration, constraints) {};
+
+/**
+ * @param {!RTCIceCandidate} candidate
+ */
+RTCPeerConnection.prototype.addIceCandidate = function(candidate) {};
+
+/**
+ * @type {!RTCIceGatheringState}
+ * Read only.
+ */
+RTCPeerConnection.prototype.iceGatheringState;
+
+/**
+ * @type {!RTCIceConnectionState}
+ * Read only.
+ */
+RTCPeerConnection.prototype.iceConnectionState;
+
+/**
+ * @return {!Array.<!MediaStream>}
+ */
+RTCPeerConnection.prototype.getLocalStreams = function() {};
+
+/**
+ * @return {!Array.<!MediaStream>}
+ */
+RTCPeerConnection.prototype.getRemoteStreams = function() {};
+
+/**
+ * @param {string} streamId
+ * @return {MediaStream}
+ */
+RTCPeerConnection.prototype.getStreamById = function(streamId) {};
+
+/**
+ * @param {?string} label
+ * @param {RTCDataChannelInit=} dataChannelDict
+ * @return {!RTCDataChannel}
+ */
+RTCPeerConnection.prototype.createDataChannel =
+ function(label, dataChannelDict) {};
+/**
+ * @param {!MediaStream} stream
+ * @param {!MediaConstraints=} constraints
+ */
+RTCPeerConnection.prototype.addStream = function(stream, constraints) {};
+
+/**
+ * @param {!MediaStream} stream
+ */
+RTCPeerConnection.prototype.removeStream = function(stream) {};
+
+// TODO(bemasc): Add identity provider stuff once implementations exist
+
+/**
+ * @param {!RTCStatsCallback} successCallback
+ * @param {MediaStreamTrack=} selector
+ */
+RTCPeerConnection.prototype.getStats = function(successCallback, selector) {};
+
+RTCPeerConnection.prototype.close = function() {};
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCPeerConnection.prototype.onnegotiationneeded;
+
+/**
+ * @type {?function(!RTCPeerConnectionIceEvent)}
+ */
+RTCPeerConnection.prototype.onicecandidate;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCPeerConnection.prototype.onsignalingstatechange;
+
+/**
+ * @type {?function(!MediaStreamEvent)}
+ */
+RTCPeerConnection.prototype.onaddstream;
+
+/**
+ * @type {?function(!MediaStreamEvent)}
+ */
+RTCPeerConnection.prototype.onremovestream;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCPeerConnection.prototype.oniceconnectionstatechange;
+
+/**
+ * @type {?function(!RTCDataChannelEvent)}
+ */
+RTCPeerConnection.prototype.ondatachannel;
+
+/**
+ * @type {function(new: RTCPeerConnection, RTCConfiguration,
+ * !MediaConstraints=)}
+ */
+var webkitRTCPeerConnection;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_selectors.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_selectors.js
new file mode 100644
index 0000000000..546dec9ce0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_selectors.js
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's Selectors API.
+ * This file depends on w3c_dom1.js.
+ * @see http://www.w3.org/TR/selectors-api2/
+ *
+ * @externs
+ */
+
+/**
+ * @param {string} selectors
+ * @return {Element}
+ * @override
+ */
+Document.prototype.querySelector = function(selectors) {};
+
+/**
+ * @param {string} selectors
+ * @return {!NodeList}
+ * @override
+ */
+Document.prototype.querySelectorAll = function(selectors) {};
+
+/**
+ * @param {string} selectors
+ * @return {Element}
+ * @override
+ */
+Element.prototype.querySelector = function(selectors) {};
+
+/**
+ * @param {string} selectors
+ * @return {!NodeList}
+ * @override
+ */
+Element.prototype.querySelectorAll = function(selectors) {};
+
+/**
+ * https://dom.spec.whatwg.org/#dom-element-matches
+ * https://developer.mozilla.org/en-US/docs/Web/API/Element.matches
+ * @param {string} selectors
+ * @return {boolean}
+ */
+Element.prototype.matches = function(selectors) {};
+
+/**
+ * @param {string} selectors
+ * @param {(Node|NodeList)=} refNodes
+ * @return {boolean}
+ */
+Element.prototype.matchesSelector = function(selectors, refNodes) {};
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/Node.mozMatchesSelector
+ * @param {string} selectors
+ * @return {boolean}
+ */
+Element.prototype.mozMatchesSelector = function(selectors) {};
+
+/**
+ * @see http://developer.apple.com/library/safari/documentation/WebKit/Reference/ElementClassRef/Element/Element.html
+ * @param {string} selectors
+ * @return {boolean}
+ */
+Element.prototype.webkitMatchesSelector = function(selectors) {};
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/ff975201.aspx
+ * @param {string} selectors
+ * @return {boolean}
+ */
+Element.prototype.msMatchesSelector = function(selectors) {};
+
+/**
+ * @see http://www.opera.com/docs/changelogs/windows/1150/
+ * @param {string} selectors
+ * @return {boolean}
+ */
+Element.prototype.oMatchesSelector = function(selectors) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_xml.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_xml.js
new file mode 100644
index 0000000000..7dadd24268
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/w3c_xml.js
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's XML related specifications.
+ * This file depends on w3c_dom2.js.
+ * The whole file has been fully type annotated.
+ *
+ * Provides the XML standards from W3C.
+ * Includes:
+ * XPath - Fully type annotated
+ * XMLHttpRequest - Fully type annotated
+ *
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html
+ * @see http://www.w3.org/TR/XMLHttpRequest/
+ * @see http://www.w3.org/TR/XMLHttpRequest2/
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathException
+ */
+function XPathException() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#INVALID_EXPRESSION_ERR
+ */
+XPathException.INVALID_EXPRESSION_ERR = 52;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#TYPE_ERR
+ */
+XPathException.TYPE_ERR = 52;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#
+ */
+XPathException.prototype.code;
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator
+ */
+function XPathEvaluator() {}
+
+/**
+ * @param {string} expr
+ * @param {?XPathNSResolver=} opt_resolver
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-createExpression
+ * @throws XPathException
+ * @throws DOMException
+ */
+XPathEvaluator.prototype.createExpression = function(expr, opt_resolver) {};
+
+/**
+ * @param {Node} nodeResolver
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-createNSResolver
+ */
+XPathEvaluator.prototype.createNSResolver = function(nodeResolver) {};
+
+/**
+ * @param {string} expr
+ * @param {Node} contextNode
+ * @param {?XPathNSResolver=} opt_resolver
+ * @param {?number=} opt_type
+ * @param {*=} opt_result
+ * @return {XPathResult}
+ * @throws XPathException
+ * @throws DOMException
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-evaluate
+ */
+XPathEvaluator.prototype.evaluate = function(expr, contextNode, opt_resolver,
+ opt_type, opt_result) {};
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathExpression
+ */
+function XPathExpression() {}
+
+/**
+ * @param {Node} contextNode
+ * @param {number=} opt_type
+ * @param {*=} opt_result
+ * @return {*}
+ * @throws XPathException
+ * @throws DOMException
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathExpression-evaluate
+ */
+XPathExpression.prototype.evaluate = function(contextNode, opt_type,
+ opt_result) {};
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathNSResolver
+ */
+function XPathNSResolver() {}
+
+/**
+ * @param {string} prefix
+ * @return {?string}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathNSResolver-lookupNamespaceURI
+ */
+XPathNSResolver.prototype.lookupNamespaceURI = function(prefix) {};
+
+/**
+ * From http://www.w3.org/TR/xpath
+ *
+ * XPath is a language for addressing parts of an XML document, designed to be
+ * used by both XSLT and XPointer.
+ *
+ * @noalias
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult
+ */
+function XPathResult() {}
+
+/**
+ * @type {boolean} {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-booleanValue
+ */
+XPathResult.prototype.booleanValue;
+
+/**
+ * @type {boolean} {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-invalid-iterator-state
+ */
+XPathResult.prototype.invalidInteratorState;
+
+/**
+ * @type {number}
+ * @throws XPathException {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-numberValue
+ */
+XPathResult.prototype.numberValue;
+
+/**
+ * @type {number}
+ * @throws XPathException {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-resultType
+ */
+XPathResult.prototype.resultType;
+
+/**
+ * @type {Node}
+ * @throws XPathException {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-singleNodeValue
+ */
+XPathResult.prototype.singleNodeValue;
+
+/**
+ * @type {number}
+ * @throws XPathException {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-snapshot-length
+ */
+XPathResult.prototype.snapshotLength;
+
+/**
+ * @type {string}
+ * @throws XPathException {@see XPathException.TYPE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-stringValue
+ */
+XPathResult.prototype.stringValue;
+
+/**
+ * @return {Node}
+ * @throws XPathException {@see XPathException.TYPE_ERR}
+ * @throws DOMException {@see DOMException.INVALID_STATE_ERR}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-iterateNext
+ */
+XPathResult.prototype.iterateNext = function() {};
+
+/**
+ * @param {number} index
+ * @return {Node}
+ * @throws XPathException
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-snapshotItem
+ */
+XPathResult.prototype.snapshotItem = function(index) {};
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-ANY-TYPE
+ */
+XPathResult.ANY_TYPE = 0;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-NUMBER-TYPE
+ */
+XPathResult.NUMBER_TYPE = 1;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-STRING-TYPE
+ */
+XPathResult.STRING_TYPE = 2;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-BOOLEAN-TYPE
+ */
+XPathResult.BOOLEAN_TYPE = 3;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-UNORDERED-NODE-ITERATOR-TYPE
+ */
+XPathResult.UNORDERED_NODE_ITERATOR_TYPE = 4;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-ORDERED-NODE-ITERATOR-TYPE
+ */
+XPathResult.ORDERED_NODE_ITERATOR_TYPE = 5;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-UNORDERED-NODE-SNAPSHOT-TYPE
+ */
+XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE = 6;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-ORDERED-NODE-SNAPSHOT-TYPE
+ */
+XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 7;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-ANY-UNORDERED-NODE-TYPE
+ */
+XPathResult.ANY_UNORDERED_NODE_TYPE = 8;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult-FIRST-ORDERED-NODE-TYPE
+ */
+XPathResult.FIRST_ORDERED_NODE_TYPE = 9;
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathNamespace
+ */
+function XPathNamespace() {}
+
+/**
+ * @type {Element}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathNamespace-ownerElement
+ */
+XPathNamespace.prototype.ownerElement;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPATH_NAMESPACE_NODE
+ */
+XPathNamespace.XPATH_NAMESPACE_NODE = 13;
+
+/**
+ * From http://www.w3.org/TR/XMLHttpRequest/
+ *
+ * (Draft)
+ *
+ * The XMLHttpRequest Object specification defines an API that provides
+ * scripted client functionality for transferring data between a client and a
+ * server.
+ *
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#xmlhttprequest-object
+ */
+function XMLHttpRequest() {}
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+XMLHttpRequest.prototype.addEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+XMLHttpRequest.prototype.removeEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/** @override */
+XMLHttpRequest.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @param {string} method
+ * @param {string} url
+ * @param {?boolean=} opt_async
+ * @param {?string=} opt_user
+ * @param {?string=} opt_password
+ * @return {undefined}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-open()-method
+ */
+XMLHttpRequest.prototype.open = function(method, url, opt_async, opt_user,
+ opt_password) {};
+
+/**
+ * @param {string} header
+ * @param {string} value
+ * @return {undefined}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method
+ */
+XMLHttpRequest.prototype.setRequestHeader = function(header, value) {};
+
+/**
+ * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=} opt_data
+ * @return {undefined}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-send()-method
+ */
+XMLHttpRequest.prototype.send = function(opt_data) {};
+
+/**
+ * @return {undefined}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-abort()-method
+ */
+XMLHttpRequest.prototype.abort = function() {};
+
+/**
+ * @return {string}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders()-method
+ */
+XMLHttpRequest.prototype.getAllResponseHeaders = function() {};
+
+/**
+ * @param {string} header
+ * @return {string}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
+ */
+XMLHttpRequest.prototype.getResponseHeader = function(header) {};
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute
+ */
+XMLHttpRequest.prototype.responseText;
+
+/**
+ * @type {Document}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsexml-attribute
+ */
+XMLHttpRequest.prototype.responseXML;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-readystate-attribute
+ */
+XMLHttpRequest.prototype.readyState;
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute
+ */
+XMLHttpRequest.prototype.status;
+
+/**
+ * @type {string}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#the-statustext-attribute
+ */
+XMLHttpRequest.prototype.statusText;
+
+/**
+ * @type {Function}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#handler-xhr-onreadystatechange
+ */
+XMLHttpRequest.prototype.onreadystatechange;
+
+/**
+ * @type {Function}
+ * @see http://www.w3.org/TR/XMLHttpRequest/#handler-xhr-onerror
+ */
+XMLHttpRequest.prototype.onerror;
+
+/**
+ * The FormData object represents an ordered collection of entries. Each entry
+ * has a name and value.
+ *
+ * @param {?Element=} opt_form An optional form to use for constructing the form
+ * data set.
+ * @constructor
+ * @see http://www.w3.org/TR/XMLHttpRequest2/#the-formdata-interface
+ */
+function FormData(opt_form) {}
+
+/**
+ * @param {string} name
+ * @param {Blob|string} value
+ */
+FormData.prototype.append = function(name, value) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_css.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_css.js
new file mode 100644
index 0000000000..60841f8e26
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_css.js
@@ -0,0 +1,456 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for WebKit's custom CSS properties. Copied from:
+ * {@link
+ * http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSPropertyNames.in}
+ *
+ * If you make changes to this file, notice that every property appears
+ * twice: once as an uppercase name and once as a lowercase name.
+ * WebKit allows both. The uppercase version is preferred.
+ *
+ * @externs
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+/** @type {string} */ CSSProperties.prototype.WebkitAlignContent;
+/** @type {string} */ CSSProperties.prototype.WebkitAlignItems;
+/** @type {string} */ CSSProperties.prototype.WebkitAlignSelf;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimation;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationDelay;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationDirection;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationDuration;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationFillMode;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationIterationCount;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationName;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationPlayState;
+/** @type {string} */ CSSProperties.prototype.WebkitAnimationTimingFunction;
+/** @type {string} */ CSSProperties.prototype.WebkitAppearance;
+/** @type {string} */ CSSProperties.prototype.WebkitAppRegion;
+/** @type {string} */ CSSProperties.prototype.WebkitAspectRatio;
+/** @type {string} */ CSSProperties.prototype.WebkitBackfaceVisibility;
+/** @type {string} */ CSSProperties.prototype.WebkitBackgroundClip;
+/** @type {string} */ CSSProperties.prototype.WebkitBackgroundComposite;
+/** @type {string} */ CSSProperties.prototype.WebkitBackgroundOrigin;
+/** @type {string} */ CSSProperties.prototype.WebkitBackgroundSize;
+/** @type {string} */ CSSProperties.prototype.WebkitBinding;
+/** @type {string} */ CSSProperties.prototype.WebkitBlendMode;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderAfter;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderAfterColor;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderAfterStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderAfterWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderBefore;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderBeforeColor;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderBeforeStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderBeforeWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderBottomLeftRadius;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderBottomRightRadius;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderEnd;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderEndColor;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderEndStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderEndWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderFit;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderHorizontalSpacing;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderImage;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderRadius;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderStart;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderStartColor;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderStartStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderStartWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderTopLeftRadius;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderTopRightRadius;
+/** @type {string} */ CSSProperties.prototype.WebkitBorderVerticalSpacing;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxAlign;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxDecorationBreak;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxDirection;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxFlex;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxFlexGroup;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxLines;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxOrdinalGroup;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxOrient;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxPack;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxReflect;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxShadow;
+/** @type {string} */ CSSProperties.prototype.WebkitBoxSizing;
+/** @type {string} */ CSSProperties.prototype.WebkitColorCorrection;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnAxis;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnBreakAfter;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnBreakBefore;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnBreakInside;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnCount;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnGap;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnProgression;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnRule;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnRuleColor;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnRuleStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnRuleWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitColumns;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnSpan;
+/** @type {string} */ CSSProperties.prototype.WebkitColumnWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitDashboardRegion;
+/** @type {string} */ CSSProperties.prototype.WebkitFilter;
+/** @type {string} */ CSSProperties.prototype.WebkitFlex;
+/** @type {string} */ CSSProperties.prototype.WebkitFlexBasis;
+/** @type {string} */ CSSProperties.prototype.WebkitFlexDirection;
+/** @type {string} */ CSSProperties.prototype.WebkitFlexFlow;
+/** @type {string} */ CSSProperties.prototype.WebkitFlexGrow;
+/** @type {string} */ CSSProperties.prototype.WebkitFlexShrink;
+/** @type {string} */ CSSProperties.prototype.WebkitFlexWrap;
+/** @type {string} */ CSSProperties.prototype.WebkitFlowFrom;
+/** @type {string} */ CSSProperties.prototype.WebkitFlowInto;
+/** @type {string} */ CSSProperties.prototype.WebkitFontSizeDelta;
+/** @type {string} */ CSSProperties.prototype.WebkitFontSmoothing;
+/** @type {string} */ CSSProperties.prototype.WebkitGridColumn;
+/** @type {string} */ CSSProperties.prototype.WebkitGridColumns;
+/** @type {string} */ CSSProperties.prototype.WebkitGridRow;
+/** @type {string} */ CSSProperties.prototype.WebkitGridRows;
+/** @type {string} */ CSSProperties.prototype.WebkitHighlight;
+/** @type {string} */ CSSProperties.prototype.WebkitHyphenateCharacter;
+/** @type {string} */ CSSProperties.prototype.WebkitHyphenateLimitAfter;
+/** @type {string} */ CSSProperties.prototype.WebkitHyphenateLimitBefore;
+/** @type {string} */ CSSProperties.prototype.WebkitHyphenateLimitLines;
+/** @type {string} */ CSSProperties.prototype.WebkitHyphens;
+/** @type {string} */ CSSProperties.prototype.WebkitJustifyContent;
+/** @type {string} */ CSSProperties.prototype.WebkitLineAlign;
+/** @type {string} */ CSSProperties.prototype.WebkitLineBoxContain;
+/** @type {string} */ CSSProperties.prototype.WebkitLineBreak;
+/** @type {string} */ CSSProperties.prototype.WebkitLineClamp;
+/** @type {string} */ CSSProperties.prototype.WebkitLineGrid;
+/** @type {string} */ CSSProperties.prototype.WebkitLineSnap;
+/** @type {string} */ CSSProperties.prototype.WebkitLocale;
+/** @type {string} */ CSSProperties.prototype.WebkitLogicalHeight;
+/** @type {string} */ CSSProperties.prototype.WebkitLogicalWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginAfter;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginAfterCollapse;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginBefore;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginBeforeCollapse;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginBottomCollapse;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginCollapse;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginEnd;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginStart;
+/** @type {string} */ CSSProperties.prototype.WebkitMarginTopCollapse;
+/** @type {string} */ CSSProperties.prototype.WebkitMarquee;
+/** @type {string} */ CSSProperties.prototype.WebkitMarqueeDirection;
+/** @type {string} */ CSSProperties.prototype.WebkitMarqueeIncrement;
+/** @type {string} */ CSSProperties.prototype.WebkitMarqueeRepetition;
+/** @type {string} */ CSSProperties.prototype.WebkitMarqueeSpeed;
+/** @type {string} */ CSSProperties.prototype.WebkitMarqueeStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitMask;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskAttachment;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImage;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageOutset;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageRepeat;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageSlice;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageSource;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskClip;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskComposite;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskImage;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskOrigin;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskPosition;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskPositionX;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskPositionY;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskRepeat;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskRepeatX;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskRepeatY;
+/** @type {string} */ CSSProperties.prototype.WebkitMaskSize;
+/** @type {string} */
+CSSProperties.prototype.WebkitMatchNearestMailBlockquoteColor;
+/** @type {string} */ CSSProperties.prototype.WebkitMaxLogicalHeight;
+/** @type {string} */ CSSProperties.prototype.WebkitMaxLogicalWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitMinLogicalHeight;
+/** @type {string} */ CSSProperties.prototype.WebkitMinLogicalWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitNbspMode;
+/** @type {string} */ CSSProperties.prototype.WebkitOrder;
+/** @type {string} */ CSSProperties.prototype.WebkitOverflowScrolling;
+/** @type {string} */ CSSProperties.prototype.WebkitPaddingAfter;
+/** @type {string} */ CSSProperties.prototype.WebkitPaddingBefore;
+/** @type {string} */ CSSProperties.prototype.WebkitPaddingEnd;
+/** @type {string} */ CSSProperties.prototype.WebkitPaddingStart;
+/** @type {string} */ CSSProperties.prototype.WebkitPerspective;
+/** @type {string} */ CSSProperties.prototype.WebkitPerspectiveOrigin;
+/** @type {string} */ CSSProperties.prototype.WebkitPerspectiveOriginX;
+/** @type {string} */ CSSProperties.prototype.WebkitPerspectiveOriginY;
+/** @type {string} */ CSSProperties.prototype.WebkitPrintColorAdjust;
+/** @type {string} */ CSSProperties.prototype.WebkitRegionBreakAfter;
+/** @type {string} */ CSSProperties.prototype.WebkitRegionBreakBefore;
+/** @type {string} */ CSSProperties.prototype.WebkitRegionBreakInside;
+/** @type {string} */ CSSProperties.prototype.WebkitRegionOverflow;
+/** @type {string} */ CSSProperties.prototype.WebkitRtlOrdering;
+/** @type {string} */ CSSProperties.prototype.WebkitRubyPosition;
+/** @type {string} */ CSSProperties.prototype.WebkitShapeInside;
+/** @type {string} */ CSSProperties.prototype.WebkitShapeMargin;
+/** @type {string} */ CSSProperties.prototype.WebkitShapeOutside;
+/** @type {string} */ CSSProperties.prototype.WebkitShapePadding;
+/** @type {string} */ CSSProperties.prototype.WebkitTapHighlightColor;
+/** @type {string} */ CSSProperties.prototype.WebkitTextAlignLast;
+/** @type {string} */ CSSProperties.prototype.WebkitTextCombine;
+/** @type {string} */ CSSProperties.prototype.WebkitTextDecorationLine;
+/** @type {string} */ CSSProperties.prototype.WebkitTextDecorationsInEffect;
+/** @type {string} */ CSSProperties.prototype.WebkitTextDecorationStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasis;
+/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasisColor;
+/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasisPosition;
+/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasisStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitTextFillColor;
+/** @type {string} */ CSSProperties.prototype.WebkitTextOrientation;
+/** @type {string} */ CSSProperties.prototype.WebkitTextSecurity;
+/** @type {string} */ CSSProperties.prototype.WebkitTextSizeAdjust;
+/** @type {string} */ CSSProperties.prototype.WebkitTextStroke;
+/** @type {string} */ CSSProperties.prototype.WebkitTextStrokeColor;
+/** @type {string} */ CSSProperties.prototype.WebkitTextStrokeWidth;
+/** @type {string} */ CSSProperties.prototype.WebkitTransform;
+/** @type {string} */ CSSProperties.prototype.WebkitTransformOrigin;
+/** @type {string} */ CSSProperties.prototype.WebkitTransformOriginX;
+/** @type {string} */ CSSProperties.prototype.WebkitTransformOriginY;
+/** @type {string} */ CSSProperties.prototype.WebkitTransformOriginZ;
+/** @type {string} */ CSSProperties.prototype.WebkitTransformStyle;
+/** @type {string} */ CSSProperties.prototype.WebkitTransition;
+/** @type {string} */ CSSProperties.prototype.WebkitTransitionDelay;
+/** @type {string} */ CSSProperties.prototype.WebkitTransitionDuration;
+/** @type {string} */ CSSProperties.prototype.WebkitTransitionProperty;
+/** @type {string} */ CSSProperties.prototype.WebkitTransitionRepeatCount;
+/** @type {string} */ CSSProperties.prototype.WebkitTransitionTimingFunction;
+/** @type {string} */ CSSProperties.prototype.WebkitUserDrag;
+/** @type {string} */ CSSProperties.prototype.WebkitUserModify;
+/** @type {string} */ CSSProperties.prototype.WebkitUserSelect;
+/** @type {string} */ CSSProperties.prototype.WebkitWrap;
+/** @type {string} */ CSSProperties.prototype.WebkitWrapFlow;
+/** @type {string} */ CSSProperties.prototype.WebkitWrapThrough;
+/** @type {string} */ CSSProperties.prototype.WebkitWritingMode;
+
+// WebKit also adds bindings for the lowercase versions of these properties.
+// The uppercase version is preferred.
+
+/** @type {string} */ CSSProperties.prototype.webkitAlignContent;
+/** @type {string} */ CSSProperties.prototype.webkitAlignItems;
+/** @type {string} */ CSSProperties.prototype.webkitAlignSelf;
+/** @type {string} */ CSSProperties.prototype.webkitAnimation;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationDelay;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationDirection;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationDuration;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationFillMode;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationIterationCount;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationName;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationPlayState;
+/** @type {string} */ CSSProperties.prototype.webkitAnimationTimingFunction;
+/** @type {string} */ CSSProperties.prototype.webkitAppearance;
+/** @type {string} */ CSSProperties.prototype.webkitAppRegion;
+/** @type {string} */ CSSProperties.prototype.webkitAspectRatio;
+/** @type {string} */ CSSProperties.prototype.webkitBackfaceVisibility;
+/** @type {string} */ CSSProperties.prototype.webkitBackgroundClip;
+/** @type {string} */ CSSProperties.prototype.webkitBackgroundComposite;
+/** @type {string} */ CSSProperties.prototype.webkitBackgroundOrigin;
+/** @type {string} */ CSSProperties.prototype.webkitBackgroundSize;
+/** @type {string} */ CSSProperties.prototype.webkitBinding;
+/** @type {string} */ CSSProperties.prototype.webkitBlendMode;
+/** @type {string} */ CSSProperties.prototype.webkitBorderAfter;
+/** @type {string} */ CSSProperties.prototype.webkitBorderAfterColor;
+/** @type {string} */ CSSProperties.prototype.webkitBorderAfterStyle;
+/** @type {string} */ CSSProperties.prototype.webkitBorderAfterWidth;
+/** @type {string} */ CSSProperties.prototype.webkitBorderBefore;
+/** @type {string} */ CSSProperties.prototype.webkitBorderBeforeColor;
+/** @type {string} */ CSSProperties.prototype.webkitBorderBeforeStyle;
+/** @type {string} */ CSSProperties.prototype.webkitBorderBeforeWidth;
+/** @type {string} */ CSSProperties.prototype.webkitBorderBottomLeftRadius;
+/** @type {string} */ CSSProperties.prototype.webkitBorderBottomRightRadius;
+/** @type {string} */ CSSProperties.prototype.webkitBorderEnd;
+/** @type {string} */ CSSProperties.prototype.webkitBorderEndColor;
+/** @type {string} */ CSSProperties.prototype.webkitBorderEndStyle;
+/** @type {string} */ CSSProperties.prototype.webkitBorderEndWidth;
+/** @type {string} */ CSSProperties.prototype.webkitBorderFit;
+/** @type {string} */ CSSProperties.prototype.webkitBorderHorizontalSpacing;
+/** @type {string} */ CSSProperties.prototype.webkitBorderImage;
+/** @type {string} */ CSSProperties.prototype.webkitBorderRadius;
+/** @type {string} */ CSSProperties.prototype.webkitBorderStart;
+/** @type {string} */ CSSProperties.prototype.webkitBorderStartColor;
+/** @type {string} */ CSSProperties.prototype.webkitBorderStartStyle;
+/** @type {string} */ CSSProperties.prototype.webkitBorderStartWidth;
+/** @type {string} */ CSSProperties.prototype.webkitBorderTopLeftRadius;
+/** @type {string} */ CSSProperties.prototype.webkitBorderTopRightRadius;
+/** @type {string} */ CSSProperties.prototype.webkitBorderVerticalSpacing;
+/** @type {string} */ CSSProperties.prototype.webkitBoxAlign;
+/** @type {string} */ CSSProperties.prototype.webkitBoxDecorationBreak;
+/** @type {string} */ CSSProperties.prototype.webkitBoxDirection;
+/** @type {string} */ CSSProperties.prototype.webkitBoxFlex;
+/** @type {string} */ CSSProperties.prototype.webkitBoxFlexGroup;
+/** @type {string} */ CSSProperties.prototype.webkitBoxLines;
+/** @type {string} */ CSSProperties.prototype.webkitBoxOrdinalGroup;
+/** @type {string} */ CSSProperties.prototype.webkitBoxOrient;
+/** @type {string} */ CSSProperties.prototype.webkitBoxPack;
+/** @type {string} */ CSSProperties.prototype.webkitBoxReflect;
+/** @type {string} */ CSSProperties.prototype.webkitBoxShadow;
+/** @type {string} */ CSSProperties.prototype.webkitBoxSizing;
+/** @type {string} */ CSSProperties.prototype.webkitColorCorrection;
+/** @type {string} */ CSSProperties.prototype.webkitColumnAxis;
+/** @type {string} */ CSSProperties.prototype.webkitColumnBreakAfter;
+/** @type {string} */ CSSProperties.prototype.webkitColumnBreakBefore;
+/** @type {string} */ CSSProperties.prototype.webkitColumnBreakInside;
+/** @type {string} */ CSSProperties.prototype.webkitColumnCount;
+/** @type {string} */ CSSProperties.prototype.webkitColumnGap;
+/** @type {string} */ CSSProperties.prototype.webkitColumnProgression;
+/** @type {string} */ CSSProperties.prototype.webkitColumnRule;
+/** @type {string} */ CSSProperties.prototype.webkitColumnRuleColor;
+/** @type {string} */ CSSProperties.prototype.webkitColumnRuleStyle;
+/** @type {string} */ CSSProperties.prototype.webkitColumnRuleWidth;
+/** @type {string} */ CSSProperties.prototype.webkitColumns;
+/** @type {string} */ CSSProperties.prototype.webkitColumnSpan;
+/** @type {string} */ CSSProperties.prototype.webkitColumnWidth;
+/** @type {string} */ CSSProperties.prototype.webkitDashboardRegion;
+/** @type {string} */ CSSProperties.prototype.webkitFilter;
+/** @type {string} */ CSSProperties.prototype.webkitFlex;
+/** @type {string} */ CSSProperties.prototype.webkitFlexBasis;
+/** @type {string} */ CSSProperties.prototype.webkitFlexDirection;
+/** @type {string} */ CSSProperties.prototype.webkitFlexFlow;
+/** @type {string} */ CSSProperties.prototype.webkitFlexGrow;
+/** @type {string} */ CSSProperties.prototype.webkitFlexShrink;
+/** @type {string} */ CSSProperties.prototype.webkitFlexWrap;
+/** @type {string} */ CSSProperties.prototype.webkitFlowFrom;
+/** @type {string} */ CSSProperties.prototype.webkitFlowInto;
+/** @type {string} */ CSSProperties.prototype.webkitFontSizeDelta;
+/** @type {string} */ CSSProperties.prototype.webkitFontSmoothing;
+/** @type {string} */ CSSProperties.prototype.webkitGridColumn;
+/** @type {string} */ CSSProperties.prototype.webkitGridColumns;
+/** @type {string} */ CSSProperties.prototype.webkitGridRow;
+/** @type {string} */ CSSProperties.prototype.webkitGridRows;
+/** @type {string} */ CSSProperties.prototype.webkitHighlight;
+/** @type {string} */ CSSProperties.prototype.webkitHyphenateCharacter;
+/** @type {string} */ CSSProperties.prototype.webkitHyphenateLimitAfter;
+/** @type {string} */ CSSProperties.prototype.webkitHyphenateLimitBefore;
+/** @type {string} */ CSSProperties.prototype.webkitHyphenateLimitLines;
+/** @type {string} */ CSSProperties.prototype.webkitHyphens;
+/** @type {string} */ CSSProperties.prototype.webkitJustifyContent;
+/** @type {string} */ CSSProperties.prototype.webkitLineAlign;
+/** @type {string} */ CSSProperties.prototype.webkitLineBoxContain;
+/** @type {string} */ CSSProperties.prototype.webkitLineBreak;
+/** @type {string} */ CSSProperties.prototype.webkitLineClamp;
+/** @type {string} */ CSSProperties.prototype.webkitLineGrid;
+/** @type {string} */ CSSProperties.prototype.webkitLineSnap;
+/** @type {string} */ CSSProperties.prototype.webkitLocale;
+/** @type {string} */ CSSProperties.prototype.webkitLogicalHeight;
+/** @type {string} */ CSSProperties.prototype.webkitLogicalWidth;
+/** @type {string} */ CSSProperties.prototype.webkitMarginAfter;
+/** @type {string} */ CSSProperties.prototype.webkitMarginAfterCollapse;
+/** @type {string} */ CSSProperties.prototype.webkitMarginBefore;
+/** @type {string} */ CSSProperties.prototype.webkitMarginBeforeCollapse;
+/** @type {string} */ CSSProperties.prototype.webkitMarginBottomCollapse;
+/** @type {string} */ CSSProperties.prototype.webkitMarginCollapse;
+/** @type {string} */ CSSProperties.prototype.webkitMarginEnd;
+/** @type {string} */ CSSProperties.prototype.webkitMarginStart;
+/** @type {string} */ CSSProperties.prototype.webkitMarginTopCollapse;
+/** @type {string} */ CSSProperties.prototype.webkitMarquee;
+/** @type {string} */ CSSProperties.prototype.webkitMarqueeDirection;
+/** @type {string} */ CSSProperties.prototype.webkitMarqueeIncrement;
+/** @type {string} */ CSSProperties.prototype.webkitMarqueeRepetition;
+/** @type {string} */ CSSProperties.prototype.webkitMarqueeSpeed;
+/** @type {string} */ CSSProperties.prototype.webkitMarqueeStyle;
+/** @type {string} */ CSSProperties.prototype.webkitMask;
+/** @type {string} */ CSSProperties.prototype.webkitMaskAttachment;
+/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImage;
+/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageOutset;
+/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageRepeat;
+/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageSlice;
+/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageSource;
+/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageWidth;
+/** @type {string} */ CSSProperties.prototype.webkitMaskClip;
+/** @type {string} */ CSSProperties.prototype.webkitMaskComposite;
+/** @type {string} */ CSSProperties.prototype.webkitMaskImage;
+/** @type {string} */ CSSProperties.prototype.webkitMaskOrigin;
+/** @type {string} */ CSSProperties.prototype.webkitMaskPosition;
+/** @type {string} */ CSSProperties.prototype.webkitMaskPositionX;
+/** @type {string} */ CSSProperties.prototype.webkitMaskPositionY;
+/** @type {string} */ CSSProperties.prototype.webkitMaskRepeat;
+/** @type {string} */ CSSProperties.prototype.webkitMaskRepeatX;
+/** @type {string} */ CSSProperties.prototype.webkitMaskRepeatY;
+/** @type {string} */ CSSProperties.prototype.webkitMaskSize;
+/** @type {string} */
+CSSProperties.prototype.webkitMatchNearestMailBlockquoteColor;
+/** @type {string} */ CSSProperties.prototype.webkitMaxLogicalHeight;
+/** @type {string} */ CSSProperties.prototype.webkitMaxLogicalWidth;
+/** @type {string} */ CSSProperties.prototype.webkitMinLogicalHeight;
+/** @type {string} */ CSSProperties.prototype.webkitMinLogicalWidth;
+/** @type {string} */ CSSProperties.prototype.webkitNbspMode;
+/** @type {string} */ CSSProperties.prototype.webkitOrder;
+/** @type {string} */ CSSProperties.prototype.webkitOverflowScrolling;
+/** @type {string} */ CSSProperties.prototype.webkitPaddingAfter;
+/** @type {string} */ CSSProperties.prototype.webkitPaddingBefore;
+/** @type {string} */ CSSProperties.prototype.webkitPaddingEnd;
+/** @type {string} */ CSSProperties.prototype.webkitPaddingStart;
+/** @type {string} */ CSSProperties.prototype.webkitPerspective;
+/** @type {string} */ CSSProperties.prototype.webkitPerspectiveOrigin;
+/** @type {string} */ CSSProperties.prototype.webkitPerspectiveOriginX;
+/** @type {string} */ CSSProperties.prototype.webkitPerspectiveOriginY;
+/** @type {string} */ CSSProperties.prototype.webkitPrintColorAdjust;
+/** @type {string} */ CSSProperties.prototype.webkitRegionBreakAfter;
+/** @type {string} */ CSSProperties.prototype.webkitRegionBreakBefore;
+/** @type {string} */ CSSProperties.prototype.webkitRegionBreakInside;
+/** @type {string} */ CSSProperties.prototype.webkitRegionOverflow;
+/** @type {string} */ CSSProperties.prototype.webkitRtlOrdering;
+/** @type {string} */ CSSProperties.prototype.webkitRubyPosition;
+/** @type {string} */ CSSProperties.prototype.webkitShapeInside;
+/** @type {string} */ CSSProperties.prototype.webkitShapeMargin;
+/** @type {string} */ CSSProperties.prototype.webkitShapeOutside;
+/** @type {string} */ CSSProperties.prototype.webkitShapePadding;
+/** @type {string} */ CSSProperties.prototype.webkitTapHighlightColor;
+/** @type {string} */ CSSProperties.prototype.webkitTextAlignLast;
+/** @type {string} */ CSSProperties.prototype.webkitTextCombine;
+/** @type {string} */ CSSProperties.prototype.webkitTextDecorationLine;
+/** @type {string} */ CSSProperties.prototype.webkitTextDecorationsInEffect;
+/** @type {string} */ CSSProperties.prototype.webkitTextDecorationStyle;
+/** @type {string} */ CSSProperties.prototype.webkitTextEmphasis;
+/** @type {string} */ CSSProperties.prototype.webkitTextEmphasisColor;
+/** @type {string} */ CSSProperties.prototype.webkitTextEmphasisPosition;
+/** @type {string} */ CSSProperties.prototype.webkitTextEmphasisStyle;
+/** @type {string} */ CSSProperties.prototype.webkitTextFillColor;
+/** @type {string} */ CSSProperties.prototype.webkitTextOrientation;
+/** @type {string} */ CSSProperties.prototype.webkitTextSecurity;
+/** @type {string} */ CSSProperties.prototype.webkitTextSizeAdjust;
+/** @type {string} */ CSSProperties.prototype.webkitTextStroke;
+/** @type {string} */ CSSProperties.prototype.webkitTextStrokeColor;
+/** @type {string} */ CSSProperties.prototype.webkitTextStrokeWidth;
+/** @type {string} */ CSSProperties.prototype.webkitTransform;
+/** @type {string} */ CSSProperties.prototype.webkitTransformOrigin;
+/** @type {string} */ CSSProperties.prototype.webkitTransformOriginX;
+/** @type {string} */ CSSProperties.prototype.webkitTransformOriginY;
+/** @type {string} */ CSSProperties.prototype.webkitTransformOriginZ;
+/** @type {string} */ CSSProperties.prototype.webkitTransformStyle;
+/** @type {string} */ CSSProperties.prototype.webkitTransition;
+/** @type {string} */ CSSProperties.prototype.webkitTransitionDelay;
+/** @type {string} */ CSSProperties.prototype.webkitTransitionDuration;
+/** @type {string} */ CSSProperties.prototype.webkitTransitionProperty;
+/** @type {string} */ CSSProperties.prototype.webkitTransitionRepeatCount;
+/** @type {string} */ CSSProperties.prototype.webkitTransitionTimingFunction;
+/** @type {string} */ CSSProperties.prototype.webkitUserDrag;
+/** @type {string} */ CSSProperties.prototype.webkitUserModify;
+/** @type {string} */ CSSProperties.prototype.webkitUserSelect;
+/** @type {string} */ CSSProperties.prototype.webkitWrap;
+/** @type {string} */ CSSProperties.prototype.webkitWrapFlow;
+/** @type {string} */ CSSProperties.prototype.webkitWrapThrough;
+/** @type {string} */ CSSProperties.prototype.webkitWritingMode;
+
+/**
+ * @constructor
+ * @param {number} x
+ * @param {number} y
+ */
+function WebKitPoint(x, y) {}
+
+/** @type {number} */
+WebKitPoint.prototype.x;
+
+/** @type {number} */
+WebKitPoint.prototype.y;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_dom.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_dom.js
new file mode 100644
index 0000000000..da8c8fdde9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_dom.js
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over W3C's DOM
+ * specification by WebKit. This file depends on w3c_dom2.js.
+ * All the provided definitions has been type annotated
+ *
+ * @externs
+ */
+
+
+/**
+ * @param {boolean=} opt_center
+ * @see https://bugzilla.mozilla.org/show_bug.cgi?id=403510
+ */
+Element.prototype.scrollIntoViewIfNeeded = function(opt_center) {};
+
+/**
+ * @constructor
+ * @see http://trac.webkit.org/browser/trunk/Source/WebCore/page/MemoryInfo.idl
+ * @see http://trac.webkit.org/browser/trunk/Source/WebCore/page/MemoryInfo.cpp
+ */
+function MemoryInfo() {};
+
+/** @type {number} */
+MemoryInfo.prototype.totalJSHeapSize;
+
+/** @type {number} */
+MemoryInfo.prototype.usedJSHeapSize;
+
+/** @type {number} */
+MemoryInfo.prototype.jsHeapSizeLimit;
+
+/**
+ * @constructor
+ * @see http://trac.webkit.org/browser/trunk/Source/WebCore/inspector/ScriptProfileNode.idl
+ */
+function ScriptProfileNode() {};
+
+/** @type {string} */
+ScriptProfileNode.prototype.functionName;
+
+/** @type {string} */
+ScriptProfileNode.prototype.url;
+
+/** @type {number} */
+ScriptProfileNode.prototype.lineNumber;
+
+/** @type {number} */
+ScriptProfileNode.prototype.totalTime;
+
+/** @type {number} */
+ScriptProfileNode.prototype.selfTime;
+
+/** @type {number} */
+ScriptProfileNode.prototype.numberOfCalls;
+
+/** @type {Array.<ScriptProfileNode>} */
+ScriptProfileNode.prototype.children;
+
+/** @type {boolean} */
+ScriptProfileNode.prototype.visible;
+
+/** @type {number} */
+ScriptProfileNode.prototype.callUID;
+
+/**
+ * @constructor
+ * @see http://trac.webkit.org/browser/trunk/Source/WebCore/inspector/ScriptProfile.idl
+ */
+function ScriptProfile() {};
+
+/** @type {string} */
+ScriptProfile.prototype.title;
+
+/** @type {number} */
+ScriptProfile.prototype.uid;
+
+/** @type {ScriptProfileNode} */
+ScriptProfile.prototype.head;
+
+/**
+ * @constructor
+ * @see http://trac.webkit.org/browser/trunk/Source/WebCore/page/Console.idl
+ * @see http://trac.webkit.org/browser/trunk/Source/WebCore/page/Console.cpp
+ */
+function Console() {};
+
+/**
+ * @param {*} condition
+ * @param {...*} var_args
+ */
+Console.prototype.assert = function(condition, var_args) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.error = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.info = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.log = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.warn = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.debug = function(var_args) {};
+
+/**
+ * @param {*} value
+ */
+Console.prototype.dir = function(value) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.dirxml = function(var_args) {};
+
+/**
+ * @param {!Object} data
+ * @param {*=} opt_columns
+ */
+Console.prototype.table = function(data, opt_columns) {};
+
+/**
+ * @return {undefined}
+ */
+Console.prototype.trace = function() {};
+
+/**
+ * @param {*} value
+ */
+Console.prototype.count = function(value) {};
+
+/**
+ * @param {*} value
+ */
+Console.prototype.markTimeline = function(value) {};
+
+/**
+ * @param {string=} opt_title
+ */
+Console.prototype.profile = function(opt_title) {};
+
+/** @type {Array.<ScriptProfile>} */
+Console.prototype.profiles;
+
+/**
+ * @param {string=} opt_title
+ */
+Console.prototype.profileEnd = function(opt_title) {};
+
+/**
+ * @param {string} name
+ */
+Console.prototype.time = function(name) {};
+
+/**
+ * @param {string} name
+ */
+Console.prototype.timeEnd = function(name) {};
+
+/**
+ * @param {*} value
+ */
+Console.prototype.timeStamp = function(value) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.group = function(var_args) {};
+
+/**
+ * @param {...*} var_args
+ */
+Console.prototype.groupCollapsed = function(var_args) {};
+
+Console.prototype.groupEnd = function() {};
+
+Console.prototype.clear = function() {};
+
+/** @type {MemoryInfo} */
+Console.prototype.memory;
+
+/** @type {!Console} */
+Window.prototype.console;
+
+/**
+ * @type {!Console}
+ * @suppress {duplicate}
+ */
+var console;
+
+/**
+ * @type {number}
+ * @see http://developer.android.com/reference/android/webkit/WebView.html
+ */
+Window.prototype.devicePixelRatio;
+
+/** @type {Node} */
+Selection.prototype.baseNode;
+
+/** @type {number} */
+Selection.prototype.baseOffset;
+
+/** @type {Node} */
+Selection.prototype.extentNode;
+
+/** @type {number} */
+Selection.prototype.extentOffset;
+
+/** @type {string} */
+Selection.prototype.type;
+
+/**
+ * @return {undefined}
+ */
+Selection.prototype.empty = function() {};
+
+/**
+ * @param {Node} baseNode
+ * @param {number} baseOffset
+ * @param {Node} extentNode
+ * @param {number} extentOffset
+ * @return {undefined}
+ */
+Selection.prototype.setBaseAndExtent =
+ function(baseNode, baseOffset, extentNode, extentOffset) {};
+
+/**
+ * @param {string} alter
+ * @param {string} direction
+ * @param {string} granularity
+ * @return {undefined}
+ */
+Selection.prototype.modify = function(alter, direction, granularity) {};
+
+/**
+ * @param {Element} element
+ * @param {string} pseudoElement
+ * @param {boolean=} opt_authorOnly
+ * @return {CSSRuleList}
+ * @nosideeffects
+ */
+ViewCSS.prototype.getMatchedCSSRules =
+ function(element, pseudoElement, opt_authorOnly) {};
+
+/**
+ * @param {string} contextId
+ * @param {string} name
+ * @param {number} width
+ * @param {number} height
+ * @nosideeffects
+ */
+Document.prototype.getCSSCanvasContext =
+ function(contextId, name, width, height) {};
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_event.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_event.js
new file mode 100644
index 0000000000..9fad616f3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_event.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for all the extensions over W3C's
+ * event specification by WebKit. This file depends on w3c_event.js.
+ * All the provided definitions have been type annotated
+ *
+ * @externs
+ */
+
+/** @type {number} */
+Event.prototype.wheelDeltaX;
+
+/** @type {number} */
+Event.prototype.wheelDeltaY;
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @see http://developer.apple.com/library/safari/documentation/AudioVideo/Reference/WebKitAnimationEventClassReference/WebKitAnimationEvent/WebKitAnimationEvent.html
+ */
+function WebKitAnimationEvent() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+WebKitAnimationEvent.prototype.animationName;
+
+/**
+ * @type {number}
+ * @const
+ */
+WebKitAnimationEvent.prototype.elapsedTime; \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_notifications.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_notifications.js
new file mode 100644
index 0000000000..30e4a0bc70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webkit_notifications.js
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for W3C's Notifications specification.
+ * @externs
+ */
+
+/**
+ * @typedef {{dir: (string|undefined), lang: (string|undefined),
+ * body: (string|undefined), tag: (string|undefined),
+ * icon: (string|undefined)}}
+ * @see http://notifications.spec.whatwg.org/#notificationoptions
+ */
+var NotificationOptions;
+
+/** @interface */
+var NotificationOptionsInterface_;
+/** @type {string} */ NotificationOptionsInterface_.prototype.dir;
+/** @type {string} */ NotificationOptionsInterface_.prototype.lang;
+/** @type {string} */ NotificationOptionsInterface_.prototype.body;
+/** @type {string} */ NotificationOptionsInterface_.prototype.tag;
+/** @type {string} */ NotificationOptionsInterface_.prototype.icon;
+
+/**
+ * @param {string} title
+ * @param {NotificationOptions=} opt_options
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://notifications.spec.whatwg.org/#notification
+ */
+function Notification(title, opt_options) {}
+
+/**
+ * @type {string}
+ */
+Notification.permission;
+
+/**
+ * @param {NotificationPermissionCallback=} opt_callback
+ */
+Notification.requestPermission = function(opt_callback) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Notification.prototype.addEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/**
+ * @param {boolean=} opt_useCapture
+ * @override
+ */
+Notification.prototype.removeEventListener =
+ function(type, listener, opt_useCapture) {};
+
+/** @override */
+Notification.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * The ID used by clients to uniquely identify notifications to eliminate
+ * duplicate notifications.
+ * @type {string}
+ * @deprecated Use NotificationOptions.tag instead.
+ */
+Notification.prototype.replaceId;
+
+/**
+ * The string used by clients to specify the directionality (rtl/ltr) of the
+ * notification.
+ * @type {string}
+ * @deprecated Use NotificationOptions.titleDir and bodyDir instead.
+ */
+Notification.prototype.dir;
+
+/**
+ * Displays the notification.
+ */
+Notification.prototype.show = function() {};
+
+/**
+ * Prevents the notification from being displayed, or closes it if it is already
+ * displayed.
+ */
+Notification.prototype.cancel = function() {};
+
+/**
+ * Prevents the notification from being displayed, or closes it if it is already
+ * displayed.
+ */
+Notification.prototype.close = function() {};
+
+/**
+ * An event handler called when notification is closed.
+ * @type {?function(Event)}
+ */
+Notification.prototype.onclose;
+
+/**
+ * An event handler called if the notification could not be displayed due to
+ * an error (i.e. resource could not be loaded).
+ * @type {?function(Event)}
+ */
+Notification.prototype.onerror;
+
+/**
+ * An event handler called when the notification has become visible.
+ * @type {?function(Event)}
+ * @deprecated Use onshow instead.
+ */
+Notification.prototype.ondisplay;
+
+/**
+ * An event handler called when the notification has become visible.
+ * @type {?function(Event)}
+ */
+Notification.prototype.onshow;
+
+/**
+ * An event handler called when the notification has been clicked on.
+ * @type {?function(Event)}
+ */
+Notification.prototype.onclick;
+
+/**
+ * @constructor
+ */
+window.Notification = Notification;
+
+/**
+ * @type {string}
+ */
+window.Notification.permission;
+
+/**
+ * @param {NotificationPermissionCallback=} opt_callback
+ */
+window.Notification.requestPermission = function(opt_callback) {};
+
+/**
+ * @typedef {function(string)}
+ * @see http://notifications.spec.whatwg.org/#notificationpermissioncallback
+ */
+var NotificationPermissionCallback;
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/2006/webapi/WebNotifications/publish/#dialog-if
+ * @deprecated Use Notification instead.
+ */
+function NotificationCenter() {}
+
+/**
+ * Creates a text+icon notification and displays it to the user.
+ * @param {string} iconUrl
+ * @param {string} title
+ * @param {string} body
+ * @return {Notification}
+ */
+NotificationCenter.prototype.createNotification =
+ function(iconUrl, title, body) {};
+
+/**
+ * Creates an HTML notification and displays it to the user.
+ * @param {string} url
+ * @return {Notification}
+ */
+NotificationCenter.prototype.createHTMLNotification = function(url) {};
+
+/**
+ * Checks if the user has permission to display notifications.
+ * @return {number}
+ */
+NotificationCenter.prototype.checkPermission = function() {};
+
+/**
+ * Requests permission from the user to display notifications.
+ * @param {Function=} opt_callback
+ * @return {void}
+ */
+NotificationCenter.prototype.requestPermission = function(opt_callback) {};
+
+/**
+ * WebKit browsers expose the NotificationCenter API through
+ * window.webkitNotifications.
+ * @type {NotificationCenter}
+ */
+Window.prototype.webkitNotifications;
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webstorage.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webstorage.js
new file mode 100644
index 0000000000..eee69d2581
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/webstorage.js
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2009 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @fileoverview Definitions for W3C's WebStorage specification.
+ * This file depends on html5.js.
+ * @externs
+ */
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/2011/CR-webstorage-20111208/#the-storage-interface
+ */
+function Storage() {}
+
+/**
+ * @type {number}
+ * @const
+ */
+Storage.prototype.length;
+
+/**
+ * @param {number} index
+ * @return {?string}
+ */
+Storage.prototype.key = function(index) {};
+
+/**
+ * @param {string} key
+ * @return {?string}
+ */
+Storage.prototype.getItem = function(key) {};
+
+/**
+ * @param {string} key
+ * @param {string} data
+ * @return {void}
+ */
+Storage.prototype.setItem = function(key, data) {};
+
+/**
+ * @param {string} key
+ * @return {void}
+ */
+Storage.prototype.removeItem = function(key) {};
+
+/**
+ * @return {void}
+ */
+Storage.prototype.clear = function() {};
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/2011/CR-webstorage-20111208/#the-sessionstorage-attribute
+ */
+function WindowSessionStorage() {}
+
+/**
+ * @type {Storage}
+ */
+WindowSessionStorage.prototype.sessionStorage;
+
+/**
+ * Window implements WindowSessionStorage
+ *
+ * @type {Storage}
+ */
+Window.prototype.sessionStorage;
+
+/**
+ * @interface
+ * @see http://www.w3.org/TR/2011/CR-webstorage-20111208/#the-localstorage-attribute
+ */
+function WindowLocalStorage() {}
+
+/**
+ * @type {Storage}
+ */
+WindowLocalStorage.prototype.localStorage;
+
+/**
+ * Window implements WindowLocalStorage
+ *
+ * @type {Storage}
+ */
+Window.prototype.localStorage;
+
+/**
+ * This is the storage event interface.
+ * @see http://www.w3.org/TR/2011/CR-webstorage-20111208/#the-storage-event
+ * @extends {Event}
+ * @constructor
+ */
+function StorageEvent() {}
+
+/**
+ * @type {string}
+ */
+StorageEvent.prototype.key;
+
+/**
+ * @type {?string}
+ */
+StorageEvent.prototype.oldValue;
+
+/**
+ * @type {?string}
+ */
+StorageEvent.prototype.newValue;
+
+/**
+ * @type {string}
+ */
+StorageEvent.prototype.url;
+
+/**
+ * @type {?Storage}
+ */
+StorageEvent.prototype.storageArea;
+
+/**
+ * @param {string} typeArg
+ * @param {boolean} canBubbleArg
+ * @param {boolean} cancelableArg
+ * @param {string} keyArg
+ * @param {?string} oldValueArg
+ * @param {?string} newValueArg
+ * @param {string} urlArg
+ * @param {?Storage} storageAreaArg
+ * @return {void}
+ */
+StorageEvent.prototype.initStorageEvent = function(typeArg, canBubbleArg,
+ cancelableArg, keyArg,
+ oldValueArg, newValueArg,
+ urlArg, storageAreaArg) {};
+
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/window.js b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/window.js
new file mode 100644
index 0000000000..34e3945c1c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/temp_externs/window.js
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview JavaScript Built-Ins for windows properties.
+ *
+ * @externs
+ * @author stevey@google.com (Steve Yegge)
+ */
+
+// Window properties
+// Only common properties are here. Others such as open()
+// should be used with an explicit Window object.
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/en/DOM/window.top
+ * @const
+ */
+var top;
+
+/**
+ * @type {Navigator}
+ * @see https://developer.mozilla.org/en/DOM/window.navigator
+ * @const
+ */
+var navigator;
+
+/**
+ * @type {!HTMLDocument}
+ * @see https://developer.mozilla.org/en/DOM/window.document
+ * @const
+ */
+var document;
+
+/**
+ * @type {Location}
+ * @see https://developer.mozilla.org/en/DOM/window.location
+ * @const
+ * @suppress {duplicate}
+ * @implicitCast
+ */
+var location;
+
+/**
+ * @type {!Screen}
+ * @see https://developer.mozilla.org/En/DOM/window.screen
+ * @const
+ */
+var screen;
+
+/**
+ * @type {!Window}
+ * @see https://developer.mozilla.org/En/DOM/Window.self
+ * @const
+ */
+var self;
+
+// Magic functions for Firefox's LiveConnect.
+// We'll probably never use these in practice. But redefining them
+// will fire up the JVM, so we want to reserve the symbol names.
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/JavaArray
+ */
+var JavaArray;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/JavaClass
+ */
+var JavaClass;
+
+// We just ripped this from the FF source; it doesn't appear to be
+// publicly documented.
+var JavaMember;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/JavaObject
+ */
+var JavaObject;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/JavaPackage
+ */
+var JavaPackage;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Packages
+ */
+var Packages;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/java
+ */
+var java;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/netscape
+ */
+var netscape;
+
+/**
+ * @see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/sun
+ */
+var sun;
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/window.alert
+ */
+function alert(x) {}
+
+/**
+ * @param {number|undefined|null} immediateID
+ * @see https://developer.mozilla.org/en-US/docs/DOM/window.clearImmediate
+ * @see http://msdn.microsoft.com/en-us/library/ie/hh924825(v=vs.85).aspx
+ */
+function clearImmediate(immediateID) {}
+
+/**
+ * @param {number|undefined?} intervalID
+ * @see https://developer.mozilla.org/en/DOM/window.clearInterval
+ * @suppress {duplicate}
+ */
+function clearInterval(intervalID) {}
+
+/**
+ * @param {number|undefined?} timeoutID
+ * @see https://developer.mozilla.org/en/DOM/window.clearTimeout
+ * @suppress {duplicate}
+ */
+function clearTimeout(timeoutID) {}
+
+/**
+ * @param {*} message
+ * @return {boolean}
+ * @see https://developer.mozilla.org/en/DOM/window.confirm
+ */
+function confirm(message) {}
+
+/**
+ * @see https://developer.mozilla.org/en/DOM/window.dump
+ */
+function dump(x) {}
+
+/**
+ * @param {string} message
+ * @param {string=} opt_value
+ * @return {?string}
+ * @see https://developer.mozilla.org/en/DOM/window.prompt
+ */
+function prompt(message, opt_value) {}
+
+/**
+ * @param {function()} callback
+ * @return {number}
+ * @see https://developer.mozilla.org/en-US/docs/DOM/window.setImmediate
+ * @see http://msdn.microsoft.com/en-us/library/ie/hh773176(v=vs.85).aspx
+ */
+function setImmediate(callback) {}
+
+/**
+ * @param {Function|string} callback
+ * @param {number=} opt_delay
+ * @return {number}
+ * @see https://developer.mozilla.org/en/DOM/window.setInterval
+ * @see https://html.spec.whatwg.org/multipage/webappapis.html#timers
+ */
+function setInterval(callback, opt_delay) {}
+
+/**
+ * @param {Function|string} callback
+ * @param {number=} opt_delay
+ * @param {...*} var_args
+ * @return {number}
+ * @see https://developer.mozilla.org/en/DOM/window.setTimeout
+ * @see https://html.spec.whatwg.org/multipage/webappapis.html#timers
+ */
+function setTimeout(callback, opt_delay, var_args) {}
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.js b/dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.js
new file mode 100644
index 0000000000..d6122231f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.js
@@ -0,0 +1,4 @@
+/** @type {WebGL2RenderingContext} */ var myContext;
+console.log(myContext.READ_BUFFER);
+// See whether WebGL 1.0 properties are correctly type checked.
+console.log(myContext.DEPTH_BUFFER_BIT);
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.sh b/dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.sh
new file mode 100755
index 0000000000..508941f3c1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/test-webgl2.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+: ${JAVA:=java}
+
+# Temporary shell script to help shake out the bugs to webgl2.js until
+# it's folded back into the Closure workspace.
+$JAVA -jar ../../../../closure/compiler.jar \
+ --use_only_custom_externs \
+ --js test-webgl2.js \
+ --externs temp_externs/chrome.js \
+ --externs temp_externs/deprecated.js \
+ --externs temp_externs/es3.js \
+ --externs temp_externs/es5.js \
+ --externs temp_externs/es6.js \
+ --externs temp_externs/es6_collections.js \
+ --externs temp_externs/fileapi.js \
+ --externs temp_externs/flash.js \
+ --externs temp_externs/gecko_css.js \
+ --externs temp_externs/gecko_dom.js \
+ --externs temp_externs/gecko_event.js \
+ --externs temp_externs/gecko_xml.js \
+ --externs temp_externs/google.js \
+ --externs temp_externs/html5.js \
+ --externs temp_externs/ie_css.js \
+ --externs temp_externs/ie_dom.js \
+ --externs temp_externs/ie_event.js \
+ --externs temp_externs/ie_vml.js \
+ --externs temp_externs/intl.js \
+ --externs temp_externs/iphone.js \
+ --externs temp_externs/mediasource.js \
+ --externs temp_externs/page_visibility.js \
+ --externs temp_externs/v8.js \
+ --externs temp_externs/w3c_anim_timing.js \
+ --externs temp_externs/w3c_css.js \
+ --externs temp_externs/w3c_css3d.js \
+ --externs temp_externs/w3c_device_sensor_event.js \
+ --externs temp_externs/w3c_dom1.js \
+ --externs temp_externs/w3c_dom2.js \
+ --externs temp_externs/w3c_dom3.js \
+ --externs temp_externs/w3c_elementtraversal.js \
+ --externs temp_externs/w3c_encoding.js \
+ --externs temp_externs/w3c_event.js \
+ --externs temp_externs/w3c_event3.js \
+ --externs temp_externs/w3c_geolocation.js \
+ --externs temp_externs/w3c_indexeddb.js \
+ --externs temp_externs/w3c_navigation_timing.js \
+ --externs temp_externs/w3c_range.js \
+ --externs temp_externs/w3c_rtc.js \
+ --externs temp_externs/w3c_selectors.js \
+ --externs temp_externs/w3c_xml.js \
+ --externs temp_externs/webkit_css.js \
+ --externs temp_externs/webkit_dom.js \
+ --externs temp_externs/webkit_event.js \
+ --externs temp_externs/webkit_notifications.js \
+ --externs temp_externs/webstorage.js \
+ --externs temp_externs/window.js \
+ --externs webgl2.js \
+ --compilation_level ADVANCED \
+ --warning_level VERBOSE \
+ --js_output_file /dev/null
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/webgl2.js b/dom/canvas/test/webgl-conf/checkout/deqp/webgl2.js
new file mode 100644
index 0000000000..91527fcbe7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/webgl2.js
@@ -0,0 +1,5520 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WebGL 2.0 portions:
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+/**
+ * @fileoverview Definitions for WebGL functions as described at
+ * http://www.khronos.org/registry/webgl/specs/latest/1.0 and
+ * http://www.khronos.org/registry/webgl/specs/latest/2.0
+ *
+ * This file is current up to the WebGL 2.0 spec, including extensions.
+ *
+ * This relies on html5.js being included for Canvas and Typed Array support.
+ *
+ * This includes some extensions defined at
+ * http://www.khronos.org/registry/webgl/extensions/
+ *
+ * This file will be merged back into the Closure workspace as soon as
+ * the WebGL 2.0 changes have been fully tested.
+ *
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @noalias
+ * @private
+ */
+function WebGLRenderingContextBase() {}
+
+/** @typedef {number} */
+WebGLRenderingContextBase.GLenum;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_BUFFER_BIT;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BUFFER_BIT;
+
+/** @type {number} */
+WebGLRenderingContextBase.COLOR_BUFFER_BIT;
+
+/** @type {number} */
+WebGLRenderingContextBase.POINTS;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINES;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINE_LOOP;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINE_STRIP;
+
+/** @type {number} */
+WebGLRenderingContextBase.TRIANGLES;
+
+/** @type {number} */
+WebGLRenderingContextBase.TRIANGLE_STRIP;
+
+/** @type {number} */
+WebGLRenderingContextBase.TRIANGLE_FAN;
+
+/** @type {number} */
+WebGLRenderingContextBase.ZERO;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE;
+
+/** @type {number} */
+WebGLRenderingContextBase.SRC_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE_MINUS_SRC_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.SRC_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE_MINUS_SRC_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.DST_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE_MINUS_DST_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.DST_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE_MINUS_DST_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.SRC_ALPHA_SATURATE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FUNC_ADD;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_EQUATION;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_EQUATION_RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_EQUATION_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.FUNC_SUBTRACT;
+
+/** @type {number} */
+WebGLRenderingContextBase.FUNC_REVERSE_SUBTRACT;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_DST_RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_SRC_RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_DST_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_SRC_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.CONSTANT_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE_MINUS_CONSTANT_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.CONSTANT_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.ONE_MINUS_CONSTANT_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.ARRAY_BUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.ELEMENT_ARRAY_BUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.ARRAY_BUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.ELEMENT_ARRAY_BUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.STREAM_DRAW;
+
+/** @type {number} */
+WebGLRenderingContextBase.STATIC_DRAW;
+
+/** @type {number} */
+WebGLRenderingContextBase.DYNAMIC_DRAW;
+
+/** @type {number} */
+WebGLRenderingContextBase.BUFFER_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.BUFFER_USAGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.CURRENT_VERTEX_ATTRIB;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRONT;
+
+/** @type {number} */
+WebGLRenderingContextBase.BACK;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRONT_AND_BACK;
+
+/** @type {number} */
+WebGLRenderingContextBase.CULL_FACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLEND;
+
+/** @type {number} */
+WebGLRenderingContextBase.DITHER;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_TEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_TEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.SCISSOR_TEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.POLYGON_OFFSET_FILL;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLE_ALPHA_TO_COVERAGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLE_COVERAGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.NO_ERROR;
+
+/** @type {number} */
+WebGLRenderingContextBase.INVALID_ENUM;
+
+/** @type {number} */
+WebGLRenderingContextBase.INVALID_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.INVALID_OPERATION;
+
+/** @type {number} */
+WebGLRenderingContextBase.OUT_OF_MEMORY;
+
+/** @type {number} */
+WebGLRenderingContextBase.CW;
+
+/** @type {number} */
+WebGLRenderingContextBase.CCW;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINE_WIDTH;
+
+/** @type {number} */
+WebGLRenderingContextBase.ALIASED_POINT_SIZE_RANGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.ALIASED_LINE_WIDTH_RANGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.CULL_FACE_MODE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRONT_FACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_RANGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_CLEAR_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_FUNC;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_CLEAR_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_FUNC;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_PASS_DEPTH_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_PASS_DEPTH_PASS;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_REF;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_VALUE_MASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_FUNC;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_PASS_DEPTH_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_PASS_DEPTH_PASS;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_REF;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_VALUE_MASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BACK_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.VIEWPORT;
+
+/** @type {number} */
+WebGLRenderingContextBase.SCISSOR_BOX;
+
+/** @type {number} */
+WebGLRenderingContextBase.COLOR_CLEAR_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.COLOR_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNPACK_ALIGNMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.PACK_ALIGNMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_TEXTURE_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_VIEWPORT_DIMS;
+
+/** @type {number} */
+WebGLRenderingContextBase.SUBPIXEL_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.RED_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.GREEN_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.BLUE_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.ALPHA_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.POLYGON_OFFSET_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.POLYGON_OFFSET_FACTOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_BINDING_2D;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLE_BUFFERS;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLES;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLE_COVERAGE_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLE_COVERAGE_INVERT;
+
+/** @type {number} */
+WebGLRenderingContextBase.COMPRESSED_TEXTURE_FORMATS;
+
+/** @type {number} */
+WebGLRenderingContextBase.DONT_CARE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FASTEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.NICEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.GENERATE_MIPMAP_HINT;
+
+/** @type {number} */
+WebGLRenderingContextBase.BYTE;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNSIGNED_BYTE;
+
+/** @type {number} */
+WebGLRenderingContextBase.SHORT;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNSIGNED_SHORT;
+
+/** @type {number} */
+WebGLRenderingContextBase.INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNSIGNED_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_COMPONENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.RGBA;
+
+/** @type {number} */
+WebGLRenderingContextBase.LUMINANCE;
+
+/** @type {number} */
+WebGLRenderingContextBase.LUMINANCE_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNSIGNED_SHORT_4_4_4_4;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNSIGNED_SHORT_5_5_5_1;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNSIGNED_SHORT_5_6_5;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAGMENT_SHADER;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_SHADER;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_VERTEX_ATTRIBS;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_VERTEX_UNIFORM_VECTORS;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_VARYING_VECTORS;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_TEXTURE_IMAGE_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_FRAGMENT_UNIFORM_VECTORS;
+
+/** @type {number} */
+WebGLRenderingContextBase.SHADER_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.DELETE_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINK_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.VALIDATE_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.ATTACHED_SHADERS;
+
+/** @type {number} */
+WebGLRenderingContextBase.ACTIVE_UNIFORMS;
+
+/** @type {number} */
+WebGLRenderingContextBase.ACTIVE_ATTRIBUTES;
+
+/** @type {number} */
+WebGLRenderingContextBase.SHADING_LANGUAGE_VERSION;
+
+/** @type {number} */
+WebGLRenderingContextBase.CURRENT_PROGRAM;
+
+/** @type {number} */
+WebGLRenderingContextBase.NEVER;
+
+/** @type {number} */
+WebGLRenderingContextBase.LESS;
+
+/** @type {number} */
+WebGLRenderingContextBase.EQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.LEQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.GREATER;
+
+/** @type {number} */
+WebGLRenderingContextBase.NOTEQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.GEQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.ALWAYS;
+
+/** @type {number} */
+WebGLRenderingContextBase.KEEP;
+
+/** @type {number} */
+WebGLRenderingContextBase.REPLACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.INCR;
+
+/** @type {number} */
+WebGLRenderingContextBase.DECR;
+
+/** @type {number} */
+WebGLRenderingContextBase.INVERT;
+
+/** @type {number} */
+WebGLRenderingContextBase.INCR_WRAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.DECR_WRAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.VENDOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERER;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERSION;
+
+/** @type {number} */
+WebGLRenderingContextBase.NEAREST;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINEAR;
+
+/** @type {number} */
+WebGLRenderingContextBase.NEAREST_MIPMAP_NEAREST;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINEAR_MIPMAP_NEAREST;
+
+/** @type {number} */
+WebGLRenderingContextBase.NEAREST_MIPMAP_LINEAR;
+
+/** @type {number} */
+WebGLRenderingContextBase.LINEAR_MIPMAP_LINEAR;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_MAG_FILTER;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_MIN_FILTER;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_WRAP_S;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_WRAP_T;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_2D;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_BINDING_CUBE_MAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP_POSITIVE_X;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP_NEGATIVE_X;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP_POSITIVE_Y;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP_NEGATIVE_Y;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP_POSITIVE_Z;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE_CUBE_MAP_NEGATIVE_Z;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_CUBE_MAP_TEXTURE_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE0;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE1;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE2;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE3;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE4;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE5;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE6;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE7;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE8;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE9;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE10;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE11;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE12;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE13;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE14;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE15;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE16;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE17;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE18;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE19;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE20;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE21;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE22;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE23;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE24;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE25;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE26;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE27;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE28;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE29;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE30;
+
+/** @type {number} */
+WebGLRenderingContextBase.TEXTURE31;
+
+/** @type {number} */
+WebGLRenderingContextBase.ACTIVE_TEXTURE;
+
+/** @type {number} */
+WebGLRenderingContextBase.REPEAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.CLAMP_TO_EDGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.MIRRORED_REPEAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT_VEC2;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT_VEC3;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT_VEC4;
+
+/** @type {number} */
+WebGLRenderingContextBase.INT_VEC2;
+
+/** @type {number} */
+WebGLRenderingContextBase.INT_VEC3;
+
+/** @type {number} */
+WebGLRenderingContextBase.INT_VEC4;
+
+/** @type {number} */
+WebGLRenderingContextBase.BOOL;
+
+/** @type {number} */
+WebGLRenderingContextBase.BOOL_VEC2;
+
+/** @type {number} */
+WebGLRenderingContextBase.BOOL_VEC3;
+
+/** @type {number} */
+WebGLRenderingContextBase.BOOL_VEC4;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT_MAT2;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT_MAT3;
+
+/** @type {number} */
+WebGLRenderingContextBase.FLOAT_MAT4;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLER_2D;
+
+/** @type {number} */
+WebGLRenderingContextBase.SAMPLER_CUBE;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_ENABLED;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_STRIDE;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_NORMALIZED;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_POINTER;
+
+/** @type {number} */
+WebGLRenderingContextBase.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.IMPLEMENTATION_COLOR_READ_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.IMPLEMENTATION_COLOR_READ_FORMAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.COMPILE_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.LOW_FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.MEDIUM_FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.HIGH_FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.LOW_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.MEDIUM_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.HIGH_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.RGBA4;
+
+/** @type {number} */
+WebGLRenderingContextBase.RGB5_A1;
+
+/** @type {number} */
+WebGLRenderingContextBase.RGB565;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_COMPONENT16;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_INDEX;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_INDEX8;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_STENCIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_WIDTH;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_HEIGHT;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_INTERNAL_FORMAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_RED_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_GREEN_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_BLUE_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_ALPHA_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_DEPTH_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_STENCIL_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.COLOR_ATTACHMENT0;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.STENCIL_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.DEPTH_STENCIL_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.NONE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_COMPLETE;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_UNSUPPORTED;
+
+/** @type {number} */
+WebGLRenderingContextBase.FRAMEBUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.RENDERBUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.MAX_RENDERBUFFER_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.INVALID_FRAMEBUFFER_OPERATION;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNPACK_FLIP_Y_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNPACK_PREMULTIPLY_ALPHA_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.CONTEXT_LOST_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.UNPACK_COLORSPACE_CONVERSION_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.BROWSER_DEFAULT_WEBGL;
+
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_BUFFER_BIT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BUFFER_BIT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.COLOR_BUFFER_BIT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.POINTS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINES;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINE_LOOP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINE_STRIP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TRIANGLES;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TRIANGLE_STRIP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TRIANGLE_FAN;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ZERO;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SRC_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE_MINUS_SRC_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SRC_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE_MINUS_SRC_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DST_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE_MINUS_DST_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DST_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE_MINUS_DST_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SRC_ALPHA_SATURATE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FUNC_ADD;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_EQUATION;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_EQUATION_RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_EQUATION_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FUNC_SUBTRACT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FUNC_REVERSE_SUBTRACT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_DST_RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_SRC_RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_DST_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_SRC_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CONSTANT_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE_MINUS_CONSTANT_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CONSTANT_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ONE_MINUS_CONSTANT_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND_COLOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ARRAY_BUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ELEMENT_ARRAY_BUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ARRAY_BUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ELEMENT_ARRAY_BUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STREAM_DRAW;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STATIC_DRAW;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DYNAMIC_DRAW;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BUFFER_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BUFFER_USAGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CURRENT_VERTEX_ATTRIB;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRONT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BACK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRONT_AND_BACK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CULL_FACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLEND;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DITHER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_TEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_TEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SCISSOR_TEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.POLYGON_OFFSET_FILL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLE_ALPHA_TO_COVERAGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLE_COVERAGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NO_ERROR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INVALID_ENUM;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INVALID_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INVALID_OPERATION;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.OUT_OF_MEMORY;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CW;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CCW;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINE_WIDTH;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ALIASED_POINT_SIZE_RANGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ALIASED_LINE_WIDTH_RANGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CULL_FACE_MODE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRONT_FACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_RANGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_CLEAR_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_FUNC;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_CLEAR_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_FUNC;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_PASS_DEPTH_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_PASS_DEPTH_PASS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_REF;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_VALUE_MASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_FUNC;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_PASS_DEPTH_FAIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_PASS_DEPTH_PASS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_REF;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_VALUE_MASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BACK_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VIEWPORT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SCISSOR_BOX;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.COLOR_CLEAR_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.COLOR_WRITEMASK;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNPACK_ALIGNMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.PACK_ALIGNMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_TEXTURE_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_VIEWPORT_DIMS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SUBPIXEL_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RED_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.GREEN_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BLUE_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ALPHA_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_BITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.POLYGON_OFFSET_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.POLYGON_OFFSET_FACTOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_BINDING_2D;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLE_BUFFERS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLES;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLE_COVERAGE_VALUE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLE_COVERAGE_INVERT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.COMPRESSED_TEXTURE_FORMATS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DONT_CARE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FASTEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NICEST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.GENERATE_MIPMAP_HINT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BYTE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNSIGNED_BYTE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SHORT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNSIGNED_SHORT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNSIGNED_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_COMPONENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RGB;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RGBA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LUMINANCE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LUMINANCE_ALPHA;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNSIGNED_SHORT_4_4_4_4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNSIGNED_SHORT_5_5_5_1;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNSIGNED_SHORT_5_6_5;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAGMENT_SHADER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_SHADER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_VERTEX_ATTRIBS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_VERTEX_UNIFORM_VECTORS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_VARYING_VECTORS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_TEXTURE_IMAGE_UNITS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_FRAGMENT_UNIFORM_VECTORS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SHADER_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DELETE_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINK_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VALIDATE_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ATTACHED_SHADERS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ACTIVE_UNIFORMS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ACTIVE_ATTRIBUTES;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SHADING_LANGUAGE_VERSION;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CURRENT_PROGRAM;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NEVER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LESS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.EQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LEQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.GREATER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NOTEQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.GEQUAL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ALWAYS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.KEEP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.REPLACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INCR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DECR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INVERT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INCR_WRAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DECR_WRAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VENDOR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERSION;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NEAREST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINEAR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NEAREST_MIPMAP_NEAREST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINEAR_MIPMAP_NEAREST;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NEAREST_MIPMAP_LINEAR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LINEAR_MIPMAP_LINEAR;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_MAG_FILTER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_MIN_FILTER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_WRAP_S;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_WRAP_T;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_2D;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_BINDING_CUBE_MAP;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP_POSITIVE_X;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP_NEGATIVE_X;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP_POSITIVE_Y;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP_NEGATIVE_Y;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP_POSITIVE_Z;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE_CUBE_MAP_NEGATIVE_Z;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_CUBE_MAP_TEXTURE_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE0;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE1;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE2;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE3;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE5;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE6;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE7;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE8;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE9;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE10;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE11;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE12;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE13;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE14;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE15;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE16;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE17;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE18;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE19;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE20;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE21;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE22;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE23;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE24;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE25;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE26;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE27;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE28;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE29;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE30;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.TEXTURE31;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.ACTIVE_TEXTURE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.REPEAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CLAMP_TO_EDGE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MIRRORED_REPEAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT_VEC2;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT_VEC3;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT_VEC4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INT_VEC2;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INT_VEC3;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INT_VEC4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BOOL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BOOL_VEC2;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BOOL_VEC3;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BOOL_VEC4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT_MAT2;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT_MAT3;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FLOAT_MAT4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLER_2D;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.SAMPLER_CUBE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_ENABLED;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_STRIDE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_NORMALIZED;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_POINTER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.IMPLEMENTATION_COLOR_READ_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.IMPLEMENTATION_COLOR_READ_FORMAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.COMPILE_STATUS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LOW_FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MEDIUM_FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.HIGH_FLOAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.LOW_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MEDIUM_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.HIGH_INT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RGBA4;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RGB5_A1;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RGB565;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_COMPONENT16;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_INDEX;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_INDEX8;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_STENCIL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_WIDTH;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_HEIGHT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_INTERNAL_FORMAT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_RED_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_GREEN_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_BLUE_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_ALPHA_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_DEPTH_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_STENCIL_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.COLOR_ATTACHMENT0;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.STENCIL_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.DEPTH_STENCIL_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.NONE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_COMPLETE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_UNSUPPORTED;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.FRAMEBUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.RENDERBUFFER_BINDING;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.MAX_RENDERBUFFER_SIZE;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.INVALID_FRAMEBUFFER_OPERATION;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNPACK_FLIP_Y_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNPACK_PREMULTIPLY_ALPHA_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.CONTEXT_LOST_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.UNPACK_COLORSPACE_CONVERSION_WEBGL;
+
+/** @type {number} */
+WebGLRenderingContextBase.prototype.BROWSER_DEFAULT_WEBGL;
+
+
+/**
+ * @type {!HTMLCanvasElement}
+ */
+WebGLRenderingContextBase.prototype.canvas;
+
+/**
+ * @type {number}
+ */
+WebGLRenderingContextBase.prototype.drawingBufferWidth;
+
+/**
+ * @type {number}
+ */
+WebGLRenderingContextBase.prototype.drawingBufferHeight;
+
+/**
+ * @return {!WebGLContextAttributes}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getContextAttributes = function() {};
+
+/**
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isContextLost = function() {};
+
+/**
+ * @return {!Array.<string>}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getSupportedExtensions = function() {};
+
+/**
+ * Note that this has side effects by enabling the extension even if the
+ * result is not used.
+ * @param {string} name
+ * @return {Object}
+ */
+WebGLRenderingContextBase.prototype.getExtension = function(name) {};
+
+/**
+ * @param {number} texture
+ */
+WebGLRenderingContextBase.prototype.activeTexture = function(texture) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {WebGLShader} shader
+ */
+WebGLRenderingContextBase.prototype.attachShader = function(program, shader) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} index
+ * @param {string} name
+ */
+WebGLRenderingContextBase.prototype.bindAttribLocation = function(
+ program, index, name) {};
+
+/**
+ * @param {number} target
+ * @param {WebGLBuffer} buffer
+ */
+WebGLRenderingContextBase.prototype.bindBuffer = function(target, buffer) {};
+
+/**
+ * @param {number} target
+ * @param {WebGLFramebuffer} buffer
+ */
+WebGLRenderingContextBase.prototype.bindFramebuffer = function(target, buffer) {};
+
+/**
+ * @param {number} target
+ * @param {WebGLRenderbuffer} buffer
+ */
+WebGLRenderingContextBase.prototype.bindRenderbuffer = function(target, buffer) {};
+
+/**
+ * @param {number} target
+ * @param {WebGLTexture} texture
+ */
+WebGLRenderingContextBase.prototype.bindTexture = function(target, texture) {};
+
+/**
+ * @param {number} red
+ * @param {number} green
+ * @param {number} blue
+ * @param {number} alpha
+ */
+WebGLRenderingContextBase.prototype.blendColor = function(
+ red, blue, green, alpha) {};
+
+/**
+ * @param {number} mode
+ */
+WebGLRenderingContextBase.prototype.blendEquation = function(mode) {};
+
+/**
+ * @param {number} modeRGB
+ * @param {number} modeAlpha
+ */
+WebGLRenderingContextBase.prototype.blendEquationSeparate = function(
+ modeRGB, modeAlpha) {};
+
+/**
+ * @param {number} sfactor
+ * @param {number} dfactor
+ */
+WebGLRenderingContextBase.prototype.blendFunc = function(sfactor, dfactor) {};
+
+/**
+ * @param {number} srcRGB
+ * @param {number} dstRGB
+ * @param {number} srcAlpha
+ * @param {number} dstAlpha
+ */
+WebGLRenderingContextBase.prototype.blendFuncSeparate = function(
+ srcRGB, dstRGB, srcAlpha, dstAlpha) {};
+
+/**
+ * @param {number} target
+ * @param {ArrayBufferView|ArrayBuffer|number} data
+ * @param {number} usage
+ */
+WebGLRenderingContextBase.prototype.bufferData = function(target, data, usage) {};
+
+/**
+ * @param {number} target
+ * @param {number} offset
+ * @param {ArrayBufferView|ArrayBuffer} data
+ */
+WebGLRenderingContextBase.prototype.bufferSubData = function(
+ target, offset, data) {};
+
+/**
+ * @param {number} target
+ * @return {number}
+ */
+WebGLRenderingContextBase.prototype.checkFramebufferStatus = function(target) {};
+
+/**
+ * @param {number} mask
+ */
+WebGLRenderingContextBase.prototype.clear = function(mask) {};
+
+/**
+ * @param {number} red
+ * @param {number} green
+ * @param {number} blue
+ * @param {number} alpha
+ */
+WebGLRenderingContextBase.prototype.clearColor = function(
+ red, green, blue, alpha) {};
+
+/**
+ * @param {number} depth
+ */
+WebGLRenderingContextBase.prototype.clearDepth = function(depth) {};
+
+/**
+ * @param {number} s
+ */
+WebGLRenderingContextBase.prototype.clearStencil = function(s) {};
+
+/**
+ * @param {boolean} red
+ * @param {boolean} green
+ * @param {boolean} blue
+ * @param {boolean} alpha
+ */
+WebGLRenderingContextBase.prototype.colorMask = function(
+ red, green, blue, alpha) {};
+
+/**
+ * @param {WebGLShader} shader
+ */
+WebGLRenderingContextBase.prototype.compileShader = function(shader) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} border
+ * @param {ArrayBufferView} data
+ */
+WebGLRenderingContextBase.prototype.compressedTexImage2D = function(
+ target, level, internalformat, width, height, border, data) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} width
+ * @param {number} height
+ * @param {number} format
+ * @param {ArrayBufferView} data
+ */
+WebGLRenderingContextBase.prototype.compressedTexSubImage2D = function(
+ target, level, xoffset, yoffset, width, height, format, data) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} format
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {number} border
+ */
+WebGLRenderingContextBase.prototype.copyTexImage2D = function(
+ target, level, format, x, y, width, height, border) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+WebGLRenderingContextBase.prototype.copyTexSubImage2D = function(
+ target, level, xoffset, yoffset, x, y, width, height) {};
+
+/**
+ * @return {!WebGLBuffer}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.createBuffer = function() {};
+
+/**
+ * @return {!WebGLFramebuffer}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.createFramebuffer = function() {};
+
+/**
+ * @return {!WebGLProgram}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.createProgram = function() {};
+
+/**
+ * @return {!WebGLRenderbuffer}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.createRenderbuffer = function() {};
+
+/**
+ * @param {number} type
+ * @return {!WebGLShader}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.createShader = function(type) {};
+
+/**
+ * @return {!WebGLTexture}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.createTexture = function() {};
+
+/**
+ * @param {number} mode
+ */
+WebGLRenderingContextBase.prototype.cullFace = function(mode) {};
+
+/**
+ * @param {WebGLBuffer} buffer
+ */
+WebGLRenderingContextBase.prototype.deleteBuffer = function(buffer) {};
+
+/**
+ * @param {WebGLFramebuffer} buffer
+ */
+WebGLRenderingContextBase.prototype.deleteFramebuffer = function(buffer) {};
+
+/**
+ * @param {WebGLProgram} program
+ */
+WebGLRenderingContextBase.prototype.deleteProgram = function(program) {};
+
+/**
+ * @param {WebGLRenderbuffer} buffer
+ */
+WebGLRenderingContextBase.prototype.deleteRenderbuffer = function(buffer) {};
+
+/**
+ * @param {WebGLShader} shader
+ */
+WebGLRenderingContextBase.prototype.deleteShader = function(shader) {};
+
+/**
+ * @param {WebGLTexture} texture
+ */
+WebGLRenderingContextBase.prototype.deleteTexture = function(texture) {};
+
+/**
+ * @param {number} func
+ */
+WebGLRenderingContextBase.prototype.depthFunc = function(func) {};
+
+/**
+ * @param {boolean} flag
+ */
+WebGLRenderingContextBase.prototype.depthMask = function(flag) {};
+
+/**
+ * @param {number} nearVal
+ * @param {number} farVal
+ */
+WebGLRenderingContextBase.prototype.depthRange = function(nearVal, farVal) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {WebGLShader} shader
+ */
+WebGLRenderingContextBase.prototype.detachShader = function(program, shader) {};
+
+/**
+ * @param {number} flags
+ */
+WebGLRenderingContextBase.prototype.disable = function(flags) {};
+
+/**
+ * @param {number} index
+ */
+WebGLRenderingContextBase.prototype.disableVertexAttribArray = function(
+ index) {};
+
+/**
+ * @param {number} mode
+ * @param {number} first
+ * @param {number} count
+ */
+WebGLRenderingContextBase.prototype.drawArrays = function(mode, first, count) {};
+
+/**
+ * @param {number} mode
+ * @param {number} count
+ * @param {number} type
+ * @param {number} offset
+ */
+WebGLRenderingContextBase.prototype.drawElements = function(
+ mode, count, type, offset) {};
+
+/**
+ * @param {number} cap
+ */
+WebGLRenderingContextBase.prototype.enable = function(cap) {};
+
+/**
+ * @param {number} index
+ */
+WebGLRenderingContextBase.prototype.enableVertexAttribArray = function(
+ index) {};
+
+WebGLRenderingContextBase.prototype.finish = function() {};
+
+WebGLRenderingContextBase.prototype.flush = function() {};
+
+/**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {number} renderbuffertarget
+ * @param {WebGLRenderbuffer} renderbuffer
+ */
+WebGLRenderingContextBase.prototype.framebufferRenderbuffer = function(
+ target, attachment, renderbuffertarget, renderbuffer) {};
+
+/**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {number} textarget
+ * @param {WebGLTexture} texture
+ * @param {number} level
+ */
+WebGLRenderingContextBase.prototype.framebufferTexture2D = function(
+ target, attachment, textarget, texture, level) {};
+
+/**
+ * @param {number} mode
+ */
+WebGLRenderingContextBase.prototype.frontFace = function(mode) {};
+
+/**
+ * @param {number} target
+ */
+WebGLRenderingContextBase.prototype.generateMipmap = function(target) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} index
+ * @return {WebGLActiveInfo}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getActiveAttrib = function(program, index) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} index
+ * @return {WebGLActiveInfo}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getActiveUniform = function(program, index) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @return {!Array.<WebGLShader>}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getAttachedShaders = function(program) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {string} name
+ * @return {number}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getAttribLocation = function(program, name) {};
+
+/**
+ * @param {number} target
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getBufferParameter = function(target, pname) {};
+
+/**
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getParameter = function(pname) {};
+
+/**
+ * @return {number}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getError = function() {};
+
+/**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getFramebufferAttachmentParameter = function(
+ target, attachment, pname) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getProgramParameter = function(
+ program, pname) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @return {string}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getProgramInfoLog = function(program) {};
+
+/**
+ * @param {number} target
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getRenderbufferParameter = function(
+ target, pname) {};
+
+/**
+ * @param {WebGLShader} shader
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getShaderParameter = function(shader, pname) {};
+
+/**
+ * @param {number} shadertype
+ * @param {number} precisiontype
+ * @return {WebGLShaderPrecisionFormat}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getShaderPrecisionFormat = function(shadertype,
+ precisiontype) {};
+
+/**
+ * @param {WebGLShader} shader
+ * @return {string}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getShaderInfoLog = function(shader) {};
+
+/**
+ * @param {WebGLShader} shader
+ * @return {string}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getShaderSource = function(shader) {};
+
+/**
+ * @param {number} target
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getTexParameter = function(target, pname) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {WebGLUniformLocation} location
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getUniform = function(program, location) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {string} name
+ * @return {WebGLUniformLocation}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getUniformLocation = function(program, name) {};
+
+/**
+ * @param {number} index
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getVertexAttrib = function(index, pname) {};
+
+/**
+ * @param {number} index
+ * @param {number} pname
+ * @return {number}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.getVertexAttribOffset = function(
+ index, pname) {};
+
+/**
+ * @param {number} target
+ * @param {number} mode
+ */
+WebGLRenderingContextBase.prototype.hint = function(target, mode) {};
+
+/**
+ * @param {WebGLObject} buffer
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isBuffer = function(buffer) {};
+
+/**
+ * @param {number} cap
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isEnabled = function(cap) {};
+
+/**
+ * @param {WebGLObject} framebuffer
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isFramebuffer = function(framebuffer) {};
+
+/**
+ * @param {WebGLObject} program
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isProgram = function(program) {};
+
+/**
+ * @param {WebGLObject} renderbuffer
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isRenderbuffer = function(renderbuffer) {};
+
+/**
+ * @param {WebGLObject} shader
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isShader = function(shader) {};
+
+/**
+ * @param {WebGLObject} texture
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGLRenderingContextBase.prototype.isTexture = function(texture) {};
+
+/**
+ * @param {number} width
+ */
+WebGLRenderingContextBase.prototype.lineWidth = function(width) {};
+
+/**
+ * @param {WebGLProgram} program
+ */
+WebGLRenderingContextBase.prototype.linkProgram = function(program) {};
+
+/**
+ * @param {number} pname
+ * @param {number} param
+ */
+WebGLRenderingContextBase.prototype.pixelStorei = function(pname, param) {};
+
+/**
+ * @param {number} factor
+ * @param {number} units
+ */
+WebGLRenderingContextBase.prototype.polygonOffset = function(factor, units) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @param {number} format
+ * @param {number} type
+ * @param {ArrayBufferView} pixels
+ */
+WebGLRenderingContextBase.prototype.readPixels = function(
+ x, y, width, height, format, type, pixels) {};
+
+/**
+ * @param {number} target
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ */
+WebGLRenderingContextBase.prototype.renderbufferStorage = function(
+ target, internalformat, width, height) {};
+
+/**
+ * @param {number} coverage
+ * @param {boolean} invert
+ */
+WebGLRenderingContextBase.prototype.sampleCoverage = function(coverage, invert) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+WebGLRenderingContextBase.prototype.scissor = function(x, y, width, height) {};
+
+/**
+ * @param {WebGLShader} shader
+ * @param {string} source
+ */
+WebGLRenderingContextBase.prototype.shaderSource = function(shader, source) {};
+
+/**
+ * @param {number} func
+ * @param {number} ref
+ * @param {number} mask
+ */
+WebGLRenderingContextBase.prototype.stencilFunc = function(func, ref, mask) {};
+
+/**
+ * @param {number} face
+ * @param {number} func
+ * @param {number} ref
+ * @param {number} mask
+ */
+WebGLRenderingContextBase.prototype.stencilFuncSeparate = function(
+ face, func, ref, mask) {};
+
+/**
+ * @param {number} mask
+ */
+WebGLRenderingContextBase.prototype.stencilMask = function(mask) {};
+
+/**
+ * @param {number} face
+ * @param {number} mask
+ */
+WebGLRenderingContextBase.prototype.stencilMaskSeparate = function(face, mask) {};
+
+/**
+ * @param {number} fail
+ * @param {number} zfail
+ * @param {number} zpass
+ */
+WebGLRenderingContextBase.prototype.stencilOp = function(fail, zfail, zpass) {};
+
+/**
+ * @param {number} face
+ * @param {number} fail
+ * @param {number} zfail
+ * @param {number} zpass
+ */
+WebGLRenderingContextBase.prototype.stencilOpSeparate = function(
+ face, fail, zfail, zpass) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalformat
+ * @param {number} format or width
+ * @param {number} type or height
+ * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|
+ * number} img or border
+ * @param {number=} opt_format
+ * @param {number=} opt_type
+ * @param {ArrayBufferView=} opt_pixels
+ */
+WebGLRenderingContextBase.prototype.texImage2D = function(
+ target, level, internalformat, format, type, img, opt_format, opt_type,
+ opt_pixels) {};
+
+/**
+ * @param {number} target
+ * @param {number} pname
+ * @param {number} param
+ */
+WebGLRenderingContextBase.prototype.texParameterf = function(
+ target, pname, param) {};
+
+/**
+ * @param {number} target
+ * @param {number} pname
+ * @param {number} param
+ */
+WebGLRenderingContextBase.prototype.texParameteri = function(
+ target, pname, param) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} format or width
+ * @param {number} type or height
+ * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|
+ * number} data or format
+ * @param {number=} opt_type
+ * @param {ArrayBufferView=} opt_pixels
+ */
+WebGLRenderingContextBase.prototype.texSubImage2D = function(
+ target, level, xoffset, yoffset, format, type, data, opt_type,
+ opt_pixels) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value
+ */
+WebGLRenderingContextBase.prototype.uniform1f = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform1fv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value
+ */
+WebGLRenderingContextBase.prototype.uniform1i = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Int32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform1iv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value1
+ * @param {number} value2
+ */
+WebGLRenderingContextBase.prototype.uniform2f = function(
+ location, value1, value2) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform2fv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value1
+ * @param {number} value2
+ */
+WebGLRenderingContextBase.prototype.uniform2i = function(
+ location, value1, value2) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Int32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform2iv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value1
+ * @param {number} value2
+ * @param {number} value3
+ */
+WebGLRenderingContextBase.prototype.uniform3f = function(
+ location, value1, value2, value3) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform3fv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value1
+ * @param {number} value2
+ * @param {number} value3
+ */
+WebGLRenderingContextBase.prototype.uniform3i = function(
+ location, value1, value2, value3) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Int32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform3iv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value1
+ * @param {number} value2
+ * @param {number} value3
+ * @param {number} value4
+ */
+WebGLRenderingContextBase.prototype.uniform4f = function(
+ location, value1, value2, value3, value4) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform4fv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} value1
+ * @param {number} value2
+ * @param {number} value3
+ * @param {number} value4
+ */
+WebGLRenderingContextBase.prototype.uniform4i = function(
+ location, value1, value2, value3, value4) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Int32Array|Array.<number>} value
+ */
+WebGLRenderingContextBase.prototype.uniform4iv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} data
+ */
+WebGLRenderingContextBase.prototype.uniformMatrix2fv = function(
+ location, transpose, data) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} data
+ */
+WebGLRenderingContextBase.prototype.uniformMatrix3fv = function(
+ location, transpose, data) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} data
+ */
+WebGLRenderingContextBase.prototype.uniformMatrix4fv = function(
+ location, transpose, data) {};
+
+/**
+ * @param {WebGLProgram} program
+ */
+WebGLRenderingContextBase.prototype.useProgram = function(program) {};
+
+/**
+ * @param {WebGLProgram} program
+ */
+WebGLRenderingContextBase.prototype.validateProgram = function(program) {};
+
+/**
+ * @param {number} indx
+ * @param {number} x
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib1f = function(indx, x) {};
+
+/**
+ * @param {number} indx
+ * @param {Float32Array|Array.<number>} values
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib1fv = function(indx, values) {};
+
+/**
+ * @param {number} indx
+ * @param {number} x
+ * @param {number} y
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib2f = function(
+ indx, x, y) {};
+
+/**
+ * @param {number} indx
+ * @param {Float32Array|Array.<number>} values
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib2fv = function(
+ indx, values) {};
+
+/**
+ * @param {number} indx
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib3f = function(
+ indx, x, y, z) {};
+
+/**
+ * @param {number} indx
+ * @param {Float32Array|Array.<number>} values
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib3fv = function(indx, values) {};
+
+/**
+ * @param {number} indx
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib4f = function(
+ indx, x, y, z, w) {};
+
+/**
+ * @param {number} indx
+ * @param {Float32Array|Array.<number>} values
+ */
+WebGLRenderingContextBase.prototype.vertexAttrib4fv = function(indx, values) {};
+
+/**
+ * @param {number} indx
+ * @param {number} size
+ * @param {number} type
+ * @param {boolean} normalized
+ * @param {number} stride
+ * @param {number} offset
+ */
+WebGLRenderingContextBase.prototype.vertexAttribPointer = function(
+ indx, size, type, normalized, stride, offset) {};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+WebGLRenderingContextBase.prototype.viewport = function(x, y, width, height) {};
+
+
+/**
+ * @constructor
+ * @noalias
+ */
+function WebGLContextAttributes() {}
+
+/**
+ * @type {boolean}
+ */
+WebGLContextAttributes.prototype.alpha;
+
+/**
+ * @type {boolean}
+ */
+WebGLContextAttributes.prototype.depth;
+
+/**
+ * @type {boolean}
+ */
+WebGLContextAttributes.prototype.stencil;
+
+/**
+ * @type {boolean}
+ */
+WebGLContextAttributes.prototype.antialias;
+
+/**
+ * @type {boolean}
+ */
+WebGLContextAttributes.prototype.premultipliedAlpha;
+
+/**
+ * @type {boolean}
+ */
+WebGLContextAttributes.prototype.preserveDrawingBuffer;
+
+
+/**
+ * @param {string} eventType
+ * @constructor
+ * @noalias
+ * @extends {Event}
+ */
+function WebGLContextEvent(eventType) {}
+
+/**
+ * @type {string}
+ */
+WebGLContextEvent.prototype.statusMessage;
+
+
+/**
+ * @constructor
+ * @noalias
+ */
+function WebGLShaderPrecisionFormat() {}
+
+/**
+ * @type {number}
+ */
+WebGLShaderPrecisionFormat.prototype.rangeMin;
+
+/**
+ * @type {number}
+ */
+WebGLShaderPrecisionFormat.prototype.rangeMax;
+
+/**
+ * @type {number}
+ */
+WebGLShaderPrecisionFormat.prototype.precision;
+
+
+/**
+ * @constructor
+ * @noalias
+ */
+function WebGLObject() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLBuffer() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLFramebuffer() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLProgram() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLRenderbuffer() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLShader() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLTexture() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ */
+function WebGLActiveInfo() {}
+
+/** @type {number} */
+WebGLActiveInfo.prototype.size;
+
+/** @type {number} */
+WebGLActiveInfo.prototype.type;
+
+/** @type {string} */
+WebGLActiveInfo.prototype.name;
+
+
+/**
+ * @constructor
+ * @noalias
+ */
+function WebGLUniformLocation() {}
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_texture_float/
+ * @constructor
+ * @noalias
+ */
+function OES_texture_float() {}
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/
+ * @constructor
+ * @noalias
+ */
+function OES_texture_half_float() {}
+
+/** @type {number} */
+OES_texture_half_float.prototype.HALF_FLOAT_OES;
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/
+ * @constructor
+ * @noalias
+ */
+function WEBGL_lose_context() {}
+
+WEBGL_lose_context.prototype.loseContext = function() {};
+
+WEBGL_lose_context.prototype.restoreContext = function() {};
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
+ * @constructor
+ * @noalias
+ */
+function OES_standard_derivatives() {}
+
+/** @type {number} */
+OES_standard_derivatives.prototype.FRAGMENT_SHADER_DERIVATIVE_HINT_OES;
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLVertexArrayObjectOES() {}
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
+ * @constructor
+ * @noalias
+ */
+function OES_vertex_array_object() {}
+
+/** @type {number} */
+OES_vertex_array_object.prototype.VERTEX_ARRAY_BINDING_OES;
+
+/**
+ * @return {WebGLVertexArrayObjectOES}
+ * @nosideeffects
+ */
+OES_vertex_array_object.prototype.createVertexArrayOES = function() {};
+
+/**
+ * @param {WebGLVertexArrayObjectOES} arrayObject
+ */
+OES_vertex_array_object.prototype.deleteVertexArrayOES =
+ function(arrayObject) {};
+
+/**
+ * @param {WebGLVertexArrayObjectOES} arrayObject
+ * @return {boolean}
+ * @nosideeffects
+ */
+OES_vertex_array_object.prototype.isVertexArrayOES = function(arrayObject) {};
+
+/**
+ * @param {WebGLVertexArrayObjectOES} arrayObject
+ */
+OES_vertex_array_object.prototype.bindVertexArrayOES = function(arrayObject) {};
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_renderer_info/
+ * @constructor
+ * @noalias
+ */
+function WEBGL_debug_renderer_info() {}
+
+/** @type {number} */
+WEBGL_debug_renderer_info.prototype.UNMASKED_VENDOR_WEBGL;
+
+/** @type {number} */
+WEBGL_debug_renderer_info.prototype.UNMASKED_RENDERER_WEBGL;
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_shaders/
+ * @constructor
+ * @noalias
+ */
+function WEBGL_debug_shaders() {}
+
+/**
+ * @param {WebGLShader} shader
+ * @return {string}
+ * @nosideeffects
+ */
+WEBGL_debug_shaders.prototype.getTranslatedShaderSource = function(shader) {};
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
+ * @constructor
+ * @noalias
+ */
+function WEBGL_compressed_texture_s3tc() {}
+
+/** @type {number} */
+WEBGL_compressed_texture_s3tc.prototype.COMPRESSED_RGB_S3TC_DXT1_EXT;
+
+/** @type {number} */
+WEBGL_compressed_texture_s3tc.prototype.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+
+/** @type {number} */
+WEBGL_compressed_texture_s3tc.prototype.COMPRESSED_RGBA_S3TC_DXT3_EXT;
+
+/** @type {number} */
+WEBGL_compressed_texture_s3tc.prototype.COMPRESSED_RGBA_S3TC_DXT5_EXT;
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_depth_texture/
+ * @constructor
+ * @noalias
+ */
+function OES_depth_texture() {}
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/
+ * @constructor
+ * @noalias
+ */
+function OES_element_index_uint() {}
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
+ * @constructor
+ * @noalias
+ */
+function EXT_texture_filter_anisotropic() {}
+
+/** @type {number} */
+EXT_texture_filter_anisotropic.prototype.TEXTURE_MAX_ANISOTROPY_EXT;
+
+/** @type {number} */
+EXT_texture_filter_anisotropic.prototype.MAX_TEXTURE_MAX_ANISOTROPY_EXT;
+
+
+
+/**
+ * @see http://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
+ * @constructor
+ * @noalias
+ */
+function ANGLE_instanced_arrays() {}
+
+
+/** @type {number} */
+ANGLE_instanced_arrays.prototype.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE;
+
+
+/**
+ * @param {number} mode Primitive type.
+ * @param {number} first First vertex.
+ * @param {number} count Number of vertices per instance.
+ * @param {number} primcount Number of instances.
+ */
+ANGLE_instanced_arrays.prototype.drawArraysInstancedANGLE = function(
+ mode, first, count, primcount) {};
+
+
+/**
+ * @param {number} mode Primitive type.
+ * @param {number} count Number of vertex indices per instance.
+ * @param {number} type Type of a vertex index.
+ * @param {number} offset Offset to the first vertex index.
+ * @param {number} primcount Number of instances.
+ */
+ANGLE_instanced_arrays.prototype.drawElementsInstancedANGLE = function(
+ mode, count, type, offset, primcount) {};
+
+
+/**
+ * @param {number} index Attribute index.
+ * @param {number} divisor Instance divisor.
+ */
+ANGLE_instanced_arrays.prototype.vertexAttribDivisorANGLE = function(
+ index, divisor) {};
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLRenderingContextBase}
+ */
+function WebGLRenderingContext() {}
+
+
+/**
+ * @constructor
+ * @private
+ * @noalias
+ * @extends {WebGLRenderingContextBase}
+ */
+function WebGL2RenderingContextBase() {}
+
+
+/** @type {number} */
+WebGL2RenderingContextBase.READ_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNPACK_ROW_LENGTH;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNPACK_SKIP_ROWS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNPACK_SKIP_PIXELS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PACK_ROW_LENGTH;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PACK_SKIP_ROWS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PACK_SKIP_PIXELS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH;
+
+/** @type {number} */
+WebGL2RenderingContextBase.STENCIL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB10_A2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_BINDING_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNPACK_SKIP_IMAGES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNPACK_IMAGE_HEIGHT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_WRAP_R;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_3D_TEXTURE_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_2_10_10_10_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_ELEMENTS_VERTICES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_ELEMENTS_INDICES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_MIN_LOD;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_MAX_LOD;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_BASE_LEVEL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_MAX_LEVEL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MIN;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH_COMPONENT24;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_TEXTURE_LOD_BIAS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_COMPARE_MODE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_COMPARE_FUNC;
+
+/** @type {number} */
+WebGL2RenderingContextBase.CURRENT_QUERY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.QUERY_RESULT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.QUERY_RESULT_AVAILABLE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.STREAM_READ;
+
+/** @type {number} */
+WebGL2RenderingContextBase.STREAM_COPY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.STATIC_READ;
+
+/** @type {number} */
+WebGL2RenderingContextBase.STATIC_COPY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DYNAMIC_READ;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DYNAMIC_COPY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_DRAW_BUFFERS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER0;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER1;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER5;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER6;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER7;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER9;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER10;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER11;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER12;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER13;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER14;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_BUFFER15;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_FRAGMENT_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_VERTEX_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SAMPLER_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SAMPLER_2D_SHADOW;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAGMENT_SHADER_DERIVATIVE_HINT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PIXEL_PACK_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PIXEL_UNPACK_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PIXEL_PACK_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.PIXEL_UNPACK_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_MAT2x3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_MAT2x4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_MAT3x2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_MAT3x4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_MAT4x2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_MAT4x3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SRGB;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SRGB8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SRGB8_ALPHA8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COMPARE_REF_TO_TEXTURE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.VERTEX_ATTRIB_ARRAY_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_ARRAY_TEXTURE_LAYERS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MIN_PROGRAM_TEXEL_OFFSET;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_PROGRAM_TEXEL_OFFSET;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_VARYING_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_BINDING_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R11F_G11F_B10F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_10F_11F_11F_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB9_E5;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_5_9_9_9_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_BUFFER_MODE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_VARYINGS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_BUFFER_START;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_BUFFER_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RASTERIZER_DISCARD;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INTERLEAVED_ATTRIBS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SEPARATE_ATTRIBS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RED_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SAMPLER_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SAMPLER_2D_ARRAY_SHADOW;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SAMPLER_CUBE_SHADOW;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_VEC2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_VEC3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_VEC4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INT_SAMPLER_2D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INT_SAMPLER_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INT_SAMPLER_CUBE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INT_SAMPLER_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_SAMPLER_2D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_SAMPLER_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_SAMPLER_CUBE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_SAMPLER_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH_COMPONENT32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH32F_STENCIL8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FLOAT_32_UNSIGNED_INT_24_8_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_RED_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_DEFAULT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH_STENCIL_ATTACHMENT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH_STENCIL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_INT_24_8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DEPTH24_STENCIL8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNED_NORMALIZED;
+
+// Same as FRAMEBUFFER_BINDING
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_FRAMEBUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.READ_FRAMEBUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.DRAW_FRAMEBUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.READ_FRAMEBUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RENDERBUFFER_SAMPLES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_COLOR_ATTACHMENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT1;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT5;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT6;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT7;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT9;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT10;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT11;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT12;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT13;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT14;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COLOR_ATTACHMENT15;
+
+/** @type {number} */
+WebGL2RenderingContextBase.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_SAMPLES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.HALF_FLOAT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.VERTEX_ARRAY_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.R8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RG8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGBA8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SIGNED_NORMALIZED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COPY_READ_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.COPY_WRITE_BUFFER;
+
+// Same as COPY_READ_BUFFER
+/** @type {number} */
+WebGL2RenderingContextBase.COPY_READ_BUFFER_BINDING;
+
+// Same as COPY_WRITE_BUFFER
+/** @type {number} */
+WebGL2RenderingContextBase.COPY_WRITE_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BUFFER_START;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BUFFER_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_VERTEX_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_FRAGMENT_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_COMBINED_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_UNIFORM_BUFFER_BINDINGS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_UNIFORM_BLOCK_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BUFFER_OFFSET_ALIGNMENT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.ACTIVE_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_TYPE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_INDEX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_OFFSET;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_ARRAY_STRIDE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_MATRIX_STRIDE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_IS_ROW_MAJOR;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_DATA_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_ACTIVE_UNIFORMS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INVALID_INDEX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_VERTEX_OUTPUT_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_FRAGMENT_INPUT_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_SERVER_WAIT_TIMEOUT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.OBJECT_TYPE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SYNC_CONDITION;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SYNC_STATUS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SYNC_FLAGS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SYNC_FENCE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SYNC_GPU_COMMANDS_COMPLETE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.UNSIGNALED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SIGNALED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.ALREADY_SIGNALED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TIMEOUT_EXPIRED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.CONDITION_SATISFIED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.WAIT_FAILED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SYNC_FLUSH_COMMANDS_BIT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.VERTEX_ATTRIB_ARRAY_DIVISOR;
+
+/** @type {number} */
+WebGL2RenderingContextBase.ANY_SAMPLES_PASSED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.ANY_SAMPLES_PASSED_CONSERVATIVE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.SAMPLER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.RGB10_A2UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.INT_2_10_10_10_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_PAUSED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_ACTIVE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TRANSFORM_FEEDBACK_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_IMMUTABLE_FORMAT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.MAX_ELEMENT_INDEX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.NUM_SAMPLE_COUNTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TEXTURE_IMMUTABLE_LEVELS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.TIMEOUT_IGNORED;
+
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.READ_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNPACK_ROW_LENGTH;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNPACK_SKIP_ROWS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNPACK_SKIP_PIXELS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PACK_ROW_LENGTH;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PACK_SKIP_ROWS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PACK_SKIP_PIXELS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.STENCIL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB10_A2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_BINDING_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNPACK_SKIP_IMAGES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNPACK_IMAGE_HEIGHT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_WRAP_R;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_3D_TEXTURE_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_2_10_10_10_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_ELEMENTS_VERTICES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_ELEMENTS_INDICES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_MIN_LOD;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_MAX_LOD;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_BASE_LEVEL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_MAX_LEVEL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MIN;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH_COMPONENT24;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_TEXTURE_LOD_BIAS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_COMPARE_MODE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_COMPARE_FUNC;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.CURRENT_QUERY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.QUERY_RESULT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.QUERY_RESULT_AVAILABLE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.STREAM_READ;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.STREAM_COPY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.STATIC_READ;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.STATIC_COPY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DYNAMIC_READ;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DYNAMIC_COPY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_DRAW_BUFFERS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER0;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER1;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER5;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER6;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER7;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER9;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER10;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER11;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER12;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER13;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER14;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_BUFFER15;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_FRAGMENT_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_VERTEX_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SAMPLER_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SAMPLER_2D_SHADOW;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAGMENT_SHADER_DERIVATIVE_HINT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PIXEL_PACK_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PIXEL_UNPACK_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PIXEL_PACK_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.PIXEL_UNPACK_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_MAT2x3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_MAT2x4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_MAT3x2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_MAT3x4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_MAT4x2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_MAT4x3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SRGB;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SRGB8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SRGB8_ALPHA8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COMPARE_REF_TO_TEXTURE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_ARRAY_TEXTURE_LAYERS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MIN_PROGRAM_TEXEL_OFFSET;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_PROGRAM_TEXEL_OFFSET;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_VARYING_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_BINDING_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R11F_G11F_B10F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_10F_11F_11F_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB9_E5;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_5_9_9_9_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_BUFFER_MODE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_VARYINGS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_BUFFER_START;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_BUFFER_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RASTERIZER_DISCARD;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INTERLEAVED_ATTRIBS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SEPARATE_ATTRIBS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RED_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SAMPLER_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SAMPLER_2D_ARRAY_SHADOW;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SAMPLER_CUBE_SHADOW;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_VEC2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_VEC3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_VEC4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INT_SAMPLER_2D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INT_SAMPLER_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INT_SAMPLER_CUBE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INT_SAMPLER_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_SAMPLER_2D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_SAMPLER_3D;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_SAMPLER_CUBE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_SAMPLER_2D_ARRAY;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH_COMPONENT32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH32F_STENCIL8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FLOAT_32_UNSIGNED_INT_24_8_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_RED_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_DEFAULT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH_STENCIL_ATTACHMENT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH_STENCIL;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_INT_24_8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DEPTH24_STENCIL8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNED_NORMALIZED;
+
+// Same as FRAMEBUFFER_BINDING
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_FRAMEBUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.READ_FRAMEBUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.DRAW_FRAMEBUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.READ_FRAMEBUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RENDERBUFFER_SAMPLES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_COLOR_ATTACHMENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT1;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT2;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT3;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT4;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT5;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT6;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT7;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT9;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT10;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT11;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT12;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT13;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT14;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COLOR_ATTACHMENT15;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_SAMPLES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.HALF_FLOAT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG_INTEGER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG8;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG16F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG32F;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG8I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG8UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG16I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG16UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG32I;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG32UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.VERTEX_ARRAY_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.R8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RG8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGBA8_SNORM;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SIGNED_NORMALIZED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COPY_READ_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COPY_WRITE_BUFFER;
+
+// Same as COPY_READ_BUFFER
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COPY_READ_BUFFER_BINDING;
+
+// Same as COPY_WRITE_BUFFER
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.COPY_WRITE_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BUFFER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BUFFER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BUFFER_START;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BUFFER_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_VERTEX_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_FRAGMENT_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_COMBINED_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_UNIFORM_BUFFER_BINDINGS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_UNIFORM_BLOCK_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BUFFER_OFFSET_ALIGNMENT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.ACTIVE_UNIFORM_BLOCKS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_TYPE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_INDEX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_OFFSET;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_ARRAY_STRIDE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_MATRIX_STRIDE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_IS_ROW_MAJOR;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_DATA_SIZE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_ACTIVE_UNIFORMS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INVALID_INDEX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_VERTEX_OUTPUT_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_FRAGMENT_INPUT_COMPONENTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_SERVER_WAIT_TIMEOUT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.OBJECT_TYPE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SYNC_CONDITION;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SYNC_STATUS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SYNC_FLAGS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SYNC_FENCE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SYNC_GPU_COMMANDS_COMPLETE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.UNSIGNALED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SIGNALED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.ALREADY_SIGNALED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TIMEOUT_EXPIRED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.CONDITION_SATISFIED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.WAIT_FAILED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SYNC_FLUSH_COMMANDS_BIT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.VERTEX_ATTRIB_ARRAY_DIVISOR;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.ANY_SAMPLES_PASSED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.ANY_SAMPLES_PASSED_CONSERVATIVE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.SAMPLER_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.RGB10_A2UI;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.INT_2_10_10_10_REV;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_PAUSED;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_ACTIVE;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TRANSFORM_FEEDBACK_BINDING;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_IMMUTABLE_FORMAT;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.MAX_ELEMENT_INDEX;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.NUM_SAMPLE_COUNTS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TEXTURE_IMMUTABLE_LEVELS;
+
+/** @type {number} */
+WebGL2RenderingContextBase.prototype.TIMEOUT_IGNORED;
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLQuery() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLSampler() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLSync() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLTransformFeedback() {}
+
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGLObject}
+ */
+function WebGLVertexArrayObject() {}
+
+
+/**
+ * @param {number} target
+ * @param {WebGLQuery} query
+ */
+WebGL2RenderingContextBase.prototype.beginQuery = function(target, query) {};
+
+/**
+ * @param {number} primitiveMode
+ */
+WebGL2RenderingContextBase.prototype.beginTransformFeedback = function(primitiveMode) {};
+
+/**
+ * @param {number} target
+ * @param {number} index
+ * @param {WebGLBuffer} buffer
+ */
+WebGL2RenderingContextBase.prototype.bindBufferBase = function(target, index, buffer) {};
+
+/**
+ * @param {number} target
+ * @param {number} index
+ * @param {WebGLBuffer} buffer
+ * @param {number} offset
+ * @param {number} size
+ */
+WebGL2RenderingContextBase.prototype.bindBufferRange = function(target, index, buffer, offset, size) {};
+
+/**
+ * @param {number} unit
+ * @param {WebGLSampler} sampler
+ */
+WebGL2RenderingContextBase.prototype.bindSampler = function(unit, sampler) {};
+
+/**
+ * @param {number} target
+ * @param {WebGLTransformFeedback} id
+ */
+WebGL2RenderingContextBase.prototype.bindTransformFeedback = function(target, id) {};
+
+/**
+ * @param {WebGLVertexArrayObject} array
+ */
+WebGL2RenderingContextBase.prototype.bindVertexArray = function(array) {};
+
+/**
+ * @param {number} srcX0
+ * @param {number} srcY0
+ * @param {number} srcX1
+ * @param {number} srcY1
+ * @param {number} dstX0
+ * @param {number} dstY0
+ * @param {number} dstX1
+ * @param {number} dstY1
+ * @param {number} mask
+ * @param {number} filter
+ */
+WebGL2RenderingContextBase.prototype.blitFramebuffer = function(
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+ dstX1, dstY1, mask, filter) {};
+
+/**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {Int32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.clearBufferiv = function(buffer, drawbuffer, value) {};
+
+/**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {Uint32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.clearBufferuiv = function(buffer, drawbuffer, value) {};
+
+/**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.clearBufferfv = function(buffer, drawbuffer, value) {};
+
+/**
+ * @param {number} buffer
+ * @param {number} drawbuffer
+ * @param {number} depth
+ * @param {number} stencil
+ */
+WebGL2RenderingContextBase.prototype.clearBufferfi = function(buffer, drawbuffer, depth, stencil) {};
+
+/**
+ * @param {WebGLSync} sync
+ * @param {number} flags
+ * @param {number} timeout
+ * @return {number}
+ */
+WebGL2RenderingContextBase.prototype.clientWaitSync = function(sync, flags, timeout) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} border
+ * @param {ArrayBufferView} data
+ */
+WebGL2RenderingContextBase.prototype.compressedTexImage3D = function(
+ target, level, internalformat, width, height, depth, border, data) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} zoffset
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} format
+ * @param {ArrayBufferView} data
+ */
+WebGL2RenderingContextBase.prototype.compressedTexSubImage3D = function(
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, data) {};
+
+/**
+ * @param {number} readTarget
+ * @param {number} writeTarget
+ * @param {number} readOffset
+ * @param {number} writeOffset
+ * @param {number} size
+ */
+WebGL2RenderingContextBase.prototype.copyBufferSubData = function(
+ readTarget, writeTarget, readOffset, writeOffset, size) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} zoffset
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+WebGL2RenderingContextBase.prototype.copyTexSubImage3D = function(
+ target, level, xoffset, yoffset, zoffset, x, y, width, height) {};
+
+/**
+ * @return {!WebGLQuery}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.createQuery = function() {};
+
+/**
+ * @return {!WebGLSampler}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.createSampler = function() {};
+
+/**
+ * @return {!WebGLTransformFeedback}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.createTransformFeedback = function() {};
+
+/**
+ * @return {!WebGLVertexArrayObject}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.createVertexArray = function() {};
+
+
+/**
+ * @param {WebGLQuery} query
+ */
+WebGL2RenderingContextBase.prototype.deleteQuery = function(query) {};
+
+/**
+ * @param {WebGLSampler} sampler
+ */
+WebGL2RenderingContextBase.prototype.deleteSampler = function(sampler) {};
+
+/**
+ * @param {WebGLSync} sync
+ */
+WebGL2RenderingContextBase.prototype.deleteSync = function(sync) {};
+
+/**
+ * @param {WebGLTransformFeedback} feedback
+ */
+WebGL2RenderingContextBase.prototype.deleteTransformFeedback = function(feedback) {};
+
+/**
+ * @param {WebGLVertexArrayObject} vertexArray
+ */
+WebGL2RenderingContextBase.prototype.deleteVertexArray = function(vertexArray) {};
+
+/**
+ * @param {number} mode
+ * @param {number} first
+ * @param {number} count
+ * @param {number} instanceCount
+ */
+WebGL2RenderingContextBase.prototype.drawArraysInstanced = function(mode, first, count, instanceCount) {};
+
+/**
+ * @param {number} mode
+ * @param {number} count
+ * @param {number} type
+ * @param {number} offset
+ * @param {number} instanceCount
+ */
+WebGL2RenderingContextBase.prototype.drawElementsInstanced = function(mode, count, type, offset, instanceCount) {};
+
+/**
+ * @param {number} mode
+ * @param {number} start
+ * @param {number} end
+ * @param {number} count
+ * @param {number} type
+ * @param {number} offset
+ */
+WebGL2RenderingContextBase.prototype.drawRangeElements = function(mode, start, end, count, type, offset) {};
+
+/**
+ * @param {Array.<number>} buffers
+ */
+WebGL2RenderingContextBase.prototype.drawBuffers = function(buffers) {};
+
+/**
+ * @param {number} target
+ */
+WebGL2RenderingContextBase.prototype.endQuery = function(target) {};
+
+/**
+ */
+WebGL2RenderingContextBase.prototype.endTransformFeedback = function() {};
+
+/**
+ * @param {number} condition
+ * @param {number} flags
+ * @return {WebGLSync}
+ */
+WebGL2RenderingContextBase.prototype.fenceSync = function(condition, flags) {};
+
+/**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {WebGLTexture} texture
+ * @param {number} level
+ * @param {number} layer
+ */
+WebGL2RenderingContextBase.prototype.framebufferTextureLayer = function(
+ target, attachment, texture, level, layer) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} uniformBlockIndex
+ * @return {string}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getActiveUniformBlockName = function(program, uniformBlockIndex) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} uniformBlockIndex
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getActiveUniformBlockParameter = function(
+ program, uniformBlockIndex, pname) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {Array.<number>} uniformIndices
+ * @param {number} pname
+ * @return {Array.<number>}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getActiveUniforms = function(
+ program, uniformIndices, pname) {};
+
+/**
+ * @param {number} target
+ * @param {number} offset
+ * @param {ArrayBuffer} returnedData
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getBufferSubData = function(
+ target, offset, returnedData) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {string} name
+ * @return {number}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getFragDataLocation = function(program, name) {};
+
+/**
+ * @param {number} target
+ * @param {number} index
+ * @return {*}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getIndexedParameter = function(target, index) {};
+
+/**
+ * @param {number} target
+ * @param {number} internalformat
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getInternalformatParameter = function(target, internalformat, pname) {};
+
+/**
+ * @param {number} target
+ * @param {number} pname
+ * @return {WebGLQuery}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getQuery = function(target, pname) {};
+
+/**
+ * @param {WebGLQuery} query
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getQueryParameter = function(query, pname) {};
+
+/**
+ * @param {WebGLSampler} sampler
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getSamplerParameter = function(sampler, pname) {};
+
+/**
+ * @param {WebGLSync} sync
+ * @param {number} pname
+ * @return {*}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getSyncParameter = function(sync, pname) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} index
+ * @return {WebGLActiveInfo}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getTransformFeedbackVarying = function(program, index) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {string} uniformBlockName
+ * @return {number}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getUniformBlockIndex = function(program, uniformBlockName) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {Array.<string>} uniformNames
+ * @return {Array.<number>}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.getUniformIndices = function(program, uniformNames) {};
+
+/**
+ * @param {number} target
+ * @param {Array.<number>} attachments
+ */
+WebGL2RenderingContextBase.prototype.invalidateFramebuffer = function(target, attachments) {};
+
+/**
+ * @param {number} target
+ * @param {Array.<number>} attachments
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+WebGL2RenderingContextBase.prototype.invalidateSubFramebuffer = function(
+ target, attachments, x, y, width, height) {};
+
+/**
+ * @param {WebGLQuery} query
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.isQuery = function(query) {};
+
+/**
+ * @param {WebGLSampler} sampler
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.isSampler = function(sampler) {};
+
+/**
+ * @param {WebGLSync} sync
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.isSync = function(sync) {};
+
+/**
+ * @param {WebGLTransformFeedback} feedback
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.isTransformFeedback = function(feedback) {};
+
+/**
+ * @param {WebGLVertexArrayObject} vertexArray
+ * @return {boolean}
+ * @nosideeffects
+ */
+WebGL2RenderingContextBase.prototype.isVertexArray = function(vertexArray) {};
+
+/**
+ */
+WebGL2RenderingContextBase.prototype.pauseTransformFeedback = function() {};
+
+/**
+ * @param {number} src
+ */
+WebGL2RenderingContextBase.prototype.readBuffer = function(src) {};
+
+/**
+ * @param {number} target
+ * @param {number} samples
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ */
+WebGL2RenderingContextBase.prototype.renderbufferStorageMultisample = function(
+ target, samples, internalformat, width, height) {};
+
+/**
+ */
+WebGL2RenderingContextBase.prototype.resumeTransformFeedback = function() {};
+
+/**
+ * @param {WebGLSampler} sampler
+ * @param {number} pname
+ * @param {number} param
+ */
+WebGL2RenderingContextBase.prototype.samplerParameteri = function(sampler, pname, param) {};
+
+/**
+ * @param {WebGLSampler} sampler
+ * @param {number} pname
+ * @param {number} param
+ */
+WebGL2RenderingContextBase.prototype.samplerParameterf = function(sampler, pname, param) {};
+
+/**
+ * @param {number} target
+ * @param {number} levels
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ */
+WebGL2RenderingContextBase.prototype.texStorage2D = function(target, levels, internalformat, width, height) {};
+
+/**
+ * @param {number} target
+ * @param {number} levels
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ */
+WebGL2RenderingContextBase.prototype.texStorage3D = function(target, levels, internalformat, width, height, depth) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} internalformat
+ * @param {number} width
+ * @param {number} height
+ * @param {number} depth
+ * @param {number} border
+ * @param {number} format
+ * @param {number} type
+ * @param {ArrayBufferView} pixels
+ */
+WebGL2RenderingContextBase.prototype.texImage3D = function(
+ target, level, internalformat, width, height, depth, border, format, type, pixels) {};
+
+/**
+ * @param {number} target
+ * @param {number} level
+ * @param {number} xoffset
+ * @param {number} yoffset
+ * @param {number} zoffset
+ * @param {number} format or width
+ * @param {number} type or height
+ * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|
+ * number} source or depth
+ * @param {number=} opt_format
+ * @param {number=} opt_type
+ * @param {ArrayBufferView=} opt_pixels
+ */
+WebGL2RenderingContextBase.prototype.texSubImage3D = function(
+ target, level, xoffset, yoffset, zoffset, format, type, source, opt_format, opt_type, opt_pixels) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {Array.<string>} varyings
+ * @param {number} bufferMode
+ */
+WebGL2RenderingContextBase.prototype.transformFeedbackVaryings = function(program, varyings, bufferMode) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} v0
+ */
+WebGL2RenderingContextBase.prototype.uniform1ui = function(location, v0) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} v0
+ * @param {number} v1
+ */
+WebGL2RenderingContextBase.prototype.uniform2ui = function(location, v0, v1) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} v0
+ * @param {number} v1
+ * @param {number} v2
+ */
+WebGL2RenderingContextBase.prototype.uniform3ui = function(location, v0, v1, v2) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {number} v0
+ * @param {number} v1
+ * @param {number} v2
+ * @param {number} v3
+ */
+WebGL2RenderingContextBase.prototype.uniform4ui = function(location, v0, v1, v2, v3) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Uint32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniform1uiv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Uint32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniform2uiv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Uint32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniform3uiv = function(location, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {Uint32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniform4uiv = function(location, value) {};
+
+/**
+ * @param {WebGLProgram} program
+ * @param {number} uniformBlockIndex
+ * @param {number} uniformBlockBinding
+ */
+WebGL2RenderingContextBase.prototype.uniformBlockBinding = function(program, uniformBlockIndex, uniformBlockBinding) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniformMatrix2x3fv = function(location, transpose, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniformMatrix3x2fv = function(location, transpose, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniformMatrix2x4fv = function(location, transpose, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniformMatrix4x2fv = function(location, transpose, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniformMatrix3x4fv = function(location, transpose, value) {};
+
+/**
+ * @param {WebGLUniformLocation} location
+ * @param {boolean} transpose
+ * @param {Float32Array|Array.<number>} value
+ */
+WebGL2RenderingContextBase.prototype.uniformMatrix4x3fv = function(location, transpose, value) {};
+
+/**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+WebGL2RenderingContextBase.prototype.vertexAttribI4i = function(index, x, y, z, w) {};
+
+/**
+ * @param {number} index
+ * @param {(Array.<number>|Int32Array)} v
+ */
+WebGL2RenderingContextBase.prototype.vertexAttribI4iv = function(index, v) {};
+
+/**
+ * @param {number} index
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {number} w
+ */
+WebGL2RenderingContextBase.prototype.vertexAttribI4ui = function(index, x, y, z, w) {};
+
+/**
+ * @param {number} index
+ * @param {(Array.<number>|Uint32Array)} v
+ */
+WebGL2RenderingContextBase.prototype.vertexAttribI4uiv = function(index, v) {};
+
+/**
+ * @param {number} index
+ * @param {number} size
+ * @param {number} type
+ * @param {number} stride
+ * @param {number} offset
+ */
+WebGL2RenderingContextBase.prototype.vertexAttribIPointer = function(index, size, type, stride, offset) {};
+
+/**
+ * @param {number} index
+ * @param {number} divisor
+ */
+WebGL2RenderingContextBase.prototype.vertexAttribDivisor = function(index, divisor) {};
+
+/**
+ * @param {WebGLSync} sync
+ * @param {number} flags
+ * @param {number} timeout
+ */
+WebGL2RenderingContextBase.prototype.waitSync = function(sync, flags, timeout) {};
+
+/**
+ * @constructor
+ * @noalias
+ * @extends {WebGL2RenderingContextBase}
+ */
+function WebGL2RenderingContext() {}
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/50x50pixel-black-with-red-triangle.png b/dom/canvas/test/webgl-conf/checkout/extra/50x50pixel-black-with-red-triangle.png
new file mode 100644
index 0000000000..4ec9751070
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/50x50pixel-black-with-red-triangle.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/big-fbos-example.html b/dom/canvas/test/webgl-conf/checkout/extra/big-fbos-example.html
new file mode 100644
index 0000000000..0e0a09bcef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/big-fbos-example.html
@@ -0,0 +1,256 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Big FBO Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../../devtools/src/debug/webgl-debug.js"></script>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="256" height="256"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vec4(vPosition.xyz, 1.0);
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+<script>
+"use strict";
+window.onload = init;
+
+var g_textures = [];
+
+debug("Tests the performance of using lots of large FBOs");
+
+function init() {
+ if (confirm(
+ "After clicking OK your machine may become unresponsive or crash.")) {
+ main();
+ } else {
+ debug("cancelled");
+ }
+}
+
+function checkFBOStatus(gl) {
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ if (err != gl.OUT_OF_MEMORY)
+ testFailed("gl.getError returned " + err);
+ else
+ testPassed("OUT-OF-MEMORY");
+ return false;
+ }
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("gl.checkFramebufferStatus() returned " + WebGLTestUtils.glEnumToString(gl, status));
+ return false;
+ }
+ return true;
+}
+
+function setupFBO(gl, size) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ size, // width
+ size, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ if (!checkFBOStatus(gl))
+ return null;
+
+ return { fb: fb, tex: tex };
+}
+
+function checkPixels(gl) {
+ var width = 256;
+ var height = 256;
+
+ var thresh = 3;
+
+ var buf = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ if (Math.abs(buf[offset] - 255) > thresh ||
+ Math.abs(buf[offset + 1] - 0) > thresh ||
+ Math.abs(buf[offset + 2] - 0) > thresh) {
+ testFailed("drawing results incorrect");
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+function handleContextLost() {
+ debug("context lost");
+}
+
+function main() {
+ debug("");
+ debug("Checking for out of memory handling.");
+
+ var canvas = document.getElementById("canvas");
+ canvas.addEventListener('webglcontextlost', handleContextLost);
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("canvas");
+ var prog = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition", "texCoord0"]);
+
+ WebGLDebugUtils.init(gl);
+
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1,1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ var texLoc = gl.getUniformLocation(prog, "tex");
+ gl.uniform1i(texLoc, 0);
+
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed");
+
+ var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
+ debug("max render buffer size: " + size +
+ ", size used: " + (size / 2));
+ size /= 2;
+
+ var maxFBOs = 200;
+ var numFBOs = 0;
+ allocateNextFBO();
+
+ function allocateNextFBO() {
+ if (numFBOs >= maxFBOs) {
+ phase2();
+ return;
+ }
+ if (!allocateFBO()) {
+ phase2();
+ return;
+ }
+ ++numFBOs;
+ setTimeout(allocateNextFBO, 100);
+ }
+
+ function allocateFBO() {
+ debug("");
+ debug("trying to create fbo #" + (numFBOs + 1));
+ var t = setupFBO(gl, 2);
+ if (!t) {
+ return false;
+ }
+
+ var tex = t.tex;
+ var fb = t.fb;
+
+ debug("allocating fbo color buffer of size " + size + " x " + size);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ size, // width
+ size, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ if (!checkFBOStatus(gl)) {
+ return false;
+ }
+ g_textures.push(tex);
+ debug("succeeded in creating fbo");
+
+ debug("clearing the fbo with red color");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.clearColor(1, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ debug("deleting fbo, but the now red texture should be untouched");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fb);
+
+ debug("drawing to the canvas using the red texture");
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ if (!checkPixels(gl)) {
+ return false;
+ }
+
+ debug("succeeded in drawing");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "each run with no error");
+ return true;
+ }
+
+ function phase2() {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ debug("");
+ debug("fbos allocated:" + numFBOs);
+ if (!checkPixels(gl)) {
+ testFailed("final check of canvas drawing buffer pixels failed");
+ }
+ debug("");
+ finishTest();
+ }
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/buffer-gc-stress.html b/dom/canvas/test/webgl-conf/checkout/extra/buffer-gc-stress.html
new file mode 100644
index 0000000000..86056747e2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/buffer-gc-stress.html
@@ -0,0 +1,155 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Float32Array garbage collection test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="40" height="40"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 inPosition;
+attribute vec4 inColor;
+
+varying vec4 color;
+
+void main()
+{
+ color = inColor;
+
+ gl_Position = vec4(inPosition, 0.0, 1.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 color;
+
+void main()
+{
+ if (color == vec4(0.0))
+ discard;
+
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+"use strict";
+
+description("Allocates a buffer object and then updates it repeatedly using throw-away Float32Array objects. " +
+ "Ideally, this should not result in a browser crash or instability, since GC should be able to collect all Float32Arrays.");
+var wtu = WebGLTestUtils;
+
+var vertices = [];
+var w = 0.25;
+for (var x = -1; x < 1; x += w) {
+ for (var y = -1; y < 1; y += w) {
+ vertices.push(x + w, y + w);
+ vertices.push(x, y + w);
+ vertices.push(x, y );
+
+ vertices.push(x + w, y + w);
+ vertices.push(x, y );
+ vertices.push(x + w, y );
+ }
+}
+var numVertices = (vertices.length / 2);
+
+var gl;
+var squareBuffer;
+var buffer;
+var updateBufferData;
+var drawIterationsPerTest = 100;
+
+function initGL() {
+ gl = wtu.create3DContext("canvas");
+ var attribs = ["inPosition", "inColor"];
+ wtu.setupProgram(gl, ["vshader", "fshader"], attribs);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ squareBuffer = gl.createBuffer();
+ gl.enableVertexAttribArray(0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, squareBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ buffer = gl.createBuffer();
+ gl.enableVertexAttribArray(1);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+}
+
+var testIndex = -1;
+var drawIterations = 0;
+var size = 0;
+function runNextTest() {
+ ++testIndex;
+ var prevSize = size;
+ size = Math.pow(2, testIndex) * numVertices * 16;
+
+ if (size > 2 * 1024 * 1024 && prevSize <= 2 * 1024 * 1024) {
+ if (!confirm("The following tests can cause unresponsiveness or instability. Press OK to continue.")) {
+ testFailed("Tests aborted");
+ return;
+ }
+ }
+
+ if (size > 64 * 1024 * 1024) {
+ gl.deleteBuffer(buffer);
+ testPassed("Tests finished");
+ return;
+ }
+
+ debug('Initializing buffer with size: ' + size);
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, size, gl.DYNAMIC_DRAW);
+ updateBufferData = new Float32Array(size / 4);
+
+ debug("Drawing " + drawIterationsPerTest + " times, each time creating a new throw-away Float32Array of size " + size + " and using it to update the buffer");
+ drawIterations = 0;
+ doDraw();
+};
+
+var doDraw = function() {
+ gl.clearColor(0, 255, 0, 255);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Update the array buffer with a throw-away Float32Array
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array(updateBufferData));
+
+ gl.drawArrays(gl.TRIANGLES, 0, numVertices);
+ var error = gl.getError();
+ if (error !== gl.NO_ERROR) {
+ testFailed("drawArrays failed with error " + wtu.glEnumToString(gl, error));
+ return;
+ }
+ if (drawIterations < drawIterationsPerTest) {
+ ++drawIterations;
+ requestAnimationFrame(doDraw);
+ } else {
+ runNextTest();
+ }
+};
+
+initGL();
+runNextTest();
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/buffer-sizes.html b/dom/canvas/test/webgl-conf/checkout/extra/buffer-sizes.html
new file mode 100644
index 0000000000..736c135b7a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/buffer-sizes.html
@@ -0,0 +1,268 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Buffer allocation test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="canvasParent"></div>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 inPosition;
+attribute vec4 inColor0;
+attribute vec4 inColor1;
+attribute vec4 inColor2;
+attribute vec4 inColor3;
+attribute vec4 inColor4;
+attribute vec4 inColor5;
+attribute vec4 inColor6;
+attribute vec4 inColor7;
+
+varying vec4 color;
+
+void main()
+{
+ color = abs(inColor0) + abs(inColor1) + abs(inColor2) + abs(inColor3) +
+ abs(inColor4) + abs(inColor5) + abs(inColor6) + abs(inColor7);
+
+ color = clamp(color, vec4(0.0), vec4(1.0));
+
+ gl_Position = vec4(inPosition, 0.0, 1.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 color;
+
+void main()
+{
+ if (color == vec4(0.0))
+ discard;
+
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+description("Allocates a number of different sized buffers and checks that the buffers are cleared " +
+ "OR that the allocation results in gl.OUT_OF_MEMORY or context loss.");
+var wtu = WebGLTestUtils;
+
+// The shader processes eight vec4 attributes at once to reduce the amount of
+// draw calls.
+var numColorAttrs = 8;
+
+// Process 64 squares at once to also reduce the amount of draw calls.
+var vertices = [];
+var w = 0.25;
+for (var x = -1; x < 1; x += w) {
+ for (var y = -1; y < 1; y += w) {
+ vertices.push(x + w, y + w);
+ vertices.push(x, y + w);
+ vertices.push(x, y );
+
+ vertices.push(x + w, y + w);
+ vertices.push(x, y );
+ vertices.push(x + w, y );
+ }
+}
+var numVertices = (vertices.length / 2);
+
+var gl;
+var squareBuffer;
+var error = 0;
+var expectContextLost = false;
+
+function initGLForBufferSizesTest() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 40;
+ canvas.height = 40;
+ var parent = document.getElementById("canvasParent");
+ parent.innerHTML = '';
+ parent.appendChild(canvas);
+ gl = wtu.create3DContext(canvas);
+ var attribs = ["inPosition", "inColor0", "inColor1", "inColor2", "inColor3",
+ "inColor4", "inColor5", "inColor6", "inColor7"];
+ wtu.setupProgram(gl, ["vshader", "fshader"], attribs);
+ gl.enableVertexAttribArray(0);
+ for (var i = 0; i < numColorAttrs; i++) {
+ gl.enableVertexAttribArray(1 + i);
+ }
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.BLEND);
+
+ squareBuffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, squareBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
+}
+
+function createBuffer(size, allowedToFail) {
+ var msg = "Calling bufferData with size=" + size;
+ var buffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, size, gl.STATIC_DRAW);
+
+ error = gl.getError();
+ if (error !== gl.NO_ERROR) {
+ gl.deleteBuffer(buffer);
+ if (allowedToFail) {
+ if (error === gl.OUT_OF_MEMORY) {
+ testPassed(msg + " failed with gl.OUT_OF_MEMORY (this is allowed)");
+ return null;
+ } else if (error === gl.CONTEXT_LOST_WEBGL) {
+ testPassed(msg + " failed with gl.CONTEXT_LOST_WEBGL (this is allowed)");
+ return null;
+ }
+ }
+ testFailed(msg + " failed with error " + wtu.glEnumToString(gl, error));
+ return null;
+ }
+
+ testPassed(msg + " did not result in any errors");
+ var reportedSize = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
+ expectContextLost = false;
+ if (reportedSize === null) {
+ testPassed("Null size reported by gl, this should happen if the context is lost which is allowed.");
+ expectContextLost = true;
+ } else if (reportedSize !== size) {
+ if (size > Math.pow(2, 32)) {
+ testPassed("gl reported different size " + reportedSize + " for the buffer, but this is expected since " +
+ "the requested size was above what the return value of getBufferParameter can represent.");
+ } else {
+ testFailed("gl reported different size " + reportedSize + " for the buffer.");
+ }
+ } else {
+ testPassed("Size reported by gl was the same as the requested size.");
+ }
+
+ return buffer;
+}
+
+// Draw a square on the canvas using attributes from the clear buffer created with bufferData.
+function drawWithBuffer(buffer, allowedToFail) {
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ var size = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
+ // Each vec4 is 16 bytes
+ var increment = numVertices * numColorAttrs * 16;
+ for (var offset = 0; offset + increment <= size; offset += increment) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, squareBuffer);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ for (var i = 0; i < numColorAttrs; i++) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.vertexAttribPointer(1 + i, 4, gl.FLOAT, false, 0,
+ offset + increment * i / numColorAttrs);
+ }
+ gl.drawArrays(gl.TRIANGLES, 0, numVertices);
+ error = gl.getError();
+
+ if (error !== gl.NO_ERROR) {
+ if (allowedToFail) {
+ if (error === gl.OUT_OF_MEMORY) {
+ testPassed("drawArrays failed with gl.OUT_OF_MEMORY (this is allowed)");
+ return;
+ } else if (error === gl.CONTEXT_LOST_WEBGL) {
+ testPassed("drawArrays failed with gl.CONTEXT_LOST_WEBGL (this is allowed)");
+ return;
+ }
+ }
+ testFailed("drawArrays failed with error " + wtu.glEnumToString(gl, error));
+ return;
+ }
+ }
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+
+// To be able to confirm the whole buffer has been cleared, the size needs to
+// be divisible by the amount of vertices. Thus most sizes are multiples of 3.
+var tests = [
+ // Reasonable sized buffers.
+ { size: 3 * 1024, allowedToFail: false, tryDrawing: true },
+ { size: 3 * 1024 * 1024, allowedToFail: false, tryDrawing: true },
+ { size: 3 * 1024 * 1024 * 16, allowedToFail: false, tryDrawing: true },
+
+ // Huge buffers, which are meant to test out of memory handling.
+ // Allowed failures are gl.OUT_OF_MEMORY or context loss.
+ // Succeeding in the allocations is allowed as well for forward compatibility.
+
+ // 1.5 GB allocation for stressing lower-end 32-bit systems.
+ // Allocation is likely to succeed on higher-end hardware.
+ { size: 3 * 1024 * 1024 * 512, allowedToFail: true, tryDrawing: true },
+ // A buffer that no implementation will be able to allocate for some time
+ // to come. To do this, we use half of the lower 43-bit half of a 44-bit
+ // memory address space, so that the size is still valid on current common
+ // 64-bit implementations, and also below 52-bit limit for exact conversion
+ // from float to long long in WebIDL (though 2^n should be safe anyway).
+ // The 4 TB size is large enough that even extrapolating the historical
+ // exponential growth trend of memory sizes, hardware in 2020's should
+ // still have some trouble actually doing the allocation.
+ { size: (1 << 12) * (1 << 30), allowedToFail: true, tryDrawing: false }
+];
+
+function finishBufferSizesTest() {
+ gl.deleteBuffer(squareBuffer);
+ finishTest();
+}
+
+var testIndex = -1;
+function runNextTest() {
+ ++testIndex;
+ if (testIndex > 0 && tests[testIndex - 1].allowedToFail) {
+ if (gl.isContextLost() || error === gl.OUT_OF_MEMORY) {
+ initGLForBufferSizesTest();
+ } else if (expectContextLost) {
+ testFailed("Context was not lost after timeout even though gl.getBufferParameter returned null.");
+ }
+ }
+ var buffer = createBuffer(tests[testIndex].size, tests[testIndex].allowedToFail);
+ if (buffer) {
+ if (tests[testIndex].tryDrawing) {
+ drawWithBuffer(buffer, tests[testIndex].allowedToFail);
+ }
+ gl.deleteBuffer(buffer);
+ }
+
+ if (testIndex + 1 >= tests.length) {
+ finishBufferSizesTest();
+ } else {
+ if (tests[testIndex + 1].allowedToFail && !tests[testIndex].allowedToFail) {
+ if (!confirm("The following tests can cause unresponsiveness or instability. Press OK to continue.")) {
+ testFailed("Tests aborted");
+ return;
+ }
+ }
+ if (tests[testIndex].allowedToFail) {
+ // Give plenty of time for possible context loss
+ setTimeout(runNextTest(), 5000);
+ } else {
+ runNextTest();
+ }
+ }
+};
+
+initGLForBufferSizesTest();
+runNextTest();
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.html b/dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.html
new file mode 100644
index 0000000000..6eab0020bc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.html
@@ -0,0 +1,88 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Canvas Compositing Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+Below are 2 50x50 pixel canvas but using CSS to display them at 100x100 pixels. <br/>
+They are solid black with a red triangle<br/>
+They each have a 10px CSS solid black border around them.<br/>
+Depending on how the browser composites the canvas with the page they will get
+a white outline<hr/>
+<div>
+2d canvas<br/>
+<canvas id="example2" width="50" height="50" style="width: 100px; height: 100px; border: 10px solid black;"></canvas>
+</div>
+<hr/>
+3d canvas<br/>
+<div>
+<canvas id="example" width="50" height="50" style="width: 100px; height: 100px; border: 10px solid black;"></canvas>
+</div>
+<hr/>
+img tag<br/>
+<img src="50x50pixel-black-with-red-triangle.png" style="width: 100px; height: 100px; border: 10px solid black;"/>
+<div id="description"></div>
+<div id="console"></div>
+ <script id="vshader" type="x-shader/x-vertex">
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ </script>
+
+ <script id="fshader" type="x-shader/x-fragment">
+ void main()
+ {
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+ }
+ </script>
+
+ <script>
+ "use strict";
+ function init()
+ {
+ var wtu = WebGLTestUtils;
+ var canvas2d = document.getElementById("example2");
+ var ctx2d = canvas2d.getContext("2d");
+ ctx2d.fillStyle = "rgba(0, 0, 0, 255)"
+ ctx2d.fillRect(0, 0, 50, 50);
+ ctx2d.fillStyle = "rgba(255, 0, 0, 255)"
+ ctx2d.beginPath();
+ ctx2d.moveTo(25, 12.5);
+ ctx2d.lineTo(12.5, 37.5);
+ ctx2d.lineTo(37.5, 37.5);
+ ctx2d.lineTo(25, 12.5);
+ ctx2d.fill();
+
+
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ 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.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ }
+
+ init();
+ var successfullyParsed = true;
+ </script>
+</body>
+<script src="../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.png b/dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.png
new file mode 100644
index 0000000000..ba80dbe760
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/canvas-compositing-test.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/constant-index-out-of-range.html b/dom/canvas/test/webgl-conf/checkout/extra/constant-index-out-of-range.html
new file mode 100644
index 0000000000..f16ade96af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/constant-index-out-of-range.html
@@ -0,0 +1,219 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Indexing with a constant expression should compile only if the index is in range</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<link rel="stylesheet" href="../resources/glsl-feature-tests.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+<script src="../js/glsl-conformance-test.js"></script>
+<script id="VertexArrayTemplate" type="x-shader/x-vertex">
+precision mediump float;
+
+uniform float ua[4];
+
+$(init)
+
+void main() {
+ float c = ua[$(constantExpression)];
+ gl_Position = vec4(c);
+}
+</script>
+<script id="FragmentArrayTemplate" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform float ua[4];
+
+$(init)
+
+void main() {
+ float c = ua[$(constantExpression)];
+ gl_FragColor = vec4(c);
+}
+</script>
+<script id="VertexVectorTemplate" type="x-shader/x-vertex">
+precision mediump float;
+
+uniform vec4 uv;
+
+$(init)
+
+void main() {
+ float c = uv[$(constantExpression)];
+ gl_Position = vec4(c);
+}
+</script>
+<script id="FragmentVectorTemplate" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform vec4 uv;
+
+$(init)
+
+void main() {
+ float c = uv[$(constantExpression)];
+ gl_FragColor = vec4(c);
+}
+</script>
+<script id="VertexMatrixTemplate" type="x-shader/x-vertex">
+precision mediump float;
+
+uniform mat4 um;
+
+$(init)
+
+void main() {
+ float c = um[$(constantExpression)].x;
+ gl_Position = vec4(c);
+}
+</script>
+<script id="FragmentMatrixTemplate" type="x-shader/x-fragment">
+precision mediump float;
+
+uniform mat4 um;
+
+$(init)
+
+void main() {
+ float c = um[$(constantExpression)].x;
+ gl_FragColor = vec4(c);
+}
+</script>
+</head>
+<body onload="runTest()">
+<div id="description"></div>
+<div id="console"></div>
+<script type="application/javascript">
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+
+// ESSL 1.00 section 4.1.9 Arrays
+// It is illegal to index an array with an integral constant expression greater than or equal to its
+// declared size. It is also illegal to index an array with a negative constant expression.
+
+// ESSL 1.00 section 5.5 Vector Components
+// Reading from or writing to a vector using a constant integral expression with a value that is negative
+// or greater than or equal to the size of the vector is illegal.
+
+// ESSL 1.00 section 5.6 Matrix components
+// The behavior when accessing a component outside the bounds of a matrix are the same as those for
+// vectors and arrays. The compiler must generate an error if the index expression is a constant expression.
+
+// ESSL 1.00 spec section 5.10.
+// A constant expression is one of
+// * a literal value (e.g., 5 or true)
+// * a global or local variable qualified as const excluding function parameters
+// * an expression formed by an operator on operands that are constant expressions, including getting
+// an element of a constant vector or a constant matrix, or a field of a constant structure
+// * a constructor whose arguments are all constant expressions
+// * a built-in function call whose arguments are all constant expressions, with the exception of the
+// texture lookup functions.
+
+var runTest = function() {
+ var vsArrayTemplate = document.getElementById('VertexArrayTemplate').text;
+ var fsArrayTemplate = document.getElementById('FragmentArrayTemplate').text;
+ var vsVectorTemplate = document.getElementById('VertexVectorTemplate').text;
+ var fsVectorTemplate = document.getElementById('FragmentVectorTemplate').text;
+ var vsMatrixTemplate = document.getElementById('VertexMatrixTemplate').text;
+ var fsMatrixTemplate = document.getElementById('FragmentMatrixTemplate').text;
+
+ var tests = [];
+
+ var pushTest = function(constantExpression, expectSuccess, opt_init) {
+ if (opt_init === undefined) {
+ opt_init = '';
+ }
+ tests.push({
+ vShaderSource: wtu.replaceParams(vsArrayTemplate, {constantExpression: constantExpression, init: opt_init}),
+ vShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Using " + constantExpression + " as an index for an array with size 4 in a vertex shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ tests.push({
+ fShaderSource: wtu.replaceParams(fsArrayTemplate, {constantExpression: constantExpression, init: opt_init}),
+ fShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Using " + constantExpression + " as an index for an array with size 4 in a fragment shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ tests.push({
+ vShaderSource: wtu.replaceParams(vsVectorTemplate, {constantExpression: constantExpression, init: opt_init}),
+ vShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Using " + constantExpression + " as a vec4 index in a vertex shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ tests.push({
+ fShaderSource: wtu.replaceParams(fsVectorTemplate, {constantExpression: constantExpression, init: opt_init}),
+ fShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Using " + constantExpression + " as a vec4 index in a fragment shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ tests.push({
+ vShaderSource: wtu.replaceParams(vsMatrixTemplate, {constantExpression: constantExpression, init: opt_init}),
+ vShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Using " + constantExpression + " as a mat4 index in a vertex shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ tests.push({
+ fShaderSource: wtu.replaceParams(fsMatrixTemplate, {constantExpression: constantExpression, init: opt_init}),
+ fShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: "Using " + constantExpression + " as a mat4 index in a fragment shader should " + (expectSuccess ? "compile." : "fail compilation.")
+ });
+ }
+
+ pushTest('0', true);
+ pushTest('3', true);
+ pushTest('-1', false);
+ pushTest('4', false);
+ pushTest('2 + 2', false);
+ pushTest('6 - 2', false);
+ pushTest('2 * 2', false);
+ pushTest('8 / 2', false);
+ pushTest('int(true) * 4', false);
+ pushTest('ivec4(4).x', false);
+ pushTest('ivec4(4)[0]', false);
+ pushTest('int(vec4(5.0).x)', false);
+ pushTest('int(mat4(5.0)[0].x)', false);
+
+ pushTest('int(radians(360.0))', false);
+ pushTest('int(degrees(1.0))', false);
+ pushTest('int(5.0 + sin(0.0))', false);
+ pushTest('int(5.0 + asin(0.0))', false);
+ pushTest('int(pow(2.0, 3.0))', false);
+ pushTest('int(exp(3.0))', false);
+ pushTest('int(exp2(4.0))', false);
+ pushTest('int(floor(-0.5))', false); // floor(-0.5) = -1.0
+ pushTest('int(5.0 + fract(-3.5))', false);
+ pushTest('int(mod(2.0, -4.0))', false); // mod(2.0, -4.0) = 2.0 - (-4.0) * floor(2.0 / -4.0) = 2.0 + 4.0 * (-1.0) = -2.0
+ pushTest('int(mix(2.0, 8.0, 0.9))', false);
+ pushTest('int(length(vec4(3.0)))', false);
+ pushTest('int(lessThan(vec4(2.0), vec4(3.0)).x) * 4', false);
+
+ pushTest('true ? 5 : 0', false);
+ pushTest('int(false ? 0.0 : 5.0)', false);
+ pushTest('my_struct(5, 1).field', false, 'struct my_struct { int field; int field2; };');
+
+ pushTest('int(-0.9)', true); // conversion to int drops the fractional part
+
+ // Sequence operator returns the value of the right-most expression.
+ // Note that the sequence operator is allowed in constant expressions in ESSL 1.00,
+ // but not in ESSL 3.00, so with ESSL 3.00 failing compilation would not be required.
+ pushTest('5, 1', true);
+ pushTest('1, 5', false);
+
+ GLSLConformanceTester.runTests(tests);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/context-creation-and-destruction-stress.html b/dom/canvas/test/webgl-conf/checkout/extra/context-creation-and-destruction-stress.html
new file mode 100644
index 0000000000..7f316da3a0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/context-creation-and-destruction-stress.html
@@ -0,0 +1,35 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test that contexts are freed and garbage collected reasonably</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+<script src="../js/tests/iterable-test.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+var wtu = WebGLTestUtils;
+
+var test = IterableTest.createContextCreationAndDestructionTest();
+var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 500;
+IterableTest.run(test, iterations);
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/cube-map-uploads-out-of-order.html b/dom/canvas/test/webgl-conf/checkout/extra/cube-map-uploads-out-of-order.html
new file mode 100644
index 0000000000..abf9d1dd7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/cube-map-uploads-out-of-order.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL cube map out of order upload test.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+<script src="../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="64" height="64">
+</canvas>
+<script>
+"use strict";
+description("Test out of order cube map uploads.");
+debug("Regression test for crbug.com/473739 / Apple Radar 20444072.");
+
+<!-- Thanks to Gregg Tavares for the original report and test case. -->
+
+var wtu = WebGLTestUtils;
+
+var canvas = document.getElementById("example");
+canvas.addEventListener('webglcontextlost', contextLost, false);
+
+var contextWasLost = false;
+
+function contextLost(e) {
+ e.preventDefault();
+ contextWasLost = true;
+ debug("***context lost -- should not happen***");
+}
+
+var dataWidth = 256;
+var dataHeight = 256;
+var gl = wtu.create3DContext(canvas);
+var tex = gl.createTexture();
+// start with 1x1 pixel cubemap
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+var color = new Uint8Array([128, 192, 255, 255]);
+for (var ii = 0; ii < 6; ++ii) {
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, color);
+}
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+gl.generateMipmap(gl.TEXTURE_CUBE_MAP); // there's no need to call this but the code doesn't check the size.
+
+var textureData = new Uint8Array(dataWidth * dataHeight * 4);
+
+// The first texture has downlaoded
+var first = 1;
+gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + first, 0, gl.RGBA, dataWidth, dataHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
+
+// Now because the first face downloaded doesn't match the other 5 faces upload the same image to the other 5
+// 1x1 faces
+for (var ii = 0; ii < 6; ++ii) {
+ if (ii !== first) {
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, gl.RGBA, dataWidth, dataHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
+ }
+}
+gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+
+// Now as each new face comes in add it
+for (var ii = 0; ii < 6; ++ii) {
+ if (ii !== first) {
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
+ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, gl.RGBA, dataWidth, dataHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ }
+}
+
+gl.flush();
+
+setTimeout(function() {
+ shouldBe("contextWasLost", "false");
+ finishTest();
+}, 1000);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/fbo-lost-context.html b/dom/canvas/test/webgl-conf/checkout/extra/fbo-lost-context.html
new file mode 100644
index 0000000000..b23113d909
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/fbo-lost-context.html
@@ -0,0 +1,202 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL FBO Lost Context Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../../devtools/src/debug/webgl-debug.js"></script>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+uniform mat4 world;
+varying vec2 texCoord;
+void main()
+{
+ gl_Position = vPosition * world;
+ texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+ gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+<canvas id="canvas" width="1024" height="1024"> </canvas>
+<script>
+"use strict";
+description("This test is to help see if an WebGL app *can* get lost context.");
+
+debug("");
+debug("Canvas.getContext");
+var wtu = WebGLTestUtils;
+var g_worldLoc;
+var g_texLoc;
+var g_textures = [];
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking for out of memory handling.");
+
+ var program = wtu.setupProgram(["vshader", "fshader"], ["vPosition", "texCoord0"]);
+ var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
+ debug("max render buffer size: " + size);
+ size = size / 2;
+ debug("size used: " + size);
+
+ var allocateFramebuffers = true;
+ var itervalId;
+ var count = 0;
+
+ gl = WebGLDebugUtils.makeDebugContext(gl, function(err, functionName, args) {
+ window.clearInterval(intervalId);
+ assertMsg(err == gl.OUT_OF_MEMORY,
+ "correctly returns gl.OUT_OF_MEMORY when out of memory");
+ finish();
+ });
+
+ function createFBO() {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ 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, // level
+ gl.RGBA, // internalFormat
+ size, // width
+ size, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ tex,
+ 0);
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("gl.checkFramebufferStatus() returned " + WebGLTestUtils.glEnumToString(gl, status));
+ }
+ return { fb: fb, tex: tex };
+ }
+
+ gl.disable(gl.DEPTH_TEST);
+
+ var numFBOs = 32;
+ for (var ii = 0; ii < numFBOs; ++ii) {
+ createFBO();
+ var t = createFBO();
+ tex = t.tex;
+ fb = t.fb;
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.scissor(0, 0, size, size);
+ gl.clearColor(0, ii / numFBOs, 1 - ii / numFBOs, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ g_textures.push(tex);
+ }
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1,1,0, 1,1,0, -1,-1,0,
+ -1,-1,0, 1,1,0, 1,-1,0
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0,0, 1,0, 0,1,
+ 0,1, 1,0, 1,1
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ g_texLoc = gl.getUniformLocation(gl.program, "tex");
+ gl.uniform1i(g_texLoc, 0);
+ g_worldLoc = gl.getUniformLocation(gl.program, "world");
+ gl.uniformMatrix4fv(g_worldLoc, false, [
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1]);
+
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+ setInterval(render, 1000/60);
+}
+
+var g_angle = 0;
+var g_texIndex = 0;
+function render() {
+ g_angle += 0.1;
+ g_texIndex++;
+ if (g_texIndex >= g_textures.length) {
+ g_texIndex = 0;
+ }
+ gl.bindTexture(gl.TEXTURE_2D, g_textures[g_texIndex]);
+ gl.uniformMatrix4fv(g_worldLoc, false, rotationZ(g_angle));
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+}
+
+/**
+ * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle.
+ * @param {number} angle The angle by which to rotate (in radians).
+ * @return {!o3djs.math.Matrix4} The rotation matrix.
+ */
+function rotationZ(angle) {
+ var c = Math.cos(angle);
+ var s = Math.sin(angle);
+
+ return [
+ c, s, 0, 0,
+ -s, c, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ ];
+};
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script>
+"use strict";
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/getbuffersubdata-nonblocking-benchmark.html b/dom/canvas/test/webgl-conf/checkout/extra/getbuffersubdata-nonblocking-benchmark.html
new file mode 100644
index 0000000000..e6233ea83f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/getbuffersubdata-nonblocking-benchmark.html
@@ -0,0 +1,223 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>getBufferSubData non-blocking test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test that getBufferSubData is non-blocking when used with fenceSync");
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+const srcData = new Uint8Array([ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ]);
+const zeroData = new Uint8Array(8);
+
+const srcBuffer = gl.createBuffer();
+gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer);
+gl.bufferData(gl.COPY_READ_BUFFER, srcData, gl.STATIC_DRAW);
+
+const readbackBuffer = gl.createBuffer();
+gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
+gl.bufferData(gl.COPY_WRITE_BUFFER, 8, gl.STREAM_READ);
+
+// unrelated buffers for tests
+gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // used as copy dst
+gl.bufferData(gl.ARRAY_BUFFER, 8, gl.STATIC_DRAW);
+gl.bindBuffer(gl.UNIFORM_BUFFER, gl.createBuffer()); // used as copy src
+gl.bufferData(gl.UNIFORM_BUFFER, 8, gl.STATIC_DRAW);
+
+const dest = new Uint8Array(8);
+
+// Makes a new "resolvable" Promise
+function resolvable() {
+ let resolve;
+ const promise = new Promise(res => { resolve = res; });
+ promise.resolve = resolve;
+ return promise;
+}
+
+function fence() {
+ const promise = resolvable();
+
+ const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ gl.flush();
+ function check() {
+ const status = gl.clientWaitSync(sync, 0, 0);
+ if (status == gl.ALREADY_SIGNALED || status == gl.CONDITION_SATISFIED) {
+ gl.deleteSync(sync);
+ promise.resolve();
+ } else {
+ setTimeout(check, 0);
+ }
+ }
+ setTimeout(check, 0);
+
+ return promise;
+}
+
+function writeToReadbackBuffer() {
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+}
+
+function timedGetBufferSubData() {
+ dest.fill(0);
+ const t0 = performance.now();
+ gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest);
+ return (performance.now() - t0);
+}
+
+function timeBlockingReadback() {
+ const promise = resolvable();
+ setTimeout(() => {
+ writeToReadbackBuffer();
+ const tBlocking = timedGetBufferSubData();
+ const tLatency = tBlocking;
+ promise.resolve({latency: tLatency, blocking: tBlocking});
+ }, 0);
+ return promise;
+}
+
+function timeNonblockingReadback() {
+ writeToReadbackBuffer();
+ const tLatency0 = performance.now();
+ return fence().then(() => {
+ const tBlocking = timedGetBufferSubData();
+ const tLatency = performance.now() - tLatency0;
+ return {latency: tLatency, blocking: tBlocking};
+ });
+}
+
+function timeReadbackWithUnrelatedCopy() {
+ writeToReadbackBuffer();
+ const tLatency0 = performance.now();
+ const f = fence();
+ // copy to a buffer unrelated to the readback
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ARRAY_BUFFER, 0, 0, 8);
+ return f.then(() => {
+ const tBlocking = timedGetBufferSubData();
+ const tLatency = performance.now() - tLatency0;
+ return {latency: tLatency, blocking: tBlocking};
+ });
+}
+
+function timeReadbackInterrupted() {
+ writeToReadbackBuffer();
+ const tLatency0 = performance.now();
+ const f = fence();
+ // interrupt the readback by inserting another write
+ gl.copyBufferSubData(gl.UNIFORM_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
+ return f.then(() => {
+ const tBlocking = timedGetBufferSubData();
+ const tLatency = performance.now() - tLatency0;
+ return {latency: tLatency, blocking: tBlocking};
+ });
+}
+
+function computeMean(timings) {
+ let total = 0;
+ for (let i = 0; i < timings.length; ++i) {
+ total += timings[i];
+ }
+ return total / timings.length;
+}
+
+function measureMean(fn, iterations) {
+ const timingsLatency = Array(iterations);
+ const timingsBlocking = Array(iterations);
+
+ // Chain together `iterations` promises to call `fn` sequentially.
+ let promise = Promise.resolve();
+ for (let i = 0; i < iterations; ++i) {
+ promise = promise
+ .then(fn)
+ .then(t => {
+ timingsLatency[i] = t.latency;
+ timingsBlocking[i] = t.blocking;
+ });
+ }
+
+ return promise.then(() => {
+ const meanLatency = computeMean(timingsLatency);
+ const meanBlocking = computeMean(timingsBlocking);
+ return { latency: meanLatency, blocking: meanBlocking };
+ });
+}
+
+let t_blocking, t_nonblocking;
+let t_unrelated;
+let t_interrupted;
+Promise.resolve()
+ .then(() => {
+ let iterations = 500;
+ debug(`blocking readback: mean over ${iterations} iterations...`);
+ return measureMean(timeBlockingReadback, iterations);
+ })
+ .then(t => {
+ t_blocking = t;
+ debug(`... latency = ${t.latency}ms, blocking = ${t.blocking}ms`);
+ })
+ .then(() => shouldBeTrue("areArraysEqual(dest, srcData)"))
+
+ .then(() => debug(""))
+ .then(() => {
+ let iterations = 500;
+ debug(`nonblocking readback: mean over ${iterations} iterations...`);
+ return measureMean(timeNonblockingReadback, iterations);
+ })
+ .then(t => {
+ t_nonblocking = t;
+ debug(`... latency = ${t.latency}ms, blocking = ${t.blocking}ms`);
+ })
+ .then(() => shouldBeTrue("areArraysEqual(dest, srcData)"))
+
+ .then(() => debug(""))
+ .then(() => {
+ let iterations = 500;
+ debug(`readback interrupted by unrelated read from copy source: mean over ${iterations} iterations...`);
+ return measureMean(timeReadbackWithUnrelatedCopy, iterations);
+ })
+ .then(t => {
+ t_unrelated = t;
+ debug(`... latency = ${t.latency}ms, blocking = ${t.blocking}ms`);
+ })
+ .then(() => shouldBeTrue("areArraysEqual(dest, srcData)"))
+
+ .then(() => debug(""))
+ .then(() => {
+ let iterations = 500;
+ debug(`readback interrupted by write to readback source: mean over ${iterations} iterations...`);
+ return measureMean(timeReadbackInterrupted, iterations);
+ })
+ .then(t => {
+ t_interrupted = t;
+ debug(`... latency = ${t.latency}ms, blocking = ${t.blocking}ms`);
+ })
+ .then(() => shouldBeTrue("areArraysEqual(dest, zeroData)"))
+
+ .then(() => {
+ debug("");
+ shouldBeTrue("t_nonblocking.blocking < t_blocking.blocking");
+ shouldBeTrue("t_unrelated.blocking < t_blocking.blocking");
+ shouldBeTrue("t_nonblocking.blocking < t_interrupted.blocking");
+ })
+ .then(finishTest);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/logo-256x256.png b/dom/canvas/test/webgl-conf/checkout/extra/logo-256x256.png
new file mode 100644
index 0000000000..b6a9ef1acd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/logo-256x256.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-example.html b/dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-example.html
new file mode 100644
index 0000000000..1c4fe866f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-example.html
@@ -0,0 +1,89 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Lots of polygons example.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="1024" height="1024" style="width: 40px; height: 40px;">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+window.onload = init;
+debug("Tests a WebGL program that draws a bunch of large polygons");
+
+function init() {
+ if (confirm(
+ "After clicking OK your machine may become unresponsive or crash.")) {
+ main();
+ } else {
+ debug("cancelled");
+ }
+}
+
+function main() {
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("example");
+ canvas.addEventListener("webglcontextlost", function(e) { e.preventDefault(); }, false);
+ canvas.addEventListener("webglcontextrestored", function(e) { }, false);
+
+ var gl = wtu.create3DContext(canvas);
+ var program = wtu.setupTexturedQuad(gl);
+
+ assertMsg(gl.getError() == gl.NO_ERROR, "Should be no errors from setup.");
+
+ var tex = gl.createTexture();
+ gl.enable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+
+ wtu.fillTexture(gl, tex, 4096, 4096, [0, 192, 128, 255], 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting texture params");
+
+ var loc = gl.getUniformLocation(program, "tex");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after getting tex locations");
+ gl.uniform1i(loc, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting tex uniform");
+
+ var numQuads = 100000;
+ var indexBuf = new ArrayBuffer(numQuads * 6);
+ var indices = new Uint8Array(indexBuf);
+ for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ indices[offset + 0] = 0;
+ indices[offset + 1] = 1;
+ indices[offset + 2] = 2;
+ indices[offset + 3] = 3;
+ indices[offset + 4] = 4;
+ indices[offset + 5] = 5;
+ }
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating index buffer");
+ gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+
+ var successfullyParsed = true;
+}
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-shader-example.html b/dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-shader-example.html
new file mode 100644
index 0000000000..2c57fbe1c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/lots-of-polys-shader-example.html
@@ -0,0 +1,155 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Lots of polygons example.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+<style>
+html, body {
+ width: 100%;
+ height: 100%;
+}
+canvas {
+ border: 1px solid black;
+ width: 95%;
+ height: 80%;
+}
+</style
+</head>
+<body>
+<canvas id="example"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+window.onload = init;
+debug("Tests a WebGL program that draws a bunch of large polygons from a quad mesh");
+
+function init() {
+ if (confirm(
+ "After clicking OK your machine may become unresponsive or crash.")) {
+ main();
+ } else {
+ debug("cancelled");
+ }
+}
+
+function main() {
+ var wtu = WebGLTestUtils;
+ var canvas = document.getElementById("example");
+ var gridRes = 1000;
+ canvas.width = canvas.clientWidth;
+ canvas.heigt = canvas.clientHeight;
+ canvas.addEventListener("webglcontextlost", function(e) { e.preventDefault(); }, false);
+ canvas.addEventListener("webglcontextrestored", function(e) { }, false);
+
+ var gl = wtu.create3DContext(canvas);
+ var program = wtu.setupProgram(
+ gl, ['vshader', 'fshader'], ['vPosition'], [0]);
+
+ wtu.setupIndexedQuad(gl, gridRes, 0, true);
+
+ // make 1 texture since we'd have at least that in CSS shaders
+ var size = 256;
+ var pixels = new Uint8Array(size * size * 4);
+ for (var y = 0; y < size; ++y) {
+ for (var x = 0; x < size; ++x) {
+ var offset = (y * size + x) * 4;
+ pixels[offset + 0] = x * 255 / size;
+ pixels[offset + 1] = y * 255 / size;
+ pixels[offset + 2] = x * y * 255 / (size * size);
+ pixels[offset + 3] = 255;
+ }
+ }
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+
+ // add test colors.
+ if (false) {
+ var vertsAcross = gridRes + 1;
+ var numQuads = vertsAcross * vertsAcross;
+ var colors = new Float32Array(numQuads * 4);
+ for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 4;
+ colors[offset + 0] = Math.random();
+ colors[offset + 1] = Math.random();
+ colors[offset + 2] = Math.random();
+ colors[offset + 3] = 1;
+ }
+ var colorLocation = gl.getAttribLocation(program, "color")
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(colorLocation);
+ gl.vertexAttribPointer(colorLocation, 3, gl.FLOAT, false, 0, 0);
+ }
+
+ var gridResLoc = gl.getUniformLocation(program, "gridRes");
+ gl.uniform1f(gridResLoc, gridRes);
+
+ assertMsg(gl.getError() == gl.NO_ERROR, "Should be no errors from setup.");
+
+ gl.enable(gl.BLEND);
+ //gl.enable(gl.CULL_FACE);
+ //gl.cullFace(gl.FRONT);
+
+ gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+
+ var successfullyParsed = true;
+}
+</script>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec2 v_texCoord;
+uniform float gridRes;
+
+#ifdef ADD_TEST_COLORS
+ attribute vec4 color;
+ varying vec4 v_color;
+#endif
+
+void main()
+{
+ // expand each quad to cover the entire element.
+ vec2 p = mod((vPosition.xy * 0.5 + 0.5) * gridRes, 2.0) * 2.0 - 1.0;
+ gl_Position = vec4(p, 0, 1);
+ v_texCoord = vPosition.xy;
+
+#ifdef ADD_TEST_COLORS
+ v_color = color;
+#endif
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+varying vec2 v_texCoord;
+uniform sampler2D tex;
+void main()
+{
+#ifdef ADD_TEST_COLORS
+ gl_FragColor = v_color;
+#else
+ gl_FragColor = texture2D(tex, v_texCoord);
+#endif
+}
+</script>
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/multisample-corruption-stress.html b/dom/canvas/test/webgl-conf/checkout/extra/multisample-corruption-stress.html
new file mode 100644
index 0000000000..a24db37681
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/multisample-corruption-stress.html
@@ -0,0 +1,37 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Multisample Renderbuffer Corruption Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../jss/webgl-test-utils.js"> </script>
+<script src="../js/tests/iterable-test.js"> </script>
+</head>
+<body>
+<canvas id="example" width="2048" height="2048" style="width: 128px; height: 128px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description(document.title);
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext("example", {antialias: true, preserveDrawingBuffer: true});
+var test = IterableTest.createMultisampleCorruptionTest(gl);
+var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 100;
+IterableTest.run(test, iterations);
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/offscreen-issue.html b/dom/canvas/test/webgl-conf/checkout/extra/offscreen-issue.html
new file mode 100644
index 0000000000..b35eefbf38
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/offscreen-issue.html
@@ -0,0 +1,43 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script type="application/javascript">
+
+window.onload = function() {
+ setup("1");
+ setup("2");
+}
+
+function setup(id) {
+ var c = document.getElementById(id);
+ var names = ["webgl", "experimental-webgl"];
+ for (var i = 0; i < names.length; ++i) {
+ gl = canvas.getContext(names[i]);
+ if (gl) {
+ break;
+ }
+ }
+ gl.clearColor(1,0,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ setTimeout(function() {
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(0,0,50,50);
+ gl.clearColor(0,1,0,1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }, 500);
+}
+</script>
+</head>
+<body>
+<canvas id="1"></canvas>
+<div style="height:4000px;">content that is tall like several articles</div>
+<canvas id="2"></canvas>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/out-of-bounds-uniform-array-access.html b/dom/canvas/test/webgl-conf/checkout/extra/out-of-bounds-uniform-array-access.html
new file mode 100644
index 0000000000..917361e986
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/out-of-bounds-uniform-array-access.html
@@ -0,0 +1,105 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL out of bounds uniform array access.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body style="background: #666;">
+<div id="description"></div>
+<div id="console"></div>
+<div>elem mult: <span id="elemMultDisplay"></span></div>
+<input type="range" id="elemMult" value="4" min="0" max="2048" style="width: 100%;"/>
+<div>line width: <span id="lineWidthDisplay"></span></div>
+<input type="range" id="lineWidth" value="512" min="0" max="2540" style="width: 100%;"/>
+<canvas id="example" width="256" height="256" style="background: black;">
+</canvas>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec4 v_color;
+uniform float lineWidth;
+uniform int elemMult;
+uniform vec4 someArray[2];
+void main()
+{
+ vec2 texcoord = vec2(vPosition.xy * 0.5 + vec2(0.5, 0.5));
+ int index = int(texcoord.x + texcoord.y * lineWidth) * elemMult;
+ v_color = someArray[index];
+ gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 v_color;
+void main()
+{
+ gl_FragColor = v_color * vec4(1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0) + vec4(0,0,0,0.5);
+}
+</script>
+<script>
+"use strict";
+window.onload = main;
+debug("Tests a WebGL program that accesses out of bounds uniform array elements");
+
+function main() {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(
+ gl,
+ ['vshader', 'fshader'],
+ ['vPosition'], [0]);
+ var gridRes = 255;
+ wtu.setupIndexedQuad(gl, gridRes, 0);
+ var lineWidthLoc = gl.getUniformLocation(program, "lineWidth");
+ var elemMultLoc = gl.getUniformLocation(program, "elemMult");
+ assertMsg(gl.getError() == gl.NO_ERROR, "Should be no errors from setup.");
+
+ var lineWidth = 512;
+ var lineWidthElem = document.getElementById("lineWidth");
+ var lineWidthDisplayElem = document.getElementById("lineWidthDisplay");
+
+ lineWidthElem.value = lineWidth;
+
+ lineWidthElem.addEventListener('change', function(event) {
+ //console.log(event.target.value);
+ lineWidth = event.target.value;
+ draw();
+ }, false);
+
+ var elemMult = 4;
+ var elemMultElem = document.getElementById("elemMult");
+ var elemMultDisplayElem = document.getElementById("elemMultDisplay");
+
+ elemMultElem.value = elemMult;
+
+ elemMultElem.addEventListener('change', function(event) {
+ //console.log(event.target.value);
+ elemMult = event.target.value;
+ draw();
+ }, false);
+
+ draw();
+
+ function draw() {
+ lineWidthDisplayElem.innerText = lineWidth;
+ elemMultDisplayElem.innerText = elemMult;
+ gl.uniform1f(lineWidthLoc, lineWidth);
+ gl.uniform1i(elemMultLoc, elemMult);
+ gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
+ }
+
+ var successfullyParsed = true;
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/out-of-memory.html b/dom/canvas/test/webgl-conf/checkout/extra/out-of-memory.html
new file mode 100644
index 0000000000..e02984d44c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/out-of-memory.html
@@ -0,0 +1,84 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Out Of Memory Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+debug("This tests WebGL running out of memory.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Allocating shaders.");
+
+ function makeBigShader() {
+ var lines = [];
+ var line = "// ";
+ for (var ii = 0; ii < 1024; ++ii) {
+ line += String.fromCharCode(48 + ii % 10);
+ }
+ for (var ii = 0; ii < 1024; ++ii) {
+ lines[ii] = line;
+ }
+ var oneMB = lines.join();
+ for (var ii = 0; ii < 64; ++ii) {
+ lines[ii] = oneMB;
+ }
+ return lines.join("\n");
+ }
+
+ var shaderSource = makeBigShader();
+ debug("created " + Math.floor(shaderSource.length / 1024 / 1024) + "MB shader");
+
+ var intervalId;
+ var count = 0;
+
+ function makeShader() {
+ ++count;
+ debug ("creating shader #" + count + " mem = " + Math.floor(shaderSource.length * count / 1024 / 1024) + "MB");
+ var shader = gl.createShader(gl.VERTEX_SHADER);
+ if (shader == null) {
+ window.clearInterval(intervalId);
+ testPassed("createShader returns null"); // not sure this is a passing
+ finishTest();
+ } else {
+ gl.shaderSource(shader, shaderSource);
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ window.clearInterval(intervalId);
+ assertMsg(err == gl.OUT_OF_MEMORY, "shaderSource returns OUT_OF_MEMORY");
+ finishTest();
+ }
+ }
+ }
+
+ intervalId = window.setInterval(makeShader, 1000/15);
+}
+</script>
+<script src="../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/out-of-resources.html b/dom/canvas/test/webgl-conf/checkout/extra/out-of-resources.html
new file mode 100644
index 0000000000..8e88c1ebfd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/out-of-resources.html
@@ -0,0 +1,120 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Out Of Resources Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../../devtools/src/debug/webgl-debug.js"></script>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<canvas id="canvas2" width="2" height="2"> </canvas>
+<script>
+"use strict";
+wtu = WebGLTestUtils;
+window.onload = init;
+debug("Tests a WebGL program that tries to use all of vram.");
+
+function init() {
+ if (confirm(
+ "After clicking OK your machine may become unresponsive or crash.")) {
+ main();
+ } else {
+ debug("cancelled");
+ }
+}
+
+function main() {
+ debug("");
+ debug("Canvas.getContext");
+
+ var gl = wtu.create3DContext("canvas");
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ var program = wtu.setupColorQuad(gl);
+ gl.useProgram(program);
+
+ debug("");
+ debug("Checking for out of memory handling.");
+
+ var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
+ debug("max render buffer size: " + size);
+
+ var allocateFramebuffers = true;
+ var itervalId;
+ var count = 0;
+
+ gl = WebGLDebugUtils.makeDebugContext(gl, function(err, functionName, args) {
+ assertMsg(err == gl.OUT_OF_MEMORY,
+ "correctly returns gl.OUT_OF_MEMORY when out of memory");
+ stop("got: " + wtu.glEnumToString(gl, err));
+ });
+
+ var fbos = [];
+
+ intervalId = window.setInterval(function() {
+ ++count;
+ var mem = count * size * size * 4;
+ debug("#" + count + " : memory allocated so far " + (mem / 1024 / 1024) + "MB");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ size, // width
+ size, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ stop("got error: " + wtu.glEnumToString(gl, err));
+ return;
+ }
+ if (allocateFramebuffers) {
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(
+ gl.FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ tex,
+ 0);
+ var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE) {
+ stop("got: " + wtu.glEnumToString(gl, status));
+ return;
+ }
+ // use the framebuffer
+ wtu.drawFloatColorQuad(gl, [1, Math.random(), 1, 1]);
+ }
+ }, 200);
+
+ function stop(msg) {
+ debug(msg);
+ window.clearInterval(intervalId);
+ finishTest();
+ }
+ }
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/out-of-vram.html b/dom/canvas/test/webgl-conf/checkout/extra/out-of-vram.html
new file mode 100644
index 0000000000..02f82949f7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/out-of-vram.html
@@ -0,0 +1,114 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Out Of VRAM Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script>
+"use strict";
+debug("This tests WebGL running out of vram.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+try {
+ var gl = wtu.create3DContext(canvas);
+} catch(e) {
+}
+if (!gl) {
+ testFailed("could not create context");
+} else {
+ testPassed("context exists");
+
+ var args = wtu.getUrlArguments();
+
+ canvas.addEventListener('webglcontextlost', contextLost, false);
+
+ function contextLost(e) {
+ e.preventDefault();
+ debug("***context lost***");
+ }
+
+ function contextRestored(e) {
+ debug("***context restored***");
+ }
+
+ var program = wtu.setupTexturedQuad(gl);
+ gl.useProgram(program);
+
+ debug("");
+ debug("Allocating textures.");
+
+ var intervalId;
+ var count = 0;
+ var textureMem = 0;
+ var textures = [];
+ var size = 2048;
+ var limit = (args.limit ? args.limit : 8192) * 1024 * 1024;
+
+ debug("limit: " + InMB(limit))
+
+ function InMB(v) {
+ return "" + Math.floor(v / 1024 / 1024) + "MB";
+ }
+
+ function makeTexture() {
+ if (gl.isContextLost()) {
+ stop("out of memory");
+ return;
+ }
+ ++count;
+ textureMem += size * size * 4;
+ if (textureMem > limit) {
+ stop("reached limit");
+ return;
+ }
+ debug ("creating texture #" + count + " mem = " + InMB(textureMem));
+ var texture = gl.createTexture();
+ textures.push(texture);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D,
+ 0, // level
+ gl.RGBA, // internalFormat
+ size, // width
+ size, // height
+ 0, // border
+ gl.RGBA, // format
+ gl.UNSIGNED_BYTE, // type
+ null); // data
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ stop("got error: " + wtu.glEnumToString(gl, err));
+ return;
+ }
+ // use the texture
+ wtu.clearAndDrawUnitQuad(gl);
+ }
+
+ intervalId = window.setInterval(makeTexture, 1000 / 15);
+
+}
+
+function stop(msg) {
+ window.clearInterval(intervalId);
+ testPassed(msg);
+ finishTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/point-no-attributes-stress.html b/dom/canvas/test/webgl-conf/checkout/extra/point-no-attributes-stress.html
new file mode 100644
index 0000000000..f567264907
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/point-no-attributes-stress.html
@@ -0,0 +1,61 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+<script id="vshader" type="x-shader/x-vertex">
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="1" height="1" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Stress test drawing a huge number of points without enabling any attributes');
+
+debug('This test stresses drawing a large number of points and workarounds created to run WebGL with simulated attrib 0');
+
+if (confirm('After clicking OK your machine may become unresponsive or crash.')) {
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext('testbed');
+
+ var program1 = wtu.setupProgram(gl, ['vshader', 'fshader']);
+
+ gl.enable(gl.BLEND);
+
+ debug('Draw 2^31 points with a shader that takes no attributes and verify it fills the whole canvas.');
+
+ gl.drawArrays(gl.POINTS, 0, Math.pow(2, 31) - 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/program-test-1.html b/dom/canvas/test/webgl-conf/checkout/extra/program-test-1.html
new file mode 100644
index 0000000000..e7cee66c9a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/program-test-1.html
@@ -0,0 +1,80 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!-- This is a visual test that programs must have both a vertex and
+ fragment shader attached; the fixed function pipeline on the
+ desktop must remain disabled. -->
+<script type="application/javascript">
+function log() {
+ var s = "";
+ for (var i = 0; i < arguments.length; ++i) {
+ s += arguments[i] + " ";
+ }
+ document.getElementById("log").innerHTML += s + "<br>";
+}
+
+function go() {
+ var gl = document.getElementById("c").getContext("experimental-webgl");
+
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var vs = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vs, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }");
+ gl.compileShader(vs);
+
+ var fs = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fs, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }");
+ gl.compileShader(fs);
+
+ var prog = gl.createProgram();
+ gl.attachShader(prog, vs);
+ // don't attach a fragment shader -- may use fixed pipeline on desktop if the implementation doesn't check!
+ //gl.attachShader(prog, fs);
+
+ gl.bindAttribLocation(prog, 0, "aVertex");
+ gl.bindAttribLocation(prog, 1, "aColor");
+
+ gl.linkProgram(prog);
+
+ var vbuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1.0, -1.0, 0.0, 1.0,
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+
+ var cbuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, cbuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([255, 0, 0,
+ 0, 255, 0,
+ 0, 0, 255,
+ 255, 255, 0]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(1, 3, gl.UNSIGNED_BYTE, false, 0, 0);
+
+ gl.enableVertexAttribArray(0);
+ gl.enableVertexAttribArray(1);
+
+ gl.useProgram(prog);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ log("glError", "0x" + gl.getError().toString(16));
+}
+</script>
+</head>
+
+<body onload="go()">
+<p>Should be green in the rectangle below:</p>
+<canvas style="background: green;" id="c"></canvas>
+<div id="log"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/readpixels-after-alert.html b/dom/canvas/test/webgl-conf/checkout/extra/readpixels-after-alert.html
new file mode 100644
index 0000000000..0fbb9cb159
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/readpixels-after-alert.html
@@ -0,0 +1,65 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Behavior After Alert and Read Pixels Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../../devtools/src/debug/webgl-debug.js"></script>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="100" height="100"> </canvas>
+<div id="description">Verify WebGL behavior after an alert and then a readPixels()</div>
+<div id="console"></div>
+<script>
+"use strict";
+
+function checkPixels(buf, width, height, thresh) {
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ if (Math.abs(buf[offset] - 255) > thresh ||
+ Math.abs(buf[offset + 1] - 0) > thresh ||
+ Math.abs(buf[offset + 2] - 0) > thresh) {
+ testFailed("Checking pixels");
+ return false;
+ }
+ }
+ }
+ testPassed("Checking pixels");
+ return true;
+}
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+gl.clearColor(1, 0, 0, 1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed");
+
+wtu.checkCanvas(gl, [255, 0, 0, 255], undefined, 3);
+
+alert("Click me to continue");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed");
+wtu.checkCanvas(gl, [255, 0, 0, 255], undefined, 3);
+
+alert("Click me to continue");
+
+gl.clearColor(1, 0, 0, 1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [255, 0, 0, 255], undefined, 3);
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/sample-100.png b/dom/canvas/test/webgl-conf/checkout/extra/sample-100.png
new file mode 100644
index 0000000000..197c869b6d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/sample-100.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/sample-200.png b/dom/canvas/test/webgl-conf/checkout/extra/sample-200.png
new file mode 100644
index 0000000000..89f2b782a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/sample-200.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/sample-400.png b/dom/canvas/test/webgl-conf/checkout/extra/sample-400.png
new file mode 100644
index 0000000000..aaee3ce0dc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/sample-400.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/sample.svg b/dom/canvas/test/webgl-conf/checkout/extra/sample.svg
new file mode 100644
index 0000000000..dfca524023
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/sample.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+ <rect width="100" height="100" fill="red"/>
+ <circle cx="50" cy="50" r="50" fill="blue"/>
+</svg>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/simulated-attrib-0-bug-test.html b/dom/canvas/test/webgl-conf/checkout/extra/simulated-attrib-0-bug-test.html
new file mode 100644
index 0000000000..83564e824a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/simulated-attrib-0-bug-test.html
@@ -0,0 +1,36 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Simulated Attrib 0 Bug Test</title>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div>Simulated Attrib 0 Bug Test</div>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+var context = wtu.create3DContext();
+var program = wtu.loadStandardProgram(context);
+
+context.useProgram(program);
+debug("This line attempts to draw with 0x7FFFFFFF triangles with attrib 0 off");
+debug("A buggy simulated attrib 0 impl will probably mult 0x7FFFFFFF * sizeof(vec4)");
+shouldBe("context.drawArrays(context.TRIANGLES, 0, 0x7fffffff);", "undefined");
+debug("This line attempts to draw with 0x7ffffff triangles.");
+debug("A buggy simulated attrib 0 impl will probably pass 0x7FFFFFF0 to glBufferData and then not check that it failed");
+shouldBe("context.drawArrays(context.TRIANGLES, 0, 0x7ffffff);", "undefined");
+debug("")
+debug("NOTE!: You may not see any manifestation here. Check your impl for these issues");
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/slow-shader-example.html b/dom/canvas/test/webgl-conf/checkout/extra/slow-shader-example.html
new file mode 100644
index 0000000000..2397bbbec8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/slow-shader-example.html
@@ -0,0 +1,112 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Slow Shader example.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="1024" height="1024" style="width: 40px; height: 40px;">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="slow" type="text/something-not-javascript">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main() {
+ gl_FragColor = texture2D(tex, texture2D(tex, texture2D(tex, texCoord).xy).xy);
+}
+</script>
+<script>
+"use strict";
+window.onload = main;
+
+debug("Tests drawing a very slow shader.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+canvas.addEventListener("webglcontextlost", function(e) { e.preventDefault(); }, false);
+canvas.addEventListener("webglcontextrestored", function(e) { }, false);
+var gl = wtu.create3DContext(canvas);
+var maxTexSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+var texSize = Math.min(maxTexSize, 4096);
+debug("Max Texture size: " + maxTexSize);
+debug("Texture size: " + texSize);
+var shaderSource =
+ document.getElementById("slow").text.replace(/\$size/g, texSize + ".0");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after getting a context");
+var program = wtu.setupProgram(
+ gl,
+ [wtu.simpleTextureVertexShader, shaderSource],
+ ['vPosition', 'texCoord0'],
+ [0, 1]);
+wtu.setupUnitQuad(gl, 0, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after program setup");
+var tex = gl.createTexture();
+gl.enable(gl.BLEND);
+gl.disable(gl.DEPTH_TEST);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+debug("preparing...");
+var numBytes = texSize * texSize * 4;
+var pixelBuf = new ArrayBuffer(numBytes);
+var pixels = new Uint8Array(pixelBuf);
+for (var ii = 0; ii < numBytes; ++ii) {
+ pixels[ii] = Math.random() * 255;
+}
+gl.bindTexture(gl.TEXTURE_2D, tex);
+gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture setup");
+
+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.REPEAT);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture param setting");
+
+var loc = gl.getUniformLocation(program, "tex");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after getting tex location");
+gl.uniform1i(loc, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting tex uniform");
+
+var numQuads = 1000;
+var indexBuf = new ArrayBuffer(numQuads * 6);
+var indices = new Uint8Array(indexBuf);
+for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ indices[offset + 0] = 0;
+ indices[offset + 1] = 1;
+ indices[offset + 2] = 2;
+ indices[offset + 3] = 3;
+ indices[offset + 4] = 4;
+ indices[offset + 5] = 5;
+}
+var indexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
+
+function main () {
+ if (confirm(
+ "After clicking OK your machine may become unresponsive or crash.")) {
+ gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+ } else {
+ debug("cancelled");
+ }
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.html b/dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.html
new file mode 100644
index 0000000000..3c25b7c985
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.html
@@ -0,0 +1,27 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+<script src="tex-image-with-video-test.js"></script>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+</script>
+</head>
+<body onload='generateTest("RGBA", "UNSIGNED_BYTE", testPrologue)()'>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.js b/dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.js
new file mode 100644
index 0000000000..01f56b56c3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/tex-image-with-video-test.js
@@ -0,0 +1,158 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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) {
+ console.log(msg);
+ old(msg);
+};
+
+function generateTest(pixelFormat, pixelType, prologue) {
+ var wtu = WebGLTestUtils;
+ var gl = null;
+ var textureLoc = null;
+ var successfullyParsed = false;
+
+ // Test each format separately because many browsers implement each
+ // differently. Some might be GPU accelerated, some might not. Etc...
+ var videos = [
+ { src: "../resources/red-green.mp4" , type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', },
+ { src: "../resources/red-green.webmvp8.webm", type: 'video/webm; codecs="vp8, vorbis"', },
+ { src: "../resources/red-green.webmvp9.webm", type: 'video/webm; codecs="vp9"', },
+ { src: "../resources/red-green.theora.ogv", type: 'video/ogg; codecs="theora, vorbis"', },
+ ];
+
+ var videoNdx = 0;
+ var video;
+
+ function runNextVideo() {
+ if (video) {
+ video.pause();
+ }
+
+ if (videoNdx == videos.length) {
+ finishTest();
+ return;
+ }
+
+ var info = videos[videoNdx++];
+ debug("");
+ debug("testing: " + info.type);
+ video = document.createElement("video");
+ video.muted = true;
+ 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.crossOrigin = 'anonymous';
+ video.src = info.src;
+ wtu.startPlayingAndWaitForVideo(video, runTest);
+ }
+
+ var init = function()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking video elements (' + pixelFormat + '/' + pixelType + ')');
+
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ var program = wtu.setupTexturedQuad(gl);
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ textureLoc = gl.getUniformLocation(program, "tex");
+ runNextVideo();
+ }
+
+ function runOneIteration(videoElement, useTexSubImage2D, flipY, topColor, bottomColor)
+ {
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY);
+ 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(gl.TEXTURE_2D, texture);
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ // Upload the videoElement into the texture
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[pixelFormat],
+ videoElement.videoWidth, videoElement.videoHeight, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl[pixelFormat], gl[pixelType], videoElement);
+ } else {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl[pixelFormat], gl[pixelFormat], gl[pixelType], videoElement);
+ }
+
+ 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);
+
+ // Point the uniform sampler to texture unit 0
+ gl.uniform1i(textureLoc, 0);
+ // 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 red = [255, 0, 0];
+ var green = [0, 255, 0];
+ runOneIteration(videoElement, false, true, red, green);
+ runOneIteration(videoElement, false, false, green, red);
+ runOneIteration(videoElement, true, true, red, green);
+ runOneIteration(videoElement, true, false, green, red);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ runNextVideo();
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/texture-allocation-stress-test.html b/dom/canvas/test/webgl-conf/checkout/extra/texture-allocation-stress-test.html
new file mode 100644
index 0000000000..e27628b621
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/texture-allocation-stress-test.html
@@ -0,0 +1,47 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Tests that resources allocated by a WebGL context are freed in a reasonable timeframe.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="32" height="32">
+</canvas>
+<script>
+"use strict";
+description();
+
+debug("Creates a WebGL context and textures consuming ~80 MB of video memory, then reloads the page and does it over again.")
+debug("GPU memory usage should be capped. It should not grow unboundedly.")
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext(document.getElementById("canvas"));
+var textures = [];
+
+for (var ii = 0; ii < 20; ++ii) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1024, 1024, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ null);
+ textures.push(tex);
+}
+
+setTimeout(function() { debug("Reloading..."); window.location.reload(); }, 500);
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/texture-from-camera-stress.html b/dom/canvas/test/webgl-conf/checkout/extra/texture-from-camera-stress.html
new file mode 100644
index 0000000000..0a9816ae07
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/texture-from-camera-stress.html
@@ -0,0 +1,79 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Stresses the camera-to-texture upload path.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="640" height="360">
+</canvas>
+<script>
+"use strict";
+description();
+
+debug("Repeatedly uploads from a camera video element to a texture, many times per frame.")
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext(document.getElementById('canvas'));
+const video = document.createElement('video');
+video.src = '';
+video.loop = false;
+video.muted = true;
+video.setAttribute('playsinline', '');
+
+const program = wtu.setupTexturedQuad(gl);
+const textureLoc = gl.getUniformLocation(program, "tex");
+gl.uniform1i(textureLoc, 0);
+
+const 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);
+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.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+
+navigator.mediaDevices.getUserMedia({
+ audio: false,
+ video: {
+ facingMode: 'environment',
+ width: 1280,
+ height: 720,
+ }
+ })
+ .then(mediaStream => {
+ video.srcObject = mediaStream;
+ video.onloadedmetadata = () => {
+ wtu.startPlayingAndWaitForVideo(video, startTestLoop);
+ };
+ });
+
+const urlOptions = wtu.getUrlOptions();
+const uploadsPerFrame = urlOptions.uploadsPerFrame ? urlOptions.uploadsPerFrame : 400;
+debug('');
+debug(`Testing with ${uploadsPerFrame} uploads per frame`);
+
+function startTestLoop() {
+ requestAnimationFrame(startTestLoop);
+ for (let i = 0; i < uploadsPerFrame; ++i) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, video);
+ }
+ wtu.clearAndDrawUnitQuad(gl);
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/texture-sizing.html b/dom/canvas/test/webgl-conf/checkout/extra/texture-sizing.html
new file mode 100644
index 0000000000..efbb65fea7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/texture-sizing.html
@@ -0,0 +1,229 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<title>Testing resolution of texture uploads</title>
+<style>
+
+.result {
+ margin-bottom: 20px;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-direction: row;
+ flex-direction: row;
+}
+
+.description, .element, .render, .log {
+ border: 1px solid black;
+ margin: 5px;
+ width: 200px;
+ height: 200px;
+ max-width: 200px;
+ max-height: 200px;
+}
+
+.render canvas {
+ width: 200px;
+ height: 200px;
+}
+
+p {
+ margin: 0;
+ padding: 5px 10px;
+}
+.viacss {
+ width: 200px;
+ height: 200px;
+}
+</style>
+<script src="../js/webgl-test-utils.js"> </script>
+<script>
+
+var outOfPageSVG = new Image();
+outOfPageSVG.src = "sample.svg";
+
+function runTest() {
+ var wtu = WebGLTestUtils;
+ var results = document.querySelectorAll(".result");
+ for (var i = 0; i < results.length; i++) {
+ var result = results[i];
+ var img = result.querySelector("img");
+ if (result.classList.contains("out-of-page")) {
+ img = outOfPageSVG;
+ }
+ if (result.classList.contains("set-dimensions")) {
+ img.width = 200;
+ img.height = 200;
+ }
+ var out = result.querySelector(".output");
+ out.innerHTML = "img.width = " + img.width + "<br>img.height = " + img.height + "<br>img.naturalWidth = " + img.naturalWidth + "<br>img.naturalHeight = " + img.naturalHeight;
+
+ var canvas = document.createElement("canvas");
+ canvas.width = 200 * window.devicePixelRatio;
+ canvas.height = 200 * window.devicePixelRatio;
+ result.querySelector(".render").appendChild(canvas);
+ var gl = wtu.create3DContext(canvas);
+ gl.enable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+
+ var program = wtu.setupSimpleTextureProgram(gl, 0, 1);
+ var buffers = wtu.setupUnitQuad(gl, 0, 1);
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ var loc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(loc, 0);
+
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+ }
+}
+
+window.addEventListener("load", function () {
+ runTest();
+}, false);
+</script>
+</head>
+<body>
+<div class="result">
+ <div class="description">
+ <p>IMG to SVG with 200x200 attributes</p>
+ </div>
+ <div class="element">
+ <img src="sample.svg" width="200" height="200">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>IMG to 100x100 PNG with 200x200 attributes</p>
+ </div>
+ <div class="element">
+ <img src="sample-100.png" width="200" height="200">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>IMG to 200x200 PNG with 200x200 attributes</p>
+ </div>
+ <div class="element">
+ <img src="sample-200.png" width="200" height="200">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>IMG to 400x400 PNG with 200x200 attributes</p>
+ </div>
+ <div class="element">
+ <img src="sample-400.png" width="200" height="200">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>IMG SRCSET to multiple PNGs with 200x200 attributes</p>
+ </div>
+ <div class="element">
+ <img src="sample-100.png" srcset="sample-200.png 1x, sample-400.png 2x" width="200" height="200">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>IMG to SVG with no attributes - 200x200 sizing via CSS</p>
+ </div>
+ <div class="element">
+ <img src="sample.svg" class="viacss">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>IMG to 400x400 PNG with no attributes - 200x200 sizing via CSS</p>
+ </div>
+ <div class="element">
+ <img src="sample-400.png" class="viacss">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result">
+ <div class="description">
+ <p>
+ IMG to SVG with no attributes and no sizing via CSS<br>
+ (although the width and height of the container set a size)
+ </p>
+ </div>
+ <div class="element">
+ <img src="sample.svg">
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result out-of-page">
+ <div class="description">
+ <p>Out of page SVG with no dimensions</p>
+ </div>
+ <div class="element">
+ Not a child of document
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+<div class="result out-of-page set-dimensions">
+ <div class="description">
+ <p>Out of page SVG with 200x200 specified</p>
+ </div>
+ <div class="element">
+ Not a child of document
+ </div>
+ <div class="render">
+ </div>
+ <div class="log">
+ <p class="output"></p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/webgl-compressed-texture-size-limit-stress.html b/dom/canvas/test/webgl-conf/checkout/extra/webgl-compressed-texture-size-limit-stress.html
new file mode 100644
index 0000000000..9f515be7ac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/webgl-compressed-texture-size-limit-stress.html
@@ -0,0 +1,33 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL compressed texture size limit stress test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../js/js-test-pre.js"></script>
+<script src="../js/webgl-test-utils.js"></script>
+<script src="../js/tests/webgl-compressed-texture-size-limit.js"></script>
+</head>
+<body>
+<canvas id="example" width="32" height="32" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Checks size limit of the webgl compressed textures. Variation on the corresponding conformance test that stresses the browser with large ArrayBuffer allocations, and both valid and invalid large texture uploads.")
+
+// Use the theoretical 4 GB - 1 byte limit for ArrayBuffer allocations.
+// The maximum texture size is often so large that it will certainly cause OOM with a cube map, so limit the positive test to a somewhat smaller size, even though this is a stress test.
+runCompressedTextureSizeLimitTest(Math.pow(2, 32) - 1, 8192);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/webgl-drawelements-validation.html b/dom/canvas/test/webgl-conf/checkout/extra/webgl-drawelements-validation.html
new file mode 100644
index 0000000000..c7e11b8cec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/webgl-drawelements-validation.html
@@ -0,0 +1,142 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Micro-benchmark for WebGL drawElements index validation</title>
+<style>
+canvas {
+ border: 1px solid #000;
+}
+</style>
+<script src="../js/webgl-test-utils.js"></script>
+<script type="application/javascript">
+"use strict";
+
+var wtu = WebGLTestUtils;
+
+var totalTimeTest1 = 0;
+var totalTimeTest2 = 0;
+var totalTimeTest3 = 0;
+var iterationsLeft = 10; // How many times to run the full test.
+var indexCount = 500001; // Divisible by 3.
+
+var indices = [];
+for (var i = 0; i < indexCount - 1; ++i) {
+ indices.push(0);
+ indices.push(1);
+ indices.push(2);
+ indices.push(3);
+}
+indices.push(4);
+
+var fullIndicesArray = new Uint16Array(indices);
+
+var drawIterations = 50;
+
+var errorsCorrect = true;
+
+var log = function(msg) {
+ console.log(msg);
+ var p = document.createElement('p');
+ p.textContent = msg;
+ document.body.appendChild(p);
+};
+
+var runTestIteration = function() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 10;
+ canvas.height = 10;
+ var gl = wtu.create3DContext(canvas);
+ document.body.appendChild(canvas);
+
+ var location = 0;
+ wtu.setupSimpleColorProgram(gl, location);
+
+ var verts = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, verts);
+ var vertData = new Float32Array([-1, -1,
+ -1, 1,
+ 1, -1,
+ 1, 1]);
+ gl.bufferData(gl.ARRAY_BUFFER, vertData, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(location);
+
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, fullIndicesArray, gl.DYNAMIC_DRAW);
+ gl.finish();
+
+ var measureTime = function(f) {
+ var startTime = new Date().getTime();
+ f();
+ var error = gl.getError();
+ var endTime = new Date().getTime();
+ errorsCorrect = errorsCorrect && error == gl.INVALID_OPERATION;
+ return endTime - startTime;
+ };
+
+ // The buffer has at least one out-of-range index from the start,
+ // so only validation will happen, not drawing.
+
+ totalTimeTest1 += measureTime(function() {
+ for (var i = 0; i < drawIterations; ++i) {
+ // Change all data, which will cause complete revalidation of the index buffer.
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, fullIndicesArray);
+ gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
+ }
+ });
+
+ totalTimeTest2 += measureTime(function() {
+ for (var i = 0; i < drawIterations; ++i) {
+ // Change only one index and vary the amount of referenced indices.
+ // These should not be a big problem to a smart implementation.
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, Math.floor(indices.length / 2), new Uint16Array([i + 5]));
+ gl.drawElements(gl.TRIANGLES, indices.length - i * 3, gl.UNSIGNED_SHORT, 0);
+ }
+ });
+
+ totalTimeTest3 += measureTime(function() {
+ for (var i = 0; i < drawIterations; ++i) {
+ // Change data at two indices to cause completely revalidating the index buffer in
+ // current implementations in Chrome and Firefox (as of March 17th 2014).
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint16Array([i + 5]));
+ gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, indices.length - 1, new Uint16Array([i + 5]));
+ gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
+ }
+ });
+
+ setTimeout(function() {
+ var lose = gl.getExtension('WEBGL_lose_context');
+ lose.loseContext();
+ }, 40);
+};
+
+var runTest = function() {
+ if (iterationsLeft > 0) {
+ runTestIteration();
+ --iterationsLeft;
+ setTimeout(runTest, 500);
+ } else {
+ log("Validation returned correct results: " + errorsCorrect);
+ log('1. Time spent on full buffer updates: ' + totalTimeTest1 + ' ms');
+ log('Indices uploaded and referenced by draw calls processed: ' + Math.round(indices.length * drawIterations / totalTimeTest1) + ' / ms');
+ log('2. Time spent on validating single index updates while range referenced also changes on every draw call: ' + totalTimeTest2 + ' ms');
+ log('Indices referenced by draw calls handled: ' + Math.round(indices.length * drawIterations / totalTimeTest2) + ' / ms');
+ log('3. Time spent on validating single index updates at each end of the buffer (worst case for Firefox implementation as of March 2014, not reflective of real world performance): ' + totalTimeTest3 + ' ms');
+ log('Indices referenced by draw calls handled: ' + Math.round(indices.length * drawIterations / totalTimeTest3) + ' / ms');
+ }
+};
+</script>
+</head>
+<body onload="setTimeout(runTest, 100)">
+<h1>Micro-benchmark for WebGL drawElements index validation</h1>
+<p>Note that these test cases are completely artificial, and their results only very rough indicators of the performance of a specific part of the system.</p>
+<p>The benchmark does not perform any drawing, but rather measures the time the browser takes to upload indices and to check if there are out-of-range indices.</p>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/webgl-info.html b/dom/canvas/test/webgl-conf/checkout/extra/webgl-info.html
new file mode 100644
index 0000000000..9929edb178
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/webgl-info.html
@@ -0,0 +1,275 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Information</title>
+<style type="text/css">
+th, td {
+ padding: 4pt;
+}
+th {
+ text-align: right;
+ min-width: 22em;
+}
+</style>
+<script src="../js/webgl-test-utils.js"> </script>
+<script>
+"use strict";
+window.onload = main;
+
+function createCell(txt, isTh) {
+ var str = txt.toString();
+ if (typeof txt != 'string') {
+ if (txt.length !== undefined) {
+ str = "";
+ for (var ii = 0; ii < txt.length; ++ii) {
+ str += (ii == 0 ? "" : ", ") + txt[ii];
+ }
+ }
+ }
+ var t = document.createTextNode(str);
+ var d = document.createElement("div");
+ var td;
+ if (isTh) {
+ td = document.createElement("th");
+ } else {
+ td = document.createElement("td");
+ }
+ d.appendChild(t);
+ td.appendChild(d);
+ return td;
+}
+
+function createRow(values) {
+ var tr = document.createElement("tr");
+ for (var i = 0; i < values.length; ++i) {
+ var td = createCell(values[i], i == 0);
+ tr.appendChild(td);
+ }
+ return tr;
+}
+
+function main() {
+ var wtu = WebGLTestUtils;
+
+ var canvas = document.getElementById("example");
+ var gl = wtu.create3DContext(canvas);
+ if (!gl) {
+ return;
+ }
+
+ var debugRendererInfoRows = function() {
+ var rows = [];
+ var debugExt = wtu.getExtensionWithKnownPrefixes(gl, 'WEBGL_debug_renderer_info');
+ if (debugExt) {
+ var extPnames = [
+ 'UNMASKED_VENDOR_WEBGL',
+ 'UNMASKED_RENDERER_WEBGL'
+ ];
+ for (var ii = 0; ii < extPnames.length; ++ii) {
+ var pname = extPnames[ii];
+ var value = gl.getParameter(debugExt[pname]);
+ rows.push([pname, value]);
+ }
+ }
+ return rows;
+ };
+
+ var precisionRows = function() {
+ var rows = [];
+
+ var addPrecisionRow = function(shaderType, precision) {
+ var typeStr = shaderType === gl.FRAGMENT_SHADER ? 'fragment' : 'vertex';
+ var precisionStr = 'highp';
+ if (precision == gl.MEDIUM_FLOAT) {
+ precisionStr = 'mediump';
+ } else if (precision == gl.LOW_FLOAT) {
+ precisionStr = 'lowp';
+ }
+ rows.push([typeStr + ' shader ' + precisionStr + ' float', gl.getShaderPrecisionFormat(shaderType, precision).precision + ' mantissa bits']);
+ };
+
+ var fSource = 'precision highp float; uniform float r; void main() { gl_FragColor = vec4(r, 0.0, 0.0, 1.0); }'
+ var f = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER);
+ if (!f) {
+ rows.push(['fragment shader highp float', 'not supported']);
+ } else {
+ addPrecisionRow(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
+ }
+ addPrecisionRow(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);
+ addPrecisionRow(gl.FRAGMENT_SHADER, gl.LOW_FLOAT);
+ addPrecisionRow(gl.VERTEX_SHADER, gl.HIGH_FLOAT);
+ addPrecisionRow(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);
+ addPrecisionRow(gl.VERTEX_SHADER, gl.LOW_FLOAT);
+ return rows;
+ };
+
+ var renderTargetRows = function() {
+ var rows = [];
+ var oesTextureFloat = wtu.getExtensionWithKnownPrefixes(gl, 'OES_texture_float');
+ var oesTextureHalfFloat = wtu.getExtensionWithKnownPrefixes(gl, 'OES_texture_half_float');
+ var formatsToTest = [
+ {
+ description: 'RGBA UNSIGNED_BYTE',
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE
+ },
+ {
+ description: 'RGB UNSIGNED_BYTE',
+ format: gl.RGB,
+ type: gl.UNSIGNED_BYTE
+ }
+ ];
+ if (oesTextureFloat) {
+ formatsToTest.push({
+ description: 'RGBA FLOAT',
+ format: gl.RGBA,
+ type: gl.FLOAT
+ });
+ formatsToTest.push({
+ description: 'RGB FLOAT (deprecated)',
+ format: gl.RGB,
+ type: gl.FLOAT
+ });
+ }
+ if (oesTextureHalfFloat) {
+ formatsToTest.push({
+ description: 'RGBA HALF_FLOAT_OES',
+ format: gl.RGBA,
+ type: oesTextureHalfFloat.HALF_FLOAT_OES
+ });
+ formatsToTest.push({
+ description: 'RGB HALF_FLOAT_OES',
+ format: gl.RGB,
+ type: oesTextureHalfFloat.HALF_FLOAT_OES
+ });
+ }
+ for (var ii = 0; ii < formatsToTest.length; ++ii) {
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ var format = formatsToTest[ii];
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+ gl.texImage2D(gl.TEXTURE_2D, 0, format.format, 256, 256, 0, format.format, format.type, null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ rows.push([format.description, 'supported']);
+ } else {
+ rows.push([format.description, 'not supported']);
+ }
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+ }
+ return rows;
+ };
+
+ var info = [
+ {
+ title: 'Renderer',
+ pnames: [
+ 'VERSION',
+ 'VENDOR',
+ 'RENDERER'
+ ],
+ genRows: debugRendererInfoRows
+ },
+ {
+ title: 'Textures and Viewport',
+ pnames: [
+ 'MAX_TEXTURE_SIZE',
+ 'MAX_CUBE_MAP_TEXTURE_SIZE',
+ 'MAX_RENDERBUFFER_SIZE',
+ 'MAX_VIEWPORT_DIMS'
+ ]
+ },
+ {
+ title: 'Shader Variables',
+ pnames: [
+ 'MAX_VARYING_VECTORS',
+ 'MAX_VERTEX_ATTRIBS',
+ 'MAX_VERTEX_UNIFORM_VECTORS',
+ 'MAX_FRAGMENT_UNIFORM_VECTORS',
+ 'MAX_VERTEX_TEXTURE_IMAGE_UNITS',
+ 'MAX_TEXTURE_IMAGE_UNITS',
+ 'MAX_COMBINED_TEXTURE_IMAGE_UNITS'
+ ]
+ },
+ {
+ title: 'Shader Precision',
+ genRows: precisionRows
+ },
+ {
+ title: 'Framebuffer Texture Attachment Support',
+ genRows: renderTargetRows
+ }
+ ];
+
+ // TODO: max anisotropy, framebuffer depth bits, MSAA samples, max multiple render targets buffers, point size, line width
+
+ for (var jj = 0; jj < info.length; ++jj) {
+ var table = document.createElement("table");
+ var tb = document.createElement("tbody");
+ if (info[jj].pnames) {
+ var pnames = info[jj].pnames;
+ for (var ii = 0; ii < pnames.length; ++ii) {
+ var pname = pnames[ii];
+ var value = gl.getParameter(gl[pname]);
+ tb.appendChild(createRow([pname, value]));
+ }
+ }
+ if (info[jj].genRows) {
+ var genRows = info[jj].genRows();
+ for (var ii = 0; ii < genRows.length; ++ii) {
+ tb.appendChild(createRow(genRows[ii]));
+ }
+ }
+ table.appendChild(tb);
+ var header = document.createElement("h2");
+ header.textContent = info[jj].title;
+ document.getElementById("info").appendChild(header);
+ document.getElementById("info").appendChild(table);
+ }
+ var extensionList = document.createElement('ul');
+ var exts = gl.getSupportedExtensions();
+ var extsWithPrefixes = [];
+ while (exts.length > 0) {
+ var prefixedNames = wtu.getExtensionPrefixedNames(exts[0]);
+ var supportedPrefixedNames = [];
+ for (var ii = 0; ii < prefixedNames.length; ++ii) {
+ var index = exts.indexOf(prefixedNames[ii]);
+ if (index >= 0) {
+ supportedPrefixedNames.push(exts[index]);
+ exts.splice(index, 1);
+ }
+ }
+ extsWithPrefixes.push(supportedPrefixedNames.join(" / "));
+ }
+ extsWithPrefixes.sort();
+ for (var ii = 0; ii < extsWithPrefixes.length; ++ii) {
+ var li = document.createElement('li');
+ li.appendChild(document.createTextNode(extsWithPrefixes[ii]));
+ extensionList.appendChild(li);
+ }
+ document.getElementById('extensions').appendChild(extensionList);
+}
+</script>
+</head>
+<body>
+<h1>WebGL Info</h1>
+<div id="info"></div>
+<h2>WebGL Extensions</h2>
+<div id="extensions"></div>
+<canvas id="example" width="256" height="16" style="width: 256px; height: 48px;"></canvas>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/webgl-translate-shader.html b/dom/canvas/test/webgl-conf/checkout/extra/webgl-translate-shader.html
new file mode 100644
index 0000000000..55176b6ffd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/webgl-translate-shader.html
@@ -0,0 +1,153 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Shader Translator</title>
+<style>
+textarea {
+ min-width: 70%;
+ min-height: 200px;
+ font-family: monospace;
+ background: #def;
+}
+#disabled {
+ color: red;
+ font-weight: bold;
+}
+</style>
+<script>
+// Needed by wtu.create3DContext():
+var testFailed = function() {};
+</script>
+<script src="../js/webgl-test-utils.js"> </script>
+<script>
+"use strict";
+window.onload = main;
+
+var gl;
+var debugShaders;
+var enabledExtensions = [];
+
+var translateButton;
+var extButton;
+
+function main() {
+ translateButton = document.getElementById('translate');
+ extButton = document.getElementById('getExts');
+
+ var wtu = WebGLTestUtils;
+ // Prioritize creating a WebGL 2 context if possible - if not, fall back to WebGL 1.
+ gl = wtu.create3DContext(undefined, undefined, 2);
+ if (!gl || !gl.getExtension('WEBGL_debug_shaders'))
+ {
+ gl = wtu.create3DContext();
+ }
+ if (!gl) {
+ disable();
+ return;
+ }
+
+ debugShaders = gl.getExtension('WEBGL_debug_shaders');
+ if (!debugShaders) {
+ disable();
+ }
+}
+
+function disable() {
+ translateButton.disabled = true;
+ extButton.disabled = true;
+ document.getElementById('disabled').style.display = 'block';
+}
+
+function getExtensions() {
+ getExtensionSet([
+ 'EXT_frag_depth',
+ 'EXT_shader_texture_lod',
+ 'OES_standard_derivatives',
+ 'WEBGL_draw_buffers'
+ ]);
+}
+
+function getExtensionSet(shaderExtensions) {
+ for (var i = 0; i < shaderExtensions.length; ++i) {
+ if (enabledExtensions.indexOf(shaderExtensions[i]) < 0) {
+ var ext = gl.getExtension(shaderExtensions[i]);
+ if (ext) {
+ enabledExtensions.push(shaderExtensions[i]);
+ }
+ }
+ }
+ if (enabledExtensions.length > 0) {
+ document.getElementById('enabled-extensions').textContent = enabledExtensions.join(', ');
+ }
+}
+
+function translateShader() {
+ var sourceElement = document.getElementById('original-shader');
+ var source = sourceElement.value;
+
+ var output = document.getElementById('translated-shader');
+ var infoLog = document.getElementById('info-log');
+ var shaderType = document.getElementById('shader-type');
+ infoLog.value = '';
+
+ // Try compiling the source as both vertex and fragment shader and see if either one works
+ var tryCompile = function(type) {
+ var shader = gl.createShader(type);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+ var shaderTypeStr;
+ if (type == gl.FRAGMENT_SHADER) {
+ shaderTypeStr = 'Fragment shader';
+ } else {
+ shaderTypeStr = 'Vertex shader';
+ }
+ if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+ shaderType.textContent = shaderTypeStr;
+ var translatedSource = debugShaders.getTranslatedShaderSource(shader);
+ output.value = translatedSource;
+ infoLog.value = gl.getShaderInfoLog(shader);
+ return true;
+ } else {
+ infoLog.value += 'Info log when compiling as ' + shaderTypeStr + ':\n' + gl.getShaderInfoLog(shader) + '\n';
+ return false;
+ }
+ }
+
+ if (!tryCompile(gl.FRAGMENT_SHADER) && !tryCompile(gl.VERTEX_SHADER)) {
+ output.value = 'Invalid shader, compilation failed as both fragment and vertex shader.';
+ shaderType.textContent = 'Shader not';
+ }
+}
+</script>
+</head>
+<body>
+<h1>WebGL Shader Translator</h1>
+<p>This page uses the browser's built-in shader translation facilities to show how a shader
+is changed before being passed on to the underlying platform's graphics driver.</p>
+<p id="disabled" style="display: none;">
+ WebGL or WEBGL_debug_shaders extension is not available on this browser configuration.
+ Use a different browser or look for other alternatives to enable the extension to be able to use this page.
+ The extension might be behind a runtime flag for privacy considerations.
+</p>
+<h2>WebGL GLSL shader</h2>
+<textarea id="original-shader"></textarea>
+<p>
+<input type="button" id="translate" value="Translate" onclick="translateShader()"></input>
+<input type="button" id="getExts" value="Enable supported GLSL extensions" onclick="getExtensions()"></input>
+</p>
+<h2><span id="shader-type">Shader</span> translated for graphics driver</h2>
+<textarea id="translated-shader"></textarea>
+<h2>Enabled shader extensions</h2>
+<p id="enabled-extensions">None</p>
+<h2>Shader info log</h2>
+<textarea id="info-log"></textarea>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/extra/workload-simulator.html b/dom/canvas/test/webgl-conf/checkout/extra/workload-simulator.html
new file mode 100644
index 0000000000..fa01977321
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/extra/workload-simulator.html
@@ -0,0 +1,851 @@
+<!DOCTYPE html><meta charset="utf-8">
+<meta name=viewport content="width=900">
+<title>WebGL workload simulator</title>
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<style>
+body {
+ margin: 0;
+ font-family: monospace;
+ user-select: none;
+ -moz-user-select: -moz-none;
+ -webkit-user-select: none;
+ font-size: 22px;
+ text-size-adjust: none;
+}
+pre { margin: 0; }
+.square img { position: relative; }
+.square {
+ overflow: hidden;
+ border-bottom: 20px solid black;
+ border-right: 20px solid black;
+ display: block;
+}
+
+#fpsSpan { font-size: 30px; }
+#fpsPanel {
+ position: fixed;
+ text-align: right;
+ left: 550px;
+ top: 0px;
+ width: 300px;
+ font-size: 12px;
+ margin: 10px;
+ pointer-events: none;
+}
+
+input, label { white-space: pre; pointer-events: auto; }
+input { margin: 15px 15px; transform: scale(2); }
+input[type="number"] { width: 50px; }
+input[type="range"] {
+ width: 100px;
+ margin: 30px 200px;
+ padding: 0px;
+ transform: scale(4);
+}
+
+.rotate { animation: rotating 2s linear infinite; }
+@keyframes rotating {
+ from { transform: scale(2) rotate(0deg); }
+ to { transform: scale(2) rotate(360deg); }
+}
+
+.bad { color: red; }
+.light { color: #CCCCCC; }
+#warning {
+ color: #FF0000;
+}
+</style>
+
+<canvas id=webglCanvas class=square></canvas>
+<canvas id=canvas class=square style=display:none;></canvas>
+<div id=dom class=square style=display:none;background:white>
+ <img id=img style=width:256px;height:256px;background:black></img>
+</div>
+<div style=margin:2em;margin-top:0>
+<div id=warning></div>
+Drag the WebGL logo.<br>
+<label for=useGl>Renderer: <input type=radio name=renderer id=useGl checked>WebGL</label>
+<label for=use2D><input type=radio name=renderer id=use2D>Canvas 2D</label>
+<label for=useDom><input type=radio name=renderer id=useDom>DOM</label>
+<br>
+<label for=animate><input type=checkbox name=animate id=animate>Animate</label>
+<span id=continuousOptions>
+ <label for=useRaf><input type=radio name=loop id=useRaf checked>requestAnimationFrame</label>
+ <label for=usePostMessage><input type=radio name=loop id=usePostMessage>postMessage</label>
+ <label for=useSetTimeout><input type=radio name=loop id=useSetTimeout>setTimeout</label>
+ <label for=useSetInterval><input type=radio name=loop id=useSetInterval>setInterval</label>
+ <br>
+ <div id=fpsOptions>
+ <input id=fpsSlider type=range min=10 max=240 step=10 value=60>
+ Target FPS: <span id=fpsLabel>60</span>
+ </div>
+</span>
+<details id=canvasOptions>
+ <summary>Canvas options</summary>
+ <div id=canvas2DOptions>
+ Canvas size <input type=number id=canvasSize value=512 min=1> pixels<sup>2</sup>
+ <label for=onscreen><input type=radio name=offscreen id=onscreen checked>Regular canvas</label>
+ <label for=offscreen><input type=radio name=offscreen id=offscreen>OffscreenCanvas (on main thread)</label>
+ <!-- <label for=offscreenWorker><input type=radio name=offscreen id=offscreenWorker>OffscreenCanvas on worker</label> -->
+ <br>
+ <label for=transferControlToOffscreen><input type=checkbox id=transferControlToOffscreen checked>Use transferControlToOffscreen</label>
+ </div>
+</details>
+<div id=glOptions>
+ <details id=glWork>
+ <summary>WebGL rendering work</summary>
+ <div id=pixelsWrapper>
+ <input type=range id=pixels min=65536 max=65536000 value=65536 step=65536>
+ draw <span id=pixelsLabel>64K</span> pixels per view
+ </div>
+ <input type=range id=drawCalls min=0 max=10000 value=0 step=10>
+ using <span id=drawCallsLabel>1</span> draw call(s) per view
+ <br>
+ Multiply the above slider values by:
+ <label for=x1><input type=radio name=multiplier id=x1 checked>1 </label>
+ <label for=x10><input type=radio name=multiplier id=x10>10 </label>
+ <label for=x100><input type=radio name=multiplier id=x100>100 </label>
+ <br>
+ <input type=range id=uploads min=0 max=256 value=0 step=0.25>
+ <span id=uploadLabel>0.00</span> MB glBufferData
+ <br>
+ <label for=finish><input type=checkbox id=finish>glFinish</label>
+ <br>
+ <label for=readPixels><input type=checkbox id=readPixels>glReadPixels</label>
+ </details>
+ <details id=contextCreation>
+ <summary>WebGL context creation options</summary>
+ <label for=useWebGL2><input type=checkbox id=useWebGL2 checked>Use WebGL 2 if available</label>
+ <label for=antialias><input type=checkbox id=antialias checked>Antialias</label>
+ <label for=alpha><input type=checkbox id=alpha checked>Alpha</label>
+ <label for=depth><input type=checkbox id=depth checked>Depth</label>
+ <label for=stencil><input type=checkbox id=stencil>Stencil</label>
+ <label for=premultipliedAlpha><input type=checkbox id=premultipliedAlpha checked>Premultiplied Alpha</label>
+ <label for=preserveDrawingBuffer><input type=checkbox id=preserveDrawingBuffer>Preserve Drawing Buffer</label>
+ <label for=desynchronized><input type=checkbox id=desynchronized>Desynchronized</label>
+ <br>
+ Power preference
+ <label for=ppDefault><input type=radio name=pp id=ppDefault checked>default</label>
+ <label for=lowPower><input type=radio name=pp id=lowPower>low-power</label>
+ <label for=highPerformance><input type=radio name=pp id=highPerformance>high-performance</label>
+ <br>
+ <label for=separateHighPowerContext><input type=checkbox id=separateHighPowerContext>Activate high power GPU (by creating a separate high power context)</label>
+ </details>
+ <div id=multiviewOptions>
+ <input type=range id=views min=1 max=4 value=0 step=1>
+ Draw <span id=viewsLabel>1</span> views(s)
+ <br>
+ <label for=multiview><input type=checkbox id=multiview>Use OVR_multiview2</label>
+ <label for=multiviewCopy><input type=checkbox id=multiviewCopy checked>Copy multiview draw results to main canvas</label>
+ </div>
+ <pre id=contextVersion>
+ </pre>
+ <details id=contextAttributes>
+ <summary>Context attributes</summary>
+ <pre></pre>
+ </details>
+ <details id=supportedExtensions>
+ <summary>Supported Extensions</summary>
+ </details>
+</div>
+<br>
+<input type=range id=jsWork min=0 max=100 value=0>
+<span id=jsWorkLabel>0</span> ms extra Javascript work per frame
+<br>
+<label for=animation><input type=checkbox id=animation>CSS animation</label>
+
+<div id=fpsPanel>
+ <label for=showFps><input type=checkbox id=showFps checked>Show FPS</label>
+ <div id=fps>
+ <span id=fpsSpan></span>
+ <p>
+ <label for=showStats><input type=checkbox id=showStats>More info</label>
+ <div id=stats></div>
+ </div>
+</div>
+
+<iframe id=highPowerFrame style=display:none></iframe>
+
+<h2><center>WebGL workload simulator</center></h2>
+</div>
+
+<script>
+'use strict';
+// Add all elements with ids as global readonly variables.
+for (let element of document.documentElement.querySelectorAll('[id]'))
+ Object.defineProperty(this, element.id, {value: element, writeable: false});
+
+
+/************\
+* Options UI *
+\************/
+
+
+// Set all input elements with values from the query string.
+const controls = document.querySelectorAll('input, details');
+const defaultChecked = {};
+const defaultValues = {};
+const defaultMaxes = {};
+for (const control of controls) {
+ if (!control.id) continue;
+ defaultChecked[control.id] = control.checked;
+ defaultValues[control.id] = control.value;
+ defaultMaxes[control.id] = control.max;
+ const param = window.location.search.match(control.id + '(?:=([^&]*))?');
+ if (param) {
+ if (control.type == 'radio')
+ control.checked = true;
+ else if (control.type == 'checkbox')
+ control.checked = param[1] != 'false';
+ else if (control instanceof HTMLDetailsElement)
+ control.open = true;
+ else
+ control.value = param[1];
+ }
+ control.oninput = updateControls;
+ if (control instanceof HTMLDetailsElement)
+ control.onclick = ()=>setTimeout(updateControls, 0);
+}
+// Some controls require a page reload when changed.
+const reloadControls = ['useWebGL2', 'antialias', 'alpha', 'depth', 'stencil', 'premultipliedAlpha', 'preserveDrawingBuffer', 'desynchronized', 'ppDefault', 'lowPower', 'highPerformance', 'canvasSize', 'onscreen', 'offscreen', 'transferControlToOffscreen'].map(x=>window[x]);
+for (let control of reloadControls) {
+ control.onchange = ()=>{
+ updateControls();
+ callReplaceStateThrottled();
+ location.reload();
+ };
+}
+
+separateHighPowerContext.onchange = ()=>{
+ if (!separateHighPowerContext.checked)
+ highPowerFrame.contentDocument.location.reload();
+ else {
+ const doc = highPowerFrame.contentDocument;
+ const canvas = doc.createElement('canvas');
+ doc.body.appendChild(canvas);
+ canvas.getContext('webgl', {powerPreference: 'high-performance'});
+ }
+}
+separateHighPowerContext.onchange();
+
+let queryString = window.location.search;
+let previousQueryString = queryString;
+let replaceStateScheduled = false;
+function callReplaceStateThrottled() {
+ replaceStateScheduled = false;
+ if (queryString == previousQueryString)
+ return;
+ previousQueryString = queryString;
+ let path = window.location.pathname;
+ history.replaceState(null, null, queryString == '?' ? path : path + queryString);
+}
+const suffixes = ['', 'K', 'M', 'G', 'E']
+const divisors = [];
+for (let i = 0; i < suffixes.length; i++)
+ divisors[i] = Math.pow(10, i * 3);
+const formatSI = (x) => {
+ const order = Math.min(Math.log10(Math.abs(x)) / 3 | 0, suffixes.length);
+ return (x / divisors[order]).toFixed(1) + suffixes[order];
+}
+var multiplier;
+function updateControls() {
+ multiplier = x1.checked ? 1 : x10.checked ? 10 : 100;
+ webglCanvas.style.display = useGl.checked ? 'block' : 'none';
+ canvas.style.display = use2D.checked ? 'block' : 'none';
+ dom.style.display = useDom.checked ? 'block' : 'none';
+ animation.className = animation.checked ? 'rotate' : null;
+ canvasOptions.style.display = useDom.checked ? 'none' : '';
+ transferControlToOffscreen.parentElement.style.display = onscreen.checked ? 'none' : '';
+ continuousOptions.style.display = animate.checked ? '' : 'none';
+ glOptions.style.display = useGl.checked ? '' : 'none';
+ multiviewOptions.style.display = (useGl.checked && multiviewAvailable) ? '' : 'none';
+ fpsOptions.style.display =
+ animate.checked && (useSetTimeout.checked || useSetInterval.checked) ?
+ '' : 'none';
+ fps.style.visibility = showFps.checked ? 'visible' : 'hidden';
+ stats.style.visibility = showStats.checked ? 'visible' : 'hidden';
+ drawCallsLabel.textContent = Math.max(1, drawCalls.value * multiplier);
+ pixelsLabel.textContent = formatSI(pixels.value * multiplier);
+ jsWorkLabel.textContent = jsWork.value;
+ fpsLabel.textContent = fpsSlider.value;
+ uploadLabel.textContent =
+ parseFloat(uploads.value).toFixed(2);
+ viewsLabel.textContent = views.value;
+ // Multiview is currently incompatible with multisampling.
+ if ((views.value > 1 || multiview.checked) && antialias.checked)
+ antialias.click();
+
+ const queryParams = [];
+ for (const control of controls) {
+ if (control.type == 'radio') {
+ if (!defaultChecked[control.id] && control.checked)
+ queryParams.push(control.id);
+ } else if (control.type == 'checkbox') {
+ if (control.checked != defaultChecked[control.id])
+ queryParams.push(defaultChecked[control.id] ? control.id + '=' + control.checked : control.id);
+ } else if (control instanceof HTMLDetailsElement) {
+ if (control.open)
+ queryParams.push(control.id);
+ } else if (control.value != defaultValues[control.id]) {
+ queryParams.push(control.id + '=' + control.value);
+ }
+ }
+ queryString = '?' + queryParams.join('&');
+ if (!replaceStateScheduled) {
+ replaceStateScheduled = true;
+ setTimeout(callReplaceStateThrottled, 200);
+ }
+ render();
+};
+
+
+/**********************\
+* Input event handling *
+\**********************/
+
+
+const imgSize = 256;
+const size = parseInt(canvasSize.value);
+let multiviewAvailable = false;
+let webglVersion;
+
+let mouseDown = false;
+const lastPos = [0, 0];
+document.onmouseup = (e) => { mouseDown = false; }
+document.onmousedown = (e) => {
+ mouseDown = true;
+ lastPos[0] = e.pageX;
+ lastPos[1] = e.pageY;
+};
+document.ontouchstart = (e) => {
+ lastPos[0] = e.touches[0].pageX;
+ lastPos[1] = e.touches[0].pageY;
+}
+const position = [(size - imgSize) / 2, (size - imgSize) / 2];
+let continuousRunning = false;
+let mouseUpdatesThisFrame = 0;
+function mouseMove(e) {
+ mouseUpdatesThisFrame++;
+ countFps("mouse/touchmove event");
+ const xy = [0, 0];
+ if (e.touches) {
+ xy[0] = e.touches[0].pageX;
+ xy[1] = e.touches[0].pageY;
+ } else {
+ xy[0] = e.pageX;
+ xy[1] = e.pageY;
+ }
+ if (e.touches || mouseDown) {
+ for (let i = 0; i < 2; ++i) {
+ position[i] += xy[i] - lastPos[i];
+ position[i] = Math.max(0, Math.min(size - imgSize, position[i]));
+ lastPos[i] = xy[i];
+ }
+ if (!continuousRunning) {
+ render();
+ }
+ }
+}
+document.addEventListener("mousemove", mouseMove, true);
+document.body.addEventListener("touchmove", mouseMove, true);
+for (const element of [dom, canvas, webglCanvas, img])
+ element.onmousedown = element.ontouchstart = (e)=>e.preventDefault();
+
+
+
+/***********\
+* Rendering *
+\***********/
+
+
+webglCanvas.width = webglCanvas.height = canvas.width = canvas.height = size;
+dom.style.width = dom.style.height = size + 'px';
+
+window.onmessage = () => render(false, true);
+
+let ctx;
+let bitmapRenderer;
+let offscreenCanvas;
+let gl;
+let glBitmapRenderer;
+let glOffscreenCanvas;
+let program;
+let buffer;
+const borderSize = 10;
+const vertices = [0, 0, 1, 0, 0, 1, 1, 1];
+const readPixelsArray = new Uint8Array(4);
+let writeBufferArray = new Float32Array(0);
+let interval;
+let intervalFps;
+let timeout = null;
+let rafPending = 0;
+let postMessagePending = 0;
+
+let maxViewsMultiview = 2;
+let multiviewProgram = [];
+let multiviewExt = null;
+let multiviewTexture = null;
+let multiviewFramebuffer = null;
+let viewFramebuffer = [];
+let lastNumViews = 0;
+
+let displayedWarningText = '';
+let warningText = '';
+
+const animationDirection = [1, -1];
+function render(fromRaf, fromPostMessage) {
+ if (fromRaf) rafPending--;
+ if (fromPostMessage) postMessagePending--;
+ // Set up the appropriate render loop callback as specified by the UI, if
+ // continuous rendering is enabled.
+ continuousRunning = animate.checked;
+ if (continuousRunning) {
+ for (let i = 0; i < 2; ++i) {
+ position[i] += animationDirection[i] * 2;
+ if (position[i] > size - imgSize) {
+ position[i] = size - imgSize;
+ animationDirection[i] = -1;
+ }
+ if (position[i] < 0) {
+ position[i] = 0;
+ animationDirection[i] = 1;
+ }
+ }
+ if (useRaf.checked && rafPending == 0) {
+ (window.requestAnimationFrame || window.mozRequestAnimationFrame ||
+ window.webkitRequestAnimationFrame)(function() { render(true); });
+ rafPending++;
+ }
+ if (useSetTimeout.checked) {
+ clearTimeout(timeout);
+ timeout = setTimeout(render, 1 / fpsSlider.value * 1000);
+ }
+ if (useSetInterval.checked) {
+ if (!interval || intervalFps != fpsSlider.value) {
+ clearInterval(interval);
+ intervalFps = fpsSlider.value;
+ interval = setInterval(render, 1 / fpsSlider.value * 1000);
+ }
+ } else {
+ clearInterval(interval);
+ interval = null;
+ }
+ if (usePostMessage.checked) {
+ if (postMessagePending == 0) {
+ ++postMessagePending;
+ window.postMessage('', '*');
+ }
+ }
+ } else {
+ clearInterval(interval);
+ interval = null;
+ }
+
+ countFps("render", mouseUpdatesThisFrame);
+ mouseUpdatesThisFrame = 0;
+
+ // Busy wait for a configurable amount of time.
+ const startMs = Date.now();
+ while (Date.now() - startMs < jsWork.value);
+
+ warningText = '';
+
+ // Initialize GL.
+ if (!gl) {
+ const options = {};
+ for (let option of ['antialias', 'alpha', 'depth', 'stencil', 'premultipliedAlpha', 'preserveDrawingBuffer', 'desynchronized'])
+ options[option] = window[option].checked;
+ options.powerPreference = ppDefault.checked ? 'default' : lowPower.checked ? 'low-power' : 'high-performance';
+ let renderCanvas = webglCanvas;
+ if (offscreen.checked) {
+ if (transferControlToOffscreen.checked) {
+ renderCanvas = webglCanvas.transferControlToOffscreen();
+ } else {
+ glBitmapRenderer = webglCanvas.getContext('bitmaprenderer')
+ renderCanvas = glOffscreenCanvas = new OffscreenCanvas(size, size);
+ }
+ }
+ renderCanvas.width = renderCanvas.height = size;
+ if (useWebGL2.checked)
+ gl = renderCanvas.getContext('webgl2', options);
+ if (gl) {
+ webglVersion = 2;
+ } else {
+ webglVersion = 1;
+ gl = renderCanvas.getContext('webgl', options);
+ const aia = gl.getExtension('ANGLE_instanced_arrays');
+ if (aia)
+ gl.drawArraysInstanced = (a, b, c, d)=>aia.drawArraysInstancedANGLE(a, b, c, d);
+ else {
+ pixels.value = pixels.min;
+ pixelsWrapper.style.display = 'none';
+ gl.drawArraysInstanced = (a, b, c, d)=>gl.drawArrays(a, b, c);
+ }
+ }
+ // Read context info like renderer string and extensions.
+ let renderer = gl.getParameter(gl.RENDERER);
+ let debugRendererInfo = gl.getExtension('WEBGL_debug_renderer_info');
+ if (debugRendererInfo)
+ renderer = gl.getParameter(debugRendererInfo.UNMASKED_RENDERER_WEBGL);
+ contextVersion.textContent = `WebGL Version: ${gl.getParameter(gl.VERSION)}\nRenderer: `;
+ const a = document.createElement('a');
+ a.textContent = renderer;
+ a.href = `https://www.google.com/search?q=${encodeURIComponent(renderer)}`
+ contextVersion.appendChild(a);
+ contextAttributes.getElementsByTagName('pre')[0].textContent = JSON.stringify(gl.getContextAttributes(), 0, 2);
+ for (const e of gl.getSupportedExtensions()) {
+ const a = document.createElement('a');
+ a.textContent = e;
+ a.href = `https://www.khronos.org/registry/webgl/extensions/${e}/`;
+ supportedExtensions.appendChild(a);
+ supportedExtensions.appendChild(document.createElement('br'));
+ }
+
+ // Setup texture
+ const tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));
+ img.onload = ()=>{
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ gl.generateMipmap(gl.TEXTURE_2D);
+ render();
+ };
+
+ function setupProgram(vsSource, fsSource, attribs, uniforms) {
+ let prog = gl.createProgram();
+ function compileShader(source, type) {
+ const shader = gl.createShader(type);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
+ console.log(gl.getShaderInfoLog(shader));
+ gl.attachShader(prog, shader);
+ }
+ compileShader(vsSource, gl.VERTEX_SHADER);
+ compileShader(fsSource, gl.FRAGMENT_SHADER);
+ for (let i = 0; i < attribs.length; ++i)
+ gl.bindAttribLocation(prog, i, attribs[i]);
+ gl.linkProgram(prog);
+ if (!gl.getProgramParameter(prog, gl.LINK_STATUS))
+ console.log(gl.getProgramInfoLog(prog));
+ for (const attrib of attribs)
+ prog[attrib] = gl.getAttribLocation(prog, attrib);
+ for (const uniform of uniforms)
+ prog[uniform] = gl.getUniformLocation(prog, uniform);
+ return prog;
+ }
+
+ program = setupProgram(`
+ attribute vec2 position;
+ varying vec2 texCoord;
+ uniform vec2 offset;
+ uniform float size;
+ void main() {
+ gl_Position = vec4(position * size + offset + vec2(size - 1., 1. - size), 0, 1);
+ texCoord = vec2(position.x, 1. - position.y);
+ }`,`
+ precision mediump float;
+ varying vec2 texCoord;
+ uniform vec4 colorAddition;
+ uniform sampler2D tex;
+ void main() {
+ gl_FragColor = texture2D(tex, texCoord) + colorAddition * 0.5;
+ }`,
+ ['position', 'texCoordIn'], ['offset', 'tex', 'size', 'colorAddition']);
+ gl.useProgram(program);
+ gl.uniform1i(program.tex, 0);
+
+ if (webglVersion >= 2 && gl.getExtension('OVR_multiview2')) {
+ multiviewAvailable = true;
+ let ext = gl.getExtension('OVR_multiview2')
+ maxViewsMultiview = Math.min(gl.getParameter(ext.MAX_VIEWS_OVR), 16);
+ views.max = maxViewsMultiview;
+ for (let i = 0; i < maxViewsMultiview; ++i) {
+ multiviewProgram[i] = setupProgram(`#version 300 es
+ #extension GL_OVR_multiview2 : enable
+ layout(num_views=${i + 1}) in;
+ in vec2 position;
+ out vec2 texCoord;
+ uniform vec2 offset;
+ uniform float size;
+ void main() {
+ gl_Position = vec4(position * size + offset + vec2(size - 1., 1. - size), 0, 1);
+ texCoord = vec2(position.x, 1. - position.y);
+ }`, `#version 300 es
+ #extension GL_OVR_multiview2 : enable
+ precision mediump float;
+ in vec2 texCoord;
+ out vec4 my_FragColor;
+ uniform sampler2D tex;
+ void main() {
+ vec4 colorAddition = vec4(((gl_ViewID_OVR & 0x4u) != 0u) ? 1.0 : 0.0,
+ ((gl_ViewID_OVR & 0x2u) != 0u) ? 1.0 : 0.0,
+ ((gl_ViewID_OVR & 0x1u) != 0u) ? 1.0 : 0.0,
+ 1.0);
+ my_FragColor = texture(tex, texCoord) + colorAddition * 0.5;
+ }`,
+ ['position', 'texCoordIn'], ['offset', 'tex', 'size']);
+ gl.useProgram(multiviewProgram[i]);
+ gl.uniform1i(multiviewProgram[i].tex, 0);
+ }
+ }
+
+ // Setup vertex buffer
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STREAM_DRAW);
+ gl.enableVertexAttribArray(program.position);
+ gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
+
+ // Setup drawing state
+ gl.viewport(0, 0, size, size);
+ gl.clearColor(1, 1, 1, 1);
+ gl.disable(gl.SCISSOR_TEST);
+ gl.disable(gl.DEPTH_TEST);
+ gl.disable(gl.STENCIL_TEST);
+ gl.disable(gl.BLEND);
+ gl.disable(gl.CULL_FACE);
+
+ updateControls();
+ } // End GL init
+
+ if (useDom.checked) {
+ img.style.left = position[0] + 'px';
+ img.style.top = position[1] + 'px';
+ return;
+ }
+ if (use2D.checked) {
+ if (!ctx) {
+ if (offscreen.checked) {
+ if (transferControlToOffscreen.checked) {
+ offscreenCanvas = canvas.transferControlToOffscreen();
+ } else {
+ bitmapRenderer = canvas.getContext('bitmaprenderer');
+ offscreenCanvas = new OffscreenCanvas(size, size);
+ }
+ ctx = offscreenCanvas.getContext('2d');
+ } else {
+ ctx = canvas.getContext('2d');
+ }
+ }
+ ctx.fillStyle = 'white';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ try {
+ ctx.drawImage(img, position[0], position[1]);
+ } catch (e) {
+ ctx.fillStyle = 'black';
+ ctx.fillRect(position[0], position[1], imgSize, imgSize);
+ }
+ if (offscreen.checked && !transferControlToOffscreen.checked && bitmapRenderer && offscreenCanvas) {
+ bitmapRenderer.transferFromImageBitmap(offscreenCanvas.transferToImageBitmap());
+ }
+ return;
+ }
+
+ // Upload some data to test the PCI bottleneck.
+ if (uploads.value > 0) {
+ if (writeBufferArray.length * 4 != uploads.value * 1024 * 1024) {
+ writeBufferArray = new Float32Array(uploads.value * 1024 * 1024 / 4);
+ // We want to actually use this data in rendering so the graphics driver
+ // can't optimize away the upload. Fill the first few bytes with our real
+ // vertex data.
+ writeBufferArray.set(vertices, 0);
+ }
+ gl.bufferData(gl.ARRAY_BUFFER, writeBufferArray, gl.STREAM_DRAW);
+ }
+
+ // Actually draw the map.
+ const numDrawCalls = Math.max(1, drawCalls.value * multiplier);
+ const numViews = multiviewAvailable ? Math.min(views.value, maxViewsMultiview) : 1;
+ const instances = pixels.value / 64000 * multiplier;
+ const instancesPerCall = Math.max(1, instances / numDrawCalls | 0);
+ const instancesFirstCall = instancesPerCall + numDrawCalls % instancesPerCall;
+ // Set up to scissor out all but one pixel of the map.
+ gl.scissor(position[0], size - position[1] - 1, 1, 1);
+
+ if (multiviewAvailable && (multiview.checked || numViews > 1) && !multiviewFramebuffer) {
+ multiviewTexture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, multiviewTexture);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, size, size, maxViewsMultiview);
+ multiviewExt = gl.getExtension('OVR_multiview2');
+ multiviewFramebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, multiviewFramebuffer);
+ multiviewExt.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture, 0, 0, numViews);
+ lastNumViews = numViews;
+ for (let i = 0; i < maxViewsMultiview; ++i) {
+ viewFramebuffer[i] = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, viewFramebuffer[i]);
+ gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture, 0, i);
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
+ }
+
+ let usedProgram = program;
+ if (multiviewAvailable && multiview.checked) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, multiviewFramebuffer);
+ if (numViews != lastNumViews) {
+ multiviewExt.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture, 0, 0, numViews);
+ lastNumViews = numViews;
+ }
+ usedProgram = multiviewProgram[numViews - 1];
+ } else {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ }
+
+ gl.useProgram(usedProgram);
+ gl.uniform2f(usedProgram.offset,
+ (position[0] - imgSize) / size * 2,
+ -position[1] / size * 2);
+ gl.uniform1f(usedProgram.size, imgSize * 2 / size);
+
+ if (usedProgram == program) {
+ gl.uniform4f(program.colorAddition, 0.0, 0.0, 0.0, 1.0);
+ }
+
+ for (let viewIndex = 0; viewIndex < numViews; ++viewIndex) {
+ let scissorEnabled = false;
+ if (multiviewAvailable && !multiview.checked && numViews > 1) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, viewFramebuffer[viewIndex]);
+ gl.uniform4f(program.colorAddition, (viewIndex & 4) ? 1.0 : 0.0, (viewIndex & 2) ? 1.0 : 0.0, (viewIndex & 1) ? 1.0 : 0.0, 1.0);
+ gl.disable(gl.SCISSOR_TEST);
+ }
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, instancesFirstCall);
+ var instancesDrawn = instancesFirstCall;
+ for (let i = 1; i < numDrawCalls; i++) {
+ if (instancesDrawn > instances && !scissorEnabled) {
+ // If we've drawn all of the requested pixels already, enable the scissor
+ // test so we only draw one pixel per draw call for the rest of the calls.
+ scissorEnabled = true;
+ gl.enable(gl.SCISSOR_TEST);
+ }
+ gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, instancesPerCall);
+ instancesDrawn += instancesPerCall;
+ }
+ if (multiviewAvailable && multiview.checked) {
+ break;
+ }
+ }
+ gl.disable(gl.SCISSOR_TEST);
+
+ if (multiviewAvailable && (multiview.checked || numViews > 1)) {
+ if (multiviewCopy.checked) {
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ gl.clearColor(1, 1, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ let gridCellsPerRow = Math.ceil(Math.sqrt(numViews));
+ for (let i = 0; i < numViews; ++i) {
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, viewFramebuffer[i]);
+ let x = i % gridCellsPerRow;
+ let y = Math.floor(i / gridCellsPerRow);
+ x *= size / gridCellsPerRow;
+ y *= size / gridCellsPerRow;
+ gl.blitFramebuffer(0, 0, size, size, x, y, x + size / gridCellsPerRow, y + size / gridCellsPerRow, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ }
+ } else {
+ warningText = 'NOTE: Offscreen multiview rendering active - rendering not copied to canvas';
+ }
+ }
+
+ if (finish.checked) {
+ gl.finish();
+ }
+ if (readPixels.checked) {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelsArray);
+ }
+ if (offscreen.checked && !transferControlToOffscreen.checked && glOffscreenCanvas && glBitmapRenderer) {
+ glBitmapRenderer.transferFromImageBitmap(glOffscreenCanvas.transferToImageBitmap());
+ }
+}
+
+
+/**************\
+* FPS counters *
+\**************/
+
+
+const counters = {};
+function countFps(name, mouseEventsThisFrame) {
+ let counter = counters[name];
+ if (!counter) {
+ counter = { history: [Date.now() - 16], name: name, count: 0 };
+ counters[name] = counter;
+ }
+ const history = counter.history;
+ history.push(Date.now());
+ while (history.length > 2 &&
+ history[0] + 1000 < history[history.length - 1]) {
+ counter.history.shift();
+ }
+ let averageMs = 0;
+ let maxMs = .1;
+ let minMs = 99999999;
+ for (let i = 1; i < history.length; i++) {
+ let diff = history[i] - history[i - 1];
+ averageMs += diff;
+ maxMs = Math.max(maxMs, diff);
+ minMs = Math.min(minMs, diff);
+ }
+ averageMs /= history.length - 1;
+ counter.fps = 1000 / averageMs;
+ counter.minFps = 1000 / maxMs;
+ counter.maxFps = 1000 / minMs;
+ counter.count++;
+
+ if (mouseEventsThisFrame !== undefined) {
+ counter.mouseEvents = counter.mouseEvents || { multiple: 0, zero: 0 };
+ if (mouseEventsThisFrame > 1) {
+ counter.mouseEvents.multiple++;
+ } else if (mouseEventsThisFrame == 0) {
+ counter.mouseEvents.zero++;
+ }
+ }
+
+ if (showFps.checked) {
+ fpsSpan.innerText = counters['render'].fps.toFixed();
+ if (showStats.checked) {
+ let text = "";
+ for (let key in counters) {
+ counter = counters[key];
+ text += "<b>" + counter.name + "</b><br>";
+ text += counter.fps.toFixed() + " avg FPS<br>";
+ text += "<div class=" +
+ (counter.maxFps - counter.fps > 10 ? "bad" : "") + ">" +
+ counter.maxFps.toFixed() + " max FPS</div>";
+ text += "<div class=" +
+ (counter.fps - counter.minFps > 10 ? "bad" : "") + ">" +
+ counter.minFps.toFixed() + " min FPS</div>";
+ if (counter.mouseEvents) {
+ text += "<div>" + counter.mouseEvents.zero +
+ " frame(s) with no mouse/touch events";
+ text += "<div>" + counter.mouseEvents.multiple +
+ " frame(s) with multiple mouse/touch events";
+ }
+ text += "<div class=light>" + counter.count + " frames</div>";
+ }
+ stats.innerHTML = text;
+ }
+ }
+ if (warningText != displayedWarningText) {
+ warning.textContent = warningText;
+ displayedWarningText = warningText;
+ }
+}
+
+updateControls();
+
+img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAgMAAAAhHED1AAAADFBMVEUAAAA5AAByAACZAAADU26qAAAFIUlEQVR42u2ZPW7jRhTHOVQkFiwEFU4RFTwCj0Am8AG8wHIDrC8QZBH4BAGJNGkdIL7BLpCo8Q1CpkqrDRCkVWEvkKSIChVUQHLy3pshRZlDeUhVCeZf6GOt+XHmvf+8+VjLMjIyMjIyMjIyMjIyMjIyMjIyMjL6j2txEUWX45u/uueo6l04qvlUNCfE9yPaf8zbendme84fB7af8ad6O6g9SzsAfjsEcNNtz6sBuVhylR7OGsCgQXhHzf5crVaCuNftQHvgd2LkF28GdKHVgcdD4C7udbvQ6sCRg9mNZheW6vZEyHUAaW/agKDhBadurxjwNN3oh1BpvGWpb6K12uOJ7gh6Mjbb6I6gL2Ffaeag1zKzZ/Jgn4wA6uo0wJUpgI8fvaDCPrCq+wcPBegaxsthgFgANvSRAEXnNxcaE2lL4UwwJh37v+F7DOTl5SkX7AiQWdaEPgI5CltRwhFy5bxwDwBGqXCoM/gtaw0Sba4G1DbKCbBBwOYYMKuzrAaIGOYIsAngSkc0AK/uoRogfLhJCxw9/mz+FCAeUfYAZBLWcUnx3OEDs2OAHGMPQBo5FIA0R0ByBIBf7EMojoka4EgfBxWOPi7QmeERwMEA2viiBIgsFtAMR++XXYBL0ySF+CoBcxliD/7oVV6JEwJm1UsCsCtKQkEzZqsGeNLHCPBLDx4WV9YsheoCgBTt45MzPXhVAnzpkjkEKSjn8HQIp4++YvwXykpAxpr3AQICZDDSzIpzF36SFpTakPG/qUrE5Itp9FINEC5JINZrADiYrJwykzH5l7SZEycAIQHS3QTb7ea8gqAD4J8U/5UnpwCpBEwwTVubrwHg89sZ3wEgdGjkGgD025bhU9fwAV0Z51TawJqHZicBTD5+A11JIfY+hBLewJqif2i2kwCL72x06xaCgXmblwwLi18yXUAKwc8gjg5/j3lzK4ZvXjUIkJAVfsa8OZwA80p7CHGBLgoA8A3/LYquOU0msOYzgNoH0sc+vH4mSsSnCHA5pVEHIGYSvPKJADDMPwDQiSz6/DQgseRchtdqUvdAAMRcsPsAQV2zPaomUFOqJz2IaTZO+gB+vTDOqZ5BVSsn/P0CRADIQkALjdMHqAsKNMWKCnW1sMX0E1mo4BE5FbbidEmTNR1ec5sGHREA4jKnmuj3Adx61XCoH7i2kINcYSSIi0sxTvsAdVnHphtaBGACb7HvDL8HBf7hAddHBNxFEVQm5cIiKj8uVFucwzSL4A0mJlYmPD0UVrMKq5Y2ubZb2A+oywBh0C8bOyN3cQ1gGr0IO5Nhi4CMvq4hYHfXVJHgbd1sohrA7MPvWcdJtPYm5MxMZGZTF1URpipuAOzXv7LuBgOfHRIgES0SVm/+6EMetAA/Zd0tDhR1LjqU0O67hHb3MmL4jLXfAnzdBkzqLRKuz3JpXWLmGP9W7p8BWFmf/GCtSG+t76Kkm4bqKDVfiqO7fINl6er5jeatNVbeYZ84Ts7wg7Z6r7sZu92vg1COPXA0e9W+E8cXz42hPrJUYw9dzcH1QX0oDHUTybkqWkuNw7PdHH1Dxd3OWv/Uo7g6mqaVjhXcvssndq/n0NYVzOPx8znXM2jrEmh/iOSrbgnVugX6kU5bC3EzmGhOCPU91JA5qr6IGjBFZ2dehVnWtaL9flBZuDnrMk8m/YzrRAVh+LVs61J35LUue920/+NqXIVdvKZxrKJz7sYXC/MfBEZGRkZGRkZGRkZGRkZGRkZGRkb/N/0Lo92VZbHxh60AAAAASUVORK5CYII=';
+</script>
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 0000000000..4d4833c2ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/desktop-gl-constants.js
@@ -0,0 +1,2639 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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 0000000000..12a056ce21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js
@@ -0,0 +1,424 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+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) {
+ // loadShader, with opt_skipCompileStatus: true.
+ vShader = wtu.loadShader(gl, vSource, gl.VERTEX_SHADER, null, null, null, null, true);
+ let compiledVShader = vShader;
+ if (vShader && !gl.getShaderParameter(vShader, gl.COMPILE_STATUS)) {
+ compiledVShader = null;
+ }
+ if (info.vShaderTest) {
+ if (!info.vShaderTest(compiledVShader)) {
+ 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 && !compiledVShader) {
+ testFailed("[unexpected vertex shader compile status] (expected: " +
+ info.vShaderSuccess + ") " + passMsg);
+ if (!quietMode() && vShader) {
+ const info = gl.getShaderInfoLog(vShader);
+ wtu.addShaderSource(consoleDiv, vLabel + " info log", info);
+ }
+ }
+ // Save the shaders so we test shared shader.
+ if (compiledVShader) {
+ vShaderDB[vSource] = compiledVShader;
+ } else {
+ vShader = null;
+ }
+ }
+
+ 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) {
+ // loadShader, with opt_skipCompileStatus: true.
+ fShader = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER, null, null, null, null, true);
+ let compiledFShader = fShader;
+ if (fShader && !gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
+ compiledFShader = null;
+ }
+ if (info.fShaderTest) {
+ if (!info.fShaderTest(compiledFShader)) {
+ 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 && !compiledFShader) {
+ testFailed("[unexpected fragment shader compile status] (expected: " +
+ info.fShaderSuccess + ") " + passMsg);
+ if (!quietMode() && fShader) {
+ const info = gl.getShaderInfoLog(fShader);
+ wtu.addShaderSource(consoleDiv, fLabel + " info log", info);
+ }
+ return;
+ }
+
+ // Safe the shaders so we test shared shader.
+ if (compiledFShader) {
+ fShaderDB[fSource] = compiledFShader;
+ } else {
+ fShader = null;
+ }
+ }
+
+ 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] (expected: " +
+ info.linkSuccess + ") " + 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 uniform = info.uniforms[i];
+ var uniformLocation = gl.getUniformLocation(program, uniform.name);
+ if (uniformLocation !== null) {
+ if (uniform.functionName.includes("Matrix")) {
+ gl[uniform.functionName](uniformLocation, false, uniform.value);
+ } else {
+ gl[uniform.functionName](uniformLocation, uniform.value);
+ }
+ debug(uniform.name + ' set to ' + uniform.value);
+ } else {
+ debug('uniform ' + uniform.name + ' had null location and was not set');
+ }
+ }
+ }
+
+ if (info.uniformBlocks !== undefined) {
+ for (var i = 0; i < info.uniformBlocks.length; ++i) {
+ var uniformBlockIndex = gl.getUniformBlockIndex(program, info.uniformBlocks[i].name);
+ if (uniformBlockIndex !== null) {
+ gl.uniformBlockBinding(program, uniformBlockIndex, i);
+ debug(info.uniformBlocks[i].name + ' (index ' + uniformBlockIndex + ') bound to slot ' + i);
+
+ var uboValueBuffer = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, i, uboValueBuffer);
+ gl.bufferData(gl.UNIFORM_BUFFER, info.uniformBlocks[i].value, info.uniformBlocks[i].usage || gl.STATIC_DRAW);
+ } else {
+ debug('uniform block' + info.uniformBlocks[i].name + ' had null block index and was not set');
+ }
+ }
+ }
+
+ 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;
+ }
+ if (info.renderColor !== undefined) {
+ wtu.checkCanvas(gl, info.renderColor, "should be expected color " + info.renderColor, tolerance);
+ } else {
+ 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;
+ }
+
+ for (var i = 0; i < shaderInfos.length; i++) {
+ runOneTest(gl, shaderInfos[i]);
+ }
+
+ finishTest();
+};
+
+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 0000000000..b5c1602980
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-constructor-tests-generator.js
@@ -0,0 +1,919 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+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 0000000000..d0b65bcb4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-generator.js
@@ -0,0 +1,1234 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+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 0000000000..2b19b3b98f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/js-test-post.js
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+shouldBeTrue("successfullyParsed");
+_addSpan('<br /><span class="pass">TEST COMPLETE</span>');
+if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole('TEST COMPLETE');
+}
+
+{
+ const e_results = document.createElement('div');
+ let fails_class = 'pass';
+ if (RESULTS.fail) {
+ fails_class = 'fail';
+ } else {
+ const parseBoolean = v => v.toLowerCase().startsWith('t') || parseFloat(v) > 0;
+ const params = new URLSearchParams(window.location.search);
+ if (parseBoolean(params.get('runUntilFail') || '')) {
+ setTimeout(() => {
+ params.set('runCount', parseInt(params.get('runCount') || '0') + 1);
+ const url = new URL(window.location.href);
+ url.search = params.toString();
+ window.location.href = url.toString();
+ }, 100);
+ }
+ }
+ e_results.classList.add('pass');
+ e_results.innerHTML = `<p>TEST COMPLETE: ${RESULTS.pass} PASS, ` +
+ `<span class="${fails_class}">${RESULTS.fail} FAIL</span></p>`;
+
+ const e_desc = document.getElementById("description");
+ e_desc.appendChild(e_results);
+}
+
+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 0000000000..e1cb9f749c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/js-test-pre.js
@@ -0,0 +1,801 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+(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.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);
+ }
+
+ /* -- 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();
+ }
+}
+
+const RESULTS = {
+ pass: 0,
+ fail: 0,
+};
+
+function reportTestResultsToHarness(success, msg) {
+ if (success) {
+ RESULTS.pass += 1;
+ } else {
+ RESULTS.fail += 1;
+ }
+ 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._didNotifyFinishedToHarness) {
+ testFailed("Duplicate notifyFinishedToHarness()");
+ }
+ window._didNotifyFinishedToHarness = true;
+
+ 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 shouldBeString(evalable, expected) {
+ const val = eval(evalable);
+ const text = evalable + " should be " + expected + ".";
+ if (val == expected) {
+ testPassed(text);
+ } else {
+ testFailed(text + " (was " + val + ")");
+ }
+}
+
+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 maxArrayDiff(a, b) {
+ if (a.length != b.length)
+ throw new Error(`a and b have different lengths: ${a.length} vs ${b.length}`);
+
+ let diff = 0;
+ for (const i in a) {
+ diff = Math.max(diff, Math.abs(a[i] - b[i]));
+ }
+ return diff;
+}
+
+function expectArray(was, expected, maxDiff=0) {
+ const diff = maxArrayDiff(expected, was);
+ let str = `Expected [${expected.toString()}]`;
+ let fn = testPassed;
+ if (maxDiff) {
+ str += ' +/- ' + maxDiff;
+ }
+ if (diff > maxDiff) {
+ fn = testFailed;
+ str += `, was [${was.toString()}]`;
+ }
+ fn(str);
+}
+
+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 shouldNotThrow(evalStr, desc) {
+ desc = desc || `\`${evalStr}\``;
+ try {
+ eval(evalStr);
+ testPassed(`${desc} should not throw.`);
+ } catch (e) {
+ testFailed(`${desc} should not throw, but threw exception ${e}.`);
+ }
+}
+
+
+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;
+ }
+
+ // WebKit's MiniBrowser.
+ if (window.$vm) {
+ window.$vm.gc();
+ 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);
+}
+
+/// Prefer `call(() => { ... })` to `(() => { ... })()`\
+/// This way, it's clear up-front that we're calling not just defining.
+function call(fn) {
+ return fn();
+}
+
+/// `for (const i of range(3))` => 0, 1, 2
+/// Don't use `for...in range(n)`, it will not work.
+function* range(n) {
+ for (let i = 0; i < n; i++) {
+ yield i;
+ }
+}
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 0000000000..d2a9b99e08
--- /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 0000000000..113e9c6008
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/test-eval.js
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+/**
+ * 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/canvas-tests-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js
new file mode 100644
index 0000000000..7c30104379
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js
@@ -0,0 +1,825 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// Some variables that will be used in this file
+var canvas;
+var gl;
+var OES_vertex_array_object;
+var uniformLocation;
+var extension;
+var buffer;
+var framebuffer;
+var program;
+var renderbuffer;
+var shader;
+var texture;
+var arrayBuffer;
+var arrayBufferView;
+var vertexArrayObject;
+var imageData;
+var float32array;
+var int32array;
+
+var OES_texture_float;
+var new_WEBGL_lose_context;
+var allowRestore;
+var contextLostEventFired;
+var contextRestoredEventFired;
+var newExtension;
+
+function compareGLError(glError, evalStr) {
+ var exception;
+ try {
+ eval(evalStr);
+ } catch (e) {
+ exception = e;
+ }
+ if (exception) {
+ return false;
+ } else {
+ if (gl.getError() == glError)
+ return true;
+ return false;
+ }
+}
+
+function contextCreation(contextType) {
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext(contextType);
+
+ if (contextType == 'webgl') {
+ if (gl instanceof WebGLRenderingContext)
+ return true;
+ return false;
+ } else if (contextType == 'webgl2') {
+ if (gl instanceof WebGL2RenderingContext)
+ return true;
+ return false;
+ } else {
+ return false;
+ }
+}
+
+function transferredOffscreenCanvasCreation(placeholder, width, height) {
+ placeholder.width = width;
+ placeholder.height = height;
+ return placeholder.transferControlToOffscreen();
+}
+
+function assertWidthAndHeight(entity, entityName, width, height) {
+ if (entity.width == width && entity.height == height) {
+ testPassed("The width and height of " + entityName + " are correct.");
+ return;
+ }
+ var errMsg = "";
+ if (entity.width != width) {
+ errMsg += "The width of " + entityName + " is " + entity.width + " while expected value is " + width + ". ";
+ }
+ if (entity.height != height) {
+ errMsg += "The height of " + entityName + " is " + entity.height + " while expected value is " + height + ". ";
+ }
+ testFailed(errMsg);
+}
+
+var webgl1Methods = [
+ "getContextAttributes",
+ "activeTexture",
+ "attachShader",
+ "bindAttribLocation",
+ "bindBuffer",
+ "bindFramebuffer",
+ "bindRenderbuffer",
+ "bindTexture",
+ "blendColor",
+ "blendEquation",
+ "blendEquationSeparate",
+ "blendFunc",
+ "blendFuncSeparate",
+ "bufferData",
+ "bufferSubData",
+ "checkFramebufferStatus",
+ "clear",
+ "clearColor",
+ "clearDepth",
+ "clearStencil",
+ "colorMask",
+ "compileShader",
+ "compressedTexImage2D",
+ "compressedTexSubImage2D",
+ "copyTexImage2D",
+ "copyTexSubImage2D",
+ "createBuffer",
+ "createFramebuffer",
+ "createProgram",
+ "createRenderbuffer",
+ "createShader",
+ "createTexture",
+ "cullFace",
+ "deleteBuffer",
+ "deleteFramebuffer",
+ "deleteProgram",
+ "deleteRenderbuffer",
+ "deleteShader",
+ "deleteTexture",
+ "depthFunc",
+ "depthMask",
+ "depthRange",
+ "detachShader",
+ "disable",
+ "disableVertexAttribArray",
+ "drawArrays",
+ "drawElements",
+ "enable",
+ "enableVertexAttribArray",
+ "finish",
+ "flush",
+ "framebufferRenderbuffer",
+ "framebufferTexture2D",
+ "frontFace",
+ "generateMipmap",
+ "getActiveAttrib",
+ "getActiveUniform",
+ "getAttachedShaders",
+ "getAttribLocation",
+ "getParameter",
+ "getBufferParameter",
+ "getError",
+ "getExtension",
+ "getFramebufferAttachmentParameter",
+ "getProgramParameter",
+ "getProgramInfoLog",
+ "getRenderbufferParameter",
+ "getShaderParameter",
+ "getShaderInfoLog",
+ "getShaderPrecisionFormat",
+ "getShaderSource",
+ "getSupportedExtensions",
+ "getTexParameter",
+ "getUniform",
+ "getUniformLocation",
+ "getVertexAttrib",
+ "getVertexAttribOffset",
+ "hint",
+ "isBuffer",
+ "isContextLost",
+ "isEnabled",
+ "isFramebuffer",
+ "isProgram",
+ "isRenderbuffer",
+ "isShader",
+ "isTexture",
+ "lineWidth",
+ "linkProgram",
+ "pixelStorei",
+ "polygonOffset",
+ "readPixels",
+ "renderbufferStorage",
+ "sampleCoverage",
+ "scissor",
+ "shaderSource",
+ "stencilFunc",
+ "stencilFuncSeparate",
+ "stencilMask",
+ "stencilMaskSeparate",
+ "stencilOp",
+ "stencilOpSeparate",
+ "texImage2D",
+ "texParameterf",
+ "texParameteri",
+ "texSubImage2D",
+ "uniform1f",
+ "uniform1fv",
+ "uniform1i",
+ "uniform1iv",
+ "uniform2f",
+ "uniform2fv",
+ "uniform2i",
+ "uniform2iv",
+ "uniform3f",
+ "uniform3fv",
+ "uniform3i",
+ "uniform3iv",
+ "uniform4f",
+ "uniform4fv",
+ "uniform4i",
+ "uniform4iv",
+ "uniformMatrix2fv",
+ "uniformMatrix3fv",
+ "uniformMatrix4fv",
+ "useProgram",
+ "validateProgram",
+ "vertexAttrib1f",
+ "vertexAttrib1fv",
+ "vertexAttrib2f",
+ "vertexAttrib2fv",
+ "vertexAttrib3f",
+ "vertexAttrib3fv",
+ "vertexAttrib4f",
+ "vertexAttrib4fv",
+ "vertexAttribPointer",
+ "viewport",
+];
+
+var webgl2Methods = [
+ "getBufferSubData",
+ "copyBufferSubData",
+ "blitFramebuffer",
+ "framebufferTextureLayer",
+ "getInternalformatParameter",
+ "invalidateFramebuffer",
+ "invalidateSubFramebuffer",
+ "readBuffer",
+ "renderbufferStorageMultisample",
+ "texImage3D",
+ "texStorage2D",
+ "texStorage3D",
+ "texSubImage3D",
+ "copyTexSubImage3D",
+ "compressedTexImage3D",
+ "compressedTexSubImage3D",
+ "getFragDataLocation",
+ "uniform1ui",
+ "uniform2ui",
+ "uniform3ui",
+ "uniform4ui",
+ "uniform1uiv",
+ "uniform2uiv",
+ "uniform3uiv",
+ "uniform4uiv",
+ "uniformMatrix2x3fv",
+ "uniformMatrix3x2fv",
+ "uniformMatrix2x4fv",
+ "uniformMatrix4x2fv",
+ "uniformMatrix3x4fv",
+ "uniformMatrix4x3fv",
+ "vertexAttribI4i",
+ "vertexAttribI4iv",
+ "vertexAttribI4ui",
+ "vertexAttribI4uiv",
+ "vertexAttribIPointer",
+ "vertexAttribDivisor",
+ "drawArraysInstanced",
+ "drawElementsInstanced",
+ "drawRangeElements",
+ "drawBuffers",
+ "clearBufferiv",
+ "clearBufferuiv",
+ "clearBufferfv",
+ "clearBufferfi",
+ "createQuery",
+ "deleteQuery",
+ "isQuery",
+ "beginQuery",
+ "endQuery",
+ "getQuery",
+ "getQueryParameter",
+ "createSampler",
+ "deleteSampler",
+ "isSampler",
+ "bindSampler",
+ "samplerParameteri",
+ "samplerParameterf",
+ "getSamplerParameter",
+ "fenceSync",
+ "isSync",
+ "deleteSync",
+ "clientWaitSync",
+ "waitSync",
+ "getSyncParameter",
+ "createTransformFeedback",
+ "deleteTransformFeedback",
+ "isTransformFeedback",
+ "bindTransformFeedback",
+ "beginTransformFeedback",
+ "endTransformFeedback",
+ "transformFeedbackVaryings",
+ "getTransformFeedbackVarying",
+ "pauseTransformFeedback",
+ "resumeTransformFeedback",
+ "bindBufferBase",
+ "bindBufferRange",
+ "getIndexedParameter",
+ "getUniformIndices",
+ "getActiveUniforms",
+ "getUniformBlockIndex",
+ "getActiveUniformBlockParameter",
+ "getActiveUniformBlockName",
+ "uniformBlockBinding",
+ "createVertexArray",
+ "deleteVertexArray",
+ "isVertexArray",
+ "bindVertexArray",
+];
+
+function assertFunction(v, f) {
+ try {
+ if (typeof v[f] != "function") {
+ return false;
+ } else {
+ return true;
+ }
+ } catch(e) {
+ return false;
+ }
+}
+
+function testAPIs(contextType) {
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext(contextType);
+ var passed = true;
+ var methods;
+ if (contextType == 'webgl')
+ methods = webgl1Methods;
+ else
+ methods = webgl1Methods.concat(webgl2Methods);
+ for (var i=0; i<methods.length; i++) {
+ var r = assertFunction(gl, methods[i]);
+ passed = passed && r;
+ }
+
+ methods.push(...["makeXRCompatible"]);
+ var extended = false;
+ for (var i in gl) {
+ if (typeof gl[i] == "function" && methods.indexOf(i) == -1) {
+ if (!extended) {
+ extended = true;
+ }
+ }
+ }
+
+ if (!passed || extended)
+ return false;
+ return true;
+}
+
+var simpleTextureVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'attribute vec2 texCoord0;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' texCoord = texCoord0;',
+ '}'].join('\n');
+
+var simpleTextureFragmentShader = [
+ 'precision mediump float;',
+ 'uniform sampler2D tex;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_FragData[0] = texture2D(tex, texCoord);',
+ '}'].join('\n');
+
+function getShader(gl, shaderStr, type)
+{
+ var shader = gl.createShader(type);
+ gl.shaderSource(shader, shaderStr);
+ gl.compileShader(shader);
+
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
+ return null;
+ return shader;
+}
+
+function setupProgram(gl, shaders, opt_attribs, opt_locations)
+{
+ var vertexShader = getShader(gl, simpleTextureVertexShader, gl.VERTEX_SHADER);
+ var fragmentShader = getShader(gl, simpleTextureFragmentShader, gl.FRAGMENT_SHADER);
+ var program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+
+ 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
+ gl.deleteProgram(program);
+ return null;
+ }
+ gl.useProgram(program);
+ return program;
+}
+
+function setupSimpleTextureProgram(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]);
+}
+
+function testLostContextWithoutRestore()
+{
+ // Functions with special return values.
+ if (!gl.isContextLost())
+ return false;
+
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_UNSUPPORTED ||
+ gl.getAttribLocation(program, 'u_modelViewProjMatrix') != -1 ||
+ gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER) != 0)
+ return false;
+
+ // Test the extension itself.
+ if (!compareGLError(gl.INVALID_OPERATION, "extension.loseContext()"))
+ return false;
+
+ imageData = new ImageData(1, 1);
+ float32array = new Float32Array(1);
+ int32array = new Int32Array(1);
+
+ // Functions returning void should return immediately.
+ // This is untestable, but we can at least be sure they cause no errors
+ // and the codepaths are exercised.
+ if (!compareGLError(gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.attachShader(program, shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, texture)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendColor(1.0, 1.0, 1.0, 1.0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendEquation(gl.FUNC_ADD)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.ONE, gl.ONE)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clearColor(1, 1, 1, 1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clearDepth(1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clearStencil(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.colorMask(1, 1, 1, 1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.compileShader(shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.cullFace(gl.FRONT)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteBuffer(buffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteFramebuffer(framebuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteRenderbuffer(renderbuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteShader(shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteTexture(texture)") ||
+ !compareGLError(gl.NO_ERROR, "gl.depthFunc(gl.NEVER)") ||
+ !compareGLError(gl.NO_ERROR, "gl.depthMask(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.depthRange(0, 1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.detachShader(program, shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.disable(gl.BLEND)") ||
+ !compareGLError(gl.NO_ERROR, "gl.disableVertexAttribArray(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.drawArrays(gl.POINTS, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.enable(gl.BLEND)") ||
+ !compareGLError(gl.NO_ERROR, "gl.enableVertexAttribArray(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.finish()") ||
+ !compareGLError(gl.NO_ERROR, "gl.flush()") ||
+ !compareGLError(gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.frontFace(gl.CW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.generateMipmap(gl.TEXTURE_2D)") ||
+ !compareGLError(gl.NO_ERROR, "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)") ||
+ !compareGLError(gl.NO_ERROR, "gl.lineWidth(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.linkProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.polygonOffset(0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.sampleCoverage(0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.scissor(0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.shaderSource(shader, '')") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilFunc(gl.NEVER, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilMask(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilMaskSeparate(gl.FRONT, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1f(uniformLocation, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1fv(uniformLocation, [0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1i(uniformLocation, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1iv(uniformLocation, [0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2f(uniformLocation, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2fv(uniformLocation, [0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2i(uniformLocation, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2iv(uniformLocation, [0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3f(uniformLocation, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3fv(uniformLocation, [0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3i(uniformLocation, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3iv(uniformLocation, [0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4f(uniformLocation, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4i(uniformLocation, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix2fv(uniformLocation, false, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix3fv(uniformLocation, false, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix4fv(uniformLocation, false, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.useProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.validateProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1f(0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1fv(0, [0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2f(0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2fv(0, [0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3f(0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3fv(0, [0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4f(0, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4fv(0, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.viewport(0, 0, 0, 0)"))
+ return false;
+
+ // Functions return nullable values should all return null.
+ if (gl.createBuffer() != null ||
+ gl.createFramebuffer() != null ||
+ gl.createProgram() != null ||
+ gl.createRenderbuffer() != null ||
+ gl.createShader(gl.GL_VERTEX_SHADER) != null ||
+ gl.createTexture() != null ||
+ gl.getActiveAttrib(program, 0) != null ||
+ gl.getActiveUniform(program, 0) != null ||
+ gl.getAttachedShaders(program) != null ||
+ gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE) != null ||
+ gl.getContextAttributes() != null ||
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) != null ||
+ gl.getParameter(gl.CURRENT_PROGRAM) != null ||
+ gl.getProgramInfoLog(program) != null ||
+ gl.getProgramParameter(program, gl.LINK_STATUS) != null ||
+ gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) != null ||
+ gl.getShaderInfoLog(shader) != null ||
+ gl.getShaderParameter(shader, gl.SHADER_TYPE) != null ||
+ gl.getShaderSource(shader) != null ||
+ gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S) != null ||
+ gl.getUniform(program, uniformLocation) != null ||
+ gl.getUniformLocation(program, 'vPosition') != null ||
+ gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) != null ||
+ gl.getSupportedExtensions() != null ||
+ gl.getExtension("WEBGL_lose_context") != null)
+ return false;
+
+ // "Is" queries should all return false.
+ if (gl.isBuffer(buffer) || gl.isEnabled(gl.BLEND) || gl.isFramebuffer(framebuffer) ||
+ gl.isProgram(program) || gl.isRenderbuffer(renderbuffer) || gl.isShader(shader) ||
+ gl.isTexture(texture))
+ return false;
+
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ // test extensions
+ if (OES_vertex_array_object) {
+ if (!compareGLError(gl.NO_ERROR, "OES_vertex_array_object.bindVertexArrayOES(vertexArrayObject)") ||
+ !compareGLError(gl.NO_ERROR, "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)") ||
+ !compareGLError(gl.NO_ERROR, "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)"))
+ return false;
+ if (OES_vertex_array_object.createVertexArrayOES() != null)
+ return false;
+ }
+ return true;
+}
+function testValidContext()
+{
+ if (gl.isContextLost())
+ return false;
+
+ arrayBuffer = new ArrayBuffer(4);
+ arrayBufferView = new Int8Array(arrayBuffer);
+
+ // Generate resources for testing.
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ program = setupSimpleTextureProgram(gl);
+ renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ shader = gl.createShader(gl.VERTEX_SHADER);
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ // Test is queries that will later be false
+ if (!compareGLError(gl.NO_ERROR, "gl.enable(gl.BLEND)"))
+ return false;
+ if (!gl.isBuffer(buffer) || !gl.isEnabled(gl.BLEND) || !gl.isFramebuffer(framebuffer) ||
+ !gl.isProgram(program) || !gl.isRenderbuffer(renderbuffer) || !gl.isShader(shader) ||
+ !gl.isTexture(texture))
+ return false;
+
+ if (OES_vertex_array_object) {
+ vertexArrayObject = OES_vertex_array_object.createVertexArrayOES();
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ if (!OES_vertex_array_object.isVertexArrayOES(vertexArrayObject))
+ return false;
+ }
+ return true;
+}
+
+function setupTest()
+{
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext('webgl');
+ WEBGL_lose_context = gl.getExtension("WEBGL_lose_context");
+ if (!WEBGL_lose_context)
+ return false;
+
+ // Try to get a few extensions
+ OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
+ OES_texture_float = gl.getExtension("OES_texture_float");
+
+ return true;
+}
+
+function testOriginalContext()
+{
+ if (gl.isContextLost())
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ return true;
+}
+
+function testLostContext(e)
+{
+ if (contextLostEventFired)
+ return false;
+ contextLostEventFired = true;
+ if (!gl.isContextLost())
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ if (allowRestore)
+ e.preventDefault();
+ return true;
+}
+
+function testLosingAndRestoringContext()
+{
+ return new Promise(function(resolve, reject) {
+ if (!setupTest())
+ reject("Test failed");
+
+ canvas.addEventListener("webglcontextlost", function(e) {
+ if (!testLostContext(e))
+ reject("Test failed");
+ // restore the context after this event has exited.
+ setTimeout(function() {
+ if (!compareGLError(gl.NO_ERROR, "WEBGL_lose_context.restoreContext()"))
+ reject("Test failed");
+ // The context should still be lost. It will not get restored until the
+ // webglrestorecontext event is fired.
+ if (!gl.isContextLost())
+ reject("Test failed");
+ if (gl.getError() != gl.NO_ERROR)
+ reject("Test failed");
+ // gl methods should still be no-ops
+ if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
+ reject("Test failed");
+ }, 0);
+ });
+ canvas.addEventListener("webglcontextrestored", function() {
+ if (!testRestoredContext())
+ reject("Test failed");
+ else
+ resolve("Test passed");
+ });
+ allowRestore = true;
+ contextLostEventFired = false;
+ contextRestoredEventFired = false;
+
+ if (!testOriginalContext())
+ reject("Test failed");
+ WEBGL_lose_context.loseContext();
+ // The context should be lost immediately.
+ if (!gl.isContextLost())
+ reject("Test failed");
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
+ reject("Test failed");
+ if (gl.getError() != gl.NO_ERROR)
+ reject("Test failed");
+ // gl methods should be no-ops
+ if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
+ reject("Test failed");
+ // but the event should not have been fired.
+ if (contextLostEventFired)
+ reject("Test failed");
+ });
+}
+
+function reGetExtensionAndTestForProperty(gl, name, expectProperty) {
+ var newExtension = gl.getExtension(name);
+ // NOTE: while getting a extension after context lost/restored is allowed to fail
+ // for the purpose the conformance tests it is not.
+ //
+ // Hypothetically the user can switch GPUs live. For example on Windows, install 2 GPUs,
+ // then in the control panen enable 1, disable the others and visa versa. Since the GPUs
+ // have different capabilities one or the other may not support a particlar extension.
+ //
+ // But, for the purpose of the conformance tests the context is expected to restore
+ // on the same GPU and therefore the extensions that succeeded previously should
+ // succeed on restore.
+ if (newExtension == null)
+ return false;
+ if (expectProperty) {
+ if (!(newExtension.webglTestProperty === true))
+ return false;
+ } else {
+ if (!(newExtension.webglTestProperty === undefined))
+ return false;
+ }
+ return newExtension;
+}
+
+
+function testOESTextureFloat() {
+ if (OES_texture_float) {
+ // Extension must still be lost.
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ if (!compareGLError(gl.INVALID_ENUM, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"))
+ return false;
+ // Try re-enabling extension
+ OES_texture_float = reGetExtensionAndTestForProperty(gl, "OES_texture_float", false);
+ if (!compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"))
+ return false;
+ return true;
+ }
+}
+
+function testOESVertexArrayObject() {
+ if (OES_vertex_array_object) {
+ // Extension must still be lost.
+ if (OES_vertex_array_object.createVertexArrayOES() != null)
+ return false;
+ // Try re-enabling extension
+
+ var old_OES_vertex_array_object = OES_vertex_array_object;
+ OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false);
+ if (OES_vertex_array_object.createVertexArrayOES() == null)
+ return false;
+ if (old_OES_vertex_array_object.createVertexArrayOES() != null)
+ return false;
+ return true;
+ }
+}
+
+function testExtensions() {
+ if (!testOESTextureFloat() || !testOESVertexArrayObject())
+ return false;
+ return true;
+}
+
+function testRestoredContext()
+{
+ if (contextRestoredEventFired)
+ return false;
+ contextRestoredEventFired = true;
+ if (gl.isContextLost())
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ if (!testExtensions())
+ return false;
+ return true;
+}
+
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 0000000000..6b8fc00599
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js
@@ -0,0 +1,92 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+'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/compositing-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/compositing-test.js
new file mode 100644
index 0000000000..ceccbc406e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/compositing-test.js
@@ -0,0 +1,136 @@
+var createCompositingTestFn = (function() {
+
+const width = 20;
+const height = 20;
+
+function waitForComposite() {
+ debug('wait for composite');
+ return new Promise(resolve => wtu.waitForComposite(resolve));
+}
+
+async function testPreserveDrawingBufferFalse(gl, drawFn, clear) {
+ debug('');
+ debug(`test preserveDrawingBuffer: false with ${drawFn.name} ${clear ? 'with' : 'without'} clear`);
+
+ if (clear) {
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+
+ if (drawFn(gl)) {
+ debug('skipped: extension does not exist');
+ return;
+ }
+
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "canvas should be red");
+
+ // enable scissor here, before compositing, to make sure it's correctly
+ // ignored and restored
+ const halfWidth = gl.canvas.width / 2;
+ const halfHeight = gl.canvas.height / 2;
+ gl.scissor(0, halfHeight, halfWidth, halfHeight);
+ gl.enable(gl.SCISSOR_TEST);
+
+ await waitForComposite();
+
+ // scissor was set earlier
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.checkCanvasRect(gl, 0, halfHeight, halfWidth, halfHeight, [0, 0, 255, 255],
+ "cleared corner should be blue, stencil should be preserved");
+ wtu.checkCanvasRect(gl, 0, 0, halfWidth, halfHeight, [0, 0, 0, 0],
+ "remainder of buffer should be cleared");
+
+ gl.disable(gl.SCISSOR_TEST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+async function testPreserveDrawingBufferTrue(gl, drawFn, clear) {
+ debug('');
+ debug(`test preserveDrawingBuffer: true with ${drawFn.name} ${clear ? 'with' : 'without'} clear`);
+
+ if (clear) {
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+
+ const skipTest = drawFn(gl);
+ if (skipTest) {
+ debug('skipped: extension does not exist');
+ return;
+ }
+
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "canvas should be red");
+
+ await waitForComposite();
+
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "canvas should be red");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function setupWebGL({
+ webglVersion,
+ shadersFn,
+ attribs,
+}) {
+ const existingCanvases = document.querySelectorAll('canvas');
+ const canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ canvas.style.display = 'block';
+ canvas.style.position = 'fixed';
+ canvas.style.left = `${existingCanvases.length * 25}px`;
+ canvas.style.top = '0';
+ // The canvas needs to be visible or the test will fail.
+ document.body.insertBefore(canvas, [...existingCanvases].pop());
+ const gl = wtu.create3DContext(canvas, attribs, webglVersion);
+ if (!gl) {
+ testFailed('WebGL context creation failed');
+ return gl;
+ }
+
+ const shaders = shadersFn(gl);
+ const program = wtu.setupProgram(gl, shaders, ["position"]);
+ if (!program) {
+ debug(`program failed to compile: ${wtu.getLastError()}`);
+ }
+ const positionBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ -1, 1,
+ 1, -1,
+ 1, 1,
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ const indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3, 4, 5]), gl.STATIC_DRAW);
+ return gl;
+}
+
+function createCompositingTestFn(options) {
+ const glPreserveDrawingBufferFalse = setupWebGL({
+ ...options,
+ attribs: {antialias: false},
+ });
+ const glPreserveDrawingBufferTrue = setupWebGL({
+ ...options,
+ attribs: {antialias: false, preserveDrawingBuffer: true},
+ });
+ return async function(drawFn) {
+ debug('---');
+ await testPreserveDrawingBufferFalse(glPreserveDrawingBufferFalse, drawFn, false);
+ await testPreserveDrawingBufferFalse(glPreserveDrawingBufferFalse, drawFn, true);
+
+ await testPreserveDrawingBufferTrue(glPreserveDrawingBufferTrue, drawFn, false);
+ await testPreserveDrawingBufferTrue(glPreserveDrawingBufferTrue, drawFn, true);
+ };
+}
+
+return createCompositingTestFn;
+}());
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 0000000000..41a49bced4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+'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/compressed-tex-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/compressed-tex-image.js
new file mode 100644
index 0000000000..7886181f4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/compressed-tex-image.js
@@ -0,0 +1,138 @@
+"use strict";
+description("This test ensures WebGL implementations correctly implement querying for compressed textures when extensions are disabled.");
+
+debug("");
+
+const wtu = WebGLTestUtils;
+const gl = wtu.create3DContext(null, undefined, contextVersion);
+
+const COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
+const COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
+
+let formats = null;
+let ext;
+
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION],
+ "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, new Uint8Array(8));");
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)");
+ shouldBeNonNull("formats");
+ shouldBe("formats.length", "0");
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4*4*4));");
+ wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, new Uint8Array(8));");
+
+ // Check too-many and too-few args.
+
+ wtu.shouldThrow(gl, false, "too many args", function() {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 0, new Uint8Array(8), null);
+ });
+ wtu.shouldThrow(gl, TypeError, "too few args", function() {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 0);
+ });
+
+ wtu.shouldThrow(gl, false, "too many args", function() {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, new Uint8Array(8), null);
+ });
+ wtu.shouldThrow(gl, TypeError, "too few args", function() {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_RGB_PVRTC_4BPPV1_IMG);
+ });
+
+ // -
+
+ let pbo;
+ // WebGL 2.0 specific
+ if (gl.PIXEL_UNPACK_BUFFER) {
+ pbo = gl.createBuffer();
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ function validateExt(extName, enumName, blockSize, blockByteSize, expectedSubImageError) {
+ debug('\n---------------------------');
+ debug('\n' + extName);
+ ext = gl.getExtension(extName);
+ if (!ext) {
+ testPassed(`Optional ext ${extName} MAY be unsupported.`);
+ return;
+ }
+ testPassed(`Optional ext ${extName} is supported.`);
+
+ const data = new Uint8Array(blockByteSize);
+
+ const views = [
+ data,
+ new Uint8ClampedArray(data.buffer),
+ new Int8Array(data.buffer),
+ new Uint16Array(data.buffer),
+ new Int16Array(data.buffer),
+ new Uint32Array(data.buffer),
+ new Int32Array(data.buffer),
+ new Float32Array(data.buffer),
+ new DataView(data.buffer),
+ ];
+ if (window.SharedArrayBuffer) {
+ const sharedBuffer = new SharedArrayBuffer(blockByteSize);
+ views.push(
+ new Uint8Array(sharedBuffer),
+ new Uint8ClampedArray(sharedBuffer),
+ new DataView(sharedBuffer)
+ );
+ }
+
+ for (const view of views) {
+ window.g_view = view;
+ debug(`\nfrom ${view.constructor.name} of ${view.buffer.constructor.name}`);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ `gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, g_view)`);
+
+ wtu.shouldGenerateGLError(gl, expectedSubImageError,
+ `gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, g_view)`);
+ }
+
+ if (pbo) {
+ debug('\nfrom PBO');
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ `gl.bufferData(gl.PIXEL_UNPACK_BUFFER, ${blockByteSize}*2, gl.STATIC_DRAW)`);
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ `gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, 0)`);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ `gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, 1)`);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ `gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, ${blockByteSize})`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ `gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, ${blockByteSize+1})`);
+
+ wtu.shouldGenerateGLError(gl, expectedSubImageError,
+ `gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, 0)`);
+ wtu.shouldGenerateGLError(gl, expectedSubImageError,
+ `gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, 1)`);
+ wtu.shouldGenerateGLError(gl, expectedSubImageError,
+ `gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, ${blockByteSize})`);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ `gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, ${blockByteSize+1})`);
+
+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
+ }
+ }
+
+ validateExt('WEBGL_compressed_texture_s3tc', 'COMPRESSED_RGBA_S3TC_DXT5_EXT', 4, 16, gl.NO_ERROR);
+ validateExt('WEBGL_compressed_texture_etc1', 'COMPRESSED_RGB_ETC1_WEBGL', 4, 8, gl.INVALID_OPERATION);
+ validateExt('WEBGL_compressed_texture_etc', 'COMPRESSED_RGBA8_ETC2_EAC', 4, 16, gl.NO_ERROR);
+ validateExt('WEBGL_compressed_texture_astc', 'COMPRESSED_RGBA_ASTC_4x4_KHR', 4, 16, gl.NO_ERROR);
+}
+
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/compressed-texture-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/compressed-texture-utils.js
new file mode 100644
index 0000000000..46d155f5f1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/compressed-texture-utils.js
@@ -0,0 +1,258 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+"use strict";
+
+let CompressedTextureUtils = (function() {
+
+let formatToString = function(ext, format) {
+ for (let p in ext) {
+ if (ext[p] == format) {
+ return p;
+ }
+ }
+ return "0x" + format.toString(16);
+};
+
+/**
+ * Make an image element from Uint8Array bitmap data.
+ * @param {number} imageHeight Height of the data in pixels.
+ * @param {number} imageWidth Width of the data in pixels.
+ * @param {number} dataWidth Width of each row in the data buffer, in pixels.
+ * @param {Uint8Array} data Image data buffer to display. Each pixel takes up 4 bytes in the array regardless of the alpha parameter.
+ * @param {boolean} alpha True if alpha data should be taken from data. Otherwise alpha channel is set to 255.
+ * @return {HTMLImageElement} The image element.
+ */
+let makeScaledImage = function(imageWidth, imageHeight, dataWidth, data, alpha, opt_scale) {
+ let scale = opt_scale ? opt_scale : 8;
+ let c = document.createElement("canvas");
+ c.width = imageWidth * scale;
+ c.height = imageHeight * scale;
+ let ctx = c.getContext("2d");
+ for (let yy = 0; yy < imageHeight; ++yy) {
+ for (let xx = 0; xx < imageWidth; ++xx) {
+ let offset = (yy * dataWidth + xx) * 4;
+ ctx.fillStyle = "rgba(" +
+ data[offset + 0] + "," +
+ data[offset + 1] + "," +
+ data[offset + 2] + "," +
+ (alpha ? data[offset + 3] / 255 : 1) + ")";
+ ctx.fillRect(xx * scale, yy * scale, scale, scale);
+ }
+ }
+ return wtu.makeImageFromCanvas(c);
+};
+
+let insertCaptionedImg = function(parent, caption, img) {
+ let div = document.createElement("div");
+ div.appendChild(img);
+ let label = document.createElement("div");
+ label.appendChild(document.createTextNode(caption));
+ div.appendChild(label);
+ parent.appendChild(div);
+};
+
+/**
+ * @param {WebGLRenderingContextBase} gl
+ * @param {Object} compressedFormats Mapping from format names to format enum values.
+ * @param expectedByteLength A function that takes in width, height and format and returns the expected buffer size in bytes.
+ */
+let testCompressedFormatsUnavailableWhenExtensionDisabled = function(gl, compressedFormats, expectedByteLength, testSize) {
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ for (let name in compressedFormats) {
+ if (compressedFormats.hasOwnProperty(name)) {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, compressedFormats[name], testSize, testSize, 0, new Uint8Array(expectedByteLength(testSize, testSize, compressedFormats[name])));
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Trying to use format " + name + " with extension disabled.");
+ }
+ }
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+};
+
+/**
+ * @param {WebGLRenderingContextBase} gl
+ * @param {Object} expectedFormats Mapping from format names to format enum values.
+ */
+let testCompressedFormatsListed = function(gl, expectedFormats) {
+ debug("");
+ debug("Testing that every format is listed by the compressed texture formats query");
+
+ let supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
+
+ let failed;
+ let count = 0;
+ for (let name in expectedFormats) {
+ if (expectedFormats.hasOwnProperty(name)) {
+ ++count;
+ let format = expectedFormats[name];
+ failed = true;
+ for (let ii = 0; ii < supportedFormats.length; ++ii) {
+ if (format == supportedFormats[ii]) {
+ testPassed("supported format " + name + " exists");
+ failed = false;
+ break;
+ }
+ }
+ if (failed) {
+ testFailed("supported format " + name + " does not exist");
+ }
+ }
+ }
+ if (supportedFormats.length != count) {
+ testFailed("Incorrect number of supported formats, was " + supportedFormats.length + " should be " + count);
+ }
+};
+
+/**
+ * @param {Object} ext Compressed texture extension object.
+ * @param {Object} expectedFormats Mapping from format names to format enum values.
+ */
+let testCorrectEnumValuesInExt = function(ext, expectedFormats) {
+ debug("");
+ debug("Testing that format enum values in the extension object are correct");
+
+ for (name in expectedFormats) {
+ if (expectedFormats.hasOwnProperty(name)) {
+ if (isResultCorrect(ext[name], expectedFormats[name])) {
+ testPassed("Enum value for " + name + " matches 0x" + ext[name].toString(16));
+ } else {
+ testFailed("Enum value for " + name + " mismatch: 0x" + ext[name].toString(16) + " should be 0x" + expectedFormats[name].toString(16));
+ }
+ }
+ }
+};
+
+/**
+ * @param {WebGLRenderingContextBase} gl
+ * @param {Object} validFormats Mapping from format names to format enum values.
+ * @param expectedByteLength A function that takes in width, height and format and returns the expected buffer size in bytes.
+ * @param getBlockDimensions A function that takes in a format and returns block size in pixels.
+ */
+let testFormatRestrictionsOnBufferSize = function(gl, validFormats, expectedByteLength, getBlockDimensions) {
+ debug("");
+ debug("Testing format restrictions on texture upload buffer size");
+
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ for (let formatId in validFormats) {
+ if (validFormats.hasOwnProperty(formatId)) {
+ let format = validFormats[formatId];
+ let blockSize = getBlockDimensions(format);
+ let expectedSize = expectedByteLength(blockSize.width * 4, blockSize.height * 4, format);
+ let data = new Uint8Array(expectedSize);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 3, blockSize.height * 4, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too small width)");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 5, blockSize.height * 4, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too large width)");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 4, blockSize.height * 3, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too small height)");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 4, blockSize.height * 5, 0, data);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too large height)");
+ }
+ }
+};
+
+/**
+ * @param {WebGLRenderingContextBase} gl
+ * @param {Object} validFormats Mapping from format names to format enum values.
+ * @param expectedByteLength A function that takes in width, height and format and returns the expected buffer size in bytes.
+ * @param getBlockDimensions A function that takes in a format and returns block size in pixels.
+ * @param {number} width Width of the image in pixels.
+ * @param {number} height Height of the image in pixels.
+ * @param {Object} subImageConfigs configs for compressedTexSubImage calls
+ */
+let testTexSubImageDimensions = function(gl, ext, validFormats, expectedByteLength, getBlockDimensions, width, height, subImageConfigs) {
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ for (let formatId in validFormats) {
+ if (validFormats.hasOwnProperty(formatId)) {
+ let format = validFormats[formatId];
+ let blockSize = getBlockDimensions(format);
+ debug("testing " + ctu.formatToString(ext, format));
+ let expectedSize = expectedByteLength(width, height, format);
+ let data = new Uint8Array(expectedSize);
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setting up compressed texture");
+
+ for (let i = 0, len = subImageConfigs.length; i < len; ++i) {
+ let c = subImageConfigs[i];
+ let subData = new Uint8Array(expectedByteLength(c.width, c.height, format));
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, c.xoffset, c.yoffset, c.width, c.height, format, subData);
+ wtu.glErrorShouldBe(gl, c.expectation, c.message);
+ }
+ }
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+};
+
+let testTexImageLevelDimensions = function(gl, ext, validFormats, expectedByteLength, getBlockDimensions, imageConfigs) {
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ for (let formatId in validFormats) {
+ if (validFormats.hasOwnProperty(formatId)) {
+ let format = validFormats[formatId];
+ let blockSize = getBlockDimensions(format);
+ debug("testing " + ctu.formatToString(ext, format));
+
+ for (let i = 0, len = imageConfigs.length; i < len; ++i) {
+ let c = imageConfigs[i];
+ let data = new Uint8Array(expectedByteLength(c.width, c.height, format));
+ gl.compressedTexImage2D(gl.TEXTURE_2D, c.level, format, c.width, c.height, 0, data);
+ wtu.glErrorShouldBe(gl, c.expectation, c.message);
+ }
+ }
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+}
+
+let testTexStorageLevelDimensions = function(gl, ext, validFormats, expectedByteLength, getBlockDimensions, imageConfigs) {
+ for (let formatId in validFormats) {
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ if (validFormats.hasOwnProperty(formatId)) {
+ let format = validFormats[formatId];
+ let blockSize = getBlockDimensions(format);
+ debug("testing " + ctu.formatToString(ext, format));
+
+ for (let i = 0, len = imageConfigs.length; i < len; ++i) {
+ let c = imageConfigs[i];
+ let data = new Uint8Array(expectedByteLength(c.width, c.height, format));
+ if (i == 0) {
+ gl.texStorage2D(gl.TEXTURE_2D, imageConfigs.length, format, c.width, c.height);
+ wtu.glErrorShouldBe(gl, c.expectation, c.message);
+ }
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, i, 0, 0, c.width, c.height, format, data);
+ wtu.glErrorShouldBe(gl, c.expectation, c.message);
+ }
+ }
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(tex);
+ }
+}
+
+return {
+ formatToString: formatToString,
+ insertCaptionedImg: insertCaptionedImg,
+ makeScaledImage: makeScaledImage,
+ testCompressedFormatsListed: testCompressedFormatsListed,
+ testCompressedFormatsUnavailableWhenExtensionDisabled: testCompressedFormatsUnavailableWhenExtensionDisabled,
+ testCorrectEnumValuesInExt: testCorrectEnumValuesInExt,
+ testFormatRestrictionsOnBufferSize: testFormatRestrictionsOnBufferSize,
+ testTexSubImageDimensions: testTexSubImageDimensions,
+ testTexImageLevelDimensions: testTexImageLevelDimensions,
+ testTexStorageLevelDimensions: testTexStorageLevelDimensions,
+};
+
+})(); \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/context-methods.js b/dom/canvas/test/webgl-conf/checkout/js/tests/context-methods.js
new file mode 100644
index 0000000000..f6476463d2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/context-methods.js
@@ -0,0 +1,52 @@
+"use strict";
+
+// Properties to be ignored because they were added in versions of the
+// spec that are backward-compatible with this version
+const IGNORED_METHODS = [
+ // There is no official spec for the commit API yet, the proposal link is:
+ // https://wiki.whatwg.org/wiki/OffscreenCanvas
+ "commit",
+
+ // For WebXR integration:
+ "makeXRCompatible",
+];
+
+function assertFunction(v, f) {
+ try {
+ if (typeof v[f] != "function") {
+ testFailed(`Property either does not exist or is not a function: ${f}`);
+ return false;
+ } else {
+ return true;
+ }
+ } catch(e) {
+ testFailed(`Trying to access the property '${f}' threw an error: ${e.toString()}`);
+ }
+}
+
+function testContextMethods(gl, requiredContextMethods) {
+ const acceptableMethods = [].concat(requiredContextMethods, IGNORED_METHODS);
+
+ let passed = true;
+ requiredContextMethods.forEach(method => {
+ const r = assertFunction(gl, method);
+ passed = passed && r;
+ });
+ if (passed) {
+ testPassed("All WebGL methods found.");
+ }
+ let extended = false;
+ for (let propertyName of Object.getOwnPropertyNames(gl)) {
+ if (typeof gl[propertyName] == "function" && !acceptableMethods.includes(propertyName)) {
+ if (!extended) {
+ extended = true;
+ testFailed("Also found the following extra methods:");
+ }
+ testFailed(propertyName);
+ }
+ }
+
+ if (!extended) {
+ testPassed("No extra methods found on WebGL context.");
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/ext-color-buffer-half-float.js b/dom/canvas/test/webgl-conf/checkout/js/tests/ext-color-buffer-half-float.js
new file mode 100644
index 0000000000..51509e8a6e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/ext-color-buffer-half-float.js
@@ -0,0 +1,473 @@
+"use strict";
+
+function allocateTexture()
+{
+ 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);
+ 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);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
+ return texture;
+}
+
+function checkRenderingResults()
+{
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+}
+
+function arrayToString(arr, size) {
+ var mySize;
+ if (!size)
+ mySize = arr.length;
+ else
+ mySize = size;
+ var out = "[";
+ for (var ii = 0; ii < mySize; ++ii) {
+ if (ii > 0) {
+ out += ", ";
+ }
+ out += arr[ii];
+ }
+ return out + "]";
+}
+
+function runReadbackTest(testProgram, subtractor)
+{
+ // Verify floating point readback
+ debug("Checking readback of floating-point values");
+ var buf = new Float32Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, buf);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels from floating-point framebuffer should succeed");
+ var ok = true;
+ var tolerance = 8.0; // TODO: factor this out from both this test and the subtractor shader above.
+ for (var ii = 0; ii < buf.length; ++ii) {
+ if (Math.abs(buf[ii] - subtractor[ii]) > tolerance) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ testPassed("readPixels of float-type data from floating-point framebuffer succeeded");
+ } else {
+ testFailed("readPixels of float-type data from floating-point framebuffer failed: expected "
+ + arrayToString(subtractor, 4) + ", got " + arrayToString(buf));
+ }
+}
+
+function runFloatTextureRenderTargetTest(enabled, internalFormatString, format, type, testProgram, numberOfChannels, subtractor, texSubImageCover)
+{
+ let internalFormat = eval(internalFormatString);
+ debug("");
+ debug("testing floating-point " + internalFormatString + " texture render target" + (texSubImageCover > 0 ? " after calling texSubImage" : ""));
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed");
+
+ // Try to use this texture as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (!enabled) {
+ if (completeStatus == gl.FRAMEBUFFER_COMPLETE && !enabled)
+ testFailed("floating-point " + internalFormatString + " render target should not be supported");
+ else
+ testPassed("floating-point " + internalFormatString + " render target should not be supported");
+ return;
+ }
+
+ if (completeStatus != gl.FRAMEBUFFER_COMPLETE) {
+ if (version == 1 && format == gl.RGB)
+ testPassed("floating-point " + internalFormatString + " render target not supported; this is allowed.")
+ else
+ testFailed("floating-point " + internalFormatString + " render target not supported");
+ return;
+ }
+
+ if (texSubImageCover > 0) {
+ // Ensure that replacing the whole texture or a part of it with texSubImage2D doesn't affect renderability
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ var data = new Float32Array(width * height * numberOfChannels * texSubImageCover);
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height * texSubImageCover, format, type, data);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed if EXT_color_buffer_half_float is enabled");
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("render target support changed after calling texSubImage2D");
+ return;
+ }
+ }
+
+ var renderProgram =
+ wtu.setupProgram(gl,
+ [wtu.simpleVertexShader, `void main()
+ {
+ gl_FragColor = vec4(1000.0, 1000.0, 1000.0, 1000.0);
+ }`],
+ ['vPosition'],
+ [0]);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed");
+
+ // Now sample from the floating-point texture and verify we got the correct values.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.useProgram(testProgram);
+ gl.uniform1i(gl.getUniformLocation(testProgram, "tex"), 0);
+ gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from floating-point texture should succeed");
+ checkRenderingResults();
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ runReadbackTest(testProgram, subtractor);
+}
+
+function runFloatRenderbufferRenderTargetTest(enabled, internalFormatString, testProgram, numberOfChannels, subtractor)
+{
+ var internalFormat = eval(internalFormatString);
+ var samples = [0];
+ if (enabled && version > 1) {
+ samples = Array.prototype.slice.call(gl.getInternalformatParameter(gl.RENDERBUFFER, internalFormat, gl.SAMPLES));
+ samples.push(0);
+ }
+ for (var ndx = 0; ndx < samples.length; ++ndx) {
+ debug("");
+ debug("testing floating-point " + internalFormatString + " renderbuffer render target with number of samples " + samples[ndx]);
+
+ var colorbuffer = gl.createRenderbuffer();
+ var width = 2;
+ var height = 2;
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
+ if (samples[ndx] == 0)
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, width, height);
+ else
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[ndx], internalFormat, width, height);
+ if (!enabled) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point renderbuffer allocation should fail if EXT_color_buffer_half_float is not enabled or this is a 32 bit format");
+ return;
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point renderbuffer allocation should succeed if EXT_color_buffer_half_float is enabled");
+ }
+
+ // Try to use this renderbuffer as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorbuffer);
+
+ var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (completeStatus != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("floating-point " + internalFormatString + " render target not supported");
+ return;
+ }
+ var resolveColorRbo = null;
+ var resolveFbo = null;
+ if (samples[ndx] > 0) {
+ resolveColorRbo = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, resolveColorRbo);
+ gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, width, height);
+ resolveFbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resolveColorRbo);
+ completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (completeStatus != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Failed to create resolve framebuffer");
+ return;
+ }
+ }
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.clearColor(1000.0, 1000.0, 1000.0, 1000.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ if (samples[ndx] > 0) {
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFbo);
+ gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, resolveFbo);
+ }
+ runReadbackTest(testProgram, subtractor);
+ }
+}
+
+function runRGB16FNegativeTest()
+{
+ debug("");
+ debug("testing RGB16F isn't color renderable");
+
+ var texture = allocateTexture();
+ var width = 2;
+ var height = 2;
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB16F, width, height, 0, gl.RGB, gl.FLOAT, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "RGB16F texture allocation should succeed");
+
+ // Try to use this texture as a render target.
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+
+ var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (completeStatus == gl.FRAMEBUFFER_COMPLETE)
+ testFailed("RGB16F render target should not be supported with or without enabling EXT_color_buffer_half_float");
+ else
+ testPassed("RGB16F render target should not be supported with or without enabling EXT_color_buffer_half_float");
+ gl.deleteTexture(texture);
+
+ var colorbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB16F, width, height);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "RGB16F renderbuffer allocation should fail with or without enabling EXT_color_buffer_half_float");
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+ gl.deleteRenderbuffer(colorbuffer);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.deleteFramebuffer(fbo);
+}
+
+function runUniqueObjectTest()
+{
+ debug("");
+ debug("Testing that getExtension() returns the same object each time");
+ gl.getExtension("EXT_color_buffer_half_float").myProperty = 2;
+ webglHarnessCollectGarbage();
+ shouldBe('gl.getExtension("EXT_color_buffer_half_float").myProperty', '2');
+}
+
+function runInternalFormatQueryTest()
+{
+ debug("");
+ debug("testing the internal format query");
+
+ var maxSamples = gl.getParameter(gl.MAX_SAMPLES);
+ const formats = [gl.RGBA16F, gl.R16F, gl.RG16F];
+ var firstMultiOnlyFormat = 4;
+ for (var fmt = 0; fmt < formats.length; ++fmt) {
+ var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, formats[fmt], gl.SAMPLES);
+ if (fmt >= firstMultiOnlyFormat && (samples.length == 0 || samples[0] < maxSamples)) {
+ testFailed("the maximum value in SAMPLES should be at least " + maxSamples);
+ return;
+ }
+
+ var prevSampleCount = 0;
+ var sampleCount;
+ for (var ndx = 0; ndx < samples.length; ++ndx, prevSampleCount = sampleCount) {
+ sampleCount = samples[ndx];
+ // sample count must be > 0
+ if (sampleCount <= 0) {
+ testFailed("Expected sample count to be at least one; got " + sampleCount);
+ return;
+ }
+
+ // samples must be ordered descending
+ if (ndx > 0 && sampleCount >= prevSampleCount) {
+ testFailed("Expected sample count to be ordered in descending order; got " + prevSampleCount + " at index " + (ndx - 1) + ", and " + sampleCount + " at index " + ndx);
+ return;
+ }
+ }
+ }
+ testPassed("Internal format query succeeded");
+}
+
+function runCopyTexImageTest(enabled)
+{
+ var width = 16;
+ var height = 16;
+ var level = 0;
+ var cases = [
+ { internalformat: "RGBA16F", format: "RGBA", destFormat: "R16F", valid: true, renderable: true, },
+ { internalformat: "RGBA16F", format: "RGBA", destFormat: "RG16F", valid: true, renderable: true, },
+ { internalformat: "RGBA16F", format: "RGBA", destFormat: "RGB16F", valid: true, renderable: true, },
+ { internalformat: "RGBA16F", format: "RGBA", destFormat: "RGBA16F", valid: true, renderable: true, },
+ { internalformat: "RGB16F", format: "RGB", destFormat: "R16F", valid: true, renderable: false, },
+ { internalformat: "RGB16F", format: "RGB", destFormat: "RG16F", valid: true, renderable: false, },
+ { internalformat: "RGB16F", format: "RGB", destFormat: "RGB16F", valid: true, renderable: false, },
+ { internalformat: "RGB16F", format: "RGB", destFormat: "RGBA16F", valid: false, renderable: false, },
+ { internalformat: "RG16F", format: "RG", destFormat: "R16F", valid: true, renderable: true, },
+ { internalformat: "RG16F", format: "RG", destFormat: "RG16F", valid: true, renderable: true, },
+ { internalformat: "RG16F", format: "RG", destFormat: "RGB16F", valid: false, renderable: true, },
+ { internalformat: "RG16F", format: "RG", destFormat: "RGBA16F", valid: false, renderable: true, },
+ { internalformat: "R16F", format: "RED", destFormat: "R16F", valid: true, renderable: true, },
+ { internalformat: "R16F", format: "RED", destFormat: "RG16F", valid: false, renderable: true, },
+ { internalformat: "R16F", format: "RED", destFormat: "RGB16F", valid: false, renderable: true, },
+ { internalformat: "R16F", format: "RED", destFormat: "RGBA16F", valid: false, renderable: true, },
+ ];
+ if (version == 1) {
+ cases = [
+ { valid: true, renderable: true, format: "RGBA", destFormat: "LUMINANCE", },
+ { valid: true, renderable: true, format: "RGBA", destFormat: "ALPHA", },
+ { valid: true, renderable: true, format: "RGBA", destFormat: "LUMINANCE_ALPHA", },
+ { valid: true, renderable: true, format: "RGBA", destFormat: "RGB", },
+ { valid: true, renderable: true, format: "RGBA", destFormat: "RGBA", },
+ { valid: true, renderable: true, format: "RGB", destFormat: "LUMINANCE", },
+ { valid: false, renderable: true, format: "RGB", destFormat: "ALPHA", },
+ { valid: false, renderable: true, format: "RGB", destFormat: "LUMINANCE_ALPHA", },
+ { valid: true, renderable: true, format: "RGB", destFormat: "RGB", },
+ { valid: false, renderable: true, format: "RGB", destFormat: "RGBA", },
+ { valid: true, renderable: false, format: "ALPHA", destFormat: "ALPHA", },
+ { valid: true, renderable: false, format: "LUMINANCE", destFormat: "LUMINANCE", },
+ { valid: true, renderable: false, format: "LUMINANCE_ALPHA", destFormat: "LUMINANCE_ALPHA", },
+ ];
+ }
+ cases.forEach(function(testcase) {
+ debug("");
+ debug(`Testing CopyTexImage2D for format: ${testcase.format}, internalformat: ${testcase.internalformat}, destformat: ${testcase.destFormat}`);
+
+ var format = gl[testcase.format];
+ var internalformat = version > 1 ? gl[testcase.internalformat] : format;
+ var type = version > 1 ? gl.HALF_FLOAT : 0x8D61 /* HALF_FLOAT_OES */;
+ var destFormat = gl[testcase.destFormat];
+ var texSrc = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texSrc);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ var data = new Uint16Array(width * height * 4);
+ gl.texImage2D(gl.TEXTURE_2D, level, internalformat, width, height, 0, format, type, data);
+ var fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texSrc, level);
+ var texDest = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texDest);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed.");
+ if (enabled && testcase.renderable) {
+ if (version == 1 && format == gl.RGB && gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
+ testPassed("RGB framebuffer attachment not supported. This is allowed.")
+ } else {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.copyTexImage2D(gl.TEXTURE_2D, level, destFormat, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, testcase.valid ? gl.NO_ERROR : [gl.INVALID_ENUM, gl.INVALID_OPERATION], "CopyTexImage2D");
+ }
+ } else {
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ gl.copyTexImage2D(gl.TEXTURE_2D, level, destFormat, 0, 0, width, height, 0);
+ wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_FRAMEBUFFER_OPERATION], "CopyTexImage2D should fail.");
+ }
+
+ gl.deleteTexture(texDest);
+ gl.deleteTexture(texSrc);
+ gl.deleteFramebuffer(fbo);
+ });
+}
+
+description("This test verifies the functionality of the EXT_color_buffer_half_float extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, version);
+
+if (version < 2) {
+ // These are exposed on the extension, but we need them before the extension has been requested so we can
+ // make sure they don't work.
+ gl.R16F = 0x822D;
+ gl.RG16F = 0x822F;
+ gl.RGB16F = 0x881B;
+ gl.RGBA16F = 0x881A;
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ var texturedShaders = [
+ wtu.simpleTextureVertexShader,
+ `precision mediump float;
+ uniform sampler2D tex;
+ uniform vec4 subtractor;
+ varying vec2 texCoord;
+ void main()
+ {
+ vec4 color = texture2D(tex, texCoord);
+ if (abs(color.r - subtractor.r) +
+ abs(color.g - subtractor.g) +
+ abs(color.b - subtractor.b) +
+ abs(color.a - subtractor.a) < 16.0) {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ } else {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+ }`,
+ ];
+ var testProgram =
+ wtu.setupProgram(gl,
+ texturedShaders,
+ ['vPosition', 'texCoord0'],
+ [0, 1]);
+ var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
+
+ if (version > 1) {
+ // Ensure these formats can't be used for rendering if the extension is disabled
+ runFloatTextureRenderTargetTest(false, "gl.R16F", gl.RED, gl.FLOAT);
+ runFloatTextureRenderTargetTest(false, "gl.RG16F", gl.RG, gl.FLOAT);
+ runFloatTextureRenderTargetTest(false, "gl.RGBA16F", gl.RGBA, gl.FLOAT);
+ }
+
+ runFloatRenderbufferRenderTargetTest(false, "gl.R16F");
+ runFloatRenderbufferRenderTargetTest(false, "gl.RG16F");
+ runFloatRenderbufferRenderTargetTest(false, "gl.RGBA16F");
+ runFloatRenderbufferRenderTargetTest(false, "gl.R32F");
+ runFloatRenderbufferRenderTargetTest(false, "gl.RG32F");
+ runFloatRenderbufferRenderTargetTest(false, "gl.RGBA32F");
+ runFloatRenderbufferRenderTargetTest(false, "gl.R11F_G11F_B10F");
+
+ if (version > 1) {
+ runCopyTexImageTest(false);
+ // Ensure RGB16F can't be used for rendering.
+ runRGB16FNegativeTest();
+ }
+
+ let oesTextureHalfFloat = null;
+ if (version == 1) {
+ // oesTextureHalfFloat implicitly enables EXT_color_buffer_half_float if supported
+ oesTextureHalfFloat = gl.getExtension("OES_texture_half_float");
+ if (oesTextureHalfFloat && gl.getSupportedExtensions().includes("EXT_color_buffer_half_float")) {
+ runFloatTextureRenderTargetTest(true, "gl.RGBA", gl.RGBA, oesTextureHalfFloat.HALF_FLOAT_OES, testProgram, 4, [1000, 1000, 1000, 1000], 0);
+ runFloatTextureRenderTargetTest(true, "gl.RGB", gl.RGB, oesTextureHalfFloat.HALF_FLOAT_OES, testProgram, 3, [1000, 1000, 1000, 1], 0);
+ }
+ }
+
+ var ext = null;
+ if (!(ext = gl.getExtension("EXT_color_buffer_half_float"))) {
+ testPassed("No EXT_color_buffer_half_float support -- this is legal");
+ } else {
+ testPassed("Successfully enabled EXT_color_buffer_half_float extension");
+
+ shouldBe("ext.RGB16F_EXT", "gl.RGB16F");
+ shouldBe("ext.RGBA16F_EXT", "gl.RGBA16F");
+ shouldBe("ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT", "0x8211");
+ shouldBe("ext.UNSIGNED_NORMALIZED_EXT", "0x8C17");
+
+ if (version > 1) {
+ runInternalFormatQueryTest();
+ runFloatTextureRenderTargetTest(true, "gl.R16F", gl.RED, gl.FLOAT, testProgram, 1, [1000, 1, 1, 1], 0);
+ runFloatTextureRenderTargetTest(true, "gl.RG16F", gl.RG, gl.FLOAT, testProgram, 2, [1000, 1000, 1, 1], 0);
+ runFloatTextureRenderTargetTest(true, "gl.RGBA16F", gl.RGBA, gl.FLOAT, testProgram, 4, [1000, 1000, 1000, 1000], 0);
+ runFloatRenderbufferRenderTargetTest(true, "gl.R16F", testProgram, 1, [1000, 1, 1, 1]);
+ runFloatRenderbufferRenderTargetTest(true, "gl.RG16F", testProgram, 2, [1000, 1000, 1, 1]);
+ runFloatRenderbufferRenderTargetTest(true, "gl.RGBA16F", testProgram, 4, [1000, 1000, 1000, 1000]);
+ }
+ if (version == 1) {
+ shouldBeNonNull(oesTextureHalfFloat); // Required by spec
+ runFloatTextureRenderTargetTest(true, "gl.RGBA", gl.RGBA, oesTextureHalfFloat.HALF_FLOAT_OES, testProgram, 4, [1000, 1000, 1000, 1000], 0);
+ runFloatTextureRenderTargetTest(true, "gl.RGB", gl.RGB, oesTextureHalfFloat.HALF_FLOAT_OES, testProgram, 3, [1000, 1000, 1000, 1], 0);
+ runFloatTextureRenderTargetTest(false, "gl.LUMINANCE_ALPHA", gl.LUMINANCE_ALPHA, oesTextureHalfFloat.HALF_FLOAT_OES, testProgram, 2, [1000, 1000, 1000, 1000], 0);
+ runFloatTextureRenderTargetTest(false, "gl.LUMINANCE", gl.LUMINANCE, oesTextureHalfFloat.HALF_FLOAT_OES, testProgram, 1, [1000, 1, 1, 1], 0);
+ }
+
+ if (version > 1)
+ runRGB16FNegativeTest(); // Ensure EXT_color_buffer_half_float does not enable RGB16F as color renderable.
+
+ runCopyTexImageTest(true);
+
+ runUniqueObjectTest();
+ }
+}
+
+debug("");
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/ext-float-blend.js b/dom/canvas/test/webgl-conf/checkout/js/tests/ext-float-blend.js
new file mode 100644
index 0000000000..ab2f9f9288
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/ext-float-blend.js
@@ -0,0 +1,237 @@
+'use strict';
+
+const trivialVsSrc = `
+void main()
+{
+ gl_Position = vec4(0,0,0,1);
+}
+`;
+const trivialFsSrc = `
+void main()
+{
+ gl_FragColor = vec4(0,1,0,1);
+}
+`;
+const trivialVsMrtSrc100 = `
+void main()
+{
+ gl_Position = vec4(0,0,0,1);
+}
+`;
+const trivialFsMrtSrc100 = `
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+void main()
+{
+ gl_FragData[0] = vec4(1, 0, 0, 1);
+ gl_FragData[1] = vec4(0, 1, 0, 1);
+}
+`;
+const trivialVsMrtSrc300 = `#version 300 es
+void main()
+{
+ gl_Position = vec4(0,0,0,1);
+}
+`;
+const trivialFsMrtSrc300 = `#version 300 es
+precision mediump float;
+layout(location = 0) out vec4 o_color0;
+layout(location = 1) out vec4 o_color1;
+void main()
+{
+ o_color0 = vec4(1, 0, 0, 1);
+ o_color1 = vec4(0, 1, 0, 1);
+}
+`;
+
+function testExtFloatBlend(internalFormat) {
+ const shouldBlend = gl.getSupportedExtensions().indexOf('EXT_float_blend') != -1;
+
+ const prog = wtu.setupProgram(gl, [trivialVsSrc, trivialFsSrc]);
+ gl.useProgram(prog);
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.disable(gl.BLEND);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, 0, 'Float32 draw target without blending');
+
+ gl.enable(gl.BLEND);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, shouldBlend ? 0 : gl.INVALID_OPERATION,
+ 'Float32 blending is ' + (shouldBlend ? '' : 'not ') + 'allowed ');
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+}
+
+function testExtFloatBlendMRTImpl(version, internalFormat, shaders, attachments, drawBuffers) {
+ const shouldBlend = gl.getSupportedExtensions().indexOf('EXT_float_blend') != -1;
+
+ const prog = wtu.setupProgram(gl, shaders);
+ gl.useProgram(prog);
+
+ const tex1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ const tex2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ const texF1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texF1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
+
+ const texF2 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texF2);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, tex1, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, tex2, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ drawBuffers(attachments);
+
+ gl.enable(gl.BLEND);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, 0, 'No Float32 color attachment');
+
+ if (version < 2) {
+ // EXT_draw_buffers require all color buffers having the same number of bitplanes
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, texF1, 0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, texF2, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, shouldBlend ? 0 : gl.INVALID_OPERATION,
+ 'Float32 blending is ' + (shouldBlend ? '' : 'not ') + 'allowed ');
+ } else {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, texF1, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, shouldBlend ? 0 : gl.INVALID_OPERATION,
+ 'Float32 blending is ' + (shouldBlend ? '' : 'not ') + 'allowed ');
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, texF2, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, shouldBlend ? 0 : gl.INVALID_OPERATION,
+ 'Float32 blending is ' + (shouldBlend ? '' : 'not ') + 'allowed ');
+
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, tex1, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, shouldBlend ? 0 : gl.INVALID_OPERATION,
+ 'Float32 blending is ' + (shouldBlend ? '' : 'not ') + 'allowed ');
+
+ drawBuffers([attachments[0]]);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, 0, 'Float32 color attachment draw buffer is not enabled');
+
+ drawBuffers(attachments);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, tex2, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, 0, 'No Float32 color attachment');
+ }
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex1);
+ gl.deleteTexture(tex2);
+ gl.deleteTexture(texF1);
+ gl.deleteTexture(texF2);
+}
+
+function testExtFloatBlendMRT(version, drawBuffersExt) {
+ if (version < 2) {
+ if (!drawBuffersExt) return;
+ testExtFloatBlendMRTImpl(
+ version,
+ gl.RGBA,
+ [trivialVsMrtSrc100, trivialFsMrtSrc100],
+ [drawBuffersExt.COLOR_ATTACHMENT0_WEBGL, drawBuffersExt.COLOR_ATTACHMENT1_WEBGL],
+ drawBuffersExt.drawBuffersWEBGL.bind(drawBuffersExt)
+ );
+ } else {
+ testExtFloatBlendMRTImpl(
+ version,
+ gl.RGBA32F,
+ [trivialVsMrtSrc300, trivialFsMrtSrc300],
+ [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1],
+ gl.drawBuffers.bind(gl)
+ );
+ }
+}
+
+function testExtFloatBlendNonFloat32TypeImpl(internalFormat, formats) {
+ const shouldBlend = gl.getSupportedExtensions().indexOf('EXT_float_blend') != -1;
+
+ const prog = wtu.setupProgram(gl, [trivialVsSrc, trivialFsSrc]);
+ gl.useProgram(prog);
+
+ gl.enable(gl.BLEND);
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, shouldBlend ? 0 : gl.INVALID_OPERATION,
+ 'Float32 blending is ' + (shouldBlend ? '' : 'not ') + 'allowed ');
+
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, 0, 'UNSIGNED_BYTE should blend anyway');
+
+ for (let i = 0, len = formats.length; i < len; i++) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, formats[i][0], 1, 1, 0, formats[i][1], formats[i][2], null);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, 0, 'Any other float type which is not 32-bit-Float should blend anyway');
+ }
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+}
+
+function testExtFloatBlendNonFloat32Type(version, oesTextureHalfFloat) {
+ if (version < 2) {
+ if (!oesTextureHalfFloat) return;
+ const formats = [
+ [gl.RGBA, gl.RGBA, oesTextureHalfFloat.HALF_FLOAT_OES]
+ ];
+ testExtFloatBlendNonFloat32TypeImpl(gl.RGBA, formats);
+ } else {
+ const formats = [
+ [gl.RGBA16F, gl.RGBA, gl.HALF_FLOAT],
+ [gl.RGBA16F, gl.RGBA, gl.FLOAT],
+ [gl.RG16F, gl.RG, gl.FLOAT],
+ [gl.R16F, gl.RED, gl.FLOAT],
+ [gl.R11F_G11F_B10F, gl.RGB, gl.FLOAT]
+ ];
+ testExtFloatBlendNonFloat32TypeImpl(gl.RGBA32F, formats);
+ }
+}
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/ext-texture-filter-anisotropic.js b/dom/canvas/test/webgl-conf/checkout/js/tests/ext-texture-filter-anisotropic.js
new file mode 100644
index 0000000000..1e60a79717
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/ext-texture-filter-anisotropic.js
@@ -0,0 +1,169 @@
+"use strict";
+description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
+
+debug("");
+
+let wtu = WebGLTestUtils;
+let canvas = document.getElementById("canvas");
+let gl = wtu.create3DContext(canvas, undefined, contextVersion);
+let ext = null;
+let sampler;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runHintTestDisabled();
+ if (contextVersion >= 2) {
+ runSamplerTestDisabled();
+ }
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_texture_filter_anisotropic");
+
+ if (!ext) {
+ testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
+
+ runSupportedTest(true);
+ runHintTestEnabled();
+ if (contextVersion >= 2) {
+ runSamplerTestEnabled();
+ }
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ if (wtu.getSupportedExtensionWithKnownPrefixes(gl, "EXT_texture_filter_anisotropic") !== undefined) {
+ if (extensionEnabled) {
+ testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
+ } else {
+ testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("EXT_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runHintTestDisabled() {
+ debug("Testing MAX_TEXTURE_MAX_ANISOTROPY_EXT with extension disabled");
+
+ const MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
+ shouldBeNull(`gl.getParameter(${MAX_TEXTURE_MAX_ANISOTROPY_EXT})`);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY_EXT should not be queryable if extension is disabled");
+
+ debug("Testing TEXTURE_MAX_ANISOTROPY_EXT with extension disabled");
+ const TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
+ let texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ shouldBeNull(`gl.getTexParameter(gl.TEXTURE_2D, ${TEXTURE_MAX_ANISOTROPY_EXT})`);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY_EXT should not be queryable if extension is disabled");
+
+ gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY_EXT, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY_EXT should not be settable if extension is disabled");
+
+ gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY_EXT, 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY_EXT should not be settable if extension is disabled");
+
+ gl.deleteTexture(texture);
+}
+
+function runHintTestEnabled() {
+ debug("Testing MAX_TEXTURE_MAX_ANISOTROPY_EXT with extension enabled");
+
+ shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT", "0x84FF");
+
+ let max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY_EXT query should succeed if extension is enabled");
+
+ if (max_anisotropy >= 2) {
+ testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY_EXT is 2.0");
+ } else {
+ testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY_EXT is 2.0, returned values was: " + max_anisotropy);
+ }
+
+ // TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
+
+ debug("Testing TEXTURE_MAX_ANISOTROPY_EXT with extension disabled");
+ shouldBe("ext.TEXTURE_MAX_ANISOTROPY_EXT", "0x84FE");
+
+ let texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ let queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY_EXT query should succeed if extension is enabled");
+
+ if (queried_value == 1) {
+ testPassed("Initial value of TEXTURE_MAX_ANISOTROPY_EXT is 1.0");
+ } else {
+ testFailed("Initial value of TEXTURE_MAX_ANISOTROPY_EXT should be 1.0, returned value was: " + queried_value);
+ }
+
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY_EXT set to < 1 should be an invalid value");
+
+ gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY_EXT set to < 1 should be an invalid value");
+
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY_EXT set to >= 2 should succeed");
+
+ gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY_EXT set to >= 2 should succeed");
+
+ queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT);
+ if (queried_value == max_anisotropy) {
+ testPassed("Set value of TEXTURE_MAX_ANISOTROPY_EXT matches expecation");
+ } else {
+ testFailed("Set value of TEXTURE_MAX_ANISOTROPY_EXT should be: " + max_anisotropy + " , returned value was: " + queried_value);
+ }
+
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, 1.5);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY_EXT set to 1.5 should succeed");
+
+ queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT);
+ if (queried_value == 1.5) {
+ testPassed("Set value of TEXTURE_MAX_ANISOTROPY_EXT matches expecation");
+ } else {
+ testFailed("Set value of TEXTURE_MAX_ANISOTROPY_EXT should be: " + 1.5 + " , returned value was: " + queried_value);
+ }
+
+ gl.deleteTexture(texture);
+}
+
+function runSamplerTestDisabled() {
+ sampler = gl.createSampler();
+ const TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
+ gl.samplerParameterf(sampler, TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "setting TEXTURE_MAX_ANISOTROPY_EXT on sampler without extension enabled should fail");
+ shouldBeNull(`gl.getSamplerParameter(sampler, ${TEXTURE_MAX_ANISOTROPY_EXT})`);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "querying TEXTURE_MAX_ANISOTROPY_EXT on sampler without extension enabled should fail");
+ gl.deleteSampler(sampler);
+}
+
+function runSamplerTestEnabled() {
+ let sampler = gl.createSampler();
+ gl.samplerParameterf(sampler, ext.TEXTURE_MAX_ANISOTROPY_EXT, 1.5);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setting TEXTURE_MAX_ANISOTROPY_EXT on sampler should succeed");
+ let queried_value = gl.getSamplerParameter(sampler, ext.TEXTURE_MAX_ANISOTROPY_EXT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "querying TEXTURE_MAX_ANISOTROPY_EXT on sampler should succeed");
+ if (queried_value == 1.5) {
+ testPassed("Set value of TEXTURE_MAX_ANISOTROPY_EXT on sampler matches expecation");
+ } else {
+ testFailed("Set value of TEXTURE_MAX_ANISOTROPY_EXT on sampler should be: " + 1.5 + " , returned value was: " + queried_value);
+ }
+ gl.deleteSampler(sampler);
+}
+
+debug("");
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js
new file mode 100644
index 0000000000..4c853fc4fa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js
@@ -0,0 +1,44 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+"use strict";
+
+var runBindAttribLocationAliasingTest = function(wtu, gl, glFragmentShader, vertexShaderTemplate) {
+ var typeInfo = [
+ { type: 'float', asVec4: 'vec4(0.0, $(var), 0.0, 1.0)' },
+ { type: 'vec2', asVec4: 'vec4($(var), 0.0, 1.0)' },
+ { type: 'vec3', asVec4: 'vec4($(var), 1.0)' },
+ { type: 'vec4', asVec4: '$(var)' },
+ ];
+ var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+ // Test all type combinations of a_1 and a_2.
+ typeInfo.forEach(function(typeInfo1) {
+ typeInfo.forEach(function(typeInfo2) {
+ debug('attribute_1: ' + typeInfo1.type + ' attribute_2: ' + typeInfo2.type);
+ var replaceParams = {
+ type_1: typeInfo1.type,
+ type_2: typeInfo2.type,
+ gl_Position_1: wtu.replaceParams(typeInfo1.asVec4, {var: 'a_1'}),
+ gl_Position_2: wtu.replaceParams(typeInfo2.asVec4, {var: 'a_2'})
+ };
+ var strVertexShader = wtu.replaceParams(vertexShaderTemplate, replaceParams);
+ var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
+ assertMsg(glVertexShader != null, "Vertex shader compiled successfully.");
+ // Bind both a_1 and a_2 to the same position and verify the link fails.
+ // Do so for all valid positions available.
+ for (var l = 0; l < maxAttributes; l++) {
+ var glProgram = gl.createProgram();
+ gl.bindAttribLocation(glProgram, l, 'a_1');
+ gl.bindAttribLocation(glProgram, l, 'a_2');
+ gl.attachShader(glProgram, glVertexShader);
+ gl.attachShader(glProgram, glFragmentShader);
+ gl.linkProgram(glProgram);
+ var linkStatus = gl.getProgramParameter(glProgram, gl.LINK_STATUS);
+ assertMsg(!linkStatus, "Link should fail when both attributes are aliased to location " + l);
+ }
+ });
+ });
+}; \ No newline at end of file
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 0000000000..32d451f7a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js
@@ -0,0 +1,123 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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 0000000000..8844bbf544
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js
@@ -0,0 +1,183 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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 0000000000..bd97434b77
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js
@@ -0,0 +1,1090 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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";
+const wtu = WebGLTestUtils;
+description("Test of get calls against GL objects like getBufferParameter, etc.");
+
+let gl = wtu.create3DContext(undefined, undefined, contextVersion);
+
+async function testInvalidArgument(funcName, argumentName, validArgumentArray, func) {
+ let validArguments = {};
+ for (let ii = 0; ii < validArgumentArray.length; ++ii) {
+ validArguments[validArgumentArray[ii]] = true;
+ }
+ let success = true;
+ const MAX = 0x10000;
+ const STEP = Math.ceil(MAX / 10);
+ for (let ii = 0; ii < MAX; ii += 1) {
+ if (ii && ii % STEP == 0) {
+ debug(`(${ii} of ${MAX}: ${(ii/MAX*100).toFixed(1)}%)`);
+ await wtu.dispatchPromise(); // Spin the event loop.
+ }
+ if (!validArguments[ii]) {
+ let result = func(ii);
+ if (result !== null) {
+ success = false;
+ testFailed(funcName + " returned " + result + " instead of null for invalid " + argumentName + " enum: " + wtu.glEnumToString(gl, ii));
+ break;
+ }
+ let 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");
+ }
+}
+
+(async () => {
+ debug("");
+ debug("test getBufferParameter");
+ // Test getBufferParameter
+ let 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 (let bb = 0; bb < bufferTypes.length; ++bb) {
+ let bufferType = bufferTypes[bb];
+ let buffer = gl.createBuffer();
+ gl.bindBuffer(bufferType, buffer);
+ gl.bufferData(bufferType, 16, gl.DYNAMIC_DRAW);
+ let expression1 = "gl.getBufferParameter(" + bufferType + ", gl.BUFFER_SIZE)";
+ let expression2 = "gl.getBufferParameter(" + bufferType + ", gl.BUFFER_USAGE)";
+ shouldBe(expression1, '16');
+ shouldBe(expression2, 'gl.DYNAMIC_DRAW');
+ await testInvalidArgument("getBufferParameter", "parameter", [gl.BUFFER_SIZE, gl.BUFFER_USAGE], function(bufferType) {
+ return function(parameter) {
+ return gl.getBufferParameter(bufferType, parameter);
+ };
+ }(bufferType));
+ gl.bindBuffer(bufferType, null);
+ }
+ await testInvalidArgument(
+ "getBufferParameter",
+ "target",
+ bufferTypes,
+ function(target) {
+ return gl.getBufferParameter(target, gl.BUFFER_SIZE);
+ }
+ );
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ let testCases = [
+ { contextStencil: true},
+ { contextStencil: false}
+ ];
+
+ for (let 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);
+ }
+
+ window.texture = gl.createTexture();
+ window.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);
+ window.framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ let 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);
+ }
+ window.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 (let 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)');
+ }
+ let 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
+ ]);
+ }
+ await testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "parameter",
+ validParametersForFBAttachment,
+ function(parameter) {
+ return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT, parameter);
+ }
+ );
+ let validTargetsForFBAttachment = [gl.FRAMEBUFFER];
+ if (contextVersion > 1) {
+ validTargetsForFBAttachment = validTargetsForFBAttachment.concat([gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER]);
+ }
+ await testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "target",
+ validTargetsForFBAttachment,
+ function(target) {
+ return gl.getFramebufferAttachmentParameter(target, gl.COLOR_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ }
+ );
+ let validAttachmentsForFBAttachment = new Array(
+ gl.COLOR_ATTACHMENT0,
+ gl.DEPTH_ATTACHMENT,
+ gl.STENCIL_ATTACHMENT,
+ gl.DEPTH_STENCIL_ATTACHMENT
+ );
+ if (contextVersion > 1) {
+ for (let ii = 1; ii < gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); ++ii) {
+ validAttachmentsForFBAttachment[validAttachmentsForFBAttachment.length] = gl.COLOR_ATTACHMENT0 + ii;
+ }
+ }
+ await 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)');
+ }
+ await testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "parameter",
+ validParametersForFBAttachment,
+ function(parameter) {
+ return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, parameter);
+ }
+ );
+ await testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "target",
+ validTargetsForFBAttachment,
+ function(target) {
+ return gl.getFramebufferAttachmentParameter(target, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ }
+ );
+ await 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");
+ window.standardVert = wtu.loadStandardVertexShader(gl);
+ window.standardFrag = wtu.loadStandardFragmentShader(gl);
+ window.standardProgram = gl.createProgram();
+ gl.attachShader(standardProgram, standardVert);
+ gl.attachShader(standardProgram, standardFrag);
+ gl.linkProgram(standardProgram);
+ window.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) {
+ let buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 1024, gl.DYNAMIC_DRAW);
+ window.uniformBlockProgram = wtu.loadUniformBlockProgram(gl);
+ let 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');
+ }
+ window.program = standardProgram;
+ let 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;
+ }
+ await 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)');
+ let 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');
+ }
+ let 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;
+ }
+ await testInvalidArgument(
+ "getRenderbufferParameter",
+ "parameter",
+ validArrayForRenderbuffer,
+ function(parameter) {
+ return gl.getRenderbufferParameter(gl.RENDERBUFFER, parameter);
+ });
+ await 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');
+ await 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.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');
+ }
+ let 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,
+ ]);
+ }
+ await testInvalidArgument(
+ "getTexParameter",
+ "parameter",
+ validParametersForTexture,
+ function(parameter) {
+ return gl.getTexParameter(gl.TEXTURE_2D, parameter);
+ }
+ );
+ let validTargetsForTexture = [ gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP];
+ if (contextVersion > 1) {
+ validTargetsForTexture = validTargetsForTexture.concat([ gl.TEXTURE_3D, gl.TEXTURE_2D_ARRAY]);
+ }
+ await 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");
+ window.boolProgram = wtu.loadProgramFromFile(gl, "../../resources/boolUniformShader.vert", "../../resources/noopUniformShader.frag");
+ shouldBe('gl.getProgramParameter(boolProgram, gl.LINK_STATUS)', 'true');
+ window.bvalLoc = gl.getUniformLocation(boolProgram, "bval");
+ window.bval2Loc = gl.getUniformLocation(boolProgram, "bval2");
+ window.bval3Loc = gl.getUniformLocation(boolProgram, "bval3");
+ window.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");
+ window.intProgram = wtu.loadProgramFromFile(gl, "../../resources/intUniformShader.vert", "../../resources/noopUniformShader.frag");
+ shouldBe('gl.getProgramParameter(intProgram, gl.LINK_STATUS)', 'true');
+ window.ivalLoc = gl.getUniformLocation(intProgram, "ival");
+ window.ival2Loc = gl.getUniformLocation(intProgram, "ival2");
+ window.ival3Loc = gl.getUniformLocation(intProgram, "ival3");
+ window.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");
+ window.floatProgram = wtu.loadProgramFromFile(gl, "../../resources/floatUniformShader.vert", "../../resources/noopUniformShader.frag");
+ shouldBe('gl.getProgramParameter(floatProgram, gl.LINK_STATUS)', 'true');
+ window.fvalLoc = gl.getUniformLocation(floatProgram, "fval");
+ window.fval2Loc = gl.getUniformLocation(floatProgram, "fval2");
+ window.fval3Loc = gl.getUniformLocation(floatProgram, "fval3");
+ window.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");
+ window.samplerProgram = wtu.loadProgramFromFile(gl, "../../resources/noopUniformShader.vert", "../../resources/samplerUniformShader.frag");
+ shouldBe('gl.getProgramParameter(samplerProgram, gl.LINK_STATUS)', 'true');
+ window.s2DValLoc = gl.getUniformLocation(samplerProgram, "s2D");
+ window.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");
+ window.matProgram = wtu.loadProgramFromFile(gl, "../../resources/matUniformShader.vert", "../../resources/noopUniformShader.frag");
+ shouldBe('gl.getProgramParameter(matProgram, gl.LINK_STATUS)', 'true');
+ window.mval2Loc = gl.getUniformLocation(matProgram, "mval2");
+ window.mval3Loc = gl.getUniformLocation(matProgram, "mval3");
+ window.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");
+ window.uintProgram = wtu.loadProgramFromFile(gl, "../../resources/uintUniformShader.vert", "../../resources/noopUniformShaderES3.frag");
+ shouldBe('gl.getProgramParameter(uintProgram, gl.LINK_STATUS)', 'true');
+ window.uvalLoc = gl.getUniformLocation(uintProgram, "uval");
+ window.uval2Loc = gl.getUniformLocation(uintProgram, "uval2");
+ window.uval3Loc = gl.getUniformLocation(uintProgram, "uval3");
+ window.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);
+
+ window.matForWebGL2Program = wtu.loadProgramFromFile(gl, "../../resources/matForWebGL2UniformShader.vert", "../../resources/noopUniformShaderES3.frag");
+ shouldBe('gl.getProgramParameter(matForWebGL2Program, gl.LINK_STATUS)', 'true');
+ window.mval2x3Loc = gl.getUniformLocation(matForWebGL2Program, "mval2x3");
+ window.mval2x4Loc = gl.getUniformLocation(matForWebGL2Program, "mval2x4");
+ window.mval3x2Loc = gl.getUniformLocation(matForWebGL2Program, "mval3x2");
+ window.mval3x4Loc = gl.getUniformLocation(matForWebGL2Program, "mval3x4");
+ window.mval4x2Loc = gl.getUniformLocation(matForWebGL2Program, "mval4x2");
+ window.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");
+ window.samplerForWebGL2Program = wtu.loadProgramFromFile(gl, "../../resources/noopUniformShaderES3.vert", "../../resources/samplerForWebGL2UniformShader.frag");
+ shouldBe('gl.getProgramParameter(samplerForWebGL2Program, gl.LINK_STATUS)', 'true');
+ window.s3DValLoc = gl.getUniformLocation(samplerForWebGL2Program, "s3D");
+ window.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");
+ let array = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+ window.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) {
+ let 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);
+ let 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;
+ }
+ await testInvalidArgument(
+ "getVertexAttrib",
+ "parameter",
+ validArrayForVertexAttrib,
+ function(parameter) {
+ return gl.getVertexAttrib(1, parameter);
+ }
+ );
+ let 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.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+
+ shouldNotBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+ gl.deleteTexture(texture);
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ shouldNotBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+ gl.deleteRenderbuffer(renderbuffer);
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ 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);
+
+ await testInvalidArgument(
+ "getInternalformatParameter",
+ "target",
+ [ gl.RENDERBUFFER ],
+ function(target) {
+ return gl.getInternalformatParameter(target, gl.R32I, gl.SAMPLES);
+ });
+
+ await testInvalidArgument(
+ "getInternalformatParameter",
+ "pname",
+ [ gl.SAMPLES ],
+ function(pname) {
+ return gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA4, pname);
+ });
+
+ let 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
+ );
+ await testInvalidArgument(
+ "getInternalformatParameter",
+ "internalformat",
+ validArrayForInterformat,
+ function(internalformat) {
+ return gl.getInternalformatParameter(gl.RENDERBUFFER, internalformat, gl.SAMPLES);
+ });
+
+
+ debug("");
+ debug("Test getIndexedParameter");
+ window.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');
+ window.buffer1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffer1);
+ gl.bufferData(gl.UNIFORM_BUFFER, 64, gl.DYNAMIC_DRAW);
+ window.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');
+
+ let 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
+ );
+ await testInvalidArgument(
+ "getIndexedParameter",
+ "target",
+ validArrayForTarget,
+ function(target) {
+ return gl.getIndexedParameter(target, 0);
+ });
+
+ debug("");
+ debug("Test getSamplerParameter");
+ window.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');
+ let 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
+ );
+ await testInvalidArgument(
+ "getSamplerParameter",
+ "pname",
+ validArrayForSamplerParameter,
+ function(pname) {
+ return gl.getSamplerParameter(sampler, pname);
+ });
+
+ debug("");
+ debug("Test getSyncParameter");
+ window.sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ shouldBe('gl.getSyncParameter(sync, gl.OBJECT_TYPE)', 'gl.SYNC_FENCE');
+ let 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');
+ let validArrayForSyncParameter = new Array(
+ gl.OBJECT_TYPE,
+ gl.SYNC_STATUS,
+ gl.SYNC_CONDITION,
+ gl.SYNC_FLAGS
+ );
+ await testInvalidArgument(
+ "getSyncParameter",
+ "pname",
+ validArrayForSyncParameter,
+ function(pname) {
+ return gl.getSyncParameter(sync, pname);
+ });
+
+ debug("");
+ debug("Test getQueryParameter");
+ window.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.
+ let validArrayForPname = new Array(
+ gl.QUERY_RESULT,
+ gl.QUERY_RESULT_AVAILABLE
+ );
+ await testInvalidArgument(
+ "getQueryParameter",
+ "pname",
+ validArrayForPname,
+ function(pname) {
+ return gl.getQueryParameter(query, pname);
+ }
+ );
+
+ debug("");
+ debug("Test getFragDataLocation");
+ let 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';
+ let 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';
+ window.vertShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vertShader, baseVertShader);
+ gl.compileShader(vertShader);
+ shouldBe('gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)', 'true');
+ window.fragShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fragShader, baseFragShader);
+ gl.compileShader(fragShader);
+ shouldBe('gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)', 'true');
+ window.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");
+ program = wtu.loadUniformBlockProgram(gl);
+ gl.linkProgram(program);
+ shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ let numActiveUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ let blockIndex = gl.getUniformBlockIndex(program, "Transform");
+ let uniformIndices = [];
+ for (let i = 0; i < numActiveUniforms; i++)
+ uniformIndices.push(i);
+ let types = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_TYPE);
+ let sizes = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_SIZE);
+ let blockIndices = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_BLOCK_INDEX);
+ let offsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ let arrayStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_ARRAY_STRIDE);
+ let matrixStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_MATRIX_STRIDE);
+ let rowMajors = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_IS_ROW_MAJOR);
+ for (let 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]);
+ }
+
+ 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
+ );
+ await testInvalidArgument(
+ "getActiveUniforms",
+ "pname",
+ validArrayForPname,
+ function(pname) {
+ return gl.getActiveUniforms(program, uniformIndices, pname);
+ }
+ );
+
+ debug("");
+ debug("Test getUniformBlockIndex");
+ 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');
+ window.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");
+ 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);
+ window.noLinkProgram = gl.createProgram();
+ shouldBeFalse('gl.getProgramParameter(noLinkProgram, gl.LINK_STATUS)');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getActiveUniformBlockName(noLinkProgram, 0)');
+ 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");
+ 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)');
+ let indices = gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
+ for (let 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]);
+ }
+ 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
+ );
+ await testInvalidArgument(
+ "getActiveUniformBlockParameter",
+ "pname",
+ validArrayForPname,
+ function(pname) {
+ return gl.getActiveUniformBlockParameter(program, 0, pname);
+ }
+ );
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ finishTest();
+})();
+
+let 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 0000000000..97cad40868
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js
@@ -0,0 +1,263 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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 0000000000..edcad3b1f6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js
@@ -0,0 +1,105 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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/invalid-vertex-attrib-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/invalid-vertex-attrib-test.js
new file mode 100644
index 0000000000..b28c484843
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/invalid-vertex-attrib-test.js
@@ -0,0 +1,129 @@
+var createInvalidAttribTestFn = (function() {
+
+async function testPreserveDrawingBufferTrue(gl, drawFn, clear) {
+ debug('');
+ debug(`test preserveDrawingBuffer: true with ${drawFn.name} ${clear ? 'with' : 'without'} clear`);
+
+ if (clear) {
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ }
+
+ const skipTest = drawFn(gl);
+ if (skipTest) {
+ debug('skipped: extension does not exist');
+ return;
+ }
+
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "canvas should be red");
+
+ await waitForComposite();
+
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "canvas should be red");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function setupWebGL({
+ webglVersion,
+ shadersFn,
+ attribs,
+}) {
+ const positionBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ -1, 1,
+ 1, -1,
+ 1, 1,
+ ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ const indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3, 4, 5]), gl.STATIC_DRAW);
+ return gl;
+}
+
+function createInvalidAttribTestFn(gl) {
+ const vs = `
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ `;
+
+ const fs = `
+ precision mediump float;
+ void main()
+ {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+ `
+
+ const program = wtu.setupProgram(gl, [vs, fs], ["vPosition"]);
+ if (!program) {
+ debug(`program failed to compile: ${wtu.getLastError()}`);
+ }
+
+ const positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ -1, 1,
+ 1, -1,
+ 1, 1,
+ ]), gl.STATIC_DRAW);
+
+ const indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
+ new Uint8Array([0, 1, 2, 3, 4, 5]),
+ gl.STATIC_DRAW);
+
+ return async function invalidAttribTestFn(drawFn) {
+ debug('');
+
+ // reset attribs
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ const numAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+ for (let i = 0; i < numAttribs; ++i) {
+ gl.disableVertexAttribArray(i);
+ gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+ }
+
+ debug(`test ${drawFn.name} draws with valid attributes`);
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ gl.clearColor(0, 0, 0, 0,);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be zero");
+
+ drawFn(gl);
+
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "canvas should be red");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+
+ debug(`test ${drawFn.name} generates INVALID_OPERATION draws with enabled attribute no buffer bound`);
+ gl.enableVertexAttribArray(1);
+
+ gl.clearColor(0, 0, 0, 0,);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be zero");
+
+ drawFn(gl);
+
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should generate INVALID_OPERATION");
+ wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be zero");
+ };
+}
+
+return createInvalidAttribTestFn;
+}());
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 0000000000..45e509f50a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js
@@ -0,0 +1,183 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+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.dispatchPromise(doNextTest);
+ } 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;
+ }
+
+ // Draws repeatedly to a large canvas with preserveDrawingBuffer enabled to
+ // try and provoke a context loss.
+ function createPreserveDrawingBufferLeakTest(gl) {
+ var contextActive = true;
+ gl.canvas.addEventListener("webglcontextlost", () => {
+ testFailed("Context was lost");
+ contextActive = false;
+ });
+
+ function test() {
+ var x = Math.random() * gl.drawingBufferWidth;
+ var y = Math.random() * gl.drawingBufferHeight;
+ var width = Math.random() * (gl.drawingBufferWidth - x);
+ var height = Math.random() * (gl.drawingBufferHeight - y);
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(x, y, width, height);
+ gl.clearColor(Math.random(), Math.random(), Math.random(), 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ return contextActive;
+ };
+
+ return test;
+ }
+
+ return {
+ run: run,
+
+ createContextCreationAndDestructionTest: createContextCreationAndDestructionTest,
+ createContextCreationTest: createContextCreationTest,
+ createMultisampleCorruptionTest: createMultisampleCorruptionTest,
+ createPreserveDrawingBufferLeakTest: createPreserveDrawingBufferLeakTest
+ };
+
+})();
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/line-rendering-quality.js b/dom/canvas/test/webgl-conf/checkout/js/tests/line-rendering-quality.js
new file mode 100644
index 0000000000..dfa7c02167
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/line-rendering-quality.js
@@ -0,0 +1,163 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+'use strict';
+description("Verifies that lines, both aliased and antialiased, have acceptable quality.");
+
+let wtu = WebGLTestUtils;
+let gl;
+
+let aa_fbo;
+
+function setupWebGL1Test(canvasId, useAntialiasing) {
+ gl = wtu.create3DContext(canvasId, { antialias: useAntialiasing }, contextVersion);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors during WebGL 1.0 setup");
+}
+
+function setupWebGL2Test(canvasId, useAntialiasing) {
+ gl = wtu.create3DContext(canvasId, { antialias: false }, contextVersion);
+ // In WebGL 2.0, we always allocate the back buffer without
+ // antialiasing. The only question is whether we allocate a
+ // framebuffer with a multisampled renderbuffer attachment.
+ aa_fbo = null;
+ if (useAntialiasing) {
+ aa_fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, aa_fbo);
+ let rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ let supported = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES);
+ // Prefer 4, then 8, then max.
+ let preferred = [4, 8];
+ let allocated = false;
+ for (let value of preferred) {
+ if (supported.indexOf(value) >= 0) {
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, value, gl.RGBA8,
+ gl.drawingBufferWidth, gl.drawingBufferHeight);
+ allocated = true;
+ break;
+ }
+ }
+ if (!allocated) {
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, supported[supported.length - 1],
+ gl.RGBA8, gl.drawingBufferWidth, gl.drawingBufferHeight);
+ }
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors during WebGL 2.0 setup");
+}
+
+function setupLines() {
+ let prog = wtu.setupSimpleColorProgram(gl, 0);
+ let loc = gl.getUniformLocation(prog, 'u_color');
+ if (loc == null) {
+ testFailed('Failed to fetch color uniform');
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After setup of line program");
+ gl.uniform4f(loc, 1.0, 1.0, 1.0, 1.0);
+ let buffer = gl.createBuffer();
+ let scale = 0.5;
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -scale, -scale, 0.0, 1.0,
+ -scale, scale, 0.0, 1.0,
+ scale, scale, 0.0, 1.0,
+ scale, -scale, 0.0, 1.0,
+ -scale, -scale, 0.0, 1.0,
+ ]), gl.STATIC_DRAW);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After setup of buffer");
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After setup of attribute array");
+}
+
+function renderLines(contextVersion, useAntialiasing) {
+ gl.clearColor(0.0, 0.0, 0.5, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.LINE_STRIP, 0, 5);
+ if (contextVersion == 2 && useAntialiasing) {
+ // Blit aa_fbo into the real back buffer.
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, aa_fbo);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
+ let w = gl.drawingBufferWidth;
+ let h = gl.drawingBufferHeight;
+ gl.blitFramebuffer(0, 0, w, h,
+ 0, 0, w, h,
+ gl.COLOR_BUFFER_BIT, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ }
+}
+
+function pixelAboveThreshold(arr, pixelIndex, threshold) {
+ return (arr[4 * pixelIndex + 0] >= threshold &&
+ arr[4 * pixelIndex + 1] >= threshold &&
+ arr[4 * pixelIndex + 2] >= threshold &&
+ arr[4 * pixelIndex + 3] >= threshold);
+}
+
+function checkLine(arr, threshold, direction) {
+ // Count number of crossings from below threshold to above (or equal
+ // to) threshold. Must be equal to 2.
+
+ let numPixels = arr.length / 4;
+ let numUpCrossings = 0;
+ let numDownCrossings = 0;
+ for (let index = 0; index < numPixels - 1; ++index) {
+ let curPixel = pixelAboveThreshold(arr, index, threshold);
+ let nextPixel = pixelAboveThreshold(arr, index + 1, threshold);
+ if (!curPixel && nextPixel) {
+ ++numUpCrossings;
+ } else if (curPixel && !nextPixel) {
+ ++numDownCrossings;
+ }
+ }
+ if (numUpCrossings != numDownCrossings) {
+ testFailed('Found differing numbers of up->down and down->up transitions');
+ }
+ if (numUpCrossings == 2) {
+ testPassed('Found 2 lines, looking in the ' + direction + ' direction');
+ } else {
+ testFailed('Found ' + numUpCrossings + ' lines, looking in the ' +
+ direction + ' direction, expected 2');
+ }
+}
+
+function checkResults() {
+ // Check the middle horizontal and middle vertical line of the canvas.
+ let w = gl.drawingBufferWidth;
+ let h = gl.drawingBufferHeight;
+ let t = 100;
+ let arr = new Uint8Array(4 * w);
+ gl.readPixels(0, Math.floor(h / 2),
+ w, 1, gl.RGBA, gl.UNSIGNED_BYTE, arr);
+ checkLine(arr, t, 'horizontal');
+ arr = new Uint8Array(4 * h);
+ gl.readPixels(Math.floor(w / 2), 0,
+ 1, h, gl.RGBA, gl.UNSIGNED_BYTE, arr);
+ checkLine(arr, t, 'vertical');
+}
+
+function runTest(contextVersion, canvasId, useAntialiasing) {
+ switch (contextVersion) {
+ case 1: {
+ setupWebGL1Test(canvasId, useAntialiasing);
+ break;
+ }
+ case 2: {
+ setupWebGL2Test(canvasId, useAntialiasing);
+ }
+ }
+ setupLines();
+ renderLines(contextVersion, useAntialiasing);
+ checkResults();
+}
+
+function runTests() {
+ runTest(contextVersion, 'testbed', false);
+ runTest(contextVersion, 'testbed2', true);
+}
+
+runTests();
+let successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/no-over-optimizations-on-uniform-array.js b/dom/canvas/test/webgl-conf/checkout/js/tests/no-over-optimizations-on-uniform-array.js
new file mode 100644
index 0000000000..1202b7868c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/no-over-optimizations-on-uniform-array.js
@@ -0,0 +1,247 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+NoOverOptimizeOnUniformArrayTester = (function(){
+
+var vshader = [
+ "attribute vec4 a_position;",
+ "void main()",
+ "{",
+ " gl_Position = a_position;",
+ "}"
+].join('\n');
+
+var fshader_max = [
+ "precision mediump float;",
+ "uniform vec4 colora[$(maxUniformVectors)];",
+ "void main()",
+ "{",
+ " gl_FragColor = vec4(colora[$(usedUniformVector)]);",
+ "}"
+].join('\n');
+
+var fshader_max_ab_ab = [
+ "precision mediump float;",
+ "uniform vec4 $(decl1);",
+ "uniform vec4 $(decl2);",
+ "void main()",
+ "{",
+ "gl_FragColor = vec4($(usage1) + $(usage2));",
+ "}"
+].join('\n');
+
+// MaxInt32 is 2^32-1. We need +1 of that to test overflow conditions
+var MaxInt32PlusOne = 4294967296;
+
+function setupTests(gl) {
+ var tests = [];
+ var maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
+
+ // This test is to test drivers the have bugs related to optimizing
+ // an array of uniforms when only 1 of those uniforms is used.
+ tests.push({
+ desc: "using last element",
+ maxUniformVectors: maxUniformVectors,
+ usedUniformVector: maxUniformVectors - 1,
+ shader: "fshader-max",
+ color: [0, 1, 0, 1],
+ arrayName: "colora",
+ extraName: "colorb",
+ });
+ tests.push({
+ desc: "using first element",
+ maxUniformVectors: maxUniformVectors,
+ usedUniformVector: 0,
+ shader: "fshader-max",
+ color: [0, 1, 0, 1],
+ arrayName: "colora",
+ extraName: "colorb",
+ });
+
+ // Generate test shaders. We're trying to force the driver to
+ // overflow from 1 array into the next if it optimizes. So for example if it was C
+ //
+ // int big[4];
+ // int little[1];
+ // big[5] = 124;
+ //
+ // Would end up setting little[0] instead of big. Some drivers optimize
+ // where if you only use say 'big[3]' it will actually only allocate just 1 element
+ // for big.
+ //
+ // But, some drivers have a bug where the fact that they optimized big to 1 element
+ // does not get passed down to glUniform so when setting the uniform 'big[3]' they
+ // overwrite memory.
+ //
+ // If the driver crashes, yea. We found a bug. We can block the driver.
+ // Otherwise we try various combinations so that setting 'little[0]' first
+ // and then setting all elements of 'big' we hope it will overwrite 'little[0]'
+ // which will show the bug and again we can block the driver.
+ //
+ // We don't know how the driver will order, in memory, the various uniforms
+ // or for that matter we don't even know if they will be contiguous in memory
+ // but to hopefully expose any bugs we try various combinations.
+ //
+ // It could be the compiler orders uniforms alphabetically.
+ // It could be it orders them in order of declaration.
+ // It could be it orders them in order of usage.
+ //
+ // We also test using only first element of big or just the last element of big.
+ //
+ for (var nameOrder = 0; nameOrder < 2; ++nameOrder) {
+ var name1 = nameOrder ? "colora" : "colorb";
+ var name2 = nameOrder ? "colorb" : "colora";
+ for (var last = 0; last < 2; ++last) {
+ var usedUniformVector = last ? maxUniformVectors - 2 : 0;
+ for (var declOrder = 0; declOrder < 2; ++declOrder) {
+ var bigName = declOrder ? name1 : name2;
+ var littleName = declOrder ? name2 : name1;
+ var decl1 = bigName + "[" + (maxUniformVectors - 1) + "]";
+ var decl2 = littleName + "[1]";
+ if (declOrder) {
+ var t = decl1;
+ decl1 = decl2;
+ decl2 = t;
+ }
+ for (var usageOrder = 0; usageOrder < 2; ++usageOrder) {
+ var usage1 = bigName + "[" + usedUniformVector + "]";
+ var usage2 = littleName + "[0]";
+ if (usageOrder) {
+ var t = usage1;
+ usage1 = usage2;
+ usage2 = t;
+ }
+ var fSrc = wtu.replaceParams(fshader_max_ab_ab, {
+ decl1: decl1,
+ decl2: decl2,
+ usage1: usage1,
+ usage2: usage2,
+ });
+ var desc = "testing: " + name1 + ":" + name2 + " using " + (last ? "last" : "first") +
+ " creating uniforms " + decl1 + " " + decl2 + " and accessing " + usage1 + " " + usage2;
+ tests.push({
+ desc: desc,
+ maxUniformVectors: maxUniformVectors - 1,
+ usedUniformVector: usedUniformVector,
+ source: fSrc,
+ color: [0, 0, 0, 1],
+ arrayName: bigName,
+ extraName: littleName,
+ });
+ }
+ }
+ }
+ }
+ return tests;
+};
+
+function testUniformOptimizationIssues(test) {
+ debug("");
+ debug(test.desc);
+ var fshader = test.source;
+ if (!fshader) {
+ fshader = wtu.replaceParams(fshader_max, test);
+ }
+
+ var consoleElem = document.getElementById("console");
+ wtu.addShaderSource(
+ consoleElem, "vertex shader", vshader);
+ wtu.addShaderSource(
+ consoleElem, "fragment shader", fshader);
+
+ var program = wtu.loadProgram(gl, vshader, fshader);
+ gl.useProgram(program);
+
+ var colorbLocation = gl.getUniformLocation(program, test.extraName + "[0]");
+ if (colorbLocation) {
+ gl.uniform4fv(colorbLocation, [0, 1, 0, 0]);
+ }
+
+ // Ensure that requesting an array uniform past MaxInt32PlusOne returns no uniform
+ var nameMaxInt32PlusOne = test.arrayName + "[" + (test.usedUniformVector + MaxInt32PlusOne) + "]";
+ assertMsg(gl.getUniformLocation(program, nameMaxInt32PlusOne) === null,
+ "Requesting " + nameMaxInt32PlusOne + " uniform should return a null uniform location");
+
+ // Set just the used uniform
+ var name = test.arrayName + "[" + test.usedUniformVector + "]";
+ var uniformLocation = gl.getUniformLocation(program, name);
+ gl.uniform4fv(uniformLocation, test.color);
+ wtu.setupIndexedQuad(gl, 1);
+ wtu.clearAndDrawIndexedQuad(gl, 1);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+
+ // Set all the unused uniforms
+ var locations = [];
+ var allRequiredUniformLocationsQueryable = true;
+ for (var ii = 0; ii < test.maxUniformVectors; ++ii) {
+ var name = test.arrayName + "[" + ii + "]";
+ var uniformLocation = gl.getUniformLocation(program, name);
+ locations.push(uniformLocation);
+ if (ii == test.usedUniformVector) {
+ continue;
+ }
+ // Locations > usedUnformVector may not exist.
+ // Locations <= usedUniformVector MUST exist.
+ if (ii <= test.usedUniformVector && (uniformLocation === undefined || uniformLocation === null)) {
+ allRequiredUniformLocationsQueryable = false;
+ }
+ gl.uniform4fv(uniformLocation, [1, 0, 0, 1]);
+ }
+ if (allRequiredUniformLocationsQueryable) {
+ testPassed("allRequiredUniformLocationsQueryable is true.");
+ }
+ else {
+ testFailed("allRequiredUniformLocationsQueryable should be true. Was false.");
+ }
+ var positionLoc = gl.getAttribLocation(program, "a_position");
+ wtu.setupIndexedQuad(gl, 1, positionLoc);
+ wtu.clearAndDrawIndexedQuad(gl, 1);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
+
+ // Check we can read & write each uniform.
+ // Note: uniforms past test.usedUniformVector might not exist.
+ for (var ii = 0; ii < test.maxUniformVectors; ++ii) {
+ gl.uniform4fv(locations[ii], [ii + 4, ii + 2, ii + 3, ii + 1]);
+ }
+
+ var kEpsilon = 0.01;
+ var isSame = function(v1, v2) {
+ return Math.abs(v1 - v2) < kEpsilon;
+ };
+
+ for (var ii = 0; ii < test.maxUniformVectors; ++ii) {
+ var location = locations[ii];
+ if (location) {
+ var value = gl.getUniform(program, locations[ii]);
+ if (!isSame(value[0], ii + 4) ||
+ !isSame(value[1], ii + 2) ||
+ !isSame(value[2], ii + 3) ||
+ !isSame(value[3], ii + 1)) {
+ testFailed("location: " + ii + " was not correct value");
+ break;
+ }
+ }
+ }
+}
+
+function runOneTest(gl, test) {
+ testUniformOptimizationIssues(test);
+};
+
+function runTests(gl, tests) {
+ debug("");
+ debug("Test drivers don't over optimize unused array elements");
+
+ for (var ii = 0; ii < tests.length; ++ii) {
+ runOneTest(gl, tests[ii]);
+ }
+};
+
+return {
+ setupTests : setupTests,
+ runTests : runTests
+};
+
+}());
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 0000000000..362023ce01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js
@@ -0,0 +1,151 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+function testTexLinear(gl, extensionName, internalFormatWebgl2, pixelType) {
+ var wtu = WebGLTestUtils;
+
+ // 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);
+ }
+
+ 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)
+ {
+ const format = gl.RGBA;
+ let internalFormat = format;
+ if (wtu.isWebGL2(gl)) {
+ internalFormat = gl[internalFormatWebgl2];
+ }
+ 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, internalFormat, 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, internalFormat, 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, pixelType + " 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, pixelType + " 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, pixelType + " texture with Linear filter should succeed with NO_ERROR if " + extensionName + " is enabled");
+ }
+
+ wtu.checkCanvas(gl, expected, "should be " + expected[0] + "," + expected[1] + "," + expected[2] + "," + expected[3]);
+ }
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/offscreencanvas-transfer-image-bitmap.js b/dom/canvas/test/webgl-conf/checkout/js/tests/offscreencanvas-transfer-image-bitmap.js
new file mode 100644
index 0000000000..b25a7dd026
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/offscreencanvas-transfer-image-bitmap.js
@@ -0,0 +1,57 @@
+function testTransferToImageBitmap(webglContextVersion, bitmap) {
+ var internalFormat = "RGBA";
+ var pixelFormat = "RGBA";
+ var pixelType = "UNSIGNED_BYTE";
+
+ var width = 32;
+ var height = 32;
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var gl = WebGLTestUtils.create3DContext(canvas);
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ TexImageUtils.setupTexturedQuad(gl, internalFormat);
+
+ 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(gl.TEXTURE_2D, texture);
+ // Set up texture parameters
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ var targets = [gl.TEXTURE_2D];
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], bitmap);
+ }
+ for (var tt = 0; tt < targets.length; ++tt) {
+ // Draw the triangles
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ var buf = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ _checkCanvas(buf, width, height, webglContextVersion);
+ }
+}
+
+function _checkCanvas(buf, width, height, webglContextVersion)
+{
+ for (var i = 0; i < width * height; i++) {
+ if (buf[i * 4] != 255 || buf[i * 4 + 1] != 255 ||
+ buf[i * 4 + 2] != 0 || buf[i * 4 + 3] != 255) {
+ testFailed("OffscreenCanvas." + webglContextVersion +
+ ": This pixel should be [255, 255, 0, 255], but it is: [" + buf[i * 4] + ", " +
+ buf[i * 4 + 1] + ", " + buf[i * 4 + 2] + ", " + buf[i * 4 + 3] + "].");
+ return;
+ }
+ }
+ testPassed("TransferToImageBitmap test on OffscreenCanvas." + webglContextVersion + " passed");
+}
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 0000000000..75e3496dfb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js
@@ -0,0 +1,321 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+'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.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 1}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 10000}));
+ 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.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 3, count: 2}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 10000}));
+ 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.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 10000}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: '0x7fffffff', count: 1}));
+};
+
+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);
+
+
+ debug('');
+ debug('Test null index buffer');
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+
+ debug('');
+ debug('Test empty index buffer');
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, 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.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.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 2}));
+ wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 10000, 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: 10000, type: 'gl.UNSIGNED_BYTE', offset: 10000}));
+
+ 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]))');
+ var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, 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, 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, indexValidationError, wtu.replaceParams(callTemplate, {count: 12, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, indexValidationError, wtu.replaceParams(callTemplate, {count: 15, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, indexValidationError, wtu.replaceParams(callTemplate, {count: 18, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, indexValidationError, 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}));
+
+ 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/ovr_multiview2_util.js b/dom/canvas/test/webgl-conf/checkout/js/tests/ovr_multiview2_util.js
new file mode 100644
index 0000000000..5de4dc88d8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/ovr_multiview2_util.js
@@ -0,0 +1,263 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+"use strict";
+
+function createTextureWithNearestFiltering(target)
+{
+ let texture = gl.createTexture();
+ gl.bindTexture(target, texture);
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
+ return texture;
+}
+
+// Write a transformation matrix to elements of floatArray starting from index.
+// The matrix transforms a unit square (-1 to 1) to a rectangle with the width scaleX and the left edge at offsetX.
+function setupTranslateAndScaleXMatrix(floatArray, index, scaleX, offsetX)
+{
+ // x position is transformed according to this equation: scaleX * x0 + translateX = offsetX
+ // By substituting x0 with -1 (unit square x value for the left edge), we get the following:
+ let translateX = offsetX + scaleX;
+
+ floatArray[index] = scaleX;
+ floatArray[index + 1] = 0.0;
+ floatArray[index + 2] = 0.0;
+ floatArray[index + 3] = 0.0;
+
+ floatArray[index + 4] = 0.0;
+ floatArray[index + 5] = 1.0;
+ floatArray[index + 6] = 0.0;
+ floatArray[index + 7] = 0.0;
+
+ floatArray[index + 8] = 0.0;
+ floatArray[index + 9] = 0.0;
+ floatArray[index + 10] = 1.0;
+ floatArray[index + 11] = 0.0;
+
+ floatArray[index + 12] = translateX;
+ floatArray[index + 13] = 0.0;
+ floatArray[index + 14] = 0.0;
+ floatArray[index + 15] = 1.0;
+}
+
+// Check the currently bound read framebuffer with dimensions <width> x <height>.
+// The framebuffer should be divided into <strips> equally wide vertical strips, with the one indicated by
+// <coloredStripIndex> colored with <expectedStripColor>. The rest of the framebuffer should be colored transparent black.
+// A two pixel wide region at each edge of the colored region is left unchecked to allow for some tolerance for rasterization.
+function checkVerticalStrip(width, height, strips, coloredStripIndex, expectedStripColor, framebufferDescription)
+{
+ let colorRegionLeftEdge = (width / strips) * coloredStripIndex;
+ let colorRegionRightEdge = (width / strips) * (coloredStripIndex + 1);
+ if (coloredStripIndex > 0) {
+ wtu.checkCanvasRect(gl, 0, 0, colorRegionLeftEdge - 1, height, [0, 0, 0, 0], 'the left edge of ' + framebufferDescription + ' should be untouched');
+ }
+ if (coloredStripIndex < strips - 1) {
+ wtu.checkCanvasRect(gl, colorRegionRightEdge + 1, 0, width - colorRegionRightEdge - 1, height, [0, 0, 0, 0], 'the right edge of ' + framebufferDescription + ' should be untouched');
+ }
+ wtu.checkCanvasRect(gl, colorRegionLeftEdge + 1, 0, colorRegionRightEdge - colorRegionLeftEdge - 2, height, expectedStripColor, 'a thin strip in ' + framebufferDescription + ' should be colored ' + expectedStripColor);
+}
+
+function getMultiviewPassthroughVertexShader(views) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+
+ 'layout(num_views = $(num_views)) in;',
+
+ 'in vec4 a_position;',
+
+ 'void main() {',
+ ' gl_Position = a_position;',
+ '}'].join('\n');
+ return wtu.replaceParams(shaderCode, {'num_views': views});
+}
+
+// This shader splits the viewport into <views> equally sized vertical strips.
+// The input quad defined by "a_position" is transformed to fill a different
+// strip in each view.
+function getMultiviewOffsetVertexShader(views) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+
+ 'layout(num_views = $(num_views)) in;',
+
+ 'in vec4 a_position;',
+
+ 'void main() {',
+ ' vec4 pos = a_position;',
+ " // Transform the quad to a thin vertical strip that's offset along the x axis according to the view id.",
+ ' pos.x = (pos.x * 0.5 + 0.5 + float(gl_ViewID_OVR)) * 2.0 / $(num_views).0 - 1.0;',
+ ' gl_Position = pos;',
+ '}'].join('\n');
+ return wtu.replaceParams(shaderCode, {'num_views': views});
+}
+
+// This shader transforms the incoming "a_position" with transforms for each
+// view given in the uniform array "transform".
+function getMultiviewRealisticUseCaseVertexShader(views) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+
+ 'layout(num_views = $(num_views)) in;',
+
+ 'uniform mat4 transform[$(num_views)];',
+ 'in vec4 a_position;',
+
+ 'void main() {',
+ " // Transform the quad with the transformation matrix chosen according to gl_ViewID_OVR.",
+ ' vec4 pos = transform[gl_ViewID_OVR] * a_position;',
+ ' gl_Position = pos;',
+ '}'].join('\n');
+ return wtu.replaceParams(shaderCode, {'num_views': views});
+}
+
+function getMultiviewColorFragmentShader() {
+ return ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+ 'precision highp float;',
+
+ 'out vec4 my_FragColor;',
+
+ 'void main() {',
+ ' uint mask = gl_ViewID_OVR + 1u;',
+ ' my_FragColor = vec4(((mask & 4u) != 0u) ? 1.0 : 0.0,',
+ ' ((mask & 2u) != 0u) ? 1.0 : 0.0,',
+ ' ((mask & 1u) != 0u) ? 1.0 : 0.0,',
+ ' 1.0);',
+ '}'].join('\n');
+}
+
+function getMultiviewColorFragmentShaderForDrawBuffers(drawBuffers) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+ 'precision highp float;',
+
+ 'out vec4 my_FragColor[$(drawBuffers)];',
+
+ 'void main() {',
+ ' uint mask;'];
+
+ for (let i = 0; i < drawBuffers; ++i) {
+ shaderCode.push(wtu.replaceParams(' mask = gl_ViewID_OVR + $(i)u;', {'i': i + 1}));
+ shaderCode.push(wtu.replaceParams(' my_FragColor[$(i)] = vec4(((mask & 4u) != 0u) ? 1.0 : 0.0,', {'i': i}));
+ shaderCode.push(' ((mask & 2u) != 0u) ? 1.0 : 0.0,');
+ shaderCode.push(' ((mask & 1u) != 0u) ? 1.0 : 0.0,');
+ shaderCode.push(' 1.0);');
+ }
+ shaderCode.push('}');
+ shaderCode = shaderCode.join('\n');
+ return wtu.replaceParams(shaderCode, {'drawBuffers' : drawBuffers});
+}
+
+function getMultiviewVaryingVertexShader(views) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+
+ 'layout(num_views = $(num_views)) in;',
+
+ 'in vec4 a_position;',
+ 'out float testVarying;',
+
+ 'void main() {',
+ ' gl_Position = a_position;',
+ ' testVarying = float(gl_ViewID_OVR);',
+ '}'].join('\n');
+ return wtu.replaceParams(shaderCode, {'num_views': views});
+}
+
+function getMultiviewVaryingFragmentShader() {
+ return ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+ 'precision highp float;',
+
+ 'in float testVarying;',
+ 'out vec4 my_FragColor;',
+
+ 'void main() {',
+ ' int mask = int(testVarying + 0.1) + 1;',
+ ' my_FragColor = vec4(((mask & 4) != 0) ? 1.0 : 0.0,',
+ ' ((mask & 2) != 0) ? 1.0 : 0.0,',
+ ' ((mask & 1) != 0) ? 1.0 : 0.0,',
+ ' 1.0);',
+ '}'].join('\n');
+}
+
+function getMultiviewFlatVaryingVertexShader(views) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+
+ 'layout(num_views = $(num_views)) in;',
+
+ 'in vec4 a_position;',
+ 'flat out int testVarying;',
+
+ 'void main() {',
+ ' gl_Position = a_position;',
+ ' testVarying = int(gl_ViewID_OVR);',
+ '}'].join('\n');
+ return wtu.replaceParams(shaderCode, {'num_views': views});
+}
+
+function getMultiviewFlatVaryingFragmentShader() {
+ return ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+ 'precision highp float;',
+
+ 'flat in int testVarying;',
+ 'out vec4 my_FragColor;',
+
+ 'void main() {',
+ ' int mask = testVarying + 1;',
+ ' my_FragColor = vec4(((mask & 4) != 0) ? 1.0 : 0.0,',
+ ' ((mask & 2) != 0) ? 1.0 : 0.0,',
+ ' ((mask & 1) != 0) ? 1.0 : 0.0,',
+ ' 1.0);',
+ '}'].join('\n');
+}
+
+function getMultiviewInstancedVertexShader(views) {
+ let shaderCode = ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+
+ 'layout(num_views = $(num_views)) in;',
+
+ 'in vec4 a_position;',
+ 'out vec4 color;',
+
+ 'void main() {',
+ ' vec4 pos = a_position;',
+ " // Transform the quad to a thin vertical strip that's offset along the x axis according to the view id and instance id.",
+ ' pos.x = (pos.x * 0.5 + 0.5 + float(gl_ViewID_OVR) + float(gl_InstanceID)) * 2.0 / ($(num_views).0 * 2.0) - 1.0;',
+ ' int mask = gl_InstanceID + 1;',
+ ' color = vec4(((mask & 4) != 0) ? 1.0 : 0.0,',
+ ' ((mask & 2) != 0) ? 1.0 : 0.0,',
+ ' ((mask & 1) != 0) ? 1.0 : 0.0,',
+ ' 1.0);',
+ ' gl_Position = pos;',
+ '}'].join('\n');
+ return wtu.replaceParams(shaderCode, {'num_views': views});
+}
+
+function getInstanceColorFragmentShader() {
+ return ['#version 300 es',
+ '#extension GL_OVR_multiview2 : require',
+ 'precision highp float;',
+
+ 'in vec4 color;',
+ 'out vec4 my_FragColor;',
+
+ 'void main() {',
+ ' my_FragColor = color;',
+ '}'].join('\n');
+}
+
+function getExpectedColor(view) {
+ var mask = (view + 1);
+ return [(mask & 4) ? 255 : 0, (mask & 2) ? 255 : 0, (mask & 1) ? 255 : 0, 255];
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/shader-with-non-reserved-words.js b/dom/canvas/test/webgl-conf/checkout/js/tests/shader-with-non-reserved-words.js
new file mode 100644
index 0000000000..561c1385af
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/shader-with-non-reserved-words.js
@@ -0,0 +1,664 @@
+/*
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+async function testNonReservedWords(part, numParts) {
+
+ description(`test shaders using reserved words as identifiers compile ${part} of ${numParts}`);
+
+ const DXWords = [
+ "Buffer",
+ "double",
+ "uint",
+ "half",
+ "dword",
+ "string",
+ "texture",
+ "pixelshader",
+ "vertexshader",
+ "switch",
+ "min16float",
+ "min10float",
+ "min16int",
+ "min12int",
+ "min16uint",
+ "vector",
+ "matrix",
+ "float2",
+ "float3",
+ "float4",
+ "float1x1",
+ "float1x2",
+ "float1x3",
+ "float1x4",
+ "float2x1",
+ "float2x2",
+ "float2x3",
+ "float2x4",
+ "float3x1",
+ "float3x2",
+ "float3x3",
+ "float3x4",
+ "float4x1",
+ "float4x2",
+ "float4x3",
+ "float4x4",
+ "int1x1",
+ "int1x2",
+ "int1x3",
+ "int1x4",
+ "int2x1",
+ "int2x2",
+ "int2x3",
+ "int2x4",
+ "int3x1",
+ "int3x2",
+ "int3x3",
+ "int3x4",
+ "int4x1",
+ "int4x2",
+ "int4x3",
+ "int4x4",
+ "double1x1",
+ "double1x2",
+ "double1x3",
+ "double1x4",
+ "double2x1",
+ "double2x2",
+ "double2x3",
+ "double2x4",
+ "double3x1",
+ "double3x2",
+ "double3x3",
+ "double3x4",
+ "double4x1",
+ "double4x2",
+ "double4x3",
+ "double4x4",
+ "abort",
+ "abs",
+ "acos",
+ "all",
+ "AllMemoryBarrier",
+ "AllMemoryBarrierWithGroupSync",
+ "any",
+ "asdouble",
+ "asfloat",
+ "asin",
+ "asint",
+ "asint",
+ "asuint",
+ "asuint",
+ "atan",
+ "atan2",
+ "ceil",
+ "clamp",
+ "clip",
+ "cos",
+ "cosh",
+ "countbits",
+ "cross",
+ "D3DCOLORtoUBYTE4",
+ "ddx",
+ "ddx_coarse",
+ "ddx_fine",
+ "ddy",
+ "ddy_coarse",
+ "ddy_fine",
+ "degrees",
+ "determinant",
+ "DeviceMemoryBarrier",
+ "DeviceMemoryBarrierWithGroupSync",
+ "distance",
+ "dot",
+ "dst",
+ "errorf",
+ "EvaluateAttributeAtCentroid",
+ "EvaluateAttributeAtSample",
+ "EvaluateAttributeSnapped",
+ "exp",
+ "exp2",
+ "f16tof32",
+ "f32tof16",
+ "faceforward",
+ "firstbithigh",
+ "firstbitlow",
+ "floor",
+ "fma",
+ "fmod",
+ "frac",
+ "frexp",
+ "fwidth",
+ "GetRenderTargetSampleCount",
+ "GetRenderTargetSamplePosition",
+ "GroupMemoryBarrier",
+ "GroupMemoryBarrierWithGroupSync",
+ "InterlockedAdd",
+ "InterlockedAnd",
+ "InterlockedCompareExchange",
+ "InterlockedCompareStore",
+ "InterlockedExchange",
+ "InterlockedMax",
+ "InterlockedMin",
+ "InterlockedOr",
+ "InterlockedXor",
+ "isfinite",
+ "isinf",
+ "isnan",
+ "ldexp",
+ "length",
+ "lerp",
+ "lit",
+ "log",
+ "log10",
+ "log2",
+ "mad",
+ "max",
+ "min",
+ "modf",
+ "msad4",
+ "mul",
+ "noise",
+ "normalize",
+ "pow",
+ "printf",
+ "Process2DQuadTessFactorsAvg",
+ "Process2DQuadTessFactorsMax",
+ "Process2DQuadTessFactorsMin",
+ "ProcessIsolineTessFactors",
+ "ProcessQuadTessFactorsAvg",
+ "ProcessQuadTessFactorsMax",
+ "ProcessQuadTessFactorsMin",
+ "ProcessTriTessFactorsAvg",
+ "ProcessTriTessFactorsMax",
+ "ProcessTriTessFactorsMin",
+ "radians",
+ "rcp",
+ "reflect",
+ "refract",
+ "reversebits",
+ "round",
+ "rsqrt",
+ "saturate",
+ "sign",
+ "sin",
+ "sincos",
+ "sinh",
+ "smoothstep",
+ "sqrt",
+ "step",
+ "tan",
+ "tanh",
+ "tex1D",
+ "tex1D",
+ "tex1Dbias",
+ "tex1Dgrad",
+ "tex1Dlod",
+ "tex1Dproj",
+ "tex2D",
+ "tex2D",
+ "tex2Dbias",
+ "tex2Dgrad",
+ "tex2Dlod",
+ "tex2Dproj",
+ "tex3D",
+ "tex3D",
+ "tex3Dbias",
+ "tex3Dgrad",
+ "tex3Dlod",
+ "tex3Dproj",
+ "texCUBE",
+ "texCUBE",
+ "texCUBEbias",
+ "texCUBEgrad",
+ "texCUBElod",
+ "texCUBEproj",
+ "transpose",
+ "trunc"
+ ];
+
+ const GLSL_4_20_11_words = [
+ "attribute",
+ "const",
+ "uniform",
+ "varying",
+ "coherent",
+ "volatile",
+ "restrict",
+ "readonly",
+ "writeonly",
+ "atomic_uint",
+ "layout",
+ "centroid",
+ "flat",
+ "smooth",
+ "noperspective",
+ "patch",
+ "sample",
+ "break",
+ "continue",
+ "do",
+ "for",
+ "while",
+ "switch",
+ "case",
+ "default",
+ "if",
+ "else",
+ "subroutine",
+ "in",
+ "out",
+ "inout",
+ "float",
+ "double",
+ "int",
+ "void",
+ "bool",
+ "true",
+ "false",
+ "invariant",
+ "discard",
+ "return",
+ "mat2",
+ "mat3",
+ "mat4",
+ "dmat2",
+ "dmat3",
+ "dmat4",
+ "mat2x2",
+ "mat2x3",
+ "mat2x4",
+ "dmat2x2",
+ "dmat2x3",
+ "dmat2x4",
+ "mat3x2",
+ "mat3x3",
+ "mat3x4",
+ "dmat3x2",
+ "dmat3x3",
+ "dmat3x4",
+ "mat4x2",
+ "mat4x3",
+ "mat4x4",
+ "dmat4x2",
+ "dmat4x3",
+ "dmat4x4",
+ "vec2",
+ "vec3",
+ "vec4",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "dvec2",
+ "dvec3",
+ "dvec4",
+ "uint",
+ "uvec2",
+ "uvec3",
+ "uvec4",
+ "lowp",
+ "mediump",
+ "highp",
+ "precision",
+ "sampler1D",
+ "sampler2D",
+ "sampler3D",
+ "samplerCube",
+ "sampler1DShadow",
+ "sampler2DShadow",
+ "samplerCubeShadow",
+ "sampler1DArray",
+ "sampler2DArray",
+ "sampler1DArrayShadow",
+ "sampler2DArrayShadow",
+ "isampler1D",
+ "isampler2D",
+ "isampler3D",
+ "isamplerCube",
+ "isampler1DArray",
+ "isampler2DArray",
+ "usampler1D",
+ "usampler2D",
+ "usampler3D",
+ "usamplerCube",
+ "usampler1DArray",
+ "usampler2DArray",
+ "sampler2DRect",
+ "sampler2DRectShadow",
+ "isampler2DRect",
+ "usampler2DRect",
+ "samplerBuffer",
+ "isamplerBuffer",
+ "usamplerBuffer",
+ "sampler2DMS",
+ "isampler2DMS",
+ "usampler2DMS",
+ "sampler2DMSArray",
+ "isampler2DMSArray",
+ "usampler2DMSArray",
+ "samplerCubeArray",
+ "samplerCubeArrayShadow",
+ "isamplerCubeArray",
+ "usamplerCubeArray",
+ "image1D",
+ "iimage1D",
+ "uimage1D",
+ "image2D",
+ "iimage2D",
+ "uimage2D",
+ "image3D",
+ "iimage3D",
+ "uimage3D",
+ "image2DRect",
+ "iimage2DRect",
+ "uimage2DRect",
+ "imageCube",
+ "iimageCube",
+ "uimageCube",
+ "imageBuffer",
+ "iimageBuffer",
+ "uimageBuffer",
+ "image1DArray",
+ "iimage1DArray",
+ "uimage1DArray",
+ "image2DArray",
+ "iimage2DArray",
+ "uimage2DArray",
+ "imageCubeArray",
+ "iimageCubeArray",
+ "uimageCubeArray",
+ "image2DMS",
+ "iimage2DMS",
+ "uimage2DMS",
+ "image2DMSArray",
+ "iimage2DMSArray",
+ "uimage2DMSArray",
+ "struct"
+ ];
+
+ const GLSL_4_20_11_future_words = [
+ "common",
+ "partition",
+ "active",
+ "asm",
+ "class",
+ "union",
+ "enum",
+ "typedef",
+ "template",
+ "this",
+ "packed",
+ "resource",
+ "goto",
+ "inline",
+ "noinline",
+ "public",
+ "static",
+ "extern",
+ "external",
+ "interface",
+ "long",
+ "short",
+ "half",
+ "fixed",
+ "unsigned",
+ "superp",
+ "input",
+ "output",
+ "hvec2",
+ "hvec3",
+ "hvec4",
+ "fvec2",
+ "fvec3",
+ "fvec4",
+ "sampler3DRect",
+ "filter",
+ "sizeof",
+ "cast",
+ "namespace",
+ "using",
+ "row_major"
+ ];
+
+ const GLSL_1_0_17_words = [
+ "attribute",
+ "const",
+ "uniform",
+ "varying",
+ "break",
+ "continue",
+ "do",
+ "for",
+ "while",
+ "if",
+ "else",
+ "in",
+ "out",
+ "inout",
+ "float",
+ "int",
+ "void",
+ "bool",
+ "true",
+ "false",
+ "lowp",
+ "mediump",
+ "highp",
+ "precision",
+ "invariant",
+ "discard",
+ "return",
+ "mat2",
+ "mat3",
+ "mat4",
+ "vec2",
+ "vec3",
+ "vec4",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "sampler2D",
+ "samplerCube",
+ "struct"
+ ]
+
+ const GLSL_1_0_17_FutureWords = [
+ "asm",
+ "class",
+ "union",
+ "enum",
+ "typedef",
+ "template",
+ "this",
+ "packed",
+ "goto",
+ "switch",
+ "default",
+ "inline",
+ "noinline",
+ "volatile",
+ "public",
+ "static",
+ "extern",
+ "external",
+ "interface",
+ "flat",
+ "long",
+ "short",
+ "double",
+ "half",
+ "fixed",
+ "unsigned",
+ "superp",
+ "input",
+ "output",
+ "hvec2",
+ "hvec3",
+ "hvec4",
+ "dvec2",
+ "dvec3",
+ "dvec4",
+ "fvec2",
+ "fvec3",
+ "fvec4",
+ "sampler1D",
+ "sampler3D",
+ "sampler1DShadow",
+ "sampler2DShadow",
+ "sampler2DRect",
+ "sampler3DRect",
+ "sampler2DRectShadow",
+ "sizeof",
+ "cast",
+ "namespace",
+ "using"
+ ];
+
+ const allBadWords = [
+ ...DXWords,
+ ...GLSL_4_20_11_words,
+ ...GLSL_4_20_11_future_words,
+ ];
+ const numWordsPerPart = Math.ceil(allBadWords.length / numParts);
+ const firstWordNdx = numWordsPerPart * (part - 1);
+ const badWords = allBadWords.slice(firstWordNdx, firstWordNdx + numWordsPerPart);
+ debug(`running tests for words ${firstWordNdx} to ${firstWordNdx + badWords.length - 1} of ${allBadWords.length}`);
+
+ const shaders = {
+ vertexShader0: `
+struct $replaceMe {
+ vec4 $replaceMe;
+};
+struct Foo {
+ $replaceMe $replaceMe;
+};
+attribute vec4 position;
+void main()
+{
+ Foo f;
+ f.$replaceMe.$replaceMe = position;
+ gl_Position = f.$replaceMe.$replaceMe;
+}
+`,
+ fragmentShader0: `
+precision mediump float;
+vec4 $replaceMe() {
+ return vec4(0,1,0,1);
+}
+void main()
+{
+ gl_FragColor = $replaceMe();
+}
+`,
+ vertexShader1: `
+attribute vec4 $replaceMe;
+void main()
+{
+ gl_Position = $replaceMe;
+}
+`,
+ fragmentShader1: `
+precision mediump float;
+vec4 foo(vec4 $replaceMe) {
+ return $replaceMe;
+}
+void main()
+{
+ gl_FragColor = foo(vec4(1,0,1,1));
+}
+`,
+ vertexShader2: `
+varying vec4 $replaceMe;
+attribute vec4 position;
+void main()
+{
+ gl_Position = position;
+ $replaceMe = position;
+}
+`,
+ fragmentShader2: `
+precision mediump float;
+varying vec4 $replaceMe;
+void main()
+{
+ gl_FragColor = $replaceMe;
+}
+`,
+ vertexShader3: `
+attribute vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+`,
+ fragmentShader3: `
+precision mediump float;
+uniform vec4 $replaceMe;
+void main()
+{
+ gl_FragColor = $replaceMe;
+}
+`,
+ };
+
+ const wtu = WebGLTestUtils;
+ const gl = wtu.create3DContext();
+ const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+ const reservedWords = new Set([
+ ...GLSL_1_0_17_words,
+ ...GLSL_1_0_17_FutureWords,
+ ]);
+
+ const checkedWords = new Set();
+
+ const src = [];
+ for (let ii = 0; ii < 4; ++ii) {
+ const vSrc = shaders[`vertexShader${ii}`];
+ const fSrc = shaders[`fragmentShader${ii}`];
+ src.push({vSrc: vSrc, fSrc: fSrc});
+ }
+
+ for (const badWord of badWords) {
+ testWord(badWord);
+ await wait();
+ }
+ finishTest();
+
+ function testWord(word) {
+ if (reservedWords.has(word) || checkedWords.has(word)) {
+ return;
+ }
+ checkedWords.add(word);
+ debug("");
+ debug(`testing: ${word}`);
+
+ for (let ii = 0; ii < src.length; ++ii) {
+ const vs = src[ii].vSrc.replace(/\$replaceMe/g, word);
+ const fs = src[ii].fSrc.replace(/\$replaceMe/g, word);
+
+ let success = true;
+ const program = wtu.loadProgram(gl, vs, fs, function(msg) {
+ debug(msg);
+ success = false;
+ }, true);
+ if (success) {
+ testPassed(`shader with: '${word}' compiled`);
+ } else {
+ testFailed(`shader with: '${word}' failed to compile`);
+ }
+ if (program) {
+ gl.deleteProgram(program);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no GL errors");
+ }
+ }
+} \ No newline at end of file
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 0000000000..792f832451
--- /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,292 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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;
+
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 0, 0];
+ break;
+
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ greenColor = [0, 0, 0];
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 0, 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;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ }
+
+ // 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;
+
+ 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]);
+
+ var msg = 'should be ' + expected;
+ wtu.checkCanvasRect(gl, 0, 0, outputCanvasWidth, outputCanvasHeight, 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);
+ 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 0000000000..a96eeb9de0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js
@@ -0,0 +1,468 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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, 255];
+ var greenColor = [0, 255, 0, 255];
+ var semiTransparentRedColor = [127, 0, 0, 127];
+ var semiTransparentGreenColor = [0, 127, 0, 127];
+ var repeatCount;
+
+ function replicateRedChannel(color)
+ {
+ color[1] = color[0];
+ color[2] = color[0];
+ }
+
+ function zapColorChannels(color)
+ {
+ color[0] = 0;
+ color[1] = 0;
+ color[2] = 0;
+ }
+
+ function setAlphaChannelTo1(color)
+ {
+ color[3] = 255;
+ }
+
+ function replicateAllRedChannels()
+ {
+ replicateRedChannel(redColor);
+ replicateRedChannel(semiTransparentRedColor);
+ replicateRedChannel(greenColor);
+ replicateRedChannel(semiTransparentGreenColor);
+ }
+
+ function setAllAlphaChannelsTo1()
+ {
+ setAlphaChannelTo1(redColor);
+ setAlphaChannelTo1(semiTransparentRedColor);
+ setAlphaChannelTo1(greenColor);
+ setAlphaChannelTo1(semiTransparentGreenColor);
+ }
+
+ function repeatCountForTextureFormat(internalFormat, pixelFormat, pixelType)
+ {
+ // There were bugs in early WebGL 1.0 implementations when repeatedly uploading canvas
+ // elements into textures. In response, this test was changed into a regression test by
+ // repeating all of the cases multiple times. Unfortunately, this means that adding a new
+ // case above significantly increases the run time of the test suite. The problem is made
+ // even worse by the addition of many more texture formats in WebGL 2.0.
+ //
+ // Doing repeated runs with just a couple of WebGL 1.0's supported texture formats acts as a
+ // sufficient regression test for the old bugs. For this reason the test has been changed to
+ // only repeat for those texture formats.
+ if ((internalFormat == 'RGBA' && pixelFormat == 'RGBA' && pixelType == 'UNSIGNED_BYTE') ||
+ (internalFormat == 'RGB' && pixelFormat == 'RGB' && pixelType == 'UNSIGNED_BYTE')) {
+ return 4;
+ }
+
+ return 1;
+ }
+
+ 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;
+ }
+
+ repeatCount = repeatCountForTextureFormat(internalFormat, pixelFormat, pixelType);
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ // Zap green and blue channels.
+ whiteColor[1] = 0;
+ whiteColor[2] = 0;
+ greenColor[1] = 0;
+ semiTransparentGreenColor[1] = 0;
+ // Alpha channel is 1.0.
+ setAllAlphaChannelsTo1();
+ break;
+ case gl.RG:
+ case gl.RG_INTEGER:
+ // Zap blue channel.
+ whiteColor[2] = 0;
+ // Alpha channel is 1.0.
+ setAllAlphaChannelsTo1();
+ break;
+ case gl.LUMINANCE:
+ // Replicate red channels.
+ replicateAllRedChannels();
+ // Alpha channel is 1.0.
+ setAllAlphaChannelsTo1();
+ break;
+ case gl.ALPHA:
+ // Red, green and blue channels are all 0.0.
+ zapColorChannels(redColor);
+ zapColorChannels(semiTransparentRedColor);
+ zapColorChannels(greenColor);
+ zapColorChannels(semiTransparentGreenColor);
+ zapColorChannels(whiteColor);
+ break;
+ case gl.LUMINANCE_ALPHA:
+ // Replicate red channels.
+ replicateAllRedChannels();
+ break;
+ case gl.RGB:
+ case gl.RGB_INTEGER:
+ // Alpha channel is 1.0.
+ setAllAlphaChannelsTo1();
+ break;
+ default:
+ break;
+ }
+
+ switch (gl[internalFormat]) {
+ case gl.SRGB8:
+ case gl.SRGB8_ALPHA8:
+ semiTransparentRedColor = wtu.sRGBToLinear(semiTransparentRedColor);
+ semiTransparentGreenColor = wtu.sRGBToLinear(semiTransparentGreenColor);
+ break;
+ case gl.RGBA8UI:
+ // For int and uint textures, TexImageUtils outputs the maximum value (in this case,
+ // 255) for the alpha channel all the time because of differences in behavior when
+ // sampling integer textures with and without alpha channels. Since changing this
+ // behavior may have large impact across the test suite, leave it as is for now.
+ setAllAlphaChannelsTo1();
+ 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.clearRect(0, 0, width, height);
+ ctx.fillStyle = "#ff0000";
+ ctx.fillRect(0, 0, width, halfHeight);
+ ctx.fillStyle = "#00ff00";
+ ctx.fillRect(0, halfHeight, width, height - halfHeight);
+ }
+
+ function setCanvasToSemiTransparentRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ ctx.clearRect(0, 0, width, height);
+ ctx.fillStyle = "rgba(127, 0, 0, 0.5)";
+ ctx.fillRect(0, 0, width, halfHeight);
+ ctx.fillStyle = "rgba(0, 127, 0, 0.5)";
+ 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 setCanvasTo257x257SemiTransparent(ctx, bindingTarget) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToSemiTransparentRedGreen(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 setCanvasToMinSemiTransparent(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;
+ setCanvasToSemiTransparentRedGreen(ctx);
+ }
+
+ function runOneIteration(canvas, useTexSubImage2D, flipY, semiTransparent, program, bindingTarget, opt_texture, opt_fontTest)
+ {
+ var objType = 'canvas';
+ if (canvas.transferToImageBitmap)
+ objType = 'OffscreenCanvas';
+ 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 +
+ ' source object type: ' + objType +
+ (opt_fontTest ? " with fonts" : " with" + (semiTransparent ? " semi-transparent" : "") + " 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;
+ 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, 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 {
+ var localRed = semiTransparent ? semiTransparentRedColor : redColor;
+ var localGreen = semiTransparent ? semiTransparentGreenColor : greenColor;
+
+ // Allow a tolerance for premultiplication/unmultiplication, especially for texture
+ // formats with lower bit depths.
+ var tolerance = 0;
+ if (semiTransparent) {
+ tolerance = 3;
+ if (pixelType == 'UNSIGNED_SHORT_5_6_5' || internalFormat == 'RGB565') {
+ tolerance = 6;
+ } else if (pixelType == 'UNSIGNED_SHORT_4_4_4_4' || internalFormat == 'RGBA4') {
+ tolerance = 9;
+ } else if (pixelType == 'UNSIGNED_SHORT_5_5_5_1' || internalFormat == 'RGB5_A1') {
+ // Semi-transparent values are allowed to convert to either 1 or 0 for this
+ // single-bit alpha format per OpenGL ES 3.0.5 section 2.1.6.2, "Conversion
+ // from Floating-Point to Normalized Fixed-Point". Ignore alpha for these
+ // tests.
+ tolerance = 6;
+ localRed = localRed.slice(0, 3);
+ localGreen = localGreen.slice(0, 3);
+ } else if (internalFormat == 'RGB10_A2') {
+ // The alpha channel is too low-resolution for any meaningful comparisons.
+ localRed = localRed.slice(0, 3);
+ localGreen = localGreen.slice(0, 3);
+ }
+ }
+
+ // 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, localRed,
+ "shouldBe " + localRed, tolerance);
+ debug("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, 0, top, width, halfHeight, localGreen,
+ "shouldBe " + localGreen, tolerance);
+ }
+
+ 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()
+ {
+ var canvas = document.createElement('canvas');
+
+ var cases = [
+ { canvas: canvas, sub: false, flipY: true, semiTransparent: false, font: false, init: setCanvasToMin },
+ { canvas: canvas, sub: false, flipY: false, semiTransparent: false, font: false },
+ { canvas: canvas, sub: true, flipY: true, semiTransparent: false, font: false },
+ { canvas: canvas, sub: true, flipY: false, semiTransparent: false, font: false },
+ { canvas: canvas, sub: false, flipY: true, semiTransparent: true, font: false, init: setCanvasToMinSemiTransparent },
+ { canvas: canvas, sub: false, flipY: false, semiTransparent: true, font: false },
+ { canvas: canvas, sub: true, flipY: true, semiTransparent: true, font: false },
+ { canvas: canvas, sub: true, flipY: false, semiTransparent: true, font: false },
+ { canvas: canvas, sub: false, flipY: true, semiTransparent: false, font: false, init: setCanvasTo257x257 },
+ { canvas: canvas, sub: false, flipY: false, semiTransparent: false, font: false },
+ { canvas: canvas, sub: true, flipY: true, semiTransparent: false, font: false },
+ { canvas: canvas, sub: true, flipY: false, semiTransparent: false, font: false },
+ { canvas: canvas, sub: false, flipY: true, semiTransparent: true, font: false, init: setCanvasTo257x257SemiTransparent },
+ { canvas: canvas, sub: false, flipY: false, semiTransparent: true, font: false },
+ { canvas: canvas, sub: true, flipY: true, semiTransparent: true, font: false },
+ { canvas: canvas, sub: true, flipY: false, semiTransparent: true, font: false },
+ ];
+
+ // The font tests don't work with ALPHA-only textures since they draw to the color channels.
+ if (internalFormat != 'ALPHA') {
+ cases = cases.concat([
+ { canvas: canvas, sub: false, flipY: true, semiTransparent: false, font: true, init: drawTextInCanvas },
+ { canvas: canvas, sub: false, flipY: false, semiTransparent: false, font: true },
+ { canvas: canvas, sub: true, flipY: true, semiTransparent: false, font: true },
+ { canvas: canvas, sub: true, flipY: false, semiTransparent: false, font: true },
+ ]);
+ }
+
+ if (window.OffscreenCanvas) {
+ var offscreenCanvas = new OffscreenCanvas(1, 1);
+ cases = cases.concat([
+ { canvas: offscreenCanvas, sub: false, flipY: true, semiTransparent: false, font: false, init: setCanvasToMin },
+ { canvas: offscreenCanvas, sub: false, flipY: false, semiTransparent: false, font: false },
+ { canvas: offscreenCanvas, sub: true, flipY: true, semiTransparent: false, font: false },
+ { canvas: offscreenCanvas, sub: true, flipY: false, semiTransparent: false, font: false },
+ { canvas: offscreenCanvas, sub: false, flipY: true, semiTransparent: true, font: false, init: setCanvasToMinSemiTransparent },
+ { canvas: offscreenCanvas, sub: false, flipY: false, semiTransparent: true, font: false },
+ { canvas: offscreenCanvas, sub: true, flipY: true, semiTransparent: true, font: false },
+ { canvas: offscreenCanvas, sub: true, flipY: false, semiTransparent: true, font: 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 = repeatCount;
+ var caseNdx = 0;
+ var texture = undefined;
+ function runNextTest() {
+ var c = cases[caseNdx];
+ var imageDataBefore = null;
+ if (c.init) {
+ c.init(c.canvas.getContext('2d'), bindingTarget);
+ }
+ texture = runOneIteration(c.canvas, c.sub, c.flipY, c.semiTransparent, program, bindingTarget, texture, c.font);
+ // 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;
+ }
+ }
+ // While we are working with Canvases, it's really unlikely that
+ // waiting for composition will change anything here, and it's much
+ // slower, so just dispatchPromise. If we want to test with composites,
+ // we should test a more narrow subset of tests.
+ wtu.dispatchPromise(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 0000000000..f434b9834c
--- /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,49 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ async 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);
+
+ debug('*** Running tests against red-green-semi-transparent.png ***');
+ let response = await fetch(resourcePath + "red-green-semi-transparent.png");
+ let blob = await response.blob();
+ await runImageBitmapTest(blob, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ debug('*** Running tests against red-green-128x128-linear-profile.jpg ***');
+ response = await fetch(resourcePath + "red-green-128x128-linear-profile.jpg");
+ blob = await response.blob();
+ // This test requires a huge tolerance because browsers - at least currently - vary
+ // widely in the colorspace conversion results for this image.
+ let tolerance = 120;
+ await runImageBitmapTest(blob, 1.0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false, tolerance);
+ 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 0000000000..08ee96c0a1
--- /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,74 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ .then(() => {
+ setCanvasTo257x257(ctx);
+ return runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ }).then(() => {
+ 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 0000000000..09821d8b3f
--- /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,56 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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"})
+ .catch( () => {
+ testPassed("createImageBitmap with options may be rejected if it is not supported. Retrying without options.");
+ return createImageBitmap(imageData);
+ }).then( bitmap => {
+ return runImageBitmapTest(bitmap, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ }, () => {
+ testFailed("createImageBitmap(imageData) should succeed.");
+ }).then(() => {
+ 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 0000000000..dd24721fe4
--- /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,49 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ .then(() => {
+ 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 0000000000..1e4b18129e
--- /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,46 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ .then(() => {
+ 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 0000000000..14cf4628be
--- /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,83 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ 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.bt601.vp9.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 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 videoNdx = 0;
+ var video;
+ function runNextVideo() {
+ if (video) {
+ video.pause();
+ }
+
+ if (videoNdx == videos.length) {
+ finishTest();
+ return;
+ }
+
+ var info = videos[videoNdx++];
+ debug("");
+ debug("testing: " + info.type);
+ video = document.createElement("video");
+ video.muted = true;
+ 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, async function() {
+ await runImageBitmapTest(video, 1, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ runNextVideo();
+ });
+ }
+ runNextVideo();
+ }
+
+ 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 0000000000..8486b0b659
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js
@@ -0,0 +1,240 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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;
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ break;
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ 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;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ }
+
+ 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);
+ wtu.checkCanvasRect(gl, right, top, halfWidth, halfHeight, tr, "shouldBe " + tr);
+ wtu.checkCanvasRect(gl, left, bottom, halfWidth, halfHeight, bl, "shouldBe " + bl);
+ 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 0000000000..f3802ba777
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js
@@ -0,0 +1,257 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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;
+
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ break;
+
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ 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 0000000000..5cc6a8283e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js
@@ -0,0 +1,140 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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;
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ break;
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ 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 0000000000..6e8bcf96e9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js
@@ -0,0 +1,291 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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;
+
+ // 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.bt601.vp9.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;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ runTest();
+ }
+
+ function runOneIteration(videoElement, unpackColorSpace, useTexSubImage2D, flipY, topColorName, bottomColorName, sourceSubRectangle, program, bindingTarget)
+ {
+ sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle;
+ }
+ unpackColorSpaceString = '';
+ if (unpackColorSpace) {
+ unpackColorSpaceString = ' unpackColorSpace=' + unpackColorSpace;
+ }
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ sourceSubRectangleString + unpackColorSpaceString);
+ 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 target color space.
+ if (unpackColorSpace) {
+ gl.unpackColorSpace = unpackColorSpace;
+ }
+ // 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");
+ }
+
+ // Compute the test colors. This test only tests RGB (not A).
+ const topColor = wtu.colorAsSampledWithInternalFormat(
+ wtu.namedColorInColorSpace(topColorName, unpackColorSpace),
+ internalFormat).slice(0, 3);
+ const bottomColor = wtu.colorAsSampledWithInternalFormat(
+ wtu.namedColorInColorSpace(bottomColorName, unpackColorSpace),
+ internalFormat).slice(0, 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 a few pixels near the top and bottom and make sure they have
+ // the right color.
+ const tolerance = Math.max(6, tiu.tolerance(internalFormat, pixelFormat, pixelType));
+ 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: 'Red', bottomColor: 'Green' },
+ { sub: false, flipY: false, topColor: 'Green', bottomColor: 'Red' },
+ { sub: true, flipY: true, topColor: 'Red', bottomColor: 'Green' },
+ { sub: true, flipY: false, topColor: 'Green', bottomColor: 'Red' },
+ ];
+
+ if (wtu.getDefault3DContextVersion() > 1) {
+ cases = cases.concat([
+ { sub: false, flipY: false, topColor: 'Red', bottomColor: 'Red',
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: false, flipY: true, topColor: 'Green', bottomColor: 'Green',
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: false, flipY: false, topColor: 'Green', bottomColor: 'Green',
+ sourceSubRectangle: [20, 80, 40, 32] },
+ { sub: false, flipY: true, topColor: 'Red', bottomColor: 'Red',
+ sourceSubRectangle: [20, 80, 40, 32] },
+ { sub: true, flipY: false, topColor: 'Red', bottomColor: 'Red',
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: true, flipY: true, topColor: 'Green', bottomColor: 'Green',
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: true, flipY: false, topColor: 'Green', bottomColor: 'Green',
+ sourceSubRectangle: [20, 80, 40, 32] },
+ { sub: true, flipY: true, topColor: 'Red', bottomColor: 'Red',
+ sourceSubRectangle: [20, 80, 40, 32] },
+ ]);
+ }
+
+ cases = tiu.crossProductTestCasesWithUnpackColorSpaces(
+ cases, tiu.unpackColorSpacesToTest(gl));
+
+ 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");
+ video.muted = true;
+ 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].unpackColorSpace, 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 0000000000..acb8768051
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js
@@ -0,0 +1,298 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+"use strict";
+
+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, 255];
+ var greenColor = [0, 255, 0, 255];
+ var repeatCount;
+
+ function shouldRepeatTestForTextureFormat(internalFormat, pixelFormat, pixelType)
+ {
+ // There were bugs in early WebGL 1.0 implementations when repeatedly uploading canvas
+ // elements into textures. In response, this test was changed into a regression test by
+ // repeating all of the cases multiple times. Unfortunately, this means that adding a new
+ // case above significantly increases the run time of the test suite. The problem is made
+ // even worse by the addition of many more texture formats in WebGL 2.0.
+ //
+ // Doing repeated runs with just a couple of WebGL 1.0's supported texture formats acts as a
+ // sufficient regression test for the old bugs. For this reason the test has been changed to
+ // only repeat for those texture formats.
+ return ((internalFormat == 'RGBA' && pixelFormat == 'RGBA' && pixelType == 'UNSIGNED_BYTE') ||
+ (internalFormat == 'RGB' && pixelFormat == 'RGB' && pixelType == 'UNSIGNED_BYTE'));
+ }
+
+ async 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)) {
+ return;
+ }
+
+ repeatCount = (shouldRepeatTestForTextureFormat(internalFormat, pixelFormat, pixelType) ? 4 : 1);
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ break;
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ await runTest();
+ }
+
+ function setCanvasToRedGreen(ctx, hasAlpha) {
+ 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);
+ if (hasAlpha) {
+ ctx.clearColor(1.0, 0, 0, 1.0);
+ } else {
+ // The WebGL implementation is responsible for making all
+ // alpha values appear as though they were 1.0.
+ ctx.clearColor(1.0, 0, 0, 0.0);
+ }
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(0, halfHeight, width, height - halfHeight);
+ if (hasAlpha) {
+ ctx.clearColor(0.0, 1.0, 0, 1.0);
+ } else {
+ // The WebGL implementation is responsible for making all
+ // alpha values appear as though they were 1.0.
+ ctx.clearColor(0.0, 1.0, 0, 0.0);
+ }
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.disable(ctx.SCISSOR_TEST);
+ }
+
+ function setCanvasTo257x257(ctx, bindingTarget, hasAlpha) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx, hasAlpha);
+ }
+
+ function setCanvasToMin(ctx, bindingTarget, hasAlpha) {
+ 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, hasAlpha);
+ }
+
+ function runOneIteration(canvas, useTexSubImage2D, alpha, flipY, program, bindingTarget, opt_texture)
+ {
+ var objType = 'canvas';
+ if (canvas.transferToImageBitmap)
+ objType = 'OffscreenCanvas';
+ else if (canvas.parentNode)
+ objType = 'canvas attached to DOM';
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + ' with alpha=' +
+ alpha + ' flipY=' + flipY + ' source object: ' + objType +
+ ' 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
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors before pixelStorei setup");
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after setting UNPACK_FLIP_Y_WEBGL");
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after setting UNPACK_PREMULTIPLY_ALPHA_WEBGL");
+ gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors after setting UNPACK_COLORSPACE_CONVERSION_WEBGL");
+ 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;
+ 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, 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;
+ }
+
+ async function runTest()
+ {
+ for (let alpha of [ true, false ]) {
+ let ctx = wtu.create3DContext(null, { alpha:alpha });
+ let canvas = ctx.canvas;
+ // Note: We use preserveDrawingBuffer:true to prevent canvas
+ // visibility from interfering with the tests.
+ let visibleCtx = wtu.create3DContext(null, { preserveDrawingBuffer:true, alpha:alpha });
+ if (!visibleCtx) {
+ testFailed("context does not exist");
+ return;
+ }
+ let visibleCanvas = visibleCtx.canvas;
+ let descriptionNode = document.getElementById("description");
+ document.body.insertBefore(visibleCanvas, descriptionNode);
+
+ let cases = [
+ { sub: false, flipY: true, ctx: ctx, init: setCanvasToMin },
+ { sub: false, flipY: false, ctx: ctx },
+ { sub: true, flipY: true, ctx: ctx },
+ { sub: true, flipY: false, ctx: ctx },
+ { sub: false, flipY: true, ctx: ctx, init: setCanvasTo257x257 },
+ { sub: false, flipY: false, ctx: ctx },
+ { sub: true, flipY: true, ctx: ctx },
+ { sub: true, flipY: false, ctx: ctx },
+ { sub: false, flipY: true, ctx: visibleCtx, init: setCanvasToMin },
+ { sub: false, flipY: false, ctx: visibleCtx },
+ { sub: true, flipY: true, ctx: visibleCtx },
+ { sub: true, flipY: false, ctx: visibleCtx },
+ ];
+
+ if (window.OffscreenCanvas) {
+ let offscreen = new OffscreenCanvas(1, 1);
+ let offscreenCtx = wtu.create3DContext(offscreen, { alpha:alpha });
+ cases = cases.concat([
+ { sub: false, flipY: true, ctx: offscreenCtx, init: setCanvasToMin },
+ { sub: false, flipY: false, ctx: offscreenCtx },
+ { sub: true, flipY: true, ctx: offscreenCtx },
+ { sub: true, flipY: false, ctx: offscreenCtx },
+ ]);
+ }
+
+ async function runTexImageTest(bindingTarget) {
+ let program;
+ if (bindingTarget == gl.TEXTURE_2D) {
+ program = tiu.setupTexturedQuad(gl, internalFormat);
+ } else {
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ }
+
+ let count = repeatCount;
+ let caseNdx = 0;
+ let texture = undefined;
+ while (true) {
+ let c = cases[caseNdx];
+ if (c.init) {
+ c.init(c.ctx, bindingTarget, alpha);
+ }
+ texture = runOneIteration(c.ctx.canvas, c.sub, alpha, c.flipY, program, bindingTarget, texture);
+ // 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)
+ return;
+ }
+ await wtu.dispatchPromise(function() {});
+ }
+ }
+
+ await runTexImageTest(gl.TEXTURE_2D);
+ await runTexImageTest(gl.TEXTURE_CUBE_MAP);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ }
+
+ return function() {
+ init().then(function(val) {
+ finishTest();
+ });
+ };
+}
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 0000000000..85f763a0de
--- /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,287 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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 0000000000..c41cc4e897
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js
@@ -0,0 +1,226 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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);
+
+ runTest();
+ }
+
+ 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)
+ {
+ var objType = 'canvas';
+ if (canvas.transferToImageBitmap)
+ objType = 'OffscreenCanvas';
+ debug('Testing ' + ' with flipY=' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ ' source object: ' + objType + ' 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 canvas = document.createElement('canvas');
+
+ var cases = [
+ { canvas: canvas, flipY: true, font: false, init: setCanvasToMin },
+ { canvas: canvas, flipY: false, font: false },
+ { canvas: canvas, flipY: true, font: false, init: setCanvasTo257x257 },
+ { canvas: canvas, flipY: false, font: false },
+ { canvas: canvas, flipY: true, font: true, init: drawTextInCanvas },
+ { canvas: canvas, flipY: false, font: true },
+ ];
+
+ if (window.OffscreenCanvas) {
+ var offscreenCanvas = new OffscreenCanvas(1, 1);
+ cases = cases.concat([
+ { canvas: offscreenCanvas, flipY: true, font: false, init: setCanvasToMin },
+ { canvas: offscreenCanvas, flipY: false, font: false },
+ ]);
+ }
+
+ 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(c.canvas.getContext('2d'), bindingTarget);
+ }
+ texture = runOneIteration(c.canvas, c.flipY, program, bindingTarget, texture, c.font);
+ // 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_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 0000000000..b55bdcb143
--- /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,48 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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.onload = function() {
+ var blob = xhr.response;
+ runImageBitmapTest(blob, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true)
+ .then(() => {
+ finishTest();
+ });
+ };
+ xhr.send();
+ }
+
+ 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 0000000000..805298b377
--- /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,74 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ .then(() => {
+ setCanvasTo257x257(ctx);
+ return runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ }).then(() => {
+ 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 0000000000..44c9ffa378
--- /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,56 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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"})
+ .catch( () => {
+ testPassed("createImageBitmap with options may be rejected if it is not supported. Retrying without options.");
+ return createImageBitmap(imageData);
+ }).then( bitmap => {
+ return runImageBitmapTest(bitmap, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ }, () => {
+ testFailed("createImageBitmap(imageData) should succeed.");
+ }).then(() => {
+ 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 0000000000..cca0358e17
--- /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,49 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ .then(() => {
+ 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 0000000000..0f1121bbb9
--- /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,45 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ .then(() => {
+ 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 0000000000..a268f7d8d5
--- /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,83 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ 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.bt601.vp9.webm", type: 'video/webm; codecs="vp9"', },
+ { src: resourcePath + "red-green.theora.ogv" , type: 'video/ogg; codecs="theora, vorbis"', },
+ ];
+
+ 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);
+
+ var videoNdx = 0;
+ var video;
+ function runNextVideo() {
+ if (video) {
+ video.pause();
+ }
+
+ if (videoNdx == videos.length) {
+ finishTest();
+ return;
+ }
+
+ var info = videos[videoNdx++];
+ debug("");
+ debug("testing: " + info.type);
+ video = document.createElement("video");
+ video.muted = true;
+ 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, async function() {
+ await runImageBitmapTest(video, 1, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ runNextVideo();
+ });
+ }
+ runNextVideo();
+ }
+
+ 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 0000000000..bedf51a96a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js
@@ -0,0 +1,259 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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 0000000000..034bd8ab46
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js
@@ -0,0 +1,260 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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 0000000000..09a108dee8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js
@@ -0,0 +1,104 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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 0000000000..0c2c40e8a5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js
@@ -0,0 +1,244 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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.bt601.vp9.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.
+ const tolerance = 6;
+ 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");
+ video.muted = true;
+ 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 0000000000..fe14b0c8eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js
@@ -0,0 +1,212 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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)
+ {
+ var objType = 'canvas';
+ if (canvas.transferToImageBitmap)
+ objType = 'OffscreenCanvas';
+ else if (canvas.parentNode)
+ objType = 'canvas attached to DOM';
+ debug('Testing flipY=' + flipY + ' object type: ' + objType +
+ ' 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;
+ // Note: We use preserveDrawingBuffer:true to prevent canvas
+ // visibility from interfering with the tests.
+ var visibleCtx = wtu.create3DContext(null, { preserveDrawingBuffer:true });
+ var visibleCanvas = visibleCtx.canvas;
+ var descriptionNode = document.getElementById("description");
+ document.body.insertBefore(visibleCanvas, descriptionNode);
+
+ var cases = [
+ { flipY: true, ctx: ctx, init: setCanvasToMin },
+ { flipY: false, ctx: ctx },
+ { flipY: true, ctx: ctx, init: setCanvasTo257x257 },
+ { flipY: false, ctx: ctx },
+ { flipY: true, ctx: visibleCtx, init: setCanvasToMin},
+ { flipY: false, ctx: visibleCtx },
+ ];
+
+ if (window.OffscreenCanvas) {
+ var offscreen = new OffscreenCanvas(1, 1);
+ var offscreenCtx = wtu.create3DContext(offscreen);
+ cases = cases.concat([
+ { flipY: true, ctx: offscreenCtx, init: setCanvasToMin },
+ { flipY: false, ctx: offscreenCtx },
+ ]);
+ }
+
+ 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(c.ctx, bindingTarget);
+ }
+ texture = runOneIteration(c.ctx.canvas, c.flipY, program, bindingTarget, texture);
+ // 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_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 0000000000..f37f12fe91
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js
@@ -0,0 +1,865 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+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 highp 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 highp 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 a list of unpack color spaces to test, supported by the specified
+ * WebGLRenderingContext.
+ */
+ var unpackColorSpacesToTest = function(gl)
+ {
+ if ('unpackColorSpace' in gl)
+ return ['srgb', 'display-p3'];
+ else
+ return [undefined];
+ }
+
+ /**
+ * For each entry in unpackColorSpaces, duplicate all of cases, adding an
+ * unpackColorSpace key with its value set to that entry to each case.
+ */
+ var crossProductTestCasesWithUnpackColorSpaces = function(testCaseList, unpackColorSpaces)
+ {
+ var testCaseWithUnpackColorSpace = function(testCase, colorSpace)
+ {
+ return {...testCase, ...{unpackColorSpace:colorSpace}};
+ }
+ var listOfTestCaseLists = unpackColorSpaces.map(colorSpace =>
+ testCaseList.map(testCase => testCaseWithUnpackColorSpace(testCase, colorSpace)));
+ return listOfTestCaseLists.flat();
+ }
+
+ /**
+ * Given given an internalformat, format, and type, return the tolerance
+ * that should be used when comparing an input 8-bit value to one that has
+ * been truncated through the specified formats.
+ */
+ var tolerance = function(internalformat, format, type) {
+ function typeTolerance(type) {
+ switch(type) {
+ case 'UNSIGNED_SHORT_5_6_5':
+ case 'UNSIGNED_SHORT_5_5_5_1':
+ return 255 / 31;
+ case 'UNSIGNED_SHORT_4_4_4_4':
+ return 255 / 15;
+ break;
+ default:
+ return 1;
+ }
+ };
+ function formatTolerance(format) {
+ switch(format) {
+ case 'RGB565':
+ case 'RGB5_A1':
+ return 255/31;
+ case 'RGBA4':
+ return 255/15;
+ default:
+ return 1;
+ }
+ };
+ return Math.max(formatTolerance(internalformat),
+ formatTolerance(format),
+ typeTolerance(type));
+ }
+
+ return {
+ setupTexturedQuad: setupTexturedQuad,
+ setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
+ setupTexturedQuadWith3D: setupTexturedQuadWith3D,
+ setupTexturedQuadWith2DArray: setupTexturedQuadWith2DArray,
+ unpackColorSpacesToTest: unpackColorSpacesToTest,
+ crossProductTestCasesWithUnpackColorSpaces: crossProductTestCasesWithUnpackColorSpaces,
+ tolerance: tolerance
+ };
+
+}());
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 0000000000..8faedf9eaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js
@@ -0,0 +1,435 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+
+function runOneIterationImageBitmapTest(useTexSubImage, bindingTarget, program, bitmap, flipY, premultiplyAlpha, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance)
+{
+ 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;
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ halfRed = [128, 128, 128];
+ halfGreen = [0, 0, 0];
+ break;
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ greenColor = [0, 0, 0];
+ halfRed = [0, 0, 0];
+ halfGreen = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ switch (gl[internalFormat]) {
+ case gl.SRGB8:
+ case gl.SRGB8_ALPHA8:
+ halfRed = wtu.sRGBToLinear(halfRed);
+ halfGreen = wtu.sRGBToLinear(halfGreen);
+ 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("Start uploading the image into a 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 into texture completed");
+
+ var width = gl.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var quarterWidth = Math.floor(halfWidth / 2);
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ var quarterHeight = Math.floor(halfHeight / 2);
+
+ var top = flipY ? quarterHeight : (height - halfHeight + quarterHeight);
+ var bottom = flipY ? (height - halfHeight + quarterHeight) : quarterHeight;
+ var left = quarterWidth;
+ var right = halfWidth + quarterWidth / 2;
+
+ 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;
+ 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 the top pixel and bottom pixel and make sure they have
+ // the right color.
+ let skipAlphaTests = (premultiplyAlpha === undefined && optionsVal.alpha != 1.0);
+ let skipStr = " (Skipping checking right pixel since premultiplyAlpha was undefined and alpha != 1.0)";
+ bufferedLogToConsole("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, left, bottom, 2, 2, tl, "shouldBe " + tl + " +/-" + tolerance, tolerance);
+ if (skipAlphaTests) {
+ bufferedLogToConsole(skipStr);
+ } else {
+ wtu.checkCanvasRect(gl, right, bottom, 2, 2, tr, "shouldBe " + tr + " +/-" + tolerance, tolerance);
+ }
+ bufferedLogToConsole("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, left, top, 2, 2, bl, "shouldBe " + bl + " +/-" + tolerance, tolerance);
+ if (skipAlphaTests) {
+ bufferedLogToConsole(skipStr);
+ } else {
+ wtu.checkCanvasRect(gl, right, top, 2, 2, br, "shouldBe " + br + " +/-" + tolerance, 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, tolerance)
+{
+ 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;
+ case gl.LUMINANCE:
+ case gl.LUMINANCE_ALPHA:
+ redColor = [255, 255, 255];
+ greenColor = [0, 0, 0];
+ halfRed = [128, 128, 128];
+ halfGreen = [0, 0, 0];
+ break;
+ case gl.ALPHA:
+ redColor = [0, 0, 0];
+ greenColor = [0, 0, 0];
+ halfRed = [0, 0, 0];
+ halfGreen = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ switch (gl[internalFormat]) {
+ case gl.SRGB8:
+ case gl.SRGB8_ALPHA8:
+ halfRed = wtu.sRGBToLinear(halfRed);
+ halfGreen = wtu.sRGBToLinear(halfGreen);
+ 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("Start uploading the image into a 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 into texture completed");
+
+ var width = gl.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var quarterWidth = Math.floor(halfWidth / 2);
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ var quarterHeight = Math.floor(halfHeight / 2);
+
+ var top = flipY ? quarterHeight : (height - halfHeight + quarterHeight);
+ var bottom = flipY ? (height - halfHeight + quarterHeight) : quarterHeight;
+
+ // 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.
+ let skipAlphaTests = (premultiplyAlpha === undefined && optionsVal.alpha != 1.0);
+ let skipStr = " (Skipping checking right pixel since premultiplyAlpha was undefined and alpha != 1.0)";
+ bufferedLogToConsole("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, quarterWidth, bottom, 2, 2, tl, "shouldBe " + tl + " +/-" + tolerance, tolerance);
+ if (skipAlphaTests) {
+ bufferedLogToConsole(skipStr);
+ } else {
+ wtu.checkCanvasRect(gl, halfWidth + quarterWidth / 2, bottom, 2, 2, tr, "shouldBe " + tr + " +/-" + tolerance, tolerance);
+ }
+ bufferedLogToConsole("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, quarterWidth, top, 2, 2, bl, "shouldBe " + bl + " +/-" + tolerance, tolerance);
+ if (skipAlphaTests) {
+ bufferedLogToConsole(skipStr);
+ } else {
+ wtu.checkCanvasRect(gl, halfWidth + quarterWidth / 2, top, 2, 2, br, "shouldBe " + br + " +/-" + tolerance, tolerance);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+
+function runTestOnBindingTargetImageBitmap(bindingTarget, program, cases, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance)
+{
+ cases.forEach(x => {
+ runOneIterationImageBitmapTest(x.sub, bindingTarget, program, x.bitmap,
+ x.bitmap.flipY, x.bitmap.premultiply, optionsVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance);
+ });
+
+ if (wtu.getDefault3DContextVersion() <= 1 ||
+ (bindingTarget == gl.TEXTURE_CUBE_MAP || bindingTarget == gl.TEXTURE_2D_ARRAY))
+ {
+ // Skip testing source sub region on TEXTURE_CUBE_MAP and TEXTURE_2D_ARRAY on WebGL2 to save
+ // running time.
+ return;
+ }
+
+ cases.forEach(x => {
+ runOneIterationImageBitmapTestSubSource(x.sub, bindingTarget, program, x.bitmap,
+ x.bitmap.flipY, x.bitmap.premultiply, optionsVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance);
+ });
+}
+
+function runImageBitmapTestInternal(bitmaps, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D, tolerance)
+{
+ var cases = [];
+ bitmaps.forEach(bitmap => {
+ cases.push({bitmap: bitmap, sub: false});
+ cases.push({bitmap: bitmap, sub: true});
+ });
+
+ var optionsVal = {alpha: alphaVal, is3D: is3D};
+ var program;
+ if (is3D) {
+ program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_3D, program, cases, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance);
+ } else {
+ program = tiu.setupTexturedQuad(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_2D, program, cases, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance);
+ }
+
+ // cube map texture must be square
+ if (bitmaps[0].width == bitmaps[0].height) {
+ if (is3D) {
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_2D_ARRAY, program, cases, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance);
+ } else {
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_CUBE_MAP, program, cases, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu, tolerance);
+ }
+ }
+}
+
+function runImageBitmapTest(source, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D, opt_tolerance)
+{
+ if (opt_tolerance === undefined) {
+ opt_tolerance = 10;
+ }
+ var p1 = createImageBitmap(source, {imageOrientation: "none", premultiplyAlpha: "premultiply"})
+ .then(cur => { cur.flipY = false; cur.premultiply = true; return cur; });
+ var p2 = createImageBitmap(source, {imageOrientation: "none", premultiplyAlpha: "none"})
+ .then(cur => { cur.flipY = false; cur.premultiply = false; return cur; });
+ var p3 = createImageBitmap(source, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"})
+ .then(cur => { cur.flipY = true; cur.premultiply = true; return cur; });
+ var p4 = createImageBitmap(source, {imageOrientation: "flipY", premultiplyAlpha: "none"})
+ .then(cur => { cur.flipY = true; cur.premultiply = false; return cur; });
+ return Promise.all([p1, p2, p3, p4])
+ .catch( () => {
+ testPassed("createImageBitmap with options may be rejected if it is not supported. Retrying without options.");
+ // The ImageBitmap's premultiplyAlpha setting will implicitly be
+ // "default", and per spec:
+ // https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#cropped-to-the-source-rectangle-with-formatting
+ // this value is implementation-dependent (either premultiplied or
+ // not). Skip testing the quadrants which have alpha != 1.0.
+ var p = createImageBitmap(source)
+ .then(cur => { cur.flipY = false; cur.premultiply = undefined; return cur; });
+ return Promise.all([p]);
+ }).then( bitmaps => {
+ bufferedLogToConsole("All createImageBitmap promises are resolved");
+ runImageBitmapTestInternal(bitmaps, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D, opt_tolerance);
+ }, (e) => {
+ // This will fail here when running from file:// instead of https://.
+ testFailed("createImageBitmap(source) failed: \"" + e.message + "\"");
+ });
+}
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 0000000000..22261afdb4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js
@@ -0,0 +1,563 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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, gl.INVALID_OPERATION] },
+ { 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, gl.INVALID_OPERATION] },
+ { target: gl.TEXTURE_2D,
+ format: gl.RGBA,
+ type: gl.BYTE,
+ expectedError: [gl.INVALID_ENUM, gl.INVALID_OPERATION] }
+ ]);
+} 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, gl.INVALID_OPERATION]},
+ { 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/texture-corner-case-videos.js b/dom/canvas/test/webgl-conf/checkout/js/tests/texture-corner-case-videos.js
new file mode 100644
index 0000000000..a80da8023d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/texture-corner-case-videos.js
@@ -0,0 +1,299 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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(desc,
+ internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion,
+ videos) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var c2d = null;
+ var successfullyParsed = false;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+ var currentTolerance = 0;
+
+ function init()
+ {
+ description(desc + ' (' + 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");
+
+ // Subsume 2D canvas tests into this test case since they usually go down similar code paths and
+ // these tests are usually already set up to run with hardware accelerated video decoding.
+ c2d = document.getElementById("c2d").getContext("2d");
+
+ 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);
+
+ runAllTests();
+ }
+
+ 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 = currentTolerance;
+ 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);
+
+ // Expose bug http://crbug.com/733172.
+ if (sourceSubRectangle) {
+ // Skip sub-rectangle tests for cube map textures for the moment.
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ continue;
+ }
+ gl.texSubImage2D(targets[tt], 0, 0, 0,
+ sourceSubRectangle[2], sourceSubRectangle[3],
+ gl[pixelFormat], gl[pixelType], videoElement);
+ } else {
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], videoElement);
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ }
+ }
+
+ function runCanvas2DTest(videoElement, topColor, bottomColor)
+ {
+ debug('Testing with 2D canvas');
+
+ var canvas = c2d.canvas;
+
+ // Draw the video to the 2D canvas context.
+ c2d.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
+
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ // Origin is upper left in 2D canvas context.
+ var tolerance = currentTolerance;
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(c2d, 4, canvas.height - 8, 2, 2, bottomColor,
+ "shouldBe " + bottomColor, tolerance);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(c2d, 4, 4, 2, 2, topColor,
+ "shouldBe " + topColor, tolerance);
+ }
+
+ function runAllTests()
+ {
+ 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 },
+ ];
+
+ 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.comment);
+ debug("video type: " + info.type);
+ // Default to tolerance of 5.
+ currentTolerance = info.tolerance || 5;
+ debug("tolerance: " + currentTolerance);
+ video = document.createElement("video");
+ video.muted = true;
+ 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; skipping test");
+ 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);
+ }
+ runCanvas2DTest(video, redColor, greenColor);
+ runNextVideo();
+ }
+ runNextVideo();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_2D).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/typed-array-test-cases.js b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js
new file mode 100644
index 0000000000..2e1b79a677
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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 0000000000..c361a0e8a2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js
@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+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/tests/webgl-compressed-texture-size-limit.js b/dom/canvas/test/webgl-conf/checkout/js/tests/webgl-compressed-texture-size-limit.js
new file mode 100644
index 0000000000..6fad5520f2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/webgl-compressed-texture-size-limit.js
@@ -0,0 +1,226 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+'use strict';
+
+var runCompressedTextureSizeLimitTest = function(maxArrayBufferSizeBytes, positiveCubeMapMaxSize) {
+
+ function numLevelsFromSize(size) {
+ var levels = 0;
+ while ((size >> levels) > 0) {
+ ++levels;
+ }
+ return levels;
+ }
+
+ // More formats can be added here when more texture compression extensions are enabled in WebGL.
+ var validFormats = {
+ COMPRESSED_RGB_S3TC_DXT1_EXT : 0x83F0,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT : 0x83F1,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT : 0x83F2,
+ COMPRESSED_RGBA_S3TC_DXT5_EXT : 0x83F3,
+ };
+
+ // format specific restrictions for COMPRESSED_RGB_S3TC_DXT1_EXT and COMPRESSED_RGBA_S3TC_DXT1_EXT
+ // on the byteLength of the ArrayBufferView, pixels
+ function func1 (width, height)
+ {
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
+ }
+
+ // format specific restrictions for COMPRESSED_RGBA_S3TC_DXT3_EXT and COMPRESSED_RGBA_S3TC_DXT5_EXT
+ // on the byteLength of the ArrayBufferView, pixels
+ function func2 (width, height)
+ {
+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
+ }
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var tests = [
+ // More tests can be added here when more texture compression extensions are enabled in WebGL.
+ // Level 0 image width and height must be a multiple of the sizeStep.
+ { extension: "WEBGL_compressed_texture_s3tc", format: validFormats.COMPRESSED_RGB_S3TC_DXT1_EXT, dataType: Uint8Array, func: func1, sizeStep: 4},
+ { extension: "WEBGL_compressed_texture_s3tc", format: validFormats.COMPRESSED_RGBA_S3TC_DXT1_EXT, dataType: Uint8Array, func: func1, sizeStep: 4},
+ { extension: "WEBGL_compressed_texture_s3tc", format: validFormats.COMPRESSED_RGBA_S3TC_DXT3_EXT, dataType: Uint8Array, func: func2, sizeStep: 4},
+ { extension: "WEBGL_compressed_texture_s3tc", format: validFormats.COMPRESSED_RGBA_S3TC_DXT5_EXT, dataType: Uint8Array, func: func2, sizeStep: 4},
+ ];
+
+ // Note: We expressly only use 2 textures because first a texture will be defined
+ // using all mip levels of 1 format, then for a moment it will have mixed formats which
+ // may uncover bugs.
+ var targets = [
+ { target: gl.TEXTURE_2D,
+ maxSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),
+ tex: gl.createTexture(),
+ targets: [gl.TEXTURE_2D]
+ },
+ { target: gl.TEXTURE_CUBE_MAP,
+ maxSize: gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE),
+ tex: gl.createTexture(),
+ 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
+ ]
+ }
+ ];
+
+ function getSharedArrayBufferSize() {
+ var sharedArrayBufferSize = 0;
+ for (var tt = 0; tt < tests.length; ++tt) {
+ var test = tests[tt];
+ for (var trg = 0; trg < targets.length; ++trg) {
+ var t = targets[trg];
+ var bufferSizeNeeded;
+ if (t.target === gl.TEXTURE_CUBE_MAP) {
+ var positiveTestSize = Math.min(2048, t.maxSize);
+ bufferSizeNeeded = test.func(positiveTestSize, positiveTestSize);
+ } else {
+ bufferSizeNeeded = test.func(t.maxSize, test.sizeStep);
+ }
+ if (bufferSizeNeeded > sharedArrayBufferSize) {
+ sharedArrayBufferSize = bufferSizeNeeded;
+ }
+ bufferSizeNeeded = test.func(t.maxSize + test.sizeStep, t.maxSize + test.sizeStep);
+ // ArrayBuffers can be at most 4GB (minus 1 byte).
+ if (bufferSizeNeeded > sharedArrayBufferSize && bufferSizeNeeded <= maxArrayBufferSizeBytes) {
+ sharedArrayBufferSize = bufferSizeNeeded;
+ }
+ }
+ }
+ return sharedArrayBufferSize;
+ }
+
+ // Share an ArrayBuffer among tests to avoid too many large allocations
+ var sharedArrayBuffer = new ArrayBuffer(getSharedArrayBufferSize());
+
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+
+ var trg = 0;
+ var tt = 0;
+ runNextTest();
+
+ function runNextTest() {
+ var t = targets[trg];
+
+ if (tt == 0) {
+ var tex = t.tex;
+ gl.bindTexture(t.target, tex);
+
+ debug("");
+ debug("max size for " + wtu.glEnumToString(gl, t.target) + ": " + t.maxSize);
+ }
+
+ var test = tests[tt];
+ testFormatType(t, test);
+ ++tt;
+ if (tt == tests.length) {
+ tt = 0;
+ ++trg;
+ if (trg == targets.length) {
+ finishTest();
+ return;
+ }
+ }
+ wtu.dispatchPromise(runNextTest);
+ }
+
+ function testFormatType(t, test) {
+ var positiveTestSize = t.maxSize;
+ var positiveTestOtherDimension = test.sizeStep;
+ if (t.target === gl.TEXTURE_CUBE_MAP) {
+ // Can't always test the maximum size since that can cause OOM:
+ positiveTestSize = Math.min(positiveCubeMapMaxSize, t.maxSize);
+ // Cube map textures need to be square:
+ positiveTestOtherDimension = positiveTestSize;
+ }
+ var positiveTestLevels = numLevelsFromSize(positiveTestSize);
+ var numLevels = numLevelsFromSize(t.maxSize);
+ debug("");
+ debug("num levels: " + numLevels + ", levels used in positive test: " + positiveTestLevels);
+
+ debug("");
+
+ // Query the extension and store globally so shouldBe can access it
+ var ext = wtu.getExtensionWithKnownPrefixes(gl, test.extension);
+ if (ext) {
+
+ testPassed("Successfully enabled " + test.extension + " extension");
+
+ for (var j = 0; j < t.targets.length; ++j) {
+ var target = t.targets[j];
+ debug("");
+ debug(wtu.glEnumToString(gl, target) + " " + wtu.glEnumToString(ext, test.format));
+
+ // positive test
+ var size = positiveTestSize;
+ var otherDimension = positiveTestOtherDimension;
+ for (var i = 0; i < positiveTestLevels; i++) {
+ var pixels = new test.dataType(sharedArrayBuffer, 0, test.func(size, otherDimension));
+ gl.compressedTexImage2D(target, i, test.format, size, otherDimension, 0, pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture should generate NO_ERROR."
+ + "level is " + i + ", size is " + size + "x" + otherDimension);
+ size /= 2;
+ otherDimension /= 2;
+ if (otherDimension < 1) {
+ otherDimension = 1;
+ }
+ }
+
+ var numLevels = numLevelsFromSize(t.maxSize);
+
+ // out of bounds tests
+
+ // width or height out of bounds
+ if (t.target != gl.TEXTURE_CUBE_MAP) {
+ // only width out of bounds
+ var wideAndShortDataSize = test.func(t.maxSize + test.sizeStep, test.sizeStep);
+ var pixelsNegativeTest1 = new test.dataType(sharedArrayBuffer, 0, wideAndShortDataSize);
+ gl.compressedTexImage2D(target, 0, test.format, t.maxSize + test.sizeStep, test.sizeStep, 0, pixelsNegativeTest1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "width out of bounds: should generate INVALID_VALUE."
+ + " level is 0, size is " + (t.maxSize + test.sizeStep) + "x" + (test.sizeStep));
+
+ // only height out of bounds
+ var narrowAndTallDataSize = test.func(test.sizeStep, t.maxSize + test.sizeStep);
+ var pixelsNegativeTest1 = new test.dataType(sharedArrayBuffer, 0, narrowAndTallDataSize);
+ gl.compressedTexImage2D(target, 0, test.format, test.sizeStep, t.maxSize + test.sizeStep, 0, pixelsNegativeTest1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "height out of bounds: should generate INVALID_VALUE."
+ + " level is 0, size is " + (test.sizeStep) + "x" + (t.maxSize + test.sizeStep));
+ }
+
+ // both width and height out of the maximum bounds simultaneously
+ var squareDataSize = test.func(t.maxSize + test.sizeStep, t.maxSize + test.sizeStep);
+ // this check assumes that each element is 1 byte
+ if (squareDataSize > sharedArrayBuffer.byteLength) {
+ testPassed("Unable to test square texture larger than maximum size due to ArrayBuffer size limitations -- this is legal");
+ } else {
+ var pixelsNegativeTest1 = new test.dataType(sharedArrayBuffer, 0, squareDataSize);
+ gl.compressedTexImage2D(target, 0, test.format, t.maxSize + test.sizeStep, t.maxSize + test.sizeStep, 0, pixelsNegativeTest1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "width and height out of bounds: should generate INVALID_VALUE."
+ + " level is 0, size is " + (t.maxSize + test.sizeStep) + "x" + (t.maxSize + test.sizeStep));
+ }
+
+ // level out of bounds
+ var pixelsNegativeTest2 = new test.dataType(sharedArrayBuffer, 0, test.func(256, 256));
+ gl.compressedTexImage2D(target, numLevels, test.format, 256, 256, 0, pixelsNegativeTest2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "level out of bounds: should generate INVALID_VALUE."
+ + " level is " + numLevels + ", size is 256x256");
+ //width and height out of bounds for specified level
+ gl.compressedTexImage2D(target, numLevels - 1, test.format, 256, 256, 0, pixelsNegativeTest2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "width or height out of bounds for specified level: should generate INVALID_VALUE."
+ + " level is " + (numLevels - 1) + ", size is 256x256");
+ }
+ }
+ else {
+ testPassed("No " + test.extension + " extension support -- this is legal");
+ }
+ }
+
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/webgl-draw-buffers-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/webgl-draw-buffers-utils.js
new file mode 100644
index 0000000000..ebd0c7ba68
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/webgl-draw-buffers-utils.js
@@ -0,0 +1,69 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// This file contains utilities shared between tests for the WEBGL_draw_buffers extension and multiple draw buffers functionality in WebGL 2.0.
+
+'use strict';
+
+var WebGLDrawBuffersUtils = function(gl, ext) {
+
+ var getMaxUsableColorAttachments = function() {
+ var maxDrawingBuffers;
+ var maxColorAttachments;
+ if (ext) {
+ // EXT_draw_buffers
+ maxDrawingBuffers = gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL);
+ maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL);
+ } else {
+ // WebGL 2.0
+ maxDrawingBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
+ maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ }
+ var maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
+ return Math.min(maxDrawingBuffers, maxColorAttachments, maxUniformVectors);
+ };
+
+ var makeColorAttachmentArray = function(size) {
+ var array = []
+ for (var ii = 0; ii < size; ++ii) {
+ array.push(gl.COLOR_ATTACHMENT0 + ii);
+ }
+ return array;
+ }
+
+ var checkProgram = wtu.setupTexturedQuad(gl);
+
+ var checkAttachmentsForColorFn = function(attachments, colorFn) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.useProgram(checkProgram);
+ attachments.forEach(function(attachment, index) {
+ gl.bindTexture(gl.TEXTURE_2D, attachment.texture);
+ wtu.clearAndDrawUnitQuad(gl);
+ var expectedColor = colorFn(attachment, index);
+ var tolerance = 0;
+ expectedColor.forEach(function(v) {
+ if (v != 0 && v != 255) {
+ tolerance = 8;
+ }
+ });
+ wtu.checkCanvas(gl, expectedColor, "attachment " + index + " should be " + expectedColor.toString(), tolerance);
+ });
+ debug("");
+ };
+
+ var checkAttachmentsForColor = function(attachments, color) {
+ checkAttachmentsForColorFn(attachments, function(attachment, index) {
+ return color || attachment.color;
+ });
+ };
+
+ return {
+ getMaxUsableColorAttachments: getMaxUsableColorAttachments,
+ makeColorAttachmentArray: makeColorAttachmentArray,
+ checkAttachmentsForColorFn: checkAttachmentsForColorFn,
+ checkAttachmentsForColor: checkAttachmentsForColor
+ };
+};
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 0000000000..f48d9d2ad7
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-harness.js
@@ -0,0 +1,642 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// 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 0000000000..f17f69fa30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
@@ -0,0 +1,3677 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+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() {};
+};
+
+const ENUM_NAME_REGEX = RegExp('[A-Z][A-Z0-9_]*');
+const ENUM_NAME_BY_VALUE = {};
+const ENUM_NAME_PROTOTYPES = new Map();
+
+/**
+ * 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(glOrExt, value) {
+ if (value === undefined)
+ throw new Error('glEnumToString: `value` must not be undefined');
+
+ const proto = glOrExt.__proto__;
+ if (!ENUM_NAME_PROTOTYPES.has(proto)) {
+ ENUM_NAME_PROTOTYPES.set(proto, true);
+
+ for (const k in proto) {
+ if (!ENUM_NAME_REGEX.test(k)) continue;
+
+ const v = glOrExt[k];
+ if (ENUM_NAME_BY_VALUE[v] === undefined) {
+ ENUM_NAME_BY_VALUE[v] = k;
+ } else {
+ ENUM_NAME_BY_VALUE[v] += '/' + k;
+ }
+ }
+ }
+
+ const key = ENUM_NAME_BY_VALUE[value];
+ if (key !== undefined) return key;
+
+ 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 vertex shader for a single texture.
+ * @type {string}
+ */
+var simpleTextureVertexShaderESSL300 = [
+ '#version 300 es',
+ 'layout(location=0) in vec4 vPosition;',
+ 'layout(location=1) in vec2 texCoord0;',
+ 'out 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 texture.
+ * @type {string}
+ */
+var simpleTextureFragmentShaderESSL300 = [
+ '#version 300 es',
+ 'precision highp float;',
+ 'uniform highp sampler2D tex;',
+ 'in vec2 texCoord;',
+ 'out vec4 out_color;',
+ 'void main() {',
+ ' out_color = texture(tex, texCoord);',
+ '}'].join('\n');
+
+/**
+ * A fragment shader for a single texture with high precision.
+ * @type {string}
+ */
+var simpleHighPrecisionTextureFragmentShader = [
+ 'precision highp float;',
+ 'uniform highp 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 highp 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 vertex shader for a uniform color.
+ * @type {string}
+ */
+var simpleVertexShaderESSL300 = [
+ '#version 300 es',
+ 'in 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 fragment shader for a uniform color.
+ * @type {string}
+ */
+var simpleColorFragmentShaderESSL300 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'out vec4 out_color;',
+ 'uniform vec4 u_color;',
+ 'void main() {',
+ ' out_color = 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, opt_skipCompileStatus) {
+ 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, opt_skipCompileStatus);
+ } else if (endsWith(shader, ".vert")) {
+ shader = loadShaderFromFile(gl, shader, gl.VERTEX_SHADER, undefined, opt_logShaders, opt_skipCompileStatus);
+ } else if (endsWith(shader, ".frag")) {
+ shader = loadShaderFromFile(gl, shader, gl.FRAGMENT_SHADER, undefined, opt_logShaders, opt_skipCompileStatus);
+ } else {
+ shader = loadShader(gl, shader, ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER, undefined, opt_logShaders, undefined, undefined, opt_skipCompileStatus);
+ }
+ } 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.
+ * @param {string} opt_fragmentShaderOverride The alternative fragment shader to use.
+ * @return {WebGLProgram}
+ */
+var setupSimpleTextureProgram = function(
+ gl, opt_positionLocation, opt_texcoordLocation, opt_fragmentShaderOverride) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ opt_fragmentShaderOverride = opt_fragmentShaderOverride || simpleTextureFragmentShader;
+ return setupProgram(gl,
+ [simpleTextureVertexShader, opt_fragmentShaderOverride],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+};
+
+/**
+ * Creates a simple texture program using glsl version 300.
+ * @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.
+ * @param {string} opt_fragmentShaderOverride The alternative fragment shader to use.
+ * @return {WebGLProgram}
+ */
+var setupSimpleTextureProgramESSL300 = function(
+ gl, opt_positionLocation, opt_texcoordLocation, opt_fragmentShaderOverride) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ opt_fragmentShaderOverride = opt_fragmentShaderOverride || simpleTextureFragmentShaderESSL300;
+ return setupProgram(gl,
+ [simpleTextureVertexShaderESSL300, opt_fragmentShaderOverride],
+ ['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.
+ * @param {!Object} various options. See setupQuad for details.
+ * @return {!Array.<WebGLBuffer>} The buffer objects that were
+ * created.
+ */
+var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation, options) {
+ return setupQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
+ opt_positionLocation, opt_texcoordLocation,
+ options);
+};
+
+/**
+ * Creates buffers for a textured 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.
+ * @param {!Object} various options. See setupQuad for details.
+ * @return {!Array.<WebGLBuffer>} The buffer objects that were
+ * created.
+ */
+var setupQuadWithTexCoords = function(
+ gl, lowerLeftTexCoords, upperRightTexCoords,
+ opt_positionLocation, opt_texcoordLocation, options) {
+ var defaultOptions = {
+ positionLocation: opt_positionLocation || 0,
+ texcoordLocation: opt_texcoordLocation || 1,
+ lowerLeftTexCoords: lowerLeftTexCoords,
+ upperRightTexCoords: upperRightTexCoords
+ };
+ if (options) {
+ for (var prop in options) {
+ defaultOptions[prop] = options[prop]
+ }
+ }
+ return setupQuad(gl, defaultOptions);
+};
+
+/**
+ * Makes a quad with various options.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Object} options
+ *
+ * scale: scale to multiply 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.
+ * @param {!Object} various options defined by setupQuad, plus an option
+ fragmentShaderOverride to specify a custom fragment shader.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuad = function(
+ gl, opt_positionLocation, opt_texcoordLocation, options) {
+ var program = setupSimpleTextureProgram(
+ gl, opt_positionLocation, opt_texcoordLocation, options && options.fragmentShaderOverride);
+ setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation, options);
+ 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.
+ * @param {!Object} various options. See setupQuad for details.
+ * @return {!WebGLProgram}
+ */
+var setupColorQuad = function(gl, opt_positionLocation, options) {
+ opt_positionLocation = opt_positionLocation || 0;
+ var program = setupSimpleColorProgram(gl, opt_positionLocation);
+ setupUnitQuad(gl, opt_positionLocation, 0, options);
+ 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);
+ setupQuadWithTexCoords(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, undefined);
+ 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);
+ poffset = 0;
+ 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:
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ case gl.UNSIGNED_INT_24_8:
+ return window.Uint32Array;
+ case gl.HALF_FLOAT:
+ case 0x8D61: // HALF_FLOAT_OES
+ return window.Uint16Array;
+ case gl.FLOAT:
+ return window.Float32Array;
+ 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:
+ case gl.HALF_FLOAT:
+ case 0x8D61: // HALF_FLOAT_OES
+ return 2;
+ case gl.INT:
+ case gl.UNSIGNED_INT:
+ case gl.UNSIGNED_INT_5_9_9_9_REV:
+ case gl.UNSIGNED_INT_10F_11F_11F_REV:
+ case gl.UNSIGNED_INT_2_10_10_10_REV:
+ case gl.UNSIGNED_INT_24_8:
+ case gl.FLOAT:
+ 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;
+ // See equation 3.10 in ES 2.0 spec and equation 3.13 in ES 3.0 spec for paddedRowLength calculation.
+ // k is paddedRowLength.
+ // n is numComponents.
+ // l is width.
+ // a is pack.
+ // s is bytesPerComponent.
+ var paddedRowLength;
+ if (bytesPerComponent >= pack)
+ paddedRowLength = numComponents * width;
+ else
+ paddedRowLength = Math.floor((rowSize + pack - 1) / pack) * pack / bytesPerComponent;
+ var size = width * numComponents + (height - 1) * paddedRowLength;
+ var buf = new (glTypeToTypedArrayType(gl, opt_type))(size);
+ for (var yy = 0; yy < height; ++yy) {
+ var off = yy * paddedRowLength;
+ 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);
+};
+
+var dummySetProgramAndDrawNothing = function(gl) {
+ if (!gl._wtuDummyProgram) {
+ gl._wtuDummyProgram = setupProgram(gl, [
+ "void main() { gl_Position = vec4(0.0); }",
+ "void main() { gl_FragColor = vec4(0.0); }"
+ ], [], []);
+ }
+ gl.useProgram(gl._wtuDummyProgram);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+};
+
+/**
+ * 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 {TypedArray} opt_readBackBuf optional buffer to read back into.
+ * Typically passed to either reuse buffer, or support readbacks from
+ * floating-point/norm16 framebuffers.
+ * @param {GLenum} opt_readBackType optional read back type, defaulting to
+ * gl.UNSIGNED_BYTE. Can be used to support readback from floating-point
+ * /norm16 framebuffers.
+ * @param {GLenum} opt_readBackFormat optional read back format, defaulting to
+ * gl.RGBA. Can be used to support readback from norm16
+ * framebuffers.
+ */
+var checkCanvasRectColor = function(gl, x, y, width, height, color, opt_errorRange, sameFn, differentFn, logFn, opt_readBackBuf, opt_readBackType, opt_readBackFormat) {
+ 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);
+ var readBackType = opt_readBackType ? opt_readBackType : gl.UNSIGNED_BYTE;
+ var readBackFormat = opt_readBackFormat ? opt_readBackFormat : gl.RGBA;
+ gl.readPixels(x, y, width, height, readBackFormat, readBackType, 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, buf);
+ 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.
+ * @param {TypedArray} opt_readBackBuf optional buffer to read back into.
+ * Typically passed to either reuse buffer, or support readbacks from
+ * floating-point/norm16 framebuffers.
+ * @param {GLenum} opt_readBackType optional read back type, defaulting to
+ * gl.UNSIGNED_BYTE. Can be used to support readback from floating-point
+ * /norm16 framebuffers.
+ * @param {GLenum} opt_readBackFormat optional read back format, defaulting to
+ * gl.RGBA. Can be used to support readback from floating-point
+ * /norm16 framebuffers.
+ */
+var checkCanvasRect = function(gl, x, y, width, height, color, opt_msg, opt_errorRange, opt_readBackBuf, opt_readBackType, opt_readBackFormat) {
+ 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,
+ opt_readBackBuf,
+ opt_readBackType,
+ opt_readBackFormat);
+};
+
+/**
+ * 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;
+ }
+
+ const parseString = v => v;
+ const parseBoolean = v => v.toLowerCase().startsWith('t') || parseFloat(v) > 0;
+ const params = new URLSearchParams(window.location.search);
+ for (const [key, parseFn] of Object.entries({
+ alpha: parseBoolean,
+ antialias: parseBoolean,
+ depth: parseBoolean,
+ desynchronized: parseBoolean,
+ failIfMajorPerformanceCaveat: parseBoolean,
+ powerPreference: parseString,
+ premultipliedAlpha: parseBoolean,
+ preserveDrawingBuffer: parseBoolean,
+ stencil: parseBoolean,
+ })) {
+ const value = params.get(key);
+ if (value) {
+ const v = parseFn(value);
+ attributes[key] = v;
+ debug(`setting context attribute: ${key} = ${v}`);
+ }
+ }
+
+ if (!opt_version) {
+ opt_version = getDefault3DContextVersion();
+ }
+ 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"]; 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");
+ } else {
+ if (!window._wtu_contexts) {
+ window._wtu_contexts = []
+ }
+ window._wtu_contexts.push(context);
+ }
+
+ if (params.get('showRenderer')) {
+ const ext = context.getExtension('WEBGL_debug_renderer_info');
+ debug(`RENDERER: ${context.getParameter(ext ? ext.UNMASKED_RENDERER_WEBGL : context.RENDERER)}`);
+ }
+
+ return context;
+};
+
+/**
+ * Indicates whether the given context is WebGL 2.0 or greater.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {boolean} True if the given context is WebGL 2.0 or greater.
+ */
+var isWebGL2 = function(gl) {
+ // Duck typing is used so that the conformance suite can be run
+ // against libraries emulating WebGL 1.0 on top of WebGL 2.0.
+ return !!gl.drawArraysInstanced;
+};
+
+/**
+ * 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);
+ return -1;
+ } else {
+ if (!opt_msg) {
+ opt_msg = "after evaluating: " + evalStr;
+ }
+ return 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) {
+ return glErrorShouldBeImpl(gl, glErrors, true, opt_msg);
+};
+
+const glErrorAssert = function(gl, glErrors, opt_msg) {
+ return glErrorShouldBeImpl(gl, glErrors, false, opt_msg);
+};
+
+/**
+ * Tests that the given framebuffer has a specific status
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glStatuses The expected gl
+ * status or an array of expected statuses.
+ * @param {string} opt_msg Optional additional message.
+ */
+var framebufferStatusShouldBe = function(gl, target, glStatuses, opt_msg) {
+ if (!glStatuses.length) {
+ glStatuses = [glStatuses];
+ }
+ opt_msg = opt_msg || "";
+ const status = gl.checkFramebufferStatus(target);
+ const ndx = glStatuses.indexOf(status);
+ const expected = glStatuses.map((status) => {
+ return glEnumToString(gl, status);
+ }).join(' or ');
+ if (ndx < 0) {
+ let msg = "checkFramebufferStatus expected" + ((glStatuses.length > 1) ? " one of: " : ": ") +
+ expected + ". Was " + glEnumToString(gl, status);
+ if (opt_msg) {
+ msg += ": " + opt_msg;
+ }
+ testFailed(msg);
+ return false;
+ }
+ let msg = `checkFramebufferStatus was ${glEnumToString(gl, status)}`;
+ if (glStatuses.length > 1) {
+ msg += `, one of: ${expected}`;
+ }
+ if (opt_msg) {
+ msg += ": " + opt_msg;
+ }
+ testPassed(msg);
+ return [status];
+}
+
+/**
+ * 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 || "";
+
+ const fnErrStr = function(errVal) {
+ if (errVal == 0) return "NO_ERROR";
+ return glEnumToString(gl, errVal);
+ };
+
+ var err = gl.getError();
+ var ndx = glErrors.indexOf(err);
+ var errStrs = [];
+ for (var ii = 0; ii < glErrors.length; ++ii) {
+ errStrs.push(fnErrStr(glErrors[ii]));
+ }
+ var expected = errStrs.join(" or ");
+ if (ndx < 0) {
+ var msg = "getError expected" + ((glErrors.length > 1) ? " one of: " : ": ");
+ testFailed(msg + expected + ". Was " + fnErrStr(err) + " : " + opt_msg);
+ } else if (reportSuccesses) {
+ var msg = "getError was " + ((glErrors.length > 1) ? "one of: " : "expected value: ");
+ testPassed(msg + expected + " : " + opt_msg);
+ }
+ return err;
+};
+
+/**
+ * Tests that a function throws or not.
+ * @param {!WebGLContext} gl The WebGLContext to use.
+ * @param throwType Type of thrown error (e.g. TypeError), or false.
+ * @param {string} info Info on what's being tested
+ * @param {function} func The func to test.
+ */
+var shouldThrow = function(gl, throwType, info, func) {
+ while (gl.getError()) {}
+
+ var shouldThrow = (throwType != false);
+
+ try {
+ func();
+
+ if (shouldThrow) {
+ testFailed("Should throw a " + throwType.name + ": " + info);
+ } else {
+ testPassed("Should not have thrown: " + info);
+ }
+ } catch (e) {
+ if (shouldThrow) {
+ if (e instanceof throwType) {
+ testPassed("Should throw a " + throwType.name + ": " + info);
+ } else {
+ testFailed("Should throw a " + throwType.name + ", threw " + e.name + ": " + info);
+ }
+ } else {
+ testFailed("Should not have thrown: " + info);
+ }
+
+ if (gl.getError()) {
+ testFailed("Should not generate an error when throwing: " + info);
+ }
+ }
+
+ while (gl.getError()) {}
+};
+
+/**
+ * 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.overrideMimeType("text/plain");
+ 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);
+
+ // 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.trim();
+
+ 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');
+ vid.muted = true;
+ 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;
+ }
+ }
+};
+
+/**
+ * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} name Name of extension to look for.
+ * @param {boolean} extensionEnabled True if the extension was enabled successfully via gl.getExtension().
+ */
+var runExtensionSupportedTest = function(gl, name, extensionEnabled) {
+ var prefixedName = getSupportedExtensionWithKnownPrefixes(gl, name);
+ if (prefixedName !== undefined) {
+ if (extensionEnabled) {
+ testPassed(name + " listed as supported and getExtension succeeded");
+ } else {
+ testFailed(name + " listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed(name + " not listed as supported but getExtension succeeded");
+ } else {
+ testPassed(name + " not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+/**
+ * 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();
+};
+
+var setZeroTimeout = (function() {
+ // See https://dbaron.org/log/20100309-faster-timeouts
+
+ var timeouts = [];
+ var messageName = "zero-timeout-message";
+
+ // Like setTimeout, but only takes a function argument. There's
+ // no time argument (always zero) and no arguments (you have to
+ // use a closure).
+ function setZeroTimeout(fn) {
+ timeouts.push(fn);
+ window.postMessage(messageName, "*");
+ }
+
+ function handleMessage(event) {
+ if (event.source == window && event.data == messageName) {
+ event.stopPropagation();
+ if (timeouts.length > 0) {
+ var fn = timeouts.shift();
+ fn();
+ }
+ }
+ }
+
+ window.addEventListener("message", handleMessage, true);
+
+ return setZeroTimeout;
+})();
+
+function dispatchPromise(fn) {
+ return new Promise((fn_resolve, fn_reject) => {
+ setZeroTimeout(() => {
+ let val;
+ if (fn) {
+ val = fn();
+ }
+ fn_resolve(val);
+ });
+ });
+}
+
+/**
+ * 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.
+ */
+async function startPlayingAndWaitForVideo(video, callback) {
+ if (video.error) {
+ testFailed('Video failed to load: ' + video.error);
+ return;
+ }
+
+ video.loop = true;
+ video.muted = true;
+ // See whether setting the preload flag de-flakes video-related tests.
+ video.preload = 'auto';
+
+ try {
+ await video.play();
+ } catch (e) {
+ testFailed('video.play failed: ' + e);
+ return;
+ }
+
+ if (video.requestVideoFrameCallback) {
+ await new Promise(go => video.requestVideoFrameCallback(go));
+ }
+
+ callback(video);
+}
+
+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() {
+ let hostname = window.location.hostname;
+ return hostname == "localhost" ||
+ hostname == "127.0.0.1" ||
+ hostname == "::1";
+}
+
+var getLocalCrossOrigin = function() {
+ var domain;
+ if (window.location.host.indexOf("localhost") != -1) {
+ // TODO(kbr): figure out whether to use an IPv6 loopback address.
+ 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("/");
+}
+
+async function loadCrossOriginImage(img, webUrl, localUrl) {
+ if (runningOnLocalhost()) {
+ img.src = getLocalCrossOrigin() + getRelativePath(localUrl);
+ console.log('[loadCrossOriginImage]', ' trying', img.src);
+ await img.decode();
+ return;
+ }
+
+ try {
+ img.src = getUrlOptions().imgUrl || webUrl;
+ console.log('[loadCrossOriginImage]', 'trying', img.src);
+ await img.decode();
+ return;
+ } catch {}
+
+ throw 'createCrossOriginImage failed';
+}
+
+/**
+ * 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);
+}
+
+/**
+ * Return the named color in the specified color space.
+ * @param {string} colorName The name of the color to convert.
+ * Supported color names are:
+ * 'Red', which is the CSS color color('srgb' 1 0 0 1)
+ * 'Green', which is the CSS color color('srgb' 0 1 0 1)
+ * @param {string} colorSpace The color space to convert to. Supported
+ color spaces are:
+ * null, which is treated as sRGB
+ * 'srgb'
+ * 'display-p3'.
+ * Documentation on the formulas for color conversion between
+ * spaces can be found at
+ https://www.w3.org/TR/css-color-4/#predefined-to-predefined
+ * @return {!Array.<number>} color The color in the specified color
+ * space as an 8-bit RGBA array with unpremultiplied alpha.
+ */
+var namedColorInColorSpace = function(colorName, colorSpace) {
+ var result;
+ switch (colorSpace) {
+ case undefined:
+ case 'srgb':
+ switch(colorName) {
+ case 'Red':
+ return [255, 0, 0, 255];
+ case 'Green':
+ return [0, 255, 0, 255];
+ break;
+ default:
+ throw 'unexpected color name: ' + colorName;
+ };
+ break;
+ case 'display-p3':
+ switch(colorName) {
+ case 'Red':
+ return [234, 51, 35, 255];
+ break;
+ case 'Green':
+ return [117, 251, 76, 255];
+ break;
+ default:
+ throw 'unexpected color name: ' + colorName;
+ }
+ break;
+ default:
+ throw 'unexpected color space: ' + colorSpace;
+ }
+}
+
+/**
+ * Return the named color as it would be sampled with the specified
+ * internal format
+ * @param {!Array.<number>} color The color as an 8-bit RGBA array.
+ * @param {string} internalformat The internal format.
+ * @return {!Array.<number>} color The color, as it would be sampled by
+ * the specified internal format, as an 8-bit RGBA array.
+ */
+var colorAsSampledWithInternalFormat = function(color, internalFormat) {
+ switch (internalFormat) {
+ case 'ALPHA':
+ return [0, 0, 0, color[3]];
+ case 'LUMINANCE':
+ return [color[0], color[0], color[0], 255];
+ case 'LUMINANCE_ALPHA':
+ return [color[0], color[0], color[0], color[3]];
+ case 'SRGB8':
+ case 'SRGB8_ALPHA8':
+ return [sRGBChannelToLinear(color[0]),
+ sRGBChannelToLinear(color[1]),
+ sRGBChannelToLinear(color[2]),
+ color[3]];
+ case 'R16F':
+ case 'R32F':
+ case 'R8':
+ case 'R8UI':
+ case 'RED':
+ case 'RED_INTEGER':
+ return [color[0], 0, 0, 0];
+ case 'RG':
+ case 'RG16F':
+ case 'RG32F':
+ case 'RG8':
+ case 'RG8UI':
+ case 'RG_INTEGER':
+ return [color[0], color[1], 0, 0];
+ break;
+ default:
+ break;
+ }
+ return color;
+}
+
+function comparePixels(cmp, ref, tolerance, diff) {
+ if (cmp.length != ref.length) {
+ testFailed("invalid pixel size.");
+ }
+
+ var count = 0;
+ for (var i = 0; i < cmp.length; i++) {
+ if (diff) {
+ diff[i * 4] = 0;
+ diff[i * 4 + 1] = 255;
+ diff[i * 4 + 2] = 0;
+ diff[i * 4 + 3] = 255;
+ }
+ if (Math.abs(cmp[i * 4] - ref[i * 4]) > tolerance ||
+ Math.abs(cmp[i * 4 + 1] - ref[i * 4 + 1]) > tolerance ||
+ Math.abs(cmp[i * 4 + 2] - ref[i * 4 + 2]) > tolerance ||
+ Math.abs(cmp[i * 4 + 3] - ref[i * 4 + 3]) > tolerance) {
+ if (count < 10) {
+ testFailed("Pixel " + i + ": expected (" +
+ [ref[i * 4], ref[i * 4 + 1], ref[i * 4 + 2], ref[i * 4 + 3]] + "), got (" +
+ [cmp[i * 4], cmp[i * 4 + 1], cmp[i * 4 + 2], cmp[i * 4 + 3]] + ")");
+ }
+ count++;
+ if (diff) {
+ diff[i * 4] = 255;
+ diff[i * 4 + 1] = 0;
+ }
+ }
+ }
+
+ return count;
+}
+
+function destroyContext(gl) {
+ const ext = gl.getExtension('WEBGL_lose_context');
+ if (ext) {
+ ext.loseContext();
+ }
+ gl.canvas.width = 1;
+ gl.canvas.height = 1;
+}
+
+function destroyAllContexts() {
+ if (!window._wtu_contexts)
+ return;
+ for (const x of window._wtu_contexts) {
+ destroyContext(x);
+ }
+ window._wtu_contexts = [];
+}
+
+function displayImageDiff(cmp, ref, diff, width, height) {
+ var div = document.createElement("div");
+
+ var cmpImg = createImageFromPixel(cmp, width, height);
+ var refImg = createImageFromPixel(ref, width, height);
+ var diffImg = createImageFromPixel(diff, width, height);
+ wtu.insertImage(div, "Reference", refImg);
+ wtu.insertImage(div, "Result", cmpImg);
+ wtu.insertImage(div, "Difference", diffImg);
+
+ var console = document.getElementById("console");
+ console.appendChild(div);
+}
+
+function createImageFromPixel(buf, width, height) {
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ var imgData = ctx.getImageData(0, 0, width, height);
+
+ for (var i = 0; i < buf.length; i++)
+ imgData.data[i] = buf[i];
+ ctx.putImageData(imgData, 0, 0);
+ var img = wtu.makeImageFromCanvas(canvas);
+ return img;
+}
+
+async function awaitTimeout(ms) {
+ await new Promise(res => {
+ setTimeout(() => {
+ res();
+ }, ms);
+ });
+}
+
+async function awaitOrTimeout(promise, opt_timeout_ms) {
+ async function throwOnTimeout(ms) {
+ await awaitTimeout(ms);
+ throw 'timeout';
+ }
+
+ let timeout_ms = opt_timeout_ms;
+ if (timeout_ms === undefined)
+ timeout_ms = 5000;
+
+ await Promise.race([promise, throwOnTimeout(timeout_ms)]);
+}
+
+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,
+ comparePixels: comparePixels,
+ destroyAllContexts: destroyAllContexts,
+ destroyContext: destroyContext,
+ dispatchPromise: dispatchPromise,
+ displayImageDiff: displayImageDiff,
+ drawUnitQuad: drawUnitQuad,
+ drawIndexedQuad: drawIndexedQuad,
+ drawUByteColorQuad: drawUByteColorQuad,
+ drawFloatColorQuad: drawFloatColorQuad,
+ dummySetProgramAndDrawNothing: dummySetProgramAndDrawNothing,
+ dumpShadersInfo: dumpShadersInfo,
+ endsWith: endsWith,
+ failIfGLError: failIfGLError,
+ fillTexture: fillTexture,
+ framebufferStatusShouldBe: framebufferStatusShouldBe,
+ 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,
+ glErrorAssert: glErrorAssert,
+ glErrorShouldBe: glErrorShouldBe,
+ glTypeToTypedArrayType: glTypeToTypedArrayType,
+ hasAttributeCaseInsensitive: hasAttributeCaseInsensitive,
+ insertImage: insertImage,
+ isWebGL2: isWebGL2,
+ linkProgram: linkProgram,
+ loadCrossOriginImage: loadCrossOriginImage,
+ 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,
+ runExtensionSupportedTest: runExtensionSupportedTest,
+ shallowCopyObject: shallowCopyObject,
+ setDefault3DContextVersion: setDefault3DContextVersion,
+ setupColorQuad: setupColorQuad,
+ setupProgram: setupProgram,
+ setupTransformFeedbackProgram: setupTransformFeedbackProgram,
+ setupQuad: setupQuad,
+ setupQuadWithTexCoords: setupQuadWithTexCoords,
+ setupIndexedQuad: setupIndexedQuad,
+ setupIndexedQuadWithOptions: setupIndexedQuadWithOptions,
+ setupSimpleColorProgram: setupSimpleColorProgram,
+ setupSimpleTextureProgram: setupSimpleTextureProgram,
+ setupSimpleTextureProgramESSL300: setupSimpleTextureProgramESSL300,
+ setupSimpleCubeMapTextureProgram: setupSimpleCubeMapTextureProgram,
+ setupSimpleVertexColorProgram: setupSimpleVertexColorProgram,
+ setupNoTexCoordTextureProgram: setupNoTexCoordTextureProgram,
+ setupTexturedQuad: setupTexturedQuad,
+ setupTexturedQuadWithTexCoords: setupTexturedQuadWithTexCoords,
+ setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
+ setupUnitQuad: setupUnitQuad,
+ setFloatDrawColor: setFloatDrawColor,
+ setUByteDrawColor: setUByteDrawColor,
+ startPlayingAndWaitForVideo: startPlayingAndWaitForVideo,
+ startsWith: startsWith,
+ shouldGenerateGLError: shouldGenerateGLError,
+ shouldThrow: shouldThrow,
+ readFile: readFile,
+ readFileList: readFileList,
+ replaceParams: replaceParams,
+ requestAnimFrame: requestAnimFrame,
+ runSteps: runSteps,
+ waitForComposite: waitForComposite,
+
+ // fullscreen api
+ setupFullscreen: setupFullscreen,
+
+ // color converter API
+ namedColorInColorSpace: namedColorInColorSpace,
+ colorAsSampledWithInternalFormat: colorAsSampledWithInternalFormat,
+
+ // sRGB converter api
+ sRGBToLinear: sRGBToLinear,
+ linearToSRGB: linearToSRGB,
+
+ getHost: getHost,
+ getBaseDomain: getBaseDomain,
+ runningOnLocalhost: runningOnLocalhost,
+ getLocalCrossOrigin: getLocalCrossOrigin,
+ getRelativePath: getRelativePath,
+ awaitOrTimeout: awaitOrTimeout,
+ awaitTimeout: awaitTimeout,
+
+ none: false
+};
+
+Object.defineProperties(API, {
+ noTexCoordTextureVertexShader: { value: noTexCoordTextureVertexShader, writable: false },
+ simpleTextureVertexShader: { value: simpleTextureVertexShader, writable: false },
+ simpleTextureVertexShaderESSL300: { value: simpleTextureVertexShaderESSL300, writable: false },
+ simpleColorFragmentShader: { value: simpleColorFragmentShader, writable: false },
+ simpleColorFragmentShaderESSL300: { value: simpleColorFragmentShaderESSL300, writable: false },
+ simpleVertexShader: { value: simpleVertexShader, writable: false },
+ simpleVertexShaderESSL300: { value: simpleVertexShaderESSL300, writable: false },
+ simpleTextureFragmentShader: { value: simpleTextureFragmentShader, writable: false },
+ simpleTextureFragmentShaderESSL300: { value: simpleTextureFragmentShaderESSL300, writable: false },
+ simpleHighPrecisionTextureFragmentShader: { value: simpleHighPrecisionTextureFragmentShader, writable: false },
+ simpleCubeMapTextureFragmentShader: { value: simpleCubeMapTextureFragmentShader, writable: false },
+ simpleVertexColorFragmentShader: { value: simpleVertexColorFragmentShader, writable: false },
+ simpleVertexColorVertexShader: { value: simpleVertexColorVertexShader, writable: false }
+});
+
+return API;
+
+}());
diff --git a/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/index.html b/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/index.html
new file mode 100644
index 0000000000..1a2a9000d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/index.html
@@ -0,0 +1,401 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Parallel Shader Compile test</title>
+
+ <style>
+ body {
+ margin: 0;
+ }
+ #log {
+ margin: 16px;
+ }
+ @keyframes move {
+ 0% { left: 0%; }
+ 50% { left: calc(100% - 64px); }
+ 100% { left: 0%; }
+ }
+ #block {
+ position: relative;
+ bottom: 0%;
+ left: 0%;
+ width: 32px;
+ height: 32px;
+ background-color: #07f;
+
+ animation-name: move;
+ animation-duration: 2000ms;
+ animation-iteration-count: infinite;
+ }
+ .container {
+ display: flex;
+ flex-wrap: wrap;
+ }
+ .button {
+ width: 260px
+ }
+ </style>
+</head>
+<body>
+ <pre id='log'></pre>
+
+ <!-- The smoothness of the block's moving indicates whether the main thread is too busy. -->
+ <div id='block'></div>
+
+ <script>
+ var testGroup;
+
+ window.addEventListener('error', function (err) {
+ var logElement = document.getElementById('log');
+ logElement.textContent += ' \n';
+ logElement.textContent += err.error.stack.replace(
+ new RegExp(window.location.href, 'g'), '/') + '\n';
+ });
+
+ function setupGLContextSerial(testRun) {
+ var infoElement = testRun.logElement;
+
+ testRun.gl = document.createElement('canvas').getContext('webgl2');
+ if (testRun.gl) {
+ infoElement.textContent += 'webgl2 context created.' + '\n\n';
+ return true;
+ } else {
+ infoElement.textContent += 'webgl2 context is not supported.' + '\n\n';
+ return false;
+ }
+ }
+
+ function setupGLContextParallel(testRun) {
+ var infoElement = testRun.logElement;
+ if (setupGLContextSerial(testRun)) {
+ // Enable KHR_parallel_shader_compile extension
+ testRun.ext = testRun.gl.getExtension('KHR_parallel_shader_compile');
+ if (testRun.ext) {
+ return true;
+ } else {
+ infoElement.textContent += 'KHR_parallel_shader_compile is unavailable, you' +
+ ' may need to turn on the webgl draft extensions for your browser.'
+ }
+ }
+ return false;
+ }
+
+ function releasePrograms(testRun) {
+ var gl = testRun.gl;
+
+ var programs = testRun.programs;
+ for (var i = 0; i < programs.length; i++) {
+ var program = programs[i];
+ if (program.vShader) {
+ gl.deleteShader(program.vShader);
+ program.vShader = null;
+ }
+ if (program.fShader) {
+ gl.deleteShader(program.fShader);
+ program.fShader = null;
+ }
+ if (program.program) {
+ gl.deleteProgram(program.program);
+ program.program = null;
+ }
+ }
+ }
+
+ function showStatistics(testRun) {
+ var infoElement = testRun.logElement;
+ infoElement.textContent += ' ' + '\n';
+ infoElement.textContent += (Math.round(testRun.elapsedTotal * 100) / 100) +
+ 'ms - ' + 'all shaders compiled, and linked.\n';
+ infoElement.textContent += ' ' + '\n';
+ infoElement.textContent += 'done.' + '\n';
+
+ releasePrograms(testRun);
+ }
+
+ function checkShader(gl, shader, infoElement) {
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+ var info = gl.getShaderInfoLog(shader);
+ infoElement.textContent += 'couldn\'t compile shader:\n';
+ infoElement.textContent += info.toString() + '\n';
+ return false;
+ }
+ return true;
+ }
+
+ function checkProgram(gl, program, infoElement) {
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ var info = gl.getProgramInfoLog(program);
+ infoElement.textContent += ' ' + '\n';
+ infoElement.textContent += 'couldn\'t link program:\n';
+ infoElement.textContent += info.toString() + '\n';
+ return false;
+ }
+ return true;
+ }
+
+ function makeAllProgramsSerial(testRun) {
+ var gl = testRun.gl;
+ var infoElement = testRun.logElement;
+
+ var programs = testRun.programs;
+ for (var i = 0; i < programs.length; i++) {
+ var program = programs[i];
+ // vertex shader compilation
+ var vShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vShader, program.vSource);
+ gl.compileShader(vShader);
+ checkShader(gl, vShader, infoElement);
+
+ // fragment shader compilation
+ var fShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fShader, program.fSource);
+ gl.compileShader(fShader);
+ checkShader(gl, fShader, infoElement);
+
+ // program
+ var programHandle = gl.createProgram();
+ gl.attachShader(programHandle, vShader);
+ gl.attachShader(programHandle, fShader);
+ gl.linkProgram(programHandle);
+ checkProgram(gl, programHandle, infoElement);
+ }
+ testRun.elapsedTotal = performance.now() - testRun.start;
+ showStatistics(testRun);
+ };
+
+ function makeAllProgramsParallel(testRun) {
+ var gl = testRun.gl;
+ var infoElement = testRun.logElement;
+
+ var programs = testRun.programs;
+ for (var i = 0; i < programs.length; i++) {
+ var program = programs[i];
+ var vShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vShader, program.vSource);
+ gl.compileShader(vShader);
+
+ var fShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fShader, program.fSource);
+ gl.compileShader(fShader);
+
+ programHandle = gl.createProgram();
+ gl.attachShader(programHandle, vShader);
+ gl.attachShader(programHandle, fShader);
+
+ program.vShader = vShader;
+ program.fShader = fShader;
+ program.program = programHandle;
+ program.status = "Compiling";
+ }
+
+ function checkCompletion() {
+ var ext = testRun.ext;
+
+ var allProgramsLinked = true;
+
+ for (var i = 0; i < programs.length; i++) {
+ var program = programs[i];
+ switch (program.status) {
+ case "Compiling":
+ if (gl.getShaderParameter(program.vShader, ext.COMPLETION_STATUS_KHR) &&
+ gl.getShaderParameter(program.fShader, ext.COMPLETION_STATUS_KHR))
+ {
+ checkShader(gl, program.vShader, infoElement);
+ checkShader(gl, program.fShader, infoElement);
+ gl.linkProgram(program.program);
+ program.status = "Linking";
+ }
+ allProgramsLinked = false;
+ break;
+
+ case "Linking":
+ if (gl.getProgramParameter(program.program, ext.COMPLETION_STATUS_KHR))
+ {
+ checkProgram(gl, program.program, infoElement);
+ program.status = "Done";
+ }
+ else {
+ allProgramsLinked = false;
+ }
+ break;
+
+ case "Done":
+ break;
+ }
+ }
+
+ if (allProgramsLinked) {
+ testRun.elapsedTotal = performance.now() - testRun.start;
+ showStatistics(testRun);
+ }
+ else {
+ requestAnimationFrame(checkCompletion);
+ }
+ }
+ requestAnimationFrame(checkCompletion);
+ }
+
+ function parsePrograms(testRun) {
+ var gl = testRun.gl;
+ var infoElement = testRun.logElement;
+
+ // Parse programs from the cached text, formatted as:
+ // __BEGINPROGRAM__
+ // __VERTEXSHADER__
+ // shader source line
+ // ...
+ // __FRAGMENTSHADER__
+ // shader source line
+ // ...
+ // __ENDPROGRAM__
+ //
+ // __BEGINPROGRAM__
+ // ...
+ var arrayOfLines = testRun.test.shaderCache.match(/[^\r\n]+/g);
+ var programs = [];
+ var currentProgram = {};
+ var currentShader;
+ var shaderSourceLine = false;
+ for (var ii = 0; ii < arrayOfLines.length; ii++) {
+ var cur = arrayOfLines[ii];
+ // Use random numbers to fool the program cache mechanism.
+ if (cur.indexOf('PROGRAM_CACHE_BREAKER_RANDOM') != -1) {
+ cur = cur.replace('PROGRAM_CACHE_BREAKER_RANDOM', Math.random())
+ }
+
+ if (cur == '__VERTEXSHADER__') {
+ currentShader = [];
+ shaderSourceLine = true;
+ } else if (cur == '__FRAGMENTSHADER__') {
+ currentProgram.vSource = currentShader.join('\n');
+
+ currentShader = [];
+ shaderSourceLine = true;
+ } else if (cur == '__ENDPROGRAM__') {
+ currentProgram.fSource = currentShader.join('\n');
+ programs.push(currentProgram);
+
+ currentProgram = {};
+ currentShader = [];
+ shaderSourceLine = false;
+ } else if (shaderSourceLine) {
+ currentShader.push(cur);
+ }
+ }
+
+ infoElement.textContent += programs.length + ' programs found.' + '\n';
+ infoElement.textContent += 'starting compilations ...' + '\n';
+
+ testRun.start = performance.now();
+
+ testRun.programs = programs;
+
+ testRun.makeAllPrograms(testRun);
+ };
+
+
+ function runTest(index, isParallel) {
+ var testRun = {};
+ var test = testGroup[index];
+ testRun.test = test;
+ testRun.name = test.name + (isParallel ? "_parallel" : "_serial");
+ testRun.logElement = document.getElementById(testRun.name);
+ testRun.logElement.textContent = '';
+
+ testRun.setupGLContext =
+ (isParallel ? setupGLContextParallel : setupGLContextSerial);
+
+ testRun.makeAllPrograms =
+ (isParallel ? makeAllProgramsParallel : makeAllProgramsSerial);
+
+ if (!testRun.setupGLContext(testRun)) {
+ return;
+ }
+
+ if (test.shaderCache === undefined) {
+ // load shader cache
+ var xhr = new XMLHttpRequest();
+ xhr.addEventListener('load', function() {
+ test.shaderCache = xhr.responseText;
+
+ requestAnimationFrame(function() {
+ parsePrograms(testRun);
+ });
+ });
+ xhr.open('GET', test.location);
+ xhr.send();
+ } else {
+ parsePrograms(testRun);
+ }
+ }
+
+ function createElement(element, attribute, inner) {
+ if (element === undefined) {
+ return false;
+ }
+ if (inner === undefined) {
+ inner = [];
+ }
+ var el = document.createElement(element);
+ if (typeof(attribute) === 'object') {
+ for (var key in attribute) {
+ el.setAttribute(key, attribute[key]);
+ }
+ }
+ if (!Array.isArray(inner)) {
+ inner = [inner];
+ }
+ for (var k = 0; k < inner.length; k++) {
+ if (inner[k].tagName) {
+ el.appendChild(inner[k]);
+ } else {
+ el.appendChild(document.createTextNode(inner[k]));
+ }
+ }
+ return el;
+ }
+
+ var container = createElement("div", {"class": "container"});
+ document.body.appendChild(container);
+
+ testGroup = [{
+ 'location': './shaders/aquarium/shader-cache.txt',
+ 'name': 'aquarium'
+ },
+ ];
+
+ testGroup.forEach((test, index) => {
+
+ function createTestView(test, index, isParallel) {
+
+ testName = test.name + (isParallel ? "_parallel" : "_serial");
+
+ var tButton = createElement(
+ 'button',
+ {'class': 'button', 'onclick': 'runTest(' + index + ', ' + isParallel + ')'},
+ testName
+ );
+
+ var tPrex = createElement("pre");
+ var tPre = createElement("textarea", { "id": testName, "rows": 10, "cols": 30});
+ var tDivContainer = createElement(
+ "div",
+ {"id": " " + testName + "_container"},
+ [tButton, tPrex, tPre]
+ );
+ container.appendChild(tDivContainer);
+ }
+
+ createTestView(test, index, false);
+ createTestView(test, index, true);
+ });
+
+ </script>
+</body>
diff --git a/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/README b/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/README
new file mode 100644
index 0000000000..3dff676045
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/README
@@ -0,0 +1,35 @@
+1. Pulled from http://webglsamples.org/aquarium/aquarium.html, the license of which is:
+
+<!--
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html>
+
+2. Inserted a few redundant shader code lines to bypass program cache.
diff --git a/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/shader-cache.txt b/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/shader-cache.txt
new file mode 100644
index 0000000000..c3ce8cf6a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/performance/parallel_shader_compile/shaders/aquarium/shader-cache.txt
@@ -0,0 +1,2747 @@
+<!--
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+
+
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+attribute vec4 position;
+varying vec4 v_position;
+void main() {
+ v_position = position;
+ gl_Position = position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform samplerCube skybox;
+uniform mat4 viewDirectionProjectionInverse;
+varying vec4 v_position;
+void main() {
+ vec4 t = viewDirectionProjectionInverse * v_position;
+ gl_FragColor = textureCube(
+ skybox,
+ normalize(t.xyz));
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+attribute vec4 position;
+attribute vec2 texCoord;
+varying vec2 v_texCoord;
+uniform mat4 worldViewProjection;
+void main() {
+ v_texCoord = texCoord;
+ gl_Position = (worldViewProjection * position);
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+
+varying vec2 v_texCoord;
+uniform vec4 colorMult;
+uniform sampler2D colorMap;
+void main() {
+ gl_FragColor = texture2D(colorMap, v_texCoord) * colorMult;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+uniform mat4 worldViewProjection;
+uniform mat4 world;
+uniform vec3 worldVelocity;
+uniform vec3 worldAcceleration;
+uniform float timeRange;
+uniform float time;
+uniform float timeOffset;
+uniform float frameDuration;
+uniform float numFrames;
+
+// Incoming vertex attributes
+attribute vec4 uvLifeTimeFrameStart; // uv, lifeTime, frameStart
+attribute vec4 positionStartTime; // position.xyz, startTime
+attribute vec4 velocityStartSize; // velocity.xyz, startSize
+attribute vec4 accelerationEndSize; // acceleration.xyz, endSize
+attribute vec4 spinStartSpinSpeed; // spinStart.x, spinSpeed.y
+attribute vec4 orientation; // orientation quaternion
+attribute vec4 colorMult; // multiplies color and ramp textures
+
+// Outgoing variables to fragment shader
+varying vec2 outputTexcoord;
+varying float outputPercentLife;
+varying vec4 outputColorMult;
+
+void main() {
+ vec2 uv = uvLifeTimeFrameStart.xy;
+ float lifeTime = uvLifeTimeFrameStart.z;
+ float frameStart = uvLifeTimeFrameStart.w;
+ vec3 position = positionStartTime.xyz;
+ float startTime = positionStartTime.w;
+ vec3 velocity = (world * vec4(velocityStartSize.xyz,
+ 0.)).xyz + worldVelocity;
+ float startSize = velocityStartSize.w;
+ vec3 acceleration = (world * vec4(accelerationEndSize.xyz,
+ 0)).xyz + worldAcceleration;
+ float endSize = accelerationEndSize.w;
+ float spinStart = spinStartSpinSpeed.x;
+ float spinSpeed = spinStartSpinSpeed.y;
+
+ float localTime = mod((time - timeOffset - startTime), timeRange);
+ float percentLife = localTime / lifeTime;
+
+ float frame = mod(floor(localTime / frameDuration + frameStart),
+ numFrames);
+ float uOffset = frame / numFrames;
+ float u = uOffset + (uv.x + 0.5) * (1. / numFrames);
+
+ outputTexcoord = vec2(u, uv.y + 0.5);
+ outputColorMult = colorMult;
+
+ float size = mix(startSize, endSize, percentLife);
+ size = (percentLife < 0. || percentLife > 1.) ? 0. : size;
+ float s = sin(spinStart + spinSpeed * localTime);
+ float c = cos(spinStart + spinSpeed * localTime);
+
+ vec4 rotatedPoint = vec4((uv.x * c + uv.y * s) * size, 0.,
+ (uv.x * s - uv.y * c) * size, 1.);
+ vec3 center = velocity * localTime +
+ acceleration * localTime * localTime +
+ position;
+
+ vec4 q2 = orientation + orientation;
+ vec4 qx = orientation.xxxw * q2.xyzx;
+ vec4 qy = orientation.xyyw * q2.xyzy;
+ vec4 qz = orientation.xxzw * q2.xxzz;
+
+ mat4 localMatrix = mat4(
+ (1.0 - qy.y) - qz.z,
+ qx.y + qz.w,
+ qx.z - qy.w,
+ 0,
+
+ qx.y - qz.w,
+ (1.0 - qx.x) - qz.z,
+ qy.z + qx.w,
+ 0,
+
+ qx.z + qy.w,
+ qy.z - qx.w,
+ (1.0 - qx.x) - qy.y,
+ 0,
+
+ center.x, center.y, center.z, 1);
+ rotatedPoint = localMatrix * rotatedPoint;
+ outputPercentLife = percentLife;
+ gl_Position = worldViewProjection * rotatedPoint;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__FRAGMENTSHADER__
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D rampSampler;
+uniform sampler2D colorSampler;
+
+// Incoming variables from vertex shader
+varying vec2 outputTexcoord;
+varying float outputPercentLife;
+varying vec4 outputColorMult;
+
+void main() {
+ vec4 colorMult = texture2D(rampSampler,
+ vec2(outputPercentLife, 0.5)) *
+ outputColorMult;
+ gl_FragColor = texture2D(colorSampler, outputTexcoord) * colorMult;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+uniform mat4 viewProjection;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform vec3 worldVelocity;
+uniform vec3 worldAcceleration;
+uniform float timeRange;
+uniform float time;
+uniform float timeOffset;
+uniform float frameDuration;
+uniform float numFrames;
+
+// Incoming vertex attributes
+attribute vec4 uvLifeTimeFrameStart; // uv, lifeTime, frameStart
+attribute vec4 positionStartTime; // position.xyz, startTime
+attribute vec4 velocityStartSize; // velocity.xyz, startSize
+attribute vec4 accelerationEndSize; // acceleration.xyz, endSize
+attribute vec4 spinStartSpinSpeed; // spinStart.x, spinSpeed.y
+attribute vec4 colorMult; // multiplies color and ramp textures
+
+// Outgoing variables to fragment shader
+varying vec2 outputTexcoord;
+varying float outputPercentLife;
+varying vec4 outputColorMult;
+
+void main() {
+ vec2 uv = uvLifeTimeFrameStart.xy;
+ float lifeTime = uvLifeTimeFrameStart.z;
+ float frameStart = uvLifeTimeFrameStart.w;
+ vec3 position = positionStartTime.xyz;
+ float startTime = positionStartTime.w;
+ vec3 velocity = (world * vec4(velocityStartSize.xyz,
+ 0.)).xyz + worldVelocity;
+ float startSize = velocityStartSize.w;
+ vec3 acceleration = (world * vec4(accelerationEndSize.xyz,
+ 0)).xyz + worldAcceleration;
+ float endSize = accelerationEndSize.w;
+ float spinStart = spinStartSpinSpeed.x;
+ float spinSpeed = spinStartSpinSpeed.y;
+
+ float localTime = mod((time - timeOffset - startTime), timeRange);
+ float percentLife = localTime / lifeTime;
+
+ float frame = mod(floor(localTime / frameDuration + frameStart),
+ numFrames);
+ float uOffset = frame / numFrames;
+ float u = uOffset + (uv.x + 0.5) * (1. / numFrames);
+
+ outputTexcoord = vec2(u, uv.y + 0.5);
+ outputColorMult = colorMult;
+
+ vec3 basisX = viewInverse[0].xyz;
+ vec3 basisZ = viewInverse[1].xyz;
+
+ float size = mix(startSize, endSize, percentLife);
+ size = (percentLife < 0. || percentLife > 1.) ? 0. : size;
+ float s = sin(spinStart + spinSpeed * localTime);
+ float c = cos(spinStart + spinSpeed * localTime);
+
+ vec2 rotatedPoint = vec2(uv.x * c + uv.y * s,
+ -uv.x * s + uv.y * c);
+ vec3 localPosition = vec3(basisX * rotatedPoint.x +
+ basisZ * rotatedPoint.y) * size +
+ velocity * localTime +
+ acceleration * localTime * localTime +
+ position;
+
+ outputPercentLife = percentLife;
+ gl_Position = viewProjection * vec4(localPosition + world[3].xyz, 1.);
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__FRAGMENTSHADER__
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D rampSampler;
+uniform sampler2D colorSampler;
+
+// Incoming variables from vertex shader
+varying vec2 outputTexcoord;
+varying float outputPercentLife;
+varying vec4 outputColorMult;
+
+void main() {
+ vec4 colorMult = texture2D(rampSampler,
+ vec2(outputPercentLife, 0.5)) *
+ outputColorMult;
+ gl_FragColor = texture2D(colorSampler, outputTexcoord) * colorMult;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec3 tangentNormal = normalSpec.xyz - // #normalMap
+ vec3(0.5, 0.5, 0.5); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec3 tangentNormal = normalSpec.xyz - // #normalMap
+ vec3(0.5, 0.5, 0.5); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec3 normal = normalize(v_normal); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec3 normal = normalize(v_normal); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;
+uniform sampler2D reflectionMap; // #reflection
+uniform samplerCube skybox; // #reflecton
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 reflection = texture2D(reflectionMap, v_texCoord.xy); // #reflection
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec4 skyColor = textureCube(skybox, -reflect(surfaceToView, normal)); // #reflection
+
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;
+uniform sampler2D reflectionMap; // #reflection
+uniform samplerCube skybox; // #reflecton
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 reflection = texture2D(reflectionMap, v_texCoord.xy); // #reflection
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec4 skyColor = textureCube(skybox, -reflect(surfaceToView, normal)); // #reflection
+
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;
+uniform samplerCube skybox; // #reflecton
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 reflection = vec4(0,0,0,0); // #noReflection
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec4 skyColor = vec4(0.5,0.5,1,1); // #noReflection
+
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;
+uniform samplerCube skybox; // #reflecton
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 reflection = vec4(0,0,0,0); // #noReflection
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec4 skyColor = vec4(0.5,0.5,1,1); // #noReflection
+
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;
+uniform samplerCube skybox; // #reflecton
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec4 reflection = vec4(0,0,0,0); // #noReflection
+ vec3 normal = normalize(v_normal); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec4 skyColor = vec4(0.5,0.5,1,1); // #noReflection
+
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;
+uniform samplerCube skybox; // #reflecton
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec4 reflection = vec4(0,0,0,0); // #noReflection
+ vec3 normal = normalize(v_normal); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec4 skyColor = vec4(0.5,0.5,1,1); // #noReflection
+
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(mix(
+ skyColor,
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a),
+ 1.0 - reflection.r).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ tangentNormal = normalize(tangentNormal + vec3(0, 0, 2)); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ tangentNormal = normalize(tangentNormal + vec3(0, 0, 2)); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec3 normal = normalize(v_normal); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 viewProjection;
+uniform vec3 worldPosition;
+uniform vec3 nextPosition;
+uniform float scale;
+uniform float time;
+uniform float fishLength;
+uniform float fishWaveLength;
+uniform float fishBendAmount;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent; // #normalMap
+attribute vec3 binormal; // #normalMap
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 vz = normalize(worldPosition - nextPosition);
+ vec3 vx = normalize(cross(vec3(0,1,0), vz));
+ vec3 vy = cross(vz, vx);
+ mat4 orientMat = mat4(
+ vec4(vx, 0),
+ vec4(vy, 0),
+ vec4(vz, 0),
+ vec4(worldPosition, 1));
+ mat4 scaleMat = mat4(
+ vec4(scale, 0, 0, 0),
+ vec4(0, scale, 0, 0),
+ vec4(0, 0, scale, 0),
+ vec4(0, 0, 0, 1));
+ mat4 world = orientMat * scaleMat;
+ mat4 worldViewProjection = viewProjection * world;
+ mat4 worldInverseTranspose = world;
+
+ v_texCoord = texCoord;
+ // NOTE:If you change this you need to change the laser code to match!
+ float mult = position.z > 0.0 ?
+ (position.z / fishLength) :
+ (-position.z / fishLength * 2.0);
+ float s = sin(time + mult * fishWaveLength);
+ float a = sign(s);
+ float offset = pow(mult, 2.0) * s * fishBendAmount;
+ v_position = (
+ worldViewProjection *
+ (position +
+ vec4(offset, 0, 0, 0)));
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec3 normal = normalize(v_normal); // #noNormalMap
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4(
+ (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor * normalSpec.a)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent;
+attribute vec3 binormal;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform sampler2D reflectionMap;
+uniform samplerCube skybox;
+uniform float shininess;
+uniform float specularFactor;
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 reflection = texture2D(reflectionMap, v_texCoord.xy);
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+// tangentNormal = normalize(tangentNormal + vec3(0,0,refractionFudge));
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+
+ vec4 skyColor = textureCube(skybox, -reflect(surfaceToView, normal));
+ float fudgeAmount = 1.1;
+ vec3 fudge = skyColor.rgb * vec3(fudgeAmount, fudgeAmount, fudgeAmount);
+ float bright = min(1.0, fudge.r * fudge.g * fudge.b);
+ vec4 reflectColor =
+ mix(vec4(skyColor.rgb, bright),
+ diffuseColor,
+ (1.0 - reflection.r));
+ float r = abs(dot(surfaceToView, normal));
+ gl_FragColor = vec4(mix(
+ skyColor,
+ reflectColor,
+ ((r + 0.3) * (reflection.r))).rgb, 1.0 - r);
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent;
+attribute vec3 binormal;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D reflectionMap;
+uniform samplerCube skybox;
+uniform float shininess;
+uniform float specularFactor;
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec4 reflection = texture2D(reflectionMap, v_texCoord.xy);
+// tangentNormal = normalize(tangentNormal + vec3(0,0,refractionFudge));
+ vec3 normal = normalize(v_normal); // #noNormalMap
+
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+
+ vec4 skyColor = textureCube(skybox, -reflect(surfaceToView, normal));
+ float fudgeAmount = 1.1;
+ vec3 fudge = skyColor.rgb * vec3(fudgeAmount, fudgeAmount, fudgeAmount);
+ float bright = min(1.0, fudge.r * fudge.g * fudge.b);
+ vec4 reflectColor =
+ mix(vec4(skyColor.rgb, bright),
+ diffuseColor,
+ (1.0 - reflection.r));
+ float r = abs(dot(surfaceToView, normal));
+ gl_FragColor = vec4(mix(
+ skyColor,
+ reflectColor,
+ ((r + 0.3) * (reflection.r))).rgb, 1.0 - r);
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec3 normal = normalize(v_normal);
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4((
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor)).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ vec3 normal = normalize(v_normal);
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4((
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent;
+attribute vec3 binormal;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform sampler2D reflectionMap;
+uniform samplerCube skybox;
+uniform float shininess;
+uniform float specularFactor;
+uniform float refractionFudge;
+uniform float eta;
+uniform float tankColorFudge;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord) +
+ vec4(tankColorFudge, tankColorFudge, tankColorFudge, 1);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 refraction = texture2D(reflectionMap, v_texCoord.xy);
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ tangentNormal = normalize(tangentNormal + vec3(0,0,refractionFudge)); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+
+ vec3 refractionVec = refract(surfaceToView, normal, eta);
+
+ vec4 skyColor = textureCube(skybox, refractionVec);
+
+// vec4 bumpSkyColor = textureCube(skybox, refractionVec);
+// vec4 nonBumpSkyColor = textureCube(
+// skybox,
+// refract(surfaceToView, normalize(v_normal), eta));
+// vec4 skyColor = mix(nonBumpSkyColor, bumpSkyColor, normalSpec.a);
+ vec4 outColor = vec4(
+ mix(skyColor * diffuseColor, diffuseColor, refraction.r).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent;
+attribute vec3 binormal;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap; // #normalMap
+uniform sampler2D reflectionMap;
+uniform samplerCube skybox;
+uniform float shininess;
+uniform float specularFactor;
+uniform float refractionFudge;
+uniform float eta;
+uniform float tankColorFudge;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord) +
+ vec4(tankColorFudge, tankColorFudge, tankColorFudge, 1);
+ mat3 tangentToWorld = mat3(v_tangent, // #normalMap
+ v_binormal, // #normalMap
+ v_normal); // #normalMap
+ vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap
+ vec4 refraction = texture2D(reflectionMap, v_texCoord.xy);
+ vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap
+ tangentNormal = normalize(tangentNormal + vec3(0,0,refractionFudge)); // #normalMap
+ vec3 normal = (tangentToWorld * tangentNormal); // #normalMap
+ normal = normalize(normal); // #normalMap
+
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+
+ vec3 refractionVec = refract(surfaceToView, normal, eta);
+
+ vec4 skyColor = textureCube(skybox, refractionVec);
+
+// vec4 bumpSkyColor = textureCube(skybox, refractionVec);
+// vec4 nonBumpSkyColor = textureCube(
+// skybox,
+// refract(surfaceToView, normalize(v_normal), eta));
+// vec4 skyColor = mix(nonBumpSkyColor, bumpSkyColor, normalSpec.a);
+ vec4 outColor = vec4(
+ mix(skyColor * diffuseColor, diffuseColor, refraction.r).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent;
+attribute vec3 binormal;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D reflectionMap;
+uniform samplerCube skybox;
+uniform float shininess;
+uniform float specularFactor;
+uniform float refractionFudge;
+uniform float eta;
+uniform float tankColorFudge;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord) +
+ vec4(tankColorFudge, tankColorFudge, tankColorFudge, 1);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec4 refraction = texture2D(reflectionMap, v_texCoord.xy);
+ vec3 normal = normalize(v_normal); // #noNormalMap
+
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+
+ vec3 refractionVec = refract(surfaceToView, normal, eta);
+
+ vec4 skyColor = textureCube(skybox, refractionVec);
+
+// vec4 bumpSkyColor = textureCube(skybox, refractionVec);
+// vec4 nonBumpSkyColor = textureCube(
+// skybox,
+// refract(surfaceToView, normalize(v_normal), eta));
+// vec4 skyColor = mix(nonBumpSkyColor, bumpSkyColor, normalSpec.a);
+ vec4 outColor = vec4(
+ mix(skyColor * diffuseColor, diffuseColor, refraction.r).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 worldViewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 world;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+attribute vec3 tangent;
+attribute vec3 binormal;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent; // #normalMap
+varying vec3 v_binormal; // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ v_texCoord = texCoord;
+ v_position = (worldViewProjection * position);
+ v_normal = (worldInverseTranspose * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ v_binormal = (worldInverseTranspose * vec4(binormal, 0)).xyz; // #normalMap
+ v_tangent = (worldInverseTranspose * vec4(tangent, 0)).xyz; // #normalMap
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D reflectionMap;
+uniform samplerCube skybox;
+uniform float shininess;
+uniform float specularFactor;
+uniform float refractionFudge;
+uniform float eta;
+uniform float tankColorFudge;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord) +
+ vec4(tankColorFudge, tankColorFudge, tankColorFudge, 1);
+ vec4 normalSpec = vec4(0,0,0,0); // #noNormalMap
+ vec4 refraction = texture2D(reflectionMap, v_texCoord.xy);
+ vec3 normal = normalize(v_normal); // #noNormalMap
+
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+
+ vec3 refractionVec = refract(surfaceToView, normal, eta);
+
+ vec4 skyColor = textureCube(skybox, refractionVec);
+
+// vec4 bumpSkyColor = textureCube(skybox, refractionVec);
+// vec4 nonBumpSkyColor = textureCube(
+// skybox,
+// refract(surfaceToView, normalize(v_normal), eta));
+// vec4 skyColor = mix(nonBumpSkyColor, bumpSkyColor, normalSpec.a);
+ vec4 outColor = vec4(
+ mix(skyColor * diffuseColor, diffuseColor, refraction.r).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 world;
+uniform mat4 viewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+uniform float time;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 toCamera = normalize(viewInverse[3].xyz - world[3].xyz);
+ vec3 yAxis = vec3(0, 1, 0);
+ vec3 xAxis = cross(yAxis, toCamera);
+ vec3 zAxis = cross(xAxis, yAxis);
+
+ mat4 newWorld = mat4(
+ vec4(xAxis, 0),
+ vec4(yAxis, 0),
+ vec4(xAxis, 0),
+ world[3]);
+
+ v_texCoord = texCoord;
+ v_position = position + vec4(
+ sin(time * 0.5) * pow(position.y * 0.07, 2.0) * 1.0,
+ -4, // TODO(gman): remove this hack
+ 0,
+ 0);
+ v_position = (viewProjection * newWorld) * v_position;
+ v_normal = (newWorld * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+uniform float fogPower;
+uniform float fogMult;
+uniform float fogOffset;
+uniform vec4 fogColor;
+
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ if (diffuseColor.a < 0.3) {
+ discard;
+ }
+ vec3 normal = normalize(v_normal);
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4((
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor)).rgb,
+ diffuseColor.a);
+ outColor = mix(outColor, vec4(fogColor.rgb, diffuseColor.a),
+ clamp(pow((v_position.z / v_position.w), fogPower) * fogMult - fogOffset,0.0,1.0));
+
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
+__BEGINPROGRAM__
+__VERTEXSHADER__
+
+uniform mat4 world;
+uniform mat4 viewProjection;
+uniform vec3 lightWorldPos;
+uniform mat4 viewInverse;
+uniform mat4 worldInverseTranspose;
+uniform float time;
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec2 texCoord;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+void main() {
+ vec3 toCamera = normalize(viewInverse[3].xyz - world[3].xyz);
+ vec3 yAxis = vec3(0, 1, 0);
+ vec3 xAxis = cross(yAxis, toCamera);
+ vec3 zAxis = cross(xAxis, yAxis);
+
+ mat4 newWorld = mat4(
+ vec4(xAxis, 0),
+ vec4(yAxis, 0),
+ vec4(xAxis, 0),
+ world[3]);
+
+ v_texCoord = texCoord;
+ v_position = position + vec4(
+ sin(time * 0.5) * pow(position.y * 0.07, 2.0) * 1.0,
+ -4, // TODO(gman): remove this hack
+ 0,
+ 0);
+ v_position = (viewProjection * newWorld) * v_position;
+ v_normal = (newWorld * vec4(normal, 0)).xyz;
+ v_surfaceToLight = lightWorldPos - (world * position).xyz;
+ v_surfaceToView = (viewInverse[3] - (world * position)).xyz;
+ gl_Position = v_position;
+ gl_Position.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+
+__FRAGMENTSHADER__
+
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+void main() {
+ vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+ if (diffuseColor.a < 0.3) {
+ discard;
+ }
+ vec3 normal = normalize(v_normal);
+ vec3 surfaceToLight = normalize(v_surfaceToLight);
+ vec3 surfaceToView = normalize(v_surfaceToView);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litR = lit(dot(normal, surfaceToLight),
+ dot(normal, halfVector), shininess);
+ vec4 outColor = vec4((
+ lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+ specular * litR.z * specularFactor)).rgb,
+ diffuseColor.a);
+ // #fogCode
+ gl_FragColor = outColor;
+ gl_FragColor.x += PROGRAM_CACHE_BREAKER_RANDOM;
+}
+
+
+__ENDPROGRAM__
diff --git a/dom/canvas/test/webgl-conf/checkout/performance/webgl_webcodecs_video_frame/index.html b/dom/canvas/test/webgl-conf/checkout/performance/webgl_webcodecs_video_frame/index.html
new file mode 100644
index 0000000000..97eb95a174
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/performance/webgl_webcodecs_video_frame/index.html
@@ -0,0 +1,186 @@
+<!-- This was created from the demo of webcodecs-blogpost-demo.glitch.me, and added the webgl support for test only purpose. -->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="origin-trial"
+ content="AoSY6Q4OOuuZVXTqOwJlfk4n77EL0esumtLRHj+9V97JoFfLq4AKsWlza8A8HmxTx1PU7SSzpjWK6F62bwWLPQYAAAB3eyJvcmlnaW4iOiJodHRwczovL3dlYmNvZGVjcy1ibG9ncG9zdC1kZW1vLmdsaXRjaC5tZTo0NDMiLCJmZWF0dXJlIjoiV2ViQ29kZWNzIiwiZXhwaXJ5IjoxNjA1NDc0OTQ4LCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
+ <title>WebCodecs API demo: Encoding and Decoding</title>
+ <style>
+ canvas {
+ padding: 10px;
+ background: gold;
+ }
+
+ button {
+ background-color: #555555;
+ border: none;
+ color: white;
+ padding: 15px 32px;
+ width: 150px;
+ text-align: center;
+ display: block;
+ font-size: 16px;
+ }
+ </style>
+ <script src="../../../../extensions/proposals/WEBGL_webcodecs_video_frame/webgl_webcodecs_video_frame.js"></script>
+</head>
+
+<body>
+ <canvas id="src" width="640" height="480"></canvas>
+ <button onclick="playPause()">Pause</button>
+ <canvas id="dst" width="640" height="480"></canvas>
+ <script>
+ let codec_string = "vp8";
+ let keep_going = true;
+
+ function playPause() {
+ keep_going = !keep_going;
+ let btn = document.querySelector("button");
+ if (keep_going) {
+ btn.innerText = "Pause";
+ } else {
+ btn.innerText = "Play";
+ }
+ }
+
+ async function startDrawing() {
+ let cnv = document.getElementById("src");
+ var ctx = cnv.getContext('2d', { alpha: false });
+
+ ctx.fillStyle = "white";
+ let width = cnv.width;
+ let height = cnv.height;
+ let cx = width / 2;
+ let cy = height / 2;
+ let r = Math.min(width, height) / 5;
+ let drawOneFrame = function (time) {
+ let angle = Math.PI * 2 * (time / 5000);
+ let scale = 1 + 0.3 * Math.sin(Math.PI * 2 * (time / 7000));
+ ctx.save();
+ ctx.fillRect(0, 0, width, height);
+
+ ctx.translate(cx, cy);
+ ctx.rotate(angle);
+ ctx.scale(scale, scale);
+
+ ctx.font = '30px Verdana';
+ ctx.fillStyle = 'black';
+ const text = "😊📹📷Hello WEBGL_webcodecs_video_frame🎥🎞️😊";
+ const size = ctx.measureText(text).width;
+ ctx.fillText(text, -size / 2, 0);
+ ctx.restore();
+ window.requestAnimationFrame(drawOneFrame);
+ }
+ window.requestAnimationFrame(drawOneFrame);
+ }
+
+ function captureAndEncode(processChunk) {
+ let cnv = document.getElementById("src");
+ let fps = 30;
+ let pending_outputs = 0;
+ let frame_counter = 0;
+ let stream = cnv.captureStream(fps);
+ let processor = new MediaStreamTrackProcessor(stream.getVideoTracks()[0]);
+
+ const init = {
+ output: (chunk) => {
+ pending_outputs--;
+ processChunk(chunk);
+ },
+ error: (e) => {
+ console.log(e.message);
+ vtr.stop();
+ }
+ };
+
+ const config = {
+ codec: codec_string,
+ width: cnv.width,
+ height: cnv.height,
+ bitrate: 10e6,
+ framerate: fps,
+ };
+
+ let encoder = new VideoEncoder(init);
+ encoder.configure(config);
+
+ const frame_reader = processor.readable.getReader();
+ frame_reader.read().then(function processFrame({done, value}) {
+ if (done)
+ return;
+
+ if (pending_outputs > 30) {
+ // Too many frames in flight, encoder is overwhelmed
+ // let's drop this frame.
+ value.close();
+ frame_reader.read().then(processFrame);
+ return;
+ }
+
+ if(!keep_going) {
+ value.close();
+ frame_reader.read().then(processFrame);
+ return;
+ }
+
+ frame_counter++;
+ pending_outputs++;
+ const insert_keyframe = (frame_counter % 150) == 0;
+ encoder.encode(value, { keyFrame: insert_keyframe });
+
+ frame_reader.read().then(processFrame);
+ });
+ }
+
+
+ function startDecodingAndRendering(cnv, handleFrame) {
+
+ const init = {
+ output: handleFrame,
+ error: (e) => {
+ console.log(e.message);
+ }
+ };
+
+ const config = {
+ codec: codec_string,
+ codedWidth: cnv.width,
+ codedHeight: cnv.height
+ };
+
+ let decoder = new VideoDecoder(init);
+ decoder.configure(config);
+ return decoder;
+ }
+
+
+ function main() {
+ if (!("VideoEncoder" in window)) {
+ document.body.innerHTML = "<h1>WebCodecs API is not supported.</h1>";
+ return;
+ }
+
+ let cnv = document.getElementById("dst");
+ let handleFrame = requestWebGLVideoFrameHandler(cnv);
+ if (handleFrame === null) {
+ document.body.innerHTML =
+ "<h1>Unable to request WebGL to render video frames.</h1>";
+ return;
+ }
+
+ startDrawing();
+ let decoder = startDecodingAndRendering(cnv, handleFrame);
+ captureAndEncode((chunk) => {
+ decoder.decode(chunk);
+ });
+ }
+
+ document.body.onload = main;
+ </script>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/dom/canvas/test/webgl-conf/checkout/py/lint/LICENSE b/dom/canvas/test/webgl-conf/checkout/py/lint/LICENSE
new file mode 100644
index 0000000000..45896e6be2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/py/lint/LICENSE
@@ -0,0 +1,30 @@
+W3C 3-clause BSD License
+
+http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of works must retain the original copyright notice,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the original copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of the W3C nor the names of its contributors may be
+ used to endorse or promote products derived from this work without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/dom/canvas/test/webgl-conf/checkout/py/lint/README.md b/dom/canvas/test/webgl-conf/checkout/py/lint/README.md
new file mode 100644
index 0000000000..fea854baf9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/py/lint/README.md
@@ -0,0 +1,115 @@
+## Introduction
+
+We have a lint tool for catching common mistakes in test files. The tool comes from
+[W3C/wpt-tools](https://github.com/w3c/wpt-tools/) with modification for catching
+common mistakes in submitted pull request, all WebGL/sdk/tests and specified folder.
+
+The copyright of this tool is belong to W3C and/or the author listed in the test
+file. The tool is dual-licensed under the
+[W3C Test Suite License](http://www.w3.org/Consortium/Legal/2008/04-testsuite-license)
+and [BSD 3-clause License](http://www.w3.org/Consortium/Legal/2008/03-bsd-license),
+which are introduced in
+[W3C's test suite licensing policy](http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright).
+
+Now the tool can check html, htm, xhtml, xhtm, js, frag and vert files.
+- You can run it manually by starting the `lint.py` executable from the root of your local
+WebGL/sdk/tests working directory like this:
+
+```
+./py/lint/lint.py
+```
+
+You can use the lint tool to check submitted pull request and fix the errors reported by the tool.
+Reviewers will not merge branches with tests that have lint errors, so you must either
+[fix all lint errors](#fixing-lint-errors) or update
+[allow-list test files] (#updating-the-allowlist) to suppress the errors.
+
+## Usage of lint tool
+
+1. Check other repos, specify the repo name with `-r`, default
+is WebGL/sdk/tests:</br>
+<code>
+./py/lint/lint.py -r demo-express
+</code>
+1. Check submitted pull request:</br>
+<code>
+./py/lint/lint.py -p
+</code>
+1. Check specified folder, the specified folder must be relative path of
+WebGL/sdk/tests:</br>
+<code>
+./py/lint/lint.py -d conformance/attribs
+</code>
+
+## Fixing lint errors
+
+You must fix any errors the lint tool reports, unless an error is for
+something essential to a certain test or that for some other exceptional
+reason shouldn't prevent the test from being merged. In those cases you can
+update [allow-list test files](#updating-the-allowlist) to suppress the errors.
+Otherwise, use the details in this section to fix all errors reported.
+
+* **CR AT EOL**: Test-file line ends with CR (U+000D) character; **fix**:
+ reformat file so each line just has LF (U+000A) line ending (standard,
+ cross-platform "Unix" line endings instead of, e.g., DOS line endings).
+
+* **INDENT TABS**: Test-file line starts with one or more tab characters;
+ **fix**: use spaces to replace any tab characters at beginning of lines.
+
+* **TRAILING WHITESPACE**: Test-file line has trailing whitespace; **fix**:
+ remove trailing whitespace from all lines in the file.
+
+* **UNNECESSARY EXECUTABLE PERMISSION**: Test file contains unnecessary executable permission; **fix**:
+ remove unnecessary executable permission of the file.
+
+* **FILENAME WHITESPACE**: Test file name contains white space; **fix**:
+ remove white space from test file name.
+
+## Updating the allowlist
+
+Normally you must [fix all lint errors](#fixing-lint-errors). But in the
+unusual case of error reports for things essential to certain tests or that
+for other exceptional reasons shouldn't prevent a merge of a test, you can
+update and commit the `lint.allowlist` file in the WebGL/sdk/tests/py/lint/
+directory to suppress errors the lint tool would report for a test file.
+
+To add a test file or directory to the allowlist, use the following format:
+
+```
+ERROR TYPE:file/name/pattern
+```
+
+For example, to allowlist the file `example/file.html` such that all
+`TRAILING WHITESPACE` errors the lint tool would report for it are
+suppressed, add the following line to the `lint.allowlist` file.
+
+```
+TRAILING WHITESPACE:example/file.html
+```
+
+To allowlist an entire directory rather than just one file, use the `*`
+wildcard. For example, to allowlist the `example` directory such that all
+`TRAILING WHITESPACE` errors the lint tool would report for any files in it
+are suppressed, add the following line to the `lint.allowlist` file.
+
+```
+TRAILING WHITESPACE:example/*
+```
+
+If needed, you can also use the `*` wildcard to express other filename
+patterns or directory-name patterns (just as you would when, e.g.,
+executing shell commands from the command line).
+
+Finally, to allowlist just one line in a file, use the following format:
+
+```
+ERROR TYPE:file/name/pattern:line_number
+```
+
+For example, to allowlist just line 128 of the file `example/file.html`
+such that any `TRAILING WHITESPACE` error the lint tool would report for
+that line is suppressed, add the following to the `lint.allowlist` file.
+
+```
+TRAILING WHITESPACE:example/file.html:128
+```
diff --git a/dom/canvas/test/webgl-conf/checkout/py/lint/lint.allowlist b/dom/canvas/test/webgl-conf/checkout/py/lint/lint.allowlist
new file mode 100644
index 0000000000..eb4efce09e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/py/lint/lint.allowlist
@@ -0,0 +1,57 @@
+# File containing whiteslist for lint errors
+# Format is:
+# ERROR TYPE:file/name/pattern[:line number]
+# e.g.
+# TRAILING WHITESPACE:example/file.html:128
+# to allow trailing whitespace on example/file.html line 128
+
+## Whitespace rules that we can't enforce yet ##
+
+TRAILING WHITESPACE:*.md
+TRAILING WHITESPACE:*.txt
+TRAILING WHITESPACE:*.frag
+TRAILING WHITESPACE:*.vert
+
+## Accept executable permission ##
+
+UNNECESSARY EXECUTABLE PERMISSION:*.cgi
+UNNECESSARY EXECUTABLE PERMISSION:.git/*
+# Pylint doesn't seem to understand symlinks properly
+UNNECESSARY EXECUTABLE PERMISSION:specs/1.0
+UNNECESSARY EXECUTABLE PERMISSION:specs/2.0
+
+## Ignore INDENT TABS ##
+
+INDENT TABS:*.frag
+INDENT TABS:*.vert
+#The original dEQP tests used tabs throughout.
+INDENT TABS:deqp/functional/gles3/*.js
+INDENT TABS:conformance-suites/2.0.0/deqp/functional/gles3/*.js
+
+## Two files in the repository deliberately contain non-UTF-8 Unicode,
+## which Python can't decode by default. Skip the content checks for
+## them.
+
+INVALID UNICODE:conformance/glsl/misc/non-ascii-comments.vert.html
+INVALID UNICODE:conformance/glsl/misc/non-ascii.vert.html
+
+## File types that should never be checked ##
+
+*:*.pdf
+*:*.jpg
+*:*.png
+*:*.gif
+*:*.pdf
+*:*.wav
+*:*.mp3
+*:*.m4a
+*:*.oga
+*:*.ogv
+*:*.webm
+*:*.mp4
+*:*.m4v
+*:*.ttf
+*:*.woff
+*:*.eot
+*:*.sfd
+*:*.swf
diff --git a/dom/canvas/test/webgl-conf/checkout/py/lint/lint.py b/dom/canvas/test/webgl-conf/checkout/py/lint/lint.py
new file mode 100755
index 0000000000..cc84f49bd2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/py/lint/lint.py
@@ -0,0 +1,225 @@
+#! /usr/bin/env python3
+import os
+import subprocess
+import re
+import sys
+import fnmatch
+
+from collections import defaultdict
+from optparse import OptionParser
+
+lint_root = os.path.dirname(os.path.abspath(__file__))
+repo_root = os.path.dirname(os.path.dirname(lint_root))
+
+
+def git(command, *args):
+ args = list(args)
+ proc_kwargs = {"cwd": repo_root}
+ command_line = ["git", command] + args
+
+ try:
+ return subprocess.check_output(command_line, universal_newlines=True, **proc_kwargs)
+ except subprocess.CalledProcessError:
+ raise
+
+
+def iter_files(flag=False, floder=""):
+ if floder != "" and floder != None:
+ os.chdir(repo_root)
+ for pardir, subdir, files in os.walk(floder):
+ for item in subdir + files:
+ if not os.path.isdir(os.path.join(pardir, item)):
+ yield os.path.join(pardir, item)
+ os.chdir(lint_root)
+ else:
+ if not flag:
+ os.chdir(repo_root)
+ for pardir, subdir, files in os.walk(repo_root):
+ for item in subdir + files:
+ if not os.path.isdir(os.path.join(pardir, item)):
+ yield os.path.join(pardir, item).split(repo_root + "/")[1]
+ os.chdir(lint_root)
+ else:
+ for item in git("diff", "--name-status", "HEAD~1").strip().split("\n"):
+ status = item.split("\t")
+ if status[0].strip() != "D":
+ yield status[1]
+
+
+def check_filename_space(path):
+ bname = os.path.basename(path)
+ if re.compile(" ").search(bname):
+ return [("FILENAME WHITESPACE", "Filename of %s contains white space" % path, None)]
+ return []
+
+
+def check_permission(path):
+ bname = os.path.basename(path)
+ if not re.compile('\.py$|\.sh$').search(bname):
+ if os.access(os.path.join(repo_root, path), os.X_OK):
+ return [("UNNECESSARY EXECUTABLE PERMISSION", "%s contains unnecessary executable permission" % path, None)]
+ return []
+
+
+def parse_allowlist_file(filename):
+ data = defaultdict(lambda:defaultdict(set))
+
+ with open(filename) as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ parts = [item.strip() for item in line.split(":")]
+ if len(parts) == 2:
+ parts.append(None)
+ else:
+ parts[-1] = int(parts[-1])
+
+ error_type, file_match, line_number = parts
+ data[file_match][error_type].add(line_number)
+
+ def inner(path, errors):
+ allowlisted = [False for item in range(len(errors))]
+
+ for file_match, allowlist_errors in data.items():
+ if fnmatch.fnmatch(path, file_match):
+ for i, (error_type, msg, line) in enumerate(errors):
+ if "*" in allowlist_errors:
+ allowlisted[i] = True
+ elif error_type in allowlist_errors:
+ allowed_lines = allowlist_errors[error_type]
+ if None in allowed_lines or line in allowed_lines:
+ allowlisted[i] = True
+
+ return [item for i, item in enumerate(errors) if not allowlisted[i]]
+ return inner
+
+
+_allowlist_fn = None
+def allowlist_errors(path, errors):
+ global _allowlist_fn
+
+ if _allowlist_fn is None:
+ _allowlist_fn = parse_allowlist_file(os.path.join(lint_root, "lint.allowlist"))
+ return _allowlist_fn(path, errors)
+
+
+class Regexp(object):
+ pattern = None
+ file_extensions = None
+ error = None
+ _re = None
+
+ def __init__(self):
+ self._re = re.compile(self.pattern)
+
+ def applies(self, path):
+ return (self.file_extensions is None or
+ os.path.splitext(path)[1] in self.file_extensions)
+
+ def search(self, line):
+ return self._re.search(line)
+
+
+class TrailingWhitespaceRegexp(Regexp):
+ pattern = " $"
+ error = "TRAILING WHITESPACE"
+
+
+class TabsRegexp(Regexp):
+ pattern = "^\t"
+ error = "INDENT TABS"
+
+
+class CRRegexp(Regexp):
+ pattern = "\r$"
+ error = "CR AT EOL"
+
+regexps = [item() for item in
+ [TrailingWhitespaceRegexp,
+ TabsRegexp,
+ CRRegexp]]
+
+
+def check_regexp_line(path, f):
+ errors = []
+
+ applicable_regexps = [regexp for regexp in regexps if regexp.applies(path)]
+
+ try:
+ for i, line in enumerate(f):
+ for regexp in applicable_regexps:
+ if regexp.search(line):
+ errors.append((regexp.error, "%s line %i" % (path, i+1), i+1))
+ except UnicodeDecodeError as e:
+ return [("INVALID UNICODE", "File %s contains non-UTF-8 Unicode characters" % path, None)]
+
+ return errors
+
+
+def output_errors(errors):
+ for error_type, error, line_number in errors:
+ print("%s: %s" % (error_type, error))
+
+
+def output_error_count(error_count):
+ if not error_count:
+ return
+
+ by_type = " ".join("%s: %d" % item for item in error_count.items())
+ count = sum(error_count.values())
+ if count == 1:
+ print("There was 1 error (%s)" % (by_type,))
+ else:
+ print("There were %d errors (%s)" % (count, by_type))
+
+
+def main():
+ global repo_root
+ error_count = defaultdict(int)
+
+ parser = OptionParser()
+ parser.add_option('-p', '--pull', dest="pull_request", action='store_true', default=False)
+ parser.add_option("-d", '--dir', dest="dir", help="specify the checking dir, e.g. tools")
+ parser.add_option("-r", '--repo', dest="repo", help="specify the repo, e.g. WebGL")
+ options, args = parser.parse_args()
+ if options.pull_request == True:
+ options.pull_request = "WebGL"
+ repo_root = repo_root.replace("WebGL/sdk/tests", options.pull_request)
+ if options.repo == "" or options.repo == None:
+ options.repo = "WebGL/sdk/tests"
+ repo_root = repo_root.replace("WebGL/sdk/tests", options.repo)
+
+ def run_lint(path, fn, *args):
+ errors = allowlist_errors(path, fn(path, *args))
+ output_errors(errors)
+ for error_type, error, line in errors:
+ error_count[error_type] += 1
+
+ for path in iter_files(options.pull_request, options.dir):
+ abs_path = os.path.join(repo_root, path)
+ if not os.path.exists(abs_path):
+ continue
+ for path_fn in file_path_lints:
+ run_lint(path, path_fn)
+ for state_fn in file_state_lints:
+ run_lint(path, state_fn)
+
+ if not os.path.isdir(abs_path):
+ if re.compile('\.html$|\.htm$|\.xhtml$|\.xhtm$|\.frag$|\.vert$|\.js$').search(abs_path):
+ with open(abs_path) as f:
+ for file_fn in file_content_lints:
+ run_lint(path, file_fn, f)
+ f.seek(0)
+
+ output_error_count(error_count)
+ return sum(error_count.values())
+
+file_path_lints = [check_filename_space]
+file_content_lints = [check_regexp_line]
+file_state_lints = [check_permission]
+
+if __name__ == "__main__":
+ error_count = main()
+ if error_count > 0:
+ sys.exit(1)
diff --git a/dom/canvas/test/webgl-conf/checkout/py/tex_image_test_generator.py b/dom/canvas/test/webgl-conf/checkout/py/tex_image_test_generator.py
new file mode 100755
index 0000000000..37b4022738
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/py/tex_image_test_generator.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python2
+
+# Copyright (c) 2019 The Khronos Group Inc.
+# Use of this source code is governed by an MIT-style license that can be
+# found in the LICENSE.txt file.
+
+"""
+ Generator for tex-2d* and tex-3d* tests.
+ This file needs to be run in its folder.
+"""
+
+import os
+import os.path
+import sys
+
+_LICENSE = """<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+"""
+
+_DO_NOT_EDIT_WARNING = """<!--
+
+This file is auto-generated from py/tex_image_test_generator.py
+DO NOT EDIT!
+
+-->
+
+"""
+
+_ELEMENT_TYPES = [
+ 'canvas',
+ 'canvas-sub-rectangle',
+ 'image',
+ 'image-data',
+ 'svg-image',
+ 'video',
+ 'webgl-canvas',
+ 'image-bitmap-from-image-data',
+ 'image-bitmap-from-image',
+ 'image-bitmap-from-video',
+ 'image-bitmap-from-canvas',
+ 'image-bitmap-from-blob',
+ 'image-bitmap-from-image-bitmap'
+]
+
+_FORMATS_TYPES_WEBGL1 = [
+ {'internal_format': 'RGB', 'format': 'RGB', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGB', 'format': 'RGB', 'type': 'UNSIGNED_SHORT_5_6_5' },
+ {'internal_format': 'RGBA', 'format': 'RGBA', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGBA', 'format': 'RGBA', 'type': 'UNSIGNED_SHORT_4_4_4_4' },
+ {'internal_format': 'RGBA', 'format': 'RGBA', 'type': 'UNSIGNED_SHORT_5_5_5_1' },
+ {'internal_format': 'LUMINANCE', 'format': 'LUMINANCE', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'ALPHA', 'format': 'ALPHA', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'LUMINANCE_ALPHA', 'format': 'LUMINANCE_ALPHA', 'type': 'UNSIGNED_BYTE' },
+]
+
+_FORMATS_TYPES_WEBGL2 = [
+ {'internal_format': 'R8', 'format': 'RED', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'R16F', 'format': 'RED', 'type': 'HALF_FLOAT' },
+ {'internal_format': 'R16F', 'format': 'RED', 'type': 'FLOAT' },
+ {'internal_format': 'R32F', 'format': 'RED', 'type': 'FLOAT' },
+ {'internal_format': 'R8UI', 'format': 'RED_INTEGER', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RG8', 'format': 'RG', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RG16F', 'format': 'RG', 'type': 'HALF_FLOAT' },
+ {'internal_format': 'RG16F', 'format': 'RG', 'type': 'FLOAT' },
+ {'internal_format': 'RG32F', 'format': 'RG', 'type': 'FLOAT' },
+ {'internal_format': 'RG8UI', 'format': 'RG_INTEGER', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGB8', 'format': 'RGB', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'SRGB8', 'format': 'RGB', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGB565', 'format': 'RGB', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGB565', 'format': 'RGB', 'type': 'UNSIGNED_SHORT_5_6_5' },
+ {'internal_format': 'R11F_G11F_B10F', 'format': 'RGB', 'type': 'UNSIGNED_INT_10F_11F_11F_REV' },
+ {'internal_format': 'R11F_G11F_B10F', 'format': 'RGB', 'type': 'HALF_FLOAT' },
+ {'internal_format': 'R11F_G11F_B10F', 'format': 'RGB', 'type': 'FLOAT' },
+ {'internal_format': 'RGB9_E5', 'format': 'RGB', 'type': 'HALF_FLOAT' },
+ {'internal_format': 'RGB9_E5', 'format': 'RGB', 'type': 'FLOAT' },
+ {'internal_format': 'RGB16F', 'format': 'RGB', 'type': 'HALF_FLOAT' },
+ {'internal_format': 'RGB16F', 'format': 'RGB', 'type': 'FLOAT' },
+ {'internal_format': 'RGB32F', 'format': 'RGB', 'type': 'FLOAT' },
+ {'internal_format': 'RGB8UI', 'format': 'RGB_INTEGER', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGBA8', 'format': 'RGBA', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'SRGB8_ALPHA8', 'format': 'RGBA', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGB5_A1', 'format': 'RGBA', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGB5_A1', 'format': 'RGBA', 'type': 'UNSIGNED_SHORT_5_5_5_1' },
+ {'internal_format': 'RGB10_A2', 'format': 'RGBA', 'type': 'UNSIGNED_INT_2_10_10_10_REV' },
+ {'internal_format': 'RGBA4', 'format': 'RGBA', 'type': 'UNSIGNED_BYTE' },
+ {'internal_format': 'RGBA4', 'format': 'RGBA', 'type': 'UNSIGNED_SHORT_4_4_4_4' },
+ {'internal_format': 'RGBA16F', 'format': 'RGBA', 'type': 'HALF_FLOAT' },
+ {'internal_format': 'RGBA16F', 'format': 'RGBA', 'type': 'FLOAT' },
+ {'internal_format': 'RGBA32F', 'format': 'RGBA', 'type': 'FLOAT' },
+ {'internal_format': 'RGBA8UI', 'format': 'RGBA_INTEGER', 'type': 'UNSIGNED_BYTE' },
+]
+
+def GenerateFilename(dimension, element_type, internal_format, format, type):
+ """Generate test filename."""
+ filename = ("tex-" + dimension + "d-" +
+ internal_format + "-" + format + "-" + type + ".html")
+ return filename.lower()
+
+def WriteTest(filename, dimension, element_type, internal_format, format, type, default_context_version):
+ """Write one test."""
+ file = open(filename, "wb")
+ file.write(_LICENSE)
+ file.write(_DO_NOT_EDIT_WARNING)
+ code = """
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>"""
+ if element_type == 'image-bitmap-from-image-data' or element_type == 'image-bitmap-from-image' or \
+ element_type == 'image-bitmap-from-video' or element_type == 'image-bitmap-from-canvas' or \
+ element_type == 'image-bitmap-from-blob' or element_type == 'image-bitmap-from-image-bitmap':
+ code += """
+<script src="../../../js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js"></script>"""
+ code += """
+<script src="../../../js/tests/tex-image-and-sub-image-%(dimension)sd-with-%(element_type)s.js"></script>
+</head>
+<body>"""
+ if element_type == 'image-data':
+ code += """
+<canvas id="texcanvas" width="2" height="2"></canvas>"""
+ code += """
+<canvas id="example" width="32" height="32"></canvas>"""
+ code += """
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+function testPrologue(gl) {
+ return true;
+}
+
+generateTest("%(internal_format)s", "%(format)s", "%(type)s", testPrologue, "../../../resources/", %(default_context_version)s)();
+</script>
+</body>
+</html>
+"""
+ file.write(code % {
+ 'dimension': dimension,
+ 'element_type': element_type,
+ 'internal_format': internal_format,
+ 'format': format,
+ 'type': type,
+ 'default_context_version': default_context_version,
+ })
+ file.close()
+
+def GenerateTests(test_dir, test_cases, dimension, default_context_version):
+ test_dir_template = test_dir + '/%s'
+ for element_type in _ELEMENT_TYPES:
+ os.chdir(test_dir_template % element_type.replace('-', '_'))
+ if dimension == '3':
+ # Assume we write 2D tests first.
+ index_file = open("00_test_list.txt", "ab")
+ else:
+ index_file = open("00_test_list.txt", "wb")
+ for tex_info in test_cases:
+ internal_format = tex_info['internal_format']
+ format = tex_info['format']
+ type = tex_info['type']
+ filename = GenerateFilename(dimension, element_type, internal_format, format, type)
+ index_file.write(filename)
+ index_file.write('\n')
+ WriteTest(filename, dimension, element_type, internal_format, format, type, default_context_version)
+ index_file.close();
+
+def main(argv):
+ """This is the main function."""
+ py_dir = os.path.dirname(os.path.realpath(__file__))
+ GenerateTests(os.path.realpath(py_dir + '/../conformance/textures'), _FORMATS_TYPES_WEBGL1, '2', '1')
+ GenerateTests(os.path.realpath(py_dir + '/../conformance2/textures'), _FORMATS_TYPES_WEBGL2, '2', '2')
+ GenerateTests(os.path.realpath(py_dir + '/../conformance2/textures'), _FORMATS_TYPES_WEBGL2, '3', '2')
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/1-channel.jpg b/dom/canvas/test/webgl-conf/checkout/resources/1-channel.jpg
new file mode 100644
index 0000000000..2b16f42abc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/1-channel.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/3x3.png b/dom/canvas/test/webgl-conf/checkout/resources/3x3.png
new file mode 100644
index 0000000000..6cf1e7447a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/3x3.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/blue-1x1.jpg b/dom/canvas/test/webgl-conf/checkout/resources/blue-1x1.jpg
new file mode 100644
index 0000000000..a70bbb0219
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/blue-1x1.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/boolUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/boolUniformShader.vert
new file mode 100644
index 0000000000..9226b3b5c0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/boolUniformShader.vert
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+uniform bool bval;
+uniform bvec2 bval2;
+uniform bvec3 bval3;
+uniform bvec4 bval4;
+
+void main()
+{
+ bool allSet = bval
+ && bval2[0] && bval2[1]
+ && bval3[0] && bval3[1] && bval3[2]
+ && bval4[0] && bval4[1] && bval4[2] && bval4[3];
+ gl_Position = vec4((allSet ? 1.0 : -1.0), 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/bug-32888-texture.png b/dom/canvas/test/webgl-conf/checkout/resources/bug-32888-texture.png
new file mode 100644
index 0000000000..e78cfe7997
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/bug-32888-texture.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-2-mirror-horizontal.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-2-mirror-horizontal.jpg
new file mode 100644
index 0000000000..c34b652c96
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-2-mirror-horizontal.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-3-rotate-180.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-3-rotate-180.jpg
new file mode 100644
index 0000000000..f4570a79be
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-3-rotate-180.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-4-mirror-vertical.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-4-mirror-vertical.jpg
new file mode 100644
index 0000000000..286bcf2951
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-4-mirror-vertical.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-5-mirror-horizontal-90-ccw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-5-mirror-horizontal-90-ccw.jpg
new file mode 100644
index 0000000000..8b7ed7fafc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-5-mirror-horizontal-90-ccw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-6-90-ccw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-6-90-ccw.jpg
new file mode 100644
index 0000000000..b4679aedd9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-6-90-ccw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-7-mirror-horizontal-90-cw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-7-mirror-horizontal-90-cw.jpg
new file mode 100644
index 0000000000..269f29f82d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-7-mirror-horizontal-90-cw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-8-90-cw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-8-90-cw.jpg
new file mode 100644
index 0000000000..d4e75fac7d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test-8-90-cw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test.psd b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test.psd
new file mode 100644
index 0000000000..277655624b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-originals/exif-orientation-test.psd
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-1-normal.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-1-normal.jpg
new file mode 100644
index 0000000000..800f993b56
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-1-normal.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-2-mirror-horizontal.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-2-mirror-horizontal.jpg
new file mode 100644
index 0000000000..d8ce15b161
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-2-mirror-horizontal.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-3-rotate-180.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-3-rotate-180.jpg
new file mode 100644
index 0000000000..5be731981b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-3-rotate-180.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-4-mirror-vertical.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-4-mirror-vertical.jpg
new file mode 100644
index 0000000000..32b626a786
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-4-mirror-vertical.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-5-mirror-horizontal-90-ccw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-5-mirror-horizontal-90-ccw.jpg
new file mode 100644
index 0000000000..a91a0f9a78
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-5-mirror-horizontal-90-ccw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-6-90-ccw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-6-90-ccw.jpg
new file mode 100644
index 0000000000..f8c9a6b0cc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-6-90-ccw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-7-mirror-horizontal-90-cw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-7-mirror-horizontal-90-cw.jpg
new file mode 100644
index 0000000000..d359c3834c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-7-mirror-horizontal-90-cw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-8-90-cw.jpg b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-8-90-cw.jpg
new file mode 100644
index 0000000000..594c86ff4e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/exif-orientation-test-8-90-cw.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/floatUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/floatUniformShader.vert
new file mode 100644
index 0000000000..58991b4741
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/floatUniformShader.vert
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+uniform float fval;
+uniform vec2 fval2;
+uniform vec3 fval3;
+uniform vec4 fval4;
+
+void main()
+{
+ float sum = fval
+ + fval2[0] + fval2[1]
+ + fval3[0] + fval3[1] + fval3[2]
+ + fval4[0] + fval4[1] + fval4[2] + fval4[3];
+ gl_Position = vec4(sum, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/fragmentShader.frag b/dom/canvas/test/webgl-conf/checkout/resources/fragmentShader.frag
new file mode 100644
index 0000000000..08596ed5db
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/fragmentShader.frag
@@ -0,0 +1,32 @@
+/*
+Copyright (C) 2009 Apple Computer, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. AS IS AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Workaround for non-compliant WebGL implementations (FIXME)
+varying mediump vec3 v_normal;
+
+void main()
+{
+ gl_FragColor = vec4(v_normal/2.0+vec3(0.5), 1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/glsl-feature-tests.css b/dom/canvas/test/webgl-conf/checkout/resources/glsl-feature-tests.css
new file mode 100644
index 0000000000..c8063d92b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/glsl-feature-tests.css
@@ -0,0 +1,29 @@
+canvas {
+ background-color: white;
+ background-image: linear-gradient(0, rgba(200, 200, 200, .5) 50%, transparent 50%), linear-gradient(rgba(200, 200, 200, .5) 50%, transparent 50%);
+ background-size: 8px 8px;
+}
+
+.shader-source {
+ border: 1px dashed black;
+ padding: 1em;
+}
+
+.shader-source li:nth-child(odd) { background: #f8f8f8; }
+.shader-source li:nth-child(even) { background: #f0f0f0; }
+
+.testimages {
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+
+IMG {
+ border: 1px solid black;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/glsl-generator.js b/dom/canvas/test/webgl-conf/checkout/resources/glsl-generator.js
new file mode 100644
index 0000000000..d0b65bcb4b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/glsl-generator.js
@@ -0,0 +1,1234 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+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/resources/gray-1024x1024.jpg b/dom/canvas/test/webgl-conf/checkout/resources/gray-1024x1024.jpg
new file mode 100644
index 0000000000..e06e7f5eef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-1024x1024.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256-with-128-alpha.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256-with-128-alpha.png
new file mode 100644
index 0000000000..183e55de21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256-with-128-alpha.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256.png
new file mode 100644
index 0000000000..01e486b5a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-256.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-default-gamma.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-default-gamma.png
new file mode 100644
index 0000000000..a5a89beb70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-default-gamma.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma0.1.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma0.1.png
new file mode 100644
index 0000000000..637c792da0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma0.1.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma1.0.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma1.0.png
new file mode 100644
index 0000000000..40ceeb0465
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma1.0.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma2.0.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma2.0.png
new file mode 100644
index 0000000000..73fcf7b41b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma2.0.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma4.0.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma4.0.png
new file mode 100644
index 0000000000..d878f1e967
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma4.0.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma9.0.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma9.0.png
new file mode 100644
index 0000000000..8a69ed1f3d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp-gamma9.0.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp.png b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp.png
new file mode 100644
index 0000000000..a5a89beb70
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/gray-ramp.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/green-2x2-16bit.png b/dom/canvas/test/webgl-conf/checkout/resources/green-2x2-16bit.png
new file mode 100644
index 0000000000..7fcb96960e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/green-2x2-16bit.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/intArrayUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/intArrayUniformShader.vert
new file mode 100644
index 0000000000..d82074e473
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/intArrayUniformShader.vert
@@ -0,0 +1,8 @@
+uniform int ival;
+uniform int ival2[2];
+
+void main()
+{
+ int sum = ival + ival2[0] + ival2[1];
+ gl_Position = vec4(sum, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/intUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/intUniformShader.vert
new file mode 100644
index 0000000000..051c05e2b8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/intUniformShader.vert
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+uniform int ival;
+uniform ivec2 ival2;
+uniform ivec3 ival3;
+uniform ivec4 ival4;
+
+void main()
+{
+ int sum = ival
+ + ival2[0] + ival2[1]
+ + ival3[0] + ival3[1] + ival3[2]
+ + ival4[0] + ival4[1] + ival4[2] + ival4[3];
+ gl_Position = vec4(sum, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/js-test-style.css b/dom/canvas/test/webgl-conf/checkout/resources/js-test-style.css
new file mode 100644
index 0000000000..5f6839b621
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/js-test-style.css
@@ -0,0 +1,20 @@
+.pass {
+ font-weight: bold;
+ color: green;
+}
+.fail {
+ font-weight: bold;
+ color: red;
+}
+.warn {
+ font-weight: bold;
+ color: yellow;
+ text-shadow: 1px 1px #ff0000
+}
+#console {
+ white-space: pre-wrap;
+ font-family: monospace;
+}
+body {
+ background-color: #ffffff;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/matForWebGL2UniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/matForWebGL2UniformShader.vert
new file mode 100644
index 0000000000..47f77c0ce3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/matForWebGL2UniformShader.vert
@@ -0,0 +1,25 @@
+#version 300 es
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+uniform mat2x3 mval2x3;
+uniform mat2x4 mval2x4;
+uniform mat3x2 mval3x2;
+uniform mat3x4 mval3x4;
+uniform mat4x2 mval4x2;
+uniform mat4x3 mval4x3;
+
+void main()
+{
+
+ gl_Position = vec4(mval2x3 * vec2(1.0, 2.0), 0.0) +
+ mval2x4 * vec2(1.0, 2.0) +
+ vec4(mval3x2 * vec3(1.0, 2.0, 3.0), 0.0, 0.0) +
+ mval3x4 * vec3(1.0, 2.0, 3.0) +
+ vec4(mval4x2 * vec4(1.0, 2.0, 3.0, 4.0), 0.0, 0.0) +
+ vec4(mval4x3 * vec4(1.0, 2.0, 3.0, 4.0), 0.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/matUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/matUniformShader.vert
new file mode 100644
index 0000000000..123a4be03b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/matUniformShader.vert
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+uniform mat2 mval2;
+uniform mat3 mval3;
+uniform mat4 mval4;
+
+void main()
+{
+ gl_Position = vec4(mval2 * vec2(1.0, 2.0), 0.0, 0.0)
+ + vec4(mval3 * vec3(1.0, 2.0, 3.0), 0.0)
+ + mval4 * vec4(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.frag b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.frag
new file mode 100644
index 0000000000..b2dfc9f1d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.frag
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+void main()
+{
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.vert
new file mode 100644
index 0000000000..821e440d4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShader.vert
@@ -0,0 +1,4 @@
+void main()
+{
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.frag b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.frag
new file mode 100644
index 0000000000..00af837a5f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.frag
@@ -0,0 +1,40 @@
+#version 300 es
+
+/*
+ * Copyright (c) 2015 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+precision mediump float;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.vert b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.vert
new file mode 100644
index 0000000000..e213a4bb3b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/noopUniformShaderES3.vert
@@ -0,0 +1,6 @@
+#version 300 es
+
+void main()
+{
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/npot-video-1920x1080.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/npot-video-1920x1080.mp4
new file mode 100644
index 0000000000..2ce5baaee8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/npot-video-1920x1080.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/npot-video.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/npot-video.mp4
new file mode 100644
index 0000000000..a263a2bba8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/npot-video.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/npot-video.theora.ogv b/dom/canvas/test/webgl-conf/checkout/resources/npot-video.theora.ogv
new file mode 100644
index 0000000000..4458678fbf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/npot-video.theora.ogv
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/npot-video.webmvp8.webm b/dom/canvas/test/webgl-conf/checkout/resources/npot-video.webmvp8.webm
new file mode 100644
index 0000000000..47277bdaac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/npot-video.webmvp8.webm
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/ogles-tests.css b/dom/canvas/test/webgl-conf/checkout/resources/ogles-tests.css
new file mode 100644
index 0000000000..42269c8b60
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/ogles-tests.css
@@ -0,0 +1,30 @@
+canvas {
+ background-color: white;
+ background-size: 8px 8px;
+}
+
+.shader-source {
+ border: 1px dashed black;
+ padding: 1em;
+}
+
+.shader-source li:nth-child(odd) { background: #f8f8f8; }
+.shader-source li:nth-child(even) { background: #f0f0f0; }
+
+.testimages {
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+
+IMG {
+ border: 1px solid black;
+ width: 250px;
+ height: 250px;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/opengl_logo.jpg b/dom/canvas/test/webgl-conf/checkout/resources/opengl_logo.jpg
new file mode 100644
index 0000000000..e3b70bef3f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/opengl_logo.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.jpg b/dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.jpg
new file mode 100644
index 0000000000..61816041cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.psd b/dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.psd
new file mode 100644
index 0000000000..28c1d07a80
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-128x128-linear-profile.psd
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272-sar-136x135-dar-16x9.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272-sar-136x135-dar-16x9.mp4
new file mode 100644
index 0000000000..4843a436eb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272-sar-136x135-dar-16x9.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272.png b/dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272.png
new file mode 100644
index 0000000000..413bafeaaa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-480x272.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.png b/dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.png
new file mode 100644
index 0000000000..80b2d1d423
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.psd b/dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.psd
new file mode 100644
index 0000000000..9cf26f9413
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-blue-cyan-4x4.psd
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.hdr b/dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.hdr
new file mode 100644
index 0000000000..bf26f2842b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.hdr
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.png b/dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.png
new file mode 100644
index 0000000000..a33d9301f4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-hard.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green-semi-transparent.png b/dom/canvas/test/webgl-conf/checkout/resources/red-green-semi-transparent.png
new file mode 100644
index 0000000000..11f2928ae2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green-semi-transparent.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green.bt601.vp9.webm b/dom/canvas/test/webgl-conf/checkout/resources/red-green.bt601.vp9.webm
new file mode 100644
index 0000000000..d90e1911c6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green.bt601.vp9.webm
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/red-green.mp4
new file mode 100644
index 0000000000..79e810be81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green.png b/dom/canvas/test/webgl-conf/checkout/resources/red-green.png
new file mode 100644
index 0000000000..605ac9ba1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green.svg b/dom/canvas/test/webgl-conf/checkout/resources/red-green.svg
new file mode 100644
index 0000000000..fe4d20718f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2">
+ <rect fill="#f00" width="2" height="1"/>
+ <rect fill="#0f0" y="1" width="2" height="1"/>
+</svg>
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green.theora.ogv b/dom/canvas/test/webgl-conf/checkout/resources/red-green.theora.ogv
new file mode 100644
index 0000000000..1543915a10
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green.theora.ogv
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-green.webmvp8.webm b/dom/canvas/test/webgl-conf/checkout/resources/red-green.webmvp8.webm
new file mode 100644
index 0000000000..fde59a18b4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-green.webmvp8.webm
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/red-indexed.png b/dom/canvas/test/webgl-conf/checkout/resources/red-indexed.png
new file mode 100644
index 0000000000..3188d2d75b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/red-indexed.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/samplerForWebGL2UniformShader.frag b/dom/canvas/test/webgl-conf/checkout/resources/samplerForWebGL2UniformShader.frag
new file mode 100644
index 0000000000..8c9a90079a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/samplerForWebGL2UniformShader.frag
@@ -0,0 +1,17 @@
+#version 300 es
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+precision mediump float;
+uniform mediump sampler3D s3D;
+uniform mediump sampler2DArray s2DArray;
+out vec4 fragColor;
+void main()
+{
+ fragColor = texture(s3D, vec3(0.5, 0.5, 0.5)) +
+ texture(s2DArray, vec3(0.5, 0.5, 0.5));
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/samplerUniformShader.frag b/dom/canvas/test/webgl-conf/checkout/resources/samplerUniformShader.frag
new file mode 100644
index 0000000000..11cba12746
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/samplerUniformShader.frag
@@ -0,0 +1,8 @@
+precision mediump float;
+uniform sampler2D s2D;
+uniform samplerCube sCube;
+void main()
+{
+ gl_FragColor = texture2D(s2D, vec2(0.5, 0.5)) +
+ textureCube(sCube, vec3(0.5, 0.5, 0.5));
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-cie-rgb-profile.png b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-cie-rgb-profile.png
new file mode 100644
index 0000000000..aa8bf37717
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-cie-rgb-profile.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colormatch-profile.png b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colormatch-profile.png
new file mode 100644
index 0000000000..63454ec0dd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colormatch-profile.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.jpg b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.jpg
new file mode 100644
index 0000000000..a9186968fb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.jpg
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.png b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.png
new file mode 100644
index 0000000000..5922627376
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-colorspin-profile.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-e-srgb-profile.png b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-e-srgb-profile.png
new file mode 100644
index 0000000000..2792b0ac57
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-e-srgb-profile.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-smpte-c-profile.png b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-smpte-c-profile.png
new file mode 100644
index 0000000000..2904e89523
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-smpte-c-profile.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-srgb-iec61966-2.1-profile.png b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-srgb-iec61966-2.1-profile.png
new file mode 100644
index 0000000000..a0201f113f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/small-square-with-srgb-iec61966-2.1-profile.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/structUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/structUniformShader.vert
new file mode 100644
index 0000000000..59c719a001
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/structUniformShader.vert
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+attribute vec4 a_vertex;
+attribute vec3 a_normal;
+
+uniform mat4 u_modelViewProjMatrix;
+
+struct MyStruct
+{
+ int x;
+ int y;
+};
+
+uniform MyStruct u_struct;
+uniform float u_array[4];
+
+varying vec3 v_normal;
+
+void main()
+{
+ v_normal = a_normal;
+ gl_Position = u_modelViewProjMatrix * a_vertex +
+ vec4(u_struct.x, u_struct.y, 0, 1) +
+ vec4(u_array[0], u_array[1], u_array[2], u_array[3]);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/thunderbird-logo-64x64.png b/dom/canvas/test/webgl-conf/checkout/resources/thunderbird-logo-64x64.png
new file mode 100644
index 0000000000..e2326f5510
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/thunderbird-logo-64x64.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.mp4
new file mode 100644
index 0000000000..261069776f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.webm b/dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.webm
new file mode 100644
index 0000000000..def8aaaeec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/transparent-2frames.webm
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/transparent-on-left-indexed.png b/dom/canvas/test/webgl-conf/checkout/resources/transparent-on-left-indexed.png
new file mode 100644
index 0000000000..2be3127440
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/transparent-on-left-indexed.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/uintUniformShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/uintUniformShader.vert
new file mode 100644
index 0000000000..e385ac9bc4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/uintUniformShader.vert
@@ -0,0 +1,21 @@
+#version 300 es
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+uniform uint uval;
+uniform uvec2 uval2;
+uniform uvec3 uval3;
+uniform uvec4 uval4;
+
+void main()
+{
+ uint sum = uval
+ + uval2[0] + uval2[1]
+ + uval3[0] + uval3[1] + uval3[2]
+ + uval4[0] + uval4[1] + uval4[2] + uval4[3];
+ gl_Position = vec4(sum, 0.0, 0.0, 1.0);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.frag b/dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.frag
new file mode 100644
index 0000000000..10a098421d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.frag
@@ -0,0 +1,19 @@
+#version 300 es
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+precision mediump float;
+
+in vec3 normal;
+in vec4 ecPosition;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(normal/2.0+vec3(0.5), 1);
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.vert
new file mode 100644
index 0000000000..a9814b7128
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/uniformBlockShader.vert
@@ -0,0 +1,26 @@
+#version 300 es
+
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+in vec4 a_vertex;
+in vec3 a_normal;
+
+uniform Transform {
+ mat4 u_modelViewMatrix;
+ mat4 u_projectionMatrix;
+ mat3 u_normalMatrix;
+};
+
+out vec3 normal;
+out vec4 ecPosition;
+
+void main()
+{
+ normal = normalize(u_normalMatrix * a_normal);
+ ecPosition = u_modelViewMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * ecPosition;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/vertexShader.vert b/dom/canvas/test/webgl-conf/checkout/resources/vertexShader.vert
new file mode 100644
index 0000000000..fe6640b75b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/vertexShader.vert
@@ -0,0 +1,36 @@
+/*
+Copyright (C) 2009 Apple Computer, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. AS IS AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+attribute vec4 a_vertex;
+attribute vec3 a_normal;
+
+uniform mediump mat4 u_modelViewProjMatrix;
+
+varying vec3 v_normal;
+
+void main()
+{
+ v_normal = a_normal;
+ gl_Position = u_modelViewProjMatrix * a_vertex;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.mp4
new file mode 100644
index 0000000000..8f471009cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.vp9.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.vp9.mp4
new file mode 100644
index 0000000000..bae85cd324
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-0.vp9.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.mp4
new file mode 100644
index 0000000000..7c5fe8ea13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.vp9.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.vp9.mp4
new file mode 100644
index 0000000000..6bb57d5626
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-180.vp9.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.mp4
new file mode 100644
index 0000000000..5dfb886f6d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.vp9.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.vp9.mp4
new file mode 100644
index 0000000000..d945c3bfb9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-270.vp9.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.mp4
new file mode 100644
index 0000000000..41e3c3675a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.vp9.mp4 b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.vp9.mp4
new file mode 100644
index 0000000000..b4a4be9464
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/video-rotation-90.vp9.mp4
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/webgl-logo.png b/dom/canvas/test/webgl-conf/checkout/resources/webgl-logo.png
new file mode 100644
index 0000000000..b9b22e1ab4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/webgl-logo.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/resources/zero-alpha.png b/dom/canvas/test/webgl-conf/checkout/resources/zero-alpha.png
new file mode 100644
index 0000000000..e55630c116
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/resources/zero-alpha.png
Binary files differ
diff --git a/dom/canvas/test/webgl-conf/checkout/test-guidelines.md b/dom/canvas/test/webgl-conf/checkout/test-guidelines.md
new file mode 100644
index 0000000000..679892b1f0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/test-guidelines.md
@@ -0,0 +1,165 @@
+Contributing WebGL conformance tests Guidelines
+===============================================
+
+Thank you for contributing to the WebGL conformance tests.
+Please try to follow these guidelines when submitting a test.
+
+* If you're new to git [here's a terse set of instructions](http://www.khronos.org/webgl/wiki/Using_Github_To_Contribute "Using Github to Contribute").
+
+* All changes and/or new tests should go in the sdk/tests folder:
+ * Tests that apply to WebGL 1 to sdk/tests/conformance
+ * Tests that only concern WebGL 2 to sdk/tests/conformance2
+
+The tests under conformance-suites are snapshots and are only to be updated by
+the WebGL Working Group when "official" snapshots are taken.
+
+* Please use the Khronos Group License (MIT)
+
+These lines must appear in a comment at the top of every code file under sdk/tests/conformance
+
+```
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+```
+
+* Please use code similar to the code in existing tests
+
+ Ideally, copy an existing test and modify it for your new test. Try not to duplicate
+ code that already exists where appropriate. In particular
+
+ * use the functions in WebGLTestUtils rather than duplicating functionality.
+
+ In particular, as much as possible, keep the WebGL code in your test specific
+ to the issue being tested and try to use the helper functions to handle
+ common setup.
+
+ Examples:
+
+ * to create a WebGL context call `WebGLTestUtils.create3DContext`. Passed nothing
+ it will create an offscreen canvas. Passed a canvas element it will create
+ a context on that element. Passed a string it will look up the canvas element
+ with the matching id and create a context from that element.
+
+ * use `WebGLTestUtils.checkCanvas` or `WebGLTestUtils.checkCanvasRect` rather
+ than checking rendering results by hand.
+
+ * use the various quad and draw functions
+
+ * `WebGLTestUtils.setupUnitQuad` and `WebGLTestUtils.clearAndDrawUnitQuad` for
+ simple drawing.
+
+ * `WebGLTestUtils.setupColorQuad`, `WebGLTestUtils.drawFloatColorQuad`, and
+ `WebGLTestUilts.drawUByteColorQuad` for drawing in a particular color.
+
+ * `WebGLTestUtils.setupIndexedQuad` and `WebGLTestUtils.clearAndDrawIndexedQuad`
+ if you need a higher subdivision of vertices and/or vertex colors.
+
+ * use `WebgLTestUtils.setupTexturedQuad` if you need a unit quad with texture coords.
+ By default the positions will be at location 0 and the texture coords at location 1.
+
+ * If you need a custom shader use `WebGLTestUtils.setupProgram`. Note that it takes
+ the following arguments. `gl`, `shaders`, `opt_attribs`, `opt_locations`, and
+ `opt_logShaders` where:
+
+ `gl` is the WebGL context.
+
+ `shaders` are an array of either script element ids, shader source, or WebGLShader
+ objects. The first element in the array is the vertex shader, the second the fragment
+ shader.
+
+ `opt_attribs` is an optional array of attribute names. If provided the named attributes
+ will have their locations bound to their index in this array.
+
+ `opt_locations` is an optional array of attribute locations. If provided each attribute
+ name in `opt_attribs` is bound to the corresponding location in `opt_locations`.
+
+ `opt_logShaders` is an optional boolean value. If set to true, the shader source will
+ be logged on the test page. It is recommended to use this in tests that concentrate on
+ shaders.
+
+ * If you need to wait for a composite call `WebGLTestUtils.waitForComposite`.
+ As compositing is a browser specific thing this provides a central place to
+ update all tests that rely on compositing to function.
+
+ * If you don't care about composition, `wtu.dispatchPromise` makes it easy to
+ yield back to the event loop.
+
+ * Code/Tag Order
+
+ Most tests run inline. They don't use window.onload or the load event. This works by placing
+ the script tag inside the body, *after* the canvas and required divs.
+
+ <canvas id="example"></canvas>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script>
+ var wtu = WebGLDebugUtils;
+ var gl = wtu.create3DContext("example");
+ ...
+
+ * Ending Tests
+
+ * Tests that are short and run synchronously end with
+
+ <script src="../../resources/js-test-post.js"></script>
+
+ * Tests that take a long time use setTimeout so as not to freeze the browser.
+
+ Many browsers will terminate JavaScript that takes more than a few seconds to execute
+ without returning control to the browser. The workaround is code like this
+
+ var numTests = 10;
+ var currenTest = 0;
+ function runNextTest() {
+ if (currentTest == numTests) {
+ finishTest(); // Tells the harness you're done.
+ return;
+ }
+ // Run your test.
+ ...
+ ++currentTest;
+ setTimeout(runNextTest, 100);
+ }
+ runNextTest();
+
+ Remember the tests need to run without timing out even and slow mobile devices.
+ The harness resets the timeout timer every time a test reports success or failure
+ so as long as some part of your test calls `testPassed` or `testFailed` or one of the
+ many wrappers (`shouldXXX`, `glErrorShouldBe`, `WebGLTestUtils.checkCanvasXXX`, etc..)
+ every so often the harness will not timeout your test.
+
+ * The test harness requires the global variable `successfullyParsed` to be set to true.
+ This usually appears at the end of a file.
+
+ var successfullyParsed = true;
+
+ * Do not use browser specific code.
+
+ * Do not check the browser version. Use feature detection.
+
+ * If you do need feature detection consider putting it into WebGLTestUtils so that
+ other tests can go through the same abstraction and the workaround is isolated
+ to one place.
+
+ * Vendors may place test harness specific code in the testing infrastructure.
+
+ resources/js-test-pre.js
+ conformance/more/unit.js
+
+ * Indent with spaces not tabs. (not everyone uses your tab settings).
+
+ * All HTML files must have a `<!DOCTYPE html>`
+
+ * All HTML files must have a `<meta charset="utf-8">`
+
+ * All JavaScript must start with "use strict";
+
+* If adding a new test edit the appropriate 00_test_list.txt file
+
+ Each folder has a 00_test_list.txt file that lists the test in that folder.
+ Each new test should be prefixed with the option `--min-version <version>` where
+ version is 1 more than the newest official version. At the time of this writing
+ all new tests should be prefixed with `--min-version 1.0.4` or `--min-version 2.0.1`.
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html b/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
new file mode 100644
index 0000000000..462659227e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
@@ -0,0 +1,1305 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<!-- Prevents Chrome from offering to translate tests which generate
+ random characters for things like attribute names -->
+<meta name="google" value="notranslate">
+<meta name="viewport" content="width=device-width">
+<title>WebGL Conformance Tests</title>
+<style>
+ * {
+ box-sizing: border-box;
+ }
+
+ body {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ max-height:100%;
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 0.8em;
+ }
+
+ input[type=button], select {
+ padding: 2px 6px 2px 6px;
+ margin: 0;
+ border: 1px solid #888;
+ border-radius: 2px;
+ background: #f4f4f4;
+ }
+
+ a {
+ color: #88F;
+ text-decoration: none;
+ }
+
+ a:hover {
+ border-bottom: 1px solid #66D;
+ }
+
+ label {
+ white-space: nowrap;
+ }
+
+ #testlist {
+ position:fixed;
+ top:180px;
+ left:0;
+ right: calc(10% + 50px);
+ bottom:0px;
+ overflow:auto;
+ min-height: 200px;
+ }
+
+ @media screen and (max-width: 500px) {
+ #testlist {
+ font-size: 80%;
+ }
+ }
+
+ #header {
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ height: 160px;
+ overflow: scroll;
+ border-bottom: 1px solid #CCC;
+ }
+
+ #info {
+ margin: 0 auto;
+ max-width: 280px;
+ }
+ #logo {
+ width: 68px;
+ height: 40px;
+ }
+
+ #iframe-container {
+ color: white;
+ display: block;
+ position: fixed;
+ width: 90%;
+ height: calc(100% - 170px);
+ bottom: 0px;
+ left: calc(90% - 50px);
+ transition: left 0.15s;
+ }
+ #iframe-container.iframe-shown {
+ left: 10%;
+ }
+ #iframe-toggle {
+ display: inline-block;
+ vertical-align: middle;
+ width: 20px;
+ height: 100%;
+ padding: 0;
+ -webkit-appearance: none;
+ }
+ #test-iframe {
+ display: inline-block;
+ vertical-align: middle;
+ background: white;
+ width: calc(100% - 20px);
+ height: 100%;
+ border: 1px solid black;
+ }
+
+ .folder {
+ margin-bottom: 1.5em;
+ }
+
+ .folderHeader {
+ white-space: nowrap;
+ position: sticky;
+ top: 0;
+ }
+ .folderHeaderInner {
+ background: white;
+ /* to hide checkboxes from parent headers */
+ position: relative;
+ left: -2em;
+ padding-left: 2em;
+ }
+
+ .folderName {
+ font-weight: bold;
+ }
+
+ .folderMessage {
+ margin-left: 1em;
+ font-size: 0.9em;
+ }
+
+ .pageHeader {
+ white-space: nowrap;
+ }
+
+ .testpage {
+ border-style: solid;
+ border-color: #CCC;
+ border-width: 0px 0 1px 0;
+ background-color: #FFF;
+ padding: 4px 0 4px 0;
+
+ -webkit-transition: background-color 0.25s;
+ -moz-transition: background-color 0.25s;
+ transition: background-color 0.25s;
+ }
+
+ .testpage:first-child {
+ border-width: 1px 0 1px 0;
+ }
+
+ .timeout { }
+ .success { }
+ .fail { }
+ .testpagesuccess { background-color: #8F8; }
+ .testpagefail { background-color: #F88; }
+ .testpageskipped { background-color: #888; }
+ .testpagetimeout { background-color: #FC8; }
+ .nowebgl { font-weight: bold; color: red; }
+ #error-wrap {
+ float: left;
+ position: relative;
+ left: 50%;
+ }
+ #error {
+ color: red;
+ float: left;
+ position: relative;
+ left: -50%;
+ text-align: left;
+ }
+ ul {
+ list-style: none;
+ padding-left: 1em;
+ }
+</style>
+<script type="application/javascript" src="js/webgl-test-harness.js"></script>
+<script>
+"use strict";
+
+window.onbeforeunload = function() {
+ // Prompt user before reloading
+ return false;
+}
+
+var DEFAULT_CONFORMANCE_TEST_VERSION = "2.0.1 (beta)";
+
+var OPTIONS = {
+ version: DEFAULT_CONFORMANCE_TEST_VERSION,
+ frames: 1,
+ allowSkip: 0,
+ root: null,
+ quiet: 0
+};
+
+var testVersions = [
+ "1.0.4 (beta)",
+ "2.0.1 (beta)"
+];
+
+function start() {
+
+ function log(msg) {
+ if (window.console && window.console.log) {
+ window.console.log(msg);
+ }
+ }
+
+ function createStylesheet() {
+ var style = document.createElement("style");
+ style.appendChild(document.createTextNode(""));
+ document.head.appendChild(style);
+ return style.sheet;
+ }
+
+ function create3DContext(canvas, attrs, version) {
+ if (!canvas) {
+ canvas = document.createElement("canvas");
+ }
+ var context = null;
+ var names;
+ switch (version) {
+ case 2:
+ names = ["webgl2"]; break;
+ default:
+ names = ["webgl", "experimental-webgl"]; break;
+ }
+ for (var i = 0; i < names.length; ++i) {
+ try {
+ context = canvas.getContext(names[i], attrs);
+ } catch (e) {
+ }
+ if (context) {
+ break;
+ }
+ }
+ return context;
+ }
+
+ var reportType = WebGLTestHarnessModule.TestHarness.reportType;
+ var pageCount = 0;
+ var folderCount = 0;
+ var autoScrollEnabled = true; // Whether the user prefers to auto scroll
+ var autoScroll = true; // Whether auto scroll is actually performed
+ let quickTestMode = true;
+
+ var Page = function(reporter, folder, testIndex, url) {
+ this.reporter = reporter;
+ this.folder = folder;
+ this.url = url;
+ this.totalTests = 0;
+ this.totalSuccessful = 0;
+ this.totalTimeouts = 0;
+ this.totalSkipped = 0;
+ this.totalFailed = 0;
+ this.testIndex = testIndex;
+ this.startTime = new Date();
+ this.totalTime = 0;
+ var that = this;
+
+ this.elementId = "page" + pageCount++;
+ var li = reporter.localDoc.createElement('li');
+ li.id = this.elementId;
+ var div = reporter.localDoc.createElement('div');
+ div.classList.add('pageHeader');
+ var check = reporter.localDoc.createElement('input');
+ check.type = 'checkbox';
+ check.checked = true;
+ check.onclick = function() {
+ if (this.checked) {
+ that.folder.enableUp_();
+ }
+ else {
+ that.folder.disableUp_();
+ }
+ };
+ div.appendChild(check);
+ var button = reporter.localDoc.createElement('input');
+ button.type = 'button';
+ button.id = this.elementId + "-button";
+ button.value = 'run';
+ button.onclick = function() {
+ autoScroll = false;
+ reporter.runTest(url);
+ };
+ if (reporter.noSelectedWebGLVersion) {
+ button.disabled = true;
+ }
+ div.appendChild(button);
+ var a = reporter.localDoc.createElement('a');
+ a.href = WebGLTestHarnessModule.getURLWithOptions(url, {
+ webglVersion: reporter.selectedWebGLVersion,
+ quiet: OPTIONS.quiet,
+ quick: quickTestMode ? 1 : 0,
+ });
+ a.target = "_blank";
+ const folderName = that.folder.displayName;
+ console.assert(folderName.startsWith("all/"));
+ console.assert(url.startsWith(folderName.substring(4) + "/"));
+ const urlWithoutFolder = url.substring(folderName.length - 4 + 1);
+ var node = reporter.localDoc.createTextNode(urlWithoutFolder);
+ a.appendChild(node);
+ div.appendChild(a);
+ li.setAttribute('class', 'testpage');
+ li.appendChild(div);
+ var ul = reporter.localDoc.createElement('ul');
+ var node = reporter.localDoc.createTextNode('');
+ li.appendChild(ul);
+ div.appendChild(node);
+ this.totalsElem = node;
+ this.resultElem = ul;
+ this.elem = li;
+ this.check = check;
+ };
+
+ Page.prototype.checked = function() {
+ return this.check.checked;
+ }
+
+ Page.prototype.addResult = function(msg, success, skipped) {
+ ++this.totalTests;
+ if (success === undefined) {
+ ++this.totalTimeouts;
+ var result = "timeout";
+ var css = "timeout";
+ } else if (success) {
+ ++this.totalSuccessful;
+ // don't report success.
+ return;
+ } else {
+ ++this.totalFailed;
+ if (skipped) {
+ // Skipped tests are counted as both skips and failures (because we
+ // don't want to accidentally accept a conformance submission with
+ // skipped tests).
+ ++this.totalSkipped;
+ }
+ var result = "failed";
+ var css = "fail";
+ }
+
+ var node = this.reporter.localDoc.createTextNode(result + ': ' + msg);
+ var li = this.reporter.localDoc.createElement('li');
+ li.appendChild(node);
+ li.setAttribute('class', css);
+ this.resultElem.appendChild(li);
+ };
+
+ Page.prototype.startPage = function() {
+ if (autoScroll && this.elem.scrollIntoView) {
+ this.elem.scrollIntoView(false);
+ }
+ this.totalTests = 0;
+ this.totalSuccessful = 0;
+ this.totalSkipped = 0;
+ this.totalFailed = 0;
+ this.totalTimeouts = 0;
+ this.totalTime = 0;
+ // remove previous results.
+ while (this.resultElem.hasChildNodes()) {
+ this.resultElem.removeChild(this.resultElem.childNodes[0]);
+ }
+ this.totalsElem.textContent = '';
+
+ var shouldRun = this.check.checked && this.folder.checked();
+
+ if (shouldRun) {
+ this.elem.classList.remove('testpagetimeout');
+ this.elem.classList.remove('testpageskipped');
+ this.elem.classList.remove('testpagefail');
+ this.elem.classList.remove('testpagesuccess');
+ this.startTime = Date.now();
+ }
+
+ return this.check.checked && this.folder.checked();
+ };
+
+ Page.prototype.firstTestIndex = function() {
+ return this.testIndex;
+ };
+
+ Page.prototype.finishPage = function(success) {
+ var shouldRun = this.check.checked && this.folder.checked();
+ if (shouldRun) {
+ this.totalTime = Date.now() - this.startTime;
+ } else {
+ this.totalTime = 0;
+ }
+
+ var passedMsg = ' (Passed: ' + this.totalSuccessful + '/' + this.totalTests;
+ var skippedMsg = '';
+ if (this.totalSkipped > 0) {
+ skippedMsg = ' Skipped: ' + this.totalSkipped + '/' + this.totalTests;
+ }
+ var failedMsg = '';
+ if (this.totalFailed > 0) {
+ failedMsg = ' Failed: ' + this.totalFailed + '/' + this.totalTests;
+ }
+ var timeoutMsg = '';
+ if (this.totalTimeouts > 0) {
+ timeoutMsg = ' Timeout: ' + this.totalTimeouts + '/' + this.totalTests;
+ }
+ var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg + ' in ' + this.totalTime.toFixed(1) + ' ms)';
+
+ if (success === undefined) {
+ var css = 'testpagetimeout';
+ msg = '(*timeout*)';
+ ++this.totalTests;
+ ++this.totalTimeouts;
+ } else if (this.totalSkipped) {
+ var css = 'testpageskipped';
+ } else if (this.totalSuccessful != this.totalTests) {
+ var css = 'testpagefail';
+ } else {
+ var css = 'testpagesuccess';
+ }
+ this.elem.classList.add(css);
+ this.totalsElem.textContent = msg;
+ this.folder.pageFinished(this, success);
+ };
+
+ Page.prototype.enableTest = function(re) {
+ if (this.url.match(re)) {
+ this.check.checked = true;
+ this.folder.enableUp_();
+ }
+ };
+
+ Page.prototype.disableTest = function(re) {
+ if (this.url.match(re)) {
+ this.check.checked = false;
+ }
+ };
+
+ Page.prototype.toJSON = function() {
+ return {
+ 'subtests': this.totalTests,
+ 'successful': this.totalSuccessful,
+ 'skipped': this.totalSkipped,
+ 'failed': this.totalFailed,
+ 'timedOut': this.totalTimeouts,
+ 'totalTime': this.totalTime,
+ };
+ };
+
+
+ var Folder = function(reporter, folder, depth, opt_name) {
+ this.reporter = reporter;
+ this.depth = depth;
+ this.name = opt_name || "";
+ this.displayName = this.name;
+ if (folder && folder.displayName) {
+ this.displayName = folder.displayName + '/' + this.displayName;
+ }
+ this.subFolders = {};
+ this.pages = [];
+ this.items = [];
+ this.folder = folder;
+ this.cachedTotalTime = 0;
+ this.cachedTotalSuccessful = 0;
+ this.cachedTotalSkipped = 0;
+ this.cachedTotalTimeouts = 0;
+ this.cachedTotalTests = 0;
+ var that = this;
+
+ var doc = reporter.localDoc;
+ this.elementId = "folder" + folderCount++;
+ var li = doc.createElement('li');
+ li.id = this.elementId;
+ li.classList.add("folder");
+ var folderHeader = doc.createElement('div');
+ folderHeader.classList.add('folderHeader');
+ var folderHeaderInner = doc.createElement('div');
+ folderHeaderInner.classList.add('folderHeaderInner');
+ folderHeader.appendChild(folderHeaderInner);
+ var check = doc.createElement('input');
+ check.type = 'checkbox';
+ check.checked = true;
+ check.onclick = function() {
+ if (this.checked) {
+ that.enableTest(".*");
+ }
+ else {
+ that.disableTest(".*", true);
+ }
+ };
+ folderHeaderInner.appendChild(check);
+ var button = doc.createElement('input');
+ button.type = 'button';
+ button.value = 'run';
+ button.onclick = function() {
+ autoScroll = autoScrollEnabled;
+ that.run();
+ };
+ if (reporter.noSelectedWebGLVersion) {
+ button.disabled = true;
+ }
+ folderHeaderInner.appendChild(button);
+ var h = doc.createElement('span');
+ h.classList.add('folderName');
+ h.appendChild(doc.createTextNode(this.displayName));
+ folderHeaderInner.appendChild(h);
+ var m = doc.createElement('span');
+ m.classList.add('folderMessage');
+ this.msgNode = doc.createTextNode('');
+ m.appendChild(this.msgNode);
+ folderHeaderInner.appendChild(m);
+ var ul = doc.createElement('ul');
+ li.appendChild(folderHeader);
+ li.appendChild(ul);
+ this.childUL = ul;
+ this.elem = li;
+ this.check = check;
+ this.folderHeader = folderHeader;
+ };
+
+ Folder.prototype.checked = function() {
+ return this.check.checked &&
+ (this.folder ? this.folder.checked() : true);
+ };
+
+ Folder.prototype.firstTestIndex = function() {
+ return this.items[0].firstTestIndex();
+ };
+
+ Folder.prototype.numChildren = function() {
+ var numChildren = 0;
+ for (var name in this.subFolders) {
+ numChildren += this.subFolders[name].numChildren();
+ }
+ return numChildren + this.pages.length;
+ };
+
+ Folder.prototype.totalTime = function() {
+ // Check to see if the cached total time needs to be recomputed
+ if (this.cachedTotalTime == -1) {
+ this.cachedTotalTime = 0;
+ for (var name in this.subFolders) {
+ this.cachedTotalTime += this.subFolders[name].totalTime();
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.cachedTotalTime += this.pages[ii].totalTime;
+ }
+ }
+ return this.cachedTotalTime;
+ };
+
+ Folder.prototype.totalSuccessful = function() {
+ if (this.cachedTotalSuccessful == -1) {
+ this.cachedTotalSuccessful = 0;
+ for (var name in this.subFolders) {
+ this.cachedTotalSuccessful += this.subFolders[name].totalSuccessful();
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.cachedTotalSuccessful += this.pages[ii].totalSuccessful;
+ }
+ }
+ return this.cachedTotalSuccessful;
+ };
+
+ Folder.prototype.totalSkipped = function() {
+ if (this.cachedTotalSkipped == -1) {
+ this.cachedTotalSkipped = 0;
+ for (var name in this.subFolders) {
+ this.cachedTotalSkipped += this.subFolders[name].totalSkipped();
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.cachedTotalSkipped += this.pages[ii].totalSkipped;
+ }
+ }
+ return this.cachedTotalSkipped;
+ };
+
+ Folder.prototype.totalFailed = function() {
+ if (this.cachedTotalFailed == -1) {
+ this.cachedTotalFailed = 0;
+ for (var name in this.subFolders) {
+ this.cachedTotalFailed += this.subFolders[name].totalFailed();
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.cachedTotalFailed += this.pages[ii].totalFailed;
+ }
+ }
+ return this.cachedTotalFailed;
+ };
+
+ Folder.prototype.totalTimeouts = function() {
+ if (this.cachedTotalTimeouts == -1) {
+ this.cachedTotalTimeouts = 0;
+ for (var name in this.subFolders) {
+ this.cachedTotalTimeouts += this.subFolders[name].totalTimeouts();
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.cachedTotalTimeouts += this.pages[ii].totalTimeouts;
+ }
+ }
+ return this.cachedTotalTimeouts;
+ };
+
+ Folder.prototype.totalTests = function() {
+ if (this.cachedTotalTests == -1) {
+ this.cachedTotalTests = 0;
+ for (var name in this.subFolders) {
+ this.cachedTotalTests += this.subFolders[name].totalTests();
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.cachedTotalTests += this.pages[ii].totalTests;
+ }
+ }
+ return this.cachedTotalTests;
+ };
+
+ Folder.prototype.run = function() {
+ this.msgNode.textContent = '';
+ var firstTestIndex = this.firstTestIndex();
+ var count = this.numChildren();
+ log("run tests: " + firstTestIndex + " to " + (firstTestIndex + count - 1))
+ testHarness.runTests({start: firstTestIndex, count: count});
+ };
+
+ Folder.prototype.pageFinished = function(page, success) {
+ this.cachedTotalTime = -1;
+ this.cachedTotalSuccessful = -1;
+ this.cachedTotalSkipped = -1;
+ this.cachedTotalFailed = -1;
+ this.cachedTotalTimeouts = -1;
+ this.cachedTotalTests = -1;
+ var passedMsg = ' (Passed: ' + this.totalSuccessful() + '/' + this.totalTests();
+ var skippedMsg = '';
+ if (this.totalSkipped() > 0) {
+ skippedMsg = ' Skipped: ' + this.totalSkipped() + '/' + this.totalTests();
+ }
+ var failedMsg = '';
+ if (this.totalFailed() > 0) {
+ failedMsg = ' Failed: ' + this.totalFailed() + '/' + this.totalTests();
+ }
+ var timeoutMsg = '';
+ if (this.totalTimeouts() > 0) {
+ timeoutMsg = ' Timeout: ' + this.totalTimeouts() + '/' + this.totalTests();
+ }
+ this.msgNode.textContent = passedMsg + skippedMsg + failedMsg + timeoutMsg + ' in ' + (this.totalTime() / 1000).toFixed(2) + ' seconds)';
+ if (this.folder) {
+ this.folder.pageFinished(page, success);
+ }
+ };
+
+ Folder.prototype.getSubFolder = function(name) {
+ var subFolder = this.subFolders[name];
+ if (subFolder === undefined) {
+ subFolder = new Folder(this.reporter, this, this.depth + 1, name);
+ this.subFolders[name] = subFolder;
+ this.items.push(subFolder);
+ this.childUL.appendChild(subFolder.elem);
+ }
+ return subFolder;
+ };
+
+ Folder.prototype.getOrCreateFolder = function(url) {
+ var parts = url.split('/');
+ var folder = this;
+ for (var pp = 0; pp < parts.length - 1; ++pp) {
+ folder = folder.getSubFolder(parts[pp]);
+ }
+ return folder;
+ };
+
+ Folder.prototype.addPage = function(page) {
+ this.pages.push(page);
+ this.items.push(page);
+ this.childUL.appendChild(page.elem);
+ this.folderHeader.classList.add('hasPages');
+ };
+
+ Folder.prototype.disableTest = function(re, opt_forceRecurse) {
+ var recurse = true;
+ if (this.name.match(re)) {
+ this.check.checked = false;
+ recurse = opt_forceRecurse;
+ }
+ if (recurse) {
+ for (var name in this.subFolders) {
+ this.subFolders[name].disableTest(re, opt_forceRecurse);
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.pages[ii].disableTest(re);
+ }
+ }
+ };
+
+ Folder.prototype.enableUp_ = function() {
+ this.check.checked = true;
+ var parent = this.folder;
+ if (parent) {
+ parent.enableUp_();
+ }
+ }
+
+ Folder.prototype.disableUp_ = function() {
+ var checked = false;
+ for (var name in this.subFolders) {
+ checked = this.subFolders[name].checked();
+ if (checked) {
+ break;
+ }
+ }
+ for (var ii = 0; ii < this.pages.length && checked == false; ++ii) {
+ checked = this.pages[ii].checked();
+ }
+ this.check.checked = checked;
+ var parent = this.folder;
+ if (parent) {
+ parent.disableUp_();
+ }
+ }
+
+ Folder.prototype.enableTest = function(re) {
+ if (this.name.match(re)) {
+ this.enableUp_();
+ }
+ for (var name in this.subFolders) {
+ this.subFolders[name].enableTest(re);
+ }
+ for (var ii = 0; ii < this.pages.length; ++ii) {
+ this.pages[ii].enableTest(re);
+ }
+ };
+
+ var Reporter = function(iframes) {
+ this.localDoc = document;
+ this.resultElem = document.getElementById("results");
+ this.fullResultsElem = document.getElementById("fullresults");
+ var node = this.localDoc.createTextNode('');
+ this.fullResultsElem.appendChild(node);
+ this.fullResultsNode = node;
+ this.iframes = iframes;
+ this.currentPageElem = null;
+ this.totalPages = 0;
+ this.pagesByURL = {};
+
+ // Check to see if WebGL is supported
+ var canvas = document.createElement("canvas");
+ var ctx = create3DContext(canvas, null, 1);
+
+ // Check to see if WebGL2 is supported
+ var canvas2 = document.createElement("canvas");
+ var ctx2 = create3DContext(canvas2, null, 2);
+
+ this.noSelectedWebGLVersion = false;
+ this.selectedWebGLVersion = WebGLTestHarnessModule.getMajorVersion(OPTIONS.version);
+ if (this.selectedWebGLVersion == 2 && !ctx2) {
+ this.noSelectedWebGLVersion = true;
+ } else if (this.selectedWebGLVersion == 1 && !ctx) {
+ this.noSelectedWebGLVersion = true;
+ }
+
+ // If the WebGL2 context could be created use it to get context info
+ if (ctx2) {
+ ctx = ctx2;
+ }
+
+ this.noWebGL = !ctx;
+
+ this.contextInfo = {};
+ this.root = new Folder(this, null, 0, "all");
+ this.resultElem.appendChild(this.root.elem);
+ this.callbacks = { };
+ this.startTime = new Date();
+
+ if (ctx) {
+ this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR);
+ this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION);
+ this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER);
+ this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS);
+ this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS);
+ this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS);
+ this.contextInfo["ALPHA_BITS"] = ctx.getParameter(ctx.ALPHA_BITS);
+ this.contextInfo["DEPTH_BITS"] = ctx.getParameter(ctx.DEPTH_BITS);
+ this.contextInfo["STENCIL_BITS"] = ctx.getParameter(ctx.STENCIL_BITS);
+
+ var ext = ctx.getExtension("WEBGL_debug_renderer_info");
+ if (ext) {
+ this.contextInfo["UNMASKED_VENDOR"] = ctx.getParameter(ext.UNMASKED_VENDOR_WEBGL);
+ this.contextInfo["UNMASKED_RENDERER"] = ctx.getParameter(ext.UNMASKED_RENDERER_WEBGL);
+ }
+ }
+ };
+
+ Reporter.prototype.enableTest = function(name) {
+ this.root.enableTest(name);
+ };
+
+ Reporter.prototype.disableTest = function(name) {
+ this.root.disableTest(name);
+ };
+
+ Reporter.prototype.disableAllTests = function() {
+ this.root.disableTest(".*", true);
+ };
+
+ Reporter.prototype.addEventListener = function(type, func) {
+ if (!this.callbacks[type]) {
+ this.callbacks[type] = [];
+ }
+ this.callbacks[type].push(func);
+ };
+
+ Reporter.prototype.executeListenerEvents_ = function(type) {
+ var callbacks = this.callbacks[type].slice(0);
+ for (var ii = 0; ii < callbacks.length; ++ii) {
+ setTimeout(callbacks[ii], 0);
+ }
+ };
+
+ Reporter.prototype.runTest = function(url) {
+ var page = this.pagesByURL[url];
+ testHarness.runTests({start: page.firstTestIndex(), count: 1});
+ };
+
+ Reporter.prototype.getFolder = function(url) {
+ return this.root.getOrCreateFolder(url);
+ };
+
+ Reporter.prototype.addPage = function(url) {
+ var folder = this.getFolder(url);
+ var page = new Page(this, folder, this.totalPages, url);
+ folder.addPage(page);
+ ++this.totalPages;
+ this.pagesByURL[url] = page;
+ };
+
+ Reporter.prototype.startPage = function(url) {
+ var page = this.pagesByURL[url];
+ return page.startPage();
+ };
+
+ Reporter.prototype.addResult = function(url, msg, success, skipped) {
+ var page = this.pagesByURL[url];
+ page.addResult(msg, success, skipped);
+ };
+
+ Reporter.prototype.finishPage = function(url, success) {
+ var page = this.pagesByURL[url];
+ page.finishPage(success);
+ if (OPTIONS.dumpShaders == 1) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', "/finishIndividualTest", true);
+ xhr.send(null);
+ }
+ };
+
+ Reporter.prototype.displayFinalResults = function(msg, success) {
+ if (success) {
+ var totalTests = 0;
+ var testsSucceeded = 0;
+ var testsFailed = 0;
+ var testsSkipped = 0;
+ var testsTimedOut = 0;
+
+ var subtestsHit = 0;
+ var subtestsSucceeded = 0;
+ var subtestsTimedOut = 0;
+ var subtestsSkipped = 0;
+ var subtestsFailed = 0;
+
+ var totalTime = Date.now() - this.startTime;
+
+ for (var url in this.pagesByURL) {
+ var page = this.pagesByURL[url];
+ totalTests += 1;
+ if (page.totalSkipped) {
+ testsSkipped += 1;
+ }
+ if (page.totalFailed) {
+ testsFailed += 1;
+ } else if (page.totalTimeouts) {
+ testsTimedOut += 1;
+ } else if (page.totalSuccessful) {
+ if (page.totalSuccessful != page.totalTests)
+ throw successes_not_equal_total;
+ testsSucceeded += 1;
+ }
+
+ subtestsHit += page.totalTests;
+ subtestsSucceeded += page.totalSuccessful;
+ subtestsTimedOut += page.totalTimeouts;
+ subtestsSkipped += page.totalSkipped;
+ subtestsFailed += page.totalFailed;
+ }
+
+ function ratio_str(x, y, name) {
+ return x + '/' + y + ' ' + name + ' (' + (x / y * 100).toFixed(2) + '%)';
+ }
+ var testsSucceededRatio = ratio_str(testsSucceeded, totalTests, 'tests');
+ var passedMsg = 'Passed ' + testsSucceededRatio + ', ' +
+ ratio_str(subtestsSucceeded, subtestsHit, 'subtests');
+ var skippedMsg = '';
+ if (testsSkipped > 0) {
+ skippedMsg = ' Skipped ' + ratio_str(testsSkipped, totalTests, 'tests');
+ }
+ var failedMsg = '';
+ if (testsFailed > 0) {
+ failedMsg = ' Failed ' + ratio_str(testsFailed, totalTests, 'tests') + ', ' +
+ ratio_str(subtestsFailed, subtestsHit, 'subtests');
+ }
+ var timeoutMsg = '';
+ if (testsTimedOut > 0) {
+ timeoutMsg = ' Timeout ' + ratio_str(testsTimedOut, totalTests, 'tests');
+ }
+ var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg;
+ this.fullResultsNode.textContent = msg;
+
+ // generate a text summary
+ var tx = "";
+ tx += "WebGL Conformance Test Results\n";
+ tx += "Version " + OPTIONS.version + "\n";
+ tx += "Generated on: " + (new Date()).toString() + "\n";
+ tx += "\n";
+ tx += "-------------------\n\n";
+ tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n";
+ tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n";
+ tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n";
+ tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n";
+ tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n";
+ tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n";
+ tx += "WebGL R/G/B/A/Depth/Stencil bits (default config): " + this.contextInfo["RED_BITS"] + "/" + this.contextInfo["GREEN_BITS"] + "/" + this.contextInfo["BLUE_BITS"] + "/" + this.contextInfo["ALPHA_BITS"] + "/" + this.contextInfo["DEPTH_BITS"] + "/" + this.contextInfo["STENCIL_BITS"] + "\n";
+ tx += "\n-------------------\n\n";
+
+ var result;
+ if (totalTests && testsSucceeded == totalTests) {
+ result = 'PASS';
+ } else {
+ result = 'FAIL';
+ }
+ tx += "Test Summary: " + result + " (" + totalTests + " tests):\n";
+ tx += subtestsHit + " subtests ran in " + (totalTime / 1000.0).toFixed(2) + " seconds\n";
+ function record(what, tests, subtests) {
+ tx += what + ": " + tests + " tests, " + subtests + " subtests\n";
+ }
+ record('PASSED', testsSucceeded, subtestsSucceeded);
+ record('NOT PASSED', totalTests - testsSucceeded, subtestsHit - subtestsSucceeded);
+
+ record('FAILED', testsFailed, subtestsFailed);
+ record('TIMED OUT', testsTimedOut, subtestsTimedOut);
+ record('SKIPPED', testsSkipped, subtestsSkipped);
+
+ tx += "\n-------------------\n\n";
+
+ const failureLines = [];
+ const timeoutLines = [];
+ const resultLines = [];
+
+ for (var url in this.pagesByURL) {
+ var page = this.pagesByURL[url];
+ resultLines.push(' "' + url + '":' + JSON.stringify(page.toJSON()));
+
+ if (page.totalFailed) {
+ failureLines.push(' "' + url + '",');
+ }
+ if (page.totalTimeouts) {
+ timeoutLines.push(' "' + url + '",');
+ }
+ }
+
+ const lines = [].concat(
+ [
+ '{',
+ ' "failures": [',
+ ],
+ failureLines,
+ [
+ ' ],',
+ ' "timeouts": [',
+ ],
+ timeoutLines,
+ [
+ ' ],',
+ ' "results": {',
+ ],
+ resultLines,
+ [
+ ' },',
+ '}',
+ ]
+ );
+
+ tx += lines.join('\n');
+
+ var r = document.getElementById("testResultsAsText");
+ while (r.firstChild) r.removeChild(r.firstChild);
+ r.appendChild(document.createTextNode(tx));
+ document.getElementById("showTextSummary").disabled = false;
+ document.getElementById("dlTextSummary").disabled = false;
+
+ this.postResultsToServer(tx);
+ } else {
+ var e = document.getElementById("error");
+ e.innerHTML = msg;
+ this.postResultsToServer(msg);
+ }
+ };
+
+ Reporter.prototype.postTestStartToServer = function(resultText) {
+ this.startTime = Date.now();
+ if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
+ return;
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', "/start", true);
+ xhr.send(null);
+ };
+
+ Reporter.prototype.postResultsToServer = function(resultText) {
+ if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
+ return;
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', "/finish", true);
+ xhr.setRequestHeader("Content-Type", "text/plain");
+ xhr.send(resultText);
+ };
+
+ Reporter.prototype.ready = function() {
+ var loading = document.getElementById("loading");
+ loading.style.display = "none";
+ if (!this.noSelectedWebGLVersion) {
+ var button = document.getElementById("runTestsButton");
+ button.disabled = false;
+ this.executeListenerEvents_("ready");
+ }
+ };
+
+ Reporter.prototype.reportFunc = function(type, url, msg, success, skipped) {
+ switch (type) {
+ case reportType.ADD_PAGE:
+ return this.addPage(msg);
+ case reportType.READY:
+ return this.ready();
+ case reportType.START_PAGE:
+ return this.startPage(url);
+ case reportType.TEST_RESULT:
+ return this.addResult(url, msg, success, skipped);
+ case reportType.FINISH_PAGE:
+ return this.finishPage(url, success);
+ case reportType.FINISHED_ALL_TESTS:
+ return this.displayFinalResults(msg, success);
+ default:
+ throw 'unhandled';
+ break;
+ };
+ };
+
+ var getURLOptions = function(obj) {
+ 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]);
+ obj[key] = value;
+ }
+ };
+
+ getURLOptions(OPTIONS);
+
+ var makeVersionSelect = function(currentVersion) {
+ var versionSelect = document.getElementById("testVersion");
+ var foundCurrentVersion = false;
+ var numericCurrentVersion = currentVersion.replace(/[^\d.]/g, '');
+
+ for (var i in testVersions) {
+ var version = testVersions[i];
+ var numericVersion = version.replace(/[^\d.]/g, '');
+ var option = document.createElement("option");
+ option.setAttribute('value', numericVersion);
+ option.innerHTML = version;
+
+ if (numericVersion == numericCurrentVersion) {
+ foundCurrentVersion = true;
+ option.selected = true;
+ }
+
+ versionSelect.appendChild(option);
+ }
+
+ // If the version requested by the query string isn't in the list add it.
+ if (!foundCurrentVersion) {
+ var option = document.createElement("option");
+ option.setAttribute('value', numericCurrentVersion);
+ option.innerHTML = currentVersion + " (unknown)";
+ option.selected = true;
+
+ versionSelect.appendChild(option);
+ }
+
+ versionSelect.addEventListener('change', function(ev) {
+ window.location.href = "?version=" + versionSelect.value;
+ }, false);
+ }
+
+ makeVersionSelect(OPTIONS.version);
+
+ // Make iframes
+ var iframes = [document.getElementById("test-iframe")];
+
+ var testPath = "00_test_list.txt";
+ if (OPTIONS.root) {
+ testPath = OPTIONS.root + "/" + testPath;
+ }
+
+ var reporter = new Reporter(iframes);
+ var testHarness = new WebGLTestHarnessModule.TestHarness(
+ iframes,
+ testPath,
+ function(type, url, msg, success, skipped) {
+ return reporter.reportFunc(type, url, msg, success, skipped);
+ },
+ OPTIONS);
+ reporter.addEventListener("ready", function() {
+ // Set which tests to include.
+ if (OPTIONS.include) {
+ reporter.disableAllTests();
+ var includes = OPTIONS.include.split(",")
+ for (var ii = 0; ii < includes.length; ++ii) {
+ reporter.enableTest(new RegExp(includes[ii]));
+ }
+ }
+ // Remove tests based on skip=re1,re2 in URL.
+ if (OPTIONS.skip) {
+ var skips = OPTIONS.skip.split(",")
+ for (var ii = 0; ii < skips.length; ++ii) {
+ reporter.disableTest(new RegExp(skips[ii]));
+ }
+ }
+ // Auto run the tests if the run=1 in URL
+ if (OPTIONS.run != undefined && OPTIONS.run != 0) {
+ reporter.postTestStartToServer();
+ testHarness.runTests();
+ }
+ });
+ window.webglTestHarness = testHarness;
+ var button = document.getElementById("runTestsButton");
+ button.disabled = true;
+ button.onclick = function() {
+ autoScroll = autoScrollEnabled;
+ reporter.postTestStartToServer();
+ testHarness.runTests();
+ };
+ var autoScrollCheckbox = document.getElementById("autoScrollCheckbox");
+ autoScrollCheckbox.checked = autoScrollEnabled;
+ autoScrollCheckbox.onclick = function() {
+ autoScrollEnabled = autoScrollCheckbox.checked;
+ autoScroll = autoScrollEnabled;
+ };
+
+ var hidePassedSheet = createStylesheet();
+ var hidePassedCheckbox = document.getElementById("hidePassedCheckbox");
+ hidePassedCheckbox.checked = false;
+ hidePassedCheckbox.onclick = function() {
+ var hidePassedTests = hidePassedCheckbox.checked;
+ if (hidePassedTests) {
+ hidePassedSheet.insertRule(".testpagesuccess { display: none; }", 0);
+ } else {
+ hidePassedSheet.deleteRule(0);
+ }
+ };
+
+ var quickTestModeCheckbox = document.getElementById("quickTestModeCheckbox");
+ quickTestModeCheckbox.checked = quickTestMode;
+ quickTestModeCheckbox.onclick = function() {
+ quickTestMode = quickTestModeCheckbox.checked;
+ };
+
+ var textbutton = document.getElementById("showTextSummary");
+ textbutton.onclick = function() {
+ log("click");
+ var htmldiv = document.getElementById("testResultsHTML");
+ var textdiv = document.getElementById("testResultsText");
+ if (textdiv.style.display == "none") {
+ textdiv.style.display = "block";
+ htmldiv.style.display = "none";
+ textbutton.setAttribute("value", "display html summary");
+ } else {
+ textdiv.style.display = "none";
+ htmldiv.style.display = "block";
+ textbutton.setAttribute("value", "display text summary");
+ }
+ };
+
+ function download(filename, text) {
+ var element = document.createElement("a");
+ element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
+ element.setAttribute("download", filename);
+ element.style.display = "none";
+ document.body.appendChild(element);
+ element.click();
+ document.body.removeChild(element);
+ }
+ var dltextbutton = document.getElementById("dlTextSummary");
+ dltextbutton.onclick = function() {
+ var textdiv = document.getElementById("testResultsText");
+ download("webgl-conformance-" + OPTIONS.version + ".txt", textdiv.innerText.trim());
+ };
+
+ if (reporter.noSelectedWebGLVersion) {
+ button.disabled = true;
+ }
+ if (reporter.noWebGL) {
+ var elem = document.getElementById("nowebgl");
+ elem.style.display = "";
+ reporter.postResultsToServer("Browser does not appear to support WebGL");
+ } else if (reporter.noSelectedWebGLVersion) {
+ var elem = document.getElementById("noselectedwebgl");
+ elem.style.display = "";
+ reporter.postResultsToServer("Browser does not appear to support the selected version of WebGL");
+ }
+
+ const iframeContainer = document.getElementById("iframe-container");
+ const iframeToggle = document.getElementById("iframe-toggle");
+ iframeToggle.value = iframeToggle.getAttribute("data-value-hidden");
+ iframeToggle.onclick = function() {
+ const expanded = iframeToggle.myExpanded = !iframeToggle.myExpanded;
+ if (expanded) {
+ iframeContainer.classList.add("iframe-shown");
+ iframeToggle.value = iframeToggle.getAttribute("data-value-shown");
+ } else {
+ iframeContainer.classList.remove("iframe-shown");
+ iframeToggle.value = iframeToggle.getAttribute("data-value-hidden");
+ }
+ };
+}
+</script>
+</head>
+<body onload="start()">
+
+<div id="testlist">
+ <div id="testResultsHTML">
+ <ul id="results">
+ </ul>
+ </div>
+ <div style="display: none;" id="testResultsText">
+ <pre id="testResultsAsText"></pre>
+ </div>
+</div> <!-- end of container -->
+
+<div id="iframe-container">
+ <input type="button" data-value-hidden="◄" data-value-shown="►" id="iframe-toggle" aria-hidden="true"
+ ><iframe id="test-iframe"></iframe>
+</div>
+
+<div id="header">
+ <div id="info">
+ <div style="text-align:center">
+ <img src="resources/webgl-logo.png" alt="WebGL" id="logo"/>
+ <br/>
+ Conformance Test Runner
+ </div>
+ Version
+ <select id="testVersion">
+ </select>
+ <a href="../../conformance-suites/">(older versions?)</a>
+ <br/>
+ <input type="button" value="run tests" id="runTestsButton"/>
+ <label for="autoScrollCheckbox"><input type="checkbox" id="autoScrollCheckbox"/>auto scroll</label>
+ <label for="hidePassedCheckbox"><input type="checkbox" id="hidePassedCheckbox"/>hide passed</label>
+ <label for="quickTestModeCheckbox"><input type="checkbox" id="quickTestModeCheckbox"/>quick test mode</label>
+ <br/>
+ <input type="button" disabled value="show text summary" id="showTextSummary"/>
+ <input type="button" disabled value="download text" id="dlTextSummary"/>
+ <div id="nowebgl" class="nowebgl" style="display: none;">
+ This browser does not appear to support WebGL
+ </div>
+ <div id="noselectedwebgl" class="nowebgl" style="display: none;">
+ This browser does not appear to support the selected version of WebGL
+ </div>
+ <div id="loading">
+ Loading Tests...
+ </div>
+ <div id="fullresults">
+ </div>
+ </div>
+ <div id="error-wrap">
+ <pre id="error"></pre>
+ </div>
+</div> <!-- end of header -->
+
+</body>
+</html>